From 2e51cea370c6c401453d77b23f552811a669d86a Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Mon, 30 Nov 2015 14:31:39 +0200 Subject: vm mode works - first test --- src/bp_gtest.cpp | 2 +- src/bp_sim.cpp | 19 ++++-- src/bp_sim.h | 6 +- src/gtest/trex_stateless_gtest.cpp | 54 ++++++++++++++++ src/main_dpdk.cpp | 19 +++--- src/stateless/cp/trex_stream.cpp | 2 + src/stateless/cp/trex_stream.h | 6 ++ src/stateless/dp/trex_stateless_dp_core.cpp | 98 +++++++++++++++++++++++++---- src/stateless/dp/trex_stream_node.h | 54 +++++++++++++++- 9 files changed, 229 insertions(+), 31 deletions(-) diff --git a/src/bp_gtest.cpp b/src/bp_gtest.cpp index a94c2d37..f24464e3 100755 --- a/src/bp_gtest.cpp +++ b/src/bp_gtest.cpp @@ -2020,7 +2020,7 @@ public: virtual int send_node(CGenNode * node); - virtual int update_mac_addr_from_global_cfg(pkt_dir_t dir, rte_mbuf_t *m){ + virtual int update_mac_addr_from_global_cfg(pkt_dir_t dir, uint8_t * p){ return (0); } diff --git a/src/bp_sim.cpp b/src/bp_sim.cpp index a61fbb8f..ed729c75 100755 --- a/src/bp_sim.cpp +++ b/src/bp_sim.cpp @@ -4657,13 +4657,24 @@ int CErfIFStl::send_node(CGenNode * _no_to_use){ if ( m_preview_mode->getFileWrite() ){ CGenNodeStateless * node_sl=(CGenNodeStateless *) _no_to_use; - + + pkt_dir_t dir=(pkt_dir_t)node_sl->get_mbuf_cache_dir(); + /* 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(); + if (m) { + /* cache packet */ + fill_raw_packet(m,_no_to_use,dir); + /* can't free the m, it is cached*/ + }else{ + + m=node_sl->alloc_node_with_vm(); + assert(m); + fill_raw_packet(m,_no_to_use,dir); + rte_pktmbuf_free(m); + + } - fill_raw_packet(m,_no_to_use,dir); BP_ASSERT(m_writer); bool res=m_writer->write_packet(m_raw); diff --git a/src/bp_sim.h b/src/bp_sim.h index 0da7fb99..b71cb3ff 100755 --- a/src/bp_sim.h +++ b/src/bp_sim.h @@ -380,7 +380,7 @@ public: * * @return */ - virtual int update_mac_addr_from_global_cfg(pkt_dir_t dir, rte_mbuf_t *m)=0; + virtual int update_mac_addr_from_global_cfg(pkt_dir_t dir, uint8_t * p)=0; /** * translate a port_id to the correct dir on the core @@ -1799,7 +1799,7 @@ public: virtual int write_pkt(CCapPktRaw *pkt_raw); virtual int close_file(void); - virtual int update_mac_addr_from_global_cfg(pkt_dir_t dir, rte_mbuf_t *m){ + virtual int update_mac_addr_from_global_cfg(pkt_dir_t dir, uint8_t * p){ return (0); } @@ -1878,7 +1878,7 @@ public: return (0); } - virtual int update_mac_addr_from_global_cfg(pkt_dir_t dir, rte_mbuf_t *m){ + virtual int update_mac_addr_from_global_cfg(pkt_dir_t dir, uint8_t * p){ return (0); } diff --git a/src/gtest/trex_stateless_gtest.cpp b/src/gtest/trex_stateless_gtest.cpp index ea54a935..e236a63d 100644 --- a/src/gtest/trex_stateless_gtest.cpp +++ b/src/gtest/trex_stateless_gtest.cpp @@ -1246,6 +1246,60 @@ TEST_F(basic_stl, multi_pkt1) { +TEST_F(basic_stl, vm_enable0) { + + CBasicStl t1; + CParserOption * po =&CGlobalInfo::m_options; + po->preview.setVMode(7); + po->preview.setFileWrite(true); + po->out_file ="exp/stl_vm_enable0"; + + TrexStreamsCompiler compile; + + uint8_t port_id=0; + + std::vector streams; + + TrexStream * stream1 = new TrexStream(TrexStream::stCONTINUOUS,0,0); + stream1->m_has_vm = true; + stream1->m_vm_prefix_size =64; + stream1->set_pps(1.0); + + + stream1->m_enabled = true; + stream1->m_self_start = true; + stream1->m_port_id= port_id; + + + 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(port_id, 1.0 /*mul*/); + + assert(compile.compile(streams, comp_obj) ); + + TrexStatelessDpStart * lpstart = new TrexStatelessDpStart(port_id, 0, comp_obj.clone(), 10.0 /*sec */ ); + + + t1.m_msg = lpstart; + + bool res=t1.init(); + + delete stream1 ; + + EXPECT_EQ_UINT32(1, res?1:0)<< "pass"; +} + + + + + /* check disabled stream with multiplier of 5*/ TEST_F(basic_stl, multi_pkt2) { diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index 3e5418b9..c17f32f3 100755 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -1875,7 +1875,7 @@ public: bool process_rx_pkt(pkt_dir_t dir,rte_mbuf_t * m); - virtual int update_mac_addr_from_global_cfg(pkt_dir_t dir, rte_mbuf_t *m); + virtual int update_mac_addr_from_global_cfg(pkt_dir_t dir, uint8_t * p); virtual pkt_dir_t port_id_to_dir(uint8_t port_id); @@ -2186,12 +2186,18 @@ int CCoreEthIFStateless::send_node(CGenNode * no){ /* 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(); CCorePerPort * lp_port=&m_ports[dir]; CVirtualIFPerSideStats * lp_stats = &m_stats[dir]; - rte_pktmbuf_refcnt_update(m,1); + if (m) { + /* cache case */ + rte_pktmbuf_refcnt_update(m,1); + }else{ + m=node_sl->alloc_node_with_vm(); + assert(m); + } send_pkt(lp_port,m,lp_stats); + return (0); }; @@ -2290,14 +2296,11 @@ int CCoreEthIF::send_node(CGenNode * node){ } -int CCoreEthIF::update_mac_addr_from_global_cfg(pkt_dir_t dir, - rte_mbuf_t *m){ - assert(m); +int CCoreEthIF::update_mac_addr_from_global_cfg(pkt_dir_t dir, uint8_t * p){ + assert(p); assert(dir<2); CCorePerPort * lp_port=&m_ports[dir]; - uint8_t *p=rte_pktmbuf_mtod(m, uint8_t*); uint8_t p_id=lp_port->m_port->get_port_id(); - memcpy(p,CGlobalInfo::m_options.get_dst_src_mac_addr(p_id),12); return (0); } diff --git a/src/stateless/cp/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp index cad603e2..8ea0c011 100644 --- a/src/stateless/cp/trex_stream.cpp +++ b/src/stateless/cp/trex_stream.cpp @@ -103,6 +103,8 @@ TrexStream::TrexStream(uint8_t type, m_pkt.binary = NULL; m_pkt.len = 0; + m_has_vm = false; + m_vm_prefix_size = 0; m_rx_check.m_enable = false; diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index 3e48d7e4..c42d0985 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -133,6 +133,9 @@ public: TrexStream * dp=new TrexStream(m_type,m_port_id,m_stream_id); + dp->m_has_vm = m_has_vm; + dp->m_vm_prefix_size = m_vm_prefix_size; + dp->m_isg_usec = m_isg_usec; dp->m_next_stream_id = m_next_stream_id; @@ -165,6 +168,7 @@ public: /* basic */ uint8_t m_type; uint8_t m_port_id; + uint16_t m_vm_prefix_size; uint32_t m_stream_id; /* id from RPC can be anything */ @@ -175,6 +179,8 @@ public: /* indicators */ bool m_enabled; bool m_self_start; + bool m_has_vm; /* do we have instructions to run */ + CStreamPktData m_pkt; /* pkt */ diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 9b62fabd..c7bb7636 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -106,13 +106,45 @@ std::string CGenNodeStateless::get_stream_state_str(stream_state_t stream_state) } +rte_mbuf_t * CGenNodeStateless::alloc_node_with_vm(){ + + rte_mbuf_t * m; + /* alloc small packet buffer*/ + uint16_t prefix_size = prefix_header_size(); + m = CGlobalInfo::pktmbuf_alloc( get_socket_id(), prefix_size ); + if (m==0) { + return (m); + } + /* TBD remove this, should handle cases of error */ + assert(m); + char *p=rte_pktmbuf_append(m, prefix_size); + memcpy( p ,m_original_packet_data_prefix, prefix_size); + + /* TBD run VM on the pointer p */ + + rte_mbuf_t * m_const = get_const_mbuf(); + if ( m_const != NULL) { + utl_rte_pktmbuf_add_after(m,m_const); + } + 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 */ + m=get_const_mbuf(); + if (m) { + rte_pktmbuf_free(m); /* reduce the ref counter */ + } + free_prefix_header(); } + } @@ -442,6 +474,10 @@ TrexStatelessDpCore::add_stream(TrexStatelessDpPerPort * lp_port, pkt_dir_t dir = m_core->m_node_gen.m_v_if->port_id_to_dir(stream->m_port_id); node->m_flags = 0; + node->m_src_port =0; + node->m_original_packet_data_prefix = 0; + + /* set socket id */ node->set_socket_id(m_core->m_node_gen.m_socket_id); @@ -486,23 +522,59 @@ TrexStatelessDpCore::add_stream(TrexStatelessDpPerPort * lp_port, node->m_port_id = stream->m_port_id; - /* allocate const mbuf */ - rte_mbuf_t *m = CGlobalInfo::pktmbuf_alloc(node->get_socket_id(), pkt_size); - assert(m); - - char *p = rte_pktmbuf_append(m, pkt_size); - assert(p); - /* copy the packet */ - memcpy(p,stream_pkt,pkt_size); - /* set dir 0 or 1 client or server */ node->set_mbuf_cache_dir(dir); - /* TBD repace the mac if req we should add flag */ - m_core->m_node_gen.m_v_if->update_mac_addr_from_global_cfg(dir, m); - /* set the packet as a readonly */ - node->set_cache_mbuf(m); + if (stream->m_has_vm == false ) { + /* allocate const mbuf */ + rte_mbuf_t *m = CGlobalInfo::pktmbuf_alloc(node->get_socket_id(), pkt_size); + assert(m); + + char *p = rte_pktmbuf_append(m, pkt_size); + assert(p); + /* copy the packet */ + memcpy(p,stream_pkt,pkt_size); + + /* TBD repace the mac if req we should add flag */ + m_core->m_node_gen.m_v_if->update_mac_addr_from_global_cfg(dir,(uint8_t*) p); + + /* set the packet as a readonly */ + node->set_cache_mbuf(m); + }else{ + /* we need to copy the object */ + + if ( pkt_size > stream->m_vm_prefix_size ) { + /* we need const packet */ + uint16_t const_pkt_size = pkt_size - stream->m_vm_prefix_size ; + rte_mbuf_t *m = CGlobalInfo::pktmbuf_alloc(node->get_socket_id(), const_pkt_size ); + assert(m); + + char *p = rte_pktmbuf_append(m, const_pkt_size); + assert(p); + + /* copy packet data */ + memcpy(p,(stream_pkt+ stream->m_vm_prefix_size),const_pkt_size); + + node->set_const_mbuf(m); + } + + + if (stream->m_vm_prefix_size > pkt_size ) { + stream->m_vm_prefix_size = pkt_size; + } + /* copy the headr */ + uint16_t header_size = stream->m_vm_prefix_size; + assert(header_size); + node->alloc_prefix_header(header_size); + uint8_t *p=node->m_original_packet_data_prefix; + assert(p); + + memcpy(p,stream_pkt , header_size); + /* TBD repace the mac if req we should add flag */ + m_core->m_node_gen.m_v_if->update_mac_addr_from_global_cfg(dir, p); + } + CDpOneStream one_stream; diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h index 111af845..1ae8cbbc 100644 --- a/src/stateless/dp/trex_stream_node.h +++ b/src/stateless/dp/trex_stream_node.h @@ -54,6 +54,16 @@ struct CGenNodeStateless : public CGenNodeBase { friend class TrexStatelessDpCore; public: + + /* flags MASKS*/ + enum { + SL_NODE_FLAGS_DIR =1, //USED by master + SL_NODE_FLAGS_MBUF_CACHE =2, //USED by master + + SL_NODE_CONST_MBUF =4 + + }; + enum { ss_FREE_RESUSE =1, /* should be free by scheduler */ ss_INACTIVE =2, /* will be active by other stream or stopped */ @@ -86,8 +96,10 @@ private: TrexStream * m_ref_stream_info; /* the stream info */ CGenNodeStateless * m_next_stream; + uint8_t * m_original_packet_data_prefix; /* pointer to the original first pointer 64/128/512 */ + /* pad to match the size of CGenNode */ - uint8_t m_pad_end[56]; + uint8_t m_pad_end[48]; @@ -256,13 +268,51 @@ public: } inline rte_mbuf_t * get_cache_mbuf(){ - if ( m_flags &NODE_FLAGS_MBUF_CACHE ) { + if ( m_flags & NODE_FLAGS_MBUF_CACHE ) { + return ((rte_mbuf_t *)m_cache_mbuf); + }else{ + return ((rte_mbuf_t *)0); + } + } + + inline void set_const_mbuf(rte_mbuf_t * m){ + m_cache_mbuf=(void *)m; + m_flags |= SL_NODE_CONST_MBUF; + } + + inline rte_mbuf_t * get_const_mbuf(){ + if ( m_flags &SL_NODE_CONST_MBUF ) { return ((rte_mbuf_t *)m_cache_mbuf); }else{ return ((rte_mbuf_t *)0); } } + /* prefix header exits only in non cache mode size is 64/128/512 other are not possible right now */ + inline void alloc_prefix_header(uint8_t size){ + set_prefix_header_size(size); + m_original_packet_data_prefix = (uint8_t *)malloc(size); + assert(m_original_packet_data_prefix); + } + + inline void free_prefix_header(){ + if (m_original_packet_data_prefix) { + free(m_original_packet_data_prefix); + } + } + + /* prefix headr could be 64/128/512 */ + inline void set_prefix_header_size(uint16_t size){ + m_src_port=size; + } + + inline uint16_t prefix_header_size(){ + return (m_src_port); + } + + + rte_mbuf_t * alloc_node_with_vm(); + void free_stl_node(); public: -- cgit 1.2.3-korg