Add a check attribute on the mac address element

This is only used in the ESX driver where, when set to "no", it will
ignore all the checks libvirt does about the origin of the MAC address
(whether or not it's in a VMWare OUI) and forward the original one to
the ESX server telling it not to check it either.

This allows keeping a deterministic MAC address which can be useful for
licensed software which might dislike changes.

Signed-off-by: Bastien Orivel <bastien.orivel@diateam.net>

VMX conversion parts rewritten to apply on top of previously merged
support for type='generated|static'

Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Bastien Orivel 2020-07-13 11:44:13 +02:00 committed by Daniel P. Berrangé
parent 80975c3c84
commit d3aa28925f
9 changed files with 67 additions and 3 deletions

View File

@ -3187,6 +3187,11 @@
</choice>
</attribute>
</optional>
<optional>
<attribute name="check">
<ref name="virYesNo"/>
</attribute>
</optional>
<empty/>
</element>
</optional>

View File

@ -11925,6 +11925,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
int rv, val;
g_autofree char *macaddr = NULL;
g_autofree char *macaddr_type = NULL;
g_autofree char *macaddr_check = NULL;
g_autofree char *type = NULL;
g_autofree char *network = NULL;
g_autofree char *portgroup = NULL;
@ -12006,6 +12007,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
if (!macaddr && virXMLNodeNameEqual(cur, "mac")) {
macaddr = virXMLPropString(cur, "address");
macaddr_type = virXMLPropString(cur, "type");
macaddr_check = virXMLPropString(cur, "check");
} else if (!network &&
def->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
virXMLNodeNameEqual(cur, "source")) {
@ -12206,6 +12208,16 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
}
def->mac_type = tmp;
}
if (macaddr_check) {
int tmpCheck;
if ((tmpCheck = virTristateBoolTypeFromString(macaddr_check)) < 0) {
virReportError(VIR_ERR_XML_ERROR,
_("invalid mac address check value: '%s'"),
macaddr_check);
goto error;
}
def->mac_check = tmpCheck;
}
if (virDomainDeviceInfoParseXML(xmlopt, node, &def->info,
flags | VIR_DOMAIN_DEF_PARSE_ALLOW_BOOT
@ -26555,6 +26567,8 @@ virDomainNetDefFormat(virBufferPtr buf,
virMacAddrFormat(&def->mac, macstr));
if (def->mac_type)
virBufferAsprintf(buf, " type='%s'", virDomainNetMacTypeTypeToString(def->mac_type));
if (def->mac_check != VIR_TRISTATE_BOOL_ABSENT)
virBufferAsprintf(buf, " check='%s'", virTristateBoolTypeToString(def->mac_check));
virBufferAddLit(buf, "/>\n");
if (publicActual) {

View File

@ -982,6 +982,7 @@ struct _virDomainNetDef {
virMacAddr mac;
bool mac_generated; /* true if mac was *just now* auto-generated by libvirt */
virDomainNetMacType mac_type;
virTristateBool mac_check;
int model; /* virDomainNetModelType */
char *modelstr;
union {

View File

@ -2638,6 +2638,14 @@ virVMXParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
goto cleanup;
}
if (checkMACAddress) {
if (STREQ(checkMACAddress, "true")) {
(*def)->mac_check = VIR_TRISTATE_BOOL_YES;
} else {
(*def)->mac_check = VIR_TRISTATE_BOOL_NO;
}
}
/* vmx:virtualDev, vmx:features -> def:model */
if (virVMXGetConfigString(conf, virtualDev_name, &virtualDev, true) < 0 ||
virVMXGetConfigLong(conf, features_name, &features, 0, true) < 0) {
@ -3865,6 +3873,9 @@ virVMXFormatEthernet(virDomainNetDefPtr def, int controller,
mac_check = VIR_TRISTATE_BOOL_ABSENT;
}
if (def->mac_check != VIR_TRISTATE_BOOL_ABSENT)
mac_check = def->mac_check;
if (mac_type == VIR_DOMAIN_NET_MAC_TYPE_GENERATED) {
virBufferAsprintf(buffer, "ethernet%d.addressType = \"%s\"\n",
controller, mac_vpx ? "vpx" : "generated");

View File

@ -0,0 +1,29 @@
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<memory unit='KiB'>219136</memory>
<currentMemory unit='KiB'>219136</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='i686' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<interface type='bridge'>
<mac address='aa:bb:cc:dd:ee:ff'/>
<source bridge='br0'/>
</interface>
<interface type='bridge'>
<mac address='aa:bb:cc:dd:ee:fe' type='static' check='yes'/>
<source bridge='br1'/>
</interface>
<interface type='bridge'>
<mac address='aa:bb:cc:dd:ee:fd' type='generated' check='no'/>
<source bridge='br2'/>
</interface>
</devices>
</domain>

View File

@ -183,6 +183,8 @@ mymain(void)
DO_TEST("cpu-cache-passthrough");
DO_TEST("cpu-cache-disable");
DO_TEST("network-interface-mac-check");
DO_TEST_DIFFERENT("chardev-tcp");
DO_TEST_FULL("chardev-tcp-missing-host", 0, false,
TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE);

View File

@ -12,7 +12,7 @@
<on_crash>destroy</on_crash>
<devices>
<interface type='bridge'>
<mac address='00:12:34:56:78:90' type='static'/>
<mac address='00:12:34:56:78:90' type='static' check='no'/>
<source bridge='VM Network'/>
</interface>
<video>

View File

@ -20,9 +20,11 @@ ethernet1.networkName = "br1"
ethernet1.connectionType = "bridged"
ethernet1.addressType = "static"
ethernet1.address = "00:0c:29:dd:ee:fe"
ethernet1.checkMACAddress = "true"
ethernet2.present = "true"
ethernet2.networkName = "br2"
ethernet2.connectionType = "bridged"
ethernet2.addressType = "generated"
ethernet2.generatedAddress = "aa:bb:cc:dd:ee:fd"
ethernet2.generatedAddressOffset = "0"
ethernet2.checkMACAddress = "false"

View File

@ -18,11 +18,11 @@
<source bridge='br0'/>
</interface>
<interface type='bridge'>
<mac address='00:0c:29:dd:ee:fe' type='static'/>
<mac address='00:0c:29:dd:ee:fe' type='static' check='yes'/>
<source bridge='br1'/>
</interface>
<interface type='bridge'>
<mac address='aa:bb:cc:dd:ee:fd' type='generated'/>
<mac address='aa:bb:cc:dd:ee:fd' type='generated' check='no'/>
<source bridge='br2'/>
</interface>
</devices>