Skip to content

Commit 8c9d6fc

Browse files
author
Balazs Gibizer
committed
Ignore PCI devices with 32bit domain
Nova and QEMU[1] supports PCI devices with a PCI address that has 16 bit domain. However there are hypervisors that reports PCI addresses with 32 bit domain. While today we cannot assign these to guests this should not prevent the nova-compute service to start. This patch changes the PCI manager to ignore such PCI devices. Please note that this patch does not change fact that nova does not allow specifying PCI addresses with 32bit domain in the [pci]/passthrough_whitelist configuration. Such configuration is still rejected at nova-compute service startup. Closes-Bug: #1897528 [1] https://github.com/qemu/qemu/blob/f2a1cf9180f63e88bb38ff21c169da97c3f2bad5/hw/core/qdev-properties.c#L993 Change-Id: I59a0746b864610b6a314078cf5661d3d2b84b1d4
1 parent 976ac72 commit 8c9d6fc

File tree

5 files changed

+77
-16
lines changed

5 files changed

+77
-16
lines changed

doc/source/admin/networking.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ A full guide on configuring and using SR-IOV is provided in the
2424
:neutron-doc:`OpenStack Networking service documentation
2525
<admin/config-sriov.html>`
2626

27+
.. note::
28+
29+
Nova only supports PCI addresses where the fields are restricted to the
30+
following maximum value:
31+
32+
* domain - 0xFFFF
33+
* bus - 0xFF
34+
* slot - 0x1F
35+
* function - 0x7
36+
37+
Nova will ignore PCI devices reported by the hypervisor if the address is
38+
outside of these ranges.
2739

2840
NUMA Affinity
2941
-------------

doc/source/admin/pci-passthrough.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ devices with potentially different capabilities.
3737
supported until the 14.0.0 Newton release, see
3838
`bug 1512800 <https://bugs.launchpad.net/nova/+bug/1512880>`_ for details.
3939

40+
.. note::
41+
42+
Nova only supports PCI addresses where the fields are restricted to the
43+
following maximum value:
44+
45+
* domain - 0xFFFF
46+
* bus - 0xFF
47+
* slot - 0x1F
48+
* function - 0x7
49+
50+
Nova will ignore PCI devices reported by the hypervisor if the address is
51+
outside of these ranges.
4052

4153
Configure host (Compute)
4254
------------------------

nova/conf/pci.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,13 @@
116116
117117
``address``
118118
PCI address of the device. Both traditional glob style and regular
119-
expression syntax is supported.
119+
expression syntax is supported. Please note that the address fields are
120+
restricted to the following maximum values:
121+
122+
* domain - 0xFFFF
123+
* bus - 0xFF
124+
* slot - 0x1F
125+
* function - 0x7
120126
121127
``devname``
122128
Device name of the device (for e.g. interface name). Not all PCI devices

nova/pci/manager.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,42 @@ def update_devices_from_hypervisor_resources(self, devices_json):
117117

118118
devices = []
119119
for dev in jsonutils.loads(devices_json):
120-
if self.dev_filter.device_assignable(dev):
121-
devices.append(dev)
120+
try:
121+
if self.dev_filter.device_assignable(dev):
122+
devices.append(dev)
123+
except exception.PciConfigInvalidWhitelist as e:
124+
# The raised exception is misleading as the problem is not with
125+
# the whitelist config but with the host PCI device reported by
126+
# libvirt. The code that matches the host PCI device to the
127+
# withelist spec reuses the WhitelistPciAddress object to parse
128+
# the host PCI device address. That parsing can fail if the
129+
# PCI address has a 32 bit domain. But this should not prevent
130+
# processing the rest of the devices. So we simply skip this
131+
# device and continue.
132+
# Please note that this except block does not ignore the
133+
# invalid whitelist configuration. The whitelist config has
134+
# already been parsed or rejected in case it was invalid. At
135+
# this point the self.dev_filter representes the parsed and
136+
# validated whitelist config.
137+
LOG.debug(
138+
'Skipping PCI device %s reported by the hypervisor: %s',
139+
{k: v for k, v in dev.items()
140+
if k in ['address', 'parent_addr']},
141+
# NOTE(gibi): this is ugly but the device_assignable() call
142+
# uses the PhysicalPciAddress class to parse the PCI
143+
# addresses and that class reuses the code from
144+
# PciAddressSpec that was originally designed to parse
145+
# whitelist spec. Hence the raised exception talks about
146+
# whitelist config. This is misleading as in our case the
147+
# PCI address that we failed to parse came from the
148+
# hypervisor.
149+
# TODO(gibi): refactor the false abstraction to make the
150+
# code reuse clean from the false assumption that we only
151+
# parse whitelist config with
152+
# devspec.PciAddressSpec._set_pci_dev_info()
153+
str(e).replace(
154+
'Invalid PCI devices Whitelist config:', 'The'))
155+
122156
self._set_hvdevs(devices)
123157

124158
@staticmethod

nova/tests/unit/pci/test_manager.py

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import nova
2323
from nova.compute import vm_states
2424
from nova import context
25-
from nova import exception
2625
from nova import objects
2726
from nova.objects import fields
2827
from nova.pci import manager
@@ -237,7 +236,9 @@ def test_update_devices_from_hypervisor_resources(self, _mock_dev_assign):
237236
tracker.update_devices_from_hypervisor_resources(fake_pci_devs_json)
238237
self.assertEqual(2, len(tracker.pci_devs))
239238

240-
def test_update_devices_from_hypervisor_resources_32bit_domain(self):
239+
@mock.patch("nova.pci.manager.LOG.debug")
240+
def test_update_devices_from_hypervisor_resources_32bit_domain(
241+
self, mock_debug):
241242
self.flags(
242243
group='pci',
243244
passthrough_whitelist=[
@@ -261,17 +262,13 @@ def test_update_devices_from_hypervisor_resources_32bit_domain(self):
261262
fake_pci_devs_json = jsonutils.dumps(fake_pci_devs)
262263
tracker = manager.PciDevTracker(self.fake_context)
263264
# We expect that the device with 32bit PCI domain is ignored
264-
# tracker.update_devices_from_hypervisor_resources(fake_pci_devs_json)
265-
# self.assertEqual(0, len(tracker.pci_devs))
266-
#
267-
# This is the bug 1897528
268-
ex = self.assertRaises(
269-
exception.PciConfigInvalidWhitelist,
270-
tracker.update_devices_from_hypervisor_resources,
271-
fake_pci_devs_json)
272-
self.assertEqual(
273-
'Invalid PCI devices Whitelist config: property domain (10000) is '
274-
'greater than the maximum allowable value (FFFF).', str(ex))
265+
tracker.update_devices_from_hypervisor_resources(fake_pci_devs_json)
266+
self.assertEqual(0, len(tracker.pci_devs))
267+
mock_debug.assert_called_once_with(
268+
'Skipping PCI device %s reported by the hypervisor: %s',
269+
{'address': '10000:00:02.0', 'parent_addr': None},
270+
'The property domain (10000) is greater than the maximum '
271+
'allowable value (FFFF).')
275272

276273
def test_set_hvdev_new_dev(self):
277274
fake_pci_3 = dict(fake_pci, address='0000:00:00.4', vendor_id='v2')

0 commit comments

Comments
 (0)