From nobody Mon Dec 15 21:27:44 2025 Received: from mail-pj1-f49.google.com (mail-pj1-f49.google.com [209.85.216.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 351C4233727; Tue, 17 Jun 2025 04:32:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750134777; cv=none; b=RACEvoerbi//Tr7y8S9xJyyOxEwlOyTRBSd5jL62KL++/AgoO8olvcWwkHN6UCJnc9AGp5PVaE9nqwLeeeCV/SmT0FfllspC2e9XiOFWuB0erawwqtkFOpo3M6g7D0ENIomz3klT0rL1if5mic5utuSKHdA80t99X3XpcpWhKxk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750134777; c=relaxed/simple; bh=M6kehEHY7OwsO30C3T5dyH4gOVxvswy/eOIw/pHWvGo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Z2vsOqC1xEHSniPNz6EKL6myMEzl52YSDqEP1LkhAQ0BRaRLRrm2MtCFkI3X02/loTNBWK7N/MVgDKNTp5UFs4d4kSxZ6wP/3AVsaA7ZOr2tRsIEPcpHh4fRJWnZsELOix/+Rk7KPdvcdKOc1DFFRr7hXpaeTMAixyIr+4sWF7o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Z7dZ2ezG; arc=none smtp.client-ip=209.85.216.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Z7dZ2ezG" Received: by mail-pj1-f49.google.com with SMTP id 98e67ed59e1d1-311bd8ce7e4so4344295a91.3; Mon, 16 Jun 2025 21:32:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1750134774; x=1750739574; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=tK3AwFkrbSBAfvCtmqP3DGRgf/aabwLUhpvOzpe/4SQ=; b=Z7dZ2ezGSmd5xdUkbYVaMWoEWPba1c+5wzfc4h6gbckJUkEk126MVsuKdWjkMf+XrY BeuON+BFGeAh13joHO4MbijUEkVNQo576qGsoQWJQfrjRna2lykMIRIdRv3EHNMrOVOD qTPMvSBYVcEenROX5wzJaLT2OrT2GvgaEByjQQRa1+o4v7mr4xv1ukxymIWPHnFVxonN UbheS593CROHQaow7GTwnJF6kjG4YmWqMQFHs09zvXIp3oYmhdSQCosvDl2hnCu/G0Ae MLMpy/xmNnBPlXAz9lO6ACmrNMSDtEtnIkUkyPwPftf/k8la3BK1e0f6VGr7LoFlmcaD SHbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750134774; x=1750739574; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tK3AwFkrbSBAfvCtmqP3DGRgf/aabwLUhpvOzpe/4SQ=; b=pEsE1K3YKuVSfwPQo56v8+CUejXzCE/eS7sEfPTPsDdzCobSbG00JfmVMDsIhl1LOK BBJTAsRNSbL7Ecw6ldu2KWBvzQoUfofGaWBX7wQq2zZKFATbXsNfslii0sSK/r5ZWrEe 53MIhK0nnB+Ri06NOikgqKWUs+eagIlCIIUXYcdqyXrhYBNdahqb99Fyufy5R2EKzKrL ioeCcM5+c0/ERXAke39ZaTLSe8dcc9btkK3ONBgbQeAsdAT9hvQEfGSqjXUeJsRDEJXv SfjbbpzaTWsSXkG/DkatLlNXPWsjN5ehvk7XtMXjBi01EQc/j7uuKw55L7v1WsNwdGHx 5WhQ== X-Forwarded-Encrypted: i=1; AJvYcCUmocU1XJymETsYq04Ujr82RN3xmSSamyhA8i0a7fA/7eKVot+YOppZpZ0FDZIbkD8KAYOyfb8G84CVQJ8tOR0V@vger.kernel.org, AJvYcCWwM/ikXSzvAfHhwfmDigzM7yzSSEVgRxYJd91Dt2pAXX3GpvOgSx1lsQ6WFx6IM+nfW8b2vPKc@vger.kernel.org, AJvYcCXtScnjdon6BvA8XYWT9S+EPsfYZQTa7Td+BVwKSvmx7O9i+ZBgHWGMXD0VWsaXxU1cskkZKdZfyujPw4E=@vger.kernel.org X-Gm-Message-State: AOJu0Yxbjz3lcpobFmYMacdUYZe02sYfrz75xFC3rT5RJiO/jRXWv2sQ Ix0PqMxCER4mXFQCeA1zAJJrKV398P5qHvKXmk/O/PMFBOhZF/+Wj/rzfS5VelNG X-Gm-Gg: ASbGncutY1OMkPN1fFkVZMVdoS6fSSY5O1EpueQW8GJwcFIaHsHHo2GuEvn6vyY45V3 Cr1ZrZPsuHDGunXheibcTk570n7/tVhPeFeUiDcwxNc8uIpwqBItZH0WB9tic81sf4HL8gLVpvN /1EnZSGIlgEe+R6ZQPLVkht9gs00fnmBxgKK5DRmz42EWVZEljEDQ9ieS45+U9An3+AkKYeGatM ptjnxHZOULPA9Y5Aov6rzyrW1v4+OpxhTdZCQrTCfCNKU8yYciIWx0iXuD3IA1otMwgy05QaR6N 1R2Qs3PoVdem4lNoz1Qfj60ETzEGhGiY59L6OLleF/L7N/P7HGbYYOgdiJM= X-Google-Smtp-Source: AGHT+IHSfb1B9OqWCmo1j9XP1ine02uUWCOqD7+7PRIocnf/lDDULUBftytAvdSsR4guD5nUqSLd4g== X-Received: by 2002:a17:90b:2745:b0:312:e9bd:5d37 with SMTP id 98e67ed59e1d1-313f1c7b54dmr16681132a91.6.1750134773541; Mon, 16 Jun 2025 21:32:53 -0700 (PDT) Received: from localhost ([2a03:2880:2ff:5::]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-313c1b5efa2sm9560585a91.41.2025.06.16.21.32.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Jun 2025 21:32:52 -0700 (PDT) From: Bobby Eshleman Date: Mon, 16 Jun 2025 21:32:50 -0700 Subject: [PATCH RFC net-next v4 01/11] selftests/vsock: add NS tests to vmtest.sh Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250616-vsock-vmtest-v4-1-bdd1659c33fb@meta.com> References: <20250616-vsock-vmtest-v4-0-bdd1659c33fb@meta.com> In-Reply-To: <20250616-vsock-vmtest-v4-0-bdd1659c33fb@meta.com> To: Stefano Garzarella , Stefan Hajnoczi , Shuah Khan Cc: kvm@vger.kernel.org, "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , linux-kernel@vger.kernel.org, virtualization@lists.linux.dev, netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, Bobby Eshleman X-Mailer: b4 0.13.0 This patch has not been tested since rebasing onto upstream vmtest.sh. It is probably very broken, but here to show the direction the testing is going in... vsock_test uses tcp for the control socket. TCP itself responds to namespaces. In order to test vsock but not break TCP, vmtest.sh sets up a bridge with socat (perhaps ip tables would be better, because it can reduce an out-of-tree tool dependency). Another option is to not use vsock_test for the NS tests, but it seems more robust to test all of vsock instead of just (for example) connectibility... Signed-off-by: Bobby Eshleman --- tools/testing/selftests/vsock/vmtest.sh | 555 ++++++++++++++++++++++++++++= +--- 1 file changed, 510 insertions(+), 45 deletions(-) diff --git a/tools/testing/selftests/vsock/vmtest.sh b/tools/testing/selfte= sts/vsock/vmtest.sh index edacebfc1632..8f627f60cc11 100755 --- a/tools/testing/selftests/vsock/vmtest.sh +++ b/tools/testing/selftests/vsock/vmtest.sh @@ -7,6 +7,48 @@ # * virtme-ng # * busybox-static (used by virtme-ng) # * qemu (used by virtme-ng) +# +# Namespace tests require to test the functionality of VSOCK under differe= nt +# namespace configurations. Ideally, we can use vsock_test and friends und= er +# the different configurations to ensure that all functionality works +# regardless of namespace setup. vsock_test also requires TCP for its cont= rol +# plane, which is also impacted by namespacing. For this reason, these tes= ts +# build a bridge between the namespaces so that the TCP control traffic can +# flow between namespaces. The bridge setup looks as follows: +# +# +# | +# +------------------+ | +# | VM | | +# | | NS0 | NS1 +# | +------------+ | | +# | | | | --------+--------------------+ +# | | vsock_test | | | | +# | | | | <-------+-----------------+ | +# | +------------+ | | VSOCK_TEST_PORT| | +# | | | | | VSOCK +# +------------------+ | | | +# ^ | | | | +# CONTROL_PORT| | | | | +# | | | | | +# | | | | v +# | | | +------------+ +# | | TCP | | | +# | | | | vsock_test | +# | | | | | +# | | | +------------+ +# CONTROL_PORT | | | CONTROL_PORT ^ | +# | | | | | +# | v | CONTROL_PORT | v +# +-------+ | +-------+ +# | |veth0 | veth1| | +# | socat |<-------------+------------- | socat | +# | | -------------+------------> | | +# +-------+ | +-------+ +# NS_BRIDGE_PORT | NS_BRIDGE_PORT +# | + +set -u =20 readonly SCRIPT_DIR=3D"$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && p= wd -P)" readonly KERNEL_CHECKOUT=3D$(realpath "${SCRIPT_DIR}"/../../../../) @@ -19,11 +61,11 @@ readonly TEST_HOST_PORT=3D50000 readonly TEST_HOST_PORT_LISTENER=3D50001 readonly SSH_GUEST_PORT=3D22 readonly SSH_HOST_PORT=3D2222 -readonly VSOCK_CID=3D1234 +readonly BRIDGE_PORT=3D5678 +readonly DEFAULT_CID=3D1234 readonly WAIT_PERIOD=3D3 readonly WAIT_PERIOD_MAX=3D60 -readonly WAIT_TOTAL=3D$(( WAIT_PERIOD * WAIT_PERIOD_MAX )) -readonly QEMU_PIDFILE=3D$(mktemp /tmp/qemu_vsock_vmtest_XXXX.pid) +WAIT_TOTAL=3D$(( WAIT_PERIOD * WAIT_PERIOD_MAX )) =20 # virtme-ng offers a netdev for ssh when using "--ssh", but we also need a # control port forwarded for vsock_test. Because virtme-ng doesn't support @@ -33,23 +75,48 @@ readonly QEMU_PIDFILE=3D$(mktemp /tmp/qemu_vsock_vmtest= _XXXX.pid) # add the kernel cmdline options that virtme-init uses to setup the interf= ace. readonly QEMU_TEST_PORT_FWD=3D"hostfwd=3Dtcp::${TEST_HOST_PORT}-:${TEST_GU= EST_PORT}" readonly QEMU_SSH_PORT_FWD=3D"hostfwd=3Dtcp::${SSH_HOST_PORT}-:${SSH_GUEST= _PORT}" -readonly QEMU_OPTS=3D"\ +readonly LOG=3D$(mktemp /tmp/vsock_vmtest_XXXX.log) +readonly TEST_NAMES=3D(vm_server_host_client vm_client_host_server vm_loop= back) +QEMU_OPTS=3D"\ -netdev user,id=3Dn0,${QEMU_TEST_PORT_FWD},${QEMU_SSH_PORT_FWD} \ -device virtio-net-pci,netdev=3Dn0 \ - -device vhost-vsock-pci,guest-cid=3D${VSOCK_CID} \ - --pidfile ${QEMU_PIDFILE} \ " readonly KERNEL_CMDLINE=3D"\ virtme.dhcp net.ifnames=3D0 biosdevname=3D0 \ virtme.ssh virtme_ssh_channel=3Dtcp virtme_ssh_user=3D$USER \ " readonly LOG=3D$(mktemp /tmp/vsock_vmtest_XXXX.log) -readonly TEST_NAMES=3D(vm_server_host_client vm_client_host_server vm_loop= back) +readonly TEST_NAMES=3D( + vm_server_host_client + vm_client_host_server + vm_loopback + host_vsock_ns_mode + host_vsock_ns_mode_write_once + global_same_cid + local_same_cid + global_local_same_cid + local_global_same_cid + global_host_connect_global_vm + global_vm_connect_global_host + global_vm_connect_mixed_host +) + readonly TEST_DESCS=3D( "Run vsock_test in server mode on the VM and in client mode on the host." "Run vsock_test in client mode on the VM and in server mode on the host." "Run vsock_test using the loopback transport in the VM." + "Check /proc/net/vsock_ns_mode strings on the host." + "Check /proc/net/vsock_ns_mode is write-once on the host." + "Test that CID allocation fails with the same CID, one global NS and anot= her global NS." + "Test that CID allocation succeeds with the same CID, one local NS and an= other local NS." + "Test that CID allocation succeeds with the same CID, one global NS and o= ne local NS, global allocates first." + "Test that CID allocation succeeds with the same CID, one global NS and o= ne local NS, local allocates first." ) +readonly NEEDS_SETUP=3D(vm_server_host_client vm_client_host_server vm_loo= pback) +readonly MODES=3D("local" "global" "mixed") +readonly PIDFILE_TEMPLATE=3D"/tmp/qemu_vsock_vmtest_XXXX.pid" + +declare -a PIDFILES =20 VERBOSE=3D0 =20 @@ -84,21 +151,40 @@ die() { exit "${KSFT_FAIL}" } =20 +cleanup() { + terminate_pidfiles ${PIDFILES[@]} + del_namespaces +} + vm_ssh() { ssh -q -o UserKnownHostsFile=3D/dev/null -p ${SSH_HOST_PORT} localhost "$= @" return $? } =20 -cleanup() { - if [[ -s "${QEMU_PIDFILE}" ]]; then - pkill -SIGTERM -F "${QEMU_PIDFILE}" > /dev/null 2>&1 - fi +vm_ssh_ns() { + local ns=3D"${1}" + local NS_EXEC=3D"ip netns exec ${ns}" + shift =20 - # If failure occurred during or before qemu start up, then we need - # to clean this up ourselves. - if [[ -e "${QEMU_PIDFILE}" ]]; then - rm "${QEMU_PIDFILE}" - fi + ${NS_EXEC} ssh -q -o UserKnownHostsFile=3D/dev/null -p ${SSH_HOST_PORT} l= ocalhost $* + + return $? +} + +terminate_pidfiles() { + local pidfile + + for pidfile in $@; do + if [[ -s "${pidfile}" ]]; then + pkill -SIGTERM -F ${pidfile} 2>&1 > /dev/null + fi + + # If failure occurred during or before qemu start up, then we need + # to clean this up ourselves. + if [[ -e "${pidfile}" ]]; then + rm "${pidfile}" + fi + done } =20 check_args() { @@ -189,7 +275,13 @@ handle_build() { } =20 vm_start() { + local cid=3D$1 + local ns=3D$2 + local verify_boot=3D${3:-1} + local pidfile=3D${4:-} + local logfile=3D/dev/null + local qemu_opts=3D"" local verbose_opt=3D"" local kernel_opt=3D"" local qemu @@ -201,35 +293,53 @@ vm_start() { logfile=3D/dev/stdout fi =20 + qemu_opts=3D"\ + ${QEMU_OPTS} -device vhost-vsock-pci,guest-cid=3D${cid} \ + --pidfile ${pidfile} + " + if [[ "${BUILD}" -eq 1 ]]; then kernel_opt=3D"${KERNEL_CHECKOUT}" fi =20 - vng \ + if [[ ! -z "${ns}" ]]; then + NS_EXEC=3D"ip netns exec ${ns}" + fi + + if [[ -z "${pidfile}" ]]; then + pidfile=3D$(mktemp $PIDFILE_TEMPLATE) + PIDFILES+=3D("${pidfile}") + fi + + ${NS_EXEC} vng \ --run \ ${kernel_opt} \ ${verbose_opt} \ - --qemu-opts=3D"${QEMU_OPTS}" \ + --qemu-opts=3D"${qemu_opts}" \ --qemu=3D"${qemu}" \ --user root \ --append "${KERNEL_CMDLINE}" \ --rw &> ${logfile} & =20 - if ! timeout ${WAIT_TOTAL} \ - bash -c 'while [[ ! -s '"${QEMU_PIDFILE}"' ]]; do sleep 1; done; exit 0'= ; then - die "failed to boot VM" - fi + timeout ${WAIT_TOTAL} \ + bash -c 'while [[ ! -s '"${pidfile}"' ]]; do sleep 1; done; exit 0' } =20 vm_wait_for_ssh() { + local ns=3D"${1}" local i =20 i=3D0 - while true; do + while [[ true ]]; do if [[ ${i} -gt ${WAIT_PERIOD_MAX} ]]; then die "Timed out waiting for guest ssh" fi - if vm_ssh -- true; then + if [[ ! -z "${ns}" ]]; then + vm_ssh_ns "${ns}" -- true + else + vm_ssh -- true + fi + if [[ $? -eq 0 ]]; then break fi i=3D$(( i + 1 )) @@ -262,8 +372,9 @@ wait_for_listener() =20 vm_wait_for_listener() { local port=3D$1 + local host_ns=3D$2 =20 - vm_ssh <&1 | log_host "${testname}" =20 return $? @@ -343,7 +465,7 @@ test_vm_client_host_server() { ${VSOCK_TEST} \ --mode "server" \ --control-port "${TEST_HOST_PORT_LISTENER}" \ - --peer-cid "${VSOCK_CID}" 2>&1 | log_host "${testname}" & + --peer-cid "${DEFAULT_CID}" 2>&1 | log_host "${testname}" & =20 host_wait_for_listener =20 @@ -376,6 +498,309 @@ test_vm_loopback() { return $? } =20 +add_namespaces() { + local init=3D${1:-0} + + for mode in "${MODES[@]}"; do + if ! ip netns add "${mode}"; then + return ${KSFT_FAIL} + fi + + # e.g., global-2, local-2, mixed-2 + if ! ip netns add "${mode}-2"; then + return ${KSFT_FAIL} + fi + + if [[ ${init} -eq 1 ]]; then + ns_set_mode "${mode}" "${mode}" + ns_set_mode "${mode}-2" "${mode}" + + # we need lo for qemu port forwarding + ip netns exec "${mode}" ip link set dev lo up + ip netns exec "${mode}-2" ip link set dev lo up + fi + done + return 0 +} + +del_namespaces() { + for mode in "${MODES[@]}"; do + ip netns del "${mode}" + ip netns del "${mode}-2" + done &>/dev/null +} + +ns_set_mode() { + local ns=3D$1 + local mode=3D$2 + + echo "${mode}" \ + | ip netns exec "${ns}" \ + tee /proc/net/vsock_ns_mode &>/dev/null +} + +setup_bridge() { + local ns0 + local ns1 + local addr1 + + ns0=3D$1 + ns1=3D$2 + + ip link add veth0 type veth peer name veth1 + ip link set veth0 netns "${ns0}" + ip link set veth1 netns "${ns1}" + ip netns exec "${ns0}" ip addr add 10.0.0.1/24 dev veth0 + ip netns exec "${ns1}" ip addr add 10.0.0.2/24 dev veth1 + ip netns exec "${ns0}" ip link set veth0 up + ip netns exec "${ns1}" ip link set veth1 up +} + +teardown_bridge() { + local ns0=3D"${1}" + + # veth1 is implicitly destroyed with veth0 + ip netns exec "${ns0}" ip link delete veth0 +} + +test_host_vsock_ns_mode() { + if ! add_namespaces; then + return ${KSFT_FAIL} + fi + + for mode in "${MODES[@]}"; do + if ! ns_set_mode "${mode}" "${mode}"; then + del_namespaces + return ${KSFT_FAIL} + fi + done + + if ! del_namespaces; then + return ${KSFT_FAIL} + fi +} + +test_host_vsock_ns_mode_write_once() { + if ! add_namespaces; then + return ${KSFT_FAIL} + fi + + for mode in "${MODES[@]}"; do + if ! ns_set_mode "${mode}" "${mode}"; then + del_namespaces + return ${KSFT_FAIL} + fi + + # try setting back to global, should fail + if ns_set_mode "${mode}" "global"; then + del_namespaces + return ${KSFT_FAIL} + fi + done + + if ! del_namespaces; then + return ${KSFT_FAIL} + fi +} + +namespaces_can_boot_same_cid() { + local ns1=3D$1 + local ns2=3D$2 + local cid=3D20 + local pidfile1 + local pidfile2 + local msg + + if ! add_namespaces 1; then + return 1 + fi + + if [[ ${VERBOSE} -gt 0 ]]; then + echo "booting vm 1" | tap_prefix + fi + + pidfile1=3D$(mktemp $PIDFILE_TEMPLATE) + PIDFILES+=3D("${pidfile1}") + vm_start ${cid} ${ns1} ${pidfile1} + + if [[ ${VERBOSE} -gt 0 ]]; then + echo "booting vm 2" | tap_prefix + fi + + pidfile2=3D$(mktemp $PIDFILE_TEMPLATE) + PIDFILES+=3D("${pidfile2}") + WAIT_TOTAL=3D30 vm_start ${cid} ${ns2} ${pidfile2} + + rc=3D$? + if [[ $rc -eq 0 ]]; then + msg=3D"successfully booted" + rc=3D0 + else + msg=3D"failed to boot" + rc=3D1 + fi + + if [[ ${VERBOSE} -gt 0 ]]; then + echo "vm 2 ${msg}" | tap_prefix + fi + if ! del_namespaces; then + echo "failed to delete namespaces" | tap_prefix + fi + + terminate_pidfiles ${pidfile1} ${pidfile2} + return $rc +} + +test_global_same_cid() { + if namespaces_can_boot_same_cid "global" "global-2"; then + return $KSFT_FAIL + fi + + return $KSFT_PASS +} + +test_local_global_same_cid() { + if namespaces_can_boot_same_cid "local" "global"; then + return $KSFT_PASS + fi + + return $KSFT_FAIL +} + +test_global_local_same_cid() { + if namespaces_can_boot_same_cid "global" "local"; then + return $KSFT_PASS + fi + + return $KSFT_FAIL +} + +test_local_same_cid() { + if namespaces_can_boot_same_cid "local" "local"; then + return $KSFT_FAIL + fi + + return $KSFT_PASS +} + +test_global_host_connect_global_vm() { + local testname=3D"${FUNCNAME[0]#test_}" + local cid=3D${DEFAULT_CID} + local port=3D1234 + local host_ns=3D"global" + local host_ns2=3D"global-2" + + add_namespaces 1 + setup_bridge "${host_ns}" "${host_ns2}" + + # Start server in VM in namespace + if ! vm_start ${cid} "${host_ns}"; then + teardown_bridge "${host_ns}" + return $KSFT_FAIL + fi + + vm_ssh_ns "${host_ns}" \ + -- "${VSOCK_TEST}" \ + --mode=3Dserver \ + --control-port=3D"${TEST_GUEST_PORT}" \ + --peer-cid=3D2 \ + 2>&1 | log_guest "${testname}" & + vm_wait_for_listener ${TEST_GUEST_PORT} "${host_ns}" + + # Setup NS-to-NS "bridge"=20 + ip netns exec "${host_ns}" socat TCP-LISTEN:${BRIDGE_PORT},fork \ + TCP-CONNECT:localhost:${TEST_HOST_PORT} & + host_ns_wait_for_listener "${host_ns}" "${BRIDGE_PORT}" + + ip netns exec "${host_ns2}" \ + socat TCP:10.0.0.1:${BRIDGE_PORT} TCP-LISTEN:${TEST_HOST_PORT},fork & + host_ns_wait_for_listener "${host_ns2}" "${TEST_HOST_PORT}" + + # Start client in other namespace + ip netns exec "${host_ns2}" ${VSOCK_TEST} \ + --mode=3Dclient \ + --control-host=3D127.0.0.1 \ + --peer-cid=3D"${cid}" \ + --control-port=3D"${TEST_HOST_PORT}" 2>&1 | log_host "${testname}" + rc=3D$? + + if [[ ! $rc -eq 0 ]]; then + return $KSFT_FAIL + fi + + del_namespaces + + return $KSFT_PASS +} + +do_ns_vm_client_host_server_test() { + local testname=3D"$1" + local host_ns=3D"$2" + local host_ns2=3D"$3" + local cid=3D${DEFAULT_CID} + + # must not be same as qemu hostfwd port + local port=3D12345 + + add_namespaces 1 + setup_bridge "${host_ns}" "${host_ns2}" + + if ! vm_start ${cid} "${host_ns}"; then + teardown_bridge "${host_ns}" + return $KSFT_FAIL + fi + + ip netns exec "${host_ns2}" ${VSOCK_TEST} \ + --mode=3Dserver \ + --peer-cid=3D"${cid}" \ + --control-port=3D"${port}" 2>&1 | log_host "${testname}" & + + host_ns_wait_for_listener "${host_ns2}" "${port}" + + ip netns exec "${host_ns2}" \ + socat TCP-LISTEN:${BRIDGE_PORT},bind=3D10.0.0.2,fork \ + TCP:localhost:${port} & + + host_ns_wait_for_listener "${host_ns2}" "${BRIDGE_PORT}" + + ip netns exec "${host_ns}" socat TCP-LISTEN:${port},fork \ + TCP-CONNECT:10.0.0.2:${BRIDGE_PORT} & + + host_ns_wait_for_listener "${host_ns}" "${port}" + + vm_ssh_ns "${host_ns}" \ + -- "${VSOCK_TEST}" \ + --mode=3Dclient \ + --control-host=3D10.0.2.2 \ + --control-port=3D"${port}" \ + --peer-cid=3D2 \ + 2>&1 | log_guest "${testname}" + + if [[ ! $? -eq 0 ]]; then + return $KSFT_FAIL + fi + + del_namespaces + + return $KSFT_PASS +} + +test_global_vm_connect_global_host() { + local testname=3D"${FUNCNAME[0]#test_}" + local host_ns=3D"global" + local host_ns2=3D"global-2" + + do_ns_vm_client_host_server_test ${testname} ${host_ns} ${host_ns2} +} + +test_global_vm_connect_mixed_host() { + local testname=3D"${FUNCNAME[0]#test_}" + local host_ns=3D"global" + local host_ns2=3D"mixed" + + do_ns_vm_client_host_server_test ${testname} ${host_ns} ${host_ns2} +} + run_test() { local host_oops_cnt_before local host_warn_cnt_before @@ -421,7 +846,40 @@ run_test() { rc=3D$KSFT_FAIL fi =20 - return "${rc}" + check_result "${rc}" +} + +needs_setup() { + local tname + + tname=3D"$1" + + for testname in ${NEEDS_SETUP[@]}; do + if [[ "${tname}" =3D=3D "${testname}" ]]; then + return 1 + fi + done + + return 0 +} + +check_result() { + local rc + + rc=3D$1 + + if [[ ${rc} -eq $KSFT_PASS ]]; then + cnt_pass=3D$(( cnt_pass + 1 )) + echo "ok ${cnt_total} ${arg}" + elif [[ ${rc} -eq $KSFT_SKIP ]]; then + cnt_skip=3D$(( cnt_skip + 1 )) + echo "ok ${cnt_total} ${arg} # SKIP" + elif [[ ${rc} -eq $KSFT_FAIL ]]; then + cnt_fail=3D$(( cnt_fail + 1 )) + echo "not ok ${cnt_total} ${arg} # exit=3D$rc" + fi + + cnt_total=3D$(( cnt_total + 1 )) } =20 QEMU=3D"qemu-system-$(uname -m)" @@ -452,29 +910,36 @@ handle_build =20 echo "1..${#ARGS[@]}" =20 -log_setup "Booting up VM" -vm_start -vm_wait_for_ssh -log_setup "VM booted up" - cnt_pass=3D0 cnt_fail=3D0 cnt_skip=3D0 cnt_total=3D0 +setup_done=3D0 + +pidfile=3D"" +for arg in ${ARGS[@]}; do + if needs_setup "${arg}"; then + if [[ -z "${pidfile}" ]]; then + pidfile=3D$(mktemp $PIDFILE_TEMPLATE) + log_setup "Booting up VM" + vm_start "${DEFAULT_CID}" "" "${pidfile}" + vm_wait_for_ssh + log_setup "VM booted up" + fi + + run_test "${arg}" + fi +done + +if [[ ! -z "${pidfile}" ]]; then + log_setup "VM terminate" + terminate_pidfiles "${pidfile}" +fi + for arg in "${ARGS[@]}"; do - run_test "${arg}" - rc=3D$? - if [[ ${rc} -eq $KSFT_PASS ]]; then - cnt_pass=3D$(( cnt_pass + 1 )) - echo "ok ${cnt_total} ${arg}" - elif [[ ${rc} -eq $KSFT_SKIP ]]; then - cnt_skip=3D$(( cnt_skip + 1 )) - echo "ok ${cnt_total} ${arg} # SKIP" - elif [[ ${rc} -eq $KSFT_FAIL ]]; then - cnt_fail=3D$(( cnt_fail + 1 )) - echo "not ok ${cnt_total} ${arg} # exit=3D$rc" + if ! needs_setup "${arg}"; then + run_test "${arg}" fi - cnt_total=3D$(( cnt_total + 1 )) done =20 echo "SUMMARY: PASS=3D${cnt_pass} SKIP=3D${cnt_skip} FAIL=3D${cnt_fail}" --=20 2.47.1