
On 3/3/2015 1:49 AM, Vasiliy Tolstov wrote:
2015-03-02 23:41 GMT+03:00 Brian Rak <brak@gameservers.com>:
In IRC, I was directed to this patch: https://www.redhat.com/archives/libvir-list/2015-February/msg01212.html ... which does exactly what I was looking for. It doesn't build cleanly in that state, but it's pretty trivial fix (needs actualType added to the function definition for qemuNetworkIfaceConnect and the two calls modified)
I send new patch version one day ago and it waiting for review.
We've been using this patch for a couple months now, and it's working perfectly. I noticed that it no longer applied cleanly against 1.2.14, so I updated it: diff -urw src_clean/src/qemu/qemu_command.c src/src/qemu/qemu_command.c --- src_clean/src/qemu/qemu_command.c 2015-03-26 22:01:44.000000000 -0400 +++ src/src/qemu/qemu_command.c 2015-04-21 11:34:03.363772741 -0400 @@ -330,10 +330,41 @@ return *tapfd < 0 ? -1 : 0; } +/** + * qemuExecuteEthernetScript: + * @ifname: the interface name + * @script: the script name + * This function executes script for new tap device created by libvirt. + * Returns 0 in case of success or -1 on failure + */ +static int qemuExecuteEthernetScript(const char *ifname, const char *script) +{ + virCommandPtr cmd; + int ret; + + cmd = virCommandNew(script); + virCommandAddArgFormat(cmd, "%s", ifname); + virCommandClearCaps(cmd); +#ifdef CAP_NET_ADMIN + virCommandAllowCap(cmd, CAP_NET_ADMIN); +#endif + virCommandAddEnvPassCommon(cmd); + + if (virCommandRun(cmd, NULL) < 0) { + ret = -1; + } else { + ret = 0; + } + + virCommandFree(cmd); + return ret; +} + /* qemuNetworkIfaceConnect - *only* called if actualType is - * VIR_DOMAIN_NET_TYPE_NETWORK or VIR_DOMAIN_NET_TYPE_BRIDGE (i.e. if - * the connection is made with a tap device connecting to a bridge - * device) + * VIR_DOMAIN_NET_TYPE_NETWORK, VIR_DOMAIN_NET_TYPE_BRIDGE or + * VIR_DOMAIN_NET_TYPE_ETHERNET (i.e. if the connection is + * made with a tap device connecting to a bridge device or + * used ethernet tap device) */ int qemuNetworkIfaceConnect(virDomainDefPtr def, @@ -341,7 +372,8 @@ virDomainNetDefPtr net, virQEMUCapsPtr qemuCaps, int *tapfd, - size_t *tapfdSize) + size_t *tapfdSize, + int actualType) { const char *brname; int ret = -1; @@ -359,11 +391,6 @@ } } - if (!(brname = virDomainNetGetActualBridgeName(net))) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing bridge name")); - goto cleanup; - } - if (!net->ifname || STRPREFIX(net->ifname, VIR_NET_GENERATED_PREFIX) || strchr(net->ifname, '%')) { @@ -379,6 +406,22 @@ tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR; } + if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) { + if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, *tapfdSize, + tap_create_flags) < 0) { + virDomainAuditNetDevice(def, net, tunpath, false); + goto cleanup; + } + if (net->script) { + if (qemuExecuteEthernetScript(net->ifname, net->script) < 0) + goto cleanup; + } + } else { + if (!(brname = virDomainNetGetActualBridgeName(net))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing bridge name")); + goto cleanup; + } + if (cfg->privileged) { if (virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac, def->uuid, tunpath, tapfd, *tapfdSize, @@ -415,8 +458,8 @@ *tapfdSize = 1; } } - virDomainAuditNetDevice(def, net, tunpath, true); + } if (cfg->macFilter && ebtablesAddForwardAllowIn(driver->ebtables, @@ -5123,6 +5166,7 @@ case VIR_DOMAIN_NET_TYPE_BRIDGE: case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_DIRECT: + case VIR_DOMAIN_NET_TYPE_ETHERNET: virBufferAsprintf(&buf, "tap%c", type_sep); /* for one tapfd 'fd=' shall be used, * for more than one 'fds=' is the right choice */ @@ -5140,20 +5184,6 @@ is_tap = true; break; - case VIR_DOMAIN_NET_TYPE_ETHERNET: - virBufferAddLit(&buf, "tap"); - if (net->ifname) { - virBufferAsprintf(&buf, "%cifname=%s", type_sep, net->ifname); - type_sep = ','; - } - if (net->script) { - virBufferAsprintf(&buf, "%cscript=%s", type_sep, - net->script); - type_sep = ','; - } - is_tap = true; - break; - case VIR_DOMAIN_NET_TYPE_CLIENT: virBufferAsprintf(&buf, "socket%cconnect=%s:%d", type_sep, @@ -8009,7 +8039,8 @@ /* Currently nothing besides TAP devices supports multiqueue. */ if (net->driver.virtio.queues > 0 && !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK || - actualType == VIR_DOMAIN_NET_TYPE_BRIDGE)) { + actualType == VIR_DOMAIN_NET_TYPE_BRIDGE || + actualType == VIR_DOMAIN_NET_TYPE_ETHERNET)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Multiqueue network is not supported for: %s"), virDomainNetTypeToString(actualType)); @@ -8026,7 +8057,8 @@ } if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK || - actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) { + actualType == VIR_DOMAIN_NET_TYPE_BRIDGE || + actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) { tapfdSize = net->driver.virtio.queues; if (!tapfdSize) tapfdSize = 1; @@ -8039,7 +8071,7 @@ if (qemuNetworkIfaceConnect(def, driver, net, qemuCaps, tapfd, - &tapfdSize) < 0) + &tapfdSize, actualType) < 0) goto cleanup; } else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) { if (VIR_ALLOC(tapfd) < 0 || VIR_ALLOC(tapfdName) < 0) diff -urw src_clean/src/qemu/qemu_command.h src/src/qemu/qemu_command.h --- src_clean/src/qemu/qemu_command.h 2015-03-25 03:36:59.000000000 -0400 +++ src/src/qemu/qemu_command.h 2015-04-21 11:33:26.557397006 -0400 @@ -223,7 +223,8 @@ virDomainNetDefPtr net, virQEMUCapsPtr qemuCaps, int *tapfd, - size_t *tapfdSize) + size_t *tapfdSize, + int qemuNetworkIfaceConnect) ATTRIBUTE_NONNULL(2); int qemuPhysIfaceConnect(virDomainDefPtr def, Only in src/src/qemu: qemu_command.h.orig diff -urw src_clean/src/qemu/qemu_hotplug.c src/src/qemu/qemu_hotplug.c --- src_clean/src/qemu/qemu_hotplug.c 2015-03-25 03:36:59.000000000 -0400 +++ src/src/qemu/qemu_hotplug.c 2015-04-21 11:34:34.810243144 -0400 @@ -898,7 +898,8 @@ /* Currently nothing besides TAP devices supports multiqueue. */ if (net->driver.virtio.queues > 0 && !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK || - actualType == VIR_DOMAIN_NET_TYPE_BRIDGE)) { + actualType == VIR_DOMAIN_NET_TYPE_BRIDGE || + actualType == VIR_DOMAIN_NET_TYPE_ETHERNET)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Multiqueue network is not supported for: %s"), virDomainNetTypeToString(actualType)); @@ -906,7 +907,8 @@ } if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE || - actualType == VIR_DOMAIN_NET_TYPE_NETWORK) { + actualType == VIR_DOMAIN_NET_TYPE_NETWORK || + actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) { tapfdSize = vhostfdSize = net->driver.virtio.queues; if (!tapfdSize) tapfdSize = vhostfdSize = 1; @@ -917,7 +919,7 @@ goto cleanup; memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize); if (qemuNetworkIfaceConnect(vm->def, driver, net, - priv->qemuCaps, tapfd, &tapfdSize) < 0) + priv->qemuCaps, tapfd, &tapfdSize, actualType) < 0) goto cleanup; iface_connected = true; if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd, &vhostfdSize) < 0) @@ -937,13 +939,6 @@ iface_connected = true; if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd, &vhostfdSize) < 0) goto cleanup; - } else if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) { - vhostfdSize = 1; - if (VIR_ALLOC(vhostfd) < 0) - goto cleanup; - *vhostfd = -1; - if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd, &vhostfdSize) < 0) - goto cleanup; } /* Set device online immediately */ diff -urw src_clean/src/qemu/qemu_process.c src/src/qemu/qemu_process.c --- src_clean/src/qemu/qemu_process.c 2015-03-30 20:36:17.000000000 -0400 +++ src/src/qemu/qemu_process.c 2015-04-21 11:33:26.559396972 -0400 @@ -5248,6 +5248,12 @@ cfg->stateDir)); VIR_FREE(net->ifname); break; + case VIR_DOMAIN_NET_TYPE_ETHERNET: + if (net->ifname) { + ignore_value(virNetDevTapDelete(net->ifname, net->backend.tap)); + VIR_FREE(net->ifname); + } + break; case VIR_DOMAIN_NET_TYPE_BRIDGE: case VIR_DOMAIN_NET_TYPE_NETWORK: #ifdef VIR_NETDEV_TAP_REQUIRE_MANUAL_CLEANUP