Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
fork
Configure Feed
Select the types of activity you want to include in your feed.
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 ipv4_mpath_balance ipv6_mpath_balance"
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
1088forwarding_cleanup()
1089{
1090 cleanup_ns $ns3
1091
1092 route_cleanup
1093}
1094
1095# extend route_setup with an ns3 reachable through ns2 over both devices
1096forwarding_setup()
1097{
1098 forwarding_cleanup
1099
1100 route_setup
1101
1102 setup_ns ns3
1103
1104 ip link add veth5 netns $ns3 type veth peer name veth6 netns $ns2
1105 ip -netns $ns3 link set veth5 up
1106 ip -netns $ns2 link set veth6 up
1107
1108 ip -netns $ns3 -4 addr add dev veth5 172.16.105.1/24
1109 ip -netns $ns2 -4 addr add dev veth6 172.16.105.2/24
1110 ip -netns $ns3 -4 route add 172.16.100.0/22 via 172.16.105.2
1111
1112 ip -netns $ns3 -6 addr add dev veth5 2001:db8:105::1/64 nodad
1113 ip -netns $ns2 -6 addr add dev veth6 2001:db8:105::2/64 nodad
1114 ip -netns $ns3 -6 route add 2001:db8:101::/33 via 2001:db8:105::2
1115}
1116
1117# assumption is that basic add of a single path route works
1118# otherwise just adding an address on an interface is broken
1119ipv6_rt_add()
1120{
1121 local rc
1122
1123 echo
1124 echo "IPv6 route add / append tests"
1125
1126 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1127 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1128 run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2"
1129 log_test $? 2 "Attempt to add duplicate route - gw"
1130
1131 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1132 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1133 run_cmd "$IP -6 ro add 2001:db8:104::/64 dev veth3"
1134 log_test $? 2 "Attempt to add duplicate route - dev only"
1135
1136 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1137 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1138 run_cmd "$IP -6 ro add unreachable 2001:db8:104::/64"
1139 log_test $? 2 "Attempt to add duplicate route - reject route"
1140
1141 # route append with same prefix adds a new route
1142 # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
1143 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1144 run_cmd "$IP -6 ro append 2001:db8:104::/64 via 2001:db8:103::2"
1145 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"
1146 log_test $? 0 "Append nexthop to existing route - gw"
1147
1148 # insert mpath directly
1149 add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1150 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"
1151 log_test $? 0 "Add multipath route"
1152
1153 add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1154 run_cmd "$IP -6 ro add 2001:db8:104::/64 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1155 log_test $? 2 "Attempt to add duplicate multipath route"
1156
1157 # insert of a second route without append but different metric
1158 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1159 run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2 metric 512"
1160 rc=$?
1161 if [ $rc -eq 0 ]; then
1162 run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::3 metric 256"
1163 rc=$?
1164 fi
1165 log_test $rc 0 "Route add with different metrics"
1166
1167 run_cmd "$IP -6 ro del 2001:db8:104::/64 metric 512"
1168 rc=$?
1169 if [ $rc -eq 0 ]; then
1170 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"
1171 rc=$?
1172 fi
1173 log_test $rc 0 "Route delete with metric"
1174}
1175
1176ipv6_rt_replace_single()
1177{
1178 # single path with single path
1179 #
1180 add_initial_route6 "via 2001:db8:101::2"
1181 run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:103::2"
1182 check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
1183 log_test $? 0 "Single path with single path"
1184
1185 # single path with multipath
1186 #
1187 add_initial_route6 "nexthop via 2001:db8:101::2"
1188 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::2"
1189 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"
1190 log_test $? 0 "Single path with multipath"
1191
1192 # single path with single path using MULTIPATH attribute
1193 #
1194 add_initial_route6 "via 2001:db8:101::2"
1195 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:103::2"
1196 check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
1197 log_test $? 0 "Single path with single path via multipath attribute"
1198
1199 # route replace fails - invalid nexthop
1200 add_initial_route6 "via 2001:db8:101::2"
1201 run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:104::2"
1202 if [ $? -eq 0 ]; then
1203 # previous command is expected to fail so if it returns 0
1204 # that means the test failed.
1205 log_test 0 1 "Invalid nexthop"
1206 else
1207 check_route6 "2001:db8:104::/64 via 2001:db8:101::2 dev veth1 metric 1024"
1208 log_test $? 0 "Invalid nexthop"
1209 fi
1210
1211 # replace non-existent route
1212 # - note use of change versus replace since ip adds NLM_F_CREATE
1213 # for replace
1214 add_initial_route6 "via 2001:db8:101::2"
1215 run_cmd "$IP -6 ro change 2001:db8:105::/64 via 2001:db8:101::2"
1216 log_test $? 2 "Single path - replace of non-existent route"
1217}
1218
1219ipv6_rt_replace_mpath()
1220{
1221 # multipath with multipath
1222 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1223 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
1224 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"
1225 log_test $? 0 "Multipath with multipath"
1226
1227 # multipath with single
1228 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1229 run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:101::3"
1230 check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
1231 log_test $? 0 "Multipath with single path"
1232
1233 # multipath with single
1234 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1235 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3"
1236 check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
1237 log_test $? 0 "Multipath with single path via multipath attribute"
1238
1239 # multipath with dev-only
1240 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1241 run_cmd "$IP -6 ro replace 2001:db8:104::/64 dev veth1"
1242 check_route6 "2001:db8:104::/64 dev veth1 metric 1024"
1243 log_test $? 0 "Multipath with dev-only"
1244
1245 # route replace fails - invalid nexthop 1
1246 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1247 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:111::3 nexthop via 2001:db8:103::3"
1248 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"
1249 log_test $? 0 "Multipath - invalid first nexthop"
1250
1251 # route replace fails - invalid nexthop 2
1252 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1253 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:113::3"
1254 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"
1255 log_test $? 0 "Multipath - invalid second nexthop"
1256
1257 # multipath non-existent route
1258 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1259 run_cmd "$IP -6 ro change 2001:db8:105::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
1260 log_test $? 2 "Multipath - replace of non-existent route"
1261}
1262
1263ipv6_rt_replace()
1264{
1265 echo
1266 echo "IPv6 route replace tests"
1267
1268 ipv6_rt_replace_single
1269 ipv6_rt_replace_mpath
1270}
1271
1272ipv6_rt_dsfield()
1273{
1274 echo
1275 echo "IPv6 route with dsfield tests"
1276
1277 run_cmd "$IP -6 route flush 2001:db8:102::/64"
1278
1279 # IPv6 doesn't support routing based on dsfield
1280 run_cmd "$IP -6 route add 2001:db8:102::/64 dsfield 0x04 via 2001:db8:101::2"
1281 log_test $? 2 "Reject route with dsfield"
1282}
1283
1284ipv6_route_test()
1285{
1286 route_setup
1287
1288 ipv6_rt_add
1289 ipv6_rt_replace
1290 ipv6_rt_dsfield
1291
1292 route_cleanup
1293}
1294
1295ip_addr_metric_check()
1296{
1297 ip addr help 2>&1 | grep -q metric
1298 if [ $? -ne 0 ]; then
1299 echo "iproute2 command does not support metric for addresses. Skipping test"
1300 return 1
1301 fi
1302
1303 return 0
1304}
1305
1306ipv6_addr_metric_test()
1307{
1308 local rc
1309
1310 echo
1311 echo "IPv6 prefix route tests"
1312
1313 ip_addr_metric_check || return 1
1314
1315 setup
1316
1317 set -e
1318 $IP li add dummy1 type dummy
1319 $IP li add dummy2 type dummy
1320 $IP li set dummy1 up
1321 $IP li set dummy2 up
1322
1323 # default entry is metric 256
1324 run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64"
1325 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64"
1326 set +e
1327
1328 check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 256 2001:db8:104::/64 dev dummy2 proto kernel metric 256"
1329 log_test $? 0 "Default metric"
1330
1331 set -e
1332 run_cmd "$IP -6 addr flush dev dummy1"
1333 run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64 metric 257"
1334 set +e
1335
1336 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 256 2001:db8:104::/64 dev dummy1 proto kernel metric 257"
1337 log_test $? 0 "User specified metric on first device"
1338
1339 set -e
1340 run_cmd "$IP -6 addr flush dev dummy2"
1341 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64 metric 258"
1342 set +e
1343
1344 check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 257 2001:db8:104::/64 dev dummy2 proto kernel metric 258"
1345 log_test $? 0 "User specified metric on second device"
1346
1347 run_cmd "$IP -6 addr del dev dummy1 2001:db8:104::1/64 metric 257"
1348 rc=$?
1349 if [ $rc -eq 0 ]; then
1350 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 258"
1351 rc=$?
1352 fi
1353 log_test $rc 0 "Delete of address on first device"
1354
1355 run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::2/64 metric 259"
1356 rc=$?
1357 if [ $rc -eq 0 ]; then
1358 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
1359 rc=$?
1360 fi
1361 log_test $rc 0 "Modify metric of address"
1362
1363 # verify prefix route removed on down
1364 run_cmd "ip netns exec $ns1 sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1"
1365 run_cmd "$IP li set dev dummy2 down"
1366 rc=$?
1367 if [ $rc -eq 0 ]; then
1368 out=$($IP -6 ro ls match 2001:db8:104::/64)
1369 check_expected "${out}" ""
1370 rc=$?
1371 fi
1372 log_test $rc 0 "Prefix route removed on link down"
1373
1374 # verify prefix route re-inserted with assigned metric
1375 run_cmd "$IP li set dev dummy2 up"
1376 rc=$?
1377 if [ $rc -eq 0 ]; then
1378 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
1379 rc=$?
1380 fi
1381 log_test $rc 0 "Prefix route with metric on link up"
1382
1383 # verify peer metric added correctly
1384 set -e
1385 run_cmd "$IP -6 addr flush dev dummy2"
1386 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::1 peer 2001:db8:104::2 metric 260"
1387 set +e
1388
1389 check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 260"
1390 log_test $? 0 "Set metric with peer route on local side"
1391 check_route6 "2001:db8:104::2 dev dummy2 proto kernel metric 260"
1392 log_test $? 0 "Set metric with peer route on peer side"
1393
1394 set -e
1395 run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::1 peer 2001:db8:104::3 metric 261"
1396 set +e
1397
1398 check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 261"
1399 log_test $? 0 "Modify metric and peer address on local side"
1400 check_route6 "2001:db8:104::3 dev dummy2 proto kernel metric 261"
1401 log_test $? 0 "Modify metric and peer address on peer side"
1402
1403 $IP li del dummy1
1404 $IP li del dummy2
1405 cleanup
1406}
1407
1408ipv6_route_metrics_test()
1409{
1410 local rc
1411
1412 echo
1413 echo "IPv6 routes with metrics"
1414
1415 route_setup
1416
1417 #
1418 # single path with metrics
1419 #
1420 run_cmd "$IP -6 ro add 2001:db8:111::/64 via 2001:db8:101::2 mtu 1400"
1421 rc=$?
1422 if [ $rc -eq 0 ]; then
1423 check_route6 "2001:db8:111::/64 via 2001:db8:101::2 dev veth1 metric 1024 mtu 1400"
1424 rc=$?
1425 fi
1426 log_test $rc 0 "Single path route with mtu metric"
1427
1428
1429 #
1430 # multipath via separate routes with metrics
1431 #
1432 run_cmd "$IP -6 ro add 2001:db8:112::/64 via 2001:db8:101::2 mtu 1400"
1433 run_cmd "$IP -6 ro append 2001:db8:112::/64 via 2001:db8:103::2"
1434 rc=$?
1435 if [ $rc -eq 0 ]; then
1436 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"
1437 rc=$?
1438 fi
1439 log_test $rc 0 "Multipath route via 2 single routes with mtu metric on first"
1440
1441 # second route is coalesced to first to make a multipath route.
1442 # MTU of the second path is hidden from display!
1443 run_cmd "$IP -6 ro add 2001:db8:113::/64 via 2001:db8:101::2"
1444 run_cmd "$IP -6 ro append 2001:db8:113::/64 via 2001:db8:103::2 mtu 1400"
1445 rc=$?
1446 if [ $rc -eq 0 ]; then
1447 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"
1448 rc=$?
1449 fi
1450 log_test $rc 0 "Multipath route via 2 single routes with mtu metric on 2nd"
1451
1452 run_cmd "$IP -6 ro del 2001:db8:113::/64 via 2001:db8:101::2"
1453 if [ $? -eq 0 ]; then
1454 check_route6 "2001:db8:113::/64 via 2001:db8:103::2 dev veth3 metric 1024 mtu 1400"
1455 log_test $? 0 " MTU of second leg"
1456 fi
1457
1458 #
1459 # multipath with metrics
1460 #
1461 run_cmd "$IP -6 ro add 2001:db8:115::/64 mtu 1400 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1462 rc=$?
1463 if [ $rc -eq 0 ]; then
1464 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"
1465 rc=$?
1466 fi
1467 log_test $rc 0 "Multipath route with mtu metric"
1468
1469 $IP -6 ro add 2001:db8:104::/64 via 2001:db8:101::2 mtu 1300
1470 run_cmd "ip netns exec $ns1 ${ping6} -w1 -c1 -s 1500 2001:db8:104::1"
1471 log_test $? 0 "Using route with mtu metric"
1472
1473 run_cmd "$IP -6 ro add 2001:db8:114::/64 via 2001:db8:101::2 congctl lock foo"
1474 log_test $? 2 "Invalid metric (fails metric_convert)"
1475
1476 route_cleanup
1477}
1478
1479# add route for a prefix, flushing any existing routes first
1480# expected to be the first step of a test
1481add_route()
1482{
1483 local pfx="$1"
1484 local nh="$2"
1485 local out
1486
1487 if [ "$VERBOSE" = "1" ]; then
1488 echo
1489 echo " ##################################################"
1490 echo
1491 fi
1492
1493 run_cmd "$IP ro flush ${pfx}"
1494 [ $? -ne 0 ] && exit 1
1495
1496 out=$($IP ro ls match ${pfx})
1497 if [ -n "$out" ]; then
1498 echo "Failed to flush routes for prefix used for tests."
1499 exit 1
1500 fi
1501
1502 run_cmd "$IP ro add ${pfx} ${nh}"
1503 if [ $? -ne 0 ]; then
1504 echo "Failed to add initial route for test."
1505 exit 1
1506 fi
1507}
1508
1509# add initial route - used in replace route tests
1510add_initial_route()
1511{
1512 add_route "172.16.104.0/24" "$1"
1513}
1514
1515check_route()
1516{
1517 local pfx
1518 local expected="$1"
1519 local out
1520
1521 set -- $expected
1522 pfx=$1
1523 [ "${pfx}" = "unreachable" ] && pfx=$2
1524
1525 out=$($IP ro ls match ${pfx})
1526 check_expected "${out}" "${expected}"
1527}
1528
1529# assumption is that basic add of a single path route works
1530# otherwise just adding an address on an interface is broken
1531ipv4_rt_add()
1532{
1533 local rc
1534
1535 echo
1536 echo "IPv4 route add / append tests"
1537
1538 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1539 add_route "172.16.104.0/24" "via 172.16.101.2"
1540 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2"
1541 log_test $? 2 "Attempt to add duplicate route - gw"
1542
1543 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1544 add_route "172.16.104.0/24" "via 172.16.101.2"
1545 run_cmd "$IP ro add 172.16.104.0/24 dev veth3"
1546 log_test $? 2 "Attempt to add duplicate route - dev only"
1547
1548 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1549 add_route "172.16.104.0/24" "via 172.16.101.2"
1550 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1551 log_test $? 2 "Attempt to add duplicate route - reject route"
1552
1553 # iproute2 prepend only sets NLM_F_CREATE
1554 # - adds a new route; does NOT convert existing route to ECMP
1555 add_route "172.16.104.0/24" "via 172.16.101.2"
1556 run_cmd "$IP ro prepend 172.16.104.0/24 via 172.16.103.2"
1557 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"
1558 log_test $? 0 "Add new nexthop for existing prefix"
1559
1560 # route append with same prefix adds a new route
1561 # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
1562 add_route "172.16.104.0/24" "via 172.16.101.2"
1563 run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
1564 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"
1565 log_test $? 0 "Append nexthop to existing route - gw"
1566
1567 add_route "172.16.104.0/24" "via 172.16.101.2"
1568 run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
1569 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 dev veth3 scope link"
1570 log_test $? 0 "Append nexthop to existing route - dev only"
1571
1572 add_route "172.16.104.0/24" "via 172.16.101.2"
1573 run_cmd "$IP ro append unreachable 172.16.104.0/24"
1574 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 unreachable 172.16.104.0/24"
1575 log_test $? 0 "Append nexthop to existing route - reject route"
1576
1577 run_cmd "$IP ro flush 172.16.104.0/24"
1578 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1579 run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
1580 check_route "unreachable 172.16.104.0/24 172.16.104.0/24 via 172.16.103.2 dev veth3"
1581 log_test $? 0 "Append nexthop to existing reject route - gw"
1582
1583 run_cmd "$IP ro flush 172.16.104.0/24"
1584 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1585 run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
1586 check_route "unreachable 172.16.104.0/24 172.16.104.0/24 dev veth3 scope link"
1587 log_test $? 0 "Append nexthop to existing reject route - dev only"
1588
1589 # insert mpath directly
1590 add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1591 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"
1592 log_test $? 0 "add multipath route"
1593
1594 add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1595 run_cmd "$IP ro add 172.16.104.0/24 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1596 log_test $? 2 "Attempt to add duplicate multipath route"
1597
1598 # insert of a second route without append but different metric
1599 add_route "172.16.104.0/24" "via 172.16.101.2"
1600 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2 metric 512"
1601 rc=$?
1602 if [ $rc -eq 0 ]; then
1603 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.3 metric 256"
1604 rc=$?
1605 fi
1606 log_test $rc 0 "Route add with different metrics"
1607
1608 run_cmd "$IP ro del 172.16.104.0/24 metric 512"
1609 rc=$?
1610 if [ $rc -eq 0 ]; then
1611 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"
1612 rc=$?
1613 fi
1614 log_test $rc 0 "Route delete with metric"
1615}
1616
1617ipv4_rt_replace_single()
1618{
1619 # single path with single path
1620 #
1621 add_initial_route "via 172.16.101.2"
1622 run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.103.2"
1623 check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
1624 log_test $? 0 "Single path with single path"
1625
1626 # single path with multipath
1627 #
1628 add_initial_route "nexthop via 172.16.101.2"
1629 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.2"
1630 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"
1631 log_test $? 0 "Single path with multipath"
1632
1633 # single path with reject
1634 #
1635 add_initial_route "nexthop via 172.16.101.2"
1636 run_cmd "$IP ro replace unreachable 172.16.104.0/24"
1637 check_route "unreachable 172.16.104.0/24"
1638 log_test $? 0 "Single path with reject route"
1639
1640 # single path with single path using MULTIPATH attribute
1641 #
1642 add_initial_route "via 172.16.101.2"
1643 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.103.2"
1644 check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
1645 log_test $? 0 "Single path with single path via multipath attribute"
1646
1647 # route replace fails - invalid nexthop
1648 add_initial_route "via 172.16.101.2"
1649 run_cmd "$IP ro replace 172.16.104.0/24 via 2001:db8:104::2"
1650 if [ $? -eq 0 ]; then
1651 # previous command is expected to fail so if it returns 0
1652 # that means the test failed.
1653 log_test 0 1 "Invalid nexthop"
1654 else
1655 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1"
1656 log_test $? 0 "Invalid nexthop"
1657 fi
1658
1659 # replace non-existent route
1660 # - note use of change versus replace since ip adds NLM_F_CREATE
1661 # for replace
1662 add_initial_route "via 172.16.101.2"
1663 run_cmd "$IP ro change 172.16.105.0/24 via 172.16.101.2"
1664 log_test $? 2 "Single path - replace of non-existent route"
1665}
1666
1667ipv4_rt_replace_mpath()
1668{
1669 # multipath with multipath
1670 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1671 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
1672 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"
1673 log_test $? 0 "Multipath with multipath"
1674
1675 # multipath with single
1676 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1677 run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.101.3"
1678 check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
1679 log_test $? 0 "Multipath with single path"
1680
1681 # multipath with single
1682 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1683 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3"
1684 check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
1685 log_test $? 0 "Multipath with single path via multipath attribute"
1686
1687 # multipath with reject
1688 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1689 run_cmd "$IP ro replace unreachable 172.16.104.0/24"
1690 check_route "unreachable 172.16.104.0/24"
1691 log_test $? 0 "Multipath with reject route"
1692
1693 # route replace fails - invalid nexthop 1
1694 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1695 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.111.3 nexthop via 172.16.103.3"
1696 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"
1697 log_test $? 0 "Multipath - invalid first nexthop"
1698
1699 # route replace fails - invalid nexthop 2
1700 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1701 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.113.3"
1702 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"
1703 log_test $? 0 "Multipath - invalid second nexthop"
1704
1705 # multipath non-existent route
1706 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1707 run_cmd "$IP ro change 172.16.105.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
1708 log_test $? 2 "Multipath - replace of non-existent route"
1709}
1710
1711ipv4_rt_replace()
1712{
1713 echo
1714 echo "IPv4 route replace tests"
1715
1716 ipv4_rt_replace_single
1717 ipv4_rt_replace_mpath
1718}
1719
1720# checks that cached input route on VRF port is deleted
1721# when VRF is deleted
1722ipv4_local_rt_cache()
1723{
1724 run_cmd "ip addr add 10.0.0.1/32 dev lo"
1725 run_cmd "setup_ns test-ns"
1726 run_cmd "ip link add veth-outside type veth peer name veth-inside"
1727 run_cmd "ip link add vrf-100 type vrf table 1100"
1728 run_cmd "ip link set veth-outside master vrf-100"
1729 run_cmd "ip link set veth-inside netns $test-ns"
1730 run_cmd "ip link set veth-outside up"
1731 run_cmd "ip link set vrf-100 up"
1732 run_cmd "ip route add 10.1.1.1/32 dev veth-outside table 1100"
1733 run_cmd "ip netns exec $test-ns ip link set veth-inside up"
1734 run_cmd "ip netns exec $test-ns ip addr add 10.1.1.1/32 dev veth-inside"
1735 run_cmd "ip netns exec $test-ns ip route add 10.0.0.1/32 dev veth-inside"
1736 run_cmd "ip netns exec $test-ns ip route add default via 10.0.0.1"
1737 run_cmd "ip netns exec $test-ns ping 10.0.0.1 -c 1 -i 1"
1738 run_cmd "ip link delete vrf-100"
1739
1740 # if we do not hang test is a success
1741 log_test $? 0 "Cached route removed from VRF port device"
1742}
1743
1744ipv4_rt_dsfield()
1745{
1746 echo
1747 echo "IPv4 route with dsfield tests"
1748
1749 run_cmd "$IP route flush 172.16.102.0/24"
1750
1751 # New routes should reject dsfield options that interfere with ECN
1752 run_cmd "$IP route add 172.16.102.0/24 dsfield 0x01 via 172.16.101.2"
1753 log_test $? 2 "Reject route with dsfield 0x01"
1754
1755 run_cmd "$IP route add 172.16.102.0/24 dsfield 0x02 via 172.16.101.2"
1756 log_test $? 2 "Reject route with dsfield 0x02"
1757
1758 run_cmd "$IP route add 172.16.102.0/24 dsfield 0x03 via 172.16.101.2"
1759 log_test $? 2 "Reject route with dsfield 0x03"
1760
1761 # A generic route that doesn't take DSCP into account
1762 run_cmd "$IP route add 172.16.102.0/24 via 172.16.101.2"
1763
1764 # A more specific route for DSCP 0x10
1765 run_cmd "$IP route add 172.16.102.0/24 dsfield 0x10 via 172.16.103.2"
1766
1767 # DSCP 0x10 should match the specific route, no matter the ECN bits
1768 $IP route get fibmatch 172.16.102.1 dsfield 0x10 | \
1769 grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2"
1770 log_test $? 0 "IPv4 route with DSCP and ECN:Not-ECT"
1771
1772 $IP route get fibmatch 172.16.102.1 dsfield 0x11 | \
1773 grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2"
1774 log_test $? 0 "IPv4 route with DSCP and ECN:ECT(1)"
1775
1776 $IP route get fibmatch 172.16.102.1 dsfield 0x12 | \
1777 grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2"
1778 log_test $? 0 "IPv4 route with DSCP and ECN:ECT(0)"
1779
1780 $IP route get fibmatch 172.16.102.1 dsfield 0x13 | \
1781 grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2"
1782 log_test $? 0 "IPv4 route with DSCP and ECN:CE"
1783
1784 # Unknown DSCP should match the generic route, no matter the ECN bits
1785 $IP route get fibmatch 172.16.102.1 dsfield 0x14 | \
1786 grep -q "172.16.102.0/24 via 172.16.101.2"
1787 log_test $? 0 "IPv4 route with unknown DSCP and ECN:Not-ECT"
1788
1789 $IP route get fibmatch 172.16.102.1 dsfield 0x15 | \
1790 grep -q "172.16.102.0/24 via 172.16.101.2"
1791 log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(1)"
1792
1793 $IP route get fibmatch 172.16.102.1 dsfield 0x16 | \
1794 grep -q "172.16.102.0/24 via 172.16.101.2"
1795 log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(0)"
1796
1797 $IP route get fibmatch 172.16.102.1 dsfield 0x17 | \
1798 grep -q "172.16.102.0/24 via 172.16.101.2"
1799 log_test $? 0 "IPv4 route with unknown DSCP and ECN:CE"
1800
1801 # Null DSCP should match the generic route, no matter the ECN bits
1802 $IP route get fibmatch 172.16.102.1 dsfield 0x00 | \
1803 grep -q "172.16.102.0/24 via 172.16.101.2"
1804 log_test $? 0 "IPv4 route with no DSCP and ECN:Not-ECT"
1805
1806 $IP route get fibmatch 172.16.102.1 dsfield 0x01 | \
1807 grep -q "172.16.102.0/24 via 172.16.101.2"
1808 log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(1)"
1809
1810 $IP route get fibmatch 172.16.102.1 dsfield 0x02 | \
1811 grep -q "172.16.102.0/24 via 172.16.101.2"
1812 log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(0)"
1813
1814 $IP route get fibmatch 172.16.102.1 dsfield 0x03 | \
1815 grep -q "172.16.102.0/24 via 172.16.101.2"
1816 log_test $? 0 "IPv4 route with no DSCP and ECN:CE"
1817}
1818
1819ipv4_route_test()
1820{
1821 route_setup
1822
1823 ipv4_rt_add
1824 ipv4_rt_replace
1825 ipv4_local_rt_cache
1826 ipv4_rt_dsfield
1827
1828 route_cleanup
1829}
1830
1831ipv4_addr_metric_test()
1832{
1833 local rc
1834
1835 echo
1836 echo "IPv4 prefix route tests"
1837
1838 ip_addr_metric_check || return 1
1839
1840 setup
1841
1842 set -e
1843 $IP li add dummy1 type dummy
1844 $IP li add dummy2 type dummy
1845 $IP li set dummy1 up
1846 $IP li set dummy2 up
1847
1848 # default entry is metric 256
1849 run_cmd "$IP addr add dev dummy1 172.16.104.1/24"
1850 run_cmd "$IP addr add dev dummy2 172.16.104.2/24"
1851 set +e
1852
1853 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"
1854 log_test $? 0 "Default metric"
1855
1856 set -e
1857 run_cmd "$IP addr flush dev dummy1"
1858 run_cmd "$IP addr add dev dummy1 172.16.104.1/24 metric 257"
1859 set +e
1860
1861 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"
1862 log_test $? 0 "User specified metric on first device"
1863
1864 set -e
1865 run_cmd "$IP addr flush dev dummy2"
1866 run_cmd "$IP addr add dev dummy2 172.16.104.2/24 metric 258"
1867 set +e
1868
1869 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"
1870 log_test $? 0 "User specified metric on second device"
1871
1872 run_cmd "$IP addr del dev dummy1 172.16.104.1/24 metric 257"
1873 rc=$?
1874 if [ $rc -eq 0 ]; then
1875 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 258"
1876 rc=$?
1877 fi
1878 log_test $rc 0 "Delete of address on first device"
1879
1880 run_cmd "$IP addr change dev dummy2 172.16.104.2/24 metric 259"
1881 rc=$?
1882 if [ $rc -eq 0 ]; then
1883 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
1884 rc=$?
1885 fi
1886 log_test $rc 0 "Modify metric of address"
1887
1888 # verify prefix route removed on down
1889 run_cmd "$IP li set dev dummy2 down"
1890 rc=$?
1891 if [ $rc -eq 0 ]; then
1892 out=$($IP ro ls match 172.16.104.0/24)
1893 check_expected "${out}" ""
1894 rc=$?
1895 fi
1896 log_test $rc 0 "Prefix route removed on link down"
1897
1898 # verify prefix route re-inserted with assigned metric
1899 run_cmd "$IP li set dev dummy2 up"
1900 rc=$?
1901 if [ $rc -eq 0 ]; then
1902 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
1903 rc=$?
1904 fi
1905 log_test $rc 0 "Prefix route with metric on link up"
1906
1907 # explicitly check for metric changes on edge scenarios
1908 run_cmd "$IP addr flush dev dummy2"
1909 run_cmd "$IP addr add dev dummy2 172.16.104.0/24 metric 259"
1910 run_cmd "$IP addr change dev dummy2 172.16.104.0/24 metric 260"
1911 rc=$?
1912 if [ $rc -eq 0 ]; then
1913 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.0 metric 260"
1914 rc=$?
1915 fi
1916 log_test $rc 0 "Modify metric of .0/24 address"
1917
1918 run_cmd "$IP addr flush dev dummy2"
1919 run_cmd "$IP addr add dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 260"
1920 rc=$?
1921 if [ $rc -eq 0 ]; then
1922 check_route "172.16.104.2 dev dummy2 proto kernel scope link src 172.16.104.1 metric 260"
1923 rc=$?
1924 fi
1925 log_test $rc 0 "Set metric of address with peer route"
1926
1927 run_cmd "$IP addr change dev dummy2 172.16.104.1/32 peer 172.16.104.3 metric 261"
1928 rc=$?
1929 if [ $rc -eq 0 ]; then
1930 check_route "172.16.104.3 dev dummy2 proto kernel scope link src 172.16.104.1 metric 261"
1931 rc=$?
1932 fi
1933 log_test $rc 0 "Modify metric and peer address for peer route"
1934
1935 $IP li del dummy1
1936 $IP li del dummy2
1937 cleanup
1938}
1939
1940ipv4_route_metrics_test()
1941{
1942 local rc
1943
1944 echo
1945 echo "IPv4 route add / append tests"
1946
1947 route_setup
1948
1949 run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 mtu 1400"
1950 rc=$?
1951 if [ $rc -eq 0 ]; then
1952 check_route "172.16.111.0/24 via 172.16.101.2 dev veth1 mtu 1400"
1953 rc=$?
1954 fi
1955 log_test $rc 0 "Single path route with mtu metric"
1956
1957
1958 run_cmd "$IP ro add 172.16.112.0/24 mtu 1400 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1959 rc=$?
1960 if [ $rc -eq 0 ]; then
1961 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"
1962 rc=$?
1963 fi
1964 log_test $rc 0 "Multipath route with mtu metric"
1965
1966 $IP ro add 172.16.104.0/24 via 172.16.101.2 mtu 1300
1967 run_cmd "ip netns exec $ns1 ping -w1 -c1 -s 1500 172.16.104.1"
1968 log_test $? 0 "Using route with mtu metric"
1969
1970 run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 congctl lock foo"
1971 log_test $? 2 "Invalid metric (fails metric_convert)"
1972
1973 route_cleanup
1974}
1975
1976ipv4_del_addr_test()
1977{
1978 echo
1979 echo "IPv4 delete address route tests"
1980
1981 setup
1982
1983 set -e
1984 $IP li add dummy1 type dummy
1985 $IP li set dummy1 up
1986 $IP li add dummy2 type dummy
1987 $IP li set dummy2 up
1988 $IP li add red type vrf table 1111
1989 $IP li set red up
1990 $IP ro add vrf red unreachable default
1991 $IP li set dummy2 vrf red
1992
1993 $IP addr add dev dummy1 172.16.104.1/24
1994 $IP addr add dev dummy1 172.16.104.11/24
1995 $IP addr add dev dummy1 172.16.104.12/24
1996 $IP addr add dev dummy1 172.16.104.13/24
1997 $IP addr add dev dummy2 172.16.104.1/24
1998 $IP addr add dev dummy2 172.16.104.11/24
1999 $IP addr add dev dummy2 172.16.104.12/24
2000 $IP route add 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
2001 $IP route add 172.16.106.0/24 dev lo src 172.16.104.12
2002 $IP route add table 0 172.16.107.0/24 via 172.16.104.2 src 172.16.104.13
2003 $IP route add vrf red 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
2004 $IP route add vrf red 172.16.106.0/24 dev lo src 172.16.104.12
2005 set +e
2006
2007 # removing address from device in vrf should only remove route from vrf table
2008 echo " Regular FIB info"
2009
2010 $IP addr del dev dummy2 172.16.104.11/24
2011 $IP ro ls vrf red | grep -q 172.16.105.0/24
2012 log_test $? 1 "Route removed from VRF when source address deleted"
2013
2014 $IP ro ls | grep -q 172.16.105.0/24
2015 log_test $? 0 "Route in default VRF not removed"
2016
2017 $IP addr add dev dummy2 172.16.104.11/24
2018 $IP route add vrf red 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
2019
2020 $IP addr del dev dummy1 172.16.104.11/24
2021 $IP ro ls | grep -q 172.16.105.0/24
2022 log_test $? 1 "Route removed in default VRF when source address deleted"
2023
2024 $IP ro ls vrf red | grep -q 172.16.105.0/24
2025 log_test $? 0 "Route in VRF is not removed by address delete"
2026
2027 # removing address from device in vrf should only remove route from vrf
2028 # table even when the associated fib info only differs in table ID
2029 echo " Identical FIB info with different table ID"
2030
2031 $IP addr del dev dummy2 172.16.104.12/24
2032 $IP ro ls vrf red | grep -q 172.16.106.0/24
2033 log_test $? 1 "Route removed from VRF when source address deleted"
2034
2035 $IP ro ls | grep -q 172.16.106.0/24
2036 log_test $? 0 "Route in default VRF not removed"
2037
2038 $IP addr add dev dummy2 172.16.104.12/24
2039 $IP route add vrf red 172.16.106.0/24 dev lo src 172.16.104.12
2040
2041 $IP addr del dev dummy1 172.16.104.12/24
2042 $IP ro ls | grep -q 172.16.106.0/24
2043 log_test $? 1 "Route removed in default VRF when source address deleted"
2044
2045 $IP ro ls vrf red | grep -q 172.16.106.0/24
2046 log_test $? 0 "Route in VRF is not removed by address delete"
2047
2048 # removing address from device in default vrf should remove route from
2049 # the default vrf even when route was inserted with a table ID of 0.
2050 echo " Table ID 0"
2051
2052 $IP addr del dev dummy1 172.16.104.13/24
2053 $IP ro ls | grep -q 172.16.107.0/24
2054 log_test $? 1 "Route removed in default VRF when source address deleted"
2055
2056 $IP li del dummy1
2057 $IP li del dummy2
2058 cleanup
2059}
2060
2061ipv6_del_addr_test()
2062{
2063 echo
2064 echo "IPv6 delete address route tests"
2065
2066 setup
2067
2068 set -e
2069 for i in $(seq 6); do
2070 $IP li add dummy${i} up type dummy
2071 done
2072
2073 $IP li add red up type vrf table 1111
2074 $IP ro add vrf red unreachable default
2075 for i in $(seq 4 6); do
2076 $IP li set dummy${i} vrf red
2077 done
2078
2079 $IP addr add dev dummy1 fe80::1/128
2080 $IP addr add dev dummy1 2001:db8:101::1/64
2081 $IP addr add dev dummy1 2001:db8:101::10/64
2082 $IP addr add dev dummy1 2001:db8:101::11/64
2083 $IP addr add dev dummy1 2001:db8:101::12/64
2084 $IP addr add dev dummy1 2001:db8:101::13/64
2085 $IP addr add dev dummy1 2001:db8:101::14/64
2086 $IP addr add dev dummy1 2001:db8:101::15/64
2087 $IP addr add dev dummy2 fe80::1/128
2088 $IP addr add dev dummy2 2001:db8:101::1/64
2089 $IP addr add dev dummy2 2001:db8:101::11/64
2090 $IP addr add dev dummy3 fe80::1/128
2091
2092 $IP addr add dev dummy4 2001:db8:101::1/64
2093 $IP addr add dev dummy4 2001:db8:101::10/64
2094 $IP addr add dev dummy4 2001:db8:101::11/64
2095 $IP addr add dev dummy4 2001:db8:101::12/64
2096 $IP addr add dev dummy4 2001:db8:101::13/64
2097 $IP addr add dev dummy4 2001:db8:101::14/64
2098 $IP addr add dev dummy5 2001:db8:101::1/64
2099 $IP addr add dev dummy5 2001:db8:101::11/64
2100
2101 # Single device using src address
2102 $IP route add 2001:db8:110::/64 dev dummy3 src 2001:db8:101::10
2103 # Two devices with the same source address
2104 $IP route add 2001:db8:111::/64 dev dummy3 src 2001:db8:101::11
2105 # VRF with single device using src address
2106 $IP route add vrf red 2001:db8:110::/64 dev dummy6 src 2001:db8:101::10
2107 # VRF with two devices using src address
2108 $IP route add vrf red 2001:db8:111::/64 dev dummy6 src 2001:db8:101::11
2109 # src address and nexthop dev in same VRF
2110 $IP route add 2001:db8:112::/64 dev dummy3 src 2001:db8:101::12
2111 $IP route add vrf red 2001:db8:112::/64 dev dummy6 src 2001:db8:101::12
2112 # src address and nexthop device in different VRF
2113 $IP route add 2001:db8:113::/64 dev lo src 2001:db8:101::13
2114 $IP route add vrf red 2001:db8:113::/64 dev lo src 2001:db8:101::13
2115 # table ID 0
2116 $IP route add table 0 2001:db8:115::/64 via 2001:db8:101::2 src 2001:db8:101::15
2117 # Link local source route
2118 $IP route add 2001:db8:116::/64 dev dummy2 src fe80::1
2119 $IP route add 2001:db8:117::/64 dev dummy3 src fe80::1
2120 set +e
2121
2122 echo " Single device using src address"
2123
2124 $IP addr del dev dummy1 2001:db8:101::10/64
2125 $IP -6 route show | grep -q "src 2001:db8:101::10 "
2126 log_test $? 1 "Prefsrc removed when src address removed on other device"
2127
2128 echo " Two devices with the same source address"
2129
2130 $IP addr del dev dummy1 2001:db8:101::11/64
2131 $IP -6 route show | grep -q "src 2001:db8:101::11 "
2132 log_test $? 0 "Prefsrc not removed when src address exist on other device"
2133
2134 $IP addr del dev dummy2 2001:db8:101::11/64
2135 $IP -6 route show | grep -q "src 2001:db8:101::11 "
2136 log_test $? 1 "Prefsrc removed when src address removed on all devices"
2137
2138 echo " VRF with single device using src address"
2139
2140 $IP addr del dev dummy4 2001:db8:101::10/64
2141 $IP -6 route show vrf red | grep -q "src 2001:db8:101::10 "
2142 log_test $? 1 "Prefsrc removed when src address removed on other device"
2143
2144 echo " VRF with two devices using src address"
2145
2146 $IP addr del dev dummy4 2001:db8:101::11/64
2147 $IP -6 route show vrf red | grep -q "src 2001:db8:101::11 "
2148 log_test $? 0 "Prefsrc not removed when src address exist on other device"
2149
2150 $IP addr del dev dummy5 2001:db8:101::11/64
2151 $IP -6 route show vrf red | grep -q "src 2001:db8:101::11 "
2152 log_test $? 1 "Prefsrc removed when src address removed on all devices"
2153
2154 echo " src address and nexthop dev in same VRF"
2155
2156 $IP addr del dev dummy4 2001:db8:101::12/64
2157 $IP -6 route show vrf red | grep -q "src 2001:db8:101::12 "
2158 log_test $? 1 "Prefsrc removed from VRF when source address deleted"
2159 $IP -6 route show | grep -q " src 2001:db8:101::12 "
2160 log_test $? 0 "Prefsrc in default VRF not removed"
2161
2162 $IP addr add dev dummy4 2001:db8:101::12/64
2163 $IP route replace vrf red 2001:db8:112::/64 dev dummy6 src 2001:db8:101::12
2164 $IP addr del dev dummy1 2001:db8:101::12/64
2165 $IP -6 route show vrf red | grep -q "src 2001:db8:101::12 "
2166 log_test $? 0 "Prefsrc not removed from VRF when source address exist"
2167 $IP -6 route show | grep -q " src 2001:db8:101::12 "
2168 log_test $? 1 "Prefsrc in default VRF removed"
2169
2170 echo " src address and nexthop device in different VRF"
2171
2172 $IP addr del dev dummy4 2001:db8:101::13/64
2173 $IP -6 route show vrf red | grep -q "src 2001:db8:101::13 "
2174 log_test $? 0 "Prefsrc not removed from VRF when nexthop dev in diff VRF"
2175 $IP -6 route show | grep -q "src 2001:db8:101::13 "
2176 log_test $? 0 "Prefsrc not removed in default VRF"
2177
2178 $IP addr add dev dummy4 2001:db8:101::13/64
2179 $IP addr del dev dummy1 2001:db8:101::13/64
2180 $IP -6 route show vrf red | grep -q "src 2001:db8:101::13 "
2181 log_test $? 1 "Prefsrc removed from VRF when nexthop dev in diff VRF"
2182 $IP -6 route show | grep -q "src 2001:db8:101::13 "
2183 log_test $? 1 "Prefsrc removed in default VRF"
2184
2185 echo " Table ID 0"
2186
2187 $IP addr del dev dummy1 2001:db8:101::15/64
2188 $IP -6 route show | grep -q "src 2001:db8:101::15"
2189 log_test $? 1 "Prefsrc removed from default VRF when source address deleted"
2190
2191 echo " Link local source route"
2192 $IP addr del dev dummy1 fe80::1/128
2193 $IP -6 route show | grep -q "2001:db8:116::/64 dev dummy2 src fe80::1"
2194 log_test $? 0 "Prefsrc not removed when delete ll addr from other dev"
2195 $IP addr del dev dummy2 fe80::1/128
2196 $IP -6 route show | grep -q "2001:db8:116::/64 dev dummy2 src fe80::1"
2197 log_test $? 1 "Prefsrc removed when delete ll addr"
2198 $IP -6 route show | grep -q "2001:db8:117::/64 dev dummy3 src fe80::1"
2199 log_test $? 0 "Prefsrc not removed when delete ll addr from other dev"
2200 $IP addr add dev dummy1 fe80::1/128
2201 $IP addr del dev dummy3 fe80::1/128
2202 $IP -6 route show | grep -q "2001:db8:117::/64 dev dummy3 src fe80::1"
2203 log_test $? 1 "Prefsrc removed even ll addr still exist on other dev"
2204
2205 for i in $(seq 6); do
2206 $IP li del dummy${i}
2207 done
2208 cleanup
2209}
2210
2211ipv4_route_v6_gw_test()
2212{
2213 local rc
2214
2215 echo
2216 echo "IPv4 route with IPv6 gateway tests"
2217
2218 route_setup
2219 sleep 2
2220
2221 #
2222 # single path route
2223 #
2224 run_cmd "$IP ro add 172.16.104.0/24 via inet6 2001:db8:101::2"
2225 rc=$?
2226 log_test $rc 0 "Single path route with IPv6 gateway"
2227 if [ $rc -eq 0 ]; then
2228 check_route "172.16.104.0/24 via inet6 2001:db8:101::2 dev veth1"
2229 fi
2230
2231 run_cmd "ip netns exec $ns1 ping -w1 -c1 172.16.104.1"
2232 log_test $rc 0 "Single path route with IPv6 gateway - ping"
2233
2234 run_cmd "$IP ro del 172.16.104.0/24 via inet6 2001:db8:101::2"
2235 rc=$?
2236 log_test $rc 0 "Single path route delete"
2237 if [ $rc -eq 0 ]; then
2238 check_route "172.16.112.0/24"
2239 fi
2240
2241 #
2242 # multipath - v6 then v4
2243 #
2244 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"
2245 rc=$?
2246 log_test $rc 0 "Multipath route add - v6 nexthop then v4"
2247 if [ $rc -eq 0 ]; then
2248 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"
2249 fi
2250
2251 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"
2252 log_test $? 2 " Multipath route delete - nexthops in wrong order"
2253
2254 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"
2255 log_test $? 0 " Multipath route delete exact match"
2256
2257 #
2258 # multipath - v4 then v6
2259 #
2260 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"
2261 rc=$?
2262 log_test $rc 0 "Multipath route add - v4 nexthop then v6"
2263 if [ $rc -eq 0 ]; then
2264 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"
2265 fi
2266
2267 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"
2268 log_test $? 2 " Multipath route delete - nexthops in wrong order"
2269
2270 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"
2271 log_test $? 0 " Multipath route delete exact match"
2272
2273 route_cleanup
2274}
2275
2276socat_check()
2277{
2278 if [ ! -x "$(command -v socat)" ]; then
2279 echo "socat command not found. Skipping test"
2280 return 1
2281 fi
2282
2283 return 0
2284}
2285
2286iptables_check()
2287{
2288 iptables -t mangle -L OUTPUT &> /dev/null
2289 if [ $? -ne 0 ]; then
2290 echo "iptables configuration not supported. Skipping test"
2291 return 1
2292 fi
2293
2294 return 0
2295}
2296
2297ip6tables_check()
2298{
2299 ip6tables -t mangle -L OUTPUT &> /dev/null
2300 if [ $? -ne 0 ]; then
2301 echo "ip6tables configuration not supported. Skipping test"
2302 return 1
2303 fi
2304
2305 return 0
2306}
2307
2308ipv4_mangle_test()
2309{
2310 local rc
2311
2312 echo
2313 echo "IPv4 mangling tests"
2314
2315 socat_check || return 1
2316 iptables_check || return 1
2317
2318 route_setup
2319 sleep 2
2320
2321 local tmp_file=$(mktemp)
2322 ip netns exec $ns2 socat UDP4-LISTEN:54321,fork $tmp_file &
2323
2324 # Add a FIB rule and a route that will direct our connection to the
2325 # listening server.
2326 $IP rule add pref 100 ipproto udp sport 12345 dport 54321 table 123
2327 $IP route add table 123 172.16.101.0/24 dev veth1
2328
2329 # Add an unreachable route to the main table that will block our
2330 # connection in case the FIB rule is not hit.
2331 $IP route add unreachable 172.16.101.2/32
2332
2333 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
2334 log_test $? 0 " Connection with correct parameters"
2335
2336 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=11111"
2337 log_test $? 1 " Connection with incorrect parameters"
2338
2339 # Add a mangling rule and make sure connection is still successful.
2340 $NS_EXEC iptables -t mangle -A OUTPUT -j MARK --set-mark 1
2341
2342 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
2343 log_test $? 0 " Connection with correct parameters - mangling"
2344
2345 # Delete the mangling rule and make sure connection is still
2346 # successful.
2347 $NS_EXEC iptables -t mangle -D OUTPUT -j MARK --set-mark 1
2348
2349 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
2350 log_test $? 0 " Connection with correct parameters - no mangling"
2351
2352 # Verify connections were indeed successful on server side.
2353 [[ $(cat $tmp_file | wc -l) -eq 3 ]]
2354 log_test $? 0 " Connection check - server side"
2355
2356 $IP route del unreachable 172.16.101.2/32
2357 $IP route del table 123 172.16.101.0/24 dev veth1
2358 $IP rule del pref 100
2359
2360 kill_process %%
2361 rm $tmp_file
2362
2363 route_cleanup
2364}
2365
2366ipv6_mangle_test()
2367{
2368 local rc
2369
2370 echo
2371 echo "IPv6 mangling tests"
2372
2373 socat_check || return 1
2374 ip6tables_check || return 1
2375
2376 route_setup
2377 sleep 2
2378
2379 local tmp_file=$(mktemp)
2380 ip netns exec $ns2 socat UDP6-LISTEN:54321,fork $tmp_file &
2381
2382 # Add a FIB rule and a route that will direct our connection to the
2383 # listening server.
2384 $IP -6 rule add pref 100 ipproto udp sport 12345 dport 54321 table 123
2385 $IP -6 route add table 123 2001:db8:101::/64 dev veth1
2386
2387 # Add an unreachable route to the main table that will block our
2388 # connection in case the FIB rule is not hit.
2389 $IP -6 route add unreachable 2001:db8:101::2/128
2390
2391 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
2392 log_test $? 0 " Connection with correct parameters"
2393
2394 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=11111"
2395 log_test $? 1 " Connection with incorrect parameters"
2396
2397 # Add a mangling rule and make sure connection is still successful.
2398 $NS_EXEC ip6tables -t mangle -A OUTPUT -j MARK --set-mark 1
2399
2400 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
2401 log_test $? 0 " Connection with correct parameters - mangling"
2402
2403 # Delete the mangling rule and make sure connection is still
2404 # successful.
2405 $NS_EXEC ip6tables -t mangle -D OUTPUT -j MARK --set-mark 1
2406
2407 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
2408 log_test $? 0 " Connection with correct parameters - no mangling"
2409
2410 # Verify connections were indeed successful on server side.
2411 [[ $(cat $tmp_file | wc -l) -eq 3 ]]
2412 log_test $? 0 " Connection check - server side"
2413
2414 $IP -6 route del unreachable 2001:db8:101::2/128
2415 $IP -6 route del table 123 2001:db8:101::/64 dev veth1
2416 $IP -6 rule del pref 100
2417
2418 kill_process %%
2419 rm $tmp_file
2420
2421 route_cleanup
2422}
2423
2424ip_neigh_get_check()
2425{
2426 ip neigh help 2>&1 | grep -q 'ip neigh get'
2427 if [ $? -ne 0 ]; then
2428 echo "iproute2 command does not support neigh get. Skipping test"
2429 return 1
2430 fi
2431
2432 return 0
2433}
2434
2435ipv4_bcast_neigh_test()
2436{
2437 local rc
2438
2439 echo
2440 echo "IPv4 broadcast neighbour tests"
2441
2442 ip_neigh_get_check || return 1
2443
2444 setup
2445
2446 set -e
2447 run_cmd "$IP neigh add 192.0.2.111 lladdr 00:11:22:33:44:55 nud perm dev dummy0"
2448 run_cmd "$IP neigh add 192.0.2.255 lladdr 00:11:22:33:44:55 nud perm dev dummy0"
2449
2450 run_cmd "$IP neigh get 192.0.2.111 dev dummy0"
2451 run_cmd "$IP neigh get 192.0.2.255 dev dummy0"
2452
2453 run_cmd "$IP address add 192.0.2.1/24 broadcast 192.0.2.111 dev dummy0"
2454
2455 run_cmd "$IP neigh add 203.0.113.111 nud failed dev dummy0"
2456 run_cmd "$IP neigh add 203.0.113.255 nud failed dev dummy0"
2457
2458 run_cmd "$IP neigh get 203.0.113.111 dev dummy0"
2459 run_cmd "$IP neigh get 203.0.113.255 dev dummy0"
2460
2461 run_cmd "$IP address add 203.0.113.1/24 broadcast 203.0.113.111 dev dummy0"
2462 set +e
2463
2464 run_cmd "$IP neigh get 192.0.2.111 dev dummy0"
2465 log_test $? 0 "Resolved neighbour for broadcast address"
2466
2467 run_cmd "$IP neigh get 192.0.2.255 dev dummy0"
2468 log_test $? 0 "Resolved neighbour for network broadcast address"
2469
2470 run_cmd "$IP neigh get 203.0.113.111 dev dummy0"
2471 log_test $? 2 "Unresolved neighbour for broadcast address"
2472
2473 run_cmd "$IP neigh get 203.0.113.255 dev dummy0"
2474 log_test $? 2 "Unresolved neighbour for network broadcast address"
2475
2476 cleanup
2477}
2478
2479mpath_dep_check()
2480{
2481 if [ ! -x "$(command -v mausezahn)" ]; then
2482 echo "mausezahn command not found. Skipping test"
2483 return 1
2484 fi
2485
2486 if [ ! -x "$(command -v jq)" ]; then
2487 echo "jq command not found. Skipping test"
2488 return 1
2489 fi
2490
2491 if [ ! -x "$(command -v bc)" ]; then
2492 echo "bc command not found. Skipping test"
2493 return 1
2494 fi
2495
2496 if [ ! -x "$(command -v perf)" ]; then
2497 echo "perf command not found. Skipping test"
2498 return 1
2499 fi
2500
2501 perf list fib:* | grep -q fib_table_lookup
2502 if [ $? -ne 0 ]; then
2503 echo "IPv4 FIB tracepoint not found. Skipping test"
2504 return 1
2505 fi
2506
2507 perf list fib6:* | grep -q fib6_table_lookup
2508 if [ $? -ne 0 ]; then
2509 echo "IPv6 FIB tracepoint not found. Skipping test"
2510 return 1
2511 fi
2512
2513 return 0
2514}
2515
2516link_stats_get()
2517{
2518 local ns=$1; shift
2519 local dev=$1; shift
2520 local dir=$1; shift
2521 local stat=$1; shift
2522
2523 ip -n $ns -j -s link show dev $dev \
2524 | jq '.[]["stats64"]["'$dir'"]["'$stat'"]'
2525}
2526
2527list_rcv_eval()
2528{
2529 local file=$1; shift
2530 local expected=$1; shift
2531
2532 local count=$(tail -n 1 $file | jq '.["counter-value"] | tonumber | floor')
2533 local ratio=$(echo "scale=2; $count / $expected" | bc -l)
2534 local res=$(echo "$ratio >= 0.95" | bc)
2535 [[ $res -eq 1 ]]
2536 log_test $? 0 "Multipath route hit ratio ($ratio)"
2537}
2538
2539ipv4_mpath_list_test()
2540{
2541 echo
2542 echo "IPv4 multipath list receive tests"
2543
2544 mpath_dep_check || return 1
2545
2546 route_setup
2547
2548 set -e
2549 run_cmd "ip netns exec $ns1 ethtool -K veth1 tcp-segmentation-offload off"
2550
2551 run_cmd "ip netns exec $ns2 bash -c \"echo 20000 > /sys/class/net/veth2/gro_flush_timeout\""
2552 run_cmd "ip netns exec $ns2 bash -c \"echo 1 > /sys/class/net/veth2/napi_defer_hard_irqs\""
2553 run_cmd "ip netns exec $ns2 ethtool -K veth2 generic-receive-offload on"
2554 run_cmd "ip -n $ns2 link add name nh1 up type dummy"
2555 run_cmd "ip -n $ns2 link add name nh2 up type dummy"
2556 run_cmd "ip -n $ns2 address add 172.16.201.1/24 dev nh1"
2557 run_cmd "ip -n $ns2 address add 172.16.202.1/24 dev nh2"
2558 run_cmd "ip -n $ns2 neigh add 172.16.201.2 lladdr 00:11:22:33:44:55 nud perm dev nh1"
2559 run_cmd "ip -n $ns2 neigh add 172.16.202.2 lladdr 00:aa:bb:cc:dd:ee nud perm dev nh2"
2560 run_cmd "ip -n $ns2 route add 203.0.113.0/24
2561 nexthop via 172.16.201.2 nexthop via 172.16.202.2"
2562 run_cmd "ip netns exec $ns2 sysctl -qw net.ipv4.fib_multipath_hash_policy=1"
2563 set +e
2564
2565 local dmac=$(ip -n $ns2 -j link show dev veth2 | jq -r '.[]["address"]')
2566 local tmp_file=$(mktemp)
2567 local cmd="ip netns exec $ns1 mausezahn veth1 -a own -b $dmac
2568 -A 172.16.101.1 -B 203.0.113.1 -t udp 'sp=12345,dp=0-65535' -q"
2569
2570 # Packets forwarded in a list using a multipath route must not reuse a
2571 # cached result so that a flow always hits the same nexthop. In other
2572 # words, the FIB lookup tracepoint needs to be triggered for every
2573 # packet.
2574 local t0_rx_pkts=$(link_stats_get $ns2 veth2 rx packets)
2575 run_cmd "perf stat -a -e fib:fib_table_lookup --filter 'err == 0' -j -o $tmp_file -- $cmd"
2576 local t1_rx_pkts=$(link_stats_get $ns2 veth2 rx packets)
2577 local diff=$(echo $t1_rx_pkts - $t0_rx_pkts | bc -l)
2578 list_rcv_eval $tmp_file $diff
2579
2580 rm $tmp_file
2581 route_cleanup
2582}
2583
2584ipv6_mpath_list_test()
2585{
2586 echo
2587 echo "IPv6 multipath list receive tests"
2588
2589 mpath_dep_check || return 1
2590
2591 route_setup
2592
2593 set -e
2594 run_cmd "ip netns exec $ns1 ethtool -K veth1 tcp-segmentation-offload off"
2595
2596 run_cmd "ip netns exec $ns2 bash -c \"echo 20000 > /sys/class/net/veth2/gro_flush_timeout\""
2597 run_cmd "ip netns exec $ns2 bash -c \"echo 1 > /sys/class/net/veth2/napi_defer_hard_irqs\""
2598 run_cmd "ip netns exec $ns2 ethtool -K veth2 generic-receive-offload on"
2599 run_cmd "ip -n $ns2 link add name nh1 up type dummy"
2600 run_cmd "ip -n $ns2 link add name nh2 up type dummy"
2601 run_cmd "ip -n $ns2 -6 address add 2001:db8:201::1/64 dev nh1"
2602 run_cmd "ip -n $ns2 -6 address add 2001:db8:202::1/64 dev nh2"
2603 run_cmd "ip -n $ns2 -6 neigh add 2001:db8:201::2 lladdr 00:11:22:33:44:55 nud perm dev nh1"
2604 run_cmd "ip -n $ns2 -6 neigh add 2001:db8:202::2 lladdr 00:aa:bb:cc:dd:ee nud perm dev nh2"
2605 run_cmd "ip -n $ns2 -6 route add 2001:db8:301::/64
2606 nexthop via 2001:db8:201::2 nexthop via 2001:db8:202::2"
2607 run_cmd "ip netns exec $ns2 sysctl -qw net.ipv6.fib_multipath_hash_policy=1"
2608 set +e
2609
2610 local dmac=$(ip -n $ns2 -j link show dev veth2 | jq -r '.[]["address"]')
2611 local tmp_file=$(mktemp)
2612 local cmd="ip netns exec $ns1 mausezahn -6 veth1 -a own -b $dmac
2613 -A 2001:db8:101::1 -B 2001:db8:301::1 -t udp 'sp=12345,dp=0-65535' -q"
2614
2615 # Packets forwarded in a list using a multipath route must not reuse a
2616 # cached result so that a flow always hits the same nexthop. In other
2617 # words, the FIB lookup tracepoint needs to be triggered for every
2618 # packet.
2619 local t0_rx_pkts=$(link_stats_get $ns2 veth2 rx packets)
2620 run_cmd "perf stat -a -e fib6:fib6_table_lookup --filter 'err == 0' -j -o $tmp_file -- $cmd"
2621 local t1_rx_pkts=$(link_stats_get $ns2 veth2 rx packets)
2622 local diff=$(echo $t1_rx_pkts - $t0_rx_pkts | bc -l)
2623 list_rcv_eval $tmp_file $diff
2624
2625 rm $tmp_file
2626 route_cleanup
2627}
2628
2629tc_set_flower_counter__saddr_syn() {
2630 tc_set_flower_counter $1 $2 $3 "src_ip $4 ip_proto tcp tcp_flags 0x2"
2631}
2632
2633ip_mpath_balance_dep_check()
2634{
2635 if [ ! -x "$(command -v socat)" ]; then
2636 echo "socat command not found. Skipping test"
2637 return 1
2638 fi
2639
2640 if [ ! -x "$(command -v jq)" ]; then
2641 echo "jq command not found. Skipping test"
2642 return 1
2643 fi
2644}
2645
2646ip_mpath_balance() {
2647 local -r ipver=$1
2648 local -r daddr=$2
2649 local -r num_conn=20
2650
2651 for i in $(seq 1 $num_conn); do
2652 ip netns exec $ns3 socat $ipver TCP-LISTEN:8000 STDIO >/dev/null &
2653 sleep 0.02
2654 echo -n a | ip netns exec $ns1 socat $ipver STDIO TCP:$daddr:8000
2655 done
2656
2657 local -r syn0="$(tc_get_flower_counter $ns1 veth1)"
2658 local -r syn1="$(tc_get_flower_counter $ns1 veth3)"
2659 local -r syns=$((syn0+syn1))
2660
2661 [ "$VERBOSE" = "1" ] && echo "multipath: syns seen: ($syn0,$syn1)"
2662
2663 [[ $syns -ge $num_conn ]] && [[ $syn0 -gt 0 ]] && [[ $syn1 -gt 0 ]]
2664}
2665
2666ipv4_mpath_balance_test()
2667{
2668 echo
2669 echo "IPv4 multipath load balance test"
2670
2671 ip_mpath_balance_dep_check || return 1
2672 forwarding_setup
2673
2674 $IP route add 172.16.105.1 \
2675 nexthop via 172.16.101.2 \
2676 nexthop via 172.16.103.2
2677
2678 ip netns exec $ns1 \
2679 sysctl -q -w net.ipv4.fib_multipath_hash_policy=1
2680
2681 tc_set_flower_counter__saddr_syn $ns1 4 veth1 172.16.101.1
2682 tc_set_flower_counter__saddr_syn $ns1 4 veth3 172.16.103.1
2683
2684 ip_mpath_balance -4 172.16.105.1
2685
2686 log_test $? 0 "IPv4 multipath loadbalance"
2687
2688 forwarding_cleanup
2689}
2690
2691ipv6_mpath_balance_test()
2692{
2693 echo
2694 echo "IPv6 multipath load balance test"
2695
2696 ip_mpath_balance_dep_check || return 1
2697 forwarding_setup
2698
2699 $IP route add 2001:db8:105::1\
2700 nexthop via 2001:db8:101::2 \
2701 nexthop via 2001:db8:103::2
2702
2703 ip netns exec $ns1 \
2704 sysctl -q -w net.ipv6.fib_multipath_hash_policy=1
2705
2706 tc_set_flower_counter__saddr_syn $ns1 6 veth1 2001:db8:101::1
2707 tc_set_flower_counter__saddr_syn $ns1 6 veth3 2001:db8:103::1
2708
2709 ip_mpath_balance -6 "[2001:db8:105::1]"
2710
2711 log_test $? 0 "IPv6 multipath loadbalance"
2712
2713 forwarding_cleanup
2714}
2715
2716################################################################################
2717# usage
2718
2719usage()
2720{
2721 cat <<EOF
2722usage: ${0##*/} OPTS
2723
2724 -t <test> Test(s) to run (default: all)
2725 (options: $TESTS)
2726 -p Pause on fail
2727 -P Pause after each test before cleanup
2728 -v verbose mode (show commands and output)
2729EOF
2730}
2731
2732################################################################################
2733# main
2734
2735trap cleanup EXIT
2736
2737while getopts :t:pPhv o
2738do
2739 case $o in
2740 t) TESTS=$OPTARG;;
2741 p) PAUSE_ON_FAIL=yes;;
2742 P) PAUSE=yes;;
2743 v) VERBOSE=$(($VERBOSE + 1));;
2744 h) usage; exit 0;;
2745 *) usage; exit 1;;
2746 esac
2747done
2748
2749PEER_CMD="ip netns exec ${PEER_NS}"
2750
2751# make sure we don't pause twice
2752[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
2753
2754if [ "$(id -u)" -ne 0 ];then
2755 echo "SKIP: Need root privileges"
2756 exit $ksft_skip;
2757fi
2758
2759if [ ! -x "$(command -v ip)" ]; then
2760 echo "SKIP: Could not run test without ip tool"
2761 exit $ksft_skip
2762fi
2763
2764ip route help 2>&1 | grep -q fibmatch
2765if [ $? -ne 0 ]; then
2766 echo "SKIP: iproute2 too old, missing fibmatch"
2767 exit $ksft_skip
2768fi
2769
2770# start clean
2771cleanup &> /dev/null
2772
2773for t in $TESTS
2774do
2775 case $t in
2776 fib_unreg_test|unregister) fib_unreg_test;;
2777 fib_down_test|down) fib_down_test;;
2778 fib_carrier_test|carrier) fib_carrier_test;;
2779 fib_rp_filter_test|rp_filter) fib_rp_filter_test;;
2780 fib_nexthop_test|nexthop) fib_nexthop_test;;
2781 fib_notify_test|ipv4_notify) fib_notify_test;;
2782 fib6_notify_test|ipv6_notify) fib6_notify_test;;
2783 fib_suppress_test|suppress) fib_suppress_test;;
2784 ipv6_route_test|ipv6_rt) ipv6_route_test;;
2785 ipv4_route_test|ipv4_rt) ipv4_route_test;;
2786 ipv6_addr_metric) ipv6_addr_metric_test;;
2787 ipv4_addr_metric) ipv4_addr_metric_test;;
2788 ipv4_del_addr) ipv4_del_addr_test;;
2789 ipv6_del_addr) ipv6_del_addr_test;;
2790 ipv6_route_metrics) ipv6_route_metrics_test;;
2791 ipv4_route_metrics) ipv4_route_metrics_test;;
2792 ipv4_route_v6_gw) ipv4_route_v6_gw_test;;
2793 ipv4_mangle) ipv4_mangle_test;;
2794 ipv6_mangle) ipv6_mangle_test;;
2795 ipv4_bcast_neigh) ipv4_bcast_neigh_test;;
2796 fib6_gc_test|ipv6_gc) fib6_gc_test;;
2797 ipv4_mpath_list) ipv4_mpath_list_test;;
2798 ipv6_mpath_list) ipv6_mpath_list_test;;
2799 ipv4_mpath_balance) ipv4_mpath_balance_test;;
2800 ipv6_mpath_balance) ipv6_mpath_balance_test;;
2801
2802 help) echo "Test names: $TESTS"; exit 0;;
2803 esac
2804done
2805
2806if [ "$TESTS" != "none" ]; then
2807 printf "\nTests passed: %3d\n" ${nsuccess}
2808 printf "Tests failed: %3d\n" ${nfail}
2809fi
2810
2811exit $ret