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>
This commit is contained in:
Родитель
12c9ee3cb4
Коммит
626d667b19
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче