Skip to content

Commit 9f08ea8

Browse files
committed
netfilter: nf_tables: keep chain counters away from hot path
These chain counters are only used by the iptables-compat tool, that allow users to use the x_tables extensions from the existing nf_tables framework. This patch makes nf_tables by ~5% for the general usecase, ie. native nft users, where no chain counters are used at all. Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 56a97e7 commit 9f08ea8

File tree

3 files changed

+23
-16
lines changed

3 files changed

+23
-16
lines changed

include/net/netfilter/nf_tables_core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ struct nft_payload_set {
4949
};
5050

5151
extern const struct nft_expr_ops nft_payload_fast_ops;
52+
53+
extern struct static_key_false nft_counters_enabled;
5254
extern struct static_key_false nft_trace_enabled;
5355

5456
#endif /* _NET_NF_TABLES_CORE_H */

net/netfilter/nf_tables_api.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,6 +1240,8 @@ static void nf_tables_chain_destroy(struct nft_chain *chain)
12401240

12411241
module_put(basechain->type->owner);
12421242
free_percpu(basechain->stats);
1243+
if (basechain->stats)
1244+
static_branch_dec(&nft_counters_enabled);
12431245
if (basechain->ops[0].dev != NULL)
12441246
dev_put(basechain->ops[0].dev);
12451247
kfree(basechain);
@@ -1504,14 +1506,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
15041506
return PTR_ERR(stats);
15051507
}
15061508
basechain->stats = stats;
1507-
} else {
1508-
stats = netdev_alloc_pcpu_stats(struct nft_stats);
1509-
if (stats == NULL) {
1510-
nft_chain_release_hook(&hook);
1511-
kfree(basechain);
1512-
return -ENOMEM;
1513-
}
1514-
rcu_assign_pointer(basechain->stats, stats);
1509+
static_branch_inc(&nft_counters_enabled);
15151510
}
15161511

15171512
hookfn = hook.type->hooks[hook.num];

net/netfilter/nf_tables_core.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,22 @@ static bool nft_payload_fast_eval(const struct nft_expr *expr,
114114
return true;
115115
}
116116

117+
DEFINE_STATIC_KEY_FALSE(nft_counters_enabled);
118+
119+
static noinline void nft_update_chain_stats(const struct nft_chain *chain,
120+
const struct nft_pktinfo *pkt)
121+
{
122+
struct nft_stats *stats;
123+
124+
local_bh_disable();
125+
stats = this_cpu_ptr(rcu_dereference(nft_base_chain(chain)->stats));
126+
u64_stats_update_begin(&stats->syncp);
127+
stats->pkts++;
128+
stats->bytes += pkt->skb->len;
129+
u64_stats_update_end(&stats->syncp);
130+
local_bh_enable();
131+
}
132+
117133
struct nft_jumpstack {
118134
const struct nft_chain *chain;
119135
const struct nft_rule *rule;
@@ -130,7 +146,6 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
130146
struct nft_regs regs;
131147
unsigned int stackptr = 0;
132148
struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE];
133-
struct nft_stats *stats;
134149
int rulenum;
135150
unsigned int gencursor = nft_genmask_cur(net);
136151
struct nft_traceinfo info;
@@ -220,13 +235,8 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
220235
nft_trace_packet(&info, basechain, NULL, -1,
221236
NFT_TRACETYPE_POLICY);
222237

223-
rcu_read_lock_bh();
224-
stats = this_cpu_ptr(rcu_dereference(nft_base_chain(basechain)->stats));
225-
u64_stats_update_begin(&stats->syncp);
226-
stats->pkts++;
227-
stats->bytes += pkt->skb->len;
228-
u64_stats_update_end(&stats->syncp);
229-
rcu_read_unlock_bh();
238+
if (static_branch_unlikely(&nft_counters_enabled))
239+
nft_update_chain_stats(basechain, pkt);
230240

231241
return nft_base_chain(basechain)->policy;
232242
}

0 commit comments

Comments
 (0)