Last active
August 23, 2019 07:03
-
-
Save ozaki-r/37bec56f93f5a57dc98ed618e8db42a3 to your computer and use it in GitHub Desktop.
workaround rumphijck for vmstat
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit d8aa69b7abe780ed6778e23e3f68713f71d13d99 | |
Author: Ryota Ozaki <ozaki-r@iij.ad.jp> | |
Date: Fri Aug 23 13:33:58 2019 +0900 | |
Restore vmstat | |
diff --git a/tests/net/net_common.sh b/tests/net/net_common.sh | |
index 8b1790f9c5a..e224047b76c 100644 | |
--- a/tests/net/net_common.sh | |
+++ b/tests/net/net_common.sh | |
@@ -341,8 +341,13 @@ rump_server_check_poolleaks() | |
{ | |
local target=$1 | |
- reqs=$($HIJACKING vmstat -mv | awk "/$target/ {print \$3;}") | |
- rels=$($HIJACKING vmstat -mv | awk "/$target/ {print \$5;}") | |
+ # XXX rumphijack doesn't work with a binary with suid/sgid bits like | |
+ # vmstat. Use a copied one to drop sgid bit as a workaround until | |
+ # vmstat stops using kvm(3) and the sgid bit. | |
+ cp /usr/bin/vmstat ./vmstat | |
+ reqs=$($HIJACKING ./vmstat -mv | awk "/$target/ {print \$3;}") | |
+ rels=$($HIJACKING ./vmstat -mv | awk "/$target/ {print \$5;}") | |
+ rm -f ./vmstat | |
atf_check_equal '$target$reqs' '$target$rels' | |
} | |
@@ -350,8 +355,7 @@ rump_server_check_poolleaks() | |
rump_server_check_memleaks() | |
{ | |
- # XXX this doesn't work in some cases for unknown reasons | |
- #rump_server_check_poolleaks llentrypl | |
+ rump_server_check_poolleaks llentrypl | |
# This doesn't work for objects allocated through pool_cache | |
#rump_server_check_poolleaks mbpl | |
#rump_server_check_poolleaks mclpl | |
@@ -437,7 +441,10 @@ dump_kernel_stats() | |
rump.netstat -nr | |
# XXX still need hijacking | |
$HIJACKING rump.netstat -nai | |
- $HIJACKING vmstat -m | |
+ # XXX workaround for vmstat with the sgid bit | |
+ cp /usr/bin/vmstat ./vmstat | |
+ $HIJACKING ./vmstat -m | |
+ rm -f ./vmstat | |
rump.arp -na | |
rump.ndp -na | |
$HIJACKING ifmcstat |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/atf-sh | |
# $NetBSD: net_common.sh,v 1.35 2019/08/20 09:53:45 ozaki-r Exp $ | |
# | |
# Copyright (c) 2016 Internet Initiative Japan Inc. | |
# All rights reserved. | |
# | |
# Redistribution and use in source and binary forms, with or without | |
# modification, are permitted provided that the following conditions | |
# are met: | |
# 1. Redistributions of source code must retain the above copyright | |
# notice, this list of conditions and the following disclaimer. | |
# 2. Redistributions in binary form must reproduce the above copyright | |
# notice, this list of conditions and the following disclaimer in the | |
# documentation and/or other materials provided with the distribution. | |
# | |
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
# POSSIBILITY OF SUCH DAMAGE. | |
# | |
# | |
# Common utility functions for tests/net | |
# | |
HIJACKING="env LD_PRELOAD=/usr/lib/librumphijack.so \ | |
RUMPHIJACK=path=/rump,socket=all:nolocal,sysctl=yes" | |
ONEDAYISH="(23h5[0-9]m|1d0h0m)[0-9]+s ?" | |
extract_new_packets() | |
{ | |
local bus=$1 | |
local old=./.__old | |
if [ ! -f $old ]; then | |
old=/dev/null | |
fi | |
shmif_dumpbus -p - $bus 2>/dev/null | | |
tcpdump -n -e -r - 2>/dev/null > ./.__new | |
diff -u $old ./.__new | grep '^+' | cut -d '+' -f 2 > ./.__diff | |
mv -f ./.__new ./.__old | |
cat ./.__diff | |
} | |
check_route() | |
{ | |
local target=$1 | |
local gw=$2 | |
local flags=${3:-\.\+} | |
local ifname=${4:-\.\+} | |
target=$(echo $target | sed 's/\./\\./g') | |
if [ "$gw" = "" ]; then | |
gw=".+" | |
else | |
gw=$(echo $gw | sed 's/\./\\./g') | |
fi | |
atf_check -s exit:0 -e ignore \ | |
-o match:"^$target +$gw +$flags +- +- +.+ +$ifname" \ | |
rump.netstat -rn | |
} | |
check_route_flags() | |
{ | |
check_route "$1" "" "$2" "" | |
} | |
check_route_gw() | |
{ | |
check_route "$1" "$2" "" "" | |
} | |
check_route_no_entry() | |
{ | |
local target=$(echo "$1" | sed 's/\./\\./g') | |
atf_check -s exit:0 -e ignore -o not-match:"^$target" rump.netstat -rn | |
} | |
get_linklocal_addr() | |
{ | |
RUMP_SERVER=${1} rump.ifconfig ${2} inet6 | | |
awk "/fe80/ {sub(/%$2/, \"\"); sub(/\\/[0-9]*/, \"\"); print \$2;}" | |
return 0 | |
} | |
get_macaddr() | |
{ | |
RUMP_SERVER=${1} rump.ifconfig ${2} | awk '/address/ {print $2;}' | |
} | |
HTTPD_PID=./.__httpd.pid | |
start_httpd() | |
{ | |
local sock=$1 | |
local ip=$2 | |
local backup=$RUMP_SERVER | |
export RUMP_SERVER=$sock | |
# start httpd in daemon mode | |
atf_check -s exit:0 env LD_PRELOAD=/usr/lib/librumphijack.so \ | |
/usr/libexec/httpd -P $HTTPD_PID -i $ip -b -s $(pwd) | |
export RUMP_SERVER=$backup | |
sleep 3 | |
} | |
stop_httpd() | |
{ | |
if [ -f $HTTPD_PID ]; then | |
kill -9 $(cat $HTTPD_PID) | |
rm -f $HTTPD_PID | |
sleep 1 | |
fi | |
} | |
NC_PID=./.__nc.pid | |
start_nc_server() | |
{ | |
local sock=$1 | |
local port=$2 | |
local outfile=$3 | |
local proto=${4:-ipv4} | |
local backup=$RUMP_SERVER | |
local opts= | |
export RUMP_SERVER=$sock | |
if [ $proto = ipv4 ]; then | |
opts="-l -4" | |
else | |
opts="-l -6" | |
fi | |
env LD_PRELOAD=/usr/lib/librumphijack.so nc $opts $port > $outfile & | |
echo $! > $NC_PID | |
if [ $proto = ipv4 ]; then | |
$DEBUG && rump.netstat -a -f inet | |
else | |
$DEBUG && rump.netstat -a -f inet6 | |
fi | |
export RUMP_SERVER=$backup | |
sleep 1 | |
} | |
stop_nc_server() | |
{ | |
if [ -f $NC_PID ]; then | |
kill -9 $(cat $NC_PID) | |
rm -f $NC_PID | |
sleep 1 | |
fi | |
} | |
BASIC_LIBS="-lrumpnet -lrumpnet_net -lrumpnet_netinet -lrumpnet_shmif" | |
FS_LIBS="$BASIC_LIBS -lrumpdev -lrumpvfs -lrumpfs_ffs" | |
CRYPTO_LIBS="$BASIC_LIBS -lrumpdev -lrumpdev_opencrypto \ | |
-lrumpkern_z -lrumpkern_crypto" | |
NPF_LIBS="$BASIC_LIBS -lrumpdev -lrumpvfs -lrumpdev_bpf -lrumpnet_npf" | |
CRYPTO_NPF_LIBS="$CRYPTO_LIBS -lrumpvfs -lrumpdev_bpf -lrumpnet_npf" | |
# We cannot keep variables between test phases, so need to store in files | |
_rump_server_socks=./.__socks | |
_rump_server_ifaces=./.__ifaces | |
_rump_server_buses=./.__buses | |
DEBUG_SYSCTL_ENTRIES="net.inet.arp.debug net.inet6.icmp6.nd6_debug \ | |
net.inet.ipsec.debug" | |
IPSEC_KEY_DEBUG=${IPSEC_KEY_DEBUG:-false} | |
_rump_server_start_common() | |
{ | |
local sock=$1 | |
local backup=$RUMP_SERVER | |
shift 1 | |
atf_check -s exit:0 rump_server "$@" "$sock" | |
if $DEBUG; then | |
# Enable debugging features in the kernel | |
export RUMP_SERVER=$sock | |
for ent in $DEBUG_SYSCTL_ENTRIES; do | |
if rump.sysctl -q $ent; then | |
atf_check -s exit:0 rump.sysctl -q -w $ent=1 | |
fi | |
done | |
export RUMP_SERVER=$backup | |
fi | |
if $IPSEC_KEY_DEBUG; then | |
# Enable debugging features in the kernel | |
export RUMP_SERVER=$sock | |
if rump.sysctl -q net.key.debug; then | |
atf_check -s exit:0 \ | |
rump.sysctl -q -w net.key.debug=0xffff | |
fi | |
export RUMP_SERVER=$backup | |
fi | |
echo $sock >> $_rump_server_socks | |
$DEBUG && cat $_rump_server_socks | |
} | |
rump_server_start() | |
{ | |
local sock=$1 | |
local lib= | |
local libs="$BASIC_LIBS" | |
shift 1 | |
for lib | |
do | |
libs="$libs -lrumpnet_$lib" | |
done | |
_rump_server_start_common $sock $libs | |
return 0 | |
} | |
rump_server_fs_start() | |
{ | |
local sock=$1 | |
local lib= | |
local libs="$FS_LIBS" | |
shift 1 | |
for lib | |
do | |
libs="$libs -lrumpnet_$lib" | |
done | |
_rump_server_start_common $sock $libs | |
return 0 | |
} | |
rump_server_crypto_start() | |
{ | |
local sock=$1 | |
local lib= | |
local libs="$CRYPTO_LIBS" | |
shift 1 | |
for lib | |
do | |
libs="$libs -lrumpnet_$lib" | |
done | |
_rump_server_start_common $sock $libs | |
return 0 | |
} | |
rump_server_npf_start() | |
{ | |
local sock=$1 | |
local lib= | |
local libs="$NPF_LIBS" | |
shift 1 | |
for lib | |
do | |
libs="$libs -lrumpnet_$lib" | |
done | |
_rump_server_start_common $sock $libs | |
return 0 | |
} | |
rump_server_crypto_npf_start() | |
{ | |
local sock=$1 | |
local lib= | |
local libs="$CRYPTO_NPF_LIBS" | |
shift 1 | |
for lib | |
do | |
libs="$libs -lrumpnet_$lib" | |
done | |
_rump_server_start_common $sock $libs | |
return 0 | |
} | |
rump_server_add_iface() | |
{ | |
local sock=$1 | |
local ifname=$2 | |
local bus=$3 | |
local backup=$RUMP_SERVER | |
export RUMP_SERVER=$sock | |
atf_check -s exit:0 rump.ifconfig $ifname create | |
if [ -n "$bus" ]; then | |
atf_check -s exit:0 rump.ifconfig $ifname linkstr $bus | |
fi | |
export RUMP_SERVER=$backup | |
echo $sock $ifname >> $_rump_server_ifaces | |
$DEBUG && cat $_rump_server_ifaces | |
echo $bus >> $_rump_server_buses | |
cat $_rump_server_buses |sort -u >./.__tmp | |
mv -f ./.__tmp $_rump_server_buses | |
$DEBUG && cat $_rump_server_buses | |
return 0 | |
} | |
rump_server_check_poolleaks() | |
{ | |
local target=$1 | |
# XXX rumphijack doesn't work with a binary with suid/sgid bits like | |
# vmstat. Use a copied one to drop sgid bit as a workaround until | |
# vmstat stops using kvm(3) and the sgid bit. | |
cp /usr/bin/vmstat ./vmstat | |
reqs=$($HIJACKING ./vmstat -mv | awk "/$target/ {print \$3;}") | |
rels=$($HIJACKING ./vmstat -mv | awk "/$target/ {print \$5;}") | |
rm -f ./vmstat | |
atf_check_equal '$target$reqs' '$target$rels' | |
} | |
rump_server_check_memleaks() | |
{ | |
rump_server_check_poolleaks llentrypl | |
# This doesn't work for objects allocated through pool_cache | |
#rump_server_check_poolleaks mbpl | |
#rump_server_check_poolleaks mclpl | |
#rump_server_check_poolleaks socket | |
} | |
rump_server_destroy_ifaces() | |
{ | |
local backup=$RUMP_SERVER | |
local output=ignore | |
local reqs= rels= | |
$DEBUG && cat $_rump_server_ifaces | |
# Try to dump states before destroying interfaces | |
for sock in $(cat $_rump_server_socks); do | |
export RUMP_SERVER=$sock | |
if $DEBUG; then | |
output=save:/dev/stdout | |
fi | |
atf_check -s exit:0 -o $output rump.ifconfig | |
atf_check -s exit:0 -o $output rump.netstat -nr | |
# XXX still need hijacking | |
atf_check -s exit:0 -o $output $HIJACKING rump.netstat -nai | |
atf_check -s exit:0 -o $output rump.arp -na | |
atf_check -s exit:0 -o $output rump.ndp -na | |
atf_check -s exit:0 -o $output $HIJACKING ifmcstat | |
done | |
# XXX using pipe doesn't work. See PR bin/51667 | |
#cat $_rump_server_ifaces | while read sock ifname; do | |
# Destroy interfaces in the reverse order | |
tac $_rump_server_ifaces > __ifaces | |
while read sock ifname; do | |
export RUMP_SERVER=$sock | |
if rump.ifconfig -l |grep -q $ifname; then | |
atf_check -s exit:0 rump.ifconfig $ifname destroy | |
fi | |
atf_check -s exit:0 -o ignore rump.ifconfig | |
done < __ifaces | |
rm -f __ifaces | |
for sock in $(cat $_rump_server_socks); do | |
export RUMP_SERVER=$sock | |
rump_server_check_memleaks | |
done | |
export RUMP_SERVER=$backup | |
return 0 | |
} | |
rump_server_halt_servers() | |
{ | |
local backup=$RUMP_SERVER | |
$DEBUG && cat $_rump_server_socks | |
for sock in $(cat $_rump_server_socks); do | |
env RUMP_SERVER=$sock rump.halt | |
done | |
export RUMP_SERVER=$backup | |
return 0 | |
} | |
extract_rump_server_core() | |
{ | |
if [ -f rump_server.core ]; then | |
gdb -ex bt /usr/bin/rump_server rump_server.core | |
# Extract kernel logs including a panic message | |
strings rump_server.core |grep -E '^\[.+\] ' | |
fi | |
} | |
dump_kernel_stats() | |
{ | |
local sock=$1 | |
echo "### Dumping $sock" | |
export RUMP_SERVER=$sock | |
rump.ifconfig -av | |
rump.netstat -nr | |
# XXX still need hijacking | |
$HIJACKING rump.netstat -nai | |
# XXX workaround for vmstat with the sgid bit | |
cp /usr/bin/vmstat ./vmstat | |
$HIJACKING ./vmstat -m | |
rm -f ./vmstat | |
rump.arp -na | |
rump.ndp -na | |
$HIJACKING ifmcstat | |
$HIJACKING dmesg | |
} | |
rump_server_dump_servers() | |
{ | |
local backup=$RUMP_SERVER | |
$DEBUG && cat $_rump_server_socks | |
for sock in $(cat $_rump_server_socks); do | |
dump_kernel_stats $sock | |
done | |
export RUMP_SERVER=$backup | |
extract_rump_server_core | |
return 0 | |
} | |
rump_server_dump_buses() | |
{ | |
if [ ! -f $_rump_server_buses ]; then | |
return 0 | |
fi | |
$DEBUG && cat $_rump_server_buses | |
for bus in $(cat $_rump_server_buses); do | |
echo "### Dumping $bus" | |
shmif_dumpbus -p - $bus 2>/dev/null| tcpdump -n -e -r - | |
done | |
return 0 | |
} | |
cleanup() | |
{ | |
rump_server_halt_servers | |
} | |
dump() | |
{ | |
rump_server_dump_servers | |
rump_server_dump_buses | |
} | |
skip_if_qemu() | |
{ | |
if sysctl machdep.cpu_brand 2>/dev/null | grep QEMU >/dev/null 2>&1 | |
then | |
atf_skip "unreliable under qemu, skip until PR kern/43997 fixed" | |
fi | |
} | |
test_create_destroy_common() | |
{ | |
local sock=$1 | |
local ifname=$2 | |
local test_address=${3:-false} | |
local ipv4="10.0.0.1/24" | |
local ipv6="fc00::1" | |
export RUMP_SERVER=$sock | |
atf_check -s exit:0 rump.ifconfig $ifname create | |
atf_check -s exit:0 rump.ifconfig $ifname destroy | |
atf_check -s exit:0 rump.ifconfig $ifname create | |
atf_check -s exit:0 rump.ifconfig $ifname up | |
atf_check -s exit:0 rump.ifconfig $ifname down | |
atf_check -s exit:0 rump.ifconfig $ifname destroy | |
# Destroy while UP | |
atf_check -s exit:0 rump.ifconfig $ifname create | |
atf_check -s exit:0 rump.ifconfig $ifname up | |
atf_check -s exit:0 rump.ifconfig $ifname destroy | |
if ! $test_address; then | |
return | |
fi | |
# With an IPv4 address | |
atf_check -s exit:0 rump.ifconfig $ifname create | |
atf_check -s exit:0 rump.ifconfig $ifname inet $ipv4 | |
atf_check -s exit:0 rump.ifconfig $ifname up | |
atf_check -s exit:0 rump.ifconfig $ifname destroy | |
# With an IPv6 address | |
atf_check -s exit:0 rump.ifconfig $ifname create | |
atf_check -s exit:0 rump.ifconfig $ifname inet6 $ipv6 | |
atf_check -s exit:0 rump.ifconfig $ifname up | |
atf_check -s exit:0 rump.ifconfig $ifname destroy | |
unset RUMP_SERVER | |
} | |
# $NetBSD: t_ndp.sh,v 1.35 2019/08/19 03:20:27 ozaki-r Exp $ | |
# | |
# Copyright (c) 2015 The NetBSD Foundation, Inc. | |
# All rights reserved. | |
# | |
# Redistribution and use in source and binary forms, with or without | |
# modification, are permitted provided that the following conditions | |
# are met: | |
# 1. Redistributions of source code must retain the above copyright | |
# notice, this list of conditions and the following disclaimer. | |
# 2. Redistributions in binary form must reproduce the above copyright | |
# notice, this list of conditions and the following disclaimer in the | |
# documentation and/or other materials provided with the distribution. | |
# | |
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
# POSSIBILITY OF SUCH DAMAGE. | |
# | |
SOCKSRC=unix://commsock1 | |
SOCKDST=unix://commsock2 | |
IP6SRC=fc00::1 | |
IP6SRC2=fc00::3 | |
IP6DST=fc00::2 | |
IP6NET=fc00::0 | |
DEBUG=${DEBUG:-false} | |
TIMEOUT=1 | |
atf_test_case ndp_cache_expiration cleanup | |
atf_test_case ndp_commands cleanup | |
atf_test_case ndp_cache_overwriting cleanup | |
atf_test_case ndp_neighborgcthresh cleanup | |
atf_test_case ndp_link_activation cleanup | |
ndp_cache_expiration_head() | |
{ | |
atf_set "descr" "Tests for NDP cache expiration" | |
atf_set "require.progs" "rump_server" | |
} | |
ndp_commands_head() | |
{ | |
atf_set "descr" "Tests for commands of ndp(8)" | |
atf_set "require.progs" "rump_server" | |
} | |
ndp_cache_overwriting_head() | |
{ | |
atf_set "descr" "Tests for behavior of overwriting NDP caches" | |
atf_set "require.progs" "rump_server" | |
} | |
ndp_neighborgcthresh_head() | |
{ | |
atf_set "descr" "Tests for GC of neighbor caches" | |
atf_set "require.progs" "rump_server" | |
} | |
ndp_link_activation_head() | |
{ | |
atf_set "descr" "Tests for activating a new MAC address" | |
atf_set "require.progs" "rump_server" | |
} | |
setup_dst_server() | |
{ | |
local assign_ip=$1 | |
rump_server_add_iface $SOCKDST shmif0 bus1 | |
export RUMP_SERVER=$SOCKDST | |
if [ "$assign_ip" != no ]; then | |
atf_check -s exit:0 rump.ifconfig shmif0 inet6 $IP6DST | |
fi | |
atf_check -s exit:0 rump.ifconfig shmif0 up | |
atf_check -s exit:0 rump.ifconfig -w 10 | |
$DEBUG && rump.ifconfig shmif0 | |
$DEBUG && rump.ndp -n -a | |
} | |
setup_src_server() | |
{ | |
$DEBUG && ulimit -c unlimited | |
export RUMP_SERVER=$SOCKSRC | |
# Setup an interface | |
rump_server_add_iface $SOCKSRC shmif0 bus1 | |
atf_check -s exit:0 rump.ifconfig shmif0 inet6 $IP6SRC | |
atf_check -s exit:0 rump.ifconfig shmif0 up | |
atf_check -s exit:0 rump.ifconfig -w 10 | |
# Sanity check | |
$DEBUG && rump.ifconfig shmif0 | |
$DEBUG && rump.ndp -n -a | |
atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6SRC | |
atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6DST | |
} | |
get_timeout() | |
{ | |
local timeout=$(env RUMP_SERVER=$SOCKSRC rump.ndp -n $IP6DST |grep $IP6DST|awk '{print $4;}') | |
timeout=${timeout%s} | |
echo $timeout | |
} | |
ndp_cache_expiration_body() | |
{ | |
local macaddr= | |
rump_server_start $SOCKSRC netinet6 | |
rump_server_start $SOCKDST netinet6 | |
setup_dst_server | |
setup_src_server | |
# Shorten the expire time of cache entries | |
export RUMP_SERVER=$SOCKSRC | |
atf_check -s exit:0 -o match:'basereachable=7s0ms' \ | |
rump.ndp -i shmif0 basereachable=7000 | |
# Make a permanent cache entry to avoid sending an NS packet disturbing | |
# the test | |
macaddr=$(get_macaddr $SOCKSRC shmif0) | |
export RUMP_SERVER=$SOCKDST | |
atf_check -s exit:0 -o ignore rump.ndp -s $IP6SRC $macaddr | |
export RUMP_SERVER=$SOCKSRC | |
# | |
# Check if a cache is expired expectedly | |
# | |
atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST | |
$DEBUG && rump.ndp -n -a | |
atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6SRC | |
# Should be cached | |
atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n $IP6DST | |
timeout=$(get_timeout $IP6DST) | |
atf_check -s exit:0 sleep $(($timeout + 1)) | |
$DEBUG && rump.ndp -n -a | |
atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6SRC | |
# Expired but remains until GC sweaps it (1 day) | |
atf_check -s exit:0 -o match:"$ONEDAYISH" rump.ndp -n $IP6DST | |
rump_server_destroy_ifaces | |
} | |
ifdown_dst_server() | |
{ | |
export RUMP_SERVER=$SOCKDST | |
atf_check -s exit:0 rump.ifconfig shmif0 down | |
export RUMP_SERVER=$SOCKSRC | |
} | |
ndp_commands_body() | |
{ | |
rump_server_start $SOCKSRC netinet6 | |
rump_server_start $SOCKDST netinet6 | |
setup_dst_server | |
setup_src_server | |
export RUMP_SERVER=$SOCKSRC | |
# Add and delete a static entry | |
$DEBUG && rump.ndp -n -a | |
atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10 | |
$DEBUG && rump.ndp -n -a | |
atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::10 | |
check_route fc00::10 'b2:a0:20:00:00:10' UHLS shmif0 | |
atf_check -s exit:0 -o match:'deleted' rump.ndp -d fc00::10 | |
$DEBUG && rump.ndp -n -a | |
atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n fc00::10 | |
check_route_no_entry fc00::10 | |
# Add multiple entries via a file (XXX not implemented) | |
#cat - > ./list <<-EOF | |
#fc00::11 b2:a0:20:00:00:11 | |
#fc00::12 b2:a0:20:00:00:12 | |
#fc00::13 b2:a0:20:00:00:13 | |
#fc00::14 b2:a0:20:00:00:14 | |
#fc00::15 b2:a0:20:00:00:15 | |
#EOF | |
#$DEBUG && rump.ndp -n -a | |
#atf_check -s exit:0 -o ignore rump.ndp -f ./list | |
#$DEBUG && rump.ndp -n -a | |
atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST | |
atf_check -s exit:0 -o ignore rump.ndp -s fc00::11 b2:a0:20:00:00:11 | |
atf_check -s exit:0 -o ignore rump.ndp -s fc00::12 b2:a0:20:00:00:12 | |
atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n $IP6DST | |
atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::11 | |
atf_check -s exit:0 -o match:'permanent' rump.ndp -n fc00::12 | |
check_route_flags $IP6DST UHL | |
check_route_flags fc00::11 UHLS | |
check_route_flags fc00::12 UHLS | |
# Test ndp -a | |
atf_check -s exit:0 -o match:'fc00::11' rump.ndp -n -a | |
atf_check -s exit:0 -o match:'fc00::12' rump.ndp -n -a | |
# Ensure no packet upsets the src server | |
ifdown_dst_server | |
# Flush all entries (-c) | |
$DEBUG && rump.ndp -n -a | |
atf_check -s exit:0 -o ignore rump.ndp -c | |
atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6SRC | |
atf_check -s not-exit:0 -o ignore -e ignore rump.ndp -n $IP6DST | |
#check_route_no_entry $IP6SRC | |
check_route_no_entry $IP6DST | |
# Only the static caches are not deleted | |
atf_check -s exit:0 -o ignore -e ignore rump.ndp -n fc00::11 | |
atf_check -s exit:0 -o ignore -e ignore rump.ndp -n fc00::12 | |
check_route_flags fc00::11 UHLS | |
check_route_flags fc00::12 UHLS | |
$DEBUG && rump.ndp -n -a | |
atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp | |
rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp | |
$DEBUG && rump.ndp -n -a | |
atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n fc00::10 | |
check_route fc00::10 'b2:a0:20:00:00:10' UHL shmif0 | |
rump_server_destroy_ifaces | |
} | |
ndp_cache_overwriting_body() | |
{ | |
rump_server_start $SOCKSRC netinet6 | |
rump_server_start $SOCKDST netinet6 | |
setup_dst_server | |
setup_src_server | |
export RUMP_SERVER=$SOCKSRC | |
# Cannot overwrite a permanent cache | |
atf_check -s exit:0 rump.ndp -s $IP6SRC b2:a0:20:00:00:ff | |
$DEBUG && rump.ndp -n -a | |
atf_check -s not-exit:0 -e ignore rump.ndp -s $IP6SRC b2:a0:20:00:00:fe | |
atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST | |
$DEBUG && rump.ndp -n -a | |
# Can overwrite a dynamic cache | |
atf_check -s exit:0 -o ignore rump.ndp -s $IP6DST b2:a0:20:00:00:00 | |
$DEBUG && rump.ndp -n -a | |
atf_check -s exit:0 -o match:'permanent' rump.ndp -n $IP6DST | |
# Test temp option (XXX it doesn't work; expire time isn't set) | |
#atf_check -s exit:0 -o ignore rump.ndp -s fc00::10 b2:a0:20:00:00:10 temp | |
#$DEBUG && rump.ndp -n -a | |
#atf_check -s exit:0 -o not-match:'permanent' rump.ndp -n fc00::10 | |
# Cannot overwrite a temp cache | |
#atf_check -s not-exit:0 -e ignore rump.ndp -s fc00::10 b2:a0:20:00:00:ff | |
#$DEBUG && rump.ndp -n -a | |
rump_server_destroy_ifaces | |
} | |
get_n_caches() | |
{ | |
echo $(rump.ndp -a -n |grep -v -e Neighbor -e permanent |wc -l) | |
} | |
ndp_neighborgcthresh_body() | |
{ | |
rump_server_start $SOCKSRC netinet6 | |
rump_server_start $SOCKDST netinet6 | |
setup_dst_server no | |
setup_src_server | |
export RUMP_SERVER=$SOCKDST | |
for i in $(seq 0 9); do | |
atf_check -s exit:0 rump.ifconfig shmif0 inet6 ${IP6DST}$i | |
done | |
export RUMP_SERVER=$SOCKSRC | |
# ping to 3 destinations | |
$DEBUG && rump.ndp -n -a | |
for i in $(seq 0 2); do | |
atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \ | |
${IP6DST}$i | |
done | |
$DEBUG && rump.ndp -n -a | |
# 3 caches should be created | |
atf_check_equal $(get_n_caches) 3 | |
# ping to additional 3 destinations | |
for i in $(seq 3 5); do | |
atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \ | |
${IP6DST}$i | |
done | |
$DEBUG && rump.ndp -n -a | |
# 6 caches should be created in total | |
atf_check_equal $(get_n_caches) 6 | |
# Limit the number of neighbor caches to 5 | |
atf_check -s exit:0 -o ignore rump.sysctl -w \ | |
net.inet6.ip6.neighborgcthresh=5 | |
# ping to additional 4 destinations | |
for i in $(seq 6 9); do | |
atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 \ | |
${IP6DST}$i | |
done | |
# More than 5 caches should be created in total, but exceeded caches | |
# should be GC-ed | |
if [ "$(get_n_caches)" -gt 5 ]; then | |
atf_fail "Neighbor caches are not GC-ed" | |
fi | |
rump_server_destroy_ifaces | |
} | |
make_pkt_str_na() | |
{ | |
local ip=$1 | |
local mac=$2 | |
local pkt= | |
pkt="$mac > 33:33:00:00:00:01, ethertype IPv6 (0x86dd), length 86:" | |
pkt="$pkt $ip > ff02::1: ICMP6, neighbor advertisement" | |
echo $pkt | |
} | |
ndp_link_activation_body() | |
{ | |
local linklocal= | |
rump_server_start $SOCKSRC netinet6 | |
rump_server_start $SOCKDST netinet6 | |
setup_dst_server | |
setup_src_server | |
# flush old packets | |
extract_new_packets bus1 > ./out | |
export RUMP_SERVER=$SOCKSRC | |
atf_check -s exit:0 -o ignore rump.ifconfig shmif0 link \ | |
b2:a1:00:00:00:01 | |
atf_check -s exit:0 sleep 1 | |
extract_new_packets bus1 > ./out | |
$DEBUG && cat ./out | |
linklocal=$(rump.ifconfig shmif0 |awk '/fe80/ {print $2;}' |awk -F % '{print $1;}') | |
$DEBUG && echo $linklocal | |
pkt=$(make_pkt_str_na $linklocal b2:a1:00:00:00:01) | |
atf_check -s not-exit:0 -x "cat ./out |grep -q '$pkt'" | |
atf_check -s exit:0 -o ignore rump.ifconfig shmif0 link \ | |
b2:a1:00:00:00:02 active | |
atf_check -s exit:0 sleep 1 | |
extract_new_packets bus1 > ./out | |
$DEBUG && cat ./out | |
linklocal=$(rump.ifconfig shmif0 |awk '/fe80/ {print $2;}' |awk -F % '{print $1;}') | |
$DEBUG && echo $linklocal | |
pkt=$(make_pkt_str_na $linklocal b2:a1:00:00:00:02) | |
atf_check -s exit:0 -x "cat ./out |grep -q '$pkt'" | |
rump_server_destroy_ifaces | |
} | |
ndp_cache_expiration_cleanup() | |
{ | |
$DEBUG && dump | |
cleanup | |
} | |
ndp_commands_cleanup() | |
{ | |
$DEBUG && dump | |
cleanup | |
} | |
ndp_cache_overwriting_cleanup() | |
{ | |
$DEBUG && dump | |
cleanup | |
} | |
ndp_neighborgcthresh_cleanup() | |
{ | |
$DEBUG && dump | |
cleanup | |
} | |
ndp_link_activation_cleanup() | |
{ | |
$DEBUG && dump | |
cleanup | |
} | |
atf_test_case ndp_rtm cleanup | |
ndp_rtm_head() | |
{ | |
atf_set "descr" "Tests for routing messages on operations of NDP entries" | |
atf_set "require.progs" "rump_server" | |
} | |
ndp_rtm_body() | |
{ | |
local macaddr_src= macaddr_dst= | |
local file=./tmp | |
local pid= hdr= what= addr= | |
rump_server_start $SOCKSRC netinet6 | |
rump_server_start $SOCKDST netinet6 | |
setup_dst_server | |
setup_src_server | |
macaddr_src=$(get_macaddr $SOCKSRC shmif0) | |
macaddr_dst=$(get_macaddr $SOCKDST shmif0) | |
export RUMP_SERVER=$SOCKSRC | |
# Test ping and a resulting routing message (RTM_ADD) | |
rump.route -n monitor -c 1 > $file & | |
pid=$! | |
sleep 1 | |
atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST | |
wait $pid | |
$DEBUG && cat $file | |
hdr="RTM_ADD.+<UP,HOST,DONE,LLINFO,CLONED>" | |
what="<DST,GATEWAY>" | |
addr="$IP6DST link#2" | |
atf_check -s exit:0 -o match:"$hdr" -o match:"$what" -o match:"$addr" \ | |
cat $file | |
# Test ndp -d and resulting routing messages (RTM_DELETE) | |
rump.route -n monitor -c 1 > $file & | |
pid=$! | |
sleep 1 | |
atf_check -s exit:0 -o ignore rump.ndp -d $IP6DST | |
wait $pid | |
$DEBUG && cat $file | |
hdr="RTM_DELETE.+<HOST,DONE,LLINFO,CLONED>" | |
what="<DST,GATEWAY>" | |
addr="$IP6DST $macaddr_dst" | |
atf_check -s exit:0 -o match:"$hdr" -o match:"$what" -o match:"$addr" \ | |
grep -A 3 RTM_DELETE $file | |
rump_server_destroy_ifaces | |
} | |
ndp_rtm_cleanup() | |
{ | |
$DEBUG && dump | |
cleanup | |
} | |
atf_test_case ndp_purge_on_route_change cleanup | |
ndp_purge_on_route_change_head() | |
{ | |
atf_set "descr" "Tests if NDP entries are removed on route change" | |
atf_set "require.progs" "rump_server" | |
} | |
ndp_purge_on_route_change_body() | |
{ | |
rump_server_start $SOCKSRC netinet6 | |
rump_server_start $SOCKDST netinet6 | |
setup_dst_server | |
setup_src_server | |
rump_server_add_iface $SOCKSRC shmif1 bus1 | |
export RUMP_SERVER=$SOCKSRC | |
atf_check -s exit:0 rump.ifconfig shmif1 inet6 fc00:1::1 | |
atf_check -s exit:0 rump.ifconfig -w 10 | |
$DEBUG && rump.netstat -nr -f inet6 | |
atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST | |
atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST | |
atf_check -s exit:0 -o ignore \ | |
rump.route change -inet6 -net $IP6NET/64 -ifp shmif1 | |
$DEBUG && rump.netstat -nr -f inet6 | |
$DEBUG && rump.ndp -na | |
# The entry was already removed on route change | |
atf_check -s not-exit:0 -o ignore -e match:'no entry' \ | |
rump.ndp -n $IP6DST | |
rump_server_destroy_ifaces | |
} | |
ndp_purge_on_route_change_cleanup() | |
{ | |
$DEBUG && dump | |
cleanup | |
} | |
atf_test_case ndp_purge_on_route_delete cleanup | |
ndp_purge_on_route_delete_head() | |
{ | |
atf_set "descr" "Tests if NDP entries are removed on route delete" | |
atf_set "require.progs" "rump_server" | |
} | |
ndp_purge_on_route_delete_body() | |
{ | |
rump_server_start $SOCKSRC netinet6 | |
rump_server_start $SOCKDST netinet6 | |
setup_dst_server | |
setup_src_server | |
$DEBUG && rump.netstat -nr -f inet6 | |
atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST | |
atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST | |
atf_check -s exit:0 -o ignore rump.route delete -inet6 -net $IP6NET/64 | |
$DEBUG && rump.netstat -nr -f inet6 | |
$DEBUG && rump.ndp -na | |
# The entry was already removed on route delete | |
atf_check -s not-exit:0 -o ignore -e match:'no entry' \ | |
rump.ndp -n $IP6DST | |
rump_server_destroy_ifaces | |
} | |
ndp_purge_on_route_delete_cleanup() | |
{ | |
$DEBUG && dump | |
cleanup | |
} | |
atf_test_case ndp_purge_on_ifdown cleanup | |
ndp_purge_on_ifdown_head() | |
{ | |
atf_set "descr" "Tests if NDP entries are removed on interface down" | |
atf_set "require.progs" "rump_server" | |
} | |
ndp_purge_on_ifdown_body() | |
{ | |
rump_server_start $SOCKSRC netinet6 | |
rump_server_start $SOCKDST netinet6 | |
setup_dst_server | |
setup_src_server | |
$DEBUG && rump.netstat -nr -f inet6 | |
atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST | |
atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST | |
# Shutdown the interface | |
atf_check -s exit:0 rump.ifconfig shmif0 down | |
$DEBUG && rump.netstat -nr -f inet6 | |
$DEBUG && rump.ndp -na | |
# The entry was already removed on ifconfig down | |
atf_check -s not-exit:0 -o ignore -e match:'no entry' \ | |
rump.ndp -n $IP6DST | |
rump_server_destroy_ifaces | |
} | |
ndp_purge_on_ifdown_cleanup() | |
{ | |
$DEBUG && dump | |
cleanup | |
} | |
atf_test_case ndp_stray_entries cleanup | |
ndp_stray_entries_head() | |
{ | |
atf_set "descr" "Tests if NDP entries are removed on route change" | |
atf_set "require.progs" "rump_server" | |
} | |
ndp_stray_entries_body() | |
{ | |
rump_server_start $SOCKSRC netinet6 | |
rump_server_start $SOCKDST netinet6 | |
setup_dst_server | |
setup_src_server | |
rump_server_add_iface $SOCKSRC shmif1 bus1 | |
export RUMP_SERVER=$SOCKSRC | |
atf_check -s exit:0 rump.ifconfig shmif1 inet6 $IP6SRC2/64 | |
atf_check -s exit:0 rump.ifconfig -w 10 | |
$DEBUG && rump.netstat -nr -f inet6 | |
atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST | |
$DEBUG && rump.ndp -na | |
atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST | |
atf_check -s exit:0 -o not-match:'shmif1' rump.ndp -n $IP6DST | |
# Clean up | |
atf_check -s exit:0 -o ignore rump.ndp -c | |
atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6DST | |
# ping from a different source address | |
atf_check -s exit:0 -o ignore \ | |
rump.ping6 -n -X 1 -c 1 -S $IP6SRC2 $IP6DST | |
$DEBUG && rump.ndp -na | |
atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST | |
# ARP reply goes back via shmif1, so a cache is created on shmif1 | |
atf_check -s exit:0 -o match:'shmif1' rump.ndp -n $IP6DST | |
# Clean up by ndp -c | |
atf_check -s exit:0 -o ignore rump.ndp -c | |
atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6DST | |
# ping from a different source address again | |
atf_check -s exit:0 -o ignore \ | |
rump.ping6 -n -X 1 -c 1 -S $IP6SRC2 $IP6DST | |
atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST | |
# ARP reply doen't come | |
atf_check -s exit:0 -o not-match:'shmif1' rump.ndp -n $IP6DST | |
# Cleanup caches on the destination | |
export RUMP_SERVER=$SOCKDST | |
$DEBUG && rump.ndp -na | |
atf_check -s exit:0 -o ignore rump.ndp -c | |
$DEBUG && rump.ndp -na | |
export RUMP_SERVER=$SOCKSRC | |
# ping from a different source address again | |
atf_check -s exit:0 -o ignore \ | |
rump.ping6 -n -X 1 -c 1 -S $IP6SRC2 $IP6DST | |
atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST | |
# ARP reply goes back via shmif1 | |
atf_check -s exit:0 -o match:'shmif1' rump.ndp -n $IP6DST | |
# Clean up by ndp -d <ip> | |
atf_check -s exit:0 -o ignore rump.ndp -d $IP6DST | |
# Both entries should be deleted | |
atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6DST | |
rump_server_destroy_ifaces | |
} | |
ndp_stray_entries_cleanup() | |
{ | |
$DEBUG && dump | |
cleanup | |
} | |
atf_test_case ndp_cache_state cleanup | |
ndp_cache_state_head() | |
{ | |
atf_set "descr" "Tests states of neighbor cache entries" | |
atf_set "require.progs" "rump_server" | |
} | |
check_cache_state() | |
{ | |
local dst=$1 | |
local state=$2 | |
$DEBUG && rump.ndp -n $dst | |
atf_check -s exit:0 -o match:"^$dst.*$state " rump.ndp -n $dst | |
} | |
wait_until_stalled() | |
{ | |
local dst=$1 | |
local state=$2 | |
$DEBUG && rump.ndp -n $dst | |
while true; do | |
rump.ndp -n $dst | grep -q "^$dst.*S " && break | |
sleep 1 | |
done | |
$DEBUG && rump.ndp -n $dst | |
} | |
ndp_cache_state_body() | |
{ | |
local macaddr= | |
rump_server_start $SOCKSRC netinet6 | |
rump_server_start $SOCKDST netinet6 | |
setup_dst_server | |
setup_src_server | |
# Shorten the expire time of cache entries | |
export RUMP_SERVER=$SOCKSRC | |
atf_check -s exit:0 -o match:'basereachable=7s0ms' \ | |
rump.ndp -i shmif0 basereachable=7000 | |
# Make a permanent cache entry to avoid sending an NS packet disturbing | |
# the test | |
macaddr=$(get_macaddr $SOCKSRC shmif0) | |
export RUMP_SERVER=$SOCKDST | |
atf_check -s exit:0 -o ignore rump.ndp -s $IP6SRC $macaddr | |
export RUMP_SERVER=$SOCKSRC | |
# | |
# Reachability confirmation (RFC 4861 7.3.3) | |
# | |
atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST | |
# Receiving a solicited NA packet changes the state of the cache to REACHABLE | |
check_cache_state $IP6DST R | |
# The state of the cache transits to STALE after a while | |
wait_until_stalled $IP6DST | |
# Sending a packet on the cache will run a reachability confirmation | |
atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST | |
sleep 1 | |
# The state of the cache is changed to DELAY and stay for 5s, then | |
# send a NS packet and change the state to PROBE | |
check_cache_state $IP6DST D | |
sleep $((5 + 1)) | |
# If the reachability confirmation is success, the state of the cache | |
# is changed to REACHABLE | |
check_cache_state $IP6DST R | |
} | |
ndp_cache_state_cleanup() | |
{ | |
$DEBUG && dump | |
cleanup | |
} | |
atf_init_test_cases() | |
{ | |
atf_add_test_case ndp_cache_expiration | |
atf_add_test_case ndp_commands | |
atf_add_test_case ndp_cache_overwriting | |
atf_add_test_case ndp_neighborgcthresh | |
atf_add_test_case ndp_link_activation | |
atf_add_test_case ndp_rtm | |
atf_add_test_case ndp_purge_on_route_change | |
atf_add_test_case ndp_purge_on_route_delete | |
atf_add_test_case ndp_purge_on_ifdown | |
atf_add_test_case ndp_stray_entries | |
atf_add_test_case ndp_cache_state | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment