Skip to content

Commit

Permalink
udp: implement complete book-keeping for encap_needed
Browse files Browse the repository at this point in the history
The *encap_needed static keys are enabled by UDP tunnels
and several UDP encapsulations type, but they are never
turned off. This can cause unneeded overall performance
degradation for systems where such features are used
transiently.

This patch introduces complete book-keeping for such keys,
decreasing the usage at socket destruction time, if needed,
and avoiding that the same socket could increase the key
usage multiple times.

rfc v3 -> v1:
 - add socket lock around udp_tunnel_encap_enable()

rfc v2 -> rfc v3:
 - use udp_tunnel_encap_enable() in setsockopt()

Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Paolo Abeni authored and David S. Miller committed Nov 8, 2018
1 parent 7e22561 commit 60fb956
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 12 deletions.
7 changes: 6 additions & 1 deletion include/linux/udp.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,12 @@ struct udp_sock {
unsigned int corkflag; /* Cork is required */
__u8 encap_type; /* Is this an Encapsulation socket? */
unsigned char no_check6_tx:1,/* Send zero UDP6 checksums on TX? */
no_check6_rx:1;/* Allow zero UDP6 checksums on RX? */
no_check6_rx:1,/* Allow zero UDP6 checksums on RX? */
encap_enabled:1; /* This socket enabled encap
* processing; UDP tunnels and
* different encapsulation layer set
* this
*/
/*
* Following member retains the information to create a UDP header
* when the socket is uncorked.
Expand Down
6 changes: 6 additions & 0 deletions include/net/udp_tunnel.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@ static inline int udp_tunnel_handle_offloads(struct sk_buff *skb, bool udp_csum)

static inline void udp_tunnel_encap_enable(struct socket *sock)
{
struct udp_sock *up = udp_sk(sock->sk);

if (up->encap_enabled)
return;

up->encap_enabled = 1;
#if IS_ENABLED(CONFIG_IPV6)
if (sock->sk->sk_family == PF_INET6)
ipv6_stub->udpv6_encap_enable();
Expand Down
19 changes: 13 additions & 6 deletions net/ipv4/udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@
#include "udp_impl.h"
#include <net/sock_reuseport.h>
#include <net/addrconf.h>
#include <net/udp_tunnel.h>

struct udp_table udp_table __read_mostly;
EXPORT_SYMBOL(udp_table);
Expand Down Expand Up @@ -2395,11 +2396,15 @@ void udp_destroy_sock(struct sock *sk)
bool slow = lock_sock_fast(sk);
udp_flush_pending_frames(sk);
unlock_sock_fast(sk, slow);
if (static_branch_unlikely(&udp_encap_needed_key) && up->encap_type) {
void (*encap_destroy)(struct sock *sk);
encap_destroy = READ_ONCE(up->encap_destroy);
if (encap_destroy)
encap_destroy(sk);
if (static_branch_unlikely(&udp_encap_needed_key)) {
if (up->encap_type) {
void (*encap_destroy)(struct sock *sk);
encap_destroy = READ_ONCE(up->encap_destroy);
if (encap_destroy)
encap_destroy(sk);
}
if (up->encap_enabled)
static_branch_disable(&udp_encap_needed_key);
}
}

Expand Down Expand Up @@ -2444,7 +2449,9 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
/* FALLTHROUGH */
case UDP_ENCAP_L2TPINUDP:
up->encap_type = val;
udp_encap_enable();
lock_sock(sk);
udp_tunnel_encap_enable(sk->sk_socket);
release_sock(sk);
break;
default:
err = -ENOPROTOOPT;
Expand Down
14 changes: 9 additions & 5 deletions net/ipv6/udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1456,11 +1456,15 @@ void udpv6_destroy_sock(struct sock *sk)
udp_v6_flush_pending_frames(sk);
release_sock(sk);

if (static_branch_unlikely(&udpv6_encap_needed_key) && up->encap_type) {
void (*encap_destroy)(struct sock *sk);
encap_destroy = READ_ONCE(up->encap_destroy);
if (encap_destroy)
encap_destroy(sk);
if (static_branch_unlikely(&udpv6_encap_needed_key)) {
if (up->encap_type) {
void (*encap_destroy)(struct sock *sk);
encap_destroy = READ_ONCE(up->encap_destroy);
if (encap_destroy)
encap_destroy(sk);
}
if (up->encap_enabled)
static_branch_disable(&udpv6_encap_needed_key);
}

inet6_destroy_sock(sk);
Expand Down

0 comments on commit 60fb956

Please sign in to comment.