summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2020-10-27 17:33:15 +0100
committerPhil Sutter <phil@nwl.cc>2020-11-04 14:44:11 +0100
commit25338cdb6c77aa2f0977afbbb612571c9d325213 (patch)
treee18d5b58d9718ebb9ee21cb06f189eb94bf7a22c /src
parent8a927c56d83ed0f78785011bd92a53edc25a0ca0 (diff)
src: Optimize prefix matches on byte-boundaries
If a prefix expression's length is on a byte-boundary, it is sufficient to just reduce the length passed to "cmp" expression. No need for explicit bitwise modification of data on LHS. The relevant code is already there, used for string prefix matches. There is one exception though, namely zero-length prefixes: Kernel doesn't accept zero-length "cmp" expressions, so keep them in the old code-path for now. This patch depends upon the previous one to correctly parse odd-sized payload matches but has to extend support for non-payload LHS as well. In practice, this is needed for "ct" expressions as they allow matching against IP address prefixes, too. Signed-off-by: Phil Sutter <phil@nwl.cc>
Diffstat (limited to 'src')
-rw-r--r--src/netlink_delinearize.c5
-rw-r--r--src/netlink_linearize.c4
2 files changed, 6 insertions, 3 deletions
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index b7876a8d..32ec07a0 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -322,8 +322,9 @@ static void netlink_parse_cmp(struct netlink_parse_ctx *ctx,
if (left->len > right->len &&
expr_basetype(left) != &string_type) {
- netlink_error(ctx, loc, "Relational expression size mismatch");
- goto err_free;
+ mpz_lshift_ui(right->value, left->len - right->len);
+ right = prefix_expr_alloc(loc, right, right->len);
+ right->prefix->len = left->len;
} else if (left->len > 0 && left->len < right->len) {
expr_free(left);
left = netlink_parse_concat_expr(ctx, loc, sreg, right->len);
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 38f66be8..23cf5463 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -533,7 +533,9 @@ static void netlink_gen_relational(struct netlink_linearize_ctx *ctx,
return netlink_gen_flagcmp(ctx, expr, dreg);
case EXPR_PREFIX:
sreg = get_register(ctx, expr->left);
- if (expr_basetype(expr->left)->type != TYPE_STRING) {
+ if (expr_basetype(expr->left)->type != TYPE_STRING &&
+ (!expr->right->prefix_len ||
+ expr->right->prefix_len % BITS_PER_BYTE)) {
len = div_round_up(expr->right->len, BITS_PER_BYTE);
netlink_gen_expr(ctx, expr->left, sreg);
right = netlink_gen_prefix(ctx, expr, sreg);