xref: /linux/tools/testing/selftests/net/fib_nexthops.sh (revision 5d085ad2e68cceec8332b23ea8f630a28b506366)
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="ipv4_fcnal ipv4_grp_fcnal ipv4_withv6_fcnal ipv4_fcnal_runtime"
23IPV6_TESTS="ipv6_fcnal ipv6_grp_fcnal ipv6_fcnal_runtime"
24
25ALL_TESTS="basic ${IPV4_TESTS} ${IPV6_TESTS}"
26TESTS="${ALL_TESTS}"
27VERBOSE=0
28PAUSE_ON_FAIL=no
29PAUSE=no
30
31nsid=100
32
33################################################################################
34# utilities
35
36log_test()
37{
38	local rc=$1
39	local expected=$2
40	local msg="$3"
41
42	if [ ${rc} -eq ${expected} ]; then
43		printf "TEST: %-60s  [ OK ]\n" "${msg}"
44		nsuccess=$((nsuccess+1))
45	else
46		ret=1
47		nfail=$((nfail+1))
48		printf "TEST: %-60s  [FAIL]\n" "${msg}"
49		if [ "$VERBOSE" = "1" ]; then
50			echo "    rc=$rc, expected $expected"
51		fi
52
53		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
54		echo
55			echo "hit enter to continue, 'q' to quit"
56			read a
57			[ "$a" = "q" ] && exit 1
58		fi
59	fi
60
61	if [ "${PAUSE}" = "yes" ]; then
62		echo
63		echo "hit enter to continue, 'q' to quit"
64		read a
65		[ "$a" = "q" ] && exit 1
66	fi
67
68	[ "$VERBOSE" = "1" ] && echo
69}
70
71run_cmd()
72{
73	local cmd="$1"
74	local out
75	local stderr="2>/dev/null"
76
77	if [ "$VERBOSE" = "1" ]; then
78		printf "COMMAND: $cmd\n"
79		stderr=
80	fi
81
82	out=$(eval $cmd $stderr)
83	rc=$?
84	if [ "$VERBOSE" = "1" -a -n "$out" ]; then
85		echo "    $out"
86	fi
87
88	return $rc
89}
90
91get_linklocal()
92{
93	local dev=$1
94	local ns
95	local addr
96
97	[ -n "$2" ] && ns="-netns $2"
98	addr=$(ip $ns -6 -br addr show dev ${dev} | \
99	awk '{
100		for (i = 3; i <= NF; ++i) {
101			if ($i ~ /^fe80/)
102				print $i
103		}
104	}'
105	)
106	addr=${addr/\/*}
107
108	[ -z "$addr" ] && return 1
109
110	echo $addr
111
112	return 0
113}
114
115create_ns()
116{
117	local n=${1}
118
119	ip netns del ${n} 2>/dev/null
120
121	set -e
122	ip netns add ${n}
123	ip netns set ${n} $((nsid++))
124	ip -netns ${n} addr add 127.0.0.1/8 dev lo
125	ip -netns ${n} link set lo up
126
127	ip netns exec ${n} sysctl -qw net.ipv4.ip_forward=1
128	ip netns exec ${n} sysctl -qw net.ipv4.fib_multipath_use_neigh=1
129	ip netns exec ${n} sysctl -qw net.ipv4.conf.default.ignore_routes_with_linkdown=1
130	ip netns exec ${n} sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1
131	ip netns exec ${n} sysctl -qw net.ipv6.conf.all.forwarding=1
132	ip netns exec ${n} sysctl -qw net.ipv6.conf.default.forwarding=1
133	ip netns exec ${n} sysctl -qw net.ipv6.conf.default.ignore_routes_with_linkdown=1
134	ip netns exec ${n} sysctl -qw net.ipv6.conf.all.accept_dad=0
135	ip netns exec ${n} sysctl -qw net.ipv6.conf.default.accept_dad=0
136
137	set +e
138}
139
140setup()
141{
142	cleanup
143
144	create_ns me
145	create_ns peer
146	create_ns remote
147
148	IP="ip -netns me"
149	set -e
150	$IP li add veth1 type veth peer name veth2
151	$IP li set veth1 up
152	$IP addr add 172.16.1.1/24 dev veth1
153	$IP -6 addr add 2001:db8:91::1/64 dev veth1 nodad
154
155	$IP li add veth3 type veth peer name veth4
156	$IP li set veth3 up
157	$IP addr add 172.16.2.1/24 dev veth3
158	$IP -6 addr add 2001:db8:92::1/64 dev veth3 nodad
159
160	$IP li set veth2 netns peer up
161	ip -netns peer addr add 172.16.1.2/24 dev veth2
162	ip -netns peer -6 addr add 2001:db8:91::2/64 dev veth2 nodad
163
164	$IP li set veth4 netns peer up
165	ip -netns peer addr add 172.16.2.2/24 dev veth4
166	ip -netns peer -6 addr add 2001:db8:92::2/64 dev veth4 nodad
167
168	ip -netns remote li add veth5 type veth peer name veth6
169	ip -netns remote li set veth5 up
170	ip -netns remote addr add dev veth5 172.16.101.1/24
171	ip -netns remote -6 addr add dev veth5 2001:db8:101::1/64 nodad
172	ip -netns remote ro add 172.16.0.0/22 via 172.16.101.2
173	ip -netns remote -6 ro add 2001:db8:90::/40 via 2001:db8:101::2
174
175	ip -netns remote li set veth6 netns peer up
176	ip -netns peer addr add dev veth6 172.16.101.2/24
177	ip -netns peer -6 addr add dev veth6 2001:db8:101::2/64 nodad
178	set +e
179}
180
181cleanup()
182{
183	local ns
184
185	for ns in me peer remote; do
186		ip netns del ${ns} 2>/dev/null
187	done
188}
189
190check_output()
191{
192	local out="$1"
193	local expected="$2"
194	local rc=0
195
196	[ "${out}" = "${expected}" ] && return 0
197
198	if [ -z "${out}" ]; then
199		if [ "$VERBOSE" = "1" ]; then
200			printf "\nNo entry found\n"
201			printf "Expected:\n"
202			printf "    ${expected}\n"
203		fi
204		return 1
205	fi
206
207	out=$(echo ${out})
208	if [ "${out}" != "${expected}" ]; then
209		rc=1
210		if [ "${VERBOSE}" = "1" ]; then
211			printf "    Unexpected entry. Have:\n"
212			printf "        ${out}\n"
213			printf "    Expected:\n"
214			printf "        ${expected}\n\n"
215		else
216			echo "      WARNING: Unexpected route entry"
217		fi
218	fi
219
220	return $rc
221}
222
223check_nexthop()
224{
225	local nharg="$1"
226	local expected="$2"
227	local out
228
229	out=$($IP nexthop ls ${nharg} 2>/dev/null)
230
231	check_output "${out}" "${expected}"
232}
233
234check_route()
235{
236	local pfx="$1"
237	local expected="$2"
238	local out
239
240	out=$($IP route ls match ${pfx} 2>/dev/null)
241
242	check_output "${out}" "${expected}"
243}
244
245check_route6()
246{
247	local pfx="$1"
248	local expected="$2"
249	local out
250
251	out=$($IP -6 route ls match ${pfx} 2>/dev/null | sed -e 's/pref medium//')
252
253	check_output "${out}" "${expected}"
254}
255
256################################################################################
257# basic operations (add, delete, replace) on nexthops and nexthop groups
258#
259# IPv6
260
261ipv6_fcnal()
262{
263	local rc
264
265	echo
266	echo "IPv6"
267	echo "----------------------"
268
269	run_cmd "$IP nexthop add id 52 via 2001:db8:91::2 dev veth1"
270	rc=$?
271	log_test $rc 0 "Create nexthop with id, gw, dev"
272	if [ $rc -ne 0 ]; then
273		echo "Basic IPv6 create fails; can not continue"
274		return 1
275	fi
276
277	run_cmd "$IP nexthop get id 52"
278	log_test $? 0 "Get nexthop by id"
279	check_nexthop "id 52" "id 52 via 2001:db8:91::2 dev veth1 scope link"
280
281	run_cmd "$IP nexthop del id 52"
282	log_test $? 0 "Delete nexthop by id"
283	check_nexthop "id 52" ""
284
285	#
286	# gw, device spec
287	#
288	# gw validation, no device - fails since dev required
289	run_cmd "$IP nexthop add id 52 via 2001:db8:92::3"
290	log_test $? 2 "Create nexthop - gw only"
291
292	# gw is not reachable throught given dev
293	run_cmd "$IP nexthop add id 53 via 2001:db8:3::3 dev veth1"
294	log_test $? 2 "Create nexthop - invalid gw+dev combination"
295
296	# onlink arg overrides gw+dev lookup
297	run_cmd "$IP nexthop add id 53 via 2001:db8:3::3 dev veth1 onlink"
298	log_test $? 0 "Create nexthop - gw+dev and onlink"
299
300	# admin down should delete nexthops
301	set -e
302	run_cmd "$IP -6 nexthop add id 55 via 2001:db8:91::3 dev veth1"
303	run_cmd "$IP nexthop add id 56 via 2001:db8:91::4 dev veth1"
304	run_cmd "$IP nexthop add id 57 via 2001:db8:91::5 dev veth1"
305	run_cmd "$IP li set dev veth1 down"
306	set +e
307	check_nexthop "dev veth1" ""
308	log_test $? 0 "Nexthops removed on admin down"
309}
310
311ipv6_grp_fcnal()
312{
313	local rc
314
315	echo
316	echo "IPv6 groups functional"
317	echo "----------------------"
318
319	# basic functionality: create a nexthop group, default weight
320	run_cmd "$IP nexthop add id 61 via 2001:db8:91::2 dev veth1"
321	run_cmd "$IP nexthop add id 101 group 61"
322	log_test $? 0 "Create nexthop group with single nexthop"
323
324	# get nexthop group
325	run_cmd "$IP nexthop get id 101"
326	log_test $? 0 "Get nexthop group by id"
327	check_nexthop "id 101" "id 101 group 61"
328
329	# delete nexthop group
330	run_cmd "$IP nexthop del id 101"
331	log_test $? 0 "Delete nexthop group by id"
332	check_nexthop "id 101" ""
333
334	$IP nexthop flush >/dev/null 2>&1
335	check_nexthop "id 101" ""
336
337	#
338	# create group with multiple nexthops - mix of gw and dev only
339	#
340	run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
341	run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
342	run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
343	run_cmd "$IP nexthop add id 65 dev veth1"
344	run_cmd "$IP nexthop add id 102 group 62/63/64/65"
345	log_test $? 0 "Nexthop group with multiple nexthops"
346	check_nexthop "id 102" "id 102 group 62/63/64/65"
347
348	# Delete nexthop in a group and group is updated
349	run_cmd "$IP nexthop del id 63"
350	check_nexthop "id 102" "id 102 group 62/64/65"
351	log_test $? 0 "Nexthop group updated when entry is deleted"
352
353	# create group with multiple weighted nexthops
354	run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
355	run_cmd "$IP nexthop add id 103 group 62/63,2/64,3/65,4"
356	log_test $? 0 "Nexthop group with weighted nexthops"
357	check_nexthop "id 103" "id 103 group 62/63,2/64,3/65,4"
358
359	# Delete nexthop in a weighted group and group is updated
360	run_cmd "$IP nexthop del id 63"
361	check_nexthop "id 103" "id 103 group 62/64,3/65,4"
362	log_test $? 0 "Weighted nexthop group updated when entry is deleted"
363
364	# admin down - nexthop is removed from group
365	run_cmd "$IP li set dev veth1 down"
366	check_nexthop "dev veth1" ""
367	log_test $? 0 "Nexthops in groups removed on admin down"
368
369	# expect groups to have been deleted as well
370	check_nexthop "" ""
371
372	run_cmd "$IP li set dev veth1 up"
373
374	$IP nexthop flush >/dev/null 2>&1
375
376	# group with nexthops using different devices
377	set -e
378	run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
379	run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
380	run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
381	run_cmd "$IP nexthop add id 65 via 2001:db8:91::5 dev veth1"
382
383	run_cmd "$IP nexthop add id 72 via 2001:db8:92::2 dev veth3"
384	run_cmd "$IP nexthop add id 73 via 2001:db8:92::3 dev veth3"
385	run_cmd "$IP nexthop add id 74 via 2001:db8:92::4 dev veth3"
386	run_cmd "$IP nexthop add id 75 via 2001:db8:92::5 dev veth3"
387	set +e
388
389	# multiple groups with same nexthop
390	run_cmd "$IP nexthop add id 104 group 62"
391	run_cmd "$IP nexthop add id 105 group 62"
392	check_nexthop "group" "id 104 group 62 id 105 group 62"
393	log_test $? 0 "Multiple groups with same nexthop"
394
395	run_cmd "$IP nexthop flush groups"
396	[ $? -ne 0 ] && return 1
397
398	# on admin down of veth1, it should be removed from the group
399	run_cmd "$IP nexthop add id 105 group 62/63/72/73/64"
400	run_cmd "$IP li set veth1 down"
401	check_nexthop "id 105" "id 105 group 72/73"
402	log_test $? 0 "Nexthops in group removed on admin down - mixed group"
403
404	run_cmd "$IP nexthop add id 106 group 105/74"
405	log_test $? 2 "Nexthop group can not have a group as an entry"
406
407	# a group can have a blackhole entry only if it is the only
408	# nexthop in the group. Needed for atomic replace with an
409	# actual nexthop group
410	run_cmd "$IP -6 nexthop add id 31 blackhole"
411	run_cmd "$IP nexthop add id 107 group 31"
412	log_test $? 0 "Nexthop group with a blackhole entry"
413
414	run_cmd "$IP nexthop add id 108 group 31/24"
415	log_test $? 2 "Nexthop group can not have a blackhole and another nexthop"
416}
417
418ipv6_fcnal_runtime()
419{
420	local rc
421
422	echo
423	echo "IPv6 functional runtime"
424	echo "-----------------------"
425
426	#
427	# IPv6 - the basics
428	#
429	run_cmd "$IP nexthop add id 81 via 2001:db8:91::2 dev veth1"
430	run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
431	log_test $? 0 "Route add"
432
433	run_cmd "$IP ro delete 2001:db8:101::1/128 nhid 81"
434	log_test $? 0 "Route delete"
435
436	run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
437	run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
438	log_test $? 0 "Ping with nexthop"
439
440	run_cmd "$IP nexthop add id 82 via 2001:db8:92::2 dev veth3"
441	run_cmd "$IP nexthop add id 122 group 81/82"
442	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
443	run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
444	log_test $? 0 "Ping - multipath"
445
446	#
447	# IPv6 with blackhole nexthops
448	#
449	run_cmd "$IP -6 nexthop add id 83 blackhole"
450	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 83"
451	run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
452	log_test $? 2 "Ping - blackhole"
453
454	run_cmd "$IP nexthop replace id 83 via 2001:db8:91::2 dev veth1"
455	run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
456	log_test $? 0 "Ping - blackhole replaced with gateway"
457
458	run_cmd "$IP -6 nexthop replace id 83 blackhole"
459	run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
460	log_test $? 2 "Ping - gateway replaced by blackhole"
461
462	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
463	run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
464	if [ $? -eq 0 ]; then
465		run_cmd "$IP nexthop replace id 122 group 83"
466		run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
467		log_test $? 2 "Ping - group with blackhole"
468
469		run_cmd "$IP nexthop replace id 122 group 81/82"
470		run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
471		log_test $? 0 "Ping - group blackhole replaced with gateways"
472	else
473		log_test 2 0 "Ping - multipath failed"
474	fi
475
476	#
477	# device only and gw + dev only mix
478	#
479	run_cmd "$IP -6 nexthop add id 85 dev veth1"
480	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 85"
481	log_test $? 0 "IPv6 route with device only nexthop"
482	check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 85 dev veth1 metric 1024"
483
484	run_cmd "$IP nexthop add id 123 group 81/85"
485	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 123"
486	log_test $? 0 "IPv6 multipath route with nexthop mix - dev only + gw"
487	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"
488
489	#
490	# IPv6 route with v4 nexthop - not allowed
491	#
492	run_cmd "$IP ro delete 2001:db8:101::1/128"
493	run_cmd "$IP nexthop add id 84 via 172.16.1.1 dev veth1"
494	run_cmd "$IP ro add 2001:db8:101::1/128 nhid 84"
495	log_test $? 2 "IPv6 route can not have a v4 gateway"
496
497	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 81"
498	run_cmd "$IP nexthop replace id 81 via 172.16.1.1 dev veth1"
499	log_test $? 2 "Nexthop replace - v6 route, v4 nexthop"
500
501	run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
502	run_cmd "$IP nexthop replace id 81 via 172.16.1.1 dev veth1"
503	log_test $? 2 "Nexthop replace of group entry - v6 route, v4 nexthop"
504
505	$IP nexthop flush >/dev/null 2>&1
506
507	#
508	# weird IPv6 cases
509	#
510	run_cmd "$IP nexthop add id 86 via 2001:db8:91::2 dev veth1"
511	run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
512
513	# TO-DO:
514	# existing route with old nexthop; append route with new nexthop
515	# existing route with old nexthop; replace route with new
516	# existing route with new nexthop; replace route with old
517	# route with src address and using nexthop - not allowed
518}
519
520ipv4_fcnal()
521{
522	local rc
523
524	echo
525	echo "IPv4 functional"
526	echo "----------------------"
527
528	#
529	# basic IPv4 ops - add, get, delete
530	#
531	run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
532	rc=$?
533	log_test $rc 0 "Create nexthop with id, gw, dev"
534	if [ $rc -ne 0 ]; then
535		echo "Basic IPv4 create fails; can not continue"
536		return 1
537	fi
538
539	run_cmd "$IP nexthop get id 12"
540	log_test $? 0 "Get nexthop by id"
541	check_nexthop "id 12" "id 12 via 172.16.1.2 dev veth1 scope link"
542
543	run_cmd "$IP nexthop del id 12"
544	log_test $? 0 "Delete nexthop by id"
545	check_nexthop "id 52" ""
546
547	#
548	# gw, device spec
549	#
550	# gw validation, no device - fails since dev is required
551	run_cmd "$IP nexthop add id 12 via 172.16.2.3"
552	log_test $? 2 "Create nexthop - gw only"
553
554	# gw not reachable through given dev
555	run_cmd "$IP nexthop add id 13 via 172.16.3.2 dev veth1"
556	log_test $? 2 "Create nexthop - invalid gw+dev combination"
557
558	# onlink flag overrides gw+dev lookup
559	run_cmd "$IP nexthop add id 13 via 172.16.3.2 dev veth1 onlink"
560	log_test $? 0 "Create nexthop - gw+dev and onlink"
561
562	# admin down should delete nexthops
563	set -e
564	run_cmd "$IP nexthop add id 15 via 172.16.1.3 dev veth1"
565	run_cmd "$IP nexthop add id 16 via 172.16.1.4 dev veth1"
566	run_cmd "$IP nexthop add id 17 via 172.16.1.5 dev veth1"
567	run_cmd "$IP li set dev veth1 down"
568	set +e
569	check_nexthop "dev veth1" ""
570	log_test $? 0 "Nexthops removed on admin down"
571}
572
573ipv4_grp_fcnal()
574{
575	local rc
576
577	echo
578	echo "IPv4 groups functional"
579	echo "----------------------"
580
581	# basic functionality: create a nexthop group, default weight
582	run_cmd "$IP nexthop add id 11 via 172.16.1.2 dev veth1"
583	run_cmd "$IP nexthop add id 101 group 11"
584	log_test $? 0 "Create nexthop group with single nexthop"
585
586	# get nexthop group
587	run_cmd "$IP nexthop get id 101"
588	log_test $? 0 "Get nexthop group by id"
589	check_nexthop "id 101" "id 101 group 11"
590
591	# delete nexthop group
592	run_cmd "$IP nexthop del id 101"
593	log_test $? 0 "Delete nexthop group by id"
594	check_nexthop "id 101" ""
595
596	$IP nexthop flush >/dev/null 2>&1
597
598	#
599	# create group with multiple nexthops
600	run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
601	run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
602	run_cmd "$IP nexthop add id 14 via 172.16.1.4 dev veth1"
603	run_cmd "$IP nexthop add id 15 via 172.16.1.5 dev veth1"
604	run_cmd "$IP nexthop add id 102 group 12/13/14/15"
605	log_test $? 0 "Nexthop group with multiple nexthops"
606	check_nexthop "id 102" "id 102 group 12/13/14/15"
607
608	# Delete nexthop in a group and group is updated
609	run_cmd "$IP nexthop del id 13"
610	check_nexthop "id 102" "id 102 group 12/14/15"
611	log_test $? 0 "Nexthop group updated when entry is deleted"
612
613	# create group with multiple weighted nexthops
614	run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
615	run_cmd "$IP nexthop add id 103 group 12/13,2/14,3/15,4"
616	log_test $? 0 "Nexthop group with weighted nexthops"
617	check_nexthop "id 103" "id 103 group 12/13,2/14,3/15,4"
618
619	# Delete nexthop in a weighted group and group is updated
620	run_cmd "$IP nexthop del id 13"
621	check_nexthop "id 103" "id 103 group 12/14,3/15,4"
622	log_test $? 0 "Weighted nexthop group updated when entry is deleted"
623
624	# admin down - nexthop is removed from group
625	run_cmd "$IP li set dev veth1 down"
626	check_nexthop "dev veth1" ""
627	log_test $? 0 "Nexthops in groups removed on admin down"
628
629	# expect groups to have been deleted as well
630	check_nexthop "" ""
631
632	run_cmd "$IP li set dev veth1 up"
633
634	$IP nexthop flush >/dev/null 2>&1
635
636	# group with nexthops using different devices
637	set -e
638	run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
639	run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
640	run_cmd "$IP nexthop add id 14 via 172.16.1.4 dev veth1"
641	run_cmd "$IP nexthop add id 15 via 172.16.1.5 dev veth1"
642
643	run_cmd "$IP nexthop add id 22 via 172.16.2.2 dev veth3"
644	run_cmd "$IP nexthop add id 23 via 172.16.2.3 dev veth3"
645	run_cmd "$IP nexthop add id 24 via 172.16.2.4 dev veth3"
646	run_cmd "$IP nexthop add id 25 via 172.16.2.5 dev veth3"
647	set +e
648
649	# multiple groups with same nexthop
650	run_cmd "$IP nexthop add id 104 group 12"
651	run_cmd "$IP nexthop add id 105 group 12"
652	check_nexthop "group" "id 104 group 12 id 105 group 12"
653	log_test $? 0 "Multiple groups with same nexthop"
654
655	run_cmd "$IP nexthop flush groups"
656	[ $? -ne 0 ] && return 1
657
658	# on admin down of veth1, it should be removed from the group
659	run_cmd "$IP nexthop add id 105 group 12/13/22/23/14"
660	run_cmd "$IP li set veth1 down"
661	check_nexthop "id 105" "id 105 group 22/23"
662	log_test $? 0 "Nexthops in group removed on admin down - mixed group"
663
664	run_cmd "$IP nexthop add id 106 group 105/24"
665	log_test $? 2 "Nexthop group can not have a group as an entry"
666
667	# a group can have a blackhole entry only if it is the only
668	# nexthop in the group. Needed for atomic replace with an
669	# actual nexthop group
670	run_cmd "$IP nexthop add id 31 blackhole"
671	run_cmd "$IP nexthop add id 107 group 31"
672	log_test $? 0 "Nexthop group with a blackhole entry"
673
674	run_cmd "$IP nexthop add id 108 group 31/24"
675	log_test $? 2 "Nexthop group can not have a blackhole and another nexthop"
676}
677
678ipv4_withv6_fcnal()
679{
680	local lladdr
681
682	set -e
683	lladdr=$(get_linklocal veth2 peer)
684	run_cmd "$IP nexthop add id 11 via ${lladdr} dev veth1"
685	set +e
686	run_cmd "$IP ro add 172.16.101.1/32 nhid 11"
687	log_test $? 0 "IPv6 nexthop with IPv4 route"
688	check_route "172.16.101.1" "172.16.101.1 nhid 11 via inet6 ${lladdr} dev veth1"
689
690	set -e
691	run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
692	run_cmd "$IP nexthop add id 101 group 11/12"
693	set +e
694	run_cmd "$IP ro replace 172.16.101.1/32 nhid 101"
695	log_test $? 0 "IPv6 nexthop with IPv4 route"
696
697	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"
698
699	run_cmd "$IP ro replace 172.16.101.1/32 via inet6 ${lladdr} dev veth1"
700	log_test $? 0 "IPv4 route with IPv6 gateway"
701	check_route "172.16.101.1" "172.16.101.1 via inet6 ${lladdr} dev veth1"
702
703	run_cmd "$IP ro replace 172.16.101.1/32 via inet6 2001:db8:50::1 dev veth1"
704	log_test $? 2 "IPv4 route with invalid IPv6 gateway"
705}
706
707ipv4_fcnal_runtime()
708{
709	local lladdr
710	local rc
711
712	echo
713	echo "IPv4 functional runtime"
714	echo "-----------------------"
715
716	run_cmd "$IP nexthop add id 21 via 172.16.1.2 dev veth1"
717	run_cmd "$IP ro add 172.16.101.1/32 nhid 21"
718	log_test $? 0 "Route add"
719	check_route "172.16.101.1" "172.16.101.1 nhid 21 via 172.16.1.2 dev veth1"
720
721	run_cmd "$IP ro delete 172.16.101.1/32 nhid 21"
722	log_test $? 0 "Route delete"
723
724	#
725	# scope mismatch
726	#
727	run_cmd "$IP nexthop add id 22 via 172.16.1.2 dev veth1"
728	run_cmd "$IP ro add 172.16.101.1/32 nhid 22 scope host"
729	log_test $? 2 "Route add - scope conflict with nexthop"
730
731	run_cmd "$IP nexthop replace id 22 dev veth3"
732	run_cmd "$IP ro add 172.16.101.1/32 nhid 22 scope host"
733	run_cmd "$IP nexthop replace id 22 via 172.16.2.2 dev veth3"
734	log_test $? 2 "Nexthop replace with invalid scope for existing route"
735
736	#
737	# add route with nexthop and check traffic
738	#
739	run_cmd "$IP nexthop replace id 21 via 172.16.1.2 dev veth1"
740	run_cmd "$IP ro replace 172.16.101.1/32 nhid 21"
741	run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
742	log_test $? 0 "Basic ping"
743
744	run_cmd "$IP nexthop replace id 22 via 172.16.2.2 dev veth3"
745	run_cmd "$IP nexthop add id 122 group 21/22"
746	run_cmd "$IP ro replace 172.16.101.1/32 nhid 122"
747	run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
748	log_test $? 0 "Ping - multipath"
749
750	run_cmd "$IP ro delete 172.16.101.1/32 nhid 122"
751
752	#
753	# multiple default routes
754	# - tests fib_select_default
755	run_cmd "$IP nexthop add id 501 via 172.16.1.2 dev veth1"
756	run_cmd "$IP ro add default nhid 501"
757	run_cmd "$IP ro add default via 172.16.1.3 dev veth1 metric 20"
758	run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
759	log_test $? 0 "Ping - multiple default routes, nh first"
760
761	# flip the order
762	run_cmd "$IP ro del default nhid 501"
763	run_cmd "$IP ro del default via 172.16.1.3 dev veth1 metric 20"
764	run_cmd "$IP ro add default via 172.16.1.2 dev veth1 metric 20"
765	run_cmd "$IP nexthop replace id 501 via 172.16.1.3 dev veth1"
766	run_cmd "$IP ro add default nhid 501 metric 20"
767	run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
768	log_test $? 0 "Ping - multiple default routes, nh second"
769
770	run_cmd "$IP nexthop delete nhid 501"
771	run_cmd "$IP ro del default"
772
773	#
774	# IPv4 with blackhole nexthops
775	#
776	run_cmd "$IP nexthop add id 23 blackhole"
777	run_cmd "$IP ro replace 172.16.101.1/32 nhid 23"
778	run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
779	log_test $? 2 "Ping - blackhole"
780
781	run_cmd "$IP nexthop replace id 23 via 172.16.1.2 dev veth1"
782	run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
783	log_test $? 0 "Ping - blackhole replaced with gateway"
784
785	run_cmd "$IP nexthop replace id 23 blackhole"
786	run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
787	log_test $? 2 "Ping - gateway replaced by blackhole"
788
789	run_cmd "$IP ro replace 172.16.101.1/32 nhid 122"
790	run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
791	if [ $? -eq 0 ]; then
792		run_cmd "$IP nexthop replace id 122 group 23"
793		run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
794		log_test $? 2 "Ping - group with blackhole"
795
796		run_cmd "$IP nexthop replace id 122 group 21/22"
797		run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
798		log_test $? 0 "Ping - group blackhole replaced with gateways"
799	else
800		log_test 2 0 "Ping - multipath failed"
801	fi
802
803	#
804	# device only and gw + dev only mix
805	#
806	run_cmd "$IP nexthop add id 85 dev veth1"
807	run_cmd "$IP ro replace 172.16.101.1/32 nhid 85"
808	log_test $? 0 "IPv4 route with device only nexthop"
809	check_route "172.16.101.1" "172.16.101.1 nhid 85 dev veth1"
810
811	run_cmd "$IP nexthop add id 123 group 21/85"
812	run_cmd "$IP ro replace 172.16.101.1/32 nhid 123"
813	log_test $? 0 "IPv4 multipath route with nexthop mix - dev only + gw"
814	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"
815
816	#
817	# IPv4 with IPv6
818	#
819	set -e
820	lladdr=$(get_linklocal veth2 peer)
821	run_cmd "$IP nexthop add id 24 via ${lladdr} dev veth1"
822	set +e
823	run_cmd "$IP ro replace 172.16.101.1/32 nhid 24"
824	run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
825	log_test $? 0 "IPv6 nexthop with IPv4 route"
826
827	$IP neigh sh | grep -q "${lladdr} dev veth1"
828	if [ $? -eq 1 ]; then
829		echo "    WARNING: Neigh entry missing for ${lladdr}"
830		$IP neigh sh | grep 'dev veth1'
831	fi
832
833	$IP neigh sh | grep -q "172.16.101.1 dev eth1"
834	if [ $? -eq 0 ]; then
835		echo "    WARNING: Neigh entry exists for 172.16.101.1"
836		$IP neigh sh | grep 'dev veth1'
837	fi
838
839	set -e
840	run_cmd "$IP nexthop add id 25 via 172.16.1.2 dev veth1"
841	run_cmd "$IP nexthop add id 101 group 24/25"
842	set +e
843	run_cmd "$IP ro replace 172.16.101.1/32 nhid 101"
844	log_test $? 0 "IPv4 route with mixed v4-v6 multipath route"
845
846	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"
847
848	run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
849	log_test $? 0 "IPv6 nexthop with IPv4 route"
850
851	run_cmd "$IP ro replace 172.16.101.1/32 via inet6 ${lladdr} dev veth1"
852	run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
853	log_test $? 0 "IPv4 route with IPv6 gateway"
854
855	$IP neigh sh | grep -q "${lladdr} dev veth1"
856	if [ $? -eq 1 ]; then
857		echo "    WARNING: Neigh entry missing for ${lladdr}"
858		$IP neigh sh | grep 'dev veth1'
859	fi
860
861	$IP neigh sh | grep -q "172.16.101.1 dev eth1"
862	if [ $? -eq 0 ]; then
863		echo "    WARNING: Neigh entry exists for 172.16.101.1"
864		$IP neigh sh | grep 'dev veth1'
865	fi
866
867	run_cmd "$IP ro del 172.16.101.1/32 via inet6 ${lladdr} dev veth1"
868	run_cmd "$IP -4 ro add default via inet6 ${lladdr} dev veth1"
869	run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
870	log_test $? 0 "IPv4 default route with IPv6 gateway"
871
872	#
873	# MPLS as an example of LWT encap
874	#
875	run_cmd "$IP nexthop add id 51 encap mpls 101 via 172.16.1.2 dev veth1"
876	log_test $? 0 "IPv4 route with MPLS encap"
877	check_nexthop "id 51" "id 51 encap mpls 101 via 172.16.1.2 dev veth1 scope link"
878	log_test $? 0 "IPv4 route with MPLS encap - check"
879
880	run_cmd "$IP nexthop add id 52 encap mpls 102 via inet6 2001:db8:91::2 dev veth1"
881	log_test $? 0 "IPv4 route with MPLS encap and v6 gateway"
882	check_nexthop "id 52" "id 52 encap mpls 102 via 2001:db8:91::2 dev veth1 scope link"
883	log_test $? 0 "IPv4 route with MPLS encap, v6 gw - check"
884}
885
886basic()
887{
888	echo
889	echo "Basic functional tests"
890	echo "----------------------"
891	run_cmd "$IP nexthop ls"
892	log_test $? 0 "List with nothing defined"
893
894	run_cmd "$IP nexthop get id 1"
895	log_test $? 2 "Nexthop get on non-existent id"
896
897	# attempt to create nh without a device or gw - fails
898	run_cmd "$IP nexthop add id 1"
899	log_test $? 2 "Nexthop with no device or gateway"
900
901	# attempt to create nh with down device - fails
902	$IP li set veth1 down
903	run_cmd "$IP nexthop add id 1 dev veth1"
904	log_test $? 2 "Nexthop with down device"
905
906	# create nh with linkdown device - fails
907	$IP li set veth1 up
908	ip -netns peer li set veth2 down
909	run_cmd "$IP nexthop add id 1 dev veth1"
910	log_test $? 2 "Nexthop with device that is linkdown"
911	ip -netns peer li set veth2 up
912
913	# device only
914	run_cmd "$IP nexthop add id 1 dev veth1"
915	log_test $? 0 "Nexthop with device only"
916
917	# create nh with duplicate id
918	run_cmd "$IP nexthop add id 1 dev veth3"
919	log_test $? 2 "Nexthop with duplicate id"
920
921	# blackhole nexthop
922	run_cmd "$IP nexthop add id 2 blackhole"
923	log_test $? 0 "Blackhole nexthop"
924
925	# blackhole nexthop can not have other specs
926	run_cmd "$IP nexthop replace id 2 blackhole dev veth1"
927	log_test $? 2 "Blackhole nexthop with other attributes"
928
929	#
930	# groups
931	#
932
933	run_cmd "$IP nexthop add id 101 group 1"
934	log_test $? 0 "Create group"
935
936	run_cmd "$IP nexthop add id 102 group 2"
937	log_test $? 0 "Create group with blackhole nexthop"
938
939	# multipath group can not have a blackhole as 1 path
940	run_cmd "$IP nexthop add id 103 group 1/2"
941	log_test $? 2 "Create multipath group where 1 path is a blackhole"
942
943	# multipath group can not have a member replaced by a blackhole
944	run_cmd "$IP nexthop replace id 2 dev veth3"
945	run_cmd "$IP nexthop replace id 102 group 1/2"
946	run_cmd "$IP nexthop replace id 2 blackhole"
947	log_test $? 2 "Multipath group can not have a member replaced by blackhole"
948
949	# attempt to create group with non-existent nexthop
950	run_cmd "$IP nexthop add id 103 group 12"
951	log_test $? 2 "Create group with non-existent nexthop"
952
953	# attempt to create group with same nexthop
954	run_cmd "$IP nexthop add id 103 group 1/1"
955	log_test $? 2 "Create group with same nexthop multiple times"
956
957	# replace nexthop with a group - fails
958	run_cmd "$IP nexthop replace id 2 group 1"
959	log_test $? 2 "Replace nexthop with nexthop group"
960
961	# replace nexthop group with a nexthop - fails
962	run_cmd "$IP nexthop replace id 101 dev veth1"
963	log_test $? 2 "Replace nexthop group with nexthop"
964
965	# nexthop group with other attributes fail
966	run_cmd "$IP nexthop add id 104 group 1 dev veth1"
967	log_test $? 2 "Nexthop group and device"
968
969	# Tests to ensure that flushing works as expected.
970	run_cmd "$IP nexthop add id 105 blackhole proto 99"
971	run_cmd "$IP nexthop add id 106 blackhole proto 100"
972	run_cmd "$IP nexthop add id 107 blackhole proto 99"
973	run_cmd "$IP nexthop flush proto 99"
974	check_nexthop "id 105" ""
975	check_nexthop "id 106" "id 106 blackhole proto 100"
976	check_nexthop "id 107" ""
977	run_cmd "$IP nexthop flush proto 100"
978	check_nexthop "id 106" ""
979
980	run_cmd "$IP nexthop flush proto 100"
981	log_test $? 0 "Test proto flush"
982
983	run_cmd "$IP nexthop add id 104 group 1 blackhole"
984	log_test $? 2 "Nexthop group and blackhole"
985
986	$IP nexthop flush >/dev/null 2>&1
987}
988
989################################################################################
990# usage
991
992usage()
993{
994	cat <<EOF
995usage: ${0##*/} OPTS
996
997        -t <test>   Test(s) to run (default: all)
998                    (options: $ALL_TESTS)
999        -4          IPv4 tests only
1000        -6          IPv6 tests only
1001        -p          Pause on fail
1002        -P          Pause after each test before cleanup
1003        -v          verbose mode (show commands and output)
1004
1005    Runtime test
1006	-n num	    Number of nexthops to target
1007	-N    	    Use new style to install routes in DUT
1008
1009done
1010EOF
1011}
1012
1013################################################################################
1014# main
1015
1016while getopts :t:pP46hv o
1017do
1018	case $o in
1019		t) TESTS=$OPTARG;;
1020		4) TESTS=${IPV4_TESTS};;
1021		6) TESTS=${IPV6_TESTS};;
1022		p) PAUSE_ON_FAIL=yes;;
1023		P) PAUSE=yes;;
1024		v) VERBOSE=$(($VERBOSE + 1));;
1025		h) usage; exit 0;;
1026		*) usage; exit 1;;
1027	esac
1028done
1029
1030# make sure we don't pause twice
1031[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
1032
1033if [ "$(id -u)" -ne 0 ];then
1034	echo "SKIP: Need root privileges"
1035	exit $ksft_skip;
1036fi
1037
1038if [ ! -x "$(command -v ip)" ]; then
1039	echo "SKIP: Could not run test without ip tool"
1040	exit $ksft_skip
1041fi
1042
1043ip help 2>&1 | grep -q nexthop
1044if [ $? -ne 0 ]; then
1045	echo "SKIP: iproute2 too old, missing nexthop command"
1046	exit $ksft_skip
1047fi
1048
1049out=$(ip nexthop ls 2>&1 | grep -q "Operation not supported")
1050if [ $? -eq 0 ]; then
1051	echo "SKIP: kernel lacks nexthop support"
1052	exit $ksft_skip
1053fi
1054
1055for t in $TESTS
1056do
1057	case $t in
1058	none) IP="ip -netns peer"; setup; exit 0;;
1059	*) setup; $t; cleanup;;
1060	esac
1061done
1062
1063if [ "$TESTS" != "none" ]; then
1064	printf "\nTests passed: %3d\n" ${nsuccess}
1065	printf "Tests failed: %3d\n"   ${nfail}
1066fi
1067
1068exit $ret
1069