]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Add a type attribute on the mac address element
authorBastien Orivel <bastien.orivel@diateam.net>
Mon, 13 Jul 2020 14:28:53 +0000 (16:28 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Mon, 13 Jul 2020 16:47:44 +0000 (18:47 +0200)
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>
docs/drvesx.html.in
docs/formatdomain.html.in
docs/schemas/domaincommon.rng
src/conf/domain_conf.c
src/conf/domain_conf.h
src/vmx/vmx.c
tests/xml2vmxdata/xml2vmx-ethernet-mac-type.vmx [new file with mode: 0644]
tests/xml2vmxdata/xml2vmx-ethernet-mac-type.xml [new file with mode: 0644]
tests/xml2vmxtest.c

index ac7bc645d149a0dfea287d5d70ae73714a4406e3..59b27bd43ed3f3d63d0e78ad925f93339753fcbf 100644 (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>
index 84eafe6cd20d305ddd2c94e4a188cf9c8ced884a..f5ee97de8163494af7eea22eb8dfa4ce9db201dc 100644 (file)
       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>
 
index 4b4aa60c66bb193b6b87bb5b840b9529c98e9b47..a810f569c6acf57742162ebd2ba4427c5ed8ac1c 100644 (file)
           <attribute name="address">
             <ref name="uniMacAddr"/>
           </attribute>
+          <optional>
+            <attribute name="type">
+              <choice>
+                <value>generated</value>
+                <value>static</value>
+              </choice>
+            </attribute>
+          </optional>
           <empty/>
         </element>
       </optional>
index d14485f18d1e0c1c3d8acf094328bc2ce8845f25..bcebfc633f960497ed814c639ef6923edc9a28ef 100644 (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
index 6a737591e2390e98b7b79a4389a311c1df53c432..241149af2489e2b39c6884dda2bd9506feb00921 100644 (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);
index d4d66f6768478b7e11a00400173fc290602c4ccf..97ec84446a95892b6be355b3fb2fff227da5f6d8 100644 (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",
diff --git a/tests/xml2vmxdata/xml2vmx-ethernet-mac-type.vmx b/tests/xml2vmxdata/xml2vmx-ethernet-mac-type.vmx
new file mode 100644 (file)
index 0000000..212b3f1
--- /dev/null
@@ -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"
diff --git a/tests/xml2vmxdata/xml2vmx-ethernet-mac-type.xml b/tests/xml2vmxdata/xml2vmx-ethernet-mac-type.xml
new file mode 100644 (file)
index 0000000..ee85a1a
--- /dev/null
@@ -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>
index 8f0a2a72a477fcea0627693c36f7df2e64b1ca89..b74fda29ef987c775e3c9ba2289310c6b02e9aaa 100644 (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);