diff options
-rw-r--r-- | src/payload.c | 28 | ||||
-rw-r--r-- | tests/shell/testcases/nft-f/dumps/0012different_defines_0.nft | 2 |
2 files changed, 28 insertions, 2 deletions
diff --git a/src/payload.c b/src/payload.c index fab97b11..f638b0c0 100644 --- a/src/payload.c +++ b/src/payload.c @@ -721,7 +721,33 @@ bool payload_can_merge(const struct expr *e1, const struct expr *e2) if (total < e1->len || total > (NFT_REG_SIZE * BITS_PER_BYTE)) return false; - return true; + /* could return true after this, the expressions are mergeable. + * + * However, there are some caveats. + * + * Loading anything <= sizeof(u32) with base >= network header + * is fast, because its handled directly from eval loop in the + * kernel. + * + * We thus restrict merging a bit more. + */ + + /* can still be handled by fastpath after merge */ + if (total <= NFT_REG32_SIZE * BITS_PER_BYTE) + return true; + + /* Linklayer base is not handled in fastpath, merge */ + if (e1->payload.base == PROTO_BASE_LL_HDR) + return true; + + /* Also merge if at least one expression is already + * above REG32 size, in this case merging is faster. + */ + if (e1->len > (NFT_REG32_SIZE * BITS_PER_BYTE) || + e2->len > (NFT_REG32_SIZE * BITS_PER_BYTE)) + return true; + + return false; } /** diff --git a/tests/shell/testcases/nft-f/dumps/0012different_defines_0.nft b/tests/shell/testcases/nft-f/dumps/0012different_defines_0.nft index c67d25b6..7abced86 100644 --- a/tests/shell/testcases/nft-f/dumps/0012different_defines_0.nft +++ b/tests/shell/testcases/nft-f/dumps/0012different_defines_0.nft @@ -4,7 +4,7 @@ table inet t { iifname { "whatever" } iif { "lo" } meta mark 0x0000007b ct state established,related,new ct state != established | related | new - ip saddr 10.0.0.0 ip saddr 10.0.0.0 ip daddr 10.0.0.2 + ip saddr 10.0.0.0 ip daddr 10.0.0.2 ip saddr 10.0.0.0 ip6 daddr fe0::1 ip6 saddr fe0::2 ip saddr vmap { 10.0.0.0 : drop, 10.0.0.2 : accept } ip6 daddr vmap { fe0::1 : drop, fe0::2 : accept } |