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