|
@@ -66,20 +66,6 @@ struct nft_jumpstack {
|
|
int rulenum;
|
|
int rulenum;
|
|
};
|
|
};
|
|
|
|
|
|
-static inline void
|
|
|
|
-nft_chain_stats(const struct nft_chain *this, const struct nft_pktinfo *pkt,
|
|
|
|
- struct nft_jumpstack *jumpstack, unsigned int stackptr)
|
|
|
|
-{
|
|
|
|
- struct nft_stats __percpu *stats;
|
|
|
|
- const struct nft_chain *chain = stackptr ? jumpstack[0].chain : this;
|
|
|
|
-
|
|
|
|
- rcu_read_lock_bh();
|
|
|
|
- stats = rcu_dereference(nft_base_chain(chain)->stats);
|
|
|
|
- __this_cpu_inc(stats->pkts);
|
|
|
|
- __this_cpu_add(stats->bytes, pkt->skb->len);
|
|
|
|
- rcu_read_unlock_bh();
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
enum nft_trace {
|
|
enum nft_trace {
|
|
NFT_TRACE_RULE,
|
|
NFT_TRACE_RULE,
|
|
NFT_TRACE_RETURN,
|
|
NFT_TRACE_RETURN,
|
|
@@ -117,13 +103,14 @@ static void nft_trace_packet(const struct nft_pktinfo *pkt,
|
|
unsigned int
|
|
unsigned int
|
|
nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
|
|
nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
|
|
{
|
|
{
|
|
- const struct nft_chain *chain = ops->priv;
|
|
|
|
|
|
+ const struct nft_chain *chain = ops->priv, *basechain = chain;
|
|
const struct nft_rule *rule;
|
|
const struct nft_rule *rule;
|
|
const struct nft_expr *expr, *last;
|
|
const struct nft_expr *expr, *last;
|
|
struct nft_data data[NFT_REG_MAX + 1];
|
|
struct nft_data data[NFT_REG_MAX + 1];
|
|
unsigned int stackptr = 0;
|
|
unsigned int stackptr = 0;
|
|
struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE];
|
|
struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE];
|
|
- int rulenum = 0;
|
|
|
|
|
|
+ struct nft_stats __percpu *stats;
|
|
|
|
+ int rulenum;
|
|
/*
|
|
/*
|
|
* Cache cursor to avoid problems in case that the cursor is updated
|
|
* Cache cursor to avoid problems in case that the cursor is updated
|
|
* while traversing the ruleset.
|
|
* while traversing the ruleset.
|
|
@@ -131,6 +118,7 @@ nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
|
|
unsigned int gencursor = ACCESS_ONCE(chain->net->nft.gencursor);
|
|
unsigned int gencursor = ACCESS_ONCE(chain->net->nft.gencursor);
|
|
|
|
|
|
do_chain:
|
|
do_chain:
|
|
|
|
+ rulenum = 0;
|
|
rule = list_entry(&chain->rules, struct nft_rule, list);
|
|
rule = list_entry(&chain->rules, struct nft_rule, list);
|
|
next_rule:
|
|
next_rule:
|
|
data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
|
|
data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
|
|
@@ -156,8 +144,10 @@ next_rule:
|
|
switch (data[NFT_REG_VERDICT].verdict) {
|
|
switch (data[NFT_REG_VERDICT].verdict) {
|
|
case NFT_BREAK:
|
|
case NFT_BREAK:
|
|
data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
|
|
data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
|
|
- /* fall through */
|
|
|
|
|
|
+ continue;
|
|
case NFT_CONTINUE:
|
|
case NFT_CONTINUE:
|
|
|
|
+ if (unlikely(pkt->skb->nf_trace))
|
|
|
|
+ nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
@@ -183,37 +173,44 @@ next_rule:
|
|
jumpstack[stackptr].rule = rule;
|
|
jumpstack[stackptr].rule = rule;
|
|
jumpstack[stackptr].rulenum = rulenum;
|
|
jumpstack[stackptr].rulenum = rulenum;
|
|
stackptr++;
|
|
stackptr++;
|
|
- /* fall through */
|
|
|
|
|
|
+ chain = data[NFT_REG_VERDICT].chain;
|
|
|
|
+ goto do_chain;
|
|
case NFT_GOTO:
|
|
case NFT_GOTO:
|
|
|
|
+ if (unlikely(pkt->skb->nf_trace))
|
|
|
|
+ nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
|
|
|
|
+
|
|
chain = data[NFT_REG_VERDICT].chain;
|
|
chain = data[NFT_REG_VERDICT].chain;
|
|
goto do_chain;
|
|
goto do_chain;
|
|
case NFT_RETURN:
|
|
case NFT_RETURN:
|
|
if (unlikely(pkt->skb->nf_trace))
|
|
if (unlikely(pkt->skb->nf_trace))
|
|
nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RETURN);
|
|
nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RETURN);
|
|
-
|
|
|
|
- /* fall through */
|
|
|
|
|
|
+ break;
|
|
case NFT_CONTINUE:
|
|
case NFT_CONTINUE:
|
|
|
|
+ if (unlikely(pkt->skb->nf_trace && !(chain->flags & NFT_BASE_CHAIN)))
|
|
|
|
+ nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_RETURN);
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
WARN_ON(1);
|
|
WARN_ON(1);
|
|
}
|
|
}
|
|
|
|
|
|
if (stackptr > 0) {
|
|
if (stackptr > 0) {
|
|
- if (unlikely(pkt->skb->nf_trace))
|
|
|
|
- nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_RETURN);
|
|
|
|
-
|
|
|
|
stackptr--;
|
|
stackptr--;
|
|
chain = jumpstack[stackptr].chain;
|
|
chain = jumpstack[stackptr].chain;
|
|
rule = jumpstack[stackptr].rule;
|
|
rule = jumpstack[stackptr].rule;
|
|
rulenum = jumpstack[stackptr].rulenum;
|
|
rulenum = jumpstack[stackptr].rulenum;
|
|
goto next_rule;
|
|
goto next_rule;
|
|
}
|
|
}
|
|
- nft_chain_stats(chain, pkt, jumpstack, stackptr);
|
|
|
|
|
|
|
|
if (unlikely(pkt->skb->nf_trace))
|
|
if (unlikely(pkt->skb->nf_trace))
|
|
- nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_POLICY);
|
|
|
|
|
|
+ nft_trace_packet(pkt, basechain, -1, NFT_TRACE_POLICY);
|
|
|
|
+
|
|
|
|
+ rcu_read_lock_bh();
|
|
|
|
+ stats = rcu_dereference(nft_base_chain(basechain)->stats);
|
|
|
|
+ __this_cpu_inc(stats->pkts);
|
|
|
|
+ __this_cpu_add(stats->bytes, pkt->skb->len);
|
|
|
|
+ rcu_read_unlock_bh();
|
|
|
|
|
|
- return nft_base_chain(chain)->policy;
|
|
|
|
|
|
+ return nft_base_chain(basechain)->policy;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(nft_do_chain);
|
|
EXPORT_SYMBOL_GPL(nft_do_chain);
|
|
|
|
|