Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ec4c359 authored by Paolo Abeni's avatar Paolo Abeni Committed by Sean Tranchetti
Browse files

udp: implement complete book-keeping for encap_needed



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()

Change-Id: Ie2faefd68ef38dd40494046b9db481044b7c5b3a
CRs-Fixed: 2351793
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git


Git-commit: 60fb9567bf30937e6bedfa939d7c8fd4ee6a1b1c
Signed-off-by: default avatarSean Tranchetti <stranche@codeaurora.org>
parent 4fb57e94
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -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 layers set
					  * this
					  */
	/*
	 * Following member retains the information to create a UDP header
	 * when the socket is uncorked.
+6 −0
Original line number Diff line number Diff line
@@ -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();
+13 −6
Original line number Diff line number Diff line
@@ -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);
@@ -2386,12 +2387,16 @@ 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_key_false(&udp_encap_needed) && up->encap_type) {
	if (static_key_false(&udp_encap_needed)) {
		if (up->encap_type) {
			void (*encap_destroy)(struct sock *sk);
			encap_destroy = ACCESS_ONCE(up->encap_destroy);
			if (encap_destroy)
				encap_destroy(sk);
		}
		if (up->encap_enabled)
			static_key_disable(&udp_encap_needed);
	}
}

/*
@@ -2435,7 +2440,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;
+9 −5
Original line number Diff line number Diff line
@@ -1460,12 +1460,16 @@ void udpv6_destroy_sock(struct sock *sk)
	udp_v6_flush_pending_frames(sk);
	release_sock(sk);

	if (static_key_false(&udpv6_encap_needed) && up->encap_type) {
	if (static_key_false(&udpv6_encap_needed)) {
		if (up->encap_type) {
			void (*encap_destroy)(struct sock *sk);
			encap_destroy = ACCESS_ONCE(up->encap_destroy);
			if (encap_destroy)
				encap_destroy(sk);
		}
		if (up->encap_enabled)
			static_key_disable(&udpv6_encap_needed);
	}

	inet6_destroy_sock(sk);
}