Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nf_tables: handle meta/lookup with direct call

Currently nft uses inlined variants for common operations
such as 'ip saddr 1.2.3.4' instead of an indirect call.

Also handle meta get operations and lookups without indirect call,
both are builtin.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Florian Westphal and committed by
Pablo Neira Ayuso
222440b4 ecbcd689

+28 -7
+7
include/net/netfilter/nf_tables_core.h
··· 71 71 extern struct nft_set_type nft_set_rbtree_type; 72 72 extern struct nft_set_type nft_set_bitmap_type; 73 73 74 + struct nft_expr; 75 + struct nft_regs; 76 + struct nft_pktinfo; 77 + void nft_meta_get_eval(const struct nft_expr *expr, 78 + struct nft_regs *regs, const struct nft_pktinfo *pkt); 79 + void nft_lookup_eval(const struct nft_expr *expr, 80 + struct nft_regs *regs, const struct nft_pktinfo *pkt); 74 81 #endif /* _NET_NF_TABLES_CORE_H */
+15 -1
net/netfilter/nf_tables_core.c
··· 120 120 struct nft_rule *const *rules; 121 121 }; 122 122 123 + static void expr_call_ops_eval(const struct nft_expr *expr, 124 + struct nft_regs *regs, 125 + struct nft_pktinfo *pkt) 126 + { 127 + unsigned long e = (unsigned long)expr->ops->eval; 128 + 129 + if (e == (unsigned long)nft_meta_get_eval) 130 + nft_meta_get_eval(expr, regs, pkt); 131 + else if (e == (unsigned long)nft_lookup_eval) 132 + nft_lookup_eval(expr, regs, pkt); 133 + else 134 + expr->ops->eval(expr, regs, pkt); 135 + } 136 + 123 137 unsigned int 124 138 nft_do_chain(struct nft_pktinfo *pkt, void *priv) 125 139 { ··· 167 153 nft_cmp_fast_eval(expr, &regs); 168 154 else if (expr->ops != &nft_payload_fast_ops || 169 155 !nft_payload_fast_eval(expr, &regs, pkt)) 170 - expr->ops->eval(expr, &regs, pkt); 156 + expr_call_ops_eval(expr, &regs, pkt); 171 157 172 158 if (regs.verdict.code != NFT_CONTINUE) 173 159 break;
+3 -3
net/netfilter/nft_lookup.c
··· 26 26 struct nft_set_binding binding; 27 27 }; 28 28 29 - static void nft_lookup_eval(const struct nft_expr *expr, 30 - struct nft_regs *regs, 31 - const struct nft_pktinfo *pkt) 29 + void nft_lookup_eval(const struct nft_expr *expr, 30 + struct nft_regs *regs, 31 + const struct nft_pktinfo *pkt) 32 32 { 33 33 const struct nft_lookup *priv = nft_expr_priv(expr); 34 34 const struct nft_set *set = priv->set;
+3 -3
net/netfilter/nft_meta.c
··· 41 41 #include "../bridge/br_private.h" 42 42 #endif 43 43 44 - static void nft_meta_get_eval(const struct nft_expr *expr, 45 - struct nft_regs *regs, 46 - const struct nft_pktinfo *pkt) 44 + void nft_meta_get_eval(const struct nft_expr *expr, 45 + struct nft_regs *regs, 46 + const struct nft_pktinfo *pkt) 47 47 { 48 48 const struct nft_meta *priv = nft_expr_priv(expr); 49 49 const struct sk_buff *skb = pkt->skb;