From 626d667b19608c64d86cd71e6ecaa9ddc8650361 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Sun, 1 Nov 2020 13:39:26 +0200 Subject: vxlan: Use a per-namespace nexthop listener instead of a global one The nexthop notification chain is a per-namespace chain and not a global one like the netdev notification chain. Therefore, a single (global) listener cannot be registered to all these chains simultaneously as it will result in list corruptions whenever listeners are registered / unregistered. Instead, register a different listener in each namespace. Currently this is not an issue because only the VXLAN driver registers a listener to this chain, but this is going to change with netdevsim and mlxsw also registering their own listeners. Signed-off-by: Ido Schimmel Reviewed-by: David Ahern Link: https://lore.kernel.org/r/20201101113926.705630-1-idosch@idosch.org Signed-off-by: Jakub Kicinski --- drivers/net/vxlan.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 1a557aeba32b..876679af6f7c 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -66,6 +66,7 @@ struct vxlan_net { struct list_head vxlan_list; struct hlist_head sock_list[PORT_HASH_SIZE]; spinlock_t sock_lock; + struct notifier_block nexthop_notifier_block; }; /* Forwarding table entry */ @@ -4693,10 +4694,6 @@ static int vxlan_nexthop_event(struct notifier_block *nb, return NOTIFY_DONE; } -static struct notifier_block vxlan_nexthop_notifier_block __read_mostly = { - .notifier_call = vxlan_nexthop_event, -}; - static __net_init int vxlan_init_net(struct net *net) { struct vxlan_net *vn = net_generic(net, vxlan_net_id); @@ -4704,11 +4701,12 @@ static __net_init int vxlan_init_net(struct net *net) INIT_LIST_HEAD(&vn->vxlan_list); spin_lock_init(&vn->sock_lock); + vn->nexthop_notifier_block.notifier_call = vxlan_nexthop_event; for (h = 0; h < PORT_HASH_SIZE; ++h) INIT_HLIST_HEAD(&vn->sock_list[h]); - return register_nexthop_notifier(net, &vxlan_nexthop_notifier_block); + return register_nexthop_notifier(net, &vn->nexthop_notifier_block); } static void vxlan_destroy_tunnels(struct net *net, struct list_head *head) @@ -4740,8 +4738,11 @@ static void __net_exit vxlan_exit_batch_net(struct list_head *net_list) LIST_HEAD(list); rtnl_lock(); - list_for_each_entry(net, net_list, exit_list) - unregister_nexthop_notifier(net, &vxlan_nexthop_notifier_block); + list_for_each_entry(net, net_list, exit_list) { + struct vxlan_net *vn = net_generic(net, vxlan_net_id); + + unregister_nexthop_notifier(net, &vn->nexthop_notifier_block); + } list_for_each_entry(net, net_list, exit_list) vxlan_destroy_tunnels(net, &list); -- cgit v1.2.3