diff options
author | Jiri Pirko <jpirko@redhat.com> | 2011-02-13 05:15:37 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-02-13 19:58:39 -0500 |
commit | fbaec0ea54f7d9131891ff98744e82c073ce03b1 (patch) | |
tree | d0622d38a51b7e4a1e853338e7cbd954d3977cf2 /net/core | |
parent | f45437efff460aa033978180da88229c5fc68455 (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.c | 43 |
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 | ||
1182 | static 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 | |||
1181 | static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | 1217 | static 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 | ||