From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by dpdk.org (Postfix) with ESMTP id 3FCAB7260 for ; Tue, 16 Jan 2018 07:10:12 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 Jan 2018 22:10:11 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.46,367,1511856000"; d="scan'208";a="26783147" Received: from dpdk-test47.sh.intel.com ([10.67.118.152]) by orsmga002.jf.intel.com with ESMTP; 15 Jan 2018 22:10:10 -0800 From: wang fei To: dts@dpdk.org Cc: yulong.pei@intel.com, wang fei Date: Tue, 16 Jan 2018 16:40:28 +0800 Message-Id: <1516092028-33040-1-git-send-email-feix.y.wang@intel.com> X-Mailer: git-send-email 2.7.4 Subject: [dts] [DTS][PATCH V1/2] Add one test suite X-BeenThere: dts@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: test suite reviews and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 16 Jan 2018 06:10:13 -0000 For next branch, add nic_single_core_perf suite using Trex as traffic generator Signed-off-by: wang fei --- tests/TestSuite_nic_single_core_perf.py | 268 ++++++++++++++++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 tests/TestSuite_nic_single_core_perf.py diff --git a/tests/TestSuite_nic_single_core_perf.py b/tests/TestSuite_nic_single_core_perf.py new file mode 100644 index 0000000..00de60b --- /dev/null +++ b/tests/TestSuite_nic_single_core_perf.py @@ -0,0 +1,268 @@ +# +# Copyright(c) 2010-2014 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. + +""" +DPDK Test suite. +""" + +import utils +import re +import time +from test_case import TestCase +from time import sleep +from settings import HEADER_SIZE +from pmd_output import PmdOutput +from copy import deepcopy +from prettytable import PrettyTable + +class TestNicSingleCorePerf(TestCase): + + def set_up_all(self): + """ + Run at the start of each test suite. + PMD prerequisites. + """ + + self.frame_sizes = [64] + self.headers_size = HEADER_SIZE['eth'] + HEADER_SIZE['ip'] + HEADER_SIZE['tcp'] + self.ixgbe_descriptors = [128, 512, 2048] + self.i40e_descriptors = [512, 2048] + + # traffic duraion in second + self.trafficDuration = 60 + + # list expected throughput values for 64byte packet size and different txd/rxd + self.expected_throughput_nnt = {64: {128: 51.303, 512: 34.603, 2048: 34.539}} + #self.expected_throughput_fvl10g = {64: {512: 0, 2048: 0}} + self.expected_throughput_fvl25g = {64: {512: 43.365, 2048: 38.658}} + self.expected_throughput_fvl40g = {64: {512: 43.614, 2048: 38.407}} + + # The acdepted gap between expected throughput and actual throughput, 1 Mpps + self.gap = 1 + + # header to print test result table + self.table_header = ['Frame Size', 'TXD/RXD', 'Throughput', 'Rate', 'Expected Throughput'] + + # Update config file and rebuild to get best perf on FVL + self.dut.send_expect("sed -i -e 's/CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=n/CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=y/' ./config/common_base", "#", 20) + self.dut.build_install_dpdk(self.target) + + # Based on h/w type, choose how many ports to use + self.dut_ports = self.dut.get_ports() + + self.socket = self.dut.get_numa_id(self.dut_ports[0]) + + self.pmdout = PmdOutput(self.dut) + + self.test_result = {} + + # determine if to save test result as a separated file + self.save_result_flag = False + + def set_up(self): + """ + Run before each test case. + """ + if self.nic == "niantic": + self.descriptors = self.ixgbe_descriptors + elif self.nic in ["fortville_eagle", "fortville_25g", "fortville_spirit"]: + self.descriptors = self.i40e_descriptors + else: + raise "This tests only support NICs: nantic, fortville_eagle, fortville_25g, fortville_spirit" + + def test_nic_single_core_perf(self): + """ + Run single core performance + """ + if len(self.dut_ports) >= 4 and self.nic == "niantic": + self.perf_test(self.nic, 4) + elif len(self.dut_ports) >= 2 and self.nic == "fortville_eagle": + self.perf_test(self.nic, 4) + elif len(self.dut_ports) >= 2 and self.nic == "fortville_25g": + self.perf_test(self.nic, 2) + elif len(self.dut_ports) >= 2 and self.nic == "fortville_spirit": + self.perf_test(self.nic, 2) + + def perf_test(self, nic_type, port_num): + """ + Single core Performance Benchmarking test + """ + # traffic option + options = { + 'rate' : '100%', + #'ip': {'action': 'inc', 'mask' : '255.255.255.0', 'step': '0.0.0.1'} + } + + header = self.table_header + if port_num == 2: + pci0 = self.dut.ports_info[0]['pci'] + pci1 = self.dut.ports_info[1]['pci'] + eal = "-w %s -w %s" % (pci0, pci1) + elif port_num == 4: + pci0 = self.dut.ports_info[0]['pci'] + pci1 = self.dut.ports_info[1]['pci'] + pci2 = self.dut.ports_info[2]['pci'] + pci3 = self.dut.ports_info[3]['pci'] + eal = "-w %s -w %s -w %s -w %s" % (pci0, pci1, pci2, pci3) + + # run testpmd with 2 cores + core_config = "1S/2C/1T" + core_list = self.dut.get_core_list(core_config, socket=self.socket) + port_mask = utils.create_mask(self.dut_ports) + + for frame_size in self.frame_sizes: + ret_datas = {} + for descriptor in self.descriptors: + self.logger.info("Executing Test Using cores: %s" % core_list) + self.pmdout.start_testpmd(core_config, "--portmask=%s --txd=%d --rxd=%d" % (port_mask, descriptor, descriptor),eal, socket=self.socket) + self.dut.send_expect("start", "testpmd> ", 15) + + self.logger.info("Running with frame size %d " % frame_size) + + # create pcap file + payload_size = frame_size - self.headers_size + self.tester.scapy_append( + 'wrpcap("test.pcap", [Ether(src="52:00:00:00:00:00")/IP(src="1.2.3.4",dst="1.1.1.1")/TCP()/("X"*%d)])' % payload_size) + self.tester.scapy_execute() + + # send the traffic + streams = self.prepare_stream(port_num, options) + _, packets_received = self.tester.pktgen.measure_throughput(stream_ids=streams, delay=self.trafficDuration) + + throughput = packets_received / 1000000.0 + + self.dut.send_expect("stop", "testpmd> ") + self.dut.send_expect("quit", "# ", 30) + + self.logger.info("Throughput result for Descriptor :%s is :%s Mpps" % (descriptor, throughput)) + + wirespeed = self.wirespeed(self.nic, frame_size, port_num) + + # one entry for test result record + ret_data = {} + ret_data[header[0]] = frame_size + ret_data[header[1]] = descriptor + ret_data[header[2]] = str(float("%.3f" % throughput)) + " Mpps" + ret_data[header[3]] = str(float("%.3f" % (throughput * 100 / wirespeed))) + "%" + if self.nic == "niantic": + ret_data[header[4]] = str(self.expected_throughput_nnt[frame_size][descriptor]) + " Mpps" + elif self.nic == "fortville_eagle": + ret_data[header[4]] = str(self.expected_throughput_fvl10g[frame_size][descriptor]) + " Mpps" + elif self.nic == "fortville_25g": + ret_data[header[4]] = str(self.expected_throughput_fvl25g[frame_size][descriptor]) + " Mpps" + elif self.nic == "fortville_spirit": + ret_data[header[4]] = str(self.expected_throughput_fvl40g[frame_size][descriptor]) + " Mpps" + ret_datas[descriptor] = deepcopy(ret_data) + self.test_result[frame_size] = deepcopy(ret_datas) + + for frame_size in self.frame_sizes: + for descriptor in self.descriptors: + self.verify(self.test_result[frame_size][descriptor][header[2]] > 0, "No traffic detected") + + # Print results + self.result_table_create(header) + for frame_size in self.frame_sizes: + for descriptor in self.descriptors: + table_row = [self.test_result[frame_size][descriptor][header[0]]] + table_row.append(self.test_result[frame_size][descriptor][header[1]]) + table_row.append(self.test_result[frame_size][descriptor][header[2]]) + table_row.append(self.test_result[frame_size][descriptor][header[3]]) + table_row.append(self.test_result[frame_size][descriptor][header[4]]) + self.result_table_add(table_row) + + self.result_table_print() + + # save test results as a file + if self.save_result_flag: + self.save_result(self.test_result) + + # check if the gap between expected throughput and actual throughput exceed accepted gap + for frame_size in self.frame_sizes: + for descriptor in self.descriptors: + self.verify(float(self.test_result[frame_size][descriptor][header[4]].split()[0]) - + float(self.test_result[frame_size][descriptor][header[2]].split()[0]) < self.gap, "Exceeded Gap") + + def prepare_stream(self, port_num, options): + ''' + create streams for ports, one port one stream + ''' + if port_num == 2: + txport0 = self.tester.get_local_port(self.dut.get_ports()[0]) + txport1 = self.tester.get_local_port(self.dut.get_ports()[1]) + stream_id0 = self.tester.pktgen.add_stream(txport0, txport1, r'/root/test.pcap') + stream_id1 = self.tester.pktgen.add_stream(txport1, txport0, r'/root/test.pcap') + self.tester.pktgen.config_stream(stream_id0, options) + self.tester.pktgen.config_stream(stream_id1, options) + return [stream_id0, stream_id1] + elif port_num == 4: + txport0 = self.tester.get_local_port(self.dut.get_ports()[0]) + txport1 = self.tester.get_local_port(self.dut.get_ports()[1]) + txport2 = self.tester.get_local_port(self.dut.get_ports()[2]) + txport3 = self.tester.get_local_port(self.dut.get_ports()[3]) + stream_id0 = self.tester.pktgen.add_stream(txport0, txport1, r'/root/test.pcap') + stream_id1 = self.tester.pktgen.add_stream(txport1, txport0, r'/root/test.pcap') + stream_id2 = self.tester.pktgen.add_stream(txport2, txport3, r'/root/test.pcap') + stream_id3 = self.tester.pktgen.add_stream(txport3, txport2, r'/root/test.pcap') + self.tester.pktgen.config_stream(stream_id0, options) + self.tester.pktgen.config_stream(stream_id1, options) + self.tester.pktgen.config_stream(stream_id2, options) + self.tester.pktgen.config_stream(stream_id3, options) + return [stream_id0, stream_id1, stream_id2, stream_id3] + + def save_result(self, data): + ''' + Saves the test results as a separated file named with self.nic+_single_core_perf.txt + in output folder if self.save_result_flag is True + ''' + header = self.table_header + table = PrettyTable(header) + for frame_size in self.frame_sizes: + for descriptor in self.descriptors: + table_row = [self.test_result[frame_size][descriptor][header[0]]] + table_row.append(self.test_result[frame_size][descriptor][header[1]]) + table_row.append(self.test_result[frame_size][descriptor][header[2]]) + table_row.append(self.test_result[frame_size][descriptor][header[3]]) + table_row.append(self.test_result[frame_size][descriptor][header[4]]) + table.add_row(table_row) + file_to_save = open("output/%s_single_core_perf.txt" % self.nic, 'w') + file_to_save.write(str(table)) + file_to_save.close() + + def tear_down(self): + """ + Run after each test case. + """ + self.dut.send_expect("sed -i -e 's/CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=y/CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=n/' ./config/common_base", "#", 20) + + def tear_down_all(self): + """ + Run after each test suite. + """ + self.dut.kill_all() -- 2.7.4