From patchwork Tue Nov 8 15:06:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yogesh Jangra X-Patchwork-Id: 119557 Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 3F3EEA00C2; Tue, 8 Nov 2022 16:16:40 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 3B62142D3A; Tue, 8 Nov 2022 16:16:40 +0100 (CET) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mails.dpdk.org (Postfix) with ESMTP id 52741400D4 for ; Tue, 8 Nov 2022 16:16:38 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1667920598; x=1699456598; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=E7wtUzgRgUpGQH+85y2YJqVgtR6EyYQg2v/hsgBqVp4=; b=hXgRNBc0xV/yQzxd/yTWUv1bVaXd+jIyHR82CIyG/Y88MXdFW09NmGUn go1EIhqIAlDN6jqM8Sl5WiY7rEILFczSgTi4+A1xWngf6e51dGHK/qLZs /PrZHA5vuyo2qFRzzwxn3aXrvJSdIXJCVrfgdE1g0+qOnHHBghS4RG0D0 DTaujaZe6dNlquKEPYQy2ItIAStgfBC2CUvIx+MoAG8FsBOZhuNxY5H0c ssIPqZEVKRLekwWcZTdivUUEVXmznVij95jbyltsmepqGAIl4ASaTuDbx gDhoKOHqrHax4ZTrm7tDnaloHYtqPlJHH84COWf8w94IHIw/3vMvtvYHl Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10525"; a="310715331" X-IronPort-AV: E=Sophos;i="5.96,148,1665471600"; d="scan'208,223";a="310715331" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Nov 2022 07:06:51 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10525"; a="638816605" X-IronPort-AV: E=Sophos;i="5.96,148,1665471600"; d="scan'208,223";a="638816605" Received: from ena3-s2600wft.iind.intel.com ([10.235.221.73]) by fmsmga007.fm.intel.com with ESMTP; 08 Nov 2022 07:06:49 -0800 From: Yogesh Jangra To: dts@dpdk.org Cc: cristian.dumitrescu@intel.com, kamalakannan.r@intel.com, harshad.suresh.narayane@intel.com Subject: [PATCH 3/3] test/softnic: updated softnic test suite as per dpdk 22.11 changes Date: Tue, 8 Nov 2022 20:36:36 +0530 Message-Id: <20221108150636.2459852-4-yogesh.jangra@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221108150636.2459852-1-yogesh.jangra@intel.com> References: <20221108150636.2459852-1-yogesh.jangra@intel.com> MIME-Version: 1.0 X-BeenThere: dts@dpdk.org X-Mailman-Version: 2.1.29 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 From dpdk 22.11 release, Soft NIC driver has started to use rte_swx_pipeline_xxx library. This changes the CLI format of the Soft NIC. To accomodate those changes, updating the test suite. Signed-off-by: Yogesh Jangra --- dep/softnic/rx_tx/pcap_files/in.txt | 12 + dep/softnic/rx_tx/pcap_files/out.txt | 12 + dep/softnic/rx_tx/readme.txt | 8 + dep/softnic/rx_tx/rx_tx.cli | 21 ++ dep/softnic/rx_tx/rx_tx.spec | 19 ++ dep/softnic/rx_tx/rx_tx_1.io | 30 ++ dep/softnic/rx_tx/rx_tx_2.io | 30 ++ test_plans/softnic_test_plan.rst | 137 ++++----- tests/TestSuite_softnic.py | 414 ++++++++++++++------------- 9 files changed, 416 insertions(+), 267 deletions(-) create mode 100644 dep/softnic/rx_tx/pcap_files/in.txt create mode 100644 dep/softnic/rx_tx/pcap_files/out.txt create mode 100644 dep/softnic/rx_tx/readme.txt create mode 100644 dep/softnic/rx_tx/rx_tx.cli create mode 100644 dep/softnic/rx_tx/rx_tx.spec create mode 100644 dep/softnic/rx_tx/rx_tx_1.io create mode 100644 dep/softnic/rx_tx/rx_tx_2.io diff --git a/dep/softnic/rx_tx/pcap_files/in.txt b/dep/softnic/rx_tx/pcap_files/in.txt new file mode 100644 index 00000000..9b37ef2e --- /dev/null +++ b/dep/softnic/rx_tx/pcap_files/in.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2022 Intel Corporation +# + +# text to pcap: text2pcap packet.txt packet.pcap +# pcap to text: tcpdump -r packet.pcap -xx + +# Packet 0 +000000 00 11 22 33 44 55 00 66 77 88 99 aa 08 00 45 00 +000010 00 2e 00 01 00 00 40 06 4e b5 64 00 00 0a c8 00 +000020 00 0a 00 64 00 c8 00 00 00 00 00 00 00 00 50 02 +000030 20 00 59 93 00 00 58 58 58 58 58 58 \ No newline at end of file diff --git a/dep/softnic/rx_tx/pcap_files/out.txt b/dep/softnic/rx_tx/pcap_files/out.txt new file mode 100644 index 00000000..9b37ef2e --- /dev/null +++ b/dep/softnic/rx_tx/pcap_files/out.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2022 Intel Corporation +# + +# text to pcap: text2pcap packet.txt packet.pcap +# pcap to text: tcpdump -r packet.pcap -xx + +# Packet 0 +000000 00 11 22 33 44 55 00 66 77 88 99 aa 08 00 45 00 +000010 00 2e 00 01 00 00 40 06 4e b5 64 00 00 0a c8 00 +000020 00 0a 00 64 00 c8 00 00 00 00 00 00 00 00 50 02 +000030 20 00 59 93 00 00 58 58 58 58 58 58 \ No newline at end of file diff --git a/dep/softnic/rx_tx/readme.txt b/dep/softnic/rx_tx/readme.txt new file mode 100644 index 00000000..906bb615 --- /dev/null +++ b/dep/softnic/rx_tx/readme.txt @@ -0,0 +1,8 @@ +Test Case: rx_tx +----------------------- +Description: + This test is to verify packet transmission by the Soft NIC driver. In this test we have two pipeline connected using ring + port. First pipeline takes packet from physical port and put the packet in ring port. And second pipeline takes packet + from ring port and send the packet out to the physical port. +Verification: + The received packets should be same as the transmitted packets. diff --git a/dep/softnic/rx_tx/rx_tx.cli b/dep/softnic/rx_tx/rx_tx.cli new file mode 100644 index 00000000..cbc0c58a --- /dev/null +++ b/dep/softnic/rx_tx/rx_tx.cli @@ -0,0 +1,21 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2022 Intel Corporation + +; +; Pipeline code generation & shared object library build. +; +pipeline codegen /tmp/softnic/rx_tx/rx_tx.spec /tmp/firmware.c +pipeline libbuild /tmp/firmware.c /tmp/firmware.so + +; +; List of pipelines. +; +pipeline RX build lib /tmp/firmware.so io /tmp/softnic/rx_tx/rx_tx_1.io numa 0 +pipeline TX build lib /tmp/firmware.so io /tmp/softnic/rx_tx/rx_tx_2.io numa 0 + +; +; Pipelines-to-threads mapping. For the Soft NIC devices, the pipelines can be mapped to any of the +; application service cores (see the -s argument): +; +thread 2 pipeline RX enable +thread 2 pipeline TX enable \ No newline at end of file diff --git a/dep/softnic/rx_tx/rx_tx.spec b/dep/softnic/rx_tx/rx_tx.spec new file mode 100644 index 00000000..106caae7 --- /dev/null +++ b/dep/softnic/rx_tx/rx_tx.spec @@ -0,0 +1,19 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2022 Intel Corporation + +// +// Meta-data. +// +struct metadata_t { + bit<32> port +} + +metadata instanceof metadata_t + +// +// Pipeline. +// +apply { + rx m.port + tx m.port +} diff --git a/dep/softnic/rx_tx/rx_tx_1.io b/dep/softnic/rx_tx/rx_tx_1.io new file mode 100644 index 00000000..731f672c --- /dev/null +++ b/dep/softnic/rx_tx/rx_tx_1.io @@ -0,0 +1,30 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2022 Intel Corporation + +; +; Pipeline input ports. +; +; Syntax: +; +; port in ethdev rxq bsz +; port in ring bsz +; port in source mempool file loop packets +; port in fd mtu mempool bsz +; +; Note: Customize the parameters below to match your setup. +; +port in 0 ethdev 0000:af:00.1 rxq 0 bsz 32 + +; +; Pipeline output ports. +; +; Syntax: +; +; port out ethdev txq bsz +; port out ring bsz +; port out sink file | none +; port out fd bsz +; +; Note: Customize the parameters below to match your setup. +; +port out 0 ring RXQ0 bsz 32 diff --git a/dep/softnic/rx_tx/rx_tx_2.io b/dep/softnic/rx_tx/rx_tx_2.io new file mode 100644 index 00000000..d8c9ccbd --- /dev/null +++ b/dep/softnic/rx_tx/rx_tx_2.io @@ -0,0 +1,30 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2022 Intel Corporation + +; +; Pipeline input ports. +; +; Syntax: +; +; port in ethdev rxq bsz +; port in ring bsz +; port in source mempool file loop packets +; port in fd mtu mempool bsz +; +; Note: Customize the parameters below to match your setup. +; +port in 0 ring TXQ0 bsz 32 + +; +; Pipeline output ports. +; +; Syntax: +; +; port out ethdev txq bsz +; port out ring bsz +; port out sink file | none +; port out fd bsz +; +; Note: Customize the parameters below to match your setup. +; +port out 0 ethdev 0000:af:00.1 txq 0 bsz 32 diff --git a/test_plans/softnic_test_plan.rst b/test_plans/softnic_test_plan.rst index 84d34f63..a6f8348a 100644 --- a/test_plans/softnic_test_plan.rst +++ b/test_plans/softnic_test_plan.rst @@ -12,95 +12,84 @@ is configurable through firmware (DPDK Packet Framework script). Prerequisites ============= -1. The DUT must have one 10G Ethernet port connected to a port on tester - that are controlled by the traffic generator:: +The DUT must have atleast one 10G Ethernet ports connected to one port on +Tester.:: dut_port_0 <---> tester_port_0 - Assume the DUT 10G Ethernet port's pci device id is as the following:: +Assume DUT 10G Ethernet ports' pci device id is as the following:: - dut_port_0 : "0000:05:00.0" + dut_port_0 : "0000:af:00.1" - Bind it to dpdk igb_uio driver:: +Bind them to dpdk vfio-pci driver:: - ./usertools/dpdk-devbind.py -b igb_uio 05:00.0 + ./usertools/dpdk-devbind.py -b vfio-pci 0000:af:00.1 -2. Change ./drivers/net/softnic/firmware.cli to meet the specific test environment. - Change the DUT port info to the actual port info in your test environment:: - - link LINK dev 0000:05:00.0 - -3. Start softnic with following command line:: - - ./x86_64-native-linuxapp-gcc/app/dpdk-testpmd -c 0x7 -s 0x4 -n 4 \ - --vdev 'net_softnic0,firmware=./drivers/net/softnic/firmware.cli,cpu_id=1,conn_port=8086' \ - -- -i --forward-mode=softnic --portmask=0x2 - testpmd> start - - Set the thread id consistent to the service core:: - - thread 2 pipeline PIPELINE0 enable - -Test Case 1: softnic performance -================================ -1. Start softnic:: - - ./x86_64-native-linuxapp-gcc/app/dpdk-testpmd -c 0x7 -s 0x4 -n 4 \ - --vdev 'net_softnic0,firmware=./drivers/net/softnic/firmware.cli,cpu_id=1,conn_port=8086' \ - -- -i --forward-mode=softnic --portmask=0x2 - testpmd> start - -2. Send packet at line rate from traffic generator (IXIA or other) with packet size from 64~1518B. -3. Check performance number is same as the physical NIC's performance number, no performance drop. - -Test Case 2: shaping for pipe -============================= -1. The specifications of the default Hierarchical Scheduler are as follows: - - Root node (x1, level 0) - Subport node (x1, level 1) - Pipe node (x4096, level 2) - Traffic Class node (x16348, level 3) - Queue node (x65536, level 4) - -2. Start softnic with the default hierarchy Qos:: - - ./x86_64-native-linuxapp-gcc/app/dpdk-testpmd -c 0x7 -s 0x4 -n 4 \ - --vdev 'net_softnic0,firmware=./drivers/net/softnic/tm_firmware.cli,cpu_id=1,conn_port=8086' \ - -- -i --forward-mode=softnic --portmask=0x2 - testpmd> start - -3. Send per flow traffic with 100% line rate, verify output flow rate is 1/4096 subport rate. - -Test Case 3: NAT +Supporting Files ================ -1. Set SNAT with proto tcp test, edit nat_firmware.cli to change "table action" as below:: - - table action profile AP0 ipv4 offset 270 fwd nat src proto tcp - -(a). Start softnic:: - - ./x86_64-native-linuxapp-gcc/app/dpdk-testpmd -c 0x7 -s 0x4 -n 4 \ - --vdev 'net_softnic0,firmware=./drivers/net/softnic/nat_firmware.cli,cpu_id=1,conn_port=8086' \ - -- -i --forward-mode=softnic --portmask=0x2 +All the supporting files for this test suite are maintained inside softnic folder, and softnic folder +is present in the {DTS_SRC_DIR}/dep directory. + +Directory Structure of Each Test Case +===================================== +Within {DTS_SRC_DIR}/dep/softnic, all files related to a particular test case are maintained +in a separate directory of which the directory structure is shown below:: + + test_case_name [directory] + test_case_name.spec + test_case_name_x.io [x: 1 to n; depending on the test case] + test_case_name.cli + table.txt [applicable for test cases requiring it] + readme.txt + pcap_files [subdirectory] + in.txt + out.txt + +For an example, files related to rx_tx test case are maintained as shown below:: + + rx_tx [directory] + rx_tx.spec + rx_tx_1.io + rx_tx_2.io + rx_tx.cli + readme.txt + pcap_files [subdirectory] + in.txt + out.txt + +Template of each Test Case +=========================== +1. Edit test_case_name/test_case_name.io: + change pci device id of port in and port out to pci device id of dut_port_0 + +2. Run softnic driver as the following:: + + x86_64-native-linuxapp-gcc/app/dpdk-testpmd -l 0-2 -n 4 --file-prefix=dpdk_2374972_20221107140937 -s 0x4 -a 0000:af:00.1 \ + --vdev 'net_softnic0,firmware=/tmp/softnic/rx_tx/firmware.cli,cpu_id=1,conn_port=8086' -- -i --portmask=0x2 testpmd> start -(b). Sent packet, verify the received packet's ipaddr and port was changed as expected. +3. Send packets at tester side using scapy. The packets to be sent are maintained in softnic/test_case_name/pcap_files/in.txt -2. Set DNAT with proto tcp test, edit nat_firmware.cli to change "table action" as below:: +4. Verify the packets received using tcpdump. The expected packets are maintained in softnic/test_case_name/pcap_files/out.txt - table action profile AP0 ipv4 offset 270 fwd nat dst proto tcp +5. Test case is considered as successful if the received packets and the expected packets match for all the port combinations used. - Then re-run step (a) & step (b). - -3. Set SNAT with proto udp test, edit nat_firmware.cli to change "table action" as below:: +Example Test Case : rx_tx +================================ +1. Edit rx_tx/rx_tx_1.io: + change pci device id of port in to pci device id of dut_port_0 + Edit rx_tx/rx_tx_2.io: + change pci device id of port out to pci device id of dut_port_0 - table action profile AP0 ipv4 offset 270 fwd nat src proto udp +2. Start softnic:: - Then re-run step (a) & step (b). + x86_64-native-linuxapp-gcc/app/dpdk-testpmd -l 0-2 -n 4 --file-prefix=dpdk_2374972_20221107140937 \ + -s 0x4 -a 0000:af:00.1 --vdev 'net_softnic0,firmware=/tmp/softnic/rx_tx/firmware.cli,cpu_id=1, \ + conn_port=8086' -- -i --portmask=0x2 + testpmd> start -4. Set DNAT with proto udp test, edit nat_firmware.cli to change "table action" as below:: +3. Send packets at tester side using scapy. The packets to be sent are maintained in softnic/rx_tx/pcap_files/in.txt - table action profile AP0 ipv4 offset 270 fwd nat dst proto udp +4. Verify the packets received using tcpdump. The expected packets are maintained in softnic/rx_tx/pcap_files/out.txt - Then re-run step (a) & step (b). +5. Test rx_tx is considered as successful if the received packets and the expected packets match for all port combinations used. \ No newline at end of file diff --git a/tests/TestSuite_softnic.py b/tests/TestSuite_softnic.py index e379125d..94814bd7 100644 --- a/tests/TestSuite_softnic.py +++ b/tests/TestSuite_softnic.py @@ -7,233 +7,263 @@ DPDK Test suite. Test softnic API in DPDK. """ +import itertools import os import re import string import time +import traceback +from time import sleep + +import scapy.layers.inet +from scapy.arch import get_if_hwaddr +from scapy.packet import Raw, bind_layers +from scapy.route import * +from scapy.sendrecv import sendp, sniff +from scapy.utils import hexstr, rdpcap, wrpcap import framework.utils as utils -from framework.pktgen import PacketGeneratorHelper from framework.pmd_output import PmdOutput -from framework.settings import HEADER_SIZE from framework.test_case import TestCase class TestSoftnic(TestCase): - def set_up_all(self): + def pair_hex_digits(self, iterable, count, fillvalue=None): + args = [iter(iterable)] * count + return itertools.zip_longest(*args, fillvalue=fillvalue) + + def get_flow_direction_param_of_tcpdump(self): + """ + get flow dirction param depend on tcpdump version + """ + param = "" + direct_param = r"(\s+)\[ (\S+) in\|out\|inout \]" + out = self.tester.send_expect("tcpdump -h", "# ", trim_whitespace=False) + for line in out.split("\n"): + m = re.match(direct_param, line) + if m: + opt = re.search("-Q", m.group(2)) + if opt: + param = "-Q" + " in" + else: + opt = re.search("-P", m.group(2)) + if opt: + param = "-P" + " in" + if len(param) == 0: + self.logger.info("tcpdump not support direction choice!!!") + return param + + def tcpdump_start_sniff(self, interface, filters=""): + """ + Starts tcpdump in the background to sniff packets that received by interface. + """ + cmd = "rm -f /tmp/tcpdump_{0}.pcap".format(interface) + self.tester.send_expect(cmd, "#") + cmd = "tcpdump -nn -e {0} -w /tmp/tcpdump_{1}.pcap -i {1} {2} -Q in 2>/tmp/tcpdump_{1}.out &".format( + self.param_flow_dir, interface, filters + ) + self.tester.send_expect(cmd, "# ") + + def tcpdump_stop_sniff(self): + """ + Stops the tcpdump process running in the background. + """ + self.tester.send_expect("killall tcpdump", "# ") + # For the [pid]+ Done tcpdump... message after killing the process + sleep(1) + self.tester.send_expect('echo "Cleaning buffer"', "# ") + sleep(1) + + def compare_packets(self, in_file, out_file, all_pkts): + """ + Flag all_pkt is zero, then it compares small packet(size upto 48 bytes). + Flag all_pkt is non-zero, then it compares all packets of out_file. + """ + if all_pkts == 0: + cmd = "diff -sqw <(head -n 11 {}) <(head -n 11 {})".format( + in_file, out_file + ) + else: + cmd = "diff -sqw {} {}".format(in_file, out_file) + return self.tester.send_command(cmd, timeout=0.5) + + def convert_tcpdump_to_text2pcap(self, in_filename, out_filename): + with open(in_filename) as input, open(out_filename, "w") as output: + output.write("# SPDX-License-Identifier: BSD-3-Clause\n") + output.write("# Copyright(c) 2022 Intel Corporation\n") + output.write("#\n\n") + output.write("# text to pcap: text2pcap packet.txt packet.pcap\n") + output.write("# pcap to text: tcpdump -r packet.pcap -xx\n\n") + + i = 0 + for line in input: + time = self.pkt_timestamp.match(line) + if time: + output.write("# Packet {}\n".format(i)) + i += 1 + continue + payload = self.pkt_content.match(line) + if payload: + address = payload.group(1) + hex_data = payload.group(2).replace(" ", "") + hex_data = " ".join( + "".join(part) for part in self.pair_hex_digits(hex_data, 2, " ") + ) + output.write("{:0>6} {:<47}\n".format(address, hex_data)) + + def send_and_sniff( + self, from_port, to_port, in_pcap, out_pcap, filters, all_pkts=0 + ): + self.tester.send_expect("rm -f /tmp/*.txt /tmp/*.pcap /tmp/*.out", "# ") + tx_count = len(from_port) + rx_count = len(to_port) + tx_port, rx_port, tx_inf, rx_inf = ([] for i in range(4)) + + for i in range(tx_count): + tx_port.append(self.tester.get_local_port(self.dut_ports[from_port[i]])) + tx_inf.append(self.tester.get_interface(tx_port[i]).strip()) + + for i in range(rx_count): + rx_port.append(self.tester.get_local_port(self.dut_ports[to_port[i]])) + rx_inf.append(self.tester.get_interface(rx_port[i]).strip()) + self.tcpdump_start_sniff(rx_inf[i], filters[i]) + + self.tester.scapy_foreground() + for i in range(tx_count): + self.tester.send_expect( + "text2pcap -q {} /tmp/tx_{}.pcap".format( + self.src_path + in_pcap[i], tx_inf[i] + ), + "# ", + ) + self.tester.scapy_append( + 'pkt = rdpcap("/tmp/tx_{}.pcap")'.format(tx_inf[i]) + ) + + self.tester.scapy_append( + 'sendp(pkt, iface="{}", count=32)'.format(tx_inf[i]) + ) + + self.tester.scapy_execute() + self.tcpdump_stop_sniff() + mismatch_count = 0 + + for i in range(rx_count): + self.tester.send_expect( + "tcpdump -n -r /tmp/tcpdump_{}.pcap -xx > /tmp/packet_rx.txt".format( + rx_inf[i] + ), + "# ", + ) + self.convert_tcpdump_to_text2pcap( + "/tmp/packet_rx.txt", "/tmp/packet_rx_rcv_{}.txt".format(rx_inf[i]) + ) + out = self.compare_packets( + "/tmp/packet_rx_rcv_{}.txt".format(rx_inf[i]), + self.src_path + out_pcap[i], + all_pkts, + ) + if "are identical" not in out: + return False + return True + def set_up_all(self): # Based on h/w type, choose how many ports to use - ports = self.dut.get_ports() - self.dut_ports = self.dut.get_ports(self.nic) + self.dut_ports = self.dut.get_ports() # Verify that enough ports are available - self.verify(len(ports) >= 1, "Insufficient ports for testing") - self.def_driver = self.dut.ports_info[ports[0]]["port"].get_nic_driver() - self.ports_socket = self.dut.get_numa_id(ports[0]) + self.verify(len(self.dut_ports) >= 1, "Insufficient ports for testing") + self.def_driver = self.dut.ports_info[self.dut_ports[0]][ + "port" + ].get_nic_driver() + self.ports_socket = self.dut.get_numa_id(self.dut_ports[0]) # Verify that enough threads are available cores = self.dut.get_core_list("1S/1C/1T") self.verify(cores is not None, "Insufficient cores for speed testing") - global P0 - P0 = ports[0] - - self.txItf = self.tester.get_interface(self.tester.get_local_port(P0)) - self.dmac = self.dut.get_mac_address(P0) - self.headers_size = HEADER_SIZE["eth"] + HEADER_SIZE["ip"] + HEADER_SIZE["udp"] - - # need change config files - self.root_path = "/tmp/" - self.firmware = r"dep/firmware.cli" - self.tm_firmware = r"dep/tm_firmware.cli" - self.nat_firmware = r"dep/nat_firmware.cli" - self.dut.session.copy_file_to(self.firmware, self.root_path) - self.dut.session.copy_file_to(self.tm_firmware, self.root_path) - self.dut.session.copy_file_to(self.nat_firmware, self.root_path) - self.eal_param = " -a %s" % self.dut.ports_info[0]["pci"] + self.param_flow_dir = self.get_flow_direction_param_of_tcpdump() + + # setting up source and destination location + self.dst_path = "/tmp/" + FILE_DIR = os.path.dirname(os.path.abspath(__file__)).split(os.path.sep) + self.src_path = os.path.sep.join(FILE_DIR[:-1]) + "/dep/" + SOFTNIC_TAR_FOLDER = self.src_path + "softnic" + + # copy dependancies to the DUT + self.tester.send_expect("rm -rf /tmp/softnic.tar.gz", "# ") + self.tester.send_expect( + "tar -zcf /tmp/softnic.tar.gz --absolute-names {}".format(self.src_path), + "# ", + 20, + ) + self.dut.send_expect("rm -rf /tmp/softnic.tar.gz /tmp/softnic", "# ", 20) + self.dut.session.copy_file_to("/tmp/softnic.tar.gz", self.dst_path) + self.dut.send_expect( + "tar -zxf /tmp/softnic.tar.gz --strip-components={} --absolute-names --directory /tmp".format( + SOFTNIC_TAR_FOLDER.count("/") - 1 + ), + "# ", + 20, + ) + + self.eal_param = " ".join( + " -a " + port_info["pci"] for port_info in self.dut.ports_info + ) self.path = self.dut.apps_name["test-pmd"] self.pmdout = PmdOutput(self.dut) + + # create packet matching regular expression + self.pkt_timestamp = re.compile(r"\d{2}\:\d{2}\:\d{2}\.\d{6}") + self.pkt_content = re.compile(r"\t0x([0-9a-fA-F]+): ([0-9a-fA-F ]+)") + # get dts output path if self.logger.log_path.startswith(os.sep): self.output_path = self.logger.log_path else: 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() - self.dut.bind_interfaces_linux(self.drivername, [ports[0]]) + # bind the ports + self.dut.bind_interfaces_linux(self.drivername, [self.dut_ports[0]]) def set_up(self): """ Run before each test case. """ - def change_config_file(self, file_name): - self.dut.send_expect( - "sed -i -e '4c link LINK0 dev %s' %s" - % (self.dut.ports_info[0]["pci"], self.root_path + file_name), - "#", - ) - self.dut.send_expect( - "sed -i -e 's/thread [0-9]/thread 2/g' %s" % self.root_path + file_name, "#" - ) + def run_test_pmd(self, file_name): + try: + cmd = 'test -f {} && echo "File exists!"'.format(file_name) + self.dut.send_expect(cmd, "File exists!", 1) - def test_perf_softnic_performance(self): - self.frame_size = [64, 128, 256, 512, 1024, 1280, 1518] - self.change_config_file("firmware.cli") - # 10G nic pps(M) - expect_pps = [14, 8, 4, 2, 1, 0.9, 0.8] - - self.pmdout.start_testpmd( - list(range(3)), - "--forward-mode=softnic --portmask=0x2", - eal_param="-s 0x4 %s --vdev 'net_softnic0,firmware=/tmp/%s,cpu_id=1,conn_port=8086'" - % (self.eal_param, "firmware.cli"), - ) - self.dut.send_expect("start", "testpmd>") - rx_port = self.tester.get_local_port(0) - tx_port = self.tester.get_local_port(0) - n = 0 - for frame in self.frame_size: - payload_size = frame - self.headers_size - tgen_input = [] - pcap = os.sep.join([self.output_path, "test.pcap"]) - pkt = "Ether(dst='%s')/IP()/UDP()/Raw(load='x'*%d)" % ( - self.dmac, - payload_size, + self.pmdout.start_testpmd( + list(range(3)), + "--portmask=0x2", + eal_param="-s 0x4 %s --vdev 'net_softnic0,firmware=%s,cpu_id=1,conn_port=8086'" + % (self.eal_param, file_name), ) - self.tester.scapy_append('wrpcap("%s", [%s])' % (pcap, pkt)) - tgen_input.append((tx_port, rx_port, pcap)) - self.tester.scapy_execute() - # clear streams before add new streams - self.tester.pktgen.clear_streams() - # run packet generator - streams = self.pktgen_helper.prepare_stream_from_tginput( - tgen_input, 100, None, self.tester.pktgen - ) - _, pps = self.tester.pktgen.measure_throughput(stream_ids=streams) - pps = pps / 1000000.0 - self.verify(pps > 0, "No traffic detected") - self.verify(pps > expect_pps[n], "No traffic detected") - n = n + 1 - - def test_perf_shaping_for_pipe(self): - self.change_config_file("tm_firmware.cli") - self.pmdout.start_testpmd( - list(range(3)), - "--forward-mode=softnic --portmask=0x2", - eal_param="-s 0x4 %s --vdev 'net_softnic0,firmware=/tmp/%s,cpu_id=1,conn_port=8086'" - % (self.eal_param, "tm_firmware.cli"), - ) + except Exception: + trace = traceback.format_exc() + self.logger.error("Error while running testpmd:\n" + trace) + + def test_rx_tx(self): + cli_file = "/tmp/softnic/rx_tx/rx_tx.cli" + self.run_test_pmd(cli_file) + sleep(5) self.dut.send_expect("start", "testpmd>") - rx_port = self.tester.get_local_port(0) - pkts = [ - "Ether(dst='%s')/IP(dst='100.0.0.0')/UDP()/Raw(load='x'*(64 - %s))", - "Ether(dst='%s')/IP(dst='100.0.15.255')/UDP()/Raw(load='x'*(64 - %s))", - "Ether(dst='%s')/IP(dst='100.0.4.0')/UDP()/Raw(load='x'*(64 - %s))", - ] - except_bps_range = [1700000, 2000000] - - for i in range(3): - tgen_input = [] - pcap = os.sep.join([self.output_path, "test.pcap"]) - pkt = pkts[i] % (self.dmac, self.headers_size) - self.tester.scapy_append('wrpcap("%s", [%s])' % (pcap, pkt)) - self.tester.scapy_execute() - if i == 2: - for j in range(16): - pk = ( - "Ether(dst='%s')/IP(dst='100.0.15.%d')/UDP()/Raw(load='x'*(64 - %s))" - % (self.dmac, j, self.headers_size) - ) - self.tester.scapy_append( - 'wrpcap("%s/test_%d.pcap", [%s])' % (self.output_path, j, pk) - ) - self.tester.scapy_execute() - tgen_input.append( - (rx_port, rx_port, "%s/test_%d.pcap" % (self.output_path, j)) - ) - else: - tgen_input.append((rx_port, rx_port, pcap)) - # clear streams before add new streams - self.tester.pktgen.clear_streams() - # run packet generator - streams = self.pktgen_helper.prepare_stream_from_tginput( - tgen_input, 100, None, self.tester.pktgen - ) - bps, pps = self.tester.pktgen.measure_throughput(stream_ids=streams) - if i == 2: - self.verify( - except_bps_range[1] * 16 > bps > except_bps_range[0] * 16, - "No traffic detected", - ) - else: - self.verify( - except_bps_range[1] > bps > except_bps_range[0], - "No traffic detected", - ) - - def test_nat(self): - self.change_config_file("nat_firmware.cli") - expect_ips = ["192.168.0.1.5000", "192.168.0.2.5001"] - ips = ["100.0.0.1", "100.0.0.2"] - pkt_location = ["src", "dst"] - pkt_type = ["tcp", "udp"] - for t in pkt_type: - for i in range(2): - self.dut.send_expect( - "sed -i -e '12c table action profile AP0 ipv4 offset 270 fwd nat %s proto %s' %s" - % (pkt_location[i], t, self.root_path + "nat_firmware.cli"), - "#", - ) - self.pmdout.start_testpmd( - list(range(3)), - "--forward-mode=softnic --portmask=0x2", - eal_param="-s 0x4 %s --vdev 'net_softnic0,firmware=/tmp/%s,cpu_id=1,conn_port=8086'" - % (self.eal_param, "nat_firmware.cli"), - ) - if self.nic in [ - "ICE_100G-E810C_QSFP", - "ICE_25G-E810C_SFP", - "ICE_25G-E810_XXV_SFP", - ]: - self.dut.send_expect("set fwd mac", "testpmd>") - self.dut.send_expect("start", "testpmd>") - # src ip tcp - for j in range(2): - out = self.scapy_send_packet(pkt_location[i], ips[j], t) - self.verify(expect_ips[j] in out, "fail to receive expect packet") - self.dut.send_expect("quit", "# ") - time.sleep(1) - - def scapy_send_packet(self, pkt_location, ip, pkt_type): - self.tester.scapy_foreground() - pkt = "Ether(dst='%s')/IP(dst='%s')/" % (self.dmac, ip) - if pkt_type == "tcp": - pkt = pkt + "TCP()/Raw(load='x'*20)" - else: - pkt = pkt + "UDP()/Raw(load='x'*20)" - self.tester.scapy_append('sendp([%s], iface="%s")' % (pkt, self.txItf)) - self.start_tcpdump(self.txItf) - self.tester.scapy_execute() - out = self.get_tcpdump_package() - return out - - def get_tcpdump_package(self): - time.sleep(4) - self.tester.send_expect("killall tcpdump", "#") - out = self.tester.send_expect( - "tcpdump -A -nn -e -vv -r getPackageByTcpdump.cap |grep '192.168'", "#" - ) - return out + in_pcap = ["softnic/rx_tx/pcap_files/in.txt"] + out_pcap = ["softnic/rx_tx/pcap_files/out.txt"] + filters = ["tcp"] + tx_port = [0] + rx_port = [0] + result = self.send_and_sniff(tx_port, rx_port, in_pcap, out_pcap, filters) + if result: + self.dut.send_expect("stop", "testpmd>") + else: + self.verify(False, "Output pcap files mismatch error") - def start_tcpdump(self, rxItf): - self.tester.send_expect("rm -rf getPackageByTcpdump.cap", "#") - self.tester.send_expect( - "tcpdump -A -nn -e -vv -w getPackageByTcpdump.cap -i %s 2> /dev/null& " - % self.txItf, - "#", - ) - time.sleep(4) + """ + Add new test cases here. + """ def tear_down(self): """ @@ -245,6 +275,4 @@ class TestSoftnic(TestCase): """ Run after each test suite. """ - self.dut.bind_interfaces_linux( - driver=self.def_driver, nics_to_bind=self.dut.get_ports() - ) + self.dut.kill_all()