Commit ac9a7f4c authored by Eric Dumazet's avatar Eric Dumazet Committed by Paolo Abeni

udp: lockless UDP_ENCAP_L2TPINUDP / UDP_GRO

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: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarWillem de Bruijn <willemb@google.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent f5f52f08
...@@ -39,6 +39,7 @@ enum { ...@@ -39,6 +39,7 @@ enum {
UDP_FLAGS_GRO_ENABLED, /* Request GRO aggregation */ UDP_FLAGS_GRO_ENABLED, /* Request GRO aggregation */
UDP_FLAGS_ACCEPT_FRAGLIST, UDP_FLAGS_ACCEPT_FRAGLIST,
UDP_FLAGS_ACCEPT_L4, UDP_FLAGS_ACCEPT_L4,
UDP_FLAGS_ENCAP_ENABLED, /* This socket enabled encap */
}; };
struct udp_sock { struct udp_sock {
...@@ -52,11 +53,7 @@ struct udp_sock { ...@@ -52,11 +53,7 @@ struct udp_sock {
int pending; /* Any pending frames ? */ int pending; /* Any pending frames ? */
__u8 encap_type; /* Is this an Encapsulation socket? */ __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: */ /* indicator bits used by pcflag: */
#define UDPLITE_BIT 0x1 /* set by udplite proto init function */ #define UDPLITE_BIT 0x1 /* set by udplite proto init function */
#define UDPLITE_SEND_CC 0x2 /* set via udplite setsockopt */ #define UDPLITE_SEND_CC 0x2 /* set via udplite setsockopt */
...@@ -104,6 +101,8 @@ struct udp_sock { ...@@ -104,6 +101,8 @@ struct udp_sock {
test_bit(UDP_FLAGS_##nr, &udp_sk(sk)->udp_flags) test_bit(UDP_FLAGS_##nr, &udp_sk(sk)->udp_flags)
#define udp_set_bit(nr, sk) \ #define udp_set_bit(nr, sk) \
set_bit(UDP_FLAGS_##nr, &udp_sk(sk)->udp_flags) 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) \ #define udp_clear_bit(nr, sk) \
clear_bit(UDP_FLAGS_##nr, &udp_sk(sk)->udp_flags) clear_bit(UDP_FLAGS_##nr, &udp_sk(sk)->udp_flags)
#define udp_assign_bit(nr, sk, val) \ #define udp_assign_bit(nr, sk, val) \
......
...@@ -174,16 +174,13 @@ static inline int udp_tunnel_handle_offloads(struct sk_buff *skb, bool udp_csum) ...@@ -174,16 +174,13 @@ static inline int udp_tunnel_handle_offloads(struct sk_buff *skb, bool udp_csum)
} }
#endif #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 (udp_test_and_set_bit(ENCAP_ENABLED, sk))
if (up->encap_enabled)
return; return;
up->encap_enabled = 1;
#if IS_ENABLED(CONFIG_IPV6) #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(); ipv6_stub->udpv6_encap_enable();
#endif #endif
udp_encap_enable(); udp_encap_enable();
......
...@@ -2618,7 +2618,7 @@ void udp_destroy_sock(struct sock *sk) ...@@ -2618,7 +2618,7 @@ void udp_destroy_sock(struct sock *sk)
if (encap_destroy) if (encap_destroy)
encap_destroy(sk); encap_destroy(sk);
} }
if (up->encap_enabled) if (udp_test_bit(ENCAP_ENABLED, sk))
static_branch_dec(&udp_encap_needed_key); static_branch_dec(&udp_encap_needed_key);
} }
} }
...@@ -2685,9 +2685,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, ...@@ -2685,9 +2685,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
fallthrough; fallthrough;
case UDP_ENCAP_L2TPINUDP: case UDP_ENCAP_L2TPINUDP:
up->encap_type = val; up->encap_type = val;
lock_sock(sk); udp_tunnel_encap_enable(sk);
udp_tunnel_encap_enable(sk->sk_socket);
release_sock(sk);
break; break;
default: default:
err = -ENOPROTOOPT; err = -ENOPROTOOPT;
...@@ -2710,14 +2708,12 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, ...@@ -2710,14 +2708,12 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
break; break;
case UDP_GRO: case UDP_GRO:
lock_sock(sk);
/* when enabling GRO, accept the related GSO packet type */ /* when enabling GRO, accept the related GSO packet type */
if (valbool) if (valbool)
udp_tunnel_encap_enable(sk->sk_socket); udp_tunnel_encap_enable(sk);
udp_assign_bit(GRO_ENABLED, sk, valbool); udp_assign_bit(GRO_ENABLED, sk, valbool);
udp_assign_bit(ACCEPT_L4, sk, valbool); udp_assign_bit(ACCEPT_L4, sk, valbool);
release_sock(sk);
break; break;
/* /*
......
...@@ -78,7 +78,7 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock, ...@@ -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_receive = cfg->gro_receive;
udp_sk(sk)->gro_complete = cfg->gro_complete; 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); EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock);
......
...@@ -1670,7 +1670,7 @@ void udpv6_destroy_sock(struct sock *sk) ...@@ -1670,7 +1670,7 @@ void udpv6_destroy_sock(struct sock *sk)
if (encap_destroy) if (encap_destroy)
encap_destroy(sk); encap_destroy(sk);
} }
if (up->encap_enabled) { if (udp_test_bit(ENCAP_ENABLED, sk)) {
static_branch_dec(&udpv6_encap_needed_key); static_branch_dec(&udpv6_encap_needed_key);
udp_encap_disable(); udp_encap_disable();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment