Tested-by: Nick Gregory <Nick.Gregory@xxxxxxxxxx> > On Feb 17, 2022, at 5:58 PM, Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> wrote: > > immediate verdict expression needs to allocate one slot in the flow offload > action array, however, immediate data expression does not need to do so. > > fwd and dup expression need to allocate one slot, this is missing. > > Add a new offload_action interface to report if this expression needs to > allocate one slot in the flow offload action array. > > Fixes: be2861dc36d7 ("netfilter: nft_{fwd,dup}_netdev: add offload support") > Reported-by: Nick Gregory <Nick.Gregory@xxxxxxxxxx> > Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> > --- > include/net/netfilter/nf_tables.h | 2 +- > include/net/netfilter/nf_tables_offload.h | 2 -- > net/netfilter/nf_tables_offload.c | 3 ++- > net/netfilter/nft_dup_netdev.c | 6 ++++++ > net/netfilter/nft_fwd_netdev.c | 6 ++++++ > net/netfilter/nft_immediate.c | 12 +++++++++++- > 6 files changed, 26 insertions(+), 5 deletions(-) > > diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h > index eaf55da9a205..c4c0861deac1 100644 > --- a/include/net/netfilter/nf_tables.h > +++ b/include/net/netfilter/nf_tables.h > @@ -905,9 +905,9 @@ struct nft_expr_ops { > int (*offload)(struct nft_offload_ctx *ctx, > struct nft_flow_rule *flow, > const struct nft_expr *expr); > + bool (*offload_action)(const struct nft_expr *expr); > void (*offload_stats)(struct nft_expr *expr, > const struct flow_stats *stats); > - u32 offload_flags; > const struct nft_expr_type *type; > void *data; > }; > diff --git a/include/net/netfilter/nf_tables_offload.h b/include/net/netfilter/nf_tables_offload.h > index f9d95ff82df8..797147843958 100644 > --- a/include/net/netfilter/nf_tables_offload.h > +++ b/include/net/netfilter/nf_tables_offload.h > @@ -67,8 +67,6 @@ struct nft_flow_rule { > struct flow_rule *rule; > }; > > -#define NFT_OFFLOAD_F_ACTION (1 << 0) > - > void nft_flow_rule_set_addr_type(struct nft_flow_rule *flow, > enum flow_dissector_key_id addr_type); > > diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c > index 9656c1646222..2d36952b1392 100644 > --- a/net/netfilter/nf_tables_offload.c > +++ b/net/netfilter/nf_tables_offload.c > @@ -94,7 +94,8 @@ struct nft_flow_rule *nft_flow_rule_create(struct net *net, > > expr = nft_expr_first(rule); > while (nft_expr_more(rule, expr)) { > - if (expr->ops->offload_flags & NFT_OFFLOAD_F_ACTION) > + if (expr->ops->offload_action && > + expr->ops->offload_action(expr)) > num_actions++; > > expr = nft_expr_next(expr); > diff --git a/net/netfilter/nft_dup_netdev.c b/net/netfilter/nft_dup_netdev.c > index bbf3fcba3df4..5b5c607fbf83 100644 > --- a/net/netfilter/nft_dup_netdev.c > +++ b/net/netfilter/nft_dup_netdev.c > @@ -67,6 +67,11 @@ static int nft_dup_netdev_offload(struct nft_offload_ctx *ctx, > return nft_fwd_dup_netdev_offload(ctx, flow, FLOW_ACTION_MIRRED, oif); > } > > +static bool nft_dup_netdev_offload_action(const struct nft_expr *expr) > +{ > + return true; > +} > + > static struct nft_expr_type nft_dup_netdev_type; > static const struct nft_expr_ops nft_dup_netdev_ops = { > .type = &nft_dup_netdev_type, > @@ -75,6 +80,7 @@ static const struct nft_expr_ops nft_dup_netdev_ops = { > .init = nft_dup_netdev_init, > .dump = nft_dup_netdev_dump, > .offload = nft_dup_netdev_offload, > + .offload_action = nft_dup_netdev_offload_action, > }; > > static struct nft_expr_type nft_dup_netdev_type __read_mostly = { > diff --git a/net/netfilter/nft_fwd_netdev.c b/net/netfilter/nft_fwd_netdev.c > index fa9301ca6033..619e394a91de 100644 > --- a/net/netfilter/nft_fwd_netdev.c > +++ b/net/netfilter/nft_fwd_netdev.c > @@ -79,6 +79,11 @@ static int nft_fwd_netdev_offload(struct nft_offload_ctx *ctx, > return nft_fwd_dup_netdev_offload(ctx, flow, FLOW_ACTION_REDIRECT, oif); > } > > +static bool nft_fwd_netdev_offload_action(const struct nft_expr *expr) > +{ > + return true; > +} > + > struct nft_fwd_neigh { > u8 sreg_dev; > u8 sreg_addr; > @@ -222,6 +227,7 @@ static const struct nft_expr_ops nft_fwd_netdev_ops = { > .dump = nft_fwd_netdev_dump, > .validate = nft_fwd_validate, > .offload = nft_fwd_netdev_offload, > + .offload_action = nft_fwd_netdev_offload_action, > }; > > static const struct nft_expr_ops * > diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c > index 90c64d27ae53..d0f67d325bdf 100644 > --- a/net/netfilter/nft_immediate.c > +++ b/net/netfilter/nft_immediate.c > @@ -213,6 +213,16 @@ static int nft_immediate_offload(struct nft_offload_ctx *ctx, > return 0; > } > > +static bool nft_immediate_offload_action(const struct nft_expr *expr) > +{ > + const struct nft_immediate_expr *priv = nft_expr_priv(expr); > + > + if (priv->dreg == NFT_REG_VERDICT) > + return true; > + > + return false; > +} > + > static const struct nft_expr_ops nft_imm_ops = { > .type = &nft_imm_type, > .size = NFT_EXPR_SIZE(sizeof(struct nft_immediate_expr)), > @@ -224,7 +234,7 @@ static const struct nft_expr_ops nft_imm_ops = { > .dump = nft_immediate_dump, > .validate = nft_immediate_validate, > .offload = nft_immediate_offload, > - .offload_flags = NFT_OFFLOAD_F_ACTION, > + .offload_action = nft_immediate_offload_action, > }; > > struct nft_expr_type nft_imm_type __read_mostly = { > -- > 2.30.2 >