diff options
Diffstat (limited to 'yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py')
-rw-r--r-- | yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py | 375 |
1 files changed, 314 insertions, 61 deletions
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 8274ff9ce..d4f75babb 100644 --- a/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py +++ b/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py @@ -1,4 +1,4 @@ -# Copyright (c) 2016-2017 Intel Corporation +# Copyright (c) 2016-2018 Intel Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -50,6 +50,20 @@ TRAFFIC_STATUS_STOPPED = 'stopped' SUPPORTED_PROTO = [PROTO_UDP] +class Vlan(object): + def __init__(self, + vlan_id, vlan_id_step=None, vlan_id_direction='increment', + prio=None, prio_step=None, prio_direction='increment', + tp_id=None): + self.vlan_id = vlan_id + self.vlan_id_step = vlan_id_step + self.vlan_id_direction = vlan_id_direction + self.prio = prio + self.prio_step = prio_step + self.prio_direction = prio_direction + self.tp_id = tp_id + + # NOTE(ralonsoh): this pragma will be removed in the last patch of this series class IxNextgen(object): # pragma: no cover @@ -107,6 +121,11 @@ class IxNextgen(object): # pragma: no cover return self._ixnet raise exceptions.IxNetworkClientNotConnected() + def get_vports(self): + """Return the list of assigned ports (vport objects)""" + vports = self.ixnet.getList(self.ixnet.getRoot(), 'vport') + return vports + def _get_config_element_by_flow_group_name(self, flow_group_name): """Get a config element using the flow group name @@ -225,15 +244,20 @@ class IxNextgen(object): # pragma: no cover zip(self._cfg['cards'], self._cfg['ports'])] log.info('Create and assign vports: %s', ports) - for port in ports: - vport = self.ixnet.add(self.ixnet.getRoot(), 'vport') - self.ixnet.commit() - self.ixnet.execute('assignPorts', [port], [], [vport], True) + + vports = [] + for _ in ports: + vports.append(self.ixnet.add(self.ixnet.getRoot(), 'vport')) self.ixnet.commit() + + self.ixnet.execute('assignPorts', ports, [], vports, True) + self.ixnet.commit() + + for vport in vports: if self.ixnet.getAttribute(vport, '-state') != 'up': log.warning('Port %s is down', vport) - def _create_traffic_item(self): + def _create_traffic_item(self, traffic_type='raw'): """Create the traffic item to hold the flow groups The traffic item tracking by "Traffic Item" is enabled to retrieve the @@ -243,7 +267,7 @@ class IxNextgen(object): # pragma: no cover traffic_item = self.ixnet.add(self.ixnet.getRoot() + '/traffic', 'trafficItem') self.ixnet.setMultiAttribute(traffic_item, '-name', 'RFC2544', - '-trafficType', 'raw') + '-trafficType', traffic_type) self.ixnet.commit() traffic_item_id = self.ixnet.remapIds(traffic_item)[0] @@ -251,27 +275,25 @@ class IxNextgen(object): # pragma: no cover '-trackBy', 'trafficGroupId0') self.ixnet.commit() - def _create_flow_groups(self): - """Create the flow groups between the assigned ports""" + def _create_flow_groups(self, uplink, downlink): + """Create the flow groups between the endpoints""" traffic_item_id = self.ixnet.getList(self.ixnet.getRoot() + 'traffic', 'trafficItem')[0] log.info('Create the flow groups') - 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): + for up, down in zip(uplink, downlink): 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, '-name', str(index + 1), - '-sources', [up + '/protocols'], - '-destinations', [down + '/protocols']) + '-sources', [up], + '-destinations', [down]) self.ixnet.setMultiAttribute( endpoint_set_2, '-name', str(index + 2), - '-sources', [down + '/protocols'], - '-destinations', [up + '/protocols']) + '-sources', [down], + '-destinations', [up]) self.ixnet.commit() index += 2 @@ -281,7 +303,7 @@ class IxNextgen(object): # pragma: no cover '/traffic/protocolTemplate:"{}"'.format(protocol_name)) self.ixnet.execute('append', previous_element, protocol) - def _setup_config_elements(self): + def _setup_config_elements(self, add_default_proto=True): """Setup the config elements The traffic item is configured to allow individual configurations per @@ -303,12 +325,13 @@ class IxNextgen(object): # pragma: no cover self.ixnet.setAttribute(config_element + '/frameRateDistribution', '-streamDistribution', 'splitRateEvenly') self.ixnet.commit() - self._append_procotol_to_stack( - PROTO_UDP, config_element + '/stack:"ethernet-1"') - self._append_procotol_to_stack( - PROTO_IPV4, config_element + '/stack:"ethernet-1"') + if add_default_proto: + self._append_procotol_to_stack( + PROTO_UDP, config_element + '/stack:"ethernet-1"') + self._append_procotol_to_stack( + PROTO_IPV4, config_element + '/stack:"ethernet-1"') - def create_traffic_model(self): + def create_traffic_model(self, uplink_ports, downlink_ports): """Create a traffic item and the needed flow groups Each flow group inside the traffic item (only one is present) @@ -319,10 +342,27 @@ class IxNextgen(object): # pragma: no cover FlowGroup3: port3 -> port4 FlowGroup4: port3 <- port4 """ - self._create_traffic_item() - self._create_flow_groups() + self._create_traffic_item('raw') + uplink_endpoints = [port + '/protocols' for port in uplink_ports] + downlink_endpoints = [port + '/protocols' for port in downlink_ports] + self._create_flow_groups(uplink_endpoints, downlink_endpoints) self._setup_config_elements() + def create_ipv4_traffic_model(self, uplink_topologies, downlink_topologies): + """Create a traffic item and the needed flow groups + + Each flow group inside the traffic item (only one is present) + represents the traffic between two topologies: + (uplink) (downlink) + FlowGroup1: uplink1 -> downlink1 + FlowGroup2: uplink1 <- downlink1 + FlowGroup3: uplink2 -> downlink2 + FlowGroup4: uplink2 <- downlink2 + """ + self._create_traffic_item('ipv4') + self._create_flow_groups(uplink_topologies, downlink_topologies) + self._setup_config_elements(False) + def _update_frame_mac(self, ethernet_descriptor, field, mac_address): """Set the MAC address in a config element stack Ethernet field @@ -366,16 +406,15 @@ class IxNextgen(object): # pragma: no cover raise exceptions.IxNetworkFlowNotPresent(flow_group=fg_id) type = traffic_param.get('traffic_type', 'fixedDuration') - 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')) - dstmac = str(traffic_param.get('dstmac', '00:00:00:00:00:02')) + traffic_param['outer_l2'].get('framesize', {})) + srcmac = str(traffic_param['outer_l2'].get('srcmac', '00:00:00:00:00:01')) + dstmac = str(traffic_param['outer_l2'].get('dstmac', '00:00:00:00:00:02')) - if traffic_param['outer_l2']['QinQ']: + if traffic_param['outer_l2'].get('QinQ'): s_vlan = traffic_param['outer_l2']['QinQ']['S-VLAN'] c_vlan = traffic_param['outer_l2']['QinQ']['C-VLAN'] @@ -400,21 +439,27 @@ class IxNextgen(object): # pragma: no cover self.ixnet.setMultiAttribute( config_element + '/transmissionControl', '-type', type, '-duration', duration) + self.ixnet.setMultiAttribute( config_element + '/frameRate', - '-rate', rate, '-type', rate_unit) - self.ixnet.setMultiAttribute( - config_element + '/frameSize', - '-type', 'weightedPairs', - '-weightedRangePairs', weighted_range_pairs) + '-rate', traffic_param['rate'], '-type', rate_unit) + + if len(weighted_range_pairs): + self.ixnet.setMultiAttribute( + config_element + '/frameSize', + '-type', 'weightedPairs', + '-weightedRangePairs', weighted_range_pairs) + self.ixnet.commit() - self._update_frame_mac( - self._get_stack_item(fg_id, PROTO_ETHERNET)[0], - 'destinationAddress', dstmac) - self._update_frame_mac( - self._get_stack_item(fg_id, PROTO_ETHERNET)[0], - 'sourceAddress', srcmac) + if dstmac: + self._update_frame_mac( + self._get_stack_item(fg_id, PROTO_ETHERNET)[0], + 'destinationAddress', dstmac) + if srcmac: + self._update_frame_mac( + self._get_stack_item(fg_id, PROTO_ETHERNET)[0], + 'sourceAddress', srcmac) def _update_vlan_tag(self, fg_id, params, vlan=0): field_to_param_map = { @@ -474,19 +519,24 @@ class IxNextgen(object): # pragma: no cover if not self._get_config_element_by_flow_group_name(fg_id): raise exceptions.IxNetworkFlowNotPresent(flow_group=fg_id) - count = traffic_param['outer_l3']['count'] - srcip = str(traffic_param['outer_l3']['srcip']) - dstip = str(traffic_param['outer_l3']['dstip']) - seed = traffic_param['outer_l3']['seed'] - srcmask = traffic_param['outer_l3']['srcmask'] or IP_VERSION_4_MASK - dstmask = traffic_param['outer_l3']['dstmask'] or IP_VERSION_4_MASK - - self._update_ipv4_address( - self._get_stack_item(fg_id, PROTO_IPV4)[0], - 'srcIp', srcip, seed, srcmask, count) - self._update_ipv4_address( - self._get_stack_item(fg_id, PROTO_IPV4)[0], - 'dstIp', dstip, seed, dstmask, count) + if traffic_param['outer_l3']: + count = traffic_param['outer_l3']['count'] + srcip = traffic_param['outer_l3']['srcip'] + dstip = traffic_param['outer_l3']['dstip'] + srcseed = traffic_param['outer_l3']['srcseed'] + dstseed = traffic_param['outer_l3']['dstseed'] + srcmask = traffic_param['outer_l3']['srcmask'] \ + or IP_VERSION_4_MASK + dstmask = traffic_param['outer_l3']['dstmask'] \ + or IP_VERSION_4_MASK + if srcip: + self._update_ipv4_address( + self._get_stack_item(fg_id, PROTO_IPV4)[0], + 'srcIp', str(srcip), srcseed, srcmask, count) + if dstip: + self._update_ipv4_address( + self._get_stack_item(fg_id, PROTO_IPV4)[0], + 'dstIp', str(dstip), dstseed, dstmask, count) def update_l4(self, traffic): """Update the L4 headers @@ -500,7 +550,10 @@ class IxNextgen(object): # pragma: no cover if not self._get_config_element_by_flow_group_name(fg_id): raise exceptions.IxNetworkFlowNotPresent(flow_group=fg_id) - proto = traffic_param['outer_l3']['proto'] + proto = traffic_param['outer_l3'].get('proto') + if not (proto and traffic_param['outer_l4']): + continue + if proto not in SUPPORTED_PROTO: raise exceptions.IXIAUnsupportedProtocol(protocol=proto) @@ -513,12 +566,15 @@ class IxNextgen(object): # pragma: no cover dstport = traffic_param['outer_l4']['dstport'] dstmask = traffic_param['outer_l4']['dstportmask'] - if proto in SUPPORTED_PROTO: - self._update_udp_port(self._get_stack_item(fg_id, proto)[0], - 'srcPort', srcport, seed, srcmask, count) - - self._update_udp_port(self._get_stack_item(fg_id, proto)[0], - 'dstPort', dstport, seed, dstmask, count) + if proto == PROTO_UDP: + if srcport: + self._update_udp_port( + self._get_stack_item(fg_id, proto)[0], + 'srcPort', srcport, seed, srcmask, count) + if dstport: + self._update_udp_port( + self._get_stack_item(fg_id, proto)[0], + 'dstPort', dstport, seed, dstmask, count) def _update_udp_port(self, descriptor, field, value, seed=1, mask=0, count=1): @@ -569,6 +625,12 @@ class IxNextgen(object): # pragma: no cover self.LATENCY_NAME_MAP)) return stats + def start_protocols(self): + self.ixnet.execute('startAllProtocols') + + def stop_protocols(self): + self.ixnet.execute('stopAllProtocols') + def start_traffic(self): """Start the traffic injection in the traffic item @@ -586,3 +648,194 @@ class IxNextgen(object): # pragma: no cover self.ixnet.execute('start', '/traffic') # pylint: disable=unnecessary-lambda utils.wait_until_true(lambda: self.is_traffic_running()) + + def add_topology(self, name, vports): + log.debug("add_topology: name='%s' ports='%s'", name, vports) + obj = self.ixnet.add(self.ixnet.getRoot(), 'topology') + self.ixnet.setMultiAttribute(obj, '-name', name, '-vports', vports) + self.ixnet.commit() + return obj + + def add_device_group(self, topology, name, multiplier): + log.debug("add_device_group: tpl='%s', name='%s', multiplier='%s'", + topology, name, multiplier) + + obj = self.ixnet.add(topology, 'deviceGroup') + self.ixnet.setMultiAttribute(obj, '-name', name, '-multiplier', + multiplier) + self.ixnet.commit() + return obj + + def add_ethernet(self, dev_group, name): + log.debug( + "add_ethernet: device_group='%s' name='%s'", dev_group, name) + obj = self.ixnet.add(dev_group, 'ethernet') + self.ixnet.setMultiAttribute(obj, '-name', name) + self.ixnet.commit() + return obj + + def _create_vlans(self, ethernet, count): + self.ixnet.setMultiAttribute(ethernet, '-useVlans', 'true') + self.ixnet.setMultiAttribute(ethernet, '-vlanCount', count) + self.ixnet.commit() + + def _configure_vlans(self, ethernet, vlans): + vlans_obj = self.ixnet.getList(ethernet, 'vlan') + for i, vlan_obj in enumerate(vlans_obj): + if vlans[i].vlan_id_step is not None: + vlan_id_obj = self.ixnet.getAttribute(vlan_obj, '-vlanId') + self.ixnet.setMultiAttribute(vlan_id_obj, '-clearOverlays', + 'true', '-pattern', 'counter') + vlan_id_counter = self.ixnet.add(vlan_id_obj, 'counter') + self.ixnet.setMultiAttribute(vlan_id_counter, '-start', + vlans[i].vlan_id, '-step', + vlans[i].vlan_id_step, + '-direction', + vlans[i].vlan_id_direction) + else: + vlan_id_obj = self.ixnet.getAttribute(vlan_obj, '-vlanId') + self.ixnet.setMultiAttribute(vlan_id_obj + '/singleValue', + '-value', vlans[i].vlan_id) + + if vlans[i].prio_step is not None: + prio_obj = self.ixnet.getAttribute(vlan_obj, '-priority') + self.ixnet.setMultiAttribute(prio_obj, '-clearOverlays', 'true', + '-pattern', 'counter') + prio_counter = self.ixnet.add(prio_obj, 'counter') + self.ixnet.setMultiAttribute(prio_counter, + '-start', vlans[i].prio, + '-step', vlans[i].prio_step, + '-direction', vlans[i].prio_direction) + elif vlans[i].prio is not None: + prio_obj = self.ixnet.getAttribute(vlan_obj, '-priority') + self.ixnet.setMultiAttribute(prio_obj + '/singleValue', + '-value', vlans[i].prio) + + if vlans[i].tp_id is not None: + tp_id_obj = self.ixnet.getAttribute(vlan_obj, '-tpid') + self.ixnet.setMultiAttribute(tp_id_obj + '/singleValue', + '-value', vlans[i].tp_id) + + self.ixnet.commit() + + def add_vlans(self, ethernet, vlans): + log.debug("add_vlans: ethernet='%s'", ethernet) + + if vlans is None or len(vlans) == 0: + raise RuntimeError( + "Invalid 'vlans' argument. Expected list of Vlan instances.") + + self._create_vlans(ethernet, len(vlans)) + self._configure_vlans(ethernet, vlans) + + def add_ipv4(self, ethernet, name='', + addr=None, addr_step=None, addr_direction='increment', + prefix=None, prefix_step=None, prefix_direction='increment', + gateway=None, gw_step=None, gw_direction='increment'): + log.debug("add_ipv4: ethernet='%s' name='%s'", ethernet, name) + obj = self.ixnet.add(ethernet, 'ipv4') + if name != '': + self.ixnet.setAttribute(obj, '-name', name) + self.ixnet.commit() + + if addr_step is not None: + # handle counter pattern + _address = self.ixnet.getAttribute(obj, '-address') + self.ixnet.setMultiAttribute(_address, '-clearOverlays', 'true', + '-pattern', 'counter') + + address_counter = self.ixnet.add(_address, 'counter') + self.ixnet.setMultiAttribute(address_counter, + '-start', addr, + '-step', addr_step, + '-direction', addr_direction) + elif addr is not None: + # handle single value + _address = self.ixnet.getAttribute(obj, '-address') + self.ixnet.setMultiAttribute(_address + '/singleValue', '-value', + addr) + + if prefix_step is not None: + # handle counter pattern + _prefix = self.ixnet.getAttribute(obj, '-prefix') + self.ixnet.setMultiAttribute(_prefix, '-clearOverlays', 'true', + '-pattern', 'counter') + prefix_counter = self.ixnet.add(_prefix, 'counter') + self.ixnet.setMultiAttribute(prefix_counter, + '-start', prefix, + '-step', prefix_step, + '-direction', prefix_direction) + elif prefix is not None: + # handle single value + _prefix = self.ixnet.getAttribute(obj, '-prefix') + self.ixnet.setMultiAttribute(_prefix + '/singleValue', '-value', + prefix) + + if gw_step is not None: + # handle counter pattern + _gateway = self.ixnet.getAttribute(obj, '-gatewayIp') + self.ixnet.setMultiAttribute(_gateway, '-clearOverlays', 'true', + '-pattern', 'counter') + + gateway_counter = self.ixnet.add(_gateway, 'counter') + self.ixnet.setMultiAttribute(gateway_counter, + '-start', gateway, + '-step', gw_step, + '-direction', gw_direction) + elif gateway is not None: + # handle single value + _gateway = self.ixnet.getAttribute(obj, '-gatewayIp') + self.ixnet.setMultiAttribute(_gateway + '/singleValue', '-value', + gateway) + + self.ixnet.commit() + return obj + + def add_pppox_client(self, xproto, auth, user, pwd): + log.debug( + "add_pppox_client: xproto='%s', auth='%s', user='%s', pwd='%s'", + xproto, auth, user, pwd) + obj = self.ixnet.add(xproto, 'pppoxclient') + self.ixnet.commit() + + if auth == 'pap': + auth_type = self.ixnet.getAttribute(obj, '-authType') + self.ixnet.setMultiAttribute(auth_type + '/singleValue', '-value', + auth) + pap_user = self.ixnet.getAttribute(obj, '-papUser') + self.ixnet.setMultiAttribute(pap_user + '/singleValue', '-value', + user) + pap_pwd = self.ixnet.getAttribute(obj, '-papPassword') + self.ixnet.setMultiAttribute(pap_pwd + '/singleValue', '-value', + pwd) + else: + raise NotImplementedError() + + self.ixnet.commit() + return obj + + def add_bgp(self, ipv4, dut_ip, local_as, bgp_type=None): + """Add BGP protocol""" + log.debug("add_bgp: ipv4='%s', dut_ip='%s', local_as='%s'", ipv4, + dut_ip, local_as) + obj = self.ixnet.add(ipv4, 'bgpIpv4Peer') + self.ixnet.commit() + + # Set DUT IP address + dut_ip_addr = self.ixnet.getAttribute(obj, '-dutIp') + self.ixnet.setAttribute(dut_ip_addr + '/singleValue', + '-value', dut_ip) + + # Set local AS number + local_as_number = self.ixnet.getAttribute(obj, '-localAs2Bytes') + self.ixnet.setAttribute(local_as_number + '/singleValue', + '-value', local_as) + + if bgp_type: + # Set BGP type. If not specified, default value is using. + # Default type is "internal" + bgp_type_field = self.ixnet.getAttribute(obj, '-type') + self.ixnet.setAttribute(bgp_type_field + '/singleValue', + '-value', bgp_type) + self.ixnet.commit() + return obj |