1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
|
AT_TESTED([ovs-vswitchd])
AT_TESTED([ovs-vsctl])
m4_include([m4/compat.m4])
dnl Make AT_SETUP automatically run the ovs_init() shell function
dnl as the first step in every test.
m4_rename([AT_SETUP], [OVS_AT_SETUP])
m4_define([AT_SETUP], [OVS_AT_SETUP($@)
ovs_init
])
dnl Make AT_CLEANUP check for Address Sanitizer errors as the last step
dnl in every test.
m4_rename([AT_CLEANUP], [OVS_AT_CLEANUP])
m4_define([AT_CLEANUP], [ovs_cleanup
OVS_AT_CLEANUP($@)
])
dnl OVS_START_SHELL_HELPERS...OVS_END_SHELL_HELPERS may bracket shell
dnl function definitions that invoke AT_CHECK and other Autotest macros
dnl that can ordinarily be run only within AT_SETUP...AT_CLEANUP.
m4_define([OVS_START_SHELL_HELPERS],
[m4_ifdef([AT_ingroup], [m4_fatal([$0: AT_SETUP and OVS_DEFINE_SHELL_HELPERS may not nest])])
m4_define([AT_ingroup])
m4_divert_push([PREPARE_TESTS])])
m4_define([OVS_END_SHELL_HELPERS], [
m4_divert_pop([PREPARE_TESTS])
m4_undefine([AT_ingroup])])
m4_divert_push([PREPARE_TESTS])
[
# Set ovs_base to the base directory in which the test is running and
# initialize the OVS_*DIR environment variables to point to this
# directory.
ovs_init() {
ovs_base=`pwd`
trap ovs_on_exit 0
: > cleanup
ovs_setenv
}
# Catch testsuite error condition and cleanup test environment by tearing down
# all interfaces and processes spawned.
# User has an option to leave the test environment in error state so that system
# can be poked around to get more information. User can enable this option by setting
# environment variable OVS_PAUSE_TEST=1. User needs to press CTRL-D to resume the
# cleanup operation.
ovs_pause() {
echo "====================================================="
echo "Set following environment variable to use various ovs utilities"
echo "export OVS_RUNDIR=$ovs_base"
echo "Press ENTER to continue: "
read
}
ovs_on_exit () {
if [ ! -z "${OVS_PAUSE_TEST}" ] && [ -z $at_verbose ]; then
trap '' INT
ovs_pause
fi
. "$ovs_base/cleanup"
}
# With no parameter or an empty parameter, sets the OVS_*DIR
# environment variables to point to $ovs_base, the base directory in
# which the test is running.
#
# With a parameter, sets them to $ovs_base/$1.
ovs_setenv() {
sandbox=$1
ovs_dir=$ovs_base${1:+/$1}
OVS_RUNDIR=$ovs_dir; export OVS_RUNDIR
OVS_LOGDIR=$ovs_dir; export OVS_LOGDIR
OVS_DBDIR=$ovs_dir; export OVS_DBDIR
OVS_SYSCONFDIR=$ovs_dir; export OVS_SYSCONFDIR
OVS_PKGDATADIR=$ovs_dir; export OVS_PKGDATADIR
}
# Prints the integers from $1 to $2, increasing by $3 (default 1) on stdout.
seq () {
if test $# = 1; then
set 1 $1
fi
while test $1 -le $2; do
echo $1
set `expr $1 + ${3-1}` $2 $3
done
}
if test "$IS_WIN32" = "yes"; then
pwd () {
command pwd -W "$@"
}
diff () {
command diff --strip-trailing-cr "$@"
}
# tskill is more effective than taskkill but it isn't always installed.
if (tskill //?) >/dev/null 2>&1; then :; else
tskill () { taskkill //F //PID $1 >/dev/null; }
fi
kill () {
signal=
retval=0
for arg; do
arg=$(echo $arg | tr -d '\n\r')
case $arg in
-*) signal=$arg ;;
[1-9][0-9]*)
# tasklist always returns 0.
# If pid does exist, there will be a line with the pid.
if tasklist //fi "PID eq $arg" | grep $arg >/dev/null; then
if test "X$signal" != "X-0"; then
tskill $arg
fi
else
retval=1
fi
;;
esac
done
return $retval
}
fi
# parent_pid PID
#
# Prints the PID of the parent of process PID.
parent_pid () {
# Using "ps" is portable to any POSIX system, but busybox "ps" (used in
# e.g. Alpine Linux) is noncompliant, so we use a Linux-specific approach
# when it's available. We check the format of the status file to avoid
# the NetBSD file with the same name but different contents.
if grep -E '^PPid:[[:space:]]*[0-9]*$' /proc/$1/status > /dev/null 2>&1; then
sed -n 's/^PPid: \([0-9]*\)/\1/p' /proc/$1/status
else
ps -o ppid= -p $1
fi
}
# kill_ovs_vswitchd [PID]
#
# Signal the ovs-vswitchd daemon to exit gracefully and wait for it to
# terminate or kill it if that takes too long.
#
# It is used to cleanup all sorts of tests and results. It can't assume
# any state, including the availability of PID file which can be provided.
kill_ovs_vswitchd () {
# Use provided PID or save the current PID if available.
TMPPID=$1
if test -z "$TMPPID"; then
TMPPID=$(cat $OVS_RUNDIR/ovs-vswitchd.pid 2>/dev/null)
fi
# Tell the daemon to terminate gracefully
ovs-appctl -t ovs-vswitchd exit --cleanup 2>/dev/null
# Nothing else to be done if there is no PID
test -z "$TMPPID" && return
for i in 1 2 3 4 5 6 7 8 9; do
# Check if the daemon is alive.
kill -0 $TMPPID 2>/dev/null || return
# Fallback to whole number since POSIX doesn't require
# fractional times to work.
sleep 0.1 || sleep 1
done
# Make sure it is terminated.
kill $TMPPID
}
# Normalize the output of 'wc' to match POSIX.
# POSIX says 'wc' should print "%d %d %d", but GNU prints "%7d %7d %7d".
# POSIX says 'wc -l' should print "%d %s", but BSD prints "%8d".
#
# This fixes all of those (it will screw up filenames that contain
# multiple sequential spaces, but that doesn't really matter).
wc () {
command wc "$@" | tr -s ' ' ' ' | sed 's/^ *//'
}
uuidfilt () {
$PYTHON3 "$top_srcdir"/tests/uuidfilt.py "$@"
}
# run_as PROGRAM_NAME COMMAND [ARG...]
#
# Runs a command with argv[0] set to PROGRAM_NAME, if possible, in a
# subshell. Most utilities print argc[0] as part of their messages,
# so this makes it easier to figure out which particular utility
# prints a message if a bunch of identical processes are running.
#
# Not all shells support "exec -a NAME", so test for it.
if (exec -a myname true 2>/dev/null); then
run_as () {
(exec -a "$@")
}
else
run_as () {
shift
(exec "$@")
}
fi
]
m4_divert_pop([PREPARE_TESTS])
OVS_START_SHELL_HELPERS
ovs_cleanup() {
if test "$(echo sanitizers.*)" != 'sanitizers.*'; then
echo "Undefined Behavior Sanitizer or Address Sanitizer reported errors in:" sanitizers.*
cat sanitizers.*
AT_FAIL_IF([:])
fi
}
ovs_wait () {
echo "$1: waiting $2..." >&AS_MESSAGE_LOG_FD
# First try the condition without waiting.
if ovs_wait_cond; then echo "$1: wait succeeded immediately" >&AS_MESSAGE_LOG_FD; return 0; fi
# Try a quick sleep, so that the test completes very quickly
# in the normal case. POSIX doesn't require fractional times to
# work, so this might not work.
sleep 0.1
if ovs_wait_cond; then echo "$1: wait succeeded quickly" >&AS_MESSAGE_LOG_FD; return 0; fi
# Then wait up to OVS_CTL_TIMEOUT seconds.
local d
for d in `seq 1 "$OVS_CTL_TIMEOUT"`; do
sleep 1
if ovs_wait_cond; then echo "$1: wait succeeded after $d seconds" >&AS_MESSAGE_LOG_FD; return 0; fi
done
echo "$1: wait failed after $d seconds" >&AS_MESSAGE_LOG_FD
ovs_wait_failed
AT_FAIL_IF([:])
}
OVS_END_SHELL_HELPERS
m4_define([OVS_WAIT], [dnl
ovs_wait_cond () {
$1
}
ovs_wait_failed () {
:
$2
}
ovs_wait "AS_ESCAPE([$3])" "AS_ESCAPE([$4])"
])
dnl OVS_WAIT_UNTIL(COMMAND, [IF-FAILED])
dnl
dnl Executes shell COMMAND in a loop until it returns zero. If COMMAND does
dnl not return zero within a reasonable time limit, executes the commands
dnl in IF-FAILED (if provided) and fails the test.
m4_define([OVS_WAIT_UNTIL],
[AT_FAIL_IF([test "$#" -ge 3])
dnl The second argument should not be a number (confused with AT_CHECK ?).
AT_FAIL_IF([test "$#" -eq 2 && test "$2" -eq "$2" 2>/dev/null])
OVS_WAIT([$1], [$2], [AT_LINE], [until $1])])
dnl OVS_WAIT_UNTIL_EQUAL(COMMAND, OUTPUT)
dnl
dnl Executes shell COMMAND in a loop until it returns zero and the output
dnl equals OUTPUT. If COMMAND does not return zero or a desired output within
dnl a reasonable time limit, fails the test.
m4_define([OVS_WAIT_UNTIL_EQUAL],
[AT_FAIL_IF([test "$#" -ge 3])
echo "$2" > wait_until_expected
OVS_WAIT_UNTIL([$1 | diff -u wait_until_expected - ])])
dnl OVS_WAIT_WHILE(COMMAND, [IF-FAILED])
dnl
dnl Executes shell COMMAND in a loop until it returns nonzero. If COMMAND does
dnl not return nonzero within a reasonable time limit, executes the commands
dnl in IF-FAILED (if provided) and fails the test.
m4_define([OVS_WAIT_WHILE],
[AT_FAIL_IF([test "$#" -ge 3])
dnl The second argument should not be a number (confused with AT_CHECK ?).
AT_FAIL_IF([test "$#" -eq 2 && test "$2" -eq "$2" 2>/dev/null])
OVS_WAIT([if $1; then return 1; else return 0; fi], [$2],
[AT_LINE], [while $1])])
dnl OVS_APP_EXIT_AND_WAIT(DAEMON)
dnl
dnl Ask the daemon named DAEMON to exit, via ovs-appctl, and then wait for it
dnl to exit.
m4_define([OVS_APP_EXIT_AND_WAIT],
[AT_CHECK([test -e $OVS_RUNDIR/$1.pid])
TMPPID=$(cat $OVS_RUNDIR/$1.pid)
AT_CHECK(m4_if([$1],[ovs-vswitchd],
[ovs-appctl -t $1 exit --cleanup],
[ovs-appctl -t $1 exit]))
OVS_WAIT_WHILE([kill -0 $TMPPID 2>/dev/null])])
dnl OVS_APP_EXIT_AND_WAIT_BY_TARGET(TARGET, PIDFILE)
dnl
dnl Ask the daemon identified by TARGET to exit, via ovs-appctl (using the target
dnl argument), and then wait for it to exit.
m4_define([OVS_APP_EXIT_AND_WAIT_BY_TARGET],
[AT_CHECK([test -e $2])
TMPPID=$(cat $2)
AT_CHECK([ovs-appctl --target=$1 exit])
OVS_WAIT_WHILE([kill -0 $TMPPID 2>/dev/null])])
dnl OVS_DAEMONIZE([command], [pidfile])
dnl
dnl Run 'command' as a background process and record its pid to 'pidfile' to
dnl allow cleanup on exit.
m4_define([OVS_DAEMONIZE],
[$1 & echo $! > $2
on_exit "kill `cat $2`"
])
dnl on_exit "COMMAND"
dnl
dnl Add the shell COMMAND to a collection executed when the current test
dnl completes, as a cleanup action. (The most common use is to kill a
dnl daemon started by the test. This is important to prevent tests that
dnl start daemons from hanging at exit.)
dnl
dnl Cleanup commands are executed in the reverse order of calls to this
dnl function.
m4_divert_text([PREPARE_TESTS], [dnl
on_exit () {
(echo "$1"; cat cleanup) > cleanup.tmp
mv cleanup.tmp cleanup
}
])
dnl Autoconf 2.63 compatibility verison of macro introduced in Autoconf 2.64:
m4_ifndef([AS_VAR_APPEND],
[m4_divert_text([PREPARE_TESTS],
[as_var_append () {
eval $1=\$$1\$2
}
])
m4_define([AS_VAR_APPEND], [as_var_append $1 $2])])
dnl Autoconf 2.63 compatibility verison of macro introduced in Autoconf 2.64:
m4_ifndef([AT_CHECK_UNQUOTED],
[m4_define([AT_CHECK_UNQUOTED],
[_AT_CHECK([$1], [$2], AS_ESCAPE(m4_dquote(m4_expand([$3])), [""]),
AS_ESCAPE(m4_dquote(m4_expand([$4])),[""]), [$5], [$6])])])
dnl Autoconf 2.63 compatibility verison of macro introduced in Autoconf 2.64:
m4_ifndef([AT_SKIP_IF],
[m4_define([AT_SKIP_IF],
[AT_CHECK([($1) \
&& exit 77 || exit 0], [0], [ignore], [ignore])])])
dnl Autoconf 2.63 compatibility verison of macro introduced in Autoconf 2.64:
m4_ifndef([AT_FAIL_IF],
[m4_define([AT_FAIL_IF],
[AT_CHECK([($1) \
&& exit 99 || exit 0], [0], [ignore], [ignore])])])
dnl Start retis to track all the traffic passing through OVS.
m4_define([RETIS_CHECK_AND_RUN],
[if test "$OVS_TEST_WITH_RETIS" = yes && retis --version > /dev/null; then
on_exit 'retis sort --utc retis.data > retis.sorted'
OVS_DAEMONIZE([retis -p ifdump collect --utc --allow-system-changes \
--ovs-track --out --print 2>retis.err 1>retis.log],
[retis.pid])
OVS_WAIT_UNTIL([grep -q 'loaded' retis.err])
fi])
dnl Add a rule to always accept the traffic.
dnl The first argument to this macro should be the command to run:
dnl iptables or ip6tables
dnl The second argument to this macro should be the interface name (netdev)
m4_define([IPTABLES_ACCEPT],
[AT_CHECK([$1 -I INPUT 1 -i $2 -j ACCEPT])
on_exit '$1 -D INPUT 1'])
dnl Certain Linux distributions, like CentOS, have default iptable rules
dnl to reject input traffic from bridges such as br-underlay.
dnl This implies the existence of a ip filter INPUT chain for IPv4 or an
dnl ip6 filter INPUT chain for IPv6. If that chain exists then add a rule
dnl to it to always accept all traffic.
dnl The first argument to this macro should be the filter chain: ip or ipv6
dnl The second argument to this macro should be the interface name (netdev)
m4_define([NFT_ACCEPT],
[if nft list chain $1 filter INPUT > /dev/null 2>1; then
AT_CHECK([nft -ae \
"insert rule $1 filter INPUT iifname \"$2\" counter accept"],
[0], [stdout-nolog])
dnl Extract handle, which is used to delete the rule
AT_CHECK([sed -n 's/.*handle //; T; p' < stdout], [0], [stdout])
on_exit "nft \"delete rule $1 filter INPUT handle $(cat stdout)\""
fi])
dnl Certain Linux distributions, like CentOS, have default iptable rules
dnl to reject input traffic from bridges such as br-underlay.
dnl Add a rule to always accept the traffic.
dnl IPv4 variant of this macro.
m4_define([XT_ACCEPT],
[if test $HAVE_NFT = yes; then
NFT_ACCEPT([ip], [$1])
else
IPTABLES_ACCEPT([iptables], [$1])
fi])
dnl Certain Linux distributions, like CentOS, have default iptable rules
dnl to reject input traffic from bridges such as br-underlay.
dnl Add a rule to always accept the traffic.
dnl IPv6 variant of this macro.
m4_define([XT6_ACCEPT],
[if test $HAVE_NFT = yes; then
NFT_ACCEPT([ip6], [$1])
else
IPTABLES_ACCEPT([ip6tables], [$1])
fi])
|