Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'selftests-vsock-refactor-and-improve-vmtest-infrastructure'

Bobby Eshleman says:

====================
selftests/vsock: refactor and improve vmtest infrastructure

This patch series refactors the vsock selftest VM infrastructure to
improve test run times, improve logging, and prepare for future tests
which make heavy usage of these refactored functions and have new
requirements such as simultaneous QEMU processes.
====================

Link: https://patch.msgid.link/20251108-vsock-selftests-fixes-and-improvements-v4-0-d5e8d6c87289@meta.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+235 -115
+235 -115
tools/testing/selftests/vsock/vmtest.sh
··· 7 7 # * virtme-ng 8 8 # * busybox-static (used by virtme-ng) 9 9 # * qemu (used by virtme-ng) 10 + # 11 + # shellcheck disable=SC2317,SC2119 10 12 11 13 readonly SCRIPT_DIR="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" 12 14 readonly KERNEL_CHECKOUT=$(realpath "${SCRIPT_DIR}"/../../../../) ··· 24 22 readonly VSOCK_CID=1234 25 23 readonly WAIT_PERIOD=3 26 24 readonly WAIT_PERIOD_MAX=60 27 - readonly WAIT_TOTAL=$(( WAIT_PERIOD * WAIT_PERIOD_MAX )) 28 - readonly QEMU_PIDFILE=$(mktemp /tmp/qemu_vsock_vmtest_XXXX.pid) 25 + readonly WAIT_QEMU=5 26 + readonly PIDFILE_TEMPLATE=/tmp/vsock_vmtest_XXXX.pid 27 + declare -A PIDFILES 29 28 30 29 # virtme-ng offers a netdev for ssh when using "--ssh", but we also need a 31 30 # control port forwarded for vsock_test. Because virtme-ng doesn't support ··· 36 33 # add the kernel cmdline options that virtme-init uses to setup the interface. 37 34 readonly QEMU_TEST_PORT_FWD="hostfwd=tcp::${TEST_HOST_PORT}-:${TEST_GUEST_PORT}" 38 35 readonly QEMU_SSH_PORT_FWD="hostfwd=tcp::${SSH_HOST_PORT}-:${SSH_GUEST_PORT}" 39 - readonly QEMU_OPTS="\ 40 - -netdev user,id=n0,${QEMU_TEST_PORT_FWD},${QEMU_SSH_PORT_FWD} \ 41 - -device virtio-net-pci,netdev=n0 \ 42 - -device vhost-vsock-pci,guest-cid=${VSOCK_CID} \ 43 - --pidfile ${QEMU_PIDFILE} \ 44 - " 45 36 readonly KERNEL_CMDLINE="\ 46 37 virtme.dhcp net.ifnames=0 biosdevname=0 \ 47 38 virtme.ssh virtme_ssh_channel=tcp virtme_ssh_user=$USER \ ··· 47 50 "Run vsock_test in client mode on the VM and in server mode on the host." 48 51 "Run vsock_test using the loopback transport in the VM." 49 52 ) 53 + 54 + readonly USE_SHARED_VM=(vm_server_host_client vm_client_host_server vm_loopback) 50 55 51 56 VERBOSE=0 52 57 ··· 83 84 exit "${KSFT_FAIL}" 84 85 } 85 86 87 + check_result() { 88 + local rc arg 89 + 90 + rc=$1 91 + arg=$2 92 + 93 + cnt_total=$(( cnt_total + 1 )) 94 + 95 + if [[ ${rc} -eq ${KSFT_PASS} ]]; then 96 + cnt_pass=$(( cnt_pass + 1 )) 97 + echo "ok ${cnt_total} ${arg}" 98 + elif [[ ${rc} -eq ${KSFT_SKIP} ]]; then 99 + cnt_skip=$(( cnt_skip + 1 )) 100 + echo "ok ${cnt_total} ${arg} # SKIP" 101 + elif [[ ${rc} -eq ${KSFT_FAIL} ]]; then 102 + cnt_fail=$(( cnt_fail + 1 )) 103 + echo "not ok ${cnt_total} ${arg} # exit=${rc}" 104 + fi 105 + } 106 + 86 107 vm_ssh() { 87 108 ssh -q -o UserKnownHostsFile=/dev/null -p ${SSH_HOST_PORT} localhost "$@" 88 109 return $? 89 110 } 90 111 91 112 cleanup() { 92 - if [[ -s "${QEMU_PIDFILE}" ]]; then 93 - pkill -SIGTERM -F "${QEMU_PIDFILE}" > /dev/null 2>&1 94 - fi 95 - 96 - # If failure occurred during or before qemu start up, then we need 97 - # to clean this up ourselves. 98 - if [[ -e "${QEMU_PIDFILE}" ]]; then 99 - rm "${QEMU_PIDFILE}" 100 - fi 113 + terminate_pidfiles "${!PIDFILES[@]}" 101 114 } 102 115 103 116 check_args() { ··· 158 147 local version 159 148 local ok 160 149 161 - tested_versions=("1.33" "1.36") 150 + tested_versions=("1.33" "1.36" "1.37") 162 151 version="$(vng --version)" 163 152 164 153 ok=0 ··· 199 188 popd &>/dev/null 200 189 } 201 190 191 + create_pidfile() { 192 + local pidfile 193 + 194 + pidfile=$(mktemp "${PIDFILE_TEMPLATE}") 195 + PIDFILES["${pidfile}"]=1 196 + 197 + echo "${pidfile}" 198 + } 199 + 200 + terminate_pidfiles() { 201 + local pidfile 202 + 203 + for pidfile in "$@"; do 204 + if [[ -s "${pidfile}" ]]; then 205 + pkill -SIGTERM -F "${pidfile}" > /dev/null 2>&1 206 + fi 207 + 208 + if [[ -e "${pidfile}" ]]; then 209 + rm -f "${pidfile}" 210 + fi 211 + 212 + unset "PIDFILES[${pidfile}]" 213 + done 214 + } 215 + 202 216 vm_start() { 217 + local pidfile=$1 203 218 local logfile=/dev/null 204 219 local verbose_opt="" 205 220 local kernel_opt="" 221 + local qemu_opts="" 206 222 local qemu 207 223 208 224 qemu=$(command -v "${QEMU}") ··· 239 201 logfile=/dev/stdout 240 202 fi 241 203 204 + qemu_opts="\ 205 + -netdev user,id=n0,${QEMU_TEST_PORT_FWD},${QEMU_SSH_PORT_FWD} \ 206 + -device virtio-net-pci,netdev=n0 \ 207 + -device vhost-vsock-pci,guest-cid=${VSOCK_CID} \ 208 + --pidfile ${pidfile} 209 + " 210 + 242 211 if [[ "${BUILD}" -eq 1 ]]; then 243 212 kernel_opt="${KERNEL_CHECKOUT}" 244 213 fi ··· 254 209 --run \ 255 210 ${kernel_opt} \ 256 211 ${verbose_opt} \ 257 - --qemu-opts="${QEMU_OPTS}" \ 212 + --qemu-opts="${qemu_opts}" \ 258 213 --qemu="${qemu}" \ 259 214 --user root \ 260 215 --append "${KERNEL_CMDLINE}" \ 261 216 --rw &> ${logfile} & 262 217 263 - if ! timeout ${WAIT_TOTAL} \ 264 - bash -c 'while [[ ! -s '"${QEMU_PIDFILE}"' ]]; do sleep 1; done; exit 0'; then 265 - die "failed to boot VM" 266 - fi 218 + timeout "${WAIT_QEMU}" \ 219 + bash -c 'while [[ ! -s '"${pidfile}"' ]]; do sleep 1; done; exit 0' 267 220 } 268 221 269 222 vm_wait_for_ssh() { ··· 294 251 295 252 # for tcp protocol additionally check the socket state 296 253 [ "${protocol}" = "tcp" ] && pattern="${pattern}0A" 254 + 297 255 for i in $(seq "${max_intervals}"); do 298 - if awk '{print $2" "$4}' /proc/net/"${protocol}"* | \ 299 - grep -q "${pattern}"; then 256 + if awk -v pattern="${pattern}" \ 257 + 'BEGIN {rc=1} $2" "$4 ~ pattern {rc=0} END {exit rc}' \ 258 + /proc/net/"${protocol}"*; then 300 259 break 301 260 fi 302 261 sleep "${interval}" ··· 315 270 } 316 271 317 272 host_wait_for_listener() { 318 - wait_for_listener "${TEST_HOST_PORT_LISTENER}" "${WAIT_PERIOD}" "${WAIT_PERIOD_MAX}" 273 + local port=$1 274 + 275 + wait_for_listener "${port}" "${WAIT_PERIOD}" "${WAIT_PERIOD_MAX}" 319 276 } 320 277 321 - __log_stdin() { 322 - cat | awk '{ printf "%s:\t%s\n","'"${prefix}"'", $0 }' 278 + vm_vsock_test() { 279 + local host=$1 280 + local cid=$2 281 + local port=$3 282 + local rc 283 + 284 + # log output and use pipefail to respect vsock_test errors 285 + set -o pipefail 286 + if [[ "${host}" != server ]]; then 287 + vm_ssh -- "${VSOCK_TEST}" \ 288 + --mode=client \ 289 + --control-host="${host}" \ 290 + --peer-cid="${cid}" \ 291 + --control-port="${port}" \ 292 + 2>&1 | log_guest 293 + rc=$? 294 + else 295 + vm_ssh -- "${VSOCK_TEST}" \ 296 + --mode=server \ 297 + --peer-cid="${cid}" \ 298 + --control-port="${port}" \ 299 + 2>&1 | log_guest & 300 + rc=$? 301 + 302 + if [[ $rc -ne 0 ]]; then 303 + set +o pipefail 304 + return $rc 305 + fi 306 + 307 + vm_wait_for_listener "${port}" 308 + rc=$? 309 + fi 310 + set +o pipefail 311 + 312 + return $rc 323 313 } 324 314 325 - __log_args() { 326 - echo "$*" | awk '{ printf "%s:\t%s\n","'"${prefix}"'", $0 }' 315 + host_vsock_test() { 316 + local host=$1 317 + local cid=$2 318 + local port=$3 319 + local rc 320 + 321 + # log output and use pipefail to respect vsock_test errors 322 + set -o pipefail 323 + if [[ "${host}" != server ]]; then 324 + ${VSOCK_TEST} \ 325 + --mode=client \ 326 + --peer-cid="${cid}" \ 327 + --control-host="${host}" \ 328 + --control-port="${port}" 2>&1 | log_host 329 + rc=$? 330 + else 331 + ${VSOCK_TEST} \ 332 + --mode=server \ 333 + --peer-cid="${cid}" \ 334 + --control-port="${port}" 2>&1 | log_host & 335 + rc=$? 336 + 337 + if [[ $rc -ne 0 ]]; then 338 + set +o pipefail 339 + return $rc 340 + fi 341 + 342 + host_wait_for_listener "${port}" 343 + rc=$? 344 + fi 345 + set +o pipefail 346 + 347 + return $rc 327 348 } 328 349 329 350 log() { 330 - local prefix="$1" 351 + local redirect 352 + local prefix 331 353 332 - shift 333 - local redirect= 334 354 if [[ ${VERBOSE} -eq 0 ]]; then 335 355 redirect=/dev/null 336 356 else 337 357 redirect=/dev/stdout 338 358 fi 339 359 340 - if [[ "$#" -eq 0 ]]; then 341 - __log_stdin | tee -a "${LOG}" > ${redirect} 342 - else 343 - __log_args "$@" | tee -a "${LOG}" > ${redirect} 344 - fi 345 - } 360 + prefix="${LOG_PREFIX:-}" 346 361 347 - log_setup() { 348 - log "setup" "$@" 362 + if [[ "$#" -eq 0 ]]; then 363 + if [[ -n "${prefix}" ]]; then 364 + awk -v prefix="${prefix}" '{printf "%s: %s\n", prefix, $0}' 365 + else 366 + cat 367 + fi 368 + else 369 + if [[ -n "${prefix}" ]]; then 370 + echo "${prefix}: " "$@" 371 + else 372 + echo "$@" 373 + fi 374 + fi | tee -a "${LOG}" > "${redirect}" 349 375 } 350 376 351 377 log_host() { 352 - local testname=$1 353 - 354 - shift 355 - log "test:${testname}:host" "$@" 378 + LOG_PREFIX=host log "$@" 356 379 } 357 380 358 381 log_guest() { 359 - local testname=$1 360 - 361 - shift 362 - log "test:${testname}:guest" "$@" 382 + LOG_PREFIX=guest log "$@" 363 383 } 364 384 365 385 test_vm_server_host_client() { 366 - local testname="${FUNCNAME[0]#test_}" 386 + if ! vm_vsock_test "server" 2 "${TEST_GUEST_PORT}"; then 387 + return "${KSFT_FAIL}" 388 + fi 367 389 368 - vm_ssh -- "${VSOCK_TEST}" \ 369 - --mode=server \ 370 - --control-port="${TEST_GUEST_PORT}" \ 371 - --peer-cid=2 \ 372 - 2>&1 | log_guest "${testname}" & 390 + if ! host_vsock_test "127.0.0.1" "${VSOCK_CID}" "${TEST_HOST_PORT}"; then 391 + return "${KSFT_FAIL}" 392 + fi 373 393 374 - vm_wait_for_listener "${TEST_GUEST_PORT}" 375 - 376 - ${VSOCK_TEST} \ 377 - --mode=client \ 378 - --control-host=127.0.0.1 \ 379 - --peer-cid="${VSOCK_CID}" \ 380 - --control-port="${TEST_HOST_PORT}" 2>&1 | log_host "${testname}" 381 - 382 - return $? 394 + return "${KSFT_PASS}" 383 395 } 384 396 385 397 test_vm_client_host_server() { 386 - local testname="${FUNCNAME[0]#test_}" 398 + if ! host_vsock_test "server" "${VSOCK_CID}" "${TEST_HOST_PORT_LISTENER}"; then 399 + return "${KSFT_FAIL}" 400 + fi 387 401 388 - ${VSOCK_TEST} \ 389 - --mode "server" \ 390 - --control-port "${TEST_HOST_PORT_LISTENER}" \ 391 - --peer-cid "${VSOCK_CID}" 2>&1 | log_host "${testname}" & 402 + if ! vm_vsock_test "10.0.2.2" 2 "${TEST_HOST_PORT_LISTENER}"; then 403 + return "${KSFT_FAIL}" 404 + fi 392 405 393 - host_wait_for_listener 394 - 395 - vm_ssh -- "${VSOCK_TEST}" \ 396 - --mode=client \ 397 - --control-host=10.0.2.2 \ 398 - --peer-cid=2 \ 399 - --control-port="${TEST_HOST_PORT_LISTENER}" 2>&1 | log_guest "${testname}" 400 - 401 - return $? 406 + return "${KSFT_PASS}" 402 407 } 403 408 404 409 test_vm_loopback() { 405 - local testname="${FUNCNAME[0]#test_}" 406 410 local port=60000 # non-forwarded local port 407 411 408 - vm_ssh -- "${VSOCK_TEST}" \ 409 - --mode=server \ 410 - --control-port="${port}" \ 411 - --peer-cid=1 2>&1 | log_guest "${testname}" & 412 + vm_ssh -- modprobe vsock_loopback &> /dev/null || : 412 413 413 - vm_wait_for_listener "${port}" 414 + if ! vm_vsock_test "server" 1 "${port}"; then 415 + return "${KSFT_FAIL}" 416 + fi 414 417 415 - vm_ssh -- "${VSOCK_TEST}" \ 416 - --mode=client \ 417 - --control-host="127.0.0.1" \ 418 - --control-port="${port}" \ 419 - --peer-cid=1 2>&1 | log_guest "${testname}" 418 + if ! vm_vsock_test "127.0.0.1" 1 "${port}"; then 419 + return "${KSFT_FAIL}" 420 + fi 420 421 421 - return $? 422 + return "${KSFT_PASS}" 422 423 } 423 424 424 - run_test() { 425 + shared_vm_test() { 426 + local tname 427 + 428 + tname="${1}" 429 + 430 + for testname in "${USE_SHARED_VM[@]}"; do 431 + if [[ "${tname}" == "${testname}" ]]; then 432 + return 0 433 + fi 434 + done 435 + 436 + return 1 437 + } 438 + 439 + shared_vm_tests_requested() { 440 + for arg in "$@"; do 441 + if shared_vm_test "${arg}"; then 442 + return 0 443 + fi 444 + done 445 + 446 + return 1 447 + } 448 + 449 + run_shared_vm_tests() { 450 + local arg 451 + 452 + for arg in "$@"; do 453 + if ! shared_vm_test "${arg}"; then 454 + continue 455 + fi 456 + 457 + run_shared_vm_test "${arg}" 458 + check_result "$?" "${arg}" 459 + done 460 + } 461 + 462 + run_shared_vm_test() { 425 463 local host_oops_cnt_before 426 464 local host_warn_cnt_before 427 465 local vm_oops_cnt_before ··· 527 399 528 400 host_oops_cnt_after=$(dmesg | grep -i 'Oops' | wc -l) 529 401 if [[ ${host_oops_cnt_after} -gt ${host_oops_cnt_before} ]]; then 530 - echo "FAIL: kernel oops detected on host" | log_host "${name}" 402 + echo "FAIL: kernel oops detected on host" | log_host 531 403 rc=$KSFT_FAIL 532 404 fi 533 405 534 406 host_warn_cnt_after=$(dmesg --level=warn | grep -c -i 'vsock') 535 407 if [[ ${host_warn_cnt_after} -gt ${host_warn_cnt_before} ]]; then 536 - echo "FAIL: kernel warning detected on host" | log_host "${name}" 408 + echo "FAIL: kernel warning detected on host" | log_host 537 409 rc=$KSFT_FAIL 538 410 fi 539 411 540 412 vm_oops_cnt_after=$(vm_ssh -- dmesg | grep -i 'Oops' | wc -l) 541 413 if [[ ${vm_oops_cnt_after} -gt ${vm_oops_cnt_before} ]]; then 542 - echo "FAIL: kernel oops detected on vm" | log_host "${name}" 414 + echo "FAIL: kernel oops detected on vm" | log_host 543 415 rc=$KSFT_FAIL 544 416 fi 545 417 546 418 vm_warn_cnt_after=$(vm_ssh -- dmesg --level=warn | grep -c -i 'vsock') 547 419 if [[ ${vm_warn_cnt_after} -gt ${vm_warn_cnt_before} ]]; then 548 - echo "FAIL: kernel warning detected on vm" | log_host "${name}" 420 + echo "FAIL: kernel warning detected on vm" | log_host 549 421 rc=$KSFT_FAIL 550 422 fi 551 423 552 424 return "${rc}" 553 425 } 554 426 427 + BUILD=0 555 428 QEMU="qemu-system-$(uname -m)" 556 429 557 430 while getopts :hvsq:b o ··· 581 452 582 453 echo "1..${#ARGS[@]}" 583 454 584 - log_setup "Booting up VM" 585 - vm_start 586 - vm_wait_for_ssh 587 - log_setup "VM booted up" 588 - 589 455 cnt_pass=0 590 456 cnt_fail=0 591 457 cnt_skip=0 592 458 cnt_total=0 593 - for arg in "${ARGS[@]}"; do 594 - run_test "${arg}" 595 - rc=$? 596 - if [[ ${rc} -eq $KSFT_PASS ]]; then 597 - cnt_pass=$(( cnt_pass + 1 )) 598 - echo "ok ${cnt_total} ${arg}" 599 - elif [[ ${rc} -eq $KSFT_SKIP ]]; then 600 - cnt_skip=$(( cnt_skip + 1 )) 601 - echo "ok ${cnt_total} ${arg} # SKIP" 602 - elif [[ ${rc} -eq $KSFT_FAIL ]]; then 603 - cnt_fail=$(( cnt_fail + 1 )) 604 - echo "not ok ${cnt_total} ${arg} # exit=$rc" 605 - fi 606 - cnt_total=$(( cnt_total + 1 )) 607 - done 459 + 460 + if shared_vm_tests_requested "${ARGS[@]}"; then 461 + log_host "Booting up VM" 462 + pidfile="$(create_pidfile)" 463 + vm_start "${pidfile}" 464 + vm_wait_for_ssh 465 + log_host "VM booted up" 466 + 467 + run_shared_vm_tests "${ARGS[@]}" 468 + terminate_pidfiles "${pidfile}" 469 + fi 608 470 609 471 echo "SUMMARY: PASS=${cnt_pass} SKIP=${cnt_skip} FAIL=${cnt_fail}" 610 472 echo "Log: ${LOG}"