@@ -1246,10 +1246,70 @@ def test_live_migration_with_vcpu_pinning(self):
12461246 assert int (taskset_vcpu0_controller , 16 ) == int (taskset_vcpu0_compute , 16 )
12471247 assert int (taskset_vcpu2_controller , 16 ) == int (taskset_vcpu2_compute , 16 )
12481248
1249+ def test_bdf_assignment (self ):
1250+ """
1251+ Test if all BDFs are correctly assigned in different scenarios:
1252+ 1) After VM creation and hotplugging a device
1253+ 2) If a devices is removed and it's BDF reused
1254+ 3) Two devices that use the same BDF (expected to fail)
1255+ 4) After live migration (all devices retain assigned BDFs)
1256+ """
1257+
1258+ VIRTIO_NETWORK_DEVICE = "1af4:1041"
1259+ VIRTIO_BLOCK_DEVICE = "1af4:1042"
1260+ VIRTIO_ENTROPY_SOURCE = "1af4:1044"
1261+
1262+ """
1263+ 1) All BDFs are correctly assigned (with precedence for XML assignments)
1264+
1265+ In the current implementation, CHV and libvirt will instantiate
1266+ disk devices before net devices (because currently we hotplug
1267+ them). The VM's XML only assigns a BDF to the net device. If
1268+ libvirt would miss to order assignment, this subtlety would
1269+ create a conflict where both try to acquire BDF 00:02.0. This
1270+ should be prevented by reserving all BDFs that are assigned to
1271+ devices in the XML before assigning one to each device. This is
1272+ implicitly tested in case 1.
1273+ """
1274+ controllerVM .succeed ("virsh define /etc/domain-chv.xml" )
1275+ controllerVM .succeed ("virsh start testvm" )
1276+ controllerVM .succeed ("virsh attach-device testvm /etc/new_interface.xml" )
1277+
1278+ assert wait_for_ssh (controllerVM )
1279+
1280+ devices_before = pci_devices_by_bdf (controllerVM )
1281+ assert devices_before ["00:01.0" ] == VIRTIO_ENTROPY_SOURCE
1282+ assert devices_before ["00:02.0" ] == VIRTIO_NETWORK_DEVICE
1283+ assert devices_before ["00:03.0" ] == VIRTIO_BLOCK_DEVICE
1284+ assert devices_before ["00:0c.0" ] == VIRTIO_NETWORK_DEVICE
1285+
1286+ # 2) Check that BDF is freed and can be reallocated when de-/attaching a (entirely different) device
1287+ controllerVM .succeed ("virsh detach-device testvm /etc/new_interface.xml" )
1288+ assert pci_devices_by_bdf (controllerVM ).get ("00:0c.0" ) == None
1289+ controllerVM .succeed (
1290+ "virsh attach-disk --domain testvm --target vdb --persistent --source /var/lib/libvirt/storage-pools/nfs-share/cirros.img --address pci:0.0.c.0"
1291+ )
1292+ devices_before_livemig = pci_devices_by_bdf (controllerVM )
1293+ assert devices_before_livemig .get ("00:0c.0" ) == VIRTIO_BLOCK_DEVICE
1294+
1295+ # 3) Adding to the same bdf twice fails
1296+ controllerVM .wait_until_fails (
1297+ "virsh attach-device testvm /etc/new_interface.xml"
1298+ )
1299+
1300+ # 4) Check that BDFs stay the same after migration
1301+ controllerVM .succeed (
1302+ "virsh migrate --domain testvm --desturi ch+tcp://computeVM/session --persistent --live --p2p"
1303+ )
1304+ assert wait_for_ssh (computeVM )
1305+ devices_after_livemig = pci_devices_by_bdf (computeVM )
1306+ assert devices_before_livemig == devices_after_livemig
1307+
12491308
12501309def suite ():
12511310 # Test cases in alphabetical order
12521311 testcases = [
1312+ LibvirtTests .test_bdf_assignment ,
12531313 LibvirtTests .test_disk_is_locked ,
12541314 LibvirtTests .test_disk_resize_qcow2 ,
12551315 LibvirtTests .test_disk_resize_raw ,
0 commit comments