aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Pirko <jpirko@redhat.com>2011-02-13 05:15:37 -0500
committerDavid S. Miller <davem@davemloft.net>2011-02-13 19:58:39 -0500
commitfbaec0ea54f7d9131891ff98744e82c073ce03b1 (patch)
treed0622d38a51b7e4a1e853338e7cbd954d3977cf2
parentf45437efff460aa033978180da88229c5fc68455 (diff)
rtnetlink: implement setting of master device
This patch allows userspace to enslave/release slave devices via netlink interface using IFLA_MASTER. This introduces generic way to add/remove underling devices. Signed-off-by: Jiri Pirko <jpirko@redhat.com> Acked-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netdevice.h12
-rw-r--r--net/core/rtnetlink.c43
2 files changed, 55 insertions, 0 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 5a42b1003767..d08ef6538579 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -783,6 +783,14 @@ struct netdev_tc_txq {
783 * Set hardware filter for RFS. rxq_index is the target queue index; 783 * Set hardware filter for RFS. rxq_index is the target queue index;
784 * flow_id is a flow ID to be passed to rps_may_expire_flow() later. 784 * flow_id is a flow ID to be passed to rps_may_expire_flow() later.
785 * Return the filter ID on success, or a negative error code. 785 * Return the filter ID on success, or a negative error code.
786 *
787 * Slave management functions (for bridge, bonding, etc). User should
788 * call netdev_set_master() to set dev->master properly.
789 * int (*ndo_add_slave)(struct net_device *dev, struct net_device *slave_dev);
790 * Called to make another netdev an underling.
791 *
792 * int (*ndo_del_slave)(struct net_device *dev, struct net_device *slave_dev);
793 * Called to release previously enslaved netdev.
786 */ 794 */
787#define HAVE_NET_DEVICE_OPS 795#define HAVE_NET_DEVICE_OPS
788struct net_device_ops { 796struct net_device_ops {
@@ -862,6 +870,10 @@ struct net_device_ops {
862 u16 rxq_index, 870 u16 rxq_index,
863 u32 flow_id); 871 u32 flow_id);
864#endif 872#endif
873 int (*ndo_add_slave)(struct net_device *dev,
874 struct net_device *slave_dev);
875 int (*ndo_del_slave)(struct net_device *dev,
876 struct net_device *slave_dev);
865}; 877};
866 878
867/* 879/*
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index da0fe457c858..49f7ea5b4c75 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1036,6 +1036,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
1036 [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, 1036 [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) },
1037 [IFLA_MTU] = { .type = NLA_U32 }, 1037 [IFLA_MTU] = { .type = NLA_U32 },
1038 [IFLA_LINK] = { .type = NLA_U32 }, 1038 [IFLA_LINK] = { .type = NLA_U32 },
1039 [IFLA_MASTER] = { .type = NLA_U32 },
1039 [IFLA_TXQLEN] = { .type = NLA_U32 }, 1040 [IFLA_TXQLEN] = { .type = NLA_U32 },
1040 [IFLA_WEIGHT] = { .type = NLA_U32 }, 1041 [IFLA_WEIGHT] = { .type = NLA_U32 },
1041 [IFLA_OPERSTATE] = { .type = NLA_U8 }, 1042 [IFLA_OPERSTATE] = { .type = NLA_U8 },
@@ -1178,6 +1179,41 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr *attr)
1178 return err; 1179 return err;
1179} 1180}
1180 1181
1182static int do_set_master(struct net_device *dev, int ifindex)
1183{
1184 struct net_device *master_dev;
1185 const struct net_device_ops *ops;
1186 int err;
1187
1188 if (dev->master) {
1189 if (dev->master->ifindex == ifindex)
1190 return 0;
1191 ops = dev->master->netdev_ops;
1192 if (ops->ndo_del_slave) {
1193 err = ops->ndo_del_slave(dev->master, dev);
1194 if (err)
1195 return err;
1196 } else {
1197 return -EOPNOTSUPP;
1198 }
1199 }
1200
1201 if (ifindex) {
1202 master_dev = __dev_get_by_index(dev_net(dev), ifindex);
1203 if (!master_dev)
1204 return -EINVAL;
1205 ops = master_dev->netdev_ops;
1206 if (ops->ndo_add_slave) {
1207 err = ops->ndo_add_slave(master_dev, dev);
1208 if (err)
1209 return err;
1210 } else {
1211 return -EOPNOTSUPP;
1212 }
1213 }
1214 return 0;
1215}
1216
1181static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, 1217static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
1182 struct nlattr **tb, char *ifname, int modified) 1218 struct nlattr **tb, char *ifname, int modified)
1183{ 1219{
@@ -1301,6 +1337,13 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
1301 goto errout; 1337 goto errout;
1302 } 1338 }
1303 1339
1340 if (tb[IFLA_MASTER]) {
1341 err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]));
1342 if (err)
1343 goto errout;
1344 modified = 1;
1345 }
1346
1304 if (tb[IFLA_TXQLEN]) 1347 if (tb[IFLA_TXQLEN])
1305 dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); 1348 dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
1306 1349