[libvirt] [PATCH 2/2] Modify generic ethernet interface so it will work when sVirt is enabled with qemu

Tyler Coumbes coumbes at gmail.com
Tue Sep 20 23:18:30 UTC 2011


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




More information about the libvir-list mailing list