summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHanoh Haim <hhaim@cisco.com>2015-11-11 22:10:05 +0200
committerHanoh Haim <hhaim@cisco.com>2015-11-11 22:10:05 +0200
commit151266e34245b99ce4cac70d82be79bfb5a3ebf9 (patch)
tree76bb6bad5d8b25e2918bc1e427c05618e647edec /src
parent6294136db42a3327049c67c12eab4684c4abbe47 (diff)
add support for multi-burst
Diffstat (limited to 'src')
-rwxr-xr-xsrc/bp_sim.cpp1
-rw-r--r--src/gtest/trex_stateless_gtest.cpp324
-rw-r--r--src/stateless/cp/trex_stream.h42
-rw-r--r--src/stateless/cp/trex_streams_compiler.cpp29
-rw-r--r--src/stateless/cp/trex_streams_compiler.h13
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.cpp61
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.h7
-rw-r--r--src/stateless/dp/trex_stream_node.h90
8 files changed, 464 insertions, 103 deletions
diff --git a/src/bp_sim.cpp b/src/bp_sim.cpp
index c63ad1af..39d46d16 100755
--- a/src/bp_sim.cpp
+++ b/src/bp_sim.cpp
@@ -3517,7 +3517,6 @@ int CNodeGenerator::flush_file(dsec_t max_time,
/* if the stream has been deactivated - end */
if (unlikely(!node_sl->is_active())) {
thread->free_node(node);
-
} else {
node_sl->handle(thread);
}
diff --git a/src/gtest/trex_stateless_gtest.cpp b/src/gtest/trex_stateless_gtest.cpp
index 7850e8da..1ea0373c 100644
--- a/src/gtest/trex_stateless_gtest.cpp
+++ b/src/gtest/trex_stateless_gtest.cpp
@@ -91,8 +91,7 @@ public:
lpt->start_stateless_daemon_simulation();
- lpt->m_node_gen.DumpHist(stdout);
-
+ //lpt->m_node_gen.DumpHist(stdout);
cmp.d_sec = m_time_diff;
if ( cmp.compare(std::string(buf),std::string(buf_ex)) != true ) {
@@ -121,42 +120,161 @@ public:
};
+class CPcapLoader {
+public:
+ CPcapLoader();
+ ~CPcapLoader();
+
+
+public:
+ bool load_pcap_file(std::string file,int pkt_id=0);
+ void update_ip_src(uint32_t ip_addr);
+ void clone_packet_into_stream(TrexStream * stream);
+ void dump_packet();
+
+public:
+ bool m_valid;
+ CCapPktRaw m_raw;
+ CPacketIndication m_pkt_indication;
+};
+
+CPcapLoader::~CPcapLoader(){
+}
-const uint8_t my_test_pkt[]={
+bool CPcapLoader::load_pcap_file(std::string cap_file,int pkt_id){
+ m_valid=false;
+ CPacketParser parser;
- 0x00,0x04,0x96,0x08,0xe0,0x40,
- 0x00,0x0e,0x2e,0x24,0x37,0x5f,
- 0x08,0x00,
+ CCapReaderBase * lp=CCapReaderFactory::CreateReader((char *)cap_file.c_str(),0);
- 0x45,0x02,0x00,0x30,
- 0x00,0x00,0x40,0x00,
- 0x40,0x84,0xbd,0x04,
- 0x9b,0xe6,0x18,0x9b, //sIP
- 0xcb,0xff,0xfc,0xc2, //DIP
+ if (lp == 0) {
+ printf(" ERROR file %s does not exist or not supported \n",(char *)cap_file.c_str());
+ return false;
+ }
- 0x80,0x44,//SPORT
- 0x00,0x50,//DPORT
+ int cnt=0;
+ bool found =false;
- 0x00,0x00,0x00,0x00, //checksum
- 0x11,0x22,0x33,0x44, // magic
- 0x00,0x00,0x00,0x00, //64 bit counter
- 0x00,0x00,0x00,0x00,
- 0x00,0x01,0xa0,0x00, //seq
- 0x00,0x00,0x00,0x00,
-};
+ while ( true ) {
+ /* read packet */
+ if ( lp->ReadPacket(&m_raw) ==false ){
+ break;
+ }
+ if (cnt==pkt_id) {
+ found = true;
+ break;
+ }
+ cnt++;
+ }
+ if ( found ){
+ if ( parser.ProcessPacket(&m_pkt_indication, &m_raw) ){
+ m_valid = true;
+ }
+ }
+
+ delete lp;
+ return (m_valid);
+}
+
+void CPcapLoader::update_ip_src(uint32_t ip_addr){
+
+ if ( m_pkt_indication.l3.m_ipv4 ) {
+ m_pkt_indication.l3.m_ipv4->setSourceIp(ip_addr);
+ m_pkt_indication.l3.m_ipv4->updateCheckSum();
+ }
+}
+
+void CPcapLoader::clone_packet_into_stream(TrexStream * stream){
+
+ uint16_t pkt_size=m_raw.getTotalLen();
+ uint8_t *binary = new uint8_t[pkt_size];
+ memcpy(binary,m_raw.raw,pkt_size);
+ stream->m_pkt.binary = binary;
+ stream->m_pkt.len = pkt_size;
+}
+
+
+
+
+CPcapLoader::CPcapLoader(){
+
+}
+
+void CPcapLoader::dump_packet(){
+ if (m_valid ) {
+ m_pkt_indication.Dump(stdout,1);
+ }else{
+ fprintf(stdout," no packets were found \n");
+ }
+}
+
+
+TEST_F(basic_stl, load_pcap_file) {
+ printf (" stateles %d \n",(int)sizeof(CGenNodeStateless));
+ CPcapLoader pcap;
+ pcap.load_pcap_file("cap2/udp_64B.pcap",0);
+ pcap.update_ip_src(0x10000001);
+ pcap.load_pcap_file("cap2/udp_64B.pcap",0);
+ pcap.update_ip_src(0x10000001);
+ //pcap.dump_packet();
+}
-TEST_F(basic_stl, limit_single_pkt) {
+TEST_F(basic_stl, single_pkt_burst1) {
CBasicStl t1;
CParserOption * po =&CGlobalInfo::m_options;
po->preview.setVMode(7);
po->preview.setFileWrite(true);
- po->out_file ="exp/stl_single_sctp_pkt";
+ po->out_file ="exp/stl_single_pkt_burst1";
+
+ TrexStreamsCompiler compile;
+
+
+ std::vector<TrexStream *> streams;
+
+ TrexStream * stream1 = new TrexStreamBurst(0,0,5, 1.0);
+ stream1->m_enabled = true;
+ stream1->m_self_start = true;
+
+ 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);
+
+ TrexStreamsCompiledObj comp_obj(0,1.0);
+
+ comp_obj.set_simulation_duration( 10.0);
+ assert(compile.compile(streams, comp_obj) );
+
+ TrexStatelessDpStart * lpstart = new TrexStatelessDpStart( comp_obj.clone() );
+
+
+ t1.m_msg = lpstart;
+
+ bool res=t1.init();
+
+ delete stream1 ;
+
+ EXPECT_EQ_UINT32(1, res?1:0)<< "pass";
+}
+
+
+
+
+TEST_F(basic_stl, single_pkt) {
+
+ CBasicStl t1;
+ CParserOption * po =&CGlobalInfo::m_options;
+ po->preview.setVMode(7);
+ po->preview.setFileWrite(true);
+ po->out_file ="exp/stl_single_stream";
TrexStreamsCompiler compile;
@@ -167,11 +285,11 @@ TEST_F(basic_stl, limit_single_pkt) {
stream1->m_enabled = true;
stream1->m_self_start = true;
- uint8_t *binary = new uint8_t[sizeof(my_test_pkt)];
- memcpy(binary,my_test_pkt,sizeof(my_test_pkt));
- stream1->m_pkt.binary = binary;
- stream1->m_pkt.len = sizeof(my_test_pkt);
+ 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);
@@ -196,6 +314,160 @@ TEST_F(basic_stl, limit_single_pkt) {
}
+TEST_F(basic_stl, multi_pkt1) {
+
+ CBasicStl t1;
+ CParserOption * po =&CGlobalInfo::m_options;
+ po->preview.setVMode(7);
+ po->preview.setFileWrite(true);
+ po->out_file ="exp/stl_multi_pkt1";
+
+ TrexStreamsCompiler compile;
+
+
+ std::vector<TrexStream *> streams;
+
+ TrexStream * stream1 = new TrexStreamContinuous(0,0,1.0);
+ stream1->m_enabled = true;
+ stream1->m_self_start = true;
+
+ 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);
+
+
+ TrexStream * stream2 = new TrexStreamContinuous(0,1,2.0);
+ stream2->m_enabled = true;
+ stream2->m_self_start = true;
+ stream2->m_isg_usec = 1000.0; /* 1 msec */
+ pcap.update_ip_src(0x20000001);
+ pcap.clone_packet_into_stream(stream2);
+
+ streams.push_back(stream2);
+
+
+ // stream - clean
+ TrexStreamsCompiledObj comp_obj(0,1.0);
+
+ comp_obj.set_simulation_duration( 10.0);
+ assert(compile.compile(streams, comp_obj) );
+
+ TrexStatelessDpStart * lpstart = new TrexStatelessDpStart( comp_obj.clone() );
+
+ t1.m_msg = lpstart;
+
+ bool res=t1.init();
+
+ delete stream1 ;
+ delete stream2 ;
+
+ EXPECT_EQ_UINT32(1, res?1:0)<< "pass";
+}
+
+
+
+
+
+/* check disabled stream with multiplier of 5*/
+TEST_F(basic_stl, multi_pkt2) {
+
+ CBasicStl t1;
+ CParserOption * po =&CGlobalInfo::m_options;
+ po->preview.setVMode(7);
+ po->preview.setFileWrite(true);
+ po->out_file ="exp/stl_multi_pkt2";
+
+ TrexStreamsCompiler compile;
+
+
+ std::vector<TrexStream *> streams;
+
+ TrexStream * stream1 = new TrexStreamContinuous(0,0,1.0);
+ stream1->m_enabled = true;
+ stream1->m_self_start = true;
+
+ 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);
+
+
+ TrexStream * stream2 = new TrexStreamContinuous(0,1,2.0);
+ stream2->m_enabled = false;
+ stream2->m_self_start = false;
+ stream2->m_isg_usec = 1000.0; /* 1 msec */
+ pcap.update_ip_src(0x20000001);
+ pcap.clone_packet_into_stream(stream2);
+
+ streams.push_back(stream2);
+
+
+ // stream - clean
+ TrexStreamsCompiledObj comp_obj(0,5.0);
+
+ comp_obj.set_simulation_duration( 10.0);
+ assert(compile.compile(streams, comp_obj) );
+
+ TrexStatelessDpStart * lpstart = new TrexStatelessDpStart( comp_obj.clone() );
+
+ t1.m_msg = lpstart;
+
+ bool res=t1.init();
+
+ delete stream1 ;
+ delete stream2 ;
+
+ EXPECT_EQ_UINT32(1, res?1:0)<< "pass";
+}
+
+
+TEST_F(basic_stl, multi_burst1) {
+
+ CBasicStl t1;
+ CParserOption * po =&CGlobalInfo::m_options;
+ po->preview.setVMode(7);
+ po->preview.setFileWrite(true);
+ po->out_file ="exp/stl_multi_burst1";
+
+ TrexStreamsCompiler compile;
+
+
+ std::vector<TrexStream *> streams;
+
+
+
+ TrexStream * stream1 = new TrexStreamMultiBurst(0,0,5, 1.0,3,2000000.0);
+ stream1->m_enabled = true;
+ stream1->m_self_start = true;
+
+ 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);
+
+ TrexStreamsCompiledObj comp_obj(0,1.0);
+
+ comp_obj.set_simulation_duration( 40.0);
+ assert(compile.compile(streams, comp_obj) );
+
+ TrexStatelessDpStart * lpstart = new TrexStatelessDpStart( comp_obj.clone() );
+
+
+ t1.m_msg = lpstart;
+
+ bool res=t1.init();
+
+ delete stream1 ;
+
+ EXPECT_EQ_UINT32(1, res?1:0)<< "pass";
+}
diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h
index d1a44909..5e6ac19a 100644
--- a/src/stateless/cp/trex_stream.h
+++ b/src/stateless/cp/trex_stream.h
@@ -39,6 +39,15 @@ class TrexRpcCmdAddStream;
class TrexStream {
public:
+ enum STREAM_TYPE {
+ stNONE = 0,
+ stCONTINUOUS = 4,
+ stSINGLE_BURST = 5,
+ stMULTI_BURST = 6
+ };
+
+
+public:
TrexStream(uint8_t port_id, uint32_t stream_id);
virtual ~TrexStream();
@@ -52,8 +61,14 @@ public:
/* access the stream json */
const Json::Value & get_stream_json();
+ double get_pps() {
+ return m_pps;
+ }
+
+
public:
/* basic */
+ uint8_t m_type;
uint8_t m_port_id;
uint32_t m_stream_id;
@@ -85,6 +100,8 @@ public:
} m_rx_check;
+ double m_pps;
+
/* original template provided by requester */
Json::Value m_stream_json;
@@ -98,15 +115,10 @@ public:
*/
class TrexStreamContinuous : public TrexStream {
public:
- TrexStreamContinuous(uint8_t port_id, uint32_t stream_id, double pps) : TrexStream(port_id, stream_id), m_pps(pps) {
+ TrexStreamContinuous(uint8_t port_id, uint32_t stream_id, double pps) : TrexStream(port_id, stream_id) {
+ m_type= TrexStream::stCONTINUOUS;
+ m_pps=pps;
}
-
- double get_pps() {
- return m_pps;
- }
-
-protected:
- double m_pps;
};
/**
@@ -117,13 +129,14 @@ class TrexStreamBurst : public TrexStream {
public:
TrexStreamBurst(uint8_t port_id, uint32_t stream_id, uint32_t total_pkts, double pps) :
TrexStream(port_id, stream_id),
- m_total_pkts(total_pkts),
- m_pps(pps) {
+ m_total_pkts(total_pkts){
+ m_type= TrexStream::stSINGLE_BURST;
+ m_pps=pps;
+
}
-protected:
+public:
uint32_t m_total_pkts;
- double m_pps;
};
/**
@@ -138,9 +151,10 @@ public:
double pps,
uint32_t num_bursts,
double ibg_usec) : TrexStreamBurst(port_id, stream_id, pkts_per_burst, pps), m_num_bursts(num_bursts), m_ibg_usec(ibg_usec) {
-
+ m_type= TrexStream::stMULTI_BURST;
}
-protected:
+
+public:
uint32_t m_num_bursts;
double m_ibg_usec;
diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp
index 7891077b..c7b881c5 100644
--- a/src/stateless/cp/trex_streams_compiler.cpp
+++ b/src/stateless/cp/trex_streams_compiler.cpp
@@ -30,24 +30,15 @@ TrexStreamsCompiledObj::TrexStreamsCompiledObj(uint8_t port_id, double mul) : m_
}
TrexStreamsCompiledObj::~TrexStreamsCompiledObj() {
- for (auto &obj : m_objs) {
- delete [] obj.m_pkt;
- }
m_objs.clear();
m_duration_sim=-1.0;
}
void
-TrexStreamsCompiledObj::add_compiled_stream(double isg_usec, double pps, uint8_t *pkt, uint16_t pkt_len) {
+TrexStreamsCompiledObj::add_compiled_stream(TrexStream * stream) {
obj_st obj;
- obj.m_isg_usec = isg_usec;
- obj.m_port_id = m_port_id;
- obj.m_pps = pps * m_mul;
- obj.m_pkt_len = pkt_len;
-
- obj.m_pkt = new uint8_t[pkt_len];
- memcpy(obj.m_pkt, pkt, pkt_len);
+ obj.m_stream = stream;
m_objs.push_back(obj);
}
@@ -62,10 +53,7 @@ TrexStreamsCompiledObj::clone() {
* clone each element
*/
for (auto obj : m_objs) {
- new_compiled_obj->add_compiled_stream(obj.m_isg_usec,
- obj.m_pps,
- obj.m_pkt,
- obj.m_pkt_len);
+ new_compiled_obj->add_compiled_stream(obj.m_stream);
}
new_compiled_obj->m_mul = m_mul;
@@ -93,17 +81,8 @@ TrexStreamsCompiler::compile(const std::vector<TrexStream *> &streams, TrexStrea
continue;
}
- /* for now support only continous ... */
- TrexStreamContinuous *cont_stream = dynamic_cast<TrexStreamContinuous *>(stream);
- if (!cont_stream) {
- continue;
- }
-
/* add it */
- obj.add_compiled_stream(cont_stream->m_isg_usec,
- cont_stream->get_pps(),
- cont_stream->m_pkt.binary,
- cont_stream->m_pkt.len);
+ obj.add_compiled_stream(stream);
}
return true;
diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h
index d86d16c6..78ac1ac7 100644
--- a/src/stateless/cp/trex_streams_compiler.h
+++ b/src/stateless/cp/trex_streams_compiler.h
@@ -40,11 +40,8 @@ public:
~TrexStreamsCompiledObj();
struct obj_st {
- double m_isg_usec;
- double m_pps;
- uint8_t *m_pkt;
- uint16_t m_pkt_len;
- uint8_t m_port_id;
+
+ TrexStream * m_stream;
};
const std::vector<obj_st> & get_objects() {
@@ -64,8 +61,12 @@ public:
*/
TrexStreamsCompiledObj * clone();
+ double get_multiplier(){
+ return (m_mul);
+ }
+
private:
- void add_compiled_stream(double isg_usec, double pps, uint8_t *pkt, uint16_t pkt_len);
+ void add_compiled_stream(TrexStream * stream);
std::vector<obj_st> m_objs;
uint8_t m_port_id;
diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp
index e1664bd9..899e14be 100644
--- a/src/stateless/dp/trex_stateless_dp_core.cpp
+++ b/src/stateless/dp/trex_stateless_dp_core.cpp
@@ -22,6 +22,7 @@ limitations under the License.
#include <trex_stateless_messaging.h>
#include <trex_streams_compiler.h>
#include <trex_stream_node.h>
+#include <trex_stream.h>
#include <bp_sim.h>
@@ -124,33 +125,64 @@ TrexStatelessDpCore::add_duration(double duration){
void
-TrexStatelessDpCore::add_cont_stream(uint8_t port_id,
- double isg_usec,
- double pps,
- const uint8_t *pkt,
- uint16_t pkt_len) {
+TrexStatelessDpCore::add_cont_stream(TrexStream * stream,
+ TrexStreamsCompiledObj *comp) {
CGenNodeStateless *node = m_core->create_node_sl();
/* add periodic */
node->m_type = CGenNode::STATELESS_PKT;
- node->m_time = m_core->m_cur_time_sec + usec_to_sec(isg_usec);
+ node->m_time = m_core->m_cur_time_sec + usec_to_sec(stream->m_isg_usec);
- pkt_dir_t dir = m_core->m_node_gen.m_v_if->port_id_to_dir(port_id);
+ pkt_dir_t dir = m_core->m_node_gen.m_v_if->port_id_to_dir(stream->m_port_id);
node->m_flags = 0;
/* set socket id */
node->set_socket_id(m_core->m_node_gen.m_socket_id);
/* build a mbuf from a packet */
- uint16_t pkt_size = pkt_len;
- const uint8_t *stream_pkt = pkt;
+
+ uint16_t pkt_size = stream->m_pkt.len;
+ const uint8_t *stream_pkt = stream->m_pkt.binary;
+
+ TrexStreamBurst * lpburst;
+ TrexStreamMultiBurst * lpmulti;
+
+ node->m_stream_type = stream->m_type;
+ node->m_next_time_offset = 1.0 / (stream->get_pps() * comp->get_multiplier()) ;
+
/* stateless specific fields */
- node->m_next_time_offset = 1.0 / pps;
+ switch ( stream->m_type ) {
+
+ case TrexStream::stCONTINUOUS :
+ break;
+
+ case TrexStream::stSINGLE_BURST :
+ node->m_stream_type = TrexStream::stMULTI_BURST;
+ lpburst = (TrexStreamBurst *)stream;
+ node->m_single_burst = lpburst->m_total_pkts;
+ node->m_single_burst_refill = lpburst->m_total_pkts;
+ node->m_multi_bursts = 1; /* single burst in multi burst of 1 */
+ node->m_ibg_sec = 0.0;
+ break;
+
+ case TrexStream::stMULTI_BURST :
+ lpmulti =(TrexStreamMultiBurst *)stream;
+
+ node->m_single_burst = lpmulti->m_total_pkts;
+ node->m_single_burst_refill = lpmulti->m_total_pkts ;
+ node->m_multi_bursts = lpmulti->m_num_bursts;
+ node->m_ibg_sec = usec_to_sec( lpmulti->m_ibg_usec );
+ break;
+ default:
+
+ assert(0);
+ };
+
node->m_is_stream_active = 1;
- node->m_port_id = port_id;
+ node->m_port_id = stream->m_port_id;
/* allocate const mbuf */
rte_mbuf_t *m = CGlobalInfo::pktmbuf_alloc(node->get_socket_id(), pkt_size);
@@ -183,15 +215,10 @@ TrexStatelessDpCore::add_cont_stream(uint8_t port_id,
void
TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj) {
for (auto single_stream : obj->get_objects()) {
- add_cont_stream(single_stream.m_port_id,
- single_stream.m_isg_usec,
- single_stream.m_pps,
- single_stream.m_pkt,
- single_stream.m_pkt_len);
+ add_cont_stream(single_stream.m_stream,obj);
}
double duration=obj->get_simulation_duration();
- printf("duration %f \n",duration);
if ( duration >0.0){
add_duration( duration );
diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h
index 51f882b2..1029213d 100644
--- a/src/stateless/dp/trex_stateless_dp_core.h
+++ b/src/stateless/dp/trex_stateless_dp_core.h
@@ -31,6 +31,7 @@ class TrexStatelessDpStart;
class CFlowGenListPerThread;
class CGenNodeStateless;
class TrexStreamsCompiledObj;
+class TrexStream;
class TrexStatelessDpCore {
@@ -134,11 +135,7 @@ private:
/* add global exit */
void add_duration(double duration);
- void add_cont_stream(uint8_t dir,
- double isg,
- double pps,
- const uint8_t *pkt,
- uint16_t pkt_len);
+ void add_cont_stream(TrexStream * stream,TrexStreamsCompiledObj *comp);
uint8_t m_thread_id;
state_e m_state;
diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h
index 2ffe04c3..e4cf964d 100644
--- a/src/stateless/dp/trex_stream_node.h
+++ b/src/stateless/dp/trex_stream_node.h
@@ -25,6 +25,7 @@ limitations under the License.
#include <stdio.h>
class TrexStatelessDpCore;
+#include <trex_stream.h>
/* this is a event for stateless */
struct CGenNodeStateless : public CGenNodeBase {
@@ -33,28 +34,51 @@ friend class TrexStatelessDpCore;
private:
void * m_cache_mbuf;
- double m_next_time_offset;
+ double m_next_time_offset; /* in sec */
+ double m_ibg_sec; /* inter burst time in sec */
+
+
uint8_t m_is_stream_active;
uint8_t m_port_id;
+ uint8_t m_stream_type; /* TrexStream::STREAM_TYPE */
+ uint8_t m_pad;
+
+ uint32_t m_single_burst; /* the number of bursts in case of burst */
+ uint32_t m_single_burst_refill;
+
+ uint32_t m_multi_bursts; /* in case of multi_burst how many bursts */
+
+
/* pad to match the size of CGenNode */
- uint8_t m_pad_end[87];
+ uint8_t m_pad_end[65];
public:
+ inline uint8_t get_stream_type(){
+ return (m_stream_type);
+ }
+
+ inline uint32_t get_single_burst_cnt(){
+ return (m_single_burst);
+ }
+
+ inline double get_multi_ibg_sec(){
+ return (m_ibg_sec);
+ }
+
+ inline uint32_t get_multi_burst_cnt(){
+ return (m_multi_bursts);
+ }
+
inline bool is_active() {
return m_is_stream_active;
}
-
- /**
- * main function to handle an event of a packet tx
- *
- */
- inline void handle(CFlowGenListPerThread *thread) {
+ inline void handle_continues(CFlowGenListPerThread *thread) {
thread->m_node_gen.m_v_if->send_node( (CGenNode *)this);
/* in case of continues */
@@ -64,6 +88,51 @@ public:
thread->m_node_gen.m_p_queue.push( (CGenNode *)this);
}
+ inline void handle_multi_burst(CFlowGenListPerThread *thread) {
+ thread->m_node_gen.m_v_if->send_node( (CGenNode *)this);
+
+ m_single_burst--;
+ if (m_single_burst > 0 ) {
+ /* in case of continues */
+ m_time += m_next_time_offset;
+
+ thread->m_node_gen.m_p_queue.push( (CGenNode *)this);
+ }else{
+ m_multi_bursts--;
+ if ( m_multi_bursts == 0 ) {
+ /* stop */
+ m_is_stream_active =0;
+ }else{
+ m_time += m_ibg_sec;
+ m_single_burst = m_single_burst_refill;
+
+ }
+ thread->m_node_gen.m_p_queue.push( (CGenNode *)this);
+ }
+ }
+
+
+ /**
+ * main function to handle an event of a packet tx
+ *
+ *
+ *
+ */
+
+ inline void handle(CFlowGenListPerThread *thread) {
+
+ if (m_stream_type == TrexStream::stCONTINUOUS ) {
+ handle_continues(thread) ;
+ }else{
+ if (m_stream_type == TrexStream::stMULTI_BURST) {
+ handle_multi_burst(thread);
+ }else{
+ assert(0);
+ }
+ }
+
+ }
+
void set_socket_id(socket_id_t socket){
m_socket_id=socket;
}
@@ -106,6 +175,9 @@ public:
} __rte_cache_aligned;
-static_assert(sizeof(CGenNodeStateless) == sizeof(CGenNode), "sizeof(CGenNodeStateless) != sizeof(CGenNode)");
+static_assert(sizeof(CGenNodeStateless) == sizeof(CGenNode), "sizeof(CGenNodeStateless) != sizeof(CGenNode)" );
+
+
+
#endif /* __TREX_STREAM_NODE_H__ */