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)) {