Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/74497/?format=api
https://patches.dpdk.org/api/patches/74497/?format=api", "web_url": "https://patches.dpdk.org/project/dts/patch/20200720140744.210132-1-ohilyard@iol.unh.edu/", "project": { "id": 3, "url": "https://patches.dpdk.org/api/projects/3/?format=api", "name": "DTS", "link_name": "dts", "list_id": "dts.dpdk.org", "list_email": "dts@dpdk.org", "web_url": "", "scm_url": "git://dpdk.org/tools/dts", "webscm_url": "http://git.dpdk.org/tools/dts/", "list_archive_url": "https://inbox.dpdk.org/dts", "list_archive_url_format": "https://inbox.dpdk.org/dts/{}", "commit_url_format": "" }, "msgid": "<20200720140744.210132-1-ohilyard@iol.unh.edu>", "list_archive_url": "https://inbox.dpdk.org/dts/20200720140744.210132-1-ohilyard@iol.unh.edu", "date": "2020-07-20T14:07:44", "name": "checksum checks: Add hardware offload l3 and l4 cases", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "9a6833d2e221d6a8a2d8cc159ce60a786c752282", "submitter": { "id": 1829, "url": "https://patches.dpdk.org/api/people/1829/?format=api", "name": "Owen Hilyard", "email": "ohilyard@iol.unh.edu" }, "delegate": null, "mbox": "https://patches.dpdk.org/project/dts/patch/20200720140744.210132-1-ohilyard@iol.unh.edu/mbox/", "series": [ { "id": 11172, "url": "https://patches.dpdk.org/api/series/11172/?format=api", "web_url": "https://patches.dpdk.org/project/dts/list/?series=11172", "date": "2020-07-20T14:07:44", "name": "checksum checks: Add hardware offload l3 and l4 cases", "version": 1, "mbox": "https://patches.dpdk.org/series/11172/mbox/" } ], "comments": "https://patches.dpdk.org/api/patches/74497/comments/", "check": "pending", "checks": "https://patches.dpdk.org/api/patches/74497/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<dts-bounces@dpdk.org>", "X-Original-To": "patchwork@inbox.dpdk.org", "Delivered-To": "patchwork@inbox.dpdk.org", "Received": [ "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 741A8A0540;\n\tMon, 20 Jul 2020 16:07:53 +0200 (CEST)", "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 319DD1DBB;\n\tMon, 20 Jul 2020 16:07:53 +0200 (CEST)", "from mail-qt1-f182.google.com (mail-qt1-f182.google.com\n [209.85.160.182]) by dpdk.org (Postfix) with ESMTP id DE3BF1AFB\n for <dts@dpdk.org>; Mon, 20 Jul 2020 16:07:51 +0200 (CEST)", "by mail-qt1-f182.google.com with SMTP id g13so13034964qtv.8\n for <dts@dpdk.org>; Mon, 20 Jul 2020 07:07:51 -0700 (PDT)", "from ohilyard-Alienware-m17.iol.unh.edu\n ([2606:4100:3880:1254::1033])\n by smtp.gmail.com with ESMTPSA id a20sm20178021qtw.54.2020.07.20.07.07.46\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Mon, 20 Jul 2020 07:07:47 -0700 (PDT)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=iol.unh.edu;\n s=unh-iol;\n h=from:to:cc:subject:date:message-id:in-reply-to:references\n :mime-version:content-transfer-encoding;\n bh=X9IVoRlh6w4belSqb1wmOYoy+pfxCshOg7gXowFHgh0=;\n b=b8UhLxNQBufWoUGhRV/rf4y4bCeEDqPbhqkkmyTWurn7Mv+7fc3mpYOp+x9lCmj/f3\n OcLdZjez7FNnuDWLH2VMXQVJhZH31+HZ/ZBXPqdsgvsq5yiXav073rJ5ArwnLXQq35sP\n xJbAW5MyOynL1MpsSukUSOQmsIT5W7cNbPxgU=", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20161025;\n h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n :references:mime-version:content-transfer-encoding;\n bh=X9IVoRlh6w4belSqb1wmOYoy+pfxCshOg7gXowFHgh0=;\n b=Op5FG/fXJDXCqH1CuSzWnU/VBLgqxmXRcuc7LQV5E7G6aYwhZlDMTOiBl5hSgUShCX\n +j8aU9U1MiEq71oGfDsGp58eNvv2rrlrbf73o+1hlUcs+RythWrB+jG1lEUa+PvnUu1d\n elJDA9BBdSfCsd26gXS1YhRl47pa7IobqBnh/YEvaEuvsvjU/kwz3UE01hv7M1CyThx7\n LiQCDJB/krtxBiW3JIZC/ZweGCU24J3ErcglaNuJIhNsIiVxYTgTQLwDm1rMv/7oOfjz\n TJiIakwaUFiVRvoK5SK9kREmp9+ZP13piw9/YN3hwyIcQ6CXoSbY7lDuFl/YqUoap4iF\n Y0nw==", "X-Gm-Message-State": "AOAM533mxmgbRKuphT0amaCVMvIKm7+s1e3HYnNe4qTHYvgLMks8JUi3\n hBBx7cpERk89fS/l7hcZ0zxGIcCSRHE3X4I9SgJo3I+BBVL5Ka7UDaqxgiKl1pW17r8BiyTNaOz\n XOJ2l905UqEiiEyEv+YxwTZGLlM7+vUbsCeoXU6UjcK9/eW6h1RtREDT3+A==", "X-Google-Smtp-Source": "\n ABdhPJzwNtkDYEspkC/g+q+cR7h60fKzwVMvRmt28LrrQN82wHz7SaQjhAtprl1J3GE0WyOp3iHdeA==", "X-Received": "by 2002:aed:2684:: with SMTP id q4mr23722426qtd.208.1595254067780;\n Mon, 20 Jul 2020 07:07:47 -0700 (PDT)", "From": "Owen Hilyard <ohilyard@iol.unh.edu>", "To": "dts@dpdk.org", "Cc": "ferruh.yigit@intel.com, arybchenko@solarflare.com, olivier.matz@6wind.com,\n david.marchand@redhat.com, ivan.malov@oktetlabs.ru,\n bruce.richardson@intel.com, lylavoie@iol.unh.edu, rasland@mellanox.com,\n j.hendergart@f5.com, ohilyard@iol.unh.edu, thomas@monjalon.net", "Date": "Mon, 20 Jul 2020 10:07:44 -0400", "Message-Id": "<20200720140744.210132-1-ohilyard@iol.unh.edu>", "X-Mailer": "git-send-email 2.25.1", "In-Reply-To": "<20200714145355.18410-1-ohilyard@iol.unh.edu>", "References": "<20200714145355.18410-1-ohilyard@iol.unh.edu>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Subject": "[dts] [PATCH] checksum checks: Add hardware offload l3 and l4 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>" }, "content": "add rx and tx l3 test cases\nadd tx l4 test case\nadd documentation for new test cases\n\nSigned-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(-)", "diff": "diff --git a/test_plans/checksum_offload_test_plan.rst b/test_plans/checksum_offload_test_plan.rst\nindex 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 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 flags=PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_BAD 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 IPv6's\n+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 flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD 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 flags=PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_BAD 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 combined\n+to test as many scenarios as possible. Currently, UDP, TCP and SCTP are used\n+as L4 protocols, with IP and IPv6 being used at level 3. The tested tunneling\n+protocols are VXLAN and GRE. This test is used to determine whether the\n+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 /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 flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD 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 flags=PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_GOOD 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 IPv6's\n+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 /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 flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD 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 flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_BAD 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.\ndiff --git a/tests/TestSuite_checksum_offload.py b/tests/TestSuite_checksum_offload.py\nindex 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\n+from scapy.layers.inet import UDP, TCP, IP\n+from scapy.layers.inet6 import IPv6\n+from scapy.layers.l2 import Ether, GRE\n+from scapy.layers.sctp import SCTP\n+from scapy.layers.vxlan import VXLAN\n+from scapy.packet import Raw\n+from scapy.utils import wrpcap, rdpcap\n+from test_capabilities import DRIVER_TEST_LACK_CAPA\n from test_case import TestCase\n+\n from framework.pmd_output import PmdOutput\n from test_capabilities import DRIVER_TEST_LACK_CAPA\n 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, 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 test_rx_checksum_valid_flags.\")\n@@ -269,11 +303,147 @@ class 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 constructed so avoid any issues with\n+ # ordering\n+ pkt = eth / l3() / l4(**chksum) / (\n+ f'UNTUNNELED,{l3.__name__},{l4.__name__},{\" \" if 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() / 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, 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()) == 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 = 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 for %s/%s with a %s checksum.\"\n+\n+ vxlan_error_message = f\"Invalid VXLAN tunnelled %s checksum state 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 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 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 == '' 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) != 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) != 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 == '' 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 to use scapy.\n+ self.pktgen_helper = PacketGeneratorHelper()\n # run packet generator\n streams = self.pktgen_helper.prepare_stream_from_tginput(tgenInput, 100,\n None, self.tester.pktgen)\n@@ -511,53 +684,93 @@ class 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 = self.try_helper_hardware_checksum_check_catch_failure('Ether(dst=\"%s\", 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 = 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 = 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 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 = 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 = 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) != 1))) for chksum in checksum_options\n ]\n \n+ capture_file_name = \"test_hardware_checksum_check_l3_tx_capture.pcap\"\n+\n+ packet_file_path = \"/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 {capture_file_path} &\", \"# \")\n+\n+ wrpcap(packet_file_path, packets)\n+ self.tester.session.copy_file_to(packet_file_path, 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, \"output/tmp/pcap/\" + capture_file_name)\n+\n+ captured_packets = rdpcap(\"output/tmp/pcap/\" + capture_file_name)\n+\n+ self.verify(len(packets) == len(captured_packets), \"Not all 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 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 = 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 = 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+ 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 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 = 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 = 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 = \"test_hardware_checksum_check_l4_tx_capture.pcap\"\n+\n+ packet_file_path = \"/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 {capture_file_path} &\", \"# \")\n+\n+ wrpcap(packet_file_path, packets)\n+ self.tester.session.copy_file_to(packet_file_path, 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, \"output/tmp/pcap/\" + capture_file_name)\n+\n+ captured_packets = rdpcap(\"output/tmp/pcap/\" + capture_file_name)\n+\n+ self.verify(len(packets) == len(captured_packets), \"Not all packets were received\")\n+\n+ error_messages = 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", "prefixes": [] }{ "id": 74497, "url": "