[libvirt] [PATCH] qemu: homogenize MAC address in live & config when hotplugging a netdev
Michal Prívozník
mprivozn at redhat.com
Tue Dec 17 18:45:56 UTC 2019
On 12/17/19 6:04 PM, Laine Stump wrote:
> Prior to commit 55ce6564634 (first in libvirt 4.6.0), the XML sent to
> virDomainAttachDeviceFlags() was parsed only once, and the results of
> that parse were inserted into both the live object of the running
> domain and into the persistent config. Thus, if MAC address was
> omitted from in XML for a network device (<interface>), both the live
> and config object would have the same MAC address.
>
> Commit 55ce6564634 changed the code to parse the incoming XML twice -
> once for live and once for config. This does eliminate the problem of
> PCI (/scsi/sata) address conflicts caused by allocating an address
> based on existing devices in live object, but then inserting the
> result into the config (which may already have a device using that
> address), BUT it also means that when the MAC address of a network
> device hasn't been specified in the XML, each copy will get a
> different auto-generated MAC address.
>
> This results in the MAC address of the device changing the next time
> the domain is shutdown and restarted, which creates havoc with the
> guest OS's network config.
>
> There have been several discussions about this in the last > 1 year,
> attempting to find the ideal solution to this problem that makes MAC
> addresses consistent and accounts for all sorts of corner cases with
> PCI/scsi/sata addresses. All of these discussions fizzled out because
> every proposal was either too difficult to implement or failed to fix
> some esoteric case someone thought up.
>
> So, in the interest of solving the MAC address problem while not
> making the "other address" situation any worse than before, this patch
> simply adds a qemuDomainAttachDeviceLiveAndConfigHomogenize() function
> that (for now) copies the MAC address from the config object to the
> live object (if the original xml had <mac address='blah'/> then this
> will be an effective NOP (as the macs already match)).
>
> Any downstream libvirt containing upstream commit
> 55ce6564634 should have this patch as well.
>
> https://bugzilla.redhat.com/1783411
> Signed-off-by: Laine Stump <laine at redhat.com>
> ---
> src/qemu/qemu_driver.c | 35 +++++++++++++++++++++++++++++++++++
> 1 file changed, 35 insertions(+)
>
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 924f01d3eb..19ddff80b5 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -8623,6 +8623,30 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
> return 0;
> }
>
> +
> +static void
> +qemuDomainAttachDeviceLiveAndConfigHomogenize(const virDomainDeviceDef *devConf,
> + virDomainDeviceDefPtr devLive)
> +{
> + /*
> + * fixup anything that needs to be identical in the live and
s/fixup/Fixup/
> + * config versions of DeviceDef, but might not be. Do this by
> + * changing the contents of devLive.
We need to warn everybody that only "small" changes are okay. I mean, we
probably don't have to explicitly warn about not changing PCI address,
but something among these lines should do:
Remember, this is done after post parse and all other checks, be very
careful!
> + */
> +
> + /* MAC address should be identical in both DeviceDefs, but if it
> + * wasn't specified in the XML, and was instead autogenerated, it
> + * will be different for the two since they are each the result of
> + * a separate parser call. If it *was* specified, it will already
> + * be the same, so copying does no harm.
> + */
> +
> + if (devConf->type == VIR_DOMAIN_DEVICE_NET)
> + virMacAddrSet(&devLive->data.net->mac, &devConf->data.net->mac);
> +
> +}
> +
> +
> static int
> qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm,
> virQEMUDriverPtr driver,
> @@ -8633,6 +8657,7 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm,
> virDomainDefPtr vmdef = NULL;
> g_autoptr(virQEMUDriverConfig) cfg = NULL;
> virDomainDeviceDefPtr devConf = NULL;
> + virDomainDeviceDef devConfSave = { 0 };
> virDomainDeviceDefPtr devLive = NULL;
> int ret = -1;
> unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
> @@ -8657,6 +8682,13 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm,
> parse_flags)))
> goto cleanup;
>
> + /*
> + * devConf will be NULLed out by
> + * qemuDomainAttachDeviceConfig(), so save it for later use by
> + * qemuDomainDeviceLiveAndConfigHomogenize()
This function was renamed ;-)
> + */
> + devConfSave = *devConf;
> +
> if (virDomainDeviceValidateAliasForHotplug(vm, devConf,
> VIR_DOMAIN_AFFECT_CONFIG) < 0)
> goto cleanup;
> @@ -8678,6 +8710,9 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm,
> parse_flags)))
> goto cleanup;
>
> + if (flags & VIR_DOMAIN_AFFECT_CONFIG)
> + qemuDomainAttachDeviceLiveAndConfigHomogenize(&devConfSave, devLive);
> +
> if (virDomainDeviceValidateAliasForHotplug(vm, devLive,
> VIR_DOMAIN_AFFECT_LIVE) < 0)
> goto cleanup;
>
Reviewed-by: Michal Privoznik <mprivozn at redhat.com>
and consider squashing the following in:
diff --git i/src/qemu/qemu_driver.c w/src/qemu/qemu_driver.c
index 19ddff80b5..0d4e9c69c2 100644
--- i/src/qemu/qemu_driver.c
+++ w/src/qemu/qemu_driver.c
@@ -8629,9 +8629,10 @@
qemuDomainAttachDeviceLiveAndConfigHomogenize(const virDomainDeviceDef
*devConf,
virDomainDeviceDefPtr
devLive)
{
/*
- * fixup anything that needs to be identical in the live and
+ * Fixup anything that needs to be identical in the live and
* config versions of DeviceDef, but might not be. Do this by
- * changing the contents of devLive.
+ * changing the contents of devLive. Remember, this is done
+ * after post parse and all other checks, be very careful!
*/
/* MAC address should be identical in both DeviceDefs, but if it
@@ -8685,7 +8686,7 @@
qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm,
/*
* devConf will be NULLed out by
* qemuDomainAttachDeviceConfig(), so save it for later use by
- * qemuDomainDeviceLiveAndConfigHomogenize()
+ * qemuDomainAttachDeviceLiveAndConfigHomogenize()
*/
devConfSave = *devConf;
Michal
More information about the libvir-list
mailing list