diff options
Diffstat (limited to 'yardstick/network_services/traffic_profile')
5 files changed, 343 insertions, 4 deletions
diff --git a/yardstick/network_services/traffic_profile/http_ixload.py b/yardstick/network_services/traffic_profile/http_ixload.py index 8a4f97f04..348056551 100644 --- a/yardstick/network_services/traffic_profile/http_ixload.py +++ b/yardstick/network_services/traffic_profile/http_ixload.py @@ -18,6 +18,7 @@ from __future__ import print_function import sys import os import logging +import collections # ixload uses its own py2. So importing jsonutils fails. So adding below # workaround to support call from yardstick @@ -26,8 +27,16 @@ try: except ImportError: import json as jsonutils -from yardstick.common.utils import join_non_strings -from yardstick.common.utils import ErrorClass + +class ErrorClass(object): + + def __init__(self, *args, **kwargs): + if 'test' not in kwargs: + raise RuntimeError + + def __getattr__(self, item): + raise AttributeError + try: from IxLoad import IxLoad, StatCollectorUtils @@ -80,11 +89,25 @@ Incoming stats: Time interval: %s """ +def validate_non_string_sequence(value, default=None, raise_exc=None): + if isinstance(value, collections.Sequence) and not isinstance(value, str): + return value + if raise_exc: + raise raise_exc + return default + + +def join_non_strings(separator, *non_strings): + try: + non_strings = validate_non_string_sequence(non_strings[0], raise_exc=RuntimeError) + except (IndexError, RuntimeError): + pass + return str(separator).join(str(non_string) for non_string in non_strings) + + class IXLOADHttpTest(object): def __init__(self, test_input): - self.test_input = jsonutils.loads(test_input) - self.parse_run_test() self.ix_load = None self.stat_utils = None self.remote_server = None @@ -94,6 +117,8 @@ class IXLOADHttpTest(object): self.chassis = None self.card = None self.ports_to_reassign = None + self.test_input = jsonutils.loads(test_input) + self.parse_run_test() @staticmethod def format_ports_for_reassignment(ports): @@ -291,4 +316,5 @@ def main(args): ixload_obj.start_http_test() if __name__ == '__main__': + LOG.info("Start http_ixload test") main(sys.argv) diff --git a/yardstick/network_services/traffic_profile/prox_ACL.py b/yardstick/network_services/traffic_profile/prox_ACL.py new file mode 100644 index 000000000..cb6246fcd --- /dev/null +++ b/yardstick/network_services/traffic_profile/prox_ACL.py @@ -0,0 +1,55 @@ +# Copyright (c) 2016-2017 Intel 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. +""" Fixed traffic profile definitions """ + +from __future__ import absolute_import + +import logging + +from yardstick.network_services.traffic_profile.prox_profile import ProxProfile + +LOG = logging.getLogger(__name__) + + +class ProxACLProfile(ProxProfile): + """ + This profile adds a single stream at the beginning of the traffic session + """ + def run_test_with_pkt_size(self, traffic_gen, pkt_size, duration): + """Run the test for a single packet size. + + :param traffic_gen: traffic generator instance + :type traffic_gen: TrafficGen + :param pkt_size: The packet size to test with. + :type pkt_size: int + :param duration: The duration for each try. + :type duration: int + + """ + + test_value = self.upper_bound + + # throughput and packet loss from the last successful test + while test_value == self.upper_bound: + result = traffic_gen.resource_helper.run_test(pkt_size, duration, + test_value, self.tolerated_loss) + + if result.success: + LOG.debug("Success! ") + else: + LOG.debug("Failure...") + + samples = result.get_samples(pkt_size) + self.fill_samples(samples, traffic_gen) + self.queue.put(samples) diff --git a/yardstick/network_services/traffic_profile/prox_binsearch.py b/yardstick/network_services/traffic_profile/prox_binsearch.py new file mode 100644 index 000000000..f98b1e59e --- /dev/null +++ b/yardstick/network_services/traffic_profile/prox_binsearch.py @@ -0,0 +1,101 @@ +# Copyright (c) 2016-2017 Intel 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. +""" Fixed traffic profile definitions """ + +from __future__ import absolute_import + +import logging + +from yardstick.network_services.traffic_profile.prox_profile import ProxProfile + +LOG = logging.getLogger(__name__) + + +class ProxBinSearchProfile(ProxProfile): + """ + This profile adds a single stream at the beginning of the traffic session + """ + + def __init__(self, tp_config): + super(ProxBinSearchProfile, self).__init__(tp_config) + self.current_lower = self.lower_bound + self.current_upper = self.upper_bound + + @property + def delta(self): + return self.current_upper - self.current_lower + + @property + def mid_point(self): + return (self.current_lower + self.current_upper) / 2 + + def bounds_iterator(self, logger=None): + self.current_lower = self.lower_bound + self.current_upper = self.upper_bound + + test_value = self.current_upper + while abs(self.delta) >= self.precision: + if logger: + logger.debug("New interval [%s, %s), precision: %d", self.current_lower, + self.current_upper, self.step_value) + logger.info("Testing with value %s", test_value) + + yield test_value + test_value = self.mid_point + + def run_test_with_pkt_size(self, traffic_gen, pkt_size, duration): + """Run the test for a single packet size. + + :param queue: queue object we put samples into + :type queue: Queue + :param traffic_gen: traffic generator instance + :type traffic_gen: TrafficGen + :param pkt_size: The packet size to test with. + :type pkt_size: int + :param duration: The duration for each try. + :type duration: int + + """ + + LOG.info("Testing with packet size %d", pkt_size) + + # Binary search assumes the lower value of the interval is + # successful and the upper value is a failure. + # The first value that is tested, is the maximum value. If that + # succeeds, no more searching is needed. If it fails, a regular + # binary search is performed. + # + # The test_value used for the first iteration of binary search + # is adjusted so that the delta between this test_value and the + # upper bound is a power-of-2 multiple of precision. In the + # optimistic situation where this first test_value results in a + # success, the binary search will complete on an integer multiple + # of the precision, rather than on a fraction of it. + + # throughput and packet loss from the most recent successful test + successful_pkt_loss = 0.0 + for test_value in self.bounds_iterator(LOG): + result = traffic_gen.resource_helper.run_test(pkt_size, duration, + test_value, self.tolerated_loss) + + if result.success: + LOG.debug("Success! Increasing lower bound") + self.current_lower = test_value + successful_pkt_loss = result.pkt_loss + else: + LOG.debug("Failure... Decreasing upper bound") + self.current_upper = test_value + + samples = result.get_samples(pkt_size, successful_pkt_loss) + self.queue.put(samples) diff --git a/yardstick/network_services/traffic_profile/prox_profile.py b/yardstick/network_services/traffic_profile/prox_profile.py new file mode 100644 index 000000000..daeaf42ed --- /dev/null +++ b/yardstick/network_services/traffic_profile/prox_profile.py @@ -0,0 +1,104 @@ +# Copyright (c) 2016-2017 Intel 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. +""" Fixed traffic profile definitions """ + +from __future__ import absolute_import + +import logging + +from yardstick.network_services.traffic_profile.base import TrafficProfile + +LOG = logging.getLogger(__name__) + + +class ProxProfile(TrafficProfile): + """ + This profile adds a single stream at the beginning of the traffic session + """ + + @staticmethod + def fill_samples(samples, traffic_gen): + for vpci_idx, intf in enumerate(traffic_gen.vpci_if_name_ascending): + name = intf[1] + # TODO: VNFDs KPIs values needs to be mapped to TRex structure + xe_port = traffic_gen.resource_helper.sut.port_stats([vpci_idx]) + samples[name] = { + "in_packets": xe_port[6], + "out_packets": xe_port[7], + } + + def __init__(self, tp_config): + super(ProxProfile, self).__init__(tp_config) + self.queue = None + self.done = False + self.results = [] + + # TODO: get init values from tp_config + self.prox_config = tp_config["traffic_profile"] + self.pkt_sizes = [int(x) for x in self.prox_config.get("packet_sizes", [])] + self.pkt_size_iterator = iter(self.pkt_sizes) + self.duration = int(self.prox_config.get("duration", 5)) + self.precision = float(self.prox_config.get('test_precision', 1.0)) + self.tolerated_loss = float(self.prox_config.get('tolerated_loss', 0.0)) + + # TODO: is this ever a function of packet size? + self.lower_bound = float(self.prox_config.get('lower_bound', 10.0)) + self.upper_bound = float(self.prox_config.get('upper_bound', 100.0)) + self.step_value = float(self.prox_config.get('step_value', 10.0)) + + def init(self, queue): + self.pkt_size_iterator = iter(self.pkt_sizes) + self.queue = queue + + def bounds_iterator(self, logger=None): + if logger: + logger.debug("Interval [%s, %s), step: %d", self.lower_bound, + self.upper_bound, self.step_value) + + test_value = self.lower_bound + while test_value <= self.upper_bound: + if logger: + logger.info("Testing with value %s", test_value) + yield test_value + test_value += self.step_value + + @property + def min_pkt_size(self): + """Return the minimum required packet size for the test. + + Defaults to 64. Individual test must override this method if they have + other requirements. + + Returns: + int. The minimum required packet size for the test. + """ + return 64 + + def run_test_with_pkt_size(self, traffic_generator, pkt_size, duration): + raise NotImplementedError + + def execute(self, traffic_generator): + try: + pkt_size = next(self.pkt_size_iterator) + except StopIteration: + self.done = True + return + + # Adjust packet size upwards if it's less than the minimum + # required packet size for the test. + if pkt_size < self.min_pkt_size: + pkt_size += self.min_pkt_size - 64 + + duration = self.duration + self.run_test_with_pkt_size(traffic_generator, pkt_size, duration) diff --git a/yardstick/network_services/traffic_profile/prox_ramp.py b/yardstick/network_services/traffic_profile/prox_ramp.py new file mode 100644 index 000000000..0f7995c1d --- /dev/null +++ b/yardstick/network_services/traffic_profile/prox_ramp.py @@ -0,0 +1,53 @@ +# Copyright (c) 2016-2017 Intel 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. +""" Fixed traffic profile definitions """ + +from __future__ import absolute_import + +import logging + +from yardstick.network_services.traffic_profile.prox_profile import ProxProfile + +LOG = logging.getLogger(__name__) + + +class ProxRampProfile(ProxProfile): + + def run_test_with_pkt_size(self, traffic_gen, pkt_size, duration): + """Run the test for a single packet size. + + :param traffic_gen: traffic generator instance + :type traffic_gen: TrafficGen + :param pkt_size: The packet size to test with. + :type pkt_size: int + :param duration: The duration for each try. + :type duration: int + + """ + + LOG.info("Testing with packet size %d", pkt_size) + + for test_value in self.bounds_iterator(LOG): + test_result = traffic_gen.resource_helper.run_test(pkt_size, duration, + test_value, self.tolerated_loss) + + if not test_result.success: + LOG.debug("Failure... stopping") + break + + LOG.debug("Success! Increasing test value") + samples = test_result.get_samples(pkt_size) + self.fill_samples(samples, traffic_gen) + + self.queue.put(samples) |