PCI: Fix PCI with fully qualified address
Specifying a PF passthrough device in the pci_passthrough_whitelist using its fully qualified PCI address (no wildcard) causes the device to not be properly loaded. The PCI device is then not available to be assigned to any guest. In this case, the hypervisor reports the PF device without a 'parent_addr'. But in the PciAddress, match() is using it when doing the comparison to its own address. This commit changes the logic of the address matching method in PciDevSpec to only try to match the address with a physical function device when a 'parent_addr' is reported by the hypervisor. Change-Id: I5255240871d8ad5c216500f39520339efe46e84b Closes-Bug: #1613434
This commit is contained in:
parent
8ecef74b27
commit
d38d5767d1
|
@ -106,25 +106,36 @@ class PciAddress(object):
|
|||
self._check_physical_function()
|
||||
|
||||
def match(self, pci_addr, pci_phys_addr):
|
||||
# Assume this is called given pci_add and pci_phys_addr from libvirt,
|
||||
# no attempt is made to verify pci_addr is a VF of pci_phys_addr
|
||||
if self.is_physical_function:
|
||||
if not pci_phys_addr:
|
||||
return False
|
||||
"""Match a device to this PciAddress. Assume this is called given
|
||||
pci_addr and pci_phys_addr reported by libvirt, no attempt is made to
|
||||
verify if pci_addr is a VF of pci_phys_addr.
|
||||
|
||||
:param pci_addr: PCI address of the device to match.
|
||||
:param pci_phys_addr: PCI address of the parent of the device to match
|
||||
(or None if the device is not a VF).
|
||||
"""
|
||||
|
||||
# Try to match on the parent PCI address if the PciDeviceSpec is a
|
||||
# PF (sriov is available) and the device to match is a VF. This
|
||||
# makes possible to specify the PCI address of a PF in the
|
||||
# pci_passthrough_whitelist to match any of it's VFs PCI devices.
|
||||
if self.is_physical_function and pci_phys_addr:
|
||||
domain, bus, slot, func = (
|
||||
utils.get_pci_address_fields(pci_phys_addr))
|
||||
return (self.domain == domain and self.bus == bus and
|
||||
self.slot == slot and self.func == func)
|
||||
else:
|
||||
domain, bus, slot, func = (
|
||||
utils.get_pci_address_fields(pci_addr))
|
||||
conditions = [
|
||||
self.domain in (ANY, domain),
|
||||
self.bus in (ANY, bus),
|
||||
self.slot in (ANY, slot),
|
||||
self.func in (ANY, func)
|
||||
]
|
||||
return all(conditions)
|
||||
if (self.domain == domain and self.bus == bus and
|
||||
self.slot == slot and self.func == func):
|
||||
return True
|
||||
|
||||
# Try to match on the device PCI address only.
|
||||
domain, bus, slot, func = (
|
||||
utils.get_pci_address_fields(pci_addr))
|
||||
conditions = [
|
||||
self.domain in (ANY, domain),
|
||||
self.bus in (ANY, bus),
|
||||
self.slot in (ANY, slot),
|
||||
self.func in (ANY, func)
|
||||
]
|
||||
return all(conditions)
|
||||
|
||||
|
||||
class PciDeviceSpec(object):
|
||||
|
|
|
@ -22,7 +22,7 @@ from nova import test
|
|||
|
||||
dev = {"vendor_id": "8086",
|
||||
"product_id": "5057",
|
||||
"address": "1234:5678:8988.5",
|
||||
"address": "0000:0b:00.5",
|
||||
"parent_addr": "0000:0a:00.0"}
|
||||
|
||||
|
||||
|
@ -95,12 +95,20 @@ class PciAddressTestCase(test.NoDBTestCase):
|
|||
"parent_addr": "0000:0a:00.0"}
|
||||
self.assertTrue(pci.match(dev))
|
||||
|
||||
@mock.patch('nova.pci.utils.is_physical_function', return_value = True)
|
||||
@mock.patch('nova.pci.utils.is_physical_function', return_value=True)
|
||||
def test_address_is_pf(self, mock_is_physical_function):
|
||||
pci_info = {"address": "0000:0a:00.0", "physical_network": "hr_net"}
|
||||
pci = devspec.PciDeviceSpec(pci_info)
|
||||
self.assertTrue(pci.match(dev))
|
||||
|
||||
@mock.patch('nova.pci.utils.is_physical_function', return_value=True)
|
||||
def test_address_pf_no_parent_addr(self, mock_is_physical_function):
|
||||
_dev = dev.copy()
|
||||
_dev.pop('parent_addr')
|
||||
pci_info = {"address": "0000:0b:00.5", "physical_network": "hr_net"}
|
||||
pci = devspec.PciDeviceSpec(pci_info)
|
||||
self.assertTrue(pci.match(_dev))
|
||||
|
||||
|
||||
class PciDevSpecTestCase(test.NoDBTestCase):
|
||||
def test_spec_match(self):
|
||||
|
|
Loading…
Reference in New Issue