Home | History | Annotate | Line # | Download | only in ndp
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