All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 00/14] tipc: new netlink API
@ 2014-09-11  8:29 richard.alpe
  2014-09-11  8:29 ` [PATCH net-next 01/14] tipc: add bearer disable/enable to new netlink api richard.alpe
                   ` (13 more replies)
  0 siblings, 14 replies; 24+ messages in thread
From: richard.alpe @ 2014-09-11  8:29 UTC (permalink / raw)
  To: netdev; +Cc: tipc-discussion

From: Richard Alpe <richard.alpe@ericsson.com>

This is a new netlink API for TIPC. It's intended to replace the
existing ASCII API. It utilizes many of the standard netlink
functionalities in the kernel, such as attribute nesting and
input polices.

There are a couple of reasons for this rewrite. The main and most
easily justifiable is that the existing API doesn't scale.  Meaning
that a TIPC cluster with a larger amount of nodes, publications or
ports will rapidly exceed what the exiting API can handle. Resulting
in truncated or corrupt responses. In addition to this, the existing
ASCII API rarely uses "standard" kernel functions and has several
tipc specific functions for sanity checking and string formating.

The new API utilizes standard function for pushing data to socket
buffers and netlink attribute nesting to logically group data.
The new API can handle an arbitrary amount of data for things that
are likely to scale up as the TIPC usage and/or cluster size
increases.

A new user-space tool has been developed to work with this new API.
It is called "tipc" and is part of the "tipc-utils" package that
comes with many Linux distributions.  The new "tipc" tool utilizes
standard functions from libnl to format, send, receive and process
messages. The tool has borrowed design philosophies from git and the
ip tool. Making the syntax resemble that of ip whiles its strong
modularity resembles that of git.

The existing tool for managing TIPC, "tipc-config" remains in the
package, but when built for kernels that has this new API it is
replaced by a script-based wrapper that maps the old syntax to the
new tool. This way, backwards compatibility is mostly preserved.

MORE ABOUT THE CODE

The main challenge here is to handle the case where the data is of
arbitrary size. This was largely neglected in the old API design.
For example when there is a lot of ports that has a large amount of
associated publications. In this specific case we can't assume that
all ports nor for that matter all the publications can fit inside a
single netlink message. Sending everything in one batch isn't an
option as we need to yield for the socket layer to cope.

This is solved by using the standard netlink callback for dumping
data and releasing the locks when the netlink message is full. The
dumping mechanism gets us back and we keep a reference (logical) to
where we where when the message became full. This means that we are
not "atomic", what is retrieved by user-space isn't a snapshot at a
certain time but rather a continuously updated data set. In the case
where we can't find our way back i.e. our logical reference are gone
we set a standard flag (NLM_F_DUMP_INTR) to tell user-space that the
dump was interrupted.

Richard Alpe (14):
  tipc: add bearer disable/enable to new netlink api
  tipc: add bearer get/dump to new netlink api
  tipc: add bearer set to new netlink api
  tipc: add sock dump to new netlink api
  tipc: add link get/dump to new netlink api
  tipc: add link set to new netlink api
  tipc: add link stat reset to new netlink api
  tipc: add media get/dump to new netlink api
  tipc: add media set to new netlink api
  tipc: add node get/dump to new netlink api
  tipc: add net dump to new netlink api
  tipc: add net set to new netlink api
  tipc: add name table dump to new netlink api
  tipc: remove old ASCII netlink API

 include/uapi/linux/tipc_config.h |  478 ++++++++++--------------
 net/tipc/Makefile                |    2 +-
 net/tipc/bcast.c                 |  130 +++++--
 net/tipc/bcast.h                 |    4 +-
 net/tipc/bearer.c                |  510 ++++++++++++++++++++++----
 net/tipc/bearer.h                |   15 +-
 net/tipc/config.c                |  342 -----------------
 net/tipc/config.h                |   67 ----
 net/tipc/core.c                  |    3 +-
 net/tipc/link.c                  |  746 +++++++++++++++++++++++---------------
 net/tipc/link.h                  |   14 +-
 net/tipc/log.c                   |    1 -
 net/tipc/name_table.c            |  375 +++++++++----------
 net/tipc/name_table.h            |    5 +-
 net/tipc/net.c                   |  107 +++++-
 net/tipc/net.h                   |    8 +-
 net/tipc/netlink.c               |  129 +++++--
 net/tipc/netlink.h               |   47 +++
 net/tipc/node.c                  |  209 +++++------
 net/tipc/node.h                  |    6 +-
 net/tipc/socket.c                |  236 ++++++++----
 net/tipc/socket.h                |    3 +-
 22 files changed, 1913 insertions(+), 1524 deletions(-)
 delete mode 100644 net/tipc/config.c
 delete mode 100644 net/tipc/config.h
 create mode 100644 net/tipc/netlink.h

-- 
1.7.10.4


------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH net-next 01/14] tipc: add bearer disable/enable to new netlink api
  2014-09-11  8:29 [PATCH net-next 00/14] tipc: new netlink API richard.alpe
@ 2014-09-11  8:29 ` richard.alpe
  2014-09-12 21:07   ` David Miller
  2014-09-11  8:29 ` [PATCH net-next 02/14] tipc: add bearer get/dump " richard.alpe
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 24+ messages in thread
From: richard.alpe @ 2014-09-11  8:29 UTC (permalink / raw)
  To: netdev; +Cc: tipc-discussion

From: Richard Alpe <richard.alpe@ericsson.com>

A new netlink API for tipc that can disable or enable a tipc bearer.

The API utilizes netlink policies for input validation. Where the
top-level netlink attributes are tipc-logical entities, like bearer.
The top level entities then contain nested attributes. In this case
a name, nested link properties and a domain.

Netlink commands implemented in this patch:
TIPC_NL_BEARER_ENABLE
TIPC_NL_BEARER_DISABLE

Netlink logical layout of bearer enable message:
-> bearer
    -> name
    [ -> domain ]
    [
    -> properties
        -> priority
    ]

Netlink logical layout of bearer disable message:
-> bearer
    -> name

Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
---
 include/uapi/linux/tipc_config.h |   44 ++++++++++++++++-
 net/tipc/bearer.c                |   99 +++++++++++++++++++++++++++++++++++++-
 net/tipc/bearer.h                |    7 ++-
 net/tipc/link.c                  |   47 ++++++++++++++++++
 net/tipc/link.h                  |    3 ++
 net/tipc/netlink.c               |   27 +++++++++--
 net/tipc/netlink.h               |   47 ++++++++++++++++++
 7 files changed, 266 insertions(+), 8 deletions(-)
 create mode 100644 net/tipc/netlink.h

diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h
index 876d0a1..954ecaa 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -1,7 +1,7 @@
 /*
  * include/uapi/linux/tipc_config.h: Header for TIPC configuration interface
  *
- * Copyright (c) 2003-2006, Ericsson AB
+ * Copyright (c) 2003-2006, 2014, Ericsson AB
  * Copyright (c) 2005-2007, 2010-2011, Wind River Systems
  * All rights reserved.
  *
@@ -46,6 +46,48 @@
 #include <arpa/inet.h> /* for ntohs etc. */
 #endif
 
+/* Netlink commands */
+enum {
+	TIPC_NL_UNSPEC,
+	TIPC_NL_LEGACY,
+	TIPC_NL_BEARER_DISABLE,
+	TIPC_NL_BEARER_ENABLE,
+
+	__TIPC_NL_CMD_MAX,
+	TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
+};
+
+/* Top level netlink attributes */
+enum {
+	TIPC_NLA_UNSPEC,
+	TIPC_NLA_BEARER,		/* nest */
+
+	__TIPC_NLA_MAX,
+	TIPC_NLA_MAX = __TIPC_NLA_MAX - 1
+};
+
+/* Bearer info */
+enum {
+	TIPC_NLA_BEARER_UNSPEC,
+	TIPC_NLA_BEARER_NAME,		/* string */
+	TIPC_NLA_BEARER_PROP,		/* nest */
+	TIPC_NLA_BEARER_DOMAIN,		/* u32 */
+
+	__TIPC_NLA_BEARER_MAX,
+	TIPC_NLA_BEARER_MAX = __TIPC_NLA_BEARER_MAX - 1
+};
+
+/* Nest, link propreties. Valid for link, media and bearer */
+enum {
+	TIPC_NLA_PROP_UNSPEC,
+
+	TIPC_NLA_PROP_PRIO,		/* u32 */
+	TIPC_NLA_PROP_TOL,		/* u32 */
+	TIPC_NLA_PROP_WIN,		/* u32 */
+
+	__TIPC_NLA_PROP_MAX,
+	TIPC_NLA_PROP_MAX = __TIPC_NLA_PROP_MAX - 1
+};
 /*
  * Configuration
  *
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 2644743..59815be 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -1,7 +1,7 @@
 /*
  * net/tipc/bearer.c: TIPC bearer code
  *
- * Copyright (c) 1996-2006, 2013, Ericsson AB
+ * Copyright (c) 1996-2006, 2013-2014, Ericsson AB
  * Copyright (c) 2004-2006, 2010-2013, Wind River Systems
  * All rights reserved.
  *
@@ -37,6 +37,7 @@
 #include "core.h"
 #include "config.h"
 #include "bearer.h"
+#include "link.h"
 #include "discover.h"
 
 #define MAX_ADDR_STR 60
@@ -49,6 +50,17 @@ static struct tipc_media * const media_info_array[] = {
 	NULL
 };
 
+static const struct nla_policy
+tipc_nl_bearer_policy[TIPC_NLA_BEARER_MAX + 1]	= {
+	[TIPC_NLA_BEARER_UNSPEC]		= { .type = NLA_UNSPEC },
+	[TIPC_NLA_BEARER_NAME] = {
+		.type = NLA_STRING,
+		.len = TIPC_MAX_BEARER_NAME
+	},
+	[TIPC_NLA_BEARER_PROP]			= { .type = NLA_NESTED },
+	[TIPC_NLA_BEARER_DOMAIN]		= { .type = NLA_U32 }
+};
+
 struct tipc_bearer __rcu *bearer_list[MAX_BEARERS + 1];
 
 static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down);
@@ -627,3 +639,88 @@ void tipc_bearer_stop(void)
 		}
 	}
 }
+
+int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info)
+{
+	int err;
+	char *name;
+	struct tipc_bearer *bearer;
+	struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
+
+	if (!info->attrs[TIPC_NLA_BEARER])
+		return -EINVAL;
+
+	err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
+			       info->attrs[TIPC_NLA_BEARER],
+			       tipc_nl_bearer_policy);
+	if (err)
+		return err;
+
+	if (!attrs[TIPC_NLA_BEARER_NAME])
+		return -EINVAL;
+
+	name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
+
+	rtnl_lock();
+	bearer = tipc_bearer_find(name);
+	if (!bearer) {
+		rtnl_unlock();
+		return -EINVAL;
+	}
+
+	bearer_disable(bearer, false);
+	rtnl_unlock();
+
+	return 0;
+}
+
+int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info)
+{
+	int err;
+	char *bearer;
+	struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
+	u32 domain;
+	u32 prio;
+
+	prio = TIPC_MEDIA_LINK_PRI;
+	domain = tipc_own_addr & TIPC_CLUSTER_MASK;
+
+	if (!info->attrs[TIPC_NLA_BEARER])
+		return -EINVAL;
+
+	err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
+			       info->attrs[TIPC_NLA_BEARER],
+			       tipc_nl_bearer_policy);
+	if (err)
+		return err;
+
+	if (!attrs[TIPC_NLA_BEARER_NAME])
+		return -EINVAL;
+
+	bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
+
+	if (attrs[TIPC_NLA_BEARER_DOMAIN])
+		domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]);
+
+	if (attrs[TIPC_NLA_BEARER_PROP]) {
+		struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
+
+		err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_BEARER_PROP],
+					      props);
+		if (err)
+			return err;
+
+		if (props[TIPC_NLA_PROP_PRIO])
+			prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
+	}
+
+	rtnl_lock();
+	err = tipc_enable_bearer(bearer, domain, prio);
+	if (err) {
+		rtnl_unlock();
+		return err;
+	}
+	rtnl_unlock();
+
+	return 0;
+}
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 78fccc4..a87e8c7 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -1,7 +1,7 @@
 /*
  * net/tipc/bearer.h: Include file for TIPC bearer code
  *
- * Copyright (c) 1996-2006, 2013, Ericsson AB
+ * Copyright (c) 1996-2006, 2013-2014, Ericsson AB
  * Copyright (c) 2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
@@ -38,6 +38,8 @@
 #define _TIPC_BEARER_H
 
 #include "bcast.h"
+#include "netlink.h"
+#include <net/genetlink.h>
 
 #define MAX_BEARERS	2
 #define MAX_MEDIA	2
@@ -176,6 +178,9 @@ extern struct tipc_media eth_media_info;
 extern struct tipc_media ib_media_info;
 #endif
 
+int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info);
+int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info);
+
 int tipc_media_set_priority(const char *name, u32 new_value);
 int tipc_media_set_window(const char *name, u32 new_value);
 void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a);
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 65410e1..4628538 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -40,6 +40,7 @@
 #include "name_distr.h"
 #include "discover.h"
 #include "config.h"
+#include "netlink.h"
 
 #include <linux/pkt_sched.h>
 
@@ -50,6 +51,14 @@ static const char *link_co_err = "Link changeover error, ";
 static const char *link_rst_msg = "Resetting link ";
 static const char *link_unk_evt = "Unknown link event ";
 
+/* Properties valid for media, bearar and link */
+static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = {
+	[TIPC_NLA_PROP_UNSPEC]		= { .type = NLA_UNSPEC },
+	[TIPC_NLA_PROP_PRIO]		= { .type = NLA_U32 },
+	[TIPC_NLA_PROP_TOL]		= { .type = NLA_U32 },
+	[TIPC_NLA_PROP_WIN]		= { .type = NLA_U32 }
+};
+
 /*
  * Out-of-range value for link session numbers
  */
@@ -2370,3 +2379,41 @@ static void link_print(struct tipc_link *l_ptr, const char *str)
 	else
 		pr_cont("\n");
 }
+
+/* Parse and validate nested (link) properties valid for media, bearer and link
+ */
+int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[])
+{
+	int err;
+
+	err = nla_parse_nested(props, TIPC_NLA_PROP_MAX, prop,
+			       tipc_nl_prop_policy);
+	if (err)
+		return err;
+
+	if (props[TIPC_NLA_PROP_PRIO]) {
+		u32 prio;
+
+		prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
+		if (prio > TIPC_MAX_LINK_PRI)
+			return -EINVAL;
+	}
+
+	if (props[TIPC_NLA_PROP_TOL]) {
+		u32 tol;
+
+		tol = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
+		if ((tol < TIPC_MIN_LINK_TOL) || (tol > TIPC_MAX_LINK_TOL))
+			return -EINVAL;
+	}
+
+	if (props[TIPC_NLA_PROP_WIN]) {
+		u32 win;
+
+		win = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
+		if ((win < TIPC_MIN_LINK_WIN) || (win > TIPC_MAX_LINK_WIN))
+			return -EINVAL;
+	}
+
+	return 0;
+}
diff --git a/net/tipc/link.h b/net/tipc/link.h
index b567a34..4338294 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -37,6 +37,7 @@
 #ifndef _TIPC_LINK_H
 #define _TIPC_LINK_H
 
+#include <net/genetlink.h>
 #include "msg.h"
 #include "node.h"
 
@@ -239,6 +240,8 @@ void tipc_link_set_queue_limits(struct tipc_link *l_ptr, u32 window);
 void tipc_link_retransmit(struct tipc_link *l_ptr,
 			  struct sk_buff *start, u32 retransmits);
 
+int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]);
+
 /*
  * Link sequence number manipulation routines (uses modulo 2**16 arithmetic)
  */
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index ad844d3..7c0cf46 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -1,7 +1,7 @@
 /*
  * net/tipc/netlink.c: TIPC configuration handling
  *
- * Copyright (c) 2005-2006, Ericsson AB
+ * Copyright (c) 2005-2006, 2014, Ericsson AB
  * Copyright (c) 2005-2007, Wind River Systems
  * All rights reserved.
  *
@@ -36,6 +36,7 @@
 
 #include "core.h"
 #include "config.h"
+#include "bearer.h"
 #include <net/genetlink.h>
 
 static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
@@ -68,19 +69,35 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
 	return 0;
 }
 
-static struct genl_family tipc_genl_family = {
+static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = {
+	[TIPC_NLA_UNSPEC]	= { .type = NLA_UNSPEC, },
+	[TIPC_NLA_BEARER]	= { .type = NLA_NESTED, },
+};
+
+struct genl_family tipc_genl_family = {
 	.id		= GENL_ID_GENERATE,
 	.name		= TIPC_GENL_NAME,
 	.version	= TIPC_GENL_VERSION,
-	.hdrsize	= TIPC_GENL_HDRLEN,
-	.maxattr	= 0,
+	.hdrsize	= 0,
+	.maxattr	= TIPC_NLA_MAX,
 };
 
-static struct genl_ops tipc_genl_ops[] = {
+static const struct genl_ops tipc_genl_ops[] = {
 	{
+		/* Legacy ASCII API */
 		.cmd		= TIPC_GENL_CMD,
 		.doit		= handle_cmd,
 	},
+	{
+		.cmd	= TIPC_NL_BEARER_DISABLE,
+		.doit	= tipc_nl_bearer_disable,
+		.policy = tipc_nl_policy,
+	},
+	{
+		.cmd	= TIPC_NL_BEARER_ENABLE,
+		.doit	= tipc_nl_bearer_enable,
+		.policy = tipc_nl_policy,
+	}
 };
 
 int tipc_netlink_start(void)
diff --git a/net/tipc/netlink.h b/net/tipc/netlink.h
new file mode 100644
index 0000000..e3b7890
--- /dev/null
+++ b/net/tipc/netlink.h
@@ -0,0 +1,47 @@
+/*
+ * net/tipc/netlink.h: Include file for TIPC netlink code
+ *
+ * Copyright (c) 2014, Ericsson AB
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_NETLINK_H
+#define _TIPC_NETLINK_H
+
+extern struct genl_family tipc_genl_family;
+
+struct tipc_nl_msg {
+	struct sk_buff *skb;
+	u32 portid;
+	u32 seq;
+};
+
+#endif
-- 
1.7.10.4


------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next 02/14] tipc: add bearer get/dump to new netlink api
  2014-09-11  8:29 [PATCH net-next 00/14] tipc: new netlink API richard.alpe
  2014-09-11  8:29 ` [PATCH net-next 01/14] tipc: add bearer disable/enable to new netlink api richard.alpe
@ 2014-09-11  8:29 ` richard.alpe
  2014-09-11  8:29 ` [PATCH net-next 03/14] tipc: add bearer set " richard.alpe
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: richard.alpe @ 2014-09-11  8:29 UTC (permalink / raw)
  To: netdev; +Cc: tipc-discussion

From: Richard Alpe <richard.alpe@ericsson.com>

Add TIPC_NL_BEARER_GET command to the new tipc netlink API.

This command supports dumping all data about all bearers or getting
all information about a specific bearer.

The information about a bearer includes name, link priorities and
domain.

Netlink logical layout of bearer get message:
-> bearer
    -> name

Netlink logical layout of returned bearer information:
-> bearer
    -> name
    -> link properties
        -> priority
        -> tolerance
        -> window
    -> domain

Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
---
 include/uapi/linux/tipc_config.h |    1 +
 net/tipc/bearer.c                |  125 ++++++++++++++++++++++++++++++++++++++
 net/tipc/bearer.h                |    2 +
 net/tipc/netlink.c               |    6 ++
 4 files changed, 134 insertions(+)

diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h
index 954ecaa..6caf581 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -52,6 +52,7 @@ enum {
 	TIPC_NL_LEGACY,
 	TIPC_NL_BEARER_DISABLE,
 	TIPC_NL_BEARER_ENABLE,
+	TIPC_NL_BEARER_GET,
 
 	__TIPC_NL_CMD_MAX,
 	TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 59815be..7f77cec 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -640,6 +640,131 @@ void tipc_bearer_stop(void)
 	}
 }
 
+/* Caller should hold rtnl_lock to protect the bearer */
+int __tipc_nl_add_bearer(struct tipc_nl_msg *msg, struct tipc_bearer *bearer)
+{
+	void *hdr;
+	struct nlattr *attrs;
+	struct nlattr *prop;
+
+	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
+			  NLM_F_MULTI, TIPC_NL_BEARER_GET);
+	if (!hdr)
+		return -EMSGSIZE;
+
+	attrs = nla_nest_start(msg->skb, TIPC_NLA_BEARER);
+	if (!attrs)
+		goto msg_full;
+
+	if (nla_put_string(msg->skb, TIPC_NLA_BEARER_NAME, bearer->name))
+		goto attr_msg_full;
+
+	prop = nla_nest_start(msg->skb, TIPC_NLA_BEARER_PROP);
+	if (!prop)
+		goto prop_msg_full;
+	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, bearer->priority))
+		goto prop_msg_full;
+	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, bearer->tolerance))
+		goto prop_msg_full;
+	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bearer->window))
+		goto prop_msg_full;
+
+	nla_nest_end(msg->skb, prop);
+	nla_nest_end(msg->skb, attrs);
+	genlmsg_end(msg->skb, hdr);
+
+	return 0;
+
+prop_msg_full:
+	nla_nest_cancel(msg->skb, prop);
+attr_msg_full:
+	nla_nest_cancel(msg->skb, attrs);
+msg_full:
+	genlmsg_cancel(msg->skb, hdr);
+
+	return -EMSGSIZE;
+}
+
+int tipc_nl_bearer_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	int err;
+	int i = cb->args[0];
+	struct tipc_bearer *bearer;
+	struct tipc_nl_msg msg;
+
+	if (i == MAX_BEARERS)
+		return 0;
+
+	msg.skb = skb;
+	msg.portid = NETLINK_CB(cb->skb).portid;
+	msg.seq = cb->nlh->nlmsg_seq;
+
+	rtnl_lock();
+	for (i = 0; i < MAX_BEARERS; i++) {
+		bearer = rtnl_dereference(bearer_list[i]);
+		if (!bearer)
+			continue;
+
+		err = __tipc_nl_add_bearer(&msg, bearer);
+		if (err)
+			break;
+	}
+	rtnl_unlock();
+
+	cb->args[0] = i;
+	return skb->len;
+}
+
+int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info)
+{
+	int err;
+	char *name;
+	struct sk_buff *rep;
+	struct tipc_bearer *bearer;
+	struct tipc_nl_msg msg;
+	struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
+
+	if (!info->attrs[TIPC_NLA_BEARER])
+		return -EINVAL;
+
+	err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
+			       info->attrs[TIPC_NLA_BEARER],
+			       tipc_nl_bearer_policy);
+	if (err)
+		return err;
+
+	if (!attrs[TIPC_NLA_BEARER_NAME])
+		return -EINVAL;
+	name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
+
+	rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!rep)
+		return -ENOMEM;
+
+	msg.skb = rep;
+	msg.portid = info->snd_portid;
+	msg.seq = info->snd_seq;
+
+	rtnl_lock();
+	bearer = tipc_bearer_find(name);
+	if (!bearer) {
+		err = -EINVAL;
+		goto err_out;
+	}
+
+	err = __tipc_nl_add_bearer(&msg, bearer);
+	if (err)
+		goto err_out;
+	rtnl_unlock();
+
+	return genlmsg_reply(rep, info);
+err_out:
+	rtnl_unlock();
+	nlmsg_free(rep);
+
+	return err;
+}
+
 int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info)
 {
 	int err;
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index a87e8c7..2d07e35 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -180,6 +180,8 @@ extern struct tipc_media ib_media_info;
 
 int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info);
 int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info);
+int tipc_nl_bearer_dump(struct sk_buff *skb, struct netlink_callback *cb);
+int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info);
 
 int tipc_media_set_priority(const char *name, u32 new_value);
 int tipc_media_set_window(const char *name, u32 new_value);
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 7c0cf46..ef106a7 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -97,6 +97,12 @@ static const struct genl_ops tipc_genl_ops[] = {
 		.cmd	= TIPC_NL_BEARER_ENABLE,
 		.doit	= tipc_nl_bearer_enable,
 		.policy = tipc_nl_policy,
+	},
+	{
+		.cmd	= TIPC_NL_BEARER_GET,
+		.doit	= tipc_nl_bearer_get,
+		.dumpit	= tipc_nl_bearer_dump,
+		.policy = tipc_nl_policy,
 	}
 };
 
-- 
1.7.10.4


------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next 03/14] tipc: add bearer set to new netlink api
  2014-09-11  8:29 [PATCH net-next 00/14] tipc: new netlink API richard.alpe
  2014-09-11  8:29 ` [PATCH net-next 01/14] tipc: add bearer disable/enable to new netlink api richard.alpe
  2014-09-11  8:29 ` [PATCH net-next 02/14] tipc: add bearer get/dump " richard.alpe
@ 2014-09-11  8:29 ` richard.alpe
  2014-09-11  8:29 ` [PATCH net-next 04/14] tipc: add sock dump " richard.alpe
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: richard.alpe @ 2014-09-11  8:29 UTC (permalink / raw)
  To: netdev; +Cc: tipc-discussion

From: Richard Alpe <richard.alpe@ericsson.com>

Add TIPC_NL_BEARER_SET command to the new tipc netlink API.

This command can set one or more link properties for a particular
bearer.

Netlink logical layout of bearer set message:
-> bearer
    -> name
    -> link properties
        [ -> tolerance ]
        [ -> priority ]
        [ -> window ]

Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
---
 include/uapi/linux/tipc_config.h |    1 +
 net/tipc/bearer.c                |   49 ++++++++++++++++++++++++++++++++++++++
 net/tipc/bearer.h                |    1 +
 net/tipc/netlink.c               |    5 ++++
 4 files changed, 56 insertions(+)

diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h
index 6caf581..af7acac 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -53,6 +53,7 @@ enum {
 	TIPC_NL_BEARER_DISABLE,
 	TIPC_NL_BEARER_ENABLE,
 	TIPC_NL_BEARER_GET,
+	TIPC_NL_BEARER_SET,
 
 	__TIPC_NL_CMD_MAX,
 	TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 7f77cec..906e644 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -849,3 +849,52 @@ int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info)
 
 	return 0;
 }
+
+int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info)
+{
+	int err;
+	char *name;
+	struct tipc_bearer *b;
+	struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
+
+	if (!info->attrs[TIPC_NLA_BEARER])
+		return -EINVAL;
+
+	err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
+			       info->attrs[TIPC_NLA_BEARER],
+			       tipc_nl_bearer_policy);
+	if (err)
+		return err;
+
+	if (!attrs[TIPC_NLA_BEARER_NAME])
+		return -EINVAL;
+	name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
+
+	rtnl_lock();
+	b = tipc_bearer_find(name);
+	if (!b) {
+		rtnl_unlock();
+		return -EINVAL;
+	}
+
+	if (attrs[TIPC_NLA_BEARER_PROP]) {
+		struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
+
+		err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_BEARER_PROP],
+					      props);
+		if (err) {
+			rtnl_unlock();
+			return err;
+		}
+
+		if (props[TIPC_NLA_PROP_TOL])
+			b->tolerance = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
+		if (props[TIPC_NLA_PROP_PRIO])
+			b->priority = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
+		if (props[TIPC_NLA_PROP_WIN])
+			b->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
+	}
+	rtnl_unlock();
+
+	return 0;
+}
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 2d07e35..c6cf9df 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -182,6 +182,7 @@ int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info);
 int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info);
 int tipc_nl_bearer_dump(struct sk_buff *skb, struct netlink_callback *cb);
 int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info);
+int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info);
 
 int tipc_media_set_priority(const char *name, u32 new_value);
 int tipc_media_set_window(const char *name, u32 new_value);
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index ef106a7..e5fbea9 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -103,6 +103,11 @@ static const struct genl_ops tipc_genl_ops[] = {
 		.doit	= tipc_nl_bearer_get,
 		.dumpit	= tipc_nl_bearer_dump,
 		.policy = tipc_nl_policy,
+	},
+	{
+		.cmd	= TIPC_NL_BEARER_SET,
+		.doit	= tipc_nl_bearer_set,
+		.policy = tipc_nl_policy,
 	}
 };
 
-- 
1.7.10.4


------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next 04/14] tipc: add sock dump to new netlink api
  2014-09-11  8:29 [PATCH net-next 00/14] tipc: new netlink API richard.alpe
                   ` (2 preceding siblings ...)
  2014-09-11  8:29 ` [PATCH net-next 03/14] tipc: add bearer set " richard.alpe
@ 2014-09-11  8:29 ` richard.alpe
  2014-09-12 21:10   ` David Miller
  2014-09-11  8:29 ` [PATCH net-next 05/14] tipc: add link get/dump " richard.alpe
                   ` (9 subsequent siblings)
  13 siblings, 1 reply; 24+ messages in thread
From: richard.alpe @ 2014-09-11  8:29 UTC (permalink / raw)
  To: netdev; +Cc: tipc-discussion

From: Richard Alpe <richard.alpe@ericsson.com>

Add TIPC_NL_SOCK_GET command to the new tipc netlink API.

This command supports dumping of all available sockets with their
associated connection or publication(s). It could be extended to reply
with a single socket if the NLM_F_DUMP isn't set.

The information about a socket includes reference, address, connection
information / publication information.

Netlink logical layout of response message:
-> socket
    -> reference
    -> address
    [
    -> connection
        -> node
        -> socket
        [
        -> connected flag
        -> type
        -> instance
        ]
    ]
    [
    -> publications
        -> publication
            -> type
            -> lower
            -> upper
    ]

Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
---
 include/uapi/linux/tipc_config.h |   44 +++++++++++
 net/tipc/netlink.c               |    7 ++
 net/tipc/socket.c                |  159 ++++++++++++++++++++++++++++++++++++++
 net/tipc/socket.h                |    2 +
 4 files changed, 212 insertions(+)

diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h
index af7acac..e09dec2 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -54,6 +54,7 @@ enum {
 	TIPC_NL_BEARER_ENABLE,
 	TIPC_NL_BEARER_GET,
 	TIPC_NL_BEARER_SET,
+	TIPC_NL_SOCK_GET,
 
 	__TIPC_NL_CMD_MAX,
 	TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
@@ -63,6 +64,7 @@ enum {
 enum {
 	TIPC_NLA_UNSPEC,
 	TIPC_NLA_BEARER,		/* nest */
+	TIPC_NLA_SOCK,			/* nest */
 
 	__TIPC_NLA_MAX,
 	TIPC_NLA_MAX = __TIPC_NLA_MAX - 1
@@ -79,6 +81,48 @@ enum {
 	TIPC_NLA_BEARER_MAX = __TIPC_NLA_BEARER_MAX - 1
 };
 
+/* Port info */
+enum {
+	TIPC_NLA_SOCK_UNSPEC,
+	TIPC_NLA_SOCK_ADDR,		/* u32 */
+	TIPC_NLA_SOCK_REF,		/* u32 */
+	TIPC_NLA_SOCK_CON,		/* nest */
+	TIPC_NLA_SOCK_PUBL,		/* nest */
+
+	__TIPC_NLA_SOCK_MAX,
+	TIPC_NLA_SOCK_MAX = __TIPC_NLA_SOCK_MAX - 1
+};
+
+/* Nest, publication info */
+enum {
+	TIPC_NLA_PUBL_UNSPEC,
+
+	TIPC_NLA_PUBL_TYPE,		/* u32 */
+	TIPC_NLA_PUBL_LOWER,		/* u32 */
+	TIPC_NLA_PUBL_UPPER,		/* u32 */
+	TIPC_NLA_PUBL_SCOPE,		/* u32 */
+	TIPC_NLA_PUBL_NODE,		/* u32 */
+	TIPC_NLA_PUBL_REF,		/* u32 */
+	TIPC_NLA_PUBL_KEY,		/* u32 */
+
+	__TIPC_NLA_PUBL_MAX,
+	TIPC_NLA_PUBL_MAX = __TIPC_NLA_PUBL_MAX - 1
+};
+
+/* Nest, connection info */
+enum {
+	TIPC_NLA_CON_UNSPEC,
+
+	TIPC_NLA_CON_FLAG,		/* flag */
+	TIPC_NLA_CON_NODE,		/* u32 */
+	TIPC_NLA_CON_SOCK,		/* u32 */
+	TIPC_NLA_CON_TYPE,		/* u32 */
+	TIPC_NLA_CON_INST,		/* u32 */
+
+	__TIPC_NLA_CON_MAX,
+	TIPC_NLA_CON_MAX = __TIPC_NLA_CON_MAX - 1
+};
+
 /* Nest, link propreties. Valid for link, media and bearer */
 enum {
 	TIPC_NLA_PROP_UNSPEC,
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index e5fbea9..52973ce 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -36,6 +36,7 @@
 
 #include "core.h"
 #include "config.h"
+#include "socket.h"
 #include "bearer.h"
 #include <net/genetlink.h>
 
@@ -72,6 +73,7 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
 static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = {
 	[TIPC_NLA_UNSPEC]	= { .type = NLA_UNSPEC, },
 	[TIPC_NLA_BEARER]	= { .type = NLA_NESTED, },
+	[TIPC_NLA_SOCK]		= { .type = NLA_NESTED, },
 };
 
 struct genl_family tipc_genl_family = {
@@ -108,6 +110,11 @@ static const struct genl_ops tipc_genl_ops[] = {
 		.cmd	= TIPC_NL_BEARER_SET,
 		.doit	= tipc_nl_bearer_set,
 		.policy = tipc_nl_policy,
+	},
+	{
+		.cmd	= TIPC_NL_SOCK_GET,
+		.dumpit	= tipc_nl_sk_dump,
+		.policy = tipc_nl_policy,
 	}
 };
 
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 75275c5..bb58029 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -2802,3 +2802,162 @@ void tipc_socket_stop(void)
 	sock_unregister(tipc_family_ops.family);
 	proto_unregister(&tipc_proto);
 }
+
+/* Caller should hold socket lock for the passed tipc socket. */
+int __tipc_nl_list_sk_publ(struct sk_buff *skb, struct netlink_callback *cb,
+			   struct tipc_sock *tsk, u32 *prev_publ)
+{
+	struct nlattr *publ;
+	struct publication *p;
+
+	if (*prev_publ) {
+		list_for_each_entry(p, &tsk->publications, pport_list) {
+			if (p->key == *prev_publ)
+				break;
+		}
+
+		if (p->key != *prev_publ) {
+			nlmsg_hdr(skb)->nlmsg_flags |= NLM_F_DUMP_INTR;
+			*prev_publ = 0;
+			return -EPIPE;
+		}
+	} else {
+		p = list_first_entry(&tsk->publications, struct publication,
+				     pport_list);
+	}
+
+	list_for_each_entry_from(p, &tsk->publications, pport_list) {
+		publ = nla_nest_start(skb, TIPC_NLA_SOCK_PUBL);
+		if (nla_put_u32(skb, TIPC_NLA_PUBL_TYPE, p->type))
+			goto msg_full;
+		if (nla_put_u32(skb, TIPC_NLA_PUBL_LOWER, p->lower))
+			goto msg_full;
+		if (nla_put_u32(skb, TIPC_NLA_PUBL_UPPER, p->upper))
+			goto msg_full;
+		nla_nest_end(skb, publ);
+	}
+
+	*prev_publ = 0;
+
+	return 0;
+
+msg_full:
+	*prev_publ = p->key;
+	nla_nest_cancel(skb, publ);
+
+	return -EMSGSIZE;
+}
+
+/* Caller should hold socket lock for the passed tipc socket. */
+int __tipc_nl_add_sk_con(struct sk_buff *skb, struct tipc_sock *tsk)
+{
+	u32 peer_node;
+	u32 peer_port;
+	struct nlattr *nest;
+
+	peer_node = tsk_peer_node(tsk);
+	peer_port = tsk_peer_port(tsk);
+
+	nest = nla_nest_start(skb, TIPC_NLA_SOCK_CON);
+
+	if (nla_put_u32(skb, TIPC_NLA_CON_NODE, peer_node))
+		goto msg_full;
+	if (nla_put_u32(skb, TIPC_NLA_CON_SOCK, peer_port))
+		goto msg_full;
+
+	if (tsk->conn_type != 0) {
+		if (nla_put_flag(skb, TIPC_NLA_CON_FLAG))
+			goto msg_full;
+		if (nla_put_u32(skb, TIPC_NLA_CON_TYPE, tsk->conn_type))
+			goto msg_full;
+		if (nla_put_u32(skb, TIPC_NLA_CON_INST, tsk->conn_instance))
+			goto msg_full;
+	}
+	nla_nest_end(skb, nest);
+
+	return 0;
+
+msg_full:
+	nla_nest_cancel(skb, nest);
+
+	return -EMSGSIZE;
+}
+
+/* Caller should hold socket lock for the passed tipc socket. */
+int __tipc_nl_add_sk(struct sk_buff *skb, struct netlink_callback *cb,
+		     struct tipc_sock *tsk, u32 *prev_publ)
+{
+	void *hdr;
+	int res = 0;
+	struct nlattr *attrs;
+	struct nlattr *publs;
+
+	hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
+			  &tipc_genl_family, NLM_F_MULTI, TIPC_NL_SOCK_GET);
+	if (!hdr)
+		goto msg_cancel;
+
+	attrs = nla_nest_start(skb, TIPC_NLA_SOCK);
+	if (!attrs)
+		goto genlmsg_cancel;
+
+	if (nla_put_u32(skb, TIPC_NLA_SOCK_REF, tsk->ref))
+		goto attr_msg_cancel;
+	if (nla_put_u32(skb, TIPC_NLA_SOCK_ADDR, tipc_own_addr))
+		goto attr_msg_cancel;
+
+	/* We assume a socket is either connected or published */
+	if (tsk->connected) {
+		res = __tipc_nl_add_sk_con(skb, tsk);
+		if (res != 0)
+			goto attr_msg_cancel;
+	} else {
+		publs = nla_nest_start(skb, TIPC_NLA_SOCK_PUBL);
+		if (!publs)
+			goto attr_msg_cancel;
+
+		res = __tipc_nl_list_sk_publ(skb, cb, tsk, prev_publ);
+		/* As the publication count is arbitrary large, we send even an
+		 * incomplete listing.
+		 */
+		nla_nest_end(skb, publs);
+	}
+
+	nla_nest_end(skb, attrs);
+	genlmsg_end(skb, hdr);
+
+	return res;
+
+attr_msg_cancel:
+	nla_nest_cancel(skb, attrs);
+genlmsg_cancel:
+	genlmsg_cancel(skb, hdr);
+msg_cancel:
+	return -EMSGSIZE;
+}
+
+int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	int err;
+	struct tipc_sock *tsk;
+	u32 prev_tsk = cb->args[0];
+	u32 prev_publ = cb->args[1];
+	u32 tsk_ref = prev_tsk;
+
+	tsk = tipc_sk_get_next(&tsk_ref);
+	for (; tsk; tsk = tipc_sk_get_next(&tsk_ref)) {
+		lock_sock(&tsk->sk);
+		err = __tipc_nl_add_sk(skb, cb, tsk, &prev_publ);
+		release_sock(&tsk->sk);
+		tipc_sk_put(tsk);
+		if (err)
+			break;
+
+		prev_tsk = tsk_ref;
+	}
+
+	cb->args[0] = prev_tsk;
+	cb->args[1] = prev_publ;
+
+	return skb->len;
+}
diff --git a/net/tipc/socket.h b/net/tipc/socket.h
index baa43d0..16dfd62 100644
--- a/net/tipc/socket.h
+++ b/net/tipc/socket.h
@@ -36,6 +36,7 @@
 #define _TIPC_SOCK_H
 
 #include <net/sock.h>
+#include <net/genetlink.h>
 
 #define TIPC_CONNACK_INTV         256
 #define TIPC_FLOWCTRL_WIN        (TIPC_CONNACK_INTV * 2)
@@ -47,5 +48,6 @@ void tipc_sk_mcast_rcv(struct sk_buff *buf);
 void tipc_sk_reinit(void);
 int tipc_sk_ref_table_init(u32 requested_size, u32 start);
 void tipc_sk_ref_table_stop(void);
+int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb);
 
 #endif
-- 
1.7.10.4


------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next 05/14] tipc: add link get/dump to new netlink api
  2014-09-11  8:29 [PATCH net-next 00/14] tipc: new netlink API richard.alpe
                   ` (3 preceding siblings ...)
  2014-09-11  8:29 ` [PATCH net-next 04/14] tipc: add sock dump " richard.alpe
@ 2014-09-11  8:29 ` richard.alpe
  2014-09-11  8:29 ` [PATCH net-next 06/14] tipc: add link set " richard.alpe
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: richard.alpe @ 2014-09-11  8:29 UTC (permalink / raw)
  To: netdev; +Cc: tipc-discussion

From: Richard Alpe <richard.alpe@ericsson.com>

Add TIPC_NL_LINK_GET command to the new tipc netlink API.

This command supports dumping all information about all links
(including the broadcast link) or getting all information about a
specific link (not the broadcast link).

The information about a link includes name, transmission info,
properties and link statistics.

As the tipc broadcast link is special we unfortunately have to treat
it specially. It is a deliberate decision not to abstract the
broadcast link on this (API) level.

Netlink logical layout of link response message:
    -> port
        -> name
        -> MTU
        -> RX
        -> TX
        -> up flag
        -> active flag
        -> properties
           -> priority
           -> tolerance
           -> window
        -> statistics
            -> rx_info
            -> rx_fragments
            -> rx_fragmented
            -> rx_bundles
            -> rx_bundled
            -> tx_info
            -> tx_fragments
            -> tx_fragmented
            -> tx_bundles
            -> tx_bundled
            -> msg_prof_tot
            -> msg_len_cnt
            -> msg_len_tot
            -> msg_len_p0
            -> msg_len_p1
            -> msg_len_p2
            -> msg_len_p3
            -> msg_len_p4
            -> msg_len_p5
            -> msg_len_p6
            -> rx_states
            -> rx_probes
            -> rx_nacks
            -> rx_deferred
            -> tx_states
            -> tx_probes
            -> tx_nacks
            -> tx_acks
            -> retransmitted
            -> duplicates
            -> link_congs
            -> max_queue
            -> avg_queue

Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
---
 include/uapi/linux/tipc_config.h |   62 +++++++++
 net/tipc/bcast.c                 |  111 +++++++++++++++
 net/tipc/bcast.h                 |    3 +
 net/tipc/link.c                  |  284 ++++++++++++++++++++++++++++++++++++++
 net/tipc/link.h                  |    2 +
 net/tipc/netlink.c               |    8 ++
 6 files changed, 470 insertions(+)

diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h
index e09dec2..9c51151 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -55,6 +55,7 @@ enum {
 	TIPC_NL_BEARER_GET,
 	TIPC_NL_BEARER_SET,
 	TIPC_NL_SOCK_GET,
+	TIPC_NL_LINK_GET,
 
 	__TIPC_NL_CMD_MAX,
 	TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
@@ -65,6 +66,7 @@ enum {
 	TIPC_NLA_UNSPEC,
 	TIPC_NLA_BEARER,		/* nest */
 	TIPC_NLA_SOCK,			/* nest */
+	TIPC_NLA_LINK,			/* nest */
 
 	__TIPC_NLA_MAX,
 	TIPC_NLA_MAX = __TIPC_NLA_MAX - 1
@@ -93,6 +95,23 @@ enum {
 	TIPC_NLA_SOCK_MAX = __TIPC_NLA_SOCK_MAX - 1
 };
 
+/* Link info */
+enum {
+	TIPC_NLA_LINK_UNSPEC,
+	TIPC_NLA_LINK_NAME,		/* string */
+	TIPC_NLA_LINK_MTU,		/* u32 */
+	TIPC_NLA_LINK_BROADCAST,	/* flag */
+	TIPC_NLA_LINK_UP,		/* flag */
+	TIPC_NLA_LINK_ACTIVE,		/* flag */
+	TIPC_NLA_LINK_PROP,		/* nest */
+	TIPC_NLA_LINK_STATS,		/* nest */
+	TIPC_NLA_LINK_RX,		/* u32 */
+	TIPC_NLA_LINK_TX,		/* u32 */
+
+	__TIPC_NLA_LINK_MAX,
+	TIPC_NLA_LINK_MAX = __TIPC_NLA_LINK_MAX - 1
+};
+
 /* Nest, publication info */
 enum {
 	TIPC_NLA_PUBL_UNSPEC,
@@ -134,6 +153,49 @@ enum {
 	__TIPC_NLA_PROP_MAX,
 	TIPC_NLA_PROP_MAX = __TIPC_NLA_PROP_MAX - 1
 };
+
+/* Nest, statistics info */
+enum {
+	TIPC_NLA_STATS_UNSPEC,
+
+	TIPC_NLA_STATS_RX_INFO,		/* u32 */
+	TIPC_NLA_STATS_RX_FRAGMENTS,	/* u32 */
+	TIPC_NLA_STATS_RX_FRAGMENTED,	/* u32 */
+	TIPC_NLA_STATS_RX_BUNDLES,	/* u32 */
+	TIPC_NLA_STATS_RX_BUNDLED,	/* u32 */
+	TIPC_NLA_STATS_TX_INFO,		/* u32 */
+	TIPC_NLA_STATS_TX_FRAGMENTS,	/* u32 */
+	TIPC_NLA_STATS_TX_FRAGMENTED,	/* u32 */
+	TIPC_NLA_STATS_TX_BUNDLES,	/* u32 */
+	TIPC_NLA_STATS_TX_BUNDLED,	/* u32 */
+	TIPC_NLA_STATS_MSG_PROF_TOT,	/* u32 */
+	TIPC_NLA_STATS_MSG_LEN_CNT,	/* u32 */
+	TIPC_NLA_STATS_MSG_LEN_TOT,	/* u32 */
+	TIPC_NLA_STATS_MSG_LEN_P0,	/* u32 */
+	TIPC_NLA_STATS_MSG_LEN_P1,	/* u32 */
+	TIPC_NLA_STATS_MSG_LEN_P2,	/* u32 */
+	TIPC_NLA_STATS_MSG_LEN_P3,	/* u32 */
+	TIPC_NLA_STATS_MSG_LEN_P4,	/* u32 */
+	TIPC_NLA_STATS_MSG_LEN_P5,	/* u32 */
+	TIPC_NLA_STATS_MSG_LEN_P6,	/* u32 */
+	TIPC_NLA_STATS_RX_STATES,	/* u32 */
+	TIPC_NLA_STATS_RX_PROBES,	/* u32 */
+	TIPC_NLA_STATS_RX_NACKS,	/* u32 */
+	TIPC_NLA_STATS_RX_DEFERRED,	/* u32 */
+	TIPC_NLA_STATS_TX_STATES,	/* u32 */
+	TIPC_NLA_STATS_TX_PROBES,	/* u32 */
+	TIPC_NLA_STATS_TX_NACKS,	/* u32 */
+	TIPC_NLA_STATS_TX_ACKS,		/* u32 */
+	TIPC_NLA_STATS_RETRANSMITTED,	/* u32 */
+	TIPC_NLA_STATS_DUPLICATES,	/* u32 */
+	TIPC_NLA_STATS_LINK_CONGS,	/* u32 */
+	TIPC_NLA_STATS_MAX_QUEUE,	/* u32 */
+	TIPC_NLA_STATS_AVG_QUEUE,	/* u32 */
+
+	__TIPC_NLA_STATS_MAX,
+	TIPC_NLA_STATS_MAX = __TIPC_NLA_STATS_MAX - 1
+};
+
 /*
  * Configuration
  *
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index b2bbe69..e12476b 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -755,6 +755,117 @@ void tipc_bcbearer_sort(struct tipc_node_map *nm_ptr, u32 node, bool action)
 	tipc_bclink_unlock();
 }
 
+int __tipc_nl_add_bc_link_stat(struct sk_buff *skb, struct tipc_stats *stats)
+{
+	int i;
+	struct nlattr *nest;
+
+	struct nla_map {
+		__u32 key;
+		__u32 val;
+	};
+
+	struct nla_map map[] = {
+		{TIPC_NLA_STATS_RX_INFO, stats->recv_info},
+		{TIPC_NLA_STATS_RX_FRAGMENTS, stats->recv_fragments},
+		{TIPC_NLA_STATS_RX_FRAGMENTED, stats->recv_fragmented},
+		{TIPC_NLA_STATS_RX_BUNDLES, stats->recv_bundles},
+		{TIPC_NLA_STATS_RX_BUNDLED, stats->recv_bundled},
+		{TIPC_NLA_STATS_TX_INFO, stats->sent_info},
+		{TIPC_NLA_STATS_TX_FRAGMENTS, stats->sent_fragments},
+		{TIPC_NLA_STATS_TX_FRAGMENTED, stats->sent_fragmented},
+		{TIPC_NLA_STATS_TX_BUNDLES, stats->sent_bundles},
+		{TIPC_NLA_STATS_TX_BUNDLED, stats->sent_bundled},
+		{TIPC_NLA_STATS_RX_NACKS, stats->recv_nacks},
+		{TIPC_NLA_STATS_RX_DEFERRED, stats->deferred_recv},
+		{TIPC_NLA_STATS_TX_NACKS, stats->sent_nacks},
+		{TIPC_NLA_STATS_TX_ACKS, stats->sent_acks},
+		{TIPC_NLA_STATS_RETRANSMITTED, stats->retransmitted},
+		{TIPC_NLA_STATS_DUPLICATES, stats->duplicates},
+		{TIPC_NLA_STATS_LINK_CONGS, stats->link_congs},
+		{TIPC_NLA_STATS_MAX_QUEUE, stats->max_queue_sz},
+		{TIPC_NLA_STATS_AVG_QUEUE, stats->queue_sz_counts ?
+			(stats->accu_queue_sz / stats->queue_sz_counts) : 0}
+	};
+
+	nest = nla_nest_start(skb, TIPC_NLA_LINK_STATS);
+	if (!nest)
+		return -EMSGSIZE;
+
+	for (i = 0; i <  ARRAY_SIZE(map); i++)
+		if (nla_put_u32(skb, map[i].key, map[i].val))
+			goto msg_full;
+
+	nla_nest_end(skb, nest);
+
+	return 0;
+msg_full:
+	nla_nest_cancel(skb, nest);
+
+	return -EMSGSIZE;
+}
+
+int tipc_nl_add_bc_link(struct tipc_nl_msg *msg)
+{
+	int err;
+	void *hdr;
+	struct nlattr *attrs;
+	struct nlattr *prop;
+
+	if (!bcl)
+		return 0;
+
+	tipc_bclink_lock();
+
+	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
+			  NLM_F_MULTI, TIPC_NL_LINK_GET);
+	if (!hdr)
+		return -EMSGSIZE;
+
+	attrs = nla_nest_start(msg->skb, TIPC_NLA_LINK);
+	if (!attrs)
+		goto msg_full;
+
+	/* The broadcast link is always up */
+	if (nla_put_flag(msg->skb, TIPC_NLA_LINK_UP))
+		goto attr_msg_full;
+
+	if (nla_put_flag(msg->skb, TIPC_NLA_LINK_BROADCAST))
+		goto attr_msg_full;
+	if (nla_put_string(msg->skb, TIPC_NLA_LINK_NAME, bcl->name))
+		goto attr_msg_full;
+	if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, bcl->next_in_no))
+		goto attr_msg_full;
+	if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, bcl->next_out_no))
+		goto attr_msg_full;
+
+	prop = nla_nest_start(msg->skb, TIPC_NLA_LINK_PROP);
+	if (!prop)
+		goto attr_msg_full;
+	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bcl->queue_limit[0]))
+		goto prop_msg_full;
+	nla_nest_end(msg->skb, prop);
+
+	err = __tipc_nl_add_bc_link_stat(msg->skb, &bcl->stats);
+	if (err)
+		goto attr_msg_full;
+
+	tipc_bclink_unlock();
+	nla_nest_end(msg->skb, attrs);
+	genlmsg_end(msg->skb, hdr);
+
+	return 0;
+
+prop_msg_full:
+	nla_nest_cancel(msg->skb, prop);
+attr_msg_full:
+	nla_nest_cancel(msg->skb, attrs);
+msg_full:
+	tipc_bclink_unlock();
+	genlmsg_cancel(msg->skb, hdr);
+
+	return -EMSGSIZE;
+}
 
 int tipc_bclink_stats(char *buf, const u32 buf_size)
 {
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
index 4875d95..3c0263e 100644
--- a/net/tipc/bcast.h
+++ b/net/tipc/bcast.h
@@ -37,6 +37,8 @@
 #ifndef _TIPC_BCAST_H
 #define _TIPC_BCAST_H
 
+#include "netlink.h"
+
 #define MAX_NODES 4096
 #define WSIZE 32
 #define TIPC_BCLINK_RESET 1
@@ -99,5 +101,6 @@ int  tipc_bclink_set_queue_limits(u32 limit);
 void tipc_bcbearer_sort(struct tipc_node_map *nm_ptr, u32 node, bool action);
 uint  tipc_bclink_get_mtu(void);
 int tipc_bclink_xmit(struct sk_buff *buf);
+int tipc_nl_add_bc_link(struct tipc_nl_msg *msg);
 
 #endif
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 4628538..e0aaca4 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -36,6 +36,7 @@
 
 #include "core.h"
 #include "link.h"
+#include "bcast.h"
 #include "socket.h"
 #include "name_distr.h"
 #include "discover.h"
@@ -51,6 +52,22 @@ static const char *link_co_err = "Link changeover error, ";
 static const char *link_rst_msg = "Resetting link ";
 static const char *link_unk_evt = "Unknown link event ";
 
+static const struct nla_policy tipc_nl_link_policy[TIPC_NLA_LINK_MAX + 1] = {
+	[TIPC_NLA_LINK_UNSPEC]		= { .type = NLA_UNSPEC },
+	[TIPC_NLA_LINK_NAME] = {
+		.type = NLA_STRING,
+		.len = TIPC_MAX_LINK_NAME
+	},
+	[TIPC_NLA_LINK_MTU]		= { .type = NLA_U32 },
+	[TIPC_NLA_LINK_BROADCAST]	= { .type = NLA_FLAG },
+	[TIPC_NLA_LINK_UP]		= { .type = NLA_FLAG },
+	[TIPC_NLA_LINK_ACTIVE]		= { .type = NLA_FLAG },
+	[TIPC_NLA_LINK_PROP]		= { .type = NLA_NESTED },
+	[TIPC_NLA_LINK_STATS]		= { .type = NLA_NESTED },
+	[TIPC_NLA_LINK_RX]		= { .type = NLA_U32 },
+	[TIPC_NLA_LINK_TX]		= { .type = NLA_U32 }
+};
+
 /* Properties valid for media, bearar and link */
 static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = {
 	[TIPC_NLA_PROP_UNSPEC]		= { .type = NLA_UNSPEC },
@@ -2417,3 +2434,270 @@ int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[])
 
 	return 0;
 }
+
+int __tipc_nl_add_stats(struct sk_buff *skb, struct tipc_stats *s)
+{
+	int i;
+	struct nlattr *stats;
+
+	struct nla_map {
+		u32 key;
+		u32 val;
+	};
+
+	struct nla_map map[] = {
+		{TIPC_NLA_STATS_RX_INFO, s->recv_info},
+		{TIPC_NLA_STATS_RX_FRAGMENTS, s->recv_fragments},
+		{TIPC_NLA_STATS_RX_FRAGMENTED, s->recv_fragmented},
+		{TIPC_NLA_STATS_RX_BUNDLES, s->recv_bundles},
+		{TIPC_NLA_STATS_RX_BUNDLED, s->recv_bundled},
+		{TIPC_NLA_STATS_TX_INFO, s->sent_info},
+		{TIPC_NLA_STATS_TX_FRAGMENTS, s->sent_fragments},
+		{TIPC_NLA_STATS_TX_FRAGMENTED, s->sent_fragmented},
+		{TIPC_NLA_STATS_TX_BUNDLES, s->sent_bundles},
+		{TIPC_NLA_STATS_TX_BUNDLED, s->sent_bundled},
+		{TIPC_NLA_STATS_MSG_PROF_TOT, (s->msg_length_counts) ?
+			s->msg_length_counts : 1},
+		{TIPC_NLA_STATS_MSG_LEN_CNT, s->msg_length_counts},
+		{TIPC_NLA_STATS_MSG_LEN_TOT, s->msg_lengths_total},
+		{TIPC_NLA_STATS_MSG_LEN_P0, s->msg_length_profile[0]},
+		{TIPC_NLA_STATS_MSG_LEN_P1, s->msg_length_profile[1]},
+		{TIPC_NLA_STATS_MSG_LEN_P2, s->msg_length_profile[2]},
+		{TIPC_NLA_STATS_MSG_LEN_P3, s->msg_length_profile[3]},
+		{TIPC_NLA_STATS_MSG_LEN_P4, s->msg_length_profile[4]},
+		{TIPC_NLA_STATS_MSG_LEN_P5, s->msg_length_profile[5]},
+		{TIPC_NLA_STATS_MSG_LEN_P6, s->msg_length_profile[6]},
+		{TIPC_NLA_STATS_RX_STATES, s->recv_states},
+		{TIPC_NLA_STATS_RX_PROBES, s->recv_probes},
+		{TIPC_NLA_STATS_RX_NACKS, s->recv_nacks},
+		{TIPC_NLA_STATS_RX_DEFERRED, s->deferred_recv},
+		{TIPC_NLA_STATS_TX_STATES, s->sent_states},
+		{TIPC_NLA_STATS_TX_PROBES, s->sent_probes},
+		{TIPC_NLA_STATS_TX_NACKS, s->sent_nacks},
+		{TIPC_NLA_STATS_TX_ACKS, s->sent_acks},
+		{TIPC_NLA_STATS_RETRANSMITTED, s->retransmitted},
+		{TIPC_NLA_STATS_DUPLICATES, s->duplicates},
+		{TIPC_NLA_STATS_LINK_CONGS, s->link_congs},
+		{TIPC_NLA_STATS_MAX_QUEUE, s->max_queue_sz},
+		{TIPC_NLA_STATS_AVG_QUEUE, s->queue_sz_counts ?
+			(s->accu_queue_sz / s->queue_sz_counts) : 0}
+	};
+
+	stats = nla_nest_start(skb, TIPC_NLA_LINK_STATS);
+	if (!stats)
+		return -EMSGSIZE;
+
+	for (i = 0; i <  ARRAY_SIZE(map); i++)
+		if (nla_put_u32(skb, map[i].key, map[i].val))
+			goto msg_full;
+
+	nla_nest_end(skb, stats);
+
+	return 0;
+msg_full:
+	nla_nest_cancel(skb, stats);
+
+	return -EMSGSIZE;
+}
+
+/* Caller should hold appropriate locks to protect the link */
+int __tipc_nl_add_link(struct tipc_nl_msg *msg, struct tipc_link *link)
+{
+	int err;
+	void *hdr;
+	struct nlattr *attrs;
+	struct nlattr *prop;
+
+	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
+			  NLM_F_MULTI, TIPC_NL_LINK_GET);
+	if (!hdr)
+		return -EMSGSIZE;
+
+	attrs = nla_nest_start(msg->skb, TIPC_NLA_LINK);
+	if (!attrs)
+		goto msg_full;
+
+	if (nla_put_string(msg->skb, TIPC_NLA_LINK_NAME, link->name))
+		goto attr_msg_full;
+	if (nla_put_u32(msg->skb, TIPC_NLA_LINK_MTU, link->max_pkt))
+		goto attr_msg_full;
+	if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, link->next_in_no))
+		goto attr_msg_full;
+	if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, link->next_out_no))
+		goto attr_msg_full;
+
+	if (tipc_link_is_up(link))
+		if (nla_put_flag(msg->skb, TIPC_NLA_LINK_UP))
+			goto attr_msg_full;
+	if (tipc_link_is_active(link))
+		if (nla_put_flag(msg->skb, TIPC_NLA_LINK_ACTIVE))
+			goto attr_msg_full;
+
+	prop = nla_nest_start(msg->skb, TIPC_NLA_LINK_PROP);
+	if (!prop)
+		goto attr_msg_full;
+	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, link->priority))
+		goto prop_msg_full;
+	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, link->tolerance))
+		goto prop_msg_full;
+	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN,
+			link->queue_limit[TIPC_LOW_IMPORTANCE]))
+		goto prop_msg_full;
+	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, link->priority))
+		goto prop_msg_full;
+	nla_nest_end(msg->skb, prop);
+
+	err = __tipc_nl_add_stats(msg->skb, &link->stats);
+	if (err)
+		goto attr_msg_full;
+
+	nla_nest_end(msg->skb, attrs);
+	genlmsg_end(msg->skb, hdr);
+
+	return 0;
+
+prop_msg_full:
+	nla_nest_cancel(msg->skb, prop);
+attr_msg_full:
+	nla_nest_cancel(msg->skb, attrs);
+msg_full:
+	genlmsg_cancel(msg->skb, hdr);
+
+	return -EMSGSIZE;
+}
+
+/* Caller should hold node lock  */
+int __tipc_nl_add_node_links(struct tipc_nl_msg *msg, struct tipc_node *node,
+			     u32 *prev_link)
+{
+	u32 i;
+	int err;
+
+	for (i = *prev_link; i < MAX_BEARERS; i++) {
+		*prev_link = i;
+
+		if (!node->links[i])
+			continue;
+
+		err = __tipc_nl_add_link(msg, node->links[i]);
+		if (err)
+			return err;
+	}
+	*prev_link = 0;
+
+	return 0;
+}
+
+int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct tipc_node *node;
+	struct tipc_nl_msg msg;
+	u32 prev_node = cb->args[0];
+	u32 prev_link = cb->args[1];
+	int done = cb->args[2];
+	int err;
+
+	if (done)
+		return 0;
+
+	msg.skb = skb;
+	msg.portid = NETLINK_CB(cb->skb).portid;
+	msg.seq = cb->nlh->nlmsg_seq;
+
+	rcu_read_lock();
+
+	if (prev_node) {
+		node = tipc_node_find(prev_node);
+		if (!node) {
+			/* We never set seq or call nl_dump_check_consistent()
+			 * this means that setting prev_seq here will cause the
+			 * consistence check to fail in the netlink callback
+			 * handler. Resulting in the last NLMSG_DONE message
+			 * having the NLM_F_DUMP_INTR flag set.
+			 */
+			cb->prev_seq = 1;
+			goto out;
+		}
+
+		list_for_each_entry_continue_rcu(node, &tipc_node_list, list) {
+			tipc_node_lock(node);
+			err = __tipc_nl_add_node_links(&msg, node, &prev_link);
+			tipc_node_unlock(node);
+			if (err)
+				goto out;
+
+			prev_node = node->addr;
+		}
+	} else {
+		err = tipc_nl_add_bc_link(&msg);
+		if (err)
+			goto out;
+
+		list_for_each_entry_rcu(node, &tipc_node_list, list) {
+			tipc_node_lock(node);
+			err = __tipc_nl_add_node_links(&msg, node, &prev_link);
+			tipc_node_unlock(node);
+			if (err)
+				goto out;
+
+			prev_node = node->addr;
+		}
+	}
+	done = 1;
+out:
+	rcu_read_unlock();
+
+	cb->args[0] = prev_node;
+	cb->args[1] = prev_link;
+	cb->args[2] = done;
+
+	return skb->len;
+}
+
+int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info)
+{
+	struct sk_buff *ans_skb;
+	struct tipc_nl_msg msg;
+	struct tipc_link *link;
+	struct tipc_node *node;
+	char *name;
+	int bearer_id;
+	int err;
+
+	if (!info->attrs[TIPC_NLA_LINK_NAME])
+		return -EINVAL;
+
+	name = nla_data(info->attrs[TIPC_NLA_LINK_NAME]);
+	node = tipc_link_find_owner(name, &bearer_id);
+	if (!node)
+		return -EINVAL;
+
+	ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!ans_skb)
+		return -ENOMEM;
+
+	msg.skb = ans_skb;
+	msg.portid = info->snd_portid;
+	msg.seq = info->snd_seq;
+
+	tipc_node_lock(node);
+	link = node->links[bearer_id];
+	if (!link) {
+		err = -EINVAL;
+		goto err_out;
+	}
+
+	err = __tipc_nl_add_link(&msg, link);
+	if (err)
+		goto err_out;
+
+	tipc_node_unlock(node);
+
+	return genlmsg_reply(ans_skb, info);
+
+err_out:
+	tipc_node_unlock(node);
+	nlmsg_free(ans_skb);
+
+	return err;
+}
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 4338294..8e3542a 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -240,6 +240,8 @@ void tipc_link_set_queue_limits(struct tipc_link *l_ptr, u32 window);
 void tipc_link_retransmit(struct tipc_link *l_ptr,
 			  struct sk_buff *start, u32 retransmits);
 
+int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb);
+int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info);
 int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]);
 
 /*
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 52973ce..5ecd0d1 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -38,6 +38,7 @@
 #include "config.h"
 #include "socket.h"
 #include "bearer.h"
+#include "link.h"
 #include <net/genetlink.h>
 
 static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
@@ -74,6 +75,7 @@ static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = {
 	[TIPC_NLA_UNSPEC]	= { .type = NLA_UNSPEC, },
 	[TIPC_NLA_BEARER]	= { .type = NLA_NESTED, },
 	[TIPC_NLA_SOCK]		= { .type = NLA_NESTED, },
+	[TIPC_NLA_LINK]		= { .type = NLA_NESTED, },
 };
 
 struct genl_family tipc_genl_family = {
@@ -115,6 +117,12 @@ static const struct genl_ops tipc_genl_ops[] = {
 		.cmd	= TIPC_NL_SOCK_GET,
 		.dumpit	= tipc_nl_sk_dump,
 		.policy = tipc_nl_policy,
+	},
+	{
+		.cmd	= TIPC_NL_LINK_GET,
+		.doit   = tipc_nl_link_get,
+		.dumpit	= tipc_nl_link_dump,
+		.policy = tipc_nl_policy,
 	}
 };
 
-- 
1.7.10.4


------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next 06/14] tipc: add link set to new netlink api
  2014-09-11  8:29 [PATCH net-next 00/14] tipc: new netlink API richard.alpe
                   ` (4 preceding siblings ...)
  2014-09-11  8:29 ` [PATCH net-next 05/14] tipc: add link get/dump " richard.alpe
@ 2014-09-11  8:29 ` richard.alpe
  2014-09-11  8:29 ` [PATCH net-next 07/14] tipc: add link stat reset " richard.alpe
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: richard.alpe @ 2014-09-11  8:29 UTC (permalink / raw)
  To: netdev; +Cc: tipc-discussion

From: Richard Alpe <richard.alpe@ericsson.com>

Add TIPC_NL_LINK_SET to the new tipc netlink API.

This command can set one or more link properties for a particular
link.

Netlink logical layout of link set message:
-> link
    -> name
    -> properties
        [ -> tolerance ]
        [ -> priority ]
        [ -> window ]

Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
---
 include/uapi/linux/tipc_config.h |    1 +
 net/tipc/link.c                  |   73 ++++++++++++++++++++++++++++++++++++++
 net/tipc/link.h                  |    1 +
 net/tipc/netlink.c               |    5 +++
 4 files changed, 80 insertions(+)

diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h
index 9c51151..3b0c0f0 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -56,6 +56,7 @@ enum {
 	TIPC_NL_BEARER_SET,
 	TIPC_NL_SOCK_GET,
 	TIPC_NL_LINK_GET,
+	TIPC_NL_LINK_SET,
 
 	__TIPC_NL_CMD_MAX,
 	TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
diff --git a/net/tipc/link.c b/net/tipc/link.c
index e0aaca4..6d0c1fa 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -2435,6 +2435,79 @@ int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[])
 	return 0;
 }
 
+int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info)
+{
+	int err;
+	int res = 0;
+	int bearer_id;
+	char *name;
+	struct tipc_link *link;
+	struct tipc_node *node;
+	struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1];
+
+	if (!info->attrs[TIPC_NLA_LINK])
+		return -EINVAL;
+
+	err = nla_parse_nested(attrs, TIPC_NLA_LINK_MAX,
+			       info->attrs[TIPC_NLA_LINK],
+			       tipc_nl_link_policy);
+	if (err)
+		return err;
+
+	if (!attrs[TIPC_NLA_LINK_NAME])
+		return -EINVAL;
+
+	name = nla_data(attrs[TIPC_NLA_LINK_NAME]);
+
+	node = tipc_link_find_owner(name, &bearer_id);
+	if (!node)
+		return -EINVAL;
+
+	tipc_node_lock(node);
+
+	link = node->links[bearer_id];
+	if (!link) {
+		res = -EINVAL;
+		goto out;
+	}
+
+	if (attrs[TIPC_NLA_LINK_PROP]) {
+		struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
+
+		err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_LINK_PROP],
+					      props);
+		if (err) {
+			res = err;
+			goto out;
+		}
+
+		if (props[TIPC_NLA_PROP_TOL]) {
+			u32 tol;
+
+			tol = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
+			link_set_supervision_props(link, tol);
+			tipc_link_proto_xmit(link, STATE_MSG, 0, 0, tol, 0, 0);
+		}
+		if (props[TIPC_NLA_PROP_PRIO]) {
+			u32 prio;
+
+			prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
+			link->priority = prio;
+			tipc_link_proto_xmit(link, STATE_MSG, 0, 0, 0, prio, 0);
+		}
+		if (props[TIPC_NLA_PROP_WIN]) {
+			u32 win;
+
+			win = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
+			tipc_link_set_queue_limits(link, win);
+		}
+	}
+
+out:
+	tipc_node_unlock(node);
+
+	return res;
+}
 int __tipc_nl_add_stats(struct sk_buff *skb, struct tipc_stats *s)
 {
 	int i;
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 8e3542a..3738ba1 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -242,6 +242,7 @@ void tipc_link_retransmit(struct tipc_link *l_ptr,
 
 int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb);
 int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info);
+int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info);
 int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]);
 
 /*
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 5ecd0d1..745a323 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -123,6 +123,11 @@ static const struct genl_ops tipc_genl_ops[] = {
 		.doit   = tipc_nl_link_get,
 		.dumpit	= tipc_nl_link_dump,
 		.policy = tipc_nl_policy,
+	},
+	{
+		.cmd	= TIPC_NL_LINK_SET,
+		.doit	= tipc_nl_link_set,
+		.policy = tipc_nl_policy,
 	}
 };
 
-- 
1.7.10.4


------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next 07/14] tipc: add link stat reset to new netlink api
  2014-09-11  8:29 [PATCH net-next 00/14] tipc: new netlink API richard.alpe
                   ` (5 preceding siblings ...)
  2014-09-11  8:29 ` [PATCH net-next 06/14] tipc: add link set " richard.alpe
@ 2014-09-11  8:29 ` richard.alpe
  2014-09-11  8:29 ` [PATCH net-next 08/14] tipc: add media get/dump " richard.alpe
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: richard.alpe @ 2014-09-11  8:29 UTC (permalink / raw)
  To: netdev; +Cc: tipc-discussion

From: Richard Alpe <richard.alpe@ericsson.com>

Add TIPC_NL_LINK_RESET_STATS command to the new netlink API.

This command resets the link statistics for a particular link.

Netlink logical layout of link reset message:
-> link
    -> name

Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
---
 include/uapi/linux/tipc_config.h |    1 +
 net/tipc/link.c                  |   49 ++++++++++++++++++++++++++++++++++++++
 net/tipc/link.h                  |    1 +
 net/tipc/netlink.c               |    5 ++++
 4 files changed, 56 insertions(+)

diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h
index 3b0c0f0..b5bedf1 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -57,6 +57,7 @@ enum {
 	TIPC_NL_SOCK_GET,
 	TIPC_NL_LINK_GET,
 	TIPC_NL_LINK_SET,
+	TIPC_NL_LINK_RESET_STATS,
 
 	__TIPC_NL_CMD_MAX,
 	TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 6d0c1fa..2195197 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -2774,3 +2774,52 @@ err_out:
 
 	return err;
 }
+
+int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info)
+{
+	int err;
+	char *link_name;
+	unsigned int bearer_id;
+	struct tipc_link *link;
+	struct tipc_node *node;
+	struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1];
+
+	if (!info->attrs[TIPC_NLA_LINK])
+		return -EINVAL;
+
+	err = nla_parse_nested(attrs, TIPC_NLA_LINK_MAX,
+			       info->attrs[TIPC_NLA_LINK],
+			       tipc_nl_link_policy);
+	if (err)
+		return err;
+
+	if (!attrs[TIPC_NLA_LINK_NAME])
+		return -EINVAL;
+
+	link_name = nla_data(attrs[TIPC_NLA_LINK_NAME]);
+
+	if (strcmp(link_name, tipc_bclink_name) == 0) {
+		err = tipc_bclink_reset_stats();
+		if (err)
+			return err;
+		return 0;
+	}
+
+	node = tipc_link_find_owner(link_name, &bearer_id);
+	if (!node)
+		return -EINVAL;
+
+	tipc_node_lock(node);
+
+	link = node->links[bearer_id];
+	if (!link) {
+		tipc_node_unlock(node);
+		return -EINVAL;
+	}
+
+	link_reset_statistics(link);
+
+	tipc_node_unlock(node);
+
+	return 0;
+}
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 3738ba1..f463e7b 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -243,6 +243,7 @@ void tipc_link_retransmit(struct tipc_link *l_ptr,
 int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb);
 int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info);
 int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info);
+int tipc_nl_link_reset_stats(struct sk_buff *skb, struct genl_info *info);
 int tipc_nl_parse_link_prop(struct nlattr *prop, struct nlattr *props[]);
 
 /*
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 745a323..de51267 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -128,6 +128,11 @@ static const struct genl_ops tipc_genl_ops[] = {
 		.cmd	= TIPC_NL_LINK_SET,
 		.doit	= tipc_nl_link_set,
 		.policy = tipc_nl_policy,
+	},
+	{
+		.cmd	= TIPC_NL_LINK_RESET_STATS,
+		.doit   = tipc_nl_link_reset_stats,
+		.policy = tipc_nl_policy,
 	}
 };
 
-- 
1.7.10.4


------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next 08/14] tipc: add media get/dump to new netlink api
  2014-09-11  8:29 [PATCH net-next 00/14] tipc: new netlink API richard.alpe
                   ` (6 preceding siblings ...)
  2014-09-11  8:29 ` [PATCH net-next 07/14] tipc: add link stat reset " richard.alpe
@ 2014-09-11  8:29 ` richard.alpe
  2014-09-11  8:29 ` [PATCH net-next 09/14] tipc: add media set " richard.alpe
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: richard.alpe @ 2014-09-11  8:29 UTC (permalink / raw)
  To: netdev; +Cc: tipc-discussion

From: Richard Alpe <richard.alpe@ericsson.com>

Add TIPC_NL_MEDIA_GET command to the new tipc netlink API.

This command supports dumping all information about all defined
media as well as getting all information about a specific media.

The information about a media includes name and link properties.

Netlink logical layout of media get response message:
-> media
    -> name
    -> link properties
        -> tolerance
        -> priority
        -> window

Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
---
 include/uapi/linux/tipc_config.h |   12 ++++
 net/tipc/bearer.c                |  125 ++++++++++++++++++++++++++++++++++++++
 net/tipc/bearer.h                |    3 +
 net/tipc/netlink.c               |    7 +++
 4 files changed, 147 insertions(+)

diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h
index b5bedf1..33b5171 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -58,6 +58,7 @@ enum {
 	TIPC_NL_LINK_GET,
 	TIPC_NL_LINK_SET,
 	TIPC_NL_LINK_RESET_STATS,
+	TIPC_NL_MEDIA_GET,
 
 	__TIPC_NL_CMD_MAX,
 	TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
@@ -69,6 +70,7 @@ enum {
 	TIPC_NLA_BEARER,		/* nest */
 	TIPC_NLA_SOCK,			/* nest */
 	TIPC_NLA_LINK,			/* nest */
+	TIPC_NLA_MEDIA,			/* nest */
 
 	__TIPC_NLA_MAX,
 	TIPC_NLA_MAX = __TIPC_NLA_MAX - 1
@@ -114,6 +116,16 @@ enum {
 	TIPC_NLA_LINK_MAX = __TIPC_NLA_LINK_MAX - 1
 };
 
+/* Media info */
+enum {
+	TIPC_NLA_MEDIA_UNSPEC,
+	TIPC_NLA_MEDIA_NAME,		/* string */
+	TIPC_NLA_MEDIA_PROP,		/* nest */
+
+	__TIPC_NLA_MEDIA_MAX,
+	TIPC_NLA_MEDIA_MAX = __TIPC_NLA_MEDIA_MAX - 1
+};
+
 /* Nest, publication info */
 enum {
 	TIPC_NLA_PUBL_UNSPEC,
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 906e644..ad33e44 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -61,6 +61,12 @@ tipc_nl_bearer_policy[TIPC_NLA_BEARER_MAX + 1]	= {
 	[TIPC_NLA_BEARER_DOMAIN]		= { .type = NLA_U32 }
 };
 
+static const struct nla_policy tipc_nl_media_policy[TIPC_NLA_MEDIA_MAX + 1] = {
+	[TIPC_NLA_MEDIA_UNSPEC]		= { .type = NLA_UNSPEC },
+	[TIPC_NLA_MEDIA_NAME]		= { .type = NLA_STRING },
+	[TIPC_NLA_MEDIA_PROP]		= { .type = NLA_NESTED }
+};
+
 struct tipc_bearer __rcu *bearer_list[MAX_BEARERS + 1];
 
 static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down);
@@ -898,3 +904,122 @@ int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info)
 
 	return 0;
 }
+
+int __tipc_nl_add_media(struct tipc_nl_msg *msg, struct tipc_media *media)
+{
+	void *hdr;
+	struct nlattr *attrs;
+	struct nlattr *prop;
+
+	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
+			  NLM_F_MULTI, TIPC_NL_MEDIA_GET);
+	if (!hdr)
+		return -EMSGSIZE;
+
+	attrs = nla_nest_start(msg->skb, TIPC_NLA_MEDIA);
+	if (!attrs)
+		goto msg_full;
+
+	if (nla_put_string(msg->skb, TIPC_NLA_MEDIA_NAME, media->name))
+		goto attr_msg_full;
+
+	prop = nla_nest_start(msg->skb, TIPC_NLA_MEDIA_PROP);
+	if (!prop)
+		goto prop_msg_full;
+	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, media->priority))
+		goto prop_msg_full;
+	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, media->tolerance))
+		goto prop_msg_full;
+	if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, media->window))
+		goto prop_msg_full;
+
+	nla_nest_end(msg->skb, prop);
+	nla_nest_end(msg->skb, attrs);
+	genlmsg_end(msg->skb, hdr);
+
+	return 0;
+
+prop_msg_full:
+	nla_nest_cancel(msg->skb, prop);
+attr_msg_full:
+	nla_nest_cancel(msg->skb, attrs);
+msg_full:
+	genlmsg_cancel(msg->skb, hdr);
+
+	return -EMSGSIZE;
+}
+
+int tipc_nl_media_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	int err;
+	int i = cb->args[0];
+	struct tipc_nl_msg msg;
+
+	if (i == MAX_MEDIA)
+		return 0;
+
+	msg.skb = skb;
+	msg.portid = NETLINK_CB(cb->skb).portid;
+	msg.seq = cb->nlh->nlmsg_seq;
+
+	rtnl_lock();
+	for (; media_info_array[i] != NULL; i++) {
+		err = __tipc_nl_add_media(&msg, media_info_array[i]);
+		if (err)
+			break;
+	}
+	rtnl_unlock();
+
+	cb->args[0] = i;
+	return skb->len;
+}
+
+int tipc_nl_media_get(struct sk_buff *skb, struct genl_info *info)
+{
+	int err;
+	char *name;
+	struct tipc_nl_msg msg;
+	struct tipc_media *media;
+	struct sk_buff *rep;
+	struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
+
+	if (!info->attrs[TIPC_NLA_MEDIA])
+		return -EINVAL;
+
+	err = nla_parse_nested(attrs, TIPC_NLA_MEDIA_MAX,
+			       info->attrs[TIPC_NLA_MEDIA],
+			       tipc_nl_media_policy);
+	if (err)
+		return err;
+
+	if (!attrs[TIPC_NLA_MEDIA_NAME])
+		return -EINVAL;
+	name = nla_data(attrs[TIPC_NLA_MEDIA_NAME]);
+
+	rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!rep)
+		return -ENOMEM;
+
+	msg.skb = rep;
+	msg.portid = info->snd_portid;
+	msg.seq = info->snd_seq;
+
+	rtnl_lock();
+	media = tipc_media_find(name);
+	if (!media) {
+		err = -EINVAL;
+		goto err_out;
+	}
+
+	err = __tipc_nl_add_media(&msg, media);
+	if (err)
+		goto err_out;
+	rtnl_unlock();
+
+	return genlmsg_reply(rep, info);
+err_out:
+	rtnl_unlock();
+	nlmsg_free(rep);
+
+	return err;
+}
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index c6cf9df..bacd225 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -184,6 +184,9 @@ int tipc_nl_bearer_dump(struct sk_buff *skb, struct netlink_callback *cb);
 int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info);
 int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info);
 
+int tipc_nl_media_dump(struct sk_buff *skb, struct netlink_callback *cb);
+int tipc_nl_media_get(struct sk_buff *skb, struct genl_info *info);
+
 int tipc_media_set_priority(const char *name, u32 new_value);
 int tipc_media_set_window(const char *name, u32 new_value);
 void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a);
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index de51267..d012857 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -76,6 +76,7 @@ static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = {
 	[TIPC_NLA_BEARER]	= { .type = NLA_NESTED, },
 	[TIPC_NLA_SOCK]		= { .type = NLA_NESTED, },
 	[TIPC_NLA_LINK]		= { .type = NLA_NESTED, },
+	[TIPC_NLA_MEDIA]	= { .type = NLA_NESTED, },
 };
 
 struct genl_family tipc_genl_family = {
@@ -133,6 +134,12 @@ static const struct genl_ops tipc_genl_ops[] = {
 		.cmd	= TIPC_NL_LINK_RESET_STATS,
 		.doit   = tipc_nl_link_reset_stats,
 		.policy = tipc_nl_policy,
+	},
+	{
+		.cmd	= TIPC_NL_MEDIA_GET,
+		.doit	= tipc_nl_media_get,
+		.dumpit	= tipc_nl_media_dump,
+		.policy = tipc_nl_policy,
 	}
 };
 
-- 
1.7.10.4


------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next 09/14] tipc: add media set to new netlink api
  2014-09-11  8:29 [PATCH net-next 00/14] tipc: new netlink API richard.alpe
                   ` (7 preceding siblings ...)
  2014-09-11  8:29 ` [PATCH net-next 08/14] tipc: add media get/dump " richard.alpe
@ 2014-09-11  8:29 ` richard.alpe
  2014-09-11  8:29 ` [PATCH net-next 10/14] tipc: add node get/dump " richard.alpe
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: richard.alpe @ 2014-09-11  8:29 UTC (permalink / raw)
  To: netdev; +Cc: tipc-discussion

From: Richard Alpe <richard.alpe@ericsson.com>

Add TIPC_NL_MEDIA_SET command to the new tipc netlink API.

This command can set one or more link properties for a particular
media.

Netlink logical layout of bearer set message:
-> media
    -> name
    -> link properties
        [ -> tolerance ]
        [ -> priority ]
        [ -> window ]

Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
---
 include/uapi/linux/tipc_config.h |    1 +
 net/tipc/bearer.c                |   47 ++++++++++++++++++++++++++++++++++++++
 net/tipc/bearer.h                |    1 +
 net/tipc/netlink.c               |    5 ++++
 4 files changed, 54 insertions(+)

diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h
index 33b5171..1bd9c8d 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -59,6 +59,7 @@ enum {
 	TIPC_NL_LINK_SET,
 	TIPC_NL_LINK_RESET_STATS,
 	TIPC_NL_MEDIA_GET,
+	TIPC_NL_MEDIA_SET,
 
 	__TIPC_NL_CMD_MAX,
 	TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index ad33e44..3e33771 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -1023,3 +1023,50 @@ err_out:
 
 	return err;
 }
+
+int tipc_nl_media_set(struct sk_buff *skb, struct genl_info *info)
+{
+	int err;
+	char *name;
+	struct tipc_media *m;
+	struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
+
+	if (!info->attrs[TIPC_NLA_MEDIA])
+		return -EINVAL;
+
+	err = nla_parse_nested(attrs, TIPC_NLA_MEDIA_MAX,
+			       info->attrs[TIPC_NLA_MEDIA],
+			       tipc_nl_media_policy);
+
+	if (!attrs[TIPC_NLA_MEDIA_NAME])
+		return -EINVAL;
+	name = nla_data(attrs[TIPC_NLA_MEDIA_NAME]);
+
+	rtnl_lock();
+	m = tipc_media_find(name);
+	if (!m) {
+		rtnl_unlock();
+		return -EINVAL;
+	}
+
+	if (attrs[TIPC_NLA_MEDIA_PROP]) {
+		struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
+
+		err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_MEDIA_PROP],
+					      props);
+		if (err) {
+			rtnl_unlock();
+			return err;
+		}
+
+		if (props[TIPC_NLA_PROP_TOL])
+			m->tolerance = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
+		if (props[TIPC_NLA_PROP_PRIO])
+			m->priority = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
+		if (props[TIPC_NLA_PROP_WIN])
+			m->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
+	}
+	rtnl_unlock();
+
+	return 0;
+}
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index bacd225..b1d9052 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -186,6 +186,7 @@ int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info);
 
 int tipc_nl_media_dump(struct sk_buff *skb, struct netlink_callback *cb);
 int tipc_nl_media_get(struct sk_buff *skb, struct genl_info *info);
+int tipc_nl_media_set(struct sk_buff *skb, struct genl_info *info);
 
 int tipc_media_set_priority(const char *name, u32 new_value);
 int tipc_media_set_window(const char *name, u32 new_value);
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index d012857..2f56b05 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -140,6 +140,11 @@ static const struct genl_ops tipc_genl_ops[] = {
 		.doit	= tipc_nl_media_get,
 		.dumpit	= tipc_nl_media_dump,
 		.policy = tipc_nl_policy,
+	},
+	{
+		.cmd	= TIPC_NL_MEDIA_SET,
+		.doit	= tipc_nl_media_set,
+		.policy = tipc_nl_policy,
 	}
 };
 
-- 
1.7.10.4


------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next 10/14] tipc: add node get/dump to new netlink api
  2014-09-11  8:29 [PATCH net-next 00/14] tipc: new netlink API richard.alpe
                   ` (8 preceding siblings ...)
  2014-09-11  8:29 ` [PATCH net-next 09/14] tipc: add media set " richard.alpe
@ 2014-09-11  8:29 ` richard.alpe
  2014-09-11  8:29 ` [PATCH net-next 11/14] tipc: add net dump " richard.alpe
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: richard.alpe @ 2014-09-11  8:29 UTC (permalink / raw)
  To: netdev; +Cc: tipc-discussion

From: Richard Alpe <richard.alpe@ericsson.com>

Add TIPC_NL_NODE_GET to the new tipc netlink API.

This command can dump the address and node status of all nodes in the
tipc cluster.

Netlink logical layout of returned node/address data:
-> node
    -> address
    -> up flag

Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
---
 include/uapi/linux/tipc_config.h |   12 +++++
 net/tipc/netlink.c               |    7 +++
 net/tipc/node.c                  |   96 ++++++++++++++++++++++++++++++++++++++
 net/tipc/node.h                  |    4 +-
 4 files changed, 118 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h
index 1bd9c8d..e3dfad7 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -60,6 +60,7 @@ enum {
 	TIPC_NL_LINK_RESET_STATS,
 	TIPC_NL_MEDIA_GET,
 	TIPC_NL_MEDIA_SET,
+	TIPC_NL_NODE_GET,
 
 	__TIPC_NL_CMD_MAX,
 	TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
@@ -72,6 +73,7 @@ enum {
 	TIPC_NLA_SOCK,			/* nest */
 	TIPC_NLA_LINK,			/* nest */
 	TIPC_NLA_MEDIA,			/* nest */
+	TIPC_NLA_NODE,			/* nest */
 
 	__TIPC_NLA_MAX,
 	TIPC_NLA_MAX = __TIPC_NLA_MAX - 1
@@ -127,6 +129,16 @@ enum {
 	TIPC_NLA_MEDIA_MAX = __TIPC_NLA_MEDIA_MAX - 1
 };
 
+/* Node info */
+enum {
+	TIPC_NLA_NODE_UNSPEC,
+	TIPC_NLA_NODE_ADDR,		/* u32 */
+	TIPC_NLA_NODE_UP,		/* flag */
+
+	__TIPC_NLA_NODE_MAX,
+	TIPC_NLA_NODE_MAX = __TIPC_NLA_NODE_MAX - 1
+};
+
 /* Nest, publication info */
 enum {
 	TIPC_NLA_PUBL_UNSPEC,
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 2f56b05..d42027e 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -39,6 +39,7 @@
 #include "socket.h"
 #include "bearer.h"
 #include "link.h"
+#include "node.h"
 #include <net/genetlink.h>
 
 static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
@@ -77,6 +78,7 @@ static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = {
 	[TIPC_NLA_SOCK]		= { .type = NLA_NESTED, },
 	[TIPC_NLA_LINK]		= { .type = NLA_NESTED, },
 	[TIPC_NLA_MEDIA]	= { .type = NLA_NESTED, },
+	[TIPC_NLA_NODE]		= { .type = NLA_NESTED, }
 };
 
 struct genl_family tipc_genl_family = {
@@ -145,6 +147,11 @@ static const struct genl_ops tipc_genl_ops[] = {
 		.cmd	= TIPC_NL_MEDIA_SET,
 		.doit	= tipc_nl_media_set,
 		.policy = tipc_nl_policy,
+	},
+	{
+		.cmd	= TIPC_NL_NODE_GET,
+		.dumpit	= tipc_nl_node_dump,
+		.policy = tipc_nl_policy,
 	}
 };
 
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 17e6378..80ca561 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -58,6 +58,12 @@ struct tipc_sock_conn {
 	struct list_head list;
 };
 
+static const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = {
+	[TIPC_NLA_NODE_UNSPEC]		= { .type = NLA_UNSPEC },
+	[TIPC_NLA_NODE_ADDR]		= { .type = NLA_U32 },
+	[TIPC_NLA_NODE_UP]		= { .type = NLA_FLAG }
+};
+
 /*
  * A trivial power-of-two bitmask technique is used for speed, since this
  * operation is done for every incoming TIPC packet. The number of hash table
@@ -586,3 +592,93 @@ void tipc_node_unlock(struct tipc_node *node)
 	if (addr)
 		tipc_named_node_up(addr);
 }
+
+/* Caller should hold node lock for the passed node */
+int __tipc_nl_add_node(struct tipc_nl_msg *msg, struct tipc_node *node)
+{
+	void *hdr;
+	struct nlattr *attrs;
+
+	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
+			  NLM_F_MULTI, TIPC_NL_NODE_GET);
+	if (!hdr)
+		return -EMSGSIZE;
+
+	attrs = nla_nest_start(msg->skb, TIPC_NLA_NODE);
+	if (!attrs)
+		goto msg_full;
+
+	if (nla_put_u32(msg->skb, TIPC_NLA_NODE_ADDR, node->addr))
+		goto attr_msg_full;
+	if (tipc_node_is_up(node))
+		if (nla_put_flag(msg->skb, TIPC_NLA_NODE_UP))
+			goto attr_msg_full;
+
+	nla_nest_end(msg->skb, attrs);
+	genlmsg_end(msg->skb, hdr);
+
+	return 0;
+
+attr_msg_full:
+	nla_nest_cancel(msg->skb, attrs);
+msg_full:
+	genlmsg_cancel(msg->skb, hdr);
+
+	return -EMSGSIZE;
+}
+
+int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	int err;
+	int done = cb->args[0];
+	int last_addr = cb->args[1];
+	struct tipc_node *node;
+	struct tipc_nl_msg msg;
+
+	if (done)
+		return 0;
+
+	msg.skb = skb;
+	msg.portid = NETLINK_CB(cb->skb).portid;
+	msg.seq = cb->nlh->nlmsg_seq;
+
+	rcu_read_lock();
+
+	if (last_addr && !tipc_node_find(last_addr)) {
+		rcu_read_unlock();
+		/* We never set seq or call nl_dump_check_consistent() this
+		 * means that setting prev_seq here will cause the consistence
+		 * check to fail in the netlink callback handler. Resulting in
+		 * the NLMSG_DONE message having the NLM_F_DUMP_INTR flag set if
+		 * the node state changed while we released the lock.
+		 */
+		cb->prev_seq = 1;
+		return -EPIPE;
+	}
+
+	list_for_each_entry_rcu(node, &tipc_node_list, list) {
+		if (last_addr) {
+			if (node->addr == last_addr)
+				last_addr = 0;
+			else
+				continue;
+		}
+
+		tipc_node_lock(node);
+		err = __tipc_nl_add_node(&msg, node);
+		if (err) {
+			last_addr = node->addr;
+			tipc_node_unlock(node);
+			goto out;
+		}
+
+		tipc_node_unlock(node);
+	}
+	done = 1;
+out:
+	cb->args[0] = done;
+	cb->args[1] = last_addr;
+	rcu_read_unlock();
+
+	return skb->len;
+}
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 522d6f3..17c0921 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -1,7 +1,7 @@
 /*
  * net/tipc/node.h: Include file for TIPC node management routines
  *
- * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2000-2006, 2014, Ericsson AB
  * Copyright (c) 2005, 2010-2014, Wind River Systems
  * All rights reserved.
  *
@@ -139,6 +139,8 @@ void tipc_node_unlock(struct tipc_node *node);
 int tipc_node_add_conn(u32 dnode, u32 port, u32 peer_port);
 void tipc_node_remove_conn(u32 dnode, u32 port);
 
+int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb);
+
 static inline void tipc_node_lock(struct tipc_node *node)
 {
 	spin_lock_bh(&node->lock);
-- 
1.7.10.4


------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next 11/14] tipc: add net dump to new netlink api
  2014-09-11  8:29 [PATCH net-next 00/14] tipc: new netlink API richard.alpe
                   ` (9 preceding siblings ...)
  2014-09-11  8:29 ` [PATCH net-next 10/14] tipc: add node get/dump " richard.alpe
@ 2014-09-11  8:29 ` richard.alpe
  2014-09-11  8:29 ` [PATCH net-next 12/14] tipc: add net set " richard.alpe
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: richard.alpe @ 2014-09-11  8:29 UTC (permalink / raw)
  To: netdev; +Cc: tipc-discussion

From: Richard Alpe <richard.alpe@ericsson.com>

Add TIPC_NL_NET_GET command to the new tipc netlink API.

This command dumps the network id of the node.

Netlink logical layout of returned network data:
-> net
    -> id

Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
---
 include/uapi/linux/tipc_config.h |   11 +++++++
 net/tipc/net.c                   |   59 ++++++++++++++++++++++++++++++++++++++
 net/tipc/net.h                   |    7 ++++-
 net/tipc/netlink.c               |    9 +++++-
 4 files changed, 84 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h
index e3dfad7..68a58b0 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -61,6 +61,7 @@ enum {
 	TIPC_NL_MEDIA_GET,
 	TIPC_NL_MEDIA_SET,
 	TIPC_NL_NODE_GET,
+	TIPC_NL_NET_GET,
 
 	__TIPC_NL_CMD_MAX,
 	TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
@@ -74,6 +75,7 @@ enum {
 	TIPC_NLA_LINK,			/* nest */
 	TIPC_NLA_MEDIA,			/* nest */
 	TIPC_NLA_NODE,			/* nest */
+	TIPC_NLA_NET,			/* nest */
 
 	__TIPC_NLA_MAX,
 	TIPC_NLA_MAX = __TIPC_NLA_MAX - 1
@@ -139,6 +141,15 @@ enum {
 	TIPC_NLA_NODE_MAX = __TIPC_NLA_NODE_MAX - 1
 };
 
+/* Net info */
+enum {
+	TIPC_NLA_NET_UNSPEC,
+	TIPC_NLA_NET_ID,		/* u32 */
+
+	__TIPC_NLA_NET_MAX,
+	TIPC_NLA_NET_MAX = __TIPC_NLA_NET_MAX - 1
+};
+
 /* Nest, publication info */
 enum {
 	TIPC_NLA_PUBL_UNSPEC,
diff --git a/net/tipc/net.c b/net/tipc/net.c
index 93b9944..b5435a6 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -42,6 +42,11 @@
 #include "node.h"
 #include "config.h"
 
+static const struct nla_policy tipc_nl_net_policy[TIPC_NLA_NET_MAX + 1] = {
+	[TIPC_NLA_NET_UNSPEC]	= { .type = NLA_UNSPEC },
+	[TIPC_NLA_NET_ID]	= { .type = NLA_U32 }
+};
+
 /*
  * The TIPC locking policy is designed to ensure a very fine locking
  * granularity, permitting complete parallel access to individual
@@ -138,3 +143,57 @@ void tipc_net_stop(void)
 
 	pr_info("Left network mode\n");
 }
+
+static int __tipc_nl_add_net(struct tipc_nl_msg *msg)
+{
+	void *hdr;
+	struct nlattr *attrs;
+
+	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
+			  NLM_F_MULTI, TIPC_NL_NET_GET);
+	if (!hdr)
+		return -EMSGSIZE;
+
+	attrs = nla_nest_start(msg->skb, TIPC_NLA_NET);
+	if (!attrs)
+		goto msg_full;
+
+	if (nla_put_u32(msg->skb, TIPC_NLA_NET_ID, tipc_net_id))
+		goto attr_msg_full;
+
+	nla_nest_end(msg->skb, attrs);
+	genlmsg_end(msg->skb, hdr);
+
+	return 0;
+
+attr_msg_full:
+	nla_nest_cancel(msg->skb, attrs);
+msg_full:
+	genlmsg_cancel(msg->skb, hdr);
+
+	return -EMSGSIZE;
+}
+
+int tipc_nl_net_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	int err;
+	int done = cb->args[0];
+	struct tipc_nl_msg msg;
+
+	if (done)
+		return 0;
+
+	msg.skb = skb;
+	msg.portid = NETLINK_CB(cb->skb).portid;
+	msg.seq = cb->nlh->nlmsg_seq;
+
+	err = __tipc_nl_add_net(&msg);
+	if (err)
+		goto out;
+
+	done = 1;
+out:
+	cb->args[0] = done;
+
+	return skb->len;
+}
diff --git a/net/tipc/net.h b/net/tipc/net.h
index 59ef338..60dc22f 100644
--- a/net/tipc/net.h
+++ b/net/tipc/net.h
@@ -1,7 +1,7 @@
 /*
  * net/tipc/net.h: Include file for TIPC network routing code
  *
- * Copyright (c) 1995-2006, Ericsson AB
+ * Copyright (c) 1995-2006, 2014, Ericsson AB
  * Copyright (c) 2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
@@ -37,7 +37,12 @@
 #ifndef _TIPC_NET_H
 #define _TIPC_NET_H
 
+#include <net/genetlink.h>
+
 int tipc_net_start(u32 addr);
+
 void tipc_net_stop(void);
 
+int tipc_nl_net_dump(struct sk_buff *skb, struct netlink_callback *cb);
+
 #endif
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index d42027e..3730876 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -40,6 +40,7 @@
 #include "bearer.h"
 #include "link.h"
 #include "node.h"
+#include "net.h"
 #include <net/genetlink.h>
 
 static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
@@ -78,7 +79,8 @@ static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = {
 	[TIPC_NLA_SOCK]		= { .type = NLA_NESTED, },
 	[TIPC_NLA_LINK]		= { .type = NLA_NESTED, },
 	[TIPC_NLA_MEDIA]	= { .type = NLA_NESTED, },
-	[TIPC_NLA_NODE]		= { .type = NLA_NESTED, }
+	[TIPC_NLA_NODE]		= { .type = NLA_NESTED, },
+	[TIPC_NLA_NET]		= { .type = NLA_NESTED, }
 };
 
 struct genl_family tipc_genl_family = {
@@ -152,6 +154,11 @@ static const struct genl_ops tipc_genl_ops[] = {
 		.cmd	= TIPC_NL_NODE_GET,
 		.dumpit	= tipc_nl_node_dump,
 		.policy = tipc_nl_policy,
+	},
+	{
+		.cmd	= TIPC_NL_NET_GET,
+		.dumpit	= tipc_nl_net_dump,
+		.policy = tipc_nl_policy,
 	}
 };
 
-- 
1.7.10.4


------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next 12/14] tipc: add net set to new netlink api
  2014-09-11  8:29 [PATCH net-next 00/14] tipc: new netlink API richard.alpe
                   ` (10 preceding siblings ...)
  2014-09-11  8:29 ` [PATCH net-next 11/14] tipc: add net dump " richard.alpe
@ 2014-09-11  8:29 ` richard.alpe
  2014-09-11  8:29 ` [PATCH net-next 13/14] tipc: add name table dump " richard.alpe
  2014-09-11  8:29 ` [PATCH net-next 14/14] tipc: remove old ASCII netlink API richard.alpe
  13 siblings, 0 replies; 24+ messages in thread
From: richard.alpe @ 2014-09-11  8:29 UTC (permalink / raw)
  To: netdev; +Cc: tipc-discussion

From: Richard Alpe <richard.alpe@ericsson.com>

Add TIPC_NL_NET_SET command to the new tipc netlink API.

This command can set the network id and network (tipc) address.

Netlink logical layout of network set message:
-> net
     [ -> id ]
     [ -> address ]

Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
---
 include/uapi/linux/tipc_config.h |    2 ++
 net/tipc/net.c                   |   47 ++++++++++++++++++++++++++++++++++++++
 net/tipc/net.h                   |    1 +
 net/tipc/netlink.c               |    5 ++++
 4 files changed, 55 insertions(+)

diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h
index 68a58b0..6fdb819 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -62,6 +62,7 @@ enum {
 	TIPC_NL_MEDIA_SET,
 	TIPC_NL_NODE_GET,
 	TIPC_NL_NET_GET,
+	TIPC_NL_NET_SET,
 
 	__TIPC_NL_CMD_MAX,
 	TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
@@ -145,6 +146,7 @@ enum {
 enum {
 	TIPC_NLA_NET_UNSPEC,
 	TIPC_NLA_NET_ID,		/* u32 */
+	TIPC_NLA_NET_ADDR,		/* u32 */
 
 	__TIPC_NLA_NET_MAX,
 	TIPC_NLA_NET_MAX = __TIPC_NLA_NET_MAX - 1
diff --git a/net/tipc/net.c b/net/tipc/net.c
index b5435a6..fdbbedf 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -197,3 +197,50 @@ out:
 
 	return skb->len;
 }
+
+int tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info)
+{
+	int err;
+	struct nlattr *attrs[TIPC_NLA_NET_MAX + 1];
+
+	if (!info->attrs[TIPC_NLA_NET])
+		return -EINVAL;
+
+	err = nla_parse_nested(attrs, TIPC_NLA_NET_MAX,
+			       info->attrs[TIPC_NLA_NET],
+			       tipc_nl_net_policy);
+	if (err)
+		return err;
+
+	if (attrs[TIPC_NLA_NET_ID]) {
+		u32 val;
+
+		/* Can't change net id once TIPC has joined a network */
+		if (tipc_own_addr)
+			return -EPERM;
+
+		val = nla_get_u32(attrs[TIPC_NLA_NET_ID]);
+		if (val < 1 || val > 9999)
+			return -EINVAL;
+
+		tipc_net_id = val;
+	}
+
+	if (attrs[TIPC_NLA_NET_ADDR]) {
+		u32 addr;
+
+		/* Can't change net addr once TIPC has joined a network */
+		if (tipc_own_addr)
+			return -EPERM;
+
+		addr = nla_get_u32(attrs[TIPC_NLA_NET_ADDR]);
+		if (!tipc_addr_node_valid(addr))
+			return -EINVAL;
+
+		rtnl_lock();
+		tipc_net_start(addr);
+		rtnl_unlock();
+	}
+
+	return 0;
+}
diff --git a/net/tipc/net.h b/net/tipc/net.h
index 60dc22f..a81c1b9 100644
--- a/net/tipc/net.h
+++ b/net/tipc/net.h
@@ -44,5 +44,6 @@ int tipc_net_start(u32 addr);
 void tipc_net_stop(void);
 
 int tipc_nl_net_dump(struct sk_buff *skb, struct netlink_callback *cb);
+int tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info);
 
 #endif
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 3730876..7803aa9 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -159,6 +159,11 @@ static const struct genl_ops tipc_genl_ops[] = {
 		.cmd	= TIPC_NL_NET_GET,
 		.dumpit	= tipc_nl_net_dump,
 		.policy = tipc_nl_policy,
+	},
+	{
+		.cmd	= TIPC_NL_NET_SET,
+		.doit	= tipc_nl_net_set,
+		.policy = tipc_nl_policy,
 	}
 };
 
-- 
1.7.10.4


------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next 13/14] tipc: add name table dump to new netlink api
  2014-09-11  8:29 [PATCH net-next 00/14] tipc: new netlink API richard.alpe
                   ` (11 preceding siblings ...)
  2014-09-11  8:29 ` [PATCH net-next 12/14] tipc: add net set " richard.alpe
@ 2014-09-11  8:29 ` richard.alpe
  2014-09-11  8:29 ` [PATCH net-next 14/14] tipc: remove old ASCII netlink API richard.alpe
  13 siblings, 0 replies; 24+ messages in thread
From: richard.alpe @ 2014-09-11  8:29 UTC (permalink / raw)
  To: netdev; +Cc: tipc-discussion

From: Richard Alpe <richard.alpe@ericsson.com>

Add TIPC_NL_NAME_TABLE_GET command to the new tipc netlink API.

This command supports dumping the name table of all nodes.

Netlink logical layout of name table response message:
-> name table
    -> publication
        -> type
        -> lower
        -> upper
        -> scope
        -> node
        -> ref
        -> key

Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
---
 include/uapi/linux/tipc_config.h |   11 +++
 net/tipc/name_table.c            |  190 +++++++++++++++++++++++++++++++++++++-
 net/tipc/name_table.h            |    4 +-
 net/tipc/netlink.c               |    9 +-
 4 files changed, 211 insertions(+), 3 deletions(-)

diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h
index 6fdb819..3d1a4ab 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -63,6 +63,7 @@ enum {
 	TIPC_NL_NODE_GET,
 	TIPC_NL_NET_GET,
 	TIPC_NL_NET_SET,
+	TIPC_NL_NAME_TABLE_GET,
 
 	__TIPC_NL_CMD_MAX,
 	TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
@@ -77,6 +78,7 @@ enum {
 	TIPC_NLA_MEDIA,			/* nest */
 	TIPC_NLA_NODE,			/* nest */
 	TIPC_NLA_NET,			/* nest */
+	TIPC_NLA_NAME_TABLE,		/* nest */
 
 	__TIPC_NLA_MAX,
 	TIPC_NLA_MAX = __TIPC_NLA_MAX - 1
@@ -152,6 +154,15 @@ enum {
 	TIPC_NLA_NET_MAX = __TIPC_NLA_NET_MAX - 1
 };
 
+/* Name table info */
+enum {
+	TIPC_NLA_NAME_TABLE_UNSPEC,
+	TIPC_NLA_NAME_TABLE_PUBL,	/* nest */
+
+	__TIPC_NLA_NAME_TABLE_MAX,
+	TIPC_NLA_NAME_TABLE_MAX = __TIPC_NLA_NAME_TABLE_MAX - 1
+};
+
 /* Nest, publication info */
 enum {
 	TIPC_NLA_PUBL_UNSPEC,
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index 3a6a0a7..7d69229 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -1,7 +1,7 @@
 /*
  * net/tipc/name_table.c: TIPC name table code
  *
- * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2000-2006, 2014, Ericsson AB
  * Copyright (c) 2004-2008, 2010-2011, Wind River Systems
  * All rights reserved.
  *
@@ -42,6 +42,12 @@
 
 #define TIPC_NAMETBL_SIZE 1024		/* must be a power of 2 */
 
+static const struct nla_policy
+tipc_nl_name_table_policy[TIPC_NLA_NAME_TABLE_MAX + 1] = {
+	[TIPC_NLA_NAME_TABLE_UNSPEC]	= { .type = NLA_UNSPEC },
+	[TIPC_NLA_NAME_TABLE_PUBL]	= { .type = NLA_NESTED }
+};
+
 /**
  * struct name_info - name sequence publication info
  * @node_list: circular list of publications made by own node
@@ -995,3 +1001,185 @@ void tipc_nametbl_stop(void)
 	table.types = NULL;
 	write_unlock_bh(&tipc_nametbl_lock);
 }
+
+int __tipc_nl_add_nametable_publ(struct tipc_nl_msg *msg, struct name_seq *seq,
+				 struct sub_seq *sseq, u32 *last_publ)
+{
+	void *hdr;
+	struct nlattr *attrs;
+	struct nlattr *publ;
+	struct publication *p;
+
+	if (*last_publ) {
+		list_for_each_entry(p, &sseq->info->zone_list, zone_list)
+			if (p->key == *last_publ)
+				break;
+		if (p->key != *last_publ)
+			return -EPIPE;
+	} else {
+		p = list_first_entry(&sseq->info->zone_list, struct publication,
+				     zone_list);
+	}
+
+	list_for_each_entry_from(p, &sseq->info->zone_list, zone_list) {
+		*last_publ = p->key;
+
+		hdr = genlmsg_put(msg->skb, msg->portid, msg->seq,
+				  &tipc_genl_family, NLM_F_MULTI,
+				  TIPC_NL_NAME_TABLE_GET);
+		if (!hdr)
+			return -EMSGSIZE;
+
+		attrs = nla_nest_start(msg->skb, TIPC_NLA_NAME_TABLE);
+		if (!attrs)
+			goto msg_full;
+
+		publ = nla_nest_start(msg->skb, TIPC_NLA_NAME_TABLE_PUBL);
+		if (!publ)
+			goto attr_msg_full;
+
+		if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_TYPE, seq->type))
+			goto publ_msg_full;
+		if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_LOWER, sseq->lower))
+			goto publ_msg_full;
+		if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_UPPER, sseq->upper))
+			goto publ_msg_full;
+		if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_SCOPE, p->scope))
+			goto publ_msg_full;
+		if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_NODE, p->node))
+			goto publ_msg_full;
+		if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_REF, p->ref))
+			goto publ_msg_full;
+		if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_KEY, p->key))
+			goto publ_msg_full;
+
+		nla_nest_end(msg->skb, publ);
+		nla_nest_end(msg->skb, attrs);
+		genlmsg_end(msg->skb, hdr);
+	}
+	*last_publ = 0;
+
+	return 0;
+
+publ_msg_full:
+	nla_nest_cancel(msg->skb, publ);
+attr_msg_full:
+	nla_nest_cancel(msg->skb, attrs);
+msg_full:
+	genlmsg_cancel(msg->skb, hdr);
+
+	return -EMSGSIZE;
+}
+
+int __tipc_nl_subseq_list(struct tipc_nl_msg *msg, struct name_seq *seq,
+			  u32 *last_lower, u32 *last_publ)
+{
+	struct sub_seq *sseq;
+	struct sub_seq *sseq_start;
+	int err;
+
+	if (*last_lower) {
+		sseq_start = nameseq_find_subseq(seq, *last_lower);
+		if (!sseq_start)
+			return -EPIPE;
+	} else {
+		sseq_start = seq->sseqs;
+	}
+
+	for (sseq = sseq_start; sseq != &seq->sseqs[seq->first_free]; sseq++) {
+		err = __tipc_nl_add_nametable_publ(msg, seq, sseq, last_publ);
+		if (err) {
+			*last_lower = sseq->lower;
+			return err;
+		}
+	}
+	*last_lower = 0;
+
+	return 0;
+}
+
+int __tipc_nl_seq_list(struct tipc_nl_msg *msg, u32 *last_type, u32 *last_lower,
+		       u32 *last_publ)
+{
+	struct hlist_head *seq_head;
+	struct name_seq *seq;
+	int err;
+	int i;
+
+	if (*last_type)
+		i = hash(*last_type);
+	else
+		i = 0;
+
+	for (; i < TIPC_NAMETBL_SIZE; i++) {
+		seq_head = &table.types[i];
+
+		if (*last_type) {
+			seq = nametbl_find_seq(*last_type);
+			if (!seq)
+				return -EPIPE;
+		} else {
+			seq = hlist_entry_safe((seq_head)->first,
+					       struct name_seq, ns_list);
+			if (!seq)
+				continue;
+		}
+
+		hlist_for_each_entry_from(seq, ns_list) {
+			spin_lock_bh(&seq->lock);
+
+			err = __tipc_nl_subseq_list(msg, seq, last_lower,
+						    last_publ);
+
+			if (err) {
+				*last_type = seq->type;
+				spin_unlock_bh(&seq->lock);
+				return err;
+			}
+			spin_unlock_bh(&seq->lock);
+		}
+		*last_type = 0;
+	}
+	return 0;
+}
+
+int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	int err;
+	int done = cb->args[3];
+	u32 last_type = cb->args[0];
+	u32 last_lower = cb->args[1];
+	u32 last_publ = cb->args[2];
+	struct tipc_nl_msg msg;
+
+	if (done)
+		return 0;
+
+	msg.skb = skb;
+	msg.portid = NETLINK_CB(cb->skb).portid;
+	msg.seq = cb->nlh->nlmsg_seq;
+
+	read_lock_bh(&tipc_nametbl_lock);
+
+	err = __tipc_nl_seq_list(&msg, &last_type, &last_lower, &last_publ);
+	if (!err) {
+		done = 1;
+	} else if (err != -EMSGSIZE) {
+		/* We never set seq or call nl_dump_check_consistent() this
+		 * means that setting prev_seq here will cause the consistence
+		 * check to fail in the netlink callback handler. Resulting in
+		 * the NLMSG_DONE message having the NLM_F_DUMP_INTR flag set if
+		 * we got an error.
+		 */
+		cb->prev_seq = 1;
+	}
+
+	read_unlock_bh(&tipc_nametbl_lock);
+
+	cb->args[0] = last_type;
+	cb->args[1] = last_lower;
+	cb->args[2] = last_publ;
+	cb->args[3] = done;
+
+	return skb->len;
+}
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h
index f02f48b..b38ebec 100644
--- a/net/tipc/name_table.h
+++ b/net/tipc/name_table.h
@@ -1,7 +1,7 @@
 /*
  * net/tipc/name_table.h: Include file for TIPC name table code
  *
- * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2000-2006, 2014, Ericsson AB
  * Copyright (c) 2004-2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
@@ -84,6 +84,8 @@ struct publication {
 
 extern rwlock_t tipc_nametbl_lock;
 
+int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb);
+
 struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space);
 u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node);
 int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 7803aa9..11a2fd8 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -37,6 +37,7 @@
 #include "core.h"
 #include "config.h"
 #include "socket.h"
+#include "name_table.h"
 #include "bearer.h"
 #include "link.h"
 #include "node.h"
@@ -80,7 +81,8 @@ static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = {
 	[TIPC_NLA_LINK]		= { .type = NLA_NESTED, },
 	[TIPC_NLA_MEDIA]	= { .type = NLA_NESTED, },
 	[TIPC_NLA_NODE]		= { .type = NLA_NESTED, },
-	[TIPC_NLA_NET]		= { .type = NLA_NESTED, }
+	[TIPC_NLA_NET]		= { .type = NLA_NESTED, },
+	[TIPC_NLA_NAME_TABLE]	= { .type = NLA_NESTED, }
 };
 
 struct genl_family tipc_genl_family = {
@@ -164,6 +166,11 @@ static const struct genl_ops tipc_genl_ops[] = {
 		.cmd	= TIPC_NL_NET_SET,
 		.doit	= tipc_nl_net_set,
 		.policy = tipc_nl_policy,
+	},
+	{
+		.cmd	= TIPC_NL_NAME_TABLE_GET,
+		.dumpit	= tipc_nl_name_table_dump,
+		.policy = tipc_nl_policy,
 	}
 };
 
-- 
1.7.10.4


------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH net-next 14/14] tipc: remove old ASCII netlink API
  2014-09-11  8:29 [PATCH net-next 00/14] tipc: new netlink API richard.alpe
                   ` (12 preceding siblings ...)
  2014-09-11  8:29 ` [PATCH net-next 13/14] tipc: add name table dump " richard.alpe
@ 2014-09-11  8:29 ` richard.alpe
  13 siblings, 0 replies; 24+ messages in thread
From: richard.alpe @ 2014-09-11  8:29 UTC (permalink / raw)
  To: netdev; +Cc: tipc-discussion

From: Richard Alpe <richard.alpe@ericsson.com>

The API has been deprecated along with its user-space tool
"tipc-config". Users shall use the new kernel netlink API already in
place along with the new user space tool "tipc" that's part of the
tipc-utils package.

Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
---
 include/uapi/linux/tipc_config.h |  299 +--------------------------------
 net/tipc/Makefile                |    2 +-
 net/tipc/bcast.c                 |   41 -----
 net/tipc/bcast.h                 |    1 -
 net/tipc/bearer.c                |   65 --------
 net/tipc/bearer.h                |    1 -
 net/tipc/config.c                |  342 --------------------------------------
 net/tipc/config.h                |   67 --------
 net/tipc/core.c                  |    3 +-
 net/tipc/link.c                  |  311 ----------------------------------
 net/tipc/link.h                  |    7 -
 net/tipc/log.c                   |    1 -
 net/tipc/name_table.c            |  185 +--------------------
 net/tipc/name_table.h            |    1 +
 net/tipc/net.c                   |    1 -
 net/tipc/netlink.c               |   36 ----
 net/tipc/node.c                  |  113 +------------
 net/tipc/node.h                  |    2 -
 net/tipc/socket.c                |   77 ---------
 net/tipc/socket.h                |    1 -
 20 files changed, 8 insertions(+), 1548 deletions(-)
 delete mode 100644 net/tipc/config.c
 delete mode 100644 net/tipc/config.h

diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h
index 3d1a4ab..359c627 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -38,13 +38,6 @@
 #define _LINUX_TIPC_CONFIG_H_
 
 #include <linux/types.h>
-#include <linux/string.h>
-#include <linux/tipc.h>
-#include <asm/byteorder.h>
-
-#ifndef __KERNEL__
-#include <arpa/inet.h> /* for ntohs etc. */
-#endif
 
 /* Netlink commands */
 enum {
@@ -248,115 +241,6 @@ enum {
 };
 
 /*
- * Configuration
- *
- * All configuration management messaging involves sending a request message
- * to the TIPC configuration service on a node, which sends a reply message
- * back.  (In the future multi-message replies may be supported.)
- *
- * Both request and reply messages consist of a transport header and payload.
- * The transport header contains info about the desired operation;
- * the payload consists of zero or more type/length/value (TLV) items
- * which specify parameters or results for the operation.
- *
- * For many operations, the request and reply messages have a fixed number
- * of TLVs (usually zero or one); however, some reply messages may return
- * a variable number of TLVs.  A failed request is denoted by the presence
- * of an "error string" TLV in the reply message instead of the TLV(s) the
- * reply should contain if the request succeeds.
- */
-
-/*
- * Public commands:
- * May be issued by any process.
- * Accepted by own node, or by remote node only if remote management enabled.
- */
-
-#define  TIPC_CMD_NOOP              0x0000    /* tx none, rx none */
-#define  TIPC_CMD_GET_NODES         0x0001    /* tx net_addr, rx node_info(s) */
-#define  TIPC_CMD_GET_MEDIA_NAMES   0x0002    /* tx none, rx media_name(s) */
-#define  TIPC_CMD_GET_BEARER_NAMES  0x0003    /* tx none, rx bearer_name(s) */
-#define  TIPC_CMD_GET_LINKS         0x0004    /* tx net_addr, rx link_info(s) */
-#define  TIPC_CMD_SHOW_NAME_TABLE   0x0005    /* tx name_tbl_query, rx ultra_string */
-#define  TIPC_CMD_SHOW_PORTS        0x0006    /* tx none, rx ultra_string */
-#define  TIPC_CMD_SHOW_LINK_STATS   0x000B    /* tx link_name, rx ultra_string */
-#define  TIPC_CMD_SHOW_STATS        0x000F    /* tx unsigned, rx ultra_string */
-
-/*
- * Protected commands:
- * May only be issued by "network administration capable" process.
- * Accepted by own node, or by remote node only if remote management enabled
- * and this node is zone manager.
- */
-
-#define  TIPC_CMD_GET_REMOTE_MNG    0x4003    /* tx none, rx unsigned */
-#define  TIPC_CMD_GET_MAX_PORTS     0x4004    /* tx none, rx unsigned */
-#define  TIPC_CMD_GET_MAX_PUBL      0x4005    /* obsoleted */
-#define  TIPC_CMD_GET_MAX_SUBSCR    0x4006    /* obsoleted */
-#define  TIPC_CMD_GET_MAX_ZONES     0x4007    /* obsoleted */
-#define  TIPC_CMD_GET_MAX_CLUSTERS  0x4008    /* obsoleted */
-#define  TIPC_CMD_GET_MAX_NODES     0x4009    /* obsoleted */
-#define  TIPC_CMD_GET_MAX_SLAVES    0x400A    /* obsoleted */
-#define  TIPC_CMD_GET_NETID         0x400B    /* tx none, rx unsigned */
-
-#define  TIPC_CMD_ENABLE_BEARER     0x4101    /* tx bearer_config, rx none */
-#define  TIPC_CMD_DISABLE_BEARER    0x4102    /* tx bearer_name, rx none */
-#define  TIPC_CMD_SET_LINK_TOL      0x4107    /* tx link_config, rx none */
-#define  TIPC_CMD_SET_LINK_PRI      0x4108    /* tx link_config, rx none */
-#define  TIPC_CMD_SET_LINK_WINDOW   0x4109    /* tx link_config, rx none */
-#define  TIPC_CMD_SET_LOG_SIZE      0x410A    /* obsoleted */
-#define  TIPC_CMD_DUMP_LOG          0x410B    /* obsoleted */
-#define  TIPC_CMD_RESET_LINK_STATS  0x410C    /* tx link_name, rx none */
-
-/*
- * Private commands:
- * May only be issued by "network administration capable" process.
- * Accepted by own node only; cannot be used on a remote node.
- */
-
-#define  TIPC_CMD_SET_NODE_ADDR     0x8001    /* tx net_addr, rx none */
-#define  TIPC_CMD_SET_REMOTE_MNG    0x8003    /* tx unsigned, rx none */
-#define  TIPC_CMD_SET_MAX_PORTS     0x8004    /* tx unsigned, rx none */
-#define  TIPC_CMD_SET_MAX_PUBL      0x8005    /* obsoleted */
-#define  TIPC_CMD_SET_MAX_SUBSCR    0x8006    /* obsoleted */
-#define  TIPC_CMD_SET_MAX_ZONES     0x8007    /* obsoleted */
-#define  TIPC_CMD_SET_MAX_CLUSTERS  0x8008    /* obsoleted */
-#define  TIPC_CMD_SET_MAX_NODES     0x8009    /* obsoleted */
-#define  TIPC_CMD_SET_MAX_SLAVES    0x800A    /* obsoleted */
-#define  TIPC_CMD_SET_NETID         0x800B    /* tx unsigned, rx none */
-
-/*
- * Reserved commands:
- * May not be issued by any process.
- * Used internally by TIPC.
- */
-
-#define  TIPC_CMD_NOT_NET_ADMIN     0xC001    /* tx none, rx none */
-
-/*
- * TLV types defined for TIPC
- */
-
-#define TIPC_TLV_NONE		0	/* no TLV present */
-#define TIPC_TLV_VOID		1	/* empty TLV (0 data bytes)*/
-#define TIPC_TLV_UNSIGNED	2	/* 32-bit integer */
-#define TIPC_TLV_STRING		3	/* char[128] (max) */
-#define TIPC_TLV_LARGE_STRING	4	/* char[2048] (max) */
-#define TIPC_TLV_ULTRA_STRING	5	/* char[32768] (max) */
-
-#define TIPC_TLV_ERROR_STRING	16	/* char[128] containing "error code" */
-#define TIPC_TLV_NET_ADDR	17	/* 32-bit integer denoting <Z.C.N> */
-#define TIPC_TLV_MEDIA_NAME	18	/* char[TIPC_MAX_MEDIA_NAME] */
-#define TIPC_TLV_BEARER_NAME	19	/* char[TIPC_MAX_BEARER_NAME] */
-#define TIPC_TLV_LINK_NAME	20	/* char[TIPC_MAX_LINK_NAME] */
-#define TIPC_TLV_NODE_INFO	21	/* struct tipc_node_info */
-#define TIPC_TLV_LINK_INFO	22	/* struct tipc_link_info */
-#define TIPC_TLV_BEARER_CONFIG	23	/* struct tipc_bearer_config */
-#define TIPC_TLV_LINK_CONFIG	24	/* struct tipc_link_config */
-#define TIPC_TLV_NAME_TBL_QUERY	25	/* struct tipc_name_table_query */
-#define TIPC_TLV_PORT_REF	26	/* 32-bit port reference */
-
-/*
  * Link priority limits (min, default, max, media default)
  */
 
@@ -385,172 +269,17 @@ enum {
 #define TIPC_DEF_LINK_WIN 50
 #define TIPC_MAX_LINK_WIN 8191
 
-
-struct tipc_node_info {
-	__be32 addr;			/* network address of node */
-	__be32 up;			/* 0=down, 1= up */
-};
-
-struct tipc_link_info {
-	__be32 dest;			/* network address of peer node */
-	__be32 up;			/* 0=down, 1=up */
-	char str[TIPC_MAX_LINK_NAME];	/* link name */
-};
-
-struct tipc_bearer_config {
-	__be32 priority;		/* Range [1,31]. Override per link  */
-	__be32 disc_domain;		/* <Z.C.N> describing desired nodes */
-	char name[TIPC_MAX_BEARER_NAME];
-};
-
-struct tipc_link_config {
-	__be32 value;
-	char name[TIPC_MAX_LINK_NAME];
-};
-
-#define TIPC_NTQ_ALLTYPES 0x80000000
-
-struct tipc_name_table_query {
-	__be32 depth;	/* 1:type, 2:+name info, 3:+port info, 4+:+debug info */
-	__be32 type;	/* {t,l,u} info ignored if high bit of "depth" is set */
-	__be32 lowbound; /* (i.e. displays all entries of name table) */
-	__be32 upbound;
-};
-
-/*
- * The error string TLV is a null-terminated string describing the cause
- * of the request failure.  To simplify error processing (and to save space)
- * the first character of the string can be a special error code character
- * (lying by the range 0x80 to 0xFF) which represents a pre-defined reason.
- */
-
-#define TIPC_CFG_TLV_ERROR      "\x80"  /* request contains incorrect TLV(s) */
-#define TIPC_CFG_NOT_NET_ADMIN  "\x81"	/* must be network administrator */
-#define TIPC_CFG_NOT_ZONE_MSTR	"\x82"	/* must be zone master */
-#define TIPC_CFG_NO_REMOTE	"\x83"	/* remote management not enabled */
-#define TIPC_CFG_NOT_SUPPORTED  "\x84"	/* request is not supported by TIPC */
-#define TIPC_CFG_INVALID_VALUE  "\x85"  /* request has invalid argument value */
-
-/*
- * A TLV consists of a descriptor, followed by the TLV value.
- * TLV descriptor fields are stored in network byte order;
- * TLV values must also be stored in network byte order (where applicable).
- * TLV descriptors must be aligned to addresses which are multiple of 4,
- * so up to 3 bytes of padding may exist at the end of the TLV value area.
- * There must not be any padding between the TLV descriptor and its value.
- */
-
-struct tlv_desc {
-	__be16 tlv_len;		/* TLV length (descriptor + value) */
-	__be16 tlv_type;		/* TLV identifier */
-};
-
-#define TLV_ALIGNTO 4
-
-#define TLV_ALIGN(datalen) (((datalen)+(TLV_ALIGNTO-1)) & ~(TLV_ALIGNTO-1))
-#define TLV_LENGTH(datalen) (sizeof(struct tlv_desc) + (datalen))
-#define TLV_SPACE(datalen) (TLV_ALIGN(TLV_LENGTH(datalen)))
-#define TLV_DATA(tlv) ((void *)((char *)(tlv) + TLV_LENGTH(0)))
-
-static inline int TLV_OK(const void *tlv, __u16 space)
-{
-	/*
-	 * Would also like to check that "tlv" is a multiple of 4,
-	 * but don't know how to do this in a portable way.
-	 * - Tried doing (!(tlv & (TLV_ALIGNTO-1))), but GCC compiler
-	 *   won't allow binary "&" with a pointer.
-	 * - Tried casting "tlv" to integer type, but causes warning about size
-	 *   mismatch when pointer is bigger than chosen type (int, long, ...).
-	 */
-
-	return (space >= TLV_SPACE(0)) &&
-		(ntohs(((struct tlv_desc *)tlv)->tlv_len) <= space);
-}
-
-static inline int TLV_CHECK(const void *tlv, __u16 space, __u16 exp_type)
-{
-	return TLV_OK(tlv, space) &&
-		(ntohs(((struct tlv_desc *)tlv)->tlv_type) == exp_type);
-}
-
-static inline int TLV_SET(void *tlv, __u16 type, void *data, __u16 len)
-{
-	struct tlv_desc *tlv_ptr;
-	int tlv_len;
-
-	tlv_len = TLV_LENGTH(len);
-	tlv_ptr = (struct tlv_desc *)tlv;
-	tlv_ptr->tlv_type = htons(type);
-	tlv_ptr->tlv_len  = htons(tlv_len);
-	if (len && data)
-		memcpy(TLV_DATA(tlv_ptr), data, tlv_len);
-	return TLV_SPACE(len);
-}
-
-/*
- * A TLV list descriptor simplifies processing of messages
- * containing multiple TLVs.
- */
-
-struct tlv_list_desc {
-	struct tlv_desc *tlv_ptr;	/* ptr to current TLV */
-	__u32 tlv_space;		/* # bytes from curr TLV to list end */
-};
-
-static inline void TLV_LIST_INIT(struct tlv_list_desc *list,
-				 void *data, __u32 space)
-{
-	list->tlv_ptr = (struct tlv_desc *)data;
-	list->tlv_space = space;
-}
-
-static inline int TLV_LIST_EMPTY(struct tlv_list_desc *list)
-{
-	return (list->tlv_space == 0);
-}
-
-static inline int TLV_LIST_CHECK(struct tlv_list_desc *list, __u16 exp_type)
-{
-	return TLV_CHECK(list->tlv_ptr, list->tlv_space, exp_type);
-}
-
-static inline void *TLV_LIST_DATA(struct tlv_list_desc *list)
-{
-	return TLV_DATA(list->tlv_ptr);
-}
-
-static inline void TLV_LIST_STEP(struct tlv_list_desc *list)
-{
-	__u16 tlv_space = TLV_ALIGN(ntohs(list->tlv_ptr->tlv_len));
-
-	list->tlv_ptr = (struct tlv_desc *)((char *)list->tlv_ptr + tlv_space);
-	list->tlv_space -= tlv_space;
-}
-
 /*
  * Configuration messages exchanged via NETLINK_GENERIC use the following
  * family id, name, version and command.
  */
 #define TIPC_GENL_NAME		"TIPC"
 #define TIPC_GENL_VERSION	0x1
-#define TIPC_GENL_CMD		0x1
-
-/*
- * TIPC specific header used in NETLINK_GENERIC requests.
- */
-struct tipc_genlmsghdr {
-	__u32 dest;		/* Destination address */
-	__u16 cmd;		/* Command */
-	__u16 reserved;		/* Unused */
-};
-
-#define TIPC_GENL_HDRLEN	NLMSG_ALIGN(sizeof(struct tipc_genlmsghdr))
 
 /*
  * Configuration messages exchanged via TIPC sockets use the TIPC configuration
- * message header, which is defined below.  This structure is analogous
- * to the Netlink message header, but fields are stored in network byte order
- * and no padding is permitted between the header and the message data
+ * message header, which is defined below. Fields are stored in network byte
+ * order and no padding is permitted between the header and the message data
  * that follows.
  */
 
@@ -561,28 +290,4 @@ struct tipc_cfg_msg_hdr {
 	char  tcm_reserved[8];	/* Unused */
 };
 
-#define TCM_F_REQUEST	0x1	/* Flag: Request message */
-#define TCM_F_MORE	0x2	/* Flag: Message to be continued */
-
-#define TCM_ALIGN(datalen)  (((datalen)+3) & ~3)
-#define TCM_LENGTH(datalen) (sizeof(struct tipc_cfg_msg_hdr) + datalen)
-#define TCM_SPACE(datalen)  (TCM_ALIGN(TCM_LENGTH(datalen)))
-#define TCM_DATA(tcm_hdr)   ((void *)((char *)(tcm_hdr) + TCM_LENGTH(0)))
-
-static inline int TCM_SET(void *msg, __u16 cmd, __u16 flags,
-			  void *data, __u16 data_len)
-{
-	struct tipc_cfg_msg_hdr *tcm_hdr;
-	int msg_len;
-
-	msg_len = TCM_LENGTH(data_len);
-	tcm_hdr = (struct tipc_cfg_msg_hdr *)msg;
-	tcm_hdr->tcm_len   = htonl(msg_len);
-	tcm_hdr->tcm_type  = htons(cmd);
-	tcm_hdr->tcm_flags = htons(flags);
-	if (data_len && data)
-		memcpy(TCM_DATA(msg), data, data_len);
-	return TCM_SPACE(data_len);
-}
-
 #endif
diff --git a/net/tipc/Makefile b/net/tipc/Makefile
index b8a13ca..c68864f 100644
--- a/net/tipc/Makefile
+++ b/net/tipc/Makefile
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_TIPC) := tipc.o
 
-tipc-y	+= addr.o bcast.o bearer.o config.o \
+tipc-y	+= addr.o bcast.o bearer.o \
 	   core.o link.o discover.o msg.o  \
 	   name_distr.o  subscr.o name_table.o net.o  \
 	   netlink.o node.o node_subscr.o \
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index e12476b..473f3a1 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -867,47 +867,6 @@ msg_full:
 	return -EMSGSIZE;
 }
 
-int tipc_bclink_stats(char *buf, const u32 buf_size)
-{
-	int ret;
-	struct tipc_stats *s;
-
-	if (!bcl)
-		return 0;
-
-	tipc_bclink_lock();
-
-	s = &bcl->stats;
-
-	ret = tipc_snprintf(buf, buf_size, "Link <%s>\n"
-			    "  Window:%u packets\n",
-			    bcl->name, bcl->queue_limit[0]);
-	ret += tipc_snprintf(buf + ret, buf_size - ret,
-			     "  RX packets:%u fragments:%u/%u bundles:%u/%u\n",
-			     s->recv_info, s->recv_fragments,
-			     s->recv_fragmented, s->recv_bundles,
-			     s->recv_bundled);
-	ret += tipc_snprintf(buf + ret, buf_size - ret,
-			     "  TX packets:%u fragments:%u/%u bundles:%u/%u\n",
-			     s->sent_info, s->sent_fragments,
-			     s->sent_fragmented, s->sent_bundles,
-			     s->sent_bundled);
-	ret += tipc_snprintf(buf + ret, buf_size - ret,
-			     "  RX naks:%u defs:%u dups:%u\n",
-			     s->recv_nacks, s->deferred_recv, s->duplicates);
-	ret += tipc_snprintf(buf + ret, buf_size - ret,
-			     "  TX naks:%u acks:%u dups:%u\n",
-			     s->sent_nacks, s->sent_acks, s->retransmitted);
-	ret += tipc_snprintf(buf + ret, buf_size - ret,
-			     "  Congestion link:%u  Send queue max:%u avg:%u\n",
-			     s->link_congs, s->max_queue_sz,
-			     s->queue_sz_counts ?
-			     (s->accu_queue_sz / s->queue_sz_counts) : 0);
-
-	tipc_bclink_unlock();
-	return ret;
-}
-
 int tipc_bclink_reset_stats(void)
 {
 	if (!bcl)
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
index 3c0263e..2c2443a 100644
--- a/net/tipc/bcast.h
+++ b/net/tipc/bcast.h
@@ -95,7 +95,6 @@ void tipc_bclink_rcv(struct sk_buff *buf);
 u32  tipc_bclink_get_last_sent(void);
 u32  tipc_bclink_acks_missing(struct tipc_node *n_ptr);
 void tipc_bclink_update_link_state(struct tipc_node *n_ptr, u32 last_sent);
-int  tipc_bclink_stats(char *stats_buf, const u32 buf_size);
 int  tipc_bclink_reset_stats(void);
 int  tipc_bclink_set_queue_limits(u32 limit);
 void tipc_bcbearer_sort(struct tipc_node_map *nm_ptr, u32 node, bool action);
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 3e33771..6798219 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -35,7 +35,6 @@
  */
 
 #include "core.h"
-#include "config.h"
 #include "bearer.h"
 #include "link.h"
 #include "discover.h"
@@ -123,26 +122,6 @@ void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a)
 }
 
 /**
- * tipc_media_get_names - record names of registered media in buffer
- */
-struct sk_buff *tipc_media_get_names(void)
-{
-	struct sk_buff *buf;
-	int i;
-
-	buf = tipc_cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME));
-	if (!buf)
-		return NULL;
-
-	for (i = 0; media_info_array[i] != NULL; i++) {
-		tipc_cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME,
-				    media_info_array[i]->name,
-				    strlen(media_info_array[i]->name) + 1);
-	}
-	return buf;
-}
-
-/**
  * bearer_name_validate - validate & (optionally) deconstruct bearer name
  * @name: ptr to bearer name string
  * @name_parts: ptr to area for bearer name components (or NULL if not needed)
@@ -203,34 +182,6 @@ struct tipc_bearer *tipc_bearer_find(const char *name)
 	return NULL;
 }
 
-/**
- * tipc_bearer_get_names - record names of bearers in buffer
- */
-struct sk_buff *tipc_bearer_get_names(void)
-{
-	struct sk_buff *buf;
-	struct tipc_bearer *b;
-	int i, j;
-
-	buf = tipc_cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME));
-	if (!buf)
-		return NULL;
-
-	for (i = 0; media_info_array[i] != NULL; i++) {
-		for (j = 0; j < MAX_BEARERS; j++) {
-			b = rtnl_dereference(bearer_list[j]);
-			if (!b)
-				continue;
-			if (b->media == media_info_array[i]) {
-				tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
-						    b->name,
-						    strlen(b->name) + 1);
-			}
-		}
-	}
-	return buf;
-}
-
 void tipc_bearer_add_dest(u32 bearer_id, u32 dest)
 {
 	struct tipc_bearer *b_ptr;
@@ -413,22 +364,6 @@ static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down)
 	kfree_rcu(b_ptr, rcu);
 }
 
-int tipc_disable_bearer(const char *name)
-{
-	struct tipc_bearer *b_ptr;
-	int res;
-
-	b_ptr = tipc_bearer_find(name);
-	if (b_ptr == NULL) {
-		pr_warn("Attempt to disable unknown bearer <%s>\n", name);
-		res = -EINVAL;
-	} else {
-		bearer_disable(b_ptr, false);
-		res = 0;
-	}
-	return res;
-}
-
 int tipc_enable_l2_media(struct tipc_bearer *b)
 {
 	struct net_device *dev;
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index b1d9052..8550ec8 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -167,7 +167,6 @@ extern struct tipc_bearer __rcu *bearer_list[];
 
 void tipc_rcv(struct sk_buff *buf, struct tipc_bearer *tb_ptr);
 int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority);
-int tipc_disable_bearer(const char *name);
 
 /*
  * Routines made available to TIPC by supported media types
diff --git a/net/tipc/config.c b/net/tipc/config.c
deleted file mode 100644
index 876f4c6..0000000
--- a/net/tipc/config.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * net/tipc/config.c: TIPC configuration management code
- *
- * Copyright (c) 2002-2006, Ericsson AB
- * Copyright (c) 2004-2007, 2010-2013, Wind River Systems
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the names of the copyright holders nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "core.h"
-#include "socket.h"
-#include "name_table.h"
-#include "config.h"
-#include "server.h"
-
-#define REPLY_TRUNCATED "<truncated>\n"
-
-static const void *req_tlv_area;	/* request message TLV area */
-static int req_tlv_space;		/* request message TLV area size */
-static int rep_headroom;		/* reply message headroom to use */
-
-struct sk_buff *tipc_cfg_reply_alloc(int payload_size)
-{
-	struct sk_buff *buf;
-
-	buf = alloc_skb(rep_headroom + payload_size, GFP_ATOMIC);
-	if (buf)
-		skb_reserve(buf, rep_headroom);
-	return buf;
-}
-
-int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type,
-			void *tlv_data, int tlv_data_size)
-{
-	struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(buf);
-	int new_tlv_space = TLV_SPACE(tlv_data_size);
-
-	if (skb_tailroom(buf) < new_tlv_space)
-		return 0;
-	skb_put(buf, new_tlv_space);
-	tlv->tlv_type = htons(tlv_type);
-	tlv->tlv_len  = htons(TLV_LENGTH(tlv_data_size));
-	if (tlv_data_size && tlv_data)
-		memcpy(TLV_DATA(tlv), tlv_data, tlv_data_size);
-	return 1;
-}
-
-static struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value)
-{
-	struct sk_buff *buf;
-	__be32 value_net;
-
-	buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(value)));
-	if (buf) {
-		value_net = htonl(value);
-		tipc_cfg_append_tlv(buf, tlv_type, &value_net,
-				    sizeof(value_net));
-	}
-	return buf;
-}
-
-static struct sk_buff *tipc_cfg_reply_unsigned(u32 value)
-{
-	return tipc_cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value);
-}
-
-struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string)
-{
-	struct sk_buff *buf;
-	int string_len = strlen(string) + 1;
-
-	buf = tipc_cfg_reply_alloc(TLV_SPACE(string_len));
-	if (buf)
-		tipc_cfg_append_tlv(buf, tlv_type, string, string_len);
-	return buf;
-}
-
-static struct sk_buff *tipc_show_stats(void)
-{
-	struct sk_buff *buf;
-	struct tlv_desc *rep_tlv;
-	char *pb;
-	int pb_len;
-	int str_len;
-	u32 value;
-
-	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
-		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
-	value = ntohl(*(u32 *)TLV_DATA(req_tlv_area));
-	if (value != 0)
-		return tipc_cfg_reply_error_string("unsupported argument");
-
-	buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
-	if (buf == NULL)
-		return NULL;
-
-	rep_tlv = (struct tlv_desc *)buf->data;
-	pb = TLV_DATA(rep_tlv);
-	pb_len = ULTRA_STRING_MAX_LEN;
-
-	str_len = tipc_snprintf(pb, pb_len, "TIPC version " TIPC_MOD_VER "\n");
-	str_len += 1;	/* for "\0" */
-	skb_put(buf, TLV_SPACE(str_len));
-	TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
-
-	return buf;
-}
-
-static struct sk_buff *cfg_enable_bearer(void)
-{
-	struct tipc_bearer_config *args;
-
-	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG))
-		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
-	args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area);
-	if (tipc_enable_bearer(args->name,
-			       ntohl(args->disc_domain),
-			       ntohl(args->priority)))
-		return tipc_cfg_reply_error_string("unable to enable bearer");
-
-	return tipc_cfg_reply_none();
-}
-
-static struct sk_buff *cfg_disable_bearer(void)
-{
-	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME))
-		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
-	if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area)))
-		return tipc_cfg_reply_error_string("unable to disable bearer");
-
-	return tipc_cfg_reply_none();
-}
-
-static struct sk_buff *cfg_set_own_addr(void)
-{
-	u32 addr;
-
-	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
-		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
-	addr = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
-	if (addr == tipc_own_addr)
-		return tipc_cfg_reply_none();
-	if (!tipc_addr_node_valid(addr))
-		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
-						   " (node address)");
-	if (tipc_own_addr)
-		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-						   " (cannot change node address once assigned)");
-	if (!tipc_net_start(addr))
-		return tipc_cfg_reply_none();
-
-	return tipc_cfg_reply_error_string("cannot change to network mode");
-}
-
-static struct sk_buff *cfg_set_max_ports(void)
-{
-	u32 value;
-
-	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
-		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-	value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
-	if (value == tipc_max_ports)
-		return tipc_cfg_reply_none();
-	if (value < 127 || value > 65535)
-		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
-						   " (max ports must be 127-65535)");
-	return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-		" (cannot change max ports while TIPC is active)");
-}
-
-static struct sk_buff *cfg_set_netid(void)
-{
-	u32 value;
-
-	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
-		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-	value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
-	if (value == tipc_net_id)
-		return tipc_cfg_reply_none();
-	if (value < 1 || value > 9999)
-		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
-						   " (network id must be 1-9999)");
-	if (tipc_own_addr)
-		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-			" (cannot change network id once TIPC has joined a network)");
-	tipc_net_id = value;
-	return tipc_cfg_reply_none();
-}
-
-struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area,
-				int request_space, int reply_headroom)
-{
-	struct sk_buff *rep_tlv_buf;
-
-	rtnl_lock();
-
-	/* Save request and reply details in a well-known location */
-	req_tlv_area = request_area;
-	req_tlv_space = request_space;
-	rep_headroom = reply_headroom;
-
-	/* Check command authorization */
-	if (likely(in_own_node(orig_node))) {
-		/* command is permitted */
-	} else {
-		rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-							  " (cannot be done remotely)");
-		goto exit;
-	}
-
-	/* Call appropriate processing routine */
-	switch (cmd) {
-	case TIPC_CMD_NOOP:
-		rep_tlv_buf = tipc_cfg_reply_none();
-		break;
-	case TIPC_CMD_GET_NODES:
-		rep_tlv_buf = tipc_node_get_nodes(req_tlv_area, req_tlv_space);
-		break;
-	case TIPC_CMD_GET_LINKS:
-		rep_tlv_buf = tipc_node_get_links(req_tlv_area, req_tlv_space);
-		break;
-	case TIPC_CMD_SHOW_LINK_STATS:
-		rep_tlv_buf = tipc_link_cmd_show_stats(req_tlv_area, req_tlv_space);
-		break;
-	case TIPC_CMD_RESET_LINK_STATS:
-		rep_tlv_buf = tipc_link_cmd_reset_stats(req_tlv_area, req_tlv_space);
-		break;
-	case TIPC_CMD_SHOW_NAME_TABLE:
-		rep_tlv_buf = tipc_nametbl_get(req_tlv_area, req_tlv_space);
-		break;
-	case TIPC_CMD_GET_BEARER_NAMES:
-		rep_tlv_buf = tipc_bearer_get_names();
-		break;
-	case TIPC_CMD_GET_MEDIA_NAMES:
-		rep_tlv_buf = tipc_media_get_names();
-		break;
-	case TIPC_CMD_SHOW_PORTS:
-		rep_tlv_buf = tipc_sk_socks_show();
-		break;
-	case TIPC_CMD_SHOW_STATS:
-		rep_tlv_buf = tipc_show_stats();
-		break;
-	case TIPC_CMD_SET_LINK_TOL:
-	case TIPC_CMD_SET_LINK_PRI:
-	case TIPC_CMD_SET_LINK_WINDOW:
-		rep_tlv_buf = tipc_link_cmd_config(req_tlv_area, req_tlv_space, cmd);
-		break;
-	case TIPC_CMD_ENABLE_BEARER:
-		rep_tlv_buf = cfg_enable_bearer();
-		break;
-	case TIPC_CMD_DISABLE_BEARER:
-		rep_tlv_buf = cfg_disable_bearer();
-		break;
-	case TIPC_CMD_SET_NODE_ADDR:
-		rep_tlv_buf = cfg_set_own_addr();
-		break;
-	case TIPC_CMD_SET_MAX_PORTS:
-		rep_tlv_buf = cfg_set_max_ports();
-		break;
-	case TIPC_CMD_SET_NETID:
-		rep_tlv_buf = cfg_set_netid();
-		break;
-	case TIPC_CMD_GET_MAX_PORTS:
-		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_ports);
-		break;
-	case TIPC_CMD_GET_NETID:
-		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id);
-		break;
-	case TIPC_CMD_NOT_NET_ADMIN:
-		rep_tlv_buf =
-			tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN);
-		break;
-	case TIPC_CMD_SET_MAX_ZONES:
-	case TIPC_CMD_GET_MAX_ZONES:
-	case TIPC_CMD_SET_MAX_SLAVES:
-	case TIPC_CMD_GET_MAX_SLAVES:
-	case TIPC_CMD_SET_MAX_CLUSTERS:
-	case TIPC_CMD_GET_MAX_CLUSTERS:
-	case TIPC_CMD_SET_MAX_NODES:
-	case TIPC_CMD_GET_MAX_NODES:
-	case TIPC_CMD_SET_MAX_SUBSCR:
-	case TIPC_CMD_GET_MAX_SUBSCR:
-	case TIPC_CMD_SET_MAX_PUBL:
-	case TIPC_CMD_GET_MAX_PUBL:
-	case TIPC_CMD_SET_LOG_SIZE:
-	case TIPC_CMD_SET_REMOTE_MNG:
-	case TIPC_CMD_GET_REMOTE_MNG:
-	case TIPC_CMD_DUMP_LOG:
-		rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-							  " (obsolete command)");
-		break;
-	default:
-		rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-							  " (unknown command)");
-		break;
-	}
-
-	WARN_ON(rep_tlv_buf->len > TLV_SPACE(ULTRA_STRING_MAX_LEN));
-
-	/* Append an error message if we cannot return all requested data */
-	if (rep_tlv_buf->len == TLV_SPACE(ULTRA_STRING_MAX_LEN)) {
-		if (*(rep_tlv_buf->data + ULTRA_STRING_MAX_LEN) != '\0')
-			sprintf(rep_tlv_buf->data + rep_tlv_buf->len -
-				sizeof(REPLY_TRUNCATED) - 1, REPLY_TRUNCATED);
-	}
-
-	/* Return reply buffer */
-exit:
-	rtnl_unlock();
-	return rep_tlv_buf;
-}
diff --git a/net/tipc/config.h b/net/tipc/config.h
deleted file mode 100644
index 47b1bf1..0000000
--- a/net/tipc/config.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * net/tipc/config.h: Include file for TIPC configuration service code
- *
- * Copyright (c) 2003-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the names of the copyright holders nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _TIPC_CONFIG_H
-#define _TIPC_CONFIG_H
-
-/* ---------------------------------------------------------------------- */
-
-#include "link.h"
-
-struct sk_buff *tipc_cfg_reply_alloc(int payload_size);
-int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type,
-			void *tlv_data, int tlv_data_size);
-struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string);
-
-static inline struct sk_buff *tipc_cfg_reply_none(void)
-{
-	return tipc_cfg_reply_alloc(0);
-}
-
-static inline struct sk_buff *tipc_cfg_reply_error_string(char *string)
-{
-	return tipc_cfg_reply_string_type(TIPC_TLV_ERROR_STRING, string);
-}
-
-static inline struct sk_buff *tipc_cfg_reply_ultra_string(char *string)
-{
-	return tipc_cfg_reply_string_type(TIPC_TLV_ULTRA_STRING, string);
-}
-
-struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd,
-				const void *req_tlv_area, int req_tlv_space,
-				int headroom);
-#endif
diff --git a/net/tipc/core.c b/net/tipc/core.c
index a5737b8..b78284b 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -37,8 +37,9 @@
 #include "core.h"
 #include "name_table.h"
 #include "subscr.h"
-#include "config.h"
 #include "socket.h"
+#include "net.h"
+#include "bearer.h"
 
 #include <linux/module.h>
 
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 2195197..2e8e184 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -40,7 +40,6 @@
 #include "socket.h"
 #include "name_distr.h"
 #include "discover.h"
-#include "config.h"
 #include "netlink.h"
 
 #include <linux/pkt_sched.h>
@@ -2028,148 +2027,6 @@ static struct tipc_node *tipc_link_find_owner(const char *link_name,
 }
 
 /**
- * link_value_is_valid -- validate proposed link tolerance/priority/window
- *
- * @cmd: value type (TIPC_CMD_SET_LINK_*)
- * @new_value: the new value
- *
- * Returns 1 if value is within range, 0 if not.
- */
-static int link_value_is_valid(u16 cmd, u32 new_value)
-{
-	switch (cmd) {
-	case TIPC_CMD_SET_LINK_TOL:
-		return (new_value >= TIPC_MIN_LINK_TOL) &&
-			(new_value <= TIPC_MAX_LINK_TOL);
-	case TIPC_CMD_SET_LINK_PRI:
-		return (new_value <= TIPC_MAX_LINK_PRI);
-	case TIPC_CMD_SET_LINK_WINDOW:
-		return (new_value >= TIPC_MIN_LINK_WIN) &&
-			(new_value <= TIPC_MAX_LINK_WIN);
-	}
-	return 0;
-}
-
-/**
- * link_cmd_set_value - change priority/tolerance/window for link/bearer/media
- * @name: ptr to link, bearer, or media name
- * @new_value: new value of link, bearer, or media setting
- * @cmd: which link, bearer, or media attribute to set (TIPC_CMD_SET_LINK_*)
- *
- * Caller must hold RTNL lock to ensure link/bearer/media is not deleted.
- *
- * Returns 0 if value updated and negative value on error.
- */
-static int link_cmd_set_value(const char *name, u32 new_value, u16 cmd)
-{
-	struct tipc_node *node;
-	struct tipc_link *l_ptr;
-	struct tipc_bearer *b_ptr;
-	struct tipc_media *m_ptr;
-	int bearer_id;
-	int res = 0;
-
-	node = tipc_link_find_owner(name, &bearer_id);
-	if (node) {
-		tipc_node_lock(node);
-		l_ptr = node->links[bearer_id];
-
-		if (l_ptr) {
-			switch (cmd) {
-			case TIPC_CMD_SET_LINK_TOL:
-				link_set_supervision_props(l_ptr, new_value);
-				tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0,
-						     new_value, 0, 0);
-				break;
-			case TIPC_CMD_SET_LINK_PRI:
-				l_ptr->priority = new_value;
-				tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0,
-						     0, new_value, 0);
-				break;
-			case TIPC_CMD_SET_LINK_WINDOW:
-				tipc_link_set_queue_limits(l_ptr, new_value);
-				break;
-			default:
-				res = -EINVAL;
-				break;
-			}
-		}
-		tipc_node_unlock(node);
-		return res;
-	}
-
-	b_ptr = tipc_bearer_find(name);
-	if (b_ptr) {
-		switch (cmd) {
-		case TIPC_CMD_SET_LINK_TOL:
-			b_ptr->tolerance = new_value;
-			break;
-		case TIPC_CMD_SET_LINK_PRI:
-			b_ptr->priority = new_value;
-			break;
-		case TIPC_CMD_SET_LINK_WINDOW:
-			b_ptr->window = new_value;
-			break;
-		default:
-			res = -EINVAL;
-			break;
-		}
-		return res;
-	}
-
-	m_ptr = tipc_media_find(name);
-	if (!m_ptr)
-		return -ENODEV;
-	switch (cmd) {
-	case TIPC_CMD_SET_LINK_TOL:
-		m_ptr->tolerance = new_value;
-		break;
-	case TIPC_CMD_SET_LINK_PRI:
-		m_ptr->priority = new_value;
-		break;
-	case TIPC_CMD_SET_LINK_WINDOW:
-		m_ptr->window = new_value;
-		break;
-	default:
-		res = -EINVAL;
-		break;
-	}
-	return res;
-}
-
-struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space,
-				     u16 cmd)
-{
-	struct tipc_link_config *args;
-	u32 new_value;
-	int res;
-
-	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_CONFIG))
-		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
-	args = (struct tipc_link_config *)TLV_DATA(req_tlv_area);
-	new_value = ntohl(args->value);
-
-	if (!link_value_is_valid(cmd, new_value))
-		return tipc_cfg_reply_error_string(
-			"cannot change, value invalid");
-
-	if (!strcmp(args->name, tipc_bclink_name)) {
-		if ((cmd == TIPC_CMD_SET_LINK_WINDOW) &&
-		    (tipc_bclink_set_queue_limits(new_value) == 0))
-			return tipc_cfg_reply_none();
-		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-						   " (cannot change setting on broadcast link)");
-	}
-
-	res = link_cmd_set_value(args->name, new_value, cmd);
-	if (res)
-		return tipc_cfg_reply_error_string("cannot change link setting");
-
-	return tipc_cfg_reply_none();
-}
-
-/**
  * link_reset_statistics - reset link statistics
  * @l_ptr: pointer to link
  */
@@ -2180,174 +2037,6 @@ static void link_reset_statistics(struct tipc_link *l_ptr)
 	l_ptr->stats.recv_info = l_ptr->next_in_no;
 }
 
-struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space)
-{
-	char *link_name;
-	struct tipc_link *l_ptr;
-	struct tipc_node *node;
-	unsigned int bearer_id;
-
-	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
-		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
-	link_name = (char *)TLV_DATA(req_tlv_area);
-	if (!strcmp(link_name, tipc_bclink_name)) {
-		if (tipc_bclink_reset_stats())
-			return tipc_cfg_reply_error_string("link not found");
-		return tipc_cfg_reply_none();
-	}
-	node = tipc_link_find_owner(link_name, &bearer_id);
-	if (!node)
-		return tipc_cfg_reply_error_string("link not found");
-
-	tipc_node_lock(node);
-	l_ptr = node->links[bearer_id];
-	if (!l_ptr) {
-		tipc_node_unlock(node);
-		return tipc_cfg_reply_error_string("link not found");
-	}
-	link_reset_statistics(l_ptr);
-	tipc_node_unlock(node);
-	return tipc_cfg_reply_none();
-}
-
-/**
- * percent - convert count to a percentage of total (rounding up or down)
- */
-static u32 percent(u32 count, u32 total)
-{
-	return (count * 100 + (total / 2)) / total;
-}
-
-/**
- * tipc_link_stats - print link statistics
- * @name: link name
- * @buf: print buffer area
- * @buf_size: size of print buffer area
- *
- * Returns length of print buffer data string (or 0 if error)
- */
-static int tipc_link_stats(const char *name, char *buf, const u32 buf_size)
-{
-	struct tipc_link *l;
-	struct tipc_stats *s;
-	struct tipc_node *node;
-	char *status;
-	u32 profile_total = 0;
-	unsigned int bearer_id;
-	int ret;
-
-	if (!strcmp(name, tipc_bclink_name))
-		return tipc_bclink_stats(buf, buf_size);
-
-	node = tipc_link_find_owner(name, &bearer_id);
-	if (!node)
-		return 0;
-
-	tipc_node_lock(node);
-
-	l = node->links[bearer_id];
-	if (!l) {
-		tipc_node_unlock(node);
-		return 0;
-	}
-
-	s = &l->stats;
-
-	if (tipc_link_is_active(l))
-		status = "ACTIVE";
-	else if (tipc_link_is_up(l))
-		status = "STANDBY";
-	else
-		status = "DEFUNCT";
-
-	ret = tipc_snprintf(buf, buf_size, "Link <%s>\n"
-			    "  %s  MTU:%u  Priority:%u  Tolerance:%u ms"
-			    "  Window:%u packets\n",
-			    l->name, status, l->max_pkt, l->priority,
-			    l->tolerance, l->queue_limit[0]);
-
-	ret += tipc_snprintf(buf + ret, buf_size - ret,
-			     "  RX packets:%u fragments:%u/%u bundles:%u/%u\n",
-			     l->next_in_no - s->recv_info, s->recv_fragments,
-			     s->recv_fragmented, s->recv_bundles,
-			     s->recv_bundled);
-
-	ret += tipc_snprintf(buf + ret, buf_size - ret,
-			     "  TX packets:%u fragments:%u/%u bundles:%u/%u\n",
-			     l->next_out_no - s->sent_info, s->sent_fragments,
-			     s->sent_fragmented, s->sent_bundles,
-			     s->sent_bundled);
-
-	profile_total = s->msg_length_counts;
-	if (!profile_total)
-		profile_total = 1;
-
-	ret += tipc_snprintf(buf + ret, buf_size - ret,
-			     "  TX profile sample:%u packets  average:%u octets\n"
-			     "  0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% "
-			     "-16384:%u%% -32768:%u%% -66000:%u%%\n",
-			     s->msg_length_counts,
-			     s->msg_lengths_total / profile_total,
-			     percent(s->msg_length_profile[0], profile_total),
-			     percent(s->msg_length_profile[1], profile_total),
-			     percent(s->msg_length_profile[2], profile_total),
-			     percent(s->msg_length_profile[3], profile_total),
-			     percent(s->msg_length_profile[4], profile_total),
-			     percent(s->msg_length_profile[5], profile_total),
-			     percent(s->msg_length_profile[6], profile_total));
-
-	ret += tipc_snprintf(buf + ret, buf_size - ret,
-			     "  RX states:%u probes:%u naks:%u defs:%u"
-			     " dups:%u\n", s->recv_states, s->recv_probes,
-			     s->recv_nacks, s->deferred_recv, s->duplicates);
-
-	ret += tipc_snprintf(buf + ret, buf_size - ret,
-			     "  TX states:%u probes:%u naks:%u acks:%u"
-			     " dups:%u\n", s->sent_states, s->sent_probes,
-			     s->sent_nacks, s->sent_acks, s->retransmitted);
-
-	ret += tipc_snprintf(buf + ret, buf_size - ret,
-			     "  Congestion link:%u  Send queue"
-			     " max:%u avg:%u\n", s->link_congs,
-			     s->max_queue_sz, s->queue_sz_counts ?
-			     (s->accu_queue_sz / s->queue_sz_counts) : 0);
-
-	tipc_node_unlock(node);
-	return ret;
-}
-
-struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space)
-{
-	struct sk_buff *buf;
-	struct tlv_desc *rep_tlv;
-	int str_len;
-	int pb_len;
-	char *pb;
-
-	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
-		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
-	buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
-	if (!buf)
-		return NULL;
-
-	rep_tlv = (struct tlv_desc *)buf->data;
-	pb = TLV_DATA(rep_tlv);
-	pb_len = ULTRA_STRING_MAX_LEN;
-	str_len = tipc_link_stats((char *)TLV_DATA(req_tlv_area),
-				  pb, pb_len);
-	if (!str_len) {
-		kfree_skb(buf);
-		return tipc_cfg_reply_error_string("link not found");
-	}
-	str_len += 1;	/* for "\0" */
-	skb_put(buf, TLV_SPACE(str_len));
-	TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
-
-	return buf;
-}
-
 /**
  * tipc_link_get_max_pkt - get maximum packet size to use when sending to destination
  * @dest: network address of destination node
diff --git a/net/tipc/link.h b/net/tipc/link.h
index f463e7b..20e9c93 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -217,13 +217,6 @@ void tipc_link_reset_fragments(struct tipc_link *l_ptr);
 int tipc_link_is_up(struct tipc_link *l_ptr);
 int tipc_link_is_active(struct tipc_link *l_ptr);
 void tipc_link_purge_queues(struct tipc_link *l_ptr);
-struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area,
-				     int req_tlv_space,
-				     u16 cmd);
-struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area,
-					 int req_tlv_space);
-struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area,
-					  int req_tlv_space);
 void tipc_link_reset_all(struct tipc_node *node);
 void tipc_link_reset(struct tipc_link *l_ptr);
 void tipc_link_reset_list(unsigned int bearer_id);
diff --git a/net/tipc/log.c b/net/tipc/log.c
index abef644..b186af0 100644
--- a/net/tipc/log.c
+++ b/net/tipc/log.c
@@ -35,7 +35,6 @@
  */
 
 #include "core.h"
-#include "config.h"
 
 /**
  * tipc_snprintf - append formatted output to print buffer
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index 7d69229..7b06a9d 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -35,9 +35,9 @@
  */
 
 #include "core.h"
-#include "config.h"
 #include "name_table.h"
 #include "name_distr.h"
+#include "bcast.h"
 #include "subscr.h"
 
 #define TIPC_NAMETBL_SIZE 1024		/* must be a power of 2 */
@@ -760,189 +760,6 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s)
 	write_unlock_bh(&tipc_nametbl_lock);
 }
 
-
-/**
- * subseq_list - print specified sub-sequence contents into the given buffer
- */
-static int subseq_list(struct sub_seq *sseq, char *buf, int len, u32 depth,
-		       u32 index)
-{
-	char portIdStr[27];
-	const char *scope_str[] = {"", " zone", " cluster", " node"};
-	struct publication *publ;
-	struct name_info *info;
-	int ret;
-
-	ret = tipc_snprintf(buf, len, "%-10u %-10u ", sseq->lower, sseq->upper);
-
-	if (depth == 2) {
-		ret += tipc_snprintf(buf - ret, len + ret, "\n");
-		return ret;
-	}
-
-	info = sseq->info;
-
-	list_for_each_entry(publ, &info->zone_list, zone_list) {
-		sprintf(portIdStr, "<%u.%u.%u:%u>",
-			 tipc_zone(publ->node), tipc_cluster(publ->node),
-			 tipc_node(publ->node), publ->ref);
-		ret += tipc_snprintf(buf + ret, len - ret, "%-26s ", portIdStr);
-		if (depth > 3) {
-			ret += tipc_snprintf(buf + ret, len - ret, "%-10u %s",
-					     publ->key, scope_str[publ->scope]);
-		}
-		if (!list_is_last(&publ->zone_list, &info->zone_list))
-			ret += tipc_snprintf(buf + ret, len - ret,
-					     "\n%33s", " ");
-	}
-
-	ret += tipc_snprintf(buf + ret, len - ret, "\n");
-	return ret;
-}
-
-/**
- * nameseq_list - print specified name sequence contents into the given buffer
- */
-static int nameseq_list(struct name_seq *seq, char *buf, int len, u32 depth,
-			u32 type, u32 lowbound, u32 upbound, u32 index)
-{
-	struct sub_seq *sseq;
-	char typearea[11];
-	int ret = 0;
-
-	if (seq->first_free == 0)
-		return 0;
-
-	sprintf(typearea, "%-10u", seq->type);
-
-	if (depth == 1) {
-		ret += tipc_snprintf(buf, len, "%s\n", typearea);
-		return ret;
-	}
-
-	for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) {
-		if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) {
-			ret += tipc_snprintf(buf + ret, len - ret, "%s ",
-					    typearea);
-			spin_lock_bh(&seq->lock);
-			ret += subseq_list(sseq, buf + ret, len - ret,
-					  depth, index);
-			spin_unlock_bh(&seq->lock);
-			sprintf(typearea, "%10s", " ");
-		}
-	}
-	return ret;
-}
-
-/**
- * nametbl_header - print name table header into the given buffer
- */
-static int nametbl_header(char *buf, int len, u32 depth)
-{
-	const char *header[] = {
-		"Type       ",
-		"Lower      Upper      ",
-		"Port Identity              ",
-		"Publication Scope"
-	};
-
-	int i;
-	int ret = 0;
-
-	if (depth > 4)
-		depth = 4;
-	for (i = 0; i < depth; i++)
-		ret += tipc_snprintf(buf + ret, len - ret, header[i]);
-	ret += tipc_snprintf(buf + ret, len - ret, "\n");
-	return ret;
-}
-
-/**
- * nametbl_list - print specified name table contents into the given buffer
- */
-static int nametbl_list(char *buf, int len, u32 depth_info,
-			u32 type, u32 lowbound, u32 upbound)
-{
-	struct hlist_head *seq_head;
-	struct name_seq *seq;
-	int all_types;
-	int ret = 0;
-	u32 depth;
-	u32 i;
-
-	all_types = (depth_info & TIPC_NTQ_ALLTYPES);
-	depth = (depth_info & ~TIPC_NTQ_ALLTYPES);
-
-	if (depth == 0)
-		return 0;
-
-	if (all_types) {
-		/* display all entries in name table to specified depth */
-		ret += nametbl_header(buf, len, depth);
-		lowbound = 0;
-		upbound = ~0;
-		for (i = 0; i < TIPC_NAMETBL_SIZE; i++) {
-			seq_head = &table.types[i];
-			hlist_for_each_entry(seq, seq_head, ns_list) {
-				ret += nameseq_list(seq, buf + ret, len - ret,
-						   depth, seq->type,
-						   lowbound, upbound, i);
-			}
-		}
-	} else {
-		/* display only the sequence that matches the specified type */
-		if (upbound < lowbound) {
-			ret += tipc_snprintf(buf + ret, len - ret,
-					"invalid name sequence specified\n");
-			return ret;
-		}
-		ret += nametbl_header(buf + ret, len - ret, depth);
-		i = hash(type);
-		seq_head = &table.types[i];
-		hlist_for_each_entry(seq, seq_head, ns_list) {
-			if (seq->type == type) {
-				ret += nameseq_list(seq, buf + ret, len - ret,
-						   depth, type,
-						   lowbound, upbound, i);
-				break;
-			}
-		}
-	}
-	return ret;
-}
-
-struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space)
-{
-	struct sk_buff *buf;
-	struct tipc_name_table_query *argv;
-	struct tlv_desc *rep_tlv;
-	char *pb;
-	int pb_len;
-	int str_len;
-
-	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY))
-		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
-	buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
-	if (!buf)
-		return NULL;
-
-	rep_tlv = (struct tlv_desc *)buf->data;
-	pb = TLV_DATA(rep_tlv);
-	pb_len = ULTRA_STRING_MAX_LEN;
-	argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area);
-	read_lock_bh(&tipc_nametbl_lock);
-	str_len = nametbl_list(pb, pb_len, ntohl(argv->depth),
-			       ntohl(argv->type),
-			       ntohl(argv->lowbound), ntohl(argv->upbound));
-	read_unlock_bh(&tipc_nametbl_lock);
-	str_len += 1;	/* for "\0" */
-	skb_put(buf, TLV_SPACE(str_len));
-	TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
-
-	return buf;
-}
-
 int tipc_nametbl_init(void)
 {
 	table.types = kcalloc(TIPC_NAMETBL_SIZE, sizeof(struct hlist_head),
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h
index b38ebec..3ed7b64 100644
--- a/net/tipc/name_table.h
+++ b/net/tipc/name_table.h
@@ -38,6 +38,7 @@
 #define _TIPC_NAME_TABLE_H
 
 #include "node_subscr.h"
+#include <net/genetlink.h>
 
 struct tipc_subscription;
 struct tipc_port_list;
diff --git a/net/tipc/net.c b/net/tipc/net.c
index fdbbedf..2b7d7f3 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -40,7 +40,6 @@
 #include "subscr.h"
 #include "socket.h"
 #include "node.h"
-#include "config.h"
 
 static const struct nla_policy tipc_nl_net_policy[TIPC_NLA_NET_MAX + 1] = {
 	[TIPC_NLA_NET_UNSPEC]	= { .type = NLA_UNSPEC },
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 11a2fd8..608a935 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -35,7 +35,6 @@
  */
 
 #include "core.h"
-#include "config.h"
 #include "socket.h"
 #include "name_table.h"
 #include "bearer.h"
@@ -44,36 +43,6 @@
 #include "net.h"
 #include <net/genetlink.h>
 
-static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
-{
-	struct sk_buff *rep_buf;
-	struct nlmsghdr *rep_nlh;
-	struct nlmsghdr *req_nlh = info->nlhdr;
-	struct tipc_genlmsghdr *req_userhdr = info->userhdr;
-	int hdr_space = nlmsg_total_size(GENL_HDRLEN + TIPC_GENL_HDRLEN);
-	u16 cmd;
-
-	if ((req_userhdr->cmd & 0xC000) && (!netlink_capable(skb, CAP_NET_ADMIN)))
-		cmd = TIPC_CMD_NOT_NET_ADMIN;
-	else
-		cmd = req_userhdr->cmd;
-
-	rep_buf = tipc_cfg_do_cmd(req_userhdr->dest, cmd,
-			nlmsg_data(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN,
-			nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN),
-			hdr_space);
-
-	if (rep_buf) {
-		skb_push(rep_buf, hdr_space);
-		rep_nlh = nlmsg_hdr(rep_buf);
-		memcpy(rep_nlh, req_nlh, hdr_space);
-		rep_nlh->nlmsg_len = rep_buf->len;
-		genlmsg_unicast(&init_net, rep_buf, NETLINK_CB(skb).portid);
-	}
-
-	return 0;
-}
-
 static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = {
 	[TIPC_NLA_UNSPEC]	= { .type = NLA_UNSPEC, },
 	[TIPC_NLA_BEARER]	= { .type = NLA_NESTED, },
@@ -95,11 +64,6 @@ struct genl_family tipc_genl_family = {
 
 static const struct genl_ops tipc_genl_ops[] = {
 	{
-		/* Legacy ASCII API */
-		.cmd		= TIPC_GENL_CMD,
-		.doit		= handle_cmd,
-	},
-	{
 		.cmd	= TIPC_NL_BEARER_DISABLE,
 		.doit	= tipc_nl_bearer_disable,
 		.policy = tipc_nl_policy,
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 80ca561..1a5ef71 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -35,8 +35,8 @@
  */
 
 #include "core.h"
-#include "config.h"
 #include "node.h"
+#include "link.h"
 #include "name_distr.h"
 #include "socket.h"
 
@@ -414,117 +414,6 @@ static void node_lost_contact(struct tipc_node *n_ptr)
 			       TIPC_NOTIFY_NODE_DOWN;
 }
 
-struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
-{
-	u32 domain;
-	struct sk_buff *buf;
-	struct tipc_node *n_ptr;
-	struct tipc_node_info node_info;
-	u32 payload_size;
-
-	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
-		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
-	domain = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
-	if (!tipc_addr_domain_valid(domain))
-		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
-						   " (network address)");
-
-	spin_lock_bh(&node_list_lock);
-	if (!tipc_num_nodes) {
-		spin_unlock_bh(&node_list_lock);
-		return tipc_cfg_reply_none();
-	}
-
-	/* For now, get space for all other nodes */
-	payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes;
-	if (payload_size > 32768u) {
-		spin_unlock_bh(&node_list_lock);
-		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-						   " (too many nodes)");
-	}
-	spin_unlock_bh(&node_list_lock);
-
-	buf = tipc_cfg_reply_alloc(payload_size);
-	if (!buf)
-		return NULL;
-
-	/* Add TLVs for all nodes in scope */
-	rcu_read_lock();
-	list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) {
-		if (!tipc_in_scope(domain, n_ptr->addr))
-			continue;
-		node_info.addr = htonl(n_ptr->addr);
-		node_info.up = htonl(tipc_node_is_up(n_ptr));
-		tipc_cfg_append_tlv(buf, TIPC_TLV_NODE_INFO,
-				    &node_info, sizeof(node_info));
-	}
-	rcu_read_unlock();
-	return buf;
-}
-
-struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
-{
-	u32 domain;
-	struct sk_buff *buf;
-	struct tipc_node *n_ptr;
-	struct tipc_link_info link_info;
-	u32 payload_size;
-
-	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
-		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-
-	domain = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
-	if (!tipc_addr_domain_valid(domain))
-		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
-						   " (network address)");
-
-	if (!tipc_own_addr)
-		return tipc_cfg_reply_none();
-
-	spin_lock_bh(&node_list_lock);
-	/* Get space for all unicast links + broadcast link */
-	payload_size = TLV_SPACE((sizeof(link_info)) * (tipc_num_links + 1));
-	if (payload_size > 32768u) {
-		spin_unlock_bh(&node_list_lock);
-		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-						   " (too many links)");
-	}
-	spin_unlock_bh(&node_list_lock);
-
-	buf = tipc_cfg_reply_alloc(payload_size);
-	if (!buf)
-		return NULL;
-
-	/* Add TLV for broadcast link */
-	link_info.dest = htonl(tipc_cluster_mask(tipc_own_addr));
-	link_info.up = htonl(1);
-	strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME);
-	tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info));
-
-	/* Add TLVs for any other links in scope */
-	rcu_read_lock();
-	list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) {
-		u32 i;
-
-		if (!tipc_in_scope(domain, n_ptr->addr))
-			continue;
-		tipc_node_lock(n_ptr);
-		for (i = 0; i < MAX_BEARERS; i++) {
-			if (!n_ptr->links[i])
-				continue;
-			link_info.dest = htonl(n_ptr->addr);
-			link_info.up = htonl(tipc_link_is_up(n_ptr->links[i]));
-			strcpy(link_info.str, n_ptr->links[i]->name);
-			tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO,
-					    &link_info, sizeof(link_info));
-		}
-		tipc_node_unlock(n_ptr);
-	}
-	rcu_read_unlock();
-	return buf;
-}
-
 /**
  * tipc_node_get_linkname - get the name of a link
  *
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 17c0921..a8849d7 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -132,8 +132,6 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr);
 void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr);
 int tipc_node_active_links(struct tipc_node *n_ptr);
 int tipc_node_is_up(struct tipc_node *n_ptr);
-struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space);
-struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space);
 int tipc_node_get_linkname(u32 bearer_id, u32 node, char *linkname, size_t len);
 void tipc_node_unlock(struct tipc_node *node);
 int tipc_node_add_conn(u32 dnode, u32 port, u32 peer_port);
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index bb58029..4cf2260 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -39,7 +39,6 @@
 #include "node.h"
 #include "link.h"
 #include <linux/export.h>
-#include "config.h"
 #include "socket.h"
 
 #define SS_LISTENING	-1	/* socket is listening */
@@ -2203,82 +2202,6 @@ static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope,
 	return rc;
 }
 
-static int tipc_sk_show(struct tipc_sock *tsk, char *buf,
-			int len, int full_id)
-{
-	struct publication *publ;
-	int ret;
-
-	if (full_id)
-		ret = tipc_snprintf(buf, len, "<%u.%u.%u:%u>:",
-				    tipc_zone(tipc_own_addr),
-				    tipc_cluster(tipc_own_addr),
-				    tipc_node(tipc_own_addr), tsk->ref);
-	else
-		ret = tipc_snprintf(buf, len, "%-10u:", tsk->ref);
-
-	if (tsk->connected) {
-		u32 dport = tsk_peer_port(tsk);
-		u32 destnode = tsk_peer_node(tsk);
-
-		ret += tipc_snprintf(buf + ret, len - ret,
-				     " connected to <%u.%u.%u:%u>",
-				     tipc_zone(destnode),
-				     tipc_cluster(destnode),
-				     tipc_node(destnode), dport);
-		if (tsk->conn_type != 0)
-			ret += tipc_snprintf(buf + ret, len - ret,
-					     " via {%u,%u}", tsk->conn_type,
-					     tsk->conn_instance);
-	} else if (tsk->published) {
-		ret += tipc_snprintf(buf + ret, len - ret, " bound to");
-		list_for_each_entry(publ, &tsk->publications, pport_list) {
-			if (publ->lower == publ->upper)
-				ret += tipc_snprintf(buf + ret, len - ret,
-						     " {%u,%u}", publ->type,
-						     publ->lower);
-			else
-				ret += tipc_snprintf(buf + ret, len - ret,
-						     " {%u,%u,%u}", publ->type,
-						     publ->lower, publ->upper);
-		}
-	}
-	ret += tipc_snprintf(buf + ret, len - ret, "\n");
-	return ret;
-}
-
-struct sk_buff *tipc_sk_socks_show(void)
-{
-	struct sk_buff *buf;
-	struct tlv_desc *rep_tlv;
-	char *pb;
-	int pb_len;
-	struct tipc_sock *tsk;
-	int str_len = 0;
-	u32 ref = 0;
-
-	buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
-	if (!buf)
-		return NULL;
-	rep_tlv = (struct tlv_desc *)buf->data;
-	pb = TLV_DATA(rep_tlv);
-	pb_len = ULTRA_STRING_MAX_LEN;
-
-	tsk = tipc_sk_get_next(&ref);
-	for (; tsk; tsk = tipc_sk_get_next(&ref)) {
-		lock_sock(&tsk->sk);
-		str_len += tipc_sk_show(tsk, pb + str_len,
-					pb_len - str_len, 0);
-		release_sock(&tsk->sk);
-		tipc_sk_put(tsk);
-	}
-	str_len += 1;	/* for "\0" */
-	skb_put(buf, TLV_SPACE(str_len));
-	TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
-
-	return buf;
-}
-
 /* tipc_sk_reinit: set non-zero address in all existing sockets
  *                 when we go from standalone to network mode.
  */
diff --git a/net/tipc/socket.h b/net/tipc/socket.h
index 16dfd62..e7cdb40 100644
--- a/net/tipc/socket.h
+++ b/net/tipc/socket.h
@@ -43,7 +43,6 @@
 #define TIPC_CONN_OVERLOAD_LIMIT ((TIPC_FLOWCTRL_WIN * 2 + 1) * \
 				  SKB_TRUESIZE(TIPC_MAX_USER_MSG_SIZE))
 int tipc_sk_rcv(struct sk_buff *buf);
-struct sk_buff *tipc_sk_socks_show(void);
 void tipc_sk_mcast_rcv(struct sk_buff *buf);
 void tipc_sk_reinit(void);
 int tipc_sk_ref_table_init(u32 requested_size, u32 start);
-- 
1.7.10.4


------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next 01/14] tipc: add bearer disable/enable to new netlink api
  2014-09-11  8:29 ` [PATCH net-next 01/14] tipc: add bearer disable/enable to new netlink api richard.alpe
@ 2014-09-12 21:07   ` David Miller
  0 siblings, 0 replies; 24+ messages in thread
From: David Miller @ 2014-09-12 21:07 UTC (permalink / raw)
  To: richard.alpe; +Cc: netdev, tipc-discussion

From: <richard.alpe@ericsson.com>
Date: Thu, 11 Sep 2014 10:29:14 +0200

> +struct tipc_nl_msg {
> +	struct sk_buff *skb;
> +	u32 portid;
> +	u32 seq;
> +};

This datastructure has no users this early in the patch series.  Add it to the
patch which actually has a user.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next 04/14] tipc: add sock dump to new netlink api
  2014-09-11  8:29 ` [PATCH net-next 04/14] tipc: add sock dump " richard.alpe
@ 2014-09-12 21:10   ` David Miller
  2014-09-15  7:55     ` Richard Alpe
  0 siblings, 1 reply; 24+ messages in thread
From: David Miller @ 2014-09-12 21:10 UTC (permalink / raw)
  To: richard.alpe; +Cc: netdev, tipc-discussion

From: <richard.alpe@ericsson.com>
Date: Thu, 11 Sep 2014 10:29:17 +0200

> +	list_for_each_entry_from(p, &tsk->publications, pport_list) {
> +		publ = nla_nest_start(skb, TIPC_NLA_SOCK_PUBL);
> +		if (nla_put_u32(skb, TIPC_NLA_PUBL_TYPE, p->type))
> +			goto msg_full;
> +		if (nla_put_u32(skb, TIPC_NLA_PUBL_LOWER, p->lower))
> +			goto msg_full;
> +		if (nla_put_u32(skb, TIPC_NLA_PUBL_UPPER, p->upper))
> +			goto msg_full;
> +		nla_nest_end(skb, publ);
> +	}
> +
> +	*prev_publ = 0;
> +
> +	return 0;
> +
> +msg_full:
> +	*prev_publ = p->key;
> +	nla_nest_cancel(skb, publ);

This restart mechanism is broken.

You can't public nested information this way.

What happens in your code is that if we hit the limit in the middle of
adding the publications, the next time we'll put the same socket into
the netlink message and then the rest of the nested publications.
That's malformed.

You can't just say sometimes you'll partially list the set of nested
attributes in an object, you must public the entire object fully in
the netlink message or skip the object entirely.

I would suggest that you instead size the amount of space you'll
need for at least the first socket being listed, and if NLMSG_GOODSIZE
is insufficient, allocate as much as you will actually need.

Then you put full socket netlink blobs in there, including all nested
attributes, and then stop and reset back the the most recent full socket
published if you run out of space.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next 04/14] tipc: add sock dump to new netlink api
  2014-09-12 21:10   ` David Miller
@ 2014-09-15  7:55     ` Richard Alpe
  2014-09-15  8:51       ` Florian Westphal
  2014-09-15 15:38       ` David Miller
  0 siblings, 2 replies; 24+ messages in thread
From: Richard Alpe @ 2014-09-15  7:55 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, tipc-discussion

On 09/12/2014 11:10 PM, David Miller wrote:
> From: <richard.alpe@ericsson.com>
> Date: Thu, 11 Sep 2014 10:29:17 +0200
>
>> +	list_for_each_entry_from(p, &tsk->publications, pport_list) {
>> +		publ = nla_nest_start(skb, TIPC_NLA_SOCK_PUBL);
>> +		if (nla_put_u32(skb, TIPC_NLA_PUBL_TYPE, p->type))
>> +			goto msg_full;
>> +		if (nla_put_u32(skb, TIPC_NLA_PUBL_LOWER, p->lower))
>> +			goto msg_full;
>> +		if (nla_put_u32(skb, TIPC_NLA_PUBL_UPPER, p->upper))
>> +			goto msg_full;
>> +		nla_nest_end(skb, publ);
>> +	}
>> +
>> +	*prev_publ = 0;
>> +
>> +	return 0;
>> +
>> +msg_full:
>> +	*prev_publ = p->key;
>> +	nla_nest_cancel(skb, publ);
>
> This restart mechanism is broken.
>
> You can't public nested information this way.
>
> What happens in your code is that if we hit the limit in the middle of
> adding the publications, the next time we'll put the same socket into
> the netlink message and then the rest of the nested publications.
> That's malformed.
Yes, that's true.

> You can't just say sometimes you'll partially list the set of nested
> attributes in an object, you must public the entire object fully in
> the netlink message or skip the object entirely.
Ok. I bluntly assumed we could put some reassemble logic in the client 
as the end integrity should still be preserved(?).

> I would suggest that you instead size the amount of space you'll
> need for at least the first socket being listed, and if NLMSG_GOODSIZE
> is insufficient, allocate as much as you will actually need.
>
> Then you put full socket netlink blobs in there, including all nested
> attributes, and then stop and reset back the the most recent full socket
> published if you run out of space.
The amount of publications a socket can have is large (~65 000). Do you 
still think this a viable solution?

I thought about querying socket publications individually. Meaning that 
the user-space tool would have to first list sockets, then ask for there 
publications. This would remove the nested malformation but create some 
overhead and increase the potential port-gone window. What do you think?

Thanks for the review, much appreciated!
/Richard

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next 04/14] tipc: add sock dump to new netlink api
  2014-09-15  7:55     ` Richard Alpe
@ 2014-09-15  8:51       ` Florian Westphal
  2014-09-15 12:35         ` Richard Alpe
  2014-09-15 15:38       ` David Miller
  1 sibling, 1 reply; 24+ messages in thread
From: Florian Westphal @ 2014-09-15  8:51 UTC (permalink / raw)
  To: Richard Alpe; +Cc: David Miller, netdev, tipc-discussion

Richard Alpe <richard.alpe@ericsson.com> wrote:
> >You can't just say sometimes you'll partially list the set of nested
> >attributes in an object, you must public the entire object fully in
> >the netlink message or skip the object entirely.
> Ok. I bluntly assumed we could put some reassemble logic in the
> client as the end integrity should still be preserved(?).
> 
> >I would suggest that you instead size the amount of space you'll
> >need for at least the first socket being listed, and if NLMSG_GOODSIZE
> >is insufficient, allocate as much as you will actually need.
> >
> >Then you put full socket netlink blobs in there, including all nested
> >attributes, and then stop and reset back the the most recent full socket
> >published if you run out of space.
> The amount of publications a socket can have is large (~65 000). Do
> you still think this a viable solution?

I suggest to look at nf_conntrack_netlink.c ctnetlink_dump_table() and
ctnetlink_fill_info().

It should be doing something similar to what you want and it handles
the restarts correctly, i.e., cancels all partial nested attributes
on error and resumes at the beginning of said entry on the next dump.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next 04/14] tipc: add sock dump to new netlink api
  2014-09-15  8:51       ` Florian Westphal
@ 2014-09-15 12:35         ` Richard Alpe
  0 siblings, 0 replies; 24+ messages in thread
From: Richard Alpe @ 2014-09-15 12:35 UTC (permalink / raw)
  To: Florian Westphal; +Cc: David Miller, netdev, tipc-discussion

On 09/15/2014 10:51 AM, Florian Westphal wrote:
> Richard Alpe <richard.alpe@ericsson.com> wrote:
>>> You can't just say sometimes you'll partially list the set of nested
>>> attributes in an object, you must public the entire object fully in
>>> the netlink message or skip the object entirely.
>> Ok. I bluntly assumed we could put some reassemble logic in the
>> client as the end integrity should still be preserved(?).
>>
>>> I would suggest that you instead size the amount of space you'll
>>> need for at least the first socket being listed, and if NLMSG_GOODSIZE
>>> is insufficient, allocate as much as you will actually need.
>>>
>>> Then you put full socket netlink blobs in there, including all nested
>>> attributes, and then stop and reset back the the most recent full socket
>>> published if you run out of space.
>> The amount of publications a socket can have is large (~65 000). Do
>> you still think this a viable solution?
>
> I suggest to look at nf_conntrack_netlink.c ctnetlink_dump_table() and
> ctnetlink_fill_info().
>
> It should be doing something similar to what you want and it handles
> the restarts correctly, i.e., cancels all partial nested attributes
> on error and resumes at the beginning of said entry on the next dump.
Thanks. In the case of ctnetlink_fill_info() it looks to me as if a set 
of nested attributes is sure to fit inside a new message and that you 
only have to cancel if the accumulation of multiple top level entities 
along where their nested attributes fills the message(?).

The problem in this case isn't solely the listing of a large amount of 
publication attributes. The problem is that there can be an arbitrary 
amount of sockets with an arbitrary amount of associated (nested) 
publications (~65 000 max).

I "solved" this by nesting as many complete publications as possible for 
each socket. This "works" but as David points out the nested publication 
data for a specific socket might or might not be complete. This is 
solely indicated by the NLMSG_DONE flag, forcing the client to know this 
and reassemble.

I'm now considering splitting the socket and publication listing so that 
the client will have to ask for a list of sockets and then ask for there 
associated publications individually. This would reduce the complexity 
on the kernel side but it may introduce some additional overhead when 
the socket count is high. On the other hand it opens the opportunity for 
client to only ask for publications.

Cheers
Richard

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next 04/14] tipc: add sock dump to new netlink api
  2014-09-15  7:55     ` Richard Alpe
  2014-09-15  8:51       ` Florian Westphal
@ 2014-09-15 15:38       ` David Miller
  2014-09-15 16:35         ` Jon Maloy
  2014-09-23 11:12         ` Richard Alpe
  1 sibling, 2 replies; 24+ messages in thread
From: David Miller @ 2014-09-15 15:38 UTC (permalink / raw)
  To: richard.alpe; +Cc: netdev, tipc-discussion

From: Richard Alpe <richard.alpe@ericsson.com>
Date: Mon, 15 Sep 2014 09:55:24 +0200

> The amount of publications a socket can have is large (~65 000). Do
> you still think this a viable solution?

Then maybe you want to have a completely separate netlink operation to
dump the publications, the request would provide a key saying which
socket's publications to dump.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* RE: [PATCH net-next 04/14] tipc: add sock dump to new netlink api
  2014-09-15 15:38       ` David Miller
@ 2014-09-15 16:35         ` Jon Maloy
  2014-09-23 11:12         ` Richard Alpe
  1 sibling, 0 replies; 24+ messages in thread
From: Jon Maloy @ 2014-09-15 16:35 UTC (permalink / raw)
  To: David Miller, Richard Alpe; +Cc: netdev, tipc-discussion



> -----Original Message-----
> From: netdev-owner@vger.kernel.org [mailto:netdev-
> owner@vger.kernel.org] On Behalf Of David Miller
> Sent: September-15-14 11:39 AM
> To: Richard Alpe
> Cc: netdev@vger.kernel.org; tipc-discussion@lists.sourceforge.net
> Subject: Re: [PATCH net-next 04/14] tipc: add sock dump to new netlink api
> 
> From: Richard Alpe <richard.alpe@ericsson.com>
> Date: Mon, 15 Sep 2014 09:55:24 +0200
> 
> > The amount of publications a socket can have is large (~65 000). Do
> > you still think this a viable solution?
> 
> Then maybe you want to have a completely separate netlink operation to
> dump the publications, the request would provide a key saying which
> socket's publications to dump.

A compromise could be to list a fix maximum number (100?) of publications
 that cover all "normal" cases, and return a hint indicating that there is
more if this was not enough. For 99% of the sockets this would be enough, 
and for the remaining ones the tool would have to use the second operation
to make the listing complete.

///jon

> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in the body
> of a message to majordomo@vger.kernel.org More majordomo info at
> http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next 04/14] tipc: add sock dump to new netlink api
  2014-09-15 15:38       ` David Miller
  2014-09-15 16:35         ` Jon Maloy
@ 2014-09-23 11:12         ` Richard Alpe
  2014-09-23 15:37           ` David Miller
  1 sibling, 1 reply; 24+ messages in thread
From: Richard Alpe @ 2014-09-23 11:12 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, tipc-discussion

On 09/15/2014 05:38 PM, David Miller wrote:
> From: Richard Alpe <richard.alpe@ericsson.com>
> Date: Mon, 15 Sep 2014 09:55:24 +0200
>
>> The amount of publications a socket can have is large (~65 000). Do
>> you still think this a viable solution?
>
> Then maybe you want to have a completely separate netlink operation to
> dump the publications, the request would provide a key saying which
> socket's publications to dump.
Yes, that would be a nice thing to have.

Ideally I would like to use the existing dump framework .dumpit 
(netlink_dump_start()) but I can't figure out a way to pass the socket 
for which to dump publications. I really don't want to reinvent the 
dumping mechanism. Any suggestions?

Regards
Richard

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH net-next 04/14] tipc: add sock dump to new netlink api
  2014-09-23 11:12         ` Richard Alpe
@ 2014-09-23 15:37           ` David Miller
  0 siblings, 0 replies; 24+ messages in thread
From: David Miller @ 2014-09-23 15:37 UTC (permalink / raw)
  To: richard.alpe; +Cc: netdev, tipc-discussion

From: Richard Alpe <richard.alpe@ericsson.com>
Date: Tue, 23 Sep 2014 13:12:47 +0200

> Ideally I would like to use the existing dump framework .dumpit
> (netlink_dump_start()) but I can't figure out a way to pass the socket
> for which to dump publications. I really don't want to reinvent the
> dumping mechanism. Any suggestions?

Look at inet_diag, and how the dump netlink request passes in a key
to match upon.

The key is of the form: include/uapi/linux/inet_diag.h:inet_diag_req{,_v2}

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2014-09-23 15:37 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-11  8:29 [PATCH net-next 00/14] tipc: new netlink API richard.alpe
2014-09-11  8:29 ` [PATCH net-next 01/14] tipc: add bearer disable/enable to new netlink api richard.alpe
2014-09-12 21:07   ` David Miller
2014-09-11  8:29 ` [PATCH net-next 02/14] tipc: add bearer get/dump " richard.alpe
2014-09-11  8:29 ` [PATCH net-next 03/14] tipc: add bearer set " richard.alpe
2014-09-11  8:29 ` [PATCH net-next 04/14] tipc: add sock dump " richard.alpe
2014-09-12 21:10   ` David Miller
2014-09-15  7:55     ` Richard Alpe
2014-09-15  8:51       ` Florian Westphal
2014-09-15 12:35         ` Richard Alpe
2014-09-15 15:38       ` David Miller
2014-09-15 16:35         ` Jon Maloy
2014-09-23 11:12         ` Richard Alpe
2014-09-23 15:37           ` David Miller
2014-09-11  8:29 ` [PATCH net-next 05/14] tipc: add link get/dump " richard.alpe
2014-09-11  8:29 ` [PATCH net-next 06/14] tipc: add link set " richard.alpe
2014-09-11  8:29 ` [PATCH net-next 07/14] tipc: add link stat reset " richard.alpe
2014-09-11  8:29 ` [PATCH net-next 08/14] tipc: add media get/dump " richard.alpe
2014-09-11  8:29 ` [PATCH net-next 09/14] tipc: add media set " richard.alpe
2014-09-11  8:29 ` [PATCH net-next 10/14] tipc: add node get/dump " richard.alpe
2014-09-11  8:29 ` [PATCH net-next 11/14] tipc: add net dump " richard.alpe
2014-09-11  8:29 ` [PATCH net-next 12/14] tipc: add net set " richard.alpe
2014-09-11  8:29 ` [PATCH net-next 13/14] tipc: add name table dump " richard.alpe
2014-09-11  8:29 ` [PATCH net-next 14/14] tipc: remove old ASCII netlink API richard.alpe

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.