* [PATCHv3 net-next 1/3] tools: ynl: Add MAC address parsing support
2025-11-10 9:59 [PATCHv3 net-next 0/3] Add YNL test framework and library improvements Hangbin Liu
@ 2025-11-10 9:59 ` Hangbin Liu
2025-11-11 10:07 ` Donald Hunter
2025-11-10 9:59 ` [PATCHv3 net-next 2/3] netlink: specs: support ipv4-or-v6 for dual-stack fields Hangbin Liu
2025-11-10 10:00 ` [PATCHv3 net-next 3/3] tools: ynl: add YNL test framework Hangbin Liu
2 siblings, 1 reply; 15+ messages in thread
From: Hangbin Liu @ 2025-11-10 9:59 UTC (permalink / raw)
To: netdev
Cc: Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Jan Stancek, Matthieu Baerts (NGI0),
Asbjørn Sloth Tønnesen, Stanislav Fomichev,
Ido Schimmel, Guillaume Nault, Sabrina Dubroca, Petr Machata,
Hangbin Liu
Add missing support for parsing MAC addresses when display_hint is 'mac'
in the YNL library. This enables YNL CLI to accept MAC address strings
for attributes like lladdr in rt-neigh operations.
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
tools/net/ynl/pyynl/lib/ynl.py | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/tools/net/ynl/pyynl/lib/ynl.py b/tools/net/ynl/pyynl/lib/ynl.py
index 225baad3c8f8..36d36eb7e3b8 100644
--- a/tools/net/ynl/pyynl/lib/ynl.py
+++ b/tools/net/ynl/pyynl/lib/ynl.py
@@ -985,6 +985,15 @@ class YnlFamily(SpecFamily):
raw = bytes.fromhex(string)
else:
raw = int(string, 16)
+ elif attr_spec.display_hint == 'mac':
+ # Parse MAC address in format "00:11:22:33:44:55" or "001122334455"
+ if ':' in string:
+ mac_bytes = [int(x, 16) for x in string.split(':')]
+ else:
+ if len(string) % 2 != 0:
+ raise Exception(f"Invalid MAC address format: {string}")
+ mac_bytes = [int(string[i:i+2], 16) for i in range(0, len(string), 2)]
+ raw = bytes(mac_bytes)
else:
raise Exception(f"Display hint '{attr_spec.display_hint}' not implemented"
f" when parsing '{attr_spec['name']}'")
--
2.50.1
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCHv3 net-next 1/3] tools: ynl: Add MAC address parsing support
2025-11-10 9:59 ` [PATCHv3 net-next 1/3] tools: ynl: Add MAC address parsing support Hangbin Liu
@ 2025-11-11 10:07 ` Donald Hunter
0 siblings, 0 replies; 15+ messages in thread
From: Donald Hunter @ 2025-11-11 10:07 UTC (permalink / raw)
To: Hangbin Liu
Cc: netdev, Jakub Kicinski, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Jan Stancek, Matthieu Baerts (NGI0),
Asbjørn Sloth Tønnesen, Stanislav Fomichev,
Ido Schimmel, Guillaume Nault, Sabrina Dubroca, Petr Machata
Hangbin Liu <liuhangbin@gmail.com> writes:
> Add missing support for parsing MAC addresses when display_hint is 'mac'
> in the YNL library. This enables YNL CLI to accept MAC address strings
> for attributes like lladdr in rt-neigh operations.
>
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Reviewed-by: Donald Hunter <donald.hunter@gmail.com>
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCHv3 net-next 2/3] netlink: specs: support ipv4-or-v6 for dual-stack fields
2025-11-10 9:59 [PATCHv3 net-next 0/3] Add YNL test framework and library improvements Hangbin Liu
2025-11-10 9:59 ` [PATCHv3 net-next 1/3] tools: ynl: Add MAC address parsing support Hangbin Liu
@ 2025-11-10 9:59 ` Hangbin Liu
2025-11-10 16:38 ` Asbjørn Sloth Tønnesen
2025-11-11 10:38 ` Donald Hunter
2025-11-10 10:00 ` [PATCHv3 net-next 3/3] tools: ynl: add YNL test framework Hangbin Liu
2 siblings, 2 replies; 15+ messages in thread
From: Hangbin Liu @ 2025-11-10 9:59 UTC (permalink / raw)
To: netdev
Cc: Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Jan Stancek, Matthieu Baerts (NGI0),
Asbjørn Sloth Tønnesen, Stanislav Fomichev,
Ido Schimmel, Guillaume Nault, Sabrina Dubroca, Petr Machata,
Hangbin Liu
Since commit 1b255e1beabf ("tools: ynl: add ipv4-or-v6 display hint"), we
can display either IPv4 or IPv6 addresses for a single field based on the
address family. However, most dual-stack fields still use the ipv4 display
hint. This update changes them to use the new ipv4-or-v6 display hint and
converts IPv4-only fields to use the u32 type.
Field changes:
- v4-or-v6
- IFA_ADDRESS, IFA_LOCAL
- IFLA_GRE_LOCAL, IFLA_GRE_REMOTE
- IFLA_VTI_LOCAL, IFLA_VTI_REMOTE
- IFLA_IPTUN_LOCAL, IFLA_IPTUN_REMOTE
- NDA_DST
- RTA_DST, RTA_SRC, RTA_GATEWAY, RTA_PREFSRC
- FRA_SRC, FRA_DST
- ipv4
- IFA_BROADCAST
- IFLA_GENEVE_REMOTE
- IFLA_IPTUN_6RD_RELAY_PREFIX
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
Documentation/netlink/genetlink-c.yaml | 2 +-
Documentation/netlink/genetlink.yaml | 2 +-
Documentation/netlink/netlink-raw.yaml | 2 +-
Documentation/netlink/specs/rt-addr.yaml | 6 +++---
Documentation/netlink/specs/rt-link.yaml | 16 ++++++++--------
Documentation/netlink/specs/rt-neigh.yaml | 2 +-
Documentation/netlink/specs/rt-route.yaml | 8 ++++----
Documentation/netlink/specs/rt-rule.yaml | 6 ++++--
8 files changed, 23 insertions(+), 21 deletions(-)
diff --git a/Documentation/netlink/genetlink-c.yaml b/Documentation/netlink/genetlink-c.yaml
index 5a234e9b5fa2..57f59fe23e3f 100644
--- a/Documentation/netlink/genetlink-c.yaml
+++ b/Documentation/netlink/genetlink-c.yaml
@@ -227,7 +227,7 @@ properties:
Optional format indicator that is intended only for choosing
the right formatting mechanism when displaying values of this
type.
- enum: [ hex, mac, fddi, ipv4, ipv6, uuid ]
+ enum: [ hex, mac, fddi, ipv4, ipv6, ipv4-or-v6, uuid ]
# Start genetlink-c
name-prefix:
type: string
diff --git a/Documentation/netlink/genetlink.yaml b/Documentation/netlink/genetlink.yaml
index 7b1ec153e834..b020a537d8ac 100644
--- a/Documentation/netlink/genetlink.yaml
+++ b/Documentation/netlink/genetlink.yaml
@@ -185,7 +185,7 @@ properties:
Optional format indicator that is intended only for choosing
the right formatting mechanism when displaying values of this
type.
- enum: [ hex, mac, fddi, ipv4, ipv6, uuid ]
+ enum: [ hex, mac, fddi, ipv4, ipv6, ipv4-or-v6, uuid ]
# Make sure name-prefix does not appear in subsets (subsets inherit naming)
dependencies:
diff --git a/Documentation/netlink/netlink-raw.yaml b/Documentation/netlink/netlink-raw.yaml
index 246fa07bccf6..0166a7e4afbb 100644
--- a/Documentation/netlink/netlink-raw.yaml
+++ b/Documentation/netlink/netlink-raw.yaml
@@ -157,7 +157,7 @@ properties:
Optional format indicator that is intended only for choosing
the right formatting mechanism when displaying values of this
type.
- enum: [ hex, mac, fddi, ipv4, ipv6, uuid ]
+ enum: [ hex, mac, fddi, ipv4, ipv6, ipv4-or-v6, uuid ]
struct:
description: Name of the nested struct type.
type: string
diff --git a/Documentation/netlink/specs/rt-addr.yaml b/Documentation/netlink/specs/rt-addr.yaml
index 3a582eac1629..abcbaa73fa9d 100644
--- a/Documentation/netlink/specs/rt-addr.yaml
+++ b/Documentation/netlink/specs/rt-addr.yaml
@@ -86,17 +86,17 @@ attribute-sets:
-
name: address
type: binary
- display-hint: ipv4
+ display-hint: ipv4-or-v6
-
name: local
type: binary
- display-hint: ipv4
+ display-hint: ipv4-or-v6
-
name: label
type: string
-
name: broadcast
- type: binary
+ type: u32
display-hint: ipv4
-
name: anycast
diff --git a/Documentation/netlink/specs/rt-link.yaml b/Documentation/netlink/specs/rt-link.yaml
index 2a23e9699c0b..5bfdcb5afa86 100644
--- a/Documentation/netlink/specs/rt-link.yaml
+++ b/Documentation/netlink/specs/rt-link.yaml
@@ -1707,11 +1707,11 @@ attribute-sets:
-
name: local
type: binary
- display-hint: ipv4
+ display-hint: ipv4-or-v6
-
name: remote
type: binary
- display-hint: ipv4
+ display-hint: ipv4-or-v6
-
name: ttl
type: u8
@@ -1833,11 +1833,11 @@ attribute-sets:
-
name: local
type: binary
- display-hint: ipv4
+ display-hint: ipv4-or-v6
-
name: remote
type: binary
- display-hint: ipv4
+ display-hint: ipv4-or-v6
-
name: fwmark
type: u32
@@ -1868,7 +1868,7 @@ attribute-sets:
type: u32
-
name: remote
- type: binary
+ type: u32
display-hint: ipv4
-
name: ttl
@@ -1923,11 +1923,11 @@ attribute-sets:
-
name: local
type: binary
- display-hint: ipv4
+ display-hint: ipv4-or-v6
-
name: remote
type: binary
- display-hint: ipv4
+ display-hint: ipv4-or-v6
-
name: ttl
type: u8
@@ -1957,7 +1957,7 @@ attribute-sets:
display-hint: ipv6
-
name: 6rd-relay-prefix
- type: binary
+ type: u32
display-hint: ipv4
-
name: 6rd-prefixlen
diff --git a/Documentation/netlink/specs/rt-neigh.yaml b/Documentation/netlink/specs/rt-neigh.yaml
index 2f568a6231c9..0f46ef313590 100644
--- a/Documentation/netlink/specs/rt-neigh.yaml
+++ b/Documentation/netlink/specs/rt-neigh.yaml
@@ -194,7 +194,7 @@ attribute-sets:
-
name: dst
type: binary
- display-hint: ipv4
+ display-hint: ipv4-or-v6
-
name: lladdr
type: binary
diff --git a/Documentation/netlink/specs/rt-route.yaml b/Documentation/netlink/specs/rt-route.yaml
index 1ecb3fadc067..33195db96746 100644
--- a/Documentation/netlink/specs/rt-route.yaml
+++ b/Documentation/netlink/specs/rt-route.yaml
@@ -87,11 +87,11 @@ attribute-sets:
-
name: dst
type: binary
- display-hint: ipv4
+ display-hint: ipv4-or-v6
-
name: src
type: binary
- display-hint: ipv4
+ display-hint: ipv4-or-v6
-
name: iif
type: u32
@@ -101,14 +101,14 @@ attribute-sets:
-
name: gateway
type: binary
- display-hint: ipv4
+ display-hint: ipv4-or-v6
-
name: priority
type: u32
-
name: prefsrc
type: binary
- display-hint: ipv4
+ display-hint: ipv4-or-v6
-
name: metrics
type: nest
diff --git a/Documentation/netlink/specs/rt-rule.yaml b/Documentation/netlink/specs/rt-rule.yaml
index bebee452a950..7f03a44ab036 100644
--- a/Documentation/netlink/specs/rt-rule.yaml
+++ b/Documentation/netlink/specs/rt-rule.yaml
@@ -96,10 +96,12 @@ attribute-sets:
attributes:
-
name: dst
- type: u32
+ type: binary
+ display-hint: ipv4-or-v6
-
name: src
- type: u32
+ type: binary
+ display-hint: ipv4-or-v6
-
name: iifname
type: string
--
2.50.1
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCHv3 net-next 2/3] netlink: specs: support ipv4-or-v6 for dual-stack fields
2025-11-10 9:59 ` [PATCHv3 net-next 2/3] netlink: specs: support ipv4-or-v6 for dual-stack fields Hangbin Liu
@ 2025-11-10 16:38 ` Asbjørn Sloth Tønnesen
2025-11-11 10:38 ` Donald Hunter
1 sibling, 0 replies; 15+ messages in thread
From: Asbjørn Sloth Tønnesen @ 2025-11-10 16:38 UTC (permalink / raw)
To: Hangbin Liu
Cc: Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Jan Stancek, Matthieu Baerts (NGI0),
Stanislav Fomichev, Ido Schimmel, Guillaume Nault,
Sabrina Dubroca, Petr Machata, netdev
On 11/10/25 9:59 AM, Hangbin Liu wrote:
> Since commit 1b255e1beabf ("tools: ynl: add ipv4-or-v6 display hint"), we
> can display either IPv4 or IPv6 addresses for a single field based on the
> address family. However, most dual-stack fields still use the ipv4 display
> hint. This update changes them to use the new ipv4-or-v6 display hint and
> converts IPv4-only fields to use the u32 type.
>
> Field changes:
> - v4-or-v6
> - IFA_ADDRESS, IFA_LOCAL
> - IFLA_GRE_LOCAL, IFLA_GRE_REMOTE
> - IFLA_VTI_LOCAL, IFLA_VTI_REMOTE
> - IFLA_IPTUN_LOCAL, IFLA_IPTUN_REMOTE
> - NDA_DST
> - RTA_DST, RTA_SRC, RTA_GATEWAY, RTA_PREFSRC
> - FRA_SRC, FRA_DST
> - ipv4
> - IFA_BROADCAST
> - IFLA_GENEVE_REMOTE
> - IFLA_IPTUN_6RD_RELAY_PREFIX
>
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Thanks for finding these! I can't remember how I did my previous
check, and why I didn't find these earlier.
Reviewed-by: Asbjørn Sloth Tønnesen <ast@fiberby.net>
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCHv3 net-next 2/3] netlink: specs: support ipv4-or-v6 for dual-stack fields
2025-11-10 9:59 ` [PATCHv3 net-next 2/3] netlink: specs: support ipv4-or-v6 for dual-stack fields Hangbin Liu
2025-11-10 16:38 ` Asbjørn Sloth Tønnesen
@ 2025-11-11 10:38 ` Donald Hunter
1 sibling, 0 replies; 15+ messages in thread
From: Donald Hunter @ 2025-11-11 10:38 UTC (permalink / raw)
To: Hangbin Liu
Cc: netdev, Jakub Kicinski, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Jan Stancek, Matthieu Baerts (NGI0),
Asbjørn Sloth Tønnesen, Stanislav Fomichev,
Ido Schimmel, Guillaume Nault, Sabrina Dubroca, Petr Machata
Hangbin Liu <liuhangbin@gmail.com> writes:
> Since commit 1b255e1beabf ("tools: ynl: add ipv4-or-v6 display hint"), we
> can display either IPv4 or IPv6 addresses for a single field based on the
> address family. However, most dual-stack fields still use the ipv4 display
> hint. This update changes them to use the new ipv4-or-v6 display hint and
> converts IPv4-only fields to use the u32 type.
>
> Field changes:
> - v4-or-v6
> - IFA_ADDRESS, IFA_LOCAL
> - IFLA_GRE_LOCAL, IFLA_GRE_REMOTE
> - IFLA_VTI_LOCAL, IFLA_VTI_REMOTE
> - IFLA_IPTUN_LOCAL, IFLA_IPTUN_REMOTE
> - NDA_DST
> - RTA_DST, RTA_SRC, RTA_GATEWAY, RTA_PREFSRC
> - FRA_SRC, FRA_DST
> - ipv4
> - IFA_BROADCAST
> - IFLA_GENEVE_REMOTE
> - IFLA_IPTUN_6RD_RELAY_PREFIX
>
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Thanks for all the fixes!
Reviewed-by: Donald Hunter <donald.hunter@gmail.com>
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCHv3 net-next 3/3] tools: ynl: add YNL test framework
2025-11-10 9:59 [PATCHv3 net-next 0/3] Add YNL test framework and library improvements Hangbin Liu
2025-11-10 9:59 ` [PATCHv3 net-next 1/3] tools: ynl: Add MAC address parsing support Hangbin Liu
2025-11-10 9:59 ` [PATCHv3 net-next 2/3] netlink: specs: support ipv4-or-v6 for dual-stack fields Hangbin Liu
@ 2025-11-10 10:00 ` Hangbin Liu
2025-11-11 11:51 ` Donald Hunter
2 siblings, 1 reply; 15+ messages in thread
From: Hangbin Liu @ 2025-11-10 10:00 UTC (permalink / raw)
To: netdev
Cc: Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Jan Stancek, Matthieu Baerts (NGI0),
Asbjørn Sloth Tønnesen, Stanislav Fomichev,
Ido Schimmel, Guillaume Nault, Sabrina Dubroca, Petr Machata,
Hangbin Liu
Add a test framework for YAML Netlink (YNL) tools, covering both CLI and
ethtool functionality. The framework includes:
1) cli: family listing, netdev, ethtool, rt-* families, and nlctrl
operations
2) ethtool: device info, statistics, ring/coalesce/pause parameters, and
feature gettings
The current YNL syntax is a bit obscure, and end users may not always know
how to use it. This test framework provides usage examples and also serves
as a regression test to catch potential breakages caused by future changes.
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
tools/net/ynl/Makefile | 8 +-
tools/net/ynl/tests/Makefile | 38 ++++
tools/net/ynl/tests/config | 6 +
tools/net/ynl/tests/test_ynl_cli.sh | 291 ++++++++++++++++++++++++
tools/net/ynl/tests/test_ynl_ethtool.sh | 196 ++++++++++++++++
5 files changed, 537 insertions(+), 2 deletions(-)
create mode 100644 tools/net/ynl/tests/Makefile
create mode 100644 tools/net/ynl/tests/config
create mode 100755 tools/net/ynl/tests/test_ynl_cli.sh
create mode 100755 tools/net/ynl/tests/test_ynl_ethtool.sh
diff --git a/tools/net/ynl/Makefile b/tools/net/ynl/Makefile
index 211df5a93ad9..8a328972564a 100644
--- a/tools/net/ynl/Makefile
+++ b/tools/net/ynl/Makefile
@@ -12,7 +12,7 @@ endif
libdir ?= $(prefix)/$(libdir_relative)
includedir ?= $(prefix)/include
-SUBDIRS = lib generated samples
+SUBDIRS = lib generated samples tests
all: $(SUBDIRS) libynl.a
@@ -48,5 +48,9 @@ install: libynl.a lib/*.h
@echo -e "\tINSTALL pyynl"
@pip install --prefix=$(DESTDIR)$(prefix) .
@make -C generated install
+ @make -C tests install
-.PHONY: all clean distclean install $(SUBDIRS)
+run_tests:
+ @$(MAKE) -C tests run_tests
+
+.PHONY: all clean distclean install run_tests $(SUBDIRS)
diff --git a/tools/net/ynl/tests/Makefile b/tools/net/ynl/tests/Makefile
new file mode 100644
index 000000000000..4d527f9c3de9
--- /dev/null
+++ b/tools/net/ynl/tests/Makefile
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: GPL-2.0
+# Makefile for YNL tests
+
+TESTS := \
+ test_ynl_cli.sh \
+ test_ynl_ethtool.sh \
+# end of TESTS
+
+all: $(TESTS)
+
+run_tests:
+ @echo "Running YNL tests..."
+ @failed=0; \
+ echo "Running test_ynl_cli.sh..."; \
+ ./test_ynl_cli.sh || failed=$$(($$failed + 1)); \
+ echo "Running test_ynl_ethtool.sh..."; \
+ ./test_ynl_ethtool.sh || failed=$$(($$failed + 1)); \
+ if [ $$failed -eq 0 ]; then \
+ echo "All tests passed!"; \
+ else \
+ echo "$$failed test(s) failed!"; \
+ exit 1; \
+ fi
+
+install: $(TESTS)
+ @mkdir -p $(DESTDIR)/usr/bin
+ @for test in $(TESTS); do \
+ name=$$(basename $$test .sh); \
+ sed -e 's|^ynl=.*|ynl="ynl"|' \
+ -e 's|^ynl_ethtool=.*|ynl_ethtool="ynl-ethtool"|' \
+ $$test > $(DESTDIR)/usr/bin/$$name; \
+ chmod +x $(DESTDIR)/usr/bin/$$name; \
+ done
+
+clean:
+ @# Nothing to clean
+
+.PHONY: all install clean run_tests
diff --git a/tools/net/ynl/tests/config b/tools/net/ynl/tests/config
new file mode 100644
index 000000000000..339f1309c03f
--- /dev/null
+++ b/tools/net/ynl/tests/config
@@ -0,0 +1,6 @@
+CONFIG_DUMMY=m
+CONFIG_INET_DIAG=y
+CONFIG_IPV6=y
+CONFIG_NET_NS=y
+CONFIG_NETDEVSIM=m
+CONFIG_VETH=m
diff --git a/tools/net/ynl/tests/test_ynl_cli.sh b/tools/net/ynl/tests/test_ynl_cli.sh
new file mode 100755
index 000000000000..5cc0624ffaad
--- /dev/null
+++ b/tools/net/ynl/tests/test_ynl_cli.sh
@@ -0,0 +1,291 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Test YNL CLI functionality
+
+# Default ynl path for direct execution, can be overridden by make install
+ynl="../pyynl/cli.py"
+
+readonly NSIM_ID="1338"
+readonly NSIM_DEV_NAME="nsim${NSIM_ID}"
+readonly VETH_A="veth_a"
+readonly VETH_B="veth_b"
+
+testns="ynl-$(mktemp -u XXXXXX)"
+
+# Test listing available families
+cli_list_families() {
+ if $ynl --list-families &>/dev/null; then
+ echo "PASS: YNL CLI list families"
+ else
+ echo "FAIL: YNL CLI list families"
+ fi
+}
+
+# Test netdev family operations (dev-get, queue-get)
+cli_netdev_ops() {
+ local dev_output
+ local ifindex
+
+ ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null)
+ if [[ -z "$ifindex" ]]; then
+ echo "FAIL: YNL CLI netdev operations (failed to get ifindex)"
+ return
+ fi
+
+ dev_output=$(ip netns exec "$testns" $ynl --family netdev \
+ --do dev-get --json "{\"ifindex\": $ifindex}" 2>/dev/null)
+
+ if ! echo "$dev_output" | grep -q "ifindex"; then
+ echo "FAIL: YNL CLI netdev operations (netdev dev-get output missing ifindex)"
+ return
+ fi
+
+ if ! ip netns exec "$testns" $ynl --family netdev \
+ --dump queue-get --json "{\"ifindex\": $ifindex}" &>/dev/null; then
+ echo "FAIL: YNL CLI netdev operations (failed to get netdev queue info)"
+ return
+ fi
+
+ echo "PASS: YNL CLI netdev operations"
+}
+
+# Test ethtool family operations (rings-get, linkinfo-get)
+cli_ethtool_ops() {
+ local rings_output
+ local linkinfo_output
+
+ rings_output=$(ip netns exec "$testns" $ynl --family ethtool \
+ --do rings-get --json "{\"header\": {\"dev-name\": \"$NSIM_DEV_NAME\"}}" 2>/dev/null)
+
+ if ! echo "$rings_output" | grep -q "header"; then
+ echo "FAIL: YNL CLI ethtool operations (ethtool rings-get output missing header)"
+ return
+ fi
+
+ linkinfo_output=$(ip netns exec "$testns" $ynl --family ethtool \
+ --do linkinfo-get --json "{\"header\": {\"dev-name\": \"$VETH_A\"}}" 2>/dev/null)
+
+ if ! echo "$linkinfo_output" | grep -q "header"; then
+ echo "FAIL: YNL CLI ethtool operations (ethtool linkinfo-get output missing header)"
+ return
+ fi
+
+ echo "PASS: YNL CLI ethtool operations"
+}
+
+# Test rt-* family operations (route, addr, link, neigh, rule)
+cli_rt_ops() {
+ local ifindex
+
+ if ! $ynl --list-families 2>/dev/null | grep -q "rt-"; then
+ echo "SKIP: YNL CLI rt-* operations (no rt-* families available)"
+ return
+ fi
+
+ ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null)
+ if [[ -z "$ifindex" ]]; then
+ echo "FAIL: YNL CLI rt-* operations (failed to get ifindex)"
+ return
+ fi
+
+
+ # Test rt-route family
+ if $ynl --list-families 2>/dev/null | grep -q "rt-route"; then
+ # Add route: 192.0.2.0/24 dev $dev scope link
+ if ip netns exec "$testns" $ynl --family rt-route --do newroute --create \
+ --json "{\"dst\": \"192.0.2.0\", \"oif\": $ifindex, \"rtm-dst-len\": 24, \"rtm-family\": 2, \"rtm-scope\": 253, \"rtm-type\": 1, \"rtm-protocol\": 3, \"rtm-table\": 254}" &>/dev/null; then
+
+ local route_output
+ route_output=$(ip netns exec "$testns" $ynl --family rt-route --dump getroute 2>/dev/null)
+ if echo "$route_output" | grep -q "192.0.2.0"; then
+ echo "PASS: YNL CLI rt-route operations"
+ else
+ echo "FAIL: YNL CLI rt-route operations (failed to verify route)"
+ fi
+
+ ip netns exec "$testns" $ynl --family rt-route --do delroute \
+ --json "{\"dst\": \"192.0.2.0\", \"oif\": $ifindex, \"rtm-dst-len\": 24, \"rtm-family\": 2, \"rtm-scope\": 253, \"rtm-type\": 1, \"rtm-protocol\": 3, \"rtm-table\": 254}" &>/dev/null
+ else
+ echo "FAIL: YNL CLI rt-route operations (failed to add route)"
+ fi
+ else
+ echo "SKIP: YNL CLI rt-route operations (rt-route family not available)"
+ fi
+
+ # Test rt-addr family
+ if $ynl --list-families 2>/dev/null | grep -q "rt-addr"; then
+ if ip netns exec "$testns" $ynl --family rt-addr --do newaddr \
+ --json "{\"ifa-index\": $ifindex, \"local\": \"192.0.2.100\", \"ifa-prefixlen\": 24, \"ifa-family\": 2}" &>/dev/null; then
+
+ local addr_output
+ addr_output=$(ip netns exec "$testns" $ynl --family rt-addr --dump getaddr 2>/dev/null)
+ if echo "$addr_output" | grep -q "192.0.2.100"; then
+ echo "PASS: YNL CLI rt-addr operations"
+ else
+ echo "FAIL: YNL CLI rt-addr operations (failed to verify address)"
+ fi
+
+ ip netns exec "$testns" $ynl --family rt-addr --do deladdr \
+ --json "{\"ifa-index\": $ifindex, \"local\": \"192.0.2.100\", \"ifa-prefixlen\": 24, \"ifa-family\": 2}" &>/dev/null
+ else
+ echo "FAIL: YNL CLI rt-addr operations (failed to add address)"
+ fi
+ else
+ echo "SKIP: YNL CLI rt-addr operations (rt-addr family not available)"
+ fi
+
+ # Test rt-link family
+ if $ynl --list-families 2>/dev/null | grep -q "rt-link"; then
+ if ip netns exec "$testns" $ynl --family rt-link --do newlink --create \
+ --json "{\"ifname\": \"dummy0\", \"linkinfo\": {\"kind\": \"dummy\"}}" &>/dev/null; then
+
+ local link_output
+ link_output=$(ip netns exec "$testns" $ynl --family rt-link --dump getlink 2>/dev/null)
+ if echo "$link_output" | grep -q "$NSIM_DEV_NAME" && echo "$link_output" | grep -q "dummy0"; then
+ echo "PASS: YNL CLI rt-link operations"
+ else
+ echo "FAIL: YNL CLI rt-link operations (failed to verify link)"
+ fi
+
+ ip netns exec "$testns" $ynl --family rt-link --do dellink \
+ --json "{\"ifname\": \"dummy0\"}" &>/dev/null
+ else
+ echo "FAIL: YNL CLI rt-link operations (failed to add link)"
+ fi
+ else
+ echo "SKIP: YNL CLI rt-link operations (rt-link family not available)"
+ fi
+
+ # Test rt-neigh family
+ if $ynl --list-families 2>/dev/null | grep -q "rt-neigh"; then
+ # Add neighbor: 192.0.2.1 dev nsim1338 lladdr 11:22:33:44:55:66 PERMANENT
+ if ip netns exec "$testns" $ynl --family rt-neigh --do newneigh --create \
+ --json "{\"ndm-ifindex\": $ifindex, \"dst\": \"192.0.2.1\", \"lladdr\": \"11:22:33:44:55:66\", \"ndm-family\": 2, \"ndm-state\": 128}" &>/dev/null; then
+
+ local neigh_output
+ neigh_output=$(ip netns exec "$testns" $ynl --family rt-neigh --dump getneigh 2>/dev/null)
+ if echo "$neigh_output" | grep -q "192.0.2.1"; then
+ echo "PASS: YNL CLI rt-neigh operations"
+ else
+ echo "FAIL: YNL CLI rt-neigh operations (failed to verify neighbor)"
+ fi
+
+ ip netns exec "$testns" $ynl --family rt-neigh --do delneigh \
+ --json "{\"ndm-ifindex\": $ifindex, \"dst\": \"192.0.2.1\", \"lladdr\": \"11:22:33:44:55:66\", \"ndm-family\": 2}" &>/dev/null
+ else
+ echo "FAIL: YNL CLI rt-neigh operations (failed to add neighbor)"
+ fi
+ else
+ echo "SKIP: YNL CLI rt-neigh operations (rt-neigh family not available)"
+ fi
+
+ # Test rt-rule family
+ if $ynl --list-families 2>/dev/null | grep -q "rt-rule"; then
+ # Add rule: from 192.0.2.0/24 lookup 100 none
+ if ip netns exec "$testns" $ynl --family rt-rule --do newrule \
+ --json "{\"family\": 2, \"src-len\": 24, \"src\": \"192.0.2.0\", \"table\": 100}" &>/dev/null; then
+
+ local rule_output
+ rule_output=$(ip netns exec "$testns" $ynl --family rt-rule --dump getrule 2>/dev/null)
+ if echo "$rule_output" | grep -q "192.0.2.0"; then
+ echo "PASS: YNL CLI rt-rule operations"
+ else
+ echo "FAIL: YNL CLI rt-rule operations (failed to verify rule)"
+ fi
+
+ ip netns exec "$testns" $ynl --family rt-rule --do delrule \
+ --json "{\"family\": 2, \"src-len\": 24, \"src\": \"192.0.2.0\", \"table\": 100}" &>/dev/null
+ else
+ echo "FAIL: YNL CLI rt-rule operations (failed to add rule)"
+ fi
+ else
+ echo "SKIP: YNL CLI rt-rule operations (rt-rule family not available)"
+ fi
+
+}
+
+# Test nlctrl family operations
+cli_nlctrl_ops() {
+ local family_output
+
+ if ! family_output=$($ynl --family nlctrl \
+ --do getfamily --json "{\"family-name\": \"netdev\"}" 2>/dev/null); then
+ echo "FAIL: YNL CLI nlctrl getfamily (failed to get nlctrl family info)"
+ return
+ fi
+
+ if ! echo "$family_output" | grep -q "family-name"; then
+ echo "FAIL: YNL CLI nlctrl getfamily (nlctrl getfamily output missing family-name)"
+ return
+ fi
+
+ if ! echo "$family_output" | grep -q "family-id"; then
+ echo "FAIL: YNL CLI nlctrl getfamily (nlctrl getfamily output missing family-id)"
+ return
+ fi
+
+ echo "PASS: YNL CLI nlctrl getfamily"
+}
+
+setup() {
+ modprobe netdevsim &> /dev/null
+ if ! [ -f /sys/bus/netdevsim/new_device ]; then
+ echo "SKIP: all YNL CLI tests (netdevsim module not available)"
+ exit 0
+ fi
+
+ if ! ip netns add "$testns" 2>/dev/null; then
+ echo "SKIP: all YNL CLI tests (failed to create test namespace)"
+ exit 0
+ fi
+
+ echo "$NSIM_ID 1" | ip netns exec "$testns" tee /sys/bus/netdevsim/new_device >/dev/null 2>&1 || {
+ echo "SKIP: all YNL CLI tests (failed to create netdevsim device)"
+ exit 0
+ }
+
+ local dev
+ dev=$(ip netns exec "$testns" ls /sys/bus/netdevsim/devices/netdevsim$NSIM_ID/net 2>/dev/null | head -1)
+ if [[ -z "$dev" ]]; then
+ echo "SKIP: all YNL CLI tests (failed to find netdevsim device)"
+ exit 0
+ fi
+
+ ip -netns "$testns" link set dev "$dev" name "$NSIM_DEV_NAME" 2>/dev/null || {
+ echo "SKIP: all YNL CLI tests (failed to rename netdevsim device)"
+ exit 0
+ }
+
+ ip -netns "$testns" link set dev "$NSIM_DEV_NAME" up 2>/dev/null
+
+ if ! ip -n "$testns" link add "$VETH_A" type veth peer name "$VETH_B" 2>/dev/null; then
+ echo "SKIP: all YNL CLI tests (failed to create veth pair)"
+ exit 0
+ fi
+
+ ip -n "$testns" link set "$VETH_A" up 2>/dev/null
+ ip -n "$testns" link set "$VETH_B" up 2>/dev/null
+}
+
+cleanup() {
+ if [[ -n "$testns" ]]; then
+ ip netns exec "$testns" bash -c "echo $NSIM_ID > /sys/bus/netdevsim/del_device" 2>/dev/null || true
+ ip netns del "$testns" 2>/dev/null || true
+ fi
+}
+
+# Check if ynl command is available
+if ! command -v $ynl &>/dev/null && [[ ! -x $ynl ]]; then
+ echo "SKIP: all YNL CLI tests (ynl command not found: $ynl)"
+ exit 0
+fi
+
+trap cleanup EXIT
+setup
+
+# Run all tests
+cli_list_families
+cli_netdev_ops
+cli_ethtool_ops
+cli_rt_ops
+cli_nlctrl_ops
diff --git a/tools/net/ynl/tests/test_ynl_ethtool.sh b/tools/net/ynl/tests/test_ynl_ethtool.sh
new file mode 100755
index 000000000000..1d1e06ff0dd0
--- /dev/null
+++ b/tools/net/ynl/tests/test_ynl_ethtool.sh
@@ -0,0 +1,196 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Test YNL ethtool functionality
+
+# Default ynl-ethtool path for direct execution, can be overridden by make install
+ynl_ethtool="../pyynl/ethtool.py"
+
+readonly NSIM_ID="1337"
+readonly NSIM_DEV_NAME="nsim${NSIM_ID}"
+readonly VETH_A="veth_a"
+readonly VETH_B="veth_b"
+
+testns="ynl-ethtool-$(mktemp -u XXXXXX)"
+
+# Uses veth device as netdevsim doesn't support basic ethtool device info
+ethtool_device_info() {
+ local info_output
+
+ info_output=$(ip netns exec "$testns" $ynl_ethtool "$VETH_A" 2>/dev/null)
+
+ if ! echo "$info_output" | grep -q "Settings for"; then
+ echo "FAIL: YNL ethtool device info (device info output missing expected content)"
+ return
+ fi
+
+ echo "PASS: YNL ethtool device info"
+}
+
+ethtool_statistics() {
+ local stats_output
+
+ stats_output=$(ip netns exec "$testns" $ynl_ethtool --statistics "$NSIM_DEV_NAME" 2>/dev/null)
+
+ if ! echo "$stats_output" | grep -q -E "(NIC statistics|packets|bytes)"; then
+ echo "FAIL: YNL ethtool statistics (statistics output missing expected content)"
+ return
+ fi
+
+ echo "PASS: YNL ethtool statistics"
+}
+
+ethtool_ring_params() {
+ local ring_output
+
+ ring_output=$(ip netns exec "$testns" $ynl_ethtool --show-ring "$NSIM_DEV_NAME" 2>/dev/null)
+
+ if ! echo "$ring_output" | grep -q -E "(Ring parameters|RX|TX)"; then
+ echo "FAIL: YNL ethtool ring parameters (ring parameters output missing expected content)"
+ return
+ fi
+
+ if ! ip netns exec "$testns" $ynl_ethtool --set-ring "$NSIM_DEV_NAME" rx 64 2>/dev/null; then
+ echo "FAIL: YNL ethtool ring parameters (set-ring command failed unexpectedly)"
+ return
+ fi
+
+ echo "PASS: YNL ethtool ring parameters (show/set)"
+}
+
+ethtool_coalesce_params() {
+ if ! ip netns exec "$testns" $ynl_ethtool --show-coalesce "$NSIM_DEV_NAME" &>/dev/null; then
+ echo "FAIL: YNL ethtool coalesce parameters (failed to get coalesce parameters)"
+ return
+ fi
+
+ if ! ip netns exec "$testns" $ynl_ethtool --set-coalesce "$NSIM_DEV_NAME" rx-usecs 50 2>/dev/null; then
+ echo "FAIL: YNL ethtool coalesce parameters (set-coalesce command failed unexpectedly)"
+ return
+ fi
+
+ echo "PASS: YNL ethtool coalesce parameters (show/set)"
+}
+
+ethtool_pause_params() {
+ if ! ip netns exec "$testns" $ynl_ethtool --show-pause "$NSIM_DEV_NAME" &>/dev/null; then
+ echo "FAIL: YNL ethtool pause parameters (failed to get pause parameters)"
+ return
+ fi
+
+ if ! ip netns exec "$testns" $ynl_ethtool --set-pause "$NSIM_DEV_NAME" tx 1 rx 1 2>/dev/null; then
+ echo "FAIL: YNL ethtool pause parameters (set-pause command failed unexpectedly)"
+ return
+ fi
+
+ echo "PASS: YNL ethtool pause parameters (show/set)"
+}
+
+ethtool_features_info() {
+ local features_output
+
+ features_output=$(ip netns exec "$testns" $ynl_ethtool --show-features "$NSIM_DEV_NAME" 2>/dev/null)
+
+ if ! echo "$features_output" | grep -q -E "(Features|offload)"; then
+ echo "FAIL: YNL ethtool features info (features output missing expected content)"
+ return
+ fi
+
+ echo "PASS: YNL ethtool features info (show/set)"
+}
+
+ethtool_channels_info() {
+ local channels_output
+
+ channels_output=$(ip netns exec "$testns" $ynl_ethtool --show-channels "$NSIM_DEV_NAME" 2>/dev/null)
+
+ if ! echo "$channels_output" | grep -q -E "(Channel|Combined|RX|TX)"; then
+ echo "FAIL: YNL ethtool channels info (channels output missing expected content)"
+ return
+ fi
+
+ if ! ip netns exec "$testns" $ynl_ethtool --set-channels "$NSIM_DEV_NAME" combined-count 1 2>/dev/null; then
+ echo "FAIL: YNL ethtool channels info (set-channels command failed unexpectedly)"
+ return
+ fi
+
+ echo "PASS: YNL ethtool channels info (show/set)"
+}
+
+ethtool_time_stamping() {
+ local ts_output
+
+ ts_output=$(ip netns exec "$testns" $ynl_ethtool --show-time-stamping "$NSIM_DEV_NAME" 2>/dev/null)
+
+ if ! echo "$ts_output" | grep -q -E "(Time stamping|timestamping|SOF_TIMESTAMPING)"; then
+ echo "FAIL: YNL ethtool time stamping (time stamping output missing expected content)"
+ return
+ fi
+
+ echo "PASS: YNL ethtool time stamping"
+}
+
+setup() {
+ modprobe netdevsim &> /dev/null
+ if ! [ -f /sys/bus/netdevsim/new_device ]; then
+ echo "SKIP: all YNL ethtool tests (netdevsim module not available)"
+ exit 0
+ fi
+
+ if ! ip netns add "$testns" 2>/dev/null; then
+ echo "SKIP: all YNL ethtool tests (failed to create test namespace)"
+ exit 0
+ fi
+
+ echo "$NSIM_ID 1" | ip netns exec "$testns" tee /sys/bus/netdevsim/new_device >/dev/null 2>&1 || {
+ echo "SKIP: all YNL ethtool tests (failed to create netdevsim device)"
+ exit 0
+ }
+
+ local dev
+ dev=$(ip netns exec "$testns" ls /sys/bus/netdevsim/devices/netdevsim$NSIM_ID/net 2>/dev/null | head -1)
+ if [[ -z "$dev" ]]; then
+ echo "SKIP: all YNL ethtool tests (failed to find netdevsim device)"
+ exit 0
+ fi
+
+ ip -netns "$testns" link set dev "$dev" name "$NSIM_DEV_NAME" 2>/dev/null || {
+ echo "SKIP: all YNL ethtool tests (failed to rename netdevsim device)"
+ exit 0
+ }
+
+ ip -netns "$testns" link set dev "$NSIM_DEV_NAME" up 2>/dev/null
+
+ if ! ip -n "$testns" link add "$VETH_A" type veth peer name "$VETH_B" 2>/dev/null; then
+ echo "SKIP: all YNL ethtool tests (failed to create veth pair)"
+ exit 0
+ fi
+
+ ip -n "$testns" link set "$VETH_A" up 2>/dev/null
+ ip -n "$testns" link set "$VETH_B" up 2>/dev/null
+}
+
+cleanup() {
+ if [[ -n "$testns" ]]; then
+ ip netns exec "$testns" bash -c "echo $NSIM_ID > /sys/bus/netdevsim/del_device" 2>/dev/null || true
+ ip netns del "$testns" 2>/dev/null || true
+ fi
+}
+
+# Check if ynl-ethtool command is available
+if ! command -v $ynl_ethtool &>/dev/null && [[ ! -x $ynl_ethtool ]]; then
+ echo "SKIP: all YNL ethtool tests (ynl-ethtool command not found: $ynl_ethtool)"
+ exit 0
+fi
+
+trap cleanup EXIT
+setup
+
+# Run all tests
+ethtool_device_info
+ethtool_statistics
+ethtool_ring_params
+ethtool_coalesce_params
+ethtool_pause_params
+ethtool_features_info
+ethtool_channels_info
+ethtool_time_stamping
--
2.50.1
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCHv3 net-next 3/3] tools: ynl: add YNL test framework
2025-11-10 10:00 ` [PATCHv3 net-next 3/3] tools: ynl: add YNL test framework Hangbin Liu
@ 2025-11-11 11:51 ` Donald Hunter
2025-11-13 3:57 ` Hangbin Liu
2025-11-13 6:06 ` Hangbin Liu
0 siblings, 2 replies; 15+ messages in thread
From: Donald Hunter @ 2025-11-11 11:51 UTC (permalink / raw)
To: Hangbin Liu
Cc: netdev, Jakub Kicinski, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Jan Stancek, Matthieu Baerts (NGI0),
Asbjørn Sloth Tønnesen, Stanislav Fomichev,
Ido Schimmel, Guillaume Nault, Sabrina Dubroca, Petr Machata
Hangbin Liu <liuhangbin@gmail.com> writes:
> Add a test framework for YAML Netlink (YNL) tools, covering both CLI and
> ethtool functionality. The framework includes:
>
> 1) cli: family listing, netdev, ethtool, rt-* families, and nlctrl
> operations
> 2) ethtool: device info, statistics, ring/coalesce/pause parameters, and
> feature gettings
>
> The current YNL syntax is a bit obscure, and end users may not always know
> how to use it. This test framework provides usage examples and also serves
> as a regression test to catch potential breakages caused by future changes.
>
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
> ---
> tools/net/ynl/Makefile | 8 +-
> tools/net/ynl/tests/Makefile | 38 ++++
> tools/net/ynl/tests/config | 6 +
> tools/net/ynl/tests/test_ynl_cli.sh | 291 ++++++++++++++++++++++++
> tools/net/ynl/tests/test_ynl_ethtool.sh | 196 ++++++++++++++++
> 5 files changed, 537 insertions(+), 2 deletions(-)
> create mode 100644 tools/net/ynl/tests/Makefile
> create mode 100644 tools/net/ynl/tests/config
> create mode 100755 tools/net/ynl/tests/test_ynl_cli.sh
> create mode 100755 tools/net/ynl/tests/test_ynl_ethtool.sh
>
> diff --git a/tools/net/ynl/Makefile b/tools/net/ynl/Makefile
> index 211df5a93ad9..8a328972564a 100644
> --- a/tools/net/ynl/Makefile
> +++ b/tools/net/ynl/Makefile
> @@ -12,7 +12,7 @@ endif
> libdir ?= $(prefix)/$(libdir_relative)
> includedir ?= $(prefix)/include
>
> -SUBDIRS = lib generated samples
> +SUBDIRS = lib generated samples tests
>
> all: $(SUBDIRS) libynl.a
>
> @@ -48,5 +48,9 @@ install: libynl.a lib/*.h
> @echo -e "\tINSTALL pyynl"
> @pip install --prefix=$(DESTDIR)$(prefix) .
> @make -C generated install
> + @make -C tests install
>
> -.PHONY: all clean distclean install $(SUBDIRS)
> +run_tests:
> + @$(MAKE) -C tests run_tests
> +
> +.PHONY: all clean distclean install run_tests $(SUBDIRS)
> diff --git a/tools/net/ynl/tests/Makefile b/tools/net/ynl/tests/Makefile
> new file mode 100644
> index 000000000000..4d527f9c3de9
> --- /dev/null
> +++ b/tools/net/ynl/tests/Makefile
> @@ -0,0 +1,38 @@
> +# SPDX-License-Identifier: GPL-2.0
> +# Makefile for YNL tests
> +
> +TESTS := \
> + test_ynl_cli.sh \
> + test_ynl_ethtool.sh \
> +# end of TESTS
> +
> +all: $(TESTS)
> +
> +run_tests:
> + @echo "Running YNL tests..."
> + @failed=0; \
> + echo "Running test_ynl_cli.sh..."; \
> + ./test_ynl_cli.sh || failed=$$(($$failed + 1)); \
> + echo "Running test_ynl_ethtool.sh..."; \
> + ./test_ynl_ethtool.sh || failed=$$(($$failed + 1)); \
This could iterate through $(TESTS) instead of being hard coded.
> + if [ $$failed -eq 0 ]; then \
> + echo "All tests passed!"; \
> + else \
> + echo "$$failed test(s) failed!"; \
AFAICS this will never be reported since the scripts only ever exit 0.
The message is also a bit misleading since it would be the count of
scripts that failed, not individual tests.
It would be great if the scripts exited with the number of test failures
so the make file could report a total.
> + exit 1; \
> + fi
> +
> +install: $(TESTS)
> + @mkdir -p $(DESTDIR)/usr/bin
> + @for test in $(TESTS); do \
> + name=$$(basename $$test .sh); \
> + sed -e 's|^ynl=.*|ynl="ynl"|' \
> + -e 's|^ynl_ethtool=.*|ynl_ethtool="ynl-ethtool"|' \
> + $$test > $(DESTDIR)/usr/bin/$$name; \
> + chmod +x $(DESTDIR)/usr/bin/$$name; \
> + done
> +
> +clean:
> + @# Nothing to clean
> +
> +.PHONY: all install clean run_tests
> diff --git a/tools/net/ynl/tests/config b/tools/net/ynl/tests/config
> new file mode 100644
> index 000000000000..339f1309c03f
> --- /dev/null
> +++ b/tools/net/ynl/tests/config
> @@ -0,0 +1,6 @@
> +CONFIG_DUMMY=m
> +CONFIG_INET_DIAG=y
> +CONFIG_IPV6=y
> +CONFIG_NET_NS=y
> +CONFIG_NETDEVSIM=m
> +CONFIG_VETH=m
> diff --git a/tools/net/ynl/tests/test_ynl_cli.sh b/tools/net/ynl/tests/test_ynl_cli.sh
> new file mode 100755
> index 000000000000..5cc0624ffaad
> --- /dev/null
> +++ b/tools/net/ynl/tests/test_ynl_cli.sh
> @@ -0,0 +1,291 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +# Test YNL CLI functionality
> +
> +# Default ynl path for direct execution, can be overridden by make install
> +ynl="../pyynl/cli.py"
> +
> +readonly NSIM_ID="1338"
> +readonly NSIM_DEV_NAME="nsim${NSIM_ID}"
> +readonly VETH_A="veth_a"
> +readonly VETH_B="veth_b"
> +
> +testns="ynl-$(mktemp -u XXXXXX)"
> +
> +# Test listing available families
> +cli_list_families() {
> + if $ynl --list-families &>/dev/null; then
> + echo "PASS: YNL CLI list families"
> + else
> + echo "FAIL: YNL CLI list families"
> + fi
> +}
> +
> +# Test netdev family operations (dev-get, queue-get)
> +cli_netdev_ops() {
> + local dev_output
> + local ifindex
> +
> + ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null)
> + if [[ -z "$ifindex" ]]; then
> + echo "FAIL: YNL CLI netdev operations (failed to get ifindex)"
This is a bit misleading, there's no ynl command here so I don't think
it should be a FAIL. Can we just report SKIP when it is an infra issue?
> + return
> + fi
> +
> + dev_output=$(ip netns exec "$testns" $ynl --family netdev \
> + --do dev-get --json "{\"ifindex\": $ifindex}" 2>/dev/null)
> +
> + if ! echo "$dev_output" | grep -q "ifindex"; then
> + echo "FAIL: YNL CLI netdev operations (netdev dev-get output missing ifindex)"
> + return
> + fi
> +
> + if ! ip netns exec "$testns" $ynl --family netdev \
> + --dump queue-get --json "{\"ifindex\": $ifindex}" &>/dev/null; then
> + echo "FAIL: YNL CLI netdev operations (failed to get netdev queue info)"
> + return
> + fi
> +
> + echo "PASS: YNL CLI netdev operations"
> +}
> +
> +# Test ethtool family operations (rings-get, linkinfo-get)
> +cli_ethtool_ops() {
> + local rings_output
> + local linkinfo_output
> +
> + rings_output=$(ip netns exec "$testns" $ynl --family ethtool \
> + --do rings-get --json "{\"header\": {\"dev-name\": \"$NSIM_DEV_NAME\"}}" 2>/dev/null)
> +
> + if ! echo "$rings_output" | grep -q "header"; then
> + echo "FAIL: YNL CLI ethtool operations (ethtool rings-get output missing header)"
> + return
> + fi
> +
> + linkinfo_output=$(ip netns exec "$testns" $ynl --family ethtool \
> + --do linkinfo-get --json "{\"header\": {\"dev-name\": \"$VETH_A\"}}" 2>/dev/null)
> +
> + if ! echo "$linkinfo_output" | grep -q "header"; then
> + echo "FAIL: YNL CLI ethtool operations (ethtool linkinfo-get output missing header)"
> + return
> + fi
> +
> + echo "PASS: YNL CLI ethtool operations"
> +}
> +
> +# Test rt-* family operations (route, addr, link, neigh, rule)
> +cli_rt_ops() {
> + local ifindex
> +
> + if ! $ynl --list-families 2>/dev/null | grep -q "rt-"; then
> + echo "SKIP: YNL CLI rt-* operations (no rt-* families available)"
> + return
> + fi
> +
> + ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null)
> + if [[ -z "$ifindex" ]]; then
> + echo "FAIL: YNL CLI rt-* operations (failed to get ifindex)"
Also FAIL -> SKIP ?
> + return
> + fi
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCHv3 net-next 3/3] tools: ynl: add YNL test framework
2025-11-11 11:51 ` Donald Hunter
@ 2025-11-13 3:57 ` Hangbin Liu
2025-11-13 6:06 ` Hangbin Liu
1 sibling, 0 replies; 15+ messages in thread
From: Hangbin Liu @ 2025-11-13 3:57 UTC (permalink / raw)
To: Donald Hunter
Cc: netdev, Jakub Kicinski, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Jan Stancek, Matthieu Baerts (NGI0),
Asbjørn Sloth Tønnesen, Stanislav Fomichev,
Ido Schimmel, Guillaume Nault, Sabrina Dubroca, Petr Machata
On Tue, Nov 11, 2025 at 11:51:38AM +0000, Donald Hunter wrote:
> > diff --git a/tools/net/ynl/tests/Makefile b/tools/net/ynl/tests/Makefile
> > new file mode 100644
> > index 000000000000..4d527f9c3de9
> > --- /dev/null
> > +++ b/tools/net/ynl/tests/Makefile
> > @@ -0,0 +1,38 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +# Makefile for YNL tests
> > +
> > +TESTS := \
> > + test_ynl_cli.sh \
> > + test_ynl_ethtool.sh \
> > +# end of TESTS
> > +
> > +all: $(TESTS)
> > +
> > +run_tests:
> > + @echo "Running YNL tests..."
> > + @failed=0; \
> > + echo "Running test_ynl_cli.sh..."; \
> > + ./test_ynl_cli.sh || failed=$$(($$failed + 1)); \
> > + echo "Running test_ynl_ethtool.sh..."; \
> > + ./test_ynl_ethtool.sh || failed=$$(($$failed + 1)); \
>
> This could iterate through $(TESTS) instead of being hard coded.
>
> > + if [ $$failed -eq 0 ]; then \
> > + echo "All tests passed!"; \
> > + else \
> > + echo "$$failed test(s) failed!"; \
>
> AFAICS this will never be reported since the scripts only ever exit 0.
> The message is also a bit misleading since it would be the count of
> scripts that failed, not individual tests.
>
> It would be great if the scripts exited with the number of test failures
> so the make file could report a total.
Yes, indeed, I will fix it. Thanks!
> > +# Test netdev family operations (dev-get, queue-get)
> > +cli_netdev_ops() {
> > + local dev_output
> > + local ifindex
> > +
> > + ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null)
> > + if [[ -z "$ifindex" ]]; then
> > + echo "FAIL: YNL CLI netdev operations (failed to get ifindex)"
>
> This is a bit misleading, there's no ynl command here so I don't think
> it should be a FAIL. Can we just report SKIP when it is an infra issue?
The test reported SKIP for infra issue in setup() function.
Here the netdevsim device has already setup. The ifindex should be there.
Maybe I should use ip cmd to get the ifindex number and skip this checking.
> > +
> > +# Test rt-* family operations (route, addr, link, neigh, rule)
> > +cli_rt_ops() {
> > + local ifindex
> > +
> > + if ! $ynl --list-families 2>/dev/null | grep -q "rt-"; then
> > + echo "SKIP: YNL CLI rt-* operations (no rt-* families available)"
> > + return
> > + fi
> > +
> > + ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null)
> > + if [[ -z "$ifindex" ]]; then
> > + echo "FAIL: YNL CLI rt-* operations (failed to get ifindex)"
>
> Also FAIL -> SKIP ?
Same here, the dev has created, I will remove this checking.
Thanks
Hangbin
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCHv3 net-next 3/3] tools: ynl: add YNL test framework
2025-11-11 11:51 ` Donald Hunter
2025-11-13 3:57 ` Hangbin Liu
@ 2025-11-13 6:06 ` Hangbin Liu
2025-11-13 9:21 ` Matthieu Baerts
1 sibling, 1 reply; 15+ messages in thread
From: Hangbin Liu @ 2025-11-13 6:06 UTC (permalink / raw)
To: Donald Hunter
Cc: netdev, Jakub Kicinski, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Jan Stancek, Matthieu Baerts (NGI0),
Asbjørn Sloth Tønnesen, Stanislav Fomichev,
Ido Schimmel, Guillaume Nault, Sabrina Dubroca, Petr Machata
On Tue, Nov 11, 2025 at 11:51:38AM +0000, Donald Hunter wrote:
> > diff --git a/tools/net/ynl/tests/Makefile b/tools/net/ynl/tests/Makefile
> > new file mode 100644
> > index 000000000000..4d527f9c3de9
> > --- /dev/null
> > +++ b/tools/net/ynl/tests/Makefile
> > @@ -0,0 +1,38 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +# Makefile for YNL tests
> > +
> > +TESTS := \
> > + test_ynl_cli.sh \
> > + test_ynl_ethtool.sh \
> > +# end of TESTS
> > +
> > +all: $(TESTS)
> > +
> > +run_tests:
> > + @echo "Running YNL tests..."
> > + @failed=0; \
> > + echo "Running test_ynl_cli.sh..."; \
> > + ./test_ynl_cli.sh || failed=$$(($$failed + 1)); \
> > + echo "Running test_ynl_ethtool.sh..."; \
> > + ./test_ynl_ethtool.sh || failed=$$(($$failed + 1)); \
>
> This could iterate through $(TESTS) instead of being hard coded.
>
> > + if [ $$failed -eq 0 ]; then \
> > + echo "All tests passed!"; \
> > + else \
> > + echo "$$failed test(s) failed!"; \
>
> AFAICS this will never be reported since the scripts only ever exit 0.
> The message is also a bit misleading since it would be the count of
> scripts that failed, not individual tests.
>
> It would be great if the scripts exited with the number of test failures
> so the make file could report a total.
Oh, BTW, do you think if we should exit with the failed test number or just
report failed number in test and exit 1. i.e.
Option 1:
test 1 (pass)
test 2 (fail)
test 3 (fail)
exit 2
Option 2:
test 1 (pass)
test 2 (fail)
test 3 (fail)
echo "2 test failed"
exit 1
With Option 1, we will summary all the failure number in the Makefile.
With Option 2, we will report failure number in each test, and report failed
*test script* number in Makefile.
Thanks
Hangbin
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCHv3 net-next 3/3] tools: ynl: add YNL test framework
2025-11-13 6:06 ` Hangbin Liu
@ 2025-11-13 9:21 ` Matthieu Baerts
2025-11-13 9:51 ` Hangbin Liu
0 siblings, 1 reply; 15+ messages in thread
From: Matthieu Baerts @ 2025-11-13 9:21 UTC (permalink / raw)
To: Hangbin Liu, Donald Hunter
Cc: netdev, Jakub Kicinski, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Jan Stancek,
Asbjørn Sloth Tønnesen, Stanislav Fomichev,
Ido Schimmel, Guillaume Nault, Sabrina Dubroca, Petr Machata
Hi Hangbin,
On 13/11/2025 07:06, Hangbin Liu wrote:
> On Tue, Nov 11, 2025 at 11:51:38AM +0000, Donald Hunter wrote:
>>> diff --git a/tools/net/ynl/tests/Makefile b/tools/net/ynl/tests/Makefile
>>> new file mode 100644
>>> index 000000000000..4d527f9c3de9
>>> --- /dev/null
>>> +++ b/tools/net/ynl/tests/Makefile
>>> @@ -0,0 +1,38 @@
>>> +# SPDX-License-Identifier: GPL-2.0
>>> +# Makefile for YNL tests
>>> +
>>> +TESTS := \
>>> + test_ynl_cli.sh \
>>> + test_ynl_ethtool.sh \
>>> +# end of TESTS
>>> +
>>> +all: $(TESTS)
>>> +
>>> +run_tests:
>>> + @echo "Running YNL tests..."
>>> + @failed=0; \
>>> + echo "Running test_ynl_cli.sh..."; \
>>> + ./test_ynl_cli.sh || failed=$$(($$failed + 1)); \
>>> + echo "Running test_ynl_ethtool.sh..."; \
>>> + ./test_ynl_ethtool.sh || failed=$$(($$failed + 1)); \
>>
>> This could iterate through $(TESTS) instead of being hard coded.
>>
>>> + if [ $$failed -eq 0 ]; then \
>>> + echo "All tests passed!"; \
>>> + else \
>>> + echo "$$failed test(s) failed!"; \
>>
>> AFAICS this will never be reported since the scripts only ever exit 0.
>> The message is also a bit misleading since it would be the count of
>> scripts that failed, not individual tests.
>>
>> It would be great if the scripts exited with the number of test failures
>> so the make file could report a total.
>
> Oh, BTW, do you think if we should exit with the failed test number or just
I know these new tests are not in the selftests, but maybe "safer" to
keep the same exit code to avoid being misinterpreted?
KSFT_PASS=0
KSFT_FAIL=1
KSFT_XFAIL=2
KSFT_XPASS=3
KSFT_SKIP=4
If there is a need to know which tests have failed, why not using (K)TAP
format for the output?
Cheers,
Matt
--
Sponsored by the NGI0 Core fund.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCHv3 net-next 3/3] tools: ynl: add YNL test framework
2025-11-13 9:21 ` Matthieu Baerts
@ 2025-11-13 9:51 ` Hangbin Liu
2025-11-13 9:59 ` Matthieu Baerts
0 siblings, 1 reply; 15+ messages in thread
From: Hangbin Liu @ 2025-11-13 9:51 UTC (permalink / raw)
To: Matthieu Baerts
Cc: Donald Hunter, netdev, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, Simon Horman, Jan Stancek,
Asbjørn Sloth Tønnesen, Stanislav Fomichev,
Ido Schimmel, Guillaume Nault, Sabrina Dubroca, Petr Machata
On Thu, Nov 13, 2025 at 10:21:41AM +0100, Matthieu Baerts wrote:
> >>> + if [ $$failed -eq 0 ]; then \
> >>> + echo "All tests passed!"; \
> >>> + else \
> >>> + echo "$$failed test(s) failed!"; \
> >>
> >> AFAICS this will never be reported since the scripts only ever exit 0.
> >> The message is also a bit misleading since it would be the count of
> >> scripts that failed, not individual tests.
> >>
> >> It would be great if the scripts exited with the number of test failures
> >> so the make file could report a total.
> >
> > Oh, BTW, do you think if we should exit with the failed test number or just
>
> I know these new tests are not in the selftests, but maybe "safer" to
> keep the same exit code to avoid being misinterpreted?
>
> KSFT_PASS=0
> KSFT_FAIL=1
> KSFT_XFAIL=2
> KSFT_XPASS=3
> KSFT_SKIP=4
Yes, that's why I ask about the return code. I also prefer use the same exit
code with selftest.
>
> If there is a need to know which tests have failed, why not using (K)TAP
> format for the output?
I feel it's too heavy to copy the (K)TAP format here. I would just using the
exit code unless Jakub ask to using the specific output format
Thanks
Hangbin
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCHv3 net-next 3/3] tools: ynl: add YNL test framework
2025-11-13 9:51 ` Hangbin Liu
@ 2025-11-13 9:59 ` Matthieu Baerts
2025-11-13 12:33 ` Hangbin Liu
0 siblings, 1 reply; 15+ messages in thread
From: Matthieu Baerts @ 2025-11-13 9:59 UTC (permalink / raw)
To: Hangbin Liu
Cc: Donald Hunter, netdev, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, Simon Horman, Jan Stancek,
Asbjørn Sloth Tønnesen, Stanislav Fomichev,
Ido Schimmel, Guillaume Nault, Sabrina Dubroca, Petr Machata
On 13/11/2025 10:51, Hangbin Liu wrote:
> On Thu, Nov 13, 2025 at 10:21:41AM +0100, Matthieu Baerts wrote:
>>>>> + if [ $$failed -eq 0 ]; then \
>>>>> + echo "All tests passed!"; \
>>>>> + else \
>>>>> + echo "$$failed test(s) failed!"; \
>>>>
>>>> AFAICS this will never be reported since the scripts only ever exit 0.
>>>> The message is also a bit misleading since it would be the count of
>>>> scripts that failed, not individual tests.
>>>>
>>>> It would be great if the scripts exited with the number of test failures
>>>> so the make file could report a total.
>>>
>>> Oh, BTW, do you think if we should exit with the failed test number or just
>>
>> I know these new tests are not in the selftests, but maybe "safer" to
>> keep the same exit code to avoid being misinterpreted?
>>
>> KSFT_PASS=0
>> KSFT_FAIL=1
>> KSFT_XFAIL=2
>> KSFT_XPASS=3
>> KSFT_SKIP=4
>
> Yes, that's why I ask about the return code. I also prefer use the same exit
> code with selftest.
Should you then exit with rc=4 instead of 0 in case of SKIP?
>> If there is a need to know which tests have failed, why not using (K)TAP
>> format for the output?
>
> I feel it's too heavy to copy the (K)TAP format here. I would just using the
> exit code unless Jakub ask to using the specific output format
OK, I thought it was just a question of changing your 'echo' from "PASS"
and "FAIL" to "(not )ok ${COUNTER} (...)" + print the header and the
number of tests. But sure, if this format is not needed, no need to bother.
Cheers,
Matt
--
Sponsored by the NGI0 Core fund.
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCHv3 net-next 3/3] tools: ynl: add YNL test framework
2025-11-13 9:59 ` Matthieu Baerts
@ 2025-11-13 12:33 ` Hangbin Liu
2025-11-13 14:26 ` Matthieu Baerts
0 siblings, 1 reply; 15+ messages in thread
From: Hangbin Liu @ 2025-11-13 12:33 UTC (permalink / raw)
To: Matthieu Baerts
Cc: Donald Hunter, netdev, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, Simon Horman, Jan Stancek,
Asbjørn Sloth Tønnesen, Stanislav Fomichev,
Ido Schimmel, Guillaume Nault, Sabrina Dubroca, Petr Machata
On Thu, Nov 13, 2025 at 10:59:49AM +0100, Matthieu Baerts wrote:
> >> I know these new tests are not in the selftests, but maybe "safer" to
> >> keep the same exit code to avoid being misinterpreted?
> >>
> >> KSFT_PASS=0
> >> KSFT_FAIL=1
> >> KSFT_XFAIL=2
> >> KSFT_XPASS=3
> >> KSFT_SKIP=4
> >
> > Yes, that's why I ask about the return code. I also prefer use the same exit
> > code with selftest.
>
> Should you then exit with rc=4 instead of 0 in case of SKIP?
Sure
>
> >> If there is a need to know which tests have failed, why not using (K)TAP
> >> format for the output?
> >
> > I feel it's too heavy to copy the (K)TAP format here. I would just using the
> > exit code unless Jakub ask to using the specific output format
>
> OK, I thought it was just a question of changing your 'echo' from "PASS"
> and "FAIL" to "(not )ok ${COUNTER} (...)" + print the header and the
> number of tests. But sure, if this format is not needed, no need to bother.
Oh, this looks reasonable. I will try add a helper for the output.
Thanks
Hangbin
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCHv3 net-next 3/3] tools: ynl: add YNL test framework
2025-11-13 12:33 ` Hangbin Liu
@ 2025-11-13 14:26 ` Matthieu Baerts
0 siblings, 0 replies; 15+ messages in thread
From: Matthieu Baerts @ 2025-11-13 14:26 UTC (permalink / raw)
To: Hangbin Liu
Cc: Donald Hunter, netdev, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, Simon Horman, Jan Stancek,
Asbjørn Sloth Tønnesen, Stanislav Fomichev,
Ido Schimmel, Guillaume Nault, Sabrina Dubroca, Petr Machata
On 13/11/2025 13:33, Hangbin Liu wrote:
> On Thu, Nov 13, 2025 at 10:59:49AM +0100, Matthieu Baerts wrote:
(...)
>>>> If there is a need to know which tests have failed, why not using (K)TAP
>>>> format for the output?
>>>
>>> I feel it's too heavy to copy the (K)TAP format here. I would just using the
>>> exit code unless Jakub ask to using the specific output format
>>
>> OK, I thought it was just a question of changing your 'echo' from "PASS"
>> and "FAIL" to "(not )ok ${COUNTER} (...)" + print the header and the
>> number of tests. But sure, if this format is not needed, no need to bother.
>
> Oh, this looks reasonable. I will try add a helper for the output.
I don't know if it is a good idea for these tests, but maybe you can use
existing ones from tools/testing/selftests/kselftest/ktap_helpers.sh?
Cheers,
Matt
--
Sponsored by the NGI0 Core fund.
^ permalink raw reply [flat|nested] 15+ messages in thread