diff options
-rw-r--r-- | src/optimize.c | 44 | ||||
-rw-r--r-- | tests/shell/testcases/optimizations/dumps/merge_stmts_concat.nft | 5 | ||||
-rwxr-xr-x | tests/shell/testcases/optimizations/merge_stmts_concat | 13 |
3 files changed, 61 insertions, 1 deletions
diff --git a/src/optimize.c b/src/optimize.c index bae36d76..5950e852 100644 --- a/src/optimize.c +++ b/src/optimize.c @@ -271,6 +271,48 @@ static void merge_stmts(const struct optimize_ctx *ctx, stmt_a->expr->right = set; } +static void merge_concat_stmts(const struct optimize_ctx *ctx, + uint32_t from, uint32_t to, + const struct merge *merge) +{ + struct expr *concat, *elem, *set; + struct stmt *stmt, *stmt_a; + uint32_t i, k; + + stmt = ctx->stmt_matrix[from][merge->stmt[0]]; + /* build concatenation of selectors, eg. ifname . ip daddr . tcp dport */ + concat = concat_expr_alloc(&internal_location); + + for (k = 0; k < merge->num_stmts; k++) { + stmt_a = ctx->stmt_matrix[from][merge->stmt[k]]; + compound_expr_add(concat, expr_get(stmt_a->expr->left)); + } + expr_free(stmt->expr->left); + stmt->expr->left = concat; + + /* build set data contenation, eg. { eth0 . 1.1.1.1 . 22 } */ + set = set_expr_alloc(&internal_location, NULL); + set->set_flags |= NFT_SET_ANONYMOUS; + + for (i = from; i <= to; i++) { + concat = concat_expr_alloc(&internal_location); + for (k = 0; k < merge->num_stmts; k++) { + stmt_a = ctx->stmt_matrix[i][merge->stmt[k]]; + compound_expr_add(concat, expr_get(stmt_a->expr->right)); + } + elem = set_elem_expr_alloc(&internal_location, concat); + compound_expr_add(set, elem); + } + expr_free(stmt->expr->right); + stmt->expr->right = set; + + for (k = 1; k < merge->num_stmts; k++) { + stmt_a = ctx->stmt_matrix[from][merge->stmt[k]]; + list_del(&stmt_a->list); + stmt_free(stmt_a); + } +} + static void rule_optimize_print(struct output_ctx *octx, const struct rule *rule) { @@ -312,7 +354,7 @@ static void merge_rules(const struct optimize_ctx *ctx, uint32_t i; if (merge->num_stmts > 1) { - return; + merge_concat_stmts(ctx, from, to, merge); } else { merge_stmts(ctx, from, to, merge); } diff --git a/tests/shell/testcases/optimizations/dumps/merge_stmts_concat.nft b/tests/shell/testcases/optimizations/dumps/merge_stmts_concat.nft new file mode 100644 index 00000000..6dbfff2e --- /dev/null +++ b/tests/shell/testcases/optimizations/dumps/merge_stmts_concat.nft @@ -0,0 +1,5 @@ +table ip x { + chain y { + iifname . ip saddr . ip daddr { "eth1" . 1.1.1.1 . 2.2.2.3, "eth1" . 1.1.1.2 . 2.2.2.4, "eth2" . 1.1.1.3 . 2.2.2.5 } accept + } +} diff --git a/tests/shell/testcases/optimizations/merge_stmts_concat b/tests/shell/testcases/optimizations/merge_stmts_concat new file mode 100755 index 00000000..941e9a5a --- /dev/null +++ b/tests/shell/testcases/optimizations/merge_stmts_concat @@ -0,0 +1,13 @@ +#!/bin/bash + +set -e + +RULESET="table ip x { + chain y { + meta iifname eth1 ip saddr 1.1.1.1 ip daddr 2.2.2.3 accept + meta iifname eth1 ip saddr 1.1.1.2 ip daddr 2.2.2.4 accept + meta iifname eth2 ip saddr 1.1.1.3 ip daddr 2.2.2.5 accept + } +}" + +$NFT -o -f - <<< $RULESET |