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(a)diateam.net>
---
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