From 299823d46b6d0c49040d81ee3eb0f37b3b0520ea Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 6 Feb 2023 14:18:10 +0100 Subject: optimize: select merge criteria based on candidates rules 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 --- src/optimize.c | 22 +++++++++++----------- .../testcases/optimizations/dumps/merge_nat.nft | 4 ++++ tests/shell/testcases/optimizations/merge_nat | 4 ++++ 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/optimize.c b/src/optimize.c index 5f6e3a64..ff4f2627 100644 --- a/src/optimize.c +++ b/src/optimize.c @@ -985,21 +985,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; } @@ -1012,7 +1012,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: diff --git a/tests/shell/testcases/optimizations/dumps/merge_nat.nft b/tests/shell/testcases/optimizations/dumps/merge_nat.nft index 7a6ecb76..32423b22 100644 --- a/tests/shell/testcases/optimizations/dumps/merge_nat.nft +++ b/tests/shell/testcases/optimizations/dumps/merge_nat.nft @@ -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 } } } diff --git a/tests/shell/testcases/optimizations/merge_nat b/tests/shell/testcases/optimizations/merge_nat index 290cfcfe..ec9b239c 100755 --- a/tests/shell/testcases/optimizations/merge_nat +++ b/tests/shell/testcases/optimizations/merge_nat @@ -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 } -- cgit v1.2.3