Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/bash
0002 # SPDX-License-Identifier: GPL-2.0
0003 #
0004 # ns: me               | ns: peer              | ns: remote
0005 #   2001:db8:91::1     |       2001:db8:91::2  |
0006 #   172.16.1.1         |       172.16.1.2      |
0007 #            veth1 <---|---> veth2             |
0008 #                      |              veth5 <--|--> veth6  172.16.101.1
0009 #            veth3 <---|---> veth4             |           2001:db8:101::1
0010 #   172.16.2.1         |       172.16.2.2      |
0011 #   2001:db8:92::1     |       2001:db8:92::2  |
0012 #
0013 # This test is for checking IPv4 and IPv6 FIB behavior with nexthop
0014 # objects. Device reference counts and network namespace cleanup tested
0015 # by use of network namespace for peer.
0016 
0017 ret=0
0018 # Kselftest framework requirement - SKIP code is 4.
0019 ksft_skip=4
0020 
0021 # all tests in this script. Can be overridden with -t option
0022 IPV4_TESTS="
0023         ipv4_fcnal
0024         ipv4_grp_fcnal
0025         ipv4_res_grp_fcnal
0026         ipv4_withv6_fcnal
0027         ipv4_fcnal_runtime
0028         ipv4_large_grp
0029         ipv4_large_res_grp
0030         ipv4_compat_mode
0031         ipv4_fdb_grp_fcnal
0032         ipv4_torture
0033         ipv4_res_torture
0034 "
0035 
0036 IPV6_TESTS="
0037         ipv6_fcnal
0038         ipv6_grp_fcnal
0039         ipv6_res_grp_fcnal
0040         ipv6_fcnal_runtime
0041         ipv6_large_grp
0042         ipv6_large_res_grp
0043         ipv6_compat_mode
0044         ipv6_fdb_grp_fcnal
0045         ipv6_torture
0046         ipv6_res_torture
0047 "
0048 
0049 ALL_TESTS="
0050         basic
0051         basic_res
0052         ${IPV4_TESTS}
0053         ${IPV6_TESTS}
0054 "
0055 TESTS="${ALL_TESTS}"
0056 VERBOSE=0
0057 PAUSE_ON_FAIL=no
0058 PAUSE=no
0059 PING_TIMEOUT=5
0060 
0061 nsid=100
0062 
0063 ################################################################################
0064 # utilities
0065 
0066 log_test()
0067 {
0068         local rc=$1
0069         local expected=$2
0070         local msg="$3"
0071 
0072         if [ ${rc} -eq ${expected} ]; then
0073                 printf "TEST: %-60s  [ OK ]\n" "${msg}"
0074                 nsuccess=$((nsuccess+1))
0075         else
0076                 ret=1
0077                 nfail=$((nfail+1))
0078                 printf "TEST: %-60s  [FAIL]\n" "${msg}"
0079                 if [ "$VERBOSE" = "1" ]; then
0080                         echo "    rc=$rc, expected $expected"
0081                 fi
0082 
0083                 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
0084                 echo
0085                         echo "hit enter to continue, 'q' to quit"
0086                         read a
0087                         [ "$a" = "q" ] && exit 1
0088                 fi
0089         fi
0090 
0091         if [ "${PAUSE}" = "yes" ]; then
0092                 echo
0093                 echo "hit enter to continue, 'q' to quit"
0094                 read a
0095                 [ "$a" = "q" ] && exit 1
0096         fi
0097 
0098         [ "$VERBOSE" = "1" ] && echo
0099 }
0100 
0101 run_cmd()
0102 {
0103         local cmd="$1"
0104         local out
0105         local stderr="2>/dev/null"
0106 
0107         if [ "$VERBOSE" = "1" ]; then
0108                 printf "COMMAND: $cmd\n"
0109                 stderr=
0110         fi
0111 
0112         out=$(eval $cmd $stderr)
0113         rc=$?
0114         if [ "$VERBOSE" = "1" -a -n "$out" ]; then
0115                 echo "    $out"
0116         fi
0117 
0118         return $rc
0119 }
0120 
0121 get_linklocal()
0122 {
0123         local dev=$1
0124         local ns
0125         local addr
0126 
0127         [ -n "$2" ] && ns="-netns $2"
0128         addr=$(ip $ns -6 -br addr show dev ${dev} | \
0129         awk '{
0130                 for (i = 3; i <= NF; ++i) {
0131                         if ($i ~ /^fe80/)
0132                                 print $i
0133                 }
0134         }'
0135         )
0136         addr=${addr/\/*}
0137 
0138         [ -z "$addr" ] && return 1
0139 
0140         echo $addr
0141 
0142         return 0
0143 }
0144 
0145 create_ns()
0146 {
0147         local n=${1}
0148 
0149         ip netns del ${n} 2>/dev/null
0150 
0151         set -e
0152         ip netns add ${n}
0153         ip netns set ${n} $((nsid++))
0154         ip -netns ${n} addr add 127.0.0.1/8 dev lo
0155         ip -netns ${n} link set lo up
0156 
0157         ip netns exec ${n} sysctl -qw net.ipv4.ip_forward=1
0158         ip netns exec ${n} sysctl -qw net.ipv4.fib_multipath_use_neigh=1
0159         ip netns exec ${n} sysctl -qw net.ipv4.conf.default.ignore_routes_with_linkdown=1
0160         ip netns exec ${n} sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1
0161         ip netns exec ${n} sysctl -qw net.ipv6.conf.all.forwarding=1
0162         ip netns exec ${n} sysctl -qw net.ipv6.conf.default.forwarding=1
0163         ip netns exec ${n} sysctl -qw net.ipv6.conf.default.ignore_routes_with_linkdown=1
0164         ip netns exec ${n} sysctl -qw net.ipv6.conf.all.accept_dad=0
0165         ip netns exec ${n} sysctl -qw net.ipv6.conf.default.accept_dad=0
0166 
0167         set +e
0168 }
0169 
0170 setup()
0171 {
0172         cleanup
0173 
0174         create_ns me
0175         create_ns peer
0176         create_ns remote
0177 
0178         IP="ip -netns me"
0179         BRIDGE="bridge -netns me"
0180         set -e
0181         $IP li add veth1 type veth peer name veth2
0182         $IP li set veth1 up
0183         $IP addr add 172.16.1.1/24 dev veth1
0184         $IP -6 addr add 2001:db8:91::1/64 dev veth1 nodad
0185 
0186         $IP li add veth3 type veth peer name veth4
0187         $IP li set veth3 up
0188         $IP addr add 172.16.2.1/24 dev veth3
0189         $IP -6 addr add 2001:db8:92::1/64 dev veth3 nodad
0190 
0191         $IP li set veth2 netns peer up
0192         ip -netns peer addr add 172.16.1.2/24 dev veth2
0193         ip -netns peer -6 addr add 2001:db8:91::2/64 dev veth2 nodad
0194 
0195         $IP li set veth4 netns peer up
0196         ip -netns peer addr add 172.16.2.2/24 dev veth4
0197         ip -netns peer -6 addr add 2001:db8:92::2/64 dev veth4 nodad
0198 
0199         ip -netns remote li add veth5 type veth peer name veth6
0200         ip -netns remote li set veth5 up
0201         ip -netns remote addr add dev veth5 172.16.101.1/24
0202         ip -netns remote -6 addr add dev veth5 2001:db8:101::1/64 nodad
0203         ip -netns remote ro add 172.16.0.0/22 via 172.16.101.2
0204         ip -netns remote -6 ro add 2001:db8:90::/40 via 2001:db8:101::2
0205 
0206         ip -netns remote li set veth6 netns peer up
0207         ip -netns peer addr add dev veth6 172.16.101.2/24
0208         ip -netns peer -6 addr add dev veth6 2001:db8:101::2/64 nodad
0209         set +e
0210 }
0211 
0212 cleanup()
0213 {
0214         local ns
0215 
0216         for ns in me peer remote; do
0217                 ip netns del ${ns} 2>/dev/null
0218         done
0219 }
0220 
0221 check_output()
0222 {
0223         local out="$1"
0224         local expected="$2"
0225         local rc=0
0226 
0227         [ "${out}" = "${expected}" ] && return 0
0228 
0229         if [ -z "${out}" ]; then
0230                 if [ "$VERBOSE" = "1" ]; then
0231                         printf "\nNo entry found\n"
0232                         printf "Expected:\n"
0233                         printf "    ${expected}\n"
0234                 fi
0235                 return 1
0236         fi
0237 
0238         out=$(echo ${out})
0239         if [ "${out}" != "${expected}" ]; then
0240                 rc=1
0241                 if [ "${VERBOSE}" = "1" ]; then
0242                         printf "    Unexpected entry. Have:\n"
0243                         printf "        ${out}\n"
0244                         printf "    Expected:\n"
0245                         printf "        ${expected}\n\n"
0246                 else
0247                         echo "      WARNING: Unexpected route entry"
0248                 fi
0249         fi
0250 
0251         return $rc
0252 }
0253 
0254 check_nexthop()
0255 {
0256         local nharg="$1"
0257         local expected="$2"
0258         local out
0259 
0260         out=$($IP nexthop ls ${nharg} 2>/dev/null)
0261 
0262         check_output "${out}" "${expected}"
0263 }
0264 
0265 check_nexthop_bucket()
0266 {
0267         local nharg="$1"
0268         local expected="$2"
0269         local out
0270 
0271         # remove the idle time since we cannot match it
0272         out=$($IP nexthop bucket ${nharg} \
0273                 | sed s/idle_time\ [0-9.]*\ // 2>/dev/null)
0274 
0275         check_output "${out}" "${expected}"
0276 }
0277 
0278 check_route()
0279 {
0280         local pfx="$1"
0281         local expected="$2"
0282         local out
0283 
0284         out=$($IP route ls match ${pfx} 2>/dev/null)
0285 
0286         check_output "${out}" "${expected}"
0287 }
0288 
0289 check_route6()
0290 {
0291         local pfx="$1"
0292         local expected="$2"
0293         local out
0294 
0295         out=$($IP -6 route ls match ${pfx} 2>/dev/null | sed -e 's/pref medium//')
0296 
0297         check_output "${out}" "${expected}"
0298 }
0299 
0300 check_large_grp()
0301 {
0302         local ipv=$1
0303         local ecmp=$2
0304         local grpnum=100
0305         local nhidstart=100
0306         local grpidstart=1000
0307         local iter=0
0308         local nhidstr=""
0309         local grpidstr=""
0310         local grpstr=""
0311         local ipstr=""
0312 
0313         if [ $ipv -eq 4 ]; then
0314                 ipstr="172.16.1."
0315         else
0316                 ipstr="2001:db8:91::"
0317         fi
0318 
0319         #
0320         # Create $grpnum groups with specified $ecmp and dump them
0321         #
0322 
0323         # create nexthops with different gateways
0324         iter=2
0325         while [ $iter -le $(($ecmp + 1)) ]
0326         do
0327                 nhidstr="$(($nhidstart + $iter))"
0328                 run_cmd "$IP nexthop add id $nhidstr via $ipstr$iter dev veth1"
0329                 check_nexthop "id $nhidstr" "id $nhidstr via $ipstr$iter dev veth1 scope link"
0330 
0331                 if [ $iter -le $ecmp ]; then
0332                         grpstr+="$nhidstr/"
0333                 else
0334                         grpstr+="$nhidstr"
0335                 fi
0336                 ((iter++))
0337         done
0338 
0339         # create duplicate large ecmp groups
0340         iter=0
0341         while [ $iter -le $grpnum ]
0342         do
0343                 grpidstr="$(($grpidstart + $iter))"
0344                 run_cmd "$IP nexthop add id $grpidstr group $grpstr"
0345                 check_nexthop "id $grpidstr" "id $grpidstr group $grpstr"
0346                 ((iter++))
0347         done
0348 
0349         # dump large groups
0350         run_cmd "$IP nexthop list"
0351         log_test $? 0 "Dump large (x$ecmp) ecmp groups"
0352 }
0353 
0354 check_large_res_grp()
0355 {
0356         local ipv=$1
0357         local buckets=$2
0358         local ipstr=""
0359 
0360         if [ $ipv -eq 4 ]; then
0361                 ipstr="172.16.1.2"
0362         else
0363                 ipstr="2001:db8:91::2"
0364         fi
0365 
0366         # create a resilient group with $buckets buckets and dump them
0367         run_cmd "$IP nexthop add id 100 via $ipstr dev veth1"
0368         run_cmd "$IP nexthop add id 1000 group 100 type resilient buckets $buckets"
0369         run_cmd "$IP nexthop bucket list"
0370         log_test $? 0 "Dump large (x$buckets) nexthop buckets"
0371 }
0372 
0373 start_ip_monitor()
0374 {
0375         local mtype=$1
0376 
0377         # start the monitor in the background
0378         tmpfile=`mktemp /var/run/nexthoptestXXX`
0379         mpid=`($IP monitor $mtype > $tmpfile & echo $!) 2>/dev/null`
0380         sleep 0.2
0381         echo "$mpid $tmpfile"
0382 }
0383 
0384 stop_ip_monitor()
0385 {
0386         local mpid=$1
0387         local tmpfile=$2
0388         local el=$3
0389 
0390         # check the monitor results
0391         kill $mpid
0392         lines=`wc -l $tmpfile | cut "-d " -f1`
0393         test $lines -eq $el
0394         rc=$?
0395         rm -rf $tmpfile
0396 
0397         return $rc
0398 }
0399 
0400 check_nexthop_fdb_support()
0401 {
0402         $IP nexthop help 2>&1 | grep -q fdb
0403         if [ $? -ne 0 ]; then
0404                 echo "SKIP: iproute2 too old, missing fdb nexthop support"
0405                 return $ksft_skip
0406         fi
0407 }
0408 
0409 check_nexthop_res_support()
0410 {
0411         $IP nexthop help 2>&1 | grep -q resilient
0412         if [ $? -ne 0 ]; then
0413                 echo "SKIP: iproute2 too old, missing resilient nexthop group support"
0414                 return $ksft_skip
0415         fi
0416 }
0417 
0418 ipv6_fdb_grp_fcnal()
0419 {
0420         local rc
0421 
0422         echo
0423         echo "IPv6 fdb groups functional"
0424         echo "--------------------------"
0425 
0426         check_nexthop_fdb_support
0427         if [ $? -eq $ksft_skip ]; then
0428                 return $ksft_skip
0429         fi
0430 
0431         # create group with multiple nexthops
0432         run_cmd "$IP nexthop add id 61 via 2001:db8:91::2 fdb"
0433         run_cmd "$IP nexthop add id 62 via 2001:db8:91::3 fdb"
0434         run_cmd "$IP nexthop add id 102 group 61/62 fdb"
0435         check_nexthop "id 102" "id 102 group 61/62 fdb"
0436         log_test $? 0 "Fdb Nexthop group with multiple nexthops"
0437 
0438         ## get nexthop group
0439         run_cmd "$IP nexthop get id 102"
0440         check_nexthop "id 102" "id 102 group 61/62 fdb"
0441         log_test $? 0 "Get Fdb nexthop group by id"
0442 
0443         # fdb nexthop group can only contain fdb nexthops
0444         run_cmd "$IP nexthop add id 63 via 2001:db8:91::4"
0445         run_cmd "$IP nexthop add id 64 via 2001:db8:91::5"
0446         run_cmd "$IP nexthop add id 103 group 63/64 fdb"
0447         log_test $? 2 "Fdb Nexthop group with non-fdb nexthops"
0448 
0449         # Non fdb nexthop group can not contain fdb nexthops
0450         run_cmd "$IP nexthop add id 65 via 2001:db8:91::5 fdb"
0451         run_cmd "$IP nexthop add id 66 via 2001:db8:91::6 fdb"
0452         run_cmd "$IP nexthop add id 104 group 65/66"
0453         log_test $? 2 "Non-Fdb Nexthop group with fdb nexthops"
0454 
0455         # fdb nexthop cannot have blackhole
0456         run_cmd "$IP nexthop add id 67 blackhole fdb"
0457         log_test $? 2 "Fdb Nexthop with blackhole"
0458 
0459         # fdb nexthop with oif
0460         run_cmd "$IP nexthop add id 68 via 2001:db8:91::7 dev veth1 fdb"
0461         log_test $? 2 "Fdb Nexthop with oif"
0462 
0463         # fdb nexthop with onlink
0464         run_cmd "$IP nexthop add id 68 via 2001:db8:91::7 onlink fdb"
0465         log_test $? 2 "Fdb Nexthop with onlink"
0466 
0467         # fdb nexthop with encap
0468         run_cmd "$IP nexthop add id 69 encap mpls 101 via 2001:db8:91::8 dev veth1 fdb"
0469         log_test $? 2 "Fdb Nexthop with encap"
0470 
0471         run_cmd "$IP link add name vx10 type vxlan id 1010 local 2001:db8:91::9 remote 2001:db8:91::10 dstport 4789 nolearning noudpcsum tos inherit ttl 100"
0472         run_cmd "$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self"
0473         log_test $? 0 "Fdb mac add with nexthop group"
0474 
0475         ## fdb nexthops can only reference nexthop groups and not nexthops
0476         run_cmd "$BRIDGE fdb add 02:02:00:00:00:14 dev vx10 nhid 61 self"
0477         log_test $? 255 "Fdb mac add with nexthop"
0478 
0479         run_cmd "$IP -6 ro add 2001:db8:101::1/128 nhid 66"
0480         log_test $? 2 "Route add with fdb nexthop"
0481 
0482         run_cmd "$IP -6 ro add 2001:db8:101::1/128 nhid 103"
0483         log_test $? 2 "Route add with fdb nexthop group"
0484 
0485         run_cmd "$IP nexthop del id 61"
0486         run_cmd "$BRIDGE fdb get to 02:02:00:00:00:13 dev vx10 self"
0487         log_test $? 0 "Fdb entry after deleting a single nexthop"
0488 
0489         run_cmd "$IP nexthop del id 102"
0490         log_test $? 0 "Fdb nexthop delete"
0491 
0492         run_cmd "$BRIDGE fdb get to 02:02:00:00:00:13 dev vx10 self"
0493         log_test $? 254 "Fdb entry after deleting a nexthop group"
0494 
0495         $IP link del dev vx10
0496 }
0497 
0498 ipv4_fdb_grp_fcnal()
0499 {
0500         local rc
0501 
0502         echo
0503         echo "IPv4 fdb groups functional"
0504         echo "--------------------------"
0505 
0506         check_nexthop_fdb_support
0507         if [ $? -eq $ksft_skip ]; then
0508                 return $ksft_skip
0509         fi
0510 
0511         # create group with multiple nexthops
0512         run_cmd "$IP nexthop add id 12 via 172.16.1.2 fdb"
0513         run_cmd "$IP nexthop add id 13 via 172.16.1.3 fdb"
0514         run_cmd "$IP nexthop add id 102 group 12/13 fdb"
0515         check_nexthop "id 102" "id 102 group 12/13 fdb"
0516         log_test $? 0 "Fdb Nexthop group with multiple nexthops"
0517 
0518         # get nexthop group
0519         run_cmd "$IP nexthop get id 102"
0520         check_nexthop "id 102" "id 102 group 12/13 fdb"
0521         log_test $? 0 "Get Fdb nexthop group by id"
0522 
0523         # fdb nexthop group can only contain fdb nexthops
0524         run_cmd "$IP nexthop add id 14 via 172.16.1.2"
0525         run_cmd "$IP nexthop add id 15 via 172.16.1.3"
0526         run_cmd "$IP nexthop add id 103 group 14/15 fdb"
0527         log_test $? 2 "Fdb Nexthop group with non-fdb nexthops"
0528 
0529         # Non fdb nexthop group can not contain fdb nexthops
0530         run_cmd "$IP nexthop add id 16 via 172.16.1.2 fdb"
0531         run_cmd "$IP nexthop add id 17 via 172.16.1.3 fdb"
0532         run_cmd "$IP nexthop add id 104 group 14/15"
0533         log_test $? 2 "Non-Fdb Nexthop group with fdb nexthops"
0534 
0535         # fdb nexthop cannot have blackhole
0536         run_cmd "$IP nexthop add id 18 blackhole fdb"
0537         log_test $? 2 "Fdb Nexthop with blackhole"
0538 
0539         # fdb nexthop with oif
0540         run_cmd "$IP nexthop add id 16 via 172.16.1.2 dev veth1 fdb"
0541         log_test $? 2 "Fdb Nexthop with oif"
0542 
0543         # fdb nexthop with onlink
0544         run_cmd "$IP nexthop add id 16 via 172.16.1.2 onlink fdb"
0545         log_test $? 2 "Fdb Nexthop with onlink"
0546 
0547         # fdb nexthop with encap
0548         run_cmd "$IP nexthop add id 17 encap mpls 101 via 172.16.1.2 dev veth1 fdb"
0549         log_test $? 2 "Fdb Nexthop with encap"
0550 
0551         run_cmd "$IP link add name vx10 type vxlan id 1010 local 10.0.0.1 remote 10.0.0.2 dstport 4789 nolearning noudpcsum tos inherit ttl 100"
0552         run_cmd "$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self"
0553         log_test $? 0 "Fdb mac add with nexthop group"
0554 
0555         # fdb nexthops can only reference nexthop groups and not nexthops
0556         run_cmd "$BRIDGE fdb add 02:02:00:00:00:14 dev vx10 nhid 12 self"
0557         log_test $? 255 "Fdb mac add with nexthop"
0558 
0559         run_cmd "$IP ro add 172.16.0.0/22 nhid 15"
0560         log_test $? 2 "Route add with fdb nexthop"
0561 
0562         run_cmd "$IP ro add 172.16.0.0/22 nhid 103"
0563         log_test $? 2 "Route add with fdb nexthop group"
0564 
0565         run_cmd "$IP nexthop del id 12"
0566         run_cmd "$BRIDGE fdb get to 02:02:00:00:00:13 dev vx10 self"
0567         log_test $? 0 "Fdb entry after deleting a single nexthop"
0568 
0569         run_cmd "$IP nexthop del id 102"
0570         log_test $? 0 "Fdb nexthop delete"
0571 
0572         run_cmd "$BRIDGE fdb get to 02:02:00:00:00:13 dev vx10 self"
0573         log_test $? 254 "Fdb entry after deleting a nexthop group"
0574 
0575         $IP link del dev vx10
0576 }
0577 
0578 ################################################################################
0579 # basic operations (add, delete, replace) on nexthops and nexthop groups
0580 #
0581 # IPv6
0582 
0583 ipv6_fcnal()
0584 {
0585         local rc
0586 
0587         echo
0588         echo "IPv6"
0589         echo "----------------------"
0590 
0591         run_cmd "$IP nexthop add id 52 via 2001:db8:91::2 dev veth1"
0592         rc=$?
0593         log_test $rc 0 "Create nexthop with id, gw, dev"
0594         if [ $rc -ne 0 ]; then
0595                 echo "Basic IPv6 create fails; can not continue"
0596                 return 1
0597         fi
0598 
0599         run_cmd "$IP nexthop get id 52"
0600         log_test $? 0 "Get nexthop by id"
0601         check_nexthop "id 52" "id 52 via 2001:db8:91::2 dev veth1 scope link"
0602 
0603         run_cmd "$IP nexthop del id 52"
0604         log_test $? 0 "Delete nexthop by id"
0605         check_nexthop "id 52" ""
0606 
0607         #
0608         # gw, device spec
0609         #
0610         # gw validation, no device - fails since dev required
0611         run_cmd "$IP nexthop add id 52 via 2001:db8:92::3"
0612         log_test $? 2 "Create nexthop - gw only"
0613 
0614         # gw is not reachable throught given dev
0615         run_cmd "$IP nexthop add id 53 via 2001:db8:3::3 dev veth1"
0616         log_test $? 2 "Create nexthop - invalid gw+dev combination"
0617 
0618         # onlink arg overrides gw+dev lookup
0619         run_cmd "$IP nexthop add id 53 via 2001:db8:3::3 dev veth1 onlink"
0620         log_test $? 0 "Create nexthop - gw+dev and onlink"
0621 
0622         # admin down should delete nexthops
0623         set -e
0624         run_cmd "$IP -6 nexthop add id 55 via 2001:db8:91::3 dev veth1"
0625         run_cmd "$IP nexthop add id 56 via 2001:db8:91::4 dev veth1"
0626         run_cmd "$IP nexthop add id 57 via 2001:db8:91::5 dev veth1"
0627         run_cmd "$IP li set dev veth1 down"
0628         set +e
0629         check_nexthop "dev veth1" ""
0630         log_test $? 0 "Nexthops removed on admin down"
0631 }
0632 
0633 ipv6_grp_refs()
0634 {
0635         if [ ! -x "$(command -v mausezahn)" ]; then
0636                 echo "SKIP: Could not run test; need mausezahn tool"
0637                 return
0638         fi
0639 
0640         run_cmd "$IP link set dev veth1 up"
0641         run_cmd "$IP link add veth1.10 link veth1 up type vlan id 10"
0642         run_cmd "$IP link add veth1.20 link veth1 up type vlan id 20"
0643         run_cmd "$IP -6 addr add 2001:db8:91::1/64 dev veth1.10"
0644         run_cmd "$IP -6 addr add 2001:db8:92::1/64 dev veth1.20"
0645         run_cmd "$IP -6 neigh add 2001:db8:91::2 lladdr 00:11:22:33:44:55 dev veth1.10"
0646         run_cmd "$IP -6 neigh add 2001:db8:92::2 lladdr 00:11:22:33:44:55 dev veth1.20"
0647         run_cmd "$IP nexthop add id 100 via 2001:db8:91::2 dev veth1.10"
0648         run_cmd "$IP nexthop add id 101 via 2001:db8:92::2 dev veth1.20"
0649         run_cmd "$IP nexthop add id 102 group 100"
0650         run_cmd "$IP route add 2001:db8:101::1/128 nhid 102"
0651 
0652         # create per-cpu dsts through nh 100
0653         run_cmd "ip netns exec me mausezahn -6 veth1.10 -B 2001:db8:101::1 -A 2001:db8:91::1 -c 5 -t tcp "dp=1-1023, flags=syn" >/dev/null 2>&1"
0654 
0655         # remove nh 100 from the group to delete the route potentially leaving
0656         # a stale per-cpu dst which holds a reference to the nexthop's net
0657         # device and to the IPv6 route
0658         run_cmd "$IP nexthop replace id 102 group 101"
0659         run_cmd "$IP route del 2001:db8:101::1/128"
0660 
0661         # add both nexthops to the group so a reference is taken on them
0662         run_cmd "$IP nexthop replace id 102 group 100/101"
0663 
0664         # if the bug described in commit "net: nexthop: release IPv6 per-cpu
0665         # dsts when replacing a nexthop group" exists at this point we have
0666         # an unlinked IPv6 route (but not freed due to stale dst) with a
0667         # reference over the group so we delete the group which will again
0668         # only unlink it due to the route reference
0669         run_cmd "$IP nexthop del id 102"
0670 
0671         # delete the nexthop with stale dst, since we have an unlinked
0672         # group with a ref to it and an unlinked IPv6 route with ref to the
0673         # group, the nh will only be unlinked and not freed so the stale dst
0674         # remains forever and we get a net device refcount imbalance
0675         run_cmd "$IP nexthop del id 100"
0676 
0677         # if a reference was lost this command will hang because the net device
0678         # cannot be removed
0679         timeout -s KILL 5 ip netns exec me ip link del veth1.10 >/dev/null 2>&1
0680 
0681         # we can't cleanup if the command is hung trying to delete the netdev
0682         if [ $? -eq 137 ]; then
0683                 return 1
0684         fi
0685 
0686         # cleanup
0687         run_cmd "$IP link del veth1.20"
0688         run_cmd "$IP nexthop flush"
0689 
0690         return 0
0691 }
0692 
0693 ipv6_grp_fcnal()
0694 {
0695         local rc
0696 
0697         echo
0698         echo "IPv6 groups functional"
0699         echo "----------------------"
0700 
0701         # basic functionality: create a nexthop group, default weight
0702         run_cmd "$IP nexthop add id 61 via 2001:db8:91::2 dev veth1"
0703         run_cmd "$IP nexthop add id 101 group 61"
0704         log_test $? 0 "Create nexthop group with single nexthop"
0705 
0706         # get nexthop group
0707         run_cmd "$IP nexthop get id 101"
0708         log_test $? 0 "Get nexthop group by id"
0709         check_nexthop "id 101" "id 101 group 61"
0710 
0711         # delete nexthop group
0712         run_cmd "$IP nexthop del id 101"
0713         log_test $? 0 "Delete nexthop group by id"
0714         check_nexthop "id 101" ""
0715 
0716         $IP nexthop flush >/dev/null 2>&1
0717         check_nexthop "id 101" ""
0718 
0719         #
0720         # create group with multiple nexthops - mix of gw and dev only
0721         #
0722         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
0723         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
0724         run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
0725         run_cmd "$IP nexthop add id 65 dev veth1"
0726         run_cmd "$IP nexthop add id 102 group 62/63/64/65"
0727         log_test $? 0 "Nexthop group with multiple nexthops"
0728         check_nexthop "id 102" "id 102 group 62/63/64/65"
0729 
0730         # Delete nexthop in a group and group is updated
0731         run_cmd "$IP nexthop del id 63"
0732         check_nexthop "id 102" "id 102 group 62/64/65"
0733         log_test $? 0 "Nexthop group updated when entry is deleted"
0734 
0735         # create group with multiple weighted nexthops
0736         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
0737         run_cmd "$IP nexthop add id 103 group 62/63,2/64,3/65,4"
0738         log_test $? 0 "Nexthop group with weighted nexthops"
0739         check_nexthop "id 103" "id 103 group 62/63,2/64,3/65,4"
0740 
0741         # Delete nexthop in a weighted group and group is updated
0742         run_cmd "$IP nexthop del id 63"
0743         check_nexthop "id 103" "id 103 group 62/64,3/65,4"
0744         log_test $? 0 "Weighted nexthop group updated when entry is deleted"
0745 
0746         # admin down - nexthop is removed from group
0747         run_cmd "$IP li set dev veth1 down"
0748         check_nexthop "dev veth1" ""
0749         log_test $? 0 "Nexthops in groups removed on admin down"
0750 
0751         # expect groups to have been deleted as well
0752         check_nexthop "" ""
0753 
0754         run_cmd "$IP li set dev veth1 up"
0755 
0756         $IP nexthop flush >/dev/null 2>&1
0757 
0758         # group with nexthops using different devices
0759         set -e
0760         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
0761         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
0762         run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
0763         run_cmd "$IP nexthop add id 65 via 2001:db8:91::5 dev veth1"
0764 
0765         run_cmd "$IP nexthop add id 72 via 2001:db8:92::2 dev veth3"
0766         run_cmd "$IP nexthop add id 73 via 2001:db8:92::3 dev veth3"
0767         run_cmd "$IP nexthop add id 74 via 2001:db8:92::4 dev veth3"
0768         run_cmd "$IP nexthop add id 75 via 2001:db8:92::5 dev veth3"
0769         set +e
0770 
0771         # multiple groups with same nexthop
0772         run_cmd "$IP nexthop add id 104 group 62"
0773         run_cmd "$IP nexthop add id 105 group 62"
0774         check_nexthop "group" "id 104 group 62 id 105 group 62"
0775         log_test $? 0 "Multiple groups with same nexthop"
0776 
0777         run_cmd "$IP nexthop flush groups"
0778         [ $? -ne 0 ] && return 1
0779 
0780         # on admin down of veth1, it should be removed from the group
0781         run_cmd "$IP nexthop add id 105 group 62/63/72/73/64"
0782         run_cmd "$IP li set veth1 down"
0783         check_nexthop "id 105" "id 105 group 72/73"
0784         log_test $? 0 "Nexthops in group removed on admin down - mixed group"
0785 
0786         run_cmd "$IP nexthop add id 106 group 105/74"
0787         log_test $? 2 "Nexthop group can not have a group as an entry"
0788 
0789         # a group can have a blackhole entry only if it is the only
0790         # nexthop in the group. Needed for atomic replace with an
0791         # actual nexthop group
0792         run_cmd "$IP -6 nexthop add id 31 blackhole"
0793         run_cmd "$IP nexthop add id 107 group 31"
0794         log_test $? 0 "Nexthop group with a blackhole entry"
0795 
0796         run_cmd "$IP nexthop add id 108 group 31/24"
0797         log_test $? 2 "Nexthop group can not have a blackhole and another nexthop"
0798 
0799         ipv6_grp_refs
0800         log_test $? 0 "Nexthop group replace refcounts"
0801 }
0802 
0803 ipv6_res_grp_fcnal()
0804 {
0805         local rc
0806 
0807         echo
0808         echo "IPv6 resilient groups functional"
0809         echo "--------------------------------"
0810 
0811         check_nexthop_res_support
0812         if [ $? -eq $ksft_skip ]; then
0813                 return $ksft_skip
0814         fi
0815 
0816         #
0817         # migration of nexthop buckets - equal weights
0818         #
0819         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
0820         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
0821         run_cmd "$IP nexthop add id 102 group 62/63 type resilient buckets 2 idle_timer 0"
0822 
0823         run_cmd "$IP nexthop del id 63"
0824         check_nexthop "id 102" \
0825                 "id 102 group 62 type resilient buckets 2 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
0826         log_test $? 0 "Nexthop group updated when entry is deleted"
0827         check_nexthop_bucket "list id 102" \
0828                 "id 102 index 0 nhid 62 id 102 index 1 nhid 62"
0829         log_test $? 0 "Nexthop buckets updated when entry is deleted"
0830 
0831         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
0832         run_cmd "$IP nexthop replace id 102 group 62/63 type resilient buckets 2 idle_timer 0"
0833         check_nexthop "id 102" \
0834                 "id 102 group 62/63 type resilient buckets 2 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
0835         log_test $? 0 "Nexthop group updated after replace"
0836         check_nexthop_bucket "list id 102" \
0837                 "id 102 index 0 nhid 63 id 102 index 1 nhid 62"
0838         log_test $? 0 "Nexthop buckets updated after replace"
0839 
0840         $IP nexthop flush >/dev/null 2>&1
0841 
0842         #
0843         # migration of nexthop buckets - unequal weights
0844         #
0845         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
0846         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
0847         run_cmd "$IP nexthop add id 102 group 62,3/63,1 type resilient buckets 4 idle_timer 0"
0848 
0849         run_cmd "$IP nexthop del id 63"
0850         check_nexthop "id 102" \
0851                 "id 102 group 62,3 type resilient buckets 4 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
0852         log_test $? 0 "Nexthop group updated when entry is deleted - nECMP"
0853         check_nexthop_bucket "list id 102" \
0854                 "id 102 index 0 nhid 62 id 102 index 1 nhid 62 id 102 index 2 nhid 62 id 102 index 3 nhid 62"
0855         log_test $? 0 "Nexthop buckets updated when entry is deleted - nECMP"
0856 
0857         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
0858         run_cmd "$IP nexthop replace id 102 group 62,3/63,1 type resilient buckets 4 idle_timer 0"
0859         check_nexthop "id 102" \
0860                 "id 102 group 62,3/63 type resilient buckets 4 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
0861         log_test $? 0 "Nexthop group updated after replace - nECMP"
0862         check_nexthop_bucket "list id 102" \
0863                 "id 102 index 0 nhid 63 id 102 index 1 nhid 62 id 102 index 2 nhid 62 id 102 index 3 nhid 62"
0864         log_test $? 0 "Nexthop buckets updated after replace - nECMP"
0865 }
0866 
0867 ipv6_fcnal_runtime()
0868 {
0869         local rc
0870 
0871         echo
0872         echo "IPv6 functional runtime"
0873         echo "-----------------------"
0874 
0875         #
0876         # IPv6 - the basics
0877         #
0878         run_cmd "$IP nexthop add id 81 via 2001:db8:91::2 dev veth1"
0879         run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
0880         log_test $? 0 "Route add"
0881 
0882         run_cmd "$IP ro delete 2001:db8:101::1/128 nhid 81"
0883         log_test $? 0 "Route delete"
0884 
0885         run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
0886         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
0887         log_test $? 0 "Ping with nexthop"
0888 
0889         run_cmd "$IP nexthop add id 82 via 2001:db8:92::2 dev veth3"
0890         run_cmd "$IP nexthop add id 122 group 81/82"
0891         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
0892         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
0893         log_test $? 0 "Ping - multipath"
0894 
0895         #
0896         # IPv6 with blackhole nexthops
0897         #
0898         run_cmd "$IP -6 nexthop add id 83 blackhole"
0899         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 83"
0900         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
0901         log_test $? 2 "Ping - blackhole"
0902 
0903         run_cmd "$IP nexthop replace id 83 via 2001:db8:91::2 dev veth1"
0904         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
0905         log_test $? 0 "Ping - blackhole replaced with gateway"
0906 
0907         run_cmd "$IP -6 nexthop replace id 83 blackhole"
0908         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
0909         log_test $? 2 "Ping - gateway replaced by blackhole"
0910 
0911         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
0912         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
0913         if [ $? -eq 0 ]; then
0914                 run_cmd "$IP nexthop replace id 122 group 83"
0915                 run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
0916                 log_test $? 2 "Ping - group with blackhole"
0917 
0918                 run_cmd "$IP nexthop replace id 122 group 81/82"
0919                 run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
0920                 log_test $? 0 "Ping - group blackhole replaced with gateways"
0921         else
0922                 log_test 2 0 "Ping - multipath failed"
0923         fi
0924 
0925         #
0926         # device only and gw + dev only mix
0927         #
0928         run_cmd "$IP -6 nexthop add id 85 dev veth1"
0929         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 85"
0930         log_test $? 0 "IPv6 route with device only nexthop"
0931         check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 85 dev veth1 metric 1024"
0932 
0933         run_cmd "$IP nexthop add id 123 group 81/85"
0934         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 123"
0935         log_test $? 0 "IPv6 multipath route with nexthop mix - dev only + gw"
0936         check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 123 metric 1024 nexthop via 2001:db8:91::2 dev veth1 weight 1 nexthop dev veth1 weight 1"
0937 
0938         #
0939         # IPv6 route with v4 nexthop - not allowed
0940         #
0941         run_cmd "$IP ro delete 2001:db8:101::1/128"
0942         run_cmd "$IP nexthop add id 84 via 172.16.1.1 dev veth1"
0943         run_cmd "$IP ro add 2001:db8:101::1/128 nhid 84"
0944         log_test $? 2 "IPv6 route can not have a v4 gateway"
0945 
0946         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 81"
0947         run_cmd "$IP nexthop replace id 81 via 172.16.1.1 dev veth1"
0948         log_test $? 2 "Nexthop replace - v6 route, v4 nexthop"
0949 
0950         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
0951         run_cmd "$IP nexthop replace id 81 via 172.16.1.1 dev veth1"
0952         log_test $? 2 "Nexthop replace of group entry - v6 route, v4 nexthop"
0953 
0954         run_cmd "$IP nexthop add id 86 via 2001:db8:92::2 dev veth3"
0955         run_cmd "$IP nexthop add id 87 via 172.16.1.1 dev veth1"
0956         run_cmd "$IP nexthop add id 88 via 172.16.1.1 dev veth1"
0957         run_cmd "$IP nexthop add id 124 group 86/87/88"
0958         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
0959         log_test $? 2 "IPv6 route can not have a group with v4 and v6 gateways"
0960 
0961         run_cmd "$IP nexthop del id 88"
0962         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
0963         log_test $? 2 "IPv6 route can not have a group with v4 and v6 gateways"
0964 
0965         run_cmd "$IP nexthop del id 87"
0966         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
0967         log_test $? 0 "IPv6 route using a group after removing v4 gateways"
0968 
0969         run_cmd "$IP ro delete 2001:db8:101::1/128"
0970         run_cmd "$IP nexthop add id 87 via 172.16.1.1 dev veth1"
0971         run_cmd "$IP nexthop add id 88 via 172.16.1.1 dev veth1"
0972         run_cmd "$IP nexthop replace id 124 group 86/87/88"
0973         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
0974         log_test $? 2 "IPv6 route can not have a group with v4 and v6 gateways"
0975 
0976         run_cmd "$IP nexthop replace id 88 via 2001:db8:92::2 dev veth3"
0977         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
0978         log_test $? 2 "IPv6 route can not have a group with v4 and v6 gateways"
0979 
0980         run_cmd "$IP nexthop replace id 87 via 2001:db8:92::2 dev veth3"
0981         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
0982         log_test $? 0 "IPv6 route using a group after replacing v4 gateways"
0983 
0984         $IP nexthop flush >/dev/null 2>&1
0985 
0986         #
0987         # weird IPv6 cases
0988         #
0989         run_cmd "$IP nexthop add id 86 via 2001:db8:91::2 dev veth1"
0990         run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
0991 
0992         # route can not use prefsrc with nexthops
0993         run_cmd "$IP ro add 2001:db8:101::2/128 nhid 86 from 2001:db8:91::1"
0994         log_test $? 2 "IPv6 route can not use src routing with external nexthop"
0995 
0996         # check cleanup path on invalid metric
0997         run_cmd "$IP ro add 2001:db8:101::2/128 nhid 86 congctl lock foo"
0998         log_test $? 2 "IPv6 route with invalid metric"
0999 
1000         # rpfilter and default route
1001         $IP nexthop flush >/dev/null 2>&1
1002         run_cmd "ip netns exec me ip6tables -t mangle -I PREROUTING 1 -m rpfilter --invert -j DROP"
1003         run_cmd "$IP nexthop add id 91 via 2001:db8:91::2 dev veth1"
1004         run_cmd "$IP nexthop add id 92 via 2001:db8:92::2 dev veth3"
1005         run_cmd "$IP nexthop add id 93 group 91/92"
1006         run_cmd "$IP -6 ro add default nhid 91"
1007         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
1008         log_test $? 0 "Nexthop with default route and rpfilter"
1009         run_cmd "$IP -6 ro replace default nhid 93"
1010         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
1011         log_test $? 0 "Nexthop with multipath default route and rpfilter"
1012 
1013         # TO-DO:
1014         # existing route with old nexthop; append route with new nexthop
1015         # existing route with old nexthop; replace route with new
1016         # existing route with new nexthop; replace route with old
1017         # route with src address and using nexthop - not allowed
1018 }
1019 
1020 ipv6_large_grp()
1021 {
1022         local ecmp=32
1023 
1024         echo
1025         echo "IPv6 large groups (x$ecmp)"
1026         echo "---------------------"
1027 
1028         check_large_grp 6 $ecmp
1029 
1030         $IP nexthop flush >/dev/null 2>&1
1031 }
1032 
1033 ipv6_large_res_grp()
1034 {
1035         echo
1036         echo "IPv6 large resilient group (128k buckets)"
1037         echo "-----------------------------------------"
1038 
1039         check_nexthop_res_support
1040         if [ $? -eq $ksft_skip ]; then
1041                 return $ksft_skip
1042         fi
1043 
1044         check_large_res_grp 6 $((128 * 1024))
1045 
1046         $IP nexthop flush >/dev/null 2>&1
1047 }
1048 
1049 ipv6_del_add_loop1()
1050 {
1051         while :; do
1052                 $IP nexthop del id 100
1053                 $IP nexthop add id 100 via 2001:db8:91::2 dev veth1
1054         done >/dev/null 2>&1
1055 }
1056 
1057 ipv6_grp_replace_loop()
1058 {
1059         while :; do
1060                 $IP nexthop replace id 102 group 100/101
1061         done >/dev/null 2>&1
1062 }
1063 
1064 ipv6_torture()
1065 {
1066         local pid1
1067         local pid2
1068         local pid3
1069         local pid4
1070         local pid5
1071 
1072         echo
1073         echo "IPv6 runtime torture"
1074         echo "--------------------"
1075         if [ ! -x "$(command -v mausezahn)" ]; then
1076                 echo "SKIP: Could not run test; need mausezahn tool"
1077                 return
1078         fi
1079 
1080         run_cmd "$IP nexthop add id 100 via 2001:db8:91::2 dev veth1"
1081         run_cmd "$IP nexthop add id 101 via 2001:db8:92::2 dev veth3"
1082         run_cmd "$IP nexthop add id 102 group 100/101"
1083         run_cmd "$IP route add 2001:db8:101::1 nhid 102"
1084         run_cmd "$IP route add 2001:db8:101::2 nhid 102"
1085 
1086         ipv6_del_add_loop1 &
1087         pid1=$!
1088         ipv6_grp_replace_loop &
1089         pid2=$!
1090         ip netns exec me ping -f 2001:db8:101::1 >/dev/null 2>&1 &
1091         pid3=$!
1092         ip netns exec me ping -f 2001:db8:101::2 >/dev/null 2>&1 &
1093         pid4=$!
1094         ip netns exec me mausezahn -6 veth1 -B 2001:db8:101::2 -A 2001:db8:91::1 -c 0 -t tcp "dp=1-1023, flags=syn" >/dev/null 2>&1 &
1095         pid5=$!
1096 
1097         sleep 300
1098         kill -9 $pid1 $pid2 $pid3 $pid4 $pid5
1099         wait $pid1 $pid2 $pid3 $pid4 $pid5 2>/dev/null
1100 
1101         # if we did not crash, success
1102         log_test 0 0 "IPv6 torture test"
1103 }
1104 
1105 ipv6_res_grp_replace_loop()
1106 {
1107         while :; do
1108                 $IP nexthop replace id 102 group 100/101 type resilient
1109         done >/dev/null 2>&1
1110 }
1111 
1112 ipv6_res_torture()
1113 {
1114         local pid1
1115         local pid2
1116         local pid3
1117         local pid4
1118         local pid5
1119 
1120         echo
1121         echo "IPv6 runtime resilient nexthop group torture"
1122         echo "--------------------------------------------"
1123 
1124         check_nexthop_res_support
1125         if [ $? -eq $ksft_skip ]; then
1126                 return $ksft_skip
1127         fi
1128 
1129         if [ ! -x "$(command -v mausezahn)" ]; then
1130                 echo "SKIP: Could not run test; need mausezahn tool"
1131                 return
1132         fi
1133 
1134         run_cmd "$IP nexthop add id 100 via 2001:db8:91::2 dev veth1"
1135         run_cmd "$IP nexthop add id 101 via 2001:db8:92::2 dev veth3"
1136         run_cmd "$IP nexthop add id 102 group 100/101 type resilient buckets 512 idle_timer 0"
1137         run_cmd "$IP route add 2001:db8:101::1 nhid 102"
1138         run_cmd "$IP route add 2001:db8:101::2 nhid 102"
1139 
1140         ipv6_del_add_loop1 &
1141         pid1=$!
1142         ipv6_res_grp_replace_loop &
1143         pid2=$!
1144         ip netns exec me ping -f 2001:db8:101::1 >/dev/null 2>&1 &
1145         pid3=$!
1146         ip netns exec me ping -f 2001:db8:101::2 >/dev/null 2>&1 &
1147         pid4=$!
1148         ip netns exec me mausezahn -6 veth1 \
1149                             -B 2001:db8:101::2 -A 2001:db8:91::1 -c 0 \
1150                             -t tcp "dp=1-1023, flags=syn" >/dev/null 2>&1 &
1151         pid5=$!
1152 
1153         sleep 300
1154         kill -9 $pid1 $pid2 $pid3 $pid4 $pid5
1155         wait $pid1 $pid2 $pid3 $pid4 $pid5 2>/dev/null
1156 
1157         # if we did not crash, success
1158         log_test 0 0 "IPv6 resilient nexthop group torture test"
1159 }
1160 
1161 ipv4_fcnal()
1162 {
1163         local rc
1164 
1165         echo
1166         echo "IPv4 functional"
1167         echo "----------------------"
1168 
1169         #
1170         # basic IPv4 ops - add, get, delete
1171         #
1172         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
1173         rc=$?
1174         log_test $rc 0 "Create nexthop with id, gw, dev"
1175         if [ $rc -ne 0 ]; then
1176                 echo "Basic IPv4 create fails; can not continue"
1177                 return 1
1178         fi
1179 
1180         run_cmd "$IP nexthop get id 12"
1181         log_test $? 0 "Get nexthop by id"
1182         check_nexthop "id 12" "id 12 via 172.16.1.2 dev veth1 scope link"
1183 
1184         run_cmd "$IP nexthop del id 12"
1185         log_test $? 0 "Delete nexthop by id"
1186         check_nexthop "id 52" ""
1187 
1188         #
1189         # gw, device spec
1190         #
1191         # gw validation, no device - fails since dev is required
1192         run_cmd "$IP nexthop add id 12 via 172.16.2.3"
1193         log_test $? 2 "Create nexthop - gw only"
1194 
1195         # gw not reachable through given dev
1196         run_cmd "$IP nexthop add id 13 via 172.16.3.2 dev veth1"
1197         log_test $? 2 "Create nexthop - invalid gw+dev combination"
1198 
1199         # onlink flag overrides gw+dev lookup
1200         run_cmd "$IP nexthop add id 13 via 172.16.3.2 dev veth1 onlink"
1201         log_test $? 0 "Create nexthop - gw+dev and onlink"
1202 
1203         # admin down should delete nexthops
1204         set -e
1205         run_cmd "$IP nexthop add id 15 via 172.16.1.3 dev veth1"
1206         run_cmd "$IP nexthop add id 16 via 172.16.1.4 dev veth1"
1207         run_cmd "$IP nexthop add id 17 via 172.16.1.5 dev veth1"
1208         run_cmd "$IP li set dev veth1 down"
1209         set +e
1210         check_nexthop "dev veth1" ""
1211         log_test $? 0 "Nexthops removed on admin down"
1212 
1213         # nexthop route delete warning: route add with nhid and delete
1214         # using device
1215         run_cmd "$IP li set dev veth1 up"
1216         run_cmd "$IP nexthop add id 12 via 172.16.1.3 dev veth1"
1217         out1=`dmesg | grep "WARNING:.*fib_nh_match.*" | wc -l`
1218         run_cmd "$IP route add 172.16.101.1/32 nhid 12"
1219         run_cmd "$IP route delete 172.16.101.1/32 dev veth1"
1220         out2=`dmesg | grep "WARNING:.*fib_nh_match.*" | wc -l`
1221         [ $out1 -eq $out2 ]
1222         rc=$?
1223         log_test $rc 0 "Delete nexthop route warning"
1224         run_cmd "$IP route delete 172.16.101.1/32 nhid 12"
1225         run_cmd "$IP nexthop del id 12"
1226 }
1227 
1228 ipv4_grp_fcnal()
1229 {
1230         local rc
1231 
1232         echo
1233         echo "IPv4 groups functional"
1234         echo "----------------------"
1235 
1236         # basic functionality: create a nexthop group, default weight
1237         run_cmd "$IP nexthop add id 11 via 172.16.1.2 dev veth1"
1238         run_cmd "$IP nexthop add id 101 group 11"
1239         log_test $? 0 "Create nexthop group with single nexthop"
1240 
1241         # get nexthop group
1242         run_cmd "$IP nexthop get id 101"
1243         log_test $? 0 "Get nexthop group by id"
1244         check_nexthop "id 101" "id 101 group 11"
1245 
1246         # delete nexthop group
1247         run_cmd "$IP nexthop del id 101"
1248         log_test $? 0 "Delete nexthop group by id"
1249         check_nexthop "id 101" ""
1250 
1251         $IP nexthop flush >/dev/null 2>&1
1252 
1253         #
1254         # create group with multiple nexthops
1255         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
1256         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
1257         run_cmd "$IP nexthop add id 14 via 172.16.1.4 dev veth1"
1258         run_cmd "$IP nexthop add id 15 via 172.16.1.5 dev veth1"
1259         run_cmd "$IP nexthop add id 102 group 12/13/14/15"
1260         log_test $? 0 "Nexthop group with multiple nexthops"
1261         check_nexthop "id 102" "id 102 group 12/13/14/15"
1262 
1263         # Delete nexthop in a group and group is updated
1264         run_cmd "$IP nexthop del id 13"
1265         check_nexthop "id 102" "id 102 group 12/14/15"
1266         log_test $? 0 "Nexthop group updated when entry is deleted"
1267 
1268         # create group with multiple weighted nexthops
1269         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
1270         run_cmd "$IP nexthop add id 103 group 12/13,2/14,3/15,4"
1271         log_test $? 0 "Nexthop group with weighted nexthops"
1272         check_nexthop "id 103" "id 103 group 12/13,2/14,3/15,4"
1273 
1274         # Delete nexthop in a weighted group and group is updated
1275         run_cmd "$IP nexthop del id 13"
1276         check_nexthop "id 103" "id 103 group 12/14,3/15,4"
1277         log_test $? 0 "Weighted nexthop group updated when entry is deleted"
1278 
1279         # admin down - nexthop is removed from group
1280         run_cmd "$IP li set dev veth1 down"
1281         check_nexthop "dev veth1" ""
1282         log_test $? 0 "Nexthops in groups removed on admin down"
1283 
1284         # expect groups to have been deleted as well
1285         check_nexthop "" ""
1286 
1287         run_cmd "$IP li set dev veth1 up"
1288 
1289         $IP nexthop flush >/dev/null 2>&1
1290 
1291         # group with nexthops using different devices
1292         set -e
1293         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
1294         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
1295         run_cmd "$IP nexthop add id 14 via 172.16.1.4 dev veth1"
1296         run_cmd "$IP nexthop add id 15 via 172.16.1.5 dev veth1"
1297 
1298         run_cmd "$IP nexthop add id 22 via 172.16.2.2 dev veth3"
1299         run_cmd "$IP nexthop add id 23 via 172.16.2.3 dev veth3"
1300         run_cmd "$IP nexthop add id 24 via 172.16.2.4 dev veth3"
1301         run_cmd "$IP nexthop add id 25 via 172.16.2.5 dev veth3"
1302         set +e
1303 
1304         # multiple groups with same nexthop
1305         run_cmd "$IP nexthop add id 104 group 12"
1306         run_cmd "$IP nexthop add id 105 group 12"
1307         check_nexthop "group" "id 104 group 12 id 105 group 12"
1308         log_test $? 0 "Multiple groups with same nexthop"
1309 
1310         run_cmd "$IP nexthop flush groups"
1311         [ $? -ne 0 ] && return 1
1312 
1313         # on admin down of veth1, it should be removed from the group
1314         run_cmd "$IP nexthop add id 105 group 12/13/22/23/14"
1315         run_cmd "$IP li set veth1 down"
1316         check_nexthop "id 105" "id 105 group 22/23"
1317         log_test $? 0 "Nexthops in group removed on admin down - mixed group"
1318 
1319         run_cmd "$IP nexthop add id 106 group 105/24"
1320         log_test $? 2 "Nexthop group can not have a group as an entry"
1321 
1322         # a group can have a blackhole entry only if it is the only
1323         # nexthop in the group. Needed for atomic replace with an
1324         # actual nexthop group
1325         run_cmd "$IP nexthop add id 31 blackhole"
1326         run_cmd "$IP nexthop add id 107 group 31"
1327         log_test $? 0 "Nexthop group with a blackhole entry"
1328 
1329         run_cmd "$IP nexthop add id 108 group 31/24"
1330         log_test $? 2 "Nexthop group can not have a blackhole and another nexthop"
1331 }
1332 
1333 ipv4_res_grp_fcnal()
1334 {
1335         local rc
1336 
1337         echo
1338         echo "IPv4 resilient groups functional"
1339         echo "--------------------------------"
1340 
1341         check_nexthop_res_support
1342         if [ $? -eq $ksft_skip ]; then
1343                 return $ksft_skip
1344         fi
1345 
1346         #
1347         # migration of nexthop buckets - equal weights
1348         #
1349         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
1350         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
1351         run_cmd "$IP nexthop add id 102 group 12/13 type resilient buckets 2 idle_timer 0"
1352 
1353         run_cmd "$IP nexthop del id 13"
1354         check_nexthop "id 102" \
1355                 "id 102 group 12 type resilient buckets 2 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
1356         log_test $? 0 "Nexthop group updated when entry is deleted"
1357         check_nexthop_bucket "list id 102" \
1358                 "id 102 index 0 nhid 12 id 102 index 1 nhid 12"
1359         log_test $? 0 "Nexthop buckets updated when entry is deleted"
1360 
1361         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
1362         run_cmd "$IP nexthop replace id 102 group 12/13 type resilient buckets 2 idle_timer 0"
1363         check_nexthop "id 102" \
1364                 "id 102 group 12/13 type resilient buckets 2 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
1365         log_test $? 0 "Nexthop group updated after replace"
1366         check_nexthop_bucket "list id 102" \
1367                 "id 102 index 0 nhid 13 id 102 index 1 nhid 12"
1368         log_test $? 0 "Nexthop buckets updated after replace"
1369 
1370         $IP nexthop flush >/dev/null 2>&1
1371 
1372         #
1373         # migration of nexthop buckets - unequal weights
1374         #
1375         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
1376         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
1377         run_cmd "$IP nexthop add id 102 group 12,3/13,1 type resilient buckets 4 idle_timer 0"
1378 
1379         run_cmd "$IP nexthop del id 13"
1380         check_nexthop "id 102" \
1381                 "id 102 group 12,3 type resilient buckets 4 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
1382         log_test $? 0 "Nexthop group updated when entry is deleted - nECMP"
1383         check_nexthop_bucket "list id 102" \
1384                 "id 102 index 0 nhid 12 id 102 index 1 nhid 12 id 102 index 2 nhid 12 id 102 index 3 nhid 12"
1385         log_test $? 0 "Nexthop buckets updated when entry is deleted - nECMP"
1386 
1387         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
1388         run_cmd "$IP nexthop replace id 102 group 12,3/13,1 type resilient buckets 4 idle_timer 0"
1389         check_nexthop "id 102" \
1390                 "id 102 group 12,3/13 type resilient buckets 4 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
1391         log_test $? 0 "Nexthop group updated after replace - nECMP"
1392         check_nexthop_bucket "list id 102" \
1393                 "id 102 index 0 nhid 13 id 102 index 1 nhid 12 id 102 index 2 nhid 12 id 102 index 3 nhid 12"
1394         log_test $? 0 "Nexthop buckets updated after replace - nECMP"
1395 }
1396 
1397 ipv4_withv6_fcnal()
1398 {
1399         local lladdr
1400 
1401         set -e
1402         lladdr=$(get_linklocal veth2 peer)
1403         run_cmd "$IP nexthop add id 11 via ${lladdr} dev veth1"
1404         set +e
1405         run_cmd "$IP ro add 172.16.101.1/32 nhid 11"
1406         log_test $? 0 "IPv6 nexthop with IPv4 route"
1407         check_route "172.16.101.1" "172.16.101.1 nhid 11 via inet6 ${lladdr} dev veth1"
1408 
1409         set -e
1410         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
1411         run_cmd "$IP nexthop add id 101 group 11/12"
1412         set +e
1413         run_cmd "$IP ro replace 172.16.101.1/32 nhid 101"
1414         log_test $? 0 "IPv6 nexthop with IPv4 route"
1415 
1416         check_route "172.16.101.1" "172.16.101.1 nhid 101 nexthop via inet6 ${lladdr} dev veth1 weight 1 nexthop via 172.16.1.2 dev veth1 weight 1"
1417 
1418         run_cmd "$IP ro replace 172.16.101.1/32 via inet6 ${lladdr} dev veth1"
1419         log_test $? 0 "IPv4 route with IPv6 gateway"
1420         check_route "172.16.101.1" "172.16.101.1 via inet6 ${lladdr} dev veth1"
1421 
1422         run_cmd "$IP ro replace 172.16.101.1/32 via inet6 2001:db8:50::1 dev veth1"
1423         log_test $? 2 "IPv4 route with invalid IPv6 gateway"
1424 }
1425 
1426 ipv4_fcnal_runtime()
1427 {
1428         local lladdr
1429         local rc
1430 
1431         echo
1432         echo "IPv4 functional runtime"
1433         echo "-----------------------"
1434 
1435         run_cmd "$IP nexthop add id 21 via 172.16.1.2 dev veth1"
1436         run_cmd "$IP ro add 172.16.101.1/32 nhid 21"
1437         log_test $? 0 "Route add"
1438         check_route "172.16.101.1" "172.16.101.1 nhid 21 via 172.16.1.2 dev veth1"
1439 
1440         run_cmd "$IP ro delete 172.16.101.1/32 nhid 21"
1441         log_test $? 0 "Route delete"
1442 
1443         #
1444         # scope mismatch
1445         #
1446         run_cmd "$IP nexthop add id 22 via 172.16.1.2 dev veth1"
1447         run_cmd "$IP ro add 172.16.101.1/32 nhid 22 scope host"
1448         log_test $? 2 "Route add - scope conflict with nexthop"
1449 
1450         run_cmd "$IP nexthop replace id 22 dev veth3"
1451         run_cmd "$IP ro add 172.16.101.1/32 nhid 22 scope host"
1452         run_cmd "$IP nexthop replace id 22 via 172.16.2.2 dev veth3"
1453         log_test $? 2 "Nexthop replace with invalid scope for existing route"
1454 
1455         # check cleanup path on invalid metric
1456         run_cmd "$IP ro add 172.16.101.2/32 nhid 22 congctl lock foo"
1457         log_test $? 2 "IPv4 route with invalid metric"
1458 
1459         #
1460         # add route with nexthop and check traffic
1461         #
1462         run_cmd "$IP nexthop replace id 21 via 172.16.1.2 dev veth1"
1463         run_cmd "$IP ro replace 172.16.101.1/32 nhid 21"
1464         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1465         log_test $? 0 "Basic ping"
1466 
1467         run_cmd "$IP nexthop replace id 22 via 172.16.2.2 dev veth3"
1468         run_cmd "$IP nexthop add id 122 group 21/22"
1469         run_cmd "$IP ro replace 172.16.101.1/32 nhid 122"
1470         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1471         log_test $? 0 "Ping - multipath"
1472 
1473         run_cmd "$IP ro delete 172.16.101.1/32 nhid 122"
1474 
1475         #
1476         # multiple default routes
1477         # - tests fib_select_default
1478         run_cmd "$IP nexthop add id 501 via 172.16.1.2 dev veth1"
1479         run_cmd "$IP ro add default nhid 501"
1480         run_cmd "$IP ro add default via 172.16.1.3 dev veth1 metric 20"
1481         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1482         log_test $? 0 "Ping - multiple default routes, nh first"
1483 
1484         # flip the order
1485         run_cmd "$IP ro del default nhid 501"
1486         run_cmd "$IP ro del default via 172.16.1.3 dev veth1 metric 20"
1487         run_cmd "$IP ro add default via 172.16.1.2 dev veth1 metric 20"
1488         run_cmd "$IP nexthop replace id 501 via 172.16.1.3 dev veth1"
1489         run_cmd "$IP ro add default nhid 501 metric 20"
1490         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1491         log_test $? 0 "Ping - multiple default routes, nh second"
1492 
1493         run_cmd "$IP nexthop delete nhid 501"
1494         run_cmd "$IP ro del default"
1495 
1496         #
1497         # IPv4 with blackhole nexthops
1498         #
1499         run_cmd "$IP nexthop add id 23 blackhole"
1500         run_cmd "$IP ro replace 172.16.101.1/32 nhid 23"
1501         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1502         log_test $? 2 "Ping - blackhole"
1503 
1504         run_cmd "$IP nexthop replace id 23 via 172.16.1.2 dev veth1"
1505         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1506         log_test $? 0 "Ping - blackhole replaced with gateway"
1507 
1508         run_cmd "$IP nexthop replace id 23 blackhole"
1509         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1510         log_test $? 2 "Ping - gateway replaced by blackhole"
1511 
1512         run_cmd "$IP ro replace 172.16.101.1/32 nhid 122"
1513         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1514         if [ $? -eq 0 ]; then
1515                 run_cmd "$IP nexthop replace id 122 group 23"
1516                 run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1517                 log_test $? 2 "Ping - group with blackhole"
1518 
1519                 run_cmd "$IP nexthop replace id 122 group 21/22"
1520                 run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1521                 log_test $? 0 "Ping - group blackhole replaced with gateways"
1522         else
1523                 log_test 2 0 "Ping - multipath failed"
1524         fi
1525 
1526         #
1527         # device only and gw + dev only mix
1528         #
1529         run_cmd "$IP nexthop add id 85 dev veth1"
1530         run_cmd "$IP ro replace 172.16.101.1/32 nhid 85"
1531         log_test $? 0 "IPv4 route with device only nexthop"
1532         check_route "172.16.101.1" "172.16.101.1 nhid 85 dev veth1"
1533 
1534         run_cmd "$IP nexthop add id 123 group 21/85"
1535         run_cmd "$IP ro replace 172.16.101.1/32 nhid 123"
1536         log_test $? 0 "IPv4 multipath route with nexthop mix - dev only + gw"
1537         check_route "172.16.101.1" "172.16.101.1 nhid 123 nexthop via 172.16.1.2 dev veth1 weight 1 nexthop dev veth1 weight 1"
1538 
1539         #
1540         # IPv4 with IPv6
1541         #
1542         set -e
1543         lladdr=$(get_linklocal veth2 peer)
1544         run_cmd "$IP nexthop add id 24 via ${lladdr} dev veth1"
1545         set +e
1546         run_cmd "$IP ro replace 172.16.101.1/32 nhid 24"
1547         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1548         log_test $? 0 "IPv6 nexthop with IPv4 route"
1549 
1550         $IP neigh sh | grep -q "${lladdr} dev veth1"
1551         if [ $? -eq 1 ]; then
1552                 echo "    WARNING: Neigh entry missing for ${lladdr}"
1553                 $IP neigh sh | grep 'dev veth1'
1554         fi
1555 
1556         $IP neigh sh | grep -q "172.16.101.1 dev eth1"
1557         if [ $? -eq 0 ]; then
1558                 echo "    WARNING: Neigh entry exists for 172.16.101.1"
1559                 $IP neigh sh | grep 'dev veth1'
1560         fi
1561 
1562         set -e
1563         run_cmd "$IP nexthop add id 25 via 172.16.1.2 dev veth1"
1564         run_cmd "$IP nexthop add id 101 group 24/25"
1565         set +e
1566         run_cmd "$IP ro replace 172.16.101.1/32 nhid 101"
1567         log_test $? 0 "IPv4 route with mixed v4-v6 multipath route"
1568 
1569         check_route "172.16.101.1" "172.16.101.1 nhid 101 nexthop via inet6 ${lladdr} dev veth1 weight 1 nexthop via 172.16.1.2 dev veth1 weight 1"
1570 
1571         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1572         log_test $? 0 "IPv6 nexthop with IPv4 route"
1573 
1574         run_cmd "$IP ro replace 172.16.101.1/32 via inet6 ${lladdr} dev veth1"
1575         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1576         log_test $? 0 "IPv4 route with IPv6 gateway"
1577 
1578         $IP neigh sh | grep -q "${lladdr} dev veth1"
1579         if [ $? -eq 1 ]; then
1580                 echo "    WARNING: Neigh entry missing for ${lladdr}"
1581                 $IP neigh sh | grep 'dev veth1'
1582         fi
1583 
1584         $IP neigh sh | grep -q "172.16.101.1 dev eth1"
1585         if [ $? -eq 0 ]; then
1586                 echo "    WARNING: Neigh entry exists for 172.16.101.1"
1587                 $IP neigh sh | grep 'dev veth1'
1588         fi
1589 
1590         run_cmd "$IP ro del 172.16.101.1/32 via inet6 ${lladdr} dev veth1"
1591         run_cmd "$IP -4 ro add default via inet6 ${lladdr} dev veth1"
1592         run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 172.16.101.1"
1593         log_test $? 0 "IPv4 default route with IPv6 gateway"
1594 
1595         #
1596         # MPLS as an example of LWT encap
1597         #
1598         run_cmd "$IP nexthop add id 51 encap mpls 101 via 172.16.1.2 dev veth1"
1599         log_test $? 0 "IPv4 route with MPLS encap"
1600         check_nexthop "id 51" "id 51 encap mpls 101 via 172.16.1.2 dev veth1 scope link"
1601         log_test $? 0 "IPv4 route with MPLS encap - check"
1602 
1603         run_cmd "$IP nexthop add id 52 encap mpls 102 via inet6 2001:db8:91::2 dev veth1"
1604         log_test $? 0 "IPv4 route with MPLS encap and v6 gateway"
1605         check_nexthop "id 52" "id 52 encap mpls 102 via 2001:db8:91::2 dev veth1 scope link"
1606         log_test $? 0 "IPv4 route with MPLS encap, v6 gw - check"
1607 }
1608 
1609 ipv4_large_grp()
1610 {
1611         local ecmp=32
1612 
1613         echo
1614         echo "IPv4 large groups (x$ecmp)"
1615         echo "---------------------"
1616 
1617         check_large_grp 4 $ecmp
1618 
1619         $IP nexthop flush >/dev/null 2>&1
1620 }
1621 
1622 ipv4_large_res_grp()
1623 {
1624         echo
1625         echo "IPv4 large resilient group (128k buckets)"
1626         echo "-----------------------------------------"
1627 
1628         check_nexthop_res_support
1629         if [ $? -eq $ksft_skip ]; then
1630                 return $ksft_skip
1631         fi
1632 
1633         check_large_res_grp 4 $((128 * 1024))
1634 
1635         $IP nexthop flush >/dev/null 2>&1
1636 }
1637 
1638 sysctl_nexthop_compat_mode_check()
1639 {
1640         local sysctlname="net.ipv4.nexthop_compat_mode"
1641         local lprefix=$1
1642 
1643         IPE="ip netns exec me"
1644 
1645         $IPE sysctl -q $sysctlname 2>&1 >/dev/null
1646         if [ $? -ne 0 ]; then
1647                 echo "SKIP: kernel lacks nexthop compat mode sysctl control"
1648                 return $ksft_skip
1649         fi
1650 
1651         out=$($IPE sysctl $sysctlname 2>/dev/null)
1652         log_test $? 0 "$lprefix default nexthop compat mode check"
1653         check_output "${out}" "$sysctlname = 1"
1654 }
1655 
1656 sysctl_nexthop_compat_mode_set()
1657 {
1658         local sysctlname="net.ipv4.nexthop_compat_mode"
1659         local mode=$1
1660         local lprefix=$2
1661 
1662         IPE="ip netns exec me"
1663 
1664         out=$($IPE sysctl -w $sysctlname=$mode)
1665         log_test $? 0 "$lprefix set compat mode - $mode"
1666         check_output "${out}" "net.ipv4.nexthop_compat_mode = $mode"
1667 }
1668 
1669 ipv6_compat_mode()
1670 {
1671         local rc
1672 
1673         echo
1674         echo "IPv6 nexthop api compat mode test"
1675         echo "--------------------------------"
1676 
1677         sysctl_nexthop_compat_mode_check "IPv6"
1678         if [ $? -eq $ksft_skip ]; then
1679                 return $ksft_skip
1680         fi
1681 
1682         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
1683         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
1684         run_cmd "$IP nexthop add id 122 group 62/63"
1685         ipmout=$(start_ip_monitor route)
1686 
1687         run_cmd "$IP -6 ro add 2001:db8:101::1/128 nhid 122"
1688         # route add notification should contain expanded nexthops
1689         stop_ip_monitor $ipmout 3
1690         log_test $? 0 "IPv6 compat mode on - route add notification"
1691 
1692         # route dump should contain expanded nexthops
1693         check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 122 metric 1024 nexthop via 2001:db8:91::2 dev veth1 weight 1 nexthop via 2001:db8:91::3 dev veth1 weight 1"
1694         log_test $? 0 "IPv6 compat mode on - route dump"
1695 
1696         # change in nexthop group should generate route notification
1697         run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
1698         ipmout=$(start_ip_monitor route)
1699         run_cmd "$IP nexthop replace id 122 group 62/64"
1700         stop_ip_monitor $ipmout 3
1701 
1702         log_test $? 0 "IPv6 compat mode on - nexthop change"
1703 
1704         # set compat mode off
1705         sysctl_nexthop_compat_mode_set 0 "IPv6"
1706 
1707         run_cmd "$IP -6 ro del 2001:db8:101::1/128 nhid 122"
1708 
1709         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
1710         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
1711         run_cmd "$IP nexthop add id 122 group 62/63"
1712         ipmout=$(start_ip_monitor route)
1713 
1714         run_cmd "$IP -6 ro add 2001:db8:101::1/128 nhid 122"
1715         # route add notification should not contain expanded nexthops
1716         stop_ip_monitor $ipmout 1
1717         log_test $? 0 "IPv6 compat mode off - route add notification"
1718 
1719         # route dump should not contain expanded nexthops
1720         check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 122 metric 1024"
1721         log_test $? 0 "IPv6 compat mode off - route dump"
1722 
1723         # change in nexthop group should not generate route notification
1724         run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
1725         ipmout=$(start_ip_monitor route)
1726         run_cmd "$IP nexthop replace id 122 group 62/64"
1727         stop_ip_monitor $ipmout 0
1728         log_test $? 0 "IPv6 compat mode off - nexthop change"
1729 
1730         # nexthop delete should not generate route notification
1731         ipmout=$(start_ip_monitor route)
1732         run_cmd "$IP nexthop del id 122"
1733         stop_ip_monitor $ipmout 0
1734         log_test $? 0 "IPv6 compat mode off - nexthop delete"
1735 
1736         # set compat mode back on
1737         sysctl_nexthop_compat_mode_set 1 "IPv6"
1738 }
1739 
1740 ipv4_compat_mode()
1741 {
1742         local rc
1743 
1744         echo
1745         echo "IPv4 nexthop api compat mode"
1746         echo "----------------------------"
1747 
1748         sysctl_nexthop_compat_mode_check "IPv4"
1749         if [ $? -eq $ksft_skip ]; then
1750                 return $ksft_skip
1751         fi
1752 
1753         run_cmd "$IP nexthop add id 21 via 172.16.1.2 dev veth1"
1754         run_cmd "$IP nexthop add id 22 via 172.16.1.2 dev veth1"
1755         run_cmd "$IP nexthop add id 122 group 21/22"
1756         ipmout=$(start_ip_monitor route)
1757 
1758         run_cmd "$IP ro add 172.16.101.1/32 nhid 122"
1759         stop_ip_monitor $ipmout 3
1760 
1761         # route add notification should contain expanded nexthops
1762         log_test $? 0 "IPv4 compat mode on - route add notification"
1763 
1764         # route dump should contain expanded nexthops
1765         check_route "172.16.101.1" "172.16.101.1 nhid 122 nexthop via 172.16.1.2 dev veth1 weight 1 nexthop via 172.16.1.2 dev veth1 weight 1"
1766         log_test $? 0 "IPv4 compat mode on - route dump"
1767 
1768         # change in nexthop group should generate route notification
1769         run_cmd "$IP nexthop add id 23 via 172.16.1.3 dev veth1"
1770         ipmout=$(start_ip_monitor route)
1771         run_cmd "$IP nexthop replace id 122 group 21/23"
1772         stop_ip_monitor $ipmout 3
1773         log_test $? 0 "IPv4 compat mode on - nexthop change"
1774 
1775         sysctl_nexthop_compat_mode_set 0 "IPv4"
1776 
1777         # cleanup
1778         run_cmd "$IP ro del 172.16.101.1/32 nhid 122"
1779 
1780         ipmout=$(start_ip_monitor route)
1781         run_cmd "$IP ro add 172.16.101.1/32 nhid 122"
1782         stop_ip_monitor $ipmout 1
1783         # route add notification should not contain expanded nexthops
1784         log_test $? 0 "IPv4 compat mode off - route add notification"
1785 
1786         # route dump should not contain expanded nexthops
1787         check_route "172.16.101.1" "172.16.101.1 nhid 122"
1788         log_test $? 0 "IPv4 compat mode off - route dump"
1789 
1790         # change in nexthop group should not generate route notification
1791         ipmout=$(start_ip_monitor route)
1792         run_cmd "$IP nexthop replace id 122 group 21/22"
1793         stop_ip_monitor $ipmout 0
1794         log_test $? 0 "IPv4 compat mode off - nexthop change"
1795 
1796         # nexthop delete should not generate route notification
1797         ipmout=$(start_ip_monitor route)
1798         run_cmd "$IP nexthop del id 122"
1799         stop_ip_monitor $ipmout 0
1800         log_test $? 0 "IPv4 compat mode off - nexthop delete"
1801 
1802         sysctl_nexthop_compat_mode_set 1 "IPv4"
1803 }
1804 
1805 ipv4_del_add_loop1()
1806 {
1807         while :; do
1808                 $IP nexthop del id 100
1809                 $IP nexthop add id 100 via 172.16.1.2 dev veth1
1810         done >/dev/null 2>&1
1811 }
1812 
1813 ipv4_grp_replace_loop()
1814 {
1815         while :; do
1816                 $IP nexthop replace id 102 group 100/101
1817         done >/dev/null 2>&1
1818 }
1819 
1820 ipv4_torture()
1821 {
1822         local pid1
1823         local pid2
1824         local pid3
1825         local pid4
1826         local pid5
1827 
1828         echo
1829         echo "IPv4 runtime torture"
1830         echo "--------------------"
1831         if [ ! -x "$(command -v mausezahn)" ]; then
1832                 echo "SKIP: Could not run test; need mausezahn tool"
1833                 return
1834         fi
1835 
1836         run_cmd "$IP nexthop add id 100 via 172.16.1.2 dev veth1"
1837         run_cmd "$IP nexthop add id 101 via 172.16.2.2 dev veth3"
1838         run_cmd "$IP nexthop add id 102 group 100/101"
1839         run_cmd "$IP route add 172.16.101.1 nhid 102"
1840         run_cmd "$IP route add 172.16.101.2 nhid 102"
1841 
1842         ipv4_del_add_loop1 &
1843         pid1=$!
1844         ipv4_grp_replace_loop &
1845         pid2=$!
1846         ip netns exec me ping -f 172.16.101.1 >/dev/null 2>&1 &
1847         pid3=$!
1848         ip netns exec me ping -f 172.16.101.2 >/dev/null 2>&1 &
1849         pid4=$!
1850         ip netns exec me mausezahn veth1 -B 172.16.101.2 -A 172.16.1.1 -c 0 -t tcp "dp=1-1023, flags=syn" >/dev/null 2>&1 &
1851         pid5=$!
1852 
1853         sleep 300
1854         kill -9 $pid1 $pid2 $pid3 $pid4 $pid5
1855         wait $pid1 $pid2 $pid3 $pid4 $pid5 2>/dev/null
1856 
1857         # if we did not crash, success
1858         log_test 0 0 "IPv4 torture test"
1859 }
1860 
1861 ipv4_res_grp_replace_loop()
1862 {
1863         while :; do
1864                 $IP nexthop replace id 102 group 100/101 type resilient
1865         done >/dev/null 2>&1
1866 }
1867 
1868 ipv4_res_torture()
1869 {
1870         local pid1
1871         local pid2
1872         local pid3
1873         local pid4
1874         local pid5
1875 
1876         echo
1877         echo "IPv4 runtime resilient nexthop group torture"
1878         echo "--------------------------------------------"
1879 
1880         check_nexthop_res_support
1881         if [ $? -eq $ksft_skip ]; then
1882                 return $ksft_skip
1883         fi
1884 
1885         if [ ! -x "$(command -v mausezahn)" ]; then
1886                 echo "SKIP: Could not run test; need mausezahn tool"
1887                 return
1888         fi
1889 
1890         run_cmd "$IP nexthop add id 100 via 172.16.1.2 dev veth1"
1891         run_cmd "$IP nexthop add id 101 via 172.16.2.2 dev veth3"
1892         run_cmd "$IP nexthop add id 102 group 100/101 type resilient buckets 512 idle_timer 0"
1893         run_cmd "$IP route add 172.16.101.1 nhid 102"
1894         run_cmd "$IP route add 172.16.101.2 nhid 102"
1895 
1896         ipv4_del_add_loop1 &
1897         pid1=$!
1898         ipv4_res_grp_replace_loop &
1899         pid2=$!
1900         ip netns exec me ping -f 172.16.101.1 >/dev/null 2>&1 &
1901         pid3=$!
1902         ip netns exec me ping -f 172.16.101.2 >/dev/null 2>&1 &
1903         pid4=$!
1904         ip netns exec me mausezahn veth1 \
1905                                 -B 172.16.101.2 -A 172.16.1.1 -c 0 \
1906                                 -t tcp "dp=1-1023, flags=syn" >/dev/null 2>&1 &
1907         pid5=$!
1908 
1909         sleep 300
1910         kill -9 $pid1 $pid2 $pid3 $pid4 $pid5
1911         wait $pid1 $pid2 $pid3 $pid4 $pid5 2>/dev/null
1912 
1913         # if we did not crash, success
1914         log_test 0 0 "IPv4 resilient nexthop group torture test"
1915 }
1916 
1917 basic()
1918 {
1919         echo
1920         echo "Basic functional tests"
1921         echo "----------------------"
1922         run_cmd "$IP nexthop ls"
1923         log_test $? 0 "List with nothing defined"
1924 
1925         run_cmd "$IP nexthop get id 1"
1926         log_test $? 2 "Nexthop get on non-existent id"
1927 
1928         # attempt to create nh without a device or gw - fails
1929         run_cmd "$IP nexthop add id 1"
1930         log_test $? 2 "Nexthop with no device or gateway"
1931 
1932         # attempt to create nh with down device - fails
1933         $IP li set veth1 down
1934         run_cmd "$IP nexthop add id 1 dev veth1"
1935         log_test $? 2 "Nexthop with down device"
1936 
1937         # create nh with linkdown device - fails
1938         $IP li set veth1 up
1939         ip -netns peer li set veth2 down
1940         run_cmd "$IP nexthop add id 1 dev veth1"
1941         log_test $? 2 "Nexthop with device that is linkdown"
1942         ip -netns peer li set veth2 up
1943 
1944         # device only
1945         run_cmd "$IP nexthop add id 1 dev veth1"
1946         log_test $? 0 "Nexthop with device only"
1947 
1948         # create nh with duplicate id
1949         run_cmd "$IP nexthop add id 1 dev veth3"
1950         log_test $? 2 "Nexthop with duplicate id"
1951 
1952         # blackhole nexthop
1953         run_cmd "$IP nexthop add id 2 blackhole"
1954         log_test $? 0 "Blackhole nexthop"
1955 
1956         # blackhole nexthop can not have other specs
1957         run_cmd "$IP nexthop replace id 2 blackhole dev veth1"
1958         log_test $? 2 "Blackhole nexthop with other attributes"
1959 
1960         # blackhole nexthop should not be affected by the state of the loopback
1961         # device
1962         run_cmd "$IP link set dev lo down"
1963         check_nexthop "id 2" "id 2 blackhole"
1964         log_test $? 0 "Blackhole nexthop with loopback device down"
1965 
1966         run_cmd "$IP link set dev lo up"
1967 
1968         #
1969         # groups
1970         #
1971 
1972         run_cmd "$IP nexthop add id 101 group 1"
1973         log_test $? 0 "Create group"
1974 
1975         run_cmd "$IP nexthop add id 102 group 2"
1976         log_test $? 0 "Create group with blackhole nexthop"
1977 
1978         # multipath group can not have a blackhole as 1 path
1979         run_cmd "$IP nexthop add id 103 group 1/2"
1980         log_test $? 2 "Create multipath group where 1 path is a blackhole"
1981 
1982         # multipath group can not have a member replaced by a blackhole
1983         run_cmd "$IP nexthop replace id 2 dev veth3"
1984         run_cmd "$IP nexthop replace id 102 group 1/2"
1985         run_cmd "$IP nexthop replace id 2 blackhole"
1986         log_test $? 2 "Multipath group can not have a member replaced by blackhole"
1987 
1988         # attempt to create group with non-existent nexthop
1989         run_cmd "$IP nexthop add id 103 group 12"
1990         log_test $? 2 "Create group with non-existent nexthop"
1991 
1992         # attempt to create group with same nexthop
1993         run_cmd "$IP nexthop add id 103 group 1/1"
1994         log_test $? 2 "Create group with same nexthop multiple times"
1995 
1996         # replace nexthop with a group - fails
1997         run_cmd "$IP nexthop replace id 2 group 1"
1998         log_test $? 2 "Replace nexthop with nexthop group"
1999 
2000         # replace nexthop group with a nexthop - fails
2001         run_cmd "$IP nexthop replace id 101 dev veth1"
2002         log_test $? 2 "Replace nexthop group with nexthop"
2003 
2004         # nexthop group with other attributes fail
2005         run_cmd "$IP nexthop add id 104 group 1 dev veth1"
2006         log_test $? 2 "Nexthop group and device"
2007 
2008         # Tests to ensure that flushing works as expected.
2009         run_cmd "$IP nexthop add id 105 blackhole proto 99"
2010         run_cmd "$IP nexthop add id 106 blackhole proto 100"
2011         run_cmd "$IP nexthop add id 107 blackhole proto 99"
2012         run_cmd "$IP nexthop flush proto 99"
2013         check_nexthop "id 105" ""
2014         check_nexthop "id 106" "id 106 blackhole proto 100"
2015         check_nexthop "id 107" ""
2016         run_cmd "$IP nexthop flush proto 100"
2017         check_nexthop "id 106" ""
2018 
2019         run_cmd "$IP nexthop flush proto 100"
2020         log_test $? 0 "Test proto flush"
2021 
2022         run_cmd "$IP nexthop add id 104 group 1 blackhole"
2023         log_test $? 2 "Nexthop group and blackhole"
2024 
2025         $IP nexthop flush >/dev/null 2>&1
2026 
2027         # Test to ensure that flushing with a multi-part nexthop dump works as
2028         # expected.
2029         local batch_file=$(mktemp)
2030 
2031         for i in $(seq 1 $((64 * 1024))); do
2032                 echo "nexthop add id $i blackhole" >> $batch_file
2033         done
2034 
2035         $IP -b $batch_file
2036         $IP nexthop flush >/dev/null 2>&1
2037         [[ $($IP nexthop | wc -l) -eq 0 ]]
2038         log_test $? 0 "Large scale nexthop flushing"
2039 
2040         rm $batch_file
2041 }
2042 
2043 check_nexthop_buckets_balance()
2044 {
2045         local nharg=$1; shift
2046         local ret
2047 
2048         while (($# > 0)); do
2049                 local selector=$1; shift
2050                 local condition=$1; shift
2051                 local count
2052 
2053                 count=$($IP -j nexthop bucket ${nharg} ${selector} | jq length)
2054                 (( $count $condition ))
2055                 ret=$?
2056                 if ((ret != 0)); then
2057                         return $ret
2058                 fi
2059         done
2060 
2061         return 0
2062 }
2063 
2064 basic_res()
2065 {
2066         echo
2067         echo "Basic resilient nexthop group functional tests"
2068         echo "----------------------------------------------"
2069 
2070         check_nexthop_res_support
2071         if [ $? -eq $ksft_skip ]; then
2072                 return $ksft_skip
2073         fi
2074 
2075         run_cmd "$IP nexthop add id 1 dev veth1"
2076 
2077         #
2078         # resilient nexthop group addition
2079         #
2080 
2081         run_cmd "$IP nexthop add id 101 group 1 type resilient buckets 8"
2082         log_test $? 0 "Add a nexthop group with default parameters"
2083 
2084         run_cmd "$IP nexthop get id 101"
2085         check_nexthop "id 101" \
2086                 "id 101 group 1 type resilient buckets 8 idle_timer 120 unbalanced_timer 0 unbalanced_time 0"
2087         log_test $? 0 "Get a nexthop group with default parameters"
2088 
2089         run_cmd "$IP nexthop add id 102 group 1 type resilient
2090                         buckets 4 idle_timer 100 unbalanced_timer 5"
2091         run_cmd "$IP nexthop get id 102"
2092         check_nexthop "id 102" \
2093                 "id 102 group 1 type resilient buckets 4 idle_timer 100 unbalanced_timer 5 unbalanced_time 0"
2094         log_test $? 0 "Get a nexthop group with non-default parameters"
2095 
2096         run_cmd "$IP nexthop add id 103 group 1 type resilient buckets 0"
2097         log_test $? 2 "Add a nexthop group with 0 buckets"
2098 
2099         #
2100         # resilient nexthop group replacement
2101         #
2102 
2103         run_cmd "$IP nexthop replace id 101 group 1 type resilient
2104                         buckets 8 idle_timer 240 unbalanced_timer 80"
2105         log_test $? 0 "Replace nexthop group parameters"
2106         check_nexthop "id 101" \
2107                 "id 101 group 1 type resilient buckets 8 idle_timer 240 unbalanced_timer 80 unbalanced_time 0"
2108         log_test $? 0 "Get a nexthop group after replacing parameters"
2109 
2110         run_cmd "$IP nexthop replace id 101 group 1 type resilient idle_timer 512"
2111         log_test $? 0 "Replace idle timer"
2112         check_nexthop "id 101" \
2113                 "id 101 group 1 type resilient buckets 8 idle_timer 512 unbalanced_timer 80 unbalanced_time 0"
2114         log_test $? 0 "Get a nexthop group after replacing idle timer"
2115 
2116         run_cmd "$IP nexthop replace id 101 group 1 type resilient unbalanced_timer 256"
2117         log_test $? 0 "Replace unbalanced timer"
2118         check_nexthop "id 101" \
2119                 "id 101 group 1 type resilient buckets 8 idle_timer 512 unbalanced_timer 256 unbalanced_time 0"
2120         log_test $? 0 "Get a nexthop group after replacing unbalanced timer"
2121 
2122         run_cmd "$IP nexthop replace id 101 group 1 type resilient"
2123         log_test $? 0 "Replace with no parameters"
2124         check_nexthop "id 101" \
2125                 "id 101 group 1 type resilient buckets 8 idle_timer 512 unbalanced_timer 256 unbalanced_time 0"
2126         log_test $? 0 "Get a nexthop group after replacing no parameters"
2127 
2128         run_cmd "$IP nexthop replace id 101 group 1"
2129         log_test $? 2 "Replace nexthop group type - implicit"
2130 
2131         run_cmd "$IP nexthop replace id 101 group 1 type mpath"
2132         log_test $? 2 "Replace nexthop group type - explicit"
2133 
2134         run_cmd "$IP nexthop replace id 101 group 1 type resilient buckets 1024"
2135         log_test $? 2 "Replace number of nexthop buckets"
2136 
2137         check_nexthop "id 101" \
2138                 "id 101 group 1 type resilient buckets 8 idle_timer 512 unbalanced_timer 256 unbalanced_time 0"
2139         log_test $? 0 "Get a nexthop group after replacing with invalid parameters"
2140 
2141         #
2142         # resilient nexthop buckets dump
2143         #
2144 
2145         $IP nexthop flush >/dev/null 2>&1
2146         run_cmd "$IP nexthop add id 1 dev veth1"
2147         run_cmd "$IP nexthop add id 2 dev veth3"
2148         run_cmd "$IP nexthop add id 101 group 1/2 type resilient buckets 4"
2149         run_cmd "$IP nexthop add id 201 group 1/2"
2150 
2151         check_nexthop_bucket "" \
2152                 "id 101 index 0 nhid 2 id 101 index 1 nhid 2 id 101 index 2 nhid 1 id 101 index 3 nhid 1"
2153         log_test $? 0 "Dump all nexthop buckets"
2154 
2155         check_nexthop_bucket "list id 101" \
2156                 "id 101 index 0 nhid 2 id 101 index 1 nhid 2 id 101 index 2 nhid 1 id 101 index 3 nhid 1"
2157         log_test $? 0 "Dump all nexthop buckets in a group"
2158 
2159         sleep 0.1
2160         (( $($IP -j nexthop bucket list id 101 |
2161              jq '[.[] | select(.bucket.idle_time > 0 and
2162                                .bucket.idle_time < 2)] | length') == 4 ))
2163         log_test $? 0 "All nexthop buckets report a positive near-zero idle time"
2164 
2165         check_nexthop_bucket "list dev veth1" \
2166                 "id 101 index 2 nhid 1 id 101 index 3 nhid 1"
2167         log_test $? 0 "Dump all nexthop buckets with a specific nexthop device"
2168 
2169         check_nexthop_bucket "list nhid 2" \
2170                 "id 101 index 0 nhid 2 id 101 index 1 nhid 2"
2171         log_test $? 0 "Dump all nexthop buckets with a specific nexthop identifier"
2172 
2173         run_cmd "$IP nexthop bucket list id 111"
2174         log_test $? 2 "Dump all nexthop buckets in a non-existent group"
2175 
2176         run_cmd "$IP nexthop bucket list id 201"
2177         log_test $? 2 "Dump all nexthop buckets in a non-resilient group"
2178 
2179         run_cmd "$IP nexthop bucket list dev bla"
2180         log_test $? 255 "Dump all nexthop buckets using a non-existent device"
2181 
2182         run_cmd "$IP nexthop bucket list groups"
2183         log_test $? 255 "Dump all nexthop buckets with invalid 'groups' keyword"
2184 
2185         run_cmd "$IP nexthop bucket list fdb"
2186         log_test $? 255 "Dump all nexthop buckets with invalid 'fdb' keyword"
2187 
2188         #
2189         # resilient nexthop buckets get requests
2190         #
2191 
2192         check_nexthop_bucket "get id 101 index 0" "id 101 index 0 nhid 2"
2193         log_test $? 0 "Get a valid nexthop bucket"
2194 
2195         run_cmd "$IP nexthop bucket get id 101 index 999"
2196         log_test $? 2 "Get a nexthop bucket with valid group, but invalid index"
2197 
2198         run_cmd "$IP nexthop bucket get id 201 index 0"
2199         log_test $? 2 "Get a nexthop bucket from a non-resilient group"
2200 
2201         run_cmd "$IP nexthop bucket get id 999 index 0"
2202         log_test $? 2 "Get a nexthop bucket from a non-existent group"
2203 
2204         #
2205         # tests for bucket migration
2206         #
2207 
2208         $IP nexthop flush >/dev/null 2>&1
2209 
2210         run_cmd "$IP nexthop add id 1 dev veth1"
2211         run_cmd "$IP nexthop add id 2 dev veth3"
2212         run_cmd "$IP nexthop add id 101
2213                         group 1/2 type resilient buckets 10
2214                         idle_timer 1 unbalanced_timer 20"
2215 
2216         check_nexthop_buckets_balance "list id 101" \
2217                                       "nhid 1" "== 5" \
2218                                       "nhid 2" "== 5"
2219         log_test $? 0 "Initial bucket allocation"
2220 
2221         run_cmd "$IP nexthop replace id 101
2222                         group 1,2/2,3 type resilient"
2223         check_nexthop_buckets_balance "list id 101" \
2224                                       "nhid 1" "== 4" \
2225                                       "nhid 2" "== 6"
2226         log_test $? 0 "Bucket allocation after replace"
2227 
2228         # Check that increase in idle timer does not make buckets appear busy.
2229         run_cmd "$IP nexthop replace id 101
2230                         group 1,2/2,3 type resilient
2231                         idle_timer 10"
2232         run_cmd "$IP nexthop replace id 101
2233                         group 1/2 type resilient"
2234         check_nexthop_buckets_balance "list id 101" \
2235                                       "nhid 1" "== 5" \
2236                                       "nhid 2" "== 5"
2237         log_test $? 0 "Buckets migrated after idle timer change"
2238 
2239         $IP nexthop flush >/dev/null 2>&1
2240 }
2241 
2242 ################################################################################
2243 # usage
2244 
2245 usage()
2246 {
2247         cat <<EOF
2248 usage: ${0##*/} OPTS
2249 
2250         -t <test>   Test(s) to run (default: all)
2251                     (options: $ALL_TESTS)
2252         -4          IPv4 tests only
2253         -6          IPv6 tests only
2254         -p          Pause on fail
2255         -P          Pause after each test before cleanup
2256         -v          verbose mode (show commands and output)
2257         -w          Timeout for ping
2258 
2259     Runtime test
2260         -n num      Number of nexthops to target
2261         -N          Use new style to install routes in DUT
2262 
2263 done
2264 EOF
2265 }
2266 
2267 ################################################################################
2268 # main
2269 
2270 while getopts :t:pP46hv:w: o
2271 do
2272         case $o in
2273                 t) TESTS=$OPTARG;;
2274                 4) TESTS=${IPV4_TESTS};;
2275                 6) TESTS=${IPV6_TESTS};;
2276                 p) PAUSE_ON_FAIL=yes;;
2277                 P) PAUSE=yes;;
2278                 v) VERBOSE=$(($VERBOSE + 1));;
2279                 w) PING_TIMEOUT=$OPTARG;;
2280                 h) usage; exit 0;;
2281                 *) usage; exit 1;;
2282         esac
2283 done
2284 
2285 # make sure we don't pause twice
2286 [ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
2287 
2288 if [ "$(id -u)" -ne 0 ];then
2289         echo "SKIP: Need root privileges"
2290         exit $ksft_skip;
2291 fi
2292 
2293 if [ ! -x "$(command -v ip)" ]; then
2294         echo "SKIP: Could not run test without ip tool"
2295         exit $ksft_skip
2296 fi
2297 
2298 ip help 2>&1 | grep -q nexthop
2299 if [ $? -ne 0 ]; then
2300         echo "SKIP: iproute2 too old, missing nexthop command"
2301         exit $ksft_skip
2302 fi
2303 
2304 out=$(ip nexthop ls 2>&1 | grep -q "Operation not supported")
2305 if [ $? -eq 0 ]; then
2306         echo "SKIP: kernel lacks nexthop support"
2307         exit $ksft_skip
2308 fi
2309 
2310 for t in $TESTS
2311 do
2312         case $t in
2313         none) IP="ip -netns peer"; setup; exit 0;;
2314         *) setup; $t; cleanup;;
2315         esac
2316 done
2317 
2318 if [ "$TESTS" != "none" ]; then
2319         printf "\nTests passed: %3d\n" ${nsuccess}
2320         printf "Tests failed: %3d\n"   ${nfail}
2321 fi
2322 
2323 exit $ret