OSDN Git Service

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