Linux Audio

Check our new training course

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