netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch net-next-2.6 1/4] net: extend netlink interface to handle generic slave management
@ 2011-02-11 15:21 Jiri Pirko
  2011-02-11 15:22 ` [patch iproute2 2/4] implement slave management operations Jiri Pirko
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Jiri Pirko @ 2011-02-11 15:21 UTC (permalink / raw)
  To: netdev; +Cc: davem, shemminger, kaber, fubar

Drivers like bridge and bonding uses their own way to manipulate with
underlink devices. This is an attempt to introduce common interface using
netlink.

Signed-off-by: Jiri Pirko <jpirko@redhat.com>
---
 include/linux/if_link.h   |   13 +++++++
 include/linux/netdevice.h |   22 ++++++++++++
 net/core/rtnetlink.c      |   81 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 116 insertions(+), 0 deletions(-)

diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index f4a2e6b..48a5f95 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -136,6 +136,9 @@ enum {
 	IFLA_PORT_SELF,
 	IFLA_AF_SPEC,
 	IFLA_GROUP,		/* Group the device belongs to */
+	IFLA_SLAVE_LIST,
+	IFLA_SLAVE_ADD,
+	IFLA_SLAVE_DEL,
 	__IFLA_MAX
 };
 
@@ -379,4 +382,14 @@ struct ifla_port_vsi {
 	__u8 pad[3];
 };
 
+/* Slave devices management section */
+
+enum {
+	IFLA_SLAVE_UNSPEC,
+	IFLA_SLAVE_DEV,
+	__IFLA_SLAVE_MAX,
+};
+
+#define IFLA_SLAVE_MAX (__IFLA_SLAVE_MAX - 1)
+
 #endif /* _LINUX_IF_LINK_H */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c7d7074..844cb85 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -783,6 +783,21 @@ struct netdev_tc_txq {
  *	Set hardware filter for RFS.  rxq_index is the target queue index;
  *	flow_id is a flow ID to be passed to rps_may_expire_flow() later.
  *	Return the filter ID on success, or a negative error code.
+ *
+ *	Slave management functions (for bridge, bonding, etc). User should
+ *	make sure that slave list doesn't change within rtnl_lock.
+ * int (*ndo_add_slave)(struct net_device *dev, struct net_device *slave_dev);
+ *	Called to make another netdev an underlink.
+ *
+ * int (*ndo_del_slave)(struct net_device *dev, struct net_device *slave_dev);
+ *	Called to release previously enslaved netdev.
+ *
+ * int (*ndo_get_slave_count)(const struct net_device *dev);
+ *	Called to get number of enslaved devices.
+ *
+ * struct net_device * (*ndo_get_slave)(const struct net_device *dev,
+ *					int slave_index);
+ *	Called to get slave device by it's index.
  */
 #define HAVE_NET_DEVICE_OPS
 struct net_device_ops {
@@ -862,6 +877,13 @@ struct net_device_ops {
 						     u16 rxq_index,
 						     u32 flow_id);
 #endif
+	int			(*ndo_add_slave)(struct net_device *dev,
+						 struct net_device *slave_dev);
+	int			(*ndo_del_slave)(struct net_device *dev,
+						 struct net_device *slave_dev);
+	int			(*ndo_get_slave_count)(const struct net_device *dev);
+	struct net_device *	(*ndo_get_slave)(const struct net_device *dev,
+						 int slave_index);
 };
 
 /*
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index da0fe45..1402a3f 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -739,6 +739,20 @@ static size_t rtnl_port_size(const struct net_device *dev)
 		return port_self_size;
 }
 
+static size_t rtnl_slave_list_size(const struct net_device *dev)
+{
+	size_t slave_size = nla_total_size(sizeof(struct nlattr)) +
+			    nla_total_size(4);
+	size_t slave_list_size = nla_total_size(sizeof(struct nlattr));
+	int slave_count;
+
+	if (!dev->netdev_ops->ndo_get_slave_count ||
+	    !dev->netdev_ops->ndo_get_slave)
+		return 0;
+	slave_count = dev->netdev_ops->ndo_get_slave_count(dev);
+	return slave_list_size + slave_count * slave_size;
+}
+
 static noinline size_t if_nlmsg_size(const struct net_device *dev)
 {
 	return NLMSG_ALIGN(sizeof(struct ifinfomsg))
@@ -760,6 +774,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev)
 	       + nla_total_size(4) /* IFLA_NUM_VF */
 	       + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */
 	       + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
+	       + rtnl_slave_list_size(dev) /* IFLA_SLAVE_LIST */
 	       + rtnl_link_get_size(dev) /* IFLA_LINKINFO */
 	       + rtnl_link_get_af_size(dev); /* IFLA_AF_SPEC */
 }
@@ -839,6 +854,39 @@ static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev)
 	return 0;
 }
 
+static int rtnl_slave_list_fill(struct sk_buff *skb, struct net_device *dev)
+{
+	int slave_count;
+	int i;
+	struct nlattr *slave_list;
+
+	if (!dev->netdev_ops->ndo_get_slave_count ||
+	    !dev->netdev_ops->ndo_get_slave)
+		return 0;
+	slave_count = dev->netdev_ops->ndo_get_slave_count(dev);
+	slave_list = nla_nest_start(skb, IFLA_SLAVE_LIST);
+	if (!slave_list)
+		return -EMSGSIZE;
+	for (i = 0; i < slave_count; i++) {
+		struct net_device *slave_dev;
+
+		slave_dev = dev->netdev_ops->ndo_get_slave(dev, i);
+		if (!slave_dev) {
+			nla_nest_cancel(skb, slave_list);
+			goto nla_put_failure;
+		}
+		NLA_PUT_U32(skb, IFLA_SLAVE_DEV, slave_dev->ifindex);
+	}
+	nla_nest_end(skb, slave_list);
+
+	return 0;
+
+nla_put_failure:
+	nla_nest_cancel(skb, slave_list);
+	return -EMSGSIZE;
+
+}
+
 static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 			    int type, u32 pid, u32 seq, u32 change,
 			    unsigned int flags)
@@ -953,6 +1001,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 	if (rtnl_port_fill(skb, dev))
 		goto nla_put_failure;
 
+	if (rtnl_slave_list_fill(skb, dev))
+		goto nla_put_failure;
+
 	if (dev->rtnl_link_ops) {
 		if (rtnl_link_fill(skb, dev) < 0)
 			goto nla_put_failure;
@@ -1047,6 +1098,8 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
 	[IFLA_VF_PORTS]		= { .type = NLA_NESTED },
 	[IFLA_PORT_SELF]	= { .type = NLA_NESTED },
 	[IFLA_AF_SPEC]		= { .type = NLA_NESTED },
+	[IFLA_SLAVE_ADD]	= { .type = NLA_U32 },
+	[IFLA_SLAVE_DEL]	= { .type = NLA_U32 },
 };
 EXPORT_SYMBOL(ifla_policy);
 
@@ -1392,6 +1445,34 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
 			modified = 1;
 		}
 	}
+
+	if (tb[IFLA_SLAVE_ADD]) {
+		int ifindex = nla_get_u32(tb[IFLA_SLAVE_ADD]);
+		struct net_device *slave_dev;
+
+		err = -EOPNOTSUPP;
+		if (ops->ndo_add_slave) {
+			slave_dev = __dev_get_by_index(dev_net(dev), ifindex);
+			err = ops->ndo_add_slave(dev, slave_dev);
+		}
+		if (err < 0)
+			goto errout;
+		modified = 1;
+	}
+
+	if (tb[IFLA_SLAVE_DEL]) {
+		int ifindex = nla_get_u32(tb[IFLA_SLAVE_DEL]);
+		struct net_device *slave_dev;
+
+		err = -EOPNOTSUPP;
+		if (ops->ndo_del_slave) {
+			slave_dev = __dev_get_by_index(dev_net(dev), ifindex);
+			err = ops->ndo_del_slave(dev, slave_dev);
+		}
+		if (err < 0)
+			goto errout;
+		modified = 1;
+	}
 	err = 0;
 
 errout:
-- 
1.7.3.4


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

end of thread, other threads:[~2011-03-01  6:19 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-02-11 15:21 [patch net-next-2.6 1/4] net: extend netlink interface to handle generic slave management Jiri Pirko
2011-02-11 15:22 ` [patch iproute2 2/4] implement slave management operations Jiri Pirko
2011-02-11 15:27   ` Jiri Pirko
2011-02-11 15:22 ` [patch net-next-2.6 3/4] bond: " Jiri Pirko
2011-02-11 17:19   ` Jay Vosburgh
2011-02-11 17:51     ` Jiri Pirko
2011-02-12 13:16   ` Nicolas de Pesloüan
2011-02-12 13:20     ` Jiri Pirko
2011-02-11 15:23 ` [patch net-next-2.6 4/4] bridge: " Jiri Pirko
2011-02-28 22:17   ` Stephen Hemminger
2011-02-28 22:45     ` Stephen Hemminger
2011-03-01  6:19       ` Jiri Pirko
2011-02-11 15:48 ` [patch net-next-2.6 1/4] net: extend netlink interface to handle generic slave management Patrick McHardy
2011-02-11 17:40   ` Jiri Pirko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).