From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by dpdk.org (Postfix) with ESMTP id 63B877D24 for ; Wed, 16 Aug 2017 08:28:26 +0200 (CEST) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga105.jf.intel.com with ESMTP; 15 Aug 2017 23:28:24 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.41,381,1498546800"; d="scan'208";a="1004168202" Received: from ypei-25.sh.intel.com ([10.67.110.158]) by orsmga003.jf.intel.com with ESMTP; 15 Aug 2017 23:28:23 -0700 From: Yulong Pei To: dts@dpdk.org, yong.liu@intel.com Cc: feix.y.wang@intel.com, qian.q.xu@intel.com Date: Tue, 15 Aug 2017 15:20:11 +0800 Message-Id: <1502781611-89367-1-git-send-email-yulong.pei@intel.com> X-Mailer: git-send-email 2.5.0 Subject: [dts] [PATCH] Add vf performance test plan and test script 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: Wed, 16 Aug 2017 06:28:27 -0000 Signed-off-by: Yulong Pei --- test_plans/vf_perf_test_plan.rst | 86 ++++++++++++ tests/TestSuite_vf_perf.py | 289 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 375 insertions(+) create mode 100644 test_plans/vf_perf_test_plan.rst create mode 100644 tests/TestSuite_vf_perf.py diff --git a/test_plans/vf_perf_test_plan.rst b/test_plans/vf_perf_test_plan.rst new file mode 100644 index 0000000..cd62752 --- /dev/null +++ b/test_plans/vf_perf_test_plan.rst @@ -0,0 +1,86 @@ +.. Copyright (c) <2017>, Intel Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + - Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + + +Test Case 1: Measure performace with kernel PF & dpdk VF +======================================================== + +1. Two NIC PF ports, using kernel driver, create 1 VF from each PF. + +2. Bind the two created VFs to dpdk igb_uio driver and start dpdk l3fwd. + +3. send packet stream from 64bytes to 1518bytes with ixia traffic generator, +got output result, the format should be as below, with figures given in Mpps: + ++-------+------+--------+-----------+ +| Frame | mode | Mpps | %linerate | ++=======+======+========+===========+ +| 64 | lpm | | | ++-------+------+--------+-----------+ +| 128 | lpm | | | ++-------+------+--------+-----------+ +| 256 | lpm | | | ++-------+------+--------+-----------+ +| 512 | lpm | | | ++-------+------+--------+-----------+ +| 1024 | lpm | | | ++-------+------+--------+-----------+ +| 1518 | lpm | | | ++-------+------+--------+-----------+ + + +Test Case 2: Measure performace with dpdk PF & dpdk VF +====================================================== + +1. Two NIC PF ports, binding to igb_uio driver, then create 1 VF from each PF. + +2. Bind the two created VFs to dpdk igb_uio driver and start dpdk l3fwd. + +3. send packet stream from 64bytes to 1518bytes with ixia traffic generator, +got output result, the format should be as below, with figures given in Mpps: + ++-------+------+--------+-----------+ +| Frame | mode | Mpps | %linerate | ++=======+======+========+===========+ +| 64 | lpm | | | ++-------+------+--------+-----------+ +| 128 | lpm | | | ++-------+------+--------+-----------+ +| 256 | lpm | | | ++-------+------+--------+-----------+ +| 512 | lpm | | | ++-------+------+--------+-----------+ +| 1024 | lpm | | | ++-------+------+--------+-----------+ +| 1518 | lpm | | | ++-------+------+--------+-----------+ + diff --git a/tests/TestSuite_vf_perf.py b/tests/TestSuite_vf_perf.py new file mode 100644 index 0000000..f6a0bb8 --- /dev/null +++ b/tests/TestSuite_vf_perf.py @@ -0,0 +1,289 @@ +# BSD LICENSE +# +# Copyright(c) 2010-2017 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import re +import time +import string + +import dts +import utils +from test_case import TestCase +from pmd_output import PmdOutput +from etgen import IxiaPacketGenerator +from settings import HEADER_SIZE + +class TestVfPerf(TestCase, IxiaPacketGenerator): + + def set_up_all(self): + + self.tester.extend_external_packet_generator(TestVfPerf, self) + + self.dut_ports = self.dut.get_ports(self.nic) + self.verify(len(self.dut_ports) >= 2, "Insufficient ports") + + self.pf0 = self.dut_ports[0] + netdev = self.dut.ports_info[self.pf0]['port'] + self.pf0_socket = netdev.get_nic_socket() + + self.cores = self.dut.get_core_list("1S/6C/1T", socket=self.pf0_socket) + print self.cores + + global valports + valports = [_ for _ in self.dut_ports if self.tester.get_local_port(_) != -1] + self.verify(len(valports) >= 2, "Insufficient active ports for speed testing") + + self.frame_sizes = [64, 128, 256, 512, 1024, 1518] + self.l3fwd_methods = ['lpm'] + + self.vf0_mac = "00:12:34:56:78:01" + self.vf1_mac = "00:12:34:56:78:02" + + self.l3fwd_test_results = {'header': [], 'data': []} + + self.dut.send_expect("sed -i -e 's/define RTE_TEST_RX_DESC_DEFAULT.*$/define RTE_TEST_RX_DESC_DEFAULT 2048/' ./examples/l3fwd/main.c", "#", 20) + self.dut.send_expect("sed -i -e 's/define RTE_TEST_TX_DESC_DEFAULT.*$/define RTE_TEST_TX_DESC_DEFAULT 2048/' ./examples/l3fwd/main.c", "#", 20) + out = self.dut.build_dpdk_apps("./examples/l3fwd", "USER_FLAGS=-DAPP_LOOKUP_METHOD=1") + self.verify("Error" not in out, "compilation error 1") + self.verify("No such file" not in out, "compilation error 2") + + def set_up(self): + + self.setup_2vf_env_flag = 0 + + def setup_2vf_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'] + + + if driver != 'igb_uio': + + pf_intf0 = self.dut.ports_info[0]['port'].get_interface_name() + self.dut.send_expect("ip link set %s vf 0 mac %s" % (pf_intf0, self.vf0_mac), "#") + pf_intf1 = self.dut.ports_info[1]['port'].get_interface_name() + self.dut.send_expect("ip link set %s vf 0 mac %s" % (pf_intf1, self.vf1_mac), "#") + + try: + + for port in self.sriov_vfs_port_0: + port.bind_driver('igb_uio') + for port in self.sriov_vfs_port_1: + port.bind_driver('igb_uio') + + time.sleep(1) + + if driver == 'igb_uio': + # start testpmd without the two VFs on the host + self.host_testpmd = PmdOutput(self.dut) + eal_param = '--socket-mem=1024,1024 --file-prefix=pf -b %(vf0)s -b %(vf1)s' % {'vf0': self.sriov_vfs_port_0[0].pci, + 'vf1': self.sriov_vfs_port_1[0].pci} + testpmd_cl = self.cores[0:2] + self.host_testpmd.start_testpmd(testpmd_cl, "", eal_param=eal_param) + self.host_testpmd.execute_cmd('set vf mac addr 0 0 %s' % self.vf0_mac) + self.host_testpmd.execute_cmd('set vf mac addr 1 0 %s' % self.vf1_mac) + time.sleep(1) + + self.setup_2vf_env_flag = 1 + + except Exception as e: + self.destroy_2vf_env() + raise Exception(e) + + def destroy_2vf_env(self): + + if getattr(self, 'host_testpmd', None): + self.host_testpmd.execute_cmd('quit', '# ') + self.host_testpmd = None + + if getattr(self, 'used_dut_port_0', None) != 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) != 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_2vf_env_flag = 0 + + def flows(self): + """ + Return a list of packets that implements the flows described in l3fwd. + """ + return [ + 'IP(src="1.2.3.4",dst="2.1.1.1")', + 'IP(src="1.2.3.4",dst="2.1.1.2")', + 'IP(src="1.2.3.4",dst="1.1.1.1")', + 'IP(src="1.2.3.4",dst="1.1.1.2")', + 'IP(src="1.2.3.4",dst="4.1.1.1")', + 'IP(src="1.2.3.4",dst="4.1.1.2")', + 'IP(src="1.2.3.4",dst="3.1.1.1")', + 'IP(src="1.2.3.4",dst="3.1.1.2")'] + + def perf_2ports(self, cmdline): + + l3fwd_session = self.dut.new_session() + + header_row = ["Frame", "mode", "Mpps", "%linerate"] + self.l3fwd_test_results['header'] = header_row + self.result_table_create(header_row) + self.l3fwd_test_results['data'] = [] + + dmac = [self.vf0_mac, self.vf1_mac] + smac = ["02:00:00:00:00:00", "02:00:00:00:00:01"] + for frame_size in self.frame_sizes: + + # Prepare traffic flow + payload_size = frame_size - HEADER_SIZE['ip'] - HEADER_SIZE['eth'] + + for _port in range(2): + flows = ['Ether(dst="%s", src="%s")/%s/("X"*%d)' % (dmac[_port], smac[_port], flow, payload_size) for flow in self.flows()[_port *2:(_port +1)*2]] + self.tester.scapy_append('wrpcap("dst%d.pcap", [%s])' %(valports[_port], string.join(flows,','))) + self.tester.scapy_execute() + + for mode in self.l3fwd_methods: + + info = "Executing l3fwd using %s mode, 2 ports, %d frame size.\n" % (mode, frame_size) + self.logger.info(info) + + if frame_size > 1518: + cmdline = cmdline + " --max-pkt-len %d" % frame_size + + out = l3fwd_session.send_expect(cmdline, "L3FWD:", 120) + + # Measure test + tgenInput = [] + for rxPort in range(2): + + if rxPort % 2 == 0: + txIntf = self.tester.get_local_port(valports[rxPort + 1]) + else: + txIntf = self.tester.get_local_port(valports[rxPort - 1]) + + rxIntf = self.tester.get_local_port(valports[rxPort]) + if rxPort % 2 == 0: + tgenInput.append((txIntf, rxIntf, "dst%d.pcap" %valports[rxPort+1])) + else: + tgenInput.append((txIntf, rxIntf, "dst%d.pcap" %valports[rxPort-1])) + + _, pps = self.tester.traffic_generator_throughput(tgenInput, rate_percent=100, delay=60) + self.verify(pps > 0, "No traffic detected") + pps /= 1000000.0 + linerate = self.wirespeed(self.nic, frame_size, 2) + pct = pps * 100 / linerate + + # Stop l3fwd + l3fwd_session.send_expect("^C", "#") + + data_row = [frame_size, mode, str(pps), str(pct)] + self.result_table_add(data_row) + self.l3fwd_test_results['data'].append(data_row) + + self.dut.close_session(l3fwd_session) + self.result_table_print() + + + def measure_vf_performance(self, driver='default'): + + if driver == 'igb_uio': + self.setup_2vf_env(driver='igb_uio') + else: + self.setup_2vf_env(driver='') + + vf0_pci = self.sriov_vfs_port_0[0].pci + vf1_pci = self.sriov_vfs_port_1[0].pci + + if self.nic in ["fortville_25g", "fortville_spirit", "fortville_eagle"]: + + l3fwd_cl = self.cores[2:6] + core_mask = utils.create_mask(l3fwd_cl) + + cmdline = "./examples/l3fwd/build/l3fwd -c {0} -n 4 -w {1} -w {2} -- -p 0x3 \ + --config '(0,0,{3}),(0,1,{4}),(1,0,{5}),(1,1,{6})' ". \ + format(core_mask, vf0_pci, vf1_pci, l3fwd_cl[0], l3fwd_cl[1], l3fwd_cl[2], l3fwd_cl[3]) + else: + + l3fwd_cl = self.cores[4:6] + core_mask = utils.create_mask(l3fwd_cl) + cmdline = "./examples/l3fwd/build/l3fwd -c {0} -n 4 -w {1} -w {2} -- -p 0x3 \ + --config '(0,0,{3}),(1,0,{4})' ". \ + format(core_mask, vf0_pci, vf1_pci, l3fwd_cl[0], l3fwd_cl[1]) + + self.perf_2ports(cmdline) + + def test_perf_a_kernel_pf_dpdk_vf_performance(self): + + self.measure_vf_performance(driver='') + + def test_perf_b_dpdk_pf_dpdk_vf_performance(self): + + self.measure_vf_performance(driver='igb_uio') + + def ip(self, port, frag, src, proto, tos, dst, chksum, len, options, version, flags, ihl, ttl, id): + + self.add_tcl_cmd("protocol config -name ip") + self.add_tcl_cmd('ip config -sourceIpAddr "%s"' % src) + self.add_tcl_cmd("ip config -sourceIpAddrMode ipRandom") + self.add_tcl_cmd('ip config -destIpAddr "%s"' % dst) + self.add_tcl_cmd("ip config -destIpAddrMode ipIdle") + self.add_tcl_cmd("ip config -ttl %d" % ttl) + self.add_tcl_cmd("ip config -totalLength %d" % len) + self.add_tcl_cmd("ip config -fragment %d" % frag) + self.add_tcl_cmd("ip config -ipProtocol ipV4ProtocolReserved255") + self.add_tcl_cmd("ip config -identifier %d" % id) + self.add_tcl_cmd("stream config -framesize %d" % (len + 18)) + self.add_tcl_cmd("ip set %d %d %d" % (self.chasId, port['card'], port['port'])) + + def tear_down(self): + + if self.setup_2vf_env_flag == 1: + self.destroy_2vf_env() + + for port_id in self.dut_ports: + self.dut.destroy_sriov_vfs_by_port(port_id) + # DPDK-1754 + intf = self.dut.ports_info[port_id]['intf'] + self.dut.send_expect("ethtool -s %s autoneg on" % intf, "# ") + + def tear_down_all(self): + pass -- 2.5.0