Skip to content

Commit 5928f9d

Browse files
strssndktnBrian Maly
authored andcommitted
vxlan: synchronously and race-free destruction of vxlan sockets
Due to the fact that the udp socket is destructed asynchronously in a work queue, we have some nondeterministic behavior during shutdown of vxlan tunnels and creating new ones. Fix this by keeping the destruction process synchronous in regards to the user space process so IFF_UP can be reliably set. udp_tunnel_sock_release destroys vs->sock->sk if reference counter indicates so. We expect to have the same lifetime of vxlan_sock and vxlan_sock->sock->sk even in fast paths with only rcu locks held. So only destruct the whole socket after we can be sure it cannot be found by searching vxlan_net->sock_list. Orabug: 29755932 Cc: Eric Dumazet <[email protected]> Cc: Jiri Benc <[email protected]> Cc: Marcelo Ricardo Leitner <[email protected]> Signed-off-by: Hannes Frederic Sowa <[email protected]> Signed-off-by: David S. Miller <[email protected]> (cherry picked from commit 0412bd9) Reviewed-by: Rama Nichanamatlu <[email protected]> Signed-off-by: Venkat Venkatsubra <[email protected]> Signed-off-by: Brian Maly <[email protected]>
1 parent 8acb266 commit 5928f9d

File tree

2 files changed

+3
-19
lines changed

2 files changed

+3
-19
lines changed

drivers/net/vxlan.c

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ struct vxlan_fdb {
9797

9898
/* salt for hash table */
9999
static u32 vxlan_salt __read_mostly;
100-
static struct workqueue_struct *vxlan_wq;
101100

102101
#if IS_ENABLED(CONFIG_IPV6)
103102
static inline
@@ -1041,7 +1040,9 @@ static void __vxlan_sock_release(struct vxlan_sock *vs)
10411040
vxlan_notify_del_rx_port(vs);
10421041
spin_unlock(&vn->sock_lock);
10431042

1044-
queue_work(vxlan_wq, &vs->del_work);
1043+
synchronize_net();
1044+
udp_tunnel_sock_release(vs->sock);
1045+
kfree(vs);
10451046
}
10461047

10471048
static void vxlan_sock_release(struct vxlan_dev *vxlan)
@@ -2461,13 +2462,6 @@ static const struct ethtool_ops vxlan_ethtool_ops = {
24612462
.get_link = ethtool_op_get_link,
24622463
};
24632464

2464-
static void vxlan_del_work(struct work_struct *work)
2465-
{
2466-
struct vxlan_sock *vs = container_of(work, struct vxlan_sock, del_work);
2467-
udp_tunnel_sock_release(vs->sock);
2468-
kfree_rcu(vs, rcu);
2469-
}
2470-
24712465
static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
24722466
__be16 port, u32 flags)
24732467
{
@@ -2513,8 +2507,6 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
25132507
for (h = 0; h < VNI_HASH_SIZE; ++h)
25142508
INIT_HLIST_HEAD(&vs->vni_list[h]);
25152509

2516-
INIT_WORK(&vs->del_work, vxlan_del_work);
2517-
25182510
sock = vxlan_create_sock(net, ipv6, port, flags);
25192511
if (IS_ERR(sock)) {
25202512
pr_info("Cannot bind port %d, err=%ld\n", ntohs(port),
@@ -3074,10 +3066,6 @@ static int __init vxlan_init_module(void)
30743066
{
30753067
int rc;
30763068

3077-
vxlan_wq = alloc_workqueue("vxlan", 0, 0);
3078-
if (!vxlan_wq)
3079-
return -ENOMEM;
3080-
30813069
get_random_bytes(&vxlan_salt, sizeof(vxlan_salt));
30823070

30833071
rc = register_pernet_subsys(&vxlan_net_ops);
@@ -3098,7 +3086,6 @@ static int __init vxlan_init_module(void)
30983086
out2:
30993087
unregister_pernet_subsys(&vxlan_net_ops);
31003088
out1:
3101-
destroy_workqueue(vxlan_wq);
31023089
return rc;
31033090
}
31043091
late_initcall(vxlan_init_module);
@@ -3107,7 +3094,6 @@ static void __exit vxlan_cleanup_module(void)
31073094
{
31083095
rtnl_link_unregister(&vxlan_link_ops);
31093096
unregister_netdevice_notifier(&vxlan_notifier_block);
3110-
destroy_workqueue(vxlan_wq);
31113097
unregister_pernet_subsys(&vxlan_net_ops);
31123098
/* rcu_barrier() is called by netns */
31133099
}

include/net/vxlan.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,7 @@ struct vxlan_metadata {
105105
/* per UDP socket information */
106106
struct vxlan_sock {
107107
struct hlist_node hlist;
108-
struct work_struct del_work;
109108
struct socket *sock;
110-
struct rcu_head rcu;
111109
struct hlist_head vni_list[VNI_HASH_SIZE];
112110
atomic_t refcnt;
113111
struct udp_offload udp_offloads;

0 commit comments

Comments
 (0)