netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH nft,v3 00/12] mark statement support for non-constant expression
@ 2023-03-23 16:58 Pablo Neira Ayuso
  2023-03-23 16:58 ` [PATCH nft,v3 01/12] netlink_delinearize: correct type and byte-order of shifts Pablo Neira Ayuso
                   ` (11 more replies)
  0 siblings, 12 replies; 15+ messages in thread
From: Pablo Neira Ayuso @ 2023-03-23 16:58 UTC (permalink / raw)
  To: netfilter-devel; +Cc: jeremy, fw

Hi,

This is v3 of the following patchset:

https://marc.info/?l=netfilter-devel&m=167904710124404&w=2

this takes over the initial effort from Jeremy Sowden to enhance mark
statements support for variable expression.

This round emphasizes on the support for bitwise expression (not only shift).

No kernel updates are required in this batch.

Patch #1 no changes.

Patch #2 changes to sets ctx->stmt_len for meta and ct only, reset
	 ctx->stmt_len in expr_evaluate_map() to avoid interference
	 with map evaluation.

Patch #3 no changes.

Patch #4 no changes.

Patch #5 new in this series, missing type in shift evaluation.
	 This is required to evaluate constant shift, eg. 1 << 1
         which is reduced at evaluation step to 0x2.

Patch #6 disable lhs maximum length cap when ctx->stmt_len is available.
	 This allows for: meta mark set ip dscp | 0xff000000

Patch #7 honor ctx->stmt_len in bitwise evaluation, otherwise evaluation
         results in incorrect bytecode. This assumes host byteorder for
	 the statement, which is fine at this stage since only ct and
	 meta statement are supported.

Patch #8 adjust byteorder in delinearize path if bitwise length hints
	 that it refers to the statement length. This assumes host
	 byteorder, in this future, when this support is generalized this
	 requires to infer the byteorder from the statement that has been
	 used.

Patch #9-#12 tests already posted in the previous batch and new ones.

Jeremy Sowden (5):
  netlink_delinearize: correct type and byte-order of shifts
  evaluate: don't eval unary arguments
  tests: py: add test-cases for ct and packet mark payload expressions
  tests: shell: rename and move bitwise test-cases
  tests: shell: add test-cases for ct and packet mark payload expressions

Pablo Neira Ayuso (7):
  evaluate: support shifts larger than the width of the left operand
  evaluate: relax type-checking for integer arguments in mark statements
  evaluate: set up integer type to shift expression
  evaluate: honor statement length in integer evaluation
  evaluate: honor statement length in bitwise evaluation
  netlink_delinerize: incorrect byteorder in mark statement listing
  tests: py: extend test-cases for mark statements with bitwise expressions

 include/rule.h                                |   1 +
 src/evaluate.c                                | 119 +++++--
 src/netlink_delinearize.c                     |  35 ++-
 tests/py/ip/ct.t                              |   6 +
 tests/py/ip/ct.t.json                         | 154 +++++++++
 tests/py/ip/ct.t.payload                      |  50 +++
 tests/py/ip/meta.t                            |   5 +
 tests/py/ip/meta.t.json                       |  78 +++++
 tests/py/ip/meta.t.payload                    |  25 ++
 tests/py/ip6/ct.t                             |   9 +
 tests/py/ip6/ct.t.json                        | 293 ++++++++++++++++++
 tests/py/ip6/ct.t.payload                     |  46 +++
 tests/py/ip6/meta.t                           |   3 +
 tests/py/ip6/meta.t.json                      |  58 ++++
 tests/py/ip6/meta.t.payload                   |  20 ++
 .../0040mark_binop_0}                         |   2 +-
 .../0040mark_binop_1}                         |   2 +-
 .../shell/testcases/bitwise/0040mark_binop_2  |  11 +
 .../shell/testcases/bitwise/0040mark_binop_3  |  11 +
 .../shell/testcases/bitwise/0040mark_binop_4  |  11 +
 .../shell/testcases/bitwise/0040mark_binop_5  |  11 +
 .../shell/testcases/bitwise/0040mark_binop_6  |  11 +
 .../shell/testcases/bitwise/0040mark_binop_7  |  11 +
 .../shell/testcases/bitwise/0040mark_binop_8  |  11 +
 .../shell/testcases/bitwise/0040mark_binop_9  |  11 +
 .../dumps/0040mark_binop_0.nft}               |   2 +-
 .../dumps/0040mark_binop_1.nft}               |   2 +-
 .../bitwise/dumps/0040mark_binop_2.nft        |   6 +
 .../bitwise/dumps/0040mark_binop_3.nft        |   6 +
 .../bitwise/dumps/0040mark_binop_4.nft        |   6 +
 .../bitwise/dumps/0040mark_binop_5.nft        |   6 +
 .../bitwise/dumps/0040mark_binop_6.nft        |   6 +
 .../bitwise/dumps/0040mark_binop_7.nft        |   6 +
 .../bitwise/dumps/0040mark_binop_8.nft        |   6 +
 .../bitwise/dumps/0040mark_binop_9.nft        |   6 +
 35 files changed, 1004 insertions(+), 42 deletions(-)
 create mode 100644 tests/py/ip6/ct.t
 create mode 100644 tests/py/ip6/ct.t.json
 create mode 100644 tests/py/ip6/ct.t.payload
 rename tests/shell/testcases/{chains/0040mark_shift_0 => bitwise/0040mark_binop_0} (68%)
 rename tests/shell/testcases/{chains/0040mark_shift_1 => bitwise/0040mark_binop_1} (70%)
 create mode 100755 tests/shell/testcases/bitwise/0040mark_binop_2
 create mode 100755 tests/shell/testcases/bitwise/0040mark_binop_3
 create mode 100755 tests/shell/testcases/bitwise/0040mark_binop_4
 create mode 100755 tests/shell/testcases/bitwise/0040mark_binop_5
 create mode 100755 tests/shell/testcases/bitwise/0040mark_binop_6
 create mode 100755 tests/shell/testcases/bitwise/0040mark_binop_7
 create mode 100755 tests/shell/testcases/bitwise/0040mark_binop_8
 create mode 100755 tests/shell/testcases/bitwise/0040mark_binop_9
 rename tests/shell/testcases/{chains/dumps/0040mark_shift_0.nft => bitwise/dumps/0040mark_binop_0.nft} (58%)
 rename tests/shell/testcases/{chains/dumps/0040mark_shift_1.nft => bitwise/dumps/0040mark_binop_1.nft} (64%)
 create mode 100644 tests/shell/testcases/bitwise/dumps/0040mark_binop_2.nft
 create mode 100644 tests/shell/testcases/bitwise/dumps/0040mark_binop_3.nft
 create mode 100644 tests/shell/testcases/bitwise/dumps/0040mark_binop_4.nft
 create mode 100644 tests/shell/testcases/bitwise/dumps/0040mark_binop_5.nft
 create mode 100644 tests/shell/testcases/bitwise/dumps/0040mark_binop_6.nft
 create mode 100644 tests/shell/testcases/bitwise/dumps/0040mark_binop_7.nft
 create mode 100644 tests/shell/testcases/bitwise/dumps/0040mark_binop_8.nft
 create mode 100644 tests/shell/testcases/bitwise/dumps/0040mark_binop_9.nft

-- 
2.30.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH nft,v3 01/12] netlink_delinearize: correct type and byte-order of shifts
  2023-03-23 16:58 [PATCH nft,v3 00/12] mark statement support for non-constant expression Pablo Neira Ayuso
@ 2023-03-23 16:58 ` Pablo Neira Ayuso
  2023-03-23 16:58 ` [PATCH nft,v3 02/12] evaluate: support shifts larger than the width of the left operand Pablo Neira Ayuso
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Pablo Neira Ayuso @ 2023-03-23 16:58 UTC (permalink / raw)
  To: netfilter-devel; +Cc: jeremy, fw

From: Jeremy Sowden <jeremy@azazel.net>

Downgrade to base type integer instead of the specific type from the
expression that is used in the shift operation.

Without this, listing a rule like:

  ct mark set ip dscp lshift 2 or 0x10

will return:

  ct mark set ip dscp << 2 | cs2

because the type of the OR's right operand will be transitively derived
from `ip dscp`.  However, this is not valid syntax:

  # nft add rule t c ct mark set ip dscp '<<' 2 '|' cs2
  Error: Could not parse integer
  add rule t c ct mark set ip dscp << 2 | cs2
                                          ^^^

Use xinteger_type to print the output in hexadecimal.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 src/netlink_delinearize.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 60350cd6cd96..c1b4c1148d33 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -2810,8 +2810,17 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
 		}
 		expr_postprocess(ctx, &expr->right);
 
-		expr_set_type(expr, expr->left->dtype,
-			      expr->left->byteorder);
+		switch (expr->op) {
+		case OP_LSHIFT:
+		case OP_RSHIFT:
+			expr_set_type(expr, &xinteger_type,
+				      BYTEORDER_HOST_ENDIAN);
+			break;
+		default:
+			expr_set_type(expr, expr->left->dtype,
+				      expr->left->byteorder);
+		}
+
 		break;
 	case EXPR_RELATIONAL:
 		switch (expr->left->etype) {
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH nft,v3 02/12] evaluate: support shifts larger than the width of the left operand
  2023-03-23 16:58 [PATCH nft,v3 00/12] mark statement support for non-constant expression Pablo Neira Ayuso
  2023-03-23 16:58 ` [PATCH nft,v3 01/12] netlink_delinearize: correct type and byte-order of shifts Pablo Neira Ayuso
@ 2023-03-23 16:58 ` Pablo Neira Ayuso
  2023-03-23 16:58 ` [PATCH nft,v3 03/12] evaluate: don't eval unary arguments Pablo Neira Ayuso
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Pablo Neira Ayuso @ 2023-03-23 16:58 UTC (permalink / raw)
  To: netfilter-devel; +Cc: jeremy, fw

If we want to left-shift a value of narrower type and assign the result
to a variable of a wider type, we are constrained to only shifting up to
the width of the narrower type.  Thus:

  add rule t c meta mark set ip dscp << 2

works, but:

  add rule t c meta mark set ip dscp << 8

does not, even though the lvalue is large enough to accommodate the
result.

Upgrade the maximum length based on the statement datatype length, which
is provided via context, if it is larger than expression lvalue.

Update netlink_delinearize.c to handle the case where the length of a
shift expression does not match that of its left-hand operand.

Based on patch from Jeremy Sowden.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/rule.h            |  1 +
 src/evaluate.c            | 62 +++++++++++++++++++++++++++------------
 src/netlink_delinearize.c |  4 +--
 3 files changed, 47 insertions(+), 20 deletions(-)

diff --git a/include/rule.h b/include/rule.h
index e1efbb819163..ef094c90b1c1 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -766,6 +766,7 @@ struct eval_ctx {
 	struct rule		*rule;
 	struct set		*set;
 	struct stmt		*stmt;
+	uint32_t		stmt_len;
 	struct expr_ctx		ectx;
 	struct proto_ctx	_pctx[2];
 	const struct proto_desc	*inner_desc;
diff --git a/src/evaluate.c b/src/evaluate.c
index 21d360493ceb..b0a7fa761624 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1289,14 +1289,19 @@ static int constant_binop_simplify(struct eval_ctx *ctx, struct expr **expr)
 static int expr_evaluate_shift(struct eval_ctx *ctx, struct expr **expr)
 {
 	struct expr *op = *expr, *left = op->left, *right = op->right;
+	unsigned int shift = mpz_get_uint32(right->value);
+	unsigned int max_shift_len;
 
-	if (mpz_get_uint32(right->value) >= left->len)
+	if (ctx->stmt_len > left->len)
+		max_shift_len = ctx->stmt_len;
+	else
+		max_shift_len = left->len;
+
+	if (shift >= max_shift_len)
 		return expr_binary_error(ctx->msgs, right, left,
-					 "%s shift of %u bits is undefined "
-					 "for type of %u bits width",
+					 "%s shift of %u bits is undefined for type of %u bits width",
 					 op->op == OP_LSHIFT ? "Left" : "Right",
-					 mpz_get_uint32(right->value),
-					 left->len);
+					 shift, max_shift_len);
 
 	/* Both sides need to be in host byte order */
 	if (byteorder_conversion(ctx, &op->left, BYTEORDER_HOST_ENDIAN) < 0)
@@ -1306,7 +1311,7 @@ static int expr_evaluate_shift(struct eval_ctx *ctx, struct expr **expr)
 		return -1;
 
 	op->byteorder = BYTEORDER_HOST_ENDIAN;
-	op->len       = left->len;
+	op->len	      = max_shift_len;
 
 	if (expr_is_constant(left))
 		return constant_binop_simplify(ctx, expr);
@@ -1339,14 +1344,20 @@ static int expr_evaluate_binop(struct eval_ctx *ctx, struct expr **expr)
 {
 	struct expr *op = *expr, *left, *right;
 	const char *sym = expr_op_symbols[op->op];
+	unsigned int max_shift_len = ctx->ectx.len;
 
 	if (expr_evaluate(ctx, &op->left) < 0)
 		return -1;
 	left = op->left;
 
-	if (op->op == OP_LSHIFT || op->op == OP_RSHIFT)
+	if (op->op == OP_LSHIFT || op->op == OP_RSHIFT) {
+		if (left->len > max_shift_len)
+			max_shift_len = left->len;
+
 		__expr_set_context(&ctx->ectx, &integer_type,
-				   left->byteorder, ctx->ectx.len, 0);
+				   left->byteorder, max_shift_len, 0);
+	}
+
 	if (expr_evaluate(ctx, &op->right) < 0)
 		return -1;
 	right = op->right;
@@ -1865,6 +1876,7 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
 	}
 
 	expr_set_context(&ctx->ectx, NULL, 0);
+	ctx->stmt_len = 0;
 	if (expr_evaluate(ctx, &map->map) < 0)
 		return -1;
 	if (expr_is_constant(map->map))
@@ -3000,20 +3012,34 @@ static int stmt_evaluate_meter(struct eval_ctx *ctx, struct stmt *stmt)
 
 static int stmt_evaluate_meta(struct eval_ctx *ctx, struct stmt *stmt)
 {
-	return stmt_evaluate_arg(ctx, stmt,
-				 stmt->meta.tmpl->dtype,
-				 stmt->meta.tmpl->len,
-				 stmt->meta.tmpl->byteorder,
-				 &stmt->meta.expr);
+	int ret;
+
+	ctx->stmt_len = stmt->meta.tmpl->len;
+
+	ret = stmt_evaluate_arg(ctx, stmt,
+				stmt->meta.tmpl->dtype,
+				stmt->meta.tmpl->len,
+				stmt->meta.tmpl->byteorder,
+				&stmt->meta.expr);
+	ctx->stmt_len = 0;
+
+	return ret;
 }
 
 static int stmt_evaluate_ct(struct eval_ctx *ctx, struct stmt *stmt)
 {
-	if (stmt_evaluate_arg(ctx, stmt,
-			      stmt->ct.tmpl->dtype,
-			      stmt->ct.tmpl->len,
-			      stmt->ct.tmpl->byteorder,
-			      &stmt->ct.expr) < 0)
+	int ret;
+
+	ctx->stmt_len = stmt->ct.tmpl->len;
+
+	ret = stmt_evaluate_arg(ctx, stmt,
+				stmt->ct.tmpl->dtype,
+				stmt->ct.tmpl->len,
+				stmt->ct.tmpl->byteorder,
+				&stmt->ct.expr);
+	ctx->stmt_len = 0;
+
+	if (ret < 0)
 		return -1;
 
 	if (stmt->ct.key == NFT_CT_SECMARK && expr_is_constant(stmt->ct.expr))
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index c1b4c1148d33..4dc28ed8e651 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -489,7 +489,7 @@ static struct expr *netlink_parse_bitwise_bool(struct netlink_parse_ctx *ctx,
 		mpz_ior(m, m, o);
 	}
 
-	if (left->len > 0 && mpz_scan0(m, 0) == left->len) {
+	if (left->len > 0 && mpz_scan0(m, 0) >= left->len) {
 		/* mask encompasses the entire value */
 		expr_free(mask);
 	} else {
@@ -537,7 +537,7 @@ static struct expr *netlink_parse_bitwise_shift(struct netlink_parse_ctx *ctx,
 	right->byteorder = BYTEORDER_HOST_ENDIAN;
 
 	expr = binop_expr_alloc(loc, op, left, right);
-	expr->len = left->len;
+	expr->len = nftnl_expr_get_u32(nle, NFTNL_EXPR_BITWISE_LEN) * BITS_PER_BYTE;
 
 	return expr;
 }
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH nft,v3 03/12] evaluate: don't eval unary arguments
  2023-03-23 16:58 [PATCH nft,v3 00/12] mark statement support for non-constant expression Pablo Neira Ayuso
  2023-03-23 16:58 ` [PATCH nft,v3 01/12] netlink_delinearize: correct type and byte-order of shifts Pablo Neira Ayuso
  2023-03-23 16:58 ` [PATCH nft,v3 02/12] evaluate: support shifts larger than the width of the left operand Pablo Neira Ayuso
@ 2023-03-23 16:58 ` Pablo Neira Ayuso
  2023-03-23 16:58 ` [PATCH nft,v3 04/12] evaluate: relax type-checking for integer arguments in mark statements Pablo Neira Ayuso
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Pablo Neira Ayuso @ 2023-03-23 16:58 UTC (permalink / raw)
  To: netfilter-devel; +Cc: jeremy, fw

From: Jeremy Sowden <jeremy@azazel.net>

When a unary expression is inserted to implement a byte-order
conversion, the expression being converted has already been evaluated
and so `expr_evaluate_unary` doesn't need to do so.

This is required by {ct|meta} statements with bitwise operations, which
might result in byteorder conversion of the expression.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 src/evaluate.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/evaluate.c b/src/evaluate.c
index b0a7fa761624..e0263f97dcf8 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1198,12 +1198,10 @@ static int expr_evaluate_range(struct eval_ctx *ctx, struct expr **expr)
  */
 static int expr_evaluate_unary(struct eval_ctx *ctx, struct expr **expr)
 {
-	struct expr *unary = *expr, *arg;
+	struct expr *unary = *expr, *arg = unary->arg;
 	enum byteorder byteorder;
 
-	if (expr_evaluate(ctx, &unary->arg) < 0)
-		return -1;
-	arg = unary->arg;
+	/* unary expression arguments has already been evaluated. */
 
 	assert(!expr_is_constant(arg));
 	assert(expr_basetype(arg)->type == TYPE_INTEGER);
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH nft,v3 04/12] evaluate: relax type-checking for integer arguments in mark statements
  2023-03-23 16:58 [PATCH nft,v3 00/12] mark statement support for non-constant expression Pablo Neira Ayuso
                   ` (2 preceding siblings ...)
  2023-03-23 16:58 ` [PATCH nft,v3 03/12] evaluate: don't eval unary arguments Pablo Neira Ayuso
@ 2023-03-23 16:58 ` Pablo Neira Ayuso
  2023-03-23 16:58 ` [PATCH nft,v3 05/12] evaluate: set up integer type to shift expression Pablo Neira Ayuso
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Pablo Neira Ayuso @ 2023-03-23 16:58 UTC (permalink / raw)
  To: netfilter-devel; +Cc: jeremy, fw

In order to be able to set ct and meta marks to values derived from
payload expressions, we need to relax the requirement that the type of
the statement argument must match that of the statement key.  Instead,
we require that the base-type of the argument is integer and that the
argument is small enough to fit.

Moreover, swap expression byteorder before to make it compatible with
the statement byteorder, to ensure rulesets are portable.

 # nft --debug=netlink add rule ip t c 'meta mark set ip saddr'
 ip t c
  [ payload load 4b @ network header + 12 => reg 1 ]
  [ byteorder reg 1 = ntoh(reg 1, 4, 4) ] <----------- byteorder swap
  [ meta set mark with reg 1 ]

Based on original work from Jeremy Sowden.

The following patches are required for this to work:

evaluate: get length from statement instead of lhs expression
evaluate: don't eval unary arguments
evaluate: support shifts larger than the width of the left operand
netlink_delinearize: correct type and byte-order of shifts
evaluate: insert byte-order conversions for expressions between 9 and 15 bits

Add one testcase for tests/py.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 src/evaluate.c             | 13 +++++++++++--
 tests/py/ip/meta.t         |  2 ++
 tests/py/ip/meta.t.json    | 20 ++++++++++++++++++++
 tests/py/ip/meta.t.payload |  8 ++++++++
 4 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/src/evaluate.c b/src/evaluate.c
index e0263f97dcf8..33b1aad72f66 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2743,13 +2743,22 @@ static int __stmt_evaluate_arg(struct eval_ctx *ctx, struct stmt *stmt,
 					 "expression has type %s with length %d",
 					 dtype->desc, (*expr)->dtype->desc,
 					 (*expr)->len);
-	else if ((*expr)->dtype->type != TYPE_INTEGER &&
-		 !datatype_equal((*expr)->dtype, dtype))
+
+	if ((dtype->type == TYPE_MARK &&
+	     !datatype_equal(datatype_basetype(dtype), datatype_basetype((*expr)->dtype))) ||
+	    (dtype->type != TYPE_MARK &&
+	     (*expr)->dtype->type != TYPE_INTEGER &&
+	     !datatype_equal((*expr)->dtype, dtype)))
 		return stmt_binary_error(ctx, *expr, stmt,		/* verdict vs invalid? */
 					 "datatype mismatch: expected %s, "
 					 "expression has type %s",
 					 dtype->desc, (*expr)->dtype->desc);
 
+	if (dtype->type == TYPE_MARK &&
+	    datatype_equal(datatype_basetype(dtype), datatype_basetype((*expr)->dtype)) &&
+	    !expr_is_constant(*expr))
+		return byteorder_conversion(ctx, expr, byteorder);
+
 	/* we are setting a value, we can't use a set */
 	switch ((*expr)->etype) {
 	case EXPR_SET:
diff --git a/tests/py/ip/meta.t b/tests/py/ip/meta.t
index 5a05923a1ce1..85eaf54ce723 100644
--- a/tests/py/ip/meta.t
+++ b/tests/py/ip/meta.t
@@ -15,3 +15,5 @@ meta obrname "br0";fail
 
 meta sdif "lo" accept;ok
 meta sdifname != "vrf1" accept;ok
+
+meta mark set ip dscp;ok
diff --git a/tests/py/ip/meta.t.json b/tests/py/ip/meta.t.json
index 3df31ce381fc..a93d7e781ce1 100644
--- a/tests/py/ip/meta.t.json
+++ b/tests/py/ip/meta.t.json
@@ -156,3 +156,23 @@
         }
     }
 ]
+
+# meta mark set ip dscp
+[
+    {
+        "mangle": {
+            "key": {
+                "meta": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "payload": {
+                    "field": "dscp",
+                    "protocol": "ip"
+                }
+            }
+        }
+    }
+]
+
diff --git a/tests/py/ip/meta.t.payload b/tests/py/ip/meta.t.payload
index afde5cc13ac5..1aa8d003b1d4 100644
--- a/tests/py/ip/meta.t.payload
+++ b/tests/py/ip/meta.t.payload
@@ -51,3 +51,11 @@ ip test-ip4 input
   [ cmp eq reg 1 0x00000011 ]
   [ payload load 2b @ transport header + 2 => reg 1 ]
   [ cmp eq reg 1 0x00004300 ]
+
+# meta mark set ip dscp
+ip test-ip4 input
+  [ payload load 1b @ network header + 1 => reg 1 ]
+  [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+  [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
+  [ meta set mark with reg 1 ]
+
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH nft,v3 05/12] evaluate: set up integer type to shift expression
  2023-03-23 16:58 [PATCH nft,v3 00/12] mark statement support for non-constant expression Pablo Neira Ayuso
                   ` (3 preceding siblings ...)
  2023-03-23 16:58 ` [PATCH nft,v3 04/12] evaluate: relax type-checking for integer arguments in mark statements Pablo Neira Ayuso
@ 2023-03-23 16:58 ` Pablo Neira Ayuso
  2023-03-28  8:21   ` Pablo Neira Ayuso
  2023-03-23 16:58 ` [PATCH nft,v3 06/12] evaluate: honor statement length in integer evaluation Pablo Neira Ayuso
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 15+ messages in thread
From: Pablo Neira Ayuso @ 2023-03-23 16:58 UTC (permalink / raw)
  To: netfilter-devel; +Cc: jeremy, fw

Otherwise expr_evaluate_value() fails with invalid datatype:

 # nft --debug=netlink add rule ip x y 'ct mark set ip dscp & 0x0f << 1'
 BUG: invalid basetype invalid
 nft: evaluate.c:440: expr_evaluate_value: Assertion `0' failed.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 src/evaluate.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/evaluate.c b/src/evaluate.c
index 33b1aad72f66..1ee9bdc5aa47 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1308,6 +1308,7 @@ static int expr_evaluate_shift(struct eval_ctx *ctx, struct expr **expr)
 	if (byteorder_conversion(ctx, &op->right, BYTEORDER_HOST_ENDIAN) < 0)
 		return -1;
 
+	op->dtype     = &integer_type;
 	op->byteorder = BYTEORDER_HOST_ENDIAN;
 	op->len	      = max_shift_len;
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH nft,v3 06/12] evaluate: honor statement length in integer evaluation
  2023-03-23 16:58 [PATCH nft,v3 00/12] mark statement support for non-constant expression Pablo Neira Ayuso
                   ` (4 preceding siblings ...)
  2023-03-23 16:58 ` [PATCH nft,v3 05/12] evaluate: set up integer type to shift expression Pablo Neira Ayuso
@ 2023-03-23 16:58 ` Pablo Neira Ayuso
  2023-03-23 16:58 ` [PATCH nft,v3 07/12] evaluate: honor statement length in bitwise evaluation Pablo Neira Ayuso
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Pablo Neira Ayuso @ 2023-03-23 16:58 UTC (permalink / raw)
  To: netfilter-devel; +Cc: jeremy, fw

Otherwise, bogus error is reported:

 # nft --debug=netlink add rule ip x y 'ct mark set ip dscp & 0x0f << 1 | 0xff000000'
 Error: Value 4278190080 exceeds valid range 0-63
 add rule ip x y ct mark set ip dscp & 0x0f << 1 | 0xff000000
                                                   ^^^^^^^^^^

Use the statement length as the maximum value in the mark statement
expression.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 src/evaluate.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/evaluate.c b/src/evaluate.c
index 1ee9bdc5aa47..7c3b5b4ddddb 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -389,6 +389,7 @@ static int expr_evaluate_integer(struct eval_ctx *ctx, struct expr **exprp)
 {
 	struct expr *expr = *exprp;
 	char *valstr, *rangestr;
+	uint32_t masklen;
 	mpz_t mask;
 
 	if (ctx->ectx.maxval > 0 &&
@@ -401,7 +402,12 @@ static int expr_evaluate_integer(struct eval_ctx *ctx, struct expr **exprp)
 		return -1;
 	}
 
-	mpz_init_bitmask(mask, ctx->ectx.len);
+	if (ctx->stmt_len > ctx->ectx.len)
+		masklen = ctx->stmt_len;
+	else
+		masklen = ctx->ectx.len;
+
+	mpz_init_bitmask(mask, masklen);
 	if (mpz_cmp(expr->value, mask) > 0) {
 		valstr = mpz_get_str(NULL, 10, expr->value);
 		rangestr = mpz_get_str(NULL, 10, mask);
@@ -414,7 +420,7 @@ static int expr_evaluate_integer(struct eval_ctx *ctx, struct expr **exprp)
 		return -1;
 	}
 	expr->byteorder = ctx->ectx.byteorder;
-	expr->len = ctx->ectx.len;
+	expr->len = masklen;
 	mpz_clear(mask);
 	return 0;
 }
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH nft,v3 07/12] evaluate: honor statement length in bitwise evaluation
  2023-03-23 16:58 [PATCH nft,v3 00/12] mark statement support for non-constant expression Pablo Neira Ayuso
                   ` (5 preceding siblings ...)
  2023-03-23 16:58 ` [PATCH nft,v3 06/12] evaluate: honor statement length in integer evaluation Pablo Neira Ayuso
@ 2023-03-23 16:58 ` Pablo Neira Ayuso
  2023-03-28  8:22   ` Pablo Neira Ayuso
  2023-03-23 16:58 ` [PATCH nft,v3 08/12] netlink_delinerize: incorrect byteorder in mark statement listing Pablo Neira Ayuso
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 15+ messages in thread
From: Pablo Neira Ayuso @ 2023-03-23 16:58 UTC (permalink / raw)
  To: netfilter-devel; +Cc: jeremy, fw

Get length from statement, instead infering it from the expression that
is used to set the value. In the particular case of {ct|meta} mark, this
is 32 bits.

Otherwise, bytecode generation is not correct:

 # nft -c --debug=netlink 'add rule ip6 x y ct mark set ip6 dscp << 2 | 0x10'
  [ payload load 2b @ network header + 0 => reg 1 ]
  [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
  [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
  [ byteorder reg 1 = ntoh(reg 1, 2, 1) ]
  [ bitwise reg 1 = ( reg 1 << 0x00000002 ) ]
  [ bitwise reg 1 = ( reg 1 & 0x00000fef ) ^ 0x00000010 ]    <--- incorrect!
  [ ct set mark with reg 1 ]

the previous bitwise shift already upgraded to 32-bits (not visible from
the netlink debug output above).

After this patch, the last | 0x10 uses 32-bits:

 [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]

note that mask 0xffffffef is used instead of 0x00000fef.

Patch ("evaluate: support shifts larger than the width of the left operand")
provides the statement length through eval context. Use it to evaluate the
bitwise expression accordingly, otherwise bytecode is incorrect:

 # nft --debug=netlink add rule ip x y 'ct mark set ip dscp & 0x0f << 1 | 0xff000000'
 ip x y
  [ 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 & 0x1e000000 ) ^ 0x000000ff ]  <-- incorrect byteorder for OR
  [ byteorder reg 1 = ntoh(reg 1, 4, 4) ]		   <-- no needed for single ip dscp byte
  [ ct set mark with reg 1 ]

Correct bytecode:

 # nft --debug=netlink add rule ip x y 'ct mark set ip dscp & 0x0f << 1 | 0xff000000
 ip x y
  [ 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 & 0x0000001e ) ^ 0xff000000 ]
  [ ct set mark with reg 1 ]

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 src/evaluate.c | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/src/evaluate.c b/src/evaluate.c
index 7c3b5b4ddddb..1db990903810 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1326,13 +1326,32 @@ static int expr_evaluate_shift(struct eval_ctx *ctx, struct expr **expr)
 static int expr_evaluate_bitwise(struct eval_ctx *ctx, struct expr **expr)
 {
 	struct expr *op = *expr, *left = op->left;
+	const struct datatype *dtype;
+	unsigned int max_len;
+	int byteorder;
+
+	if (ctx->stmt_len > left->len) {
+		max_len = ctx->stmt_len;
+		byteorder = BYTEORDER_HOST_ENDIAN;
+		dtype = &integer_type;
+
+		/* Both sides need to be in host byte order */
+		if (byteorder_conversion(ctx, &op->left, BYTEORDER_HOST_ENDIAN) < 0)
+			return -1;
+
+		left = op->left;
+	} else {
+		max_len = left->len;
+		byteorder = left->byteorder;
+		dtype = left->dtype;
+	}
 
-	if (byteorder_conversion(ctx, &op->right, left->byteorder) < 0)
+	if (byteorder_conversion(ctx, &op->right, byteorder) < 0)
 		return -1;
 
-	op->dtype     = left->dtype;
-	op->byteorder = left->byteorder;
-	op->len	      = left->len;
+	op->dtype     = dtype;
+	op->byteorder = byteorder;
+	op->len	      = max_len;
 
 	if (expr_is_constant(left))
 		return constant_binop_simplify(ctx, expr);
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH nft,v3 08/12] netlink_delinerize: incorrect byteorder in mark statement listing
  2023-03-23 16:58 [PATCH nft,v3 00/12] mark statement support for non-constant expression Pablo Neira Ayuso
                   ` (6 preceding siblings ...)
  2023-03-23 16:58 ` [PATCH nft,v3 07/12] evaluate: honor statement length in bitwise evaluation Pablo Neira Ayuso
@ 2023-03-23 16:58 ` Pablo Neira Ayuso
  2023-03-23 16:58 ` [PATCH nft,v3 09/12] tests: py: add test-cases for ct and packet mark payload expressions Pablo Neira Ayuso
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Pablo Neira Ayuso @ 2023-03-23 16:58 UTC (permalink / raw)
  To: netfilter-devel; +Cc: jeremy, fw

When using ip dscp in combination with bitwise operation:

 # nft --debug=netlink add rule ip x y 'ct mark set ip dscp | 0x4'
 ip x y
   [ 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 & 0xfffffffb ) ^ 0x00000004 ]
   [ ct set mark with reg 1 ]

the listing is showing in the incorrect byteorder:

 # nft list ruleset
 table ip x {
        chain y {
		ct mark set ip dscp | 0x4000000
	}
 }

handle and and or operations in host byteorder.

The following command:

 # nft --debug=netlink add rule ip6 x y 'ct mark set ip6 dscp | 0x4'
 ip6 x y
   [ payload load 2b @ network header + 0 => reg 1 ]
   [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
   [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
   [ byteorder reg 1 = ntoh(reg 1, 2, 1) ]
   [ bitwise reg 1 = ( reg 1 & 0xfffffffb ) ^ 0x00000004 ]
   [ ct set mark with reg 1 ]

works fine (without requiring this patch) because there is an explicit
byteorder expression.

However, ip dscp takes only 1-byte, so it does not require the byteorder
expression. Use host byteorder if the rhs of bitwise AND OR is larger
than lhs payload expression and such expression is equal or less than
1-byte.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 src/netlink_delinearize.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 4dc28ed8e651..7da8e68726cd 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -2784,8 +2784,13 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
 				      BYTEORDER_HOST_ENDIAN);
 			break;
 		case OP_AND:
-			expr_set_type(expr->right, expr->left->dtype,
-				      expr->left->byteorder);
+			if (expr->right->len > expr->left->len) {
+				expr_set_type(expr->right, expr->left->dtype,
+					      BYTEORDER_HOST_ENDIAN);
+			} else {
+				expr_set_type(expr->right, expr->left->dtype,
+					      expr->left->byteorder);
+			}
 
 			/* Do not process OP_AND in ordinary rule context.
 			 *
@@ -2805,8 +2810,13 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
 			}
 			break;
 		default:
-			expr_set_type(expr->right, expr->left->dtype,
-				      expr->left->byteorder);
+			if (expr->right->len > expr->left->len) {
+				expr_set_type(expr->right, expr->left->dtype,
+					      BYTEORDER_HOST_ENDIAN);
+			} else {
+				expr_set_type(expr->right, expr->left->dtype,
+					      expr->left->byteorder);
+			}
 		}
 		expr_postprocess(ctx, &expr->right);
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH nft,v3 09/12] tests: py: add test-cases for ct and packet mark payload expressions
  2023-03-23 16:58 [PATCH nft,v3 00/12] mark statement support for non-constant expression Pablo Neira Ayuso
                   ` (7 preceding siblings ...)
  2023-03-23 16:58 ` [PATCH nft,v3 08/12] netlink_delinerize: incorrect byteorder in mark statement listing Pablo Neira Ayuso
@ 2023-03-23 16:58 ` Pablo Neira Ayuso
  2023-03-23 16:58 ` [PATCH nft,v3 10/12] tests: shell: rename and move bitwise test-cases Pablo Neira Ayuso
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Pablo Neira Ayuso @ 2023-03-23 16:58 UTC (permalink / raw)
  To: netfilter-devel; +Cc: jeremy, fw

From: Jeremy Sowden <jeremy@azazel.net>

Add new test-cases to verify that defining a rule that sets the ct or
packet mark to a value derived from a payload works correctly.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 tests/py/ip/ct.t            |   2 +
 tests/py/ip/ct.t.json       |  58 ++++++++++
 tests/py/ip/ct.t.payload    |  18 +++
 tests/py/ip/meta.t          |   3 +
 tests/py/ip/meta.t.json     |  58 ++++++++++
 tests/py/ip/meta.t.payload  |  17 +++
 tests/py/ip6/ct.t           |   6 +
 tests/py/ip6/ct.t.json      | 221 ++++++++++++++++++++++++++++++++++++
 tests/py/ip6/ct.t.payload   |  19 ++++
 tests/py/ip6/meta.t         |   3 +
 tests/py/ip6/meta.t.json    |  58 ++++++++++
 tests/py/ip6/meta.t.payload |  20 ++++
 12 files changed, 483 insertions(+)
 create mode 100644 tests/py/ip6/ct.t
 create mode 100644 tests/py/ip6/ct.t.json
 create mode 100644 tests/py/ip6/ct.t.payload

diff --git a/tests/py/ip/ct.t b/tests/py/ip/ct.t
index a387863e0d8e..eea9fd4e0562 100644
--- a/tests/py/ip/ct.t
+++ b/tests/py/ip/ct.t
@@ -28,3 +28,5 @@ meta mark set ct original saddr . meta mark map { 1.1.1.1 . 0x00000014 : 0x00000
 meta mark set ct original ip saddr . meta mark map { 1.1.1.1 . 0x00000014 : 0x0000001e };ok
 ct original saddr . meta mark { 1.1.1.1 . 0x00000014 };fail
 ct original ip saddr . meta mark { 1.1.1.1 . 0x00000014 };ok
+ct mark set ip dscp << 2 | 0x10;ok
+ct mark set ip dscp << 26 | 0x10;ok
diff --git a/tests/py/ip/ct.t.json b/tests/py/ip/ct.t.json
index 3288413f8f3f..e739b5f65bfe 100644
--- a/tests/py/ip/ct.t.json
+++ b/tests/py/ip/ct.t.json
@@ -325,3 +325,61 @@
         }
     }
 ]
+
+# ct mark set ip dscp << 2 | 0x10
+[
+    {
+        "mangle": {
+            "key": {
+                "ct": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "<<": [
+                            {
+                                "payload": {
+                                    "field": "dscp",
+                                    "protocol": "ip"
+                                }
+                            },
+                            2
+                        ]
+                    },
+                    16
+                ]
+            }
+        }
+    }
+]
+
+# ct mark set ip dscp << 26 | 0x10
+[
+    {
+        "mangle": {
+            "key": {
+                "ct": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "<<": [
+                            {
+                                "payload": {
+                                    "field": "dscp",
+                                    "protocol": "ip"
+                                }
+                            },
+                            26
+                        ]
+                    },
+                    16
+                ]
+            }
+        }
+    }
+]
diff --git a/tests/py/ip/ct.t.payload b/tests/py/ip/ct.t.payload
index 49f06a8401f5..45dba3390940 100644
--- a/tests/py/ip/ct.t.payload
+++ b/tests/py/ip/ct.t.payload
@@ -84,3 +84,21 @@ ip
   [ ct load src_ip => reg 1 , dir original ]
   [ meta load mark => reg 9 ]
   [ lookup reg 1 set __set%d ]
+
+# ct mark set ip dscp << 2 | 0x10
+ip test-ip4 output
+  [ 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 << 0x00000002 ) ]
+  [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
+  [ ct set mark with reg 1 ]
+
+# ct mark set ip dscp << 26 | 0x10
+ip
+  [ 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 << 0x0000001a ) ]
+  [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
+  [ ct set mark with reg 1 ]
diff --git a/tests/py/ip/meta.t b/tests/py/ip/meta.t
index 85eaf54ce723..a88a6145559d 100644
--- a/tests/py/ip/meta.t
+++ b/tests/py/ip/meta.t
@@ -17,3 +17,6 @@ meta sdif "lo" accept;ok
 meta sdifname != "vrf1" accept;ok
 
 meta mark set ip dscp;ok
+
+meta mark set ip dscp << 2 | 0x10;ok
+meta mark set ip dscp << 26 | 0x10;ok
diff --git a/tests/py/ip/meta.t.json b/tests/py/ip/meta.t.json
index a93d7e781ce1..25936dba98b9 100644
--- a/tests/py/ip/meta.t.json
+++ b/tests/py/ip/meta.t.json
@@ -176,3 +176,61 @@
     }
 ]
 
+# meta mark set ip dscp << 2 | 0x10
+[
+    {
+        "mangle": {
+            "key": {
+                "meta": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "<<": [
+                            {
+                                "payload": {
+                                    "field": "dscp",
+                                    "protocol": "ip"
+                                }
+                            },
+                            2
+                        ]
+                    },
+                    16
+                ]
+            }
+        }
+    }
+]
+
+
+# meta mark set ip dscp << 26 | 0x10
+[
+    {
+        "mangle": {
+            "key": {
+                "meta": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "<<": [
+                            {
+                                "payload": {
+                                    "field": "dscp",
+                                    "protocol": "ip"
+                                }
+                            },
+                            26
+                        ]
+                    },
+                    16
+                ]
+            }
+        }
+    }
+]
diff --git a/tests/py/ip/meta.t.payload b/tests/py/ip/meta.t.payload
index 1aa8d003b1d4..880ac5d6c707 100644
--- a/tests/py/ip/meta.t.payload
+++ b/tests/py/ip/meta.t.payload
@@ -59,3 +59,20 @@ ip test-ip4 input
   [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
   [ meta set mark with reg 1 ]
 
+# meta mark set ip dscp << 2 | 0x10
+ip test-ip4 input
+  [ 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 << 0x00000002 ) ]
+  [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
+  [ meta set mark with reg 1 ]
+
+# meta mark set ip dscp << 26 | 0x10
+ip
+  [ 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 << 0x0000001a ) ]
+  [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
+  [ meta set mark with reg 1 ]
diff --git a/tests/py/ip6/ct.t b/tests/py/ip6/ct.t
new file mode 100644
index 000000000000..da69b7a910e4
--- /dev/null
+++ b/tests/py/ip6/ct.t
@@ -0,0 +1,6 @@
+:output;type filter hook output priority 0
+
+*ip6;test-ip6;output
+
+ct mark set ip6 dscp << 2 | 0x10;ok
+ct mark set ip6 dscp << 26 | 0x10;ok
diff --git a/tests/py/ip6/ct.t.json b/tests/py/ip6/ct.t.json
new file mode 100644
index 000000000000..7579a65ef791
--- /dev/null
+++ b/tests/py/ip6/ct.t.json
@@ -0,0 +1,221 @@
+# ct mark set ip6 dscp lshift 2 or 0x10
+[
+    {
+        "mangle": {
+            "key": {
+                "ct": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "<<": [
+                            {
+                                "payload": {
+                                    "field": "dscp",
+                                    "protocol": "ip6"
+                                }
+                            },
+                            2
+                        ]
+                    },
+                    16
+                ]
+            }
+        }
+    }
+]
+
+# ct mark set ip6 dscp lshift 26 or 0x10
+[
+    {
+        "mangle": {
+            "key": {
+                "ct": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "<<": [
+                            {
+                                "payload": {
+                                    "field": "dscp",
+                                    "protocol": "ip6"
+                                }
+                            },
+                            26
+                        ]
+                    },
+                    16
+                ]
+            }
+        }
+    }
+]
+
+# ct mark set ip6 dscp << 2 | 0x10
+[
+    {
+        "mangle": {
+            "key": {
+                "ct": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "<<": [
+                            {
+                                "payload": {
+                                    "field": "dscp",
+                                    "protocol": "ip6"
+                                }
+                            },
+                            2
+                        ]
+                    },
+                    16
+                ]
+            }
+        }
+    }
+]
+
+# ct mark set ip6 dscp << 26 | 0x10
+[
+    {
+        "mangle": {
+            "key": {
+                "ct": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "<<": [
+                            {
+                                "payload": {
+                                    "field": "dscp",
+                                    "protocol": "ip6"
+                                }
+                            },
+                            26
+                        ]
+                    },
+                    16
+                ]
+            }
+        }
+    }
+]
+
+# ct mark set ip6 dscp | 0x04
+[
+    {
+        "mangle": {
+            "key": {
+                "ct": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "payload": {
+                            "field": "dscp",
+                            "protocol": "ip6"
+                        }
+                    },
+                    4
+                ]
+            }
+        }
+    }
+]
+
+# ct mark set ip6 dscp | 0xff000000
+[
+    {
+        "mangle": {
+            "key": {
+                "ct": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "payload": {
+                            "field": "dscp",
+                            "protocol": "ip6"
+                        }
+                    },
+                    4278190080
+                ]
+            }
+        }
+    }
+]
+
+# ct mark set ip6 dscp << 2 | 0x10
+[
+    {
+        "mangle": {
+            "key": {
+                "ct": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "<<": [
+                            {
+                                "payload": {
+                                    "field": "dscp",
+                                    "protocol": "ip6"
+                                }
+                            },
+                            2
+                        ]
+                    },
+                    16
+                ]
+            }
+        }
+    }
+]
+
+# ct mark set ip6 dscp << 26 | 0x10
+[
+    {
+        "mangle": {
+            "key": {
+                "ct": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "<<": [
+                            {
+                                "payload": {
+                                    "field": "dscp",
+                                    "protocol": "ip6"
+                                }
+                            },
+                            26
+                        ]
+                    },
+                    16
+                ]
+            }
+        }
+    }
+]
diff --git a/tests/py/ip6/ct.t.payload b/tests/py/ip6/ct.t.payload
new file mode 100644
index 000000000000..00768dae79f1
--- /dev/null
+++ b/tests/py/ip6/ct.t.payload
@@ -0,0 +1,19 @@
+# ct mark set ip6 dscp << 2 | 0x10
+ip6 test-ip6 output
+  [ payload load 2b @ network header + 0 => reg 1 ]
+  [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+  [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+  [ byteorder reg 1 = ntoh(reg 1, 2, 1) ]
+  [ bitwise reg 1 = ( reg 1 << 0x00000002 ) ]
+  [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
+  [ ct set mark with reg 1 ]
+
+# ct mark set ip6 dscp << 26 | 0x10
+ip6 test-ip6 output
+  [ payload load 2b @ network header + 0 => reg 1 ]
+  [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+  [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+  [ byteorder reg 1 = ntoh(reg 1, 2, 1) ]
+  [ bitwise reg 1 = ( reg 1 << 0x0000001a ) ]
+  [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
+  [ ct set mark with reg 1 ]
diff --git a/tests/py/ip6/meta.t b/tests/py/ip6/meta.t
index 471e14811975..c177b0815176 100644
--- a/tests/py/ip6/meta.t
+++ b/tests/py/ip6/meta.t
@@ -14,3 +14,6 @@ meta protocol ip6 udp dport 67;ok;udp dport 67
 
 meta sdif "lo" accept;ok
 meta sdifname != "vrf1" accept;ok
+
+meta mark set ip6 dscp << 2 | 0x10;ok
+meta mark set ip6 dscp << 26 | 0x10;ok
diff --git a/tests/py/ip6/meta.t.json b/tests/py/ip6/meta.t.json
index 351320d70f7c..5bd8b07bbc90 100644
--- a/tests/py/ip6/meta.t.json
+++ b/tests/py/ip6/meta.t.json
@@ -194,3 +194,61 @@
         }
     }
 ]
+
+# meta mark set ip6 dscp lshift 2 or 0x10
+[
+    {
+        "mangle": {
+            "key": {
+                "meta": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "<<": [
+                            {
+                                "payload": {
+                                    "field": "dscp",
+                                    "protocol": "ip6"
+                                }
+                            },
+                            2
+                        ]
+                    },
+                    16
+                ]
+            }
+        }
+    }
+]
+
+# meta mark set ip6 dscp lshift 26 or 0x10
+[
+    {
+        "mangle": {
+            "key": {
+                "meta": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "<<": [
+                            {
+                                "payload": {
+                                    "field": "dscp",
+                                    "protocol": "ip6"
+                                }
+                            },
+                            26
+                        ]
+                    },
+                    16
+                ]
+            }
+        }
+    }
+]
diff --git a/tests/py/ip6/meta.t.payload b/tests/py/ip6/meta.t.payload
index 0e3db6ba07f9..f0507dc47073 100644
--- a/tests/py/ip6/meta.t.payload
+++ b/tests/py/ip6/meta.t.payload
@@ -60,3 +60,23 @@ ip6 test-ip6 input
   [ cmp eq reg 1 0x00000011 ]
   [ payload load 2b @ transport header + 2 => reg 1 ]
   [ cmp eq reg 1 0x00004300 ]
+
+# meta mark set ip6 dscp << 2 | 0x10
+ip6 test-ip6 input
+  [ payload load 2b @ network header + 0 => reg 1 ]
+  [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+  [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+  [ byteorder reg 1 = ntoh(reg 1, 2, 1) ]
+  [ bitwise reg 1 = ( reg 1 << 0x00000002 ) ]
+  [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
+  [ meta set mark with reg 1 ]
+
+# meta mark set ip6 dscp << 26 | 0x10
+ip6 test-ip6 input
+  [ payload load 2b @ network header + 0 => reg 1 ]
+  [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+  [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+  [ byteorder reg 1 = ntoh(reg 1, 2, 1) ]
+  [ bitwise reg 1 = ( reg 1 << 0x0000001a ) ]
+  [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
+  [ meta set mark with reg 1 ]
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH nft,v3 10/12] tests: shell: rename and move bitwise test-cases
  2023-03-23 16:58 [PATCH nft,v3 00/12] mark statement support for non-constant expression Pablo Neira Ayuso
                   ` (8 preceding siblings ...)
  2023-03-23 16:58 ` [PATCH nft,v3 09/12] tests: py: add test-cases for ct and packet mark payload expressions Pablo Neira Ayuso
@ 2023-03-23 16:58 ` Pablo Neira Ayuso
  2023-03-23 16:58 ` [PATCH nft,v3 11/12] tests: shell: add test-cases for ct and packet mark payload expressions Pablo Neira Ayuso
  2023-03-23 16:58 ` [PATCH nft,v3 12/12] tests: py: extend test-cases for mark statements with bitwise expressions Pablo Neira Ayuso
  11 siblings, 0 replies; 15+ messages in thread
From: Pablo Neira Ayuso @ 2023-03-23 16:58 UTC (permalink / raw)
  To: netfilter-devel; +Cc: jeremy, fw

From: Jeremy Sowden <jeremy@azazel.net>

The `0040mark_shift_?` tests are testing not just shifts, but binops
more generally, so name them accordingly.

Move them to a new folder specifically for bitwise operations.

Change the priorities of the chains to match the type.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 .../{chains/0040mark_shift_0 => bitwise/0040mark_binop_0}       | 2 +-
 .../{chains/0040mark_shift_1 => bitwise/0040mark_binop_1}       | 2 +-
 .../0040mark_shift_0.nft => bitwise/dumps/0040mark_binop_0.nft} | 2 +-
 .../0040mark_shift_1.nft => bitwise/dumps/0040mark_binop_1.nft} | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)
 rename tests/shell/testcases/{chains/0040mark_shift_0 => bitwise/0040mark_binop_0} (68%)
 rename tests/shell/testcases/{chains/0040mark_shift_1 => bitwise/0040mark_binop_1} (70%)
 rename tests/shell/testcases/{chains/dumps/0040mark_shift_0.nft => bitwise/dumps/0040mark_binop_0.nft} (58%)
 rename tests/shell/testcases/{chains/dumps/0040mark_shift_1.nft => bitwise/dumps/0040mark_binop_1.nft} (64%)

diff --git a/tests/shell/testcases/chains/0040mark_shift_0 b/tests/shell/testcases/bitwise/0040mark_binop_0
similarity index 68%
rename from tests/shell/testcases/chains/0040mark_shift_0
rename to tests/shell/testcases/bitwise/0040mark_binop_0
index ef3dccfa049a..4280e33ac45a 100755
--- a/tests/shell/testcases/chains/0040mark_shift_0
+++ b/tests/shell/testcases/bitwise/0040mark_binop_0
@@ -4,7 +4,7 @@ set -e
 
 RULESET="
   add table t
-  add chain t c { type filter hook output priority mangle; }
+  add chain t c { type filter hook output priority filter; }
   add rule t c oif lo ct mark set (meta mark | 0x10) << 8
 "
 
diff --git a/tests/shell/testcases/chains/0040mark_shift_1 b/tests/shell/testcases/bitwise/0040mark_binop_1
similarity index 70%
rename from tests/shell/testcases/chains/0040mark_shift_1
rename to tests/shell/testcases/bitwise/0040mark_binop_1
index b609f5ef10ad..7e71f3eb43a8 100755
--- a/tests/shell/testcases/chains/0040mark_shift_1
+++ b/tests/shell/testcases/bitwise/0040mark_binop_1
@@ -4,7 +4,7 @@ set -e
 
 RULESET="
   add table t
-  add chain t c { type filter hook input priority mangle; }
+  add chain t c { type filter hook input priority filter; }
   add rule t c iif lo ct mark & 0xff 0x10 meta mark set ct mark >> 8
 "
 
diff --git a/tests/shell/testcases/chains/dumps/0040mark_shift_0.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_0.nft
similarity index 58%
rename from tests/shell/testcases/chains/dumps/0040mark_shift_0.nft
rename to tests/shell/testcases/bitwise/dumps/0040mark_binop_0.nft
index 52d59d2c6da4..fc0a600a4dbe 100644
--- a/tests/shell/testcases/chains/dumps/0040mark_shift_0.nft
+++ b/tests/shell/testcases/bitwise/dumps/0040mark_binop_0.nft
@@ -1,6 +1,6 @@
 table ip t {
 	chain c {
-		type filter hook output priority mangle; policy accept;
+		type filter hook output priority filter; policy accept;
 		oif "lo" ct mark set (meta mark | 0x00000010) << 8
 	}
 }
diff --git a/tests/shell/testcases/chains/dumps/0040mark_shift_1.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_1.nft
similarity index 64%
rename from tests/shell/testcases/chains/dumps/0040mark_shift_1.nft
rename to tests/shell/testcases/bitwise/dumps/0040mark_binop_1.nft
index 56ec8dc766ca..dbaacefb93c7 100644
--- a/tests/shell/testcases/chains/dumps/0040mark_shift_1.nft
+++ b/tests/shell/testcases/bitwise/dumps/0040mark_binop_1.nft
@@ -1,6 +1,6 @@
 table ip t {
 	chain c {
-		type filter hook input priority mangle; policy accept;
+		type filter hook input priority filter; policy accept;
 		iif "lo" ct mark & 0x000000ff == 0x00000010 meta mark set ct mark >> 8
 	}
 }
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH nft,v3 11/12] tests: shell: add test-cases for ct and packet mark payload expressions
  2023-03-23 16:58 [PATCH nft,v3 00/12] mark statement support for non-constant expression Pablo Neira Ayuso
                   ` (9 preceding siblings ...)
  2023-03-23 16:58 ` [PATCH nft,v3 10/12] tests: shell: rename and move bitwise test-cases Pablo Neira Ayuso
@ 2023-03-23 16:58 ` Pablo Neira Ayuso
  2023-03-23 16:58 ` [PATCH nft,v3 12/12] tests: py: extend test-cases for mark statements with bitwise expressions Pablo Neira Ayuso
  11 siblings, 0 replies; 15+ messages in thread
From: Pablo Neira Ayuso @ 2023-03-23 16:58 UTC (permalink / raw)
  To: netfilter-devel; +Cc: jeremy, fw

From: Jeremy Sowden <jeremy@azazel.net>

Add new test-cases to verify that defining a rule that sets the ct or
packet mark to a value derived from a payload works correctly.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 tests/shell/testcases/bitwise/0040mark_binop_2        | 11 +++++++++++
 tests/shell/testcases/bitwise/0040mark_binop_3        | 11 +++++++++++
 tests/shell/testcases/bitwise/0040mark_binop_4        | 11 +++++++++++
 tests/shell/testcases/bitwise/0040mark_binop_5        | 11 +++++++++++
 tests/shell/testcases/bitwise/0040mark_binop_6        | 11 +++++++++++
 tests/shell/testcases/bitwise/0040mark_binop_7        | 11 +++++++++++
 tests/shell/testcases/bitwise/0040mark_binop_8        | 11 +++++++++++
 tests/shell/testcases/bitwise/0040mark_binop_9        | 11 +++++++++++
 .../testcases/bitwise/dumps/0040mark_binop_2.nft      |  6 ++++++
 .../testcases/bitwise/dumps/0040mark_binop_3.nft      |  6 ++++++
 .../testcases/bitwise/dumps/0040mark_binop_4.nft      |  6 ++++++
 .../testcases/bitwise/dumps/0040mark_binop_5.nft      |  6 ++++++
 .../testcases/bitwise/dumps/0040mark_binop_6.nft      |  6 ++++++
 .../testcases/bitwise/dumps/0040mark_binop_7.nft      |  6 ++++++
 .../testcases/bitwise/dumps/0040mark_binop_8.nft      |  6 ++++++
 .../testcases/bitwise/dumps/0040mark_binop_9.nft      |  6 ++++++
 16 files changed, 136 insertions(+)
 create mode 100755 tests/shell/testcases/bitwise/0040mark_binop_2
 create mode 100755 tests/shell/testcases/bitwise/0040mark_binop_3
 create mode 100755 tests/shell/testcases/bitwise/0040mark_binop_4
 create mode 100755 tests/shell/testcases/bitwise/0040mark_binop_5
 create mode 100755 tests/shell/testcases/bitwise/0040mark_binop_6
 create mode 100755 tests/shell/testcases/bitwise/0040mark_binop_7
 create mode 100755 tests/shell/testcases/bitwise/0040mark_binop_8
 create mode 100755 tests/shell/testcases/bitwise/0040mark_binop_9
 create mode 100644 tests/shell/testcases/bitwise/dumps/0040mark_binop_2.nft
 create mode 100644 tests/shell/testcases/bitwise/dumps/0040mark_binop_3.nft
 create mode 100644 tests/shell/testcases/bitwise/dumps/0040mark_binop_4.nft
 create mode 100644 tests/shell/testcases/bitwise/dumps/0040mark_binop_5.nft
 create mode 100644 tests/shell/testcases/bitwise/dumps/0040mark_binop_6.nft
 create mode 100644 tests/shell/testcases/bitwise/dumps/0040mark_binop_7.nft
 create mode 100644 tests/shell/testcases/bitwise/dumps/0040mark_binop_8.nft
 create mode 100644 tests/shell/testcases/bitwise/dumps/0040mark_binop_9.nft

diff --git a/tests/shell/testcases/bitwise/0040mark_binop_2 b/tests/shell/testcases/bitwise/0040mark_binop_2
new file mode 100755
index 000000000000..94ebe976c987
--- /dev/null
+++ b/tests/shell/testcases/bitwise/0040mark_binop_2
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+set -e
+
+RULESET="
+  add table t
+  add chain t c { type filter hook output priority filter; }
+  add rule t c ct mark set ip dscp lshift 2 or 0x10
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_3 b/tests/shell/testcases/bitwise/0040mark_binop_3
new file mode 100755
index 000000000000..b491565ca573
--- /dev/null
+++ b/tests/shell/testcases/bitwise/0040mark_binop_3
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+set -e
+
+RULESET="
+  add table t
+  add chain t c { type filter hook input priority filter; }
+  add rule t c meta mark set ip dscp lshift 2 or 0x10
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_4 b/tests/shell/testcases/bitwise/0040mark_binop_4
new file mode 100755
index 000000000000..adc5f25ba930
--- /dev/null
+++ b/tests/shell/testcases/bitwise/0040mark_binop_4
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+set -e
+
+RULESET="
+  add table t
+  add chain t c { type filter hook output priority filter; }
+  add rule t c ct mark set ip dscp lshift 26 or 0x10
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_5 b/tests/shell/testcases/bitwise/0040mark_binop_5
new file mode 100755
index 000000000000..286b7b1fc7f9
--- /dev/null
+++ b/tests/shell/testcases/bitwise/0040mark_binop_5
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+set -e
+
+RULESET="
+  add table t
+  add chain t c { type filter hook input priority filter; }
+  add rule t c meta mark set ip dscp lshift 26 or 0x10
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_6 b/tests/shell/testcases/bitwise/0040mark_binop_6
new file mode 100755
index 000000000000..9ea82952ef24
--- /dev/null
+++ b/tests/shell/testcases/bitwise/0040mark_binop_6
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+set -e
+
+RULESET="
+  add table ip6 t
+  add chain ip6 t c { type filter hook output priority filter; }
+  add rule ip6 t c ct mark set ip6 dscp lshift 2 or 0x10
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_7 b/tests/shell/testcases/bitwise/0040mark_binop_7
new file mode 100755
index 000000000000..ff9cfb55ac3e
--- /dev/null
+++ b/tests/shell/testcases/bitwise/0040mark_binop_7
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+set -e
+
+RULESET="
+  add table ip6 t
+  add chain ip6 t c { type filter hook input priority filter; }
+  add rule ip6 t c meta mark set ip6 dscp lshift 2 or 0x10
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_8 b/tests/shell/testcases/bitwise/0040mark_binop_8
new file mode 100755
index 000000000000..b348ee9367df
--- /dev/null
+++ b/tests/shell/testcases/bitwise/0040mark_binop_8
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+set -e
+
+RULESET="
+  add table ip6 t
+  add chain ip6 t c { type filter hook output priority filter; }
+  add rule ip6 t c ct mark set ip6 dscp lshift 26 or 0x10
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/0040mark_binop_9 b/tests/shell/testcases/bitwise/0040mark_binop_9
new file mode 100755
index 000000000000..d19447d42b22
--- /dev/null
+++ b/tests/shell/testcases/bitwise/0040mark_binop_9
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+set -e
+
+RULESET="
+  add table ip6 t
+  add chain ip6 t c { type filter hook input priority filter; }
+  add rule ip6 t c meta mark set ip6 dscp lshift 26 or 0x10
+"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_2.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_2.nft
new file mode 100644
index 000000000000..2b9be36e2a03
--- /dev/null
+++ b/tests/shell/testcases/bitwise/dumps/0040mark_binop_2.nft
@@ -0,0 +1,6 @@
+table ip t {
+	chain c {
+		type filter hook output priority filter; policy accept;
+		ct mark set ip dscp << 2 | 0x10
+	}
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_3.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_3.nft
new file mode 100644
index 000000000000..8206fec045bc
--- /dev/null
+++ b/tests/shell/testcases/bitwise/dumps/0040mark_binop_3.nft
@@ -0,0 +1,6 @@
+table ip t {
+	chain c {
+		type filter hook input priority filter; policy accept;
+		meta mark set ip dscp << 2 | 0x10
+	}
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_4.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_4.nft
new file mode 100644
index 000000000000..91d9f5662acb
--- /dev/null
+++ b/tests/shell/testcases/bitwise/dumps/0040mark_binop_4.nft
@@ -0,0 +1,6 @@
+table ip t {
+	chain c {
+		type filter hook output priority filter; policy accept;
+		ct mark set ip dscp << 26 | 0x10
+	}
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_5.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_5.nft
new file mode 100644
index 000000000000..f2b51eb80674
--- /dev/null
+++ b/tests/shell/testcases/bitwise/dumps/0040mark_binop_5.nft
@@ -0,0 +1,6 @@
+table ip t {
+	chain c {
+		type filter hook input priority filter; policy accept;
+		meta mark set ip dscp << 26 | 0x10
+	}
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_6.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_6.nft
new file mode 100644
index 000000000000..cf7be90c35e1
--- /dev/null
+++ b/tests/shell/testcases/bitwise/dumps/0040mark_binop_6.nft
@@ -0,0 +1,6 @@
+table ip6 t {
+	chain c {
+		type filter hook output priority filter; policy accept;
+		ct mark set ip6 dscp << 2 | 0x10
+	}
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_7.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_7.nft
new file mode 100644
index 000000000000..a9663e621448
--- /dev/null
+++ b/tests/shell/testcases/bitwise/dumps/0040mark_binop_7.nft
@@ -0,0 +1,6 @@
+table ip6 t {
+	chain c {
+		type filter hook input priority filter; policy accept;
+		meta mark set ip6 dscp << 2 | 0x10
+	}
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_8.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_8.nft
new file mode 100644
index 000000000000..04b866ad6dd5
--- /dev/null
+++ b/tests/shell/testcases/bitwise/dumps/0040mark_binop_8.nft
@@ -0,0 +1,6 @@
+table ip6 t {
+	chain c {
+		type filter hook output priority filter; policy accept;
+		ct mark set ip6 dscp << 26 | 0x10
+	}
+}
diff --git a/tests/shell/testcases/bitwise/dumps/0040mark_binop_9.nft b/tests/shell/testcases/bitwise/dumps/0040mark_binop_9.nft
new file mode 100644
index 000000000000..d4745ea4947e
--- /dev/null
+++ b/tests/shell/testcases/bitwise/dumps/0040mark_binop_9.nft
@@ -0,0 +1,6 @@
+table ip6 t {
+	chain c {
+		type filter hook input priority filter; policy accept;
+		meta mark set ip6 dscp << 26 | 0x10
+	}
+}
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH nft,v3 12/12] tests: py: extend test-cases for mark statements with bitwise expressions
  2023-03-23 16:58 [PATCH nft,v3 00/12] mark statement support for non-constant expression Pablo Neira Ayuso
                   ` (10 preceding siblings ...)
  2023-03-23 16:58 ` [PATCH nft,v3 11/12] tests: shell: add test-cases for ct and packet mark payload expressions Pablo Neira Ayuso
@ 2023-03-23 16:58 ` Pablo Neira Ayuso
  11 siblings, 0 replies; 15+ messages in thread
From: Pablo Neira Ayuso @ 2023-03-23 16:58 UTC (permalink / raw)
  To: netfilter-devel; +Cc: jeremy, fw

Add more tests to cover bitwise operation. Shift operations are used on
constant value which are reduced at evaluation time.

Shift takes precendence over AND and OR operations, otherwise use parens
to override this.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 tests/py/ip/ct.t          |  4 ++
 tests/py/ip/ct.t.json     | 96 +++++++++++++++++++++++++++++++++++++++
 tests/py/ip/ct.t.payload  | 32 +++++++++++++
 tests/py/ip6/ct.t         |  3 ++
 tests/py/ip6/ct.t.json    | 72 +++++++++++++++++++++++++++++
 tests/py/ip6/ct.t.payload | 27 +++++++++++
 6 files changed, 234 insertions(+)

diff --git a/tests/py/ip/ct.t b/tests/py/ip/ct.t
index eea9fd4e0562..a0a222893dd0 100644
--- a/tests/py/ip/ct.t
+++ b/tests/py/ip/ct.t
@@ -30,3 +30,7 @@ ct original saddr . meta mark { 1.1.1.1 . 0x00000014 };fail
 ct original ip saddr . meta mark { 1.1.1.1 . 0x00000014 };ok
 ct mark set ip dscp << 2 | 0x10;ok
 ct mark set ip dscp << 26 | 0x10;ok
+ct mark set ip dscp & 0x0f << 1;ok;ct mark set ip dscp & af33
+ct mark set ip dscp & 0x0f << 2;ok;ct mark set ip dscp & 0x3c
+ct mark set ip dscp | 0x04;ok
+ct mark set ip dscp | 1 << 20;ok;ct mark set ip dscp | 0x100000
diff --git a/tests/py/ip/ct.t.json b/tests/py/ip/ct.t.json
index e739b5f65bfe..915632aef076 100644
--- a/tests/py/ip/ct.t.json
+++ b/tests/py/ip/ct.t.json
@@ -383,3 +383,99 @@
         }
     }
 ]
+
+# ct mark set ip dscp & 0x0f << 1
+[
+    {
+        "mangle": {
+            "key": {
+                "ct": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "&": [
+                    {
+                        "payload": {
+                            "field": "dscp",
+                            "protocol": "ip"
+                        }
+                    },
+                    "af33"
+                ]
+            }
+        }
+    }
+]
+
+# ct mark set ip dscp & 0x0f << 2
+[
+    {
+        "mangle": {
+            "key": {
+                "ct": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "&": [
+                    {
+                        "payload": {
+                            "field": "dscp",
+                            "protocol": "ip"
+                        }
+                    },
+                    60
+                ]
+            }
+        }
+    }
+]
+
+# ct mark set ip dscp | 0x04
+[
+    {
+        "mangle": {
+            "key": {
+                "ct": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "payload": {
+                            "field": "dscp",
+                            "protocol": "ip"
+                        }
+                    },
+                    4
+                ]
+            }
+        }
+    }
+]
+
+# ct mark set ip dscp | 1 << 20
+[
+    {
+        "mangle": {
+            "key": {
+                "ct": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "payload": {
+                            "field": "dscp",
+                            "protocol": "ip"
+                        }
+                    },
+                    1048576
+                ]
+            }
+        }
+    }
+]
diff --git a/tests/py/ip/ct.t.payload b/tests/py/ip/ct.t.payload
index 45dba3390940..692011d0f860 100644
--- a/tests/py/ip/ct.t.payload
+++ b/tests/py/ip/ct.t.payload
@@ -102,3 +102,35 @@ ip
   [ bitwise reg 1 = ( reg 1 << 0x0000001a ) ]
   [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
   [ ct set mark with reg 1 ]
+
+# ct mark set ip dscp & 0x0f << 1
+ip test-ip4 output
+  [ 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 & 0x0000001e ) ^ 0x00000000 ]
+  [ ct set mark with reg 1 ]
+
+# ct mark set ip dscp & 0x0f << 2
+ip test-ip4 output
+  [ 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 & 0x0000003c ) ^ 0x00000000 ]
+  [ ct set mark with reg 1 ]
+
+# ct mark set ip dscp | 0x04
+ip test-ip4 output
+  [ 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 & 0xfffffffb ) ^ 0x00000004 ]
+  [ ct set mark with reg 1 ]
+
+# ct mark set ip dscp | 1 << 20
+ip test-ip4 output
+  [ 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 & 0xffefffff ) ^ 0x00100000 ]
+  [ ct set mark with reg 1 ]
diff --git a/tests/py/ip6/ct.t b/tests/py/ip6/ct.t
index da69b7a910e4..c06fd6a0441d 100644
--- a/tests/py/ip6/ct.t
+++ b/tests/py/ip6/ct.t
@@ -4,3 +4,6 @@
 
 ct mark set ip6 dscp << 2 | 0x10;ok
 ct mark set ip6 dscp << 26 | 0x10;ok
+ct mark set ip6 dscp | 0x04;ok
+ct mark set ip6 dscp | 0xff000000;ok
+ct mark set ip6 dscp & 0x0f << 2;ok;ct mark set ip6 dscp & 0x3c
diff --git a/tests/py/ip6/ct.t.json b/tests/py/ip6/ct.t.json
index 7579a65ef791..7d8c88bb09cb 100644
--- a/tests/py/ip6/ct.t.json
+++ b/tests/py/ip6/ct.t.json
@@ -219,3 +219,75 @@
         }
     }
 ]
+
+# ct mark set ip6 dscp | 0x04
+[
+    {
+        "mangle": {
+            "key": {
+                "ct": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "payload": {
+                            "field": "dscp",
+                            "protocol": "ip6"
+                        }
+                    },
+                    4
+                ]
+            }
+        }
+    }
+]
+
+# ct mark set ip6 dscp | 0xff000000
+[
+    {
+        "mangle": {
+            "key": {
+                "ct": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "payload": {
+                            "field": "dscp",
+                            "protocol": "ip6"
+                        }
+                    },
+                    4278190080
+                ]
+            }
+        }
+    }
+]
+
+# ct mark set ip6 dscp & 0x0f << 2
+[
+    {
+        "mangle": {
+            "key": {
+                "ct": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "&": [
+                    {
+                        "payload": {
+                            "field": "dscp",
+                            "protocol": "ip6"
+                        }
+                    },
+                    60
+                ]
+            }
+        }
+    }
+]
diff --git a/tests/py/ip6/ct.t.payload b/tests/py/ip6/ct.t.payload
index 00768dae79f1..164149e93d17 100644
--- a/tests/py/ip6/ct.t.payload
+++ b/tests/py/ip6/ct.t.payload
@@ -17,3 +17,30 @@ ip6 test-ip6 output
   [ bitwise reg 1 = ( reg 1 << 0x0000001a ) ]
   [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]
   [ ct set mark with reg 1 ]
+
+# ct mark set ip6 dscp | 0x04
+ip6 test-ip6 output
+  [ payload load 2b @ network header + 0 => reg 1 ]
+  [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+  [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+  [ byteorder reg 1 = ntoh(reg 1, 2, 1) ]
+  [ bitwise reg 1 = ( reg 1 & 0xfffffffb ) ^ 0x00000004 ]
+  [ ct set mark with reg 1 ]
+
+# ct mark set ip6 dscp | 0xff000000
+ip6 test-ip6 output
+  [ payload load 2b @ network header + 0 => reg 1 ]
+  [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+  [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+  [ byteorder reg 1 = ntoh(reg 1, 2, 1) ]
+  [ bitwise reg 1 = ( reg 1 & 0x00ffffff ) ^ 0xff000000 ]
+  [ ct set mark with reg 1 ]
+
+# ct mark set ip6 dscp & 0x0f << 2
+ip6 test-ip6 output
+  [ payload load 2b @ network header + 0 => reg 1 ]
+  [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+  [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+  [ byteorder reg 1 = ntoh(reg 1, 2, 1) ]
+  [ bitwise reg 1 = ( reg 1 & 0x0000003c ) ^ 0x00000000 ]
+  [ ct set mark with reg 1 ]
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH nft,v3 05/12] evaluate: set up integer type to shift expression
  2023-03-23 16:58 ` [PATCH nft,v3 05/12] evaluate: set up integer type to shift expression Pablo Neira Ayuso
@ 2023-03-28  8:21   ` Pablo Neira Ayuso
  0 siblings, 0 replies; 15+ messages in thread
From: Pablo Neira Ayuso @ 2023-03-28  8:21 UTC (permalink / raw)
  To: netfilter-devel; +Cc: jeremy, fw

On Thu, Mar 23, 2023 at 05:58:48PM +0100, Pablo Neira Ayuso wrote:
> Otherwise expr_evaluate_value() fails with invalid datatype:
> 
>  # nft --debug=netlink add rule ip x y 'ct mark set ip dscp & 0x0f << 1'
>  BUG: invalid basetype invalid
>  nft: evaluate.c:440: expr_evaluate_value: Assertion `0' failed.
> 
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> ---
>  src/evaluate.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/src/evaluate.c b/src/evaluate.c
> index 33b1aad72f66..1ee9bdc5aa47 100644
> --- a/src/evaluate.c
> +++ b/src/evaluate.c
> @@ -1308,6 +1308,7 @@ static int expr_evaluate_shift(struct eval_ctx *ctx, struct expr **expr)
>  	if (byteorder_conversion(ctx, &op->right, BYTEORDER_HOST_ENDIAN) < 0)
>  		return -1;
>  
> +	op->dtype     = &integer_type;

I have updated this patch to use:

        datatype_set(op, &integer_type);

before pushing out this batch.

otherwise, datatype leak is possible.

>  	op->byteorder = BYTEORDER_HOST_ENDIAN;
>  	op->len	      = max_shift_len;
>  
> -- 
> 2.30.2
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH nft,v3 07/12] evaluate: honor statement length in bitwise evaluation
  2023-03-23 16:58 ` [PATCH nft,v3 07/12] evaluate: honor statement length in bitwise evaluation Pablo Neira Ayuso
@ 2023-03-28  8:22   ` Pablo Neira Ayuso
  0 siblings, 0 replies; 15+ messages in thread
From: Pablo Neira Ayuso @ 2023-03-28  8:22 UTC (permalink / raw)
  To: netfilter-devel; +Cc: jeremy, fw

On Thu, Mar 23, 2023 at 05:58:50PM +0100, Pablo Neira Ayuso wrote:
> @@ -1326,13 +1326,32 @@ static int expr_evaluate_shift(struct eval_ctx *ctx, struct expr **expr)
>  static int expr_evaluate_bitwise(struct eval_ctx *ctx, struct expr **expr)
>  {
>  	struct expr *op = *expr, *left = op->left;
> +	const struct datatype *dtype;
> +	unsigned int max_len;
> +	int byteorder;
> +
> +	if (ctx->stmt_len > left->len) {
> +		max_len = ctx->stmt_len;
> +		byteorder = BYTEORDER_HOST_ENDIAN;
> +		dtype = &integer_type;
> +
> +		/* Both sides need to be in host byte order */
> +		if (byteorder_conversion(ctx, &op->left, BYTEORDER_HOST_ENDIAN) < 0)
> +			return -1;
> +
> +		left = op->left;
> +	} else {
> +		max_len = left->len;
> +		byteorder = left->byteorder;
> +		dtype = left->dtype;
> +	}
>  
> -	if (byteorder_conversion(ctx, &op->right, left->byteorder) < 0)
> +	if (byteorder_conversion(ctx, &op->right, byteorder) < 0)
>  		return -1;
>  
> -	op->dtype     = left->dtype;
> -	op->byteorder = left->byteorder;
> -	op->len	      = left->len;
> +	op->dtype     = dtype;

As in patch 5, this now uses too:

        datatype_set(op, dtype);

> +	op->byteorder = byteorder;
> +	op->len	      = max_len;
>  
>  	if (expr_is_constant(left))
>  		return constant_binop_simplify(ctx, expr);
> -- 
> 2.30.2
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2023-03-28  8:22 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-23 16:58 [PATCH nft,v3 00/12] mark statement support for non-constant expression Pablo Neira Ayuso
2023-03-23 16:58 ` [PATCH nft,v3 01/12] netlink_delinearize: correct type and byte-order of shifts Pablo Neira Ayuso
2023-03-23 16:58 ` [PATCH nft,v3 02/12] evaluate: support shifts larger than the width of the left operand Pablo Neira Ayuso
2023-03-23 16:58 ` [PATCH nft,v3 03/12] evaluate: don't eval unary arguments Pablo Neira Ayuso
2023-03-23 16:58 ` [PATCH nft,v3 04/12] evaluate: relax type-checking for integer arguments in mark statements Pablo Neira Ayuso
2023-03-23 16:58 ` [PATCH nft,v3 05/12] evaluate: set up integer type to shift expression Pablo Neira Ayuso
2023-03-28  8:21   ` Pablo Neira Ayuso
2023-03-23 16:58 ` [PATCH nft,v3 06/12] evaluate: honor statement length in integer evaluation Pablo Neira Ayuso
2023-03-23 16:58 ` [PATCH nft,v3 07/12] evaluate: honor statement length in bitwise evaluation Pablo Neira Ayuso
2023-03-28  8:22   ` Pablo Neira Ayuso
2023-03-23 16:58 ` [PATCH nft,v3 08/12] netlink_delinerize: incorrect byteorder in mark statement listing Pablo Neira Ayuso
2023-03-23 16:58 ` [PATCH nft,v3 09/12] tests: py: add test-cases for ct and packet mark payload expressions Pablo Neira Ayuso
2023-03-23 16:58 ` [PATCH nft,v3 10/12] tests: shell: rename and move bitwise test-cases Pablo Neira Ayuso
2023-03-23 16:58 ` [PATCH nft,v3 11/12] tests: shell: add test-cases for ct and packet mark payload expressions Pablo Neira Ayuso
2023-03-23 16:58 ` [PATCH nft,v3 12/12] tests: py: extend test-cases for mark statements with bitwise expressions Pablo Neira Ayuso

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).