diff --git a/src/Makefile.am b/src/Makefile.am index b6c1701381..550362cca3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -733,7 +733,8 @@ QEMU_DRIVER_SOURCES = \ qemu/qemu_monitor_text.h \ qemu/qemu_monitor_json.c \ qemu/qemu_monitor_json.h \ - qemu/qemu_driver.c qemu/qemu_driver.h + qemu/qemu_driver.c qemu/qemu_driver.h \ + qemu/qemu_interface.c qemu/qemu_interface.h XENAPI_DRIVER_SOURCES = \ xenapi/xenapi_driver.c xenapi/xenapi_driver.h \ diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 632fc17ac6..1c0d4e5bf1 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -297,6 +297,7 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn, virNetDevVPortProfilePtr prof; virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver); const char *linkdev = virDomainNetGetActualDirectDev(net); + unsigned int macvlan_create_flags = VIR_NETDEV_MACVLAN_CREATE_IFUP; /* XXX how todo bandwidth controls ? * Since the 'net-ifname' is about to be moved to a different @@ -332,7 +333,8 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn, prof, &res_ifname, VIR_NETDEV_VPORT_PROFILE_OP_CREATE, - cfg->stateDir, 0) < 0) + cfg->stateDir, + macvlan_create_flags) < 0) goto cleanup; ret = res_ifname; diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 95304517af..8c0642e424 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -30,6 +30,7 @@ #include "qemu_domain.h" #include "qemu_command.h" #include "qemu_hostdev.h" +#include "qemu_interface.h" #include "domain_audit.h" #include "netdev_bandwidth_conf.h" #include "domain_nwfilter.h" @@ -943,6 +944,10 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, goto cleanup; } + /* Set device online immediately */ + if (qemuInterfaceStartDevice(net) < 0) + goto cleanup; + /* Set Bandwidth */ if (virNetDevSupportBandwidth(actualType) && virNetDevBandwidthSet(net->ifname, diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c new file mode 100644 index 0000000000..b0f0c5df9f --- /dev/null +++ b/src/qemu/qemu_interface.c @@ -0,0 +1,100 @@ +/* + * qemu_interface.c: QEMU interface management + * + * Copyright IBM Corp. 2014 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * Authors: + * Matthew J. Rosato + */ + +#include + +#include "qemu_interface.h" +#include "virnetdev.h" +#include "virnetdevtap.h" +#include "virnetdevmacvlan.h" +#include "virnetdevvportprofile.h" + +/** + * qemuInterfaceStartDevice: + * @net: net device to start + * + * Based upon the type of device provided, perform the appropriate + * work to completely activate the device and make it reachable from + * the rest of the network. + */ +int +qemuInterfaceStartDevice(virDomainNetDefPtr net) +{ + int ret = -1; + + switch (virDomainNetGetActualType(net)) { + case VIR_DOMAIN_NET_TYPE_BRIDGE: + case VIR_DOMAIN_NET_TYPE_NETWORK: + break; + case VIR_DOMAIN_NET_TYPE_DIRECT: + /* macvtap devices share their MAC address with the guest + * domain, and if they are set online prior to the domain CPUs + * being started, the host may send out traffic from this + * device that could confuse other entities on the network (in + * particular, if this new domain is the destination of a + * migration, and the source domain is still running, another + * host may mistakenly direct traffic for the guest to the + * destination domain rather than source domain). To prevent + * this, we create the macvtap device with IFF_UP false + * (i.e. "offline") then wait to bring it online until just as + * we are starting the domain CPUs. + */ + if (virNetDevSetOnline(net->ifname, true) < 0) + goto cleanup; + break; + + case VIR_DOMAIN_NET_TYPE_USER: + case VIR_DOMAIN_NET_TYPE_ETHERNET: + case VIR_DOMAIN_NET_TYPE_VHOSTUSER: + case VIR_DOMAIN_NET_TYPE_SERVER: + case VIR_DOMAIN_NET_TYPE_CLIENT: + case VIR_DOMAIN_NET_TYPE_MCAST: + case VIR_DOMAIN_NET_TYPE_INTERNAL: + case VIR_DOMAIN_NET_TYPE_HOSTDEV: + case VIR_DOMAIN_NET_TYPE_LAST: + /* these types all require no action */ + break; + } + + ret = 0; + cleanup: + return ret; +} + +/** + * qemuInterfaceStartDevices: + * @def: domain definition + * + * Set all ifaces associated with this domain to the online state. + */ +int +qemuInterfaceStartDevices(virDomainDefPtr def) +{ + size_t i; + + for (i = 0; i < def->nnets; i++) { + if (qemuInterfaceStartDevice(def->nets[i]) < 0) + return -1; + } + return 0; +} diff --git a/src/qemu/qemu_interface.h b/src/qemu/qemu_interface.h new file mode 100644 index 0000000000..d040f52611 --- /dev/null +++ b/src/qemu/qemu_interface.h @@ -0,0 +1,32 @@ +/* + * qemu_interface.h: QEMU interface management + * + * Copyright IBM Corp. 2014 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * Authors: + * Matthew J. Rosato + */ + +#ifndef __QEMU_INTERFACE_H__ +# define __QEMU_INTERFACE_H__ + +# include "domain_conf.h" + +int qemuInterfaceStartDevice(virDomainNetDefPtr net); +int qemuInterfaceStartDevices(virDomainDefPtr def); + +#endif /* __QEMU_INTERFACE_H__ */ diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index a14b6f7fe0..ab4df9bce5 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -42,6 +42,7 @@ #include "qemu_hostdev.h" #include "qemu_hotplug.h" #include "qemu_migration.h" +#include "qemu_interface.h" #include "cpu/cpu.h" #include "datatypes.h" @@ -3124,6 +3125,12 @@ qemuProcessStartCPUs(virQEMUDriverPtr driver, virDomainObjPtr vm, qemuDomainObjPrivatePtr priv = vm->privateData; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + /* Bring up netdevs before starting CPUs */ + if (reason != VIR_DOMAIN_RUNNING_UNPAUSED && + reason != VIR_DOMAIN_RUNNING_SAVE_CANCELED && + qemuInterfaceStartDevices(vm->def) < 0) + goto cleanup; + VIR_DEBUG("Using lock state '%s'", NULLSTR(priv->lockState)); if (virDomainLockProcessResume(driver->lockManager, cfg->uri, vm, priv->lockState) < 0) { diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c index 2ff24b1f90..f2eae06115 100644 --- a/src/util/virnetdevmacvlan.c +++ b/src/util/virnetdevmacvlan.c @@ -899,9 +899,11 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *tgifname, goto link_del_exit; } - if (virNetDevSetOnline(cr_ifname, true) < 0) { - rc = -1; - goto disassociate_exit; + if (flags & VIR_NETDEV_MACVLAN_CREATE_IFUP) { + if (virNetDevSetOnline(cr_ifname, true) < 0) { + rc = -1; + goto disassociate_exit; + } } if (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) { diff --git a/src/util/virnetdevmacvlan.h b/src/util/virnetdevmacvlan.h index f08d32bf5d..298e52240e 100644 --- a/src/util/virnetdevmacvlan.h +++ b/src/util/virnetdevmacvlan.h @@ -44,6 +44,8 @@ typedef enum { VIR_NETDEV_MACVLAN_CREATE_NONE = 0, /* Create with a tap device */ VIR_NETDEV_MACVLAN_CREATE_WITH_TAP = 1 << 0, + /* Bring the interface up */ + VIR_NETDEV_MACVLAN_CREATE_IFUP = 1 << 1, } virNetDevMacVLanCreateFlags; int virNetDevMacVLanCreate(const char *ifname,