summaryrefslogtreecommitdiffstats
path: root/test/scripts/run_vpp_in_vm.sh
diff options
context:
space:
mode:
authorNaveen Joy <najoy@cisco.com>2021-05-11 10:31:18 -0700
committerNaveen Joy <najoy@cisco.com>2022-08-04 12:19:35 -0700
commit7ea7ab5f215a95dbc1a38acc03b7fea6d3dbedcf (patch)
tree0fbc23c6fc67019a785c577204ca01a26272a173 /test/scripts/run_vpp_in_vm.sh
parent157e4f5d249a262bd8a9c920b8591411e179763c (diff)
tests: run a test inside a QEMU VM
Use the script test/run.py to run a test named test_vm_tap inside a QEMU VM. The run script builds out a virtual env, launches a light weight QEMU VM, mounts host directories, starts VPP inside the VM and runs the test. The test named test_vm_tap, creates two tap v2 interfaces in separate Linux namespaces and using iPerf, streams traffic between the VM and VPP. All data files are stored in the directory named /tmp/vpp-vm-tests. To clean up, use the make test-wipe command. Usage: test/run.py --vm --debug --test test_vm_tap Type: improvement Change-Id: I4425dbef52acee1e5b8af5acaa169b89a2c0f171 Signed-off-by: Naveen Joy <najoy@cisco.com>
Diffstat (limited to 'test/scripts/run_vpp_in_vm.sh')
-rwxr-xr-xtest/scripts/run_vpp_in_vm.sh198
1 files changed, 198 insertions, 0 deletions
diff --git a/test/scripts/run_vpp_in_vm.sh b/test/scripts/run_vpp_in_vm.sh
new file mode 100755
index 00000000000..8b8d14e9af3
--- /dev/null
+++ b/test/scripts/run_vpp_in_vm.sh
@@ -0,0 +1,198 @@
+#!/usr/bin/env bash
+# Run VPP in a QEMU VM
+# set -o xtrace
+set -o nounset
+
+# Arguments:
+# $1:- Test Filter
+# $2:- Kernel Image
+# $3:- Test Data Directory
+# $4:- CPU Mask String (e.g. "5,6,7,8")
+# $5:- Guest MEM in Gibibytes (e.g. 2G)
+
+if [[ -z "${1:-}" ]]; then
+ echo "ERROR: A non-empty test selection is required to run
+ tests in a QEMU VM"
+ exit 1
+fi
+TEST=${1:-}
+TEST_JOBS=${TEST_JOBS:-1}
+
+# Init RAM disk image to boot the QEMU VM
+INITRD=${INITRD:-}
+
+# Ensure test dir
+TEST_DATA_DIR=${3:-"/tmp/vpp-vm-tests"}
+if [[ ! -d ${TEST_DATA_DIR} ]]; then
+ mkdir -p ${TEST_DATA_DIR}
+fi
+
+# CPU Affinity for taskset
+CPU_MASK=${4:-"5,6,7,8"}
+IFS=',' read -r -a CPU_MASK_ARRAY <<< ${CPU_MASK}
+CPUS=${#CPU_MASK_ARRAY[@]}
+
+# Guest MEM (Default 2G)
+MEM=${5:-"2G"}
+
+# Set the QEMU executable for the OS pkg.
+os_VENDOR=$(lsb_release -i -s)
+if [[ $os_VENDOR =~ (Debian|Ubuntu) ]]; then
+ os_PACKAGE="deb"
+ QEMU=${QEMU:-"qemu-system-x86_64"}
+else
+ os_PACKAGE="rpm"
+ QEMU=${QEMU:-"qemu-kvm"}
+fi
+
+# Exit if the ${QEMU} executable is not available
+if ! command -v ${QEMU} &> /dev/null; then
+ echo "Error: ${QEMU} is required, but could not be found."
+ exit 1
+fi
+
+# Download the Generic Linux Kernel, if needed
+if [[ -z "${2:-}" ]] || [[ ! -f "${2:-}" ]]; then
+ if [[ $os_PACKAGE == "deb" ]]; then
+ PWD=$(pwd)
+ cd ${TEST_DATA_DIR}
+ PKG="linux-image-$(uname -r)"
+ echo "Getting the Linux Kernel image..${PKG}"
+ apt-get download ${PKG}
+ dpkg --fsys-tarfile ${PKG}_*.deb | tar xvf - ./boot
+ KERNEL_BIN=$(ls ${TEST_DATA_DIR}/boot/vmlinuz-*-generic)
+ cd ${PWD}
+ else
+ echo "ERROR: Kernel Image selection is required for RPM pkgs."
+ exit 1
+ fi
+else
+ KERNEL_BIN=${2:-}
+fi
+
+## Create initrd with 9p drivers, if ${INITRD} is null
+DRIVERS_9P=""
+if [[ -z "${INITRD}" ]] && [[ ! -d "/etc/initramfs-tools" ]]; then
+ echo "To boot the QEMU VM, an initial RAM disk with 9p drivers is needed"
+ echo "Install the initramfs-tools package or set env var INITRD to the RAM disk path"
+ exit 1
+elif [[ -z "${INITRD}" ]]; then
+ if [[ -f "/etc/initramfs-tools/modules" ]]; then
+ DRIVERS_9P=$(grep 9p /etc/initramfs-tools/modules | awk '{print $1}' | cut -d$'\n' -f1)
+ fi
+ if [[ -z "${DRIVERS_9P}" ]]; then
+ echo "You'll need to update the file /etc/initramfs-tools/modules with the below 9p drivers"
+ echo "9p >> /etc/initramfs-tools/modules"
+ echo "9pnet >> /etc/initramfs-tools/modules"
+ echo "9pnet_virtio >> /etc/initramfs-tools/modules"
+ exit 1
+ fi
+ # Generate the initramfs image, if the we haven't generated one yet
+ if ! ls ${TEST_DATA_DIR}/boot/initrd.img-*-generic &> /dev/null; then
+ echo "Generating a bootable initramfs image in ${TEST_DATA_DIR}/boot/"
+ update-initramfs -c -k $(uname -r) -b ${TEST_DATA_DIR}/boot >/dev/null 2>&1
+ echo "Generated the INITRD image"
+ fi
+ INITRD=$(ls ${TEST_DATA_DIR}/boot/initrd.img-*-generic)
+fi
+echo "Using INITRD=${TEST_DATA_DIR}/boot/${INITRD} for booting the QEMU VM"
+
+
+## Install iperf into ${TEST_DATA_DIR}
+IPERF=${TEST_DATA_DIR}/usr/bin/iperf
+if [[ ! -x ${IPERF} ]] && [[ $os_PACKAGE == "deb" ]]; then
+ echo "Installing iperf: ${IPERF}"
+ PWD=$(pwd)
+ cd ${TEST_DATA_DIR}
+ IPRF_PKG="iperf_2.0.5+dfsg1-2_amd64.deb"
+ wget https://iperf.fr/download/ubuntu/${IPRF_PKG}
+ dpkg --fsys-tarfile ${IPRF_PKG} | tar xvf -
+ if [[ -x ${IPERF} ]]; then
+ echo "${IPERF} installed successfully"
+ else
+ echo "ERROR: iperf executable ${IPERF} installation failed"
+ exit 1
+ fi
+ cd ${PWD}
+elif [[ ! -x ${IPERF} ]] && [[ $os_PACKAGE != "deb" ]]; then
+ echo "ERROR: install iperf: ${IPERF} before running QEMU tests"
+ exit 1
+fi
+
+FAILED_DIR=${FAILED_DIR:-"/tmp/vpp-failed-unittests/"}
+if [[ ! -d ${FAILED_DIR} ]]; then
+ mkdir -p ${FAILED_DIR}
+fi
+
+HUGEPAGES=${HUGEPAGES:-256}
+
+# Ensure all required Env vars are bound to non-zero values
+EnvVarArray=("WS_ROOT=${WS_ROOT:-}"
+ "RND_SEED=${RND_SEED:-}"
+ "BR=${BR:-}"
+ "VENV_PATH=${VENV_PATH:-}"
+ "VPP_BUILD_DIR=${VPP_BUILD_DIR:-}"
+ "VPP_BIN=${VPP_BIN:-}"
+ "VPP_PLUGIN_PATH=${VPP_PLUGIN_PATH:-}"
+ "VPP_TEST_PLUGIN_PATH=${VPP_TEST_PLUGIN_PATH:-}"
+ "VPP_INSTALL_PATH=${VPP_INSTALL_PATH:-}"
+ "LD_LIBRARY_PATH=${LD_LIBRARY_PATH:-}")
+
+for envVar in ${EnvVarArray[*]}; do
+ var_name=$(echo $envVar | cut -d= -f1)
+ var_val=$(echo $envVar | cut -d= -f2)
+ if [[ -z "$var_val" ]]; then
+ echo "ERROR: Env var: $var_name is not set"
+ exit 1
+ fi
+done
+
+# Boot QEMU VM and run the test
+function run_in_vm {
+ INIT=$(mktemp -p ${TEST_DATA_DIR})
+ cat > ${INIT} << _EOF_
+#!/bin/bash
+mkdir -p /dev/shm
+mount -t tmpfs -o rw,nosuid,nodev tmpfs /dev/shm
+mount -t devpts -o noexec,nosuid,gid=5,mode=0620 devpts /dev/pts || true
+mount -t tmpfs -o "noexec,nosuid,size=10%,mode=0755" tmpfs /run
+mount -t 9p /dev/vpp9p ${WS_ROOT}
+mount -t 9p tmp9p /tmp
+modprobe -a vhost_net
+env SOCKET=1 SANITY=no \
+FAILED_DIR=${FAILED_DIR} RND_SEED=${RND_SEED} BR=${BR} \
+VENV_PATH=${VENV_PATH} TEST=${TEST} TEST_JOBS=${TEST_JOBS} \
+VPP_BUILD_DIR=${VPP_BUILD_DIR} VPP_BIN=${VPP_BIN} VPP_PLUGIN_PATH=${VPP_PLUGIN_PATH} \
+VPP_TEST_PLUGIN_PATH=${VPP_TEST_PLUGIN_PATH} VPP_INSTALL_PATH=${VPP_INSTALL_PATH} \
+LD_LIBRARY_PATH=${LD_LIBRARY_PATH} TEST_DATA_DIR=${TEST_DATA_DIR} INITRD=${INITRD} \
+bash -c "${WS_ROOT}/test/scripts/run.sh --filter=${TEST} --jobs=${TEST_JOBS} --failed-dir=${FAILED_DIR} \
+--venv-dir=${VENV_PATH} --vpp-ws-dir=${WS_ROOT} --extended"
+poweroff -f
+_EOF_
+
+ chmod +x ${INIT}
+
+ sudo taskset -c ${CPU_MASK} ${QEMU} \
+ -nodefaults \
+ -name test_$(basename $INIT) \
+ -chardev stdio,mux=on,id=char0 \
+ -mon chardev=char0,mode=readline,pretty=on \
+ -serial chardev:char0 \
+ -machine pc,accel=kvm,usb=off,mem-merge=off \
+ -cpu host \
+ -smp ${CPUS},sockets=1,cores=${CPUS},threads=1 \
+ -m ${MEM} \
+ -no-user-config \
+ -kernel ${KERNEL_BIN} \
+ -initrd ${INITRD} \
+ -fsdev local,id=root9p,path=/,security_model=none,multidevs=remap \
+ -device virtio-9p-pci,fsdev=root9p,mount_tag=fsRoot \
+ -virtfs local,path=${WS_ROOT},mount_tag=/dev/vpp9p,security_model=none,id=vpp9p,multidevs=remap \
+ -virtfs local,path=/tmp,mount_tag=tmp9p,security_model=passthrough,id=tmp9p,multidevs=remap \
+ -netdev tap,id=net0,vhost=on \
+ -device virtio-net-pci,netdev=net0,mac=52:54:00:de:64:01 \
+ -nographic \
+ -append "ro root=fsRoot rootfstype=9p rootflags=trans=virtio,cache=mmap console=ttyS0 hugepages=${HUGEPAGES} init=${INIT}"
+ }
+
+run_in_vm