d9f08f29ae
* Thu Nov 07 2024 Phil Sutter <psutter@redhat.com> [1.1.1-1.el10] - monitor: Recognize flowtable add/del events (Phil Sutter) [RHEL-65346] - tests: py: Fix for storing payload into missing file (Phil Sutter) [RHEL-65346] - json: Support typeof in set and map types (Phil Sutter) [RHEL-65346] - json: collapse set element commands from parser (Phil Sutter) [RHEL-65346] - doc: extend description of fib expression (Phil Sutter) [RHEL-65346] - tests: monitor: fix up test case breakage (Phil Sutter) [RHEL-65346] - src: fix extended netlink error reporting with large set elements (Phil Sutter) [RHEL-65346] - rule: netlink attribute offset is uint32_t for struct nlerr_loc (Phil Sutter) [RHEL-65346] - mnl: update cmd_add_loc() to take struct nlmsghdr (Phil Sutter) [RHEL-65346] - mnl: rename to mnl_seqnum_alloc() to mnl_seqnum_inc() (Phil Sutter) [RHEL-65346] - src: collapse set element commands from parser (Phil Sutter) [RHEL-65346] - libnftables-json: fix raw payload expression documentation (Phil Sutter) [RHEL-65346] - tests: shell: fix spurious dump failure in vmap timeout test (Phil Sutter) [RHEL-65346] - Rebase onto version 1.1.1 (Phil Sutter) [RHEL-65346] Resolves: RHEL-65346
527 lines
17 KiB
Diff
527 lines
17 KiB
Diff
From d66b043a46f4b8e48ab96503613d4ea7483899d4 Mon Sep 17 00:00:00 2001
|
|
From: Phil Sutter <psutter@redhat.com>
|
|
Date: Thu, 7 Nov 2024 18:38:46 +0100
|
|
Subject: [PATCH] json: Support typeof in set and map types
|
|
|
|
JIRA: https://issues.redhat.com/browse/RHEL-65346
|
|
Upstream Status: nftables commit bb6312484af93a83a9ec8716f3887a43566a775a
|
|
|
|
commit bb6312484af93a83a9ec8716f3887a43566a775a
|
|
Author: Phil Sutter <phil@nwl.cc>
|
|
Date: Sat Sep 28 00:55:34 2024 +0200
|
|
|
|
json: Support typeof in set and map types
|
|
|
|
Implement this as a special "type" property value which is an object
|
|
with sole property "typeof". The latter's value is the JSON
|
|
representation of the expression in set->key, so for concatenated
|
|
typeofs it is a concat expression.
|
|
|
|
All this is a bit clumsy right now but it works and it should be
|
|
possible to tear it down a bit for more user-friendliness in a
|
|
compatible way by either replacing the concat expression by the array it
|
|
contains or even the whole "typeof" object - the parser would just
|
|
assume any object (or objects in an array) in the "type" property value
|
|
are expressions to extract a type from.
|
|
|
|
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
|
|
|
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
|
---
|
|
doc/libnftables-json.adoc | 7 ++-
|
|
src/json.c | 13 ++++-
|
|
src/parser_json.c | 9 +++
|
|
tests/monitor/testcases/map-expr.t | 2 +-
|
|
tests/monitor/testcases/set-concat-interval.t | 2 +-
|
|
.../maps/dumps/0012map_concat_0.json-nft | 21 +++++--
|
|
.../maps/dumps/0017_map_variable_0.json-nft | 18 +++++-
|
|
.../maps/dumps/named_limits.json-nft | 55 ++++++++++++++++---
|
|
.../dumps/typeof_maps_add_delete.json-nft | 9 ++-
|
|
.../maps/dumps/typeof_maps_update_0.json-nft | 9 ++-
|
|
.../maps/dumps/vmap_timeout.json-nft | 22 ++++++--
|
|
.../packetpath/dumps/set_lookups.json-nft | 42 +++++++++++---
|
|
.../sets/dumps/0048set_counters_0.json-nft | 9 ++-
|
|
.../testcases/sets/dumps/inner_0.json-nft | 34 ++++++++++--
|
|
.../set_element_timeout_updates.json-nft | 9 ++-
|
|
15 files changed, 220 insertions(+), 41 deletions(-)
|
|
|
|
diff --git a/doc/libnftables-json.adoc b/doc/libnftables-json.adoc
|
|
index 2f29ac0..244eb41 100644
|
|
--- a/doc/libnftables-json.adoc
|
|
+++ b/doc/libnftables-json.adoc
|
|
@@ -341,7 +341,7 @@ ____
|
|
"auto-merge":* 'BOOLEAN'
|
|
*}}*
|
|
|
|
-'SET_TYPE' := 'STRING' | *[* 'SET_TYPE_LIST' *]*
|
|
+'SET_TYPE' := 'STRING' | *[* 'SET_TYPE_LIST' *]* | *{ "typeof":* 'EXPRESSION' *}*
|
|
'SET_TYPE_LIST' := 'STRING' [*,* 'SET_TYPE_LIST' ]
|
|
'SET_POLICY' := *"performance"* | *"memory"*
|
|
'SET_FLAG_LIST' := 'SET_FLAG' [*,* 'SET_FLAG_LIST' ]
|
|
@@ -381,8 +381,9 @@ that they translate a unique key to a value.
|
|
Automatic merging of adjacent/overlapping set elements in interval sets.
|
|
|
|
==== TYPE
|
|
-The set type might be a string, such as *"ipv4_addr"* or an array
|
|
-consisting of strings (for concatenated types).
|
|
+The set type might be a string, such as *"ipv4_addr"*, an array
|
|
+consisting of strings (for concatenated types) or a *typeof* object containing
|
|
+an expression to extract the type from.
|
|
|
|
==== ELEM
|
|
A single set element might be given as string, integer or boolean value for
|
|
diff --git a/src/json.c b/src/json.c
|
|
index b1531ff..1f609bf 100644
|
|
--- a/src/json.c
|
|
+++ b/src/json.c
|
|
@@ -96,6 +96,17 @@ static json_t *set_dtype_json(const struct expr *key)
|
|
return root;
|
|
}
|
|
|
|
+static json_t *set_key_dtype_json(const struct set *set,
|
|
+ struct output_ctx *octx)
|
|
+{
|
|
+ bool use_typeof = set->key_typeof_valid;
|
|
+
|
|
+ if (!use_typeof)
|
|
+ return set_dtype_json(set->key);
|
|
+
|
|
+ return json_pack("{s:o}", "typeof", expr_print_json(set->key, octx));
|
|
+}
|
|
+
|
|
static json_t *stmt_print_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
{
|
|
char buf[1024];
|
|
@@ -158,7 +169,7 @@ static json_t *set_print_json(struct output_ctx *octx, const struct set *set)
|
|
"family", family2str(set->handle.family),
|
|
"name", set->handle.set.name,
|
|
"table", set->handle.table.name,
|
|
- "type", set_dtype_json(set->key),
|
|
+ "type", set_key_dtype_json(set, octx),
|
|
"handle", set->handle.handle.id);
|
|
|
|
if (set->comment)
|
|
diff --git a/src/parser_json.c b/src/parser_json.c
|
|
index 68c0600..02cfcd6 100644
|
|
--- a/src/parser_json.c
|
|
+++ b/src/parser_json.c
|
|
@@ -1731,7 +1731,16 @@ static struct expr *json_parse_dtype_expr(struct json_ctx *ctx, json_t *root)
|
|
compound_expr_add(expr, i);
|
|
}
|
|
return expr;
|
|
+ } else if (json_is_object(root)) {
|
|
+ const char *key;
|
|
+ json_t *val;
|
|
+
|
|
+ if (!json_unpack_stmt(ctx, root, &key, &val) &&
|
|
+ !strcmp(key, "typeof")) {
|
|
+ return json_parse_expr(ctx, val);
|
|
+ }
|
|
}
|
|
+
|
|
json_error(ctx, "Invalid set datatype.");
|
|
return NULL;
|
|
}
|
|
diff --git a/tests/monitor/testcases/map-expr.t b/tests/monitor/testcases/map-expr.t
|
|
index 8729c0b..d11ad0e 100644
|
|
--- a/tests/monitor/testcases/map-expr.t
|
|
+++ b/tests/monitor/testcases/map-expr.t
|
|
@@ -3,4 +3,4 @@ I add table ip t
|
|
I add map ip t m { typeof meta day . meta hour : verdict; flags interval; counter; }
|
|
O -
|
|
J {"add": {"table": {"family": "ip", "name": "t", "handle": 0}}}
|
|
-J {"add": {"map": {"family": "ip", "name": "m", "table": "t", "type": ["day", "hour"], "handle": 0, "map": "verdict", "flags": ["interval"], "stmt": [{"counter": null}]}}}
|
|
+J {"add": {"map": {"family": "ip", "name": "m", "table": "t", "type": {"typeof": {"concat": [{"meta": {"key": "day"}}, {"meta": {"key": "hour"}}]}}, "handle": 0, "map": "verdict", "flags": ["interval"], "stmt": [{"counter": null}]}}}
|
|
diff --git a/tests/monitor/testcases/set-concat-interval.t b/tests/monitor/testcases/set-concat-interval.t
|
|
index 75f3828..3542b82 100644
|
|
--- a/tests/monitor/testcases/set-concat-interval.t
|
|
+++ b/tests/monitor/testcases/set-concat-interval.t
|
|
@@ -10,6 +10,6 @@ I add map ip t s { typeof udp length . @ih,32,32 : verdict; flags interval; elem
|
|
O add map ip t s { typeof udp length . @ih,32,32 : verdict; flags interval; }
|
|
O add element ip t s { 20-80 . 0x14 : accept }
|
|
O add element ip t s { 1-10 . 0xa : drop }
|
|
-J {"add": {"map": {"family": "ip", "name": "s", "table": "t", "type": ["integer", "integer"], "handle": 0, "map": "verdict", "flags": ["interval"]}}}
|
|
+J {"add": {"map": {"family": "ip", "name": "s", "table": "t", "type": {"typeof": {"concat": [{"payload": {"protocol": "udp", "field": "length"}}, {"payload": {"base": "ih", "offset": 32, "len": 32}}]}}, "handle": 0, "map": "verdict", "flags": ["interval"]}}}
|
|
J {"add": {"element": {"family": "ip", "table": "t", "name": "s", "elem": {"set": [[{"concat": [{"range": [20, 80]}, 20]}, {"accept": null}]]}}}}
|
|
J {"add": {"element": {"family": "ip", "table": "t", "name": "s", "elem": {"set": [[{"concat": [{"range": [1, 10]}, 10]}, {"drop": null}]]}}}}
|
|
diff --git a/tests/shell/testcases/maps/dumps/0012map_concat_0.json-nft b/tests/shell/testcases/maps/dumps/0012map_concat_0.json-nft
|
|
index 0005223..88bf498 100644
|
|
--- a/tests/shell/testcases/maps/dumps/0012map_concat_0.json-nft
|
|
+++ b/tests/shell/testcases/maps/dumps/0012map_concat_0.json-nft
|
|
@@ -31,10 +31,23 @@
|
|
"family": "ip",
|
|
"name": "w",
|
|
"table": "x",
|
|
- "type": [
|
|
- "ipv4_addr",
|
|
- "mark"
|
|
- ],
|
|
+ "type": {
|
|
+ "typeof": {
|
|
+ "concat": [
|
|
+ {
|
|
+ "payload": {
|
|
+ "protocol": "ip",
|
|
+ "field": "saddr"
|
|
+ }
|
|
+ },
|
|
+ {
|
|
+ "meta": {
|
|
+ "key": "mark"
|
|
+ }
|
|
+ }
|
|
+ ]
|
|
+ }
|
|
+ },
|
|
"handle": 0,
|
|
"map": "verdict",
|
|
"flags": [
|
|
diff --git a/tests/shell/testcases/maps/dumps/0017_map_variable_0.json-nft b/tests/shell/testcases/maps/dumps/0017_map_variable_0.json-nft
|
|
index 725498c..8eacf61 100644
|
|
--- a/tests/shell/testcases/maps/dumps/0017_map_variable_0.json-nft
|
|
+++ b/tests/shell/testcases/maps/dumps/0017_map_variable_0.json-nft
|
|
@@ -19,7 +19,14 @@
|
|
"family": "ip",
|
|
"name": "y",
|
|
"table": "x",
|
|
- "type": "ipv4_addr",
|
|
+ "type": {
|
|
+ "typeof": {
|
|
+ "payload": {
|
|
+ "protocol": "ip",
|
|
+ "field": "saddr"
|
|
+ }
|
|
+ }
|
|
+ },
|
|
"handle": 0,
|
|
"map": "mark",
|
|
"elem": [
|
|
@@ -39,7 +46,14 @@
|
|
"family": "ip",
|
|
"name": "z",
|
|
"table": "x",
|
|
- "type": "ipv4_addr",
|
|
+ "type": {
|
|
+ "typeof": {
|
|
+ "payload": {
|
|
+ "protocol": "ip",
|
|
+ "field": "saddr"
|
|
+ }
|
|
+ }
|
|
+ },
|
|
"handle": 0,
|
|
"map": "mark",
|
|
"elem": [
|
|
diff --git a/tests/shell/testcases/maps/dumps/named_limits.json-nft b/tests/shell/testcases/maps/dumps/named_limits.json-nft
|
|
index 7fa1298..3c6845a 100644
|
|
--- a/tests/shell/testcases/maps/dumps/named_limits.json-nft
|
|
+++ b/tests/shell/testcases/maps/dumps/named_limits.json-nft
|
|
@@ -75,7 +75,14 @@
|
|
"family": "inet",
|
|
"name": "tarpit4",
|
|
"table": "filter",
|
|
- "type": "ipv4_addr",
|
|
+ "type": {
|
|
+ "typeof": {
|
|
+ "payload": {
|
|
+ "protocol": "ip",
|
|
+ "field": "saddr"
|
|
+ }
|
|
+ }
|
|
+ },
|
|
"handle": 0,
|
|
"size": 10000,
|
|
"flags": [
|
|
@@ -90,7 +97,14 @@
|
|
"family": "inet",
|
|
"name": "tarpit6",
|
|
"table": "filter",
|
|
- "type": "ipv6_addr",
|
|
+ "type": {
|
|
+ "typeof": {
|
|
+ "payload": {
|
|
+ "protocol": "ip6",
|
|
+ "field": "saddr"
|
|
+ }
|
|
+ }
|
|
+ },
|
|
"handle": 0,
|
|
"size": 10000,
|
|
"flags": [
|
|
@@ -105,11 +119,29 @@
|
|
"family": "inet",
|
|
"name": "addr4limit",
|
|
"table": "filter",
|
|
- "type": [
|
|
- "inet_proto",
|
|
- "ipv4_addr",
|
|
- "inet_service"
|
|
- ],
|
|
+ "type": {
|
|
+ "typeof": {
|
|
+ "concat": [
|
|
+ {
|
|
+ "meta": {
|
|
+ "key": "l4proto"
|
|
+ }
|
|
+ },
|
|
+ {
|
|
+ "payload": {
|
|
+ "protocol": "ip",
|
|
+ "field": "saddr"
|
|
+ }
|
|
+ },
|
|
+ {
|
|
+ "payload": {
|
|
+ "protocol": "tcp",
|
|
+ "field": "sport"
|
|
+ }
|
|
+ }
|
|
+ ]
|
|
+ }
|
|
+ },
|
|
"handle": 0,
|
|
"map": "limit",
|
|
"flags": [
|
|
@@ -244,7 +276,14 @@
|
|
"family": "inet",
|
|
"name": "saddr6limit",
|
|
"table": "filter",
|
|
- "type": "ipv6_addr",
|
|
+ "type": {
|
|
+ "typeof": {
|
|
+ "payload": {
|
|
+ "protocol": "ip6",
|
|
+ "field": "saddr"
|
|
+ }
|
|
+ }
|
|
+ },
|
|
"handle": 0,
|
|
"map": "limit",
|
|
"flags": [
|
|
diff --git a/tests/shell/testcases/maps/dumps/typeof_maps_add_delete.json-nft b/tests/shell/testcases/maps/dumps/typeof_maps_add_delete.json-nft
|
|
index b3204a2..effe02d 100644
|
|
--- a/tests/shell/testcases/maps/dumps/typeof_maps_add_delete.json-nft
|
|
+++ b/tests/shell/testcases/maps/dumps/typeof_maps_add_delete.json-nft
|
|
@@ -39,7 +39,14 @@
|
|
"family": "ip",
|
|
"name": "dynmark",
|
|
"table": "dynset",
|
|
- "type": "ipv4_addr",
|
|
+ "type": {
|
|
+ "typeof": {
|
|
+ "payload": {
|
|
+ "protocol": "ip",
|
|
+ "field": "daddr"
|
|
+ }
|
|
+ }
|
|
+ },
|
|
"handle": 0,
|
|
"map": "mark",
|
|
"size": 64,
|
|
diff --git a/tests/shell/testcases/maps/dumps/typeof_maps_update_0.json-nft b/tests/shell/testcases/maps/dumps/typeof_maps_update_0.json-nft
|
|
index 1d50477..7315146 100644
|
|
--- a/tests/shell/testcases/maps/dumps/typeof_maps_update_0.json-nft
|
|
+++ b/tests/shell/testcases/maps/dumps/typeof_maps_update_0.json-nft
|
|
@@ -50,7 +50,14 @@
|
|
"family": "ip",
|
|
"name": "sticky-set-svc-153CN2XYVUHRQ7UB",
|
|
"table": "kube-nfproxy-v4",
|
|
- "type": "ipv4_addr",
|
|
+ "type": {
|
|
+ "typeof": {
|
|
+ "payload": {
|
|
+ "protocol": "ip",
|
|
+ "field": "daddr"
|
|
+ }
|
|
+ }
|
|
+ },
|
|
"handle": 0,
|
|
"map": "mark",
|
|
"size": 65535,
|
|
diff --git a/tests/shell/testcases/maps/dumps/vmap_timeout.json-nft b/tests/shell/testcases/maps/dumps/vmap_timeout.json-nft
|
|
index 1c3aa59..71e9a9e 100644
|
|
--- a/tests/shell/testcases/maps/dumps/vmap_timeout.json-nft
|
|
+++ b/tests/shell/testcases/maps/dumps/vmap_timeout.json-nft
|
|
@@ -87,10 +87,24 @@
|
|
"family": "inet",
|
|
"name": "portaddrmap",
|
|
"table": "filter",
|
|
- "type": [
|
|
- "ipv4_addr",
|
|
- "inet_service"
|
|
- ],
|
|
+ "type": {
|
|
+ "typeof": {
|
|
+ "concat": [
|
|
+ {
|
|
+ "payload": {
|
|
+ "protocol": "ip",
|
|
+ "field": "daddr"
|
|
+ }
|
|
+ },
|
|
+ {
|
|
+ "payload": {
|
|
+ "protocol": "th",
|
|
+ "field": "dport"
|
|
+ }
|
|
+ }
|
|
+ ]
|
|
+ }
|
|
+ },
|
|
"handle": 0,
|
|
"map": "verdict",
|
|
"flags": [
|
|
diff --git a/tests/shell/testcases/packetpath/dumps/set_lookups.json-nft b/tests/shell/testcases/packetpath/dumps/set_lookups.json-nft
|
|
index 24363f9..bcf6914 100644
|
|
--- a/tests/shell/testcases/packetpath/dumps/set_lookups.json-nft
|
|
+++ b/tests/shell/testcases/packetpath/dumps/set_lookups.json-nft
|
|
@@ -60,10 +60,23 @@
|
|
"family": "ip",
|
|
"name": "s2",
|
|
"table": "t",
|
|
- "type": [
|
|
- "ipv4_addr",
|
|
- "iface_index"
|
|
- ],
|
|
+ "type": {
|
|
+ "typeof": {
|
|
+ "concat": [
|
|
+ {
|
|
+ "payload": {
|
|
+ "protocol": "ip",
|
|
+ "field": "saddr"
|
|
+ }
|
|
+ },
|
|
+ {
|
|
+ "meta": {
|
|
+ "key": "iif"
|
|
+ }
|
|
+ }
|
|
+ ]
|
|
+ }
|
|
+ },
|
|
"handle": 0,
|
|
"elem": [
|
|
{
|
|
@@ -113,10 +126,23 @@
|
|
"family": "ip",
|
|
"name": "nomatch",
|
|
"table": "t",
|
|
- "type": [
|
|
- "ipv4_addr",
|
|
- "iface_index"
|
|
- ],
|
|
+ "type": {
|
|
+ "typeof": {
|
|
+ "concat": [
|
|
+ {
|
|
+ "payload": {
|
|
+ "protocol": "ip",
|
|
+ "field": "saddr"
|
|
+ }
|
|
+ },
|
|
+ {
|
|
+ "meta": {
|
|
+ "key": "iif"
|
|
+ }
|
|
+ }
|
|
+ ]
|
|
+ }
|
|
+ },
|
|
"handle": 0,
|
|
"elem": [
|
|
{
|
|
diff --git a/tests/shell/testcases/sets/dumps/0048set_counters_0.json-nft b/tests/shell/testcases/sets/dumps/0048set_counters_0.json-nft
|
|
index 62a6a17..4be4112 100644
|
|
--- a/tests/shell/testcases/sets/dumps/0048set_counters_0.json-nft
|
|
+++ b/tests/shell/testcases/sets/dumps/0048set_counters_0.json-nft
|
|
@@ -31,7 +31,14 @@
|
|
"family": "ip",
|
|
"name": "y",
|
|
"table": "x",
|
|
- "type": "ipv4_addr",
|
|
+ "type": {
|
|
+ "typeof": {
|
|
+ "payload": {
|
|
+ "protocol": "ip",
|
|
+ "field": "saddr"
|
|
+ }
|
|
+ }
|
|
+ },
|
|
"handle": 0,
|
|
"elem": [
|
|
{
|
|
diff --git a/tests/shell/testcases/sets/dumps/inner_0.json-nft b/tests/shell/testcases/sets/dumps/inner_0.json-nft
|
|
index 8d84e1c..e5dc198 100644
|
|
--- a/tests/shell/testcases/sets/dumps/inner_0.json-nft
|
|
+++ b/tests/shell/testcases/sets/dumps/inner_0.json-nft
|
|
@@ -27,10 +27,26 @@
|
|
"family": "netdev",
|
|
"name": "x",
|
|
"table": "x",
|
|
- "type": [
|
|
- "ipv4_addr",
|
|
- "ipv4_addr"
|
|
- ],
|
|
+ "type": {
|
|
+ "typeof": {
|
|
+ "concat": [
|
|
+ {
|
|
+ "payload": {
|
|
+ "tunnel": "vxlan",
|
|
+ "protocol": "ip",
|
|
+ "field": "saddr"
|
|
+ }
|
|
+ },
|
|
+ {
|
|
+ "payload": {
|
|
+ "tunnel": "vxlan",
|
|
+ "protocol": "ip",
|
|
+ "field": "daddr"
|
|
+ }
|
|
+ }
|
|
+ ]
|
|
+ }
|
|
+ },
|
|
"handle": 0,
|
|
"elem": [
|
|
{
|
|
@@ -47,7 +63,15 @@
|
|
"family": "netdev",
|
|
"name": "y",
|
|
"table": "x",
|
|
- "type": "ipv4_addr",
|
|
+ "type": {
|
|
+ "typeof": {
|
|
+ "payload": {
|
|
+ "tunnel": "vxlan",
|
|
+ "protocol": "ip",
|
|
+ "field": "saddr"
|
|
+ }
|
|
+ }
|
|
+ },
|
|
"handle": 0,
|
|
"size": 65535,
|
|
"flags": [
|
|
diff --git a/tests/shell/testcases/sets/dumps/set_element_timeout_updates.json-nft b/tests/shell/testcases/sets/dumps/set_element_timeout_updates.json-nft
|
|
index aa90829..d92d8d7 100644
|
|
--- a/tests/shell/testcases/sets/dumps/set_element_timeout_updates.json-nft
|
|
+++ b/tests/shell/testcases/sets/dumps/set_element_timeout_updates.json-nft
|
|
@@ -31,7 +31,14 @@
|
|
"family": "ip",
|
|
"name": "s",
|
|
"table": "t",
|
|
- "type": "ipv4_addr",
|
|
+ "type": {
|
|
+ "typeof": {
|
|
+ "payload": {
|
|
+ "protocol": "ip",
|
|
+ "field": "saddr"
|
|
+ }
|
|
+ }
|
|
+ },
|
|
"handle": 0,
|
|
"flags": [
|
|
"timeout"
|