diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2012-04-11 19:05:28 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-04-13 13:39:37 -0400 |
commit | 447167bf565a474ff0cfb0f41d54936937479e97 (patch) | |
tree | 38b03cb4e23bec19939545575e36f7395c5b156e /net/ipv4/udp.c | |
parent | 77577bf93275b485cecb4f358a085949c32e9dcd (diff) |
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>
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r-- | net/ipv4/udp.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index fe141052a1be..ad1e0dd4da48 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -107,6 +107,7 @@ | |||
107 | #include <net/checksum.h> | 107 | #include <net/checksum.h> |
108 | #include <net/xfrm.h> | 108 | #include <net/xfrm.h> |
109 | #include <trace/events/udp.h> | 109 | #include <trace/events/udp.h> |
110 | #include <linux/static_key.h> | ||
110 | #include "udp_impl.h" | 111 | #include "udp_impl.h" |
111 | 112 | ||
112 | struct udp_table udp_table __read_mostly; | 113 | struct udp_table udp_table __read_mostly; |
@@ -1379,6 +1380,14 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
1379 | 1380 | ||
1380 | } | 1381 | } |
1381 | 1382 | ||
1383 | static struct static_key udp_encap_needed __read_mostly; | ||
1384 | void udp_encap_enable(void) | ||
1385 | { | ||
1386 | if (!static_key_enabled(&udp_encap_needed)) | ||
1387 | static_key_slow_inc(&udp_encap_needed); | ||
1388 | } | ||
1389 | EXPORT_SYMBOL(udp_encap_enable); | ||
1390 | |||
1382 | /* returns: | 1391 | /* returns: |
1383 | * -1: error | 1392 | * -1: error |
1384 | * 0: success | 1393 | * 0: success |
@@ -1400,7 +1409,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
1400 | goto drop; | 1409 | goto drop; |
1401 | nf_reset(skb); | 1410 | nf_reset(skb); |
1402 | 1411 | ||
1403 | if (up->encap_type) { | 1412 | if (static_key_false(&udp_encap_needed) && up->encap_type) { |
1404 | int (*encap_rcv)(struct sock *sk, struct sk_buff *skb); | 1413 | int (*encap_rcv)(struct sock *sk, struct sk_buff *skb); |
1405 | 1414 | ||
1406 | /* | 1415 | /* |
@@ -1760,6 +1769,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, | |||
1760 | /* FALLTHROUGH */ | 1769 | /* FALLTHROUGH */ |
1761 | case UDP_ENCAP_L2TPINUDP: | 1770 | case UDP_ENCAP_L2TPINUDP: |
1762 | up->encap_type = val; | 1771 | up->encap_type = val; |
1772 | udp_encap_enable(); | ||
1763 | break; | 1773 | break; |
1764 | default: | 1774 | default: |
1765 | err = -ENOPROTOOPT; | 1775 | err = -ENOPROTOOPT; |