diff options
author | Vratko Polak <vrpolak@cisco.com> | 2018-04-27 15:11:12 +0200 |
---|---|---|
committer | Peter Mikus <pmikus@cisco.com> | 2018-05-04 11:46:26 +0000 |
commit | 35175924550d67f98fb1c2c50b0634656d29169e (patch) | |
tree | fe1008e80c9c6f09227dff84672bd0eaa831ff23 /resources/libraries/python/TrafficGenerator.py | |
parent | 4bfd1dcd604dac12d1dd00ba63c0d5e4170a1f2b (diff) |
CSIT-992: Add libraries for optimized search
+ Place the libraries into resources/libraries/python/search/.
+ Except OptimizedTrexSearch in TrafficGenerator.py
+ Change traffic generator to support floats for duration and warmup.
+ Remove explicit type conversions where not needed.
+ Add robot keywords to performance_utils.robot
+ for calling the optimized search.
+ for reporting the resulting values.
+ for checking the minimal performance has been reached.
+ for running five second "Traffic should pass with no loss" after the search.
- Add methodology documentation in subsequent Change.
- Add simulator for testing algorithm correctness in a subsequent Change.
- Add tests using the libraries in subsequent Change.
Change-Id: Ia041008382ee4c9a562172099aea794c854d5f2f
Signed-off-by: Vratko Polak <vrpolak@cisco.com>
Diffstat (limited to 'resources/libraries/python/TrafficGenerator.py')
-rw-r--r-- | resources/libraries/python/TrafficGenerator.py | 154 |
1 files changed, 134 insertions, 20 deletions
diff --git a/resources/libraries/python/TrafficGenerator.py b/resources/libraries/python/TrafficGenerator.py index 4da1c8766f..aa839dd80e 100644 --- a/resources/libraries/python/TrafficGenerator.py +++ b/resources/libraries/python/TrafficGenerator.py @@ -16,14 +16,17 @@ from robot.api import logger from robot.libraries.BuiltIn import BuiltIn -from resources.libraries.python.constants import Constants -from resources.libraries.python.ssh import SSH -from resources.libraries.python.topology import NodeType -from resources.libraries.python.topology import NodeSubTypeTG -from resources.libraries.python.topology import Topology -from resources.libraries.python.DropRateSearch import DropRateSearch +from .DropRateSearch import DropRateSearch +from .constants import Constants +from .ssh import SSH +from .topology import NodeType +from .topology import NodeSubTypeTG +from .topology import Topology +from .search.AbstractRateProvider import AbstractRateProvider +from .search.OptimizedSearchAlgorithm import OptimizedSearchAlgorithm +from .search.ReceiveRateMeasurement import ReceiveRateMeasurement -__all__ = ['TrafficGenerator', 'TGDropRateSearchImpl'] +__all__ = ['TGDropRateSearchImpl', 'TrafficGenerator', 'OptimizedSearch'] class TGDropRateSearchImpl(DropRateSearch): @@ -40,9 +43,10 @@ class TGDropRateSearchImpl(DropRateSearch): :param frame_size: Size of frame. :param loss_acceptance: Permitted drop ratio or frames count. :param loss_acceptance_type: Type of permitted loss. - :param traffic_type: Traffic profile ([2,3]-node-L[2,3], ...). + :param traffic_type: Module name as a traffic type identifier. + See resources/traffic_profiles/trex for implemented modules. :param skip_warmup: Start TRex without warmup traffic if true. - :type rate: int + :type rate: float :type frame_size: str :type loss_acceptance: float :type loss_acceptance_type: LossAcceptanceType @@ -66,7 +70,7 @@ class TGDropRateSearchImpl(DropRateSearch): tg_instance.trex_stl_start_remote_exec(self.get_duration(), unit_rate, frame_size, traffic_type, - warmup_time=0) + warmup_time=0.0) else: tg_instance.trex_stl_start_remote_exec(self.get_duration(), unit_rate, frame_size, @@ -97,8 +101,13 @@ class TGDropRateSearchImpl(DropRateSearch): return tg_instance.get_latency_int() -class TrafficGenerator(object): - """Traffic Generator.""" +class TrafficGenerator(AbstractRateProvider): + """Traffic Generator. + + FIXME: Describe API.""" + + # TODO: Decrease friction between various search and rate provider APIs. + # FIXME: Remove "trex" from lines which could work with other TGs. # use one instance of TrafficGenerator for all tests in test suite ROBOT_LIBRARY_SCOPE = 'TEST SUITE' @@ -112,6 +121,10 @@ class TrafficGenerator(object): self._node = None # T-REX interface order mapping self._ifaces_reordered = False + # Parameters not given by measure(). + self.frame_size = None + self.traffic_type = None + self.warmup_time = None @property def node(self): @@ -374,23 +387,24 @@ class TrafficGenerator(object): def trex_stl_start_remote_exec(self, duration, rate, framesize, traffic_type, async_call=False, - latency=True, warmup_time=5): + latency=True, warmup_time=5.0): """Execute script on remote node over ssh to start traffic. :param duration: Time expresed in seconds for how long to send traffic. :param rate: Traffic rate expressed with units (pps, %) :param framesize: L2 frame size to send (without padding and IPG). - :param traffic_type: Traffic profile. + :param traffic_type: Module name as a traffic type identifier. + See resources/traffic_profiles/trex for implemented modules. :param async_call: If enabled then don't wait for all incomming trafic. :param latency: With latency measurement. :param warmup_time: Warmup time period. - :type duration: int + :type duration: float :type rate: str :type framesize: str :type traffic_type: str :type async_call: bool :type latency: bool - :type warmup_time: int + :type warmup_time: float :returns: Nothing :raises RuntimeError: In case of TG driver issue. """ @@ -418,7 +432,7 @@ class TrafficGenerator(object): "{9}'". # --latency format(Constants.REMOTE_FW_DIR, profile_path, duration, framesize, rate, warmup_time, _p0 - 1, _p1 - 1, _async, _latency), - timeout=int(duration) + 60) + timeout=float(duration) + 60) if int(ret) != 0: raise RuntimeError('TRex stateless runtime error') @@ -462,7 +476,8 @@ class TrafficGenerator(object): :param duration: Duration of test traffic generation in seconds. :param rate: Offered load per interface (e.g. 1%, 3gbps, 4mpps, ...). :param framesize: Frame size (L2) in Bytes. - :param traffic_type: Traffic profile. + :param traffic_type: Module name as a traffic type identifier. + See resources/traffic_profiles/trex for implemented modules. :param warmup_time: Warmup phase in seconds. :param async_call: Async mode. :param latency: With latency measurement. @@ -470,7 +485,7 @@ class TrafficGenerator(object): :type rate: str :type framesize: str :type traffic_type: str - :type warmup_time: int + :type warmup_time: float :type async_call: bool :type latency: bool :returns: TG output. @@ -490,7 +505,7 @@ class TrafficGenerator(object): if node['subtype'] is None: raise RuntimeError('TG subtype not defined') elif node['subtype'] == NodeSubTypeTG.TREX: - self.trex_stl_start_remote_exec(int(duration), rate, framesize, + self.trex_stl_start_remote_exec(duration, rate, framesize, traffic_type, async_call, latency, warmup_time=warmup_time) else: @@ -533,3 +548,102 @@ class TrafficGenerator(object): if loss > float(loss_acceptance): raise Exception("Traffic loss {} above loss acceptance: {}".format( loss, loss_acceptance)) + + def set_rate_provider_defaults(self, frame_size, traffic_type, + warmup_time=0.0): + """Store values accessed by measure(). + + :param frame_size: Frame size identifier or value [B]. + :param traffic_type: Module name as a traffic type identifier. + See resources/traffic_profiles/trex for implemented modules. + :param warmup_time: Traffic duration before measurement starts [s]. + :type frame_size: str or int + :type traffic_type: str + :type warmup_time: float + """ + self.frame_size = frame_size + self.traffic_type = str(traffic_type) + self.warmup_time = float(warmup_time) + + def measure(self, duration, transmit_rate): + """Run bi-directional measurement, parse and return results. + + :param duration: Trial duration [s]. + :param transmit_rate: Target bidirectional transmit rate [pps]. + :type duration: float + :type transmit_rate: float + :returns: Structure containing the result of the measurement. + :rtype: ReceiveRateMeasurement + :raises RuntimeError: If TG is not set, or if node is not TG, + or if subtype is not specified. + :raises NotImplementedError: If TG is not supported. + """ + duration = float(duration) + transmit_rate = float(transmit_rate) + # Trex needs target Tr per stream, but reports aggregate Tx and Dx. + unit_rate = str(transmit_rate / 2.0) + "pps" + self.send_traffic_on_tg( + duration, unit_rate, self.frame_size, self.traffic_type, + self.warmup_time, latency=True) + transmit_count = int(self.get_sent()) + drop_count = int(self.get_loss()) + measurement = ReceiveRateMeasurement( + duration, transmit_rate, transmit_count, drop_count) + measurement.latency = self.get_latency_int() + return measurement + + +class OptimizedSearch(object): + """Class to be imported as Robot Library, containing a single keyword.""" + + @staticmethod + def perform_optimized_ndrpdr_search( + frame_size, traffic_type, fail_rate, line_rate, + allowed_drop_fraction=0.005, final_relative_width=0.005, + final_trial_duration=30.0, initial_trial_duration=1.0, + intermediate_phases=2, timeout=600.0): + """Setup initialized TG, perform optimized search, return intervals. + + :param frame_size: Frame size identifier or value [B]. + :param traffic_type: Module name as a traffic type identifier. + See resources/traffic_profiles/trex for implemented modules. + :param fail_rate: Minimal target transmit rate [pps]. + :param line_rate: Maximal target transmit rate [pps]. + :param allowed_drop_fraction: Fraction of dropped packets for PDR [1]. + :param final_relative_width: Final lower bound transmit rate + cannot be more distant that this multiple of upper bound [1]. + :param final_trial_duration: Trial duration for the final phase [s]. + :param initial_trial_duration: Trial duration for the initial phase + and also for the first intermediate phase [s]. + :param intermediate_phases: Number of intermediate phases to perform + before the final phase [1]. + :param timeout: The search will fail itself when not finished + before this overall time [s]. + :type frame_size: str or int + :type traffic_type: str + :type fail_rate: float + :type line_rate: float + :type allowed_drop_fraction: float + :type final_relative_width: float + :type final_trial_duration: float + :type initial_trial_duration: float + :type intermediate_phases: int + :type timeout: float + :returns: Structure containing narrowed down intervals + and their measurements. + :rtype: NdrPdrResult + :raises RuntimeError: If total duration is larger than timeout. + """ + # we need instance of TrafficGenerator instantiated by Robot Framework + # to be able to use trex_stl-*() + tg_instance = BuiltIn().get_library_instance( + 'resources.libraries.python.TrafficGenerator') + tg_instance.set_rate_provider_defaults(frame_size, traffic_type) + algorithm = OptimizedSearchAlgorithm( + tg_instance, final_trial_duration=final_trial_duration, + final_relative_width=final_relative_width, + intermediate_phases=intermediate_phases, + initial_trial_duration=initial_trial_duration, timeout=timeout) + result = algorithm.narrow_down_ndr_and_pdr( + fail_rate, line_rate, allowed_drop_fraction) + return result |