aboutsummaryrefslogtreecommitdiffstats
path: root/resources/libraries/python/DPDK
diff options
context:
space:
mode:
authorPeter Mikus <pmikus@cisco.com>2020-04-17 12:38:09 +0000
committerPeter Mikus <pmikus@cisco.com>2020-04-23 12:36:54 +0000
commit54beb458703ff91e9f522f8af0a57722966f093e (patch)
tree5aa977fe9149e2d870ac87a35256783aeac60761 /resources/libraries/python/DPDK
parent5dc176ab31af5dff73be6dd5266169a7be19dd13 (diff)
Performance: DPDK refactor
+ Rework BASH scripts (more code to python). + Move BASH into libraries. + Allows RDMA usage. + Fix 9000B tests. + Rename confusing l2fwd -> testpmd. + Fix suite setup. + Fix PCI whitelist to not accidentally pickup wrong interface. + Fix deprecated DPDK cli arguments. - MLX5 jumbo are disabled on NIC (i will increase separately). https://jenkins.fd.io/job/csit-dpdk-perf-verify-master-2n-clx/6/console (l3fwd still broken) - MLX5 IMIX seems to be some TRex issue with IMIX for mlx5 (i will handle separately) Signed-off-by: Peter Mikus <pmikus@cisco.com> Change-Id: I31d1b67305fa247cb5e1f57e739d3ef30dc1a04b
Diffstat (limited to 'resources/libraries/python/DPDK')
-rw-r--r--resources/libraries/python/DPDK/DPDKTools.py123
-rw-r--r--resources/libraries/python/DPDK/L2fwdTest.py58
-rw-r--r--resources/libraries/python/DPDK/L3fwdTest.py140
-rw-r--r--resources/libraries/python/DPDK/TestpmdTest.py85
4 files changed, 215 insertions, 191 deletions
diff --git a/resources/libraries/python/DPDK/DPDKTools.py b/resources/libraries/python/DPDK/DPDKTools.py
index 868d2d886d..9bb89968d2 100644
--- a/resources/libraries/python/DPDK/DPDKTools.py
+++ b/resources/libraries/python/DPDK/DPDKTools.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2019 Cisco and/or its affiliates.
+# Copyright (c) 2020 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,12 +12,12 @@
# limitations under the License.
-"""This module implements initialization and cleanup of DPDK environment."""
+"""This module implements initialization and cleanup of DPDK framework."""
from robot.api import logger
from resources.libraries.python.Constants import Constants
-from resources.libraries.python.ssh import SSH, exec_cmd_no_error
+from resources.libraries.python.ssh import exec_cmd_no_error
from resources.libraries.python.topology import NodeType, Topology
@@ -28,84 +28,68 @@ class DPDKTools:
"""
@staticmethod
- def initialize_dpdk_environment(dut_node, dut_if1, dut_if2):
+ def initialize_dpdk_framework(node, if1, if2, nic_driver):
"""
- Initialize the DPDK test environment on the dut_node.
- Load the module uio and igb_uio, then bind the test NIC to the igb_uio.
-
- :param dut_node: Will init the DPDK on this node.
- :param dut_if1: DUT interface name.
- :param dut_if2: DUT interface name.
- :type dut_node: dict
- :type dut_if1: str
- :type dut_if2: str
- :raises RuntimeError: If it fails to bind the interfaces to igb_uio.
- """
- if dut_node[u"type"] == NodeType.DUT:
- pci_address1 = Topology.get_interface_pci_addr(dut_node, dut_if1)
- pci_address2 = Topology.get_interface_pci_addr(dut_node, dut_if2)
-
- ssh = SSH()
- ssh.connect(dut_node)
+ Initialize the DPDK framework on the DUT node. Bind interfaces to
+ driver.
- arch = Topology.get_node_arch(dut_node)
- cmd = f"{Constants.REMOTE_FW_DIR}/tests/dpdk/dpdk_scripts" \
- f"/init_dpdk.sh {pci_address1} {pci_address2} {arch}"
+ :param node: DUT node.
+ :param if1: DUT first interface name.
+ :param if2: DUT second interface name.
+ :param nic_driver: Interface driver.
+ :type node: dict
+ :type if1: str
+ :type if2: str
+ :type nic_driver: str
+ :raises RuntimeError: If it fails to bind the interfaces to driver.
+ """
+ if node[u"type"] == NodeType.DUT:
+ pci_address1 = Topology.get_interface_pci_addr(node, if1)
+ pci_address2 = Topology.get_interface_pci_addr(node, if2)
- ret_code, _, _ = ssh.exec_command_sudo(cmd, timeout=600)
- if ret_code != 0:
- raise RuntimeError(
- f"Failed to bind the interfaces to igb_uio at node "
- f"{dut_node['host']}"
- )
+ command = f"{Constants.REMOTE_FW_DIR}/{Constants.RESOURCES_LIB_SH}"\
+ f"/entry/init_dpdk.sh " \
+ f"{nic_driver} {pci_address1} {pci_address2}"
+ message = u"Initialize the DPDK failed!"
+ exec_cmd_no_error(node, command, timeout=600, message=message)
@staticmethod
- def cleanup_dpdk_environment(dut_node, dut_if1, dut_if2):
+ def cleanup_dpdk_framework(node, if1, if2):
"""
- Cleanup the DPDK test environment on the DUT node.
- Unbind the NIC from the igb_uio and bind them to the kernel driver.
-
- :param dut_node: Will cleanup the DPDK on this node.
- :param dut_if1: DUT interface name.
- :param dut_if2: DUT interface name.
- :type dut_node: dict
- :type dut_if1: str
- :type dut_if2: str
+ Cleanup the DPDK framework on the DUT node. Bind interfaces to
+ default driver specified in topology.
+
+ :param node: Will cleanup the DPDK on this node.
+ :param if1: DUT first interface name.
+ :param if2: DUT second interface name.
+ :type node: dict
+ :type if1: str
+ :type if2: str
:raises RuntimeError: If it fails to cleanup the dpdk.
"""
- if dut_node[u"type"] == NodeType.DUT:
- pci_address1 = Topology.get_interface_pci_addr(dut_node, dut_if1)
- if1_driver = Topology.get_interface_driver(dut_node, dut_if1)
- pci_address2 = Topology.get_interface_pci_addr(dut_node, dut_if2)
- if2_driver = Topology.get_interface_driver(dut_node, dut_if2)
-
- ssh = SSH()
- ssh.connect(dut_node)
-
- cmd = f"{Constants.REMOTE_FW_DIR}/tests/dpdk/dpdk_scripts" \
- f"/cleanup_dpdk.sh {if1_driver} {pci_address1} {if2_driver} " \
- f"{pci_address2}"
-
- ret_code, _, _ = ssh.exec_command_sudo(cmd, timeout=1200)
- if ret_code != 0:
- raise RuntimeError(
- f"Failed to cleanup the dpdk at node {dut_node[u'host']}"
- )
+ if node[u"type"] == NodeType.DUT:
+ pci_address1 = Topology.get_interface_pci_addr(node, if1)
+ pci_address2 = Topology.get_interface_pci_addr(node, if2)
+ # We are not supporting more than one driver yet.
+ nic_driver = Topology.get_interface_driver(node, if1)
+
+ command = f"{Constants.REMOTE_FW_DIR}/{Constants.RESOURCES_LIB_SH}"\
+ f"/entry/cleanup_dpdk.sh " \
+ f"{nic_driver} {pci_address1} {pci_address2}"
+ message = u"Cleanup the DPDK failed!"
+ exec_cmd_no_error(node, command, timeout=1200, message=message)
@staticmethod
- def install_dpdk_test(node):
+ def install_dpdk_framework(node):
"""
- Prepare the DPDK test environment
+ Prepare the DPDK framework on the DUT node.
- :param node: Dictionary created from topology
+ :param node: Node from topology file.
:type node: dict
- :returns: nothing
:raises RuntimeError: If command returns nonzero return code.
"""
- arch = Topology.get_node_arch(node)
-
- command = f"{Constants.REMOTE_FW_DIR}/tests/dpdk/dpdk_scripts" \
- f"/install_dpdk.sh {arch}"
+ command = f"{Constants.REMOTE_FW_DIR}/{Constants.RESOURCES_LIB_SH}" \
+ f"/entry/install_dpdk.sh"
message = u"Install the DPDK failed!"
exec_cmd_no_error(node, command, timeout=600, message=message)
@@ -116,14 +100,13 @@ class DPDKTools:
logger.info(f"DPDK Version: {stdout}")
@staticmethod
- def install_dpdk_test_on_all_duts(nodes):
+ def install_dpdk_framework_on_all_duts(nodes):
"""
- Prepare the DPDK test environment on all DUTs.
+ Prepare the DPDK framework on all DUTs.
:param nodes: Nodes from topology file.
:type nodes: dict
- :returns: nothing
"""
for node in list(nodes.values()):
if node[u"type"] == NodeType.DUT:
- DPDKTools.install_dpdk_test(node)
+ DPDKTools.install_dpdk_framework(node)
diff --git a/resources/libraries/python/DPDK/L2fwdTest.py b/resources/libraries/python/DPDK/L2fwdTest.py
deleted file mode 100644
index 76d1dcb362..0000000000
--- a/resources/libraries/python/DPDK/L2fwdTest.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (c) 2020 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:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""This module implements functionality which sets L2 forwarding for DPDK on
-DUT nodes.
-"""
-
-from resources.libraries.python.Constants import Constants
-from resources.libraries.python.ssh import exec_cmd_no_error
-from resources.libraries.python.topology import NodeType
-
-
-class L2fwdTest:
- """Setup the DPDK for l2fwd performance test."""
-
- @staticmethod
- def start_the_l2fwd_test(
- node, cpu_cores, nb_cores, queue_nums, jumbo_frames,
- rxq_size=1024, txq_size=1024):
- """
- Execute the l2fwd on the DUT node.
-
- :param node: Will execute the l2fwd on this node.
- :param cpu_cores: The DPDK run cores.
- :param nb_cores: The cores number for the forwarding.
- :param queue_nums: The queues number for the NIC.
- :param jumbo_frames: Indication if the jumbo frames are used (True) or
- not (False).
- :param rxq_size: RXQ size. Default=1024.
- :param txq_size: TXQ size. Default=1024.
- :type node: dict
- :type cpu_cores: str
- :type nb_cores: str
- :type queue_nums: str
- :type jumbo_frames: bool
- :type rxq_size: int
- :type txq_size: int
- :raises RuntimeError: If the script "run_l2fwd.sh" fails.
- """
- if node[u"type"] == NodeType.DUT:
- jumbo = u"yes" if jumbo_frames else u"no"
- command = f"{Constants.REMOTE_FW_DIR}/tests/dpdk/dpdk_scripts" \
- f"/run_l2fwd.sh {cpu_cores} {nb_cores} {queue_nums} {jumbo} " \
- f"{rxq_size} {txq_size}"
-
- message = f"Failed to execute l2fwd test at node {node['host']}"
-
- exec_cmd_no_error(node, command, timeout=1800, message=message)
diff --git a/resources/libraries/python/DPDK/L3fwdTest.py b/resources/libraries/python/DPDK/L3fwdTest.py
index 18becabd9b..46697cfdd5 100644
--- a/resources/libraries/python/DPDK/L3fwdTest.py
+++ b/resources/libraries/python/DPDK/L3fwdTest.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2019 Cisco and/or its affiliates.
+# Copyright (c) 2020 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:
@@ -16,7 +16,8 @@ This module exists to provide the l3fwd test for DPDK on topology nodes.
"""
from resources.libraries.python.Constants import Constants
-from resources.libraries.python.ssh import SSH
+from resources.libraries.python.DpdkUtil import DpdkUtil
+from resources.libraries.python.ssh import exec_cmd_no_error
from resources.libraries.python.topology import NodeType, Topology
@@ -24,33 +25,33 @@ class L3fwdTest:
"""Test the DPDK l3fwd performance."""
@staticmethod
- def start_the_l3fwd_test(
- nodes_info, dut_node, dut_if1, dut_if2, nb_cores, lcores_list,
- queue_nums, jumbo_frames):
+ def start_l3fwd(
+ nodes, node, if1, if2, lcores_list, nb_cores, queue_nums,
+ jumbo_frames):
"""
Execute the l3fwd on the dut_node.
- :param nodes_info: All the nodes info in the topology file.
- :param dut_node: Will execute the l3fwd on this node
- :param dut_if1: The test link interface 1.
- :param dut_if2: The test link interface 2.
- :param nb_cores: The cores number for the forwarding
+ :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 lcores_list: The lcore list string for the l3fwd routing
+ :param nb_cores: The cores number for the forwarding
:param queue_nums: The queues number for the NIC
:param jumbo_frames: Indication if the jumbo frames are used (True) or
not (False).
- :type nodes_info: dict
- :type dut_node: dict
- :type dut_if1: str
- :type dut_if2: str
- :type nb_cores: str
+ :type nodes: dict
+ :type node: dict
+ :type if1: str
+ :type if2: str
:type lcores_list: str
+ :type nb_cores: str
:type queue_nums: str
:type jumbo_frames: bool
"""
- if dut_node[u"type"] == NodeType.DUT:
- adj_mac0, adj_mac1 = L3fwdTest.get_adj_mac(
- nodes_info, dut_node, dut_if1, dut_if2
+ if node[u"type"] == NodeType.DUT:
+ adj_mac0, adj_mac1, if_pci0, if_pci1 = L3fwdTest.get_adj_mac(
+ nodes, node, if1, if2
)
list_cores = [int(item) for item in lcores_list.split(u",")]
@@ -65,79 +66,92 @@ class L3fwdTest:
port_config += f"({port}, {queue}, {list_cores[index]}),"
index += 1
- ssh = SSH()
- ssh.connect(dut_node)
+ if jumbo_frames:
+ l3fwd_args = DpdkUtil.get_l3fwd_args(
+ eal_corelist=f"0,{lcores_list}",
+ eal_driver=False,
+ eal_pci_whitelist0=if_pci0,
+ eal_pci_whitelist1=if_pci1,
+ eal_in_memory=True,
+ pmd_config=f"\\\"{port_config.rstrip(u',')}\\\"",
+ 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:
+ l3fwd_args = DpdkUtil.get_l3fwd_args(
+ eal_corelist=f"0,{lcores_list}",
+ eal_driver=False,
+ eal_pci_whitelist0=if_pci0,
+ eal_pci_whitelist1=if_pci1,
+ eal_in_memory=True,
+ pmd_config=f"\\\"{port_config.rstrip(u',')}\\\"",
+ pmd_eth_dest_0=f"\\\"0,{adj_mac0}\\\"",
+ pmd_eth_dest_1=f"\\\"1,{adj_mac1}\\\"",
+ pmd_parse_ptype=True
+ )
- cmd = f"{Constants.REMOTE_FW_DIR}/tests/dpdk/dpdk_scripts" \
- f"/run_l3fwd.sh \"{lcores_list}\" " \
- f"\"{port_config.rstrip(u',')}\" " \
- f"{adj_mac0} {adj_mac1} {u'yes' if jumbo_frames else u'no'}"
+ command = f"{Constants.REMOTE_FW_DIR}/{Constants.RESOURCES_LIB_SH}"\
+ f"/entry/run_l3fwd.sh \"{l3fwd_args} -P -L -p 0x3\""
+ message = f"Failed to execute l3fwd test at node {node['host']}"
+ exec_cmd_no_error(node, command, timeout=1800, message=message)
- ret_code, _, _ = ssh.exec_command_sudo(cmd, timeout=1800)
- if ret_code != 0:
- raise Exception(
- f"Failed to execute l3fwd test at node {dut_node[u'host']}"
- )
@staticmethod
- def get_adj_mac(nodes_info, dut_node, dut_if1, dut_if2):
+ def get_adj_mac(nodes, node, if1, if2):
"""
Get adjacency MAC addresses of the DUT node.
- :param nodes_info: All the nodes info in the topology file.
- :param dut_node: Will execute the l3fwd on this node
- :param dut_if1: The test link interface 1.
- :param dut_if2: The test link interface 2.
- :type nodes_info: dict
- :type dut_node: dict
- :type dut_if1: str
- :type dut_if2: str
- :returns: Returns MAC addresses of adjacency DUT nodes.
+ :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.
+ :type nodes: dict
+ :type node: dict
+ :type if1: str
+ :type if2: str
+ :returns: Returns MAC addresses of adjacency DUT nodes and PCI
+ addresses.
:rtype: str
"""
- if_key0 = dut_if1
- if_key1 = dut_if2
- if_pci0 = Topology.get_interface_pci_addr(dut_node, if_key0)
- if_pci1 = Topology.get_interface_pci_addr(dut_node, if_key1)
+ if_key0 = if1
+ if_key1 = if2
+ if_pci0 = Topology.get_interface_pci_addr(node, if_key0)
+ if_pci1 = Topology.get_interface_pci_addr(node, if_key1)
- # detect which is the port 0
+ # Detect which is the port 0.
if min(if_pci0, if_pci1) != if_pci0:
if_key0, if_key1 = if_key1, if_key0
- L3fwdTest.patch_l3fwd(dut_node, u"patch_l3fwd_flip_routes")
+ L3fwdTest.patch_l3fwd(node, u"patch_l3fwd_flip_routes")
adj_node0, adj_if_key0 = Topology.get_adjacent_node_and_interface(
- nodes_info, dut_node, if_key0
+ nodes, node, if_key0
)
adj_node1, adj_if_key1 = Topology.get_adjacent_node_and_interface(
- nodes_info, dut_node, if_key1
+ nodes, node, if_key1
)
-
+ if_pci0 = Topology.get_interface_pci_addr(node, if_key0)
+ if_pci1 = Topology.get_interface_pci_addr(node, if_key1)
adj_mac0 = Topology.get_interface_mac(adj_node0, adj_if_key0)
adj_mac1 = Topology.get_interface_mac(adj_node1, adj_if_key1)
- return adj_mac0, adj_mac1
+ return adj_mac0, adj_mac1, if_pci0, if_pci1
@staticmethod
def patch_l3fwd(node, patch):
"""
Patch l3fwd application and recompile.
- :param node: Dictionary created from topology.
+ :param node: DUT node.
:param patch: Patch to apply.
:type node: dict
:type patch: str
:raises RuntimeError: Patching of l3fwd failed.
"""
- arch = Topology.get_node_arch(node)
-
- ssh = SSH()
- ssh.connect(node)
-
- ret_code, _, _ = ssh.exec_command(
- f"{Constants.REMOTE_FW_DIR}/tests/dpdk/dpdk_scripts/patch_l3fwd.sh "
- f"{arch} {Constants.REMOTE_FW_DIR}/tests/dpdk/dpdk_scripts/{patch}",
- timeout=600
- )
-
- if ret_code != 0:
- raise RuntimeError(u"Patch of l3fwd failed.")
+ command = f"{Constants.REMOTE_FW_DIR}/{Constants.RESOURCES_LIB_SH}"\
+ f"/entry/patch_l3fwd.sh " \
+ f"{Constants.REMOTE_FW_DIR}/{Constants.RESOURCES_LIB_SH}/{patch}"
+ message = f"Failed to patch l3fwd at node {node['host']}"
+ exec_cmd_no_error(node, command, timeout=1800, message=message)
diff --git a/resources/libraries/python/DPDK/TestpmdTest.py b/resources/libraries/python/DPDK/TestpmdTest.py
new file mode 100644
index 0000000000..1eccd7addf
--- /dev/null
+++ b/resources/libraries/python/DPDK/TestpmdTest.py
@@ -0,0 +1,85 @@
+# Copyright (c) 2020 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:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""This module implements functionality which sets L2 forwarding for DPDK on
+DUT nodes.
+"""
+
+from resources.libraries.python.Constants import Constants
+from resources.libraries.python.DpdkUtil import DpdkUtil
+from resources.libraries.python.ssh import exec_cmd_no_error
+from resources.libraries.python.topology import NodeType, Topology
+
+
+class TestpmdTest:
+ """Setup the DPDK for testpmd performance test."""
+
+ @staticmethod
+ def start_testpmd(
+ node, if1, if2, lcores_list, nb_cores, queue_nums,
+ jumbo_frames, rxq_size=1024, txq_size=1024):
+ """
+ Execute the testpmd on the DUT node.
+
+ :param node: DUT node.
+ :param if1: The test link interface 1.
+ :param if2: The test link interface 2.
+ :param lcores_list: The DPDK run cores.
+ :param nb_cores: The cores number for the forwarding.
+ :param queue_nums: The queues number for the NIC.
+ :param jumbo_frames: Indication if the jumbo frames are used (True) or
+ not (False).
+ :param rxq_size: RXQ size. Default=1024.
+ :param txq_size: TXQ size. Default=1024.
+ :type node: dict
+ :type if1: str
+ :type if2: str
+ :type lcores_list: str
+ :type nb_cores: str
+ :type queue_nums: str
+ :type jumbo_frames: bool
+ :type rxq_size: int
+ :type txq_size: int
+ :raises RuntimeError: If the script "run_testpmd.sh" fails.
+ """
+ if node[u"type"] == NodeType.DUT:
+ if_pci0 = Topology.get_interface_pci_addr(node, if1)
+ if_pci1 = Topology.get_interface_pci_addr(node, if2)
+
+ pmd_max_pkt_len = u"9200" if jumbo_frames else u"1518"
+ testpmd_args = DpdkUtil.get_testpmd_args(
+ eal_corelist=f"0,{lcores_list}",
+ eal_driver=False,
+ eal_pci_whitelist0=if_pci0,
+ eal_pci_whitelist1=if_pci1,
+ eal_in_memory=True,
+ pmd_num_mbufs=16384,
+ pmd_fwd_mode=u"io",
+ pmd_nb_ports=u"2",
+ pmd_portmask=u"0x3",
+ pmd_max_pkt_len=pmd_max_pkt_len,
+ pmd_mbuf_size=u"16384",
+ pmd_rxd=rxq_size,
+ pmd_txd=txq_size,
+ pmd_rxq=queue_nums,
+ pmd_txq=queue_nums,
+ pmd_nb_cores=nb_cores,
+ pmd_disable_link_check=True,
+ pmd_auto_start=True,
+ pmd_numa=True
+ )
+
+ command = f"{Constants.REMOTE_FW_DIR}/{Constants.RESOURCES_LIB_SH}"\
+ f"/entry/run_testpmd.sh \"{testpmd_args}\""
+ message = f"Failed to execute testpmd at node {node['host']}"
+ exec_cmd_no_error(node, command, timeout=1800, message=message)