netfilter: nft_exthdr: add reduce support
authorFlorian Westphal <fw@strlen.de>
Mon, 14 Mar 2022 17:23:13 +0000 (18:23 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sat, 19 Mar 2022 23:29:47 +0000 (00:29 +0100)
Check if we can elide the load. Cancel if the new candidate
isn't identical to previous store.

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

index d2b9378..22c3e05 100644 (file)
@@ -603,12 +603,40 @@ static int nft_exthdr_dump_strip(struct sk_buff *skb, const struct nft_expr *exp
        return nft_exthdr_dump_common(skb, priv);
 }
 
+static bool nft_exthdr_reduce(struct nft_regs_track *track,
+                              const struct nft_expr *expr)
+{
+       const struct nft_exthdr *priv = nft_expr_priv(expr);
+       const struct nft_exthdr *exthdr;
+
+       if (!nft_reg_track_cmp(track, expr, priv->dreg)) {
+               nft_reg_track_update(track, expr, priv->dreg, priv->len);
+               return false;
+       }
+
+       exthdr = nft_expr_priv(track->regs[priv->dreg].selector);
+       if (priv->type != exthdr->type ||
+           priv->op != exthdr->op ||
+           priv->flags != exthdr->flags ||
+           priv->offset != exthdr->offset ||
+           priv->len != exthdr->len) {
+               nft_reg_track_update(track, expr, priv->dreg, priv->len);
+               return false;
+       }
+
+       if (!track->regs[priv->dreg].bitwise)
+               return true;
+
+       return nft_expr_reduce_bitwise(track, expr);
+}
+
 static const struct nft_expr_ops nft_exthdr_ipv6_ops = {
        .type           = &nft_exthdr_type,
        .size           = NFT_EXPR_SIZE(sizeof(struct nft_exthdr)),
        .eval           = nft_exthdr_ipv6_eval,
        .init           = nft_exthdr_init,
        .dump           = nft_exthdr_dump,
+       .reduce         = nft_exthdr_reduce,
 };
 
 static const struct nft_expr_ops nft_exthdr_ipv4_ops = {
@@ -617,6 +645,7 @@ static const struct nft_expr_ops nft_exthdr_ipv4_ops = {
        .eval           = nft_exthdr_ipv4_eval,
        .init           = nft_exthdr_ipv4_init,
        .dump           = nft_exthdr_dump,
+       .reduce         = nft_exthdr_reduce,
 };
 
 static const struct nft_expr_ops nft_exthdr_tcp_ops = {
@@ -625,6 +654,7 @@ static const struct nft_expr_ops nft_exthdr_tcp_ops = {
        .eval           = nft_exthdr_tcp_eval,
        .init           = nft_exthdr_init,
        .dump           = nft_exthdr_dump,
+       .reduce         = nft_exthdr_reduce,
 };
 
 static const struct nft_expr_ops nft_exthdr_tcp_set_ops = {
@@ -633,6 +663,7 @@ static const struct nft_expr_ops nft_exthdr_tcp_set_ops = {
        .eval           = nft_exthdr_tcp_set_eval,
        .init           = nft_exthdr_tcp_set_init,
        .dump           = nft_exthdr_dump_set,
+       .reduce         = NFT_REDUCE_READONLY,
 };
 
 static const struct nft_expr_ops nft_exthdr_tcp_strip_ops = {
@@ -641,6 +672,7 @@ static const struct nft_expr_ops nft_exthdr_tcp_strip_ops = {
        .eval           = nft_exthdr_tcp_strip_eval,
        .init           = nft_exthdr_tcp_strip_init,
        .dump           = nft_exthdr_dump_strip,
+       .reduce         = NFT_REDUCE_READONLY,
 };
 
 static const struct nft_expr_ops nft_exthdr_sctp_ops = {
@@ -649,6 +681,7 @@ static const struct nft_expr_ops nft_exthdr_sctp_ops = {
        .eval           = nft_exthdr_sctp_eval,
        .init           = nft_exthdr_init,
        .dump           = nft_exthdr_dump,
+       .reduce         = nft_exthdr_reduce,
 };
 
 static const struct nft_expr_ops *