Skip to content

Commit

Permalink
netfilter: nf_tables: handle meta/lookup with direct call
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Florian Westphal authored and Pablo Neira Ayuso committed Jul 30, 2018
1 parent ecbcd68 commit 222440b
Showing 4 changed files with 28 additions and 7 deletions.
7 changes: 7 additions & 0 deletions include/net/netfilter/nf_tables_core.h
Original file line number Diff line number Diff line change
@@ -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 */
16 changes: 15 additions & 1 deletion net/netfilter/nf_tables_core.c
Original file line number Diff line number Diff line change
@@ -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 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
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;
6 changes: 3 additions & 3 deletions net/netfilter/nft_lookup.c
Original file line number Diff line number Diff line change
@@ -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;
6 changes: 3 additions & 3 deletions net/netfilter/nft_meta.c
Original file line number Diff line number Diff line change
@@ -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;

0 comments on commit 222440b

Please sign in to comment.