render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
7a3408
From e09abaad84630d6cd25a1ecff1811ce070201006 Mon Sep 17 00:00:00 2001
7a3408
Message-Id: <e09abaad84630d6cd25a1ecff1811ce070201006@dist-git>
7a3408
From: Laine Stump <laine@laine.org>
7a3408
Date: Thu, 3 Sep 2015 12:08:25 -0400
7a3408
Subject: [PATCH] util: don't use netlink to save/set mac for
7a3408
 macvtap+passthrough+802.1Qbh
7a3408
7a3408
Before libvirt sets the MAC address of the physdev (the physical
7a3408
ethernet device) linked to a macvtap passthrough device, it always
7a3408
saves the previous MAC address to restore when the guest is finished
7a3408
(following a "leave nothing behind" policy). For a long time it
7a3408
accomplished the save/restore with a combination of
7a3408
ioctl(SIOCGIFHWADDR) and ioctl(SIOCSIFHWADDR), but in commit cbfe38c
7a3408
(first in libvirt 1.2.15) this was changed to use netlink RTM_GETLINK
7a3408
and RTM_SETLINK commands sent to the Physical Function (PF) of any
7a3408
device that was detected to be a Virtual Function (VF).
7a3408
7a3408
We later found out that this caused problems with any devices using
7a3408
the Cisco enic driver (e.g. vmfex cards) because the enic driver
7a3408
hasn't implemented the function that is called to gather the
7a3408
information in the IFLA_VFINFO_LIST attribute of RTM_GETLINK
7a3408
(ndo_get_vf_config() for those keeping score), so we would never get
7a3408
back a useful response.
7a3408
7a3408
In an ideal world, all drivers would implement all functions, but it
7a3408
turns out that in this case we can work around this omission without
7a3408
any bad side effects - since all macvtap passthrough <interface>
7a3408
definitions pointing to a physdev that uses the enic driver *must*
7a3408
have a <virtualport type='802.1Qbh'>, and since no other type of
7a3408
ethernet devices use 802.1Qbh, libvirt can change its behavior in this
7a3408
case to use the old-style.  ioctl(SIOC[GS]IFHWADDR).  That's what this
7a3408
patch does.
7a3408
7a3408
Resolves:  https://bugzilla.redhat.com/show_bug.cgi?id=1257004
7a3408
(cherry picked from commit 46cf0cefa0168a0d929ca87010f59e1cba6c689b)
7a3408
7a3408
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
7a3408
---
7a3408
 src/util/virnetdevmacvlan.c | 26 ++++++++++++++++++++++----
7a3408
 1 file changed, 22 insertions(+), 4 deletions(-)
7a3408
7a3408
diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c
7a3408
index 213b8eb..641bd24 100644
7a3408
--- a/src/util/virnetdevmacvlan.c
7a3408
+++ b/src/util/virnetdevmacvlan.c
7a3408
@@ -778,9 +778,22 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *tgifname,
7a3408
      * This is especially important when using SRIOV capable cards that
7a3408
      * emulate their switch in firmware.
7a3408
      */
7a3408
+
7a3408
     if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) {
7a3408
-        if (virNetDevReplaceNetConfig(linkdev, -1, macaddress, -1, stateDir) < 0)
7a3408
-            return -1;
7a3408
+        if (virtPortProfile &&
7a3408
+            virtPortProfile->virtPortType == VIR_NETDEV_VPORT_PROFILE_8021QBH) {
7a3408
+            /* The Cisco enic driver (the only card that uses
7a3408
+             * 802.1Qbh) doesn't support IFLA_VFINFO_LIST, which is
7a3408
+             * required for virNetDevReplaceNetConfig(), so we must
7a3408
+             * use this function (which uses ioctl(SIOCGIFHWADDR)
7a3408
+             * instead or virNetDevReplaceNetConfig()
7a3408
+             */
7a3408
+            if (virNetDevReplaceMacAddress(linkdev, macaddress, stateDir) < 0)
7a3408
+                return -1;
7a3408
+        } else {
7a3408
+            if (virNetDevReplaceNetConfig(linkdev, -1, macaddress, -1, stateDir) < 0)
7a3408
+                return -1;
7a3408
+        }
7a3408
     }
7a3408
 
7a3408
     if (tgifname) {
7a3408
@@ -913,8 +926,13 @@ int virNetDevMacVLanDeleteWithVPortProfile(const char *ifname,
7a3408
     int ret = 0;
7a3408
     int vf = -1;
7a3408
 
7a3408
-    if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU)
7a3408
-        ignore_value(virNetDevRestoreNetConfig(linkdev, vf, stateDir));
7a3408
+    if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) {
7a3408
+        if (virtPortProfile &&
7a3408
+             virtPortProfile->virtPortType == VIR_NETDEV_VPORT_PROFILE_8021QBH)
7a3408
+            ignore_value(virNetDevRestoreMacAddress(linkdev, stateDir));
7a3408
+        else
7a3408
+            ignore_value(virNetDevRestoreNetConfig(linkdev, vf, stateDir));
7a3408
+    }
7a3408
 
7a3408
     if (ifname) {
7a3408
         if (virNetDevVPortProfileDisassociate(ifname,
7a3408
-- 
7a3408
2.5.1
7a3408