From patchwork Thu Sep 24 03:03:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, XiX" X-Patchwork-Id: 78627 Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id D6893A04B1; Thu, 24 Sep 2020 05:02:21 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id B13841C2F7; Thu, 24 Sep 2020 05:02:21 +0200 (CEST) Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by dpdk.org (Postfix) with ESMTP id AAA261C2F2 for ; Thu, 24 Sep 2020 05:02:19 +0200 (CEST) IronPort-SDR: gAaUZVp+0V+1zzA6F79B77bzNA1EiaOb+V4TcGUchQON4hBXlaBdjy/kam+Zg+Orxi36s7BQgY 3Wcu1WeX41Tw== X-IronPort-AV: E=McAfee;i="6000,8403,9753"; a="225218500" X-IronPort-AV: E=Sophos;i="5.77,296,1596524400"; d="scan'208";a="225218500" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Sep 2020 20:02:18 -0700 IronPort-SDR: H3FlT1F5/2xNxxSv0uOAAI601Gs9hoX5WGk6JWkDYQFU3/HJ/MlBmad7E0dnwJykAWkETh0Cei 1J2epiicFX2A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.77,296,1596524400"; d="scan'208";a="413197196" Received: from unknown (HELO localhost.localdomain.sh.intel.com) ([10.240.182.150]) by fmsmga001.fm.intel.com with ESMTP; 23 Sep 2020 20:02:16 -0700 From: xizhan4x To: dts@dpdk.org Cc: xizhan4x Date: Thu, 24 Sep 2020 11:03:44 +0800 Message-Id: <1600916624-30757-1-git-send-email-xix.zhang@intel.com> X-Mailer: git-send-email 1.8.3.1 Subject: [dts] [PATCH V1] tests/TestSuite_vhost_cbdma:add virtio cbdma 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: , Errors-To: dts-bounces@dpdk.org Sender: "dts" add virtio cbdma suite Signed-off-by: xizhan4x Acked-by: Wang, Yinan --- tests/TestSuite_vhost_cbdma.py | 346 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 346 insertions(+) create mode 100644 tests/TestSuite_vhost_cbdma.py diff --git a/tests/TestSuite_vhost_cbdma.py b/tests/TestSuite_vhost_cbdma.py new file mode 100644 index 0000000..e15839f --- /dev/null +++ b/tests/TestSuite_vhost_cbdma.py @@ -0,0 +1,346 @@ +# BSD LICENSE +# +# Copyright(c) <2019> 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. + +""" +DPDK Test suite. +We introduce a new vdev parameter to enable DMA acceleration for Tx +operations of queues: + - dmas: This parameter is used to specify the assigned DMA device of + a queue. + - dmathr: If packets length >= dmathr, leverage I/OAT device to perform memory copy; + otherwise, leverage librte_vhost to perform memory copy. + +Here is an example: + $ ./testpmd -c f -n 4 \ + --vdev 'net_vhost0,iface=/tmp/s0,queues=1,dmas=[txq0@80:04.0],dmathr=1024' +""" +import re +import time +from test_case import TestCase +from settings import HEADER_SIZE +from pktgen import PacketGeneratorHelper +from pmd_output import PmdOutput + + +class TestVirTioVhostCbdma(TestCase): + def set_up_all(self): + # Get and verify the ports + self.dut_ports = self.dut.get_ports() + self.number_of_ports = 1 + + self.vhost_user = self.dut.new_session(suite="vhost-user") + self.virtio_user = self.dut.new_session(suite="virtio-user") + self.pmdout_vhost_user = PmdOutput(self.dut, self.vhost_user) + self.pmdout_virtio_user = PmdOutput(self.dut, self.virtio_user) + self.frame_sizes = [64, 1518] + self.virtio_mac = "00:01:02:03:04:05" + self.headers_size = HEADER_SIZE['eth'] + HEADER_SIZE['ip'] + self.pci_info = self.dut.ports_info[0]['pci'] + self.cores = self.dut.get_core_list("all") + self.cbdma_dev_infos = [] + + self.ports_socket = self.dut.get_numa_id(self.dut_ports[0]) + self.bind_nic_driver(self.dut_ports) + # the path of pcap file + self.out_path = '/tmp/%s' % self.suite_name + out = self.tester.send_expect('ls -d %s' % self.out_path, '# ') + if 'No such file or directory' in out: + self.tester.send_expect('mkdir -p %s' % self.out_path, '# ') + self.pktgen_helper = PacketGeneratorHelper() + self.base_dir = self.dut.base_dir.replace('~', '/root') + + def set_up(self): + """ + Run before each test case. + """ + self.table_header = ['Frame'] + self.used_cbdma = [] + self.table_header.append("Mode") + self.table_header.append("Mpps") + self.table_header.append("% linerate") + self.result_table_create(self.table_header) + self.vhost = self.dut.new_session(suite="vhost-user") + self.dut.send_expect("rm -rf %s/vhost-net*" % self.base_dir, "#") + self.dut.send_expect("rm -rf /tmp/s0", "#") + + def bind_nic_driver(self, ports, driver=""): + if driver == "igb_uio": + for port in ports: + netdev = self.dut.ports_info[port]['port'] + driver = netdev.get_nic_driver() + if driver != 'igb_uio': + netdev.bind_driver(driver='igb_uio') + else: + for port in ports: + netdev = self.dut.ports_info[port]['port'] + driver_now = netdev.get_nic_driver() + if driver == "": + driver = netdev.default_driver + if driver != driver_now: + netdev.bind_driver(driver=driver) + + def get_cbdma_ports_info_and_bind_to_dpdk(self, cbdma_num): + """ + get all cbdma ports + """ + + out = self.dut.send_expect('./usertools/dpdk-devbind.py --status-dev misc', '# ', 30) + device_info = out.split('\n') + for device in device_info: + pci_info = re.search('\s*(0000:\d*:\d*.\d*)', device) + if pci_info is not None: + dev_info = pci_info.group(1) + # the numa id of ioat dev, only add the device which + # on same socket with nic dev + bus = int(dev_info[5:7], base=16) + if bus >= 128: + cur_socket = 1 + else: + cur_socket = 0 + if self.ports_socket == cur_socket: + self.cbdma_dev_infos.append(pci_info.group(1)) + self.verify(len(self.cbdma_dev_infos) >= cbdma_num, 'There no enough cbdma device to run this suite') + + self.used_cbdma = self.cbdma_dev_infos[0:cbdma_num] + + self.device_str = ' '.join(self.used_cbdma) + self.dut.send_expect('./usertools/dpdk-devbind.py --force --bind=%s %s %s' % + ("igb_uio", self.device_str, self.pci_info), '# ', 60) + + def bind_cbdma_device_to_kernel(self): + if self.device_str is not None: + self.dut.send_expect('modprobe ioatdma', '# ') + self.dut.send_expect('./usertools/dpdk-devbind.py -u %s' % self.device_str, '# ', 30) + self.dut.send_expect('./usertools/dpdk-devbind.py --force --bind=ioatdma %s' % self.device_str, + '# ', 60) + + @property + def check_2m_env(self): + out = self.dut.send_expect("cat /proc/meminfo |grep Hugepagesize|awk '{print($2)}'", "# ") + return True if out == '2048' else False + + def launch_testpmd_as_vhost_user(self, command, cores="Default", dev=""): + self.pmdout_vhost_user.start_testpmd(cores=cores, param=command, vdevs=[dev], ports=[], + + prefix="vhost", fixed_prefix=True) + + self.vhost_user.send_expect('set fwd mac', 'testpmd> ', 120) + self.vhost_user.send_expect('start', 'testpmd> ', 120) + + def launch_testpmd_as_virtio_user(self, command, cores="Default", dev=""): + eal_params = "" + if self.check_2m_env: + eal_params += " --single-file-segments" + self.pmdout_virtio_user.start_testpmd(cores, command, vdevs=[dev], ports=[], no_pci=True, + prefix="virtio", fixed_prefix=True, eal_param=eal_params) + + self.virtio_user.send_expect('set fwd mac', 'testpmd> ', 120) + self.virtio_user.send_expect('start', 'testpmd> ', 120) + + def diff_param_launch_send_and_verify(self, mode, params, dev, cores, is_quit=True): + self.launch_testpmd_as_virtio_user(params, + cores, + dev=dev) + + self.send_and_verify(mode) + if is_quit: + self.virtio_user.send_expect("quit", "# ") + time.sleep(3) + + def test_perf_pvp_spilt_all_path_with_cbdma_vhost_enqueue_operations(self): + """ + used one cbdma port bonding igb_uio + :return: + """ + txd_rxd = 1024 + dmathr = 1024 + eal_tx_rxd = ' --nb-cores=%d --txd=%d --rxd=%d' + queue = 1 + used_cbdma_num = 1 + self.get_cbdma_ports_info_and_bind_to_dpdk(used_cbdma_num) + vhost_vdevs = f"'net_vhost0,iface=/tmp/s0,queues=%d,dmas=[txq0@{self.device_str}],dmathr=%d'" + dev_path_mode_mapper = { + "inorder_mergeable_path": 'mrg_rxbuf=1,in_order=1', + "mergeable_path": 'mrg_rxbuf=1,in_order=0', + "inorder_non_mergeable_path": 'mrg_rxbuf=0,in_order=1', + "non_mergeable_path": 'mrg_rxbuf=0,in_order=0', + "vector_rx_path": 'mrg_rxbuf=0,in_order=0', + } + + pvp_split_all_path_virtio_params = "--tx-offloads=0x0 --enable-hw-vlan-strip --nb-cores=%d --txd=%d " \ + "--rxd=%d" % (queue, txd_rxd, txd_rxd) + self.launch_testpmd_as_vhost_user(eal_tx_rxd % (queue, txd_rxd, txd_rxd), self.cores[1:3], + dev=vhost_vdevs % (queue, dmathr), ) + + for key, path_mode in dev_path_mode_mapper.items(): + if key == "vector_rx_path": + pvp_split_all_path_virtio_params = eal_tx_rxd % ( + queue, txd_rxd, txd_rxd) + vdevs = f"'net_virtio_user0,mac={self.virtio_mac},path=/tmp/s0,{path_mode},queues=%d'" % queue + self.diff_param_launch_send_and_verify(key, pvp_split_all_path_virtio_params, vdevs, + self.cores[4:6], + ) + self.result_table_print() + + def test_perf_dynamic_queue_number_cbdma_vhost_enqueue_operations(self): + """ + # used 2 cbdma ports bonding igb_uio + :return: + """ + used_cbdma_num = 2 + queue = 2 + txd_rxd = 1024 + dmathr = 1024 + nb_cores = 1 + virtio_path = "/tmp/s0" + path_mode = 'mrg_rxbuf=1,in_order=1' + self.get_cbdma_ports_info_and_bind_to_dpdk(used_cbdma_num) + vhost_dmas = f"dmas=[txq0@{self.used_cbdma[0]};txq1@{self.used_cbdma[1]}],dmathr={dmathr}" + + eal_params = " --nb-cores=%d --txd=%d --rxd=%d --txq=%d --rxq=%d " % (nb_cores, txd_rxd, txd_rxd, queue, queue) + + dynamic_queue_number_cbdma_virtio_params = f" --tx-offloads=0x0 --enable-hw-vlan-strip {eal_params}" + + virtio_dev = f"net_virtio_user0,mac={self.virtio_mac},path={virtio_path},{path_mode},queues={queue},server=1" + vhost_dev = f"'net_vhost0,iface={virtio_path},queues={queue},client=1,%s'" + + # launch vhost testpmd + self.launch_testpmd_as_vhost_user(eal_params, self.cores[27:29], + dev=vhost_dev % vhost_dmas) + # + # queue 2 start virtio testpmd,virtio queue 2 to 1 + mode = "dynamic_queue2" + self.launch_testpmd_as_virtio_user(dynamic_queue_number_cbdma_virtio_params, + self.cores[29:31], + dev=virtio_dev) + self.send_and_verify(mode) + self.vhost_or_virtio_set_one_queue(self.virtio_user) + self.send_and_verify("virtio_user_" + mode + "_change_to_1", multiple_queue=False) + + self.virtio_user.send_expect("stop", "testpmd> ") + self.virtio_user.send_expect("quit", "# ") + time.sleep(5) + self.dut.send_expect(f"rm -rf {virtio_path}", "#") + # queue 2 start virtio testpmd,vhost queue 2 to 1 + self.launch_testpmd_as_virtio_user(dynamic_queue_number_cbdma_virtio_params, + self.cores[29:31], + dev=virtio_dev) + mode = "Relaunch_dynamic_queue2" + self.send_and_verify(mode) + self.vhost_or_virtio_set_one_queue(self.vhost_user) + self.send_and_verify("vhost_user" + mode + "_change_to_1") + self.vhost_user.send_expect("quit", "# ") + time.sleep(2) + + # Relaunch vhost with another two cbdma channels + mode = "Relaunch_vhost_2_cbdma" + dmathr = 512 + vhost_dmas = f"dmas=[txq0@{self.used_cbdma[0]}],dmathr={dmathr}" + self.launch_testpmd_as_vhost_user(eal_params, self.cores[27:29], + dev=vhost_dev % vhost_dmas) + self.send_and_verify(mode) + self.virtio_user.send_expect("quit", "# ") + self.vhost_user.send_expect("quit", "# ") + time.sleep(2) + self.result_table_print() + + @staticmethod + def vhost_or_virtio_set_one_queue(session): + session.send_expect('start', 'testpmd> ', 120) + session.send_expect('stop', 'testpmd> ', 120) + session.send_expect('port stop all', 'testpmd> ', 120) + session.send_expect('port config all rxq 1', 'testpmd> ', 120) + session.send_expect('port start all', 'testpmd> ', 120) + session.send_expect('start', 'testpmd> ', 120) + time.sleep(5) + + @property + def check_value(self): + check_dict = dict.fromkeys(self.frame_sizes) + linerate = {64: 0.085, 128: 0.12, 256: 0.20, 512: 0.35, 1024: 0.50, 1280: 0.55, 1518: 0.60} + for size in self.frame_sizes: + speed = self.wirespeed(self.nic, size, self.number_of_ports) + check_dict[size] = round(speed * linerate[size], 2) + return check_dict + + def send_and_verify(self, mode, multiple_queue=True): + """ + Send packet with packet generator and verify + """ + for frame_size in self.frame_sizes: + payload_size = frame_size - self.headers_size + tgen_input = [] + rx_port = self.tester.get_local_port(self.dut_ports[0]) + tx_port = self.tester.get_local_port(self.dut_ports[0]) + ip_src = 'src=RandIP()' + if not multiple_queue: + ip_src = "" + + pacp = 'wrpcap("%s/vhost.pcap", [Ether(dst="%s")/IP(%s)/("X"*%d)])' \ + % (self.out_path, self.virtio_mac, ip_src, payload_size) + self.tester.scapy_append(pacp) + tgen_input.append((tx_port, rx_port, "%s/vhost.pcap" % self.out_path)) + + self.tester.scapy_execute() + self.tester.pktgen.clear_streams() + streams = self.pktgen_helper.prepare_stream_from_tginput(tgen_input, 100, + None, self.tester.pktgen) + trans_options = {'delay': 5, 'duration': 20} + _, pps = self.tester.pktgen.measure_throughput(stream_ids=streams, options=trans_options) + Mpps = pps / 1000000.0 + self.verify(Mpps > 0, + "%s can not receive packets of frame size %d" % (self.running_case, frame_size)) + throughput = Mpps * 100 / \ + float(self.wirespeed(self.nic, frame_size, 1)) + + results_row = [frame_size] + results_row.append(mode) + results_row.append(Mpps) + results_row.append(throughput) + self.result_table_add(results_row) + + def tear_down(self): + """ + Run after each test case. + Clear qemu and testpmd to avoid blocking the following TCs + """ + self.bind_cbdma_device_to_kernel() + self.bind_nic_driver(self.dut_ports) + + def tear_down_all(self): + """ + Run after each test suite. + """ + + self.bind_nic_driver(self.dut_ports, self.drivername) + self.dut.close_session(self.vhost_user) + self.dut.close_session(self.virtio_user) +