Skip to content

Commit

Permalink
Merge pull request #5945 from Yingshun/iommu_unload_driver
Browse files Browse the repository at this point in the history
vIOMMU: Add a test about driver load/unload
  • Loading branch information
chloerh authored Oct 28, 2024
2 parents 88bafdb + 855e516 commit 9992aff
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 0 deletions.
27 changes: 27 additions & 0 deletions libvirt/tests/cfg/sriov/vIOMMU/viommu_unload_driver.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
- vIOMMU.unload_driver:
type = viommu_unload_driver
start_vm = "no"

variants:
- virtio:
only q35, aarch64
func_supported_since_libvirt_ver = (8, 3, 0)
iommu_dict = {'model': 'virtio'}
- intel:
only q35
start_vm = "yes"
enable_guest_iommu = "yes"
iommu_dict = {'model': 'intel', 'driver': {'intremap': 'on', 'caching_mode': 'on', 'eim': 'on', 'iotlb': 'on', 'aw_bits': '48'}}
- smmuv3:
only aarch64
func_supported_since_libvirt_ver = (5, 5, 0)
iommu_dict = {'model': 'smmuv3'}
variants:
- virtio_interface:
variants:
- vhost_on:
interface_driver_name = "vhost"
- vhost_off:
interface_driver_name = "qemu"
interface_driver = {'driver_attr': {'name': '${interface_driver_name}', 'iommu': 'on'}}
iface_dict = {'type_name': 'network', 'model': 'virtio', 'driver': ${interface_driver}, 'source': {'network': 'default'}}
138 changes: 138 additions & 0 deletions libvirt/tests/src/sriov/vIOMMU/viommu_unload_driver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import os
import time

from avocado.utils import crypto
from avocado.utils import process

from virttest import data_dir
from virttest import utils_misc
from virttest import utils_net

from virttest.libvirt_xml import vm_xml
from virttest.utils_libvirt import libvirt_vmxml

from provider.viommu import viommu_base


def run(test, params, env):
"""
Verify the vm with iommu enabled interface work properly
after loading/unloading the driver.
"""
def all_threads_done(threads):
"""
Check whether all threads have finished
"""
for thread in threads:
if thread.is_alive():
return False
else:
continue
return True

def all_threads_alive(threads):
"""
Check whether all threads is alive
"""
for thread in threads:
if not thread.is_alive():
return False
else:
continue
return True

cleanup_ifaces = "yes" == params.get("cleanup_ifaces", "yes")
iommu_dict = eval(params.get('iommu_dict', '{}'))
filesize = int(params.get("filesize", 512))
transfer_timeout = int(params.get("transfer_timeout", 1000))

vm_name = params.get("main_vm", "avocado-vt-vm1")
vm = env.get_vm(vm_name)

test_obj = viommu_base.VIOMMUTest(vm, test, params)

try:
test.log.info("TEST_SETUP: Update VM XML.")
test_obj.setup_iommu_test(iommu_dict=iommu_dict,
cleanup_ifaces=cleanup_ifaces)

iface_dict = test_obj.parse_iface_dict()
if cleanup_ifaces:
libvirt_vmxml.modify_vm_device(
vm_xml.VMXML.new_from_dumpxml(vm.name),
"interface", iface_dict)

test.log.info("TEST_STEP: Start the VM.")
vm.start()
vm_session = vm.wait_for_login()
test.log.debug(vm_xml.VMXML.new_from_dumpxml(vm.name))

test.log.info("TEST_STEP: Get interface driver.")
ethname = utils_net.get_linux_ifname(vm_session, vm.get_mac_address(0))
output = vm_session.cmd_output(f"readlink -f /sys/class/net/{ethname}/device/driver")
nic_driver = os.path.basename(output)

test.log.info("TEST_STEP: Prepare file on host and guest.")
tmp_dir = data_dir.get_tmp_dir()
host_path = os.path.join(tmp_dir, "host_file_%s" %
utils_misc.generate_random_string(8))
guest_path = os.path.join("/home", "guest_file_%s" %
utils_misc.generate_random_string(8))
cmd = "dd if=/dev/zero of=%s bs=1M count=%d" % (host_path, filesize)
process.run(cmd)
file_checksum = crypto.hash_file(host_path, algorithm="md5")
vm.copy_files_to(host_path, guest_path, timeout=transfer_timeout)
if vm_session.cmd_status("md5sum %s | grep %s" %
(guest_path, file_checksum)):
test.cancel("File MD5SUMs changed after copy to guest")

test.log.info("TEST_STEP: Transfer files between host and guest.")
threads = []
file_paths = []
host_file_paths = []
for sess_index in range(int(params.get("sessions_num", "5"))):
sess_path = os.path.join("/home", "dst-%s" % sess_index)
host_sess_path = os.path.join(tmp_dir, "dst-%s" % sess_index)
thread1 = utils_misc.InterruptedThread(
vm.copy_files_to, (host_path, sess_path),
{"timeout": transfer_timeout})

thread2 = utils_misc.InterruptedThread(
vm.copy_files_from, (guest_path, host_sess_path),
{"timeout": transfer_timeout})
thread1.start()
threads.append(thread1)
thread2.start()
threads.append(thread2)
file_paths.append(sess_path)
host_file_paths.append(host_sess_path)

utils_misc.wait_for(lambda: all_threads_alive(threads), 60, 10, 1, text="check if all threads are alive")
time.sleep(5)

test.log.info("TEST_STEP: Unload and load the driver.")
vm.cleanup_serial_console()
vm.create_serial_console()
vm_serial = vm.wait_for_serial_login(timeout=120)
while not all_threads_done(threads):
vm_serial.cmd("modprobe -r %s" % nic_driver, timeout=120)
time.sleep(2)
vm_serial.cmd("modprobe %s" % nic_driver, timeout=120)
time.sleep(2)

for copied_file in file_paths:
if vm_serial.cmd_status("md5sum %s | grep %s" % (copied_file, file_checksum)):
test.fail("Guest file MD5SUMs changed after copying %s" % copied_file)
for copied_file in host_file_paths:
if process.run("md5sum %s | grep %s" %
(copied_file, file_checksum), shell=True, verbose=True,
ignore_status=True).exit_status:
test.fail("Host file MD5SUMs changed after copying %s" % copied_file)

finally:
test.log.info("TEST_TEARDOWN: Cleanup the env.")
for thread in threads:
thread.join()
for copied_file in host_file_paths:
process.system("rm -rf %s" % copied_file)
test_obj.teardown_iommu_test()

0 comments on commit 9992aff

Please sign in to comment.