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