diff options
author | treyad <treyad@viosoft.com> | 2018-11-20 01:54:08 -0800 |
---|---|---|
committer | treyad <treyad@viosoft.com> | 2019-03-27 05:17:13 -0700 |
commit | f3fc3571f491c0e1c583a1856c2e246c30e69748 (patch) | |
tree | e0282836f9afdd38e1e1919afd6725a489150728 | |
parent | b3d3d4e0454be6175f161fba7d22113e5dd8a150 (diff) |
Support FD.io Multiple Loss Ratio search (MLRsearch)
Optimized binary search algorithm for finding NDR and PDR bounds
JIRA: YARDSTICK-1486
Change-Id: Iba0e6c7065b61f7b7f3f65cceca509d1aaff8366
Signed-off-by: treyad <treyad@viosoft.com>
14 files changed, 3455 insertions, 11 deletions
diff --git a/samples/vnf_samples/traffic_profiles/ipv4_throughput_latency_vpp.yaml b/samples/vnf_samples/traffic_profiles/ipv4_throughput_latency_vpp.yaml index 1add9bfb4..abbad6728 100644 --- a/samples/vnf_samples/traffic_profiles/ipv4_throughput_latency_vpp.yaml +++ b/samples/vnf_samples/traffic_profiles/ipv4_throughput_latency_vpp.yaml @@ -20,6 +20,7 @@ description: Traffic profile to run RFC2544 latency traffic_profile: traffic_type: VppRFC2544Profile # defines traffic behavior - constant or look for highest possible throughput enable_latency: true + intermediate_phases: 2 test_precision: 0.1 duration: 30 lower_bound: 1.0 diff --git a/yardstick/network_services/helpers/vpp_helpers/__init__.py b/yardstick/network_services/helpers/vpp_helpers/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/yardstick/network_services/helpers/vpp_helpers/__init__.py diff --git a/yardstick/network_services/helpers/vpp_helpers/abstract_search_algorithm.py b/yardstick/network_services/helpers/vpp_helpers/abstract_search_algorithm.py new file mode 100644 index 000000000..fced05833 --- /dev/null +++ b/yardstick/network_services/helpers/vpp_helpers/abstract_search_algorithm.py @@ -0,0 +1,53 @@ +# Copyright (c) 2019 Viosoft Corporation +# +# 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 +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This is a modified copy of +# https://gerrit.fd.io/r/gitweb?p=csit.git;a=blob_plain;f=resources/libraries/python/MLRsearch/AbstractSearchAlgorithm.py;hb=HEAD + + +from abc import ABCMeta, abstractmethod + + +class AbstractSearchAlgorithm(object): + """Abstract class defining common API for search algorithms.""" + + __metaclass__ = ABCMeta + + def __init__(self, measurer): + """Store the rate provider. + + :param measurer: Object able to perform trial or composite measurements. + :type measurer: AbstractMeasurer.AbstractMeasurer + """ + # TODO: Type check for AbstractMeasurer? + self.measurer = measurer + + @abstractmethod + def narrow_down_ndr_and_pdr( + self, fail_rate, line_rate, packet_loss_ratio): + """Perform measurements to narrow down intervals, return them. + + This will be renamed when custom loss ratio lists are supported. + + :param fail_rate: Minimal target transmit rate [pps]. + :param line_rate: Maximal target transmit rate [pps]. + :param packet_loss_ratio: Fraction of packets lost, for PDR [1]. + :type fail_rate: float + :type line_rate: float + :type packet_loss_ratio: float + :returns: Structure containing narrowed down intervals + and their measurements. + :rtype: NdrPdrResult.NdrPdrResult + """ + # TODO: Do we agree on arguments related to precision or trial duration? diff --git a/yardstick/network_services/helpers/vpp_helpers/multiple_loss_ratio_search.py b/yardstick/network_services/helpers/vpp_helpers/multiple_loss_ratio_search.py new file mode 100644 index 000000000..582e3dc27 --- /dev/null +++ b/yardstick/network_services/helpers/vpp_helpers/multiple_loss_ratio_search.py @@ -0,0 +1,688 @@ +# Copyright (c) 2019 Viosoft Corporation +# +# 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 +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This is a modified copy of +# https://gerrit.fd.io/r/gitweb?p=csit.git;a=blob_plain;f=resources/libraries/python/MLRsearch/MultipleLossRatioSearch.py;hb=HEAD + +import datetime +import logging +import math +import time + +from yardstick.network_services.helpers.vpp_helpers.abstract_search_algorithm import \ + AbstractSearchAlgorithm +from yardstick.network_services.helpers.vpp_helpers.ndr_pdr_result import \ + NdrPdrResult +from yardstick.network_services.helpers.vpp_helpers.receive_rate_interval import \ + ReceiveRateInterval +from yardstick.network_services.helpers.vpp_helpers.receive_rate_measurement import \ + ReceiveRateMeasurement + +LOGGING = logging.getLogger(__name__) + + +class MultipleLossRatioSearch(AbstractSearchAlgorithm): + """Optimized binary search algorithm for finding NDR and PDR bounds. + + Traditional binary search algorithm needs initial interval + (lower and upper bound), and returns final interval after bisecting + (until some exit condition is met). + The exit condition is usually related to the interval width, + (upper bound value minus lower bound value). + + The optimized algorithm contains several improvements + aimed to reduce overall search time. + + One improvement is searching for two intervals at once. + The intervals are for NDR (No Drop Rate) and PDR (Partial Drop Rate). + + Next improvement is that the initial interval does not need to be valid. + Imagine initial interval (10, 11) where 11 is smaller + than the searched value. + The algorithm will try (11, 13) interval next, and if 13 is still smaller, + (13, 17) and so on, doubling width until the upper bound is valid. + The part when interval expands is called external search, + the part when interval is bisected is called internal search. + + Next improvement is that trial measurements at small trial duration + can be used to find a reasonable interval for full trial duration search. + This results in more trials performed, but smaller overall duration + in general. + + Next improvement is bisecting in logarithmic quantities, + so that exit criteria can be independent of measurement units. + + Next improvement is basing the initial interval on receive rates. + + Final improvement is exiting early if the minimal value + is not a valid lower bound. + + The complete search consist of several phases, + each phase performing several trial measurements. + Initial phase creates initial interval based on receive rates + at maximum rate and at maximum receive rate (MRR). + Final phase and preceding intermediate phases are performing + external and internal search steps, + each resulting interval is the starting point for the next phase. + The resulting interval of final phase is the result of the whole algorithm. + + Each non-initial phase uses its own trial duration and width goal. + Any non-initial phase stops searching (for NDR or PDR independently) + when minimum is not a valid lower bound (at current duration), + or all of the following is true: + Both bounds are valid, bound bounds are measured at the current phase + trial duration, interval width is less than the width goal + for current phase. + + TODO: Review and update this docstring according to rst docs. + TODO: Support configurable number of Packet Loss Ratios. + """ + + class ProgressState(object): + """Structure containing data to be passed around in recursion.""" + + def __init__( + self, result, phases, duration, width_goal, packet_loss_ratio, + minimum_transmit_rate, maximum_transmit_rate): + """Convert and store the argument values. + + :param result: Current measured NDR and PDR intervals. + :param phases: How many intermediate phases to perform + before the current one. + :param duration: Trial duration to use in the current phase [s]. + :param width_goal: The goal relative width for the curreent phase. + :param packet_loss_ratio: PDR fraction for the current search. + :param minimum_transmit_rate: Minimum target transmit rate + for the current search [pps]. + :param maximum_transmit_rate: Maximum target transmit rate + for the current search [pps]. + :type result: NdrPdrResult.NdrPdrResult + :type phases: int + :type duration: float + :type width_goal: float + :type packet_loss_ratio: float + :type minimum_transmit_rate: float + :type maximum_transmit_rate: float + """ + self.result = result + self.phases = int(phases) + self.duration = float(duration) + self.width_goal = float(width_goal) + self.packet_loss_ratio = float(packet_loss_ratio) + self.minimum_transmit_rate = float(minimum_transmit_rate) + self.maximum_transmit_rate = float(maximum_transmit_rate) + + def __init__(self, measurer, latency=False, pkt_size=64, + final_relative_width=0.005, + final_trial_duration=30.0, initial_trial_duration=1.0, + number_of_intermediate_phases=2, timeout=600.0, doublings=1): + """Store the measurer object and additional arguments. + + :param measurer: Rate provider to use by this search object. + :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 number_of_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]. + :param doublings: How many doublings to do in external search step. + Default 1 is suitable for fairly stable tests, + less stable tests might get better overal duration with 2 or more. + :type measurer: AbstractMeasurer.AbstractMeasurer + :type final_relative_width: float + :type final_trial_duration: float + :type initial_trial_duration: int + :type number_of_intermediate_phases: int + :type timeout: float + :type doublings: int + """ + super(MultipleLossRatioSearch, self).__init__(measurer) + self.latency = latency + self.pkt_size = int(pkt_size) + self.final_trial_duration = float(final_trial_duration) + self.final_relative_width = float(final_relative_width) + self.number_of_intermediate_phases = int(number_of_intermediate_phases) + self.initial_trial_duration = float(initial_trial_duration) + self.timeout = float(timeout) + self.doublings = int(doublings) + + self.queue = None + self.port_pg_id = None + self.ports = [] + self.test_data = {} + self.profiles = {} + + @staticmethod + def double_relative_width(relative_width): + """Return relative width corresponding to double logarithmic width. + + :param relative_width: The base relative width to double. + :type relative_width: float + :returns: The relative width of double logarithmic size. + :rtype: float + """ + return 1.999 * relative_width - relative_width * relative_width + # The number should be 2.0, but we want to avoid rounding errors, + # and ensure half of double is not larger than the original value. + + @staticmethod + def double_step_down(relative_width, current_bound): + """Return rate of double logarithmic width below. + + :param relative_width: The base relative width to double. + :param current_bound: The current target transmit rate to move [pps]. + :type relative_width: float + :type current_bound: float + :returns: Transmit rate smaller by logarithmically double width [pps]. + :rtype: float + """ + return current_bound * ( + 1.0 - MultipleLossRatioSearch.double_relative_width( + relative_width)) + + @staticmethod + def expand_down(relative_width, doublings, current_bound): + """Return rate of expanded logarithmic width below. + + :param relative_width: The base relative width to double. + :param doublings: How many doublings to do for expansion. + :param current_bound: The current target transmit rate to move [pps]. + :type relative_width: float + :type doublings: int + :type current_bound: float + :returns: Transmit rate smaller by logarithmically double width [pps]. + :rtype: float + """ + for _ in range(doublings): + relative_width = MultipleLossRatioSearch.double_relative_width( + relative_width) + return current_bound * (1.0 - relative_width) + + @staticmethod + def double_step_up(relative_width, current_bound): + """Return rate of double logarithmic width above. + + :param relative_width: The base relative width to double. + :param current_bound: The current target transmit rate to move [pps]. + :type relative_width: float + :type current_bound: float + :returns: Transmit rate larger by logarithmically double width [pps]. + :rtype: float + """ + return current_bound / ( + 1.0 - MultipleLossRatioSearch.double_relative_width( + relative_width)) + + @staticmethod + def expand_up(relative_width, doublings, current_bound): + """Return rate of expanded logarithmic width above. + + :param relative_width: The base relative width to double. + :param doublings: How many doublings to do for expansion. + :param current_bound: The current target transmit rate to move [pps]. + :type relative_width: float + :type doublings: int + :type current_bound: float + :returns: Transmit rate smaller by logarithmically double width [pps]. + :rtype: float + """ + for _ in range(doublings): + relative_width = MultipleLossRatioSearch.double_relative_width( + relative_width) + return current_bound / (1.0 - relative_width) + + @staticmethod + def half_relative_width(relative_width): + """Return relative width corresponding to half logarithmic width. + + :param relative_width: The base relative width to halve. + :type relative_width: float + :returns: The relative width of half logarithmic size. + :rtype: float + """ + return 1.0 - math.sqrt(1.0 - relative_width) + + @staticmethod + def half_step_up(relative_width, current_bound): + """Return rate of half logarithmic width above. + + :param relative_width: The base relative width to halve. + :param current_bound: The current target transmit rate to move [pps]. + :type relative_width: float + :type current_bound: float + :returns: Transmit rate larger by logarithmically half width [pps]. + :rtype: float + """ + return current_bound / ( + 1.0 - MultipleLossRatioSearch.half_relative_width( + relative_width)) + + def init_generator(self, ports, port_pg_id, profiles, test_data, queue): + self.ports = ports + self.port_pg_id = port_pg_id + self.profiles = profiles + self.test_data = test_data + self.queue = queue + self.queue.cancel_join_thread() + + def collect_kpi(self, stats, test_value): + samples = self.measurer.generate_samples(stats, self.ports, + self.port_pg_id, self.latency) + samples.update(self.test_data) + LOGGING.info("Collect TG KPIs %s %s %s", datetime.datetime.now(), + test_value, samples) + self.queue.put(samples) + + def narrow_down_ndr_and_pdr( + self, minimum_transmit_rate, maximum_transmit_rate, + packet_loss_ratio): + """Perform initial phase, create state object, proceed with next phases. + + :param minimum_transmit_rate: Minimal target transmit rate [pps]. + :param maximum_transmit_rate: Maximal target transmit rate [pps]. + :param packet_loss_ratio: Fraction of packets lost, for PDR [1]. + :type minimum_transmit_rate: float + :type maximum_transmit_rate: float + :type packet_loss_ratio: float + :returns: Structure containing narrowed down intervals + and their measurements. + :rtype: NdrPdrResult.NdrPdrResult + :raises RuntimeError: If total duration is larger than timeout. + """ + minimum_transmit_rate = float(minimum_transmit_rate) + maximum_transmit_rate = float(maximum_transmit_rate) + packet_loss_ratio = float(packet_loss_ratio) + line_measurement = self.measure( + self.initial_trial_duration, maximum_transmit_rate, self.latency) + initial_width_goal = self.final_relative_width + for _ in range(self.number_of_intermediate_phases): + initial_width_goal = self.double_relative_width(initial_width_goal) + max_lo = maximum_transmit_rate * (1.0 - initial_width_goal) + mrr = max( + minimum_transmit_rate, + min(max_lo, line_measurement.receive_rate)) + mrr_measurement = self.measure( + self.initial_trial_duration, mrr, self.latency) + # Attempt to get narrower width. + if mrr_measurement.loss_fraction > 0.0: + max2_lo = mrr * (1.0 - initial_width_goal) + mrr2 = min(max2_lo, mrr_measurement.receive_rate) + else: + mrr2 = mrr / (1.0 - initial_width_goal) + if mrr2 > minimum_transmit_rate and mrr2 < maximum_transmit_rate: + line_measurement = mrr_measurement + mrr_measurement = self.measure( + self.initial_trial_duration, mrr2, self.latency) + if mrr2 > mrr: + buf = line_measurement + line_measurement = mrr_measurement + mrr_measurement = buf + starting_interval = ReceiveRateInterval( + mrr_measurement, line_measurement) + starting_result = NdrPdrResult(starting_interval, starting_interval) + state = self.ProgressState( + starting_result, self.number_of_intermediate_phases, + self.final_trial_duration, self.final_relative_width, + packet_loss_ratio, minimum_transmit_rate, maximum_transmit_rate) + state = self.ndrpdr(state) + result = state.result + # theor_max_thruput = 0 + result_samples = {} + + MultipleLossRatioSearch.display_single_bound(result_samples, + 'NDR_LOWER', result.ndr_interval.measured_low.transmit_rate, + self.pkt_size, result.ndr_interval.measured_low.latency) + MultipleLossRatioSearch.display_single_bound(result_samples, + 'NDR_UPPER', result.ndr_interval.measured_high.transmit_rate, + self.pkt_size) + MultipleLossRatioSearch.display_single_bound(result_samples, + 'PDR_LOWER', result.pdr_interval.measured_low.transmit_rate, + self.pkt_size, result.pdr_interval.measured_low.latency) + MultipleLossRatioSearch.display_single_bound(result_samples, + 'PDR_UPPER', result.pdr_interval.measured_high.transmit_rate, + self.pkt_size) + pdr_msg = self.check_ndrpdr_interval_validity(result_samples, "PDR", + result.pdr_interval, + packet_loss_ratio) + ndr_msg = self.check_ndrpdr_interval_validity(result_samples, "NDR", + result.ndr_interval) + self.queue.put(result_samples) + + LOGGING.debug("result_samples: %s", result_samples) + LOGGING.info(pdr_msg) + LOGGING.info(ndr_msg) + + self.perform_additional_measurements_based_on_ndrpdr_result(result) + + return result_samples + + def _measure_and_update_state(self, state, transmit_rate): + """Perform trial measurement, update bounds, return new state. + + :param state: State before this measurement. + :param transmit_rate: Target transmit rate for this measurement [pps]. + :type state: ProgressState + :type transmit_rate: float + :returns: State after the measurement. + :rtype: ProgressState + """ + # TODO: Implement https://stackoverflow.com/a/24683360 + # to avoid the string manipulation if log verbosity is too low. + LOGGING.info("result before update: %s", state.result) + LOGGING.debug( + "relative widths in goals: %s", state.result.width_in_goals( + self.final_relative_width)) + measurement = self.measure(state.duration, transmit_rate, self.latency) + ndr_interval = self._new_interval( + state.result.ndr_interval, measurement, 0.0) + pdr_interval = self._new_interval( + state.result.pdr_interval, measurement, state.packet_loss_ratio) + state.result = NdrPdrResult(ndr_interval, pdr_interval) + return state + + @staticmethod + def _new_interval(old_interval, measurement, packet_loss_ratio): + """Return new interval with bounds updated according to the measurement. + + :param old_interval: The current interval before the measurement. + :param measurement: The new meaqsurement to take into account. + :param packet_loss_ratio: Fraction for PDR (or zero for NDR). + :type old_interval: ReceiveRateInterval.ReceiveRateInterval + :type measurement: ReceiveRateMeasurement.ReceiveRateMeasurement + :type packet_loss_ratio: float + :returns: The updated interval. + :rtype: ReceiveRateInterval.ReceiveRateInterval + """ + old_lo, old_hi = old_interval.measured_low, old_interval.measured_high + # Priority zero: direct replace if the target Tr is the same. + if measurement.target_tr in (old_lo.target_tr, old_hi.target_tr): + if measurement.target_tr == old_lo.target_tr: + return ReceiveRateInterval(measurement, old_hi) + else: + return ReceiveRateInterval(old_lo, measurement) + # Priority one: invalid lower bound allows only one type of update. + if old_lo.loss_fraction > packet_loss_ratio: + # We can only expand down, old bound becomes valid upper one. + if measurement.target_tr < old_lo.target_tr: + return ReceiveRateInterval(measurement, old_lo) + else: + return old_interval + # Lower bound is now valid. + # Next priorities depend on target Tr. + if measurement.target_tr < old_lo.target_tr: + # Lower external measurement, relevant only + # if the new measurement has high loss rate. + if measurement.loss_fraction > packet_loss_ratio: + # Returning the broader interval as old_lo + # would be invalid upper bound. + return ReceiveRateInterval(measurement, old_hi) + elif measurement.target_tr > old_hi.target_tr: + # Upper external measurement, only relevant for invalid upper bound. + if old_hi.loss_fraction <= packet_loss_ratio: + # Old upper bound becomes valid new lower bound. + return ReceiveRateInterval(old_hi, measurement) + else: + # Internal measurement, replaced boundary + # depends on measured loss fraction. + if measurement.loss_fraction > packet_loss_ratio: + # We have found a narrow valid interval, + # regardless of whether old upper bound was valid. + return ReceiveRateInterval(old_lo, measurement) + else: + # In ideal world, we would not want to shrink interval + # if upper bound is not valid. + # In the real world, we want to shrink it for + # "invalid upper bound at maximal rate" case. + return ReceiveRateInterval(measurement, old_hi) + # Fallback, the interval is unchanged by the measurement. + return old_interval + + def ndrpdr(self, state): + """Pefrom trials for this phase. Return the new state when done. + + :param state: State before this phase. + :type state: ProgressState + :returns: The updated state. + :rtype: ProgressState + :raises RuntimeError: If total duration is larger than timeout. + """ + start_time = time.time() + if state.phases > 0: + # We need to finish preceding intermediate phases first. + saved_phases = state.phases + state.phases -= 1 + # Preceding phases have shorter duration. + saved_duration = state.duration + duration_multiplier = state.duration / self.initial_trial_duration + phase_exponent = float(state.phases) / saved_phases + state.duration = self.initial_trial_duration * math.pow( + duration_multiplier, phase_exponent) + # Shorter durations do not need that narrow widths. + saved_width = state.width_goal + state.width_goal = self.double_relative_width(state.width_goal) + # Recurse. + state = self.ndrpdr(state) + # Restore the state for current phase. + state.duration = saved_duration + state.width_goal = saved_width + state.phases = saved_phases # Not needed, but just in case. + LOGGING.info( + "starting iterations with duration %s and relative width goal %s", + state.duration, state.width_goal) + while 1: + if time.time() > start_time + self.timeout: + raise RuntimeError("Optimized search takes too long.") + # Order of priorities: invalid bounds (nl, pl, nh, ph), + # then narrowing relative Tr widths. + # Durations are not priorities yet, + # they will settle on their own hopefully. + ndr_lo = state.result.ndr_interval.measured_low + ndr_hi = state.result.ndr_interval.measured_high + pdr_lo = state.result.pdr_interval.measured_low + pdr_hi = state.result.pdr_interval.measured_high + ndr_rel_width = max( + state.width_goal, state.result.ndr_interval.rel_tr_width) + pdr_rel_width = max( + state.width_goal, state.result.pdr_interval.rel_tr_width) + # If we are hitting maximal or minimal rate, we cannot shift, + # but we can re-measure. + if ndr_lo.loss_fraction > 0.0: + if ndr_lo.target_tr > state.minimum_transmit_rate: + new_tr = max( + state.minimum_transmit_rate, + self.expand_down( + ndr_rel_width, self.doublings, ndr_lo.target_tr)) + LOGGING.info("ndr lo external %s", new_tr) + state = self._measure_and_update_state(state, new_tr) + continue + elif ndr_lo.duration < state.duration: + LOGGING.info("ndr lo minimal re-measure") + state = self._measure_and_update_state( + state, state.minimum_transmit_rate) + continue + if pdr_lo.loss_fraction > state.packet_loss_ratio: + if pdr_lo.target_tr > state.minimum_transmit_rate: + new_tr = max( + state.minimum_transmit_rate, + self.expand_down( + pdr_rel_width, self.doublings, pdr_lo.target_tr)) + LOGGING.info("pdr lo external %s", new_tr) + state = self._measure_and_update_state(state, new_tr) + continue + elif pdr_lo.duration < state.duration: + LOGGING.info("pdr lo minimal re-measure") + state = self._measure_and_update_state( + state, state.minimum_transmit_rate) + continue + if ndr_hi.loss_fraction <= 0.0: + if ndr_hi.target_tr < state.maximum_transmit_rate: + new_tr = min( + state.maximum_transmit_rate, + self.expand_up( + ndr_rel_width, self.doublings, ndr_hi.target_tr)) + LOGGING.info("ndr hi external %s", new_tr) + state = self._measure_and_update_state(state, new_tr) + continue + elif ndr_hi.duration < state.duration: + LOGGING.info("ndr hi maximal re-measure") + state = self._measure_and_update_state( + state, state.maximum_transmit_rate) + continue + if pdr_hi.loss_fraction <= state.packet_loss_ratio: + if pdr_hi.target_tr < state.maximum_transmit_rate: + new_tr = min( + state.maximum_transmit_rate, + self.expand_up( + pdr_rel_width, self.doublings, pdr_hi.target_tr)) + LOGGING.info("pdr hi external %s", new_tr) + state = self._measure_and_update_state(state, new_tr) + continue + elif pdr_hi.duration < state.duration: + LOGGING.info("ndr hi maximal re-measure") + state = self._measure_and_update_state( + state, state.maximum_transmit_rate) + continue + # If we are hitting maximum_transmit_rate, + # it is still worth narrowing width, + # hoping large enough loss fraction will happen. + # But if we are hitting the minimal rate (at current duration), + # no additional measurement will help with that, + # so we can stop narrowing in this phase. + if (ndr_lo.target_tr <= state.minimum_transmit_rate + and ndr_lo.loss_fraction > 0.0): + ndr_rel_width = 0.0 + if (pdr_lo.target_tr <= state.minimum_transmit_rate + and pdr_lo.loss_fraction > state.packet_loss_ratio): + pdr_rel_width = 0.0 + if ndr_rel_width > state.width_goal: + # We have to narrow NDR width first, as NDR internal search + # can invalidate PDR (but not vice versa). + new_tr = self.half_step_up(ndr_rel_width, ndr_lo.target_tr) + LOGGING.info("Bisecting for NDR at %s", new_tr) + state = self._measure_and_update_state(state, new_tr) + continue + if pdr_rel_width > state.width_goal: + # PDR iternal search. + new_tr = self.half_step_up(pdr_rel_width, pdr_lo.target_tr) + LOGGING.info("Bisecting for PDR at %s", new_tr) + state = self._measure_and_update_state(state, new_tr) + continue + # We do not need to improve width, but there still might be + # some measurements with smaller duration. + # We need to re-measure with full duration, possibly + # creating invalid bounds to resolve (thus broadening width). + if ndr_lo.duration < state.duration: + LOGGING.info("re-measuring NDR lower bound") + state = self._measure_and_update_state(state, ndr_lo.target_tr) + continue + if pdr_lo.duration < state.duration: + LOGGING.info("re-measuring PDR lower bound") + state = self._measure_and_update_state(state, pdr_lo.target_tr) + continue + # Except when lower bounds have high loss fraction, in that case + # we do not need to re-measure _upper_ bounds. + if ndr_hi.duration < state.duration and ndr_rel_width > 0.0: + LOGGING.info("re-measuring NDR upper bound") + state = self._measure_and_update_state(state, ndr_hi.target_tr) + continue + if pdr_hi.duration < state.duration and pdr_rel_width > 0.0: + LOGGING.info("re-measuring PDR upper bound") + state = self._measure_and_update_state(state, pdr_hi.target_tr) + continue + # Widths are narrow (or lower bound minimal), bound measurements + # are long enough, we can return. + LOGGING.info("phase done") + break + return state + + def measure(self, duration, transmit_rate, latency): + 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" + stats = self.measurer.send_traffic_on_tg(self.ports, self.port_pg_id, + duration, unit_rate, + latency=latency) + self.measurer.client.reset(ports=self.ports) + self.measurer.client.clear_stats(ports=self.ports) + self.measurer.client.remove_all_streams(ports=self.ports) + for port, profile in self.profiles.items(): + self.measurer.client.add_streams(profile, ports=[port]) + self.collect_kpi(stats, unit_rate) + transmit_count = int(self.measurer.sent) + loss_count = int(self.measurer.loss) + measurement = ReceiveRateMeasurement( + duration, transmit_rate, transmit_count, loss_count) + measurement.latency = self.measurer.latency + return measurement + + def perform_additional_measurements_based_on_ndrpdr_result(self, result): + duration = 5.0 + rate = "{}{}".format(result.ndr_interval.measured_low.target_tr / 2.0, + 'pps') + for _ in range(0, 1): + stats = self.measurer.send_traffic_on_tg(self.ports, + self.port_pg_id, duration, + rate) + self.collect_kpi(stats, rate) + LOGGING.info('Traffic loss occurred: %s', self.measurer.loss) + + @staticmethod + def display_single_bound(result_samples, result_type, rate_total, pkt_size, + latency=None): + bandwidth_total = float(rate_total) * (pkt_size + 20) * 8 / (10 ** 9) + + result_samples["Result_{}".format(result_type)] = { + "rate_total_pps": float(rate_total), + "bandwidth_total_Gbps": float(bandwidth_total), + } + + if latency: + for item in latency: + if latency.index(item) == 0: + name = "Result_{}_{}".format("stream0", result_type) + else: + name = "Result_{}_{}".format("stream1", result_type) + lat_min, lat_avg, lat_max = item.split('/') + result_samples[name] = { + "min_latency": float(lat_min), + "avg_latency": float(lat_avg), + "max_latency": float(lat_max), + } + + @staticmethod + def check_ndrpdr_interval_validity(result_samples, result_type, interval, + packet_loss_ratio=0.0): + lower_bound = interval.measured_low + lower_bound_lf = lower_bound.loss_fraction + + result_samples["Result_{}_packets_lost".format(result_type)] = { + "packet_loss_ratio": float(lower_bound_lf), + "packets_lost": float(lower_bound.loss_count), + } + + if lower_bound_lf <= packet_loss_ratio: + return "Minimal rate loss fraction {} reach target {}".format( + lower_bound_lf, packet_loss_ratio) + else: + message = "Minimal rate loss fraction {} does not reach target {}".format( + lower_bound_lf, packet_loss_ratio) + if lower_bound_lf >= 1.0: + return '{}\nZero packets forwarded!'.format(message) + else: + return '{}\n{} packets lost.'.format(message, + lower_bound.loss_count) diff --git a/yardstick/network_services/helpers/vpp_helpers/ndr_pdr_result.py b/yardstick/network_services/helpers/vpp_helpers/ndr_pdr_result.py new file mode 100644 index 000000000..34a97f9fb --- /dev/null +++ b/yardstick/network_services/helpers/vpp_helpers/ndr_pdr_result.py @@ -0,0 +1,68 @@ +# Copyright (c) 2019 Viosoft Corporation +# +# 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 +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This is a modified copy of +# https://gerrit.fd.io/r/gitweb?p=csit.git;a=blob_plain;f=resources/libraries/python/MLRsearch/NdrPdrResult.py;hb=HEAD + +from yardstick.network_services.helpers.vpp_helpers.receive_rate_interval import \ + ReceiveRateInterval + + +class NdrPdrResult(object): + """Two measurement intervals, return value of search algorithms. + + Partial fraction is NOT part of the result. Pdr interval should be valid + for all partial fractions implied by the interval.""" + + def __init__(self, ndr_interval, pdr_interval): + """Store the measured intervals after checking argument types. + + :param ndr_interval: Object containing data for NDR part of the result. + :param pdr_interval: Object containing data for PDR part of the result. + :type ndr_interval: ReceiveRateInterval.ReceiveRateInterval + :type pdr_interval: ReceiveRateInterval.ReceiveRateInterval + """ + # TODO: Type checking is not very pythonic, + # perhaps users can fix wrong usage without it? + if not isinstance(ndr_interval, ReceiveRateInterval): + raise TypeError("ndr_interval, is not a ReceiveRateInterval: " + "{ndr!r}".format(ndr=ndr_interval)) + if not isinstance(pdr_interval, ReceiveRateInterval): + raise TypeError("pdr_interval, is not a ReceiveRateInterval: " + "{pdr!r}".format(pdr=pdr_interval)) + self.ndr_interval = ndr_interval + self.pdr_interval = pdr_interval + + def width_in_goals(self, relative_width_goal): + """Return a debug string related to current widths in logarithmic scale. + + :param relative_width_goal: Upper bound times this is the goal + difference between upper bound and lower bound. + :type relative_width_goal: float + :returns: Message containing NDR and PDR widths in goals. + :rtype: str + """ + return "ndr {ndr_in_goals}; pdr {pdr_in_goals}".format( + ndr_in_goals=self.ndr_interval.width_in_goals(relative_width_goal), + pdr_in_goals=self.pdr_interval.width_in_goals(relative_width_goal)) + + def __str__(self): + """Return string as tuple of named values.""" + return "NDR={ndr!s};PDR={pdr!s}".format( + ndr=self.ndr_interval, pdr=self.pdr_interval) + + def __repr__(self): + """Return string evaluable as a constructor call.""" + return "NdrPdrResult(ndr_interval={ndr!r},pdr_interval={pdr!r})".format( + ndr=self.ndr_interval, pdr=self.pdr_interval) diff --git a/yardstick/network_services/helpers/vpp_helpers/receive_rate_interval.py b/yardstick/network_services/helpers/vpp_helpers/receive_rate_interval.py new file mode 100644 index 000000000..517a99c1f --- /dev/null +++ b/yardstick/network_services/helpers/vpp_helpers/receive_rate_interval.py @@ -0,0 +1,88 @@ +# Copyright (c) 2019 Viosoft Corporation +# +# 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 +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This is a modified copy of +# https://gerrit.fd.io/r/gitweb?p=csit.git;a=blob_plain;f=resources/libraries/python/MLRsearch/ReceiveRateInterval.py;hb=HEAD + +import math + +from yardstick.network_services.helpers.vpp_helpers.receive_rate_measurement import \ + ReceiveRateMeasurement + + +class ReceiveRateInterval(object): + """Structure defining two Rr measurements, and their relation.""" + + def __init__(self, measured_low, measured_high): + """Store the bound measurements after checking argument types. + + :param measured_low: Measurement for the lower bound. + :param measured_high: Measurement for the upper bound. + :type measured_low: ReceiveRateMeasurement.ReceiveRateMeasurement + :type measured_high: ReceiveRateMeasurement.ReceiveRateMeasurement + """ + # TODO: Type checking is not very pythonic, + # perhaps users can fix wrong usage without it? + if not isinstance(measured_low, ReceiveRateMeasurement): + raise TypeError("measured_low is not a ReceiveRateMeasurement: " + "{low!r}".format(low=measured_low)) + if not isinstance(measured_high, ReceiveRateMeasurement): + raise TypeError("measured_high is not a ReceiveRateMeasurement: " + "{high!r}".format(high=measured_high)) + self.measured_low = measured_low + self.measured_high = measured_high + # Declare secondary quantities to appease pylint. + self.abs_tr_width = None + """Absolute width of target transmit rate. Upper minus lower.""" + self.rel_tr_width = None + """Relative width of target transmit rate. Absolute divided by upper.""" + self.sort() + + def sort(self): + """Sort bounds by target Tr, compute secondary quantities.""" + if self.measured_low.target_tr > self.measured_high.target_tr: + self.measured_low, self.measured_high = ( + self.measured_high, self.measured_low) + self.abs_tr_width = ( + self.measured_high.target_tr - self.measured_low.target_tr) + self.rel_tr_width = round( + self.abs_tr_width / self.measured_high.target_tr, 5) + + def width_in_goals(self, relative_width_goal): + """Return float value. + + Relative width goal is some (negative) value on logarithmic scale. + Current relative width is another logarithmic value. + Return the latter divided by the former. + This is useful when investigating how did surprising widths come to be. + + :param relative_width_goal: Upper bound times this is the goal + difference between upper bound and lower bound. + :type relative_width_goal: float + :returns: Current width as logarithmic multiple of goal width [1]. + :rtype: float + """ + return round(math.log(1.0 - self.rel_tr_width) / math.log( + 1.0 - relative_width_goal), 5) + + def __str__(self): + """Return string as half-open interval.""" + return "[{low!s};{high!s})".format( + low=self.measured_low, high=self.measured_high) + + def __repr__(self): + """Return string evaluable as a constructor call.""" + return ("ReceiveRateInterval(measured_low={low!r}" + ",measured_high={high!r})".format(low=self.measured_low, + high=self.measured_high)) diff --git a/yardstick/network_services/helpers/vpp_helpers/receive_rate_measurement.py b/yardstick/network_services/helpers/vpp_helpers/receive_rate_measurement.py new file mode 100644 index 000000000..2c59ea104 --- /dev/null +++ b/yardstick/network_services/helpers/vpp_helpers/receive_rate_measurement.py @@ -0,0 +1,58 @@ +# Copyright (c) 2019 Viosoft Corporation +# +# 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 +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This is a modified copy of +# https://gerrit.fd.io/r/gitweb?p=csit.git;a=blob_plain;f=resources/libraries/python/MLRsearch/ReceiveRateMeasurement.py;hb=HEAD + + +class ReceiveRateMeasurement(object): + """Structure defining the result of single Rr measurement.""" + + def __init__(self, duration, target_tr, transmit_count, loss_count): + """Constructor, normalize primary and compute secondary quantities. + + :param duration: Measurement duration [s]. + :param target_tr: Target transmit rate [pps]. + If bidirectional traffic is measured, this is bidirectional rate. + :param transmit_count: Number of packets transmitted [1]. + :param loss_count: Number of packets transmitted but not received [1]. + :type duration: float + :type target_tr: float + :type transmit_count: int + :type loss_count: int + """ + self.duration = float(duration) + self.target_tr = float(target_tr) + self.transmit_count = int(transmit_count) + self.loss_count = int(loss_count) + self.receive_count = round(transmit_count - loss_count, 5) + self.transmit_rate = round(transmit_count / self.duration, 5) + self.loss_rate = round(loss_count / self.duration, 5) + self.receive_rate = round(self.receive_count / self.duration, 5) + self.loss_fraction = round( + float(self.loss_count) / self.transmit_count, 5) + # TODO: Do we want to store also the real time (duration + overhead)? + + def __str__(self): + """Return string reporting input and loss fraction.""" + return "d={dur!s},Tr={rate!s},Df={frac!s}".format( + dur=self.duration, rate=self.target_tr, frac=self.loss_fraction) + + def __repr__(self): + """Return string evaluable as a constructor call.""" + return ("ReceiveRateMeasurement(duration={dur!r},target_tr={rate!r}" + ",transmit_count={trans!r},loss_count={loss!r})".format( + dur=self.duration, rate=self.target_tr, + trans=self.transmit_count, + loss=self.loss_count)) diff --git a/yardstick/network_services/traffic_profile/vpp_rfc2544.py b/yardstick/network_services/traffic_profile/vpp_rfc2544.py index 0f8185f90..412e4e69a 100644 --- a/yardstick/network_services/traffic_profile/vpp_rfc2544.py +++ b/yardstick/network_services/traffic_profile/vpp_rfc2544.py @@ -13,17 +13,19 @@ # limitations under the License. import datetime +import ipaddress import logging -from random import choice -from string import ascii_letters +import random +import string -from ipaddress import ip_address from trex_stl_lib import api as Pkt from trex_stl_lib import trex_stl_client from trex_stl_lib import trex_stl_packet_builder_scapy from trex_stl_lib import trex_stl_streams from yardstick.common import constants +from yardstick.network_services.helpers.vpp_helpers.multiple_loss_ratio_search import \ + MultipleLossRatioSearch from yardstick.network_services.traffic_profile.rfc2544 import RFC2544Profile, \ PortPgIDMap from yardstick.network_services.traffic_profile.trex_traffic_profile import IP, \ @@ -37,6 +39,10 @@ class VppRFC2544Profile(RFC2544Profile): def __init__(self, traffic_generator): super(VppRFC2544Profile, self).__init__(traffic_generator) + tp_cfg = traffic_generator["traffic_profile"] + self.number_of_intermediate_phases = tp_cfg.get("intermediate_phases", + 2) + self.duration = self.config.duration self.precision = self.config.test_precision self.lower_bound = self.config.lower_bound @@ -85,7 +91,7 @@ class VppRFC2544Profile(RFC2544Profile): def _gen_payload(length): payload = "" for _ in range(length): - payload += choice(ascii_letters) + payload += random.choice(string.ascii_letters) return payload @@ -153,8 +159,9 @@ class VppRFC2544Profile(RFC2544Profile): dst=dst_start_ip, proto=outer_l3v4['proto']) if self.flow > 1: - dst_start_int = int(ip_address(str(dst_start_ip))) - dst_end_ip_new = ip_address(dst_start_int + self.flow - 1) + dst_start_int = int(ipaddress.ip_address(str(dst_start_ip))) + dst_end_ip_new = ipaddress.ip_address( + dst_start_int + self.flow - 1) # self._set_proto_addr(IP, SRC, outer_l3v4['srcip4'], outer_l3v4['count']) self._set_proto_addr(IP, DST, "{start_ip}-{end_ip}".format( @@ -248,8 +255,19 @@ class VppRFC2544Profile(RFC2544Profile): def binary_search_with_optimized(self, traffic_generator, duration, timeout, test_data): - # TODO Support FD.io Multiple Loss Ratio search (MLRsearch) - pass + self.queue.cancel_join_thread() + algorithm = MultipleLossRatioSearch( + measurer=traffic_generator, latency=self.enable_latency, + pkt_size=self.pkt_size, + final_trial_duration=duration, + final_relative_width=self.step_interval / 100, + number_of_intermediate_phases=self.number_of_intermediate_phases, + initial_trial_duration=1, + timeout=timeout) + algorithm.init_generator(self.ports, self.port_pg_id, self.profiles, + test_data, self.queue) + return algorithm.narrow_down_ndr_and_pdr(10000, self.max_rate, + self.tolerance_high) def binary_search(self, traffic_generator, duration, tolerance_value, test_data): diff --git a/yardstick/tests/unit/network_services/helpers/vpp_helpers/__init__.py b/yardstick/tests/unit/network_services/helpers/vpp_helpers/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/yardstick/tests/unit/network_services/helpers/vpp_helpers/__init__.py diff --git a/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_multiple_loss_ratio_search.py b/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_multiple_loss_ratio_search.py new file mode 100644 index 000000000..d3145546a --- /dev/null +++ b/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_multiple_loss_ratio_search.py @@ -0,0 +1,2164 @@ +# Copyright (c) 2019 Viosoft Corporation +# +# 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 +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +import mock + +from yardstick.network_services.helpers.vpp_helpers.multiple_loss_ratio_search import \ + MultipleLossRatioSearch +from yardstick.network_services.helpers.vpp_helpers.ndr_pdr_result import \ + NdrPdrResult +from yardstick.network_services.helpers.vpp_helpers.receive_rate_interval import \ + ReceiveRateInterval +from yardstick.network_services.helpers.vpp_helpers.receive_rate_measurement import \ + ReceiveRateMeasurement +from yardstick.network_services.traffic_profile.rfc2544 import PortPgIDMap + + +class TestMultipleLossRatioSearch(unittest.TestCase): + + def test___init__(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + self.assertEqual(True, algorithm.latency) + self.assertEqual(64, algorithm.pkt_size) + self.assertEqual(30, algorithm.final_trial_duration) + self.assertEqual(0.005, algorithm.final_relative_width) + self.assertEqual(2, algorithm.number_of_intermediate_phases) + self.assertEqual(1, algorithm.initial_trial_duration) + self.assertEqual(720, algorithm.timeout) + self.assertEqual(1, algorithm.doublings) + + def test_double_relative_width(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + self.assertEqual(0.00997, algorithm.double_relative_width(0.005)) + + def test_double_step_down(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + self.assertEqual(99003.0, algorithm.double_step_down(0.005, 100000)) + + def test_expand_down(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + self.assertEqual(99003.0, algorithm.expand_down(0.005, 1, 100000)) + + def test_double_step_up(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + self.assertEqual(101007.0401907013, + algorithm.double_step_up(0.005, 100000)) + + def test_expand_up(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + self.assertEqual(101007.0401907013, + algorithm.expand_up(0.005, 1, 100000)) + + def test_half_relative_width(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + self.assertEqual(0.0025031328369998773, + algorithm.half_relative_width(0.005)) + + def test_half_step_up(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + self.assertEqual(100250.94142341711, + algorithm.half_step_up(0.005, 100000)) + + def test_init_generator(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.Mock(), + mock.Mock(), mock.Mock())) + self.assertEqual(ports, algorithm.ports) + self.assertEqual(port_pg_id, algorithm.port_pg_id) + + def test_collect_kpi(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + algorithm.init_generator(ports, port_pg_id, mock.Mock, mock.Mock, + mock.Mock()) + self.assertIsNone(algorithm.collect_kpi({}, 100000)) + + def test_narrow_down_ndr_and_pdr(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock, + mock.Mock())) + with mock.patch.object(algorithm, 'measure') as \ + mock_measure, \ + mock.patch.object(algorithm, 'ndrpdr') as \ + mock_ndrpdr: + ndr_measured_low = ReceiveRateMeasurement(10, 13880000, 13879927, + 0) + ndr_measured_high = ReceiveRateMeasurement(10, 14880000, 14879927, + 0) + ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_low = ReceiveRateMeasurement(10, 11880000, 11879927, + 0) + pdr_measured_high = ReceiveRateMeasurement(10, 12880000, 12879927, + 0) + pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_interval = ReceiveRateInterval(ndr_measured_low, + ndr_measured_high) + pdr_interval = ReceiveRateInterval(pdr_measured_low, + pdr_measured_high) + starting_result = NdrPdrResult(ndr_interval, pdr_interval) + mock_measure.return_value = ReceiveRateMeasurement(1, 14880000, + 14879927, 0) + mock_ndrpdr.return_value = MultipleLossRatioSearch.ProgressState( + starting_result, 2, 30, 0.005, 0.0, + 4857361, 4977343) + self.assertEqual( + {'Result_NDR_LOWER': {'bandwidth_total_Gbps': 0.9327310944, + 'rate_total_pps': 1387992.7}, + 'Result_NDR_UPPER': { + 'bandwidth_total_Gbps': 0.9999310943999999, + 'rate_total_pps': 1487992.7}, + 'Result_NDR_packets_lost': {'packet_loss_ratio': 0.0, + 'packets_lost': 0.0}, + 'Result_PDR_LOWER': { + 'bandwidth_total_Gbps': 0.7983310943999999, + 'rate_total_pps': 1187992.7}, + 'Result_PDR_UPPER': {'bandwidth_total_Gbps': 0.8655310944, + 'rate_total_pps': 1287992.7}, + 'Result_PDR_packets_lost': {'packet_loss_ratio': 0.0, + 'packets_lost': 0.0}, + 'Result_stream0_NDR_LOWER': {'avg_latency': 3081.0, + 'max_latency': 3962.0, + 'min_latency': 1000.0}, + 'Result_stream0_PDR_LOWER': {'avg_latency': 3081.0, + 'max_latency': 3962.0, + 'min_latency': 1000.0}, + 'Result_stream1_NDR_LOWER': {'avg_latency': 3149.0, + 'max_latency': 3730.0, + 'min_latency': 500.0}, + 'Result_stream1_PDR_LOWER': {'avg_latency': 3149.0, + 'max_latency': 3730.0, + 'min_latency': 500.0}}, + algorithm.narrow_down_ndr_and_pdr(12880000, 15880000, 0.0)) + + def test__measure_and_update_state(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + starting_interval = ReceiveRateInterval(measured_low, measured_high) + starting_result = NdrPdrResult(starting_interval, starting_interval) + previous_state = MultipleLossRatioSearch.ProgressState(starting_result, + 2, 30, 0.005, + 0.0, 4857361, + 4977343) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock, + mock.Mock())) + with mock.patch.object(algorithm, 'measure') as \ + mock_measure: + mock_measure.return_value = ReceiveRateMeasurement(1, + 4626121.09635, + 4626100, 13074) + state = algorithm._measure_and_update_state(previous_state, + 4626121.09635) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertEqual(1, state.result.ndr_interval.measured_low.duration) + self.assertEqual(4626121.09635, + state.result.ndr_interval.measured_low.target_tr) + self.assertEqual(4626100, + state.result.ndr_interval.measured_low.transmit_count) + self.assertEqual(13074, + state.result.ndr_interval.measured_low.loss_count) + self.assertEqual(4613026, + state.result.ndr_interval.measured_low.receive_count) + self.assertEqual(4626100, + state.result.ndr_interval.measured_low.transmit_rate) + self.assertEqual(13074.0, + state.result.ndr_interval.measured_low.loss_rate) + self.assertEqual(4613026.0, + state.result.ndr_interval.measured_low.receive_rate) + self.assertEqual(0.00283, + state.result.ndr_interval.measured_low.loss_fraction) + self.assertEqual(1, state.result.ndr_interval.measured_high.duration) + self.assertEqual(4857361, + state.result.ndr_interval.measured_high.target_tr) + self.assertEqual(4857339, + state.result.ndr_interval.measured_high.transmit_count) + self.assertEqual(84965, + state.result.ndr_interval.measured_high.loss_count) + self.assertEqual(4772374, + state.result.ndr_interval.measured_high.receive_count) + self.assertEqual(4857339, + state.result.ndr_interval.measured_high.transmit_rate) + self.assertEqual(84965.0, + state.result.ndr_interval.measured_high.loss_rate) + self.assertEqual(4772374.0, + state.result.ndr_interval.measured_high.receive_rate) + self.assertEqual(0.01749, + state.result.ndr_interval.measured_high.loss_fraction) + self.assertEqual(1, state.result.pdr_interval.measured_low.duration) + self.assertEqual(4626121.09635, + state.result.pdr_interval.measured_low.target_tr) + self.assertEqual(4626100, + state.result.pdr_interval.measured_low.transmit_count) + self.assertEqual(13074, + state.result.pdr_interval.measured_low.loss_count) + self.assertEqual(4613026, + state.result.pdr_interval.measured_low.receive_count) + self.assertEqual(4626100, + state.result.pdr_interval.measured_low.transmit_rate) + self.assertEqual(13074.0, + state.result.pdr_interval.measured_low.loss_rate) + self.assertEqual(4613026.0, + state.result.pdr_interval.measured_low.receive_rate) + self.assertEqual(0.00283, + state.result.pdr_interval.measured_low.loss_fraction) + self.assertEqual(1, state.result.pdr_interval.measured_high.duration) + self.assertEqual(4857361, + state.result.pdr_interval.measured_high.target_tr) + self.assertEqual(4857339, + state.result.pdr_interval.measured_high.transmit_count) + self.assertEqual(84965, + state.result.pdr_interval.measured_high.loss_count) + self.assertEqual(4772374, + state.result.pdr_interval.measured_high.receive_count) + self.assertEqual(4857339, + state.result.pdr_interval.measured_high.transmit_rate) + self.assertEqual(84965.0, + state.result.pdr_interval.measured_high.loss_rate) + self.assertEqual(4772374.0, + state.result.pdr_interval.measured_high.receive_rate) + self.assertEqual(0.01749, + state.result.pdr_interval.measured_high.loss_fraction) + self.assertEqual(2, state.phases) + self.assertEqual(30, state.duration) + self.assertEqual(0.005, state.width_goal) + self.assertEqual(0.0, state.packet_loss_ratio) + self.assertEqual(4857361, state.minimum_transmit_rate) + self.assertEqual(4977343, state.maximum_transmit_rate) + + def test_new_interval(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + measured = ReceiveRateMeasurement(1, 3972540.4108, 21758482, 0) + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + receive_rate_interval = ReceiveRateInterval(measured_low, + measured_high) + result = algorithm._new_interval(receive_rate_interval, measured, 0.0) + self.assertIsInstance(result, ReceiveRateInterval) + self.assertEqual(1, result.measured_low.duration) + self.assertEqual(3972540.4108, result.measured_low.target_tr) + self.assertEqual(21758482, result.measured_low.transmit_count) + self.assertEqual(0, result.measured_low.loss_count) + self.assertEqual(21758482, result.measured_low.receive_count) + self.assertEqual(21758482, result.measured_low.transmit_rate) + self.assertEqual(0.0, result.measured_low.loss_rate) + self.assertEqual(21758482.0, result.measured_low.receive_rate) + self.assertEqual(0.0, result.measured_low.loss_fraction) + self.assertEqual(1, result.measured_high.duration) + self.assertEqual(4857361, result.measured_high.target_tr) + self.assertEqual(4857339, result.measured_high.transmit_count) + self.assertEqual(84965, result.measured_high.loss_count) + self.assertEqual(4772374, result.measured_high.receive_count) + self.assertEqual(4857339, result.measured_high.transmit_rate) + self.assertEqual(84965.0, result.measured_high.loss_rate) + self.assertEqual(4772374.0, result.measured_high.receive_rate) + self.assertEqual(0.01749, result.measured_high.loss_fraction) + + def test_new_interval_zero(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + measured = ReceiveRateMeasurement(1, 4977343, 21758482, 0) + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + receive_rate_interval = ReceiveRateInterval(measured_low, + measured_high) + result = algorithm._new_interval(receive_rate_interval, measured, 0.0) + self.assertIsInstance(result, ReceiveRateInterval) + self.assertEqual(1, result.measured_low.duration) + self.assertEqual(4857361.0, result.measured_low.target_tr) + self.assertEqual(4857339, result.measured_low.transmit_count) + self.assertEqual(84965, result.measured_low.loss_count) + self.assertEqual(4772374, result.measured_low.receive_count) + self.assertEqual(4857339.0, result.measured_low.transmit_rate) + self.assertEqual(84965.0, result.measured_low.loss_rate) + self.assertEqual(4772374.0, result.measured_low.receive_rate) + self.assertEqual(0.01749, result.measured_low.loss_fraction) + self.assertEqual(1, result.measured_high.duration) + self.assertEqual(4977343.0, result.measured_high.target_tr) + self.assertEqual(21758482, result.measured_high.transmit_count) + self.assertEqual(0, result.measured_high.loss_count) + self.assertEqual(21758482, result.measured_high.receive_count) + self.assertEqual(21758482.0, result.measured_high.transmit_rate) + self.assertEqual(0.0, result.measured_high.loss_rate) + self.assertEqual(21758482.0, result.measured_high.receive_rate) + self.assertEqual(0.0, result.measured_high.loss_fraction) + + def test_new_interval_one(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + measured = ReceiveRateMeasurement(1, 5000000, 2175848, 0) + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + receive_rate_interval = ReceiveRateInterval(measured_low, + measured_high) + result = algorithm._new_interval(receive_rate_interval, measured, 0.0) + self.assertIsInstance(result, ReceiveRateInterval) + self.assertEqual(1, result.measured_low.duration) + self.assertEqual(4857361.0, result.measured_low.target_tr) + self.assertEqual(4857339, result.measured_low.transmit_count) + self.assertEqual(84965, result.measured_low.loss_count) + self.assertEqual(4772374, result.measured_low.receive_count) + self.assertEqual(4857339.0, result.measured_low.transmit_rate) + self.assertEqual(84965.0, result.measured_low.loss_rate) + self.assertEqual(4772374.0, result.measured_low.receive_rate) + self.assertEqual(0.01749, result.measured_low.loss_fraction) + self.assertEqual(1, result.measured_high.duration) + self.assertEqual(4977343.0, result.measured_high.target_tr) + self.assertEqual(4977320, result.measured_high.transmit_count) + self.assertEqual(119959, result.measured_high.loss_count) + self.assertEqual(4857361, result.measured_high.receive_count) + self.assertEqual(4977320.0, result.measured_high.transmit_rate) + self.assertEqual(119959.0, result.measured_high.loss_rate) + self.assertEqual(4857361.0, result.measured_high.receive_rate) + self.assertEqual(0.0241, result.measured_high.loss_fraction) + + def test_new_interval_valid_1st(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + measured = ReceiveRateMeasurement(1, 4000000, 2175848, 0) + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + receive_rate_interval = ReceiveRateInterval(measured_low, + measured_high) + result = algorithm._new_interval(receive_rate_interval, measured, 0.5) + self.assertIsInstance(result, ReceiveRateInterval) + self.assertEqual(1, result.measured_low.duration) + self.assertEqual(4857361.0, result.measured_low.target_tr) + self.assertEqual(4857339, result.measured_low.transmit_count) + self.assertEqual(84965, result.measured_low.loss_count) + self.assertEqual(4772374, result.measured_low.receive_count) + self.assertEqual(4857339.0, result.measured_low.transmit_rate) + self.assertEqual(84965.0, result.measured_low.loss_rate) + self.assertEqual(4772374.0, result.measured_low.receive_rate) + self.assertEqual(0.01749, result.measured_low.loss_fraction) + self.assertEqual(1, result.measured_high.duration) + self.assertEqual(4977343.0, result.measured_high.target_tr) + self.assertEqual(4977320, result.measured_high.transmit_count) + self.assertEqual(119959, result.measured_high.loss_count) + self.assertEqual(4857361, result.measured_high.receive_count) + self.assertEqual(4977320.0, result.measured_high.transmit_rate) + self.assertEqual(119959.0, result.measured_high.loss_rate) + self.assertEqual(4857361.0, result.measured_high.receive_rate) + self.assertEqual(0.0241, result.measured_high.loss_fraction) + + def test_new_interval_valid_1st_loss(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + measured = ReceiveRateMeasurement(1, 4000000, 2175848, 1000000) + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + receive_rate_interval = ReceiveRateInterval(measured_low, + measured_high) + result = algorithm._new_interval(receive_rate_interval, measured, 0.02) + self.assertIsInstance(result, ReceiveRateInterval) + self.assertEqual(1, result.measured_low.duration) + self.assertEqual(4000000.0, result.measured_low.target_tr) + self.assertEqual(2175848, result.measured_low.transmit_count) + self.assertEqual(1000000, result.measured_low.loss_count) + self.assertEqual(1175848, result.measured_low.receive_count) + self.assertEqual(2175848.0, result.measured_low.transmit_rate) + self.assertEqual(1000000.0, result.measured_low.loss_rate) + self.assertEqual(1175848.0, result.measured_low.receive_rate) + self.assertEqual(0.45959, result.measured_low.loss_fraction) + self.assertEqual(1, result.measured_high.duration) + self.assertEqual(4977343.0, result.measured_high.target_tr) + self.assertEqual(4977320, result.measured_high.transmit_count) + self.assertEqual(119959, result.measured_high.loss_count) + self.assertEqual(4857361, result.measured_high.receive_count) + self.assertEqual(4977320.0, result.measured_high.transmit_rate) + self.assertEqual(119959.0, result.measured_high.loss_rate) + self.assertEqual(4857361.0, result.measured_high.receive_rate) + self.assertEqual(0.0241, result.measured_high.loss_fraction) + + def test_new_interval_valid_2nd(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + measured = ReceiveRateMeasurement(1, 5000000, 2175848, 0) + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + receive_rate_interval = ReceiveRateInterval(measured_low, + measured_high) + result = algorithm._new_interval(receive_rate_interval, measured, 0.5) + self.assertIsInstance(result, ReceiveRateInterval) + self.assertEqual(1, result.measured_low.duration) + self.assertEqual(4977343.0, result.measured_low.target_tr) + self.assertEqual(4977320, result.measured_low.transmit_count) + self.assertEqual(119959, result.measured_low.loss_count) + self.assertEqual(4857361, result.measured_low.receive_count) + self.assertEqual(4977320.0, result.measured_low.transmit_rate) + self.assertEqual(119959.0, result.measured_low.loss_rate) + self.assertEqual(4857361.0, result.measured_low.receive_rate) + self.assertEqual(0.0241, result.measured_low.loss_fraction) + self.assertEqual(1, result.measured_high.duration) + self.assertEqual(5000000.0, result.measured_high.target_tr) + self.assertEqual(2175848, result.measured_high.transmit_count) + self.assertEqual(0, result.measured_high.loss_count) + self.assertEqual(2175848, result.measured_high.receive_count) + self.assertEqual(2175848.0, result.measured_high.transmit_rate) + self.assertEqual(0.0, result.measured_high.loss_rate) + self.assertEqual(2175848.0, result.measured_high.receive_rate) + self.assertEqual(0.0, result.measured_high.loss_fraction) + + def test_new_interval_valid_3rd(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + measured = ReceiveRateMeasurement(1, 4867361, 2175848, 0) + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + receive_rate_interval = ReceiveRateInterval(measured_low, + measured_high) + result = algorithm._new_interval(receive_rate_interval, measured, 0.5) + self.assertIsInstance(result, ReceiveRateInterval) + self.assertEqual(1, result.measured_low.duration) + self.assertEqual(4867361.0, result.measured_low.target_tr) + self.assertEqual(2175848, result.measured_low.transmit_count) + self.assertEqual(0, result.measured_low.loss_count) + self.assertEqual(2175848, result.measured_low.receive_count) + self.assertEqual(2175848.0, result.measured_low.transmit_rate) + self.assertEqual(0.0, result.measured_low.loss_rate) + self.assertEqual(2175848.0, result.measured_low.receive_rate) + self.assertEqual(0.0, result.measured_low.loss_fraction) + self.assertEqual(1, result.measured_high.duration) + self.assertEqual(4977343.0, result.measured_high.target_tr) + self.assertEqual(4977320, result.measured_high.transmit_count) + self.assertEqual(119959, result.measured_high.loss_count) + self.assertEqual(4857361, result.measured_high.receive_count) + self.assertEqual(4977320.0, result.measured_high.transmit_rate) + self.assertEqual(119959.0, result.measured_high.loss_rate) + self.assertEqual(4857361.0, result.measured_high.receive_rate) + self.assertEqual(0.0241, result.measured_high.loss_fraction) + + def test_new_interval_valid_3rd_loss(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + measured = ReceiveRateMeasurement(1, 4867361, 2175848, 1000000) + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + receive_rate_interval = ReceiveRateInterval(measured_low, + measured_high) + result = algorithm._new_interval(receive_rate_interval, measured, 0.2) + self.assertIsInstance(result, ReceiveRateInterval) + self.assertEqual(1, result.measured_low.duration) + self.assertEqual(4857361.0, result.measured_low.target_tr) + self.assertEqual(4857339, result.measured_low.transmit_count) + self.assertEqual(84965, result.measured_low.loss_count) + self.assertEqual(4772374, result.measured_low.receive_count) + self.assertEqual(4857339.0, result.measured_low.transmit_rate) + self.assertEqual(84965.0, result.measured_low.loss_rate) + self.assertEqual(4772374.0, result.measured_low.receive_rate) + self.assertEqual(0.01749, result.measured_low.loss_fraction) + self.assertEqual(1, result.measured_high.duration) + self.assertEqual(4867361.0, result.measured_high.target_tr) + self.assertEqual(2175848, result.measured_high.transmit_count) + self.assertEqual(1000000, result.measured_high.loss_count) + self.assertEqual(1175848, result.measured_high.receive_count) + self.assertEqual(2175848.0, result.measured_high.transmit_rate) + self.assertEqual(1000000.0, result.measured_high.loss_rate) + self.assertEqual(1175848.0, result.measured_high.receive_rate) + self.assertEqual(0.45959, result.measured_high.loss_fraction) + + def test_ndrpdr(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock, + mock.Mock())) + with mock.patch.object(algorithm, 'measure') as \ + mock_measure: + measured_low = ReceiveRateMeasurement(30, 14880000, 14879927, 0) + measured_high = ReceiveRateMeasurement(30, 14880000, 14879927, 0) + measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + starting_interval = ReceiveRateInterval(measured_low, + measured_high) + starting_result = NdrPdrResult(starting_interval, + starting_interval) + mock_measure.return_value = ReceiveRateMeasurement(1, 14880000, + 14879927, 0) + previous_state = MultipleLossRatioSearch.ProgressState( + starting_result, -1, 30, 0.005, 0.0, 14880000, + 14880000) + state = algorithm.ndrpdr(previous_state) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertEqual(30, state.result.ndr_interval.measured_low.duration) + self.assertEqual(14880000, + state.result.ndr_interval.measured_low.target_tr) + self.assertEqual(14879927, + state.result.ndr_interval.measured_low.transmit_count) + self.assertEqual(0, state.result.ndr_interval.measured_low.loss_count) + self.assertEqual(14879927, + state.result.ndr_interval.measured_low.receive_count) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, state.result.ndr_interval.measured_low.loss_rate) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.ndr_interval.measured_high.duration) + self.assertEqual(14880000, + state.result.ndr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.ndr_interval.measured_high.transmit_count) + self.assertEqual(0, state.result.ndr_interval.measured_high.loss_count) + self.assertEqual(14879927, + state.result.ndr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_high.transmit_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_high.loss_rate) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_high.receive_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_high.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_low.duration) + self.assertEqual(14880000, + state.result.pdr_interval.measured_low.target_tr) + self.assertEqual(14879927, + state.result.pdr_interval.measured_low.transmit_count) + self.assertEqual(0, state.result.pdr_interval.measured_low.loss_count) + self.assertEqual(14879927, + state.result.pdr_interval.measured_low.receive_count) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, state.result.pdr_interval.measured_low.loss_rate) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_high.duration) + self.assertEqual(14880000, + state.result.pdr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.pdr_interval.measured_high.transmit_count) + self.assertEqual(0, state.result.pdr_interval.measured_high.loss_count) + self.assertEqual(14879927, + state.result.pdr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_high.transmit_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_high.loss_rate) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_high.receive_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_high.loss_fraction) + self.assertEqual(-1, state.phases) + self.assertEqual(30, state.duration) + self.assertEqual(0.005, state.width_goal) + self.assertEqual(0.0, state.packet_loss_ratio) + self.assertEqual(14880000, state.minimum_transmit_rate) + self.assertEqual(14880000, state.maximum_transmit_rate) + + def test_ndrpdr_ndr_rel_width(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock, + mock.Mock())) + with mock.patch.object(algorithm, 'measure') as \ + mock_measure, \ + mock.patch.object(algorithm, '_measure_and_update_state') as \ + mock__measure_and_update_state: + measured_low = ReceiveRateMeasurement(30, 880000, 879927, 0) + measured_high = ReceiveRateMeasurement(30, 14880000, 14879927, 0) + measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + starting_interval = ReceiveRateInterval(measured_low, + measured_high) + ending_interval = ReceiveRateInterval(measured_high, measured_high) + starting_result = NdrPdrResult(starting_interval, + starting_interval) + ending_result = NdrPdrResult(ending_interval, ending_interval) + mock_measure.return_value = ReceiveRateMeasurement(1, 14880000, + 14879927, 0) + mock__measure_and_update_state.return_value = \ + MultipleLossRatioSearch.ProgressState(ending_result, -1, 30, + 0.005, 0.0, 14880000, + 14880000) + previous_state = MultipleLossRatioSearch.ProgressState( + starting_result, -1, 30, 0.005, 0.0, 14880000, + 14880000) + state = algorithm.ndrpdr(previous_state) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertEqual(30, state.result.ndr_interval.measured_low.duration) + self.assertEqual(14880000, + state.result.ndr_interval.measured_low.target_tr) + self.assertEqual(14879927, + state.result.ndr_interval.measured_low.transmit_count) + self.assertEqual(0, state.result.ndr_interval.measured_low.loss_count) + self.assertEqual(14879927, + state.result.ndr_interval.measured_low.receive_count) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, state.result.ndr_interval.measured_low.loss_rate) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.ndr_interval.measured_high.duration) + self.assertEqual(14880000, + state.result.ndr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.ndr_interval.measured_high.transmit_count) + self.assertEqual(0, state.result.ndr_interval.measured_high.loss_count) + self.assertEqual(14879927, + state.result.ndr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_high.transmit_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_high.loss_rate) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_high.receive_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_high.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_low.duration) + self.assertEqual(14880000, + state.result.pdr_interval.measured_low.target_tr) + self.assertEqual(14879927, + state.result.pdr_interval.measured_low.transmit_count) + self.assertEqual(0, state.result.pdr_interval.measured_low.loss_count) + self.assertEqual(14879927, + state.result.pdr_interval.measured_low.receive_count) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, state.result.pdr_interval.measured_low.loss_rate) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_high.duration) + self.assertEqual(14880000, + state.result.pdr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.pdr_interval.measured_high.transmit_count) + self.assertEqual(0, state.result.pdr_interval.measured_high.loss_count) + self.assertEqual(14879927, + state.result.pdr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_high.transmit_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_high.loss_rate) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_high.receive_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_high.loss_fraction) + self.assertEqual(-1, state.phases) + self.assertEqual(30, state.duration) + self.assertEqual(0.005, state.width_goal) + self.assertEqual(0.0, state.packet_loss_ratio) + self.assertEqual(14880000, state.minimum_transmit_rate) + self.assertEqual(14880000, state.maximum_transmit_rate) + + def test_ndrpdr_pdr_rel_width(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock, + mock.Mock())) + with mock.patch.object(algorithm, 'measure') as \ + mock_measure, \ + mock.patch.object(algorithm, '_measure_and_update_state') as \ + mock__measure_and_update_state: + ndr_measured_low = ReceiveRateMeasurement(30, 14880000, 14879927, + 0) + ndr_measured_high = ReceiveRateMeasurement(30, 14880000, 14879927, + 0) + ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_low = ReceiveRateMeasurement(30, 880000, 879927, 0) + pdr_measured_high = ReceiveRateMeasurement(30, 14880000, 14879927, + 0) + pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_interval = ReceiveRateInterval(ndr_measured_low, + ndr_measured_high) + pdr_interval = ReceiveRateInterval(pdr_measured_low, + pdr_measured_high) + starting_result = NdrPdrResult(ndr_interval, pdr_interval) + ending_result = NdrPdrResult(ndr_interval, ndr_interval) + mock_measure.return_value = ReceiveRateMeasurement(1, 14880000, + 14879927, 0) + mock__measure_and_update_state.return_value = \ + MultipleLossRatioSearch.ProgressState(ending_result, -1, 30, + 0.005, 0.0, 14880000, + 14880000) + previous_state = MultipleLossRatioSearch.ProgressState( + starting_result, -1, 30, 0.005, 0.0, 14880000, + 14880000) + state = algorithm.ndrpdr(previous_state) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertEqual(30, state.result.ndr_interval.measured_low.duration) + self.assertEqual(14880000, + state.result.ndr_interval.measured_low.target_tr) + self.assertEqual(14879927, + state.result.ndr_interval.measured_low.transmit_count) + self.assertEqual(0, state.result.ndr_interval.measured_low.loss_count) + self.assertEqual(14879927, + state.result.ndr_interval.measured_low.receive_count) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, state.result.ndr_interval.measured_low.loss_rate) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.ndr_interval.measured_high.duration) + self.assertEqual(14880000, + state.result.ndr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.ndr_interval.measured_high.transmit_count) + self.assertEqual(0, state.result.ndr_interval.measured_high.loss_count) + self.assertEqual(14879927, + state.result.ndr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_high.transmit_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_high.loss_rate) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_high.receive_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_high.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_low.duration) + self.assertEqual(14880000, + state.result.pdr_interval.measured_low.target_tr) + self.assertEqual(14879927, + state.result.pdr_interval.measured_low.transmit_count) + self.assertEqual(0, state.result.pdr_interval.measured_low.loss_count) + self.assertEqual(14879927, + state.result.pdr_interval.measured_low.receive_count) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, state.result.pdr_interval.measured_low.loss_rate) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_high.duration) + self.assertEqual(14880000, + state.result.pdr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.pdr_interval.measured_high.transmit_count) + self.assertEqual(0, state.result.pdr_interval.measured_high.loss_count) + self.assertEqual(14879927, + state.result.pdr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_high.transmit_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_high.loss_rate) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_high.receive_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_high.loss_fraction) + self.assertEqual(-1, state.phases) + self.assertEqual(30, state.duration) + self.assertEqual(0.005, state.width_goal) + self.assertEqual(0.0, state.packet_loss_ratio) + self.assertEqual(14880000, state.minimum_transmit_rate) + self.assertEqual(14880000, state.maximum_transmit_rate) + + def test_ndrpdr_ndr_lo_duration(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock, + mock.Mock())) + with mock.patch.object(algorithm, 'measure') as \ + mock_measure, \ + mock.patch.object(algorithm, '_measure_and_update_state') as \ + mock__measure_and_update_state: + measured_low = ReceiveRateMeasurement(30, 14880000, 14879927, 0) + measured_high = ReceiveRateMeasurement(30, 14880000, 14879927, 100) + measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + starting_interval = ReceiveRateInterval(measured_low, + measured_high) + starting_result = NdrPdrResult(starting_interval, + starting_interval) + mock_measure.return_value = ReceiveRateMeasurement(1, 14880000, + 14879927, 0) + mock__measure_and_update_state.return_value = \ + MultipleLossRatioSearch.ProgressState(starting_result, -1, 30, + 0.005, 0.0, 14880000, + 14880000) + previous_state = MultipleLossRatioSearch.ProgressState( + starting_result, -1, 50, 0.005, 0.0, 14880000, + 14880000) + state = algorithm.ndrpdr(previous_state) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertEqual(30, state.result.ndr_interval.measured_low.duration) + self.assertEqual(14880000, + state.result.ndr_interval.measured_low.target_tr) + self.assertEqual(14879927, + state.result.ndr_interval.measured_low.transmit_count) + self.assertEqual(0, state.result.ndr_interval.measured_low.loss_count) + self.assertEqual(14879927, + state.result.ndr_interval.measured_low.receive_count) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, state.result.ndr_interval.measured_low.loss_rate) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.ndr_interval.measured_high.duration) + self.assertEqual(14880000, + state.result.ndr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.ndr_interval.measured_high.transmit_count) + self.assertEqual(100, + state.result.ndr_interval.measured_high.loss_count) + self.assertEqual(14879827, + state.result.ndr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_high.transmit_rate) + self.assertEqual(3.33333, + state.result.ndr_interval.measured_high.loss_rate) + self.assertEqual(495994.23333, + state.result.ndr_interval.measured_high.receive_rate) + self.assertEqual(1e-05, + state.result.ndr_interval.measured_high.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_low.duration) + self.assertEqual(14880000, + state.result.pdr_interval.measured_low.target_tr) + self.assertEqual(14879927, + state.result.pdr_interval.measured_low.transmit_count) + self.assertEqual(0, state.result.pdr_interval.measured_low.loss_count) + self.assertEqual(14879927, + state.result.pdr_interval.measured_low.receive_count) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, state.result.pdr_interval.measured_low.loss_rate) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_high.duration) + self.assertEqual(14880000, + state.result.pdr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.pdr_interval.measured_high.transmit_count) + self.assertEqual(100, + state.result.pdr_interval.measured_high.loss_count) + self.assertEqual(14879827, + state.result.pdr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_high.transmit_rate) + self.assertEqual(3.33333, + state.result.pdr_interval.measured_high.loss_rate) + self.assertEqual(495994.23333, + state.result.pdr_interval.measured_high.receive_rate) + self.assertEqual(1e-05, + state.result.pdr_interval.measured_high.loss_fraction) + self.assertEqual(-1, state.phases) + self.assertEqual(30, state.duration) + self.assertEqual(0.005, state.width_goal) + self.assertEqual(0.0, state.packet_loss_ratio) + self.assertEqual(14880000, state.minimum_transmit_rate) + self.assertEqual(14880000, state.maximum_transmit_rate) + + def test_ndrpdr_ndr_hi_duration(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock, + mock.Mock())) + with mock.patch.object(algorithm, 'measure') as \ + mock_measure, \ + mock.patch.object(algorithm, '_measure_and_update_state') as \ + mock__measure_and_update_state: + measured_low = ReceiveRateMeasurement(60, 14880000, 14879927, 0) + measured_high = ReceiveRateMeasurement(30, 14880000, 14879927, 100) + measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + starting_interval = ReceiveRateInterval(measured_low, + measured_high) + starting_result = NdrPdrResult(starting_interval, + starting_interval) + mock_measure.return_value = ReceiveRateMeasurement(1, 14880000, + 14879927, 0) + mock__measure_and_update_state.return_value = \ + MultipleLossRatioSearch.ProgressState(starting_result, -1, 30, + 0.005, 0.0, 14880000, + 14880000) + previous_state = MultipleLossRatioSearch.ProgressState( + starting_result, -1, 50, 0.005, 0.0, 14880000, + 14880000) + state = algorithm.ndrpdr(previous_state) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertEqual(60.0, state.result.ndr_interval.measured_low.duration) + self.assertEqual(14880000, + state.result.ndr_interval.measured_low.target_tr) + self.assertEqual(14879927, + state.result.ndr_interval.measured_low.transmit_count) + self.assertEqual(0, state.result.ndr_interval.measured_low.loss_count) + self.assertEqual(14879927, + state.result.ndr_interval.measured_low.receive_count) + self.assertEqual(247998.78333, + state.result.ndr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, state.result.ndr_interval.measured_low.loss_rate) + self.assertEqual(247998.78333, + state.result.ndr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.ndr_interval.measured_high.duration) + self.assertEqual(14880000, + state.result.ndr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.ndr_interval.measured_high.transmit_count) + self.assertEqual(100, + state.result.ndr_interval.measured_high.loss_count) + self.assertEqual(14879827, + state.result.ndr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_high.transmit_rate) + self.assertEqual(3.33333, + state.result.ndr_interval.measured_high.loss_rate) + self.assertEqual(495994.23333, + state.result.ndr_interval.measured_high.receive_rate) + self.assertEqual(1e-05, + state.result.ndr_interval.measured_high.loss_fraction) + self.assertEqual(60.0, state.result.pdr_interval.measured_low.duration) + self.assertEqual(14880000, + state.result.pdr_interval.measured_low.target_tr) + self.assertEqual(14879927, + state.result.pdr_interval.measured_low.transmit_count) + self.assertEqual(0, state.result.pdr_interval.measured_low.loss_count) + self.assertEqual(14879927, + state.result.pdr_interval.measured_low.receive_count) + self.assertEqual(247998.78333, + state.result.pdr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, state.result.pdr_interval.measured_low.loss_rate) + self.assertEqual(247998.78333, + state.result.pdr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_high.duration) + self.assertEqual(14880000, + state.result.pdr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.pdr_interval.measured_high.transmit_count) + self.assertEqual(100, + state.result.pdr_interval.measured_high.loss_count) + self.assertEqual(14879827, + state.result.pdr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_high.transmit_rate) + self.assertEqual(3.33333, + state.result.pdr_interval.measured_high.loss_rate) + self.assertEqual(495994.23333, + state.result.pdr_interval.measured_high.receive_rate) + self.assertEqual(1e-05, + state.result.pdr_interval.measured_high.loss_fraction) + self.assertEqual(-1, state.phases) + self.assertEqual(30, state.duration) + self.assertEqual(0.005, state.width_goal) + self.assertEqual(0.0, state.packet_loss_ratio) + self.assertEqual(14880000, state.minimum_transmit_rate) + self.assertEqual(14880000, state.maximum_transmit_rate) + + def test_ndrpdr_error(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=0) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock, + mock.Mock())) + with mock.patch.object(algorithm, 'measure') as \ + mock_measure: + measured_low = ReceiveRateMeasurement(30, 14880000, 14879927, 0) + measured_high = ReceiveRateMeasurement(30, 14880000, 14879927, 0) + measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + starting_interval = ReceiveRateInterval(measured_low, + measured_high) + starting_result = NdrPdrResult(starting_interval, + starting_interval) + mock_measure.return_value = ReceiveRateMeasurement(1, 14880000, + 14879927, 0) + previous_state = MultipleLossRatioSearch.ProgressState( + starting_result, -1, 30, 0.005, 0.0, 14880000, + 14880000) + with self.assertRaises(RuntimeError) as raised: + algorithm.ndrpdr(previous_state) + + self.assertIn('Optimized search takes too long.', + str(raised.exception)) + + def test_ndrpdr_update_state_ndr_hi(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock, + mock.Mock())) + with mock.patch.object(algorithm, 'measure') as \ + mock_measure, \ + mock.patch.object(algorithm, '_measure_and_update_state') as \ + mock__measure_and_update_state: + ndr_measured_low = ReceiveRateMeasurement(30, 10880000, 10879927, + 0) + ndr_measured_high = ReceiveRateMeasurement(30, 12880000, 12879927, + 0) + ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_low = ReceiveRateMeasurement(30, 12880000, 12879927, + 0) + pdr_measured_high = ReceiveRateMeasurement(30, 14880000, 14879927, + 0) + pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_interval = ReceiveRateInterval(ndr_measured_low, + ndr_measured_high) + pdr_interval = ReceiveRateInterval(pdr_measured_low, + pdr_measured_high) + starting_result = NdrPdrResult(ndr_interval, pdr_interval) + ending_result = NdrPdrResult(pdr_interval, pdr_interval) + mock_measure.return_value = ReceiveRateMeasurement(1, 14880000, + 14879927, 0) + mock__measure_and_update_state.return_value = \ + MultipleLossRatioSearch.ProgressState(ending_result, -1, 30, + 0.2, 0.0, 14880000, + 14880000) + previous_state = MultipleLossRatioSearch.ProgressState( + starting_result, -1, 30, 0.005, 0.0, 14880000, + 14880000) + state = algorithm.ndrpdr(previous_state) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertEqual(30, state.result.ndr_interval.measured_low.duration) + self.assertEqual(12880000.0, + state.result.ndr_interval.measured_low.target_tr) + self.assertEqual(12879927, + state.result.ndr_interval.measured_low.transmit_count) + self.assertEqual(0, state.result.ndr_interval.measured_low.loss_count) + self.assertEqual(12879927, + state.result.ndr_interval.measured_low.receive_count) + self.assertEqual(429330.9, + state.result.ndr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, state.result.ndr_interval.measured_low.loss_rate) + self.assertEqual(429330.9, + state.result.ndr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.ndr_interval.measured_high.duration) + self.assertEqual(14880000.0, + state.result.ndr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.ndr_interval.measured_high.transmit_count) + self.assertEqual(0, state.result.ndr_interval.measured_high.loss_count) + self.assertEqual(14879927, + state.result.ndr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_high.transmit_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_high.loss_rate) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_high.receive_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_high.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_low.duration) + self.assertEqual(12880000.0, + state.result.pdr_interval.measured_low.target_tr) + self.assertEqual(12879927, + state.result.pdr_interval.measured_low.transmit_count) + self.assertEqual(0, state.result.pdr_interval.measured_low.loss_count) + self.assertEqual(12879927, + state.result.pdr_interval.measured_low.receive_count) + self.assertEqual(429330.9, + state.result.pdr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, state.result.pdr_interval.measured_low.loss_rate) + self.assertEqual(429330.9, + state.result.pdr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_high.duration) + self.assertEqual(14880000, + state.result.pdr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.pdr_interval.measured_high.transmit_count) + self.assertEqual(0, state.result.pdr_interval.measured_high.loss_count) + self.assertEqual(14879927, + state.result.pdr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_high.transmit_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_high.loss_rate) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_high.receive_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_high.loss_fraction) + self.assertEqual(-1, state.phases) + self.assertEqual(30, state.duration) + self.assertEqual(0.2, state.width_goal) + self.assertEqual(0.0, state.packet_loss_ratio) + self.assertEqual(14880000, state.minimum_transmit_rate) + self.assertEqual(14880000, state.maximum_transmit_rate) + + def test_ndrpdr_update_state_ndr_hi_duration(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock, + mock.Mock())) + with mock.patch.object(algorithm, 'measure') as \ + mock_measure, \ + mock.patch.object(algorithm, '_measure_and_update_state') as \ + mock__measure_and_update_state: + ndr_measured_low = ReceiveRateMeasurement(30, 10880000, 10879927, + 0) + ndr_measured_high = ReceiveRateMeasurement(30, 12880000, 12879927, + 0) + ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_low = ReceiveRateMeasurement(30, 12880000, 12879927, + 0) + pdr_measured_high = ReceiveRateMeasurement(30, 14880000, 14879927, + 0) + pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_interval = ReceiveRateInterval(ndr_measured_low, + ndr_measured_high) + pdr_interval = ReceiveRateInterval(pdr_measured_low, + pdr_measured_high) + starting_result = NdrPdrResult(ndr_interval, pdr_interval) + ending_result = NdrPdrResult(pdr_interval, pdr_interval) + mock_measure.return_value = ReceiveRateMeasurement(1, 14880000, + 14879927, 0) + mock__measure_and_update_state.return_value = \ + MultipleLossRatioSearch.ProgressState(ending_result, -1, 30, + 0.2, 0.0, 14880000, + 14880000) + previous_state = MultipleLossRatioSearch.ProgressState( + starting_result, -1, 50, 0.005, 0.0, 4880000, + 10880000) + state = algorithm.ndrpdr(previous_state) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertEqual(30, state.result.ndr_interval.measured_low.duration) + self.assertEqual(12880000.0, + state.result.ndr_interval.measured_low.target_tr) + self.assertEqual(12879927, + state.result.ndr_interval.measured_low.transmit_count) + self.assertEqual(0, state.result.ndr_interval.measured_low.loss_count) + self.assertEqual(12879927, + state.result.ndr_interval.measured_low.receive_count) + self.assertEqual(429330.9, + state.result.ndr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, state.result.ndr_interval.measured_low.loss_rate) + self.assertEqual(429330.9, + state.result.ndr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.ndr_interval.measured_high.duration) + self.assertEqual(14880000.0, + state.result.ndr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.ndr_interval.measured_high.transmit_count) + self.assertEqual(0, state.result.ndr_interval.measured_high.loss_count) + self.assertEqual(14879927, + state.result.ndr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_high.transmit_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_high.loss_rate) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_high.receive_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_high.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_low.duration) + self.assertEqual(12880000.0, + state.result.pdr_interval.measured_low.target_tr) + self.assertEqual(12879927, + state.result.pdr_interval.measured_low.transmit_count) + self.assertEqual(0, state.result.pdr_interval.measured_low.loss_count) + self.assertEqual(12879927, + state.result.pdr_interval.measured_low.receive_count) + self.assertEqual(429330.9, + state.result.pdr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, state.result.pdr_interval.measured_low.loss_rate) + self.assertEqual(429330.9, + state.result.pdr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_high.duration) + self.assertEqual(14880000, + state.result.pdr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.pdr_interval.measured_high.transmit_count) + self.assertEqual(0, state.result.pdr_interval.measured_high.loss_count) + self.assertEqual(14879927, + state.result.pdr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_high.transmit_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_high.loss_rate) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_high.receive_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_high.loss_fraction) + self.assertEqual(-1, state.phases) + self.assertEqual(30, state.duration) + self.assertEqual(0.2, state.width_goal) + self.assertEqual(0.0, state.packet_loss_ratio) + self.assertEqual(14880000, state.minimum_transmit_rate) + self.assertEqual(14880000, state.maximum_transmit_rate) + + def test_ndrpdr_update_state_ndr_lo(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock, + mock.Mock())) + with mock.patch.object(algorithm, 'measure') as \ + mock_measure, \ + mock.patch.object(algorithm, '_measure_and_update_state') as \ + mock__measure_and_update_state: + ndr_measured_low = ReceiveRateMeasurement(30, 10880000, 10879927, + 100000) + ndr_measured_high = ReceiveRateMeasurement(30, 12880000, 12879927, + 100000) + ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_low = ReceiveRateMeasurement(30, 12880000, 12879927, + 100000) + pdr_measured_high = ReceiveRateMeasurement(30, 14880000, 14879927, + 100000) + pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_interval = ReceiveRateInterval(ndr_measured_low, + ndr_measured_high) + pdr_interval = ReceiveRateInterval(pdr_measured_low, + pdr_measured_high) + starting_result = NdrPdrResult(ndr_interval, pdr_interval) + ending_result = NdrPdrResult(pdr_interval, pdr_interval) + mock_measure.return_value = ReceiveRateMeasurement(1, 14880000, + 14879927, 0) + mock__measure_and_update_state.return_value = \ + MultipleLossRatioSearch.ProgressState(ending_result, -1, 30, + 0.2, 0.0, 14880000, + 14880000) + previous_state = MultipleLossRatioSearch.ProgressState( + starting_result, -1, 30, 0.005, 0.0, 100000, + 14880000) + state = algorithm.ndrpdr(previous_state) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertEqual(30, state.result.ndr_interval.measured_low.duration) + self.assertEqual(12880000.0, + state.result.ndr_interval.measured_low.target_tr) + self.assertEqual(12879927, + state.result.ndr_interval.measured_low.transmit_count) + self.assertEqual(100000, + state.result.ndr_interval.measured_low.loss_count) + self.assertEqual(12779927, + state.result.ndr_interval.measured_low.receive_count) + self.assertEqual(429330.9, + state.result.ndr_interval.measured_low.transmit_rate) + self.assertEqual(3333.33333, + state.result.ndr_interval.measured_low.loss_rate) + self.assertEqual(425997.56667, + state.result.ndr_interval.measured_low.receive_rate) + self.assertEqual(0.00776, + state.result.ndr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.ndr_interval.measured_high.duration) + self.assertEqual(14880000.0, + state.result.ndr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.ndr_interval.measured_high.transmit_count) + self.assertEqual(100000, + state.result.ndr_interval.measured_high.loss_count) + self.assertEqual(14779927, + state.result.ndr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_high.transmit_rate) + self.assertEqual(3333.33333, + state.result.ndr_interval.measured_high.loss_rate) + self.assertEqual(492664.23333, + state.result.ndr_interval.measured_high.receive_rate) + self.assertEqual(0.00672, + state.result.ndr_interval.measured_high.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_low.duration) + self.assertEqual(12880000.0, + state.result.pdr_interval.measured_low.target_tr) + self.assertEqual(12879927, + state.result.pdr_interval.measured_low.transmit_count) + self.assertEqual(100000, + state.result.pdr_interval.measured_low.loss_count) + self.assertEqual(12779927, + state.result.pdr_interval.measured_low.receive_count) + self.assertEqual(429330.9, + state.result.pdr_interval.measured_low.transmit_rate) + self.assertEqual(3333.33333, + state.result.pdr_interval.measured_low.loss_rate) + self.assertEqual(425997.56667, + state.result.pdr_interval.measured_low.receive_rate) + self.assertEqual(0.00776, + state.result.pdr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_high.duration) + self.assertEqual(14880000, + state.result.pdr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.pdr_interval.measured_high.transmit_count) + self.assertEqual(100000, + state.result.pdr_interval.measured_high.loss_count) + self.assertEqual(14779927, + state.result.pdr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_high.transmit_rate) + self.assertEqual(3333.33333, + state.result.pdr_interval.measured_high.loss_rate) + self.assertEqual(492664.23333, + state.result.pdr_interval.measured_high.receive_rate) + self.assertEqual(0.00672, + state.result.pdr_interval.measured_high.loss_fraction) + self.assertEqual(-1, state.phases) + self.assertEqual(30, state.duration) + self.assertEqual(0.2, state.width_goal) + self.assertEqual(0.0, state.packet_loss_ratio) + self.assertEqual(14880000, state.minimum_transmit_rate) + self.assertEqual(14880000, state.maximum_transmit_rate) + + def test_ndrpdr_update_state_pdr_lo(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock, + mock.Mock())) + with mock.patch.object(algorithm, 'measure') as \ + mock_measure, \ + mock.patch.object(algorithm, '_measure_and_update_state') as \ + mock__measure_and_update_state: + ndr_measured_low = ReceiveRateMeasurement(30, 10880000, 10879927, + 0) + ndr_measured_high = ReceiveRateMeasurement(30, 12880000, 12879927, + 0) + ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_low = ReceiveRateMeasurement(30, 12880000, 12879927, + 100000) + pdr_measured_high = ReceiveRateMeasurement(30, 14880000, 14879927, + 100000) + pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_interval = ReceiveRateInterval(ndr_measured_low, + ndr_measured_high) + pdr_interval = ReceiveRateInterval(pdr_measured_low, + pdr_measured_high) + starting_result = NdrPdrResult(ndr_interval, pdr_interval) + ending_result = NdrPdrResult(pdr_interval, pdr_interval) + mock_measure.return_value = ReceiveRateMeasurement(1, 14880000, + 14879927, 0) + mock__measure_and_update_state.return_value = \ + MultipleLossRatioSearch.ProgressState(ending_result, -1, 30, + 0.2, 0.0, 14880000, + 14880000) + previous_state = MultipleLossRatioSearch.ProgressState( + starting_result, -1, 30, 0.005, 0.0, 100000, + 14880000) + state = algorithm.ndrpdr(previous_state) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertEqual(30, state.result.ndr_interval.measured_low.duration) + self.assertEqual(12880000.0, + state.result.ndr_interval.measured_low.target_tr) + self.assertEqual(12879927, + state.result.ndr_interval.measured_low.transmit_count) + self.assertEqual(100000, + state.result.ndr_interval.measured_low.loss_count) + self.assertEqual(12779927, + state.result.ndr_interval.measured_low.receive_count) + self.assertEqual(429330.9, + state.result.ndr_interval.measured_low.transmit_rate) + self.assertEqual(3333.33333, + state.result.ndr_interval.measured_low.loss_rate) + self.assertEqual(425997.56667, + state.result.ndr_interval.measured_low.receive_rate) + self.assertEqual(0.00776, + state.result.ndr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.ndr_interval.measured_high.duration) + self.assertEqual(14880000.0, + state.result.ndr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.ndr_interval.measured_high.transmit_count) + self.assertEqual(100000, + state.result.ndr_interval.measured_high.loss_count) + self.assertEqual(14779927, + state.result.ndr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_high.transmit_rate) + self.assertEqual(3333.33333, + state.result.ndr_interval.measured_high.loss_rate) + self.assertEqual(492664.23333, + state.result.ndr_interval.measured_high.receive_rate) + self.assertEqual(0.00672, + state.result.ndr_interval.measured_high.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_low.duration) + self.assertEqual(12880000.0, + state.result.pdr_interval.measured_low.target_tr) + self.assertEqual(12879927, + state.result.pdr_interval.measured_low.transmit_count) + self.assertEqual(100000, + state.result.pdr_interval.measured_low.loss_count) + self.assertEqual(12779927, + state.result.pdr_interval.measured_low.receive_count) + self.assertEqual(429330.9, + state.result.pdr_interval.measured_low.transmit_rate) + self.assertEqual(3333.33333, + state.result.pdr_interval.measured_low.loss_rate) + self.assertEqual(425997.56667, + state.result.pdr_interval.measured_low.receive_rate) + self.assertEqual(0.00776, + state.result.pdr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_high.duration) + self.assertEqual(14880000, + state.result.pdr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.pdr_interval.measured_high.transmit_count) + self.assertEqual(100000, + state.result.pdr_interval.measured_high.loss_count) + self.assertEqual(14779927, + state.result.pdr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_high.transmit_rate) + self.assertEqual(3333.33333, + state.result.pdr_interval.measured_high.loss_rate) + self.assertEqual(492664.23333, + state.result.pdr_interval.measured_high.receive_rate) + self.assertEqual(0.00672, + state.result.pdr_interval.measured_high.loss_fraction) + self.assertEqual(-1, state.phases) + self.assertEqual(30, state.duration) + self.assertEqual(0.2, state.width_goal) + self.assertEqual(0.0, state.packet_loss_ratio) + self.assertEqual(14880000, state.minimum_transmit_rate) + self.assertEqual(14880000, state.maximum_transmit_rate) + + def test_ndrpdr_update_state_pdr_lo_duration(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock, + mock.Mock())) + with mock.patch.object(algorithm, 'measure') as \ + mock_measure, \ + mock.patch.object(algorithm, '_measure_and_update_state') as \ + mock__measure_and_update_state: + ndr_measured_low = ReceiveRateMeasurement(30, 10880000, 10879927, + 0) + ndr_measured_high = ReceiveRateMeasurement(30, 12880000, 12879927, + 0) + ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_low = ReceiveRateMeasurement(30, 12880000, 12879927, + 100000) + pdr_measured_high = ReceiveRateMeasurement(30, 14880000, 14879927, + 100000) + pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_interval = ReceiveRateInterval(ndr_measured_low, + ndr_measured_high) + pdr_interval = ReceiveRateInterval(pdr_measured_low, + pdr_measured_high) + starting_result = NdrPdrResult(ndr_interval, pdr_interval) + ending_result = NdrPdrResult(pdr_interval, pdr_interval) + mock_measure.return_value = ReceiveRateMeasurement(1, 14880000, + 14879927, 0) + mock__measure_and_update_state.return_value = \ + MultipleLossRatioSearch.ProgressState(ending_result, -1, 30, + 0.2, 0.0, 14880000, + 14880000) + previous_state = MultipleLossRatioSearch.ProgressState( + starting_result, -1, 50, 0.005, 0.0, 14880000, + 14880000) + state = algorithm.ndrpdr(previous_state) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertEqual(30, state.result.ndr_interval.measured_low.duration) + self.assertEqual(12880000.0, + state.result.ndr_interval.measured_low.target_tr) + self.assertEqual(12879927, + state.result.ndr_interval.measured_low.transmit_count) + self.assertEqual(100000, + state.result.ndr_interval.measured_low.loss_count) + self.assertEqual(12779927, + state.result.ndr_interval.measured_low.receive_count) + self.assertEqual(429330.9, + state.result.ndr_interval.measured_low.transmit_rate) + self.assertEqual(3333.33333, + state.result.ndr_interval.measured_low.loss_rate) + self.assertEqual(425997.56667, + state.result.ndr_interval.measured_low.receive_rate) + self.assertEqual(0.00776, + state.result.ndr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.ndr_interval.measured_high.duration) + self.assertEqual(14880000.0, + state.result.ndr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.ndr_interval.measured_high.transmit_count) + self.assertEqual(100000, + state.result.ndr_interval.measured_high.loss_count) + self.assertEqual(14779927, + state.result.ndr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.ndr_interval.measured_high.transmit_rate) + self.assertEqual(3333.33333, + state.result.ndr_interval.measured_high.loss_rate) + self.assertEqual(492664.23333, + state.result.ndr_interval.measured_high.receive_rate) + self.assertEqual(0.00672, + state.result.ndr_interval.measured_high.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_low.duration) + self.assertEqual(12880000.0, + state.result.pdr_interval.measured_low.target_tr) + self.assertEqual(12879927, + state.result.pdr_interval.measured_low.transmit_count) + self.assertEqual(100000, + state.result.pdr_interval.measured_low.loss_count) + self.assertEqual(12779927, + state.result.pdr_interval.measured_low.receive_count) + self.assertEqual(429330.9, + state.result.pdr_interval.measured_low.transmit_rate) + self.assertEqual(3333.33333, + state.result.pdr_interval.measured_low.loss_rate) + self.assertEqual(425997.56667, + state.result.pdr_interval.measured_low.receive_rate) + self.assertEqual(0.00776, + state.result.pdr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_high.duration) + self.assertEqual(14880000, + state.result.pdr_interval.measured_high.target_tr) + self.assertEqual(14879927, + state.result.pdr_interval.measured_high.transmit_count) + self.assertEqual(100000, + state.result.pdr_interval.measured_high.loss_count) + self.assertEqual(14779927, + state.result.pdr_interval.measured_high.receive_count) + self.assertEqual(495997.56667, + state.result.pdr_interval.measured_high.transmit_rate) + self.assertEqual(3333.33333, + state.result.pdr_interval.measured_high.loss_rate) + self.assertEqual(492664.23333, + state.result.pdr_interval.measured_high.receive_rate) + self.assertEqual(0.00672, + state.result.pdr_interval.measured_high.loss_fraction) + self.assertEqual(-1, state.phases) + self.assertEqual(30, state.duration) + self.assertEqual(0.2, state.width_goal) + self.assertEqual(0.0, state.packet_loss_ratio) + self.assertEqual(14880000, state.minimum_transmit_rate) + self.assertEqual(14880000, state.maximum_transmit_rate) + + def test_ndrpdr_update_state_pdr_hi(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock, + mock.Mock())) + with mock.patch.object(algorithm, 'measure') as \ + mock_measure, \ + mock.patch.object(algorithm, '_measure_and_update_state') as \ + mock__measure_and_update_state: + ndr_measured_low = ReceiveRateMeasurement(30, 10880000, 10879927, + 0) + ndr_measured_high = ReceiveRateMeasurement(30, 12880000, 12879927, + 100000) + ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_low = ReceiveRateMeasurement(30, 12880000, 12879927, + 0) + pdr_measured_high = ReceiveRateMeasurement(30, 13880000, 14879927, + 0) + pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_interval = ReceiveRateInterval(ndr_measured_low, + ndr_measured_high) + pdr_interval = ReceiveRateInterval(pdr_measured_low, + pdr_measured_high) + starting_result = NdrPdrResult(ndr_interval, pdr_interval) + ending_result = NdrPdrResult(ndr_interval, ndr_interval) + mock_measure.return_value = ReceiveRateMeasurement(1, 14880000, + 14879927, 0) + mock__measure_and_update_state.return_value = \ + MultipleLossRatioSearch.ProgressState(ending_result, -1, 30, + 0.2, 0.0, 14880000, + 14880000) + previous_state = MultipleLossRatioSearch.ProgressState( + starting_result, -1, 30, 0.005, 0.0, 100000, + 14880000) + state = algorithm.ndrpdr(previous_state) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertEqual(30, state.result.ndr_interval.measured_low.duration) + self.assertEqual(10880000.0, + state.result.ndr_interval.measured_low.target_tr) + self.assertEqual(10879927, + state.result.ndr_interval.measured_low.transmit_count) + self.assertEqual(0, + state.result.ndr_interval.measured_low.loss_count) + self.assertEqual(10879927, + state.result.ndr_interval.measured_low.receive_count) + self.assertEqual(362664.23333, + state.result.ndr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_low.loss_rate) + self.assertEqual(362664.23333, + state.result.ndr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.ndr_interval.measured_high.duration) + self.assertEqual(12880000.0, + state.result.ndr_interval.measured_high.target_tr) + self.assertEqual(12879927, + state.result.ndr_interval.measured_high.transmit_count) + self.assertEqual(100000, + state.result.ndr_interval.measured_high.loss_count) + self.assertEqual(12779927, + state.result.ndr_interval.measured_high.receive_count) + self.assertEqual(429330.9, + state.result.ndr_interval.measured_high.transmit_rate) + self.assertEqual(3333.33333, + state.result.ndr_interval.measured_high.loss_rate) + self.assertEqual(425997.56667, + state.result.ndr_interval.measured_high.receive_rate) + self.assertEqual(0.00776, + state.result.ndr_interval.measured_high.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_low.duration) + self.assertEqual(10880000.0, + state.result.pdr_interval.measured_low.target_tr) + self.assertEqual(10879927, + state.result.pdr_interval.measured_low.transmit_count) + self.assertEqual(0, + state.result.pdr_interval.measured_low.loss_count) + self.assertEqual(10879927, + state.result.pdr_interval.measured_low.receive_count) + self.assertEqual(362664.23333, + state.result.pdr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_low.loss_rate) + self.assertEqual(362664.23333, + state.result.pdr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_high.duration) + self.assertEqual(12880000, + state.result.pdr_interval.measured_high.target_tr) + self.assertEqual(12879927, + state.result.pdr_interval.measured_high.transmit_count) + self.assertEqual(100000, + state.result.pdr_interval.measured_high.loss_count) + self.assertEqual(12779927, + state.result.pdr_interval.measured_high.receive_count) + self.assertEqual(429330.9, + state.result.pdr_interval.measured_high.transmit_rate) + self.assertEqual(3333.33333, + state.result.pdr_interval.measured_high.loss_rate) + self.assertEqual(425997.56667, + state.result.pdr_interval.measured_high.receive_rate) + self.assertEqual(0.00776, + state.result.pdr_interval.measured_high.loss_fraction) + self.assertEqual(-1, state.phases) + self.assertEqual(30, state.duration) + self.assertEqual(0.2, state.width_goal) + self.assertEqual(0.0, state.packet_loss_ratio) + self.assertEqual(14880000, state.minimum_transmit_rate) + self.assertEqual(14880000, state.maximum_transmit_rate) + + def test_ndrpdr_update_state_pdr_hi_duration(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock, + mock.Mock())) + with mock.patch.object(algorithm, 'measure') as \ + mock_measure, \ + mock.patch.object(algorithm, '_measure_and_update_state') as \ + mock__measure_and_update_state: + ndr_measured_low = ReceiveRateMeasurement(30, 10880000, 10879927, + 0) + ndr_measured_high = ReceiveRateMeasurement(30, 12880000, 12879927, + 100000) + ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_low = ReceiveRateMeasurement(30, 12880000, 12879927, + 0) + pdr_measured_high = ReceiveRateMeasurement(30, 13880000, 14879927, + 0) + pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + ndr_interval = ReceiveRateInterval(ndr_measured_low, + ndr_measured_high) + pdr_interval = ReceiveRateInterval(pdr_measured_low, + pdr_measured_high) + starting_result = NdrPdrResult(ndr_interval, pdr_interval) + ending_result = NdrPdrResult(ndr_interval, ndr_interval) + mock_measure.return_value = ReceiveRateMeasurement(1, 14880000, + 14879927, 0) + mock__measure_and_update_state.return_value = \ + MultipleLossRatioSearch.ProgressState(ending_result, -1, 30, + 0.2, 0.0, 14880000, + 14880000) + previous_state = MultipleLossRatioSearch.ProgressState( + starting_result, -1, 50, 0.005, 0.0, 100000, + 10880000) + state = algorithm.ndrpdr(previous_state) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState) + self.assertEqual(30, state.result.ndr_interval.measured_low.duration) + self.assertEqual(10880000.0, + state.result.ndr_interval.measured_low.target_tr) + self.assertEqual(10879927, + state.result.ndr_interval.measured_low.transmit_count) + self.assertEqual(0, + state.result.ndr_interval.measured_low.loss_count) + self.assertEqual(10879927, + state.result.ndr_interval.measured_low.receive_count) + self.assertEqual(362664.23333, + state.result.ndr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_low.loss_rate) + self.assertEqual(362664.23333, + state.result.ndr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.ndr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.ndr_interval.measured_high.duration) + self.assertEqual(12880000.0, + state.result.ndr_interval.measured_high.target_tr) + self.assertEqual(12879927, + state.result.ndr_interval.measured_high.transmit_count) + self.assertEqual(100000, + state.result.ndr_interval.measured_high.loss_count) + self.assertEqual(12779927, + state.result.ndr_interval.measured_high.receive_count) + self.assertEqual(429330.9, + state.result.ndr_interval.measured_high.transmit_rate) + self.assertEqual(3333.33333, + state.result.ndr_interval.measured_high.loss_rate) + self.assertEqual(425997.56667, + state.result.ndr_interval.measured_high.receive_rate) + self.assertEqual(0.00776, + state.result.ndr_interval.measured_high.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_low.duration) + self.assertEqual(10880000.0, + state.result.pdr_interval.measured_low.target_tr) + self.assertEqual(10879927, + state.result.pdr_interval.measured_low.transmit_count) + self.assertEqual(0, + state.result.pdr_interval.measured_low.loss_count) + self.assertEqual(10879927, + state.result.pdr_interval.measured_low.receive_count) + self.assertEqual(362664.23333, + state.result.pdr_interval.measured_low.transmit_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_low.loss_rate) + self.assertEqual(362664.23333, + state.result.pdr_interval.measured_low.receive_rate) + self.assertEqual(0.0, + state.result.pdr_interval.measured_low.loss_fraction) + self.assertEqual(30, state.result.pdr_interval.measured_high.duration) + self.assertEqual(12880000, + state.result.pdr_interval.measured_high.target_tr) + self.assertEqual(12879927, + state.result.pdr_interval.measured_high.transmit_count) + self.assertEqual(100000, + state.result.pdr_interval.measured_high.loss_count) + self.assertEqual(12779927, + state.result.pdr_interval.measured_high.receive_count) + self.assertEqual(429330.9, + state.result.pdr_interval.measured_high.transmit_rate) + self.assertEqual(3333.33333, + state.result.pdr_interval.measured_high.loss_rate) + self.assertEqual(425997.56667, + state.result.pdr_interval.measured_high.receive_rate) + self.assertEqual(0.00776, + state.result.pdr_interval.measured_high.loss_fraction) + self.assertEqual(-1, state.phases) + self.assertEqual(30, state.duration) + self.assertEqual(0.2, state.width_goal) + self.assertEqual(0.0, state.packet_loss_ratio) + self.assertEqual(14880000, state.minimum_transmit_rate) + self.assertEqual(14880000, state.maximum_transmit_rate) + + def test_measure(self): + measurer = mock.MagicMock() + measurer.sent = 102563094 + measurer.loss = 30502 + algorithm = MultipleLossRatioSearch(measurer=measurer, latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.MagicMock(), + mock.Mock, mock.Mock())) + measurement = algorithm.measure(30, 3418770.3425, True) + self.assertIsInstance(measurement, ReceiveRateMeasurement) + self.assertEqual(30, measurement.duration) + self.assertEqual(3418770.3425, measurement.target_tr) + self.assertEqual(102563094, measurement.transmit_count) + self.assertEqual(30502, measurement.loss_count) + self.assertEqual(102532592, measurement.receive_count) + self.assertEqual(3418769.8, measurement.transmit_rate) + self.assertEqual(1016.73333, measurement.loss_rate) + self.assertEqual(3417753.06667, measurement.receive_rate) + self.assertEqual(0.0003, measurement.loss_fraction) + + def test_perform_additional_measurements_based_on_ndrpdr_result(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + ports = [0, 1] + port_pg_id = PortPgIDMap() + port_pg_id.add_port(0) + port_pg_id.add_port(1) + self.assertIsNone( + algorithm.init_generator(ports, port_pg_id, mock.Mock, mock.Mock, + mock.Mock())) + result = mock.MagicMock() + result.ndr_interval.measured_low.target_tr.return_result = 100000 + self.assertIsNone( + algorithm.perform_additional_measurements_based_on_ndrpdr_result( + result)) + + def test_display_single_bound(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + result_samples = {} + self.assertIsNone( + algorithm.display_single_bound(result_samples, 'NDR_LOWER', + 4857361, 64, + ['20/849/1069', '40/69/183'])) + self.assertEqual( + {'Result_NDR_LOWER': {'bandwidth_total_Gbps': 3.264146592, + 'rate_total_pps': 4857361.0}, + 'Result_stream0_NDR_LOWER': {'avg_latency': 849.0, + 'max_latency': 1069.0, + 'min_latency': 20.0}, + 'Result_stream1_NDR_LOWER': {'avg_latency': 69.0, + 'max_latency': 183.0, + 'min_latency': 40.0}}, + result_samples) + + def test_check_ndrpdr_interval_validity(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + result_samples = {} + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 0) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 0) + receive_rate_interval = ReceiveRateInterval(measured_low, + measured_high) + self.assertEqual('Minimal rate loss fraction 0.0 reach target 0.0', + algorithm.check_ndrpdr_interval_validity( + result_samples, 'NDR_LOWER', + receive_rate_interval)) + self.assertEqual( + {'Result_NDR_LOWER_packets_lost': {'packet_loss_ratio': 0.0, + 'packets_lost': 0.0}}, + result_samples) + + def test_check_ndrpdr_interval_validity_fail(self): + algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True, + pkt_size=64, + final_trial_duration=30, + final_relative_width=0.005, + number_of_intermediate_phases=2, + initial_trial_duration=1, + timeout=720) + result_samples = {} + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + receive_rate_interval = ReceiveRateInterval(measured_low, + measured_high) + self.assertEqual( + 'Minimal rate loss fraction 0.01749 does not reach target 0.005\n84965 packets lost.', + algorithm.check_ndrpdr_interval_validity(result_samples, + 'NDR_LOWER', + receive_rate_interval, + 0.005)) + self.assertEqual({'Result_NDR_LOWER_packets_lost': { + 'packet_loss_ratio': 0.01749, + 'packets_lost': 84965.0}}, result_samples) diff --git a/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_ndr_pdr_result.py b/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_ndr_pdr_result.py new file mode 100644 index 000000000..ea9c39a03 --- /dev/null +++ b/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_ndr_pdr_result.py @@ -0,0 +1,91 @@ +# Copyright (c) 2019 Viosoft Corporation +# +# 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 +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +import mock + +from yardstick.network_services.helpers.vpp_helpers.ndr_pdr_result import \ + NdrPdrResult +from yardstick.network_services.helpers.vpp_helpers.receive_rate_interval import \ + ReceiveRateInterval +from yardstick.network_services.helpers.vpp_helpers.receive_rate_measurement import \ + ReceiveRateMeasurement + + +class TestNdrPdrResult(unittest.TestCase): + + def test___init__(self): + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + starting_interval = ReceiveRateInterval(measured_low, measured_high) + ndrpdr_result = NdrPdrResult(starting_interval, starting_interval) + self.assertIsInstance(ndrpdr_result.ndr_interval, ReceiveRateInterval) + self.assertIsInstance(ndrpdr_result.pdr_interval, ReceiveRateInterval) + + def test___init__ndr_error(self): + starting_interval = mock.MagicMock() + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + end_interval = ReceiveRateInterval(measured_low, measured_high) + with self.assertRaises(TypeError) as raised: + NdrPdrResult(starting_interval, end_interval) + self.assertIn('ndr_interval, is not a ReceiveRateInterval: ', + str(raised.exception)) + + def test___init__pdr_error(self): + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + starting_interval = ReceiveRateInterval(measured_low, measured_high) + end_interval = mock.MagicMock() + with self.assertRaises(TypeError) as raised: + NdrPdrResult(starting_interval, end_interval) + self.assertIn('pdr_interval, is not a ReceiveRateInterval: ', + str(raised.exception)) + + def test_width_in_goals(self): + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + starting_interval = ReceiveRateInterval(measured_low, measured_high) + ndrpdr_result = NdrPdrResult(starting_interval, starting_interval) + self.assertEqual('ndr 4.86887; pdr 4.86887', + ndrpdr_result.width_in_goals(0.005)) + + def test___str__(self): + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + starting_interval = ReceiveRateInterval(measured_low, measured_high) + ndrpdr_result = NdrPdrResult(starting_interval, starting_interval) + self.assertEqual( + 'NDR=[d=1.0,Tr=4857361.0,Df=0.01749;d=1.0,Tr=4977343.0,Df=0.0241);' + 'PDR=[d=1.0,Tr=4857361.0,Df=0.01749;d=1.0,Tr=4977343.0,Df=0.0241)', + ndrpdr_result.__str__()) + + def test___repr__(self): + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + starting_interval = ReceiveRateInterval(measured_low, measured_high) + ndrpdr_result = NdrPdrResult(starting_interval, starting_interval) + self.assertEqual( + 'NdrPdrResult(ndr_interval=ReceiveRateInterval(measured_low=' \ + 'ReceiveRateMeasurement(duration=1.0,target_tr=4857361.0,' \ + 'transmit_count=4857339,loss_count=84965),measured_high=' \ + 'ReceiveRateMeasurement(duration=1.0,target_tr=4977343.0,' \ + 'transmit_count=4977320,loss_count=119959)),pdr_interval=' \ + 'ReceiveRateInterval(measured_low=ReceiveRateMeasurement' \ + '(duration=1.0,target_tr=4857361.0,transmit_count=4857339,' \ + 'loss_count=84965),measured_high=ReceiveRateMeasurement' \ + '(duration=1.0,target_tr=4977343.0,transmit_count=4977320,' \ + 'loss_count=119959)))', + ndrpdr_result.__repr__()) diff --git a/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_receive_rate_interval.py b/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_receive_rate_interval.py new file mode 100644 index 000000000..bbf241613 --- /dev/null +++ b/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_receive_rate_interval.py @@ -0,0 +1,100 @@ +# Copyright (c) 2019 Viosoft Corporation +# +# 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 +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +import mock + +from yardstick.network_services.helpers.vpp_helpers.receive_rate_interval import \ + ReceiveRateInterval +from yardstick.network_services.helpers.vpp_helpers.receive_rate_measurement import \ + ReceiveRateMeasurement + + +class TestReceiveRateInterval(unittest.TestCase): + + def test__init__(self): + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + receive_rate_interval = ReceiveRateInterval(measured_low, + measured_high) + self.assertIsInstance(receive_rate_interval.measured_low, + ReceiveRateMeasurement) + self.assertIsInstance(receive_rate_interval.measured_high, + ReceiveRateMeasurement) + + def test__init__measured_low_error(self): + measured_low = mock.MagicMock() + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + with self.assertRaises(TypeError) as raised: + ReceiveRateInterval(measured_low, measured_high) + self.assertIn('measured_low is not a ReceiveRateMeasurement: ', + str(raised.exception)) + + def test__init__measured_high_error(self): + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = mock.MagicMock() + with self.assertRaises(TypeError) as raised: + ReceiveRateInterval(measured_low, measured_high) + self.assertIn('measured_high is not a ReceiveRateMeasurement: ', + str(raised.exception)) + + def test_sort(self): + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + receive_rate_interval = ReceiveRateInterval(measured_low, + measured_high) + self.assertIsNone(receive_rate_interval.sort()) + self.assertEqual(119982.0, receive_rate_interval.abs_tr_width) + self.assertEqual(0.02411, + receive_rate_interval.rel_tr_width) + + def test_sort_swap(self): + measured_low = ReceiveRateMeasurement(1, 14857361, 14857339, 184965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + receive_rate_interval = ReceiveRateInterval(measured_low, + measured_high) + self.assertIsNone(receive_rate_interval.sort()) + self.assertEqual(9880018.0, receive_rate_interval.abs_tr_width) + self.assertEqual(0.66499, + receive_rate_interval.rel_tr_width) + + def test_width_in_goals(self): + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + receive_rate_interval = ReceiveRateInterval(measured_low, + measured_high) + self.assertEqual(4.86887, + receive_rate_interval.width_in_goals(0.005)) + + def test___str__(self): + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + receive_rate_interval = ReceiveRateInterval(measured_low, + measured_high) + self.assertEqual( + '[d=1.0,Tr=4857361.0,Df=0.01749;d=1.0,Tr=4977343.0,Df=0.0241)', + receive_rate_interval.__str__()) + + def test___repr__(self): + measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959) + receive_rate_interval = ReceiveRateInterval(measured_low, + measured_high) + self.assertEqual('ReceiveRateInterval(measured_low=' \ + 'ReceiveRateMeasurement(duration=1.0,target_tr=4857361.0,' \ + 'transmit_count=4857339,loss_count=84965),measured_high=' \ + 'ReceiveRateMeasurement(duration=1.0,target_tr=4977343.0,' \ + 'transmit_count=4977320,loss_count=119959))', + receive_rate_interval.__repr__()) diff --git a/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_receive_rate_measurement.py b/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_receive_rate_measurement.py new file mode 100644 index 000000000..d4e2d7920 --- /dev/null +++ b/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_receive_rate_measurement.py @@ -0,0 +1,44 @@ +# Copyright (c) 2019 Viosoft Corporation +# +# 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 +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +from yardstick.network_services.helpers.vpp_helpers.receive_rate_measurement import \ + ReceiveRateMeasurement + + +class TestReceiveRateMeasurement(unittest.TestCase): + + def test__init__(self): + measured = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + self.assertEqual(1, measured.duration) + self.assertEqual(4857361, measured.target_tr) + self.assertEqual(4857339, measured.transmit_count) + self.assertEqual(84965, measured.loss_count) + self.assertEqual(4772374, measured.receive_count) + self.assertEqual(4857339, measured.transmit_rate) + self.assertEqual(84965.0, measured.loss_rate) + self.assertEqual(4772374.0, measured.receive_rate) + self.assertEqual(0.01749, measured.loss_fraction) + + def test___str__(self): + measured = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + self.assertEqual('d=1.0,Tr=4857361.0,Df=0.01749', + measured.__str__()) + + def test___repr__(self): + measured = ReceiveRateMeasurement(1, 4857361, 4857339, 84965) + self.assertEqual('ReceiveRateMeasurement(duration=1.0,' \ + 'target_tr=4857361.0,transmit_count=4857339,loss_count=84965)', + measured.__repr__()) diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_vpp_rfc2544.py b/yardstick/tests/unit/network_services/traffic_profile/test_vpp_rfc2544.py index 4e5a0f708..8ad17b547 100644 --- a/yardstick/tests/unit/network_services/traffic_profile/test_vpp_rfc2544.py +++ b/yardstick/tests/unit/network_services/traffic_profile/test_vpp_rfc2544.py @@ -18,8 +18,17 @@ from trex_stl_lib import trex_stl_packet_builder_scapy from trex_stl_lib import trex_stl_streams from yardstick.common import constants +from yardstick.network_services.helpers.vpp_helpers.multiple_loss_ratio_search import \ + MultipleLossRatioSearch +from yardstick.network_services.helpers.vpp_helpers.ndr_pdr_result import \ + NdrPdrResult +from yardstick.network_services.helpers.vpp_helpers.receive_rate_interval import \ + ReceiveRateInterval +from yardstick.network_services.helpers.vpp_helpers.receive_rate_measurement import \ + ReceiveRateMeasurement from yardstick.network_services.traffic_profile import base as tp_base from yardstick.network_services.traffic_profile import rfc2544, vpp_rfc2544 +from yardstick.network_services.traffic_profile.rfc2544 import PortPgIDMap from yardstick.tests.unit import base @@ -129,6 +138,7 @@ class TestVppRFC2544Profile(base.BaseUnitTestCase): self.assertEqual(vpp_rfc2544_profile.max_rate, vpp_rfc2544_profile.rate) self.assertEqual(0, vpp_rfc2544_profile.min_rate) + self.assertEqual(2, vpp_rfc2544_profile.number_of_intermediate_phases) self.assertEqual(30, vpp_rfc2544_profile.duration) self.assertEqual(0.1, vpp_rfc2544_profile.precision) self.assertEqual(1.0, vpp_rfc2544_profile.lower_bound) @@ -287,6 +297,7 @@ class TestVppRFC2544Profile(base.BaseUnitTestCase): vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile( self.TRAFFIC_PROFILE_MAX_RATE) vpp_rfc2544_profile.init_queue(mock.MagicMock()) + vpp_rfc2544_profile.pkt_size = 64 vpp_rfc2544_profile.params = { 'downlink_0': 'profile1', 'uplink_0': 'profile2'} @@ -480,6 +491,7 @@ class TestVppRFC2544Profile(base.BaseUnitTestCase): mock_latency.side_effect = ['latency1', 'latency2'] vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile( self.TRAFFIC_PROFILE_MAX_RATE) + vpp_rfc2544_profile.pkt_size = 64 vpp_rfc2544_profile.port_pg_id = rfc2544.PortPgIDMap() vpp_rfc2544_profile.port_pg_id.add_port(1) with mock.patch.object(vpp_rfc2544_profile, '_create_single_packet') as \ @@ -523,10 +535,69 @@ class TestVppRFC2544Profile(base.BaseUnitTestCase): def test_binary_search_with_optimized(self): vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile( self.TRAFFIC_PROFILE) + vpp_rfc2544_profile.pkt_size = 64 + vpp_rfc2544_profile.init_queue(mock.MagicMock()) mock_generator = mock.MagicMock() - self.assertIsNone( - vpp_rfc2544_profile.binary_search_with_optimized(mock_generator, - 30, 720, '')) + mock_generator.vnfd_helper.interfaces = [ + {"name": "xe0"}, {"name": "xe0"} + ] + + vpp_rfc2544_profile.ports = [0, 1] + vpp_rfc2544_profile.port_pg_id = PortPgIDMap() + vpp_rfc2544_profile.port_pg_id.add_port(0) + vpp_rfc2544_profile.port_pg_id.add_port(1) + vpp_rfc2544_profile.profiles = mock.MagicMock() + vpp_rfc2544_profile.test_data = mock.MagicMock() + vpp_rfc2544_profile.queue = mock.MagicMock() + + with mock.patch.object(MultipleLossRatioSearch, 'measure') as \ + mock_measure, \ + mock.patch.object(MultipleLossRatioSearch, 'ndrpdr') as \ + mock_ndrpdr: + measured_low = ReceiveRateMeasurement(1, 14880000, 14879927, 0) + measured_high = ReceiveRateMeasurement(1, 14880000, 14879927, 0) + measured_low.latency = ['1000/3081/3962', '500/3149/3730'] + measured_high.latency = ['1000/3081/3962', '500/3149/3730'] + starting_interval = ReceiveRateInterval(measured_low, + measured_high) + starting_result = NdrPdrResult(starting_interval, + starting_interval) + mock_measure.return_value = ReceiveRateMeasurement(1, 14880000, + 14879927, 0) + mock_ndrpdr.return_value = MultipleLossRatioSearch.ProgressState( + starting_result, 2, 30, 0.005, 0.0, + 4857361, 4977343) + + result_samples = vpp_rfc2544_profile.binary_search_with_optimized( + traffic_generator=mock_generator, duration=30, + timeout=720, + test_data={}) + + expected = {'Result_NDR_LOWER': {'bandwidth_total_Gbps': 9.999310944, + 'rate_total_pps': 14879927.0}, + 'Result_NDR_UPPER': {'bandwidth_total_Gbps': 9.999310944, + 'rate_total_pps': 14879927.0}, + 'Result_NDR_packets_lost': {'packet_loss_ratio': 0.0, + 'packets_lost': 0.0}, + 'Result_PDR_LOWER': {'bandwidth_total_Gbps': 9.999310944, + 'rate_total_pps': 14879927.0}, + 'Result_PDR_UPPER': {'bandwidth_total_Gbps': 9.999310944, + 'rate_total_pps': 14879927.0}, + 'Result_PDR_packets_lost': {'packet_loss_ratio': 0.0, + 'packets_lost': 0.0}, + 'Result_stream0_NDR_LOWER': {'avg_latency': 3081.0, + 'max_latency': 3962.0, + 'min_latency': 1000.0}, + 'Result_stream0_PDR_LOWER': {'avg_latency': 3081.0, + 'max_latency': 3962.0, + 'min_latency': 1000.0}, + 'Result_stream1_NDR_LOWER': {'avg_latency': 3149.0, + 'max_latency': 3730.0, + 'min_latency': 500.0}, + 'Result_stream1_PDR_LOWER': {'avg_latency': 3149.0, + 'max_latency': 3730.0, + 'min_latency': 500.0}} + self.assertEqual(expected, result_samples) def test_binary_search(self): vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile( |