summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-05-06 03:47:09 +0300
committerJakub Kicinski <kuba@kernel.org>2026-05-06 03:47:09 +0300
commited36fad2cdcd620130b159be383d74a59097ea50 (patch)
tree37f893d0c7c177e90760cc0a0f51cfb9804bd58a
parent8c699be3dad7bba87cdda485dc099226cfc2f706 (diff)
parent72d3b9a4c2b137b32fdf5342699d16229e2ac75e (diff)
downloadlinux-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.c6
-rw-r--r--drivers/infiniband/sw/rxe/rxe_ns.c4
-rw-r--r--drivers/net/amt.c80
-rw-r--r--drivers/net/bareudp.c51
-rw-r--r--drivers/net/geneve.c54
-rw-r--r--drivers/net/gtp.c10
-rw-r--r--drivers/net/ovpn/udp.c2
-rw-r--r--drivers/net/pfcp.c17
-rw-r--r--drivers/net/vxlan/vxlan_core.c60
-rw-r--r--drivers/net/vxlan/vxlan_multicast.c8
-rw-r--r--drivers/net/wireguard/socket.c8
-rw-r--r--include/net/amt.h2
-rw-r--r--include/net/udp_tunnel.h14
-rw-r--r--include/net/vxlan.h5
-rw-r--r--net/ipv4/fou_core.c21
-rw-r--r--net/ipv4/udp_tunnel_core.c23
-rw-r--r--net/ipv6/ip6_udp_tunnel.c6
-rw-r--r--net/l2tp/l2tp_core.c2
-rw-r--r--net/rxrpc/local_object.c2
-rw-r--r--net/sctp/protocol.c10
-rw-r--r--net/tipc/udp_media.c32
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);
}