Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools: ynl: add YNL test framework

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.

Reviewed-by: Donald Hunter <donald.hunter@gmail.com>
Acked-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Link: https://patch.msgid.link/20251124022055.33389-1-liuhangbin@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Hangbin Liu and committed by
Jakub Kicinski
308b7dee 651765e8

+593 -2
+6 -2
tools/net/ynl/Makefile
··· 12 12 libdir ?= $(prefix)/$(libdir_relative) 13 13 includedir ?= $(prefix)/include 14 14 15 - SUBDIRS = lib generated samples ynltool 15 + SUBDIRS = lib generated samples ynltool tests 16 16 17 17 all: $(SUBDIRS) libynl.a 18 18 ··· 49 49 @echo -e "\tINSTALL pyynl" 50 50 @pip install --prefix=$(DESTDIR)$(prefix) . 51 51 @make -C generated install 52 + @make -C tests install 52 53 53 - .PHONY: all clean distclean install $(SUBDIRS) 54 + run_tests: 55 + @$(MAKE) -C tests run_tests 56 + 57 + .PHONY: all clean distclean install run_tests $(SUBDIRS)
+32
tools/net/ynl/tests/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # Makefile for YNL tests 3 + 4 + TESTS := \ 5 + test_ynl_cli.sh \ 6 + test_ynl_ethtool.sh \ 7 + # end of TESTS 8 + 9 + all: $(TESTS) 10 + 11 + run_tests: 12 + @for test in $(TESTS); do \ 13 + ./$$test; \ 14 + done 15 + 16 + install: $(TESTS) 17 + @mkdir -p $(DESTDIR)/usr/bin 18 + @mkdir -p $(DESTDIR)/usr/share/kselftest 19 + @cp ../../../testing/selftests/kselftest/ktap_helpers.sh $(DESTDIR)/usr/share/kselftest/ 20 + @for test in $(TESTS); do \ 21 + name=$$(basename $$test .sh); \ 22 + sed -e 's|^ynl=.*|ynl="ynl"|' \ 23 + -e 's|^ynl_ethtool=.*|ynl_ethtool="ynl-ethtool"|' \ 24 + -e 's|KSELFTEST_KTAP_HELPERS=.*|KSELFTEST_KTAP_HELPERS="/usr/share/kselftest/ktap_helpers.sh"|' \ 25 + $$test > $(DESTDIR)/usr/bin/$$name; \ 26 + chmod +x $(DESTDIR)/usr/bin/$$name; \ 27 + done 28 + 29 + clean distclean: 30 + @# Nothing to clean 31 + 32 + .PHONY: all install clean run_tests
+6
tools/net/ynl/tests/config
··· 1 + CONFIG_DUMMY=m 2 + CONFIG_INET_DIAG=y 3 + CONFIG_IPV6=y 4 + CONFIG_NET_NS=y 5 + CONFIG_NETDEVSIM=m 6 + CONFIG_VETH=m
+327
tools/net/ynl/tests/test_ynl_cli.sh
··· 1 + #!/bin/bash 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Test YNL CLI functionality 4 + 5 + # Load KTAP test helpers 6 + KSELFTEST_KTAP_HELPERS="$(dirname "$(realpath "$0")")/../../../testing/selftests/kselftest/ktap_helpers.sh" 7 + # shellcheck source=../../../testing/selftests/kselftest/ktap_helpers.sh 8 + source "$KSELFTEST_KTAP_HELPERS" 9 + 10 + # Default ynl path for direct execution, can be overridden by make install 11 + ynl="../pyynl/cli.py" 12 + 13 + readonly NSIM_ID="1338" 14 + readonly NSIM_DEV_NAME="nsim${NSIM_ID}" 15 + readonly VETH_A="veth_a" 16 + readonly VETH_B="veth_b" 17 + 18 + testns="ynl-$(mktemp -u XXXXXX)" 19 + TESTS_NO=0 20 + 21 + # Test listing available families 22 + cli_list_families() 23 + { 24 + if $ynl --list-families &>/dev/null; then 25 + ktap_test_pass "YNL CLI list families" 26 + else 27 + ktap_test_fail "YNL CLI list families" 28 + fi 29 + } 30 + TESTS_NO=$((TESTS_NO + 1)) 31 + 32 + # Test netdev family operations (dev-get, queue-get) 33 + cli_netdev_ops() 34 + { 35 + local dev_output 36 + local ifindex 37 + 38 + ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null) 39 + 40 + dev_output=$(ip netns exec "$testns" $ynl --family netdev \ 41 + --do dev-get --json "{\"ifindex\": $ifindex}" 2>/dev/null) 42 + 43 + if ! echo "$dev_output" | grep -q "ifindex"; then 44 + ktap_test_fail "YNL CLI netdev operations (netdev dev-get output missing ifindex)" 45 + return 46 + fi 47 + 48 + if ! ip netns exec "$testns" $ynl --family netdev \ 49 + --dump queue-get --json "{\"ifindex\": $ifindex}" &>/dev/null; then 50 + ktap_test_fail "YNL CLI netdev operations (failed to get netdev queue info)" 51 + return 52 + fi 53 + 54 + ktap_test_pass "YNL CLI netdev operations" 55 + } 56 + TESTS_NO=$((TESTS_NO + 1)) 57 + 58 + # Test ethtool family operations (rings-get, linkinfo-get) 59 + cli_ethtool_ops() 60 + { 61 + local rings_output 62 + local linkinfo_output 63 + 64 + rings_output=$(ip netns exec "$testns" $ynl --family ethtool \ 65 + --do rings-get --json "{\"header\": {\"dev-name\": \"$NSIM_DEV_NAME\"}}" 2>/dev/null) 66 + 67 + if ! echo "$rings_output" | grep -q "header"; then 68 + ktap_test_fail "YNL CLI ethtool operations (ethtool rings-get output missing header)" 69 + return 70 + fi 71 + 72 + linkinfo_output=$(ip netns exec "$testns" $ynl --family ethtool \ 73 + --do linkinfo-get --json "{\"header\": {\"dev-name\": \"$VETH_A\"}}" 2>/dev/null) 74 + 75 + if ! echo "$linkinfo_output" | grep -q "header"; then 76 + ktap_test_fail "YNL CLI ethtool operations (ethtool linkinfo-get output missing header)" 77 + return 78 + fi 79 + 80 + ktap_test_pass "YNL CLI ethtool operations" 81 + } 82 + TESTS_NO=$((TESTS_NO + 1)) 83 + 84 + # Test rt-route family operations 85 + cli_rt_route_ops() 86 + { 87 + local ifindex 88 + 89 + if ! $ynl --list-families 2>/dev/null | grep -q "rt-route"; then 90 + ktap_test_skip "YNL CLI rt-route operations (rt-route family not available)" 91 + return 92 + fi 93 + 94 + ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null) 95 + 96 + # Add route: 192.0.2.0/24 dev $dev scope link 97 + if ! ip netns exec "$testns" $ynl --family rt-route --do newroute --create \ 98 + --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 99 + ktap_test_fail "YNL CLI rt-route operations (failed to add route)" 100 + return 101 + fi 102 + 103 + local route_output 104 + route_output=$(ip netns exec "$testns" $ynl --family rt-route --dump getroute 2>/dev/null) 105 + if echo "$route_output" | grep -q "192.0.2.0"; then 106 + ktap_test_pass "YNL CLI rt-route operations" 107 + else 108 + ktap_test_fail "YNL CLI rt-route operations (failed to verify route)" 109 + fi 110 + 111 + ip netns exec "$testns" $ynl --family rt-route --do delroute \ 112 + --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 113 + } 114 + TESTS_NO=$((TESTS_NO + 1)) 115 + 116 + # Test rt-addr family operations 117 + cli_rt_addr_ops() 118 + { 119 + local ifindex 120 + 121 + if ! $ynl --list-families 2>/dev/null | grep -q "rt-addr"; then 122 + ktap_test_skip "YNL CLI rt-addr operations (rt-addr family not available)" 123 + return 124 + fi 125 + 126 + ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null) 127 + 128 + if ! ip netns exec "$testns" $ynl --family rt-addr --do newaddr \ 129 + --json "{\"ifa-index\": $ifindex, \"local\": \"192.0.2.100\", \"ifa-prefixlen\": 24, \"ifa-family\": 2}" &>/dev/null; then 130 + ktap_test_fail "YNL CLI rt-addr operations (failed to add address)" 131 + return 132 + fi 133 + 134 + local addr_output 135 + addr_output=$(ip netns exec "$testns" $ynl --family rt-addr --dump getaddr 2>/dev/null) 136 + if echo "$addr_output" | grep -q "192.0.2.100"; then 137 + ktap_test_pass "YNL CLI rt-addr operations" 138 + else 139 + ktap_test_fail "YNL CLI rt-addr operations (failed to verify address)" 140 + fi 141 + 142 + ip netns exec "$testns" $ynl --family rt-addr --do deladdr \ 143 + --json "{\"ifa-index\": $ifindex, \"local\": \"192.0.2.100\", \"ifa-prefixlen\": 24, \"ifa-family\": 2}" &>/dev/null 144 + } 145 + TESTS_NO=$((TESTS_NO + 1)) 146 + 147 + # Test rt-link family operations 148 + cli_rt_link_ops() 149 + { 150 + if ! $ynl --list-families 2>/dev/null | grep -q "rt-link"; then 151 + ktap_test_skip "YNL CLI rt-link operations (rt-link family not available)" 152 + return 153 + fi 154 + 155 + if ! ip netns exec "$testns" $ynl --family rt-link --do newlink --create \ 156 + --json "{\"ifname\": \"dummy0\", \"linkinfo\": {\"kind\": \"dummy\"}}" &>/dev/null; then 157 + ktap_test_fail "YNL CLI rt-link operations (failed to add link)" 158 + return 159 + fi 160 + 161 + local link_output 162 + link_output=$(ip netns exec "$testns" $ynl --family rt-link --dump getlink 2>/dev/null) 163 + if echo "$link_output" | grep -q "$NSIM_DEV_NAME" && echo "$link_output" | grep -q "dummy0"; then 164 + ktap_test_pass "YNL CLI rt-link operations" 165 + else 166 + ktap_test_fail "YNL CLI rt-link operations (failed to verify link)" 167 + fi 168 + 169 + ip netns exec "$testns" $ynl --family rt-link --do dellink \ 170 + --json "{\"ifname\": \"dummy0\"}" &>/dev/null 171 + } 172 + TESTS_NO=$((TESTS_NO + 1)) 173 + 174 + # Test rt-neigh family operations 175 + cli_rt_neigh_ops() 176 + { 177 + local ifindex 178 + 179 + if ! $ynl --list-families 2>/dev/null | grep -q "rt-neigh"; then 180 + ktap_test_skip "YNL CLI rt-neigh operations (rt-neigh family not available)" 181 + return 182 + fi 183 + 184 + ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null) 185 + 186 + # Add neighbor: 192.0.2.1 dev nsim1338 lladdr 11:22:33:44:55:66 PERMANENT 187 + if ! ip netns exec "$testns" $ynl --family rt-neigh --do newneigh --create \ 188 + --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 189 + ktap_test_fail "YNL CLI rt-neigh operations (failed to add neighbor)" 190 + fi 191 + 192 + local neigh_output 193 + neigh_output=$(ip netns exec "$testns" $ynl --family rt-neigh --dump getneigh 2>/dev/null) 194 + if echo "$neigh_output" | grep -q "192.0.2.1"; then 195 + ktap_test_pass "YNL CLI rt-neigh operations" 196 + else 197 + ktap_test_fail "YNL CLI rt-neigh operations (failed to verify neighbor)" 198 + fi 199 + 200 + ip netns exec "$testns" $ynl --family rt-neigh --do delneigh \ 201 + --json "{\"ndm-ifindex\": $ifindex, \"dst\": \"192.0.2.1\", \"lladdr\": \"11:22:33:44:55:66\", \"ndm-family\": 2}" &>/dev/null 202 + } 203 + TESTS_NO=$((TESTS_NO + 1)) 204 + 205 + # Test rt-rule family operations 206 + cli_rt_rule_ops() 207 + { 208 + if ! $ynl --list-families 2>/dev/null | grep -q "rt-rule"; then 209 + ktap_test_skip "YNL CLI rt-rule operations (rt-rule family not available)" 210 + return 211 + fi 212 + 213 + # Add rule: from 192.0.2.0/24 lookup 100 none 214 + if ! ip netns exec "$testns" $ynl --family rt-rule --do newrule \ 215 + --json "{\"family\": 2, \"src-len\": 24, \"src\": \"192.0.2.0\", \"table\": 100}" &>/dev/null; then 216 + ktap_test_fail "YNL CLI rt-rule operations (failed to add rule)" 217 + return 218 + fi 219 + 220 + local rule_output 221 + rule_output=$(ip netns exec "$testns" $ynl --family rt-rule --dump getrule 2>/dev/null) 222 + if echo "$rule_output" | grep -q "192.0.2.0"; then 223 + ktap_test_pass "YNL CLI rt-rule operations" 224 + else 225 + ktap_test_fail "YNL CLI rt-rule operations (failed to verify rule)" 226 + fi 227 + 228 + ip netns exec "$testns" $ynl --family rt-rule --do delrule \ 229 + --json "{\"family\": 2, \"src-len\": 24, \"src\": \"192.0.2.0\", \"table\": 100}" &>/dev/null 230 + } 231 + TESTS_NO=$((TESTS_NO + 1)) 232 + 233 + # Test nlctrl family operations 234 + cli_nlctrl_ops() 235 + { 236 + local family_output 237 + 238 + if ! family_output=$($ynl --family nlctrl \ 239 + --do getfamily --json "{\"family-name\": \"netdev\"}" 2>/dev/null); then 240 + ktap_test_fail "YNL CLI nlctrl getfamily (failed to get nlctrl family info)" 241 + return 242 + fi 243 + 244 + if ! echo "$family_output" | grep -q "family-name"; then 245 + ktap_test_fail "YNL CLI nlctrl getfamily (nlctrl getfamily output missing family-name)" 246 + return 247 + fi 248 + 249 + if ! echo "$family_output" | grep -q "family-id"; then 250 + ktap_test_fail "YNL CLI nlctrl getfamily (nlctrl getfamily output missing family-id)" 251 + return 252 + fi 253 + 254 + ktap_test_pass "YNL CLI nlctrl getfamily" 255 + } 256 + TESTS_NO=$((TESTS_NO + 1)) 257 + 258 + setup() 259 + { 260 + modprobe netdevsim &> /dev/null 261 + if ! [ -f /sys/bus/netdevsim/new_device ]; then 262 + ktap_skip_all "netdevsim module not available" 263 + exit "$KSFT_SKIP" 264 + fi 265 + 266 + if ! ip netns add "$testns" 2>/dev/null; then 267 + ktap_skip_all "failed to create test namespace" 268 + exit "$KSFT_SKIP" 269 + fi 270 + 271 + echo "$NSIM_ID 1" | ip netns exec "$testns" tee /sys/bus/netdevsim/new_device >/dev/null 2>&1 || { 272 + ktap_skip_all "failed to create netdevsim device" 273 + exit "$KSFT_SKIP" 274 + } 275 + 276 + local dev 277 + dev=$(ip netns exec "$testns" ls /sys/bus/netdevsim/devices/netdevsim$NSIM_ID/net 2>/dev/null | head -1) 278 + if [[ -z "$dev" ]]; then 279 + ktap_skip_all "failed to find netdevsim device" 280 + exit "$KSFT_SKIP" 281 + fi 282 + 283 + ip -netns "$testns" link set dev "$dev" name "$NSIM_DEV_NAME" 2>/dev/null || { 284 + ktap_skip_all "failed to rename netdevsim device" 285 + exit "$KSFT_SKIP" 286 + } 287 + 288 + ip -netns "$testns" link set dev "$NSIM_DEV_NAME" up 2>/dev/null 289 + 290 + if ! ip -n "$testns" link add "$VETH_A" type veth peer name "$VETH_B" 2>/dev/null; then 291 + ktap_skip_all "failed to create veth pair" 292 + exit "$KSFT_SKIP" 293 + fi 294 + 295 + ip -n "$testns" link set "$VETH_A" up 2>/dev/null 296 + ip -n "$testns" link set "$VETH_B" up 2>/dev/null 297 + } 298 + 299 + cleanup() 300 + { 301 + ip netns exec "$testns" bash -c "echo $NSIM_ID > /sys/bus/netdevsim/del_device" 2>/dev/null || true 302 + ip netns del "$testns" 2>/dev/null || true 303 + } 304 + 305 + # Check if ynl command is available 306 + if ! command -v $ynl &>/dev/null && [[ ! -x $ynl ]]; then 307 + ktap_skip_all "ynl command not found: $ynl" 308 + exit "$KSFT_SKIP" 309 + fi 310 + 311 + trap cleanup EXIT 312 + 313 + ktap_print_header 314 + setup 315 + ktap_set_plan "${TESTS_NO}" 316 + 317 + cli_list_families 318 + cli_netdev_ops 319 + cli_ethtool_ops 320 + cli_rt_route_ops 321 + cli_rt_addr_ops 322 + cli_rt_link_ops 323 + cli_rt_neigh_ops 324 + cli_rt_rule_ops 325 + cli_nlctrl_ops 326 + 327 + ktap_finished
+222
tools/net/ynl/tests/test_ynl_ethtool.sh
··· 1 + #!/bin/bash 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Test YNL ethtool functionality 4 + 5 + # Load KTAP test helpers 6 + KSELFTEST_KTAP_HELPERS="$(dirname "$(realpath "$0")")/../../../testing/selftests/kselftest/ktap_helpers.sh" 7 + # shellcheck source=../../../testing/selftests/kselftest/ktap_helpers.sh 8 + source "$KSELFTEST_KTAP_HELPERS" 9 + 10 + # Default ynl-ethtool path for direct execution, can be overridden by make install 11 + ynl_ethtool="../pyynl/ethtool.py" 12 + 13 + readonly NSIM_ID="1337" 14 + readonly NSIM_DEV_NAME="nsim${NSIM_ID}" 15 + readonly VETH_A="veth_a" 16 + readonly VETH_B="veth_b" 17 + 18 + testns="ynl-ethtool-$(mktemp -u XXXXXX)" 19 + TESTS_NO=0 20 + 21 + # Uses veth device as netdevsim doesn't support basic ethtool device info 22 + ethtool_device_info() 23 + { 24 + local info_output 25 + 26 + info_output=$(ip netns exec "$testns" $ynl_ethtool "$VETH_A" 2>/dev/null) 27 + 28 + if ! echo "$info_output" | grep -q "Settings for"; then 29 + ktap_test_fail "YNL ethtool device info (device info output missing expected content)" 30 + return 31 + fi 32 + 33 + ktap_test_pass "YNL ethtool device info" 34 + } 35 + TESTS_NO=$((TESTS_NO + 1)) 36 + 37 + ethtool_statistics() 38 + { 39 + local stats_output 40 + 41 + stats_output=$(ip netns exec "$testns" $ynl_ethtool --statistics "$NSIM_DEV_NAME" 2>/dev/null) 42 + 43 + if ! echo "$stats_output" | grep -q -E "(NIC statistics|packets|bytes)"; then 44 + ktap_test_fail "YNL ethtool statistics (statistics output missing expected content)" 45 + return 46 + fi 47 + 48 + ktap_test_pass "YNL ethtool statistics" 49 + } 50 + TESTS_NO=$((TESTS_NO + 1)) 51 + 52 + ethtool_ring_params() 53 + { 54 + local ring_output 55 + 56 + ring_output=$(ip netns exec "$testns" $ynl_ethtool --show-ring "$NSIM_DEV_NAME" 2>/dev/null) 57 + 58 + if ! echo "$ring_output" | grep -q -E "(Ring parameters|RX|TX)"; then 59 + ktap_test_fail "YNL ethtool ring parameters (ring parameters output missing expected content)" 60 + return 61 + fi 62 + 63 + if ! ip netns exec "$testns" $ynl_ethtool --set-ring "$NSIM_DEV_NAME" rx 64 2>/dev/null; then 64 + ktap_test_fail "YNL ethtool ring parameters (set-ring command failed unexpectedly)" 65 + return 66 + fi 67 + 68 + ktap_test_pass "YNL ethtool ring parameters (show/set)" 69 + } 70 + TESTS_NO=$((TESTS_NO + 1)) 71 + 72 + ethtool_coalesce_params() 73 + { 74 + if ! ip netns exec "$testns" $ynl_ethtool --show-coalesce "$NSIM_DEV_NAME" &>/dev/null; then 75 + ktap_test_fail "YNL ethtool coalesce parameters (failed to get coalesce parameters)" 76 + return 77 + fi 78 + 79 + if ! ip netns exec "$testns" $ynl_ethtool --set-coalesce "$NSIM_DEV_NAME" rx-usecs 50 2>/dev/null; then 80 + ktap_test_fail "YNL ethtool coalesce parameters (set-coalesce command failed unexpectedly)" 81 + return 82 + fi 83 + 84 + ktap_test_pass "YNL ethtool coalesce parameters (show/set)" 85 + } 86 + TESTS_NO=$((TESTS_NO + 1)) 87 + 88 + ethtool_pause_params() 89 + { 90 + if ! ip netns exec "$testns" $ynl_ethtool --show-pause "$NSIM_DEV_NAME" &>/dev/null; then 91 + ktap_test_fail "YNL ethtool pause parameters (failed to get pause parameters)" 92 + return 93 + fi 94 + 95 + if ! ip netns exec "$testns" $ynl_ethtool --set-pause "$NSIM_DEV_NAME" tx 1 rx 1 2>/dev/null; then 96 + ktap_test_fail "YNL ethtool pause parameters (set-pause command failed unexpectedly)" 97 + return 98 + fi 99 + 100 + ktap_test_pass "YNL ethtool pause parameters (show/set)" 101 + } 102 + TESTS_NO=$((TESTS_NO + 1)) 103 + 104 + ethtool_features_info() 105 + { 106 + local features_output 107 + 108 + features_output=$(ip netns exec "$testns" $ynl_ethtool --show-features "$NSIM_DEV_NAME" 2>/dev/null) 109 + 110 + if ! echo "$features_output" | grep -q -E "(Features|offload)"; then 111 + ktap_test_fail "YNL ethtool features info (features output missing expected content)" 112 + return 113 + fi 114 + 115 + ktap_test_pass "YNL ethtool features info (show/set)" 116 + } 117 + TESTS_NO=$((TESTS_NO + 1)) 118 + 119 + ethtool_channels_info() 120 + { 121 + local channels_output 122 + 123 + channels_output=$(ip netns exec "$testns" $ynl_ethtool --show-channels "$NSIM_DEV_NAME" 2>/dev/null) 124 + 125 + if ! echo "$channels_output" | grep -q -E "(Channel|Combined|RX|TX)"; then 126 + ktap_test_fail "YNL ethtool channels info (channels output missing expected content)" 127 + return 128 + fi 129 + 130 + if ! ip netns exec "$testns" $ynl_ethtool --set-channels "$NSIM_DEV_NAME" combined-count 1 2>/dev/null; then 131 + ktap_test_fail "YNL ethtool channels info (set-channels command failed unexpectedly)" 132 + return 133 + fi 134 + 135 + ktap_test_pass "YNL ethtool channels info (show/set)" 136 + } 137 + TESTS_NO=$((TESTS_NO + 1)) 138 + 139 + ethtool_time_stamping() 140 + { 141 + local ts_output 142 + 143 + ts_output=$(ip netns exec "$testns" $ynl_ethtool --show-time-stamping "$NSIM_DEV_NAME" 2>/dev/null) 144 + 145 + if ! echo "$ts_output" | grep -q -E "(Time stamping|timestamping|SOF_TIMESTAMPING)"; then 146 + ktap_test_fail "YNL ethtool time stamping (time stamping output missing expected content)" 147 + return 148 + fi 149 + 150 + ktap_test_pass "YNL ethtool time stamping" 151 + } 152 + TESTS_NO=$((TESTS_NO + 1)) 153 + 154 + setup() 155 + { 156 + modprobe netdevsim &> /dev/null 157 + if ! [ -f /sys/bus/netdevsim/new_device ]; then 158 + ktap_skip_all "netdevsim module not available" 159 + exit "$KSFT_SKIP" 160 + fi 161 + 162 + if ! ip netns add "$testns" 2>/dev/null; then 163 + ktap_skip_all "failed to create test namespace" 164 + exit "$KSFT_SKIP" 165 + fi 166 + 167 + echo "$NSIM_ID 1" | ip netns exec "$testns" tee /sys/bus/netdevsim/new_device >/dev/null 2>&1 || { 168 + ktap_skip_all "failed to create netdevsim device" 169 + exit "$KSFT_SKIP" 170 + } 171 + 172 + local dev 173 + dev=$(ip netns exec "$testns" ls /sys/bus/netdevsim/devices/netdevsim$NSIM_ID/net 2>/dev/null | head -1) 174 + if [[ -z "$dev" ]]; then 175 + ktap_skip_all "failed to find netdevsim device" 176 + exit "$KSFT_SKIP" 177 + fi 178 + 179 + ip -netns "$testns" link set dev "$dev" name "$NSIM_DEV_NAME" 2>/dev/null || { 180 + ktap_skip_all "failed to rename netdevsim device" 181 + exit "$KSFT_SKIP" 182 + } 183 + 184 + ip -netns "$testns" link set dev "$NSIM_DEV_NAME" up 2>/dev/null 185 + 186 + if ! ip -n "$testns" link add "$VETH_A" type veth peer name "$VETH_B" 2>/dev/null; then 187 + ktap_skip_all "failed to create veth pair" 188 + exit "$KSFT_SKIP" 189 + fi 190 + 191 + ip -n "$testns" link set "$VETH_A" up 2>/dev/null 192 + ip -n "$testns" link set "$VETH_B" up 2>/dev/null 193 + } 194 + 195 + cleanup() 196 + { 197 + ip netns exec "$testns" bash -c "echo $NSIM_ID > /sys/bus/netdevsim/del_device" 2>/dev/null || true 198 + ip netns del "$testns" 2>/dev/null || true 199 + } 200 + 201 + # Check if ynl-ethtool command is available 202 + if ! command -v $ynl_ethtool &>/dev/null && [[ ! -x $ynl_ethtool ]]; then 203 + ktap_skip_all "ynl-ethtool command not found: $ynl_ethtool" 204 + exit "$KSFT_SKIP" 205 + fi 206 + 207 + trap cleanup EXIT 208 + 209 + ktap_print_header 210 + setup 211 + ktap_set_plan "${TESTS_NO}" 212 + 213 + ethtool_device_info 214 + ethtool_statistics 215 + ethtool_ring_params 216 + ethtool_coalesce_params 217 + ethtool_pause_params 218 + ethtool_features_info 219 + ethtool_channels_info 220 + ethtool_time_stamping 221 + 222 + ktap_finished