From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id EE764A0566; Wed, 11 Mar 2020 05:32:10 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id D61DC1BF96; Wed, 11 Mar 2020 05:32:10 +0100 (CET) Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by dpdk.org (Postfix) with ESMTP id 3D0451BF7F for ; Wed, 11 Mar 2020 05:32:09 +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 orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 10 Mar 2020 21:32:08 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,518,1574150400"; d="scan'208";a="261023920" Received: from fmsmsx107.amr.corp.intel.com ([10.18.124.205]) by orsmga002.jf.intel.com with ESMTP; 10 Mar 2020 21:32:08 -0700 Received: from fmsmsx121.amr.corp.intel.com (10.18.125.36) by fmsmsx107.amr.corp.intel.com (10.18.124.205) with Microsoft SMTP Server (TLS) id 14.3.439.0; Tue, 10 Mar 2020 21:32:07 -0700 Received: from shsmsx103.ccr.corp.intel.com (10.239.4.69) by fmsmsx121.amr.corp.intel.com (10.18.125.36) with Microsoft SMTP Server (TLS) id 14.3.439.0; Tue, 10 Mar 2020 21:32:07 -0700 Received: from shsmsx101.ccr.corp.intel.com ([169.254.1.43]) by SHSMSX103.ccr.corp.intel.com ([169.254.4.137]) with mapi id 14.03.0439.000; Wed, 11 Mar 2020 12:32:05 +0800 From: "Tu, Lijuan" To: "Mo, YufengX" , "dts@dpdk.org" , "Han, YingyaX" Thread-Topic: [dts][PATCH V1 1/1] l3fwd: support more features Thread-Index: AQHV8TXhbrzQ33WzVUaK7uakiBV4FahC2ZJg Date: Wed, 11 Mar 2020 04:32:04 +0000 Message-ID: <8CE3E05A3F976642AAB0F4675D0AD20E0BBEB99C@SHSMSX101.ccr.corp.intel.com> References: <20200303083338.5251-1-yufengx.mo@intel.com> <20200303083338.5251-2-yufengx.mo@intel.com> In-Reply-To: <20200303083338.5251-2-yufengx.mo@intel.com> Accept-Language: zh-CN, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-version: 11.2.0.6 dlp-reaction: no-action x-originating-ip: [10.239.127.40] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dts] [PATCH V1 1/1] l3fwd: support more features 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" Applied, thanks > -----Original Message----- > From: Mo, YufengX > Sent: Tuesday, March 3, 2020 4:34 PM > To: dts@dpdk.org; Tu, Lijuan ; Han, YingyaX > > Cc: Mo, YufengX > Subject: [dts][PATCH V1 1/1] l3fwd: support more features >=20 >=20 > #. add IP/NONE stream format support, user can select udp/raw stream in > l3fwd_basic.cfg. > #. add wait time after l3fwd start, user can set this time interval in su= ite.cfg > file. > #. user can set l3fwd restart or not in suite.cfg file. If not set, not r= estart > l3fwd when command option is the same as previous one. > #. user can set a time interval after pktgen traffic is stopped in suite.= cfg file. > #. unify macro usage. >=20 > Signed-off-by: yufengmx > --- > tests/l3fwd_base.py | 175 ++++++++++++++++++++++++++++++++++++-------- > 1 file changed, 144 insertions(+), 31 deletions(-) >=20 > diff --git a/tests/l3fwd_base.py b/tests/l3fwd_base.py index > 5e3b68d..431c28e 100644 > --- a/tests/l3fwd_base.py > +++ b/tests/l3fwd_base.py > @@ -37,12 +37,12 @@ import time > import traceback > import texttable > import json > +from enum import Enum > from pprint import pformat > from itertools import product > from copy import deepcopy >=20 > from config import SuiteConf > -from settings import HEADER_SIZE > from packet import Packet > from pktgen import TRANSMIT_CONT, PKTGEN_TREX, PKTGEN_IXIA from > utils import convert_int2ip, convert_ip2int @@ -50,13 +50,48 @@ from > exception import VerifyFailure import utils >=20 >=20 > +class MATCH_MODE(Enum): > + # LPM(longest prefix match) mode > + LPM =3D 'lpm' > + # EM(Exact-Match) mode > + EM =3D 'em' > + > # LPM(longest prefix match) mode > -LPM =3D 'lpm' > +LPM =3D MATCH_MODE.LPM > # EM(Exact-Match) mode > -EM =3D 'em' > -# stream types > -L3_IPV6 =3D 'ipv6' > -L3_IPV4 =3D 'ipv4' > +EM =3D MATCH_MODE.EM > + > + > +# stream internet protocol layer types > +class IP_TYPE(Enum): > + V6 =3D 'ipv6' > + V4 =3D 'ipv4' > + > +L3_IPV6 =3D IP_TYPE.V6 > +L3_IPV4 =3D IP_TYPE.V4 > + > + > +class STREAM_TYPE(Enum): > + UDP =3D 'UDP' > + RAW =3D 'RAW' > + > + > +HEADER_SIZE =3D { > + 'ether': 18, > + 'ipv4': 20, > + 'ipv6': 40, > + 'udp': 8, > + 'tcp': 20, > + 'vlan': 8, } > + > + > +def get_enum_name(value, enum_cls): > + for _, enum_name in list(enum_cls.__members__.items()): > + if value =3D=3D enum_name.value: > + return enum_name > + else: > + msg =3D f"{value} not define in Enum class {enum_cls}" > + raise Exception(msg) >=20 >=20 > class L3fwdBase(object): > @@ -66,10 +101,15 @@ class L3fwdBase(object): > self.__white_list =3D None > self.__socket =3D socket > self.__nic_name =3D self.nic > - self.__pkt_typ =3D 'udp' > + self.__pkt_typ =3D STREAM_TYPE.RAW > # for result > self.__cur_case =3D None > self.__json_results =3D {} > + # binary file process > + self.__l3fwd_restart =3D True > + self.__pre_l3fwd_cmd =3D None > + self.__l3fwd_wait_up =3D 0 > + self.__traffic_stop_wait_time =3D 0 >=20 > @property > def output_path(self): > @@ -120,30 +160,52 @@ class L3fwdBase(object): > 'action': 'random', }, }, } > return layers, fields_config >=20 > + def ___get_pkt_layers(self, pkt_type): > + if pkt_type in list(Packet.def_packet.keys()): > + return deepcopy(Packet.def_packet.get(pkt_type).get('layers'= )) > + local_def_packet =3D { > + 'IPv6_RAW': ['ether', 'ipv6', 'raw'], > + } > + layers =3D local_def_packet.get(pkt_type) > + if not layers: > + msg =3D f"{pkt_type} not set in framework/packet.py, nor in = local" > + raise VerifyFailure(msg) > + return layers > + > def __get_pkt_len(self, pkt_type, ip_type=3D'ip', frame_size=3D64): > - headers_size =3D sum( > - map(lambda x: HEADER_SIZE[x], ['eth', ip_type, pkt_type])) > + layers =3D self.___get_pkt_layers(pkt_type) > + if 'raw' in layers: > + layers.remove('raw') > + headers_size =3D sum(map(lambda x: HEADER_SIZE[x], layers)) > pktlen =3D frame_size - headers_size > return pktlen >=20 > def __get_frame_size(self, name, frame_size): > - _frame_size =3D 66 if name =3D=3D L3_IPV6 and frame_size =3D=3D = 64 else \ > + _frame_size =3D 66 if name is IP_TYPE.V6 and frame_size =3D=3D 6= 4 > + else \ > frame_size > return _frame_size >=20 > + def __get_pkt_type_name(self, ip_layer): > + if ip_layer is IP_TYPE.V4: > + name =3D 'IP_RAW' if self.__pkt_typ =3D=3D STREAM_TYPE.RAW e= lse \ > + self.__pkt_typ.value > + else: > + name =3D 'IPv6_' + self.__pkt_typ.value > + return name > + > def __config_stream(self, stm_name, layers=3DNone, frame_size=3D64): > _framesize =3D self.__get_frame_size(stm_name, frame_size) > payload_size =3D self.__get_pkt_len( > - self.__pkt_typ, > - 'ip' if stm_name =3D=3D L3_IPV4 else 'ipv6', _framesize) > + self.__get_pkt_type_name(stm_name), > + 'ip' if stm_name is IP_TYPE.V4 else 'ipv6', _framesize) > # set streams for traffic > pkt_configs =3D { > - L3_IPV4: { > - 'type': self.__pkt_typ.upper(), > + IP_TYPE.V4: { > + 'type': self.__get_pkt_type_name(IP_TYPE.V4), > 'pkt_layers': { > 'raw': {'payload': ['58'] * payload_size}}}, > - L3_IPV6: { > - 'type': 'IPv6_' + self.__pkt_typ.upper(), > + IP_TYPE.V6: { > + 'type': self.__get_pkt_type_name(IP_TYPE.V6), > 'pkt_layers': { > 'raw': {'payload': ['58'] * payload_size}}}, } > if stm_name not in pkt_configs.keys(): > @@ -160,8 +222,16 @@ class L3fwdBase(object): > def __get_pkt_inst(self, pkt_config): > pkt_type =3D pkt_config.get('type') > pkt_layers =3D pkt_config.get('pkt_layers') > - pkt =3D Packet(pkt_type=3Dpkt_type) > - for layer in pkt_layers.keys(): > + _layers =3D self.___get_pkt_layers(pkt_type) > + if pkt_type not in Packet.def_packet.keys(): > + pkt =3D Packet() > + pkt.pkt_cfgload =3D True > + pkt.assign_layers(_layers) > + else: > + pkt =3D Packet(pkt_type=3Dpkt_type) > + for layer in list(pkt_layers.keys()): > + if layer not in _layers: > + continue > pkt.config_layer(layer, pkt_layers[layer]) > self.logger.debug(pformat(pkt.pktgen.pkt.command())) >=20 > @@ -174,9 +244,11 @@ class L3fwdBase(object): > raise VerifyFailure(msg) > flows_configs =3D {} > for name, mode_configs in flows.items(): > + _name =3D get_enum_name(name.lower(), IP_TYPE) > for mode, configs in mode_configs.items(): > + _mode =3D get_enum_name(mode.lower(), MATCH_MODE) > for index, config in enumerate(configs): > - if mode =3D=3D LPM: > + if _mode is MATCH_MODE.LPM: > # under LPM mode, one port only set one stream > if index >=3D len(self.__valports): > break > @@ -185,7 +257,7 @@ class L3fwdBase(object): > _layer =3D {'ether': {'dst': dmac, }, } > _layer2, fields_config =3D \ > self.__get_ipv4_lpm_vm_config(config) \ > - if name =3D=3D L3_IPV4 else \ > + if _name is IP_TYPE.V4 else \ > self.__get_ipv6_lpm_vm_config(config) > _layer.update(_layer2) > else: > @@ -197,7 +269,7 @@ class L3fwdBase(object): > _layer =3D {'ether': {'dst': dmac, }, } > _layer.update(config) > fields_config =3D None > - flows_configs.setdefault((name, mode), []).append( > + flows_configs.setdefault((_name, _mode), > + []).append( > [_layer, fields_config]) > return flows_configs >=20 > @@ -261,6 +333,9 @@ class L3fwdBase(object): > stream_ids =3D self.__add_stream_to_pktgen(streams, stream_optio= n) > # run packet generator > result =3D self.tester.pktgen.measure(stream_ids, traffic_opt) > + self.logger.debug( > + f"wait {self.__traffic_stop_wait_time} second after traffic = stop") > + time.sleep(self.__traffic_stop_wait_time) > return result >=20 > def __throughput(self, l3_proto, mode, frame_size): > @@ -356,16 +431,16 @@ class L3fwdBase(object): > "define RTE_TEST_TX_DESC_DEFAULT.*$/" > "define RTE_TEST_TX_DESC_DEFAULT 2048/' " > "./examples/l3fwd/l3fwd.h")) > - self.__l3fwd_em =3D self.__init_l3fwd(EM) > - self.__l3fwd_lpm =3D self.__init_l3fwd(LPM) > + self.__l3fwd_em =3D self.__init_l3fwd(MATCH_MODE.EM) > + self.__l3fwd_lpm =3D self.__init_l3fwd(MATCH_MODE.LPM) >=20 > def __init_l3fwd(self, mode): > """ > Prepare long prefix match table, __replace P(x) port pattern > """ > - l3fwd_method =3D '_'.join(['l3fwd', mode]) > + l3fwd_method =3D '_'.join(['l3fwd', mode.value]) > self.d_con("make clean -C examples/l3fwd") > - flg =3D 1 if LPM in l3fwd_method else 0 > + flg =3D 1 if mode is MATCH_MODE.LPM else 0 > out =3D self.dut.build_dpdk_apps( > "./examples/l3fwd", > "USER_FLAGS=3D-DAPP_LOOKUP_METHOD=3D{}".format(flg)) > @@ -379,7 +454,7 @@ class L3fwdBase(object): > return l3fwd_bin >=20 > def __start_l3fwd(self, mode, core_mask, config, frame_size): > - bin =3D self.__l3fwd_em if mode =3D=3D EM else self.__l3fwd_lpm > + bin =3D self.__l3fwd_em if mode is MATCH_MODE.EM else > + self.__l3fwd_lpm > # Start L3fwd application > command_line =3D ( > "{bin} " > @@ -400,15 +475,39 @@ class L3fwdBase(object): > command_line +=3D " --parse-ptype" > if frame_size > 1518: > command_line +=3D " --enable-jumbo --max-pkt-len %d" % frame= _size > + # ignore duplicate start binary with the same option > + if self.__l3fwd_restart_check(command_line): > + return > self.d_con([command_line, "L3FWD:", 120]) > self.__is_l3fwd_on =3D True > # wait several second for l3fwd checking ports link status. > - # It is aimed to make sure trex detect link up status. > - time.sleep(2 * len(self.__valports)) > + # It is aimed to make sure packet generator detect link up statu= s. > + wait_time =3D self.__l3fwd_wait_up if self.__l3fwd_wait_up else = \ > + 2 * len(self.__valports) > + self.logger.debug(f"wait {wait_time} seconds for port link up") > + time.sleep(wait_time) > + > + def __l3fwd_restart_check(self, command_line): > + if self.__l3fwd_restart: > + self.__pre_l3fwd_cmd =3D None > + return False > + > + if self.__pre_l3fwd_cmd and self.__pre_l3fwd_cmd =3D=3D command_= line: > + self.logger.debug( > + ('<{}> is the same command as previous one, ' > + 'ignore re-start l3fwd').format(command_line)) > + return True > + else: > + self.__pre_l3fwd_cmd =3D None > + self.__close_l3fwd() > + self.__pre_l3fwd_cmd =3D command_line > + return False >=20 > def __close_l3fwd(self): > if not self.__is_l3fwd_on: > return > + if not self.__l3fwd_restart and self.__pre_l3fwd_cmd: > + return > self.d_con("^C") > self.__is_l3fwd_on =3D False >=20 > @@ -610,11 +709,12 @@ class L3fwdBase(object): > self.__close_l3fwd() > if result: > results.append([config, frame_size, result]) > - self.__check_throughput_result(l3_proto, results, mode) > + self.__check_throughput_result(l3_proto, results, > + mode.value) > except Exception as e: > self.logger.error(traceback.format_exc()) > except_content =3D e > finally: > + self.__pre_l3fwd_cmd =3D None > self.__close_l3fwd() >=20 > # re-raise verify exception result @@ -638,11 +738,12 @@ class > L3fwdBase(object): > self.__close_l3fwd() > if result: > results.append([config, frame_size, result]) > - self.__check_rfc2544_result(l3_proto, results, mode) > + self.__check_rfc2544_result(l3_proto, results, mode.value) > except Exception as e: > self.logger.error(traceback.format_exc()) > except_content =3D e > finally: > + self.__pre_l3fwd_cmd =3D None > self.__close_l3fwd() >=20 > # re-raise verify exception result @@ -694,7 +795,19 @@ class > L3fwdBase(object): > suite_conf =3D SuiteConf('l3fwd_base') > flows =3D suite_conf.suite_cfg.get('l3fwd_flows') > test_content['flows'] =3D flows > - # parse port config of l3fwd > + # set stream format type > + stream_type =3D suite_conf.suite_cfg.get('stream_type') > + if stream_type and isinstance(stream_type, str): > + self.__pkt_typ =3D get_enum_name(stream_type.upper(), > STREAM_TYPE) > + else: > + msg =3D f"use default stream format {self.__pkt_typ.value}" > + self.logger.warning(msg) > + # binary file process setting > + self.__l3fwd_wait_up =3D test_content.get('l3fwd_wait_up', 0) > + self.__l3fwd_restart =3D test_content.get('l3fwd_restart', True) > + self.__traffic_stop_wait_time =3D \ > + test_content.get('traffic_stop_wait_time', 0) > + # parse port config of l3fwd suite > port_configs, frame_sizes =3D self.__get_test_configs( > test_content.get('test_parameters'), > len(self.__valports), self.__socket) > -- > 2.21.0