From: Florian Westphal <fw@strlen.de>
To: <netfilter-devel@vger.kernel.org>
Cc: jake.owen@superloop.com, Florian Westphal <fw@strlen.de>
Subject: [PATCH nft 6/8] src: queue: allow use of arbitrary queue expressions
Date: Wed, 16 Jun 2021 23:16:50 +0200 [thread overview]
Message-ID: <20210616211652.11765-7-fw@strlen.de> (raw)
In-Reply-To: <20210616211652.11765-1-fw@strlen.de>
back in 2016 Liping Zhang added support to kernel and libnftnl to
specify a source register containing the queue number to use.
This was never added to nft itself, so allow this.
On linearization side, check if attached expression is a range.
If its not, allocate a new register and set NFTNL_EXPR_QUEUE_SREG_QNUM
attribute after generating the lowlevel expressions for the kernel.
On delinarization we need to check for presence of
NFTNL_EXPR_QUEUE_SREG_QNUM and decode the expression(s) when present.
Also need to do postprocessing for STMT_QUEUE so that the protocol
context is set correctly, without this only raw payload expressions
will be shown (@nh,32,...) instead of 'ip ...'.
Next patch adds test cases.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
doc/statements.txt | 4 ++++
src/evaluate.c | 13 ++++++-----
src/netlink_delinearize.c | 48 +++++++++++++++++++++++++++++++--------
src/netlink_linearize.c | 28 +++++++++++++++++++----
src/parser_bison.y | 16 +++++++++++--
src/statement.c | 9 ++++++--
6 files changed, 93 insertions(+), 25 deletions(-)
diff --git a/doc/statements.txt b/doc/statements.txt
index 602a5b2011a7..c2a616594fce 100644
--- a/doc/statements.txt
+++ b/doc/statements.txt
@@ -591,11 +591,15 @@ for details.
____
*queue* [*flags* 'QUEUE_FLAGS'] [*num* 'queue_number']
*queue* [*flags* 'QUEUE_FLAGS'] [*num* 'queue_number_from' - 'queue_number_to']
+*queue* [*flags* 'QUEUE_FLAGS'] [*to* 'QUEUE_EXPRESSION' ]
'QUEUE_FLAGS' := 'QUEUE_FLAG' [*,* 'QUEUE_FLAGS']
'QUEUE_FLAG' := *bypass* | *fanout*
+'QUEUE_EXPRESSION' := *numgen* | *hash* | *symhash*
____
+QUEUE_EXPRESSION can be used to compute a queue number
+at run-time with the hash or numgen expressions.
.queue statement values
[options="header"]
diff --git a/src/evaluate.c b/src/evaluate.c
index bebdb3f827e9..4a7ec95cd961 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1019,7 +1019,6 @@ static int expr_evaluate_range(struct eval_ctx *ctx, struct expr **expr)
if (mpz_cmp(left->value, right->value) >= 0)
return expr_error(ctx->msgs, range,
"Range has zero or negative size");
-
datatype_set(range, left->dtype);
range->flags |= EXPR_F_CONSTANT;
return 0;
@@ -3428,14 +3427,16 @@ static int stmt_evaluate_queue(struct eval_ctx *ctx, struct stmt *stmt)
BYTEORDER_HOST_ENDIAN,
&stmt->queue.queue) < 0)
return -1;
- if (!expr_is_constant(stmt->queue.queue))
- return expr_error(ctx->msgs, stmt->queue.queue,
- "queue number is not constant");
- if (stmt->queue.queue->etype != EXPR_RANGE &&
- (stmt->queue.flags & NFT_QUEUE_FLAG_CPU_FANOUT))
+
+ if ((stmt->queue.flags & NFT_QUEUE_FLAG_CPU_FANOUT) &&
+ stmt->queue.queue->etype != EXPR_RANGE)
return expr_error(ctx->msgs, stmt->queue.queue,
"fanout requires a range to be "
"specified");
+
+ if (ctx->ectx.maxval > USHRT_MAX)
+ return expr_error(ctx->msgs, stmt->queue.queue,
+ "queue expression max value exceeds %u", USHRT_MAX);
}
stmt->flags |= STMT_F_TERMINAL;
return 0;
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 7ea31e6a2639..07a6d06876e2 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -1467,19 +1467,32 @@ static void netlink_parse_queue(struct netlink_parse_ctx *ctx,
const struct location *loc,
const struct nftnl_expr *nle)
{
- uint16_t num, total, flags;
- struct expr *expr, *high;
+ struct expr *expr;
+ uint16_t flags;
- num = nftnl_expr_get_u16(nle, NFTNL_EXPR_QUEUE_NUM);
- total = nftnl_expr_get_u16(nle, NFTNL_EXPR_QUEUE_TOTAL);
+ if (nftnl_expr_is_set(nle, NFTNL_EXPR_QUEUE_SREG_QNUM)) {
+ enum nft_registers reg = netlink_parse_register(nle, NFTNL_EXPR_QUEUE_SREG_QNUM);
- expr = constant_expr_alloc(loc, &integer_type,
- BYTEORDER_HOST_ENDIAN, 16, &num);
- if (total > 1) {
- total += num - 1;
- high = constant_expr_alloc(loc, &integer_type,
+ expr = netlink_get_register(ctx, loc, reg);
+ if (!expr) {
+ netlink_error(ctx, loc, "queue statement has no sreg expression");
+ return;
+ }
+ } else {
+ uint16_t total = nftnl_expr_get_u16(nle, NFTNL_EXPR_QUEUE_TOTAL);
+ uint16_t num = nftnl_expr_get_u16(nle, NFTNL_EXPR_QUEUE_NUM);
+
+ expr = constant_expr_alloc(loc, &integer_type,
+ BYTEORDER_HOST_ENDIAN, 16, &num);
+
+ if (total > 1) {
+ struct expr *high;
+
+ total += num - 1;
+ high = constant_expr_alloc(loc, &integer_type,
BYTEORDER_HOST_ENDIAN, 16, &total);
- expr = range_expr_alloc(loc, expr, high);
+ expr = range_expr_alloc(loc, expr, high);
+ }
}
flags = nftnl_expr_get_u16(nle, NFTNL_EXPR_QUEUE_FLAGS);
@@ -2788,6 +2801,18 @@ static void stmt_payload_postprocess(struct rule_pp_ctx *ctx)
expr_postprocess(ctx, &stmt->payload.val);
}
+static void stmt_queue_postprocess(struct rule_pp_ctx *ctx)
+{
+ struct stmt *stmt = ctx->stmt;
+ struct expr *e = stmt->queue.queue;
+
+ if (e == NULL || e->etype == EXPR_VALUE ||
+ e->etype == EXPR_RANGE)
+ return;
+
+ expr_postprocess(ctx, &stmt->queue.queue);
+}
+
/*
* We can only remove payload dependencies if they occur without
* a statement with side effects in between.
@@ -2889,6 +2914,9 @@ static void rule_parse_postprocess(struct netlink_parse_ctx *ctx, struct rule *r
case STMT_OBJREF:
expr_postprocess(&rctx, &stmt->objref.expr);
break;
+ case STMT_QUEUE:
+ stmt_queue_postprocess(&rctx);
+ break;
default:
break;
}
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 7b35aae1f913..b1f3feeeb4b7 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -1334,21 +1334,39 @@ static void netlink_gen_fwd_stmt(struct netlink_linearize_ctx *ctx,
static void netlink_gen_queue_stmt(struct netlink_linearize_ctx *ctx,
const struct stmt *stmt)
{
+ enum nft_registers sreg = 0;
struct nftnl_expr *nle;
uint16_t total_queues;
+ struct expr *expr;
mpz_t low, high;
mpz_init2(low, 16);
mpz_init2(high, 16);
- if (stmt->queue.queue != NULL) {
- range_expr_value_low(low, stmt->queue.queue);
- range_expr_value_high(high, stmt->queue.queue);
+
+ expr = stmt->queue.queue;
+
+ if (expr) {
+ if (expr->etype == EXPR_RANGE || expr->etype == EXPR_VALUE) {
+ range_expr_value_low(low, stmt->queue.queue);
+ range_expr_value_high(high, stmt->queue.queue);
+ } else {
+ sreg = get_register(ctx, expr);
+ netlink_gen_expr(ctx, expr, sreg);
+ release_register(ctx, expr);
+ }
}
+
total_queues = mpz_get_uint16(high) - mpz_get_uint16(low) + 1;
nle = alloc_nft_expr("queue");
- nftnl_expr_set_u16(nle, NFTNL_EXPR_QUEUE_NUM, mpz_get_uint16(low));
- nftnl_expr_set_u16(nle, NFTNL_EXPR_QUEUE_TOTAL, total_queues);
+
+ if (sreg) {
+ netlink_put_register(nle, NFTNL_EXPR_QUEUE_SREG_QNUM, sreg);
+ } else {
+ nftnl_expr_set_u16(nle, NFTNL_EXPR_QUEUE_NUM, mpz_get_uint16(low));
+ nftnl_expr_set_u16(nle, NFTNL_EXPR_QUEUE_TOTAL, total_queues);
+ }
+
if (stmt->queue.flags)
nftnl_expr_set_u16(nle, NFTNL_EXPR_QUEUE_FLAGS,
stmt->queue.flags);
diff --git a/src/parser_bison.y b/src/parser_bison.y
index cf90d5ce5672..d75960715a90 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -705,8 +705,8 @@ int nft_lex(void *, void *, void *);
%type <stmt> queue_stmt queue_stmt_alloc queue_stmt_compat
%destructor { stmt_free($$); } queue_stmt queue_stmt_alloc queue_stmt_compat
-%type <expr> queue_stmt_expr_simple
-%destructor { expr_free($$); } queue_stmt_expr_simple
+%type <expr> queue_stmt_expr_simple queue_stmt_expr
+%destructor { expr_free($$); } queue_stmt_expr_simple queue_stmt_expr
%type <val> queue_stmt_flags queue_stmt_flag
%type <stmt> dup_stmt
%destructor { stmt_free($$); } dup_stmt
@@ -3739,6 +3739,14 @@ nf_nat_flag : RANDOM { $$ = NF_NAT_RANGE_PROTO_RANDOM; }
;
queue_stmt : queue_stmt_compat close_scope_queue
+ | QUEUE TO queue_stmt_expr close_scope_queue
+ {
+ $$ = queue_stmt_alloc(&@$, $3, 0);
+ }
+ | QUEUE FLAGS queue_stmt_flags TO queue_stmt_expr close_scope_queue
+ {
+ $$ = queue_stmt_alloc(&@$, $5, $3);
+ }
| QUEUE FLAGS queue_stmt_flags QUEUENUM queue_stmt_expr_simple close_scope_queue
{
$$ = queue_stmt_alloc(&@$, $5, $3);
@@ -3777,6 +3785,10 @@ queue_stmt_expr_simple : integer_expr
| range_rhs_expr
;
+queue_stmt_expr : numgen_expr
+ | hash_expr
+ ;
+
queue_stmt_flags : queue_stmt_flag
| queue_stmt_flags COMMA queue_stmt_flag
{
diff --git a/src/statement.c b/src/statement.c
index 9eb49339555b..dfd275104c59 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -507,8 +507,13 @@ static void queue_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
nft_print(octx, "%sfanout", delim);
if (e) {
- nft_print(octx, " num ");
- expr_print(stmt->queue.queue, octx);
+ if (e->etype == EXPR_VALUE || e->etype == EXPR_RANGE) {
+ nft_print(octx, " num ");
+ expr_print(stmt->queue.queue, octx);
+ } else {
+ nft_print(octx, " to ");
+ expr_print(stmt->queue.queue, octx);
+ }
} else {
nft_print(octx, " num 0");
}
--
2.31.1
next prev parent reply other threads:[~2021-06-16 21:17 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-06-16 21:16 [PATCH nft 0/8] Enableruntime queue selection via jhash, numgen and map statement Florian Westphal
2021-06-16 21:16 ` [PATCH nft 1/8] evaluate: fix hash expression maxval Florian Westphal
2021-06-16 21:16 ` [PATCH nft 2/8] parser: restrict queue num expressiveness Florian Westphal
2021-06-16 21:16 ` [PATCH nft 3/8] src: add queue expr and flags to queue_stmt_alloc Florian Westphal
2021-06-16 21:16 ` [PATCH nft 4/8] parser: add queue_stmt_compat Florian Westphal
2021-06-16 21:16 ` [PATCH nft 5/8] parser: new queue flag input format Florian Westphal
2021-06-16 21:16 ` Florian Westphal [this message]
2021-06-16 21:16 ` [PATCH nft 7/8] tests: extend queue testcases for new sreg support Florian Westphal
2021-06-16 21:16 ` [PATCH nft 8/8] src: queue: allow use of MAP statement for queue number retrieval Florian Westphal
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210616211652.11765-7-fw@strlen.de \
--to=fw@strlen.de \
--cc=jake.owen@superloop.com \
--cc=netfilter-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).