summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHanoh Haim <hhaim@cisco.com>2015-11-22 18:02:22 +0200
committerHanoh Haim <hhaim@cisco.com>2015-11-22 18:02:22 +0200
commitbd8b640077591377375f2ab5ec6c542119ead0a2 (patch)
tree9349dfe4649fb14df3a3f2e27324036b1a773782
parentb08b2c0990d29141a1c6eecc6a8fed405cf8b979 (diff)
dp support for pause/resume only continues is supported
-rw-r--r--.gitignore1
-rw-r--r--scripts/exp/stl_basic_pause_resume0-0-ex.erfbin0 -> 704 bytes
-rw-r--r--src/gtest/trex_stateless_gtest.cpp73
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.cpp52
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.h18
-rw-r--r--src/stateless/dp/trex_stream_node.h19
-rw-r--r--src/stateless/messaging/trex_stateless_messaging.cpp25
-rw-r--r--src/stateless/messaging/trex_stateless_messaging.h36
8 files changed, 221 insertions, 3 deletions
diff --git a/.gitignore b/.gitignore
index 839008be..cfe53466 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,6 +30,7 @@ scripts/exp/stl_bb_start_stop2-0.erf
scripts/exp/stl_bb_start_stop3-0.erf
scripts/exp/stl_bb_start_stop_delay1-0.erf
scripts/exp/stl_bb_start_stop_delay2-0.erf
+scripts/exp/stl_basic_pause_resume0-0.erf
diff --git a/scripts/exp/stl_basic_pause_resume0-0-ex.erf b/scripts/exp/stl_basic_pause_resume0-0-ex.erf
new file mode 100644
index 00000000..7f833920
--- /dev/null
+++ b/scripts/exp/stl_basic_pause_resume0-0-ex.erf
Binary files differ
diff --git a/src/gtest/trex_stateless_gtest.cpp b/src/gtest/trex_stateless_gtest.cpp
index 5bb7fca1..8640e7db 100644
--- a/src/gtest/trex_stateless_gtest.cpp
+++ b/src/gtest/trex_stateless_gtest.cpp
@@ -379,11 +379,84 @@ TEST_F(basic_stl, load_pcap_file) {
+class CBBStartPause0: public CBasicStlSink {
+public:
+
+ virtual void call_after_init(CBasicStl * m_obj);
+ virtual void call_after_run(CBasicStl * m_obj){
+ };
+ uint8_t m_port_id;
+};
+
+
+
+void CBBStartPause0::call_after_init(CBasicStl * m_obj){
+
+ TrexStatelessDpPause * lpPauseCmd = new TrexStatelessDpPause(m_port_id);
+ TrexStatelessDpResume * lpResumeCmd1 = new TrexStatelessDpResume(m_port_id);
+
+ m_obj->m_msg_queue.add_command(m_core,lpPauseCmd, 5.0); /* command in delay of 5 sec */
+ m_obj->m_msg_queue.add_command(m_core,lpResumeCmd1, 7.0);/* command in delay of 7 sec */
+
+}
+
+
+/* start/stop/stop back to back */
+TEST_F(basic_stl, basic_pause_resume0) {
+
+ CBasicStl t1;
+ CParserOption * po =&CGlobalInfo::m_options;
+ po->preview.setVMode(7);
+ po->preview.setFileWrite(true);
+ po->out_file ="exp/stl_basic_pause_resume0";
+
+ TrexStreamsCompiler compile;
+ uint8_t port_id=0;
+
+ std::vector<TrexStream *> streams;
+
+ TrexStream * stream1 = new TrexStream(TrexStream::stCONTINUOUS,0,0);
+ stream1->set_pps(1.0);
+
+ stream1->m_enabled = true;
+ stream1->m_self_start = true;
+ stream1->m_port_id= port_id;
+
+
+ CPcapLoader pcap;
+ pcap.load_pcap_file("cap2/udp_64B.pcap",0);
+ pcap.update_ip_src(0x10000001);
+ pcap.clone_packet_into_stream(stream1);
+
+ streams.push_back(stream1);
+
+ // stream - clean
+
+ TrexStreamsCompiledObj comp_obj(port_id, 1.0 /*mul*/);
+
+ assert(compile.compile(streams, comp_obj) );
+
+ TrexStatelessDpStart * lpStartCmd = new TrexStatelessDpStart(port_id, 0, comp_obj.clone(), 10.0 /*sec */ );
+
+ t1.m_msg_queue.add_msg(lpStartCmd);
+
+
+ CBBStartPause0 sink;
+ sink.m_port_id = port_id;
+ t1.m_sink = &sink;
+
+ bool res=t1.init();
+
+ delete stream1 ;
+
+ EXPECT_EQ_UINT32(1, res?1:0)<< "pass";
+}
+//////////////////////////////////////////////////////////////
class CBBStartStopDelay2: public CBasicStlSink {
diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp
index f8afb3bb..03b13d6c 100644
--- a/src/stateless/dp/trex_stateless_dp_core.cpp
+++ b/src/stateless/dp/trex_stateless_dp_core.cpp
@@ -124,6 +124,37 @@ bool TrexStatelessDpPerPort::update_number_of_active_streams(uint32_t d){
return (false);
}
+bool TrexStatelessDpPerPort::resume_traffic(uint8_t port_id){
+
+ /* we are working with continues streams so we must be in transmit mode */
+ assert(m_state == TrexStatelessDpPerPort::ppSTATE_PAUSE);
+
+ for (auto dp_stream : m_active_nodes) {
+ CGenNodeStateless * node =dp_stream.m_node;
+ assert(node->get_port_id() == port_id);
+ assert(node->is_pause() == true);
+ node->set_pause(false);
+ }
+ m_state = TrexStatelessDpPerPort::ppSTATE_TRANSMITTING;
+ return (true);
+}
+
+
+bool TrexStatelessDpPerPort::pause_traffic(uint8_t port_id){
+
+ /* we are working with continues streams so we must be in transmit mode */
+ assert(m_state == TrexStatelessDpPerPort::ppSTATE_TRANSMITTING);
+
+ for (auto dp_stream : m_active_nodes) {
+ CGenNodeStateless * node =dp_stream.m_node;
+ assert(node->get_port_id() == port_id);
+ assert(node->is_pause() == false);
+ node->set_pause(true);
+ }
+ m_state = TrexStatelessDpPerPort::ppSTATE_PAUSE;
+ return (true);
+}
+
bool TrexStatelessDpPerPort::stop_traffic(uint8_t port_id,
bool stop_on_id,
@@ -294,6 +325,8 @@ TrexStatelessDpCore::run_once(){
}
+
+
void
TrexStatelessDpCore::start() {
@@ -402,6 +435,7 @@ TrexStatelessDpCore::add_cont_stream(TrexStatelessDpPerPort * lp_port,
uint16_t pkt_size = stream->m_pkt.len;
const uint8_t *stream_pkt = stream->m_pkt.binary;
+ node->m_pause =0;
node->m_stream_type = stream->m_type;
node->m_next_time_offset = 1.0 / (stream->get_pps() * comp->get_multiplier()) ;
@@ -529,6 +563,24 @@ bool TrexStatelessDpCore::are_all_ports_idle(){
}
+void
+TrexStatelessDpCore::resume_traffic(uint8_t port_id){
+
+ TrexStatelessDpPerPort * lp_port = get_port_db(port_id);
+
+ lp_port->resume_traffic(port_id);
+}
+
+
+void
+TrexStatelessDpCore::pause_traffic(uint8_t port_id){
+
+ TrexStatelessDpPerPort * lp_port = get_port_db(port_id);
+
+ lp_port->pause_traffic(port_id);
+}
+
+
void
TrexStatelessDpCore::stop_traffic(uint8_t port_id,
bool stop_on_id,
diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h
index 187c40d8..eda1ae59 100644
--- a/src/stateless/dp/trex_stateless_dp_core.h
+++ b/src/stateless/dp/trex_stateless_dp_core.h
@@ -53,7 +53,9 @@ public:
/* states */
enum state_e {
ppSTATE_IDLE,
- ppSTATE_TRANSMITTING
+ ppSTATE_TRANSMITTING,
+ ppSTATE_PAUSE
+
};
public:
@@ -62,6 +64,10 @@ public:
void create(CFlowGenListPerThread * core);
+ bool pause_traffic(uint8_t port_id);
+
+ bool resume_traffic(uint8_t port_id);
+
bool stop_traffic(uint8_t port_id,
bool stop_on_id,
int event_id);
@@ -143,7 +149,17 @@ public:
double duration,
int m_event_id);
+
+ /* pause the streams, work only if all are continues */
+ void pause_traffic(uint8_t port_id);
+
+
+
+ void resume_traffic(uint8_t port_id);
+
+
/**
+ *
* stop all traffic for this core
*
*/
diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h
index 20e32b78..ccf99eaa 100644
--- a/src/stateless/dp/trex_stream_node.h
+++ b/src/stateless/dp/trex_stream_node.h
@@ -48,6 +48,7 @@ public:
static_assert(sizeof(CGenNodeCommand) == sizeof(CGenNode), "sizeof(CGenNodeCommand) != sizeof(CGenNode)" );
+
/* this is a event for stateless */
struct CGenNodeStateless : public CGenNodeBase {
friend class TrexStatelessDpCore;
@@ -74,7 +75,7 @@ private:
stream_state_t m_state;
uint8_t m_port_id;
uint8_t m_stream_type; /* see TrexStream::STREAM_TYPE ,stream_type_t */
- uint8_t m_pad;
+ uint8_t m_pause;
uint32_t m_single_burst; /* the number of bursts in case of burst */
uint32_t m_single_burst_refill;
@@ -112,7 +113,18 @@ public:
/* only to be safe */
m_ref_stream_info= NULL;
m_next_stream= NULL;
+ }
+ bool is_pause(){
+ return (m_pause==1?true:false);
+ }
+
+ void set_pause(bool enable){
+ if ( enable ){
+ m_pause=1;
+ }else{
+ m_pause=0;
+ }
}
inline uint8_t get_stream_type(){
@@ -143,7 +155,10 @@ public:
void refresh();
inline void handle_continues(CFlowGenListPerThread *thread) {
- thread->m_node_gen.m_v_if->send_node( (CGenNode *)this);
+
+ if (unlikely (is_pause()==false)) {
+ thread->m_node_gen.m_v_if->send_node( (CGenNode *)this);
+ }
/* in case of continues */
m_time += m_next_time_offset;
diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp
index bbd4b68c..ec8b7839 100644
--- a/src/stateless/messaging/trex_stateless_messaging.cpp
+++ b/src/stateless/messaging/trex_stateless_messaging.cpp
@@ -87,6 +87,31 @@ void TrexStatelessDpStop::on_node_remove(){
}
+TrexStatelessCpToDpMsgBase * TrexStatelessDpPause::clone(){
+
+ TrexStatelessDpPause *new_msg = new TrexStatelessDpPause(m_port_id);
+ return new_msg;
+}
+
+
+bool TrexStatelessDpPause::handle(TrexStatelessDpCore *dp_core){
+ dp_core->pause_traffic(m_port_id);
+ return (true);
+}
+
+
+
+TrexStatelessCpToDpMsgBase * TrexStatelessDpResume::clone(){
+ TrexStatelessDpResume *new_msg = new TrexStatelessDpResume(m_port_id);
+ return new_msg;
+}
+
+bool TrexStatelessDpResume::handle(TrexStatelessDpCore *dp_core){
+ dp_core->resume_traffic(m_port_id);
+ return (true);
+}
+
+
/**
* clone for DP stop message
*
diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h
index afa5953a..6bd0dbe3 100644
--- a/src/stateless/messaging/trex_stateless_messaging.h
+++ b/src/stateless/messaging/trex_stateless_messaging.h
@@ -99,6 +99,42 @@ private:
};
+class TrexStatelessDpPause : public TrexStatelessCpToDpMsgBase {
+public:
+
+ TrexStatelessDpPause(uint8_t port_id) : m_port_id(port_id) {
+ }
+
+
+ virtual TrexStatelessCpToDpMsgBase * clone();
+
+
+ virtual bool handle(TrexStatelessDpCore *dp_core);
+
+
+private:
+ uint8_t m_port_id;
+};
+
+
+class TrexStatelessDpResume : public TrexStatelessCpToDpMsgBase {
+public:
+
+ TrexStatelessDpResume(uint8_t port_id) : m_port_id(port_id) {
+ }
+
+
+ virtual TrexStatelessCpToDpMsgBase * clone();
+
+
+ virtual bool handle(TrexStatelessDpCore *dp_core);
+
+
+private:
+ uint8_t m_port_id;
+};
+
+
/**
* a message to stop traffic
*