summaryrefslogtreecommitdiffstats
path: root/src/payload.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/payload.c')
-rw-r--r--src/payload.c28
1 files changed, 27 insertions, 1 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;
}
/**