From bdc690e8229808974a8f899e145931c06db6e082 Mon Sep 17 00:00:00 2001 From: Yaroslav Brustinov Date: Mon, 1 Feb 2016 14:18:14 +0200 Subject: HTLAPI update --- .../trex_control_plane/client/trex_hltapi.py | 233 +++++++++++++-------- .../client/trex_stateless_client.py | 4 + 2 files changed, 155 insertions(+), 82 deletions(-) diff --git a/scripts/automation/trex_control_plane/client/trex_hltapi.py b/scripts/automation/trex_control_plane/client/trex_hltapi.py index 4a43f66b..59873d49 100755 --- a/scripts/automation/trex_control_plane/client/trex_hltapi.py +++ b/scripts/automation/trex_control_plane/client/trex_hltapi.py @@ -23,12 +23,33 @@ traffic_config() 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 - l3_length 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 ) @@ -51,6 +72,7 @@ import dpkt import socket from misc_methods import print_r import traceback +import time class HLT_ERR(dict): def __init__(self, log = 'Unknown error', **kwargs): @@ -72,7 +94,7 @@ class HLT_OK(dict): class CTRexHltApi(object): - def __init__(self, verbose = 1): + def __init__(self, verbose = 0): self.trex_client = None self.connected = False self.verbose = verbose @@ -84,7 +106,7 @@ class CTRexHltApi(object): ########################### # device: ip or hostname - def connect(self, device, port_list, username='', reset=False, break_locks=False): + def connect(self, device, port_list, username = '', reset = False, break_locks = False): try: device = socket.gethostbyname(device) # work with ip @@ -235,76 +257,26 @@ class CTRexHltApi(object): bidirect_err = 'When using bidirectional flag, ' if len(port_handle) != 2: return HLT_ERR(bidirect_err + 'number of ports should be exactly 2') - if mac_src not in kwargs or mac_dst not in kwargs: - return HLT_ERR(bidirect_err + 'mac_src and mac_dst should be specified') try: res1 = self.traffic_config(mode, port_handle[0], **kwargs) - res2 = self.traffic_config(mode, port_handle[1], mac_src = kwargs['mac_dst'], mac_dst = kwargs['mac_src'], **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) except Exception as e: return HLT_ERR('Could not generate bidirectional traffic: %s' % e) - return HLT_OK(stream_id = [res1['stream_id'], res2['stream_id']]) - - try: - packet = CTRexHltApi._generate_stream(**kwargs) - except Exception as e: - return HLT_ERR('Could not generate stream: %s' % e) - # set transmission attributes - #try: - # tx_mode = CTxMode(type = transmit_mode, pps = rate_pps, **kwargs) - #except Exception as e: - # return HLT_ERR('Could not init CTxMode: %s' % e) - - try: - # set rx_stats - #rx_stats = CRxStats() # defaults with disabled - rx_stats = None - except Exception as e: - return HLT_ERR('Could not init CTxMode: %s' % e) + return HLT_OK(stream_id = {port_handle[0]: res1['stream_id'], port_handle[1]: res2['stream_id']}) 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) - 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 = burst_loop_count, ibg = inter_burst_gap) - else: - return HLT_ERR('transmit_mode %s not supported/implemented') + stream_obj = CTRexHltApi._generate_stream(**kwargs) except Exception as e: - # some exception happened during the stream creation - return HLT_ERR('Could not create transmit_mode class %s: %s' % (transmit_mode, e)) - - try: - # join the generated data into stream - - stream_obj = STLStream(packet = packet, - #enabled = True, - #self_start = True, - mode = transmit_mode_class, - rx_stats = rx_stats, - #next_stream_id = -1 - ) - # using CStream - #stream_obj_params = {'enabled': False, - # 'self_start': True, - # 'next_stream_id': -1, - # 'isg': 0.0, - # 'mode': tx_mode, - # 'rx_stats': rx_stats, - # 'packet': packet} # vm is excluded from this list since CTRexPktBuilder obj is passed - #stream_obj.load_data(**stream_obj_params) - #print stream_obj.get_id() - except Exception as e: - # some exception happened during the stream creation - return HLT_ERR(e) - + return HLT_ERR('Could not create stream: %s' % e) stream_id = stream_obj.get_id() - #print stream_obj + # try adding the stream per ports try: self.trex_client.add_streams(streams=stream_obj, @@ -446,21 +418,90 @@ class CTRexHltApi(object): return responses @staticmethod - def _generate_stream(l2_encap = 'ethernet_ii', mac_src = '00:00:01:00:00:01', mac_dst = '00:00:00:00:00:00', - l3_protocol = 'ipv4', ip_src_addr = '0.0.0.0', ip_dst_addr = '192.0.0.1', l3_length = 110, - l4_protocol = 'tcp', - **kwards): + def _generate_stream(**kwargs): + try: + packet = CTRexHltApi._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) + 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 = burst_loop_count, ibg = inter_burst_gap) + else: + raise Exception('transmit_mode %s not supported/implemented') + except Exception as e: + raise Exception('Could not create transmit_mode class %s: %s' % (transmit_mode, e)) + + try: + stream_obj = STLStream(packet = packet, + #enabled = True, + #self_start = True, + mode = transmit_mode_class, + #rx_stats = rx_stats, + #next_stream_id = -1 + ) + except Exception as e: + raise Exception('Could not create stream: %s' % e) + + debug_filename = kwargs.get('save_to_yaml') + if type(debug_filename) is str: + stream_obj.dump_to_yaml(debug_filename, stream_obj) + return stream_obj + + @staticmethod + def _generate_packet( + l2_encap = 'ethernet_ii', + mac_src = '00:00:01:00:00:01', + mac_dst = '00:00:00:00:00:00', + + l3_protocol = 'ipv4', + ip_tos_field = 0, + l3_length = 110, + ip_id = 0, + ip_fragment_offset = 0, + ip_ttl = 64, + ip_checksum = 0, + ip_src_addr = '0.0.0.0', + ip_dst_addr = '192.0.0.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 = 0, + tcp_urgent_ptr = 0, + **kwargs): ALLOWED_L3_PROTOCOL = {'ipv4': dpkt.ethernet.ETH_TYPE_IP, - 'ipv6': dpkt.ethernet.ETH_TYPE_IP6, - 'arp': dpkt.ethernet.ETH_TYPE_ARP} + #'ipv6': dpkt.ethernet.ETH_TYPE_IP6, + #'arp': dpkt.ethernet.ETH_TYPE_ARP + } ALLOWED_L4_PROTOCOL = {'tcp': dpkt.ip.IP_PROTO_TCP, - 'udp': dpkt.ip.IP_PROTO_UDP, - 'icmp': dpkt.ip.IP_PROTO_ICMP, - 'icmpv6': dpkt.ip.IP_PROTO_ICMP6, - 'igmp': dpkt.ip.IP_PROTO_IGMP, - 'rtp': dpkt.ip.IP_PROTO_IRTP, - 'isis': dpkt.ip.IP_PROTO_ISIS, - 'ospf': dpkt.ip.IP_PROTO_OSPF} + #'udp': dpkt.ip.IP_PROTO_UDP, + #'icmp': dpkt.ip.IP_PROTO_ICMP, + #'icmpv6': dpkt.ip.IP_PROTO_ICMP6, + #'igmp': dpkt.ip.IP_PROTO_IGMP, + #'rtp': dpkt.ip.IP_PROTO_IRTP, + #'isis': dpkt.ip.IP_PROTO_ISIS, + #'ospf': dpkt.ip.IP_PROTO_OSPF + } pkt_bld = CTRexPktBuilder() if l2_encap == 'ethernet_ii': @@ -491,9 +532,14 @@ class CTRexHltApi(object): #('src', '4s', '\x00' * 4), #('dst', '4s', '\x00' * 4) pkt_bld.add_pkt_layer('l3', dpkt.ip.IP()) + pkt_bld.set_layer_attr('l3', 'tos', ip_tos_field) + pkt_bld.set_layer_attr('l3', 'len', l3_length) + pkt_bld.set_layer_attr('l3', 'id', ip_id) + pkt_bld.set_layer_attr('l3', 'off', ip_fragment_offset) + pkt_bld.set_layer_attr('l3', 'ttl', ip_ttl) + pkt_bld.set_layer_attr('l3', 'sum', ip_checksum) pkt_bld.set_ip_layer_addr('l3', 'src', ip_src_addr) pkt_bld.set_ip_layer_addr('l3', 'dst', ip_dst_addr) - pkt_bld.set_layer_attr('l3', 'len', l3_length) else: raise NotImplementedError("l3_protocol '{0}' is not supported by TRex yet.".format(l3_protocol)) @@ -514,15 +560,38 @@ class CTRexHltApi(object): #('win', 'H', TCP_WIN_MAX), #('sum', 'H', 0), #('urp', 'H', 0) - #pkt_bld.set_ip_layer_addr('l4', 'sport', ip_src_addr) - #pkt_bld.set_ip_layer_addr('l4', 'dport', ip_dst_addr) + pkt_bld.set_layer_attr('l4', 'sport', tcp_src_port) + pkt_bld.set_layer_attr('l4', 'dport', tcp_dst_port) + pkt_bld.set_layer_attr('l4', 'seq', tcp_seq_num) + pkt_bld.set_layer_attr('l4', 'ack', tcp_ack_num) + pkt_bld.set_layer_attr('l4', 'off_x2', tcp_data_offset) + #TH_FIN = 0x01 # end of data + #TH_SYN = 0x02 # synchronize sequence numbers + #TH_RST = 0x04 # reset connection + #TH_PUSH = 0x08 # push + #TH_ACK = 0x10 # acknowledgment number set + #TH_URG = 0x20 # urgent pointer set + #TH_ECE = 0x40 # ECN echo, RFC 3168 + #TH_CWR = 0x80 # congestion window reduced + tcp_flags = (tcp_fin_flag * dpkt.tcp.TH_FIN + + tcp_syn_flag * dpkt.tcp.TH_SYN + + tcp_rst_flag * dpkt.tcp.TH_RST + + tcp_psh_flag * dpkt.tcp.TH_PUSH + + tcp_ack_flag * dpkt.tcp.TH_ACK + + tcp_urg_flag * dpkt.tcp.TH_URG) + pkt_bld.set_layer_attr('l4', 'flags', tcp_flags) + pkt_bld.set_layer_attr('l4', 'win', tcp_window) + pkt_bld.set_layer_attr('l4', 'sum', tcp_checksum) + pkt_bld.set_layer_attr('l4', 'urp', tcp_urgent_ptr) else: raise NotImplementedError("l4_protocol '{0}' is not supported by TRex yet.".format(l3_protocol)) pkt_bld.set_pkt_payload('Hello, World' + '!'*58) # debug - #pkt_bld.dump_pkt_to_pcap('stream_test.pcap') + debug_filename = kwargs.get('save_to_pcap') + if type(debug_filename) is str: + pkt_bld.dump_pkt_to_pcap(debug_filename) return pkt_bld diff --git a/scripts/automation/trex_control_plane/client/trex_stateless_client.py b/scripts/automation/trex_control_plane/client/trex_stateless_client.py index 4a2cc436..78adbcc2 100755 --- a/scripts/automation/trex_control_plane/client/trex_stateless_client.py +++ b/scripts/automation/trex_control_plane/client/trex_stateless_client.py @@ -932,6 +932,8 @@ class STLClient(object): # by default use all ports if ports == None: ports = self.get_all_ports() + else: + ports = self.__ports(ports) # verify valid port id list rc = self._validate_port_list(ports) @@ -1632,6 +1634,8 @@ class STLClient(object): # by default use all ports if ports == None: ports = self.get_all_ports() + else: + ports = self.__ports(ports) # verify valid port id list rc = self._validate_port_list(ports) -- cgit From 11bcf4ca8fed5259e321c535bf90d0442e9b9746 Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 1 Feb 2016 08:59:38 -0500 Subject: fix for http://trex-tgn.cisco.com/youtrack/issue/trex-174 --- .../client/trex_stateless_client.py | 35 ++++++---- .../client/trex_stateless_sim.py | 8 +-- scripts/exp/stl_vm_split_client_var.erf-0.erf | Bin 11000 -> 11000 bytes .../exp/stl_vm_split_flow_var_big_range.erf-0.erf | Bin 11000 -> 11000 bytes scripts/exp/stl_vm_split_flow_var_inc.erf-0.erf | Bin 11000 -> 11000 bytes .../stl_vm_split_flow_var_small_range.erf-0.erf | Bin 11000 -> 11000 bytes src/bp_sim.cpp | 21 ++++-- src/gtest/trex_stateless_gtest.cpp | 16 +++-- src/sim/trex_sim_stateless.cpp | 1 + src/stateless/cp/trex_stateless_port.cpp | 11 +++- src/stateless/cp/trex_stream.h | 13 ++++ src/stateless/cp/trex_stream_vm.h | 2 +- src/stateless/cp/trex_streams_compiler.cpp | 71 +++++++++++++++++++-- src/stateless/cp/trex_streams_compiler.h | 17 +++++ src/stateless/dp/trex_stateless_dp_core.h | 9 +++ 15 files changed, 169 insertions(+), 35 deletions(-) diff --git a/scripts/automation/trex_control_plane/client/trex_stateless_client.py b/scripts/automation/trex_control_plane/client/trex_stateless_client.py index 78adbcc2..506decfe 100755 --- a/scripts/automation/trex_control_plane/client/trex_stateless_client.py +++ b/scripts/automation/trex_control_plane/client/trex_stateless_client.py @@ -25,6 +25,7 @@ from trex_port import Port from common.trex_types import * from common.trex_stl_exceptions import * from trex_async_client import CTRexAsyncClient +from yaml import YAMLError ############################ logger ############################# @@ -436,9 +437,6 @@ class STLClient(object): self.stats_generator = trex_stats.CTRexInfoGenerator(self.global_stats, self.ports) - # stream DB - self.streams_db = CStreamsDB() - ############# private functions - used by the class itself ########### @@ -1301,17 +1299,28 @@ class STLClient(object): if not rc: raise STLArgumentError('ports', ports, valid_values = self.get_all_ports()) - # load the YAML + + streams = None + + # try YAML try: - streams_pack = self.streams_db.load_yaml_file(filename) - except Exception as e: - raise STLError(str(e)) - - # HACK - convert the stream pack to simple streams - streams = [] - for stream in streams_pack.compiled: - s = HACKSTLStream(stream) - streams.append(s) + streams_db = CStreamsDB() + stream_list = streams_db.load_yaml_file(filename) + + # convert to new style stream object + streams = [HACKSTLStream(stream) for stream in stream_list.compiled] + except YAMLError: + # try python + try: + basedir = os.path.dirname(filename) + sys.path.append(basedir) + file = os.path.basename(filename).split('.')[0] + module = __import__(file, globals(), locals(), [], -1) + + streams = module.register().get_streams() + + except (AttributeError, ImportError): + raise STLError("bad format input file '{0}'".format(filename)) self.add_streams(streams, ports) diff --git a/scripts/automation/trex_control_plane/client/trex_stateless_sim.py b/scripts/automation/trex_control_plane/client/trex_stateless_sim.py index 7f65996d..d8f6ed92 100644 --- a/scripts/automation/trex_control_plane/client/trex_stateless_sim.py +++ b/scripts/automation/trex_control_plane/client/trex_stateless_sim.py @@ -25,7 +25,7 @@ except ImportError: import client.outer_packages from common.trex_stl_exceptions import STLError -from yaml.scanner import ScannerError +from yaml import YAMLError from common.trex_streams import * from client_utils import parsing_opts @@ -103,7 +103,7 @@ class STLSim(object): # convert to new style stream object return [HACKSTLStream(stream) for stream in stream_list.compiled] - except ScannerError: + except YAMLError: pass # try python @@ -111,12 +111,12 @@ class STLSim(object): basedir = os.path.dirname(input_file) sys.path.append(basedir) - file = os.path.basename(input_file).split('.py')[0] + file = os.path.basename(input_file).split('.')[0] module = __import__(file, globals(), locals(), [], -1) return module.register().get_streams() - except AttributeError: + except (AttributeError, ImportError): pass raise STLError("bad format input file '{0}'".format(input_file)) diff --git a/scripts/exp/stl_vm_split_client_var.erf-0.erf b/scripts/exp/stl_vm_split_client_var.erf-0.erf index 12e68c09..a9f330fe 100644 Binary files a/scripts/exp/stl_vm_split_client_var.erf-0.erf and b/scripts/exp/stl_vm_split_client_var.erf-0.erf differ diff --git a/scripts/exp/stl_vm_split_flow_var_big_range.erf-0.erf b/scripts/exp/stl_vm_split_flow_var_big_range.erf-0.erf index 8f4fe297..8e62aca6 100644 Binary files a/scripts/exp/stl_vm_split_flow_var_big_range.erf-0.erf and b/scripts/exp/stl_vm_split_flow_var_big_range.erf-0.erf differ diff --git a/scripts/exp/stl_vm_split_flow_var_inc.erf-0.erf b/scripts/exp/stl_vm_split_flow_var_inc.erf-0.erf index 82025972..acd31a64 100644 Binary files a/scripts/exp/stl_vm_split_flow_var_inc.erf-0.erf and b/scripts/exp/stl_vm_split_flow_var_inc.erf-0.erf differ diff --git a/scripts/exp/stl_vm_split_flow_var_small_range.erf-0.erf b/scripts/exp/stl_vm_split_flow_var_small_range.erf-0.erf index 5dac9893..4cf58e67 100644 Binary files a/scripts/exp/stl_vm_split_flow_var_small_range.erf-0.erf and b/scripts/exp/stl_vm_split_flow_var_small_range.erf-0.erf differ diff --git a/src/bp_sim.cpp b/src/bp_sim.cpp index a7fadf93..0acb991a 100755 --- a/src/bp_sim.cpp +++ b/src/bp_sim.cpp @@ -790,13 +790,18 @@ int CErfIF::write_pkt(CCapPktRaw *pkt_raw){ int CErfIF::close_file(void){ - BP_ASSERT(m_raw); - delete m_raw; + if (m_raw) { + delete m_raw; + m_raw = NULL; + } + if ( m_preview_mode->getFileWrite() ){ - BP_ASSERT(m_writer); - delete m_writer; - m_writer=0; + if (m_writer) { + delete m_writer; + m_writer = NULL; + } } + return (0); } @@ -4042,7 +4047,11 @@ void CFlowGenListPerThread::stop_stateless_simulation_file(){ void CFlowGenListPerThread::start_stateless_daemon_simulation(){ m_cur_time_sec = 0; - m_stateless_dp_info.run_once(); + + /* if no pending CP messages - the core will simply be stuck forever */ + if (m_stateless_dp_info.are_any_pending_cp_messages()) { + m_stateless_dp_info.run_once(); + } } diff --git a/src/gtest/trex_stateless_gtest.cpp b/src/gtest/trex_stateless_gtest.cpp index 704a24b7..f01346b0 100644 --- a/src/gtest/trex_stateless_gtest.cpp +++ b/src/gtest/trex_stateless_gtest.cpp @@ -1432,7 +1432,7 @@ public: } lpt->start_stateless_daemon_simulation(); - + lpt->stop_stateless_simulation_file(); //lpt->m_node_gen.DumpHist(stdout); @@ -3054,6 +3054,8 @@ public: assert(compile.compile(0, streams, objs, dp_core_count)); /* choose one DP object */ + assert(objs[dp_core_to_check]); + TrexStatelessDpStart *lpStartCmd = new TrexStatelessDpStart(0, 0, objs[dp_core_to_check], 1 /*sec */ ); objs[dp_core_to_check] = NULL; /* free all the non used DP objects */ @@ -3089,7 +3091,8 @@ TEST_F(basic_stl, vm_split_flow_var_inc) { VmSplitTest split("exp/stl_vm_split_flow_var_inc.erf"); TrexStream stream(TrexStream::stSINGLE_BURST, 0, 0); - stream.set_pps(1000); + stream.set_single_burst(1000); + stream.set_pps(100000); split.set_stream(&stream); split.run(8, 4); @@ -3101,7 +3104,8 @@ TEST_F(basic_stl, vm_split_flow_var_small_range) { VmSplitTest split("exp/stl_vm_split_flow_var_small_range.erf"); TrexStream stream(TrexStream::stSINGLE_BURST, 0, 0); - stream.set_pps(1000); + stream.set_single_burst(1000); + stream.set_pps(100000); split.set_stream(&stream); split.set_flow_var_as_split(StreamVmInstructionFlowMan::FLOW_VAR_OP_INC, 0, 1, 0); @@ -3114,7 +3118,8 @@ TEST_F(basic_stl, vm_split_flow_var_big_range) { VmSplitTest split("exp/stl_vm_split_flow_var_big_range.erf"); TrexStream stream(TrexStream::stSINGLE_BURST, 0, 0); - stream.set_pps(1000); + stream.set_single_burst(1000); + stream.set_pps(100000); split.set_stream(&stream); split.set_flow_var_as_split(StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC, 1, 1000, 1000); @@ -3128,7 +3133,8 @@ TEST_F(basic_stl, vm_split_client_var) { VmSplitTest split("exp/stl_vm_split_client_var.erf"); TrexStream stream(TrexStream::stSINGLE_BURST, 0, 0); - stream.set_pps(1000); + stream.set_single_burst(1000); + stream.set_pps(100000); split.set_stream(&stream); split.set_client_var_as_split(0x10000001, 0x100000fe, 5000, 5050); diff --git a/src/sim/trex_sim_stateless.cpp b/src/sim/trex_sim_stateless.cpp index 46b9916f..897d1fec 100644 --- a/src/sim/trex_sim_stateless.cpp +++ b/src/sim/trex_sim_stateless.cpp @@ -422,6 +422,7 @@ SimStateless::run_dp_core(int core_index, lpt->start_stateless_simulation_file((std::string)out_filename, CGlobalInfo::m_options.preview, get_limit_per_core(core_index)); lpt->start_stateless_daemon_simulation(); + lpt->stop_stateless_simulation_file(); flush_dp_to_cp_messages_core(core_index); diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 2286ef76..a281e428 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -184,8 +184,15 @@ TrexStatelessPort::start_traffic(const TrexPortMultiplier &mul, double duration, int index = 0; for (auto core_id : m_cores_id_list) { - TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(m_port_id, event_id, compiled_objs[index], duration); - send_message_to_dp(core_id, start_msg); + /* was the core assigned a compiled object ? */ + if (compiled_objs[index]) { + TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(m_port_id, event_id, compiled_objs[index], duration); + send_message_to_dp(core_id, start_msg); + } else { + + /* mimic an end event */ + m_dp_events.handle_event(TrexDpPortEvent::EVENT_STOP, core_id, event_id); + } index++; } diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index e854cdf7..525bf594 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -165,6 +165,19 @@ public: } + /* can this stream be split ? */ + bool is_splitable(uint8_t dp_core_count) const { + + /* cont stream is always splitable */ + if (m_type == stCONTINUOUS) { + return true; + } + + int per_core_burst_total_pkts = (m_burst_total_pkts / dp_core_count); + + return (per_core_burst_total_pkts > 0); + + } void set_multi_burst(uint32_t burst_total_pkts, uint32_t num_bursts, diff --git a/src/stateless/cp/trex_stream_vm.h b/src/stateless/cp/trex_stream_vm.h index ca7f71c1..dabc502c 100644 --- a/src/stateless/cp/trex_stream_vm.h +++ b/src/stateless/cp/trex_stream_vm.h @@ -1196,7 +1196,7 @@ public: void copy_instructions(StreamVm &other) const; - bool is_vm_empty() { + bool is_vm_empty() const { return (m_inst_list.size() == 0); } diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index d9f979e8..9d048dbd 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -391,6 +391,7 @@ TrexStreamsCompiler::compile(uint8_t port_id, } } + bool TrexStreamsCompiler::compile_internal(uint8_t port_id, const std::vector &streams, @@ -440,6 +441,14 @@ TrexStreamsCompiler::compile_internal(uint8_t por compile_stream(stream, factor, dp_core_count, objs, nodes); } + /* some objects might be empty - no streams were assigned */ + for (uint8_t i = 0; i < dp_core_count; i++) { + if (objs[i]->is_empty()) { + delete objs[i]; + objs[i] = NULL; + } + } + return true; } @@ -466,13 +475,43 @@ TrexStreamsCompiler::compile_stream(const TrexStream *stream, new_next_id = nodes.get(stream->m_next_stream_id)->m_compressed_stream_id; } + + /* can this stream be split to many cores ? */ + if (!stream->is_splitable(dp_core_count)) { + compile_stream_on_single_core(stream, + factor, + objs[0], + new_id, + new_next_id); + } else { + compile_stream_on_all_cores(stream, + factor, + dp_core_count, + objs, + new_id, + new_next_id); + } + + +} + +/** + * compile the stream on all the cores available + * + */ +void +TrexStreamsCompiler::compile_stream_on_all_cores(const TrexStream *stream, + double factor, + uint8_t dp_core_count, + std::vector &objs, + int new_id, + int new_next_id) { + std::vector core_streams(dp_core_count); - /* calculate rate */ double per_core_rate = (stream->m_pps * (factor / dp_core_count)); int per_core_burst_total_pkts = (stream->m_burst_total_pkts / dp_core_count); - /* for each core - creates its own version of the stream */ for (uint8_t i = 0; i < dp_core_count; i++) { TrexStream *dp_stream = stream->clone(); @@ -488,7 +527,7 @@ TrexStreamsCompiler::compile_stream(const TrexStream *stream, core_streams[i] = dp_stream; } - /* take care of remainder from a burst */ + /* take care of remainder from a burst on core 0 */ int burst_remainder = stream->m_burst_total_pkts - (per_core_burst_total_pkts * dp_core_count); core_streams[0]->m_burst_total_pkts += burst_remainder; @@ -501,9 +540,33 @@ TrexStreamsCompiler::compile_stream(const TrexStream *stream, objs[i]->add_compiled_stream(core_streams[i]); } - } +/** + * compile the stream on core 0 + * + */ +void +TrexStreamsCompiler::compile_stream_on_single_core(const TrexStream *stream, + double factor, + TrexStreamsCompiledObj *obj, + int new_id, + int new_next_id) { + + TrexStream *dp_stream = stream->clone(); + + /* fix stream ID */ + dp_stream->fix_dp_stream_id(new_id, new_next_id); + + /* compile the VM if exists */ + if (!stream->m_vm.is_vm_empty()) { + ((TrexStream *)stream)->vm_compile(); + dp_stream->m_vm_dp = stream->m_vm_dp->clone(); + } + + /* update the core */ + obj->add_compiled_stream(dp_stream); +} /************************************** * streams graph diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index aaef78be..a3a1f8f7 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -65,6 +65,10 @@ public: TrexStreamsCompiledObj* clone(); + bool is_empty() { + return (m_objs.size() == 0); + } + private: void add_compiled_stream(TrexStream *stream); @@ -125,6 +129,19 @@ private: std::vector &objs, GraphNodeMap &nodes); + void compile_stream_on_single_core(const TrexStream *stream, + double factor, + TrexStreamsCompiledObj *obj, + int new_id, + int new_next_id); + + void compile_stream_on_all_cores(const TrexStream *stream, + double factor, + uint8_t dp_core_count, + std::vector &objs, + int new_id, + int new_next_id); + std::vector m_warnings; }; diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index efdb364c..c8a5eff5 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -180,6 +180,15 @@ public: bool are_all_ports_idle(); + /** + * return true if core has any pending messages from CP + * + */ + bool are_any_pending_cp_messages() { + return (!m_ring_from_cp->isEmpty()); + } + + /** * check for and handle messages from CP * -- cgit