From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by dpdk.org (Postfix) with ESMTP id ECCDE2C55 for ; Tue, 8 Mar 2016 08:35:39 +0100 (CET) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga103.jf.intel.com with ESMTP; 07 Mar 2016 23:35:39 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.22,555,1449561600"; d="scan'208";a="919134914" Received: from unknown (HELO dpdk-fedora20.icx.intel.com) ([10.238.55.12]) by fmsmga001.fm.intel.com with ESMTP; 07 Mar 2016 23:35:37 -0800 From: Lijuan Tu To: dts@dpdk.org, yulong.pei@intel.com Date: Tue, 8 Mar 2016 15:31:16 +0800 Message-Id: <1457422276-56481-1-git-send-email-lijuanx.a.tu@intel.com> X-Mailer: git-send-email 1.9.3 Subject: [dts] [PATCH v4]tests,test_plans: add checksum offload and tso 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: , X-List-Received-Date: Tue, 08 Mar 2016 07:35:41 -0000 Add checksum offload and tso test scripts, test plan, config file Signed-off-by: Lijuan Tu --- conf/vf_offload.cfg | 107 ++++++++++ test_plans/vf_offload_test_plan.rst | 172 ++++++++++++++++ tests/TestSuite_vf_offload.py | 380 ++++++++++++++++++++++++++++++++++++ 3 files changed, 659 insertions(+) create mode 100644 conf/vf_offload.cfg create mode 100644 test_plans/vf_offload_test_plan.rst create mode 100644 tests/TestSuite_vf_offload.py diff --git a/conf/vf_offload.cfg b/conf/vf_offload.cfg new file mode 100644 index 0000000..4ecbe0f --- /dev/null +++ b/conf/vf_offload.cfg @@ -0,0 +1,107 @@ +# QEMU options +# name +# name: vm0 +# +# enable_kvm +# enable: [yes | no] +# +# cpu +# model: [host | core2duo | ...] +# usage: +# choose model value from the command +# qemu-system-x86_64 -cpu help +# number: '4' #number of vcpus +# cpupin: '3 4 5 6' # host cpu list +# +# mem +# size: 1024 +# +# disk +# file: /path/to/image/test.img +# +# net +# type: [nic | user | tap | bridge | ...] +# nic +# opt_vlan: 0 +# note: Default is 0. +# opt_macaddr: 00:00:00:00:01:01 +# note: if creating a nic, it`s better to specify a MAC, +# else it will get a random number. +# opt_model:["e1000" | "virtio" | "i82551" | ...] +# note: Default is e1000. +# opt_name: 'nic1' +# opt_addr: '' +# note: PCI cards only. +# opt_vectors: +# note: This option currently only affects virtio cards. +# user +# opt_vlan: 0 +# note: default is 0. +# opt_hostfwd: [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport +# note: If not specified, it will be setted automatically. +# tap +# opt_vlan: 0 +# note: default is 0. +# opt_br: br0 +# note: if choosing tap, need to specify bridge name, +# else it will be br0. +# opt_script: QEMU_IFUP_PATH +# note: if not specified, default is self.QEMU_IFUP_PATH. +# opt_downscript: QEMU_IFDOWN_PATH +# note: if not specified, default is self.QEMU_IFDOWN_PATH. +# +# device +# driver: [pci-assign | virtio-net-pci | ...] +# pci-assign +# prop_host: 08:00.0 +# prop_addr: 00:00:00:00:01:02 +# virtio-net-pci +# prop_netdev: mynet1 +# prop_id: net1 +# prop_mac: 00:00:00:00:01:03 +# prop_bus: pci.0 +# prop_addr: 0x3 +# +# monitor +# port: 6061 +# note: if adding monitor to vm, need to specicy +# this port, else it will get a free port +# on the host machine. +# +# qga +# enable: [yes | no] +# +# serial_port +# enable: [yes | no] +# +# vnc +# displayNum: 1 +# note: you can choose a number not used on the host. +# +# daemon +# enable: 'yes' +# note: +# By default VM will start with the daemonize status. +# Not support starting it on the stdin now. + +# vm configuration for pmd sriov case +[vm0] +cpu = + model=host,number=4,cpupin=4 5 6 7; +disk = + file=/home/image/sriov-fc23-1.img; +mem = + size=4096; +login = + user=root,password=tester; +net = + type=nic,opt_vlan=0; + type=user,opt_vlan=0; +monitor = + port=; +qga = + enable=yes; +vnc = + displayNum=11; +daemon = + enable=yes; diff --git a/test_plans/vf_offload_test_plan.rst b/test_plans/vf_offload_test_plan.rst new file mode 100644 index 0000000..36beaaa --- /dev/null +++ b/test_plans/vf_offload_test_plan.rst @@ -0,0 +1,172 @@ +Prerequisites for checksum offload +================================== + +Support igb_uio and vfio driver, if used vfio, kernel need 3.6+ and enable vt-d in bios. +When used vfio , used "modprobe vfio" and "modprobe vfio-pci" insmod vfiod driver, then used +"./tools/dpdk_nic_bind.py --bind=vfio-pci device_bus_id" to bind vfio driver to test driver. + +Assuming that ports ``0`` and ``2`` are connected to a traffic generator, +launch the ``testpmd`` with the following arguments:: + + ./build/app/testpmd -cffffff -n 1 -- -i --burst=1 --txpt=32 \ + --txht=8 --txwt=0 --txfreet=0 --rxfreet=64 --mbcache=250 --portmask=0x5 + enable-rx-checksum + +Set the verbose level to 1 to display informations for each received packet:: + + testpmd> set verbose 1 + +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 + +Verify that how many packets found with Bad-ipcsum or Bad-l4csum:: + + testpmd> stop + ---------------------- Forward statistics for port 0 ---------------------- + RX-packets: 0 RX-dropped: 0 RX-total: 0 + Bad-ipcsum: 0 Bad-l4csum: 0 + TX-packets: 0 TX-dropped: 0 TX-total: 0 + ---------------------------------------------------------------------------- + + +Test Case: HW checksum offload check +======================================================================== +Start testpmd and enable checksum offload on tx port. + +Setup the ``csum`` forwarding mode:: + + testpmd> set fwd csum + Set csum packet forwarding mode + +Enable the IPv4/UDP/TCP/SCTP checksum offload on port 0:: + + testpmd> + testpmd> tx_checksum set ip hw 0 + testpmd> tx_checksum set udp hw 0 + testpmd> tx_checksum set tcp hw 0 + testpmd> tx_checksum set sctp hw 0 + 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 + +Configure the traffic generator to send the multiple packets for the following +combination: IPv4/UDP, IPv4/TCP, IPv4/SCTP, IPv6/UDP, IPv6/TCP. + +Send packets with incorrect checksum, +Verify dpdk can rx it and reported the checksum error, +Verify that the same number of packet are correctly received on the traffic +generator side. And IPv4 checksum, TCP checksum, UDP checksum, SCTP CRC32c need +be validated as pass by the tester. + +The IPv4 source address will not be changed by testpmd. + + +Test Case: SW checksum offload check +========================================================================== +disable HW checksum offload on tx port, SW Checksum check. +Send same packet with incorrect checksum and verify checksum is valid. + +Setup the ``csum`` forwarding mode:: + + testpmd> set fwd csum + Set csum packet forwarding mode + +Disable the IPv4/UDP/TCP/SCTP checksum offload on port 0:: + + testpmd> tx_checksum set 0x0 0 + 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 + +Configure the traffic generator to send the multiple packets for the follwing +combination: IPv4/UDP, IPv4/TCP, IPv6/UDP, IPv6/TCP. + +Send packets with incorrect checksum, +Verify dpdk can rx it and reported the checksum error, +Verify that the same number of packet are correctly received on the traffic +generator side. And IPv4 checksum, TCP checksum, UDP checksum need +be validated as pass by the IXIA. + +The first byte of source IPv4 address will be increment by testpmd. The checksum +is indeed recalculated by software algorithms. + +Prerequisites for TSO +===================== + +The DUT must take one of the Ethernet controller ports connected to a port on another +device that is controlled by the Scapy packet generator. + +The Ethernet interface identifier of the port that Scapy will use must be known. +On tester, all offload feature should be disabled on tx port, and start rx port capture:: + ethtool -K rx off tx off tso off gso off gro off lro off + ip l set up + tcpdump -n -e -i -s 0 -w /tmp/cap + + +On DUT, run pmd with parameter "--enable-rx-cksum". Then enable TSO on tx port +and checksum on rx port. The test commands is below:: + #enable hw checksum on rx port + tx_checksum set ip hw 0 + tx_checksum set udp hw 0 + tx_checksum set tcp hw 0 + tx_checksum set sctp hw 0 + set fwd csum + + # enable TSO on tx port + *tso set 800 1 + + +Test case: csum fwd engine, use TSO +==================================================== + +This test uses ``Scapy`` to send out one large TCP package. The dut forwards package +with TSO enable on tx port while rx port turns checksum on. After package send out +by TSO on tx port, the tester receives multiple small TCP package. + +Turn off tx port by ethtool on tester:: + ethtool -K rx off tx off tso off gso off gro off lro off + ip l set up +capture package rx port on tester:: + tcpdump -n -e -i -s 0 -w /tmp/cap + +Launch the userland ``testpmd`` application on DUT as follows:: + + testpmd> set verbose 1 + + # enable hw checksum on rx port + testpmd> tx_checksum set ip hw 0 + testpmd> tx_checksum set udp hw 0 + testpmd> tx_checksum set tcp hw 0 + testpmd> tx_checksum set sctp hw 0 + # enable TSO on tx port + testpmd> tso set 800 1 + # set fwd engine and start + testpmd> set fwd csum + testpmd> start + +Test IPv4() in scapy: + sendp([Ether(dst="%s", src="52:00:00:00:00:00")/IP(src="192.168.1.1",dst="192.168.1.2")/UDP(sport=1021,dport=1021)/Raw(load="\x50"*%s)], iface="%s") + +Test IPv6() in scapy: + sendp([Ether(dst="%s", src="52:00:00:00:00:00")/IPv6(src="FE80:0:0:0:200:1FF:FE00:200", dst="3555:5555:6666:6666:7777:7777:8888:8888")/UDP(sport=1021,dport=1021)/Raw(load="\x50"*%s)], iface="%s" + diff --git a/tests/TestSuite_vf_offload.py b/tests/TestSuite_vf_offload.py new file mode 100644 index 0000000..78fa5a6 --- /dev/null +++ b/tests/TestSuite_vf_offload.py @@ -0,0 +1,380 @@ +# + +import re +import time + +import dts +from qemu_kvm import QEMUKvm +from test_case import TestCase +from pmd_output import PmdOutput +from utils import RED, GREEN +from net_device import NetDevice +from crb import Crb +from scapy.all import * +from settings import HEADER_SIZE +VM_CORES_MASK = 'all' + +class TestVfOffload(TestCase): + + def set_up_all(self): + self.dut_ports = self.dut.get_ports(self.nic) + self.verify(len(self.dut_ports) > 1, "Insufficient ports") + self.vm0 = None + self.setup_2pf_2vf_1vm_env_flag = 0 + self.setup_2pf_2vf_1vm_env(driver='') + self.vm0_dut_ports = self.vm_dut_0.get_ports('any') + self.portMask = dts.create_mask([self.vm0_dut_ports[0]]) + self.vm0_testpmd = PmdOutput(self.vm_dut_0) + + def set_up(self): + pass + + def setup_2pf_2vf_1vm_env(self, driver='default'): + + self.used_dut_port_0 = self.dut_ports[0] + self.dut.generate_sriov_vfs_by_port(self.used_dut_port_0, 1, driver=driver) + self.sriov_vfs_port_0 = self.dut.ports_info[self.used_dut_port_0]['vfs_port'] + self.used_dut_port_1 = self.dut_ports[1] + self.dut.generate_sriov_vfs_by_port(self.used_dut_port_1, 1, driver=driver) + self.sriov_vfs_port_1 = self.dut.ports_info[self.used_dut_port_1]['vfs_port'] + + try: + + for port in self.sriov_vfs_port_0: + port.bind_driver('pci-stub') + + for port in self.sriov_vfs_port_1: + port.bind_driver('pci-stub') + + time.sleep(1) + vf0_prop = {'opt_host': self.sriov_vfs_port_0[0].pci} + vf1_prop = {'opt_host': self.sriov_vfs_port_1[0].pci} + + if driver == 'igb_uio': + # start testpmd without the two VFs on the host + self.host_testpmd = PmdOutput(self.dut) + eal_param = '-b %(vf0)s -b %(vf1)s' % {'vf0': self.sriov_vfs_port_0[0].pci, + 'vf1': self.sriov_vfs_port_1[0].pci} + self.host_testpmd.start_testpmd("1S/2C/2T", eal_param=eal_param) + + # set up VM0 ENV + self.vm0 = QEMUKvm(self.dut, 'vm0', 'vf_offload') + self.vm0.set_vm_device(driver='pci-assign', **vf0_prop) + self.vm0.set_vm_device(driver='pci-assign', **vf1_prop) + self.vm_dut_0 = self.vm0.start() + if self.vm_dut_0 is None: + raise Exception("Set up VM0 ENV failed!") + + self.setup_2pf_2vf_1vm_env_flag = 1 + except Exception as e: + self.destroy_2pf_2vf_1vm_env() + raise Exception(e) + + def destroy_2pf_2vf_1vm_env(self): + if getattr(self, 'vm0', None): + #destroy testpmd in vm0 + self.vm0_testpmd = None + self.vm0_dut_ports = None + #destroy vm0 + self.vm0.stop() + self.vm0 = None + + if getattr(self, 'host_testpmd', None): + self.host_testpmd.execute_cmd('quit', '# ') + self.host_testpmd = None + + if getattr(self, 'used_dut_port_0', None): + self.dut.destroy_sriov_vfs_by_port(self.used_dut_port_0) + port = self.dut.ports_info[self.used_dut_port_0]['port'] + port.bind_driver() + self.used_dut_port_0 = None + + if getattr(self, 'used_dut_port_1', None): + self.dut.destroy_sriov_vfs_by_port(self.used_dut_port_1) + port = self.dut.ports_info[self.used_dut_port_1]['port'] + port.bind_driver() + self.used_dut_port_1 = None + + for port_id in self.dut_ports: + port = self.dut.ports_info[port_id]['port'] + port.bind_driver() + + self.setup_2pf_2vf_1vm_env_flag = 0 + + def checksum_enablehw(self, port, dut): + dut.send_expect("csum set ip hw %d" % port, "testpmd>") + dut.send_expect("csum set udp hw %d" % port, "testpmd>") + dut.send_expect("csum set tcp hw %d" % port, "testpmd>") + dut.send_expect("csum set sctp hw %d" % port, "testpmd>") + + def checksum_enablesw(self, port, dut): + dut.send_expect("csum set ip sw %d" % port, "testpmd>") + dut.send_expect("csum set udp sw %d" % port, "testpmd>") + dut.send_expect("csum set tcp sw %d" % port, "testpmd>") + dut.send_expect("csum set sctp sw %d" % port, "testpmd>") + + def checksum_validate(self, packets_sent, packets_expected): + """ + Validate the checksum. + """ + tx_interface = self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0])) + rx_interface = self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0])) + + sniff_src = self.vm0_testpmd.get_port_mac(0) + checksum_pattern = re.compile("chksum.*=.*(0x[0-9a-z]+)") + + chksum = dict() + result = dict() + + self.tester.send_expect("scapy", ">>> ") + + for packet_type in packets_expected.keys(): + self.tester.send_expect("p = %s" % packets_expected[packet_type], ">>>") + out = self.tester.send_expect("p.show2()", ">>>") + chksums = checksum_pattern.findall(out) + chksum[packet_type] = chksums + print packet_type, ": ", chksums + + self.tester.send_expect("exit()", "#") + + self.tester.scapy_background() + self.tester.scapy_append('p = sniff(filter="ether src %s", iface="%s", count=%d)' % (sniff_src, rx_interface, len(packets_sent))) + self.tester.scapy_append('nr_packets=len(p)') + self.tester.scapy_append('reslist = [p[i].sprintf("%IP.chksum%;%TCP.chksum%;%UDP.chksum%;%SCTP.chksum%") for i in range(nr_packets)]') + self.tester.scapy_append('import string') + self.tester.scapy_append('RESULT = string.join(reslist, ",")') + + # Send packet. + self.tester.scapy_foreground() + + for packet_type in packets_sent.keys(): + self.tester.scapy_append('sendp([%s], iface="%s")' % (packets_sent[packet_type], tx_interface)) + + self.tester.scapy_execute() + out = self.tester.scapy_get_result() + packets_received = out.split(',') + self.verify(len(packets_sent) == len(packets_received), "Unexpected Packets Drop") + + for packet_received in packets_received: + ip_checksum, tcp_checksum, udp_checksup, sctp_checksum = packet_received.split(';') + print "ip_checksum: ", ip_checksum, "tcp_checksum:, ", tcp_checksum, "udp_checksup: ", udp_checksup, "sctp_checksum: ", sctp_checksum + + packet_type = '' + l4_checksum = '' + if tcp_checksum != '??': + packet_type = 'TCP' + l4_checksum = tcp_checksum + elif udp_checksup != '??': + packet_type = 'UDP' + l4_checksum = udp_checksup + elif sctp_checksum != '??': + packet_type = 'SCTP' + l4_checksum = sctp_checksum + + if ip_checksum != '??': + packet_type = 'IP/' + packet_type + if chksum[packet_type] != [ip_checksum, l4_checksum]: + result[packet_type] = packet_type + " checksum error" + else: + packet_type = 'IPv6/' + packet_type + if chksum[packet_type] != [l4_checksum]: + result[packet_type] = packet_type + " checksum error" + + return result + + def test_checksum_offload_enable(self): + """ + Enable HW Checksum offload. + Send packet with incorrect checksum, + can rx it and reported the checksum error, + verify forwarded packets have correct checksum + """ + self.vm0_testpmd.start_testpmd(VM_CORES_MASK, "--portmask=%s " % + (self.portMask) + "--disable-hw-vlan --enable-rx-cksum " + "--txqflags=0 " + + "--crc-strip --port-topology=loop") + self.vm0_testpmd.execute_cmd('set fwd csum') + + time.sleep(2) + port_id_0 = 0 + mac = self.vm0_testpmd.get_port_mac(0) + + sndIP = '10.0.0.1' + sndIPv6 = '::1' + pkts = {'IP/UDP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(src="%s", chksum=0xf)/UDP(chksum=0xf)/("X"*46)' % (mac, sndIP), + 'IP/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(src="%s", chksum=0xf)/TCP(chksum=0xf)/("X"*46)' % (mac, sndIP), + 'IP/SCTP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(src="%s", chksum=0xf)/SCTP(chksum=0xf)/("X"*48)' % (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 = "10.0.0.2" + expIPv6 = '::2' + pkts_ref = {'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), + 'IP/SCTP': 'Ether(dst="02:00:00:00:00:00", src="%s")/IP(src="%s")/SCTP()/("X"*48)' % (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)} + + if self.nic in ['redrockcanyou', 'atwood']: + del pkts['IP/SCTP'] + del pkts_ref['IP/SCTP'] + + self.checksum_enablehw(0,self.vm_dut_0) + + self.vm0_testpmd.execute_cmd('start') + result = self.checksum_validate(pkts, pkts_ref) + + # Validate checksum on the receive packet + out = self.vm0_testpmd.execute_cmd('stop') + bad_ipcsum = self.vm0_testpmd.get_pmd_value("Bad-ipcsum:", out) + bad_l4csum = self.vm0_testpmd.get_pmd_value("Bad-l4csum:", out) + self.verify(bad_ipcsum == 3, "Bad-ipcsum check error") + self.verify(bad_l4csum == 5, "Bad-l4csum check error") + + self.verify(len(result) == 0, string.join(result.values(), ",")) + + def test_checksum_offload_disable(self): + """ + disable HW checksum offload on tx port, SW Checksum check. + SW Checksum on by default. + Send same packet with incorrect checksum and verify checksum is valid. + """ + + self.vm0_testpmd.start_testpmd(VM_CORES_MASK, "--portmask=%s " % + (self.portMask) + "--disable-hw-vlan --enable-rx-cksum " + + "--crc-strip --port-topology=loop") + self.vm0_testpmd.execute_cmd('set fwd csum') + + time.sleep(2) + + mac = self.vm0_testpmd.get_port_mac(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=0xf)/UDP(chksum=0xf)/("X"*46)' % (mac, sndIP), + 'IP/TCP': 'Ether(dst="%s", src="52:00:00:00:00:00")/IP(src="%s",chksum=0xf)/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 = "10.0.0.2" + expIPv6 = '::2' + 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)} + + self.vm0_testpmd.execute_cmd('start') + result = self.checksum_validate(sndPkts, expPkts) + + # Validate checksum on the receive packet + out = self.vm0_testpmd.execute_cmd('stop') + bad_ipcsum = self.vm0_testpmd.get_pmd_value("Bad-ipcsum:", out) + bad_l4csum = self.vm0_testpmd.get_pmd_value("Bad-l4csum:", out) + self.verify(bad_ipcsum == 2, "Bad-ipcsum check error") + self.verify(bad_l4csum == 4, "Bad-l4csum check error") + + self.verify(len(result) == 0, string.join(result.values(), ",")) + + def tcpdump_start_sniffing(self, ifaces=[]): + """ + Starts tcpdump in the background to sniff the tester interface where + the packets are transmitted to and from the self.dut. + All the captured packets are going to be stored in a file for a + post-analysis. + """ + + for iface in ifaces: + command = ('tcpdump -w tcpdump_{0}.pcap -i {0} 2>tcpdump_{0}.out &').format(iface) + self.tester.send_expect('rm -f tcpdump_{0}.pcap', '#').format(iface) + self.tester.send_expect(command, '#') + + def tcpdump_stop_sniff(self): + """ + Stops the tcpdump process running in the background. + """ + self.tester.send_expect('killall tcpdump', '#') + time.sleep(1) + self.tester.send_expect('echo "Cleaning buffer"', '#') + time.sleep(1) + + def tcpdump_command(self, command): + """ + Sends a tcpdump related command and returns an integer from the output + """ + + result = self.tester.send_expect(command, '#') + print result + return int(result.strip()) + + def number_of_packets(self, iface): + """ + By reading the file generated by tcpdump it counts how many packets were + forwarded by the sample app and received in the self.tester. The sample app + will add a known MAC address for the test to look for. + """ + + command = ('tcpdump -A -nn -e -v -r tcpdump_{iface}.pcap 2>/dev/null | ' + + 'grep -c "seq"') + return self.tcpdump_command(command.format(**locals())) + + def test_tso(self): + """ + TSO IPv4 TCP, IPv6 TCP, VXLan testing + """ + tx_interface = self.tester.get_interface(self.tester.get_local_port(self.dut_ports[0])) + rx_interface = self.tester.get_interface(self.tester.get_local_port(self.dut_ports[1])) + + self.frame_sizes = [128, 1458] + self.headers_size = HEADER_SIZE['eth'] + HEADER_SIZE['ip'] + HEADER_SIZE['tcp'] + padding = self.frame_sizes[0] - self.headers_size + + self.tester.send_expect("ethtool -K %s rx off tx off tso off gso off gro off lro off" % tx_interface, "# ") + self.tester.send_expect("ip l set %s up" % tx_interface, "# ") + + self.portMask = dts.create_mask([self.vm0_dut_ports[0]]) + self.vm0_testpmd.start_testpmd(VM_CORES_MASK, "--portmask=%s " % + (self.portMask) + "--enable-rx-cksum " + + "--txqflags=0 " + + "--crc-strip --port-topology=loop") + + mac = self.vm0_testpmd.get_port_mac(0) + + self.checksum_enablehw(0,self.vm_dut_0) + self.vm0_testpmd.execute_cmd("tso set 800 %d" % self.vm0_dut_ports[1]) + self.vm0_testpmd.execute_cmd("set fwd csum") + self.vm0_testpmd.execute_cmd("start") + + self.tester.scapy_foreground() + time.sleep(5) + + # IPv4 tcp test + + self.tcpdump_start_sniffing([tx_interface, rx_interface]) + self.tester.scapy_append('sendp([Ether(dst="%s",src="52:00:00:00:00:00")/IP(src="192.168.1.1",dst="192.168.1.2")/TCP(sport=1021,dport=1021)/("X"*%s)], iface="%s")' % (mac, padding, tx_interface)) + out = self.tester.scapy_execute() + out = self.vm0_testpmd.execute_cmd("show port stats all") + print out + self.tcpdump_stop_sniff() + rx_stats = self.number_of_packets(rx_interface) + if (rx_stats == 2): + self.verify(1, "Pass") + + # IPv6 tcp test + + self.tcpdump_start_sniffing([tx_interface, rx_interface]) + self.tester.scapy_append('sendp([Ether(dst="%s", src="52:00:00:00:00:00")/IPv6(src="FE80:0:0:0:200:1FF:FE00:200", dst="3555:5555:6666:6666:7777:7777:8888:8888")/TCP(sport=1021,dport=1021)/("X"*%s)], iface="%s")' % (mac, padding, tx_interface)) + out = self.tester.scapy_execute() + out = self.vm0_testpmd.execute_cmd("show port stats all") + print out + self.tcpdump_stop_sniff() + rx_stats = self.number_of_packets(rx_interface) + if (rx_stats == 2): + self.verify(1, "Pass") + + + def tear_down(self): + self.vm0_testpmd.execute_cmd('quit', '# ') + pass + + def tear_down_all(self): + print "tear_down_all" + if self.setup_2pf_2vf_1vm_env_flag == 1: + self.destroy_2pf_2vf_1vm_env() -- 2.5.0