All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH nft,v2] src: add negation match on singleton bitmask value
@ 2021-02-04  0:00 Pablo Neira Ayuso
  0 siblings, 0 replies; only message in thread
From: Pablo Neira Ayuso @ 2021-02-04  0:00 UTC (permalink / raw)
  To: netfilter-devel

This patch provides a shortcut for:

	ct status and dnat == 0

which allows to check for the packet whose dnat bit is unset:

  # nft add rule x y ct status ! dnat counter packets

This operation is only available for expression with a bitmask basetype, eg.

  # nft describe ct status
  ct expression, datatype ct_status (conntrack status) (basetype bitmask, integer), 32 bits

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: add a tests/py unit.

 include/expression.h      |  1 +
 src/evaluate.c            |  8 ++++++++
 src/expression.c          |  1 +
 src/netlink_delinearize.c | 14 +++++++++++---
 src/netlink_linearize.c   |  9 +++++++--
 src/parser_bison.y        |  1 +
 tests/py/any/ct.t         |  1 +
 tests/py/any/ct.t.payload |  6 ++++++
 8 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/include/expression.h b/include/expression.h
index 718dac5a122d..2d07f3d96beb 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -93,6 +93,7 @@ enum ops {
 	OP_GT,
 	OP_LTE,
 	OP_GTE,
+	OP_NEG,
 	__OP_MAX
 };
 #define OP_MAX		(__OP_MAX - 1)
diff --git a/src/evaluate.c b/src/evaluate.c
index 1d5db4dacd82..2f6c9d68f0d9 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1956,6 +1956,14 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
 
 		/* fall through */
 	case OP_NEQ:
+	case OP_NEG:
+		if (rel->op == OP_NEG &&
+		    (right->etype != EXPR_VALUE ||
+		     right->dtype->basetype == NULL ||
+		     right->dtype->basetype->type != TYPE_BITMASK))
+			return expr_binary_error(ctx->msgs, left, right,
+						 "negation can only be used with singleton bitmask values");
+
 		switch (right->etype) {
 		case EXPR_RANGE:
 			if (byteorder_conversion(ctx, &rel->left, BYTEORDER_BIG_ENDIAN) < 0)
diff --git a/src/expression.c b/src/expression.c
index 58d73e9509b0..a90a89ca9f74 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -560,6 +560,7 @@ const char *expr_op_symbols[] = {
 	[OP_GT]		= ">",
 	[OP_LTE]	= "<=",
 	[OP_GTE]	= ">=",
+	[OP_NEG]	= "!",
 };
 
 static void unary_expr_print(const struct expr *expr, struct output_ctx *octx)
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 04560b976974..7cd7d403a038 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -2167,7 +2167,7 @@ static void relational_binop_postprocess(struct rule_pp_ctx *ctx, struct expr *e
 {
 	struct expr *binop = expr->left, *value = expr->right;
 
-	if (binop->op == OP_AND && expr->op == OP_NEQ &&
+	if (binop->op == OP_AND && (expr->op == OP_NEQ || expr->op == OP_EQ) &&
 	    value->dtype->basetype &&
 	    value->dtype->basetype->type == TYPE_BITMASK &&
 	    !mpz_cmp_ui(value->value, 0)) {
@@ -2180,8 +2180,16 @@ static void relational_binop_postprocess(struct rule_pp_ctx *ctx, struct expr *e
 
 		expr->left  = expr_get(binop->left);
 		expr->right = binop_tree_to_list(NULL, binop->right);
-		expr->op    = OP_IMPLICIT;
-
+		switch (expr->op) {
+		case OP_NEQ:
+			expr->op = OP_IMPLICIT;
+			break;
+		case OP_EQ:
+			expr->op = OP_NEG;
+			break;
+		default:
+			BUG("unknown operation type %d\n", expr->op);
+		}
 		expr_free(binop);
 	} else if (binop->left->dtype->flags & DTYPE_F_PREFIX &&
 		   binop->op == OP_AND && expr->right->etype == EXPR_VALUE &&
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index f1b3ff6940ea..21bc492e85f4 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -490,7 +490,11 @@ static void netlink_gen_flagcmp(struct netlink_linearize_ctx *ctx,
 
 	nle = alloc_nft_expr("cmp");
 	netlink_put_register(nle, NFTNL_EXPR_CMP_SREG, sreg);
-	nftnl_expr_set_u32(nle, NFTNL_EXPR_CMP_OP, NFT_CMP_NEQ);
+	if (expr->op == OP_NEG)
+		nftnl_expr_set_u32(nle, NFTNL_EXPR_CMP_OP, NFT_CMP_EQ);
+	else
+		nftnl_expr_set_u32(nle, NFTNL_EXPR_CMP_OP, NFT_CMP_NEQ);
+
 	nftnl_expr_set(nle, NFTNL_EXPR_CMP_DATA, nld.value, nld.len);
 	nft_rule_add_expr(ctx, nle, &expr->location);
 
@@ -518,6 +522,7 @@ static void netlink_gen_relational(struct netlink_linearize_ctx *ctx,
 	case OP_GT:
 	case OP_LTE:
 	case OP_GTE:
+	case OP_NEG:
 		break;
 	default:
 		BUG("invalid relational operation %u\n", expr->op);
@@ -547,7 +552,7 @@ static void netlink_gen_relational(struct netlink_linearize_ctx *ctx,
 		}
 		break;
 	default:
-		if (expr->op == OP_IMPLICIT &&
+		if ((expr->op == OP_IMPLICIT || expr->op == OP_NEG) &&
 		    expr->right->dtype->basetype != NULL &&
 		    expr->right->dtype->basetype->type == TYPE_BITMASK)
 			return netlink_gen_flagcmp(ctx, expr, dreg);
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 519e8efe5ab7..11e899ff2f20 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -4639,6 +4639,7 @@ relational_op		:	EQ		{ $$ = OP_EQ; }
 			|	GT		{ $$ = OP_GT; }
 			|	GTE		{ $$ = OP_GTE; }
 			|	LTE		{ $$ = OP_LTE; }
+			|	NOT		{ $$ = OP_NEG; }
 			;
 
 verdict_expr		:	ACCEPT
diff --git a/tests/py/any/ct.t b/tests/py/any/ct.t
index cc09aebcbc44..07583fdf33f8 100644
--- a/tests/py/any/ct.t
+++ b/tests/py/any/ct.t
@@ -29,6 +29,7 @@ ct status {expected, seen-reply, assured, confirmed, dying};ok
 ct status expected,seen-reply,assured,confirmed,snat,dnat,dying;ok
 ct status snat;ok
 ct status dnat;ok
+ct status ! dnat;ok
 ct status xxx;fail
 
 ct mark 0;ok;ct mark 0x00000000
diff --git a/tests/py/any/ct.t.payload b/tests/py/any/ct.t.payload
index 51a825034901..2c9648f5b825 100644
--- a/tests/py/any/ct.t.payload
+++ b/tests/py/any/ct.t.payload
@@ -511,3 +511,9 @@ ip test-ip4 output
   [ ct load unknown => reg 1 ]
   [ cmp eq reg 1 0x39300000 ]
 
+# ct status ! dnat
+ip6
+  [ ct load status => reg 1 ]
+  [ bitwise reg 1 = ( reg 1 & 0x00000020 ) ^ 0x00000000 ]
+  [ cmp eq reg 1 0x00000000 ]
+
-- 
2.20.1


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2021-02-04  0:00 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-04  0:00 [PATCH nft,v2] src: add negation match on singleton bitmask value Pablo Neira Ayuso

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.