[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

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



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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]