GNU Linux-libre 4.19.264-gnu1
[releases.git] / tools / testing / selftests / net / fib-onlink-tests.sh
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3
4 # IPv4 and IPv6 onlink tests
5
6 PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
7
8 # Network interfaces
9 # - odd in current namespace; even in peer ns
10 declare -A NETIFS
11 # default VRF
12 NETIFS[p1]=veth1
13 NETIFS[p2]=veth2
14 NETIFS[p3]=veth3
15 NETIFS[p4]=veth4
16 # VRF
17 NETIFS[p5]=veth5
18 NETIFS[p6]=veth6
19 NETIFS[p7]=veth7
20 NETIFS[p8]=veth8
21
22 # /24 network
23 declare -A V4ADDRS
24 V4ADDRS[p1]=169.254.1.1
25 V4ADDRS[p2]=169.254.1.2
26 V4ADDRS[p3]=169.254.3.1
27 V4ADDRS[p4]=169.254.3.2
28 V4ADDRS[p5]=169.254.5.1
29 V4ADDRS[p6]=169.254.5.2
30 V4ADDRS[p7]=169.254.7.1
31 V4ADDRS[p8]=169.254.7.2
32
33 # /64 network
34 declare -A V6ADDRS
35 V6ADDRS[p1]=2001:db8:101::1
36 V6ADDRS[p2]=2001:db8:101::2
37 V6ADDRS[p3]=2001:db8:301::1
38 V6ADDRS[p4]=2001:db8:301::2
39 V6ADDRS[p5]=2001:db8:501::1
40 V6ADDRS[p6]=2001:db8:501::2
41 V6ADDRS[p7]=2001:db8:701::1
42 V6ADDRS[p8]=2001:db8:701::2
43
44 # Test networks:
45 # [1] = default table
46 # [2] = VRF
47 #
48 # /32 host routes
49 declare -A TEST_NET4
50 TEST_NET4[1]=169.254.101
51 TEST_NET4[2]=169.254.102
52 # /128 host routes
53 declare -A TEST_NET6
54 TEST_NET6[1]=2001:db8:101
55 TEST_NET6[2]=2001:db8:102
56
57 # connected gateway
58 CONGW[1]=169.254.1.254
59 CONGW[2]=169.254.3.254
60 CONGW[3]=169.254.5.254
61
62 # recursive gateway
63 RECGW4[1]=169.254.11.254
64 RECGW4[2]=169.254.12.254
65 RECGW6[1]=2001:db8:11::64
66 RECGW6[2]=2001:db8:12::64
67
68 # for v4 mapped to v6
69 declare -A TEST_NET4IN6IN6
70 TEST_NET4IN6[1]=10.1.1.254
71 TEST_NET4IN6[2]=10.2.1.254
72
73 # mcast address
74 MCAST6=ff02::1
75
76
77 PEER_NS=bart
78 PEER_CMD="ip netns exec ${PEER_NS}"
79 VRF=lisa
80 VRF_TABLE=1101
81 PBR_TABLE=101
82
83 ################################################################################
84 # utilities
85
86 log_test()
87 {
88         local rc=$1
89         local expected=$2
90         local msg="$3"
91
92         if [ ${rc} -eq ${expected} ]; then
93                 nsuccess=$((nsuccess+1))
94                 printf "\n    TEST: %-50s  [ OK ]\n" "${msg}"
95         else
96                 nfail=$((nfail+1))
97                 printf "\n    TEST: %-50s  [FAIL]\n" "${msg}"
98                 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
99                         echo
100                         echo "hit enter to continue, 'q' to quit"
101                         read a
102                         [ "$a" = "q" ] && exit 1
103                 fi
104         fi
105 }
106
107 log_section()
108 {
109         echo
110         echo "######################################################################"
111         echo "TEST SECTION: $*"
112         echo "######################################################################"
113 }
114
115 log_subsection()
116 {
117         echo
118         echo "#########################################"
119         echo "TEST SUBSECTION: $*"
120 }
121
122 run_cmd()
123 {
124         echo
125         echo "COMMAND: $*"
126         eval $*
127 }
128
129 get_linklocal()
130 {
131         local dev=$1
132         local pfx
133         local addr
134
135         addr=$(${pfx} ip -6 -br addr show dev ${dev} | \
136         awk '{
137                 for (i = 3; i <= NF; ++i) {
138                         if ($i ~ /^fe80/)
139                                 print $i
140                 }
141         }'
142         )
143         addr=${addr/\/*}
144
145         [ -z "$addr" ] && return 1
146
147         echo $addr
148
149         return 0
150 }
151
152 ################################################################################
153 #
154
155 setup()
156 {
157         echo
158         echo "########################################"
159         echo "Configuring interfaces"
160
161         set -e
162
163         # create namespace
164         ip netns add ${PEER_NS}
165         ip -netns ${PEER_NS} li set lo up
166
167         # add vrf table
168         ip li add ${VRF} type vrf table ${VRF_TABLE}
169         ip li set ${VRF} up
170         ip ro add table ${VRF_TABLE} unreachable default metric 8192
171         ip -6 ro add table ${VRF_TABLE} unreachable default metric 8192
172
173         # create test interfaces
174         ip li add ${NETIFS[p1]} type veth peer name ${NETIFS[p2]}
175         ip li add ${NETIFS[p3]} type veth peer name ${NETIFS[p4]}
176         ip li add ${NETIFS[p5]} type veth peer name ${NETIFS[p6]}
177         ip li add ${NETIFS[p7]} type veth peer name ${NETIFS[p8]}
178
179         # enslave vrf interfaces
180         for n in 5 7; do
181                 ip li set ${NETIFS[p${n}]} vrf ${VRF}
182         done
183
184         # add addresses
185         for n in 1 3 5 7; do
186                 ip li set ${NETIFS[p${n}]} up
187                 ip addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
188                 ip addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad
189         done
190
191         # move peer interfaces to namespace and add addresses
192         for n in 2 4 6 8; do
193                 ip li set ${NETIFS[p${n}]} netns ${PEER_NS} up
194                 ip -netns ${PEER_NS} addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
195                 ip -netns ${PEER_NS} addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad
196         done
197
198         ip -6 ro add default via ${V6ADDRS[p3]/::[0-9]/::64}
199         ip -6 ro add table ${VRF_TABLE} default via ${V6ADDRS[p7]/::[0-9]/::64}
200
201         set +e
202 }
203
204 cleanup()
205 {
206         # make sure we start from a clean slate
207         ip netns del ${PEER_NS} 2>/dev/null
208         for n in 1 3 5 7; do
209                 ip link del ${NETIFS[p${n}]} 2>/dev/null
210         done
211         ip link del ${VRF} 2>/dev/null
212         ip ro flush table ${VRF_TABLE}
213         ip -6 ro flush table ${VRF_TABLE}
214 }
215
216 ################################################################################
217 # IPv4 tests
218 #
219
220 run_ip()
221 {
222         local table="$1"
223         local prefix="$2"
224         local gw="$3"
225         local dev="$4"
226         local exp_rc="$5"
227         local desc="$6"
228
229         # dev arg may be empty
230         [ -n "${dev}" ] && dev="dev ${dev}"
231
232         run_cmd ip ro add table "${table}" "${prefix}"/32 via "${gw}" "${dev}" onlink
233         log_test $? ${exp_rc} "${desc}"
234 }
235
236 run_ip_mpath()
237 {
238         local table="$1"
239         local prefix="$2"
240         local nh1="$3"
241         local nh2="$4"
242         local exp_rc="$5"
243         local desc="$6"
244
245         # dev arg may be empty
246         [ -n "${dev}" ] && dev="dev ${dev}"
247
248         run_cmd ip ro add table "${table}" "${prefix}"/32 \
249                 nexthop via ${nh1} nexthop via ${nh2}
250         log_test $? ${exp_rc} "${desc}"
251 }
252
253 valid_onlink_ipv4()
254 {
255         # - unicast connected, unicast recursive
256         #
257         log_subsection "default VRF - main table"
258
259         run_ip 254 ${TEST_NET4[1]}.1 ${CONGW[1]} ${NETIFS[p1]} 0 "unicast connected"
260         run_ip 254 ${TEST_NET4[1]}.2 ${RECGW4[1]} ${NETIFS[p1]} 0 "unicast recursive"
261
262         log_subsection "VRF ${VRF}"
263
264         run_ip ${VRF_TABLE} ${TEST_NET4[2]}.1 ${CONGW[3]} ${NETIFS[p5]} 0 "unicast connected"
265         run_ip ${VRF_TABLE} ${TEST_NET4[2]}.2 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive"
266
267         log_subsection "VRF device, PBR table"
268
269         run_ip ${PBR_TABLE} ${TEST_NET4[2]}.3 ${CONGW[3]} ${NETIFS[p5]} 0 "unicast connected"
270         run_ip ${PBR_TABLE} ${TEST_NET4[2]}.4 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive"
271
272         # multipath version
273         #
274         log_subsection "default VRF - main table - multipath"
275
276         run_ip_mpath 254 ${TEST_NET4[1]}.5 \
277                 "${CONGW[1]} dev ${NETIFS[p1]} onlink" \
278                 "${CONGW[2]} dev ${NETIFS[p3]} onlink" \
279                 0 "unicast connected - multipath"
280
281         run_ip_mpath 254 ${TEST_NET4[1]}.6 \
282                 "${RECGW4[1]} dev ${NETIFS[p1]} onlink" \
283                 "${RECGW4[2]} dev ${NETIFS[p3]} onlink" \
284                 0 "unicast recursive - multipath"
285
286         run_ip_mpath 254 ${TEST_NET4[1]}.7 \
287                 "${CONGW[1]} dev ${NETIFS[p1]}"        \
288                 "${CONGW[2]} dev ${NETIFS[p3]} onlink" \
289                 0 "unicast connected - multipath onlink first only"
290
291         run_ip_mpath 254 ${TEST_NET4[1]}.8 \
292                 "${CONGW[1]} dev ${NETIFS[p1]} onlink" \
293                 "${CONGW[2]} dev ${NETIFS[p3]}"        \
294                 0 "unicast connected - multipath onlink second only"
295 }
296
297 invalid_onlink_ipv4()
298 {
299         run_ip 254 ${TEST_NET4[1]}.11 ${V4ADDRS[p1]} ${NETIFS[p1]} 2 \
300                 "Invalid gw - local unicast address"
301
302         run_ip ${VRF_TABLE} ${TEST_NET4[2]}.11 ${V4ADDRS[p5]} ${NETIFS[p5]} 2 \
303                 "Invalid gw - local unicast address, VRF"
304
305         run_ip 254 ${TEST_NET4[1]}.101 ${V4ADDRS[p1]} "" 2 "No nexthop device given"
306
307         run_ip 254 ${TEST_NET4[1]}.102 ${V4ADDRS[p3]} ${NETIFS[p1]} 2 \
308                 "Gateway resolves to wrong nexthop device"
309
310         run_ip ${VRF_TABLE} ${TEST_NET4[2]}.103 ${V4ADDRS[p7]} ${NETIFS[p5]} 2 \
311                 "Gateway resolves to wrong nexthop device - VRF"
312 }
313
314 ################################################################################
315 # IPv6 tests
316 #
317
318 run_ip6()
319 {
320         local table="$1"
321         local prefix="$2"
322         local gw="$3"
323         local dev="$4"
324         local exp_rc="$5"
325         local desc="$6"
326
327         # dev arg may be empty
328         [ -n "${dev}" ] && dev="dev ${dev}"
329
330         run_cmd ip -6 ro add table "${table}" "${prefix}"/128 via "${gw}" "${dev}" onlink
331         log_test $? ${exp_rc} "${desc}"
332 }
333
334 run_ip6_mpath()
335 {
336         local table="$1"
337         local prefix="$2"
338         local opts="$3"
339         local nh1="$4"
340         local nh2="$5"
341         local exp_rc="$6"
342         local desc="$7"
343
344         run_cmd ip -6 ro add table "${table}" "${prefix}"/128 "${opts}" \
345                 nexthop via ${nh1} nexthop via ${nh2}
346         log_test $? ${exp_rc} "${desc}"
347 }
348
349 valid_onlink_ipv6()
350 {
351         # - unicast connected, unicast recursive, v4-mapped
352         #
353         log_subsection "default VRF - main table"
354
355         run_ip6 254 ${TEST_NET6[1]}::1 ${V6ADDRS[p1]/::*}::64 ${NETIFS[p1]} 0 "unicast connected"
356         run_ip6 254 ${TEST_NET6[1]}::2 ${RECGW6[1]} ${NETIFS[p1]} 0 "unicast recursive"
357         run_ip6 254 ${TEST_NET6[1]}::3 ::ffff:${TEST_NET4IN6[1]} ${NETIFS[p1]} 0 "v4-mapped"
358
359         log_subsection "VRF ${VRF}"
360
361         run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::1 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected"
362         run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::2 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive"
363         run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::3 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped"
364
365         log_subsection "VRF device, PBR table"
366
367         run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::4 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected"
368         run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::5 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive"
369         run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::6 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped"
370
371         # multipath version
372         #
373         log_subsection "default VRF - main table - multipath"
374
375         run_ip6_mpath 254 ${TEST_NET6[1]}::4 "onlink" \
376                 "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]}" \
377                 "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]}" \
378                 0 "unicast connected - multipath onlink"
379
380         run_ip6_mpath 254 ${TEST_NET6[1]}::5 "onlink" \
381                 "${RECGW6[1]} dev ${NETIFS[p1]}" \
382                 "${RECGW6[2]} dev ${NETIFS[p3]}" \
383                 0 "unicast recursive - multipath onlink"
384
385         run_ip6_mpath 254 ${TEST_NET6[1]}::6 "onlink" \
386                 "::ffff:${TEST_NET4IN6[1]} dev ${NETIFS[p1]}" \
387                 "::ffff:${TEST_NET4IN6[2]} dev ${NETIFS[p3]}" \
388                 0 "v4-mapped - multipath onlink"
389
390         run_ip6_mpath 254 ${TEST_NET6[1]}::7 "" \
391                 "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]} onlink" \
392                 "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]} onlink" \
393                 0 "unicast connected - multipath onlink both nexthops"
394
395         run_ip6_mpath 254 ${TEST_NET6[1]}::8 "" \
396                 "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]} onlink" \
397                 "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]}" \
398                 0 "unicast connected - multipath onlink first only"
399
400         run_ip6_mpath 254 ${TEST_NET6[1]}::9 "" \
401                 "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]}"        \
402                 "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]} onlink" \
403                 0 "unicast connected - multipath onlink second only"
404 }
405
406 invalid_onlink_ipv6()
407 {
408         local lladdr
409
410         lladdr=$(get_linklocal ${NETIFS[p1]}) || return 1
411
412         run_ip6 254 ${TEST_NET6[1]}::11 ${V6ADDRS[p1]} ${NETIFS[p1]} 2 \
413                 "Invalid gw - local unicast address"
414         run_ip6 254 ${TEST_NET6[1]}::12 ${lladdr} ${NETIFS[p1]} 2 \
415                 "Invalid gw - local linklocal address"
416         run_ip6 254 ${TEST_NET6[1]}::12 ${MCAST6} ${NETIFS[p1]} 2 \
417                 "Invalid gw - multicast address"
418
419         lladdr=$(get_linklocal ${NETIFS[p5]}) || return 1
420         run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::11 ${V6ADDRS[p5]} ${NETIFS[p5]} 2 \
421                 "Invalid gw - local unicast address, VRF"
422         run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${lladdr} ${NETIFS[p5]} 2 \
423                 "Invalid gw - local linklocal address, VRF"
424         run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${MCAST6} ${NETIFS[p5]} 2 \
425                 "Invalid gw - multicast address, VRF"
426
427         run_ip6 254 ${TEST_NET6[1]}::101 ${V6ADDRS[p1]} "" 2 \
428                 "No nexthop device given"
429
430         # default VRF validation is done against LOCAL table
431         # run_ip6 254 ${TEST_NET6[1]}::102 ${V6ADDRS[p3]/::[0-9]/::64} ${NETIFS[p1]} 2 \
432         #       "Gateway resolves to wrong nexthop device"
433
434         run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::103 ${V6ADDRS[p7]/::[0-9]/::64} ${NETIFS[p5]} 2 \
435                 "Gateway resolves to wrong nexthop device - VRF"
436 }
437
438 run_onlink_tests()
439 {
440         log_section "IPv4 onlink"
441         log_subsection "Valid onlink commands"
442         valid_onlink_ipv4
443         log_subsection "Invalid onlink commands"
444         invalid_onlink_ipv4
445
446         log_section "IPv6 onlink"
447         log_subsection "Valid onlink commands"
448         valid_onlink_ipv6
449         log_subsection "Invalid onlink commands"
450         invalid_onlink_ipv6
451 }
452
453 ################################################################################
454 # main
455
456 nsuccess=0
457 nfail=0
458
459 cleanup
460 setup
461 run_onlink_tests
462 cleanup
463
464 if [ "$TESTS" != "none" ]; then
465         printf "\nTests passed: %3d\n" ${nsuccess}
466         printf "Tests failed: %3d\n"   ${nfail}
467 fi