aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2015-11-28 15:53:05 -0500
committerPablo Neira Ayuso <pablo@netfilter.org>2015-12-09 07:23:13 -0500
commite639f7ab079b5256660018511d87aa34b54f1a9d (patch)
tree09f266f4a2ad558dced74ac4287a3277cccdc6be /net
parent33d5a7b14bfd02e60af9d223db8dfff0cbcabe6b (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.c1
-rw-r--r--net/netfilter/nf_tables_core.c9
-rw-r--r--net/netfilter/nf_tables_trace.c4
-rw-r--r--net/netfilter/nft_meta.c16
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, &regs.verdict, basechain); 141 info.trace = false;
142 if (static_branch_unlikely(&nft_trace_enabled))
143 nft_trace_init(&info, pkt, &regs.verdict, basechain);
141do_chain: 144do_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
28DEFINE_STATIC_KEY_FALSE(nft_trace_enabled);
29EXPORT_SYMBOL_GPL(nft_trace_enabled);
30
27static int trace_fill_id(struct sk_buff *nlskb, struct sk_buff *skb) 31static 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
27void nft_meta_get_eval(const struct nft_expr *expr, 29void 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}
302EXPORT_SYMBOL_GPL(nft_meta_set_init); 307EXPORT_SYMBOL_GPL(nft_meta_set_init);
@@ -334,6 +339,16 @@ nla_put_failure:
334} 339}
335EXPORT_SYMBOL_GPL(nft_meta_set_dump); 340EXPORT_SYMBOL_GPL(nft_meta_set_dump);
336 341
342void 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}
350EXPORT_SYMBOL_GPL(nft_meta_set_destroy);
351
337static struct nft_expr_type nft_meta_type; 352static struct nft_expr_type nft_meta_type;
338static const struct nft_expr_ops nft_meta_get_ops = { 353static 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