This patch makes the changes to the generic ethernet interface for QEMU. Allowing it to be used with sVirt enabled. src/qemu/qemu_command.c | 79 ++++++++++++++++++++++++++++++++++++++++++++-- src/qemu/qemu_command.h | 4 ++ src/qemu/qemu_hotplug.c | 15 +++++++++ src/qemu/qemu_process.c | 13 ++++++++ 4 files changed, 107 insertions(+), 4 deletions(-) --- diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 30c0be6..b00920b 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -404,6 +404,62 @@ qemuOpenVhostNet(virDomainDefPtr def, } +int qemuEthernetIfaceCreate(virDomainDefPtr def, + virDomainNetDefPtr net, + virBitmapPtr qemuCaps) +{ + int err; + int tapfd = 0; + int vnet_hdr = 0; + brControl *brctl = NULL; + unsigned char tapmac[VIR_MAC_BUFLEN]; + + if (qemuCapsGet(qemuCaps, QEMU_CAPS_VNET_HDR) && + net->model && STREQ(net->model, "virtio")) + vnet_hdr = 1; + + if (!net->ifname || + STRPREFIX(net->ifname, "vnet") || + strchr(net->ifname, '%')) { + VIR_FREE(net->ifname); + if (!(net->ifname = strdup("vnet%d"))) { + virReportOOMError(); + goto error; + } + } + + if(brInit(&brctl) < 0) + goto error; + + err = brCreateTap(brctl, &net->ifname, vnet_hdr, &tapfd); + virDomainAuditNetDevice(def, net, "/dev/net/tun", tapfd >= 0); + if (tapfd < 0 || err) + goto error; + + memcpy(tapmac, net->mac, VIR_MAC_BUFLEN); + /* Discourage bridge from using TAP dev MAC */ + tapmac[0] = 0xFE; + err = brSetInterfaceMac(brctl, net->ifname, tapmac); + + if (err) + goto error; + + err = brSetInterfaceUp(brctl, net->ifname, 1); + + if (err) + goto error; + + brShutdown(brctl); + + return tapfd; + + error: + brShutdown(brctl); + VIR_FORCE_CLOSE(tapfd); + return -1; +} + + static int qemuDomainDeviceAliasIndex(virDomainDeviceInfoPtr info, const char *prefix) { @@ -2154,14 +2210,17 @@ qemuBuildHostNetStr(virDomainNetDefPtr net, case VIR_DOMAIN_NET_TYPE_ETHERNET: virBufferAddLit(&buf, "tap"); - if (net->ifname) { - virBufferAsprintf(&buf, "%cifname=%s", type_sep, net->ifname); - type_sep = ','; - } if (net->data.ethernet.script) { + if (net->ifname) { + virBufferAsprintf(&buf, "%cifname=%s", type_sep, net->ifname); + type_sep = ','; + } virBufferAsprintf(&buf, "%cscript=%s", type_sep, net->data.ethernet.script); type_sep = ','; + } else if(net->ifname) { + virBufferAsprintf(&buf, "%cfd=%s", type_sep, tapfd); + type_sep = ','; } is_tap = true; break; @@ -4190,6 +4249,18 @@ qemuBuildCommandLine(virConnectPtr conn, if (snprintf(tapfd_name, sizeof(tapfd_name), "%d", tapfd) >= sizeof(tapfd_name)) goto no_memory; + } else if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET && + !net->data.ethernet.script) { + int tapfd = qemuEthernetIfaceCreate(def, net, qemuCaps); + if (tapfd < 0) + goto error; + + last_good_net = i; + virCommandTransferFD(cmd, tapfd); + + if (snprintf(tapfd_name, sizeof(tapfd_name), "%d", + tapfd) >= sizeof(tapfd_name)) + goto no_memory; } if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK || diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 00e58a2..b21eeb6 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -142,6 +142,10 @@ int qemuOpenVhostNet(virDomainDefPtr def, virBitmapPtr qemuCaps, int *vhostfd); +int qemuEthernetIfaceCreate(virDomainDefPtr def, + virDomainNetDefPtr net, + virBitmapPtr qemuCaps); + int qemudCanonicalizeMachine(struct qemud_driver *driver, virDomainDefPtr def); diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 037f4aa..715efb2 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -680,6 +680,12 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, iface_connected = true; if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd) < 0) goto cleanup; + } else if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET && + !net->data.ethernet.script) + { + if ((tapfd = qemuEthernetIfaceCreate(vm->def, net, priv->qemuCaps)) < 0) + goto cleanup; + iface_connected = true; } if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets+1) < 0) @@ -1820,6 +1826,7 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver, qemuDomainObjPrivatePtr priv = vm->privateData; int vlan; char *hostnet_name = NULL; + brControl *brctl = NULL; for (i = 0 ; i < vm->def->nnets ; i++) { virDomainNetDefPtr net = vm->def->nets[i]; @@ -1916,6 +1923,14 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver, } #endif + if(detach->type == VIR_DOMAIN_NET_TYPE_ETHERNET && + !detach->data.ethernet.script) { + if(brInit(&brctl) < 0) + goto cleanup; + brDeleteTap(brctl, detach->ifname); + brShutdown(brctl); + } + if ((driver->macFilter) && (detach->ifname != NULL)) { if ((errno = networkDisallowMacOnPort(driver, detach->ifname, diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index a7fe86c..b8ebf36 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3300,6 +3300,7 @@ void qemuProcessStop(struct qemud_driver *driver, int logfile = -1; char *timestamp; char ebuf[1024]; + brControl *brctl = NULL; VIR_DEBUG("Shutting down VM '%s' pid=%d migrated=%d", vm->def->name, vm->pid, migrated); @@ -3421,6 +3422,18 @@ void qemuProcessStop(struct qemud_driver *driver, networkReleaseActualDevice(net); } + def = vm->def; + for(i=0; i < def->nnets; i++) { + virDomainNetDefPtr net = def->nets[i]; + if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET && + !net->data.ethernet.script) { + if(brInit(&brctl) > 0) { + brDeleteTap(brctl, net->ifname); + brShutdown(brctl); + } + } + } + retry: if ((ret = qemuRemoveCgroup(driver, vm, 0)) < 0) { if (ret == -EBUSY && (retries++ < 5)) { -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list