Home | History | Annotate | Line # | Download | only in net
net_common.sh revision 1.44
      1 #	$NetBSD: net_common.sh,v 1.44 2022/11/02 09:35:12 ozaki-r Exp $
      2 #
      3 # Copyright (c) 2016 Internet Initiative Japan 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 #
     29 # Common utility functions for tests/net
     30 #
     31 
     32 export PATH="/sbin:/usr/sbin:/bin:/usr/bin"
     33 
     34 HIJACKING="env LD_PRELOAD=/usr/lib/librumphijack.so \
     35     RUMPHIJACK=path=/rump,socket=all:nolocal,sysctl=yes"
     36 ONEDAYISH="(23h5[0-9]m|1d0h0m)[0-9]+s ?"
     37 
     38 extract_new_packets()
     39 {
     40 	local bus=$1
     41 	local old=./.__old
     42 
     43 	if [ ! -f $old ]; then
     44 		old=/dev/null
     45 	fi
     46 
     47 	shmif_dumpbus -p - $bus 2>/dev/null |
     48 	    tcpdump -n -e -r - 2>/dev/null > ./.__new
     49 	diff -u $old ./.__new | grep '^+' | cut -d '+' -f 2   > ./.__diff
     50 	mv -f ./.__new ./.__old
     51 	cat ./.__diff
     52 }
     53 
     54 check_route()
     55 {
     56 	local target=$1
     57 	local gw=$2
     58 	local flags=${3:-\.\+}
     59 	local ifname=${4:-\.\+}
     60 
     61 	target=$(echo $target | sed 's/\./\\./g')
     62 	if [ "$gw" = "" ]; then
     63 		gw=".+"
     64 	else
     65 		gw=$(echo $gw | sed 's/\./\\./g')
     66 	fi
     67 
     68 	atf_check -s exit:0 -e ignore \
     69 	    -o match:"^$target +$gw +$flags +- +- +.+ +$ifname" \
     70 	    rump.netstat -rn
     71 }
     72 
     73 check_route_flags()
     74 {
     75 
     76 	check_route "$1" "" "$2" ""
     77 }
     78 
     79 check_route_gw()
     80 {
     81 
     82 	check_route "$1" "$2" "" ""
     83 }
     84 
     85 check_route_no_entry()
     86 {
     87 	local target=$(echo "$1" | sed 's/\./\\./g')
     88 
     89 	atf_check -s exit:0 -e ignore -o not-match:"^$target" rump.netstat -rn
     90 }
     91 
     92 get_linklocal_addr()
     93 {
     94 
     95 	RUMP_SERVER=${1} rump.ifconfig ${2} inet6 |
     96 	    awk "/fe80/ {sub(/%$2/, \"\"); sub(/\\/[0-9]*/, \"\"); print \$2;}"
     97 
     98 	return 0
     99 }
    100 
    101 get_macaddr()
    102 {
    103 
    104 	RUMP_SERVER=${1} rump.ifconfig ${2} | awk '/address/ {print $2;}'
    105 }
    106 
    107 HTTPD_PID=./.__httpd.pid
    108 start_httpd()
    109 {
    110 	local sock=$1
    111 	local ip=$2
    112 	local backup=$RUMP_SERVER
    113 
    114 	export RUMP_SERVER=$sock
    115 
    116 	# start httpd in daemon mode
    117 	atf_check -s exit:0 env LD_PRELOAD=/usr/lib/librumphijack.so \
    118 	    /usr/libexec/httpd -P $HTTPD_PID -i $ip -b -s $(pwd)
    119 
    120 	export RUMP_SERVER=$backup
    121 
    122 	sleep 3
    123 }
    124 
    125 stop_httpd()
    126 {
    127 
    128 	if [ -f $HTTPD_PID ]; then
    129 		kill -9 $(cat $HTTPD_PID)
    130 		rm -f $HTTPD_PID
    131 		sleep 1
    132 	fi
    133 }
    134 
    135 NC_PID=./.__nc.pid
    136 start_nc_server()
    137 {
    138 	local sock=$1
    139 	local port=$2
    140 	local outfile=$3
    141 	local proto=${4:-ipv4}
    142 	local extra_opts="$5"
    143 	local backup=$RUMP_SERVER
    144 	local opts=
    145 
    146 	export RUMP_SERVER=$sock
    147 
    148 	if [ $proto = ipv4 ]; then
    149 		opts="-l -4"
    150 	else
    151 		opts="-l -6"
    152 	fi
    153 	opts="$opts $extra_opts"
    154 
    155 	env LD_PRELOAD=/usr/lib/librumphijack.so nc $opts $port > $outfile &
    156 	echo $! > $NC_PID
    157 
    158 	if [ $proto = ipv4 ]; then
    159 		$DEBUG && rump.netstat -a -f inet
    160 	else
    161 		$DEBUG && rump.netstat -a -f inet6
    162 	fi
    163 
    164 	export RUMP_SERVER=$backup
    165 
    166 	sleep 1
    167 }
    168 
    169 stop_nc_server()
    170 {
    171 
    172 	if [ -f $NC_PID ]; then
    173 		kill -9 $(cat $NC_PID)
    174 		rm -f $NC_PID
    175 		sleep 1
    176 	fi
    177 }
    178 
    179 BASIC_LIBS="-lrumpnet -lrumpnet_net -lrumpnet_netinet -lrumpnet_shmif"
    180 FS_LIBS="$BASIC_LIBS -lrumpdev -lrumpvfs -lrumpfs_ffs"
    181 CRYPTO_LIBS="$BASIC_LIBS -lrumpdev -lrumpdev_opencrypto \
    182     -lrumpkern_z -lrumpkern_crypto"
    183 NPF_LIBS="$BASIC_LIBS -lrumpdev -lrumpvfs -lrumpdev_bpf -lrumpnet_npf"
    184 CRYPTO_NPF_LIBS="$CRYPTO_LIBS -lrumpvfs -lrumpdev_bpf -lrumpnet_npf"
    185 BPF_LIBS="$BASIC_LIBS -lrumpdev -lrumpvfs -lrumpdev_bpf"
    186 
    187 # We cannot keep variables between test phases, so need to store in files
    188 _rump_server_socks=./.__socks
    189 _rump_server_ifaces=./.__ifaces
    190 _rump_server_buses=./.__buses
    191 _rump_server_macaddrs=./.__macaddrs
    192 
    193 DEBUG_SYSCTL_ENTRIES="net.inet.arp.debug net.inet6.icmp6.nd6_debug \
    194     net.inet.ipsec.debug"
    195 
    196 IPSEC_KEY_DEBUG=${IPSEC_KEY_DEBUG:-false}
    197 
    198 _rump_server_start_common()
    199 {
    200 	local sock=$1
    201 	local backup=$RUMP_SERVER
    202 
    203 	shift 1
    204 
    205 	atf_check -s exit:0 rump_server "$@" "$sock"
    206 
    207 	if $DEBUG; then
    208 		# Enable debugging features in the kernel
    209 		export RUMP_SERVER=$sock
    210 		for ent in $DEBUG_SYSCTL_ENTRIES; do
    211 			if rump.sysctl -q $ent; then
    212 				atf_check -s exit:0 rump.sysctl -q -w $ent=1
    213 			fi
    214 		done
    215 		export RUMP_SERVER=$backup
    216 	fi
    217 	if $IPSEC_KEY_DEBUG; then
    218 		# Enable debugging features in the kernel
    219 		export RUMP_SERVER=$sock
    220 		if rump.sysctl -q net.key.debug; then
    221 			atf_check -s exit:0 \
    222 			    rump.sysctl -q -w net.key.debug=0xffff
    223 		fi
    224 		export RUMP_SERVER=$backup
    225 	fi
    226 
    227 	echo $sock >> $_rump_server_socks
    228 	$DEBUG && cat $_rump_server_socks
    229 }
    230 
    231 rump_server_start()
    232 {
    233 	local sock=$1
    234 	local lib=
    235 	local libs="$BASIC_LIBS"
    236 
    237 	shift 1
    238 
    239 	for lib
    240 	do
    241 		libs="$libs -lrumpnet_$lib"
    242 	done
    243 
    244 	_rump_server_start_common $sock $libs
    245 
    246 	return 0
    247 }
    248 
    249 rump_server_fs_start()
    250 {
    251 	local sock=$1
    252 	local lib=
    253 	local libs="$FS_LIBS"
    254 
    255 	shift 1
    256 
    257 	for lib
    258 	do
    259 		libs="$libs -lrumpnet_$lib"
    260 	done
    261 
    262 	_rump_server_start_common $sock $libs
    263 
    264 	return 0
    265 }
    266 
    267 rump_server_crypto_start()
    268 {
    269 	local sock=$1
    270 	local lib=
    271 	local libs="$CRYPTO_LIBS"
    272 
    273 	shift 1
    274 
    275 	for lib
    276 	do
    277 		libs="$libs -lrumpnet_$lib"
    278 	done
    279 
    280 	_rump_server_start_common $sock $libs
    281 
    282 	return 0
    283 }
    284 
    285 rump_server_npf_start()
    286 {
    287 	local sock=$1
    288 	local lib=
    289 	local libs="$NPF_LIBS"
    290 
    291 	shift 1
    292 
    293 	for lib
    294 	do
    295 		libs="$libs -lrumpnet_$lib"
    296 	done
    297 
    298 	_rump_server_start_common $sock $libs
    299 
    300 	return 0
    301 }
    302 
    303 rump_server_crypto_npf_start()
    304 {
    305 	local sock=$1
    306 	local lib=
    307 	local libs="$CRYPTO_NPF_LIBS"
    308 
    309 	shift 1
    310 
    311 	for lib
    312 	do
    313 		libs="$libs -lrumpnet_$lib"
    314 	done
    315 
    316 	_rump_server_start_common $sock $libs
    317 
    318 	return 0
    319 }
    320 
    321 rump_server_bpf_start()
    322 {
    323 	local sock=$1
    324 	local lib=
    325 	local libs="$BPF_LIBS"
    326 
    327 	shift 1
    328 
    329 	for lib
    330 	do
    331 		libs="$libs -lrumpnet_$lib"
    332 	done
    333 
    334 	_rump_server_start_common $sock $libs
    335 
    336 	return 0
    337 }
    338 
    339 rump_server_add_iface()
    340 {
    341 	local sock=$1
    342 	local ifname=$2
    343 	local bus=$3
    344 	local backup=$RUMP_SERVER
    345 	local macaddr=
    346 
    347 	export RUMP_SERVER=$sock
    348 	atf_check -s exit:0 rump.ifconfig $ifname create
    349 	if [ -n "$bus" ]; then
    350 		atf_check -s exit:0 rump.ifconfig $ifname linkstr $bus
    351 	fi
    352 
    353 	macaddr=$(get_macaddr $sock $ifname)
    354 	if [ -n "$macaddr" ]; then
    355 		if [ -f $_rump_server_macaddrs ]; then
    356 			atf_check -s not-exit:0 \
    357 			    grep -q $macaddr $_rump_server_macaddrs
    358 		fi
    359 		echo $macaddr >> $_rump_server_macaddrs
    360 	fi
    361 
    362 	export RUMP_SERVER=$backup
    363 
    364 	echo $sock $ifname >> $_rump_server_ifaces
    365 	$DEBUG && cat $_rump_server_ifaces
    366 
    367 	echo $bus >> $_rump_server_buses
    368 	cat $_rump_server_buses |sort -u >./.__tmp
    369 	mv -f ./.__tmp $_rump_server_buses
    370 	$DEBUG && cat $_rump_server_buses
    371 
    372 	return 0
    373 }
    374 
    375 rump_server_check_poolleaks()
    376 {
    377 	local target=$1
    378 
    379 	# XXX rumphijack doesn't work with a binary with suid/sgid bits like
    380 	# vmstat.  Use a copied one to drop sgid bit as a workaround until
    381 	# vmstat stops using kvm(3) for /dev/kmem and the sgid bit.
    382 	cp /usr/bin/vmstat ./vmstat
    383 	reqs=$($HIJACKING ./vmstat -mv | awk "/$target/ {print \$3;}")
    384 	rels=$($HIJACKING ./vmstat -mv | awk "/$target/ {print \$5;}")
    385 	rm -f ./vmstat
    386 	atf_check_equal '$target$reqs' '$target$rels'
    387 }
    388 
    389 #
    390 # rump_server_check_memleaks detects memory leaks.  It can detect leaks of pool
    391 # objects that are guaranteed to be all deallocated at this point, i.e., all
    392 # created interfaces are destroyed.  Currently only llentpl satisfies this
    393 # constraint.  This mechanism can't be applied to objects allocated through
    394 # pool_cache(9) because it doesn't track released objects explicitly.
    395 #
    396 rump_server_check_memleaks()
    397 {
    398 
    399 	rump_server_check_poolleaks llentrypl
    400 	# This doesn't work for objects allocated through pool_cache
    401 	#rump_server_check_poolleaks mbpl
    402 	#rump_server_check_poolleaks mclpl
    403 	#rump_server_check_poolleaks socket
    404 }
    405 
    406 rump_server_destroy_ifaces()
    407 {
    408 	local backup=$RUMP_SERVER
    409 	local output=ignore
    410 	local reqs= rels=
    411 
    412 	$DEBUG && cat $_rump_server_ifaces
    413 
    414 	# Try to dump states before destroying interfaces
    415 	for sock in $(cat $_rump_server_socks); do
    416 		export RUMP_SERVER=$sock
    417 		if $DEBUG; then
    418 			output=save:/dev/stdout
    419 		fi
    420 		atf_check -s exit:0 -o $output rump.ifconfig
    421 		atf_check -s exit:0 -o $output rump.netstat -nr
    422 		# XXX still need hijacking
    423 		atf_check -s exit:0 -o $output $HIJACKING rump.netstat -nai
    424 		atf_check -s exit:0 -o $output rump.arp -na
    425 		atf_check -s exit:0 -o $output rump.ndp -na
    426 		atf_check -s exit:0 -o $output $HIJACKING ifmcstat
    427 	done
    428 
    429 	# XXX using pipe doesn't work. See PR bin/51667
    430 	#cat $_rump_server_ifaces | while read sock ifname; do
    431 	# Destroy interfaces in the reverse order
    432 	tac $_rump_server_ifaces > __ifaces
    433 	while read sock ifname; do
    434 		export RUMP_SERVER=$sock
    435 		if rump.ifconfig -l |grep -q $ifname; then
    436 			if $DEBUG; then
    437 				rump.ifconfig -v $ifname
    438 			fi
    439 			atf_check -s exit:0 rump.ifconfig $ifname destroy
    440 		fi
    441 		atf_check -s exit:0 -o ignore rump.ifconfig
    442 	done < __ifaces
    443 	rm -f __ifaces
    444 
    445 	for sock in $(cat $_rump_server_socks); do
    446 		export RUMP_SERVER=$sock
    447 		rump_server_check_memleaks
    448 	done
    449 
    450 	export RUMP_SERVER=$backup
    451 
    452 	return 0
    453 }
    454 
    455 rump_server_halt_servers()
    456 {
    457 	local backup=$RUMP_SERVER
    458 
    459 	$DEBUG && cat $_rump_server_socks
    460 	for sock in $(cat $_rump_server_socks); do
    461 		env RUMP_SERVER=$sock rump.halt
    462 	done
    463 	export RUMP_SERVER=$backup
    464 
    465 	return 0
    466 }
    467 
    468 extract_rump_server_core()
    469 {
    470 
    471 	if [ -f rump_server.core ]; then
    472 		gdb -ex bt /usr/bin/rump_server rump_server.core
    473 		# Extract kernel logs including a panic message
    474 		strings rump_server.core |grep -E '^\[.+\] '
    475 	fi
    476 }
    477 
    478 dump_kernel_stats()
    479 {
    480 	local sock=$1
    481 
    482 	echo "### Dumping $sock"
    483 	export RUMP_SERVER=$sock
    484 	rump.ifconfig -av
    485 	rump.netstat -nr
    486 	# XXX still need hijacking
    487 	$HIJACKING rump.netstat -nai
    488 	# XXX workaround for vmstat with the sgid bit
    489 	cp /usr/bin/vmstat ./vmstat
    490 	$HIJACKING ./vmstat -m
    491 	rm -f ./vmstat
    492 	rump.arp -na
    493 	rump.ndp -na
    494 	$HIJACKING ifmcstat
    495 	$HIJACKING dmesg
    496 }
    497 
    498 rump_server_dump_servers()
    499 {
    500 	local backup=$RUMP_SERVER
    501 
    502 	$DEBUG && cat $_rump_server_socks
    503 	for sock in $(cat $_rump_server_socks); do
    504 		dump_kernel_stats $sock
    505 	done
    506 	export RUMP_SERVER=$backup
    507 
    508 	extract_rump_server_core
    509 	return 0
    510 }
    511 
    512 rump_server_dump_buses()
    513 {
    514 
    515 	if [ ! -f $_rump_server_buses ]; then
    516 		return 0
    517 	fi
    518 
    519 	$DEBUG && cat $_rump_server_buses
    520 	for bus in $(cat $_rump_server_buses); do
    521 		echo "### Dumping $bus"
    522 		shmif_dumpbus -p - $bus 2>/dev/null| tcpdump -n -e -r -
    523 	done
    524 	return 0
    525 }
    526 
    527 cleanup()
    528 {
    529 
    530 	rump_server_halt_servers
    531 }
    532 
    533 dump()
    534 {
    535 
    536 	rump_server_dump_servers
    537 	rump_server_dump_buses
    538 }
    539 
    540 skip_if_qemu()
    541 {
    542 	if drvctl -l qemufwcfg0 >/dev/null 2>&1
    543 	then
    544 	    atf_skip "unreliable under qemu, skip until PR kern/43997 fixed"
    545 	fi
    546 }
    547 
    548 test_create_destroy_common()
    549 {
    550 	local sock=$1
    551 	local ifname=$2
    552 	local test_address=${3:-false}
    553 	local ipv4="10.0.0.1/24"
    554 	local ipv6="fc00::1"
    555 
    556 	export RUMP_SERVER=$sock
    557 
    558 	atf_check -s exit:0 rump.ifconfig $ifname create
    559 	atf_check -s exit:0 rump.ifconfig $ifname destroy
    560 
    561 	atf_check -s exit:0 rump.ifconfig $ifname create
    562 	atf_check -s exit:0 rump.ifconfig $ifname up
    563 	atf_check -s exit:0 rump.ifconfig $ifname down
    564 	atf_check -s exit:0 rump.ifconfig $ifname destroy
    565 
    566 	# Destroy while UP
    567 	atf_check -s exit:0 rump.ifconfig $ifname create
    568 	atf_check -s exit:0 rump.ifconfig $ifname up
    569 	atf_check -s exit:0 rump.ifconfig $ifname destroy
    570 
    571 	if ! $test_address; then
    572 		return
    573 	fi
    574 
    575 	# With an IPv4 address
    576 	atf_check -s exit:0 rump.ifconfig $ifname create
    577 	atf_check -s exit:0 rump.ifconfig $ifname inet $ipv4
    578 	atf_check -s exit:0 rump.ifconfig $ifname up
    579 	atf_check -s exit:0 rump.ifconfig $ifname destroy
    580 
    581 	# With an IPv6 address
    582 	atf_check -s exit:0 rump.ifconfig $ifname create
    583 	atf_check -s exit:0 rump.ifconfig $ifname inet6 $ipv6
    584 	atf_check -s exit:0 rump.ifconfig $ifname up
    585 	atf_check -s exit:0 rump.ifconfig $ifname destroy
    586 
    587 	unset RUMP_SERVER
    588 }
    589