selftests: net: add fdb nexthop tests
[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 ipv4_compat_mode ipv4_fdb_grp_fcnal"
23 IPV6_TESTS="ipv6_fcnal ipv6_grp_fcnal ipv6_fcnal_runtime ipv6_compat_mode ipv6_fdb_grp_fcnal"
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         BRIDGE="bridge -netns me"
150         set -e
151         $IP li add veth1 type veth peer name veth2
152         $IP li set veth1 up
153         $IP addr add 172.16.1.1/24 dev veth1
154         $IP -6 addr add 2001:db8:91::1/64 dev veth1 nodad
155
156         $IP li add veth3 type veth peer name veth4
157         $IP li set veth3 up
158         $IP addr add 172.16.2.1/24 dev veth3
159         $IP -6 addr add 2001:db8:92::1/64 dev veth3 nodad
160
161         $IP li set veth2 netns peer up
162         ip -netns peer addr add 172.16.1.2/24 dev veth2
163         ip -netns peer -6 addr add 2001:db8:91::2/64 dev veth2 nodad
164
165         $IP li set veth4 netns peer up
166         ip -netns peer addr add 172.16.2.2/24 dev veth4
167         ip -netns peer -6 addr add 2001:db8:92::2/64 dev veth4 nodad
168
169         ip -netns remote li add veth5 type veth peer name veth6
170         ip -netns remote li set veth5 up
171         ip -netns remote addr add dev veth5 172.16.101.1/24
172         ip -netns remote -6 addr add dev veth5 2001:db8:101::1/64 nodad
173         ip -netns remote ro add 172.16.0.0/22 via 172.16.101.2
174         ip -netns remote -6 ro add 2001:db8:90::/40 via 2001:db8:101::2
175
176         ip -netns remote li set veth6 netns peer up
177         ip -netns peer addr add dev veth6 172.16.101.2/24
178         ip -netns peer -6 addr add dev veth6 2001:db8:101::2/64 nodad
179         set +e
180 }
181
182 cleanup()
183 {
184         local ns
185
186         for ns in me peer remote; do
187                 ip netns del ${ns} 2>/dev/null
188         done
189 }
190
191 check_output()
192 {
193         local out="$1"
194         local expected="$2"
195         local rc=0
196
197         [ "${out}" = "${expected}" ] && return 0
198
199         if [ -z "${out}" ]; then
200                 if [ "$VERBOSE" = "1" ]; then
201                         printf "\nNo entry found\n"
202                         printf "Expected:\n"
203                         printf "    ${expected}\n"
204                 fi
205                 return 1
206         fi
207
208         out=$(echo ${out})
209         if [ "${out}" != "${expected}" ]; then
210                 rc=1
211                 if [ "${VERBOSE}" = "1" ]; then
212                         printf "    Unexpected entry. Have:\n"
213                         printf "        ${out}\n"
214                         printf "    Expected:\n"
215                         printf "        ${expected}\n\n"
216                 else
217                         echo "      WARNING: Unexpected route entry"
218                 fi
219         fi
220
221         return $rc
222 }
223
224 check_nexthop()
225 {
226         local nharg="$1"
227         local expected="$2"
228         local out
229
230         out=$($IP nexthop ls ${nharg} 2>/dev/null)
231
232         check_output "${out}" "${expected}"
233 }
234
235 check_route()
236 {
237         local pfx="$1"
238         local expected="$2"
239         local out
240
241         out=$($IP route ls match ${pfx} 2>/dev/null)
242
243         check_output "${out}" "${expected}"
244 }
245
246 check_route6()
247 {
248         local pfx="$1"
249         local expected="$2"
250         local out
251
252         out=$($IP -6 route ls match ${pfx} 2>/dev/null | sed -e 's/pref medium//')
253
254         check_output "${out}" "${expected}"
255 }
256
257 start_ip_monitor()
258 {
259         local mtype=$1
260
261         # start the monitor in the background
262         tmpfile=`mktemp /var/run/nexthoptestXXX`
263         mpid=`($IP monitor $mtype > $tmpfile & echo $!) 2>/dev/null`
264         sleep 0.2
265         echo "$mpid $tmpfile"
266 }
267
268 stop_ip_monitor()
269 {
270         local mpid=$1
271         local tmpfile=$2
272         local el=$3
273
274         # check the monitor results
275         kill $mpid
276         lines=`wc -l $tmpfile | cut "-d " -f1`
277         test $lines -eq $el
278         rc=$?
279         rm -rf $tmpfile
280
281         return $rc
282 }
283
284 check_nexthop_fdb_support()
285 {
286         $IP nexthop help 2>&1 | grep -q fdb
287         if [ $? -ne 0 ]; then
288                 echo "SKIP: iproute2 too old, missing fdb nexthop support"
289                 return $ksft_skip
290         fi
291 }
292
293 ipv6_fdb_grp_fcnal()
294 {
295         local rc
296
297         echo
298         echo "IPv6 fdb groups functional"
299         echo "--------------------------"
300
301         check_nexthop_fdb_support
302         if [ $? -eq $ksft_skip ]; then
303                 return $ksft_skip
304         fi
305
306         # create group with multiple nexthops
307         run_cmd "$IP nexthop add id 61 via 2001:db8:91::2 fdb"
308         run_cmd "$IP nexthop add id 62 via 2001:db8:91::3 fdb"
309         run_cmd "$IP nexthop add id 102 group 61/62 fdb"
310         check_nexthop "id 102" "id 102 group 61/62 fdb"
311         log_test $? 0 "Fdb Nexthop group with multiple nexthops"
312
313         ## get nexthop group
314         run_cmd "$IP nexthop get id 102"
315         check_nexthop "id 102" "id 102 group 61/62 fdb"
316         log_test $? 0 "Get Fdb nexthop group by id"
317
318         # fdb nexthop group can only contain fdb nexthops
319         run_cmd "$IP nexthop add id 63 via 2001:db8:91::4"
320         run_cmd "$IP nexthop add id 64 via 2001:db8:91::5"
321         run_cmd "$IP nexthop add id 103 group 63/64 fdb"
322         log_test $? 2 "Fdb Nexthop group with non-fdb nexthops"
323
324         # Non fdb nexthop group can not contain fdb nexthops
325         run_cmd "$IP nexthop add id 65 via 2001:db8:91::5 fdb"
326         run_cmd "$IP nexthop add id 66 via 2001:db8:91::6 fdb"
327         run_cmd "$IP nexthop add id 104 group 65/66"
328         log_test $? 2 "Non-Fdb Nexthop group with fdb nexthops"
329
330         # fdb nexthop cannot have blackhole
331         run_cmd "$IP nexthop add id 67 blackhole fdb"
332         log_test $? 2 "Fdb Nexthop with blackhole"
333
334         # fdb nexthop with oif
335         run_cmd "$IP nexthop add id 68 via 2001:db8:91::7 dev veth1 fdb"
336         log_test $? 2 "Fdb Nexthop with oif"
337
338         # fdb nexthop with onlink
339         run_cmd "$IP nexthop add id 68 via 2001:db8:91::7 onlink fdb"
340         log_test $? 2 "Fdb Nexthop with onlink"
341
342         # fdb nexthop with encap
343         run_cmd "$IP nexthop add id 69 encap mpls 101 via 2001:db8:91::8 dev veth1 fdb"
344         log_test $? 2 "Fdb Nexthop with encap"
345
346         run_cmd "$IP link add name vx10 type vxlan id 1010 local 2001:db8:91::9 remote 2001:db8:91::10 dstport 4789 nolearning noudpcsum tos inherit ttl 100"
347         run_cmd "$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self"
348         log_test $? 0 "Fdb mac add with nexthop group"
349
350         ## fdb nexthops can only reference nexthop groups and not nexthops
351         run_cmd "$BRIDGE fdb add 02:02:00:00:00:14 dev vx10 nhid 61 self"
352         log_test $? 255 "Fdb mac add with nexthop"
353
354         run_cmd "$IP -6 ro add 2001:db8:101::1/128 nhid 66"
355         log_test $? 2 "Route add with fdb nexthop"
356
357         run_cmd "$IP -6 ro add 2001:db8:101::1/128 nhid 103"
358         log_test $? 2 "Route add with fdb nexthop group"
359
360         run_cmd "$IP nexthop del id 102"
361         log_test $? 0 "Fdb nexthop delete"
362
363         $IP link del dev vx10
364 }
365
366 ipv4_fdb_grp_fcnal()
367 {
368         local rc
369
370         echo
371         echo "IPv4 fdb groups functional"
372         echo "--------------------------"
373
374         check_nexthop_fdb_support
375         if [ $? -eq $ksft_skip ]; then
376                 return $ksft_skip
377         fi
378
379         # create group with multiple nexthops
380         run_cmd "$IP nexthop add id 12 via 172.16.1.2 fdb"
381         run_cmd "$IP nexthop add id 13 via 172.16.1.3 fdb"
382         run_cmd "$IP nexthop add id 102 group 12/13 fdb"
383         check_nexthop "id 102" "id 102 group 12/13 fdb"
384         log_test $? 0 "Fdb Nexthop group with multiple nexthops"
385
386         # get nexthop group
387         run_cmd "$IP nexthop get id 102"
388         check_nexthop "id 102" "id 102 group 12/13 fdb"
389         log_test $? 0 "Get Fdb nexthop group by id"
390
391         # fdb nexthop group can only contain fdb nexthops
392         run_cmd "$IP nexthop add id 14 via 172.16.1.2"
393         run_cmd "$IP nexthop add id 15 via 172.16.1.3"
394         run_cmd "$IP nexthop add id 103 group 14/15 fdb"
395         log_test $? 2 "Fdb Nexthop group with non-fdb nexthops"
396
397         # Non fdb nexthop group can not contain fdb nexthops
398         run_cmd "$IP nexthop add id 16 via 172.16.1.2 fdb"
399         run_cmd "$IP nexthop add id 17 via 172.16.1.3 fdb"
400         run_cmd "$IP nexthop add id 104 group 14/15"
401         log_test $? 2 "Non-Fdb Nexthop group with fdb nexthops"
402
403         # fdb nexthop cannot have blackhole
404         run_cmd "$IP nexthop add id 18 blackhole fdb"
405         log_test $? 2 "Fdb Nexthop with blackhole"
406
407         # fdb nexthop with oif
408         run_cmd "$IP nexthop add id 16 via 172.16.1.2 dev veth1 fdb"
409         log_test $? 2 "Fdb Nexthop with oif"
410
411         # fdb nexthop with onlink
412         run_cmd "$IP nexthop add id 16 via 172.16.1.2 onlink fdb"
413         log_test $? 2 "Fdb Nexthop with onlink"
414
415         # fdb nexthop with encap
416         run_cmd "$IP nexthop add id 17 encap mpls 101 via 172.16.1.2 dev veth1 fdb"
417         log_test $? 2 "Fdb Nexthop with encap"
418
419         run_cmd "$IP link add name vx10 type vxlan id 1010 local 10.0.0.1 remote 10.0.0.2 dstport 4789 nolearning noudpcsum tos inherit ttl 100"
420         run_cmd "$BRIDGE fdb add 02:02:00:00:00:13 dev vx10 nhid 102 self"
421         log_test $? 0 "Fdb mac add with nexthop group"
422
423         # fdb nexthops can only reference nexthop groups and not nexthops
424         run_cmd "$BRIDGE fdb add 02:02:00:00:00:14 dev vx10 nhid 12 self"
425         log_test $? 255 "Fdb mac add with nexthop"
426
427         run_cmd "$IP ro add 172.16.0.0/22 nhid 15"
428         log_test $? 2 "Route add with fdb nexthop"
429
430         run_cmd "$IP ro add 172.16.0.0/22 nhid 103"
431         log_test $? 2 "Route add with fdb nexthop group"
432
433         run_cmd "$IP nexthop del id 102"
434         log_test $? 0 "Fdb nexthop delete"
435
436         $IP link del dev vx10
437 }
438
439 ################################################################################
440 # basic operations (add, delete, replace) on nexthops and nexthop groups
441 #
442 # IPv6
443
444 ipv6_fcnal()
445 {
446         local rc
447
448         echo
449         echo "IPv6"
450         echo "----------------------"
451
452         run_cmd "$IP nexthop add id 52 via 2001:db8:91::2 dev veth1"
453         rc=$?
454         log_test $rc 0 "Create nexthop with id, gw, dev"
455         if [ $rc -ne 0 ]; then
456                 echo "Basic IPv6 create fails; can not continue"
457                 return 1
458         fi
459
460         run_cmd "$IP nexthop get id 52"
461         log_test $? 0 "Get nexthop by id"
462         check_nexthop "id 52" "id 52 via 2001:db8:91::2 dev veth1 scope link"
463
464         run_cmd "$IP nexthop del id 52"
465         log_test $? 0 "Delete nexthop by id"
466         check_nexthop "id 52" ""
467
468         #
469         # gw, device spec
470         #
471         # gw validation, no device - fails since dev required
472         run_cmd "$IP nexthop add id 52 via 2001:db8:92::3"
473         log_test $? 2 "Create nexthop - gw only"
474
475         # gw is not reachable throught given dev
476         run_cmd "$IP nexthop add id 53 via 2001:db8:3::3 dev veth1"
477         log_test $? 2 "Create nexthop - invalid gw+dev combination"
478
479         # onlink arg overrides gw+dev lookup
480         run_cmd "$IP nexthop add id 53 via 2001:db8:3::3 dev veth1 onlink"
481         log_test $? 0 "Create nexthop - gw+dev and onlink"
482
483         # admin down should delete nexthops
484         set -e
485         run_cmd "$IP -6 nexthop add id 55 via 2001:db8:91::3 dev veth1"
486         run_cmd "$IP nexthop add id 56 via 2001:db8:91::4 dev veth1"
487         run_cmd "$IP nexthop add id 57 via 2001:db8:91::5 dev veth1"
488         run_cmd "$IP li set dev veth1 down"
489         set +e
490         check_nexthop "dev veth1" ""
491         log_test $? 0 "Nexthops removed on admin down"
492 }
493
494 ipv6_grp_fcnal()
495 {
496         local rc
497
498         echo
499         echo "IPv6 groups functional"
500         echo "----------------------"
501
502         # basic functionality: create a nexthop group, default weight
503         run_cmd "$IP nexthop add id 61 via 2001:db8:91::2 dev veth1"
504         run_cmd "$IP nexthop add id 101 group 61"
505         log_test $? 0 "Create nexthop group with single nexthop"
506
507         # get nexthop group
508         run_cmd "$IP nexthop get id 101"
509         log_test $? 0 "Get nexthop group by id"
510         check_nexthop "id 101" "id 101 group 61"
511
512         # delete nexthop group
513         run_cmd "$IP nexthop del id 101"
514         log_test $? 0 "Delete nexthop group by id"
515         check_nexthop "id 101" ""
516
517         $IP nexthop flush >/dev/null 2>&1
518         check_nexthop "id 101" ""
519
520         #
521         # create group with multiple nexthops - mix of gw and dev only
522         #
523         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
524         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
525         run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
526         run_cmd "$IP nexthop add id 65 dev veth1"
527         run_cmd "$IP nexthop add id 102 group 62/63/64/65"
528         log_test $? 0 "Nexthop group with multiple nexthops"
529         check_nexthop "id 102" "id 102 group 62/63/64/65"
530
531         # Delete nexthop in a group and group is updated
532         run_cmd "$IP nexthop del id 63"
533         check_nexthop "id 102" "id 102 group 62/64/65"
534         log_test $? 0 "Nexthop group updated when entry is deleted"
535
536         # create group with multiple weighted nexthops
537         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
538         run_cmd "$IP nexthop add id 103 group 62/63,2/64,3/65,4"
539         log_test $? 0 "Nexthop group with weighted nexthops"
540         check_nexthop "id 103" "id 103 group 62/63,2/64,3/65,4"
541
542         # Delete nexthop in a weighted group and group is updated
543         run_cmd "$IP nexthop del id 63"
544         check_nexthop "id 103" "id 103 group 62/64,3/65,4"
545         log_test $? 0 "Weighted nexthop group updated when entry is deleted"
546
547         # admin down - nexthop is removed from group
548         run_cmd "$IP li set dev veth1 down"
549         check_nexthop "dev veth1" ""
550         log_test $? 0 "Nexthops in groups removed on admin down"
551
552         # expect groups to have been deleted as well
553         check_nexthop "" ""
554
555         run_cmd "$IP li set dev veth1 up"
556
557         $IP nexthop flush >/dev/null 2>&1
558
559         # group with nexthops using different devices
560         set -e
561         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
562         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
563         run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
564         run_cmd "$IP nexthop add id 65 via 2001:db8:91::5 dev veth1"
565
566         run_cmd "$IP nexthop add id 72 via 2001:db8:92::2 dev veth3"
567         run_cmd "$IP nexthop add id 73 via 2001:db8:92::3 dev veth3"
568         run_cmd "$IP nexthop add id 74 via 2001:db8:92::4 dev veth3"
569         run_cmd "$IP nexthop add id 75 via 2001:db8:92::5 dev veth3"
570         set +e
571
572         # multiple groups with same nexthop
573         run_cmd "$IP nexthop add id 104 group 62"
574         run_cmd "$IP nexthop add id 105 group 62"
575         check_nexthop "group" "id 104 group 62 id 105 group 62"
576         log_test $? 0 "Multiple groups with same nexthop"
577
578         run_cmd "$IP nexthop flush groups"
579         [ $? -ne 0 ] && return 1
580
581         # on admin down of veth1, it should be removed from the group
582         run_cmd "$IP nexthop add id 105 group 62/63/72/73/64"
583         run_cmd "$IP li set veth1 down"
584         check_nexthop "id 105" "id 105 group 72/73"
585         log_test $? 0 "Nexthops in group removed on admin down - mixed group"
586
587         run_cmd "$IP nexthop add id 106 group 105/74"
588         log_test $? 2 "Nexthop group can not have a group as an entry"
589
590         # a group can have a blackhole entry only if it is the only
591         # nexthop in the group. Needed for atomic replace with an
592         # actual nexthop group
593         run_cmd "$IP -6 nexthop add id 31 blackhole"
594         run_cmd "$IP nexthop add id 107 group 31"
595         log_test $? 0 "Nexthop group with a blackhole entry"
596
597         run_cmd "$IP nexthop add id 108 group 31/24"
598         log_test $? 2 "Nexthop group can not have a blackhole and another nexthop"
599 }
600
601 ipv6_fcnal_runtime()
602 {
603         local rc
604
605         echo
606         echo "IPv6 functional runtime"
607         echo "-----------------------"
608
609         #
610         # IPv6 - the basics
611         #
612         run_cmd "$IP nexthop add id 81 via 2001:db8:91::2 dev veth1"
613         run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
614         log_test $? 0 "Route add"
615
616         run_cmd "$IP ro delete 2001:db8:101::1/128 nhid 81"
617         log_test $? 0 "Route delete"
618
619         run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
620         run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
621         log_test $? 0 "Ping with nexthop"
622
623         run_cmd "$IP nexthop add id 82 via 2001:db8:92::2 dev veth3"
624         run_cmd "$IP nexthop add id 122 group 81/82"
625         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
626         run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
627         log_test $? 0 "Ping - multipath"
628
629         #
630         # IPv6 with blackhole nexthops
631         #
632         run_cmd "$IP -6 nexthop add id 83 blackhole"
633         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 83"
634         run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
635         log_test $? 2 "Ping - blackhole"
636
637         run_cmd "$IP nexthop replace id 83 via 2001:db8:91::2 dev veth1"
638         run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
639         log_test $? 0 "Ping - blackhole replaced with gateway"
640
641         run_cmd "$IP -6 nexthop replace id 83 blackhole"
642         run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
643         log_test $? 2 "Ping - gateway replaced by blackhole"
644
645         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
646         run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
647         if [ $? -eq 0 ]; then
648                 run_cmd "$IP nexthop replace id 122 group 83"
649                 run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
650                 log_test $? 2 "Ping - group with blackhole"
651
652                 run_cmd "$IP nexthop replace id 122 group 81/82"
653                 run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
654                 log_test $? 0 "Ping - group blackhole replaced with gateways"
655         else
656                 log_test 2 0 "Ping - multipath failed"
657         fi
658
659         #
660         # device only and gw + dev only mix
661         #
662         run_cmd "$IP -6 nexthop add id 85 dev veth1"
663         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 85"
664         log_test $? 0 "IPv6 route with device only nexthop"
665         check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 85 dev veth1 metric 1024"
666
667         run_cmd "$IP nexthop add id 123 group 81/85"
668         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 123"
669         log_test $? 0 "IPv6 multipath route with nexthop mix - dev only + gw"
670         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"
671
672         #
673         # IPv6 route with v4 nexthop - not allowed
674         #
675         run_cmd "$IP ro delete 2001:db8:101::1/128"
676         run_cmd "$IP nexthop add id 84 via 172.16.1.1 dev veth1"
677         run_cmd "$IP ro add 2001:db8:101::1/128 nhid 84"
678         log_test $? 2 "IPv6 route can not have a v4 gateway"
679
680         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 81"
681         run_cmd "$IP nexthop replace id 81 via 172.16.1.1 dev veth1"
682         log_test $? 2 "Nexthop replace - v6 route, v4 nexthop"
683
684         run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 122"
685         run_cmd "$IP nexthop replace id 81 via 172.16.1.1 dev veth1"
686         log_test $? 2 "Nexthop replace of group entry - v6 route, v4 nexthop"
687
688         $IP nexthop flush >/dev/null 2>&1
689
690         #
691         # weird IPv6 cases
692         #
693         run_cmd "$IP nexthop add id 86 via 2001:db8:91::2 dev veth1"
694         run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
695
696         # TO-DO:
697         # existing route with old nexthop; append route with new nexthop
698         # existing route with old nexthop; replace route with new
699         # existing route with new nexthop; replace route with old
700         # route with src address and using nexthop - not allowed
701 }
702
703 ipv4_fcnal()
704 {
705         local rc
706
707         echo
708         echo "IPv4 functional"
709         echo "----------------------"
710
711         #
712         # basic IPv4 ops - add, get, delete
713         #
714         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
715         rc=$?
716         log_test $rc 0 "Create nexthop with id, gw, dev"
717         if [ $rc -ne 0 ]; then
718                 echo "Basic IPv4 create fails; can not continue"
719                 return 1
720         fi
721
722         run_cmd "$IP nexthop get id 12"
723         log_test $? 0 "Get nexthop by id"
724         check_nexthop "id 12" "id 12 via 172.16.1.2 dev veth1 scope link"
725
726         run_cmd "$IP nexthop del id 12"
727         log_test $? 0 "Delete nexthop by id"
728         check_nexthop "id 52" ""
729
730         #
731         # gw, device spec
732         #
733         # gw validation, no device - fails since dev is required
734         run_cmd "$IP nexthop add id 12 via 172.16.2.3"
735         log_test $? 2 "Create nexthop - gw only"
736
737         # gw not reachable through given dev
738         run_cmd "$IP nexthop add id 13 via 172.16.3.2 dev veth1"
739         log_test $? 2 "Create nexthop - invalid gw+dev combination"
740
741         # onlink flag overrides gw+dev lookup
742         run_cmd "$IP nexthop add id 13 via 172.16.3.2 dev veth1 onlink"
743         log_test $? 0 "Create nexthop - gw+dev and onlink"
744
745         # admin down should delete nexthops
746         set -e
747         run_cmd "$IP nexthop add id 15 via 172.16.1.3 dev veth1"
748         run_cmd "$IP nexthop add id 16 via 172.16.1.4 dev veth1"
749         run_cmd "$IP nexthop add id 17 via 172.16.1.5 dev veth1"
750         run_cmd "$IP li set dev veth1 down"
751         set +e
752         check_nexthop "dev veth1" ""
753         log_test $? 0 "Nexthops removed on admin down"
754 }
755
756 ipv4_grp_fcnal()
757 {
758         local rc
759
760         echo
761         echo "IPv4 groups functional"
762         echo "----------------------"
763
764         # basic functionality: create a nexthop group, default weight
765         run_cmd "$IP nexthop add id 11 via 172.16.1.2 dev veth1"
766         run_cmd "$IP nexthop add id 101 group 11"
767         log_test $? 0 "Create nexthop group with single nexthop"
768
769         # get nexthop group
770         run_cmd "$IP nexthop get id 101"
771         log_test $? 0 "Get nexthop group by id"
772         check_nexthop "id 101" "id 101 group 11"
773
774         # delete nexthop group
775         run_cmd "$IP nexthop del id 101"
776         log_test $? 0 "Delete nexthop group by id"
777         check_nexthop "id 101" ""
778
779         $IP nexthop flush >/dev/null 2>&1
780
781         #
782         # create group with multiple nexthops
783         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
784         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
785         run_cmd "$IP nexthop add id 14 via 172.16.1.4 dev veth1"
786         run_cmd "$IP nexthop add id 15 via 172.16.1.5 dev veth1"
787         run_cmd "$IP nexthop add id 102 group 12/13/14/15"
788         log_test $? 0 "Nexthop group with multiple nexthops"
789         check_nexthop "id 102" "id 102 group 12/13/14/15"
790
791         # Delete nexthop in a group and group is updated
792         run_cmd "$IP nexthop del id 13"
793         check_nexthop "id 102" "id 102 group 12/14/15"
794         log_test $? 0 "Nexthop group updated when entry is deleted"
795
796         # create group with multiple weighted nexthops
797         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
798         run_cmd "$IP nexthop add id 103 group 12/13,2/14,3/15,4"
799         log_test $? 0 "Nexthop group with weighted nexthops"
800         check_nexthop "id 103" "id 103 group 12/13,2/14,3/15,4"
801
802         # Delete nexthop in a weighted group and group is updated
803         run_cmd "$IP nexthop del id 13"
804         check_nexthop "id 103" "id 103 group 12/14,3/15,4"
805         log_test $? 0 "Weighted nexthop group updated when entry is deleted"
806
807         # admin down - nexthop is removed from group
808         run_cmd "$IP li set dev veth1 down"
809         check_nexthop "dev veth1" ""
810         log_test $? 0 "Nexthops in groups removed on admin down"
811
812         # expect groups to have been deleted as well
813         check_nexthop "" ""
814
815         run_cmd "$IP li set dev veth1 up"
816
817         $IP nexthop flush >/dev/null 2>&1
818
819         # group with nexthops using different devices
820         set -e
821         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
822         run_cmd "$IP nexthop add id 13 via 172.16.1.3 dev veth1"
823         run_cmd "$IP nexthop add id 14 via 172.16.1.4 dev veth1"
824         run_cmd "$IP nexthop add id 15 via 172.16.1.5 dev veth1"
825
826         run_cmd "$IP nexthop add id 22 via 172.16.2.2 dev veth3"
827         run_cmd "$IP nexthop add id 23 via 172.16.2.3 dev veth3"
828         run_cmd "$IP nexthop add id 24 via 172.16.2.4 dev veth3"
829         run_cmd "$IP nexthop add id 25 via 172.16.2.5 dev veth3"
830         set +e
831
832         # multiple groups with same nexthop
833         run_cmd "$IP nexthop add id 104 group 12"
834         run_cmd "$IP nexthop add id 105 group 12"
835         check_nexthop "group" "id 104 group 12 id 105 group 12"
836         log_test $? 0 "Multiple groups with same nexthop"
837
838         run_cmd "$IP nexthop flush groups"
839         [ $? -ne 0 ] && return 1
840
841         # on admin down of veth1, it should be removed from the group
842         run_cmd "$IP nexthop add id 105 group 12/13/22/23/14"
843         run_cmd "$IP li set veth1 down"
844         check_nexthop "id 105" "id 105 group 22/23"
845         log_test $? 0 "Nexthops in group removed on admin down - mixed group"
846
847         run_cmd "$IP nexthop add id 106 group 105/24"
848         log_test $? 2 "Nexthop group can not have a group as an entry"
849
850         # a group can have a blackhole entry only if it is the only
851         # nexthop in the group. Needed for atomic replace with an
852         # actual nexthop group
853         run_cmd "$IP nexthop add id 31 blackhole"
854         run_cmd "$IP nexthop add id 107 group 31"
855         log_test $? 0 "Nexthop group with a blackhole entry"
856
857         run_cmd "$IP nexthop add id 108 group 31/24"
858         log_test $? 2 "Nexthop group can not have a blackhole and another nexthop"
859 }
860
861 ipv4_withv6_fcnal()
862 {
863         local lladdr
864
865         set -e
866         lladdr=$(get_linklocal veth2 peer)
867         run_cmd "$IP nexthop add id 11 via ${lladdr} dev veth1"
868         set +e
869         run_cmd "$IP ro add 172.16.101.1/32 nhid 11"
870         log_test $? 0 "IPv6 nexthop with IPv4 route"
871         check_route "172.16.101.1" "172.16.101.1 nhid 11 via inet6 ${lladdr} dev veth1"
872
873         set -e
874         run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
875         run_cmd "$IP nexthop add id 101 group 11/12"
876         set +e
877         run_cmd "$IP ro replace 172.16.101.1/32 nhid 101"
878         log_test $? 0 "IPv6 nexthop with IPv4 route"
879
880         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"
881
882         run_cmd "$IP ro replace 172.16.101.1/32 via inet6 ${lladdr} dev veth1"
883         log_test $? 0 "IPv4 route with IPv6 gateway"
884         check_route "172.16.101.1" "172.16.101.1 via inet6 ${lladdr} dev veth1"
885
886         run_cmd "$IP ro replace 172.16.101.1/32 via inet6 2001:db8:50::1 dev veth1"
887         log_test $? 2 "IPv4 route with invalid IPv6 gateway"
888 }
889
890 ipv4_fcnal_runtime()
891 {
892         local lladdr
893         local rc
894
895         echo
896         echo "IPv4 functional runtime"
897         echo "-----------------------"
898
899         run_cmd "$IP nexthop add id 21 via 172.16.1.2 dev veth1"
900         run_cmd "$IP ro add 172.16.101.1/32 nhid 21"
901         log_test $? 0 "Route add"
902         check_route "172.16.101.1" "172.16.101.1 nhid 21 via 172.16.1.2 dev veth1"
903
904         run_cmd "$IP ro delete 172.16.101.1/32 nhid 21"
905         log_test $? 0 "Route delete"
906
907         #
908         # scope mismatch
909         #
910         run_cmd "$IP nexthop add id 22 via 172.16.1.2 dev veth1"
911         run_cmd "$IP ro add 172.16.101.1/32 nhid 22 scope host"
912         log_test $? 2 "Route add - scope conflict with nexthop"
913
914         run_cmd "$IP nexthop replace id 22 dev veth3"
915         run_cmd "$IP ro add 172.16.101.1/32 nhid 22 scope host"
916         run_cmd "$IP nexthop replace id 22 via 172.16.2.2 dev veth3"
917         log_test $? 2 "Nexthop replace with invalid scope for existing route"
918
919         #
920         # add route with nexthop and check traffic
921         #
922         run_cmd "$IP nexthop replace id 21 via 172.16.1.2 dev veth1"
923         run_cmd "$IP ro replace 172.16.101.1/32 nhid 21"
924         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
925         log_test $? 0 "Basic ping"
926
927         run_cmd "$IP nexthop replace id 22 via 172.16.2.2 dev veth3"
928         run_cmd "$IP nexthop add id 122 group 21/22"
929         run_cmd "$IP ro replace 172.16.101.1/32 nhid 122"
930         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
931         log_test $? 0 "Ping - multipath"
932
933         run_cmd "$IP ro delete 172.16.101.1/32 nhid 122"
934
935         #
936         # multiple default routes
937         # - tests fib_select_default
938         run_cmd "$IP nexthop add id 501 via 172.16.1.2 dev veth1"
939         run_cmd "$IP ro add default nhid 501"
940         run_cmd "$IP ro add default via 172.16.1.3 dev veth1 metric 20"
941         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
942         log_test $? 0 "Ping - multiple default routes, nh first"
943
944         # flip the order
945         run_cmd "$IP ro del default nhid 501"
946         run_cmd "$IP ro del default via 172.16.1.3 dev veth1 metric 20"
947         run_cmd "$IP ro add default via 172.16.1.2 dev veth1 metric 20"
948         run_cmd "$IP nexthop replace id 501 via 172.16.1.3 dev veth1"
949         run_cmd "$IP ro add default nhid 501 metric 20"
950         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
951         log_test $? 0 "Ping - multiple default routes, nh second"
952
953         run_cmd "$IP nexthop delete nhid 501"
954         run_cmd "$IP ro del default"
955
956         #
957         # IPv4 with blackhole nexthops
958         #
959         run_cmd "$IP nexthop add id 23 blackhole"
960         run_cmd "$IP ro replace 172.16.101.1/32 nhid 23"
961         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
962         log_test $? 2 "Ping - blackhole"
963
964         run_cmd "$IP nexthop replace id 23 via 172.16.1.2 dev veth1"
965         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
966         log_test $? 0 "Ping - blackhole replaced with gateway"
967
968         run_cmd "$IP nexthop replace id 23 blackhole"
969         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
970         log_test $? 2 "Ping - gateway replaced by blackhole"
971
972         run_cmd "$IP ro replace 172.16.101.1/32 nhid 122"
973         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
974         if [ $? -eq 0 ]; then
975                 run_cmd "$IP nexthop replace id 122 group 23"
976                 run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
977                 log_test $? 2 "Ping - group with blackhole"
978
979                 run_cmd "$IP nexthop replace id 122 group 21/22"
980                 run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
981                 log_test $? 0 "Ping - group blackhole replaced with gateways"
982         else
983                 log_test 2 0 "Ping - multipath failed"
984         fi
985
986         #
987         # device only and gw + dev only mix
988         #
989         run_cmd "$IP nexthop add id 85 dev veth1"
990         run_cmd "$IP ro replace 172.16.101.1/32 nhid 85"
991         log_test $? 0 "IPv4 route with device only nexthop"
992         check_route "172.16.101.1" "172.16.101.1 nhid 85 dev veth1"
993
994         run_cmd "$IP nexthop add id 123 group 21/85"
995         run_cmd "$IP ro replace 172.16.101.1/32 nhid 123"
996         log_test $? 0 "IPv4 multipath route with nexthop mix - dev only + gw"
997         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"
998
999         #
1000         # IPv4 with IPv6
1001         #
1002         set -e
1003         lladdr=$(get_linklocal veth2 peer)
1004         run_cmd "$IP nexthop add id 24 via ${lladdr} dev veth1"
1005         set +e
1006         run_cmd "$IP ro replace 172.16.101.1/32 nhid 24"
1007         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
1008         log_test $? 0 "IPv6 nexthop with IPv4 route"
1009
1010         $IP neigh sh | grep -q "${lladdr} dev veth1"
1011         if [ $? -eq 1 ]; then
1012                 echo "    WARNING: Neigh entry missing for ${lladdr}"
1013                 $IP neigh sh | grep 'dev veth1'
1014         fi
1015
1016         $IP neigh sh | grep -q "172.16.101.1 dev eth1"
1017         if [ $? -eq 0 ]; then
1018                 echo "    WARNING: Neigh entry exists for 172.16.101.1"
1019                 $IP neigh sh | grep 'dev veth1'
1020         fi
1021
1022         set -e
1023         run_cmd "$IP nexthop add id 25 via 172.16.1.2 dev veth1"
1024         run_cmd "$IP nexthop add id 101 group 24/25"
1025         set +e
1026         run_cmd "$IP ro replace 172.16.101.1/32 nhid 101"
1027         log_test $? 0 "IPv4 route with mixed v4-v6 multipath route"
1028
1029         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"
1030
1031         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
1032         log_test $? 0 "IPv6 nexthop with IPv4 route"
1033
1034         run_cmd "$IP ro replace 172.16.101.1/32 via inet6 ${lladdr} dev veth1"
1035         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
1036         log_test $? 0 "IPv4 route with IPv6 gateway"
1037
1038         $IP neigh sh | grep -q "${lladdr} dev veth1"
1039         if [ $? -eq 1 ]; then
1040                 echo "    WARNING: Neigh entry missing for ${lladdr}"
1041                 $IP neigh sh | grep 'dev veth1'
1042         fi
1043
1044         $IP neigh sh | grep -q "172.16.101.1 dev eth1"
1045         if [ $? -eq 0 ]; then
1046                 echo "    WARNING: Neigh entry exists for 172.16.101.1"
1047                 $IP neigh sh | grep 'dev veth1'
1048         fi
1049
1050         run_cmd "$IP ro del 172.16.101.1/32 via inet6 ${lladdr} dev veth1"
1051         run_cmd "$IP -4 ro add default via inet6 ${lladdr} dev veth1"
1052         run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
1053         log_test $? 0 "IPv4 default route with IPv6 gateway"
1054
1055         #
1056         # MPLS as an example of LWT encap
1057         #
1058         run_cmd "$IP nexthop add id 51 encap mpls 101 via 172.16.1.2 dev veth1"
1059         log_test $? 0 "IPv4 route with MPLS encap"
1060         check_nexthop "id 51" "id 51 encap mpls 101 via 172.16.1.2 dev veth1 scope link"
1061         log_test $? 0 "IPv4 route with MPLS encap - check"
1062
1063         run_cmd "$IP nexthop add id 52 encap mpls 102 via inet6 2001:db8:91::2 dev veth1"
1064         log_test $? 0 "IPv4 route with MPLS encap and v6 gateway"
1065         check_nexthop "id 52" "id 52 encap mpls 102 via 2001:db8:91::2 dev veth1 scope link"
1066         log_test $? 0 "IPv4 route with MPLS encap, v6 gw - check"
1067 }
1068
1069 sysctl_nexthop_compat_mode_check()
1070 {
1071         local sysctlname="net.ipv4.nexthop_compat_mode"
1072         local lprefix=$1
1073
1074         IPE="ip netns exec me"
1075
1076         $IPE sysctl -q $sysctlname 2>&1 >/dev/null
1077         if [ $? -ne 0 ]; then
1078                 echo "SKIP: kernel lacks nexthop compat mode sysctl control"
1079                 return $ksft_skip
1080         fi
1081
1082         out=$($IPE sysctl $sysctlname 2>/dev/null)
1083         log_test $? 0 "$lprefix default nexthop compat mode check"
1084         check_output "${out}" "$sysctlname = 1"
1085 }
1086
1087 sysctl_nexthop_compat_mode_set()
1088 {
1089         local sysctlname="net.ipv4.nexthop_compat_mode"
1090         local mode=$1
1091         local lprefix=$2
1092
1093         IPE="ip netns exec me"
1094
1095         out=$($IPE sysctl -w $sysctlname=$mode)
1096         log_test $? 0 "$lprefix set compat mode - $mode"
1097         check_output "${out}" "net.ipv4.nexthop_compat_mode = $mode"
1098 }
1099
1100 ipv6_compat_mode()
1101 {
1102         local rc
1103
1104         echo
1105         echo "IPv6 nexthop api compat mode test"
1106         echo "--------------------------------"
1107
1108         sysctl_nexthop_compat_mode_check "IPv6"
1109         if [ $? -eq $ksft_skip ]; then
1110                 return $ksft_skip
1111         fi
1112
1113         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
1114         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
1115         run_cmd "$IP nexthop add id 122 group 62/63"
1116         ipmout=$(start_ip_monitor route)
1117
1118         run_cmd "$IP -6 ro add 2001:db8:101::1/128 nhid 122"
1119         # route add notification should contain expanded nexthops
1120         stop_ip_monitor $ipmout 3
1121         log_test $? 0 "IPv6 compat mode on - route add notification"
1122
1123         # route dump should contain expanded nexthops
1124         check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 122 metric 1024 nexthop via 2001:db8:91::2 dev veth1 weight 1 nexthop via 2001:db8:91::3 dev veth1 weight 1"
1125         log_test $? 0 "IPv6 compat mode on - route dump"
1126
1127         # change in nexthop group should generate route notification
1128         run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
1129         ipmout=$(start_ip_monitor route)
1130         run_cmd "$IP nexthop replace id 122 group 62/64"
1131         stop_ip_monitor $ipmout 3
1132
1133         log_test $? 0 "IPv6 compat mode on - nexthop change"
1134
1135         # set compat mode off
1136         sysctl_nexthop_compat_mode_set 0 "IPv6"
1137
1138         run_cmd "$IP -6 ro del 2001:db8:101::1/128 nhid 122"
1139
1140         run_cmd "$IP nexthop add id 62 via 2001:db8:91::2 dev veth1"
1141         run_cmd "$IP nexthop add id 63 via 2001:db8:91::3 dev veth1"
1142         run_cmd "$IP nexthop add id 122 group 62/63"
1143         ipmout=$(start_ip_monitor route)
1144
1145         run_cmd "$IP -6 ro add 2001:db8:101::1/128 nhid 122"
1146         # route add notification should not contain expanded nexthops
1147         stop_ip_monitor $ipmout 1
1148         log_test $? 0 "IPv6 compat mode off - route add notification"
1149
1150         # route dump should not contain expanded nexthops
1151         check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 122 metric 1024"
1152         log_test $? 0 "IPv6 compat mode off - route dump"
1153
1154         # change in nexthop group should not generate route notification
1155         run_cmd "$IP nexthop add id 64 via 2001:db8:91::4 dev veth1"
1156         ipmout=$(start_ip_monitor route)
1157         run_cmd "$IP nexthop replace id 122 group 62/64"
1158         stop_ip_monitor $ipmout 0
1159         log_test $? 0 "IPv6 compat mode off - nexthop change"
1160
1161         # nexthop delete should not generate route notification
1162         ipmout=$(start_ip_monitor route)
1163         run_cmd "$IP nexthop del id 122"
1164         stop_ip_monitor $ipmout 0
1165         log_test $? 0 "IPv6 compat mode off - nexthop delete"
1166
1167         # set compat mode back on
1168         sysctl_nexthop_compat_mode_set 1 "IPv6"
1169 }
1170
1171 ipv4_compat_mode()
1172 {
1173         local rc
1174
1175         echo
1176         echo "IPv4 nexthop api compat mode"
1177         echo "----------------------------"
1178
1179         sysctl_nexthop_compat_mode_check "IPv4"
1180         if [ $? -eq $ksft_skip ]; then
1181                 return $ksft_skip
1182         fi
1183
1184         run_cmd "$IP nexthop add id 21 via 172.16.1.2 dev veth1"
1185         run_cmd "$IP nexthop add id 22 via 172.16.1.2 dev veth1"
1186         run_cmd "$IP nexthop add id 122 group 21/22"
1187         ipmout=$(start_ip_monitor route)
1188
1189         run_cmd "$IP ro add 172.16.101.1/32 nhid 122"
1190         stop_ip_monitor $ipmout 3
1191
1192         # route add notification should contain expanded nexthops
1193         log_test $? 0 "IPv4 compat mode on - route add notification"
1194
1195         # route dump should contain expanded nexthops
1196         check_route "172.16.101.1" "172.16.101.1 nhid 122 nexthop via 172.16.1.2 dev veth1 weight 1 nexthop via 172.16.1.2 dev veth1 weight 1"
1197         log_test $? 0 "IPv4 compat mode on - route dump"
1198
1199         # change in nexthop group should generate route notification
1200         run_cmd "$IP nexthop add id 23 via 172.16.1.3 dev veth1"
1201         ipmout=$(start_ip_monitor route)
1202         run_cmd "$IP nexthop replace id 122 group 21/23"
1203         stop_ip_monitor $ipmout 3
1204         log_test $? 0 "IPv4 compat mode on - nexthop change"
1205
1206         sysctl_nexthop_compat_mode_set 0 "IPv4"
1207
1208         # cleanup
1209         run_cmd "$IP ro del 172.16.101.1/32 nhid 122"
1210
1211         ipmout=$(start_ip_monitor route)
1212         run_cmd "$IP ro add 172.16.101.1/32 nhid 122"
1213         stop_ip_monitor $ipmout 1
1214         # route add notification should not contain expanded nexthops
1215         log_test $? 0 "IPv4 compat mode off - route add notification"
1216
1217         # route dump should not contain expanded nexthops
1218         check_route "172.16.101.1" "172.16.101.1 nhid 122"
1219         log_test $? 0 "IPv4 compat mode off - route dump"
1220
1221         # change in nexthop group should not generate route notification
1222         ipmout=$(start_ip_monitor route)
1223         run_cmd "$IP nexthop replace id 122 group 21/22"
1224         stop_ip_monitor $ipmout 0
1225         log_test $? 0 "IPv4 compat mode off - nexthop change"
1226
1227         # nexthop delete should not generate route notification
1228         ipmout=$(start_ip_monitor route)
1229         run_cmd "$IP nexthop del id 122"
1230         stop_ip_monitor $ipmout 0
1231         log_test $? 0 "IPv4 compat mode off - nexthop delete"
1232
1233         sysctl_nexthop_compat_mode_set 1 "IPv4"
1234 }
1235
1236 basic()
1237 {
1238         echo
1239         echo "Basic functional tests"
1240         echo "----------------------"
1241         run_cmd "$IP nexthop ls"
1242         log_test $? 0 "List with nothing defined"
1243
1244         run_cmd "$IP nexthop get id 1"
1245         log_test $? 2 "Nexthop get on non-existent id"
1246
1247         # attempt to create nh without a device or gw - fails
1248         run_cmd "$IP nexthop add id 1"
1249         log_test $? 2 "Nexthop with no device or gateway"
1250
1251         # attempt to create nh with down device - fails
1252         $IP li set veth1 down
1253         run_cmd "$IP nexthop add id 1 dev veth1"
1254         log_test $? 2 "Nexthop with down device"
1255
1256         # create nh with linkdown device - fails
1257         $IP li set veth1 up
1258         ip -netns peer li set veth2 down
1259         run_cmd "$IP nexthop add id 1 dev veth1"
1260         log_test $? 2 "Nexthop with device that is linkdown"
1261         ip -netns peer li set veth2 up
1262
1263         # device only
1264         run_cmd "$IP nexthop add id 1 dev veth1"
1265         log_test $? 0 "Nexthop with device only"
1266
1267         # create nh with duplicate id
1268         run_cmd "$IP nexthop add id 1 dev veth3"
1269         log_test $? 2 "Nexthop with duplicate id"
1270
1271         # blackhole nexthop
1272         run_cmd "$IP nexthop add id 2 blackhole"
1273         log_test $? 0 "Blackhole nexthop"
1274
1275         # blackhole nexthop can not have other specs
1276         run_cmd "$IP nexthop replace id 2 blackhole dev veth1"
1277         log_test $? 2 "Blackhole nexthop with other attributes"
1278
1279         #
1280         # groups
1281         #
1282
1283         run_cmd "$IP nexthop add id 101 group 1"
1284         log_test $? 0 "Create group"
1285
1286         run_cmd "$IP nexthop add id 102 group 2"
1287         log_test $? 0 "Create group with blackhole nexthop"
1288
1289         # multipath group can not have a blackhole as 1 path
1290         run_cmd "$IP nexthop add id 103 group 1/2"
1291         log_test $? 2 "Create multipath group where 1 path is a blackhole"
1292
1293         # multipath group can not have a member replaced by a blackhole
1294         run_cmd "$IP nexthop replace id 2 dev veth3"
1295         run_cmd "$IP nexthop replace id 102 group 1/2"
1296         run_cmd "$IP nexthop replace id 2 blackhole"
1297         log_test $? 2 "Multipath group can not have a member replaced by blackhole"
1298
1299         # attempt to create group with non-existent nexthop
1300         run_cmd "$IP nexthop add id 103 group 12"
1301         log_test $? 2 "Create group with non-existent nexthop"
1302
1303         # attempt to create group with same nexthop
1304         run_cmd "$IP nexthop add id 103 group 1/1"
1305         log_test $? 2 "Create group with same nexthop multiple times"
1306
1307         # replace nexthop with a group - fails
1308         run_cmd "$IP nexthop replace id 2 group 1"
1309         log_test $? 2 "Replace nexthop with nexthop group"
1310
1311         # replace nexthop group with a nexthop - fails
1312         run_cmd "$IP nexthop replace id 101 dev veth1"
1313         log_test $? 2 "Replace nexthop group with nexthop"
1314
1315         # nexthop group with other attributes fail
1316         run_cmd "$IP nexthop add id 104 group 1 dev veth1"
1317         log_test $? 2 "Nexthop group and device"
1318
1319         # Tests to ensure that flushing works as expected.
1320         run_cmd "$IP nexthop add id 105 blackhole proto 99"
1321         run_cmd "$IP nexthop add id 106 blackhole proto 100"
1322         run_cmd "$IP nexthop add id 107 blackhole proto 99"
1323         run_cmd "$IP nexthop flush proto 99"
1324         check_nexthop "id 105" ""
1325         check_nexthop "id 106" "id 106 blackhole proto 100"
1326         check_nexthop "id 107" ""
1327         run_cmd "$IP nexthop flush proto 100"
1328         check_nexthop "id 106" ""
1329
1330         run_cmd "$IP nexthop flush proto 100"
1331         log_test $? 0 "Test proto flush"
1332
1333         run_cmd "$IP nexthop add id 104 group 1 blackhole"
1334         log_test $? 2 "Nexthop group and blackhole"
1335
1336         $IP nexthop flush >/dev/null 2>&1
1337 }
1338
1339 ################################################################################
1340 # usage
1341
1342 usage()
1343 {
1344         cat <<EOF
1345 usage: ${0##*/} OPTS
1346
1347         -t <test>   Test(s) to run (default: all)
1348                     (options: $ALL_TESTS)
1349         -4          IPv4 tests only
1350         -6          IPv6 tests only
1351         -p          Pause on fail
1352         -P          Pause after each test before cleanup
1353         -v          verbose mode (show commands and output)
1354
1355     Runtime test
1356         -n num      Number of nexthops to target
1357         -N          Use new style to install routes in DUT
1358
1359 done
1360 EOF
1361 }
1362
1363 ################################################################################
1364 # main
1365
1366 while getopts :t:pP46hv o
1367 do
1368         case $o in
1369                 t) TESTS=$OPTARG;;
1370                 4) TESTS=${IPV4_TESTS};;
1371                 6) TESTS=${IPV6_TESTS};;
1372                 p) PAUSE_ON_FAIL=yes;;
1373                 P) PAUSE=yes;;
1374                 v) VERBOSE=$(($VERBOSE + 1));;
1375                 h) usage; exit 0;;
1376                 *) usage; exit 1;;
1377         esac
1378 done
1379
1380 # make sure we don't pause twice
1381 [ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
1382
1383 if [ "$(id -u)" -ne 0 ];then
1384         echo "SKIP: Need root privileges"
1385         exit $ksft_skip;
1386 fi
1387
1388 if [ ! -x "$(command -v ip)" ]; then
1389         echo "SKIP: Could not run test without ip tool"
1390         exit $ksft_skip
1391 fi
1392
1393 ip help 2>&1 | grep -q nexthop
1394 if [ $? -ne 0 ]; then
1395         echo "SKIP: iproute2 too old, missing nexthop command"
1396         exit $ksft_skip
1397 fi
1398
1399 out=$(ip nexthop ls 2>&1 | grep -q "Operation not supported")
1400 if [ $? -eq 0 ]; then
1401         echo "SKIP: kernel lacks nexthop support"
1402         exit $ksft_skip
1403 fi
1404
1405 for t in $TESTS
1406 do
1407         case $t in
1408         none) IP="ip -netns peer"; setup; exit 0;;
1409         *) setup; $t; cleanup;;
1410         esac
1411 done
1412
1413 if [ "$TESTS" != "none" ]; then
1414         printf "\nTests passed: %3d\n" ${nsuccess}
1415         printf "Tests failed: %3d\n"   ${nfail}
1416 fi
1417
1418 exit $ret