X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2FDPDK%2FL3fwdTest.py;h=265806c7e92850c5520e5872cb735f731611c860;hb=466674c41326aa5765f18805a9dbc37a8df7918a;hp=07ffae9c4354de1098f0937ebb08f0ccd393555f;hpb=7829fea4a2c8936513fa95215b7d84997f814a69;p=csit.git diff --git a/resources/libraries/python/DPDK/L3fwdTest.py b/resources/libraries/python/DPDK/L3fwdTest.py index 07ffae9c43..265806c7e9 100644 --- a/resources/libraries/python/DPDK/L3fwdTest.py +++ b/resources/libraries/python/DPDK/L3fwdTest.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Cisco and/or its affiliates. +# Copyright (c) 2022 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -12,25 +12,101 @@ # limitations under the License. """ -This module exists to provide the l3fwd test for DPDK on topology nodes. +This module exists to start l3fwd on topology nodes. """ +from robot.libraries.BuiltIn import BuiltIn from resources.libraries.python.Constants import Constants +from resources.libraries.python.CpuUtils import CpuUtils from resources.libraries.python.DpdkUtil import DpdkUtil from resources.libraries.python.ssh import exec_cmd_no_error, exec_cmd from resources.libraries.python.topology import NodeType, Topology +NB_PORTS = 2 + class L3fwdTest: - """Test the DPDK l3fwd performance.""" + """This class start l3fwd on topology nodes and check if properly started. + """ + + @staticmethod + def start_l3fwd_on_all_duts( + nodes, topology_info, phy_cores, rx_queues=None, jumbo_frames=False, + rxd=None, txd=None): + """ + Execute the l3fwd on all dut nodes. + + :param nodes: All the nodes info from the topology file. + :param topology_info: All the info from the topology file. + :param phy_cores: Number of physical cores to use. + :param rx_queues: Number of RX queues. + :param jumbo_frames: Jumbo frames on/off. + :param rxd: Number of RX descriptors. + :param txd: Number of TX descriptors. + + :type nodes: dict + :type topology_info: dict + :type phy_cores: int + :type rx_queues: int + :type jumbo_frames: bool + :type rxd: int + :type txd: int + :raises RuntimeError: If bash return code is not 0. + """ + cpu_count_int = dp_count_int = int(phy_cores) + dp_cores = cpu_count_int+1 + tg_flip = topology_info[f"tg_if1_pci"] > topology_info[f"tg_if2_pci"] + for node in nodes: + if u"DUT" in node: + compute_resource_info = CpuUtils.get_affinity_vswitch( + nodes, node, phy_cores, rx_queues=rx_queues, + rxd=rxd, txd=txd + ) + if dp_count_int > 1: + BuiltIn().set_tags('MTHREAD') + else: + BuiltIn().set_tags('STHREAD') + BuiltIn().set_tags( + f"{dp_count_int}T{cpu_count_int}C" + ) + + cpu_dp = compute_resource_info[u"cpu_dp"] + rxq_count_int = compute_resource_info[u"rxq_count_int"] + if1 = topology_info[f"{node}_pf1"][0] + if2 = topology_info[f"{node}_pf2"][0] + L3fwdTest.start_l3fwd( + nodes, nodes[node], if1=if1, if2=if2, lcores_list=cpu_dp, + nb_cores=dp_count_int, queue_nums=rxq_count_int, + jumbo_frames=jumbo_frames, tg_flip=tg_flip + ) + for node in nodes: + if u"DUT" in node: + for i in range(3): + try: + L3fwdTest.check_l3fwd(nodes[node]) + break + except RuntimeError: + L3fwdTest.start_l3fwd( + nodes, nodes[node], if1=if1, if2=if2, + lcores_list=cpu_dp, nb_cores=dp_count_int, + queue_nums=rxq_count_int, jumbo_frames=jumbo_frames, + tg_flip=tg_flip + ) + else: + message = f"Failed to start l3fwd at node {node}" + raise RuntimeError(message) @staticmethod def start_l3fwd( nodes, node, if1, if2, lcores_list, nb_cores, queue_nums, - jumbo_frames): + jumbo_frames, tg_flip): """ Execute the l3fwd on the dut_node. + L3fwd uses default IP forwarding table, but sorts ports by API address. + When that does not match the traffic profile (depends on topology), + the only way to fix is is to latch and recompile l3fwd app. + :param nodes: All the nodes info in the topology file. :param node: DUT node. :param if1: The test link interface 1. @@ -40,6 +116,7 @@ class L3fwdTest: :param queue_nums: The queues number for the NIC :param jumbo_frames: Indication if the jumbo frames are used (True) or not (False). + :param tg_flip: Whether TG ports are reordered. :type nodes: dict :type node: dict :type if1: str @@ -48,22 +125,24 @@ class L3fwdTest: :type nb_cores: str :type queue_nums: str :type jumbo_frames: bool + :type tg_flip: bool """ if node[u"type"] == NodeType.DUT: adj_mac0, adj_mac1, if_pci0, if_pci1 = L3fwdTest.get_adj_mac( - nodes, node, if1, if2 + nodes, node, if1, if2, tg_flip ) - list_cores = [int(item) for item in lcores_list.split(u",")] + lcores = [int(item) for item in lcores_list.split(u",")] # prepare the port config param nb_cores = int(nb_cores) index = 0 port_config = '' - for port in range(0, 2): + for port in range(0, NB_PORTS): for queue in range(0, int(queue_nums)): index = 0 if nb_cores == 1 else index - port_config += f"({port}, {queue}, {list_cores[index]})," + port_config += \ + f"({port}, {queue}, {lcores[index % NB_PORTS]})," index += 1 if jumbo_frames: @@ -77,7 +156,6 @@ class L3fwdTest: pmd_eth_dest_0=f"\\\"0,{adj_mac0}\\\"", pmd_eth_dest_1=f"\\\"1,{adj_mac1}\\\"", pmd_parse_ptype=True, - pmd_enable_jumbo=jumbo_frames, pmd_max_pkt_len=jumbo_frames ) else: @@ -98,20 +176,40 @@ class L3fwdTest: message = f"Failed to execute l3fwd test at node {node['host']}" exec_cmd_no_error(node, command, timeout=1800, message=message) + @staticmethod + def check_l3fwd(node): + """ + Execute the l3fwd check on the DUT node. + + :param node: DUT node. + :type node: dict + :raises RuntimeError: If the script "check_l3fwd.sh" fails. + """ + if node[u"type"] == NodeType.DUT: + command = f"{Constants.REMOTE_FW_DIR}/{Constants.RESOURCES_LIB_SH}"\ + f"/entry/check_l3fwd.sh" + message = "L3fwd not started properly" + exec_cmd_no_error(node, command, timeout=1800, message=message) @staticmethod - def get_adj_mac(nodes, node, if1, if2): + def get_adj_mac(nodes, node, if1, if2, tg_flip): """ Get adjacency MAC addresses of the DUT node. + Interfaces are re-ordered according to PCI address, + but the need to patch and recompile also depends on TG port order. + "tg_flip" signals whether TG ports are reordered. + :param nodes: All the nodes info in the topology file. :param node: DUT node. :param if1: The test link interface 1. :param if2: The test link interface 2. + :param tg_flip: Whether tg ports are reordered. :type nodes: dict :type node: dict :type if1: str :type if2: str + :type tg_flip: bool :returns: Returns MAC addresses of adjacency DUT nodes and PCI addresses. :rtype: str @@ -121,9 +219,19 @@ class L3fwdTest: if_pci0 = Topology.get_interface_pci_addr(node, if_key0) if_pci1 = Topology.get_interface_pci_addr(node, if_key1) + # Flipping routes logic: + # If TG and DUT ports are reordered -> flip + # If TG reordered and DUT not reordered -> don't flip + # If DUT reordered and TG not reordered -> don't flip + # If DUT and TG not reordered -> flip + # Detect which is the port 0. - if min(if_pci0, if_pci1) != if_pci0: + dut_flip = if_pci0 > if_pci1 + if dut_flip: if_key0, if_key1 = if_key1, if_key0 + if tg_flip: + L3fwdTest.patch_l3fwd(node, u"patch_l3fwd_flip_routes") + elif not tg_flip: L3fwdTest.patch_l3fwd(node, u"patch_l3fwd_flip_routes") adj_node0, adj_if_key0 = Topology.get_adjacent_node_and_interface(