|
| 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 |
0 commit comments