]> xenbits.xensource.com Git - libvirt.git/commitdiff
conf: Parse more of our nodedev XML
authorMartin Kletzander <mkletzan@redhat.com>
Sun, 3 Apr 2016 19:01:06 +0000 (21:01 +0200)
committerMartin Kletzander <mkletzan@redhat.com>
Mon, 2 May 2016 13:46:23 +0000 (15:46 +0200)
We were lacking tests that are checking for the completeness of our
nodedev XMLs and also whether we output properly formatted ones.  This
patch adds parsing for the capability elements inside the <capability
type='pci'> element.  Also bunch of tests are added to show everything
works properly.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
src/conf/node_device_conf.c
tests/nodedevxml2xmltest.c

index 96ec6a0037147006bff9feb41ffc3cd21468004c..a06e4504285172d28b00c5c8548fc90f1c239d0c 100644 (file)
@@ -1268,6 +1268,91 @@ virPCIEDeviceInfoParseXML(xmlXPathContextPtr ctxt,
 }
 
 
+static int
+virNodeDevPCICapabilityParseXML(xmlXPathContextPtr ctxt,
+                                xmlNodePtr node,
+                                virNodeDevCapDataPtr data)
+{
+    char *maxFuncsStr = virXMLPropString(node, "maxCount");
+    char *type = virXMLPropString(node, "type");
+    xmlNodePtr *addresses = NULL;
+    xmlNodePtr orignode = ctxt->node;
+    int ret = -1;
+    size_t i = 0;
+
+    ctxt->node = node;
+
+    if (!type) {
+        virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing capability type"));
+        goto out;
+    }
+
+    if (STREQ(type, "phys_function")) {
+        xmlNodePtr address = virXPathNode("./address[1]", ctxt);
+
+        if (VIR_ALLOC(data->pci_dev.physical_function) < 0)
+            goto out;
+
+        data->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION;
+
+        if (!address) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("Missing address in 'phys_function' capability"));
+            goto out;
+        }
+
+        if (virPCIDeviceAddressParseXML(address,
+                                        data->pci_dev.physical_function) < 0)
+            goto out;
+    } else if (STREQ(type, "virt_functions")) {
+        int naddresses = virXPathNodeSet("./address", ctxt, &addresses);
+
+        if (maxFuncsStr &&
+            virStrToLong_uip(maxFuncsStr, NULL, 10,
+                             &data->pci_dev.max_virtual_functions) < 0) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("Malformed 'maxCount' parameter"));
+            goto out;
+        }
+
+        if (VIR_ALLOC_N(data->pci_dev.virtual_functions, naddresses) < 0)
+            goto out;
+
+        for (i = 0; i < naddresses; i++) {
+            virPCIDeviceAddressPtr addr = NULL;
+
+            if (VIR_ALLOC(addr) < 0)
+                goto out;
+
+            if (virPCIDeviceAddressParseXML(addresses[i], addr) < 0) {
+                VIR_FREE(addr);
+                goto out;
+            }
+
+            if (VIR_APPEND_ELEMENT(data->pci_dev.virtual_functions,
+                                   data->pci_dev.num_virtual_functions,
+                                   addr) < 0)
+                goto out;
+        }
+
+        data->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION;
+    } else {
+        int hdrType = virPCIHeaderTypeFromString(type);
+
+        if (hdrType > 0 && !data->pci_dev.hdrType)
+            data->pci_dev.hdrType = hdrType;
+    }
+
+    ret = 0;
+ out:
+    VIR_FREE(addresses);
+    VIR_FREE(maxFuncsStr);
+    VIR_FREE(type);
+    ctxt->node = orignode;
+    return ret;
+}
+
+
 static int
 virNodeDevCapPCIDevParseXML(xmlXPathContextPtr ctxt,
                             virNodeDeviceDefPtr def,
@@ -1275,9 +1360,12 @@ virNodeDevCapPCIDevParseXML(xmlXPathContextPtr ctxt,
                             virNodeDevCapDataPtr data)
 {
     xmlNodePtr orignode, iommuGroupNode, pciExpress;
+    xmlNodePtr *nodes = NULL;
+    int n = 0;
     int ret = -1;
     virPCIEDeviceInfoPtr pci_express = NULL;
     char *tmp = NULL;
+    size_t i = 0;
 
     orignode = ctxt->node;
     ctxt->node = node;
@@ -1321,6 +1409,15 @@ virNodeDevCapPCIDevParseXML(xmlXPathContextPtr ctxt,
     data->pci_dev.vendor_name  = virXPathString("string(./vendor[1])", ctxt);
     data->pci_dev.product_name = virXPathString("string(./product[1])", ctxt);
 
+    if ((n = virXPathNodeSet("./capability", ctxt, &nodes)) < 0)
+        goto out;
+
+    for (i = 0; i < n; i++) {
+        if (virNodeDevPCICapabilityParseXML(ctxt, nodes[i], data) < 0)
+            goto out;
+    }
+    VIR_FREE(nodes);
+
     if ((iommuGroupNode = virXPathNode("./iommuGroup[1]", ctxt))) {
         if (virNodeDevCapPCIDevIommuGroupParseXML(ctxt, iommuGroupNode,
                                                   data) < 0) {
@@ -1349,6 +1446,7 @@ virNodeDevCapPCIDevParseXML(xmlXPathContextPtr ctxt,
 
     ret = 0;
  out:
+    VIR_FREE(nodes);
     VIR_FREE(tmp);
     virPCIEDeviceInfoFree(pci_express);
     ctxt->node = orignode;
index 96041f50b9cd3025ea648ca280c6854649704c73..0ed06fdff3e21bb4e80b28371065cf1e4d6a0e2f 100644 (file)
@@ -91,7 +91,14 @@ mymain(void)
     DO_TEST("usb_device_1d6b_1_0000_00_1d_0");
     DO_TEST("pci_8086_4238_pcie_wireless");
     DO_TEST("pci_8086_0c0c_snd_hda_intel");
+    DO_TEST("pci_0000_00_02_0_header_type");
+    DO_TEST("pci_0000_00_1c_0_header_type");
     DO_TEST("scsi_target0_0_0");
+    DO_TEST("pci_0000_02_10_7_sriov");
+    DO_TEST("pci_0000_02_10_7_sriov_vfs");
+    DO_TEST("pci_0000_02_10_7_sriov_zero_vfs_max_count");
+    DO_TEST("pci_0000_02_10_7_sriov_pf_vfs_all");
+    DO_TEST("pci_0000_02_10_7_sriov_pf_vfs_all_header_type");
 
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }