t_ndp.sh revision 1.28 1 # $NetBSD: t_ndp.sh,v 1.28 2017/06/28 04:14:53 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 SOCKSRC=unix://commsock1
29 SOCKDST=unix://commsock2
30 IP6SRC=fc00::1
31 IP6SRC2=fc00::3
32 IP6DST=fc00::2
33 IP6NET=fc00::0
34
35 DEBUG=${DEBUG:-false}
36 TIMEOUT=1
37
38 atf_test_case ndp_cache_expiration cleanup
39 atf_test_case ndp_commands cleanup
40 atf_test_case ndp_cache_overwriting cleanup
41 atf_test_case ndp_neighborgcthresh cleanup
42 atf_test_case ndp_link_activation cleanup
43
44 ndp_cache_expiration_head()
45 {
46 atf_set "descr" "Tests for NDP cache expiration"
47 atf_set "require.progs" "rump_server"
48 }
49
50 ndp_commands_head()
51 {
52 atf_set "descr" "Tests for commands of ndp(8)"
53 atf_set "require.progs" "rump_server"
54 }
55
56 ndp_cache_overwriting_head()
57 {
58 atf_set "descr" "Tests for behavior of overwriting NDP caches"
59 atf_set "require.progs" "rump_server"
60 }
61
62 ndp_neighborgcthresh_head()
63 {
64 atf_set "descr" "Tests for GC of neighbor caches"
65 atf_set "require.progs" "rump_server"
66 }
67
68 ndp_link_activation_head()
69 {
70 atf_set "descr" "Tests for activating a new MAC address"
71 atf_set "require.progs" "rump_server"
72 }
73
74 setup_dst_server()
75 {
76 local assign_ip=$1
77
78 rump_server_add_iface $SOCKDST shmif0 bus1
79 export RUMP_SERVER=$SOCKDST
80 if [ "$assign_ip" != no ]; then
81 atf_check -s exit:0 rump.ifconfig shmif0 inet6 $IP6DST
82 fi
83 atf_check -s exit:0 rump.ifconfig shmif0 up
84 atf_check -s exit:0 rump.ifconfig -w 10
85
86 $DEBUG && rump.ifconfig shmif0
87 $DEBUG && rump.ndp -n -a
88 }
89
90 setup_src_server()
91 {
92 $DEBUG && ulimit -c unlimited
93 export RUMP_SERVER=$SOCKSRC
94
95 # Setup an interface
96 rump_server_add_iface $SOCKSRC shmif0 bus1
97 atf_check -s exit:0 rump.ifconfig shmif0 inet6 $IP6SRC
98 atf_check -s exit:0 rump.ifconfig shmif0 up
99 atf_check -s exit:0 rump.ifconfig -w 10
100
101 # Sanity check
102 $DEBUG && rump.ifconfig shmif0
103 $DEBUG && rump.ndp -n -a
104 atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6SRC
105 atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6DST
106 }
107
108 get_timeout()
109 {
110 local timeout=$(env RUMP_SERVER=$SOCKSRC rump.ndp -n $IP6DST |grep $IP6DST|awk '{print $4;}')
111 timeout=${timeout%s}
112 echo $timeout
113 }
114
115 ndp_cache_expiration_body()
116 {
117
118 rump_server_start $SOCKSRC netinet6
119 rump_server_start $SOCKDST netinet6
120
121 setup_dst_server
122 setup_src_server
123
124 #
125 # Check if a cache is expired expectedly
126 #
127 export RUMP_SERVER=$SOCKSRC
128 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
129
130 $DEBUG && rump.ndp -n -a
131 atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6SRC
132 # Should be cached
133 atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n $IP6DST
134
135 timeout=$(get_timeout $IP6DST)
136
137 atf_check -s exit:0 sleep $(($timeout + 1))
138
139 $DEBUG && rump.ndp -n -a
140 atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6SRC
141 # Expired but remains until GC sweaps it (1 day)
142 atf_check -s exit:0 -o match:"$ONEDAYISH" rump.ndp -n $IP6DST
143
144 rump_server_destroy_ifaces
145 }
146
147 ifdown_dst_server()
148 {
149 export RUMP_SERVER=$SOCKDST
150 atf_check -s exit:0 rump.ifconfig shmif0 down
151 export RUMP_SERVER=$SOCKSRC
152 }
153
154 ndp_commands_body()
155 {
156
157 rump_server_start $SOCKSRC netinet6
158 rump_server_start $SOCKDST netinet6
159
160 setup_dst_server
161 setup_src_server
162
163 export RUMP_SERVER=$SOCKSRC
164
165 # Add and delete a static entry
166 $DEBUG && rump.ndp -n -a
167 atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10
168 $DEBUG && rump.ndp -n -a
169 atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::10
170 check_route fc00::10 'b2:a0:20:00:00:10' UHLS shmif0
171 atf_check -s exit:0 -o match:'deleted' rump.ndp -d fc00::10
172 $DEBUG && rump.ndp -n -a
173 atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n fc00::10
174 check_route_no_entry fc00::10
175
176 # Add multiple entries via a file (XXX not implemented)
177 #cat - > ./list <<-EOF
178 #fc00::11 b2:a0:20:00:00:11
179 #fc00::12 b2:a0:20:00:00:12
180 #fc00::13 b2:a0:20:00:00:13
181 #fc00::14 b2:a0:20:00:00:14
182 #fc00::15 b2:a0:20:00:00:15
183 #EOF
184 #$DEBUG && rump.ndp -n -a
185 #atf_check -s exit:0 -o ignore rump.ndp -f ./list
186 #$DEBUG && rump.ndp -n -a
187
188 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
189 atf_check -s exit:0 -o ignore rump.ndp -s fc00::11 b2:a0:20:00:00:11
190 atf_check -s exit:0 -o ignore rump.ndp -s fc00::12 b2:a0:20:00:00:12
191
192 atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n $IP6DST
193 atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::11
194 atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::12
195 check_route_flags $IP6DST UHL
196 check_route_flags fc00::11 UHLS
197 check_route_flags fc00::12 UHLS
198
199 # Test ndp -a
200 atf_check -s exit:0 -o match:'fc00::11' rump.ndp -n -a
201 atf_check -s exit:0 -o match:'fc00::12' rump.ndp -n -a
202
203 # Ensure no packet upsets the src server
204 ifdown_dst_server
205
206 # Flush all entries (-c)
207 $DEBUG && rump.ndp -n -a
208 atf_check -s exit:0 -o ignore rump.ndp -c
209 atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6SRC
210 atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6DST
211 #check_route_no_entry $IP6SRC
212 check_route_no_entry $IP6DST
213 # Only the static caches are not deleted
214 atf_check -s exit:0 -o ignore -e ignore rump.ndp -n fc00::11
215 atf_check -s exit:0 -o ignore -e ignore rump.ndp -n fc00::12
216 check_route_flags fc00::11 UHLS
217 check_route_flags fc00::12 UHLS
218
219 $DEBUG && rump.ndp -n -a
220 atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
221 rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
222 $DEBUG && rump.ndp -n -a
223 atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n fc00::10
224 check_route fc00::10 'b2:a0:20:00:00:10' UHL shmif0
225
226 rump_server_destroy_ifaces
227 }
228
229 ndp_cache_overwriting_body()
230 {
231
232 rump_server_start $SOCKSRC netinet6
233 rump_server_start $SOCKDST netinet6
234
235 setup_dst_server
236 setup_src_server
237
238 export RUMP_SERVER=$SOCKSRC
239
240 # Cannot overwrite a permanent cache
241 atf_check -s exit:0 rump.ndp -s $IP6SRC b2:a0:20:00:00:ff
242 $DEBUG && rump.ndp -n -a
243 atf_check -s not-exit:0 -e ignore rump.ndp -s $IP6SRC b2:a0:20:00:00:fe
244
245 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
246 $DEBUG && rump.ndp -n -a
247 # Can overwrite a dynamic cache
248 atf_check -s exit:0 -o ignore rump.ndp -s $IP6DST b2:a0:20:00:00:00
249 $DEBUG && rump.ndp -n -a
250 atf_check -s exit:0 -o match:'permanent' rump.ndp -n $IP6DST
251
252 # Test temp option (XXX it doesn't work; expire time isn't set)
253 #atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
254 #$DEBUG && rump.ndp -n -a
255 #atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n fc00::10
256 # Cannot overwrite a temp cache
257 #atf_check -s not-exit:0 -e ignore rump.ndp -s fc00::10 b2:a0:20:00:00:ff
258 #$DEBUG && rump.ndp -n -a
259
260 rump_server_destroy_ifaces
261 }
262
263 get_n_caches()
264 {
265
266 echo $(rump.ndp -a -n |grep -v -e Neighbor -e permanent |wc -l)
267 }
268
269 ndp_neighborgcthresh_body()
270 {
271
272 rump_server_start $SOCKSRC netinet6
273 rump_server_start $SOCKDST netinet6
274
275 setup_dst_server no
276 setup_src_server
277
278 export RUMP_SERVER=$SOCKDST
279 for i in $(seq 0 9); do
280 atf_check -s exit:0 rump.ifconfig shmif0 inet6 ${IP6DST}$i
281 done
282
283 export RUMP_SERVER=$SOCKSRC
284
285 # ping to 3 destinations
286 $DEBUG && rump.ndp -n -a
287 for i in $(seq 0 2); do
288 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
289 ${IP6DST}$i
290 done
291 $DEBUG && rump.ndp -n -a
292
293 # 3 caches should be created
294 atf_check_equal $(get_n_caches) 3
295
296 # ping to additional 3 destinations
297 for i in $(seq 3 5); do
298 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
299 ${IP6DST}$i
300 done
301 $DEBUG && rump.ndp -n -a
302
303 # 6 caches should be created in total
304 atf_check_equal $(get_n_caches) 6
305
306 # Limit the number of neighbor caches to 5
307 atf_check -s exit:0 -o ignore rump.sysctl -w \
308 net.inet6.ip6.neighborgcthresh=5
309
310 # ping to additional 4 destinations
311 for i in $(seq 6 9); do
312 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
313 ${IP6DST}$i
314 done
315
316 # More than 5 caches should be created in total, but exceeded caches
317 # should be GC-ed
318 if [ "$(get_n_caches)" -gt 5 ]; then
319 atf_fail "Neighbor caches are not GC-ed"
320 fi
321
322 rump_server_destroy_ifaces
323 }
324
325 make_pkt_str_na()
326 {
327 local ip=$1
328 local mac=$2
329 local pkt=
330 pkt="$mac > 33:33:00:00:00:01, ethertype IPv6 (0x86dd), length 86:"
331 pkt="$pkt $ip > ff02::1: ICMP6, neighbor advertisement"
332 echo $pkt
333 }
334
335 ndp_link_activation_body()
336 {
337 local linklocal=
338
339 rump_server_start $SOCKSRC netinet6
340 rump_server_start $SOCKDST netinet6
341
342 setup_dst_server
343 setup_src_server
344
345 # flush old packets
346 extract_new_packets bus1 > ./out
347
348 export RUMP_SERVER=$SOCKSRC
349
350 atf_check -s exit:0 -o ignore rump.ifconfig shmif0 link \
351 b2:a1:00:00:00:01
352
353 atf_check -s exit:0 sleep 1
354 extract_new_packets bus1 > ./out
355 $DEBUG && cat ./out
356
357 linklocal=$(rump.ifconfig shmif0 |awk '/fe80/ {print $2;}' |awk -F % '{print $1;}')
358 $DEBUG && echo $linklocal
359
360 pkt=$(make_pkt_str_na $linklocal b2:a1:00:00:00:01)
361 atf_check -s not-exit:0 -x "cat ./out |grep -q '$pkt'"
362
363 atf_check -s exit:0 -o ignore rump.ifconfig shmif0 link \
364 b2:a1:00:00:00:02 active
365
366 atf_check -s exit:0 sleep 1
367 extract_new_packets bus1 > ./out
368 $DEBUG && cat ./out
369
370 linklocal=$(rump.ifconfig shmif0 |awk '/fe80/ {print $2;}' |awk -F % '{print $1;}')
371 $DEBUG && echo $linklocal
372
373 pkt=$(make_pkt_str_na $linklocal b2:a1:00:00:00:02)
374 atf_check -s exit:0 -x "cat ./out |grep -q '$pkt'"
375
376 rump_server_destroy_ifaces
377 }
378
379 ndp_cache_expiration_cleanup()
380 {
381 $DEBUG && dump
382 cleanup
383 }
384
385 ndp_commands_cleanup()
386 {
387 $DEBUG && dump
388 cleanup
389 }
390
391 ndp_cache_overwriting_cleanup()
392 {
393 $DEBUG && dump
394 cleanup
395 }
396
397 ndp_neighborgcthresh_cleanup()
398 {
399 $DEBUG && dump
400 cleanup
401 }
402
403 ndp_link_activation_cleanup()
404 {
405 $DEBUG && dump
406 cleanup
407 }
408
409 atf_test_case ndp_rtm cleanup
410 ndp_rtm_head()
411 {
412
413 atf_set "descr" "Tests for routing messages on operations of NDP entries"
414 atf_set "require.progs" "rump_server"
415 }
416
417 ndp_rtm_body()
418 {
419 local macaddr_src= macaddr_dst=
420 local file=./tmp
421 local pid= str=
422
423 rump_server_start $SOCKSRC netinet6
424 rump_server_start $SOCKDST netinet6
425
426 setup_dst_server
427 setup_src_server
428
429 macaddr_src=$(get_macaddr $SOCKSRC shmif0)
430 macaddr_dst=$(get_macaddr $SOCKDST shmif0)
431
432 export RUMP_SERVER=$SOCKSRC
433
434 # Test ping and a resulting routing message (RTM_ADD)
435 rump.route -n monitor -c 1 > $file &
436 pid=$?
437 sleep 1
438 atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST
439 wait $pid
440 $DEBUG && cat $file
441
442 str="RTM_ADD.+<UP,HOST,DONE,LLINFO,CLONED>"
443 atf_check -s exit:0 -o match:"$str" cat $file
444 str="<DST,GATEWAY>"
445 atf_check -s exit:0 -o match:"$str" cat $file
446 str="$IP6DST link#2"
447 atf_check -s exit:0 -o match:"$str" cat $file
448
449 # Test ndp -d and resulting routing messages (RTM_GET and RTM_DELETE)
450 rump.route -n monitor -c 2 > $file &
451 pid=$?
452 sleep 1
453 atf_check -s exit:0 -o ignore rump.ndp -d $IP6DST
454 wait $pid
455 $DEBUG && cat $file
456
457 str="RTM_GET.+<UP,DONE,LLINFO>"
458 atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_GET $file
459 str="<DST,GATEWAY>"
460 atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_GET $file
461 str="$IP6DST $macaddr_dst"
462 atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_GET $file
463 str="RTM_DELETE.+<DONE,LLINFO>"
464 atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_DELETE $file
465 str="<DST,GATEWAY>"
466 atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_DELETE $file
467 str="$IP6DST $macaddr_dst"
468 atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_DELETE $file
469
470 rump_server_destroy_ifaces
471 }
472
473 ndp_rtm_cleanup()
474 {
475
476 $DEBUG && dump
477 cleanup
478 }
479
480 atf_test_case ndp_purge_on_route_change cleanup
481 ndp_purge_on_route_change_head()
482 {
483
484 atf_set "descr" "Tests if NDP entries are removed on route change"
485 atf_set "require.progs" "rump_server"
486 }
487
488 ndp_purge_on_route_change_body()
489 {
490
491 rump_server_start $SOCKSRC netinet6
492 rump_server_start $SOCKDST netinet6
493
494 setup_dst_server
495 setup_src_server
496
497 rump_server_add_iface $SOCKSRC shmif1 bus1
498 export RUMP_SERVER=$SOCKSRC
499 atf_check -s exit:0 rump.ifconfig shmif1 inet6 $IP6SRC2
500 atf_check -s exit:0 rump.ifconfig -w 10
501
502 $DEBUG && rump.netstat -nr -f inet6
503 atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST
504 atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST
505
506 atf_check -s exit:0 -o ignore \
507 rump.route change -inet6 -net $IP6NET/64 -ifp shmif1
508 $DEBUG && rump.netstat -nr -f inet6
509 $DEBUG && rump.ndp -na
510 # The entry was already removed on route change
511 atf_check -s not-exit:0 -o ignore -e match:'no entry' \
512 rump.ndp -n $IP6DST
513
514 rump_server_destroy_ifaces
515 }
516
517 ndp_purge_on_route_change_cleanup()
518 {
519
520 $DEBUG && dump
521 cleanup
522 }
523
524 atf_test_case ndp_purge_on_route_delete cleanup
525 ndp_purge_on_route_delete_head()
526 {
527
528 atf_set "descr" "Tests if NDP entries are removed on route delete"
529 atf_set "require.progs" "rump_server"
530 }
531
532 ndp_purge_on_route_delete_body()
533 {
534
535 rump_server_start $SOCKSRC netinet6
536 rump_server_start $SOCKDST netinet6
537
538 setup_dst_server
539 setup_src_server
540
541 $DEBUG && rump.netstat -nr -f inet6
542 atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST
543 atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST
544
545 atf_check -s exit:0 -o ignore rump.route delete -inet6 -net $IP6NET/64
546 $DEBUG && rump.netstat -nr -f inet6
547 $DEBUG && rump.ndp -na
548
549 # The entry was already removed on route delete
550 atf_check -s not-exit:0 -o ignore -e match:'no entry' \
551 rump.ndp -n $IP6DST
552
553 rump_server_destroy_ifaces
554 }
555
556 ndp_purge_on_route_delete_cleanup()
557 {
558
559 $DEBUG && dump
560 cleanup
561 }
562
563 atf_test_case ndp_purge_on_ifdown cleanup
564 ndp_purge_on_ifdown_head()
565 {
566
567 atf_set "descr" "Tests if NDP entries are removed on interface down"
568 atf_set "require.progs" "rump_server"
569 }
570
571 ndp_purge_on_ifdown_body()
572 {
573
574 rump_server_start $SOCKSRC netinet6
575 rump_server_start $SOCKDST netinet6
576
577 setup_dst_server
578 setup_src_server
579
580 $DEBUG && rump.netstat -nr -f inet6
581 atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST
582 atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST
583
584 # Shutdown the interface
585 atf_check -s exit:0 rump.ifconfig shmif0 down
586 $DEBUG && rump.netstat -nr -f inet6
587 $DEBUG && rump.ndp -na
588
589 # The entry was already removed on ifconfig down
590 atf_check -s not-exit:0 -o ignore -e match:'no entry' \
591 rump.ndp -n $IP6DST
592
593 rump_server_destroy_ifaces
594 }
595
596 ndp_purge_on_ifdown_cleanup()
597 {
598
599 $DEBUG && dump
600 cleanup
601 }
602
603 atf_init_test_cases()
604 {
605 atf_add_test_case ndp_cache_expiration
606 atf_add_test_case ndp_commands
607 atf_add_test_case ndp_cache_overwriting
608 atf_add_test_case ndp_neighborgcthresh
609 atf_add_test_case ndp_link_activation
610 atf_add_test_case ndp_rtm
611 atf_add_test_case ndp_purge_on_route_change
612 atf_add_test_case ndp_purge_on_route_delete
613 atf_add_test_case ndp_purge_on_ifdown
614 }
615