From e95b81c2fd62d700f697349964b8b2f63e44c64b Mon Sep 17 00:00:00 2001 From: Martin Kletzander Date: Fri, 1 Sep 2023 16:51:59 +0200 Subject: [PATCH] conf: Generate MAC address instead of keeping all zeroes When we parse we keep that in memory and pass it down to the hypervisor. However, that MAC address is not strictly valid as it is not marked as locally administered (bit 0x02) but it is not even globally unique. It is also used for loopback device on Linux, for example. And QEMU sees such MAC address just as "not specified" and generates a new one that libvirt does not even know about. So to make the overall experience better we now generate it if the supplied one is all clear. Resolves: https://issues.redhat.com/browse/RHEL-974 Signed-off-by: Martin Kletzander Reviewed-by: Michal Privoznik --- src/conf/domain_conf.c | 2 +- src/libvirt_private.syms | 1 + src/util/virmacaddr.c | 5 +++++ src/util/virmacaddr.h | 1 + .../network-interface-mac-clear.xml | 21 +++++++++++++++++++ .../network-interface-mac-clear.xml | 21 +++++++++++++++++++ tests/genericxml2xmltest.c | 4 +++- 7 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 tests/genericxml2xmlindata/network-interface-mac-clear.xml create mode 100644 tests/genericxml2xmloutdata/network-interface-mac-clear.xml diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index cac00c7f17..2c8727de54 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -9665,7 +9665,7 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt, return NULL; } - if (!macaddr) { + if (!macaddr || virMacAddrIsAllClear(&def->mac)) { virDomainNetGenerateMAC(xmlopt, &def->mac); def->mac_generated = true; } diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 1e3e407097..f8cda2f773 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2743,6 +2743,7 @@ virMacAddrCompare; virMacAddrFormat; virMacAddrGenerate; virMacAddrGetRaw; +virMacAddrIsAllClear; virMacAddrIsBroadcastRaw; virMacAddrIsMulticast; virMacAddrIsUnicast; diff --git a/src/util/virmacaddr.c b/src/util/virmacaddr.c index 073f298b5b..e06bb200fc 100644 --- a/src/util/virmacaddr.c +++ b/src/util/virmacaddr.c @@ -246,6 +246,11 @@ virMacAddrIsBroadcastRaw(const unsigned char s[VIR_MAC_BUFLEN]) return memcmp(virMacAddrBroadcastAddrRaw, s, sizeof(*s)) == 0; } +bool virMacAddrIsAllClear(const virMacAddr *addr) +{ + return !virMacAddrCmpRaw(addr, (const unsigned char[VIR_MAC_BUFLEN]){0}); +} + void virMacAddrFree(virMacAddr *addr) { diff --git a/src/util/virmacaddr.h b/src/util/virmacaddr.h index f32b58805a..7b9eb7443b 100644 --- a/src/util/virmacaddr.h +++ b/src/util/virmacaddr.h @@ -58,6 +58,7 @@ int virMacAddrParseHex(const char* str, bool virMacAddrIsUnicast(const virMacAddr *addr); bool virMacAddrIsMulticast(const virMacAddr *addr); bool virMacAddrIsBroadcastRaw(const unsigned char s[VIR_MAC_BUFLEN]); +bool virMacAddrIsAllClear(const virMacAddr *addr); void virMacAddrFree(virMacAddr *addr); G_DEFINE_AUTOPTR_CLEANUP_FUNC(virMacAddr, virMacAddrFree); diff --git a/tests/genericxml2xmlindata/network-interface-mac-clear.xml b/tests/genericxml2xmlindata/network-interface-mac-clear.xml new file mode 100644 index 0000000000..41beda8a79 --- /dev/null +++ b/tests/genericxml2xmlindata/network-interface-mac-clear.xml @@ -0,0 +1,21 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + + + + + + diff --git a/tests/genericxml2xmloutdata/network-interface-mac-clear.xml b/tests/genericxml2xmloutdata/network-interface-mac-clear.xml new file mode 100644 index 0000000000..a7935fa9f4 --- /dev/null +++ b/tests/genericxml2xmloutdata/network-interface-mac-clear.xml @@ -0,0 +1,21 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + + + + + + diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c index ce8073e85a..3cf9bd8159 100644 --- a/tests/genericxml2xmltest.c +++ b/tests/genericxml2xmltest.c @@ -187,6 +187,7 @@ mymain(void) DO_TEST("cpu-cache-disable"); DO_TEST("network-interface-mac-check"); + DO_TEST_DIFFERENT("network-interface-mac-clear"); DO_TEST_DIFFERENT("chardev-tcp"); DO_TEST_FAIL_ACTIVE("chardev-tcp-missing-host"); @@ -257,4 +258,5 @@ mymain(void) return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } -VIR_TEST_MAIN(mymain) +VIR_TEST_MAIN_PRELOAD(mymain, + VIR_TEST_MOCK("virrandom"))