Libvirt: gracefully handle non-nic VFs

As part of adding support for bandwidth based scheduling
I038867c4094d79ae4a20615ab9c9f9e38fcc2e0a introduced
automatic discovery of parent netdev names for PCIe
virtual functions.

Nova's PCI passthrough support was originally developed for
Intel QAT devices and other generic PCI devices. Later support
for Neutron based SR-IOV NIC was added.

The PCI-SIG SR-IOV specification while most often used by NIC
vendors to virtualise a NIC in hardware was designed for devices
of any PCIe class. Support for Intel's QAT device and other
accelerators like AMD's SRIOV based vGPU have therefore been
regressed by the introduction of the new parent_ifname lookup code.

This change simply catches the exception that would be raised
when pci_utils.get_ifname_by_pci_address is called on generic
VFs allowing a graceful fallback to the previous behaviour.

Change-Id: Ib3811f828246311d90b0e3ba71c162c03fb8fe5a
Closes-Bug: #1821938
(cherry picked from commit e7ae6c65cd)
This commit is contained in:
Sean Mooney 2019-04-02 18:27:24 +01:00 committed by Matt Riedemann
parent 0fd77f3f65
commit 97a806b790
2 changed files with 34 additions and 4 deletions

View File

@ -15103,6 +15103,28 @@ class LibvirtConnTestCase(test.NoDBTestCase,
mock_get_net_name.called_once_with(parent_address)
mock_dev_lookup.called_once_with(dev_name)
@mock.patch.object(pci_utils, 'get_ifname_by_pci_address')
def test_get_pcidev_info_non_nic(self, mock_get_ifname):
self.stub_out('nova.virt.libvirt.host.Host.device_lookup_by_name',
lambda self, name: FakeNodeDevice(
_fake_NodeDevXml[name]))
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
id = "pci_0000_04_10_7"
mock_get_ifname.side_effect = exception.PciDeviceNotFoundById(id=id)
actualvf = drvr._get_pcidev_info(id)
expect_vf = {
"dev_id": id,
"address": "0000:04:10.7",
"product_id": '1520',
"numa_node": None,
"vendor_id": '8086',
"label": 'label_8086_1520',
"dev_type": fields.PciDeviceType.SRIOV_VF,
'parent_addr': '0000:04:00.3',
}
self.assertEqual(expect_vf, actualvf)
@mock.patch.object(pci_utils, 'get_ifname_by_pci_address',
return_value='ens1')
def test_get_pcidev_info(self, mock_get_ifname):

View File

@ -6013,13 +6013,21 @@ class LibvirtDriver(driver.ComputeDriver):
fun_cap.device_addrs[0][1],
fun_cap.device_addrs[0][2],
fun_cap.device_addrs[0][3])
return {
result = {
'dev_type': fields.PciDeviceType.SRIOV_VF,
'parent_addr': phys_address,
'parent_ifname':
pci_utils.get_ifname_by_pci_address(
pci_address, pf_interface=True),
}
parent_ifname = None
try:
parent_ifname = pci_utils.get_ifname_by_pci_address(
pci_address, pf_interface=True)
except exception.PciDeviceNotFoundById:
# NOTE(sean-k-mooney): we ignore this error as it
# is expected when the virtual function is not a NIC.
pass
if parent_ifname:
result['parent_ifname'] = parent_ifname
return result
return {'dev_type': fields.PciDeviceType.STANDARD}