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

Tyler Coumbes coumbes at gmail.com
Mon Oct 24 23:44:42 UTC 2011


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




More information about the libvir-list mailing list