xref: /linux/tools/testing/selftests/net/fib_tests.sh (revision 1c9f8dff62d85ce00b0e99f774a84bd783af7cac)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# This test is for checking IPv4 and IPv6 FIB behavior in response to
5# different events.
6
7ret=0
8# Kselftest framework requirement - SKIP code is 4.
9ksft_skip=4
10
11# all tests in this script. Can be overridden with -t option
12TESTS="unregister down carrier nexthop suppress ipv6_notify ipv4_notify \
13       ipv6_rt ipv4_rt ipv6_addr_metric ipv4_addr_metric ipv6_route_metrics \
14       ipv4_route_metrics ipv4_route_v6_gw rp_filter ipv4_del_addr \
15       ipv6_del_addr ipv4_mangle ipv6_mangle ipv4_bcast_neigh fib6_gc_test"
16
17VERBOSE=0
18PAUSE_ON_FAIL=no
19PAUSE=no
20IP="$(which ip) -netns ns1"
21NS_EXEC="$(which ip) netns exec ns1"
22
23which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping)
24
25log_test()
26{
27	local rc=$1
28	local expected=$2
29	local msg="$3"
30
31	if [ ${rc} -eq ${expected} ]; then
32		printf "    TEST: %-60s  [ OK ]\n" "${msg}"
33		nsuccess=$((nsuccess+1))
34	else
35		ret=1
36		nfail=$((nfail+1))
37		printf "    TEST: %-60s  [FAIL]\n" "${msg}"
38		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
39		echo
40			echo "hit enter to continue, 'q' to quit"
41			read a
42			[ "$a" = "q" ] && exit 1
43		fi
44	fi
45
46	if [ "${PAUSE}" = "yes" ]; then
47		echo
48		echo "hit enter to continue, 'q' to quit"
49		read a
50		[ "$a" = "q" ] && exit 1
51	fi
52}
53
54setup()
55{
56	set -e
57	ip netns add ns1
58	ip netns set ns1 auto
59	$IP link set dev lo up
60	ip netns exec ns1 sysctl -qw net.ipv4.ip_forward=1
61	ip netns exec ns1 sysctl -qw net.ipv6.conf.all.forwarding=1
62
63	$IP link add dummy0 type dummy
64	$IP link set dev dummy0 up
65	$IP address add 198.51.100.1/24 dev dummy0
66	$IP -6 address add 2001:db8:1::1/64 dev dummy0
67	set +e
68
69}
70
71cleanup()
72{
73	$IP link del dev dummy0 &> /dev/null
74	ip netns del ns1 &> /dev/null
75	ip netns del ns2 &> /dev/null
76}
77
78get_linklocal()
79{
80	local dev=$1
81	local addr
82
83	addr=$($IP -6 -br addr show dev ${dev} | \
84	awk '{
85		for (i = 3; i <= NF; ++i) {
86			if ($i ~ /^fe80/)
87				print $i
88		}
89	}'
90	)
91	addr=${addr/\/*}
92
93	[ -z "$addr" ] && return 1
94
95	echo $addr
96
97	return 0
98}
99
100fib_unreg_unicast_test()
101{
102	echo
103	echo "Single path route test"
104
105	setup
106
107	echo "    Start point"
108	$IP route get fibmatch 198.51.100.2 &> /dev/null
109	log_test $? 0 "IPv4 fibmatch"
110	$IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
111	log_test $? 0 "IPv6 fibmatch"
112
113	set -e
114	$IP link del dev dummy0
115	set +e
116
117	echo "    Nexthop device deleted"
118	$IP route get fibmatch 198.51.100.2 &> /dev/null
119	log_test $? 2 "IPv4 fibmatch - no route"
120	$IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
121	log_test $? 2 "IPv6 fibmatch - no route"
122
123	cleanup
124}
125
126fib_unreg_multipath_test()
127{
128
129	echo
130	echo "Multipath route test"
131
132	setup
133
134	set -e
135	$IP link add dummy1 type dummy
136	$IP link set dev dummy1 up
137	$IP address add 192.0.2.1/24 dev dummy1
138	$IP -6 address add 2001:db8:2::1/64 dev dummy1
139
140	$IP route add 203.0.113.0/24 \
141		nexthop via 198.51.100.2 dev dummy0 \
142		nexthop via 192.0.2.2 dev dummy1
143	$IP -6 route add 2001:db8:3::/64 \
144		nexthop via 2001:db8:1::2 dev dummy0 \
145		nexthop via 2001:db8:2::2 dev dummy1
146	set +e
147
148	echo "    Start point"
149	$IP route get fibmatch 203.0.113.1 &> /dev/null
150	log_test $? 0 "IPv4 fibmatch"
151	$IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
152	log_test $? 0 "IPv6 fibmatch"
153
154	set -e
155	$IP link del dev dummy0
156	set +e
157
158	echo "    One nexthop device deleted"
159	$IP route get fibmatch 203.0.113.1 &> /dev/null
160	log_test $? 2 "IPv4 - multipath route removed on delete"
161
162	$IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
163	# In IPv6 we do not flush the entire multipath route.
164	log_test $? 0 "IPv6 - multipath down to single path"
165
166	set -e
167	$IP link del dev dummy1
168	set +e
169
170	echo "    Second nexthop device deleted"
171	$IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
172	log_test $? 2 "IPv6 - no route"
173
174	cleanup
175}
176
177fib_unreg_test()
178{
179	fib_unreg_unicast_test
180	fib_unreg_multipath_test
181}
182
183fib_down_unicast_test()
184{
185	echo
186	echo "Single path, admin down"
187
188	setup
189
190	echo "    Start point"
191	$IP route get fibmatch 198.51.100.2 &> /dev/null
192	log_test $? 0 "IPv4 fibmatch"
193	$IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
194	log_test $? 0 "IPv6 fibmatch"
195
196	set -e
197	$IP link set dev dummy0 down
198	set +e
199
200	echo "    Route deleted on down"
201	$IP route get fibmatch 198.51.100.2 &> /dev/null
202	log_test $? 2 "IPv4 fibmatch"
203	$IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
204	log_test $? 2 "IPv6 fibmatch"
205
206	cleanup
207}
208
209fib_down_multipath_test_do()
210{
211	local down_dev=$1
212	local up_dev=$2
213
214	$IP route get fibmatch 203.0.113.1 \
215		oif $down_dev &> /dev/null
216	log_test $? 2 "IPv4 fibmatch on down device"
217	$IP -6 route get fibmatch 2001:db8:3::1 \
218		oif $down_dev &> /dev/null
219	log_test $? 2 "IPv6 fibmatch on down device"
220
221	$IP route get fibmatch 203.0.113.1 \
222		oif $up_dev &> /dev/null
223	log_test $? 0 "IPv4 fibmatch on up device"
224	$IP -6 route get fibmatch 2001:db8:3::1 \
225		oif $up_dev &> /dev/null
226	log_test $? 0 "IPv6 fibmatch on up device"
227
228	$IP route get fibmatch 203.0.113.1 | \
229		grep $down_dev | grep -q "dead linkdown"
230	log_test $? 0 "IPv4 flags on down device"
231	$IP -6 route get fibmatch 2001:db8:3::1 | \
232		grep $down_dev | grep -q "dead linkdown"
233	log_test $? 0 "IPv6 flags on down device"
234
235	$IP route get fibmatch 203.0.113.1 | \
236		grep $up_dev | grep -q "dead linkdown"
237	log_test $? 1 "IPv4 flags on up device"
238	$IP -6 route get fibmatch 2001:db8:3::1 | \
239		grep $up_dev | grep -q "dead linkdown"
240	log_test $? 1 "IPv6 flags on up device"
241}
242
243fib_down_multipath_test()
244{
245	echo
246	echo "Admin down multipath"
247
248	setup
249
250	set -e
251	$IP link add dummy1 type dummy
252	$IP link set dev dummy1 up
253
254	$IP address add 192.0.2.1/24 dev dummy1
255	$IP -6 address add 2001:db8:2::1/64 dev dummy1
256
257	$IP route add 203.0.113.0/24 \
258		nexthop via 198.51.100.2 dev dummy0 \
259		nexthop via 192.0.2.2 dev dummy1
260	$IP -6 route add 2001:db8:3::/64 \
261		nexthop via 2001:db8:1::2 dev dummy0 \
262		nexthop via 2001:db8:2::2 dev dummy1
263	set +e
264
265	echo "    Verify start point"
266	$IP route get fibmatch 203.0.113.1 &> /dev/null
267	log_test $? 0 "IPv4 fibmatch"
268
269	$IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
270	log_test $? 0 "IPv6 fibmatch"
271
272	set -e
273	$IP link set dev dummy0 down
274	set +e
275
276	echo "    One device down, one up"
277	fib_down_multipath_test_do "dummy0" "dummy1"
278
279	set -e
280	$IP link set dev dummy0 up
281	$IP link set dev dummy1 down
282	set +e
283
284	echo "    Other device down and up"
285	fib_down_multipath_test_do "dummy1" "dummy0"
286
287	set -e
288	$IP link set dev dummy0 down
289	set +e
290
291	echo "    Both devices down"
292	$IP route get fibmatch 203.0.113.1 &> /dev/null
293	log_test $? 2 "IPv4 fibmatch"
294	$IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
295	log_test $? 2 "IPv6 fibmatch"
296
297	$IP link del dev dummy1
298	cleanup
299}
300
301fib_down_test()
302{
303	fib_down_unicast_test
304	fib_down_multipath_test
305}
306
307# Local routes should not be affected when carrier changes.
308fib_carrier_local_test()
309{
310	echo
311	echo "Local carrier tests - single path"
312
313	setup
314
315	set -e
316	$IP link set dev dummy0 carrier on
317	set +e
318
319	echo "    Start point"
320	$IP route get fibmatch 198.51.100.1 &> /dev/null
321	log_test $? 0 "IPv4 fibmatch"
322	$IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
323	log_test $? 0 "IPv6 fibmatch"
324
325	$IP route get fibmatch 198.51.100.1 | \
326		grep -q "linkdown"
327	log_test $? 1 "IPv4 - no linkdown flag"
328	$IP -6 route get fibmatch 2001:db8:1::1 | \
329		grep -q "linkdown"
330	log_test $? 1 "IPv6 - no linkdown flag"
331
332	set -e
333	$IP link set dev dummy0 carrier off
334	sleep 1
335	set +e
336
337	echo "    Carrier off on nexthop"
338	$IP route get fibmatch 198.51.100.1 &> /dev/null
339	log_test $? 0 "IPv4 fibmatch"
340	$IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
341	log_test $? 0 "IPv6 fibmatch"
342
343	$IP route get fibmatch 198.51.100.1 | \
344		grep -q "linkdown"
345	log_test $? 1 "IPv4 - linkdown flag set"
346	$IP -6 route get fibmatch 2001:db8:1::1 | \
347		grep -q "linkdown"
348	log_test $? 1 "IPv6 - linkdown flag set"
349
350	set -e
351	$IP address add 192.0.2.1/24 dev dummy0
352	$IP -6 address add 2001:db8:2::1/64 dev dummy0
353	set +e
354
355	echo "    Route to local address with carrier down"
356	$IP route get fibmatch 192.0.2.1 &> /dev/null
357	log_test $? 0 "IPv4 fibmatch"
358	$IP -6 route get fibmatch 2001:db8:2::1 &> /dev/null
359	log_test $? 0 "IPv6 fibmatch"
360
361	$IP route get fibmatch 192.0.2.1 | \
362		grep -q "linkdown"
363	log_test $? 1 "IPv4 linkdown flag set"
364	$IP -6 route get fibmatch 2001:db8:2::1 | \
365		grep -q "linkdown"
366	log_test $? 1 "IPv6 linkdown flag set"
367
368	cleanup
369}
370
371fib_carrier_unicast_test()
372{
373	ret=0
374
375	echo
376	echo "Single path route carrier test"
377
378	setup
379
380	set -e
381	$IP link set dev dummy0 carrier on
382	set +e
383
384	echo "    Start point"
385	$IP route get fibmatch 198.51.100.2 &> /dev/null
386	log_test $? 0 "IPv4 fibmatch"
387	$IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
388	log_test $? 0 "IPv6 fibmatch"
389
390	$IP route get fibmatch 198.51.100.2 | \
391		grep -q "linkdown"
392	log_test $? 1 "IPv4 no linkdown flag"
393	$IP -6 route get fibmatch 2001:db8:1::2 | \
394		grep -q "linkdown"
395	log_test $? 1 "IPv6 no linkdown flag"
396
397	set -e
398	$IP link set dev dummy0 carrier off
399	sleep 1
400	set +e
401
402	echo "    Carrier down"
403	$IP route get fibmatch 198.51.100.2 &> /dev/null
404	log_test $? 0 "IPv4 fibmatch"
405	$IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
406	log_test $? 0 "IPv6 fibmatch"
407
408	$IP route get fibmatch 198.51.100.2 | \
409		grep -q "linkdown"
410	log_test $? 0 "IPv4 linkdown flag set"
411	$IP -6 route get fibmatch 2001:db8:1::2 | \
412		grep -q "linkdown"
413	log_test $? 0 "IPv6 linkdown flag set"
414
415	set -e
416	$IP address add 192.0.2.1/24 dev dummy0
417	$IP -6 address add 2001:db8:2::1/64 dev dummy0
418	set +e
419
420	echo "    Second address added with carrier down"
421	$IP route get fibmatch 192.0.2.2 &> /dev/null
422	log_test $? 0 "IPv4 fibmatch"
423	$IP -6 route get fibmatch 2001:db8:2::2 &> /dev/null
424	log_test $? 0 "IPv6 fibmatch"
425
426	$IP route get fibmatch 192.0.2.2 | \
427		grep -q "linkdown"
428	log_test $? 0 "IPv4 linkdown flag set"
429	$IP -6 route get fibmatch 2001:db8:2::2 | \
430		grep -q "linkdown"
431	log_test $? 0 "IPv6 linkdown flag set"
432
433	cleanup
434}
435
436fib_carrier_test()
437{
438	fib_carrier_local_test
439	fib_carrier_unicast_test
440}
441
442fib_rp_filter_test()
443{
444	echo
445	echo "IPv4 rp_filter tests"
446
447	setup
448
449	set -e
450	ip netns add ns2
451	ip netns set ns2 auto
452
453	ip -netns ns2 link set dev lo up
454
455	$IP link add name veth1 type veth peer name veth2
456	$IP link set dev veth2 netns ns2
457	$IP address add 192.0.2.1/24 dev veth1
458	ip -netns ns2 address add 192.0.2.1/24 dev veth2
459	$IP link set dev veth1 up
460	ip -netns ns2 link set dev veth2 up
461
462	$IP link set dev lo address 52:54:00:6a:c7:5e
463	$IP link set dev veth1 address 52:54:00:6a:c7:5e
464	ip -netns ns2 link set dev lo address 52:54:00:6a:c7:5e
465	ip -netns ns2 link set dev veth2 address 52:54:00:6a:c7:5e
466
467	# 1. (ns2) redirect lo's egress to veth2's egress
468	ip netns exec ns2 tc qdisc add dev lo parent root handle 1: fq_codel
469	ip netns exec ns2 tc filter add dev lo parent 1: protocol arp basic \
470		action mirred egress redirect dev veth2
471	ip netns exec ns2 tc filter add dev lo parent 1: protocol ip basic \
472		action mirred egress redirect dev veth2
473
474	# 2. (ns1) redirect veth1's ingress to lo's ingress
475	$NS_EXEC tc qdisc add dev veth1 ingress
476	$NS_EXEC tc filter add dev veth1 ingress protocol arp basic \
477		action mirred ingress redirect dev lo
478	$NS_EXEC tc filter add dev veth1 ingress protocol ip basic \
479		action mirred ingress redirect dev lo
480
481	# 3. (ns1) redirect lo's egress to veth1's egress
482	$NS_EXEC tc qdisc add dev lo parent root handle 1: fq_codel
483	$NS_EXEC tc filter add dev lo parent 1: protocol arp basic \
484		action mirred egress redirect dev veth1
485	$NS_EXEC tc filter add dev lo parent 1: protocol ip basic \
486		action mirred egress redirect dev veth1
487
488	# 4. (ns2) redirect veth2's ingress to lo's ingress
489	ip netns exec ns2 tc qdisc add dev veth2 ingress
490	ip netns exec ns2 tc filter add dev veth2 ingress protocol arp basic \
491		action mirred ingress redirect dev lo
492	ip netns exec ns2 tc filter add dev veth2 ingress protocol ip basic \
493		action mirred ingress redirect dev lo
494
495	$NS_EXEC sysctl -qw net.ipv4.conf.all.rp_filter=1
496	$NS_EXEC sysctl -qw net.ipv4.conf.all.accept_local=1
497	$NS_EXEC sysctl -qw net.ipv4.conf.all.route_localnet=1
498	ip netns exec ns2 sysctl -qw net.ipv4.conf.all.rp_filter=1
499	ip netns exec ns2 sysctl -qw net.ipv4.conf.all.accept_local=1
500	ip netns exec ns2 sysctl -qw net.ipv4.conf.all.route_localnet=1
501	set +e
502
503	run_cmd "ip netns exec ns2 ping -w1 -c1 192.0.2.1"
504	log_test $? 0 "rp_filter passes local packets"
505
506	run_cmd "ip netns exec ns2 ping -w1 -c1 127.0.0.1"
507	log_test $? 0 "rp_filter passes loopback packets"
508
509	cleanup
510}
511
512################################################################################
513# Tests on nexthop spec
514
515# run 'ip route add' with given spec
516add_rt()
517{
518	local desc="$1"
519	local erc=$2
520	local vrf=$3
521	local pfx=$4
522	local gw=$5
523	local dev=$6
524	local cmd out rc
525
526	[ "$vrf" = "-" ] && vrf="default"
527	[ -n "$gw" ] && gw="via $gw"
528	[ -n "$dev" ] && dev="dev $dev"
529
530	cmd="$IP route add vrf $vrf $pfx $gw $dev"
531	if [ "$VERBOSE" = "1" ]; then
532		printf "\n    COMMAND: $cmd\n"
533	fi
534
535	out=$(eval $cmd 2>&1)
536	rc=$?
537	if [ "$VERBOSE" = "1" -a -n "$out" ]; then
538		echo "    $out"
539	fi
540	log_test $rc $erc "$desc"
541}
542
543fib4_nexthop()
544{
545	echo
546	echo "IPv4 nexthop tests"
547
548	echo "<<< write me >>>"
549}
550
551fib6_nexthop()
552{
553	local lldummy=$(get_linklocal dummy0)
554	local llv1=$(get_linklocal dummy0)
555
556	if [ -z "$lldummy" ]; then
557		echo "Failed to get linklocal address for dummy0"
558		return 1
559	fi
560	if [ -z "$llv1" ]; then
561		echo "Failed to get linklocal address for veth1"
562		return 1
563	fi
564
565	echo
566	echo "IPv6 nexthop tests"
567
568	add_rt "Directly connected nexthop, unicast address" 0 \
569		- 2001:db8:101::/64 2001:db8:1::2
570	add_rt "Directly connected nexthop, unicast address with device" 0 \
571		- 2001:db8:102::/64 2001:db8:1::2 "dummy0"
572	add_rt "Gateway is linklocal address" 0 \
573		- 2001:db8:103::1/64 $llv1 "veth0"
574
575	# fails because LL address requires a device
576	add_rt "Gateway is linklocal address, no device" 2 \
577		- 2001:db8:104::1/64 $llv1
578
579	# local address can not be a gateway
580	add_rt "Gateway can not be local unicast address" 2 \
581		- 2001:db8:105::/64 2001:db8:1::1
582	add_rt "Gateway can not be local unicast address, with device" 2 \
583		- 2001:db8:106::/64 2001:db8:1::1 "dummy0"
584	add_rt "Gateway can not be a local linklocal address" 2 \
585		- 2001:db8:107::1/64 $lldummy "dummy0"
586
587	# VRF tests
588	add_rt "Gateway can be local address in a VRF" 0 \
589		- 2001:db8:108::/64 2001:db8:51::2
590	add_rt "Gateway can be local address in a VRF, with device" 0 \
591		- 2001:db8:109::/64 2001:db8:51::2 "veth0"
592	add_rt "Gateway can be local linklocal address in a VRF" 0 \
593		- 2001:db8:110::1/64 $llv1 "veth0"
594
595	add_rt "Redirect to VRF lookup" 0 \
596		- 2001:db8:111::/64 "" "red"
597
598	add_rt "VRF route, gateway can be local address in default VRF" 0 \
599		red 2001:db8:112::/64 2001:db8:51::1
600
601	# local address in same VRF fails
602	add_rt "VRF route, gateway can not be a local address" 2 \
603		red 2001:db8:113::1/64 2001:db8:2::1
604	add_rt "VRF route, gateway can not be a local addr with device" 2 \
605		red 2001:db8:114::1/64 2001:db8:2::1 "dummy1"
606}
607
608# Default VRF:
609#   dummy0 - 198.51.100.1/24 2001:db8:1::1/64
610#   veth0  - 192.0.2.1/24    2001:db8:51::1/64
611#
612# VRF red:
613#   dummy1 - 192.168.2.1/24 2001:db8:2::1/64
614#   veth1  - 192.0.2.2/24   2001:db8:51::2/64
615#
616#  [ dummy0   veth0 ]--[ veth1   dummy1 ]
617
618fib_nexthop_test()
619{
620	setup
621
622	set -e
623
624	$IP -4 rule add pref 32765 table local
625	$IP -4 rule del pref 0
626	$IP -6 rule add pref 32765 table local
627	$IP -6 rule del pref 0
628
629	$IP link add red type vrf table 1
630	$IP link set red up
631	$IP -4 route add vrf red unreachable default metric 4278198272
632	$IP -6 route add vrf red unreachable default metric 4278198272
633
634	$IP link add veth0 type veth peer name veth1
635	$IP link set dev veth0 up
636	$IP address add 192.0.2.1/24 dev veth0
637	$IP -6 address add 2001:db8:51::1/64 dev veth0
638
639	$IP link set dev veth1 vrf red up
640	$IP address add 192.0.2.2/24 dev veth1
641	$IP -6 address add 2001:db8:51::2/64 dev veth1
642
643	$IP link add dummy1 type dummy
644	$IP link set dev dummy1 vrf red up
645	$IP address add 192.168.2.1/24 dev dummy1
646	$IP -6 address add 2001:db8:2::1/64 dev dummy1
647	set +e
648
649	sleep 1
650	fib4_nexthop
651	fib6_nexthop
652
653	(
654	$IP link del dev dummy1
655	$IP link del veth0
656	$IP link del red
657	) 2>/dev/null
658	cleanup
659}
660
661fib6_notify_test()
662{
663	setup
664
665	echo
666	echo "Fib6 info length calculation in route notify test"
667	set -e
668
669	for i in 10 20 30 40 50 60 70;
670	do
671		$IP link add dummy_$i type dummy
672		$IP link set dev dummy_$i up
673		$IP -6 address add 2001:$i::1/64 dev dummy_$i
674	done
675
676	$NS_EXEC ip monitor route &> errors.txt &
677	sleep 2
678
679	$IP -6 route add 2001::/64 \
680                nexthop via 2001:10::2 dev dummy_10 \
681                nexthop encap ip6 dst 2002::20 via 2001:20::2 dev dummy_20 \
682                nexthop encap ip6 dst 2002::30 via 2001:30::2 dev dummy_30 \
683                nexthop encap ip6 dst 2002::40 via 2001:40::2 dev dummy_40 \
684                nexthop encap ip6 dst 2002::50 via 2001:50::2 dev dummy_50 \
685                nexthop encap ip6 dst 2002::60 via 2001:60::2 dev dummy_60 \
686                nexthop encap ip6 dst 2002::70 via 2001:70::2 dev dummy_70
687
688	set +e
689
690	err=`cat errors.txt |grep "Message too long"`
691	if [ -z "$err" ];then
692		ret=0
693	else
694		ret=1
695	fi
696
697	log_test $ret 0 "ipv6 route add notify"
698
699	{ kill %% && wait %%; } 2>/dev/null
700
701	#rm errors.txt
702
703	cleanup &> /dev/null
704}
705
706
707fib_notify_test()
708{
709	setup
710
711	echo
712	echo "Fib4 info length calculation in route notify test"
713
714	set -e
715
716	for i in 10 20 30 40 50 60 70;
717	do
718		$IP link add dummy_$i type dummy
719		$IP link set dev dummy_$i up
720		$IP address add 20.20.$i.2/24 dev dummy_$i
721	done
722
723	$NS_EXEC ip monitor route &> errors.txt &
724	sleep 2
725
726        $IP route add 10.0.0.0/24 \
727                nexthop via 20.20.10.1 dev dummy_10 \
728                nexthop encap ip dst 192.168.10.20 via 20.20.20.1 dev dummy_20 \
729                nexthop encap ip dst 192.168.10.30 via 20.20.30.1 dev dummy_30 \
730                nexthop encap ip dst 192.168.10.40 via 20.20.40.1 dev dummy_40 \
731                nexthop encap ip dst 192.168.10.50 via 20.20.50.1 dev dummy_50 \
732                nexthop encap ip dst 192.168.10.60 via 20.20.60.1 dev dummy_60 \
733                nexthop encap ip dst 192.168.10.70 via 20.20.70.1 dev dummy_70
734
735	set +e
736
737	err=`cat errors.txt |grep "Message too long"`
738	if [ -z "$err" ];then
739		ret=0
740	else
741		ret=1
742	fi
743
744	log_test $ret 0 "ipv4 route add notify"
745
746	{ kill %% && wait %%; } 2>/dev/null
747
748	rm  errors.txt
749
750	cleanup &> /dev/null
751}
752
753fib6_gc_test()
754{
755	setup
756
757	echo
758	echo "Fib6 garbage collection test"
759	set -e
760
761	EXPIRE=3
762
763	# Check expiration of routes every $EXPIRE seconds (GC)
764	$NS_EXEC sysctl -wq net.ipv6.route.gc_interval=$EXPIRE
765
766	$IP link add dummy_10 type dummy
767	$IP link set dev dummy_10 up
768	$IP -6 address add 2001:10::1/64 dev dummy_10
769
770	$NS_EXEC sysctl -wq net.ipv6.route.flush=1
771
772	# Temporary routes
773	for i in $(seq 1 1000); do
774	    # Expire route after $EXPIRE seconds
775	    $IP -6 route add 2001:20::$i \
776		via 2001:10::2 dev dummy_10 expires $EXPIRE
777	done
778	sleep $(($EXPIRE * 2))
779	N_EXP_SLEEP=$($IP -6 route list |grep expires|wc -l)
780	if [ $N_EXP_SLEEP -ne 0 ]; then
781	    echo "FAIL: expected 0 routes with expires, got $N_EXP_SLEEP"
782	    ret=1
783	else
784	    ret=0
785	fi
786
787	# Permanent routes
788	for i in $(seq 1 5000); do
789	    $IP -6 route add 2001:30::$i \
790		via 2001:10::2 dev dummy_10
791	done
792	# Temporary routes
793	for i in $(seq 1 1000); do
794	    # Expire route after $EXPIRE seconds
795	    $IP -6 route add 2001:20::$i \
796		via 2001:10::2 dev dummy_10 expires $EXPIRE
797	done
798	sleep $(($EXPIRE * 2))
799	N_EXP_SLEEP=$($IP -6 route list |grep expires|wc -l)
800	if [ $N_EXP_SLEEP -ne 0 ]; then
801	    echo "FAIL: expected 0 routes with expires," \
802		 "got $N_EXP_SLEEP (5000 permanent routes)"
803	    ret=1
804	else
805	    ret=0
806	fi
807
808	set +e
809
810	log_test $ret 0 "ipv6 route garbage collection"
811
812	cleanup &> /dev/null
813}
814
815fib_suppress_test()
816{
817	echo
818	echo "FIB rule with suppress_prefixlength"
819	setup
820
821	$IP link add dummy1 type dummy
822	$IP link set dummy1 up
823	$IP -6 route add default dev dummy1
824	$IP -6 rule add table main suppress_prefixlength 0
825	ping -f -c 1000 -W 1 1234::1 >/dev/null 2>&1
826	$IP -6 rule del table main suppress_prefixlength 0
827	$IP link del dummy1
828
829	# If we got here without crashing, we're good.
830	log_test 0 0 "FIB rule suppress test"
831
832	cleanup
833}
834
835################################################################################
836# Tests on route add and replace
837
838run_cmd()
839{
840	local cmd="$1"
841	local out
842	local stderr="2>/dev/null"
843
844	if [ "$VERBOSE" = "1" ]; then
845		printf "    COMMAND: $cmd\n"
846		stderr=
847	fi
848
849	out=$(eval $cmd $stderr)
850	rc=$?
851	if [ "$VERBOSE" = "1" -a -n "$out" ]; then
852		echo "    $out"
853	fi
854
855	[ "$VERBOSE" = "1" ] && echo
856
857	return $rc
858}
859
860check_expected()
861{
862	local out="$1"
863	local expected="$2"
864	local rc=0
865
866	[ "${out}" = "${expected}" ] && return 0
867
868	if [ -z "${out}" ]; then
869		if [ "$VERBOSE" = "1" ]; then
870			printf "\nNo route entry found\n"
871			printf "Expected:\n"
872			printf "    ${expected}\n"
873		fi
874		return 1
875	fi
876
877	# tricky way to convert output to 1-line without ip's
878	# messy '\'; this drops all extra white space
879	out=$(echo ${out})
880	if [ "${out}" != "${expected}" ]; then
881		rc=1
882		if [ "${VERBOSE}" = "1" ]; then
883			printf "    Unexpected route entry. Have:\n"
884			printf "        ${out}\n"
885			printf "    Expected:\n"
886			printf "        ${expected}\n\n"
887		fi
888	fi
889
890	return $rc
891}
892
893# add route for a prefix, flushing any existing routes first
894# expected to be the first step of a test
895add_route6()
896{
897	local pfx="$1"
898	local nh="$2"
899	local out
900
901	if [ "$VERBOSE" = "1" ]; then
902		echo
903		echo "    ##################################################"
904		echo
905	fi
906
907	run_cmd "$IP -6 ro flush ${pfx}"
908	[ $? -ne 0 ] && exit 1
909
910	out=$($IP -6 ro ls match ${pfx})
911	if [ -n "$out" ]; then
912		echo "Failed to flush routes for prefix used for tests."
913		exit 1
914	fi
915
916	run_cmd "$IP -6 ro add ${pfx} ${nh}"
917	if [ $? -ne 0 ]; then
918		echo "Failed to add initial route for test."
919		exit 1
920	fi
921}
922
923# add initial route - used in replace route tests
924add_initial_route6()
925{
926	add_route6 "2001:db8:104::/64" "$1"
927}
928
929check_route6()
930{
931	local pfx
932	local expected="$1"
933	local out
934	local rc=0
935
936	set -- $expected
937	pfx=$1
938
939	out=$($IP -6 ro ls match ${pfx} | sed -e 's/ pref medium//')
940	check_expected "${out}" "${expected}"
941}
942
943route_cleanup()
944{
945	$IP li del red 2>/dev/null
946	$IP li del dummy1 2>/dev/null
947	$IP li del veth1 2>/dev/null
948	$IP li del veth3 2>/dev/null
949
950	cleanup &> /dev/null
951}
952
953route_setup()
954{
955	route_cleanup
956	setup
957
958	[ "${VERBOSE}" = "1" ] && set -x
959	set -e
960
961	ip netns add ns2
962	ip netns set ns2 auto
963	ip -netns ns2 link set dev lo up
964	ip netns exec ns2 sysctl -qw net.ipv4.ip_forward=1
965	ip netns exec ns2 sysctl -qw net.ipv6.conf.all.forwarding=1
966
967	$IP li add veth1 type veth peer name veth2
968	$IP li add veth3 type veth peer name veth4
969
970	$IP li set veth1 up
971	$IP li set veth3 up
972	$IP li set veth2 netns ns2 up
973	$IP li set veth4 netns ns2 up
974	ip -netns ns2 li add dummy1 type dummy
975	ip -netns ns2 li set dummy1 up
976
977	$IP -6 addr add 2001:db8:101::1/64 dev veth1 nodad
978	$IP -6 addr add 2001:db8:103::1/64 dev veth3 nodad
979	$IP addr add 172.16.101.1/24 dev veth1
980	$IP addr add 172.16.103.1/24 dev veth3
981
982	ip -netns ns2 -6 addr add 2001:db8:101::2/64 dev veth2 nodad
983	ip -netns ns2 -6 addr add 2001:db8:103::2/64 dev veth4 nodad
984	ip -netns ns2 -6 addr add 2001:db8:104::1/64 dev dummy1 nodad
985
986	ip -netns ns2 addr add 172.16.101.2/24 dev veth2
987	ip -netns ns2 addr add 172.16.103.2/24 dev veth4
988	ip -netns ns2 addr add 172.16.104.1/24 dev dummy1
989
990	set +e
991}
992
993# assumption is that basic add of a single path route works
994# otherwise just adding an address on an interface is broken
995ipv6_rt_add()
996{
997	local rc
998
999	echo
1000	echo "IPv6 route add / append tests"
1001
1002	# route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1003	add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1004	run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2"
1005	log_test $? 2 "Attempt to add duplicate route - gw"
1006
1007	# route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1008	add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1009	run_cmd "$IP -6 ro add 2001:db8:104::/64 dev veth3"
1010	log_test $? 2 "Attempt to add duplicate route - dev only"
1011
1012	# route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1013	add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1014	run_cmd "$IP -6 ro add unreachable 2001:db8:104::/64"
1015	log_test $? 2 "Attempt to add duplicate route - reject route"
1016
1017	# route append with same prefix adds a new route
1018	# - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
1019	add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1020	run_cmd "$IP -6 ro append 2001:db8:104::/64 via 2001:db8:103::2"
1021	check_route6 "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1022	log_test $? 0 "Append nexthop to existing route - gw"
1023
1024	# insert mpath directly
1025	add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1026	check_route6  "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1027	log_test $? 0 "Add multipath route"
1028
1029	add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1030	run_cmd "$IP -6 ro add 2001:db8:104::/64 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1031	log_test $? 2 "Attempt to add duplicate multipath route"
1032
1033	# insert of a second route without append but different metric
1034	add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1035	run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2 metric 512"
1036	rc=$?
1037	if [ $rc -eq 0 ]; then
1038		run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::3 metric 256"
1039		rc=$?
1040	fi
1041	log_test $rc 0 "Route add with different metrics"
1042
1043	run_cmd "$IP -6 ro del 2001:db8:104::/64 metric 512"
1044	rc=$?
1045	if [ $rc -eq 0 ]; then
1046		check_route6 "2001:db8:104::/64 via 2001:db8:103::3 dev veth3 metric 256 2001:db8:104::/64 via 2001:db8:101::2 dev veth1 metric 1024"
1047		rc=$?
1048	fi
1049	log_test $rc 0 "Route delete with metric"
1050}
1051
1052ipv6_rt_replace_single()
1053{
1054	# single path with single path
1055	#
1056	add_initial_route6 "via 2001:db8:101::2"
1057	run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:103::2"
1058	check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
1059	log_test $? 0 "Single path with single path"
1060
1061	# single path with multipath
1062	#
1063	add_initial_route6 "nexthop via 2001:db8:101::2"
1064	run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::2"
1065	check_route6 "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::3 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1066	log_test $? 0 "Single path with multipath"
1067
1068	# single path with single path using MULTIPATH attribute
1069	#
1070	add_initial_route6 "via 2001:db8:101::2"
1071	run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:103::2"
1072	check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
1073	log_test $? 0 "Single path with single path via multipath attribute"
1074
1075	# route replace fails - invalid nexthop
1076	add_initial_route6 "via 2001:db8:101::2"
1077	run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:104::2"
1078	if [ $? -eq 0 ]; then
1079		# previous command is expected to fail so if it returns 0
1080		# that means the test failed.
1081		log_test 0 1 "Invalid nexthop"
1082	else
1083		check_route6 "2001:db8:104::/64 via 2001:db8:101::2 dev veth1 metric 1024"
1084		log_test $? 0 "Invalid nexthop"
1085	fi
1086
1087	# replace non-existent route
1088	# - note use of change versus replace since ip adds NLM_F_CREATE
1089	#   for replace
1090	add_initial_route6 "via 2001:db8:101::2"
1091	run_cmd "$IP -6 ro change 2001:db8:105::/64 via 2001:db8:101::2"
1092	log_test $? 2 "Single path - replace of non-existent route"
1093}
1094
1095ipv6_rt_replace_mpath()
1096{
1097	# multipath with multipath
1098	add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1099	run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
1100	check_route6  "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::3 dev veth1 weight 1 nexthop via 2001:db8:103::3 dev veth3 weight 1"
1101	log_test $? 0 "Multipath with multipath"
1102
1103	# multipath with single
1104	add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1105	run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:101::3"
1106	check_route6  "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
1107	log_test $? 0 "Multipath with single path"
1108
1109	# multipath with single
1110	add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1111	run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3"
1112	check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
1113	log_test $? 0 "Multipath with single path via multipath attribute"
1114
1115	# multipath with dev-only
1116	add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1117	run_cmd "$IP -6 ro replace 2001:db8:104::/64 dev veth1"
1118	check_route6 "2001:db8:104::/64 dev veth1 metric 1024"
1119	log_test $? 0 "Multipath with dev-only"
1120
1121	# route replace fails - invalid nexthop 1
1122	add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1123	run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:111::3 nexthop via 2001:db8:103::3"
1124	check_route6  "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1125	log_test $? 0 "Multipath - invalid first nexthop"
1126
1127	# route replace fails - invalid nexthop 2
1128	add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1129	run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:113::3"
1130	check_route6  "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1131	log_test $? 0 "Multipath - invalid second nexthop"
1132
1133	# multipath non-existent route
1134	add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1135	run_cmd "$IP -6 ro change 2001:db8:105::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
1136	log_test $? 2 "Multipath - replace of non-existent route"
1137}
1138
1139ipv6_rt_replace()
1140{
1141	echo
1142	echo "IPv6 route replace tests"
1143
1144	ipv6_rt_replace_single
1145	ipv6_rt_replace_mpath
1146}
1147
1148ipv6_rt_dsfield()
1149{
1150	echo
1151	echo "IPv6 route with dsfield tests"
1152
1153	run_cmd "$IP -6 route flush 2001:db8:102::/64"
1154
1155	# IPv6 doesn't support routing based on dsfield
1156	run_cmd "$IP -6 route add 2001:db8:102::/64 dsfield 0x04 via 2001:db8:101::2"
1157	log_test $? 2 "Reject route with dsfield"
1158}
1159
1160ipv6_route_test()
1161{
1162	route_setup
1163
1164	ipv6_rt_add
1165	ipv6_rt_replace
1166	ipv6_rt_dsfield
1167
1168	route_cleanup
1169}
1170
1171ip_addr_metric_check()
1172{
1173	ip addr help 2>&1 | grep -q metric
1174	if [ $? -ne 0 ]; then
1175		echo "iproute2 command does not support metric for addresses. Skipping test"
1176		return 1
1177	fi
1178
1179	return 0
1180}
1181
1182ipv6_addr_metric_test()
1183{
1184	local rc
1185
1186	echo
1187	echo "IPv6 prefix route tests"
1188
1189	ip_addr_metric_check || return 1
1190
1191	setup
1192
1193	set -e
1194	$IP li add dummy1 type dummy
1195	$IP li add dummy2 type dummy
1196	$IP li set dummy1 up
1197	$IP li set dummy2 up
1198
1199	# default entry is metric 256
1200	run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64"
1201	run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64"
1202	set +e
1203
1204	check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 256 2001:db8:104::/64 dev dummy2 proto kernel metric 256"
1205	log_test $? 0 "Default metric"
1206
1207	set -e
1208	run_cmd "$IP -6 addr flush dev dummy1"
1209	run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64 metric 257"
1210	set +e
1211
1212	check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 256 2001:db8:104::/64 dev dummy1 proto kernel metric 257"
1213	log_test $? 0 "User specified metric on first device"
1214
1215	set -e
1216	run_cmd "$IP -6 addr flush dev dummy2"
1217	run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64 metric 258"
1218	set +e
1219
1220	check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 257 2001:db8:104::/64 dev dummy2 proto kernel metric 258"
1221	log_test $? 0 "User specified metric on second device"
1222
1223	run_cmd "$IP -6 addr del dev dummy1 2001:db8:104::1/64 metric 257"
1224	rc=$?
1225	if [ $rc -eq 0 ]; then
1226		check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 258"
1227		rc=$?
1228	fi
1229	log_test $rc 0 "Delete of address on first device"
1230
1231	run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::2/64 metric 259"
1232	rc=$?
1233	if [ $rc -eq 0 ]; then
1234		check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
1235		rc=$?
1236	fi
1237	log_test $rc 0 "Modify metric of address"
1238
1239	# verify prefix route removed on down
1240	run_cmd "ip netns exec ns1 sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1"
1241	run_cmd "$IP li set dev dummy2 down"
1242	rc=$?
1243	if [ $rc -eq 0 ]; then
1244		out=$($IP -6 ro ls match 2001:db8:104::/64)
1245		check_expected "${out}" ""
1246		rc=$?
1247	fi
1248	log_test $rc 0 "Prefix route removed on link down"
1249
1250	# verify prefix route re-inserted with assigned metric
1251	run_cmd "$IP li set dev dummy2 up"
1252	rc=$?
1253	if [ $rc -eq 0 ]; then
1254		check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
1255		rc=$?
1256	fi
1257	log_test $rc 0 "Prefix route with metric on link up"
1258
1259	# verify peer metric added correctly
1260	set -e
1261	run_cmd "$IP -6 addr flush dev dummy2"
1262	run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::1 peer 2001:db8:104::2 metric 260"
1263	set +e
1264
1265	check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 260"
1266	log_test $? 0 "Set metric with peer route on local side"
1267	check_route6 "2001:db8:104::2 dev dummy2 proto kernel metric 260"
1268	log_test $? 0 "Set metric with peer route on peer side"
1269
1270	set -e
1271	run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::1 peer 2001:db8:104::3 metric 261"
1272	set +e
1273
1274	check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 261"
1275	log_test $? 0 "Modify metric and peer address on local side"
1276	check_route6 "2001:db8:104::3 dev dummy2 proto kernel metric 261"
1277	log_test $? 0 "Modify metric and peer address on peer side"
1278
1279	$IP li del dummy1
1280	$IP li del dummy2
1281	cleanup
1282}
1283
1284ipv6_route_metrics_test()
1285{
1286	local rc
1287
1288	echo
1289	echo "IPv6 routes with metrics"
1290
1291	route_setup
1292
1293	#
1294	# single path with metrics
1295	#
1296	run_cmd "$IP -6 ro add 2001:db8:111::/64 via 2001:db8:101::2 mtu 1400"
1297	rc=$?
1298	if [ $rc -eq 0 ]; then
1299		check_route6  "2001:db8:111::/64 via 2001:db8:101::2 dev veth1 metric 1024 mtu 1400"
1300		rc=$?
1301	fi
1302	log_test $rc 0 "Single path route with mtu metric"
1303
1304
1305	#
1306	# multipath via separate routes with metrics
1307	#
1308	run_cmd "$IP -6 ro add 2001:db8:112::/64 via 2001:db8:101::2 mtu 1400"
1309	run_cmd "$IP -6 ro append 2001:db8:112::/64 via 2001:db8:103::2"
1310	rc=$?
1311	if [ $rc -eq 0 ]; then
1312		check_route6 "2001:db8:112::/64 metric 1024 mtu 1400 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1313		rc=$?
1314	fi
1315	log_test $rc 0 "Multipath route via 2 single routes with mtu metric on first"
1316
1317	# second route is coalesced to first to make a multipath route.
1318	# MTU of the second path is hidden from display!
1319	run_cmd "$IP -6 ro add 2001:db8:113::/64 via 2001:db8:101::2"
1320	run_cmd "$IP -6 ro append 2001:db8:113::/64 via 2001:db8:103::2 mtu 1400"
1321	rc=$?
1322	if [ $rc -eq 0 ]; then
1323		check_route6 "2001:db8:113::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1324		rc=$?
1325	fi
1326	log_test $rc 0 "Multipath route via 2 single routes with mtu metric on 2nd"
1327
1328	run_cmd "$IP -6 ro del 2001:db8:113::/64 via 2001:db8:101::2"
1329	if [ $? -eq 0 ]; then
1330		check_route6 "2001:db8:113::/64 via 2001:db8:103::2 dev veth3 metric 1024 mtu 1400"
1331		log_test $? 0 "    MTU of second leg"
1332	fi
1333
1334	#
1335	# multipath with metrics
1336	#
1337	run_cmd "$IP -6 ro add 2001:db8:115::/64 mtu 1400 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1338	rc=$?
1339	if [ $rc -eq 0 ]; then
1340		check_route6  "2001:db8:115::/64 metric 1024 mtu 1400 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1341		rc=$?
1342	fi
1343	log_test $rc 0 "Multipath route with mtu metric"
1344
1345	$IP -6 ro add 2001:db8:104::/64 via 2001:db8:101::2 mtu 1300
1346	run_cmd "ip netns exec ns1 ${ping6} -w1 -c1 -s 1500 2001:db8:104::1"
1347	log_test $? 0 "Using route with mtu metric"
1348
1349	run_cmd "$IP -6 ro add 2001:db8:114::/64 via  2001:db8:101::2  congctl lock foo"
1350	log_test $? 2 "Invalid metric (fails metric_convert)"
1351
1352	route_cleanup
1353}
1354
1355# add route for a prefix, flushing any existing routes first
1356# expected to be the first step of a test
1357add_route()
1358{
1359	local pfx="$1"
1360	local nh="$2"
1361	local out
1362
1363	if [ "$VERBOSE" = "1" ]; then
1364		echo
1365		echo "    ##################################################"
1366		echo
1367	fi
1368
1369	run_cmd "$IP ro flush ${pfx}"
1370	[ $? -ne 0 ] && exit 1
1371
1372	out=$($IP ro ls match ${pfx})
1373	if [ -n "$out" ]; then
1374		echo "Failed to flush routes for prefix used for tests."
1375		exit 1
1376	fi
1377
1378	run_cmd "$IP ro add ${pfx} ${nh}"
1379	if [ $? -ne 0 ]; then
1380		echo "Failed to add initial route for test."
1381		exit 1
1382	fi
1383}
1384
1385# add initial route - used in replace route tests
1386add_initial_route()
1387{
1388	add_route "172.16.104.0/24" "$1"
1389}
1390
1391check_route()
1392{
1393	local pfx
1394	local expected="$1"
1395	local out
1396
1397	set -- $expected
1398	pfx=$1
1399	[ "${pfx}" = "unreachable" ] && pfx=$2
1400
1401	out=$($IP ro ls match ${pfx})
1402	check_expected "${out}" "${expected}"
1403}
1404
1405# assumption is that basic add of a single path route works
1406# otherwise just adding an address on an interface is broken
1407ipv4_rt_add()
1408{
1409	local rc
1410
1411	echo
1412	echo "IPv4 route add / append tests"
1413
1414	# route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1415	add_route "172.16.104.0/24" "via 172.16.101.2"
1416	run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2"
1417	log_test $? 2 "Attempt to add duplicate route - gw"
1418
1419	# route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1420	add_route "172.16.104.0/24" "via 172.16.101.2"
1421	run_cmd "$IP ro add 172.16.104.0/24 dev veth3"
1422	log_test $? 2 "Attempt to add duplicate route - dev only"
1423
1424	# route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1425	add_route "172.16.104.0/24" "via 172.16.101.2"
1426	run_cmd "$IP ro add unreachable 172.16.104.0/24"
1427	log_test $? 2 "Attempt to add duplicate route - reject route"
1428
1429	# iproute2 prepend only sets NLM_F_CREATE
1430	# - adds a new route; does NOT convert existing route to ECMP
1431	add_route "172.16.104.0/24" "via 172.16.101.2"
1432	run_cmd "$IP ro prepend 172.16.104.0/24 via 172.16.103.2"
1433	check_route "172.16.104.0/24 via 172.16.103.2 dev veth3 172.16.104.0/24 via 172.16.101.2 dev veth1"
1434	log_test $? 0 "Add new nexthop for existing prefix"
1435
1436	# route append with same prefix adds a new route
1437	# - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
1438	add_route "172.16.104.0/24" "via 172.16.101.2"
1439	run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
1440	check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 via 172.16.103.2 dev veth3"
1441	log_test $? 0 "Append nexthop to existing route - gw"
1442
1443	add_route "172.16.104.0/24" "via 172.16.101.2"
1444	run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
1445	check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 dev veth3 scope link"
1446	log_test $? 0 "Append nexthop to existing route - dev only"
1447
1448	add_route "172.16.104.0/24" "via 172.16.101.2"
1449	run_cmd "$IP ro append unreachable 172.16.104.0/24"
1450	check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 unreachable 172.16.104.0/24"
1451	log_test $? 0 "Append nexthop to existing route - reject route"
1452
1453	run_cmd "$IP ro flush 172.16.104.0/24"
1454	run_cmd "$IP ro add unreachable 172.16.104.0/24"
1455	run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
1456	check_route "unreachable 172.16.104.0/24 172.16.104.0/24 via 172.16.103.2 dev veth3"
1457	log_test $? 0 "Append nexthop to existing reject route - gw"
1458
1459	run_cmd "$IP ro flush 172.16.104.0/24"
1460	run_cmd "$IP ro add unreachable 172.16.104.0/24"
1461	run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
1462	check_route "unreachable 172.16.104.0/24 172.16.104.0/24 dev veth3 scope link"
1463	log_test $? 0 "Append nexthop to existing reject route - dev only"
1464
1465	# insert mpath directly
1466	add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1467	check_route  "172.16.104.0/24 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1468	log_test $? 0 "add multipath route"
1469
1470	add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1471	run_cmd "$IP ro add 172.16.104.0/24 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1472	log_test $? 2 "Attempt to add duplicate multipath route"
1473
1474	# insert of a second route without append but different metric
1475	add_route "172.16.104.0/24" "via 172.16.101.2"
1476	run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2 metric 512"
1477	rc=$?
1478	if [ $rc -eq 0 ]; then
1479		run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.3 metric 256"
1480		rc=$?
1481	fi
1482	log_test $rc 0 "Route add with different metrics"
1483
1484	run_cmd "$IP ro del 172.16.104.0/24 metric 512"
1485	rc=$?
1486	if [ $rc -eq 0 ]; then
1487		check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 via 172.16.103.3 dev veth3 metric 256"
1488		rc=$?
1489	fi
1490	log_test $rc 0 "Route delete with metric"
1491}
1492
1493ipv4_rt_replace_single()
1494{
1495	# single path with single path
1496	#
1497	add_initial_route "via 172.16.101.2"
1498	run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.103.2"
1499	check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
1500	log_test $? 0 "Single path with single path"
1501
1502	# single path with multipath
1503	#
1504	add_initial_route "nexthop via 172.16.101.2"
1505	run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.2"
1506	check_route "172.16.104.0/24 nexthop via 172.16.101.3 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1507	log_test $? 0 "Single path with multipath"
1508
1509	# single path with reject
1510	#
1511	add_initial_route "nexthop via 172.16.101.2"
1512	run_cmd "$IP ro replace unreachable 172.16.104.0/24"
1513	check_route "unreachable 172.16.104.0/24"
1514	log_test $? 0 "Single path with reject route"
1515
1516	# single path with single path using MULTIPATH attribute
1517	#
1518	add_initial_route "via 172.16.101.2"
1519	run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.103.2"
1520	check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
1521	log_test $? 0 "Single path with single path via multipath attribute"
1522
1523	# route replace fails - invalid nexthop
1524	add_initial_route "via 172.16.101.2"
1525	run_cmd "$IP ro replace 172.16.104.0/24 via 2001:db8:104::2"
1526	if [ $? -eq 0 ]; then
1527		# previous command is expected to fail so if it returns 0
1528		# that means the test failed.
1529		log_test 0 1 "Invalid nexthop"
1530	else
1531		check_route "172.16.104.0/24 via 172.16.101.2 dev veth1"
1532		log_test $? 0 "Invalid nexthop"
1533	fi
1534
1535	# replace non-existent route
1536	# - note use of change versus replace since ip adds NLM_F_CREATE
1537	#   for replace
1538	add_initial_route "via 172.16.101.2"
1539	run_cmd "$IP ro change 172.16.105.0/24 via 172.16.101.2"
1540	log_test $? 2 "Single path - replace of non-existent route"
1541}
1542
1543ipv4_rt_replace_mpath()
1544{
1545	# multipath with multipath
1546	add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1547	run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
1548	check_route  "172.16.104.0/24 nexthop via 172.16.101.3 dev veth1 weight 1 nexthop via 172.16.103.3 dev veth3 weight 1"
1549	log_test $? 0 "Multipath with multipath"
1550
1551	# multipath with single
1552	add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1553	run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.101.3"
1554	check_route  "172.16.104.0/24 via 172.16.101.3 dev veth1"
1555	log_test $? 0 "Multipath with single path"
1556
1557	# multipath with single
1558	add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1559	run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3"
1560	check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
1561	log_test $? 0 "Multipath with single path via multipath attribute"
1562
1563	# multipath with reject
1564	add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1565	run_cmd "$IP ro replace unreachable 172.16.104.0/24"
1566	check_route "unreachable 172.16.104.0/24"
1567	log_test $? 0 "Multipath with reject route"
1568
1569	# route replace fails - invalid nexthop 1
1570	add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1571	run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.111.3 nexthop via 172.16.103.3"
1572	check_route  "172.16.104.0/24 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1573	log_test $? 0 "Multipath - invalid first nexthop"
1574
1575	# route replace fails - invalid nexthop 2
1576	add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1577	run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.113.3"
1578	check_route  "172.16.104.0/24 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1579	log_test $? 0 "Multipath - invalid second nexthop"
1580
1581	# multipath non-existent route
1582	add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1583	run_cmd "$IP ro change 172.16.105.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
1584	log_test $? 2 "Multipath - replace of non-existent route"
1585}
1586
1587ipv4_rt_replace()
1588{
1589	echo
1590	echo "IPv4 route replace tests"
1591
1592	ipv4_rt_replace_single
1593	ipv4_rt_replace_mpath
1594}
1595
1596# checks that cached input route on VRF port is deleted
1597# when VRF is deleted
1598ipv4_local_rt_cache()
1599{
1600	run_cmd "ip addr add 10.0.0.1/32 dev lo"
1601	run_cmd "ip netns add test-ns"
1602	run_cmd "ip link add veth-outside type veth peer name veth-inside"
1603	run_cmd "ip link add vrf-100 type vrf table 1100"
1604	run_cmd "ip link set veth-outside master vrf-100"
1605	run_cmd "ip link set veth-inside netns test-ns"
1606	run_cmd "ip link set veth-outside up"
1607	run_cmd "ip link set vrf-100 up"
1608	run_cmd "ip route add 10.1.1.1/32 dev veth-outside table 1100"
1609	run_cmd "ip netns exec test-ns ip link set veth-inside up"
1610	run_cmd "ip netns exec test-ns ip addr add 10.1.1.1/32 dev veth-inside"
1611	run_cmd "ip netns exec test-ns ip route add 10.0.0.1/32 dev veth-inside"
1612	run_cmd "ip netns exec test-ns ip route add default via 10.0.0.1"
1613	run_cmd "ip netns exec test-ns ping 10.0.0.1 -c 1 -i 1"
1614	run_cmd "ip link delete vrf-100"
1615
1616	# if we do not hang test is a success
1617	log_test $? 0 "Cached route removed from VRF port device"
1618}
1619
1620ipv4_rt_dsfield()
1621{
1622	echo
1623	echo "IPv4 route with dsfield tests"
1624
1625	run_cmd "$IP route flush 172.16.102.0/24"
1626
1627	# New routes should reject dsfield options that interfere with ECN
1628	run_cmd "$IP route add 172.16.102.0/24 dsfield 0x01 via 172.16.101.2"
1629	log_test $? 2 "Reject route with dsfield 0x01"
1630
1631	run_cmd "$IP route add 172.16.102.0/24 dsfield 0x02 via 172.16.101.2"
1632	log_test $? 2 "Reject route with dsfield 0x02"
1633
1634	run_cmd "$IP route add 172.16.102.0/24 dsfield 0x03 via 172.16.101.2"
1635	log_test $? 2 "Reject route with dsfield 0x03"
1636
1637	# A generic route that doesn't take DSCP into account
1638	run_cmd "$IP route add 172.16.102.0/24 via 172.16.101.2"
1639
1640	# A more specific route for DSCP 0x10
1641	run_cmd "$IP route add 172.16.102.0/24 dsfield 0x10 via 172.16.103.2"
1642
1643	# DSCP 0x10 should match the specific route, no matter the ECN bits
1644	$IP route get fibmatch 172.16.102.1 dsfield 0x10 | \
1645		grep -q "via 172.16.103.2"
1646	log_test $? 0 "IPv4 route with DSCP and ECN:Not-ECT"
1647
1648	$IP route get fibmatch 172.16.102.1 dsfield 0x11 | \
1649		grep -q "via 172.16.103.2"
1650	log_test $? 0 "IPv4 route with DSCP and ECN:ECT(1)"
1651
1652	$IP route get fibmatch 172.16.102.1 dsfield 0x12 | \
1653		grep -q "via 172.16.103.2"
1654	log_test $? 0 "IPv4 route with DSCP and ECN:ECT(0)"
1655
1656	$IP route get fibmatch 172.16.102.1 dsfield 0x13 | \
1657		grep -q "via 172.16.103.2"
1658	log_test $? 0 "IPv4 route with DSCP and ECN:CE"
1659
1660	# Unknown DSCP should match the generic route, no matter the ECN bits
1661	$IP route get fibmatch 172.16.102.1 dsfield 0x14 | \
1662		grep -q "via 172.16.101.2"
1663	log_test $? 0 "IPv4 route with unknown DSCP and ECN:Not-ECT"
1664
1665	$IP route get fibmatch 172.16.102.1 dsfield 0x15 | \
1666		grep -q "via 172.16.101.2"
1667	log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(1)"
1668
1669	$IP route get fibmatch 172.16.102.1 dsfield 0x16 | \
1670		grep -q "via 172.16.101.2"
1671	log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(0)"
1672
1673	$IP route get fibmatch 172.16.102.1 dsfield 0x17 | \
1674		grep -q "via 172.16.101.2"
1675	log_test $? 0 "IPv4 route with unknown DSCP and ECN:CE"
1676
1677	# Null DSCP should match the generic route, no matter the ECN bits
1678	$IP route get fibmatch 172.16.102.1 dsfield 0x00 | \
1679		grep -q "via 172.16.101.2"
1680	log_test $? 0 "IPv4 route with no DSCP and ECN:Not-ECT"
1681
1682	$IP route get fibmatch 172.16.102.1 dsfield 0x01 | \
1683		grep -q "via 172.16.101.2"
1684	log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(1)"
1685
1686	$IP route get fibmatch 172.16.102.1 dsfield 0x02 | \
1687		grep -q "via 172.16.101.2"
1688	log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(0)"
1689
1690	$IP route get fibmatch 172.16.102.1 dsfield 0x03 | \
1691		grep -q "via 172.16.101.2"
1692	log_test $? 0 "IPv4 route with no DSCP and ECN:CE"
1693}
1694
1695ipv4_route_test()
1696{
1697	route_setup
1698
1699	ipv4_rt_add
1700	ipv4_rt_replace
1701	ipv4_local_rt_cache
1702	ipv4_rt_dsfield
1703
1704	route_cleanup
1705}
1706
1707ipv4_addr_metric_test()
1708{
1709	local rc
1710
1711	echo
1712	echo "IPv4 prefix route tests"
1713
1714	ip_addr_metric_check || return 1
1715
1716	setup
1717
1718	set -e
1719	$IP li add dummy1 type dummy
1720	$IP li add dummy2 type dummy
1721	$IP li set dummy1 up
1722	$IP li set dummy2 up
1723
1724	# default entry is metric 256
1725	run_cmd "$IP addr add dev dummy1 172.16.104.1/24"
1726	run_cmd "$IP addr add dev dummy2 172.16.104.2/24"
1727	set +e
1728
1729	check_route "172.16.104.0/24 dev dummy1 proto kernel scope link src 172.16.104.1 172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2"
1730	log_test $? 0 "Default metric"
1731
1732	set -e
1733	run_cmd "$IP addr flush dev dummy1"
1734	run_cmd "$IP addr add dev dummy1 172.16.104.1/24 metric 257"
1735	set +e
1736
1737	check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 172.16.104.0/24 dev dummy1 proto kernel scope link src 172.16.104.1 metric 257"
1738	log_test $? 0 "User specified metric on first device"
1739
1740	set -e
1741	run_cmd "$IP addr flush dev dummy2"
1742	run_cmd "$IP addr add dev dummy2 172.16.104.2/24 metric 258"
1743	set +e
1744
1745	check_route "172.16.104.0/24 dev dummy1 proto kernel scope link src 172.16.104.1 metric 257 172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 258"
1746	log_test $? 0 "User specified metric on second device"
1747
1748	run_cmd "$IP addr del dev dummy1 172.16.104.1/24 metric 257"
1749	rc=$?
1750	if [ $rc -eq 0 ]; then
1751		check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 258"
1752		rc=$?
1753	fi
1754	log_test $rc 0 "Delete of address on first device"
1755
1756	run_cmd "$IP addr change dev dummy2 172.16.104.2/24 metric 259"
1757	rc=$?
1758	if [ $rc -eq 0 ]; then
1759		check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
1760		rc=$?
1761	fi
1762	log_test $rc 0 "Modify metric of address"
1763
1764	# verify prefix route removed on down
1765	run_cmd "$IP li set dev dummy2 down"
1766	rc=$?
1767	if [ $rc -eq 0 ]; then
1768		out=$($IP ro ls match 172.16.104.0/24)
1769		check_expected "${out}" ""
1770		rc=$?
1771	fi
1772	log_test $rc 0 "Prefix route removed on link down"
1773
1774	# verify prefix route re-inserted with assigned metric
1775	run_cmd "$IP li set dev dummy2 up"
1776	rc=$?
1777	if [ $rc -eq 0 ]; then
1778		check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
1779		rc=$?
1780	fi
1781	log_test $rc 0 "Prefix route with metric on link up"
1782
1783	# explicitly check for metric changes on edge scenarios
1784	run_cmd "$IP addr flush dev dummy2"
1785	run_cmd "$IP addr add dev dummy2 172.16.104.0/24 metric 259"
1786	run_cmd "$IP addr change dev dummy2 172.16.104.0/24 metric 260"
1787	rc=$?
1788	if [ $rc -eq 0 ]; then
1789		check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.0 metric 260"
1790		rc=$?
1791	fi
1792	log_test $rc 0 "Modify metric of .0/24 address"
1793
1794	run_cmd "$IP addr flush dev dummy2"
1795	run_cmd "$IP addr add dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 260"
1796	rc=$?
1797	if [ $rc -eq 0 ]; then
1798		check_route "172.16.104.2 dev dummy2 proto kernel scope link src 172.16.104.1 metric 260"
1799		rc=$?
1800	fi
1801	log_test $rc 0 "Set metric of address with peer route"
1802
1803	run_cmd "$IP addr change dev dummy2 172.16.104.1/32 peer 172.16.104.3 metric 261"
1804	rc=$?
1805	if [ $rc -eq 0 ]; then
1806		check_route "172.16.104.3 dev dummy2 proto kernel scope link src 172.16.104.1 metric 261"
1807		rc=$?
1808	fi
1809	log_test $rc 0 "Modify metric and peer address for peer route"
1810
1811	$IP li del dummy1
1812	$IP li del dummy2
1813	cleanup
1814}
1815
1816ipv4_route_metrics_test()
1817{
1818	local rc
1819
1820	echo
1821	echo "IPv4 route add / append tests"
1822
1823	route_setup
1824
1825	run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 mtu 1400"
1826	rc=$?
1827	if [ $rc -eq 0 ]; then
1828		check_route "172.16.111.0/24 via 172.16.101.2 dev veth1 mtu 1400"
1829		rc=$?
1830	fi
1831	log_test $rc 0 "Single path route with mtu metric"
1832
1833
1834	run_cmd "$IP ro add 172.16.112.0/24 mtu 1400 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1835	rc=$?
1836	if [ $rc -eq 0 ]; then
1837		check_route "172.16.112.0/24 mtu 1400 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1838		rc=$?
1839	fi
1840	log_test $rc 0 "Multipath route with mtu metric"
1841
1842	$IP ro add 172.16.104.0/24 via 172.16.101.2 mtu 1300
1843	run_cmd "ip netns exec ns1 ping -w1 -c1 -s 1500 172.16.104.1"
1844	log_test $? 0 "Using route with mtu metric"
1845
1846	run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 congctl lock foo"
1847	log_test $? 2 "Invalid metric (fails metric_convert)"
1848
1849	route_cleanup
1850}
1851
1852ipv4_del_addr_test()
1853{
1854	echo
1855	echo "IPv4 delete address route tests"
1856
1857	setup
1858
1859	set -e
1860	$IP li add dummy1 type dummy
1861	$IP li set dummy1 up
1862	$IP li add dummy2 type dummy
1863	$IP li set dummy2 up
1864	$IP li add red type vrf table 1111
1865	$IP li set red up
1866	$IP ro add vrf red unreachable default
1867	$IP li set dummy2 vrf red
1868
1869	$IP addr add dev dummy1 172.16.104.1/24
1870	$IP addr add dev dummy1 172.16.104.11/24
1871	$IP addr add dev dummy1 172.16.104.12/24
1872	$IP addr add dev dummy1 172.16.104.13/24
1873	$IP addr add dev dummy2 172.16.104.1/24
1874	$IP addr add dev dummy2 172.16.104.11/24
1875	$IP addr add dev dummy2 172.16.104.12/24
1876	$IP route add 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1877	$IP route add 172.16.106.0/24 dev lo src 172.16.104.12
1878	$IP route add table 0 172.16.107.0/24 via 172.16.104.2 src 172.16.104.13
1879	$IP route add vrf red 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1880	$IP route add vrf red 172.16.106.0/24 dev lo src 172.16.104.12
1881	set +e
1882
1883	# removing address from device in vrf should only remove route from vrf table
1884	echo "    Regular FIB info"
1885
1886	$IP addr del dev dummy2 172.16.104.11/24
1887	$IP ro ls vrf red | grep -q 172.16.105.0/24
1888	log_test $? 1 "Route removed from VRF when source address deleted"
1889
1890	$IP ro ls | grep -q 172.16.105.0/24
1891	log_test $? 0 "Route in default VRF not removed"
1892
1893	$IP addr add dev dummy2 172.16.104.11/24
1894	$IP route add vrf red 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1895
1896	$IP addr del dev dummy1 172.16.104.11/24
1897	$IP ro ls | grep -q 172.16.105.0/24
1898	log_test $? 1 "Route removed in default VRF when source address deleted"
1899
1900	$IP ro ls vrf red | grep -q 172.16.105.0/24
1901	log_test $? 0 "Route in VRF is not removed by address delete"
1902
1903	# removing address from device in vrf should only remove route from vrf
1904	# table even when the associated fib info only differs in table ID
1905	echo "    Identical FIB info with different table ID"
1906
1907	$IP addr del dev dummy2 172.16.104.12/24
1908	$IP ro ls vrf red | grep -q 172.16.106.0/24
1909	log_test $? 1 "Route removed from VRF when source address deleted"
1910
1911	$IP ro ls | grep -q 172.16.106.0/24
1912	log_test $? 0 "Route in default VRF not removed"
1913
1914	$IP addr add dev dummy2 172.16.104.12/24
1915	$IP route add vrf red 172.16.106.0/24 dev lo src 172.16.104.12
1916
1917	$IP addr del dev dummy1 172.16.104.12/24
1918	$IP ro ls | grep -q 172.16.106.0/24
1919	log_test $? 1 "Route removed in default VRF when source address deleted"
1920
1921	$IP ro ls vrf red | grep -q 172.16.106.0/24
1922	log_test $? 0 "Route in VRF is not removed by address delete"
1923
1924	# removing address from device in default vrf should remove route from
1925	# the default vrf even when route was inserted with a table ID of 0.
1926	echo "    Table ID 0"
1927
1928	$IP addr del dev dummy1 172.16.104.13/24
1929	$IP ro ls | grep -q 172.16.107.0/24
1930	log_test $? 1 "Route removed in default VRF when source address deleted"
1931
1932	$IP li del dummy1
1933	$IP li del dummy2
1934	cleanup
1935}
1936
1937ipv6_del_addr_test()
1938{
1939	echo
1940	echo "IPv6 delete address route tests"
1941
1942	setup
1943
1944	set -e
1945	for i in $(seq 6); do
1946		$IP li add dummy${i} up type dummy
1947	done
1948
1949	$IP li add red up type vrf table 1111
1950	$IP ro add vrf red unreachable default
1951	for i in $(seq 4 6); do
1952		$IP li set dummy${i} vrf red
1953	done
1954
1955	$IP addr add dev dummy1 fe80::1/128
1956	$IP addr add dev dummy1 2001:db8:101::1/64
1957	$IP addr add dev dummy1 2001:db8:101::10/64
1958	$IP addr add dev dummy1 2001:db8:101::11/64
1959	$IP addr add dev dummy1 2001:db8:101::12/64
1960	$IP addr add dev dummy1 2001:db8:101::13/64
1961	$IP addr add dev dummy1 2001:db8:101::14/64
1962	$IP addr add dev dummy1 2001:db8:101::15/64
1963	$IP addr add dev dummy2 fe80::1/128
1964	$IP addr add dev dummy2 2001:db8:101::1/64
1965	$IP addr add dev dummy2 2001:db8:101::11/64
1966	$IP addr add dev dummy3 fe80::1/128
1967
1968	$IP addr add dev dummy4 2001:db8:101::1/64
1969	$IP addr add dev dummy4 2001:db8:101::10/64
1970	$IP addr add dev dummy4 2001:db8:101::11/64
1971	$IP addr add dev dummy4 2001:db8:101::12/64
1972	$IP addr add dev dummy4 2001:db8:101::13/64
1973	$IP addr add dev dummy4 2001:db8:101::14/64
1974	$IP addr add dev dummy5 2001:db8:101::1/64
1975	$IP addr add dev dummy5 2001:db8:101::11/64
1976
1977	# Single device using src address
1978	$IP route add 2001:db8:110::/64 dev dummy3 src 2001:db8:101::10
1979	# Two devices with the same source address
1980	$IP route add 2001:db8:111::/64 dev dummy3 src 2001:db8:101::11
1981	# VRF with single device using src address
1982	$IP route add vrf red 2001:db8:110::/64 dev dummy6 src 2001:db8:101::10
1983	# VRF with two devices using src address
1984	$IP route add vrf red 2001:db8:111::/64 dev dummy6 src 2001:db8:101::11
1985	# src address and nexthop dev in same VRF
1986	$IP route add 2001:db8:112::/64 dev dummy3 src 2001:db8:101::12
1987	$IP route add vrf red 2001:db8:112::/64 dev dummy6 src 2001:db8:101::12
1988	# src address and nexthop device in different VRF
1989	$IP route add 2001:db8:113::/64 dev lo src 2001:db8:101::13
1990	$IP route add vrf red 2001:db8:113::/64 dev lo src 2001:db8:101::13
1991	# table ID 0
1992	$IP route add table 0 2001:db8:115::/64 via 2001:db8:101::2 src 2001:db8:101::15
1993	# Link local source route
1994	$IP route add 2001:db8:116::/64 dev dummy2 src fe80::1
1995	$IP route add 2001:db8:117::/64 dev dummy3 src fe80::1
1996	set +e
1997
1998	echo "    Single device using src address"
1999
2000	$IP addr del dev dummy1 2001:db8:101::10/64
2001	$IP -6 route show | grep -q "src 2001:db8:101::10 "
2002	log_test $? 1 "Prefsrc removed when src address removed on other device"
2003
2004	echo "    Two devices with the same source address"
2005
2006	$IP addr del dev dummy1 2001:db8:101::11/64
2007	$IP -6 route show | grep -q "src 2001:db8:101::11 "
2008	log_test $? 0 "Prefsrc not removed when src address exist on other device"
2009
2010	$IP addr del dev dummy2 2001:db8:101::11/64
2011	$IP -6 route show | grep -q "src 2001:db8:101::11 "
2012	log_test $? 1 "Prefsrc removed when src address removed on all devices"
2013
2014	echo "    VRF with single device using src address"
2015
2016	$IP addr del dev dummy4 2001:db8:101::10/64
2017	$IP -6 route show vrf red | grep -q "src 2001:db8:101::10 "
2018	log_test $? 1 "Prefsrc removed when src address removed on other device"
2019
2020	echo "    VRF with two devices using src address"
2021
2022	$IP addr del dev dummy4 2001:db8:101::11/64
2023	$IP -6 route show vrf red | grep -q "src 2001:db8:101::11 "
2024	log_test $? 0 "Prefsrc not removed when src address exist on other device"
2025
2026	$IP addr del dev dummy5 2001:db8:101::11/64
2027	$IP -6 route show vrf red | grep -q "src 2001:db8:101::11 "
2028	log_test $? 1 "Prefsrc removed when src address removed on all devices"
2029
2030	echo "    src address and nexthop dev in same VRF"
2031
2032	$IP addr del dev dummy4 2001:db8:101::12/64
2033	$IP -6 route show vrf red | grep -q "src 2001:db8:101::12 "
2034	log_test $? 1 "Prefsrc removed from VRF when source address deleted"
2035	$IP -6 route show | grep -q " src 2001:db8:101::12 "
2036	log_test $? 0 "Prefsrc in default VRF not removed"
2037
2038	$IP addr add dev dummy4 2001:db8:101::12/64
2039	$IP route replace vrf red 2001:db8:112::/64 dev dummy6 src 2001:db8:101::12
2040	$IP addr del dev dummy1 2001:db8:101::12/64
2041	$IP -6 route show vrf red | grep -q "src 2001:db8:101::12 "
2042	log_test $? 0 "Prefsrc not removed from VRF when source address exist"
2043	$IP -6 route show | grep -q " src 2001:db8:101::12 "
2044	log_test $? 1 "Prefsrc in default VRF removed"
2045
2046	echo "    src address and nexthop device in different VRF"
2047
2048	$IP addr del dev dummy4 2001:db8:101::13/64
2049	$IP -6 route show vrf red | grep -q "src 2001:db8:101::13 "
2050	log_test $? 0 "Prefsrc not removed from VRF when nexthop dev in diff VRF"
2051	$IP -6 route show | grep -q "src 2001:db8:101::13 "
2052	log_test $? 0 "Prefsrc not removed in default VRF"
2053
2054	$IP addr add dev dummy4 2001:db8:101::13/64
2055	$IP addr del dev dummy1 2001:db8:101::13/64
2056	$IP -6 route show vrf red | grep -q "src 2001:db8:101::13 "
2057	log_test $? 1 "Prefsrc removed from VRF when nexthop dev in diff VRF"
2058	$IP -6 route show | grep -q "src 2001:db8:101::13 "
2059	log_test $? 1 "Prefsrc removed in default VRF"
2060
2061	echo "    Table ID 0"
2062
2063	$IP addr del dev dummy1 2001:db8:101::15/64
2064	$IP -6 route show | grep -q "src 2001:db8:101::15"
2065	log_test $? 1 "Prefsrc removed from default VRF when source address deleted"
2066
2067	echo "    Link local source route"
2068	$IP addr del dev dummy1 fe80::1/128
2069	$IP -6 route show | grep -q "2001:db8:116::/64 dev dummy2 src fe80::1"
2070	log_test $? 0 "Prefsrc not removed when delete ll addr from other dev"
2071	$IP addr del dev dummy2 fe80::1/128
2072	$IP -6 route show | grep -q "2001:db8:116::/64 dev dummy2 src fe80::1"
2073	log_test $? 1 "Prefsrc removed when delete ll addr"
2074	$IP -6 route show | grep -q "2001:db8:117::/64 dev dummy3 src fe80::1"
2075	log_test $? 0 "Prefsrc not removed when delete ll addr from other dev"
2076	$IP addr add dev dummy1 fe80::1/128
2077	$IP addr del dev dummy3 fe80::1/128
2078	$IP -6 route show | grep -q "2001:db8:117::/64 dev dummy3 src fe80::1"
2079	log_test $? 1 "Prefsrc removed even ll addr still exist on other dev"
2080
2081	for i in $(seq 6); do
2082		$IP li del dummy${i}
2083	done
2084	cleanup
2085}
2086
2087ipv4_route_v6_gw_test()
2088{
2089	local rc
2090
2091	echo
2092	echo "IPv4 route with IPv6 gateway tests"
2093
2094	route_setup
2095	sleep 2
2096
2097	#
2098	# single path route
2099	#
2100	run_cmd "$IP ro add 172.16.104.0/24 via inet6 2001:db8:101::2"
2101	rc=$?
2102	log_test $rc 0 "Single path route with IPv6 gateway"
2103	if [ $rc -eq 0 ]; then
2104		check_route "172.16.104.0/24 via inet6 2001:db8:101::2 dev veth1"
2105	fi
2106
2107	run_cmd "ip netns exec ns1 ping -w1 -c1 172.16.104.1"
2108	log_test $rc 0 "Single path route with IPv6 gateway - ping"
2109
2110	run_cmd "$IP ro del 172.16.104.0/24 via inet6 2001:db8:101::2"
2111	rc=$?
2112	log_test $rc 0 "Single path route delete"
2113	if [ $rc -eq 0 ]; then
2114		check_route "172.16.112.0/24"
2115	fi
2116
2117	#
2118	# multipath - v6 then v4
2119	#
2120	run_cmd "$IP ro add 172.16.104.0/24 nexthop via inet6 2001:db8:101::2 dev veth1 nexthop via 172.16.103.2 dev veth3"
2121	rc=$?
2122	log_test $rc 0 "Multipath route add - v6 nexthop then v4"
2123	if [ $rc -eq 0 ]; then
2124		check_route "172.16.104.0/24 nexthop via inet6 2001:db8:101::2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
2125	fi
2126
2127	run_cmd "$IP ro del 172.16.104.0/24 nexthop via 172.16.103.2 dev veth3 nexthop via inet6 2001:db8:101::2 dev veth1"
2128	log_test $? 2 "    Multipath route delete - nexthops in wrong order"
2129
2130	run_cmd "$IP ro del 172.16.104.0/24 nexthop via inet6 2001:db8:101::2 dev veth1 nexthop via 172.16.103.2 dev veth3"
2131	log_test $? 0 "    Multipath route delete exact match"
2132
2133	#
2134	# multipath - v4 then v6
2135	#
2136	run_cmd "$IP ro add 172.16.104.0/24 nexthop via 172.16.103.2 dev veth3 nexthop via inet6 2001:db8:101::2 dev veth1"
2137	rc=$?
2138	log_test $rc 0 "Multipath route add - v4 nexthop then v6"
2139	if [ $rc -eq 0 ]; then
2140		check_route "172.16.104.0/24 nexthop via 172.16.103.2 dev veth3 weight 1 nexthop via inet6 2001:db8:101::2 dev veth1 weight 1"
2141	fi
2142
2143	run_cmd "$IP ro del 172.16.104.0/24 nexthop via inet6 2001:db8:101::2 dev veth1 nexthop via 172.16.103.2 dev veth3"
2144	log_test $? 2 "    Multipath route delete - nexthops in wrong order"
2145
2146	run_cmd "$IP ro del 172.16.104.0/24 nexthop via 172.16.103.2 dev veth3 nexthop via inet6 2001:db8:101::2 dev veth1"
2147	log_test $? 0 "    Multipath route delete exact match"
2148
2149	route_cleanup
2150}
2151
2152socat_check()
2153{
2154	if [ ! -x "$(command -v socat)" ]; then
2155		echo "socat command not found. Skipping test"
2156		return 1
2157	fi
2158
2159	return 0
2160}
2161
2162iptables_check()
2163{
2164	iptables -t mangle -L OUTPUT &> /dev/null
2165	if [ $? -ne 0 ]; then
2166		echo "iptables configuration not supported. Skipping test"
2167		return 1
2168	fi
2169
2170	return 0
2171}
2172
2173ip6tables_check()
2174{
2175	ip6tables -t mangle -L OUTPUT &> /dev/null
2176	if [ $? -ne 0 ]; then
2177		echo "ip6tables configuration not supported. Skipping test"
2178		return 1
2179	fi
2180
2181	return 0
2182}
2183
2184ipv4_mangle_test()
2185{
2186	local rc
2187
2188	echo
2189	echo "IPv4 mangling tests"
2190
2191	socat_check || return 1
2192	iptables_check || return 1
2193
2194	route_setup
2195	sleep 2
2196
2197	local tmp_file=$(mktemp)
2198	ip netns exec ns2 socat UDP4-LISTEN:54321,fork $tmp_file &
2199
2200	# Add a FIB rule and a route that will direct our connection to the
2201	# listening server.
2202	$IP rule add pref 100 ipproto udp sport 12345 dport 54321 table 123
2203	$IP route add table 123 172.16.101.0/24 dev veth1
2204
2205	# Add an unreachable route to the main table that will block our
2206	# connection in case the FIB rule is not hit.
2207	$IP route add unreachable 172.16.101.2/32
2208
2209	run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
2210	log_test $? 0 "    Connection with correct parameters"
2211
2212	run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=11111"
2213	log_test $? 1 "    Connection with incorrect parameters"
2214
2215	# Add a mangling rule and make sure connection is still successful.
2216	$NS_EXEC iptables -t mangle -A OUTPUT -j MARK --set-mark 1
2217
2218	run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
2219	log_test $? 0 "    Connection with correct parameters - mangling"
2220
2221	# Delete the mangling rule and make sure connection is still
2222	# successful.
2223	$NS_EXEC iptables -t mangle -D OUTPUT -j MARK --set-mark 1
2224
2225	run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
2226	log_test $? 0 "    Connection with correct parameters - no mangling"
2227
2228	# Verify connections were indeed successful on server side.
2229	[[ $(cat $tmp_file | wc -l) -eq 3 ]]
2230	log_test $? 0 "    Connection check - server side"
2231
2232	$IP route del unreachable 172.16.101.2/32
2233	$IP route del table 123 172.16.101.0/24 dev veth1
2234	$IP rule del pref 100
2235
2236	{ kill %% && wait %%; } 2>/dev/null
2237	rm $tmp_file
2238
2239	route_cleanup
2240}
2241
2242ipv6_mangle_test()
2243{
2244	local rc
2245
2246	echo
2247	echo "IPv6 mangling tests"
2248
2249	socat_check || return 1
2250	ip6tables_check || return 1
2251
2252	route_setup
2253	sleep 2
2254
2255	local tmp_file=$(mktemp)
2256	ip netns exec ns2 socat UDP6-LISTEN:54321,fork $tmp_file &
2257
2258	# Add a FIB rule and a route that will direct our connection to the
2259	# listening server.
2260	$IP -6 rule add pref 100 ipproto udp sport 12345 dport 54321 table 123
2261	$IP -6 route add table 123 2001:db8:101::/64 dev veth1
2262
2263	# Add an unreachable route to the main table that will block our
2264	# connection in case the FIB rule is not hit.
2265	$IP -6 route add unreachable 2001:db8:101::2/128
2266
2267	run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
2268	log_test $? 0 "    Connection with correct parameters"
2269
2270	run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=11111"
2271	log_test $? 1 "    Connection with incorrect parameters"
2272
2273	# Add a mangling rule and make sure connection is still successful.
2274	$NS_EXEC ip6tables -t mangle -A OUTPUT -j MARK --set-mark 1
2275
2276	run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
2277	log_test $? 0 "    Connection with correct parameters - mangling"
2278
2279	# Delete the mangling rule and make sure connection is still
2280	# successful.
2281	$NS_EXEC ip6tables -t mangle -D OUTPUT -j MARK --set-mark 1
2282
2283	run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
2284	log_test $? 0 "    Connection with correct parameters - no mangling"
2285
2286	# Verify connections were indeed successful on server side.
2287	[[ $(cat $tmp_file | wc -l) -eq 3 ]]
2288	log_test $? 0 "    Connection check - server side"
2289
2290	$IP -6 route del unreachable 2001:db8:101::2/128
2291	$IP -6 route del table 123 2001:db8:101::/64 dev veth1
2292	$IP -6 rule del pref 100
2293
2294	{ kill %% && wait %%; } 2>/dev/null
2295	rm $tmp_file
2296
2297	route_cleanup
2298}
2299
2300ip_neigh_get_check()
2301{
2302	ip neigh help 2>&1 | grep -q 'ip neigh get'
2303	if [ $? -ne 0 ]; then
2304		echo "iproute2 command does not support neigh get. Skipping test"
2305		return 1
2306	fi
2307
2308	return 0
2309}
2310
2311ipv4_bcast_neigh_test()
2312{
2313	local rc
2314
2315	echo
2316	echo "IPv4 broadcast neighbour tests"
2317
2318	ip_neigh_get_check || return 1
2319
2320	setup
2321
2322	set -e
2323	run_cmd "$IP neigh add 192.0.2.111 lladdr 00:11:22:33:44:55 nud perm dev dummy0"
2324	run_cmd "$IP neigh add 192.0.2.255 lladdr 00:11:22:33:44:55 nud perm dev dummy0"
2325
2326	run_cmd "$IP neigh get 192.0.2.111 dev dummy0"
2327	run_cmd "$IP neigh get 192.0.2.255 dev dummy0"
2328
2329	run_cmd "$IP address add 192.0.2.1/24 broadcast 192.0.2.111 dev dummy0"
2330
2331	run_cmd "$IP neigh add 203.0.113.111 nud failed dev dummy0"
2332	run_cmd "$IP neigh add 203.0.113.255 nud failed dev dummy0"
2333
2334	run_cmd "$IP neigh get 203.0.113.111 dev dummy0"
2335	run_cmd "$IP neigh get 203.0.113.255 dev dummy0"
2336
2337	run_cmd "$IP address add 203.0.113.1/24 broadcast 203.0.113.111 dev dummy0"
2338	set +e
2339
2340	run_cmd "$IP neigh get 192.0.2.111 dev dummy0"
2341	log_test $? 0 "Resolved neighbour for broadcast address"
2342
2343	run_cmd "$IP neigh get 192.0.2.255 dev dummy0"
2344	log_test $? 0 "Resolved neighbour for network broadcast address"
2345
2346	run_cmd "$IP neigh get 203.0.113.111 dev dummy0"
2347	log_test $? 2 "Unresolved neighbour for broadcast address"
2348
2349	run_cmd "$IP neigh get 203.0.113.255 dev dummy0"
2350	log_test $? 2 "Unresolved neighbour for network broadcast address"
2351
2352	cleanup
2353}
2354
2355################################################################################
2356# usage
2357
2358usage()
2359{
2360	cat <<EOF
2361usage: ${0##*/} OPTS
2362
2363        -t <test>   Test(s) to run (default: all)
2364                    (options: $TESTS)
2365        -p          Pause on fail
2366        -P          Pause after each test before cleanup
2367        -v          verbose mode (show commands and output)
2368EOF
2369}
2370
2371################################################################################
2372# main
2373
2374trap cleanup EXIT
2375
2376while getopts :t:pPhv o
2377do
2378	case $o in
2379		t) TESTS=$OPTARG;;
2380		p) PAUSE_ON_FAIL=yes;;
2381		P) PAUSE=yes;;
2382		v) VERBOSE=$(($VERBOSE + 1));;
2383		h) usage; exit 0;;
2384		*) usage; exit 1;;
2385	esac
2386done
2387
2388PEER_CMD="ip netns exec ${PEER_NS}"
2389
2390# make sure we don't pause twice
2391[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
2392
2393if [ "$(id -u)" -ne 0 ];then
2394	echo "SKIP: Need root privileges"
2395	exit $ksft_skip;
2396fi
2397
2398if [ ! -x "$(command -v ip)" ]; then
2399	echo "SKIP: Could not run test without ip tool"
2400	exit $ksft_skip
2401fi
2402
2403ip route help 2>&1 | grep -q fibmatch
2404if [ $? -ne 0 ]; then
2405	echo "SKIP: iproute2 too old, missing fibmatch"
2406	exit $ksft_skip
2407fi
2408
2409# start clean
2410cleanup &> /dev/null
2411
2412for t in $TESTS
2413do
2414	case $t in
2415	fib_unreg_test|unregister)	fib_unreg_test;;
2416	fib_down_test|down)		fib_down_test;;
2417	fib_carrier_test|carrier)	fib_carrier_test;;
2418	fib_rp_filter_test|rp_filter)	fib_rp_filter_test;;
2419	fib_nexthop_test|nexthop)	fib_nexthop_test;;
2420	fib_notify_test|ipv4_notify)	fib_notify_test;;
2421	fib6_notify_test|ipv6_notify)	fib6_notify_test;;
2422	fib_suppress_test|suppress)	fib_suppress_test;;
2423	ipv6_route_test|ipv6_rt)	ipv6_route_test;;
2424	ipv4_route_test|ipv4_rt)	ipv4_route_test;;
2425	ipv6_addr_metric)		ipv6_addr_metric_test;;
2426	ipv4_addr_metric)		ipv4_addr_metric_test;;
2427	ipv4_del_addr)			ipv4_del_addr_test;;
2428	ipv6_del_addr)			ipv6_del_addr_test;;
2429	ipv6_route_metrics)		ipv6_route_metrics_test;;
2430	ipv4_route_metrics)		ipv4_route_metrics_test;;
2431	ipv4_route_v6_gw)		ipv4_route_v6_gw_test;;
2432	ipv4_mangle)			ipv4_mangle_test;;
2433	ipv6_mangle)			ipv6_mangle_test;;
2434	ipv4_bcast_neigh)		ipv4_bcast_neigh_test;;
2435	fib6_gc_test|ipv6_gc)		fib6_gc_test;;
2436
2437	help) echo "Test names: $TESTS"; exit 0;;
2438	esac
2439done
2440
2441if [ "$TESTS" != "none" ]; then
2442	printf "\nTests passed: %3d\n" ${nsuccess}
2443	printf "Tests failed: %3d\n"   ${nfail}
2444fi
2445
2446exit $ret
2447