网络模拟

QEMU 可模拟多种网卡,例如 PC 的 PCI 或 ISA 卡,并连接到主机网络后端或 模拟集线器。后端可通过 TAP、非特权用户网络栈连接真实网络,也可通过套接字 连接另一个 QEMU 进程中的客户机。

使用 TAP 接口

这是连接真实网络的标准方式。QEMU 在主机添加 tapN 虚拟设备,可像真实 以太网卡一样配置。

Linux 主机

发行版通常提供辅助脚本,默认 /etc/qemu-ifup 和 /etc/qemu-ifdown,QEMU 改变网络状态时按需调用。

非特权运行时,可能需正确配置 sudo,使脚本中的网络命令能以 root 执行。

确认主机内核支持 TAP,即 /dev/net/tun 存在。

命令行示例见 调用方式。

Windows 主机

Windows 2000/XP 的虚拟以太网驱动名为 TAP-Win32,不包含在标准 QEMU Windows 版本中,需要单独获取。它属于 OpenVPN,可从 https://openvpn.net/ 下载。

使用用户模式网络栈

-net user 使用完全用户空间网络,不需 root;未指定 -net 时默认采用。 虚拟网络如下:

guest (10.0.2.15)  <------>  Firewall/DHCP server <-----> Internet
                      |          (10.0.2.2)
                      |
                      ---->  DNS server (10.0.2.3)
                      |
                      ---->  SMB server (10.0.2.4)

虚拟机相当于位于阻止所有传入连接的防火墙后。可以通过 DHCP 自动配置, 地址从 10.0.2.15 开始分配。

检查网络时,可 ping 10.0.2.2,并确认获得 10.0.2.x 地址。

一般 ICMP 不工作,但 ping 本地路由器 10.0.2.2 应可用。Linux 3.0 及以后 可使用非特权 ICMP ping 套接字访问互联网,管理员需设置 ping_group_range。 例如允许 GID 100(通常是 users):

echo 100 100 > /proc/sys/net/ipv4/ping_group_range

使用内置 TFTP 时,路由器也是 TFTP 服务器。

-netdev user,hostfwd=... 可将主机 TCP、UDP 或 Unix 连接重定向到客户机, 例如 X11、telnet 或 SSH。

使用 passt 用户模式网络栈

passt 可直接替代 SLIRP(-net user),不需要任何特权或能力。它性能更好, 完整支持 IPv6,且作为 QEMU 外部守护进程,安全性更好。

可像 user 后端一样使用 -net passt、-netdev passt、-nic passt,也可手动 启动,再通过 -netdev stream 套接字或 -netdev vhost-user 连接。

后两种方式可启用 passt 后端接口尚未提供的功能,例如迁移。

详情见 passt(1)。

使用 passt 后端接口

无需自行启动守护进程,QEMU 会代劳,默认使用套接字模式。

qemu-system-x86_64 [...OPTIONS...] -nic passt

(qemu) info network
e1000e.0: index=0,type=nic,model=e1000e,macaddr=52:54:00:12:34:56
 #net071: index=0,type=passt,stream,connected to pid 24846
qemu-system-x86_64 [...OPTIONS...] -net nic -net passt,tcp-ports=10001,udp-ports=10001

(qemu) info network
hub 0
 hub0port1: #net136: index=0,type=passt,stream,connected to pid 25204
 hub0port0: e1000e.0: index=0,type=nic,model=e1000e,macaddr=52:54:00:12:34:56
qemu-system-x86_64 [...OPTIONS...] -netdev passt,id=netdev0 -device virtio-net,mac=9a:2b:2c:2d:2e:2f,id=virtio0,netdev=netdev0

(qemu) info network
virtio0: index=0,type=nic,model=virtio-net-pci,macaddr=9a:2b:2c:2d:2e:2f
 netdev0: index=0,type=passt,stream,connected to pid 25428

使用 vhost 接口时,添加 vhost-user=on 并选择 virtio-net:

qemu-system-x86_64 [...OPTIONS...] -nic passt,model=virtio,vhost-user=on

(qemu) info network
virtio-net-pci.0: index=0,type=nic,model=virtio-net-pci,macaddr=52:54:00:12:34:56
 #net006: index=0,type=passt,vhost-user,connected to pid 25731

使用套接字 passt 接口

启动守护进程:

passt --socket ~/passt.socket

未提供 --socket 时,会输出可连接路径,如 /tmp/passt_1.socket、 /tmp/passt_2.socket。随后连接 QEMU:

qemu-system-x86_64 [...OPTIONS...] -device virtio-net-pci,netdev=netdev0 -netdev stream,id=netdev0,server=off,addr.type=unix,addr.path=~/passt.socket

~/passt.socket 是 passt 创建的通信套接字。

使用 vhost 接口

以 --vhost-user 启动:

passt --vhost-user --socket ~/passt.socket

然后连接 QEMU:

qemu-system-x86_64 [...OPTIONS...] -m $RAMSIZE -chardev socket,id=chr0,path=~/passt.socket -netdev vhost-user,id=netdev0,chardev=chr0 -device virtio-net,netdev=netdev0 -object memory-backend-memfd,id=memfd0,share=on,size=$RAMSIZE -numa node,memdev=memfd0

$RAMSIZE 为虚拟机内存,-m 必须与 memory-backend-memfd 的 size 匹配。

迁移 passt

使用 vhost-user 时,passt 可随 QEMU 迁移而不中断网络连接。

它无特权运行,因此依赖 passt-repair 通过 TCP_REPAIR 保存和加载 TCP 状态。 辅助程序需要 CAP_NET_ADMIN 或 root。缺少它时,TCP 连接不会保留。

同一主机迁移客户机示例

运行前,以 root 为 passt-repair 设置能力:

setcap cap_net_admin+eip ./passt-repair

启动源端 passt:

passt --vhost-user --socket ~/passt_src.socket --repair-path ~/passt-repair_src.socket

~/passt-repair_src.socket 用于与辅助程序通信,默认路径为 --socket 后加 .repair。

启动 passt-repair:

passt-repair ~/passt-repair_src.socket

启动源端 QEMU,并提供监视器以发送迁移命令:

qemu-system-x86_64 [...OPTIONS...] [...VHOST USER OPTIONS...] -monitor stdio

启动目的端 passt:

passt --vhost-user --socket ~/passt_dst.socket --repair-path ~/passt-repair_dst.socket

启动目的端 passt-repair:

passt-repair ~/passt-repair_dst.socket

启动带 -incoming 的 QEMU:

qemu-system-x86_64 [...OPTIONS...] [...VHOST USER OPTIONS...] -incoming tcp:localhost:4444

在源端监视器启动迁移:

(qemu) migrate tcp:localhost:4444

每次迁移都需要独立 passt-repair。迁移失败后,重试前也需重新启动它。

集线器

QEMU 可模拟多个集线器,作为网卡或 TAP 等设备间的虚拟连接。通过 -netdev hubport 或 -nic hubport 连接客户机网卡或主机后端。旧式 -net 也连接到默认 ID 0 集线器,除非用 -net nic,netdev=xxx 指定后端。

连接多个 QEMU 实例的模拟网络

-netdev socket、-nic socket 或 -net socket 可建立跨多个实例的网络。 基本示例见 调用方式 中 -netdev socket 的说明。