Thread (7 messages) 7 messages, 2 authors, 2018-04-02

Re: [BUG/Q] can_pernet_exit() leaves devices on dead net

flat view

From: Kirill Tkhai <hidden>
Date: 2018-03-16 09:19:36

On 06.03.2018 13:26, Oliver Hartkopp wrote:
- DaveM

Hi Kirill,

On 03/05/2018 04:22 PM, Kirill Tkhai wrote:
quoted
Thanks for the explanation, and module unloading should be nice. Just to clarify,
I worry not about rules, but about netdevices.

	unshare -n ip link add type vcan

This command creates net ns, adds vcan there and exits. Then net ns is destroyed.
Since vcan has rtnl_link_ops, it unregistered by default_device_exit_batch().
Real can devices are moved to init_net in default_device_exit(), as they don't
have rtnl_link_ops set.
In fact most of the real CAN drivers have rtnl_link_ops:

https://elixir.bootlin.com/linux/latest/source/drivers/net/can/dev.c#L1162
https://elixir.bootlin.com/linux/latest/source/drivers/net/can/dev.c#L1225

Just slcan.c which is something like slip.c is missing these feature.

AFAIK real CAN netdevices are created in init_net at system startup, and you
can move them to a netns later.

When we already have rtnl_link_ops in the real CAN drivers - what happens to
them when the namespace is destroyed? Are they still moved to init_net, or do
we need to add some default handler in the current rtnl_link_ops setup?
They are unregistered in default_device_exit_batch():

        list_for_each_entry(net, net_list, exit_list) {
                for_each_netdev_reverse(net, dev) {
                        if (dev->rtnl_link_ops && dev->rtnl_link_ops->dellink)
                                dev->rtnl_link_ops->dellink(dev, &dev_kill_list);
                        else
                                unregister_netdevice_queue(dev, &dev_kill_list);
                }
        }
        unregister_netdevice_many(&dev_kill_list);

So that, my question in the start of the topic is about that. If we unregister them,
what devices we're going to meet in can_pernet_exit()?

Also, can devices not having rtnl_link_ops are moved into init_net in default_device_exit():

for_each_netdev_safe(net, dev, aux) {
                if (dev->features & NETIF_F_NETNS_LOCAL)
                        continue;

                /* Leave virtual devices for the generic cleanup */
                if (dev->rtnl_link_ops)
                        continue;

                err = dev_change_net_namespace(dev, &init_net, fb_name);
}
 
quoted
So, for_each_netdev_rcu() cycle in can_pernet_exit() should be useless (there are
no can devices in the list of net's devices). This looks so for me, please say
what devices are there if my assumption is wrong.
See above?
quoted
quoted
quoted
Since can_pernet_ops is pernet subsys, it's executed after default_device_exit()
from default_device_ops pernet device, as devices exit methods are executed first
(see net/core/net_namespace.c).
Hm - a device exit fires the NETDEV_UNREGISTER notifier which removes the
user-generated filters (e.g. in raw_notifier() in net/can/raw.c).
Finally the can_dev_rcv_lists structure is free'd in af_can.c.

Marc Kleine-Budde recently proposed a patch to create the can_dev_rcv_lists at
netdevice creation time (-> the space is allocated by alloc_netdev() and
removed by free_netdev()). This would remove the handling (allocate & free) of
ml_priv by af_can.c. Would this rework fix the described issue?
Could you please give me a link to the patches? I can't find them in patchwork.
There was a patchset of 14 patches from Marc where some of the refactoring &
renaming already made it into mainline - but the patches to move the
can_dev_rcv_lists data structure into the network device space have not been
pushed:

https://marc.info/?l=linux-can&m=150169588319315&w=2
https://marc.info/?l=linux-can&r=1&b=201708&w=2

This patch & documentation describes Marc's proposed idea best:
https://marc.info/?l=linux-can&m=150169589619340&w=2
Yes, this one looks good:
https://marc.info/?l=linux-can&m=150169589119335&w=2

Regards,
Kirill
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help