List patch comments

GET /api/patches/74497/comments/?format=api&order=id
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Link: 
<https://patches.dpdk.org/api/patches/74497/comments/?format=api&order=id&page=1>; rel="first",
<https://patches.dpdk.org/api/patches/74497/comments/?format=api&order=id&page=1>; rel="last"
Vary: Accept
[ { "id": 116572, "web_url": "https://patches.dpdk.org/comment/116572/", "msgid": "<8CE3E05A3F976642AAB0F4675D0AD20E0BC84184@SHSMSX101.ccr.corp.intel.com>", "list_archive_url": "https://inbox.dpdk.org/dts/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/?format=api", "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>", "X-Original-To": "patchwork@inbox.dpdk.org", "Delivered-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" ], "IronPort-SDR": [ "\n 4P5nE+JpDohkmeV2RQ0mMX8dYXP2syY0k4jstl263LpM+ndpodVkXM/XVw1ba5ONFfH4e84OBF\n R0iRETuVnW2g==", "\n Wt+WfBUza/I/TG1ayAL4dU2c+YAdroCbTAQ6V7Lt7MzlLcXZ+ZHHj7+jETGL9hqgZ1LvjCwg4v\n rf1IOwDtlFUw==" ], "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\"" ], "X-Amp-Result": "SKIPPED(no attachment in message)", "X-Amp-File-Uploaded": "False", "X-ExtLoop1": "1", "From": "\"Tu, Lijuan\" <lijuan.tu@intel.com>", "To": "Owen Hilyard <ohilyard@iol.unh.edu>, \"dts@dpdk.org\" <dts@dpdk.org>", "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>", "Thread-Topic": "[dts] [PATCH] checksum checks: Add hardware offload l3 and l4\n cases", "Thread-Index": "AQHWXp89mL6E1oXHI0+62lB+zyCCzqkWC0OQ", "Date": "Fri, 24 Jul 2020 02:45:08 +0000", "Message-ID": "\n <8CE3E05A3F976642AAB0F4675D0AD20E0BC84184@SHSMSX101.ccr.corp.intel.com>", "References": "<20200714145355.18410-1-ohilyard@iol.unh.edu>\n <20200720140744.210132-1-ohilyard@iol.unh.edu>", "In-Reply-To": "<20200720140744.210132-1-ohilyard@iol.unh.edu>", "Accept-Language": "zh-CN, en-US", "Content-Language": "en-US", "X-MS-Has-Attach": "", "X-MS-TNEF-Correlator": "", "dlp-product": "dlpe-windows", "dlp-version": "11.2.0.6", "dlp-reaction": "no-action", "x-originating-ip": "[10.239.127.40]", "Content-Type": "text/plain; charset=\"iso-2022-jp\"", "Content-Transfer-Encoding": "quoted-printable", "MIME-Version": "1.0", "Subject": "Re: [dts] [PATCH] checksum checks: Add hardware offload l3 and l4\n cases", "X-BeenThere": "dts@dpdk.org", "X-Mailman-Version": "2.1.15", "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", "Sender": "\"dts\" <dts-bounces@dpdk.org>" }, "addressed": null }, { "id": 116603, "web_url": "https://patches.dpdk.org/comment/116603/", "msgid": "<CAHx6DYAUQcNwR52AhM6nxPwPFvyFvRBkmX0RZeto+R66ghE4Dg@mail.gmail.com>", "list_archive_url": "https://inbox.dpdk.org/dts/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/?format=api", "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>", "X-Original-To": "patchwork@inbox.dpdk.org", "Delivered-To": "patchwork@inbox.dpdk.org", "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)" ], "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=", "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==", "X-Gm-Message-State": "AOAM530wclpz9+TwcTG/TFozfA5aC7hXGYPT0Yrvq0V4mdJa0vrkDQ1n\n CiiFp4IX+TZYtOPC3zb9MoY/BBOCOP5Ujs5c6cM07Q==", "X-Google-Smtp-Source": "\n ABdhPJxsyzGtO8nS3ioRAdFIdr2Wo2Ov6cnmJCw/OLsyJPdI9GPYSMFe/YDVOMBiIJDRYh1OWxmqsnXQRuiD5cLmiV8=", "X-Received": "by 2002:a0c:e252:: with SMTP id x18mr9476270qvl.30.1595594627200;\n Fri, 24 Jul 2020 05:43:47 -0700 (PDT)", "MIME-Version": "1.0", "References": "<20200714145355.18410-1-ohilyard@iol.unh.edu>\n <20200720140744.210132-1-ohilyard@iol.unh.edu>\n <8CE3E05A3F976642AAB0F4675D0AD20E0BC84184@SHSMSX101.ccr.corp.intel.com>", "In-Reply-To": "\n <8CE3E05A3F976642AAB0F4675D0AD20E0BC84184@SHSMSX101.ccr.corp.intel.com>", "From": "Owen Hilyard <ohilyard@iol.unh.edu>", "Date": "Fri, 24 Jul 2020 08:43:11 -0400", "Message-ID": "\n <CAHx6DYAUQcNwR52AhM6nxPwPFvyFvRBkmX0RZeto+R66ghE4Dg@mail.gmail.com>", "To": "\"Tu, Lijuan\" <lijuan.tu@intel.com>", "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>", "Content-Type": "multipart/alternative; boundary=\"000000000000f5d56005ab2f52ac\"", "Subject": "Re: [dts] [PATCH] checksum checks: Add hardware offload l3 and l4\n\tcases", "X-BeenThere": "dts@dpdk.org", "X-Mailman-Version": "2.1.15", "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", "Sender": "\"dts\" <dts-bounces@dpdk.org>" }, "addressed": null } ]