summaryrefslogtreecommitdiffstats
path: root/drivers/net/vxlan.c
diff options
context:
space:
mode:
authorIdo Schimmel <idosch@nvidia.com>2020-11-01 12:39:26 +0100
committerJakub Kicinski <kuba@kernel.org>2020-11-04 00:22:49 +0100
commit626d667b19608c64d86cd71e6ecaa9ddc8650361 (patch)
treeea784ac6b46c92bfd1291479184c57c6f9b7125f /drivers/net/vxlan.c
parentMerge branch 'net-hdlc_fr-improve-fr_rx-and-add-support-for-any-ethertype' (diff)
downloadlinux-626d667b19608c64d86cd71e6ecaa9ddc8650361.tar.xz
linux-626d667b19608c64d86cd71e6ecaa9ddc8650361.zip
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 <idosch@nvidia.com> Reviewed-by: David Ahern <dsahern@kernel.org> Link: https://lore.kernel.org/r/20201101113926.705630-1-idosch@idosch.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to '')
-rw-r--r--drivers/net/vxlan.c15
1 files changed, 8 insertions, 7 deletions
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);