List comments

GET /api/patches/74497/comments/?order=submitter
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "id": 116572,
        "web_url": "https://patches.dpdk.org/comment/116572/",
        "msgid": "<8CE3E05A3F976642AAB0F4675D0AD20E0BC84184@SHSMSX101.ccr.corp.intel.com>",
        "date": "2020-07-24T02:45:08",
        "subject": "Re: [dts] [PATCH] checksum checks: Add hardware offload l3 and l4\n cases",
        "submitter": {
            "id": 1098,
            "url": "https://patches.dpdk.org/api/people/1098/",
            "name": "Tu, Lijuan",
            "email": "lijuan.tu@intel.com"
        },
        "content": "Is the patch based on the latest DTS ? sorry, I can't merge it because of code conflict. Could you please rework it. Btw, all patches, v1/v2... should be based on latest DTS.\n\nThanks, Lijuan.\n\n> -----Original Message-----\n> From: dts <dts-bounces@dpdk.org> On Behalf Of Owen Hilyard\n> Sent: 2020年7月20日 22:08\n> To: dts@dpdk.org\n> Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; arybchenko@solarflare.com;\n> olivier.matz@6wind.com; david.marchand@redhat.com;\n> ivan.malov@oktetlabs.ru; Richardson, Bruce <bruce.richardson@intel.com>;\n> lylavoie@iol.unh.edu; rasland@mellanox.com; j.hendergart@f5.com;\n> ohilyard@iol.unh.edu; thomas@monjalon.net\n> Subject: [dts] [PATCH] checksum checks: Add hardware offload l3 and l4 cases\n> \n> add rx and tx l3 test cases\n> add tx l4 test case\n> add documentation for new test cases\n> \n> Signed-off-by: Owen Hilyard <ohilyard@iol.unh.edu>\n> ---\n>  test_plans/checksum_offload_test_plan.rst | 122 +++++++-\n>  tests/TestSuite_checksum_offload.py       | 331 +++++++++++++++++++---\n>  2 files changed, 412 insertions(+), 41 deletions(-)\n> \n> diff --git a/test_plans/checksum_offload_test_plan.rst\n> b/test_plans/checksum_offload_test_plan.rst\n> index 4fd8c5a..de2e1a9 100644\n> --- a/test_plans/checksum_offload_test_plan.rst\n> +++ b/test_plans/checksum_offload_test_plan.rst\n> @@ -221,7 +221,7 @@ combination: good/bad ip checksum + good/bad\n> udp/tcp checksum.\n> \n>  Check the Rx checksum flags consistent with expected flags.\n> \n> -Test Case: Hardware Checksum Check L4\n> +Test Case: Hardware Checksum Check L4 RX\n>  ===========================================\n>  This test involves testing many different scenarios with a L4 checksum.\n>  A variety of tunneling protocols, L3 protocols and L4 protocols are combined\n> @@ -256,4 +256,122 @@ Send a packet with a bad checksum::\n>     rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8\n> flags=PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_BAD\n> PKT_RX_OUTER_L4_CKSUM_UNKNOWN\n>     tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4\n> \n> -Verify flags are as expected.\n> \\ No newline at end of file\n> +Verify flags are as expected.\n> +\n> +Test Case: Hardware Checksum Check L3 RX\n> +===========================================\n> +This test involves testing L3 checksum hardware offload.\n> +Due to the relative dominance of IPv4 and IPv6 as L3 protocols, and\n> +IPv6's lack of a checksum, only IPv4's checksum is tested.\n> +\n> +Setup the ``csum`` forwarding mode::\n> +\n> +  testpmd> set fwd csum\n> +  Set csum packet forwarding mode\n> +\n> +Start the packet forwarding::\n> +\n> +  testpmd> start\n> +    csum packet forwarding - CRC stripping disabled - packets/burst=32\n> +    nb forwarding cores=1 - nb forwarding ports=10\n> +    RX queues=1 - RX desc=128 - RX free threshold=64\n> +    RX threshold registers: pthresh=8 hthresh=8 wthresh=4\n> +    TX queues=1 - TX desc=512 - TX free threshold=0\n> +    TX threshold registers: pthresh=32 hthresh=8 wthresh=8\n> +\n> +Send a packet with a good checksum::\n> +\n> +   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:\n> +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8\n> flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD\n> PKT_RX_OUTER_L4_CKSUM_UNKNOWN\n> +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4\n> +\n> +Send a packet with a bad checksum::\n> +\n> +   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:\n> +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8\n> flags=PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_BAD\n> PKT_RX_OUTER_L4_CKSUM_UNKNOWN\n> +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4\n> +\n> +Verify flags are as expected.\n> +\n> +Test Case: Hardware Checksum Check L4 TX\n> +===========================================\n> +This test involves testing many different scenarios with a L4 checksum.\n> +A variety of tunneling protocols, L3 protocols and L4 protocols are\n> +combined to test as many scenarios as possible. Currently, UDP, TCP and\n> +SCTP are used as L4 protocols, with IP and IPv6 being used at level 3.\n> +The tested tunneling protocols are VXLAN and GRE. This test is used to\n> +determine whether the hardware offloading of checksums works properly.\n> +\n> +Setup the ``csum`` forwarding mode::\n> +\n> +  testpmd> set fwd csum\n> +  Set csum packet forwarding mode\n> +\n> +Start the packet forwarding::\n> +\n> +  testpmd> start\n> +    csum packet forwarding - CRC stripping disabled - packets/burst=32\n> +    nb forwarding cores=1 - nb forwarding ports=10\n> +    RX queues=1 - RX desc=128 - RX free threshold=64\n> +    RX threshold registers: pthresh=8 hthresh=8 wthresh=4\n> +    TX queues=1 - TX desc=512 - TX free threshold=0\n> +    TX threshold registers: pthresh=32 hthresh=8 wthresh=8\n> +\n> +\n> +Start a packet capture on the tester in the backround::\n> +\n> +   # tcpdump -i <iface> -s 65535 -w\n> + /tmp/tester/test_hardware_checksum_check_l4_tx_capture.pcap &\n> +\n> +Send a packet with a good checksum::\n> +\n> +   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:\n> +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8\n> flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD\n> PKT_RX_OUTER_L4_CKSUM_UNKNOWN\n> +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4\n> +\n> +Send a packet with a bad checksum::\n> +\n> +   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:\n> +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8\n> flags=PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_GOOD\n> PKT_RX_OUTER_L4_CKSUM_UNKNOWN\n> +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4\n> +\n> +Inspect the pcap file from the packet capture and verify the checksums.\n> +\n> +Test Case: Hardware Checksum Check L3 TX\n> +===========================================\n> +This test involves testing L3 checksum hardware offload.\n> +Due to the relative dominance of IPv4 and IPv6 as L3 protocols, and\n> +IPv6's lack of a checksum, only IPv4's checksum is tested.\n> +\n> +Setup the ``csum`` forwarding mode::\n> +\n> +  testpmd> set fwd csum\n> +  Set csum packet forwarding mode\n> +\n> +Start the packet forwarding::\n> +\n> +  testpmd> start\n> +    csum packet forwarding - CRC stripping disabled - packets/burst=32\n> +    nb forwarding cores=1 - nb forwarding ports=10\n> +    RX queues=1 - RX desc=128 - RX free threshold=64\n> +    RX threshold registers: pthresh=8 hthresh=8 wthresh=4\n> +    TX queues=1 - TX desc=512 - TX free threshold=0\n> +    TX threshold registers: pthresh=32 hthresh=8 wthresh=8\n> +\n> +\n> +Start a packet capture on the tester in the backround::\n> +\n> +   # tcpdump -i <iface> -s 65535 -w\n> + /tmp/tester/test_hardware_checksum_check_l3_tx_capture.pcap &\n> +\n> +Send a packet with a good checksum with a 1 in it's payload::\n> +\n> +   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:\n> +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8\n> flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD\n> PKT_RX_OUTER_L4_CKSUM_UNKNOWN\n> +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4\n> +\n> +Send a packet with a bad checksum with a 0 in it's payload::\n> +\n> +   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:\n> +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8\n> flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_BAD\n> PKT_RX_OUTER_L4_CKSUM_UNKNOWN\n> +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4\n> +\n> +Inspect the pcap file from the packet capture and verify the checksums.\n> diff --git a/tests/TestSuite_checksum_offload.py\n> b/tests/TestSuite_checksum_offload.py\n> index 9ff5a41..c4a877d 100644\n> --- a/tests/TestSuite_checksum_offload.py\n> +++ b/tests/TestSuite_checksum_offload.py\n> @@ -47,8 +47,18 @@ import time\n> \n>  from rst import RstReport\n>  import utils\n> -\n> +from exception import VerifyFailure\n> +from pktgen import PacketGeneratorHelper from scapy.layers.inet import\n> +UDP, TCP, IP from scapy.layers.inet6 import IPv6 from scapy.layers.l2\n> +import Ether, GRE from scapy.layers.sctp import SCTP from\n> +scapy.layers.vxlan import VXLAN from scapy.packet import Raw from\n> +scapy.utils import wrpcap, rdpcap from test_capabilities import\n> +DRIVER_TEST_LACK_CAPA\n>  from test_case import TestCase\n> +\n>  from framework.pmd_output import PmdOutput  from test_capabilities import\n> DRIVER_TEST_LACK_CAPA  from pktgen import PacketGeneratorHelper @@ -\n> 57,6 +67,33 @@ import packet\n> \n>  from settings import FOLDERS\n> \n> +l3_proto_classes = [\n> +    IP,\n> +    IPv6\n> +]\n> +\n> +l4_proto_classes = [\n> +    UDP,\n> +    TCP,\n> +    SCTP\n> +]\n> +\n> +tunnelling_proto_classes = [\n> +    VXLAN,\n> +    GRE,\n> +]\n> +\n> +l3_protos = [\n> +    \"IP\",\n> +    \"IPv6\"\n> +]\n> +\n> +l4_protos = [\n> +    \"UDP\",\n> +    \"TCP\",\n> +    \"SCTP\",\n> +]\n> +\n> \n>  class TestChecksumOffload(TestCase):\n> \n> @@ -79,8 +116,6 @@ class TestChecksumOffload(TestCase):\n>              cur_path = os.path.dirname(\n>                  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> \n>      def set_up(self):\n>          \"\"\"\n> @@ -243,7 +278,6 @@ class TestChecksumOffload(TestCase):\n>      def send_pkt_expect_good_bad_from_flag(self, pkt_str: str, flag: str,\n> test_name: str, should_pass: bool = True):\n>          self.pmdout.get_output(timeout=5)  # Remove any old output\n>          self.scapy_exec(f\"sendp({pkt_str}, iface=iface)\")\n> -        time.sleep(1)\n>          testpmd_output: str = self.pmdout.get_output(timeout=5)\n>          self.verify(flag in testpmd_output,\n>                      f\"Flag {flag[:-1]} not found for test {test_name}, please run\n> test_rx_checksum_valid_flags.\") @@ -269,11 +303,147 @@ class\n> TestChecksumOffload(TestCase):\n> \n>          return None\n> \n> -    def scapy_exec(self, cmd: str):\n> -        return self.tester.send_expect(cmd, \">>>\")\n> +    def validate_checksum(self, pkt, layer) -> 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> +\n> +        csum = pkt[layer].chksum\n> +        del pkt[layer].chksum\n> +        # Converting it to raw will calculate the checksum\n> +        return layer(Raw(pkt[layer])).chksum == csum\n> \n> -    def scapy_send_append(self, packet: str):\n> -        return self.tester.scapy_append(f'sendp({packet}, iface=iface)')\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 = ({}, {'chksum': 0xf},)\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\n> constructed so avoid any issues with\n> +                    # ordering\n> +                    pkt = eth / l3() / l4(**chksum) / (\n> +                        f'UNTUNNELED,{l3.__name__},{l4.__name__},{\" \" if\n> len(chksum.values()) == 0 else chksum[\"chksum\"]}'\n> +                    )\n> +\n> +                    # Prevents the default behavior which adds DNS headers\n> +                    if l4 == UDP:\n> +                        pkt[UDP].dport, pkt[UDP].sport = 1001, 1001\n> +\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 = eth / l3() / UDP(**outer_arg) / VXLAN() / Ether() / l3() /\n> l4(**inner_arg) / (\n> +                            f'VXLAN,{l3.__name__},{l4.__name__},'\n> +                            f'{\" \" if len(outer_arg.values()) == 0 else outer_arg[\"chksum\"]},'\n> +                            f'{\" \" if len(inner_arg.values()) == 0 else inner_arg[\"chksum\"]}'\n> +                        )\n> +                        # Prevents the default behavior which adds DNS headers\n> +                        if l4 == UDP:\n> +                            pkt[VXLAN][UDP].dport,\n> + pkt[VXLAN][UDP].sport = 1001, 1001\n> +\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) / (\n> +                        f'GRE,{l3.__name__},{l4.__name__},{\" \" if len(chksum.values()) ==\n> 0 else chksum[\"chksum\"]}'\n> +                    )\n> +\n> +                    # Prevents the default behavior which adds DNS headers\n> +                    if l4 == UDP:\n> +                        pkt[GRE][UDP].dport, pkt[GRE][UDP].sport =\n> + 1001, 1001\n> +\n> +                    packets.append(pkt)\n> +\n> +        return packets\n> +\n> +    def replay_pcap_file_on_tester(self, iface, packet_file_path):\n> +        self.tester.send_expect(\"scapy\", \">>>\")\n> +        self.scapy_exec(f\"packets = rdpcap('{packet_file_path}')\")\n> +        self.scapy_exec(f\"sendp(packets, iface={iface})\")\n> +        self.tester.send_expect(\"quit()\", \"# \")\n> +\n> +    def validate_packet_list_checksums(self, packets):\n> +        name_to_class_dict = {\n> +            'UDP': UDP,\n> +            'TCP': TCP,\n> +            'SCTP': SCTP,\n> +            'IP': IP,\n> +            'IPv6': IPv6,\n> +            'VXLAN': VXLAN,\n> +            'GRE': GRE,\n> +        }\n> +\n> +        error_messages = []\n> +\n> +        untunnelled_error_message = f\"Invalid untunneled checksum state\n> for %s/%s with a %s checksum.\"\n> +\n> +        vxlan_error_message = f\"Invalid VXLAN tunnelled %s checksum state\n> for %s/%s\" \\\n> +                              f\" with a %s inner checksum and a %s outer checksum.\"\n> +\n> +        gre_error_message = f\"Invalid GRE tunnelled checksum state for %s/%s\n> with a %s checksum.\"\n> +\n> +        for packet in packets:\n> +            payload: str\n> +            # try:\n> +            payload = packet[Raw].load.decode('utf-8').split(\",\")\n> +            # # This error usually happens with tunneling protocols, and means that\n> an additional cast is needed\n> +            # except UnicodeDecodeError:\n> +            #     for proto in tunnelling_proto_classes:\n> +\n> +            l3 = name_to_class_dict[payload[1]]\n> +            l4 = name_to_class_dict[payload[2]]\n> +            if payload[0] == \"UNTUNNELED\":\n> +                chksum_should_be_valid = payload[3] == \" \"\n> +                if self.validate_checksum(packet, l4) != chksum_should_be_valid:\n> +                    error_messages.append(\n> +                        untunnelled_error_message % (\n> +                            l3.__name__, l4.__name__, 'valid' if chksum_should_be_valid\n> == '' else 'invalid'\n> +                        )\n> +                    )\n> +            elif payload[0] == \"VXLAN\":\n> +                outer_chksum_should_be_valid = payload[3] == \" \"\n> +                inner_chksum_should_be_valid = payload[4] == \" \"\n> +                if self.validate_checksum(packet[VXLAN], l4) !=\n> inner_chksum_should_be_valid:\n> +                    error_messages.append(\n> +                        vxlan_error_message % (\n> +                            \"inner\", l4.__name__, l3.__name__,\n> +                            'valid' if inner_chksum_should_be_valid == '' else 'invalid',\n> +                            'valid' if outer_chksum_should_be_valid == '' else 'invalid'\n> +                        )\n> +                    )\n> +                if self.validate_checksum(packet, l4) !=\n> outer_chksum_should_be_valid:\n> +                    error_messages.append(\n> +                        vxlan_error_message % (\n> +                            \"outer\", l3.__name__, l4.__name__,\n> +                            'valid' if inner_chksum_should_be_valid == '' else 'invalid',\n> +                            'valid' if outer_chksum_should_be_valid == '' else 'invalid'\n> +                        )\n> +                    )\n> +            elif payload[0] == \"GRE\":\n> +                chksum_should_be_valid = payload[3] == \" \"\n> +                if self.validate_checksum(packet, l4) != chksum_should_be_valid:\n> +                    error_messages.append(\n> +                        gre_error_message % (\n> +                            l3.__name__, l4.__name__, 'valid' if chksum_should_be_valid\n> == '' else 'invalid'\n> +                        )\n> +                    )\n> +\n> +        return error_messages\n> \n>      #\n>      #\n> @@ -448,6 +618,9 @@ class TestChecksumOffload(TestCase):\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\n> to use scapy.\n> +            self.pktgen_helper = PacketGeneratorHelper()\n>              # run packet generator\n>              streams = self.pktgen_helper.prepare_stream_from_tginput(tgenInput,\n> 100,\n>                      None, self.tester.pktgen) @@ -511,53 +684,93 @@ class\n> TestChecksumOffload(TestCase):\n>              self.dut.send_expect(\"quit\", \"#\", 10)\n>              self.result_table_print()\n> \n> -    def test_hardware_checksum_check_ip(self):\n> +    def test_hardware_checksum_check_ip_rx(self):\n>          self.dut.send_expect(\"start\", \"testpmd>\")\n> +        self.tester.send_expect(\"scapy\", \">>>\")\n>          self.checksum_enablehw(self.dut_ports[0])\n> +        self.dut.send_expect(\"start\", \"testpmd>\")\n> \n>          verification_errors: List[VerifyFailure] = []\n> \n> -        # untunnelled\n> -        vf =\n> self.try_helper_hardware_checksum_check_catch_failure('Ether(dst=\"%s\",\n> src=\"%s\")/IP(%s)/UDP()/(\"X\"*50)',\n> -                                                                   \"PKT_RX_IP_CKSUM_\")\n> -        if vf is not None:\n> -            verification_errors.append(vf)\n> +        iface =\n> self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))\n> +        dut_mac = self.dut.get_mac_address(self.dut_ports[0])\n> +        tester_mac =\n> + self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))\n> \n> -        # tunneled inner\n> -        vf = self.try_helper_hardware_checksum_check_catch_failure(\n> -            'Ether(dst=\"%s\", src=\"%s\")/IP()/UDP()/IP(%s)/(\"X\"*50)',\n> -            \"PKT_RX_OUTER_IP_CKSUM_\")\n> -        if vf is not None:\n> -            verification_errors.append(vf)\n> +        self.scapy_exec(f\"eth = Ether(dst='{dut_mac}', src='{tester_mac}')\")\n> +        self.scapy_exec(f\"iface = '{iface}'\")\n> \n> -        # tunneled outer\n> -        vf = self.try_helper_hardware_checksum_check_catch_failure(\n> -            'Ether(dst=\"%s\", src=\"%s\")/IP()/UDP()/IP(%s)/(\"X\"*50)',\n> -            \"PKT_RX_OUTER_IP_CKSUM_\")\n> -        if vf is not None:\n> -            verification_errors.append(vf)\n> +        # Untunnelled\n> +        for l4 in l4_protos:\n> +            for chksum in \"\", \"chksum=0xf\":\n> +                vf = self.send_pkt_expect_good_bad_from_flag_catch_failure(\n> +                    f\"eth/IP({chksum})/{l4}()/(X'*50)\",\n> +                    \"PKT_RX_IP_CKSUM_\", f\"{l4}\",\n> +                    should_pass=(chksum == \"\"))\n> +                if vf is not None:\n> +                    verification_errors.append(vf)\n> \n> -        self.verify(len(verification_errors) == 0, \"\\n\".join(verification_errors))\n> +        for err in verification_errors:\n> +            self.logger.error(str(err))\n> +        self.verify(len(verification_errors) == 0, \"See previous\n> + output\")\n> \n> +        self.tester.send_expect(\"quit()\", \"# \")\n>          self.dut.send_expect(\"stop\", \"testpmd>\")\n> \n> -    def test_hardware_checksum_check_l4(self):\n> +    def test_hardware_checksum_check_ip_tx(self):\n>          self.checksum_enablehw(self.dut_ports[0])\n>          self.dut.send_expect(\"start\", \"testpmd>\")\n> \n>          verification_errors: List[VerifyFailure] = []\n> \n> -        l3_protos: List[str] = [\n> -            \"IP\",\n> -            \"IPv6\"\n> -        ]\n> +        iface =\n> self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))\n> +        dut_mac = self.dut.get_mac_address(self.dut_ports[0])\n> +        tester_mac =\n> self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))\n> +        eth = Ether(dst=dut_mac, src=tester_mac)\n> \n> -        l4_protos: List[str] = [\n> -            \"UDP\",\n> -            \"TCP\",\n> -            \"SCTP\",\n> +        checksum_options = ({}, {'chksum': 0xf},)\n> +\n> +        packets = [\n> +            eth / IP(**chksum) / TCP() / Raw(load=str(int(len(chksum)\n> + != 1))) for chksum in checksum_options\n>          ]\n> \n> +        capture_file_name =\n> \"test_hardware_checksum_check_l3_tx_capture.pcap\"\n> +\n> +        packet_file_path =\n> \"/tmp/test_hardware_checksum_check_l3_tx_packets.pcap\"\n> +        capture_file_path = \"/tmp/tester/\" + capture_file_name\n> +\n> +        self.tester.send_expect(f\"tcpdump -i {iface} -s 65535 -w\n> + {capture_file_path} &\", \"# \")\n> +\n> +        wrpcap(packet_file_path, packets)\n> +        self.tester.session.copy_file_to(packet_file_path,\n> + packet_file_path)\n> +\n> +        self.replay_pcap_file_on_tester(iface, packet_file_path)\n> +\n> +        self.tester.session.copy_file_from(packet_file_path,\n> + \"output/tmp/pcap/\" + capture_file_name)\n> +\n> +        captured_packets = rdpcap(\"output/tmp/pcap/\" +\n> + capture_file_name)\n> +\n> +        self.verify(len(packets) == len(captured_packets), \"Not all\n> + packets were received\")\n> +\n> +        error_messages = []\n> +        for pkt in captured_packets:\n> +            should_pass = pkt[TCP].payload.build() == b'1'\n> +            if not (self.validate_checksum(pkt, IP) == should_pass):\n> +                error_messages.append(f\"A packet was marked as having a\"\n> +                                      f\"{' valid' if should_pass == '' else 'n invalid'}\"\n> +                                      f\" checksum when it should have\n> + had the opposite.\")\n> +\n> +        self.dut.send_expect(\"stop\", \"testpmd>\")\n> +        if len(error_messages) != 0:\n> +            for error_msg in error_messages:\n> +                self.logger.error(error_msg)\n> +            self.verify(False, \"See prior output\")\n> +\n> +    def test_hardware_checksum_check_l4_rx(self):\n> +        self.checksum_enablehw(self.dut_ports[0])\n> +        self.dut.send_expect(\"start\", \"testpmd>\")\n> +\n> +        verification_errors: List[VerifyFailure] = []\n> +\n>          iface =\n> self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))\n>          dut_mac = self.dut.get_mac_address(self.dut_ports[0])\n>          tester_mac =\n> self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))\n> @@ -589,7 +802,7 @@ class TestChecksumOffload(TestCase):\n>                                  should_pass = outer_arg == \"\"\n>                              vf = self.send_pkt_expect_good_bad_from_flag_catch_failure(\n>                                  f\"eth/{l3}()/{l4}({outer_arg})/VXLAN()/{l3}()/\"\n> -                                f\"{l4}({inner_arg})/('X'*50)\",\n> +                                f\"{l4}(chksum={inner_arg})/('X'*50)\",\n>                                  flag, f\"{l3}/{l4}/VXLAN/{l3}/{l4}\",\n>                                  should_pass=should_pass)\n> \n> @@ -602,8 +815,7 @@ class TestChecksumOffload(TestCase):\n>                  for inner_arg in \"\", \"chksum=0xf\":\n>                      should_pass: bool = inner_arg == \"\"\n>                      vf = self.send_pkt_expect_good_bad_from_flag_catch_failure(\n> -                        f\"eth/{l3}()/GRE()/{l3}()/\"\n> -                        f\"{l4}({inner_arg})/('X'*50)\",\n> +\n> + f\"eth/{l3}()/GRE()/{l3}()/{l4}({inner_arg})/('X'*50)\",\n>                          \"PKT_RX_L4_CKSUM_\", f\"{l3}/GRE/{l3}/{l4}\",\n>                          should_pass=should_pass)\n> \n> @@ -615,6 +827,8 @@ class TestChecksumOffload(TestCase):\n>          # updated this test case can easily take advantage of the new functionality.\n> \n>          # # GENEVE\n> +        # # This import is over here so that it is not forgotten when the update\n> happens\n> +        # from scapy.contrib.geneve import GENEVE\n>          # for l3_outer in l3_protos:\n>          #     for l4_outer in l4_protos:\n>          #         for l3_inner in l3_protos:\n> @@ -638,7 +852,46 @@ class TestChecksumOffload(TestCase):\n>              self.logger.error(str(err))\n>          self.verify(len(verification_errors) == 0, \"See previous output\")\n> \n> +        self.tester.send_expect(\"quit\", \"#\")\n> +        self.dut.send_expect(\"stop\", \"testpmd>\")\n> +\n> +    def test_hardware_checksum_check_l4_tx(self):\n> +        self.checksum_enablehw(self.dut_ports[0])\n> +        self.dut.send_expect(\"start\", \"testpmd>\")\n> +\n> +        verification_errors: List[VerifyFailure] = []\n> +\n> +        iface =\n> self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))\n> +        dut_mac = self.dut.get_mac_address(self.dut_ports[0])\n> +        tester_mac =\n> + self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))\n> +\n> +        packets = self.get_packets(dut_mac, tester_mac)\n> +\n> +        capture_file_name =\n> \"test_hardware_checksum_check_l4_tx_capture.pcap\"\n> +\n> +        packet_file_path =\n> \"/tmp/test_hardware_checksum_check_l4_tx_packets.pcap\"\n> +        capture_file_path = \"/tmp/tester/\" + capture_file_name\n> +\n> +        self.tester.send_expect(f\"tcpdump -i {iface} -s 65535 -w\n> + {capture_file_path} &\", \"# \")\n> +\n> +        wrpcap(packet_file_path, packets)\n> +        self.tester.session.copy_file_to(packet_file_path,\n> + packet_file_path)\n> +\n> +        self.replay_pcap_file_on_tester(iface, packet_file_path)\n> +\n> +        self.tester.session.copy_file_from(packet_file_path,\n> + \"output/tmp/pcap/\" + capture_file_name)\n> +\n> +        captured_packets = rdpcap(\"output/tmp/pcap/\" +\n> + capture_file_name)\n> +\n> +        self.verify(len(packets) == len(captured_packets), \"Not all\n> + packets were received\")\n> +\n> +        error_messages =\n> + self.validate_packet_list_checksums(captured_packets)\n> +\n>          self.dut.send_expect(\"stop\", \"testpmd>\")\n> +        if len(error_messages) != 0:\n> +            for error_msg in error_messages:\n> +                self.logger.error(error_msg)\n> +            self.verify(False, \"See prior output\")\n> \n>      def tear_down(self):\n>          \"\"\"\n> --\n> 2.25.1",
        "headers": {
            "Return-Path": "<dts-bounces@dpdk.org>",
            "dlp-version": "11.2.0.6",
            "dlp-reaction": "no-action",
            "References": "<20200714145355.18410-1-ohilyard@iol.unh.edu>\n <20200720140744.210132-1-ohilyard@iol.unh.edu>",
            "X-Mailman-Version": "2.1.15",
            "X-IronPort-AV": [
                "E=McAfee;i=\"6000,8403,9691\"; a=\"212186175\"",
                "E=Sophos;i=\"5.75,389,1589266800\"; d=\"scan'208\";a=\"212186175\"",
                "E=Sophos;i=\"5.75,389,1589266800\"; d=\"scan'208\";a=\"271221232\""
            ],
            "From": "\"Tu, Lijuan\" <lijuan.tu@intel.com>",
            "x-originating-ip": "[10.239.127.40]",
            "IronPort-SDR": [
                "\n 4P5nE+JpDohkmeV2RQ0mMX8dYXP2syY0k4jstl263LpM+ndpodVkXM/XVw1ba5ONFfH4e84OBF\n R0iRETuVnW2g==",
                "\n Wt+WfBUza/I/TG1ayAL4dU2c+YAdroCbTAQ6V7Lt7MzlLcXZ+ZHHj7+jETGL9hqgZ1LvjCwg4v\n rf1IOwDtlFUw=="
            ],
            "Thread-Index": "AQHWXp89mL6E1oXHI0+62lB+zyCCzqkWC0OQ",
            "Message-ID": "\n <8CE3E05A3F976642AAB0F4675D0AD20E0BC84184@SHSMSX101.ccr.corp.intel.com>",
            "X-ExtLoop1": "1",
            "CC": "\"Yigit, Ferruh\" <ferruh.yigit@intel.com>, \"arybchenko@solarflare.com\"\n <arybchenko@solarflare.com>, \"olivier.matz@6wind.com\"\n <olivier.matz@6wind.com>, \"david.marchand@redhat.com\"\n <david.marchand@redhat.com>, \"ivan.malov@oktetlabs.ru\"\n <ivan.malov@oktetlabs.ru>, \"Richardson, Bruce\" <bruce.richardson@intel.com>,\n \"lylavoie@iol.unh.edu\" <lylavoie@iol.unh.edu>, \"rasland@mellanox.com\"\n <rasland@mellanox.com>, \"j.hendergart@f5.com\" <j.hendergart@f5.com>,\n \"thomas@monjalon.net\" <thomas@monjalon.net>",
            "Delivered-To": "patchwork@inbox.dpdk.org",
            "X-Original-To": "patchwork@inbox.dpdk.org",
            "Received": [
                "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id E9016A0518;\n\tFri, 24 Jul 2020 04:45:16 +0200 (CEST)",
                "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id DFB161D5F9;\n\tFri, 24 Jul 2020 04:45:16 +0200 (CEST)",
                "from mga06.intel.com (mga06.intel.com [134.134.136.31])\n by dpdk.org (Postfix) with ESMTP id EB3591D531\n for <dts@dpdk.org>; Fri, 24 Jul 2020 04:45:14 +0200 (CEST)",
                "from fmsmga007.fm.intel.com ([10.253.24.52])\n by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 23 Jul 2020 19:45:14 -0700",
                "from fmsmsx103.amr.corp.intel.com ([10.18.124.201])\n by fmsmga007.fm.intel.com with ESMTP; 23 Jul 2020 19:45:13 -0700",
                "from fmsmsx609.amr.corp.intel.com (10.18.126.89) by\n FMSMSX103.amr.corp.intel.com (10.18.124.201) with Microsoft SMTP Server (TLS)\n id 14.3.439.0; Thu, 23 Jul 2020 19:45:13 -0700",
                "from fmsmsx609.amr.corp.intel.com (10.18.126.89) by\n fmsmsx609.amr.corp.intel.com (10.18.126.89) with Microsoft SMTP Server\n (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id\n 15.1.1713.5; Thu, 23 Jul 2020 19:45:11 -0700",
                "from shsmsx154.ccr.corp.intel.com (10.239.6.54) by\n fmsmsx609.amr.corp.intel.com (10.18.126.89) with Microsoft SMTP Server\n (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.1713.5\n via Frontend Transport; Thu, 23 Jul 2020 19:45:11 -0700",
                "from shsmsx101.ccr.corp.intel.com ([169.254.1.22]) by\n SHSMSX154.ccr.corp.intel.com ([169.254.7.32]) with mapi id 14.03.0439.000;\n Fri, 24 Jul 2020 10:45:09 +0800"
            ],
            "Subject": "Re: [dts] [PATCH] checksum checks: Add hardware offload l3 and l4\n cases",
            "Sender": "\"dts\" <dts-bounces@dpdk.org>",
            "List-Help": "<mailto:dts-request@dpdk.org?subject=help>",
            "Content-Language": "en-US",
            "Accept-Language": "zh-CN, en-US",
            "Content-Type": "text/plain; charset=\"iso-2022-jp\"",
            "X-MS-Has-Attach": "",
            "X-BeenThere": "dts@dpdk.org",
            "Date": "Fri, 24 Jul 2020 02:45:08 +0000",
            "List-Archive": "<http://mails.dpdk.org/archives/dts/>",
            "X-Amp-File-Uploaded": "False",
            "List-Subscribe": "<https://mails.dpdk.org/listinfo/dts>,\n <mailto:dts-request@dpdk.org?subject=subscribe>",
            "List-Id": "test suite reviews and discussions <dts.dpdk.org>",
            "Precedence": "list",
            "Thread-Topic": "[dts] [PATCH] checksum checks: Add hardware offload l3 and l4\n cases",
            "In-Reply-To": "<20200720140744.210132-1-ohilyard@iol.unh.edu>",
            "Errors-To": "dts-bounces@dpdk.org",
            "List-Unsubscribe": "<https://mails.dpdk.org/options/dts>,\n <mailto:dts-request@dpdk.org?subject=unsubscribe>",
            "dlp-product": "dlpe-windows",
            "MIME-Version": "1.0",
            "List-Post": "<mailto:dts@dpdk.org>",
            "Content-Transfer-Encoding": "quoted-printable",
            "To": "Owen Hilyard <ohilyard@iol.unh.edu>, \"dts@dpdk.org\" <dts@dpdk.org>",
            "X-Amp-Result": "SKIPPED(no attachment in message)",
            "X-MS-TNEF-Correlator": ""
        }
    },
    {
        "id": 116603,
        "web_url": "https://patches.dpdk.org/comment/116603/",
        "msgid": "<CAHx6DYAUQcNwR52AhM6nxPwPFvyFvRBkmX0RZeto+R66ghE4Dg@mail.gmail.com>",
        "date": "2020-07-24T12:43:11",
        "subject": "Re: [dts] [PATCH] checksum checks: Add hardware offload l3 and l4\n\tcases",
        "submitter": {
            "id": 1829,
            "url": "https://patches.dpdk.org/api/people/1829/",
            "name": "Owen Hilyard",
            "email": "ohilyard@iol.unh.edu"
        },
        "content": "Unfortunately I had to start a new email thread since intel's server didn't\nlike the self-signed certificate on my local mail server. I merged all of\nthe patches into one patch so it's a little easier to review for the second\ntime.\n\nOn Thu, Jul 23, 2020 at 10:45 PM Tu, Lijuan <lijuan.tu@intel.com> wrote:\n\n> Is the patch based on the latest DTS ? sorry, I can't merge it because of\n> code conflict. Could you please rework it. Btw, all patches, v1/v2...\n> should be based on latest DTS.\n>\n> Thanks, Lijuan.\n>\n> > -----Original Message-----\n> > From: dts <dts-bounces@dpdk.org> On Behalf Of Owen Hilyard\n> > Sent: 2020年7月20日 22:08\n> > To: dts@dpdk.org\n> > Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; arybchenko@solarflare.com;\n> > olivier.matz@6wind.com; david.marchand@redhat.com;\n> > ivan.malov@oktetlabs.ru; Richardson, Bruce <bruce.richardson@intel.com>;\n> > lylavoie@iol.unh.edu; rasland@mellanox.com; j.hendergart@f5.com;\n> > ohilyard@iol.unh.edu; thomas@monjalon.net\n> > Subject: [dts] [PATCH] checksum checks: Add hardware offload l3 and l4\n> cases\n> >\n> > add rx and tx l3 test cases\n> > add tx l4 test case\n> > add documentation for new test cases\n> >\n> > Signed-off-by: Owen Hilyard <ohilyard@iol.unh.edu>\n> > ---\n> >  test_plans/checksum_offload_test_plan.rst | 122 +++++++-\n> >  tests/TestSuite_checksum_offload.py       | 331 +++++++++++++++++++---\n> >  2 files changed, 412 insertions(+), 41 deletions(-)\n> >\n> > diff --git a/test_plans/checksum_offload_test_plan.rst\n> > b/test_plans/checksum_offload_test_plan.rst\n> > index 4fd8c5a..de2e1a9 100644\n> > --- a/test_plans/checksum_offload_test_plan.rst\n> > +++ b/test_plans/checksum_offload_test_plan.rst\n> > @@ -221,7 +221,7 @@ combination: good/bad ip checksum + good/bad\n> > udp/tcp checksum.\n> >\n> >  Check the Rx checksum flags consistent with expected flags.\n> >\n> > -Test Case: Hardware Checksum Check L4\n> > +Test Case: Hardware Checksum Check L4 RX\n> >  ===========================================\n> >  This test involves testing many different scenarios with a L4 checksum.\n> >  A variety of tunneling protocols, L3 protocols and L4 protocols are\n> combined\n> > @@ -256,4 +256,122 @@ Send a packet with a bad checksum::\n> >     rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8\n> > flags=PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_BAD\n> > PKT_RX_OUTER_L4_CKSUM_UNKNOWN\n> >     tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4\n> >\n> > -Verify flags are as expected.\n> > \\ No newline at end of file\n> > +Verify flags are as expected.\n> > +\n> > +Test Case: Hardware Checksum Check L3 RX\n> > +===========================================\n> > +This test involves testing L3 checksum hardware offload.\n> > +Due to the relative dominance of IPv4 and IPv6 as L3 protocols, and\n> > +IPv6's lack of a checksum, only IPv4's checksum is tested.\n> > +\n> > +Setup the ``csum`` forwarding mode::\n> > +\n> > +  testpmd> set fwd csum\n> > +  Set csum packet forwarding mode\n> > +\n> > +Start the packet forwarding::\n> > +\n> > +  testpmd> start\n> > +    csum packet forwarding - CRC stripping disabled - packets/burst=32\n> > +    nb forwarding cores=1 - nb forwarding ports=10\n> > +    RX queues=1 - RX desc=128 - RX free threshold=64\n> > +    RX threshold registers: pthresh=8 hthresh=8 wthresh=4\n> > +    TX queues=1 - TX desc=512 - TX free threshold=0\n> > +    TX threshold registers: pthresh=32 hthresh=8 wthresh=8\n> > +\n> > +Send a packet with a good checksum::\n> > +\n> > +   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:\n> > +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8\n> > flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD\n> > PKT_RX_OUTER_L4_CKSUM_UNKNOWN\n> > +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4\n> > +\n> > +Send a packet with a bad checksum::\n> > +\n> > +   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:\n> > +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8\n> > flags=PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_BAD\n> > PKT_RX_OUTER_L4_CKSUM_UNKNOWN\n> > +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4\n> > +\n> > +Verify flags are as expected.\n> > +\n> > +Test Case: Hardware Checksum Check L4 TX\n> > +===========================================\n> > +This test involves testing many different scenarios with a L4 checksum.\n> > +A variety of tunneling protocols, L3 protocols and L4 protocols are\n> > +combined to test as many scenarios as possible. Currently, UDP, TCP and\n> > +SCTP are used as L4 protocols, with IP and IPv6 being used at level 3.\n> > +The tested tunneling protocols are VXLAN and GRE. This test is used to\n> > +determine whether the hardware offloading of checksums works properly.\n> > +\n> > +Setup the ``csum`` forwarding mode::\n> > +\n> > +  testpmd> set fwd csum\n> > +  Set csum packet forwarding mode\n> > +\n> > +Start the packet forwarding::\n> > +\n> > +  testpmd> start\n> > +    csum packet forwarding - CRC stripping disabled - packets/burst=32\n> > +    nb forwarding cores=1 - nb forwarding ports=10\n> > +    RX queues=1 - RX desc=128 - RX free threshold=64\n> > +    RX threshold registers: pthresh=8 hthresh=8 wthresh=4\n> > +    TX queues=1 - TX desc=512 - TX free threshold=0\n> > +    TX threshold registers: pthresh=32 hthresh=8 wthresh=8\n> > +\n> > +\n> > +Start a packet capture on the tester in the backround::\n> > +\n> > +   # tcpdump -i <iface> -s 65535 -w\n> > + /tmp/tester/test_hardware_checksum_check_l4_tx_capture.pcap &\n> > +\n> > +Send a packet with a good checksum::\n> > +\n> > +   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:\n> > +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8\n> > flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD\n> > PKT_RX_OUTER_L4_CKSUM_UNKNOWN\n> > +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4\n> > +\n> > +Send a packet with a bad checksum::\n> > +\n> > +   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:\n> > +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8\n> > flags=PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_GOOD\n> > PKT_RX_OUTER_L4_CKSUM_UNKNOWN\n> > +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4\n> > +\n> > +Inspect the pcap file from the packet capture and verify the checksums.\n> > +\n> > +Test Case: Hardware Checksum Check L3 TX\n> > +===========================================\n> > +This test involves testing L3 checksum hardware offload.\n> > +Due to the relative dominance of IPv4 and IPv6 as L3 protocols, and\n> > +IPv6's lack of a checksum, only IPv4's checksum is tested.\n> > +\n> > +Setup the ``csum`` forwarding mode::\n> > +\n> > +  testpmd> set fwd csum\n> > +  Set csum packet forwarding mode\n> > +\n> > +Start the packet forwarding::\n> > +\n> > +  testpmd> start\n> > +    csum packet forwarding - CRC stripping disabled - packets/burst=32\n> > +    nb forwarding cores=1 - nb forwarding ports=10\n> > +    RX queues=1 - RX desc=128 - RX free threshold=64\n> > +    RX threshold registers: pthresh=8 hthresh=8 wthresh=4\n> > +    TX queues=1 - TX desc=512 - TX free threshold=0\n> > +    TX threshold registers: pthresh=32 hthresh=8 wthresh=8\n> > +\n> > +\n> > +Start a packet capture on the tester in the backround::\n> > +\n> > +   # tcpdump -i <iface> -s 65535 -w\n> > + /tmp/tester/test_hardware_checksum_check_l3_tx_capture.pcap &\n> > +\n> > +Send a packet with a good checksum with a 1 in it's payload::\n> > +\n> > +   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:\n> > +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8\n> > flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD\n> > PKT_RX_OUTER_L4_CKSUM_UNKNOWN\n> > +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4\n> > +\n> > +Send a packet with a bad checksum with a 0 in it's payload::\n> > +\n> > +   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:\n> > +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8\n> > flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_BAD\n> > PKT_RX_OUTER_L4_CKSUM_UNKNOWN\n> > +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4\n> > +\n> > +Inspect the pcap file from the packet capture and verify the checksums.\n> > diff --git a/tests/TestSuite_checksum_offload.py\n> > b/tests/TestSuite_checksum_offload.py\n> > index 9ff5a41..c4a877d 100644\n> > --- a/tests/TestSuite_checksum_offload.py\n> > +++ b/tests/TestSuite_checksum_offload.py\n> > @@ -47,8 +47,18 @@ import time\n> >\n> >  from rst import RstReport\n> >  import utils\n> > -\n> > +from exception import VerifyFailure\n> > +from pktgen import PacketGeneratorHelper from scapy.layers.inet import\n> > +UDP, TCP, IP from scapy.layers.inet6 import IPv6 from scapy.layers.l2\n> > +import Ether, GRE from scapy.layers.sctp import SCTP from\n> > +scapy.layers.vxlan import VXLAN from scapy.packet import Raw from\n> > +scapy.utils import wrpcap, rdpcap from test_capabilities import\n> > +DRIVER_TEST_LACK_CAPA\n> >  from test_case import TestCase\n> > +\n> >  from framework.pmd_output import PmdOutput  from test_capabilities\n> import\n> > DRIVER_TEST_LACK_CAPA  from pktgen import PacketGeneratorHelper @@ -\n> > 57,6 +67,33 @@ import packet\n> >\n> >  from settings import FOLDERS\n> >\n> > +l3_proto_classes = [\n> > +    IP,\n> > +    IPv6\n> > +]\n> > +\n> > +l4_proto_classes = [\n> > +    UDP,\n> > +    TCP,\n> > +    SCTP\n> > +]\n> > +\n> > +tunnelling_proto_classes = [\n> > +    VXLAN,\n> > +    GRE,\n> > +]\n> > +\n> > +l3_protos = [\n> > +    \"IP\",\n> > +    \"IPv6\"\n> > +]\n> > +\n> > +l4_protos = [\n> > +    \"UDP\",\n> > +    \"TCP\",\n> > +    \"SCTP\",\n> > +]\n> > +\n> >\n> >  class TestChecksumOffload(TestCase):\n> >\n> > @@ -79,8 +116,6 @@ class TestChecksumOffload(TestCase):\n> >              cur_path = os.path.dirname(\n> >                  os.path.dirname(os.path.realpath(__file__)))\n> >              self.output_path = os.sep.join([cur_path,\n> self.logger.log_path])\n> > -        # create an instance to set stream field setting\n> > -        self.pktgen_helper = PacketGeneratorHelper()\n> >\n> >      def set_up(self):\n> >          \"\"\"\n> > @@ -243,7 +278,6 @@ class TestChecksumOffload(TestCase):\n> >      def send_pkt_expect_good_bad_from_flag(self, pkt_str: str, flag:\n> str,\n> > test_name: str, should_pass: bool = True):\n> >          self.pmdout.get_output(timeout=5)  # Remove any old output\n> >          self.scapy_exec(f\"sendp({pkt_str}, iface=iface)\")\n> > -        time.sleep(1)\n> >          testpmd_output: str = self.pmdout.get_output(timeout=5)\n> >          self.verify(flag in testpmd_output,\n> >                      f\"Flag {flag[:-1]} not found for test {test_name},\n> please run\n> > test_rx_checksum_valid_flags.\") @@ -269,11 +303,147 @@ class\n> > TestChecksumOffload(TestCase):\n> >\n> >          return None\n> >\n> > -    def scapy_exec(self, cmd: str):\n> > -        return self.tester.send_expect(cmd, \">>>\")\n> > +    def validate_checksum(self, pkt, layer) -> 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> > +\n> > +        csum = pkt[layer].chksum\n> > +        del pkt[layer].chksum\n> > +        # Converting it to raw will calculate the checksum\n> > +        return layer(Raw(pkt[layer])).chksum == csum\n> >\n> > -    def scapy_send_append(self, packet: str):\n> > -        return self.tester.scapy_append(f'sendp({packet}, iface=iface)')\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 = ({}, {'chksum': 0xf},)\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\n> packet was\n> > constructed so avoid any issues with\n> > +                    # ordering\n> > +                    pkt = eth / l3() / l4(**chksum) / (\n> > +                        f'UNTUNNELED,{l3.__name__},{l4.__name__},{\" \" if\n> > len(chksum.values()) == 0 else chksum[\"chksum\"]}'\n> > +                    )\n> > +\n> > +                    # Prevents the default behavior which adds DNS\n> headers\n> > +                    if l4 == UDP:\n> > +                        pkt[UDP].dport, pkt[UDP].sport = 1001, 1001\n> > +\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 = eth / l3() / UDP(**outer_arg) / VXLAN() /\n> Ether() / l3() /\n> > l4(**inner_arg) / (\n> > +                            f'VXLAN,{l3.__name__},{l4.__name__},'\n> > +                            f'{\" \" if len(outer_arg.values()) == 0 else\n> outer_arg[\"chksum\"]},'\n> > +                            f'{\" \" if len(inner_arg.values()) == 0 else\n> inner_arg[\"chksum\"]}'\n> > +                        )\n> > +                        # Prevents the default behavior which adds DNS\n> headers\n> > +                        if l4 == UDP:\n> > +                            pkt[VXLAN][UDP].dport,\n> > + pkt[VXLAN][UDP].sport = 1001, 1001\n> > +\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) / (\n> > +                        f'GRE,{l3.__name__},{l4.__name__},{\" \" if\n> len(chksum.values()) ==\n> > 0 else chksum[\"chksum\"]}'\n> > +                    )\n> > +\n> > +                    # Prevents the default behavior which adds DNS\n> headers\n> > +                    if l4 == UDP:\n> > +                        pkt[GRE][UDP].dport, pkt[GRE][UDP].sport =\n> > + 1001, 1001\n> > +\n> > +                    packets.append(pkt)\n> > +\n> > +        return packets\n> > +\n> > +    def replay_pcap_file_on_tester(self, iface, packet_file_path):\n> > +        self.tester.send_expect(\"scapy\", \">>>\")\n> > +        self.scapy_exec(f\"packets = rdpcap('{packet_file_path}')\")\n> > +        self.scapy_exec(f\"sendp(packets, iface={iface})\")\n> > +        self.tester.send_expect(\"quit()\", \"# \")\n> > +\n> > +    def validate_packet_list_checksums(self, packets):\n> > +        name_to_class_dict = {\n> > +            'UDP': UDP,\n> > +            'TCP': TCP,\n> > +            'SCTP': SCTP,\n> > +            'IP': IP,\n> > +            'IPv6': IPv6,\n> > +            'VXLAN': VXLAN,\n> > +            'GRE': GRE,\n> > +        }\n> > +\n> > +        error_messages = []\n> > +\n> > +        untunnelled_error_message = f\"Invalid untunneled checksum state\n> > for %s/%s with a %s checksum.\"\n> > +\n> > +        vxlan_error_message = f\"Invalid VXLAN tunnelled %s checksum\n> state\n> > for %s/%s\" \\\n> > +                              f\" with a %s inner checksum and a %s\n> outer checksum.\"\n> > +\n> > +        gre_error_message = f\"Invalid GRE tunnelled checksum state for\n> %s/%s\n> > with a %s checksum.\"\n> > +\n> > +        for packet in packets:\n> > +            payload: str\n> > +            # try:\n> > +            payload = packet[Raw].load.decode('utf-8').split(\",\")\n> > +            # # This error usually happens with tunneling protocols,\n> and means that\n> > an additional cast is needed\n> > +            # except UnicodeDecodeError:\n> > +            #     for proto in tunnelling_proto_classes:\n> > +\n> > +            l3 = name_to_class_dict[payload[1]]\n> > +            l4 = name_to_class_dict[payload[2]]\n> > +            if payload[0] == \"UNTUNNELED\":\n> > +                chksum_should_be_valid = payload[3] == \" \"\n> > +                if self.validate_checksum(packet, l4) !=\n> chksum_should_be_valid:\n> > +                    error_messages.append(\n> > +                        untunnelled_error_message % (\n> > +                            l3.__name__, l4.__name__, 'valid' if\n> chksum_should_be_valid\n> > == '' else 'invalid'\n> > +                        )\n> > +                    )\n> > +            elif payload[0] == \"VXLAN\":\n> > +                outer_chksum_should_be_valid = payload[3] == \" \"\n> > +                inner_chksum_should_be_valid = payload[4] == \" \"\n> > +                if self.validate_checksum(packet[VXLAN], l4) !=\n> > inner_chksum_should_be_valid:\n> > +                    error_messages.append(\n> > +                        vxlan_error_message % (\n> > +                            \"inner\", l4.__name__, l3.__name__,\n> > +                            'valid' if inner_chksum_should_be_valid ==\n> '' else 'invalid',\n> > +                            'valid' if outer_chksum_should_be_valid ==\n> '' else 'invalid'\n> > +                        )\n> > +                    )\n> > +                if self.validate_checksum(packet, l4) !=\n> > outer_chksum_should_be_valid:\n> > +                    error_messages.append(\n> > +                        vxlan_error_message % (\n> > +                            \"outer\", l3.__name__, l4.__name__,\n> > +                            'valid' if inner_chksum_should_be_valid ==\n> '' else 'invalid',\n> > +                            'valid' if outer_chksum_should_be_valid ==\n> '' else 'invalid'\n> > +                        )\n> > +                    )\n> > +            elif payload[0] == \"GRE\":\n> > +                chksum_should_be_valid = payload[3] == \" \"\n> > +                if self.validate_checksum(packet, l4) !=\n> chksum_should_be_valid:\n> > +                    error_messages.append(\n> > +                        gre_error_message % (\n> > +                            l3.__name__, l4.__name__, 'valid' if\n> chksum_should_be_valid\n> > == '' else 'invalid'\n> > +                        )\n> > +                    )\n> > +\n> > +        return error_messages\n> >\n> >      #\n> >      #\n> > @@ -448,6 +618,9 @@ class TestChecksumOffload(TestCase):\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\n> functional tests\n> > to use scapy.\n> > +            self.pktgen_helper = PacketGeneratorHelper()\n> >              # run packet generator\n> >              streams =\n> self.pktgen_helper.prepare_stream_from_tginput(tgenInput,\n> > 100,\n> >                      None, self.tester.pktgen) @@ -511,53 +684,93 @@\n> class\n> > TestChecksumOffload(TestCase):\n> >              self.dut.send_expect(\"quit\", \"#\", 10)\n> >              self.result_table_print()\n> >\n> > -    def test_hardware_checksum_check_ip(self):\n> > +    def test_hardware_checksum_check_ip_rx(self):\n> >          self.dut.send_expect(\"start\", \"testpmd>\")\n> > +        self.tester.send_expect(\"scapy\", \">>>\")\n> >          self.checksum_enablehw(self.dut_ports[0])\n> > +        self.dut.send_expect(\"start\", \"testpmd>\")\n> >\n> >          verification_errors: List[VerifyFailure] = []\n> >\n> > -        # untunnelled\n> > -        vf =\n> > self.try_helper_hardware_checksum_check_catch_failure('Ether(dst=\"%s\",\n> > src=\"%s\")/IP(%s)/UDP()/(\"X\"*50)',\n> > -\n>  \"PKT_RX_IP_CKSUM_\")\n> > -        if vf is not None:\n> > -            verification_errors.append(vf)\n> > +        iface =\n> > self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))\n> > +        dut_mac = self.dut.get_mac_address(self.dut_ports[0])\n> > +        tester_mac =\n> > + self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))\n> >\n> > -        # tunneled inner\n> > -        vf = self.try_helper_hardware_checksum_check_catch_failure(\n> > -            'Ether(dst=\"%s\", src=\"%s\")/IP()/UDP()/IP(%s)/(\"X\"*50)',\n> > -            \"PKT_RX_OUTER_IP_CKSUM_\")\n> > -        if vf is not None:\n> > -            verification_errors.append(vf)\n> > +        self.scapy_exec(f\"eth = Ether(dst='{dut_mac}',\n> src='{tester_mac}')\")\n> > +        self.scapy_exec(f\"iface = '{iface}'\")\n> >\n> > -        # tunneled outer\n> > -        vf = self.try_helper_hardware_checksum_check_catch_failure(\n> > -            'Ether(dst=\"%s\", src=\"%s\")/IP()/UDP()/IP(%s)/(\"X\"*50)',\n> > -            \"PKT_RX_OUTER_IP_CKSUM_\")\n> > -        if vf is not None:\n> > -            verification_errors.append(vf)\n> > +        # Untunnelled\n> > +        for l4 in l4_protos:\n> > +            for chksum in \"\", \"chksum=0xf\":\n> > +                vf =\n> self.send_pkt_expect_good_bad_from_flag_catch_failure(\n> > +                    f\"eth/IP({chksum})/{l4}()/(X'*50)\",\n> > +                    \"PKT_RX_IP_CKSUM_\", f\"{l4}\",\n> > +                    should_pass=(chksum == \"\"))\n> > +                if vf is not None:\n> > +                    verification_errors.append(vf)\n> >\n> > -        self.verify(len(verification_errors) == 0,\n> \"\\n\".join(verification_errors))\n> > +        for err in verification_errors:\n> > +            self.logger.error(str(err))\n> > +        self.verify(len(verification_errors) == 0, \"See previous\n> > + output\")\n> >\n> > +        self.tester.send_expect(\"quit()\", \"# \")\n> >          self.dut.send_expect(\"stop\", \"testpmd>\")\n> >\n> > -    def test_hardware_checksum_check_l4(self):\n> > +    def test_hardware_checksum_check_ip_tx(self):\n> >          self.checksum_enablehw(self.dut_ports[0])\n> >          self.dut.send_expect(\"start\", \"testpmd>\")\n> >\n> >          verification_errors: List[VerifyFailure] = []\n> >\n> > -        l3_protos: List[str] = [\n> > -            \"IP\",\n> > -            \"IPv6\"\n> > -        ]\n> > +        iface =\n> > self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))\n> > +        dut_mac = self.dut.get_mac_address(self.dut_ports[0])\n> > +        tester_mac =\n> > self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))\n> > +        eth = Ether(dst=dut_mac, src=tester_mac)\n> >\n> > -        l4_protos: List[str] = [\n> > -            \"UDP\",\n> > -            \"TCP\",\n> > -            \"SCTP\",\n> > +        checksum_options = ({}, {'chksum': 0xf},)\n> > +\n> > +        packets = [\n> > +            eth / IP(**chksum) / TCP() / Raw(load=str(int(len(chksum)\n> > + != 1))) for chksum in checksum_options\n> >          ]\n> >\n> > +        capture_file_name =\n> > \"test_hardware_checksum_check_l3_tx_capture.pcap\"\n> > +\n> > +        packet_file_path =\n> > \"/tmp/test_hardware_checksum_check_l3_tx_packets.pcap\"\n> > +        capture_file_path = \"/tmp/tester/\" + capture_file_name\n> > +\n> > +        self.tester.send_expect(f\"tcpdump -i {iface} -s 65535 -w\n> > + {capture_file_path} &\", \"# \")\n> > +\n> > +        wrpcap(packet_file_path, packets)\n> > +        self.tester.session.copy_file_to(packet_file_path,\n> > + packet_file_path)\n> > +\n> > +        self.replay_pcap_file_on_tester(iface, packet_file_path)\n> > +\n> > +        self.tester.session.copy_file_from(packet_file_path,\n> > + \"output/tmp/pcap/\" + capture_file_name)\n> > +\n> > +        captured_packets = rdpcap(\"output/tmp/pcap/\" +\n> > + capture_file_name)\n> > +\n> > +        self.verify(len(packets) == len(captured_packets), \"Not all\n> > + packets were received\")\n> > +\n> > +        error_messages = []\n> > +        for pkt in captured_packets:\n> > +            should_pass = pkt[TCP].payload.build() == b'1'\n> > +            if not (self.validate_checksum(pkt, IP) == should_pass):\n> > +                error_messages.append(f\"A packet was marked as having a\"\n> > +                                      f\"{' valid' if should_pass == ''\n> else 'n invalid'}\"\n> > +                                      f\" checksum when it should have\n> > + had the opposite.\")\n> > +\n> > +        self.dut.send_expect(\"stop\", \"testpmd>\")\n> > +        if len(error_messages) != 0:\n> > +            for error_msg in error_messages:\n> > +                self.logger.error(error_msg)\n> > +            self.verify(False, \"See prior output\")\n> > +\n> > +    def test_hardware_checksum_check_l4_rx(self):\n> > +        self.checksum_enablehw(self.dut_ports[0])\n> > +        self.dut.send_expect(\"start\", \"testpmd>\")\n> > +\n> > +        verification_errors: List[VerifyFailure] = []\n> > +\n> >          iface =\n> > self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))\n> >          dut_mac = self.dut.get_mac_address(self.dut_ports[0])\n> >          tester_mac =\n> > self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))\n> > @@ -589,7 +802,7 @@ class TestChecksumOffload(TestCase):\n> >                                  should_pass = outer_arg == \"\"\n> >                              vf =\n> self.send_pkt_expect_good_bad_from_flag_catch_failure(\n> >\n> f\"eth/{l3}()/{l4}({outer_arg})/VXLAN()/{l3}()/\"\n> > -                                f\"{l4}({inner_arg})/('X'*50)\",\n> > +                                f\"{l4}(chksum={inner_arg})/('X'*50)\",\n> >                                  flag, f\"{l3}/{l4}/VXLAN/{l3}/{l4}\",\n> >                                  should_pass=should_pass)\n> >\n> > @@ -602,8 +815,7 @@ class TestChecksumOffload(TestCase):\n> >                  for inner_arg in \"\", \"chksum=0xf\":\n> >                      should_pass: bool = inner_arg == \"\"\n> >                      vf =\n> self.send_pkt_expect_good_bad_from_flag_catch_failure(\n> > -                        f\"eth/{l3}()/GRE()/{l3}()/\"\n> > -                        f\"{l4}({inner_arg})/('X'*50)\",\n> > +\n> > + f\"eth/{l3}()/GRE()/{l3}()/{l4}({inner_arg})/('X'*50)\",\n> >                          \"PKT_RX_L4_CKSUM_\", f\"{l3}/GRE/{l3}/{l4}\",\n> >                          should_pass=should_pass)\n> >\n> > @@ -615,6 +827,8 @@ class TestChecksumOffload(TestCase):\n> >          # updated this test case can easily take advantage of the new\n> functionality.\n> >\n> >          # # GENEVE\n> > +        # # This import is over here so that it is not forgotten when\n> the update\n> > happens\n> > +        # from scapy.contrib.geneve import GENEVE\n> >          # for l3_outer in l3_protos:\n> >          #     for l4_outer in l4_protos:\n> >          #         for l3_inner in l3_protos:\n> > @@ -638,7 +852,46 @@ class TestChecksumOffload(TestCase):\n> >              self.logger.error(str(err))\n> >          self.verify(len(verification_errors) == 0, \"See previous\n> output\")\n> >\n> > +        self.tester.send_expect(\"quit\", \"#\")\n> > +        self.dut.send_expect(\"stop\", \"testpmd>\")\n> > +\n> > +    def test_hardware_checksum_check_l4_tx(self):\n> > +        self.checksum_enablehw(self.dut_ports[0])\n> > +        self.dut.send_expect(\"start\", \"testpmd>\")\n> > +\n> > +        verification_errors: List[VerifyFailure] = []\n> > +\n> > +        iface =\n> > self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))\n> > +        dut_mac = self.dut.get_mac_address(self.dut_ports[0])\n> > +        tester_mac =\n> > + self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))\n> > +\n> > +        packets = self.get_packets(dut_mac, tester_mac)\n> > +\n> > +        capture_file_name =\n> > \"test_hardware_checksum_check_l4_tx_capture.pcap\"\n> > +\n> > +        packet_file_path =\n> > \"/tmp/test_hardware_checksum_check_l4_tx_packets.pcap\"\n> > +        capture_file_path = \"/tmp/tester/\" + capture_file_name\n> > +\n> > +        self.tester.send_expect(f\"tcpdump -i {iface} -s 65535 -w\n> > + {capture_file_path} &\", \"# \")\n> > +\n> > +        wrpcap(packet_file_path, packets)\n> > +        self.tester.session.copy_file_to(packet_file_path,\n> > + packet_file_path)\n> > +\n> > +        self.replay_pcap_file_on_tester(iface, packet_file_path)\n> > +\n> > +        self.tester.session.copy_file_from(packet_file_path,\n> > + \"output/tmp/pcap/\" + capture_file_name)\n> > +\n> > +        captured_packets = rdpcap(\"output/tmp/pcap/\" +\n> > + capture_file_name)\n> > +\n> > +        self.verify(len(packets) == len(captured_packets), \"Not all\n> > + packets were received\")\n> > +\n> > +        error_messages =\n> > + self.validate_packet_list_checksums(captured_packets)\n> > +\n> >          self.dut.send_expect(\"stop\", \"testpmd>\")\n> > +        if len(error_messages) != 0:\n> > +            for error_msg in error_messages:\n> > +                self.logger.error(error_msg)\n> > +            self.verify(False, \"See prior output\")\n> >\n> >      def tear_down(self):\n> >          \"\"\"\n> > --\n> > 2.25.1\n>\n>",
        "headers": {
            "Return-Path": "<dts-bounces@dpdk.org>",
            "References": "<20200714145355.18410-1-ohilyard@iol.unh.edu>\n <20200720140744.210132-1-ohilyard@iol.unh.edu>\n <8CE3E05A3F976642AAB0F4675D0AD20E0BC84184@SHSMSX101.ccr.corp.intel.com>",
            "X-Mailman-Version": "2.1.15",
            "Date": "Fri, 24 Jul 2020 08:43:11 -0400",
            "List-Post": "<mailto:dts@dpdk.org>",
            "X-BeenThere": "dts@dpdk.org",
            "Content-Type": "multipart/alternative; boundary=\"000000000000f5d56005ab2f52ac\"",
            "MIME-Version": "1.0",
            "X-Original-To": "patchwork@inbox.dpdk.org",
            "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20161025;\n h=x-gm-message-state:mime-version:references:in-reply-to:from:date\n :message-id:subject:to:cc;\n bh=I2zZDBvST5jItuo1Bdh1191Lwa76G7zWT2ReR3KJeTk=;\n b=HOUrS0FusOixTGqU3jotqjJO6QNFcAxqLZ0YCynzBZ0LBanyshE84DeZKZDkqzoO03\n 3dIWqD/4J8N2Vi/2P64nlrHSqzcK1/qa0/CO6iHp6Uf7LI1ov9NBpPp3gl4KDx3TnTXV\n jZMQVmYIlm2yWA63htA4XxEy4DUF9fL+ZCD+exaeiVk8yXSX4G1LON2uFPAJCodpoP9c\n t/Bspq/ZMXQ5GZlDH4FOQELh8JrVyCGQ8/tWbCOSv5c76NuHX1sDr69qgl8jsyrFZYM6\n Hlp6aWQRqoT/O5gjoWgFxhRPy4ZWBM1kVyP71GnIv2kMdjwg61FGg9GzPcH6HcpnESxE\n 4JRg==",
            "Received": [
                "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id C9C70A0526;\n\tFri, 24 Jul 2020 14:43:49 +0200 (CEST)",
                "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id BD3031BFE7;\n\tFri, 24 Jul 2020 14:43:49 +0200 (CEST)",
                "from mail-qv1-f53.google.com (mail-qv1-f53.google.com\n [209.85.219.53]) by dpdk.org (Postfix) with ESMTP id 016841BFE3\n for <dts@dpdk.org>; Fri, 24 Jul 2020 14:43:47 +0200 (CEST)",
                "by mail-qv1-f53.google.com with SMTP id y11so1065841qvl.4\n for <dts@dpdk.org>; Fri, 24 Jul 2020 05:43:47 -0700 (PDT)"
            ],
            "Subject": "Re: [dts] [PATCH] checksum checks: Add hardware offload l3 and l4\n\tcases",
            "X-Received": "by 2002:a0c:e252:: with SMTP id x18mr9476270qvl.30.1595594627200;\n Fri, 24 Jul 2020 05:43:47 -0700 (PDT)",
            "List-Help": "<mailto:dts-request@dpdk.org?subject=help>",
            "From": "Owen Hilyard <ohilyard@iol.unh.edu>",
            "Message-ID": "\n <CAHx6DYAUQcNwR52AhM6nxPwPFvyFvRBkmX0RZeto+R66ghE4Dg@mail.gmail.com>",
            "Precedence": "list",
            "X-Gm-Message-State": "AOAM530wclpz9+TwcTG/TFozfA5aC7hXGYPT0Yrvq0V4mdJa0vrkDQ1n\n CiiFp4IX+TZYtOPC3zb9MoY/BBOCOP5Ujs5c6cM07Q==",
            "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=iol.unh.edu;\n s=unh-iol;\n h=mime-version:references:in-reply-to:from:date:message-id:subject:to\n :cc; bh=I2zZDBvST5jItuo1Bdh1191Lwa76G7zWT2ReR3KJeTk=;\n b=VgqUtwl0g7hCVc23lGmk6QrEODHtSx7xhwhbfXqkwz6atY1NtR0dfZQ6+p0zs+Z9YM\n 2T2RDMl89FxamXNNp8vD/ZVgmoz/gL43oFV/3CxP3HLGjktXm3rxRaxzStDjsmYwEMZw\n ifBbnhnHRVDvK8wifmL63VfQmLZs8qGEjmKlY=",
            "List-Archive": "<http://mails.dpdk.org/archives/dts/>",
            "Sender": "\"dts\" <dts-bounces@dpdk.org>",
            "Errors-To": "dts-bounces@dpdk.org",
            "List-Subscribe": "<https://mails.dpdk.org/listinfo/dts>,\n <mailto:dts-request@dpdk.org?subject=subscribe>",
            "X-Google-Smtp-Source": "\n ABdhPJxsyzGtO8nS3ioRAdFIdr2Wo2Ov6cnmJCw/OLsyJPdI9GPYSMFe/YDVOMBiIJDRYh1OWxmqsnXQRuiD5cLmiV8=",
            "Cc": "\"dts@dpdk.org\" <dts@dpdk.org>, \"Yigit, Ferruh\" <ferruh.yigit@intel.com>,\n \"arybchenko@solarflare.com\" <arybchenko@solarflare.com>,\n \"olivier.matz@6wind.com\" <olivier.matz@6wind.com>,\n \"david.marchand@redhat.com\" <david.marchand@redhat.com>,\n \"ivan.malov@oktetlabs.ru\" <ivan.malov@oktetlabs.ru>, \"Richardson,\n Bruce\" <bruce.richardson@intel.com>,\n \"lylavoie@iol.unh.edu\" <lylavoie@iol.unh.edu>,\n \"rasland@mellanox.com\" <rasland@mellanox.com>,\n \"j.hendergart@f5.com\" <j.hendergart@f5.com>,\n \"thomas@monjalon.net\" <thomas@monjalon.net>",
            "List-Id": "test suite reviews and discussions <dts.dpdk.org>",
            "Delivered-To": "patchwork@inbox.dpdk.org",
            "In-Reply-To": "\n <8CE3E05A3F976642AAB0F4675D0AD20E0BC84184@SHSMSX101.ccr.corp.intel.com>",
            "List-Unsubscribe": "<https://mails.dpdk.org/options/dts>,\n <mailto:dts-request@dpdk.org?subject=unsubscribe>",
            "To": "\"Tu, Lijuan\" <lijuan.tu@intel.com>"
        }
    }
]