]> xenbits.xensource.com Git - libvirt.git/commitdiff
Retain PCI address from NIC attach
authorMark McLoughlin <markmc@redhat.com>
Fri, 17 Jul 2009 21:08:34 +0000 (22:08 +0100)
committerMark McLoughlin <markmc@redhat.com>
Wed, 22 Jul 2009 10:34:07 +0000 (11:34 +0100)
When we pci_add a NIC, we need to retain the PCI address assigned by
qemu for using during detach.

* src/qemu_driver.c: use qemudParsePciAddReply() to pull the PCI
  address from the pci_add reply

* src/domain_conf.c: handle storing and parsing the PCI address in the
  domain state XML file

src/domain_conf.c
src/domain_conf.h
src/qemu_driver.c

index 0fd6cc8e75629bc8fd87bccb7dd4b22c96a714a3..fbe9d78f653ade9c978c6a130a8ccab0821ed8f3 100644 (file)
@@ -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");
index 2836b013f12127f6d73c9bddf68be00462192d97..8dda78d807035b3d199ed2e3ee7117cedf03811b 100644 (file)
@@ -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,
index 642cec5210ac21949f781bedee1566b33640e429..7c245e80478d6e18a02b02de6219d1a8f71f6940 100644 (file)
@@ -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;