diff options
author | Florian Westphal <fw@strlen.de> | 2015-11-28 15:53:05 -0500 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2015-12-09 07:23:13 -0500 |
commit | e639f7ab079b5256660018511d87aa34b54f1a9d (patch) | |
tree | 09f266f4a2ad558dced74ac4287a3277cccdc6be /net | |
parent | 33d5a7b14bfd02e60af9d223db8dfff0cbcabe6b (diff) |
netfilter: nf_tables: wrap tracing with a static key
Only needed when meta nftrace rule(s) were added.
The assumption is that no such rules are active, so the call to
nft_trace_init is "never" needed.
When nftrace rules are active, we always call the nft_trace_* functions,
but will only send netlink messages when all of the following are true:
- traceinfo structure was initialised
- skb->nf_trace == 1
- at least one subscriber to trace group.
Adding an extra conditional
(static_branch ... && skb->nf_trace)
nft_trace_init( ..)
Is possible but results in a larger nft_do_chain footprint.
Signed-off-by: Florian Westphal <fw@strlen.de>
Acked-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/netfilter/nft_meta_bridge.c | 1 | ||||
-rw-r--r-- | net/netfilter/nf_tables_core.c | 9 | ||||
-rw-r--r-- | net/netfilter/nf_tables_trace.c | 4 | ||||
-rw-r--r-- | net/netfilter/nft_meta.c | 16 |
4 files changed, 27 insertions, 3 deletions
diff --git a/net/bridge/netfilter/nft_meta_bridge.c b/net/bridge/netfilter/nft_meta_bridge.c index a21269b83f16..4b901d9f2e7c 100644 --- a/net/bridge/netfilter/nft_meta_bridge.c +++ b/net/bridge/netfilter/nft_meta_bridge.c | |||
@@ -84,6 +84,7 @@ static const struct nft_expr_ops nft_meta_bridge_set_ops = { | |||
84 | .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)), | 84 | .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)), |
85 | .eval = nft_meta_set_eval, | 85 | .eval = nft_meta_set_eval, |
86 | .init = nft_meta_set_init, | 86 | .init = nft_meta_set_init, |
87 | .destroy = nft_meta_set_destroy, | ||
87 | .dump = nft_meta_set_dump, | 88 | .dump = nft_meta_set_dump, |
88 | }; | 89 | }; |
89 | 90 | ||
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 2395de7c8ab2..67fa41d317f6 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
17 | #include <linux/netlink.h> | 17 | #include <linux/netlink.h> |
18 | #include <linux/netfilter.h> | 18 | #include <linux/netfilter.h> |
19 | #include <linux/static_key.h> | ||
19 | #include <linux/netfilter/nfnetlink.h> | 20 | #include <linux/netfilter/nfnetlink.h> |
20 | #include <linux/netfilter/nf_tables.h> | 21 | #include <linux/netfilter/nf_tables.h> |
21 | #include <net/netfilter/nf_tables_core.h> | 22 | #include <net/netfilter/nf_tables_core.h> |
@@ -50,7 +51,7 @@ static noinline void __nft_trace_packet(struct nft_traceinfo *info, | |||
50 | { | 51 | { |
51 | const struct nft_pktinfo *pkt = info->pkt; | 52 | const struct nft_pktinfo *pkt = info->pkt; |
52 | 53 | ||
53 | if (!pkt->skb->nf_trace) | 54 | if (!info->trace || !pkt->skb->nf_trace) |
54 | return; | 55 | return; |
55 | 56 | ||
56 | info->chain = chain; | 57 | info->chain = chain; |
@@ -70,7 +71,7 @@ static inline void nft_trace_packet(struct nft_traceinfo *info, | |||
70 | int rulenum, | 71 | int rulenum, |
71 | enum nft_trace_types type) | 72 | enum nft_trace_types type) |
72 | { | 73 | { |
73 | if (unlikely(info->trace)) { | 74 | if (static_branch_unlikely(&nft_trace_enabled)) { |
74 | info->rule = rule; | 75 | info->rule = rule; |
75 | __nft_trace_packet(info, chain, rulenum, type); | 76 | __nft_trace_packet(info, chain, rulenum, type); |
76 | } | 77 | } |
@@ -137,7 +138,9 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv) | |||
137 | unsigned int gencursor = nft_genmask_cur(net); | 138 | unsigned int gencursor = nft_genmask_cur(net); |
138 | struct nft_traceinfo info; | 139 | struct nft_traceinfo info; |
139 | 140 | ||
140 | nft_trace_init(&info, pkt, ®s.verdict, basechain); | 141 | info.trace = false; |
142 | if (static_branch_unlikely(&nft_trace_enabled)) | ||
143 | nft_trace_init(&info, pkt, ®s.verdict, basechain); | ||
141 | do_chain: | 144 | do_chain: |
142 | rulenum = 0; | 145 | rulenum = 0; |
143 | rule = list_entry(&chain->rules, struct nft_rule, list); | 146 | rule = list_entry(&chain->rules, struct nft_rule, list); |
diff --git a/net/netfilter/nf_tables_trace.c b/net/netfilter/nf_tables_trace.c index 36fd7ad6729a..e9e959f65d91 100644 --- a/net/netfilter/nf_tables_trace.c +++ b/net/netfilter/nf_tables_trace.c | |||
@@ -8,6 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/static_key.h> | ||
11 | #include <linux/hash.h> | 12 | #include <linux/hash.h> |
12 | #include <linux/jhash.h> | 13 | #include <linux/jhash.h> |
13 | #include <linux/if_vlan.h> | 14 | #include <linux/if_vlan.h> |
@@ -24,6 +25,9 @@ | |||
24 | #define NFT_TRACETYPE_NETWORK_HSIZE 40 | 25 | #define NFT_TRACETYPE_NETWORK_HSIZE 40 |
25 | #define NFT_TRACETYPE_TRANSPORT_HSIZE 20 | 26 | #define NFT_TRACETYPE_TRANSPORT_HSIZE 20 |
26 | 27 | ||
28 | DEFINE_STATIC_KEY_FALSE(nft_trace_enabled); | ||
29 | EXPORT_SYMBOL_GPL(nft_trace_enabled); | ||
30 | |||
27 | static int trace_fill_id(struct sk_buff *nlskb, struct sk_buff *skb) | 31 | static int trace_fill_id(struct sk_buff *nlskb, struct sk_buff *skb) |
28 | { | 32 | { |
29 | __be32 id; | 33 | __be32 id; |
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index 9dfaf4d55ee0..85a465b773e5 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c | |||
@@ -18,10 +18,12 @@ | |||
18 | #include <linux/ip.h> | 18 | #include <linux/ip.h> |
19 | #include <linux/ipv6.h> | 19 | #include <linux/ipv6.h> |
20 | #include <linux/smp.h> | 20 | #include <linux/smp.h> |
21 | #include <linux/static_key.h> | ||
21 | #include <net/dst.h> | 22 | #include <net/dst.h> |
22 | #include <net/sock.h> | 23 | #include <net/sock.h> |
23 | #include <net/tcp_states.h> /* for TCP_TIME_WAIT */ | 24 | #include <net/tcp_states.h> /* for TCP_TIME_WAIT */ |
24 | #include <net/netfilter/nf_tables.h> | 25 | #include <net/netfilter/nf_tables.h> |
26 | #include <net/netfilter/nf_tables_core.h> | ||
25 | #include <net/netfilter/nft_meta.h> | 27 | #include <net/netfilter/nft_meta.h> |
26 | 28 | ||
27 | void nft_meta_get_eval(const struct nft_expr *expr, | 29 | void nft_meta_get_eval(const struct nft_expr *expr, |
@@ -297,6 +299,9 @@ int nft_meta_set_init(const struct nft_ctx *ctx, | |||
297 | if (err < 0) | 299 | if (err < 0) |
298 | return err; | 300 | return err; |
299 | 301 | ||
302 | if (priv->key == NFT_META_NFTRACE) | ||
303 | static_branch_inc(&nft_trace_enabled); | ||
304 | |||
300 | return 0; | 305 | return 0; |
301 | } | 306 | } |
302 | EXPORT_SYMBOL_GPL(nft_meta_set_init); | 307 | EXPORT_SYMBOL_GPL(nft_meta_set_init); |
@@ -334,6 +339,16 @@ nla_put_failure: | |||
334 | } | 339 | } |
335 | EXPORT_SYMBOL_GPL(nft_meta_set_dump); | 340 | EXPORT_SYMBOL_GPL(nft_meta_set_dump); |
336 | 341 | ||
342 | void nft_meta_set_destroy(const struct nft_ctx *ctx, | ||
343 | const struct nft_expr *expr) | ||
344 | { | ||
345 | const struct nft_meta *priv = nft_expr_priv(expr); | ||
346 | |||
347 | if (priv->key == NFT_META_NFTRACE) | ||
348 | static_branch_dec(&nft_trace_enabled); | ||
349 | } | ||
350 | EXPORT_SYMBOL_GPL(nft_meta_set_destroy); | ||
351 | |||
337 | static struct nft_expr_type nft_meta_type; | 352 | static struct nft_expr_type nft_meta_type; |
338 | static const struct nft_expr_ops nft_meta_get_ops = { | 353 | static const struct nft_expr_ops nft_meta_get_ops = { |
339 | .type = &nft_meta_type, | 354 | .type = &nft_meta_type, |
@@ -348,6 +363,7 @@ static const struct nft_expr_ops nft_meta_set_ops = { | |||
348 | .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)), | 363 | .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)), |
349 | .eval = nft_meta_set_eval, | 364 | .eval = nft_meta_set_eval, |
350 | .init = nft_meta_set_init, | 365 | .init = nft_meta_set_init, |
366 | .destroy = nft_meta_set_destroy, | ||
351 | .dump = nft_meta_set_dump, | 367 | .dump = nft_meta_set_dump, |
352 | }; | 368 | }; |
353 | 369 | ||