On Fri, Apr 11, 2025 at 10:32:45AM +0200, Stefano Garzarella wrote:
On Thu, Apr 10, 2025 at 06:07:59PM -0700, Bobby Eshleman wrote:
This commit introduces a new vmtest.sh runner for vsock.
It uses virtme-ng/qemu to run tests in a VM. The tests are designed to validate both G2H and H2G paths. The testing tools from tools from tools/testing/vsock/ are reused. Currently, only vsock_test is used.
Coool, thanks for that. I'll leave some comments, but I'll try this next week since today I'm a bit busy.
Only tested on x86.
To run:
$ tools/testing/selftests/vsock/vmtest.sh
Signed-off-by: Bobby Eshleman bobbyeshleman@gmail.com
MAINTAINERS | 1 + tools/testing/selftests/vsock/.gitignore | 1 + tools/testing/selftests/vsock/config.vsock | 6 + tools/testing/selftests/vsock/vmtest.sh | 247 +++++++++++++++++++++++++++++ 4 files changed, 255 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS index c3fce441672349f7850c57d788bc1a29b203fba5..f214cf7c4fb59ec67885ee6c81daa44e17c80f5f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -25323,6 +25323,7 @@ F: include/uapi/linux/vm_sockets.h F: include/uapi/linux/vm_sockets_diag.h F: include/uapi/linux/vsockmon.h F: net/vmw_vsock/ +F: tools/testing/selftests/vsock/ F: tools/testing/vsock/
VMALLOC diff --git a/tools/testing/selftests/vsock/.gitignore b/tools/testing/selftests/vsock/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..1950aa8ac68c0831c12c1aaa429da45bbe41e60f --- /dev/null +++ b/tools/testing/selftests/vsock/.gitignore @@ -0,0 +1 @@ +vsock_selftests.log diff --git a/tools/testing/selftests/vsock/config.vsock b/tools/testing/selftests/vsock/config.vsock new file mode 100644 index 0000000000000000000000000000000000000000..a229c329d44e4a0b650d073b74949b577da3dc64 --- /dev/null +++ b/tools/testing/selftests/vsock/config.vsock @@ -0,0 +1,6 @@ +CONFIG_VSOCKETS=y +CONFIG_VSOCKETS_DIAG=y +CONFIG_VSOCKETS_LOOPBACK=y +CONFIG_VIRTIO_VSOCKETS=y +CONFIG_VIRTIO_VSOCKETS_COMMON=y +CONFIG_VHOST_VSOCK=y
Should we enabled also other transports?
(I'm not sure since we don't test it)
Probably for the best to catch things that break the build?
diff --git a/tools/testing/selftests/vsock/vmtest.sh b/tools/testing/selftests/vsock/vmtest.sh new file mode 100755 index 0000000000000000000000000000000000000000..f2dafcb893232f95ebb22104a62ce1e0312f4e89 --- /dev/null +++ b/tools/testing/selftests/vsock/vmtest.sh @@ -0,0 +1,247 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2025 Meta Platforms, Inc. and affiliates +# +# Dependencies: +# * virtme-ng +# * busybox-static (used by virtme-ng) +# * qemu (used by virtme-ng)
+SCRIPT_DIR="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" +KERNEL_CHECKOUT=$(realpath ${SCRIPT_DIR}/../../../..) +PLATFORM=${PLATFORM:-$(uname -m)}
+if [[ -z "${QEMU:-}" ]]; then
- QEMU=$(which qemu-system-${PLATFORM})
+fi
+VSOCK_TEST=${KERNEL_CHECKOUT}/tools/testing/vsock/vsock_test
+TEST_GUEST_PORT=51000 +TEST_HOST_PORT=50000 +TEST_HOST_PORT_LISTENER=50001 +SSH_GUEST_PORT=22 +SSH_HOST_PORT=2222 +VSOCK_CID=1234
+QEMU_PIDFILE=/tmp/qemu.pid
+# 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 +# adding an additional port to forward to the device created from "--ssh" and +# virtme-init mistakenly sets identical IPs to the ssh device and additional +# devices, we instead opt out of using --ssh, add the device manually, and also +# add the kernel cmdline options that virtme-init uses to setup the interface. +QEMU_OPTS="" +QEMU_OPTS="${QEMU_OPTS} -netdev user,id=n0,hostfwd=tcp::${TEST_HOST_PORT}-:${TEST_GUEST_PORT}" +QEMU_OPTS="${QEMU_OPTS},hostfwd=tcp::${SSH_HOST_PORT}-:${SSH_GUEST_PORT}" +QEMU_OPTS="${QEMU_OPTS} -device virtio-net-pci,netdev=n0" +QEMU_OPTS="${QEMU_OPTS} -device vhost-vsock-pci,guest-cid=${VSOCK_CID}" +QEMU_OPTS="${QEMU_OPTS} --pidfile ${QEMU_PIDFILE}" +KERNEL_CMDLINE="virtme.dhcp net.ifnames=0 biosdevname=0 virtme.ssh virtme_ssh_user=$USER"
+LOG=${SCRIPT_DIR}/vsock_selftests.log
+# Name Description +tests="
- vm_server_host_client Run vsock_test in server mode on the VM and in client mode on the host.
- vm_client_host_server Run vsock_test in client mode on the VM and in server mode on the host.
What about adding tests also with loopback in the VM?
Can do!
+"
+usage() {
- echo
- echo "$0 [OPTIONS]"
- echo
- echo "Options"
- echo " -v: verbose output"
- echo
- echo "Available tests${tests}"
- exit 1
+}
+die() {
- echo "$*" >&2
- exit 1
+}
+vm_ssh() {
- ssh -q -o UserKnownHostsFile=/dev/null -p 2222 localhost $*
- return $?
+}
+cleanup() {
- if [[ -f "${QEMU_PIDFILE}" ]]; then
pkill -9 -F ${QEMU_PIDFILE} 2>&1 >/dev/null
- fi
+}
+build() {
- log_setup "Building kernel and tests"
- pushd ${KERNEL_CHECKOUT} >/dev/null
- vng \
--kconfig \
--config ${KERNEL_CHECKOUT}/tools/testing/selftests/vsock/config.vsock
- make -j$(nproc)
- make -C ${KERNEL_CHECKOUT}/tools/testing/vsock
- popd >/dev/null
- echo
+}
+vm_setup() {
- local VNG_OPTS=""
- if [[ "${VERBOSE}" = 1 ]]; then
VNG_OPTS="--verbose"
- fi
- vng \
$VNG_OPTS \
--run ~/local/linux \
--qemu /bin/qemu-system-x86_64 \
--qemu-opts="${QEMU_OPTS}" \
--user root \
--append "${KERNEL_CMDLINE}" \
--rw 2>&1 >/dev/null &
+}
+vm_wait_for_ssh() {
- i=0
- while [[ true ]]; do
if (( i > 20 )); then
die "Timed out waiting for guest ssh"
fi
vm_ssh -- true
if [[ $? -eq 0 ]]; then
break
fi
i=$(( i + 1 ))
sleep 5
- done
+}
+wait_for_listener() {
- local PORT=$1
- local i=0
- while ! ss -ltn | grep -q ":${PORT}"; do
if (( i > 30 )); then
die "Timed out waiting for listener on port ${PORT}"
fi
sleep 3
i=$(( i + 1 ))
- done
+}
+vm_wait_for_listener() {
- vm_ssh -- "$(declare -f wait)for_listener); wait_for_listener
${TEST_GUEST_PORT}" +}
+host_wait_for_listener() {
- wait_for_listener ${TEST_HOST_LISTENER_PORT}
+}
+log() {
- local prefix="$1"
- shift
- if [[ "$#" -eq 0 ]]; then
cat | awk '{ printf "%s:\t%s\n","'"${prefix}"'", $0 }' | tee -a ${LOG}
- else
echo "$*" | awk '{ printf "%s:\t%s\n","'"${prefix}"'", $0 }' | tee -a ${LOG}
- fi
+}
+log_setup() {
- log "setup" "$@"
+}
+log_host() {
- testname=$1
- shift
- log "test:${testname}:host" "$@"
+}
+log_guest() {
- testname=$1
- shift
- log "test:${testname}:guest" "$@"
+}
+test_vm_server_host_client() {
- local testname="vm_server_host_client"
- vm_ssh -- "${VSOCK_TEST}" \
--mode=server \
--control-port="${TEST_GUEST_PORT}" \
--peer-cid=2 \
2>&1 | log_guest "${testname}" &
Strange indentation here.
Got it.
- vm_wait_for_listener
- ${VSOCK_TEST} \
--mode=client \
--control-host=127.0.0.1 \
--peer-cid="${VSOCK_CID}" \
--control-port="${TEST_HOST_PORT}" 2>&1 | log_host "${testname}"
- rc=$?
+}
+test_vm_client_host_server() {
- local testname="vm_client_host_server"
- ${VSOCK_TEST} \
--mode "server" \
--control-port "${TEST_HOST_PORT_LISTENER}" \
--peer-cid "${VSOCK_CID}" 2>&1 | log_host "${testname}" &
- host_wait_for_listener
- vm_ssh -- "${VSOCK_TEST}" \
--mode=client \
--control-host=10.0.2.2 \
--peer-cid=2 \
--control-port="${TEST_HOST_PORT_LISTENER}" 2>&1 | log_guest "${testname}"
- rc=$?
+}
+run_test() {
- unset IFS
- name=$(echo "${1}" | awk '{ print $1 }')
- eval test_"${name}"
+}
+while getopts :hv o +do
- case $o in
- v) VERBOSE=1;;
- h|*) usage;;
- esac
+done +shift $((OPTIND-1))
+trap cleanup EXIT
+> ${LOG} +build +log_setup "Booting up VM" +vm_setup +vm_wait_for_ssh +log_setup "VM booted up"
+IFS=" +" +cnt=0 +for t in ${tests}; do
- rc=0
- run_test "${t}"
- if [[ ${rc} != 0 ]]; then
cnt=$(( cnt + 1 ))
- fi
+done
+if [[ ${cnt} = 0 ]]; then
- echo OK
In my suite I also check if we have some kernel warnings or oops. Should we add something similar or does the infrastructure already handle that?
I think we'll need to add that, AFAIK infra like NIPA depends entirely on the exit code of the test script.
BTW, I'm planning on integrating with NIPA, but that is still TODO.
Thanks, Stefano
Thanks!
-Bobby