test suite reviews and discussions
 help / color / Atom feed
* [dts] [PATCH] checksum offload: add hardware checksum checks case
@ 2020-07-14 14:53 Owen Hilyard
  2020-07-20 14:07 ` [dts] [PATCH] checksum checks: Add hardware offload l3 and l4 cases Owen Hilyard
  0 siblings, 1 reply; 6+ messages in thread
From: Owen Hilyard @ 2020-07-14 14:53 UTC (permalink / raw)
  To: dts
  Cc: ferruh.yigit, arybchenko, olivier.matz, david.marchand,
	ivan.malov, bruce.richardson, jerin.jacob, lylavoie, rasland,
	j.hendergart, ohilyard, thomas

add test case for hardware checksum checks
add test documentation for test case

Signed-off-by: Owen Hilyard <ohilyard@iol.unh.edu>
---
 test_plans/checksum_offload_test_plan.rst | 134 +---------
 tests/TestSuite_checksum_offload.py       | 287 +++++++++++++++-------
 2 files changed, 200 insertions(+), 221 deletions(-)

diff --git a/test_plans/checksum_offload_test_plan.rst b/test_plans/checksum_offload_test_plan.rst
index a42e28e..4fd8c5a 100644
--- a/test_plans/checksum_offload_test_plan.rst
+++ b/test_plans/checksum_offload_test_plan.rst
@@ -221,8 +221,13 @@ combination: good/bad ip checksum + good/bad udp/tcp checksum.
 
 Check the Rx checksum flags consistent with expected flags.
 
-Test Case: Hardware Checksum Check IP UDP
+Test Case: Hardware Checksum Check L4
 ===========================================
+This test involves testing many different scenarios with a L4 checksum.
+A variety of tunneling protocols, L3 protocols and L4 protocols are combined
+to test as many scenarios as possible. Currently, UDP, TCP and SCTP are used
+as L4 protocols, with IP and IPv6 being used at level 3. The tested tunneling
+protocols are VXLAN and GRE.
 
 Setup the ``csum`` forwarding mode::
 
@@ -251,131 +256,4 @@ Send a packet with a bad checksum::
    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
    tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
 
-Verify flags are as expected.
-Test Case: Hardware Checksum Check IP TCP
-===========================================
-
-Setup the ``csum`` forwarding mode::
-
-  testpmd> set fwd csum
-  Set csum packet forwarding mode
-
-Start the packet forwarding::
-
-  testpmd> start
-    csum packet forwarding - CRC stripping disabled - packets/burst=32
-    nb forwarding cores=1 - nb forwarding ports=10
-    RX queues=1 - RX desc=128 - RX free threshold=64
-    RX threshold registers: pthresh=8 hthresh=8 wthresh=4
-    TX queues=1 - TX desc=512 - TX free threshold=0
-    TX threshold registers: pthresh=32 hthresh=8 wthresh=8
-
-Send a packet with a good checksum::
-
-   port=0, mbuf=0x2269df7500, pkt_len=108, nb_segs=1:
-   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=6 l4_len=20 flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD PKT_RX_OUTER_L4_CKSUM_UNKNOWN
-   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
-
-Send a packet with a bad checksum::
-
-   port=0, mbuf=0x2269df6bc0, pkt_len=108, nb_segs=1:
-   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=6 l4_len=20 flags=PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_BAD PKT_RX_OUTER_L4_CKSUM_UNKNOWN
-   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
-
-Verify flags are as expected.
-
-Test Case: Hardware Checksum Check IP SCTP
-===========================================
-
-Setup the ``csum`` forwarding mode::
-
-  testpmd> set fwd csum
-  Set csum packet forwarding mode
-
-Start the packet forwarding::
-
-  testpmd> start
-    csum packet forwarding - CRC stripping disabled - packets/burst=32
-    nb forwarding cores=1 - nb forwarding ports=10
-    RX queues=1 - RX desc=128 - RX free threshold=64
-    RX threshold registers: pthresh=8 hthresh=8 wthresh=4
-    TX queues=1 - TX desc=512 - TX free threshold=0
-    TX threshold registers: pthresh=32 hthresh=8 wthresh=8
-
-Send a packet with a good checksum::
-
-   port=0, mbuf=0x2269df6280, pkt_len=100, nb_segs=1:
-   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=132 l4_len=0 flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD PKT_RX_OUTER_L4_CKSUM_UNKNOWN
-   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
-
-Send a packet with a bad checksum::
-
-   port=0, mbuf=0x2269df5940, pkt_len=100, nb_segs=1:
-   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=132 l4_len=0 flags=PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_BAD PKT_RX_OUTER_L4_CKSUM_UNKNOWN
-   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
-
-Verify flags are as expected.
-Test Case: Hardware Checksum Check IPv6 UDP
-===========================================
-
-Setup the ``csum`` forwarding mode::
-
-  testpmd> set fwd csum
-  Set csum packet forwarding mode
-
-Start the packet forwarding::
-
-  testpmd> start
-    csum packet forwarding - CRC stripping disabled - packets/burst=32
-    nb forwarding cores=1 - nb forwarding ports=10
-    RX queues=1 - RX desc=128 - RX free threshold=64
-    RX threshold registers: pthresh=8 hthresh=8 wthresh=4
-    TX queues=1 - TX desc=512 - TX free threshold=0
-    TX threshold registers: pthresh=32 hthresh=8 wthresh=8
-
-Send a packet with a good checksum::
-
-   port=0, mbuf=0x2269df5000, pkt_len=116, nb_segs=1:
-   rx: l2_len=18 ethertype=86dd l3_len=40 l4_proto=17 l4_len=8 flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD PKT_RX_OUTER_L4_CKSUM_UNKNOWN
-   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV6
-
-
-Send a packet with a bad checksum::
-
-   port=0, mbuf=0x2269df46c0, pkt_len=116, nb_segs=1:
-   rx: l2_len=18 ethertype=86dd l3_len=40 l4_proto=17 l4_len=8 flags=PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_GOOD PKT_RX_OUTER_L4_CKSUM_UNKNOWN
-   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV6
-
-Verify flags are as expected.
-Test Case: Hardware Checksum Check IPv6 TCP
-===========================================
-
-Setup the ``csum`` forwarding mode::
-
-  testpmd> set fwd csum
-  Set csum packet forwarding mode
-
-Start the packet forwarding::
-
-  testpmd> start
-    csum packet forwarding - CRC stripping disabled - packets/burst=32
-    nb forwarding cores=1 - nb forwarding ports=10
-    RX queues=1 - RX desc=128 - RX free threshold=64
-    RX threshold registers: pthresh=8 hthresh=8 wthresh=4
-    TX queues=1 - TX desc=512 - TX free threshold=0
-    TX threshold registers: pthresh=32 hthresh=8 wthresh=8
-
-Send a packet with a good checksum::
-
-   port=0, mbuf=0x2269df3d80, pkt_len=128, nb_segs=1:
-   rx: l2_len=18 ethertype=86dd l3_len=40 l4_proto=6 l4_len=20 flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD PKT_RX_OUTER_L4_CKSUM_UNKNOWN
-   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV6
-
-
-Send a packet with a bad checksum::
-
-   port=0, mbuf=0x2269df3440, pkt_len=128, nb_segs=1:
-   rx: l2_len=18 ethertype=86dd l3_len=40 l4_proto=6 l4_len=20 flags=PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_GOOD PKT_RX_OUTER_L4_CKSUM_UNKNOWN
-   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV6
-
 Verify flags are as expected.
\ No newline at end of file
diff --git a/tests/TestSuite_checksum_offload.py b/tests/TestSuite_checksum_offload.py
index 53eb918..9ff5a41 100644
--- a/tests/TestSuite_checksum_offload.py
+++ b/tests/TestSuite_checksum_offload.py
@@ -39,6 +39,10 @@ Test support of RX/TX Checksum Offload Features by Poll Mode Drivers.
 
 import os
 import re
+import subprocess
+import time
+from typing import List, Union, Tuple, Pattern
+
 import time
 
 from rst import RstReport
@@ -48,8 +52,11 @@ from test_case import TestCase
 from framework.pmd_output import PmdOutput
 from test_capabilities import DRIVER_TEST_LACK_CAPA
 from pktgen import PacketGeneratorHelper
+from exception import VerifyFailure
 import packet
 
+from settings import FOLDERS
+
 
 class TestChecksumOffload(TestCase):
 
@@ -91,6 +98,9 @@ class TestChecksumOffload(TestCase):
         self.dut.send_expect("csum set udp hw %d" % port, "testpmd>")
         self.dut.send_expect("csum set tcp hw %d" % port, "testpmd>")
         self.dut.send_expect("csum set sctp hw %d" % port, "testpmd>")
+        self.dut.send_expect("csum set outer-ip hw %d" % port, "testpmd>")
+        self.dut.send_expect("csum set outer-udp hw %d" % port, "testpmd>")
+        self.dut.send_expect("csum parse-tunnel on %d" % port, "testpmd>")
         self.dut.send_expect("port start all", "testpmd>")
 
     def checksum_enablesw(self, port):
@@ -146,11 +156,9 @@ class TestChecksumOffload(TestCase):
                                 self.verify("PKT_RX_L4_CKSUM_GOOD" in line, "Packet Rx L4 checksum valid-flags error!")
                             elif (flag == 0):
                                 if self.nic == "cavium_a063":
-                                    self.verify("PKT_RX_L4_CKSUM_BAD" in line or "PKT_RX_L4_CKSUM_UNKNOWN" in line,
-                                                "Packet Rx L4 checksum valid-flags error!")
+                                    self.verify("PKT_RX_L4_CKSUM_BAD" in line or "PKT_RX_L4_CKSUM_UNKNOWN" in line, "Packet Rx L4 checksum valid-flags error!")
                                 else:
-                                    self.verify("PKT_RX_L4_CKSUM_BAD" in line,
-                                                "Packet Rx L4 checksum valid-flags error!")
+                                    self.verify("PKT_RX_L4_CKSUM_BAD" in line, "Packet Rx L4 checksum valid-flags error!")
                     else:
                         if "PKT_RX_L4_CKSUM" not in line:
                             self.verify(0, "There is no L4 checksum flags appeared!")
@@ -178,8 +186,8 @@ class TestChecksumOffload(TestCase):
 
         chksum = self.get_chksum_values(packets_expected)
 
-        inst = self.tester.tcpdump_sniff_packets(intf=rx_interface, count=len(packets_sent) * 4,
-                                                 filters=[{'layer': 'ether', 'config': {'src': sniff_src}}])
+        inst = self.tester.tcpdump_sniff_packets(intf=rx_interface, count=len(packets_sent)*4,
+                filters=[{'layer': 'ether', 'config': {'src': sniff_src}}])
 
         self.pkt = packet.Packet()
         for packet_type in list(packets_sent.keys()):
@@ -189,10 +197,9 @@ class TestChecksumOffload(TestCase):
         p = self.tester.load_tcpdump_sniff_packets(inst)
         nr_packets = len(p)
         print(p)
-        packets_received = [p[i].sprintf("%IP.chksum%;%TCP.chksum%;%UDP.chksum%;%SCTP.chksum%") for i in
-                            range(nr_packets)]
+        packets_received = [p[i].sprintf("%IP.chksum%;%TCP.chksum%;%UDP.chksum%;%SCTP.chksum%") for i in range(nr_packets)]
         print(len(packets_sent), len(packets_received))
-        self.verify(len(packets_sent) * 4 == len(packets_received), "Unexpected Packets Drop")
+        self.verify(len(packets_sent)*4 == len(packets_received), "Unexpected Packets Drop")
 
         for packet_received in packets_received:
             ip_checksum, tcp_checksum, udp_checksum, sctp_checksum = packet_received.split(';')
@@ -227,47 +234,47 @@ class TestChecksumOffload(TestCase):
         self.tester.scapy_append(f'sendp({packet}, iface="{itf}")')
         return self.tester.scapy_execute()
 
-    def checksum_flags_are_good(self, flag: str, testpmd_output: str) -> bool:
-        good_flag_in_output: bool = flag + "GOOD" in testpmd_output
-        self.verify(good_flag_in_output or flag + "BAD" in testpmd_output,
-                    f"Flag {flag[:-1]} not found, please run test_rx_checksum_valid_flags.")
-        return good_flag_in_output
-
     def get_pkt_rx_l4_cksum(self, testpmd_output: str) -> bool:
         return self.checksum_flags_are_good("PKT_RX_L4_CKSUM_", testpmd_output)
 
     def get_pkt_rx_ip_cksum(self, testpmd_output: str) -> bool:
         return self.checksum_flags_are_good("PKT_RX_IP_CKSUM_", testpmd_output)
 
-    def send_pkt_expect_good_bad_from_flag(self, pkt_str: str, do_l3_csum: bool = False, good: bool = True):
-        self.send_scapy_packet(pkt_str)
-        out: str = self.pmdout.get_output(timeout=5)
-        # self.logger.info("Packet Result:\n" + out)
-        self.verify(self.get_pkt_rx_l4_cksum(out) == good, "L4 checksum was not correctly checked.")
-        if do_l3_csum:
-            self.verify(self.get_pkt_rx_ip_cksum(out) == good, "L3 checksum was not correctly checked.")
+    def send_pkt_expect_good_bad_from_flag(self, pkt_str: str, flag: str, test_name: str, should_pass: bool = True):
+        self.pmdout.get_output(timeout=5)  # Remove any old output
+        self.scapy_exec(f"sendp({pkt_str}, iface=iface)")
+        time.sleep(1)
+        testpmd_output: str = self.pmdout.get_output(timeout=5)
+        self.verify(flag in testpmd_output,
+                    f"Flag {flag[:-1]} not found for test {test_name}, please run test_rx_checksum_valid_flags.")
+        self.verify((flag + "UNKNOWN") not in testpmd_output,
+                    f"Flag {flag[:-1]} was found to be unknown for test {test_name}, indicating a possible lack of support")
+        if should_pass:
+            if flag + "GOOD" in testpmd_output:
+                return
+            else:  # flag + "BAD" in testpmd_output
+                self.verify(False, f"{flag}BAD was found in output, expecting {flag}GOOD.")
+        else:
+            if flag + "BAD" in testpmd_output:
+                return
+            else:  # flag + "GOOD" in testpmd_output
+                self.verify(False, f"{flag}GOOD was found in output, expecting {flag}BAD.")
 
-    def helper_hardware_checksum_check(self, pkt_str: str, do_l3_csum: bool = False):
-        self.dut.send_expect("start", "testpmd>")
+    def send_pkt_expect_good_bad_from_flag_catch_failure(self, pkt_str: str, flag: str, test_name: str,
+                                                         should_pass: bool = True) -> Union[VerifyFailure, None]:
+        try:
+            self.send_pkt_expect_good_bad_from_flag(pkt_str, flag, test_name, should_pass=should_pass)
+        except VerifyFailure as vf:
+            return vf
 
-        self.checksum_enablehw(self.dut_ports[0])
-        dut_mac = self.dut.get_mac_address(self.dut_ports[0])
-        tester_mac = self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))
+        return None
 
-        good_pkt: str
-        bad_pkt: str
-        if do_l3_csum:
-            # Blank out the fields where a checksum would go for the good packet
-            good_pkt = pkt_str % (dut_mac, tester_mac, "", "")
-            bad_pkt = pkt_str % (dut_mac, tester_mac, "chksum=0xf", "chksum=0xf")
-        else:
-            good_pkt = pkt_str % (dut_mac, tester_mac, "")
-            bad_pkt = pkt_str % (dut_mac, tester_mac, "chksum=0xf")
+    def scapy_exec(self, cmd: str):
+        return self.tester.send_expect(cmd, ">>>")
 
-        self.send_pkt_expect_good_bad_from_flag(good_pkt, do_l3_csum=do_l3_csum, good=True)
-        self.send_pkt_expect_good_bad_from_flag(bad_pkt, do_l3_csum=do_l3_csum, good=False)
+    def scapy_send_append(self, packet: str):
+        return self.tester.scapy_append(f'sendp({packet}, iface=iface)')
 
-        self.dut.send_expect("stop", "testpmd>")
     #
     #
     #
@@ -281,19 +288,17 @@ class TestChecksumOffload(TestCase):
         """
         mac = self.dut.get_mac_address(self.dut_ports[0])
 
-        pktsChkErr = {
-            'IP/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/Dot1Q(vlan=1)/IP(chksum=0x0)/UDP(chksum=0xf)/("X"*46)' % mac,
-            'IP/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/Dot1Q(vlan=1)/IP(chksum=0x0)/TCP(chksum=0xf)/("X"*46)' % mac,
-            'IP/SCTP': 'Ether(dst="%s", src="52:00:00:00:00:00")/Dot1Q(vlan=1)/IP(chksum=0x0)/SCTP(chksum=0xf)/("X"*48)' % mac,
-            'IPv6/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/Dot1Q(vlan=1)/IPv6(src="::1")/UDP(chksum=0xf)/("X"*46)' % mac,
-            'IPv6/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/Dot1Q(vlan=1)/IPv6(src="::1")/TCP(chksum=0xf)/("X"*46)' % mac}
+        pktsChkErr = {'IP/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/Dot1Q(vlan=1)/IP(chksum=0x0)/UDP(chksum=0xf)/("X"*46)' % mac,
+                      'IP/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/Dot1Q(vlan=1)/IP(chksum=0x0)/TCP(chksum=0xf)/("X"*46)' % mac,
+                      'IP/SCTP': 'Ether(dst="%s", src="52:00:00:00:00:00")/Dot1Q(vlan=1)/IP(chksum=0x0)/SCTP(chksum=0xf)/("X"*48)' % mac,
+                      'IPv6/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/Dot1Q(vlan=1)/IPv6(src="::1")/UDP(chksum=0xf)/("X"*46)' % mac,
+                      'IPv6/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/Dot1Q(vlan=1)/IPv6(src="::1")/TCP(chksum=0xf)/("X"*46)' % mac}
 
-        pkts = {
-            'IP/UDP': 'Ether(dst="02:00:00:00:00:00", src="%s")/Dot1Q(vlan=1)/IP(src="127.0.0.1")/UDP()/("X"*46)' % mac,
-            'IP/TCP': 'Ether(dst="02:00:00:00:00:00", src="%s")/Dot1Q(vlan=1)/IP(src="127.0.0.1")/TCP()/("X"*46)' % mac,
-            'IP/SCTP': 'Ether(dst="02:00:00:00:00:00", src="%s")/Dot1Q(vlan=1)/IP(src="127.0.0.1")/SCTP()/("X"*48)' % mac,
-            'IPv6/UDP': 'Ether(dst="02:00:00:00:00:00", src="%s")/Dot1Q(vlan=1)/IPv6(src="::1")/UDP()/("X"*46)' % mac,
-            'IPv6/TCP': 'Ether(dst="02:00:00:00:00:00", src="%s")/Dot1Q(vlan=1)/IPv6(src="::1")/TCP()/("X"*46)' % mac}
+        pkts = {'IP/UDP': 'Ether(dst="02:00:00:00:00:00", src="%s")/Dot1Q(vlan=1)/IP(src="127.0.0.1")/UDP()/("X"*46)' % mac,
+                'IP/TCP': 'Ether(dst="02:00:00:00:00:00", src="%s")/Dot1Q(vlan=1)/IP(src="127.0.0.1")/TCP()/("X"*46)' % mac,
+                'IP/SCTP': 'Ether(dst="02:00:00:00:00:00", src="%s")/Dot1Q(vlan=1)/IP(src="127.0.0.1")/SCTP()/("X"*48)' % mac,
+                'IPv6/UDP': 'Ether(dst="02:00:00:00:00:00", src="%s")/Dot1Q(vlan=1)/IPv6(src="::1")/UDP()/("X"*46)' % mac,
+                'IPv6/TCP': 'Ether(dst="02:00:00:00:00:00", src="%s")/Dot1Q(vlan=1)/IPv6(src="::1")/TCP()/("X"*46)' % mac}
 
         if self.kdriver in DRIVER_TEST_LACK_CAPA['sctp_tx_offload']:
             del pktsChkErr['IP/SCTP']
@@ -325,17 +330,11 @@ class TestChecksumOffload(TestCase):
         result = self.get_chksum_values(pkts_ref)
 
         # set the expected checksum values same with the actual values
-        pkts_good = {
-            'IP/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(chksum=int(%s))/UDP(chksum=int(%s))/("X"*46)' % (
-                mac, result['IP/UDP'][0], result['IP/UDP'][1]),
-            'IP/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(src="10.0.0.1",chksum=int(%s))/TCP(chksum=int(%s))/("X"*46)' % (
-                mac, result['IP/TCP'][0], result['IP/TCP'][1]),
-            'IP/SCTP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(src="10.0.0.1",chksum=int(%s))/SCTP(chksum=int(%s))/("X"*48)' % (
-                mac, result['IP/SCTP'][0], result['IP/SCTP'][1]),
-            'IPv6/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6(src="::1")/UDP(chksum=int(%s))/("X"*46)' % (
-                mac, result['IPv6/UDP'][0]),
-            'IPv6/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6(src="::1")/TCP(chksum=int(%s))/("X"*46)' % (
-                mac, result['IPv6/TCP'][0])}
+        pkts_good = {'IP/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(chksum=int(%s))/UDP(chksum=int(%s))/("X"*46)' % (mac, result['IP/UDP'][0], result['IP/UDP'][1]),
+                     'IP/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(src="10.0.0.1",chksum=int(%s))/TCP(chksum=int(%s))/("X"*46)' % (mac, result['IP/TCP'][0], result['IP/TCP'][1]),
+                     'IP/SCTP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(src="10.0.0.1",chksum=int(%s))/SCTP(chksum=int(%s))/("X"*48)' % (mac, result['IP/SCTP'][0], result['IP/SCTP'][1]),
+                     'IPv6/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6(src="::1")/UDP(chksum=int(%s))/("X"*46)' % (mac, result['IPv6/UDP'][0]),
+                     'IPv6/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6(src="::1")/TCP(chksum=int(%s))/("X"*46)' % (mac, result['IPv6/TCP'][0])}
 
         # set the expected checksum values different from the actual values
         pkts_bad = {'IP/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(chksum=0x0)/UDP(chksum=0xf)/("X"*46)' % mac,
@@ -399,24 +398,17 @@ class TestChecksumOffload(TestCase):
         mac = self.dut.get_mac_address(self.dut_ports[0])
         sndIP = '10.0.0.1'
         sndIPv6 = '::1'
-        sndPkts = {
-            'IP/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(src="%s",chksum=0x0)/UDP(chksum=0xf)/("X"*46)' % (
-                mac, sndIP),
-            'IP/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(src="%s",chksum=0x0)/TCP(chksum=0xf)/("X"*46)' % (
-                mac, sndIP),
-            'IPv6/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6(src="%s")/UDP(chksum=0xf)/("X"*46)' % (
-                mac, sndIPv6),
-            'IPv6/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6(src="%s")/TCP(chksum=0xf)/("X"*46)' % (
-                mac, sndIPv6)}
+        sndPkts = {'IP/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(src="%s",chksum=0x0)/UDP(chksum=0xf)/("X"*46)' % (mac, sndIP),
+                   'IP/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(src="%s",chksum=0x0)/TCP(chksum=0xf)/("X"*46)' % (mac, sndIP),
+                   'IPv6/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6(src="%s")/UDP(chksum=0xf)/("X"*46)' % (mac, sndIPv6),
+                   'IPv6/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IPv6(src="%s")/TCP(chksum=0xf)/("X"*46)' % (mac, sndIPv6)}
 
         expIP = sndIP
         expIPv6 = sndIPv6
         expPkts = {'IP/UDP': 'Ether(dst="02:00:00:00:00:00", src="%s")/IP(src="%s")/UDP()/("X"*46)' % (mac, expIP),
                    'IP/TCP': 'Ether(dst="02:00:00:00:00:00", src="%s")/IP(src="%s")/TCP()/("X"*46)' % (mac, expIP),
-                   'IPv6/UDP': 'Ether(dst="02:00:00:00:00:00", src="%s")/IPv6(src="%s")/UDP()/("X"*46)' % (
-                       mac, expIPv6),
-                   'IPv6/TCP': 'Ether(dst="02:00:00:00:00:00", src="%s")/IPv6(src="%s")/TCP()/("X"*46)' % (
-                       mac, expIPv6)}
+                   'IPv6/UDP': 'Ether(dst="02:00:00:00:00:00", src="%s")/IPv6(src="%s")/UDP()/("X"*46)' % (mac, expIPv6),
+                   'IPv6/TCP': 'Ether(dst="02:00:00:00:00:00", src="%s")/IPv6(src="%s")/TCP()/("X"*46)' % (mac, expIPv6)}
 
         self.dut.send_expect("start", "testpmd>")
         result = self.checksum_validate(sndPkts, expPkts)
@@ -458,12 +450,12 @@ class TestChecksumOffload(TestCase):
             self.tester.pktgen.clear_streams()
             # run packet generator
             streams = self.pktgen_helper.prepare_stream_from_tginput(tgenInput, 100,
-                                                                     None, self.tester.pktgen)
+                    None, self.tester.pktgen)
             Bps[str(size)], Pps[str(size)] = self.tester.pktgen.measure_throughput(stream_ids=streams)
             self.verify(Pps[str(size)] > 0, "No traffic detected")
             Pps[str(size)] /= 1E6
             Pct[str(size)] = (Pps[str(size)] * 100) / \
-                             self.wirespeed(self.nic, size, 2)
+                self.wirespeed(self.nic, size, 2)
 
             result.append(Pps[str(size)])
             result.append(Pct[str(size)])
@@ -500,7 +492,7 @@ class TestChecksumOffload(TestCase):
             self.result_table_create(tblheader)
             self.pmdout.start_testpmd(
                 lcore, "--portmask=%s" % self.portMask + " --enable-rx-cksum " +
-                       "--port-topology=loop", socket=self.ports_socket)
+                                  "--port-topology=loop", socket=self.ports_socket)
 
             self.dut.send_expect("set fwd csum", "testpmd> ")
             if mode == "hw":
@@ -519,25 +511,134 @@ class TestChecksumOffload(TestCase):
             self.dut.send_expect("quit", "#", 10)
             self.result_table_print()
 
-    def test_hardware_checksum_check_ip_udp(self):
-        self.helper_hardware_checksum_check('Ether(dst="%s", src="%s")/IP(%s)/UDP(%s)/("X"*50)',
-                                            do_l3_csum=True)
+    def test_hardware_checksum_check_ip(self):
+        self.dut.send_expect("start", "testpmd>")
+        self.checksum_enablehw(self.dut_ports[0])
+
+        verification_errors: List[VerifyFailure] = []
 
-    def test_hardware_checksum_check_ip_tcp(self):
-        self.helper_hardware_checksum_check('Ether(dst="%s", src="%s")/IP(%s)/TCP(%s)/("X"*50)',
-                                            do_l3_csum=True)
+        # untunnelled
+        vf = self.try_helper_hardware_checksum_check_catch_failure('Ether(dst="%s", src="%s")/IP(%s)/UDP()/("X"*50)',
+                                                                   "PKT_RX_IP_CKSUM_")
+        if vf is not None:
+            verification_errors.append(vf)
 
-    def test_hardware_checksum_check_ip_sctp(self):
-        self.helper_hardware_checksum_check('Ether(dst="%s", src="%s")/IP(%s)/SCTP(%s)/("X"*50)',
-                                            do_l3_csum=True)
+        # tunneled inner
+        vf = self.try_helper_hardware_checksum_check_catch_failure(
+            'Ether(dst="%s", src="%s")/IP()/UDP()/IP(%s)/("X"*50)',
+            "PKT_RX_OUTER_IP_CKSUM_")
+        if vf is not None:
+            verification_errors.append(vf)
 
-    def test_hardware_checksum_check_ipv6_udp(self):
-        self.helper_hardware_checksum_check('Ether(dst="%s", src="%s")/IPv6(src="::1")/UDP(%s)/("X"*50)',
-                                            do_l3_csum=False)
+        # tunneled outer
+        vf = self.try_helper_hardware_checksum_check_catch_failure(
+            'Ether(dst="%s", src="%s")/IP()/UDP()/IP(%s)/("X"*50)',
+            "PKT_RX_OUTER_IP_CKSUM_")
+        if vf is not None:
+            verification_errors.append(vf)
 
-    def test_hardware_checksum_check_ipv6_tcp(self):
-        self.helper_hardware_checksum_check('Ether(dst="%s", src="%s")/IPv6(src="::1")/TCP(%s)/("X"*50)',
-                                            do_l3_csum=False)
+        self.verify(len(verification_errors) == 0, "\n".join(verification_errors))
+
+        self.dut.send_expect("stop", "testpmd>")
+
+    def test_hardware_checksum_check_l4(self):
+        self.checksum_enablehw(self.dut_ports[0])
+        self.dut.send_expect("start", "testpmd>")
+
+        verification_errors: List[VerifyFailure] = []
+
+        l3_protos: List[str] = [
+            "IP",
+            "IPv6"
+        ]
+
+        l4_protos: List[str] = [
+            "UDP",
+            "TCP",
+            "SCTP",
+        ]
+
+        iface = self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))
+        dut_mac = self.dut.get_mac_address(self.dut_ports[0])
+        tester_mac = self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))
+
+        self.tester.send_expect("scapy", ">>> ")
+        self.scapy_exec(f"eth = Ether(dst='{dut_mac}', src='{tester_mac}')")
+        self.scapy_exec(f"iface = '{iface}'")
+        # Untunneled
+        for l3 in l3_protos:
+            for l4 in l4_protos:
+                for chksum in "", "chksum=0xf":
+                    vf = self.send_pkt_expect_good_bad_from_flag_catch_failure(
+                        f"eth/{l3}()/{l4}({chksum})/('X'*50)",
+                        "PKT_RX_L4_CKSUM_", f"{l3}/{l4}",
+                        should_pass=(chksum == ""))
+                    if vf is not None:
+                        verification_errors.append(vf)
+
+        # Tunneled
+        # VXLAN
+        for l3 in l3_protos:
+            for l4 in l4_protos:
+                for outer_arg in "", "chksum=0xf":
+                    for inner_arg in "", "chksum=0xf":
+                        for flag in "PKT_RX_L4_CKSUM_", "PKT_RX_OUTER_L4_CKSUM_":
+                            if flag == "PKT_RX_L4_CKSUM_":
+                                should_pass = inner_arg == ""
+                            else:  # flag == PKT_RX_OUTER_L4_CKSUM_
+                                should_pass = outer_arg == ""
+                            vf = self.send_pkt_expect_good_bad_from_flag_catch_failure(
+                                f"eth/{l3}()/{l4}({outer_arg})/VXLAN()/{l3}()/"
+                                f"{l4}({inner_arg})/('X'*50)",
+                                flag, f"{l3}/{l4}/VXLAN/{l3}/{l4}",
+                                should_pass=should_pass)
+
+                            if vf is not None:
+                                verification_errors.append(vf)
+
+        # GRE
+        for l3 in l3_protos:
+            for l4 in l4_protos:
+                for inner_arg in "", "chksum=0xf":
+                    should_pass: bool = inner_arg == ""
+                    vf = self.send_pkt_expect_good_bad_from_flag_catch_failure(
+                        f"eth/{l3}()/GRE()/{l3}()/"
+                        f"{l4}({inner_arg})/('X'*50)",
+                        "PKT_RX_L4_CKSUM_", f"{l3}/GRE/{l3}/{l4}",
+                        should_pass=should_pass)
+
+                    if vf is not None:
+                        verification_errors.append(vf)
+
+        # This section is commented out because GENEVE is not supported in the current version (2.3.3) that is used
+        # in dts. This will be available in scapy 2.4.3, so this was added and commented out so that when scapy is
+        # updated this test case can easily take advantage of the new functionality.
+
+        # # GENEVE
+        # for l3_outer in l3_protos:
+        #     for l4_outer in l4_protos:
+        #         for l3_inner in l3_protos:
+        #             for l4 in l4_protos:
+        #                 for outer_arg in "", "chksum=0xf":
+        #                     for inner_arg in "", "chksum=0xf":
+        #                         for flag in "PKT_RX_L4_CKSUM_", "PKT_RX_OUTER_L4_CKSUM_":
+        #                             should_pass: bool = inner_arg == "" if flag == "PKT_RX_L4_CKSUM_" else outer_arg == ""
+        #                             vf = self.send_pkt_expect_good_bad_from_flag_catch_failure(
+        #                                 f"eth/{l3_outer}()/{l4_outer}({outer_arg})/GENEVE()/eth/{l3_inner}()/"
+        #                                 f"{l4}({inner_arg})/('X'*50)",
+        #                                 flag, f"{l3_outer}/{l4_outer}/VXLAN/{l3_inner}/{l4}",
+        #                                 should_pass=should_pass)
+        #
+        #                             if vf is not None:
+        #                                 verification_errors.append(vf)
+
+        # tunneled inner
+
+        for err in verification_errors:
+            self.logger.error(str(err))
+        self.verify(len(verification_errors) == 0, "See previous output")
+
+        self.dut.send_expect("stop", "testpmd>")
 
     def tear_down(self):
         """
-- 
2.25.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [dts] [PATCH] checksum checks: Add hardware offload l3 and l4 cases
  2020-07-14 14:53 [dts] [PATCH] checksum offload: add hardware checksum checks case Owen Hilyard
@ 2020-07-20 14:07 ` Owen Hilyard
  2020-07-20 14:13   ` [dts] [PATCH] checksum hardware checks: fix typo Owen Hilyard
  2020-07-24  2:45   ` [dts] [PATCH] checksum checks: Add hardware offload l3 and l4 cases Tu, Lijuan
  0 siblings, 2 replies; 6+ messages in thread
From: Owen Hilyard @ 2020-07-20 14:07 UTC (permalink / raw)
  To: dts
  Cc: ferruh.yigit, arybchenko, olivier.matz, david.marchand,
	ivan.malov, bruce.richardson, lylavoie, rasland, j.hendergart,
	ohilyard, thomas

add rx and tx l3 test cases
add tx l4 test case
add documentation for new test cases

Signed-off-by: Owen Hilyard <ohilyard@iol.unh.edu>
---
 test_plans/checksum_offload_test_plan.rst | 122 +++++++-
 tests/TestSuite_checksum_offload.py       | 331 +++++++++++++++++++---
 2 files changed, 412 insertions(+), 41 deletions(-)

diff --git a/test_plans/checksum_offload_test_plan.rst b/test_plans/checksum_offload_test_plan.rst
index 4fd8c5a..de2e1a9 100644
--- a/test_plans/checksum_offload_test_plan.rst
+++ b/test_plans/checksum_offload_test_plan.rst
@@ -221,7 +221,7 @@ combination: good/bad ip checksum + good/bad udp/tcp checksum.
 
 Check the Rx checksum flags consistent with expected flags.
 
-Test Case: Hardware Checksum Check L4
+Test Case: Hardware Checksum Check L4 RX
 ===========================================
 This test involves testing many different scenarios with a L4 checksum.
 A variety of tunneling protocols, L3 protocols and L4 protocols are combined
@@ -256,4 +256,122 @@ Send a packet with a bad checksum::
    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
    tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
 
-Verify flags are as expected.
\ No newline at end of file
+Verify flags are as expected.
+
+Test Case: Hardware Checksum Check L3 RX
+===========================================
+This test involves testing L3 checksum hardware offload.
+Due to the relative dominance of IPv4 and IPv6 as L3 protocols, and IPv6's
+lack of a checksum, only IPv4's checksum is tested.
+
+Setup the ``csum`` forwarding mode::
+
+  testpmd> set fwd csum
+  Set csum packet forwarding mode
+
+Start the packet forwarding::
+
+  testpmd> start
+    csum packet forwarding - CRC stripping disabled - packets/burst=32
+    nb forwarding cores=1 - nb forwarding ports=10
+    RX queues=1 - RX desc=128 - RX free threshold=64
+    RX threshold registers: pthresh=8 hthresh=8 wthresh=4
+    TX queues=1 - TX desc=512 - TX free threshold=0
+    TX threshold registers: pthresh=32 hthresh=8 wthresh=8
+
+Send a packet with a good checksum::
+
+   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:
+   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
+   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
+
+Send a packet with a bad checksum::
+
+   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:
+   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
+   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
+
+Verify flags are as expected.
+
+Test Case: Hardware Checksum Check L4 TX
+===========================================
+This test involves testing many different scenarios with a L4 checksum.
+A variety of tunneling protocols, L3 protocols and L4 protocols are combined
+to test as many scenarios as possible. Currently, UDP, TCP and SCTP are used
+as L4 protocols, with IP and IPv6 being used at level 3. The tested tunneling
+protocols are VXLAN and GRE. This test is used to determine whether the
+hardware offloading of checksums works properly.
+
+Setup the ``csum`` forwarding mode::
+
+  testpmd> set fwd csum
+  Set csum packet forwarding mode
+
+Start the packet forwarding::
+
+  testpmd> start
+    csum packet forwarding - CRC stripping disabled - packets/burst=32
+    nb forwarding cores=1 - nb forwarding ports=10
+    RX queues=1 - RX desc=128 - RX free threshold=64
+    RX threshold registers: pthresh=8 hthresh=8 wthresh=4
+    TX queues=1 - TX desc=512 - TX free threshold=0
+    TX threshold registers: pthresh=32 hthresh=8 wthresh=8
+
+
+Start a packet capture on the tester in the backround::
+
+   # tcpdump -i <iface> -s 65535 -w /tmp/tester/test_hardware_checksum_check_l4_tx_capture.pcap &
+
+Send a packet with a good checksum::
+
+   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:
+   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
+   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
+
+Send a packet with a bad checksum::
+
+   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:
+   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
+   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
+
+Inspect the pcap file from the packet capture and verify the checksums.
+
+Test Case: Hardware Checksum Check L3 TX
+===========================================
+This test involves testing L3 checksum hardware offload.
+Due to the relative dominance of IPv4 and IPv6 as L3 protocols, and IPv6's
+lack of a checksum, only IPv4's checksum is tested.
+
+Setup the ``csum`` forwarding mode::
+
+  testpmd> set fwd csum
+  Set csum packet forwarding mode
+
+Start the packet forwarding::
+
+  testpmd> start
+    csum packet forwarding - CRC stripping disabled - packets/burst=32
+    nb forwarding cores=1 - nb forwarding ports=10
+    RX queues=1 - RX desc=128 - RX free threshold=64
+    RX threshold registers: pthresh=8 hthresh=8 wthresh=4
+    TX queues=1 - TX desc=512 - TX free threshold=0
+    TX threshold registers: pthresh=32 hthresh=8 wthresh=8
+
+
+Start a packet capture on the tester in the backround::
+
+   # tcpdump -i <iface> -s 65535 -w /tmp/tester/test_hardware_checksum_check_l3_tx_capture.pcap &
+
+Send a packet with a good checksum with a 1 in it's payload::
+
+   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:
+   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
+   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
+
+Send a packet with a bad checksum with a 0 in it's payload::
+
+   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:
+   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
+   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
+
+Inspect the pcap file from the packet capture and verify the checksums.
diff --git a/tests/TestSuite_checksum_offload.py b/tests/TestSuite_checksum_offload.py
index 9ff5a41..c4a877d 100644
--- a/tests/TestSuite_checksum_offload.py
+++ b/tests/TestSuite_checksum_offload.py
@@ -47,8 +47,18 @@ import time
 
 from rst import RstReport
 import utils
-
+from exception import VerifyFailure
+from pktgen import PacketGeneratorHelper
+from scapy.layers.inet import UDP, TCP, IP
+from scapy.layers.inet6 import IPv6
+from scapy.layers.l2 import Ether, GRE
+from scapy.layers.sctp import SCTP
+from scapy.layers.vxlan import VXLAN
+from scapy.packet import Raw
+from scapy.utils import wrpcap, rdpcap
+from test_capabilities import DRIVER_TEST_LACK_CAPA
 from test_case import TestCase
+
 from framework.pmd_output import PmdOutput
 from test_capabilities import DRIVER_TEST_LACK_CAPA
 from pktgen import PacketGeneratorHelper
@@ -57,6 +67,33 @@ import packet
 
 from settings import FOLDERS
 
+l3_proto_classes = [
+    IP,
+    IPv6
+]
+
+l4_proto_classes = [
+    UDP,
+    TCP,
+    SCTP
+]
+
+tunnelling_proto_classes = [
+    VXLAN,
+    GRE,
+]
+
+l3_protos = [
+    "IP",
+    "IPv6"
+]
+
+l4_protos = [
+    "UDP",
+    "TCP",
+    "SCTP",
+]
+
 
 class TestChecksumOffload(TestCase):
 
@@ -79,8 +116,6 @@ class TestChecksumOffload(TestCase):
             cur_path = os.path.dirname(
                 os.path.dirname(os.path.realpath(__file__)))
             self.output_path = os.sep.join([cur_path, self.logger.log_path])
-        # create an instance to set stream field setting
-        self.pktgen_helper = PacketGeneratorHelper()
 
     def set_up(self):
         """
@@ -243,7 +278,6 @@ class TestChecksumOffload(TestCase):
     def send_pkt_expect_good_bad_from_flag(self, pkt_str: str, flag: str, test_name: str, should_pass: bool = True):
         self.pmdout.get_output(timeout=5)  # Remove any old output
         self.scapy_exec(f"sendp({pkt_str}, iface=iface)")
-        time.sleep(1)
         testpmd_output: str = self.pmdout.get_output(timeout=5)
         self.verify(flag in testpmd_output,
                     f"Flag {flag[:-1]} not found for test {test_name}, please run test_rx_checksum_valid_flags.")
@@ -269,11 +303,147 @@ class TestChecksumOffload(TestCase):
 
         return None
 
-    def scapy_exec(self, cmd: str):
-        return self.tester.send_expect(cmd, ">>>")
+    def validate_checksum(self, pkt, layer) -> bool:
+        """
+        @param pkt: The packet to validate the checksum of.
+        @return: Whether the checksum was valid.
+        """
+        if pkt is None:
+            return False
+
+        csum = pkt[layer].chksum
+        del pkt[layer].chksum
+        # Converting it to raw will calculate the checksum
+        return layer(Raw(pkt[layer])).chksum == csum
 
-    def scapy_send_append(self, packet: str):
-        return self.tester.scapy_append(f'sendp({packet}, iface=iface)')
+    def scapy_exec(self, cmd: str, timeout=1) -> str:
+        return self.tester.send_expect(cmd, ">>>", timeout=timeout)
+
+    def get_packets(self, dut_mac, tester_mac):
+        eth = Ether(dst=dut_mac, src=tester_mac)
+        packets = []
+        checksum_options = ({}, {'chksum': 0xf},)
+        # Untunneled
+        for l3 in l3_proto_classes:
+            for l4 in l4_proto_classes:
+                for chksum in checksum_options:
+                    # The packet's data can be used to identify how the packet was constructed so avoid any issues with
+                    # ordering
+                    pkt = eth / l3() / l4(**chksum) / (
+                        f'UNTUNNELED,{l3.__name__},{l4.__name__},{" " if len(chksum.values()) == 0 else chksum["chksum"]}'
+                    )
+
+                    # Prevents the default behavior which adds DNS headers
+                    if l4 == UDP:
+                        pkt[UDP].dport, pkt[UDP].sport = 1001, 1001
+
+                    packets.append(pkt)
+
+        # Tunneled
+        # VXLAN
+        for l3 in l3_proto_classes:
+            for l4 in l4_proto_classes:
+                for outer_arg in checksum_options:
+                    for inner_arg in checksum_options:
+                        pkt = eth / l3() / UDP(**outer_arg) / VXLAN() / Ether() / l3() / l4(**inner_arg) / (
+                            f'VXLAN,{l3.__name__},{l4.__name__},'
+                            f'{" " if len(outer_arg.values()) == 0 else outer_arg["chksum"]},'
+                            f'{" " if len(inner_arg.values()) == 0 else inner_arg["chksum"]}'
+                        )
+                        # Prevents the default behavior which adds DNS headers
+                        if l4 == UDP:
+                            pkt[VXLAN][UDP].dport, pkt[VXLAN][UDP].sport = 1001, 1001
+
+                        packets.append(pkt)
+        # GRE
+        for l3 in l3_proto_classes:
+            for l4 in l4_proto_classes:
+                for chksum in checksum_options:
+                    pkt = eth / l3() / GRE() / l3() / l4(**chksum) / (
+                        f'GRE,{l3.__name__},{l4.__name__},{" " if len(chksum.values()) == 0 else chksum["chksum"]}'
+                    )
+
+                    # Prevents the default behavior which adds DNS headers
+                    if l4 == UDP:
+                        pkt[GRE][UDP].dport, pkt[GRE][UDP].sport = 1001, 1001
+
+                    packets.append(pkt)
+
+        return packets
+
+    def replay_pcap_file_on_tester(self, iface, packet_file_path):
+        self.tester.send_expect("scapy", ">>>")
+        self.scapy_exec(f"packets = rdpcap('{packet_file_path}')")
+        self.scapy_exec(f"sendp(packets, iface={iface})")
+        self.tester.send_expect("quit()", "# ")
+
+    def validate_packet_list_checksums(self, packets):
+        name_to_class_dict = {
+            'UDP': UDP,
+            'TCP': TCP,
+            'SCTP': SCTP,
+            'IP': IP,
+            'IPv6': IPv6,
+            'VXLAN': VXLAN,
+            'GRE': GRE,
+        }
+
+        error_messages = []
+
+        untunnelled_error_message = f"Invalid untunneled checksum state for %s/%s with a %s checksum."
+
+        vxlan_error_message = f"Invalid VXLAN tunnelled %s checksum state for %s/%s" \
+                              f" with a %s inner checksum and a %s outer checksum."
+
+        gre_error_message = f"Invalid GRE tunnelled checksum state for %s/%s with a %s checksum."
+
+        for packet in packets:
+            payload: str
+            # try:
+            payload = packet[Raw].load.decode('utf-8').split(",")
+            # # This error usually happens with tunneling protocols, and means that an additional cast is needed
+            # except UnicodeDecodeError:
+            #     for proto in tunnelling_proto_classes:
+
+            l3 = name_to_class_dict[payload[1]]
+            l4 = name_to_class_dict[payload[2]]
+            if payload[0] == "UNTUNNELED":
+                chksum_should_be_valid = payload[3] == " "
+                if self.validate_checksum(packet, l4) != chksum_should_be_valid:
+                    error_messages.append(
+                        untunnelled_error_message % (
+                            l3.__name__, l4.__name__, 'valid' if chksum_should_be_valid == '' else 'invalid'
+                        )
+                    )
+            elif payload[0] == "VXLAN":
+                outer_chksum_should_be_valid = payload[3] == " "
+                inner_chksum_should_be_valid = payload[4] == " "
+                if self.validate_checksum(packet[VXLAN], l4) != inner_chksum_should_be_valid:
+                    error_messages.append(
+                        vxlan_error_message % (
+                            "inner", l4.__name__, l3.__name__,
+                            'valid' if inner_chksum_should_be_valid == '' else 'invalid',
+                            'valid' if outer_chksum_should_be_valid == '' else 'invalid'
+                        )
+                    )
+                if self.validate_checksum(packet, l4) != outer_chksum_should_be_valid:
+                    error_messages.append(
+                        vxlan_error_message % (
+                            "outer", l3.__name__, l4.__name__,
+                            'valid' if inner_chksum_should_be_valid == '' else 'invalid',
+                            'valid' if outer_chksum_should_be_valid == '' else 'invalid'
+                        )
+                    )
+            elif payload[0] == "GRE":
+                chksum_should_be_valid = payload[3] == " "
+                if self.validate_checksum(packet, l4) != chksum_should_be_valid:
+                    error_messages.append(
+                        gre_error_message % (
+                            l3.__name__, l4.__name__, 'valid' if chksum_should_be_valid == '' else 'invalid'
+                        )
+                    )
+
+        return error_messages
 
     #
     #
@@ -448,6 +618,9 @@ class TestChecksumOffload(TestCase):
 
             # clear streams before add new streams
             self.tester.pktgen.clear_streams()
+            # create an instance to set stream field setting
+            # Moved here because it messes with the ability of the functional tests to use scapy.
+            self.pktgen_helper = PacketGeneratorHelper()
             # run packet generator
             streams = self.pktgen_helper.prepare_stream_from_tginput(tgenInput, 100,
                     None, self.tester.pktgen)
@@ -511,53 +684,93 @@ class TestChecksumOffload(TestCase):
             self.dut.send_expect("quit", "#", 10)
             self.result_table_print()
 
-    def test_hardware_checksum_check_ip(self):
+    def test_hardware_checksum_check_ip_rx(self):
         self.dut.send_expect("start", "testpmd>")
+        self.tester.send_expect("scapy", ">>>")
         self.checksum_enablehw(self.dut_ports[0])
+        self.dut.send_expect("start", "testpmd>")
 
         verification_errors: List[VerifyFailure] = []
 
-        # untunnelled
-        vf = self.try_helper_hardware_checksum_check_catch_failure('Ether(dst="%s", src="%s")/IP(%s)/UDP()/("X"*50)',
-                                                                   "PKT_RX_IP_CKSUM_")
-        if vf is not None:
-            verification_errors.append(vf)
+        iface = self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))
+        dut_mac = self.dut.get_mac_address(self.dut_ports[0])
+        tester_mac = self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))
 
-        # tunneled inner
-        vf = self.try_helper_hardware_checksum_check_catch_failure(
-            'Ether(dst="%s", src="%s")/IP()/UDP()/IP(%s)/("X"*50)',
-            "PKT_RX_OUTER_IP_CKSUM_")
-        if vf is not None:
-            verification_errors.append(vf)
+        self.scapy_exec(f"eth = Ether(dst='{dut_mac}', src='{tester_mac}')")
+        self.scapy_exec(f"iface = '{iface}'")
 
-        # tunneled outer
-        vf = self.try_helper_hardware_checksum_check_catch_failure(
-            'Ether(dst="%s", src="%s")/IP()/UDP()/IP(%s)/("X"*50)',
-            "PKT_RX_OUTER_IP_CKSUM_")
-        if vf is not None:
-            verification_errors.append(vf)
+        # Untunnelled
+        for l4 in l4_protos:
+            for chksum in "", "chksum=0xf":
+                vf = self.send_pkt_expect_good_bad_from_flag_catch_failure(
+                    f"eth/IP({chksum})/{l4}()/(X'*50)",
+                    "PKT_RX_IP_CKSUM_", f"{l4}",
+                    should_pass=(chksum == ""))
+                if vf is not None:
+                    verification_errors.append(vf)
 
-        self.verify(len(verification_errors) == 0, "\n".join(verification_errors))
+        for err in verification_errors:
+            self.logger.error(str(err))
+        self.verify(len(verification_errors) == 0, "See previous output")
 
+        self.tester.send_expect("quit()", "# ")
         self.dut.send_expect("stop", "testpmd>")
 
-    def test_hardware_checksum_check_l4(self):
+    def test_hardware_checksum_check_ip_tx(self):
         self.checksum_enablehw(self.dut_ports[0])
         self.dut.send_expect("start", "testpmd>")
 
         verification_errors: List[VerifyFailure] = []
 
-        l3_protos: List[str] = [
-            "IP",
-            "IPv6"
-        ]
+        iface = self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))
+        dut_mac = self.dut.get_mac_address(self.dut_ports[0])
+        tester_mac = self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))
+        eth = Ether(dst=dut_mac, src=tester_mac)
 
-        l4_protos: List[str] = [
-            "UDP",
-            "TCP",
-            "SCTP",
+        checksum_options = ({}, {'chksum': 0xf},)
+
+        packets = [
+            eth / IP(**chksum) / TCP() / Raw(load=str(int(len(chksum) != 1))) for chksum in checksum_options
         ]
 
+        capture_file_name = "test_hardware_checksum_check_l3_tx_capture.pcap"
+
+        packet_file_path = "/tmp/test_hardware_checksum_check_l3_tx_packets.pcap"
+        capture_file_path = "/tmp/tester/" + capture_file_name
+
+        self.tester.send_expect(f"tcpdump -i {iface} -s 65535 -w {capture_file_path} &", "# ")
+
+        wrpcap(packet_file_path, packets)
+        self.tester.session.copy_file_to(packet_file_path, packet_file_path)
+
+        self.replay_pcap_file_on_tester(iface, packet_file_path)
+
+        self.tester.session.copy_file_from(packet_file_path, "output/tmp/pcap/" + capture_file_name)
+
+        captured_packets = rdpcap("output/tmp/pcap/" + capture_file_name)
+
+        self.verify(len(packets) == len(captured_packets), "Not all packets were received")
+
+        error_messages = []
+        for pkt in captured_packets:
+            should_pass = pkt[TCP].payload.build() == b'1'
+            if not (self.validate_checksum(pkt, IP) == should_pass):
+                error_messages.append(f"A packet was marked as having a"
+                                      f"{' valid' if should_pass == '' else 'n invalid'}"
+                                      f" checksum when it should have had the opposite.")
+
+        self.dut.send_expect("stop", "testpmd>")
+        if len(error_messages) != 0:
+            for error_msg in error_messages:
+                self.logger.error(error_msg)
+            self.verify(False, "See prior output")
+
+    def test_hardware_checksum_check_l4_rx(self):
+        self.checksum_enablehw(self.dut_ports[0])
+        self.dut.send_expect("start", "testpmd>")
+
+        verification_errors: List[VerifyFailure] = []
+
         iface = self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))
         dut_mac = self.dut.get_mac_address(self.dut_ports[0])
         tester_mac = self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))
@@ -589,7 +802,7 @@ class TestChecksumOffload(TestCase):
                                 should_pass = outer_arg == ""
                             vf = self.send_pkt_expect_good_bad_from_flag_catch_failure(
                                 f"eth/{l3}()/{l4}({outer_arg})/VXLAN()/{l3}()/"
-                                f"{l4}({inner_arg})/('X'*50)",
+                                f"{l4}(chksum={inner_arg})/('X'*50)",
                                 flag, f"{l3}/{l4}/VXLAN/{l3}/{l4}",
                                 should_pass=should_pass)
 
@@ -602,8 +815,7 @@ class TestChecksumOffload(TestCase):
                 for inner_arg in "", "chksum=0xf":
                     should_pass: bool = inner_arg == ""
                     vf = self.send_pkt_expect_good_bad_from_flag_catch_failure(
-                        f"eth/{l3}()/GRE()/{l3}()/"
-                        f"{l4}({inner_arg})/('X'*50)",
+                        f"eth/{l3}()/GRE()/{l3}()/{l4}({inner_arg})/('X'*50)",
                         "PKT_RX_L4_CKSUM_", f"{l3}/GRE/{l3}/{l4}",
                         should_pass=should_pass)
 
@@ -615,6 +827,8 @@ class TestChecksumOffload(TestCase):
         # updated this test case can easily take advantage of the new functionality.
 
         # # GENEVE
+        # # This import is over here so that it is not forgotten when the update happens
+        # from scapy.contrib.geneve import GENEVE
         # for l3_outer in l3_protos:
         #     for l4_outer in l4_protos:
         #         for l3_inner in l3_protos:
@@ -638,7 +852,46 @@ class TestChecksumOffload(TestCase):
             self.logger.error(str(err))
         self.verify(len(verification_errors) == 0, "See previous output")
 
+        self.tester.send_expect("quit", "#")
+        self.dut.send_expect("stop", "testpmd>")
+
+    def test_hardware_checksum_check_l4_tx(self):
+        self.checksum_enablehw(self.dut_ports[0])
+        self.dut.send_expect("start", "testpmd>")
+
+        verification_errors: List[VerifyFailure] = []
+
+        iface = self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))
+        dut_mac = self.dut.get_mac_address(self.dut_ports[0])
+        tester_mac = self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))
+
+        packets = self.get_packets(dut_mac, tester_mac)
+
+        capture_file_name = "test_hardware_checksum_check_l4_tx_capture.pcap"
+
+        packet_file_path = "/tmp/test_hardware_checksum_check_l4_tx_packets.pcap"
+        capture_file_path = "/tmp/tester/" + capture_file_name
+
+        self.tester.send_expect(f"tcpdump -i {iface} -s 65535 -w {capture_file_path} &", "# ")
+
+        wrpcap(packet_file_path, packets)
+        self.tester.session.copy_file_to(packet_file_path, packet_file_path)
+
+        self.replay_pcap_file_on_tester(iface, packet_file_path)
+
+        self.tester.session.copy_file_from(packet_file_path, "output/tmp/pcap/" + capture_file_name)
+
+        captured_packets = rdpcap("output/tmp/pcap/" + capture_file_name)
+
+        self.verify(len(packets) == len(captured_packets), "Not all packets were received")
+
+        error_messages = self.validate_packet_list_checksums(captured_packets)
+
         self.dut.send_expect("stop", "testpmd>")
+        if len(error_messages) != 0:
+            for error_msg in error_messages:
+                self.logger.error(error_msg)
+            self.verify(False, "See prior output")
 
     def tear_down(self):
         """
-- 
2.25.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [dts] [PATCH] checksum hardware checks: fix typo
  2020-07-20 14:07 ` [dts] [PATCH] checksum checks: Add hardware offload l3 and l4 cases Owen Hilyard
@ 2020-07-20 14:13   ` Owen Hilyard
  2020-08-12  1:53     ` Ma, LihongX
  2020-07-24  2:45   ` [dts] [PATCH] checksum checks: Add hardware offload l3 and l4 cases Tu, Lijuan
  1 sibling, 1 reply; 6+ messages in thread
From: Owen Hilyard @ 2020-07-20 14:13 UTC (permalink / raw)
  To: dts
  Cc: ferruh.yigit, arybchenko, olivier.matz, david.marchand,
	ivan.malov, bruce.richardson, lylavoie, rasland, j.hendergart,
	ohilyard, thomas

fixed typo

Signed-off-by: Owen Hilyard <ohilyard@iol.unh.edu>
---
 test_plans/checksum_offload_test_plan.rst | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test_plans/checksum_offload_test_plan.rst b/test_plans/checksum_offload_test_plan.rst
index de2e1a9..2010641 100644
--- a/test_plans/checksum_offload_test_plan.rst
+++ b/test_plans/checksum_offload_test_plan.rst
@@ -318,7 +318,7 @@ Start the packet forwarding::
     TX threshold registers: pthresh=32 hthresh=8 wthresh=8
 
 
-Start a packet capture on the tester in the backround::
+Start a packet capture on the tester in the background::
 
    # tcpdump -i <iface> -s 65535 -w /tmp/tester/test_hardware_checksum_check_l4_tx_capture.pcap &
 
@@ -358,7 +358,7 @@ Start the packet forwarding::
     TX threshold registers: pthresh=32 hthresh=8 wthresh=8
 
 
-Start a packet capture on the tester in the backround::
+Start a packet capture on the tester in the background::
 
    # tcpdump -i <iface> -s 65535 -w /tmp/tester/test_hardware_checksum_check_l3_tx_capture.pcap &
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [dts] [PATCH] checksum checks: Add hardware offload l3 and l4 cases
  2020-07-20 14:07 ` [dts] [PATCH] checksum checks: Add hardware offload l3 and l4 cases Owen Hilyard
  2020-07-20 14:13   ` [dts] [PATCH] checksum hardware checks: fix typo Owen Hilyard
@ 2020-07-24  2:45   ` Tu, Lijuan
  2020-07-24 12:43     ` Owen Hilyard
  1 sibling, 1 reply; 6+ messages in thread
From: Tu, Lijuan @ 2020-07-24  2:45 UTC (permalink / raw)
  To: Owen Hilyard, dts
  Cc: Yigit, Ferruh, arybchenko, olivier.matz, david.marchand,
	ivan.malov, Richardson, Bruce, lylavoie, rasland, j.hendergart,
	thomas

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.

Thanks, Lijuan.

> -----Original Message-----
> From: dts <dts-bounces@dpdk.org> On Behalf Of Owen Hilyard
> Sent: 2020^[$BG/^[(B7^[$B7n^[(B20^[$BF|^[(B 22:08
> To: dts@dpdk.org
> Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; arybchenko@solarflare.com;
> olivier.matz@6wind.com; david.marchand@redhat.com;
> ivan.malov@oktetlabs.ru; Richardson, Bruce <bruce.richardson@intel.com>;
> lylavoie@iol.unh.edu; rasland@mellanox.com; j.hendergart@f5.com;
> ohilyard@iol.unh.edu; thomas@monjalon.net
> Subject: [dts] [PATCH] checksum checks: Add hardware offload l3 and l4 cases
> 
> add rx and tx l3 test cases
> add tx l4 test case
> add documentation for new test cases
> 
> Signed-off-by: Owen Hilyard <ohilyard@iol.unh.edu>
> ---
>  test_plans/checksum_offload_test_plan.rst | 122 +++++++-
>  tests/TestSuite_checksum_offload.py       | 331 +++++++++++++++++++---
>  2 files changed, 412 insertions(+), 41 deletions(-)
> 
> diff --git a/test_plans/checksum_offload_test_plan.rst
> b/test_plans/checksum_offload_test_plan.rst
> index 4fd8c5a..de2e1a9 100644
> --- a/test_plans/checksum_offload_test_plan.rst
> +++ b/test_plans/checksum_offload_test_plan.rst
> @@ -221,7 +221,7 @@ combination: good/bad ip checksum + good/bad
> udp/tcp checksum.
> 
>  Check the Rx checksum flags consistent with expected flags.
> 
> -Test Case: Hardware Checksum Check L4
> +Test Case: Hardware Checksum Check L4 RX
>  ===========================================
>  This test involves testing many different scenarios with a L4 checksum.
>  A variety of tunneling protocols, L3 protocols and L4 protocols are combined
> @@ -256,4 +256,122 @@ Send a packet with a bad checksum::
>     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
>     tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
> 
> -Verify flags are as expected.
> \ No newline at end of file
> +Verify flags are as expected.
> +
> +Test Case: Hardware Checksum Check L3 RX
> +===========================================
> +This test involves testing L3 checksum hardware offload.
> +Due to the relative dominance of IPv4 and IPv6 as L3 protocols, and
> +IPv6's lack of a checksum, only IPv4's checksum is tested.
> +
> +Setup the ``csum`` forwarding mode::
> +
> +  testpmd> set fwd csum
> +  Set csum packet forwarding mode
> +
> +Start the packet forwarding::
> +
> +  testpmd> start
> +    csum packet forwarding - CRC stripping disabled - packets/burst=32
> +    nb forwarding cores=1 - nb forwarding ports=10
> +    RX queues=1 - RX desc=128 - RX free threshold=64
> +    RX threshold registers: pthresh=8 hthresh=8 wthresh=4
> +    TX queues=1 - TX desc=512 - TX free threshold=0
> +    TX threshold registers: pthresh=32 hthresh=8 wthresh=8
> +
> +Send a packet with a good checksum::
> +
> +   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:
> +   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
> +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
> +
> +Send a packet with a bad checksum::
> +
> +   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:
> +   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
> +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
> +
> +Verify flags are as expected.
> +
> +Test Case: Hardware Checksum Check L4 TX
> +===========================================
> +This test involves testing many different scenarios with a L4 checksum.
> +A variety of tunneling protocols, L3 protocols and L4 protocols are
> +combined to test as many scenarios as possible. Currently, UDP, TCP and
> +SCTP are used as L4 protocols, with IP and IPv6 being used at level 3.
> +The tested tunneling protocols are VXLAN and GRE. This test is used to
> +determine whether the hardware offloading of checksums works properly.
> +
> +Setup the ``csum`` forwarding mode::
> +
> +  testpmd> set fwd csum
> +  Set csum packet forwarding mode
> +
> +Start the packet forwarding::
> +
> +  testpmd> start
> +    csum packet forwarding - CRC stripping disabled - packets/burst=32
> +    nb forwarding cores=1 - nb forwarding ports=10
> +    RX queues=1 - RX desc=128 - RX free threshold=64
> +    RX threshold registers: pthresh=8 hthresh=8 wthresh=4
> +    TX queues=1 - TX desc=512 - TX free threshold=0
> +    TX threshold registers: pthresh=32 hthresh=8 wthresh=8
> +
> +
> +Start a packet capture on the tester in the backround::
> +
> +   # tcpdump -i <iface> -s 65535 -w
> + /tmp/tester/test_hardware_checksum_check_l4_tx_capture.pcap &
> +
> +Send a packet with a good checksum::
> +
> +   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:
> +   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
> +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
> +
> +Send a packet with a bad checksum::
> +
> +   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:
> +   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
> +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
> +
> +Inspect the pcap file from the packet capture and verify the checksums.
> +
> +Test Case: Hardware Checksum Check L3 TX
> +===========================================
> +This test involves testing L3 checksum hardware offload.
> +Due to the relative dominance of IPv4 and IPv6 as L3 protocols, and
> +IPv6's lack of a checksum, only IPv4's checksum is tested.
> +
> +Setup the ``csum`` forwarding mode::
> +
> +  testpmd> set fwd csum
> +  Set csum packet forwarding mode
> +
> +Start the packet forwarding::
> +
> +  testpmd> start
> +    csum packet forwarding - CRC stripping disabled - packets/burst=32
> +    nb forwarding cores=1 - nb forwarding ports=10
> +    RX queues=1 - RX desc=128 - RX free threshold=64
> +    RX threshold registers: pthresh=8 hthresh=8 wthresh=4
> +    TX queues=1 - TX desc=512 - TX free threshold=0
> +    TX threshold registers: pthresh=32 hthresh=8 wthresh=8
> +
> +
> +Start a packet capture on the tester in the backround::
> +
> +   # tcpdump -i <iface> -s 65535 -w
> + /tmp/tester/test_hardware_checksum_check_l3_tx_capture.pcap &
> +
> +Send a packet with a good checksum with a 1 in it's payload::
> +
> +   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:
> +   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
> +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
> +
> +Send a packet with a bad checksum with a 0 in it's payload::
> +
> +   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:
> +   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
> +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
> +
> +Inspect the pcap file from the packet capture and verify the checksums.
> diff --git a/tests/TestSuite_checksum_offload.py
> b/tests/TestSuite_checksum_offload.py
> index 9ff5a41..c4a877d 100644
> --- a/tests/TestSuite_checksum_offload.py
> +++ b/tests/TestSuite_checksum_offload.py
> @@ -47,8 +47,18 @@ import time
> 
>  from rst import RstReport
>  import utils
> -
> +from exception import VerifyFailure
> +from pktgen import PacketGeneratorHelper from scapy.layers.inet import
> +UDP, TCP, IP from scapy.layers.inet6 import IPv6 from scapy.layers.l2
> +import Ether, GRE from scapy.layers.sctp import SCTP from
> +scapy.layers.vxlan import VXLAN from scapy.packet import Raw from
> +scapy.utils import wrpcap, rdpcap from test_capabilities import
> +DRIVER_TEST_LACK_CAPA
>  from test_case import TestCase
> +
>  from framework.pmd_output import PmdOutput  from test_capabilities import
> DRIVER_TEST_LACK_CAPA  from pktgen import PacketGeneratorHelper @@ -
> 57,6 +67,33 @@ import packet
> 
>  from settings import FOLDERS
> 
> +l3_proto_classes = [
> +    IP,
> +    IPv6
> +]
> +
> +l4_proto_classes = [
> +    UDP,
> +    TCP,
> +    SCTP
> +]
> +
> +tunnelling_proto_classes = [
> +    VXLAN,
> +    GRE,
> +]
> +
> +l3_protos = [
> +    "IP",
> +    "IPv6"
> +]
> +
> +l4_protos = [
> +    "UDP",
> +    "TCP",
> +    "SCTP",
> +]
> +
> 
>  class TestChecksumOffload(TestCase):
> 
> @@ -79,8 +116,6 @@ class TestChecksumOffload(TestCase):
>              cur_path = os.path.dirname(
>                  os.path.dirname(os.path.realpath(__file__)))
>              self.output_path = os.sep.join([cur_path, self.logger.log_path])
> -        # create an instance to set stream field setting
> -        self.pktgen_helper = PacketGeneratorHelper()
> 
>      def set_up(self):
>          """
> @@ -243,7 +278,6 @@ class TestChecksumOffload(TestCase):
>      def send_pkt_expect_good_bad_from_flag(self, pkt_str: str, flag: str,
> test_name: str, should_pass: bool = True):
>          self.pmdout.get_output(timeout=5)  # Remove any old output
>          self.scapy_exec(f"sendp({pkt_str}, iface=iface)")
> -        time.sleep(1)
>          testpmd_output: str = self.pmdout.get_output(timeout=5)
>          self.verify(flag in testpmd_output,
>                      f"Flag {flag[:-1]} not found for test {test_name}, please run
> test_rx_checksum_valid_flags.") @@ -269,11 +303,147 @@ class
> TestChecksumOffload(TestCase):
> 
>          return None
> 
> -    def scapy_exec(self, cmd: str):
> -        return self.tester.send_expect(cmd, ">>>")
> +    def validate_checksum(self, pkt, layer) -> bool:
> +        """
> +        @param pkt: The packet to validate the checksum of.
> +        @return: Whether the checksum was valid.
> +        """
> +        if pkt is None:
> +            return False
> +
> +        csum = pkt[layer].chksum
> +        del pkt[layer].chksum
> +        # Converting it to raw will calculate the checksum
> +        return layer(Raw(pkt[layer])).chksum == csum
> 
> -    def scapy_send_append(self, packet: str):
> -        return self.tester.scapy_append(f'sendp({packet}, iface=iface)')
> +    def scapy_exec(self, cmd: str, timeout=1) -> str:
> +        return self.tester.send_expect(cmd, ">>>", timeout=timeout)
> +
> +    def get_packets(self, dut_mac, tester_mac):
> +        eth = Ether(dst=dut_mac, src=tester_mac)
> +        packets = []
> +        checksum_options = ({}, {'chksum': 0xf},)
> +        # Untunneled
> +        for l3 in l3_proto_classes:
> +            for l4 in l4_proto_classes:
> +                for chksum in checksum_options:
> +                    # The packet's data can be used to identify how the packet was
> constructed so avoid any issues with
> +                    # ordering
> +                    pkt = eth / l3() / l4(**chksum) / (
> +                        f'UNTUNNELED,{l3.__name__},{l4.__name__},{" " if
> len(chksum.values()) == 0 else chksum["chksum"]}'
> +                    )
> +
> +                    # Prevents the default behavior which adds DNS headers
> +                    if l4 == UDP:
> +                        pkt[UDP].dport, pkt[UDP].sport = 1001, 1001
> +
> +                    packets.append(pkt)
> +
> +        # Tunneled
> +        # VXLAN
> +        for l3 in l3_proto_classes:
> +            for l4 in l4_proto_classes:
> +                for outer_arg in checksum_options:
> +                    for inner_arg in checksum_options:
> +                        pkt = eth / l3() / UDP(**outer_arg) / VXLAN() / Ether() / l3() /
> l4(**inner_arg) / (
> +                            f'VXLAN,{l3.__name__},{l4.__name__},'
> +                            f'{" " if len(outer_arg.values()) == 0 else outer_arg["chksum"]},'
> +                            f'{" " if len(inner_arg.values()) == 0 else inner_arg["chksum"]}'
> +                        )
> +                        # Prevents the default behavior which adds DNS headers
> +                        if l4 == UDP:
> +                            pkt[VXLAN][UDP].dport,
> + pkt[VXLAN][UDP].sport = 1001, 1001
> +
> +                        packets.append(pkt)
> +        # GRE
> +        for l3 in l3_proto_classes:
> +            for l4 in l4_proto_classes:
> +                for chksum in checksum_options:
> +                    pkt = eth / l3() / GRE() / l3() / l4(**chksum) / (
> +                        f'GRE,{l3.__name__},{l4.__name__},{" " if len(chksum.values()) ==
> 0 else chksum["chksum"]}'
> +                    )
> +
> +                    # Prevents the default behavior which adds DNS headers
> +                    if l4 == UDP:
> +                        pkt[GRE][UDP].dport, pkt[GRE][UDP].sport =
> + 1001, 1001
> +
> +                    packets.append(pkt)
> +
> +        return packets
> +
> +    def replay_pcap_file_on_tester(self, iface, packet_file_path):
> +        self.tester.send_expect("scapy", ">>>")
> +        self.scapy_exec(f"packets = rdpcap('{packet_file_path}')")
> +        self.scapy_exec(f"sendp(packets, iface={iface})")
> +        self.tester.send_expect("quit()", "# ")
> +
> +    def validate_packet_list_checksums(self, packets):
> +        name_to_class_dict = {
> +            'UDP': UDP,
> +            'TCP': TCP,
> +            'SCTP': SCTP,
> +            'IP': IP,
> +            'IPv6': IPv6,
> +            'VXLAN': VXLAN,
> +            'GRE': GRE,
> +        }
> +
> +        error_messages = []
> +
> +        untunnelled_error_message = f"Invalid untunneled checksum state
> for %s/%s with a %s checksum."
> +
> +        vxlan_error_message = f"Invalid VXLAN tunnelled %s checksum state
> for %s/%s" \
> +                              f" with a %s inner checksum and a %s outer checksum."
> +
> +        gre_error_message = f"Invalid GRE tunnelled checksum state for %s/%s
> with a %s checksum."
> +
> +        for packet in packets:
> +            payload: str
> +            # try:
> +            payload = packet[Raw].load.decode('utf-8').split(",")
> +            # # This error usually happens with tunneling protocols, and means that
> an additional cast is needed
> +            # except UnicodeDecodeError:
> +            #     for proto in tunnelling_proto_classes:
> +
> +            l3 = name_to_class_dict[payload[1]]
> +            l4 = name_to_class_dict[payload[2]]
> +            if payload[0] == "UNTUNNELED":
> +                chksum_should_be_valid = payload[3] == " "
> +                if self.validate_checksum(packet, l4) != chksum_should_be_valid:
> +                    error_messages.append(
> +                        untunnelled_error_message % (
> +                            l3.__name__, l4.__name__, 'valid' if chksum_should_be_valid
> == '' else 'invalid'
> +                        )
> +                    )
> +            elif payload[0] == "VXLAN":
> +                outer_chksum_should_be_valid = payload[3] == " "
> +                inner_chksum_should_be_valid = payload[4] == " "
> +                if self.validate_checksum(packet[VXLAN], l4) !=
> inner_chksum_should_be_valid:
> +                    error_messages.append(
> +                        vxlan_error_message % (
> +                            "inner", l4.__name__, l3.__name__,
> +                            'valid' if inner_chksum_should_be_valid == '' else 'invalid',
> +                            'valid' if outer_chksum_should_be_valid == '' else 'invalid'
> +                        )
> +                    )
> +                if self.validate_checksum(packet, l4) !=
> outer_chksum_should_be_valid:
> +                    error_messages.append(
> +                        vxlan_error_message % (
> +                            "outer", l3.__name__, l4.__name__,
> +                            'valid' if inner_chksum_should_be_valid == '' else 'invalid',
> +                            'valid' if outer_chksum_should_be_valid == '' else 'invalid'
> +                        )
> +                    )
> +            elif payload[0] == "GRE":
> +                chksum_should_be_valid = payload[3] == " "
> +                if self.validate_checksum(packet, l4) != chksum_should_be_valid:
> +                    error_messages.append(
> +                        gre_error_message % (
> +                            l3.__name__, l4.__name__, 'valid' if chksum_should_be_valid
> == '' else 'invalid'
> +                        )
> +                    )
> +
> +        return error_messages
> 
>      #
>      #
> @@ -448,6 +618,9 @@ class TestChecksumOffload(TestCase):
> 
>              # clear streams before add new streams
>              self.tester.pktgen.clear_streams()
> +            # create an instance to set stream field setting
> +            # Moved here because it messes with the ability of the functional tests
> to use scapy.
> +            self.pktgen_helper = PacketGeneratorHelper()
>              # run packet generator
>              streams = self.pktgen_helper.prepare_stream_from_tginput(tgenInput,
> 100,
>                      None, self.tester.pktgen) @@ -511,53 +684,93 @@ class
> TestChecksumOffload(TestCase):
>              self.dut.send_expect("quit", "#", 10)
>              self.result_table_print()
> 
> -    def test_hardware_checksum_check_ip(self):
> +    def test_hardware_checksum_check_ip_rx(self):
>          self.dut.send_expect("start", "testpmd>")
> +        self.tester.send_expect("scapy", ">>>")
>          self.checksum_enablehw(self.dut_ports[0])
> +        self.dut.send_expect("start", "testpmd>")
> 
>          verification_errors: List[VerifyFailure] = []
> 
> -        # untunnelled
> -        vf =
> self.try_helper_hardware_checksum_check_catch_failure('Ether(dst="%s",
> src="%s")/IP(%s)/UDP()/("X"*50)',
> -                                                                   "PKT_RX_IP_CKSUM_")
> -        if vf is not None:
> -            verification_errors.append(vf)
> +        iface =
> self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))
> +        dut_mac = self.dut.get_mac_address(self.dut_ports[0])
> +        tester_mac =
> + self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))
> 
> -        # tunneled inner
> -        vf = self.try_helper_hardware_checksum_check_catch_failure(
> -            'Ether(dst="%s", src="%s")/IP()/UDP()/IP(%s)/("X"*50)',
> -            "PKT_RX_OUTER_IP_CKSUM_")
> -        if vf is not None:
> -            verification_errors.append(vf)
> +        self.scapy_exec(f"eth = Ether(dst='{dut_mac}', src='{tester_mac}')")
> +        self.scapy_exec(f"iface = '{iface}'")
> 
> -        # tunneled outer
> -        vf = self.try_helper_hardware_checksum_check_catch_failure(
> -            'Ether(dst="%s", src="%s")/IP()/UDP()/IP(%s)/("X"*50)',
> -            "PKT_RX_OUTER_IP_CKSUM_")
> -        if vf is not None:
> -            verification_errors.append(vf)
> +        # Untunnelled
> +        for l4 in l4_protos:
> +            for chksum in "", "chksum=0xf":
> +                vf = self.send_pkt_expect_good_bad_from_flag_catch_failure(
> +                    f"eth/IP({chksum})/{l4}()/(X'*50)",
> +                    "PKT_RX_IP_CKSUM_", f"{l4}",
> +                    should_pass=(chksum == ""))
> +                if vf is not None:
> +                    verification_errors.append(vf)
> 
> -        self.verify(len(verification_errors) == 0, "\n".join(verification_errors))
> +        for err in verification_errors:
> +            self.logger.error(str(err))
> +        self.verify(len(verification_errors) == 0, "See previous
> + output")
> 
> +        self.tester.send_expect("quit()", "# ")
>          self.dut.send_expect("stop", "testpmd>")
> 
> -    def test_hardware_checksum_check_l4(self):
> +    def test_hardware_checksum_check_ip_tx(self):
>          self.checksum_enablehw(self.dut_ports[0])
>          self.dut.send_expect("start", "testpmd>")
> 
>          verification_errors: List[VerifyFailure] = []
> 
> -        l3_protos: List[str] = [
> -            "IP",
> -            "IPv6"
> -        ]
> +        iface =
> self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))
> +        dut_mac = self.dut.get_mac_address(self.dut_ports[0])
> +        tester_mac =
> self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))
> +        eth = Ether(dst=dut_mac, src=tester_mac)
> 
> -        l4_protos: List[str] = [
> -            "UDP",
> -            "TCP",
> -            "SCTP",
> +        checksum_options = ({}, {'chksum': 0xf},)
> +
> +        packets = [
> +            eth / IP(**chksum) / TCP() / Raw(load=str(int(len(chksum)
> + != 1))) for chksum in checksum_options
>          ]
> 
> +        capture_file_name =
> "test_hardware_checksum_check_l3_tx_capture.pcap"
> +
> +        packet_file_path =
> "/tmp/test_hardware_checksum_check_l3_tx_packets.pcap"
> +        capture_file_path = "/tmp/tester/" + capture_file_name
> +
> +        self.tester.send_expect(f"tcpdump -i {iface} -s 65535 -w
> + {capture_file_path} &", "# ")
> +
> +        wrpcap(packet_file_path, packets)
> +        self.tester.session.copy_file_to(packet_file_path,
> + packet_file_path)
> +
> +        self.replay_pcap_file_on_tester(iface, packet_file_path)
> +
> +        self.tester.session.copy_file_from(packet_file_path,
> + "output/tmp/pcap/" + capture_file_name)
> +
> +        captured_packets = rdpcap("output/tmp/pcap/" +
> + capture_file_name)
> +
> +        self.verify(len(packets) == len(captured_packets), "Not all
> + packets were received")
> +
> +        error_messages = []
> +        for pkt in captured_packets:
> +            should_pass = pkt[TCP].payload.build() == b'1'
> +            if not (self.validate_checksum(pkt, IP) == should_pass):
> +                error_messages.append(f"A packet was marked as having a"
> +                                      f"{' valid' if should_pass == '' else 'n invalid'}"
> +                                      f" checksum when it should have
> + had the opposite.")
> +
> +        self.dut.send_expect("stop", "testpmd>")
> +        if len(error_messages) != 0:
> +            for error_msg in error_messages:
> +                self.logger.error(error_msg)
> +            self.verify(False, "See prior output")
> +
> +    def test_hardware_checksum_check_l4_rx(self):
> +        self.checksum_enablehw(self.dut_ports[0])
> +        self.dut.send_expect("start", "testpmd>")
> +
> +        verification_errors: List[VerifyFailure] = []
> +
>          iface =
> self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))
>          dut_mac = self.dut.get_mac_address(self.dut_ports[0])
>          tester_mac =
> self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))
> @@ -589,7 +802,7 @@ class TestChecksumOffload(TestCase):
>                                  should_pass = outer_arg == ""
>                              vf = self.send_pkt_expect_good_bad_from_flag_catch_failure(
>                                  f"eth/{l3}()/{l4}({outer_arg})/VXLAN()/{l3}()/"
> -                                f"{l4}({inner_arg})/('X'*50)",
> +                                f"{l4}(chksum={inner_arg})/('X'*50)",
>                                  flag, f"{l3}/{l4}/VXLAN/{l3}/{l4}",
>                                  should_pass=should_pass)
> 
> @@ -602,8 +815,7 @@ class TestChecksumOffload(TestCase):
>                  for inner_arg in "", "chksum=0xf":
>                      should_pass: bool = inner_arg == ""
>                      vf = self.send_pkt_expect_good_bad_from_flag_catch_failure(
> -                        f"eth/{l3}()/GRE()/{l3}()/"
> -                        f"{l4}({inner_arg})/('X'*50)",
> +
> + f"eth/{l3}()/GRE()/{l3}()/{l4}({inner_arg})/('X'*50)",
>                          "PKT_RX_L4_CKSUM_", f"{l3}/GRE/{l3}/{l4}",
>                          should_pass=should_pass)
> 
> @@ -615,6 +827,8 @@ class TestChecksumOffload(TestCase):
>          # updated this test case can easily take advantage of the new functionality.
> 
>          # # GENEVE
> +        # # This import is over here so that it is not forgotten when the update
> happens
> +        # from scapy.contrib.geneve import GENEVE
>          # for l3_outer in l3_protos:
>          #     for l4_outer in l4_protos:
>          #         for l3_inner in l3_protos:
> @@ -638,7 +852,46 @@ class TestChecksumOffload(TestCase):
>              self.logger.error(str(err))
>          self.verify(len(verification_errors) == 0, "See previous output")
> 
> +        self.tester.send_expect("quit", "#")
> +        self.dut.send_expect("stop", "testpmd>")
> +
> +    def test_hardware_checksum_check_l4_tx(self):
> +        self.checksum_enablehw(self.dut_ports[0])
> +        self.dut.send_expect("start", "testpmd>")
> +
> +        verification_errors: List[VerifyFailure] = []
> +
> +        iface =
> self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))
> +        dut_mac = self.dut.get_mac_address(self.dut_ports[0])
> +        tester_mac =
> + self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))
> +
> +        packets = self.get_packets(dut_mac, tester_mac)
> +
> +        capture_file_name =
> "test_hardware_checksum_check_l4_tx_capture.pcap"
> +
> +        packet_file_path =
> "/tmp/test_hardware_checksum_check_l4_tx_packets.pcap"
> +        capture_file_path = "/tmp/tester/" + capture_file_name
> +
> +        self.tester.send_expect(f"tcpdump -i {iface} -s 65535 -w
> + {capture_file_path} &", "# ")
> +
> +        wrpcap(packet_file_path, packets)
> +        self.tester.session.copy_file_to(packet_file_path,
> + packet_file_path)
> +
> +        self.replay_pcap_file_on_tester(iface, packet_file_path)
> +
> +        self.tester.session.copy_file_from(packet_file_path,
> + "output/tmp/pcap/" + capture_file_name)
> +
> +        captured_packets = rdpcap("output/tmp/pcap/" +
> + capture_file_name)
> +
> +        self.verify(len(packets) == len(captured_packets), "Not all
> + packets were received")
> +
> +        error_messages =
> + self.validate_packet_list_checksums(captured_packets)
> +
>          self.dut.send_expect("stop", "testpmd>")
> +        if len(error_messages) != 0:
> +            for error_msg in error_messages:
> +                self.logger.error(error_msg)
> +            self.verify(False, "See prior output")
> 
>      def tear_down(self):
>          """
> --
> 2.25.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [dts] [PATCH] checksum checks: Add hardware offload l3 and l4 cases
  2020-07-24  2:45   ` [dts] [PATCH] checksum checks: Add hardware offload l3 and l4 cases Tu, Lijuan
@ 2020-07-24 12:43     ` Owen Hilyard
  0 siblings, 0 replies; 6+ messages in thread
From: Owen Hilyard @ 2020-07-24 12:43 UTC (permalink / raw)
  To: Tu, Lijuan
  Cc: dts, Yigit, Ferruh, arybchenko, olivier.matz, david.marchand,
	ivan.malov, Richardson, Bruce, lylavoie, rasland, j.hendergart,
	thomas

[-- Attachment #1: Type: text/plain, Size: 28747 bytes --]

Unfortunately I had to start a new email thread since intel's server didn't
like the self-signed certificate on my local mail server. I merged all of
the patches into one patch so it's a little easier to review for the second
time.

On Thu, Jul 23, 2020 at 10:45 PM Tu, Lijuan <lijuan.tu@intel.com> wrote:

> 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.
>
> Thanks, Lijuan.
>
> > -----Original Message-----
> > From: dts <dts-bounces@dpdk.org> On Behalf Of Owen Hilyard
> > Sent: 2020年7月20日 22:08
> > To: dts@dpdk.org
> > Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; arybchenko@solarflare.com;
> > olivier.matz@6wind.com; david.marchand@redhat.com;
> > ivan.malov@oktetlabs.ru; Richardson, Bruce <bruce.richardson@intel.com>;
> > lylavoie@iol.unh.edu; rasland@mellanox.com; j.hendergart@f5.com;
> > ohilyard@iol.unh.edu; thomas@monjalon.net
> > Subject: [dts] [PATCH] checksum checks: Add hardware offload l3 and l4
> cases
> >
> > add rx and tx l3 test cases
> > add tx l4 test case
> > add documentation for new test cases
> >
> > Signed-off-by: Owen Hilyard <ohilyard@iol.unh.edu>
> > ---
> >  test_plans/checksum_offload_test_plan.rst | 122 +++++++-
> >  tests/TestSuite_checksum_offload.py       | 331 +++++++++++++++++++---
> >  2 files changed, 412 insertions(+), 41 deletions(-)
> >
> > diff --git a/test_plans/checksum_offload_test_plan.rst
> > b/test_plans/checksum_offload_test_plan.rst
> > index 4fd8c5a..de2e1a9 100644
> > --- a/test_plans/checksum_offload_test_plan.rst
> > +++ b/test_plans/checksum_offload_test_plan.rst
> > @@ -221,7 +221,7 @@ combination: good/bad ip checksum + good/bad
> > udp/tcp checksum.
> >
> >  Check the Rx checksum flags consistent with expected flags.
> >
> > -Test Case: Hardware Checksum Check L4
> > +Test Case: Hardware Checksum Check L4 RX
> >  ===========================================
> >  This test involves testing many different scenarios with a L4 checksum.
> >  A variety of tunneling protocols, L3 protocols and L4 protocols are
> combined
> > @@ -256,4 +256,122 @@ Send a packet with a bad checksum::
> >     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
> >     tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
> >
> > -Verify flags are as expected.
> > \ No newline at end of file
> > +Verify flags are as expected.
> > +
> > +Test Case: Hardware Checksum Check L3 RX
> > +===========================================
> > +This test involves testing L3 checksum hardware offload.
> > +Due to the relative dominance of IPv4 and IPv6 as L3 protocols, and
> > +IPv6's lack of a checksum, only IPv4's checksum is tested.
> > +
> > +Setup the ``csum`` forwarding mode::
> > +
> > +  testpmd> set fwd csum
> > +  Set csum packet forwarding mode
> > +
> > +Start the packet forwarding::
> > +
> > +  testpmd> start
> > +    csum packet forwarding - CRC stripping disabled - packets/burst=32
> > +    nb forwarding cores=1 - nb forwarding ports=10
> > +    RX queues=1 - RX desc=128 - RX free threshold=64
> > +    RX threshold registers: pthresh=8 hthresh=8 wthresh=4
> > +    TX queues=1 - TX desc=512 - TX free threshold=0
> > +    TX threshold registers: pthresh=32 hthresh=8 wthresh=8
> > +
> > +Send a packet with a good checksum::
> > +
> > +   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:
> > +   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
> > +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
> > +
> > +Send a packet with a bad checksum::
> > +
> > +   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:
> > +   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
> > +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
> > +
> > +Verify flags are as expected.
> > +
> > +Test Case: Hardware Checksum Check L4 TX
> > +===========================================
> > +This test involves testing many different scenarios with a L4 checksum.
> > +A variety of tunneling protocols, L3 protocols and L4 protocols are
> > +combined to test as many scenarios as possible. Currently, UDP, TCP and
> > +SCTP are used as L4 protocols, with IP and IPv6 being used at level 3.
> > +The tested tunneling protocols are VXLAN and GRE. This test is used to
> > +determine whether the hardware offloading of checksums works properly.
> > +
> > +Setup the ``csum`` forwarding mode::
> > +
> > +  testpmd> set fwd csum
> > +  Set csum packet forwarding mode
> > +
> > +Start the packet forwarding::
> > +
> > +  testpmd> start
> > +    csum packet forwarding - CRC stripping disabled - packets/burst=32
> > +    nb forwarding cores=1 - nb forwarding ports=10
> > +    RX queues=1 - RX desc=128 - RX free threshold=64
> > +    RX threshold registers: pthresh=8 hthresh=8 wthresh=4
> > +    TX queues=1 - TX desc=512 - TX free threshold=0
> > +    TX threshold registers: pthresh=32 hthresh=8 wthresh=8
> > +
> > +
> > +Start a packet capture on the tester in the backround::
> > +
> > +   # tcpdump -i <iface> -s 65535 -w
> > + /tmp/tester/test_hardware_checksum_check_l4_tx_capture.pcap &
> > +
> > +Send a packet with a good checksum::
> > +
> > +   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:
> > +   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
> > +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
> > +
> > +Send a packet with a bad checksum::
> > +
> > +   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:
> > +   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
> > +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
> > +
> > +Inspect the pcap file from the packet capture and verify the checksums.
> > +
> > +Test Case: Hardware Checksum Check L3 TX
> > +===========================================
> > +This test involves testing L3 checksum hardware offload.
> > +Due to the relative dominance of IPv4 and IPv6 as L3 protocols, and
> > +IPv6's lack of a checksum, only IPv4's checksum is tested.
> > +
> > +Setup the ``csum`` forwarding mode::
> > +
> > +  testpmd> set fwd csum
> > +  Set csum packet forwarding mode
> > +
> > +Start the packet forwarding::
> > +
> > +  testpmd> start
> > +    csum packet forwarding - CRC stripping disabled - packets/burst=32
> > +    nb forwarding cores=1 - nb forwarding ports=10
> > +    RX queues=1 - RX desc=128 - RX free threshold=64
> > +    RX threshold registers: pthresh=8 hthresh=8 wthresh=4
> > +    TX queues=1 - TX desc=512 - TX free threshold=0
> > +    TX threshold registers: pthresh=32 hthresh=8 wthresh=8
> > +
> > +
> > +Start a packet capture on the tester in the backround::
> > +
> > +   # tcpdump -i <iface> -s 65535 -w
> > + /tmp/tester/test_hardware_checksum_check_l3_tx_capture.pcap &
> > +
> > +Send a packet with a good checksum with a 1 in it's payload::
> > +
> > +   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:
> > +   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
> > +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
> > +
> > +Send a packet with a bad checksum with a 0 in it's payload::
> > +
> > +   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:
> > +   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
> > +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4
> > +
> > +Inspect the pcap file from the packet capture and verify the checksums.
> > diff --git a/tests/TestSuite_checksum_offload.py
> > b/tests/TestSuite_checksum_offload.py
> > index 9ff5a41..c4a877d 100644
> > --- a/tests/TestSuite_checksum_offload.py
> > +++ b/tests/TestSuite_checksum_offload.py
> > @@ -47,8 +47,18 @@ import time
> >
> >  from rst import RstReport
> >  import utils
> > -
> > +from exception import VerifyFailure
> > +from pktgen import PacketGeneratorHelper from scapy.layers.inet import
> > +UDP, TCP, IP from scapy.layers.inet6 import IPv6 from scapy.layers.l2
> > +import Ether, GRE from scapy.layers.sctp import SCTP from
> > +scapy.layers.vxlan import VXLAN from scapy.packet import Raw from
> > +scapy.utils import wrpcap, rdpcap from test_capabilities import
> > +DRIVER_TEST_LACK_CAPA
> >  from test_case import TestCase
> > +
> >  from framework.pmd_output import PmdOutput  from test_capabilities
> import
> > DRIVER_TEST_LACK_CAPA  from pktgen import PacketGeneratorHelper @@ -
> > 57,6 +67,33 @@ import packet
> >
> >  from settings import FOLDERS
> >
> > +l3_proto_classes = [
> > +    IP,
> > +    IPv6
> > +]
> > +
> > +l4_proto_classes = [
> > +    UDP,
> > +    TCP,
> > +    SCTP
> > +]
> > +
> > +tunnelling_proto_classes = [
> > +    VXLAN,
> > +    GRE,
> > +]
> > +
> > +l3_protos = [
> > +    "IP",
> > +    "IPv6"
> > +]
> > +
> > +l4_protos = [
> > +    "UDP",
> > +    "TCP",
> > +    "SCTP",
> > +]
> > +
> >
> >  class TestChecksumOffload(TestCase):
> >
> > @@ -79,8 +116,6 @@ class TestChecksumOffload(TestCase):
> >              cur_path = os.path.dirname(
> >                  os.path.dirname(os.path.realpath(__file__)))
> >              self.output_path = os.sep.join([cur_path,
> self.logger.log_path])
> > -        # create an instance to set stream field setting
> > -        self.pktgen_helper = PacketGeneratorHelper()
> >
> >      def set_up(self):
> >          """
> > @@ -243,7 +278,6 @@ class TestChecksumOffload(TestCase):
> >      def send_pkt_expect_good_bad_from_flag(self, pkt_str: str, flag:
> str,
> > test_name: str, should_pass: bool = True):
> >          self.pmdout.get_output(timeout=5)  # Remove any old output
> >          self.scapy_exec(f"sendp({pkt_str}, iface=iface)")
> > -        time.sleep(1)
> >          testpmd_output: str = self.pmdout.get_output(timeout=5)
> >          self.verify(flag in testpmd_output,
> >                      f"Flag {flag[:-1]} not found for test {test_name},
> please run
> > test_rx_checksum_valid_flags.") @@ -269,11 +303,147 @@ class
> > TestChecksumOffload(TestCase):
> >
> >          return None
> >
> > -    def scapy_exec(self, cmd: str):
> > -        return self.tester.send_expect(cmd, ">>>")
> > +    def validate_checksum(self, pkt, layer) -> bool:
> > +        """
> > +        @param pkt: The packet to validate the checksum of.
> > +        @return: Whether the checksum was valid.
> > +        """
> > +        if pkt is None:
> > +            return False
> > +
> > +        csum = pkt[layer].chksum
> > +        del pkt[layer].chksum
> > +        # Converting it to raw will calculate the checksum
> > +        return layer(Raw(pkt[layer])).chksum == csum
> >
> > -    def scapy_send_append(self, packet: str):
> > -        return self.tester.scapy_append(f'sendp({packet}, iface=iface)')
> > +    def scapy_exec(self, cmd: str, timeout=1) -> str:
> > +        return self.tester.send_expect(cmd, ">>>", timeout=timeout)
> > +
> > +    def get_packets(self, dut_mac, tester_mac):
> > +        eth = Ether(dst=dut_mac, src=tester_mac)
> > +        packets = []
> > +        checksum_options = ({}, {'chksum': 0xf},)
> > +        # Untunneled
> > +        for l3 in l3_proto_classes:
> > +            for l4 in l4_proto_classes:
> > +                for chksum in checksum_options:
> > +                    # The packet's data can be used to identify how the
> packet was
> > constructed so avoid any issues with
> > +                    # ordering
> > +                    pkt = eth / l3() / l4(**chksum) / (
> > +                        f'UNTUNNELED,{l3.__name__},{l4.__name__},{" " if
> > len(chksum.values()) == 0 else chksum["chksum"]}'
> > +                    )
> > +
> > +                    # Prevents the default behavior which adds DNS
> headers
> > +                    if l4 == UDP:
> > +                        pkt[UDP].dport, pkt[UDP].sport = 1001, 1001
> > +
> > +                    packets.append(pkt)
> > +
> > +        # Tunneled
> > +        # VXLAN
> > +        for l3 in l3_proto_classes:
> > +            for l4 in l4_proto_classes:
> > +                for outer_arg in checksum_options:
> > +                    for inner_arg in checksum_options:
> > +                        pkt = eth / l3() / UDP(**outer_arg) / VXLAN() /
> Ether() / l3() /
> > l4(**inner_arg) / (
> > +                            f'VXLAN,{l3.__name__},{l4.__name__},'
> > +                            f'{" " if len(outer_arg.values()) == 0 else
> outer_arg["chksum"]},'
> > +                            f'{" " if len(inner_arg.values()) == 0 else
> inner_arg["chksum"]}'
> > +                        )
> > +                        # Prevents the default behavior which adds DNS
> headers
> > +                        if l4 == UDP:
> > +                            pkt[VXLAN][UDP].dport,
> > + pkt[VXLAN][UDP].sport = 1001, 1001
> > +
> > +                        packets.append(pkt)
> > +        # GRE
> > +        for l3 in l3_proto_classes:
> > +            for l4 in l4_proto_classes:
> > +                for chksum in checksum_options:
> > +                    pkt = eth / l3() / GRE() / l3() / l4(**chksum) / (
> > +                        f'GRE,{l3.__name__},{l4.__name__},{" " if
> len(chksum.values()) ==
> > 0 else chksum["chksum"]}'
> > +                    )
> > +
> > +                    # Prevents the default behavior which adds DNS
> headers
> > +                    if l4 == UDP:
> > +                        pkt[GRE][UDP].dport, pkt[GRE][UDP].sport =
> > + 1001, 1001
> > +
> > +                    packets.append(pkt)
> > +
> > +        return packets
> > +
> > +    def replay_pcap_file_on_tester(self, iface, packet_file_path):
> > +        self.tester.send_expect("scapy", ">>>")
> > +        self.scapy_exec(f"packets = rdpcap('{packet_file_path}')")
> > +        self.scapy_exec(f"sendp(packets, iface={iface})")
> > +        self.tester.send_expect("quit()", "# ")
> > +
> > +    def validate_packet_list_checksums(self, packets):
> > +        name_to_class_dict = {
> > +            'UDP': UDP,
> > +            'TCP': TCP,
> > +            'SCTP': SCTP,
> > +            'IP': IP,
> > +            'IPv6': IPv6,
> > +            'VXLAN': VXLAN,
> > +            'GRE': GRE,
> > +        }
> > +
> > +        error_messages = []
> > +
> > +        untunnelled_error_message = f"Invalid untunneled checksum state
> > for %s/%s with a %s checksum."
> > +
> > +        vxlan_error_message = f"Invalid VXLAN tunnelled %s checksum
> state
> > for %s/%s" \
> > +                              f" with a %s inner checksum and a %s
> outer checksum."
> > +
> > +        gre_error_message = f"Invalid GRE tunnelled checksum state for
> %s/%s
> > with a %s checksum."
> > +
> > +        for packet in packets:
> > +            payload: str
> > +            # try:
> > +            payload = packet[Raw].load.decode('utf-8').split(",")
> > +            # # This error usually happens with tunneling protocols,
> and means that
> > an additional cast is needed
> > +            # except UnicodeDecodeError:
> > +            #     for proto in tunnelling_proto_classes:
> > +
> > +            l3 = name_to_class_dict[payload[1]]
> > +            l4 = name_to_class_dict[payload[2]]
> > +            if payload[0] == "UNTUNNELED":
> > +                chksum_should_be_valid = payload[3] == " "
> > +                if self.validate_checksum(packet, l4) !=
> chksum_should_be_valid:
> > +                    error_messages.append(
> > +                        untunnelled_error_message % (
> > +                            l3.__name__, l4.__name__, 'valid' if
> chksum_should_be_valid
> > == '' else 'invalid'
> > +                        )
> > +                    )
> > +            elif payload[0] == "VXLAN":
> > +                outer_chksum_should_be_valid = payload[3] == " "
> > +                inner_chksum_should_be_valid = payload[4] == " "
> > +                if self.validate_checksum(packet[VXLAN], l4) !=
> > inner_chksum_should_be_valid:
> > +                    error_messages.append(
> > +                        vxlan_error_message % (
> > +                            "inner", l4.__name__, l3.__name__,
> > +                            'valid' if inner_chksum_should_be_valid ==
> '' else 'invalid',
> > +                            'valid' if outer_chksum_should_be_valid ==
> '' else 'invalid'
> > +                        )
> > +                    )
> > +                if self.validate_checksum(packet, l4) !=
> > outer_chksum_should_be_valid:
> > +                    error_messages.append(
> > +                        vxlan_error_message % (
> > +                            "outer", l3.__name__, l4.__name__,
> > +                            'valid' if inner_chksum_should_be_valid ==
> '' else 'invalid',
> > +                            'valid' if outer_chksum_should_be_valid ==
> '' else 'invalid'
> > +                        )
> > +                    )
> > +            elif payload[0] == "GRE":
> > +                chksum_should_be_valid = payload[3] == " "
> > +                if self.validate_checksum(packet, l4) !=
> chksum_should_be_valid:
> > +                    error_messages.append(
> > +                        gre_error_message % (
> > +                            l3.__name__, l4.__name__, 'valid' if
> chksum_should_be_valid
> > == '' else 'invalid'
> > +                        )
> > +                    )
> > +
> > +        return error_messages
> >
> >      #
> >      #
> > @@ -448,6 +618,9 @@ class TestChecksumOffload(TestCase):
> >
> >              # clear streams before add new streams
> >              self.tester.pktgen.clear_streams()
> > +            # create an instance to set stream field setting
> > +            # Moved here because it messes with the ability of the
> functional tests
> > to use scapy.
> > +            self.pktgen_helper = PacketGeneratorHelper()
> >              # run packet generator
> >              streams =
> self.pktgen_helper.prepare_stream_from_tginput(tgenInput,
> > 100,
> >                      None, self.tester.pktgen) @@ -511,53 +684,93 @@
> class
> > TestChecksumOffload(TestCase):
> >              self.dut.send_expect("quit", "#", 10)
> >              self.result_table_print()
> >
> > -    def test_hardware_checksum_check_ip(self):
> > +    def test_hardware_checksum_check_ip_rx(self):
> >          self.dut.send_expect("start", "testpmd>")
> > +        self.tester.send_expect("scapy", ">>>")
> >          self.checksum_enablehw(self.dut_ports[0])
> > +        self.dut.send_expect("start", "testpmd>")
> >
> >          verification_errors: List[VerifyFailure] = []
> >
> > -        # untunnelled
> > -        vf =
> > self.try_helper_hardware_checksum_check_catch_failure('Ether(dst="%s",
> > src="%s")/IP(%s)/UDP()/("X"*50)',
> > -
>  "PKT_RX_IP_CKSUM_")
> > -        if vf is not None:
> > -            verification_errors.append(vf)
> > +        iface =
> > self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))
> > +        dut_mac = self.dut.get_mac_address(self.dut_ports[0])
> > +        tester_mac =
> > + self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))
> >
> > -        # tunneled inner
> > -        vf = self.try_helper_hardware_checksum_check_catch_failure(
> > -            'Ether(dst="%s", src="%s")/IP()/UDP()/IP(%s)/("X"*50)',
> > -            "PKT_RX_OUTER_IP_CKSUM_")
> > -        if vf is not None:
> > -            verification_errors.append(vf)
> > +        self.scapy_exec(f"eth = Ether(dst='{dut_mac}',
> src='{tester_mac}')")
> > +        self.scapy_exec(f"iface = '{iface}'")
> >
> > -        # tunneled outer
> > -        vf = self.try_helper_hardware_checksum_check_catch_failure(
> > -            'Ether(dst="%s", src="%s")/IP()/UDP()/IP(%s)/("X"*50)',
> > -            "PKT_RX_OUTER_IP_CKSUM_")
> > -        if vf is not None:
> > -            verification_errors.append(vf)
> > +        # Untunnelled
> > +        for l4 in l4_protos:
> > +            for chksum in "", "chksum=0xf":
> > +                vf =
> self.send_pkt_expect_good_bad_from_flag_catch_failure(
> > +                    f"eth/IP({chksum})/{l4}()/(X'*50)",
> > +                    "PKT_RX_IP_CKSUM_", f"{l4}",
> > +                    should_pass=(chksum == ""))
> > +                if vf is not None:
> > +                    verification_errors.append(vf)
> >
> > -        self.verify(len(verification_errors) == 0,
> "\n".join(verification_errors))
> > +        for err in verification_errors:
> > +            self.logger.error(str(err))
> > +        self.verify(len(verification_errors) == 0, "See previous
> > + output")
> >
> > +        self.tester.send_expect("quit()", "# ")
> >          self.dut.send_expect("stop", "testpmd>")
> >
> > -    def test_hardware_checksum_check_l4(self):
> > +    def test_hardware_checksum_check_ip_tx(self):
> >          self.checksum_enablehw(self.dut_ports[0])
> >          self.dut.send_expect("start", "testpmd>")
> >
> >          verification_errors: List[VerifyFailure] = []
> >
> > -        l3_protos: List[str] = [
> > -            "IP",
> > -            "IPv6"
> > -        ]
> > +        iface =
> > self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))
> > +        dut_mac = self.dut.get_mac_address(self.dut_ports[0])
> > +        tester_mac =
> > self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))
> > +        eth = Ether(dst=dut_mac, src=tester_mac)
> >
> > -        l4_protos: List[str] = [
> > -            "UDP",
> > -            "TCP",
> > -            "SCTP",
> > +        checksum_options = ({}, {'chksum': 0xf},)
> > +
> > +        packets = [
> > +            eth / IP(**chksum) / TCP() / Raw(load=str(int(len(chksum)
> > + != 1))) for chksum in checksum_options
> >          ]
> >
> > +        capture_file_name =
> > "test_hardware_checksum_check_l3_tx_capture.pcap"
> > +
> > +        packet_file_path =
> > "/tmp/test_hardware_checksum_check_l3_tx_packets.pcap"
> > +        capture_file_path = "/tmp/tester/" + capture_file_name
> > +
> > +        self.tester.send_expect(f"tcpdump -i {iface} -s 65535 -w
> > + {capture_file_path} &", "# ")
> > +
> > +        wrpcap(packet_file_path, packets)
> > +        self.tester.session.copy_file_to(packet_file_path,
> > + packet_file_path)
> > +
> > +        self.replay_pcap_file_on_tester(iface, packet_file_path)
> > +
> > +        self.tester.session.copy_file_from(packet_file_path,
> > + "output/tmp/pcap/" + capture_file_name)
> > +
> > +        captured_packets = rdpcap("output/tmp/pcap/" +
> > + capture_file_name)
> > +
> > +        self.verify(len(packets) == len(captured_packets), "Not all
> > + packets were received")
> > +
> > +        error_messages = []
> > +        for pkt in captured_packets:
> > +            should_pass = pkt[TCP].payload.build() == b'1'
> > +            if not (self.validate_checksum(pkt, IP) == should_pass):
> > +                error_messages.append(f"A packet was marked as having a"
> > +                                      f"{' valid' if should_pass == ''
> else 'n invalid'}"
> > +                                      f" checksum when it should have
> > + had the opposite.")
> > +
> > +        self.dut.send_expect("stop", "testpmd>")
> > +        if len(error_messages) != 0:
> > +            for error_msg in error_messages:
> > +                self.logger.error(error_msg)
> > +            self.verify(False, "See prior output")
> > +
> > +    def test_hardware_checksum_check_l4_rx(self):
> > +        self.checksum_enablehw(self.dut_ports[0])
> > +        self.dut.send_expect("start", "testpmd>")
> > +
> > +        verification_errors: List[VerifyFailure] = []
> > +
> >          iface =
> > self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))
> >          dut_mac = self.dut.get_mac_address(self.dut_ports[0])
> >          tester_mac =
> > self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))
> > @@ -589,7 +802,7 @@ class TestChecksumOffload(TestCase):
> >                                  should_pass = outer_arg == ""
> >                              vf =
> self.send_pkt_expect_good_bad_from_flag_catch_failure(
> >
> f"eth/{l3}()/{l4}({outer_arg})/VXLAN()/{l3}()/"
> > -                                f"{l4}({inner_arg})/('X'*50)",
> > +                                f"{l4}(chksum={inner_arg})/('X'*50)",
> >                                  flag, f"{l3}/{l4}/VXLAN/{l3}/{l4}",
> >                                  should_pass=should_pass)
> >
> > @@ -602,8 +815,7 @@ class TestChecksumOffload(TestCase):
> >                  for inner_arg in "", "chksum=0xf":
> >                      should_pass: bool = inner_arg == ""
> >                      vf =
> self.send_pkt_expect_good_bad_from_flag_catch_failure(
> > -                        f"eth/{l3}()/GRE()/{l3}()/"
> > -                        f"{l4}({inner_arg})/('X'*50)",
> > +
> > + f"eth/{l3}()/GRE()/{l3}()/{l4}({inner_arg})/('X'*50)",
> >                          "PKT_RX_L4_CKSUM_", f"{l3}/GRE/{l3}/{l4}",
> >                          should_pass=should_pass)
> >
> > @@ -615,6 +827,8 @@ class TestChecksumOffload(TestCase):
> >          # updated this test case can easily take advantage of the new
> functionality.
> >
> >          # # GENEVE
> > +        # # This import is over here so that it is not forgotten when
> the update
> > happens
> > +        # from scapy.contrib.geneve import GENEVE
> >          # for l3_outer in l3_protos:
> >          #     for l4_outer in l4_protos:
> >          #         for l3_inner in l3_protos:
> > @@ -638,7 +852,46 @@ class TestChecksumOffload(TestCase):
> >              self.logger.error(str(err))
> >          self.verify(len(verification_errors) == 0, "See previous
> output")
> >
> > +        self.tester.send_expect("quit", "#")
> > +        self.dut.send_expect("stop", "testpmd>")
> > +
> > +    def test_hardware_checksum_check_l4_tx(self):
> > +        self.checksum_enablehw(self.dut_ports[0])
> > +        self.dut.send_expect("start", "testpmd>")
> > +
> > +        verification_errors: List[VerifyFailure] = []
> > +
> > +        iface =
> > self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))
> > +        dut_mac = self.dut.get_mac_address(self.dut_ports[0])
> > +        tester_mac =
> > + self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))
> > +
> > +        packets = self.get_packets(dut_mac, tester_mac)
> > +
> > +        capture_file_name =
> > "test_hardware_checksum_check_l4_tx_capture.pcap"
> > +
> > +        packet_file_path =
> > "/tmp/test_hardware_checksum_check_l4_tx_packets.pcap"
> > +        capture_file_path = "/tmp/tester/" + capture_file_name
> > +
> > +        self.tester.send_expect(f"tcpdump -i {iface} -s 65535 -w
> > + {capture_file_path} &", "# ")
> > +
> > +        wrpcap(packet_file_path, packets)
> > +        self.tester.session.copy_file_to(packet_file_path,
> > + packet_file_path)
> > +
> > +        self.replay_pcap_file_on_tester(iface, packet_file_path)
> > +
> > +        self.tester.session.copy_file_from(packet_file_path,
> > + "output/tmp/pcap/" + capture_file_name)
> > +
> > +        captured_packets = rdpcap("output/tmp/pcap/" +
> > + capture_file_name)
> > +
> > +        self.verify(len(packets) == len(captured_packets), "Not all
> > + packets were received")
> > +
> > +        error_messages =
> > + self.validate_packet_list_checksums(captured_packets)
> > +
> >          self.dut.send_expect("stop", "testpmd>")
> > +        if len(error_messages) != 0:
> > +            for error_msg in error_messages:
> > +                self.logger.error(error_msg)
> > +            self.verify(False, "See prior output")
> >
> >      def tear_down(self):
> >          """
> > --
> > 2.25.1
>
>

[-- Attachment #2: Type: text/html, Size: 37192 bytes --]

<div dir="ltr">Unfortunately I had to start a new email thread since intel&#39;s server didn&#39;t like the self-signed certificate on my local mail server. I merged all of the patches into one patch so it&#39;s a little easier to review for the second time. </div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Jul 23, 2020 at 10:45 PM Tu, Lijuan &lt;<a href="mailto:lijuan.tu@intel.com">lijuan.tu@intel.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Is the patch based on the latest DTS ? sorry, I can&#39;t merge it because of code conflict. Could you please rework it. Btw, all patches, v1/v2... should be based on latest DTS.<br>
<br>
Thanks, Lijuan.<br>
<br>
&gt; -----Original Message-----<br>
&gt; From: dts &lt;<a href="mailto:dts-bounces@dpdk.org" target="_blank">dts-bounces@dpdk.org</a>&gt; On Behalf Of Owen Hilyard<br>
&gt; Sent: 2020年7月20日 22:08<br>
&gt; To: <a href="mailto:dts@dpdk.org" target="_blank">dts@dpdk.org</a><br>
&gt; Cc: Yigit, Ferruh &lt;<a href="mailto:ferruh.yigit@intel.com" target="_blank">ferruh.yigit@intel.com</a>&gt;; <a href="mailto:arybchenko@solarflare.com" target="_blank">arybchenko@solarflare.com</a>;<br>
&gt; <a href="mailto:olivier.matz@6wind.com" target="_blank">olivier.matz@6wind.com</a>; <a href="mailto:david.marchand@redhat.com" target="_blank">david.marchand@redhat.com</a>;<br>
&gt; <a href="mailto:ivan.malov@oktetlabs.ru" target="_blank">ivan.malov@oktetlabs.ru</a>; Richardson, Bruce &lt;<a href="mailto:bruce.richardson@intel.com" target="_blank">bruce.richardson@intel.com</a>&gt;;<br>
&gt; <a href="mailto:lylavoie@iol.unh.edu" target="_blank">lylavoie@iol.unh.edu</a>; <a href="mailto:rasland@mellanox.com" target="_blank">rasland@mellanox.com</a>; <a href="mailto:j.hendergart@f5.com" target="_blank">j.hendergart@f5.com</a>;<br>
&gt; <a href="mailto:ohilyard@iol.unh.edu" target="_blank">ohilyard@iol.unh.edu</a>; <a href="mailto:thomas@monjalon.net" target="_blank">thomas@monjalon.net</a><br>
&gt; Subject: [dts] [PATCH] checksum checks: Add hardware offload l3 and l4 cases<br>
&gt; <br>
&gt; add rx and tx l3 test cases<br>
&gt; add tx l4 test case<br>
&gt; add documentation for new test cases<br>
&gt; <br>
&gt; Signed-off-by: Owen Hilyard &lt;<a href="mailto:ohilyard@iol.unh.edu" target="_blank">ohilyard@iol.unh.edu</a>&gt;<br>
&gt; ---<br>
&gt;  test_plans/checksum_offload_test_plan.rst | 122 +++++++-<br>
&gt;  tests/TestSuite_checksum_offload.py       | 331 +++++++++++++++++++---<br>
&gt;  2 files changed, 412 insertions(+), 41 deletions(-)<br>
&gt; <br>
&gt; diff --git a/test_plans/checksum_offload_test_plan.rst<br>
&gt; b/test_plans/checksum_offload_test_plan.rst<br>
&gt; index 4fd8c5a..de2e1a9 100644<br>
&gt; --- a/test_plans/checksum_offload_test_plan.rst<br>
&gt; +++ b/test_plans/checksum_offload_test_plan.rst<br>
&gt; @@ -221,7 +221,7 @@ combination: good/bad ip checksum + good/bad<br>
&gt; udp/tcp checksum.<br>
&gt; <br>
&gt;  Check the Rx checksum flags consistent with expected flags.<br>
&gt; <br>
&gt; -Test Case: Hardware Checksum Check L4<br>
&gt; +Test Case: Hardware Checksum Check L4 RX<br>
&gt;  ===========================================<br>
&gt;  This test involves testing many different scenarios with a L4 checksum.<br>
&gt;  A variety of tunneling protocols, L3 protocols and L4 protocols are combined<br>
&gt; @@ -256,4 +256,122 @@ Send a packet with a bad checksum::<br>
&gt;     rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8<br>
&gt; flags=PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_BAD<br>
&gt; PKT_RX_OUTER_L4_CKSUM_UNKNOWN<br>
&gt;     tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4<br>
&gt; <br>
&gt; -Verify flags are as expected.<br>
&gt; \ No newline at end of file<br>
&gt; +Verify flags are as expected.<br>
&gt; +<br>
&gt; +Test Case: Hardware Checksum Check L3 RX<br>
&gt; +===========================================<br>
&gt; +This test involves testing L3 checksum hardware offload.<br>
&gt; +Due to the relative dominance of IPv4 and IPv6 as L3 protocols, and<br>
&gt; +IPv6&#39;s lack of a checksum, only IPv4&#39;s checksum is tested.<br>
&gt; +<br>
&gt; +Setup the ``csum`` forwarding mode::<br>
&gt; +<br>
&gt; +  testpmd&gt; set fwd csum<br>
&gt; +  Set csum packet forwarding mode<br>
&gt; +<br>
&gt; +Start the packet forwarding::<br>
&gt; +<br>
&gt; +  testpmd&gt; start<br>
&gt; +    csum packet forwarding - CRC stripping disabled - packets/burst=32<br>
&gt; +    nb forwarding cores=1 - nb forwarding ports=10<br>
&gt; +    RX queues=1 - RX desc=128 - RX free threshold=64<br>
&gt; +    RX threshold registers: pthresh=8 hthresh=8 wthresh=4<br>
&gt; +    TX queues=1 - TX desc=512 - TX free threshold=0<br>
&gt; +    TX threshold registers: pthresh=32 hthresh=8 wthresh=8<br>
&gt; +<br>
&gt; +Send a packet with a good checksum::<br>
&gt; +<br>
&gt; +   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:<br>
&gt; +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8<br>
&gt; flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD<br>
&gt; PKT_RX_OUTER_L4_CKSUM_UNKNOWN<br>
&gt; +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4<br>
&gt; +<br>
&gt; +Send a packet with a bad checksum::<br>
&gt; +<br>
&gt; +   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:<br>
&gt; +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8<br>
&gt; flags=PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_BAD<br>
&gt; PKT_RX_OUTER_L4_CKSUM_UNKNOWN<br>
&gt; +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4<br>
&gt; +<br>
&gt; +Verify flags are as expected.<br>
&gt; +<br>
&gt; +Test Case: Hardware Checksum Check L4 TX<br>
&gt; +===========================================<br>
&gt; +This test involves testing many different scenarios with a L4 checksum.<br>
&gt; +A variety of tunneling protocols, L3 protocols and L4 protocols are<br>
&gt; +combined to test as many scenarios as possible. Currently, UDP, TCP and<br>
&gt; +SCTP are used as L4 protocols, with IP and IPv6 being used at level 3.<br>
&gt; +The tested tunneling protocols are VXLAN and GRE. This test is used to<br>
&gt; +determine whether the hardware offloading of checksums works properly.<br>
&gt; +<br>
&gt; +Setup the ``csum`` forwarding mode::<br>
&gt; +<br>
&gt; +  testpmd&gt; set fwd csum<br>
&gt; +  Set csum packet forwarding mode<br>
&gt; +<br>
&gt; +Start the packet forwarding::<br>
&gt; +<br>
&gt; +  testpmd&gt; start<br>
&gt; +    csum packet forwarding - CRC stripping disabled - packets/burst=32<br>
&gt; +    nb forwarding cores=1 - nb forwarding ports=10<br>
&gt; +    RX queues=1 - RX desc=128 - RX free threshold=64<br>
&gt; +    RX threshold registers: pthresh=8 hthresh=8 wthresh=4<br>
&gt; +    TX queues=1 - TX desc=512 - TX free threshold=0<br>
&gt; +    TX threshold registers: pthresh=32 hthresh=8 wthresh=8<br>
&gt; +<br>
&gt; +<br>
&gt; +Start a packet capture on the tester in the backround::<br>
&gt; +<br>
&gt; +   # tcpdump -i &lt;iface&gt; -s 65535 -w<br>
&gt; + /tmp/tester/test_hardware_checksum_check_l4_tx_capture.pcap &amp;<br>
&gt; +<br>
&gt; +Send a packet with a good checksum::<br>
&gt; +<br>
&gt; +   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:<br>
&gt; +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8<br>
&gt; flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD<br>
&gt; PKT_RX_OUTER_L4_CKSUM_UNKNOWN<br>
&gt; +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4<br>
&gt; +<br>
&gt; +Send a packet with a bad checksum::<br>
&gt; +<br>
&gt; +   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:<br>
&gt; +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8<br>
&gt; flags=PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_GOOD<br>
&gt; PKT_RX_OUTER_L4_CKSUM_UNKNOWN<br>
&gt; +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4<br>
&gt; +<br>
&gt; +Inspect the pcap file from the packet capture and verify the checksums.<br>
&gt; +<br>
&gt; +Test Case: Hardware Checksum Check L3 TX<br>
&gt; +===========================================<br>
&gt; +This test involves testing L3 checksum hardware offload.<br>
&gt; +Due to the relative dominance of IPv4 and IPv6 as L3 protocols, and<br>
&gt; +IPv6&#39;s lack of a checksum, only IPv4&#39;s checksum is tested.<br>
&gt; +<br>
&gt; +Setup the ``csum`` forwarding mode::<br>
&gt; +<br>
&gt; +  testpmd&gt; set fwd csum<br>
&gt; +  Set csum packet forwarding mode<br>
&gt; +<br>
&gt; +Start the packet forwarding::<br>
&gt; +<br>
&gt; +  testpmd&gt; start<br>
&gt; +    csum packet forwarding - CRC stripping disabled - packets/burst=32<br>
&gt; +    nb forwarding cores=1 - nb forwarding ports=10<br>
&gt; +    RX queues=1 - RX desc=128 - RX free threshold=64<br>
&gt; +    RX threshold registers: pthresh=8 hthresh=8 wthresh=4<br>
&gt; +    TX queues=1 - TX desc=512 - TX free threshold=0<br>
&gt; +    TX threshold registers: pthresh=32 hthresh=8 wthresh=8<br>
&gt; +<br>
&gt; +<br>
&gt; +Start a packet capture on the tester in the backround::<br>
&gt; +<br>
&gt; +   # tcpdump -i &lt;iface&gt; -s 65535 -w<br>
&gt; + /tmp/tester/test_hardware_checksum_check_l3_tx_capture.pcap &amp;<br>
&gt; +<br>
&gt; +Send a packet with a good checksum with a 1 in it&#39;s payload::<br>
&gt; +<br>
&gt; +   port=0, mbuf=0x2269df8780, pkt_len=96, nb_segs=1:<br>
&gt; +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8<br>
&gt; flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD<br>
&gt; PKT_RX_OUTER_L4_CKSUM_UNKNOWN<br>
&gt; +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4<br>
&gt; +<br>
&gt; +Send a packet with a bad checksum with a 0 in it&#39;s payload::<br>
&gt; +<br>
&gt; +   port=0, mbuf=0x2269df7e40, pkt_len=96, nb_segs=1:<br>
&gt; +   rx: l2_len=18 ethertype=800 l3_len=20 l4_proto=17 l4_len=8<br>
&gt; flags=PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_BAD<br>
&gt; PKT_RX_OUTER_L4_CKSUM_UNKNOWN<br>
&gt; +   tx: flags=PKT_TX_L4_NO_CKSUM PKT_TX_IPV4<br>
&gt; +<br>
&gt; +Inspect the pcap file from the packet capture and verify the checksums.<br>
&gt; diff --git a/tests/TestSuite_checksum_offload.py<br>
&gt; b/tests/TestSuite_checksum_offload.py<br>
&gt; index 9ff5a41..c4a877d 100644<br>
&gt; --- a/tests/TestSuite_checksum_offload.py<br>
&gt; +++ b/tests/TestSuite_checksum_offload.py<br>
&gt; @@ -47,8 +47,18 @@ import time<br>
&gt; <br>
&gt;  from rst import RstReport<br>
&gt;  import utils<br>
&gt; -<br>
&gt; +from exception import VerifyFailure<br>
&gt; +from pktgen import PacketGeneratorHelper from scapy.layers.inet import<br>
&gt; +UDP, TCP, IP from scapy.layers.inet6 import IPv6 from scapy.layers.l2<br>
&gt; +import Ether, GRE from scapy.layers.sctp import SCTP from<br>
&gt; +scapy.layers.vxlan import VXLAN from scapy.packet import Raw from<br>
&gt; +scapy.utils import wrpcap, rdpcap from test_capabilities import<br>
&gt; +DRIVER_TEST_LACK_CAPA<br>
&gt;  from test_case import TestCase<br>
&gt; +<br>
&gt;  from framework.pmd_output import PmdOutput  from test_capabilities import<br>
&gt; DRIVER_TEST_LACK_CAPA  from pktgen import PacketGeneratorHelper @@ -<br>
&gt; 57,6 +67,33 @@ import packet<br>
&gt; <br>
&gt;  from settings import FOLDERS<br>
&gt; <br>
&gt; +l3_proto_classes = [<br>
&gt; +    IP,<br>
&gt; +    IPv6<br>
&gt; +]<br>
&gt; +<br>
&gt; +l4_proto_classes = [<br>
&gt; +    UDP,<br>
&gt; +    TCP,<br>
&gt; +    SCTP<br>
&gt; +]<br>
&gt; +<br>
&gt; +tunnelling_proto_classes = [<br>
&gt; +    VXLAN,<br>
&gt; +    GRE,<br>
&gt; +]<br>
&gt; +<br>
&gt; +l3_protos = [<br>
&gt; +    &quot;IP&quot;,<br>
&gt; +    &quot;IPv6&quot;<br>
&gt; +]<br>
&gt; +<br>
&gt; +l4_protos = [<br>
&gt; +    &quot;UDP&quot;,<br>
&gt; +    &quot;TCP&quot;,<br>
&gt; +    &quot;SCTP&quot;,<br>
&gt; +]<br>
&gt; +<br>
&gt; <br>
&gt;  class TestChecksumOffload(TestCase):<br>
&gt; <br>
&gt; @@ -79,8 +116,6 @@ class TestChecksumOffload(TestCase):<br>
&gt;              cur_path = os.path.dirname(<br>
&gt;                  os.path.dirname(os.path.realpath(__file__)))<br>
&gt;              self.output_path = os.sep.join([cur_path, self.logger.log_path])<br>
&gt; -        # create an instance to set stream field setting<br>
&gt; -        self.pktgen_helper = PacketGeneratorHelper()<br>
&gt; <br>
&gt;      def set_up(self):<br>
&gt;          &quot;&quot;&quot;<br>
&gt; @@ -243,7 +278,6 @@ class TestChecksumOffload(TestCase):<br>
&gt;      def send_pkt_expect_good_bad_from_flag(self, pkt_str: str, flag: str,<br>
&gt; test_name: str, should_pass: bool = True):<br>
&gt;          self.pmdout.get_output(timeout=5)  # Remove any old output<br>
&gt;          self.scapy_exec(f&quot;sendp({pkt_str}, iface=iface)&quot;)<br>
&gt; -        time.sleep(1)<br>
&gt;          testpmd_output: str = self.pmdout.get_output(timeout=5)<br>
&gt;          self.verify(flag in testpmd_output,<br>
&gt;                      f&quot;Flag {flag[:-1]} not found for test {test_name}, please run<br>
&gt; test_rx_checksum_valid_flags.&quot;) @@ -269,11 +303,147 @@ class<br>
&gt; TestChecksumOffload(TestCase):<br>
&gt; <br>
&gt;          return None<br>
&gt; <br>
&gt; -    def scapy_exec(self, cmd: str):<br>
&gt; -        return self.tester.send_expect(cmd, &quot;&gt;&gt;&gt;&quot;)<br>
&gt; +    def validate_checksum(self, pkt, layer) -&gt; bool:<br>
&gt; +        &quot;&quot;&quot;<br>
&gt; +        @param pkt: The packet to validate the checksum of.<br>
&gt; +        @return: Whether the checksum was valid.<br>
&gt; +        &quot;&quot;&quot;<br>
&gt; +        if pkt is None:<br>
&gt; +            return False<br>
&gt; +<br>
&gt; +        csum = pkt[layer].chksum<br>
&gt; +        del pkt[layer].chksum<br>
&gt; +        # Converting it to raw will calculate the checksum<br>
&gt; +        return layer(Raw(pkt[layer])).chksum == csum<br>
&gt; <br>
&gt; -    def scapy_send_append(self, packet: str):<br>
&gt; -        return self.tester.scapy_append(f&#39;sendp({packet}, iface=iface)&#39;)<br>
&gt; +    def scapy_exec(self, cmd: str, timeout=1) -&gt; str:<br>
&gt; +        return self.tester.send_expect(cmd, &quot;&gt;&gt;&gt;&quot;, timeout=timeout)<br>
&gt; +<br>
&gt; +    def get_packets(self, dut_mac, tester_mac):<br>
&gt; +        eth = Ether(dst=dut_mac, src=tester_mac)<br>
&gt; +        packets = []<br>
&gt; +        checksum_options = ({}, {&#39;chksum&#39;: 0xf},)<br>
&gt; +        # Untunneled<br>
&gt; +        for l3 in l3_proto_classes:<br>
&gt; +            for l4 in l4_proto_classes:<br>
&gt; +                for chksum in checksum_options:<br>
&gt; +                    # The packet&#39;s data can be used to identify how the packet was<br>
&gt; constructed so avoid any issues with<br>
&gt; +                    # ordering<br>
&gt; +                    pkt = eth / l3() / l4(**chksum) / (<br>
&gt; +                        f&#39;UNTUNNELED,{l3.__name__},{l4.__name__},{&quot; &quot; if<br>
&gt; len(chksum.values()) == 0 else chksum[&quot;chksum&quot;]}&#39;<br>
&gt; +                    )<br>
&gt; +<br>
&gt; +                    # Prevents the default behavior which adds DNS headers<br>
&gt; +                    if l4 == UDP:<br>
&gt; +                        pkt[UDP].dport, pkt[UDP].sport = 1001, 1001<br>
&gt; +<br>
&gt; +                    packets.append(pkt)<br>
&gt; +<br>
&gt; +        # Tunneled<br>
&gt; +        # VXLAN<br>
&gt; +        for l3 in l3_proto_classes:<br>
&gt; +            for l4 in l4_proto_classes:<br>
&gt; +                for outer_arg in checksum_options:<br>
&gt; +                    for inner_arg in checksum_options:<br>
&gt; +                        pkt = eth / l3() / UDP(**outer_arg) / VXLAN() / Ether() / l3() /<br>
&gt; l4(**inner_arg) / (<br>
&gt; +                            f&#39;VXLAN,{l3.__name__},{l4.__name__},&#39;<br>
&gt; +                            f&#39;{&quot; &quot; if len(outer_arg.values()) == 0 else outer_arg[&quot;chksum&quot;]},&#39;<br>
&gt; +                            f&#39;{&quot; &quot; if len(inner_arg.values()) == 0 else inner_arg[&quot;chksum&quot;]}&#39;<br>
&gt; +                        )<br>
&gt; +                        # Prevents the default behavior which adds DNS headers<br>
&gt; +                        if l4 == UDP:<br>
&gt; +                            pkt[VXLAN][UDP].dport,<br>
&gt; + pkt[VXLAN][UDP].sport = 1001, 1001<br>
&gt; +<br>
&gt; +                        packets.append(pkt)<br>
&gt; +        # GRE<br>
&gt; +        for l3 in l3_proto_classes:<br>
&gt; +            for l4 in l4_proto_classes:<br>
&gt; +                for chksum in checksum_options:<br>
&gt; +                    pkt = eth / l3() / GRE() / l3() / l4(**chksum) / (<br>
&gt; +                        f&#39;GRE,{l3.__name__},{l4.__name__},{&quot; &quot; if len(chksum.values()) ==<br>
&gt; 0 else chksum[&quot;chksum&quot;]}&#39;<br>
&gt; +                    )<br>
&gt; +<br>
&gt; +                    # Prevents the default behavior which adds DNS headers<br>
&gt; +                    if l4 == UDP:<br>
&gt; +                        pkt[GRE][UDP].dport, pkt[GRE][UDP].sport =<br>
&gt; + 1001, 1001<br>
&gt; +<br>
&gt; +                    packets.append(pkt)<br>
&gt; +<br>
&gt; +        return packets<br>
&gt; +<br>
&gt; +    def replay_pcap_file_on_tester(self, iface, packet_file_path):<br>
&gt; +        self.tester.send_expect(&quot;scapy&quot;, &quot;&gt;&gt;&gt;&quot;)<br>
&gt; +        self.scapy_exec(f&quot;packets = rdpcap(&#39;{packet_file_path}&#39;)&quot;)<br>
&gt; +        self.scapy_exec(f&quot;sendp(packets, iface={iface})&quot;)<br>
&gt; +        self.tester.send_expect(&quot;quit()&quot;, &quot;# &quot;)<br>
&gt; +<br>
&gt; +    def validate_packet_list_checksums(self, packets):<br>
&gt; +        name_to_class_dict = {<br>
&gt; +            &#39;UDP&#39;: UDP,<br>
&gt; +            &#39;TCP&#39;: TCP,<br>
&gt; +            &#39;SCTP&#39;: SCTP,<br>
&gt; +            &#39;IP&#39;: IP,<br>
&gt; +            &#39;IPv6&#39;: IPv6,<br>
&gt; +            &#39;VXLAN&#39;: VXLAN,<br>
&gt; +            &#39;GRE&#39;: GRE,<br>
&gt; +        }<br>
&gt; +<br>
&gt; +        error_messages = []<br>
&gt; +<br>
&gt; +        untunnelled_error_message = f&quot;Invalid untunneled checksum state<br>
&gt; for %s/%s with a %s checksum.&quot;<br>
&gt; +<br>
&gt; +        vxlan_error_message = f&quot;Invalid VXLAN tunnelled %s checksum state<br>
&gt; for %s/%s&quot; \<br>
&gt; +                              f&quot; with a %s inner checksum and a %s outer checksum.&quot;<br>
&gt; +<br>
&gt; +        gre_error_message = f&quot;Invalid GRE tunnelled checksum state for %s/%s<br>
&gt; with a %s checksum.&quot;<br>
&gt; +<br>
&gt; +        for packet in packets:<br>
&gt; +            payload: str<br>
&gt; +            # try:<br>
&gt; +            payload = packet[Raw].load.decode(&#39;utf-8&#39;).split(&quot;,&quot;)<br>
&gt; +            # # This error usually happens with tunneling protocols, and means that<br>
&gt; an additional cast is needed<br>
&gt; +            # except UnicodeDecodeError:<br>
&gt; +            #     for proto in tunnelling_proto_classes:<br>
&gt; +<br>
&gt; +            l3 = name_to_class_dict[payload[1]]<br>
&gt; +            l4 = name_to_class_dict[payload[2]]<br>
&gt; +            if payload[0] == &quot;UNTUNNELED&quot;:<br>
&gt; +                chksum_should_be_valid = payload[3] == &quot; &quot;<br>
&gt; +                if self.validate_checksum(packet, l4) != chksum_should_be_valid:<br>
&gt; +                    error_messages.append(<br>
&gt; +                        untunnelled_error_message % (<br>
&gt; +                            l3.__name__, l4.__name__, &#39;valid&#39; if chksum_should_be_valid<br>
&gt; == &#39;&#39; else &#39;invalid&#39;<br>
&gt; +                        )<br>
&gt; +                    )<br>
&gt; +            elif payload[0] == &quot;VXLAN&quot;:<br>
&gt; +                outer_chksum_should_be_valid = payload[3] == &quot; &quot;<br>
&gt; +                inner_chksum_should_be_valid = payload[4] == &quot; &quot;<br>
&gt; +                if self.validate_checksum(packet[VXLAN], l4) !=<br>
&gt; inner_chksum_should_be_valid:<br>
&gt; +                    error_messages.append(<br>
&gt; +                        vxlan_error_message % (<br>
&gt; +                            &quot;inner&quot;, l4.__name__, l3.__name__,<br>
&gt; +                            &#39;valid&#39; if inner_chksum_should_be_valid == &#39;&#39; else &#39;invalid&#39;,<br>
&gt; +                            &#39;valid&#39; if outer_chksum_should_be_valid == &#39;&#39; else &#39;invalid&#39;<br>
&gt; +                        )<br>
&gt; +                    )<br>
&gt; +                if self.validate_checksum(packet, l4) !=<br>
&gt; outer_chksum_should_be_valid:<br>
&gt; +                    error_messages.append(<br>
&gt; +                        vxlan_error_message % (<br>
&gt; +                            &quot;outer&quot;, l3.__name__, l4.__name__,<br>
&gt; +                            &#39;valid&#39; if inner_chksum_should_be_valid == &#39;&#39; else &#39;invalid&#39;,<br>
&gt; +                            &#39;valid&#39; if outer_chksum_should_be_valid == &#39;&#39; else &#39;invalid&#39;<br>
&gt; +                        )<br>
&gt; +                    )<br>
&gt; +            elif payload[0] == &quot;GRE&quot;:<br>
&gt; +                chksum_should_be_valid = payload[3] == &quot; &quot;<br>
&gt; +                if self.validate_checksum(packet, l4) != chksum_should_be_valid:<br>
&gt; +                    error_messages.append(<br>
&gt; +                        gre_error_message % (<br>
&gt; +                            l3.__name__, l4.__name__, &#39;valid&#39; if chksum_should_be_valid<br>
&gt; == &#39;&#39; else &#39;invalid&#39;<br>
&gt; +                        )<br>
&gt; +                    )<br>
&gt; +<br>
&gt; +        return error_messages<br>
&gt; <br>
&gt;      #<br>
&gt;      #<br>
&gt; @@ -448,6 +618,9 @@ class TestChecksumOffload(TestCase):<br>
&gt; <br>
&gt;              # clear streams before add new streams<br>
&gt;              self.tester.pktgen.clear_streams()<br>
&gt; +            # create an instance to set stream field setting<br>
&gt; +            # Moved here because it messes with the ability of the functional tests<br>
&gt; to use scapy.<br>
&gt; +            self.pktgen_helper = PacketGeneratorHelper()<br>
&gt;              # run packet generator<br>
&gt;              streams = self.pktgen_helper.prepare_stream_from_tginput(tgenInput,<br>
&gt; 100,<br>
&gt;                      None, self.tester.pktgen) @@ -511,53 +684,93 @@ class<br>
&gt; TestChecksumOffload(TestCase):<br>
&gt;              self.dut.send_expect(&quot;quit&quot;, &quot;#&quot;, 10)<br>
&gt;              self.result_table_print()<br>
&gt; <br>
&gt; -    def test_hardware_checksum_check_ip(self):<br>
&gt; +    def test_hardware_checksum_check_ip_rx(self):<br>
&gt;          self.dut.send_expect(&quot;start&quot;, &quot;testpmd&gt;&quot;)<br>
&gt; +        self.tester.send_expect(&quot;scapy&quot;, &quot;&gt;&gt;&gt;&quot;)<br>
&gt;          self.checksum_enablehw(self.dut_ports[0])<br>
&gt; +        self.dut.send_expect(&quot;start&quot;, &quot;testpmd&gt;&quot;)<br>
&gt; <br>
&gt;          verification_errors: List[VerifyFailure] = []<br>
&gt; <br>
&gt; -        # untunnelled<br>
&gt; -        vf =<br>
&gt; self.try_helper_hardware_checksum_check_catch_failure(&#39;Ether(dst=&quot;%s&quot;,<br>
&gt; src=&quot;%s&quot;)/IP(%s)/UDP()/(&quot;X&quot;*50)&#39;,<br>
&gt; -                                                                   &quot;PKT_RX_IP_CKSUM_&quot;)<br>
&gt; -        if vf is not None:<br>
&gt; -            verification_errors.append(vf)<br>
&gt; +        iface =<br>
&gt; self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))<br>
&gt; +        dut_mac = self.dut.get_mac_address(self.dut_ports[0])<br>
&gt; +        tester_mac =<br>
&gt; + self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))<br>
&gt; <br>
&gt; -        # tunneled inner<br>
&gt; -        vf = self.try_helper_hardware_checksum_check_catch_failure(<br>
&gt; -            &#39;Ether(dst=&quot;%s&quot;, src=&quot;%s&quot;)/IP()/UDP()/IP(%s)/(&quot;X&quot;*50)&#39;,<br>
&gt; -            &quot;PKT_RX_OUTER_IP_CKSUM_&quot;)<br>
&gt; -        if vf is not None:<br>
&gt; -            verification_errors.append(vf)<br>
&gt; +        self.scapy_exec(f&quot;eth = Ether(dst=&#39;{dut_mac}&#39;, src=&#39;{tester_mac}&#39;)&quot;)<br>
&gt; +        self.scapy_exec(f&quot;iface = &#39;{iface}&#39;&quot;)<br>
&gt; <br>
&gt; -        # tunneled outer<br>
&gt; -        vf = self.try_helper_hardware_checksum_check_catch_failure(<br>
&gt; -            &#39;Ether(dst=&quot;%s&quot;, src=&quot;%s&quot;)/IP()/UDP()/IP(%s)/(&quot;X&quot;*50)&#39;,<br>
&gt; -            &quot;PKT_RX_OUTER_IP_CKSUM_&quot;)<br>
&gt; -        if vf is not None:<br>
&gt; -            verification_errors.append(vf)<br>
&gt; +        # Untunnelled<br>
&gt; +        for l4 in l4_protos:<br>
&gt; +            for chksum in &quot;&quot;, &quot;chksum=0xf&quot;:<br>
&gt; +                vf = self.send_pkt_expect_good_bad_from_flag_catch_failure(<br>
&gt; +                    f&quot;eth/IP({chksum})/{l4}()/(X&#39;*50)&quot;,<br>
&gt; +                    &quot;PKT_RX_IP_CKSUM_&quot;, f&quot;{l4}&quot;,<br>
&gt; +                    should_pass=(chksum == &quot;&quot;))<br>
&gt; +                if vf is not None:<br>
&gt; +                    verification_errors.append(vf)<br>
&gt; <br>
&gt; -        self.verify(len(verification_errors) == 0, &quot;\n&quot;.join(verification_errors))<br>
&gt; +        for err in verification_errors:<br>
&gt; +            self.logger.error(str(err))<br>
&gt; +        self.verify(len(verification_errors) == 0, &quot;See previous<br>
&gt; + output&quot;)<br>
&gt; <br>
&gt; +        self.tester.send_expect(&quot;quit()&quot;, &quot;# &quot;)<br>
&gt;          self.dut.send_expect(&quot;stop&quot;, &quot;testpmd&gt;&quot;)<br>
&gt; <br>
&gt; -    def test_hardware_checksum_check_l4(self):<br>
&gt; +    def test_hardware_checksum_check_ip_tx(self):<br>
&gt;          self.checksum_enablehw(self.dut_ports[0])<br>
&gt;          self.dut.send_expect(&quot;start&quot;, &quot;testpmd&gt;&quot;)<br>
&gt; <br>
&gt;          verification_errors: List[VerifyFailure] = []<br>
&gt; <br>
&gt; -        l3_protos: List[str] = [<br>
&gt; -            &quot;IP&quot;,<br>
&gt; -            &quot;IPv6&quot;<br>
&gt; -        ]<br>
&gt; +        iface =<br>
&gt; self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))<br>
&gt; +        dut_mac = self.dut.get_mac_address(self.dut_ports[0])<br>
&gt; +        tester_mac =<br>
&gt; self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))<br>
&gt; +        eth = Ether(dst=dut_mac, src=tester_mac)<br>
&gt; <br>
&gt; -        l4_protos: List[str] = [<br>
&gt; -            &quot;UDP&quot;,<br>
&gt; -            &quot;TCP&quot;,<br>
&gt; -            &quot;SCTP&quot;,<br>
&gt; +        checksum_options = ({}, {&#39;chksum&#39;: 0xf},)<br>
&gt; +<br>
&gt; +        packets = [<br>
&gt; +            eth / IP(**chksum) / TCP() / Raw(load=str(int(len(chksum)<br>
&gt; + != 1))) for chksum in checksum_options<br>
&gt;          ]<br>
&gt; <br>
&gt; +        capture_file_name =<br>
&gt; &quot;test_hardware_checksum_check_l3_tx_capture.pcap&quot;<br>
&gt; +<br>
&gt; +        packet_file_path =<br>
&gt; &quot;/tmp/test_hardware_checksum_check_l3_tx_packets.pcap&quot;<br>
&gt; +        capture_file_path = &quot;/tmp/tester/&quot; + capture_file_name<br>
&gt; +<br>
&gt; +        self.tester.send_expect(f&quot;tcpdump -i {iface} -s 65535 -w<br>
&gt; + {capture_file_path} &amp;&quot;, &quot;# &quot;)<br>
&gt; +<br>
&gt; +        wrpcap(packet_file_path, packets)<br>
&gt; +        self.tester.session.copy_file_to(packet_file_path,<br>
&gt; + packet_file_path)<br>
&gt; +<br>
&gt; +        self.replay_pcap_file_on_tester(iface, packet_file_path)<br>
&gt; +<br>
&gt; +        self.tester.session.copy_file_from(packet_file_path,<br>
&gt; + &quot;output/tmp/pcap/&quot; + capture_file_name)<br>
&gt; +<br>
&gt; +        captured_packets = rdpcap(&quot;output/tmp/pcap/&quot; +<br>
&gt; + capture_file_name)<br>
&gt; +<br>
&gt; +        self.verify(len(packets) == len(captured_packets), &quot;Not all<br>
&gt; + packets were received&quot;)<br>
&gt; +<br>
&gt; +        error_messages = []<br>
&gt; +        for pkt in captured_packets:<br>
&gt; +            should_pass = pkt[TCP].payload.build() == b&#39;1&#39;<br>
&gt; +            if not (self.validate_checksum(pkt, IP) == should_pass):<br>
&gt; +                error_messages.append(f&quot;A packet was marked as having a&quot;<br>
&gt; +                                      f&quot;{&#39; valid&#39; if should_pass == &#39;&#39; else &#39;n invalid&#39;}&quot;<br>
&gt; +                                      f&quot; checksum when it should have<br>
&gt; + had the opposite.&quot;)<br>
&gt; +<br>
&gt; +        self.dut.send_expect(&quot;stop&quot;, &quot;testpmd&gt;&quot;)<br>
&gt; +        if len(error_messages) != 0:<br>
&gt; +            for error_msg in error_messages:<br>
&gt; +                self.logger.error(error_msg)<br>
&gt; +            self.verify(False, &quot;See prior output&quot;)<br>
&gt; +<br>
&gt; +    def test_hardware_checksum_check_l4_rx(self):<br>
&gt; +        self.checksum_enablehw(self.dut_ports[0])<br>
&gt; +        self.dut.send_expect(&quot;start&quot;, &quot;testpmd&gt;&quot;)<br>
&gt; +<br>
&gt; +        verification_errors: List[VerifyFailure] = []<br>
&gt; +<br>
&gt;          iface =<br>
&gt; self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))<br>
&gt;          dut_mac = self.dut.get_mac_address(self.dut_ports[0])<br>
&gt;          tester_mac =<br>
&gt; self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))<br>
&gt; @@ -589,7 +802,7 @@ class TestChecksumOffload(TestCase):<br>
&gt;                                  should_pass = outer_arg == &quot;&quot;<br>
&gt;                              vf = self.send_pkt_expect_good_bad_from_flag_catch_failure(<br>
&gt;                                  f&quot;eth/{l3}()/{l4}({outer_arg})/VXLAN()/{l3}()/&quot;<br>
&gt; -                                f&quot;{l4}({inner_arg})/(&#39;X&#39;*50)&quot;,<br>
&gt; +                                f&quot;{l4}(chksum={inner_arg})/(&#39;X&#39;*50)&quot;,<br>
&gt;                                  flag, f&quot;{l3}/{l4}/VXLAN/{l3}/{l4}&quot;,<br>
&gt;                                  should_pass=should_pass)<br>
&gt; <br>
&gt; @@ -602,8 +815,7 @@ class TestChecksumOffload(TestCase):<br>
&gt;                  for inner_arg in &quot;&quot;, &quot;chksum=0xf&quot;:<br>
&gt;                      should_pass: bool = inner_arg == &quot;&quot;<br>
&gt;                      vf = self.send_pkt_expect_good_bad_from_flag_catch_failure(<br>
&gt; -                        f&quot;eth/{l3}()/GRE()/{l3}()/&quot;<br>
&gt; -                        f&quot;{l4}({inner_arg})/(&#39;X&#39;*50)&quot;,<br>
&gt; +<br>
&gt; + f&quot;eth/{l3}()/GRE()/{l3}()/{l4}({inner_arg})/(&#39;X&#39;*50)&quot;,<br>
&gt;                          &quot;PKT_RX_L4_CKSUM_&quot;, f&quot;{l3}/GRE/{l3}/{l4}&quot;,<br>
&gt;                          should_pass=should_pass)<br>
&gt; <br>
&gt; @@ -615,6 +827,8 @@ class TestChecksumOffload(TestCase):<br>
&gt;          # updated this test case can easily take advantage of the new functionality.<br>
&gt; <br>
&gt;          # # GENEVE<br>
&gt; +        # # This import is over here so that it is not forgotten when the update<br>
&gt; happens<br>
&gt; +        # from scapy.contrib.geneve import GENEVE<br>
&gt;          # for l3_outer in l3_protos:<br>
&gt;          #     for l4_outer in l4_protos:<br>
&gt;          #         for l3_inner in l3_protos:<br>
&gt; @@ -638,7 +852,46 @@ class TestChecksumOffload(TestCase):<br>
&gt;              self.logger.error(str(err))<br>
&gt;          self.verify(len(verification_errors) == 0, &quot;See previous output&quot;)<br>
&gt; <br>
&gt; +        self.tester.send_expect(&quot;quit&quot;, &quot;#&quot;)<br>
&gt; +        self.dut.send_expect(&quot;stop&quot;, &quot;testpmd&gt;&quot;)<br>
&gt; +<br>
&gt; +    def test_hardware_checksum_check_l4_tx(self):<br>
&gt; +        self.checksum_enablehw(self.dut_ports[0])<br>
&gt; +        self.dut.send_expect(&quot;start&quot;, &quot;testpmd&gt;&quot;)<br>
&gt; +<br>
&gt; +        verification_errors: List[VerifyFailure] = []<br>
&gt; +<br>
&gt; +        iface =<br>
&gt; self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0]))<br>
&gt; +        dut_mac = self.dut.get_mac_address(self.dut_ports[0])<br>
&gt; +        tester_mac =<br>
&gt; + self.tester.get_mac(self.tester.get_local_port(self.dut_ports[0]))<br>
&gt; +<br>
&gt; +        packets = self.get_packets(dut_mac, tester_mac)<br>
&gt; +<br>
&gt; +        capture_file_name =<br>
&gt; &quot;test_hardware_checksum_check_l4_tx_capture.pcap&quot;<br>
&gt; +<br>
&gt; +        packet_file_path =<br>
&gt; &quot;/tmp/test_hardware_checksum_check_l4_tx_packets.pcap&quot;<br>
&gt; +        capture_file_path = &quot;/tmp/tester/&quot; + capture_file_name<br>
&gt; +<br>
&gt; +        self.tester.send_expect(f&quot;tcpdump -i {iface} -s 65535 -w<br>
&gt; + {capture_file_path} &amp;&quot;, &quot;# &quot;)<br>
&gt; +<br>
&gt; +        wrpcap(packet_file_path, packets)<br>
&gt; +        self.tester.session.copy_file_to(packet_file_path,<br>
&gt; + packet_file_path)<br>
&gt; +<br>
&gt; +        self.replay_pcap_file_on_tester(iface, packet_file_path)<br>
&gt; +<br>
&gt; +        self.tester.session.copy_file_from(packet_file_path,<br>
&gt; + &quot;output/tmp/pcap/&quot; + capture_file_name)<br>
&gt; +<br>
&gt; +        captured_packets = rdpcap(&quot;output/tmp/pcap/&quot; +<br>
&gt; + capture_file_name)<br>
&gt; +<br>
&gt; +        self.verify(len(packets) == len(captured_packets), &quot;Not all<br>
&gt; + packets were received&quot;)<br>
&gt; +<br>
&gt; +        error_messages =<br>
&gt; + self.validate_packet_list_checksums(captured_packets)<br>
&gt; +<br>
&gt;          self.dut.send_expect(&quot;stop&quot;, &quot;testpmd&gt;&quot;)<br>
&gt; +        if len(error_messages) != 0:<br>
&gt; +            for error_msg in error_messages:<br>
&gt; +                self.logger.error(error_msg)<br>
&gt; +            self.verify(False, &quot;See prior output&quot;)<br>
&gt; <br>
&gt;      def tear_down(self):<br>
&gt;          &quot;&quot;&quot;<br>
&gt; --<br>
&gt; 2.25.1<br>
<br>
</blockquote></div>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [dts] [PATCH] checksum hardware checks: fix typo
  2020-07-20 14:13   ` [dts] [PATCH] checksum hardware checks: fix typo Owen Hilyard
@ 2020-08-12  1:53     ` Ma, LihongX
  0 siblings, 0 replies; 6+ messages in thread
From: Ma, LihongX @ 2020-08-12  1:53 UTC (permalink / raw)
  To: Owen Hilyard, dts
  Cc: Yigit, Ferruh, arybchenko, olivier.matz, david.marchand,
	ivan.malov, Richardson, Bruce, lylavoie, rasland, j.hendergart,
	thomas

Acked-by: lihongx.ma <lihongx.ma@intel.com>

Regards,
Ma,lihong

-----Original Message-----
From: dts <dts-bounces@dpdk.org> On Behalf Of Owen Hilyard
Sent: Monday, July 20, 2020 10:14 PM
To: dts@dpdk.org
Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; arybchenko@solarflare.com; olivier.matz@6wind.com; david.marchand@redhat.com; ivan.malov@oktetlabs.ru; Richardson, Bruce <bruce.richardson@intel.com>; lylavoie@iol.unh.edu; rasland@mellanox.com; j.hendergart@f5.com; ohilyard@iol.unh.edu; thomas@monjalon.net
Subject: [dts] [PATCH] checksum hardware checks: fix typo

fixed typo

Signed-off-by: Owen Hilyard <ohilyard@iol.unh.edu>
---
 test_plans/checksum_offload_test_plan.rst | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, back to index

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-14 14:53 [dts] [PATCH] checksum offload: add hardware checksum checks case Owen Hilyard
2020-07-20 14:07 ` [dts] [PATCH] checksum checks: Add hardware offload l3 and l4 cases Owen Hilyard
2020-07-20 14:13   ` [dts] [PATCH] checksum hardware checks: fix typo Owen Hilyard
2020-08-12  1:53     ` Ma, LihongX
2020-07-24  2:45   ` [dts] [PATCH] checksum checks: Add hardware offload l3 and l4 cases Tu, Lijuan
2020-07-24 12:43     ` Owen Hilyard

test suite reviews and discussions

Archives are clonable:
	git clone --mirror http://inbox.dpdk.org/dts/0 dts/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dts dts/ http://inbox.dpdk.org/dts \
		dts@dpdk.org
	public-inbox-index dts


Newsgroup available over NNTP:
	nntp://inbox.dpdk.org/inbox.dpdk.dts


AGPL code for this site: git clone https://public-inbox.org/ public-inbox