]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
udp: lockless UDP_ENCAP_L2TPINUDP / UDP_GRO
authorEric Dumazet <edumazet@google.com>
Tue, 12 Sep 2023 09:17:27 +0000 (09:17 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 10 Jan 2024 16:10:28 +0000 (17:10 +0100)
[ Upstream commit ac9a7f4ce5dda1472e8f44096f33066c6ec1a3b4 ]

Move udp->encap_enabled to udp->udp_flags.

Add udp_test_and_set_bit() helper to allow lockless
udp_tunnel_encap_enable() implementation.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Stable-dep-of: 70a36f571362 ("udp: annotate data-races around udp->encap_type")
Signed-off-by: Sasha Levin <sashal@kernel.org>
include/linux/udp.h
include/net/udp_tunnel.h
net/ipv4/udp.c
net/ipv4/udp_tunnel_core.c
net/ipv6/udp.c

index 0e6880856246aece327d95c7bc2b737cd82cc2b9..efd9ab6df379702316d73b94ae4bff14294eb75c 100644 (file)
@@ -37,6 +37,7 @@ enum {
        UDP_FLAGS_GRO_ENABLED,  /* Request GRO aggregation */
        UDP_FLAGS_ACCEPT_FRAGLIST,
        UDP_FLAGS_ACCEPT_L4,
+       UDP_FLAGS_ENCAP_ENABLED, /* This socket enabled encap */
 };
 
 struct udp_sock {
@@ -50,11 +51,7 @@ struct udp_sock {
 
        int              pending;       /* Any pending frames ? */
        __u8             encap_type;    /* Is this an Encapsulation socket? */
-       unsigned char    encap_enabled:1; /* This socket enabled encap
-                                          * processing; UDP tunnels and
-                                          * different encapsulation layer set
-                                          * this
-                                          */
+
 /* indicator bits used by pcflag: */
 #define UDPLITE_BIT      0x1           /* set by udplite proto init function */
 #define UDPLITE_SEND_CC  0x2           /* set via udplite setsockopt         */
@@ -98,6 +95,8 @@ struct udp_sock {
        test_bit(UDP_FLAGS_##nr, &udp_sk(sk)->udp_flags)
 #define udp_set_bit(nr, sk)                    \
        set_bit(UDP_FLAGS_##nr, &udp_sk(sk)->udp_flags)
+#define udp_test_and_set_bit(nr, sk)           \
+       test_and_set_bit(UDP_FLAGS_##nr, &udp_sk(sk)->udp_flags)
 #define udp_clear_bit(nr, sk)                  \
        clear_bit(UDP_FLAGS_##nr, &udp_sk(sk)->udp_flags)
 #define udp_assign_bit(nr, sk, val)            \
index 72394f441dad83c1ad144bd6ff566536dbe46773..e5f81710b18f4fea63148acccbab3b13715f31d9 100644 (file)
@@ -174,16 +174,13 @@ static inline int udp_tunnel_handle_offloads(struct sk_buff *skb, bool udp_csum)
 }
 #endif
 
-static inline void udp_tunnel_encap_enable(struct socket *sock)
+static inline void udp_tunnel_encap_enable(struct sock *sk)
 {
-       struct udp_sock *up = udp_sk(sock->sk);
-
-       if (up->encap_enabled)
+       if (udp_test_and_set_bit(ENCAP_ENABLED, sk))
                return;
 
-       up->encap_enabled = 1;
 #if IS_ENABLED(CONFIG_IPV6)
-       if (sock->sk->sk_family == PF_INET6)
+       if (READ_ONCE(sk->sk_family) == PF_INET6)
                ipv6_stub->udpv6_encap_enable();
 #endif
        udp_encap_enable();
index df0ea45b8b8f2f9ff6da67e70d6c870a6d923b3c..267f77633a8f39d19f352f1e6ebb0469290e52fd 100644 (file)
@@ -2645,7 +2645,7 @@ void udp_destroy_sock(struct sock *sk)
                        if (encap_destroy)
                                encap_destroy(sk);
                }
-               if (up->encap_enabled)
+               if (udp_test_bit(ENCAP_ENABLED, sk))
                        static_branch_dec(&udp_encap_needed_key);
        }
 }
@@ -2700,9 +2700,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
                        fallthrough;
                case UDP_ENCAP_L2TPINUDP:
                        up->encap_type = val;
-                       lock_sock(sk);
-                       udp_tunnel_encap_enable(sk->sk_socket);
-                       release_sock(sk);
+                       udp_tunnel_encap_enable(sk);
                        break;
                default:
                        err = -ENOPROTOOPT;
@@ -2725,14 +2723,12 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
                break;
 
        case UDP_GRO:
-               lock_sock(sk);
 
                /* when enabling GRO, accept the related GSO packet type */
                if (valbool)
-                       udp_tunnel_encap_enable(sk->sk_socket);
+                       udp_tunnel_encap_enable(sk);
                udp_assign_bit(GRO_ENABLED, sk, valbool);
                udp_assign_bit(ACCEPT_L4, sk, valbool);
-               release_sock(sk);
                break;
 
        /*
index 5f8104cf082d0e25a204f1d7ae5c27d9961914ea..732e21b75ba28be9ce08695e6c0ee1c5357a33d4 100644 (file)
@@ -78,7 +78,7 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
        udp_sk(sk)->gro_receive = cfg->gro_receive;
        udp_sk(sk)->gro_complete = cfg->gro_complete;
 
-       udp_tunnel_encap_enable(sock);
+       udp_tunnel_encap_enable(sk);
 }
 EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock);
 
index ddd17b5ea42591fedfa320aa1b576feb8f263978..5b7c4f8e2ed03488349a0f6f3b7f539531e6b29a 100644 (file)
@@ -1688,7 +1688,7 @@ void udpv6_destroy_sock(struct sock *sk)
                        if (encap_destroy)
                                encap_destroy(sk);
                }
-               if (up->encap_enabled) {
+               if (udp_test_bit(ENCAP_ENABLED, sk)) {
                        static_branch_dec(&udpv6_encap_needed_key);
                        udp_encap_disable();
                }