This series enhances YNL tools with some functionalities and adds YNL selftest framework.
Changes include: - Add MAC address parsing support in YNL library - Fix rt-rule spec consistency with other rt-* families - Add selftests covering CLI and ethtool functionality
The tests provide usage examples and regression testing for YNL tools.
Hangbin Liu (3): tools: ynl: Add MAC address parsing support netlink: specs: update rt-rule src/dst attribute types to support IPv4 addresses selftests: net: add YNL test framework
Documentation/netlink/specs/rt-rule.yaml | 6 +- tools/net/ynl/pyynl/lib/ynl.py | 9 + tools/testing/selftests/Makefile | 1 + tools/testing/selftests/net/ynl/Makefile | 18 ++ tools/testing/selftests/net/ynl/cli.sh | 234 +++++++++++++++++++++ tools/testing/selftests/net/ynl/config | 6 + tools/testing/selftests/net/ynl/ethtool.sh | 188 +++++++++++++++++ tools/testing/selftests/net/ynl/settings | 1 + 8 files changed, 461 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/net/ynl/Makefile create mode 100755 tools/testing/selftests/net/ynl/cli.sh create mode 100644 tools/testing/selftests/net/ynl/config create mode 100755 tools/testing/selftests/net/ynl/ethtool.sh create mode 100644 tools/testing/selftests/net/ynl/settings
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']}'")
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 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
On Wed, 29 Oct 2025 08:22:44 +0000 Hangbin Liu wrote:
- name: dst
type: u32
type: binarydisplay-hint: ipv4 - name: src
type: u32
type: binarydisplay-hint: ipv4
This will be annoying For C / C++, and you didn't set the max len so I think we'll also have to malloc each time. Do we not support display-hint for scalars?
On Wed, Oct 29, 2025 at 04:37:42PM -0700, Jakub Kicinski wrote:
On Wed, 29 Oct 2025 08:22:44 +0000 Hangbin Liu wrote:
- name: dst
type: u32
type: binarydisplay-hint: ipv4 - name: src
type: u32
type: binarydisplay-hint: ipv4This will be annoying For C / C++, and you didn't set the max len so I think we'll also have to malloc each time. Do we not support display-hint for scalars?
Ah, I didn't notice this. Should we convert all the
type: binary display-hint: ipv4
to
type: u32 byte-order: big-endian display-hint: ipv4
Thanks Hangbin
On Thu, 30 Oct 2025 06:35:18 +0000 Hangbin Liu wrote:
This will be annoying For C / C++, and you didn't set the max len so I think we'll also have to malloc each time. Do we not support display-hint for scalars?
Ah, I didn't notice this. Should we convert all the
type: binary display-hint: ipv4
to
type: u32 byte-order: big-endian display-hint: ipv4
I think we should try. Technically it may change some kernel policies, but without min/max-like checks the byte-order should be a nop for the policy.
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/testing/selftests/Makefile | 1 + tools/testing/selftests/net/ynl/Makefile | 18 ++ tools/testing/selftests/net/ynl/cli.sh | 234 +++++++++++++++++++++ tools/testing/selftests/net/ynl/config | 6 + tools/testing/selftests/net/ynl/ethtool.sh | 188 +++++++++++++++++ tools/testing/selftests/net/ynl/settings | 1 + 6 files changed, 448 insertions(+) create mode 100644 tools/testing/selftests/net/ynl/Makefile create mode 100755 tools/testing/selftests/net/ynl/cli.sh create mode 100644 tools/testing/selftests/net/ynl/config create mode 100755 tools/testing/selftests/net/ynl/ethtool.sh create mode 100644 tools/testing/selftests/net/ynl/settings
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index c46ebdb9b8ef..3335a8dc7cff 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -78,6 +78,7 @@ TARGETS += net/ovpn TARGETS += net/packetdrill TARGETS += net/rds TARGETS += net/tcp_ao +TARGETS += net/ynl TARGETS += nolibc TARGETS += nsfs TARGETS += pci_endpoint diff --git a/tools/testing/selftests/net/ynl/Makefile b/tools/testing/selftests/net/ynl/Makefile new file mode 100644 index 000000000000..0144c47b69ab --- /dev/null +++ b/tools/testing/selftests/net/ynl/Makefile @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# Makefile for YNL tests + +TEST_PROGS := \ + cli.sh \ + ethtool.sh \ +# end of TEST_PROGS + +TEST_FILES := \ + settings \ +# end of TEST_FILES + +TEST_INCLUDES := \ + $(wildcard ../lib/sh/*.sh) \ + ../lib.sh \ +# end of TEST_INCLUDES + +include ../../lib.mk diff --git a/tools/testing/selftests/net/ynl/cli.sh b/tools/testing/selftests/net/ynl/cli.sh new file mode 100755 index 000000000000..ecc2e349c4e6 --- /dev/null +++ b/tools/testing/selftests/net/ynl/cli.sh @@ -0,0 +1,234 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Test YNL CLI functionality + +# shellcheck disable=SC1091,SC2034,SC2154,SC2317 +source ../lib.sh + +readonly NSIM_ID="1338" +readonly NSIM_DEV_NAME="nsim${NSIM_ID}" +readonly VETH_A="veth_a" +readonly VETH_B="veth_b" + +ALL_TESTS=" + cli_list_families + cli_netdev_ops + cli_ethtool_ops + cli_rt_ops + cli_nlctrl_ops +" + +# Test listing available families +cli_list_families() +{ + RET=0 + + ynl --list-families &>/dev/null + check_err $? "failed to list families" + + log_test "YNL CLI list families" +} + +# Test netdev family operations (dev-get, queue-get) +cli_netdev_ops() +{ + RET=0 + + local dev_output + local ifindex + ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex) + + dev_output=$(ip netns exec "$testns" ynl --family netdev \ + --do dev-get --json "{"ifindex": $ifindex}" 2>/dev/null) + check_err $? "failed to get netdev dev info for $NSIM_DEV_NAME" + + echo "$dev_output" | grep -q "ifindex" + check_err $? "netdev dev-get output missing ifindex" + + ip netns exec "$testns" ynl --family netdev \ + --dump queue-get --json "{"ifindex": $ifindex}" &>/dev/null + check_err $? "failed to get netdev queue info for $NSIM_DEV_NAME" + + log_test "YNL CLI netdev operations" +} + +# Test ethtool family operations (rings-get, linkinfo-get) +cli_ethtool_ops() +{ + RET=0 + + local rings_output + rings_output=$(ip netns exec "$testns" ynl --family ethtool \ + --do rings-get --json "{"header": {"dev-name": "$NSIM_DEV_NAME"}}" 2>/dev/null) + check_err $? "failed to get ethtool rings info for $NSIM_DEV_NAME" + + echo "$rings_output" | grep -q "header" + check_err $? "ethtool rings-get output missing header" + + local linkinfo_output + linkinfo_output=$(ip netns exec "$testns" ynl --family ethtool \ + --do linkinfo-get --json "{"header": {"dev-name": "$VETH_A"}}" 2>/dev/null) + check_err $? "failed to get ethtool linkinfo for $VETH_A" + + echo "$linkinfo_output" | grep -q "header" + check_err $? "ethtool linkinfo-get output missing header" + + log_test "YNL CLI ethtool operations" +} + +# Test rt-* family operations (route, addr, link, neigh, rule) +cli_rt_ops() +{ + RET=0 + if ! ynl --list-families 2>/dev/null | grep -q "rt-"; then + log_test_skip "YNL CLI rt-* operations" "no rt-* families available" + return "$ksft_skip" + fi + + local ifindex + ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex) + + if ynl --list-families 2>/dev/null | grep -q "rt-route"; then + # Add route: 192.0.2.0/24 dev $dev scope link + 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 + + local route_output + route_output=$(ip netns exec "$testns" ynl --family rt-route \ + --dump getroute 2>/dev/null) + check_err $? "failed to get route info" + + echo "$route_output" | grep -q "192.0.2.0" + check_err $? "added route 192.0.2.0 not found in route output" + + 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 + fi + + if ynl --list-families 2>/dev/null | grep -q "rt-addr"; then + 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 + + local addr_output + addr_output=$(ip netns exec "$testns" ynl --family rt-addr \ + --dump getaddr 2>/dev/null) + check_err $? "failed to get address info" + + echo "$addr_output" | grep -q "192.0.2.100" + check_err $? "added address 192.0.2.100 not found in address output" + + 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 + fi + + if ynl --list-families 2>/dev/null | grep -q "rt-link"; then + ip netns exec "$testns" ynl --family rt-link --do newlink --create \ + --json "{"ifname": "dummy0", "linkinfo": {"kind": "dummy"}}" &>/dev/null + + local link_output + link_output=$(ip netns exec "$testns" ynl --family rt-link \ + --dump getlink 2>/dev/null) + check_err $? "failed to get link info" + + echo "$link_output" | grep -q "$NSIM_DEV_NAME" + check_err $? "test device not found in link output" + + echo "$link_output" | grep -q "dummy0" + check_err $? "created dummy0 interface not found in link output" + + ip netns exec "$testns" ynl --family rt-link --do dellink \ + --json "{"ifname": "dummy0"}" &>/dev/null + fi + + 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 + 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 + + local neigh_output + neigh_output=$(ip netns exec "$testns" ynl --family rt-neigh \ + --dump getneigh 2>/dev/null) + check_err $? "failed to get neighbor info" + + echo "$neigh_output" | grep -q "192.0.2.1" + check_err $? "added neighbor 192.0.2.1 not found in neighbor output" + + 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 + fi + + if ynl --list-families 2>/dev/null | grep -q "rt-rule"; then + # Add rule: from 192.0.2.0/24 lookup 100 none + 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 + + local rule_output + rule_output=$(ip netns exec "$testns" ynl --family rt-rule \ + --dump getrule 2>/dev/null) + check_err $? "failed to get rule info" + + echo "$rule_output" | grep -q "192.0.2.0" + check_err $? "added rule with src 192.0.2.0 not found in rule output" + + 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 + fi + + log_test "YNL CLI rt-* operations" +} + +# Test nlctrl family operations +cli_nlctrl_ops() +{ + RET=0 + + local family_output + family_output=$(ynl --family nlctrl \ + --do getfamily --json "{"family-name": "netdev"}" 2>/dev/null) + check_err $? "failed to get nlctrl family info for netdev" + + echo "$family_output" | grep -q "family-name" + check_err $? "nlctrl getfamily output missing family-name" + + echo "$family_output" | grep -q "family-id" + check_err $? "nlctrl getfamily output missing family-id" + + log_test "YNL CLI nlctrl getfamily" +} + +setup() +{ + if ! modprobe netdevsim &>/dev/null; then + log_test_skip "all YNL CLI tests" "netdevsim module not available" + exit "$ksft_skip" + fi + + setup_ns testns + + if ! create_netdevsim "$NSIM_ID" "$testns" &>/dev/null; then + log_test_skip "all YNL CLI tests" "failed to create netdevsim device" + exit "$ksft_skip" + fi + + if ! ip -n "$testns" link add "$VETH_A" type veth peer name "$VETH_B"; then + log_test_skip "all YNL CLI tests" "failed to create veth pair" + exit "$ksft_skip" + fi + + ip -n "$testns" link set "$VETH_A" up + ip -n "$testns" link set "$VETH_B" up +} + +cleanup() +{ + cleanup_netdevsim "$NSIM_ID" + cleanup_all_ns +} + +trap cleanup EXIT + +require_command "ynl" +setup +tests_run + +exit "$EXIT_STATUS" diff --git a/tools/testing/selftests/net/ynl/config b/tools/testing/selftests/net/ynl/config new file mode 100644 index 000000000000..339f1309c03f --- /dev/null +++ b/tools/testing/selftests/net/ynl/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/testing/selftests/net/ynl/ethtool.sh b/tools/testing/selftests/net/ynl/ethtool.sh new file mode 100755 index 000000000000..a70552afd7e2 --- /dev/null +++ b/tools/testing/selftests/net/ynl/ethtool.sh @@ -0,0 +1,188 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Test YNL ethtool functionality + +# shellcheck disable=SC1091,SC2034,SC2154,SC2317 +source ../lib.sh + +readonly NSIM_ID="1337" +readonly NSIM_DEV_NAME="nsim${NSIM_ID}" +readonly VETH_A="veth_a" +readonly VETH_B="veth_b" + +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 +" + +# Uses veth device as netdevsim doesn't support basic ethtool device info +ethtool_device_info() +{ + RET=0 + + local info_output + info_output=$(ip netns exec "$testns" ynl-ethtool "$VETH_A" 2>/dev/null) + check_err $? "failed to get device info for $VETH_A" + + echo "$info_output" | grep -q "Settings for" + check_err $? "device info output missing expected content" + + log_test "YNL ethtool device info" +} + +ethtool_statistics() +{ + RET=0 + + local stats_output + stats_output=$(ip netns exec "$testns" ynl-ethtool --statistics "$NSIM_DEV_NAME" 2>/dev/null) + check_err $? "failed to get statistics for $NSIM_DEV_NAME" + + echo "$stats_output" | grep -q -E "(NIC statistics|packets|bytes)" + check_err $? "statistics output missing expected content" + + log_test "YNL ethtool statistics" +} + +ethtool_ring_params() +{ + RET=0 + + local ring_output + ring_output=$(ip netns exec "$testns" ynl-ethtool --show-ring "$NSIM_DEV_NAME" 2>/dev/null) + check_err $? "failed to get ring parameters for $NSIM_DEV_NAME" + + if [[ -n "$ring_output" ]]; then + echo "$ring_output" | grep -q -E "(Ring parameters|RX|TX)" + check_err $? "ring parameters output missing expected content" + fi + + if ! ip netns exec "$testns" ynl-ethtool --set-ring "$NSIM_DEV_NAME" rx 64 2>/dev/null; then + check_err 1 "set-ring command failed unexpectedly" + fi + + log_test "YNL ethtool ring parameters (show/set)" +} + +ethtool_coalesce_params() +{ + RET=0 + + ip netns exec "$testns" ynl-ethtool --show-coalesce "$NSIM_DEV_NAME" &>/dev/null + check_err $? "failed to get coalesce parameters for $NSIM_DEV_NAME" + + if ! ip netns exec "$testns" ynl-ethtool --set-coalesce "$NSIM_DEV_NAME" rx-usecs 50 2>/dev/null; then + check_err 1 "set-coalesce command failed unexpectedly" + fi + + log_test "YNL ethtool coalesce parameters (show/set)" +} + +ethtool_pause_params() +{ + RET=0 + + ip netns exec "$testns" ynl-ethtool --show-pause "$NSIM_DEV_NAME" &>/dev/null + check_err $? "failed to get pause parameters for $NSIM_DEV_NAME" + + if ! ip netns exec "$testns" ynl-ethtool --set-pause "$NSIM_DEV_NAME" tx 1 rx 1 2>/dev/null; then + check_err 1 "set-pause command failed unexpectedly" + fi + + log_test "YNL ethtool pause parameters (show/set)" +} + +ethtool_features_info() +{ + RET=0 + + local features_output + features_output=$(ip netns exec "$testns" ynl-ethtool --show-features "$NSIM_DEV_NAME" 2>/dev/null) + check_err $? "failed to get features for $NSIM_DEV_NAME" + + if [[ -n "$features_output" ]]; then + echo "$features_output" | grep -q -E "(Features|offload)" + check_err $? "features output missing expected content" + fi + + log_test "YNL ethtool features info (show/set)" +} + +ethtool_channels_info() +{ + RET=0 + + local channels_output + channels_output=$(ip netns exec "$testns" ynl-ethtool --show-channels "$NSIM_DEV_NAME" 2>/dev/null) + check_err $? "failed to get channels for $NSIM_DEV_NAME" + + if [[ -n "$channels_output" ]]; then + echo "$channels_output" | grep -q -E "(Channel|Combined|RX|TX)" + check_err $? "channels output missing expected content" + fi + + if ! ip netns exec "$testns" ynl-ethtool --set-channels "$NSIM_DEV_NAME" combined-count 1 2>/dev/null; then + check_err 1 "set-channels command failed unexpectedly" + fi + + log_test "YNL ethtool channels info (show/set)" +} + +ethtool_time_stamping() +{ + RET=0 + + local ts_output + ts_output=$(ip netns exec "$testns" ynl-ethtool --show-time-stamping "$NSIM_DEV_NAME" 2>/dev/null) + check_err $? "failed to get time stamping info for $NSIM_DEV_NAME" + + if [[ -n "$ts_output" ]]; then + echo "$ts_output" | grep -q -E "(Time stamping|timestamping|SOF_TIMESTAMPING)" + check_err $? "time stamping output missing expected content" + fi + + log_test "YNL ethtool time stamping" +} + +setup() +{ + if ! modprobe netdevsim &>/dev/null; then + log_test_skip "all YNL ethtool tests" "netdevsim module not available" + exit "$ksft_skip" + fi + + setup_ns testns + + if ! create_netdevsim "$NSIM_ID" "$testns" >/dev/null 2>&1; then + log_test_skip "all YNL ethtool tests" "failed to create netdevsim device" + exit "$ksft_skip" + fi + + if ! ip -n "$testns" link add "$VETH_A" type veth peer name "$VETH_B" 2>/dev/null; then + log_test_skip "all YNL ethtool tests" "failed to create veth pair" + exit "$ksft_skip" + fi + + ip -n "$testns" link set "$VETH_A" up + ip -n "$testns" link set "$VETH_B" up +} + +cleanup() +{ + cleanup_netdevsim "$NSIM_ID" 2>/dev/null + cleanup_all_ns +} + +trap cleanup EXIT + +require_command "ynl-ethtool" +setup +tests_run + +exit "$EXIT_STATUS" diff --git a/tools/testing/selftests/net/ynl/settings b/tools/testing/selftests/net/ynl/settings new file mode 100644 index 000000000000..6091b45d226b --- /dev/null +++ b/tools/testing/selftests/net/ynl/settings @@ -0,0 +1 @@ +timeout=120
On Wed, 29 Oct 2025 08:22:45 +0000 Hangbin Liu wrote:
Add a test framework for YAML Netlink (YNL) tools, covering both CLI and ethtool functionality. The framework includes:
- cli: family listing, netdev, ethtool, rt-* families, and nlctrl operations
- 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.
Hm, my knee-jerk reaction was that we should avoid adding too much ynl stuff to the kernel at this point. But looking closer it's not that long.
Do I understand correctly, tho, that you're testing _system_ YNL? Not what's in tree?
On Wed, Oct 29, 2025 at 04:41:59PM -0700, Jakub Kicinski wrote:
On Wed, 29 Oct 2025 08:22:45 +0000 Hangbin Liu wrote:
Add a test framework for YAML Netlink (YNL) tools, covering both CLI and ethtool functionality. The framework includes:
- cli: family listing, netdev, ethtool, rt-* families, and nlctrl operations
- 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.
Hm, my knee-jerk reaction was that we should avoid adding too much ynl stuff to the kernel at this point. But looking closer it's not that long.
Do I understand correctly, tho, that you're testing _system_ YNL? Not what's in tree?
Kind of. With this we can test both the system's YNL and also make sure the YNL interface has no regression.
Thanks Hangbin
On Thu, 30 Oct 2025 06:00:24 +0000 Hangbin Liu wrote:
Hm, my knee-jerk reaction was that we should avoid adding too much ynl stuff to the kernel at this point. But looking closer it's not that long.
Do I understand correctly, tho, that you're testing _system_ YNL? Not what's in tree?
Kind of. With this we can test both the system's YNL and also make sure the YNL interface has no regression.
Meaning we still test the spec, right?
To state the obvious ideally we'd test both the specs and the Python tools. Strictly better, and without it adding tests for new Python features will be a little annoying for people running the selftest.
Maybe the solution is as simple as finding and alias'ing ynl to the cli.py ?
On Thu, Oct 30, 2025 at 08:39:44AM -0700, Jakub Kicinski wrote:
On Thu, 30 Oct 2025 06:00:24 +0000 Hangbin Liu wrote:
Hm, my knee-jerk reaction was that we should avoid adding too much ynl stuff to the kernel at this point. But looking closer it's not that long.
Do I understand correctly, tho, that you're testing _system_ YNL? Not what's in tree?
Kind of. With this we can test both the system's YNL and also make sure the YNL interface has no regression.
Meaning we still test the spec, right?
I just do `make install` in tools/net/ynl. Both the ynl scripts and specs are installed. So I think the specs are also tested.
To state the obvious ideally we'd test both the specs and the Python tools. Strictly better, and without it adding tests for new Python features will be a little annoying for people running the selftest.
Yes
Maybe the solution is as simple as finding and alias'ing ynl to the cli.py ?
I didn't get here. The `ynl` calls pyynl.cli:main, that should be enough. Do you mean we should find the `cli.py` path and call it like `$source_code/tools/net/ynl/pyynl/cli.py --spec $source_code/Documentation/netlink/specs/xxx.yaml ...`?
Thanks Hangbin
On Fri, 31 Oct 2025 01:48:17 +0000 Hangbin Liu wrote:
Kind of. With this we can test both the system's YNL and also make sure the YNL interface has no regression.
Meaning we still test the spec, right?
I just do `make install` in tools/net/ynl. Both the ynl scripts and specs are installed. So I think the specs are also tested.
To state the obvious ideally we'd test both the specs and the Python tools. Strictly better, and without it adding tests for new Python features will be a little annoying for people running the selftest.
Yes
Maybe the solution is as simple as finding and alias'ing ynl to the cli.py ?
I didn't get here. The `ynl` calls pyynl.cli:main, that should be enough. Do you mean we should find the `cli.py` path and call it like `$source_code/tools/net/ynl/pyynl/cli.py --spec $source_code/Documentation/netlink/specs/xxx.yaml ...`?
More or less. But it needs to know how to install itself when kernel selftests are installed. Maybe it's not worth the complexity and we should add the script under tools/net/ynl. Easier to refer from there.
linux-kselftest-mirror@lists.linaro.org