Code Review
/
csit.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
review
|
tree
raw
|
inline
| side by side
feat(papi): use newer API messages
[csit.git]
/
resources
/
libraries
/
python
/
DropRateSearch.py
diff --git
a/resources/libraries/python/DropRateSearch.py
b/resources/libraries/python/DropRateSearch.py
index
0c4f2c6
..
2417df8
100644
(file)
--- a/
resources/libraries/python/DropRateSearch.py
+++ b/
resources/libraries/python/DropRateSearch.py
@@
-1,4
+1,4
@@
-# Copyright (c) 20
19
Cisco and/or its affiliates.
+# Copyright (c) 20
21
Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
# 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:
@@
-20,7
+20,6
@@
from enum import Enum, unique
@unique
class SearchDirection(Enum):
"""Direction of linear search."""
@unique
class SearchDirection(Enum):
"""Direction of linear search."""
-
TOP_DOWN = 1
BOTTOM_UP = 2
TOP_DOWN = 1
BOTTOM_UP = 2
@@
-28,7
+27,6
@@
class SearchDirection(Enum):
@unique
class SearchResults(Enum):
"""Result of the drop rate search."""
@unique
class SearchResults(Enum):
"""Result of the drop rate search."""
-
SUCCESS = 1
FAILURE = 2
SUSPICIOUS = 3
SUCCESS = 1
FAILURE = 2
SUSPICIOUS = 3
@@
-37,7
+35,6
@@
class SearchResults(Enum):
@unique
class RateType(Enum):
"""Type of rate units."""
@unique
class RateType(Enum):
"""Type of rate units."""
-
PERCENTAGE = 1
PACKETS_PER_SECOND = 2
BITS_PER_SECOND = 3
PERCENTAGE = 1
PACKETS_PER_SECOND = 2
BITS_PER_SECOND = 3
@@
-46,7
+43,6
@@
class RateType(Enum):
@unique
class LossAcceptanceType(Enum):
"""Type of the loss acceptance criteria."""
@unique
class LossAcceptanceType(Enum):
"""Type of the loss acceptance criteria."""
-
FRAMES = 1
PERCENTAGE = 2
FRAMES = 1
PERCENTAGE = 2
@@
-54,17
+50,12
@@
class LossAcceptanceType(Enum):
@unique
class SearchResultType(Enum):
"""Type of search result evaluation."""
@unique
class SearchResultType(Enum):
"""Type of search result evaluation."""
-
BEST_OF_N = 1
WORST_OF_N = 2
BEST_OF_N = 1
WORST_OF_N = 2
-class DropRateSearch(
object
):
+class DropRateSearch(
metaclass=ABCMeta
):
"""Abstract class with search algorithm implementation."""
"""Abstract class with search algorithm implementation."""
- #TODO DropRateSearch should be refactored as part of CSIT-1378
- #pylint: disable=too-many-instance-attributes
-
- __metaclass__ = ABCMeta
def __init__(self):
# duration of traffic run (binary, linear)
def __init__(self):
# duration of traffic run (binary, linear)
@@
-88,8
+79,8
@@
class DropRateSearch(object):
# permitted values: LossAcceptanceType
self._loss_acceptance_type = LossAcceptanceType.FRAMES
# size of frames to send
# permitted values: LossAcceptanceType
self._loss_acceptance_type = LossAcceptanceType.FRAMES
# size of frames to send
- self._frame_size = "64"
- # binary convergence criteri
um
type is self._rate_type
+ self._frame_size =
u
"64"
+ # binary convergence criteri
on
type is self._rate_type
self._binary_convergence_threshold = 5000
# numbers of traffic runs during one rate step
self._max_attempts = 1
self._binary_convergence_threshold = 5000
# numbers of traffic runs during one rate step
self._max_attempts = 1
@@
-107,11
+98,11
@@
class DropRateSearch(object):
:returns: Latency stats.
:rtype: list
"""
:returns: Latency stats.
:rtype: list
"""
- pass
@abstractmethod
@abstractmethod
- def measure_loss(self, rate, frame_size, loss_acceptance,
- loss_acceptance_type, traffic_profile, skip_warmup=False):
+ def measure_loss(
+ self, rate, frame_size, loss_acceptance, loss_acceptance_type,
+ traffic_profile, skip_warmup=False):
"""Send traffic from TG and measure count of dropped frames.
:param rate: Offered traffic load.
"""Send traffic from TG and measure count of dropped frames.
:param rate: Offered traffic load.
@@
-120,7
+111,7
@@
class DropRateSearch(object):
:param loss_acceptance_type: Type of permitted loss.
:param traffic_profile: Module name to use for traffic generation.
:param skip_warmup: Start TRex without warmup traffic if true.
:param loss_acceptance_type: Type of permitted loss.
:param traffic_profile: Module name to use for traffic generation.
:param skip_warmup: Start TRex without warmup traffic if true.
- :type rate:
in
t
+ :type rate:
floa
t
:type frame_size: str
:type loss_acceptance: float
:type loss_acceptance_type: LossAcceptanceType
:type frame_size: str
:type loss_acceptance: float
:type loss_acceptance_type: LossAcceptanceType
@@
-129,7
+120,6
@@
class DropRateSearch(object):
:returns: Drop threshold exceeded? (True/False)
:rtype: bool
"""
:returns: Drop threshold exceeded? (True/False)
:rtype: bool
"""
- pass
def set_search_rate_boundaries(self, max_rate, min_rate):
"""Set search boundaries: min,max.
def set_search_rate_boundaries(self, max_rate, min_rate):
"""Set search boundaries: min,max.
@@
-142,53
+132,55
@@
class DropRateSearch(object):
:raises ValueError: If min rate is lower than 0 or higher than max rate.
"""
if float(min_rate) <= 0:
:raises ValueError: If min rate is lower than 0 or higher than max rate.
"""
if float(min_rate) <= 0:
- raise ValueError("min_rate must be higher than 0")
+ msg = u"min_rate must be higher than 0"
elif float(min_rate) > float(max_rate):
elif float(min_rate) > float(max_rate):
- raise ValueError("min_rate must be lower than max_rate")
+ msg = u"min_rate must be lower than max_rate"
else:
self._rate_max = float(max_rate)
self._rate_min = float(min_rate)
else:
self._rate_max = float(max_rate)
self._rate_min = float(min_rate)
+ return
+ raise ValueError(msg)
def set_loss_acceptance(self, loss_acceptance):
def set_loss_acceptance(self, loss_acceptance):
- """Set loss acceptance treshold for PDR search.
+ """Set loss acceptance t
h
reshold for PDR search.
- :param loss_acceptance: Loss acceptance treshold for PDR search.
+ :param loss_acceptance: Loss acceptance t
h
reshold for PDR search.
:type loss_acceptance: str
:returns: nothing
:raises ValueError: If loss acceptance is lower than zero.
"""
:type loss_acceptance: str
:returns: nothing
:raises ValueError: If loss acceptance is lower than zero.
"""
- if float(loss_acceptance) < 0:
- raise ValueError("Loss acceptance must be higher or equal 0")
- else:
+ if float(loss_acceptance) >= 0:
self._loss_acceptance = float(loss_acceptance)
self._loss_acceptance = float(loss_acceptance)
+ else:
+ raise ValueError(u"Loss acceptance must be higher or equal 0")
def get_loss_acceptance(self):
def get_loss_acceptance(self):
- """Return configured loss acceptance treshold.
+ """Return configured loss acceptance t
h
reshold.
- :returns: Loss acceptance treshold.
+ :returns: Loss acceptance t
h
reshold.
:rtype: float
"""
return self._loss_acceptance
def set_loss_acceptance_type_percentage(self):
:rtype: float
"""
return self._loss_acceptance
def set_loss_acceptance_type_percentage(self):
- """Set loss acceptance treshold type to percentage.
+ """Set loss acceptance t
h
reshold type to percentage.
:returns: nothing
"""
self._loss_acceptance_type = LossAcceptanceType.PERCENTAGE
def set_loss_acceptance_type_frames(self):
:returns: nothing
"""
self._loss_acceptance_type = LossAcceptanceType.PERCENTAGE
def set_loss_acceptance_type_frames(self):
- """Set loss acceptance treshold type to frames.
+ """Set loss acceptance t
h
reshold type to frames.
:returns: nothing
"""
self._loss_acceptance_type = LossAcceptanceType.FRAMES
def loss_acceptance_type_is_percentage(self):
:returns: nothing
"""
self._loss_acceptance_type = LossAcceptanceType.FRAMES
def loss_acceptance_type_is_percentage(self):
- """Return true if loss acceptance treshold type is percentage,
+ """Return true if loss acceptance t
h
reshold type is percentage,
false otherwise.
false otherwise.
- :returns: True if loss acceptance treshold type is percentage.
+ :returns: True if loss acceptance t
h
reshold type is percentage.
:rtype: boolean
"""
return self._loss_acceptance_type == LossAcceptanceType.PERCENTAGE
:rtype: boolean
"""
return self._loss_acceptance_type == LossAcceptanceType.PERCENTAGE
@@
-231,10
+223,10
@@
class DropRateSearch(object):
:returns: nothing
:raises Exception: If rate type is unknown.
"""
:returns: nothing
:raises Exception: If rate type is unknown.
"""
- if rate_type not in RateType:
- raise Exception("rate_type unknown: {}".format(rate_type))
- else:
+ if rate_type in RateType:
self._rate_type = rate_type
self._rate_type = rate_type
+ else:
+ raise Exception(f"rate_type unknown: {rate_type}")
def set_search_frame_size(self, frame_size):
"""Set size of frames to send.
def set_search_frame_size(self, frame_size):
"""Set size of frames to send.
@@
-265,7
+257,7
@@
class DropRateSearch(object):
def set_binary_convergence_threshold(self, convergence):
"""Set convergence for binary search.
def set_binary_convergence_threshold(self, convergence):
"""Set convergence for binary search.
- :param convergence: Treshold value number.
+ :param convergence: T
h
reshold value number.
:type convergence: float
:returns: nothing
"""
:type convergence: float
:returns: nothing
"""
@@
-274,7
+266,7
@@
class DropRateSearch(object):
def get_binary_convergence_threshold(self):
"""Get convergence for binary search.
def get_binary_convergence_threshold(self):
"""Get convergence for binary search.
- :returns: Treshold value number.
+ :returns: T
h
reshold value number.
:rtype: float
"""
return self._binary_convergence_threshold
:rtype: float
"""
return self._binary_convergence_threshold
@@
-287,13
+279,14
@@
class DropRateSearch(object):
:raises ValueError: If rate type is unknown.
"""
if self._rate_type == RateType.PERCENTAGE:
:raises ValueError: If rate type is unknown.
"""
if self._rate_type == RateType.PERCENTAGE:
- ret
urn
"%"
+ ret
val = u
"%"
elif self._rate_type == RateType.BITS_PER_SECOND:
elif self._rate_type == RateType.BITS_PER_SECOND:
- ret
urn
"bps"
+ ret
val = u
"bps"
elif self._rate_type == RateType.PACKETS_PER_SECOND:
elif self._rate_type == RateType.PACKETS_PER_SECOND:
- ret
urn
"pps"
+ ret
val = u
"pps"
else:
else:
- raise ValueError("RateType unknown")
+ raise ValueError(u"RateType unknown")
+ return retval
def set_max_attempts(self, max_attempts):
"""Set maximum number of traffic runs during one rate step.
def set_max_attempts(self, max_attempts):
"""Set maximum number of traffic runs during one rate step.
@@
-306,7
+299,7
@@
class DropRateSearch(object):
if int(max_attempts) > 0:
self._max_attempts = int(max_attempts)
else:
if int(max_attempts) > 0:
self._max_attempts = int(max_attempts)
else:
- raise ValueError("Max attempt must by greater than zero")
+ raise ValueError(
u
"Max attempt must by greater than zero")
def get_max_attempts(self):
"""Return maximum number of traffic runs during one rate step.
def get_max_attempts(self):
"""Return maximum number of traffic runs during one rate step.
@@
-338,10
+331,10
@@
class DropRateSearch(object):
:returns: nothing
:raises ValueError: If search type is unknown.
"""
:returns: nothing
:raises ValueError: If search type is unknown.
"""
- if search_type not in SearchResultType:
- raise ValueError("search_type unknown: {}".format(search_type))
- else:
+ if search_type in SearchResultType:
self._search_result_type = search_type
self._search_result_type = search_type
+ else:
+ raise ValueError(f"search_type unknown: {search_type}")
@staticmethod
def _get_best_of_n(res_list):
@staticmethod
def _get_best_of_n(res_list):
@@
-377,11
+370,12
@@
class DropRateSearch(object):
:raises ValueError: If search result type is unknown.
"""
if self._search_result_type == SearchResultType.BEST_OF_N:
:raises ValueError: If search result type is unknown.
"""
if self._search_result_type == SearchResultType.BEST_OF_N:
- ret
urn
self._get_best_of_n(res_list)
+ ret
val =
self._get_best_of_n(res_list)
elif self._search_result_type == SearchResultType.WORST_OF_N:
elif self._search_result_type == SearchResultType.WORST_OF_N:
- ret
urn
self._get_worst_of_n(res_list)
+ ret
val =
self._get_worst_of_n(res_list)
else:
else:
- raise ValueError("Unknown search result type")
+ raise ValueError(u"Unknown search result type")
+ return retval
def linear_search(self, start_rate, traffic_profile):
"""Linear search of rate with loss below acceptance criteria.
def linear_search(self, start_rate, traffic_profile):
"""Linear search of rate with loss below acceptance criteria.
@@
-393,9
+387,8
@@
class DropRateSearch(object):
:returns: nothing
:raises ValueError: If start rate is not in range.
"""
:returns: nothing
:raises ValueError: If start rate is not in range.
"""
-
if not self._rate_min <= float(start_rate) <= self._rate_max:
if not self._rate_min <= float(start_rate) <= self._rate_max:
- raise ValueError("Start rate is not in min,max range")
+ raise ValueError(
u
"Start rate is not in min,max range")
rate = float(start_rate)
# the last but one step
rate = float(start_rate)
# the last but one step
@@
-405,9
+398,12
@@
class DropRateSearch(object):
while True:
res = []
for dummy in range(self._max_attempts):
while True:
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_profile))
+ res.append(
+ self.measure_loss(
+ rate, self._frame_size, self._loss_acceptance,
+ self._loss_acceptance_type, traffic_profile
+ )
+ )
res = self._get_res_based_on_search_type(res)
res = self._get_res_based_on_search_type(res)
@@
-421,21
+417,17
@@
class DropRateSearch(object):
# one last step with rate set to _rate_min
rate = self._rate_min
continue
# one last step with rate set to _rate_min
rate = self._rate_min
continue
- else:
- self._search_result = SearchResults.FAILURE
- self._search_result_rate = None
- return
- else:
- continue
+ self._search_result = SearchResults.FAILURE
+ self._search_result_rate = None
+ return
+ continue
# no loss => non/partial drop rate found
elif res:
self._search_result = SearchResults.SUCCESS
self._search_result_rate = rate
return
# no loss => non/partial drop rate found
elif res:
self._search_result = SearchResults.SUCCESS
self._search_result_rate = rate
return
- else:
- raise RuntimeError("Unknown search result")
- else:
- raise Exception("Unknown search direction")
+ raise RuntimeError(u"Unknown search result")
+ raise Exception(u"Unknown search direction")
def verify_search_result(self):
"""Fail if search was not successful.
def verify_search_result(self):
"""Fail if search was not successful.
@@
-444,13
+436,14
@@
class DropRateSearch(object):
:rtype: tuple
:raises Exception: If search failed.
"""
:rtype: tuple
:raises Exception: If search failed.
"""
- if self._search_result in
[
- SearchResults.SUCCESS, SearchResults.SUSPICIOUS]:
+ if self._search_result in
\
+
[
SearchResults.SUCCESS, SearchResults.SUSPICIOUS]:
return self._search_result_rate, self.get_latency()
return self._search_result_rate, self.get_latency()
- raise Exception(
'Search FAILED'
)
+ raise Exception(
u"Search FAILED"
)
- def binary_search(self, b_min, b_max, traffic_profile, skip_max_rate=False,
- skip_warmup=False):
+ def binary_search(
+ self, b_min, b_max, traffic_profile, skip_max_rate=False,
+ skip_warmup=False):
"""Binary search of rate with loss below acceptance criteria.
:param b_min: Min range rate.
"""Binary search of rate with loss below acceptance criteria.
:param b_min: Min range rate.
@@
-466,13
+459,12
@@
class DropRateSearch(object):
:returns: nothing
:raises ValueError: If input values are not valid.
"""
:returns: nothing
:raises ValueError: If input values are not valid.
"""
-
if not self._rate_min <= float(b_min) <= self._rate_max:
if not self._rate_min <= float(b_min) <= self._rate_max:
- raise ValueError("Min rate is not in min,max range")
+ raise ValueError(
u
"Min rate is not in min,max range")
if not self._rate_min <= float(b_max) <= self._rate_max:
if not self._rate_min <= float(b_max) <= self._rate_max:
- raise ValueError("Max rate is not in min,max range")
+ raise ValueError(
u
"Max rate is not in min,max range")
if float(b_max) < float(b_min):
if float(b_max) < float(b_min):
- raise ValueError("Min rate is greater than max rate")
+ raise ValueError(
u
"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) \
# rate is half of interval + start of interval if not using max rate
rate = ((float(b_max) - float(b_min)) / 2) + float(b_min) \
@@
-494,7
+486,8
@@
class DropRateSearch(object):
res.append(self.measure_loss(
rate, self._frame_size, self._loss_acceptance,
self._loss_acceptance_type, traffic_profile,
res.append(self.measure_loss(
rate, self._frame_size, self._loss_acceptance,
self._loss_acceptance_type, traffic_profile,
- skip_warmup=skip_warmup))
+ skip_warmup=skip_warmup
+ ))
res = self._get_res_based_on_search_type(res)
res = self._get_res_based_on_search_type(res)
@@
-516,11
+509,10
@@
class DropRateSearch(object):
:returns: nothing
:raises RuntimeError: If linear search failed.
"""
:returns: nothing
:raises RuntimeError: If linear search failed.
"""
-
self.linear_search(start_rate, traffic_profile)
self.linear_search(start_rate, traffic_profile)
- if self._search_result in
[SearchResults.SUCCESS,
-
SearchResults.SUSPICIOUS]:
+ if self._search_result in
\
+
[SearchResults.SUCCESS,
SearchResults.SUSPICIOUS]:
b_min = self._search_result_rate
b_max = self._search_result_rate + self._rate_linear_step
b_min = self._search_result_rate
b_max = self._search_result_rate + self._rate_linear_step
@@
-539,15
+531,16
@@
class DropRateSearch(object):
# we will use binary search to refine search in one linear step
self.binary_search(b_min, b_max, traffic_profile, True)
# we will use binary search to refine search in one linear step
self.binary_search(b_min, b_max, traffic_profile, True)
- # linear and binary search succeed
- if self._search_result == SearchResults.SUCCESS:
- return
+
# linear search succeed but binary failed or suspicious
# linear search succeed but binary failed or suspicious
-
else
:
+
if self._search_result != SearchResults.SUCCESS
:
self._search_result = SearchResults.SUSPICIOUS
self._search_result_rate = temp_rate
self._search_result = SearchResults.SUSPICIOUS
self._search_result_rate = temp_rate
+ # linear and binary search succeed
+ else:
+ return
else:
else:
- raise RuntimeError("Linear search FAILED")
+ raise RuntimeError(
u
"Linear search FAILED")
@staticmethod
def floats_are_close_equal(num_a, num_b, rel_tol=1e-9, abs_tol=0.0):
@staticmethod
def floats_are_close_equal(num_a, num_b, rel_tol=1e-9, abs_tol=0.0):
@@
-555,23
+548,24
@@
class DropRateSearch(object):
:param num_a: First number to compare.
:param num_b: Second number to compare.
:param num_a: First number to compare.
:param num_b: Second number to compare.
- :param rel_tol=1e-9: The relative tolerance.
- :param abs_tol=0.0: The minimum absolute tolerance level.
+ :param rel_tol: The relative tolerance.
+ :param abs_tol: The minimum absolute tolerance level. (Optional,
+ default value: 0.0)
:type num_a: float
:type num_b: float
:type rel_tol: float
:type abs_tol: float
:returns: Returns True if num_a is close in value to num_b or equal.
:type num_a: float
:type num_b: float
:type rel_tol: float
:type abs_tol: float
:returns: Returns True if num_a is close in value to num_b or equal.
-
False otherwise.
+ False otherwise.
:rtype: boolean
:raises ValueError: If input values are not valid.
"""
:rtype: boolean
:raises ValueError: If input values are not valid.
"""
-
if num_a == num_b:
return True
if rel_tol < 0.0 or abs_tol < 0.0:
if num_a == num_b:
return True
if rel_tol < 0.0 or abs_tol < 0.0:
- raise ValueError(
'Error tolerances must be non-negative'
)
+ raise ValueError(
u"Error tolerances must be non-negative"
)
- return abs(num_b - num_a) <= max(rel_tol * max(abs(num_a), abs(num_b)),
- abs_tol)
+ return abs(num_b - num_a) <= max(
+ rel_tol * max(abs(num_a), abs(num_b)), abs_tol
+ )