Update code to create generic ethernet interfaces using the new
utility library tunctl making
changes to create the TAP device in libvirt and pass it to qemu as a
file descriptor.
---
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index ee4b52b..181f56c 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -396,6 +396,51 @@ qemuOpenVhostNet(virDomainDefPtr def,
}
+int qemuEthernetIfaceCreate(virDomainDefPtr def,
+ virDomainNetDefPtr net,
+ virBitmapPtr qemuCaps)
+{
+ int tapfd;
+ int err;
+ int vnet_hdr = 0;
+ 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();
+ return -1;
+ }
+ }
+
+ err = createTap(&net->ifname, vnet_hdr, &tapfd);
+ virDomainAuditNetDevice(def, net, "/dev/net/tun", tapfd >= 0);
+ if (tapfd < 0 || err)
+ return -1;
+
+ memcpy(tapmac, net->mac, VIR_MAC_BUFLEN);
+ /* Discourage bridge from using TAP dev MAC */
+ tapmac[0] = 0xFE;
+ err = tapSetInterfaceMac(net->ifname, tapmac);
+
+ if (err)
+ return -1;
+
+ err = tapSetInterfaceUp(net->ifname, 1);
+
+ if (err)
+ return -1;
+
+ return tapfd;
+}
+
+
static int qemuDomainDeviceAliasIndex(virDomainDeviceInfoPtr info,
const char *prefix)
{
@@ -2055,14 +2100,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;
@@ -4064,6 +4112,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_conf.h b/src/qemu/qemu_conf.h
index e8b92a4..cbea145 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -29,6 +29,7 @@
# include "ebtables.h"
# include "internal.h"
# include "bridge.h"
+# include "tunctl.h"
# include "capabilities.h"
# include "network_conf.h"
# include "domain_conf.h"
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 6cfe392..32c5edb 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -645,6 +645,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)
@@ -1881,6 +1887,10 @@ int qemuDomainDetachNetDevice(struct
qemud_driver *driver,
}
#endif
+ if(detach->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
+ !detach->data.ethernet.script)
+ delTap(detach->ifname);
+
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 3baaa19..11e4219 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3392,6 +3392,14 @@ 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)
+ delTap(net->ifname);
+ }
+
retry:
if ((ret = qemuRemoveCgroup(driver, vm, 0)) < 0) {
if (ret == -EBUSY && (retries++ < 5)) {