summaryrefslogtreecommitdiffstats
path: root/src/stateless
diff options
context:
space:
mode:
Diffstat (limited to 'src/stateless')
-rw-r--r--src/stateless/cp/trex_stream.cpp3
-rw-r--r--src/stateless/cp/trex_stream.h3
-rw-r--r--src/stateless/cp/trex_vm_splitter.cpp28
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.cpp171
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.h7
-rw-r--r--src/stateless/dp/trex_stream_node.h83
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 */