selftests: A few improvements to fib_nexthops.sh
[linux-2.6-microblaze.git] / tools / testing / selftests / net / fib_nexthops.sh
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 #
4 # ns: me               | ns: peer              | ns: remote
5 #   2001:db8:91::1     |       2001:db8:91::2  |
6 #   172.16.1.1         |       172.16.1.2      |
7 #            veth1 <---|---> veth2             |
8 #                      |              veth5 <--|--> veth6  172.16.101.1
9 #            veth3 <---|---> veth4             |           2001:db8:101::1
10 #   172.16.2.1         |       172.16.2.2      |
11 #   2001:db8:92::1     |       2001:db8:92::2  |
12 #
13 # This test is for checking IPv4 and IPv6 FIB behavior with nexthop
14 # objects. Device reference counts and network namespace cleanup tested
15 # by use of network namespace for peer.
16
17 ret=0
18 # Kselftest framework requirement - SKIP code is 4.
19 ksft_skip=4
20
21 # all tests in this script. Can be overridden with -t option
22 IPV4_TESTS="ipv4_fcnal ipv4_grp_fcnal ipv4_withv6_fcnal ipv4_fcnal_runtime"
23 IPV6_TESTS="ipv6_fcnal ipv6_grp_fcnal ipv6_fcnal_runtime"
24
25 ALL_TESTS="basic ${IPV4_TESTS} ${IPV6_TESTS}"
26 TESTS="${ALL_TESTS}"
27 VERBOSE=0
28 PAUSE_ON_FAIL=no
29 PAUSE=no
30
31 nsid=100
32
33 ################################################################################
34 # utilities
35
36 log_test()
37 {
38         local rc=$1
39         local expected=$2
40         local msg="$3"
41
42         if [ ${rc} -eq ${expected} ]; then
43                 printf "TEST: %-60s  [ OK ]\n" "${msg}"
44                 nsuccess=$((nsuccess+1))
45         else
46                 ret=1
47                 nfail=$((nfail+1))
48                 printf "TEST: %-60s  [FAIL]\n" "${msg}"
49                 if [ "$VERBOSE" = "1" ]; then
50                         echo "    rc=$rc, expected $expected"
51                 fi
52
53                 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
54                 echo
55                         echo "hit enter to continue, 'q' to quit"
56                         read a
57                         [ "$a" = "q" ] && exit 1
58                 fi
59         fi
60
61         if [ "${PAUSE}" = "yes" ]; then
62                 echo
63                 echo "hit enter to continue, 'q' to quit"
64                 read a
65                 [ "$a" = "q" ] && exit 1
66         fi
67
68         [ "$VERBOSE" = "1" ] && echo
69 }
70
71 run_cmd()
72 {
73         local cmd="$1"
74         local out
75         local stderr="2>/dev/null"
76
77         if [ "$VERBOSE" = "1" ]; then
78                 printf "COMMAND: $cmd\n"
79                 stderr=
80         fi
81
82         out=$(eval $cmd $stderr)
83         rc=$?
84         if [ "$VERBOSE" = "1" -a -n "$out" ]; then
85                 echo "    $out"
86         fi
87
88         return $rc
89 }
90
91 get_linklocal()
92 {
93         local dev=$1
94         local ns
95         local addr
96
97         [ -n "$2" ] && ns="-netns $2"
98         addr=$(ip $ns -6 -br addr show dev ${dev} | \
99         awk '{
100                 for (i = 3; i <= NF; ++i) {
101                         if ($i ~ /^fe80/)
102                                 print $i
103                 }
104         }'
105         )
106         addr=${addr/\/*}
107
108         [ -z "$addr" ] && return 1
109
110         echo $addr
111
112         return 0
113 }
114
115 create_ns()
116 {
117         local n=${1}
118
119         ip netns del ${n} 2>/dev/null
120
121         set -e
122         ip netns add ${n}
123         ip netns set ${n} $((nsid++))
124         ip -netns ${n} addr add 127.0.0.1/8 dev lo
125         ip -netns ${n} link set lo up
126
127         ip netns exec ${n} sysctl -qw net.ipv4.ip_forward=1
128         ip netns exec ${n} sysctl -qw net.ipv4.fib_multipath_use_neigh=1
129         ip netns exec ${n} sysctl -qw net.ipv4.conf.default.ignore_routes_with_linkdown=1
130         ip netns exec ${n} sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1
131         ip netns exec ${n} sysctl -qw net.ipv6.conf.all.forwarding=1
132         ip netns exec ${n} sysctl -qw net.ipv6.conf.default.forwarding=1
133         ip netns exec ${n} sysctl -qw net.ipv6.conf.default.ignore_routes_with_linkdown=1
134         ip netns exec ${n} sysctl -qw net.ipv6.conf.all.accept_dad=0
135         ip netns exec ${n} sysctl -qw net.ipv6.conf.default.accept_dad=0
136
137         set +e
138 }
139
140 setup()
141 {
142         cleanup
143
144         create_ns me
145         create_ns peer
146         create_ns remote
147
148         IP="ip -netns me"
149         set -e
150         $IP li add veth1 type veth peer name veth2
151         $IP li set veth1 up
152         $IP addr add 172.16.1.1/24 dev veth1
153         $IP -6 addr add 2001:db8:91::1/64 dev veth1 nodad
154
155         $IP li add veth3 type veth peer name veth4
156         $IP li set veth3 up
157         $IP addr add 172.16.2.1/24 dev veth3
158         $IP -6 addr add 2001:db8:92::1/64 dev veth3 nodad
159
160         $IP li set veth2 netns peer up
161         ip -netns peer addr add 172.16.1.2/24 dev veth2
162         ip -netns peer -6 addr add 2001:db8:91::2/64 dev veth2 nodad
163
164         $IP li set veth4 netns peer up
165         ip -netns peer addr add 172.16.2.2/24 dev veth4
166         ip -netns peer -6 addr add 2001:db8:92::2/64 dev veth4 nodad
167
168         ip -netns remote li add veth5 type veth peer name veth6
169         ip -netns remote li set veth5 up
170         ip -netns remote addr add dev veth5 172.16.101.1/24
171         ip -netns remote -6 addr add dev veth5 2001:db8:101::1/64 nodad
172         ip -netns remote ro add 172.16.0.0/22 via 172.16.101.2
173         ip -netns remote -6 ro add 2001:db8:90::/40 via 2001:db8:101::2
174
175         ip -netns remote li set veth6 netns peer up
176         ip -netns peer addr add dev veth6 172.16.101.2/24
177         ip -netns peer -6 addr add dev veth6 2001:db8:101::2/64 nodad
178         set +e
179 }
180
181 cleanup()
182 {
183         local ns
184
185         for ns in me peer remote; do
186                 ip netns del ${ns} 2>/dev/null
187         done
188 }
189
190 check_output()
191 {
192         local out="$1"
193         local expected="$2"
194         local rc=0
195
196         [ "${out}" = "${expected}" ] && return 0
197
198         if [ -z "${out}" ]; then
199                 if [ "$VERBOSE" = "1" ]; then
200                         printf "\nNo entry found\n"
201                         printf "Expected:\n"
202                         printf "    ${expected}\n"
203                 fi
204                 return 1
205         fi
206
207         out=$(echo ${out})
208         if [ "${out}" != "${expected}" ]; then
209                 rc=1
210                 if [ "${VERBOSE}" = "1" ]; then
211                         printf "    Unexpected entry. Have:\n"
212                         printf "        ${out}\n"
213                         printf "    Expected:\n"
214                         printf "        ${expected}\n\n"
215                 else
216                         echo "      WARNING: Unexpected route entry"
217                 fi
218         fi
219
220         return $rc
221 }
222
223 check_nexthop()
224 {
225         local nharg="$1"
226         local expected="$2"
227         local out
228
229         out=$($IP nexthop ls ${nharg} 2>/dev/null)
230
231         check_output "${out}" "${expected}"
232 }
233
234 check_route()
235 {
236         local pfx="$1"
237         local expected="$2"
238         local out
239
240         out=$($IP route ls match ${pfx} 2>/dev/null)
241
242         check_output "${out}" "${expected}"
243 }
244
245 check_route6()
246 {
247         local pfx="$1"
248         local expected="$2"
249         local out
250
251         out=$($IP -6 route ls match ${pfx} 2>/dev/null | sed -e 's/pref medium//')
252
253         check_output "${out}" "${expected}"
254 }
255
256 ################################################################################
257 # basic operations (add, delete, replace) on nexthops and nexthop groups
258 #
259 # IPv6
260
261 ipv6_fcnal()
262 {
263         local rc
264
265         echo
266         echo "IPv6"
267         echo "----------------------"
268
269         run_cmd "$IP nexthop add id 52 via 2001:db8:91::2 dev veth1"
270         rc=$?
271         log_test $rc 0 "Create nexthop with id, gw, dev"
272         if [ $rc -ne 0 ]; then
273                 echo "Basic IPv6 create fails; can not continue"
274                 return 1
275         fi
276
277         run_cmd "$IP nexthop get id 52"
278         log_test $? 0 "Get nexthop by id"
279         check_nexthop "id 52" "id 52 via 2001:db8:91::2 dev veth1 scope link"
280
281         run_cmd "$IP nexthop del id 52"
282         log_test $? 0 "Delete nexthop by id"
283         check_nexthop "id 52" ""
284
285         #
286         # gw, device spec
287         #
288         # gw validation, no device - fails since dev required
289         run_cmd "$IP nexthop add id 52 via 2001:db8:92::3"
290         log_test $? 2 "Create nexthop - gw only"
291
292         # gw is not reachable throught given dev
293         run_cmd "$IP nexthop add id 53 via 2001:db8:3::3 dev veth1"
294         log_test $? 2 "Create nexthop - invalid gw+dev combination"
295
296         # onlink arg overrides gw+dev lookup
297         run_cmd "$IP nexthop add id 53 via 2001:db8:3::3 dev veth1 onlink"
298         log_test $? 0 "Create nexthop - gw+dev and onlink"
299
300         # admin down should delete nexthops
301         set -e
302         run_cmd "$IP -6 nexthop add id 55 via 2001:db8:91::3 dev veth1"
303         run_cmd "$IP nexthop add id 56 via 2001:db8:91::4 dev veth1"
304         run_cmd "$IP nexthop add id 57 via 2001:db8:91::5 dev veth1"
305         run_cmd "$IP li set dev veth1 down"
306         set +e
307         check_nexthop "dev veth1" ""
308         log_test $? 0 "Nexthops removed on admin down"
309 }
310
311 ipv6_grp_fcnal()
312 {
313         local rc
314
315         echo
316         echo "IPv6 groups functional"
317         echo "----------------------"
318
319         # basic functionality: create a nexthop group, default weight
320         run_cmd "$IP nexthop add id 61 via 2001:db8:91::2 dev veth1"
321         run_cmd "$IP nexthop add id 101 group 61"
322         log_test $? 0 "Create nexthop group with single nexthop"
323
324         # get nexthop group
325         run_cmd "$IP nexthop get id 101"
326         log_test $? 0 "Get nexthop group by id"
327         check_nexthop "id 101" "id 101 group 61"
328
329         # delete nexthop group
330         run_cmd "$IP nexthop del id 101"
331         log_test $? 0 "Delete nexthop group by id"
332         check_nexthop "id 101" ""
333
334         $IP nexthop flush >/dev/null 2>&1
335         check_nexthop "id 101" ""
336
337         #
338         # create group with multiple nexthops - mix of gw and dev only
339         #
340         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
341         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
342         run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
343         run_cmd "$IP nexthop add id 65 dev veth1"
344         run_cmd "$IP nexthop add id 102 group 62/63/64/65"
345         log_test $? 0 "Nexthop group with multiple nexthops"
346         check_nexthop "id 102" "id 102 group 62/63/64/65"
347
348         # Delete nexthop in a group and group is updated
349         run_cmd "$IP nexthop del id 63"
350         check_nexthop "id 102" "id 102 group 62/64/65"
351         log_test $? 0 "Nexthop group updated when entry is deleted"
352
353         # create group with multiple weighted nexthops
354         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
355         run_cmd "$IP nexthop add id 103 group 62/63,2/64,3/65,4"
356         log_test $? 0 "Nexthop group with weighted nexthops"
357         check_nexthop "id 103" "id 103 group 62/63,2/64,3/65,4"
358
359         # Delete nexthop in a weighted group and group is updated
360         run_cmd "$IP nexthop del id 63"
361         check_nexthop "id 103" "id 103 group 62/64,3/65,4"
362         log_test $? 0 "Weighted nexthop group updated when entry is deleted"
363
364         # admin down - nexthop is removed from group
365         run_cmd "$IP li set dev veth1 down"
366         check_nexthop "dev veth1" ""
367         log_test $? 0 "Nexthops in groups removed on admin down"
368
369         # expect groups to have been deleted as well
370         check_nexthop "" ""
371
372         run_cmd "$IP li set dev veth1 up"
373
374         $IP nexthop flush >/dev/null 2>&1
375
376         # group with nexthops using different devices
377         set -e
378         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
379         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
380         run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
381         run_cmd "$IP nexthop add id 65 via 2001:db8:91::5 dev veth1"
382
383         run_cmd "$IP nexthop add id 72 via 2001:db8:92::2 dev veth3"
384         run_cmd "$IP nexthop add id 73 via 2001:db8:92::3 dev veth3"
385         run_cmd "$IP nexthop add id 74 via 2001:db8:92::4 dev veth3"
386         run_cmd "$IP nexthop add id 75 via 2001:db8:92::5 dev veth3"
387         set +e
388
389         # multiple groups with same nexthop
390         run_cmd "$IP nexthop add id 104 group 62"
391         run_cmd "$IP nexthop add id 105 group 62"
392         check_nexthop "group" "id 104 group 62 id 105 group 62"
393         log_test $? 0 "Multiple groups with same nexthop"
394
395         run_cmd "$IP nexthop flush groups"
396         [ $? -ne 0 ] && return 1
397
398         # on admin down of veth1, it should be removed from the group
399         run_cmd "$IP nexthop add id 105 group 62/63/72/73/64"
400         run_cmd "$IP li set veth1 down"
401         check_nexthop "id 105" "id 105 group 72/73"
402         log_test $? 0 "Nexthops in group removed on admin down - mixed group"
403
404         run_cmd "$IP nexthop add id 106 group 105/74"
405         log_test $? 2 "Nexthop group can not have a group as an entry"
406
407         # a group can have a blackhole entry only if it is the only
408         # nexthop in the group. Needed for atomic replace with an
409         # actual nexthop group
410         run_cmd "$IP -6 nexthop add id 31 blackhole"
411         run_cmd "$IP nexthop add id 107 group 31"
412         log_test $? 0 "Nexthop group with a blackhole entry"
413
414         run_cmd "$IP nexthop add id 108 group 31/24"
415         log_test $? 2 "Nexthop group can not have a blackhole and another nexthop"
416 }
417
418 ipv6_fcnal_runtime()
419 {
420         local rc
421
422         echo
423         echo "IPv6 functional runtime"
424         echo "-----------------------"
425
426         #
427         # IPv6 - the basics
428         #
429         run_cmd "$IP nexthop add id 81 via 2001:db8:91::2 dev veth1"
430         run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
431         log_test $? 0 "Route add"
432
433         run_cmd "$IP ro delete 2001:db8:101::1/128 nhid 81"
434         log_test $? 0 "Route delete"
435
436         run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
437         run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
438         log_test $? 0 "Ping with nexthop"
439
440         run_cmd "$IP nexthop add id 82 via 2001:db8:92::2 dev veth3"
441         run_cmd "$IP nexthop add id 122 group 81/82"
442         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
443         run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
444         log_test $? 0 "Ping - multipath"
445
446         #
447         # IPv6 with blackhole nexthops
448         #
449         run_cmd "$IP -6 nexthop add id 83 blackhole"
450         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 83"
451         run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
452         log_test $? 2 "Ping - blackhole"
453
454         run_cmd "$IP nexthop replace id 83 via 2001:db8:91::2 dev veth1"
455         run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
456         log_test $? 0 "Ping - blackhole replaced with gateway"
457
458         run_cmd "$IP -6 nexthop replace id 83 blackhole"
459         run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
460         log_test $? 2 "Ping - gateway replaced by blackhole"
461
462         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
463         run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
464         if [ $? -eq 0 ]; then
465                 run_cmd "$IP nexthop replace id 122 group 83"
466                 run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
467                 log_test $? 2 "Ping - group with blackhole"
468
469                 run_cmd "$IP nexthop replace id 122 group 81/82"
470                 run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
471                 log_test $? 0 "Ping - group blackhole replaced with gateways"
472         else
473                 log_test 2 0 "Ping - multipath failed"
474         fi
475
476         #
477         # device only and gw + dev only mix
478         #
479         run_cmd "$IP -6 nexthop add id 85 dev veth1"
480         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 85"
481         log_test $? 0 "IPv6 route with device only nexthop"
482         check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 85 dev veth1 metric 1024"
483
484         run_cmd "$IP nexthop add id 123 group 81/85"
485         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 123"
486         log_test $? 0 "IPv6 multipath route with nexthop mix - dev only + gw"
487         check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 123 metric 1024 nexthop via 2001:db8:91::2 dev veth1 weight 1 nexthop dev veth1 weight 1"
488
489         #
490         # IPv6 route with v4 nexthop - not allowed
491         #
492         run_cmd "$IP ro delete 2001:db8:101::1/128"
493         run_cmd "$IP nexthop add id 84 via 172.16.1.1 dev veth1"
494         run_cmd "$IP ro add 2001:db8:101::1/128 nhid 84"
495         log_test $? 2 "IPv6 route can not have a v4 gateway"
496
497         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 81"
498         run_cmd "$IP nexthop replace id 81 via 172.16.1.1 dev veth1"
499         log_test $? 2 "Nexthop replace - v6 route, v4 nexthop"
500
501         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
502         run_cmd "$IP nexthop replace id 81 via 172.16.1.1 dev veth1"
503         log_test $? 2 "Nexthop replace of group entry - v6 route, v4 nexthop"
504
505         $IP nexthop flush >/dev/null 2>&1
506
507         #
508         # weird IPv6 cases
509         #
510         run_cmd "$IP nexthop add id 86 via 2001:db8:91::2 dev veth1"
511         run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
512
513         # TO-DO:
514         # existing route with old nexthop; append route with new nexthop
515         # existing route with old nexthop; replace route with new
516         # existing route with new nexthop; replace route with old
517         # route with src address and using nexthop - not allowed
518 }
519
520 ipv4_fcnal()
521 {
522         local rc
523
524         echo
525         echo "IPv4 functional"
526         echo "----------------------"
527
528         #
529         # basic IPv4 ops - add, get, delete
530         #
531         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
532         rc=$?
533         log_test $rc 0 "Create nexthop with id, gw, dev"
534         if [ $rc -ne 0 ]; then
535                 echo "Basic IPv4 create fails; can not continue"
536                 return 1
537         fi
538
539         run_cmd "$IP nexthop get id 12"
540         log_test $? 0 "Get nexthop by id"
541         check_nexthop "id 12" "id 12 via 172.16.1.2 dev veth1 scope link"
542
543         run_cmd "$IP nexthop del id 12"
544         log_test $? 0 "Delete nexthop by id"
545         check_nexthop "id 52" ""
546
547         #
548         # gw, device spec
549         #
550         # gw validation, no device - fails since dev is required
551         run_cmd "$IP nexthop add id 12 via 172.16.2.3"
552         log_test $? 2 "Create nexthop - gw only"
553
554         # gw not reachable through given dev
555         run_cmd "$IP nexthop add id 13 via 172.16.3.2 dev veth1"
556         log_test $? 2 "Create nexthop - invalid gw+dev combination"
557
558         # onlink flag overrides gw+dev lookup
559         run_cmd "$IP nexthop add id 13 via 172.16.3.2 dev veth1 onlink"
560         log_test $? 0 "Create nexthop - gw+dev and onlink"
561
562         # admin down should delete nexthops
563         set -e
564         run_cmd "$IP nexthop add id 15 via 172.16.1.3 dev veth1"
565         run_cmd "$IP nexthop add id 16 via 172.16.1.4 dev veth1"
566         run_cmd "$IP nexthop add id 17 via 172.16.1.5 dev veth1"
567         run_cmd "$IP li set dev veth1 down"
568         set +e
569         check_nexthop "dev veth1" ""
570         log_test $? 0 "Nexthops removed on admin down"
571 }
572
573 ipv4_grp_fcnal()
574 {
575         local rc
576
577         echo
578         echo "IPv4 groups functional"
579         echo "----------------------"
580
581         # basic functionality: create a nexthop group, default weight
582         run_cmd "$IP nexthop add id 11 via 172.16.1.2 dev veth1"
583         run_cmd "$IP nexthop add id 101 group 11"
584         log_test $? 0 "Create nexthop group with single nexthop"
585
586         # get nexthop group
587         run_cmd "$IP nexthop get id 101"
588         log_test $? 0 "Get nexthop group by id"
589         check_nexthop "id 101" "id 101 group 11"
590
591         # delete nexthop group
592         run_cmd "$IP nexthop del id 101"
593         log_test $? 0 "Delete nexthop group by id"
594         check_nexthop "id 101" ""
595
596         $IP nexthop flush >/dev/null 2>&1
597
598         #
599         # create group with multiple nexthops
600         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
601         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
602         run_cmd "$IP nexthop add id 14 via 172.16.1.4 dev veth1"
603         run_cmd "$IP nexthop add id 15 via 172.16.1.5 dev veth1"
604         run_cmd "$IP nexthop add id 102 group 12/13/14/15"
605         log_test $? 0 "Nexthop group with multiple nexthops"
606         check_nexthop "id 102" "id 102 group 12/13/14/15"
607
608         # Delete nexthop in a group and group is updated
609         run_cmd "$IP nexthop del id 13"
610         check_nexthop "id 102" "id 102 group 12/14/15"
611         log_test $? 0 "Nexthop group updated when entry is deleted"
612
613         # create group with multiple weighted nexthops
614         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
615         run_cmd "$IP nexthop add id 103 group 12/13,2/14,3/15,4"
616         log_test $? 0 "Nexthop group with weighted nexthops"
617         check_nexthop "id 103" "id 103 group 12/13,2/14,3/15,4"
618
619         # Delete nexthop in a weighted group and group is updated
620         run_cmd "$IP nexthop del id 13"
621         check_nexthop "id 103" "id 103 group 12/14,3/15,4"
622         log_test $? 0 "Weighted nexthop group updated when entry is deleted"
623
624         # admin down - nexthop is removed from group
625         run_cmd "$IP li set dev veth1 down"
626         check_nexthop "dev veth1" ""
627         log_test $? 0 "Nexthops in groups removed on admin down"
628
629         # expect groups to have been deleted as well
630         check_nexthop "" ""
631
632         run_cmd "$IP li set dev veth1 up"
633
634         $IP nexthop flush >/dev/null 2>&1
635
636         # group with nexthops using different devices
637         set -e
638         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
639         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
640         run_cmd "$IP nexthop add id 14 via 172.16.1.4 dev veth1"
641         run_cmd "$IP nexthop add id 15 via 172.16.1.5 dev veth1"
642
643         run_cmd "$IP nexthop add id 22 via 172.16.2.2 dev veth3"
644         run_cmd "$IP nexthop add id 23 via 172.16.2.3 dev veth3"
645         run_cmd "$IP nexthop add id 24 via 172.16.2.4 dev veth3"
646         run_cmd "$IP nexthop add id 25 via 172.16.2.5 dev veth3"
647         set +e
648
649         # multiple groups with same nexthop
650         run_cmd "$IP nexthop add id 104 group 12"
651         run_cmd "$IP nexthop add id 105 group 12"
652         check_nexthop "group" "id 104 group 12 id 105 group 12"
653         log_test $? 0 "Multiple groups with same nexthop"
654
655         run_cmd "$IP nexthop flush groups"
656         [ $? -ne 0 ] && return 1
657
658         # on admin down of veth1, it should be removed from the group
659         run_cmd "$IP nexthop add id 105 group 12/13/22/23/14"
660         run_cmd "$IP li set veth1 down"
661         check_nexthop "id 105" "id 105 group 22/23"
662         log_test $? 0 "Nexthops in group removed on admin down - mixed group"
663
664         run_cmd "$IP nexthop add id 106 group 105/24"
665         log_test $? 2 "Nexthop group can not have a group as an entry"
666
667         # a group can have a blackhole entry only if it is the only
668         # nexthop in the group. Needed for atomic replace with an
669         # actual nexthop group
670         run_cmd "$IP nexthop add id 31 blackhole"
671         run_cmd "$IP nexthop add id 107 group 31"
672         log_test $? 0 "Nexthop group with a blackhole entry"
673
674         run_cmd "$IP nexthop add id 108 group 31/24"
675         log_test $? 2 "Nexthop group can not have a blackhole and another nexthop"
676 }
677
678 ipv4_withv6_fcnal()
679 {
680         local lladdr
681
682         set -e
683         lladdr=$(get_linklocal veth2 peer)
684         run_cmd "$IP nexthop add id 11 via ${lladdr} dev veth1"
685         set +e
686         run_cmd "$IP ro add 172.16.101.1/32 nhid 11"
687         log_test $? 0 "IPv6 nexthop with IPv4 route"
688         check_route "172.16.101.1" "172.16.101.1 nhid 11 via inet6 ${lladdr} dev veth1"
689
690         set -e
691         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
692         run_cmd "$IP nexthop add id 101 group 11/12"
693         set +e
694         run_cmd "$IP ro replace 172.16.101.1/32 nhid 101"
695         log_test $? 0 "IPv6 nexthop with IPv4 route"
696
697         check_route "172.16.101.1" "172.16.101.1 nhid 101 nexthop via inet6 ${lladdr} dev veth1 weight 1 nexthop via 172.16.1.2 dev veth1 weight 1"
698
699         run_cmd "$IP ro replace 172.16.101.1/32 via inet6 ${lladdr} dev veth1"
700         log_test $? 0 "IPv4 route with IPv6 gateway"
701         check_route "172.16.101.1" "172.16.101.1 via inet6 ${lladdr} dev veth1"
702
703         run_cmd "$IP ro replace 172.16.101.1/32 via inet6 2001:db8:50::1 dev veth1"
704         log_test $? 2 "IPv4 route with invalid IPv6 gateway"
705 }
706
707 ipv4_fcnal_runtime()
708 {
709         local lladdr
710         local rc
711
712         echo
713         echo "IPv4 functional runtime"
714         echo "-----------------------"
715
716         run_cmd "$IP nexthop add id 21 via 172.16.1.2 dev veth1"
717         run_cmd "$IP ro add 172.16.101.1/32 nhid 21"
718         log_test $? 0 "Route add"
719         check_route "172.16.101.1" "172.16.101.1 nhid 21 via 172.16.1.2 dev veth1"
720
721         run_cmd "$IP ro delete 172.16.101.1/32 nhid 21"
722         log_test $? 0 "Route delete"
723
724         #
725         # scope mismatch
726         #
727         run_cmd "$IP nexthop add id 22 via 172.16.1.2 dev veth1"
728         run_cmd "$IP ro add 172.16.101.1/32 nhid 22 scope host"
729         log_test $? 2 "Route add - scope conflict with nexthop"
730
731         run_cmd "$IP nexthop replace id 22 dev veth3"
732         run_cmd "$IP ro add 172.16.101.1/32 nhid 22 scope host"
733         run_cmd "$IP nexthop replace id 22 via 172.16.2.2 dev veth3"
734         log_test $? 2 "Nexthop replace with invalid scope for existing route"
735
736         #
737         # add route with nexthop and check traffic
738         #
739         run_cmd "$IP nexthop replace id 21 via 172.16.1.2 dev veth1"
740         run_cmd "$IP ro replace 172.16.101.1/32 nhid 21"
741         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
742         log_test $? 0 "Basic ping"
743
744         run_cmd "$IP nexthop replace id 22 via 172.16.2.2 dev veth3"
745         run_cmd "$IP nexthop add id 122 group 21/22"
746         run_cmd "$IP ro replace 172.16.101.1/32 nhid 122"
747         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
748         log_test $? 0 "Ping - multipath"
749
750         #
751         # IPv4 with blackhole nexthops
752         #
753         run_cmd "$IP nexthop add id 23 blackhole"
754         run_cmd "$IP ro replace 172.16.101.1/32 nhid 23"
755         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
756         log_test $? 2 "Ping - blackhole"
757
758         run_cmd "$IP nexthop replace id 23 via 172.16.1.2 dev veth1"
759         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
760         log_test $? 0 "Ping - blackhole replaced with gateway"
761
762         run_cmd "$IP nexthop replace id 23 blackhole"
763         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
764         log_test $? 2 "Ping - gateway replaced by blackhole"
765
766         run_cmd "$IP ro replace 172.16.101.1/32 nhid 122"
767         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
768         if [ $? -eq 0 ]; then
769                 run_cmd "$IP nexthop replace id 122 group 23"
770                 run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
771                 log_test $? 2 "Ping - group with blackhole"
772
773                 run_cmd "$IP nexthop replace id 122 group 21/22"
774                 run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
775                 log_test $? 0 "Ping - group blackhole replaced with gateways"
776         else
777                 log_test 2 0 "Ping - multipath failed"
778         fi
779
780         #
781         # device only and gw + dev only mix
782         #
783         run_cmd "$IP nexthop add id 85 dev veth1"
784         run_cmd "$IP ro replace 172.16.101.1/32 nhid 85"
785         log_test $? 0 "IPv4 route with device only nexthop"
786         check_route "172.16.101.1" "172.16.101.1 nhid 85 dev veth1"
787
788         run_cmd "$IP nexthop add id 123 group 21/85"
789         run_cmd "$IP ro replace 172.16.101.1/32 nhid 123"
790         log_test $? 0 "IPv4 multipath route with nexthop mix - dev only + gw"
791         check_route "172.16.101.1" "172.16.101.1 nhid 123 nexthop via 172.16.1.2 dev veth1 weight 1 nexthop dev veth1 weight 1"
792
793         #
794         # IPv4 with IPv6
795         #
796         set -e
797         lladdr=$(get_linklocal veth2 peer)
798         run_cmd "$IP nexthop add id 24 via ${lladdr} dev veth1"
799         set +e
800         run_cmd "$IP ro replace 172.16.101.1/32 nhid 24"
801         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
802         log_test $? 0 "IPv6 nexthop with IPv4 route"
803
804         $IP neigh sh | grep -q "${lladdr} dev veth1"
805         if [ $? -eq 1 ]; then
806                 echo "    WARNING: Neigh entry missing for ${lladdr}"
807                 $IP neigh sh | grep 'dev veth1'
808         fi
809
810         $IP neigh sh | grep -q "172.16.101.1 dev eth1"
811         if [ $? -eq 0 ]; then
812                 echo "    WARNING: Neigh entry exists for 172.16.101.1"
813                 $IP neigh sh | grep 'dev veth1'
814         fi
815
816         set -e
817         run_cmd "$IP nexthop add id 25 via 172.16.1.2 dev veth1"
818         run_cmd "$IP nexthop add id 101 group 24/25"
819         set +e
820         run_cmd "$IP ro replace 172.16.101.1/32 nhid 101"
821         log_test $? 0 "IPv4 route with mixed v4-v6 multipath route"
822
823         check_route "172.16.101.1" "172.16.101.1 nhid 101 nexthop via inet6 ${lladdr} dev veth1 weight 1 nexthop via 172.16.1.2 dev veth1 weight 1"
824
825         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
826         log_test $? 0 "IPv6 nexthop with IPv4 route"
827
828         run_cmd "$IP ro replace 172.16.101.1/32 via inet6 ${lladdr} dev veth1"
829         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
830         log_test $? 0 "IPv4 route with IPv6 gateway"
831
832         $IP neigh sh | grep -q "${lladdr} dev veth1"
833         if [ $? -eq 1 ]; then
834                 echo "    WARNING: Neigh entry missing for ${lladdr}"
835                 $IP neigh sh | grep 'dev veth1'
836         fi
837
838         $IP neigh sh | grep -q "172.16.101.1 dev eth1"
839         if [ $? -eq 0 ]; then
840                 echo "    WARNING: Neigh entry exists for 172.16.101.1"
841                 $IP neigh sh | grep 'dev veth1'
842         fi
843
844         run_cmd "$IP ro del 172.16.101.1/32 via inet6 ${lladdr} dev veth1"
845         run_cmd "$IP -4 ro add default via inet6 ${lladdr} dev veth1"
846         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
847         log_test $? 0 "IPv4 default route with IPv6 gateway"
848
849         #
850         # MPLS as an example of LWT encap
851         #
852         run_cmd "$IP nexthop add id 51 encap mpls 101 via 172.16.1.2 dev veth1"
853         log_test $? 0 "IPv4 route with MPLS encap"
854         check_nexthop "id 51" "id 51 encap mpls 101 via 172.16.1.2 dev veth1 scope link"
855         log_test $? 0 "IPv4 route with MPLS encap - check"
856
857         run_cmd "$IP nexthop add id 52 encap mpls 102 via inet6 2001:db8:91::2 dev veth1"
858         log_test $? 0 "IPv4 route with MPLS encap and v6 gateway"
859         check_nexthop "id 52" "id 52 encap mpls 102 via 2001:db8:91::2 dev veth1 scope link"
860         log_test $? 0 "IPv4 route with MPLS encap, v6 gw - check"
861 }
862
863 basic()
864 {
865         echo
866         echo "Basic functional tests"
867         echo "----------------------"
868         run_cmd "$IP nexthop ls"
869         log_test $? 0 "List with nothing defined"
870
871         run_cmd "$IP nexthop get id 1"
872         log_test $? 2 "Nexthop get on non-existent id"
873
874         # attempt to create nh without a device or gw - fails
875         run_cmd "$IP nexthop add id 1"
876         log_test $? 2 "Nexthop with no device or gateway"
877
878         # attempt to create nh with down device - fails
879         $IP li set veth1 down
880         run_cmd "$IP nexthop add id 1 dev veth1"
881         log_test $? 2 "Nexthop with down device"
882
883         # create nh with linkdown device - fails
884         $IP li set veth1 up
885         ip -netns peer li set veth2 down
886         run_cmd "$IP nexthop add id 1 dev veth1"
887         log_test $? 2 "Nexthop with device that is linkdown"
888         ip -netns peer li set veth2 up
889
890         # device only
891         run_cmd "$IP nexthop add id 1 dev veth1"
892         log_test $? 0 "Nexthop with device only"
893
894         # create nh with duplicate id
895         run_cmd "$IP nexthop add id 1 dev veth3"
896         log_test $? 2 "Nexthop with duplicate id"
897
898         # blackhole nexthop
899         run_cmd "$IP nexthop add id 2 blackhole"
900         log_test $? 0 "Blackhole nexthop"
901
902         # blackhole nexthop can not have other specs
903         run_cmd "$IP nexthop replace id 2 blackhole dev veth1"
904         log_test $? 2 "Blackhole nexthop with other attributes"
905
906         #
907         # groups
908         #
909
910         run_cmd "$IP nexthop add id 101 group 1"
911         log_test $? 0 "Create group"
912
913         run_cmd "$IP nexthop add id 102 group 2"
914         log_test $? 0 "Create group with blackhole nexthop"
915
916         # multipath group can not have a blackhole as 1 path
917         run_cmd "$IP nexthop add id 103 group 1/2"
918         log_test $? 2 "Create multipath group where 1 path is a blackhole"
919
920         # multipath group can not have a member replaced by a blackhole
921         run_cmd "$IP nexthop replace id 2 dev veth3"
922         run_cmd "$IP nexthop replace id 102 group 1/2"
923         run_cmd "$IP nexthop replace id 2 blackhole"
924         log_test $? 2 "Multipath group can not have a member replaced by blackhole"
925
926         # attempt to create group with non-existent nexthop
927         run_cmd "$IP nexthop add id 103 group 12"
928         log_test $? 2 "Create group with non-existent nexthop"
929
930         # attempt to create group with same nexthop
931         run_cmd "$IP nexthop add id 103 group 1/1"
932         log_test $? 2 "Create group with same nexthop multiple times"
933
934         # replace nexthop with a group - fails
935         run_cmd "$IP nexthop replace id 2 group 1"
936         log_test $? 2 "Replace nexthop with nexthop group"
937
938         # replace nexthop group with a nexthop - fails
939         run_cmd "$IP nexthop replace id 101 dev veth1"
940         log_test $? 2 "Replace nexthop group with nexthop"
941
942         # nexthop group with other attributes fail
943         run_cmd "$IP nexthop add id 104 group 1 dev veth1"
944         log_test $? 2 "Nexthop group and device"
945
946         # Tests to ensure that flushing works as expected.
947         run_cmd "$IP nexthop add id 105 blackhole proto 99"
948         run_cmd "$IP nexthop add id 106 blackhole proto 100"
949         run_cmd "$IP nexthop add id 107 blackhole proto 99"
950         run_cmd "$IP nexthop flush proto 99"
951         check_nexthop "id 105" ""
952         check_nexthop "id 106" "id 106 blackhole proto 100"
953         check_nexthop "id 107" ""
954         run_cmd "$IP nexthop flush proto 100"
955         check_nexthop "id 106" ""
956
957         run_cmd "$IP nexthop flush proto 100"
958         log_test $? 0 "Test proto flush"
959
960         run_cmd "$IP nexthop add id 104 group 1 blackhole"
961         log_test $? 2 "Nexthop group and blackhole"
962
963         $IP nexthop flush >/dev/null 2>&1
964 }
965
966 ################################################################################
967 # usage
968
969 usage()
970 {
971         cat <<EOF
972 usage: ${0##*/} OPTS
973
974         -t <test>   Test(s) to run (default: all)
975                     (options: $ALL_TESTS)
976         -4          IPv4 tests only
977         -6          IPv6 tests only
978         -p          Pause on fail
979         -P          Pause after each test before cleanup
980         -v          verbose mode (show commands and output)
981
982     Runtime test
983         -n num      Number of nexthops to target
984         -N          Use new style to install routes in DUT
985
986 done
987 EOF
988 }
989
990 ################################################################################
991 # main
992
993 while getopts :t:pP46hv o
994 do
995         case $o in
996                 t) TESTS=$OPTARG;;
997                 4) TESTS=${IPV4_TESTS};;
998                 6) TESTS=${IPV6_TESTS};;
999                 p) PAUSE_ON_FAIL=yes;;
1000                 P) PAUSE=yes;;
1001                 v) VERBOSE=$(($VERBOSE + 1));;
1002                 h) usage; exit 0;;
1003                 *) usage; exit 1;;
1004         esac
1005 done
1006
1007 # make sure we don't pause twice
1008 [ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
1009
1010 if [ "$(id -u)" -ne 0 ];then
1011         echo "SKIP: Need root privileges"
1012         exit $ksft_skip;
1013 fi
1014
1015 if [ ! -x "$(command -v ip)" ]; then
1016         echo "SKIP: Could not run test without ip tool"
1017         exit $ksft_skip
1018 fi
1019
1020 ip help 2>&1 | grep -q nexthop
1021 if [ $? -ne 0 ]; then
1022         echo "SKIP: iproute2 too old, missing nexthop command"
1023         exit $ksft_skip
1024 fi
1025
1026 out=$(ip nexthop ls 2>&1 | grep -q "Operation not supported")
1027 if [ $? -eq 0 ]; then
1028         echo "SKIP: kernel lacks nexthop support"
1029         exit $ksft_skip
1030 fi
1031
1032 for t in $TESTS
1033 do
1034         case $t in
1035         none) IP="ip -netns peer"; setup; exit 0;;
1036         *) setup; $t; cleanup;;
1037         esac
1038 done
1039
1040 if [ "$TESTS" != "none" ]; then
1041         printf "\nTests passed: %3d\n" ${nsuccess}
1042         printf "Tests failed: %3d\n"   ${nfail}
1043 fi
1044
1045 exit $ret