netns: Delete virtual interfaces during namespace cleanup
Subsystems (3)
PATCH 1/1 netns: Delete virtual interfaces during namespace cleanup
When physical devices are inside of network namespace and that network namespace terminates we can not make them go away. We have to keep them and moving them to the initial network namespace is the best we can do.
For virtual devices left in a network namespace that is exiting we have no need to preserve them and we now have the infrastructure that allows us to delete them. So delete virtual devices when we exit a network namespace. Keeping the necessary user space clean up after a network namespace exits much more tractable.
This patch removes much of the need for user space clean up code to run after a network namespace exits.
--- net/core/dev.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-)
net/core/dev.c +6 -0
@@ -4844,6 +4844,12 @@ static void __net_exit default_device_exit(struct net *net)if (dev->features &NETIF_F_NETNS_LOCAL )continue ; +/* Delete virtual devices */ +if (dev->rtnl_link_ops && dev->rtnl_link_ops->dellink) { + dev->rtnl_link_ops->dellink (dev); +continue ; + } +/* Push remaing network devices to init_net */ snprintf (fb_name,IFNAMSIZ ,"dev%d" , dev->ifindex); err =dev_change_net_namespace (dev, &init_net, fb_name);
Signature · 1 line
1.5.3.rc6.17.g1911
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/1 net: Support specifying the network namespace upon device creation.
There is no good reason to not support userspace specifying the network namespace during device creation and it seems a handy thing to do.
We have to be a little extra careful in this case to ensure that the network namespace exists through the point where we call register_netdevice.
In addition we need to pass the network namespace to the rtnl_link_ops.newlink method so we can properly create the new device in another namespace and have it be a vlan device of a device in our current network namespace.
In summary this patch makes ip link add somename netns NNN type sometype do the obvious thing instead of ignoring the network namespace parameter.
--- drivers/net/macvlan.c | 4 ++-- drivers/net/veth.c | 5 +++-- include/net/rtnetlink.h | 3 ++- net/8021q/vlan_netlink.c | 4 ++-- net/core/rtnetlink.c | 17 ++++++++++++++++- 5 files changed, 25 insertions(+), 8 deletions(-)
drivers/net/macvlan.c +2 -2
@@ -416,7 +416,7 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])return 0 ; } -static int macvlan_newlink (struct net_device *dev, +static int macvlan_newlink (struct net *net,struct net_device *dev,struct nlattr *tb[],struct nlattr *data[]) {struct macvlan_dev *vlan =netdev_priv (dev);
@@ -427,7 +427,7 @@ static int macvlan_newlink(struct net_device *dev,if (!tb[IFLA_LINK ])return -EINVAL ; - lowerdev =__dev_get_by_index (dev_net (dev),nla_get_u32 (tb[IFLA_LINK ])); + lowerdev =__dev_get_by_index (net,nla_get_u32 (tb[IFLA_LINK ]));if (lowerdev ==NULL )return -ENODEV ;
drivers/net/veth.c +3 -2
@@ -335,7 +335,7 @@ static int veth_validate(struct nlattr *tb[], struct nlattr *data[])static struct rtnl_link_ops veth_link_ops; -static int veth_newlink (struct net_device *dev, +static int veth_newlink (struct net *net,struct net_device *dev,struct nlattr *tb[],struct nlattr *data[]) {int err;
@@ -375,7 +375,7 @@ static int veth_newlink(struct net_device *dev,else snprintf (ifname,IFNAMSIZ ,DRV_NAME "%%d" ); - peer =rtnl_create_link (dev_net (dev), ifname, &veth_link_ops, tbp); + peer =rtnl_create_link (net, ifname, &veth_link_ops, tbp);if (IS_ERR (peer))return PTR_ERR (peer);
@@ -383,6 +383,7 @@ static int veth_newlink(struct net_device *dev,random_ether_addr (peer->dev_addr); err =register_netdevice (peer); +put_net (peer->nd_net);if (err <0 ) goto err_register_peer;
include/net/rtnetlink.h +2 -1
@@ -55,7 +55,8 @@ struct rtnl_link_ops {int (*validate)(struct nlattr *tb[],struct nlattr *data[]); -int (*newlink)(struct net_device *dev, +int (*newlink)(struct net *net, +struct net_device *dev,struct nlattr *tb[],struct nlattr *data[]); int (*changelink)(struct net_device *dev,
net/8021q/vlan_netlink.c +2 -2
@@ -100,7 +100,7 @@ static int vlan_changelink(struct net_device *dev,return 0 ; } -static int vlan_newlink (struct net_device *dev, +static int vlan_newlink (struct net *net,struct net_device *dev,struct nlattr *tb[],struct nlattr *data[]) {struct vlan_dev_info *vlan =vlan_dev_info (dev);
@@ -112,7 +112,7 @@ static int vlan_newlink(struct net_device *dev,if (!tb[IFLA_LINK ])return -EINVAL ; - real_dev =__dev_get_by_index (dev_net (dev),nla_get_u32 (tb[IFLA_LINK ])); + real_dev =__dev_get_by_index (net,nla_get_u32 (tb[IFLA_LINK ]));if (!real_dev)return -ENODEV ;
net/core/rtnetlink.c +16 -1
@@ -1002,6 +1002,19 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname, goto err_free; } +/* To support userspace specifying a network namespace during +* device creation we grab the network namespace here and hold +* it until just after register_netdevice to prevent races. +*/ +if (!tb[IFLA_NET_NS_PID ]) +get_net (net); +else { + net =get_net_ns_by_pid (nla_get_u32 (tb[IFLA_NET_NS_PID ])); +if (IS_ERR (net)) { + err =PTR_ERR (net); + goto err_free; + } + }dev_net_set (dev, net); dev->rtnl_link_ops = ops;
@@ -1150,10 +1163,12 @@ replay:if (IS_ERR (dev)) err =PTR_ERR (dev);else if (ops->newlink) - err = ops->newlink (dev, tb, data); + err = ops->newlink (net, dev, tb, data);else err =register_netdevice (dev); +if (!IS_ERR (dev)) +put_net (dev->nd_net);if (err <0 && !IS_ERR (dev))free_netdev (dev);return err;
Signature · 1 line
1.5.3.rc6.17.g1911
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH] net: Support specifying the network namespace upon device creation.
Quoted 105 lines · Eric W. Biederman
There is no good reason to not support userspace specifying the network namespace during device creation and it seems a handy thing to do.
We have to be a little extra careful in this case to ensure that the network namespace exists through the point where we call
register_netdevice.In addition we need to pass the network namespace to the rtnl_link_ops.newlink method so we can properly create the new device in another namespace and have it be a vlan device of a device in our current network namespace.
In summary this patch makes ip link add somename netns NNN type sometype do the obvious thing instead of ignoring the network namespace parameter.
--- drivers/net/macvlan.c | 4 ++-- drivers/net/veth.c | 5 +++-- include/net/rtnetlink.h | 3 ++- net/8021q/vlan_netlink.c | 4 ++-- net/core/rtnetlink.c | 17 ++++++++++++++++- 5 files changed, 25 insertions(+), 8 deletions(-)drivers/net/macvlan.c +2
-2@@ -416,7 +416,7 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])return 0 ; } -static int macvlan_newlink (struct net_device *dev, +static int macvlan_newlink (struct net *net,struct net_device *dev,struct nlattr *tb[],struct nlattr *data[]) {struct macvlan_dev *vlan =netdev_priv (dev);@@ -427,7 +427,7 @@ static int macvlan_newlink(struct net_device *dev,if (!tb[IFLA_LINK ])return -EINVAL ; - lowerdev =__dev_get_by_index (dev_net (dev),nla_get_u32 (tb[IFLA_LINK ])); + lowerdev =__dev_get_by_index (net,nla_get_u32 (tb[IFLA_LINK ]));if (lowerdev ==NULL )return -ENODEV ;drivers/net/veth.c +3
-2@@ -335,7 +335,7 @@ static int veth_validate(struct nlattr *tb[], struct nlattr *data[])static struct rtnl_link_ops veth_link_ops; -static int veth_newlink (struct net_device *dev, +static int veth_newlink (struct net *net,struct net_device *dev,struct nlattr *tb[],struct nlattr *data[]) {int err;@@ -375,7 +375,7 @@ static int veth_newlink(struct net_device *dev,else snprintf (ifname,IFNAMSIZ ,DRV_NAME "%%d" ); - peer =rtnl_create_link (dev_net (dev), ifname, &veth_link_ops, tbp); + peer =rtnl_create_link (net, ifname, &veth_link_ops, tbp);if (IS_ERR (peer))return PTR_ERR (peer);@@ -383,6 +383,7 @@ static int veth_newlink(struct net_device *dev,random_ether_addr (peer->dev_addr); err =register_netdevice (peer); +put_net (peer->nd_net);if (err <0 ) goto err_register_peer;include/net/rtnetlink.h +2
-1@@ -55,7 +55,8 @@ struct rtnl_link_ops {int (*validate)(struct nlattr *tb[],struct nlattr *data[]); -int (*newlink)(struct net_device *dev, +int (*newlink)(struct net *net, +struct net_device *dev,struct nlattr *tb[],struct nlattr *data[]); int (*changelink)(struct net_device *dev,net/8021q/vlan_netlink.c +1
-1@@ -100,7 +100,7 @@ static int vlan_changelink(struct net_device *dev,return 0 ; } -static int vlan_newlink (struct net_device *dev, +static int vlan_newlink (struct net *net,struct net_device *dev,struct nlattr *tb[],struct nlattr *data[]) {struct vlan_dev_info *vlan =vlan_dev_info (dev);
net/8021q/vlan_netlink.c static int vlan_newlink(struct net_device *dev, · line 115
Quoted 5 lines
net/8021q/vlan_netlink.c +1
-1@@ -112,7 +112,7 @@ static int vlan_newlink(struct net_device *dev,if (!tb[IFLA_LINK ])return -EINVAL ; - real_dev =__dev_get_by_index (dev_net (dev),nla_get_u32 (tb[IFLA_LINK ])); + real_dev =__dev_get_by_index (net,nla_get_u32 (tb[IFLA_LINK ]));
Hmm, if the macvlan is created inside a namespace, the network namespace specified in the parameter function will not be the namespace where belongs IFLA_LINK and the __dev_get_by_index will fail, no ?
Quoted 28 lines
net/8021q/vlan_netlink.c +0
-0if (!real_dev)return -ENODEV ;net/core/rtnetlink.c +13
-0@@ -1002,6 +1002,19 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname, goto err_free; } +/* To support userspace specifying a network namespace during +* device creation we grab the network namespace here and hold +* it until just after register_netdevice to prevent races. +*/ +if (!tb[IFLA_NET_NS_PID ]) +get_net (net); +else { + net =get_net_ns_by_pid (nla_get_u32 (tb[IFLA_NET_NS_PID ])); +if (IS_ERR (net)) { + err =PTR_ERR (net); + goto err_free; + } + }dev_net_set (dev, net); dev->rtnl_link_ops = ops;
net/core/rtnetlink.c replay: · line 1171
Quoted 10 lines
net/core/rtnetlink.c +3
-1@@ -1150,10 +1163,12 @@ replay:if (IS_ERR (dev)) err =PTR_ERR (dev);else if (ops->newlink) - err = ops->newlink (dev, tb, data); + err = ops->newlink (net, dev, tb, data);else err =register_netdevice (dev); +if (!IS_ERR (dev)) +put_net (dev->nd_net);
If there is an error in ops->newlink or register_netdevice, we will exit without releasing the net refcount.
Quoted 3 lines
net/core/rtnetlink.c +0
-0if (err <0 && !IS_ERR (dev))free_netdev (dev);return err;
A message that is not in the archive (sent off-list or not yet received): 48EB541A.5070306-NmTC/[email protected]
Re: [PATCH] net: Support specifying the network namespace upon device creation.
Quoted 109 lines · Daniel Lezcano
drivers/net/macvlan.c static int macvlan_validate(struct nlattr *tb[], struct
Quoted 30 lines · Eric W. Biederman
There is no good reason to not support userspace specifying the network namespace during device creation and it seems a handy thing to do.
We have to be a little extra careful in this case to ensure that the network namespace exists through the point where we call
register_netdevice.In addition we need to pass the network namespace to the rtnl_link_ops.newlink method so we can properly create the new device in another namespace and have it be a vlan device of a device in our current network namespace.
In summary this patch makes ip link add somename netns NNN type sometype do the obvious thing instead of ignoring the network namespace parameter.
--- drivers/net/macvlan.c | 4 ++-- drivers/net/veth.c | 5 +++-- include/net/rtnetlink.h | 3 ++- net/8021q/vlan_netlink.c | 4 ++-- net/core/rtnetlink.c | 17 ++++++++++++++++- 5 files changed, 25 insertions(+), 8 deletions(-)drivers/net/macvlan.c +0
-0@@ -416,7 +416,7 @@ static int macvlan_validate(struct nlattr *tb[], structnlattr *data[])
drivers/net/veth.c static int veth_validate(struct nlattr *tb[], struct
Quoted 22 lines
drivers/net/macvlan.c +2
-2return 0 ; } -static int macvlan_newlink (struct net_device *dev, +static int macvlan_newlink (struct net *net,struct net_device *dev,struct nlattr *tb[],struct nlattr *data[]) {struct macvlan_dev *vlan =netdev_priv (dev);@@ -427,7 +427,7 @@ static int macvlan_newlink(struct net_device *dev,if (!tb[IFLA_LINK ])return -EINVAL ; - lowerdev =__dev_get_by_index (dev_net (dev),nla_get_u32 (tb[IFLA_LINK ])); + lowerdev =__dev_get_by_index (net,nla_get_u32 (tb[IFLA_LINK ]));if (lowerdev ==NULL )return -ENODEV ;drivers/net/veth.c +0
-0@@ -335,7 +335,7 @@ static int veth_validate(struct nlattr *tb[], structnlattr *data[])
Quoted 54 lines
drivers/net/veth.c +3
-2static struct rtnl_link_ops veth_link_ops; -static int veth_newlink (struct net_device *dev, +static int veth_newlink (struct net *net,struct net_device *dev,struct nlattr *tb[],struct nlattr *data[]) {int err;@@ -375,7 +375,7 @@ static int veth_newlink(struct net_device *dev,else snprintf (ifname,IFNAMSIZ ,DRV_NAME "%%d" ); - peer =rtnl_create_link (dev_net (dev), ifname, &veth_link_ops, tbp); + peer =rtnl_create_link (net, ifname, &veth_link_ops, tbp);if (IS_ERR (peer))return PTR_ERR (peer);@@ -383,6 +383,7 @@ static int veth_newlink(struct net_device *dev,random_ether_addr (peer->dev_addr); err =register_netdevice (peer); +put_net (peer->nd_net);if (err <0 ) goto err_register_peer;include/net/rtnetlink.h +2
-1@@ -55,7 +55,8 @@ struct rtnl_link_ops {int (*validate)(struct nlattr *tb[],struct nlattr *data[]); -int (*newlink)(struct net_device *dev, +int (*newlink)(struct net *net, +struct net_device *dev,struct nlattr *tb[],struct nlattr *data[]); int (*changelink)(struct net_device *dev,net/8021q/vlan_netlink.c +1
-1@@ -100,7 +100,7 @@ static int vlan_changelink(struct net_device *dev,return 0 ; } -static int vlan_newlink (struct net_device *dev, +static int vlan_newlink (struct net *net,struct net_device *dev,struct nlattr *tb[],struct nlattr *data[]) {struct vlan_dev_info *vlan =vlan_dev_info (dev);@@ -112,7 +112,7 @@ static int vlan_newlink(struct net_device *dev,
Quoted 8 lines
net/8021q/vlan_netlink.c static int vlan_newlink(struct net_device *dev, · line 115
Quoted 4 lines
net/8021q/vlan_netlink.c +1
-1if (!tb[IFLA_LINK ])return -EINVAL ; - real_dev =__dev_get_by_index (dev_net (dev),nla_get_u32 (tb[IFLA_LINK ])); + real_dev =__dev_get_by_index (net,nla_get_u32 (tb[IFLA_LINK ]));Hmm, if the macvlan is created inside a namespace, the network namespace specified in the parameter function will not be the namespace where belongs
IFLA_LINKand the__dev_get_by_indexwill fail, no ?
The actual operation is creation in the current network namespace and then immediately move to another namespace. Anything else gets into some semantics problems.
The typical case would be to create a macvlan from eth0 in the initial network namespace, and then move it to the namespace where you want to use it.
Quoted 37 lines
net/core/rtnetlink.c struct net_device *rtnl_create_link(struct net *net,
Quoted 8 lines
net/8021q/vlan_netlink.c +0
-0if (!real_dev)return -ENODEV ;net/core/rtnetlink.c +0
-0@@ -1002,6 +1002,19 @@ struct net_device *rtnl_create_link(struct net *net,char *ifname,
Quoted 28 lines
net/core/rtnetlink.c +14
-1goto err_free; } +/* To support userspace specifying a network namespace during +* device creation we grab the network namespace here and hold +* it until just after register_netdevice to prevent races. +*/ +if (!tb[IFLA_NET_NS_PID ]) +get_net (net); +else { + net =get_net_ns_by_pid (nla_get_u32 (tb[IFLA_NET_NS_PID ])); +if (IS_ERR (net)) { + err =PTR_ERR (net); + goto err_free; + } + }dev_net_set (dev, net); dev->rtnl_link_ops = ops;@@ -1150,10 +1163,12 @@ replay:if (IS_ERR (dev)) err =PTR_ERR (dev);else if (ops->newlink) - err = ops->newlink (dev, tb, data); + err = ops->newlink (net, dev, tb, data);else err =register_netdevice (dev);
Quoted 5 lines
net/core/rtnetlink.c replay: · line 1171
Quoted 2 lines
net/core/rtnetlink.c +2
-0+if (!IS_ERR (dev)) +put_net (dev->nd_net);If there is an error in
ops->newlinkorregister_netdevice, we will exit without releasing the net refcount.
Nope. That is IS_ERR(dev). Which only is true if rtnl_create_link fails. newlink and register_netdevice set error but don't change dev.
Eric
Quoted 5 lines · Eric W. Biederman
When physical devices are inside of network namespace and that network namespace terminates we can not make them go away. We have to keep them and moving them to the initial network namespace is the best we can do.
Quoted 8 lines
For virtual devices left in a network namespace that is exiting we have no need to preserve them and we now have the infrastructure that allows us to delete them. So delete virtual devices when we exit a network namespace. Keeping the necessary user space clean up after a network namespace exits much more tractable.
This patch removes much of the need for user space clean up code to run after a network namespace exits.
I agree that will make the life easier for user space developer :)
I have a few questions about this new behaviour.
After discussing with Benjamin, this patch means an user can no longer manage a pool of virtual devices because they will be automatically destroyed when the namespace exits. I don't think it is a big concern, but just in case I am asking :)
Another point, at present, the virtual devices go back to the initial network namespace when the namespace dies, and this behaviour is used to track the namespace life cycle. With this patch we have no way to know when the network namespace has exited. So we can have the last process exiting the network namespace, but the network namespace can stay alive (eg. some sockets still have buffer to send) ?
AFAIR, Pavel told us about a patch extending the "wait" semantic and pass namespace options to wait for. Is that right Pavel ? Shouldn't we apply this path before deleting the virtual network devices ?
Thanks.
-- Daniel
Quoted 22 lines
--- net/core/dev.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-)net/core/dev.c +6
-0@@ -4844,6 +4844,12 @@ static void __net_exit default_device_exit(struct net *net)if (dev->features &NETIF_F_NETNS_LOCAL )continue ; +/* Delete virtual devices */ +if (dev->rtnl_link_ops && dev->rtnl_link_ops->dellink) { + dev->rtnl_link_ops->dellink (dev); +continue ; + } +/* Push remaing network devices to init_net */ snprintf (fb_name,IFNAMSIZ ,"dev%d" , dev->ifindex); err =dev_change_net_namespace (dev, &init_net, fb_name);
A message that is not in the archive (sent off-list or not yet received): 48EB36FC.4000008-NmTC/[email protected]
Quoted 9 lines · Daniel Lezcano
I agree that will make the life easier for user space developer :)
I have a few questions about this new behaviour.
After discussing with Benjamin, this patch means an user can no longer manage a pool of virtual devices because they will be automatically destroyed when the namespace exits. I don't think it is a big concern, but just in case I am asking :)
Quoted 6 lines
Another point, at present, the virtual devices go back to the initial network namespace when the namespace dies, and this behaviour is used to track the namespace life cycle. With this patch we have no way to know when the network namespace has exited. So we can have the last process exiting the network namespace, but the network namespace can stay alive (eg. some sockets still have buffer to send) ?
Depending on the network interfaces going back to the initial network namespace is problematic in the long term because is breaks recursive containers. I can't see any behavior that does that as anything other than a bug. Especially as I already have production uses for recursive containers.
Quoted 3 lines
AFAIR, Pavel told us about a patch extending the "wait" semantic and pass namespace options to wait for. Is that right Pavel ? Shouldn't we apply this path before deleting the virtual network devices ?
Tell you what. I will post in a bit my patchset that makes /proc/net it's own filesystem, that magically mounts on /proc/self/net. It is a long stupid story why I haven't posted it publicly. At which point we have complete visibility into when a network namespace exits and if we need to be able to wait for it we can just implement a poll method on the root directory.
That is simple and will work quite nicely in the long term, and gives us a lot more visibility than a simple this namespace has exited bit.
Eric
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 18 lines · Eric W. Biederman
Quoted 9 lines · Daniel Lezcano
I agree that will make the life easier for user space developer :)
I have a few questions about this new behaviour.
After discussing with Benjamin, this patch means an user can no longer manage a pool of virtual devices because they will be automatically destroyed when the namespace exits. I don't think it is a big concern, but just in case I am asking :)
Quoted 6 lines
Another point, at present, the virtual devices go back to the initial network namespace when the namespace dies, and this behaviour is used to track the namespace life cycle. With this patch we have no way to know when the network namespace has exited. So we can have the last process exiting the network namespace, but the network namespace can stay alive (eg. some sockets still have buffer to send) ?
Quoted 3 lines
Depending on the network interfaces going back to the initial network namespace is problematic in the long term because is breaks recursive containers. I can't see any behavior that does that as anything other than a bug.
Perhaps, I am misunderstanding your sentence :) But just in case, let me clarify my idea.
If you have a TCP connection with a send queue not empty (the kernel has buffered the data the application has sent), when your process exits because the last socket write was done in userspace, the TCP socket will be orphan but still there taking a ref count on your network namespace. Hence the process and the network namespace life cycles is not correlated. This is a correct behavior, it is not a bug.
Quoted 7 lines
Especially
as I already have production uses for recursive containers.Quoted 3 lines
AFAIR, Pavel told us about a patch extending the "wait" semantic and pass namespace options to wait for. Is that right Pavel ? Shouldn't we apply this path before deleting the virtual network devices ?
Quoted 6 lines
Tell you what. I will post in a bit my patchset that makes
/proc/netit's own filesystem, that magically mounts on/proc/self/net. It is a long stupid story why I haven't posted it publicly. At which point we have complete visibility into when a network namespace exits and if we need to be able to wait for it we can just implement a poll method on the root directory.
Can a process outside of the network namespace look at this directory even if there are no more processes running inside the namespace ?
Quoted 2 lines
That is simple and will work quite nicely in the long term, and gives us a lot more visibility than a simple this namespace has exited bit.
This is nice :)
Shouldn't you send /proc/net filesystem patch before sending the virtual network devices autodestroy patch ?
A message that is not in the archive (sent off-list or not yet received): 48EB4679.1040602-NmTC/[email protected]
Quoted 9 lines · Daniel Lezcano
Perhaps, I am misunderstanding your sentence :) But just in case, let me clarify my idea.
If you have a TCP connection with a send queue not empty (the kernel has buffered the data the application has sent), when your process exits because the last socket write was done in userspace, the TCP socket will be orphan but still there taking a ref count on your network namespace. Hence the process and the network namespace life cycles is not correlated. This is a correct behavior, it is not a bug.
Agreed, letting the network stack finish sending the last bits of data from sockets is not a bug.
The problem I see is having a veth device that exists in a child container, and the application waiting for the child device to return to the current network namespace. Since we always return network devices to the initial network namespace waiting for a device in a child container does not work in a recursive container. And thus is a bug.
Quoted 2 lines
Can a process outside of the network namespace look at this directory even if there are no more processes running inside the namespace ?
If you mount it somewhere besides /proc/self/net yes.
Say: mount --bind /proc/self/net /tmp/net
Quoted 7 lines
Quoted 2 lines
That is simple and will work quite nicely in the long term, and gives us a lot more visibility than a simple this namespace has exited bit.
This is nice :)
Shouldn't you send
/proc/netfilesystem patch before sending the virtual network devices autodestroy patch ?
Well there is the cheap trick with this patch of waiting until the local end of veth dies.
Eric
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 12 lines · Eric W. Biederman
Quoted 9 lines · Daniel Lezcano
Perhaps, I am misunderstanding your sentence :) But just in case, let me clarify my idea.
If you have a TCP connection with a send queue not empty (the kernel has buffered the data the application has sent), when your process exits because the last socket write was done in userspace, the TCP socket will be orphan but still there taking a ref count on your network namespace. Hence the process and the network namespace life cycles is not correlated. This is a correct behavior, it is not a bug.
Quoted 8 lines
Agreed, letting the network stack finish sending the last bits of data from sockets is not a bug.
The problem I see is having a veth device that exists in a child container, and the application waiting for the child device to return to the current network namespace. Since we always return network devices to the initial network namespace waiting for a device in a child container does not work in a recursive container. And thus is a bug.
I agree.
Quoted 6 lines
Quoted 2 lines
Can a process outside of the network namespace look at this directory even if there are no more processes running inside the namespace ?
If you mount it somewhere besides
/proc/self/netyes.Say: mount --bind
/proc/self/net/tmp/net
Ok, thanks.
Quoted 9 lines
Quoted 6 lines
Quoted 2 lines
That is simple and will work quite nicely in the long term, and gives us a lot more visibility than a simple this namespace has exited bit.
This is nice :)
Shouldn't you send
/proc/netfilesystem patch before sending the virtual network devices autodestroy patch ?Well there is the cheap trick with this patch of waiting until the local end of veth dies.
I actually use veth, macvlan, empty netns and physical. But if you are planning the send netns fs soon, I guess I can live with that a time.
Thanks.
-- Daniel
A message that is not in the archive (sent off-list or not yet received): 48EB50E4.3060303-NmTC/[email protected]
From: Daniel Lezcano <dlezcano-NmTC/[email protected]>
Date: Tue, 07 Oct 2008 14:07:00 +0200
Quoted 7 lines
Quoted 2 lines · Eric W. Biederman
Well there is the cheap trick with this patch of waiting until the local end of veth dies.
I actually use veth, macvlan, empty netns and physical. But if you are planning the send netns fs soon, I guess I can live with that a time.
Are we anywhere near consensus with this patch?
Please resubmit once there is some agreement.
A message that is not in the archive (sent off-list or not yet received): 20081007.160807.32968959.davem-fT/PcQaiUtIeIZ0/[email protected]
Daniel Lezcano
Acked-byQuoted 6 lines · David Miller
From: Daniel Lezcano <dlezcano-NmTC/[email protected]>
Date: Tue, 07 Oct 2008 14:07:00 +0200Quoted 3 lines
Quoted 2 lines · Eric W. Biederman
Well there is the cheap trick with this patch of waiting until the local end of veth dies.
Quoted 7 lines
Quoted 3 lines
I actually use veth, macvlan, empty netns and physical. But if you are planning the send netns fs soon, I guess I can live with that a time.
Are we anywhere near consensus with this patch?
Please resubmit once there is some agreement.
I am fine with this patch.
Quoted 31 lines · Daniel Lezcano
Quoted 5 lines · Eric W. Biederman
When physical devices are inside of network namespace and that network namespace terminates we can not make them go away. We have to keep them and moving them to the initial network namespace is the best we can do.
Quoted 8 lines
For virtual devices left in a network namespace that is exiting we have no need to preserve them and we now have the infrastructure that allows us to delete them. So delete virtual devices when we exit a network namespace. Keeping the necessary user space clean up after a network namespace exits much more tractable.
This patch removes much of the need for user space clean up code to run after a network namespace exits.
I agree that will make the life easier for user space developer :)
I have a few questions about this new behaviour.
After discussing with Benjamin, this patch means an user can no longer manage a pool of virtual devices because they will be automatically destroyed when the namespace exits. I don't think it is a big concern, but just in case I am asking :)
Another point, at present, the virtual devices go back to the initial network namespace when the namespace dies, and this behaviour is used to track the namespace life cycle. With this patch we have no way to know when the network namespace has exited. So we can have the last process exiting the network namespace, but the network namespace can stay alive (eg. some sockets still have buffer to send) ?
Quoted 3 lines
AFAIR, Pavel told us about a patch extending the "wait" semantic and pass namespace options to wait for. Is that right Pavel ? Shouldn't we apply this path before deleting the virtual network devices ?
I remember that I promised to prepare the wait-extending patch. But I haven't manage to find time for this, sorry :( In a month or two I will finish one time-hungry task and hopefully be able to do it.
As far as this particular patch is concerned.
All the virtual devices we have now in namespaces (vlan and tunnels) kill themselves *before* this code is called. But even if we try to move this destruction from modules to here, we'll be in a tricky situation, when the e.g. ipip module has already kfree-d the net_ipip structure, while none of ipip devices are released yet.
If we try to look in the future - if we ever have a virtual device driver, that will be able to create its devices in namespace, we'll have to destroy all these devices *before* (or inside) this driver's net->exit callback is called, but this patch dies the ->dellink call at the very end, i.e. *after* any potential ->exit callback.
Eric - did you see any device, that was ->dellink-ed by this patch?
Quoted 26 lines
Thanks.
-- DanielQuoted 22 lines
--- net/core/dev.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-)net/core/dev.c +6
-0@@ -4844,6 +4844,12 @@ static void __net_exit default_device_exit(struct net *net)if (dev->features &NETIF_F_NETNS_LOCAL )continue ; +/* Delete virtual devices */ +if (dev->rtnl_link_ops && dev->rtnl_link_ops->dellink) { + dev->rtnl_link_ops->dellink (dev); +continue ; + } +/* Push remaing network devices to init_net */ snprintf (fb_name,IFNAMSIZ ,"dev%d" , dev->ifindex); err =dev_change_net_namespace (dev, &init_net, fb_name);
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 12 lines · Pavel Emelyanov
I remember that I promised to prepare the wait-extending patch. But I haven't manage to find time for this, sorry :( In a month or two I will finish one time-hungry task and hopefully be able to do it.
As far as this particular patch is concerned.
All the virtual devices we have now in namespaces (vlan and tunnels) kill themselves *before* this code is called. But even if we try to move this destruction from modules to here, we'll be in a tricky situation, when the e.g. ipip module has already kfree-d the
net_ipipstructure, while none of ipip devices are released yet.
Quoted 7 lines
If we try to look in the future - if we ever have a virtual device driver, that will be able to create its devices in namespace, we'll have to destroy all these devices *before* (or inside) this driver's
net->exitcallback is called, but this patch dies the ->dellink call at the very end, i.e. *after* any potential ->exit callback.Eric - did you see any device, that was ->dellink-ed by this patch?
macvlan, veth, and dummy interfaces. Basically everything I use this deletes the virtual interfaces, instead of sending them back to the initial network namespace.
From the looks of the code vlans are also be handled.
Things like tun/tap and ipip are handled in the exit methods and I have no problem with that, although I do wonder if we are handling moving or refusing to move them between namespaces properly.
For devices that don't need a dedicated virtual interface in every network namespace this certainly looks like the easiest way to handle them, as the driver doesn't need to a thing about network namespaces and the right thing just happens.
Eric
A message that is not in the archive (sent off-list or not yet received): [email protected]
Pavel Emelyanov
Acked-byQuoted 20 lines · Eric W. Biederman
Quoted 18 lines · Pavel Emelyanov
I remember that I promised to prepare the wait-extending patch. But I haven't manage to find time for this, sorry :( In a month or two I will finish one time-hungry task and hopefully be able to do it.
As far as this particular patch is concerned.
All the virtual devices we have now in namespaces (vlan and tunnels) kill themselves *before* this code is called. But even if we try to move this destruction from modules to here, we'll be in a tricky situation, when the e.g. ipip module has already kfree-d the
net_ipipstructure, while none of ipip devices are released yet.If we try to look in the future - if we ever have a virtual device driver, that will be able to create its devices in namespace, we'll have to destroy all these devices *before* (or inside) this driver's
net->exitcallback is called, but this patch dies the ->dellink call at the very end, i.e. *after* any potential ->exit callback.
Quoted 5 lines
Quoted 1 line
Eric - did you see any device, that was ->dellink-ed by this patch?
macvlan, veth, and dummy interfaces. Basically everything I use this deletes the virtual interfaces, instead of sending them back to the initial network namespace.
OK, then.
Quoted 13 lines
Quoted 1 line
From the looks of the code vlans are also be handled.
Things like tun/tap and ipip are handled in the exit methods and I have no problem with that, although I do wonder if we are handling moving or refusing to move them between namespaces properly.
For devices that don't need a dedicated virtual interface in every network namespace this certainly looks like the easiest way to handle them, as the driver doesn't need to a thing about network namespaces and the right thing just happens.
Eric
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/3 netns: Delete virtual interfaces during namespace cleanup
When physical devices are inside of network namespace and that network namespace terminates we can not make them go away. We have to keep them and moving them to the initial network namespace is the best we can do.
For virtual devices left in a network namespace that is exiting we have no need to preserve them and we now have the infrastructure that allows us to delete them. So delete virtual devices when we exit a network namespace. Keeping the necessary user space clean up after a network namespace exits much more tractable.
--- net/core/dev.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-)
net/core/dev.c +6 -0
@@ -4852,6 +4852,12 @@ static void __net_exit default_device_exit(struct net *net)if (dev->features &NETIF_F_NETNS_LOCAL )continue ; +/* Delete virtual devices */ +if (dev->rtnl_link_ops && dev->rtnl_link_ops->dellink) { + dev->rtnl_link_ops->dellink (dev); +continue ; + } +/* Push remaing network devices to init_net */ snprintf (fb_name,IFNAMSIZ ,"dev%d" , dev->ifindex); err =dev_change_net_namespace (dev, &init_net, fb_name);
Signature · 1 line
1.5.6.5
PATCH 2/3 net: Guaranetee the proper ordering of the loopback device.
I was recently hunting a bug that occurred in network namespace cleanup. In looking at the code it became apparrent that we have and will continue to have cases where if we have anything going on in a network namespace there will be assumptions that the
loopback device is present. Things like sending igmp unsubscribe
messages when we bring down network devices invokes the routing code which assumes that at least the loopback driver is present.
Therefore to avoid magic initcall ordering hackery that is hard to follow and hard to get right insert a call to register the
loopback device directly from net_dev_init(). This guarantes
that the loopback device is the first device registered and the last network device to go away.
--- drivers/net/loopback.c | 13 ++----------- include/linux/netdevice.h | 1 + net/core/dev.c | 12 ++++++++++++ 3 files changed, 15 insertions(+), 11 deletions(-)
drivers/net/loopback.c +2 -11
@@ -204,17 +204,8 @@ static __net_exit void loopback_net_exit(struct net *net)unregister_netdev (dev); } -static struct pernet_operations __net_initdata loopback_net_ops = { +/* Registered in net/core/dev.c */ +struct pernet_operations __net_initdata loopback_net_ops = { .init = loopback_net_init, .exit = loopback_net_exit, }; - -static int __init loopback_init (void ) -{ -return register_pernet_device (&loopback_net_ops); -} - -/* Loopback is special. It should be initialized before any other network -* device and network subsystem. -*/ -fs_initcall (loopback_init);
include/linux/netdevice.h +1 -0
@@ -1766,6 +1766,7 @@ static inline int skb_bond_should_drop(struct sk_buff *skb)return 0 ; } +extern struct pernet_operations __net_initdata loopback_net_ops;#endif /* __KERNEL__ */ #endif /* _LINUX_DEV_H */
net/core/dev.c +12 -0
@@ -4904,6 +4904,18 @@ static int __init net_dev_init(void)if (register_pernet_subsys (&netdev_net_ops)) goto out; +/* The loopback device is special if any other network devices +* is present in a network namespace the loopback device must +* be present. Since we now dynamically allocate and free the +* loopback device ensure this invariant is maintained by +* keeping the loopback device as the first device on the +* list of network devices. Ensuring the loopback devices +* is the first device that appears and the last network device +* that disappears. +*/ +if (register_pernet_device (&loopback_net_ops)) + goto out; +if (register_pernet_device (&default_device_ops)) goto out;
Signature · 1 line
1.5.6.5
PATCH 3/3 net: Don't leak packets when a netns is going down
I have been tracking for a while a case where when the network namespace exits the cleanup gets stck in an endless precessess of:
unregister_netdevice: waiting for lo to become free. Usage count = 3unregister_netdevice: waiting for lo to become free. Usage count = 3unregister_netdevice: waiting for lo to become free. Usage count = 3unregister_netdevice: waiting for lo to become free. Usage count = 3unregister_netdevice: waiting for lo to become free. Usage count = 3unregister_netdevice: waiting for lo to become free. Usage count = 3unregister_netdevice: waiting for lo to become free. Usage count = 3
It turns out that if you listen on a multicast address an unsubscribe
packet is sent when the network device goes down. If you shutdown
the network namespace without carefully cleaning up this can trigger the unsubscribe packet to be sent over the loopback interface while the network namespace is going down.
All of which is fine except when we drop the packet and forget to free it leaking the skb and the dst entry attached to. As it turns out the dst entry hold a reference to the idev which holds the dev and keeps everything from being cleaned up. Yuck!
By fixing my earlier thinko and add the needed kfree_skb and everything cleans up beautifully.
--- net/core/dev.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
net/core/dev.c +3 -1
@@ -2253,8 +2253,10 @@ int netif_receive_skb(struct sk_buff *skb)rcu_read_lock ();/* Don't receive packets in an exiting network namespace */ -if (!net_alive (dev_net (skb->dev))) +if (!net_alive (dev_net (skb->dev))) { +kfree_skb (skb); goto out; + }#ifdef CONFIG_NET_CLS_ACT if (skb->tc_verd &TC_NCLS ) {
Signature · 1 line
1.5.6.5
Re: [PATCH 3/3] net: Don't leak packets when a netns is going down
From: [email protected] (Eric W. Biederman)
Date: Wed, 05 Nov 2008 15:27:34 -0800
Quoted 24 lines
I have been tracking for a while a case where when the network namespace exits the cleanup gets stck in an endless precessess of:
unregister_netdevice: waiting for lo to become free. Usage count = 3unregister_netdevice: waiting for lo to become free. Usage count = 3unregister_netdevice: waiting for lo to become free. Usage count = 3unregister_netdevice: waiting for lo to become free. Usage count = 3unregister_netdevice: waiting for lo to become free. Usage count = 3unregister_netdevice: waiting for lo to become free. Usage count = 3unregister_netdevice: waiting for lo to become free. Usage count = 3It turns out that if you listen on a multicast address an unsubscribe
packet is sent when the network device goes down. If you shutdown
the network namespace without carefully cleaning up this can trigger the unsubscribe packet to be sent over the loopback interface while the network namespace is going down.All of which is fine except when we drop the packet and forget to free it leaking the skb and the dst entry attached to. As it turns out the dst entry hold a reference to the idev which holds the dev and keeps everything from being cleaned up. Yuck!
Quoted 4 lines
By fixing my earlier thinko and add the needed
kfree_skband everything cleans up beautifully.Signed-off-by Eric W. Biederman <[email protected]>
Applied.
Re: [PATCH 2/3] net: Guaranetee the proper ordering of the loopback device.
In reply to Eric W. BiedermanFrom: [email protected] (Eric W. Biederman)
Date: Wed, 05 Nov 2008 15:25:39 -0800
Quoted 9 lines
I was recently hunting a bug that occurred in network namespace cleanup. In looking at the code it became apparrent that we have and will continue to have cases where if we have anything going on in a network namespace there will be assumptions that the
loopback device is present. Things like sending igmp unsubscribe
messages when we bring down network devices invokes the routing code which assumes that at least the loopback driver is present.
Quoted 7 lines
Therefore to avoid magic initcall ordering hackery that is hard to follow and hard to get right insert a call to register the
loopback device directly fromnet_dev_init(). This guarantes
that the loopback device is the first device registered and the last network device to go away.Signed-off-by Eric W. Biederman <[email protected]>
Applied.
Re: [PATCH 2/3] net: Guaranetee the proper ordering of the loopback device.
Dave can you please drop this one for the moment.
I cleaned up my patch after the basic testing was over and the result is a kernel that won't boot. So if we can prevent this patch from spreading and breaking a git-bisect that would be great.
I will follow up in a moment with a properly tested version. My apologies.
Eric
PATCH 1/2 net: fib_rules ordering fixes.
We need to setup the network namespace state before we register the notifier. Otherwise if a network device is already registered we get a nasty NULL pointer dereference.
--- net/core/fib_rules.c | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-)
net/core/fib_rules.c +4 -3
@@ -664,17 +664,18 @@ static int __init fib_rules_init(void)rtnl_register (PF_UNSPEC ,RTM_DELRULE , fib_nl_delrule,NULL );rtnl_register (PF_UNSPEC ,RTM_GETRULE ,NULL , fib_nl_dumprule); - err =register_netdevice_notifier (&fib_rules_notifier); + err =register_pernet_subsys (&fib_rules_net_ops);if (err <0 ) goto fail; - err =register_pernet_subsys (&fib_rules_net_ops); + err =register_netdevice_notifier (&fib_rules_notifier);if (err <0 ) goto fail_unregister; +return 0 ; fail_unregister: -unregister_netdevice_notifier (&fib_rules_notifier); +unregister_pernet_subsys (&fib_rules_net_ops); fail:rtnl_unregister (PF_UNSPEC ,RTM_NEWRULE );rtnl_unregister (PF_UNSPEC ,RTM_DELRULE );
Signature · 1 line
1.5.6.5
PATCH 2/2 net: Guaranetee the proper ordering of the loopback device. v2
I was recently hunting a bug that occurred in network namespace cleanup. In looking at the code it became apparrent that we have and will continue to have cases where if we have anything going on in a network namespace there will be assumptions that the
loopback device is present. Things like sending igmp unsubscribe
messages when we bring down network devices invokes the routing code which assumes that at least the loopback driver is present.
Therefore to avoid magic initcall ordering hackery that is hard to follow and hard to get right insert a call to register the
loopback device directly from net_dev_init(). This guarantes
that the loopback device is the first device registered and the last network device to go away.
But do it carefully so we register the loopback device after we clear dev_boot_phase.
--- drivers/net/loopback.c | 13 ++----------- include/linux/netdevice.h | 1 + net/core/dev.c | 22 +++++++++++++++++----- 3 files changed, 20 insertions(+), 16 deletions(-)
drivers/net/loopback.c +2 -11
@@ -215,17 +215,8 @@ static __net_exit void loopback_net_exit(struct net *net)unregister_netdev (dev); } -static struct pernet_operations __net_initdata loopback_net_ops = { +/* Registered in net/core/dev.c */ +struct pernet_operations __net_initdata loopback_net_ops = { .init = loopback_net_init, .exit = loopback_net_exit, }; - -static int __init loopback_init (void ) -{ -return register_pernet_device (&loopback_net_ops); -} - -/* Loopback is special. It should be initialized before any other network -* device and network subsystem. -*/ -fs_initcall (loopback_init);
include/linux/netdevice.h +1 -0
@@ -1726,6 +1726,7 @@ static inline int skb_bond_should_drop(struct sk_buff *skb)return 0 ; } +extern struct pernet_operations __net_initdata loopback_net_ops;#endif /* __KERNEL__ */ #endif /* _LINUX_DEV_H */
net/core/dev.c +17 -5
@@ -4824,9 +4824,6 @@ static int __init net_dev_init(void)if (register_pernet_subsys (&netdev_net_ops)) goto out; -if (register_pernet_device (&default_device_ops)) - goto out; -/* * Initialise the packet receive queues. */
@@ -4843,10 +4840,25 @@ static int __init net_dev_init(void) queue->backlog.weight = weight_p; } -netdev_dma_register (); - dev_boot_phase =0 ; +/* The loopback device is special if any other network devices +* is present in a network namespace the loopback device must +* be present. Since we now dynamically allocate and free the +* loopback device ensure this invariant is maintained by +* keeping the loopback device as the first device on the +* list of network devices. Ensuring the loopback devices +* is the first device that appears and the last network device +* that disappears. +*/ +if (register_pernet_device (&loopback_net_ops)) + goto out; + +if (register_pernet_device (&default_device_ops)) + goto out; + +netdev_dma_register (); +open_softirq (NET_TX_SOFTIRQ , net_tx_action);open_softirq (NET_RX_SOFTIRQ , net_rx_action);
Signature · 1 line
1.5.6.5
Re: [PATCH 2/2] net: Guaranetee the proper ordering of the loopback device. v2
From: [email protected] (Eric W. Biederman)
Date: Thu, 06 Nov 2008 07:36:00 -0800
Quoted 14 lines
I was recently hunting a bug that occurred in network namespace cleanup. In looking at the code it became apparrent that we have and will continue to have cases where if we have anything going on in a network namespace there will be assumptions that the
loopback device is present. Things like sending igmp unsubscribe
messages when we bring down network devices invokes the routing code which assumes that at least the loopback driver is present.Therefore to avoid magic initcall ordering hackery that is hard to follow and hard to get right insert a call to register the
loopback device directly fromnet_dev_init(). This guarantes
that the loopback device is the first device registered and the last network device to go away.
Quoted 4 lines
But do it carefully so we register the loopback device after we clear
dev_boot_phase.Signed-off-by Eric W. Biederman <[email protected]>
Applied.
Re: [PATCH 1/2] net: fib_rules ordering fixes.
In reply to Eric W. BiedermanFrom: [email protected] (Eric W. Biederman)
Date: Thu, 06 Nov 2008 07:34:28 -0800
Quoted 6 lines
We need to setup the network namespace state before we register the notifier. Otherwise if a network device is already registered we get a nasty NULL pointer dereference.
Signed-off-by Eric W. Biederman <[email protected]>
Applied.
Re: [PATCH 2/3] net: Guaranetee the proper ordering of the loopback device.
In reply to Eric W. BiedermanFrom: [email protected] (Eric W. Biederman)
Date: Thu, 06 Nov 2008 05:02:33 -0800
Quoted 9 lines
Dave can you please drop this one for the moment.
I cleaned up my patch after the basic testing was over and the result is a kernel that won't boot. So if we can prevent this patch from spreading and breaking a git-bisect that would be great.
I will follow up in a moment with a properly tested version. My apologies.
It's already in my tree, so I need a relative fixup patch not an entire new one.
David Miller
maintainerRe: [PATCH 2/3] net: Guaranetee the proper ordering of the loopback device.
In reply to Eric W. BiedermanFrom: [email protected] (Eric W. Biederman)
Date: Thu, 06 Nov 2008 05:02:33 -0800
Quoted 8 lines
Dave can you please drop this one for the moment.
I cleaned up my patch after the basic testing was over and the result is a kernel that won't boot. So if we can prevent this patch from spreading and breaking a git-bisect that would be great.
I will follow up in a moment with a properly tested version. My apologies.
I'm putting a revert changeset in there, then your two new patches on top.
I'm not screwing up my GIT tree for everyone who pulls from me just because you can't be bothered to test the actual changes you send me.
Re: [PATCH 2/3] net: Guaranetee the proper ordering of the loopback device.
Quoted 5 lines · David Miller
I'm putting a revert changeset in there, then your two new patches on top.
I'm not screwing up my GIT tree for everyone who pulls from me just because you can't be bothered to test the actual changes you send me.
Understood. When I sent the email it looked like it might not have landed in your git tree yet. I badly messed up on that one and I apologize.
Eric
A message that is not in the archive (sent off-list or not yet received): m14p2l4v2l.fsf_-_-B27657KtZYmhTnVgQlOflh2eb7JE58TQ@public.gmane.org
David Miller
AppliedFrom: ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected] (Eric W. Biederman)
Date: Wed, 05 Nov 2008 15:22:26 -0800
Quoted 12 lines
When physical devices are inside of network namespace and that network namespace terminates we can not make them go away. We have to keep them and moving them to the initial network namespace is the best we can do.
For virtual devices left in a network namespace that is exiting we have no need to preserve them and we now have the infrastructure that allows us to delete them. So delete virtual devices when we exit a network namespace. Keeping the necessary user space clean up after a network namespace exits much more tractable.
Quoted 3 lines
Applied.