]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
macvtap IFF_VNET_HDR configuration
authorStefan Berger <stefanb@us.ibm.com>
Fri, 19 Feb 2010 10:38:57 +0000 (11:38 +0100)
committerDaniel Veillard <veillard@redhat.com>
Fri, 19 Feb 2010 10:38:57 +0000 (11:38 +0100)
This patch sets or unsets the IFF_VNET_HDR flag depending on what device
is used in the VM. The manipulation of the flag is done in the open
function and is only fatal if the IFF_VNET_HDR flag could not be cleared
although it has to be (or if an ioctl generally fails). In that case the
macvtap tap is closed again and the macvtap interface torn.

* src/qemu/qemu_conf.c src/qemu/qemu_conf.h: pass qemuCmdFlags to
  qemudPhysIfaceConnect()
* src/util/macvtap.c src/util/macvtap.h: add vnet_hdr boolean to
  openMacvtapTap(), and private function configMacvtapTap()
* src/qemu/qemu_driver.c: add extra qemuCmdFlags when calling
  qemudPhysIfaceConnect()

src/qemu/qemu_conf.c
src/qemu/qemu_conf.h
src/qemu/qemu_driver.c
src/util/macvtap.c
src/util/macvtap.h

index 8f91d07af55743d252f11738ad1718dea45eee81..dcd2ce76accc358b53a0e04e25b3fab6fe9f75e1 100644 (file)
@@ -1434,14 +1434,20 @@ int
 qemudPhysIfaceConnect(virConnectPtr conn,
                       virDomainNetDefPtr net,
                       char *linkdev,
-                      int brmode)
+                      int brmode,
+                      unsigned long long qemuCmdFlags)
 {
     int rc;
 #if WITH_MACVTAP
     char *res_ifname = NULL;
+    int vnet_hdr = 0;
+
+    if (qemuCmdFlags & QEMUD_CMD_FLAG_VNET_HDR &&
+        net->model && STREQ(net->model, "virtio"))
+        vnet_hdr = 1;
 
     rc = openMacvtapTap(conn, net->ifname, net->mac, linkdev, brmode,
-                        &res_ifname);
+                        &res_ifname, vnet_hdr);
     if (rc >= 0) {
         VIR_FREE(net->ifname);
         net->ifname = res_ifname;
@@ -1451,6 +1457,7 @@ qemudPhysIfaceConnect(virConnectPtr conn,
     (void)net;
     (void)linkdev;
     (void)brmode;
+    (void)qemuCmdFlags;
     qemuReportError(VIR_ERR_INTERNAL_ERROR,
                     "%s", _("No support for macvtap device"));
     rc = -1;
@@ -3752,7 +3759,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
             } else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
                 int tapfd = qemudPhysIfaceConnect(conn, net,
                                                   net->data.direct.linkdev,
-                                                  net->data.direct.mode);
+                                                  net->data.direct.mode,
+                                                  qemuCmdFlags);
                 if (tapfd < 0)
                     goto error;
 
index 4f35a9cb32f434dcbaa410b31ae643da7109aa98..b25c300d9989f57c3cbf7fb3ddc8a7a60f837064 100644 (file)
@@ -253,7 +253,8 @@ int         qemudNetworkIfaceConnect    (virConnectPtr conn,
 int qemudPhysIfaceConnect(virConnectPtr conn,
                           virDomainNetDefPtr net,
                           char *linkdev,
-                          int brmode);
+                          int brmode,
+                          unsigned long long qemuCmdFlags);
 
 int         qemudProbeMachineTypes      (const char *binary,
                                          virCapsGuestMachinePtr **machines,
index 0fb2413b1eec76b160984d614fbcc23deaaad3e9..3d121fb586c03e6c6dec003b905eee31b13f6ff8 100644 (file)
@@ -5725,7 +5725,8 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn,
 
         if ((tapfd = qemudPhysIfaceConnect(conn, net,
                                            net->data.direct.linkdev,
-                                           net->data.direct.mode)) < 0)
+                                           net->data.direct.mode,
+                                           qemuCmdFlags)) < 0)
             return -1;
     }
 
index 88a64ceb883371ad41b63345cccdec8b85c5ad89..8c29588961aee358c4dab0f94667f9ef3ea38a58 100644 (file)
@@ -614,6 +614,64 @@ macvtapModeFromInt(enum virDomainNetdevMacvtapType mode)
 }
 
 
+/**
+ * configMacvtapTap:
+ * @tapfd: file descriptor of the macvtap tap
+ * @vnet_hdr: 1 to enable IFF_VNET_HDR, 0 to disable it
+ *
+ * Returns 0 on success, -1 in case of fatal error, error code otherwise.
+ *
+ * Turn the IFF_VNET_HDR flag, if requested and available, make sure
+ * it's off in the other cases.
+ * A fatal error is defined as the VNET_HDR flag being set but it cannot
+ * be turned off for some reason. This is reported with -1. Other fatal
+ * error is not being able to read the interface flags. In that case the
+ * macvtap device should not be used.
+ */
+static int
+configMacvtapTap(int tapfd, int vnet_hdr)
+{
+    unsigned int features;
+    struct ifreq ifreq;
+    short new_flags = 0;
+    int rc_on_fail = 0;
+    const char *errmsg = NULL;
+
+    memset(&ifreq, 0, sizeof(ifreq));
+
+    if (ioctl(tapfd, TUNGETIFF, &ifreq) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("cannot get interface flags on macvtap tap"));
+        return -1;
+    }
+
+    new_flags = ifreq.ifr_flags;
+
+    if ((ifreq.ifr_flags & IFF_VNET_HDR) && !vnet_hdr) {
+        new_flags = ifreq.ifr_flags & ~IFF_VNET_HDR;
+        rc_on_fail = -1;
+        errmsg = _("cannot clean IFF_VNET_HDR flag on macvtap tap");
+    } else if ((ifreq.ifr_flags & IFF_VNET_HDR) == 0 && vnet_hdr) {
+        if (ioctl(tapfd, TUNGETFEATURES, &features) != 0)
+            return errno;
+        if ((features & IFF_VNET_HDR)) {
+            new_flags = ifreq.ifr_flags | IFF_VNET_HDR;
+            errmsg = _("cannot set IFF_VNET_HDR flag on macvtap tap");
+        }
+    }
+
+    if (new_flags != ifreq.ifr_flags) {
+        ifreq.ifr_flags = new_flags;
+        if (ioctl(tapfd, TUNSETIFF, &ifreq) < 0) {
+            virReportSystemError(errno, "%s", errmsg);
+            return rc_on_fail;
+        }
+    }
+
+    return 0;
+}
+
+
 /**
  * openMacvtapTap:
  * Create an instance of a macvtap device and open its tap character
@@ -640,7 +698,8 @@ openMacvtapTap(virConnectPtr conn,
                const unsigned char *macaddress,
                const char *linkdev,
                int mode,
-               char **res_ifname)
+               char **res_ifname,
+               int vnet_hdr)
 {
     const char *type = "macvtap";
     int c, rc;
@@ -699,9 +758,14 @@ create_name:
 
     rc = openTap(cr_ifname, 10);
 
-    if (rc >= 0)
+    if (rc >= 0) {
+        if (configMacvtapTap(rc, vnet_hdr) < 0) {
+            close(rc);
+            rc = -1;
+            goto link_del_exit;
+        }
         *res_ifname = strdup(cr_ifname);
-    else
+    else
         goto link_del_exit;
 
     return rc;
index a1a0a7a8afed25b4da88b4c06847a0d716dfef88..4c2fe8acd73c5e24c2759d00942ae9244fc06373 100644 (file)
@@ -33,9 +33,10 @@ int openMacvtapTap(virConnectPtr conn,
                    const unsigned char *macaddress,
                    const char *linkdev,
                    int mode,
-                   char **res_ifname);
+                   char **res_ifname,
+                   int vnet_hdr);
 
-void delMacvtap(const char *name);
+void delMacvtap(const char *ifname);
 
 #endif /* WITH_MACVTAP */