This is only used in the ESX driver where, when set to "static", 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@xxxxxxxxxxx> --- NEWS.rst | 6 ++++ docs/schemas/domaincommon.rng | 8 +++++ src/conf/domain_conf.c | 26 ++++++++++++++++- src/conf/domain_conf.h | 11 +++++++ src/vmx/vmx.c | 8 +++-- .../network-interface-mac-type.xml | 29 +++++++++++++++++++ tests/genericxml2xmltest.c | 2 ++ 7 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 tests/genericxml2xmlindata/network-interface-mac-type.xml diff --git a/NEWS.rst b/NEWS.rst index 1928220854..2c6c628c61 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -18,6 +18,12 @@ v6.6.0 (unreleased) Libvirt allows configuring ACPI Heterogeneous Memory Attribute Table to hint software running inside the guest on optimization. + * esx: Add a ``type`` attribute for mac addresses. + + This attribute allows (when set to ``static``) ignoring VMWare checks of the + MAC addresses that would generate a new one if they were in its OUI + (00:0c:29). + * **Improvements** * esx: Change the NIC limit for recent virtualHW versions diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 4b4aa60c66..a810f569c6 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3179,6 +3179,14 @@ <attribute name="address"> <ref name="uniMacAddr"/> </attribute> + <optional> + <attribute name="type"> + <choice> + <value>generated</value> + <value>static</value> + </choice> + </attribute> + </optional> <empty/> </element> </optional> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index d14485f18d..93e203de23 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -611,6 +611,13 @@ VIR_ENUM_IMPL(virDomainChrDeviceState, "disconnected", ); +VIR_ENUM_IMPL(virDomainNetMacType, + VIR_DOMAIN_NET_MAC_TYPE_LAST, + "", + "generated", + "static", +); + VIR_ENUM_IMPL(virDomainChrSerialTarget, VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_LAST, "none", @@ -11904,6 +11911,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, virDomainChrSourceReconnectDef reconnect = {0}; int rv, val; g_autofree char *macaddr = NULL; + g_autofree char *macaddr_type = NULL; g_autofree char *type = NULL; g_autofree char *network = NULL; g_autofree char *portgroup = NULL; @@ -11984,6 +11992,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, } if (!macaddr && virXMLNodeNameEqual(cur, "mac")) { macaddr = virXMLPropString(cur, "address"); + macaddr_type = virXMLPropString(cur, "type"); } else if (!network && def->type == VIR_DOMAIN_NET_TYPE_NETWORK && virXMLNodeNameEqual(cur, "source")) { @@ -12173,6 +12182,18 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, def->mac_generated = true; } + if (macaddr_type) { + virDomainNetMacType tmp; + if ((tmp = virDomainNetMacTypeTypeFromString(macaddr_type)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, + _("invalid mac address check value: '%s'. Valid " + "values are \"generated\" and \"static\"."), + macaddr_type); + goto error; + } + def->mac_type = tmp; + } + if (virDomainDeviceInfoParseXML(xmlopt, node, &def->info, flags | VIR_DOMAIN_DEF_PARSE_ALLOW_BOOT | VIR_DOMAIN_DEF_PARSE_ALLOW_ROM) < 0) { @@ -26468,8 +26489,11 @@ virDomainNetDefFormat(virBufferPtr buf, virBufferAddLit(buf, ">\n"); virBufferAdjustIndent(buf, 2); - virBufferAsprintf(buf, "<mac address='%s'/>\n", + virBufferAsprintf(buf, "<mac address='%s'", virMacAddrFormat(&def->mac, macstr)); + if (def->mac_type) + virBufferAsprintf(buf, " type='%s'", virDomainNetMacTypeTypeToString(def->mac_type)); + virBufferAddLit(buf, "/>\n"); if (publicActual) { /* when there is a virDomainActualNetDef, and we haven't been diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6a737591e2..7b754f959d 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -921,6 +921,15 @@ typedef enum { VIR_DOMAIN_NET_VIRTIO_TX_MODE_LAST } virDomainNetVirtioTxModeType; +/* whether a mac address should be marked as generated in the esx driver or not*/ +typedef enum { + VIR_DOMAIN_NET_MAC_TYPE_DEFAULT, /* generated */ + VIR_DOMAIN_NET_MAC_TYPE_GENERATED, + VIR_DOMAIN_NET_MAC_TYPE_STATIC, + + VIR_DOMAIN_NET_MAC_TYPE_LAST +} virDomainNetMacType; + /* the type of teaming device */ typedef enum { VIR_DOMAIN_NET_TEAMING_TYPE_NONE, @@ -972,6 +981,7 @@ struct _virDomainNetDef { virDomainNetType type; virMacAddr mac; bool mac_generated; /* true if mac was *just now* auto-generated by libvirt */ + virDomainNetMacType mac_type; int model; /* virDomainNetModelType */ char *modelstr; union { @@ -3556,6 +3566,7 @@ VIR_ENUM_DECL(virDomainFSCacheMode); VIR_ENUM_DECL(virDomainNet); VIR_ENUM_DECL(virDomainNetBackend); VIR_ENUM_DECL(virDomainNetVirtioTxMode); +VIR_ENUM_DECL(virDomainNetMacType); VIR_ENUM_DECL(virDomainNetTeaming); VIR_ENUM_DECL(virDomainNetInterfaceLinkState); VIR_ENUM_DECL(virDomainNetModel); diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c index d4d66f6768..b307072869 100644 --- a/src/vmx/vmx.c +++ b/src/vmx/vmx.c @@ -3829,19 +3829,21 @@ virVMXFormatEthernet(virDomainNetDefPtr def, int controller, prefix = (def->mac.addr[0] << 16) | (def->mac.addr[1] << 8) | def->mac.addr[2]; suffix = (def->mac.addr[3] << 16) | (def->mac.addr[4] << 8) | def->mac.addr[5]; - if (prefix == 0x000c29) { + bool staticMac = def->mac_type == VIR_DOMAIN_NET_MAC_TYPE_STATIC; + + if (prefix == 0x000c29 && !staticMac) { virBufferAsprintf(buffer, "ethernet%d.addressType = \"generated\"\n", controller); virBufferAsprintf(buffer, "ethernet%d.generatedAddress = \"%s\"\n", controller, mac_string); virBufferAsprintf(buffer, "ethernet%d.generatedAddressOffset = \"0\"\n", controller); - } else if (prefix == 0x005056 && suffix <= 0x3fffff) { + } else if (prefix == 0x005056 && suffix <= 0x3fffff && !staticMac) { virBufferAsprintf(buffer, "ethernet%d.addressType = \"static\"\n", controller); virBufferAsprintf(buffer, "ethernet%d.address = \"%s\"\n", controller, mac_string); - } else if (prefix == 0x005056 && suffix >= 0x800000 && suffix <= 0xbfffff) { + } else if (prefix == 0x005056 && suffix >= 0x800000 && suffix <= 0xbfffff && !staticMac) { virBufferAsprintf(buffer, "ethernet%d.addressType = \"vpx\"\n", controller); virBufferAsprintf(buffer, "ethernet%d.generatedAddress = \"%s\"\n", diff --git a/tests/genericxml2xmlindata/network-interface-mac-type.xml b/tests/genericxml2xmlindata/network-interface-mac-type.xml new file mode 100644 index 0000000000..2b690629bb --- /dev/null +++ b/tests/genericxml2xmlindata/network-interface-mac-type.xml @@ -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'/> + <source bridge='br1'/> + </interface> + <interface type='bridge'> + <mac address='aa:bb:cc:dd:ee:fd' type='generated'/> + <source bridge='br2'/> + </interface> + </devices> +</domain> diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c index 8b9b0bafb6..ea6585c901 100644 --- a/tests/genericxml2xmltest.c +++ b/tests/genericxml2xmltest.c @@ -183,6 +183,8 @@ mymain(void) DO_TEST("cpu-cache-passthrough"); DO_TEST("cpu-cache-disable"); + DO_TEST("network-interface-mac-type"); + DO_TEST_DIFFERENT("chardev-tcp"); DO_TEST_FULL("chardev-tcp-missing-host", 0, false, TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE); -- 2.20.1