From: Richa Marwaha <rmarwah@xxxxxxxxxxxxxxxxxx> QEMU has a new feature which allows QEMU to execute under an unprivileged user ID and still be able to add a tap device to a Linux network bridge. Below is the link to the QEMU patches for the bridge helper feature: http://lists.gnu.org/archive/html/qemu-devel/2012-01/msg03562.html The existing libvirt tap network device support for adding a tap device to a bridge (-netdev tap) works only when connected to a libvirtd instance running as the privileged system account 'root'. When connected to a libvirtd instance running as an unprivileged user (ie. using the session URI) creation of the tap device fails as follows: error: Failed to start domain F14_64 error: Unable to create tap device vnet%d: Operation not permitted With this support, creating a tap device in the above scenario will be possible. Additionally, hot attaching a tap device to a bridge while running when connected to a libvirtd instance running as an unprivileged user will be possible. Signed-off-by: Richa Marwaha <rmarwah@xxxxxxxxxxxxxxxxxx> Signed-off-by: Corey Bryant<coreyb@xxxxxxxxxxxxxxxxxx> --- src/qemu/qemu_command.c | 38 +++++++++++++++++++++++++------------- src/qemu/qemu_command.h | 1 + src/qemu/qemu_hotplug.c | 19 +++++++++++-------- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 117542f..daa5381 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2745,6 +2745,7 @@ error: char * qemuBuildHostNetStr(virDomainNetDefPtr net, + struct qemud_driver *driver, char type_sep, int vlan, const char *tapfd, @@ -2753,6 +2754,7 @@ qemuBuildHostNetStr(virDomainNetDefPtr net, bool is_tap = false; virBuffer buf = VIR_BUFFER_INITIALIZER; enum virDomainNetType netType = virDomainNetGetActualType(net); + const char *brname = NULL; if (net->script && netType != VIR_DOMAIN_NET_TYPE_ETHERNET) { qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -2762,8 +2764,15 @@ qemuBuildHostNetStr(virDomainNetDefPtr net, } switch (netType) { - case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_BRIDGE: + if (!driver->privileged) { + brname = virDomainNetGetActualBridgeName(net); + virBufferAsprintf(&buf, "bridge%cbr=%s", type_sep, brname); + type_sep = ','; + is_tap = true; + break; + } + case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_DIRECT: virBufferAsprintf(&buf, "tap%cfd=%s", type_sep, tapfd); type_sep = ','; @@ -4865,7 +4874,7 @@ qemuBuildCommandLine(virConnectPtr conn, for (i = 0 ; i < def->nnets ; i++) { virDomainNetDefPtr net = def->nets[i]; char *nic, *host; - char tapfd_name[50]; + char tapfd_name[50] = ""; char vhostfd_name[50] = ""; int vlan; int bootindex = bootNet; @@ -4902,17 +4911,20 @@ qemuBuildCommandLine(virConnectPtr conn, if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK || actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) { - int tapfd = qemuNetworkIfaceConnect(def, conn, driver, net, - qemuCaps); - if (tapfd < 0) - goto error; + if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK || + driver->privileged) { + int tapfd = qemuNetworkIfaceConnect(def, conn, driver, net, + qemuCaps); + if (tapfd < 0) + goto error; - last_good_net = i; - virCommandTransferFD(cmd, tapfd); + last_good_net = i; + virCommandTransferFD(cmd, tapfd); - if (snprintf(tapfd_name, sizeof(tapfd_name), "%d", - tapfd) >= sizeof(tapfd_name)) - goto no_memory; + if (snprintf(tapfd_name, sizeof(tapfd_name), "%d", + tapfd) >= sizeof(tapfd_name)) + goto no_memory; + } } else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) { int tapfd = qemuPhysIfaceConnect(def, driver, net, qemuCaps, vmop); @@ -4955,7 +4967,7 @@ qemuBuildCommandLine(virConnectPtr conn, if (qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV) && qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { virCommandAddArg(cmd, "-netdev"); - if (!(host = qemuBuildHostNetStr(net, ',', vlan, + if (!(host = qemuBuildHostNetStr(net, driver, ',', vlan, tapfd_name, vhostfd_name))) goto error; virCommandAddArg(cmd, host); @@ -4978,7 +4990,7 @@ qemuBuildCommandLine(virConnectPtr conn, if (!(qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV) && qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE))) { virCommandAddArg(cmd, "-net"); - if (!(host = qemuBuildHostNetStr(net, ',', vlan, + if (!(host = qemuBuildHostNetStr(net, driver, ',', vlan, tapfd_name, vhostfd_name))) goto error; virCommandAddArg(cmd, host); diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 1eafeb3..04240bc 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -62,6 +62,7 @@ qemuBuildChrDeviceStr (virDomainChrDefPtr serial, /* With vlan == -1, use netdev syntax, else old hostnet */ char * qemuBuildHostNetStr(virDomainNetDefPtr net, + struct qemud_driver *driver, char type_sep, int vlan, const char *tapfd, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index ad31eba..7f8b1e4 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -699,12 +699,15 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE || actualType == VIR_DOMAIN_NET_TYPE_NETWORK) { - if ((tapfd = qemuNetworkIfaceConnect(vm->def, conn, driver, net, - priv->qemuCaps)) < 0) - goto cleanup; - iface_connected = true; - if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd) < 0) - goto cleanup; + if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK || + driver->privileged) { + if ((tapfd = qemuNetworkIfaceConnect(vm->def, conn, driver, net, + priv->qemuCaps)) < 0) + goto cleanup; + iface_connected = true; + if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd) < 0) + goto cleanup; + } } else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) { if ((tapfd = qemuPhysIfaceConnect(vm->def, driver, net, priv->qemuCaps, @@ -752,11 +755,11 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_NETDEV) && qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { - if (!(netstr = qemuBuildHostNetStr(net, ',', + if (!(netstr = qemuBuildHostNetStr(net, driver, ',', -1, tapfd_name, vhostfd_name))) goto cleanup; } else { - if (!(netstr = qemuBuildHostNetStr(net, ' ', + if (!(netstr = qemuBuildHostNetStr(net, driver, ' ', vlan, tapfd_name, vhostfd_name))) goto cleanup; } -- 1.7.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list