diff options
author | 2016-02-23 15:32:19 +0200 | |
---|---|---|
committer | 2016-02-23 15:32:19 +0200 | |
commit | 36cc1ecef32dcee3640e6ddf96422c07d89777b3 (patch) | |
tree | 6a9eadb662ad0f98395886077fe32943512fd040 /scripts/automation/trex_control_plane/stl/trex_stl_lib | |
parent | 68ebd739646a27f1bb92ce8eacb5bb76f6399580 (diff) | |
parent | 81059eb5df274efe48ad3914039ddb657c3285ab (diff) |
Merge ipv4 checksum issue
Diffstat (limited to 'scripts/automation/trex_control_plane/stl/trex_stl_lib')
6 files changed, 356 insertions, 209 deletions
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py index 5311884d..60654f0a 100755 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py @@ -22,6 +22,7 @@ cleanup_session_kwargs = { # traffic_config() traffic_config_kwargs = { 'mode': None, # ( create | modify | remove | reset ) + 'split_by_cores': 'split', # ( split | duplicate | single ) TRex extention: split = split traffic by cores, duplicate = duplicate traffic for all cores, single = run only with sinle core (not implemented yet) 'port_handle': None, 'port_handle2': None, # stream builder parameters @@ -32,6 +33,7 @@ traffic_config_kwargs = { 'stream_id': None, 'name': None, 'bidirectional': 0, + 'direction': 0, # ( 0 | 1 ) TRex extention: 1 = exchange sources and destinations 'pkts_per_burst': 1, 'burst_loop_count': 1, 'inter_burst_gap': 12, @@ -327,7 +329,7 @@ class CTRexHltApi(object): # connection successfully created with server, try acquiring ports of TRex try: - port_list = self.parse_port_list(kwargs['port_list']) + port_list = self._parse_port_list(kwargs['port_list']) self.trex_client.acquire(ports = port_list, force = kwargs['break_locks']) except Exception as e: self.trex_client = None @@ -358,7 +360,7 @@ class CTRexHltApi(object): if port_list == 'all': port_list = self.trex_client.get_acquired_ports() else: - port_list = self.parse_port_list(port_list) + port_list = self._parse_port_list(port_list) except Exception as e: return HLT_ERR('Unable to determine which ports to release: %s' % e if isinstance(e, STLError) else traceback.format_exc()) try: @@ -412,10 +414,7 @@ class CTRexHltApi(object): else: stream_id = stream_id[0] - port_handle = kwargs['port_handle'] - if type(port_handle) is not list: - port_handle = [port_handle] - + port_handle = port_list = self._parse_port_list(kwargs['port_handle']) ALLOWED_MODES = ['create', 'modify', 'remove', 'enable', 'disable', 'reset'] if mode not in ALLOWED_MODES: return HLT_ERR('Mode must be one of the following values: %s' % ALLOWED_MODES) @@ -455,13 +454,12 @@ class CTRexHltApi(object): # if stream_id not in self._streams_history: # return HLT_ERR('This stream_id (%s) was not used before, please create new.' % stream_id) # self._streams_history[stream_id].update(kwargs) # <- the modification - if mode == 'modify': # we remove stream and create new one with same stream_id stream_id = kwargs.get('stream_id') if stream_id is None: return HLT_ERR('Please specify stream_id to modify.') - + if len(port_handle) > 1: for port in port_handle: user_kwargs[port_handle] = port @@ -502,12 +500,10 @@ class CTRexHltApi(object): if res1['status'] == 0: raise STLError('Could not create bidirectional stream 1: %s' % res1['log']) streams_per_port.add_streams_from_res(res1) + kwargs['direction'] = 1 - kwargs['direction'] # not + correct_direction(user_kwargs, kwargs) user_kwargs['mac_src'] = kwargs['mac_src2'] user_kwargs['mac_dst'] = kwargs['mac_dst2'] - user_kwargs['ip_src_addr'] = kwargs['ip_dst_addr'] - user_kwargs['ip_dst_addr'] = kwargs['ip_src_addr'] - user_kwargs['ipv6_src_addr'] = kwargs['ipv6_dst_addr'] - user_kwargs['ipv6_dst_addr'] = kwargs['ipv6_src_addr'] if save_to_yaml and type(save_to_yaml) is str: user_kwargs['save_to_yaml'] = save_to_yaml.replace('.yaml', '_bi2.yaml') user_kwargs['port_handle'] = port_handle2 @@ -657,30 +653,15 @@ class CTRexHltApi(object): # Private functions # ########################### - # obsolete @staticmethod - def process_response(port_list, response): - log = response.data() if response.good() else response.err() - if isinstance(port_list, list): - log = CTRexHltApi.join_batch_response(log) - return response.good(), log - - @staticmethod - def parse_port_list(port_list): - if isinstance(port_list, str): - return [int(port) - for port in port_list.split()] - elif isinstance(port_list, list): - return [int(port) - for port in port_list] - else: - return port_list - - @staticmethod - def join_batch_response(responses): - if type(responses) is list(): - return '\n'. join([str(response) for response in responses]) - return responses + def _parse_port_list(port_list): + if type(port_list) is str: + return [int(port) for port in port_list.strip().split()] + elif type(port_list) is list: + return [int(port) for port in port_list] + elif type(port) in (int, long): + return [int(port_list)] + raise STLError('port_list should be string with ports, list, or single number') def STLHltStream(**user_kwargs): kwargs = merge_kwargs(traffic_config_kwargs, user_kwargs) @@ -745,7 +726,6 @@ def STLHltStream(**user_kwargs): #self_start = True, mode = transmit_mode_class, #rx_stats = rx_stats, - #next_stream_id = -1, stream_id = kwargs.get('stream_id'), name = kwargs.get('name'), ) @@ -761,6 +741,7 @@ def STLHltStream(**user_kwargs): def generate_packet(**user_kwargs): correct_macs(user_kwargs) kwargs = merge_kwargs(traffic_config_kwargs, user_kwargs) + correct_direction(kwargs, kwargs) vm_cmds = [] fix_ipv4_checksum = False @@ -772,42 +753,70 @@ def generate_packet(**user_kwargs): # XShortEnumField("type", 0x9000, ETHER_TYPES) ] l2_layer = Ether(src = kwargs['mac_src'], dst = kwargs['mac_dst']) - # TODO: add Eth VM once variable masking will be done + # Eth VM + # WIP!!! Need 8 bytes mask and vars + if kwargs['mac_src_mode'] != 'fixed': + mac_src_count = kwargs['mac_src_count'] - 1 + if mac_src_count < 0: + raise STLError('mac_src_count has to be at least 1') + if mac_src_count > 0: + mac_src = mac_str_to_num(mac2str(kwargs['mac_src'])) + if kwargs['mac_src_mode'] == 'increment': + vm_cmds.append(CTRexVmDescFlowVar(name = 'mac_src', size = 4, op = 'inc', step = kwargs['mac_src_step'], + min_value = mac_src, + max_value = mac_src + mac_src_count * kwargs['mac_src_step'])) + elif kwargs['mac_src_mode'] == 'decrement': + vm_cmds.append(CTRexVmDescFlowVar(name = 'mac_src', size = 4, op = 'dec', step = kwargs['mac_src_step'], + min_value = mac_src - mac_src_count * kwargs['mac_src_step'], + max_value = mac_src)) + elif kwargs['mac_src_mode'] == 'random': + vm_cmds.append(CTRexVmDescFlowVar(name = 'mac_src', size = 4, op = 'random', min_value = 0, max_value = 0xffffffffffffffff)) + else: + raise STLError('mac_src_mode %s is not supported' % kwargs['mac_src_mode']) + vm_cmds.append(STLVmWrMaskFlowVar(fv_name = 'mac_src', pkt_offset = 'Ethernet.src', pkt_cast_size = 4, mask = 0xffffffff)) + if kwargs['l2_encap'] == 'ethernet_ii_vlan' or (kwargs['l2_encap'] == 'ethernet_ii' and vlan_in_args(user_kwargs)): #fields_desc = [ BitField("prio", 0, 3), # BitField("id", 0, 1), # BitField("vlan", 1, 12), # XShortEnumField("type", 0x0000, ETHER_TYPES) ] for i, vlan_kwargs in enumerate(split_vlan_args(kwargs)): + vlan_id = int(vlan_kwargs['vlan_id']) dot1q_kwargs = {'prio': vlan_kwargs['vlan_user_priority'], - 'vlan': vlan_kwargs['vlan_id'], + 'vlan': vlan_id, 'id': vlan_kwargs['vlan_cfi']} - if vlan_kwargs['vlan_protocol_tag_id'] is not None: - dot1q_kwargs['type'] = vlan_kwargs['vlan_protocol_tag_id'] + vlan_protocol_tag_id = vlan_kwargs['vlan_protocol_tag_id'] + if vlan_protocol_tag_id is not None: + if type(vlan_protocol_tag_id) is str: + vlan_protocol_tag_id = int(vlan_protocol_tag_id, 16) + dot1q_kwargs['type'] = vlan_protocol_tag_id l2_layer /= Dot1Q(**dot1q_kwargs) + # vlan VM - if vlan_kwargs['vlan_id_mode'] != 'fixed': - if vlan_kwargs['vlan_id_count'] < 1: + vlan_id_mode = vlan_kwargs['vlan_id_mode'] + if vlan_id_mode != 'fixed': + vlan_id_count = int(vlan_kwargs['vlan_id_count']) - 1 + if vlan_id_count < 0: raise STLError('vlan_id_count has to be at least 1') - if kwargs['vlan_id_count'] > 1: + if vlan_id_count > 0 or vlan_id_mode == 'random': var_name = 'vlan_id%s' % i - raise STLError('vlan_id VM not supported yet, waiting for bitmask from stateless') - if kwargs['vlan_id_mode'] == 'increment': - vm_cmds.append(CTRexVmDescFlowVar(name = var_name, size = 4, op = 'inc', step = vlan_kwargs['vlan_id_step'], - min_value = kwargs['vlan_id'], - max_value = kwargs['vlan_id'] + kwargs['vlan_id_count'] - 1)) - elif kwargs['vlan_id_mode'] == 'decrement': - vm_cmds.append(CTRexVmDescFlowVar(name = var_name, size = 4, op = 'dec', step = vlan_kwargs['vlan_id_step'], - min_value = kwargs['vlan_id'] - kwargs['vlan_id_count'] + 1, - max_value = kwargs['vlan_id'])) - elif kwargs['vlan_id_mode'] == 'random': - vm_cmds.append(CTRexVmDescFlowVar(name = var_name, size = 4, op = 'random', - min_value = kwargs['vlan_id'], - max_value = kwargs['vlan_id'] + kwargs['vlan_id_count'] - 1)) + step = int(vlan_kwargs['vlan_id_step']) + if vlan_id_mode == 'increment': + vm_cmds.append(CTRexVmDescFlowVar(name = var_name, size = 2, op = 'inc', step = step, + min_value = vlan_id, + max_value = vlan_id + vlan_id_count * step)) + elif vlan_id_mode == 'decrement': + vm_cmds.append(CTRexVmDescFlowVar(name = var_name, size = 2, op = 'dec', step = step, + min_value = vlan_id - vlan_id_count * step, + max_value = vlan_id)) + elif vlan_id_mode == 'random': + vm_cmds.append(CTRexVmDescFlowVar(name = var_name, size = 2, op = 'random', min_value = 0, max_value = 0xffff)) else: - raise STLError('vlan_id_mode %s is not supported' % kwargs['vlan_id_mode']) - vm_cmds.append(CTRexVmDescWrFlowVar(fv_name = var_name, pkt_offset = 'Dot1Q:%s.vlan' % i)) + raise STLError('vlan_id_mode %s is not supported' % vlan_id_mode) + vm_cmds.append(STLVmWrMaskFlowVar(fv_name = var_name, pkt_offset = '802|1Q:%s.vlan' % i, + pkt_cast_size = 2, mask = 0xfff)) + else: raise NotImplementedError("l2_encap does not support the desired encapsulation '%s'" % kwargs['l2_encap']) base_pkt = l2_layer @@ -830,7 +839,7 @@ def generate_packet(**user_kwargs): ip_tos = get_TOS(user_kwargs, kwargs) if ip_tos < 0 or ip_tos > 255: raise STLError('TOS %s is not in range 0-255' % ip_tos) - l3_layer = IP(tos = get_TOS(user_kwargs, kwargs), + l3_layer = IP(tos = ip_tos, len = kwargs['l3_length'], id = kwargs['ip_id'], frag = kwargs['ip_fragment_offset'], @@ -841,45 +850,53 @@ def generate_packet(**user_kwargs): ) # IPv4 VM if kwargs['ip_src_mode'] != 'fixed': - if kwargs['ip_src_count'] < 1: + ip_src_count = kwargs['ip_src_count'] - 1 + if ip_src_count < 0: raise STLError('ip_src_count has to be at least 1') - if kwargs['ip_src_count'] > 1: + if ip_src_count > 0: fix_ipv4_checksum = True - ip_src_addr_num = ipv4_str_to_num(is_valid_ipv4(kwargs['ip_src_addr'])) + ip_src_addr = kwargs['ip_src_addr'] + if type(ip_src_addr) is str: + ip_src_addr = ipv4_str_to_num(is_valid_ipv4(ip_src_addr)) + ip_src_step = kwargs['ip_src_step'] + if type(ip_src_step) is str: + ip_src_step = ipv4_str_to_num(is_valid_ipv4(ip_src_step)) if kwargs['ip_src_mode'] == 'increment': - vm_cmds.append(CTRexVmDescFlowVar(name = 'ip_src', size = 4, op = 'inc', step = kwargs['ip_src_step'], - min_value = ip_src_addr_num, - max_value = ip_src_addr_num + kwargs['ip_src_count'] - 1)) + vm_cmds.append(CTRexVmDescFlowVar(name = 'ip_src', size = 4, op = 'inc', step = ip_src_step, + min_value = ip_src_addr, + max_value = ip_src_addr + ip_src_count * ip_src_step)) elif kwargs['ip_src_mode'] == 'decrement': - vm_cmds.append(CTRexVmDescFlowVar(name = 'ip_src', size = 4, op = 'dec', step = kwargs['ip_src_step'], - min_value = ip_src_addr_num - kwargs['ip_src_count'] + 1, - max_value = ip_src_addr_num)) + vm_cmds.append(CTRexVmDescFlowVar(name = 'ip_src', size = 4, op = 'dec', step = ip_src_step, + min_value = ip_src_addr - ip_src_count * ip_src_step, + max_value = ip_src_addr)) elif kwargs['ip_src_mode'] == 'random': - vm_cmds.append(CTRexVmDescFlowVar(name = 'ip_src', size = 4, op = 'random', - min_value = ip_src_addr_num, - max_value = ip_src_addr_num + kwargs['ip_src_count'] - 1)) + vm_cmds.append(CTRexVmDescFlowVar(name = 'ip_src', size = 4, op = 'random', min_value = 0, max_value = 0xffffffff)) else: raise STLError('ip_src_mode %s is not supported' % kwargs['ip_src_mode']) vm_cmds.append(CTRexVmDescWrFlowVar(fv_name='ip_src', pkt_offset = 'IP.src')) if kwargs['ip_dst_mode'] != 'fixed': - if kwargs['ip_dst_count'] < 1: + ip_dst_count = kwargs['ip_dst_count'] - 1 + if ip_dst_count < 0: raise STLError('ip_dst_count has to be at least 1') - if kwargs['ip_dst_count'] > 1: + if ip_dst_count > 0: fix_ipv4_checksum = True - ip_dst_addr_num = ipv4_str_to_num(is_valid_ipv4(kwargs['ip_dst_addr'])) + ip_dst_addr = kwargs['ip_dst_addr'] + if type(ip_dst_addr) is str: + ip_dst_addr = ipv4_str_to_num(is_valid_ipv4(ip_dst_addr)) + ip_dst_step = kwargs['ip_dst_step'] + if type(ip_dst_step) is str: + ip_dst_step = ipv4_str_to_num(is_valid_ipv4(ip_dst_step)) if kwargs['ip_dst_mode'] == 'increment': - vm_cmds.append(CTRexVmDescFlowVar(name = 'ip_dst', size = 4, op = 'inc', step = kwargs['ip_dst_step'], - min_value = ip_dst_addr_num, - max_value = ip_dst_addr_num + kwargs['ip_dst_count'] - 1)) + vm_cmds.append(CTRexVmDescFlowVar(name = 'ip_dst', size = 4, op = 'inc', step = ip_dst_step, + min_value = ip_dst_addr, + max_value = ip_dst_addr + ip_dst_count * ip_dst_step)) elif kwargs['ip_dst_mode'] == 'decrement': - vm_cmds.append(CTRexVmDescFlowVar(name = 'ip_dst', size = 4, op = 'dec', step = kwargs['ip_dst_step'], - min_value = ip_dst_addr_num - kwargs['ip_dst_count'] + 1, - max_value = ip_dst_addr_num)) + vm_cmds.append(CTRexVmDescFlowVar(name = 'ip_dst', size = 4, op = 'dec', step = ip_dst_step, + min_value = ip_dst_addr - ip_dst_count * ip_dst_step, + max_value = ip_dst_addr)) elif kwargs['ip_dst_mode'] == 'random': - vm_cmds.append(CTRexVmDescFlowVar(name = 'ip_dst', size = 4, op = 'random', - min_value = ip_dst_addr_num, - max_value = ip_dst_addr_num + kwargs['ip_dst_count'] - 1)) + vm_cmds.append(CTRexVmDescFlowVar(name = 'ip_dst', size = 4, op = 'random', min_value = 0, max_value = 0xffffffff)) else: raise STLError('ip_dst_mode %s is not supported' % kwargs['ip_dst_mode']) vm_cmds.append(CTRexVmDescWrFlowVar(fv_name='ip_dst', pkt_offset = 'IP.dst')) @@ -902,51 +919,50 @@ def generate_packet(**user_kwargs): if kwargs['ipv6_next_header'] is not None: ipv6_kwargs['nh'] = kwargs['ipv6_next_header'] l3_layer = IPv6(**ipv6_kwargs) + # IPv6 VM if kwargs['ipv6_src_mode'] != 'fixed': - if kwargs['ipv6_src_count'] < 1: + ipv6_src_count = kwargs['ipv6_src_count'] - 1 + if ipv6_src_count < 0: raise STLError('ipv6_src_count has to be at least 1') - if kwargs['ipv6_src_count'] > 1: + if ipv6_src_count > 0: ipv6_src_addr_num = ipv4_str_to_num(is_valid_ipv6(kwargs['ipv6_src_addr'])[-4:]) ipv6_src_step = kwargs['ipv6_src_step'] - if type(kwargs['ipv6_src_step']) is str: # convert ipv6 step to number + if type(ipv6_src_step) is str: # convert ipv6 step to number ipv6_src_step = ipv4_str_to_num(is_valid_ipv6(ipv6_src_step)[-4:]) if kwargs['ipv6_src_mode'] == 'increment': vm_cmds.append(CTRexVmDescFlowVar(name = 'ipv6_src', size = 4, op = 'inc', step = ipv6_src_step, min_value = ipv6_src_addr_num, - max_value = ipv6_src_addr_num + kwargs['ipv6_src_count'] - 1)) + max_value = ipv6_src_addr_num + ipv6_src_count * ipv6_src_step)) elif kwargs['ipv6_src_mode'] == 'decrement': vm_cmds.append(CTRexVmDescFlowVar(name = 'ipv6_src', size = 4, op = 'dec', step = ipv6_src_step, - min_value = ipv6_src_addr_num - kwargs['ipv6_src_count'] + 1, + min_value = ipv6_src_addr_num - ipv6_src_count * ipv6_src_step, max_value = ipv6_src_addr_num)) elif kwargs['ipv6_src_mode'] == 'random': - vm_cmds.append(CTRexVmDescFlowVar(name = 'ipv6_src', size = 4, op = 'random', - min_value = ipv6_src_addr_num, - max_value = ipv6_src_addr_num + kwargs['ipv6_src_count'] - 1)) + vm_cmds.append(CTRexVmDescFlowVar(name = 'ipv6_src', size = 4, op = 'random', min_value = 0, max_value = 0xffffffff)) else: raise STLError('ipv6_src_mode %s is not supported' % kwargs['ipv6_src_mode']) vm_cmds.append(CTRexVmDescWrFlowVar(fv_name='ipv6_src', pkt_offset = 'IPv6.src', offset_fixup = 12)) if kwargs['ipv6_dst_mode'] != 'fixed': - if kwargs['ipv6_dst_count'] < 1: + ipv6_dst_count = kwargs['ipv6_dst_count'] - 1 + if ipv6_dst_count < 0: raise STLError('ipv6_dst_count has to be at least 1') - if kwargs['ipv6_dst_count'] > 1: + if ipv6_dst_count > 0: ipv6_dst_addr_num = ipv4_str_to_num(is_valid_ipv6(kwargs['ipv6_dst_addr'])[-4:]) ipv6_dst_step = kwargs['ipv6_dst_step'] - if type(kwargs['ipv6_dst_step']) is str: # convert ipv6 step to number + if type(ipv6_dst_step) is str: # convert ipv6 step to number ipv6_dst_step = ipv4_str_to_num(is_valid_ipv6(ipv6_dst_step)[-4:]) if kwargs['ipv6_dst_mode'] == 'increment': vm_cmds.append(CTRexVmDescFlowVar(name = 'ipv6_dst', size = 4, op = 'inc', step = ipv6_dst_step, min_value = ipv6_dst_addr_num, - max_value = ipv6_dst_addr_num + kwargs['ipv6_dst_count'] - 1)) + max_value = ipv6_dst_addr_num + ipv6_dst_count * ipv6_dst_step)) elif kwargs['ipv6_dst_mode'] == 'decrement': vm_cmds.append(CTRexVmDescFlowVar(name = 'ipv6_dst', size = 4, op = 'dec', step = ipv6_dst_step, - min_value = ipv6_dst_addr_num - kwargs['ipv6_dst_count'] + 1, + min_value = ipv6_dst_addr_num - ipv6_dst_count * ipv6_dst_step, max_value = ipv6_dst_addr_num)) elif kwargs['ipv6_dst_mode'] == 'random': - vm_cmds.append(CTRexVmDescFlowVar(name = 'ipv6_dst', size = 4, op = 'random', - min_value = ipv6_dst_addr_num, - max_value = ipv6_dst_addr_num + kwargs['ipv6_dst_count'] - 1)) + vm_cmds.append(CTRexVmDescFlowVar(name = 'ipv6_dst', size = 4, op = 'random', min_value = 0, max_value = 0xffffffff)) else: raise STLError('ipv6_dst_mode %s is not supported' % kwargs['ipv6_dst_mode']) vm_cmds.append(CTRexVmDescWrFlowVar(fv_name='ipv6_dst', pkt_offset = 'IPv6.dst', offset_fixup = 12)) @@ -986,44 +1002,42 @@ def generate_packet(**user_kwargs): urgptr = kwargs['tcp_urgent_ptr'], ) # TCP VM - if kwargs['tcp_src_port_count'] != 1: - if kwargs['tcp_src_port_count'] < 1: + if kwargs['tcp_src_port_mode'] != 'fixed': + tcp_src_port_count = kwargs['tcp_src_port_count'] - 1 + if tcp_src_port_count < 0: raise STLError('tcp_src_port_count has to be at least 1') - if kwargs['tcp_src_port_count'] > 1: + if tcp_src_port_count > 0: fix_ipv4_checksum = True if kwargs['tcp_src_port_mode'] == 'increment': vm_cmds.append(CTRexVmDescFlowVar(name = 'tcp_src', size = 2, op = 'inc', step = kwargs['tcp_src_port_step'], min_value = kwargs['tcp_src_port'], - max_value = kwargs['tcp_src_port'] + kwargs['tcp_src_port_count'] - 1)) + max_value = kwargs['tcp_src_port'] + tcp_src_port_count * kwargs['tcp_src_port_step'])) elif kwargs['tcp_src_port_mode'] == 'decrement': vm_cmds.append(CTRexVmDescFlowVar(name = 'tcp_src', size = 2, op = 'dec', step = kwargs['tcp_src_port_step'], - min_value = kwargs['tcp_src_port'] - kwargs['tcp_src_port_count'] +1, + min_value = kwargs['tcp_src_port'] - tcp_src_port_count * kwargs['tcp_src_port_step'], max_value = kwargs['tcp_src_port'])) elif kwargs['tcp_src_port_mode'] == 'random': - vm_cmds.append(CTRexVmDescFlowVar(name = 'tcp_src', size = 2, op = 'random', - min_value = kwargs['tcp_src_port'], - max_value = kwargs['tcp_src_port'] + kwargs['tcp_src_port_count'] - 1)) + vm_cmds.append(CTRexVmDescFlowVar(name = 'tcp_src', size = 2, op = 'random', min_value = 0, max_value = 0xffff)) else: raise STLError('tcp_src_port_mode %s is not supported' % kwargs['tcp_src_port_mode']) vm_cmds.append(CTRexVmDescWrFlowVar(fv_name='tcp_src', pkt_offset = 'TCP.sport')) - if kwargs['tcp_dst_port_count'] != 1: - if kwargs['tcp_dst_port_count'] < 1: + if kwargs['tcp_dst_port_mode'] != 'fixed': + tcp_dst_port_count = kwargs['tcp_dst_port_count'] - 1 + if tcp_dst_port_count < 0: raise STLError('tcp_dst_port_count has to be at least 1') - if kwargs['tcp_dst_port_count'] > 1: + if tcp_dst_port_count > 0: fix_ipv4_checksum = True if kwargs['tcp_dst_port_mode'] == 'increment': vm_cmds.append(CTRexVmDescFlowVar(name = 'tcp_dst', size = 2, op = 'inc', step = kwargs['tcp_dst_port_step'], min_value = kwargs['tcp_dst_port'], - max_value = kwargs['tcp_dst_port'] + kwargs['tcp_dst_port_count'] - 1)) + max_value = kwargs['tcp_dst_port'] + tcp_dst_port_count * kwargs['tcp_dst_port_step'])) elif kwargs['tcp_dst_port_mode'] == 'decrement': vm_cmds.append(CTRexVmDescFlowVar(name = 'tcp_dst', size = 2, op = 'dec', step = kwargs['tcp_dst_port_step'], - min_value = kwargs['tcp_dst_port'] - kwargs['tcp_dst_port_count'] +1, + min_value = kwargs['tcp_dst_port'] - tcp_dst_port_count * kwargs['tcp_dst_port_step'], max_value = kwargs['tcp_dst_port'])) elif kwargs['tcp_dst_port_mode'] == 'random': - vm_cmds.append(CTRexVmDescFlowVar(name = 'tcp_dst', size = 2, op = 'random', - min_value = kwargs['tcp_dst_port'], - max_value = kwargs['tcp_dst_port'] + kwargs['tcp_dst_port_count'] - 1)) + vm_cmds.append(CTRexVmDescFlowVar(name = 'tcp_dst', size = 2, op = 'random', min_value = 0, max_value = 0xffff)) else: raise STLError('tcp_dst_port_mode %s is not supported' % kwargs['tcp_dst_port_mode']) vm_cmds.append(CTRexVmDescWrFlowVar(fv_name='tcp_dst', pkt_offset = 'TCP.dport')) @@ -1037,44 +1051,42 @@ def generate_packet(**user_kwargs): dport = kwargs['udp_dst_port'], len = kwargs['udp_length'], chksum = None) # UDP VM - if kwargs['udp_src_port_count'] != 1: - if kwargs['udp_src_port_count'] < 1: + if kwargs['udp_src_port_mode'] != 'fixed': + udp_src_port_count = kwargs['udp_src_port_count'] - 1 + if udp_src_port_count < 0: raise STLError('udp_src_port_count has to be at least 1') - if kwargs['udp_src_port_count'] > 1: + if udp_src_port_count > 0: fix_ipv4_checksum = True if kwargs['udp_src_port_mode'] == 'increment': vm_cmds.append(CTRexVmDescFlowVar(name = 'udp_src', size = 2, op = 'inc', step = kwargs['udp_src_port_step'], min_value = kwargs['udp_src_port'], - max_value = kwargs['udp_src_port'] + kwargs['udp_src_port_count'] - 1)) + max_value = kwargs['udp_src_port'] + udp_src_port_count * kwargs['udp_src_port_step'])) elif kwargs['udp_src_port_mode'] == 'decrement': vm_cmds.append(CTRexVmDescFlowVar(name = 'udp_src', size = 2, op = 'dec', step = kwargs['udp_src_port_step'], - min_value = kwargs['udp_src_port'] - kwargs['udp_src_port_count'] +1, + min_value = kwargs['udp_src_port'] - udp_src_port_count * kwargs['udp_src_port_step'], max_value = kwargs['udp_src_port'])) elif kwargs['udp_src_port_mode'] == 'random': - vm_cmds.append(CTRexVmDescFlowVar(name = 'udp_src', size = 2, op = 'random', - min_value = kwargs['udp_src_port'], - max_value = kwargs['udp_src_port'] + kwargs['udp_src_port_count'] - 1)) + vm_cmds.append(CTRexVmDescFlowVar(name = 'udp_src', size = 2, op = 'random', min_value = 0, max_value = 0xffff)) else: raise STLError('udp_src_port_mode %s is not supported' % kwargs['udp_src_port_mode']) vm_cmds.append(CTRexVmDescWrFlowVar(fv_name='udp_src', pkt_offset = 'UDP.sport')) - if kwargs['udp_dst_port_count'] != 1: - if kwargs['udp_dst_port_count'] < 1: + if kwargs['udp_dst_port_mode'] != 'fixed': + udp_dst_port_count = kwargs['udp_dst_port_count'] - 1 + if udp_dst_port_count < 0: raise STLError('udp_dst_port_count has to be at least 1') - if kwargs['udp_dst_port_count'] > 1: + if udp_dst_port_count > 0: fix_ipv4_checksum = True if kwargs['udp_dst_port_mode'] == 'increment': vm_cmds.append(CTRexVmDescFlowVar(name = 'udp_dst', size = 2, op = 'inc', step = kwargs['udp_dst_port_step'], min_value = kwargs['udp_dst_port'], - max_value = kwargs['udp_dst_port'] + kwargs['udp_dst_port_count'] - 1)) + max_value = kwargs['udp_dst_port'] + udp_dst_port_count * kwargs['udp_dst_port_step'])) elif kwargs['udp_dst_port_mode'] == 'decrement': vm_cmds.append(CTRexVmDescFlowVar(name = 'udp_dst', size = 2, op = 'dec', step = kwargs['udp_dst_port_step'], - min_value = kwargs['udp_dst_port'] - kwargs['udp_dst_port_count'] +1, + min_value = kwargs['udp_dst_port'] - udp_dst_port_count * kwargs['udp_dst_port_step'], max_value = kwargs['udp_dst_port'])) elif kwargs['udp_dst_port_mode'] == 'random': - vm_cmds.append(CTRexVmDescFlowVar(name = 'udp_dst', size = 2, op = 'random', - min_value = kwargs['udp_dst_port'], - max_value = kwargs['udp_dst_port'] + kwargs['udp_dst_port_count'] - 1)) + vm_cmds.append(CTRexVmDescFlowVar(name = 'udp_dst', size = 2, op = 'random', min_value = 0, max_value = 0xffff)) else: raise STLError('udp_dst_port_mode %s is not supported' % kwargs['udp_dst_port_mode']) vm_cmds.append(CTRexVmDescWrFlowVar(fv_name='udp_dst', pkt_offset = 'UDP.dport')) @@ -1138,7 +1150,25 @@ def generate_packet(**user_kwargs): if fix_ipv4_checksum and l3_layer.name == 'IP' and kwargs['ip_checksum'] is None: vm_cmds.append(CTRexVmDescFixIpv4(offset = 'IP')) if vm_cmds: - pkt.add_command(CTRexScRaw(vm_cmds)) + split_by_field = None + if kwargs['split_by_cores'] == 'single': + raise STLError("split_by_cores 'single' not implemented yet") + elif kwargs['split_by_cores'] == 'split': + max_length = 0 + for cmd in vm_cmds: + if isinstance(cmd, CTRexVmDescFlowVar): + if cmd.op not in ('inc', 'dec'): + continue + length = float(cmd.max_value - cmd.min_value) / cmd.step + if cmd.name == 'ip_src' and length > 7: # priority is to split by ip_src + split_by_field = 'ip_src' + break + if length > max_length: + max_length = length + split_by_field = cmd.name + elif kwargs['split_by_cores'] != 'duplicate': + raise STLError("split_by_cores '%s' not supported" % kwargs['split_by_cores']) + pkt.add_command(CTRexScRaw(vm_cmds, split_by_field)) # debug (only the base packet, without VM) debug_filename = kwargs.get('save_to_pcap') @@ -1183,10 +1213,6 @@ def split_vlan_args(kwargs): for arg, value in kwargs.items(): if arg.startswith('vlan_'): vlan_args_dict[arg] = split_vlan_arg(value) - if arg == 'vlan_protocol_tag_id': # special case, can be string of hex - print vlan_args_dict[arg] - vlan_args_dict[arg] = [int(x, 16) for x in vlan_args_dict[arg] if type(x) is str] - print vlan_args_dict[arg] dot1q_headers_count = max([len(x) for x in vlan_args_dict.values()]) vlan_args_per_header = [{} for _ in range(dot1q_headers_count)] for arg, value in vlan_args_dict.items(): @@ -1197,4 +1223,17 @@ def split_vlan_args(kwargs): vlan_args_per_header[i][arg] = traffic_config_kwargs[arg] return vlan_args_per_header - +def correct_direction(user_kwargs, kwargs): + if kwargs['direction'] == 0: + return + user_kwargs['mac_src'], user_kwargs['mac_dst'] = kwargs['mac_dst'], kwargs['mac_src'] + if kwargs['l3_protocol'] == 'ipv4': + for arg in kwargs.keys(): + if 'ip_src_' in arg: + dst_arg = 'ip_dst_' + arg[7:] + user_kwargs[arg], user_kwargs[dst_arg] = kwargs[dst_arg], kwargs[arg] + elif kwargs['l3_protocol'] == 'ipv6': + for arg in kwargs.keys(): + if 'ipv6_src_' in arg: + dst_arg = 'ipv6_dst_' + arg[9:] + user_kwargs[arg], user_kwargs[dst_arg] = kwargs[dst_arg], kwargs[arg] diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py index 24a7301b..713769b6 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py @@ -28,17 +28,24 @@ class CTRexPacketBuildException(Exception): ################################################################################################ -def ipv4_str_to_num (ipv4_buffer): +def _buffer_to_num(str_buffer): + assert type(str_buffer)==str, 'type of str_buffer is not str' + res=0 + for i in str_buffer: + res = res << 8 + res += ord(i) + return res + +def ipv4_str_to_num (ipv4_buffer): assert type(ipv4_buffer)==str, 'type of ipv4_buffer is not str' assert len(ipv4_buffer)==4, 'size of ipv4_buffer is not 4' - res=0 - shift=24 - for i in ipv4_buffer: - res = res + (ord(i)<<shift); - shift =shift -8 - return res + return _buffer_to_num(ipv4_buffer) +def mac_str_to_num (mac_buffer): + assert type(mac_buffer)==str, 'type of mac_buffer is not str' + assert len(mac_buffer)==6, 'size of mac_buffer is not 6' + return _buffer_to_num(mac_buffer) def is_valid_ipv4(ip_addr): @@ -215,12 +222,16 @@ class CTRexVmInsFlowVar(CTRexVmInsBase): self.op = op self.init_value = init_value assert type(init_value)==int, 'type of init_value is not int' + assert init_value >= 0, 'init_value (%s) is negative' % init_value self.min_value=min_value assert type(min_value)==int, 'type of min_value is not int' + assert min_value >= 0, 'min_value (%s) is negative' % min_value self.max_value=max_value - assert type(max_value)==int, 'type of min_value is not int' + assert type(max_value)==int, 'type of max_value is not int' + assert max_value >= 0, 'max_value (%s) is negative' % max_value self.step=step assert type(step)==int, 'type of step should be int' + assert step >= 0, 'step (%s) is negative' % step class CTRexVmInsWrFlowVar(CTRexVmInsBase): def __init__(self, fv_name, pkt_offset, add_value=0, is_big_endian=True): @@ -588,7 +599,7 @@ class CTRexVmDescWrMaskFlowVar(CTRexVmDescBase): self.pkt_offset =pkt_offset self.pkt_cast_size =pkt_cast_size assert type(pkt_cast_size)==int,'type of pkt_cast_size is not int' - if not (pkt_cast_size in [1,2,4]): + if not (pkt_cast_size in [1,2,4,8]): raise CTRexPacketBuildException(-10,"not valid cast size"); self.mask = mask diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py index 838a49ed..29bad041 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py @@ -4,6 +4,7 @@ from collections import namedtuple, OrderedDict import trex_stl_stats from trex_stl_types import * import time +import copy StreamOnPort = namedtuple('StreamOnPort', ['compiled_stream', 'metadata']) @@ -160,8 +161,8 @@ class Port(object): return self.err("Please stop port before attempting to add streams") # listify - streams_list = streams_list if isinstance(streams_list, list) else [streams_list] - + streams_list = copy.deepcopy(streams_list if isinstance(streams_list, list) else [streams_list]) + lookup = {} # allocate IDs @@ -171,10 +172,12 @@ class Port(object): lookup[stream.get_name()] = stream.get_id() - # resolve names + batch = [] + + for stream in streams_list: - next_id = -1 + next_id = -1 next = stream.get_next() if next: if not next in lookup: @@ -183,10 +186,7 @@ class Port(object): stream.set_next_id(next_id) - - - batch = [] - for stream in streams_list: + stream_json = stream.to_json() stream_json['next_stream_id'] = stream.get_next_id() diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py index e5578564..34c7a857 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py @@ -117,8 +117,10 @@ class CTRexInfoGenerator(object): per_field_stats = OrderedDict([("owner", []), ("state", []), ("--", []), - ("Tx bps", []), + ("Tx bps L2", []), + ("Tx bps L1", []), ("Tx pps", []), + ("Line Util.", []), ("---", []), ("Rx bps", []), @@ -313,7 +315,15 @@ class CTRexStats(object): # must be implemented by designated classes (such as port/ global stats) raise NotImplementedError() + def generate_extended_values (self, snapshot): + raise NotImplementedError() + + def update(self, snapshot): + + # some extended generated values (from base values) + self.generate_extended_values(snapshot) + # update self.latest_stats = snapshot @@ -326,6 +336,8 @@ class CTRexStats(object): if (not self.reference_stats) or (diff_time > 3): self.reference_stats = self.latest_stats + + self.last_update_ts = time.time() @@ -439,6 +451,20 @@ class CGlobalStats(CTRexStats): return stats + def generate_extended_values (self, snapshot): + # L1 bps + bps = snapshot.get("m_tx_bps") + pps = snapshot.get("m_tx_pps") + + if pps > 0: + avg_pkt_size = bps / (pps * 8.0) + bps_L1 = bps * ( (avg_pkt_size + 20.0) / avg_pkt_size ) + else: + bps_L1 = 0.0 + + snapshot['m_tx_bps_L1'] = bps_L1 + + def generate_stats(self): return OrderedDict([("connection", "{host}, Port {port}".format(host=self.connection_info.get("server"), port=self.connection_info.get("sync_port"))), @@ -450,8 +476,11 @@ class CGlobalStats(CTRexStats): (" ", ""), - ("total_tx", u"{0} {1}".format( self.get("m_tx_bps", format=True, suffix="b/sec"), - self.get_trend_gui("m_tx_bps"))), + ("total_tx_L2", u"{0} {1}".format( self.get("m_tx_bps", format=True, suffix="b/sec"), + self.get_trend_gui("m_tx_bps"))), + + ("total_tx_L1", u"{0} {1}".format( self.get("m_tx_bps_L1", format=True, suffix="b/sec"), + self.get_trend_gui("m_tx_bps_L1"))), ("total_rx", u"{0} {1}".format( self.get("m_rx_bps", format=True, suffix="b/sec"), self.get_trend_gui("m_rx_bps"))), @@ -532,6 +561,21 @@ class CPortStats(CTRexStats): return stats + def generate_extended_values (self, snapshot): + # L1 bps + bps = snapshot.get("m_total_tx_bps") + pps = snapshot.get("m_total_tx_pps") + + if pps > 0: + avg_pkt_size = bps / (pps * 8.0) + bps_L1 = bps * ( (avg_pkt_size + 20.0) / avg_pkt_size ) + else: + bps_L1 = 0.0 + + snapshot['m_total_tx_bps_L1'] = bps_L1 + snapshot['m_percentage'] = (bps_L1 / self._port_obj.get_speed_bps()) * 100 + + def generate_stats(self): state = self._port_obj.get_port_state_name() if self._port_obj else "" @@ -542,6 +586,7 @@ class CPortStats(CTRexStats): else: state = format_text(state, 'bold') + return {"owner": self._port_obj.user if self._port_obj else "", "state": "{0}".format(state), @@ -550,8 +595,16 @@ class CPortStats(CTRexStats): "----": " ", "-----": " ", - "Tx bps": u"{0} {1}".format(self.get_trend_gui("m_total_tx_bps", show_value = False), - self.get("m_total_tx_bps", format = True, suffix = "bps")), + "Tx bps L1": u"{0} {1}".format(self.get_trend_gui("m_total_tx_bps_L1", show_value = False), + self.get("m_total_tx_bps_L1", format = True, suffix = "bps")), + + "Tx bps L2": u"{0} {1}".format(self.get_trend_gui("m_total_tx_bps", show_value = False), + self.get("m_total_tx_bps", format = True, suffix = "bps")), + + "Line Util.": u"{0} {1}".format(self.get_trend_gui("m_percentage", show_value = False), + format_text( + self.get("m_percentage", format = True, suffix = "%") if self._port_obj else "", + 'bold')), "Rx bps": u"{0} {1}".format(self.get_trend_gui("m_total_rx_bps", show_value = False), self.get("m_total_rx_bps", format = True, suffix = "bps")), diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py index b72b5d35..f79d25c3 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py @@ -1,6 +1,7 @@ #!/router/bin/python from trex_stl_exceptions import * +from trex_stl_types import verify_exclusive_arg, validate_type from trex_stl_packet_builder_interface import CTrexPktBuilderInterface from trex_stl_packet_builder_scapy import CScapyTRexPktBuilder, Ether, IP, UDP, TCP, RawPcapReader from collections import OrderedDict, namedtuple @@ -11,15 +12,50 @@ import yaml import base64 import string import traceback - -def random_name (l): - return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(l)) +from types import NoneType +import copy # base class for TX mode class STLTXMode(object): - def __init__ (self): - self.fields = {} + def __init__ (self, pps = None, bps_L1 = None, bps_L2 = None, percentage = None): + args = [pps, bps_L1, bps_L2, percentage] + + # default + if all([x is None for x in args]): + pps = 1.0 + else: + verify_exclusive_arg(args) + + self.fields = {'rate': {}} + + if pps is not None: + validate_type('pps', pps, [float, int]) + + self.fields['rate']['type'] = 'pps' + self.fields['rate']['value'] = pps + + elif bps_L1 is not None: + validate_type('bps_L1', bps_L1, [float, int]) + + self.fields['rate']['type'] = 'bps_L1' + self.fields['rate']['value'] = bps_L1 + + elif bps_L2 is not None: + validate_type('bps_L2', bps_L2, [float, int]) + + self.fields['rate']['type'] = 'bps_L2' + self.fields['rate']['value'] = bps_L2 + + elif percentage is not None: + validate_type('percentage', percentage, [float, int]) + if not (percentage > 0 and percentage <= 100): + raise STLArgumentError('percentage', percentage) + + self.fields['rate']['type'] = 'percentage' + self.fields['rate']['value'] = percentage + + def to_json (self): return self.fields @@ -28,15 +64,11 @@ class STLTXMode(object): # continuous mode class STLTXCont(STLTXMode): - def __init__ (self, pps = 1): + def __init__ (self, pps = None, bps_L1 = None, bps_L2 = None, percentage = None): - if not isinstance(pps, (int, float)): - raise STLArgumentError('pps', pps) - - super(STLTXCont, self).__init__() + super(STLTXCont, self).__init__(pps, bps_L1, bps_L2, percentage) self.fields['type'] = 'continuous' - self.fields['pps'] = pps def __str__ (self): return "Continuous" @@ -44,18 +76,14 @@ class STLTXCont(STLTXMode): # single burst mode class STLTXSingleBurst(STLTXMode): - def __init__ (self, pps = 1, total_pkts = 1): - - if not isinstance(pps, (int, float)): - raise STLArgumentError('pps', pps) + def __init__ (self, total_pkts = 1, pps = None, bps_L1 = None, bps_L2 = None, percentage = None): if not isinstance(total_pkts, int): raise STLArgumentError('total_pkts', total_pkts) - super(STLTXSingleBurst, self).__init__() + super(STLTXSingleBurst, self).__init__(pps, bps_L1, bps_L2, percentage) self.fields['type'] = 'single_burst' - self.fields['pps'] = pps self.fields['total_pkts'] = total_pkts def __str__ (self): @@ -65,13 +93,13 @@ class STLTXSingleBurst(STLTXMode): class STLTXMultiBurst(STLTXMode): def __init__ (self, - pps = 1, pkts_per_burst = 1, ibg = 0.0, # usec not SEC - count = 1): - - if not isinstance(pps, (int, float)): - raise STLArgumentError('pps', pps) + count = 1, + pps = None, + bps_L1 = None, + bps_L2 = None, + percentage = None): if not isinstance(pkts_per_burst, int): raise STLArgumentError('pkts_per_burst', pkts_per_burst) @@ -82,10 +110,9 @@ class STLTXMultiBurst(STLTXMode): if not isinstance(count, int): raise STLArgumentError('count', count) - super(STLTXMultiBurst, self).__init__() + super(STLTXMultiBurst, self).__init__(pps, bps_L1, bps_L2, percentage) self.fields['type'] = 'multi_burst' - self.fields['pps'] = pps self.fields['pkts_per_burst'] = pkts_per_burst self.fields['ibg'] = ibg self.fields['count'] = count @@ -104,7 +131,7 @@ class STLStream(object): def __init__ (self, name = None, packet = None, - mode = STLTXCont(1), + mode = STLTXCont(pps = 1), enabled = True, self_start = True, isg = 0.0, @@ -117,20 +144,12 @@ class STLStream(object): ): # type checking - if not isinstance(mode, STLTXMode): - raise STLArgumentError('mode', mode) - - if packet and not isinstance(packet, CTrexPktBuilderInterface): - raise STLArgumentError('packet', packet) - - if not isinstance(enabled, bool): - raise STLArgumentError('enabled', enabled) - - if not isinstance(self_start, bool): - raise STLArgumentError('self_start', self_start) - - if not isinstance(isg, (int, float)): - raise STLArgumentError('isg', isg) + validate_type('mode', mode, STLTXMode) + validate_type('packet', packet, (NoneType, CTrexPktBuilderInterface)) + validate_type('enabled', enabled, bool) + validate_type('self_start', self_start, bool) + validate_type('isg', isg, (int, float)) + validate_type('stream_id', stream_id, (NoneType, int)) if (type(mode) == STLTXCont) and (next != None): raise STLError("continuous stream cannot have a next stream ID") @@ -181,6 +200,8 @@ class STLStream(object): self.fields['mode'] = mode.to_json() self.mode_desc = str(mode) + + # packet self.fields['packet'] = {} self.fields['vm'] = {} @@ -249,8 +270,6 @@ class STLStream(object): return pkt_len - def get_pps (self): - return self.fields['mode']['pps'] def get_mode (self): return self.mode_desc @@ -265,7 +284,14 @@ class STLStream(object): if self.next: y['next'] = self.next - y['stream'] = self.fields + y['stream'] = copy.deepcopy(self.fields) + + # some shortcuts for YAML + rate_type = self.fields['mode']['rate']['type'] + rate_value = self.fields['mode']['rate']['value'] + + y['stream']['mode'][rate_type] = rate_value + del y['stream']['mode']['rate'] return y @@ -313,23 +339,29 @@ class YAMLLoader(object): def __parse_mode (self, mode_obj): + rate_parser = set(mode_obj).intersection(['pps', 'bps_L1', 'bps_L2', 'percentage']) + if len(rate_parser) != 1: + raise STLError("'rate' must contain exactly one from 'pps', 'bps_L1', 'bps_L2', 'percentage'") + + rate_type = rate_parser.pop() + rate = {rate_type : mode_obj[rate_type]} + mode_type = mode_obj.get('type') if mode_type == 'continuous': - defaults = STLTXCont() - mode = STLTXCont(pps = mode_obj.get('pps', defaults.fields['pps'])) + mode = STLTXCont(**rate) elif mode_type == 'single_burst': defaults = STLTXSingleBurst() - mode = STLTXSingleBurst(pps = mode_obj.get('pps', defaults.fields['pps']), - total_pkts = mode_obj.get('total_pkts', defaults.fields['total_pkts'])) + mode = STLTXSingleBurst(total_pkts = mode_obj.get('total_pkts', defaults.fields['total_pkts']), + **rate) elif mode_type == 'multi_burst': defaults = STLTXMultiBurst() - mode = STLTXMultiBurst(pps = mode_obj.get('pps', defaults.fields['pps']), - pkts_per_burst = mode_obj.get('pkts_per_burst', defaults.fields['pkts_per_burst']), + mode = STLTXMultiBurst(pkts_per_burst = mode_obj.get('pkts_per_burst', defaults.fields['pkts_per_burst']), ibg = mode_obj.get('ibg', defaults.fields['ibg']), - count = mode_obj.get('count', defaults.fields['count'])) + count = mode_obj.get('count', defaults.fields['count']), + **rate) else: raise STLError("mode type can be 'continuous', 'single_burst' or 'multi_burst") @@ -338,6 +370,8 @@ class YAMLLoader(object): return mode + + def __parse_stream (self, yaml_object): s_obj = yaml_object['stream'] @@ -536,3 +570,4 @@ class STLProfile(object): def __len__ (self): return len(self.streams) + diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py index 0a6e64fb..d4ad8bd2 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py @@ -2,6 +2,7 @@ from collections import namedtuple from utils.text_opts import * from trex_stl_exceptions import * +import types RpcCmdData = namedtuple('RpcCmdData', ['method', 'params']) TupleRC = namedtuple('RC', ['rc', 'data', 'is_warn']) @@ -102,9 +103,17 @@ def RC_WARN (warn): def validate_type(arg_name, arg, valid_types): if type(valid_types) is list: valid_types = tuple(valid_types) - if type(valid_types) is type or type(valid_types) is tuple: + if (type(valid_types) is type or # single type, not array of types + type(valid_types) is tuple or # several valid types as tuple + type(valid_types) is types.ClassType): # old style class if isinstance(arg, valid_types): return raise STLTypeError(arg_name, type(arg), valid_types) else: raise STLError('validate_type: valid_types should be type or list or tuple of types') + +# throws STLError if not exactly one argument is present +def verify_exclusive_arg (args_list): + if not (len(filter(lambda x: x is not None, args_list)) == 1): + raise STLError('exactly one parameter from {0} should be provided'.format(args_list)) + |