summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/optimize.c28
-rw-r--r--tests/shell/testcases/optimizations/dumps/not_mergeable.nft12
-rwxr-xr-xtests/shell/testcases/optimizations/not_mergeable16
3 files changed, 55 insertions, 1 deletions
diff --git a/src/optimize.c b/src/optimize.c
index 419a37f2..ea067f80 100644
--- a/src/optimize.c
+++ b/src/optimize.c
@@ -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
index 00000000..08b2b58f
--- /dev/null
+++ b/tests/shell/testcases/optimizations/dumps/not_mergeable.nft
@@ -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
index 00000000..25635cdd
--- /dev/null
+++ b/tests/shell/testcases/optimizations/not_mergeable
@@ -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