Skip to content

Commit 63e9bbb

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: nf_tables: don't store chain address on jump
Now that the rule trailer/end marker and the rcu head reside in the same structure, we no longer need to save/restore the chain pointer when performing/returning from a jump. We can simply let the trace infra walk the evaluated rule until it hits the end marker and then fetch the chain pointer from there. When the rule is NULL (policy tracing), then chain and basechain pointers were already identical, so just use the basechain. This cuts size of jumpstack in half, from 256 to 128 bytes in 64bit, scripts/stackusage says: nf_tables_core.c:251 nft_do_chain 328 static Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent d4d89e6 commit 63e9bbb

File tree

4 files changed

+44
-28
lines changed

4 files changed

+44
-28
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,6 +1046,18 @@ struct nft_rule_dp {
10461046
__attribute__((aligned(__alignof__(struct nft_expr))));
10471047
};
10481048

1049+
struct nft_rule_dp_last {
1050+
struct nft_rule_dp end; /* end of nft_rule_blob marker */
1051+
struct rcu_head h; /* call_rcu head */
1052+
struct nft_rule_blob *blob; /* ptr to free via call_rcu */
1053+
const struct nft_chain *chain; /* for nftables tracing */
1054+
};
1055+
1056+
static inline const struct nft_rule_dp *nft_rule_next(const struct nft_rule_dp *rule)
1057+
{
1058+
return (void *)rule + sizeof(*rule) + rule->dlen;
1059+
}
1060+
10491061
struct nft_rule_blob {
10501062
unsigned long size;
10511063
unsigned char data[]
@@ -1396,7 +1408,6 @@ void nft_unregister_flowtable_type(struct nf_flowtable_type *type);
13961408
* @packet_dumped: packet headers sent in a previous traceinfo message
13971409
* @pkt: pktinfo currently processed
13981410
* @basechain: base chain currently processed
1399-
* @chain: chain currently processed
14001411
* @rule: rule that was evaluated
14011412
* @verdict: verdict given by rule
14021413
*/
@@ -1408,7 +1419,6 @@ struct nft_traceinfo {
14081419
u32 skbid;
14091420
const struct nft_pktinfo *pkt;
14101421
const struct nft_base_chain *basechain;
1411-
const struct nft_chain *chain;
14121422
const struct nft_rule_dp *rule;
14131423
const struct nft_verdict *verdict;
14141424
};

net/netfilter/nf_tables_api.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2110,13 +2110,6 @@ static void nft_chain_release_hook(struct nft_chain_hook *hook)
21102110
module_put(hook->type->owner);
21112111
}
21122112

2113-
struct nft_rule_dp_last {
2114-
struct nft_rule_dp end; /* end of nft_rule_blob marker */
2115-
struct rcu_head h;
2116-
struct nft_rule_blob *blob;
2117-
const struct nft_chain *chain; /* for tracing */
2118-
};
2119-
21202113
static void nft_last_rule(const struct nft_chain *chain, const void *ptr)
21212114
{
21222115
struct nft_rule_dp_last *lrule;

net/netfilter/nf_tables_core.c

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,28 +42,25 @@ static inline void nf_skip_indirect_calls_enable(void) { }
4242
#endif
4343

4444
static noinline void __nft_trace_packet(struct nft_traceinfo *info,
45-
const struct nft_chain *chain,
4645
enum nft_trace_types type)
4746
{
4847
if (!info->trace || !info->nf_trace)
4948
return;
5049

51-
info->chain = chain;
5250
info->type = type;
5351

5452
nft_trace_notify(info);
5553
}
5654

5755
static inline void nft_trace_packet(const struct nft_pktinfo *pkt,
5856
struct nft_traceinfo *info,
59-
const struct nft_chain *chain,
6057
const struct nft_rule_dp *rule,
6158
enum nft_trace_types type)
6259
{
6360
if (static_branch_unlikely(&nft_trace_enabled)) {
6461
info->nf_trace = pkt->skb->nf_trace;
6562
info->rule = rule;
66-
__nft_trace_packet(info, chain, type);
63+
__nft_trace_packet(info, type);
6764
}
6865
}
6966

@@ -111,7 +108,6 @@ static void nft_cmp16_fast_eval(const struct nft_expr *expr,
111108
}
112109

113110
static noinline void __nft_trace_verdict(struct nft_traceinfo *info,
114-
const struct nft_chain *chain,
115111
const struct nft_regs *regs)
116112
{
117113
enum nft_trace_types type;
@@ -133,17 +129,16 @@ static noinline void __nft_trace_verdict(struct nft_traceinfo *info,
133129
break;
134130
}
135131

136-
__nft_trace_packet(info, chain, type);
132+
__nft_trace_packet(info, type);
137133
}
138134

139135
static inline void nft_trace_verdict(struct nft_traceinfo *info,
140-
const struct nft_chain *chain,
141136
const struct nft_rule_dp *rule,
142137
const struct nft_regs *regs)
143138
{
144139
if (static_branch_unlikely(&nft_trace_enabled)) {
145140
info->rule = rule;
146-
__nft_trace_verdict(info, chain, regs);
141+
__nft_trace_verdict(info, regs);
147142
}
148143
}
149144

@@ -203,7 +198,6 @@ static noinline void nft_update_chain_stats(const struct nft_chain *chain,
203198
}
204199

205200
struct nft_jumpstack {
206-
const struct nft_chain *chain;
207201
const struct nft_rule_dp *rule;
208202
};
209203

@@ -247,7 +241,6 @@ static void expr_call_ops_eval(const struct nft_expr *expr,
247241
#define nft_rule_expr_first(rule) (struct nft_expr *)&rule->data[0]
248242
#define nft_rule_expr_next(expr) ((void *)expr) + expr->ops->size
249243
#define nft_rule_expr_last(rule) (struct nft_expr *)&rule->data[rule->dlen]
250-
#define nft_rule_next(rule) (void *)rule + sizeof(*rule) + rule->dlen
251244

252245
#define nft_rule_dp_for_each_expr(expr, last, rule) \
253246
for ((expr) = nft_rule_expr_first(rule), (last) = nft_rule_expr_last(rule); \
@@ -302,14 +295,14 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
302295
nft_trace_copy_nftrace(pkt, &info);
303296
continue;
304297
case NFT_CONTINUE:
305-
nft_trace_packet(pkt, &info, chain, rule,
298+
nft_trace_packet(pkt, &info, rule,
306299
NFT_TRACETYPE_RULE);
307300
continue;
308301
}
309302
break;
310303
}
311304

312-
nft_trace_verdict(&info, chain, rule, &regs);
305+
nft_trace_verdict(&info, rule, &regs);
313306

314307
switch (regs.verdict.code & NF_VERDICT_MASK) {
315308
case NF_ACCEPT:
@@ -323,7 +316,6 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
323316
case NFT_JUMP:
324317
if (WARN_ON_ONCE(stackptr >= NFT_JUMP_STACK_SIZE))
325318
return NF_DROP;
326-
jumpstack[stackptr].chain = chain;
327319
jumpstack[stackptr].rule = nft_rule_next(rule);
328320
stackptr++;
329321
fallthrough;
@@ -339,12 +331,11 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
339331

340332
if (stackptr > 0) {
341333
stackptr--;
342-
chain = jumpstack[stackptr].chain;
343334
rule = jumpstack[stackptr].rule;
344335
goto next_rule;
345336
}
346337

347-
nft_trace_packet(pkt, &info, basechain, NULL, NFT_TRACETYPE_POLICY);
338+
nft_trace_packet(pkt, &info, NULL, NFT_TRACETYPE_POLICY);
348339

349340
if (static_branch_unlikely(&nft_counters_enabled))
350341
nft_update_chain_stats(basechain, pkt);

net/netfilter/nf_tables_trace.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,29 @@ static bool nft_trace_have_verdict_chain(struct nft_traceinfo *info)
164164
return true;
165165
}
166166

167+
static const struct nft_chain *nft_trace_get_chain(const struct nft_traceinfo *info)
168+
{
169+
const struct nft_rule_dp *rule = info->rule;
170+
const struct nft_rule_dp_last *last;
171+
172+
if (!rule)
173+
return &info->basechain->chain;
174+
175+
while (!rule->is_last)
176+
rule = nft_rule_next(rule);
177+
178+
last = (const struct nft_rule_dp_last *)rule;
179+
180+
if (WARN_ON_ONCE(!last->chain))
181+
return &info->basechain->chain;
182+
183+
return last->chain;
184+
}
185+
167186
void nft_trace_notify(struct nft_traceinfo *info)
168187
{
169188
const struct nft_pktinfo *pkt = info->pkt;
189+
const struct nft_chain *chain;
170190
struct nlmsghdr *nlh;
171191
struct sk_buff *skb;
172192
unsigned int size;
@@ -176,9 +196,11 @@ void nft_trace_notify(struct nft_traceinfo *info)
176196
if (!nfnetlink_has_listeners(nft_net(pkt), NFNLGRP_NFTRACE))
177197
return;
178198

199+
chain = nft_trace_get_chain(info);
200+
179201
size = nlmsg_total_size(sizeof(struct nfgenmsg)) +
180-
nla_total_size(strlen(info->chain->table->name)) +
181-
nla_total_size(strlen(info->chain->name)) +
202+
nla_total_size(strlen(chain->table->name)) +
203+
nla_total_size(strlen(chain->name)) +
182204
nla_total_size_64bit(sizeof(__be64)) + /* rule handle */
183205
nla_total_size(sizeof(__be32)) + /* trace type */
184206
nla_total_size(0) + /* VERDICT, nested */
@@ -217,10 +239,10 @@ void nft_trace_notify(struct nft_traceinfo *info)
217239
if (nla_put_u32(skb, NFTA_TRACE_ID, info->skbid))
218240
goto nla_put_failure;
219241

220-
if (nla_put_string(skb, NFTA_TRACE_CHAIN, info->chain->name))
242+
if (nla_put_string(skb, NFTA_TRACE_CHAIN, chain->name))
221243
goto nla_put_failure;
222244

223-
if (nla_put_string(skb, NFTA_TRACE_TABLE, info->chain->table->name))
245+
if (nla_put_string(skb, NFTA_TRACE_TABLE, chain->table->name))
224246
goto nla_put_failure;
225247

226248
if (nf_trace_fill_rule_info(skb, info))

0 commit comments

Comments
 (0)