]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: Optimize prefix matches on byte-boundaries
authorPhil Sutter <phil@nwl.cc>
Tue, 27 Oct 2020 16:33:15 +0000 (17:33 +0100)
committerPhil Sutter <phil@nwl.cc>
Wed, 4 Nov 2020 13:44:11 +0000 (14:44 +0100)
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>
src/netlink_delinearize.c
src/netlink_linearize.c
tests/py/ip/ct.t.payload
tests/py/ip/ip.t.payload
tests/py/ip/ip.t.payload.bridge
tests/py/ip/ip.t.payload.inet
tests/py/ip/ip.t.payload.netdev
tests/py/ip6/ip6.t.payload.inet
tests/py/ip6/ip6.t.payload.ip6

index b7876a8da83755fdecab7b2508f752c8dec527c7..32ec07a09121625b490168bded1f62741491d2e0 100644 (file)
@@ -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);
index 38f66be8814f96b276c704408f53dec578bece6c..23cf54639303a9e758fdf9605455391bf859ab8a 100644 (file)
@@ -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);
index d5faed4c667c526592b16c33177b6b9e2c63cb04..a7e08f98e6a3e4065cbc176cd3b7c253589cbb06 100644 (file)
@@ -21,25 +21,21 @@ ip test-ip4 output
 # ct original ip saddr 192.168.1.0/24
 ip test-ip4 output
   [ ct load src_ip => reg 1 , dir original ]
-  [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
   [ cmp eq reg 1 0x0001a8c0 ]
 
 # ct reply ip saddr 192.168.1.0/24
 ip test-ip4 output
   [ ct load src_ip => reg 1 , dir reply ]
-  [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
   [ cmp eq reg 1 0x0001a8c0 ]
 
 # ct original ip daddr 192.168.1.0/24
 ip test-ip4 output
   [ ct load dst_ip => reg 1 , dir original ]
-  [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
   [ cmp eq reg 1 0x0001a8c0 ]
 
 # ct reply ip daddr 192.168.1.0/24
 ip test-ip4 output
   [ ct load dst_ip => reg 1 , dir reply ]
-  [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
   [ cmp eq reg 1 0x0001a8c0 ]
 
 # ct l3proto ipv4
index d627b22f261481259d7b530b99d72d439bf67fcc..825c0f0b1b6ed644ce680cb8cc9ce4313b1ef320 100644 (file)
@@ -358,14 +358,12 @@ ip test-ip4 input
 
 # ip saddr 192.168.2.0/24
 ip test-ip4 input
-  [ payload load 4b @ network header + 12 => reg 1 ]
-  [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
+  [ payload load 3b @ network header + 12 => reg 1 ]
   [ cmp eq reg 1 0x0002a8c0 ]
 
 # ip saddr != 192.168.2.0/24
 ip test-ip4 input
-  [ payload load 4b @ network header + 12 => reg 1 ]
-  [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
+  [ payload load 3b @ network header + 12 => reg 1 ]
   [ cmp neq reg 1 0x0002a8c0 ]
 
 # ip saddr 192.168.3.1 ip daddr 192.168.3.100
index 91a4fde382e6555d335b6742819ef9b691093071..e958a5b4b4e9e18be684608d33361a13c508f548 100644 (file)
@@ -466,16 +466,14 @@ bridge test-bridge input
 bridge test-bridge input 
   [ meta load protocol => reg 1 ]
   [ cmp eq reg 1 0x00000008 ]
-  [ payload load 4b @ network header + 12 => reg 1 ]
-  [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
+  [ payload load 3b @ network header + 12 => reg 1 ]
   [ cmp eq reg 1 0x0002a8c0 ]
 
 # ip saddr != 192.168.2.0/24
 bridge test-bridge input 
   [ meta load protocol => reg 1 ]
   [ cmp eq reg 1 0x00000008 ]
-  [ payload load 4b @ network header + 12 => reg 1 ]
-  [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
+  [ payload load 3b @ network header + 12 => reg 1 ]
   [ cmp neq reg 1 0x0002a8c0 ]
 
 # ip saddr 192.168.3.1 ip daddr 192.168.3.100
index b9cb28a22e7a8bc2bc76c6fbade8add21ddc4394..650147391c97886316eeb0cba20a67aaa5d0c5a8 100644 (file)
@@ -466,16 +466,14 @@ inet test-inet input
 inet test-inet input
   [ meta load nfproto => reg 1 ]
   [ cmp eq reg 1 0x00000002 ]
-  [ payload load 4b @ network header + 12 => reg 1 ]
-  [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
+  [ payload load 3b @ network header + 12 => reg 1 ]
   [ cmp eq reg 1 0x0002a8c0 ]
 
 # ip saddr != 192.168.2.0/24
 inet test-inet input
   [ meta load nfproto => reg 1 ]
   [ cmp eq reg 1 0x00000002 ]
-  [ payload load 4b @ network header + 12 => reg 1 ]
-  [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
+  [ payload load 3b @ network header + 12 => reg 1 ]
   [ cmp neq reg 1 0x0002a8c0 ]
 
 # ip saddr 192.168.3.1 ip daddr 192.168.3.100
index 588e5ca2a3e30eacc7cb372b7a0ea6de610fdd7a..58ae358bdc47843ece3403bf0a79b0ec819708ec 100644 (file)
@@ -379,16 +379,14 @@ netdev test-netdev ingress
 netdev test-netdev ingress 
   [ meta load protocol => reg 1 ]
   [ cmp eq reg 1 0x00000008 ]
-  [ payload load 4b @ network header + 12 => reg 1 ]
-  [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
+  [ payload load 3b @ network header + 12 => reg 1 ]
   [ cmp eq reg 1 0x0002a8c0 ]
 
 # ip saddr != 192.168.2.0/24
 netdev test-netdev ingress 
   [ meta load protocol => reg 1 ]
   [ cmp eq reg 1 0x00000008 ]
-  [ payload load 4b @ network header + 12 => reg 1 ]
-  [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
+  [ payload load 3b @ network header + 12 => reg 1 ]
   [ cmp neq reg 1 0x0002a8c0 ]
 
 # ip saddr 192.168.3.1 ip daddr 192.168.3.100
index d015c8efaa2575344e8997b7d29464c3234541ea..ffc9b9f5b560bb2d9552bc6d49d77cd82ef9c44e 100644 (file)
@@ -604,9 +604,8 @@ inet test-inet input
 inet test-inet input
   [ meta load nfproto => reg 1 ]
   [ cmp eq reg 1 0x0000000a ]
-  [ payload load 16b @ network header + 8 => reg 1 ]
-  [ bitwise reg 1 = (reg=1 & 0xffffffff 0xffffffff 0x00000000 0x00000000 ) ^ 0x00000000 0x00000000 0x00000000 0x00000000 ]
-  [ cmp eq reg 1 0x00000000 0x00000000 0x00000000 0x00000000 ]
+  [ payload load 8b @ network header + 8 => reg 1 ]
+  [ cmp eq reg 1 0x00000000 0x00000000 ]
 
 # ip6 saddr ::1 ip6 daddr ::2
 inet test-inet input
index b2e8363c01e1fccd0099c6dc26f95e4683bf423c..18b8bcbe601a0944ad21c5e39499cf02cbde1c32 100644 (file)
@@ -452,9 +452,8 @@ ip6 test-ip6 input
 
 # ip6 saddr ::/64
 ip6 test-ip6 input
-  [ payload load 16b @ network header + 8 => reg 1 ]
-  [ bitwise reg 1 = (reg=1 & 0xffffffff 0xffffffff 0x00000000 0x00000000 ) ^ 0x00000000 0x00000000 0x00000000 0x00000000 ]
-  [ cmp eq reg 1 0x00000000 0x00000000 0x00000000 0x00000000 ]
+  [ payload load 8b @ network header + 8 => reg 1 ]
+  [ cmp eq reg 1 0x00000000 0x00000000 ]
 
 # ip6 saddr ::1 ip6 daddr ::2
 ip6 test-ip6 input