Skip to content

Commit acaf4e7

Browse files
Daniel Borkmanndavem330
authored andcommitted
net: vxlan: when lower dev unregisters remove vxlan dev as well
We can create a vxlan device with an explicit underlying carrier. In that case, when the carrier link is being deleted from the system (e.g. due to module unload) we should also clean up all created vxlan devices on top of it since otherwise we're in an inconsistent state in vxlan device. In that case, the user needs to remove all such devices, while in case of other virtual devs that sit on top of physical ones, it is usually the case that these devices do unregister automatically as well and do not leave the burden on the user. This work is not necessary when vxlan device was not created with a real underlying device, as connections can resume in that case when driver is plugged again. But at least for the other cases, we should go ahead and do the cleanup on removal. We don't register the notifier during vxlan_newlink() here since I consider this event rather rare, and therefore we should not bloat vxlan's core structure unecessary. Also, we can simply make use of unregister_netdevice_many() to batch that. fdb is flushed upon ndo_stop(). E.g. `ip -d link show vxlan13` after carrier removal before this patch: 5: vxlan13: <BROADCAST,MULTICAST> mtu 1450 qdisc noop state DOWN mode DEFAULT group default link/ether 1e:47:da:6d:4d:99 brd ff:ff:ff:ff:ff:ff promiscuity 0 vxlan id 13 group 239.0.0.10 dev 2 port 32768 61000 ageing 300 ^^^^^ Signed-off-by: Daniel Borkmann <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent fb52cab commit acaf4e7

File tree

1 file changed

+46
-2
lines changed

1 file changed

+46
-2
lines changed

drivers/net/vxlan.c

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2655,6 +2655,44 @@ static struct rtnl_link_ops vxlan_link_ops __read_mostly = {
26552655
.fill_info = vxlan_fill_info,
26562656
};
26572657

2658+
static void vxlan_handle_lowerdev_unregister(struct vxlan_net *vn,
2659+
struct net_device *dev)
2660+
{
2661+
struct vxlan_dev *vxlan, *next;
2662+
LIST_HEAD(list_kill);
2663+
2664+
list_for_each_entry_safe(vxlan, next, &vn->vxlan_list, next) {
2665+
struct vxlan_rdst *dst = &vxlan->default_dst;
2666+
2667+
/* In case we created vxlan device with carrier
2668+
* and we loose the carrier due to module unload
2669+
* we also need to remove vxlan device. In other
2670+
* cases, it's not necessary and remote_ifindex
2671+
* is 0 here, so no matches.
2672+
*/
2673+
if (dst->remote_ifindex == dev->ifindex)
2674+
vxlan_dellink(vxlan->dev, &list_kill);
2675+
}
2676+
2677+
unregister_netdevice_many(&list_kill);
2678+
}
2679+
2680+
static int vxlan_lowerdev_event(struct notifier_block *unused,
2681+
unsigned long event, void *ptr)
2682+
{
2683+
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
2684+
struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
2685+
2686+
if (event == NETDEV_UNREGISTER)
2687+
vxlan_handle_lowerdev_unregister(vn, dev);
2688+
2689+
return NOTIFY_DONE;
2690+
}
2691+
2692+
static struct notifier_block vxlan_notifier_block __read_mostly = {
2693+
.notifier_call = vxlan_lowerdev_event,
2694+
};
2695+
26582696
static __net_init int vxlan_init_net(struct net *net)
26592697
{
26602698
struct vxlan_net *vn = net_generic(net, vxlan_net_id);
@@ -2703,12 +2741,17 @@ static int __init vxlan_init_module(void)
27032741
if (rc)
27042742
goto out1;
27052743

2706-
rc = rtnl_link_register(&vxlan_link_ops);
2744+
rc = register_netdevice_notifier(&vxlan_notifier_block);
27072745
if (rc)
27082746
goto out2;
27092747

2710-
return 0;
2748+
rc = rtnl_link_register(&vxlan_link_ops);
2749+
if (rc)
2750+
goto out3;
27112751

2752+
return 0;
2753+
out3:
2754+
unregister_netdevice_notifier(&vxlan_notifier_block);
27122755
out2:
27132756
unregister_pernet_device(&vxlan_net_ops);
27142757
out1:
@@ -2720,6 +2763,7 @@ late_initcall(vxlan_init_module);
27202763
static void __exit vxlan_cleanup_module(void)
27212764
{
27222765
rtnl_link_unregister(&vxlan_link_ops);
2766+
unregister_netdevice_notifier(&vxlan_notifier_block);
27232767
destroy_workqueue(vxlan_wq);
27242768
unregister_pernet_device(&vxlan_net_ops);
27252769
rcu_barrier();

0 commit comments

Comments
 (0)