From: "Chen, Zhaoyan" <zhaoyan.chen@intel.com>
To: "Mo, YufengX" <yufengx.mo@intel.com>,
"dts@dpdk.org" <dts@dpdk.org>,
"Wang, Yinan" <yinan.wang@intel.com>,
"Ma, LihongX" <lihongx.ma@intel.com>
Cc: "Mo, YufengX" <yufengx.mo@intel.com>,
"Chen, Zhaoyan" <zhaoyan.chen@intel.com>
Subject: Re: [dts] [PATCH V3 3/5] framework/pktgen_base: add new features
Date: Thu, 2 Jan 2020 03:29:12 +0000 [thread overview]
Message-ID: <9DEEADBC57E43F4DA73B571777FECECA41E76D0B@SHSMSX104.ccr.corp.intel.com> (raw)
In-Reply-To: <20191129090315.60124-4-yufengx.mo@intel.com>
Acked-by: Zhaoyan Chen <zhaoyan.chen@intel.com>
Regards,
Zhaoyan Chen
> -----Original Message-----
> From: dts <dts-bounces@dpdk.org> On Behalf Of yufengmx
> Sent: Friday, November 29, 2019 5:03 PM
> To: dts@dpdk.org; Wang, Yinan <yinan.wang@intel.com>; Ma, LihongX
> <lihongx.ma@intel.com>
> Cc: Mo, YufengX <yufengx.mo@intel.com>
> Subject: [dts] [PATCH V3 3/5] framework/pktgen_base: add new features
>
>
> *. 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 a callback to deal with executing other tools query actions in throughput traffic
> lasting status.
> *. add measure_rfc2544_dichotomy method.
>
> Signed-off-by: yufengmx <yufengx.mo@intel.com>
> ---
> framework/pktgen_base.py | 244 ++++++++++++++++++++++++++++++++++++---
> 1 file changed, 228 insertions(+), 16 deletions(-)
>
> diff --git a/framework/pktgen_base.py b/framework/pktgen_base.py index
> 7855f6f..75c3036 100644
> --- a/framework/pktgen_base.py
> +++ b/framework/pktgen_base.py
> @@ -81,7 +81,7 @@ class PacketGenerator(object):
> return port_idx
> else:
> port = -1
> - except:
> + except Exception as e:
> port = -1
>
> return port
> @@ -100,7 +100,7 @@ class PacketGenerator(object):
> port = self._get_gen_port(tester_pci)
> msg = "test port {0} map gen port {1}".format(port_id, port)
> self.logger.debug(msg)
> - except:
> + except Exception as e:
> port = -1
>
> return port
> @@ -157,39 +157,120 @@ class PacketGenerator(object):
> def reset_streams(self):
> self.__streams = []
>
> - def measure_throughput(self, stream_ids=[], options={}):
> - """
> - Measure throughput on each tx ports
> - """
> - bps_rx = []
> - pps_rx = []
> - self._prepare_transmission(stream_ids=stream_ids)
> + def __warm_up_pktgen(self, stream_ids, options, delay):
> + ''' run warm up traffic before start main traffic '''
> + if not delay:
> + return
> + msg = '{1} packet generator: run traffic {0}s to warm up ... '.format(
> + delay, self.pktgen_type)
> + self.logger.info(msg)
> self._start_transmission(stream_ids, options)
> -
> - delay = options.get('delay') or 5
> time.sleep(delay)
> + self._stop_transmission(stream_ids)
> + self._clear_streams()
> +
> + def __get_single_throughput_statistic(self, stream_ids):
> + bps_rx = []
> + pps_rx = []
> 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, callback=None):
> + """
> + duration: traffic duration (second)
> + interval: interval of get throughput statistics (second)
> + callback: a callback method of suite, which is used to do some actions
> + during traffic lasting.
> +
> + 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))
> + if callback and callable(callback):
> + callback()
> + 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.
> +
> + callback:
> + this key works with ``interval`` key. If it is set, the callback
> + of suite level will be executed after getting throughput statistic.
> + callback method should define as below, don't add sleep in this method.
> +
> + def callback(self):
> + xxxx()
> +
> + duration:
> + traffic lasting time(second). Default value is 10 second.
> + """
> + interval = options.get('interval')
> + callback = options.get('callback')
> + 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)
> + # keep traffic within a duration time and get throughput statistic
> + if interval and duration:
> + stats = self.__get_multi_throughput_statistic(
> + stream_ids, duration, interval, callback)
> + 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 = []
> @@ -210,6 +291,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 @@ -218,9
> +312,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 = {}
> @@ -248,7 +361,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 = options.get('rate') or float(100)
> permit_loss_rate = options.get('pdr') or 0 @@ -265,6 +397,9 @@ class
> PacketGenerator(object):
> tx_num, rx_num = result.values()[0][1:]
> return rate_percent, tx_num, rx_num
> _options = deepcopy(options)
> + # if warm up option 'delay' is set, ignore it in next work flow
> + if 'delay' in _options:
> + _options.pop('delay')
> if 'rate' in _options:
> _options.pop('rate')
> while not status and rate_percent > 0:
> @@ -328,6 +463,81 @@ class PacketGenerator(object):
> # here only pick one
> return loss_pps_table[-1][1].values()[0]
>
> + def measure_rfc2544_dichotomy(self, stream_ids=[], options={}):
> + """ check loss rate using dichotomy algorithm
> +
> + options usage:
> + 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.
> +
> + min_rate:
> + lower bound rate percent , default is 0.
> +
> + max_rate:
> + upper bound rate percent , default is 100.
> +
> + pdr:
> + permit packet drop rate(<1.0), default is 0.
> +
> + accuracy :
> + dichotomy algorithm accuracy, default 0.001.
> + """
> + max_rate = options.get('max_rate') or 100.0
> + min_rate = options.get('min_rate') or 0.0
> + accuracy = options.get('accuracy') or 0.001
> + permit_loss_rate = options.get('pdr') or 0.0
> + duration = options.get('duration') or 10.0
> + # start warm up traffic
> + delay = options.get('delay')
> + _options = {'duration': duration}
> + self.__warm_up_pktgen(stream_ids, _options, delay)
> + # traffic parameters for dichotomy algorithm
> + loss_rate_table = []
> + hit_result = None
> + rate = traffic_rate_max = max_rate
> + traffic_rate_min = min_rate
> + while True:
> + # run loss rate testing
> + _options = {'duration': duration}
> + result = self._measure_loss(stream_ids, _options)
> + loss_rate_table.append([rate, result])
> + status = self._check_loss_rate(result, permit_loss_rate)
> + # if upper bound rate percent hit, quit the left flow
> + if rate == max_rate and status:
> + hit_result = result
> + break
> + # if lower bound rate percent not hit, quit the left flow
> + if rate == min_rate and not status:
> + break
> + if status:
> + traffic_rate_min = rate
> + hit_result = result
> + else:
> + traffic_rate_max = rate
> + if traffic_rate_max - traffic_rate_min < accuracy:
> + break
> + rate = (traffic_rate_max - traffic_rate_min)/2 + traffic_rate_min
> + self._clear_streams()
> + # set stream rate percent to custom value
> + self._set_stream_rate_percent(rate)
> +
> + if not hit_result:
> + msg = ('expected permit loss rate <{0}>'
> + 'not between rate {1} and rate {2}').format(
> + permit_loss_rate, max_rate, min_rate)
> + self.logger.error(msg)
> + self.logger.info(pformat(loss_rate_table))
> + else:
> + self.logger.debug(pformat(loss_rate_table))
> + self.logger.info("zero loss rate is %f" % rate)
> +
> + return hit_result
> +
> def measure(self, stream_ids, traffic_opt):
> '''
> use as an unify interface method for packet generator @@ -343,6 +553,8 @@
> class PacketGenerator(object):
> result = self.measure_rfc2544(stream_ids, traffic_opt)
> elif method == 'rfc2544_with_pps':
> result = self.measure_rfc2544_with_pps(stream_ids, traffic_opt)
> + elif method == 'rfc2544_dichotomy':
> + result = self.measure_rfc2544_dichotomy(stream_ids,
> + traffic_opt)
> else:
> result = None
>
> --
> 2.21.0
next prev parent reply other threads:[~2020-01-02 3:29 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-11-29 9:03 [dts] [PATCH V3 0/5] dts/pktgen: " yufengmx
2019-11-29 9:03 ` [dts] [PATCH V3 1/5] conf/pktgen: remove un-used optons yufengmx
2020-01-02 3:29 ` Chen, Zhaoyan
2019-11-29 9:03 ` [dts] [PATCH V3 2/5] doc/dts_gsg/pktgen_prog_guide: update description yufengmx
2020-01-02 3:29 ` Chen, Zhaoyan
2019-11-29 9:03 ` [dts] [PATCH V3 3/5] framework/pktgen_base: add new features yufengmx
2020-01-02 3:29 ` Chen, Zhaoyan [this message]
2019-11-29 9:03 ` [dts] [PATCH V3 4/5] framework/pktgen_ixia: " yufengmx
2019-11-29 9:03 ` [dts] [PATCH V3 5/5] framework/pktgen_trex: " yufengmx
2020-01-02 3:29 ` Chen, Zhaoyan
2020-01-02 3:28 ` [dts] [PATCH V3 0/5] dts/pktgen: " Chen, Zhaoyan
2020-01-02 5:04 ` Tu, Lijuan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=9DEEADBC57E43F4DA73B571777FECECA41E76D0B@SHSMSX104.ccr.corp.intel.com \
--to=zhaoyan.chen@intel.com \
--cc=dts@dpdk.org \
--cc=lihongx.ma@intel.com \
--cc=yinan.wang@intel.com \
--cc=yufengx.mo@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).