1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4# Copyright (c) 2025 Meta Platforms, Inc. and affiliates 5# 6# Dependencies: 7# * virtme-ng 8# * busybox-static (used by virtme-ng) 9# * qemu (used by virtme-ng) 10# 11# shellcheck disable=SC2317,SC2119 12 13readonly SCRIPT_DIR="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" 14readonly KERNEL_CHECKOUT=$(realpath "${SCRIPT_DIR}"/../../../../) 15 16source "${SCRIPT_DIR}"/../kselftest/ktap_helpers.sh 17 18readonly VSOCK_TEST="${SCRIPT_DIR}"/vsock_test 19readonly TEST_GUEST_PORT=51000 20readonly TEST_HOST_PORT=50000 21readonly TEST_HOST_PORT_LISTENER=50001 22readonly SSH_GUEST_PORT=22 23readonly SSH_HOST_PORT=2222 24readonly VSOCK_CID=1234 25readonly WAIT_PERIOD=3 26readonly WAIT_PERIOD_MAX=60 27readonly WAIT_QEMU=5 28readonly PIDFILE_TEMPLATE=/tmp/vsock_vmtest_XXXX.pid 29declare -A PIDFILES 30 31# virtme-ng offers a netdev for ssh when using "--ssh", but we also need a 32# control port forwarded for vsock_test. Because virtme-ng doesn't support 33# adding an additional port to forward to the device created from "--ssh" and 34# virtme-init mistakenly sets identical IPs to the ssh device and additional 35# devices, we instead opt out of using --ssh, add the device manually, and also 36# add the kernel cmdline options that virtme-init uses to setup the interface. 37readonly QEMU_TEST_PORT_FWD="hostfwd=tcp::${TEST_HOST_PORT}-:${TEST_GUEST_PORT}" 38readonly QEMU_SSH_PORT_FWD="hostfwd=tcp::${SSH_HOST_PORT}-:${SSH_GUEST_PORT}" 39readonly KERNEL_CMDLINE="\ 40 virtme.dhcp net.ifnames=0 biosdevname=0 \ 41 virtme.ssh virtme_ssh_channel=tcp virtme_ssh_user=$USER \ 42" 43readonly LOG=$(mktemp /tmp/vsock_vmtest_XXXX.log) 44 45# Namespace tests must use the ns_ prefix. This is checked in check_netns() and 46# is used to determine if a test needs namespace setup before test execution. 47readonly TEST_NAMES=( 48 vm_server_host_client 49 vm_client_host_server 50 vm_loopback 51 ns_host_vsock_ns_mode_ok 52 ns_host_vsock_child_ns_mode_ok 53) 54readonly TEST_DESCS=( 55 # vm_server_host_client 56 "Run vsock_test in server mode on the VM and in client mode on the host." 57 58 # vm_client_host_server 59 "Run vsock_test in client mode on the VM and in server mode on the host." 60 61 # vm_loopback 62 "Run vsock_test using the loopback transport in the VM." 63 64 # ns_host_vsock_ns_mode_ok 65 "Check /proc/sys/net/vsock/ns_mode strings on the host." 66 67 # ns_host_vsock_child_ns_mode_ok 68 "Check /proc/sys/net/vsock/ns_mode is read-only and child_ns_mode is writable." 69) 70 71readonly USE_SHARED_VM=( 72 vm_server_host_client 73 vm_client_host_server 74 vm_loopback 75) 76readonly NS_MODES=("local" "global") 77 78VERBOSE=0 79 80usage() { 81 local name 82 local desc 83 local i 84 85 echo 86 echo "$0 [OPTIONS] [TEST]..." 87 echo "If no TEST argument is given, all tests will be run." 88 echo 89 echo "Options" 90 echo " -b: build the kernel from the current source tree and use it for guest VMs" 91 echo " -q: set the path to or name of qemu binary" 92 echo " -v: verbose output" 93 echo 94 echo "Available tests" 95 96 for ((i = 0; i < ${#TEST_NAMES[@]}; i++)); do 97 name=${TEST_NAMES[${i}]} 98 desc=${TEST_DESCS[${i}]} 99 printf "\t%-35s%-35s\n" "${name}" "${desc}" 100 done 101 echo 102 103 exit 1 104} 105 106die() { 107 echo "$*" >&2 108 exit "${KSFT_FAIL}" 109} 110 111check_result() { 112 local rc arg 113 114 rc=$1 115 arg=$2 116 117 cnt_total=$(( cnt_total + 1 )) 118 119 if [[ ${rc} -eq ${KSFT_PASS} ]]; then 120 cnt_pass=$(( cnt_pass + 1 )) 121 echo "ok ${cnt_total} ${arg}" 122 elif [[ ${rc} -eq ${KSFT_SKIP} ]]; then 123 cnt_skip=$(( cnt_skip + 1 )) 124 echo "ok ${cnt_total} ${arg} # SKIP" 125 elif [[ ${rc} -eq ${KSFT_FAIL} ]]; then 126 cnt_fail=$(( cnt_fail + 1 )) 127 echo "not ok ${cnt_total} ${arg} # exit=${rc}" 128 fi 129} 130 131add_namespaces() { 132 local orig_mode 133 orig_mode=$(cat /proc/sys/net/vsock/child_ns_mode) 134 135 for mode in "${NS_MODES[@]}"; do 136 echo "${mode}" > /proc/sys/net/vsock/child_ns_mode 137 ip netns add "${mode}0" 2>/dev/null 138 ip netns add "${mode}1" 2>/dev/null 139 done 140 141 echo "${orig_mode}" > /proc/sys/net/vsock/child_ns_mode 142} 143 144init_namespaces() { 145 for mode in "${NS_MODES[@]}"; do 146 # we need lo for qemu port forwarding 147 ip netns exec "${mode}0" ip link set dev lo up 148 ip netns exec "${mode}1" ip link set dev lo up 149 done 150} 151 152del_namespaces() { 153 for mode in "${NS_MODES[@]}"; do 154 ip netns del "${mode}0" &>/dev/null 155 ip netns del "${mode}1" &>/dev/null 156 log_host "removed ns ${mode}0" 157 log_host "removed ns ${mode}1" 158 done 159} 160 161vm_ssh() { 162 local ns_exec 163 164 if [[ "${1}" == init_ns ]]; then 165 ns_exec="" 166 else 167 ns_exec="ip netns exec ${1}" 168 fi 169 170 shift 171 172 ${ns_exec} ssh -q -o UserKnownHostsFile=/dev/null -p "${SSH_HOST_PORT}" localhost "$@" 173 174 return $? 175} 176 177cleanup() { 178 terminate_pidfiles "${!PIDFILES[@]}" 179 del_namespaces 180} 181 182check_args() { 183 local found 184 185 for arg in "$@"; do 186 found=0 187 for name in "${TEST_NAMES[@]}"; do 188 if [[ "${name}" = "${arg}" ]]; then 189 found=1 190 break 191 fi 192 done 193 194 if [[ "${found}" -eq 0 ]]; then 195 echo "${arg} is not an available test" >&2 196 usage 197 fi 198 done 199 200 for arg in "$@"; do 201 if ! command -v > /dev/null "test_${arg}"; then 202 echo "Test ${arg} not found" >&2 203 usage 204 fi 205 done 206} 207 208check_deps() { 209 for dep in vng ${QEMU} busybox pkill ssh ss; do 210 if [[ ! -x $(command -v "${dep}") ]]; then 211 echo -e "skip: dependency ${dep} not found!\n" 212 exit "${KSFT_SKIP}" 213 fi 214 done 215 216 if [[ ! -x $(command -v "${VSOCK_TEST}") ]]; then 217 printf "skip: %s not found!" "${VSOCK_TEST}" 218 printf " Please build the kselftest vsock target.\n" 219 exit "${KSFT_SKIP}" 220 fi 221} 222 223check_netns() { 224 local tname=$1 225 226 # If the test requires NS support, check if NS support exists 227 # using /proc/self/ns 228 if [[ "${tname}" =~ ^ns_ ]] && 229 [[ ! -e /proc/self/ns ]]; then 230 log_host "No NS support detected for test ${tname}" 231 return 1 232 fi 233 234 return 0 235} 236 237check_vng() { 238 local tested_versions 239 local version 240 local ok 241 242 tested_versions=("1.33" "1.36" "1.37") 243 version="$(vng --version)" 244 245 ok=0 246 for tv in "${tested_versions[@]}"; do 247 if [[ "${version}" == *"${tv}"* ]]; then 248 ok=1 249 break 250 fi 251 done 252 253 if [[ ! "${ok}" -eq 1 ]]; then 254 printf "warning: vng version '%s' has not been tested and may " "${version}" >&2 255 printf "not function properly.\n\tThe following versions have been tested: " >&2 256 echo "${tested_versions[@]}" >&2 257 fi 258} 259 260handle_build() { 261 if [[ ! "${BUILD}" -eq 1 ]]; then 262 return 263 fi 264 265 if [[ ! -d "${KERNEL_CHECKOUT}" ]]; then 266 echo "-b requires vmtest.sh called from the kernel source tree" >&2 267 exit 1 268 fi 269 270 pushd "${KERNEL_CHECKOUT}" &>/dev/null 271 272 if ! vng --kconfig --config "${SCRIPT_DIR}"/config; then 273 die "failed to generate .config for kernel source tree (${KERNEL_CHECKOUT})" 274 fi 275 276 if ! make -j$(nproc); then 277 die "failed to build kernel from source tree (${KERNEL_CHECKOUT})" 278 fi 279 280 popd &>/dev/null 281} 282 283create_pidfile() { 284 local pidfile 285 286 pidfile=$(mktemp "${PIDFILE_TEMPLATE}") 287 PIDFILES["${pidfile}"]=1 288 289 echo "${pidfile}" 290} 291 292terminate_pidfiles() { 293 local pidfile 294 295 for pidfile in "$@"; do 296 if [[ -s "${pidfile}" ]]; then 297 pkill -SIGTERM -F "${pidfile}" > /dev/null 2>&1 298 fi 299 300 if [[ -e "${pidfile}" ]]; then 301 rm -f "${pidfile}" 302 fi 303 304 unset "PIDFILES[${pidfile}]" 305 done 306} 307 308vm_start() { 309 local pidfile=$1 310 local ns=$2 311 local logfile=/dev/null 312 local verbose_opt="" 313 local kernel_opt="" 314 local qemu_opts="" 315 local ns_exec="" 316 local qemu 317 318 qemu=$(command -v "${QEMU}") 319 320 if [[ "${VERBOSE}" -eq 1 ]]; then 321 verbose_opt="--verbose" 322 logfile=/dev/stdout 323 fi 324 325 qemu_opts="\ 326 -netdev user,id=n0,${QEMU_TEST_PORT_FWD},${QEMU_SSH_PORT_FWD} \ 327 -device virtio-net-pci,netdev=n0 \ 328 -device vhost-vsock-pci,guest-cid=${VSOCK_CID} \ 329 --pidfile ${pidfile} 330 " 331 332 if [[ "${BUILD}" -eq 1 ]]; then 333 kernel_opt="${KERNEL_CHECKOUT}" 334 fi 335 336 if [[ "${ns}" != "init_ns" ]]; then 337 ns_exec="ip netns exec ${ns}" 338 fi 339 340 ${ns_exec} vng \ 341 --run \ 342 ${kernel_opt} \ 343 ${verbose_opt} \ 344 --qemu-opts="${qemu_opts}" \ 345 --qemu="${qemu}" \ 346 --user root \ 347 --append "${KERNEL_CMDLINE}" \ 348 --rw &> ${logfile} & 349 350 timeout "${WAIT_QEMU}" \ 351 bash -c 'while [[ ! -s '"${pidfile}"' ]]; do sleep 1; done; exit 0' 352} 353 354vm_wait_for_ssh() { 355 local ns=$1 356 local i 357 358 i=0 359 while true; do 360 if [[ ${i} -gt ${WAIT_PERIOD_MAX} ]]; then 361 die "Timed out waiting for guest ssh" 362 fi 363 364 if vm_ssh "${ns}" -- true; then 365 break 366 fi 367 i=$(( i + 1 )) 368 sleep ${WAIT_PERIOD} 369 done 370} 371 372# derived from selftests/net/net_helper.sh 373wait_for_listener() 374{ 375 local port=$1 376 local interval=$2 377 local max_intervals=$3 378 local protocol=$4 379 local i 380 381 for i in $(seq "${max_intervals}"); do 382 case "${protocol}" in 383 tcp) 384 if ss --listening --tcp --numeric | grep -q ":${port} "; then 385 break 386 fi 387 ;; 388 vsock) 389 if ss --listening --vsock --numeric | grep -q ":${port} "; then 390 break 391 fi 392 ;; 393 unix) 394 # For unix sockets, port is actually the socket path 395 if ss --listening --unix | grep -q "${port}"; then 396 break 397 fi 398 ;; 399 *) 400 echo "Unknown protocol: ${protocol}" >&2 401 break 402 ;; 403 esac 404 sleep "${interval}" 405 done 406} 407 408vm_wait_for_listener() { 409 local ns=$1 410 local port=$2 411 local protocol=$3 412 413 vm_ssh "${ns}" <<EOF 414$(declare -f wait_for_listener) 415wait_for_listener ${port} ${WAIT_PERIOD} ${WAIT_PERIOD_MAX} ${protocol} 416EOF 417} 418 419host_wait_for_listener() { 420 local ns=$1 421 local port=$2 422 local protocol=$3 423 424 if [[ "${ns}" == "init_ns" ]]; then 425 wait_for_listener "${port}" "${WAIT_PERIOD}" "${WAIT_PERIOD_MAX}" "${protocol}" 426 else 427 ip netns exec "${ns}" bash <<-EOF 428 $(declare -f wait_for_listener) 429 wait_for_listener ${port} ${WAIT_PERIOD} ${WAIT_PERIOD_MAX} ${protocol} 430 EOF 431 fi 432} 433 434vm_dmesg_oops_count() { 435 local ns=$1 436 437 vm_ssh "${ns}" -- dmesg 2>/dev/null | grep -c -i 'Oops' 438} 439 440vm_dmesg_warn_count() { 441 local ns=$1 442 443 vm_ssh "${ns}" -- dmesg --level=warn 2>/dev/null | grep -c -i 'vsock' 444} 445 446vm_vsock_test() { 447 local ns=$1 448 local host=$2 449 local cid=$3 450 local port=$4 451 local rc 452 453 # log output and use pipefail to respect vsock_test errors 454 set -o pipefail 455 if [[ "${host}" != server ]]; then 456 vm_ssh "${ns}" -- "${VSOCK_TEST}" \ 457 --mode=client \ 458 --control-host="${host}" \ 459 --peer-cid="${cid}" \ 460 --control-port="${port}" \ 461 2>&1 | log_guest 462 rc=$? 463 else 464 vm_ssh "${ns}" -- "${VSOCK_TEST}" \ 465 --mode=server \ 466 --peer-cid="${cid}" \ 467 --control-port="${port}" \ 468 2>&1 | log_guest & 469 rc=$? 470 471 if [[ $rc -ne 0 ]]; then 472 set +o pipefail 473 return $rc 474 fi 475 476 vm_wait_for_listener "${ns}" "${port}" "tcp" 477 rc=$? 478 fi 479 set +o pipefail 480 481 return $rc 482} 483 484host_vsock_test() { 485 local ns=$1 486 local host=$2 487 local cid=$3 488 local port=$4 489 local rc 490 491 local cmd="${VSOCK_TEST}" 492 if [[ "${ns}" != "init_ns" ]]; then 493 cmd="ip netns exec ${ns} ${cmd}" 494 fi 495 496 # log output and use pipefail to respect vsock_test errors 497 set -o pipefail 498 if [[ "${host}" != server ]]; then 499 ${cmd} \ 500 --mode=client \ 501 --peer-cid="${cid}" \ 502 --control-host="${host}" \ 503 --control-port="${port}" 2>&1 | log_host 504 rc=$? 505 else 506 ${cmd} \ 507 --mode=server \ 508 --peer-cid="${cid}" \ 509 --control-port="${port}" 2>&1 | log_host & 510 rc=$? 511 512 if [[ $rc -ne 0 ]]; then 513 set +o pipefail 514 return $rc 515 fi 516 517 host_wait_for_listener "${ns}" "${port}" "tcp" 518 rc=$? 519 fi 520 set +o pipefail 521 522 return $rc 523} 524 525log() { 526 local redirect 527 local prefix 528 529 if [[ ${VERBOSE} -eq 0 ]]; then 530 redirect=/dev/null 531 else 532 redirect=/dev/stdout 533 fi 534 535 prefix="${LOG_PREFIX:-}" 536 537 if [[ "$#" -eq 0 ]]; then 538 if [[ -n "${prefix}" ]]; then 539 awk -v prefix="${prefix}" '{printf "%s: %s\n", prefix, $0}' 540 else 541 cat 542 fi 543 else 544 if [[ -n "${prefix}" ]]; then 545 echo "${prefix}: " "$@" 546 else 547 echo "$@" 548 fi 549 fi | tee -a "${LOG}" > "${redirect}" 550} 551 552log_host() { 553 LOG_PREFIX=host log "$@" 554} 555 556log_guest() { 557 LOG_PREFIX=guest log "$@" 558} 559 560ns_get_mode() { 561 local ns=$1 562 563 ip netns exec "${ns}" cat /proc/sys/net/vsock/ns_mode 2>/dev/null 564} 565 566test_ns_host_vsock_ns_mode_ok() { 567 for mode in "${NS_MODES[@]}"; do 568 local actual 569 570 actual=$(ns_get_mode "${mode}0") 571 if [[ "${actual}" != "${mode}" ]]; then 572 log_host "expected mode ${mode}, got ${actual}" 573 return "${KSFT_FAIL}" 574 fi 575 done 576 577 return "${KSFT_PASS}" 578} 579 580test_ns_host_vsock_child_ns_mode_ok() { 581 local orig_mode 582 local rc 583 584 orig_mode=$(cat /proc/sys/net/vsock/child_ns_mode) 585 586 rc="${KSFT_PASS}" 587 for mode in "${NS_MODES[@]}"; do 588 local ns="${mode}0" 589 590 if echo "${mode}" 2>/dev/null > /proc/sys/net/vsock/ns_mode; then 591 log_host "ns_mode should be read-only but write succeeded" 592 rc="${KSFT_FAIL}" 593 continue 594 fi 595 596 if ! echo "${mode}" > /proc/sys/net/vsock/child_ns_mode; then 597 log_host "child_ns_mode should be writable to ${mode}" 598 rc="${KSFT_FAIL}" 599 continue 600 fi 601 done 602 603 echo "${orig_mode}" > /proc/sys/net/vsock/child_ns_mode 604 605 return "${rc}" 606} 607 608test_vm_server_host_client() { 609 if ! vm_vsock_test "init_ns" "server" 2 "${TEST_GUEST_PORT}"; then 610 return "${KSFT_FAIL}" 611 fi 612 613 if ! host_vsock_test "init_ns" "127.0.0.1" "${VSOCK_CID}" "${TEST_HOST_PORT}"; then 614 return "${KSFT_FAIL}" 615 fi 616 617 return "${KSFT_PASS}" 618} 619 620test_vm_client_host_server() { 621 if ! host_vsock_test "init_ns" "server" "${VSOCK_CID}" "${TEST_HOST_PORT_LISTENER}"; then 622 return "${KSFT_FAIL}" 623 fi 624 625 if ! vm_vsock_test "init_ns" "10.0.2.2" 2 "${TEST_HOST_PORT_LISTENER}"; then 626 return "${KSFT_FAIL}" 627 fi 628 629 return "${KSFT_PASS}" 630} 631 632test_vm_loopback() { 633 local port=60000 # non-forwarded local port 634 635 vm_ssh "init_ns" -- modprobe vsock_loopback &> /dev/null || : 636 637 if ! vm_vsock_test "init_ns" "server" 1 "${port}"; then 638 return "${KSFT_FAIL}" 639 fi 640 641 642 if ! vm_vsock_test "init_ns" "127.0.0.1" 1 "${port}"; then 643 return "${KSFT_FAIL}" 644 fi 645 646 return "${KSFT_PASS}" 647} 648 649shared_vm_test() { 650 local tname 651 652 tname="${1}" 653 654 for testname in "${USE_SHARED_VM[@]}"; do 655 if [[ "${tname}" == "${testname}" ]]; then 656 return 0 657 fi 658 done 659 660 return 1 661} 662 663shared_vm_tests_requested() { 664 for arg in "$@"; do 665 if shared_vm_test "${arg}"; then 666 return 0 667 fi 668 done 669 670 return 1 671} 672 673run_shared_vm_tests() { 674 local arg 675 676 for arg in "$@"; do 677 if ! shared_vm_test "${arg}"; then 678 continue 679 fi 680 681 if ! check_netns "${arg}"; then 682 check_result "${KSFT_SKIP}" "${arg}" 683 continue 684 fi 685 686 run_shared_vm_test "${arg}" 687 check_result "$?" "${arg}" 688 done 689} 690 691run_shared_vm_test() { 692 local host_oops_cnt_before 693 local host_warn_cnt_before 694 local vm_oops_cnt_before 695 local vm_warn_cnt_before 696 local host_oops_cnt_after 697 local host_warn_cnt_after 698 local vm_oops_cnt_after 699 local vm_warn_cnt_after 700 local name 701 local rc 702 703 host_oops_cnt_before=$(dmesg | grep -c -i 'Oops') 704 host_warn_cnt_before=$(dmesg --level=warn | grep -c -i 'vsock') 705 vm_oops_cnt_before=$(vm_dmesg_oops_count "init_ns") 706 vm_warn_cnt_before=$(vm_dmesg_warn_count "init_ns") 707 708 name=$(echo "${1}" | awk '{ print $1 }') 709 eval test_"${name}" 710 rc=$? 711 712 host_oops_cnt_after=$(dmesg | grep -i 'Oops' | wc -l) 713 if [[ ${host_oops_cnt_after} -gt ${host_oops_cnt_before} ]]; then 714 echo "FAIL: kernel oops detected on host" | log_host 715 rc=$KSFT_FAIL 716 fi 717 718 host_warn_cnt_after=$(dmesg --level=warn | grep -c -i 'vsock') 719 if [[ ${host_warn_cnt_after} -gt ${host_warn_cnt_before} ]]; then 720 echo "FAIL: kernel warning detected on host" | log_host 721 rc=$KSFT_FAIL 722 fi 723 724 vm_oops_cnt_after=$(vm_dmesg_oops_count "init_ns") 725 if [[ ${vm_oops_cnt_after} -gt ${vm_oops_cnt_before} ]]; then 726 echo "FAIL: kernel oops detected on vm" | log_host 727 rc=$KSFT_FAIL 728 fi 729 730 vm_warn_cnt_after=$(vm_dmesg_warn_count "init_ns") 731 if [[ ${vm_warn_cnt_after} -gt ${vm_warn_cnt_before} ]]; then 732 echo "FAIL: kernel warning detected on vm" | log_host 733 rc=$KSFT_FAIL 734 fi 735 736 return "${rc}" 737} 738 739run_ns_tests() { 740 for arg in "${ARGS[@]}"; do 741 if shared_vm_test "${arg}"; then 742 continue 743 fi 744 745 if ! check_netns "${arg}"; then 746 check_result "${KSFT_SKIP}" "${arg}" 747 continue 748 fi 749 750 add_namespaces 751 752 name=$(echo "${arg}" | awk '{ print $1 }') 753 log_host "Executing test_${name}" 754 755 host_oops_before=$(dmesg 2>/dev/null | grep -c -i 'Oops') 756 host_warn_before=$(dmesg --level=warn 2>/dev/null | grep -c -i 'vsock') 757 eval test_"${name}" 758 rc=$? 759 760 host_oops_after=$(dmesg 2>/dev/null | grep -c -i 'Oops') 761 if [[ "${host_oops_after}" -gt "${host_oops_before}" ]]; then 762 echo "FAIL: kernel oops detected on host" | log_host 763 check_result "${KSFT_FAIL}" "${name}" 764 del_namespaces 765 continue 766 fi 767 768 host_warn_after=$(dmesg --level=warn 2>/dev/null | grep -c -i 'vsock') 769 if [[ "${host_warn_after}" -gt "${host_warn_before}" ]]; then 770 echo "FAIL: kernel warning detected on host" | log_host 771 check_result "${KSFT_FAIL}" "${name}" 772 del_namespaces 773 continue 774 fi 775 776 check_result "${rc}" "${name}" 777 778 del_namespaces 779 done 780} 781 782BUILD=0 783QEMU="qemu-system-$(uname -m)" 784 785while getopts :hvsq:b o 786do 787 case $o in 788 v) VERBOSE=1;; 789 b) BUILD=1;; 790 q) QEMU=$OPTARG;; 791 h|*) usage;; 792 esac 793done 794shift $((OPTIND-1)) 795 796trap cleanup EXIT 797 798if [[ ${#} -eq 0 ]]; then 799 ARGS=("${TEST_NAMES[@]}") 800else 801 ARGS=("$@") 802fi 803 804check_args "${ARGS[@]}" 805check_deps 806check_vng 807handle_build 808 809echo "1..${#ARGS[@]}" 810 811cnt_pass=0 812cnt_fail=0 813cnt_skip=0 814cnt_total=0 815 816if shared_vm_tests_requested "${ARGS[@]}"; then 817 log_host "Booting up VM" 818 pidfile="$(create_pidfile)" 819 vm_start "${pidfile}" "init_ns" 820 vm_wait_for_ssh "init_ns" 821 log_host "VM booted up" 822 823 run_shared_vm_tests "${ARGS[@]}" 824 terminate_pidfiles "${pidfile}" 825fi 826 827run_ns_tests "${ARGS[@]}" 828 829echo "SUMMARY: PASS=${cnt_pass} SKIP=${cnt_skip} FAIL=${cnt_fail}" 830echo "Log: ${LOG}" 831 832if [ $((cnt_pass + cnt_skip)) -eq ${cnt_total} ]; then 833 exit "$KSFT_PASS" 834else 835 exit "$KSFT_FAIL" 836fi 837