]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
netfilter: nf_tables: handle meta/lookup with direct call
authorFlorian Westphal <fw@strlen.de>
Wed, 4 Jul 2018 10:48:04 +0000 (12:48 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 30 Jul 2018 09:52:02 +0000 (11:52 +0200)
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>
include/net/netfilter/nf_tables_core.h
net/netfilter/nf_tables_core.c
net/netfilter/nft_lookup.c
net/netfilter/nft_meta.c

index a05134507e7bc806d9afd9ff7c86b95e5df084eb..8da837d2aaf997d5d642b081154c1bf9d2b3b26b 100644 (file)
@@ -71,4 +71,11 @@ extern struct nft_set_type nft_set_hash_fast_type;
 extern struct nft_set_type nft_set_rbtree_type;
 extern struct nft_set_type nft_set_bitmap_type;
 
+struct nft_expr;
+struct nft_regs;
+struct nft_pktinfo;
+void nft_meta_get_eval(const struct nft_expr *expr,
+                      struct nft_regs *regs, const struct nft_pktinfo *pkt);
+void nft_lookup_eval(const struct nft_expr *expr,
+                    struct nft_regs *regs, const struct nft_pktinfo *pkt);
 #endif /* _NET_NF_TABLES_CORE_H */
index 8de912ca53d3bfb1b2a924cbeb655d8e4d4ebd3a..ffd5c0f9412b4dab673b3294292a2fa6a7da404b 100644 (file)
@@ -120,6 +120,20 @@ struct nft_jumpstack {
        struct nft_rule *const *rules;
 };
 
+static void expr_call_ops_eval(const struct nft_expr *expr,
+                              struct nft_regs *regs,
+                              struct nft_pktinfo *pkt)
+{
+       unsigned long e = (unsigned long)expr->ops->eval;
+
+       if (e == (unsigned long)nft_meta_get_eval)
+               nft_meta_get_eval(expr, regs, pkt);
+       else if (e == (unsigned long)nft_lookup_eval)
+               nft_lookup_eval(expr, regs, pkt);
+       else
+               expr->ops->eval(expr, regs, pkt);
+}
+
 unsigned int
 nft_do_chain(struct nft_pktinfo *pkt, void *priv)
 {
@@ -153,7 +167,7 @@ next_rule:
                                nft_cmp_fast_eval(expr, &regs);
                        else if (expr->ops != &nft_payload_fast_ops ||
                                 !nft_payload_fast_eval(expr, &regs, pkt))
-                               expr->ops->eval(expr, &regs, pkt);
+                               expr_call_ops_eval(expr, &regs, pkt);
 
                        if (regs.verdict.code != NFT_CONTINUE)
                                break;
index c2a1d84cdfc460d86b50ae6d28dde2653f1666dd..ad13e8643599722a2eb0376957e126f5b192385d 100644 (file)
@@ -26,9 +26,9 @@ struct nft_lookup {
        struct nft_set_binding          binding;
 };
 
-static void nft_lookup_eval(const struct nft_expr *expr,
-                           struct nft_regs *regs,
-                           const struct nft_pktinfo *pkt)
+void nft_lookup_eval(const struct nft_expr *expr,
+                    struct nft_regs *regs,
+                    const struct nft_pktinfo *pkt)
 {
        const struct nft_lookup *priv = nft_expr_priv(expr);
        const struct nft_set *set = priv->set;
index 2b94dcc4345656a852e171afd7bb853f252ccaf7..297fe7d97c182ffbcbfb15c94f10bdec633f1149 100644 (file)
@@ -41,9 +41,9 @@ static DEFINE_PER_CPU(struct rnd_state, nft_prandom_state);
 #include "../bridge/br_private.h"
 #endif
 
-static void nft_meta_get_eval(const struct nft_expr *expr,
-                             struct nft_regs *regs,
-                             const struct nft_pktinfo *pkt)
+void nft_meta_get_eval(const struct nft_expr *expr,
+                      struct nft_regs *regs,
+                      const struct nft_pktinfo *pkt)
 {
        const struct nft_meta *priv = nft_expr_priv(expr);
        const struct sk_buff *skb = pkt->skb;