Skip to content

Commit

Permalink
Merge branch 'vxlan_lower_dev_unregister'
Browse files Browse the repository at this point in the history
Daniel Borkmann says:

====================
vxlan updates

Did the split into two patches upon request from Cong Wang.

Changelog:

 v1->v2:
  - Removed BUG_ON as it's not needed.
 v2->v3:
  - Removed dev->reg_state check for netns.
 v3->v4:
  - Removed list_del(), we seem to do it in some places and
    in some others not; we agreed it's not really necessary.
  - Split patch into 2 patches, notifier part and module
    unload cleanup part.
====================

Reviewed-by: Cong Wang <cwang@twopensource.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jan 15, 2014
2 parents fb52cab + 8425783 commit e07d4ca
Showing 1 changed file with 51 additions and 7 deletions.
58 changes: 51 additions & 7 deletions drivers/net/vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -2655,6 +2655,44 @@ static struct rtnl_link_ops vxlan_link_ops __read_mostly = {
.fill_info = vxlan_fill_info,
};

static void vxlan_handle_lowerdev_unregister(struct vxlan_net *vn,
struct net_device *dev)
{
struct vxlan_dev *vxlan, *next;
LIST_HEAD(list_kill);

list_for_each_entry_safe(vxlan, next, &vn->vxlan_list, next) {
struct vxlan_rdst *dst = &vxlan->default_dst;

/* In case we created vxlan device with carrier
* and we loose the carrier due to module unload
* we also need to remove vxlan device. In other
* cases, it's not necessary and remote_ifindex
* is 0 here, so no matches.
*/
if (dst->remote_ifindex == dev->ifindex)
vxlan_dellink(vxlan->dev, &list_kill);
}

unregister_netdevice_many(&list_kill);
}

static int vxlan_lowerdev_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);

if (event == NETDEV_UNREGISTER)
vxlan_handle_lowerdev_unregister(vn, dev);

return NOTIFY_DONE;
}

static struct notifier_block vxlan_notifier_block __read_mostly = {
.notifier_call = vxlan_lowerdev_event,
};

static __net_init int vxlan_init_net(struct net *net)
{
struct vxlan_net *vn = net_generic(net, vxlan_net_id);
Expand All @@ -2672,13 +2710,13 @@ static __net_init int vxlan_init_net(struct net *net)
static __net_exit void vxlan_exit_net(struct net *net)
{
struct vxlan_net *vn = net_generic(net, vxlan_net_id);
struct vxlan_dev *vxlan;
LIST_HEAD(list);
struct vxlan_dev *vxlan, *next;
LIST_HEAD(list_kill);

rtnl_lock();
list_for_each_entry(vxlan, &vn->vxlan_list, next)
unregister_netdevice_queue(vxlan->dev, &list);
unregister_netdevice_many(&list);
list_for_each_entry_safe(vxlan, next, &vn->vxlan_list, next)
vxlan_dellink(vxlan->dev, &list_kill);
unregister_netdevice_many(&list_kill);
rtnl_unlock();
}

Expand All @@ -2703,12 +2741,17 @@ static int __init vxlan_init_module(void)
if (rc)
goto out1;

rc = rtnl_link_register(&vxlan_link_ops);
rc = register_netdevice_notifier(&vxlan_notifier_block);
if (rc)
goto out2;

return 0;
rc = rtnl_link_register(&vxlan_link_ops);
if (rc)
goto out3;

return 0;
out3:
unregister_netdevice_notifier(&vxlan_notifier_block);
out2:
unregister_pernet_device(&vxlan_net_ops);
out1:
Expand All @@ -2720,6 +2763,7 @@ late_initcall(vxlan_init_module);
static void __exit vxlan_cleanup_module(void)
{
rtnl_link_unregister(&vxlan_link_ops);
unregister_netdevice_notifier(&vxlan_notifier_block);
destroy_workqueue(vxlan_wq);
unregister_pernet_device(&vxlan_net_ops);
rcu_barrier();
Expand Down

0 comments on commit e07d4ca

Please sign in to comment.