t_ndp.sh revision 1.34 1 # $NetBSD: t_ndp.sh,v 1.34 2019/08/13 07:20:43 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 local macaddr=
118
119 rump_server_start $SOCKSRC netinet6
120 rump_server_start $SOCKDST netinet6
121
122 setup_dst_server
123 setup_src_server
124
125 # Shorten the expire time of cache entries
126 export RUMP_SERVER=$SOCKSRC
127 atf_check -s exit:0 -o match:'basereachable=7s0ms' \
128 rump.ndp -i shmif0 basereachable=7000
129
130 # Make a permanent cache entry to avoid sending an NS packet disturbing
131 # the test
132 macaddr=$(get_macaddr $SOCKSRC shmif0)
133 export RUMP_SERVER=$SOCKDST
134 atf_check -s exit:0 -o ignore rump.ndp -s $IP6SRC $macaddr
135
136 export RUMP_SERVER=$SOCKSRC
137
138 #
139 # Check if a cache is expired expectedly
140 #
141 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
142
143 $DEBUG && rump.ndp -n -a
144 atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6SRC
145 # Should be cached
146 atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n $IP6DST
147
148 timeout=$(get_timeout $IP6DST)
149
150 atf_check -s exit:0 sleep $(($timeout + 1))
151
152 $DEBUG && rump.ndp -n -a
153 atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6SRC
154 # Expired but remains until GC sweaps it (1 day)
155 atf_check -s exit:0 -o match:"$ONEDAYISH" rump.ndp -n $IP6DST
156
157 rump_server_destroy_ifaces
158 }
159
160 ifdown_dst_server()
161 {
162 export RUMP_SERVER=$SOCKDST
163 atf_check -s exit:0 rump.ifconfig shmif0 down
164 export RUMP_SERVER=$SOCKSRC
165 }
166
167 ndp_commands_body()
168 {
169
170 rump_server_start $SOCKSRC netinet6
171 rump_server_start $SOCKDST netinet6
172
173 setup_dst_server
174 setup_src_server
175
176 export RUMP_SERVER=$SOCKSRC
177
178 # Add and delete a static entry
179 $DEBUG && rump.ndp -n -a
180 atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10
181 $DEBUG && rump.ndp -n -a
182 atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::10
183 check_route fc00::10 'b2:a0:20:00:00:10' UHLS shmif0
184 atf_check -s exit:0 -o match:'deleted' rump.ndp -d fc00::10
185 $DEBUG && rump.ndp -n -a
186 atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n fc00::10
187 check_route_no_entry fc00::10
188
189 # Add multiple entries via a file (XXX not implemented)
190 #cat - > ./list <<-EOF
191 #fc00::11 b2:a0:20:00:00:11
192 #fc00::12 b2:a0:20:00:00:12
193 #fc00::13 b2:a0:20:00:00:13
194 #fc00::14 b2:a0:20:00:00:14
195 #fc00::15 b2:a0:20:00:00:15
196 #EOF
197 #$DEBUG && rump.ndp -n -a
198 #atf_check -s exit:0 -o ignore rump.ndp -f ./list
199 #$DEBUG && rump.ndp -n -a
200
201 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
202 atf_check -s exit:0 -o ignore rump.ndp -s fc00::11 b2:a0:20:00:00:11
203 atf_check -s exit:0 -o ignore rump.ndp -s fc00::12 b2:a0:20:00:00:12
204
205 atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n $IP6DST
206 atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::11
207 atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::12
208 check_route_flags $IP6DST UHL
209 check_route_flags fc00::11 UHLS
210 check_route_flags fc00::12 UHLS
211
212 # Test ndp -a
213 atf_check -s exit:0 -o match:'fc00::11' rump.ndp -n -a
214 atf_check -s exit:0 -o match:'fc00::12' rump.ndp -n -a
215
216 # Ensure no packet upsets the src server
217 ifdown_dst_server
218
219 # Flush all entries (-c)
220 $DEBUG && rump.ndp -n -a
221 atf_check -s exit:0 -o ignore rump.ndp -c
222 atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6SRC
223 atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6DST
224 #check_route_no_entry $IP6SRC
225 check_route_no_entry $IP6DST
226 # Only the static caches are not deleted
227 atf_check -s exit:0 -o ignore -e ignore rump.ndp -n fc00::11
228 atf_check -s exit:0 -o ignore -e ignore rump.ndp -n fc00::12
229 check_route_flags fc00::11 UHLS
230 check_route_flags fc00::12 UHLS
231
232 $DEBUG && rump.ndp -n -a
233 atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
234 rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
235 $DEBUG && rump.ndp -n -a
236 atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n fc00::10
237 check_route fc00::10 'b2:a0:20:00:00:10' UHL shmif0
238
239 rump_server_destroy_ifaces
240 }
241
242 ndp_cache_overwriting_body()
243 {
244
245 rump_server_start $SOCKSRC netinet6
246 rump_server_start $SOCKDST netinet6
247
248 setup_dst_server
249 setup_src_server
250
251 export RUMP_SERVER=$SOCKSRC
252
253 # Cannot overwrite a permanent cache
254 atf_check -s exit:0 rump.ndp -s $IP6SRC b2:a0:20:00:00:ff
255 $DEBUG && rump.ndp -n -a
256 atf_check -s not-exit:0 -e ignore rump.ndp -s $IP6SRC b2:a0:20:00:00:fe
257
258 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
259 $DEBUG && rump.ndp -n -a
260 # Can overwrite a dynamic cache
261 atf_check -s exit:0 -o ignore rump.ndp -s $IP6DST b2:a0:20:00:00:00
262 $DEBUG && rump.ndp -n -a
263 atf_check -s exit:0 -o match:'permanent' rump.ndp -n $IP6DST
264
265 # Test temp option (XXX it doesn't work; expire time isn't set)
266 #atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
267 #$DEBUG && rump.ndp -n -a
268 #atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n fc00::10
269 # Cannot overwrite a temp cache
270 #atf_check -s not-exit:0 -e ignore rump.ndp -s fc00::10 b2:a0:20:00:00:ff
271 #$DEBUG && rump.ndp -n -a
272
273 rump_server_destroy_ifaces
274 }
275
276 get_n_caches()
277 {
278
279 echo $(rump.ndp -a -n |grep -v -e Neighbor -e permanent |wc -l)
280 }
281
282 ndp_neighborgcthresh_body()
283 {
284
285 rump_server_start $SOCKSRC netinet6
286 rump_server_start $SOCKDST netinet6
287
288 setup_dst_server no
289 setup_src_server
290
291 export RUMP_SERVER=$SOCKDST
292 for i in $(seq 0 9); do
293 atf_check -s exit:0 rump.ifconfig shmif0 inet6 ${IP6DST}$i
294 done
295
296 export RUMP_SERVER=$SOCKSRC
297
298 # ping to 3 destinations
299 $DEBUG && rump.ndp -n -a
300 for i in $(seq 0 2); do
301 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
302 ${IP6DST}$i
303 done
304 $DEBUG && rump.ndp -n -a
305
306 # 3 caches should be created
307 atf_check_equal $(get_n_caches) 3
308
309 # ping to additional 3 destinations
310 for i in $(seq 3 5); do
311 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
312 ${IP6DST}$i
313 done
314 $DEBUG && rump.ndp -n -a
315
316 # 6 caches should be created in total
317 atf_check_equal $(get_n_caches) 6
318
319 # Limit the number of neighbor caches to 5
320 atf_check -s exit:0 -o ignore rump.sysctl -w \
321 net.inet6.ip6.neighborgcthresh=5
322
323 # ping to additional 4 destinations
324 for i in $(seq 6 9); do
325 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
326 ${IP6DST}$i
327 done
328
329 # More than 5 caches should be created in total, but exceeded caches
330 # should be GC-ed
331 if [ "$(get_n_caches)" -gt 5 ]; then
332 atf_fail "Neighbor caches are not GC-ed"
333 fi
334
335 rump_server_destroy_ifaces
336 }
337
338 make_pkt_str_na()
339 {
340 local ip=$1
341 local mac=$2
342 local pkt=
343 pkt="$mac > 33:33:00:00:00:01, ethertype IPv6 (0x86dd), length 86:"
344 pkt="$pkt $ip > ff02::1: ICMP6, neighbor advertisement"
345 echo $pkt
346 }
347
348 ndp_link_activation_body()
349 {
350 local linklocal=
351
352 rump_server_start $SOCKSRC netinet6
353 rump_server_start $SOCKDST netinet6
354
355 setup_dst_server
356 setup_src_server
357
358 # flush old packets
359 extract_new_packets bus1 > ./out
360
361 export RUMP_SERVER=$SOCKSRC
362
363 atf_check -s exit:0 -o ignore rump.ifconfig shmif0 link \
364 b2:a1:00:00:00:01
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:01)
374 atf_check -s not-exit:0 -x "cat ./out |grep -q '$pkt'"
375
376 atf_check -s exit:0 -o ignore rump.ifconfig shmif0 link \
377 b2:a1:00:00:00:02 active
378
379 atf_check -s exit:0 sleep 1
380 extract_new_packets bus1 > ./out
381 $DEBUG && cat ./out
382
383 linklocal=$(rump.ifconfig shmif0 |awk '/fe80/ {print $2;}' |awk -F % '{print $1;}')
384 $DEBUG && echo $linklocal
385
386 pkt=$(make_pkt_str_na $linklocal b2:a1:00:00:00:02)
387 atf_check -s exit:0 -x "cat ./out |grep -q '$pkt'"
388
389 rump_server_destroy_ifaces
390 }
391
392 ndp_cache_expiration_cleanup()
393 {
394 $DEBUG && dump
395 cleanup
396 }
397
398 ndp_commands_cleanup()
399 {
400 $DEBUG && dump
401 cleanup
402 }
403
404 ndp_cache_overwriting_cleanup()
405 {
406 $DEBUG && dump
407 cleanup
408 }
409
410 ndp_neighborgcthresh_cleanup()
411 {
412 $DEBUG && dump
413 cleanup
414 }
415
416 ndp_link_activation_cleanup()
417 {
418 $DEBUG && dump
419 cleanup
420 }
421
422 atf_test_case ndp_rtm cleanup
423 ndp_rtm_head()
424 {
425
426 atf_set "descr" "Tests for routing messages on operations of NDP entries"
427 atf_set "require.progs" "rump_server"
428 }
429
430 ndp_rtm_body()
431 {
432 local macaddr_src= macaddr_dst=
433 local file=./tmp
434 local pid= hdr= what= addr=
435
436 rump_server_start $SOCKSRC netinet6
437 rump_server_start $SOCKDST netinet6
438
439 setup_dst_server
440 setup_src_server
441
442 macaddr_src=$(get_macaddr $SOCKSRC shmif0)
443 macaddr_dst=$(get_macaddr $SOCKDST shmif0)
444
445 export RUMP_SERVER=$SOCKSRC
446
447 # Test ping and a resulting routing message (RTM_ADD)
448 rump.route -n monitor -c 1 > $file &
449 pid=$!
450 sleep 1
451 atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST
452 wait $pid
453 $DEBUG && cat $file
454
455 hdr="RTM_ADD.+<UP,HOST,DONE,LLINFO,CLONED>"
456 what="<DST,GATEWAY>"
457 addr="$IP6DST link#2"
458 atf_check -s exit:0 -o match:"$hdr" -o match:"$what" -o match:"$addr" \
459 cat $file
460
461 # Test ndp -d and resulting routing messages (RTM_DELETE)
462 rump.route -n monitor -c 1 > $file &
463 pid=$!
464 sleep 1
465 atf_check -s exit:0 -o ignore rump.ndp -d $IP6DST
466 wait $pid
467 $DEBUG && cat $file
468
469 hdr="RTM_DELETE.+<HOST,DONE,LLINFO,CLONED>"
470 what="<DST,GATEWAY>"
471 addr="$IP6DST $macaddr_dst"
472 atf_check -s exit:0 -o match:"$hdr" -o match:"$what" -o match:"$addr" \
473 grep -A 3 RTM_DELETE $file
474
475 rump_server_destroy_ifaces
476 }
477
478 ndp_rtm_cleanup()
479 {
480
481 $DEBUG && dump
482 cleanup
483 }
484
485 atf_test_case ndp_purge_on_route_change cleanup
486 ndp_purge_on_route_change_head()
487 {
488
489 atf_set "descr" "Tests if NDP entries are removed on route change"
490 atf_set "require.progs" "rump_server"
491 }
492
493 ndp_purge_on_route_change_body()
494 {
495
496 rump_server_start $SOCKSRC netinet6
497 rump_server_start $SOCKDST netinet6
498
499 setup_dst_server
500 setup_src_server
501
502 rump_server_add_iface $SOCKSRC shmif1 bus1
503 export RUMP_SERVER=$SOCKSRC
504 atf_check -s exit:0 rump.ifconfig shmif1 inet6 fc00:1::1
505 atf_check -s exit:0 rump.ifconfig -w 10
506
507 $DEBUG && rump.netstat -nr -f inet6
508 atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST
509 atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST
510
511 atf_check -s exit:0 -o ignore \
512 rump.route change -inet6 -net $IP6NET/64 -ifp shmif1
513 $DEBUG && rump.netstat -nr -f inet6
514 $DEBUG && rump.ndp -na
515 # The entry was already removed on route change
516 atf_check -s not-exit:0 -o ignore -e match:'no entry' \
517 rump.ndp -n $IP6DST
518
519 rump_server_destroy_ifaces
520 }
521
522 ndp_purge_on_route_change_cleanup()
523 {
524
525 $DEBUG && dump
526 cleanup
527 }
528
529 atf_test_case ndp_purge_on_route_delete cleanup
530 ndp_purge_on_route_delete_head()
531 {
532
533 atf_set "descr" "Tests if NDP entries are removed on route delete"
534 atf_set "require.progs" "rump_server"
535 }
536
537 ndp_purge_on_route_delete_body()
538 {
539
540 rump_server_start $SOCKSRC netinet6
541 rump_server_start $SOCKDST netinet6
542
543 setup_dst_server
544 setup_src_server
545
546 $DEBUG && rump.netstat -nr -f inet6
547 atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST
548 atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST
549
550 atf_check -s exit:0 -o ignore rump.route delete -inet6 -net $IP6NET/64
551 $DEBUG && rump.netstat -nr -f inet6
552 $DEBUG && rump.ndp -na
553
554 # The entry was already removed on route delete
555 atf_check -s not-exit:0 -o ignore -e match:'no entry' \
556 rump.ndp -n $IP6DST
557
558 rump_server_destroy_ifaces
559 }
560
561 ndp_purge_on_route_delete_cleanup()
562 {
563
564 $DEBUG && dump
565 cleanup
566 }
567
568 atf_test_case ndp_purge_on_ifdown cleanup
569 ndp_purge_on_ifdown_head()
570 {
571
572 atf_set "descr" "Tests if NDP entries are removed on interface down"
573 atf_set "require.progs" "rump_server"
574 }
575
576 ndp_purge_on_ifdown_body()
577 {
578
579 rump_server_start $SOCKSRC netinet6
580 rump_server_start $SOCKDST netinet6
581
582 setup_dst_server
583 setup_src_server
584
585 $DEBUG && rump.netstat -nr -f inet6
586 atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST
587 atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST
588
589 # Shutdown the interface
590 atf_check -s exit:0 rump.ifconfig shmif0 down
591 $DEBUG && rump.netstat -nr -f inet6
592 $DEBUG && rump.ndp -na
593
594 # The entry was already removed on ifconfig down
595 atf_check -s not-exit:0 -o ignore -e match:'no entry' \
596 rump.ndp -n $IP6DST
597
598 rump_server_destroy_ifaces
599 }
600
601 ndp_purge_on_ifdown_cleanup()
602 {
603
604 $DEBUG && dump
605 cleanup
606 }
607
608 atf_test_case ndp_stray_entries cleanup
609 ndp_stray_entries_head()
610 {
611
612 atf_set "descr" "Tests if NDP entries are removed on route change"
613 atf_set "require.progs" "rump_server"
614 }
615
616 ndp_stray_entries_body()
617 {
618
619 rump_server_start $SOCKSRC netinet6
620 rump_server_start $SOCKDST netinet6
621
622 setup_dst_server
623 setup_src_server
624
625 rump_server_add_iface $SOCKSRC shmif1 bus1
626
627 export RUMP_SERVER=$SOCKSRC
628 atf_check -s exit:0 rump.ifconfig shmif1 inet6 $IP6SRC2/64
629 atf_check -s exit:0 rump.ifconfig -w 10
630
631 $DEBUG && rump.netstat -nr -f inet6
632 atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST
633 $DEBUG && rump.ndp -na
634 atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST
635 atf_check -s exit:0 -o not-match:'shmif1' rump.ndp -n $IP6DST
636
637 # Clean up
638 atf_check -s exit:0 -o ignore rump.ndp -c
639 atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6DST
640
641 # ping from a different source address
642 atf_check -s exit:0 -o ignore \
643 rump.ping6 -n -X 1 -c 1 -S $IP6SRC2 $IP6DST
644 $DEBUG && rump.ndp -na
645 atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST
646 # ARP reply goes back via shmif1, so a cache is created on shmif1
647 atf_check -s exit:0 -o match:'shmif1' rump.ndp -n $IP6DST
648
649 # Clean up by ndp -c
650 atf_check -s exit:0 -o ignore rump.ndp -c
651 atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6DST
652
653 # ping from a different source address again
654 atf_check -s exit:0 -o ignore \
655 rump.ping6 -n -X 1 -c 1 -S $IP6SRC2 $IP6DST
656 atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST
657 # ARP reply doen't come
658 atf_check -s exit:0 -o not-match:'shmif1' rump.ndp -n $IP6DST
659
660 # Cleanup caches on the destination
661 export RUMP_SERVER=$SOCKDST
662 $DEBUG && rump.ndp -na
663 atf_check -s exit:0 -o ignore rump.ndp -c
664 $DEBUG && rump.ndp -na
665 export RUMP_SERVER=$SOCKSRC
666
667 # ping from a different source address again
668 atf_check -s exit:0 -o ignore \
669 rump.ping6 -n -X 1 -c 1 -S $IP6SRC2 $IP6DST
670 atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST
671 # ARP reply goes back via shmif1
672 atf_check -s exit:0 -o match:'shmif1' rump.ndp -n $IP6DST
673
674 # Clean up by ndp -d <ip>
675 atf_check -s exit:0 -o ignore rump.ndp -d $IP6DST
676 # Both entries should be deleted
677 atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6DST
678
679 rump_server_destroy_ifaces
680 }
681
682 ndp_stray_entries_cleanup()
683 {
684
685 $DEBUG && dump
686 cleanup
687 }
688
689 atf_test_case ndp_cache_state cleanup
690 ndp_stray_entries_head()
691 {
692
693 atf_set "descr" "Tests states of neighbor cache entries"
694 atf_set "require.progs" "rump_server"
695 }
696
697 check_cache_state()
698 {
699 local dst=$1
700 local state=$2
701
702 $DEBUG && rump.ndp -n $dst
703 atf_check -s exit:0 -o match:"^$dst.*$state " rump.ndp -n $dst
704 }
705
706 wait_until_stalled()
707 {
708 local dst=$1
709 local state=$2
710
711 $DEBUG && rump.ndp -n $dst
712 while true; do
713 rump.ndp -n $dst | grep -q "^$dst.*S " && break
714 sleep 1
715 done
716 $DEBUG && rump.ndp -n $dst
717 }
718
719 ndp_cache_state_body()
720 {
721 local macaddr=
722
723 rump_server_start $SOCKSRC netinet6
724 rump_server_start $SOCKDST netinet6
725
726 setup_dst_server
727 setup_src_server
728
729 # Shorten the expire time of cache entries
730 export RUMP_SERVER=$SOCKSRC
731 atf_check -s exit:0 -o match:'basereachable=7s0ms' \
732 rump.ndp -i shmif0 basereachable=7000
733
734 # Make a permanent cache entry to avoid sending an NS packet disturbing
735 # the test
736 macaddr=$(get_macaddr $SOCKSRC shmif0)
737 export RUMP_SERVER=$SOCKDST
738 atf_check -s exit:0 -o ignore rump.ndp -s $IP6SRC $macaddr
739
740 export RUMP_SERVER=$SOCKSRC
741
742 #
743 # Reachability confirmation (RFC 4861 7.3.3)
744 #
745 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
746
747 # Receiving a solicited NA packet changes the state of the cache to REACHABLE
748 check_cache_state $IP6DST R
749
750 # The state of the cache transits to STALE after a while
751 wait_until_stalled $IP6DST
752
753 # Sending a packet on the cache will run a reachability confirmation
754 atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
755
756 sleep 1
757
758 # The state of the cache is changed to DELAY and stay for 5s, then
759 # send a NS packet and change the state to PROBE
760 check_cache_state $IP6DST D
761
762 sleep $((5 + 1))
763
764 # If the reachability confirmation is success, the state of the cache
765 # is changed to REACHABLE
766 check_cache_state $IP6DST R
767 }
768
769 ndp_cache_state_cleanup()
770 {
771
772 $DEBUG && dump
773 cleanup
774 }
775
776 atf_init_test_cases()
777 {
778 atf_add_test_case ndp_cache_expiration
779 atf_add_test_case ndp_commands
780 atf_add_test_case ndp_cache_overwriting
781 atf_add_test_case ndp_neighborgcthresh
782 atf_add_test_case ndp_link_activation
783 atf_add_test_case ndp_rtm
784 atf_add_test_case ndp_purge_on_route_change
785 atf_add_test_case ndp_purge_on_route_delete
786 atf_add_test_case ndp_purge_on_ifdown
787 atf_add_test_case ndp_stray_entries
788 atf_add_test_case ndp_cache_state
789 }
790