(before anything else - you committed an unresolved merge conflict in qemu_command.h. You'll need to remove the extra ">>>>>>>>> blah" text.) Hopefully Eric can once again review the logic of the code that determines what bridges need to be auto-added, and assign PCI addresses to devices, since he was kind enough to review it last time :-) On 04/22/2013 02:43 PM, Ján Tomko wrote: > Add a "dry run" address allocation to figure out how many bridges > will be needed for all the devices without explicit addresses. > > Auto-add just enough bridges to put all the devices on, or up to the > bridge with the largest specified index. Ah, so then we don't need to warn about gaps in the index sequence. > --- > src/conf/domain_conf.c | 26 ++- > src/qemu/qemu_command.c | 211 +++++++++++++++++---- > src/qemu/qemu_command.h | 4 +- > tests/qemuxml2argvdata/qemuxml2argv-pci-bridge.xml | 210 ++++++++++++++++++++ > tests/qemuxml2xmltest.c | 1 + > 5 files changed, 411 insertions(+), 41 deletions(-) > create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-bridge.xml > > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index 5740009..800c0a7 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -2578,6 +2578,9 @@ virDomainDefPostParseInternal(virDomainDefPtr def, > virCapsPtr caps ATTRIBUTE_UNUSED) > { > int i; > + bool b; > + int ret = -1; > + virBitmapPtr bitmap = NULL; > > /* verify init path for container based domains */ > if (STREQ(def->os.type, "exe") && !def->os.init) { > @@ -2653,11 +2656,30 @@ virDomainDefPostParseInternal(virDomainDefPtr def, > } > } > > - return 0; > + /* Verify that PCI controller indexes are unique */ > + bitmap = virBitmapNew(def->ncontrollers); > + for (i = 0; i < def->ncontrollers; i++) { > + if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) { > + ignore_value(virBitmapGetBit(bitmap, def->controllers[i]->idx, &b)); > + if (b) { > + virReportError(VIR_ERR_XML_ERROR, > + _("Multiple PCI controllers with index %d"), > + def->controllers[i]->idx); > + goto cleanup; > + } > + ignore_value(virBitmapSetBit(bitmap, def->controllers[i]->idx)); > + } > + } > + ret = 0; > + > +cleanup: > + virBitmapFree(bitmap); > + > + return ret; I don't see where we do something like this for the other controller types. We should (separate patch though, of course :-) > > no_memory: > virReportOOMError(); > - return -1; > + goto cleanup; > } > > > diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c > index 3787ff1..ec7d0e6 100644 > --- a/src/qemu/qemu_command.c > +++ b/src/qemu/qemu_command.c > @@ -1197,6 +1197,8 @@ struct _qemuDomainPCIAddressSet { > qemuDomainPCIAddressBus *used; > virDevicePCIAddress lastaddr; > size_t nbuses; /* allocation of 'used' */ > + bool dryRun; /* on a dry run, new buses are auto-added > + and addresses aren't saved in device infos */ > }; > > > @@ -1216,9 +1218,10 @@ static bool qemuPCIAddressValidate(qemuDomainPCIAddressSetPtr addrs ATTRIBUTE_UN > _("Only PCI domain 0 is available")); > return false; > } > - if (addr->bus != 0) { > - virReportError(VIR_ERR_XML_ERROR, "%s", > - _("Only PCI bus 0 is available")); > + if (addr->bus >= addrs->nbuses) { > + virReportError(VIR_ERR_XML_ERROR, > + _("Only PCI buses up to %zu are available"), > + addrs->nbuses - 1); > return false; > } > if (addr->function >= QEMU_PCI_ADDRESS_FUNCTION_LAST) { > @@ -1233,9 +1236,46 @@ static bool qemuPCIAddressValidate(qemuDomainPCIAddressSetPtr addrs ATTRIBUTE_UN > QEMU_PCI_ADDRESS_SLOT_LAST); > return false; > } > + if (addr->slot == 0) { > + if (addr->bus) { > + virReportError(VIR_ERR_XML_ERROR, "%s", > + _("Slot 0 is unusable on PCI bridges")); > + return false; > + } else { > + virReportError(VIR_ERR_XML_ERROR, "%s", > + _("Slot 0 on bus 0 is reserved for the host bridge")); > + return false; > + } You can move the duplicated "return false;" out of the if and else, to a single occurrence. > + } > return true; > } > > +/* Ensure addr fits in the address set, by expanding it if needed. > + * Return value: > + * -1 = OOM > + * 0 = no action performed > + * >0 = number of buses added > + */ > +static int > +qemuDomainPCIAddressSetGrow(qemuDomainPCIAddressSetPtr addrs, > + virDevicePCIAddressPtr addr) > +{ > + int add, i; > + > + add = addr->bus - addrs->nbuses + 1; > + i = addrs->nbuses; > + if (add <= 0) > + return 0; > + if (VIR_EXPAND_N(addrs->used, addrs->nbuses, add) < 0) { > + virReportOOMError(); > + return -1; > + } > + /* reserve slot 0 on the new buses */ > + for (; i < addrs->nbuses; i++) > + addrs->used[i][0] = 0xFF; > + return add; > +} > + > > static char *qemuPCIAddressAsString(virDevicePCIAddressPtr addr) > { > @@ -1273,6 +1313,9 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, > return 0; > } > > + if (addrs->dryRun && qemuDomainPCIAddressSetGrow(addrs, addr) < 0) > + return -1; > + > if (!qemuPCIAddressValidate(addrs, addr)) > return -1; > > @@ -1326,15 +1369,54 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, > qemuDomainObjPrivatePtr priv = NULL; > > if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { > + int max_idx = 0; > int nbuses = 0; > int i; > + int rv; > > for (i = 0; i < def->ncontrollers; i++) { > - if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) > + if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) { > + if (def->controllers[i]->idx > max_idx) > + max_idx = def->controllers[i]->idx; > nbuses++; > + } > + } > + > + if (nbuses > 0 && max_idx >= nbuses) > + nbuses = max_idx + 1; > + > + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PCI_BRIDGE)) { > + virDomainDeviceInfo info; > + /* 1st pass to figure out how many PCI bridges we need */ > + if (!(addrs = qemuDomainPCIAddressSetCreate(def, nbuses, true))) > + goto cleanup; > + if (qemuAssignDevicePCISlots(def, qemuCaps, addrs) < 0) > + goto cleanup; > + /* Reserve 1 extra slot for a (potential) bridge */ > + if (qemuDomainPCIAddressSetNextAddr(addrs, &info) < 0) > + goto cleanup; > + > + for (i = 1; i < addrs->nbuses; i++) { > + if ((rv = virDomainDefMaybeAddController( > + def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, > + i, VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE)) < 0) > + goto cleanup; > + /* If we added a new bridge, we will need one more address */ > + if (rv > 0 && qemuDomainPCIAddressSetNextAddr(addrs, &info) < 0) > + goto cleanup; > + } > + nbuses = addrs->nbuses; > + qemuDomainPCIAddressSetFree(addrs); > + addrs = NULL; > + > + } else if (nbuses > 1) { > + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("PCI bridges are not supported " > + "by this QEMU binary")); > + goto cleanup; > } > > - if (!(addrs = qemuDomainPCIAddressSetCreate(def, nbuses))) > + if (!(addrs = qemuDomainPCIAddressSetCreate(def, nbuses, false))) > goto cleanup; > > if (qemuAssignDevicePCISlots(def, qemuCaps, addrs) < 0) > @@ -1380,7 +1462,8 @@ int qemuDomainAssignAddresses(virDomainDefPtr def, > } > > qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def, > - unsigned int nbuses) > + unsigned int nbuses, > + bool dryRun) > { > qemuDomainPCIAddressSetPtr addrs; > int i; > @@ -1392,6 +1475,7 @@ qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def, > goto no_memory; > > addrs->nbuses = nbuses; > + addrs->dryRun = dryRun; > > /* reserve slot 0 in every bus - it's used by the host bridge on bus 0 > * and unusable on PCI bridges */ > @@ -1424,6 +1508,9 @@ int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs, > { > char *str; > > + if (addrs->dryRun && qemuDomainPCIAddressSetGrow(addrs, addr) < 0) > + return -1; > + > if (!(str = qemuPCIAddressAsString(addr))) > return -1; > > @@ -1450,6 +1537,9 @@ int qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs, > { > char *str; > > + if (addrs->dryRun && qemuDomainPCIAddressSetGrow(addrs, addr) < 0) > + return -1; > + > if (!(str = qemuPCIAddressAsString(addr))) > return -1; > > @@ -1519,41 +1609,58 @@ void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs) > VIR_FREE(addrs); > } > > - > static int > qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs, > virDevicePCIAddressPtr next_addr) > { > - virDevicePCIAddress tmp_addr = addrs->lastaddr; > - int i; > - char *addr; > + virDevicePCIAddress a = addrs->lastaddr; > > - tmp_addr.slot++; > - for (i = 0; i < QEMU_PCI_ADDRESS_SLOT_LAST; i++, tmp_addr.slot++) { > - if (QEMU_PCI_ADDRESS_SLOT_LAST <= tmp_addr.slot) { > - tmp_addr.slot = 0; > - } > + if (addrs->nbuses == 0) { > + virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses available")); > + return -1; > + } > > - if (!(addr = qemuPCIAddressAsString(&tmp_addr))) > - return -1; > + /* Start the search at the last used bus and slot */ > + for (a.slot++; a.bus < addrs->nbuses; a.bus++) { > + for ( ; a.slot < QEMU_PCI_ADDRESS_SLOT_LAST; a.slot++) { > + if (!qemuDomainPCIAddressSlotInUse(addrs, &a)) > + goto success; > > - if (qemuDomainPCIAddressSlotInUse(addrs, &tmp_addr)) { > - VIR_DEBUG("PCI addr %s already in use", addr); > - VIR_FREE(addr); > - continue; > + VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use", > + a.domain, a.bus, a.slot); > } > + a.slot = 1; > + } > > - VIR_DEBUG("Found free PCI addr %s", addr); > - VIR_FREE(addr); > + /* There were no free slots after the last used one */ > + if (addrs->dryRun) { > + /* a is already set to the first new bus and slot 1 */ > + if (qemuDomainPCIAddressSetGrow(addrs, &a) < 0) > + return -1; > + goto success; > + } else { > + /* Check the buses from 0 up to the last used one */ > + for (a.bus = 0; a.bus <= addrs->lastaddr.bus; a.bus++) { > + for (a.slot = 1; a.slot < QEMU_PCI_ADDRESS_SLOT_LAST; a.slot++) { > + if (!qemuDomainPCIAddressSlotInUse(addrs, &a)) > + goto success; > > - addrs->lastaddr = tmp_addr; > - *next_addr = tmp_addr; > - return 0; > + VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use", > + a.domain, a.bus, a.slot); > + } > + > + } > } > > virReportError(VIR_ERR_INTERNAL_ERROR, > "%s", _("No more available PCI addresses")); > return -1; > + > +success: > + VIR_DEBUG("Found free PCI slot %.4x:%.2x:%.2x", > + a.domain, a.bus, a.slot); > + *next_addr = a; > + return 0; > } > > int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs, > @@ -1566,8 +1673,10 @@ int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs, > if (qemuDomainPCIAddressReserveSlot(addrs, &addr) < 0) > return -1; > > - dev->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; > - dev->addr.pci = addr; > + if (!addrs->dryRun) { > + dev->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; > + dev->addr.pci = addr; > + } > > addrs->lastaddr = addr; > return 0; > @@ -1741,6 +1850,18 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, > } > } > > + /* PCI controllers */ > + for (i = 0; i < def->ncontrollers; i++) { > + if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) { > + if (def->controllers[i]->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) > + continue; > + if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) > + continue; > + if (qemuDomainPCIAddressSetNextAddr(addrs, &def->controllers[i]->info) < 0) > + goto error; > + } > + } > + > for (i = 0; i < def->nfss ; i++) { > if (def->fss[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) > continue; > @@ -1780,9 +1901,10 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, > > /* Device controllers (SCSI, USB, but not IDE, FDC or CCID) */ > for (i = 0; i < def->ncontrollers ; i++) { > - /* PCI root has no address */ > + /* PCI controllers have been dealt with earlier */ > if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) > continue; > + > /* FDC lives behind the ISA bridge; CCID is a usb device */ > if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC || > def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_CCID) > @@ -1972,16 +2094,29 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, > } > } > > - /* XXX > - * When QEMU grows support for > 1 PCI bus, then pci.0 changes > - * to pci.1, pci.2, etc > - * When QEMU grows support for > 1 PCI domain, then pci.0 change > - * to pciNN.0 where NN is the domain number > + /* > + * PCI bridge support is required for multiple buses > + * 'pci.%u' is the ID of the bridge as specified in > + * qemuBuildControllerDevStr > + * > + * PCI_MULTIBUS capability indicates that the implicit > + * PCI bus is named 'pci.0' instead of 'pci'. > */ > - if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIBUS)) > - virBufferAsprintf(buf, ",bus=pci.0"); > - else > - virBufferAsprintf(buf, ",bus=pci"); > + if (info->addr.pci.bus != 0) { > + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PCI_BRIDGE)) { > + virBufferAsprintf(buf, ",bus=pci.%u", info->addr.pci.bus); > + } else { > + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("Multiple PCI buses are not supported " > + "with this QEMU binary")); > + return -1; > + } > + } else { > + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIBUS)) > + virBufferAsprintf(buf, ",bus=pci.0"); > + else > + virBufferAsprintf(buf, ",bus=pci"); > + } > if (info->addr.pci.multi == VIR_DEVICE_ADDRESS_PCI_MULTI_ON) > virBufferAddLit(buf, ",multifunction=on"); > else if (info->addr.pci.multi == VIR_DEVICE_ADDRESS_PCI_MULTI_OFF) > diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h > index b05510b..5d9ae72 100644 > --- a/src/qemu/qemu_command.h > +++ b/src/qemu/qemu_command.h > @@ -197,7 +197,9 @@ int qemuDomainAssignPCIAddresses(virDomainDefPtr def, > virQEMUCapsPtr qemuCaps, > virDomainObjPtr obj); > qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def, > - unsigned int nbuses); > + unsigned int nbuses, > + bool dryRun); > +>>>>>>> a3dcfa9... qemu: auto-add bridges and allow using them Oops. You've got an unresolved merge error! > int qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs, > virDevicePCIAddressPtr addr); > int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs, > diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-bridge.xml b/tests/qemuxml2argvdata/qemuxml2argv-pci-bridge.xml > new file mode 100644 > index 0000000..eb20328 > --- /dev/null > +++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-bridge.xml You should also do a test case where you haven't specified the bridges in the "xmlIn", but only in the "xmlOut". I *think* you should be able to do that by just putting the file that contains the bridges in qemuxml2xmloutdata, and calling the test with DO_TEST_DIFFERENT() in qemuxml2xmltest, AND omitting this test from qemuargv2xmltest. > @@ -0,0 +1,210 @@ > +<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-1.2'>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/libexec/qemu-kvm</emulator> > + <disk type='file' device='cdrom'> > + <driver name='qemu' type='raw'/> > + <source file='/var/iso/f18kde.iso'/> > + <target dev='hdc' bus='ide'/> > + <readonly/> > + <address type='drive' controller='0' bus='1' target='0' unit='0'/> > + </disk> > + <controller type='usb' index='0'> > + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> > + </controller> > + <controller type='ide' index='0'> > + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> > + </controller> > + <controller type='pci' index='0' model='pci-root'/> > + <controller type='pci' index='1' model='pci-bridge'/> > + <controller type='pci' index='2' model='pci-bridge'/> > + <interface type='network'> > + <mac address='52:54:00:f1:95:51'/> > + <source network='default'/> > + <model type='rtl8139'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:5c:c6:1a'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:39:97:ac'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:45:28:cb'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:ee:b9:a8'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:a9:f7:17'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:df:2b:f3'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:78:94:b4'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:6b:9b:06'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:17:df:bc'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:3b:d0:51'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:8d:2d:17'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:a7:66:af'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:54:ab:d7'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:1f:99:90'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:c8:43:87'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:df:22:b2'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:d2:9a:47'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:86:05:e2'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:8c:1c:c2'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:48:58:92'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:99:e5:bf'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:b1:8c:25'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:60:e0:d0'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:37:00:6a'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:c7:c8:ad'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:4e:a7:cf'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:00:79:69'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:47:00:6f'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:2a:8c:8b'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:ec:d5:e3'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <interface type='network'> > + <mac address='52:54:00:7e:6e:c8'/> > + <source network='default'/> > + <model type='e1000'/> > + </interface> > + <input type='mouse' bus='ps2'/> > + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us'> > + <listen type='address' address='127.0.0.1'/> > + </graphics> > + <video> > + <model type='cirrus' vram='9216' heads='1'/> > + <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 7434190..04b14df 100644 > --- a/tests/qemuxml2xmltest.c > +++ b/tests/qemuxml2xmltest.c > @@ -276,6 +276,7 @@ mymain(void) > DO_TEST_DIFFERENT("metadata"); > > DO_TEST("tpm-passthrough"); > + DO_TEST("pci-bridge"); > > virObjectUnref(driver.caps); > virObjectUnref(driver.xmlopt); What about qemuxml2argvtest.c? (which means you also need a .args file.) -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list