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 C3109A00E6 for ; Mon, 5 Aug 2019 07:49:58 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 0B3B01BE64; Mon, 5 Aug 2019 07:49:58 +0200 (CEST) Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by dpdk.org (Postfix) with ESMTP id CC46C1BE44 for ; Mon, 5 Aug 2019 07:49:55 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 04 Aug 2019 22:49:55 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,348,1559545200"; d="scan'208";a="372969518" Received: from dpdk-moyufen01.sh.intel.com ([10.67.111.77]) by fmsmga005.fm.intel.com with ESMTP; 04 Aug 2019 22:49:54 -0700 From: yufengmx To: dts@dpdk.org Cc: yufengmx Date: Mon, 5 Aug 2019 13:50:40 +0800 Message-Id: <1564984244-151448-7-git-send-email-yufengx.mo@intel.com> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1564984244-151448-1-git-send-email-yufengx.mo@intel.com> References: <1564984244-151448-1-git-send-email-yufengx.mo@intel.com> Subject: [dts] [PATCH V1 6/10] [next]framework/pktgen_base: add new feature and fix 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" internal bug *. add test method(latency/loss/throughput) delay/duration options new usage definition and relevant process source code. *. set delay option to be the warm up time after start transmission. *. add __get_single_throughput_statistic/__get_multi_throughput_statistic methods to realize measure_throughput support return several throughput numbers in a duration. *. set duration option default value to 10 second. *. add test method(latency/loss/throughput/rfc2544) options parameter usage comment, which is the same as doc pktgen_prog_guide.rst. *. add missing start traffic option input in measure_throughput method. *. remove logger format setting after import libs to fix dts redundant logs. *. set part of information logger display to debug level. *. remove un-used libs import. *. fix pep8 issue. Signed-off-by: yufengmx --- framework/pktgen_base.py | 179 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 149 insertions(+), 30 deletions(-) diff --git a/framework/pktgen_base.py b/framework/pktgen_base.py index e9d3fcb..8915ac5 100644 --- a/framework/pktgen_base.py +++ b/framework/pktgen_base.py @@ -29,27 +29,22 @@ # (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 os import time import logging from abc import abstractmethod from copy import deepcopy -from logger import getLogger from pprint import pformat from config import PktgenConf +from logger import getLogger, set_verbose # packet generator name -from settings import PKTGEN_DPDK, PKTGEN_TREX, PKTGEN_IXIA, PKTGEN +from settings import (PKTGEN_DPDK, PKTGEN_TREX, PKTGEN_IXIA, PKTGEN, + load_global_setting, DEBUG_SETTING) # macro definition TRANSMIT_CONT = 'continuous' TRANSMIT_M_BURST = 'multi_burst' TRANSMIT_S_BURST = 'single_burst' -# set logger -FORMAT = '%(message)s' -logging.basicConfig(format=FORMAT) -logger = logging.getLogger(os.path.basename(__file__)[:-3].upper()) -logger.setLevel(logging.INFO) class PacketGenerator(object): @@ -57,8 +52,11 @@ class PacketGenerator(object): Basic class for packet generator, define basic function for each kinds of generators """ + def __init__(self, tester): self.logger = getLogger(PKTGEN) + if load_global_setting(DEBUG_SETTING) == "yes": + set_verbose() self.tester = tester self.__streams = [] self._ports_map = [] @@ -82,8 +80,8 @@ class PacketGenerator(object): tester_pci = info['pci'] if tester_pci == gen_pci: msg = "gen port {0} map test port {1}".format( - port_id, port_idx) - self.logger.info(msg) + port_id, port_idx) + self.logger.debug(msg) return port_idx else: port = -1 @@ -105,15 +103,15 @@ class PacketGenerator(object): tester_pci = info['pci'] port = self._get_gen_port(tester_pci) msg = "test port {0} map gen port {1}".format(port_id, port) - self.logger.info(msg) + self.logger.debug(msg) except: port = -1 return port def add_stream(self, tx_port, rx_port, pcap_file): - pktgen_tx_port = self._convert_tester_port(tx_port) - pktgen_rx_port = self._convert_tester_port(rx_port) + pktgen_tx_port = self._convert_tester_port(tx_port) + pktgen_rx_port = self._convert_tester_port(rx_port) stream_id = len(self.__streams) stream = {'tx_port': pktgen_tx_port, @@ -163,39 +161,105 @@ class PacketGenerator(object): def reset_streams(self): self.__streams = [] - def measure_throughput(self, stream_ids=[], options={}): - """ - Measure throughput on each tx ports - """ + def __warm_up_pktgen(self, stream_ids, options, delay): + ''' run warm up traffic before start main traffic ''' + if not delay: + return + msg = 'run traffic {0}s to warm up {1} packet generator '.format( + delay, self.pktgen_type) + self.logger.info(msg) + self._start_transmission(stream_ids, options) + time.sleep(delay) + self._stop_transmission(stream_ids) + + def __get_single_throughput_statistic(self, stream_ids): bps_rx = [] pps_rx = [] - self._prepare_transmission(stream_ids=stream_ids) - self._start_transmission(stream_ids) - - delay = options.get('delay') or 5 - time.sleep(delay) used_rx_port = [] + msg = 'begin get port statistic ...' + self.logger.info(msg) for stream_id in stream_ids: if self.__streams[stream_id]['rx_port'] not in used_rx_port: rxbps_rates, rxpps_rates = self._retrieve_port_statistic( - stream_id, 'throughput') + stream_id, 'throughput') used_rx_port.append(self.__streams[stream_id]['rx_port']) bps_rx.append(rxbps_rates) pps_rx.append(rxpps_rates) - self._stop_transmission(stream_id) - bps_rx_total = self._summary_statistic(bps_rx) pps_rx_total = self._summary_statistic(pps_rx) - self.logger.info("throughput: pps_rx %f, bps_rx %f" % (pps_rx_total, bps_rx_total)) + self.logger.info( + "throughput: pps_rx %f, bps_rx %f" % (pps_rx_total, bps_rx_total)) return bps_rx_total, pps_rx_total + def __get_multi_throughput_statistic(self, stream_ids, duration, interval): + """ + duration: define the measure duration (second) + interval: define the interval of get throughput number (second) + + Return: a list of throughput instead of a single tuple of pps/bps rate + """ + time_elapsed = 0 + stats = [] + while time_elapsed < duration: + time.sleep(interval) + stats.append(self.__get_single_throughput_statistic(stream_ids)) + time_elapsed += interval + return stats + + def measure_throughput(self, stream_ids=[], options={}): + """ + Measure throughput on each tx ports + + options usage: + rate: + port rate percent, float(0--100). Default value is 100. + + delay: + warm up time before start main traffic. If it is set, it will start + a delay time traffic to make sure packet generator under good status. + Warm up flow is ignored by default. + + interval: + a interval time of get throughput statistic (second) + If set this key value, pktgen will return several throughput statistic + data within a duration traffic. If not set this key value, only return one statistic + data. It is ignored by default. + + duration: + traffic lasting time(second). Default value is 10 second. + """ + interval = options.get('interval') + duration = options.get('duration') or 10 + delay = options.get('delay') + self._prepare_transmission(stream_ids=stream_ids) + # start warm up traffic + self.__warm_up_pktgen(stream_ids, options, delay) + # main traffic + self._start_transmission(stream_ids, options) + # keep traffic within a duration time and get throughput statistic + if interval and duration: + stats = self.__get_multi_throughput_statistic( + stream_ids, duration, interval) + else: + time.sleep(duration) + stats = self.__get_single_throughput_statistic(stream_ids) + self._stop_transmission(stream_ids) + return stats + def _measure_loss(self, stream_ids=[], options={}): """ Measure lost rate on each tx/rx ports """ + delay = options.get('delay') + duration = options.get('duration') or 10 self._prepare_transmission(stream_ids=stream_ids) + # start warm up traffic + self.__warm_up_pktgen(stream_ids, options, delay) + # main traffic self._start_transmission(stream_ids, options) + # keep traffic within a duration time + time.sleep(duration) self._stop_transmission(None) result = {} used_rx_port = [] @@ -216,6 +280,19 @@ class PacketGenerator(object): return result def measure_loss(self, stream_ids=[], options={}): + ''' + options usage: + rate: + port rate percent, float(0--100). Default value is 100. + + delay: + warm up time before start main traffic. If it is set, it will + start a delay time traffic to make sure packet generator + under good status. Warm up flow is ignored by default. + + duration: + traffic lasting time(second). Default value is 10 second. + ''' result = self._measure_loss(stream_ids, options) # here only to make sure that return value is the same as dts/etgen format # In real testing scenario, this method can offer more data than it @@ -224,9 +301,28 @@ class PacketGenerator(object): def measure_latency(self, stream_ids=[], options={}): """ Measure latency on each tx/rx ports + + options usage: + rate: + port rate percent, float(0--100). Default value is 100. + + delay: + warm up time before start main traffic. If it is set, it will + start a delay time transmission to make sure packet generator + under correct status. Warm up flow is ignored by default. + + duration: + traffic lasting time(second). Default value is 10 second. """ + delay = options.get('delay') + duration = options.get('duration') or 10 self._prepare_transmission(stream_ids=stream_ids, latency=True) + # start warm up traffic + self.__warm_up_pktgen(stream_ids, options, delay) + # main traffic self._start_transmission(stream_ids, options) + # keep traffic within a duration time + time.sleep(duration) self._stop_transmission(None) result = {} @@ -254,7 +350,26 @@ class PacketGenerator(object): return True def measure_rfc2544(self, stream_ids=[], options={}): - """ check loss rate with rate percent dropping """ + """ check loss rate with rate percent dropping + + options usage: + rate: + port rate percent at first round testing(0 ~ 100), default is 100. + + pdr: + permit packet drop rate, , default is 0. + + drop_step: + port rate percent drop step(0 ~ 100), default is 1. + + delay: + warm up time before start main traffic. If it is set, it will + start a delay time traffic to make sure packet generator + under good status. Warm up flow is ignored by default. + + duration: + traffic lasting time(second). Default value is 10 second. + """ loss_rate_table = [] rate_percent = float(100) permit_loss_rate = options.get('pdr') or 0 @@ -263,7 +378,7 @@ class PacketGenerator(object): result = self._measure_loss(stream_ids, options) status = self._check_loss_rate(result, permit_loss_rate) loss_rate_table.append( - [options.get('rate') or rate_percent, result]) + [options.get('rate') or rate_percent, result]) # if first time loss rate is ok, ignore left flow if status: # return data is the same with dts/etgen format @@ -271,6 +386,9 @@ class PacketGenerator(object): # here only pick one return result.values()[0] _options = deepcopy(options) + # if warm up option 'delay' is set, ignore it in next work flow + if 'delay' in _options: + _options.pop('delay') while not status and rate_percent > 0: rate_percent = rate_percent - rate_step if rate_percent <= 0: @@ -320,7 +438,7 @@ class PacketGenerator(object): traffic_pps_min = pps if traffic_pps_max - traffic_pps_min < step: break - pps = (traffic_pps_max - traffic_pps_min)/2 + traffic_pps_min + pps = (traffic_pps_max - traffic_pps_min) / 2 + traffic_pps_min self.logger.info("zero loss pps is %f" % last_no_lost_mult) # use last result as return data to keep the same with dts/etgen format @@ -397,4 +515,5 @@ class PacketGenerator(object): pass -class DpdkPacketGenerator(PacketGenerator): pass # not implemented \ No newline at end of file +class DpdkPacketGenerator(PacketGenerator): + pass # not implemented -- 1.9.3