summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHanoh Haim <hhaim@cisco.com>2016-02-01 17:16:38 +0200
committerHanoh Haim <hhaim@cisco.com>2016-02-01 17:16:38 +0200
commit37ea6af93798ef5e2a877b755ff6dc6cb2cde33a (patch)
tree038bd751a2b5904125769b5192101aa49ef728a7
parent00d74df1d05ce2b47d37574fda8806d71841d3e9 (diff)
parent11bcf4ca8fed5259e321c535bf90d0442e9b9746 (diff)
Merge from origin
-rwxr-xr-xscripts/automation/trex_control_plane/client/trex_hltapi.py233
-rwxr-xr-xscripts/automation/trex_control_plane/client/trex_stateless_client.py37
-rw-r--r--scripts/automation/trex_control_plane/client/trex_stateless_sim.py8
-rw-r--r--scripts/exp/stl_vm_split_client_var.erf-0.erfbin11000 -> 11000 bytes
-rw-r--r--scripts/exp/stl_vm_split_flow_var_big_range.erf-0.erfbin11000 -> 11000 bytes
-rw-r--r--scripts/exp/stl_vm_split_flow_var_inc.erf-0.erfbin11000 -> 11000 bytes
-rw-r--r--scripts/exp/stl_vm_split_flow_var_small_range.erf-0.erfbin11000 -> 11000 bytes
-rwxr-xr-xsrc/bp_sim.cpp21
-rw-r--r--src/gtest/trex_stateless_gtest.cpp16
-rw-r--r--src/sim/trex_sim_stateless.cpp1
-rw-r--r--src/stateless/cp/trex_stateless_port.cpp11
-rw-r--r--src/stateless/cp/trex_stream.h13
-rw-r--r--src/stateless/cp/trex_stream_vm.h2
-rw-r--r--src/stateless/cp/trex_streams_compiler.cpp71
-rw-r--r--src/stateless/cp/trex_streams_compiler.h17
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.h9
16 files changed, 323 insertions, 116 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..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 ###########
@@ -932,6 +930,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)
@@ -1299,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))
+ streams_db = CStreamsDB()
+ stream_list = streams_db.load_yaml_file(filename)
- # HACK - convert the stream pack to simple streams
- streams = []
- for stream in streams_pack.compiled:
- s = HACKSTLStream(stream)
- streams.append(s)
+ # 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)
@@ -1632,6 +1643,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)
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
--- a/scripts/exp/stl_vm_split_client_var.erf-0.erf
+++ b/scripts/exp/stl_vm_split_client_var.erf-0.erf
Binary files 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
--- 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
Binary files 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
--- a/scripts/exp/stl_vm_split_flow_var_inc.erf-0.erf
+++ b/scripts/exp/stl_vm_split_flow_var_inc.erf-0.erf
Binary files 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
--- 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
Binary files differ
diff --git a/src/bp_sim.cpp b/src/bp_sim.cpp
index bb1eb073..72ad1097 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);
}
@@ -4040,7 +4045,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<TrexStream *> &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<TrexStreamsCompiledObj *> &objs,
+ int new_id,
+ int new_next_id) {
+
std::vector<TrexStream *> 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<TrexStreamsCompiledObj *> &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<TrexStreamsCompiledObj *> &objs,
+ int new_id,
+ int new_next_id);
+
std::vector<std::string> 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
@@ -181,6 +181,15 @@ public:
/**
+ * 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
*
* @author imarom (27-Oct-15)