diff options
author | 2016-02-18 16:48:47 +0200 | |
---|---|---|
committer | 2016-02-18 16:48:47 +0200 | |
commit | 2c9504ac710b7ae9021601b8947069d922040a34 (patch) | |
tree | a518fd36d927126c7ceb2cbe1af078be56436d57 | |
parent | c6f710bc844e812fe448f7a2850fe15058328777 (diff) |
hltapi update: vlans (one or nested), ipv6, "imix" moved to stream builder
-rwxr-xr-x | scripts/automation/regression/unit_tests/functional_tests/hltapi_stream_builder_test.py | 198 | ||||
-rw-r--r-- | scripts/automation/regression/unit_tests/functional_tests/stl_basic_tests.py | 7 | ||||
-rwxr-xr-x | scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py | 1123 | ||||
-rw-r--r-- | scripts/exp/hlt_imix_default.pcap | bin | 0 -> 15376 bytes | |||
-rw-r--r-- | scripts/exp/hlt_udp_inc_dec_len_9k.pcap | bin | 186264 -> 93144 bytes |
5 files changed, 761 insertions, 567 deletions
diff --git a/scripts/automation/regression/unit_tests/functional_tests/hltapi_stream_builder_test.py b/scripts/automation/regression/unit_tests/functional_tests/hltapi_stream_builder_test.py index d0adb546..e76e3bb0 100755 --- a/scripts/automation/regression/unit_tests/functional_tests/hltapi_stream_builder_test.py +++ b/scripts/automation/regression/unit_tests/functional_tests/hltapi_stream_builder_test.py @@ -5,6 +5,7 @@ import unittest from trex_stl_lib.trex_stl_hltapi import STLHltStream from trex_stl_lib.trex_stl_types import validate_type from nose.plugins.attrib import attr +from nose.tools import nottest def compare_yamls(yaml1, yaml2): validate_type('yaml1', yaml1, str) @@ -12,8 +13,7 @@ def compare_yamls(yaml1, yaml2): i = 0 for line1, line2 in zip(yaml1.strip().split('\n'), yaml2.strip().split('\n')): i += 1 - if line1 != line2: - raise Exception('yamls are not equal starting from line %s:\n%s\n Golden <-> Generated\n%s' % (i, line1.strip(), line2.strip())) + assert line1 == line2, 'yamls are not equal starting from line %s:\n%s\n Golden <-> Generated\n%s' % (i, line1.strip(), line2.strip()) class CTRexHltApi_Test(unittest.TestCase): @@ -26,8 +26,18 @@ class CTRexHltApi_Test(unittest.TestCase): def tearDown(self): compare_yamls(self.golden_yaml, self.test_yaml) - # Eth/IP/TCP, all values default, no VM instructions - def test_default(self): + # Eth/IP/TCP, all values default, no VM instructions + test MACs correction + def test_hlt_basic(self): + STLHltStream(mac_src = 'a0:00:01:::01', mac_dst = '0d 00 01 00 00 01', + mac_src2 = '{00 b0 01 00 00 01}', mac_dst2 = 'd0.00.01.00.00.01') + with self.assertRaises(Exception): + STLHltStream(mac_src2 = '00:00:00:00:00:0k') + with self.assertRaises(Exception): + STLHltStream(mac_dst2 = '100:00:00:00:00:00') + # wrong encap + with self.assertRaises(Exception): + STLHltStream(l2_encap = 'ethernet_sdfgsdfg') + # all default values test_stream = STLHltStream(name = 'stream-0') self.test_yaml = test_stream.dump_to_yaml(self.yaml_save_location()) self.golden_yaml = ''' @@ -51,6 +61,16 @@ class CTRexHltApi_Test(unittest.TestCase): split_by_var: '' ''' + # Eth/IP/TCP, test L2 fields, wait for masking of variables for MAC + @nottest + def test_l2_basic(self): + test_stream = STLHltStream(name = 'stream-0') + self.test_yaml = test_stream.dump_to_yaml(self.yaml_save_location()) + self.golden_yaml = ''' +TBD +''' + + # Eth/IP/TCP, ip src and dest is changed by VM def test_ip_ranges(self): test_stream = STLHltStream(ip_src_addr = '192.168.1.1', @@ -247,12 +267,6 @@ class CTRexHltApi_Test(unittest.TestCase): # Eth/IP/TCP, packet length is changed in VM by frame_size def test_pkt_len_by_framesize(self): - # frame_size_step should be 1 (as default) - with self.assertRaises(Exception): - test_stream = STLHltStream(length_mode = 'decrement', - frame_size_min = 100, - frame_size_max = 3000, - frame_size_step = 20) # just check errors, no compare to golden STLHltStream(length_mode = 'increment', frame_size_min = 100, @@ -302,13 +316,6 @@ class CTRexHltApi_Test(unittest.TestCase): # Eth/IP/UDP, packet length is changed in VM by l3_length def test_pkt_len_by_l3length(self): - # l3_length_step should be 1 - with self.assertRaises(Exception): - STLHltStream(l4_protocol = 'udp', - length_mode = 'random', - l3_length_min = 100, - l3_length_max = 400, - l3_length_step = 20) test_stream = STLHltStream(l4_protocol = 'udp', length_mode = 'random', l3_length_min = 100, @@ -358,8 +365,163 @@ class CTRexHltApi_Test(unittest.TestCase): split_by_var: '' ''' + # Eth/IP/TCP, with vlan, no VM + def test_vlan_basic(self): + with self.assertRaises(Exception): + STLHltStream(l2_encap = 'ethernet_ii', + vlan_id = 'sdfgsdgf') + test_stream = STLHltStream(l2_encap = 'ethernet_ii') + assert ':802.1Q:' not in test_stream.get_pkt_type(), 'Default packet should not include dot1q' + + test_stream = STLHltStream(name = 'stream-0', l2_encap = 'ethernet_ii_vlan') + assert ':802.1Q:' in test_stream.get_pkt_type(), 'No dot1q in packet with encap ethernet_ii_vlan' + self.test_yaml = test_stream.dump_to_yaml(self.yaml_save_location()) + self.golden_yaml = ''' +- name: stream-0 + stream: + action_count: 0 + enabled: true + flags: 3 + isg: 0.0 + mode: + pps: 1 + type: continuous + packet: + binary: AAAAAAAAAAABAAABgQAwAAgARQAALgAAAABABrrJAAAAAMAAAAEEAABQAAAAAQAAAAFQAA/leEMAACEhISEhIQ== + meta: '' + rx_stats: + enabled: false + self_start: true + vm: + instructions: [] + split_by_var: '' +''' + + # Eth/IP/TCP, with 4 vlan + def test_vlan_multiple(self): + # default frame size should be not enough + with self.assertRaises(Exception): + STLHltStream(vlan_id = [1, 2, 3, 4]) + test_stream = STLHltStream(name = 'stream-0', frame_size = 100, vlan_id = [1, 2, 3, 4], vlan_protocol_tag_id = '8100 0x8100') + pkt_layers = test_stream.get_pkt_type() + assert ':802.1Q:802.1Q:802.1Q:802.1Q:' in pkt_layers, 'No four dot1q layers in packet: %s' % pkt_layers + self.test_yaml = test_stream.dump_to_yaml(self.yaml_save_location()) + self.golden_yaml = ''' +- name: stream-0 + stream: + action_count: 0 + enabled: true + flags: 3 + isg: 0.0 + mode: + pps: 1 + type: continuous + packet: + binary: AAAAAAAAAAABAAABgQAwAYEAMAKBADADgQAwBAgARQAARgAAAABABrqxAAAAAMAAAAEEAABQAAAAAQAAAAFQAA/l6p0AACEhISEhISEhISEhISEhISEhISEhISEhISEhISEhIQ== + meta: '' + rx_stats: + enabled: false + self_start: true + vm: + instructions: [] + split_by_var: '' +''' + + # Eth/IPv6/TCP, no VM + def test_ipv6_basic(self): + # default frame size should be not enough + with self.assertRaises(Exception): + STLHltStream(l3_protocol = 'ipv6') + # error should not affect + STLHltStream(ipv6_src_addr = 'asdfasdfasgasdf') + # error should affect + with self.assertRaises(Exception): + STLHltStream(l3_protocol = 'ipv6', ipv6_src_addr = 'asdfasdfasgasdf') + test_stream = STLHltStream(name = 'stream-0', l3_protocol = 'ipv6', length_mode = 'fixed', l3_length = 150, ) + self.test_yaml = test_stream.dump_to_yaml(self.yaml_save_location()) + self.golden_yaml = ''' +- name: stream-0 + stream: + action_count: 0 + enabled: true + flags: 3 + isg: 0.0 + mode: + pps: 1 + type: continuous + packet: + binary: AAAAAAAAAAABAAABht1gAAAAAFIGQP6AAAAAAAAAAAAAAAAAABL+gAAAAAAAAAAAAAAAAAAiBAAAUAAAAAEAAAABUAAP5Zs3AAAhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhIQ== + meta: '' + rx_stats: + enabled: false + self_start: true + vm: + instructions: [] + split_by_var: '' +''' + + # Eth/IPv6/UDP, VM on ipv6 fields + def test_ipv6_src_dst_ranges(self): + test_stream = STLHltStream(name = 'stream-0', l3_protocol = 'ipv6', l3_length = 150, l4_protocol = 'udp', + ipv6_src_addr = '1111:2222:3333:4444:5555:6666:7777:8888', + ipv6_dst_addr = '1111:1111:1111:1111:1111:1111:1111:1111', + ipv6_src_mode = 'increment', ipv6_src_step = 5, ipv6_src_count = 10, + ipv6_dst_mode = 'decrement', ipv6_dst_step = '1111:1111:1111:1111:1111:1111:0000:0011', ipv6_dst_count = 150, + ) + self.test_yaml = test_stream.dump_to_yaml(self.yaml_save_location()) + self.golden_yaml = ''' +- name: stream-0 + stream: + action_count: 0 + enabled: true + flags: 3 + isg: 0.0 + mode: + pps: 1 + type: continuous + packet: + binary: AAAAAAAAAAABAAABht1gAAAAAFIRQBERIiIzM0REVVVmZnd3iIgRERERERERERERERERERERBAAAUABSQkIhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhIQ== + meta: '' + rx_stats: + enabled: false + self_start: true + vm: + instructions: + - init_value: 2004322440 + max_value: 2004322449 + min_value: 2004322440 + name: ipv6_src + op: inc + size: 4 + step: 5 + type: flow_var + - add_value: 0 + is_big_endian: true + name: ipv6_src + pkt_offset: 34 + type: write_flow_var + - init_value: 286331153 + max_value: 286331153 + min_value: 286331004 + name: ipv6_dst + op: dec + size: 4 + step: 17 + type: flow_var + - add_value: 0 + is_big_endian: true + name: ipv6_dst + pkt_offset: 50 + type: write_flow_var + split_by_var: '' +''' + + + + + def yaml_save_location(self): - #return os.devnull + return os.devnull # debug/deveopment, comment line above return '/tmp/%s.yaml' % self._testMethodName diff --git a/scripts/automation/regression/unit_tests/functional_tests/stl_basic_tests.py b/scripts/automation/regression/unit_tests/functional_tests/stl_basic_tests.py index a2249d5a..34bd42df 100644 --- a/scripts/automation/regression/unit_tests/functional_tests/stl_basic_tests.py +++ b/scripts/automation/regression/unit_tests/functional_tests/stl_basic_tests.py @@ -187,14 +187,15 @@ class CStlBasic_Test(functional_general_test.CGeneralFunctional_Test): self.run_py_profile_path (obj[0],obj[1],compare =obj[2], do_no_remove=True) - def hlt_profiles (self): + def test_hlt_profiles (self): p = ( - ['hlt/hlt_udp_inc_dec_len_9k.py', '-m 1 -l 40', True], + ['hlt/hlt_udp_inc_dec_len_9k.py', '-m 1 -l 20', True], + ['hlt/hlt_imix_default.py', '-m 1 -l 40', True], ) for obj in p: - self.run_py_profile_path (obj[0], obj[1], compare =obj[2], do_no_remove=False) + self.run_py_profile_path (obj[0], obj[1], compare =obj[2], do_no_remove=True) # valgrind tests def test_valgrind_various_profiles (self): 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 a05e6bd9..5311884d 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 @@ -48,24 +48,40 @@ traffic_config_kwargs = { '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 ) + 'frame_size_step': 1, + 'l2_encap': 'ethernet_ii', # ( ethernet_ii | ethernet_ii_vlan ) 'mac_src': '00:00:01:00:00:01', 'mac_dst': '00:00:00:00:00:00', 'mac_src2': '00:00:01:00:00:01', 'mac_dst2': '00:00:00:00:00:00', - #'vlan': 'enable', # TODO: verify what is it exactly + 'mac_src_mode': 'fixed', # ( fixed | increment | decrement | random ) + 'mac_src_step': 1, + 'mac_src_count': 1, + 'mac_dst_mode': 'fixed', # ( fixed | increment | decrement | random ) + 'mac_dst_step': 1, + 'mac_dst_count': 1, + 'mac_src2_mode': 'fixed', # ( fixed | increment | decrement | random ) + 'mac_src2_step': 1, + 'mac_src2_count': 1, + 'mac_dst2_mode': 'fixed', # ( fixed | increment | decrement | random ) + 'mac_dst2_step': 1, + 'mac_dst2_count': 1, + # vlan options below can have multiple values for nested Dot1Q headers 'vlan_user_priority': 1, + 'vlan_priority_mode': 'fixed', # ( fixed | increment | decrement | random ) + 'vlan_priority_count': 1, + 'vlan_priority_step': 1, 'vlan_id': 0, - 'vlan_id_mode': 'increment', # ( fixed | increment) + 'vlan_id_mode': 'fixed', # ( fixed | increment | decrement | random ) 'vlan_id_count': 1, - 'vlan_id_step': 1, # has to be 1 + 'vlan_id_step': 1, 'vlan_cfi': 1, + 'vlan_protocol_tag_id': None, #L3, general - 'l3_protocol': 'ipv4', # ( ipv4 ) + 'l3_protocol': 'ipv4', # ( ipv4 | ipv6 ) 'l3_length_min': 110, 'l3_length_max': 238, - 'l3_length_step': 1, # has to be 1 + 'l3_length_step': 1, #L3, IPv4 'ip_precedence': 0, 'ip_tos_field': 0, @@ -85,10 +101,10 @@ traffic_config_kwargs = { '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_step': 1, # ip or number 'ip_src_count': 1, 'ip_dst_mode': 'fixed', # ( fixed | increment | decrement | random ) - 'ip_dst_step': 1, # has to be 1 + 'ip_dst_step': 1, # ip or number 'ip_dst_count': 1, #L3, IPv6 'ipv6_traffic_class': 0, @@ -99,11 +115,11 @@ traffic_config_kwargs = { 'ipv6_src_addr': 'fe80:0:0:0:0:0:0:12', 'ipv6_dst_addr': 'fe80:0:0:0:0:0:0:22', 'ipv6_src_mode': 'fixed', # ( fixed | increment | decrement | random ) - 'ipv6_src_step': 1, # has to be 1 - 'ipv6_src_count': 1, # we are changing only 32 lowest bits + 'ipv6_src_step': 1, # we are changing only 32 lowest bits; can be ipv6 or number + 'ipv6_src_count': 1, 'ipv6_dst_mode': 'fixed', # ( fixed | increment | decrement | random ) - 'ipv6_dst_step': 1, # has to be 1 - 'ipv6_dst_count': 1, # we are changing only 32 lowest bits + 'ipv6_dst_step': 1, # we are changing only 32 lowest bits; can be ipv6 or number + 'ipv6_dst_count': 1, #L4, TCP 'l4_protocol': 'tcp', # ( tcp | udp ) 'tcp_src_port': 1024, @@ -121,21 +137,20 @@ traffic_config_kwargs = { '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_step': 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_step': 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_step': 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_step': 1, 'udp_dst_port_count': 1, } @@ -180,8 +195,6 @@ class HLT_OK(dict): def merge_kwargs(default_kwargs, user_kwargs): kwargs = copy.deepcopy(default_kwargs) - if 'user_kwargs' not in kwargs: - kwargs['user_kwargs'] = copy.deepcopy(user_kwargs) for key, value in user_kwargs.items(): if key in kwargs: kwargs[key] = value @@ -194,18 +207,21 @@ def merge_kwargs(default_kwargs, user_kwargs): # change MACs from HLT formats {a b c d e f} or a-b-c-d-e-f or a.b.c.d.e.f to Scapy format a:b:c:d:e:f def correct_macs(kwargs): list_of_mac_args = ['mac_src', 'mac_dst', 'mac_src2', 'mac_dst2'] - for mac_arg in list_of_mac_args: + list_of_mac_steps = ['mac_src_step', 'mac_dst_step', 'mac_src2_step', 'mac_dst2_step'] + for mac_arg in list_of_mac_args + list_of_mac_steps: if mac_arg in kwargs: + if type(kwargs[mac_arg]) in (int, long) and kwargs[mac_arg] in list_of_mac_steps: # step can be number + continue if type(kwargs[mac_arg]) is not str: raise STLError('Argument %s should be str' % mac_arg) - kwargs[mac_arg] = kwargs[mac_arg].replace('{', '').replace('}', '').strip().replace('-', ':').replace(' ', ':').replace('.', ':') - kwargs[mac_arg] = ':'.join(kwargs[mac_arg].split(':')) # remove duplicate ':' if any + kwargs[mac_arg] = kwargs[mac_arg].replace('{', '').replace('}', '').strip().replace('-', ' ').replace(':', ' ').replace('.', ' ') + kwargs[mac_arg] = ':'.join(kwargs[mac_arg].split()) try: mac2str(kwargs[mac_arg]) # verify we are ok except: raise STLError('Incorrect MAC %s=%s, please use 01:23:45:67:89:10 or 01-23-45-67-89-10 or 01.23.45.67.89.10 or {01 23 45 67 89 10}' % (mac_arg, kwargs[mac_arg])) def is_true(input): - if input in (True, 'True', 'true', 1, '1', 'enable', 'Enable', 'Yes', 'yes', 'y', 'Y'): + if input in (True, 'True', 'true', 1, '1', 'enable', 'Enable', 'Yes', 'yes', 'y', 'Y', 'enabled', 'Enabled'): return True return False @@ -254,7 +270,6 @@ class CStreamsPerPort(defaultdict): if not isinstance(ports_list, list): ports_list = [ports_list] for port in ports_list: - del stream_hlt_args['port_handle'] if stream_id in self[port]: self[port][stream_id].update(stream_hlt_args) else: @@ -279,7 +294,6 @@ class CTRexHltApi(object): def __init__(self, verbose = 0): self.trex_client = None - self.connected = False self.verbose = verbose self._streams_history = {} # streams per stream_id per port in format of HLT arguments for modify later @@ -303,13 +317,13 @@ class CTRexHltApi(object): # sync = RPC, async = ZMQ 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)) + return HLT_ERR('Could not init stateless client %s: %s' % (device, e if isinstance(e, STLError) else traceback.format_exc())) + try: self.trex_client.connect() except Exception as e: self.trex_client = None - return HLT_ERR('Could not connect to device %s: %s' % (device, e)) + return HLT_ERR('Could not connect to device %s: %s' % (device, e if isinstance(e, STLError) else traceback.format_exc())) # connection successfully created with server, try acquiring ports of TRex try: @@ -317,7 +331,7 @@ class CTRexHltApi(object): 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)) + return HLT_ERR('Could not acquire ports %s: %s' % (port_list, e if isinstance(e, STLError) else traceback.format_exc())) # since only supporting single TRex at the moment, 1:1 map port_handle = self.trex_client.get_acquired_ports() @@ -330,10 +344,9 @@ class CTRexHltApi(object): self.trex_client.reset(ports = port_list) except Exception as e: self.trex_client = None - return HLT_ERR('Error in reset traffic: %s' % e) + return HLT_ERR('Error in reset traffic: %s' % e if isinstance(e, STLError) else traceback.format_exc()) self._streams_history = CStreamsPerPort(hlt_history = True) - self.connected = True return HLT_OK(port_handle = port_handle) def cleanup_session(self, **user_kwargs): @@ -347,7 +360,7 @@ class CTRexHltApi(object): else: port_list = self.parse_port_list(port_list) except Exception as e: - return HLT_ERR('Unable to determine which ports to release: %s' % e) + return HLT_ERR('Unable to determine which ports to release: %s' % e if isinstance(e, STLError) else traceback.format_exc()) try: self.trex_client.release(port_list) except Exception as e: @@ -357,12 +370,11 @@ class CTRexHltApi(object): except Exception as e: return HLT_ERR('Error disconnecting: %s' % e) self.trex_client = None - self.connected = False return HLT_OK() def interface_config(self, port_handle, mode='config'): - if not self.connected: - return HLT_ERR('connect first') + if not self.trex_client: + return HLT_ERR('Connect first') ALLOWED_MODES = ['config', 'modify', 'destroy'] if mode not in ALLOWED_MODES: return HLT_ERR('Mode must be one of the following values: %s' % ALLOWED_MODES) @@ -375,12 +387,12 @@ class CTRexHltApi(object): ########################### def traffic_config(self, **user_kwargs): - if not self.connected: - return HLT_ERR('connect first') + if not self.trex_client: + return HLT_ERR('Connect first') try: correct_macs(user_kwargs) except Exception as e: - return HLT_ERR(e) + return HLT_ERR(e if isinstance(e, STLError) else traceback.format_exc()) kwargs = merge_kwargs(traffic_config_kwargs, user_kwargs) stream_id = kwargs['stream_id'] mode = kwargs['mode'] @@ -416,7 +428,7 @@ class CTRexHltApi(object): del self._streams_history[port] return HLT_OK() except Exception as e: - return HLT_ERR('Could not reset streams at ports %s: %s' % (port_handle, e)) + return HLT_ERR('Could not reset streams at ports %s: %s' % (port_handle, e if isinstance(e, STLError) else traceback.format_exc())) if mode == 'remove': if stream_id is None: @@ -428,12 +440,12 @@ class CTRexHltApi(object): if port in self._streams_history: del self._streams_history[port] except Exception as e: - return HLT_ERR('Could not remove all streams at ports %s: %s' % (port_handle, e)) + return HLT_ERR('Could not remove all streams at ports %s: %s' % (port_handle, e if isinstance(e, STLError) else traceback.format_exc())) else: try: self._remove_stream(stream_id, port_handle) except Exception as e: - return HLT_ERR('Could not remove streams with specified by %s, error: %s' % (stream_id, e)) + return HLT_ERR('Could not remove streams with specified by %s, error: %s' % (stream_id, e if isinstance(e, STLError) else traceback.format_exc())) return HLT_OK() #if mode == 'enable': @@ -468,7 +480,7 @@ class CTRexHltApi(object): try: self.trex_client.remove_streams(stream_id, port_handle) except Exception as e: - return HLT_ERR('Could not remove stream(s) %s from port(s) %s: %s' % (stream_id, port_handle, e)) + return HLT_ERR('Could not remove stream(s) %s from port(s) %s: %s' % (stream_id, port_handle, e if isinstance(e, STLError) else traceback.format_exc())) if mode == 'create' or mode == 'modify': # create a new stream with desired attributes, starting by creating packet @@ -504,70 +516,16 @@ class CTRexHltApi(object): raise STLError('Could not create bidirectional stream 2: %s' % res2['log']) streams_per_port.add_streams_from_res(res2) except Exception as e: - return HLT_ERR('Could not generate bidirectional traffic: %s' % e) + return HLT_ERR('Could not generate bidirectional traffic: %s' % e if isinstance(e, STLError) else traceback.format_exc()) if mode == 'create': return HLT_OK(stream_id = streams_per_port) else: return HLT_OK() - if kwargs['length_mode'] == 'imix': # several streams with given length - try: - user_kwargs['length_mode'] = 'fixed' - if kwargs['l3_imix1_size'] < 32 or kwargs['l3_imix2_size'] < 32 or kwargs['l3_imix3_size'] < 32 or kwargs['l3_imix4_size'] < 32: - return HLT_ERR('l3_imix*_size should be at least 32') - total_rate = kwargs['l3_imix1_ratio'] + kwargs['l3_imix2_ratio'] + kwargs['l3_imix3_ratio'] + kwargs['l3_imix4_ratio'] - if total_rate == 0: - return HLT_ERR('Used length_mode imix, but all the ratio are 0') - save_to_yaml = kwargs.get('save_to_yaml') - rate_pps = float(kwargs['rate_pps']) - if kwargs['l3_imix1_ratio'] > 0: - if save_to_yaml and type(save_to_yaml) is str: - user_kwargs['save_to_yaml'] = save_to_yaml.replace('.yaml', '_imix1.yaml') - user_kwargs['frame_size'] = kwargs['l3_imix1_size'] - user_kwargs['rate_pps'] = rate_pps * kwargs['l3_imix1_ratio'] / total_rate - res = self.traffic_config(**user_kwargs) - if res['status'] == 0: - return HLT_ERR('Could not create stream imix1: %s' % res['log']) - streams_per_port.add_streams_from_res(res) - - if kwargs['l3_imix2_ratio'] > 0: - if save_to_yaml and type(save_to_yaml) is str: - user_kwargs['save_to_yaml'] = save_to_yaml.replace('.yaml', '_imix2.yaml') - user_kwargs['frame_size'] = kwargs['l3_imix2_size'] - user_kwargs['rate_pps'] = rate_pps * kwargs['l3_imix2_ratio'] / total_rate - res = self.traffic_config(**user_kwargs) - if res['status'] == 0: - return HLT_ERR('Could not create stream imix2: %s' % res['log']) - streams_per_port.add_streams_from_res(res) - if kwargs['l3_imix3_ratio'] > 0: - if save_to_yaml and type(save_to_yaml) is str: - kwargs['save_to_yaml'] = save_to_yaml.replace('.yaml', '_imix3.yaml') - user_kwargs['frame_size'] = kwargs['l3_imix3_size'] - user_kwargs['rate_pps'] = rate_pps * kwargs['l3_imix3_ratio'] / total_rate - res = self.traffic_config(**user_kwargs) - if res['status'] == 0: - return HLT_ERR('Could not create stream imix3: %s' % res['log']) - streams_per_port.add_streams_from_res(res) - if kwargs['l3_imix4_ratio'] > 0: - if save_to_yaml and type(save_to_yaml) is str: - user_kwargs['save_to_yaml'] = save_to_yaml.replace('.yaml', '_imix4.yaml') - user_kwargs['frame_size'] = kwargs['l3_imix4_size'] - user_kwargs['rate_pps'] = rate_pps * kwargs['l3_imix4_ratio'] / total_rate - res = self.traffic_config(**user_kwargs) - if res['status'] == 0: - return HLT_ERR('Could not create stream imix4: %s' % res['log']) - streams_per_port.add_streams_from_res(res) - except Exception as e: - return HLT_ERR('Could not generate imix streams: %s' % e) - if mode == 'create': - return HLT_OK(stream_id = streams_per_port) - else: - return HLT_OK() try: stream_obj = STLHltStream(**user_kwargs) - print stream_obj except Exception as e: - return HLT_ERR('Could not create stream: %s' % e) + return HLT_ERR('Could not create stream: %s' % e if isinstance(e, STLError) else traceback.format_exc()) # try adding the stream per ports try: @@ -576,17 +534,17 @@ class CTRexHltApi(object): for port in port_handle: self._streams_history.save_stream_args(port_handle, stream_id_arr[0], user_kwargs) except Exception as e: - return HLT_ERR('Could not add stream to ports: %s' % e) + return HLT_ERR('Could not add stream to ports: %s' % e if isinstance(e, STLError) else traceback.format_exc()) if mode == 'create': - return HLT_OK(stream_id = dict((port, stream_id_arr) for port in port_handle)) + return HLT_OK(stream_id = dict((port, stream_id_arr[0]) for port in port_handle)) else: return HLT_OK() return HLT_ERR('Got to the end of traffic_config, mode not implemented or forgot "return" somewhere.') def traffic_control(self, **user_kwargs): - if not self.connected: - return HLT_ERR('connect first') + if not self.trex_client: + return HLT_ERR('Connect first') kwargs = merge_kwargs(traffic_control_kwargs, user_kwargs) action = kwargs['action'] port_handle = kwargs['port_handle'] @@ -597,19 +555,17 @@ class CTRexHltApi(object): port_handle = [port_handle] if action == 'run': - try: self.trex_client.start(ports = port_handle) except Exception as e: - return HLT_ERR('Could not start traffic: %s' % e) + return HLT_ERR('Could not start traffic: %s' % e if isinstance(e, STLError) else traceback.format_exc()) return HLT_OK(stopped = 0) elif action == 'stop': - try: self.trex_client.stop(ports = port_handle) except Exception as e: - return HLT_ERR('Could not start traffic: %s' % e) + return HLT_ERR('Could not start traffic: %s' % e if isinstance(e, STLError) else traceback.format_exc()) return HLT_OK(stopped = 1) else: return HLT_ERR("Action '{0}' is not supported yet on TRex".format(action)) @@ -618,8 +574,8 @@ class CTRexHltApi(object): return HLT_ERR("Probably action '%s' is not implemented" % action) def traffic_stats(self, **user_kwargs): - if not self.connected: - return HLT_ERR('connect first') + if not self.trex_client: + return HLT_ERR('Connect first') kwargs = merge_kwargs(traffic_stats_kwargs, user_kwargs) mode = kwargs['mode'] port_handle = kwargs['port_handle'] @@ -633,7 +589,7 @@ class CTRexHltApi(object): try: stats = self.trex_client.get_stats(port_handle) except Exception as e: - return HLT_ERR('Could not retrieve stats: %s' % e) + return HLT_ERR('Could not retrieve stats: %s' % e if isinstance(e, STLError) else traceback.format_exc()) for port_id, stat_dict in stats.iteritems(): if type(port_id) in (int, long): hlt_stats_dict[port_id] = { @@ -726,444 +682,519 @@ class CTRexHltApi(object): return '\n'. join([str(response) for response in responses]) return responses -class STLHltStream(STLStream): - def __init__(self, **user_kwargs): - kwargs = merge_kwargs(traffic_config_kwargs, user_kwargs) - try: - packet = STLHltStream.generate_packet(**user_kwargs) - except Exception as e: - raise STLError('Could not generate packet: %s' % e) - - try: - transmit_mode = kwargs['transmit_mode'] - rate_pps = kwargs['rate_pps'] - pkts_per_burst = kwargs['pkts_per_burst'] - if transmit_mode == 'continuous': - transmit_mode_class = STLTXCont(pps = rate_pps) - elif transmit_mode == 'single_burst': - transmit_mode_class = STLTXSingleBurst(pps = rate_pps, total_pkts = pkts_per_burst) - elif transmit_mode == 'multi_burst': - transmit_mode_class = STLTXMultiBurst(pps = rate_pps, total_pkts = pkts_per_burst, - count = kwargs['burst_loop_count'], ibg = kwargs['inter_burst_gap']) - else: - raise STLError('transmit_mode %s not supported/implemented') - except Exception as e: - raise STLError('Could not create transmit_mode class %s: %s' % (transmit_mode, e)) - - try: - STLStream.__init__(self, - packet = packet, - #enabled = True, - #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'), - ) - except Exception as e: - raise STLError('Could not create stream: %s' % e) - - debug_filename = kwargs.get('save_to_yaml') - if type(debug_filename) is str: - print 'saving to %s' % debug_filename - self.dump_to_yaml(debug_filename) - - @staticmethod - def generate_packet(**user_kwargs): - kwargs = merge_kwargs(traffic_config_kwargs, user_kwargs) - #return Eth()/IPv6()/TCP - vm_cmds = [] - fix_ipv4_checksum = False - - ### L2 ### - if kwargs['l2_encap'] in ('ethernet_ii', 'ethernet_ii_vlan'): - #fields_desc = [ MACField("dst","00:00:00:01:00:00"), - # MACField("src","00:00:00:02:00:00"), - # XShortEnumField("type", 0x9000, ETHER_TYPES) ] - l2_layer = Ether(src = kwargs['mac_src'], dst = kwargs['mac_dst']) - if kwargs['l2_encap'] == 'ethernet_ii_vlan': - #fields_desc = [ BitField("prio", 0, 3), - # BitField("id", 0, 1), - # BitField("vlan", 1, 12), - # XShortEnumField("type", 0x0000, ETHER_TYPES) ] - l2_layer /= Dot1Q(prio = kwargs['vlan_user_priority'], - vlan = kwargs['vlan_id'], - id = kwargs['vlan_cfi'], - ) - # vlan VM - if kwargs['vlan_id_mode'] != 'fixed': - if kwargs['vlan_id_step'] != 1: - raise STLError('vlan_id_step has to be 1 (TRex limitation)') - if kwargs['vlan_id_count'] < 1: - raise STLError('vlan_id_count has to be at least 1') - if kwargs['vlan_id_count'] > 1: - raise STLError('vlan_id VM not supported yet, waiting for bitmask from stateless') - if kwargs['vlan_id_mode'] == 'increment': - vm_cmds.append(CTRexVmDescFlowVar(name = 'vlan_id', size = 4, op = 'inc', - 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 = 'vlan_id', size = 4, op = 'dec', - 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 = 'vlan_id', size = 4, op = 'random', - min_value = kwargs['vlan_id'], - max_value = kwargs['vlan_id'] + kwargs['vlan_id_count'] - 1)) - else: - raise STLError('vlan_id_mode %s is not supported' % kwargs['vlan_id_mode']) - vm_cmds.append(CTRexVmDescWrFlowVar(fv_name='vlan_id', pkt_offset = 'Eth.vlan_id')) - +def STLHltStream(**user_kwargs): + kwargs = merge_kwargs(traffic_config_kwargs, user_kwargs) + if kwargs['length_mode'] == 'imix': # several streams with given length + streams_arr = [] + user_kwargs['length_mode'] = 'fixed' + if kwargs['l3_imix1_size'] < 32 or kwargs['l3_imix2_size'] < 32 or kwargs['l3_imix3_size'] < 32 or kwargs['l3_imix4_size'] < 32: + raise STLError('l3_imix*_size should be at least 32') + total_rate = kwargs['l3_imix1_ratio'] + kwargs['l3_imix2_ratio'] + kwargs['l3_imix3_ratio'] + kwargs['l3_imix4_ratio'] + if total_rate == 0: + raise STLError('Used length_mode imix, but all the ratios are 0') + save_to_yaml = kwargs.get('save_to_yaml') + rate_pps = float(kwargs['rate_pps']) + if kwargs['l3_imix1_ratio'] > 0: + if save_to_yaml and type(save_to_yaml) is str: + user_kwargs['save_to_yaml'] = save_to_yaml.replace('.yaml', '_imix1.yaml') + user_kwargs['frame_size'] = kwargs['l3_imix1_size'] + user_kwargs['rate_pps'] = rate_pps * kwargs['l3_imix1_ratio'] / total_rate + streams_arr.append(STLHltStream(**user_kwargs)) + if kwargs['l3_imix2_ratio'] > 0: + if save_to_yaml and type(save_to_yaml) is str: + user_kwargs['save_to_yaml'] = save_to_yaml.replace('.yaml', '_imix2.yaml') + user_kwargs['frame_size'] = kwargs['l3_imix2_size'] + user_kwargs['rate_pps'] = rate_pps * kwargs['l3_imix2_ratio'] / total_rate + streams_arr.append(STLHltStream(**user_kwargs)) + if kwargs['l3_imix3_ratio'] > 0: + if save_to_yaml and type(save_to_yaml) is str: + user_kwargs['save_to_yaml'] = save_to_yaml.replace('.yaml', '_imix3.yaml') + user_kwargs['frame_size'] = kwargs['l3_imix3_size'] + user_kwargs['rate_pps'] = rate_pps * kwargs['l3_imix3_ratio'] / total_rate + streams_arr.append(STLHltStream(**user_kwargs)) + if kwargs['l3_imix4_ratio'] > 0: + if save_to_yaml and type(save_to_yaml) is str: + user_kwargs['save_to_yaml'] = save_to_yaml.replace('.yaml', '_imix4.yaml') + user_kwargs['frame_size'] = kwargs['l3_imix4_size'] + user_kwargs['rate_pps'] = rate_pps * kwargs['l3_imix4_ratio'] / total_rate + streams_arr.append(STLHltStream(**user_kwargs)) + return streams_arr + + # packet generation + packet = generate_packet(**user_kwargs) + try: + transmit_mode = kwargs['transmit_mode'] + rate_pps = kwargs['rate_pps'] + pkts_per_burst = kwargs['pkts_per_burst'] + if transmit_mode == 'continuous': + transmit_mode_class = STLTXCont(pps = rate_pps) + elif transmit_mode == 'single_burst': + transmit_mode_class = STLTXSingleBurst(pps = rate_pps, total_pkts = pkts_per_burst) + elif transmit_mode == 'multi_burst': + transmit_mode_class = STLTXMultiBurst(pps = rate_pps, total_pkts = pkts_per_burst, + count = kwargs['burst_loop_count'], ibg = kwargs['inter_burst_gap']) else: - raise NotImplementedError("l2_encap does not support the desired encapsulation '%s'" % kwargs['l2_encap']) - base_pkt = l2_layer - - ### L3 ### - if kwargs['l3_protocol'] == 'ipv4': - #fields_desc = [ BitField("version" , 4 , 4), - # BitField("ihl", None, 4), - # XByteField("tos", 0), - # ShortField("len", None), - # ShortField("id", 1), - # FlagsField("flags", 0, 3, ["MF","DF","evil"]), - # BitField("frag", 0, 13), - # ByteField("ttl", 64), - # ByteEnumField("proto", 0, IP_PROTOS), - # XShortField("chksum", None), - # 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) ] - # TODO: define way to pick TOS arguments - l3_layer = IP(#tos = kwargs['ip_precedence'] << 5 + kwargs['ip_tos_field'] << 2 + kwargs['ip_mbz'], - #tos = kwargs['ip_precedence'] << 5 + kwargs['ip_delay'] << 4 + kwargs['ip_throughput'] << 3 + kwargs['ip_reliability'] << 2 + kwargs['ip_cost'] << 1 + kwargs['ip_reserved'] - tos = kwargs['ip_dscp'] << 2 + kwargs['ip_cu'], - len = 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': - if kwargs['ip_src_step'] != 1: - raise STLError('ip_src_step has to be 1 (TRex limitation)') - if kwargs['ip_src_count'] < 1: - raise STLError('ip_src_count has to be at least 1') - if kwargs['ip_src_count'] > 1: - fix_ipv4_checksum = True - ip_src_addr_num = ipv4_str_to_num(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 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_step'] != 1: - raise STLError('ip_dst_step has to be 1 (TRex limitation)') - if kwargs['ip_dst_count'] < 1: - raise STLError('ip_dst_count has to be at least 1') - if kwargs['ip_dst_count'] > 1: - fix_ipv4_checksum = True - ip_dst_addr_num = ipv4_str_to_num(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 STLError('ip_dst_mode %s is not supported' % kwargs['ip_dst_mode']) - vm_cmds.append(CTRexVmDescWrFlowVar(fv_name='ip_dst', pkt_offset = 'IP.dst')) - elif kwargs['l3_protocol'] == 'ipv6': - #fields_desc = [ BitField("version" , 6 , 4), - # BitField("tc", 0, 8), #TODO: IPv6, ByteField ? - # BitField("fl", 0, 20), - # ShortField("plen", None), - # ByteEnumField("nh", 59, ipv6nh), - # ByteField("hlim", 64), - # IP6Field("dst", "::2"), - # #SourceIP6Field("src", "dst"), # dst is for src @ selection - # IP6Field("src", "::1") ] - ipv6_kwargs = {'tc': kwargs['ipv6_traffic_class'], - 'fl': kwargs['ipv6_flow_label'], - 'plen': kwargs['ipv6_length'], - 'hlim': kwargs['ipv6_hop_limit'], - 'src': kwargs['ipv6_src_addr'], - 'dst': kwargs['ipv6_dst_addr']} - 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_step'] != 1: - raise STLError('ipv6_src_step has to be 1 (TRex limitation)') - if kwargs['ipv6_src_count'] < 1: - raise STLError('ipv6_src_count has to be at least 1') - if kwargs['ipv6_src_count'] > 1: - ipv6_src_addr_num = ipv4_str_to_num(is_valid_ipv6(kwargs['ipv6_src_addr'])[-4:]) - if kwargs['ipv6_src_mode'] == 'increment': - vm_cmds.append(CTRexVmDescFlowVar(name = 'ipv6_src', size = 4, op = 'inc', - min_value = ipv6_src_addr_num, - max_value = ipv6_src_addr_num + kwargs['ipv6_src_count'] - 1)) - elif kwargs['ipv6_src_mode'] == 'decrement': - vm_cmds.append(CTRexVmDescFlowVar(name = 'ipv6_src', size = 4, op = 'dec', - min_value = ipv6_src_addr_num - kwargs['ipv6_src_count'] + 1, - 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)) - 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_step'] != 1: - raise STLError('ipv6_dst_step has to be 1 (TRex limitation)') - if kwargs['ipv6_dst_count'] < 1: - raise STLError('ipv6_dst_count has to be at least 1') - if kwargs['ipv6_dst_count'] > 1: - ipv6_dst_addr_num = ipv4_str_to_num(is_valid_ipv6(kwargs['ipv6_dst_addr'])[-4:]) - if kwargs['ipv6_dst_mode'] == 'increment': - vm_cmds.append(CTRexVmDescFlowVar(name = 'ipv6_dst', size = 4, op = 'inc', - min_value = ipv6_dst_addr_num, - max_value = ipv6_dst_addr_num + kwargs['ipv6_dst_count'] - 1)) - elif kwargs['ipv6_dst_mode'] == 'decrement': - vm_cmds.append(CTRexVmDescFlowVar(name = 'ipv6_dst', size = 4, op = 'dec', - min_value = ipv6_dst_addr_num - kwargs['ipv6_dst_count'] + 1, - 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)) - 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)) - - else: - raise NotImplementedError("l3_protocol '%s' is not supported by TRex yet." % kwargs['l3_protocol']) - base_pkt /= l3_layer - - ### L4 ### - if kwargs['l4_protocol'] == 'tcp': - #fields_desc = [ ShortEnumField("sport", 20, TCP_SERVICES), - # ShortEnumField("dport", 80, TCP_SERVICES), - # IntField("seq", 0), - # IntField("ack", 0), - # BitField("dataofs", None, 4), - # BitField("reserved", 0, 4), - # FlagsField("flags", 0x2, 8, "FSRPAUEC"), - # ShortField("window", 8192), - # XShortField("chksum", None), - # ShortField("urgptr", 0), - # TCPOptionsField("options", {}) ] - 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 = 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'], + raise STLError('transmit_mode %s not supported/implemented') + except Exception as e: + raise STLError('Could not create transmit_mode class %s: %s' % (transmit_mode, e if isinstance(e, STLError) else traceback.format_exc())) + + # stream generation + try: + stream = STLStream(packet = packet, + #enabled = True, + #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'), ) - # TCP VM - if kwargs['tcp_src_port_count'] != 1: - if kwargs['tcp_src_port_step'] != 1: - raise STLError('tcp_src_port_step has to be 1 (TRex limitation)') - if kwargs['tcp_src_port_count'] < 1: - raise STLError('tcp_src_port_count has to be at least 1') - if kwargs['tcp_src_port_count'] > 1: - fix_ipv4_checksum = True - 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 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_step'] != 1: - raise STLError('tcp_dst_port_step has to be 1 (TRex limitation)') - if kwargs['tcp_dst_port_count'] < 1: - raise STLError('tcp_dst_port_count has to be at least 1') - if kwargs['tcp_dst_port_count'] > 1: - fix_ipv4_checksum = True - 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 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')) - - - 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 = 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: - if kwargs['udp_src_port_step'] != 1: - raise STLError('udp_src_port_step has to be 1 (TRex limitation)') - if kwargs['udp_src_port_count'] < 1: - raise STLError('udp_src_port_count has to be at least 1') - if kwargs['udp_src_port_count'] > 1: - fix_ipv4_checksum = True - 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 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_step'] != 1: - raise STLError('udp_dst_port_step has to be 1 (TRex limitation)') - if kwargs['udp_dst_port_count'] < 1: - raise STLError('udp_dst_port_count has to be at least 1') - if kwargs['udp_dst_port_count'] > 1: - fix_ipv4_checksum = True - 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 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')) - else: - raise NotImplementedError("l4_protocol '%s' is not supported by TRex yet." % kwargs['l3_protocol']) - base_pkt /= l4_layer - - trim_dict = {'increment': 'inc', 'decrement': 'dec', 'random': 'random'} - length_mode = kwargs['length_mode'] - if length_mode == 'auto': - payload_len = 0 - elif length_mode == 'fixed': - if 'frame_size' in user_kwargs: - payload_len = kwargs['frame_size'] - len(base_pkt) - elif 'l3_length' in user_kwargs: - payload_len = kwargs['l3_length'] - len(base_pkt) - len(l2_layer) - else: # default - payload_len = kwargs['frame_size'] - len(base_pkt) - elif length_mode == 'imix': - raise STLError("Should not use length_mode 'imix' directly in packet building, split it to each stream at higher levels.") - elif length_mode in trim_dict: - if kwargs['frame_size_step'] != 1 or kwargs['l3_length_step'] != 1: - raise STLError('frame_size_step and l3_length_step has to be 1 (TRex limitation)') - if 'frame_size_min' in user_kwargs or 'frame_size_max' in user_kwargs: # size is determined by L2, higher priority over L3 size - if kwargs['frame_size_min'] < 44 or kwargs['frame_size_max'] < 44: - raise STLError('frame_size_min and frame_size_max should be at least 44') - if kwargs['frame_size_min'] > kwargs['frame_size_max']: - raise STLError('frame_size_min is bigger than frame_size_max') - if kwargs['frame_size_min'] != kwargs['frame_size_max']: - fix_ipv4_checksum = True - vm_cmds.append(CTRexVmDescFlowVar(name = 'pkt_len', size = 2, op = trim_dict[length_mode], - min_value = kwargs['frame_size_min'], - max_value = kwargs['frame_size_max'])) - vm_cmds.append(CTRexVmDescTrimPktSize('pkt_len')) - payload_len = kwargs['frame_size_max'] - len(base_pkt) - else: # size is determined by L3 - if kwargs['l3_length_min'] < 40 or kwargs['l3_length_max'] < 40: - raise STLError('l3_length_min and l3_length_max should be at least 40') - if kwargs['l3_length_min'] > kwargs['l3_length_max']: - raise STLError('l3_length_min is bigger than l3_length_max') - if kwargs['l3_length_min'] != kwargs['l3_length_max']: - fix_ipv4_checksum = True - vm_cmds.append(CTRexVmDescFlowVar(name = 'pkt_len', size = 2, op = trim_dict[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) + except Exception as e: + raise STLError('Could not create stream: %s' % e if isinstance(e, STLError) else traceback.format_exc()) + + debug_filename = kwargs.get('save_to_yaml') + if type(debug_filename) is str: + print 'saving to %s' % debug_filename + stream.dump_to_yaml(debug_filename) + return stream + +def generate_packet(**user_kwargs): + correct_macs(user_kwargs) + kwargs = merge_kwargs(traffic_config_kwargs, user_kwargs) + + vm_cmds = [] + fix_ipv4_checksum = False + + ### L2 ### + if kwargs['l2_encap'] in ('ethernet_ii', 'ethernet_ii_vlan'): + #fields_desc = [ MACField("dst","00:00:00:01:00:00"), + # MACField("src","00:00:00:02:00:00"), + # 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 + + 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)): + dot1q_kwargs = {'prio': vlan_kwargs['vlan_user_priority'], + 'vlan': vlan_kwargs['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'] + l2_layer /= Dot1Q(**dot1q_kwargs) + # vlan VM + if vlan_kwargs['vlan_id_mode'] != 'fixed': + if vlan_kwargs['vlan_id_count'] < 1: + raise STLError('vlan_id_count has to be at least 1') + if kwargs['vlan_id_count'] > 1: + 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)) + 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)) + else: + raise NotImplementedError("l2_encap does not support the desired encapsulation '%s'" % kwargs['l2_encap']) + base_pkt = l2_layer + + ### L3 ### + if kwargs['l3_protocol'] == 'ipv4': + #fields_desc = [ BitField("version" , 4 , 4), + # BitField("ihl", None, 4), + # XByteField("tos", 0), + # ShortField("len", None), + # ShortField("id", 1), + # FlagsField("flags", 0, 3, ["MF","DF","evil"]), + # BitField("frag", 0, 13), + # ByteField("ttl", 64), + # ByteEnumField("proto", 0, IP_PROTOS), + # XShortField("chksum", None), + # 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) ] + 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), + len = 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': + if kwargs['ip_src_count'] < 1: + raise STLError('ip_src_count has to be at least 1') + if kwargs['ip_src_count'] > 1: + fix_ipv4_checksum = True + ip_src_addr_num = ipv4_str_to_num(is_valid_ipv4(kwargs['ip_src_addr'])) + 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)) + 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)) + 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 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: + raise STLError('ip_dst_count has to be at least 1') + if kwargs['ip_dst_count'] > 1: + fix_ipv4_checksum = True + ip_dst_addr_num = ipv4_str_to_num(is_valid_ipv4(kwargs['ip_dst_addr'])) + 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)) + 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)) + 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 STLError('ip_dst_mode %s is not supported' % kwargs['ip_dst_mode']) + vm_cmds.append(CTRexVmDescWrFlowVar(fv_name='ip_dst', pkt_offset = 'IP.dst')) + elif kwargs['l3_protocol'] == 'ipv6': + #fields_desc = [ BitField("version" , 6 , 4), + # BitField("tc", 0, 8), #TODO: IPv6, ByteField ? + # BitField("fl", 0, 20), + # ShortField("plen", None), + # ByteEnumField("nh", 59, ipv6nh), + # ByteField("hlim", 64), + # IP6Field("dst", "::2"), + # #SourceIP6Field("src", "dst"), # dst is for src @ selection + # IP6Field("src", "::1") ] + ipv6_kwargs = {'tc': kwargs['ipv6_traffic_class'], + 'fl': kwargs['ipv6_flow_label'], + 'plen': kwargs['ipv6_length'], + 'hlim': kwargs['ipv6_hop_limit'], + 'src': kwargs['ipv6_src_addr'], + 'dst': kwargs['ipv6_dst_addr']} + 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: + raise STLError('ipv6_src_count has to be at least 1') + if kwargs['ipv6_src_count'] > 1: + 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 + 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)) + 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, + 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)) + 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: + raise STLError('ipv6_dst_count has to be at least 1') + if kwargs['ipv6_dst_count'] > 1: + 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 + 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)) + 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, + 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)) + 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)) + + else: + raise NotImplementedError("l3_protocol '%s' is not supported by TRex yet." % kwargs['l3_protocol']) + base_pkt /= l3_layer + + ### L4 ### + if kwargs['l4_protocol'] == 'tcp': + #fields_desc = [ ShortEnumField("sport", 20, TCP_SERVICES), + # ShortEnumField("dport", 80, TCP_SERVICES), + # IntField("seq", 0), + # IntField("ack", 0), + # BitField("dataofs", None, 4), + # BitField("reserved", 0, 4), + # FlagsField("flags", 0x2, 8, "FSRPAUEC"), + # ShortField("window", 8192), + # XShortField("chksum", None), + # ShortField("urgptr", 0), + # TCPOptionsField("options", {}) ] + 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 = 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: + if kwargs['tcp_src_port_count'] < 1: + raise STLError('tcp_src_port_count has to be at least 1') + if kwargs['tcp_src_port_count'] > 1: + 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)) + 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, + 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 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: + raise STLError('tcp_dst_port_count has to be at least 1') + if kwargs['tcp_dst_port_count'] > 1: + 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)) + 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, + 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 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')) + + 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 = UDP(sport = kwargs['udp_src_port'], + 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: + raise STLError('udp_src_port_count has to be at least 1') + if kwargs['udp_src_port_count'] > 1: + 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)) + 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, + 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 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: + raise STLError('udp_dst_port_count has to be at least 1') + if kwargs['udp_dst_port_count'] > 1: + 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)) + 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, + 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 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')) + else: + raise NotImplementedError("l4_protocol '%s' is not supported by TRex yet." % kwargs['l3_protocol']) + base_pkt /= l4_layer + + trim_dict = {'increment': 'inc', 'decrement': 'dec', 'random': 'random'} + length_mode = kwargs['length_mode'] + if length_mode == 'auto': + payload_len = 0 + elif length_mode == 'fixed': + if 'frame_size' in user_kwargs: + payload_len = kwargs['frame_size'] - len(base_pkt) + elif 'l3_length' in user_kwargs: + payload_len = kwargs['l3_length'] - len(base_pkt) - len(l2_layer) + else: # default + payload_len = kwargs['frame_size'] - len(base_pkt) + elif length_mode == 'imix': + raise STLError("length_mode 'imix' should be treated at stream creating level.") + elif length_mode in trim_dict: + if 'frame_size_min' in user_kwargs or 'frame_size_max' in user_kwargs: # size is determined by L2, higher priority over L3 size + if kwargs['frame_size_min'] < 44 or kwargs['frame_size_max'] < 44: + raise STLError('frame_size_min and frame_size_max should be at least 44') + if kwargs['frame_size_min'] > kwargs['frame_size_max']: + raise STLError('frame_size_min is bigger than frame_size_max') + if kwargs['frame_size_min'] != kwargs['frame_size_max']: + fix_ipv4_checksum = True + vm_cmds.append(CTRexVmDescFlowVar(name = 'pkt_len', size = 2, op = trim_dict[length_mode], step = kwargs['frame_size_step'], + min_value = kwargs['frame_size_min'], + max_value = kwargs['frame_size_max'])) vm_cmds.append(CTRexVmDescTrimPktSize('pkt_len')) + payload_len = kwargs['frame_size_max'] - len(base_pkt) + else: # size is determined by L3 + if kwargs['l3_length_min'] < 40 or kwargs['l3_length_max'] < 40: + raise STLError('l3_length_min and l3_length_max should be at least 40') + if kwargs['l3_length_min'] > kwargs['l3_length_max']: + raise STLError('l3_length_min is bigger than l3_length_max') + if kwargs['l3_length_min'] != kwargs['l3_length_max']: + fix_ipv4_checksum = True + vm_cmds.append(CTRexVmDescFlowVar(name = 'pkt_len', size = 2, op = trim_dict[length_mode], step = kwargs['l3_length_step'], + 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(CTRexVmDescTrimPktSize('pkt_len')) + + 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 = 'pkt_len', pkt_offset = 'IP.len', add_val = -len(l2_layer))) + if l4_layer.name == 'UDP': + vm_cmds.append(CTRexVmDescWrFlowVar(fv_name = 'pkt_len', pkt_offset = 'UDP.len', add_val = -len(l2_layer) - len(l3_layer))) + else: + raise STLError('length_mode should be one of the following: %s' % ['auto', 'fixed'] + trim_dict.keys()) + + if payload_len < 0: + raise STLError('Packet length is bigger than defined by frame_size* or l3_length*. We got payload size %s' % payload_len) + base_pkt /= '!' * payload_len + + pkt = STLPktBuilder() + pkt.set_packet(base_pkt) + 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)) + + # 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) + return pkt + +def get_TOS(user_kwargs, kwargs): + TOS0 = set(['ip_precedence', 'ip_tos_field', 'ip_mbz']) + TOS1 = set(['ip_precedence', 'ip_delay', 'ip_throughput', 'ip_reliability', 'ip_cost', 'ip_reserved']) + TOS2 = set(['ip_dscp', 'ip_cu']) + user_args = set(user_kwargs.keys()) + if user_args & (TOS1 - TOS0) and user_args & (TOS0 - TOS1): + raise STLError('You have mixed %s and %s TOS parameters' % (TOS0, TOS1)) + if user_args & (TOS2 - TOS0) and user_args & (TOS0 - TOS2): + raise STLError('You have mixed %s and %s TOS parameters' % (TOS0, TOS2)) + if user_args & (TOS2 - TOS1) and user_args & (TOS1 - TOS2): + raise STLError('You have mixed %s and %s TOS parameters' % (TOS1, TOS2)) + if user_args & (TOS0 - TOS1 - TOS2): + return (kwargs['ip_precedence'] << 5) + (kwargs['ip_tos_field'] << 2) + kwargs['ip_mbz'] + if user_args & (TOS1 - TOS2): + return (kwargs['ip_precedence'] << 5) + (kwargs['ip_delay'] << 4) + (kwargs['ip_throughput'] << 3) + (kwargs['ip_reliability'] << 2) + (kwargs['ip_cost'] << 1) + kwargs['ip_reserved'] + return (kwargs['ip_dscp'] << 2) + kwargs['ip_cu'] + +def vlan_in_args(user_kwargs): + for arg in user_kwargs: + if arg.startswith('vlan_'): + return True + return False + +def split_vlan_arg(vlan_arg): + if type(vlan_arg) is list: + return vlan_arg + if type(vlan_arg) in (int, long, type(None)): + return [vlan_arg] + if type(vlan_arg) is str: + return vlan_arg.replace('{', '').replace('}', '').strip().split() + raise STLError('vlan argument invalid (expecting list, int, long, str, None): %s' % vlan_arg) + +def split_vlan_args(kwargs): + vlan_args_dict = {} + 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(): + for i in range(dot1q_headers_count): + if len(value) > i: + vlan_args_per_header[i][arg] = value[i] + else: + vlan_args_per_header[i][arg] = traffic_config_kwargs[arg] + return vlan_args_per_header - 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 = 'pkt_len', pkt_offset = 'IP.len', add_val = -len(l2_layer))) - if l4_layer.name == 'UDP': - vm_cmds.append(CTRexVmDescWrFlowVar(fv_name = 'pkt_len', pkt_offset = 'UDP.len', add_val = -len(l2_layer) - len(l3_layer))) - else: - raise STLError('length_mode should be one of the following: %s' % ['auto', 'fixed'] + trim_dict.keys()) - - if payload_len < 0: - raise STLError('Packet length is bigger than defined by frame_size* or l3_length*. We got payload size %s' % payload_len) - base_pkt /= '!' * payload_len - - pkt = STLPktBuilder() - pkt.set_packet(base_pkt) - 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)) - - # 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) - return pkt diff --git a/scripts/exp/hlt_imix_default.pcap b/scripts/exp/hlt_imix_default.pcap Binary files differnew file mode 100644 index 00000000..eb124acb --- /dev/null +++ b/scripts/exp/hlt_imix_default.pcap diff --git a/scripts/exp/hlt_udp_inc_dec_len_9k.pcap b/scripts/exp/hlt_udp_inc_dec_len_9k.pcap Binary files differindex 295a2def..3ceead39 100644 --- a/scripts/exp/hlt_udp_inc_dec_len_9k.pcap +++ b/scripts/exp/hlt_udp_inc_dec_len_9k.pcap |