summaryrefslogtreecommitdiffstats
path: root/src/optimize.c
Commit message (Collapse)AuthorAgeFilesLines
* optimize: infer family for nat mappingPablo Neira Ayuso2023-02-211-2/+21
| | | | | | | | | | | | | | | Infer family from key in nat mapping, otherwise nat mapping via merge breaks since family is not specified. Merging: fw-test-bug2.nft:4:9-78: iifname enp2s0 ip daddr 72.2.3.66 tcp dport 53122 dnat to 10.1.1.10:22 fw-test-bug2.nft:5:9-77: iifname enp2s0 ip daddr 72.2.3.66 tcp dport 443 dnat to 10.1.1.52:443 fw-test-bug2.nft:6:9-75: iifname enp2s0 ip daddr 72.2.3.70 tcp dport 80 dnat to 10.1.1.52:80 into: dnat ip to iifname . ip daddr . tcp dport map { enp2s0 . 72.2.3.66 . 53122 : 10.1.1.10 . 22, enp2s0 . 72.2.3.66 . 443 : 10.1.1.52 . 443, enp2s0 . 72.2.3.70 . 80 : 10.1.1.52 . 80 } Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1657 Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: ignore existing nat mappingPablo Neira Ayuso2023-02-071-0/+7
| | | | | | | | | | | | | | | | User might be already using a nat mapping in their ruleset, use the unsupported statement when collecting statements in this case. # nft -c -o -f ruleset.nft nft: optimize.c:443: rule_build_stmt_matrix_stmts: Assertion `k >= 0' failed. Aborted The -o/--optimize feature only cares about linear rulesets at this stage, but do not hit assert() in this case. Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1656 Fixes: 0a6dbfce6dc3 ("optimize: merge nat rules with same selectors into map") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: select merge criteria based on candidates rulesPablo Neira Ayuso2023-02-061-11/+11
| | | | | | | | | | | | | 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>
* optimize: fix incorrect expansion into concatenation with verdict mapPablo Neira Ayuso2023-02-021-11/+22
| | | | | | | | | | | | | | | | | | # nft -c -o -f ruleset.nft Merging: ruleset.nft:3:3-53: meta pkttype broadcast udp dport { 67, 547 } accept ruleset.nft:4:17-58: meta pkttype multicast udp dport 1900 drop into: meta pkttype . udp dport vmap { broadcast . { 67, 547 } : accept, multicast . 1900 : drop } ruleset.nft:3:38-39: Error: invalid data type, expected concatenation of (packet type, internet network service) meta pkttype broadcast udp dport { 67, 547 } accept ^^ Similar to 187c6d01d357 ("optimize: expand implicit set element when merging into concatenation") but for verdict maps. Reported-by: Simon G. Trajkovski <neur0armitage@proton.me> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: wrap code to build concatenation in helper functionPablo Neira Ayuso2023-02-021-7/+15
| | | | | | | | | Move code to build concatenations into helper function, this routine includes support for expansion of implicit sets containing singleton values. This is preparation work to reuse existing code in a follow up patch. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: Do not return garbage from stackPhil Sutter2023-01-131-1/+1
| | | | | | | | | If input does not contain a single 'add' command (unusual, but possible), 'ret' value was not initialized by nft_optimize() before returning its value. Fixes: fb298877ece27 ("src: add ruleset optimization infrastructure") Signed-off-by: Phil Sutter <phil@nwl.cc>
* optimize: Clarify chain_optimize() array allocationsPhil Sutter2023-01-131-3/+4
| | | | | | | | | | | | Arguments passed to sizeof() where deemed suspicious by covscan due to the different type. Consistently specify size of an array 'a' using 'sizeof(*a) * nmemb'. For the statement arrays in stmt_matrix, even use xzalloc_array() since the item count is fixed and therefore can't be zero. Fixes: fb298877ece27 ("src: add ruleset optimization infrastructure") Signed-off-by: Phil Sutter <phil@nwl.cc>
* optimize: payload expression requires inner_desc comparisonPablo Neira Ayuso2023-01-041-0/+2
| | | | | | | | | | | Since 772892a018b4 ("src: add vxlan matching support"), payload expressions have an inner_desc field that provides the description for the outer tunnel header. When searching for common mergeable selectors, compare the inner description too. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: handle prefix and range when merging into set + concatenationPablo Neira Ayuso2022-11-051-0/+2
| | | | | | | | | | | | | | | | The following ruleset fails to be merged using set + concatenation: meta iifname eth1 ip saddr 1.1.1.2 ip daddr 2.2.3.0/24 accept meta iifname eth1 ip saddr 1.1.1.2 ip daddr 2.2.4.0-2.2.4.10 accept hitting the following assertion: nft: optimize.c:585: __merge_concat_stmts: Assertion `0' failed. Abort This patch also updates tests/shell. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: expand implicit set element when merging into concatenationPablo Neira Ayuso2022-08-301-10/+50
| | | | | | | | | | | | | | | | | | | | | | | | Generalize the existing code to deal with implicit sets. When merging a ruleset like the following: udp dport 128 iifname "foo" #1 udp dport { 67, 123 } iifname "bar" #2 into a concatenation of statements, the following expansion need to be done for rule #2: 67 . "bar" 123 . "bar" The expansion logic consists of cloning the existing concatenation being built and then append each element in the implicit set. A list of ongoing concatenations being built is maintained, so further expansions are also supported. Extend test to cover for this use-case. Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1628 Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: check for mergeable rulesPablo Neira Ayuso2022-08-111-1/+27
| | | | | | Rules that are equal need to have at least one mergeable statement. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: merging concatenation is unsupportedPablo Neira Ayuso2022-08-111-0/+4
| | | | | | | | | | | Existing concatenation cannot be merge at this stage, skip them otherwise this assertion is hit: nft: optimize.c:434: rule_build_stmt_matrix_stmts: Assertion `k >= 0' failed Extend existing test to cover this. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: limit statement is not supported yetPablo Neira Ayuso2022-06-231-12/+0
| | | | | | | | Revert support for limit statement, the limit statement is stateful and it applies a ratelimit per rule, transformation for merging rules with the limit statement needs to use anonymous sets with statements. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: assume verdict is same when rules have no verdictPablo Neira Ayuso2022-06-231-1/+2
| | | | Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: only merge OP_IMPLICIT and OP_EQ relationalPablo Neira Ayuso2022-06-231-0/+10
| | | | | | Add test to cover this case. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: add unsupported statementPablo Neira Ayuso2022-06-231-4/+52
| | | | | | | | | | | | | | | | Do not try to merge rules with unsupported statements. This patch adds a dummy unsupported statement which is included in the statement collection and the rule vs statement matrix. When looking for possible rule mergers, rules using unsupported statements are discarded, otherwise bogus rule mergers might occur. Note that __stmt_type_eq() already returns false for unsupported statements. Add a test using meta mark statement, which is not yet supported. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: add hash expression supportPablo Neira Ayuso2022-06-231-0/+12
| | | | | | Extend expr_cmp() to compare hash expressions used in relational. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: add numgen expression supportPablo Neira Ayuso2022-06-231-0/+8
| | | | | | Extend expr_cmp() to compare numgen expressions used in relational. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: add binop expression supportPablo Neira Ayuso2022-06-231-0/+2
| | | | | | | Do recursive call using left expression in the binop expression tree to search for the primary expression. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: add fib expression supportPablo Neira Ayuso2022-06-231-0/+6
| | | | | | Extend expr_cmp() to compare fib expressions used in relational. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: add xfrm expression supportPablo Neira Ayuso2022-06-231-0/+6
| | | | | | Extend expr_cmp() to compare xfrm expressions used in relational. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: add osf expression supportPablo Neira Ayuso2022-06-231-0/+6
| | | | | | Extend expr_cmp() to compare osf expressions used in relational. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: fix verdict map mergingPablo Neira Ayuso2022-06-231-4/+7
| | | | | | | | | | Skip comparison when collecting the statement and building the rule vs statement matrix. Compare verdict type when merging rules. When infering rule mergers, honor the STMT_VERDICT with map (ie. vmap). Fixes: 561aa3cfa8da ("optimize: merge verdict maps with same lookup key") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: fix reject statementPablo Neira Ayuso2022-06-231-3/+16
| | | | | | | | Add missing code to the statement collection routine. Compare reject expressions when available. Add tests/shell. Fixes: fb298877ece2 ("src: add ruleset optimization infrastructure") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: remove comment after mergingPablo Neira Ayuso2022-06-231-0/+5
| | | | | | | | | Remove rule comment after merging rules, let the user decide if they want to reintroduce the comment in the ruleset file. Update optimizations/merge_stmt test. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: do not print stateful informationPablo Neira Ayuso2022-06-231-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | Do not print stateful information such as counters which are likely set to zero. Before this patch: Merging: packets.conf:10:3-29: ip protocol 4 counter drop packets.conf:11:3-29: ip protocol 41 counter drop packets.conf:12:3-29: ip protocol 47 counter drop into: ip protocol { 4, 41, 47 } counter packets 0 bytes 0 drop ^^^^^^^^^^^^^^^^^ After: Merging: packets.conf:10:3-29: ip protocol 4 counter drop packets.conf:11:3-29: ip protocol 41 counter drop packets.conf:12:3-29: ip protocol 47 counter drop into: ip protocol { 4, 41, 47 } counter drop Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: do not merge rules with set reference in rhsPablo Neira Ayuso2022-06-231-0/+10
| | | | | | | Otherwise set reference ends up included in an anonymous set, as an element, which is not supported. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: do not compare relational expression rhs when collecting statementsPablo Neira Ayuso2022-06-231-18/+21
| | | | | | | | | | | When building the statement matrix, do not compare expression right hand side, otherwise bogus mismatches might occur. The fully compared flag is set on when comparing rules to look for possible mergers. Fixes: 3f36cc6c3dcd ("optimize: do not merge unsupported statement expressions") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: segfault when releasing unsupported statementPablo Neira Ayuso2022-06-011-1/+1
| | | | | | | | | Call xfree() instead since stmt_alloc() does not initialize the statement type fields. Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1609 Fixes: ea1f1c9ff608 ("optimize: memleak in statement matrix") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: memleak in statement matrixPablo Neira Ayuso2022-05-041-0/+1
| | | | | | | Release clone object in case this statement is not supported. Fixes: 743b0e81371f ("optimize: do not clone unsupported statement") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: merge nat rules with same selectors into mapPablo Neira Ayuso2022-05-031-10/+194
| | | | | | | | | | | | | | | | | | | | | | | Verdict and nat are mutually exclusive, no need to support for this combination. # cat ruleset.nft table ip x { chain y { type nat hook postrouting priority srcnat; policy drop; ip saddr 1.1.1.1 tcp dport 8000 snat to 4.4.4.4:80 ip saddr 2.2.2.2 tcp dport 8001 snat to 5.5.5.5:90 } } # nft -o -c -f ruleset.nft Merging: ruleset.nft:4:3-52: ip saddr 1.1.1.1 tcp dport 8000 snat to 4.4.4.4:80 ruleset.nft:5:3-52: ip saddr 2.2.2.2 tcp dport 8001 snat to 5.5.5.5:90 into: snat to ip saddr . tcp dport map { 1.1.1.1 . 8000 : 4.4.4.4 . 80, 2.2.2.2 . 8001 : 5.5.5.5 . 90 } Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: do not clone unsupported statementPablo Neira Ayuso2022-05-031-1/+1
| | | | | | | | Skip unsupported statements when building the statement matrix, otherwise clone remains uninitialized. Fixes: fb298877ece2 ("src: add ruleset optimization infrastructure") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: incorrect logic in verdict comparisonPablo Neira Ayuso2022-05-031-4/+6
| | | | | | | | Keep inspecting rule verdicts before assuming they are equal. Update existing test to catch this bug. Fixes: 1542082e259b ("optimize: merge same selector with different verdict into verdict map") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: Restore optimization for raw payload expressionsPablo Neira Ayuso2022-03-291-3/+0
| | | | | | | | This patch reverts d0f14b5337e7 ("optimize: do not merge raw payload expressions") after adding support for concatenation with variable length TYPE_INTEGER. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: do not assume log prefixPablo Neira Ayuso2022-03-041-3/+12
| | | | | | ... log prefix might not be present in log statements. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: do not merge unsupported statement expressionsPablo Neira Ayuso2022-03-031-0/+21
| | | | | | Only value, range, prefix, set and list are supported at this stage. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: incorrect assert() for unexpected expression typePablo Neira Ayuso2022-03-031-3/+3
| | | | | | | assert(1) is noop, this should be assert(0) instead. Fixes: 561aa3cfa8da ("optimize: merge verdict maps with same lookup key") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: more robust statement merge with vmapPablo Neira Ayuso2022-03-031-2/+16
| | | | | | | | | | | | | | Check expressions that are expected on the rhs rather than using a catch-all default case. Actually, lists and sets need to be their own routine, because this needs the set element key expression to be merged. This is a follow up to 99eb46969f3d ("optimize: fix vmap with anonymous sets"). Fixes: 1542082e259b ("optimize: merge same selector with different verdict into verdict map") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: fix vmap with anonymous setsPablo Neira Ayuso2022-03-031-2/+6
| | | | | | | | | | | | | | | | The following example ruleset crashes: table inet a { chain b { tcp dport { 1 } accept tcp dport 2-3 drop } } because handling for EXPR_SET is missing. Fixes: 1542082e259b ("optimize: merge same selector with different verdict into verdict map") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: do not merge raw payload expressionsPablo Neira Ayuso2022-01-261-0/+3
| | | | | | | | | | | Merging raw expressions results in a valid concatenation which throws: Error: can not use variable sized data types (integer) in concat expressions Disable merging raw expressions until this is supported by skipping raw expressions. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: check for payload base and offset when searching for mergersPablo Neira Ayuso2022-01-261-0/+4
| | | | | | Extend the existing checks to cover the payload base and offset. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: merge verdict maps with same lookup keyPablo Neira Ayuso2022-01-261-12/+93
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Merge two consecutive verdict maps with the same lookup key. For instance, merge the following: table inet x { chain filter_in_tcp { tcp dport vmap { 80 : accept, 81 : accept, 443 : accept, 931 : accept, 5001 : accept, 5201 : accept, } tcp dport vmap { 6800-6999 : accept, 33434-33499 : accept, } } } into: table inet x { chain filter_in_tcp { tcp dport vmap { 80 : accept, 81 : accept, 443 : accept, 931 : accept, 5001 : accept, 5201 : accept, 6800-6999 : accept, 33434-33499 : accept, } } } This patch updates statement comparison routine to inspect the verdict expression type to detect possible merger. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: add __expr_cmp()Pablo Neira Ayuso2022-01-261-46/+52
| | | | | | Add helper function to compare expression to allow for reuse. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: silence compiler warningsFlorian Westphal2022-01-151-1/+1
| | | | | | | | | | | | cache.c:504:22: warning: ‘chain’ may be used uninitialized in this function [-Wmaybe-uninitialized] cache.c:504:22: warning: ‘table’ may be used uninitialized in this function [-Wmaybe-uninitialized] erec.c:128:16: warning: ‘line’ may be used uninitialized in this function [-Wmaybe-uninitialized] optimize.c:524:9: warning: ‘line’ may be used uninitialized in this function [-Wmaybe-uninitialized] Fixes: 8ad4056e9182 ("erec: expose print_location() and line_location()") Fixes: afbd102211dc ("src: do not use the nft_cache_filter object from mnl.c") Fixes: fb298877ece2 ("src: add ruleset optimization infrastructure") Signed-off-by: Florian Westphal <fw@strlen.de>
* optimize: merge several selectors with different verdict into verdict mapPablo Neira Ayuso2022-01-151-1/+56
| | | | | | | | | | | | | Transform: ip saddr 1.1.1.1 ip daddr 2.2.2.2 accept ip saddr 2.2.2.2 ip daddr 3.3.3.3 drop into: ip saddr . ip daddr vmap { 1.1.1.1 . 2.2.2.2 : accept, 2.2.2.2 . 3.3.3.3 : drop } Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: merge same selector with different verdict into verdict mapPablo Neira Ayuso2022-01-151-15/+147
| | | | | | | | | | | | | Transform: ct state invalid drop ct state established,related accept into: ct state vmap { established : accept, related : accept, invalid : drop } Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* optimize: merge rules with same selectors into a concatenationPablo Neira Ayuso2022-01-151-1/+43
| | | | | | | | | | | | | | | | | This patch extends the ruleset optimization infrastructure to collapse several rules with the same selectors into a concatenation. Transform: 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.5 accept meta iifname eth2 ip saddr 1.1.1.3 ip daddr 2.2.2.6 accept into: meta iifname . ip saddr . ip daddr { eth1 . 1.1.1.1 . 2.2.2.6, eth1 . 1.1.1.2 . 2.2.2.5 , eth1 . 1.1.1.3 . 2.2.2.6 } accept Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: add ruleset optimization infrastructurePablo Neira Ayuso2022-01-151-0/+478
This patch adds a new -o/--optimize option to enable ruleset optimization. You can combine this option with the dry run mode (--check) to review the proposed ruleset updates without actually loading the ruleset, e.g. # nft -c -o -f ruleset.test Merging: ruleset.nft:16:3-37: ip daddr 192.168.0.1 counter accept ruleset.nft:17:3-37: ip daddr 192.168.0.2 counter accept ruleset.nft:18:3-37: ip daddr 192.168.0.3 counter accept into: ip daddr { 192.168.0.1, 192.168.0.2, 192.168.0.3 } counter packets 0 bytes 0 accept This infrastructure collects the common statements that are used in rules, then it builds a matrix of rules vs. statements. Then, it looks for common statements in consecutive rules which allows to merge rules. This ruleset optimization always performs an implicit dry run to validate that the original ruleset is correct. Then, on a second pass, it performs the ruleset optimization and add the rules into the kernel (unless --check has been specified by the user). From libnftables perspective, there is a new API to enable this feature: uint32_t nft_ctx_get_optimize(struct nft_ctx *ctx); void nft_ctx_set_optimize(struct nft_ctx *ctx, uint32_t flags); This patch adds support for the first optimization: Collapse a linear list of rules matching on a single selector into a set as exposed in the example above. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>