1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-30 18:50:18 +03:00

qemu: Reflect MAC address change in live domain XML

If a guest changes MAC address on its vNIC, then QEMU emits
NIC_RX_FILTER_CHANGED event (the event is emitted in other cases
too, but that's not important right now). Now, domain XML allows
users to chose whether to trust these events or not:

  <interface trustGuestRxFilters='yes|no'/>

For the 'no' case no action is performed and the event is
ignored. But for the 'yes' case, some host side features of
corresponding vNIC (well tap/macvtap device) are tweaked to
reflect changed MAC address. But what is missing is reflecting
this new MAC address in domain XML.

Basically, what happens is: the host sees traffic with new MAC
address, all tools inside the guest see the new MAC address
(including 'virsh domifaddr --source agent') which makes it
harder to match device in the guest with the one in the domain
XML.

Therefore, report this new MAC address as another attribute of
the <mac/> element:

  <mac address="52:54:00:a4:6f:91" currentAddress="00:11:22:33:44:55"/>

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
This commit is contained in:
Michal Privoznik 2023-06-27 17:13:33 +02:00
parent d5666b3c2e
commit ac95617d3d
6 changed files with 52 additions and 1 deletions

View File

@ -5052,6 +5052,11 @@ when it's in the reserved VMware range by adding a ``type="static"`` attribute
to the ``<mac/>`` element. Note that this attribute is useless if the provided
MAC address is outside of the reserved VMWare ranges.
:since:`Since 11.2.0`, the ``<mac/>`` element can optionally contain
``currentAddress`` attribute (output only), which contains new MAC address if the
guest changed it. This is currently implemented only for QEMU/KVM and requires
setting ``trustGuestRxFilters`` to ``yes``.
:since:`Since 7.3.0`, one can set the ACPI index against network interfaces.
With some operating systems (eg Linux with systemd), the ACPI index is used
to provide network interface device naming, that is stable across changes

View File

@ -2853,6 +2853,7 @@ virDomainNetDefFree(virDomainNetDef *def)
if (!def)
return;
g_free(def->currentAddress);
g_free(def->modelstr);
switch (def->type) {
@ -24948,6 +24949,11 @@ virDomainNetDefFormat(virBuffer *buf,
virBufferAsprintf(&macAttrBuf, " type='%s'", virDomainNetMacTypeTypeToString(def->mac_type));
if (def->mac_check != VIR_TRISTATE_BOOL_ABSENT)
virBufferAsprintf(&macAttrBuf, " check='%s'", virTristateBoolTypeToString(def->mac_check));
if (def->currentAddress &&
!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) {
virBufferAsprintf(&macAttrBuf, " currentAddress='%s'",
virMacAddrFormat(def->currentAddress, macstr));
}
virXMLFormatElement(buf, "mac", &macAttrBuf, NULL);
if (publicActual) {

View File

@ -1091,6 +1091,9 @@ struct _virDomainNetDef {
bool mac_generated; /* true if mac was *just now* auto-generated by libvirt */
virDomainNetMacType mac_type;
virTristateBool mac_check;
virMacAddr *currentAddress; /* MAC address from query-rx-filter (as reported
by guest). Not parsed from domain XML. Output
only. */
int model; /* virDomainNetModelType */
char *modelstr;
union {

View File

@ -3844,6 +3844,11 @@
<ref name="virYesNo"/>
</attribute>
</optional>
<optional>
<attribute name="currentAddress">
<ref name="uniMacAddr"/>
</attribute>
</optional>
<empty/>
</element>
</optional>

View File

@ -11072,6 +11072,19 @@ syncNicRxFilterMulticast(char *ifname,
}
/**
* qemuDomainSyncRxFilter:
* @vm: domain object
* @def: domain interface definition
* @asyncJob: async job type
*
* Fetch new state of RX Filter and set host side of the interface
* accordingly (e.g. reflect MAC address change on macvtap).
*
* Reflect changed MAC address in the domain definition.
*
* Returns: 0 on success, -1 on error.
*/
int
qemuDomainSyncRxFilter(virDomainObj *vm,
virDomainNetDef *def,
@ -11080,6 +11093,7 @@ qemuDomainSyncRxFilter(virDomainObj *vm,
qemuDomainObjPrivate *priv = vm->privateData;
g_autoptr(virNetDevRxFilter) guestFilter = NULL;
g_autoptr(virNetDevRxFilter) hostFilter = NULL;
virMacAddr *oldMac = NULL;
int rc;
if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0)
@ -11125,6 +11139,24 @@ qemuDomainSyncRxFilter(virDomainObj *vm,
return -1;
}
if (def->currentAddress)
oldMac = def->currentAddress;
else
oldMac = &def->mac;
if (virMacAddrCmp(oldMac, &guestFilter->mac)) {
/* Reflect changed MAC address in the domain XML. */
if (virMacAddrCmp(&def->mac, &guestFilter->mac)) {
if (!def->currentAddress) {
def->currentAddress = g_new0(virMacAddr, 1);
}
virMacAddrSet(def->currentAddress, &guestFilter->mac);
} else {
VIR_FREE(def->currentAddress);
}
}
return 0;
}

View File

@ -3689,7 +3689,7 @@ processNicRxFilterChangedEvent(virDomainObj *vm,
"from domain %p %s",
devAlias, vm, vm->def->name);
if (virDomainObjBeginJob(vm, VIR_JOB_QUERY) < 0)
if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0)
return;
if (!virDomainObjIsActive(vm)) {