diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/bp_gtest.cpp | 18 | ||||
-rwxr-xr-x | src/bp_sim.cpp | 173 | ||||
-rwxr-xr-x | src/bp_sim.h | 46 | ||||
-rw-r--r-- | src/gtest/trex_stateless_gtest.cpp | 603 | ||||
-rwxr-xr-x | src/main.cpp | 47 | ||||
-rwxr-xr-x | src/msg_manager.cpp | 26 | ||||
-rwxr-xr-x | src/msg_manager.h | 1 | ||||
-rwxr-xr-x | src/pal/linux/mbuf.cpp | 7 | ||||
-rwxr-xr-x | src/pal/linux/mbuf.h | 2 | ||||
-rwxr-xr-x | src/pal/linux_dpdk/mbuf.h | 4 | ||||
-rwxr-xr-x | src/platform_cfg.cpp | 2 | ||||
-rwxr-xr-x | src/platform_cfg.h | 2 | ||||
-rw-r--r-- | src/rpc-server/commands/trex_rpc_cmd_stream.cpp | 14 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream.cpp | 9 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream.h | 150 | ||||
-rw-r--r-- | src/stateless/cp/trex_streams_compiler.cpp | 34 | ||||
-rw-r--r-- | src/stateless/cp/trex_streams_compiler.h | 21 | ||||
-rw-r--r-- | src/stateless/dp/trex_stateless_dp_core.cpp | 98 | ||||
-rw-r--r-- | src/stateless/dp/trex_stateless_dp_core.h | 17 | ||||
-rw-r--r-- | src/stateless/dp/trex_stream_node.h | 100 | ||||
-rw-r--r-- | src/stateless/messaging/trex_stateless_messaging.h | 1 |
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 §ion, 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 §ion, 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; }; |