Skip to content

Commit 0412bd9

Browse files
strssndktndavem330
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. 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]>
1 parent f48256e commit 0412bd9

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
@@ -98,7 +98,6 @@ struct vxlan_fdb {
9898

9999
/* salt for hash table */
100100
static u32 vxlan_salt __read_mostly;
101-
static struct workqueue_struct *vxlan_wq;
102101

103102
static inline bool vxlan_collect_metadata(struct vxlan_sock *vs)
104103
{
@@ -1053,7 +1052,9 @@ static void __vxlan_sock_release(struct vxlan_sock *vs)
10531052
vxlan_notify_del_rx_port(vs);
10541053
spin_unlock(&vn->sock_lock);
10551054

1056-
queue_work(vxlan_wq, &vs->del_work);
1055+
synchronize_net();
1056+
udp_tunnel_sock_release(vs->sock);
1057+
kfree(vs);
10571058
}
10581059

10591060
static void vxlan_sock_release(struct vxlan_dev *vxlan)
@@ -2674,13 +2675,6 @@ static const struct ethtool_ops vxlan_ethtool_ops = {
26742675
.get_link = ethtool_op_get_link,
26752676
};
26762677

2677-
static void vxlan_del_work(struct work_struct *work)
2678-
{
2679-
struct vxlan_sock *vs = container_of(work, struct vxlan_sock, del_work);
2680-
udp_tunnel_sock_release(vs->sock);
2681-
kfree_rcu(vs, rcu);
2682-
}
2683-
26842678
static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
26852679
__be16 port, u32 flags)
26862680
{
@@ -2726,8 +2720,6 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
27262720
for (h = 0; h < VNI_HASH_SIZE; ++h)
27272721
INIT_HLIST_HEAD(&vs->vni_list[h]);
27282722

2729-
INIT_WORK(&vs->del_work, vxlan_del_work);
2730-
27312723
sock = vxlan_create_sock(net, ipv6, port, flags);
27322724
if (IS_ERR(sock)) {
27332725
pr_info("Cannot bind port %d, err=%ld\n", ntohs(port),
@@ -3346,10 +3338,6 @@ static int __init vxlan_init_module(void)
33463338
{
33473339
int rc;
33483340

3349-
vxlan_wq = alloc_workqueue("vxlan", 0, 0);
3350-
if (!vxlan_wq)
3351-
return -ENOMEM;
3352-
33533341
get_random_bytes(&vxlan_salt, sizeof(vxlan_salt));
33543342

33553343
rc = register_pernet_subsys(&vxlan_net_ops);
@@ -3370,7 +3358,6 @@ static int __init vxlan_init_module(void)
33703358
out2:
33713359
unregister_pernet_subsys(&vxlan_net_ops);
33723360
out1:
3373-
destroy_workqueue(vxlan_wq);
33743361
return rc;
33753362
}
33763363
late_initcall(vxlan_init_module);
@@ -3379,7 +3366,6 @@ static void __exit vxlan_cleanup_module(void)
33793366
{
33803367
rtnl_link_unregister(&vxlan_link_ops);
33813368
unregister_netdevice_notifier(&vxlan_notifier_block);
3382-
destroy_workqueue(vxlan_wq);
33833369
unregister_pernet_subsys(&vxlan_net_ops);
33843370
/* rcu_barrier() is called by netns */
33853371
}

include/net/vxlan.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,7 @@ struct vxlan_metadata {
184184
/* per UDP socket information */
185185
struct vxlan_sock {
186186
struct hlist_node hlist;
187-
struct work_struct del_work;
188187
struct socket *sock;
189-
struct rcu_head rcu;
190188
struct hlist_head vni_list[VNI_HASH_SIZE];
191189
atomic_t refcnt;
192190
u32 flags;

0 commit comments

Comments
 (0)