Four VM Network Modes
In one line
The choice in VM networking divides by who processes the packets. User space (SLIRP), the kernel (TAP), a kernel bridge, and virtio processing inside the kernel (vhost-net).
Why you need this
"The internet works from the VM, but I can't get into the VM from outside." The cause of this report is almost always user (SLIRP) mode. It is used as the default in development environments, and if you do not know its characteristics, it goes out to production as it is.
How it works
user (SLIRP)
QEMU implements an entire TCP/IP stack in user space. QEMU interprets the packets the guest sends and rebuilds them as ordinary sockets on the host.
- No privileges are needed at all. This is why it is the only one usable in this lab environment.
- The guest is placed in the
10.0.2.0/24range, with the gateway10.0.2.2and DNS10.0.2.3. - Nothing from the outside can come in to the guest. You have to open individual ports with
hostfwd. - ICMP is limited.
pingoften does not work from the guest, and that is normal. - Performance is low. Every packet passes through user space one more time.
tap
It creates a kernel virtual Ethernet device and QEMU holds one end of it. The packets come up into the kernel network stack as they are, so from the host it looks like a real interface. In exchange, creating a TAP device needs privileges (or permission on a device created in advance).
bridge
You plug the TAP into a Linux bridge. If a physical NIC is also plugged into the bridge, it behaves as if the VM were attached directly to the physical network. The VM gets an internal network address by DHCP, and other servers can connect to that address directly. This is the default configuration in production.
ip link add br0 type bridge
ip link set eth0 master br0
ip link set br0 up
qemu-system-x86_64 -netdev tap,id=n0,ifname=tap0,script=no -device virtio-net-pci,netdev=n0
vhost-net
It does the virtio ring buffer processing inside the kernel. It does not make round trips through QEMU user space, so latency and CPU usage drop significantly. -netdev tap,...,vhost=on.
| Mode | Privileges | Outside→inside access | Performance | Use |
|---|---|---|---|---|
| user | Not needed | Only through hostfwd | Low | Development/testing |
| tap | Needed | Possible | Medium | Isolated VM network |
| bridge | Needed | Possible (directly on the physical network) | Medium to high | Production |
| vhost-net | Needed | Possible | High | High-performance workloads |
What it looks like in the field
Something that worked in development does not work in staging. Development uses user mode, so only port 22 was opened with hostfwd, while staging uses a bridge, so everything is open. Conversely, if you have been accessing only through hostfwd and then move to a bridge, you have to design the firewall anew — because until now QEMU had effectively been acting as the firewall.
MTU problems. When an overlay such as VXLAN is layered on top of a bridge, the effective MTU shrinks. Inside the VM it is still 1500, so large packets quietly vanish. You need to lower the guest MTU or use MSS clamping.
What is the same and what differs from container networking
The four modes seen so far repeat almost as they are on the container side. Only the names differ and the jobs are the same, so if you understand one side, the other comes along for free.
- The VM's user mode ≈ container port forwarding. From inside to outside it goes out, but from outside to inside it comes in only through the ports that have been opened.
- The VM's tap ≈ a container's veth pair. It creates a virtual interface in the kernel and puts one end inside and one end outside.
- The VM's bridge ≈ Docker's default bridge network. You plug several into the same bridge so they can communicate with each other.
- The VM's vhost-net ≈ pushing the data plane down into the kernel or eBPF. It gets faster because it does not make round trips through user space.
There are clear differences too. A container shares the host kernel, so only the network namespace is separated, but a VM holds its own kernel. So changing a kernel parameter inside a VM has no effect on the host, while a considerable number of kernel settings inside a container are shared with the host or cannot be changed at all. Conversely, a VM has a long boot time and reserves its memory in full.
Translated into a practical judgment, it goes like this. If you need to deal with the kernel itself (loading modules, a different kernel version), or need truly high isolation, or need to run something that is not Linux, use a VM. Otherwise, a container is almost always lighter and faster. And mixing the two is common — a typical example is a setup where the Kubernetes node itself is a VM and containers run on top of it, and in that case the network layers stack up two deep, so the MTU problem mentioned earlier shows up especially often.
What comes next
This module covers concepts only. You should now be able to explain why you used -netdev user,hostfwd=... in the earlier vm-boot lab — because it was the only possible choice in an environment without privileges.