+ :returns: Result rate and latency stats.
+ :rtype: tuple
+ :raises Exception: If search failed.
+ """
+ if self._search_result in [
+ SearchResults.SUCCESS, SearchResults.SUSPICIOUS]:
+ return self._search_result_rate, self.get_latency()
+ raise Exception('Search FAILED')
+
+ def binary_search(self, b_min, b_max, traffic_type, skip_max_rate=False,
+ skip_warmup=False):
+ """Binary search of rate with loss below acceptance criteria.
+
+ :param b_min: Min range rate.
+ :param b_max: Max range rate.
+ :param traffic_type: Traffic profile.
+ :param skip_max_rate: Start with max rate first
+ :param skip_warmup: Start TRex without warmup traffic if true.
+ :type b_min: float
+ :type b_max: float
+ :type traffic_type: str
+ :type skip_max_rate: bool
+ :type skip_warmup: bool
+ :returns: nothing
+ :raises ValueError: If input values are not valid.
+ """
+
+ if not self._rate_min <= float(b_min) <= self._rate_max:
+ raise ValueError("Min rate is not in min,max range")
+ if not self._rate_min <= float(b_max) <= self._rate_max:
+ raise ValueError("Max rate is not in min,max range")
+ if float(b_max) < float(b_min):
+ raise ValueError("Min rate is greater than max rate")
+
+ # rate is half of interval + start of interval if not using max rate
+ rate = ((float(b_max) - float(b_min)) / 2) + float(b_min) \
+ if skip_max_rate else float(b_max)
+
+ # rate diff with previous run
+ rate_diff = abs(self._last_binary_rate - rate)
+
+ # convergence criterium
+ if float(rate_diff) < float(self._binary_convergence_threshold):
+ self._search_result = SearchResults.SUCCESS \
+ if self._search_result_rate else SearchResults.FAILURE
+ return
+
+ self._last_binary_rate = rate
+
+ res = []
+ for dummy in range(self._max_attempts):
+ res.append(self.measure_loss(rate, self._frame_size,
+ self._loss_acceptance,
+ self._loss_acceptance_type,
+ traffic_type, skip_warmup=skip_warmup))
+
+ res = self._get_res_based_on_search_type(res)
+
+ # loss occurred and it was above acceptance criteria
+ if not res:
+ self.binary_search(b_min, rate, traffic_type, True, True)
+ # there was no loss / loss below acceptance criteria
+ else:
+ self._search_result_rate = rate
+ self.binary_search(rate, b_max, traffic_type, True, True)
+
+ def combined_search(self, start_rate, traffic_type):
+ """Combined search of rate with loss below acceptance criteria.
+
+ :param start_rate: Initial rate.
+ :param traffic_type: Traffic profile.
+ :type start_rate: float
+ :type traffic_type: str
+ :returns: nothing
+ :raises RuntimeError: If linear search failed.