netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [nft PATCH 0/9] Support wildcard netdev hooks and events
@ 2024-10-02 19:38 Phil Sutter
  2024-10-02 19:38 ` [nft PATCH 1/9] json: Support typeof in set and map types Phil Sutter
                   ` (10 more replies)
  0 siblings, 11 replies; 14+ messages in thread
From: Phil Sutter @ 2024-10-02 19:38 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

This series is the second (and last?) step of enabling support for
name-based and wildcard interface hooks in user space. It depends on the
previously sent series for libnftnl.

Patches 1-4 are fallout, fixing for deficits in different areas.

Patches 5 and 6 extend parser and serializer to accept and correctly
pass interface wildcards on to the kernel.

Patch 7 adjusts shell test cases to the different behaviour (removed
interfaces no longer disappearing from hook specs), mostly stored dump
adjustments.

Patches 8 and 9 extend nft monitor to print NEWDEV/DELDEV events and
extend the monitor testsuite to cover the code.

Phil Sutter (9):
  json: Support typeof in set and map types
  tests: py: Fix for storing payload into missing file
  monitor: Recognize flowtable add/del events
  tests: monitor: Run in own netns
  mnl: Support simple wildcards in netdev hooks
  parser_bison: Accept ASTERISK_STRING in flowtable_expr_member
  tests: shell: Adjust to ifname-based flowtables
  tests: monitor: Support running external commands
  monitor: Support NFT_MSG_(NEW|DEL)DEV events

 doc/libnftables-json.adoc                     |   7 +-
 include/json.h                                |  20 +++
 include/linux/netfilter/nf_tables.h           |  10 ++
 include/netlink.h                             |   1 +
 include/rule.h                                |   1 +
 src/json.c                                    |  46 ++++++-
 src/mnl.c                                     |  19 ++-
 src/monitor.c                                 | 125 ++++++++++++++++++
 src/parser_bison.y                            |  11 +-
 src/parser_json.c                             |  15 +++
 src/rule.c                                    |  15 +++
 tests/monitor/run-tests.sh                    |  72 +++++++++-
 tests/monitor/testcases/chain-netdev.t        |  66 +++++++++
 tests/monitor/testcases/flowtable-simple.t    |  66 +++++++++
 tests/monitor/testcases/map-expr.t            |   2 +-
 tests/monitor/testcases/set-concat-interval.t |   3 +
 tests/py/nft-test.py                          |   5 +-
 .../chains/dumps/netdev_chain_0.json-nft      |  17 +++
 .../testcases/chains/dumps/netdev_chain_0.nft |   3 +
 .../netdev_chain_dormant_autoremove.json-nft  |   5 +-
 .../dumps/netdev_chain_dormant_autoremove.nft |   2 +-
 .../dumps/0012flowtable_variable_0.json-nft   |  10 +-
 .../dumps/0012flowtable_variable_0.nft        |   4 +-
 .../testcases/json/dumps/netdev.json-nft      |  13 ++
 tests/shell/testcases/json/dumps/netdev.nft   |   3 +
 .../listing/dumps/0020flowtable_0.json-nft    |   6 +-
 .../listing/dumps/0020flowtable_0.nft         |   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 +-
 tests/shell/testcases/transactions/0050rule_1 |  19 ---
 .../transactions/dumps/0050rule_1.json-nft    |  11 --
 .../transactions/dumps/0050rule_1.nft         |   0
 40 files changed, 706 insertions(+), 101 deletions(-)
 create mode 100644 tests/monitor/testcases/chain-netdev.t
 create mode 100644 tests/monitor/testcases/flowtable-simple.t
 delete mode 100755 tests/shell/testcases/transactions/0050rule_1
 delete mode 100644 tests/shell/testcases/transactions/dumps/0050rule_1.json-nft
 delete mode 100644 tests/shell/testcases/transactions/dumps/0050rule_1.nft

-- 
2.43.0


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

* [nft PATCH 1/9] json: Support typeof in set and map types
  2024-10-02 19:38 [nft PATCH 0/9] Support wildcard netdev hooks and events Phil Sutter
@ 2024-10-02 19:38 ` Phil Sutter
  2024-10-02 19:38 ` [nft PATCH 2/9] tests: py: Fix for storing payload into missing file Phil Sutter
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Phil Sutter @ 2024-10-02 19:38 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

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>
---
 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 |  3 +
 .../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, 222 insertions(+), 40 deletions(-)

diff --git a/doc/libnftables-json.adoc b/doc/libnftables-json.adoc
index a8a6165fde59d..593d407c924e9 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 b1531ff3f4c9e..1f609bf2b03e9 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 bbe3b1c59192c..f8200db1fe114 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -1729,7 +1729,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 8729c0b44ee2c..d11ad0ebc0d57 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 763dc319f0d13..3542b8225ebd1 100644
--- a/tests/monitor/testcases/set-concat-interval.t
+++ b/tests/monitor/testcases/set-concat-interval.t
@@ -10,3 +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": {"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 000522365df9f..88bf4984dbde7 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 725498cdcbef8..8eacf612d12fb 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 7fa1298103832..3c6845ac43b42 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 b3204a283d0ad..effe02dcf8364 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 1d50477d783df..731514663b1aa 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 1c3aa590f846e..71e9a9ee9f21b 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 24363f9071b22..bcf6914e95cb9 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 62a6a177b7776..4be4112bf7935 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 8d84e1ccecb9f..e5dc198f436be 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 aa908297e49ea..d92d8d7a54940 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"
-- 
2.43.0


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

* [nft PATCH 2/9] tests: py: Fix for storing payload into missing file
  2024-10-02 19:38 [nft PATCH 0/9] Support wildcard netdev hooks and events Phil Sutter
  2024-10-02 19:38 ` [nft PATCH 1/9] json: Support typeof in set and map types Phil Sutter
@ 2024-10-02 19:38 ` Phil Sutter
  2024-10-02 19:38 ` [nft PATCH 3/9] monitor: Recognize flowtable add/del events Phil Sutter
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Phil Sutter @ 2024-10-02 19:38 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

When running a test for which no corresponding *.payload file exists,
the *.payload.got file name was incorrectly constructed due to
'payload_path' variable not being set.

Fixes: 2cfab7a3e10fc ("tests/py: Write dissenting payload into the right file")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 tests/py/nft-test.py | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/tests/py/nft-test.py b/tests/py/nft-test.py
index 00799e281d566..7acdb77f2d0a2 100755
--- a/tests/py/nft-test.py
+++ b/tests/py/nft-test.py
@@ -769,10 +769,9 @@ def set_delete_elements(set_element, set_name, table, filename=None,
 
     if rule[1].strip() == "ok":
         payload_expected = None
-        payload_path = None
+        payload_path = "%s.payload" % filename_path
         try:
-            payload_log = open("%s.payload" % filename_path)
-            payload_path = payload_log.name
+            payload_log = open(payload_path)
             payload_expected = payload_find_expected(payload_log, rule[0])
         except:
             payload_log = None
-- 
2.43.0


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

* [nft PATCH 3/9] monitor: Recognize flowtable add/del events
  2024-10-02 19:38 [nft PATCH 0/9] Support wildcard netdev hooks and events Phil Sutter
  2024-10-02 19:38 ` [nft PATCH 1/9] json: Support typeof in set and map types Phil Sutter
  2024-10-02 19:38 ` [nft PATCH 2/9] tests: py: Fix for storing payload into missing file Phil Sutter
@ 2024-10-02 19:38 ` Phil Sutter
  2024-10-02 19:38 ` [nft PATCH 4/9] tests: monitor: Run in own netns Phil Sutter
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Phil Sutter @ 2024-10-02 19:38 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

These were entirely ignored before, add the necessary code analogous to
e.g. objects.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 include/json.h                             | 10 ++++
 include/netlink.h                          |  1 +
 include/rule.h                             |  1 +
 src/json.c                                 |  6 +++
 src/monitor.c                              | 61 ++++++++++++++++++++++
 src/parser_json.c                          |  6 +++
 src/rule.c                                 | 15 ++++++
 tests/monitor/testcases/flowtable-simple.t | 10 ++++
 8 files changed, 110 insertions(+)
 create mode 100644 tests/monitor/testcases/flowtable-simple.t

diff --git a/include/json.h b/include/json.h
index 39be8928e8ee0..0670b8714519b 100644
--- a/include/json.h
+++ b/include/json.h
@@ -11,6 +11,7 @@ struct nlmsghdr;
 struct rule;
 struct set;
 struct obj;
+struct flowtable;
 struct stmt;
 struct symbol_table;
 struct table;
@@ -113,6 +114,8 @@ void monitor_print_element_json(struct netlink_mon_handler *monh,
 				const char *cmd, struct set *s);
 void monitor_print_obj_json(struct netlink_mon_handler *monh,
 			    const char *cmd, struct obj *o);
+void monitor_print_flowtable_json(struct netlink_mon_handler *monh,
+				  const char *cmd, struct flowtable *ft);
 void monitor_print_rule_json(struct netlink_mon_handler *monh,
 			     const char *cmd, struct rule *r);
 
@@ -254,6 +257,13 @@ static inline void monitor_print_obj_json(struct netlink_mon_handler *monh,
 	/* empty */
 }
 
+static inline void
+monitor_print_flowtable_json(struct netlink_mon_handler *monh,
+			     const char *cmd, struct flowtable *ft)
+{
+	/* empty */
+}
+
 static inline void monitor_print_rule_json(struct netlink_mon_handler *monh,
 					   const char *cmd, struct rule *r)
 {
diff --git a/include/netlink.h b/include/netlink.h
index cf7ba3693885a..e9667a24b0d11 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -97,6 +97,7 @@ extern struct nftnl_table *netlink_table_alloc(const struct nlmsghdr *nlh);
 extern struct nftnl_chain *netlink_chain_alloc(const struct nlmsghdr *nlh);
 extern struct nftnl_set *netlink_set_alloc(const struct nlmsghdr *nlh);
 extern struct nftnl_obj *netlink_obj_alloc(const struct nlmsghdr *nlh);
+extern struct nftnl_flowtable *netlink_flowtable_alloc(const struct nlmsghdr *nlh);
 extern struct nftnl_rule *netlink_rule_alloc(const struct nlmsghdr *nlh);
 
 struct nft_data_linearize {
diff --git a/include/rule.h b/include/rule.h
index 5b3e12b5d7dcf..75166b48446f5 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -551,6 +551,7 @@ extern struct flowtable *flowtable_lookup_fuzzy(const char *ft_name,
 						const struct table **table);
 
 void flowtable_print(const struct flowtable *n, struct output_ctx *octx);
+void flowtable_print_plain(const struct flowtable *ft, struct output_ctx *octx);
 
 /**
  * enum cmd_ops - command operations
diff --git a/src/json.c b/src/json.c
index 1f609bf2b03e9..64a6888f9e0ac 100644
--- a/src/json.c
+++ b/src/json.c
@@ -2108,6 +2108,12 @@ void monitor_print_obj_json(struct netlink_mon_handler *monh,
 	monitor_print_json(monh, cmd, obj_print_json(o));
 }
 
+void monitor_print_flowtable_json(struct netlink_mon_handler *monh,
+				  const char *cmd, struct flowtable *ft)
+{
+	monitor_print_json(monh, cmd, flowtable_print_json(ft));
+}
+
 void monitor_print_rule_json(struct netlink_mon_handler *monh,
 			     const char *cmd, struct rule *r)
 {
diff --git a/src/monitor.c b/src/monitor.c
index 2fc16d6776a28..a787db8cbf5a3 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -127,6 +127,19 @@ struct nftnl_obj *netlink_obj_alloc(const struct nlmsghdr *nlh)
 	return nlo;
 }
 
+struct nftnl_flowtable *netlink_flowtable_alloc(const struct nlmsghdr *nlh)
+{
+	struct nftnl_flowtable *nlf;
+
+	nlf = nftnl_flowtable_alloc();
+	if (nlf == NULL)
+		memory_allocation_error();
+	if (nftnl_flowtable_nlmsg_parse(nlh, nlf) < 0)
+		netlink_abi_error();
+
+	return nlf;
+}
+
 static uint32_t netlink_msg2nftnl_of(uint32_t type, uint16_t flags)
 {
 	switch (type) {
@@ -542,6 +555,50 @@ static int netlink_events_obj_cb(const struct nlmsghdr *nlh, int type,
 	return MNL_CB_OK;
 }
 
+static int netlink_events_flowtable_cb(const struct nlmsghdr *nlh, int type,
+				       struct netlink_mon_handler *monh)
+{
+	const char *family, *cmd;
+	struct nftnl_flowtable *nlf;
+	struct flowtable *ft;
+
+	nlf = netlink_flowtable_alloc(nlh);
+
+	ft = netlink_delinearize_flowtable(monh->ctx, nlf);
+	if (!ft) {
+		nftnl_flowtable_free(nlf);
+		return MNL_CB_ERROR;
+	}
+	family = family2str(ft->handle.family);
+	cmd = netlink_msg2cmd(type, nlh->nlmsg_flags);
+
+	switch (monh->format) {
+	case NFTNL_OUTPUT_DEFAULT:
+		nft_mon_print(monh, "%s ", cmd);
+
+		switch (type) {
+		case NFT_MSG_NEWFLOWTABLE:
+			flowtable_print_plain(ft, &monh->ctx->nft->output);
+			break;
+		case NFT_MSG_DELFLOWTABLE:
+			nft_mon_print(monh, "flowtable %s %s %s", family,
+				      ft->handle.table.name,
+				      ft->handle.flowtable.name);
+			break;
+		}
+		nft_mon_print(monh, "\n");
+		break;
+	case NFTNL_OUTPUT_JSON:
+		monitor_print_flowtable_json(monh, cmd, ft);
+		if (!nft_output_echo(&monh->ctx->nft->output))
+			nft_mon_print(monh, "\n");
+		break;
+	}
+	flowtable_free(ft);
+	nftnl_flowtable_free(nlf);
+	return MNL_CB_OK;
+}
+
 static void rule_map_decompose_cb(struct set *s, void *data)
 {
 	if (!set_is_anonymous(s->flags))
@@ -962,6 +1019,10 @@ static int netlink_events_cb(const struct nlmsghdr *nlh, void *data)
 	case NFT_MSG_DELOBJ:
 		ret = netlink_events_obj_cb(nlh, type, monh);
 		break;
+	case NFT_MSG_NEWFLOWTABLE:
+	case NFT_MSG_DELFLOWTABLE:
+		ret = netlink_events_flowtable_cb(nlh, type, monh);
+		break;
 	case NFT_MSG_NEWGEN:
 		ret = netlink_events_newgen_cb(nlh, type, monh);
 		break;
diff --git a/src/parser_json.c b/src/parser_json.c
index f8200db1fe114..bcc216e12e51c 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -4421,6 +4421,7 @@ static int json_echo_error(struct netlink_mon_handler *monh,
 
 static uint64_t handle_from_nlmsg(const struct nlmsghdr *nlh)
 {
+	struct nftnl_flowtable *nlf;
 	struct nftnl_table *nlt;
 	struct nftnl_chain *nlc;
 	struct nftnl_rule *nlr;
@@ -4457,6 +4458,11 @@ static uint64_t handle_from_nlmsg(const struct nlmsghdr *nlh)
 		handle = nftnl_obj_get_u64(nlo, NFTNL_OBJ_HANDLE);
 		nftnl_obj_free(nlo);
 		break;
+	case NFT_MSG_NEWFLOWTABLE:
+		nlf = netlink_flowtable_alloc(nlh);
+		handle = nftnl_flowtable_get_u64(nlf, NFTNL_FLOWTABLE_HANDLE);
+		nftnl_flowtable_free(nlf);
+		break;
 	}
 	return handle;
 }
diff --git a/src/rule.c b/src/rule.c
index 9bc160ec0d888..dc6b9d89fc967 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -2155,6 +2155,21 @@ void flowtable_print(const struct flowtable *s, struct output_ctx *octx)
 	do_flowtable_print(s, &opts, octx);
 }
 
+void flowtable_print_plain(const struct flowtable *ft, struct output_ctx *octx)
+{
+	struct print_fmt_options opts = {
+		.tab		= "",
+		.nl		= " ",
+		.table		= ft->handle.table.name,
+		.family		= family2str(ft->handle.family),
+		.stmt_separator = "; ",
+	};
+
+	flowtable_print_declaration(ft, &opts, octx);
+	nft_print(octx, "}");
+}
+
+
 struct flowtable *flowtable_lookup_fuzzy(const char *ft_name,
 					 const struct nft_cache *cache,
 					 const struct table **t)
diff --git a/tests/monitor/testcases/flowtable-simple.t b/tests/monitor/testcases/flowtable-simple.t
new file mode 100644
index 0000000000000..df8eccbd91e0a
--- /dev/null
+++ b/tests/monitor/testcases/flowtable-simple.t
@@ -0,0 +1,10 @@
+# setup first
+I add table ip t
+I add flowtable ip t ft { hook ingress priority 0; devices = { lo }; }
+O -
+J {"add": {"table": {"family": "ip", "name": "t", "handle": 0}}}
+J {"add": {"flowtable": {"family": "ip", "name": "ft", "table": "t", "handle": 0, "hook": "ingress", "prio": 0, "dev": "lo"}}}
+
+I delete flowtable ip t ft
+O -
+J {"delete": {"flowtable": {"family": "ip", "name": "ft", "table": "t", "handle": 0, "hook": "ingress", "prio": 0, "dev": "lo"}}}
-- 
2.43.0


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

* [nft PATCH 4/9] tests: monitor: Run in own netns
  2024-10-02 19:38 [nft PATCH 0/9] Support wildcard netdev hooks and events Phil Sutter
                   ` (2 preceding siblings ...)
  2024-10-02 19:38 ` [nft PATCH 3/9] monitor: Recognize flowtable add/del events Phil Sutter
@ 2024-10-02 19:38 ` Phil Sutter
  2024-10-02 19:38 ` [nft PATCH 5/9] mnl: Support simple wildcards in netdev hooks Phil Sutter
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Phil Sutter @ 2024-10-02 19:38 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Have the script call itself prefixed by unshare. This won't prevent
clashing test case contents, but at least leave the host netns alone.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 tests/monitor/run-tests.sh | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/tests/monitor/run-tests.sh b/tests/monitor/run-tests.sh
index f1ac790acf80c..214512d269e8d 100755
--- a/tests/monitor/run-tests.sh
+++ b/tests/monitor/run-tests.sh
@@ -120,6 +120,14 @@ echo_run_test() {
 	return $rc
 }
 
+netns=true
+for arg in "$@"; do
+	[[ "$arg" == "--no-netns" ]] && netns=false
+done
+if $netns; then
+	exec unshare -n $0 --no-netns "$@"
+fi
+
 testcases=""
 while [ -n "$1" ]; do
 	case "$1" in
@@ -131,6 +139,9 @@ while [ -n "$1" ]; do
 		test_json=true
 		shift
 		;;
+	--no-netns)
+		shift
+		;;
 	-H|--host)
 		nft=nft
 		shift
-- 
2.43.0


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

* [nft PATCH 5/9] mnl: Support simple wildcards in netdev hooks
  2024-10-02 19:38 [nft PATCH 0/9] Support wildcard netdev hooks and events Phil Sutter
                   ` (3 preceding siblings ...)
  2024-10-02 19:38 ` [nft PATCH 4/9] tests: monitor: Run in own netns Phil Sutter
@ 2024-10-02 19:38 ` Phil Sutter
  2024-10-02 19:38 ` [nft PATCH 6/9] parser_bison: Accept ASTERISK_STRING in flowtable_expr_member Phil Sutter
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Phil Sutter @ 2024-10-02 19:38 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

When building NFTA_FLOWTABLE_HOOK_DEVS, NFTA_HOOK_DEV or NFTA_HOOK_DEVS
attributes, detect trailing asterisks in interface names and reduce
attribute length accordingly. Kernel will use strncmp(), effectively
performing a prefix search this way.

Deserialization (i.e., appending asterisk to interface names which don't
include a trailing nul-char) happens in libnftnl.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 src/mnl.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/src/mnl.c b/src/mnl.c
index db53a60b43cb9..4faf027ce1027 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -787,18 +787,24 @@ static void mnl_nft_chain_devs_build(struct nlmsghdr *nlh, struct cmd *cmd)
 {
 	const struct expr *dev_expr = cmd->chain->dev_expr;
 	const struct nft_dev *dev_array;
+	int i, len, num_devs = 0;
 	struct nlattr *nest_dev;
-	int i, num_devs = 0;
 
 	dev_array = nft_dev_array(dev_expr, &num_devs);
 	if (num_devs == 1) {
 		cmd_add_loc(cmd, nlh->nlmsg_len, dev_array[0].location);
-		mnl_attr_put_strz(nlh, NFTA_HOOK_DEV, dev_array[0].ifname);
+		len = strlen(dev_array[0].ifname) + 1;
+		if (dev_array[0].ifname[len - 2] == '*')
+			len -= 2;
+		mnl_attr_put(nlh, NFTA_HOOK_DEV, len, dev_array[0].ifname);
 	} else {
 		nest_dev = mnl_attr_nest_start(nlh, NFTA_HOOK_DEVS);
 		for (i = 0; i < num_devs; i++) {
 			cmd_add_loc(cmd, nlh->nlmsg_len, dev_array[i].location);
-			mnl_attr_put_strz(nlh, NFTA_DEVICE_NAME, dev_array[i].ifname);
+			len = strlen(dev_array[i].ifname) + 1;
+			if (dev_array[i].ifname[len - 2] == '*')
+				len -= 2;
+			mnl_attr_put(nlh, NFTA_DEVICE_NAME, len, dev_array[i].ifname);
 			mnl_attr_nest_end(nlh, nest_dev);
 		}
 	}
@@ -1999,14 +2005,17 @@ static void mnl_nft_ft_devs_build(struct nlmsghdr *nlh, struct cmd *cmd)
 {
 	const struct expr *dev_expr = cmd->flowtable->dev_expr;
 	const struct nft_dev *dev_array;
+	int i, len, num_devs = 0;
 	struct nlattr *nest_dev;
-	int i, num_devs= 0;
 
 	dev_array = nft_dev_array(dev_expr, &num_devs);
 	nest_dev = mnl_attr_nest_start(nlh, NFTA_FLOWTABLE_HOOK_DEVS);
 	for (i = 0; i < num_devs; i++) {
 		cmd_add_loc(cmd, nlh->nlmsg_len, dev_array[i].location);
-		mnl_attr_put_strz(nlh, NFTA_DEVICE_NAME, dev_array[i].ifname);
+		len = strlen(dev_array[i].ifname) + 1;
+		if (dev_array[i].ifname[len - 2] == '*')
+			len -= 2;
+		mnl_attr_put(nlh, NFTA_DEVICE_NAME, len, dev_array[i].ifname);
 	}
 
 	mnl_attr_nest_end(nlh, nest_dev);
-- 
2.43.0


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

* [nft PATCH 6/9] parser_bison: Accept ASTERISK_STRING in flowtable_expr_member
  2024-10-02 19:38 [nft PATCH 0/9] Support wildcard netdev hooks and events Phil Sutter
                   ` (4 preceding siblings ...)
  2024-10-02 19:38 ` [nft PATCH 5/9] mnl: Support simple wildcards in netdev hooks Phil Sutter
@ 2024-10-02 19:38 ` Phil Sutter
  2024-10-02 19:38 ` [nft PATCH 7/9] tests: shell: Adjust to ifname-based flowtables Phil Sutter
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Phil Sutter @ 2024-10-02 19:38 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

All clauses are identical, so instead of adding a third one for
ASTERISK_STRING, use a single one for 'string' (which combines all three
variants).

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 src/parser_bison.y | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/src/parser_bison.y b/src/parser_bison.y
index e2936d10efe4c..d9cf2cd25c2f0 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -2477,16 +2477,7 @@ flowtable_list_expr	:	flowtable_expr_member
 			|	flowtable_list_expr	COMMA	opt_newline
 			;
 
-flowtable_expr_member	:	QUOTED_STRING
-			{
-				struct expr *expr = ifname_expr_alloc(&@$, state->msgs, $1);
-
-				if (!expr)
-					YYERROR;
-
-				$$ = expr;
-			}
-			|	STRING
+flowtable_expr_member	:	string
 			{
 				struct expr *expr = ifname_expr_alloc(&@$, state->msgs, $1);
 
-- 
2.43.0


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

* [nft PATCH 7/9] tests: shell: Adjust to ifname-based flowtables
  2024-10-02 19:38 [nft PATCH 0/9] Support wildcard netdev hooks and events Phil Sutter
                   ` (5 preceding siblings ...)
  2024-10-02 19:38 ` [nft PATCH 6/9] parser_bison: Accept ASTERISK_STRING in flowtable_expr_member Phil Sutter
@ 2024-10-02 19:38 ` Phil Sutter
  2024-10-02 19:38 ` [nft PATCH 8/9] tests: monitor: Support running external commands Phil Sutter
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Phil Sutter @ 2024-10-02 19:38 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Removed interfaces will remain in place in dumps. Also drop
transactions/0050rule_1 test entirely: It won't fail anymore as the
flowtable is accepted despite the non-existent interfaces and thus the
test as a whole does not work anymore.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 .../chains/dumps/netdev_chain_0.json-nft      | 17 +++++++++++++++++
 .../testcases/chains/dumps/netdev_chain_0.nft |  3 +++
 .../netdev_chain_dormant_autoremove.json-nft  |  5 ++++-
 .../dumps/netdev_chain_dormant_autoremove.nft |  2 +-
 .../dumps/0012flowtable_variable_0.json-nft   | 10 ++++++++--
 .../dumps/0012flowtable_variable_0.nft        |  4 ++--
 .../testcases/json/dumps/netdev.json-nft      | 13 +++++++++++++
 tests/shell/testcases/json/dumps/netdev.nft   |  3 +++
 .../listing/dumps/0020flowtable_0.json-nft    |  6 ++++--
 .../listing/dumps/0020flowtable_0.nft         |  2 ++
 tests/shell/testcases/transactions/0050rule_1 | 19 -------------------
 .../transactions/dumps/0050rule_1.json-nft    | 11 -----------
 .../transactions/dumps/0050rule_1.nft         |  0
 13 files changed, 57 insertions(+), 38 deletions(-)
 delete mode 100755 tests/shell/testcases/transactions/0050rule_1
 delete mode 100644 tests/shell/testcases/transactions/dumps/0050rule_1.json-nft
 delete mode 100644 tests/shell/testcases/transactions/dumps/0050rule_1.nft

diff --git a/tests/shell/testcases/chains/dumps/netdev_chain_0.json-nft b/tests/shell/testcases/chains/dumps/netdev_chain_0.json-nft
index 7d78bd6757034..13e9f6bb016f7 100644
--- a/tests/shell/testcases/chains/dumps/netdev_chain_0.json-nft
+++ b/tests/shell/testcases/chains/dumps/netdev_chain_0.json-nft
@@ -13,6 +13,23 @@
         "name": "x",
         "handle": 0
       }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "x",
+        "name": "y",
+        "handle": 0,
+        "dev": [
+          "d0",
+          "d1",
+          "d2"
+        ],
+        "type": "filter",
+        "hook": "ingress",
+        "prio": 0,
+        "policy": "accept"
+      }
     }
   ]
 }
diff --git a/tests/shell/testcases/chains/dumps/netdev_chain_0.nft b/tests/shell/testcases/chains/dumps/netdev_chain_0.nft
index aa571e00885fe..6606d5bc3f608 100644
--- a/tests/shell/testcases/chains/dumps/netdev_chain_0.nft
+++ b/tests/shell/testcases/chains/dumps/netdev_chain_0.nft
@@ -1,2 +1,5 @@
 table netdev x {
+	chain y {
+		type filter hook ingress devices = { d0, d1, d2 } priority filter; policy accept;
+	}
 }
diff --git a/tests/shell/testcases/chains/dumps/netdev_chain_dormant_autoremove.json-nft b/tests/shell/testcases/chains/dumps/netdev_chain_dormant_autoremove.json-nft
index 9151d42f17d91..88b8958f4d86e 100644
--- a/tests/shell/testcases/chains/dumps/netdev_chain_dormant_autoremove.json-nft
+++ b/tests/shell/testcases/chains/dumps/netdev_chain_dormant_autoremove.json-nft
@@ -21,7 +21,10 @@
         "table": "test",
         "name": "ingress",
         "handle": 0,
-        "dev": "dummy1",
+        "dev": [
+          "dummy0",
+          "dummy1"
+        ],
         "type": "filter",
         "hook": "ingress",
         "prio": 0,
diff --git a/tests/shell/testcases/chains/dumps/netdev_chain_dormant_autoremove.nft b/tests/shell/testcases/chains/dumps/netdev_chain_dormant_autoremove.nft
index aad7cb6337734..f4bd9556b3e03 100644
--- a/tests/shell/testcases/chains/dumps/netdev_chain_dormant_autoremove.nft
+++ b/tests/shell/testcases/chains/dumps/netdev_chain_dormant_autoremove.nft
@@ -2,6 +2,6 @@ table netdev test {
 	flags dormant
 
 	chain ingress {
-		type filter hook ingress device "dummy1" priority filter; policy drop;
+		type filter hook ingress devices = { dummy0, dummy1 } priority filter; policy drop;
 	}
 }
diff --git a/tests/shell/testcases/flowtable/dumps/0012flowtable_variable_0.json-nft b/tests/shell/testcases/flowtable/dumps/0012flowtable_variable_0.json-nft
index 10f1df98874ab..20da08fb2fc29 100644
--- a/tests/shell/testcases/flowtable/dumps/0012flowtable_variable_0.json-nft
+++ b/tests/shell/testcases/flowtable/dumps/0012flowtable_variable_0.json-nft
@@ -22,7 +22,10 @@
         "handle": 0,
         "hook": "ingress",
         "prio": 0,
-        "dev": "lo"
+        "dev": [
+          "dummy1",
+          "lo"
+        ]
       }
     },
     {
@@ -40,7 +43,10 @@
         "handle": 0,
         "hook": "ingress",
         "prio": 0,
-        "dev": "lo"
+        "dev": [
+          "dummy1",
+          "lo"
+        ]
       }
     }
   ]
diff --git a/tests/shell/testcases/flowtable/dumps/0012flowtable_variable_0.nft b/tests/shell/testcases/flowtable/dumps/0012flowtable_variable_0.nft
index df1c51a247033..1cbb2f1103f03 100644
--- a/tests/shell/testcases/flowtable/dumps/0012flowtable_variable_0.nft
+++ b/tests/shell/testcases/flowtable/dumps/0012flowtable_variable_0.nft
@@ -1,14 +1,14 @@
 table ip filter1 {
 	flowtable Main_ft1 {
 		hook ingress priority filter
-		devices = { lo }
+		devices = { dummy1, lo }
 		counter
 	}
 }
 table ip filter2 {
 	flowtable Main_ft2 {
 		hook ingress priority filter
-		devices = { lo }
+		devices = { dummy1, lo }
 		counter
 	}
 }
diff --git a/tests/shell/testcases/json/dumps/netdev.json-nft b/tests/shell/testcases/json/dumps/netdev.json-nft
index e0d2bfb4385b7..6eb19a17b31d9 100644
--- a/tests/shell/testcases/json/dumps/netdev.json-nft
+++ b/tests/shell/testcases/json/dumps/netdev.json-nft
@@ -13,6 +13,19 @@
         "name": "test_table",
         "handle": 0
       }
+    },
+    {
+      "chain": {
+        "family": "netdev",
+        "table": "test_table",
+        "name": "test_chain",
+        "handle": 0,
+        "dev": "d0",
+        "type": "filter",
+        "hook": "ingress",
+        "prio": 0,
+        "policy": "accept"
+      }
     }
   ]
 }
diff --git a/tests/shell/testcases/json/dumps/netdev.nft b/tests/shell/testcases/json/dumps/netdev.nft
index 3c568ed3eb38d..373ea0a46d600 100644
--- a/tests/shell/testcases/json/dumps/netdev.nft
+++ b/tests/shell/testcases/json/dumps/netdev.nft
@@ -1,2 +1,5 @@
 table netdev test_table {
+	chain test_chain {
+		type filter hook ingress device "d0" priority filter; policy accept;
+	}
 }
diff --git a/tests/shell/testcases/listing/dumps/0020flowtable_0.json-nft b/tests/shell/testcases/listing/dumps/0020flowtable_0.json-nft
index d511739abd4b6..b1b3a5fba34a0 100644
--- a/tests/shell/testcases/listing/dumps/0020flowtable_0.json-nft
+++ b/tests/shell/testcases/listing/dumps/0020flowtable_0.json-nft
@@ -32,7 +32,8 @@
         "table": "filter",
         "handle": 0,
         "hook": "ingress",
-        "prio": 0
+        "prio": 0,
+        "dev": "d0"
       }
     },
     {
@@ -60,7 +61,8 @@
         "table": "filter",
         "handle": 0,
         "hook": "ingress",
-        "prio": 0
+        "prio": 0,
+        "dev": "d0"
       }
     }
   ]
diff --git a/tests/shell/testcases/listing/dumps/0020flowtable_0.nft b/tests/shell/testcases/listing/dumps/0020flowtable_0.nft
index 4a64e531db840..59fcbec8e5130 100644
--- a/tests/shell/testcases/listing/dumps/0020flowtable_0.nft
+++ b/tests/shell/testcases/listing/dumps/0020flowtable_0.nft
@@ -6,6 +6,7 @@ table inet filter {
 
 	flowtable f2 {
 		hook ingress priority filter
+		devices = { d0 }
 	}
 }
 table ip filter {
@@ -16,5 +17,6 @@ table ip filter {
 
 	flowtable f2 {
 		hook ingress priority filter
+		devices = { d0 }
 	}
 }
diff --git a/tests/shell/testcases/transactions/0050rule_1 b/tests/shell/testcases/transactions/0050rule_1
deleted file mode 100755
index 89e5f42fc9f4d..0000000000000
--- a/tests/shell/testcases/transactions/0050rule_1
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-
-set -e
-
-RULESET="table inet filter {
-	flowtable ftable {
-		hook ingress priority 0; devices = { eno1, eno0, x };
-	}
-
-chain forward {
-	type filter hook forward priority 0; policy drop;
-
-	ip protocol { tcp, udp } ct mark and 1 == 1 counter flow add @ftable
-	ip6 nexthdr { tcp, udp } ct mark and 2 == 2 counter flow add @ftable
-	ct mark and 30 == 30 ct state established,related log prefix \"nftables accept: \" level info accept
-	}
-}"
-
-$NFT -f - <<< "$RULESET" >/dev/null || exit 0
diff --git a/tests/shell/testcases/transactions/dumps/0050rule_1.json-nft b/tests/shell/testcases/transactions/dumps/0050rule_1.json-nft
deleted file mode 100644
index 546cc5977db61..0000000000000
--- a/tests/shell/testcases/transactions/dumps/0050rule_1.json-nft
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "nftables": [
-    {
-      "metainfo": {
-        "version": "VERSION",
-        "release_name": "RELEASE_NAME",
-        "json_schema_version": 1
-      }
-    }
-  ]
-}
diff --git a/tests/shell/testcases/transactions/dumps/0050rule_1.nft b/tests/shell/testcases/transactions/dumps/0050rule_1.nft
deleted file mode 100644
index e69de29bb2d1d..0000000000000
-- 
2.43.0


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

* [nft PATCH 8/9] tests: monitor: Support running external commands
  2024-10-02 19:38 [nft PATCH 0/9] Support wildcard netdev hooks and events Phil Sutter
                   ` (6 preceding siblings ...)
  2024-10-02 19:38 ` [nft PATCH 7/9] tests: shell: Adjust to ifname-based flowtables Phil Sutter
@ 2024-10-02 19:38 ` Phil Sutter
  2024-10-02 19:38 ` [nft PATCH 9/9] monitor: Support NFT_MSG_(NEW|DEL)DEV events Phil Sutter
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Phil Sutter @ 2024-10-02 19:38 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Accept '@'-prefixed lines mixed in between 'I'-prefixed ones and apply
nft input and run commands in specified ordering.

To keep things simple, ignore such test cases when in echo mode for now.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 tests/monitor/run-tests.sh | 61 ++++++++++++++++++++++++++++++++++----
 1 file changed, 56 insertions(+), 5 deletions(-)

diff --git a/tests/monitor/run-tests.sh b/tests/monitor/run-tests.sh
index 214512d269e8d..36fc800c10520 100755
--- a/tests/monitor/run-tests.sh
+++ b/tests/monitor/run-tests.sh
@@ -59,6 +59,44 @@ json_output_filter() { # (filename)
 	# unify handle values
 	sed -i -e 's/\("handle":\) [0-9][0-9]*/\1 0/g' "$1"
 }
+apply_commands_from_file() { # (command_file)
+	grep -q '^# run: ' $1 || {
+		$nft -f - <$1 || {
+			err "nft command failed!"
+			return 1
+		}
+		return 0
+	}
+	local nft_cmd=""
+	local sep=""
+	local line=""
+	while read line; do
+		[[ $line =~ ^#\ run: ]] || {
+			nft_cmd+="$sep$line"
+			sep="; "
+			continue
+		}
+		[[ -n $nft_cmd ]] && {
+			$nft -f - <<<"$nft_cmd" || {
+				err "nft command failed!"
+				return 1
+			}
+		}
+		nft_cmd=""
+		sep=""
+		${line#\# run: } || {
+			err "custom command failed!"
+			return 1
+		}
+	done <$1
+	[[ -n $nft_cmd ]] && {
+		$nft -f - <<<"$nft_cmd" || {
+			err "nft command failed!"
+			return 1
+		}
+	}
+	return 0
+}
 monitor_run_test() {
 	monitor_output=$(mktemp -p $testdir)
 	monitor_args=""
@@ -74,10 +112,7 @@ monitor_run_test() {
 		echo "command file:"
 		cat $command_file
 	}
-	$nft -f - <$command_file || {
-		err "nft command failed!"
-		rc=1
-	}
+	apply_commands_from_file $command_file || rc=1
 	sleep 0.5
 	kill $monitor_pid
 	wait >/dev/null 2>&1
@@ -103,6 +138,17 @@ echo_run_test() {
 		echo "command file:"
 		cat $command_file
 	}
+	grep -q '^# run: ' $command_file && {
+		$debug && {
+			echo "skipping unsuitable test case in command file:"
+			cat $command_file
+		}
+		rm $command_file
+		rm $output_file
+		touch $command_file
+		touch $output_file
+		return 0
+	}
 	$nft -nn -e -f - <$command_file >$echo_output || {
 		err "nft command failed!"
 		rc=1
@@ -182,18 +228,23 @@ for variant in $variants; do
 		# O add table ip t
 		# I add chain ip t c
 		# O add chain ip t c
+		# I <nft input1>
+		# @ <command to run after nft input1>
+		# I <nft input2>
+		# O ...
 
 		$nft flush ruleset
 
 		input_complete=false
 		while read dir line; do
 			case $dir in
-			I)
+			I|@)
 				$input_complete && {
 					$run_test
 					let "rc += $?"
 				}
 				input_complete=false
+				[[ $dir == '@' ]] && line="# run: $line"
 				cmd_append "$line"
 				;;
 			O)
-- 
2.43.0


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

* [nft PATCH 9/9] monitor: Support NFT_MSG_(NEW|DEL)DEV events
  2024-10-02 19:38 [nft PATCH 0/9] Support wildcard netdev hooks and events Phil Sutter
                   ` (7 preceding siblings ...)
  2024-10-02 19:38 ` [nft PATCH 8/9] tests: monitor: Support running external commands Phil Sutter
@ 2024-10-02 19:38 ` Phil Sutter
  2024-10-02 19:55   ` Phil Sutter
  2024-10-31 22:08 ` [nft PATCH 0/9] Support wildcard netdev hooks and events Florian Westphal
  2024-11-06 10:01 ` Phil Sutter
  10 siblings, 1 reply; 14+ messages in thread
From: Phil Sutter @ 2024-10-02 19:38 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Kernels with name-based netdev hooks emit these messages when a device
is added to or removed from an existing flowtable or netdev-family
base-chain.

This patch depends on respective support code in libnftnl.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 include/json.h                             | 10 ++++
 include/linux/netfilter/nf_tables.h        | 10 ++++
 src/json.c                                 | 27 +++++++++
 src/monitor.c                              | 64 +++++++++++++++++++++
 tests/monitor/testcases/chain-netdev.t     | 66 ++++++++++++++++++++++
 tests/monitor/testcases/flowtable-simple.t | 56 ++++++++++++++++++
 6 files changed, 233 insertions(+)
 create mode 100644 tests/monitor/testcases/chain-netdev.t

diff --git a/include/json.h b/include/json.h
index 0670b8714519b..10a75ba050a6c 100644
--- a/include/json.h
+++ b/include/json.h
@@ -20,6 +20,7 @@ struct nft_ctx;
 struct location;
 struct output_ctx;
 struct list_head;
+struct nftnl_device;
 
 #ifdef HAVE_LIBJANSSON
 
@@ -118,6 +119,8 @@ void monitor_print_flowtable_json(struct netlink_mon_handler *monh,
 				  const char *cmd, struct flowtable *ft);
 void monitor_print_rule_json(struct netlink_mon_handler *monh,
 			     const char *cmd, struct rule *r);
+void monitor_print_device_json(struct netlink_mon_handler *monh,
+			       const char *cmd, struct nftnl_device *nld);
 
 int json_events_cb(const struct nlmsghdr *nlh,
 		   struct netlink_mon_handler *monh);
@@ -270,6 +273,13 @@ static inline void monitor_print_rule_json(struct netlink_mon_handler *monh,
 	/* empty */
 }
 
+static inline void
+monitor_print_device_json(struct netlink_mon_handler *monh,
+			  const char *cmd, struct nftnl_device *nld)
+{
+	/* empty */
+}
+
 static inline int json_events_cb(const struct nlmsghdr *nlh,
                                  struct netlink_mon_handler *monh)
 {
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index c62e6ac563988..206d90b190951 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -142,6 +142,8 @@ enum nf_tables_msg_types {
 	NFT_MSG_DESTROYOBJ,
 	NFT_MSG_DESTROYFLOWTABLE,
 	NFT_MSG_GETSETELEM_RESET,
+	NFT_MSG_NEWDEV,
+	NFT_MSG_DELDEV,
 	NFT_MSG_MAX,
 };
 
@@ -1761,10 +1763,18 @@ enum nft_synproxy_attributes {
  * enum nft_device_attributes - nf_tables device netlink attributes
  *
  * @NFTA_DEVICE_NAME: name of this device (NLA_STRING)
+ * @NFTA_DEVICE_TABLE: table containing the flowtable or chain hooking into the device (NLA_STRING)
+ * @NFTA_DEVICE_FLOWTABLE: flowtable hooking into the device (NLA_STRING)
+ * @NFTA_DEVICE_CHAIN: chain hooking into the device (NLA_STRING)
+ * @NFTA_DEVICE_SPEC: hook spec matching the device (NLA_STRING)
  */
 enum nft_devices_attributes {
 	NFTA_DEVICE_UNSPEC,
 	NFTA_DEVICE_NAME,
+	NFTA_DEVICE_TABLE,
+	NFTA_DEVICE_FLOWTABLE,
+	NFTA_DEVICE_CHAIN,
+	NFTA_DEVICE_SPEC,
 	__NFTA_DEVICE_MAX
 };
 #define NFTA_DEVICE_MAX		(__NFTA_DEVICE_MAX - 1)
diff --git a/src/json.c b/src/json.c
index 64a6888f9e0ac..02f21bb6b0d92 100644
--- a/src/json.c
+++ b/src/json.c
@@ -17,6 +17,8 @@
 #include <rt.h>
 #include "nftutils.h"
 
+#include <libnftnl/device.h>
+
 #include <netdb.h>
 #include <netinet/icmp6.h>
 #include <netinet/in.h>
@@ -2122,6 +2124,31 @@ void monitor_print_rule_json(struct netlink_mon_handler *monh,
 	monitor_print_json(monh, cmd, rule_print_json(octx, r));
 }
 
+void monitor_print_device_json(struct netlink_mon_handler *monh,
+			       const char *cmd, struct nftnl_device *nld)
+{
+	int32_t family = nftnl_device_get_s32(nld, NFTNL_DEVICE_FAMILY);
+	const char *key, *val;
+	json_t *root;
+
+	if (nftnl_device_is_set(nld, NFTNL_DEVICE_CHAIN)) {
+		key = "chain";
+		val = nftnl_device_get_str(nld, NFTNL_DEVICE_CHAIN);
+	} else if (nftnl_device_is_set(nld, NFTNL_DEVICE_FLOWTABLE)) {
+		key = "flowtable";
+		val = nftnl_device_get_str(nld, NFTNL_DEVICE_FLOWTABLE);
+	} else {
+		return;
+	}
+	root = json_pack("{s:{s:s, s:s, s:s, s:s, s:s}}", "device",
+			 "family", family2str(family),
+			 "table", nftnl_device_get_str(nld, NFTNL_DEVICE_TABLE),
+			 key, val,
+			 "name", nftnl_device_get_str(nld, NFTNL_DEVICE_NAME),
+			 "spec", nftnl_device_get_str(nld, NFTNL_DEVICE_SPEC));
+	monitor_print_json(monh, cmd, root);
+}
+
 void json_alloc_echo(struct nft_ctx *nft)
 {
 	nft->json_echo = json_array();
diff --git a/src/monitor.c b/src/monitor.c
index a787db8cbf5a3..3d53f62a61280 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -25,6 +25,7 @@
 #include <libnftnl/udata.h>
 #include <libnftnl/ruleset.h>
 #include <libnftnl/common.h>
+#include <libnftnl/device.h>
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nf_tables.h>
 #include <linux/netfilter.h>
@@ -154,6 +155,7 @@ static uint32_t netlink_msg2nftnl_of(uint32_t type, uint16_t flags)
 	case NFT_MSG_NEWSETELEM:
 	case NFT_MSG_NEWOBJ:
 	case NFT_MSG_NEWFLOWTABLE:
+	case NFT_MSG_NEWDEV:
 		if (flags & NLM_F_EXCL)
 			return NFT_OF_EVENT_CREATE;
 		else
@@ -165,6 +167,7 @@ static uint32_t netlink_msg2nftnl_of(uint32_t type, uint16_t flags)
 	case NFT_MSG_DELRULE:
 	case NFT_MSG_DELOBJ:
 	case NFT_MSG_DELFLOWTABLE:
+	case NFT_MSG_DELDEV:
 		return NFTNL_OF_EVENT_DEL;
 	}
 
@@ -599,6 +602,61 @@ static int netlink_events_flowtable_cb(const struct nlmsghdr *nlh, int type,
 	return MNL_CB_OK;
 }
 
+static struct nftnl_device *netlink_device_alloc(const struct nlmsghdr *nlh)
+{
+	struct nftnl_device *nld;
+
+	nld = nftnl_device_alloc();
+	if (nld == NULL)
+		memory_allocation_error();
+	if (nftnl_device_nlmsg_parse(nlh, nld) < 0)
+		netlink_abi_error();
+
+	return nld;
+}
+
+static int netlink_events_dev_cb(const struct nlmsghdr *nlh, int type,
+				 struct netlink_mon_handler *monh)
+{
+	struct nftnl_device *nld = netlink_device_alloc(nlh);
+	const char *cmd, *obj;
+	uint32_t objattr;
+	int32_t family;
+
+	if (nftnl_device_is_set(nld, NFTNL_DEVICE_CHAIN)) {
+		objattr = NFTNL_DEVICE_CHAIN;
+		obj = "chain";
+	} else if (nftnl_device_is_set(nld, NFTNL_DEVICE_FLOWTABLE)) {
+		objattr = NFTNL_DEVICE_FLOWTABLE;
+		obj = "flowtable";
+	} else {
+		return MNL_CB_ERROR;
+	}
+
+	cmd = netlink_msg2cmd(type, nlh->nlmsg_flags);
+	family = nftnl_device_get_s32(nld, NFTNL_DEVICE_FAMILY);
+
+	switch (monh->format) {
+	case NFTNL_OUTPUT_DEFAULT:
+		nft_mon_print(monh, "%s device %s %s %s %s hook %s { %s }",
+			      cmd, obj, family2str(family),
+			      nftnl_device_get_str(nld, NFTNL_DEVICE_TABLE),
+			      nftnl_device_get_str(nld, objattr),
+			      nftnl_device_get_str(nld, NFTNL_DEVICE_SPEC),
+			      nftnl_device_get_str(nld, NFTNL_DEVICE_NAME));
+		nft_mon_print(monh, "\n");
+		break;
+	case NFTNL_OUTPUT_JSON:
+		monitor_print_device_json(monh, cmd, nld);
+		if (!nft_output_echo(&monh->ctx->nft->output))
+			nft_mon_print(monh, "\n");
+		break;
+	}
+
+	nftnl_device_free(nld);
+	return MNL_CB_OK;
+}
+
 static void rule_map_decompose_cb(struct set *s, void *data)
 {
 	if (!set_is_anonymous(s->flags))
@@ -921,6 +979,8 @@ static const char *const nftnl_msg_types[NFT_MSG_MAX] = {
 	[NFT_MSG_NEWGEN]	= "NFT_MSG_NEWGEN",
 	[NFT_MSG_NEWOBJ]	= "NFT_MSG_NEWOBJ",
 	[NFT_MSG_DELOBJ]	= "NFT_MSG_DELOBJ",
+	[NFT_MSG_NEWDEV]	= "NFT_MSG_NEWDEV",
+	[NFT_MSG_DELDEV]	= "NFT_MSG_DELDEV",
 };
 
 static const char *nftnl_msgtype2str(uint16_t type)
@@ -1026,6 +1086,10 @@ static int netlink_events_cb(const struct nlmsghdr *nlh, void *data)
 	case NFT_MSG_NEWGEN:
 		ret = netlink_events_newgen_cb(nlh, type, monh);
 		break;
+	case NFT_MSG_NEWDEV:
+	case NFT_MSG_DELDEV:
+		ret = netlink_events_dev_cb(nlh, type, monh);
+		break;
 	}
 
 	return ret;
diff --git a/tests/monitor/testcases/chain-netdev.t b/tests/monitor/testcases/chain-netdev.t
new file mode 100644
index 0000000000000..3c004af0cd855
--- /dev/null
+++ b/tests/monitor/testcases/chain-netdev.t
@@ -0,0 +1,66 @@
+# setup first
+I add table netdev t
+I add chain netdev t c { type filter hook ingress devices = { lo } priority 0; policy accept; }
+O -
+J {"add": {"table": {"family": "netdev", "name": "t", "handle": 0}}}
+J {"add": {"chain": {"family": "netdev", "table": "t", "name": "c", "handle": 0, "dev": "lo", "type": "filter", "hook": "ingress", "prio": 0, "policy": "accept"}}}
+
+I delete chain netdev t c
+O delete chain netdev t c { type filter hook ingress devices = { lo } priority 0; policy accept; }
+J {"delete": {"chain": {"family": "netdev", "table": "t", "name": "c", "handle": 0, "dev": "lo", "type": "filter", "hook": "ingress", "prio": 0, "policy": "accept"}}}
+
+I add chain netdev t c { type filter hook ingress devices = { eth1337, lo } priority 0; policy accept; }
+O -
+J {"add": {"chain": {"family": "netdev", "table": "t", "name": "c", "handle": 0, "dev": ["eth1337", "lo"], "type": "filter", "hook": "ingress", "prio": 0, "policy": "accept"}}}
+
+@ ip link add eth1337 type dummy
+O add device chain netdev t c hook eth1337 { eth1337 }
+J {"add": {"device": {"family": "netdev", "table": "t", "chain": "c", "name": "eth1337", "spec": "eth1337"}}}
+
+@ ip link del eth1337
+O delete device chain netdev t c hook eth1337 { eth1337 }
+J {"delete": {"device": {"family": "netdev", "table": "t", "chain": "c", "name": "eth1337", "spec": "eth1337"}}}
+
+I delete chain netdev t c
+O delete chain netdev t c { type filter hook ingress devices = { eth1337, lo } priority 0; policy accept; }
+J {"delete": {"chain": {"family": "netdev", "table": "t", "name": "c", "handle": 0, "dev": ["eth1337", "lo"], "type": "filter", "hook": "ingress", "prio": 0, "policy": "accept"}}}
+
+I add chain netdev t c { type filter hook ingress devices = { wild* } priority 0; }
+@ ip link add wild23 type dummy
+@ ip link add wild42 type dummy
+@ ip link del wild23
+I delete chain netdev t c
+O add chain netdev t c { type filter hook ingress devices = { wild* } priority 0; policy accept; }
+O add device chain netdev t c hook wild* { wild23 }
+O add device chain netdev t c hook wild* { wild42 }
+O delete device chain netdev t c hook wild* { wild23 }
+O delete chain netdev t c { type filter hook ingress devices = { wild* } priority 0; policy accept; }
+J {"add": {"chain": {"family": "netdev", "table": "t", "name": "c", "handle": 0, "dev": "wild*", "type": "filter", "hook": "ingress", "prio": 0, "policy": "accept"}}}
+J {"add": {"device": {"family": "netdev", "table": "t", "chain": "c", "name": "wild23", "spec": "wild*"}}}
+J {"add": {"device": {"family": "netdev", "table": "t", "chain": "c", "name": "wild42", "spec": "wild*"}}}
+J {"delete": {"device": {"family": "netdev", "table": "t", "chain": "c", "name": "wild23", "spec": "wild*"}}}
+J {"delete": {"chain": {"family": "netdev", "table": "t", "name": "c", "handle": 0, "dev": "wild*", "type": "filter", "hook": "ingress", "prio": 0, "policy": "accept"}}}
+
+I add chain netdev t c { type filter hook ingress devices = { wild* } priority 0; }
+I add chain netdev t c2 { type filter hook ingress devices = { wald* } priority 0; }
+@ ip link add wild23 type dummy
+@ ip link set wild42 name wald42
+@ ip link del wild23
+I delete chain netdev t c
+I delete chain netdev t c2
+O add chain netdev t c { type filter hook ingress devices = { wild* } priority 0; policy accept; }
+O add chain netdev t c2 { type filter hook ingress devices = { wald* } priority 0; policy accept; }
+O add device chain netdev t c hook wild* { wild23 }
+O add device chain netdev t c2 hook wald* { wald42 }
+O delete device chain netdev t c hook wild* { wald42 }
+O delete device chain netdev t c hook wild* { wild23 }
+O delete chain netdev t c { type filter hook ingress devices = { wild* } priority 0; policy accept; }
+O delete chain netdev t c2 { type filter hook ingress devices = { wald* } priority 0; policy accept; }
+J {"add": {"chain": {"family": "netdev", "table": "t", "name": "c", "handle": 0, "dev": "wild*", "type": "filter", "hook": "ingress", "prio": 0, "policy": "accept"}}}
+J {"add": {"chain": {"family": "netdev", "table": "t", "name": "c2", "handle": 0, "dev": "wald*", "type": "filter", "hook": "ingress", "prio": 0, "policy": "accept"}}}
+J {"add": {"device": {"family": "netdev", "table": "t", "chain": "c", "name": "wild23", "spec": "wild*"}}}
+J {"add": {"device": {"family": "netdev", "table": "t", "chain": "c2", "name": "wald42", "spec": "wald*"}}}
+J {"delete": {"device": {"family": "netdev", "table": "t", "chain": "c", "name": "wald42", "spec": "wild*"}}}
+J {"delete": {"device": {"family": "netdev", "table": "t", "chain": "c", "name": "wild23", "spec": "wild*"}}}
+J {"delete": {"chain": {"family": "netdev", "table": "t", "name": "c", "handle": 0, "dev": "wild*", "type": "filter", "hook": "ingress", "prio": 0, "policy": "accept"}}}
+J {"delete": {"chain": {"family": "netdev", "table": "t", "name": "c2", "handle": 0, "dev": "wald*", "type": "filter", "hook": "ingress", "prio": 0, "policy": "accept"}}}
diff --git a/tests/monitor/testcases/flowtable-simple.t b/tests/monitor/testcases/flowtable-simple.t
index df8eccbd91e0a..113b15f20d1dc 100644
--- a/tests/monitor/testcases/flowtable-simple.t
+++ b/tests/monitor/testcases/flowtable-simple.t
@@ -8,3 +8,59 @@ J {"add": {"flowtable": {"family": "ip", "name": "ft", "table": "t", "handle": 0
 I delete flowtable ip t ft
 O -
 J {"delete": {"flowtable": {"family": "ip", "name": "ft", "table": "t", "handle": 0, "hook": "ingress", "prio": 0, "dev": "lo"}}}
+
+I add flowtable ip t ft { hook ingress priority 0; devices = { eth1337, lo }; }
+O -
+J {"add": {"flowtable": {"family": "ip", "name": "ft", "table": "t", "handle": 0, "hook": "ingress", "prio": 0, "dev": ["eth1337", "lo"]}}}
+
+@ ip link add eth1337 type dummy
+O add device flowtable ip t ft hook eth1337 { eth1337 }
+J {"add": {"device": {"family": "ip", "table": "t", "flowtable": "ft", "name": "eth1337", "spec": "eth1337"}}}
+
+@ ip link del eth1337
+O delete device flowtable ip t ft hook eth1337 { eth1337 }
+J {"delete": {"device": {"family": "ip", "table": "t", "flowtable": "ft", "name": "eth1337", "spec": "eth1337"}}}
+
+I delete flowtable ip t ft
+O -
+J {"delete": {"flowtable": {"family": "ip", "name": "ft", "table": "t", "handle": 0, "hook": "ingress", "prio": 0, "dev": ["eth1337", "lo"]}}}
+
+I add flowtable ip t ft { hook ingress priority 0; devices = { wild* }; }
+@ ip link add wild23 type dummy
+@ ip link add wild42 type dummy
+@ ip link del wild23
+I delete flowtable ip t ft
+O add flowtable ip t ft { hook ingress priority 0; devices = { wild* }; }
+O add device flowtable ip t ft hook wild* { wild23 }
+O add device flowtable ip t ft hook wild* { wild42 }
+O delete device flowtable ip t ft hook wild* { wild23 }
+O delete flowtable ip t ft
+J {"add": {"flowtable": {"family": "ip", "name": "ft", "table": "t", "handle": 0, "hook": "ingress", "prio": 0, "dev": "wild*"}}}
+J {"add": {"device": {"family": "ip", "table": "t", "flowtable": "ft", "name": "wild23", "spec": "wild*"}}}
+J {"add": {"device": {"family": "ip", "table": "t", "flowtable": "ft", "name": "wild42", "spec": "wild*"}}}
+J {"delete": {"device": {"family": "ip", "table": "t", "flowtable": "ft", "name": "wild23", "spec": "wild*"}}}
+J {"delete": {"flowtable": {"family": "ip", "name": "ft", "table": "t", "handle": 0, "hook": "ingress", "prio": 0, "dev": "wild*"}}}
+
+I add flowtable ip t ft { hook ingress priority 0; devices = { wild* }; }
+I add flowtable ip t ft2 { hook ingress priority 0; devices = { wald* }; }
+@ ip link add wild23 type dummy
+@ ip link set wild42 name wald42
+@ ip link del wild23
+I delete flowtable ip t ft
+I delete flowtable ip t ft2
+O add flowtable ip t ft { hook ingress priority 0; devices = { wild* }; }
+O add flowtable ip t ft2 { hook ingress priority 0; devices = { wald* }; }
+O add device flowtable ip t ft hook wild* { wild23 }
+O add device flowtable ip t ft2 hook wald* { wald42 }
+O delete device flowtable ip t ft hook wild* { wald42 }
+O delete device flowtable ip t ft hook wild* { wild23 }
+O delete flowtable ip t ft
+O delete flowtable ip t ft2
+J {"add": {"flowtable": {"family": "ip", "name": "ft", "table": "t", "handle": 0, "hook": "ingress", "prio": 0, "dev": "wild*"}}}
+J {"add": {"flowtable": {"family": "ip", "name": "ft2", "table": "t", "handle": 0, "hook": "ingress", "prio": 0, "dev": "wald*"}}}
+J {"add": {"device": {"family": "ip", "table": "t", "flowtable": "ft", "name": "wild23", "spec": "wild*"}}}
+J {"add": {"device": {"family": "ip", "table": "t", "flowtable": "ft2", "name": "wald42", "spec": "wald*"}}}
+J {"delete": {"device": {"family": "ip", "table": "t", "flowtable": "ft", "name": "wald42", "spec": "wild*"}}}
+J {"delete": {"device": {"family": "ip", "table": "t", "flowtable": "ft", "name": "wild23", "spec": "wild*"}}}
+J {"delete": {"flowtable": {"family": "ip", "name": "ft", "table": "t", "handle": 0, "hook": "ingress", "prio": 0, "dev": "wild*"}}}
+J {"delete": {"flowtable": {"family": "ip", "name": "ft2", "table": "t", "handle": 0, "hook": "ingress", "prio": 0, "dev": "wald*"}}}
-- 
2.43.0


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

* Re: [nft PATCH 9/9] monitor: Support NFT_MSG_(NEW|DEL)DEV events
  2024-10-02 19:38 ` [nft PATCH 9/9] monitor: Support NFT_MSG_(NEW|DEL)DEV events Phil Sutter
@ 2024-10-02 19:55   ` Phil Sutter
  0 siblings, 0 replies; 14+ messages in thread
From: Phil Sutter @ 2024-10-02 19:55 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

On Wed, Oct 02, 2024 at 09:38:53PM +0200, Phil Sutter wrote:
[...]
>  tests/monitor/testcases/chain-netdev.t     | 66 ++++++++++++++++++++++
>  tests/monitor/testcases/flowtable-simple.t | 56 ++++++++++++++++++

And as foretold in patch 4, the new chain-netdev.t clashes with similar
content in flowtable-simple.t. To avoid this, both need a trivial
adjustment:

diff --git a/tests/monitor/testcases/chain-netdev.t b/tests/monitor/testcases/chain-netdev.t
index 3c004af0cd855..414040045dd20 100644
--- a/tests/monitor/testcases/chain-netdev.t
+++ b/tests/monitor/testcases/chain-netdev.t
@@ -48,6 +48,7 @@ I add chain netdev t c2 { type filter hook ingress devices = { wald* } priority
 @ ip link del wild23
 I delete chain netdev t c
 I delete chain netdev t c2
+@ ip link del wald42
 O add chain netdev t c { type filter hook ingress devices = { wild* } priority 0; policy accept; }
 O add chain netdev t c2 { type filter hook ingress devices = { wald* } priority 0; policy accept; }
 O add device chain netdev t c hook wild* { wild23 }
diff --git a/tests/monitor/testcases/flowtable-simple.t b/tests/monitor/testcases/flowtable-simple.t
index 113b15f20d1dc..2c82f4907ed93 100644
--- a/tests/monitor/testcases/flowtable-simple.t
+++ b/tests/monitor/testcases/flowtable-simple.t
@@ -48,6 +48,7 @@ I add flowtable ip t ft2 { hook ingress priority 0; devices = { wald* }; }
 @ ip link del wild23
 I delete flowtable ip t ft
 I delete flowtable ip t ft2
+@ ip link del wald42
 O add flowtable ip t ft { hook ingress priority 0; devices = { wild* }; }
 O add flowtable ip t ft2 { hook ingress priority 0; devices = { wald* }; }
 O add device flowtable ip t ft hook wild* { wild23 }

I'll wait for feedback before including this in a v2.
Sorry for the mess.

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

* Re: [nft PATCH 0/9] Support wildcard netdev hooks and events
  2024-10-02 19:38 [nft PATCH 0/9] Support wildcard netdev hooks and events Phil Sutter
                   ` (8 preceding siblings ...)
  2024-10-02 19:38 ` [nft PATCH 9/9] monitor: Support NFT_MSG_(NEW|DEL)DEV events Phil Sutter
@ 2024-10-31 22:08 ` Florian Westphal
  2024-10-31 22:13   ` Pablo Neira Ayuso
  2024-11-06 10:01 ` Phil Sutter
  10 siblings, 1 reply; 14+ messages in thread
From: Florian Westphal @ 2024-10-31 22:08 UTC (permalink / raw)
  To: Phil Sutter; +Cc: Pablo Neira Ayuso, netfilter-devel

Phil Sutter <phil@nwl.cc> wrote:
> This series is the second (and last?) step of enabling support for
> name-based and wildcard interface hooks in user space. It depends on the
> previously sent series for libnftnl.
> 
> Patches 1-4 are fallout, fixing for deficits in different areas.

These look good, happy to see typeof support on json side, feel free to
push them out.

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

* Re: [nft PATCH 0/9] Support wildcard netdev hooks and events
  2024-10-31 22:08 ` [nft PATCH 0/9] Support wildcard netdev hooks and events Florian Westphal
@ 2024-10-31 22:13   ` Pablo Neira Ayuso
  0 siblings, 0 replies; 14+ messages in thread
From: Pablo Neira Ayuso @ 2024-10-31 22:13 UTC (permalink / raw)
  To: Florian Westphal; +Cc: Phil Sutter, netfilter-devel

On Thu, Oct 31, 2024 at 11:08:23PM +0100, Florian Westphal wrote:
> Phil Sutter <phil@nwl.cc> wrote:
> > This series is the second (and last?) step of enabling support for
> > name-based and wildcard interface hooks in user space. It depends on the
> > previously sent series for libnftnl.
> > 
> > Patches 1-4 are fallout, fixing for deficits in different areas.
> 
> These look good, happy to see typeof support on json side, feel free to
> push them out.

Ack for 1-4 in this series, thanks.

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

* Re: [nft PATCH 0/9] Support wildcard netdev hooks and events
  2024-10-02 19:38 [nft PATCH 0/9] Support wildcard netdev hooks and events Phil Sutter
                   ` (9 preceding siblings ...)
  2024-10-31 22:08 ` [nft PATCH 0/9] Support wildcard netdev hooks and events Florian Westphal
@ 2024-11-06 10:01 ` Phil Sutter
  10 siblings, 0 replies; 14+ messages in thread
From: Phil Sutter @ 2024-11-06 10:01 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

On Wed, Oct 02, 2024 at 09:38:44PM +0200, Phil Sutter wrote:
> This series is the second (and last?) step of enabling support for
> name-based and wildcard interface hooks in user space. It depends on the
> previously sent series for libnftnl.
> 
> Patches 1-4 are fallout, fixing for deficits in different areas.

Applied these four patches.

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

end of thread, other threads:[~2024-11-06 10:01 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-02 19:38 [nft PATCH 0/9] Support wildcard netdev hooks and events Phil Sutter
2024-10-02 19:38 ` [nft PATCH 1/9] json: Support typeof in set and map types Phil Sutter
2024-10-02 19:38 ` [nft PATCH 2/9] tests: py: Fix for storing payload into missing file Phil Sutter
2024-10-02 19:38 ` [nft PATCH 3/9] monitor: Recognize flowtable add/del events Phil Sutter
2024-10-02 19:38 ` [nft PATCH 4/9] tests: monitor: Run in own netns Phil Sutter
2024-10-02 19:38 ` [nft PATCH 5/9] mnl: Support simple wildcards in netdev hooks Phil Sutter
2024-10-02 19:38 ` [nft PATCH 6/9] parser_bison: Accept ASTERISK_STRING in flowtable_expr_member Phil Sutter
2024-10-02 19:38 ` [nft PATCH 7/9] tests: shell: Adjust to ifname-based flowtables Phil Sutter
2024-10-02 19:38 ` [nft PATCH 8/9] tests: monitor: Support running external commands Phil Sutter
2024-10-02 19:38 ` [nft PATCH 9/9] monitor: Support NFT_MSG_(NEW|DEL)DEV events Phil Sutter
2024-10-02 19:55   ` Phil Sutter
2024-10-31 22:08 ` [nft PATCH 0/9] Support wildcard netdev hooks and events Florian Westphal
2024-10-31 22:13   ` Pablo Neira Ayuso
2024-11-06 10:01 ` Phil Sutter

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).