Fix the PCI device capability dict creation
VPD handling was added in ab49f97b2c
and
introduced a regression which was not caught by unit or functional
tests: if a VPD capability is present for a PCI device, it overrides
the network capabilities obtained from the associated netdev.
This change fixes the issue and adds additional test coverage.
Closes-Bug: #1964995
Change-Id: Ifa9ae93530339828333dd3e23cdffe9f85e96a70
This commit is contained in:
parent
dde15d9c47
commit
c3ad968c87
|
@ -2163,6 +2163,27 @@ _fake_NodeDevXml = {
|
|||
<link validity='sta' width='0'/>
|
||||
</pci-express>
|
||||
</capability>
|
||||
</device>""",
|
||||
"net_enp130s0f0v0_36_33_10_a3_94_64": """
|
||||
<device>
|
||||
<name>net_enp130s0f0v0_36_33_10_a3_94_64</name>
|
||||
<path>/sys/devices/pci0000:80/0000:80:03.0/0000:82:00.3/net/enp130s0f0v0</path>
|
||||
<parent>pci_0000_82_00_3</parent>
|
||||
<capability type='net'>
|
||||
<interface>enp130s0f0v0</interface>
|
||||
<address>36:33:10:a3:94:64</address>
|
||||
<link state='down'/>
|
||||
<feature name='rx'/>
|
||||
<feature name='tx'/>
|
||||
<feature name='sg'/>
|
||||
<feature name='tso'/>
|
||||
<feature name='gso'/>
|
||||
<feature name='gro'/>
|
||||
<feature name='rxvlan'/>
|
||||
<feature name='txvlan'/>
|
||||
<feature name='rxhash'/>
|
||||
<capability type='80203'/>
|
||||
</capability>
|
||||
</device>""", # noqa:E501
|
||||
}
|
||||
|
||||
|
|
|
@ -1280,7 +1280,10 @@ Active: 8381604 kB
|
|||
"vendor_id": "15b3",
|
||||
"label": "label_15b3_101e",
|
||||
"dev_type": obj_fields.PciDeviceType.SRIOV_VF,
|
||||
"parent_ifname": "ens1",
|
||||
"capabilities": {
|
||||
"network": ["rx", "tx", "sg", "tso", "gso", "gro", "rxvlan",
|
||||
"txvlan", "rxhash"],
|
||||
# Should be obtained from the parent PF in this case.
|
||||
"vpd": {"card_serial_number": "MT2113X00000"}},
|
||||
}
|
||||
|
|
|
@ -1336,31 +1336,11 @@ class Host(object):
|
|||
|
||||
return {'dev_type': fields.PciDeviceType.STANDARD}
|
||||
|
||||
def _get_device_capabilities(
|
||||
device_dict: dict,
|
||||
device: 'libvirt.virNodeDevice',
|
||||
net_devs: ty.List['libvirt.virNodeDevice']
|
||||
) -> ty.Dict[str, ty.Dict[str, ty.Any]]:
|
||||
"""Get PCI VF device's additional capabilities.
|
||||
|
||||
If a PCI device is a virtual function, this function reads the PCI
|
||||
parent's network capabilities (must be always a NIC device) and
|
||||
appends this information to the device's dictionary.
|
||||
"""
|
||||
caps: ty.Dict[str, ty.Dict[str, ty.Any]] = {}
|
||||
|
||||
if device_dict.get('dev_type') == fields.PciDeviceType.SRIOV_VF:
|
||||
pcinet_info = self._get_pcinet_info(device, net_devs)
|
||||
if pcinet_info:
|
||||
return {'capabilities': {'network': pcinet_info}}
|
||||
|
||||
return caps
|
||||
|
||||
def _get_vpd_details(
|
||||
device_dict: dict,
|
||||
device: 'libvirt.virNodeDevice',
|
||||
pci_devs: ty.List['libvirt.virNodeDevice']
|
||||
) -> ty.Dict[str, ty.Dict[str, ty.Any]]:
|
||||
) -> ty.Dict[str, ty.Any]:
|
||||
"""Get information from PCI VPD (if present).
|
||||
|
||||
PCI/PCIe devices may include the optional VPD capability. It may
|
||||
|
@ -1373,7 +1353,7 @@ class Host(object):
|
|||
the VPD capability or not may be controlled via a vendor-specific
|
||||
firmware setting.
|
||||
"""
|
||||
caps: ty.Dict[str, ty.Dict[str, ty.Any]] = {}
|
||||
vpd_info: ty.Dict[str, ty.Any] = {}
|
||||
# At the time of writing only the serial number had a clear
|
||||
# use-case. However, the set of fields may be extended.
|
||||
card_serial_number = self._get_vpd_card_serial_number(device)
|
||||
|
@ -1388,7 +1368,7 @@ class Host(object):
|
|||
LOG.warning("A VF device dict does not have a parent PF "
|
||||
"address in it which is unexpected. Skipping "
|
||||
"serial number retrieval")
|
||||
return caps
|
||||
return vpd_info
|
||||
|
||||
formatted_addr = pf_addr.replace('.', '_').replace(':', '_')
|
||||
vpd_cap = self._get_vf_parent_pci_vpd_info(
|
||||
|
@ -1397,8 +1377,35 @@ class Host(object):
|
|||
card_serial_number = vpd_cap.card_serial_number
|
||||
|
||||
if card_serial_number:
|
||||
caps = {'capabilities': {
|
||||
'vpd': {"card_serial_number": card_serial_number}}}
|
||||
vpd_info = {'card_serial_number': card_serial_number}
|
||||
return vpd_info
|
||||
|
||||
def _get_device_capabilities(
|
||||
device_dict: dict,
|
||||
device: 'libvirt.virNodeDevice',
|
||||
pci_devs: ty.List['libvirt.virNodeDevice'],
|
||||
net_devs: ty.List['libvirt.virNodeDevice']
|
||||
) -> ty.Dict[str, ty.Any]:
|
||||
"""Get PCI VF device's additional capabilities.
|
||||
|
||||
If a PCI device is a virtual function, this function reads the PCI
|
||||
parent's network capabilities (must be always a NIC device) and
|
||||
appends this information to the device's dictionary.
|
||||
"""
|
||||
caps: ty.Dict[str, ty.Any] = {}
|
||||
|
||||
if device_dict.get('dev_type') == fields.PciDeviceType.SRIOV_VF:
|
||||
pcinet_info = self._get_pcinet_info(device, net_devs)
|
||||
if pcinet_info:
|
||||
caps['network'] = pcinet_info
|
||||
|
||||
vpd_info = _get_vpd_details(device_dict, device, pci_devs)
|
||||
if vpd_info:
|
||||
caps['vpd'] = vpd_info
|
||||
|
||||
if caps:
|
||||
return {'capabilities': caps}
|
||||
|
||||
return caps
|
||||
|
||||
xmlstr = dev.XMLDesc(0)
|
||||
|
@ -1424,8 +1431,8 @@ class Host(object):
|
|||
device['label'] = 'label_%(vendor_id)s_%(product_id)s' % device
|
||||
device.update(
|
||||
_get_device_type(cfgdev, address, dev, net_devs, vdpa_devs))
|
||||
device.update(_get_device_capabilities(device, dev, net_devs))
|
||||
device.update(_get_vpd_details(device, dev, pci_devs))
|
||||
device.update(_get_device_capabilities(device, dev,
|
||||
pci_devs, net_devs))
|
||||
return device
|
||||
|
||||
def get_vdpa_nodedev_by_address(
|
||||
|
|
Loading…
Reference in New Issue