From cc352e04fd45913132f3e1ddc86d88571c926879 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Wed, 11 Nov 2015 15:37:46 +0200 Subject: add first stl test and cleanup valgrind --- linux/ws_main.py | 19 +- src/bp_gtest.cpp | 18 -- src/bp_sim.cpp | 174 +++++++--- src/bp_sim.h | 46 ++- src/gtest/trex_stateless_gtest.cpp | 360 ++++++--------------- src/main.cpp | 47 ++- src/msg_manager.cpp | 26 +- src/msg_manager.h | 1 + src/pal/linux/mbuf.cpp | 7 + src/pal/linux/mbuf.h | 2 + src/pal/linux_dpdk/mbuf.h | 4 + src/stateless/cp/trex_stream.h | 4 +- src/stateless/cp/trex_streams_compiler.cpp | 2 +- src/stateless/dp/trex_stateless_dp_core.cpp | 44 ++- src/stateless/dp/trex_stateless_dp_core.h | 10 + src/stateless/dp/trex_stream_node.h | 10 +- src/stateless/messaging/trex_stateless_messaging.h | 1 + 17 files changed, 426 insertions(+), 349 deletions(-) diff --git a/linux/ws_main.py b/linux/ws_main.py index d020411a..65ca4522 100755 --- a/linux/ws_main.py +++ b/linux/ws_main.py @@ -238,9 +238,15 @@ bp =SrcGroups([ bp_sim_gtest, main_src, cmn_src , + net_src , yaml_src, - bp_hack_for_compile, + json_src, + stateless_src, + rpc_server_src + #rpc_server_mock_src, + + #bp_hack_for_compile, ]); @@ -393,10 +399,13 @@ class build_option: build_types = [ - build_option(name = "bp-sim", src = bp, debug_mode= DEBUG_, platform = PLATFORM_64, is_pie = False, - flags = ['-Wall', '-Werror', '-Wno-sign-compare', '-Wno-strict-aliasing']), - build_option(name = "bp-sim", src = bp, debug_mode= RELEASE_,platform = PLATFORM_64, is_pie = False, - flags = ['-Wall', '-Werror', '-Wno-sign-compare', '-Wno-strict-aliasing']), + build_option(name = "bp-sim", src = bp, use = ['zmq'],debug_mode= DEBUG_, platform = PLATFORM_64, is_pie = False, + flags = ['-Wall', '-Werror', '-Wno-sign-compare', '-Wno-strict-aliasing'], + rpath = ['.']), + + build_option(name = "bp-sim", src = bp, use = ['zmq'],debug_mode= RELEASE_,platform = PLATFORM_64, is_pie = False, + flags = ['-Wall', '-Werror', '-Wno-sign-compare', '-Wno-strict-aliasing'], + rpath = ['.']), build_option(name = "mock-rpc-server", use = ['zmq'], src = rpc_server_mock, debug_mode= DEBUG_,platform = PLATFORM_64, is_pie = False, flags = ['-DTREX_RPC_MOCK_SERVER', '-Wall', '-Werror', '-Wno-sign-compare'], 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..c63ad1af 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,9 +3510,14 @@ 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); + } else { node_sl->handle(thread); } @@ -3899,41 +3942,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 +4030,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 +4067,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 +4600,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 +6867,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..36e48f6e 100644 --- a/src/gtest/trex_stateless_gtest.cpp +++ b/src/gtest/trex_stateless_gtest.cpp @@ -22,332 +22,180 @@ limitations under the License. #include "bp_sim.h" #include #include +#include +#include +#include +#include +#include +#include +#include #define EXPECT_EQ_UINT32(a,b) EXPECT_EQ((uint32_t)(a),(uint32_t)(b)) -// one stream info with const packet , no VM -class CTRexDpStatelessVM { -}; - -//- add dump function -// - check one object -// create frame work -class CTRexDpStreamModeContinues{ +/* basic stateless test */ +class basic_stl : public testing::Test { + protected: + virtual void SetUp() { + } + virtual void TearDown() { + } public: - void set_pps(double pps){ - m_pps=pps; - } - double get_pps(){ - return (m_pps); - } - - void dump(FILE *fd); -private: - double m_pps; }; -void CTRexDpStreamModeContinues::dump(FILE *fd){ - fprintf (fd," pps : %f \n",m_pps); -} +class CBasicStl { - -class CTRexDpStreamModeSingleBurst{ public: - void set_pps(double pps){ - m_pps=pps; - } - double get_pps(){ - return (m_pps); - } - - void set_total_packets(uint64_t total_packets){ - m_total_packets =total_packets; - } - - uint64_t get_total_packets(){ - return (m_total_packets); + CBasicStl(){ + m_time_diff=0.001; + m_threads=1; } - void dump(FILE *fd); - -private: - double m_pps; - uint64_t m_total_packets; -}; - - -void CTRexDpStreamModeSingleBurst::dump(FILE *fd){ - fprintf (fd," pps : %f \n",m_pps); - fprintf (fd," total_packets : %llu \n", (unsigned long long)m_total_packets); -} - + bool init(void){ -class CTRexDpStreamModeMultiBurst{ -public: - void set_pps(double pps){ - m_pps=pps; - } - double get_pps(){ - return (m_pps); - } + CErfIFStl erf_vif; + fl.Create(); + fl.generate_p_thread_info(1); + CFlowGenListPerThread * lpt; - void set_pkts_per_burst(uint64_t pkts_per_burst){ - m_pkts_per_burst =pkts_per_burst; - } + fl.m_threads_info[0]->set_vif(&erf_vif); - uint64_t get_pkts_per_burst(){ - return (m_pkts_per_burst); - } + CErfCmp cmp; + cmp.dump=1; - void set_ibg(double ibg){ - m_ibg = ibg; - } + CMessagingManager * cp_dp = CMsgIns::Ins()->getCpDp(); - double get_ibg(){ - return ( m_ibg ); - } + m_ring_from_cp = cp_dp->getRingCpToDp(0); - void set_number_of_bursts(uint32_t number_of_bursts){ - m_number_of_bursts = number_of_bursts; - } - uint32_t get_number_of_bursts(){ - return (m_number_of_bursts); - } + bool res=true; - void dump(FILE *fd); + lpt=fl.m_threads_info[0]; -private: - double m_pps; - double m_ibg; // inter burst gap - uint64_t m_pkts_per_burst; - uint32_t m_number_of_bursts; -}; + 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); -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); -} + 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); -class CTRexDpStreamMode { -public: - enum MODES { - moCONTINUES = 0x0, - moSINGLE_BURST = 0x1, - moMULTI_BURST = 0x2 - } ; - typedef uint8_t MODE_TYPE_t; + lpt->start_stateless_daemon_simulation(); - void reset(); + #if 0 + lpt->m_node_gen.DumpHist(stdout); - void set_mode(MODE_TYPE_t mode ){ - m_type = mode; - } - MODE_TYPE_t get_mode(){ - return (m_type); - } + cmp.d_sec = m_time_diff; + if ( cmp.compare(std::string(buf),std::string(buf_ex)) != true ) { + res=false; + } - CTRexDpStreamModeContinues & cont(void){ - return (m_data.m_cont); - } - CTRexDpStreamModeSingleBurst & single_burst(void){ - return (m_data.m_signle_burst); - } + 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()); + } + #endif - CTRexDpStreamModeMultiBurst & multi_burst(void){ - return (m_data.m_multi_burst); + fl.Delete(); + return (res); } - void dump(FILE *fd); -private: - uint8_t m_type; - union Data { - CTRexDpStreamModeContinues m_cont; - CTRexDpStreamModeSingleBurst m_signle_burst; - CTRexDpStreamModeMultiBurst m_multi_burst; - } m_data; +public: + int m_threads; + double m_time_diff; + bool m_dump_json; + TrexStatelessCpToDpMsgBase * m_msg; + CNodeRing *m_ring_from_cp; + CFlowGenList fl; }; -void CTRexDpStreamMode::reset(){ - m_type =CTRexDpStreamMode::moCONTINUES; - memset(&m_data,0,sizeof(m_data)); -} - -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; - } -} +const uint8_t my_test_pkt[]={ + 0x00,0x04,0x96,0x08,0xe0,0x40, + 0x00,0x0e,0x2e,0x24,0x37,0x5f, + 0x08,0x00, + 0x45,0x02,0x00,0x30, + 0x00,0x00,0x40,0x00, + 0x40,0x84,0xbd,0x04, + 0x9b,0xe6,0x18,0x9b, //sIP + 0xcb,0xff,0xfc,0xc2, //DIP -class CTRexDpStatelessStream { + 0x80,0x44,//SPORT + 0x00,0x50,//DPORT -public: - enum FLAGS_0{ - _ENABLE = 0, - _SELF_START = 1, - _VM_ENABLE =2, - _END_STREAM =-1 - }; - - CTRexDpStatelessStream(){ - reset(); - } + 0x00,0x00,0x00,0x00, //checksum - 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(); - } + 0x11,0x22,0x33,0x44, // magic + 0x00,0x00,0x00,0x00, //64 bit counter + 0x00,0x00,0x00,0x00, + 0x00,0x01,0xa0,0x00, //seq + 0x00,0x00,0x00,0x00, +}; - void set_enable(bool enable){ - btSetMaskBit32(m_flags,_ENABLE,_ENABLE,enable?1:0); - } - 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); - } - bool get_self_start(bool enable){ - return (btGetMaskBit32(m_flags,_SELF_START,_SELF_START)?true:false); - } +TEST_F(basic_stl, limit_single_pkt) { - /* 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); - } + CBasicStl t1; + CParserOption * po =&CGlobalInfo::m_options; + po->preview.setVMode(0); + po->preview.setFileWrite(true); + po->out_file ="exp/stl_single_sctp_pkt"; - bool get_vm_enabled(bool enable){ - return (btGetMaskBit32(m_flags,_VM_ENABLE,_VM_ENABLE)?true:false); - } + TrexStreamsCompiler compile; - void set_inter_stream_gap(double isg_sec){ - m_isg_sec =isg_sec; - } - double get_inter_stream_gap(){ - return (m_isg_sec); - } + std::vector streams; - CTRexDpStreamMode & get_mode(); + TrexStream * stream1 = new TrexStreamContinuous(0,0,1.0); + stream1->m_enabled = true; + stream1->m_self_start = true; + uint8_t *binary = new uint8_t[sizeof(my_test_pkt)]; + memcpy(binary,my_test_pkt,sizeof(my_test_pkt)); - // CTRexDpStatelessStream::_END_STREAM for END - void set_next_stream(int32_t next_stream){ - m_next_stream =next_stream; - } + stream1->m_pkt.binary = binary; + stream1->m_pkt.len = sizeof(my_test_pkt); - int32_t get_next_stream(void){ - return ( m_next_stream ); - } - void dump(FILE *fd); + streams.push_back(stream1); -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 -//- 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 - -#if 0 -void CTRexDpStatelessStream::dump(FILE *fd){ - - 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); - } -} + TrexStreamsCompiledObj comp_obj(0,1.0); + assert(compile.compile(streams, comp_obj) ); + TrexStatelessDpStart * lpstart = new TrexStatelessDpStart( comp_obj.clone() ); -class CTRexStatelessBasic { - -public: - CTRexStatelessBasic(){ - m_threads=1; - } - - bool init(void){ - return (true); - } - -public: - bool m_threads; -}; + t1.m_msg = lpstart; + bool res=t1.init(); -/* stateless basic */ -class dp_sl_basic : public testing::Test { - protected: - virtual void SetUp() { - } - virtual void TearDown() { - } -public: -}; - + 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 #include +#include + // 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; iDelete(); + 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/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index c8a15240..d1a44909 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -40,7 +40,7 @@ class TrexStream { public: TrexStream(uint8_t port_id, uint32_t stream_id); - virtual ~TrexStream() = 0; + virtual ~TrexStream(); /* defines the min max per packet supported */ static const uint32_t MIN_PKT_SIZE_BYTES = 1; @@ -88,6 +88,8 @@ public: /* original template provided by requester */ Json::Value m_stream_json; + + }; /** diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index 06c0119a..667da158 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -31,7 +31,7 @@ TrexStreamsCompiledObj::TrexStreamsCompiledObj(uint8_t port_id, double mul) : m_ TrexStreamsCompiledObj::~TrexStreamsCompiledObj() { for (auto &obj : m_objs) { - delete obj.m_pkt; + delete [] obj.m_pkt; } m_objs.clear(); } diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index b2bd0152..c9e47090 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -31,6 +31,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,16 +91,41 @@ 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(uint8_t port_id, + double duration){ + if (duration > 0.0) { + + CGenNode *node = m_core->create_node() ; + + node->m_type = CGenNode::EXIT_SCHED; + + /* 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); - start_scheduler(); } } + void TrexStatelessDpCore::add_cont_stream(uint8_t port_id, double isg_usec, @@ -155,6 +192,9 @@ TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj) { single_stream.m_pkt, single_stream.m_pkt_len); } + + /* TBD need to fix this */ + add_duration(0,10.0); } void diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index f4dbad08..a23e81c9 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -45,6 +45,7 @@ public: TrexStatelessDpCore() { m_thread_id = 0; m_core = NULL; + m_duration = -1; } /** @@ -61,6 +62,10 @@ public: */ void start(); + + /* exit after batch of commands */ + void run_once(); + /** * dummy traffic creator * @@ -126,6 +131,9 @@ private: */ void handle_cp_msg(TrexStatelessCpToDpMsgBase *msg); + void add_duration(uint8_t port_id, + double duration); + void add_cont_stream(uint8_t dir, double isg, double pps, @@ -142,6 +150,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..2ffe04c3 100644 --- a/src/stateless/dp/trex_stream_node.h +++ b/src/stateless/dp/trex_stream_node.h @@ -22,6 +22,7 @@ limitations under the License. #define __TREX_STREAM_NODE_H__ #include +#include class TrexStatelessDpCore; @@ -42,6 +43,7 @@ private: public: + inline bool is_active() { return m_is_stream_active; } @@ -82,8 +84,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,6 +97,12 @@ 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; 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; }; -- cgit 1.2.3-korg