9119d9
From 2d14de522db3d5735e02f76e9204e550363a37ea Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <2d14de522db3d5735e02f76e9204e550363a37ea@dist-git>
9119d9
From: Matthew Rosato <mjrosato@linux.vnet.ibm.com>
9119d9
Date: Sun, 14 Dec 2014 23:44:49 -0500
9119d9
Subject: [PATCH] network: Bring netdevs online later
9119d9
9119d9
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1081461
9119d9
9119d9
Currently, MAC registration occurs during device creation, which is
9119d9
early enough that, during live migration, you end up with duplicate
9119d9
MAC addresses on still-running source and target devices, even though
9119d9
the target device isn't actually being used yet.
9119d9
This patch proposes to defer MAC registration until right before
9119d9
the guest can actually use the device -- In other words, right
9119d9
before starting guest CPUs.
9119d9
9119d9
Signed-off-by: Matthew Rosato <mjrosato@linux.vnet.ibm.com>
9119d9
Signed-off-by: Laine Stump <laine@laine.org>
9119d9
(cherry picked from commit 82977058f5b1d143a355079900029e9cbfee2fe4)
9119d9
9119d9
Conflicts:
9119d9
	src/lxc/lxc_process.c
9119d9
          - bandwidth removed from function arglist upstream
9119d9
	src/qemu/qemu_hotplug.c
9119d9
          - context upstream different due to centralized handling
9119d9
            of bandwidth setting.
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 src/Makefile.am             |   3 +-
9119d9
 src/lxc/lxc_process.c       |   4 +-
9119d9
 src/qemu/qemu_hotplug.c     |   5 +++
9119d9
 src/qemu/qemu_interface.c   | 100 ++++++++++++++++++++++++++++++++++++++++++++
9119d9
 src/qemu/qemu_interface.h   |  32 ++++++++++++++
9119d9
 src/qemu/qemu_process.c     |   7 ++++
9119d9
 src/util/virnetdevmacvlan.c |   8 ++--
9119d9
 src/util/virnetdevmacvlan.h |   2 +
9119d9
 8 files changed, 156 insertions(+), 5 deletions(-)
9119d9
 create mode 100644 src/qemu/qemu_interface.c
9119d9
 create mode 100644 src/qemu/qemu_interface.h
9119d9
9119d9
diff --git a/src/Makefile.am b/src/Makefile.am
9119d9
index fa741a8..035120e 100644
9119d9
--- a/src/Makefile.am
9119d9
+++ b/src/Makefile.am
9119d9
@@ -703,7 +703,8 @@ QEMU_DRIVER_SOURCES =							\
9119d9
 		qemu/qemu_monitor_text.h				\
9119d9
 		qemu/qemu_monitor_json.c				\
9119d9
 		qemu/qemu_monitor_json.h				\
9119d9
-		qemu/qemu_driver.c qemu/qemu_driver.h
9119d9
+		qemu/qemu_driver.c qemu/qemu_driver.h	\
9119d9
+		qemu/qemu_interface.c qemu/qemu_interface.h
9119d9
 
9119d9
 XENAPI_DRIVER_SOURCES =						\
9119d9
 		xenapi/xenapi_driver.c xenapi/xenapi_driver.h	\
9119d9
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
9119d9
index 6c83fdb..3b294fe 100644
9119d9
--- a/src/lxc/lxc_process.c
9119d9
+++ b/src/lxc/lxc_process.c
9119d9
@@ -300,6 +300,7 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn,
9119d9
     virNetDevBandwidthPtr bw;
9119d9
     virNetDevVPortProfilePtr prof;
9119d9
     virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
9119d9
+    unsigned int macvlan_create_flags = VIR_NETDEV_MACVLAN_CREATE_IFUP;
9119d9
 
9119d9
     /* XXX how todo bandwidth controls ?
9119d9
      * Since the 'net-ifname' is about to be moved to a different
9119d9
@@ -336,7 +337,8 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn,
9119d9
             &res_ifname,
9119d9
             VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
9119d9
             cfg->stateDir,
9119d9
-            virDomainNetGetActualBandwidth(net), 0) < 0)
9119d9
+            virDomainNetGetActualBandwidth(net),
9119d9
+            macvlan_create_flags) < 0)
9119d9
         goto cleanup;
9119d9
 
9119d9
     ret = res_ifname;
9119d9
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
9119d9
index 54febb3..aaa7e21 100644
9119d9
--- a/src/qemu/qemu_hotplug.c
9119d9
+++ b/src/qemu/qemu_hotplug.c
9119d9
@@ -30,6 +30,7 @@
9119d9
 #include "qemu_domain.h"
9119d9
 #include "qemu_command.h"
9119d9
 #include "qemu_hostdev.h"
9119d9
+#include "qemu_interface.h"
9119d9
 #include "domain_audit.h"
9119d9
 #include "domain_nwfilter.h"
9119d9
 #include "virlog.h"
9119d9
@@ -948,6 +949,10 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
9119d9
             goto cleanup;
9119d9
     }
9119d9
 
9119d9
+    /* Set device online immediately */
9119d9
+    if (qemuInterfaceStartDevice(net) < 0)
9119d9
+       goto cleanup;
9119d9
+
9119d9
     for (i = 0; i < tapfdSize; i++) {
9119d9
         if (virSecurityManagerSetTapFDLabel(driver->securityManager,
9119d9
                                             vm->def, tapfd[i]) < 0)
9119d9
diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c
9119d9
new file mode 100644
9119d9
index 0000000..b0f0c5d
9119d9
--- /dev/null
9119d9
+++ b/src/qemu/qemu_interface.c
9119d9
@@ -0,0 +1,100 @@
9119d9
+/*
9119d9
+ * qemu_interface.c: QEMU interface management
9119d9
+ *
9119d9
+ * Copyright IBM Corp. 2014
9119d9
+ *
9119d9
+ * This library is free software; you can redistribute it and/or
9119d9
+ * modify it under the terms of the GNU Lesser General Public
9119d9
+ * License as published by the Free Software Foundation; either
9119d9
+ * version 2.1 of the License, or (at your option) any later version.
9119d9
+ *
9119d9
+ * This library is distributed in the hope that it will be useful,
9119d9
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9119d9
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
9119d9
+ * Lesser General Public License for more details.
9119d9
+ *
9119d9
+ * You should have received a copy of the GNU Lesser General Public
9119d9
+ * License along with this library.  If not, see
9119d9
+ * <http://www.gnu.org/licenses/>.
9119d9
+ *
9119d9
+ * Authors:
9119d9
+ *     Matthew J. Rosato <mjrosato@linux.vnet.ibm.com>
9119d9
+ */
9119d9
+
9119d9
+#include <config.h>
9119d9
+
9119d9
+#include "qemu_interface.h"
9119d9
+#include "virnetdev.h"
9119d9
+#include "virnetdevtap.h"
9119d9
+#include "virnetdevmacvlan.h"
9119d9
+#include "virnetdevvportprofile.h"
9119d9
+
9119d9
+/**
9119d9
+ * qemuInterfaceStartDevice:
9119d9
+ * @net: net device to start
9119d9
+ *
9119d9
+ * Based upon the type of device provided, perform the appropriate
9119d9
+ * work to completely activate the device and make it reachable from
9119d9
+ * the rest of the network.
9119d9
+ */
9119d9
+int
9119d9
+qemuInterfaceStartDevice(virDomainNetDefPtr net)
9119d9
+{
9119d9
+    int ret = -1;
9119d9
+
9119d9
+    switch (virDomainNetGetActualType(net)) {
9119d9
+    case VIR_DOMAIN_NET_TYPE_BRIDGE:
9119d9
+    case VIR_DOMAIN_NET_TYPE_NETWORK:
9119d9
+        break;
9119d9
+    case VIR_DOMAIN_NET_TYPE_DIRECT:
9119d9
+        /* macvtap devices share their MAC address with the guest
9119d9
+         * domain, and if they are set online prior to the domain CPUs
9119d9
+         * being started, the host may send out traffic from this
9119d9
+         * device that could confuse other entities on the network (in
9119d9
+         * particular, if this new domain is the destination of a
9119d9
+         * migration, and the source domain is still running, another
9119d9
+         * host may mistakenly direct traffic for the guest to the
9119d9
+         * destination domain rather than source domain). To prevent
9119d9
+         * this, we create the macvtap device with IFF_UP false
9119d9
+         * (i.e. "offline") then wait to bring it online until just as
9119d9
+         * we are starting the domain CPUs.
9119d9
+         */
9119d9
+        if (virNetDevSetOnline(net->ifname, true) < 0)
9119d9
+            goto cleanup;
9119d9
+        break;
9119d9
+
9119d9
+    case VIR_DOMAIN_NET_TYPE_USER:
9119d9
+    case VIR_DOMAIN_NET_TYPE_ETHERNET:
9119d9
+    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
9119d9
+    case VIR_DOMAIN_NET_TYPE_SERVER:
9119d9
+    case VIR_DOMAIN_NET_TYPE_CLIENT:
9119d9
+    case VIR_DOMAIN_NET_TYPE_MCAST:
9119d9
+    case VIR_DOMAIN_NET_TYPE_INTERNAL:
9119d9
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
9119d9
+    case VIR_DOMAIN_NET_TYPE_LAST:
9119d9
+        /* these types all require no action */
9119d9
+        break;
9119d9
+    }
9119d9
+
9119d9
+    ret = 0;
9119d9
+ cleanup:
9119d9
+    return ret;
9119d9
+}
9119d9
+
9119d9
+/**
9119d9
+ * qemuInterfaceStartDevices:
9119d9
+ * @def: domain definition
9119d9
+ *
9119d9
+ * Set all ifaces associated with this domain to the online state.
9119d9
+ */
9119d9
+int
9119d9
+qemuInterfaceStartDevices(virDomainDefPtr def)
9119d9
+{
9119d9
+    size_t i;
9119d9
+
9119d9
+    for (i = 0; i < def->nnets; i++) {
9119d9
+        if (qemuInterfaceStartDevice(def->nets[i]) < 0)
9119d9
+            return -1;
9119d9
+    }
9119d9
+    return 0;
9119d9
+}
9119d9
diff --git a/src/qemu/qemu_interface.h b/src/qemu/qemu_interface.h
9119d9
new file mode 100644
9119d9
index 0000000..d040f52
9119d9
--- /dev/null
9119d9
+++ b/src/qemu/qemu_interface.h
9119d9
@@ -0,0 +1,32 @@
9119d9
+/*
9119d9
+ * qemu_interface.h: QEMU interface management
9119d9
+ *
9119d9
+ * Copyright IBM Corp. 2014
9119d9
+ *
9119d9
+ * This library is free software; you can redistribute it and/or
9119d9
+ * modify it under the terms of the GNU Lesser General Public
9119d9
+ * License as published by the Free Software Foundation; either
9119d9
+ * version 2.1 of the License, or (at your option) any later version.
9119d9
+ *
9119d9
+ * This library is distributed in the hope that it will be useful,
9119d9
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9119d9
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
9119d9
+ * Lesser General Public License for more details.
9119d9
+ *
9119d9
+ * You should have received a copy of the GNU Lesser General Public
9119d9
+ * License along with this library.  If not, see
9119d9
+ * <http://www.gnu.org/licenses/>.
9119d9
+ *
9119d9
+ * Authors:
9119d9
+ *     Matthew J. Rosato <mjrosato@linux.vnet.ibm.com>
9119d9
+ */
9119d9
+
9119d9
+#ifndef __QEMU_INTERFACE_H__
9119d9
+# define __QEMU_INTERFACE_H__
9119d9
+
9119d9
+# include "domain_conf.h"
9119d9
+
9119d9
+int qemuInterfaceStartDevice(virDomainNetDefPtr net);
9119d9
+int qemuInterfaceStartDevices(virDomainDefPtr def);
9119d9
+
9119d9
+#endif /* __QEMU_INTERFACE_H__ */
9119d9
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
9119d9
index 3d275a3..dd74432 100644
9119d9
--- a/src/qemu/qemu_process.c
9119d9
+++ b/src/qemu/qemu_process.c
9119d9
@@ -42,6 +42,7 @@
9119d9
 #include "qemu_hostdev.h"
9119d9
 #include "qemu_hotplug.h"
9119d9
 #include "qemu_migration.h"
9119d9
+#include "qemu_interface.h"
9119d9
 
9119d9
 #include "cpu/cpu.h"
9119d9
 #include "datatypes.h"
9119d9
@@ -3112,6 +3113,12 @@ qemuProcessStartCPUs(virQEMUDriverPtr driver, virDomainObjPtr vm,
9119d9
     qemuDomainObjPrivatePtr priv = vm->privateData;
9119d9
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
9119d9
 
9119d9
+    /* Bring up netdevs before starting CPUs */
9119d9
+    if (reason != VIR_DOMAIN_RUNNING_UNPAUSED &&
9119d9
+        reason != VIR_DOMAIN_RUNNING_SAVE_CANCELED &&
9119d9
+        qemuInterfaceStartDevices(vm->def) < 0)
9119d9
+       goto cleanup;
9119d9
+
9119d9
     VIR_DEBUG("Using lock state '%s'", NULLSTR(priv->lockState));
9119d9
     if (virDomainLockProcessResume(driver->lockManager, cfg->uri,
9119d9
                                    vm, priv->lockState) < 0) {
9119d9
diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c
9119d9
index 50aabc5..9f4c2a7 100644
9119d9
--- a/src/util/virnetdevmacvlan.c
9119d9
+++ b/src/util/virnetdevmacvlan.c
9119d9
@@ -903,9 +903,11 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *tgifname,
9119d9
         goto link_del_exit;
9119d9
     }
9119d9
 
9119d9
-    if (virNetDevSetOnline(cr_ifname, true) < 0) {
9119d9
-        rc = -1;
9119d9
-        goto disassociate_exit;
9119d9
+    if (flags & VIR_NETDEV_MACVLAN_CREATE_IFUP) {
9119d9
+        if (virNetDevSetOnline(cr_ifname, true) < 0) {
9119d9
+            rc = -1;
9119d9
+            goto disassociate_exit;
9119d9
+        }
9119d9
     }
9119d9
 
9119d9
     if (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) {
9119d9
diff --git a/src/util/virnetdevmacvlan.h b/src/util/virnetdevmacvlan.h
9119d9
index 41aa4e2..41b4014 100644
9119d9
--- a/src/util/virnetdevmacvlan.h
9119d9
+++ b/src/util/virnetdevmacvlan.h
9119d9
@@ -44,6 +44,8 @@ typedef enum {
9119d9
    VIR_NETDEV_MACVLAN_CREATE_NONE     = 0,
9119d9
    /* Create with a tap device */
9119d9
    VIR_NETDEV_MACVLAN_CREATE_WITH_TAP = 1 << 0,
9119d9
+   /* Bring the interface up */
9119d9
+   VIR_NETDEV_MACVLAN_CREATE_IFUP     = 1 << 1,
9119d9
 } virNetDevMacVLanCreateFlags;
9119d9
 
9119d9
 int virNetDevMacVLanCreate(const char *ifname,
9119d9
-- 
9119d9
2.2.0
9119d9