diff --git a/lisa/nic.py b/lisa/nic.py index 1fc57e4d78..0d591a7e8a 100644 --- a/lisa/nic.py +++ b/lisa/nic.py @@ -56,6 +56,7 @@ def __str__(self) -> str: f"pci_slot: {self.pci_slot}\n" f"ip_addr: {self.ip_addr}\n" f"mac_addr: {self.mac_addr}\n" + f"dev_uuid: {self.dev_uuid}\n" ) @property diff --git a/microsoft/testsuites/dpdk/dpdksuite.py b/microsoft/testsuites/dpdk/dpdksuite.py index f1b3128166..4a00a8cb2a 100644 --- a/microsoft/testsuites/dpdk/dpdksuite.py +++ b/microsoft/testsuites/dpdk/dpdksuite.py @@ -24,7 +24,19 @@ from lisa.features import Gpu, Infiniband, IsolatedResource, Sriov from lisa.operating_system import BSD, CBLMariner, Ubuntu, Windows from lisa.testsuite import TestResult, simple_requirement -from lisa.tools import Echo, Git, Hugepages, Ip, Kill, Lscpu, Lsmod, Make, Modprobe +from lisa.tools import ( + Echo, + Git, + Hugepages, + Ip, + Kill, + Lscpu, + Lsmod, + Make, + Modprobe, + Ping, + Timeout, +) from lisa.tools.hugepages import HugePageSize from lisa.tools.lscpu import CpuArchitecture from lisa.util.constants import SIGINT @@ -40,7 +52,7 @@ UnsupportedPackageVersionException, check_send_receive_compatibility, do_parallel_cleanup, - enable_uio_hv_generic_for_nic, + enable_uio_hv_generic, generate_send_receive_run_info, init_nodes_concurrent, initialize_node_resources, @@ -103,6 +115,123 @@ def verify_dpdk_build_netvsc( node, log, variables, "netvsc", HugePageSize.HUGE_2MB, result=result ) + @TestCaseMetadata( + description=""" + netvsc pmd version. + This test case checks DPDK can be built and installed correctly. + Prerequisites, accelerated networking must be enabled. + The VM should have at least two network interfaces, + with one interface for management. + More details refer https://docs.microsoft.com/en-us/azure/virtual-network/setup-dpdk#prerequisites # noqa: E501 + """, + priority=2, + requirement=simple_requirement( + min_core_count=8, + min_nic_count=3, + network_interface=Sriov(), + unsupported_features=[Gpu, Infiniband], + ), + ) + def verify_dpdk_symmetric_mp( + self, + node: Node, + log: Logger, + variables: Dict[str, Any], + result: TestResult, + ) -> None: + # setup and unwrap the resources for this test + nics = [node.nics.get_nic("eth1"), node.nics.get_nic("eth2")] + test_nic = node.nics.get_secondary_nic() + extra_nics = [nic for nic in nics if nic.name != test_nic.name] + ping = node.tools[Ping] + ping.install() + try: + test_kit = initialize_node_resources( + node, + log, + variables, + "netvsc", + HugePageSize.HUGE_2MB, + extra_nics=extra_nics, + ) + except (NotEnoughMemoryException, UnsupportedOperationException) as err: + raise SkippedException(err) + testpmd = test_kit.testpmd + if isinstance(testpmd.installer, PackageManagerInstall): + # The Testpmd tool doesn't get re-initialized + # even if you invoke it with new arguments. + raise SkippedException( + "DPDK symmetric_mp test is not implemented for " + " package manager installation." + ) + symmetric_mp_path = testpmd.get_example_app_path("dpdk-symmetric_mp") + node.log.debug("\n".join([str(nic) for nic in nics])) + if node.nics.is_mana_device_present(): + nic_args = ( + f'--vdev="{test_nic.pci_slot},' + f"mac={test_nic.mac_addr}," + f'mac={extra_nics[0].mac_addr}"' + ) + else: + nic_args = f"-b {node.nics.get_primary_nic().pci_slot}" + + output = node.execute( + f"{str(testpmd.get_example_app_path('dpdk-devname'))} {nic_args}", + sudo=True, + shell=True, + ).stdout + port_mask = 0x0 + port_regex = re.compile( + r"dpdk-devname found port=(?P[0-9]+) driver=net_netvsc .*\n" + ) + matches = port_regex.findall(output) + if not matches: + fail("could not find port ids") + for match in matches: + port_mask ^= 1 << (int(match)) + + node.log.debug(f"Port mask: {hex(port_mask)}") + # primary_nic = node.nics.get_primary_nic().pci_slot + symmetric_mp_args = ( + f"{nic_args} --proc-type auto " + "--log-level netvsc,debug --log-level mana,debug --log-level eal,debug " + f"-- -p {hex(port_mask)[2:]} --num-procs 2" + ) + primary = node.tools[Timeout].start_with_timeout( + command=f"{str(symmetric_mp_path)} -l 1 {symmetric_mp_args} --proc-id 0", + timeout=150, + signal=SIGINT, + kill_timeout=30, + ) + primary.wait_output("APP: Finished Process Init") + secondary = node.tools[Timeout].start_with_timeout( + command=f"{str(symmetric_mp_path)} -l 2 {symmetric_mp_args} --proc-id 1", + timeout=120, + signal=SIGINT, + kill_timeout=35, + ) + _ = ping.ping_async( + target=test_nic.ip_addr, + nic_name=node.nics.get_primary_nic().name, + count=100, + ) + secondary_exit = secondary.wait_result() + assert_that(secondary_exit.exit_code).described_as( + f"Secondary process failure: {secondary_exit.stdout}" + ).is_zero() + process_result = primary.wait_result( + expected_exit_code=0, + expected_exit_code_failure_message="Primary process failed to exit with 0", + ) + node.log.debug( + f"Primary process:\n\n{process_result.stdout}\n" + f"\nprimary stderr:\n{process_result.stderr}" + ) + node.log.debug( + f"Secondary system:\n\n{secondary_exit.stdout}\n" + f"secondary stderr:\n{secondary_exit.stderr}" + ) + @TestCaseMetadata( description=""" netvsc pmd version with 1GiB hugepages @@ -925,7 +1054,7 @@ def verify_uio_binding( nic = node.nics.get_secondary_nic() node.nics.get_nic_driver(nic.name) if nic.module_name == "hv_netvsc": - enable_uio_hv_generic_for_nic(node, nic) + enable_uio_hv_generic(node) original_driver = nic.driver_sysfs_path node.nics.unbind(nic) diff --git a/microsoft/testsuites/dpdk/dpdktestpmd.py b/microsoft/testsuites/dpdk/dpdktestpmd.py index 8d5f8629d2..2d5e66004b 100644 --- a/microsoft/testsuites/dpdk/dpdktestpmd.py +++ b/microsoft/testsuites/dpdk/dpdktestpmd.py @@ -198,6 +198,7 @@ class DpdkSourceInstall(Installer): "l3fwd", "multi_process/client_server_mp/mp_server", "multi_process/client_server_mp/mp_client", + "multi_process/symmetric_mp", ] def _check_if_installed(self) -> bool: @@ -257,6 +258,12 @@ def get_installed_version(self) -> VersionInfo: def _install(self) -> None: super()._install() + _ = self._node.tools[Git].clone( + url="https://github.com/mcgov/devname.git", + cwd=self.asset_path.joinpath("examples"), + dir_name="devname", + ) + self._sample_applications += ["devname"] if self._sample_applications: sample_apps = f"-Dexamples={','.join(self._sample_applications)}" else: diff --git a/microsoft/testsuites/dpdk/dpdkutil.py b/microsoft/testsuites/dpdk/dpdkutil.py index 84074dad0d..3345f7d237 100644 --- a/microsoft/testsuites/dpdk/dpdkutil.py +++ b/microsoft/testsuites/dpdk/dpdkutil.py @@ -224,7 +224,7 @@ def generate_send_receive_run_info( HV_NETVSC_SYSFS_PATH = "/sys/bus/vmbus/drivers/hv_netvsc" -def enable_uio_hv_generic_for_nic(node: Node, nic: NicInfo) -> None: +def enable_uio_hv_generic(node: Node) -> None: # hv_uio_generic driver uuid, a constant value used by vmbus. # https://doc.dpdk.org/guides/nics/netvsc.html#installation hv_uio_generic_uuid = "f8615163-df3e-46c5-913f-f2d2f965ed0e" @@ -262,21 +262,29 @@ def enable_uio_hv_generic_for_nic(node: Node, nic: NicInfo) -> None: def do_pmd_driver_setup( - node: Node, test_nic: NicInfo, testpmd: DpdkTestpmd, pmd: str = "failsafe" + node: Node, test_nics: List[NicInfo], testpmd: DpdkTestpmd, pmd: str = "failsafe" ) -> None: if pmd == "netvsc": # setup system for netvsc pmd # https://doc.dpdk.org/guides/nics/netvsc.html - enable_uio_hv_generic_for_nic(node, test_nic) - node.nics.unbind(test_nic) - node.nics.bind(test_nic, UIO_HV_GENERIC_SYSFS_PATH) + enable_uio_hv_generic(node) + # bound vmbus device may be the same when using vports + # ie... MANA. So track which devices we've already unbound to avoid + # doing things twice. + bound: List[str] = [] + for nic in test_nics: + if nic.dev_uuid not in bound: + node.nics.unbind(nic) + node.nics.bind(nic, UIO_HV_GENERIC_SYSFS_PATH) + bound.append(nic.dev_uuid) # if mana is present, set VF interface down. # FIXME: add mana dpdk docs link when it's available. if testpmd.is_mana: ip = node.tools[Ip] - if test_nic.lower and ip.is_device_up(test_nic.lower): - ip.down(test_nic.lower) + for test_nic in test_nics: + if test_nic.lower and ip.is_device_up(test_nic.lower): + ip.down(test_nic.lower) def initialize_node_resources( @@ -366,10 +374,11 @@ def initialize_node_resources( ).is_equal_to("hv_netvsc") # netvsc pmd requires uio_hv_generic to be loaded before use - do_pmd_driver_setup(node=node, test_nic=test_nic, testpmd=testpmd, pmd=pmd) - if extra_nics: - for extra_nic in extra_nics: - do_pmd_driver_setup(node=node, test_nic=extra_nic, testpmd=testpmd, pmd=pmd) + test_nics = [test_nic] + if extra_nics is not None: + test_nics += extra_nics + + do_pmd_driver_setup(node=node, test_nics=test_nics, testpmd=testpmd, pmd=pmd) return DpdkTestResources(_node=node, _testpmd=testpmd, _rdma_core=rdma_core)