diff options
Diffstat (limited to 'src/stateless')
-rw-r--r-- | src/stateless/cp/trex_stream.cpp | 3 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream.h | 3 | ||||
-rw-r--r-- | src/stateless/cp/trex_vm_splitter.cpp | 28 | ||||
-rw-r--r-- | src/stateless/dp/trex_stateless_dp_core.cpp | 171 | ||||
-rw-r--r-- | src/stateless/dp/trex_stateless_dp_core.h | 7 | ||||
-rw-r--r-- | src/stateless/dp/trex_stream_node.h | 83 |
6 files changed, 269 insertions, 26 deletions
diff --git a/src/stateless/cp/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp index 4325858c..5a24e2b3 100644 --- a/src/stateless/cp/trex_stream.cpp +++ b/src/stateless/cp/trex_stream.cpp @@ -121,7 +121,7 @@ void TrexStream::Dump(FILE *fd){ fprintf(fd," bps L1 : %f\n", m_rate.get_bps_L1()); fprintf(fd," bps L2 : %f\n", m_rate.get_bps_L2()); fprintf(fd," percentage : %f\n", m_rate.get_percentage()); - + fprintf(fd," cache_size : %lu\n", (ulong)m_cache_size); } @@ -134,6 +134,7 @@ TrexStream::TrexStream(uint8_t type, m_next_stream_id = -1; m_enabled = false; m_self_start = false; + m_cache_size = 0; m_mc_phase_pre_sec = 0; m_mc_phase_post_sec = 0; diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index c5bfdb98..ba5fa214 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -440,6 +440,7 @@ public: dp->m_num_bursts = m_num_bursts; dp->m_ibg_usec = m_ibg_usec; dp->m_flags = m_flags; + dp->m_cache_size = m_cache_size; dp->m_action_count = m_action_count; dp->m_random_seed = m_random_seed; @@ -514,8 +515,10 @@ public: uint8_t m_type; uint8_t m_port_id; uint16_t m_flags; + uint32_t m_stream_id; /* id from RPC can be anything */ uint16_t m_action_count; + uint16_t m_cache_size; uint32_t m_random_seed; diff --git a/src/stateless/cp/trex_vm_splitter.cpp b/src/stateless/cp/trex_vm_splitter.cpp index 963b4525..5069c535 100644 --- a/src/stateless/cp/trex_vm_splitter.cpp +++ b/src/stateless/cp/trex_vm_splitter.cpp @@ -40,6 +40,34 @@ TrexVmSplitter::split(TrexStream *stream, std::vector<TrexStream *> core_streams m_core_streams = &core_streams; m_stream = stream; + uint16_t cache_size=m_stream->m_cache_size; + /* split the cache_size */ + if (cache_size>0) { + + /* TBD need to check if we need to it is not too big from pool */ + if (cache_size > 10000) { + throw TrexException("Cache is too big try to reduce it "); + } + + /* split like variable splitters with leftovers */ + uint16_t cache_per_core = cache_size/m_dp_core_count; + uint16_t leftover = cache_size % m_dp_core_count; + + if (cache_per_core<1) { + cache_per_core=1; + leftover=0; + } + + for (TrexStream *core_stream : *m_core_streams) { + core_stream->m_cache_size = cache_per_core; + if (leftover) { + core_stream->m_cache_size+=1; + leftover-=1; + } + } + } + + /* if we cannot split - compile the main and duplicate */ bool rc = split_internal(); if (!rc) { diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 6648e2f3..c5963625 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -25,6 +25,88 @@ limitations under the License. #include "trex_stream.h" #include "trex_stream_node.h" #include "trex_streams_compiler.h" +#include "mbuf.h" + + + + +void CGenNodeStateless::cache_mbuf_array_init(){ + m_cache_size=0; + m_cache_array_cnt=0; +} + + + +void CGenNodeStateless::cache_mbuf_array_copy(CGenNodeCacheMbuf *obj, + uint16_t size){ + + int i; + cache_mbuf_array_alloc(size); + for (i=0; i<size; i++) { + cache_mbuf_array_set(i,obj->m_array[i]); + } + cache_mbuf_array_set_const_mbuf(obj->m_mbuf_const); +} + + +rte_mbuf_t ** CGenNodeStateless::cache_mbuf_array_alloc(uint16_t size){ + + uint32_t buf_size = CGenNodeCacheMbuf::get_object_size(size); + /* TBD replace with align, zero API */ + m_cache_mbuf = (void *)malloc(buf_size); + assert(m_cache_mbuf); + memset(m_cache_mbuf,0,buf_size); + + m_flags |= SL_NODE_CONST_MBUF_CACHE_ARRAY; + m_cache_size=size; + m_cache_array_cnt=0; + return ((rte_mbuf_t **)m_cache_mbuf); +} + +void CGenNodeStateless::cache_mbuf_array_free(){ + + assert(m_cache_mbuf); + int i; + for (i=0; i<(int)m_cache_size; i++) { + rte_mbuf_t * m=cache_mbuf_array_get((uint16_t)i); + assert(m); + rte_pktmbuf_free(m); + } + + /* free the const */ + rte_mbuf_t * m=cache_mbuf_array_get_const_mbuf() ; + if (m) { + rte_pktmbuf_free(m); + } + + free(m_cache_mbuf); + m_cache_mbuf=0; +} + + +rte_mbuf_t * CGenNodeStateless::cache_mbuf_array_get(uint16_t index){ + + CGenNodeCacheMbuf *p =(CGenNodeCacheMbuf *) m_cache_mbuf; + return (p->m_array[index]); +} + +void CGenNodeStateless::cache_mbuf_array_set_const_mbuf(rte_mbuf_t * m){ + CGenNodeCacheMbuf *p =(CGenNodeCacheMbuf *) m_cache_mbuf; + p->m_mbuf_const=m; +} + +rte_mbuf_t * CGenNodeStateless::cache_mbuf_array_get_const_mbuf(){ + CGenNodeCacheMbuf *p =(CGenNodeCacheMbuf *) m_cache_mbuf; + return (p->m_mbuf_const); +} + + +void CGenNodeStateless::cache_mbuf_array_set(uint16_t index, + rte_mbuf_t * m){ + CGenNodeCacheMbuf *p =(CGenNodeCacheMbuf *) m_cache_mbuf; + p->m_array[index]=m; +} + void CDpOneStream::Delete(CFlowGenListPerThread * core){ assert(m_node->get_state() == CGenNodeStateless::ss_INACTIVE); @@ -186,26 +268,40 @@ rte_mbuf_t * CGenNodeStateless::alloc_node_with_vm(){ return (m); } - -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; - }else{ - /* non cache - must have an header */ +void CGenNodeStateless::free_stl_vm_buf(){ + rte_mbuf_t * m ; m=get_const_mbuf(); if (m) { rte_pktmbuf_free(m); /* reduce the ref counter */ + /* clear the const marker */ + clear_const_mbuf(); } + free_prefix_header(); + + if (m_vm_flow_var) { + /* free flow var */ + free(m_vm_flow_var); + m_vm_flow_var=0; + } +} + + + +void CGenNodeStateless::free_stl_node(){ + + if ( is_cache_mbuf_array() ){ + /* do we have cache of mbuf pre allocated */ + cache_mbuf_array_free(); + }else{ + /* if we have cache mbuf free it */ + rte_mbuf_t * m=get_cache_mbuf(); + if (m) { + rte_pktmbuf_free(m); + m_cache_mbuf=0; + } } - if (m_vm_flow_var) { - /* free flow var */ - free(m_vm_flow_var); - m_vm_flow_var=0; - } + free_stl_vm_buf(); } @@ -633,6 +729,40 @@ void TrexStatelessDpCore::update_mac_addr(TrexStream * stream, } +void TrexStatelessDpCore::replay_vm_into_cache(TrexStream * stream, + CGenNodeStateless *node){ + + uint16_t cache_size = stream->m_cache_size; + assert(cache_size>0); + rte_mbuf_t * m=0; + + uint32_t buf_size = CGenNodeCacheMbuf::get_object_size(cache_size); + CGenNodeCacheMbuf * p = (CGenNodeCacheMbuf *)malloc(buf_size); + assert(p); + memset(p,0,buf_size); + + int i; + for (i=0; i<cache_size; i++) { + p->m_array[i] = node->alloc_node_with_vm(); + } + /* save const */ + m=node->get_const_mbuf(); + if (m) { + p->m_mbuf_const=m; + rte_pktmbuf_refcnt_update(m,1); + } + + /* free all VM and const mbuf */ + node->free_stl_vm_buf(); + + /* copy to local node meory */ + node->cache_mbuf_array_copy(p,cache_size); + + /* free the memory */ + free(p); +} + + void TrexStatelessDpCore::add_stream(TrexStatelessDpPerPort * lp_port, TrexStream * stream, @@ -640,6 +770,9 @@ TrexStatelessDpCore::add_stream(TrexStatelessDpPerPort * lp_port, CGenNodeStateless *node = m_core->create_node_sl(); + node->cache_mbuf_array_init(); + node->m_batch_size=0; + /* add periodic */ node->m_cache_mbuf=0; node->m_type = CGenNode::STATELESS_PKT; @@ -799,6 +932,11 @@ TrexStatelessDpCore::add_stream(TrexStatelessDpPerPort * lp_port, memcpy(p,stream_pkt , header_size); update_mac_addr(stream,node,dir,(char *)p); + + if (stream->m_cache_size > 0 ) { + /* we need to create cache of objects */ + replay_vm_into_cache(stream, node); + } } @@ -825,6 +963,11 @@ TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj, lp_port->m_active_streams = 0; lp_port->set_event_id(event_id); + /* update cur time */ + if ( CGlobalInfo::is_realtime() ){ + m_core->m_cur_time_sec = now_sec() + SCHD_OFFSET_DTIME ; + } + /* no nodes in the list */ assert(lp_port->m_active_nodes.size()==0); diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index 0941f6f3..af2187ae 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -114,6 +114,8 @@ class TrexStatelessDpCore { public: + #define SCHD_OFFSET_DTIME (10.0/1000000.0) + /* states */ enum state_e { STATE_IDLE, @@ -302,6 +304,11 @@ private: TrexStream * stream, TrexStreamsCompiledObj *comp); + + void replay_vm_into_cache(TrexStream * stream, + CGenNodeStateless *node); + + uint8_t m_thread_id; uint8_t m_local_port_offset; diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h index 70054bbc..b5395e78 100644 --- a/src/stateless/dp/trex_stream_node.h +++ b/src/stateless/dp/trex_stream_node.h @@ -51,6 +51,15 @@ public: static_assert(sizeof(CGenNodeCommand) == sizeof(CGenNode), "sizeof(CGenNodeCommand) != sizeof(CGenNode)" ); +struct CGenNodeCacheMbuf { + rte_mbuf_t * m_mbuf_const; + rte_mbuf_t * m_array[0]; +public: + static uint32_t get_object_size(uint32_t size){ + return ( sizeof(CGenNodeCacheMbuf) + sizeof(rte_mbuf_t *) * size ); + } +}; + /* this is a event for stateless */ struct CGenNodeStateless : public CGenNodeBase { friend class TrexStatelessDpCore; @@ -63,10 +72,10 @@ public: SL_NODE_FLAGS_MBUF_CACHE =2, //USED by master SL_NODE_CONST_MBUF =4, - - SL_NODE_VAR_PKT_SIZE =8, - SL_NODE_STATS_NEEDED = 0x10 - + + SL_NODE_VAR_PKT_SIZE = 8, + SL_NODE_STATS_NEEDED = 0x10, + SL_NODE_CONST_MBUF_CACHE_ARRAY = 0x20 /* array of mbuf - cache */ }; enum { @@ -79,15 +88,18 @@ public: static std::string get_stream_state_str(stream_state_t stream_state); private: - /* cache line 0 */ - /* important stuff here */ - void * m_cache_mbuf; + /******************************/ + /* cache line 0 */ + /* important stuff here R/W */ + /******************************/ + void * m_cache_mbuf; /* could be an array or a one mbuf */ double m_next_time_offset; /* in sec */ uint16_t m_action_counter; uint8_t m_stat_hw_id; // hw id used to count rx and tx stats uint8_t m_null_stream; - uint32_t m_pad12; + uint16_t m_cache_array_cnt; + uint16_t m_pad12; stream_state_t m_state; uint8_t m_port_id; @@ -99,7 +111,10 @@ private: uint32_t m_multi_bursts; /* in case of multi_burst how many bursts */ - /* cache line 1 */ + /******************************/ + /* cache line 1 + this cache line should be READONLY ! you can write only at init time */ + /******************************/ TrexStream * m_ref_stream_info; /* the stream info */ CGenNodeStateless * m_next_stream; @@ -109,8 +124,11 @@ private: uint8_t * m_vm_flow_var; /* pointer to the vm flow var */ uint8_t * m_vm_program; /* pointer to the program */ uint16_t m_vm_program_size; /* up to 64K op codes */ - uint16_t m_pad2; - uint32_t m_pad3; + uint16_t m_cache_size; /*RO*/ /* the size of the mbuf array */ + uint8_t m_batch_size; /*RO*/ /* the batch size */ + + uint8_t m_pad4; + uint16_t m_pad5; /* End Fast Field VM Section */ @@ -120,6 +138,8 @@ private: public: + + void set_random_seed(uint32_t seed){ uint32_t *p=get_random_bss_seed_memory(); *p=seed; @@ -343,6 +363,10 @@ public: } } + void clear_const_mbuf(){ + m_flags= ( m_flags & ~SL_NODE_CONST_MBUF ); + } + /* prefix header exits only in non cache mode size is 64/128/512 other are not possible right now */ inline void alloc_prefix_header(uint16_t size){ set_prefix_header_size(size); @@ -353,6 +377,7 @@ public: inline void free_prefix_header(){ if (m_original_packet_data_prefix) { free(m_original_packet_data_prefix); + m_original_packet_data_prefix=0; } } @@ -370,6 +395,42 @@ public: void free_stl_node(); +protected: + + void free_stl_vm_buf(); + +public: + void cache_mbuf_array_init(); + + inline bool is_cache_mbuf_array(){ + return ( m_flags & SL_NODE_CONST_MBUF_CACHE_ARRAY ? true:false ); + } + + void cache_mbuf_array_copy(CGenNodeCacheMbuf *obj,uint16_t size); + + rte_mbuf_t ** cache_mbuf_array_alloc(uint16_t size); + + void cache_mbuf_array_free(); + + void cache_mbuf_array_set(uint16_t index,rte_mbuf_t * m); + + void cache_mbuf_array_set_const_mbuf(rte_mbuf_t * m); + + rte_mbuf_t * cache_mbuf_array_get_const_mbuf(); + + rte_mbuf_t * cache_mbuf_array_get(uint16_t index); + + rte_mbuf_t * cache_mbuf_array_get_cur(void){ + CGenNodeCacheMbuf *p =(CGenNodeCacheMbuf *) m_cache_mbuf; + rte_mbuf_t * m=p->m_array[m_cache_array_cnt]; + assert(m); + m_cache_array_cnt++; + if (m_cache_array_cnt == m_cache_size) { + m_cache_array_cnt=0; + } + return m; + } + public: /* debug functions */ |