Merge tag 'overflow-v4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees...
[linux-2.6-microblaze.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 VERBOSE=${VERBOSE:=0}
12 PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
13 IP="ip -netns testns"
14
15 log_test()
16 {
17         local rc=$1
18         local expected=$2
19         local msg="$3"
20
21         if [ ${rc} -eq ${expected} ]; then
22                 printf "    TEST: %-60s  [ OK ]\n" "${msg}"
23         else
24                 ret=1
25                 printf "    TEST: %-60s  [FAIL]\n" "${msg}"
26                 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
27                 echo
28                         echo "hit enter to continue, 'q' to quit"
29                         read a
30                         [ "$a" = "q" ] && exit 1
31                 fi
32         fi
33 }
34
35 setup()
36 {
37         set -e
38         ip netns add testns
39         $IP link set dev lo up
40
41         $IP link add dummy0 type dummy
42         $IP link set dev dummy0 up
43         $IP address add 198.51.100.1/24 dev dummy0
44         $IP -6 address add 2001:db8:1::1/64 dev dummy0
45         set +e
46
47 }
48
49 cleanup()
50 {
51         $IP link del dev dummy0 &> /dev/null
52         ip netns del testns
53 }
54
55 get_linklocal()
56 {
57         local dev=$1
58         local addr
59
60         addr=$($IP -6 -br addr show dev ${dev} | \
61         awk '{
62                 for (i = 3; i <= NF; ++i) {
63                         if ($i ~ /^fe80/)
64                                 print $i
65                 }
66         }'
67         )
68         addr=${addr/\/*}
69
70         [ -z "$addr" ] && return 1
71
72         echo $addr
73
74         return 0
75 }
76
77 fib_unreg_unicast_test()
78 {
79         echo
80         echo "Single path route test"
81
82         setup
83
84         echo "    Start point"
85         $IP route get fibmatch 198.51.100.2 &> /dev/null
86         log_test $? 0 "IPv4 fibmatch"
87         $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
88         log_test $? 0 "IPv6 fibmatch"
89
90         set -e
91         $IP link del dev dummy0
92         set +e
93
94         echo "    Nexthop device deleted"
95         $IP route get fibmatch 198.51.100.2 &> /dev/null
96         log_test $? 2 "IPv4 fibmatch - no route"
97         $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
98         log_test $? 2 "IPv6 fibmatch - no route"
99
100         cleanup
101 }
102
103 fib_unreg_multipath_test()
104 {
105
106         echo
107         echo "Multipath route test"
108
109         setup
110
111         set -e
112         $IP link add dummy1 type dummy
113         $IP link set dev dummy1 up
114         $IP address add 192.0.2.1/24 dev dummy1
115         $IP -6 address add 2001:db8:2::1/64 dev dummy1
116
117         $IP route add 203.0.113.0/24 \
118                 nexthop via 198.51.100.2 dev dummy0 \
119                 nexthop via 192.0.2.2 dev dummy1
120         $IP -6 route add 2001:db8:3::/64 \
121                 nexthop via 2001:db8:1::2 dev dummy0 \
122                 nexthop via 2001:db8:2::2 dev dummy1
123         set +e
124
125         echo "    Start point"
126         $IP route get fibmatch 203.0.113.1 &> /dev/null
127         log_test $? 0 "IPv4 fibmatch"
128         $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
129         log_test $? 0 "IPv6 fibmatch"
130
131         set -e
132         $IP link del dev dummy0
133         set +e
134
135         echo "    One nexthop device deleted"
136         $IP route get fibmatch 203.0.113.1 &> /dev/null
137         log_test $? 2 "IPv4 - multipath route removed on delete"
138
139         $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
140         # In IPv6 we do not flush the entire multipath route.
141         log_test $? 0 "IPv6 - multipath down to single path"
142
143         set -e
144         $IP link del dev dummy1
145         set +e
146
147         echo "    Second nexthop device deleted"
148         $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
149         log_test $? 2 "IPv6 - no route"
150
151         cleanup
152 }
153
154 fib_unreg_test()
155 {
156         fib_unreg_unicast_test
157         fib_unreg_multipath_test
158 }
159
160 fib_down_unicast_test()
161 {
162         echo
163         echo "Single path, admin down"
164
165         setup
166
167         echo "    Start point"
168         $IP route get fibmatch 198.51.100.2 &> /dev/null
169         log_test $? 0 "IPv4 fibmatch"
170         $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
171         log_test $? 0 "IPv6 fibmatch"
172
173         set -e
174         $IP link set dev dummy0 down
175         set +e
176
177         echo "    Route deleted on down"
178         $IP route get fibmatch 198.51.100.2 &> /dev/null
179         log_test $? 2 "IPv4 fibmatch"
180         $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
181         log_test $? 2 "IPv6 fibmatch"
182
183         cleanup
184 }
185
186 fib_down_multipath_test_do()
187 {
188         local down_dev=$1
189         local up_dev=$2
190
191         $IP route get fibmatch 203.0.113.1 \
192                 oif $down_dev &> /dev/null
193         log_test $? 2 "IPv4 fibmatch on down device"
194         $IP -6 route get fibmatch 2001:db8:3::1 \
195                 oif $down_dev &> /dev/null
196         log_test $? 2 "IPv6 fibmatch on down device"
197
198         $IP route get fibmatch 203.0.113.1 \
199                 oif $up_dev &> /dev/null
200         log_test $? 0 "IPv4 fibmatch on up device"
201         $IP -6 route get fibmatch 2001:db8:3::1 \
202                 oif $up_dev &> /dev/null
203         log_test $? 0 "IPv6 fibmatch on up device"
204
205         $IP route get fibmatch 203.0.113.1 | \
206                 grep $down_dev | grep -q "dead linkdown"
207         log_test $? 0 "IPv4 flags on down device"
208         $IP -6 route get fibmatch 2001:db8:3::1 | \
209                 grep $down_dev | grep -q "dead linkdown"
210         log_test $? 0 "IPv6 flags on down device"
211
212         $IP route get fibmatch 203.0.113.1 | \
213                 grep $up_dev | grep -q "dead linkdown"
214         log_test $? 1 "IPv4 flags on up device"
215         $IP -6 route get fibmatch 2001:db8:3::1 | \
216                 grep $up_dev | grep -q "dead linkdown"
217         log_test $? 1 "IPv6 flags on up device"
218 }
219
220 fib_down_multipath_test()
221 {
222         echo
223         echo "Admin down multipath"
224
225         setup
226
227         set -e
228         $IP link add dummy1 type dummy
229         $IP link set dev dummy1 up
230
231         $IP address add 192.0.2.1/24 dev dummy1
232         $IP -6 address add 2001:db8:2::1/64 dev dummy1
233
234         $IP route add 203.0.113.0/24 \
235                 nexthop via 198.51.100.2 dev dummy0 \
236                 nexthop via 192.0.2.2 dev dummy1
237         $IP -6 route add 2001:db8:3::/64 \
238                 nexthop via 2001:db8:1::2 dev dummy0 \
239                 nexthop via 2001:db8:2::2 dev dummy1
240         set +e
241
242         echo "    Verify start point"
243         $IP route get fibmatch 203.0.113.1 &> /dev/null
244         log_test $? 0 "IPv4 fibmatch"
245
246         $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
247         log_test $? 0 "IPv6 fibmatch"
248
249         set -e
250         $IP link set dev dummy0 down
251         set +e
252
253         echo "    One device down, one up"
254         fib_down_multipath_test_do "dummy0" "dummy1"
255
256         set -e
257         $IP link set dev dummy0 up
258         $IP link set dev dummy1 down
259         set +e
260
261         echo "    Other device down and up"
262         fib_down_multipath_test_do "dummy1" "dummy0"
263
264         set -e
265         $IP link set dev dummy0 down
266         set +e
267
268         echo "    Both devices down"
269         $IP route get fibmatch 203.0.113.1 &> /dev/null
270         log_test $? 2 "IPv4 fibmatch"
271         $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
272         log_test $? 2 "IPv6 fibmatch"
273
274         $IP link del dev dummy1
275         cleanup
276 }
277
278 fib_down_test()
279 {
280         fib_down_unicast_test
281         fib_down_multipath_test
282 }
283
284 # Local routes should not be affected when carrier changes.
285 fib_carrier_local_test()
286 {
287         echo
288         echo "Local carrier tests - single path"
289
290         setup
291
292         set -e
293         $IP link set dev dummy0 carrier on
294         set +e
295
296         echo "    Start point"
297         $IP route get fibmatch 198.51.100.1 &> /dev/null
298         log_test $? 0 "IPv4 fibmatch"
299         $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
300         log_test $? 0 "IPv6 fibmatch"
301
302         $IP route get fibmatch 198.51.100.1 | \
303                 grep -q "linkdown"
304         log_test $? 1 "IPv4 - no linkdown flag"
305         $IP -6 route get fibmatch 2001:db8:1::1 | \
306                 grep -q "linkdown"
307         log_test $? 1 "IPv6 - no linkdown flag"
308
309         set -e
310         $IP link set dev dummy0 carrier off
311         sleep 1
312         set +e
313
314         echo "    Carrier off on nexthop"
315         $IP route get fibmatch 198.51.100.1 &> /dev/null
316         log_test $? 0 "IPv4 fibmatch"
317         $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
318         log_test $? 0 "IPv6 fibmatch"
319
320         $IP route get fibmatch 198.51.100.1 | \
321                 grep -q "linkdown"
322         log_test $? 1 "IPv4 - linkdown flag set"
323         $IP -6 route get fibmatch 2001:db8:1::1 | \
324                 grep -q "linkdown"
325         log_test $? 1 "IPv6 - linkdown flag set"
326
327         set -e
328         $IP address add 192.0.2.1/24 dev dummy0
329         $IP -6 address add 2001:db8:2::1/64 dev dummy0
330         set +e
331
332         echo "    Route to local address with carrier down"
333         $IP route get fibmatch 192.0.2.1 &> /dev/null
334         log_test $? 0 "IPv4 fibmatch"
335         $IP -6 route get fibmatch 2001:db8:2::1 &> /dev/null
336         log_test $? 0 "IPv6 fibmatch"
337
338         $IP route get fibmatch 192.0.2.1 | \
339                 grep -q "linkdown"
340         log_test $? 1 "IPv4 linkdown flag set"
341         $IP -6 route get fibmatch 2001:db8:2::1 | \
342                 grep -q "linkdown"
343         log_test $? 1 "IPv6 linkdown flag set"
344
345         cleanup
346 }
347
348 fib_carrier_unicast_test()
349 {
350         ret=0
351
352         echo
353         echo "Single path route carrier test"
354
355         setup
356
357         set -e
358         $IP link set dev dummy0 carrier on
359         set +e
360
361         echo "    Start point"
362         $IP route get fibmatch 198.51.100.2 &> /dev/null
363         log_test $? 0 "IPv4 fibmatch"
364         $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
365         log_test $? 0 "IPv6 fibmatch"
366
367         $IP route get fibmatch 198.51.100.2 | \
368                 grep -q "linkdown"
369         log_test $? 1 "IPv4 no linkdown flag"
370         $IP -6 route get fibmatch 2001:db8:1::2 | \
371                 grep -q "linkdown"
372         log_test $? 1 "IPv6 no linkdown flag"
373
374         set -e
375         $IP link set dev dummy0 carrier off
376         set +e
377
378         echo "    Carrier down"
379         $IP route get fibmatch 198.51.100.2 &> /dev/null
380         log_test $? 0 "IPv4 fibmatch"
381         $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
382         log_test $? 0 "IPv6 fibmatch"
383
384         $IP route get fibmatch 198.51.100.2 | \
385                 grep -q "linkdown"
386         log_test $? 0 "IPv4 linkdown flag set"
387         $IP -6 route get fibmatch 2001:db8:1::2 | \
388                 grep -q "linkdown"
389         log_test $? 0 "IPv6 linkdown flag set"
390
391         set -e
392         $IP address add 192.0.2.1/24 dev dummy0
393         $IP -6 address add 2001:db8:2::1/64 dev dummy0
394         set +e
395
396         echo "    Second address added with carrier down"
397         $IP route get fibmatch 192.0.2.2 &> /dev/null
398         log_test $? 0 "IPv4 fibmatch"
399         $IP -6 route get fibmatch 2001:db8:2::2 &> /dev/null
400         log_test $? 0 "IPv6 fibmatch"
401
402         $IP route get fibmatch 192.0.2.2 | \
403                 grep -q "linkdown"
404         log_test $? 0 "IPv4 linkdown flag set"
405         $IP -6 route get fibmatch 2001:db8:2::2 | \
406                 grep -q "linkdown"
407         log_test $? 0 "IPv6 linkdown flag set"
408
409         cleanup
410 }
411
412 fib_carrier_test()
413 {
414         fib_carrier_local_test
415         fib_carrier_unicast_test
416 }
417
418 ################################################################################
419 # Tests on nexthop spec
420
421 # run 'ip route add' with given spec
422 add_rt()
423 {
424         local desc="$1"
425         local erc=$2
426         local vrf=$3
427         local pfx=$4
428         local gw=$5
429         local dev=$6
430         local cmd out rc
431
432         [ "$vrf" = "-" ] && vrf="default"
433         [ -n "$gw" ] && gw="via $gw"
434         [ -n "$dev" ] && dev="dev $dev"
435
436         cmd="$IP route add vrf $vrf $pfx $gw $dev"
437         if [ "$VERBOSE" = "1" ]; then
438                 printf "\n    COMMAND: $cmd\n"
439         fi
440
441         out=$(eval $cmd 2>&1)
442         rc=$?
443         if [ "$VERBOSE" = "1" -a -n "$out" ]; then
444                 echo "    $out"
445         fi
446         log_test $rc $erc "$desc"
447 }
448
449 fib4_nexthop()
450 {
451         echo
452         echo "IPv4 nexthop tests"
453
454         echo "<<< write me >>>"
455 }
456
457 fib6_nexthop()
458 {
459         local lldummy=$(get_linklocal dummy0)
460         local llv1=$(get_linklocal dummy0)
461
462         if [ -z "$lldummy" ]; then
463                 echo "Failed to get linklocal address for dummy0"
464                 return 1
465         fi
466         if [ -z "$llv1" ]; then
467                 echo "Failed to get linklocal address for veth1"
468                 return 1
469         fi
470
471         echo
472         echo "IPv6 nexthop tests"
473
474         add_rt "Directly connected nexthop, unicast address" 0 \
475                 - 2001:db8:101::/64 2001:db8:1::2
476         add_rt "Directly connected nexthop, unicast address with device" 0 \
477                 - 2001:db8:102::/64 2001:db8:1::2 "dummy0"
478         add_rt "Gateway is linklocal address" 0 \
479                 - 2001:db8:103::1/64 $llv1 "veth0"
480
481         # fails because LL address requires a device
482         add_rt "Gateway is linklocal address, no device" 2 \
483                 - 2001:db8:104::1/64 $llv1
484
485         # local address can not be a gateway
486         add_rt "Gateway can not be local unicast address" 2 \
487                 - 2001:db8:105::/64 2001:db8:1::1
488         add_rt "Gateway can not be local unicast address, with device" 2 \
489                 - 2001:db8:106::/64 2001:db8:1::1 "dummy0"
490         add_rt "Gateway can not be a local linklocal address" 2 \
491                 - 2001:db8:107::1/64 $lldummy "dummy0"
492
493         # VRF tests
494         add_rt "Gateway can be local address in a VRF" 0 \
495                 - 2001:db8:108::/64 2001:db8:51::2
496         add_rt "Gateway can be local address in a VRF, with device" 0 \
497                 - 2001:db8:109::/64 2001:db8:51::2 "veth0"
498         add_rt "Gateway can be local linklocal address in a VRF" 0 \
499                 - 2001:db8:110::1/64 $llv1 "veth0"
500
501         add_rt "Redirect to VRF lookup" 0 \
502                 - 2001:db8:111::/64 "" "red"
503
504         add_rt "VRF route, gateway can be local address in default VRF" 0 \
505                 red 2001:db8:112::/64 2001:db8:51::1
506
507         # local address in same VRF fails
508         add_rt "VRF route, gateway can not be a local address" 2 \
509                 red 2001:db8:113::1/64 2001:db8:2::1
510         add_rt "VRF route, gateway can not be a local addr with device" 2 \
511                 red 2001:db8:114::1/64 2001:db8:2::1 "dummy1"
512 }
513
514 # Default VRF:
515 #   dummy0 - 198.51.100.1/24 2001:db8:1::1/64
516 #   veth0  - 192.0.2.1/24    2001:db8:51::1/64
517 #
518 # VRF red:
519 #   dummy1 - 192.168.2.1/24 2001:db8:2::1/64
520 #   veth1  - 192.0.2.2/24   2001:db8:51::2/64
521 #
522 #  [ dummy0   veth0 ]--[ veth1   dummy1 ]
523
524 fib_nexthop_test()
525 {
526         setup
527
528         set -e
529
530         $IP -4 rule add pref 32765 table local
531         $IP -4 rule del pref 0
532         $IP -6 rule add pref 32765 table local
533         $IP -6 rule del pref 0
534
535         $IP link add red type vrf table 1
536         $IP link set red up
537         $IP -4 route add vrf red unreachable default metric 4278198272
538         $IP -6 route add vrf red unreachable default metric 4278198272
539
540         $IP link add veth0 type veth peer name veth1
541         $IP link set dev veth0 up
542         $IP address add 192.0.2.1/24 dev veth0
543         $IP -6 address add 2001:db8:51::1/64 dev veth0
544
545         $IP link set dev veth1 vrf red up
546         $IP address add 192.0.2.2/24 dev veth1
547         $IP -6 address add 2001:db8:51::2/64 dev veth1
548
549         $IP link add dummy1 type dummy
550         $IP link set dev dummy1 vrf red up
551         $IP address add 192.168.2.1/24 dev dummy1
552         $IP -6 address add 2001:db8:2::1/64 dev dummy1
553         set +e
554
555         sleep 1
556         fib4_nexthop
557         fib6_nexthop
558
559         (
560         $IP link del dev dummy1
561         $IP link del veth0
562         $IP link del red
563         ) 2>/dev/null
564         cleanup
565 }
566
567 ################################################################################
568 #
569
570 fib_test()
571 {
572         if [ -n "$TEST" ]; then
573                 eval $TEST
574         else
575                 fib_unreg_test
576                 fib_down_test
577                 fib_carrier_test
578                 fib_nexthop_test
579         fi
580 }
581
582 if [ "$(id -u)" -ne 0 ];then
583         echo "SKIP: Need root privileges"
584         exit $ksft_skip;
585 fi
586
587 if [ ! -x "$(command -v ip)" ]; then
588         echo "SKIP: Could not run test without ip tool"
589         exit $ksft_skip
590 fi
591
592 ip route help 2>&1 | grep -q fibmatch
593 if [ $? -ne 0 ]; then
594         echo "SKIP: iproute2 too old, missing fibmatch"
595         exit $ksft_skip
596 fi
597
598 # start clean
599 cleanup &> /dev/null
600
601 fib_test
602
603 exit $ret