Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/111377/?format=api
http://patches.dpdk.org/api/patches/111377/?format=api", "web_url": "http://patches.dpdk.org/project/dts/patch/20220519080016.1815932-1-songx.jiale@intel.com/", "project": { "id": 3, "url": "http://patches.dpdk.org/api/projects/3/?format=api", "name": "DTS", "link_name": "dts", "list_id": "dts.dpdk.org", "list_email": "dts@dpdk.org", "web_url": "", "scm_url": "git://dpdk.org/tools/dts", "webscm_url": "http://git.dpdk.org/tools/dts/", "list_archive_url": "https://inbox.dpdk.org/dts", "list_archive_url_format": "https://inbox.dpdk.org/dts/{}", "commit_url_format": "" }, "msgid": "<20220519080016.1815932-1-songx.jiale@intel.com>", "list_archive_url": "https://inbox.dpdk.org/dts/20220519080016.1815932-1-songx.jiale@intel.com", "date": "2022-05-19T08:00:15", "name": "[V4,1/2] tests/multiprocess_iavf: add vf multiprocess test case", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "75cc81de35a97ffa16f4a0897f1c863e12ddb9cd", "submitter": { "id": 2352, "url": "http://patches.dpdk.org/api/people/2352/?format=api", "name": "Jiale, SongX", "email": "songx.jiale@intel.com" }, "delegate": null, "mbox": "http://patches.dpdk.org/project/dts/patch/20220519080016.1815932-1-songx.jiale@intel.com/mbox/", "series": [ { "id": 23027, "url": "http://patches.dpdk.org/api/series/23027/?format=api", "web_url": "http://patches.dpdk.org/project/dts/list/?series=23027", "date": "2022-05-19T08:00:15", "name": "[V4,1/2] tests/multiprocess_iavf: add vf multiprocess test case", "version": 4, "mbox": "http://patches.dpdk.org/series/23027/mbox/" } ], "comments": "http://patches.dpdk.org/api/patches/111377/comments/", "check": "pending", "checks": "http://patches.dpdk.org/api/patches/111377/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<dts-bounces@dpdk.org>", "X-Original-To": "patchwork@inbox.dpdk.org", "Delivered-To": "patchwork@inbox.dpdk.org", "Received": [ "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 505CAA0503;\n\tThu, 19 May 2022 10:00:30 +0200 (CEST)", "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 495B740156;\n\tThu, 19 May 2022 10:00:30 +0200 (CEST)", "from mga04.intel.com (mga04.intel.com [192.55.52.120])\n by mails.dpdk.org (Postfix) with ESMTP id 63C8240140\n for <dts@dpdk.org>; Thu, 19 May 2022 10:00:28 +0200 (CEST)", "from orsmga005.jf.intel.com ([10.7.209.41])\n by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 19 May 2022 01:00:27 -0700", "from unknown (HELO daily-regression-131.intel.com)\n ([10.239.251.131])\n by orsmga005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 19 May 2022 01:00:24 -0700" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n t=1652947228; x=1684483228;\n h=from:to:cc:subject:date:message-id:mime-version:\n content-transfer-encoding;\n bh=uacPRidC5OjqgA2Ll7IFFvkAOhwjg0szcMoAUUwjPqA=;\n b=AnciQ9qpNomqzyKfb8ftuHNUY6zXcEDbLuMWxbrF3Lhc9zumf6NTDLpf\n K75EujuJCr2UMhkBCjDN3sfgRRVHe2zFBfXGfJ+dkKNtFxRtULYKjL0Fs\n eBLTz8QWpMKTTSzwThi2kgyh4lCS+IcRD8L/qHc22lVfFHgRQGG+ir0fI\n 966glm0V5ruRPrlSkFTINJ7RQHsvlf7wPIKn1F7Ss2S0ohpgqkgeXs+uS\n MorpOeCkPKeoLlpxW9s/2aa2dvandUR6E7dXqu3CNrPW/EdWs2Cr5BVAJ\n jiUvAO/3vPXcA3WN/7IV5JER3RifeGDFyPxWJLH2z4SK0X9FTarfmF/zt Q==;", "X-IronPort-AV": [ "E=McAfee;i=\"6400,9594,10351\"; a=\"270903580\"", "E=Sophos;i=\"5.91,237,1647327600\"; d=\"scan'208\";a=\"270903580\"", "E=Sophos;i=\"5.91,237,1647327600\"; d=\"scan'208\";a=\"742783582\"" ], "From": "Jiale Song <songx.jiale@intel.com>", "To": "dts@dpdk.org", "Cc": "Jiale Song <songx.jiale@intel.com>", "Subject": "[dts] [PATCH V4 1/2] tests/multiprocess_iavf: add vf multiprocess\n test case", "Date": "Thu, 19 May 2022 16:00:15 +0800", "Message-Id": "<20220519080016.1815932-1-songx.jiale@intel.com>", "X-Mailer": "git-send-email 2.25.1", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-BeenThere": "dts@dpdk.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "test suite reviews and discussions <dts.dpdk.org>", "List-Unsubscribe": "<https://mails.dpdk.org/options/dts>,\n <mailto:dts-request@dpdk.org?subject=unsubscribe>", "List-Archive": "<http://mails.dpdk.org/archives/dts/>", "List-Post": "<mailto:dts@dpdk.org>", "List-Help": "<mailto:dts-request@dpdk.org?subject=help>", "List-Subscribe": "<https://mails.dpdk.org/listinfo/dts>,\n <mailto:dts-request@dpdk.org?subject=subscribe>", "Errors-To": "dts-bounces@dpdk.org" }, "content": "Signed-off-by: Jiale Song <songx.jiale@intel.com>\n---\n tests/TestSuite_multiprocess_iavf.py | 1946 ++++++++++++++++++++++++++\n 1 file changed, 1946 insertions(+)\n create mode 100644 tests/TestSuite_multiprocess_iavf.py", "diff": "diff --git a/tests/TestSuite_multiprocess_iavf.py b/tests/TestSuite_multiprocess_iavf.py\nnew file mode 100644\nindex 00000000..2e301367\n--- /dev/null\n+++ b/tests/TestSuite_multiprocess_iavf.py\n@@ -0,0 +1,1946 @@\n+# BSD LICENSE\n+#\n+# Copyright(c) 2022 Intel Corporation. All rights reserved.\n+# All rights reserved.\n+#\n+# Redistribution and use in source and binary forms, with or without\n+# modification, are permitted provided that the following conditions\n+# are met:\n+#\n+# * Redistributions of source code must retain the above copyright\n+# notice, this list of conditions and the following disclaimer.\n+# * Redistributions in binary form must reproduce the above copyright\n+# notice, this list of conditions and the following disclaimer in\n+# the documentation and/or other materials provided with the\n+# distribution.\n+# * Neither the name of Intel Corporation nor the names of its\n+# contributors may be used to endorse or promote products derived\n+# from this software without specific prior written permission.\n+#\n+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+\n+\"\"\"\n+DPDK Test suite.\n+Multi-process Test.\n+\"\"\"\n+\n+import copy\n+import os\n+import random\n+import re\n+import time\n+import traceback\n+from collections import OrderedDict\n+\n+import framework.utils as utils\n+from framework.exception import VerifyFailure\n+from framework.packet import Packet\n+from framework.pktgen import PacketGeneratorHelper\n+from framework.pmd_output import PmdOutput\n+from framework.test_case import TestCase, check_supported_nic\n+from framework.utils import GREEN, RED\n+\n+from .rte_flow_common import FdirProcessing as fdirprocess\n+from .rte_flow_common import RssProcessing as rssprocess\n+\n+executions = []\n+\n+\n+class TestMultiprocess(TestCase):\n+\n+ support_nic = [\"ICE_100G-E810C_QSFP\", \"ICE_25G-E810C_SFP\", \"ICE_25G-E810_XXV_SFP\"]\n+\n+ def set_up_all(self):\n+ \"\"\"\n+ Run at the start of each test suite.\n+\n+ Multiprocess prerequisites.\n+ Requirements:\n+ OS is not freeBSD\n+ DUT core number >= 4\n+ multi_process build pass\n+ \"\"\"\n+ # self.verify('bsdapp' not in self.target, \"Multiprocess not support freebsd\")\n+\n+ self.verify(len(self.dut.get_all_cores()) >= 4, \"Not enough Cores\")\n+ self.dut_ports = self.dut.get_ports()\n+ self.pkt = Packet()\n+ self.socket = self.dut.get_numa_id(self.dut_ports[0])\n+ extra_option = \"-Dexamples='multi_process/client_server_mp/mp_server,multi_process/client_server_mp/mp_client,multi_process/simple_mp,multi_process/symmetric_mp'\"\n+ self.dut.build_install_dpdk(target=self.target, extra_options=extra_option)\n+ self.app_mp_client = self.dut.apps_name[\"mp_client\"]\n+ self.app_mp_server = self.dut.apps_name[\"mp_server\"]\n+ self.app_simple_mp = self.dut.apps_name[\"simple_mp\"]\n+ self.app_symmetric_mp = self.dut.apps_name[\"symmetric_mp\"]\n+\n+ executions.append({\"nprocs\": 1, \"cores\": \"1S/1C/1T\", \"pps\": 0})\n+ executions.append({\"nprocs\": 2, \"cores\": \"1S/1C/2T\", \"pps\": 0})\n+ executions.append({\"nprocs\": 2, \"cores\": \"1S/2C/1T\", \"pps\": 0})\n+ executions.append({\"nprocs\": 4, \"cores\": \"1S/2C/2T\", \"pps\": 0})\n+ executions.append({\"nprocs\": 4, \"cores\": \"1S/4C/1T\", \"pps\": 0})\n+ executions.append({\"nprocs\": 8, \"cores\": \"1S/4C/2T\", \"pps\": 0})\n+\n+ self.eal_param = \"\"\n+ for i in self.dut_ports:\n+ self.eal_param += \" -a %s\" % self.dut.ports_info[i][\"pci\"]\n+\n+ self.eal_para = self.dut.create_eal_parameters(cores=\"1S/2C/1T\")\n+ # start new session to run secondary\n+ self.session_secondary = self.dut.new_session()\n+\n+ # get dts output path\n+ if self.logger.log_path.startswith(os.sep):\n+ self.output_path = self.logger.log_path\n+ else:\n+ cur_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))\n+ self.output_path = os.sep.join([cur_path, self.logger.log_path])\n+ # create an instance to set stream field setting\n+ self.pktgen_helper = PacketGeneratorHelper()\n+ self.dport_info0 = self.dut.ports_info[self.dut_ports[0]]\n+ self.pci0 = self.dport_info0[\"pci\"]\n+ self.tester_ifaces = [\n+ self.tester.get_interface(self.dut.ports_map[port])\n+ for port in self.dut_ports\n+ ]\n+ self.rxq = 1\n+ self.session_list = []\n+ self.logfmt = \"*\" * 20\n+\n+ def set_up(self):\n+ \"\"\"\n+ Run before each test case.\n+ \"\"\"\n+ pass\n+\n+ def launch_multi_testpmd(self, proc_type, queue_num, process_num, **kwargs):\n+ self.session_list = [\n+ self.dut.new_session(\"process_{}\".format(i)) for i in range(process_num)\n+ ]\n+ self.pmd_output_list = [\n+ PmdOutput(self.dut, self.session_list[i]) for i in range(process_num)\n+ ]\n+ self.dut.init_reserved_core()\n+ proc_type_list = []\n+ self.out_list = []\n+ if isinstance(proc_type, list):\n+ proc_type_list = copy.deepcopy(proc_type)\n+ proc_type = proc_type_list[0]\n+ for i in range(process_num):\n+ cores = self.dut.get_reserved_core(\"2C\", socket=0)\n+ if i != 0 and proc_type_list:\n+ proc_type = proc_type_list[1]\n+ eal_param = \"--proc-type={} -a {} --log-level=ice,7\".format(\n+ proc_type, self.pci0\n+ )\n+ param = \"--rxq={0} --txq={0} --num-procs={1} --proc-id={2}\".format(\n+ queue_num, process_num, i\n+ )\n+ if kwargs.get(\"options\") is not None:\n+ param = \"\".join([param, kwargs.get(\"options\")])\n+ out = self.pmd_output_list[i].start_testpmd(\n+ cores=cores,\n+ eal_param=eal_param,\n+ param=param,\n+ timeout=kwargs.get(\"timeout\", 20),\n+ )\n+ self.out_list.append(out)\n+ self.pmd_output_list[i].execute_cmd(\"set fwd rxonly\")\n+ self.pmd_output_list[i].execute_cmd(\"set verbose 1\")\n+ self.pmd_output_list[i].execute_cmd(\"start\")\n+ self.pmd_output_list[i].execute_cmd(\"clear port stats all\")\n+\n+ def get_pkt_statistic_process(self, out, **kwargs):\n+ \"\"\"\n+ :param out: information received by testpmd process after sending packets and port statistics\n+ :return: forward statistic dict, eg: {'rx-packets':1, 'tx-packets:0, 'tx-dropped':1}\n+ \"\"\"\n+ p = re.compile(\n+ r\"Forward\\s+Stats\\s+for\\s+RX\\s+Port=\\s+{}/Queue=([\\s\\d+]\\d+)\\s+.*\\n.*RX-packets:\\s+(\\d+)\\s+TX-packets:\\s+(\\d+)\\s+TX-dropped:\\s+(\\d+)\\s\".format(\n+ kwargs.get(\"port_id\")\n+ )\n+ )\n+ item_name = [\"rx-packets\", \"tx-packets\", \"tx-dropped\"]\n+ statistic = p.findall(out)\n+ if statistic:\n+ rx_pkt_total, tx_pkt_total, tx_drop_total = 0, 0, 0\n+ queue_set = set()\n+ for item in statistic:\n+ queue, rx_pkt, tx_pkt, tx_drop = map(int, item)\n+ queue_set.add(queue)\n+ rx_pkt_total += rx_pkt\n+ tx_pkt_total += tx_pkt\n+ tx_drop_total += tx_drop\n+ static_dict = {\n+ k: v\n+ for k, v in zip(item_name, [rx_pkt_total, tx_pkt_total, tx_drop_total])\n+ }\n+ static_dict[\"queue\"] = queue_set\n+ return static_dict\n+ else:\n+ raise Exception(\"got wrong output, not match pattern {}\".format(p.pattern))\n+\n+ def random_packet(self, pkt_num):\n+ pkt = Packet()\n+ pkt.generate_random_pkts(\n+ pktnum=pkt_num,\n+ dstmac=\"00:11:22:33:44:55\",\n+ )\n+ pkt.send_pkt(crb=self.tester, tx_port=self.tester_ifaces[0], count=1)\n+\n+ def specify_packet(self, que_num):\n+ # create rule to set queue as one of each process queues\n+ rule_str = \"flow create 0 ingress pattern eth / ipv4 src is 192.168.{0}.3 / end actions queue index {0} / end\"\n+ rules = [rule_str.format(i) for i in range(que_num)]\n+ fdirprocess(\n+ self, self.pmd_output_list[0], self.tester_ifaces, rxq=que_num\n+ ).create_rule(rules)\n+ # send 1 packet for each queue,the number of packets should be received by each process is (queue_num/proc_num)\n+ pkt = Packet()\n+ pkt_num = que_num\n+ self.logger.info(\"packet num:{}\".format(pkt_num))\n+ packets = [\n+ 'Ether(dst=\"00:11:22:33:44:55\") / IP(src=\"192.168.{0}.3\", dst=\"192.168.0.21\") / Raw(\"x\" * 80)'.format(\n+ i\n+ )\n+ for i in range(pkt_num)\n+ ]\n+ pkt.update_pkt(packets)\n+ pkt.send_pkt(crb=self.tester, tx_port=self.tester_ifaces[0], count=1)\n+\n+ def _multiprocess_data_pass(self, case):\n+ que_num, proc_num = case.get(\"queue_num\"), case.get(\"proc_num\")\n+ pkt_num = case.setdefault(\"pkt_num\", que_num)\n+ step = int(que_num / proc_num)\n+ proc_queue = [set(range(i, i + step)) for i in range(0, que_num, step)]\n+ queue_dict = {\n+ k: v\n+ for k, v in zip(\n+ [\"process_{}\".format(i) for i in range(que_num)], proc_queue\n+ )\n+ }\n+ # start testpmd multi-process\n+ self.launch_multi_testpmd(\n+ proc_type=case.get(\"proc_type\"), queue_num=que_num, process_num=proc_num\n+ )\n+ # send random or specify packets\n+ packet_func = getattr(self, case.get(\"packet_type\") + \"_packet\")\n+ packet_func(pkt_num)\n+ # get output for each process\n+ process_static = {}\n+ for i in range(len(self.pmd_output_list)):\n+ out = self.pmd_output_list[i].execute_cmd(\"stop\")\n+ static = self.get_pkt_statistic_process(out, port_id=0)\n+ process_static[\"process_{}\".format(i)] = static\n+ self.logger.info(\"process output static:{}\".format(process_static))\n+ # check whether each process receives packet, and ecah process receives packets with the corresponding queue\n+ for k, v in process_static.items():\n+ self.verify(\n+ v.get(\"rx-packets\") > 0,\n+ \"fail:process:{} does not receive packet\".format(k),\n+ )\n+ self.verify(\n+ v.get(\"queue\").issubset(queue_dict.get(k)),\n+ \"fail: {} is not a subset of {}, \"\n+ \"process should use its own queues\".format(\n+ v.get(\"queue\"), queue_dict.get(k)\n+ ),\n+ )\n+ self.logger.info(\"pass:each process receives packets and uses its own queue\")\n+ # check whether the sum of packets received by all processes is equal to the number of packets sent\n+ received_pkts = sum(\n+ int(v.get(\"rx-packets\", 0)) for v in process_static.values()\n+ )\n+ self.verify(\n+ received_pkts == pkt_num,\n+ \"the number of packets received is not equal to packets sent,\"\n+ \"send packet:{}, received packet:{}\".format(pkt_num, received_pkts),\n+ )\n+ self.logger.info(\n+ \"pass:the number of packets received is {}, equal to packets sent\".format(\n+ received_pkts\n+ )\n+ )\n+\n+ def check_rss(self, out, **kwargs):\n+ \"\"\"\n+ check whether the packet directed by rss or not according to the specified parameters\n+ :param out: information received by testpmd after sending packets and port statistics\n+ :param kwargs: some specified parameters, such as: rxq, stats\n+ :return: queue value list\n+ usage:\n+ check_rss(out, rxq=rxq, stats=stats)\n+ \"\"\"\n+ self.logger.info(\"{0} check rss {0}\".format(self.logfmt))\n+ rxq = kwargs.get(\"rxq\")\n+ p = re.compile(\"RSS\\shash=(\\w+)\\s-\\sRSS\\squeue=(\\w+)\")\n+ pkt_info = p.findall(out)\n+ self.verify(\n+ pkt_info,\n+ \"no information matching the pattern was found,pattern:{}\".format(\n+ p.pattern\n+ ),\n+ )\n+ pkt_queue = set([int(i[1], 16) for i in pkt_info])\n+ if kwargs.get(\"stats\"):\n+ self.verify(\n+ all([int(i[0], 16) % rxq == int(i[1], 16) for i in pkt_info]),\n+ \"some pkt not directed by rss.\",\n+ )\n+ self.logger.info((GREEN(\"pass: all pkts directed by rss\")))\n+ else:\n+ self.verify(\n+ not any([int(i[0], 16) % rxq == int(i[1], 16) for i in pkt_info]),\n+ \"some pkt directed by rss, expect not directed by rss\",\n+ )\n+ self.logger.info((GREEN(\"pass: no pkt directed by rss\")))\n+ return pkt_queue\n+\n+ def check_mark_id(self, out, check_param, **kwargs):\n+ \"\"\"\n+ verify that the mark ID matches the expected value\n+ :param out: information received by testpmd after sending packets\n+ :param check_param: check item name and value, eg\n+ \"check_param\": {\"port_id\": 0, \"mark_id\": 1}\n+ :param kwargs: some specified parameters,eg: stats\n+ :return: None\n+ usage:\n+ check_mark_id(out, check_param, stats=stats)\n+ \"\"\"\n+ self.logger.info(\"{0} check mark id {0}\".format(self.logfmt))\n+ fdir_scanner = re.compile(\"FDIR matched ID=(0x\\w+)\")\n+ all_mark = fdir_scanner.findall(out)\n+ stats = kwargs.get(\"stats\")\n+ if stats:\n+ mark_list = set(int(i, 16) for i in all_mark)\n+ self.verify(\n+ all([i == check_param[\"mark_id\"] for i in mark_list]) and mark_list,\n+ \"failed: some packet mark id of {} not match expect {}\".format(\n+ mark_list, check_param[\"mark_id\"]\n+ ),\n+ )\n+ self.logger.info((GREEN(\"pass: all packets mark id are matched \")))\n+ else:\n+ # for mismatch packet,verify no mark id in output of received packet\n+ self.verify(\n+ not all_mark, \"mark id {} in output, expect no mark id\".format(all_mark)\n+ )\n+ self.logger.info((GREEN(\"pass: no mark id in output\")))\n+\n+ def check_drop(self, out, **kwargs):\n+ \"\"\"\n+ check the drop number of packets according to the specified parameters\n+ :param out: information received by testpmd after sending packets and port statistics\n+ :param kwargs: some specified parameters, such as: pkt_num, port_id, stats\n+ :return: None\n+ usage:\n+ chek_drop(out, pkt_num=pkt_num, port_id=portid, stats=stats)\n+ \"\"\"\n+ self.logger.info(\"{0} check drop {0}\".format(self.logfmt))\n+ pkt_num = kwargs.get(\"pkt_num\")\n+ stats = kwargs.get(\"stats\")\n+ res = self.get_pkt_statistic(out, **kwargs)\n+ self.verify(\n+ pkt_num == res[\"rx-total\"],\n+ \"failed: get wrong amount of packet {}, expected {}\".format(\n+ res[\"rx-total\"], pkt_num\n+ ),\n+ )\n+ drop_packet_num = res[\"rx-dropped\"]\n+ if stats:\n+ self.verify(\n+ drop_packet_num == pkt_num,\n+ \"failed: {} packet dropped,expect {} dropped\".format(\n+ drop_packet_num, pkt_num\n+ ),\n+ )\n+ self.logger.info(\n+ (\n+ GREEN(\n+ \"pass: drop packet number {} is matched\".format(drop_packet_num)\n+ )\n+ )\n+ )\n+ else:\n+ self.verify(\n+ drop_packet_num == 0 and res[\"rx-packets\"] == pkt_num,\n+ \"failed: {} packet dropped, expect 0 packet dropped\".format(\n+ drop_packet_num\n+ ),\n+ )\n+ self.logger.info(\n+ (\n+ GREEN(\n+ \"pass: drop packet number {} is matched\".format(drop_packet_num)\n+ )\n+ )\n+ )\n+\n+ @staticmethod\n+ def get_pkt_statistic(out, **kwargs):\n+ \"\"\"\n+ :param out: information received by testpmd after sending packets and port statistics\n+ :return: rx statistic dict, eg: {'rx-packets':1, 'rx-dropped':0, 'rx-total':1}\n+ \"\"\"\n+ p = re.compile(\n+ r\"Forward\\sstatistics\\s+for\\s+port\\s+{}\\s+.*\\n.*RX-packets:\\s(\\d+)\\s+RX-dropped:\\s(\\d+)\\s+RX-total:\\s(\\d+)\\s\".format(\n+ kwargs.get(\"port_id\")\n+ )\n+ )\n+ item_name = [\"rx-packets\", \"rx-dropped\", \"rx-total\"]\n+ statistic = p.findall(out)\n+ if statistic:\n+ static_dict = {\n+ k: v for k, v in zip(item_name, list(map(int, list(statistic[0]))))\n+ }\n+ return static_dict\n+ else:\n+ raise Exception(\n+ \"got wrong output, not match pattern {}\".format(p.pattern).replace(\n+ \"\\\\\\\\\", \"\\\\\"\n+ )\n+ )\n+\n+ def send_pkt_get_output(\n+ self, instance_obj, pkts, port_id=0, count=1, interval=0, get_stats=False\n+ ):\n+ instance_obj.pmd_output.execute_cmd(\"clear port stats all\")\n+ tx_port = self.tester_ifaces[port_id]\n+ self.logger.info(\"----------send packet-------------\")\n+ self.logger.info(\"{}\".format(pkts))\n+ if not isinstance(pkts, list):\n+ pkts = [pkts]\n+ self.pkt.update_pkt(pkts)\n+ self.pkt.send_pkt(\n+ crb=self.tester,\n+ tx_port=tx_port,\n+ count=count,\n+ interval=interval,\n+ )\n+ out1 = instance_obj.pmd_output.get_output(timeout=1)\n+ if get_stats:\n+ out2 = instance_obj.pmd_output.execute_cmd(\"show port stats all\")\n+ instance_obj.pmd_output.execute_cmd(\"stop\")\n+ else:\n+ out2 = instance_obj.pmd_output.execute_cmd(\"stop\")\n+ instance_obj.pmd_output.execute_cmd(\"start\")\n+ return \"\".join([out1, out2])\n+\n+ def check_pkt_num(self, out, **kwargs):\n+ \"\"\"\n+ check number of received packets matches the expected value\n+ :param out: information received by testpmd after sending packets and port statistics\n+ :param kwargs: some specified parameters, such as: pkt_num, port_id\n+ :return: rx statistic dict\n+ \"\"\"\n+ self.logger.info(\n+ \"{0} check pkt num for port:{1} {0}\".format(\n+ self.logfmt, kwargs.get(\"port_id\")\n+ )\n+ )\n+ pkt_num = kwargs.get(\"pkt_num\")\n+ res = self.get_pkt_statistic(out, **kwargs)\n+ res_num = res[\"rx-total\"]\n+ self.verify(\n+ res_num == pkt_num,\n+ \"fail: got wrong number of packets, expect pakcet number {}, got {}\".format(\n+ pkt_num, res_num\n+ ),\n+ )\n+ self.logger.info(\n+ (GREEN(\"pass: pkt num is {} same as expected\".format(pkt_num)))\n+ )\n+ return res\n+\n+ def check_queue(self, out, check_param, **kwargs):\n+ \"\"\"\n+ verify that queue value matches the expected value\n+ :param out: information received by testpmd after sending packets and port statistics\n+ :param check_param: check item name and value, eg\n+ \"check_param\": {\"port_id\": 0, \"queue\": 2}\n+ :param kwargs: some specified parameters, such as: pkt_num, port_id, stats\n+ :return:\n+ \"\"\"\n+ self.logger.info(\"{0} check queue {0}\".format(self.logfmt))\n+ queue = check_param[\"queue\"]\n+ if isinstance(check_param[\"queue\"], int):\n+ queue = [queue]\n+ patt = re.compile(\n+ r\"port\\s+{}/queue(.+?):\\s+received\\s+(\\d+)\\s+packets\".format(\n+ kwargs.get(\"port_id\")\n+ )\n+ )\n+ res = patt.findall(out)\n+ if res:\n+ pkt_queue = set([int(i[0]) for i in res])\n+ if kwargs.get(\"stats\"):\n+ self.verify(\n+ all(q in queue for q in pkt_queue),\n+ \"fail: queue id not matched, expect queue {}, got {}\".format(\n+ queue, pkt_queue\n+ ),\n+ )\n+ self.logger.info((GREEN(\"pass: queue id {} matched\".format(pkt_queue))))\n+ else:\n+ try:\n+ self.verify(\n+ not any(q in queue for q in pkt_queue),\n+ \"fail: queue id should not matched, {} should not in {}\".format(\n+ pkt_queue, queue\n+ ),\n+ )\n+ self.logger.info(\n+ (GREEN(\"pass: queue id {} not matched\".format(pkt_queue)))\n+ )\n+ except VerifyFailure:\n+ self.logger.info(\n+ \"queue id {} contains the queue {} specified in rule, so need to check\"\n+ \" whether the packet directed by rss or not\".format(\n+ pkt_queue, queue\n+ )\n+ )\n+ # for mismatch packet the 'stats' parameter is False, need to change to True\n+ kwargs[\"stats\"] = True\n+ self.check_rss(out, **kwargs)\n+\n+ else:\n+ raise Exception(\"got wrong output, not match pattern\")\n+\n+ def check_with_param(self, out, pkt_num, check_param, stats=True):\n+ \"\"\"\n+ according to the key and value of the check parameter,\n+ perform the corresponding verification in the out information\n+ :param out: information received by testpmd after sending packets and port statistics\n+ :param pkt_num: number of packets sent\n+ :param check_param: check item name and value, eg:\n+ \"check_param\": {\"port_id\": 0, \"mark_id\": 1, \"queue\": 1}\n+ \"check_param\": {\"port_id\": 0, \"drop\": 1}\n+ :param stats: effective status of rule, True or False, default is True\n+ :return:\n+ usage:\n+ check_with_param(out, pkt_num, check_param, stats)\n+ check_with_param(out, pkt_num, check_param=check_param)\n+ \"\"\"\n+ rxq = check_param.get(\"rxq\")\n+ port_id = (\n+ check_param[\"port_id\"] if check_param.get(\"port_id\") is not None else 0\n+ )\n+ match_flag = True\n+ \"\"\"\n+ check_dict shows the supported check items,the key is item name and value represent the check priority,\n+ the smaller the value, the higher the priority, priority default value is 999. if need to add new check item,\n+ please add it to the dict and implement the corresponding method and named as 'check_itemname',eg: check_queue\n+ \"\"\"\n+ self.matched_queue = []\n+ default_pri = 999\n+ check_dict = {\n+ \"queue\": default_pri,\n+ \"drop\": default_pri,\n+ \"mark_id\": 1,\n+ \"rss\": default_pri,\n+ }\n+ params = {\"port_id\": port_id, \"rxq\": rxq, \"pkt_num\": pkt_num, \"stats\": stats}\n+ # sort check_param order by priority, from high to low, set priority as 999 if key not in check_dict\n+ check_param = OrderedDict(\n+ sorted(\n+ check_param.items(),\n+ key=lambda item: check_dict.get(item[0], default_pri),\n+ )\n+ )\n+ if not check_param.get(\"drop\"):\n+ self.check_pkt_num(out, **params)\n+ for k in check_param:\n+ parameter = copy.deepcopy(params)\n+ if k not in check_dict:\n+ continue\n+ func_name = \"check_{}\".format(k)\n+ try:\n+ func = getattr(self, func_name)\n+ except AttributeError:\n+ emsg = \"{},this func is not implemented, please check!\".format(\n+ traceback.format_exc()\n+ )\n+ raise Exception(emsg)\n+ else:\n+ # for mismatch packet, if the check item is 'rss',should also verify the packets are distributed by rss\n+ if k == \"rss\" and not stats:\n+ parameter[\"stats\"] = True\n+ match_flag = False\n+ res = func(out=out, check_param=check_param, **parameter)\n+ if k == \"rss\" and match_flag:\n+ self.matched_queue.append(res)\n+\n+ def destroy_rule(self, instance_obj, port_id=0, rule_id=None):\n+ rule_id = 0 if rule_id is None else rule_id\n+ if not isinstance(rule_id, list):\n+ rule_id = [rule_id]\n+ for i in rule_id:\n+ out = instance_obj.pmd_output.execute_cmd(\n+ \"flow destroy {} rule {}\".format(port_id, i)\n+ )\n+ p = re.compile(r\"Flow rule #(\\d+) destroyed\")\n+ m = p.search(out)\n+ self.verify(m, \"flow rule {} delete failed\".format(rule_id))\n+\n+ def multiprocess_flow_data(self, case, **pmd_param):\n+ que_num, proc_num = pmd_param.get(\"queue_num\"), pmd_param.get(\"proc_num\")\n+ # start testpmd multi-process\n+ self.launch_multi_testpmd(\n+ proc_type=pmd_param.get(\"proc_type\"),\n+ queue_num=que_num,\n+ process_num=proc_num,\n+ )\n+ self.pmd_output_list[0].execute_cmd(\"flow flush 0\")\n+ check_param = case[\"check_param\"]\n+ check_param[\"rxq\"] = pmd_param.get(\"queue_num\")\n+ if check_param.get(\"rss\"):\n+ [pmd.execute_cmd(\"port config all rss all\") for pmd in self.pmd_output_list]\n+ fdir_pro = fdirprocess(\n+ self,\n+ self.pmd_output_list[0],\n+ self.tester_ifaces,\n+ rxq=pmd_param.get(\"queue_num\"),\n+ )\n+ fdir_pro.create_rule(case.get(\"rule\"))\n+ # send match and mismatch packet\n+ packets = [case.get(\"packet\")[\"match\"], case.get(\"packet\")[\"mismatch\"]]\n+ for i in range(2):\n+ out1 = self.send_pkt_get_output(fdir_pro, packets[i])\n+ patt = re.compile(\n+ r\"port\\s+{}/queue(.+?):\\s+received\\s+(\\d+)\\s+packets\".format(\n+ check_param.get(\"port_id\")\n+ )\n+ )\n+ if patt.findall(out1) and check_param.get(\"rss\"):\n+ self.logger.info(\n+ \"check whether the packets received by the primary process are distributed by RSS\"\n+ )\n+ self.check_rss(out1, stats=True, **check_param)\n+ for proc_pmd in self.pmd_output_list[1:]:\n+ out2 = proc_pmd.get_output(timeout=1)\n+ out3 = proc_pmd.execute_cmd(\"stop\")\n+ out1 = \"\".join([out1, out2, out3])\n+ proc_pmd.execute_cmd(\"start\")\n+ if patt.findall(out2) and check_param.get(\"rss\"):\n+ self.logger.info(\n+ \"check whether the packets received by the secondary process are distributed by RSS\"\n+ )\n+ self.check_rss(out2, stats=True, **check_param)\n+ pkt_num = len(packets[i])\n+ self.check_with_param(\n+ out1,\n+ pkt_num=pkt_num,\n+ check_param=check_param,\n+ stats=True if i == 0 else False,\n+ )\n+\n+ def _handle_test(self, tests, instance_obj, port_id=0):\n+ for test in tests:\n+ if \"send_packet\" in test:\n+ out = self.send_pkt_get_output(\n+ instance_obj, test[\"send_packet\"], port_id\n+ )\n+ for proc_pmd in self.pmd_output_list[1:]:\n+ out1 = proc_pmd.get_output(timeout=1)\n+ out = \"\".join([out, out1])\n+ if \"action\" in test:\n+ instance_obj.handle_actions(out, test[\"action\"])\n+\n+ def multiprocess_rss_data(self, case, **pmd_param):\n+ que_num, proc_num = pmd_param.get(\"queue_num\"), pmd_param.get(\"proc_num\")\n+ # start testpmd multi-process\n+ self.launch_multi_testpmd(\n+ proc_type=pmd_param.get(\"proc_type\"),\n+ queue_num=que_num,\n+ process_num=proc_num,\n+ options=pmd_param.get(\"options\", None),\n+ )\n+ self.pmd_output_list[0].execute_cmd(\"flow flush 0\")\n+ rss_pro = rssprocess(\n+ self,\n+ self.pmd_output_list[0],\n+ self.tester_ifaces,\n+ rxq=pmd_param.get(\"queue_num\"),\n+ )\n+ rss_pro.error_msgs = []\n+ # handle tests\n+ tests = case[\"test\"]\n+ port_id = case[\"port_id\"]\n+ self.logger.info(\"------------handle test--------------\")\n+ # validate rule\n+ rule = case.get(\"rule\", None)\n+ if rule:\n+ rss_pro.validate_rule(rule=rule)\n+ rule_ids = rss_pro.create_rule(rule=rule)\n+ rss_pro.check_rule(rule_list=rule_ids)\n+ self._handle_test(tests, rss_pro, port_id)\n+ # handle post-test\n+ if \"post-test\" in case:\n+ self.logger.info(\"------------handle post-test--------------\")\n+ self.destroy_rule(rss_pro, port_id=port_id, rule_id=rule_ids)\n+ rss_pro.check_rule(port_id=port_id, stats=False)\n+ self._handle_test(case[\"post-test\"], rss_pro, port_id)\n+\n+ if rss_pro.error_msgs:\n+ self.verify(\n+ False,\n+ \" \".join([errs.replace(\"'\", \" \") for errs in rss_pro.error_msgs[:500]]),\n+ )\n+\n+ def rte_flow(self, case_list, func_name, **kwargs):\n+ \"\"\"\n+ main flow of case:\n+ 1. iterate the case list and do the below steps:\n+ a. get the subcase name and init dict to save result\n+ b. call method by func name to execute case step\n+ c. record case result and err msg if case failed\n+ d. clear flow rule\n+ 2. calculate the case passing rate according to the result dict\n+ 3. record case result and pass rate in the case log file\n+ 4. verify whether the case pass rate is equal to 100, if not, mark the case as failed and raise the err msg\n+ :param case_list: case list, each item is a subcase of case\n+ :param func_name: hadle case method name, eg:\n+ 'flow_rule_operate': a method of 'FlowRuleProcessing' class,\n+ used to handle flow rule related suites,such as fdir and switch_filter\n+ 'handle_rss_distribute_cases': a method of 'RssProcessing' class,\n+ used to handle rss related suites\n+ :return:\n+ usage:\n+ for flow rule related:\n+ rte_flow(caselist, flow_rule_operate)\n+ for rss related:\n+ rte_flow(caselist, handle_rss_distribute_cases)\n+ \"\"\"\n+ if not isinstance(case_list, list):\n+ case_list = [case_list]\n+ test_results = dict()\n+ for case in case_list:\n+ case_name = case.get(\"sub_casename\")\n+ test_results[case_name] = {}\n+ try:\n+ self.logger.info(\"{0} case_name:{1} {0}\".format(\"*\" * 20, case_name))\n+ func_name(case, **kwargs)\n+ except Exception:\n+ test_results[case_name][\"result\"] = \"failed\"\n+ test_results[case_name][\"err\"] = re.sub(\n+ r\"['\\r\\n]\", \"\", str(traceback.format_exc(limit=1))\n+ ).replace(\"\\\\\\\\\", \"\\\\\")\n+ self.logger.info(\n+ (\n+ RED(\n+ \"case failed:{}, err:{}\".format(\n+ case_name, traceback.format_exc()\n+ )\n+ )\n+ )\n+ )\n+ else:\n+ test_results[case_name][\"result\"] = \"passed\"\n+ self.logger.info((GREEN(\"case passed: {}\".format(case_name))))\n+ finally:\n+ self.pmd_output_list[0].execute_cmd(\"flow flush 0\")\n+ for sess in self.session_list:\n+ self.dut.close_session(sess)\n+ pass_rate = (\n+ round(\n+ sum(1 for k in test_results if \"passed\" in test_results[k][\"result\"])\n+ / len(test_results),\n+ 4,\n+ )\n+ * 100\n+ )\n+ self.logger.info(\n+ [\n+ \"{}:{}\".format(sub_name, test_results[sub_name][\"result\"])\n+ for sub_name in test_results\n+ ]\n+ )\n+ self.logger.info(\"pass rate is: {}\".format(pass_rate))\n+ msg = [\n+ \"subcase_name:{}:{},err:{}\".format(\n+ name, test_results[name].get(\"result\"), test_results[name].get(\"err\")\n+ )\n+ for name in test_results.keys()\n+ if \"failed\" in test_results[name][\"result\"]\n+ ]\n+ self.verify(\n+ int(pass_rate) == 100,\n+ \"some subcases failed, detail as below:{}\".format(msg),\n+ )\n+\n+ def test_multiprocess_simple_mpbasicoperation(self):\n+ \"\"\"\n+ Basic operation.\n+ \"\"\"\n+ # Send message from secondary to primary\n+ cores = self.dut.get_core_list(\"1S/2C/1T\", socket=self.socket)\n+ coremask = utils.create_mask(cores)\n+ self.dut.send_expect(\n+ self.app_simple_mp + \" %s --proc-type=primary\" % (self.eal_para),\n+ \"Finished Process Init\",\n+ 100,\n+ )\n+ time.sleep(20)\n+ coremask = hex(int(coremask, 16) * 0x10).rstrip(\"L\")\n+ self.session_secondary.send_expect(\n+ self.app_simple_mp + \" %s --proc-type=secondary\" % (self.eal_para),\n+ \"Finished Process Init\",\n+ 100,\n+ )\n+\n+ self.session_secondary.send_expect(\"send hello_primary\", \">\")\n+ out = self.dut.get_session_output()\n+ self.session_secondary.send_expect(\"quit\", \"# \")\n+ self.dut.send_expect(\"quit\", \"# \")\n+ self.verify(\n+ \"Received 'hello_primary'\" in out, \"Message not received on primary process\"\n+ )\n+ # Send message from primary to secondary\n+ cores = self.dut.get_core_list(\"1S/2C/1T\", socket=self.socket)\n+ coremask = utils.create_mask(cores)\n+ self.session_secondary.send_expect(\n+ self.app_simple_mp + \" %s --proc-type=primary \" % (self.eal_para),\n+ \"Finished Process Init\",\n+ 100,\n+ )\n+ time.sleep(20)\n+ coremask = hex(int(coremask, 16) * 0x10).rstrip(\"L\")\n+ self.dut.send_expect(\n+ self.app_simple_mp + \" %s --proc-type=secondary\" % (self.eal_para),\n+ \"Finished Process Init\",\n+ 100,\n+ )\n+ self.session_secondary.send_expect(\"send hello_secondary\", \">\")\n+ out = self.dut.get_session_output()\n+ self.session_secondary.send_expect(\"quit\", \"# \")\n+ self.dut.send_expect(\"quit\", \"# \")\n+\n+ self.verify(\n+ \"Received 'hello_secondary'\" in out,\n+ \"Message not received on primary process\",\n+ )\n+\n+ def test_multiprocess_simple_mploadtest(self):\n+ \"\"\"\n+ Load test of Simple MP application.\n+ \"\"\"\n+\n+ cores = self.dut.get_core_list(\"1S/2C/1T\", socket=self.socket)\n+ coremask = utils.create_mask(cores)\n+ self.session_secondary.send_expect(\n+ self.app_simple_mp + \" %s --proc-type=primary\" % (self.eal_para),\n+ \"Finished Process Init\",\n+ 100,\n+ )\n+ time.sleep(20)\n+ coremask = hex(int(coremask, 16) * 0x10).rstrip(\"L\")\n+ self.dut.send_expect(\n+ self.app_simple_mp + \" %s --proc-type=secondary\" % (self.eal_para),\n+ \"Finished Process Init\",\n+ 100,\n+ )\n+ stringsSent = 0\n+ for line in open(\"/usr/share/dict/words\", \"r\").readlines():\n+ line = line.split(\"\\n\")[0]\n+ self.dut.send_expect(\"send %s\" % line, \">\")\n+ stringsSent += 1\n+ if stringsSent == 3:\n+ break\n+\n+ time.sleep(5)\n+ self.dut.send_expect(\"quit\", \"# \")\n+ self.session_secondary.send_expect(\"quit\", \"# \")\n+\n+ def test_multiprocess_simple_mpapplicationstartup(self):\n+ \"\"\"\n+ Test use of Auto for Application Startup.\n+ \"\"\"\n+\n+ # Send message from secondary to primary (auto process type)\n+ cores = self.dut.get_core_list(\"1S/2C/1T\", socket=self.socket)\n+ coremask = utils.create_mask(cores)\n+ out = self.dut.send_expect(\n+ self.app_simple_mp + \" %s --proc-type=auto \" % (self.eal_para),\n+ \"Finished Process Init\",\n+ 100,\n+ )\n+ self.verify(\n+ \"EAL: Auto-detected process type: PRIMARY\" in out,\n+ \"The type of process (PRIMARY) was not detected properly\",\n+ )\n+ time.sleep(20)\n+ coremask = hex(int(coremask, 16) * 0x10).rstrip(\"L\")\n+ out = self.session_secondary.send_expect(\n+ self.app_simple_mp + \" %s --proc-type=auto\" % (self.eal_para),\n+ \"Finished Process Init\",\n+ 100,\n+ )\n+ self.verify(\n+ \"EAL: Auto-detected process type: SECONDARY\" in out,\n+ \"The type of process (SECONDARY) was not detected properly\",\n+ )\n+\n+ self.session_secondary.send_expect(\"send hello_primary\", \">\")\n+ out = self.dut.get_session_output()\n+ self.session_secondary.send_expect(\"quit\", \"# \")\n+ self.dut.send_expect(\"quit\", \"# \")\n+ self.verify(\n+ \"Received 'hello_primary'\" in out, \"Message not received on primary process\"\n+ )\n+\n+ # Send message from primary to secondary (auto process type)\n+ cores = self.dut.get_core_list(\"1S/2C/1T\", socket=self.socket)\n+ coremask = utils.create_mask(cores)\n+ out = self.session_secondary.send_expect(\n+ self.app_simple_mp + \" %s --proc-type=auto\" % (self.eal_para),\n+ \"Finished Process Init\",\n+ 100,\n+ )\n+ self.verify(\n+ \"EAL: Auto-detected process type: PRIMARY\" in out,\n+ \"The type of process (PRIMARY) was not detected properly\",\n+ )\n+ time.sleep(20)\n+ coremask = hex(int(coremask, 16) * 0x10).rstrip(\"L\")\n+ out = self.dut.send_expect(\n+ self.app_simple_mp + \" %s --proc-type=auto\" % (self.eal_para),\n+ \"Finished Process Init\",\n+ 100,\n+ )\n+ self.verify(\n+ \"EAL: Auto-detected process type: SECONDARY\" in out,\n+ \"The type of process (SECONDARY) was not detected properly\",\n+ )\n+ self.session_secondary.send_expect(\"send hello_secondary\", \">\", 100)\n+ out = self.dut.get_session_output()\n+ self.session_secondary.send_expect(\"quit\", \"# \")\n+ self.dut.send_expect(\"quit\", \"# \")\n+\n+ self.verify(\n+ \"Received 'hello_secondary'\" in out,\n+ \"Message not received on primary process\",\n+ )\n+\n+ def test_multiprocess_simple_mpnoflag(self):\n+ \"\"\"\n+ Multiple processes without \"--proc-type\" flag.\n+ \"\"\"\n+\n+ cores = self.dut.get_core_list(\"1S/2C/1T\", socket=self.socket)\n+ coremask = utils.create_mask(cores)\n+ self.session_secondary.send_expect(\n+ self.app_simple_mp + \" %s -m 64\" % (self.eal_para),\n+ \"Finished Process Init\",\n+ 100,\n+ )\n+ coremask = hex(int(coremask, 16) * 0x10).rstrip(\"L\")\n+ out = self.dut.send_expect(\n+ self.app_simple_mp + \" %s\" % (self.eal_para), \"# \", 100\n+ )\n+\n+ self.verify(\n+ \"Is another primary process running\" in out,\n+ \"No other primary process detected\",\n+ )\n+\n+ self.session_secondary.send_expect(\"quit\", \"# \")\n+\n+ def test_multiprocess_symmetric_mp_packet(self):\n+ # run multiple symmetric_mp process\n+ portMask = utils.create_mask(self.dut_ports)\n+ # launch symmetric_mp, process num is 2\n+ proc_num = 2\n+ session_list = [\n+ self.dut.new_session(\"process_{}\".format(i)) for i in range(proc_num)\n+ ]\n+ for i in range(proc_num):\n+ session_list[i].send_expect(\n+ self.app_symmetric_mp\n+ + \" -l {} -n 4 --proc-type=auto {} -- -p {} --num-procs={} --proc-id={}\".format(\n+ i + 1, self.eal_param, portMask, proc_num, i\n+ ),\n+ \"Finished Process Init\",\n+ )\n+ # send packets\n+ packet_num = random.randint(20, 256)\n+ self.logger.info(\"packet num:{}\".format(packet_num))\n+ self.random_packet(packet_num)\n+ res = []\n+ for session_obj in session_list:\n+ try:\n+ out = session_obj.send_command(\"^C\")\n+ except Exception as e:\n+ self.logger.err(\"Error occured:{}\".format(traceback.format_exc(e)))\n+ finally:\n+ session_obj.close()\n+ rx_num = re.search(r\"Port 0: RX - (?P<RX>\\d+)\", out)\n+ rx_nums = int(rx_num.group(\"RX\"))\n+ self.verify(\n+ rx_nums > 0,\n+ \"fail: {} received packets shoud greater than 0, actual is {}\".format(\n+ session_obj.name, rx_nums\n+ ),\n+ )\n+ res.append(rx_nums)\n+ rx_total = sum(res)\n+ self.logger.info(\"RX total:{}, send packet:{}\".format(rx_total, packet_num))\n+ self.verify(\n+ rx_total >= packet_num,\n+ \"some packet not received by symmetric_mp, \"\n+ \"number of RX total should greater than or equal to send packet\",\n+ )\n+\n+ def test_multiprocess_server_client_mp_packet(self):\n+ # run multiple client_server_mp process\n+ portMask = utils.create_mask(self.dut_ports)\n+ # launch client_server_mp, client process num is 2\n+ proc_num = 2\n+ session_list = [\n+ self.dut.new_session(\"process_{}\".format(i)) for i in range(proc_num + 1)\n+ ]\n+ server_session = session_list[-1]\n+ # start server\n+ server_session.send_expect(\n+ self.app_mp_server\n+ + \" -l 1,2 -n 4 -- -p {} -n {}\".format(portMask, proc_num),\n+ \"Finished Process Init\",\n+ )\n+ # start client\n+ for i in range(proc_num):\n+ self.dut.init_reserved_core()\n+ session_list[i].send_expect(\n+ self.app_mp_client\n+ + \" -l {} -n 4 --proc-type=auto -- -n {}\".format(i + 3, i),\n+ \"Finished Process Init\",\n+ )\n+ # send packets\n+ packet_num = random.randint(20, 256)\n+ self.logger.info(\"packet num:{}\".format(packet_num))\n+ self.random_packet(packet_num)\n+ out = server_session.get_session_before(timeout=5)\n+ for session_obj in session_list:\n+ try:\n+ session_obj.send_command(\"^C\")\n+ except Exception as e:\n+ self.logger.err(\"Error occured:{}\".format(traceback.format_exc(e)))\n+ finally:\n+ session_obj.close()\n+ res = re.search(\n+ r\"Port \\d+\\s+-\\s+rx:\\s+(?P<rx>\\d+)\\s+tx:.*PORTS\", out, re.DOTALL\n+ )\n+ rx_num = re.findall(r\"Client\\s+\\d\\s+-\\s+rx:\\s+(\\d+)\", res.group(0))\n+ for i in range(proc_num):\n+ self.verify(\n+ int(rx_num[i]) > 0,\n+ \"fail: client_{} received packets shoud greater than 0, \"\n+ \"actual is {}\".format(i, int(rx_num[i])),\n+ )\n+ rx_total = sum(int(rx) for rx in rx_num)\n+ self.logger.info(\"rx total:{}, send packet:{}\".format(rx_total, packet_num))\n+ self.verify(\n+ rx_total >= packet_num,\n+ \"some packet not received by server_client process,\"\n+ \"number of RX total should greater than or equal to send packet.\",\n+ )\n+\n+ # test testpmd multi-process\n+ @check_supported_nic(support_nic)\n+ def test_multiprocess_auto_process_type_detected(self):\n+ # start 2 process\n+ self.launch_multi_testpmd(\"auto\", 8, 2)\n+ # get output of each process and check the detected process type is correctly\n+ process_type = [\"PRIMARY\", \"SECONDARY\"]\n+ for i in range(2):\n+ self.verify(\n+ \"Auto-detected process type: {}\".format(process_type[i])\n+ in self.out_list[i],\n+ \"the process type is not correctly, expect {}\".format(process_type[i]),\n+ )\n+ self.logger.info(\n+ \"pass: Auto-detected {} process type correctly\".format(process_type[i])\n+ )\n+\n+ @check_supported_nic(support_nic)\n+ def test_multiprocess_negative_2_primary_process(self):\n+ # start 2 primary process\n+ try:\n+ self.launch_multi_testpmd([\"primary\", \"primary\"], 8, 2, timeout=10)\n+ except Exception as e:\n+ # check second process start failed\n+ self.verify(\n+ \"Is another primary process running?\" in e.output,\n+ \"fail: More than one primary process was started, only one should be started!\",\n+ )\n+ self.logger.info(\n+ \"pass: only one primary process start successfully, match the expect\"\n+ )\n+ return\n+ self.verify(False, \"fail: 2 primary process launch succeed, expect launch fail\")\n+\n+ @check_supported_nic(support_nic)\n+ def test_multiprocess_negative_exceed_process_num(self):\n+ \"\"\"\n+ If the specified number of processes is exceeded, starting the process will fail\n+ \"\"\"\n+ # start 2 process\n+ proc_type, queue_num, process_num = \"auto\", 8, 2\n+ self.launch_multi_testpmd(proc_type, queue_num, process_num)\n+ # start a process with 'proc-id=2', should start failed\n+ pmd_2 = PmdOutput(self.dut, self.dut.new_session(\"process_2\"))\n+ self.dut.init_reserved_core()\n+ cores = self.dut.get_reserved_core(\"2C\", socket=1)\n+ eal_param = \"--proc-type={} -a {} --log-level=ice,7\".format(\"auto\", self.pci0)\n+ param = \"--rxq={0} --txq={0} --num-procs={1} --proc-id={2}\".format(\n+ queue_num, process_num, 2\n+ )\n+ try:\n+ pmd_2.start_testpmd(\n+ cores=cores, eal_param=eal_param, param=param, timeout=10\n+ )\n+ except Exception as e:\n+ p = re.compile(\n+ r\"The\\s+multi-process\\s+option\\s+'proc-id\\(\\d+\\)'\\s+should\\s+be\\s+less\\s+than\\s+'num-procs\\(\\d+\\)'\"\n+ )\n+ res = p.search(e.output)\n+ self.verify(\n+ res,\n+ \"fail: 'multi-process proc-id should be less than num-process' should in output\",\n+ )\n+ self.logger.info(\n+ \"pass: exceed the specified number, process launch failed as expected\"\n+ )\n+ return\n+ self.verify(\n+ False,\n+ \"fail: exceed the specified number, process launch succeed, expect launch fail\",\n+ )\n+\n+ @check_supported_nic(support_nic)\n+ def test_multiprocess_proc_type_random_packet(self):\n+ case_list = [\n+ {\n+ \"sub_casename\": \"proc_type_auto_4_process\",\n+ \"queue_num\": 16,\n+ \"proc_num\": 4,\n+ \"proc_type\": \"auto\",\n+ \"packet_type\": \"random\",\n+ \"pkt_num\": 30,\n+ },\n+ {\n+ \"sub_casename\": \"proc_type_primary_secondary_2_process\",\n+ \"queue_num\": 4,\n+ \"proc_num\": 2,\n+ \"proc_type\": [\"primary\", \"secondary\"],\n+ \"packet_type\": \"random\",\n+ \"pkt_num\": 20,\n+ },\n+ ]\n+ self.rte_flow(case_list, self._multiprocess_data_pass)\n+\n+ @check_supported_nic(support_nic)\n+ def test_multiprocess_proc_type_specify_packet(self):\n+ case_list = [\n+ {\n+ \"sub_casename\": \"proc_type_auto_2_process\",\n+ \"queue_num\": 8,\n+ \"proc_num\": 2,\n+ \"proc_type\": \"auto\",\n+ \"packet_type\": \"specify\",\n+ },\n+ {\n+ \"sub_casename\": \"proc_type_primary_secondary_3_process\",\n+ \"queue_num\": 6,\n+ \"proc_num\": 3,\n+ \"proc_type\": [\"primary\", \"secondary\"],\n+ \"packet_type\": \"specify\",\n+ },\n+ ]\n+ self.rte_flow(case_list, self._multiprocess_data_pass)\n+\n+ @check_supported_nic(support_nic)\n+ def test_multiprocess_with_fdir_rule(self):\n+ pmd_param = {\n+ \"queue_num\": 64,\n+ \"proc_num\": 2,\n+ \"proc_type\": \"auto\",\n+ }\n+ MAC_IPV4_PAY = {\n+ \"match\": [\n+ 'Ether(dst=\"00:11:22:33:44:55\")/IP(src=\"192.168.0.20\",dst=\"192.168.0.21\", proto=255, ttl=2, tos=4) / Raw(\"x\" * 80)'\n+ ],\n+ \"mismatch\": [\n+ 'Ether(dst=\"00:11:22:33:44:55\")/IP(src=\"192.168.0.20\",dst=\"192.168.0.22\", proto=255, ttl=2, tos=4) / Raw(\"x\" * 80)',\n+ 'Ether(dst=\"00:11:22:33:44:55\")/IP(src=\"192.168.0.22\",dst=\"192.168.0.21\", proto=255, ttl=2, tos=4) / Raw(\"x\" * 80)',\n+ 'Ether(dst=\"00:11:22:33:44:55\")/IP(src=\"192.168.0.20\",dst=\"192.168.1.21\", proto=255, ttl=2, tos=4) / Raw(\"x\" * 80)',\n+ 'Ether(dst=\"00:11:22:33:44:55\")/IP(src=\"192.168.0.20\",dst=\"192.168.0.21\", proto=1, ttl=2, tos=4) / Raw(\"x\" * 80)',\n+ 'Ether(dst=\"00:11:22:33:44:55\")/IP(src=\"192.168.0.20\",dst=\"192.168.0.21\", proto=255, ttl=3, tos=4) / Raw(\"x\" * 80)',\n+ 'Ether(dst=\"00:11:22:33:44:55\")/IP(src=\"192.168.0.20\",dst=\"192.168.0.21\", proto=255, ttl=2, tos=9) / Raw(\"x\" * 80)',\n+ ],\n+ }\n+ mac_ipv4_pay_queue_index = {\n+ \"sub_casename\": \"mac_ipv4_pay_queue_index\",\n+ \"rule\": \"flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / ipv4 src is 192.168.0.20 dst is 192.168.0.21 proto is 255 ttl is 2 tos is 4 / end actions queue index 62 / mark id 4 / end\",\n+ \"packet\": MAC_IPV4_PAY,\n+ \"check_param\": {\"port_id\": 0, \"queue\": 62, \"mark_id\": 4},\n+ }\n+ mac_ipv4_pay_drop = {\n+ \"sub_casename\": \"mac_ipv4_pay_drop\",\n+ \"rule\": \"flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / ipv4 src is 192.168.0.20 dst is 192.168.0.21 proto is 255 ttl is 2 tos is 4 / end actions drop / mark / end\",\n+ \"packet\": MAC_IPV4_PAY,\n+ \"check_param\": {\"port_id\": 0, \"drop\": True},\n+ }\n+ mac_ipv4_pay_rss_queues = {\n+ \"sub_casename\": \"mac_ipv4_pay_rss_queues\",\n+ \"rule\": \"flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / ipv4 src is 192.168.0.20 dst is 192.168.0.21 proto is 255 ttl is 2 tos is 4 / end actions rss queues 31 32 end / mark / end\",\n+ \"packet\": MAC_IPV4_PAY,\n+ \"check_param\": {\"port_id\": 0, \"queue\": [31, 32]},\n+ }\n+ mac_ipv4_pay_mark_rss = {\n+ \"sub_casename\": \"mac_ipv4_pay_mark_rss\",\n+ \"rule\": \"flow create 0 ingress pattern eth dst is 00:11:22:33:44:55 / ipv4 src is 192.168.0.20 dst is 192.168.0.21 proto is 255 ttl is 2 tos is 4 / end actions mark / rss / end\",\n+ \"packet\": MAC_IPV4_PAY,\n+ \"check_param\": {\"port_id\": 0, \"mark_id\": 0, \"rss\": True},\n+ }\n+ case_list = [\n+ mac_ipv4_pay_queue_index,\n+ mac_ipv4_pay_drop,\n+ mac_ipv4_pay_rss_queues,\n+ mac_ipv4_pay_mark_rss,\n+ ]\n+ self.rte_flow(case_list, self.multiprocess_flow_data, **pmd_param)\n+\n+ @check_supported_nic(support_nic)\n+ def test_multiprocess_with_rss_toeplitz(self):\n+ pmd_param = {\n+ \"queue_num\": 32,\n+ \"proc_num\": 2,\n+ \"proc_type\": \"auto\",\n+ \"options\": \" --disable-rss --rxd=384 --txd=384\",\n+ }\n+ mac_ipv4_tcp_toeplitz_basic_pkt = {\n+ \"ipv4-tcp\": [\n+ 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ ],\n+ }\n+ mac_ipv4_tcp_toeplitz_non_basic_pkt = [\n+ 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/UDP(sport=22,dport=23)/(\"X\"*480)',\n+ 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IPv6(src=\"ABAB:910B:6666:3457:8295:3333:1800:2929\",dst=\"CDCD:910A:2222:5498:8475:1111:3900:2020\")/TCP(sport=22,dport=23)/Raw(\"x\"*80)',\n+ ]\n+ mac_ipv4_tcp_l2_src = {\n+ \"sub_casename\": \"mac_ipv4_tcp_l2_src\",\n+ \"port_id\": 0,\n+ \"rule\": \"flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types eth l2-src-only end key_len 0 queues end / end\",\n+ \"test\": [\n+ {\n+ \"send_packet\": mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"],\n+ \"action\": \"save_hash\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:53\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:27:E0\")/IP(dst=\"192.168.0.3\", src=\"192.168.0.5\")/TCP(sport=25,dport=99)/(\"X\"*480)',\n+ \"action\": \"check_hash_same\",\n+ },\n+ ],\n+ \"post-test\": [\n+ {\n+ \"send_packet\": [\n+ mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"][0],\n+ ],\n+ \"action\": \"check_no_hash\",\n+ },\n+ ],\n+ }\n+ mac_ipv4_tcp_l2_dst = {\n+ \"sub_casename\": \"mac_ipv4_tcp_l2_dst\",\n+ \"port_id\": 0,\n+ \"rule\": \"flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types eth l2-dst-only end key_len 0 queues end / end\",\n+ \"test\": [\n+ {\n+ \"send_packet\": mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"],\n+ \"action\": \"save_hash\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:27:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:53\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.3\", src=\"192.168.0.5\")/TCP(sport=25,dport=99)/(\"X\"*480)',\n+ \"action\": \"check_hash_same\",\n+ },\n+ {\n+ \"send_packet\": mac_ipv4_tcp_toeplitz_non_basic_pkt,\n+ \"action\": \"check_no_hash\",\n+ },\n+ ],\n+ \"post-test\": [\n+ {\n+ \"send_packet\": [\n+ mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"][0],\n+ ],\n+ \"action\": \"check_no_hash\",\n+ },\n+ ],\n+ }\n+ mac_ipv4_tcp_l2src_l2dst = {\n+ \"sub_casename\": \"mac_ipv4_tcp_l2src_l2dst\",\n+ \"port_id\": 0,\n+ \"rule\": \"flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types eth end key_len 0 queues end / end\",\n+ \"test\": [\n+ {\n+ \"send_packet\": mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"],\n+ \"action\": \"save_hash\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:53\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:27:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:53\", dst=\"68:05:CA:BB:27:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.3\", src=\"192.168.0.5\")/TCP(sport=25,dport=99)/(\"X\"*480)',\n+ \"action\": \"check_hash_same\",\n+ },\n+ {\n+ \"send_packet\": mac_ipv4_tcp_toeplitz_non_basic_pkt,\n+ \"action\": \"check_no_hash\",\n+ },\n+ ],\n+ \"post-test\": [\n+ {\n+ \"send_packet\": [\n+ mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"][0],\n+ ],\n+ \"action\": \"check_no_hash\",\n+ },\n+ ],\n+ }\n+ mac_ipv4_tcp_l3_src = {\n+ \"sub_casename\": \"mac_ipv4_tcp_l3_src\",\n+ \"port_id\": 0,\n+ \"rule\": \"flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-src-only end key_len 0 queues end / end\",\n+ \"test\": [\n+ {\n+ \"send_packet\": mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"],\n+ \"action\": \"save_hash\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.1.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:53\", dst=\"68:05:CA:BB:27:E0\")/IP(dst=\"192.168.1.1\", src=\"192.168.0.2\")/TCP(sport=32,dport=33)/(\"X\"*480)',\n+ \"action\": \"check_hash_same\",\n+ },\n+ ],\n+ \"post-test\": [\n+ {\n+ \"send_packet\": [\n+ mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"][0],\n+ ],\n+ \"action\": \"check_no_hash\",\n+ },\n+ ],\n+ }\n+ mac_ipv4_tcp_l3_dst = {\n+ \"sub_casename\": \"mac_ipv4_tcp_l3_dst\",\n+ \"port_id\": 0,\n+ \"rule\": \"flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-dst-only end key_len 0 queues end / end\",\n+ \"test\": [\n+ {\n+ \"send_packet\": mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"],\n+ \"action\": \"save_hash\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.1.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:53\", dst=\"68:05:CA:BB:27:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.1.2\")/TCP(sport=32,dport=33)/(\"X\"*480)',\n+ \"action\": \"check_hash_same\",\n+ },\n+ ],\n+ \"post-test\": [\n+ {\n+ \"send_packet\": [\n+ mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"][0],\n+ ],\n+ \"action\": \"check_no_hash\",\n+ },\n+ ],\n+ }\n+ mac_ipv4_tcp_l3src_l4src = {\n+ \"sub_casename\": \"mac_ipv4_tcp_l3src_l4src\",\n+ \"port_id\": 0,\n+ \"rule\": \"flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-src-only l4-src-only end key_len 0 queues end / end\",\n+ \"test\": [\n+ {\n+ \"send_packet\": mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"],\n+ \"action\": \"save_hash\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.1.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/TCP(sport=32,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:53\", dst=\"68:05:CA:BB:27:E0\")/IP(dst=\"192.168.1.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=33)/(\"X\"*480)',\n+ \"action\": \"check_hash_same\",\n+ },\n+ ],\n+ \"post-test\": [\n+ {\n+ \"send_packet\": [\n+ mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"][0],\n+ ],\n+ \"action\": \"check_no_hash\",\n+ },\n+ ],\n+ }\n+ mac_ipv4_tcp_l3src_l4dst = {\n+ \"sub_casename\": \"mac_ipv4_tcp_l3src_l4dst\",\n+ \"port_id\": 0,\n+ \"rule\": \"flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-src-only l4-dst-only end key_len 0 queues end / end\",\n+ \"test\": [\n+ {\n+ \"send_packet\": mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"],\n+ \"action\": \"save_hash\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.1.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=33)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:53\", dst=\"68:05:CA:BB:27:E0\")/IP(dst=\"192.168.1.1\", src=\"192.168.0.2\")/TCP(sport=32,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_same\",\n+ },\n+ ],\n+ \"post-test\": [\n+ {\n+ \"send_packet\": [\n+ mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"][0],\n+ ],\n+ \"action\": \"check_no_hash\",\n+ },\n+ ],\n+ }\n+ mac_ipv4_tcp_l3dst_l4src = {\n+ \"sub_casename\": \"mac_ipv4_tcp_l3dst_l4src\",\n+ \"port_id\": 0,\n+ \"rule\": \"flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-dst-only l4-src-only end key_len 0 queues end / end\",\n+ \"test\": [\n+ {\n+ \"send_packet\": mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"],\n+ \"action\": \"save_hash\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.1.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/TCP(sport=32,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:53\", dst=\"68:05:CA:BB:27:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.1.2\")/TCP(sport=22,dport=33)/(\"X\"*480)',\n+ \"action\": \"check_hash_same\",\n+ },\n+ ],\n+ \"post-test\": [\n+ {\n+ \"send_packet\": [\n+ mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"][0],\n+ ],\n+ \"action\": \"check_no_hash\",\n+ },\n+ ],\n+ }\n+ mac_ipv4_tcp_l3dst_l4dst = {\n+ \"sub_casename\": \"mac_ipv4_tcp_l3dst_l4dst\",\n+ \"port_id\": 0,\n+ \"rule\": \"flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-dst-only l4-dst-only end key_len 0 queues end / end\",\n+ \"test\": [\n+ {\n+ \"send_packet\": mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"],\n+ \"action\": \"save_hash\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.1.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=33)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:53\", dst=\"68:05:CA:BB:27:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.1.2\")/TCP(sport=32,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_same\",\n+ },\n+ ],\n+ \"post-test\": [\n+ {\n+ \"send_packet\": [\n+ mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"][0],\n+ ],\n+ \"action\": \"check_no_hash\",\n+ },\n+ ],\n+ }\n+ mac_ipv4_tcp_l4_src = {\n+ \"sub_casename\": \"mac_ipv4_tcp_l4_src\",\n+ \"port_id\": 0,\n+ \"rule\": \"flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l4-src-only end key_len 0 queues end / end\",\n+ \"test\": [\n+ {\n+ \"send_packet\": mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"],\n+ \"action\": \"save_hash\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/TCP(sport=32,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:53\", dst=\"68:05:CA:BB:27:E0\")/IP(dst=\"192.168.1.1\", src=\"192.168.1.2\")/TCP(sport=22,dport=33)/(\"X\"*480)',\n+ \"action\": \"check_hash_same\",\n+ },\n+ ],\n+ \"post-test\": [\n+ {\n+ \"send_packet\": [\n+ mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"][0],\n+ ],\n+ \"action\": \"check_no_hash\",\n+ },\n+ ],\n+ }\n+ mac_ipv4_tcp_l4_dst = {\n+ \"sub_casename\": \"mac_ipv4_tcp_l4_dst\",\n+ \"port_id\": 0,\n+ \"rule\": \"flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l4-dst-only end key_len 0 queues end / end\",\n+ \"test\": [\n+ {\n+ \"send_packet\": mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"],\n+ \"action\": \"save_hash\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=33)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:53\", dst=\"68:05:CA:BB:27:E0\")/IP(dst=\"192.168.1.1\", src=\"192.168.1.2\")/TCP(sport=32,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_same\",\n+ },\n+ ],\n+ \"post-test\": [\n+ {\n+ \"send_packet\": [\n+ mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"][0],\n+ ],\n+ \"action\": \"check_no_hash\",\n+ },\n+ ],\n+ }\n+ mac_ipv4_tcp_all = {\n+ \"sub_casename\": \"mac_ipv4_tcp_all\",\n+ \"port_id\": 0,\n+ \"rule\": \"flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp end key_len 0 queues end / end\",\n+ \"test\": [\n+ {\n+ \"send_packet\": mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"],\n+ \"action\": \"save_hash\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=33)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/TCP(sport=32,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.1.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.1.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:53\", dst=\"68:05:CA:BB:27:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_same\",\n+ },\n+ ],\n+ \"post-test\": [\n+ {\n+ \"send_packet\": [\n+ mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"][0],\n+ ],\n+ \"action\": \"check_no_hash\",\n+ },\n+ ],\n+ }\n+ mac_ipv4_tcp_ipv4 = {\n+ \"sub_casename\": \"mac_ipv4_tcp_ipv4\",\n+ \"port_id\": 0,\n+ \"rule\": \"flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4 end key_len 0 queues end / end\",\n+ \"test\": [\n+ {\n+ \"send_packet\": mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"],\n+ \"action\": \"save_hash\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.1.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:55\", dst=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.1.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_different\",\n+ },\n+ {\n+ \"send_packet\": 'Ether(src=\"00:11:22:33:44:53\", dst=\"68:05:CA:BB:27:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ \"action\": \"check_hash_same\",\n+ },\n+ ],\n+ \"post-test\": [\n+ {\n+ \"send_packet\": [\n+ mac_ipv4_tcp_toeplitz_basic_pkt[\"ipv4-tcp\"][0],\n+ ],\n+ \"action\": \"check_no_hash\",\n+ },\n+ ],\n+ }\n+\n+ case_list = [\n+ mac_ipv4_tcp_l2_src,\n+ mac_ipv4_tcp_l2_dst,\n+ mac_ipv4_tcp_l2src_l2dst,\n+ mac_ipv4_tcp_l3_src,\n+ mac_ipv4_tcp_l3_dst,\n+ mac_ipv4_tcp_l3src_l4src,\n+ mac_ipv4_tcp_l3src_l4dst,\n+ mac_ipv4_tcp_l3dst_l4src,\n+ mac_ipv4_tcp_l3dst_l4dst,\n+ mac_ipv4_tcp_l4_src,\n+ mac_ipv4_tcp_l4_dst,\n+ mac_ipv4_tcp_all,\n+ mac_ipv4_tcp_ipv4,\n+ ]\n+ self.rte_flow(case_list, self.multiprocess_rss_data, **pmd_param)\n+\n+ @check_supported_nic(support_nic)\n+ def test_multiprocess_with_rss_symmetric(self):\n+ pmd_param = {\n+ \"queue_num\": 64,\n+ \"proc_num\": 2,\n+ \"proc_type\": \"auto\",\n+ }\n+ packets = [\n+ 'Ether(dst=\"00:11:22:33:44:55\", src=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"192.168.0.2\")/(\"X\"*480)',\n+ 'Ether(dst=\"00:11:22:33:44:55\", src=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.2\", src=\"192.168.0.1\")/(\"X\"*480)',\n+ 'Ether(dst=\"00:11:22:33:44:55\", src=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.1\", src=\"12.168.0.2\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ 'Ether(dst=\"00:11:22:33:44:55\", src=\"68:05:CA:BB:26:E0\")/IP(dst=\"192.168.0.2\", src=\"12.168.0.1\")/TCP(sport=22,dport=23)/(\"X\"*480)',\n+ ]\n+ mac_ipv4_symmetric = {\n+ \"sub_casename\": \"mac_ipv4_all\",\n+ \"port_id\": 0,\n+ \"rule\": \"flow create 0 ingress pattern eth / ipv4 / end actions rss func symmetric_toeplitz types ipv4 end key_len 0 queues end / end\",\n+ \"test\": [\n+ {\n+ \"send_packet\": packets[0],\n+ \"action\": {\"save_hash\": \"ipv4-nonfrag\"},\n+ },\n+ {\n+ \"send_packet\": packets[1],\n+ \"action\": {\"check_hash_same\": \"ipv4-nonfrag\"},\n+ },\n+ {\n+ \"send_packet\": packets[2],\n+ \"action\": {\"save_hash\": \"ipv4-tcp\"},\n+ },\n+ {\n+ \"send_packet\": packets[3],\n+ \"action\": {\"check_hash_same\": \"ipv4-tcp\"},\n+ },\n+ ],\n+ \"post-test\": [\n+ {\n+ \"send_packet\": packets[0],\n+ \"action\": {\"save_or_no_hash\": \"ipv4-nonfrag-post\"},\n+ },\n+ {\n+ \"send_packet\": packets[1],\n+ \"action\": {\"check_no_hash_or_different\": \"ipv4-nonfrag-post\"},\n+ },\n+ {\n+ \"send_packet\": packets[2],\n+ \"action\": {\"save_or_no_hash\": \"ipv4-tcp-post\"},\n+ },\n+ {\n+ \"send_packet\": packets[3],\n+ \"action\": {\"check_no_hash_or_different\": \"ipv4-tcp-post\"},\n+ },\n+ ],\n+ }\n+ self.rte_flow(mac_ipv4_symmetric, self.multiprocess_rss_data, **pmd_param)\n+\n+ def test_perf_multiprocess_performance(self):\n+ \"\"\"\n+ Benchmark Multiprocess performance.\n+ #\"\"\"\n+ packet_count = 16\n+ self.dut.send_expect(\"fg\", \"# \")\n+ txPort = self.tester.get_local_port(self.dut_ports[0])\n+ rxPort = self.tester.get_local_port(self.dut_ports[1])\n+ mac = self.tester.get_mac(txPort)\n+ dmac = self.dut.get_mac_address(self.dut_ports[0])\n+ tgenInput = []\n+\n+ # create mutative src_ip+dst_ip package\n+ for i in range(packet_count):\n+ package = (\n+ r'flows = [Ether(src=\"%s\", dst=\"%s\")/IP(src=\"192.168.1.%d\", dst=\"192.168.1.%d\")/(\"X\"*26)]'\n+ % (mac, dmac, i + 1, i + 2)\n+ )\n+ self.tester.scapy_append(package)\n+ pcap = os.sep.join([self.output_path, \"test_%d.pcap\" % i])\n+ self.tester.scapy_append('wrpcap(\"%s\", flows)' % pcap)\n+ tgenInput.append([txPort, rxPort, pcap])\n+ self.tester.scapy_execute()\n+\n+ # run multiple symmetric_mp process\n+ validExecutions = []\n+ for execution in executions:\n+ if len(self.dut.get_core_list(execution[\"cores\"])) == execution[\"nprocs\"]:\n+ validExecutions.append(execution)\n+\n+ portMask = utils.create_mask(self.dut_ports)\n+\n+ for n in range(len(validExecutions)):\n+ execution = validExecutions[n]\n+ # get coreList form execution['cores']\n+ coreList = self.dut.get_core_list(execution[\"cores\"], socket=self.socket)\n+ # to run a set of symmetric_mp instances, like test plan\n+ dutSessionList = []\n+ for index in range(len(coreList)):\n+ dut_new_session = self.dut.new_session()\n+ dutSessionList.append(dut_new_session)\n+ # add -a option when tester and dut in same server\n+ dut_new_session.send_expect(\n+ self.app_symmetric_mp\n+ + \" -c %s --proc-type=auto %s -- -p %s --num-procs=%d --proc-id=%d\"\n+ % (\n+ utils.create_mask([coreList[index]]),\n+ self.eal_param,\n+ portMask,\n+ execution[\"nprocs\"],\n+ index,\n+ ),\n+ \"Finished Process Init\",\n+ )\n+\n+ # clear streams before add new streams\n+ self.tester.pktgen.clear_streams()\n+ # run packet generator\n+ streams = self.pktgen_helper.prepare_stream_from_tginput(\n+ tgenInput, 100, None, self.tester.pktgen\n+ )\n+ _, pps = self.tester.pktgen.measure_throughput(stream_ids=streams)\n+\n+ execution[\"pps\"] = pps\n+\n+ # close all symmetric_mp process\n+ self.dut.send_expect(\"killall symmetric_mp\", \"# \")\n+ # close all dut sessions\n+ for dut_session in dutSessionList:\n+ self.dut.close_session(dut_session)\n+\n+ # get rate and mpps data\n+ for n in range(len(executions)):\n+ self.verify(executions[n][\"pps\"] is not 0, \"No traffic detected\")\n+ self.result_table_create(\n+ [\n+ \"Num-procs\",\n+ \"Sockets/Cores/Threads\",\n+ \"Num Ports\",\n+ \"Frame Size\",\n+ \"%-age Line Rate\",\n+ \"Packet Rate(mpps)\",\n+ ]\n+ )\n+\n+ for execution in validExecutions:\n+ self.result_table_add(\n+ [\n+ execution[\"nprocs\"],\n+ execution[\"cores\"],\n+ 2,\n+ 64,\n+ execution[\"pps\"] / float(100000000 / (8 * 84)),\n+ execution[\"pps\"] / float(1000000),\n+ ]\n+ )\n+\n+ self.result_table_print()\n+\n+ def test_perf_multiprocess_client_serverperformance(self):\n+ \"\"\"\n+ Benchmark Multiprocess client-server performance.\n+ \"\"\"\n+ self.dut.kill_all()\n+ self.dut.send_expect(\"fg\", \"# \")\n+ txPort = self.tester.get_local_port(self.dut_ports[0])\n+ rxPort = self.tester.get_local_port(self.dut_ports[1])\n+ mac = self.tester.get_mac(txPort)\n+\n+ self.tester.scapy_append(\n+ 'dmac=\"%s\"' % self.dut.get_mac_address(self.dut_ports[0])\n+ )\n+ self.tester.scapy_append('smac=\"%s\"' % mac)\n+ self.tester.scapy_append(\n+ 'flows = [Ether(src=smac, dst=dmac)/IP(src=\"192.168.1.1\", dst=\"192.168.1.1\")/(\"X\"*26)]'\n+ )\n+\n+ pcap = os.sep.join([self.output_path, \"test.pcap\"])\n+ self.tester.scapy_append('wrpcap(\"%s\", flows)' % pcap)\n+ self.tester.scapy_execute()\n+\n+ validExecutions = []\n+ for execution in executions:\n+ if len(self.dut.get_core_list(execution[\"cores\"])) == execution[\"nprocs\"]:\n+ validExecutions.append(execution)\n+\n+ for execution in validExecutions:\n+ coreList = self.dut.get_core_list(execution[\"cores\"], socket=self.socket)\n+ # get core with socket parameter to specified which core dut used when tester and dut in same server\n+ coreMask = utils.create_mask(\n+ self.dut.get_core_list(\"1S/1C/1T\", socket=self.socket)\n+ )\n+ portMask = utils.create_mask(self.dut_ports)\n+ # specified mp_server core and add -a option when tester and dut in same server\n+ self.dut.send_expect(\n+ self.app_mp_server\n+ + \" -n %d -c %s %s -- -p %s -n %d\"\n+ % (\n+ self.dut.get_memory_channels(),\n+ coreMask,\n+ self.eal_param,\n+ portMask,\n+ execution[\"nprocs\"],\n+ ),\n+ \"Finished Process Init\",\n+ 20,\n+ )\n+ self.dut.send_expect(\"^Z\", \"\\r\\n\")\n+ self.dut.send_expect(\"bg\", \"# \")\n+\n+ for n in range(execution[\"nprocs\"]):\n+ time.sleep(5)\n+ # use next core as mp_client core, different from mp_server\n+ coreMask = utils.create_mask([str(int(coreList[n]) + 1)])\n+ self.dut.send_expect(\n+ self.app_mp_client\n+ + \" -n %d -c %s --proc-type=secondary %s -- -n %d\"\n+ % (self.dut.get_memory_channels(), coreMask, self.eal_param, n),\n+ \"Finished Process Init\",\n+ )\n+ self.dut.send_expect(\"^Z\", \"\\r\\n\")\n+ self.dut.send_expect(\"bg\", \"# \")\n+\n+ tgenInput = []\n+ tgenInput.append([txPort, rxPort, pcap])\n+\n+ # clear streams before add new streams\n+ self.tester.pktgen.clear_streams()\n+ # run packet generator\n+ streams = self.pktgen_helper.prepare_stream_from_tginput(\n+ tgenInput, 100, None, self.tester.pktgen\n+ )\n+ _, pps = self.tester.pktgen.measure_throughput(stream_ids=streams)\n+\n+ execution[\"pps\"] = pps\n+ self.dut.kill_all()\n+ time.sleep(5)\n+\n+ for n in range(len(executions)):\n+ self.verify(executions[n][\"pps\"] is not 0, \"No traffic detected\")\n+\n+ self.result_table_create(\n+ [\n+ \"Server threads\",\n+ \"Server Cores/Threads\",\n+ \"Num-procs\",\n+ \"Sockets/Cores/Threads\",\n+ \"Num Ports\",\n+ \"Frame Size\",\n+ \"%-age Line Rate\",\n+ \"Packet Rate(mpps)\",\n+ ]\n+ )\n+\n+ for execution in validExecutions:\n+ self.result_table_add(\n+ [\n+ 1,\n+ \"1S/1C/1T\",\n+ execution[\"nprocs\"],\n+ execution[\"cores\"],\n+ 2,\n+ 64,\n+ execution[\"pps\"] / float(100000000 / (8 * 84)),\n+ execution[\"pps\"] / float(1000000),\n+ ]\n+ )\n+\n+ self.result_table_print()\n+\n+ def set_fields(self):\n+ \"\"\"set ip protocol field behavior\"\"\"\n+ fields_config = {\n+ \"ip\": {\n+ \"src\": {\"range\": 64, \"action\": \"inc\"},\n+ \"dst\": {\"range\": 64, \"action\": \"inc\"},\n+ },\n+ }\n+\n+ return fields_config\n+\n+ def tear_down(self):\n+ \"\"\"\n+ Run after each test case.\n+ \"\"\"\n+ if self.session_list:\n+ for sess in self.session_list:\n+ self.dut.close_session(sess)\n+ self.dut.kill_all()\n+\n+ def tear_down_all(self):\n+ \"\"\"\n+ Run after each test suite.\n+ \"\"\"\n+ self.dut.kill_all()\n+ pass\n", "prefixes": [ "V4", "1/2" ] }{ "id": 111377, "url": "