# How to test Vhost-user net with OpenVSwitch/DPDK The purpose of this document is to illustrate how to test vhost-user-net in cloud-hypervisor with OVS/DPDK as the backend. This document was tested with Open vSwitch v2.17.8, DPDK v21.11.4, and Cloud Hypervisor v37.0 on Ubuntu 22.04.3 (host kernel v5.15.0). ## Framework It's a simple test to validate the communication between two virtual machine, connecting them to vhost-user ports respectively provided by `OVS/DPDK`. ``` +----+----------+ +-------------+-----------+-------------+ +----------+----+ | | | | | | | | | | | |vhost-user|----------| vhost-user | ovs | vhost-user |----------|vhost-user| | | |net device| | port 1 | | port 2 | |net device| | | | | | | | | | | | | +----------+ +-------------+-----------+-------------+ +----------+ | | | | | | | |vm1 | | dpdk | | vm2 | | | | | | | +--+---------------------------------------------------------------------------------------------+--+ | | hugepages | | | +---------------------------------------------------------------------------------------------+ | | | | host | | | +---------------------------------------------------------------------------------------------------+ ``` ## Prerequisites Prior to running the test, the following steps need to be performed. - Enable hugepages - Install DPDK - Install OVS Here is a good reference for setting up OVS with DPDK from scratch: https://docs.openvswitch.org/en/latest/intro/install/dpdk/. On Ubuntu systems (18.04 or newer), the OpenVswitch-DPDK package can be easily installed with: ```bash sudo apt-get update sudo apt-get install openvswitch-switch-dpdk sudo update-alternatives --set ovs-vswitchd /usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdk ``` ## Test The test runs with multiple queue (MQ) support enabled, using 2 pairs of TX/RX queues defined for both OVS and the virtual machine. Here are the detailed instructions. _Setup OVS_ Here is an example how to configure a basic OpenVswitch using DPDK: ```bash # load the ovs kernel module modprobe openvswitch sudo service openvswitch-switch start ovs-vsctl init ovs-vsctl set Open_vSwitch . other_config:dpdk-init=true # run on core 0-3 only ovs-vsctl set Open_vSwitch . other_config:dpdk-lcore-mask=0xf # allocate 2G huge pages (to NUMA 0 only) ovs-vsctl set Open_vSwitch . other_config:dpdk-socket-mem=1024 # run PMD (Pull Mode Driver) threads on core 0-3 only ovs-vsctl set Open_vSwitch . other_config:pmd-cpu-mask=0xf sudo service openvswitch-switch restart # double check the configurations ovs-vsctl list Open_vSwitch ``` Here is an example how to create a bridge and add two DPDK ports to it (for later use via Cloud Hypervisor): ```bash # create a bridge ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev # create two DPDK ports and add them to the bridge ovs-vsctl add-port ovsbr0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuserclient options:vhost-server-path=/tmp/vhost-user1 ovs-vsctl add-port ovsbr0 vhost-user2 -- set Interface vhost-user2 type=dpdkvhostuserclient options:vhost-server-path=/tmp/vhost-user2 # set the number of rx queues ovs-vsctl set Interface vhost-user1 options:n_rxq=2 ovs-vsctl set Interface vhost-user2 options:n_rxq=2 ``` _Launch the VMs_ VMs run in client mode. They connect to the socket created by the `dpdkvhostuser` backend. ```bash # From one terminal. We need to give the cloud-hypervisor binary the NET_ADMIN capabilities for it to set TAP interfaces up on the host. ./cloud-hypervisor \ --cpus boot=2 \ --memory size=512M,hugepages=on,shared=true \ --kernel vmlinux \ --cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \ --disk path=focal-server-cloudimg-amd64.raw \ --net mac=52:54:00:02:d9:01,vhost_user=true,socket=/tmp/vhost-user1,num_queues=4,vhost_mode=server # From another terminal. We need to give the cloud-hypervisor binary the NET_ADMIN capabilities for it to set TAP interfaces up on the host. ./cloud-hypervisor \ --cpus boot=2 \ --memory size=512M,hugepages=on,shared=true \ --kernel vmlinux \ --cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \ --disk path=focal-server-cloudimg-amd64.raw \ --net mac=52:54:20:11:C5:02,vhost_user=true,socket=/tmp/vhost-user2,num_queues=4,vhost_mode=server ``` _Setup VM1_ ```bash # From inside the guest sudo ip addr add 172.100.0.1/24 dev ens3 sudo ip link set up dev ens3 ``` _Setup VM2_ ```bash # From inside the guest sudo ip addr add 172.100.0.2/24 dev ens3 sudo ip link set up dev ens3 ``` _Ping VM1 from VM2_ ```bash # From inside the guest sudo ping 172.100.0.1 ``` _Ping VM2 from VM1_ ```bash # From inside the guest sudo ping 172.100.0.2 ``` __Result:__ At this point, VM1 and VM2 can ping each other successfully. We can now run `iperf3` test. _Run VM1 as server_ ```bash # From inside the guest iperf3 -s -p 4444 ``` _Run VM2 as client_ ```bash # From inside the guest iperf3 -c 172.100.0.1 -t 30 -p 4444 & ```