rtnl: allow to create device with IFLA_LINK_NETNSID set
authorNicolas Dichtel <nicolas.dichtel@6wind.com>
Thu, 15 Jan 2015 14:11:18 +0000 (15:11 +0100)
committerDavid S. Miller <davem@davemloft.net>
Mon, 19 Jan 2015 19:32:03 +0000 (14:32 -0500)
This patch adds the ability to create a netdevice in a specified netns and
then move it into the final netns. In fact, it allows to have a symetry between
get and set rtnl messages.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/rtnetlink.c

index bd6370f0cb3181c60f08efd2abb2ec11b277b9c8..a12eecc0f97631df3888a3dd94ba73fd0632d15f 100644 (file)
@@ -1248,6 +1248,7 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
        [IFLA_PHYS_PORT_ID]     = { .type = NLA_BINARY, .len = MAX_PHYS_ITEM_ID_LEN },
        [IFLA_CARRIER_CHANGES]  = { .type = NLA_U32 },  /* ignored */
        [IFLA_PHYS_SWITCH_ID]   = { .type = NLA_BINARY, .len = MAX_PHYS_ITEM_ID_LEN },
+       [IFLA_LINK_NETNSID]     = { .type = NLA_S32 },
 };
 
 static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
@@ -2021,7 +2022,7 @@ replay:
                struct nlattr *slave_attr[m_ops ? m_ops->slave_maxtype + 1 : 0];
                struct nlattr **data = NULL;
                struct nlattr **slave_data = NULL;
-               struct net *dest_net;
+               struct net *dest_net, *link_net = NULL;
 
                if (ops) {
                        if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) {
@@ -2127,7 +2128,18 @@ replay:
                if (IS_ERR(dest_net))
                        return PTR_ERR(dest_net);
 
-               dev = rtnl_create_link(dest_net, ifname, name_assign_type, ops, tb);
+               if (tb[IFLA_LINK_NETNSID]) {
+                       int id = nla_get_s32(tb[IFLA_LINK_NETNSID]);
+
+                       link_net = get_net_ns_by_id(dest_net, id);
+                       if (!link_net) {
+                               err =  -EINVAL;
+                               goto out;
+                       }
+               }
+
+               dev = rtnl_create_link(link_net ? : dest_net, ifname,
+                                      name_assign_type, ops, tb);
                if (IS_ERR(dev)) {
                        err = PTR_ERR(dev);
                        goto out;
@@ -2155,9 +2167,16 @@ replay:
                        }
                }
                err = rtnl_configure_link(dev, ifm);
-               if (err < 0)
+               if (err < 0) {
                        unregister_netdevice(dev);
+                       goto out;
+               }
+
+               if (link_net)
+                       err = dev_change_net_namespace(dev, dest_net, ifname);
 out:
+               if (link_net)
+                       put_net(link_net);
                put_net(dest_net);
                return err;
        }