cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fib_nexthops.sh (69622B)


      1#!/bin/bash
      2# SPDX-License-Identifier: GPL-2.0
      3#
      4# ns: me               | ns: peer              | ns: remote
      5#   2001:db8:91::1     |       2001:db8:91::2  |
      6#   172.16.1.1         |       172.16.1.2      |
      7#            veth1 <---|---> veth2             |
      8#                      |              veth5 <--|--> veth6  172.16.101.1
      9#            veth3 <---|---> veth4             |           2001:db8:101::1
     10#   172.16.2.1         |       172.16.2.2      |
     11#   2001:db8:92::1     |       2001:db8:92::2  |
     12#
     13# This test is for checking IPv4 and IPv6 FIB behavior with nexthop
     14# objects. Device reference counts and network namespace cleanup tested
     15# by use of network namespace for peer.
     16
     17ret=0
     18# Kselftest framework requirement - SKIP code is 4.
     19ksft_skip=4
     20
     21# all tests in this script. Can be overridden with -t option
     22IPV4_TESTS="
     23	ipv4_fcnal
     24	ipv4_grp_fcnal
     25	ipv4_res_grp_fcnal
     26	ipv4_withv6_fcnal
     27	ipv4_fcnal_runtime
     28	ipv4_large_grp
     29	ipv4_large_res_grp
     30	ipv4_compat_mode
     31	ipv4_fdb_grp_fcnal
     32	ipv4_torture
     33	ipv4_res_torture
     34"
     35
     36IPV6_TESTS="
     37	ipv6_fcnal
     38	ipv6_grp_fcnal
     39	ipv6_res_grp_fcnal
     40	ipv6_fcnal_runtime
     41	ipv6_large_grp
     42	ipv6_large_res_grp
     43	ipv6_compat_mode
     44	ipv6_fdb_grp_fcnal
     45	ipv6_torture
     46	ipv6_res_torture
     47"
     48
     49ALL_TESTS="
     50	basic
     51	basic_res
     52	${IPV4_TESTS}
     53	${IPV6_TESTS}
     54"
     55TESTS="${ALL_TESTS}"
     56VERBOSE=0
     57PAUSE_ON_FAIL=no
     58PAUSE=no
     59PING_TIMEOUT=5
     60
     61nsid=100
     62
     63################################################################################
     64# utilities
     65
     66log_test()
     67{
     68	local rc=$1
     69	local expected=$2
     70	local msg="$3"
     71
     72	if [ ${rc} -eq ${expected} ]; then
     73		printf "TEST: %-60s  [ OK ]\n" "${msg}"
     74		nsuccess=$((nsuccess+1))
     75	else
     76		ret=1
     77		nfail=$((nfail+1))
     78		printf "TEST: %-60s  [FAIL]\n" "${msg}"
     79		if [ "$VERBOSE" = "1" ]; then
     80			echo "    rc=$rc, expected $expected"
     81		fi
     82
     83		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
     84		echo
     85			echo "hit enter to continue, 'q' to quit"
     86			read a
     87			[ "$a" = "q" ] && exit 1
     88		fi
     89	fi
     90
     91	if [ "${PAUSE}" = "yes" ]; then
     92		echo
     93		echo "hit enter to continue, 'q' to quit"
     94		read a
     95		[ "$a" = "q" ] && exit 1
     96	fi
     97
     98	[ "$VERBOSE" = "1" ] && echo
     99}
    100
    101run_cmd()
    102{
    103	local cmd="$1"
    104	local out
    105	local stderr="2>/dev/null"
    106
    107	if [ "$VERBOSE" = "1" ]; then
    108		printf "COMMAND: $cmd\n"
    109		stderr=
    110	fi
    111
    112	out=$(eval $cmd $stderr)
    113	rc=$?
    114	if [ "$VERBOSE" = "1" -a -n "$out" ]; then
    115		echo "    $out"
    116	fi
    117
    118	return $rc
    119}
    120
    121get_linklocal()
    122{
    123	local dev=$1
    124	local ns
    125	local addr
    126
    127	[ -n "$2" ] && ns="-netns $2"
    128	addr=$(ip $ns -6 -br addr show dev ${dev} | \
    129	awk '{
    130		for (i = 3; i <= NF; ++i) {
    131			if ($i ~ /^fe80/)
    132				print $i
    133		}
    134	}'
    135	)
    136	addr=${addr/\/*}
    137
    138	[ -z "$addr" ] && return 1
    139
    140	echo $addr
    141
    142	return 0
    143}
    144
    145create_ns()
    146{
    147	local n=${1}
    148
    149	ip netns del ${n} 2>/dev/null
    150
    151	set -e
    152	ip netns add ${n}
    153	ip netns set ${n} $((nsid++))
    154	ip -netns ${n} addr add 127.0.0.1/8 dev lo
    155	ip -netns ${n} link set lo up
    156
    157	ip netns exec ${n} sysctl -qw net.ipv4.ip_forward=1
    158	ip netns exec ${n} sysctl -qw net.ipv4.fib_multipath_use_neigh=1
    159	ip netns exec ${n} sysctl -qw net.ipv4.conf.default.ignore_routes_with_linkdown=1
    160	ip netns exec ${n} sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1
    161	ip netns exec ${n} sysctl -qw net.ipv6.conf.all.forwarding=1
    162	ip netns exec ${n} sysctl -qw net.ipv6.conf.default.forwarding=1
    163	ip netns exec ${n} sysctl -qw net.ipv6.conf.default.ignore_routes_with_linkdown=1
    164	ip netns exec ${n} sysctl -qw net.ipv6.conf.all.accept_dad=0
    165	ip netns exec ${n} sysctl -qw net.ipv6.conf.default.accept_dad=0
    166
    167	set +e
    168}
    169
    170setup()
    171{
    172	cleanup
    173
    174	create_ns me
    175	create_ns peer
    176	create_ns remote
    177
    178	IP="ip -netns me"
    179	BRIDGE="bridge -netns me"
    180	set -e
    181	$IP li add veth1 type veth peer name veth2
    182	$IP li set veth1 up
    183	$IP addr add 172.16.1.1/24 dev veth1
    184	$IP -6 addr add 2001:db8:91::1/64 dev veth1 nodad
    185
    186	$IP li add veth3 type veth peer name veth4
    187	$IP li set veth3 up
    188	$IP addr add 172.16.2.1/24 dev veth3
    189	$IP -6 addr add 2001:db8:92::1/64 dev veth3 nodad
    190
    191	$IP li set veth2 netns peer up
    192	ip -netns peer addr add 172.16.1.2/24 dev veth2
    193	ip -netns peer -6 addr add 2001:db8:91::2/64 dev veth2 nodad
    194
    195	$IP li set veth4 netns peer up
    196	ip -netns peer addr add 172.16.2.2/24 dev veth4
    197	ip -netns peer -6 addr add 2001:db8:92::2/64 dev veth4 nodad
    198
    199	ip -netns remote li add veth5 type veth peer name veth6
    200	ip -netns remote li set veth5 up
    201	ip -netns remote addr add dev veth5 172.16.101.1/24
    202	ip -netns remote -6 addr add dev veth5 2001:db8:101::1/64 nodad
    203	ip -netns remote ro add 172.16.0.0/22 via 172.16.101.2
    204	ip -netns remote -6 ro add 2001:db8:90::/40 via 2001:db8:101::2
    205
    206	ip -netns remote li set veth6 netns peer up
    207	ip -netns peer addr add dev veth6 172.16.101.2/24
    208	ip -netns peer -6 addr add dev veth6 2001:db8:101::2/64 nodad
    209	set +e
    210}
    211
    212cleanup()
    213{
    214	local ns
    215
    216	for ns in me peer remote; do
    217		ip netns del ${ns} 2>/dev/null
    218	done
    219}
    220
    221check_output()
    222{
    223	local out="$1"
    224	local expected="$2"
    225	local rc=0
    226
    227	[ "${out}" = "${expected}" ] && return 0
    228
    229	if [ -z "${out}" ]; then
    230		if [ "$VERBOSE" = "1" ]; then
    231			printf "\nNo entry found\n"
    232			printf "Expected:\n"
    233			printf "    ${expected}\n"
    234		fi
    235		return 1
    236	fi
    237
    238	out=$(echo ${out})
    239	if [ "${out}" != "${expected}" ]; then
    240		rc=1
    241		if [ "${VERBOSE}" = "1" ]; then
    242			printf "    Unexpected entry. Have:\n"
    243			printf "        ${out}\n"
    244			printf "    Expected:\n"
    245			printf "        ${expected}\n\n"
    246		else
    247			echo "      WARNING: Unexpected route entry"
    248		fi
    249	fi
    250
    251	return $rc
    252}
    253
    254check_nexthop()
    255{
    256	local nharg="$1"
    257	local expected="$2"
    258	local out
    259
    260	out=$($IP nexthop ls ${nharg} 2>/dev/null)
    261
    262	check_output "${out}" "${expected}"
    263}
    264
    265check_nexthop_bucket()
    266{
    267	local nharg="$1"
    268	local expected="$2"
    269	local out
    270
    271	# remove the idle time since we cannot match it
    272	out=$($IP nexthop bucket ${nharg} \
    273		| sed s/idle_time\ [0-9.]*\ // 2>/dev/null)
    274
    275	check_output "${out}" "${expected}"
    276}
    277
    278check_route()
    279{
    280	local pfx="$1"
    281	local expected="$2"
    282	local out
    283
    284	out=$($IP route ls match ${pfx} 2>/dev/null)
    285
    286	check_output "${out}" "${expected}"
    287}
    288
    289check_route6()
    290{
    291	local pfx="$1"
    292	local expected="$2"
    293	local out
    294
    295	out=$($IP -6 route ls match ${pfx} 2>/dev/null | sed -e 's/pref medium//')
    296
    297	check_output "${out}" "${expected}"
    298}
    299
    300check_large_grp()
    301{
    302	local ipv=$1
    303	local ecmp=$2
    304	local grpnum=100
    305	local nhidstart=100
    306	local grpidstart=1000
    307	local iter=0
    308	local nhidstr=""
    309	local grpidstr=""
    310	local grpstr=""
    311	local ipstr=""
    312
    313	if [ $ipv -eq 4 ]; then
    314		ipstr="172.16.1."
    315	else
    316		ipstr="2001:db8:91::"
    317	fi
    318
    319	#
    320	# Create $grpnum groups with specified $ecmp and dump them
    321	#
    322
    323	# create nexthops with different gateways
    324	iter=2
    325	while [ $iter -le $(($ecmp + 1)) ]
    326	do
    327		nhidstr="$(($nhidstart + $iter))"
    328		run_cmd "$IP nexthop add id $nhidstr via $ipstr$iter dev veth1"
    329		check_nexthop "id $nhidstr" "id $nhidstr via $ipstr$iter dev veth1 scope link"
    330
    331		if [ $iter -le $ecmp ]; then
    332			grpstr+="$nhidstr/"
    333		else
    334			grpstr+="$nhidstr"
    335		fi
    336		((iter++))
    337	done
    338
    339	# create duplicate large ecmp groups
    340	iter=0
    341	while [ $iter -le $grpnum ]
    342	do
    343		grpidstr="$(($grpidstart + $iter))"
    344		run_cmd "$IP nexthop add id $grpidstr group $grpstr"
    345		check_nexthop "id $grpidstr" "id $grpidstr group $grpstr"
    346		((iter++))
    347	done
    348
    349	# dump large groups
    350	run_cmd "$IP nexthop list"
    351	log_test $? 0 "Dump large (x$ecmp) ecmp groups"
    352}
    353
    354check_large_res_grp()
    355{
    356	local ipv=$1
    357	local buckets=$2
    358	local ipstr=""
    359
    360	if [ $ipv -eq 4 ]; then
    361		ipstr="172.16.1.2"
    362	else
    363		ipstr="2001:db8:91::2"
    364	fi
    365
    366	# create a resilient group with $buckets buckets and dump them
    367	run_cmd "$IP nexthop add id 100 via $ipstr dev veth1"
    368	run_cmd "$IP nexthop add id 1000 group 100 type resilient buckets $buckets"
    369	run_cmd "$IP nexthop bucket list"
    370	log_test $? 0 "Dump large (x$buckets) nexthop buckets"
    371}
    372
    373start_ip_monitor()
    374{
    375	local mtype=$1
    376
    377	# start the monitor in the background
    378	tmpfile=`mktemp /var/run/nexthoptestXXX`
    379	mpid=`($IP monitor $mtype > $tmpfile & echo $!) 2>/dev/null`
    380	sleep 0.2
    381	echo "$mpid $tmpfile"
    382}
    383
    384stop_ip_monitor()
    385{
    386	local mpid=$1
    387	local tmpfile=$2
    388	local el=$3
    389
    390	# check the monitor results
    391	kill $mpid
    392	lines=`wc -l $tmpfile | cut "-d " -f1`
    393	test $lines -eq $el
    394	rc=$?
    395	rm -rf $tmpfile
    396
    397	return $rc
    398}
    399
    400check_nexthop_fdb_support()
    401{
    402	$IP nexthop help 2>&1 | grep -q fdb
    403	if [ $? -ne 0 ]; then
    404		echo "SKIP: iproute2 too old, missing fdb nexthop support"
    405		return $ksft_skip
    406	fi
    407}
    408
    409check_nexthop_res_support()
    410{
    411	$IP nexthop help 2>&1 | grep -q resilient
    412	if [ $? -ne 0 ]; then
    413		echo "SKIP: iproute2 too old, missing resilient nexthop group support"
    414		return $ksft_skip
    415	fi
    416}
    417
    418ipv6_fdb_grp_fcnal()
    419{
    420	local rc
    421
    422	echo
    423	echo "IPv6 fdb groups functional"
    424	echo "--------------------------"
    425
    426	check_nexthop_fdb_support
    427	if [ $? -eq $ksft_skip ]; then
    428		return $ksft_skip
    429	fi
    430
    431	# create group with multiple nexthops
    432	run_cmd "$IP nexthop add id 61 via 2001:db8:91::2 fdb"
    433	run_cmd "$IP nexthop add id 62 via 2001:db8:91::3 fdb"
    434	run_cmd "$IP nexthop add id 102 group 61/62 fdb"
    435	check_nexthop "id 102" "id 102 group 61/62 fdb"
    436	log_test $? 0 "Fdb Nexthop group with multiple nexthops"
    437
    438	## get nexthop group
    439	run_cmd "$IP nexthop get id 102"
    440	check_nexthop "id 102" "id 102 group 61/62 fdb"
    441	log_test $? 0 "Get Fdb nexthop group by id"
    442
    443	# fdb nexthop group can only contain fdb nexthops
    444	run_cmd "$IP nexthop add id 63 via 2001:db8:91::4"
    445	run_cmd "$IP nexthop add id 64 via 2001:db8:91::5"
    446	run_cmd "$IP nexthop add id 103 group 63/64 fdb"
    447	log_test $? 2 "Fdb Nexthop group with non-fdb nexthops"
    448
    449	# Non fdb nexthop group can not contain fdb nexthops
    450	run_cmd "$IP nexthop add id 65 via 2001:db8:91::5 fdb"
    451	run_cmd "$IP nexthop add id 66 via 2001:db8:91::6 fdb"
    452	run_cmd "$IP nexthop add id 104 group 65/66"
    453	log_test $? 2 "Non-Fdb Nexthop group with fdb nexthops"
    454
    455	# fdb nexthop cannot have blackhole
    456	run_cmd "$IP nexthop add id 67 blackhole fdb"
    457	log_test $? 2 "Fdb Nexthop with blackhole"
    458
    459	# fdb nexthop with oif
    460	run_cmd "$IP nexthop add id 68 via 2001:db8:91::7 dev veth1 fdb"
    461	log_test $? 2 "Fdb Nexthop with oif"
    462
    463	# fdb nexthop with onlink
    464	run_cmd "$IP nexthop add id 68 via 2001:db8:91::7 onlink fdb"
    465	log_test $? 2 "Fdb Nexthop with onlink"
    466
    467	# fdb nexthop with encap
    468	run_cmd "$IP nexthop add id 69 encap mpls 101 via 2001:db8:91::8 dev veth1 fdb"
    469	log_test $? 2 "Fdb Nexthop with encap"
    470
    471	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"
    472	run_cmd "$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self"
    473	log_test $? 0 "Fdb mac add with nexthop group"
    474
    475	## fdb nexthops can only reference nexthop groups and not nexthops
    476	run_cmd "$BRIDGE fdb add 02:02:00:00:00:14 dev vx10 nhid 61 self"
    477	log_test $? 255 "Fdb mac add with nexthop"
    478
    479	run_cmd "$IP -6 ro add 2001:db8:101::1/128 nhid 66"
    480	log_test $? 2 "Route add with fdb nexthop"
    481
    482	run_cmd "$IP -6 ro add 2001:db8:101::1/128 nhid 103"
    483	log_test $? 2 "Route add with fdb nexthop group"
    484
    485	run_cmd "$IP nexthop del id 61"
    486	run_cmd "$BRIDGE fdb get to 02:02:00:00:00:13 dev vx10 self"
    487	log_test $? 0 "Fdb entry after deleting a single nexthop"
    488
    489	run_cmd "$IP nexthop del id 102"
    490	log_test $? 0 "Fdb nexthop delete"
    491
    492	run_cmd "$BRIDGE fdb get to 02:02:00:00:00:13 dev vx10 self"
    493	log_test $? 254 "Fdb entry after deleting a nexthop group"
    494
    495	$IP link del dev vx10
    496}
    497
    498ipv4_fdb_grp_fcnal()
    499{
    500	local rc
    501
    502	echo
    503	echo "IPv4 fdb groups functional"
    504	echo "--------------------------"
    505
    506	check_nexthop_fdb_support
    507	if [ $? -eq $ksft_skip ]; then
    508		return $ksft_skip
    509	fi
    510
    511	# create group with multiple nexthops
    512	run_cmd "$IP nexthop add id 12 via 172.16.1.2 fdb"
    513	run_cmd "$IP nexthop add id 13 via 172.16.1.3 fdb"
    514	run_cmd "$IP nexthop add id 102 group 12/13 fdb"
    515	check_nexthop "id 102" "id 102 group 12/13 fdb"
    516	log_test $? 0 "Fdb Nexthop group with multiple nexthops"
    517
    518	# get nexthop group
    519	run_cmd "$IP nexthop get id 102"
    520	check_nexthop "id 102" "id 102 group 12/13 fdb"
    521	log_test $? 0 "Get Fdb nexthop group by id"
    522
    523	# fdb nexthop group can only contain fdb nexthops
    524	run_cmd "$IP nexthop add id 14 via 172.16.1.2"
    525	run_cmd "$IP nexthop add id 15 via 172.16.1.3"
    526	run_cmd "$IP nexthop add id 103 group 14/15 fdb"
    527	log_test $? 2 "Fdb Nexthop group with non-fdb nexthops"
    528
    529	# Non fdb nexthop group can not contain fdb nexthops
    530	run_cmd "$IP nexthop add id 16 via 172.16.1.2 fdb"
    531	run_cmd "$IP nexthop add id 17 via 172.16.1.3 fdb"
    532	run_cmd "$IP nexthop add id 104 group 14/15"
    533	log_test $? 2 "Non-Fdb Nexthop group with fdb nexthops"
    534
    535	# fdb nexthop cannot have blackhole
    536	run_cmd "$IP nexthop add id 18 blackhole fdb"
    537	log_test $? 2 "Fdb Nexthop with blackhole"
    538
    539	# fdb nexthop with oif
    540	run_cmd "$IP nexthop add id 16 via 172.16.1.2 dev veth1 fdb"
    541	log_test $? 2 "Fdb Nexthop with oif"
    542
    543	# fdb nexthop with onlink
    544	run_cmd "$IP nexthop add id 16 via 172.16.1.2 onlink fdb"
    545	log_test $? 2 "Fdb Nexthop with onlink"
    546
    547	# fdb nexthop with encap
    548	run_cmd "$IP nexthop add id 17 encap mpls 101 via 172.16.1.2 dev veth1 fdb"
    549	log_test $? 2 "Fdb Nexthop with encap"
    550
    551	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"
    552	run_cmd "$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self"
    553	log_test $? 0 "Fdb mac add with nexthop group"
    554
    555	# fdb nexthops can only reference nexthop groups and not nexthops
    556	run_cmd "$BRIDGE fdb add 02:02:00:00:00:14 dev vx10 nhid 12 self"
    557	log_test $? 255 "Fdb mac add with nexthop"
    558
    559	run_cmd "$IP ro add 172.16.0.0/22 nhid 15"
    560	log_test $? 2 "Route add with fdb nexthop"
    561
    562	run_cmd "$IP ro add 172.16.0.0/22 nhid 103"
    563	log_test $? 2 "Route add with fdb nexthop group"
    564
    565	run_cmd "$IP nexthop del id 12"
    566	run_cmd "$BRIDGE fdb get to 02:02:00:00:00:13 dev vx10 self"
    567	log_test $? 0 "Fdb entry after deleting a single nexthop"
    568
    569	run_cmd "$IP nexthop del id 102"
    570	log_test $? 0 "Fdb nexthop delete"
    571
    572	run_cmd "$BRIDGE fdb get to 02:02:00:00:00:13 dev vx10 self"
    573	log_test $? 254 "Fdb entry after deleting a nexthop group"
    574
    575	$IP link del dev vx10
    576}
    577
    578################################################################################
    579# basic operations (add, delete, replace) on nexthops and nexthop groups
    580#
    581# IPv6
    582
    583ipv6_fcnal()
    584{
    585	local rc
    586
    587	echo
    588	echo "IPv6"
    589	echo "----------------------"
    590
    591	run_cmd "$IP nexthop add id 52 via 2001:db8:91::2 dev veth1"
    592	rc=$?
    593	log_test $rc 0 "Create nexthop with id, gw, dev"
    594	if [ $rc -ne 0 ]; then
    595		echo "Basic IPv6 create fails; can not continue"
    596		return 1
    597	fi
    598
    599	run_cmd "$IP nexthop get id 52"
    600	log_test $? 0 "Get nexthop by id"
    601	check_nexthop "id 52" "id 52 via 2001:db8:91::2 dev veth1 scope link"
    602
    603	run_cmd "$IP nexthop del id 52"
    604	log_test $? 0 "Delete nexthop by id"
    605	check_nexthop "id 52" ""
    606
    607	#
    608	# gw, device spec
    609	#
    610	# gw validation, no device - fails since dev required
    611	run_cmd "$IP nexthop add id 52 via 2001:db8:92::3"
    612	log_test $? 2 "Create nexthop - gw only"
    613
    614	# gw is not reachable throught given dev
    615	run_cmd "$IP nexthop add id 53 via 2001:db8:3::3 dev veth1"
    616	log_test $? 2 "Create nexthop - invalid gw+dev combination"
    617
    618	# onlink arg overrides gw+dev lookup
    619	run_cmd "$IP nexthop add id 53 via 2001:db8:3::3 dev veth1 onlink"
    620	log_test $? 0 "Create nexthop - gw+dev and onlink"
    621
    622	# admin down should delete nexthops
    623	set -e
    624	run_cmd "$IP -6 nexthop add id 55 via 2001:db8:91::3 dev veth1"
    625	run_cmd "$IP nexthop add id 56 via 2001:db8:91::4 dev veth1"
    626	run_cmd "$IP nexthop add id 57 via 2001:db8:91::5 dev veth1"
    627	run_cmd "$IP li set dev veth1 down"
    628	set +e
    629	check_nexthop "dev veth1" ""
    630	log_test $? 0 "Nexthops removed on admin down"
    631}
    632
    633ipv6_grp_refs()
    634{
    635	if [ ! -x "$(command -v mausezahn)" ]; then
    636		echo "SKIP: Could not run test; need mausezahn tool"
    637		return
    638	fi
    639
    640	run_cmd "$IP link set dev veth1 up"
    641	run_cmd "$IP link add veth1.10 link veth1 up type vlan id 10"
    642	run_cmd "$IP link add veth1.20 link veth1 up type vlan id 20"
    643	run_cmd "$IP -6 addr add 2001:db8:91::1/64 dev veth1.10"
    644	run_cmd "$IP -6 addr add 2001:db8:92::1/64 dev veth1.20"
    645	run_cmd "$IP -6 neigh add 2001:db8:91::2 lladdr 00:11:22:33:44:55 dev veth1.10"
    646	run_cmd "$IP -6 neigh add 2001:db8:92::2 lladdr 00:11:22:33:44:55 dev veth1.20"
    647	run_cmd "$IP nexthop add id 100 via 2001:db8:91::2 dev veth1.10"
    648	run_cmd "$IP nexthop add id 101 via 2001:db8:92::2 dev veth1.20"
    649	run_cmd "$IP nexthop add id 102 group 100"
    650	run_cmd "$IP route add 2001:db8:101::1/128 nhid 102"
    651
    652	# create per-cpu dsts through nh 100
    653	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"
    654
    655	# remove nh 100 from the group to delete the route potentially leaving
    656	# a stale per-cpu dst which holds a reference to the nexthop's net
    657	# device and to the IPv6 route
    658	run_cmd "$IP nexthop replace id 102 group 101"
    659	run_cmd "$IP route del 2001:db8:101::1/128"
    660
    661	# add both nexthops to the group so a reference is taken on them
    662	run_cmd "$IP nexthop replace id 102 group 100/101"
    663
    664	# if the bug described in commit "net: nexthop: release IPv6 per-cpu
    665	# dsts when replacing a nexthop group" exists at this point we have
    666	# an unlinked IPv6 route (but not freed due to stale dst) with a
    667	# reference over the group so we delete the group which will again
    668	# only unlink it due to the route reference
    669	run_cmd "$IP nexthop del id 102"
    670
    671	# delete the nexthop with stale dst, since we have an unlinked
    672	# group with a ref to it and an unlinked IPv6 route with ref to the
    673	# group, the nh will only be unlinked and not freed so the stale dst
    674	# remains forever and we get a net device refcount imbalance
    675	run_cmd "$IP nexthop del id 100"
    676
    677	# if a reference was lost this command will hang because the net device
    678	# cannot be removed
    679	timeout -s KILL 5 ip netns exec me ip link del veth1.10 >/dev/null 2>&1
    680
    681	# we can't cleanup if the command is hung trying to delete the netdev
    682	if [ $? -eq 137 ]; then
    683		return 1
    684	fi
    685
    686	# cleanup
    687	run_cmd "$IP link del veth1.20"
    688	run_cmd "$IP nexthop flush"
    689
    690	return 0
    691}
    692
    693ipv6_grp_fcnal()
    694{
    695	local rc
    696
    697	echo
    698	echo "IPv6 groups functional"
    699	echo "----------------------"
    700
    701	# basic functionality: create a nexthop group, default weight
    702	run_cmd "$IP nexthop add id 61 via 2001:db8:91::2 dev veth1"
    703	run_cmd "$IP nexthop add id 101 group 61"
    704	log_test $? 0 "Create nexthop group with single nexthop"
    705
    706	# get nexthop group
    707	run_cmd "$IP nexthop get id 101"
    708	log_test $? 0 "Get nexthop group by id"
    709	check_nexthop "id 101" "id 101 group 61"
    710
    711	# delete nexthop group
    712	run_cmd "$IP nexthop del id 101"
    713	log_test $? 0 "Delete nexthop group by id"
    714	check_nexthop "id 101" ""
    715
    716	$IP nexthop flush >/dev/null 2>&1
    717	check_nexthop "id 101" ""
    718
    719	#
    720	# create group with multiple nexthops - mix of gw and dev only
    721	#
    722	run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
    723	run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
    724	run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
    725	run_cmd "$IP nexthop add id 65 dev veth1"
    726	run_cmd "$IP nexthop add id 102 group 62/63/64/65"
    727	log_test $? 0 "Nexthop group with multiple nexthops"
    728	check_nexthop "id 102" "id 102 group 62/63/64/65"
    729
    730	# Delete nexthop in a group and group is updated
    731	run_cmd "$IP nexthop del id 63"
    732	check_nexthop "id 102" "id 102 group 62/64/65"
    733	log_test $? 0 "Nexthop group updated when entry is deleted"
    734
    735	# create group with multiple weighted nexthops
    736	run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
    737	run_cmd "$IP nexthop add id 103 group 62/63,2/64,3/65,4"
    738	log_test $? 0 "Nexthop group with weighted nexthops"
    739	check_nexthop "id 103" "id 103 group 62/63,2/64,3/65,4"
    740
    741	# Delete nexthop in a weighted group and group is updated
    742	run_cmd "$IP nexthop del id 63"
    743	check_nexthop "id 103" "id 103 group 62/64,3/65,4"
    744	log_test $? 0 "Weighted nexthop group updated when entry is deleted"
    745
    746	# admin down - nexthop is removed from group
    747	run_cmd "$IP li set dev veth1 down"
    748	check_nexthop "dev veth1" ""
    749	log_test $? 0 "Nexthops in groups removed on admin down"
    750
    751	# expect groups to have been deleted as well
    752	check_nexthop "" ""
    753
    754	run_cmd "$IP li set dev veth1 up"
    755
    756	$IP nexthop flush >/dev/null 2>&1
    757
    758	# group with nexthops using different devices
    759	set -e
    760	run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
    761	run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
    762	run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
    763	run_cmd "$IP nexthop add id 65 via 2001:db8:91::5 dev veth1"
    764
    765	run_cmd "$IP nexthop add id 72 via 2001:db8:92::2 dev veth3"
    766	run_cmd "$IP nexthop add id 73 via 2001:db8:92::3 dev veth3"
    767	run_cmd "$IP nexthop add id 74 via 2001:db8:92::4 dev veth3"
    768	run_cmd "$IP nexthop add id 75 via 2001:db8:92::5 dev veth3"
    769	set +e
    770
    771	# multiple groups with same nexthop
    772	run_cmd "$IP nexthop add id 104 group 62"
    773	run_cmd "$IP nexthop add id 105 group 62"
    774	check_nexthop "group" "id 104 group 62 id 105 group 62"
    775	log_test $? 0 "Multiple groups with same nexthop"
    776
    777	run_cmd "$IP nexthop flush groups"
    778	[ $? -ne 0 ] && return 1
    779
    780	# on admin down of veth1, it should be removed from the group
    781	run_cmd "$IP nexthop add id 105 group 62/63/72/73/64"
    782	run_cmd "$IP li set veth1 down"
    783	check_nexthop "id 105" "id 105 group 72/73"
    784	log_test $? 0 "Nexthops in group removed on admin down - mixed group"
    785
    786	run_cmd "$IP nexthop add id 106 group 105/74"
    787	log_test $? 2 "Nexthop group can not have a group as an entry"
    788
    789	# a group can have a blackhole entry only if it is the only
    790	# nexthop in the group. Needed for atomic replace with an
    791	# actual nexthop group
    792	run_cmd "$IP -6 nexthop add id 31 blackhole"
    793	run_cmd "$IP nexthop add id 107 group 31"
    794	log_test $? 0 "Nexthop group with a blackhole entry"
    795
    796	run_cmd "$IP nexthop add id 108 group 31/24"
    797	log_test $? 2 "Nexthop group can not have a blackhole and another nexthop"
    798
    799	ipv6_grp_refs
    800	log_test $? 0 "Nexthop group replace refcounts"
    801}
    802
    803ipv6_res_grp_fcnal()
    804{
    805	local rc
    806
    807	echo
    808	echo "IPv6 resilient groups functional"
    809	echo "--------------------------------"
    810
    811	check_nexthop_res_support
    812	if [ $? -eq $ksft_skip ]; then
    813		return $ksft_skip
    814	fi
    815
    816	#
    817	# migration of nexthop buckets - equal weights
    818	#
    819	run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
    820	run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
    821	run_cmd "$IP nexthop add id 102 group 62/63 type resilient buckets 2 idle_timer 0"
    822
    823	run_cmd "$IP nexthop del id 63"
    824	check_nexthop "id 102" \
    825		"id 102 group 62 type resilient buckets 2 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
    826	log_test $? 0 "Nexthop group updated when entry is deleted"
    827	check_nexthop_bucket "list id 102" \
    828		"id 102 index 0 nhid 62 id 102 index 1 nhid 62"
    829	log_test $? 0 "Nexthop buckets updated when entry is deleted"
    830
    831	run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
    832	run_cmd "$IP nexthop replace id 102 group 62/63 type resilient buckets 2 idle_timer 0"
    833	check_nexthop "id 102" \
    834		"id 102 group 62/63 type resilient buckets 2 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
    835	log_test $? 0 "Nexthop group updated after replace"
    836	check_nexthop_bucket "list id 102" \
    837		"id 102 index 0 nhid 63 id 102 index 1 nhid 62"
    838	log_test $? 0 "Nexthop buckets updated after replace"
    839
    840	$IP nexthop flush >/dev/null 2>&1
    841
    842	#
    843	# migration of nexthop buckets - unequal weights
    844	#
    845	run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
    846	run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
    847	run_cmd "$IP nexthop add id 102 group 62,3/63,1 type resilient buckets 4 idle_timer 0"
    848
    849	run_cmd "$IP nexthop del id 63"
    850	check_nexthop "id 102" \
    851		"id 102 group 62,3 type resilient buckets 4 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
    852	log_test $? 0 "Nexthop group updated when entry is deleted - nECMP"
    853	check_nexthop_bucket "list id 102" \
    854		"id 102 index 0 nhid 62 id 102 index 1 nhid 62 id 102 index 2 nhid 62 id 102 index 3 nhid 62"
    855	log_test $? 0 "Nexthop buckets updated when entry is deleted - nECMP"
    856
    857	run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
    858	run_cmd "$IP nexthop replace id 102 group 62,3/63,1 type resilient buckets 4 idle_timer 0"
    859	check_nexthop "id 102" \
    860		"id 102 group 62,3/63 type resilient buckets 4 idle_timer 0 unbalanced_timer 0 unbalanced_time 0"
    861	log_test $? 0 "Nexthop group updated after replace - nECMP"
    862	check_nexthop_bucket "list id 102" \
    863		"id 102 index 0 nhid 63 id 102 index 1 nhid 62 id 102 index 2 nhid 62 id 102 index 3 nhid 62"
    864	log_test $? 0 "Nexthop buckets updated after replace - nECMP"
    865}
    866
    867ipv6_fcnal_runtime()
    868{
    869	local rc
    870
    871	echo
    872	echo "IPv6 functional runtime"
    873	echo "-----------------------"
    874
    875	#
    876	# IPv6 - the basics
    877	#
    878	run_cmd "$IP nexthop add id 81 via 2001:db8:91::2 dev veth1"
    879	run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
    880	log_test $? 0 "Route add"
    881
    882	run_cmd "$IP ro delete 2001:db8:101::1/128 nhid 81"
    883	log_test $? 0 "Route delete"
    884
    885	run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
    886	run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
    887	log_test $? 0 "Ping with nexthop"
    888
    889	run_cmd "$IP nexthop add id 82 via 2001:db8:92::2 dev veth3"
    890	run_cmd "$IP nexthop add id 122 group 81/82"
    891	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
    892	run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
    893	log_test $? 0 "Ping - multipath"
    894
    895	#
    896	# IPv6 with blackhole nexthops
    897	#
    898	run_cmd "$IP -6 nexthop add id 83 blackhole"
    899	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 83"
    900	run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
    901	log_test $? 2 "Ping - blackhole"
    902
    903	run_cmd "$IP nexthop replace id 83 via 2001:db8:91::2 dev veth1"
    904	run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
    905	log_test $? 0 "Ping - blackhole replaced with gateway"
    906
    907	run_cmd "$IP -6 nexthop replace id 83 blackhole"
    908	run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
    909	log_test $? 2 "Ping - gateway replaced by blackhole"
    910
    911	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
    912	run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
    913	if [ $? -eq 0 ]; then
    914		run_cmd "$IP nexthop replace id 122 group 83"
    915		run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
    916		log_test $? 2 "Ping - group with blackhole"
    917
    918		run_cmd "$IP nexthop replace id 122 group 81/82"
    919		run_cmd "ip netns exec me ping -c1 -w$PING_TIMEOUT 2001:db8:101::1"
    920		log_test $? 0 "Ping - group blackhole replaced with gateways"
    921	else
    922		log_test 2 0 "Ping - multipath failed"
    923	fi
    924
    925	#
    926	# device only and gw + dev only mix
    927	#
    928	run_cmd "$IP -6 nexthop add id 85 dev veth1"
    929	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 85"
    930	log_test $? 0 "IPv6 route with device only nexthop"
    931	check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 85 dev veth1 metric 1024"
    932
    933	run_cmd "$IP nexthop add id 123 group 81/85"
    934	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 123"
    935	log_test $? 0 "IPv6 multipath route with nexthop mix - dev only + gw"
    936	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"
    937
    938	#
    939	# IPv6 route with v4 nexthop - not allowed
    940	#
    941	run_cmd "$IP ro delete 2001:db8:101::1/128"
    942	run_cmd "$IP nexthop add id 84 via 172.16.1.1 dev veth1"
    943	run_cmd "$IP ro add 2001:db8:101::1/128 nhid 84"
    944	log_test $? 2 "IPv6 route can not have a v4 gateway"
    945
    946	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 81"
    947	run_cmd "$IP nexthop replace id 81 via 172.16.1.1 dev veth1"
    948	log_test $? 2 "Nexthop replace - v6 route, v4 nexthop"
    949
    950	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
    951	run_cmd "$IP nexthop replace id 81 via 172.16.1.1 dev veth1"
    952	log_test $? 2 "Nexthop replace of group entry - v6 route, v4 nexthop"
    953
    954	run_cmd "$IP nexthop add id 86 via 2001:db8:92::2 dev veth3"
    955	run_cmd "$IP nexthop add id 87 via 172.16.1.1 dev veth1"
    956	run_cmd "$IP nexthop add id 88 via 172.16.1.1 dev veth1"
    957	run_cmd "$IP nexthop add id 124 group 86/87/88"
    958	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
    959	log_test $? 2 "IPv6 route can not have a group with v4 and v6 gateways"
    960
    961	run_cmd "$IP nexthop del id 88"
    962	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
    963	log_test $? 2 "IPv6 route can not have a group with v4 and v6 gateways"
    964
    965	run_cmd "$IP nexthop del id 87"
    966	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
    967	log_test $? 0 "IPv6 route using a group after removing v4 gateways"
    968
    969	run_cmd "$IP ro delete 2001:db8:101::1/128"
    970	run_cmd "$IP nexthop add id 87 via 172.16.1.1 dev veth1"
    971	run_cmd "$IP nexthop add id 88 via 172.16.1.1 dev veth1"
    972	run_cmd "$IP nexthop replace id 124 group 86/87/88"
    973	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
    974	log_test $? 2 "IPv6 route can not have a group with v4 and v6 gateways"
    975
    976	run_cmd "$IP nexthop replace id 88 via 2001:db8:92::2 dev veth3"
    977	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
    978	log_test $? 2 "IPv6 route can not have a group with v4 and v6 gateways"
    979
    980	run_cmd "$IP nexthop replace id 87 via 2001:db8:92::2 dev veth3"
    981	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 124"
    982	log_test $? 0 "IPv6 route using a group after replacing v4 gateways"
    983
    984	$IP nexthop flush >/dev/null 2>&1
    985
    986	#
    987	# weird IPv6 cases
    988	#
    989	run_cmd "$IP nexthop add id 86 via 2001:db8:91::2 dev veth1"
    990	run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
    991
    992	# route can not use prefsrc with nexthops
    993	run_cmd "$IP ro add 2001:db8:101::2/128 nhid 86 from 2001:db8:91::1"
    994	log_test $? 2 "IPv6 route can not use src routing with external nexthop"
    995
    996	# check cleanup path on invalid metric
    997	run_cmd "$IP ro add 2001:db8:101::2/128 nhid 86 congctl lock foo"
    998	log_test $? 2 "IPv6 route with invalid metric"
    999
   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
   1020ipv6_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
   1033ipv6_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
   1049ipv6_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
   1057ipv6_grp_replace_loop()
   1058{
   1059	while :; do
   1060		$IP nexthop replace id 102 group 100/101
   1061	done >/dev/null 2>&1
   1062}
   1063
   1064ipv6_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
   1105ipv6_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
   1112ipv6_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
   1161ipv4_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
   1228ipv4_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
   1333ipv4_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
   1397ipv4_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
   1426ipv4_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
   1609ipv4_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
   1622ipv4_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
   1638sysctl_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
   1656sysctl_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
   1669ipv6_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
   1740ipv4_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
   1805ipv4_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
   1813ipv4_grp_replace_loop()
   1814{
   1815	while :; do
   1816		$IP nexthop replace id 102 group 100/101
   1817	done >/dev/null 2>&1
   1818}
   1819
   1820ipv4_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
   1861ipv4_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
   1868ipv4_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
   1917basic()
   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
   2043check_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
   2064basic_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
   2245usage()
   2246{
   2247	cat <<EOF
   2248usage: ${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
   2263done
   2264EOF
   2265}
   2266
   2267################################################################################
   2268# main
   2269
   2270while getopts :t:pP46hv:w: o
   2271do
   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
   2283done
   2284
   2285# make sure we don't pause twice
   2286[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
   2287
   2288if [ "$(id -u)" -ne 0 ];then
   2289	echo "SKIP: Need root privileges"
   2290	exit $ksft_skip;
   2291fi
   2292
   2293if [ ! -x "$(command -v ip)" ]; then
   2294	echo "SKIP: Could not run test without ip tool"
   2295	exit $ksft_skip
   2296fi
   2297
   2298ip help 2>&1 | grep -q nexthop
   2299if [ $? -ne 0 ]; then
   2300	echo "SKIP: iproute2 too old, missing nexthop command"
   2301	exit $ksft_skip
   2302fi
   2303
   2304out=$(ip nexthop ls 2>&1 | grep -q "Operation not supported")
   2305if [ $? -eq 0 ]; then
   2306	echo "SKIP: kernel lacks nexthop support"
   2307	exit $ksft_skip
   2308fi
   2309
   2310for t in $TESTS
   2311do
   2312	case $t in
   2313	none) IP="ip -netns peer"; setup; exit 0;;
   2314	*) setup; $t; cleanup;;
   2315	esac
   2316done
   2317
   2318if [ "$TESTS" != "none" ]; then
   2319	printf "\nTests passed: %3d\n" ${nsuccess}
   2320	printf "Tests failed: %3d\n"   ${nfail}
   2321fi
   2322
   2323exit $ret