[libvirt] [PATCH 5/5] conf: Parse more of our nodedev XML

Martin Kletzander mkletzan at redhat.com
Sun Apr 3 19:28:01 UTC 2016


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 at redhat.com>
---
 src/conf/node_device_conf.c | 98 +++++++++++++++++++++++++++++++++++++++++++++
 tests/nodedevxml2xmltest.c  |  7 ++++
 2 files changed, 105 insertions(+)

diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
index b6e2f82727d0..5a41f7e0d2cc 100644
--- a/src/conf/node_device_conf.c
+++ b/src/conf/node_device_conf.c
@@ -1269,15 +1269,103 @@ 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 (virDevicePCIAddressParseXML(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++) {
+            virDevicePCIAddressPtr addr = NULL;
+
+            if (VIR_ALLOC(addr) < 0)
+                goto out;
+
+            if (virDevicePCIAddressParseXML(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,
                             xmlNodePtr node,
                             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;
diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c
index 96041f50b9cd..0ed06fdff3e2 100644
--- a/tests/nodedevxml2xmltest.c
+++ b/tests/nodedevxml2xmltest.c
@@ -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;
 }
-- 
2.8.0




More information about the libvir-list mailing list