Storing PCI(e) VPD Board Serial Numbers

Dmitrii Shcherbakov dmitrii.shcherbakov at
Fri May 28 19:58:05 UTC 2021

Hello Libvirt Developers,

I am looking for some feedback on a planned enhancement to Libvirt: the aim
to store a portion of PCI(e) Vital Product Data (VPD) for each device along
with other PCI/PCIe device information already collected. Specifically, the
(Serial Number) read-only field of a VPD data structure of a device is of
interest which is described in PCI/PCIe specs (PCI local bus 2.1+ and PCIe

The context for this is the cross-project work in OpenStack (Nova, Neutron),
OVS and OVN to support for off-path SmartNIC DPUs ([1], [2], [3], [4]). The
Nova specification [1] provides an overview of the relevant hardware and the
use-case for board serial numbers, however, VPD is the standard capability
the PCI/PCIe specifications not tied to the use-case in particular so the
suggestion from the Nova core team was to aim at introducing means of
collecting this information via Libvirt. It can then be retrieved by the
respective virt driver in Nova via Libvirt without having to introduce this
code into Nova itself.

Quoting the PCI(e) specs:

* "Vital Product Data (VPD) is the information that uniquely defines items
as the hardware, software, and microcode elements of a system.";
* "Vital Product Data is made up of Small and Large Resource Data Types.";
* "Large resource type VPD-R Tag: This tag contains the read only VPD
for an add-in card."
* SN read-only field: "The characters are alphanumeric and represent the
add-in card Serial Number."

The VPD capability is optional per the specification so it may or may not
appear for PCI(e) endpoints. The devices of interest (SmartNIC DPUs),
generally have it exposed.

The PCI/PCIe specs define a binary format for VPD and a sysfs entry exposing
a binary blob in that format has been available since kernel v2.6.26 [5].
relevant sections of specs are:

* "6.4. Vital Product Data" in the PCI Local Bus specification;
* "6.28  Vital Product Data (VPD)" in the PCIe 4.0 Base Specification.

Note that the serial number stored in VPD is not identical to the
stored in the Device Serial Number (DSN) capability also present in the
as it may identify a component on a board which presents a multi-function
device but the board itself may have multiple components ([9] also makes a
distinction between a board serial and a device serial).

As a reference, there is some code to parse and print the VPD in lspci [6]
there is a prototype along those lines in Python [7], a polished version of
which I plan to use in Nova until the relevant functionality appears in

Likewise, the devlink kernel infrastructure, which is already used in
to query additional device capabilities [8] (e.g. the presence of an
and its switchdev mode) has a devlink-info API [9] that exposes a way to
a board serial number if a device driver exposes it (in turn, by querying

controller firmware or via PCIe VPD). This allows doing that in a

bus-independent manner (e.g. it would work for PCIe, platform devices or
I/O interconnects) but in the context of devices that implement devlink API

only (which are not necessarily network devices [10] but most of them

I would like to suggest the following to be done in Libvirt:

1) adding the code for extracting a serial number from VPD for PCI/PCIe
   in general and storing it for exposure via the Libvirt API;
More specifically, I propose adding a nested capability called "vpd" under
  <capability type='pci'>
    <capability type='vpd'>
<!-- ... other VPD attributes if present -->
<!-- ... -->
2) (optional) implementing functionality to obtain a board serial number via
   devlink-info for PCIe devices if they do not expose a VPD capability
but the device driver can retrieve it via firmware. The board serial number
can be stored in the same element as suggested above.

Not all devices expose the devlink API and even fewer do expose board serial
via devlink-info:

* devlink was added in 4.10 [11];
* devlink-info was introduced in 5.1 [12];
* querying for board.serial_number was added in kernel 5.9 [13] and iproute2
  5.9.0 [14];
* Besides the generic devlink infrastructure support above, device drivers
  also need to support exposing this field.

Therefore, implementing two approaches (sysfs VPD, devlink) is preferable
for better compatibility.

I would appreciate any feedback on whether this potential addition makes
If so, I can look into implementing this.


Best Regards,
Dmitrii Shcherbakov
LP: ~dmitriis
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the libvir-list mailing list