qemu-bridge

在 qemu 中使用桥接网络只需要如下简单配置即可(当然,前提是已经有了可用的桥接口)。

-netdev bridge

-netdev bridge,br=br0,id=net0 \
-device virtio-net-pci,netdev=net0

如果 -netdev 不指定 helper= 参数,则使用默认的 qemu-bridge-helper 程序。

#define DEFAULT_BRIDGE_HELPER CONFIG_QEMU_HELPERDIR "/qemu-bridge-helper"

// qemu/net/tap.c

net_init_bridge
  fd = net_bridge_run_helper(helper, br, errp);
    helper = default_helper = get_relocated_path(DEFAULT_BRIDGE_HELPER);
  net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr);

net_init_tap
    if (tap->fd) {
        net_init_tap_one(fd)
    } else if (tap->fds) {
        for (i = 0; i < nfds; i++) {
            net_init_tap_one(fd)
        }
    } else if (tap->helper) {
        fd = net_bridge_run_helper
        net_init_tap_one(fd)
    } else {
        fd = net_tap_init(ifname)
        net_init_tap_one(fd)
    }

net_init_tap_one
    net_tap_fd_init
    qemu_set_info_str

https://github.com/qemu/qemu/blob/v8.0.2/net/tap.c

从上面的代码可以看到 -netdev bridge 只是 -netdev tap 的简化写法,qemu-bridge-helper 在背后替我们做了 tap 设备创建以及将 tap 设备加入桥接口的所有事情。

qemu-bridge-helper

qemu-bridge-helper 会对 br= 参数进行 acl 检测。

❯ sudo vi /etc/qemu/bridge.conf
allow all
// qemu/qemu-bridge-helper.c

#define DEFAULT_ACL_FILE CONFIG_QEMU_CONFDIR "/bridge.conf"

enum {
    ACL_ALLOW = 0,
    ACL_ALLOW_ALL,
    ACL_DENY,
    ACL_DENY_ALL,
};

main
    QSIMPLEQ_FOREACH(acl_rule, &acl_list, entry) {
        switch (acl_rule->type) {
        case ACL_ALLOW_ALL:
            access_allowed = 1;
            break;
        case ACL_ALLOW:
            if (strcmp(bridge, acl_rule->iface) == 0) {
                access_allowed = 1;
            }
            break;
        case ACL_DENY_ALL:
            access_denied = 1;
            break;
        case ACL_DENY:
            if (strcmp(bridge, acl_rule->iface) == 0) {
                access_denied = 1;
            }
            break;
        }
    }

    if ((access_allowed == 0) || (access_denied == 1)) {
        fprintf(stderr, "access denied by acl file\n");
        ret = EXIT_FAILURE;
        goto cleanup;
    }

https://github.com/qemu/qemu/blob/v8.0.2/qemu-bridge-helper.c

完整示例

❯ sudo qemu-system-x86_64 -M q35 -cpu host \
-enable-kvm -smp 2 -m 1024 -nodefaults \
-drive if=pflash,format=raw,file=/usr/share/edk2/x64/OVMF.4m.fd \
-device qemu-xhci,bus=pcie.0,addr=1 \
-device usb-kbd -device usb-mouse -device usb-tablet \
-serial mon:stdio \
-chardev socket,id=qmp,path=mon.qmp,server=on,wait=off \
-device virtio-gpu-pci,bus=pcie.0,addr=2 \
-netdev user,id=net0 \
-device virtio-net-pci,bus=pcie.0,addr=3,netdev=net0 \
-netdev bridge,br=docker0,id=net1 \
-device virtio-net-pci,bus=pcie.0,addr=4,netdev=net1 \
-device virtio-scsi-pci,id=scsi0,bus=pcie.0,addr=5 \
-drive if=none,file=ubuntu.qcow2,id=hd1,format=qcow2 \
-device scsi-hd,bus=scsi0.0,drive=hd1,bootindex=1 \
-display gtk

其中 -netdev user 中的 hostfwd 端口映射语法如下:

hostfwd=[tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport,hostfwd=,hostfwd=,...

参考资料

Configuring QEMU bridge helper after “access denied by acl file” error
https://blog.christophersmart.com/2016/08/31/configuring-qemu-bridge-helper-after-access-denied-by-acl-file-error/


最后修改于 2023-06-17