Blame SOURCES/libvirt-conf-properly-clear-out-autogenerated-macvtap-names-when-formatting-parsing.patch

e870a1
From bcce526443723e7cf3272f67c4d34b6925b63209 Mon Sep 17 00:00:00 2001
e870a1
Message-Id: <bcce526443723e7cf3272f67c4d34b6925b63209@dist-git>
e870a1
From: Laine Stump <laine@redhat.com>
e870a1
Date: Sun, 13 Sep 2020 10:26:25 -0400
e870a1
Subject: [PATCH] conf: properly clear out autogenerated macvtap names when
e870a1
 formatting/parsing
e870a1
MIME-Version: 1.0
e870a1
Content-Type: text/plain; charset=UTF-8
e870a1
Content-Transfer-Encoding: 8bit
e870a1
e870a1
Back when macvtap support was added in commit 315baab9443 in Feb. 2010
e870a1
(libvirt-0.7.7), it was setup to autogenerate a name for the device if
e870a1
one wasn't supplied, in the pattern "macvtap%d" (or "macvlan%d"),
e870a1
similar to the way an unspecified standard tap device name will lead
e870a1
to an autogenerated "vnet%d".
e870a1
e870a1
As a matter of fact, in commit ca1b7cc8e45 added in May 2010, the code
e870a1
was changed to *always* ignore a supplied device name for macvtap
e870a1
interfaces by deleting *any* name immediately during the <interface>
e870a1
parsing (this was intended to prevent one domain which had failed to
e870a1
completely start from deleting the macvtap device of another domain
e870a1
which had subsequently been provided the same device name (this will
e870a1
seem mildly ironic later). This was later fixed to only clear the
e870a1
device name when inactive XML was being parsed. HOWEVER - this was
e870a1
only done if the xml was <interface type='direct'> - autogenerated
e870a1
names were not cleared for <interface type='network'> (which could
e870a1
also result in a macvtap device).
e870a1
e870a1
Although the names of "vnetX" tap devices had always been
e870a1
automatically cleared when parsing <interface> (see commit d1304583d
e870a1
from July 2008 (!)), at the time macvtap support was added, both vnetX
e870a1
and macvtapX device names were always included when formatting the
e870a1
XML.
e870a1
e870a1
Then in commit a8be259d0cc (July 2011, libvirt-0.9.4), <interface>
e870a1
formatting was changed to also clear out "vnetX" device names during
e870a1
XML formatting as well. However the same treatment wasn't given to
e870a1
"macvtapX".
e870a1
e870a1
Now in 2020, there has been a report that a failed migration leads to
e870a1
the macvtap device of some other unrelated guest on the destination
e870a1
host losing its network connectivity. It was determined that this was
e870a1
due to the domain XML in the migration containing a macvtap device
e870a1
name, e.g. "macvtap0", that was already in use by the other guest on
e870a1
the destination. Normally this wouldn't be a problem, because libvirt
e870a1
would see that the device was already in use, and then find a
e870a1
different unused name. But in this case, other external problems were
e870a1
causing the migration to fail prior to selecting a macvtap device and
e870a1
successfully opening it, and during error recovery, qemuProcessStop()
e870a1
was called, which went through all def->nets objects and (if they were
e870a1
macvtap) deleted the device specified in net->ifname; since libvirt
e870a1
hadn't gotten to the point of replacing the incoming "macvtap0" with
e870a1
the name of a device it actually created for this guest, that meant
e870a1
that "macvtap0" was deleted, *even though it was currently in use by a
e870a1
different guest*!
e870a1
e870a1
Whew!
e870a1
e870a1
So, it turns out that when formatting "migratable" XML, "vnetX"
e870a1
devices are omitted, just as when formatting "inactive" XML. By making
e870a1
the code in both interface parsing and formatting consistent for
e870a1
"vnetX", "macvtapX", and "macvlanX", we can thus make sure that the
e870a1
autogenerated (and unneeded / completely *not* wanted) macvtap device
e870a1
name will not be sent with the migration XML. This way when a
e870a1
migration fails, net->ifname will be NULL, and libvirt won't have any
e870a1
device to try and (erroneously) delete.
e870a1
e870a1
Signed-off-by: Laine Stump <laine@redhat.com>
e870a1
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
e870a1
(cherry picked from commit 282d135ddbb7203565cd5527b451469b14953994)
e870a1
e870a1
https://bugzilla.redhat.com/1868549
e870a1
e870a1
Conflicts: src/conf/domain_conf.c - glib is now used upstream. Also
e870a1
  upstream has added managed_tap, which changes the context of one
e870a1
  hunk, and the position+context+exact content of another.
e870a1
e870a1
Signed-off-by: Laine Stump <laine@redhat.com>
e870a1
Message-Id: <20200913142625.21235-1-laine@redhat.com>
e870a1
Reviewed-by: Ján Tomko <jtomko@redhat.com>
e870a1
---
e870a1
 src/conf/domain_conf.c | 26 +++++++++++---------------
e870a1
 1 file changed, 11 insertions(+), 15 deletions(-)
e870a1
e870a1
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
e870a1
index 8bd527cfa1..75d099fdc7 100644
e870a1
--- a/src/conf/domain_conf.c
e870a1
+++ b/src/conf/domain_conf.c
e870a1
@@ -11411,13 +11411,6 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
e870a1
             } else if (!ifname &&
e870a1
                        virXMLNodeNameEqual(cur, "target")) {
e870a1
                 ifname = virXMLPropString(cur, "dev");
e870a1
-                if (ifname &&
e870a1
-                    (flags & VIR_DOMAIN_DEF_PARSE_INACTIVE) &&
e870a1
-                    (STRPREFIX(ifname, VIR_NET_GENERATED_TAP_PREFIX) ||
e870a1
-                     (prefix && STRPREFIX(ifname, prefix)))) {
e870a1
-                    /* An auto-generated target name, blank it out */
e870a1
-                    VIR_FREE(ifname);
e870a1
-                }
e870a1
             } else if ((!ifname_guest || !ifname_guest_actual) &&
e870a1
                        virXMLNodeNameEqual(cur, "guest")) {
e870a1
                 ifname_guest = virXMLPropString(cur, "dev");
e870a1
@@ -11708,14 +11701,6 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
e870a1
 
e870a1
         def->data.direct.linkdev = dev;
e870a1
         dev = NULL;
e870a1
-
e870a1
-        if (ifname &&
e870a1
-            flags & VIR_DOMAIN_DEF_PARSE_INACTIVE &&
e870a1
-            (STRPREFIX(ifname, VIR_NET_GENERATED_MACVTAP_PREFIX) ||
e870a1
-             STRPREFIX(ifname, VIR_NET_GENERATED_MACVLAN_PREFIX))) {
e870a1
-            VIR_FREE(ifname);
e870a1
-        }
e870a1
-
e870a1
         break;
e870a1
 
e870a1
     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
e870a1
@@ -11757,6 +11742,15 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
e870a1
         def->domain_name = domain_name;
e870a1
         domain_name = NULL;
e870a1
     }
e870a1
+    if (ifname &&
e870a1
+        (flags & VIR_DOMAIN_DEF_PARSE_INACTIVE) &&
e870a1
+        (STRPREFIX(ifname, VIR_NET_GENERATED_TAP_PREFIX) ||
e870a1
+         STRPREFIX(ifname, VIR_NET_GENERATED_MACVTAP_PREFIX) ||
e870a1
+         STRPREFIX(ifname, VIR_NET_GENERATED_MACVLAN_PREFIX) ||
e870a1
+         (prefix && STRPREFIX(ifname, prefix)))) {
e870a1
+         /* An auto-generated target name, blank it out */
e870a1
+         VIR_FREE(ifname);
e870a1
+    }
e870a1
     if (ifname != NULL) {
e870a1
         def->ifname = ifname;
e870a1
         ifname = NULL;
e870a1
@@ -25394,6 +25388,8 @@ virDomainNetDefFormat(virBufferPtr buf,
e870a1
     if (def->ifname &&
e870a1
         !((flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE) &&
e870a1
           (STRPREFIX(def->ifname, VIR_NET_GENERATED_TAP_PREFIX) ||
e870a1
+           STRPREFIX(def->ifname, VIR_NET_GENERATED_MACVTAP_PREFIX) ||
e870a1
+           STRPREFIX(def->ifname, VIR_NET_GENERATED_MACVLAN_PREFIX) ||
e870a1
            (prefix && STRPREFIX(def->ifname, prefix))))) {
e870a1
         /* Skip auto-generated target names for inactive config. */
e870a1
         virBufferEscapeString(buf, "<target dev='%s'/>\n", def->ifname);
e870a1
-- 
e870a1
2.28.0
e870a1