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

[libvirt] [PATCH 3/5] macvtap support for libvirt -- qemu support



This part adds support for qemu making a macvtap tap device available
via file descriptor passed to qemu command line. This also attempts to
tear down the macvtap device when a VM terminates. This includes support
for attachment and detachment to/from running VM.

Signed-off-by: Stefan Berger <stefanb us ibm com>




Index: libvirt-macvtap/src/qemu/qemu_conf.c
===================================================================
--- libvirt-macvtap.orig/src/qemu/qemu_conf.c
+++ libvirt-macvtap/src/qemu/qemu_conf.c
@@ -52,6 +52,7 @@
 #include "nodeinfo.h"
 #include "logging.h"
 #include "network.h"
+#include "macvtap.h"
 #include "cpu/cpu.h"
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
@@ -1420,6 +1421,51 @@ int qemudExtractVersion(struct qemud_dri
     return 0;
 }
 
+/**
+ * qemudPhysIfaceConnect:
+ * @conn: pointer to virConnect object
+ * @net: pointer to he VM's interface description with direct device type
+ * @linkdev: The name of the physical interface to link the macvtap to
+ * @brmode: The mode to put the macvtap device into
+ *
+ * Returns a filedescriptor on success or -1 in case of error.
+ */
+int
+qemudPhysIfaceConnect(virConnectPtr conn,
+                      virDomainNetDefPtr net,
+                      char *linkdev,
+                      int brmode)
+{
+    int rc;
+#if defined(WITH_MACVTAP)
+    char *res_ifname = NULL;
+    int hasBusyDev = 0;
+
+    delMacvtapByMACAddress(net->mac, &hasBusyDev);
+
+    if (hasBusyDev) {
+        virReportSystemError(errno, "%s",
+                             _("A macvtap with the same MAC address is in use"));
+        return -1;
+    }
+
+    rc = openMacvtapTap(conn, net->ifname, net->mac, linkdev, brmode,
+                        &res_ifname);
+    if (rc >= 0) {
+        VIR_FREE(net->ifname);
+        net->ifname = res_ifname;
+    }
+#else
+    (void)net;
+    (void)linkdev;
+    (void)brmode;
+    qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                    "%s", _("No support for macvtap device"));
+    rc = -1;
+#endif
+    return rc;
+}
+
 
 int
 qemudNetworkIfaceConnect(virConnectPtr conn,
@@ -2515,6 +2561,7 @@ qemuBuildHostNetStr(virDomainNetDefPtr n
     switch (net->type) {
     case VIR_DOMAIN_NET_TYPE_NETWORK:
     case VIR_DOMAIN_NET_TYPE_BRIDGE:
+    case VIR_DOMAIN_NET_TYPE_DIRECT:
         virBufferAddLit(&buf, "tap");
         virBufferVSprintf(&buf, "%cfd=%s", type_sep, tapfd);
         type_sep = ',';
@@ -3632,6 +3679,22 @@ int qemudBuildCommandLine(virConnectPtr 
 
                 if (snprintf(tapfd_name, sizeof(tapfd_name), "%d", tapfd) >= sizeof(tapfd_name))
                     goto no_memory;
+            } else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+                int tapfd = qemudPhysIfaceConnect(conn, net,
+                                                  net->data.direct.linkdev,
+                                                  net->data.direct.mode);
+                if (tapfd < 0)
+                    goto error;
+
+                if (VIR_REALLOC_N(*tapfds, (*ntapfds)+1) < 0) {
+                    close(tapfd);
+                    goto no_memory;
+                }
+
+                (*tapfds)[(*ntapfds)++] = tapfd;
+
+                if (snprintf(tapfd_name, sizeof(tapfd_name), "%d", tapfd) >= sizeof(tapfd_name))
+                    goto no_memory;
             }
 
             /* Possible combinations:
Index: libvirt-macvtap/src/qemu/qemu_driver.c
===================================================================
--- libvirt-macvtap.orig/src/qemu/qemu_driver.c
+++ libvirt-macvtap/src/qemu/qemu_driver.c
@@ -75,6 +75,7 @@
 #include "libvirt_internal.h"
 #include "xml.h"
 #include "cpu/cpu.h"
+#include "macvtap.h"
 
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
@@ -2795,6 +2796,8 @@ static void qemudShutdownVMDaemon(struct
     int retries = 0;
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virErrorPtr orig_err;
+    virDomainDefPtr def;
+    int i;
 
     if (!virDomainObjIsActive(vm))
         return;
@@ -2806,8 +2809,7 @@ static void qemudShutdownVMDaemon(struct
     orig_err = virSaveLastError();
 
     if (driver->macFilter) {
-        int i;
-        virDomainDefPtr def = vm->def;
+        def = vm->def;
         for (i = 0 ; i < def->nnets ; i++) {
             virDomainNetDefPtr net = def->nets[i];
             if (net->ifname == NULL)
@@ -2821,6 +2823,17 @@ static void qemudShutdownVMDaemon(struct
         }
     }
 
+#if defined(WITH_MACVTAP)
+    def = vm->def;
+    for (i = 0; i < def->nnets; i++) {
+        virDomainNetDefPtr net = def->nets[i];
+        if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+            int dummy;
+            delMacvtapByMACAddress(net->mac, &dummy);
+        }
+    }
+#endif
+
     if (virKillProcess(vm->pid, 0) == 0 &&
         virKillProcess(vm->pid, SIGTERM) < 0)
         virReportSystemError(errno,
@@ -5589,6 +5602,19 @@ static int qemudDomainAttachNetDevice(vi
 
         if ((tapfd = qemudNetworkIfaceConnect(conn, driver, net, qemuCmdFlags)) < 0)
             return -1;
+    } else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+        if (priv->monConfig->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
+            qemuReportError(VIR_ERR_NO_SUPPORT,
+                            _("network device type '%s' cannot be attached: "
+                            "qemu is not using a unix socket monitor"),
+                            virDomainNetTypeToString(net->type));
+            return -1;
+        }
+
+        if ((tapfd = qemudPhysIfaceConnect(conn, net,
+                                           net->data.direct.linkdev,
+                                           net->data.direct.mode)) < 0)
+            return -1;
     }
 
     if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets+1) < 0)
@@ -6207,6 +6233,11 @@ qemudDomainDetachNetDevice(struct qemud_
     }
     qemuDomainObjExitMonitorWithDriver(driver, vm);
 
+    if (detach->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+        int dummy;
+        delMacvtapByMACAddress(detach->mac, &dummy);
+    }
+
     if ((driver->macFilter) && (detach->ifname != NULL)) {
         if ((errno = networkDisallowMacOnPort(driver,
                                               detach->ifname,
Index: libvirt-macvtap/src/qemu/qemu_conf.h
===================================================================
--- libvirt-macvtap.orig/src/qemu/qemu_conf.h
+++ libvirt-macvtap/src/qemu/qemu_conf.h
@@ -247,6 +247,11 @@ int         qemudNetworkIfaceConnect    
                                          unsigned long long qemuCmdFlags)
     ATTRIBUTE_NONNULL(1);
 
+int qemudPhysIfaceConnect(virConnectPtr conn,
+                          virDomainNetDefPtr net,
+                          char *linkdev,
+                          int brmode);
+
 int         qemudProbeMachineTypes      (const char *binary,
                                          virCapsGuestMachinePtr **machines,
                                          int *nmachines);

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