]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
optimize: check for mergeable rules
authorPablo Neira Ayuso <pablo@netfilter.org>
Tue, 9 Aug 2022 20:45:21 +0000 (22:45 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 11 Aug 2022 14:23:15 +0000 (16:23 +0200)
Rules that are equal need to have at least one mergeable statement.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/optimize.c
tests/shell/testcases/optimizations/dumps/not_mergeable.nft [new file with mode: 0644]
tests/shell/testcases/optimizations/not_mergeable [new file with mode: 0755]

index 419a37f2bb20516f15bd7e5f8e62390abdc9c906..ea067f80bce0b8a56e2a0a817bc66dbc01e0d102 100644 (file)
@@ -1011,15 +1011,41 @@ static bool stmt_type_eq(const struct stmt *stmt_a, const struct stmt *stmt_b)
        return __stmt_type_eq(stmt_a, stmt_b, true);
 }
 
+static bool stmt_is_mergeable(const struct stmt *stmt)
+{
+       if (!stmt)
+               return false;
+
+       switch (stmt->ops->type) {
+       case STMT_VERDICT:
+               if (stmt->expr->etype == EXPR_MAP)
+                       return true;
+               break;
+       case STMT_EXPRESSION:
+       case STMT_NAT:
+               return true;
+       default:
+               break;
+       }
+
+       return false;
+}
+
 static bool rules_eq(const struct optimize_ctx *ctx, int i, int j)
 {
-       uint32_t k;
+       uint32_t k, mergeable = 0;
 
        for (k = 0; k < ctx->num_stmts; k++) {
+               if (stmt_is_mergeable(ctx->stmt_matrix[i][k]))
+                       mergeable++;
+
                if (!stmt_type_eq(ctx->stmt_matrix[i][k], ctx->stmt_matrix[j][k]))
                        return false;
        }
 
+       if (mergeable == 0)
+               return false;
+
        return true;
 }
 
diff --git a/tests/shell/testcases/optimizations/dumps/not_mergeable.nft b/tests/shell/testcases/optimizations/dumps/not_mergeable.nft
new file mode 100644 (file)
index 0000000..08b2b58
--- /dev/null
@@ -0,0 +1,12 @@
+table ip x {
+       chain t1 {
+       }
+
+       chain t2 {
+       }
+
+       chain y {
+               counter packets 0 bytes 0 jump t1
+               counter packets 0 bytes 0 jump t2
+       }
+}
diff --git a/tests/shell/testcases/optimizations/not_mergeable b/tests/shell/testcases/optimizations/not_mergeable
new file mode 100755 (executable)
index 0000000..25635cd
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+set -e
+
+RULESET="table ip x {
+       chain t1 {
+       }
+       chain t2 {
+       }
+       chain y {
+               counter jump t1
+               counter jump t2
+       }
+}"
+
+$NFT -o -f - <<< $RULESET