]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
optimize: select merge criteria based on candidates rules
authorPablo Neira Ayuso <pablo@netfilter.org>
Mon, 6 Feb 2023 13:18:10 +0000 (14:18 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 2 Nov 2023 10:56:19 +0000 (11:56 +0100)
commit 299823d46b6d0c49040d81ee3eb0f37b3b0520ea upstream.

Select the merge criteria based on the statements that are used
in the candidate rules, instead of using the list of statements
in the given chain.

Update tests to include a rule with a verdict, which triggers
the bug described in the bugzilla ticket.

Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1657
Fixes: 0a6dbfce6dc3 ("optimize: merge nat rules with same selectors into map")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/optimize.c
tests/shell/testcases/optimizations/dumps/merge_nat.nft
tests/shell/testcases/optimizations/merge_nat

index 794af452c9118a9b6bc1b7b648033cf9df1ba8bf..48f669c8462cb41c5c7bd2a59789af2675471c22 100644 (file)
@@ -983,21 +983,21 @@ static void rule_optimize_print(struct output_ctx *octx,
        fprintf(octx->error_fp, "%s\n", line);
 }
 
-static enum stmt_types merge_stmt_type(const struct optimize_ctx *ctx)
+static enum stmt_types merge_stmt_type(const struct optimize_ctx *ctx,
+                                      uint32_t from, uint32_t to)
 {
-       uint32_t i;
+       uint32_t i, j;
 
-       for (i = 0; i < ctx->num_stmts; i++) {
-               switch (ctx->stmt[i]->ops->type) {
-               case STMT_VERDICT:
-               case STMT_NAT:
-                       return ctx->stmt[i]->ops->type;
-               default:
-                       continue;
+       for (i = from; i <= to; i++) {
+               for (j = 0; j < ctx->num_stmts; j++) {
+                       if (!ctx->stmt_matrix[i][j])
+                               continue;
+                       if (ctx->stmt_matrix[i][j]->ops->type == STMT_NAT)
+                               return STMT_NAT;
                }
        }
 
-       /* actually no verdict, this assumes rules have the same verdict. */
+       /* merge by verdict, even if no verdict is specified. */
        return STMT_VERDICT;
 }
 
@@ -1010,7 +1010,7 @@ static void merge_rules(const struct optimize_ctx *ctx,
        bool same_verdict;
        uint32_t i;
 
-       stmt_type = merge_stmt_type(ctx);
+       stmt_type = merge_stmt_type(ctx, from, to);
 
        switch (stmt_type) {
        case STMT_VERDICT:
index 7a6ecb76a9346abad930c1bf542795e8df22029d..32423b220ed17ce1f8c1ebcb2f5bd57904b2b73b 100644 (file)
@@ -1,20 +1,24 @@
 table ip test1 {
        chain y {
+               oif "lo" accept
                dnat to ip saddr map { 4.4.4.4 : 1.1.1.1, 5.5.5.5 : 2.2.2.2 }
        }
 }
 table ip test2 {
        chain y {
+               oif "lo" accept
                dnat ip to tcp dport map { 80 : 1.1.1.1 . 8001, 81 : 2.2.2.2 . 9001 }
        }
 }
 table ip test3 {
        chain y {
+               oif "lo" accept
                snat to ip saddr . tcp sport map { 1.1.1.1 . 1024-65535 : 3.3.3.3, 2.2.2.2 . 1024-65535 : 4.4.4.4 }
        }
 }
 table ip test4 {
        chain y {
+               oif "lo" accept
                dnat ip to ip daddr . tcp dport map { 1.1.1.1 . 80 : 4.4.4.4 . 8000, 2.2.2.2 . 81 : 3.3.3.3 . 9000 }
        }
 }
index 290cfcfebe2e04122e156f3becdd962314592019..ec9b239c6f487a5f96cdb1620d2aa893323bf3e0 100755 (executable)
@@ -4,6 +4,7 @@ set -e
 
 RULESET="table ip test1 {
         chain y {
+                oif lo accept
                 ip saddr 4.4.4.4 dnat to 1.1.1.1
                 ip saddr 5.5.5.5 dnat to 2.2.2.2
         }
@@ -13,6 +14,7 @@ $NFT -o -f - <<< $RULESET
 
 RULESET="table ip test2 {
         chain y {
+                oif lo accept
                 tcp dport 80 dnat to 1.1.1.1:8001
                 tcp dport 81 dnat to 2.2.2.2:9001
         }
@@ -22,6 +24,7 @@ $NFT -o -f - <<< $RULESET
 
 RULESET="table ip test3 {
         chain y {
+                oif lo accept
                 ip saddr 1.1.1.1 tcp sport 1024-65535 snat to 3.3.3.3
                 ip saddr 2.2.2.2 tcp sport 1024-65535 snat to 4.4.4.4
         }
@@ -31,6 +34,7 @@ $NFT -o -f - <<< $RULESET
 
 RULESET="table ip test4 {
         chain y {
+                oif lo accept
                 ip daddr 1.1.1.1 tcp dport 80 dnat to 4.4.4.4:8000
                 ip daddr 2.2.2.2 tcp dport 81 dnat to 3.3.3.3:9000
         }