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