[libvirt PATCH v2 0/5] qemu: support stable NIC device naming

With this series applied it is possible to get stable NIC device naming in combination with QEMU >= 6.0.0 (release imminent), by setting the ACPI device index against NICs. <acpi index="NNN"/> The index is an unique integer that can be assigned to any PCI/PCIe device. systemd uses this value for its stable NIC naming scheme. If not present, then it falls back to an SMBIOS device index, but QEMU doesn't support that concept. Note that although this is only known to be useful for NICs, the ACPI feature is conceptually available for any PCI device, and so libvirt doesn't restrict the usage to only NICs. Tested with current QEMU git master, and Fedora 30 guest. It works with i440fx, but fails with Q35. The latter problem is reported to qemu-devel and awaiting response. <interface type="network"> <mac address="52:54:00:c3:d3:ef" /> <source network="default" portid="c2361e1b-3ebf-484e-813e-9ee8e2b760c7" bridge="virbr0" /> <target dev="vnet6" /> <model type="virtio" /> <alias name="net0" /> <acpi index="103" /> <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x0" /> </interface> <interface type="network"> <mac address="52:54:00:98:22:a6" /> <source network="default" portid="e6cdb3da-ca24-42fa-973e-8cdb92fcad3f" bridge="virbr0" /> <target dev="vnet7" /> <model type="virtio" /> <alias name="net1" /> <acpi index="113" /> <address type="pci" domain="0x0000" bus="0x00" slot="0x0a" function="0x0" /> </interface> <interface type="network"> <mac address="52:54:00:42:00:bc" /> <source network="default" portid="10efeab4-f59c-4ef7-90a3-32b3895080b7" bridge="virbr0" /> <target dev="vnet8" /> <model type="virtio" /> <alias name="net2" /> <acpi index="123" /> <address type="pci" domain="0x0000" bus="0x00" slot="0x0b" function="0x0" /> </interface> <interface type="network"> <mac address="52:54:00:36:8e:5a" /> <source network="default" portid="fb016189-d764-41b2-b256-f5783ade3726" bridge="virbr0" /> <target dev="vnet9" /> <model type="virtio" /> <alias name="net3" /> <acpi index="133" /> <address type="pci" domain="0x0000" bus="0x00" slot="0x0c" function="0x0" /> </interface> Name MAC address Protocol Address ------------------------------------------------------------------------------- vnet6 52:54:00:c3:d3:ef ipv4 192.168.122.61/24 vnet7 52:54:00:98:22:a6 ipv4 192.168.122.69/24 vnet8 52:54:00:42:00:bc ipv4 192.168.122.17/24 vnet9 52:54:00:36:8e:5a ipv4 192.168.122.13/24 $ ip -4 addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 2: eno103: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 inet 192.168.122.61/24 brd 192.168.122.255 scope global dynamic noprefixroute eno103 valid_lft 2987sec preferred_lft 2987sec 3: eno113: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 inet 192.168.122.69/24 brd 192.168.122.255 scope global dynamic noprefixroute eno113 valid_lft 2987sec preferred_lft 2987sec 4: eno123: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 inet 192.168.122.17/24 brd 192.168.122.255 scope global dynamic noprefixroute eno123 valid_lft 2987sec preferred_lft 2987sec 5: eno133: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 inet 192.168.122.13/24 brd 192.168.122.255 scope global dynamic noprefixroute eno133 valid_lft 2988sec preferred_lft 2988sec Changed in v2: - Fix typos - Document limits / uniqueness - Drop caps refresh - Add xml2xml test Daniel P. Berrangé (5): conf: add support for <acpi index='NNN'/> for PCI devices qemu: fix indentation off-by-1 qemu: use a switch when building device addresses qemu: probe for "acpi-index" property qemu: wire up command line support for ACPI index docs/formatdomain.rst | 7 ++ docs/schemas/domaincommon.rng | 73 +++++++++++++++++++ src/conf/device_conf.h | 3 + src/conf/domain_conf.c | 19 +++++ src/qemu/qemu_capabilities.c | 6 ++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 42 +++++++++-- src/qemu/qemu_validate.c | 35 +++++++++ .../caps_6.0.0.x86_64.xml | 1 + .../devices-acpi-index.x86_64-latest.args | 57 +++++++++++++++ tests/qemuxml2argvdata/devices-acpi-index.xml | 62 ++++++++++++++++ tests/qemuxml2argvtest.c | 2 + .../devices-acpi-index.x86_64-latest.xml | 73 +++++++++++++++++++ tests/qemuxml2xmltest.c | 2 + 14 files changed, 376 insertions(+), 7 deletions(-) create mode 100644 tests/qemuxml2argvdata/devices-acpi-index.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/devices-acpi-index.xml create mode 100644 tests/qemuxml2xmloutdata/devices-acpi-index.x86_64-latest.xml -- 2.30.2

PCI devices can be associated with a unique integer index that is exposed via ACPI. In Linux OS with systemd, this value is used for provide a NIC device naming scheme that is stable across changes in PCI slot configuration. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- docs/formatdomain.rst | 7 ++++ docs/schemas/domaincommon.rng | 73 +++++++++++++++++++++++++++++++++++ src/conf/device_conf.h | 3 ++ src/conf/domain_conf.c | 19 +++++++++ 4 files changed, 102 insertions(+) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 782ebc8564..29d2e02da1 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -4363,6 +4363,7 @@ Network interfaces <mac address='52:54:00:5d:c7:9e'/> <boot order='1'/> <rom bar='off'/> + <acpi index='4'/> </interface> </devices> ... @@ -4389,6 +4390,12 @@ when it's in the reserved VMware range by adding a ``type="static"`` attribute to the ``<mac/>`` element. Note that this attribute is useless if the provided MAC address is outside of the reserved VMWare ranges. +:since:`Since 7.3.0`, one can set the ACPI index against network interfaces. +With some operating systems (eg Linux with systemd), the ACPI index is used +to provide network interface device naming, that is stable across changes +in PCI addresses assigned to the device. This value is required to be unique +across all devices and be between 1 and (16*1024-1). + :anchor:`<a id="elementsNICSVirtual"/>` Virtual network diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 73ce253821..99cd873832 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1444,6 +1444,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> @@ -2435,6 +2438,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> @@ -2863,6 +2869,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> @@ -3520,6 +3529,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> @@ -4146,6 +4158,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> @@ -4286,6 +4301,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> @@ -4538,6 +4556,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> @@ -4942,6 +4963,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> @@ -5011,6 +5035,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> @@ -5043,6 +5070,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> @@ -5121,6 +5151,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> @@ -5165,6 +5198,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> @@ -5192,6 +5228,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> @@ -5287,6 +5326,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <element name="driver"> <ref name="virtioOptions"/> @@ -5389,6 +5431,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> @@ -5404,6 +5449,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> @@ -5423,6 +5471,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> @@ -5454,6 +5505,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="deviceBoot"/> </optional> @@ -6425,6 +6479,16 @@ </element> </define> + <define name="acpi"> + <element name="acpi"> + <optional> + <attribute name="index"> + <ref name="unsignedInt"/> + </attribute> + </optional> + </element> + </define> + <define name="memorydev"> <element name="memory"> <attribute name="model"> @@ -6463,6 +6527,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> </interleave> </element> </define> @@ -6554,6 +6621,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> @@ -7546,6 +7616,9 @@ <optional> <ref name="alias"/> </optional> + <optional> + <ref name="acpi"/> + </optional> <optional> <ref name="address"/> </optional> diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h index a51bdf10ee..af9a43bff2 100644 --- a/src/conf/device_conf.h +++ b/src/conf/device_conf.h @@ -159,6 +159,9 @@ struct _virDomainDeviceInfo { /* bootIndex is only used for disk, network interface, hostdev * and redirdev devices */ unsigned int bootIndex; + /* Valid for any PCI device. Can be used for NIC to get + * stable numbering in Linux */ + unsigned int acpiIndex; /* pciConnectFlags is only used internally during address * assignment, never saved and never reported. diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index f93af0a85c..83415f9271 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -6335,6 +6335,9 @@ virDomainDeviceInfoFormat(virBufferPtr buf, virBufferAddLit(buf, "/>\n"); } + if (info->acpiIndex != 0) + virBufferAsprintf(buf, "<acpi index='%u'/>\n", info->acpiIndex); + if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE || info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) /* We're done here */ @@ -6661,6 +6664,7 @@ virDomainDeviceInfoParseXML(virDomainXMLOptionPtr xmlopt, g_autofree char *romenabled = NULL; g_autofree char *rombar = NULL; g_autofree char *aliasStr = NULL; + g_autofree char *acpiIndex = NULL; VIR_XPATH_NODE_AUTORESTORE(ctxt) virDomainDeviceInfoClear(info); @@ -6709,6 +6713,14 @@ virDomainDeviceInfoParseXML(virDomainXMLOptionPtr xmlopt, } } + acpiIndex = virXPathString("string(./acpi/@index)", ctxt); + if (acpiIndex && + virStrToLong_ui(acpiIndex, NULL, 10, &info->acpiIndex) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Cannot parse ACPI index value '%s'"), acpiIndex); + goto cleanup; + } + if ((address = virXPathNode("./address", ctxt)) && virDomainDeviceAddressParseXML(address, info) < 0) goto cleanup; @@ -22193,6 +22205,13 @@ virDomainDeviceInfoCheckABIStability(virDomainDeviceInfoPtr src, break; } + if (src->acpiIndex != dst->acpiIndex) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target ACPI index '%u' does not match source '%u'"), + dst->acpiIndex, src->acpiIndex); + return false; + } + return true; } -- 2.30.2

Reviewed-by: Peter Krempa <pkrempa@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 7cb07306f3..20fba45780 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -418,7 +418,7 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, virBufferAddLit(buf, ",multifunction=off"); virBufferAsprintf(buf, ",addr=0x%x", info->addr.pci.slot); if (info->addr.pci.function != 0) - virBufferAsprintf(buf, ".0x%x", info->addr.pci.function); + virBufferAsprintf(buf, ".0x%x", info->addr.pci.function); } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) { if (!(contAlias = virDomainControllerAliasFind(domainDef, VIR_DOMAIN_CONTROLLER_TYPE_USB, -- 2.30.2

The compiler can more easily optimize a switch, and more importantly can also warn when new address types are added which are not handled. Reviewed-by: Peter Krempa <pkrempa@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_command.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 20fba45780..02f9d16f63 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -351,7 +351,8 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, bool contIsPHB = false; int contTargetIndex = 0; - if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { + switch ((virDomainDeviceAddressType)info->type) { + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI: { size_t i; if (!(devStr = virPCIDeviceAddressAsString(&info->addr.pci))) @@ -419,7 +420,10 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, virBufferAsprintf(buf, ",addr=0x%x", info->addr.pci.slot); if (info->addr.pci.function != 0) virBufferAsprintf(buf, ".0x%x", info->addr.pci.function); - } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) { + } + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB: if (!(contAlias = virDomainControllerAliasFind(domainDef, VIR_DOMAIN_CONTROLLER_TYPE_USB, info->addr.usb.bus))) @@ -429,23 +433,45 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, virBufferAddLit(buf, ",port="); virDomainUSBAddressPortFormatBuf(buf, info->addr.usb.port); } - } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO) { + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO: if (info->addr.spaprvio.has_reg) virBufferAsprintf(buf, ",reg=0x%08llx", info->addr.spaprvio.reg); - } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW: if (info->addr.ccw.assigned) virBufferAsprintf(buf, ",devno=%x.%x.%04x", info->addr.ccw.cssid, info->addr.ccw.ssid, info->addr.ccw.devno); - } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA) { + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA: virBufferAsprintf(buf, ",iobase=0x%x,irq=0x%x", info->addr.isa.iobase, info->addr.isa.irq); - } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM) { + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM: virBufferAsprintf(buf, ",slot=%d", info->addr.dimm.slot); if (info->addr.dimm.base) virBufferAsprintf(buf, ",addr=%llu", info->addr.dimm.base); + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE: + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE: + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL: + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID: + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390: + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO: + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED: + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST: + virReportEnumRangeError(virDomainDeviceAddressType, info->type); + return -1; } return 0; -- 2.30.2

This property is exposed by QEMU on any PCI device, but we have to pick some specific device(s) to probe it against. We expect that at least one of the virtio devices will be present, so probe against them. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_capabilities.c | 6 ++++++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml | 1 + 3 files changed, 8 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 41ef199a79..37ed750f8b 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -628,6 +628,7 @@ VIR_ENUM_IMPL(virQEMUCaps, /* 400 */ "compat-deprecated", + "acpi-index", ); @@ -1366,6 +1367,7 @@ static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsVirtioBalloon[] { "ats", QEMU_CAPS_VIRTIO_PCI_ATS, NULL }, { "packed", QEMU_CAPS_VIRTIO_PACKED_QUEUES, NULL }, { "free-page-reporting", QEMU_CAPS_VIRTIO_BALLOON_FREE_PAGE_REPORTING, NULL }, + { "acpi-index", QEMU_CAPS_ACPI_INDEX, NULL }, }; @@ -1398,6 +1400,7 @@ static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsVirtioBlk[] = { { "write-cache", QEMU_CAPS_DISK_WRITE_CACHE, NULL }, { "werror", QEMU_CAPS_STORAGE_WERROR, NULL }, { "packed", QEMU_CAPS_VIRTIO_PACKED_QUEUES, NULL }, + { "acpi-index", QEMU_CAPS_ACPI_INDEX, NULL }, }; static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsVirtioNet[] = { @@ -1411,6 +1414,7 @@ static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsVirtioNet[] = { { "ats", QEMU_CAPS_VIRTIO_PCI_ATS, NULL }, { "failover", QEMU_CAPS_VIRTIO_NET_FAILOVER, NULL }, { "packed", QEMU_CAPS_VIRTIO_PACKED_QUEUES, NULL }, + { "acpi-index", QEMU_CAPS_ACPI_INDEX, NULL }, }; static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsPCIeRootPort[] = { @@ -1431,6 +1435,7 @@ static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsVirtioSCSI[] = { { "iommu_platform", QEMU_CAPS_VIRTIO_PCI_IOMMU_PLATFORM, NULL }, { "ats", QEMU_CAPS_VIRTIO_PCI_ATS, NULL }, { "packed", QEMU_CAPS_VIRTIO_PACKED_QUEUES, NULL }, + { "acpi-index", QEMU_CAPS_ACPI_INDEX, NULL }, }; static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsVfioPCI[] = { @@ -1502,6 +1507,7 @@ static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsVirtioGpu[] = { { "iommu_platform", QEMU_CAPS_VIRTIO_PCI_IOMMU_PLATFORM, NULL }, { "ats", QEMU_CAPS_VIRTIO_PCI_ATS, NULL }, { "packed", QEMU_CAPS_VIRTIO_PACKED_QUEUES, NULL }, + { "acpi-index", QEMU_CAPS_ACPI_INDEX, NULL }, }; static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsICH9[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index c553a5f4a4..1ca9c1ea7b 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -608,6 +608,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ /* 400 */ QEMU_CAPS_COMPAT_DEPRECATED, /* -compat deprecated-(input|output) is supported */ + QEMU_CAPS_ACPI_INDEX, /* PCI device 'acpi-index' property */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml index 8d12645a8e..8cc949d735 100644 --- a/tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml @@ -262,6 +262,7 @@ <flag name='object.qapified'/> <flag name='rotation-rate'/> <flag name='compat-deprecated'/> + <flag name='acpi-index'/> <version>5002092</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100242</microcodeVersion> -- 2.30.2

This makes it possible to enable stable NIC device names in most modern Linux distros. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/qemu/qemu_command.c | 2 + src/qemu/qemu_validate.c | 35 +++++++++ .../devices-acpi-index.x86_64-latest.args | 57 +++++++++++++++ tests/qemuxml2argvdata/devices-acpi-index.xml | 62 ++++++++++++++++ tests/qemuxml2argvtest.c | 2 + .../devices-acpi-index.x86_64-latest.xml | 73 +++++++++++++++++++ tests/qemuxml2xmltest.c | 2 + 7 files changed, 233 insertions(+) create mode 100644 tests/qemuxml2argvdata/devices-acpi-index.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/devices-acpi-index.xml create mode 100644 tests/qemuxml2xmloutdata/devices-acpi-index.x86_64-latest.xml diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 02f9d16f63..45eb0dc976 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -420,6 +420,8 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, virBufferAsprintf(buf, ",addr=0x%x", info->addr.pci.slot); if (info->addr.pci.function != 0) virBufferAsprintf(buf, ".0x%x", info->addr.pci.function); + if (info->acpiIndex != 0) + virBufferAsprintf(buf, ",acpi-index=%u", info->acpiIndex); } break; diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 09778085a8..27afcab9aa 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -1069,6 +1069,32 @@ qemuValidateDomainDefPanic(const virDomainDef *def, } +static int +qemuValidateDomainDeviceInfo(virDomainDefPtr def G_GNUC_UNUSED, + virDomainDeviceDefPtr dev G_GNUC_UNUSED, + virDomainDeviceInfoPtr info, + void *opaque) +{ + virQEMUCapsPtr qemuCaps = opaque; + + if (info->acpiIndex) { + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_ACPI_INDEX)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("ACPI index is not supported with this QEMU")); + return -1; + } + + if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && + info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("ACPI index is only supported for PCI devices")); + return -1; + } + } + + return 0; +} + int qemuValidateDomainDef(const virDomainDef *def, void *opaque, @@ -1235,6 +1261,15 @@ qemuValidateDomainDef(const virDomainDef *def, return -1; } + /* Explicitly discarding 'const' from 'def' is ok because + * we know our callback qemuValidateDomainDeviceInfo will + * not modify it + */ + if (virDomainDeviceInfoIterate((virDomainDefPtr)def, + qemuValidateDomainDeviceInfo, + qemuCaps) < 0) + return -1; + return 0; } diff --git a/tests/qemuxml2argvdata/devices-acpi-index.x86_64-latest.args b/tests/qemuxml2argvdata/devices-acpi-index.x86_64-latest.args new file mode 100644 index 0000000000..07a8b0d189 --- /dev/null +++ b/tests/qemuxml2argvdata/devices-acpi-index.x86_64-latest.args @@ -0,0 +1,57 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-fdr-br \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-fdr-br/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-fdr-br/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-fdr-br/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=fdr-br,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw",\ +"file":"/tmp/lib/domain--1-fdr-br/master-key.aes"}' \ +-machine pc-i440fx-5.0,accel=tcg,usb=off,dump-guest-core=off,\ +memory-backend=pc.ram \ +-cpu qemu64 \ +-m 2048 \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":2147483648}' \ +-overcommit mem-lock=off \ +-smp 2,sockets=2,cores=1,threads=1 \ +-uuid 3ec6cbe1-b5a2-4515-b800-31a61855df41 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \ +-blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/test.img",\ +"node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-2-format","read-only":false,"driver":"raw",\ +"file":"libvirt-2-storage"}' \ +-device virtio-blk-pci,bus=pci.0,addr=0x3,acpi-index=1,drive=libvirt-2-format,\ +id=virtio-disk0,bootindex=1 \ +-blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/test1.img",\ +"node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw",\ +"file":"libvirt-1-storage"}' \ +-device virtio-blk-pci,bus=pci.0,addr=0x4,acpi-index=42,drive=libvirt-1-format,\ +id=virtio-disk1 \ +-netdev user,id=hostnet0 \ +-device virtio-net-pci,netdev=hostnet0,id=net0,mac=00:11:22:33:44:55,bus=pci.0,\ +addr=0x5,acpi-index=100 \ +-netdev user,id=hostnet1 \ +-device virtio-net-pci,netdev=hostnet1,id=net1,mac=00:11:22:33:44:55,bus=pci.0,\ +addr=0x7,acpi-index=200 \ +-netdev user,id=hostnet2 \ +-device virtio-net-pci,netdev=hostnet2,id=net2,mac=00:11:22:33:44:55,bus=pci.0,\ +addr=0x8,acpi-index=300 \ +-audiodev id=audio1,driver=none \ +-device cirrus-vga,id=video0,bus=pci.0,addr=0x2,acpi-index=1729 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6 \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\ +resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/devices-acpi-index.xml b/tests/qemuxml2argvdata/devices-acpi-index.xml new file mode 100644 index 0000000000..5d0176e7fe --- /dev/null +++ b/tests/qemuxml2argvdata/devices-acpi-index.xml @@ -0,0 +1,62 @@ +<domain type='qemu'> + <name>fdr-br</name> + <uuid>3ec6cbe1-b5a2-4515-b800-31a61855df41</uuid> + <memory unit='KiB'>2097152</memory> + <currentMemory unit='KiB'>2097152</currentMemory> + <vcpu placement='static' cpuset='0-1'>2</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-5.0'>hvm</type> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/var/lib/libvirt/images/test.img'/> + <target dev='vda' bus='virtio'/> + <acpi index='1'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/var/lib/libvirt/images/test1.img'/> + <target dev='vdb' bus='virtio'/> + <acpi index='42'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </disk> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <acpi index='100'/> + <model type='virtio'/> + </interface> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <acpi index='200'/> + <model type='virtio'/> + </interface> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <acpi index='300'/> + <model type='virtio'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <video> + <model type='cirrus' vram='16384' heads='1'/> + <acpi index='1729'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index ea98f0e6a8..83dd6a7756 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -3611,6 +3611,8 @@ mymain(void) DO_TEST_CAPS_LATEST("virtio-9p-multidevs"); DO_TEST_CAPS_LATEST("virtio-9p-createmode"); + DO_TEST_CAPS_LATEST("devices-acpi-index"); + if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL) virFileDeleteTree(fakerootdir); diff --git a/tests/qemuxml2xmloutdata/devices-acpi-index.x86_64-latest.xml b/tests/qemuxml2xmloutdata/devices-acpi-index.x86_64-latest.xml new file mode 100644 index 0000000000..3c6b384e8a --- /dev/null +++ b/tests/qemuxml2xmloutdata/devices-acpi-index.x86_64-latest.xml @@ -0,0 +1,73 @@ +<domain type='qemu'> + <name>fdr-br</name> + <uuid>3ec6cbe1-b5a2-4515-b800-31a61855df41</uuid> + <memory unit='KiB'>2097152</memory> + <currentMemory unit='KiB'>2097152</currentMemory> + <vcpu placement='static' cpuset='0-1'>2</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-5.0'>hvm</type> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/var/lib/libvirt/images/test.img'/> + <target dev='vda' bus='virtio'/> + <acpi index='1'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/var/lib/libvirt/images/test1.img'/> + <target dev='vdb' bus='virtio'/> + <acpi index='42'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </disk> + <controller type='usb' index='0' model='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <model type='virtio'/> + <acpi index='100'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </interface> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <model type='virtio'/> + <acpi index='200'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> + </interface> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <model type='virtio'/> + <acpi index='300'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <video> + <model type='cirrus' vram='16384' heads='1' primary='yes'/> + <acpi index='1729'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index c92e1dd0cf..70a4a57df1 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -1522,6 +1522,8 @@ mymain(void) driver.config->nogfxAllowHostAudio = false; g_unsetenv("QEMU_AUDIO_DRV"); + DO_TEST_CAPS_LATEST("devices-acpi-index"); + cleanup: if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL) virFileDeleteTree(fakerootdir); -- 2.30.2

On Wed, Apr 07, 2021 at 17:24:35 +0100, Daniel Berrange wrote: [...]
Daniel P. Berrangé (5): conf: add support for <acpi index='NNN'/> for PCI devices qemu: fix indentation off-by-1 qemu: use a switch when building device addresses qemu: probe for "acpi-index" property qemu: wire up command line support for ACPI index
docs/formatdomain.rst | 7 ++ docs/schemas/domaincommon.rng | 73 +++++++++++++++++++ src/conf/device_conf.h | 3 + src/conf/domain_conf.c | 19 +++++ src/qemu/qemu_capabilities.c | 6 ++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 42 +++++++++-- src/qemu/qemu_validate.c | 35 +++++++++ .../caps_6.0.0.x86_64.xml | 1 + .../devices-acpi-index.x86_64-latest.args | 57 +++++++++++++++ tests/qemuxml2argvdata/devices-acpi-index.xml | 62 ++++++++++++++++ tests/qemuxml2argvtest.c | 2 + .../devices-acpi-index.x86_64-latest.xml | 73 +++++++++++++++++++ tests/qemuxml2xmltest.c | 2 + 14 files changed, 376 insertions(+), 7 deletions(-) create mode 100644 tests/qemuxml2argvdata/devices-acpi-index.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/devices-acpi-index.xml create mode 100644 tests/qemuxml2xmloutdata/devices-acpi-index.x86_64-latest.xml
Series: Reviewed-by: Peter Krempa <pkrempa@redhat.com>
participants (2)
-
Daniel P. Berrangé
-
Peter Krempa