From: Laine Stump Date: Wed, 10 Dec 2014 17:41:16 +0000 (-0500) Subject: qemu: add/remove bridge fdb entries as guest CPUs are started/stopped X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=44292e48a0ffa76badf84d42ad33f885e67d30e9;p=libvirt.git qemu: add/remove bridge fdb entries as guest CPUs are started/stopped When libvirt is managing a bridge's forwarding database (FDB) (macTableManager='libvirt'), if we add FDB entries for a new guest interface even before the qemu process is created, then in the case of a migration any other guest attached to the "destination" bridge will have its traffic immediately sent to the destination of the migration even while the source domain is still running (and the destination, of course, isn't). To make sure that traffic from other guests on the new host continues flowing to the old guest until the new one is ready, we have to wait until the new guest CPUs are started to add the FDB entries. Conversely, we need to remove the FDB entries from the bridge any time the guest CPUs are stopped; among other things, this will assure proper operation during a post-copy migration (which is just the opposite of the problem described in the previous paragraph). --- diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index c44560f299..53d662906b 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -335,18 +335,14 @@ qemuNetworkIfaceConnect(virDomainDefPtr def, /* libvirt is managing the FDB of the bridge this device * is attaching to, so we need to turn off learning and * unicast_flood on the device to prevent the kernel from - * adding any FDB entries for it, then add an fdb entry - * outselves, using the MAC address from the interface - * config. + * adding any FDB entries for it. We will add add an fdb + * entry ourselves (during qemuInterfaceStartDevices(), + * using the MAC address from the interface config. */ if (virNetDevBridgePortSetLearning(brname, net->ifname, false) < 0) goto cleanup; if (virNetDevBridgePortSetUnicastFlood(brname, net->ifname, false) < 0) goto cleanup; - if (virNetDevBridgeFDBAdd(&net->mac, net->ifname, - VIR_NETDEVBRIDGE_FDB_FLAG_MASTER | - VIR_NETDEVBRIDGE_FDB_FLAG_TEMP) < 0) - goto cleanup; } } else { if (qemuCreateInBridgePortWithHelper(cfg, brname, diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c index 2d33075f54..201a7dd30b 100644 --- a/src/qemu/qemu_interface.c +++ b/src/qemu/qemu_interface.c @@ -23,10 +23,12 @@ #include +#include "network_conf.h" #include "qemu_interface.h" #include "virnetdev.h" #include "virnetdevtap.h" #include "virnetdevmacvlan.h" +#include "virnetdevbridge.h" #include "virnetdevvportprofile.h" /** @@ -46,6 +48,20 @@ qemuInterfaceStartDevice(virDomainNetDefPtr net) switch (actualType) { case VIR_DOMAIN_NET_TYPE_BRIDGE: case VIR_DOMAIN_NET_TYPE_NETWORK: + if (virDomainNetGetActualBridgeMACTableManager(net) + == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) { + /* libvirt is managing the FDB of the bridge this device + * is attaching to, so we have turned off learning and + * unicast_flood on the device to prevent the kernel from + * adding any FDB entries for it. This means we need to + * add an fdb entry ourselves, using the MAC address from + * the interface config. + */ + if (virNetDevBridgeFDBAdd(&net->mac, net->ifname, + VIR_NETDEVBRIDGE_FDB_FLAG_MASTER | + VIR_NETDEVBRIDGE_FDB_FLAG_TEMP) < 0) + goto cleanup; + } break; case VIR_DOMAIN_NET_TYPE_DIRECT: /* macvtap devices share their MAC address with the guest @@ -118,6 +134,16 @@ qemuInterfaceStopDevice(virDomainNetDefPtr net) switch (actualType) { case VIR_DOMAIN_NET_TYPE_BRIDGE: case VIR_DOMAIN_NET_TYPE_NETWORK: + if (virDomainNetGetActualBridgeMACTableManager(net) + == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) { + /* remove the FDB entries that were added during + * qemuInterfaceStartDevices() + */ + if (virNetDevBridgeFDBDel(&net->mac, net->ifname, + VIR_NETDEVBRIDGE_FDB_FLAG_MASTER | + VIR_NETDEVBRIDGE_FDB_FLAG_TEMP) < 0) + goto cleanup; + } break; case VIR_DOMAIN_NET_TYPE_DIRECT: