From 69e5a5c6b94175ece07b247af1b5ca6c0cfdf0e9 Mon Sep 17 00:00:00 2001 From: Yaroslav Brustinov Date: Fri, 5 Feb 2016 17:39:09 +0200 Subject: HLTAPI update + HLT packet builder functional tests (no simulation) --- .../trex_control_plane/client/trex_hltapi.py | 610 ++++++++++++++------- 1 file changed, 400 insertions(+), 210 deletions(-) (limited to 'scripts/automation/trex_control_plane/client/trex_hltapi.py') diff --git a/scripts/automation/trex_control_plane/client/trex_hltapi.py b/scripts/automation/trex_control_plane/client/trex_hltapi.py index 3bbf62e0..5d3f506c 100755 --- a/scripts/automation/trex_control_plane/client/trex_hltapi.py +++ b/scripts/automation/trex_control_plane/client/trex_hltapi.py @@ -1,78 +1,123 @@ #!/router/bin/python ''' -Supported function/arguments: -connect() - device - port_list - username - reset - break_locks - -cleanup_session() - maintain_lock - port_list - port_handle - -traffic_config() - mode ( create | modify | remove | reset ) - port_handle - transmit_mode ( continuous | multi_burst | single_burst ) - rate_pps - stream_id - bidirectional - l2_encap - mac_src - mac_src2 - mac_dst - mac_dst2 - l3_protocol - ip_tos_field - l3_length - ip_id - ip_fragment_offset - ip_ttl - ip_checksum - ip_src_addr - ip_dst_addr - l4_protocol - tcp_src_port - tcp_dst_port - tcp_seq_num - tcp_ack_num - tcp_data_offset - tcp_fin_flag - tcp_syn_flag - tcp_rst_flag - tcp_psh_flag - tcp_ack_flag - tcp_urg_flag - tcp_window - tcp_checksum - tcp_urgent_ptr - -traffic_control() - action ( run | stop ) - port_handle - -traffic_stats() - mode ( aggregate ) - port_handle - +Supported function/arguments/defaults: ''' - - - -import trex_root_path +# connect() +connect_kwargs = { + 'device': 'localhost', # ip or hostname of TRex + 'port_list': None, # list of ports + 'username': 'TRexUser', + 'reset': True, + 'break_locks': False, +} + +# cleanup_session() +cleanup_session_kwargs = { + 'maintain_lock': False, # release ports at the end or not + 'port_list': None, + 'port_handle': None, +} + +# traffic_config() +traffic_config_kwargs = { + 'mode': None, # ( create | modify | remove | reset ) + 'port_handle': None, + 'transmit_mode': 'continuous', # ( continuous | multi_burst | single_burst ) + 'rate_pps': 1, + 'stream_id': None, + 'bidirectional': 0, + # stream builder parameters + 'pkts_per_burst': 1, + 'burst_loop_count': 1, + 'inter_burst_gap': 12, + 'length_mode': 'fixed', # ( auto | fixed | increment | decrement | random ) + #L2 + 'frame_size': 64, + 'frame_size_min': 64, + 'frame_size_max': 64, + 'frame_size_step': 1, # has to be 1 + 'l2_encap': 'ethernet_ii', # ( ethernet_ii ) + 'mac_src': '00:00:01:00:00:01', + 'mac_dst': '00:00:00:00:00:00', + #L3, IP + 'l3_protocol': 'ipv4', # ( ipv4 ) + 'ip_tos_field': 0, + 'l3_length': 50, + 'ip_id': 0, + 'ip_fragment_offset': 0, + 'ip_ttl': 64, + 'ip_checksum': None, + 'ip_src_addr': '0.0.0.0', + 'ip_dst_addr': '192.0.0.1', + 'ip_src_mode': 'fixed', # ( fixed | increment | decrement | random ) + 'ip_src_step': 1, # has to be 1 + 'ip_src_count': 1, + 'ip_dst_mode': 'fixed', # ( fixed | increment | decrement | random ) + 'ip_dst_step': 1, # has to be 1 + 'ip_dst_count': 1, + 'l3_length_min': 110, + 'l3_length_max': 238, + 'l3_length_step': 1, # has to be 1 + #L3, IPv6 (TODO: add) + #L4, TCP + 'l4_protocol': 'tcp', # ( tcp | udp ) + 'tcp_src_port': 1024, + 'tcp_dst_port': 80, + 'tcp_seq_num': 1, + 'tcp_ack_num': 1, + 'tcp_data_offset': 5, + 'tcp_fin_flag': 0, + 'tcp_syn_flag': 0, + 'tcp_rst_flag': 0, + 'tcp_psh_flag': 0, + 'tcp_ack_flag': 0, + 'tcp_urg_flag': 0, + 'tcp_window': 4069, + 'tcp_checksum': None, + 'tcp_urgent_ptr': 0, + 'tcp_src_port_mode': 'increment', # ( increment | decrement | random ) + 'tcp_src_port_step': 1, # has to be 1 + 'tcp_src_port_count': 1, + 'tcp_dst_port_mode': 'increment', # ( increment | decrement | random ) + 'tcp_dst_port_step': 1, # has to be 1 + 'tcp_dst_port_count': 1, + # L4, UDP + 'udp_src_port': 1024, + 'udp_dst_port': 80, + 'udp_length': None, + 'udp_checksum': None, + 'udp_dst_port_mode': 'increment', # ( increment | decrement | random ) + 'udp_src_port_step': 1, # has to be 1 + 'udp_src_port_count': 1, + 'udp_src_port_mode': 'increment', # ( increment | decrement | random ) + 'udp_dst_port_step': 1, # has to be 1 + 'udp_dst_port_count': 1, +} + +# traffic_control() +traffic_control_kwargs = { + 'action': None, # ( run | stop ) + 'port_handle': None +} + +# traffic_stats() +traffic_stats_kwargs = { + 'mode': 'aggregate', # ( aggregate ) + 'port_handle': None +} + + +#import trex_root_path import client_utils.scapy_packet_builder as pkt_bld +from client_utils.scapy_packet_builder import CTRexVmDescFlowVar, CTRexVmDescWrFlowVar from trex_stateless_client import STLClient from common.trex_streams import * from client_utils.general_utils import get_integer -import dpkt import socket +import copy from misc_methods import print_r -import traceback -import time + class HLT_ERR(dict): def __init__(self, log = 'Unknown error', **kwargs): @@ -91,6 +136,16 @@ class HLT_OK(dict): dict.update(self, init_dict) dict.update(self, kwargs) +def merge_kwargs(default_kwargs, user_kwargs): + extra_args = [] + kwargs = copy.deepcopy(default_kwargs) + for key, value in user_kwargs.items(): + if key in kwargs: + kwargs[key] = value + elif key not in ('save_to_yaml', 'save_to_pcap'): # internal debug arguments + print("Warning: provided parameter '%s' not supported" % key) + return kwargs + class CTRexHltApi(object): @@ -105,9 +160,9 @@ class CTRexHltApi(object): # Session functions # ########################### - # device: ip or hostname - def connect(self, device, port_list, username = '', reset = False, break_locks = False): - + def connect(self, **user_kwargs): + kwargs = merge_kwargs(connect_kwargs, user_kwargs) + device = kwargs['device'] try: device = socket.gethostbyname(device) # work with ip except: # give it another try @@ -118,7 +173,7 @@ class CTRexHltApi(object): try: # sync = RPC, async = ZMQ - self.trex_client = STLClient(username, device, sync_port = 4501, async_port = 4500, verbose_level = self.verbose) + self.trex_client = STLClient(kwargs['username'], device, sync_port = 4501, async_port = 4500, verbose_level = self.verbose) except Exception as e: self.trex_client = None return HLT_ERR('Could not init stateless client %s: %s' % (device, e)) @@ -130,8 +185,9 @@ class CTRexHltApi(object): # connection successfully created with server, try acquiring ports of TRex try: - port_list = self.parse_port_list(port_list) - self.trex_client.acquire(ports = port_list, force = break_locks) + port_list = self.parse_port_list(kwargs['port_list']) + print kwargs['break_locks'] + self.trex_client.acquire(ports = port_list, force = kwargs['break_locks']) except Exception as e: self.trex_client = None return HLT_ERR('Could not acquire ports %s: %s' % (port_list, e)) @@ -140,9 +196,11 @@ class CTRexHltApi(object): port_handle = self.trex_client.get_acquired_ports() # arrived here, all desired ports were successfully acquired - if reset: + if kwargs['reset']: # remove all port traffic configuration from TRex try: + print 'reseting' + self.trex_client.stop(ports = port_list) self.trex_client.reset(ports = port_list) except Exception as e: self.trex_client = None @@ -151,10 +209,11 @@ class CTRexHltApi(object): self.connected = True return HLT_OK(port_handle = port_handle) - def cleanup_session(self, maintain_lock = False, **kwargs): - if not maintain_lock: + def cleanup_session(self, **user_kwargs): + kwargs = merge_kwargs(cleanup_session_kwargs, user_kwargs) + if not kwargs['maintain_lock']: # release taken ports - port_list = kwargs.get('port_list', kwargs.get('port_handle', 'all')) + port_list = kwargs['port_list'] or kwargs['port_handle'] or 'all' try: if port_list == 'all': port_list = self.trex_client.get_acquired_ports() @@ -186,16 +245,19 @@ class CTRexHltApi(object): # Traffic functions # ########################### - def traffic_config(self, mode, port_handle, **kwargs): - stream_id = kwargs.get('stream_id') + def traffic_config(self, **user_kwargs): + kwargs = merge_kwargs(traffic_config_kwargs, user_kwargs) + stream_id = kwargs['stream_id'] if type(stream_id) is list: del kwargs['stream_id'] for each_stream_id in stream_id: - res = self.traffic_config(mode, port_handle, stream_id = each_stream_id, **kwargs) + res = self.traffic_config(stream_id = each_stream_id, **kwargs) if type(res) is HLT_ERR: return res return HLT_OK() + mode = kwargs['mode'] + port_handle = kwargs['port_handle'] if type(port_handle) is not list: port_handle = [port_handle] ALLOWED_MODES = ['create', 'modify', 'remove', 'enable', 'disable', 'reset'] @@ -240,7 +302,6 @@ class CTRexHltApi(object): if stream_id not in self._hlt_streams_history: return HLT_ERR('This stream_id (%s) was not used before, please create new.' % stream_id) self._hlt_streams_history[stream_id].update(kwargs) # <- the modification - kwargs = self._hlt_streams_history[stream_id] #for port_id in port_handle: # if stream_id not in self.trex_client.get_stream_id_list(port_id): # return HLT_ERR('Port %s does not have stream_id %s.' % (port_id, stream_id)) @@ -252,27 +313,27 @@ class CTRexHltApi(object): if mode == 'create' or mode == 'modify': # create a new stream with desired attributes, starting by creating packet - if 'bidirectional' in kwargs: # two streams with opposite src and dst MAC + if kwargs['bidirectional']: # two streams with opposite directions del kwargs['bidirectional'] + del kwargs['port_handle'] bidirect_err = 'When using bidirectional flag, ' if len(port_handle) != 2: return HLT_ERR(bidirect_err + 'number of ports should be exactly 2') try: - res1 = self.traffic_config(mode, port_handle[0], **kwargs) - res2 = self.traffic_config(mode, port_handle[1], - mac_src = kwargs.get(mac_src2, '00-00-01-00-00-01'), - mac_dst = kwargs.get(mac_dst2, '00-00-00-00-00-00'), - ip_src_addr = kwargs.get(ip_dst_addr, '192.0.0.1'), - ip_dst_addr = kwargs.get(ip_src_addr, '0.0.0.0'), - ipv6_src_addr = kwargs.get(ipv6_dst_addr, 'fe80:0:0:0:0:0:0:22'), - ipv6_dst_addr = kwargs.get(ipv6_src_addr, 'fe80:0:0:0:0:0:0:12'), - **kwargs) + res1 = self.traffic_config(port_handle = port_handle[0], **kwargs) + kwargs['mac_src'] = kwargs['mac_src2'] + kwargs['mac_dst'] = kwargs['mac_dst2'] + kwargs['ip_src_addr'] = kwargs['ip_dst_addr'] + kwargs['ip_dst_addr'] = kwargs['ip_src_addr'] + kwargs['ipv6_src_addr'] = kwargs['ipv6_dst_addr'] + kwargs['ipv6_dst_addr'] = kwargs['ipv6_src_addr'] + res2 = self.traffic_config(port_handle = port_handle[1], **kwargs) except Exception as e: return HLT_ERR('Could not generate bidirectional traffic: %s' % e) return HLT_OK(stream_id = {port_handle[0]: res1['stream_id'], port_handle[1]: res2['stream_id']}) - + stream_obj = CTRexHltApiPktBuilder.generate_stream(**kwargs) try: - stream_obj = CTRexHltApi._generate_stream(**kwargs) + stream_obj = CTRexHltApiPktBuilder.generate_stream(**kwargs) except Exception as e: return HLT_ERR('Could not create stream: %s' % e) stream_id = stream_obj.get_id() @@ -288,7 +349,10 @@ class CTRexHltApi(object): return HLT_ERR('Got to the end of traffic_config, mode not implemented or forgot "return" function somewhere.') - def traffic_control(self, action, port_handle, **kwargs): + def traffic_control(self, **user_kwargs): + kwargs = merge_kwargs(traffic_control_kwargs, user_kwargs) + action = kwargs['action'] + port_handle = kwargs['port_handle'] ALLOWED_ACTIONS = ['clear_stats', 'run', 'stop', 'sync_run'] if action not in ALLOWED_ACTIONS: return HLT_ERR('Action must be one of the following values: {actions}'.format(actions=ALLOWED_ACTIONS)) @@ -298,7 +362,7 @@ class CTRexHltApi(object): if action == 'run': try: - self.trex_client.start(duration = kwargs.get('duration', -1), ports = port_handle) + self.trex_client.start(ports = port_handle) except Exception as e: return HLT_ERR('Could not start traffic: %s' % e) return HLT_OK(stopped = 0) @@ -316,7 +380,10 @@ class CTRexHltApi(object): # if we arrived here, this means that operation FAILED! return HLT_ERR("Probably action '%s' is not implemented" % action) - def traffic_stats(self, port_handle, mode): + def traffic_stats(self, **user_kwargs): + kwargs = merge_kwargs(traffic_stats_kwargs, user_kwargs) + mode = kwargs['mode'] + port_handle = kwargs['port_handle'] ALLOWED_MODES = ['aggregate', 'streams', 'all'] if mode not in ALLOWED_MODES: return HLT_ERR("'mode' must be one of the following values: %s" % ALLOWED_MODES) @@ -417,19 +484,21 @@ class CTRexHltApi(object): return '\n'. join([str(response) for response in responses]) return responses +class CTRexHltApiPktBuilder: @staticmethod - def _generate_stream(**kwargs): + def generate_stream(**user_kwargs): + kwargs = merge_kwargs(traffic_config_kwargs, user_kwargs) try: - packet = CTRexHltApi._generate_packet(**kwargs) + packet = CTRexHltApiPktBuilder.generate_packet(**kwargs) except Exception as e: raise Exception('Could not generate packet: %s' % e) try: - transmit_mode = kwargs.get('transmit_mode', 'continuous') - rate_pps = kwargs.get('rate_pps', 1) - pkts_per_burst = kwargs.get('pkts_per_burst', 1) - burst_loop_count = kwargs.get('burst_loop_count', 1) - inter_burst_gap = kwargs.get('inter_burst_gap', 12) + transmit_mode = kwargs['transmit_mode'] + rate_pps = kwargs['rate_pps'] + pkts_per_burst = kwargs['pkts_per_burst'] + burst_loop_count = kwargs['burst_loop_count'] + inter_burst_gap = kwargs['inter_burst_gap'] if transmit_mode == 'continuous': transmit_mode_class = STLTXCont(pps = rate_pps) elif transmit_mode == 'single_burst': @@ -458,59 +527,25 @@ class CTRexHltApi(object): return stream_obj @staticmethod - def _generate_packet( - # L2 - frame_size = 64, - l2_encap = 'ethernet_ii', - mac_src = '00:00:01:00:00:01', - mac_dst = '00:00:00:00:00:00', - - # L3 IPv4 - l3_protocol = 'ipv4', - ip_tos_field = 0, - l3_length = 50, - ip_id = 0, - ip_fragment_offset = 0, - ip_ttl = 64, - ip_checksum = None, - ip_src_addr = '0.0.0.0', - ip_dst_addr = '192.0.0.1', - - # L3 IPv4 FE - ip_src_mode = 'fixed', - ip_src_step = 1, - ip_src_count = 1, - - l4_protocol = 'tcp', - tcp_src_port = 1024, - tcp_dst_port = 80, - tcp_seq_num = 1, - tcp_ack_num = 1, - tcp_data_offset = 1, - tcp_fin_flag = 0, - tcp_syn_flag = 0, - tcp_rst_flag = 0, - tcp_psh_flag = 0, - tcp_ack_flag = 0, - tcp_urg_flag = 0, - tcp_window = 4069, - tcp_checksum = None, - tcp_urgent_ptr = 0, - **kwargs): - - pkt_plus_vm = pkt_bld.CScapyTRexPktBuilder() + def generate_packet(**user_kwargs): + kwargs = merge_kwargs(traffic_config_kwargs, user_kwargs) + pkt = pkt_bld.CScapyTRexPktBuilder() + + vm_cmds = [] + fix_ipv4_checksum = False ### L2 ### - if l2_encap == 'ethernet_ii': + if kwargs['l2_encap'] == 'ethernet_ii': #fields_desc = [ MACField("dst","00:00:00:01:00:00"), # MACField("src","00:00:00:02:00:00"), # XShortEnumField("type", 0x9000, ETHER_TYPES) ] - pkt = pkt_bld.Ether(src = mac_src, dst = mac_dst) + l2_layer = pkt_bld.Ether(src = kwargs['mac_src'], dst = kwargs['mac_dst']) else: - raise NotImplementedError("l2_encap does not support the desired encapsulation '%s'" % l2_encap) + raise NotImplementedError("l2_encap does not support the desired encapsulation '%s'" % kwargs['l2_encap']) + base_pkt = l2_layer ### L3 ### - if l3_protocol == 'ipv4': + if kwargs['l3_protocol'] == 'ipv4': #fields_desc = [ BitField("version" , 4 , 4), # BitField("ihl", None, 4), # XByteField("tos", 0), @@ -526,39 +561,67 @@ class CTRexHltApi(object): # Emph(IPField("src", "16.0.0.1")), # Emph(IPField("dst", "48.0.0.1")), # PacketListField("options", [], IPOption, length_from=lambda p:p.ihl*4-20) ] - pkt /= pkt_bld.IP(tos = ip_tos_field, - len = l3_length, - id = ip_id, - frag = ip_fragment_offset, - ttl = ip_ttl, - chksum = ip_checksum, - src = ip_src_addr, - dst = ip_dst_addr - ) - # IP FE (Field Engine) - print dir(pkt_bld.IP.src.fld) - print_r(pkt_bld.IP.src.fld) - if ip_src_mode == 'increment': - ip_src_vm = pkt_bld.CTRexScRaw([ pkt_bld.CTRexVmDescFlowVar(name='a', min_value='16.0.0.1', max_value='16.0.0.10', init_value='16.0.0.1', size=4, op='inc'), - pkt_bld.CTRexVmDescWrFlowVar (fv_name='a', pkt_offset = 'IP.src'), - pkt_bld.CTRexVmDescFixIpv4(offset = 'IP')]) - pkt_plus_vm.add_command(ip_src_vm) - - #print '>> is inc' - #if ip_src_step != 1: - # return HLT_ERR('ip_src_step has to be 1 (TRex limitation)') - #FE_var_ip_src_addr = pkt_bld.vm.CTRexVMFlowVariable('ip_src_addr') - #FE_var_ip_src_addr.set_field('size', 4) - #FE_var_ip_src_addr.set_field('operation', 'inc') - #FE_var_ip_src_addr.set_field('init_value', ip_src_addr) - #FE_var_ip_src_addr.set_field('init_value', 1) - #FE_var_ip_src_addr.set_field('max_value', ip_src_count) - #pkt_bld.vm.vm_var.set_field('split_by_core', False) + l3_layer = pkt_bld.IP(tos = kwargs['ip_tos_field'], + len = None if kwargs['length_mode'] == 'auto' else kwargs['l3_length'], + id = kwargs['ip_id'], + frag = kwargs['ip_fragment_offset'], + ttl = kwargs['ip_ttl'], + chksum = kwargs['ip_checksum'], + src = kwargs['ip_src_addr'], + dst = kwargs['ip_dst_addr'] + ) + # IPv4 VM + if kwargs['ip_src_mode'] != 'fixed': + fix_ipv4_checksum = True + if kwargs['ip_src_step'] != 1: + raise Exception('ip_src_step has to be 1 (TRex limitation)') + if kwargs['ip_src_count'] < 1: + raise Exception('ip_src_count has to be at least 1') + ip_src_addr_num = pkt_bld.ipv4_str_to_num(pkt_bld.is_valid_ipv4(kwargs['ip_src_addr'])) + if kwargs['ip_src_mode'] == 'increment': + vm_cmds.append(CTRexVmDescFlowVar(name = 'ip_src', size = 4, op = 'inc', + min_value = ip_src_addr_num, + max_value = ip_src_addr_num + kwargs['ip_src_count'] - 1)) + elif kwargs['ip_src_mode'] == 'decrement': + vm_cmds.append(CTRexVmDescFlowVar(name = 'ip_src', size = 4, op = 'dec', + min_value = ip_src_addr_num - kwargs['ip_src_count'] + 1, + max_value = ip_src_addr_num)) + 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)) + else: + raise Exception('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': + fix_ipv4_checksum = True + if kwargs['ip_dst_step'] != 1: + raise Exception('ip_dst_step has to be 1 (TRex limitation)') + if kwargs['ip_dst_count'] < 1: + raise Exception('ip_dst_count has to be at least 1') + ip_dst_addr_num = pkt_bld.ipv4_str_to_num(pkt_bld.is_valid_ipv4(kwargs['ip_dst_addr'])) + if kwargs['ip_dst_mode'] == 'increment': + vm_cmds.append(CTRexVmDescFlowVar(name = 'ip_dst', size = 4, op = 'inc', + min_value = ip_dst_addr_num, + max_value = ip_dst_addr_num + kwargs['ip_dst_count'] - 1)) + elif kwargs['ip_dst_mode'] == 'decrement': + vm_cmds.append(CTRexVmDescFlowVar(name = 'ip_dst', size = 4, op = 'dec', + min_value = ip_dst_addr_num - kwargs['ip_dst_count'] + 1, + max_value = ip_dst_addr_num)) + 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)) + else: + raise Exception('ip_dst_mode %s is not supported' % kwargs['ip_dst_mode']) + vm_cmds.append(CTRexVmDescWrFlowVar(fv_name='ip_dst', pkt_offset = 'IP.dst')) else: - raise NotImplementedError("l3_protocol '%s' is not supported by TRex yet." % l3_protocol) + raise NotImplementedError("l3_protocol '%s' is not supported by TRex yet." % kwargs['l3_protocol']) + base_pkt /= l3_layer ### L4 ### - if l4_protocol == 'tcp': + if kwargs['l4_protocol'] == 'tcp': #fields_desc = [ ShortEnumField("sport", 20, TCP_SERVICES), # ShortEnumField("dport", 80, TCP_SERVICES), # IntField("seq", 0), @@ -570,41 +633,168 @@ class CTRexHltApi(object): # XShortField("chksum", None), # ShortField("urgptr", 0), # TCPOptionsField("options", {}) ] - tcp_flags = ('F' if tcp_fin_flag else '' + - 'S' if tcp_syn_flag else '' + - 'R' if tcp_rst_flag else '' + - 'P' if tcp_psh_flag else '' + - 'A' if tcp_ack_flag else '' + - 'U' if tcp_urg_flag else '') - - pkt /= pkt_bld.TCP(sport = tcp_src_port, - dport = tcp_dst_port, - seq = tcp_seq_num, - ack = tcp_ack_num, - dataofs = tcp_data_offset, - flags = tcp_flags, - window = tcp_window, - chksum = tcp_checksum, - urgptr = tcp_urgent_ptr, - ) - else: - raise NotImplementedError("l4_protocol '%s' is not supported by TRex yet." % l3_protocol) - pkt /= 'payload' - pkt_plus_vm.set_packet(pkt) - #payload = frame_size - pkt - #payload = pkt_bld.payload_gen.gen_repeat_ptrn('Hello, World!') - #pkt_bld.set_pkt_payload(payload) - - #print pkt_bld.vm - # debug (only base packet, without FE) - debug_filename = kwargs.get('save_to_pcap') - if type(debug_filename) is str: - pkt_plus_vm.dump_pkt_to_pcap(debug_filename) - pkt_plus_vm.compile() - return pkt_plus_vm + tcp_flags = ('F' if kwargs['tcp_fin_flag'] else '' + + 'S' if kwargs['tcp_syn_flag'] else '' + + 'R' if kwargs['tcp_rst_flag'] else '' + + 'P' if kwargs['tcp_psh_flag'] else '' + + 'A' if kwargs['tcp_ack_flag'] else '' + + 'U' if kwargs['tcp_urg_flag'] else '') + + l4_layer = pkt_bld.TCP(sport = kwargs['tcp_src_port'], + dport = kwargs['tcp_dst_port'], + seq = kwargs['tcp_seq_num'], + ack = kwargs['tcp_ack_num'], + dataofs = kwargs['tcp_data_offset'], + flags = tcp_flags, + window = kwargs['tcp_window'], + chksum = kwargs['tcp_checksum'], + urgptr = kwargs['tcp_urgent_ptr'], + ) + # TCP VM + if kwargs['tcp_src_port_count'] != 1: + fix_ipv4_checksum = True + if kwargs['tcp_src_port_step'] != 1: + raise Exception('tcp_src_port_step has to be 1 (TRex limitation)') + if kwargs['tcp_src_port_count'] < 1: + raise Exception('tcp_src_port_count has to be at least 1') + if kwargs['tcp_src_port_mode'] == 'increment': + vm_cmds.append(CTRexVmDescFlowVar(name = 'tcp_src', size = 2, op = 'inc', + min_value = kwargs['tcp_src_port'], + max_value = kwargs['tcp_src_port'] + kwargs['tcp_src_port_count'] - 1)) + elif kwargs['tcp_src_port_mode'] == 'decrement': + vm_cmds.append(CTRexVmDescFlowVar(name = 'tcp_src', size = 2, op = 'dec', + min_value = kwargs['tcp_src_port'] - kwargs['tcp_src_port_count'] +1, + 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)) + else: + raise Exception('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: + fix_ipv4_checksum = True + if kwargs['tcp_dst_port_step'] != 1: + raise Exception('tcp_dst_port_step has to be 1 (TRex limitation)') + if kwargs['tcp_dst_port_count'] < 1: + raise Exception('tcp_dst_port_count has to be at least 1') + if kwargs['tcp_dst_port_mode'] == 'increment': + vm_cmds.append(CTRexVmDescFlowVar(name = 'tcp_dst', size = 2, op = 'inc', + min_value = kwargs['tcp_dst_port'], + max_value = kwargs['tcp_dst_port'] + kwargs['tcp_dst_port_count'] - 1)) + elif kwargs['tcp_dst_port_mode'] == 'decrement': + vm_cmds.append(CTRexVmDescFlowVar(name = 'tcp_dst', size = 2, op = 'dec', + min_value = kwargs['tcp_dst_port'] - kwargs['tcp_dst_port_count'] +1, + 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)) + else: + raise Exception('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')) + elif kwargs['l4_protocol'] == 'udp': + #fields_desc = [ ShortEnumField("sport", 53, UDP_SERVICES), + # ShortEnumField("dport", 53, UDP_SERVICES), + # ShortField("len", None), + # XShortField("chksum", None), ] + l4_layer = pkt_bld.UDP(sport = kwargs['udp_src_port'], + dport = kwargs['udp_dst_port'], + len = kwargs['udp_length'], + chksum = kwargs['udp_checksum']) + # UDP VM + if kwargs['udp_src_port_count'] != 1: + fix_ipv4_checksum = True + if kwargs['udp_src_port_step'] != 1: + raise Exception('udp_src_port_step has to be 1 (TRex limitation)') + if kwargs['udp_src_port_count'] < 1: + raise Exception('udp_src_port_count has to be at least 1') + if kwargs['udp_src_port_mode'] == 'increment': + vm_cmds.append(CTRexVmDescFlowVar(name = 'udp_src', size = 2, op = 'inc', + min_value = kwargs['udp_src_port'], + max_value = kwargs['udp_src_port'] + kwargs['udp_src_port_count'] - 1)) + elif kwargs['udp_src_port_mode'] == 'decrement': + vm_cmds.append(CTRexVmDescFlowVar(name = 'udp_src', size = 2, op = 'dec', + min_value = kwargs['udp_src_port'] - kwargs['udp_src_port_count'] +1, + 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)) + else: + raise Exception('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: + fix_ipv4_checksum = True + if kwargs['udp_dst_port_step'] != 1: + raise Exception('udp_dst_port_step has to be 1 (TRex limitation)') + if kwargs['udp_dst_port_count'] < 1: + raise Exception('udp_dst_port_count has to be at least 1') + if kwargs['udp_dst_port_mode'] == 'increment': + vm_cmds.append(CTRexVmDescFlowVar(name = 'udp_dst', size = 2, op = 'inc', + min_value = kwargs['udp_dst_port'], + max_value = kwargs['udp_dst_port'] + kwargs['udp_dst_port_count'] - 1)) + elif kwargs['udp_dst_port_mode'] == 'decrement': + vm_cmds.append(CTRexVmDescFlowVar(name = 'udp_dst', size = 2, op = 'dec', + min_value = kwargs['udp_dst_port'] - kwargs['udp_dst_port_count'] +1, + 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)) + else: + raise Exception('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')) + else: + raise NotImplementedError("l4_protocol '%s' is not supported by TRex yet." % kwargs['l3_protocol']) + base_pkt /= l4_layer -if __name__ == '__main__': - pass + if kwargs['length_mode'] == 'auto': + payload_len = 0 + elif kwargs['length_mode'] == 'fixed': + payload_len = kwargs['frame_size'] - len(base_pkt) + else: + fix_ipv4_checksum = True + if kwargs['frame_size_step'] != 1 or kwargs['l3_length_step'] != 1: + raise Exception('frame_size_step and l3_length_step has to be 1 (TRex limitation)') + trim_dict = {'increment': 'inc', 'decrement': 'dec'} + if kwargs['frame_size_min'] != 64 or kwargs['frame_size_max'] != 64: # size is determined by L2, higher priority over L3 size + if kwargs['frame_size_min'] < 12 or kwargs['frame_size_max'] < 12: + raise Exception('frame_size_min and frame_size_max should be at least 12') + vm_cmds.append(CTRexVmDescFlowVar(name = 'fv_rand', size=2, op=trim_dict.get(kwargs['length_mode'], kwargs['length_mode']), + min_value = kwargs['frame_size_min'], max_value = kwargs['frame_size_max'])) + payload_len = kwargs['frame_size_max'] - len(base_pkt) + else: # size is determined by L3 + vm_cmds.append(CTRexVmDescFlowVar(name = 'fv_rand', size=2, op=trim_dict.get(kwargs['length_mode'], kwargs['length_mode']), + min_value = kwargs['l3_length_min'] + len(l2_layer), max_value = kwargs['l3_length_max'] + len(l2_layer))) + payload_len = kwargs['l3_length_max'] + len(l2_layer) - len(base_pkt) + + vm_cmds.append(pkt_bld.CTRexVmDescTrimPktSize('fv_rand')) + if l3_layer.name == 'IP' or l4_layer.name == 'UDP': # add here other things need to fix due to size change + if l3_layer.name == 'IP': + vm_cmds.append(CTRexVmDescWrFlowVar(fv_name = 'fv_rand', pkt_offset = 'IP.len', add_val = -len(l2_layer))) + if l4_layer.name == 'UDP': + vm_cmds.append(CTRexVmDescWrFlowVar(fv_name = 'fv_rand', pkt_offset = 'UDP.len', add_val = -len(l2_layer) - len(l3_layer))) + + if payload_len < 0: + raise Exception('Packet length is bigger than defined by frame_size* or l3_length*') + base_pkt /= '!' * payload_len + + pkt.set_packet(base_pkt) + if fix_ipv4_checksum and l3_layer.name == 'IP' and kwargs['ip_checksum'] is None: + vm_cmds.append(pkt_bld.CTRexVmDescFixIpv4(offset = 'IP')) + if vm_cmds: + pkt.add_command(pkt_bld.CTRexScRaw(vm_cmds)) + + # debug (only the base packet, without VM) + debug_filename = kwargs.get('save_to_pcap') + if type(debug_filename) is str: + pkt.dump_pkt_to_pcap(debug_filename) + #pkt.compile() + #pkt.dump_scripts() + return pkt -- cgit 1.2.3-korg