From fcce2ca13e7dacebf719fd9f7a6dcc8fb24f56ef Mon Sep 17 00:00:00 2001 From: Peter Mikus Date: Fri, 10 Jan 2020 12:44:45 +0000 Subject: [PATCH] Performance: TRex approximatedDuration and approximateRate - API to provide duration for send and receive traffic Signed-off-by: Peter Mikus Change-Id: Id186a200be66b7703348e6fd3099ffd405e915ae --- resources/libraries/python/TrafficGenerator.py | 19 +++++++++++++-- .../robot/performance/performance_utils.robot | 8 +++++-- resources/tools/trex/trex_stateless_profile.py | 27 ++++++++++++++-------- resources/tools/trex/trex_stateless_stop.py | 7 +++--- 4 files changed, 44 insertions(+), 17 deletions(-) diff --git a/resources/libraries/python/TrafficGenerator.py b/resources/libraries/python/TrafficGenerator.py index 4e3a5493bd..539ced584a 100644 --- a/resources/libraries/python/TrafficGenerator.py +++ b/resources/libraries/python/TrafficGenerator.py @@ -151,6 +151,8 @@ class TrafficGenerator(AbstractMeasurer): self._sent = None self._latency = None self._received = None + self._approximated_rate = None + self._approximated_duration = None # Measurement input fields, needed for async stop result. self._start_time = None self._rate = None @@ -204,6 +206,15 @@ class TrafficGenerator(AbstractMeasurer): """ return self._latency + def get_approximated_rate(self): + """Return approximated rate computed as ratio of transmited packets over + duration of trial. + + :returns: Approximated rate. + :rtype: str + """ + return self._approximated_rate + # TODO: pylint says disable=too-many-locals. # A fix is developed in https://gerrit.fd.io/r/c/csit/+/22221 def initialize_traffic_generator( @@ -460,9 +471,12 @@ class TrafficGenerator(AbstractMeasurer): self._received = self._result.split(u", ")[1].split(u"=", 1)[1] self._sent = self._result.split(u", ")[2].split(u"=", 1)[1] self._loss = self._result.split(u", ")[3].split(u"=", 1)[1] + self._approximated_duration = \ + self._result.split(u", ")[5].split(u"=", 1)[1] + self._approximated_rate = self._result.split(u", ")[6].split(u"=", 1)[1] self._latency = list() - self._latency.append(self._result.split(u", ")[4].split(u"=", 1)[1]) - self._latency.append(self._result.split(u", ")[5].split(u"=", 1)[1]) + self._latency.append(self._result.split(u", ")[7].split(u"=", 1)[1]) + self._latency.append(self._result.split(u", ")[8].split(u"=", 1)[1]) def trex_stl_stop_remote_exec(self, node): """Execute script on remote node over ssh to stop running traffic. @@ -748,6 +762,7 @@ class TrafficGenerator(AbstractMeasurer): duration, transmit_rate, transmit_count, loss_count ) measurement.latency = self.get_latency_int() + measurement.approximated_rate = self.get_approximated_rate() return measurement def measure(self, duration, transmit_rate): diff --git a/resources/libraries/robot/performance/performance_utils.robot b/resources/libraries/robot/performance/performance_utils.robot index 52ddc9193e..ee49b98adf 100644 --- a/resources/libraries/robot/performance/performance_utils.robot +++ b/resources/libraries/robot/performance/performance_utils.robot @@ -379,7 +379,8 @@ | | ... | ${fail_no_traffic}=${True} | ${subsamples}=${PERF_TRIAL_MULTIPLICITY} | | ... | ${traffic_directions}=${2} | ${tx_port}=${0} | ${rx_port}=${1} | | -| | ${results} = | Send traffic at specified rate | ${trial_duration} +| | ${results} | ${approximated_results} = | Send traffic at specified rate +| | ... | ${trial_duration} | | ... | ${max_rate}pps | ${frame_size} | ${traffic_profile} | ${subsamples} | | ... | ${traffic_directions} | ${tx_port} | ${rx_port} | | Set Test Message | ${\n}Maximum Receive Rate trial results @@ -427,6 +428,7 @@ | | Run Keyword If | ${dut_stats}==${True} | | ... | VPP enable elog traces on all DUTs | ${nodes} | | ${results} = | Create List +| | ${approximated_results} = | Create List | | FOR | ${i} | IN RANGE | ${subsamples} | | | # The following line is skipping some default arguments, | | | # that is why subsequent arguments have to be named. @@ -435,8 +437,10 @@ | | | ... | traffic_directions=${traffic_directions} | tx_port=${tx_port} | | | ... | rx_port=${rx_port} | | | ${rx} = | Get Received +| | | ${ar} = | Get Approximated Rate | | | ${rr} = | Evaluate | ${rx} / ${trial_duration} | | | Append To List | ${results} | ${rr} +| | | Append To List | ${approximated_results} | ${ar} | | END | | Run Keyword If | ${dut_stats}==${True} | Show event logger on all DUTs | | ... | ${nodes} @@ -444,7 +448,7 @@ | | ... | ${nodes} | | Run Keyword If | ${dut_stats}==${True} and ${pkt_trace}==${True} | | ... | Show Packet Trace On All Duts | ${nodes} | maximum=${100} -| | Return From Keyword | ${results} +| | Return From Keyword | ${results} | ${approximated_results} | Measure and show latency at specified rate | | [Documentation] diff --git a/resources/tools/trex/trex_stateless_profile.py b/resources/tools/trex/trex_stateless_profile.py index a41e4e8562..a0de5c0cd3 100755 --- a/resources/tools/trex/trex_stateless_profile.py +++ b/resources/tools/trex/trex_stateless_profile.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 -# Copyright (c) 2019 Cisco and/or its affiliates. +# Copyright (c) 2020 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -105,6 +105,8 @@ def simple_burst( client = None total_rcvd = 0 total_sent = 0 + approximated_duration = 0 + approximated_rate = 0 lost_a = 0 lost_b = 0 lat_a = u"-1/-1/-1/" @@ -161,14 +163,14 @@ def simple_burst( client.clear_stats() # Choose rate and start traffic: - time_start = time.time() client.start(ports=ports, mult=rate, duration=warmup_time, force=force) # Block until done: + time_start = time.monotonic() client.wait_on_traffic(ports=ports, timeout=warmup_time+30) - time_stop = time.time() - print(f"Warmup traffic took {time_stop - time_start} seconds.") + time_stop = time.monotonic() + approximated_duration = time_stop - time_start if client.get_warnings(): for warning in client.get_warnings(): @@ -194,8 +196,7 @@ def simple_burst( lost_b = 0 # Choose rate and start traffic: - client.start(ports=ports, mult=rate, duration=duration, force=force) - time_start = time.time() + client.start(ports=ports, mult=rate, duration=duration) if async_start: # For async stop, we need to export the current snapshot. @@ -206,9 +207,10 @@ def simple_burst( print(f"Xstats snapshot 1: {xsnap1!r}") else: # Block until done: + time_start = time.monotonic() client.wait_on_traffic(ports=ports, timeout=duration+30) - time_stop = time.time() - print(f"Main traffic took {time_stop - time_start} seconds.") + time_stop = time.monotonic() + approximated_duration = time_stop - time_start if client.get_warnings(): for warning in client.get_warnings(): @@ -225,7 +227,6 @@ def simple_burst( lost_b = stats[port_1][u"opackets"] - stats[port_0][u"ipackets"] # Stats index is not a port number, but "pgid". - # TODO: Find out what "pgid" means. if latency: lat_obj = stats[u"latency"][0][u"latency"] lat_a = fmt_latency( @@ -243,6 +244,10 @@ def simple_burst( else: total_sent = stats[port_0][u"opackets"] total_rcvd = stats[port_1][u"ipackets"] + try: + approximated_rate = total_sent / approximated_duration + except ZeroDivisionError: + pass print(f"\npackets lost from {port_0} --> {port_1}: {lost_a} pkts") if traffic_directions > 1: @@ -262,8 +267,10 @@ def simple_burst( print( f"rate={rate!r}, totalReceived={total_rcvd}, " f"totalSent={total_sent}, frameLoss={lost_a + lost_b}, " + f"targetDuration={duration!r}, " + f"approximatedDuration={approximated_duration!r}, " + f"approximatedRate={approximated_rate}, " f"latencyStream0(usec)={lat_a}, latencyStream1(usec)={lat_b}, " - f"targetDuration={duration!r}" ) diff --git a/resources/tools/trex/trex_stateless_stop.py b/resources/tools/trex/trex_stateless_stop.py index d4461ffd39..5e8721d28c 100755 --- a/resources/tools/trex/trex_stateless_stop.py +++ b/resources/tools/trex/trex_stateless_stop.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 -# Copyright (c) 2019 Cisco and/or its affiliates. +# Copyright (c) 2020 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -94,8 +94,9 @@ def main(): # TODO: Add latency. print( f"rate='unknown', totalReceived={total_rcvd}, totalSent={total_sent}, " - f"frameLoss={total_lost}, latencyStream0(usec)=-1/-1/-1, " - f"latencyStream1(usec)=-1/-1/-1, targetDuration='manual'" + f"frameLoss={total_lost}, targetDuration='manual', " + f"approximatedDuration='manual', approximatedRate='unknown', " + f"latencyStream0(usec)=-1/-1/-1, latencyStream1(usec)=-1/-1/-1" ) -- 2.16.6