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>
This commit is contained in:
parent
33d5a7b14b
commit
e639f7ab07
|
@ -57,6 +57,7 @@ struct nft_payload_set {
|
|||
};
|
||||
|
||||
extern const struct nft_expr_ops nft_payload_fast_ops;
|
||||
extern struct static_key_false nft_trace_enabled;
|
||||
|
||||
int nft_payload_module_init(void);
|
||||
void nft_payload_module_exit(void);
|
||||
|
|
|
@ -33,4 +33,7 @@ void nft_meta_set_eval(const struct nft_expr *expr,
|
|||
struct nft_regs *regs,
|
||||
const struct nft_pktinfo *pkt);
|
||||
|
||||
void nft_meta_set_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_expr *expr);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -84,6 +84,7 @@ static const struct nft_expr_ops nft_meta_bridge_set_ops = {
|
|||
.size = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
|
||||
.eval = nft_meta_set_eval,
|
||||
.init = nft_meta_set_init,
|
||||
.destroy = nft_meta_set_destroy,
|
||||
.dump = nft_meta_set_dump,
|
||||
};
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/skbuff.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/static_key.h>
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netfilter/nf_tables.h>
|
||||
#include <net/netfilter/nf_tables_core.h>
|
||||
|
@ -50,7 +51,7 @@ static noinline void __nft_trace_packet(struct nft_traceinfo *info,
|
|||
{
|
||||
const struct nft_pktinfo *pkt = info->pkt;
|
||||
|
||||
if (!pkt->skb->nf_trace)
|
||||
if (!info->trace || !pkt->skb->nf_trace)
|
||||
return;
|
||||
|
||||
info->chain = chain;
|
||||
|
@ -70,7 +71,7 @@ static inline void nft_trace_packet(struct nft_traceinfo *info,
|
|||
int rulenum,
|
||||
enum nft_trace_types type)
|
||||
{
|
||||
if (unlikely(info->trace)) {
|
||||
if (static_branch_unlikely(&nft_trace_enabled)) {
|
||||
info->rule = rule;
|
||||
__nft_trace_packet(info, chain, rulenum, type);
|
||||
}
|
||||
|
@ -137,6 +138,8 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
|
|||
unsigned int gencursor = nft_genmask_cur(net);
|
||||
struct nft_traceinfo info;
|
||||
|
||||
info.trace = false;
|
||||
if (static_branch_unlikely(&nft_trace_enabled))
|
||||
nft_trace_init(&info, pkt, ®s.verdict, basechain);
|
||||
do_chain:
|
||||
rulenum = 0;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/static_key.h>
|
||||
#include <linux/hash.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/if_vlan.h>
|
||||
|
@ -24,6 +25,9 @@
|
|||
#define NFT_TRACETYPE_NETWORK_HSIZE 40
|
||||
#define NFT_TRACETYPE_TRANSPORT_HSIZE 20
|
||||
|
||||
DEFINE_STATIC_KEY_FALSE(nft_trace_enabled);
|
||||
EXPORT_SYMBOL_GPL(nft_trace_enabled);
|
||||
|
||||
static int trace_fill_id(struct sk_buff *nlskb, struct sk_buff *skb)
|
||||
{
|
||||
__be32 id;
|
||||
|
|
|
@ -18,10 +18,12 @@
|
|||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/static_key.h>
|
||||
#include <net/dst.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/tcp_states.h> /* for TCP_TIME_WAIT */
|
||||
#include <net/netfilter/nf_tables.h>
|
||||
#include <net/netfilter/nf_tables_core.h>
|
||||
#include <net/netfilter/nft_meta.h>
|
||||
|
||||
void nft_meta_get_eval(const struct nft_expr *expr,
|
||||
|
@ -297,6 +299,9 @@ int nft_meta_set_init(const struct nft_ctx *ctx,
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (priv->key == NFT_META_NFTRACE)
|
||||
static_branch_inc(&nft_trace_enabled);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_meta_set_init);
|
||||
|
@ -334,6 +339,16 @@ int nft_meta_set_dump(struct sk_buff *skb,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(nft_meta_set_dump);
|
||||
|
||||
void nft_meta_set_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_expr *expr)
|
||||
{
|
||||
const struct nft_meta *priv = nft_expr_priv(expr);
|
||||
|
||||
if (priv->key == NFT_META_NFTRACE)
|
||||
static_branch_dec(&nft_trace_enabled);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_meta_set_destroy);
|
||||
|
||||
static struct nft_expr_type nft_meta_type;
|
||||
static const struct nft_expr_ops nft_meta_get_ops = {
|
||||
.type = &nft_meta_type,
|
||||
|
@ -348,6 +363,7 @@ static const struct nft_expr_ops nft_meta_set_ops = {
|
|||
.size = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
|
||||
.eval = nft_meta_set_eval,
|
||||
.init = nft_meta_set_init,
|
||||
.destroy = nft_meta_set_destroy,
|
||||
.dump = nft_meta_set_dump,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue