netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv2 net-next 0/3] Add YNL test framework and library improvements
@ 2025-11-05  8:28 Hangbin Liu
  2025-11-05  8:28 ` [PATCHv2 net-next 1/3] tools: ynl: Add MAC address parsing support Hangbin Liu
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Hangbin Liu @ 2025-11-05  8:28 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, Petr Machata, Hangbin Liu

This series enhances YNL tools with some functionalities and adds
YNL test framework.

Changes include:
- Add MAC address parsing support in YNL library
- Fix rt-rule spec consistency with other rt-* families
- Add tests covering CLI and ethtool functionality

The tests provide usage examples and regression testing for YNL tools.
Test result:
  # test_ynl_cli
  PASS: YNL CLI list families
  PASS: YNL CLI netdev operations
  PASS: YNL CLI ethtool operations
  PASS: YNL CLI rt-route operations
  PASS: YNL CLI rt-addr operations
  PASS: YNL CLI rt-link operations
  PASS: YNL CLI rt-neigh operations
  PASS: YNL CLI rt-rule operations
  PASS: YNL CLI nlctrl getfamily
  # test_ynl_ethtool
  PASS: YNL ethtool device info
  PASS: YNL ethtool statistics
  PASS: YNL ethtool ring parameters (show/set)
  PASS: YNL ethtool coalesce parameters (show/set)
  PASS: YNL ethtool pause parameters (show/set)
  PASS: YNL ethtool features info (show/set)
  PASS: YNL ethtool channels info (show/set)
  PASS: YNL ethtool time stamping

v2: move test from selftest to ynl folder (Jakub Kicinski)
v1: https://lore.kernel.org/netdev/20251029082245.128675-1-liuhangbin@gmail.com

Hangbin Liu (3):
  tools: ynl: Add MAC address parsing support
  netlink: specs: update rt-rule src/dst attribute types to support IPv4
    addresses
  tools: ynl: add YNL test framework

 Documentation/netlink/specs/rt-rule.yaml |   6 +-
 tools/net/ynl/Makefile                   |   3 +-
 tools/net/ynl/pyynl/lib/ynl.py           |   9 +
 tools/net/ynl/tests/Makefile             |  24 ++
 tools/net/ynl/tests/config               |   6 +
 tools/net/ynl/tests/test_ynl_cli.sh      | 290 +++++++++++++++++++++++
 tools/net/ynl/tests/test_ynl_ethtool.sh  | 195 +++++++++++++++
 7 files changed, 530 insertions(+), 3 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

-- 
2.50.1


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

* [PATCHv2 net-next 1/3] tools: ynl: Add MAC address parsing support
  2025-11-05  8:28 [PATCHv2 net-next 0/3] Add YNL test framework and library improvements Hangbin Liu
@ 2025-11-05  8:28 ` Hangbin Liu
  2025-11-05  8:28 ` [PATCHv2 net-next 2/3] netlink: specs: update rt-rule src/dst attribute types to support IPv4 addresses Hangbin Liu
  2025-11-05  8:28 ` [PATCHv2 net-next 3/3] tools: ynl: add YNL test framework Hangbin Liu
  2 siblings, 0 replies; 9+ messages in thread
From: Hangbin Liu @ 2025-11-05  8:28 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, 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] 9+ messages in thread

* [PATCHv2 net-next 2/3] netlink: specs: update rt-rule src/dst attribute types to support IPv4 addresses
  2025-11-05  8:28 [PATCHv2 net-next 0/3] Add YNL test framework and library improvements Hangbin Liu
  2025-11-05  8:28 ` [PATCHv2 net-next 1/3] tools: ynl: Add MAC address parsing support Hangbin Liu
@ 2025-11-05  8:28 ` Hangbin Liu
  2025-11-05  8:28 ` [PATCHv2 net-next 3/3] tools: ynl: add YNL test framework Hangbin Liu
  2 siblings, 0 replies; 9+ messages in thread
From: Hangbin Liu @ 2025-11-05  8:28 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, Petr Machata, Hangbin Liu

Similar with other rt-* family specs (rt-route, rt-addr, rt-neigh), change
src and dst attributes in rt-rule.yaml from type u32 to type binary with
display-hint ipv4 to properly support IPv4/IPv6 address operations.

Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
 Documentation/netlink/specs/rt-rule.yaml | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/Documentation/netlink/specs/rt-rule.yaml b/Documentation/netlink/specs/rt-rule.yaml
index bebee452a950..7ebd95312ee4 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
       -
         name: src
-        type: u32
+        type: binary
+        display-hint: ipv4
       -
         name: iifname
         type: string
-- 
2.50.1


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

* [PATCHv2 net-next 3/3] tools: ynl: add YNL test framework
  2025-11-05  8:28 [PATCHv2 net-next 0/3] Add YNL test framework and library improvements Hangbin Liu
  2025-11-05  8:28 ` [PATCHv2 net-next 1/3] tools: ynl: Add MAC address parsing support Hangbin Liu
  2025-11-05  8:28 ` [PATCHv2 net-next 2/3] netlink: specs: update rt-rule src/dst attribute types to support IPv4 addresses Hangbin Liu
@ 2025-11-05  8:28 ` Hangbin Liu
  2025-11-05 17:00   ` Sabrina Dubroca
  2025-11-06  2:33   ` Jakub Kicinski
  2 siblings, 2 replies; 9+ messages in thread
From: Hangbin Liu @ 2025-11-05  8:28 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, 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                  |   3 +-
 tools/net/ynl/tests/Makefile            |  24 ++
 tools/net/ynl/tests/config              |   6 +
 tools/net/ynl/tests/test_ynl_cli.sh     | 290 ++++++++++++++++++++++++
 tools/net/ynl/tests/test_ynl_ethtool.sh | 195 ++++++++++++++++
 5 files changed, 517 insertions(+), 1 deletion(-)
 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..89a9cd0a1306 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,6 @@ 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)
diff --git a/tools/net/ynl/tests/Makefile b/tools/net/ynl/tests/Makefile
new file mode 100644
index 000000000000..10bca7fe54c5
--- /dev/null
+++ b/tools/net/ynl/tests/Makefile
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: GPL-2.0
+# Makefile for YNL tests
+
+TESTS := \
+	test_ynl_cli.sh \
+	test_ynl_ethtool.sh \
+# end of TESTS
+
+all: $(TESTS)
+
+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
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..53e66f7aeeb4
--- /dev/null
+++ b/tools/net/ynl/tests/test_ynl_cli.sh
@@ -0,0 +1,290 @@
+#!/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() {
+	if ! modprobe netdevsim &>/dev/null; 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..ca60b8adc126
--- /dev/null
+++ b/tools/net/ynl/tests/test_ynl_ethtool.sh
@@ -0,0 +1,195 @@
+#!/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() {
+	if ! modprobe netdevsim &>/dev/null; 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] 9+ messages in thread

* Re: [PATCHv2 net-next 3/3] tools: ynl: add YNL test framework
  2025-11-05  8:28 ` [PATCHv2 net-next 3/3] tools: ynl: add YNL test framework Hangbin Liu
@ 2025-11-05 17:00   ` Sabrina Dubroca
  2025-11-06  1:39     ` Hangbin Liu
  2025-11-06  2:33   ` Jakub Kicinski
  1 sibling, 1 reply; 9+ messages in thread
From: Sabrina Dubroca @ 2025-11-05 17:00 UTC (permalink / raw)
  To: Hangbin Liu
  Cc: netdev, 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, Petr Machata

2025-11-05, 08:28:41 +0000, Hangbin Liu wrote:
> +setup() {
> +	if ! modprobe netdevsim &>/dev/null; then
> +		echo "SKIP: all YNL CLI tests (netdevsim module not available)"

Can we maybe find a way to try to load the module and still run the
test if modprobe fails but netdevsim is built-in? I usually do my
testing in VMs with kernels where everything I need is built in, so I
don't do "make modules_install" and "modprobe netdevsim" fails even if
netdevsim is actually available (because it's built in).

For some modules it may be difficult, for netdevsim we could just run
modprobe (but ignore its return value) and check if
/sys/bus/netdevsim/new_device exists to decide if we need to skip the
tests?


Or do we only expect selftests/those new tests to run with the
standard net selftests config, and not with custom configs that also
provide all the required features?

-- 
Sabrina

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

* Re: [PATCHv2 net-next 3/3] tools: ynl: add YNL test framework
  2025-11-05 17:00   ` Sabrina Dubroca
@ 2025-11-06  1:39     ` Hangbin Liu
  0 siblings, 0 replies; 9+ messages in thread
From: Hangbin Liu @ 2025-11-06  1:39 UTC (permalink / raw)
  To: Sabrina Dubroca
  Cc: netdev, 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, Petr Machata

On Wed, Nov 05, 2025 at 06:00:06PM +0100, Sabrina Dubroca wrote:
> 2025-11-05, 08:28:41 +0000, Hangbin Liu wrote:
> > +setup() {
> > +	if ! modprobe netdevsim &>/dev/null; then
> > +		echo "SKIP: all YNL CLI tests (netdevsim module not available)"
> 
> Can we maybe find a way to try to load the module and still run the
> test if modprobe fails but netdevsim is built-in? I usually do my
> testing in VMs with kernels where everything I need is built in, so I
> don't do "make modules_install" and "modprobe netdevsim" fails even if
> netdevsim is actually available (because it's built in).
> 
> For some modules it may be difficult, for netdevsim we could just run
> modprobe (but ignore its return value) and check if
> /sys/bus/netdevsim/new_device exists to decide if we need to skip the
> tests?

Yes, could be.
> 
> 
> Or do we only expect selftests/those new tests to run with the
> standard net selftests config, and not with custom configs that also
> provide all the required features?

I do not have a preference. I added a config file to the test folder. However,
this config file is just for reference.

Thanks
Hangbin

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

* Re: [PATCHv2 net-next 3/3] tools: ynl: add YNL test framework
  2025-11-05  8:28 ` [PATCHv2 net-next 3/3] tools: ynl: add YNL test framework Hangbin Liu
  2025-11-05 17:00   ` Sabrina Dubroca
@ 2025-11-06  2:33   ` Jakub Kicinski
  2025-11-06  2:40     ` Hangbin Liu
  1 sibling, 1 reply; 9+ messages in thread
From: Jakub Kicinski @ 2025-11-06  2:33 UTC (permalink / raw)
  To: Hangbin Liu
  Cc: netdev, Donald Hunter, 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, Petr Machata

On Wed,  5 Nov 2025 08:28:41 +0000 Hangbin Liu wrote:
> 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.

And how would we run all the tests in the new directory?

Since we have two test files we need some way to run all.

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

* Re: [PATCHv2 net-next 3/3] tools: ynl: add YNL test framework
  2025-11-06  2:33   ` Jakub Kicinski
@ 2025-11-06  2:40     ` Hangbin Liu
  2025-11-06 14:45       ` Jakub Kicinski
  0 siblings, 1 reply; 9+ messages in thread
From: Hangbin Liu @ 2025-11-06  2:40 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: netdev, Donald Hunter, 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, Petr Machata

On Wed, Nov 05, 2025 at 06:33:13PM -0800, Jakub Kicinski wrote:
> On Wed,  5 Nov 2025 08:28:41 +0000 Hangbin Liu wrote:
> > 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.
> 
> And how would we run all the tests in the new directory?
> 
> Since we have two test files we need some way to run all.

I didn't get your requirement. We can run them one by one in the test folder.

 # ./test_ynl_cli.sh
 # ./test_ynl_ethtool.sh

Do you want to use a wrapper to run the 2 tests? e.g.
 # ./run_all_ynl_tests.sh

Thanks
Hangbin

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

* Re: [PATCHv2 net-next 3/3] tools: ynl: add YNL test framework
  2025-11-06  2:40     ` Hangbin Liu
@ 2025-11-06 14:45       ` Jakub Kicinski
  0 siblings, 0 replies; 9+ messages in thread
From: Jakub Kicinski @ 2025-11-06 14:45 UTC (permalink / raw)
  To: Hangbin Liu
  Cc: netdev, Donald Hunter, 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, Petr Machata

On Thu, 6 Nov 2025 02:40:25 +0000 Hangbin Liu wrote:
> On Wed, Nov 05, 2025 at 06:33:13PM -0800, Jakub Kicinski wrote:
> > On Wed,  5 Nov 2025 08:28:41 +0000 Hangbin Liu wrote:  
> > > 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.  
> > 
> > And how would we run all the tests in the new directory?
> > 
> > Since we have two test files we need some way to run all.  
> 
> I didn't get your requirement. We can run them one by one in the test folder.
> 
>  # ./test_ynl_cli.sh
>  # ./test_ynl_ethtool.sh
> 
> Do you want to use a wrapper to run the 2 tests? e.g.
>  # ./run_all_ynl_tests.sh

Or make run_tests, like ksft

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

end of thread, other threads:[~2025-11-06 14:45 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-05  8:28 [PATCHv2 net-next 0/3] Add YNL test framework and library improvements Hangbin Liu
2025-11-05  8:28 ` [PATCHv2 net-next 1/3] tools: ynl: Add MAC address parsing support Hangbin Liu
2025-11-05  8:28 ` [PATCHv2 net-next 2/3] netlink: specs: update rt-rule src/dst attribute types to support IPv4 addresses Hangbin Liu
2025-11-05  8:28 ` [PATCHv2 net-next 3/3] tools: ynl: add YNL test framework Hangbin Liu
2025-11-05 17:00   ` Sabrina Dubroca
2025-11-06  1:39     ` Hangbin Liu
2025-11-06  2:33   ` Jakub Kicinski
2025-11-06  2:40     ` Hangbin Liu
2025-11-06 14:45       ` Jakub Kicinski

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