aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
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 /net/core
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>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/rtnetlink.c43
1 files changed, 43 insertions, 0 deletions
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