diff --git a/src/domain_conf.c b/src/domain_conf.c index 0fd6cc8e75..fbe9d78f65 100644 --- a/src/domain_conf.c +++ b/src/domain_conf.c @@ -962,6 +962,7 @@ virDomainNetDefParseXML(virConnectPtr conn, char *internal = NULL; char *nic_name = NULL; char *hostnet_name = NULL; + char *devaddr = NULL; char *vlan = NULL; if (VIR_ALLOC(def) < 0) { @@ -1032,6 +1033,7 @@ virDomainNetDefParseXML(virConnectPtr conn, xmlStrEqual(cur->name, BAD_CAST "state")) { nic_name = virXMLPropString(cur, "nic"); hostnet_name = virXMLPropString(cur, "hostnet"); + devaddr = virXMLPropString(cur, "devaddr"); vlan = virXMLPropString(cur, "vlan"); } } @@ -1044,6 +1046,17 @@ virDomainNetDefParseXML(virConnectPtr conn, virCapabilitiesGenerateMac(caps, def->mac); } + if (devaddr && + sscanf(devaddr, "%x:%x:%x", + &def->pci_addr.domain, + &def->pci_addr.bus, + &def->pci_addr.slot) < 3) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Unable to parse devaddr parameter '%s'"), + devaddr); + goto error; + } + def->nic_name = nic_name; def->hostnet_name = hostnet_name; nic_name = hostnet_name = NULL; @@ -1176,6 +1189,7 @@ cleanup: VIR_FREE(internal); VIR_FREE(nic_name); VIR_FREE(hostnet_name); + VIR_FREE(devaddr); VIR_FREE(vlan); return def; @@ -3634,6 +3648,11 @@ virDomainNetDefFormat(virConnectPtr conn, virBufferEscapeString(buf, " nic='%s'", def->nic_name); if (def->hostnet_name) virBufferEscapeString(buf, " hostnet='%s'", def->hostnet_name); + if (virNetHasValidPciAddr(def)) + virBufferVSprintf(buf, " devaddr='%.4x:%.2x:%.2x'", + def->pci_addr.domain, + def->pci_addr.bus, + def->pci_addr.slot); if (def->vlan > 0) virBufferVSprintf(buf, " vlan='%d'", def->vlan); virBufferAddLit(buf, "/>\n"); diff --git a/src/domain_conf.h b/src/domain_conf.h index 2836b013f1..8dda78d807 100644 --- a/src/domain_conf.h +++ b/src/domain_conf.h @@ -192,9 +192,20 @@ struct _virDomainNetDef { char *ifname; char *nic_name; char *hostnet_name; + struct { + unsigned domain; + unsigned bus; + unsigned slot; + } pci_addr; int vlan; }; +static inline int +virNetHasValidPciAddr(virDomainNetDefPtr def) +{ + return def->pci_addr.domain || def->pci_addr.domain || def->pci_addr.slot; +} + enum virDomainChrSrcType { VIR_DOMAIN_CHR_TYPE_NULL, VIR_DOMAIN_CHR_TYPE_VC, diff --git a/src/qemu_driver.c b/src/qemu_driver.c index 642cec5210..7c245e8047 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -4551,6 +4551,7 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, virDomainNetDefPtr net = dev->data.net; char *cmd, *reply, *remove_cmd; int i; + unsigned domain, bus, slot; if (!(qemuCmdFlags & QEMUD_CMD_FLAG_HOST_NET_ADD)) { qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s", @@ -4622,10 +4623,22 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, goto try_remove; } - VIR_FREE(reply); VIR_FREE(cmd); + + if (qemudParsePciAddReply(vm, reply, &domain, &bus, &slot) < 0) { + qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + _("parsing pci_add reply failed: %s"), reply); + VIR_FREE(reply); + goto try_remove; + } + + VIR_FREE(reply); VIR_FREE(remove_cmd); + net->pci_addr.domain = domain; + net->pci_addr.bus = bus; + net->pci_addr.slot = slot; + vm->def->nets[vm->def->nnets++] = net; return 0;