[PATCH nft] netlink_linearize: reduce register waste with non-constant binop expressions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Register use is not good with bitwise operations that involve three or
more selectors, eg.

 mark set ip dscp and 0x3 or ct mark or meta mark
  [ payload load 1b @ network header + 1 => reg 1 ]
  [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
  [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
  [ bitwise reg 1 = ( reg 1 & 0x00000003 ) ^ 0x00000000 ]
  [ ct load mark => reg 2 ]
  [ bitwise reg 1 = ( reg 1 | reg 2 ) ]
  [ meta load mark => reg 3 ]		  <--- this could use register 2 instead!
  [ bitwise reg 1 = ( reg 1 | reg 3 ) ]
  [ meta set mark with reg 1 ]

register 3 is use to store meta mark, however, register 2 can be already
use since register 1 already stores the partial result of the bitwise
operation for this expression.

After this fix:

  [ payload load 1b @ network header + 1 => reg 1 ]
  [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
  [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
  [ bitwise reg 1 = ( reg 1 & 0x00000003 ) ^ 0x00000000 ]
  [ ct load mark => reg 2 ]
  [ bitwise reg 1 = ( reg 1 | reg 2 ) ]
  [ meta load mark => reg 2 ]            <--- recycle register 2
  [ bitwise reg 1 = ( reg 1 | reg 2 ) ]
  [ meta set mark with reg 1 ]

Release source register in bitwise operation given destination register
already stores the partial result of the expression.

Extend tests/py to cover this.

Fixes: 54bfc38c522b ("src: allow binop expressions with variable right-hand operands")
Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
---
 src/netlink_linearize.c     |  1 +
 tests/py/any/meta.t         |  2 ++
 tests/py/any/meta.t.json    | 32 ++++++++++++++++++++++++++++++++
 tests/py/any/meta.t.payload |  9 +++++++++
 4 files changed, 44 insertions(+)

diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index e69d323cdeaf..598ddfab5827 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -778,6 +778,7 @@ static void netlink_gen_bitwise_bool(struct netlink_linearize_ctx *ctx,
 	sreg2 = get_register(ctx, expr->right);
 	netlink_gen_expr(ctx, expr->right, sreg2);
 	netlink_put_register(nle, NFTNL_EXPR_BITWISE_SREG2, sreg2);
+	release_register(ctx, expr->right);
 
 	len = div_round_up(expr->len, BITS_PER_BYTE);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_BITWISE_LEN, len);
diff --git a/tests/py/any/meta.t b/tests/py/any/meta.t
index bd10c56dfe5f..3f0ef121a8c0 100644
--- a/tests/py/any/meta.t
+++ b/tests/py/any/meta.t
@@ -228,3 +228,5 @@ meta day 7 drop;fail
 meta mark set vlan id map { 1 : 0x00000001, 4095 : 0x00004095 };ok
 !map1 typeof vlan id : meta mark;ok
 meta mark set vlan id map @map1;ok
+
+meta mark set meta mark | iif | meta cpu;ok
diff --git a/tests/py/any/meta.t.json b/tests/py/any/meta.t.json
index 676affea4dc6..65590388bb80 100644
--- a/tests/py/any/meta.t.json
+++ b/tests/py/any/meta.t.json
@@ -2818,3 +2818,35 @@
     }
 ]
 
+# meta mark set meta mark | iif | meta cpu
+[
+    {
+        "mangle": {
+            "key": {
+                "meta": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "meta": {
+                            "key": "mark"
+                        }
+                    },
+                    {
+                        "meta": {
+                            "key": "iif"
+                        }
+                    },
+                    {
+                        "meta": {
+                            "key": "cpu"
+                        }
+                    }
+                ]
+            }
+        }
+    }
+]
+
diff --git a/tests/py/any/meta.t.payload b/tests/py/any/meta.t.payload
index a037e0673fec..52c3efa84eb5 100644
--- a/tests/py/any/meta.t.payload
+++ b/tests/py/any/meta.t.payload
@@ -1090,3 +1090,12 @@ ip test-ip4 input
   [ bitwise reg 1 = ( reg 1 & 0x0000ff0f ) ^ 0x00000000 ]
   [ lookup reg 1 set map1 dreg 1 ]
   [ meta set mark with reg 1 ]
+
+# meta mark set meta mark | iif | meta cpu
+ip test-ip4 input
+  [ meta load mark => reg 1 ]
+  [ meta load iif => reg 2 ]
+  [ bitwise reg 1 = ( reg 1 | reg 2 ) ]
+  [ meta load cpu => reg 2 ]
+  [ bitwise reg 1 = ( reg 1 | reg 2 ) ]
+  [ meta set mark with reg 1 ]
-- 
2.30.2





[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux