get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/121779/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 121779,
    "url": "https://patches.dpdk.org/api/patches/121779/?format=api",
    "web_url": "https://patches.dpdk.org/project/dts/patch/20230110164431.19390-8-hongbox.li@intel.com/",
    "project": {
        "id": 3,
        "url": "https://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": "<20230110164431.19390-8-hongbox.li@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dts/20230110164431.19390-8-hongbox.li@intel.com",
    "date": "2023-01-10T16:44:30",
    "name": "[V3,7/8] tests/checksum_offload: split performance plan and suite",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "6b1bc80e6cc4b328c1c7e7a1474aa138ef111d5c",
    "submitter": {
        "id": 2804,
        "url": "https://patches.dpdk.org/api/people/2804/?format=api",
        "name": "Li, HongboX",
        "email": "hongbox.li@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dts/patch/20230110164431.19390-8-hongbox.li@intel.com/mbox/",
    "series": [
        {
            "id": 26458,
            "url": "https://patches.dpdk.org/api/series/26458/?format=api",
            "web_url": "https://patches.dpdk.org/project/dts/list/?series=26458",
            "date": "2023-01-10T16:44:23",
            "name": "split performance plan and suite",
            "version": 3,
            "mbox": "https://patches.dpdk.org/series/26458/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/121779/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/121779/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 EAADD423A1;\n\tTue, 10 Jan 2023 09:25:07 +0100 (CET)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id E3FA242D1F;\n\tTue, 10 Jan 2023 09:25:07 +0100 (CET)",
            "from mga07.intel.com (mga07.intel.com [134.134.136.100])\n by mails.dpdk.org (Postfix) with ESMTP id 2D95C40689\n for <dts@dpdk.org>; Tue, 10 Jan 2023 09:25:06 +0100 (CET)",
            "from fmsmga001.fm.intel.com ([10.253.24.23])\n by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 10 Jan 2023 00:25:05 -0800",
            "from unknown (HELO cvl_100g_103.icx.intel.com) ([10.239.252.93])\n by fmsmga001-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 10 Jan 2023 00:25:03 -0800"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n t=1673339106; x=1704875106;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=fLDSyPtkBNm45kT9mQoX9T4x6tSVbn1AKbv6GmIg01g=;\n b=kUhlQeRyWxWtMhLKWztR5TQM0FSyEA5VYi/UwooRX985qFAVl9gKE9Vi\n n7EVxDeV074U9pBlMiQ0viySf/GYe/NTc1VdzhA4Qce/9puQiU/eCJoU8\n zVCc7LojCpo9oPR/8vFOr7sqCzVmGciFVME4UclWg0jJUWi83Hxrsxz7t\n 2NB8rHlW1u5sSbLx60izbkGUGKmbhcmDrbkPQxMuKoXqG49weda8PZjFz\n E2hUt5VP3aU/6sykWwCIzL3rLSo0XQAlwqOu1Yh4o01fZGzbbfab8El0s\n rOXK12OqvgzzkSYRpa/z5Qm8xxTOe8XZKg0OfRL6xkiB2dkq+PPctKwML g==;",
        "X-IronPort-AV": [
            "E=McAfee;i=\"6500,9779,10585\"; a=\"387543519\"",
            "E=Sophos;i=\"5.96,314,1665471600\"; d=\"scan'208\";a=\"387543519\"",
            "E=McAfee;i=\"6500,9779,10585\"; a=\"799339298\"",
            "E=Sophos;i=\"5.96,314,1665471600\"; d=\"scan'208\";a=\"799339298\""
        ],
        "From": "Hongbo Li <hongbox.li@intel.com>",
        "To": "dts@dpdk.org",
        "Cc": "Hongbo Li <hongbox.li@intel.com>",
        "Subject": "[dts][PATCH V3 7/8] tests/checksum_offload: split performance plan\n and suite",
        "Date": "Wed, 11 Jan 2023 00:44:30 +0800",
        "Message-Id": "<20230110164431.19390-8-hongbox.li@intel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20230110164431.19390-1-hongbox.li@intel.com>",
        "References": "<20230110164431.19390-1-hongbox.li@intel.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8",
        "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": "split performance plan and suite\n\nSigned-off-by: Hongbo Li <hongbox.li@intel.com>\n---\n tests/TestSuite_checksum_offload.py      |  54 --\n tests/TestSuite_perf_checksum_offload.py | 624 +++++++++++++++++++++++\n 2 files changed, 624 insertions(+), 54 deletions(-)\n create mode 100644 tests/TestSuite_perf_checksum_offload.py",
    "diff": "diff --git a/tests/TestSuite_checksum_offload.py b/tests/TestSuite_checksum_offload.py\nindex 0214231c..9ba06a19 100644\n--- a/tests/TestSuite_checksum_offload.py\n+++ b/tests/TestSuite_checksum_offload.py\n@@ -756,60 +756,6 @@ class TestChecksumOffload(TestCase):\n \n         self.result_table_add(result)\n \n-    def test_perf_checksum_throughtput(self):\n-        \"\"\"\n-        Test checksum offload performance.\n-        \"\"\"\n-        # Verify that enough ports are available\n-        self.verify(len(self.dut_ports) >= 2, \"Insufficient ports for testing\")\n-        self.dut.send_expect(\"quit\", \"#\")\n-\n-        # sizes = [64, 128, 256, 512, 1024]\n-        sizes = [64, 128]\n-        pkts = {\n-            \"IP/UDP\": 'Ether(dst=\"%s\", src=\"52:00:00:00:00:00\")/IP()/UDP()/(\"X\"*(%d-46))',\n-            \"IP/TCP\": 'Ether(dst=\"%s\", src=\"52:00:00:00:00:00\")/IP()/TCP()/(\"X\"*(%d-58))',\n-            \"IP/SCTP\": 'Ether(dst=\"%s\", src=\"52:00:00:00:00:00\")/IP()/SCTP()/(\"X\"*(%d-50+2))',\n-            \"IPv6/UDP\": 'Ether(dst=\"%s\", src=\"52:00:00:00:00:00\")/IPv6()/UDP()/(\"X\"* (lambda x: x - 66 if x > 66 else 0)(%d))',\n-            \"IPv6/TCP\": 'Ether(dst=\"%s\", src=\"52:00:00:00:00:00\")/IPv6()/TCP()/(\"X\"* (lambda x: x - 78 if x > 78 else 0)(%d))',\n-        }\n-\n-        if self.kdriver in DRIVER_TEST_LACK_CAPA[\"sctp_tx_offload\"]:\n-            del pkts[\"IP/SCTP\"]\n-\n-        lcore = \"1S/2C/1T\"\n-        portMask = utils.create_mask([self.dut_ports[0], self.dut_ports[1]])\n-        for mode in [\"sw\", \"hw\"]:\n-            self.logger.info(\"%s performance\" % mode)\n-            tblheader = [\"Ports\", \"S/C/T\", \"Packet Type\", \"Mode\"]\n-            for size in sizes:\n-                tblheader.append(\"%sB mpps\" % str(size))\n-                tblheader.append(\"%sB %%   \" % str(size))\n-            self.result_table_create(tblheader)\n-            self.pmdout.start_testpmd(\n-                lcore,\n-                \"--portmask=%s\" % self.portMask\n-                + \" --enable-rx-cksum \"\n-                + \"--port-topology=loop\",\n-                socket=self.ports_socket,\n-            )\n-\n-            self.dut.send_expect(\"set fwd csum\", \"testpmd> \")\n-            if mode == \"hw\":\n-                self.checksum_enablehw(self.dut_ports[0])\n-                self.checksum_enablehw(self.dut_ports[1])\n-            else:\n-                self.checksum_enablesw(self.dut_ports[0])\n-                self.checksum_enablesw(self.dut_ports[1])\n-\n-            self.dut.send_expect(\"start\", \"testpmd> \", 3)\n-            for ptype in list(pkts.keys()):\n-                self.benchmark(lcore, ptype, mode, pkts[ptype], sizes, self.nic)\n-\n-            self.dut.send_expect(\"stop\", \"testpmd> \")\n-            self.dut.send_expect(\"quit\", \"#\", 10)\n-            self.result_table_print()\n-\n     def test_hardware_checksum_check_ip_rx(self):\n         self.tester.send_expect(\"scapy\", \">>>\")\n         self.checksum_enablehw(self.dut_ports[0])\ndiff --git a/tests/TestSuite_perf_checksum_offload.py b/tests/TestSuite_perf_checksum_offload.py\nnew file mode 100644\nindex 00000000..a2288613\n--- /dev/null\n+++ b/tests/TestSuite_perf_checksum_offload.py\n@@ -0,0 +1,624 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2010-2014 Intel Corporation\n+# Copyright(c) 2018-2019 The University of New Hampshire\n+#\n+\n+\"\"\"\n+DPDK Test suite.\n+\n+Test support of RX/TX Checksum Offload Features by Poll Mode Drivers.\n+\n+\"\"\"\n+\n+import os\n+import re\n+import subprocess\n+import time\n+from typing import List, Pattern, Tuple, Union\n+\n+from scapy.layers.inet import IP, TCP, UDP\n+from scapy.layers.inet6 import IPv6\n+from scapy.layers.l2 import GRE, Ether\n+from scapy.layers.sctp import SCTP\n+from scapy.layers.vxlan import VXLAN\n+from scapy.packet import Raw\n+from scapy.utils import rdpcap, wrpcap\n+\n+import framework.packet as packet\n+import framework.utils as utils\n+from framework.exception import VerifyFailure\n+from framework.pktgen import PacketGeneratorHelper\n+from framework.pmd_output import PmdOutput\n+from framework.rst import RstReport\n+from framework.settings import FOLDERS\n+from framework.test_capabilities import DRIVER_TEST_LACK_CAPA\n+from framework.test_case import TestCase\n+\n+l3_proto_classes = [IP, IPv6]\n+\n+l4_proto_classes = [\n+    UDP,\n+    TCP,\n+]\n+\n+tunnelling_proto_classes = [\n+    VXLAN,\n+    GRE,\n+]\n+\n+l3_protos = [\"IP\", \"IPv6\"]\n+\n+l4_protos = [\n+    \"UDP\",\n+    \"TCP\",\n+    \"SCTP\",\n+]\n+\n+\n+class TestChecksumOffload(TestCase):\n+    def set_up_all(self):\n+        \"\"\"\n+        Run at the start of each test suite.\n+        Checksum offload prerequisites.\n+        \"\"\"\n+        # Based on h/w type, choose how many ports to use\n+        self.dut_ports = self.dut.get_ports(self.nic)\n+        # Verify that enough ports are available\n+        self.verify(len(self.dut_ports) >= 1, \"Insufficient ports for testing\")\n+        self.pmdout: PmdOutput = PmdOutput(self.dut)\n+        self.portMask = utils.create_mask([self.dut_ports[0]])\n+        self.ports_socket = self.dut.get_numa_id(self.dut_ports[0])\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+        # log debug used\n+        self.count = 0\n+\n+    def set_up(self):\n+        \"\"\"\n+        Run before each test case.\n+        \"\"\"\n+        self.pmdout.start_testpmd(\n+            \"Default\",\n+            \"--portmask=%s \" % (self.portMask)\n+            + \" --enable-rx-cksum \"\n+            + \"--port-topology=loop\",\n+            socket=self.ports_socket,\n+        )\n+        self.dut.send_expect(\"set verbose 1\", \"testpmd>\")\n+        self.dut.send_expect(\"set fwd csum\", \"testpmd>\")\n+        self.dut.send_expect(\"csum mac-swap off 0\", \"testpmd>\")\n+\n+    def checksum_enablehw(self, port):\n+        self.dut.send_expect(\"port stop all\", \"testpmd>\")\n+        self.dut.send_expect(\"rx_vxlan_port add 4789 0 \", \"testpmd>\")\n+        self.dut.send_expect(\"csum set ip hw %d\" % port, \"testpmd>\")\n+        self.dut.send_expect(\"csum set udp hw %d\" % port, \"testpmd>\")\n+        self.dut.send_expect(\"csum set tcp hw %d\" % port, \"testpmd>\")\n+        self.dut.send_expect(\"csum set sctp hw %d\" % port, \"testpmd>\")\n+        self.dut.send_expect(\"csum set outer-ip hw %d\" % port, \"testpmd>\")\n+        self.dut.send_expect(\"csum set outer-udp hw %d\" % port, \"testpmd>\")\n+        self.dut.send_expect(\"csum parse-tunnel on %d\" % port, \"testpmd>\")\n+        self.dut.send_expect(\"port start all\", \"testpmd>\")\n+\n+    def checksum_enablesw(self, port):\n+        self.dut.send_expect(\"port stop all\", \"testpmd>\")\n+        self.dut.send_expect(\"csum set ip sw %d\" % port, \"testpmd>\")\n+        self.dut.send_expect(\"csum set udp sw %d\" % port, \"testpmd>\")\n+        self.dut.send_expect(\"csum set tcp sw %d\" % port, \"testpmd>\")\n+        self.dut.send_expect(\"csum set sctp sw %d\" % port, \"testpmd>\")\n+        self.dut.send_expect(\"port start all\", \"testpmd>\")\n+\n+    def get_chksum_values(self, packets_expected):\n+        \"\"\"\n+        Validate the checksum flags.\n+        \"\"\"\n+        checksum_pattern = re.compile(\"chksum.*=.*(0x[0-9a-z]+)\")\n+\n+        chksum = dict()\n+\n+        self.tester.send_expect(\"scapy\", \">>> \")\n+\n+        for packet_type in list(packets_expected.keys()):\n+            self.tester.send_expect(\"p = %s\" % packets_expected[packet_type], \">>>\")\n+            out = self.tester.send_command(\"p.show2()\", timeout=1)\n+            chksums = checksum_pattern.findall(out)\n+            chksum[packet_type] = chksums\n+\n+        self.tester.send_expect(\"exit()\", \"#\")\n+\n+        return chksum\n+\n+    def checksum_valid_flags(self, packets_sent, flag):\n+        \"\"\"\n+        Sends packets and check the checksum valid-flags.\n+        \"\"\"\n+        self.dut.send_expect(\"start\", \"testpmd>\")\n+        tx_interface = self.tester.get_interface(\n+            self.tester.get_local_port(self.dut_ports[0])\n+        )\n+        for packet_type in list(packets_sent.keys()):\n+            self.pkt = packet.Packet(pkt_str=packets_sent[packet_type])\n+            self.pkt.send_pkt(self.tester, tx_interface, count=4)\n+            out = self.dut.get_session_output(timeout=1)\n+            lines = out.split(\"\\r\\n\")\n+\n+            # collect the checksum result\n+            for line in lines:\n+                line = line.strip()\n+                if len(line) != 0 and line.startswith(\"rx\"):\n+                    # IPv6 don't be checksum, so always show \"GOOD\"\n+                    if packet_type.startswith(\"IPv6\"):\n+                        if \"RTE_MBUF_F_RX_L4_CKSUM\" not in line:\n+                            self.verify(0, \"There is no checksum flags appeared!\")\n+                        else:\n+                            if flag == 1:\n+                                self.verify(\n+                                    \"RTE_MBUF_F_RX_L4_CKSUM_GOOD\" in line,\n+                                    \"Packet Rx L4 checksum valid-flags error!\",\n+                                )\n+                            elif flag == 0:\n+                                self.verify(\n+                                    \"RTE_MBUF_F_RX_L4_CKSUM_BAD\" in line\n+                                    or \"RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN\" in line,\n+                                    \"Packet Rx L4 checksum valid-flags error!\",\n+                                )\n+                    else:\n+                        if \"RTE_MBUF_F_RX_L4_CKSUM\" not in line:\n+                            self.verify(0, \"There is no L4 checksum flags appeared!\")\n+                        elif \"RTE_MBUF_F_RX_IP_CKSUM\" not in line:\n+                            self.verify(0, \"There is no IP checksum flags appeared!\")\n+                        else:\n+                            if flag == 1:\n+                                self.verify(\n+                                    \"RTE_MBUF_F_RX_L4_CKSUM_GOOD\" in line,\n+                                    \"Packet Rx L4 checksum valid-flags error!\",\n+                                )\n+                                self.verify(\n+                                    \"RTE_MBUF_F_RX_IP_CKSUM_GOOD\" in line,\n+                                    \"Packet Rx IP checksum valid-flags error!\",\n+                                )\n+                            elif flag == 0:\n+                                self.verify(\n+                                    \"RTE_MBUF_F_RX_L4_CKSUM_BAD\" in line\n+                                    or \"RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN\" in line,\n+                                    \"Packet Rx L4 checksum valid-flags error!\",\n+                                )\n+                                self.verify(\n+                                    \"RTE_MBUF_F_RX_IP_CKSUM_BAD\" in line,\n+                                    \"Packet Rx IP checksum valid-flags error!\",\n+                                )\n+\n+        self.dut.send_expect(\"stop\", \"testpmd>\")\n+\n+    def checksum_validate(self, packets_sent, packets_expected):\n+        \"\"\"\n+        Validate the checksum.\n+        \"\"\"\n+        tx_interface = self.tester.get_interface(\n+            self.tester.get_local_port(self.dut_ports[0])\n+        )\n+        rx_interface = self.tester.get_interface(\n+            self.tester.get_local_port(self.dut_ports[0])\n+        )\n+\n+        sniff_src = \"52:00:00:00:00:00\"\n+        result = dict()\n+\n+        chksum = self.get_chksum_values(packets_expected)\n+        inst = self.tester.tcpdump_sniff_packets(\n+            intf=rx_interface,\n+            count=len(packets_sent) * 4,\n+            filters=[{\"layer\": \"ether\", \"config\": {\"src\": sniff_src}}],\n+        )\n+\n+        self.pkt = packet.Packet()\n+        for packet_type in list(packets_sent.keys()):\n+            self.pkt.append_pkt(packets_sent[packet_type])\n+        self.pkt.send_pkt(crb=self.tester, tx_port=tx_interface, count=4)\n+\n+        p = self.tester.load_tcpdump_sniff_packets(inst)\n+        nr_packets = len(p)\n+        print(p)\n+        packets_received = [\n+            p[i].sprintf(\"%IP.chksum%;%TCP.chksum%;%UDP.chksum%;%SCTP.chksum%\")\n+            for i in range(nr_packets)\n+        ]\n+        print(len(packets_sent), len(packets_received))\n+        self.verify(\n+            len(packets_sent) * 4 == len(packets_received), \"Unexpected Packets Drop\"\n+        )\n+\n+        for packet_received in packets_received:\n+            (\n+                ip_checksum,\n+                tcp_checksum,\n+                udp_checksum,\n+                sctp_checksum,\n+            ) = packet_received.split(\";\")\n+\n+            packet_type = \"\"\n+            l4_checksum = \"\"\n+            if tcp_checksum != \"??\":\n+                packet_type = \"TCP\"\n+                l4_checksum = tcp_checksum\n+            elif udp_checksum != \"??\":\n+                packet_type = \"UDP\"\n+                l4_checksum = udp_checksum\n+            elif sctp_checksum != \"??\":\n+                packet_type = \"SCTP\"\n+                l4_checksum = sctp_checksum\n+\n+            if ip_checksum != \"??\":\n+                packet_type = \"IP/\" + packet_type\n+                if chksum[packet_type] != [ip_checksum, l4_checksum]:\n+                    result[packet_type] = packet_type + \" checksum error\"\n+            else:\n+                packet_type = \"IPv6/\" + packet_type\n+                if chksum[packet_type] != [l4_checksum]:\n+                    result[packet_type] = packet_type + \" checksum error\"\n+\n+        return result\n+\n+    def send_scapy_packet(self, packet: str):\n+        itf = self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))\n+\n+        self.tester.scapy_foreground()\n+        self.tester.scapy_append(f'sendp({packet}, iface=\"{itf}\")')\n+        return self.tester.scapy_execute()\n+\n+    def get_pkt_rx_l4_cksum(self, testpmd_output: str) -> bool:\n+        return self.checksum_flags_are_good(\"RTE_MBUF_F_RX_L4_CKSUM_\", testpmd_output)\n+\n+    def get_pkt_rx_ip_cksum(self, testpmd_output: str) -> bool:\n+        return self.checksum_flags_are_good(\"RTE_MBUF_F_RX_IP_CKSUM_\", testpmd_output)\n+\n+    def send_pkt_expect_good_bad_from_flag(\n+        self, pkt_str: str, flag: str, test_name: str, should_pass: bool = True\n+    ):\n+        self.pmdout.get_output(timeout=1)  # Remove any old output\n+        self.scapy_exec(f\"sendp({pkt_str}, iface=iface)\")\n+        testpmd_output: str = self.pmdout.get_output(timeout=1)\n+        self.verify(\n+            flag in testpmd_output,\n+            f\"Flag {flag[:-1]} not found for test {test_name}, please run test_rx_checksum_valid_flags.\",\n+        )\n+        self.verify(\n+            (flag + \"UNKNOWN\") not in testpmd_output,\n+            f\"Flag {flag[:-1]} was found to be unknown for test {test_name}, indicating a possible lack of support\",\n+        )\n+        if should_pass:\n+            if flag + \"GOOD\" in testpmd_output:\n+                return\n+            else:  # flag + \"BAD\" in testpmd_output\n+                self.verify(\n+                    False, f\"{flag}BAD was found in output, expecting {flag}GOOD.\"\n+                )\n+        else:\n+            if flag + \"BAD\" in testpmd_output:\n+                return\n+            else:  # flag + \"GOOD\" in testpmd_output\n+                self.verify(\n+                    False, f\"{flag}GOOD was found in output, expecting {flag}BAD.\"\n+                )\n+\n+    def send_pkt_expect_good_bad_from_flag_catch_failure(\n+        self, pkt_str: str, flag: str, test_name: str, should_pass: bool = True\n+    ) -> Union[VerifyFailure, None]:\n+        try:\n+            self.send_pkt_expect_good_bad_from_flag(\n+                pkt_str, flag, test_name, should_pass=should_pass\n+            )\n+        except VerifyFailure as vf:\n+            return vf\n+\n+        return None\n+\n+    def validate_checksum(self, pkt, pkt_type, inner_flag=False) -> bool:\n+        \"\"\"\n+        @param pkt: The packet to validate the checksum of.\n+        @return: Whether the checksum was valid.\n+        \"\"\"\n+        if pkt is None:\n+            return False\n+        for i in range(0, len(l3_protos)):\n+            if l3_protos[i] in pkt:\n+                l3 = l3_protos[i]\n+        for j in range(0, len(l4_protos)):\n+            if l4_protos[j] in pkt:\n+                layer = l4_proto_classes[j]\n+                csum = pkt[layer].chksum\n+                if csum is None:\n+                    csum = 0\n+                del pkt[layer].chksum\n+                # Converting it to raw will calculate the checksum\n+                correct_csum = layer(bytes(Raw(pkt[layer]))).chksum\n+                if correct_csum == csum:\n+                    # checksum value is correct\n+                    return False\n+                else:\n+                    if inner_flag:\n+                        print(\n+                            \"{} pkg[{}] VXLAN/{}/{} inner checksum {} is not correct {}\".format(\n+                                pkt_type,\n+                                self.count,\n+                                l3,\n+                                l4_protos[j],\n+                                hex(correct_csum),\n+                                hex(csum),\n+                            )\n+                        )\n+                    else:\n+                        print(\n+                            \"{} pkg[{}] {}/{} outer checksum {} is not correct {}\".format(\n+                                pkt_type,\n+                                self.count,\n+                                l3,\n+                                l4_protos[j],\n+                                hex(correct_csum),\n+                                hex(csum),\n+                            )\n+                        )\n+                    return True\n+        return False\n+\n+    def scapy_exec(self, cmd: str, timeout=1) -> str:\n+        return self.tester.send_expect(cmd, \">>>\", timeout=timeout)\n+\n+    def get_packets(self, dut_mac, tester_mac):\n+        eth = Ether(dst=dut_mac, src=tester_mac)\n+        packets = []\n+        checksum_options = (\n+            {},\n+            {\"chksum\": 0xF},\n+        )\n+        # Untunneled\n+        for l3 in l3_proto_classes:\n+            for l4 in l4_proto_classes:\n+                for chksum in checksum_options:\n+                    # The packet's data can be used to identify how the packet was constructed so avoid any issues with\n+                    # ordering\n+                    pkt = eth / l3() / l4(**chksum) / (b\"X\" * 48)\n+                    # Prevents the default behavior which adds DNS headers\n+                    if l4 == UDP:\n+                        pkt[UDP].dport, pkt[UDP].sport = 1001, 1001\n+                    packets.append(pkt)\n+\n+        # Tunneled\n+        # VXLAN\n+        for l3 in l3_proto_classes:\n+            for l4 in l4_proto_classes:\n+                for outer_arg in checksum_options:\n+                    for inner_arg in checksum_options:\n+                        pkt = (\n+                            eth\n+                            / l3()\n+                            / UDP(**outer_arg)\n+                            / VXLAN()\n+                            / Ether()\n+                            / l3()\n+                            / l4(**inner_arg)\n+                            / (b\"Y\" * 48)\n+                        )\n+                        # Prevents the default behavior which adds DNS headers\n+                        if l4 == UDP:\n+                            pkt[VXLAN][UDP].dport, pkt[VXLAN][UDP].sport = 1001, 1001\n+                        packets.append(pkt)\n+        # GRE\n+        for l3 in l3_proto_classes:\n+            for l4 in l4_proto_classes:\n+                for chksum in checksum_options:\n+                    pkt = eth / l3() / GRE() / l3() / l4(**chksum) / (b\"Z\" * 48)\n+                    # Prevents the default behavior which adds DNS headers\n+                    if l4 == UDP:\n+                        pkt[GRE][UDP].dport, pkt[GRE][UDP].sport = 1001, 1001\n+                    packets.append(pkt)\n+\n+        return packets\n+\n+    def send_tx_package(\n+        self, packet_file_path, capture_file_path, packets, iface, dut_mac\n+    ):\n+        if os.path.isfile(capture_file_path):\n+            os.remove(capture_file_path)\n+        src_mac = \"52:00:00:00:00:00\"\n+        self.tester.send_expect(\n+            f\"tcpdump -i '{iface}' ether src {src_mac} -s 0 -w {capture_file_path} -Q in &\",\n+            \"# \",\n+        )\n+\n+        if os.path.isfile(packet_file_path):\n+            os.remove(packet_file_path)\n+        wrpcap(packet_file_path, packets)\n+        self.tester.session.copy_file_to(packet_file_path, packet_file_path)\n+\n+        # send packet\n+        self.tester.send_expect(\"scapy\", \">>>\")\n+        self.scapy_exec(f\"packets = rdpcap('{packet_file_path}')\")\n+        for i in range(0, len(packets)):\n+            self.scapy_exec(f\"packets[{i}].show\")\n+            self.scapy_exec(f\"sendp(packets[{i}], iface='{iface}')\")\n+            self.pmdout.get_output(timeout=0.5)\n+            self.dut.send_expect(\n+                \"show port stats {}\".format(self.dut_ports[0]), \"testpmd>\"\n+            )\n+        self.tester.send_expect(\"quit()\", \"# \")\n+\n+        time.sleep(1)\n+        self.tester.send_expect(\"killall tcpdump\", \"#\")\n+        time.sleep(1)\n+        self.tester.send_expect('echo \"Cleaning buffer\"', \"#\")\n+        time.sleep(1)\n+        return\n+\n+    def validate_packet_list_checksums(self, packets):\n+        error_messages = []\n+        untunnelled_error_message = (\n+            f\"un-tunneled checksum state for pkg[%s] with a invalid checksum.\"\n+        )\n+        vxlan_error_message = (\n+            f\"VXLAN tunnelled checksum state for pkg[%s]  with a invalid checksum.\"\n+        )\n+        gre_error_message = (\n+            f\"GRE tunnelled checksum state for pkg[%s] with a invalid checksum.\"\n+        )\n+\n+        for packet in packets:\n+            self.count = self.count + 1\n+            payload: str\n+            # try:\n+            payload = packet[Raw].load.decode(\"utf-8\")\n+            # # This error usually happens with tunneling protocols, and means that an additional cast is needed\n+            # except UnicodeDecodeError:\n+            #     for proto in tunnelling_proto_classes:\n+            if \"X\" in payload:\n+                if self.validate_checksum(packet, \"un-tunneled\"):\n+                    error_messages.append(untunnelled_error_message % self.count)\n+            elif \"Y\" in payload:\n+                if self.validate_checksum(\n+                    packet[VXLAN][Ether], \"VXLAN\", inner_flag=True\n+                ):\n+                    error_messages.append(vxlan_error_message % self.count)\n+                # Intel® Ethernet 700 Series not support outer udp checksum\n+                if self.is_eth_series_nic(700):\n+                    continue\n+                if self.validate_checksum(packet, \"VXLAN\"):\n+                    error_messages.append(vxlan_error_message % self.count)\n+            elif \"Z\" in payload:\n+                if self.validate_checksum(packet, \"GRE\"):\n+                    error_messages.append(gre_error_message % self.count)\n+        return error_messages\n+\n+    #\n+    #\n+    #\n+    # Test Cases\n+    #\n+    def benchmark(self, lcore, ptype, mode, flow_format, size_list, nic):\n+        \"\"\"\n+        Test ans report checksum offload performance for given parameters.\n+        \"\"\"\n+        Bps = dict()\n+        Pps = dict()\n+        Pct = dict()\n+        dmac = self.dut.get_mac_address(self.dut_ports[0])\n+        dmac1 = self.dut.get_mac_address(self.dut_ports[1])\n+\n+        result = [2, lcore, ptype, mode]\n+        for size in size_list:\n+            flow = flow_format % (dmac, size)\n+            pcap = os.sep.join([self.output_path, \"test.pcap\"])\n+            self.tester.scapy_append('wrpcap(\"%s\", [%s])' % (pcap, flow))\n+            self.tester.scapy_execute()\n+            flow = flow_format % (dmac1, size)\n+            pcap = os.sep.join([self.output_path, \"test1.pcap\"])\n+            self.tester.scapy_append('wrpcap(\"%s\", [%s])' % (pcap, flow))\n+            self.tester.scapy_execute()\n+\n+            tgenInput = []\n+            pcap = os.sep.join([self.output_path, \"test.pcap\"])\n+            tgenInput.append(\n+                (\n+                    self.tester.get_local_port(self.dut_ports[0]),\n+                    self.tester.get_local_port(self.dut_ports[1]),\n+                    pcap,\n+                )\n+            )\n+            pcap = os.sep.join([self.output_path, \"test1.pcap\"])\n+            tgenInput.append(\n+                (\n+                    self.tester.get_local_port(self.dut_ports[1]),\n+                    self.tester.get_local_port(self.dut_ports[0]),\n+                    pcap,\n+                )\n+            )\n+\n+            # clear streams before add new streams\n+            self.tester.pktgen.clear_streams()\n+            # create an instance to set stream field setting\n+            # Moved here because it messes with the ability of the functional tests to use scapy.\n+            self.pktgen_helper = PacketGeneratorHelper()\n+            # run packet generator\n+            streams = self.pktgen_helper.prepare_stream_from_tginput(\n+                tgenInput, 100, None, self.tester.pktgen\n+            )\n+            Bps[str(size)], Pps[str(size)] = self.tester.pktgen.measure_throughput(\n+                stream_ids=streams\n+            )\n+            self.verify(Pps[str(size)] > 0, \"No traffic detected\")\n+            Pps[str(size)] /= 1e6\n+            Pct[str(size)] = (Pps[str(size)] * 100) / self.wirespeed(self.nic, size, 2)\n+\n+            result.append(Pps[str(size)])\n+            result.append(Pct[str(size)])\n+\n+        self.result_table_add(result)\n+\n+    def test_perf_checksum_throughtput(self):\n+        \"\"\"\n+        Test checksum offload performance.\n+        \"\"\"\n+        # Verify that enough ports are available\n+        self.verify(len(self.dut_ports) >= 2, \"Insufficient ports for testing\")\n+        self.dut.send_expect(\"quit\", \"#\")\n+\n+        # sizes = [64, 128, 256, 512, 1024]\n+        sizes = [64, 128]\n+        pkts = {\n+            \"IP/UDP\": 'Ether(dst=\"%s\", src=\"52:00:00:00:00:00\")/IP()/UDP()/(\"X\"*(%d-46))',\n+            \"IP/TCP\": 'Ether(dst=\"%s\", src=\"52:00:00:00:00:00\")/IP()/TCP()/(\"X\"*(%d-58))',\n+            \"IP/SCTP\": 'Ether(dst=\"%s\", src=\"52:00:00:00:00:00\")/IP()/SCTP()/(\"X\"*(%d-50+2))',\n+            \"IPv6/UDP\": 'Ether(dst=\"%s\", src=\"52:00:00:00:00:00\")/IPv6()/UDP()/(\"X\"* (lambda x: x - 66 if x > 66 else 0)(%d))',\n+            \"IPv6/TCP\": 'Ether(dst=\"%s\", src=\"52:00:00:00:00:00\")/IPv6()/TCP()/(\"X\"* (lambda x: x - 78 if x > 78 else 0)(%d))',\n+        }\n+\n+        if self.kdriver in DRIVER_TEST_LACK_CAPA[\"sctp_tx_offload\"]:\n+            del pkts[\"IP/SCTP\"]\n+\n+        lcore = \"1S/2C/1T\"\n+        portMask = utils.create_mask([self.dut_ports[0], self.dut_ports[1]])\n+        for mode in [\"sw\", \"hw\"]:\n+            self.logger.info(\"%s performance\" % mode)\n+            tblheader = [\"Ports\", \"S/C/T\", \"Packet Type\", \"Mode\"]\n+            for size in sizes:\n+                tblheader.append(\"%sB mpps\" % str(size))\n+                tblheader.append(\"%sB %%   \" % str(size))\n+            self.result_table_create(tblheader)\n+            self.pmdout.start_testpmd(\n+                lcore,\n+                \"--portmask=%s\" % self.portMask\n+                + \" --enable-rx-cksum \"\n+                + \"--port-topology=loop\",\n+                socket=self.ports_socket,\n+            )\n+\n+            self.dut.send_expect(\"set fwd csum\", \"testpmd> \")\n+            if mode == \"hw\":\n+                self.checksum_enablehw(self.dut_ports[0])\n+                self.checksum_enablehw(self.dut_ports[1])\n+            else:\n+                self.checksum_enablesw(self.dut_ports[0])\n+                self.checksum_enablesw(self.dut_ports[1])\n+\n+            self.dut.send_expect(\"start\", \"testpmd> \", 3)\n+            for ptype in list(pkts.keys()):\n+                self.benchmark(lcore, ptype, mode, pkts[ptype], sizes, self.nic)\n+\n+            self.dut.send_expect(\"stop\", \"testpmd> \")\n+            self.dut.send_expect(\"quit\", \"#\", 10)\n+            self.result_table_print()\n+\n+    def tear_down(self):\n+        \"\"\"\n+        Run after each test case.\n+        \"\"\"\n+        self.dut.send_expect(\"quit\", \"#\")\n+\n+    def tear_down_all(self):\n+        \"\"\"\n+        Run after each test suite.\n+        \"\"\"\n+        pass\n",
    "prefixes": [
        "V3",
        "7/8"
    ]
}