Forgot to add `-s` when using `git publish` so "Signed-off-by" is missing - my apologies about that. Will add it in v5 if there will be a need for it.

Best Regards,
Dmitrii Shcherbakov
LP/MM/oftc: dmitriis


On Wed, Sep 22, 2021 at 5:23 PM Dmitrii Shcherbakov <dmitrii.shcherbakov@canonical.com> wrote:
Add support for deserializing the binary PCI/PCIe VPD format and
exposing VPD resources as XML elements in a new nested capability
of PCI/PCIe devices called 'vpd'.

The series contains the following incremental changes:

* The PCI VPD parser module, in-memory resource representation
  and tests;
* VPD-related helpers added to the virpci module;
* VPD capability support: XML serialization/deserialization from/into
  VPD resource data structures;
* Documentation.

The VPD format is specified in "I.3. VPD Definitions" in PCI specs
(2.2+) and "6.28.1 VPD Format" PCIe 4.0. As section 6.28 in PCIe 4.0
notes, the PCI Local Bus and PCIe VPD formats are binary compatible
and PCIe 4.0 merely started incorporating what was already present in
PCI specs.

Linux kernel exposes a binary blob in the VPD format via sysfs since
v2.6.26 (commit 94e6108803469a37ee1e3c92dafdd1d59298602f) which requires
a parser to interpret.

There are usage scenarios where information such as the board serial
number needs to be retrieved from PCI(e) VPD. Projects like Nova can
utilize this information for cases which involve virtual interface
plugging on SmartNIC DPUs but there may be other scenarios and types of
information useful to retrieve from VPD. The fact that the format is
binary requires proper parsing instead of substring searching hence the
full parser is proposed. Likewise, checksum validation requires proper
parsing as well.

A usage example is present here:
https://review.opendev.org/c/openstack/nova/+/808199

The patch follows a prior discussion on the mailing list which has
additional context about the use-case but a narrower proposal:

https://listman.redhat.com/archives/libvir-list/2021-May/msg00873.html
https://www.mail-archive.com/libvir-list@redhat.com/msg218165.html

The new functionality is mostly contained in virpcivpd with a
couple of new functions added to virpci. Additionally, the necessary XML
serialization/deserialization and glue code is added to expose the VPD
capability to external clients as XML.

A new capability flag is added along with a new capability in order to
allow for filtering of PCI devices with the VPD capability using virsh:

virsh nodedev-list --cap vpd
sudo virsh nodedev-dumpxml --device pci_dddd_bb_ss_f

In this example having the root uid is required in order to access the
vpd sysfs entry, therefore, the nodedev XML output will only contain
the VPD capability if virsh is run as root.

The capability is treated as dynamic due to the presence of read-write
sections in the VPD format per PCI/PCIe specs (the idea being that
read-write resource fields may potentially be altered by the DPU OS
over time independently from the host OS).

Unit tests cover the parser functionality (including many possible
invalid cases), in-memory representation as well as XML serialization
and deserialization.

Manual functional testing was performed with 2 DPUs and several other
NIC models which expose PCI(e) VPD. Testing have also been performed
for devices that do not have VPD or those that expose a VPD capability
but exhibit invalid behavior (I/O errors while reading a sysfs entry).

Per the existing guidelines, the implementation relies heavily on glib
for various purposes.

https://libvirt.org/glib-adoption.html

The v4 of the patch includes a number of fixes compared to v3:

* Fixed the patch to correctly build against older glib (2.56.0);
  * Notably, glib commit 86c073dba9d82ef3f1bc3d3116b058b9b5c3b1eb (in
          2.59.0) fixes g_autolist support for derivable Glib types. To make
          things work in 2.56.0 a workaround is conditionally applied;
        * virCreateAnonymousFile now uses a temporary file which is
          unlinked after creation instead of memfd because OpenSUSE 15.2 does
                not have support memfd;
* Keyword resources now use GTree instead of GHashTable as the
  underlying data structure:
  * This allows for stable ordering which is important for XML2XML tests
          as they were failing with when GLib versions were different,
                resulting in a different ordering of elements;
        * The keyword resource iteration function was complex and got replaced
          by a simpler g_tree_foreach-based approach;
* Added more testing: functions added to virpci are now assessed by
  creating a mocked vpd file under a mocked sysfs structure while the
        parser is still tested in virpcivpdtest file;
* Refactoring:
  * Applied changes based on the indent tool operation with some
          post-processing;
        * Renamed functions which had the Glib naming style to use camel case
          where possible. Auto-generated declarations are an exception:
                gobject/gtype.h defines type_name##_init, type_name##_class_init,
                module_obj_name##_get_type functions which were left unchanged;
        * camelCase is now used for local variables and function parameters;
        * Replaced //-style comments with multi-line ones;
        * Split out one patch into 4 based on distinct features:
          * PCI VPD parser functionality and the respective in-memory types;
                * VPD helpers in virpci;
                * XML serialization/deserialization and VPD capability support;
                * Documentation.

Build & test results for targets in ci/manifest.yaml:

ci/helper test --meson-args='-Dexpensive_tests=enabled' <target>

* First Patch:
https://gist.github.com/dshcherb/8388165df0b62b71c2c95fbc351d1aee
* Patches 1 and 2:
https://gist.github.com/dshcherb/33c3f0f6e717788aea24b5dae2210f38
* Patches 1, 2 and 3:
https://gist.github.com/dshcherb/400bcb13d01fd28030f4986e3e178262
* All patches:
https://gist.github.com/dshcherb/b2fc8bd3a349f6357a25da85c542dda3

Dmitrii Shcherbakov (4):
  Add a PCI/PCIe device VPD Parser
  Add PCI VPD-related helper functions to virpci
  Add PCI VPD Capability Support
  Add PCI VPD Capability Documentation

 build-aux/syntax-check.mk                     |   4 +-
 docs/drvnodedev.html.in                       |  46 ++
 docs/formatnode.html.in                       |  24 +-
 docs/schemas/nodedev.rng                      |  40 +
 include/libvirt/libvirt-nodedev.h             |   1 +
 po/POTFILES.in                                |   1 +
 src/conf/node_device_conf.c                   | 271 +++++++
 src/conf/node_device_conf.h                   |   6 +-
 src/conf/virnodedeviceobj.c                   |   7 +-
 src/libvirt_private.syms                      |  17 +
 src/node_device/node_device_driver.c          |   2 +
 src/node_device/node_device_udev.c            |   2 +
 src/util/meson.build                          |   1 +
 src/util/virpci.c                             |  62 ++
 src/util/virpci.h                             |   3 +
 src/util/virpcivpd.c                          | 755 ++++++++++++++++++
 src/util/virpcivpd.h                          | 117 +++
 src/util/virpcivpdpriv.h                      |  45 ++
 tests/meson.build                             |   1 +
 .../pci_0000_42_00_0_vpd.xml                  |  33 +
 .../pci_0000_42_00_0_vpd.xml                  |   1 +
 tests/nodedevxml2xmltest.c                    |   1 +
 tests/testutils.c                             |  40 +
 tests/testutils.h                             |   4 +
 tests/virpcimock.c                            |  30 +
 tests/virpcitest.c                            |  64 ++
 tests/virpcivpdtest.c                         | 704 ++++++++++++++++
 tools/virsh-nodedev.c                         |   3 +
 28 files changed, 2280 insertions(+), 5 deletions(-)
 create mode 100644 src/util/virpcivpd.c
 create mode 100644 src/util/virpcivpd.h
 create mode 100644 src/util/virpcivpdpriv.h
 create mode 100644 tests/nodedevschemadata/pci_0000_42_00_0_vpd.xml
 create mode 120000 tests/nodedevxml2xmlout/pci_0000_42_00_0_vpd.xml
 create mode 100644 tests/virpcivpdtest.c

--
2.30.2