diff options
author | David Ahern <dsahern@gmail.com> | 2018-02-13 11:44:06 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-02-13 14:47:33 -0500 |
commit | 153e1b84f477f716bc3f81e6cfae1a3d941fc7ec (patch) | |
tree | 47f0f848223208a48fdff785a27ad3aab6272807 /tools | |
parent | b95367e3bd8eaf2d88d7b7a7ab2847f5a6e70321 (diff) |
selftests: Add FIB onlink tests
Add test cases verifying FIB onlink commands work as expected in
various conditions - IPv4, IPv6, main table, and VRF.
Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/testing/selftests/net/fib-onlink-tests.sh | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/tools/testing/selftests/net/fib-onlink-tests.sh b/tools/testing/selftests/net/fib-onlink-tests.sh new file mode 100755 index 000000000000..06b1d7cc12cc --- /dev/null +++ b/tools/testing/selftests/net/fib-onlink-tests.sh | |||
@@ -0,0 +1,375 @@ | |||
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.5.254 | ||
60 | |||
61 | # recursive gateway | ||
62 | RECGW4[1]=169.254.11.254 | ||
63 | RECGW4[2]=169.254.12.254 | ||
64 | RECGW6[1]=2001:db8:11::64 | ||
65 | RECGW6[2]=2001:db8:12::64 | ||
66 | |||
67 | # for v4 mapped to v6 | ||
68 | declare -A TEST_NET4IN6IN6 | ||
69 | TEST_NET4IN6[1]=10.1.1.254 | ||
70 | TEST_NET4IN6[2]=10.2.1.254 | ||
71 | |||
72 | # mcast address | ||
73 | MCAST6=ff02::1 | ||
74 | |||
75 | |||
76 | PEER_NS=bart | ||
77 | PEER_CMD="ip netns exec ${PEER_NS}" | ||
78 | VRF=lisa | ||
79 | VRF_TABLE=1101 | ||
80 | PBR_TABLE=101 | ||
81 | |||
82 | ################################################################################ | ||
83 | # utilities | ||
84 | |||
85 | log_test() | ||
86 | { | ||
87 | local rc=$1 | ||
88 | local expected=$2 | ||
89 | local msg="$3" | ||
90 | |||
91 | if [ ${rc} -eq ${expected} ]; then | ||
92 | nsuccess=$((nsuccess+1)) | ||
93 | printf "\n TEST: %-50s [ OK ]\n" "${msg}" | ||
94 | else | ||
95 | nfail=$((nfail+1)) | ||
96 | printf "\n TEST: %-50s [FAIL]\n" "${msg}" | ||
97 | if [ "${PAUSE_ON_FAIL}" = "yes" ]; then | ||
98 | echo | ||
99 | echo "hit enter to continue, 'q' to quit" | ||
100 | read a | ||
101 | [ "$a" = "q" ] && exit 1 | ||
102 | fi | ||
103 | fi | ||
104 | } | ||
105 | |||
106 | log_section() | ||
107 | { | ||
108 | echo | ||
109 | echo "######################################################################" | ||
110 | echo "TEST SECTION: $*" | ||
111 | echo "######################################################################" | ||
112 | } | ||
113 | |||
114 | log_subsection() | ||
115 | { | ||
116 | echo | ||
117 | echo "#########################################" | ||
118 | echo "TEST SUBSECTION: $*" | ||
119 | } | ||
120 | |||
121 | run_cmd() | ||
122 | { | ||
123 | echo | ||
124 | echo "COMMAND: $*" | ||
125 | eval $* | ||
126 | } | ||
127 | |||
128 | get_linklocal() | ||
129 | { | ||
130 | local dev=$1 | ||
131 | local pfx | ||
132 | local addr | ||
133 | |||
134 | addr=$(${pfx} ip -6 -br addr show dev ${dev} | \ | ||
135 | awk '{ | ||
136 | for (i = 3; i <= NF; ++i) { | ||
137 | if ($i ~ /^fe80/) | ||
138 | print $i | ||
139 | } | ||
140 | }' | ||
141 | ) | ||
142 | addr=${addr/\/*} | ||
143 | |||
144 | [ -z "$addr" ] && return 1 | ||
145 | |||
146 | echo $addr | ||
147 | |||
148 | return 0 | ||
149 | } | ||
150 | |||
151 | ################################################################################ | ||
152 | # | ||
153 | |||
154 | setup() | ||
155 | { | ||
156 | echo | ||
157 | echo "########################################" | ||
158 | echo "Configuring interfaces" | ||
159 | |||
160 | set -e | ||
161 | |||
162 | # create namespace | ||
163 | ip netns add ${PEER_NS} | ||
164 | ip -netns ${PEER_NS} li set lo up | ||
165 | |||
166 | # add vrf table | ||
167 | ip li add ${VRF} type vrf table ${VRF_TABLE} | ||
168 | ip li set ${VRF} up | ||
169 | ip ro add table ${VRF_TABLE} unreachable default | ||
170 | ip -6 ro add table ${VRF_TABLE} unreachable default | ||
171 | |||
172 | # create test interfaces | ||
173 | ip li add ${NETIFS[p1]} type veth peer name ${NETIFS[p2]} | ||
174 | ip li add ${NETIFS[p3]} type veth peer name ${NETIFS[p4]} | ||
175 | ip li add ${NETIFS[p5]} type veth peer name ${NETIFS[p6]} | ||
176 | ip li add ${NETIFS[p7]} type veth peer name ${NETIFS[p8]} | ||
177 | |||
178 | # enslave vrf interfaces | ||
179 | for n in 5 7; do | ||
180 | ip li set ${NETIFS[p${n}]} vrf ${VRF} | ||
181 | done | ||
182 | |||
183 | # add addresses | ||
184 | for n in 1 3 5 7; do | ||
185 | ip li set ${NETIFS[p${n}]} up | ||
186 | ip addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]} | ||
187 | ip addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} | ||
188 | done | ||
189 | |||
190 | # move peer interfaces to namespace and add addresses | ||
191 | for n in 2 4 6 8; do | ||
192 | ip li set ${NETIFS[p${n}]} netns ${PEER_NS} up | ||
193 | ip -netns ${PEER_NS} addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]} | ||
194 | ip -netns ${PEER_NS} addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} | ||
195 | done | ||
196 | |||
197 | set +e | ||
198 | |||
199 | # let DAD complete - assume default of 1 probe | ||
200 | sleep 1 | ||
201 | } | ||
202 | |||
203 | cleanup() | ||
204 | { | ||
205 | # make sure we start from a clean slate | ||
206 | ip netns del ${PEER_NS} 2>/dev/null | ||
207 | for n in 1 3 5 7; do | ||
208 | ip link del ${NETIFS[p${n}]} 2>/dev/null | ||
209 | done | ||
210 | ip link del ${VRF} 2>/dev/null | ||
211 | ip ro flush table ${VRF_TABLE} | ||
212 | ip -6 ro flush table ${VRF_TABLE} | ||
213 | } | ||
214 | |||
215 | ################################################################################ | ||
216 | # IPv4 tests | ||
217 | # | ||
218 | |||
219 | run_ip() | ||
220 | { | ||
221 | local table="$1" | ||
222 | local prefix="$2" | ||
223 | local gw="$3" | ||
224 | local dev="$4" | ||
225 | local exp_rc="$5" | ||
226 | local desc="$6" | ||
227 | |||
228 | # dev arg may be empty | ||
229 | [ -n "${dev}" ] && dev="dev ${dev}" | ||
230 | |||
231 | run_cmd ip ro add table "${table}" "${prefix}"/32 via "${gw}" "${dev}" onlink | ||
232 | log_test $? ${exp_rc} "${desc}" | ||
233 | } | ||
234 | |||
235 | valid_onlink_ipv4() | ||
236 | { | ||
237 | # - unicast connected, unicast recursive | ||
238 | # | ||
239 | log_subsection "default VRF - main table" | ||
240 | |||
241 | run_ip 254 ${TEST_NET4[1]}.1 ${CONGW[1]} ${NETIFS[p1]} 0 "unicast connected" | ||
242 | run_ip 254 ${TEST_NET4[1]}.2 ${RECGW4[1]} ${NETIFS[p1]} 0 "unicast recursive" | ||
243 | |||
244 | log_subsection "VRF ${VRF}" | ||
245 | |||
246 | run_ip ${VRF_TABLE} ${TEST_NET4[2]}.1 ${CONGW[2]} ${NETIFS[p5]} 0 "unicast connected" | ||
247 | run_ip ${VRF_TABLE} ${TEST_NET4[2]}.2 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive" | ||
248 | |||
249 | log_subsection "VRF device, PBR table" | ||
250 | |||
251 | run_ip ${PBR_TABLE} ${TEST_NET4[2]}.3 ${CONGW[2]} ${NETIFS[p5]} 0 "unicast connected" | ||
252 | run_ip ${PBR_TABLE} ${TEST_NET4[2]}.4 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive" | ||
253 | } | ||
254 | |||
255 | invalid_onlink_ipv4() | ||
256 | { | ||
257 | run_ip 254 ${TEST_NET4[1]}.11 ${V4ADDRS[p1]} ${NETIFS[p1]} 2 \ | ||
258 | "Invalid gw - local unicast address" | ||
259 | |||
260 | run_ip ${VRF_TABLE} ${TEST_NET4[2]}.11 ${V4ADDRS[p5]} ${NETIFS[p5]} 2 \ | ||
261 | "Invalid gw - local unicast address, VRF" | ||
262 | |||
263 | run_ip 254 ${TEST_NET4[1]}.101 ${V4ADDRS[p1]} "" 2 "No nexthop device given" | ||
264 | |||
265 | run_ip 254 ${TEST_NET4[1]}.102 ${V4ADDRS[p3]} ${NETIFS[p1]} 2 \ | ||
266 | "Gateway resolves to wrong nexthop device" | ||
267 | |||
268 | run_ip ${VRF_TABLE} ${TEST_NET4[2]}.103 ${V4ADDRS[p7]} ${NETIFS[p5]} 2 \ | ||
269 | "Gateway resolves to wrong nexthop device - VRF" | ||
270 | } | ||
271 | |||
272 | ################################################################################ | ||
273 | # IPv6 tests | ||
274 | # | ||
275 | |||
276 | run_ip6() | ||
277 | { | ||
278 | local table="$1" | ||
279 | local prefix="$2" | ||
280 | local gw="$3" | ||
281 | local dev="$4" | ||
282 | local exp_rc="$5" | ||
283 | local desc="$6" | ||
284 | |||
285 | # dev arg may be empty | ||
286 | [ -n "${dev}" ] && dev="dev ${dev}" | ||
287 | |||
288 | run_cmd ip -6 ro add table "${table}" "${prefix}"/128 via "${gw}" "${dev}" onlink | ||
289 | log_test $? ${exp_rc} "${desc}" | ||
290 | } | ||
291 | |||
292 | valid_onlink_ipv6() | ||
293 | { | ||
294 | # - unicast connected, unicast recursive, v4-mapped | ||
295 | # | ||
296 | log_subsection "default VRF - main table" | ||
297 | |||
298 | run_ip6 254 ${TEST_NET6[1]}::1 ${V6ADDRS[p1]/::*}::64 ${NETIFS[p1]} 0 "unicast connected" | ||
299 | run_ip6 254 ${TEST_NET6[1]}::2 ${RECGW6[1]} ${NETIFS[p1]} 0 "unicast recursive" | ||
300 | run_ip6 254 ${TEST_NET6[1]}::3 ::ffff:${TEST_NET4IN6[1]} ${NETIFS[p1]} 0 "v4-mapped" | ||
301 | |||
302 | log_subsection "VRF ${VRF}" | ||
303 | |||
304 | run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::1 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected" | ||
305 | run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::2 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive" | ||
306 | run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::3 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped" | ||
307 | |||
308 | log_subsection "VRF device, PBR table" | ||
309 | |||
310 | run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::4 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected" | ||
311 | run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::5 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive" | ||
312 | run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::6 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped" | ||
313 | } | ||
314 | |||
315 | invalid_onlink_ipv6() | ||
316 | { | ||
317 | local lladdr | ||
318 | |||
319 | lladdr=$(get_linklocal ${NETIFS[p1]}) || return 1 | ||
320 | |||
321 | run_ip6 254 ${TEST_NET6[1]}::11 ${V6ADDRS[p1]} ${NETIFS[p1]} 2 \ | ||
322 | "Invalid gw - local unicast address" | ||
323 | run_ip6 254 ${TEST_NET6[1]}::12 ${lladdr} ${NETIFS[p1]} 2 \ | ||
324 | "Invalid gw - local linklocal address" | ||
325 | run_ip6 254 ${TEST_NET6[1]}::12 ${MCAST6} ${NETIFS[p1]} 2 \ | ||
326 | "Invalid gw - multicast address" | ||
327 | |||
328 | lladdr=$(get_linklocal ${NETIFS[p5]}) || return 1 | ||
329 | run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::11 ${V6ADDRS[p5]} ${NETIFS[p5]} 2 \ | ||
330 | "Invalid gw - local unicast address, VRF" | ||
331 | run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${lladdr} ${NETIFS[p5]} 2 \ | ||
332 | "Invalid gw - local linklocal address, VRF" | ||
333 | run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${MCAST6} ${NETIFS[p5]} 2 \ | ||
334 | "Invalid gw - multicast address, VRF" | ||
335 | |||
336 | run_ip6 254 ${TEST_NET6[1]}::101 ${V6ADDRS[p1]} "" 2 \ | ||
337 | "No nexthop device given" | ||
338 | |||
339 | # default VRF validation is done against LOCAL table | ||
340 | # run_ip6 254 ${TEST_NET6[1]}::102 ${V6ADDRS[p3]/::[0-9]/::64} ${NETIFS[p1]} 2 \ | ||
341 | # "Gateway resolves to wrong nexthop device" | ||
342 | |||
343 | run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::103 ${V6ADDRS[p7]/::[0-9]/::64} ${NETIFS[p5]} 2 \ | ||
344 | "Gateway resolves to wrong nexthop device - VRF" | ||
345 | } | ||
346 | |||
347 | run_onlink_tests() | ||
348 | { | ||
349 | log_section "IPv4 onlink" | ||
350 | log_subsection "Valid onlink commands" | ||
351 | valid_onlink_ipv4 | ||
352 | log_subsection "Invalid onlink commands" | ||
353 | invalid_onlink_ipv4 | ||
354 | |||
355 | log_section "IPv6 onlink" | ||
356 | log_subsection "Valid onlink commands" | ||
357 | valid_onlink_ipv6 | ||
358 | invalid_onlink_ipv6 | ||
359 | } | ||
360 | |||
361 | ################################################################################ | ||
362 | # main | ||
363 | |||
364 | nsuccess=0 | ||
365 | nfail=0 | ||
366 | |||
367 | cleanup | ||
368 | setup | ||
369 | run_onlink_tests | ||
370 | cleanup | ||
371 | |||
372 | if [ "$TESTS" != "none" ]; then | ||
373 | printf "\nTests passed: %3d\n" ${nsuccess} | ||
374 | printf "Tests failed: %3d\n" ${nfail} | ||
375 | fi | ||