1313680Sngie#	$NetBSD: t_ndp.sh,v 1.17 2016/11/25 08:51:17 ozaki-r Exp $
2303980Sngie#
3303980Sngie# Copyright (c) 2015 The NetBSD Foundation, Inc.
4303980Sngie# All rights reserved.
5303980Sngie#
6303980Sngie# Redistribution and use in source and binary forms, with or without
7303980Sngie# modification, are permitted provided that the following conditions
8303980Sngie# are met:
9303980Sngie# 1. Redistributions of source code must retain the above copyright
10303980Sngie#    notice, this list of conditions and the following disclaimer.
11303980Sngie# 2. Redistributions in binary form must reproduce the above copyright
12303980Sngie#    notice, this list of conditions and the following disclaimer in the
13303980Sngie#    documentation and/or other materials provided with the distribution.
14303980Sngie#
15303980Sngie# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16303980Sngie# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17303980Sngie# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18303980Sngie# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19303980Sngie# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20303980Sngie# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21303980Sngie# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22303980Sngie# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23303980Sngie# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24303980Sngie# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25303980Sngie# POSSIBILITY OF SUCH DAMAGE.
26303980Sngie#
27303980Sngie
28303980SngieSOCKSRC=unix://commsock1
29303980SngieSOCKDST=unix://commsock2
30303980SngieIP6SRC=fc00::1
31303980SngieIP6DST=fc00::2
32303980Sngie
33313680SngieDEBUG=${DEBUG:-true}
34303980SngieTIMEOUT=1
35303980Sngie
36303980Sngieatf_test_case ndp_cache_expiration cleanup
37303980Sngieatf_test_case ndp_commands cleanup
38303980Sngieatf_test_case ndp_cache_overwriting cleanup
39303980Sngieatf_test_case ndp_neighborgcthresh cleanup
40303980Sngieatf_test_case ndp_link_activation cleanup
41303980Sngie
42303980Sngiendp_cache_expiration_head()
43303980Sngie{
44303980Sngie	atf_set "descr" "Tests for NDP cache expiration"
45303980Sngie	atf_set "require.progs" "rump_server"
46303980Sngie}
47303980Sngie
48303980Sngiendp_commands_head()
49303980Sngie{
50303980Sngie	atf_set "descr" "Tests for commands of ndp(8)"
51303980Sngie	atf_set "require.progs" "rump_server"
52303980Sngie}
53303980Sngie
54303980Sngiendp_cache_overwriting_head()
55303980Sngie{
56303980Sngie	atf_set "descr" "Tests for behavior of overwriting NDP caches"
57303980Sngie	atf_set "require.progs" "rump_server"
58303980Sngie}
59303980Sngie
60303980Sngiendp_neighborgcthresh_head()
61303980Sngie{
62303980Sngie	atf_set "descr" "Tests for GC of neighbor caches"
63303980Sngie	atf_set "require.progs" "rump_server"
64303980Sngie}
65303980Sngie
66303980Sngiendp_link_activation_head()
67303980Sngie{
68303980Sngie	atf_set "descr" "Tests for activating a new MAC address"
69303980Sngie	atf_set "require.progs" "rump_server"
70303980Sngie}
71303980Sngie
72303980Sngiesetup_dst_server()
73303980Sngie{
74303980Sngie	local assign_ip=$1
75303980Sngie
76313680Sngie	rump_server_add_iface $SOCKDST shmif0 bus1
77303980Sngie	export RUMP_SERVER=$SOCKDST
78303980Sngie	if [ "$assign_ip" != no ]; then
79303980Sngie		atf_check -s exit:0 rump.ifconfig shmif0 inet6 $IP6DST
80303980Sngie	fi
81303980Sngie	atf_check -s exit:0 rump.ifconfig shmif0 up
82303980Sngie	atf_check -s exit:0 rump.ifconfig -w 10
83303980Sngie
84303980Sngie	$DEBUG && rump.ifconfig shmif0
85303980Sngie	$DEBUG && rump.ndp -n -a
86303980Sngie}
87303980Sngie
88303980Sngiesetup_src_server()
89303980Sngie{
90303980Sngie	$DEBUG && ulimit -c unlimited
91303980Sngie	export RUMP_SERVER=$SOCKSRC
92303980Sngie
93303980Sngie	# Setup an interface
94313680Sngie	rump_server_add_iface $SOCKSRC shmif0 bus1
95303980Sngie	atf_check -s exit:0 rump.ifconfig shmif0 inet6 $IP6SRC
96303980Sngie	atf_check -s exit:0 rump.ifconfig shmif0 up
97303980Sngie	atf_check -s exit:0 rump.ifconfig -w 10
98303980Sngie
99303980Sngie	# Sanity check
100303980Sngie	$DEBUG && rump.ifconfig shmif0
101303980Sngie	$DEBUG && rump.ndp -n -a
102303980Sngie	atf_check -s exit:0 -o ignore rump.ndp -n $IP6SRC
103303980Sngie	atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6DST
104303980Sngie}
105303980Sngie
106303980Sngieget_timeout()
107303980Sngie{
108303980Sngie	local timeout=$(env RUMP_SERVER=$SOCKSRC rump.ndp -n $IP6DST |grep $IP6DST|awk '{print $4;}')
109303980Sngie	timeout=${timeout%s}
110303980Sngie	echo $timeout
111303980Sngie}
112303980Sngie
113303980Sngiendp_cache_expiration_body()
114303980Sngie{
115303980Sngie
116313680Sngie	rump_server_start $SOCKSRC netinet6
117313680Sngie	rump_server_start $SOCKDST netinet6
118313680Sngie
119303980Sngie	setup_dst_server
120303980Sngie	setup_src_server
121303980Sngie
122303980Sngie	#
123303980Sngie	# Check if a cache is expired expectedly
124303980Sngie	#
125303980Sngie	export RUMP_SERVER=$SOCKSRC
126303980Sngie	atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
127303980Sngie
128303980Sngie	$DEBUG && rump.ndp -n -a
129303980Sngie	atf_check -s exit:0 -o match:'permanent' rump.ndp -n $IP6SRC
130303980Sngie	# Should be cached
131303980Sngie	atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n $IP6DST
132303980Sngie
133303980Sngie	timeout=$(get_timeout $IP6DST)
134303980Sngie
135303980Sngie	atf_check -s exit:0 sleep $(($timeout + 1))
136303980Sngie
137303980Sngie	$DEBUG && rump.ndp -n -a
138303980Sngie	atf_check -s exit:0 -o match:'permanent' rump.ndp -n $IP6SRC
139303980Sngie	# Expired but remains until GC sweaps it (1 day)
140303980Sngie	atf_check -s exit:0 -o match:'(1d0h0m|23h59m)' rump.ndp -n $IP6DST
141313680Sngie
142313680Sngie	rump_server_destroy_ifaces
143303980Sngie}
144303980Sngie
145303980Sngieifdown_dst_server()
146303980Sngie{
147303980Sngie	export RUMP_SERVER=$SOCKDST
148303980Sngie	atf_check -s exit:0 rump.ifconfig shmif0 down
149303980Sngie	export RUMP_SERVER=$SOCKSRC
150303980Sngie}
151303980Sngie
152303980Sngiendp_commands_body()
153303980Sngie{
154303980Sngie
155313680Sngie	rump_server_start $SOCKSRC netinet6
156313680Sngie	rump_server_start $SOCKDST netinet6
157313680Sngie
158303980Sngie	setup_dst_server
159303980Sngie	setup_src_server
160303980Sngie
161303980Sngie	export RUMP_SERVER=$SOCKSRC
162303980Sngie
163303980Sngie	# We can delete the entry for the interface's IP address
164303980Sngie	atf_check -s exit:0 -o match:"$IP6SRC" rump.ndp -d $IP6SRC
165303980Sngie
166303980Sngie	# Add and delete a static entry
167303980Sngie	$DEBUG && rump.ndp -n -a
168303980Sngie	atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10
169303980Sngie	$DEBUG && rump.ndp -n -a
170303980Sngie	atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::10
171303980Sngie	atf_check -s exit:0 -o match:'deleted' rump.ndp -d fc00::10
172303980Sngie	$DEBUG && rump.ndp -n -a
173303980Sngie	atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n fc00::10
174303980Sngie
175303980Sngie	# Add multiple entries via a file (XXX not implemented)
176303980Sngie	#cat - > ./list <<-EOF
177303980Sngie	#fc00::11 b2:a0:20:00:00:11
178303980Sngie	#fc00::12 b2:a0:20:00:00:12
179303980Sngie	#fc00::13 b2:a0:20:00:00:13
180303980Sngie	#fc00::14 b2:a0:20:00:00:14
181303980Sngie	#fc00::15 b2:a0:20:00:00:15
182303980Sngie	#EOF
183303980Sngie	#$DEBUG && rump.ndp -n -a
184303980Sngie	#atf_check -s exit:0 -o ignore rump.ndp -f ./list
185303980Sngie	#$DEBUG && rump.ndp -n -a
186303980Sngie
187303980Sngie	atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
188303980Sngie	atf_check -s exit:0 -o ignore rump.ndp -s fc00::11 b2:a0:20:00:00:11
189303980Sngie	atf_check -s exit:0 -o ignore rump.ndp -s fc00::12 b2:a0:20:00:00:12
190303980Sngie
191303980Sngie	atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n $IP6DST
192303980Sngie	atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::11
193303980Sngie	atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::12
194303980Sngie
195303980Sngie	# Test ndp -a
196303980Sngie	atf_check -s exit:0 -o match:'fc00::11' rump.ndp -n -a
197303980Sngie	atf_check -s exit:0 -o match:'fc00::12' rump.ndp -n -a
198303980Sngie
199303980Sngie	# Ensure no packet upsets the src server
200303980Sngie	ifdown_dst_server
201303980Sngie
202303980Sngie	# Flush all entries (-c)
203303980Sngie	$DEBUG && rump.ndp -n -a
204303980Sngie	atf_check -s exit:0 -o ignore rump.ndp -c
205303980Sngie	atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6SRC
206303980Sngie	atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6DST
207303980Sngie	# Only the static caches are not deleted
208303980Sngie	atf_check -s exit:0 -o ignore -e ignore rump.ndp -n fc00::11
209303980Sngie	atf_check -s exit:0 -o ignore -e ignore rump.ndp -n fc00::12
210303980Sngie
211303980Sngie	$DEBUG && rump.ndp -n -a
212303980Sngie	atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
213303980Sngie	rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
214303980Sngie	$DEBUG && rump.ndp -n -a
215303980Sngie	atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n fc00::10
216303980Sngie
217313680Sngie	rump_server_destroy_ifaces
218303980Sngie}
219303980Sngie
220303980Sngiendp_cache_overwriting_body()
221303980Sngie{
222303980Sngie
223313680Sngie	rump_server_start $SOCKSRC netinet6
224313680Sngie	rump_server_start $SOCKDST netinet6
225313680Sngie
226303980Sngie	setup_dst_server
227303980Sngie	setup_src_server
228303980Sngie
229303980Sngie	export RUMP_SERVER=$SOCKSRC
230303980Sngie
231303980Sngie	# Cannot overwrite a permanent cache
232303980Sngie	atf_check -s not-exit:0 -e ignore rump.ndp -s $IP6SRC b2:a0:20:00:00:ff
233303980Sngie	$DEBUG && rump.ndp -n -a
234303980Sngie
235303980Sngie	atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST
236303980Sngie	$DEBUG && rump.ndp -n -a
237303980Sngie	# Can overwrite a dynamic cache
238303980Sngie	atf_check -s exit:0 -o ignore rump.ndp -s $IP6DST b2:a0:20:00:00:00
239303980Sngie	$DEBUG && rump.ndp -n -a
240303980Sngie	atf_check -s exit:0 -o match:'permanent' rump.ndp -n $IP6DST
241303980Sngie
242303980Sngie	# Test temp option (XXX it doesn't work; expire time isn't set)
243303980Sngie	#atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp
244303980Sngie	#$DEBUG && rump.ndp -n -a
245303980Sngie	#atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n fc00::10
246303980Sngie	# Cannot overwrite a temp cache
247303980Sngie	#atf_check -s not-exit:0 -e ignore rump.ndp -s fc00::10 b2:a0:20:00:00:ff
248303980Sngie	#$DEBUG && rump.ndp -n -a
249303980Sngie
250313680Sngie	rump_server_destroy_ifaces
251303980Sngie}
252303980Sngie
253303980Sngieget_n_caches()
254303980Sngie{
255303980Sngie
256303980Sngie	echo $(rump.ndp -a -n |grep -v -e Neighbor -e permanent |wc -l)
257303980Sngie}
258303980Sngie
259303980Sngiendp_neighborgcthresh_body()
260303980Sngie{
261303980Sngie
262313680Sngie	rump_server_start $SOCKSRC netinet6
263313680Sngie	rump_server_start $SOCKDST netinet6
264303980Sngie
265303980Sngie	setup_dst_server no
266303980Sngie	setup_src_server
267303980Sngie
268303980Sngie	export RUMP_SERVER=$SOCKDST
269303980Sngie	for i in $(seq 0 9); do
270303980Sngie		atf_check -s exit:0 rump.ifconfig shmif0 inet6 ${IP6DST}$i
271303980Sngie	done
272303980Sngie
273303980Sngie	export RUMP_SERVER=$SOCKSRC
274303980Sngie
275303980Sngie	# ping to 3 destinations
276303980Sngie	$DEBUG && rump.ndp -n -a
277303980Sngie	for i in $(seq 0 2); do
278303980Sngie		atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
279303980Sngie		    ${IP6DST}$i
280303980Sngie	done
281303980Sngie	$DEBUG && rump.ndp -n -a
282303980Sngie
283303980Sngie	# 3 caches should be created
284303980Sngie	atf_check_equal $(get_n_caches) 3
285303980Sngie
286303980Sngie	# ping to additional 3 destinations
287303980Sngie	for i in $(seq 3 5); do
288303980Sngie		atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
289303980Sngie		    ${IP6DST}$i
290303980Sngie	done
291303980Sngie	$DEBUG && rump.ndp -n -a
292303980Sngie
293303980Sngie	# 6 caches should be created in total
294303980Sngie	atf_check_equal $(get_n_caches) 6
295303980Sngie
296303980Sngie	# Limit the number of neighbor caches to 5
297303980Sngie	atf_check -s exit:0 -o ignore rump.sysctl -w \
298303980Sngie	    net.inet6.ip6.neighborgcthresh=5
299303980Sngie
300303980Sngie	# ping to additional 4 destinations
301303980Sngie	for i in $(seq 6 9); do
302303980Sngie		atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \
303303980Sngie		    ${IP6DST}$i
304303980Sngie	done
305303980Sngie
306303980Sngie	# More than 5 caches should be created in total, but exceeded caches
307303980Sngie	# should be GC-ed
308303980Sngie	if [ "$(get_n_caches)" -gt 5 ]; then
309303980Sngie		atf_fail "Neighbor caches are not GC-ed"
310303980Sngie	fi
311303980Sngie
312313680Sngie	rump_server_destroy_ifaces
313303980Sngie}
314303980Sngie
315303980Sngiemake_pkt_str_na()
316303980Sngie{
317303980Sngie	local ip=$1
318303980Sngie	local mac=$2
319303980Sngie	local pkt=
320303980Sngie	pkt="$mac > 33:33:00:00:00:01, ethertype IPv6 (0x86dd), length 86:"
321303980Sngie	pkt="$pkt $ip > ff02::1: ICMP6, neighbor advertisement"
322303980Sngie	echo $pkt
323303980Sngie}
324303980Sngie
325303980Sngiendp_link_activation_body()
326303980Sngie{
327303980Sngie	local linklocal=
328303980Sngie
329313680Sngie	rump_server_start $SOCKSRC netinet6
330313680Sngie	rump_server_start $SOCKDST netinet6
331303980Sngie
332303980Sngie	setup_dst_server
333303980Sngie	setup_src_server
334303980Sngie
335303980Sngie	# flush old packets
336313680Sngie	extract_new_packets bus1 > ./out
337303980Sngie
338303980Sngie	export RUMP_SERVER=$SOCKSRC
339303980Sngie
340303980Sngie	atf_check -s exit:0 -o ignore rump.ifconfig shmif0 link \
341303980Sngie	    b2:a1:00:00:00:01
342303980Sngie
343303980Sngie	atf_check -s exit:0 sleep 1
344313680Sngie	extract_new_packets bus1 > ./out
345303980Sngie	$DEBUG && cat ./out
346303980Sngie
347303980Sngie	linklocal=$(rump.ifconfig shmif0 |awk '/fe80/ {print $2;}' |awk -F % '{print $1;}')
348303980Sngie	$DEBUG && echo $linklocal
349303980Sngie
350303980Sngie	pkt=$(make_pkt_str_na $linklocal b2:a1:00:00:00:01)
351303980Sngie	atf_check -s not-exit:0 -x "cat ./out |grep -q '$pkt'"
352303980Sngie
353303980Sngie	atf_check -s exit:0 -o ignore rump.ifconfig shmif0 link \
354303980Sngie	    b2:a1:00:00:00:02 active
355303980Sngie
356303980Sngie	atf_check -s exit:0 sleep 1
357313680Sngie	extract_new_packets bus1 > ./out
358303980Sngie	$DEBUG && cat ./out
359303980Sngie
360303980Sngie	linklocal=$(rump.ifconfig shmif0 |awk '/fe80/ {print $2;}' |awk -F % '{print $1;}')
361303980Sngie	$DEBUG && echo $linklocal
362303980Sngie
363303980Sngie	pkt=$(make_pkt_str_na $linklocal b2:a1:00:00:00:02)
364303980Sngie	atf_check -s exit:0 -x "cat ./out |grep -q '$pkt'"
365303980Sngie
366313680Sngie	rump_server_destroy_ifaces
367303980Sngie}
368303980Sngie
369303980Sngiendp_cache_expiration_cleanup()
370303980Sngie{
371303980Sngie	$DEBUG && dump
372303980Sngie	cleanup
373303980Sngie}
374303980Sngie
375303980Sngiendp_commands_cleanup()
376303980Sngie{
377303980Sngie	$DEBUG && dump
378303980Sngie	cleanup
379303980Sngie}
380303980Sngie
381303980Sngiendp_cache_overwriting_cleanup()
382303980Sngie{
383303980Sngie	$DEBUG && dump
384303980Sngie	cleanup
385303980Sngie}
386303980Sngie
387303980Sngiendp_neighborgcthresh_cleanup()
388303980Sngie{
389303980Sngie	$DEBUG && dump
390303980Sngie	cleanup
391303980Sngie}
392303980Sngie
393303980Sngiendp_link_activation_cleanup()
394303980Sngie{
395303980Sngie	$DEBUG && dump
396303980Sngie	cleanup
397303980Sngie}
398303980Sngie
399303980Sngieatf_init_test_cases()
400303980Sngie{
401303980Sngie	atf_add_test_case ndp_cache_expiration
402303980Sngie	atf_add_test_case ndp_commands
403303980Sngie	atf_add_test_case ndp_cache_overwriting
404303980Sngie	atf_add_test_case ndp_neighborgcthresh
405303980Sngie	atf_add_test_case ndp_link_activation
406303980Sngie}
407