This episode builds VM networking: setting up TAP and bridge on the host, connecting a NIC to the guest with --net tap=...,mac=...,ip=..., offloading the data plane to a vhost-user daemon for high performance, and getting to know the still-experimental vDPA. You'll also learn how to build a multi-NIC setup.

With storage sorted in episode 6, it's time to connect the VM to the outside world. Networking in Cloud Hypervisor is built on Linux concepts you already know — TAP devices — and extended with vhost-user for data plane offload and vDPA for hardware virtio.
Think of TAP as a virtual cable running from inside the VM to the host. On the host end, that cable can be plugged into a bridge (like a physical switch) so the VM can talk to other VMs and the outside world. Understanding this model early prevents confusion when VM traffic doesn't flow the way you expect.
A TAP is a virtual L2 interface: packets sent from the VM appear on this interface, and whatever the host writes to the TAP goes into the VM. Cloud Hypervisor creates its own TAP if you give it a name, as long as the binary has CAP_NET_ADMIN (episode 3):
ip link show type tapIf you don't want Cloud Hypervisor to create the TAP automatically, create it manually then hand it to the VMM:
sudo ip tuntap add dev ch0 mode tap user "$USER"
sudo ip link set ch0 upuser "$USER" hands TAP ownership to your user so Cloud Hypervisor can use it without root.
A TAP alone is useless without a route out. Create a bridge, add the TAP and the host NIC to it:
sudo ip link add name br0 type bridge
sudo ip link set ch0 master br0
sudo ip link set br0 upNow VMs connected to ch0 can talk to each other (through br0) and to the outside (if the host NIC is added and routing is set up). Make sure ip_forward is enabled for inter-VM traffic:
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forwardThe most common way to connect an existing TAP to a VM:
cloud-hypervisor \
--kernel kernel-vmlinux \
--disk path=os.raw \
--net tap=ch0,ip=192.168.100.1,mac=a8:21:95:80:35:e6 \
--cpus boot=2 \
--memory size=2Gtap=ch0: use the TAP that was already created.ip=192.168.100.1: the address assigned to the TAP interface on the host side.mac=a8:21:95:80:35:e6: the MAC address for the guest NIC — always set it explicitly for stability (some licenses and DHCP rely on a fixed MAC).If tap isn't specified, Cloud Hypervisor creates a new TAP with the given name — provided the binary has CAP_NET_ADMIN.
A common scenario: one NIC for management, one for data. Present several interfaces:
cloud-hypervisor \
--kernel kernel-vmlinux \
--disk path=os.raw \
--net tap=mgmt,ip=192.168.1.1,mac=a8:21:95:80:00:01 \
--net tap=data,ip=10.0.0.1,mac=a8:21:95:80:00:02 \
--cpus boot=4 \
--memory size=4GInside the guest, the first NIC appears as enp0s2, the second as enp0s3 (the order can differ — don't rely on names alone; use MACs for identification).
After the VM boots, configure the IP inside the guest (example with iproute2):
ip addr add 192.168.100.10/24 dev enp0s2
ip link set enp0s2 up
ip route add default via 192.168.100.1For peak performance, the data plane can be handed to an external daemon via vhost-user. The daemon holds fds that give it direct access to guest memory (via shared memory), so packets don't have to bounce back and forth to the VMM process.
vhost-user-net --socket-path /tmp/vhost-net.sock \
--netdev type=tap,id=net0,ifname=ch0 \
--socket-mem=1024Then connect it to the VM:
cloud-hypervisor \
--kernel kernel-vmlinux \
--disk path=os.raw \
--net vhost_user=true,socket=/tmp/vhost-net.sock,mac=a8:21:95:80:35:e6 \
--cpus boot=2 \
--memory size=2GThe advantage: packets are handled in a daemon that can run on a dedicated CPU core, lowering latency and maximizing throughput. The cost: one extra process that must be kept alive — if the daemon dies, the guest NIC goes down.
Note
vhost-user requires guest memory with shared=on (episode 5), because the daemon needs to map guest memory to access ring buffers and packet buffers. Without it, the VM fails to start with a memory-sharing related error.
vDPA (vhost Data Path Acceleration) is a technology that connects hardware virtio to a VM: physical network devices (like SmartNICs) that support virtio are presented directly to the guest without software emulation. The result: near-native performance with standard virtio drivers.
In Cloud Hypervisor, vDPA support is still experimental. The idea: instead of a userspace daemon, the data plane is handled by hardware; the VMM just connects the guest to the host's vDPA device.
vdpa dev add name vdpa0 mgmtdev pci/0000:01:00.0Because it's experimental and depends on specific hardware, use vDPA only after verifying compatibility in your environment. For most cases, a plain TAP or vhost-user is enough.
When traffic doesn't flow, check in order:
ip addr show br0
ip addr show ch0
ping -c 3 192.168.100.10If the host can ping the guest but the guest has no internet, check routing and forwarding on the host. If there's no traffic at all, check the NIC status inside the guest:
ip addr show
ip link show
ethtool -k enp0s2 | headethtool -k shows offload features — features like TSO/GSO that aren't supported can cause large packets to fail through an incompatible TAP.
Warning
Never share one TAP between two VMs — every VM needs its own interface; sharing them causes MAC conflicts and traffic chaos. Use a bridge to connect multiple VMs, don't share the same TAP.
Key takeaways:
--net tap=...,mac=...,ip=... connects a guest NIC to a host TAP.shared=on.In the next episode, episode 8, we'll cover hotplug: CPU, memory, and devices — adding vCPUs and RAM live with --cpus hotplug and ACPI, its reflection in the guest, and device passthrough with VFIO for GPUs and other devices, including the still-experimental vfio-user. Your VM can now start to "grow" without restarting.