netfilter: nft_meta: track register operations
authorPablo Neira Ayuso <pablo@netfilter.org>
Sun, 9 Jan 2022 16:11:23 +0000 (17:11 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sun, 9 Jan 2022 22:35:17 +0000 (23:35 +0100)
Check if the destination register already contains the data that this
meta store expression performs. This allows to skip this redundant
operation. If the destination contains a different selector, update
the register tracking information.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/nft_meta.c

index fe91ff5..430f40b 100644 (file)
@@ -750,12 +750,40 @@ static int nft_meta_get_offload(struct nft_offload_ctx *ctx,
        return 0;
 }
 
+static bool nft_meta_get_reduce(struct nft_regs_track *track,
+                               const struct nft_expr *expr)
+{
+       const struct nft_meta *priv = nft_expr_priv(expr);
+       const struct nft_meta *meta;
+
+       if (!track->regs[priv->dreg].selector ||
+           track->regs[priv->dreg].selector->ops != expr->ops) {
+               track->regs[priv->dreg].selector = expr;
+               track->regs[priv->dreg].bitwise = NULL;
+               return false;
+       }
+
+       meta = nft_expr_priv(track->regs[priv->dreg].selector);
+       if (priv->key != meta->key ||
+           priv->dreg != meta->dreg) {
+               track->regs[priv->dreg].selector = expr;
+               track->regs[priv->dreg].bitwise = NULL;
+               return false;
+       }
+
+       if (!track->regs[priv->dreg].bitwise)
+               return true;
+
+       return false;
+}
+
 static const struct nft_expr_ops nft_meta_get_ops = {
        .type           = &nft_meta_type,
        .size           = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
        .eval           = nft_meta_get_eval,
        .init           = nft_meta_get_init,
        .dump           = nft_meta_get_dump,
+       .reduce         = nft_meta_get_reduce,
        .validate       = nft_meta_get_validate,
        .offload        = nft_meta_get_offload,
 };