diff options
| author | Jakub Kicinski <kuba@kernel.org> | 2026-05-06 03:47:09 +0300 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2026-05-06 03:47:09 +0300 |
| commit | ed36fad2cdcd620130b159be383d74a59097ea50 (patch) | |
| tree | 37f893d0c7c177e90760cc0a0f51cfb9804bd58a | |
| parent | 8c699be3dad7bba87cdda485dc099226cfc2f706 (diff) | |
| parent | 72d3b9a4c2b137b32fdf5342699d16229e2ac75e (diff) | |
| download | linux-ed36fad2cdcd620130b159be383d74a59097ea50.tar.xz | |
Merge branch 'udp_tunnel-speed-up-udp-tunnel-device-destruction-part-i'
Kuniyuki Iwashima says:
====================
udp_tunnel: Speed up UDP tunnel device destruction (Part I)
Most of the UDP tunnel devices call synchronize_rcu() twice
during destruction, for example, vxlan has
1) synchronize_rcu() in udp_tunnel_sock_release()
2) synchronize_net() in vxlan_sock_release()
The goal of this series is to remove the former, and another
followup series removes the latter.
synchronize_rcu() was added in udp_tunnel_sock_release() by
commit 3cf7203ca620 ("net/tunnel: wait until all sk_user_data
reader finish before releasing the sock").
This was intended to protect the fast path of a dying vxlan
from dereferencing vxlan_sock->sock->sk after sock_orphan()
has set sock->sk to NULL.
Most of the UDP tunnel devices store struct socket to its
private struct, but it is NOT needed in the fast paths;
struct sock is used there, but struct socket is only used
for tunnel setup / teardown.
This is probably because UDP tunnel functions accept struct
socket, but even such functions do not need it, except for
udp_tunnel_sock_release(), which can safely access sk->sk_socket.
The overview of the series:
Patch 1 - 5 : Convert UDP tunnel helper to take struct sock
Patch 6 : Small fix for 10-years-old bug
Patch 7 - 14 : Store struct sock in tunnel devices
Patch 15 : Remove synchronize_rcu() in udp_tunnel_sock_release()
With this change, a script creating/upping vxlan in 4000 netns
runs 10x faster.
====================
[See Link for benchmark results.]
Link: https://patch.msgid.link/20260502031401.3557229-1-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
| -rw-r--r-- | drivers/infiniband/sw/rxe/rxe_net.c | 6 | ||||
| -rw-r--r-- | drivers/infiniband/sw/rxe/rxe_ns.c | 4 | ||||
| -rw-r--r-- | drivers/net/amt.c | 80 | ||||
| -rw-r--r-- | drivers/net/bareudp.c | 51 | ||||
| -rw-r--r-- | drivers/net/geneve.c | 54 | ||||
| -rw-r--r-- | drivers/net/gtp.c | 10 | ||||
| -rw-r--r-- | drivers/net/ovpn/udp.c | 2 | ||||
| -rw-r--r-- | drivers/net/pfcp.c | 17 | ||||
| -rw-r--r-- | drivers/net/vxlan/vxlan_core.c | 60 | ||||
| -rw-r--r-- | drivers/net/vxlan/vxlan_multicast.c | 8 | ||||
| -rw-r--r-- | drivers/net/wireguard/socket.c | 8 | ||||
| -rw-r--r-- | include/net/amt.h | 2 | ||||
| -rw-r--r-- | include/net/udp_tunnel.h | 14 | ||||
| -rw-r--r-- | include/net/vxlan.h | 5 | ||||
| -rw-r--r-- | net/ipv4/fou_core.c | 21 | ||||
| -rw-r--r-- | net/ipv4/udp_tunnel_core.c | 23 | ||||
| -rw-r--r-- | net/ipv6/ip6_udp_tunnel.c | 6 | ||||
| -rw-r--r-- | net/l2tp/l2tp_core.c | 2 | ||||
| -rw-r--r-- | net/rxrpc/local_object.c | 2 | ||||
| -rw-r--r-- | net/sctp/protocol.c | 10 | ||||
| -rw-r--r-- | net/tipc/udp_media.c | 32 |
21 files changed, 209 insertions, 208 deletions
diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c index 50a2cb5405e2..082ff387d081 100644 --- a/drivers/infiniband/sw/rxe/rxe_net.c +++ b/drivers/infiniband/sw/rxe/rxe_net.c @@ -283,12 +283,12 @@ static struct socket *rxe_setup_udp_tunnel(struct net *net, __be16 port, tnl_cfg.encap_rcv = rxe_udp_encap_recv; /* Setup UDP tunnel */ - setup_udp_tunnel_sock(net, sock, &tnl_cfg); + setup_udp_tunnel_sock(net, sock->sk, &tnl_cfg); return sock; } -static void rxe_release_udp_tunnel(struct socket *sk) +static void rxe_release_udp_tunnel(struct sock *sk) { if (sk) udp_tunnel_sock_release(sk); @@ -636,7 +636,7 @@ static void rxe_sock_put(struct sock *sk, if (refcount_read(&sk->sk_refcnt) > SK_REF_FOR_TUNNEL) { __sock_put(sk); } else { - rxe_release_udp_tunnel(sk->sk_socket); + rxe_release_udp_tunnel(sk); sk = NULL; set_sk(net, sk); } diff --git a/drivers/infiniband/sw/rxe/rxe_ns.c b/drivers/infiniband/sw/rxe/rxe_ns.c index 8b9d734229b2..64621c89f8bf 100644 --- a/drivers/infiniband/sw/rxe/rxe_ns.c +++ b/drivers/infiniband/sw/rxe/rxe_ns.c @@ -47,7 +47,7 @@ static void rxe_ns_exit(struct net *net) rcu_read_unlock(); if (sk) { rcu_assign_pointer(ns_sk->rxe_sk4, NULL); - udp_tunnel_sock_release(sk->sk_socket); + udp_tunnel_sock_release(sk); } #if IS_ENABLED(CONFIG_IPV6) @@ -56,7 +56,7 @@ static void rxe_ns_exit(struct net *net) rcu_read_unlock(); if (sk) { rcu_assign_pointer(ns_sk->rxe_sk6, NULL); - udp_tunnel_sock_release(sk->sk_socket); + udp_tunnel_sock_release(sk); } #endif } diff --git a/drivers/net/amt.c b/drivers/net/amt.c index f2f3139e38a5..724a8163a514 100644 --- a/drivers/net/amt.c +++ b/drivers/net/amt.c @@ -614,24 +614,24 @@ static void amt_send_discovery(struct amt_dev *amt) { struct amt_header_discovery *amtd; int hlen, tlen, offset; - struct socket *sock; struct udphdr *udph; struct sk_buff *skb; struct iphdr *iph; struct rtable *rt; struct flowi4 fl4; + struct sock *sk; u32 len; int err; rcu_read_lock(); - sock = rcu_dereference(amt->sock); - if (!sock) + sk = rcu_dereference(amt->sk); + if (!sk) goto out; if (!netif_running(amt->stream_dev) || !netif_running(amt->dev)) goto out; - rt = ip_route_output_ports(amt->net, &fl4, sock->sk, + rt = ip_route_output_ports(amt->net, &fl4, sk, amt->discovery_ip, amt->local_ip, amt->gw_port, amt->relay_port, IPPROTO_UDP, 0, @@ -690,7 +690,7 @@ static void amt_send_discovery(struct amt_dev *amt) skb->ip_summed = CHECKSUM_NONE; ip_select_ident(amt->net, skb, NULL); ip_send_check(iph); - err = ip_local_out(amt->net, sock->sk, skb); + err = ip_local_out(amt->net, sk, skb); if (unlikely(net_xmit_eval(err))) amt->dev->stats.tx_errors++; @@ -703,24 +703,24 @@ static void amt_send_request(struct amt_dev *amt, bool v6) { struct amt_header_request *amtrh; int hlen, tlen, offset; - struct socket *sock; struct udphdr *udph; struct sk_buff *skb; struct iphdr *iph; struct rtable *rt; struct flowi4 fl4; + struct sock *sk; u32 len; int err; rcu_read_lock(); - sock = rcu_dereference(amt->sock); - if (!sock) + sk = rcu_dereference(amt->sk); + if (!sk) goto out; if (!netif_running(amt->stream_dev) || !netif_running(amt->dev)) goto out; - rt = ip_route_output_ports(amt->net, &fl4, sock->sk, + rt = ip_route_output_ports(amt->net, &fl4, sk, amt->remote_ip, amt->local_ip, amt->gw_port, amt->relay_port, IPPROTO_UDP, 0, @@ -781,7 +781,7 @@ static void amt_send_request(struct amt_dev *amt, bool v6) skb->ip_summed = CHECKSUM_NONE; ip_select_ident(amt->net, skb, NULL); ip_send_check(iph); - err = ip_local_out(amt->net, sock->sk, skb); + err = ip_local_out(amt->net, sk, skb); if (unlikely(net_xmit_eval(err))) amt->dev->stats.tx_errors++; @@ -1000,14 +1000,14 @@ static bool amt_send_membership_update(struct amt_dev *amt, bool v6) { struct amt_header_membership_update *amtmu; - struct socket *sock; struct iphdr *iph; struct flowi4 fl4; struct rtable *rt; + struct sock *sk; int err; - sock = rcu_dereference_bh(amt->sock); - if (!sock) + sk = rcu_dereference_bh(amt->sk); + if (!sk) return true; err = skb_cow_head(skb, LL_RESERVED_SPACE(amt->dev) + sizeof(*amtmu) + @@ -1039,7 +1039,7 @@ static bool amt_send_membership_update(struct amt_dev *amt, skb_set_inner_protocol(skb, htons(ETH_P_IP)); else skb_set_inner_protocol(skb, htons(ETH_P_IPV6)); - udp_tunnel_xmit_skb(rt, sock->sk, skb, + udp_tunnel_xmit_skb(rt, sk, skb, fl4.saddr, fl4.daddr, AMT_TOS, @@ -1060,14 +1060,14 @@ static void amt_send_multicast_data(struct amt_dev *amt, bool v6) { struct amt_header_mcast_data *amtmd; - struct socket *sock; struct sk_buff *skb; struct iphdr *iph; struct flowi4 fl4; struct rtable *rt; + struct sock *sk; - sock = rcu_dereference_bh(amt->sock); - if (!sock) + sk = rcu_dereference_bh(amt->sk); + if (!sk) return; skb = skb_copy_expand(oskb, sizeof(*amtmd) + sizeof(*iph) + @@ -1097,7 +1097,7 @@ static void amt_send_multicast_data(struct amt_dev *amt, skb_set_inner_protocol(skb, htons(ETH_P_IP)); else skb_set_inner_protocol(skb, htons(ETH_P_IPV6)); - udp_tunnel_xmit_skb(rt, sock->sk, skb, + udp_tunnel_xmit_skb(rt, sk, skb, fl4.saddr, fl4.daddr, AMT_TOS, @@ -1116,13 +1116,13 @@ static bool amt_send_membership_query(struct amt_dev *amt, bool v6) { struct amt_header_membership_query *amtmq; - struct socket *sock; struct rtable *rt; struct flowi4 fl4; + struct sock *sk; int err; - sock = rcu_dereference_bh(amt->sock); - if (!sock) + sk = rcu_dereference_bh(amt->sk); + if (!sk) return true; err = skb_cow_head(skb, LL_RESERVED_SPACE(amt->dev) + sizeof(*amtmq) + @@ -1156,7 +1156,7 @@ static bool amt_send_membership_query(struct amt_dev *amt, skb_set_inner_protocol(skb, htons(ETH_P_IP)); else skb_set_inner_protocol(skb, htons(ETH_P_IPV6)); - udp_tunnel_xmit_skb(rt, sock->sk, skb, + udp_tunnel_xmit_skb(rt, sk, skb, fl4.saddr, fl4.daddr, AMT_TOS, @@ -2554,24 +2554,24 @@ static void amt_send_advertisement(struct amt_dev *amt, __be32 nonce, { struct amt_header_advertisement *amta; int hlen, tlen, offset; - struct socket *sock; struct udphdr *udph; struct sk_buff *skb; struct iphdr *iph; struct rtable *rt; struct flowi4 fl4; + struct sock *sk; u32 len; int err; rcu_read_lock(); - sock = rcu_dereference(amt->sock); - if (!sock) + sk = rcu_dereference(amt->sk); + if (!sk) goto out; if (!netif_running(amt->stream_dev) || !netif_running(amt->dev)) goto out; - rt = ip_route_output_ports(amt->net, &fl4, sock->sk, + rt = ip_route_output_ports(amt->net, &fl4, sk, daddr, amt->local_ip, dport, amt->relay_port, IPPROTO_UDP, 0, @@ -2631,7 +2631,7 @@ static void amt_send_advertisement(struct amt_dev *amt, __be32 nonce, skb->ip_summed = CHECKSUM_NONE; ip_select_ident(amt->net, skb, NULL); ip_send_check(iph); - err = ip_local_out(amt->net, sock->sk, skb); + err = ip_local_out(amt->net, sk, skb); if (unlikely(net_xmit_eval(err))) amt->dev->stats.tx_errors++; @@ -2944,7 +2944,7 @@ drop: return 0; } -static struct socket *amt_create_sock(struct net *net, __be16 port) +static struct sock *amt_create_sock(struct net *net, __be16 port) { struct udp_port_cfg udp_conf; struct socket *sock; @@ -2960,17 +2960,17 @@ static struct socket *amt_create_sock(struct net *net, __be16 port) if (err < 0) return ERR_PTR(err); - return sock; + return sock->sk; } static int amt_socket_create(struct amt_dev *amt) { struct udp_tunnel_sock_cfg tunnel_cfg; - struct socket *sock; + struct sock *sk; - sock = amt_create_sock(amt->net, amt->relay_port); - if (IS_ERR(sock)) - return PTR_ERR(sock); + sk = amt_create_sock(amt->net, amt->relay_port); + if (IS_ERR(sk)) + return PTR_ERR(sk); /* Mark socket as an encapsulation socket */ memset(&tunnel_cfg, 0, sizeof(tunnel_cfg)); @@ -2979,9 +2979,9 @@ static int amt_socket_create(struct amt_dev *amt) tunnel_cfg.encap_rcv = amt_rcv; tunnel_cfg.encap_err_lookup = amt_err_lookup; tunnel_cfg.encap_destroy = NULL; - setup_udp_tunnel_sock(amt->net, sock, &tunnel_cfg); + setup_udp_tunnel_sock(amt->net, sk, &tunnel_cfg); - rcu_assign_pointer(amt->sock, sock); + rcu_assign_pointer(amt->sk, sk); return 0; } @@ -3019,8 +3019,8 @@ static int amt_dev_stop(struct net_device *dev) { struct amt_dev *amt = netdev_priv(dev); struct amt_tunnel_list *tunnel, *tmp; - struct socket *sock; struct sk_buff *skb; + struct sock *sk; int i; cancel_delayed_work_sync(&amt->req_wq); @@ -3028,11 +3028,11 @@ static int amt_dev_stop(struct net_device *dev) cancel_delayed_work_sync(&amt->secret_wq); /* shutdown */ - sock = rtnl_dereference(amt->sock); - RCU_INIT_POINTER(amt->sock, NULL); + sk = rtnl_dereference(amt->sk); + RCU_INIT_POINTER(amt->sk, NULL); synchronize_net(); - if (sock) - udp_tunnel_sock_release(sock); + if (sk) + udp_tunnel_sock_release(sk); cancel_work_sync(&amt->event_wq); for (i = 0; i < AMT_MAX_EVENTS; i++) { diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c index da5866ba0699..890a0650d9cf 100644 --- a/drivers/net/bareudp.c +++ b/drivers/net/bareudp.c @@ -53,7 +53,7 @@ struct bareudp_dev { __be16 port; u16 sport_min; bool multi_proto_mode; - struct socket __rcu *sock; + struct sock __rcu *sk; struct list_head next; /* bareudp node on namespace list */ struct gro_cells gro_cells; }; @@ -228,7 +228,7 @@ static void bareudp_uninit(struct net_device *dev) gro_cells_destroy(&bareudp->gro_cells); } -static struct socket *bareudp_create_sock(struct net *net, __be16 port) +static struct sock *bareudp_create_sock(struct net *net, __be16 port) { struct udp_port_cfg udp_conf; struct socket *sock; @@ -248,18 +248,18 @@ static struct socket *bareudp_create_sock(struct net *net, __be16 port) return ERR_PTR(err); udp_allow_gso(sock->sk); - return sock; + return sock->sk; } /* Create new listen socket if needed */ static int bareudp_socket_create(struct bareudp_dev *bareudp, __be16 port) { struct udp_tunnel_sock_cfg tunnel_cfg; - struct socket *sock; + struct sock *sk; - sock = bareudp_create_sock(bareudp->net, port); - if (IS_ERR(sock)) - return PTR_ERR(sock); + sk = bareudp_create_sock(bareudp->net, port); + if (IS_ERR(sk)) + return PTR_ERR(sk); /* Mark socket as an encapsulation socket */ memset(&tunnel_cfg, 0, sizeof(tunnel_cfg)); @@ -268,29 +268,27 @@ static int bareudp_socket_create(struct bareudp_dev *bareudp, __be16 port) tunnel_cfg.encap_rcv = bareudp_udp_encap_recv; tunnel_cfg.encap_err_lookup = bareudp_err_lookup; tunnel_cfg.encap_destroy = NULL; - setup_udp_tunnel_sock(bareudp->net, sock, &tunnel_cfg); + setup_udp_tunnel_sock(bareudp->net, sk, &tunnel_cfg); - rcu_assign_pointer(bareudp->sock, sock); + rcu_assign_pointer(bareudp->sk, sk); return 0; } static int bareudp_open(struct net_device *dev) { struct bareudp_dev *bareudp = netdev_priv(dev); - int ret = 0; - ret = bareudp_socket_create(bareudp, bareudp->port); - return ret; + return bareudp_socket_create(bareudp, bareudp->port); } static void bareudp_sock_release(struct bareudp_dev *bareudp) { - struct socket *sock; + struct sock *sk; - sock = bareudp->sock; - rcu_assign_pointer(bareudp->sock, NULL); + sk = bareudp->sk; + rcu_assign_pointer(bareudp->sk, NULL); synchronize_net(); - udp_tunnel_sock_release(sock); + udp_tunnel_sock_release(sk); } static int bareudp_stop(struct net_device *dev) @@ -308,7 +306,7 @@ static int bareudp_xmit_skb(struct sk_buff *skb, struct net_device *dev, bool udp_sum = test_bit(IP_TUNNEL_CSUM_BIT, info->key.tun_flags); bool xnet = !net_eq(bareudp->net, dev_net(bareudp->dev)); bool use_cache = ip_tunnel_dst_cache_usable(skb, info); - struct socket *sock = rcu_dereference(bareudp->sock); + struct sock *sk = rcu_dereference(bareudp->sk); const struct ip_tunnel_key *key = &info->key; struct rtable *rt; __be16 sport, df; @@ -320,7 +318,7 @@ static int bareudp_xmit_skb(struct sk_buff *skb, struct net_device *dev, if (skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB))) return -EINVAL; - if (!sock) + if (!sk) return -ESHUTDOWN; sport = udp_flow_src_port(bareudp->net, skb, @@ -359,7 +357,7 @@ static int bareudp_xmit_skb(struct sk_buff *skb, struct net_device *dev, goto free_dst; skb_set_inner_protocol(skb, bareudp->ethertype); - udp_tunnel_xmit_skb(rt, sock->sk, skb, saddr, info->key.u.ipv4.dst, + udp_tunnel_xmit_skb(rt, sk, skb, saddr, info->key.u.ipv4.dst, tos, ttl, df, sport, bareudp->port, !net_eq(bareudp->net, dev_net(bareudp->dev)), !test_bit(IP_TUNNEL_CSUM_BIT, info->key.tun_flags), @@ -378,7 +376,7 @@ static int bareudp6_xmit_skb(struct sk_buff *skb, struct net_device *dev, bool udp_sum = test_bit(IP_TUNNEL_CSUM_BIT, info->key.tun_flags); bool xnet = !net_eq(bareudp->net, dev_net(bareudp->dev)); bool use_cache = ip_tunnel_dst_cache_usable(skb, info); - struct socket *sock = rcu_dereference(bareudp->sock); + struct sock *sk = rcu_dereference(bareudp->sk); const struct ip_tunnel_key *key = &info->key; struct dst_entry *dst = NULL; struct in6_addr saddr, daddr; @@ -390,13 +388,13 @@ static int bareudp6_xmit_skb(struct sk_buff *skb, struct net_device *dev, if (skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB))) return -EINVAL; - if (!sock) + if (!sk) return -ESHUTDOWN; sport = udp_flow_src_port(bareudp->net, skb, bareudp->sport_min, USHRT_MAX, true); - dst = udp_tunnel6_dst_lookup(skb, dev, bareudp->net, sock, 0, &saddr, + dst = udp_tunnel6_dst_lookup(skb, dev, bareudp->net, sk, 0, &saddr, key, sport, bareudp->port, key->tos, use_cache ? (struct dst_cache *) &info->dst_cache : NULL); @@ -427,7 +425,7 @@ static int bareudp6_xmit_skb(struct sk_buff *skb, struct net_device *dev, goto free_dst; daddr = info->key.u.ipv6.dst; - udp_tunnel6_xmit_skb(dst, sock->sk, skb, dev, + udp_tunnel6_xmit_skb(dst, sk, skb, dev, &saddr, &daddr, prio, ttl, info->key.label, sport, bareudp->port, !test_bit(IP_TUNNEL_CSUM_BIT, @@ -527,12 +525,13 @@ static int bareudp_fill_metadata_dst(struct net_device *dev, } else if (ip_tunnel_info_af(info) == AF_INET6) { struct dst_entry *dst; struct in6_addr saddr; - struct socket *sock = rcu_dereference(bareudp->sock); + struct sock *sk; - if (!sock) + sk = rcu_dereference(bareudp->sk); + if (!sk) return -ESHUTDOWN; - dst = udp_tunnel6_dst_lookup(skb, dev, bareudp->net, sock, + dst = udp_tunnel6_dst_lookup(skb, dev, bareudp->net, sk, 0, &saddr, &info->key, sport, bareudp->port, info->key.tos, use_cache ? &info->dst_cache : NULL); diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index c6563367d382..b36fad833724 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -106,7 +106,7 @@ struct geneve_sock { bool collect_md; bool gro_hint; struct list_head list; - struct socket *sock; + struct sock *sk; struct rcu_head rcu; int refcnt; struct hlist_head vni_list[VNI_HASH_SIZE]; @@ -167,7 +167,7 @@ static bool eq_tun_id_and_vni(u8 *tun_id, u8 *vni) static sa_family_t geneve_get_sk_family(struct geneve_sock *gs) { - return gs->sock->sk->sk_family; + return gs->sk->sk_family; } static struct geneve_dev *geneve_lookup(struct geneve_sock *gs, @@ -760,11 +760,11 @@ static int geneve_udp_encap_err_lookup(struct sock *sk, struct sk_buff *skb) return -EPFNOSUPPORT; } -static struct socket *geneve_create_sock(struct net *net, bool ipv6, - __be16 port, bool ipv6_rx_csum) +static struct sock *geneve_create_sock(struct net *net, bool ipv6, + __be16 port, bool ipv6_rx_csum) { - struct socket *sock; struct udp_port_cfg udp_conf; + struct socket *sock; int err; memset(&udp_conf, 0, sizeof(udp_conf)); @@ -786,7 +786,7 @@ static struct socket *geneve_create_sock(struct net *net, bool ipv6, return ERR_PTR(err); udp_allow_gso(sock->sk); - return sock; + return sock->sk; } static bool geneve_hdr_match(struct sk_buff *skb, @@ -974,28 +974,28 @@ static struct geneve_sock *geneve_socket_create(struct net *net, __be16 port, bool ipv6, bool ipv6_rx_csum) { struct geneve_net *gn = net_generic(net, geneve_net_id); - struct geneve_sock *gs; - struct socket *sock; struct udp_tunnel_sock_cfg tunnel_cfg; + struct geneve_sock *gs; + struct sock *sk; int h; gs = kzalloc_obj(*gs); if (!gs) return ERR_PTR(-ENOMEM); - sock = geneve_create_sock(net, ipv6, port, ipv6_rx_csum); - if (IS_ERR(sock)) { + sk = geneve_create_sock(net, ipv6, port, ipv6_rx_csum); + if (IS_ERR(sk)) { kfree(gs); - return ERR_CAST(sock); + return ERR_CAST(sk); } - gs->sock = sock; + gs->sk = sk; gs->refcnt = 1; for (h = 0; h < VNI_HASH_SIZE; ++h) INIT_HLIST_HEAD(&gs->vni_list[h]); /* Initialize the geneve udp offloads structure */ - udp_tunnel_notify_add_rx_port(gs->sock, UDP_TUNNEL_TYPE_GENEVE); + udp_tunnel_notify_add_rx_port(sk, UDP_TUNNEL_TYPE_GENEVE); /* Mark socket as an encapsulation socket */ memset(&tunnel_cfg, 0, sizeof(tunnel_cfg)); @@ -1006,7 +1006,7 @@ static struct geneve_sock *geneve_socket_create(struct net *net, __be16 port, tunnel_cfg.encap_rcv = geneve_udp_encap_recv; tunnel_cfg.encap_err_lookup = geneve_udp_encap_err_lookup; tunnel_cfg.encap_destroy = NULL; - setup_udp_tunnel_sock(net, sock, &tunnel_cfg); + setup_udp_tunnel_sock(net, sk, &tunnel_cfg); list_add(&gs->list, &gn->sock_list); return gs; } @@ -1017,8 +1017,8 @@ static void __geneve_sock_release(struct geneve_sock *gs) return; list_del(&gs->list); - udp_tunnel_notify_del_rx_port(gs->sock, UDP_TUNNEL_TYPE_GENEVE); - udp_tunnel_sock_release(gs->sock); + udp_tunnel_notify_del_rx_port(gs->sk, UDP_TUNNEL_TYPE_GENEVE); + udp_tunnel_sock_release(gs->sk); kfree_rcu(gs, rcu); } @@ -1048,7 +1048,7 @@ static struct geneve_sock *geneve_find_sock(struct geneve_net *gn, struct geneve_sock *gs; list_for_each_entry(gs, &gn->sock_list, list) { - if (inet_sk(gs->sock->sk)->inet_sport == dst_port && + if (inet_sk(gs->sk)->inet_sport == dst_port && geneve_get_sk_family(gs) == family && gs->gro_hint == gro_hint) { return gs; @@ -1390,7 +1390,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, if (unlikely(err)) return err; - udp_tunnel_xmit_skb(rt, gs4->sock->sk, skb, saddr, info->key.u.ipv4.dst, + udp_tunnel_xmit_skb(rt, gs4->sk, skb, saddr, info->key.u.ipv4.dst, tos, ttl, df, sport, geneve->cfg.info.key.tp_dst, !net_eq(geneve->net, dev_net(geneve->dev)), !test_bit(IP_TUNNEL_CSUM_BIT, info->key.tun_flags), @@ -1424,7 +1424,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, geneve->cfg.port_min, geneve->cfg.port_max, true); - dst = udp_tunnel6_dst_lookup(skb, dev, geneve->net, gs6->sock, 0, + dst = udp_tunnel6_dst_lookup(skb, dev, geneve->net, gs6->sk, 0, &saddr, key, sport, geneve->cfg.info.key.tp_dst, prio, use_cache ? @@ -1480,7 +1480,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, if (unlikely(err)) return err; - udp_tunnel6_xmit_skb(dst, gs6->sock->sk, skb, dev, + udp_tunnel6_xmit_skb(dst, gs6->sk, skb, dev, &saddr, &key->u.ipv6.dst, prio, ttl, info->key.label, sport, geneve->cfg.info.key.tp_dst, !test_bit(IP_TUNNEL_CSUM_BIT, @@ -1592,7 +1592,7 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) geneve->cfg.port_min, geneve->cfg.port_max, true); - dst = udp_tunnel6_dst_lookup(skb, dev, geneve->net, gs6->sock, 0, + dst = udp_tunnel6_dst_lookup(skb, dev, geneve->net, gs6->sk, 0, &saddr, &info->key, sport, geneve->cfg.info.key.tp_dst, prio, use_cache ? &info->dst_cache : NULL); @@ -1654,10 +1654,10 @@ static void geneve_offload_rx_ports(struct net_device *dev, bool push) list_for_each_entry(gs, &gn->sock_list, list) { if (push) { - udp_tunnel_push_rx_port(dev, gs->sock, + udp_tunnel_push_rx_port(dev, gs->sk, UDP_TUNNEL_TYPE_GENEVE); } else { - udp_tunnel_drop_rx_port(dev, gs->sock, + udp_tunnel_drop_rx_port(dev, gs->sk, UDP_TUNNEL_TYPE_GENEVE); } } @@ -2183,12 +2183,12 @@ static void geneve_quiesce(struct geneve_dev *geneve, struct geneve_sock **gs4, *gs4 = rtnl_dereference(geneve->sock4); rcu_assign_pointer(geneve->sock4, NULL); if (*gs4) - rcu_assign_sk_user_data((*gs4)->sock->sk, NULL); + rcu_assign_sk_user_data((*gs4)->sk, NULL); #if IS_ENABLED(CONFIG_IPV6) *gs6 = rtnl_dereference(geneve->sock6); rcu_assign_pointer(geneve->sock6, NULL); if (*gs6) - rcu_assign_sk_user_data((*gs6)->sock->sk, NULL); + rcu_assign_sk_user_data((*gs6)->sk, NULL); #else *gs6 = NULL; #endif @@ -2201,11 +2201,11 @@ static void geneve_unquiesce(struct geneve_dev *geneve, struct geneve_sock *gs4, { rcu_assign_pointer(geneve->sock4, gs4); if (gs4) - rcu_assign_sk_user_data(gs4->sock->sk, gs4); + rcu_assign_sk_user_data(gs4->sk, gs4); #if IS_ENABLED(CONFIG_IPV6) rcu_assign_pointer(geneve->sock6, gs6); if (gs6) - rcu_assign_sk_user_data(gs6->sock->sk, gs6); + rcu_assign_sk_user_data(gs6->sk, gs6); #endif synchronize_net(); } diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 5150f2e4f66b..a60ef32b35b8 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -885,8 +885,8 @@ static void gtp_encap_disable_sock(struct sock *sk) static void gtp_encap_disable(struct gtp_dev *gtp) { if (gtp->sk_created) { - udp_tunnel_sock_release(gtp->sk0->sk_socket); - udp_tunnel_sock_release(gtp->sk1u->sk_socket); + udp_tunnel_sock_release(gtp->sk0); + udp_tunnel_sock_release(gtp->sk1u); gtp->sk_created = false; gtp->sk0 = NULL; gtp->sk1u = NULL; @@ -1434,7 +1434,7 @@ static struct sock *gtp_create_sock(int type, struct gtp_dev *gtp, tuncfg.encap_rcv = gtp_encap_recv; tuncfg.encap_destroy = NULL; - setup_udp_tunnel_sock(net, sock, &tuncfg); + setup_udp_tunnel_sock(net, sock->sk, &tuncfg); return sock->sk; } @@ -1451,7 +1451,7 @@ static int gtp_create_sockets(struct gtp_dev *gtp, const struct nlattr *nla, sk1u = gtp_create_sock(UDP_ENCAP_GTP1U, gtp, nla, family); if (IS_ERR(sk1u)) { - udp_tunnel_sock_release(sk0->sk_socket); + udp_tunnel_sock_release(sk0); return PTR_ERR(sk1u); } @@ -1689,7 +1689,7 @@ static struct sock *gtp_encap_enable_socket(int fd, int type, tuncfg.encap_rcv = gtp_encap_recv; tuncfg.encap_destroy = gtp_encap_destroy; - setup_udp_tunnel_sock(sock_net(sock->sk), sock, &tuncfg); + setup_udp_tunnel_sock(sock_net(sock->sk), sk, &tuncfg); out_rel_sock: release_sock(sock->sk); diff --git a/drivers/net/ovpn/udp.c b/drivers/net/ovpn/udp.c index 059e896b4a2f..493a5a0744af 100644 --- a/drivers/net/ovpn/udp.c +++ b/drivers/net/ovpn/udp.c @@ -399,7 +399,7 @@ int ovpn_udp_socket_attach(struct ovpn_socket *ovpn_sock, struct socket *sock, if (!old_data) { /* socket is currently unused - we can take it */ rcu_read_unlock(); - setup_udp_tunnel_sock(sock_net(ovpn_sock->sk), sock, &cfg); + setup_udp_tunnel_sock(sock_net(ovpn_sock->sk), sock->sk, &cfg); return 0; } diff --git a/drivers/net/pfcp.c b/drivers/net/pfcp.c index 28e6bc4a1f14..5f1c9d2c0b49 100644 --- a/drivers/net/pfcp.c +++ b/drivers/net/pfcp.c @@ -18,7 +18,7 @@ struct pfcp_dev { struct list_head list; - struct socket *sock; + struct sock *sk; struct net_device *dev; struct net *net; @@ -104,8 +104,8 @@ drop: static void pfcp_del_sock(struct pfcp_dev *pfcp) { - udp_tunnel_sock_release(pfcp->sock); - pfcp->sock = NULL; + udp_tunnel_sock_release(pfcp->sk); + pfcp->sk = NULL; } static void pfcp_dev_uninit(struct net_device *dev) @@ -151,7 +151,7 @@ static void pfcp_link_setup(struct net_device *dev) netif_keep_dst(dev); } -static struct socket *pfcp_create_sock(struct pfcp_dev *pfcp) +static struct sock *pfcp_create_sock(struct pfcp_dev *pfcp) { struct udp_tunnel_sock_cfg tuncfg = {}; struct udp_port_cfg udp_conf = { @@ -172,16 +172,16 @@ static struct socket *pfcp_create_sock(struct pfcp_dev *pfcp) tuncfg.encap_rcv = pfcp_encap_recv; tuncfg.encap_type = 1; - setup_udp_tunnel_sock(net, sock, &tuncfg); + setup_udp_tunnel_sock(net, sock->sk, &tuncfg); - return sock; + return sock->sk; } static int pfcp_add_sock(struct pfcp_dev *pfcp) { - pfcp->sock = pfcp_create_sock(pfcp); + pfcp->sk = pfcp_create_sock(pfcp); - return PTR_ERR_OR_ZERO(pfcp->sock); + return PTR_ERR_OR_ZERO(pfcp->sk); } static int pfcp_newlink(struct net_device *dev, @@ -216,6 +216,7 @@ static int pfcp_newlink(struct net_device *dev, exit_del_pfcp_sock: pfcp_del_sock(pfcp); + synchronize_rcu(); exit_err: pfcp->net = NULL; return err; diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index e88798497503..00facbfabced 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -88,10 +88,10 @@ static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family, flags &= VXLAN_F_RCV_FLAGS; hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) { - if (inet_sk(vs->sock->sk)->inet_sport == port && + if (inet_sk(vs->sk)->inet_sport == port && vxlan_get_sk_family(vs) == family && vs->flags == flags && - vs->sock->sk->sk_bound_dev_if == ifindex) + vs->sk->sk_bound_dev_if == ifindex) return vs; } return NULL; @@ -657,14 +657,18 @@ static struct vxlanhdr *vxlan_gro_prepare_receive(struct sock *sk, struct sk_buff *skb, struct gro_remcsum *grc) { - struct sk_buff *p; struct vxlanhdr *vh, *vh2; unsigned int hlen, off_vx; - struct vxlan_sock *vs = rcu_dereference_sk_user_data(sk); + struct vxlan_sock *vs; + struct sk_buff *p; __be32 flags; skb_gro_remcsum_init(grc); + vs = rcu_dereference_sk_user_data(sk); + if (!vs) + return NULL; + off_vx = skb_gro_offset(skb); hlen = off_vx + sizeof(*vh); vh = skb_gro_header(skb, hlen, off_vx); @@ -1493,7 +1497,7 @@ static bool __vxlan_sock_release_prep(struct vxlan_sock *vs) return false; hlist_del_rcu(&vs->hlist); - udp_tunnel_notify_del_rx_port(vs->sock, + udp_tunnel_notify_del_rx_port(vs->sk, (vs->flags & VXLAN_F_GPE) ? UDP_TUNNEL_TYPE_VXLAN_GPE : UDP_TUNNEL_TYPE_VXLAN); @@ -1519,14 +1523,14 @@ static void vxlan_sock_release(struct vxlan_dev *vxlan) vxlan_vs_del_dev(vxlan); if (__vxlan_sock_release_prep(sock4)) { - udp_tunnel_sock_release(sock4->sock); - kfree(sock4); + udp_tunnel_sock_release(sock4->sk); + kfree_rcu(sock4, rcu); } #if IS_ENABLED(CONFIG_IPV6) if (__vxlan_sock_release_prep(sock6)) { - udp_tunnel_sock_release(sock6->sock); - kfree(sock6); + udp_tunnel_sock_release(sock6->sk); + kfree_rcu(sock6, rcu); } #endif } @@ -2473,7 +2477,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, } if (!ifindex) - ifindex = sock4->sock->sk->sk_bound_dev_if; + ifindex = sock4->sk->sk_bound_dev_if; rt = udp_tunnel_dst_lookup(skb, dev, vxlan->net, ifindex, &saddr, pkey, src_port, dst_port, @@ -2540,7 +2544,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, goto tx_error; } - udp_tunnel_xmit_skb(rt, sock4->sock->sk, skb, saddr, + udp_tunnel_xmit_skb(rt, sock4->sk, skb, saddr, pkey->u.ipv4.dst, tos, ttl, df, src_port, dst_port, xnet, !udp_sum, ipcb_flags); @@ -2557,9 +2561,9 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, } if (!ifindex) - ifindex = sock6->sock->sk->sk_bound_dev_if; + ifindex = sock6->sk->sk_bound_dev_if; - ndst = udp_tunnel6_dst_lookup(skb, dev, vxlan->net, sock6->sock, + ndst = udp_tunnel6_dst_lookup(skb, dev, vxlan->net, sock6->sk, ifindex, &saddr, pkey, src_port, dst_port, tos, use_cache ? dst_cache : NULL); @@ -2615,7 +2619,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, goto tx_error; } - udp_tunnel6_xmit_skb(ndst, sock6->sock->sk, skb, dev, + udp_tunnel6_xmit_skb(ndst, sock6->sk, skb, dev, &saddr, &pkey->u.ipv6.dst, tos, ttl, pkey->label, src_port, dst_port, !udp_sum, ip6cb_flags); @@ -3254,7 +3258,7 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) if (!sock6) return -EIO; - ndst = udp_tunnel6_dst_lookup(skb, dev, vxlan->net, sock6->sock, + ndst = udp_tunnel6_dst_lookup(skb, dev, vxlan->net, sock6->sk, 0, &info->key.u.ipv6.src, &info->key, sport, dport, info->key.tos, @@ -3332,9 +3336,9 @@ static void vxlan_offload_rx_ports(struct net_device *dev, bool push) type = UDP_TUNNEL_TYPE_VXLAN; if (push) - udp_tunnel_push_rx_port(dev, vs->sock, type); + udp_tunnel_push_rx_port(dev, vs->sk, type); else - udp_tunnel_drop_rx_port(dev, vs->sock, type); + udp_tunnel_drop_rx_port(dev, vs->sk, type); } } } @@ -3540,8 +3544,8 @@ static const struct ethtool_ops vxlan_ethtool_ops = { .get_link_ksettings = vxlan_get_link_ksettings, }; -static struct socket *vxlan_create_sock(struct net *net, bool ipv6, - __be16 port, u32 flags, int ifindex) +static struct sock *vxlan_create_sock(struct net *net, bool ipv6, + __be16 port, u32 flags, int ifindex) { struct socket *sock; struct udp_port_cfg udp_conf; @@ -3567,7 +3571,7 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6, return ERR_PTR(err); udp_allow_gso(sock->sk); - return sock; + return sock->sk; } /* Create new listen socket if needed */ @@ -3575,10 +3579,10 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6, __be16 port, u32 flags, int ifindex) { + struct udp_tunnel_sock_cfg tunnel_cfg; struct vxlan_sock *vs; - struct socket *sock; + struct sock *sk; unsigned int h; - struct udp_tunnel_sock_cfg tunnel_cfg; ASSERT_RTNL(); @@ -3589,18 +3593,18 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6, for (h = 0; h < VNI_HASH_SIZE; ++h) INIT_HLIST_HEAD(&vs->vni_list[h]); - sock = vxlan_create_sock(net, ipv6, port, flags, ifindex); - if (IS_ERR(sock)) { + sk = vxlan_create_sock(net, ipv6, port, flags, ifindex); + if (IS_ERR(sk)) { kfree(vs); - return ERR_CAST(sock); + return ERR_CAST(sk); } - vs->sock = sock; + vs->sk = sk; refcount_set(&vs->refcnt, 1); vs->flags = (flags & VXLAN_F_RCV_FLAGS); hlist_add_head_rcu(&vs->hlist, vs_head(net, port)); - udp_tunnel_notify_add_rx_port(sock, + udp_tunnel_notify_add_rx_port(sk, (vs->flags & VXLAN_F_GPE) ? UDP_TUNNEL_TYPE_VXLAN_GPE : UDP_TUNNEL_TYPE_VXLAN); @@ -3620,7 +3624,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6, tunnel_cfg.gro_complete = vxlan_gro_complete; } - setup_udp_tunnel_sock(net, sock, &tunnel_cfg); + setup_udp_tunnel_sock(net, sk, &tunnel_cfg); return vs; } diff --git a/drivers/net/vxlan/vxlan_multicast.c b/drivers/net/vxlan/vxlan_multicast.c index b0e80bca855c..3b75b48dc726 100644 --- a/drivers/net/vxlan/vxlan_multicast.c +++ b/drivers/net/vxlan/vxlan_multicast.c @@ -29,7 +29,7 @@ int vxlan_igmp_join(struct vxlan_dev *vxlan, union vxlan_addr *rip, .imr_ifindex = ifindex, }; - sk = sock4->sock->sk; + sk = sock4->sk; lock_sock(sk); ret = ip_mc_join_group(sk, &mreq); release_sock(sk); @@ -37,7 +37,7 @@ int vxlan_igmp_join(struct vxlan_dev *vxlan, union vxlan_addr *rip, } else { struct vxlan_sock *sock6 = rtnl_dereference(vxlan->vn6_sock); - sk = sock6->sock->sk; + sk = sock6->sk; lock_sock(sk); ret = ipv6_sock_mc_join(sk, ifindex, &ip->sin6.sin6_addr); release_sock(sk); @@ -62,7 +62,7 @@ int vxlan_igmp_leave(struct vxlan_dev *vxlan, union vxlan_addr *rip, .imr_ifindex = ifindex, }; - sk = sock4->sock->sk; + sk = sock4->sk; lock_sock(sk); ret = ip_mc_leave_group(sk, &mreq); release_sock(sk); @@ -70,7 +70,7 @@ int vxlan_igmp_leave(struct vxlan_dev *vxlan, union vxlan_addr *rip, } else { struct vxlan_sock *sock6 = rtnl_dereference(vxlan->vn6_sock); - sk = sock6->sock->sk; + sk = sock6->sk; lock_sock(sk); ret = ipv6_sock_mc_drop(sk, ifindex, &ip->sin6.sin6_addr); release_sock(sk); diff --git a/drivers/net/wireguard/socket.c b/drivers/net/wireguard/socket.c index c362c78d908e..0028ef17dc71 100644 --- a/drivers/net/wireguard/socket.c +++ b/drivers/net/wireguard/socket.c @@ -335,7 +335,7 @@ static void sock_free(struct sock *sock) if (unlikely(!sock)) return; sk_clear_memalloc(sock); - udp_tunnel_sock_release(sock->sk_socket); + udp_tunnel_sock_release(sock); } static void set_sock_opts(struct socket *sock) @@ -389,14 +389,14 @@ retry: goto out; } set_sock_opts(new4); - setup_udp_tunnel_sock(net, new4, &cfg); + setup_udp_tunnel_sock(net, new4->sk, &cfg); #if IS_ENABLED(CONFIG_IPV6) if (ipv6_mod_enabled()) { port6.local_udp_port = inet_sk(new4->sk)->inet_sport; ret = udp_sock_create(net, &port6, &new6); if (ret < 0) { - udp_tunnel_sock_release(new4); + udp_tunnel_sock_release(new4->sk); if (ret == -EADDRINUSE && !port && retries++ < 100) goto retry; pr_err("%s: Could not create IPv6 socket\n", @@ -404,7 +404,7 @@ retry: goto out; } set_sock_opts(new6); - setup_udp_tunnel_sock(net, new6, &cfg); + setup_udp_tunnel_sock(net, new6->sk, &cfg); } #endif diff --git a/include/net/amt.h b/include/net/amt.h index c881bc8b673b..a0255491f5b0 100644 --- a/include/net/amt.h +++ b/include/net/amt.h @@ -331,7 +331,7 @@ struct amt_dev { enum amt_status status; /* Generated key */ siphash_key_t key; - struct socket __rcu *sock; + struct sock __rcu *sk; u32 max_groups; u32 max_sources; u32 hash_buckets; diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h index 47c23d4a1740..498b7b262fa9 100644 --- a/include/net/udp_tunnel.h +++ b/include/net/udp_tunnel.h @@ -94,7 +94,7 @@ struct udp_tunnel_sock_cfg { }; /* Setup the given (UDP) sock to receive UDP encapsulated packets */ -void setup_udp_tunnel_sock(struct net *net, struct socket *sock, +void setup_udp_tunnel_sock(struct net *net, struct sock *sk, struct udp_tunnel_sock_cfg *sock_cfg); /* -- List of parsable UDP tunnel types -- @@ -127,12 +127,12 @@ struct udp_tunnel_info { }; /* Notify network devices of offloadable types */ -void udp_tunnel_push_rx_port(struct net_device *dev, struct socket *sock, +void udp_tunnel_push_rx_port(struct net_device *dev, struct sock *sk, unsigned short type); -void udp_tunnel_drop_rx_port(struct net_device *dev, struct socket *sock, +void udp_tunnel_drop_rx_port(struct net_device *dev, struct sock *sk, unsigned short type); -void udp_tunnel_notify_add_rx_port(struct socket *sock, unsigned short type); -void udp_tunnel_notify_del_rx_port(struct socket *sock, unsigned short type); +void udp_tunnel_notify_add_rx_port(struct sock *sk, unsigned short type); +void udp_tunnel_notify_del_rx_port(struct sock *sk, unsigned short type); /* Transmit the skb using UDP encapsulation. */ void udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb, @@ -176,7 +176,7 @@ static inline void udp_tunnel_set_inner_protocol(struct sk_buff *skb, skb_set_inner_protocol(skb, inner_proto); } -void udp_tunnel_sock_release(struct socket *sock); +void udp_tunnel_sock_release(struct sock *sk); struct rtable *udp_tunnel_dst_lookup(struct sk_buff *skb, struct net_device *dev, @@ -188,7 +188,7 @@ struct rtable *udp_tunnel_dst_lookup(struct sk_buff *skb, struct dst_entry *udp_tunnel6_dst_lookup(struct sk_buff *skb, struct net_device *dev, struct net *net, - struct socket *sock, int oif, + struct sock *sk, int oif, struct in6_addr *saddr, const struct ip_tunnel_key *key, __be16 sport, __be16 dport, u8 dsfield, diff --git a/include/net/vxlan.h b/include/net/vxlan.h index 0ee50785f4f1..dfba89695efc 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -185,7 +185,8 @@ struct vxlan_metadata { /* per UDP socket information */ struct vxlan_sock { struct hlist_node hlist; - struct socket *sock; + struct sock *sk; + struct rcu_head rcu; struct hlist_head vni_list[VNI_HASH_SIZE]; refcount_t refcnt; u32 flags; @@ -448,7 +449,7 @@ static inline __be32 vxlan_compute_rco(unsigned int start, unsigned int offset) static inline unsigned short vxlan_get_sk_family(struct vxlan_sock *vs) { - return vs->sock->sk->sk_family; + return vs->sk->sk_family; } #if IS_ENABLED(CONFIG_IPV6) diff --git a/net/ipv4/fou_core.c b/net/ipv4/fou_core.c index 5bae3cf7fe76..865bd7205122 100644 --- a/net/ipv4/fou_core.c +++ b/net/ipv4/fou_core.c @@ -22,7 +22,7 @@ #include "fou_nl.h" struct fou { - struct socket *sock; + struct sock *sk; u8 protocol; u8 flags; __be16 port; @@ -508,8 +508,8 @@ out: static bool fou_cfg_cmp(struct fou *fou, struct fou_cfg *cfg) { - struct sock *sk = fou->sock->sk; struct udp_port_cfg *udp_cfg = &cfg->udp_config; + struct sock *sk = fou->sk; if (fou->family != udp_cfg->family || fou->port != udp_cfg->local_udp_port || @@ -558,11 +558,8 @@ static int fou_add_to_port_list(struct net *net, struct fou *fou, static void fou_release(struct fou *fou) { - struct socket *sock = fou->sock; - list_del(&fou->list); - udp_tunnel_sock_release(sock); - + udp_tunnel_sock_release(fou->sk); kfree_rcu(fou, rcu); } @@ -593,7 +590,7 @@ static int fou_create(struct net *net, struct fou_cfg *cfg, fou->family = cfg->udp_config.family; fou->flags = cfg->flags; fou->type = cfg->type; - fou->sock = sock; + fou->sk = sk; memset(&tunnel_cfg, 0, sizeof(tunnel_cfg)); tunnel_cfg.encap_type = 1; @@ -618,7 +615,7 @@ static int fou_create(struct net *net, struct fou_cfg *cfg, goto error; } - setup_udp_tunnel_sock(net, sock, &tunnel_cfg); + setup_udp_tunnel_sock(net, sk, &tunnel_cfg); sk->sk_allocation = GFP_ATOMIC; @@ -634,7 +631,7 @@ static int fou_create(struct net *net, struct fou_cfg *cfg, error: kfree(fou); if (sock) - udp_tunnel_sock_release(sock); + udp_tunnel_sock_release(sock->sk); return err; } @@ -779,9 +776,9 @@ int fou_nl_del_doit(struct sk_buff *skb, struct genl_info *info) static int fou_fill_info(struct fou *fou, struct sk_buff *msg) { - struct sock *sk = fou->sock->sk; + struct sock *sk = fou->sk; - if (nla_put_u8(msg, FOU_ATTR_AF, fou->sock->sk->sk_family) || + if (nla_put_u8(msg, FOU_ATTR_AF, sk->sk_family) || nla_put_be16(msg, FOU_ATTR_PORT, fou->port) || nla_put_be16(msg, FOU_ATTR_PEER_PORT, sk->sk_dport) || nla_put_u8(msg, FOU_ATTR_IPPROTO, fou->protocol) || @@ -793,7 +790,7 @@ static int fou_fill_info(struct fou *fou, struct sk_buff *msg) if (nla_put_flag(msg, FOU_ATTR_REMCSUM_NOPARTIAL)) return -1; - if (fou->sock->sk->sk_family == AF_INET) { + if (sk->sk_family == AF_INET) { if (nla_put_in_addr(msg, FOU_ATTR_LOCAL_V4, sk->sk_rcv_saddr)) return -1; diff --git a/net/ipv4/udp_tunnel_core.c b/net/ipv4/udp_tunnel_core.c index b1f667c52cb2..9ab3728f9630 100644 --- a/net/ipv4/udp_tunnel_core.c +++ b/net/ipv4/udp_tunnel_core.c @@ -68,11 +68,9 @@ static bool sk_saddr_any(struct sock *sk) #endif } -void setup_udp_tunnel_sock(struct net *net, struct socket *sock, +void setup_udp_tunnel_sock(struct net *net, struct sock *sk, struct udp_tunnel_sock_cfg *cfg) { - struct sock *sk = sock->sk; - /* Disable multicast loopback */ inet_clear_bit(MC_LOOP, sk); @@ -99,10 +97,9 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock, } EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock); -void udp_tunnel_push_rx_port(struct net_device *dev, struct socket *sock, +void udp_tunnel_push_rx_port(struct net_device *dev, struct sock *sk, unsigned short type) { - struct sock *sk = sock->sk; struct udp_tunnel_info ti; ti.type = type; @@ -113,10 +110,9 @@ void udp_tunnel_push_rx_port(struct net_device *dev, struct socket *sock, } EXPORT_SYMBOL_GPL(udp_tunnel_push_rx_port); -void udp_tunnel_drop_rx_port(struct net_device *dev, struct socket *sock, +void udp_tunnel_drop_rx_port(struct net_device *dev, struct sock *sk, unsigned short type) { - struct sock *sk = sock->sk; struct udp_tunnel_info ti; ti.type = type; @@ -128,9 +124,8 @@ void udp_tunnel_drop_rx_port(struct net_device *dev, struct socket *sock, EXPORT_SYMBOL_GPL(udp_tunnel_drop_rx_port); /* Notify netdevs that UDP port started listening */ -void udp_tunnel_notify_add_rx_port(struct socket *sock, unsigned short type) +void udp_tunnel_notify_add_rx_port(struct sock *sk, unsigned short type) { - struct sock *sk = sock->sk; struct net *net = sock_net(sk); struct udp_tunnel_info ti; struct net_device *dev; @@ -150,9 +145,8 @@ void udp_tunnel_notify_add_rx_port(struct socket *sock, unsigned short type) EXPORT_SYMBOL_GPL(udp_tunnel_notify_add_rx_port); /* Notify netdevs that UDP port is no more listening */ -void udp_tunnel_notify_del_rx_port(struct socket *sock, unsigned short type) +void udp_tunnel_notify_del_rx_port(struct sock *sk, unsigned short type) { - struct sock *sk = sock->sk; struct net *net = sock_net(sk); struct udp_tunnel_info ti; struct net_device *dev; @@ -195,10 +189,11 @@ void udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb } EXPORT_SYMBOL_GPL(udp_tunnel_xmit_skb); -void udp_tunnel_sock_release(struct socket *sock) +void udp_tunnel_sock_release(struct sock *sk) { - rcu_assign_sk_user_data(sock->sk, NULL); - synchronize_rcu(); + struct socket *sock = sk->sk_socket; + + rcu_assign_sk_user_data(sk, NULL); kernel_sock_shutdown(sock, SHUT_RDWR); sock_release(sock); } diff --git a/net/ipv6/ip6_udp_tunnel.c b/net/ipv6/ip6_udp_tunnel.c index 405ef1cb8864..9adb5775487f 100644 --- a/net/ipv6/ip6_udp_tunnel.c +++ b/net/ipv6/ip6_udp_tunnel.c @@ -118,7 +118,7 @@ EXPORT_SYMBOL_GPL(udp_tunnel6_xmit_skb); * @skb: Packet for which lookup is done * @dev: Tunnel device * @net: Network namespace of tunnel device - * @sock: Socket which provides route info + * @sk: Socket which provides route info * @oif: Index of the output interface * @saddr: Memory to store the src ip address * @key: Tunnel information @@ -135,7 +135,7 @@ EXPORT_SYMBOL_GPL(udp_tunnel6_xmit_skb); struct dst_entry *udp_tunnel6_dst_lookup(struct sk_buff *skb, struct net_device *dev, struct net *net, - struct socket *sock, + struct sock *sk, int oif, struct in6_addr *saddr, const struct ip_tunnel_key *key, @@ -162,7 +162,7 @@ struct dst_entry *udp_tunnel6_dst_lookup(struct sk_buff *skb, fl6.fl6_dport = dport; fl6.flowlabel = ip6_make_flowinfo(dsfield, key->label); - dst = ip6_dst_lookup_flow(net, sock->sk, &fl6, NULL); + dst = ip6_dst_lookup_flow(net, sk, &fl6, NULL); if (IS_ERR(dst)) { netdev_dbg(dev, "no route to %pI6\n", &fl6.daddr); return ERR_PTR(-ENETUNREACH); diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 157fc23ce4e1..cbc5a3e57b33 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -1683,7 +1683,7 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net, .encap_destroy = l2tp_udp_encap_destroy, }; - setup_udp_tunnel_sock(net, sock, &udp_cfg); + setup_udp_tunnel_sock(net, sock->sk, &udp_cfg); } sk->sk_allocation = GFP_ATOMIC; diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c index 111f574fe667..169f9dfdaa77 100644 --- a/net/rxrpc/local_object.c +++ b/net/rxrpc/local_object.c @@ -194,7 +194,7 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net) tuncfg.encap_rcv = rxrpc_encap_rcv; tuncfg.encap_err_rcv = rxrpc_encap_err_rcv; tuncfg.sk_user_data = local; - setup_udp_tunnel_sock(net, local->socket, &tuncfg); + setup_udp_tunnel_sock(net, local->socket->sk, &tuncfg); /* set the socket up */ usk = local->socket->sk; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 5800e7ee7ea0..5c6fa8e8d34d 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -864,7 +864,7 @@ int sctp_udp_sock_start(struct net *net) tuncfg.encap_type = 1; tuncfg.encap_rcv = sctp_udp_rcv; tuncfg.encap_err_lookup = sctp_udp_v4_err; - setup_udp_tunnel_sock(net, sock, &tuncfg); + setup_udp_tunnel_sock(net, sock->sk, &tuncfg); net->sctp.udp4_sock = sock->sk; #if IS_ENABLED(CONFIG_IPV6) @@ -878,7 +878,7 @@ int sctp_udp_sock_start(struct net *net) err = udp_sock_create(net, &udp_conf, &sock); if (err) { pr_err("Failed to create the SCTP UDP tunneling v6 sock\n"); - udp_tunnel_sock_release(net->sctp.udp4_sock->sk_socket); + udp_tunnel_sock_release(net->sctp.udp4_sock); net->sctp.udp4_sock = NULL; return err; } @@ -886,7 +886,7 @@ int sctp_udp_sock_start(struct net *net) tuncfg.encap_type = 1; tuncfg.encap_rcv = sctp_udp_rcv; tuncfg.encap_err_lookup = sctp_udp_v6_err; - setup_udp_tunnel_sock(net, sock, &tuncfg); + setup_udp_tunnel_sock(net, sock->sk, &tuncfg); net->sctp.udp6_sock = sock->sk; #endif @@ -896,11 +896,11 @@ int sctp_udp_sock_start(struct net *net) void sctp_udp_sock_stop(struct net *net) { if (net->sctp.udp4_sock) { - udp_tunnel_sock_release(net->sctp.udp4_sock->sk_socket); + udp_tunnel_sock_release(net->sctp.udp4_sock); net->sctp.udp4_sock = NULL; } if (net->sctp.udp6_sock) { - udp_tunnel_sock_release(net->sctp.udp6_sock->sk_socket); + udp_tunnel_sock_release(net->sctp.udp6_sock); net->sctp.udp6_sock = NULL; } } diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c index 2c66b356025a..988b8a7f953a 100644 --- a/net/tipc/udp_media.c +++ b/net/tipc/udp_media.c @@ -89,14 +89,14 @@ struct udp_replicast { /** * struct udp_bearer - ip/udp bearer data structure * @bearer: associated generic tipc bearer - * @ubsock: bearer associated socket + * @sk: bearer associated socket * @ifindex: local address scope * @work: used to schedule deferred work on a bearer * @rcast: associated udp_replicast container */ struct udp_bearer { struct tipc_bearer __rcu *bearer; - struct socket *ubsock; + struct sock *sk; u32 ifindex; struct work_struct work; struct udp_replicast rcast; @@ -194,7 +194,7 @@ static int tipc_udp_xmit(struct net *net, struct sk_buff *skb, } ttl = ip4_dst_hoplimit(&rt->dst); - udp_tunnel_xmit_skb(rt, ub->ubsock->sk, skb, src->ipv4.s_addr, + udp_tunnel_xmit_skb(rt, ub->sk, skb, src->ipv4.s_addr, dst->ipv4.s_addr, 0, ttl, 0, src->port, dst->port, false, true, 0); #if IS_ENABLED(CONFIG_IPV6) @@ -206,7 +206,7 @@ static int tipc_udp_xmit(struct net *net, struct sk_buff *skb, .saddr = src->ipv6, .flowi6_proto = IPPROTO_UDP }; - ndst = ip6_dst_lookup_flow(net, ub->ubsock->sk, + ndst = ip6_dst_lookup_flow(net, ub->sk, &fl6, NULL); if (IS_ERR(ndst)) { err = PTR_ERR(ndst); @@ -215,7 +215,7 @@ static int tipc_udp_xmit(struct net *net, struct sk_buff *skb, dst_cache_set_ip6(cache, ndst, &fl6.saddr); } ttl = ip6_dst_hoplimit(ndst); - udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, NULL, + udp_tunnel6_xmit_skb(ndst, ub->sk, skb, NULL, &src->ipv6, &dst->ipv6, 0, ttl, 0, src->port, dst->port, false, 0); #endif @@ -405,9 +405,9 @@ out: static int enable_mcast(struct udp_bearer *ub, struct udp_media_addr *remote) { - int err = 0; + struct sock *sk = ub->sk; struct ip_mreqn mreqn; - struct sock *sk = ub->ubsock->sk; + int err = 0; if (ntohs(remote->proto) == ETH_P_IP) { mreqn.imr_multiaddr = remote->ipv4; @@ -670,6 +670,7 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b, struct nlattr *opts[TIPC_NLA_UDP_MAX + 1]; u8 node_id[NODE_ID_LEN] = {0,}; struct net_device *dev; + struct socket *sock; int rmcast = 0; ub = kzalloc_obj(*ub, GFP_ATOMIC); @@ -764,14 +765,16 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b, goto err; } udp_conf.local_udp_port = local.port; - err = udp_sock_create(net, &udp_conf, &ub->ubsock); + err = udp_sock_create(net, &udp_conf, &sock); if (err) goto err; + + ub->sk = sock->sk; tuncfg.sk_user_data = ub; tuncfg.encap_type = 1; tuncfg.encap_rcv = tipc_udp_recv; tuncfg.encap_destroy = NULL; - setup_udp_tunnel_sock(net, ub->ubsock, &tuncfg); + setup_udp_tunnel_sock(net, ub->sk, &tuncfg); err = dst_cache_init(&ub->rcast.dst_cache, GFP_ATOMIC); if (err) @@ -793,7 +796,8 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b, free: dst_cache_destroy(&ub->rcast.dst_cache); - udp_tunnel_sock_release(ub->ubsock); + udp_tunnel_sock_release(ub->sk); + synchronize_rcu(); err: kfree(ub); return err; @@ -812,10 +816,10 @@ static void cleanup_bearer(struct work_struct *work) kfree_rcu(rcast, rcu); } - tn = tipc_net(sock_net(ub->ubsock->sk)); + tn = tipc_net(sock_net(ub->sk)); dst_cache_destroy(&ub->rcast.dst_cache); - udp_tunnel_sock_release(ub->ubsock); + udp_tunnel_sock_release(ub->sk); /* Note: could use a call_rcu() to avoid another synchronize_net() */ synchronize_net(); @@ -833,11 +837,11 @@ static void tipc_udp_disable(struct tipc_bearer *b) pr_err("UDP bearer instance not found\n"); return; } - sock_set_flag(ub->ubsock->sk, SOCK_DEAD); + sock_set_flag(ub->sk, SOCK_DEAD); RCU_INIT_POINTER(ub->bearer, NULL); /* sock_release need to be done outside of rtnl lock */ - atomic_inc(&tipc_net(sock_net(ub->ubsock->sk))->wq_count); + atomic_inc(&tipc_net(sock_net(ub->sk))->wq_count); INIT_WORK(&ub->work, cleanup_bearer); schedule_work(&ub->work); } |
