From patchwork Tue Nov 24 02:35:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Chen, BoX C" X-Patchwork-Id: 84481 Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id D9265A04B1; Tue, 24 Nov 2020 03:37:23 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 8BA41C914; Tue, 24 Nov 2020 03:37:22 +0100 (CET) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id 0D9A1C8FA for ; Tue, 24 Nov 2020 03:37:20 +0100 (CET) IronPort-SDR: poRimItyjeE6gGK3uqLhVXS2asFVLYSfwy7cz0mg4ufmFBcaGOxPx/G85LgR7Bwl76aJKgiM1L PzRkYWKatMxw== X-IronPort-AV: E=McAfee;i="6000,8403,9814"; a="159648467" X-IronPort-AV: E=Sophos;i="5.78,364,1599548400"; d="scan'208";a="159648467" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Nov 2020 18:37:18 -0800 IronPort-SDR: eGPMUJ5HBHfGTu6//nAfXmSfIUwI2YymjqnHHOLnUTHkZ0OXaGaUViHGeGrmrauqHaH83zs4GR 406mAVqX3f/g== X-IronPort-AV: E=Sophos;i="5.78,364,1599548400"; d="scan'208";a="312405253" Received: from unknown (HELO cb-dts.sh.intel.com) ([10.240.183.58]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Nov 2020 18:37:15 -0800 From: ChenBo To: dts@dpdk.org Cc: ohilyard@iol.unh.edu, ChenBo Date: Tue, 24 Nov 2020 10:35:51 +0800 Message-Id: <20201124023551.12624-1-box.c.chen@intel.com> X-Mailer: git-send-email 2.17.1 Subject: [dts] [PATCH V1] tests/checksum_offload: rework l4 tx/rx test case X-BeenThere: dts@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: test suite reviews and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dts-bounces@dpdk.org Sender: "dts" 1. Fix incorrect payload of SCTP package. 2. Fix vxlan package errors. 3. Support for adding FVL network card. 4. Improve contracting efficiency and add debugging information. Signed-off-by: ChenBo --- conf/test_case_supportlist.json | 6 + tests/TestSuite_checksum_offload.py | 187 +++++++++++++--------------- 2 files changed, 92 insertions(+), 101 deletions(-) diff --git a/conf/test_case_supportlist.json b/conf/test_case_supportlist.json index 34f2303..f976248 100644 --- a/conf/test_case_supportlist.json +++ b/conf/test_case_supportlist.json @@ -2260,6 +2260,9 @@ "ALL" ], "NIC": [ + "fortville_eagle", + "fortville_25g", + "fortville_spirit", "columbiaville_100g", "columbiaville_25g" ], @@ -2276,6 +2279,9 @@ "ALL" ], "NIC": [ + "fortville_eagle", + "fortville_25g", + "fortville_spirit", "columbiaville_100g", "columbiaville_25g" ], diff --git a/tests/TestSuite_checksum_offload.py b/tests/TestSuite_checksum_offload.py index 89abf04..afdeb46 100644 --- a/tests/TestSuite_checksum_offload.py +++ b/tests/TestSuite_checksum_offload.py @@ -116,6 +116,7 @@ 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]) + self.count = 0 def set_up(self): """ @@ -277,9 +278,9 @@ class TestChecksumOffload(TestCase): return self.checksum_flags_are_good("PKT_RX_IP_CKSUM_", testpmd_output) 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.pmdout.get_output(timeout=1) # Remove any old output self.scapy_exec(f"sendp({pkt_str}, iface=iface)") - testpmd_output: str = self.pmdout.get_output(timeout=5) + testpmd_output: str = self.pmdout.get_output(timeout=1) 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, @@ -304,18 +305,37 @@ class TestChecksumOffload(TestCase): return None - def validate_checksum(self, pkt, layer) -> bool: + def validate_checksum(self, pkt, pkt_type, inner_flag=False) -> 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(bytes(Raw(pkt[layer]))).chksum == csum + for i in range(0, len(l3_protos)): + if l3_protos[i] in pkt: + l3 = l3_protos[i] + for j in range(0, len(l4_protos)): + if l4_protos[j] in pkt: + layer = l4_proto_classes[j] + csum = pkt[layer].chksum + if csum is None: + csum = 0 + del pkt[layer].chksum + # Converting it to raw will calculate the checksum + correct_csum = layer(bytes(Raw(pkt[layer]))).chksum + if correct_csum == csum: + # checksum value is correct + return False + else: + if inner_flag: + print("{} pkg[{}] VXLAN/{}/{} inner checksum {} is not correct {}".format( + pkt_type, self.count, l3, l4_protos[j], hex(correct_csum), hex(csum))) + else: + print("{} pkg[{}] {}/{} outer checksum {} is not correct {}".format( + pkt_type, self.count, l3, l4_protos[j], hex(correct_csum), hex(csum))) + return True + return False def scapy_exec(self, cmd: str, timeout=1) -> str: return self.tester.send_expect(cmd, ">>>", timeout=timeout) @@ -330,14 +350,10 @@ class TestChecksumOffload(TestCase): 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"]}' - ) - + pkt = eth / l3() / l4(**chksum) / (b'X' * 48) # Prevents the default behavior which adds DNS headers if l4 == UDP: pkt[UDP].dport, pkt[UDP].sport = 1001, 1001 - packets.append(pkt) # Tunneled @@ -346,104 +362,55 @@ class TestChecksumOffload(TestCase): 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"]}' - ) + pkt = eth / l3() / UDP(**outer_arg) / VXLAN() / Ether() / l3() / l4(**inner_arg) / (b'Y' * 48) # 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"]}' - ) - + pkt = eth / l3() / GRE() / l3() / l4(**chksum) / (b'Z' * 48) # 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 replay_pcap_file_on_tester(self, iface, offset, packet_file_path): + self.scapy_exec(f"packets[{offset}].show") + self.scapy_exec(f"sendp(packets[{offset}], iface='{iface}')") 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." + untunnelled_error_message = f"un-tunneled checksum state for pkg[%s] with a invalid checksum." + vxlan_error_message = f"VXLAN tunnelled checksum state for pkg[%s] with a invalid checksum." + gre_error_message = f"GRE tunnelled checksum state for pkg[%s] with a invalid checksum." for packet in packets: + self.count = self.count + 1 payload: str # try: - payload = packet[Raw].load.decode('utf-8').split(",") + payload = packet[Raw].load.decode('utf-8') # # 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' - ) - ) - + if 'X' in payload: + if self.validate_checksum(packet, 'un-tunneled'): + error_messages.append(untunnelled_error_message % self.count) + elif 'Y' in payload: + if self.validate_checksum(packet[VXLAN][Ether], 'VXLAN', inner_flag=True): + error_messages.append(vxlan_error_message % self.count) + # fortville not support outer udp checksum + if 'fortville' in self.nic: + continue + if self.validate_checksum(packet, 'VXLAN'): + error_messages.append(vxlan_error_message % self.count) + elif 'Z' in payload: + if self.validate_checksum(packet, 'GRE'): + error_messages.append(gre_error_message % self.count) return error_messages # @@ -783,7 +750,7 @@ class TestChecksumOffload(TestCase): 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)", + f"eth/{l3}()/{l4}({chksum})/('X'*48)", "PKT_RX_L4_CKSUM_", f"{l3}/{l4}", should_pass=(chksum == "")) if vf is not None: @@ -791,20 +758,22 @@ class TestChecksumOffload(TestCase): # Tunneled # VXLAN - VXLAN_l4_protos=['UDP'] for l3 in l3_protos: - for l4 in VXLAN_l4_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_ + # fortville not support outer checksum + if 'fortville' in self.nic: + continue should_pass = outer_arg == "" vf = self.send_pkt_expect_good_bad_from_flag_catch_failure( - f"eth/{l3}()/{l4}(dport=4789,{outer_arg})/VXLAN()/eth/{l3}()/" - f"{l4}({inner_arg})/('X'*50)", - flag, f"{l3}/{l4}/VXLAN/{l3}/{l4}", + f"eth/{l3}()/UDP(dport=4789,{outer_arg})/VXLAN()/eth/{l3}()/" + f"{l4}({inner_arg})/('X'*48)", + flag, f"{l3}/UDP/VXLAN/{l3}/{l4}", should_pass=should_pass) if vf is not None: @@ -816,7 +785,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}()/{l4}({inner_arg})/('X'*50)", + f"eth/{l3}()/GRE()/{l3}()/{l4}({inner_arg})/('X'*48)", "PKT_RX_L4_CKSUM_", f"{l3}/GRE/{l3}/{l4}", should_pass=should_pass) @@ -854,7 +823,6 @@ class TestChecksumOffload(TestCase): self.logger.error(str(err)) self.verify(len(verification_errors) == 0, "See previous output") - def test_hardware_checksum_check_l4_tx(self): self.checksum_enablehw(self.dut_ports[0]) self.dut.send_expect("start", "testpmd>") @@ -872,24 +840,41 @@ class TestChecksumOffload(TestCase): 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} &", "# ") - + if os.path.isfile(packet_file_path): + os.remove(packet_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) + if os.path.isfile(capture_file_path): + os.remove(capture_file_path) + self.tester.send_expect(f"tcpdump -i '{iface}' ether src {dut_mac} -s 0 -w {capture_file_path} &", "# ") - self.tester.session.copy_file_from(packet_file_path, "output/tmp/pcap/" + capture_file_name) + # send packet + self.tester.send_expect("scapy", ">>>") + self.scapy_exec(f"packets = rdpcap('{packet_file_path}')") + for i in range(0, len(packets)): + self.replay_pcap_file_on_tester(iface, i, packet_file_path) + self.pmdout.get_output(timeout=0.5) + self.dut.send_expect("show port stats {}".format(self.dut_ports[0]), "testpmd>") + self.tester.send_expect("quit()", "# ") + + time.sleep(1) + self.tester.send_expect('killall tcpdump', '#') + time.sleep(1) + self.tester.send_expect('echo "Cleaning buffer"', '#') + time.sleep(1) + + self.tester.session.copy_file_from(capture_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.tester.send_expect("quit", "#") self.dut.send_expect("stop", "testpmd>") + self.count = 0 + error_messages = self.validate_packet_list_checksums(captured_packets) + if len(error_messages) != 0: for error_msg in error_messages: self.logger.error(error_msg)