From 02f4147b37e6ed4fb8a0f7f344e3b9b50a06b0b2 Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Thu, 19 Jul 2018 12:30:59 +0100 Subject: Accept line rate percentage or fps a initial rate for IXIA RFC2544 Accept line rate percentage or fps a initial rate for IXIA RFC2544 traffic profile: traffic_profile: traffic_type : IXIARFC2544Profile frame_rate : 100% traffic_profile: traffic_type : IXIARFC2544Profile frame_rate : 5000fps JIRA: YARDSTICK-1336 Change-Id: I85b3dd0daf563bb7af098a3aa5bb872961fb009b Signed-off-by: Rodolfo Alonso Hernandez --- yardstick/common/exceptions.py | 6 ++-- .../libs/ixia_libs/ixnet/ixnet_api.py | 12 +++++--- yardstick/network_services/traffic_profile/base.py | 32 ++++++++++++++++++++-- .../traffic_profile/ixia_rfc2544.py | 24 ++++++++-------- .../libs/ixia_libs/test_ixnet_api.py | 12 ++++++-- .../network_services/traffic_profile/test_base.py | 21 +++++++++++++- 6 files changed, 83 insertions(+), 24 deletions(-) diff --git a/yardstick/common/exceptions.py b/yardstick/common/exceptions.py index cbb294989..2e6cbdd7b 100644 --- a/yardstick/common/exceptions.py +++ b/yardstick/common/exceptions.py @@ -85,7 +85,6 @@ class InfluxDBConfigurationMissing(YardstickException): class YardstickBannedModuleImported(YardstickException): - # pragma: no cover message = 'Module "%(module)s" cannnot be imported. Reason: "%(reason)s"' @@ -95,7 +94,6 @@ class PayloadMissingAttributes(YardstickException): class HeatTemplateError(YardstickException): - """Error in Heat during the stack deployment""" message = ('Error in Heat during the creation of the OpenStack stack ' '"%(stack_name)s"') @@ -108,6 +106,10 @@ class TrafficProfileNotImplemented(YardstickException): message = 'No implementation for traffic profile %(profile_class)s.' +class TrafficProfileRate(YardstickException): + message = 'Traffic profile rate must be "[fps|%]"' + + class DPDKSetupDriverError(YardstickException): message = '"igb_uio" driver is not loaded' diff --git a/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py b/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py index 74deeecb5..cee768dba 100644 --- a/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py +++ b/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py @@ -18,6 +18,7 @@ import IxNetwork from yardstick.common import exceptions from yardstick.common import utils +from yardstick.network_services.traffic_profile import base as tp_base log = logging.getLogger(__name__) @@ -336,8 +337,8 @@ class IxNextgen(object): # pragma: no cover - Duration: in case of traffic_type="fixedDuration", amount of seconds to inject traffic. - Rate: in frames per seconds or percentage. - - Type of rate: "framesPerSecond" ("bitsPerSecond" and - "percentLineRate" no used) + - Type of rate: "framesPerSecond" or "percentLineRate" ("bitsPerSecond" + no used) - Frame size: custom IMIX [1] definition; a list of packet size in bytes and the weight. E.g.: [[64, 64, 10], [128, 128, 15], [512, 512, 5]] @@ -355,7 +356,10 @@ class IxNextgen(object): # pragma: no cover type = traffic_param.get('traffic_type', 'fixedDuration') duration = traffic_param.get('duration', 30) - rate = traffic_param['iload'] + rate = traffic_param['rate'] + rate_unit = ( + 'framesPerSecond' if traffic_param['rate_unit'] == + tp_base.TrafficProfileConfig.RATE_FPS else 'percentLineRate') weighted_range_pairs = self._parse_framesize( traffic_param['outer_l2']['framesize']) srcmac = str(traffic_param.get('srcmac', '00:00:00:00:00:01')) @@ -370,7 +374,7 @@ class IxNextgen(object): # pragma: no cover '-type', type, '-duration', duration) self.ixnet.setMultiAttribute( config_element + '/frameRate', - '-rate', rate, '-type', 'framesPerSecond') + '-rate', rate, '-type', rate_unit) self.ixnet.setMultiAttribute( config_element + '/frameSize', '-type', 'weightedPairs', diff --git a/yardstick/network_services/traffic_profile/base.py b/yardstick/network_services/traffic_profile/base.py index f4b5b178c..a8f950b7b 100644 --- a/yardstick/network_services/traffic_profile/base.py +++ b/yardstick/network_services/traffic_profile/base.py @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +import re + from yardstick.common import exceptions from yardstick.common import utils @@ -21,10 +23,12 @@ class TrafficProfileConfig(object): This object will parse and validate the traffic profile information. """ - DEFAULT_SCHEMA = 'nsb:traffic_profile:0.1' - DEFAULT_FRAME_RATE = 100 + DEFAULT_FRAME_RATE = '100' DEFAULT_DURATION = 30 + RATE_FPS = 'fps' + RATE_PERCENTAGE = '%' + RATE_REGEX = re.compile(r'([0-9]*\.[0-9]+|[0-9]+)\s*(fps|%)*(.*)') def __init__(self, tp_config): self.schema = tp_config.get('schema', self.DEFAULT_SCHEMA) @@ -32,7 +36,8 @@ class TrafficProfileConfig(object): self.description = tp_config.get('description') tprofile = tp_config['traffic_profile'] self.traffic_type = tprofile.get('traffic_type') - self.frame_rate = tprofile.get('frame_rate', self.DEFAULT_FRAME_RATE) + self.frame_rate, self.rate_unit = self._parse_rate( + tprofile.get('frame_rate', self.DEFAULT_FRAME_RATE)) self.test_precision = tprofile.get('test_precision') self.packet_sizes = tprofile.get('packet_sizes') self.duration = tprofile.get('duration', self.DEFAULT_DURATION) @@ -40,6 +45,27 @@ class TrafficProfileConfig(object): self.upper_bound = tprofile.get('upper_bound') self.step_interval = tprofile.get('step_interval') + def _parse_rate(self, rate): + """Parse traffic profile rate + + The line rate can be defined in fps or percentage over the maximum line + rate: + - frame_rate = 5000 (by default, unit is 'fps') + - frame_rate = 5000fps + - frame_rate = 25% + + :param rate: (string, int) line rate in fps or % + :return: (tuple: int, string) line rate number and unit + """ + match = self.RATE_REGEX.match(str(rate)) + if not match: + exceptions.TrafficProfileRate() + rate = float(match.group(1)) + unit = match.group(2) if match.group(2) else self.RATE_FPS + if match.group(3): + raise exceptions.TrafficProfileRate() + return rate, unit + class TrafficProfile(object): """ diff --git a/yardstick/network_services/traffic_profile/ixia_rfc2544.py b/yardstick/network_services/traffic_profile/ixia_rfc2544.py index 39336785e..7d54ec4ab 100644 --- a/yardstick/network_services/traffic_profile/ixia_rfc2544.py +++ b/yardstick/network_services/traffic_profile/ixia_rfc2544.py @@ -14,13 +14,14 @@ import logging -from yardstick.network_services.traffic_profile.trex_traffic_profile import \ - TrexProfile +from yardstick.network_services.traffic_profile import base as tp_base +from yardstick.network_services.traffic_profile import trex_traffic_profile + LOG = logging.getLogger(__name__) -class IXIARFC2544Profile(TrexProfile): +class IXIARFC2544Profile(trex_traffic_profile.TrexProfile): UPLINK = 'uplink' DOWNLINK = 'downlink' @@ -28,11 +29,10 @@ class IXIARFC2544Profile(TrexProfile): def __init__(self, yaml_data): super(IXIARFC2544Profile, self).__init__(yaml_data) self.rate = self.config.frame_rate + self.rate_unit = self.config.rate_unit def _get_ixia_traffic_profile(self, profile_data, mac=None): - if mac is None: - mac = {} - + mac = {} if mac is None else mac result = {} for traffickey, values in profile_data.items(): if not traffickey.startswith((self.UPLINK, self.DOWNLINK)): @@ -58,8 +58,9 @@ class IXIARFC2544Profile(TrexProfile): result[traffickey] = { 'bidir': False, - 'iload': '100', 'id': port_id, + 'rate': self.rate, + 'rate_unit': self.rate_unit, 'outer_l2': { 'framesize': value['outer_l2']['framesize'], 'framesPerSecond': True, @@ -83,9 +84,6 @@ class IXIARFC2544Profile(TrexProfile): return result def _ixia_traffic_generate(self, traffic, ixia_obj): - for key, value in traffic.items(): - if key.startswith((self.UPLINK, self.DOWNLINK)): - value['iload'] = str(self.rate) ixia_obj.update_frame(traffic) ixia_obj.update_ip_packet(traffic) ixia_obj.start_traffic() @@ -114,7 +112,7 @@ class IXIARFC2544Profile(TrexProfile): self.pg_id = 0 self.update_traffic_profile(traffic_generator) self.max_rate = self.rate - self.min_rate = 0 + self.min_rate = 0.0 else: self.rate = round(float(self.max_rate + self.min_rate) / 2.0, 2) @@ -150,8 +148,10 @@ class IXIARFC2544Profile(TrexProfile): samples['DropPercentage'] = drop_percent if first_run: - self.rate = out_packets_sum / duration / num_ifaces completed = True if drop_percent <= tolerance else False + if (first_run and + self.rate_unit == tp_base.TrafficProfileConfig.RATE_FPS): + self.rate = out_packets_sum / duration / num_ifaces if drop_percent > tolerance: self.max_rate = self.rate diff --git a/yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py b/yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py index 541855aa8..afa4cc3dc 100644 --- a/yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py +++ b/yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py @@ -28,7 +28,8 @@ TRAFFIC_PARAMETERS = { 'id': 1, 'bidir': 'False', 'duration': 60, - 'iload': '100', + 'rate': 10000.5, + 'rate_unit': 'fps', 'outer_l2': { 'framesize': {'64B': '25', '256B': '75'} }, @@ -65,7 +66,8 @@ TRAFFIC_PARAMETERS = { 'id': 2, 'bidir': 'False', 'duration': 60, - 'iload': '100', + 'rate': 75.2, + 'rate_unit': '%', 'outer_l2': { 'framesize': {'128B': '35', '1024B': '65'} }, @@ -396,6 +398,12 @@ class TestIxNextgen(unittest.TestCase): self.assertEqual(6, len(ixnet_gen.ixnet.setMultiAttribute.mock_calls)) self.assertEqual(4, len(mock_update_frame.mock_calls)) + ixnet_gen.ixnet.setMultiAttribute.assert_has_calls( + [mock.call('cfg_element/frameRate', '-rate', 10000.5, + '-type', 'framesPerSecond'), + mock.call('cfg_element/frameRate', '-rate', 75.2, '-type', + 'percentLineRate')], + any_order=True) def test_update_frame_flow_not_present(self): ixnet_gen = ixnet_api.IxNextgen() diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_base.py b/yardstick/tests/unit/network_services/traffic_profile/test_base.py index 55276af58..2a366fc94 100644 --- a/yardstick/tests/unit/network_services/traffic_profile/test_base.py +++ b/yardstick/tests/unit/network_services/traffic_profile/test_base.py @@ -82,7 +82,26 @@ class TrafficProfileConfigTestCase(unittest.TestCase): self.assertEqual({'64B': 100}, tp_config_obj.packet_sizes) self.assertEqual(base.TrafficProfileConfig.DEFAULT_SCHEMA, tp_config_obj.schema) - self.assertEqual(base.TrafficProfileConfig.DEFAULT_FRAME_RATE, + self.assertEqual(float(base.TrafficProfileConfig.DEFAULT_FRAME_RATE), tp_config_obj.frame_rate) self.assertEqual(base.TrafficProfileConfig.DEFAULT_DURATION, tp_config_obj.duration) + + def test__parse_rate(self): + tp_config = {'traffic_profile': {'packet_sizes': {'64B': 100}}} + tp_config_obj = base.TrafficProfileConfig(tp_config) + self.assertEqual((100.0, 'fps'), tp_config_obj._parse_rate('100 ')) + self.assertEqual((200.5, 'fps'), tp_config_obj._parse_rate('200.5')) + self.assertEqual((300.8, 'fps'), tp_config_obj._parse_rate('300.8fps')) + self.assertEqual((400.2, 'fps'), + tp_config_obj._parse_rate('400.2 fps')) + self.assertEqual((500.3, '%'), tp_config_obj._parse_rate('500.3%')) + self.assertEqual((600.1, '%'), tp_config_obj._parse_rate('600.1 %')) + + def test__parse_rate_exception(self): + tp_config = {'traffic_profile': {'packet_sizes': {'64B': 100}}} + tp_config_obj = base.TrafficProfileConfig(tp_config) + with self.assertRaises(exceptions.TrafficProfileRate): + tp_config_obj._parse_rate('100Fps') + with self.assertRaises(exceptions.TrafficProfileRate): + tp_config_obj._parse_rate('100 kbps') -- cgit 1.2.3-korg