1*308b7deeSHangbin Liu#!/bin/bash 2*308b7deeSHangbin Liu# SPDX-License-Identifier: GPL-2.0 3*308b7deeSHangbin Liu# Test YNL CLI functionality 4*308b7deeSHangbin Liu 5*308b7deeSHangbin Liu# Load KTAP test helpers 6*308b7deeSHangbin LiuKSELFTEST_KTAP_HELPERS="$(dirname "$(realpath "$0")")/../../../testing/selftests/kselftest/ktap_helpers.sh" 7*308b7deeSHangbin Liu# shellcheck source=../../../testing/selftests/kselftest/ktap_helpers.sh 8*308b7deeSHangbin Liusource "$KSELFTEST_KTAP_HELPERS" 9*308b7deeSHangbin Liu 10*308b7deeSHangbin Liu# Default ynl path for direct execution, can be overridden by make install 11*308b7deeSHangbin Liuynl="../pyynl/cli.py" 12*308b7deeSHangbin Liu 13*308b7deeSHangbin Liureadonly NSIM_ID="1338" 14*308b7deeSHangbin Liureadonly NSIM_DEV_NAME="nsim${NSIM_ID}" 15*308b7deeSHangbin Liureadonly VETH_A="veth_a" 16*308b7deeSHangbin Liureadonly VETH_B="veth_b" 17*308b7deeSHangbin Liu 18*308b7deeSHangbin Liutestns="ynl-$(mktemp -u XXXXXX)" 19*308b7deeSHangbin LiuTESTS_NO=0 20*308b7deeSHangbin Liu 21*308b7deeSHangbin Liu# Test listing available families 22*308b7deeSHangbin Liucli_list_families() 23*308b7deeSHangbin Liu{ 24*308b7deeSHangbin Liu if $ynl --list-families &>/dev/null; then 25*308b7deeSHangbin Liu ktap_test_pass "YNL CLI list families" 26*308b7deeSHangbin Liu else 27*308b7deeSHangbin Liu ktap_test_fail "YNL CLI list families" 28*308b7deeSHangbin Liu fi 29*308b7deeSHangbin Liu} 30*308b7deeSHangbin LiuTESTS_NO=$((TESTS_NO + 1)) 31*308b7deeSHangbin Liu 32*308b7deeSHangbin Liu# Test netdev family operations (dev-get, queue-get) 33*308b7deeSHangbin Liucli_netdev_ops() 34*308b7deeSHangbin Liu{ 35*308b7deeSHangbin Liu local dev_output 36*308b7deeSHangbin Liu local ifindex 37*308b7deeSHangbin Liu 38*308b7deeSHangbin Liu ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null) 39*308b7deeSHangbin Liu 40*308b7deeSHangbin Liu dev_output=$(ip netns exec "$testns" $ynl --family netdev \ 41*308b7deeSHangbin Liu --do dev-get --json "{\"ifindex\": $ifindex}" 2>/dev/null) 42*308b7deeSHangbin Liu 43*308b7deeSHangbin Liu if ! echo "$dev_output" | grep -q "ifindex"; then 44*308b7deeSHangbin Liu ktap_test_fail "YNL CLI netdev operations (netdev dev-get output missing ifindex)" 45*308b7deeSHangbin Liu return 46*308b7deeSHangbin Liu fi 47*308b7deeSHangbin Liu 48*308b7deeSHangbin Liu if ! ip netns exec "$testns" $ynl --family netdev \ 49*308b7deeSHangbin Liu --dump queue-get --json "{\"ifindex\": $ifindex}" &>/dev/null; then 50*308b7deeSHangbin Liu ktap_test_fail "YNL CLI netdev operations (failed to get netdev queue info)" 51*308b7deeSHangbin Liu return 52*308b7deeSHangbin Liu fi 53*308b7deeSHangbin Liu 54*308b7deeSHangbin Liu ktap_test_pass "YNL CLI netdev operations" 55*308b7deeSHangbin Liu} 56*308b7deeSHangbin LiuTESTS_NO=$((TESTS_NO + 1)) 57*308b7deeSHangbin Liu 58*308b7deeSHangbin Liu# Test ethtool family operations (rings-get, linkinfo-get) 59*308b7deeSHangbin Liucli_ethtool_ops() 60*308b7deeSHangbin Liu{ 61*308b7deeSHangbin Liu local rings_output 62*308b7deeSHangbin Liu local linkinfo_output 63*308b7deeSHangbin Liu 64*308b7deeSHangbin Liu rings_output=$(ip netns exec "$testns" $ynl --family ethtool \ 65*308b7deeSHangbin Liu --do rings-get --json "{\"header\": {\"dev-name\": \"$NSIM_DEV_NAME\"}}" 2>/dev/null) 66*308b7deeSHangbin Liu 67*308b7deeSHangbin Liu if ! echo "$rings_output" | grep -q "header"; then 68*308b7deeSHangbin Liu ktap_test_fail "YNL CLI ethtool operations (ethtool rings-get output missing header)" 69*308b7deeSHangbin Liu return 70*308b7deeSHangbin Liu fi 71*308b7deeSHangbin Liu 72*308b7deeSHangbin Liu linkinfo_output=$(ip netns exec "$testns" $ynl --family ethtool \ 73*308b7deeSHangbin Liu --do linkinfo-get --json "{\"header\": {\"dev-name\": \"$VETH_A\"}}" 2>/dev/null) 74*308b7deeSHangbin Liu 75*308b7deeSHangbin Liu if ! echo "$linkinfo_output" | grep -q "header"; then 76*308b7deeSHangbin Liu ktap_test_fail "YNL CLI ethtool operations (ethtool linkinfo-get output missing header)" 77*308b7deeSHangbin Liu return 78*308b7deeSHangbin Liu fi 79*308b7deeSHangbin Liu 80*308b7deeSHangbin Liu ktap_test_pass "YNL CLI ethtool operations" 81*308b7deeSHangbin Liu} 82*308b7deeSHangbin LiuTESTS_NO=$((TESTS_NO + 1)) 83*308b7deeSHangbin Liu 84*308b7deeSHangbin Liu# Test rt-route family operations 85*308b7deeSHangbin Liucli_rt_route_ops() 86*308b7deeSHangbin Liu{ 87*308b7deeSHangbin Liu local ifindex 88*308b7deeSHangbin Liu 89*308b7deeSHangbin Liu if ! $ynl --list-families 2>/dev/null | grep -q "rt-route"; then 90*308b7deeSHangbin Liu ktap_test_skip "YNL CLI rt-route operations (rt-route family not available)" 91*308b7deeSHangbin Liu return 92*308b7deeSHangbin Liu fi 93*308b7deeSHangbin Liu 94*308b7deeSHangbin Liu ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null) 95*308b7deeSHangbin Liu 96*308b7deeSHangbin Liu # Add route: 192.0.2.0/24 dev $dev scope link 97*308b7deeSHangbin Liu if ! ip netns exec "$testns" $ynl --family rt-route --do newroute --create \ 98*308b7deeSHangbin Liu --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*308b7deeSHangbin Liu ktap_test_fail "YNL CLI rt-route operations (failed to add route)" 100*308b7deeSHangbin Liu return 101*308b7deeSHangbin Liu fi 102*308b7deeSHangbin Liu 103*308b7deeSHangbin Liu local route_output 104*308b7deeSHangbin Liu route_output=$(ip netns exec "$testns" $ynl --family rt-route --dump getroute 2>/dev/null) 105*308b7deeSHangbin Liu if echo "$route_output" | grep -q "192.0.2.0"; then 106*308b7deeSHangbin Liu ktap_test_pass "YNL CLI rt-route operations" 107*308b7deeSHangbin Liu else 108*308b7deeSHangbin Liu ktap_test_fail "YNL CLI rt-route operations (failed to verify route)" 109*308b7deeSHangbin Liu fi 110*308b7deeSHangbin Liu 111*308b7deeSHangbin Liu ip netns exec "$testns" $ynl --family rt-route --do delroute \ 112*308b7deeSHangbin Liu --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*308b7deeSHangbin Liu} 114*308b7deeSHangbin LiuTESTS_NO=$((TESTS_NO + 1)) 115*308b7deeSHangbin Liu 116*308b7deeSHangbin Liu# Test rt-addr family operations 117*308b7deeSHangbin Liucli_rt_addr_ops() 118*308b7deeSHangbin Liu{ 119*308b7deeSHangbin Liu local ifindex 120*308b7deeSHangbin Liu 121*308b7deeSHangbin Liu if ! $ynl --list-families 2>/dev/null | grep -q "rt-addr"; then 122*308b7deeSHangbin Liu ktap_test_skip "YNL CLI rt-addr operations (rt-addr family not available)" 123*308b7deeSHangbin Liu return 124*308b7deeSHangbin Liu fi 125*308b7deeSHangbin Liu 126*308b7deeSHangbin Liu ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null) 127*308b7deeSHangbin Liu 128*308b7deeSHangbin Liu if ! ip netns exec "$testns" $ynl --family rt-addr --do newaddr \ 129*308b7deeSHangbin Liu --json "{\"ifa-index\": $ifindex, \"local\": \"192.0.2.100\", \"ifa-prefixlen\": 24, \"ifa-family\": 2}" &>/dev/null; then 130*308b7deeSHangbin Liu ktap_test_fail "YNL CLI rt-addr operations (failed to add address)" 131*308b7deeSHangbin Liu return 132*308b7deeSHangbin Liu fi 133*308b7deeSHangbin Liu 134*308b7deeSHangbin Liu local addr_output 135*308b7deeSHangbin Liu addr_output=$(ip netns exec "$testns" $ynl --family rt-addr --dump getaddr 2>/dev/null) 136*308b7deeSHangbin Liu if echo "$addr_output" | grep -q "192.0.2.100"; then 137*308b7deeSHangbin Liu ktap_test_pass "YNL CLI rt-addr operations" 138*308b7deeSHangbin Liu else 139*308b7deeSHangbin Liu ktap_test_fail "YNL CLI rt-addr operations (failed to verify address)" 140*308b7deeSHangbin Liu fi 141*308b7deeSHangbin Liu 142*308b7deeSHangbin Liu ip netns exec "$testns" $ynl --family rt-addr --do deladdr \ 143*308b7deeSHangbin Liu --json "{\"ifa-index\": $ifindex, \"local\": \"192.0.2.100\", \"ifa-prefixlen\": 24, \"ifa-family\": 2}" &>/dev/null 144*308b7deeSHangbin Liu} 145*308b7deeSHangbin LiuTESTS_NO=$((TESTS_NO + 1)) 146*308b7deeSHangbin Liu 147*308b7deeSHangbin Liu# Test rt-link family operations 148*308b7deeSHangbin Liucli_rt_link_ops() 149*308b7deeSHangbin Liu{ 150*308b7deeSHangbin Liu if ! $ynl --list-families 2>/dev/null | grep -q "rt-link"; then 151*308b7deeSHangbin Liu ktap_test_skip "YNL CLI rt-link operations (rt-link family not available)" 152*308b7deeSHangbin Liu return 153*308b7deeSHangbin Liu fi 154*308b7deeSHangbin Liu 155*308b7deeSHangbin Liu if ! ip netns exec "$testns" $ynl --family rt-link --do newlink --create \ 156*308b7deeSHangbin Liu --json "{\"ifname\": \"dummy0\", \"linkinfo\": {\"kind\": \"dummy\"}}" &>/dev/null; then 157*308b7deeSHangbin Liu ktap_test_fail "YNL CLI rt-link operations (failed to add link)" 158*308b7deeSHangbin Liu return 159*308b7deeSHangbin Liu fi 160*308b7deeSHangbin Liu 161*308b7deeSHangbin Liu local link_output 162*308b7deeSHangbin Liu link_output=$(ip netns exec "$testns" $ynl --family rt-link --dump getlink 2>/dev/null) 163*308b7deeSHangbin Liu if echo "$link_output" | grep -q "$NSIM_DEV_NAME" && echo "$link_output" | grep -q "dummy0"; then 164*308b7deeSHangbin Liu ktap_test_pass "YNL CLI rt-link operations" 165*308b7deeSHangbin Liu else 166*308b7deeSHangbin Liu ktap_test_fail "YNL CLI rt-link operations (failed to verify link)" 167*308b7deeSHangbin Liu fi 168*308b7deeSHangbin Liu 169*308b7deeSHangbin Liu ip netns exec "$testns" $ynl --family rt-link --do dellink \ 170*308b7deeSHangbin Liu --json "{\"ifname\": \"dummy0\"}" &>/dev/null 171*308b7deeSHangbin Liu} 172*308b7deeSHangbin LiuTESTS_NO=$((TESTS_NO + 1)) 173*308b7deeSHangbin Liu 174*308b7deeSHangbin Liu# Test rt-neigh family operations 175*308b7deeSHangbin Liucli_rt_neigh_ops() 176*308b7deeSHangbin Liu{ 177*308b7deeSHangbin Liu local ifindex 178*308b7deeSHangbin Liu 179*308b7deeSHangbin Liu if ! $ynl --list-families 2>/dev/null | grep -q "rt-neigh"; then 180*308b7deeSHangbin Liu ktap_test_skip "YNL CLI rt-neigh operations (rt-neigh family not available)" 181*308b7deeSHangbin Liu return 182*308b7deeSHangbin Liu fi 183*308b7deeSHangbin Liu 184*308b7deeSHangbin Liu ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null) 185*308b7deeSHangbin Liu 186*308b7deeSHangbin Liu # Add neighbor: 192.0.2.1 dev nsim1338 lladdr 11:22:33:44:55:66 PERMANENT 187*308b7deeSHangbin Liu if ! ip netns exec "$testns" $ynl --family rt-neigh --do newneigh --create \ 188*308b7deeSHangbin Liu --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*308b7deeSHangbin Liu ktap_test_fail "YNL CLI rt-neigh operations (failed to add neighbor)" 190*308b7deeSHangbin Liu fi 191*308b7deeSHangbin Liu 192*308b7deeSHangbin Liu local neigh_output 193*308b7deeSHangbin Liu neigh_output=$(ip netns exec "$testns" $ynl --family rt-neigh --dump getneigh 2>/dev/null) 194*308b7deeSHangbin Liu if echo "$neigh_output" | grep -q "192.0.2.1"; then 195*308b7deeSHangbin Liu ktap_test_pass "YNL CLI rt-neigh operations" 196*308b7deeSHangbin Liu else 197*308b7deeSHangbin Liu ktap_test_fail "YNL CLI rt-neigh operations (failed to verify neighbor)" 198*308b7deeSHangbin Liu fi 199*308b7deeSHangbin Liu 200*308b7deeSHangbin Liu ip netns exec "$testns" $ynl --family rt-neigh --do delneigh \ 201*308b7deeSHangbin Liu --json "{\"ndm-ifindex\": $ifindex, \"dst\": \"192.0.2.1\", \"lladdr\": \"11:22:33:44:55:66\", \"ndm-family\": 2}" &>/dev/null 202*308b7deeSHangbin Liu} 203*308b7deeSHangbin LiuTESTS_NO=$((TESTS_NO + 1)) 204*308b7deeSHangbin Liu 205*308b7deeSHangbin Liu# Test rt-rule family operations 206*308b7deeSHangbin Liucli_rt_rule_ops() 207*308b7deeSHangbin Liu{ 208*308b7deeSHangbin Liu if ! $ynl --list-families 2>/dev/null | grep -q "rt-rule"; then 209*308b7deeSHangbin Liu ktap_test_skip "YNL CLI rt-rule operations (rt-rule family not available)" 210*308b7deeSHangbin Liu return 211*308b7deeSHangbin Liu fi 212*308b7deeSHangbin Liu 213*308b7deeSHangbin Liu # Add rule: from 192.0.2.0/24 lookup 100 none 214*308b7deeSHangbin Liu if ! ip netns exec "$testns" $ynl --family rt-rule --do newrule \ 215*308b7deeSHangbin Liu --json "{\"family\": 2, \"src-len\": 24, \"src\": \"192.0.2.0\", \"table\": 100}" &>/dev/null; then 216*308b7deeSHangbin Liu ktap_test_fail "YNL CLI rt-rule operations (failed to add rule)" 217*308b7deeSHangbin Liu return 218*308b7deeSHangbin Liu fi 219*308b7deeSHangbin Liu 220*308b7deeSHangbin Liu local rule_output 221*308b7deeSHangbin Liu rule_output=$(ip netns exec "$testns" $ynl --family rt-rule --dump getrule 2>/dev/null) 222*308b7deeSHangbin Liu if echo "$rule_output" | grep -q "192.0.2.0"; then 223*308b7deeSHangbin Liu ktap_test_pass "YNL CLI rt-rule operations" 224*308b7deeSHangbin Liu else 225*308b7deeSHangbin Liu ktap_test_fail "YNL CLI rt-rule operations (failed to verify rule)" 226*308b7deeSHangbin Liu fi 227*308b7deeSHangbin Liu 228*308b7deeSHangbin Liu ip netns exec "$testns" $ynl --family rt-rule --do delrule \ 229*308b7deeSHangbin Liu --json "{\"family\": 2, \"src-len\": 24, \"src\": \"192.0.2.0\", \"table\": 100}" &>/dev/null 230*308b7deeSHangbin Liu} 231*308b7deeSHangbin LiuTESTS_NO=$((TESTS_NO + 1)) 232*308b7deeSHangbin Liu 233*308b7deeSHangbin Liu# Test nlctrl family operations 234*308b7deeSHangbin Liucli_nlctrl_ops() 235*308b7deeSHangbin Liu{ 236*308b7deeSHangbin Liu local family_output 237*308b7deeSHangbin Liu 238*308b7deeSHangbin Liu if ! family_output=$($ynl --family nlctrl \ 239*308b7deeSHangbin Liu --do getfamily --json "{\"family-name\": \"netdev\"}" 2>/dev/null); then 240*308b7deeSHangbin Liu ktap_test_fail "YNL CLI nlctrl getfamily (failed to get nlctrl family info)" 241*308b7deeSHangbin Liu return 242*308b7deeSHangbin Liu fi 243*308b7deeSHangbin Liu 244*308b7deeSHangbin Liu if ! echo "$family_output" | grep -q "family-name"; then 245*308b7deeSHangbin Liu ktap_test_fail "YNL CLI nlctrl getfamily (nlctrl getfamily output missing family-name)" 246*308b7deeSHangbin Liu return 247*308b7deeSHangbin Liu fi 248*308b7deeSHangbin Liu 249*308b7deeSHangbin Liu if ! echo "$family_output" | grep -q "family-id"; then 250*308b7deeSHangbin Liu ktap_test_fail "YNL CLI nlctrl getfamily (nlctrl getfamily output missing family-id)" 251*308b7deeSHangbin Liu return 252*308b7deeSHangbin Liu fi 253*308b7deeSHangbin Liu 254*308b7deeSHangbin Liu ktap_test_pass "YNL CLI nlctrl getfamily" 255*308b7deeSHangbin Liu} 256*308b7deeSHangbin LiuTESTS_NO=$((TESTS_NO + 1)) 257*308b7deeSHangbin Liu 258*308b7deeSHangbin Liusetup() 259*308b7deeSHangbin Liu{ 260*308b7deeSHangbin Liu modprobe netdevsim &> /dev/null 261*308b7deeSHangbin Liu if ! [ -f /sys/bus/netdevsim/new_device ]; then 262*308b7deeSHangbin Liu ktap_skip_all "netdevsim module not available" 263*308b7deeSHangbin Liu exit "$KSFT_SKIP" 264*308b7deeSHangbin Liu fi 265*308b7deeSHangbin Liu 266*308b7deeSHangbin Liu if ! ip netns add "$testns" 2>/dev/null; then 267*308b7deeSHangbin Liu ktap_skip_all "failed to create test namespace" 268*308b7deeSHangbin Liu exit "$KSFT_SKIP" 269*308b7deeSHangbin Liu fi 270*308b7deeSHangbin Liu 271*308b7deeSHangbin Liu echo "$NSIM_ID 1" | ip netns exec "$testns" tee /sys/bus/netdevsim/new_device >/dev/null 2>&1 || { 272*308b7deeSHangbin Liu ktap_skip_all "failed to create netdevsim device" 273*308b7deeSHangbin Liu exit "$KSFT_SKIP" 274*308b7deeSHangbin Liu } 275*308b7deeSHangbin Liu 276*308b7deeSHangbin Liu local dev 277*308b7deeSHangbin Liu dev=$(ip netns exec "$testns" ls /sys/bus/netdevsim/devices/netdevsim$NSIM_ID/net 2>/dev/null | head -1) 278*308b7deeSHangbin Liu if [[ -z "$dev" ]]; then 279*308b7deeSHangbin Liu ktap_skip_all "failed to find netdevsim device" 280*308b7deeSHangbin Liu exit "$KSFT_SKIP" 281*308b7deeSHangbin Liu fi 282*308b7deeSHangbin Liu 283*308b7deeSHangbin Liu ip -netns "$testns" link set dev "$dev" name "$NSIM_DEV_NAME" 2>/dev/null || { 284*308b7deeSHangbin Liu ktap_skip_all "failed to rename netdevsim device" 285*308b7deeSHangbin Liu exit "$KSFT_SKIP" 286*308b7deeSHangbin Liu } 287*308b7deeSHangbin Liu 288*308b7deeSHangbin Liu ip -netns "$testns" link set dev "$NSIM_DEV_NAME" up 2>/dev/null 289*308b7deeSHangbin Liu 290*308b7deeSHangbin Liu if ! ip -n "$testns" link add "$VETH_A" type veth peer name "$VETH_B" 2>/dev/null; then 291*308b7deeSHangbin Liu ktap_skip_all "failed to create veth pair" 292*308b7deeSHangbin Liu exit "$KSFT_SKIP" 293*308b7deeSHangbin Liu fi 294*308b7deeSHangbin Liu 295*308b7deeSHangbin Liu ip -n "$testns" link set "$VETH_A" up 2>/dev/null 296*308b7deeSHangbin Liu ip -n "$testns" link set "$VETH_B" up 2>/dev/null 297*308b7deeSHangbin Liu} 298*308b7deeSHangbin Liu 299*308b7deeSHangbin Liucleanup() 300*308b7deeSHangbin Liu{ 301*308b7deeSHangbin Liu ip netns exec "$testns" bash -c "echo $NSIM_ID > /sys/bus/netdevsim/del_device" 2>/dev/null || true 302*308b7deeSHangbin Liu ip netns del "$testns" 2>/dev/null || true 303*308b7deeSHangbin Liu} 304*308b7deeSHangbin Liu 305*308b7deeSHangbin Liu# Check if ynl command is available 306*308b7deeSHangbin Liuif ! command -v $ynl &>/dev/null && [[ ! -x $ynl ]]; then 307*308b7deeSHangbin Liu ktap_skip_all "ynl command not found: $ynl" 308*308b7deeSHangbin Liu exit "$KSFT_SKIP" 309*308b7deeSHangbin Liufi 310*308b7deeSHangbin Liu 311*308b7deeSHangbin Liutrap cleanup EXIT 312*308b7deeSHangbin Liu 313*308b7deeSHangbin Liuktap_print_header 314*308b7deeSHangbin Liusetup 315*308b7deeSHangbin Liuktap_set_plan "${TESTS_NO}" 316*308b7deeSHangbin Liu 317*308b7deeSHangbin Liucli_list_families 318*308b7deeSHangbin Liucli_netdev_ops 319*308b7deeSHangbin Liucli_ethtool_ops 320*308b7deeSHangbin Liucli_rt_route_ops 321*308b7deeSHangbin Liucli_rt_addr_ops 322*308b7deeSHangbin Liucli_rt_link_ops 323*308b7deeSHangbin Liucli_rt_neigh_ops 324*308b7deeSHangbin Liucli_rt_rule_ops 325*308b7deeSHangbin Liucli_nlctrl_ops 326*308b7deeSHangbin Liu 327*308b7deeSHangbin Liuktap_finished 328