summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHanoh Haim <hhaim@cisco.com>2016-06-22 16:06:20 +0300
committerHanoh Haim <hhaim@cisco.com>2016-06-22 16:06:20 +0300
commit92267f3a419fe33d5f0a0e15ddaa3e8117b3b2fd (patch)
tree43f291d603cfc7691ea9cd51144bc37e7c3ead91
parentd97b7b7159c8c7f37f45cd2c98de042b1c7b5d69 (diff)
parent9249859480c57960905f37282e9fa8047cf17484 (diff)
Merge regression tests
-rwxr-xr-xlinux_dpdk/ws_main.py3
-rw-r--r--scripts/automation/regression/functional_tests/stl_basic_tests.py2
-rwxr-xr-xscripts/automation/regression/trex_unit_test.py6
-rwxr-xr-xscripts/automation/trex_control_plane/common/text_opts.py3
-rwxr-xr-xscripts/automation/trex_control_plane/server/trex_server.py8
-rwxr-xr-xscripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py7
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py1
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_opts.py3
-rw-r--r--scripts/exp/flow_stats.pcapbin0 -> 100 bytes
-rw-r--r--scripts/exp/flow_stats_latency.pcapbin0 -> 136 bytes
-rwxr-xr-xsrc/bp_sim.cpp28
-rw-r--r--src/flow_stat.cpp10
-rw-r--r--src/stateless/cp/trex_stateless_port.cpp73
-rw-r--r--src/stateless/cp/trex_streams_compiler.cpp31
-rw-r--r--src/stateless/cp/trex_streams_compiler.h4
15 files changed, 133 insertions, 46 deletions
diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py
index dde94dc4..12a2fd89 100755
--- a/linux_dpdk/ws_main.py
+++ b/linux_dpdk/ws_main.py
@@ -714,7 +714,8 @@ def build_prog (bld, build_obj):
debug_file_list='';
if not build_obj.isRelease ():
#debug
- debug_file_list +=ef_src.file_list(top)
+ #debug_file_list +=ef_src.file_list(top)
+ pass
bld.objects(
diff --git a/scripts/automation/regression/functional_tests/stl_basic_tests.py b/scripts/automation/regression/functional_tests/stl_basic_tests.py
index 863307f1..a4e28ca9 100644
--- a/scripts/automation/regression/functional_tests/stl_basic_tests.py
+++ b/scripts/automation/regression/functional_tests/stl_basic_tests.py
@@ -201,6 +201,8 @@ class CStlBasic_Test(functional_general_test.CGeneralFunctional_Test):
["multi_burst_2st_1000pkt.py","-m 1 -l 100",True],
["pcap.py", "-m 1", True],
["pcap_with_vm.py", "-m 1", True],
+ ["flow_stats.py", "-m 1 -l 1", True],
+ ["flow_stats_latency.py", "-m 1 -l 1", True],
# YAML test
["yaml/burst_1000_pkt.yaml","-m 1 -l 100",True],
diff --git a/scripts/automation/regression/trex_unit_test.py b/scripts/automation/regression/trex_unit_test.py
index 11902a1a..915cd682 100755
--- a/scripts/automation/regression/trex_unit_test.py
+++ b/scripts/automation/regression/trex_unit_test.py
@@ -146,6 +146,9 @@ class CTRexTestConfiguringPlugin(Plugin):
parser.add_option('--debug-image', action="store_true", default = False,
dest="debug_image",
help="Flag that specifies to use t-rex-64-debug as TRex executable.")
+ parser.add_option('--trex-args', action='store', default = '',
+ dest="trex_args",
+ help="Additional TRex arguments (--no-watchdog etc.).")
def configure(self, options, conf):
@@ -186,7 +189,8 @@ class CTRexTestConfiguringPlugin(Plugin):
if not self.no_daemon:
CTRexScenario.trex = CTRexClient(trex_host = self.configuration.trex['trex_name'],
verbose = self.json_verbose,
- debug_image = options.debug_image)
+ debug_image = options.debug_image,
+ trex_args = options.trex_args)
if not CTRexScenario.trex.check_master_connectivity():
print('Could not connect to master daemon')
sys.exit(-1)
diff --git a/scripts/automation/trex_control_plane/common/text_opts.py b/scripts/automation/trex_control_plane/common/text_opts.py
index 78a0ab1f..ab0fd2f2 100755
--- a/scripts/automation/trex_control_plane/common/text_opts.py
+++ b/scripts/automation/trex_control_plane/common/text_opts.py
@@ -61,6 +61,9 @@ def format_time (t_sec):
if t_sec < 0:
return "infinite"
+ if t_sec == 0:
+ return "zero"
+
if t_sec < 1:
# low numbers
for unit in ['ms', 'usec', 'ns']:
diff --git a/scripts/automation/trex_control_plane/server/trex_server.py b/scripts/automation/trex_control_plane/server/trex_server.py
index 091b729b..9fe7d70b 100755
--- a/scripts/automation/trex_control_plane/server/trex_server.py
+++ b/scripts/automation/trex_control_plane/server/trex_server.py
@@ -310,7 +310,7 @@ class CTRexServer(object):
return False
- def start_trex(self, trex_cmd_options, user, block_to_success = True, timeout = 40, stateless = False, debug_image = False):
+ def start_trex(self, trex_cmd_options, user, block_to_success = True, timeout = 40, stateless = False, debug_image = False, trex_args = ''):
with self.start_lock:
logger.info("Processing start_trex() command.")
if self.is_reserved():
@@ -323,7 +323,7 @@ class CTRexServer(object):
return Fault(-13, '') # raise at client TRexInUseError
try:
- server_cmd_data = self.generate_run_cmd(stateless = stateless, debug_image = debug_image, **trex_cmd_options)
+ server_cmd_data = self.generate_run_cmd(stateless = stateless, debug_image = debug_image, trex_args = trex_args, **trex_cmd_options)
self.zmq_monitor.first_dump = True
self.trex.start_trex(self.TREX_PATH, server_cmd_data)
logger.info("TRex session has been successfully initiated.")
@@ -413,7 +413,7 @@ class CTRexServer(object):
return self.trex.get_running_info()
- def generate_run_cmd (self, iom = 0, export_path="/tmp/trex.txt", stateless = False, debug_image = False, **kwargs):
+ def generate_run_cmd (self, iom = 0, export_path="/tmp/trex.txt", stateless = False, debug_image = False, trex_args = '', **kwargs):
""" generate_run_cmd(self, iom, export_path, kwargs) -> str
Generates a custom running command for the kick-off of the TRex traffic generator.
@@ -450,6 +450,8 @@ class CTRexServer(object):
continue
else:
trex_cmd_options += (dash + '{k} {val}'.format( k = tmp_key, val = value ))
+ if trex_args:
+ trex_cmd_options += ' %s' % trex_args
if not stateless:
if 'f' not in kwargs:
diff --git a/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py
index 57d19459..a13fe31f 100755
--- a/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py
+++ b/scripts/automation/trex_control_plane/stf/trex_stf_lib/trex_client.py
@@ -40,7 +40,7 @@ class CTRexClient(object):
This class defines the client side of the RESTfull interaction with TRex
"""
- def __init__(self, trex_host, max_history_size = 100, filtered_latency_amount = 0.001, trex_daemon_port = 8090, master_daemon_port = 8091, trex_zmq_port = 4500, verbose = False, debug_image = False):
+ def __init__(self, trex_host, max_history_size = 100, filtered_latency_amount = 0.001, trex_daemon_port = 8090, master_daemon_port = 8091, trex_zmq_port = 4500, verbose = False, debug_image = False, trex_args = ''):
"""
Instantiate a TRex client object, and connecting it to listening daemon-server
@@ -97,6 +97,7 @@ class CTRexClient(object):
self.trex_server_path = "http://{hostname}:{port}/".format( hostname = self.trex_host, port = trex_daemon_port )
self.server = jsonrpclib.Server(self.trex_server_path, history = self.history)
self.debug_image = debug_image
+ self.trex_args = trex_args
def add (self, x, y):
@@ -160,7 +161,7 @@ class CTRexClient(object):
self.result_obj.clear_results()
try:
issue_time = time.time()
- retval = self.server.start_trex(trex_cmd_options, user, block_to_success, timeout, False, self.debug_image)
+ retval = self.server.start_trex(trex_cmd_options, user, block_to_success, timeout, False, self.debug_image, self.trex_args)
except AppError as err:
self._handle_AppError_exception(err.args[0])
except ProtocolError:
@@ -206,7 +207,7 @@ class CTRexClient(object):
"""
try:
user = user or self.__default_user
- retval = self.server.start_trex(trex_cmd_options, user, block_to_success, timeout, True, self.debug_image)
+ retval = self.server.start_trex(trex_cmd_options, user, block_to_success, timeout, True, self.debug_image, self.trex_args)
except AppError as err:
self._handle_AppError_exception(err.args[0])
except ProtocolError:
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py
index 0ec98a0d..88a94865 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py
@@ -1036,6 +1036,7 @@ class CLatencyStats(CTRexStats):
output[int_pg_id]['latency']['total_min'] = min_val
else:
output[int_pg_id]['latency']['total_min'] = StatNotAvailable('total_min')
+ output[int_pg_id]['latency']['histogram'] = {}
self.latest_stats = output
return True
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_opts.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_opts.py
index 7e0bf9e4..26e64dae 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_opts.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_opts.py
@@ -61,6 +61,9 @@ def format_time (t_sec):
if t_sec < 0:
return "infinite"
+ if t_sec == 0:
+ return "zero"
+
if t_sec < 1:
# low numbers
for unit in ['ms', 'usec', 'ns']:
diff --git a/scripts/exp/flow_stats.pcap b/scripts/exp/flow_stats.pcap
new file mode 100644
index 00000000..267eeaab
--- /dev/null
+++ b/scripts/exp/flow_stats.pcap
Binary files differ
diff --git a/scripts/exp/flow_stats_latency.pcap b/scripts/exp/flow_stats_latency.pcap
new file mode 100644
index 00000000..89d27701
--- /dev/null
+++ b/scripts/exp/flow_stats_latency.pcap
Binary files differ
diff --git a/src/bp_sim.cpp b/src/bp_sim.cpp
index f4eb6f7e..f9e96b6b 100755
--- a/src/bp_sim.cpp
+++ b/src/bp_sim.cpp
@@ -4991,29 +4991,27 @@ int CErfIFStl::send_sl_node(CGenNodeStateless *node_sl) {
bool is_const = false;
if (m) {
is_const = true;
+ rte_pktmbuf_refcnt_update(m,1);
}else{
m=node_sl->alloc_node_with_vm();
assert(m);
}
- if (node_sl->is_stat_needed()) {
+ if (node_sl->is_stat_needed() && (node_sl->get_stat_hw_id() >= MAX_FLOW_STATS) ) {
+ /* latency packet. flow stat without latency handled like normal packet in simulation */
uint16_t hw_id = node_sl->get_stat_hw_id();
- if (hw_id >= MAX_FLOW_STATS) {
- rte_mbuf_t *mi;
- struct flow_stat_payload_header *fsp_head;
- mi = node_sl->alloc_flow_stat_mbuf(m, fsp_head, is_const);
- fsp_head->seq = 0x12345678;
- fsp_head->hw_id = hw_id - MAX_FLOW_STATS;
- fsp_head->magic = FLOW_STAT_PAYLOAD_MAGIC;
- fsp_head->time_stamp = 0x8899aabbccddeeff;
- fill_raw_packet(m,(CGenNode *)node_sl,dir);
- rte_pktmbuf_free(mi);
- }
+ rte_mbuf_t *mi;
+ struct flow_stat_payload_header *fsp_head;
+ mi = node_sl->alloc_flow_stat_mbuf(m, fsp_head, is_const);
+ fsp_head->seq = 0x12345678;
+ fsp_head->hw_id = hw_id - MAX_FLOW_STATS;
+ fsp_head->magic = FLOW_STAT_PAYLOAD_MAGIC;
+ fsp_head->time_stamp = 0x8899aabbccddeeff;
+ fill_raw_packet(mi, (CGenNode *)node_sl, dir);
+ rte_pktmbuf_free(mi);
} else {
fill_raw_packet(m,(CGenNode *)node_sl,dir);
- if (! is_const) {
- rte_pktmbuf_free(m);
- }
+ rte_pktmbuf_free(m);
}
}
/* check that we have mbuf */
diff --git a/src/flow_stat.cpp b/src/flow_stat.cpp
index 366c3aa8..cb7a1bf9 100644
--- a/src/flow_stat.cpp
+++ b/src/flow_stat.cpp
@@ -472,6 +472,16 @@ CFlowStatRuleMgr::CFlowStatRuleMgr() {
CFlowStatRuleMgr::~CFlowStatRuleMgr() {
delete m_parser;
+#ifdef TREX_SIM
+ // In simulator, nobody handles the messages to RX, so need to free them to have clean valgrind run.
+ if (m_ring_to_rx) {
+ CGenNode *msg = NULL;
+ while (! m_ring_to_rx->isEmpty()) {
+ m_ring_to_rx->Dequeue(msg);
+ delete msg;
+ }
+ }
+#endif
}
void CFlowStatRuleMgr::create() {
diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp
index 4dc3e449..d736d09e 100644
--- a/src/stateless/cp/trex_stateless_port.cpp
+++ b/src/stateless/cp/trex_stateless_port.cpp
@@ -87,6 +87,68 @@ protected:
}
};
+/*************************************
+ * Streams Feeder
+ * A class that holds a temporary
+ * clone of streams that can be
+ * manipulated
+ *
+ * this is a RAII object meant for
+ * graceful cleanup
+ ************************************/
+class StreamsFeeder {
+public:
+ StreamsFeeder(TrexStatelessPort *port) {
+
+ /* start pesimistic */
+ m_success = false;
+
+ /* fetch the original streams */
+ port->get_object_list(m_in_streams);
+
+ for (const TrexStream *in_stream : m_in_streams) {
+ TrexStream *out_stream = in_stream->clone(true);
+
+ get_stateless_obj()->m_rx_flow_stat.start_stream(out_stream);
+
+ m_out_streams.push_back(out_stream);
+ }
+ }
+
+ void set_status(bool status) {
+ m_success = status;
+ }
+
+ vector<TrexStream *> &get_streams() {
+ return m_out_streams;
+ }
+
+ /**
+ * RAII
+ */
+ ~StreamsFeeder() {
+ for (int i = 0; i < m_out_streams.size(); i++) {
+ TrexStream *out_stream = m_out_streams[i];
+ TrexStream *in_stream = m_in_streams[i];
+
+ if (m_success) {
+ /* success path */
+ get_stateless_obj()->m_rx_flow_stat.copy_state(out_stream, in_stream);
+ } else {
+ /* fail path */
+ get_stateless_obj()->m_rx_flow_stat.stop_stream(out_stream);
+ }
+ delete out_stream;
+ }
+ }
+
+private:
+ vector<TrexStream *> m_in_streams;
+ vector<TrexStream *> m_out_streams;
+ bool m_success;
+};
+
+
/***************************
* trex stateless port
*
@@ -193,10 +255,7 @@ TrexStatelessPort::start_traffic(const TrexPortMultiplier &mul, double duration,
/* caclulate the effective factor for DP */
double factor = calculate_effective_factor(mul, force);
- /* fetch all the streams from the table */
- vector<TrexStream *> streams;
- get_object_list(streams);
-
+ StreamsFeeder feeder(this);
/* compiler it */
std::vector<TrexStreamsCompiledObj *> compiled_objs;
@@ -204,15 +263,19 @@ TrexStatelessPort::start_traffic(const TrexPortMultiplier &mul, double duration,
TrexStreamsCompiler compiler;
bool rc = compiler.compile(m_port_id,
- streams,
+ feeder.get_streams(),
compiled_objs,
get_dp_core_count(),
factor,
&fail_msg);
+
if (!rc) {
+ feeder.set_status(false);
throw TrexException(fail_msg);
}
+ feeder.set_status(true);
+
/* generate a message to all the relevant DP cores to start transmitting */
assert(m_pending_async_stop_event == TrexDpPortEvents::INVALID_ID);
m_pending_async_stop_event = m_dp_events.create_event(new AsyncStopEvent());
diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp
index d2fe416a..e54c5f9c 100644
--- a/src/stateless/cp/trex_streams_compiler.cpp
+++ b/src/stateless/cp/trex_streams_compiler.cpp
@@ -382,7 +382,13 @@ TrexStreamsCompiler::compile(uint8_t port_id,
assert(dp_core_count > 0);
try {
- return compile_internal(port_id,streams,objs,dp_core_count,factor,fail_msg);
+ return compile_internal(port_id,
+ streams,
+ objs,
+ dp_core_count,
+ factor,
+ fail_msg);
+
} catch (const TrexException &ex) {
if (fail_msg) {
*fail_msg = ex.what();
@@ -411,7 +417,6 @@ TrexStreamsCompiler::compile_internal(uint8_t por
GraphNodeMap nodes;
-
/* compile checks */
pre_compile_check(streams, nodes);
@@ -474,7 +479,7 @@ TrexStreamsCompiler::compile_on_single_core(uint8_t
}
/* compile all the streams */
- for (auto stream : streams) {
+ for (auto const stream : streams) {
/* skip non-enabled streams */
if (!stream->m_enabled) {
@@ -507,7 +512,7 @@ TrexStreamsCompiler::compile_on_all_cores(uint8_t
}
/* compile all the streams */
- for (auto stream : streams) {
+ for (auto const stream : streams) {
/* skip non-enabled streams */
if (!stream->m_enabled) {
@@ -527,7 +532,7 @@ TrexStreamsCompiler::compile_on_all_cores(uint8_t
*
*/
void
-TrexStreamsCompiler::compile_stream(TrexStream *stream,
+TrexStreamsCompiler::compile_stream(const TrexStream *stream,
double factor,
uint8_t dp_core_count,
std::vector<TrexStreamsCompiledObj *> &objs,
@@ -543,31 +548,25 @@ TrexStreamsCompiler::compile_stream(TrexStream *stream,
new_next_id = nodes.get(stream->m_next_stream_id)->m_compressed_stream_id;
}
- TrexStream *fixed_rx_flow_stat_stream = stream->clone(true);
-
- get_stateless_obj()->m_rx_flow_stat.start_stream(fixed_rx_flow_stat_stream);
- // CFlowStatRuleMgr keeps state of the stream object. We duplicated the stream here (in order not
- // change the packet kept in the stream). We want the state to be saved in the original stream.
- get_stateless_obj()->m_rx_flow_stat.copy_state(fixed_rx_flow_stat_stream, stream);
-
- fixed_rx_flow_stat_stream->update_rate_factor(factor);
+ /* we clone because we alter the stream now */
+ std::unique_ptr<TrexStream> tmp_stream(stream->clone(true));
+ tmp_stream->update_rate_factor(factor);
/* can this stream be split to many cores ? */
if ( (dp_core_count == 1) || (!stream->is_splitable(dp_core_count)) ) {
- compile_stream_on_single_core(fixed_rx_flow_stat_stream,
+ compile_stream_on_single_core(tmp_stream.get(),
dp_core_count,
objs,
new_id,
new_next_id);
} else {
- compile_stream_on_all_cores(fixed_rx_flow_stat_stream,
+ compile_stream_on_all_cores(tmp_stream.get(),
dp_core_count,
objs,
new_id,
new_next_id);
}
- delete fixed_rx_flow_stat_stream;
}
/**
diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h
index 0ce71b49..7e674364 100644
--- a/src/stateless/cp/trex_streams_compiler.h
+++ b/src/stateless/cp/trex_streams_compiler.h
@@ -141,7 +141,7 @@ private:
bool all_continues);
- void compile_stream(TrexStream *stream,
+ void compile_stream(const TrexStream *stream,
double factor,
uint8_t dp_core_count,
std::vector<TrexStreamsCompiledObj *> &objs,
@@ -244,7 +244,7 @@ public:
}
double get_factor_pps(double req_pps) const {
- if ( (req_pps - m_fixed.m_pps) <= 0 ) {
+ if ( (req_pps - m_fixed.m_pps) < 0 ) {
std::stringstream ss;
ss << "current stream configuration enforces a minimum rate of '" << m_fixed.m_pps << "' pps";
throw TrexException(ss.str());