diff options
author | Rodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com> | 2018-04-10 09:15:55 +0100 |
---|---|---|
committer | Rodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com> | 2018-06-12 08:31:00 +0100 |
commit | 8d10a6a8447fc2798491a6f3856e21b85fa309ba (patch) | |
tree | b775fdcf0513a7ef5f1d5ec0be2c2fe8a245cc89 /yardstick/network_services/libs/ixia_libs | |
parent | ee721fd3e8b77ccfe4252a107a9af8dc41ccc389 (diff) |
Improve IXIA IxNetwork library and traffic profile (2)
This patch modifies the way the packet frame and the flow is configured
before the injection.
"IxNextgen.update_frame" modifies the L2 frame according to the
test case and setup the frame rate, frame size, traffic injection
duration and MAC addresses.
JIRA: YARDSTICK-1116
Change-Id: Ife08f15a4eda24d7835c92c4172b450854d112ee
Signed-off-by: Rodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
Signed-off-by: Emma Foley <emma.l.foley@intel.com>
Diffstat (limited to 'yardstick/network_services/libs/ixia_libs')
-rw-r--r-- | yardstick/network_services/libs/ixia_libs/ixnet/__init__.py (renamed from yardstick/network_services/libs/ixia_libs/IxNet/__init__.py) | 0 | ||||
-rw-r--r-- | yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py (renamed from yardstick/network_services/libs/ixia_libs/IxNet/IxNet.py) | 359 |
2 files changed, 189 insertions, 170 deletions
diff --git a/yardstick/network_services/libs/ixia_libs/IxNet/__init__.py b/yardstick/network_services/libs/ixia_libs/ixnet/__init__.py index e69de29bb..e69de29bb 100644 --- a/yardstick/network_services/libs/ixia_libs/IxNet/__init__.py +++ b/yardstick/network_services/libs/ixia_libs/ixnet/__init__.py diff --git a/yardstick/network_services/libs/ixia_libs/IxNet/IxNet.py b/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py index 0cf2a4126..70d0eeed8 100644 --- a/yardstick/network_services/libs/ixia_libs/IxNet/IxNet.py +++ b/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py @@ -14,10 +14,10 @@ import logging -import re -from itertools import product import IxNetwork +from yardstick.common import exceptions + log = logging.getLogger(__name__) @@ -30,57 +30,8 @@ PROTO_TCP = 'tcp' PROTO_VLAN = 'vlan' -class TrafficStreamHelper(object): - - TEMPLATE = '{0.traffic_item}/{0.stream}:{0.param_id}/{1}' - - def __init__(self, traffic_item, stream, param_id): - super(TrafficStreamHelper, self).__init__() - self.traffic_item = traffic_item - self.stream = stream - self.param_id = param_id - - def __getattr__(self, item): - return self.TEMPLATE.format(self, item) - - -class FramesizeHelper(object): - - def __init__(self): - super(FramesizeHelper, self).__init__() - self.weighted_pairs = [] - self.weighted_range_pairs = [] - - @property - def weighted_pairs_arg(self): - return '-weightedPairs', self.weighted_pairs - - @property - def weighted_range_pairs_arg(self): - return '-weightedRangePairs', self.weighted_range_pairs - - def make_args(self, *args): - return self.weighted_pairs_arg + self.weighted_range_pairs_arg + args - - def populate_data(self, framesize_data): - for key, value in framesize_data.items(): - if value == '0': - continue - - replaced = re.sub('[Bb]', '', key) - self.weighted_pairs.extend([ - replaced, - value, - ]) - pairs = [ - replaced, - replaced, - value, - ] - self.weighted_range_pairs.append(pairs) - - -class IxNextgen(object): +# NOTE(ralonsoh): this pragma will be removed in the last patch of this series +class IxNextgen(object): # pragma: no cover PORT_STATS_NAME_MAP = { "stat_name": 'Stat Name', @@ -135,59 +86,61 @@ class IxNextgen(object): return cfg - def __init__(self, ixnet=None): - self.ixnet = ixnet - self._objRefs = dict() + def __init__(self): # pragma: no cover + self._ixnet = None self._cfg = None self._params = None self._bidir = None + @property + def ixnet(self): # pragma: no cover + if self._ixnet: + return self._ixnet + raise exceptions.IxNetworkClientNotConnected() + + def _get_config_element_by_flow_group_name(self, flow_group_name): + """Get a config element using the flow group name + + Each named flow group contains one config element (by configuration). + According to the documentation, "configElements" is a list and "each + item in this list is aligned to the sequential order of your endpoint + list". + + :param flow_group_name: (str) flow group name; this parameter is + always a number (converted to string) starting + from "1". + :return: (str) config element reference ID or None. + """ + traffic_item = self.ixnet.getList(self.ixnet.getRoot() + '/traffic', + 'trafficItem')[0] + flow_groups = self.ixnet.getList(traffic_item, 'endpointSet') + for flow_group in flow_groups: + if (str(self.ixnet.getAttribute(flow_group, '-name')) == + flow_group_name): + return traffic_item + '/configElement:' + flow_group_name + + @staticmethod + def _parse_framesize(framesize): + """Parse "framesize" config param. to return a list of weighted pairs + + :param framesize: dictionary of frame sizes and weights + :return: list of paired frame sizes and weights + """ + weighted_range_pairs = [] + for size, weight in framesize.items(): + weighted_range_pairs.append(int(size.upper().replace('B', ''))) + weighted_range_pairs.append(int(weight)) + return weighted_range_pairs + def iter_over_get_lists(self, x1, x2, y2, offset=0): for x in self.ixnet.getList(x1, x2): y_list = self.ixnet.getList(x, y2) for i, y in enumerate(y_list, offset): yield x, y, i - def set_random_ip_multi_attribute(self, ipv4, seed, fixed_bits, random_mask, l3_count): - self.ixnet.setMultiAttribute( - ipv4, - '-seed', str(seed), - '-fixedBits', str(fixed_bits), - '-randomMask', str(random_mask), - '-valueType', 'random', - '-countValue', str(l3_count)) - - def set_random_ip_multi_attributes(self, ip, version, seeds, l3): - try: - random_mask = self.RANDOM_MASK_MAP[version] - except KeyError: - raise ValueError('Unknown version %s' % version) - - l3_count = l3['count'] - if "srcIp" in ip: - fixed_bits = l3['srcip4'] - self.set_random_ip_multi_attribute(ip, seeds[0], fixed_bits, random_mask, l3_count) - if "dstIp" in ip: - fixed_bits = l3['dstip4'] - self.set_random_ip_multi_attribute(ip, seeds[1], fixed_bits, random_mask, l3_count) - - def add_ip_header(self, params, version): - for _, ep, i in self.iter_over_get_lists('/traffic', 'trafficItem', "configElement", 1): - iter1 = (v['outer_l3'] for v in params.values() if str(v['id']) == str(i)) - try: - l3 = next(iter1, {}) - seeds = self.MODE_SEEDS_MAP.get(i, self.MODE_SEEDS_DEFAULT)[1] - except (KeyError, IndexError): - continue - - for _, ip_bits, _ in self.iter_over_get_lists(ep, 'stack', 'field'): - self.set_random_ip_multi_attributes(ip_bits, version, seeds, l3) - - self.ixnet.commit() - def connect(self, tg_cfg): self._cfg = self.get_config(tg_cfg) - self.ixnet = IxNetwork.IxNet() + self._ixnet = IxNetwork.IxNet() machine = self._cfg['machine'] port = str(self._cfg['port']) @@ -255,19 +208,21 @@ class IxNextgen(object): vports = self.ixnet.getList(self.ixnet.getRoot(), 'vport') uplink_ports = vports[::2] downlink_ports = vports[1::2] + index = 0 for up, down in zip(uplink_ports, downlink_ports): log.info('FGs: %s <--> %s', up, down) endpoint_set_1 = self.ixnet.add(traffic_item_id, 'endpointSet') endpoint_set_2 = self.ixnet.add(traffic_item_id, 'endpointSet') self.ixnet.setMultiAttribute( - endpoint_set_1, - '-sources', [up + ' /protocols'], + endpoint_set_1, '-name', str(index + 1), + '-sources', [up + '/protocols'], '-destinations', [down + '/protocols']) self.ixnet.setMultiAttribute( - endpoint_set_2, - '-sources', [down + ' /protocols'], + endpoint_set_2, '-name', str(index + 2), + '-sources', [down + '/protocols'], '-destinations', [up + '/protocols']) self.ixnet.commit() + index += 2 def _append_procotol_to_stack(self, protocol_name, previous_element): """Append a new element in the packet definition stack""" @@ -317,87 +272,134 @@ class IxNextgen(object): self._create_flow_groups() self._setup_config_elements() - def ix_update_frame(self, params): - streams = ["configElement"] - - for param in params.values(): - framesize_data = FramesizeHelper() - traffic_items = self.ixnet.getList('/traffic', 'trafficItem') - param_id = param['id'] - for traffic_item, stream in product(traffic_items, streams): - helper = TrafficStreamHelper(traffic_item, stream, param_id) - - self.ixnet.setMultiAttribute(helper.transmissionControl, - '-type', '{0}'.format(param.get('traffic_type', - 'fixedDuration')), - '-duration', '{0}'.format(param.get('duration', - "30"))) - - stream_frame_rate_path = helper.frameRate - self.ixnet.setMultiAttribute(stream_frame_rate_path, '-rate', param['iload']) - if param['outer_l2']['framesPerSecond']: - self.ixnet.setMultiAttribute(stream_frame_rate_path, - '-type', 'framesPerSecond') - - framesize_data.populate_data(param['outer_l2']['framesize']) - - make_attr_args = framesize_data.make_args('-incrementFrom', '66', - '-randomMin', '66', - '-quadGaussian', [], - '-type', 'weightedPairs', - '-presetDistribution', 'cisco', - '-incrementTo', '1518') - - self.ixnet.setMultiAttribute(helper.frameSize, *make_attr_args) - - self.ixnet.commit() - - def update_ether_multi_attribute(self, ether, mac_addr): - self.ixnet.setMultiAttribute(ether, - '-singleValue', mac_addr, - '-fieldValue', mac_addr, + def _get_field_in_stack_item(self, stack_item, field_name): + """List all fields in a stack item an return t + + :param stack_item: (str) stack item descriptor + :param field_name: (str) field name + :return: (str) field descriptor + """ + fields = self.ixnet.getList(stack_item, 'field') + for field in (field for field in fields if field_name in field): + return field + raise exceptions.IxNetworkFieldNotPresentInStackItem( + field_name=field_name, stack_item=stack_item) + + def _update_frame_mac(self, ethernet_descriptor, field, mac_address): + """Set the MAC address in a config element stack Ethernet field + + :param ethernet_descriptor: (str) ethernet descriptor, e.g.: + /traffic/trafficItem:1/configElement:1/stack:"ethernet-1" + :param field: (str) field name, e.g.: destinationAddress + :param mac_address: (str) MAC address + """ + field_descriptor = self._get_field_in_stack_item(ethernet_descriptor, + field) + self.ixnet.setMultiAttribute(field_descriptor, + '-singleValue', mac_address, + '-fieldValue', mac_address, '-valueType', 'singleValue') + self.ixnet.commit() - def update_ether_multi_attributes(self, ether, l2): - if "ethernet.header.destinationAddress" in ether: - self.update_ether_multi_attribute(ether, str(l2.get('dstmac', "00:00:00:00:00:02"))) + def update_frame(self, traffic): + """Update the L2 frame - if "ethernet.header.sourceAddress" in ether: - self.update_ether_multi_attribute(ether, str(l2.get('srcmac', "00:00:00:00:00:01"))) + This function updates the L2 frame options: + - Traffic type: "continuous", "fixedDuration". + - 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) + - Frame size: custom IMIX [1] definition; a list of packet size in + bytes and the weight. E.g.: + [64, 10, 128, 15, 512, 5] - def ix_update_ether(self, params): - for _, ep, index in self.iter_over_get_lists('/traffic', 'trafficItem', - "configElement", 1): - iter1 = (v['outer_l2'] for v in params.values() if str(v['id']) == str(index)) - try: - l2 = next(iter1, {}) - except KeyError: - continue + [1] https://en.wikipedia.org/wiki/Internet_Mix - for _, ether, _ in self.iter_over_get_lists(ep, 'stack', 'field'): - self.update_ether_multi_attributes(ether, l2) + :param traffic: list of traffic elements; each traffic element contains + the injection parameter for each flow group. + """ + for traffic_param in traffic.values(): + config_element = self._get_config_element_by_flow_group_name( + str(traffic_param['id'])) + if not config_element: + raise exceptions.IxNetworkFlowNotPresent( + flow_group=traffic_param['id']) + + type = traffic_param.get('traffic_type', 'fixedDuration') + duration = traffic_param.get('duration', 30) + rate = traffic_param['iload'] + weighted_range_pairs = self._parse_framesize( + traffic_param['outer_l2']['framesize']) + srcmac = str(traffic_param.get('srcmac', '00:00:00:00:00:01')) + dstmac = str(traffic_param.get('dstmac', '00:00:00:00:00:02')) + # NOTE(ralonsoh): add QinQ tagging when + # traffic_param['outer_l2']['QinQ'] exists. + # s_vlan = traffic_param['outer_l2']['QinQ']['S-VLAN'] + # c_vlan = traffic_param['outer_l2']['QinQ']['C-VLAN'] - self.ixnet.commit() + self.ixnet.setMultiAttribute( + config_element + '/transmissionControl', + '-type', type, '-duration', duration) + self.ixnet.setMultiAttribute( + config_element + '/frameRate', + '-rate', rate, '-type', 'framesPerSecond') + self.ixnet.setMultiAttribute( + config_element + '/frameSize', + '-type', 'weightedPairs', + '-weightedRangePairs', weighted_range_pairs) + self.ixnet.commit() - def ix_update_udp(self, params): - pass + self._update_frame_mac( + config_element + '/stack:"ethernet-1"', + 'destinationAddress', dstmac) + self._update_frame_mac( + config_element + '/stack:"ethernet-1"', + 'sourceAddress', srcmac) - def ix_update_tcp(self, params): - pass + def set_random_ip_multi_attribute(self, ipv4, seed, fixed_bits, random_mask, l3_count): + self.ixnet.setMultiAttribute( + ipv4, + '-seed', str(seed), + '-fixedBits', str(fixed_bits), + '-randomMask', str(random_mask), + '-valueType', 'random', + '-countValue', str(l3_count)) - def ix_start_traffic(self): - tis = self.ixnet.getList('/traffic', 'trafficItem') - for ti in tis: - self.ixnet.execute('generate', [ti]) - self.ixnet.execute('apply', '/traffic') - self.ixnet.execute('start', '/traffic') + # NOTE(ralonsoh): to be updated in next patchset + # pragma: no cover + def set_random_ip_multi_attributes(self, ip, version, seeds, l3): + try: + random_mask = self.RANDOM_MASK_MAP[version] + except KeyError: + raise ValueError('Unknown version %s' % version) - def ix_stop_traffic(self): - tis = self.ixnet.getList('/traffic', 'trafficItem') - for _ in tis: - self.ixnet.execute('stop', '/traffic') + l3_count = l3['count'] + if 'srcIp' in ip: + fixed_bits = l3['srcip4'] + self.set_random_ip_multi_attribute(ip, seeds[0], fixed_bits, random_mask, l3_count) + if 'dstIp' in ip: + fixed_bits = l3['dstip4'] + self.set_random_ip_multi_attribute(ip, seeds[1], fixed_bits, random_mask, l3_count) + + # NOTE(ralonsoh): to be updated in next patchset + # pragma: no cover + def add_ip_header(self, params, version): + for _, ep, i in self.iter_over_get_lists('/traffic', 'trafficItem', "configElement", 1): + iter1 = (v['outer_l3'] for v in params.values() if str(v['id']) == str(i)) + try: + l3 = next(iter1, {}) + seeds = self.MODE_SEEDS_MAP.get(i, self.MODE_SEEDS_DEFAULT)[1] + except (KeyError, IndexError): + continue - def build_stats_map(self, view_obj, name_map): + for _, ip_bits, _ in self.iter_over_get_lists(ep, 'stack', 'field'): + self.set_random_ip_multi_attributes(ip_bits, version, seeds, l3) + + self.ixnet.commit() + + def _build_stats_map(self, view_obj, name_map): return {data_yardstick: self.ixnet.execute( 'getColumnValues', view_obj, data_ixia) for data_yardstick, data_ixia in name_map.items()} @@ -413,7 +415,24 @@ class IxNextgen(object): """ port_statistics = '::ixNet::OBJ-/statistics/view:"Port Statistics"' flow_statistics = '::ixNet::OBJ-/statistics/view:"Flow Statistics"' - stats = self.build_stats_map(port_statistics, self.PORT_STATS_NAME_MAP) - stats.update(self.build_stats_map(flow_statistics, + stats = self._build_stats_map(port_statistics, + self.PORT_STATS_NAME_MAP) + stats.update(self._build_stats_map(flow_statistics, self.LATENCY_NAME_MAP)) return stats + + # NOTE(ralonsoh): to be updated in next patchset + # pragma: no cover + def ix_start_traffic(self): + tis = self.ixnet.getList('/traffic', 'trafficItem') + for ti in tis: + self.ixnet.execute('generate', [ti]) + self.ixnet.execute('apply', '/traffic') + self.ixnet.execute('start', '/traffic') + + # NOTE(ralonsoh): to be updated in next patchset + # pragma: no cover + def ix_stop_traffic(self): + tis = self.ixnet.getList('/traffic', 'trafficItem') + for _ in tis: + self.ixnet.execute('stop', '/traffic') |