diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 8c0642e424..e56cffe2ea 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -3513,6 +3513,14 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver, VIR_WARN("cannot clear bandwidth setting for device : %s", detach->ifname); + /* deactivate the tap/macvtap device on the host (currently this + * isn't necessary, as everything done in + * qemuInterfaceStopDevice() is made meaningless when the device + * is deleted anyway, but in the future it may be important, and + * doesn't hurt anything for now) + */ + ignore_value(qemuInterfaceStopDevice(detach)); + qemuDomainMarkDeviceForRemoval(vm, &detach->info); qemuDomainObjEnterMonitor(driver, vm); diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c index b0f0c5df9f..2d33075f54 100644 --- a/src/qemu/qemu_interface.c +++ b/src/qemu/qemu_interface.c @@ -41,8 +41,9 @@ int qemuInterfaceStartDevice(virDomainNetDefPtr net) { int ret = -1; + virDomainNetType actualType = virDomainNetGetActualType(net); - switch (virDomainNetGetActualType(net)) { + switch (actualType) { case VIR_DOMAIN_NET_TYPE_BRIDGE: case VIR_DOMAIN_NET_TYPE_NETWORK: break; @@ -98,3 +99,70 @@ qemuInterfaceStartDevices(virDomainDefPtr def) } return 0; } + + +/** + * qemuInterfaceStopDevice: + * @net: net device to stop + * + * Based upon the type of device provided, perform the appropriate + * work to deactivate the device so that packets aren't forwarded to + * it from the rest of the network. + */ +int +qemuInterfaceStopDevice(virDomainNetDefPtr net) +{ + int ret = -1; + virDomainNetType actualType = virDomainNetGetActualType(net); + + switch (actualType) { + case VIR_DOMAIN_NET_TYPE_BRIDGE: + case VIR_DOMAIN_NET_TYPE_NETWORK: + break; + + case VIR_DOMAIN_NET_TYPE_DIRECT: + /* macvtap interfaces need to be marked !IFF_UP (ie "down") to + * prevent any host-generated traffic sent from this interface + * from putting bad info into the arp caches of other machines + * on this network. + */ + if (virNetDevSetOnline(net->ifname, false) < 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; +} + +/** + * qemuInterfaceStopDevices: + * @def: domain definition + * + * Make all interfaces associated with this domain inaccessible from + * the rest of the network. + */ +int +qemuInterfaceStopDevices(virDomainDefPtr def) +{ + size_t i; + + for (i = 0; i < def->nnets; i++) { + if (qemuInterfaceStopDevice(def->nets[i]) < 0) + return -1; + } + return 0; +} diff --git a/src/qemu/qemu_interface.h b/src/qemu/qemu_interface.h index d040f52611..b4c1efcb08 100644 --- a/src/qemu/qemu_interface.h +++ b/src/qemu/qemu_interface.h @@ -28,5 +28,7 @@ int qemuInterfaceStartDevice(virDomainNetDefPtr net); int qemuInterfaceStartDevices(virDomainDefPtr def); +int qemuInterfaceStopDevice(virDomainNetDefPtr net); +int qemuInterfaceStopDevices(virDomainDefPtr def); #endif /* __QEMU_INTERFACE_H__ */ diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 0028283cdd..a19e71a8f0 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3182,6 +3182,9 @@ int qemuProcessStopCPUs(virQEMUDriverPtr driver, if (ret < 0) goto cleanup; + /* de-activate netdevs after stopping CPUs */ + ignore_value(qemuInterfaceStopDevices(vm->def)); + if (priv->job.current) ignore_value(virTimeMillisNow(&priv->job.current->stopped));