diff options
-rwxr-xr-x | linux/ws_main.py | 39 | ||||
-rwxr-xr-x | linux_dpdk/ws_main.py | 3 | ||||
-rwxr-xr-x | src/bp_sim.cpp | 101 | ||||
-rwxr-xr-x | src/bp_sim.h | 8 | ||||
-rw-r--r-- | src/mock/trex_rpc_server_mock.cpp | 18 | ||||
-rwxr-xr-x | src/msg_manager.h | 11 | ||||
-rwxr-xr-x | src/nat_check.h | 10 | ||||
-rw-r--r-- | src/rpc-server/commands/trex_rpc_cmd_stream.cpp | 2 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless_port.cpp | 38 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream.h | 4 | ||||
-rw-r--r-- | src/stateless/dp/trex_stateless_dp_core.cpp | 137 | ||||
-rw-r--r-- | src/stateless/dp/trex_stateless_dp_core.h | 120 | ||||
-rw-r--r-- | src/stateless/messaging/trex_stateless_messaging.cpp | 60 | ||||
-rw-r--r-- | src/stateless/messaging/trex_stateless_messaging.h | 88 | ||||
-rw-r--r-- | src/stub/trex_stateless_stub.cpp | 13 |
15 files changed, 548 insertions, 104 deletions
diff --git a/linux/ws_main.py b/linux/ws_main.py index a94e975c..00fd3f21 100755 --- a/linux/ws_main.py +++ b/linux/ws_main.py @@ -91,10 +91,11 @@ def configure(conf): conf.load('g++') verify_cc_version(conf.env) - +bp_sim_main = SrcGroup(dir='src', + src_list=['main.cpp']) + main_src = SrcGroup(dir='src', src_list=[ - 'main.cpp', 'bp_sim.cpp', 'bp_gtest.cpp', 'os_time.cpp', @@ -146,6 +147,8 @@ stateless_src = SrcGroup(dir='src/stateless/', 'cp/trex_stream_vm.cpp', 'cp/trex_stateless.cpp', 'cp/trex_stateless_port.cpp', + 'dp/trex_stateless_dp_core.cpp', + 'messaging/trex_stateless_messaging.cpp', ]) # RPC code rpc_server_src = SrcGroup(dir='src/rpc-server/', @@ -169,8 +172,6 @@ rpc_server_mock_src = SrcGroup(dir='src/mock/', 'trex_rpc_server_mock.cpp', 'trex_platform_api_mock.cpp', '../gtest/rpc_test.cpp', - '../pal/linux/mbuf.cpp', - '../os_time.cpp', ]) # JSON package @@ -179,12 +180,6 @@ json_src = SrcGroup(dir='external_libs/json', 'jsoncpp.cpp' ]) -rpc_server_mock = SrcGroups([cmn_src, - rpc_server_src, - rpc_server_mock_src, - stateless_src, - json_src - ]) yaml_src = SrcGroup(dir='external_libs/yaml-cpp/src/', src_list=[ @@ -216,11 +211,30 @@ yaml_src = SrcGroup(dir='external_libs/yaml-cpp/src/', 'stream.cpp', 'tag.cpp']); + +rpc_server_mock = SrcGroups([ + main_src, + cmn_src, + rpc_server_src, + rpc_server_mock_src, + stateless_src, + json_src, + yaml_src, + net_src, + ]) + +# REMOVE ME - need to decide if stateless is part of bp sim or not +bp_hack_for_compile = SrcGroup(dir='/src/stub/', + src_list=['trex_stateless_stub.cpp' + ]) + bp =SrcGroups([ + bp_sim_main, main_src, cmn_src , net_src , yaml_src, + bp_hack_for_compile, ]); @@ -242,6 +256,7 @@ includes_path =''' ../src/pal/linux/ ../src/rpc-server/ ../src/stateless/cp/ ../src/stateless/dp/ + ../src/stateless/messaging/ ../external_libs/json/ ../external_libs/zmq/include/ ../external_libs/yaml-cpp/include/ @@ -372,13 +387,11 @@ class build_option: build_types = [ - #build_option(name = "bp-sim", src = bp, debug_mode= DEBUG_, platform = PLATFORM_32, is_pie = False), build_option(name = "bp-sim", src = bp, debug_mode= DEBUG_, platform = PLATFORM_64, is_pie = False), - #build_option(name = "bp-sim", src = bp, debug_mode= RELEASE_,platform = PLATFORM_32, is_pie = False), build_option(name = "bp-sim", src = bp, debug_mode= RELEASE_,platform = PLATFORM_64, is_pie = False), 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', '-Wno-sign-compare', '-Werror'], + flags = ['-DTREX_RPC_MOCK_SERVER', '-Wall', '-Wno-sign-compare'], rpath = ['.']), ] diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py index d54531f3..d8b1bc98 100755 --- a/linux_dpdk/ws_main.py +++ b/linux_dpdk/ws_main.py @@ -158,6 +158,8 @@ stateless_src = SrcGroup(dir='src/stateless/', 'cp/trex_stream_vm.cpp', 'cp/trex_stateless.cpp', 'cp/trex_stateless_port.cpp', + 'dp/trex_stateless_dp_core.cpp', + 'messaging/trex_stateless_messaging.cpp' ]) # JSON package json_src = SrcGroup(dir='external_libs/json', @@ -414,6 +416,7 @@ includes_path =''' ../src/pal/linux_dpdk/ ../src/rpc-server/ ../src/stateless/cp/ ../src/stateless/dp/ + ../src/stateless/messaging/ ../external_libs/yaml-cpp/include/ ../external_libs/zmq/include/ diff --git a/src/bp_sim.cpp b/src/bp_sim.cpp index d72da70c..72da7089 100755 --- a/src/bp_sim.cpp +++ b/src/bp_sim.cpp @@ -25,7 +25,6 @@ limitations under the License. #include "msg_manager.h" #include <common/basic_utils.h> - #undef VALG #ifdef VALG @@ -279,7 +278,7 @@ void CPlatformSocketInfoConfig::dump(FILE *fd){ fprintf(fd," \n"); fprintf(fd," active sockets : %d \n",max_num_active_sockets()); - fprintf(fd," ports_sockets : \n",max_num_active_sockets()); + fprintf(fd," ports_sockets : %d \n",max_num_active_sockets()); for (i=0; i<(MAX_LATENCY_PORTS); i++) { fprintf(fd,"%d,",port_to_socket(i)); @@ -3200,6 +3199,10 @@ bool CFlowGenListPerThread::Create(uint32_t thread_id, assert(m_ring_from_rx); assert(m_ring_to_rx); + + /* create the info required for stateless DP core */ + m_stateless_dp_info = new TrexStatelessDpCore(thread_id, this); + return (true); } @@ -3347,6 +3350,9 @@ void CFlowGenListPerThread::Delete(){ m_node_gen.Delete(); Clean(); m_cpu_cp_u.Delete(); + + delete m_stateless_dp_info; + m_stateless_dp_info = NULL; } @@ -3452,12 +3458,9 @@ int CNodeGenerator::flush_file(dsec_t max_time, uint8_t type=node->m_type; if ( type == CGenNode::STATELESS_PKT ) { - - flush_one_node_to_file(node); - /* in case of continues */ - node->m_time += 0.0001; /*TBD PPS*/ - m_p_queue.push(node); - /* no need per thread stats, it is too heavy */ + m_p_queue.pop(); + // TODO: should this be inlined ? with IPO is this important ? + thread->m_stateless_dp_info->handle_pkt_event(node); }else{ if ( likely( type == CGenNode::FLOW_PKT ) ) { @@ -3564,9 +3567,12 @@ void CNodeGenerator::handle_slow_messages(uint8_t type, }else{ if ( type == CGenNode::FLOW_SYNC ){ + + m_p_queue.pop(); + thread->check_msgs(); /* check messages */ m_v_if->flush_tx_queue(); /* flush pkt each timeout */ - m_p_queue.pop(); + if ( always == false) { node->m_time += SYNC_TIME_OUT; m_p_queue.push(node); @@ -3815,11 +3821,15 @@ void CFlowGenListPerThread::handel_nat_msg(CGenNodeNatInfo * msg){ } } +void CFlowGenListPerThread::check_msgs(void) { + + /* inlined for performance */ + m_stateless_dp_info->periodic_check_for_cp_messages(); -void CFlowGenListPerThread::check_msgs(void){ - if ( likely ( m_ring_from_rx->isEmpty() ) ){ + if ( likely ( m_ring_from_rx->isEmpty() ) ) { return; } + #ifdef NAT_TRACE_ printf(" %.03f got message from RX \n",now_sec()); #endif @@ -3839,9 +3849,11 @@ void CFlowGenListPerThread::check_msgs(void){ case CGenNodeMsgBase::NAT_FIRST: handel_nat_msg((CGenNodeNatInfo * )msg); break; + case CGenNodeMsgBase::LATENCY_PKT: handel_latecy_pkt_msg((CGenNodeLatencyPktInfo *) msg); break; + default: printf("ERROR pkt-thread message type is not valid %d \n",msg_type); assert(0); @@ -3887,72 +3899,8 @@ const uint8_t test_udp_pkt[]={ 0xe7 }; - - - -void CFlowGenListPerThread::start_stateless_const_rate_demo(){ - - CGenNodeStateless * node= create_node_sl(); - - /* add periodic */ - node->m_type = CGenNode::STATELESS_PKT; - node->m_time = m_cur_time_sec+ 0.0 /* STREAM ISG */; - node->m_flags =0; - - /* set socket id */ - node->set_socket_id(m_node_gen.m_socket_id); - - /* build a mbuf from a packet */ - uint16_t pkt_size=sizeof(test_udp_pkt); - uint8_t * stream_pkt=(uint8_t *)test_udp_pkt; - - /* 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 */ - pkt_dir_t dir=0; - node->set_mbuf_cache_dir(dir); - - /* TBD repace the mac if req we should add flag */ - 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 0 - /* dump the packet */ - uint8_t *p1=rte_pktmbuf_mtod(m, uint8_t*); - uint16_t pkt_size1=rte_pktmbuf_pkt_len(m); - utl_DumpBuffer(stdout,p,pkt_size,0); - #endif - - m_node_gen.add_node((CGenNode *)node); - - - double old_offset=0.0; - - CGenNode * node_sync= create_node() ; - node_sync->m_type = CGenNode::FLOW_SYNC; - node_sync->m_time = m_cur_time_sec + SYNC_TIME_OUT ; - m_node_gen.add_node(node_sync); - - // TBD time - m_node_gen.flush_file(100000000,0.0, false,this,old_offset); -} - void CFlowGenListPerThread::start_stateless_daemon(){ - /* todo sleep */ - start_stateless_const_rate_demo(); - - while (1) { - delay(100); - } - /* sleep , get message from queue, shecudule --> get message */ + m_stateless_dp_info->start(); } @@ -4073,6 +4021,7 @@ int CFlowGenList::load_from_mac_file(std::string file_name) { exit(-1); } + return (0); } diff --git a/src/bp_sim.h b/src/bp_sim.h index 2cdfccb2..5747c2da 100755 --- a/src/bp_sim.h +++ b/src/bp_sim.h @@ -57,6 +57,8 @@ limitations under the License. #include <arpa/inet.h> #include "platform_cfg.h" +#include <trex_stateless_dp_core.h> + #undef NAT_TRACE_ @@ -1641,6 +1643,9 @@ public: struct CGenNodeStateless : public CGenNodeBase { public: + inline uint8_t *get_opaque_storage() { + return (uint8_t *)&m_pad_end; + } private: void * m_cache_mbuf; @@ -3450,7 +3455,6 @@ public: void Clean(); void start_generate_stateful(std::string erf_file_name,CPreviewMode &preview); void start_stateless_daemon(); - void start_stateless_const_rate_demo(); void Dump(FILE *fd); @@ -3465,6 +3469,7 @@ public: private: void check_msgs(void); + void handel_nat_msg(CGenNodeNatInfo * msg); void handel_latecy_pkt_msg(CGenNodeLatencyPktInfo * msg); @@ -3543,6 +3548,7 @@ private: flow_id_node_t m_flow_id_to_node_lookup; + TrexStatelessDpCore *m_stateless_dp_info; private: uint8_t m_cacheline_pad[RTE_CACHE_LINE_SIZE][19]; // improve prefech diff --git a/src/mock/trex_rpc_server_mock.cpp b/src/mock/trex_rpc_server_mock.cpp index 6e14390a..6642e50e 100644 --- a/src/mock/trex_rpc_server_mock.cpp +++ b/src/mock/trex_rpc_server_mock.cpp @@ -82,6 +82,24 @@ uint16_t gtest_get_mock_server_port() { return g_rpc_port; } +void delay(int msec){ + + if (msec == 0) + {//user that requested that probebly wanted the minimal delay + //but because of scaling problem he have got 0 so we will give the min delay + //printf("\n\n\nERROR-Task delay ticks == 0 found in task %s task id = %d\n\n\n\n", + // SANB_TaskName(SANB_TaskIdSelf()), SANB_TaskIdSelf()); + msec =1; + + } + + struct timespec time1, remain; // 2 sec max delay + time1.tv_sec=msec/1000; + time1.tv_nsec=(msec - (time1.tv_sec*1000))*1000000; + + nanosleep(&time1,&remain); +} + /** * on simulation this is not rebuild every version * (improved stub) diff --git a/src/msg_manager.h b/src/msg_manager.h index 6308eb1b..8958f826 100755 --- a/src/msg_manager.h +++ b/src/msg_manager.h @@ -28,8 +28,15 @@ limitations under the License. /* messages from CP->DP Ids */ -#define NAT_MSG (7) -#define LATENCY_PKT_SEND_MSG (8) +struct CGenNodeMsgBase { + enum { + NAT_FIRST = 7, + LATENCY_PKT = 8, + } msg_types; + +public: + uint8_t m_msg_type; /* msg type */ +}; /* diff --git a/src/nat_check.h b/src/nat_check.h index b67c523c..a500ddaf 100755 --- a/src/nat_check.h +++ b/src/nat_check.h @@ -59,16 +59,6 @@ struct CNatFlowInfo { this struct should be in the same size of CGenNode beacuse allocator is global . */ -struct CGenNodeMsgBase { - enum { - NAT_FIRST = NAT_MSG, - LATENCY_PKT = LATENCY_PKT_SEND_MSG - } msg_types; - -public: - uint8_t m_msg_type; /* msg type */ -}; - struct CGenNodeNatInfo : public CGenNodeMsgBase { uint8_t m_pad; diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp index 4f697e3c..51ac0f92 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp @@ -462,7 +462,7 @@ TrexRpcCmdStartTraffic::_run(const Json::Value ¶ms, Json::Value &result) { generate_execute_err(result, ss.str()); } - return (TREX_RPC_CMD_OK); + return (TREX_RPC_CMD_OK); } /*************************** diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 6b77b107..92d0a7f8 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -18,8 +18,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ + #include <trex_stateless.h> #include <trex_stateless_port.h> +#include <trex_stateless_messaging.h> + #include <string> #ifndef TREX_RPC_MOCK_SERVER @@ -61,7 +64,32 @@ TrexStatelessPort::start_traffic(void) { m_port_state = PORT_STATE_TRANSMITTING; - /* real code goes here */ + + /* ************* A HACK FOR NOW *************/ + /* we support only one stream continious */ + if (get_stream_table()->size() != 1) { + return (RC_ERR_FAILED_TO_COMPILE_STREAMS); + } + + TrexStream *stream; + for (auto it = get_stream_table()->begin(); it != get_stream_table()->end(); it++ ) { + stream = (*it).second; + } + + /* support only cont streams */ + TrexStreamContinuous *cont_stream = dynamic_cast<TrexStreamContinuous *>(stream); + if (!cont_stream) { + return (RC_ERR_FAILED_TO_COMPILE_STREAMS); + } + + /* generate a message to all the relevant DP cores to start transmitting */ + TrexStatelessCpToDpMsgBase *start_msg = new TrexStatelessDpStart(cont_stream->m_pkt.binary, cont_stream->m_pkt.len, cont_stream->get_pps()); + + // FIXME (add the right core list) + CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingCpToDp(0); + + ring->Enqueue((CGenNode *)start_msg); + return (RC_OK); } @@ -72,6 +100,14 @@ TrexStatelessPort::stop_traffic(void) { if (m_port_state == PORT_STATE_TRANSMITTING) { m_port_state = PORT_STATE_UP_IDLE; } + + /* generate a message to all the relevant DP cores to start transmitting */ + TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(); + + // FIXME (add the right core list) + CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingCpToDp(0); + + ring->Enqueue((CGenNode *)stop_msg); } /** diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index f5bc96ef..91e64d23 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -41,6 +41,7 @@ class TrexStream { friend class TrexRpcCmdAddStream; friend class TrexRpcCmdGetStream; friend class TrexStreamTable; + friend class TrexStatelessPort; public: TrexStream(uint8_t port_id, uint32_t stream_id); @@ -197,6 +198,9 @@ public: */ int size(); + std::unordered_map<int, TrexStream *>::iterator begin() {return m_stream_table.begin();} + std::unordered_map<int, TrexStream *>::iterator end() {return m_stream_table.end();} + private: /** * holds all the stream in a hash table by stream id diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp new file mode 100644 index 00000000..20eadfc5 --- /dev/null +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -0,0 +1,137 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#include <trex_stateless_dp_core.h> +#include <trex_stateless_messaging.h> + +#include <bp_sim.h> + +typedef struct dp_node_extended_info_ { + double next_time_offset; +} dp_node_extended_info_st; + +TrexStatelessDpCore::TrexStatelessDpCore(uint8_t thread_id, CFlowGenListPerThread *core) { + m_thread_id = thread_id; + m_core = core; + + m_state = STATE_IDLE; + + CMessagingManager * cp_dp = CMsgIns::Ins()->getCpDp(); + + m_ring_from_cp = cp_dp->getRingCpToDp(thread_id); + m_ring_to_cp = cp_dp->getRingDpToCp(thread_id); +} + +void +TrexStatelessDpCore::start() { + + /* creates a maintenace job using the scheduler */ + CGenNode * node_sync = m_core->create_node() ; + node_sync->m_type = CGenNode::FLOW_SYNC; + node_sync->m_time = m_core->m_cur_time_sec + SYNC_TIME_OUT; + m_core->m_node_gen.add_node(node_sync); + + double old_offset = 0.0; + m_core->m_node_gen.flush_file(100000000, 0.0, false, m_core, old_offset); + +} + +void +TrexStatelessDpCore::handle_pkt_event(CGenNode *node) { + + /* if port has stopped - no transmition */ + if (m_state == STATE_IDLE) { + return; + } + + m_core->m_node_gen.m_v_if->send_node(node); + + CGenNodeStateless *node_sl = (CGenNodeStateless *)node; + + /* in case of continues */ + dp_node_extended_info_st *opaque = (dp_node_extended_info_st *)node_sl->get_opaque_storage(); + node->m_time += opaque->next_time_offset; + + /* insert a new event */ + m_core->m_node_gen.m_p_queue.push(node); +} + +void +TrexStatelessDpCore::start_const_traffic(const uint8_t *pkt, + uint16_t pkt_len, + double pps) { + + CGenNodeStateless *node = m_core->create_node_sl(); + + /* add periodic */ + node->m_type = CGenNode::STATELESS_PKT; + node->m_time = m_core->m_cur_time_sec + 0.0 /* STREAM ISG */; + 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; + + dp_node_extended_info_st *opaque = (dp_node_extended_info_st *)node->get_opaque_storage(); + opaque->next_time_offset = 1.0 / pps; + + /* 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 */ + pkt_dir_t dir = 0; + 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); + + m_state = TrexStatelessDpCore::STATE_TRANSMITTING; + + m_core->m_node_gen.add_node((CGenNode *)node); + +} + +void +TrexStatelessDpCore::stop_traffic() { + m_state = STATE_IDLE; +} + +/** + * handle a message from CP to DP + * + */ +void +TrexStatelessDpCore::handle_cp_msg(TrexStatelessCpToDpMsgBase *msg) { + msg->handle(this); + delete msg; +} + diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h new file mode 100644 index 00000000..65d894d2 --- /dev/null +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -0,0 +1,120 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#ifndef __TREX_STATELESS_DP_CORE_H__ +#define __TREX_STATELESS_DP_CORE_H__ + +#include <msg_manager.h> +#include <pal_utl.h> + +class TrexStatelessCpToDpMsgBase; +class TrexStatelessDpStart; +class CFlowGenListPerThread; +class CGenNode; + +class TrexStatelessDpCore { + +public: + + /* states */ + enum state_e { + STATE_IDLE, + STATE_TRANSMITTING + }; + + TrexStatelessDpCore(uint8_t thread_id, CFlowGenListPerThread *core); + + /** + * launch the stateless DP core code + * + */ + void start(); + + /** + * handle pkt event + * + * @author imarom (27-Oct-15) + */ + void handle_pkt_event(CGenNode *node); + + /** + * dummy traffic creator + * + * @author imarom (27-Oct-15) + * + * @param pkt + * @param pkt_len + */ + void start_const_traffic(const uint8_t *pkt, uint16_t pkt_len, double pps); + + /** + * stop all traffic for this core + * + */ + void stop_traffic(); + + /** + * check for and handle messages from CP + * + * @author imarom (27-Oct-15) + */ + void periodic_check_for_cp_messages() { + // doing this inline for performance reasons + + /* fast path */ + if ( likely ( m_ring_from_cp->isEmpty() ) ) { + return; + } + + while ( true ) { + CGenNode * node; + if (m_ring_from_cp->Dequeue(node) != 0) { + break; + } + + assert(node); + + TrexStatelessCpToDpMsgBase * msg = (TrexStatelessCpToDpMsgBase *)node; + handle_cp_msg(msg); + } + + } + +private: + /** + * handles a CP to DP message + * + * @author imarom (27-Oct-15) + * + * @param msg + */ + void handle_cp_msg(TrexStatelessCpToDpMsgBase *msg); + + uint8_t m_thread_id; + state_e m_state; + CNodeRing *m_ring_from_cp; + CNodeRing *m_ring_to_cp; + + /* pointer to the main object */ + CFlowGenListPerThread *m_core; +}; + +#endif /* __TREX_STATELESS_DP_CORE_H__ */ + diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp new file mode 100644 index 00000000..4cd5b416 --- /dev/null +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -0,0 +1,60 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#include <trex_stateless_messaging.h> +#include <trex_stateless_dp_core.h> +#include <string.h> + +/************************* + start traffic message + ************************/ +TrexStatelessDpStart::TrexStatelessDpStart(const uint8_t *pkt, uint16_t pkt_len, double pps) { + assert(pkt); + assert(pkt_len > 0); + + m_pkt = new uint8_t[pkt_len]; + memcpy(m_pkt, pkt, pkt_len); + m_pkt_len = pkt_len; + + m_pps = pps; +} + +TrexStatelessDpStart::~TrexStatelessDpStart() { + if (m_pkt) { + delete m_pkt; + } +} + +bool +TrexStatelessDpStart::handle(TrexStatelessDpCore *dp_core) { + + dp_core->start_const_traffic(m_pkt, m_pkt_len, m_pps); + return true; +} + +/************************* + stop traffic message + ************************/ +bool +TrexStatelessDpStop::handle(TrexStatelessDpCore *dp_core) { + dp_core->stop_traffic(); + return true; +} + diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h new file mode 100644 index 00000000..af05aa4c --- /dev/null +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -0,0 +1,88 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#ifndef __TREX_STATELESS_MESSAGING_H__ +#define __TREX_STATELESS_MESSAGING_H__ + +#include <msg_manager.h> + +class TrexStatelessDpCore; + +/** + * defines the base class for CP to DP messages + * + * @author imarom (27-Oct-15) + */ +class TrexStatelessCpToDpMsgBase { +public: + + TrexStatelessCpToDpMsgBase() { + } + + virtual ~TrexStatelessCpToDpMsgBase() { + } + + /** + * virtual function to handle a message + * + */ + virtual bool handle(TrexStatelessDpCore *dp_core) = 0; +}; + +/** + * a message to start traffic + * + * @author imarom (27-Oct-15) + */ +class TrexStatelessDpStart : public TrexStatelessCpToDpMsgBase { +public: + + TrexStatelessDpStart(const uint8_t *pkt, uint16_t pkt_len, double pps); + + ~TrexStatelessDpStart(); + + const uint8_t * get_pkt() { + return m_pkt; + } + + uint16_t get_pkt_len() { + return m_pkt_len; + } + + virtual bool handle(TrexStatelessDpCore *dp_core); + +private: + uint8_t *m_pkt; + uint16_t m_pkt_len; + double m_pps; +}; + +/** + * a message to stop traffic + * + * @author imarom (27-Oct-15) + */ +class TrexStatelessDpStop : public TrexStatelessCpToDpMsgBase { +public: + virtual bool handle(TrexStatelessDpCore *dp_core); +}; + + +#endif /* __TREX_STATELESS_MESSAGING_H__ */ diff --git a/src/stub/trex_stateless_stub.cpp b/src/stub/trex_stateless_stub.cpp new file mode 100644 index 00000000..8e8d4fa8 --- /dev/null +++ b/src/stub/trex_stateless_stub.cpp @@ -0,0 +1,13 @@ + +#include <trex_stateless_dp_core.h> + +class CFlowGenListPerThread; +class TrexStatelessCpToDpMsgBase; + +TrexStatelessDpCore::TrexStatelessDpCore(unsigned char, CFlowGenListPerThread*) {} + +void TrexStatelessDpCore::start(){} + +void TrexStatelessDpCore::handle_cp_msg(TrexStatelessCpToDpMsgBase*) {} + +void TrexStatelessDpCore::handle_pkt_event(CGenNode*) {} |