summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2015-11-13 14:28:54 +0200
committerimarom <imarom@cisco.com>2015-11-13 14:28:54 +0200
commit1f98e85aba1fb41110ea9743a69c075eeb60f476 (patch)
treee5c4216361e75df62d4790ec50776451c979b5ea /src
parent57e67fd2ae248039951798978cc8c1c219c3d752 (diff)
parent45b71cff9d0465b77f82e4cd40b64a9f3183c1c7 (diff)
Merge branch 'rpc_intg1' of csi-sceasr-b45:/auto/proj-pcube-b/apps/PL-b/tools/repo//trex-core into rpc_intg1
Diffstat (limited to 'src')
-rwxr-xr-xsrc/bp_gtest.cpp18
-rwxr-xr-xsrc/bp_sim.cpp173
-rwxr-xr-xsrc/bp_sim.h46
-rw-r--r--src/gtest/trex_stateless_gtest.cpp603
-rwxr-xr-xsrc/main.cpp47
-rwxr-xr-xsrc/msg_manager.cpp26
-rwxr-xr-xsrc/msg_manager.h1
-rwxr-xr-xsrc/pal/linux/mbuf.cpp7
-rwxr-xr-xsrc/pal/linux/mbuf.h2
-rwxr-xr-xsrc/pal/linux_dpdk/mbuf.h4
-rwxr-xr-xsrc/platform_cfg.cpp2
-rwxr-xr-xsrc/platform_cfg.h2
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_stream.cpp14
-rw-r--r--src/stateless/cp/trex_stream.cpp9
-rw-r--r--src/stateless/cp/trex_stream.h150
-rw-r--r--src/stateless/cp/trex_streams_compiler.cpp34
-rw-r--r--src/stateless/cp/trex_streams_compiler.h21
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.cpp98
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.h17
-rw-r--r--src/stateless/dp/trex_stream_node.h100
-rw-r--r--src/stateless/messaging/trex_stateless_messaging.h1
21 files changed, 931 insertions, 444 deletions
diff --git a/src/bp_gtest.cpp b/src/bp_gtest.cpp
index 03ab74bd..a94c2d37 100755
--- a/src/bp_gtest.cpp
+++ b/src/bp_gtest.cpp
@@ -131,16 +131,6 @@ int test_human_p(){
-static bool was_init=false;
-
-void gtest_init_once(){
-
- if ( !was_init ){
- CGlobalInfo::init_pools(1000);
- time_init();
- was_init=true;
- }
-}
@@ -259,7 +249,6 @@ public:
class basic : public testing::Test {
protected:
virtual void SetUp() {
- gtest_init_once();
}
virtual void TearDown() {
}
@@ -269,7 +258,6 @@ public:
class cpu : public testing::Test {
protected:
virtual void SetUp() {
- gtest_init_once();
}
virtual void TearDown() {
}
@@ -1199,7 +1187,6 @@ TEST_F(cpu, cpu3) {
class timerwl : public testing::Test {
protected:
virtual void SetUp() {
- gtest_init_once();
}
virtual void TearDown() {
}
@@ -1450,7 +1437,6 @@ TEST_F(timerwl, many_timers_with_stop) {
class rx_check : public testing::Test {
protected:
virtual void SetUp() {
- gtest_init_once();
m_rx_check.Create();
}
@@ -2142,7 +2128,6 @@ public:
class rx_check_system : public testing::Test {
protected:
virtual void SetUp() {
- gtest_init_once();
m_rx_check.m_callback=&m_callback;
m_callback.mg =&m_mg;
@@ -2420,8 +2405,6 @@ public:
class nat_check_system : public testing::Test {
protected:
virtual void SetUp() {
- gtest_init_once();
-
m_rx_check.m_callback=&m_callback;
m_callback.mg =&m_mg;
m_mg.Create();
@@ -2467,7 +2450,6 @@ class file_flow_info : public testing::Test {
protected:
virtual void SetUp() {
- gtest_init_once();
assert(m_flow_info.Create());
}
diff --git a/src/bp_sim.cpp b/src/bp_sim.cpp
index 0c0cbb75..39d46d16 100755
--- a/src/bp_sim.cpp
+++ b/src/bp_sim.cpp
@@ -496,6 +496,26 @@ void CRteMemPool::dump(FILE *fd){
}
////////////////////////////////////////
+
+void CGlobalInfo::free_pools(){
+ CPlatformSocketInfo * lpSocket =&m_socket;
+ CRteMemPool * lpmem;
+ int i;
+ for (i=0; i<(int)MAX_SOCKETS_SUPPORTED; i++) {
+ if (lpSocket->is_sockets_enable((socket_id_t)i)) {
+ lpmem= &m_mem_pool[i];
+ utl_rte_mempool_delete(lpmem->m_big_mbuf_pool);
+ utl_rte_mempool_delete(lpmem->m_small_mbuf_pool);
+ utl_rte_mempool_delete(lpmem->m_mbuf_pool_128);
+ utl_rte_mempool_delete(lpmem->m_mbuf_pool_256);
+ utl_rte_mempool_delete(lpmem->m_mbuf_pool_512);
+ utl_rte_mempool_delete(lpmem->m_mbuf_pool_1024);
+ }
+ utl_rte_mempool_delete(m_mem_pool[0].m_mbuf_global_nodes);
+ }
+}
+
+
void CGlobalInfo::init_pools(uint32_t rx_buffers){
/* this include the pkt from 64- */
CGlobalMemory * lp=&CGlobalInfo::m_memory_cfg;
@@ -748,9 +768,7 @@ int CErfIF::write_pkt(CCapPktRaw *pkt_raw){
int CErfIF::close_file(void){
BP_ASSERT(m_raw);
- m_raw->raw=0;
delete m_raw;
-
if ( m_preview_mode->getFileWrite() ){
BP_ASSERT(m_writer);
delete m_writer;
@@ -3054,6 +3072,16 @@ void CGenNode::DumpHeader(FILE *fd){
fprintf(fd," pkt_id,time,fid,pkt_info,pkt,len,type,is_init,is_last,type,thread_id,src_ip,dest_ip,src_port \n");
}
+
+void CGenNode::free_gen_node(){
+ rte_mbuf_t * m=get_cache_mbuf();
+ if ( unlikely(m != NULL) ) {
+ rte_pktmbuf_free(m);
+ m_plugin_info=0;
+ }
+}
+
+
void CGenNode::Dump(FILE *fd){
fprintf(fd,"%.6f,%llx,%p,%llu,%d,%d,%d,%d,%d,%d,%x,%x,%d\n",
m_time,
@@ -3123,6 +3151,15 @@ int CNodeGenerator::close_file(CFlowGenListPerThread * thread){
return (0);
}
+int CNodeGenerator::update_stl_stats(CGenNodeStateless *node_sl){
+ if ( m_preview_mode.getVMode() >2 ){
+ fprintf(stdout," %llu ,", (unsigned long long)m_cnt);
+ node_sl->Dump(stdout);
+ m_cnt++;
+ }
+ return (0);
+}
+
int CNodeGenerator::update_stats(CGenNode * node){
if ( m_preview_mode.getVMode() >2 ){
@@ -3361,6 +3398,7 @@ void CFlowGenListPerThread::Delete(){
Clean();
m_cpu_cp_u.Delete();
+ utl_rte_mempool_delete(m_node_pool);
}
@@ -3462,9 +3500,9 @@ int CNodeGenerator::flush_file(dsec_t max_time,
}
}
- #ifndef RTE_DPDK
- thread->check_msgs();
- #endif
+ //#ifndef RTE_DPDK
+ //thread->check_msgs();
+ //#endif
uint8_t type=node->m_type;
@@ -3472,6 +3510,10 @@ int CNodeGenerator::flush_file(dsec_t max_time,
m_p_queue.pop();
CGenNodeStateless *node_sl = (CGenNodeStateless *)node;
+ #ifdef _DEBUG
+ update_stl_stats(node_sl);
+ #endif
+
/* if the stream has been deactivated - end */
if (unlikely(!node_sl->is_active())) {
thread->free_node(node);
@@ -3899,41 +3941,26 @@ void CFlowGenListPerThread::check_msgs(void) {
}
}
-void delay(int msec);
+//void delay(int msec);
-const uint8_t test_udp_pkt[]={
- 0x00,0x00,0x00,0x01,0x00,0x00,
- 0x00,0x00,0x00,0x01,0x00,0x00,
- 0x08,0x00,
- 0x45,0x00,0x00,0x81,
- 0xaf,0x7e,0x00,0x00,
- 0x12,0x11,0xd9,0x23,
- 0x01,0x01,0x01,0x01,
- 0x3d,0xad,0x72,0x1b,
-
- 0x11,0x11,
- 0x11,0x11,
-
- 0x00,0x6d,
- 0x00,0x00,
-
- 0x64,0x31,0x3a,0x61,
- 0x64,0x32,0x3a,0x69,0x64,
- 0x32,0x30,0x3a,0xd0,0x0e,
- 0xa1,0x4b,0x7b,0xbd,0xbd,
- 0x16,0xc6,0xdb,0xc4,0xbb,0x43,
- 0xf9,0x4b,0x51,0x68,0x33,0x72,
- 0x20,0x39,0x3a,0x69,0x6e,0x66,0x6f,
- 0x5f,0x68,0x61,0x73,0x68,0x32,0x30,0x3a,0xee,0xc6,0xa3,
- 0xd3,0x13,0xa8,0x43,0x06,0x03,0xd8,0x9e,0x3f,0x67,0x6f,
- 0xe7,0x0a,0xfd,0x18,0x13,0x8d,0x65,0x31,0x3a,0x71,0x39,
- 0x3a,0x67,0x65,0x74,0x5f,0x70,0x65,0x65,0x72,0x73,0x31,
- 0x3a,0x74,0x38,0x3a,0x3d,0xeb,0x0c,0xbf,0x0d,0x6a,0x0d,
- 0xa5,0x31,0x3a,0x79,0x31,0x3a,0x71,0x65,0x87,0xa6,0x7d,
- 0xe7
-};
+void CFlowGenListPerThread::start_stateless_simulation_file(std::string erf_file_name,
+ CPreviewMode &preview){
+ m_preview_mode = preview;
+ m_node_gen.open_file(erf_file_name,&m_preview_mode);
+}
+
+void CFlowGenListPerThread::stop_stateless_simulation_file(){
+ m_node_gen.close_file(this);
+}
+
+void CFlowGenListPerThread::start_stateless_daemon_simulation(){
+
+ m_cur_time_sec = 0;
+ m_stateless_dp_info.run_once();
+
+}
void CFlowGenListPerThread::start_stateless_daemon(){
m_cur_time_sec = 0;
@@ -4002,6 +4029,12 @@ void CFlowGenListPerThread::start_generate_stateful(std::string erf_file_name,
m_node_gen.close_file(this);
}
+void CFlowGenList::Delete(){
+ clean_p_thread_info();
+ Clean();
+ delete CPluginCallback::callback;
+}
+
bool CFlowGenList::Create(){
check_objects_sizes();
@@ -4033,10 +4066,6 @@ void CFlowGenList::clean_p_thread_info(void){
}
-void CFlowGenList::Delete(){
- clean_p_thread_info();
- Clean();
-}
int CFlowGenList::load_from_mac_file(std::string file_name) {
if ( !utl_is_file_exists (file_name) ){
@@ -4570,24 +4599,54 @@ int CNullIF::send_node(CGenNode * node){
}
-int CErfIF::send_node(CGenNode * node){
- if ( m_preview_mode->getFileWrite() ){
- CFlowPktInfo * lp=node->m_pkt_info;
- rte_mbuf_t * m=lp->generate_new_mbuf(node);
+void CErfIF::fill_raw_packet(rte_mbuf_t * m,CGenNode * node,pkt_dir_t dir){
fill_pkt(m_raw,m);
+
CPktNsecTimeStamp t_c(node->m_time);
m_raw->time_nsec = t_c.m_time_nsec;
m_raw->time_sec = t_c.m_time_sec;
-
- pkt_dir_t dir=node->cur_interface_dir();
uint8_t p_id = (uint8_t)dir;
-
m_raw->setInterface(p_id);
+}
+
+
+int CErfIFStl::send_node(CGenNode * _no_to_use){
+
+ if ( m_preview_mode->getFileWrite() ){
+
+ CGenNodeStateless * node_sl=(CGenNodeStateless *) _no_to_use;
+
+ /* check that we have mbuf */
+ rte_mbuf_t * m=node_sl->get_cache_mbuf();
+ assert( m );
+ pkt_dir_t dir=(pkt_dir_t)node_sl->get_mbuf_cache_dir();
+
+ fill_raw_packet(m,_no_to_use,dir);
+ BP_ASSERT(m_writer);
+ bool res=m_writer->write_packet(m_raw);
+
+
+ BP_ASSERT(res);
+ }
+ return (0);
+}
+
+
+int CErfIF::send_node(CGenNode * node){
+
+ if ( m_preview_mode->getFileWrite() ){
+
+ CFlowPktInfo * lp=node->m_pkt_info;
+ rte_mbuf_t * m=lp->generate_new_mbuf(node);
+ pkt_dir_t dir=node->cur_interface_dir();
+
+ fill_raw_packet(m,node,dir);
/* update mac addr dest/src 12 bytes */
uint8_t *p=(uint8_t *)m_raw->raw;
+ int p_id=(int)dir;
memcpy(p,CGlobalInfo::m_options.get_dst_src_mac_addr(p_id),12);
/* If vlan is enabled, add vlan header */
@@ -6807,6 +6866,24 @@ bool CSimplePacketParser::Parse(){
}
+/* free the right object.
+ it is classic to use virtual function but we can't do it here and we don't even want to use callback function
+ as we want to save space and in most cases there is nothing to free.
+ this might be changed in the future
+ */
+void CGenNodeBase::free_base(){
+ if ( m_type == FLOW_PKT ) {
+ CGenNode* p=(CGenNode*)this;
+ p->free_gen_node();
+ return;
+ }
+ if (m_type==STATELESS_PKT) {
+ CGenNodeStateless* p=(CGenNodeStateless*)this;
+ p->free_stl_node();
+ return;
+ }
+}
+
diff --git a/src/bp_sim.h b/src/bp_sim.h
index 36595581..eef5576b 100755
--- a/src/bp_sim.h
+++ b/src/bp_sim.h
@@ -328,6 +328,9 @@ public:
CVirtualIF (){
m_preview_mode =NULL;
}
+
+ virtual ~CVirtualIF(){
+ }
public:
virtual int open_file(std::string file_name)=0;
@@ -1140,6 +1143,9 @@ public:
class CGlobalInfo {
public:
static void init_pools(uint32_t rx_buffers);
+ /* for simulation */
+ static void free_pools();
+
static inline rte_mbuf_t * pktmbuf_alloc_small(socket_id_t socket){
return ( m_mem_pool[socket].pktmbuf_alloc_small() );
@@ -1376,7 +1382,9 @@ public:
FLOW_PKT_NAT =3,
FLOW_SYNC =4, /* called evey 1 msec */
STATELESS_PKT =5,
- EXIT_SCHED =6
+ EXIT_SCHED =6,
+ EXIT_PORT_SCHED =7
+
};
@@ -1432,6 +1440,7 @@ public:
}
+ void free_base();
};
@@ -1466,6 +1475,9 @@ public:
uint32_t m_dest_idx;
uint32_t m_end_of_cache_line[6];
+
+public:
+ void free_gen_node();
public:
void Dump(FILE *fd);
@@ -1652,6 +1664,8 @@ public:
+
+
#if __x86_64__
/* size of 64 bytes */
#define DEFER_CLIENTS_NUM (16)
@@ -1802,11 +1816,24 @@ public:
virtual int flush_tx_queue(void);
-private:
+protected:
+
+ void fill_raw_packet(rte_mbuf_t * m,CGenNode * node,pkt_dir_t dir);
+
CFileWriterBase * m_writer;
CCapPktRaw * m_raw;
};
+/* for stateless we have a small changes in case we send the packets for optimization */
+class CErfIFStl : public CErfIF {
+
+public:
+
+ virtual int send_node(CGenNode * node);
+};
+
+
+
static inline int fill_pkt(CCapPktRaw * raw,rte_mbuf_t * m){
raw->pkt_len = m->pkt_len;
char *p=raw->raw;
@@ -1903,6 +1930,8 @@ private:
return (m_v_if->send_node(node));
}
int update_stats(CGenNode * node);
+ int update_stl_stats(CGenNodeStateless *node_sl);
+
FORCE_NO_INLINE bool handle_slow_messages(uint8_t type,
CGenNode * node,
@@ -3412,6 +3441,14 @@ public:
void start_generate_stateful(std::string erf_file_name,CPreviewMode &preview);
void start_stateless_daemon();
+ void start_stateless_daemon_simulation();
+
+ /* open a file for simulation */
+ void start_stateless_simulation_file(std::string erf_file_name,CPreviewMode &preview);
+ /* close a file for simulation */
+ void stop_stateless_simulation_file();
+
+
void Dump(FILE *fd);
void DumpCsv(FILE *fd);
@@ -3519,7 +3556,10 @@ inline CGenNode * CFlowGenListPerThread::create_node(void){
return (res);
}
+
+
inline void CFlowGenListPerThread::free_node(CGenNode *p){
+ p->free_base();
rte_mempool_sp_put(m_node_pool, p);
}
@@ -4033,6 +4073,8 @@ enum MINVM_PLUGIN_ID{
class CPluginCallback {
public:
+ virtual ~CPluginCallback(){
+ }
virtual void on_node_first(uint8_t plugin_id,CGenNode * node,CFlowYamlInfo * template_info, CTupleTemplateGeneratorSmart * tuple_gen,CFlowGenListPerThread * flow_gen) =0;
virtual void on_node_last(uint8_t plugin_id,CGenNode * node)=0;
virtual rte_mbuf_t * on_node_generate_mbuf(uint8_t plugin_id,CGenNode * node,CFlowPktInfo * pkt_info)=0;
diff --git a/src/gtest/trex_stateless_gtest.cpp b/src/gtest/trex_stateless_gtest.cpp
index 2bab4dff..8b96ef88 100644
--- a/src/gtest/trex_stateless_gtest.cpp
+++ b/src/gtest/trex_stateless_gtest.cpp
@@ -22,332 +22,471 @@ limitations under the License.
#include "bp_sim.h"
#include <common/gtest.h>
#include <common/basic_utils.h>
+#include <trex_stateless_dp_core.h>
+#include <trex_stateless_messaging.h>
+#include <trex_streams_compiler.h>
+#include <trex_stream_node.h>
+#include <trex_stream.h>
+#include <trex_stateless_port.h>
+#include <trex_rpc_server_api.h>
#define EXPECT_EQ_UINT32(a,b) EXPECT_EQ((uint32_t)(a),(uint32_t)(b))
-// one stream info with const packet , no VM
-class CTRexDpStatelessVM {
+
+/* basic stateless test */
+class basic_stl : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ }
+ virtual void TearDown() {
+ }
+public:
};
-//- add dump function
-// - check one object
-// create frame work
-class CTRexDpStreamModeContinues{
+
+class CBasicStl {
+
public:
- void set_pps(double pps){
- m_pps=pps;
+ CBasicStl(){
+ m_time_diff=0.001;
+ m_threads=1;
+ m_dump_json=false;
}
- double get_pps(){
- return (m_pps);
+
+ bool init(void){
+
+ CErfIFStl erf_vif;
+ fl.Create();
+ fl.generate_p_thread_info(1);
+ CFlowGenListPerThread * lpt;
+
+ fl.m_threads_info[0]->set_vif(&erf_vif);
+
+ CErfCmp cmp;
+ cmp.dump=1;
+
+ CMessagingManager * cp_dp = CMsgIns::Ins()->getCpDp();
+
+ m_ring_from_cp = cp_dp->getRingCpToDp(0);
+
+
+ bool res=true;
+
+ lpt=fl.m_threads_info[0];
+
+ char buf[100];
+ char buf_ex[100];
+ sprintf(buf,"%s-%d.erf",CGlobalInfo::m_options.out_file.c_str(),0);
+ sprintf(buf_ex,"%s-%d-ex.erf",CGlobalInfo::m_options.out_file.c_str(),0);
+
+ lpt->start_stateless_simulation_file(buf,CGlobalInfo::m_options.preview);
+
+ /* add stream to the queue */
+ assert(m_msg);
+
+ assert(m_ring_from_cp->Enqueue((CGenNode *)m_msg)==0);
+
+ lpt->start_stateless_daemon_simulation();
+
+ //lpt->m_node_gen.DumpHist(stdout);
+
+ cmp.d_sec = m_time_diff;
+ if ( cmp.compare(std::string(buf),std::string(buf_ex)) != true ) {
+ res=false;
+ }
+
+ if ( m_dump_json ){
+ printf(" dump json ...........\n");
+ std::string s;
+ fl.m_threads_info[0]->m_node_gen.dump_json(s);
+ printf(" %s \n",s.c_str());
+ }
+
+ fl.Delete();
+ return (res);
}
- void dump(FILE *fd);
-private:
- double m_pps;
+
+public:
+ int m_threads;
+ double m_time_diff;
+ bool m_dump_json;
+ TrexStatelessCpToDpMsgBase * m_msg;
+ CNodeRing *m_ring_from_cp;
+ CFlowGenList fl;
};
-void CTRexDpStreamModeContinues::dump(FILE *fd){
- fprintf (fd," pps : %f \n",m_pps);
-}
+class CPcapLoader {
+public:
+ CPcapLoader();
+ ~CPcapLoader();
-class CTRexDpStreamModeSingleBurst{
public:
- void set_pps(double pps){
- m_pps=pps;
+ 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(){
+}
+
+bool CPcapLoader::load_pcap_file(std::string cap_file,int pkt_id){
+ m_valid=false;
+ CPacketParser parser;
+
+ CCapReaderBase * lp=CCapReaderFactory::CreateReader((char *)cap_file.c_str(),0);
+
+ if (lp == 0) {
+ printf(" ERROR file %s does not exist or not supported \n",(char *)cap_file.c_str());
+ return false;
+ }
+
+ int cnt=0;
+ bool found =false;
+
+
+ while ( true ) {
+ /* read packet */
+ if ( lp->ReadPacket(&m_raw) ==false ){
+ break;
+ }
+ if (cnt==pkt_id) {
+ found = true;
+ break;
+ }
+ cnt++;
}
- double get_pps(){
- return (m_pps);
+ if ( found ){
+ if ( parser.ProcessPacket(&m_pkt_indication, &m_raw) ){
+ m_valid = true;
+ }
}
- void set_total_packets(uint64_t total_packets){
- m_total_packets =total_packets;
+ 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();
- uint64_t get_total_packets(){
- return (m_total_packets);
+ 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");
}
+}
- void dump(FILE *fd);
-private:
- double m_pps;
- uint64_t m_total_packets;
-};
+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);
-void CTRexDpStreamModeSingleBurst::dump(FILE *fd){
- fprintf (fd," pps : %f \n",m_pps);
- fprintf (fd," total_packets : %llu \n", (unsigned long long)m_total_packets);
+ //pcap.dump_packet();
}
-class CTRexDpStreamModeMultiBurst{
-public:
- void set_pps(double pps){
- m_pps=pps;
- }
- double get_pps(){
- return (m_pps);
- }
+TEST_F(basic_stl, single_pkt_burst1) {
- void set_pkts_per_burst(uint64_t pkts_per_burst){
- m_pkts_per_burst =pkts_per_burst;
- }
+ CBasicStl t1;
+ CParserOption * po =&CGlobalInfo::m_options;
+ po->preview.setVMode(7);
+ po->preview.setFileWrite(true);
+ po->out_file ="exp/stl_single_pkt_burst1";
- uint64_t get_pkts_per_burst(){
- return (m_pkts_per_burst);
- }
+ TrexStreamsCompiler compile;
- void set_ibg(double ibg){
- m_ibg = ibg;
- }
- double get_ibg(){
- return ( m_ibg );
- }
+ std::vector<TrexStream *> streams;
- void set_number_of_bursts(uint32_t number_of_bursts){
- m_number_of_bursts = number_of_bursts;
- }
+ TrexStream * stream1 = new TrexStream(TrexStream::stSINGLE_BURST, 0,0);
+ stream1->set_pps(1.0);
+ stream1->set_signle_burtst(5);
+ stream1->m_enabled = true;
+ stream1->m_self_start = true;
- uint32_t get_number_of_bursts(){
- return (m_number_of_bursts);
- }
+ CPcapLoader pcap;
+ pcap.load_pcap_file("cap2/udp_64B.pcap",0);
+ pcap.update_ip_src(0x10000001);
+ pcap.clone_packet_into_stream(stream1);
- void dump(FILE *fd);
+ streams.push_back(stream1);
-private:
- double m_pps;
- double m_ibg; // inter burst gap
- uint64_t m_pkts_per_burst;
- uint32_t m_number_of_bursts;
-};
+ 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;
-void CTRexDpStreamModeMultiBurst::dump(FILE *fd){
- fprintf (fd," pps : %f \n",m_pps);
- fprintf (fd," total_packets : %llu \n", (unsigned long long)m_pkts_per_burst);
- fprintf (fd," ibg : %f \n",m_ibg);
- fprintf (fd," num_of_bursts : %lu \n", (ulong)m_number_of_bursts);
+ bool res=t1.init();
+
+ delete stream1 ;
+
+ EXPECT_EQ_UINT32(1, res?1:0)<< "pass";
}
-class CTRexDpStreamMode {
-public:
- enum MODES {
- moCONTINUES = 0x0,
- moSINGLE_BURST = 0x1,
- moMULTI_BURST = 0x2
- } ;
- typedef uint8_t MODE_TYPE_t;
- void reset();
+TEST_F(basic_stl, single_pkt) {
- void set_mode(MODE_TYPE_t mode ){
- m_type = mode;
- }
+ CBasicStl t1;
+ CParserOption * po =&CGlobalInfo::m_options;
+ po->preview.setVMode(7);
+ po->preview.setFileWrite(true);
+ po->out_file ="exp/stl_single_stream";
- MODE_TYPE_t get_mode(){
- return (m_type);
- }
+ TrexStreamsCompiler compile;
- CTRexDpStreamModeContinues & cont(void){
- return (m_data.m_cont);
- }
- CTRexDpStreamModeSingleBurst & single_burst(void){
- return (m_data.m_signle_burst);
- }
+ std::vector<TrexStream *> streams;
- CTRexDpStreamModeMultiBurst & multi_burst(void){
- return (m_data.m_multi_burst);
- }
+ TrexStream * stream1 = new TrexStream(TrexStream::stCONTINUOUS,0,0);
+ stream1->set_pps(1.0);
- void dump(FILE *fd);
+
+ stream1->m_enabled = true;
+ stream1->m_self_start = true;
-private:
- uint8_t m_type;
- union Data {
- CTRexDpStreamModeContinues m_cont;
- CTRexDpStreamModeSingleBurst m_signle_burst;
- CTRexDpStreamModeMultiBurst m_multi_burst;
- } m_data;
-};
+ 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(0,1.0);
+
+ comp_obj.set_simulation_duration( 10.0);
+ assert(compile.compile(streams, comp_obj) );
-void CTRexDpStreamMode::reset(){
- m_type =CTRexDpStreamMode::moCONTINUES;
- memset(&m_data,0,sizeof(m_data));
+ 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";
}
-
-void CTRexDpStreamMode::dump(FILE *fd){
- const char * table[3] = {"CONTINUES","SINGLE_BURST","MULTI_BURST"};
-
- fprintf(fd," mode : %s \n", (char*)table[m_type]);
- switch (m_type) {
- case CTRexDpStreamMode::moCONTINUES :
- cont().dump(fd);
- break;
- case CTRexDpStreamMode::moSINGLE_BURST :
- single_burst().dump(fd);
- break;
- case CTRexDpStreamMode::moMULTI_BURST :
- multi_burst().dump(fd);
- break;
- default:
- fprintf(fd," ERROR type if not valid %d \n",m_type);
- break;
- }
+
+
+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 TrexStream(TrexStream::stCONTINUOUS,0,0);
+ stream1->set_pps(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 TrexStream(TrexStream::stCONTINUOUS,0,0);
+ stream2->set_pps(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";
}
-class CTRexDpStatelessStream {
-public:
- enum FLAGS_0{
- _ENABLE = 0,
- _SELF_START = 1,
- _VM_ENABLE =2,
- _END_STREAM =-1
- };
-
- CTRexDpStatelessStream(){
- reset();
- }
+/* check disabled stream with multiplier of 5*/
+TEST_F(basic_stl, multi_pkt2) {
- void reset(){
- m_packet =0;
- m_vm=0;
- m_flags=0;
- m_isg_sec=0.0;
- m_next_stream = CTRexDpStatelessStream::_END_STREAM ; // END
- m_mode.reset();
- }
+ CBasicStl t1;
+ CParserOption * po =&CGlobalInfo::m_options;
+ po->preview.setVMode(7);
+ po->preview.setFileWrite(true);
+ po->out_file ="exp/stl_multi_pkt2";
- void set_enable(bool enable){
- btSetMaskBit32(m_flags,_ENABLE,_ENABLE,enable?1:0);
- }
+ TrexStreamsCompiler compile;
- bool get_enabled(){
- return (btGetMaskBit32(m_flags,_ENABLE,_ENABLE)?true:false);
- }
- void set_self_start(bool enable){
- btSetMaskBit32(m_flags,_SELF_START,_SELF_START,enable?1:0);
- }
+ std::vector<TrexStream *> streams;
- bool get_self_start(bool enable){
- return (btGetMaskBit32(m_flags,_SELF_START,_SELF_START)?true:false);
- }
+ TrexStream * stream1 = new TrexStream(TrexStream::stCONTINUOUS,0,0);
+ stream1->set_pps(1.0);
- /* if we don't have VM we could just replicate the mbuf and allocate it once */
- void set_vm_enable(bool enable){
- btSetMaskBit32(m_flags,_VM_ENABLE,_VM_ENABLE,enable?1:0);
- }
- bool get_vm_enabled(bool enable){
- return (btGetMaskBit32(m_flags,_VM_ENABLE,_VM_ENABLE)?true:false);
- }
+ stream1->m_enabled = true;
+ stream1->m_self_start = true;
- void set_inter_stream_gap(double isg_sec){
- m_isg_sec =isg_sec;
- }
+ CPcapLoader pcap;
+ pcap.load_pcap_file("cap2/udp_64B.pcap",0);
+ pcap.update_ip_src(0x10000001);
+ pcap.clone_packet_into_stream(stream1);
- double get_inter_stream_gap(){
- return (m_isg_sec);
- }
+ streams.push_back(stream1);
- CTRexDpStreamMode & get_mode();
+ TrexStream * stream2 = new TrexStream(TrexStream::stCONTINUOUS,0,1);
+ stream2->set_pps(2.0);
- // CTRexDpStatelessStream::_END_STREAM for END
- void set_next_stream(int32_t next_stream){
- m_next_stream =next_stream;
- }
+ 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);
- int32_t get_next_stream(void){
- return ( m_next_stream );
- }
+ streams.push_back(stream2);
- void dump(FILE *fd);
-private:
- char * m_packet;
- CTRexDpStatelessVM * m_vm;
- uint32_t m_flags;
- double m_isg_sec; // in second
- CTRexDpStreamMode m_mode;
- int32_t m_next_stream; // next stream id
-};
+ // stream - clean
+ TrexStreamsCompiledObj comp_obj(0,5.0);
-//- list of streams info with const packet , no VM
-// - object that include the stream /scheduler/ packet allocation / need to create an object for one thread that works for test
-// generate pcap file and compare it
+ comp_obj.set_simulation_duration( 10.0);
+ assert(compile.compile(streams, comp_obj) );
-#if 0
-void CTRexDpStatelessStream::dump(FILE *fd){
+ TrexStatelessDpStart * lpstart = new TrexStatelessDpStart( comp_obj.clone() );
- fprintf(fd," enabled : %d \n",get_enabled()?1:0);
- fprintf(fd," self_start : %d \n",get_self_start()?1:0);
- fprintf(fd," vm : %d \n",get_vm_enabled()?1:0);
- fprintf(" isg : %f \n",m_isg_sec);
- m_mode.dump(fd);
- if (m_next_stream == CTRexDpStatelessStream::_END_STREAM ) {
- fprintf(fd," action : End of Stream \n");
- }else{
- fprintf(" next : %d \n",m_next_stream);
- }
+ 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) {
-class CTRexStatelessBasic {
+ CBasicStl t1;
+ CParserOption * po =&CGlobalInfo::m_options;
+ po->preview.setVMode(7);
+ po->preview.setFileWrite(true);
+ po->out_file ="exp/stl_multi_burst1";
-public:
- CTRexStatelessBasic(){
- m_threads=1;
- }
+ TrexStreamsCompiler compile;
- bool init(void){
- return (true);
- }
-public:
- bool m_threads;
-};
+ std::vector<TrexStream *> streams;
+ TrexStream * stream1 = new TrexStream(TrexStream::stMULTI_BURST,0,0);
+ stream1->set_pps(1.0);
+ stream1->set_multi_burst(5,
+ 3,
+ 2000000.0);
-/* stateless basic */
-class dp_sl_basic : public testing::Test {
- protected:
- virtual void SetUp() {
- }
- virtual void TearDown() {
- }
-public:
-};
+ 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 ;
-TEST_F(dp_sl_basic, test1) {
- CTRexDpStatelessStream s1;
- s1.set_enable(true);
- s1.set_self_start(true);
- s1.set_inter_stream_gap(0.77);
- s1.get_mode().set_mode(CTRexDpStreamMode::moCONTINUES);
- s1.get_mode().cont().set_pps(100.2);
- s1.dump(stdout);
+ EXPECT_EQ_UINT32(1, res?1:0)<< "pass";
}
-#endif
diff --git a/src/main.cpp b/src/main.cpp
index df9d8b40..64547d57 100755
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -26,6 +26,8 @@ limitations under the License.
#include <common/arg/SimpleGlob.h>
#include <common/arg/SimpleOpt.h>
+#include <stateless/cp/trex_stateless.h>
+
// An enum for all the option types
enum { OPT_HELP, OPT_CFG, OPT_NODE_DUMP, OP_STATS,
@@ -94,21 +96,20 @@ static int usage(){
int gtest_main(int argc, char **argv) ;
-static int parse_options(int argc, char *argv[], CParserOption* po ) {
+static int parse_options(int argc, char *argv[], CParserOption* po, bool & is_gtest ) {
CSimpleOpt args(argc, argv, parser_options);
int a=0;
int node_dump=0;
po->preview.clean();
po->preview.setFileWrite(true);
- int res1;
while ( args.Next() ){
if (args.LastError() == SO_SUCCESS) {
switch (args.OptionId()) {
case OPT_UT :
- res1=gtest_main(argc, argv);
- exit(res1);
+ is_gtest=true;
+ return (0);
break;
case OPT_HELP:
usage();
@@ -749,18 +750,50 @@ int merge_2_cap_files_sip() {
return (0);
}
+static TrexStateless *g_trex_stateless;
+
+
+TrexStateless * get_stateless_obj() {
+ return g_trex_stateless;
+}
+
+extern "C" const char * get_build_date(void){
+ return (__DATE__);
+}
+
+extern "C" const char * get_build_time(void){
+ return (__TIME__ );
+}
+
+
int main(int argc , char * argv[]){
+ int res=0;
time_init();
CGlobalInfo::m_socket.Create(0);
-
CGlobalInfo::init_pools(1000);
assert( CMsgIns::Ins()->Create(4) );
- if ( parse_options(argc, argv, &CGlobalInfo::m_options ) != 0){
+
+ bool is_gtest=false;
+
+ if ( parse_options(argc, argv, &CGlobalInfo::m_options , is_gtest) != 0){
exit(-1);
}
- return (load_list_of_cap_files(&CGlobalInfo::m_options));
+
+ if ( is_gtest ) {
+ res = gtest_main(argc, argv);
+ }else{
+ res = load_list_of_cap_files(&CGlobalInfo::m_options);
+ }
+
+ CMsgIns::Ins()->Free();
+ CGlobalInfo::free_pools();
+ CGlobalInfo::m_socket.Delete();
+
+
+ return (res);
+
}
diff --git a/src/msg_manager.cpp b/src/msg_manager.cpp
index 9f41d08c..5fe44771 100755
--- a/src/msg_manager.cpp
+++ b/src/msg_manager.cpp
@@ -51,15 +51,20 @@ bool CMessagingManager::Create(uint8_t num_dp_threads,std::string a_name){
return (true);
}
void CMessagingManager::Delete(){
- if (m_dp_to_cp) {
- m_dp_to_cp->Delete();
- delete []m_dp_to_cp;
- }
- if (m_cp_to_dp) {
- m_cp_to_dp->Delete();
- delete []m_cp_to_dp;
+
+ assert(m_cp_to_dp);
+ assert(m_dp_to_cp);
+ int i;
+ for (i=0; i<m_num_dp_threads; i++) {
+ CNodeRing * lp;
+ lp=getRingCpToDp(i);
+ lp->Delete();
+ lp=getRingDpToCp(i);
+ lp->Delete();
}
+ delete []m_dp_to_cp;
+ delete []m_cp_to_dp;
}
CNodeRing * CMessagingManager::getRingCpToDp(uint8_t thread_id){
@@ -76,6 +81,7 @@ CNodeRing * CMessagingManager::getRingDpToCp(uint8_t thread_id){
void CMsgIns::Free(){
if (m_ins) {
+ m_ins->Delete();
delete m_ins;
}
}
@@ -98,6 +104,12 @@ bool CMsgIns::Create(uint8_t num_threads){
}
+void CMsgIns::Delete(){
+ m_cp_dp.Delete();
+ m_rx_dp.Delete();
+}
+
+
CMsgIns * CMsgIns::m_ins=0;
diff --git a/src/msg_manager.h b/src/msg_manager.h
index 8958f826..0390ce10 100755
--- a/src/msg_manager.h
+++ b/src/msg_manager.h
@@ -98,6 +98,7 @@ public:
static CMsgIns * Ins();
static void Free();
bool Create(uint8_t num_threads);
+ void Delete();
public:
CMessagingManager * getRxDp(){
return (&m_rx_dp);
diff --git a/src/pal/linux/mbuf.cpp b/src/pal/linux/mbuf.cpp
index 7eca8fd5..26a54fe9 100755
--- a/src/pal/linux/mbuf.cpp
+++ b/src/pal/linux/mbuf.cpp
@@ -78,6 +78,13 @@ rte_mempool_t * utl_rte_mempool_create(const char *name,
return p;
}
+void utl_rte_mempool_delete(rte_mempool_t * & pool){
+ if (pool) {
+ delete pool;
+ pool=0;
+ }
+}
+
uint16_t rte_mbuf_refcnt_update(rte_mbuf_t *m, int16_t value)
{
diff --git a/src/pal/linux/mbuf.h b/src/pal/linux/mbuf.h
index 35a442bf..4132f842 100755
--- a/src/pal/linux/mbuf.h
+++ b/src/pal/linux/mbuf.h
@@ -65,6 +65,8 @@ typedef struct rte_mempool rte_mempool_t;
#define RTE_PKTMBUF_HEADROOM 0
+void utl_rte_mempool_delete(rte_mempool_t * &pool);
+
rte_mempool_t * utl_rte_mempool_create(const char *name,
unsigned n,
unsigned elt_size,
diff --git a/src/pal/linux_dpdk/mbuf.h b/src/pal/linux_dpdk/mbuf.h
index cde01077..339c0909 100755
--- a/src/pal/linux_dpdk/mbuf.h
+++ b/src/pal/linux_dpdk/mbuf.h
@@ -30,6 +30,10 @@ typedef struct rte_mbuf rte_mbuf_t;
typedef struct rte_mempool rte_mempool_t;
+inline void utl_rte_mempool_delete(rte_mempool_t * & pool){
+}
+
+
rte_mempool_t * utl_rte_mempool_create(const char *name,
unsigned n,
unsigned elt_size,
diff --git a/src/platform_cfg.cpp b/src/platform_cfg.cpp
index df04cd89..547cc3ad 100755
--- a/src/platform_cfg.cpp
+++ b/src/platform_cfg.cpp
@@ -414,7 +414,9 @@ void CPlatformYamlInfo::Dump(FILE *fd){
}
if ( m_telnet_exist ){
fprintf(fd," telnet_port : %d \n",m_telnet_port);
+
}
+ fprintf(fd," m_zmq_rpc_port : %d \n",m_zmq_rpc_port);
if ( m_mac_info_exist ){
int i;
diff --git a/src/platform_cfg.h b/src/platform_cfg.h
index b4b03b10..4fc3c3dd 100755
--- a/src/platform_cfg.h
+++ b/src/platform_cfg.h
@@ -180,11 +180,11 @@ public:
m_enable_zmq_pub_exist=false;
m_enable_zmq_pub=true;
m_zmq_pub_port=4500;
+ m_zmq_rpc_port = 4501;
m_telnet_exist=false;
m_telnet_port=4502 ;
- m_zmq_rpc_port = 5050;
m_mac_info_exist=false;
m_port_bandwidth_gb = 10;
diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
index fffc800a..e32073b0 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
@@ -140,14 +140,18 @@ TrexRpcCmdAddStream::allocate_new_stream(const Json::Value &section, uint8_t por
if (type == "continuous") {
double pps = parse_double(mode, "pps", result);
- stream = new TrexStreamContinuous(port_id, stream_id, pps);
+ stream = new TrexStream( TrexStream::stCONTINUOUS, port_id, stream_id);
+ stream->set_pps(pps);
} else if (type == "single_burst") {
uint32_t total_pkts = parse_int(mode, "total_pkts", result);
double pps = parse_double(mode, "pps", result);
- stream = new TrexStreamBurst(port_id, stream_id, total_pkts, pps);
+ stream = new TrexStream(TrexStream::stSINGLE_BURST,port_id, stream_id);
+ stream->set_pps(pps);
+ stream->set_signle_burtst(total_pkts);
+
} else if (type == "multi_burst") {
@@ -156,8 +160,10 @@ TrexRpcCmdAddStream::allocate_new_stream(const Json::Value &section, uint8_t por
uint32_t num_bursts = parse_int(mode, "number_of_bursts", result);
uint32_t pkts_per_burst = parse_int(mode, "pkts_per_burst", result);
- stream = new TrexStreamMultiBurst(port_id, stream_id, pkts_per_burst, pps, num_bursts, ibg_usec);
-
+ stream = new TrexStream(TrexStream::stMULTI_BURST,port_id, stream_id );
+ stream->set_pps(pps);
+ stream->set_multi_burst(pkts_per_burst,num_bursts,ibg_usec);
+
} else {
generate_parse_err(result, "bad stream type provided: '" + type + "'");
diff --git a/src/stateless/cp/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp
index ba306137..1a05257c 100644
--- a/src/stateless/cp/trex_stream.cpp
+++ b/src/stateless/cp/trex_stream.cpp
@@ -25,9 +25,11 @@ limitations under the License.
/**************************************
* stream
*************************************/
-TrexStream::TrexStream(uint8_t port_id, uint32_t stream_id) : m_port_id(port_id), m_stream_id(stream_id) {
+TrexStream::TrexStream(uint8_t type,
+ uint8_t port_id, uint32_t stream_id) : m_port_id(port_id), m_stream_id(stream_id) {
/* default values */
+ m_type = type;
m_isg_usec = 0;
m_next_stream_id = -1;
m_enabled = false;
@@ -38,6 +40,11 @@ TrexStream::TrexStream(uint8_t port_id, uint32_t stream_id) : m_port_id(port_id)
m_rx_check.m_enable = false;
+
+ m_pps=-1.0;
+ m_burst_total_pkts=0;
+ m_num_bursts=1;
+ m_ibg_usec=0.0;
}
TrexStream::~TrexStream() {
diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h
index c8a15240..151723ad 100644
--- a/src/stateless/cp/trex_stream.h
+++ b/src/stateless/cp/trex_stream.h
@@ -29,9 +29,28 @@ limitations under the License.
#include <json/json.h>
#include <trex_stream_vm.h>
+#include <stdio.h>
+#include <string.h>
class TrexRpcCmdAddStream;
+
+struct CStreamPktData {
+ uint8_t *binary;
+ uint16_t len;
+
+ std::string meta;
+
+public:
+ inline void clone(uint8_t * in_binary,
+ uint32_t in_pkt_size){
+ binary = new uint8_t[in_pkt_size];
+ len = in_pkt_size;
+ memcpy(binary,in_binary,in_pkt_size);
+ }
+};
+
+
/**
* Stateless Stream
*
@@ -39,8 +58,17 @@ class TrexRpcCmdAddStream;
class TrexStream {
public:
- TrexStream(uint8_t port_id, uint32_t stream_id);
- virtual ~TrexStream() = 0;
+ enum STREAM_TYPE {
+ stNONE = 0,
+ stCONTINUOUS = 4,
+ stSINGLE_BURST = 5,
+ stMULTI_BURST = 6
+ };
+
+
+public:
+ TrexStream(uint8_t type,uint8_t port_id, uint32_t stream_id);
+ virtual ~TrexStream();
/* defines the min max per packet supported */
static const uint32_t MIN_PKT_SIZE_BYTES = 1;
@@ -52,8 +80,61 @@ public:
/* access the stream json */
const Json::Value & get_stream_json();
+ double get_pps() {
+ return m_pps;
+ }
+
+ void set_pps(double pps){
+ m_pps = pps;
+ }
+
+ void set_type(uint8_t type){
+ m_type = type;
+ }
+
+ uint8_t get_type(void){
+ return ( m_type );
+ }
+
+
+
+ void set_multi_burst(uint32_t burst_total_pkts,
+ uint32_t num_bursts,
+ double ibg_usec){
+ m_burst_total_pkts = burst_total_pkts;
+ m_num_bursts = num_bursts;
+ m_ibg_usec = ibg_usec;
+ }
+
+ void set_signle_burtst(uint32_t burst_total_pkts){
+ set_multi_burst(burst_total_pkts,1,0.0);
+ }
+
+ /* create new stream */
+ TrexStream * clone_as_dp(){
+ TrexStream * dp=new TrexStream(m_type,m_port_id,m_stream_id);
+
+
+ dp->m_isg_usec = m_isg_usec;
+ dp->m_next_stream_id = m_next_stream_id;
+
+ dp->m_enabled = m_enabled;
+ dp->m_self_start = m_self_start;
+
+ /* deep copy */
+ dp->m_pkt.clone(m_pkt.binary,m_pkt.len);
+
+ dp->m_rx_check = m_rx_check;
+ dp->m_pps = m_pps;
+ dp->m_burst_total_pkts = m_burst_total_pkts;
+ dp->m_num_bursts = m_num_bursts;
+ dp->m_ibg_usec = m_ibg_usec ;
+ return (dp);
+ }
+
public:
/* basic */
+ uint8_t m_type;
uint8_t m_port_id;
uint32_t m_stream_id;
@@ -65,13 +146,9 @@ public:
/* indicators */
bool m_enabled;
bool m_self_start;
-
+
+ CStreamPktData m_pkt;
/* pkt */
- struct {
- uint8_t *binary;
- uint16_t len;
- std::string meta;
- } m_pkt;
/* VM */
StreamVm m_vm;
@@ -85,64 +162,19 @@ public:
} m_rx_check;
+ double m_pps;
- /* original template provided by requester */
- Json::Value m_stream_json;
-};
+ uint32_t m_burst_total_pkts; /* valid in case of burst stSINGLE_BURST,stMULTI_BURST*/
-/**
- * continuous stream
- *
- */
-class TrexStreamContinuous : public TrexStream {
-public:
- TrexStreamContinuous(uint8_t port_id, uint32_t stream_id, double pps) : TrexStream(port_id, stream_id), m_pps(pps) {
- }
+ uint32_t m_num_bursts; /* valid in case of stMULTI_BURST */
- double get_pps() {
- return m_pps;
- }
+ double m_ibg_usec; /* valid in case of stMULTI_BURST */
-protected:
- double m_pps;
-};
-
-/**
- * single burst
- *
- */
-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) {
- }
+ /* original template provided by requester */
+ Json::Value m_stream_json;
-protected:
- uint32_t m_total_pkts;
- double m_pps;
};
-/**
- * multi burst
- *
- */
-class TrexStreamMultiBurst : public TrexStreamBurst {
-public:
- TrexStreamMultiBurst(uint8_t port_id,
- uint32_t stream_id,
- uint32_t pkts_per_burst,
- 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) {
-
- }
-protected:
- uint32_t m_num_bursts;
- double m_ibg_usec;
-
-};
/**
* holds all the streams
diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp
index 0b2549a0..80cdb31c 100644
--- a/src/stateless/cp/trex_streams_compiler.cpp
+++ b/src/stateless/cp/trex_streams_compiler.cpp
@@ -27,26 +27,21 @@ limitations under the License.
* stream compiled object
*************************************/
TrexStreamsCompiledObj::TrexStreamsCompiledObj(uint8_t port_id, double mul) : m_port_id(port_id), m_mul(mul) {
+ m_duration_sim=-1.0;
}
TrexStreamsCompiledObj::~TrexStreamsCompiledObj() {
- for (auto &obj : m_objs) {
- delete obj.m_pkt;
+ for (auto obj : m_objs) {
+ delete obj.m_stream;
}
m_objs.clear();
}
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->clone_as_dp();
m_objs.push_back(obj);
}
@@ -61,15 +56,13 @@ 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);
}
- /* fix the multiplier */
new_compiled_obj->m_mul = m_mul;
+ new_compiled_obj->m_duration_sim = m_duration_sim;
+
return new_compiled_obj;
}
@@ -91,17 +84,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 404fdd21..78ac1ac7 100644
--- a/src/stateless/cp/trex_streams_compiler.h
+++ b/src/stateless/cp/trex_streams_compiler.h
@@ -40,29 +40,38 @@ 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() {
return m_objs;
}
+ void set_simulation_duration(double duration){
+ m_duration_sim=duration;
+ }
+
+ double get_simulation_duration(){
+ return (m_duration_sim);
+ }
/**
* clone the compiled object
*
*/
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;
double m_mul;
+ double m_duration_sim; /* duration for all simulation */
};
class TrexStreamsCompiler {
diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp
index b2bd0152..96c18dbd 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>
@@ -31,6 +32,18 @@ usec_to_sec(double usec) {
}
+
+void CGenNodeStateless::free_stl_node(){
+ /* if we have cache mbuf free it */
+ rte_mbuf_t * m=get_cache_mbuf();
+ if (m) {
+ rte_pktmbuf_free(m);
+ m_cache_mbuf=0;
+ }
+}
+
+
+
void
TrexStatelessDpCore::create(uint8_t thread_id, CFlowGenListPerThread *core) {
m_thread_id = thread_id;
@@ -79,44 +92,91 @@ TrexStatelessDpCore::start_scheduler() {
m_core->m_node_gen.close_file(m_core);
}
+
+void
+TrexStatelessDpCore::run_once(){
+
+ idle_state_loop();
+ start_scheduler();
+}
+
+
void
TrexStatelessDpCore::start() {
while (true) {
- idle_state_loop();
+ run_once();
+ }
+}
+
+void
+TrexStatelessDpCore::add_duration(double duration){
+ if (duration > 0.0) {
+ CGenNode *node = m_core->create_node() ;
+
+ node->m_type = CGenNode::EXIT_SCHED;
- start_scheduler();
+ /* make sure it will be scheduled after the current node */
+ node->m_time = m_core->m_cur_time_sec + duration ;
+
+ m_core->m_node_gen.add_node(node);
}
}
+
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;
+
+ 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;
+ node->m_single_burst = stream->m_burst_total_pkts;
+ node->m_single_burst_refill = stream->m_burst_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 :
+ node->m_single_burst = stream->m_burst_total_pkts;
+ node->m_single_burst_refill = stream->m_burst_total_pkts;
+ node->m_multi_bursts = stream->m_num_bursts;
+ node->m_ibg_sec = usec_to_sec( stream->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);
@@ -149,11 +209,13 @@ 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();
+
+ 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 f4dbad08..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 {
@@ -45,6 +46,7 @@ public:
TrexStatelessDpCore() {
m_thread_id = 0;
m_core = NULL;
+ m_duration = -1;
}
/**
@@ -61,6 +63,10 @@ public:
*/
void start();
+
+ /* exit after batch of commands */
+ void run_once();
+
/**
* dummy traffic creator
*
@@ -126,11 +132,10 @@ private:
*/
void handle_cp_msg(TrexStatelessCpToDpMsgBase *msg);
- void add_cont_stream(uint8_t dir,
- double isg,
- double pps,
- const uint8_t *pkt,
- uint16_t pkt_len);
+ /* add global exit */
+ void add_duration(double duration);
+
+ void add_cont_stream(TrexStream * stream,TrexStreamsCompiledObj *comp);
uint8_t m_thread_id;
state_e m_state;
@@ -142,6 +147,8 @@ private:
/* pointer to the main object */
CFlowGenListPerThread *m_core;
+
+ double m_duration;
};
#endif /* __TREX_STATELESS_DP_CORE_H__ */
diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h
index 92b428ab..e4cf964d 100644
--- a/src/stateless/dp/trex_stream_node.h
+++ b/src/stateless/dp/trex_stream_node.h
@@ -22,8 +22,10 @@ limitations under the License.
#define __TREX_STREAM_NODE_H__
#include <bp_sim.h>
+#include <stdio.h>
class TrexStatelessDpCore;
+#include <trex_stream.h>
/* this is a event for stateless */
struct CGenNodeStateless : public CGenNodeBase {
@@ -32,27 +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 */
@@ -62,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;
}
@@ -82,8 +153,6 @@ public:
return ((pkt_dir_t)( m_flags &1));
}
-
-
inline void set_cache_mbuf(rte_mbuf_t * m){
m_cache_mbuf=(void *)m;
m_flags |= NODE_FLAGS_MBUF_CACHE;
@@ -97,9 +166,18 @@ public:
}
}
+ void free_stl_node();
+
+
+ void Dump(FILE *fd){
+ fprintf(fd," %f, %lu, %lu \n",m_time,(ulong)m_port_id,(ulong)get_mbuf_cache_dir());
+ }
} __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__ */
diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h
index 7978b7f9..d288fc83 100644
--- a/src/stateless/messaging/trex_stateless_messaging.h
+++ b/src/stateless/messaging/trex_stateless_messaging.h
@@ -74,6 +74,7 @@ public:
virtual TrexStatelessCpToDpMsgBase * clone();
+
private:
TrexStreamsCompiledObj *m_obj;
};