Skip to content

Commit c2f4841

Browse files
committed
Split PCI pools per PF
Each PCI device and each PF is a separate RP in Placement and the scheduler allocate them specifically so the PCI filtering and claiming also needs to handle these devices individually. Nova pooled PCI devices together if they had the same device_spec and same device type and numa node. Now this is changed that only pool VFs from the same parent PF. Fortunately nova already handled consuming devices for a single InstancePCIRequest from multiple PCI pools, so this change does not affect the device consumption code path. The test_live_migrate_server_with_neutron test needed to be changed. Originally this test used a compute with the following config: * PF 81.00.0 ** VFs 81.00.[1-4] * PF 81.01.0 ** VFs 81.01.[1-4] * PF 82.00.0 And booted a VM that needed one VF and one PF. This request has two widely different solutions: 1) allocate the VF from under 81.00 and therefore consume 81.00.0 and allocate the 82.00.0 PF This was what the test asserted to happen. 2) allocate the VF from under 81.00 and therefore consume 81.00.0 and allocate the 81.00.0 PF and therefore consume all the VFs under it This results in a different amount of free devices than #1) AFAIK nova does not have any implemented preference for consuming PFs without VFs. The test just worked by chance (some internal device and pool ordering made it that way). However when the PCI pools are split nova started choosing solution #2) making the test fail. As both solution is equally good from nova's scheduling contract perspective I don't consider this as a behavior change. Therefore the test is updated not to create a situation where two different scheduling solutions are possible. blueprint: pci-device-tracking-in-placement Change-Id: I4b67cca3807fbda9e9b07b220a28e331def57624
1 parent b10482c commit c2f4841

File tree

4 files changed

+185
-85
lines changed

4 files changed

+185
-85
lines changed

nova/pci/stats.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,19 @@ def _create_pool_keys_from_dev(
139139
return None
140140
tags = devspec.get_tags()
141141
pool = {k: getattr(dev, k) for k in self.pool_keys}
142+
142143
if tags:
143144
pool.update(
144145
{k: v for k, v in tags.items() if k not in self.ignored_tags}
145146
)
147+
# NOTE(gibi): since PCI in placement maps a PCI dev or a PF to a
148+
# single RP and the scheduler allocates from a specific RP we need
149+
# to split the pools by PCI or PF address. We can still keep
150+
# the VFs from the same parent PF in a single pool though as they
151+
# are equivalent from placement perspective.
152+
address = dev.parent_addr or dev.address
153+
pool['address'] = address
154+
146155
# NOTE(gibi): parent_ifname acts like a tag during pci claim but
147156
# not provided as part of the whitelist spec as it is auto detected
148157
# by the virt driver.

nova/tests/functional/libvirt/test_pci_sriov_servers.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -879,7 +879,7 @@ def test_live_migrate_server_with_neutron(self):
879879

880880
# start two compute services with differing PCI device inventory
881881
source_pci_info = fakelibvirt.HostPCIDevicesInfo(
882-
num_pfs=2, num_vfs=8, numa_node=0)
882+
num_pfs=1, num_vfs=4, numa_node=0)
883883
# add an extra PF without VF to be used by direct-physical ports
884884
source_pci_info.add_device(
885885
dev_type='PF',
@@ -932,7 +932,7 @@ def test_live_migrate_server_with_neutron(self):
932932
# our source host should have marked two PCI devices as used, the VF
933933
# and the parent PF, while the future destination is currently unused
934934
self.assertEqual('test_compute0', server['OS-EXT-SRV-ATTR:host'])
935-
self.assertPCIDeviceCounts('test_compute0', total=11, free=8)
935+
self.assertPCIDeviceCounts('test_compute0', total=6, free=3)
936936
self.assertPCIDeviceCounts('test_compute1', total=4, free=4)
937937

938938
# the instance should be on host NUMA node 0, since that's where our
@@ -956,7 +956,7 @@ def test_live_migrate_server_with_neutron(self):
956956
# TODO(stephenfin): Stop relying on a side-effect of how nova
957957
# chooses from multiple PCI devices (apparently the last
958958
# matching one)
959-
'pci_slot': '0000:81:01.4',
959+
'pci_slot': '0000:81:00.4',
960960
'physical_network': 'physnet4',
961961
},
962962
port['binding:profile'],
@@ -980,7 +980,7 @@ def test_live_migrate_server_with_neutron(self):
980980

981981
# we should now have transitioned our usage to the destination, freeing
982982
# up the source in the process
983-
self.assertPCIDeviceCounts('test_compute0', total=11, free=11)
983+
self.assertPCIDeviceCounts('test_compute0', total=6, free=6)
984984
self.assertPCIDeviceCounts('test_compute1', total=4, free=1)
985985

986986
# the instance should now be on host NUMA node 1, since that's where

nova/tests/unit/compute/test_resource_tracker.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2401,7 +2401,10 @@ def test_claim_with_pci(self, migr_mock, pci_stats_mock,
24012401
vendor_id='0001',
24022402
product_id='0002',
24032403
numa_node=0,
2404-
tags={'dev_type': 'type-PCI'},
2404+
tags={
2405+
'dev_type': 'type-PCI',
2406+
'address': '0000:81:00.0'
2407+
},
24052408
count=0
24062409
)
24072410
]

0 commit comments

Comments
 (0)