Add a type attribute on the mac address element

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@diateam.net>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Bastien Orivel 2020-07-13 16:28:53 +02:00 committed by Michal Privoznik
parent c051e56d27
commit 454e5961ab
9 changed files with 121 additions and 4 deletions

View File

@ -427,6 +427,13 @@ error: invalid argument in libvirt was built without the 'esx' driver
<pre>
ethernet0.checkMACAddress = "false"
</pre>
<p>
<span class="since">Since 6.6.0</span>, one can force libvirt to keep the
provided MAC address when it's in the reserved VMware range by adding a
<code>type="static"</code> attribute to the <code>&lt;mac/&gt;</code> element.
Note that this attribute is useless if the provided MAC address is outside of
the reserved VMWare ranges.
</p>
<h3><a id="hardware">Available hardware</a></h3>

View File

@ -5768,6 +5768,13 @@
attribute <code>type='pci'</code>
as <a href="#elementsAddress">documented above</a>.
</p>
<p>
<span class="since">Since 6.6.0</span>, one can force libvirt to keep the
provided MAC address when it's in the reserved VMware range by adding a
<code>type="static"</code> attribute to the <code>&lt;mac/&gt;</code> element.
Note that this attribute is useless if the provided MAC address is outside of
the reserved VMWare ranges.
</p>
<h5><a id="elementsNICSVirtual">Virtual network</a></h5>

View File

@ -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>

View File

@ -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) {
int 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

View File

@ -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 = 0, /* 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);

View File

@ -3732,6 +3732,7 @@ virVMXFormatEthernet(virDomainNetDefPtr def, int controller,
virBufferPtr buffer, int virtualHW_version)
{
char mac_string[VIR_MAC_STRING_BUFLEN];
const bool staticMac = def->mac_type == VIR_DOMAIN_NET_MAC_TYPE_STATIC;
unsigned int prefix, suffix;
/*
@ -3829,19 +3830,19 @@ 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) {
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",

View File

@ -0,0 +1,29 @@
.encoding = "UTF-8"
config.version = "8"
virtualHW.version = "4"
guestOS = "other"
uuid.bios = "c7 a5 fd bd ed af 94 55-92 6a d6 5c 16 db 18 09"
displayName = "ethernet-mac-type"
memsize = "216"
sched.mem.max = "214"
numvcpus = "1"
floppy0.present = "false"
floppy1.present = "false"
ethernet0.present = "true"
ethernet0.networkName = "br0"
ethernet0.connectionType = "bridged"
ethernet0.addressType = "static"
ethernet0.address = "aa:bb:cc:dd:ee:ff"
ethernet0.checkMACAddress = "false"
ethernet1.present = "true"
ethernet1.networkName = "br1"
ethernet1.connectionType = "bridged"
ethernet1.addressType = "static"
ethernet1.address = "00:0c:29:dd:ee:fe"
ethernet1.checkMACAddress = "false"
ethernet2.present = "true"
ethernet2.networkName = "br2"
ethernet2.connectionType = "bridged"
ethernet2.addressType = "static"
ethernet2.address = "aa:bb:cc:dd:ee:fd"
ethernet2.checkMACAddress = "false"

View File

@ -0,0 +1,29 @@
<domain type='vmware'>
<name>ethernet-mac-type</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='00:0c:29: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>

View File

@ -255,6 +255,7 @@ mymain(void)
DO_TEST("ethernet-static", "ethernet-static", 4);
DO_TEST("ethernet-vpx", "ethernet-vpx", 4);
DO_TEST("ethernet-other", "ethernet-other", 4);
DO_TEST("ethernet-mac-type", "ethernet-mac-type", 4);
DO_TEST("serial-file", "serial-file", 4);
DO_TEST("serial-device", "serial-device", 4);