t_ndp.sh revision 1.14 1 # $NetBSD: t_ndp.sh,v 1.14 2016/11/07 05:25:37 ozaki-r Exp $
2 #
3 # Copyright (c) 2015 The NetBSD Foundation, Inc.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 # POSSIBILITY OF SUCH DAMAGE.
26 #
27
28 inetserver="rump_server -lrumpnet -lrumpnet_net -lrumpnet_netinet"
29 inetserver="$inetserver -lrumpnet_netinet6 -lrumpnet_shmif"
30 inetserver="$inetserver -lrumpdev"
31 HIJACKING="env LD_PRELOAD=/usr/lib/librumphijack.so RUMPHIJACK=sysctl=yes"
32
33 SOCKSRC=unix://commsock1
34 SOCKDST=unix://commsock2
35 IP6SRC=fc00::1
36 IP6DST=fc00::2
37
38 DEBUG=${DEBUG:-true}
39 TIMEOUT=1
40
41 atf_test_case ndp_cache_expiration cleanup
42 atf_test_case ndp_commands cleanup
43 atf_test_case ndp_cache_overwriting cleanup
44 atf_test_case ndp_neighborgcthresh cleanup
45 atf_test_case ndp_link_activation cleanup
46
47 ndp_cache_expiration_head()
48 {
49 atf_set "descr" "Tests for NDP cache expiration"
50 atf_set "require.progs" "rump_server"
51 }
52
53 ndp_commands_head()
54 {
55 atf_set "descr" "Tests for commands of ndp(8)"
56 atf_set "require.progs" "rump_server"
57 }
58
59 ndp_cache_overwriting_head()
60 {
61 atf_set "descr" "Tests for behavior of overwriting NDP caches"
62 atf_set "require.progs" "rump_server"
63 }
64
65 ndp_neighborgcthresh_head()
66 {
67 atf_set "descr" "Tests for GC of neighbor caches"
68 atf_set "require.progs" "rump_server"
69 }
70
71 ndp_link_activation_head()
72 {
73 atf_set "descr" "Tests for activating a new MAC address"
74 atf_set "require.progs" "rump_server"
75 }
76
77 setup_dst_server()
78 {
79 local assign_ip=$1
80
81 export RUMP_SERVER=$SOCKDST
82 atf_check -s exit:0 rump.ifconfig shmif0 create
83 atf_check -s exit:0 rump.ifconfig shmif0 linkstr bus1
84 if [ "$assign_ip" != no ]; then
85 atf_check -s exit:0 rump.ifconfig shmif0 inet6 $IP6DST
86 fi
87 atf_check -s exit:0 rump.ifconfig shmif0 up
88 atf_check -s exit:0 rump.ifconfig -w 10
89
90 $DEBUG && rump.ifconfig shmif0
91 $DEBUG && rump.ndp -n -a
92 }
93
94 setup_src_server()
95 {
96 $DEBUG && ulimit -c unlimited
97 export RUMP_SERVER=$SOCKSRC
98
99 # Setup an interface
100 atf_check -s exit:0 rump.ifconfig shmif0 create
101 atf_check -s exit:0 rump.ifconfig shmif0 linkstr bus1
102 atf_check -s exit:0 rump.ifconfig shmif0 inet6 $IP6SRC
103 atf_check -s exit:0 rump.ifconfig shmif0 up
104 atf_check -s exit:0 rump.ifconfig -w 10
105
106 # Sanity check
107 $DEBUG && rump.ifconfig shmif0
108 $DEBUG && rump.ndp -n -a
109 atf_check -s exit:0 -o ignore rump.ndp -n $IP6SRC
110 atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6DST
111 }
112
113 get_timeout()
114 {
115 local timeout=$(env RUMP_SERVER=$SOCKSRC rump.ndp -n $IP6DST |grep $IP6DST|awk '{print $4;}')
116 timeout=${timeout%s}
117 echo $timeout
118 }
119
120 ndp_cache_expiration_body()
121 {
122 atf_check -s exit:0 ${inetserver} $SOCKSRC
123 atf_check -s exit:0 ${inetserver} $SOCKDST
124
125 setup_dst_server
126 setup_src_server
127
128 #
129 # Check if a cache is expired expectedly
130 #
131 export RUMP_SERVER=$SOCKSRC
132 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
133
134 $DEBUG && rump.ndp -n -a
135 atf_check -s exit:0 -o match:'permanent' rump.ndp -n $IP6SRC
136 # Should be cached
137 atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n $IP6DST
138
139 timeout=$(get_timeout $IP6DST)
140
141 atf_check -s exit:0 sleep $(($timeout + 1))
142
143 $DEBUG && rump.ndp -n -a
144 atf_check -s exit:0 -o match:'permanent' rump.ndp -n $IP6SRC
145 # Expired but remains until GC sweaps it (1 day)
146 atf_check -s exit:0 -o match:'(1d0h0m|23h59m)' rump.ndp -n $IP6DST
147 }
148
149 ifdown_dst_server()
150 {
151 export RUMP_SERVER=$SOCKDST
152 atf_check -s exit:0 rump.ifconfig shmif0 down
153 export RUMP_SERVER=$SOCKSRC
154 }
155
156 ndp_commands_body()
157 {
158 atf_check -s exit:0 ${inetserver} $SOCKSRC
159 atf_check -s exit:0 ${inetserver} $SOCKDST
160
161 setup_dst_server
162 setup_src_server
163
164 export RUMP_SERVER=$SOCKSRC
165
166 # We can delete the entry for the interface's IP address
167 atf_check -s exit:0 -o match:"$IP6SRC" rump.ndp -d $IP6SRC
168
169 # Add and delete a static entry
170 $DEBUG && rump.ndp -n -a
171 atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10
172 $DEBUG && rump.ndp -n -a
173 atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::10
174 atf_check -s exit:0 -o match:'deleted' rump.ndp -d fc00::10
175 $DEBUG && rump.ndp -n -a
176 atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n fc00::10
177
178 # Add multiple entries via a file (XXX not implemented)
179 #cat - > ./list <<-EOF
180 #fc00::11 b2:a0:20:00:00:11
181 #fc00::12 b2:a0:20:00:00:12
182 #fc00::13 b2:a0:20:00:00:13
183 #fc00::14 b2:a0:20:00:00:14
184 #fc00::15 b2:a0:20:00:00:15
185 #EOF
186 #$DEBUG && rump.ndp -n -a
187 #atf_check -s exit:0 -o ignore rump.ndp -f ./list
188 #$DEBUG && rump.ndp -n -a
189
190 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
191 atf_check -s exit:0 -o ignore rump.ndp -s fc00::11 b2:a0:20:00:00:11
192 atf_check -s exit:0 -o ignore rump.ndp -s fc00::12 b2:a0:20:00:00:12
193
194 atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n $IP6DST
195 atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::11
196 atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::12
197
198 # Test ndp -a
199 atf_check -s exit:0 -o match:'fc00::11' rump.ndp -n -a
200 atf_check -s exit:0 -o match:'fc00::12' rump.ndp -n -a
201
202 # Ensure no packet upsets the src server
203 ifdown_dst_server
204
205 # Flush all entries (-c)
206 $DEBUG && rump.ndp -n -a
207 atf_check -s exit:0 -o ignore rump.ndp -c
208 atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6SRC
209 atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6DST
210 # Only the static caches are not deleted
211 atf_check -s exit:0 -o ignore -e ignore rump.ndp -n fc00::11
212 atf_check -s exit:0 -o ignore -e ignore rump.ndp -n fc00::12
213
214 $DEBUG && rump.ndp -n -a
215 atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
216 rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
217 $DEBUG && rump.ndp -n -a
218 atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n fc00::10
219
220 return 0
221 }
222
223 ndp_cache_overwriting_body()
224 {
225 atf_check -s exit:0 ${inetserver} $SOCKSRC
226 atf_check -s exit:0 ${inetserver} $SOCKDST
227
228 setup_dst_server
229 setup_src_server
230
231 export RUMP_SERVER=$SOCKSRC
232
233 # Cannot overwrite a permanent cache
234 atf_check -s not-exit:0 -e ignore rump.ndp -s $IP6SRC b2:a0:20:00:00:ff
235 $DEBUG && rump.ndp -n -a
236
237 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
238 $DEBUG && rump.ndp -n -a
239 # Can overwrite a dynamic cache
240 atf_check -s exit:0 -o ignore rump.ndp -s $IP6DST b2:a0:20:00:00:00
241 $DEBUG && rump.ndp -n -a
242 atf_check -s exit:0 -o match:'permanent' rump.ndp -n $IP6DST
243
244 # Test temp option (XXX it doesn't work; expire time isn't set)
245 #atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
246 #$DEBUG && rump.ndp -n -a
247 #atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n fc00::10
248 # Cannot overwrite a temp cache
249 #atf_check -s not-exit:0 -e ignore rump.ndp -s fc00::10 b2:a0:20:00:00:ff
250 #$DEBUG && rump.ndp -n -a
251
252 return 0
253 }
254
255 get_n_caches()
256 {
257
258 echo $(rump.ndp -a -n |grep -v -e Neighbor -e permanent |wc -l)
259 }
260
261 ndp_neighborgcthresh_body()
262 {
263
264 atf_check -s exit:0 ${inetserver} $SOCKSRC
265 atf_check -s exit:0 ${inetserver} $SOCKDST
266
267 setup_dst_server no
268 setup_src_server
269
270 export RUMP_SERVER=$SOCKDST
271 for i in $(seq 0 9); do
272 atf_check -s exit:0 rump.ifconfig shmif0 inet6 ${IP6DST}$i
273 done
274
275 export RUMP_SERVER=$SOCKSRC
276
277 # ping to 3 destinations
278 $DEBUG && rump.ndp -n -a
279 for i in $(seq 0 2); do
280 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
281 ${IP6DST}$i
282 done
283 $DEBUG && rump.ndp -n -a
284
285 # 3 caches should be created
286 atf_check_equal $(get_n_caches) 3
287
288 # ping to additional 3 destinations
289 for i in $(seq 3 5); do
290 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
291 ${IP6DST}$i
292 done
293 $DEBUG && rump.ndp -n -a
294
295 # 6 caches should be created in total
296 atf_check_equal $(get_n_caches) 6
297
298 # Limit the number of neighbor caches to 5
299 atf_check -s exit:0 -o ignore rump.sysctl -w \
300 net.inet6.ip6.neighborgcthresh=5
301
302 # ping to additional 4 destinations
303 for i in $(seq 6 9); do
304 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
305 ${IP6DST}$i
306 done
307
308 # More than 5 caches should be created in total, but exceeded caches
309 # should be GC-ed
310 if [ "$(get_n_caches)" -gt 5 ]; then
311 atf_fail "Neighbor caches are not GC-ed"
312 fi
313
314 return 0
315 }
316
317 make_pkt_str_na()
318 {
319 local ip=$1
320 local mac=$2
321 local pkt=
322 pkt="$mac > 33:33:00:00:00:01, ethertype IPv6 (0x86dd), length 86:"
323 pkt="$pkt $ip > ff02::1: ICMP6, neighbor advertisement"
324 echo $pkt
325 }
326
327 extract_new_packets()
328 {
329 local old=./old
330
331 if [ ! -f $old ]; then
332 old=/dev/null
333 fi
334
335 shmif_dumpbus -p - bus1 2>/dev/null| \
336 tcpdump -n -e -r - 2>/dev/null > ./new
337 diff -u $old ./new |grep '^+' |cut -d '+' -f 2 > ./diff
338 mv -f ./new ./old
339 cat ./diff
340 }
341
342 ndp_link_activation_body()
343 {
344 local linklocal=
345
346 atf_check -s exit:0 ${inetserver} $SOCKSRC
347 atf_check -s exit:0 ${inetserver} $SOCKDST
348
349 setup_dst_server
350 setup_src_server
351
352 # flush old packets
353 extract_new_packets > ./out
354
355 export RUMP_SERVER=$SOCKSRC
356
357 atf_check -s exit:0 -o ignore rump.ifconfig shmif0 link \
358 b2:a1:00:00:00:01
359
360 atf_check -s exit:0 sleep 1
361 extract_new_packets > ./out
362 $DEBUG && cat ./out
363
364 linklocal=$(rump.ifconfig shmif0 |awk '/fe80/ {print $2;}' |awk -F % '{print $1;}')
365 $DEBUG && echo $linklocal
366
367 pkt=$(make_pkt_str_na $linklocal b2:a1:00:00:00:01)
368 atf_check -s not-exit:0 -x "cat ./out |grep -q '$pkt'"
369
370 atf_check -s exit:0 -o ignore rump.ifconfig shmif0 link \
371 b2:a1:00:00:00:02 active
372
373 atf_check -s exit:0 sleep 1
374 extract_new_packets > ./out
375 $DEBUG && cat ./out
376
377 linklocal=$(rump.ifconfig shmif0 |awk '/fe80/ {print $2;}' |awk -F % '{print $1;}')
378 $DEBUG && echo $linklocal
379
380 pkt=$(make_pkt_str_na $linklocal b2:a1:00:00:00:02)
381 atf_check -s exit:0 -x "cat ./out |grep -q '$pkt'"
382 }
383
384 cleanup()
385 {
386 env RUMP_SERVER=$SOCKSRC rump.halt
387 env RUMP_SERVER=$SOCKDST rump.halt
388 }
389
390 dump_src()
391 {
392 export RUMP_SERVER=$SOCKSRC
393 rump.netstat -nr
394 rump.ndp -n -a
395 rump.ifconfig
396 $HIJACKING dmesg
397 }
398
399 dump_dst()
400 {
401 export RUMP_SERVER=$SOCKDST
402 rump.netstat -nr
403 rump.ndp -n -a
404 rump.ifconfig
405 $HIJACKING dmesg
406 }
407
408 dump()
409 {
410 dump_src
411 dump_dst
412 shmif_dumpbus -p - bus1 2>/dev/null| tcpdump -n -e -r -
413 $DEBUG && gdb -ex bt /usr/bin/rump_server rump_server.core
414 $DEBUG && gdb -ex bt /usr/sbin/rump.ndp rump.ndp.core
415 }
416
417 ndp_cache_expiration_cleanup()
418 {
419 $DEBUG && dump
420 cleanup
421 }
422
423 ndp_commands_cleanup()
424 {
425 $DEBUG && dump
426 cleanup
427 }
428
429 ndp_cache_overwriting_cleanup()
430 {
431 $DEBUG && dump
432 cleanup
433 }
434
435 ndp_neighborgcthresh_cleanup()
436 {
437 $DEBUG && dump
438 cleanup
439 }
440
441 ndp_link_activation_cleanup()
442 {
443 $DEBUG && dump
444 cleanup
445 }
446
447 atf_init_test_cases()
448 {
449 atf_add_test_case ndp_cache_expiration
450 atf_add_test_case ndp_commands
451 atf_add_test_case ndp_cache_overwriting
452 atf_add_test_case ndp_neighborgcthresh
453 atf_add_test_case ndp_link_activation
454 }
455