* [dts] [PATCH v3]tests,test_plans: add checksum offload and tso @ 2016-03-01 6:07 Lijuan Tu 2016-03-08 1:44 ` Pei, Yulong 0 siblings, 1 reply; 3+ messages in thread From: Lijuan Tu @ 2016-03-01 6:07 UTC (permalink / raw) To: dts, yulong.pei Add checksum offload and tso test scripts, test plan, config file Signed-off-by: Lijuan Tu <lijuanx.a.tu@intel.com> --- conf/vf_offload.cfg | 107 ++++++++++ test_plans/vf_offload_test_plan.rst | 175 +++++++++++++++++ tests/TestSuite_vf_offload.py | 380 ++++++++++++++++++++++++++++++++++++ 3 files changed, 662 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..ab1c0c7 --- /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=5 6 7 8 9; +disk = + file=/home/image/fedora23.img; +mem = + size=8196 +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..1c0b914 --- /dev/null +++ b/test_plans/vf_offload_test_plan.rst @@ -0,0 +1,175 @@ +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. +Send packet with incorrect checksum, can rx it and reported the checksum error, +and verify forwarded packets have correct checksum. + +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. + +Except that SCTP header + payload length must be a multiple of 4 bytes. +IPv4 + UDP/TCP packet length can range from the minimum length to 1518 bytes. + +Then 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 IXIA. + +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. + +IPv4 + UDP/TCP packet length can range from the minimum length to 1518 bytes. + +Then 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 <tx port> rx off tx off tso off gso off gro off lro off + ip l set <tx port> up + tcpdump -n -e -i <rx port> -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 <tx port> rx off tx off tso off gso off gro off lro off + ip l set <tx port> up +capture package rx port on tester:: + tcpdump -n -e -i <rx port> -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 @@ +# <COPYRIGHT_TAG> + +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 ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [dts] [PATCH v3]tests,test_plans: add checksum offload and tso 2016-03-01 6:07 [dts] [PATCH v3]tests,test_plans: add checksum offload and tso Lijuan Tu @ 2016-03-08 1:44 ` Pei, Yulong 2016-03-08 1:49 ` Tu, LijuanX A 0 siblings, 1 reply; 3+ messages in thread From: Pei, Yulong @ 2016-03-08 1:44 UTC (permalink / raw) To: Tu, LijuanX A, dts Hi Lijuan, Please see my comment's below, -----Original Message----- From: Tu, LijuanX A Sent: Tuesday, March 1, 2016 2:07 PM To: dts@dpdk.org; Pei, Yulong <yulong.pei@intel.com> Cc: Tu, LijuanX A <lijuanx.a.tu@intel.com> Subject: [dts][PATCH v3]tests,test_plans: add checksum offload and tso Add checksum offload and tso test scripts, test plan, config file Signed-off-by: Lijuan Tu <lijuanx.a.tu@intel.com> --- conf/vf_offload.cfg | 107 ++++++++++ test_plans/vf_offload_test_plan.rst | 175 +++++++++++++++++ tests/TestSuite_vf_offload.py | 380 ++++++++++++++++++++++++++++++++++++ 3 files changed, 662 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..ab1c0c7 --- /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=5 6 7 8 9; disk = Number=4, and cpupin is 5, right ? + file=/home/image/fedora23.img; +mem = + size=8196 +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..1c0b914 --- /dev/null +++ b/test_plans/vf_offload_test_plan.rst @@ -0,0 +1,175 @@ +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. +Send packet with incorrect checksum, can rx it and reported the +checksum error, and verify forwarded packets have correct checksum. + +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. + +Except that SCTP header + payload length must be a multiple of 4 bytes. +IPv4 + UDP/TCP packet length can range from the minimum length to 1518 bytes. + +Then 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 IXIA. + Does your cases need IXIA ? +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. + +IPv4 + UDP/TCP packet length can range from the minimum length to 1518 bytes. + +Then 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. + Does your cases need IXIA ? Best Regards Yulong Pei +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 <tx port> rx off tx off tso off gso off gro off lro off + ip l set <tx port> up + tcpdump -n -e -i <rx port> -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 <tx port> rx off tx off tso off gso off gro off lro off + ip l set <tx port> up +capture package rx port on tester:: + tcpdump -n -e -i <rx port> -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(sp +ort=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 @@ +# <COPYRIGHT_TAG> + +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 ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [dts] [PATCH v3]tests,test_plans: add checksum offload and tso 2016-03-08 1:44 ` Pei, Yulong @ 2016-03-08 1:49 ` Tu, LijuanX A 0 siblings, 0 replies; 3+ messages in thread From: Tu, LijuanX A @ 2016-03-08 1:49 UTC (permalink / raw) To: Pei, Yulong, dts Hi ,yulong, I use scapy to send packets and check checksum. IXIA is an example as an tester packet generator > -----Original Message----- > From: Pei, Yulong > Sent: Tuesday, March 08, 2016 9:45 AM > To: Tu, LijuanX A; dts@dpdk.org > Subject: RE: [dts][PATCH v3]tests,test_plans: add checksum offload and > tso > > Hi Lijuan, > > Please see my comment's below, > > > -----Original Message----- > From: Tu, LijuanX A > Sent: Tuesday, March 1, 2016 2:07 PM > To: dts@dpdk.org; Pei, Yulong <yulong.pei@intel.com> > Cc: Tu, LijuanX A <lijuanx.a.tu@intel.com> > Subject: [dts][PATCH v3]tests,test_plans: add checksum offload and tso > > Add checksum offload and tso test scripts, test plan, config file > > Signed-off-by: Lijuan Tu <lijuanx.a.tu@intel.com> > --- > conf/vf_offload.cfg | 107 ++++++++++ > test_plans/vf_offload_test_plan.rst | 175 +++++++++++++++++ > tests/TestSuite_vf_offload.py | 380 > ++++++++++++++++++++++++++++++++++++ > 3 files changed, 662 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..ab1c0c7 > --- /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=5 6 7 8 9; disk = > > Number=4, and cpupin is 5, right ? > > > + file=/home/image/fedora23.img; > +mem = > + size=8196 > +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..1c0b914 > --- /dev/null > +++ b/test_plans/vf_offload_test_plan.rst > @@ -0,0 +1,175 @@ > +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. > +Send packet with incorrect checksum, can rx it and reported the > +checksum error, and verify forwarded packets have correct checksum. > + > +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. > + > +Except that SCTP header + payload length must be a multiple of 4 bytes. > +IPv4 + UDP/TCP packet length can range from the minimum length to 1518 > bytes. > + > +Then 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 IXIA. > + > > Does your cases need IXIA ? > > > +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. > + > +IPv4 + UDP/TCP packet length can range from the minimum length to 1518 > bytes. > + > +Then 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. > + > > Does your cases need IXIA ? > > > Best Regards > Yulong Pei > > > +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 <tx port> rx off tx off tso off gso off gro off lro off > + ip l set <tx port> up > + tcpdump -n -e -i <rx port> -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 <tx port> rx off tx off tso off gso off gro off lro off > + ip l set <tx port> up > +capture package rx port on tester:: > + tcpdump -n -e -i <rx port> -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(s > p > +ort=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=102 > 1)/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 @@ > +# <COPYRIGHT_TAG> > + > +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"*4 > 6)' % (mac, sndIP), > + 'IP/TCP': 'Ether(dst="%s", > src="52:00:00:00:00:00")/IP(src="%s",chksum=0xf)/TCP(chksum=0xf)/("X"*4 > 6)' % (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=102 > 1)/("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 ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2016-03-08 1:49 UTC | newest] Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2016-03-01 6:07 [dts] [PATCH v3]tests,test_plans: add checksum offload and tso Lijuan Tu 2016-03-08 1:44 ` Pei, Yulong 2016-03-08 1:49 ` Tu, LijuanX A
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).