udp: intoduce udp_encap_needed static_key
Most machines dont use UDP encapsulation (L2TP) Adds a static_key so that udp_queue_rcv_skb() doesnt have to perform a test if L2TP never setup the encap_rcv on a socket. Idea of this patch came after Simon Horman proposal to add a hook on TCP as well. If static_key is not yet enabled, the fast path does a single JMP . When static_key is enabled, JMP destination is patched to reach the real encap_type/encap_rcv logic, possibly adding cache misses. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Cc: Simon Horman <horms@verge.net.au> Cc: dev@openvswitch.org Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
77577bf932
commit
447167bf56
|
@ -267,4 +267,5 @@ extern void udp_init(void);
|
|||
extern int udp4_ufo_send_check(struct sk_buff *skb);
|
||||
extern struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
|
||||
netdev_features_t features);
|
||||
extern void udp_encap_enable(void);
|
||||
#endif /* _UDP_H */
|
||||
|
|
|
@ -107,6 +107,7 @@
|
|||
#include <net/checksum.h>
|
||||
#include <net/xfrm.h>
|
||||
#include <trace/events/udp.h>
|
||||
#include <linux/static_key.h>
|
||||
#include "udp_impl.h"
|
||||
|
||||
struct udp_table udp_table __read_mostly;
|
||||
|
@ -1379,6 +1380,14 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
|||
|
||||
}
|
||||
|
||||
static struct static_key udp_encap_needed __read_mostly;
|
||||
void udp_encap_enable(void)
|
||||
{
|
||||
if (!static_key_enabled(&udp_encap_needed))
|
||||
static_key_slow_inc(&udp_encap_needed);
|
||||
}
|
||||
EXPORT_SYMBOL(udp_encap_enable);
|
||||
|
||||
/* returns:
|
||||
* -1: error
|
||||
* 0: success
|
||||
|
@ -1400,7 +1409,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
|||
goto drop;
|
||||
nf_reset(skb);
|
||||
|
||||
if (up->encap_type) {
|
||||
if (static_key_false(&udp_encap_needed) && up->encap_type) {
|
||||
int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);
|
||||
|
||||
/*
|
||||
|
@ -1760,6 +1769,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
|
|||
/* FALLTHROUGH */
|
||||
case UDP_ENCAP_L2TPINUDP:
|
||||
up->encap_type = val;
|
||||
udp_encap_enable();
|
||||
break;
|
||||
default:
|
||||
err = -ENOPROTOOPT;
|
||||
|
|
|
@ -1424,6 +1424,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
|
|||
/* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
|
||||
udp_sk(sk)->encap_type = UDP_ENCAP_L2TPINUDP;
|
||||
udp_sk(sk)->encap_rcv = l2tp_udp_encap_recv;
|
||||
udp_encap_enable();
|
||||
}
|
||||
|
||||
sk->sk_user_data = tunnel;
|
||||
|
|
Loading…
Reference in New Issue