179 lines
6.0 KiB
Diff
179 lines
6.0 KiB
Diff
From f1fd3a56922f88551c2a2c94654aa5175f6d410c Mon Sep 17 00:00:00 2001
|
|
From: Phil Sutter <psutter@redhat.com>
|
|
Date: Fri, 17 Jul 2026 11:30:58 +0200
|
|
Subject: [PATCH] expression: propagate key datatype for anonymous sets
|
|
|
|
JIRA: https://issues.redhat.com/browse/RHEL-190549
|
|
Upstream Status: nftables commit 3d6ad54dbc74449e171823cdaf9d43cd41721b8d
|
|
|
|
commit 3d6ad54dbc74449e171823cdaf9d43cd41721b8d
|
|
Author: Florian Westphal <fw@strlen.de>
|
|
Date: Thu Feb 27 15:52:08 2025 +0100
|
|
|
|
expression: propagate key datatype for anonymous sets
|
|
|
|
set s {
|
|
typeof tcp option mptcp subtype
|
|
elements = { mp-join, dss }
|
|
}
|
|
|
|
is listed correctly. The set key provides the 'mptcpopt_subtype'
|
|
information and listing can print all elements with symbolic names.
|
|
|
|
In anon set case this doesn't work:
|
|
tcp option mptcp subtype { mp-join, dss }
|
|
|
|
is printed as "... subtype { 1, 2}" because the anon set only provides
|
|
plain integer type.
|
|
|
|
This change propagates the datatype to the individual members of the
|
|
anon set.
|
|
|
|
After this change, multiple existing data types such as TYPE_ICMP_TYPE
|
|
could theoretically be replaced by integer-type aliases.
|
|
|
|
However, those datatypes are already exposed to userspace via the
|
|
'set type' keyword. Thus removing them will break set definitions that
|
|
use them.
|
|
|
|
Signed-off-by: Florian Westphal <fw@strlen.de>
|
|
|
|
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
|
---
|
|
src/expression.c | 35 +++++++++++++++++++++++++++++++++++
|
|
tests/py/any/tcpopt.t | 2 +-
|
|
tests/py/any/tcpopt.t.json | 11 ++++++++---
|
|
tests/py/any/tcpopt.t.payload | 10 +++++-----
|
|
4 files changed, 49 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/src/expression.c b/src/expression.c
|
|
index 09449da..4fd0a91 100644
|
|
--- a/src/expression.c
|
|
+++ b/src/expression.c
|
|
@@ -1365,6 +1365,32 @@ static void set_ref_expr_destroy(struct expr *expr)
|
|
set_free(expr->set);
|
|
}
|
|
|
|
+static void set_ref_expr_set_type(const struct expr *expr,
|
|
+ const struct datatype *dtype,
|
|
+ enum byteorder byteorder)
|
|
+{
|
|
+ const struct set *s = expr->set;
|
|
+
|
|
+ /* normal sets already have a precise datatype that is given in
|
|
+ * the set definition via type foo.
|
|
+ *
|
|
+ * Anon sets do not have this, and need to rely on type info
|
|
+ * generated at rule creation time.
|
|
+ *
|
|
+ * For most cases, the type info is correct.
|
|
+ * In some cases however, the kernel only stores TYPE_INTEGER.
|
|
+ *
|
|
+ * This happens with expressions that only use an integer alias
|
|
+ * type, e.g. the mptcpopt_subtype datatype.
|
|
+ *
|
|
+ * In this case nft will print the elements as numerical values
|
|
+ * because the base type lacks the ->sym_tbl information of the
|
|
+ * subtypes.
|
|
+ */
|
|
+ if (s->init && set_is_anonymous(s->flags))
|
|
+ expr_set_type(s->init, dtype, byteorder);
|
|
+}
|
|
+
|
|
static const struct expr_ops set_ref_expr_ops = {
|
|
.type = EXPR_SET_REF,
|
|
.name = "set reference",
|
|
@@ -1372,6 +1398,7 @@ static const struct expr_ops set_ref_expr_ops = {
|
|
.json = set_ref_expr_json,
|
|
.clone = set_ref_expr_clone,
|
|
.destroy = set_ref_expr_destroy,
|
|
+ .set_type = set_ref_expr_set_type,
|
|
};
|
|
|
|
struct expr *set_ref_expr_alloc(const struct location *loc, struct set *set)
|
|
@@ -1431,6 +1458,13 @@ static void set_elem_expr_clone(struct expr *new, const struct expr *expr)
|
|
__set_elem_expr_clone(new, expr);
|
|
}
|
|
|
|
+static void set_elem_expr_set_type(const struct expr *expr,
|
|
+ const struct datatype *dtype,
|
|
+ enum byteorder byteorder)
|
|
+{
|
|
+ expr_set_type(expr->key, dtype, byteorder);
|
|
+}
|
|
+
|
|
static const struct expr_ops set_elem_expr_ops = {
|
|
.type = EXPR_SET_ELEM,
|
|
.name = "set element",
|
|
@@ -1438,6 +1472,7 @@ static const struct expr_ops set_elem_expr_ops = {
|
|
.print = set_elem_expr_print,
|
|
.json = set_elem_expr_json,
|
|
.destroy = set_elem_expr_destroy,
|
|
+ .set_type = set_elem_expr_set_type,
|
|
};
|
|
|
|
struct expr *set_elem_expr_alloc(const struct location *loc, struct expr *key)
|
|
diff --git a/tests/py/any/tcpopt.t b/tests/py/any/tcpopt.t
|
|
index a2fcdb3..79699e2 100644
|
|
--- a/tests/py/any/tcpopt.t
|
|
+++ b/tests/py/any/tcpopt.t
|
|
@@ -53,7 +53,7 @@ tcp option mptcp exists;ok
|
|
|
|
tcp option mptcp subtype mp-capable;ok
|
|
tcp option mptcp subtype 1;ok;tcp option mptcp subtype mp-join
|
|
-tcp option mptcp subtype { 0, 2};ok
|
|
+tcp option mptcp subtype { mp-capable, mp-join, remove-addr, mp-prio, mp-fail, mp-fastclose, mp-tcprst };ok
|
|
|
|
reset tcp option mptcp;ok
|
|
reset tcp option 2;ok;reset tcp option maxseg
|
|
diff --git a/tests/py/any/tcpopt.t.json b/tests/py/any/tcpopt.t.json
|
|
index bf10c55..fb0662a 100644
|
|
--- a/tests/py/any/tcpopt.t.json
|
|
+++ b/tests/py/any/tcpopt.t.json
|
|
@@ -565,7 +565,7 @@
|
|
}
|
|
]
|
|
|
|
-# tcp option mptcp subtype { 0, 2}
|
|
+# tcp option mptcp subtype { mp-capable, mp-join, remove-addr, mp-prio, mp-fail, mp-fastclose, mp-tcprst }
|
|
[
|
|
{
|
|
"match": {
|
|
@@ -578,8 +578,13 @@
|
|
"op": "==",
|
|
"right": {
|
|
"set": [
|
|
- 0,
|
|
- 2
|
|
+ "mp-capable",
|
|
+ "mp-join",
|
|
+ "remove-addr",
|
|
+ "mp-prio",
|
|
+ "mp-fail",
|
|
+ "mp-fastclose",
|
|
+ "mp-tcprst"
|
|
]
|
|
}
|
|
}
|
|
diff --git a/tests/py/any/tcpopt.t.payload b/tests/py/any/tcpopt.t.payload
|
|
index e3cf500..af8c431 100644
|
|
--- a/tests/py/any/tcpopt.t.payload
|
|
+++ b/tests/py/any/tcpopt.t.payload
|
|
@@ -180,11 +180,11 @@ inet
|
|
[ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
|
|
[ cmp eq reg 1 0x00000010 ]
|
|
|
|
-# tcp option mptcp subtype { 0, 2}
|
|
-__set%d test-inet 3 size 2
|
|
-__set%d test-inet 0
|
|
- element 00000000 : 0 [end] element 00000020 : 0 [end]
|
|
-inet
|
|
+# tcp option mptcp subtype { mp-capable, mp-join, remove-addr, mp-prio, mp-fail, mp-fastclose, mp-tcprst }
|
|
+__set%d test-ip4 3 size 7
|
|
+__set%d test-ip4 0
|
|
+ element 00000000 : 0 [end] element 00000010 : 0 [end] element 00000040 : 0 [end] element 00000050 : 0 [end] element 00000060 : 0 [end] element 00000070 : 0 [end] element 00000080 : 0 [end]
|
|
+ip test-ip4 input
|
|
[ exthdr load tcpopt 1b @ 30 + 2 => reg 1 ]
|
|
[ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
|
|
[ lookup reg 1 set __set%d ]
|