summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHanoh Haim <hhaim@cisco.com>2015-10-19 16:30:55 +0300
committerHanoh Haim <hhaim@cisco.com>2015-10-19 16:30:55 +0300
commit872a205b4c5e4119b6d0d10a7ec774ce22d63256 (patch)
treee650ddcc3ceb5cb9e4b9c33609fcbfc956455f03 /src
parentcf5dc18ecbeca6b4be9a171d996bba1cba9c3679 (diff)
parent6c7880b9881ed6690954f0c29259dd0b584b3970 (diff)
Merge branch 'rpc' -> add support for interactive mode
Diffstat (limited to 'src')
-rwxr-xr-xsrc/bp_sim.h34
-rw-r--r--src/gtest/rpc_test.cpp9
-rwxr-xr-xsrc/main_dpdk.cpp160
-rw-r--r--src/mock/rte_ethdev.h44
-rw-r--r--src/mock/trex_rpc_server_mock.cpp (renamed from src/rpc-server/trex_rpc_server_mock.cpp)44
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_general.cpp17
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_stream.cpp5
-rw-r--r--src/rpc-server/trex_rpc_async_server.cpp109
-rw-r--r--src/rpc-server/trex_rpc_async_server.h54
-rw-r--r--src/rpc-server/trex_rpc_cmd.cpp3
-rw-r--r--src/rpc-server/trex_rpc_req_resp_server.cpp12
-rw-r--r--src/rpc-server/trex_rpc_req_resp_server.h2
-rw-r--r--src/rpc-server/trex_rpc_server.cpp16
-rw-r--r--src/rpc-server/trex_rpc_server_api.h11
-rw-r--r--src/stateless/cp/trex_stateless.cpp212
-rw-r--r--src/stateless/cp/trex_stateless.h202
-rw-r--r--src/stateless/cp/trex_stateless_port.cpp226
-rw-r--r--src/stateless/cp/trex_stateless_port.h (renamed from src/stateless/trex_stateless_api.h)158
-rw-r--r--src/stateless/cp/trex_stream.cpp (renamed from src/stateless/trex_stream.cpp)2
-rw-r--r--src/stateless/cp/trex_stream.h (renamed from src/stateless/trex_stream_api.h)6
-rw-r--r--src/stateless/cp/trex_stream_vm.cpp (renamed from src/stateless/trex_stream_vm.cpp)0
-rw-r--r--src/stateless/cp/trex_stream_vm.h (renamed from src/stateless/trex_stream_vm.h)0
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.cpp132
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.h43
-rw-r--r--src/stateless/trex_stateless.cpp171
-rwxr-xr-xsrc/tuple_gen.h3
26 files changed, 1321 insertions, 354 deletions
diff --git a/src/bp_sim.h b/src/bp_sim.h
index 675e88b4..b7cfb20b 100755
--- a/src/bp_sim.h
+++ b/src/bp_sim.h
@@ -221,7 +221,9 @@ private:
memset(m_pyload_mbuf_ptr+len+m_new_pkt_size,0xa,(-m_new_pkt_size));
}
+ return (0);
}
+
public:
int16_t m_new_pkt_size; /* New packet size after transform by plugin */
CFlowPktInfo * m_pkt_info;
@@ -302,7 +304,7 @@ public:
void CVirtualIFPerSideStats::Dump(FILE *fd){
- #define DP_B(f) if (f) printf(" %-40s : %llu \n",#f,f)
+ #define DP_B(f) if (f) printf(" %-40s : %lu \n",#f,f)
DP_B(m_tx_pkt);
DP_B(m_tx_rx_check_pkt);
DP_B(m_tx_bytes);
@@ -688,6 +690,15 @@ public:
RUN_FLAGS_RXCHECK_CONST_TS =1,
};
+ /**
+ * different running modes for Trex
+ */
+ enum trex_run_mode_e {
+ RUN_MODE_INVALID,
+ RUN_MODE_BATCH,
+ RUN_MODE_INTERACTIVE
+ };
+
public:
CParserOption(){
m_factor=1.0;
@@ -707,6 +718,7 @@ public:
m_run_flags=0;
prefix="";
m_mac_splitter=0;
+ m_run_mode = RUN_MODE_INVALID;
}
CPreviewMode preview;
@@ -730,13 +742,14 @@ public:
uint8_t m_mac_splitter;
uint8_t m_pad;
+ trex_run_mode_e m_run_mode;
- std::string cfg_file;
- std::string mac_file;
- std::string platform_cfg_file;
+ std::string cfg_file;
+ std::string mac_file;
+ std::string platform_cfg_file;
- std::string out_file;
- std::string prefix;
+ std::string out_file;
+ std::string prefix;
CMacAddrCfg m_mac_addr[MAX_LATENCY_PORTS];
@@ -1429,7 +1442,7 @@ public:
inline bool is_eligible_from_server_side(){
- return ( (m_src_ip&1==1)?true:false);
+ return ( ( (m_src_ip&1) == 1)?true:false);
}
@@ -1636,7 +1649,7 @@ public:
*/
inline int check_objects_sizes(void){
if ( sizeof(CGenNodeDeferPort) != sizeof(CGenNode) ) {
- printf("ERROR sizeof(CGenNodeDeferPort) %d != sizeof(CGenNode) %d must be the same size \n",sizeof(CGenNodeDeferPort),sizeof(CGenNode));
+ printf("ERROR sizeof(CGenNodeDeferPort) %lu != sizeof(CGenNode) %lu must be the same size \n",sizeof(CGenNodeDeferPort),sizeof(CGenNode));
assert(0);
}
if ( (int)offsetof(struct CGenNodeDeferPort,m_type)!=offsetof(struct CGenNode,m_type) ){
@@ -2576,6 +2589,8 @@ inline void CFlowPktInfo::update_pkt_info2(char *p,
EthernetHeader * et =
(EthernetHeader * )(p + m_pkt_indication.getFastEtherOffset());
+ (void)et;
+
if ( unlikely (m_pkt_indication.is_ipv6())) {
IPv6Header *ipv6= (IPv6Header *)ipv4;
@@ -2658,6 +2673,8 @@ inline void CFlowPktInfo::update_pkt_info(char *p,
EthernetHeader * et =
(EthernetHeader * )(p + m_pkt_indication.getFastEtherOffset());
+ (void)et;
+
uint16_t src_port = node->m_src_port;
pkt_dir_t ip_dir = node->cur_pkt_ip_addr_dir();
@@ -2858,6 +2875,7 @@ inline rte_mbuf_t * CFlowPktInfo::do_generate_new_mbuf_ex_vm(CGenNode * node,
/* need to update the mbuf size here .., this is not must but needed for accuracy */
uint16_t buf_adjust = len - vm.m_new_pkt_size;
int rc = rte_pktmbuf_trim(m, buf_adjust);
+ (void)rc;
/* update IP length , and TCP checksum , we can accelerate this using hardware ! */
uint16_t pkt_adjust = vm.m_new_pkt_size - m_packet->pkt_len;
diff --git a/src/gtest/rpc_test.cpp b/src/gtest/rpc_test.cpp
index 38d34320..250d5342 100644
--- a/src/gtest/rpc_test.cpp
+++ b/src/gtest/rpc_test.cpp
@@ -42,11 +42,6 @@ protected:
m_verbose = false;
- TrexRpcServerConfig cfg = TrexRpcServerConfig(TrexRpcServerConfig::RPC_PROT_TCP, 5050);
-
- m_rpc = new TrexRpcServer(cfg);
- m_rpc->start();
-
m_context = zmq_ctx_new ();
m_socket = zmq_socket (m_context, ZMQ_REQ);
zmq_connect (m_socket, "tcp://localhost:5050");
@@ -54,9 +49,6 @@ protected:
}
virtual void TearDown() {
- m_rpc->stop();
-
- delete m_rpc;
zmq_close(m_socket);
zmq_term(m_context);
}
@@ -657,3 +649,4 @@ TEST_F(RpcTestOwned, start_stop_traffic) {
send_request(request, response);
EXPECT_EQ(response["result"], "ACK");
}
+
diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp
index 0d03a207..a0af9fdf 100755
--- a/src/main_dpdk.cpp
+++ b/src/main_dpdk.cpp
@@ -55,6 +55,7 @@ limitations under the License.
#include <common/arg/SimpleGlob.h>
#include <common/arg/SimpleOpt.h>
#include <common/basic_utils.h>
+#include <stateless/cp/trex_stateless.h>
#include <../linux_dpdk/version.h>
extern "C" {
@@ -426,7 +427,8 @@ static char global_loglevel_str[20];
// cores =0==1,1*2,2,3,4,5,6
// An enum for all the option types
enum { OPT_HELP,
- OPT_CFG,
+ OPT_MODE_BATCH,
+ OPT_MODE_INTERACTIVE,
OPT_NODE_DUMP,
OPT_UT,
OPT_FILE_OUT,
@@ -478,15 +480,16 @@ enum { OPT_HELP,
*/
static CSimpleOpt::SOption parser_options[] =
{
- { OPT_HELP, "-?", SO_NONE },
- { OPT_HELP, "-h", SO_NONE },
- { OPT_HELP, "--help", SO_NONE },
- { OPT_UT, "--ut", SO_NONE },
- { OPT_CFG, "-f", SO_REQ_SEP},
- { OPT_PLAT_CFG_FILE,"--cfg", SO_REQ_SEP},
- { OPT_REAL_TIME , "-r", SO_NONE },
- { OPT_SINGLE_CORE , "-s", SO_NONE },
- { OPT_FILE_OUT , "-o" , SO_REQ_SEP},
+ { OPT_HELP, "-?", SO_NONE },
+ { OPT_HELP, "-h", SO_NONE },
+ { OPT_HELP, "--help", SO_NONE },
+ { OPT_UT, "--ut", SO_NONE },
+ { OPT_MODE_BATCH, "-f", SO_REQ_SEP},
+ { OPT_MODE_INTERACTIVE, "-i", SO_NONE },
+ { OPT_PLAT_CFG_FILE, "--cfg", SO_REQ_SEP},
+ { OPT_REAL_TIME , "-r", SO_NONE },
+ { OPT_SINGLE_CORE, "-s", SO_NONE },
+ { OPT_FILE_OUT, "-o" , SO_REQ_SEP},
{ OPT_FLIP_CLIENT_SERVER,"--flip",SO_NONE },
{ OPT_FLOW_FLIP_CLIENT_SERVER,"-p",SO_NONE },
{ OPT_FLOW_FLIP_CLIENT_SERVER_SIDE,"-e",SO_NONE },
@@ -533,13 +536,18 @@ static CSimpleOpt::SOption parser_options[] =
static int usage(){
- printf(" Usage: t-rex-64 [OPTION] -f cfg.yaml -c cores \n");
+ printf(" Usage: t-rex-64 [MODE] [OPTION] -f cfg.yaml -c cores \n");
printf(" \n");
printf(" \n");
- printf(" options \n");
+
+ printf(" mode \n\n");
printf(" -f [file] : YAML file with template configuration \n");
+ printf(" -i : launch TRex in interactive mode (RPC server)\n");
printf(" \n\n");
- printf(" --mac [file] : YAML file with <client ip, mac addr> configuration \n");
+
+ printf(" options \n\n");
+
+ printf(" --mac [file] : YAML file with <client ip, mac addr> configuration \n");
printf(" \n\n");
printf(" -r : realtime enable \n");
printf(" \n\n");
@@ -612,7 +620,8 @@ static int usage(){
printf(" --mac-spread : Spread the destination mac-order by this factor. e.g 2 will generate the traffic to 2 devices DEST-MAC ,DEST-MAC+1 \n");
printf(" maximum is up to 128 devices \n");
- printf(" simulation mode : \n");
+
+ printf("\n simulation mode : \n");
printf(" Using this mode you can generate the traffic into a pcap file and learn how trex works \n");
printf(" With this version you must be SUDO to use this mode ( I know this is not normal ) \n");
printf(" you can use the Linux CEL version of t-rex to do it without super user \n");
@@ -653,6 +662,7 @@ static int usage(){
printf(" Open Source Components / Libraries \n");
printf(" DPDK (BSD) \n");
printf(" YAML-CPP (BSD) \n");
+ printf(" JSONCPP (MIT) \n");
printf(" \n");
printf(" Open Source Binaries \n");
printf(" ZMQ (LGPL v3plus) \n");
@@ -667,6 +677,11 @@ static int usage(){
int gtest_main(int argc, char **argv) ;
+static void parse_err(const std::string &msg) {
+ std::cout << "\nArgument Parsing Error: \n\n" << "*** "<< msg << "\n\n";
+ exit(-1);
+}
+
static int parse_options(int argc, char *argv[], CParserOption* po, bool first_time ) {
CSimpleOpt args(argc, argv, parser_options);
@@ -679,36 +694,55 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t
int res1;
uint32_t tmp_data;
+ po->m_run_mode = CParserOption::RUN_MODE_INVALID;
while ( args.Next() ){
if (args.LastError() == SO_SUCCESS) {
switch (args.OptionId()) {
+
case OPT_UT :
- printf(" Supported only in simulation \n");
- res1=0;
- exit(res1);
+ parse_err("Supported only in simulation");
break;
+
case OPT_HELP:
usage();
return -1;
- case OPT_CFG:
+
+ case OPT_MODE_BATCH:
+ if (po->m_run_mode != CParserOption::RUN_MODE_INVALID) {
+ parse_err("Please specify single run mode");
+ }
+ po->m_run_mode = CParserOption::RUN_MODE_BATCH;
po->cfg_file = args.OptionArg();
break;
+
+ case OPT_MODE_INTERACTIVE:
+ if (po->m_run_mode != CParserOption::RUN_MODE_INVALID) {
+ parse_err("Please specify single run mode");
+ }
+ po->m_run_mode = CParserOption::RUN_MODE_INTERACTIVE;
+ break;
+
case OPT_NO_KEYBOARD_INPUT :
po->preview.set_no_keyboard(true);
break;
+
case OPT_MAC_FILE :
po->mac_file = args.OptionArg();
break;
+
case OPT_PLAT_CFG_FILE :
po->platform_cfg_file = args.OptionArg();
break;
+
case OPT_SINGLE_CORE :
po->preview.setSingleCore(true);
break;
+
case OPT_IPV6:
po->preview.set_ipv6_mode_enable(true);
break;
+
case OPT_VLAN:
po->preview.set_vlan_mode_enable(true);
break;
@@ -726,6 +760,7 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t
printf(" warning -r is deprecated, real time is not needed any more , it is the default \n");
po->preview.setRealTime(true);
break;
+
case OPT_NO_FLOW_CONTROL:
po->preview.set_disable_flow_control_setting(true);
break;
@@ -832,21 +867,20 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t
} // End of while
- if ((po->cfg_file =="") ) {
- printf("Invalid combination of parameters you must add -f with configuration file \n");
- return -1;
+ if ((po->m_run_mode == CParserOption::RUN_MODE_INVALID) ) {
+ parse_err("Please provide single run mode (e.g. batch or interactive)");
}
if ( po->m_mac_splitter > 128 ){
- printf("maximum mac spreading is 128 you set it to %d \n",po->m_mac_splitter);
- return -1;
+ std::stringstream ss;
+ ss << "maximum mac spreading is 128 you set it to: " << po->m_mac_splitter;
+ parse_err(ss.str());
}
if ( po->preview.get_learn_mode_enable() ){
if ( po->preview.get_ipv6_mode_enable() ){
- printf("--learn mode is not supported with --ipv6, beacuse there is not such thing NAT66 ( ipv6-ipv6) \n");
- printf("if you think it is important,open a defect \n");
- return -1;
+ parse_err("--learn mode is not supported with --ipv6, beacuse there is not such thing NAT66 ( ipv6-ipv6) \n" \
+ "if you think it is important,open a defect \n");
}
if ( po->is_latency_disabled() ){
/* set latency thread */
@@ -2701,7 +2735,7 @@ public:
}
public:
- bool Create();
+ bool Create(bool is_stateless);
void Delete();
int ixgbe_prob_init();
@@ -3375,18 +3409,22 @@ int CGlobalPortCfg::ixgbe_start(void){
}
-bool CGlobalPortCfg::Create(){
-
- if ( !m_zmq_publisher.Create( CGlobalInfo::m_options.m_zmq_port,
- !CGlobalInfo::m_options.preview.get_zmq_publish_enable() ) ){
- return (false);
- }
+bool CGlobalPortCfg::Create(bool is_stateless){
+ /* hack - need to refactor */
+ if (!is_stateless) {
+ if ( !m_zmq_publisher.Create( CGlobalInfo::m_options.m_zmq_port,
+ !CGlobalInfo::m_options.preview.get_zmq_publish_enable() ) ){
+ return (false);
+ }
+ }
/* We load the YAML twice,
this is the first time. to update global flags */
CFlowsYamlInfo pre_yaml_info;
- pre_yaml_info.load_from_yaml_file(CGlobalInfo::m_options.cfg_file);
+ if (!is_stateless) {
+ pre_yaml_info.load_from_yaml_file(CGlobalInfo::m_options.cfg_file);
+ }
if ( pre_yaml_info.m_vlan_info.m_enable ){
CGlobalInfo::m_options.preview.set_vlan_mode_enable(true);
@@ -3863,6 +3901,7 @@ int CGlobalPortCfg::run_in_master(){
std::string json;
bool was_stopped=false;
+
while ( true ) {
if ( CGlobalInfo::m_options.preview.get_no_keyboard() ==false ){
@@ -3976,6 +4015,7 @@ int CGlobalPortCfg::run_in_master(){
break;
}
}
+
m_mg.stop();
delay(1000);
if ( was_stopped ){
@@ -4172,7 +4212,18 @@ static int latency_one_lcore(__attribute__((unused)) void *dummy)
}
+static int stateless_entry(__attribute__((unused)) void *dummy) {
+ CPlatformSocketInfo * lpsock=&CGlobalInfo::m_socket;
+ physical_thread_id_t phy_id = rte_lcore_id();
+
+ if (lpsock->thread_phy_is_master( phy_id )) {
+ TrexStateless::get_instance().launch_control_plane();
+ } else {
+ TrexStateless::get_instance().launch_on_dp_core(phy_id);
+ }
+ return (0);
+}
static int slave_one_lcore(__attribute__((unused)) void *dummy)
{
@@ -4381,7 +4432,37 @@ int sim_load_list_of_cap_files(CParserOption * op){
+static int
+launch_stateless_trex() {
+ CPlatformSocketInfo *lpsock=&CGlobalInfo::m_socket;
+ CParserOption *lpop= &CGlobalInfo::m_options;
+ CPlatformYamlInfo *cg=&global_platform_cfg_info;
+
+ TrexStatelessCfg cfg;
+
+ TrexRpcServerConfig rpc_req_resp_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5050);
+ TrexRpcServerConfig rpc_async_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5051);
+ cfg.m_dp_core_count = lpop->preview.getCores();
+ cfg.m_port_count = lpop->m_expected_portd;
+ cfg.m_rpc_req_resp_cfg = &rpc_req_resp_cfg;
+ cfg.m_rpc_async_cfg = &rpc_async_cfg;
+ cfg.m_rpc_server_verbose = true;
+
+ TrexStateless::configure(cfg);
+
+ printf("\nStarting T-Rex Stateless\n");
+ printf("Starting RPC Server...\n\n");
+
+ rte_eal_mp_remote_launch(stateless_entry, NULL, CALL_MASTER);
+
+ unsigned lcore_id;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (rte_eal_wait_lcore(lcore_id) < 0)
+ return -1;
+ }
+ return (0);
+}
@@ -4436,7 +4517,6 @@ int main_test(int argc , char * argv[]){
rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
}
-
time_init();
/* check if we are in simulation mode */
@@ -4445,11 +4525,18 @@ int main_test(int argc , char * argv[]){
return ( sim_load_list_of_cap_files(&CGlobalInfo::m_options) );
}
+ bool is_stateless = (CGlobalInfo::m_options.m_run_mode == CParserOption::RUN_MODE_INTERACTIVE);
- if ( !ports_cfg.Create() ){
+ if ( !ports_cfg.Create(is_stateless) ){
exit(1);
}
+ /* patch here */
+ if (is_stateless) {
+ return launch_stateless_trex();
+ }
+
+
if (po->preview.get_is_rx_check_enable() && (po->m_rx_check_sampe< get_min_sample_rate()) ) {
po->m_rx_check_sampe = get_min_sample_rate();
printf("Warning rx check sample rate should be lower than %d setting it to %d\n",get_min_sample_rate(),get_min_sample_rate());
@@ -4518,6 +4605,7 @@ int main_test(int argc , char * argv[]){
if (rte_eal_wait_lcore(lcore_id) < 0)
return -1;
}
+
ports_cfg.stop_master();
ports_cfg.Delete();
utl_termio_reset();
diff --git a/src/mock/rte_ethdev.h b/src/mock/rte_ethdev.h
new file mode 100644
index 00000000..046d8366
--- /dev/null
+++ b/src/mock/rte_ethdev.h
@@ -0,0 +1,44 @@
+/*
+ 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 __MOCK_FILE_RTE_ETHDEV_H__
+#define __MOCK_FILE_RTE_ETHDEV_H__
+
+#include <string.h>
+
+struct rte_eth_stats {
+ uint64_t obytes;
+ uint64_t ibytes;
+ uint64_t opackets;
+ uint64_t ipackets;
+};
+
+static inline void
+rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats) {
+ memset(stats, 0, sizeof(rte_eth_stats));
+}
+
+static inline uint16_t
+rte_eth_tx_burst(uint8_t port_id, uint16_t queue_id,
+ struct rte_mbuf **tx_pkts, uint16_t nb_pkts) {
+ return (0);
+}
+
+#endif /* __MOCK_FILE_RTE_ETHDEV_H__ */
diff --git a/src/rpc-server/trex_rpc_server_mock.cpp b/src/mock/trex_rpc_server_mock.cpp
index 835e28b8..de43f92f 100644
--- a/src/rpc-server/trex_rpc_server_mock.cpp
+++ b/src/mock/trex_rpc_server_mock.cpp
@@ -20,7 +20,7 @@ limitations under the License.
*/
#include <trex_rpc_server_api.h>
-#include <trex_stateless_api.h>
+#include <trex_stateless.h>
#include <iostream>
#include <unistd.h>
@@ -44,29 +44,42 @@ int gtest_main(int argc, char **argv);
int main(int argc, char *argv[]) {
- /* configure the stateless object with 4 ports */
- TrexStateless::configure(4);
+ bool is_gtest = false;
- // gtest ?
+ // gtest ?
if (argc > 1) {
if (string(argv[1]) != "--ut") {
cout << "\n[Usage] " << argv[0] << ": " << " [--ut]\n\n";
exit(-1);
}
- return gtest_main(argc, argv);
+ is_gtest = true;
}
- cout << "\n-= Starting RPC Server Mock =-\n\n";
- cout << "Listening on tcp://localhost:5050 [ZMQ]\n\n";
+ /* configure the stateless object with 4 ports */
+ TrexStatelessCfg cfg;
- TrexRpcServerConfig rpc_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5050);
- TrexRpcServer rpc(rpc_cfg);
+ TrexRpcServerConfig rpc_req_resp_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5050);
+ TrexRpcServerConfig rpc_async_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5051);
- /* init the RPC server */
- rpc.start();
+ cfg.m_port_count = 4;
+ cfg.m_dp_core_count = 2;
+ cfg.m_rpc_req_resp_cfg = &rpc_req_resp_cfg;
+ cfg.m_rpc_async_cfg = &rpc_async_cfg;
+ cfg.m_rpc_server_verbose = (is_gtest ? false : true);
- cout << "Setting Server To Full Verbose\n\n";
- rpc.set_verbose(true);
+ TrexStateless::configure(cfg);
+
+ TrexStateless::get_instance().launch_control_plane();
+
+ /* gtest handling */
+ if (is_gtest) {
+ int rc = gtest_main(argc, argv);
+ TrexStateless::destroy();
+ return rc;
+ }
+
+ cout << "\n-= Starting RPC Server Mock =-\n\n";
+ cout << "Listening on tcp://localhost:5050 [ZMQ]\n\n";
cout << "Server Started\n\n";
@@ -74,7 +87,6 @@ int main(int argc, char *argv[]) {
sleep(1);
}
- rpc.stop();
-
-
+ TrexStateless::destroy();
}
+
diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
index 0c9f2c49..ae87d749 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
@@ -21,7 +21,8 @@ limitations under the License.
#include "trex_rpc_cmds.h"
#include <trex_rpc_server_api.h>
-#include <trex_stateless_api.h>
+#include <trex_stateless.h>
+#include <trex_stateless_port.h>
#include <trex_rpc_cmds_table.h>
#include <fstream>
@@ -154,7 +155,7 @@ TrexRpcCmdGetSysInfo::_run(const Json::Value &params, Json::Value &result) {
section["uptime"] = TrexRpcServer::get_server_uptime();
/* FIXME: core count */
- section["dp_core_count"] = 1;
+ section["dp_core_count"] = instance.get_dp_core_count();
section["core_type"] = get_cpu_model();
/* ports */
@@ -271,17 +272,7 @@ TrexRpcCmdGetPortStats::_run(const Json::Value &params, Json::Value &result) {
result["result"]["status"] = port->get_state_as_string();
- result["result"]["tx_bps"] = Json::Value::UInt64(port->get_port_stats().tx_bps);
- result["result"]["tx_pps"] = Json::Value::UInt64(port->get_port_stats().tx_pps);
- result["result"]["total_tx_pkts"] = Json::Value::UInt64(port->get_port_stats().total_tx_pkts);
- result["result"]["total_tx_bytes"] = Json::Value::UInt64(port->get_port_stats().total_tx_bytes);
-
- result["result"]["rx_bps"] = Json::Value::UInt64(port->get_port_stats().rx_bps);
- result["result"]["rx_pps"] = Json::Value::UInt64(port->get_port_stats().rx_pps);
- result["result"]["total_rx_pkts"] = Json::Value::UInt64(port->get_port_stats().total_rx_pkts);
- result["result"]["total_rx_bytes"] = Json::Value::UInt64(port->get_port_stats().total_rx_bytes);
-
- result["result"]["tx_rx_error"] = Json::Value::UInt64(port->get_port_stats().tx_rx_errors);
+ port->encode_stats(result["result"]);
return (TREX_RPC_CMD_OK);
}
diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
index 1450e1a9..812d819e 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
@@ -20,8 +20,9 @@ limitations under the License.
*/
#include "trex_rpc_cmds.h"
#include <trex_rpc_server_api.h>
-#include <trex_stream_api.h>
-#include <trex_stateless_api.h>
+#include <trex_stream.h>
+#include <trex_stateless.h>
+#include <trex_stateless_port.h>
#include <iostream>
diff --git a/src/rpc-server/trex_rpc_async_server.cpp b/src/rpc-server/trex_rpc_async_server.cpp
new file mode 100644
index 00000000..f4d21f2f
--- /dev/null
+++ b/src/rpc-server/trex_rpc_async_server.cpp
@@ -0,0 +1,109 @@
+/*
+ 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.
+*/
+
+/* required for sleep_for c++ 2011
+ https://bugs.launchpad.net/ubuntu/+source/gcc-4.4/+bug/608145
+*/
+#define _GLIBCXX_USE_NANOSLEEP
+
+#include <trex_stateless.h>
+#include <trex_stateless_port.h>
+#include <trex_rpc_async_server.h>
+#include <zmq.h>
+#include <json/json.h>
+#include <string>
+#include <iostream>
+
+/**
+ * ZMQ based publisher server
+ *
+ */
+TrexRpcServerAsync::TrexRpcServerAsync(const TrexRpcServerConfig &cfg, std::mutex *lock) : TrexRpcServerInterface(cfg, "publisher", lock) {
+ /* ZMQ is not thread safe - this should be outside */
+ m_context = zmq_ctx_new();
+}
+
+/**
+ * publisher thread
+ *
+ */
+void
+TrexRpcServerAsync::_rpc_thread_cb() {
+ std::stringstream ss;
+
+ /* create a socket based on the configuration */
+ m_socket = zmq_socket (m_context, ZMQ_PUB);
+
+ switch (m_cfg.get_protocol()) {
+ case TrexRpcServerConfig::RPC_PROT_TCP:
+ ss << "tcp://*:";
+ break;
+ default:
+ throw TrexRpcException("unknown protocol for RPC");
+ }
+
+ ss << m_cfg.get_port();
+
+ /* bind the scoket */
+ int rc = zmq_bind (m_socket, ss.str().c_str());
+ if (rc != 0) {
+ throw TrexRpcException("Unable to start ZMQ server at: " + ss.str());
+ }
+
+ /* while the server is running - publish results */
+ while (m_is_running) {
+ Json::Value snapshot;
+ Json::FastWriter writer;
+
+ /* if lock was provided - take it */
+ if (m_lock) {
+ m_lock->lock();
+ }
+
+ /* trigger a full update for stats */
+ TrexStateless::get_instance().update_stats();
+
+ /* done with the lock */
+ if (m_lock) {
+ m_lock->unlock();
+ }
+
+ /* encode them to JSON */
+ TrexStateless::get_instance().encode_stats(snapshot);
+
+ /* write to string and publish */
+ std::string snapshot_str = writer.write(snapshot);
+
+ zmq_send(m_socket, snapshot_str.c_str(), snapshot_str.size(), 0);
+ //std::cout << "sending " << snapshot_str << "\n";
+
+ /* relax for some time */
+ std::this_thread::sleep_for (std::chrono::milliseconds(1000));
+ }
+
+ /* must be closed from the same thread */
+ zmq_close(m_socket);
+}
+
+void
+TrexRpcServerAsync::_stop_rpc_thread() {
+ zmq_term(m_context);
+}
diff --git a/src/rpc-server/trex_rpc_async_server.h b/src/rpc-server/trex_rpc_async_server.h
new file mode 100644
index 00000000..02d1490e
--- /dev/null
+++ b/src/rpc-server/trex_rpc_async_server.h
@@ -0,0 +1,54 @@
+/*
+ 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_RPC_ASYNC_SERVER_H__
+#define __TREX_RPC_ASYNC_SERVER_H__
+
+#include <trex_rpc_server_api.h>
+#include <trex_stateless_port.h>
+
+/**
+ * async RPC server
+ *
+ * @author imarom (11-Aug-15)
+ */
+class TrexRpcServerAsync : public TrexRpcServerInterface {
+public:
+
+ TrexRpcServerAsync(const TrexRpcServerConfig &cfg, std::mutex *lock = NULL);
+
+protected:
+ void _rpc_thread_cb();
+ void _stop_rpc_thread();
+
+private:
+
+ void handle_server_error(const std::string &specific_err);
+
+ static const int RPC_MAX_MSG_SIZE = (20 * 1024);
+ void *m_context;
+ void *m_socket;
+ uint8_t m_msg_buffer[RPC_MAX_MSG_SIZE];
+};
+
+
+#endif /* __TREX_RPC_ASYNC_SERVER_H__ */
+
diff --git a/src/rpc-server/trex_rpc_cmd.cpp b/src/rpc-server/trex_rpc_cmd.cpp
index 6c355e70..920a8d30 100644
--- a/src/rpc-server/trex_rpc_cmd.cpp
+++ b/src/rpc-server/trex_rpc_cmd.cpp
@@ -20,7 +20,8 @@ limitations under the License.
*/
#include <trex_rpc_cmd_api.h>
#include <trex_rpc_server_api.h>
-#include <trex_stateless_api.h>
+#include <trex_stateless.h>
+#include <trex_stateless_port.h>
trex_rpc_cmd_rc_e
TrexRpcCommand::run(const Json::Value &params, Json::Value &result) {
diff --git a/src/rpc-server/trex_rpc_req_resp_server.cpp b/src/rpc-server/trex_rpc_req_resp_server.cpp
index 3d52686c..9147f75d 100644
--- a/src/rpc-server/trex_rpc_req_resp_server.cpp
+++ b/src/rpc-server/trex_rpc_req_resp_server.cpp
@@ -34,7 +34,7 @@ limitations under the License.
* ZMQ based request-response server
*
*/
-TrexRpcServerReqRes::TrexRpcServerReqRes(const TrexRpcServerConfig &cfg) : TrexRpcServerInterface(cfg, "req resp") {
+TrexRpcServerReqRes::TrexRpcServerReqRes(const TrexRpcServerConfig &cfg, std::mutex *lock) : TrexRpcServerInterface(cfg, "req resp", lock) {
/* ZMQ is not thread safe - this should be outside */
m_context = zmq_ctx_new();
}
@@ -127,6 +127,11 @@ void TrexRpcServerReqRes::handle_request(const std::string &request) {
int index = 0;
+ /* if lock was provided, take it */
+ if (m_lock) {
+ m_lock->lock();
+ }
+
/* for every command parsed - launch it */
for (auto command : commands) {
Json::Value single_response;
@@ -138,6 +143,11 @@ void TrexRpcServerReqRes::handle_request(const std::string &request) {
}
+ /* done with the lock */
+ if (m_lock) {
+ m_lock->unlock();
+ }
+
/* write the JSON to string and sever on ZMQ */
std::string response_str;
diff --git a/src/rpc-server/trex_rpc_req_resp_server.h b/src/rpc-server/trex_rpc_req_resp_server.h
index 7c1d66d1..1f638adf 100644
--- a/src/rpc-server/trex_rpc_req_resp_server.h
+++ b/src/rpc-server/trex_rpc_req_resp_server.h
@@ -32,7 +32,7 @@ limitations under the License.
class TrexRpcServerReqRes : public TrexRpcServerInterface {
public:
- TrexRpcServerReqRes(const TrexRpcServerConfig &cfg);
+ TrexRpcServerReqRes(const TrexRpcServerConfig &cfg, std::mutex *lock = NULL);
protected:
void _rpc_thread_cb();
diff --git a/src/rpc-server/trex_rpc_server.cpp b/src/rpc-server/trex_rpc_server.cpp
index 6b8c200d..a14e6f97 100644
--- a/src/rpc-server/trex_rpc_server.cpp
+++ b/src/rpc-server/trex_rpc_server.cpp
@@ -21,6 +21,7 @@ limitations under the License.
#include <trex_rpc_server_api.h>
#include <trex_rpc_req_resp_server.h>
+#include <trex_rpc_async_server.h>
#include <trex_rpc_jsonrpc_v2_parser.h>
#include <unistd.h>
#include <zmq.h>
@@ -29,7 +30,7 @@ limitations under the License.
/************** RPC server interface ***************/
-TrexRpcServerInterface::TrexRpcServerInterface(const TrexRpcServerConfig &cfg, const std::string &name) : m_cfg(cfg), m_name(name) {
+TrexRpcServerInterface::TrexRpcServerInterface(const TrexRpcServerConfig &cfg, const std::string &name, std::mutex *lock) : m_cfg(cfg), m_name(name), m_lock(lock) {
m_is_running = false;
m_is_verbose = false;
}
@@ -112,10 +113,19 @@ get_current_date_time() {
const std::string TrexRpcServer::s_server_uptime = get_current_date_time();
-TrexRpcServer::TrexRpcServer(const TrexRpcServerConfig &req_resp_cfg) {
+TrexRpcServer::TrexRpcServer(const TrexRpcServerConfig *req_resp_cfg,
+ const TrexRpcServerConfig *async_cfg,
+ std::mutex *lock) {
/* add the request response server */
- m_servers.push_back(new TrexRpcServerReqRes(req_resp_cfg));
+ if (req_resp_cfg) {
+ m_servers.push_back(new TrexRpcServerReqRes(*req_resp_cfg, lock));
+ }
+
+ /* add async publisher */
+ if (async_cfg) {
+ m_servers.push_back(new TrexRpcServerAsync(*async_cfg, lock));
+ }
}
TrexRpcServer::~TrexRpcServer() {
diff --git a/src/rpc-server/trex_rpc_server_api.h b/src/rpc-server/trex_rpc_server_api.h
index 06bbe10c..ff876ac4 100644
--- a/src/rpc-server/trex_rpc_server_api.h
+++ b/src/rpc-server/trex_rpc_server_api.h
@@ -24,6 +24,7 @@ limitations under the License.
#include <stdint.h>
#include <vector>
+#include <mutex>
#include <thread>
#include <string>
#include <stdexcept>
@@ -68,7 +69,7 @@ private:
class TrexRpcServerInterface {
public:
- TrexRpcServerInterface(const TrexRpcServerConfig &cfg, const std::string &name);
+ TrexRpcServerInterface(const TrexRpcServerConfig &cfg, const std::string &name, std::mutex *m_lock = NULL);
virtual ~TrexRpcServerInterface();
/**
@@ -127,6 +128,7 @@ protected:
bool m_is_verbose;
std::thread *m_thread;
std::string m_name;
+ std::mutex *m_lock;
};
/**
@@ -139,8 +141,11 @@ protected:
class TrexRpcServer {
public:
- /* currently only request response server config is required */
- TrexRpcServer(const TrexRpcServerConfig &req_resp_cfg);
+ /* creates the collection of servers using configurations */
+ TrexRpcServer(const TrexRpcServerConfig *req_resp_cfg,
+ const TrexRpcServerConfig *async_cfg,
+ std::mutex *m_lock = NULL);
+
~TrexRpcServer();
/**
diff --git a/src/stateless/cp/trex_stateless.cpp b/src/stateless/cp/trex_stateless.cpp
new file mode 100644
index 00000000..72762e26
--- /dev/null
+++ b/src/stateless/cp/trex_stateless.cpp
@@ -0,0 +1,212 @@
+/*
+ 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.h>
+#include <trex_stateless_port.h>
+
+#include <sched.h>
+#include <iostream>
+#include <unistd.h>
+
+using namespace std;
+
+/***********************************************************
+ * Trex stateless object
+ *
+ **********************************************************/
+TrexStateless::TrexStateless() {
+ m_is_configured = false;
+}
+
+
+/**
+ * configure the singleton stateless object
+ *
+ */
+void TrexStateless::configure(const TrexStatelessCfg &cfg) {
+
+ TrexStateless& instance = get_instance_internal();
+
+ /* check status */
+ if (instance.m_is_configured) {
+ throw TrexException("re-configuration of stateless object is not allowed");
+ }
+
+ /* create RPC servers */
+
+ /* set both servers to mutex each other */
+ instance.m_rpc_server = new TrexRpcServer(cfg.m_rpc_req_resp_cfg, cfg.m_rpc_async_cfg, &instance.m_global_cp_lock);
+ instance.m_rpc_server->set_verbose(cfg.m_rpc_server_verbose);
+
+ /* configure ports */
+
+ instance.m_port_count = cfg.m_port_count;
+
+ for (int i = 0; i < instance.m_port_count; i++) {
+ instance.m_ports.push_back(new TrexStatelessPort(i));
+ }
+
+ /* cores */
+ instance.m_dp_core_count = cfg.m_dp_core_count;
+ for (int i = 0; i < instance.m_dp_core_count; i++) {
+ instance.m_dp_cores.push_back(new TrexStatelessDpCore(i));
+ }
+
+ /* done */
+ instance.m_is_configured = true;
+}
+
+/**
+ * starts the control plane side
+ *
+ */
+void
+TrexStateless::launch_control_plane() {
+ //std::cout << "\n on control/master core \n";
+
+ /* pin this process to the current running CPU
+ any new thread will be called on the same CPU
+ (control plane restriction)
+ */
+ cpu_set_t mask;
+ CPU_ZERO(&mask);
+ CPU_SET(sched_getcpu(), &mask);
+ sched_setaffinity(0, sizeof(mask), &mask);
+
+ /* start RPC server */
+ m_rpc_server->start();
+}
+
+void
+TrexStateless::launch_on_dp_core(uint8_t core_id) {
+ m_dp_cores[core_id - 1]->run();
+}
+
+/**
+ * destroy the singleton and release all memory
+ *
+ * @author imarom (08-Oct-15)
+ */
+void
+TrexStateless::destroy() {
+ TrexStateless& instance = get_instance_internal();
+
+ if (!instance.m_is_configured) {
+ return;
+ }
+
+ /* release memory for ports */
+ for (auto port : instance.m_ports) {
+ delete port;
+ }
+ instance.m_ports.clear();
+
+ /* stops the RPC server */
+ instance.m_rpc_server->stop();
+ delete instance.m_rpc_server;
+
+ instance.m_rpc_server = NULL;
+
+ /* done */
+ instance.m_is_configured = false;
+}
+
+/**
+ * fetch a port by ID
+ *
+ */
+TrexStatelessPort * TrexStateless::get_port_by_id(uint8_t port_id) {
+ if (port_id >= m_port_count) {
+ throw TrexException("index out of range");
+ }
+
+ return m_ports[port_id];
+
+}
+
+uint8_t
+TrexStateless::get_port_count() {
+ return m_port_count;
+}
+
+uint8_t
+TrexStateless::get_dp_core_count() {
+ return m_dp_core_count;
+}
+
+void
+TrexStateless::update_stats() {
+
+ /* update CPU util.
+ TODO
+ */
+ m_stats.m_stats.m_cpu_util = 0;
+
+ /* for every port update and accumulate */
+ for (uint8_t i = 0; i < m_port_count; i++) {
+ m_ports[i]->update_stats();
+
+ const TrexPortStats & port_stats = m_ports[i]->get_stats();
+
+ m_stats.m_stats.m_tx_bps += port_stats.m_stats.m_tx_bps;
+ m_stats.m_stats.m_rx_bps += port_stats.m_stats.m_rx_bps;
+
+ m_stats.m_stats.m_tx_pps += port_stats.m_stats.m_tx_pps;
+ m_stats.m_stats.m_rx_pps += port_stats.m_stats.m_rx_pps;
+
+ m_stats.m_stats.m_total_tx_pkts += port_stats.m_stats.m_total_tx_pkts;
+ m_stats.m_stats.m_total_rx_pkts += port_stats.m_stats.m_total_rx_pkts;
+
+ m_stats.m_stats.m_total_tx_bytes += port_stats.m_stats.m_total_tx_bytes;
+ m_stats.m_stats.m_total_rx_bytes += port_stats.m_stats.m_total_rx_bytes;
+
+ m_stats.m_stats.m_tx_rx_errors += port_stats.m_stats.m_tx_rx_errors;
+ }
+}
+
+void
+TrexStateless::encode_stats(Json::Value &global) {
+
+ global["cpu_util"] = m_stats.m_stats.m_cpu_util;
+
+ global["tx_bps"] = m_stats.m_stats.m_tx_bps;
+ global["rx_bps"] = m_stats.m_stats.m_rx_bps;
+
+ global["tx_pps"] = m_stats.m_stats.m_tx_pps;
+ global["rx_pps"] = m_stats.m_stats.m_rx_pps;
+
+ global["total_tx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_pkts);
+ global["total_rx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_pkts);
+
+ global["total_tx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_bytes);
+ global["total_rx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_bytes);
+
+ global["tx_rx_errors"] = Json::Value::UInt64(m_stats.m_stats.m_tx_rx_errors);
+
+ for (uint8_t i = 0; i < m_port_count; i++) {
+ std::stringstream ss;
+
+ ss << "port " << i;
+ Json::Value &port_section = global[ss.str()];
+
+ m_ports[i]->encode_stats(port_section);
+ }
+}
+
diff --git a/src/stateless/cp/trex_stateless.h b/src/stateless/cp/trex_stateless.h
new file mode 100644
index 00000000..649b25dd
--- /dev/null
+++ b/src/stateless/cp/trex_stateless.h
@@ -0,0 +1,202 @@
+/*
+ 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_H__
+#define __TREX_STATELESS_H__
+
+#include <stdint.h>
+#include <string>
+#include <stdexcept>
+
+#include <mutex>
+
+#include <trex_stream.h>
+#include <trex_stateless_port.h>
+#include <trex_stateless_dp_core.h>
+#include <trex_rpc_server_api.h>
+
+/**
+ * generic exception for errors
+ * TODO: move this to a better place
+ */
+class TrexException : public std::runtime_error
+{
+public:
+ TrexException() : std::runtime_error("") {
+
+ }
+ TrexException(const std::string &what) : std::runtime_error(what) {
+ }
+};
+
+class TrexStatelessPort;
+
+/**
+ * unified stats
+ *
+ * @author imarom (06-Oct-15)
+ */
+class TrexStatelessStats {
+public:
+ TrexStatelessStats() {
+ m_stats = {0};
+ }
+
+ struct {
+ double m_cpu_util;
+
+ double m_tx_bps;
+ double m_rx_bps;
+
+ double m_tx_pps;
+ double m_rx_pps;
+
+ uint64_t m_total_tx_pkts;
+ uint64_t m_total_rx_pkts;
+
+ uint64_t m_total_tx_bytes;
+ uint64_t m_total_rx_bytes;
+
+ uint64_t m_tx_rx_errors;
+ } m_stats;
+};
+
+/**
+ * config object for stateless object
+ *
+ * @author imarom (08-Oct-15)
+ */
+class TrexStatelessCfg {
+public:
+ /* default values */
+ TrexStatelessCfg() {
+ m_port_count = 0;
+ m_dp_core_count = 0;
+ m_rpc_req_resp_cfg = NULL;
+ m_rpc_async_cfg = NULL;
+ m_rpc_server_verbose = false;
+ }
+
+ const TrexRpcServerConfig *m_rpc_req_resp_cfg;
+ const TrexRpcServerConfig *m_rpc_async_cfg;
+ bool m_rpc_server_verbose;
+ uint8_t m_port_count;
+ uint8_t m_dp_core_count;
+};
+
+/**
+ * defines the T-Rex stateless operation mode
+ *
+ */
+class TrexStateless {
+public:
+
+ /**
+ * configure the stateless object singelton
+ * reconfiguration is not allowed
+ * an exception will be thrown
+ */
+ static void configure(const TrexStatelessCfg &cfg);
+
+ /**
+ * destroy the instance
+ *
+ */
+ static void destroy();
+
+ /**
+ * singleton public get instance
+ *
+ */
+ static TrexStateless& get_instance() {
+ TrexStateless& instance = get_instance_internal();
+
+ if (!instance.m_is_configured) {
+ throw TrexException("object is not configured");
+ }
+
+ return instance;
+ }
+
+ /**
+ * starts the control plane side
+ *
+ */
+ void launch_control_plane();
+
+ /**
+ * launch on a single DP core
+ *
+ */
+ void launch_on_dp_core(uint8_t core_id);
+
+ TrexStatelessPort * get_port_by_id(uint8_t port_id);
+ uint8_t get_port_count();
+
+ uint8_t get_dp_core_count();
+
+ /**
+ * update all the stats (deep update)
+ * (include all the ports and global stats)
+ *
+ */
+ void update_stats();
+
+ /**
+ * fetch all the stats
+ *
+ */
+ void encode_stats(Json::Value &global);
+
+
+protected:
+ TrexStateless();
+
+ static TrexStateless& get_instance_internal () {
+ static TrexStateless instance;
+ return instance;
+ }
+
+ /* c++ 2011 style singleton */
+ TrexStateless(TrexStateless const&) = delete;
+ void operator=(TrexStateless const&) = delete;
+
+ /* status */
+ bool m_is_configured;
+
+ /* RPC server array */
+ TrexRpcServer *m_rpc_server;
+
+ /* ports */
+ std::vector <TrexStatelessPort *> m_ports;
+ uint8_t m_port_count;
+
+ /* cores */
+ std::vector <TrexStatelessDpCore *> m_dp_cores;
+ uint8_t m_dp_core_count;
+
+ /* stats */
+ TrexStatelessStats m_stats;
+
+ std::mutex m_global_cp_lock;
+};
+
+#endif /* __TREX_STATELESS_H__ */
+
diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp
new file mode 100644
index 00000000..f745bee9
--- /dev/null
+++ b/src/stateless/cp/trex_stateless_port.cpp
@@ -0,0 +1,226 @@
+/*
+ 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.h>
+#include <trex_stateless_port.h>
+#include <string>
+
+// DPDK c++ issue
+#define UINT8_MAX 255
+#define UINT16_MAX 0xFFFF
+// DPDK c++ issue
+
+#include <rte_ethdev.h>
+#include <os_time.h>
+
+using namespace std;
+
+/***************************
+ * trex stateless port
+ *
+ **************************/
+TrexStatelessPort::TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) {
+ m_port_state = PORT_STATE_UP_IDLE;
+ clear_owner();
+}
+
+
+/**
+ * starts the traffic on the port
+ *
+ */
+TrexStatelessPort::rc_e
+TrexStatelessPort::start_traffic(void) {
+
+ if (m_port_state != PORT_STATE_UP_IDLE) {
+ return (RC_ERR_BAD_STATE_FOR_OP);
+ }
+
+ if (get_stream_table()->size() == 0) {
+ return (RC_ERR_NO_STREAMS);
+ }
+
+ m_port_state = PORT_STATE_TRANSMITTING;
+
+ /* real code goes here */
+ return (RC_OK);
+}
+
+void
+TrexStatelessPort::stop_traffic(void) {
+
+ /* real code goes here */
+ if (m_port_state == PORT_STATE_TRANSMITTING) {
+ m_port_state = PORT_STATE_UP_IDLE;
+ }
+}
+
+/**
+* access the stream table
+*
+*/
+TrexStreamTable * TrexStatelessPort::get_stream_table() {
+ return &m_stream_table;
+}
+
+
+std::string
+TrexStatelessPort::get_state_as_string() {
+
+ switch (get_state()) {
+ case PORT_STATE_DOWN:
+ return "down";
+
+ case PORT_STATE_UP_IDLE:
+ return "idle";
+
+ case PORT_STATE_TRANSMITTING:
+ return "transmitting";
+ }
+
+ return "unknown";
+}
+
+void
+TrexStatelessPort::get_properties(string &driver, string &speed) {
+
+ /* take this from DPDK */
+ driver = "e1000";
+ speed = "1 Gbps";
+}
+
+
+/**
+ * generate a random connection handler
+ *
+ */
+std::string
+TrexStatelessPort::generate_handler() {
+ std::stringstream ss;
+
+ static const char alphanum[] =
+ "0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz";
+
+ /* generate 8 bytes of random handler */
+ for (int i = 0; i < 8; ++i) {
+ ss << alphanum[rand() % (sizeof(alphanum) - 1)];
+ }
+
+ return (ss.str());
+}
+
+/**
+ * update stats for the port
+ *
+ */
+void
+TrexStatelessPort::update_stats() {
+ struct rte_eth_stats stats;
+ rte_eth_stats_get(m_port_id, &stats);
+
+ /* copy straight values */
+ m_stats.m_stats.m_total_tx_bytes = stats.obytes;
+ m_stats.m_stats.m_total_rx_bytes = stats.ibytes;
+
+ m_stats.m_stats.m_total_tx_pkts = stats.opackets;
+ m_stats.m_stats.m_total_rx_pkts = stats.ipackets;
+
+ /* calculate stats */
+ m_stats.m_stats.m_tx_bps = m_stats.m_bw_tx_bps.add(stats.obytes);
+ m_stats.m_stats.m_rx_bps = m_stats.m_bw_rx_bps.add(stats.ibytes);
+
+ m_stats.m_stats.m_tx_pps = m_stats.m_bw_tx_pps.add(stats.opackets);
+ m_stats.m_stats.m_rx_pps = m_stats.m_bw_rx_pps.add(stats.ipackets);
+
+}
+
+const TrexPortStats &
+TrexStatelessPort::get_stats() {
+ return m_stats;
+}
+
+void
+TrexStatelessPort::encode_stats(Json::Value &port) {
+
+ port["tx_bps"] = m_stats.m_stats.m_tx_bps;
+ port["rx_bps"] = m_stats.m_stats.m_rx_bps;
+
+ port["tx_pps"] = m_stats.m_stats.m_tx_pps;
+ port["rx_pps"] = m_stats.m_stats.m_rx_pps;
+
+ port["total_tx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_pkts);
+ port["total_rx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_pkts);
+
+ port["total_tx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_bytes);
+ port["total_rx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_bytes);
+
+ port["tx_rx_errors"] = Json::Value::UInt64(m_stats.m_stats.m_tx_rx_errors);
+}
+
+
+
+/***************************
+ * BW measurement
+ *
+ **************************/
+/* TODO: move this to a common place */
+BWMeasure::BWMeasure() {
+ reset();
+}
+
+void BWMeasure::reset(void) {
+ m_start=false;
+ m_last_time_msec=0;
+ m_last_bytes=0;
+ m_last_result=0.0;
+};
+
+double BWMeasure::calc_MBsec(uint32_t dtime_msec,
+ uint64_t dbytes){
+ double rate=0.000008*( ( (double)dbytes*(double)os_get_time_freq())/((double)dtime_msec) );
+ return(rate);
+}
+
+double BWMeasure::add(uint64_t size) {
+ if ( false == m_start ) {
+ m_start=true;
+ m_last_time_msec = os_get_time_msec() ;
+ m_last_bytes=size;
+ return(0.0);
+ }
+
+ uint32_t ctime=os_get_time_msec();
+ if ((ctime - m_last_time_msec) <os_get_time_freq() ) {
+ return(m_last_result);
+ }
+
+ uint32_t dtime_msec = ctime-m_last_time_msec;
+ uint64_t dbytes = size - m_last_bytes;
+
+ m_last_time_msec = ctime;
+ m_last_bytes = size;
+
+ m_last_result= 0.5*calc_MBsec(dtime_msec,dbytes) +0.5*(m_last_result);
+ return( m_last_result );
+}
+
+
diff --git a/src/stateless/trex_stateless_api.h b/src/stateless/cp/trex_stateless_port.h
index 7a9080aa..428d5aee 100644
--- a/src/stateless/trex_stateless_api.h
+++ b/src/stateless/cp/trex_stateless_port.h
@@ -18,27 +18,74 @@ 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_API_H__
-#define __TREX_STATELESS_API_H__
+#ifndef __TREX_STATELESS_PORT_H__
+#define __TREX_STATELESS_PORT_H__
-#include <stdint.h>
-#include <string>
-#include <stdexcept>
+#include <trex_stream.h>
-#include <trex_stream_api.h>
+/**
+ * bandwidth measurement class
+ *
+ */
+class BWMeasure {
+public:
+ BWMeasure();
+ void reset(void);
+ double add(uint64_t size);
+
+private:
+ double calc_MBsec(uint32_t dtime_msec,
+ uint64_t dbytes);
+
+public:
+ bool m_start;
+ uint32_t m_last_time_msec;
+ uint64_t m_last_bytes;
+ double m_last_result;
+};
/**
- * generic exception for errors
- * TODO: move this to a better place
+ * TRex stateless port stats
+ *
+ * @author imarom (24-Sep-15)
*/
-class TrexException : public std::runtime_error
-{
+class TrexPortStats {
+
public:
- TrexException() : std::runtime_error("") {
+ TrexPortStats() {
+ m_stats = {0};
+ m_bw_tx_bps.reset();
+ m_bw_rx_bps.reset();
+
+ m_bw_tx_pps.reset();
+ m_bw_rx_pps.reset();
}
- TrexException(const std::string &what) : std::runtime_error(what) {
- }
+
+public:
+
+ BWMeasure m_bw_tx_bps;
+ BWMeasure m_bw_rx_bps;
+
+ BWMeasure m_bw_tx_pps;
+ BWMeasure m_bw_rx_pps;
+
+ struct {
+
+ double m_tx_bps;
+ double m_rx_bps;
+
+ double m_tx_pps;
+ double m_rx_pps;
+
+ uint64_t m_total_tx_pkts;
+ uint64_t m_total_rx_pkts;
+
+ uint64_t m_total_tx_bytes;
+ uint64_t m_total_rx_bytes;
+
+ uint64_t m_tx_rx_errors;
+ } m_stats;
};
/**
@@ -49,20 +96,6 @@ public:
class TrexStatelessPort {
public:
- struct TrexPortStats {
- uint64_t tx_pps;
- uint64_t tx_bps;
- uint64_t total_tx_pkts;
- uint64_t total_tx_bytes;
-
- uint64_t rx_pps;
- uint64_t rx_bps;
- uint64_t total_rx_pkts;
- uint64_t total_rx_bytes;
-
- uint64_t tx_rx_errors;
- };
-
/**
* port state
*/
@@ -169,15 +202,18 @@ public:
}
- const TrexPortStats & get_port_stats(void) {
- /* scrabble */
- m_stats.tx_bps += 1 + rand() % 100;
- m_stats.tx_pps += 1 + rand() % 10;
- m_stats.total_tx_bytes += 1 + rand() % 10;
- m_stats.total_tx_pkts += 1 + rand() % 5;
+ /**
+ * update the values of the stats
+ *
+ */
+ void update_stats();
+
+ const TrexPortStats & get_stats();
- return m_stats;
- }
+ /**
+ * encode stats as JSON
+ */
+ void encode_stats(Json::Value &port);
private:
@@ -191,54 +227,4 @@ private:
TrexPortStats m_stats;
};
-/**
- * defines the T-Rex stateless operation mode
- *
- */
-class TrexStateless {
-public:
-
- /**
- * configure the stateless object singelton
- * reconfiguration is not allowed
- * an exception will be thrown
- */
- static void configure(uint8_t port_count);
-
- /**
- * singleton public get instance
- *
- */
- static TrexStateless& get_instance() {
- TrexStateless& instance = get_instance_internal();
-
- if (!instance.m_is_configured) {
- throw TrexException("object is not configured");
- }
-
- return instance;
- }
-
- TrexStatelessPort *get_port_by_id(uint8_t port_id);
- uint8_t get_port_count();
-
-protected:
- TrexStateless();
- ~TrexStateless();
-
- static TrexStateless& get_instance_internal () {
- static TrexStateless instance;
- return instance;
- }
-
- /* c++ 2011 style singleton */
- TrexStateless(TrexStateless const&) = delete;
- void operator=(TrexStateless const&) = delete;
-
- bool m_is_configured;
- TrexStatelessPort **m_ports;
- uint8_t m_port_count;
-};
-
-#endif /* __TREX_STATELESS_API_H__ */
-
+#endif /* __TREX_STATELESS_PORT_H__ */
diff --git a/src/stateless/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp
index 8bf04748..182036f1 100644
--- a/src/stateless/trex_stream.cpp
+++ b/src/stateless/cp/trex_stream.cpp
@@ -18,7 +18,7 @@ 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_stream_api.h>
+#include <trex_stream.h>
#include <cstddef>
/**************************************
diff --git a/src/stateless/trex_stream_api.h b/src/stateless/cp/trex_stream.h
index d3c0fb29..f5bc96ef 100644
--- a/src/stateless/trex_stream_api.h
+++ b/src/stateless/cp/trex_stream.h
@@ -18,8 +18,8 @@ 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_STREAM_API_H__
-#define __TREX_STREAM_API_H__
+#ifndef __TREX_STREAM_H__
+#define __TREX_STREAM_H__
#include <unordered_map>
#include <vector>
@@ -205,5 +205,5 @@ private:
std::unordered_map<int, TrexStream *> m_stream_table;
};
-#endif /* __TREX_STREAM_API_H__ */
+#endif /* __TREX_STREAM_H__ */
diff --git a/src/stateless/trex_stream_vm.cpp b/src/stateless/cp/trex_stream_vm.cpp
index 2e760ae9..2e760ae9 100644
--- a/src/stateless/trex_stream_vm.cpp
+++ b/src/stateless/cp/trex_stream_vm.cpp
diff --git a/src/stateless/trex_stream_vm.h b/src/stateless/cp/trex_stream_vm.h
index 56edbcaf..56edbcaf 100644
--- a/src/stateless/trex_stream_vm.h
+++ b/src/stateless/cp/trex_stream_vm.h
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..1c96487d
--- /dev/null
+++ b/src/stateless/dp/trex_stateless_dp_core.cpp
@@ -0,0 +1,132 @@
+/*
+ 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 <stdio.h>
+#include <unistd.h>
+#include <trex_stateless.h>
+
+#include <bp_sim.h>
+
+// DPDK c++ issue
+#define UINT8_MAX 255
+#define UINT16_MAX 0xFFFF
+// DPDK c++ issue
+
+#include <rte_ethdev.h>
+#include "mbuf.h"
+
+/**
+ * TEST
+ *
+ */
+static const uint8_t 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
+};
+
+static int
+test_inject_pkt(uint8_t *pkt, uint32_t pkt_size) {
+
+ #ifndef TREX_RPC_MOCK_SERVER
+ rte_mempool_t * mp= CGlobalInfo::m_mem_pool[0].m_big_mbuf_pool ;
+ #else
+ rte_mempool_t * mp = NULL;
+ #endif
+
+ rte_mbuf_t *m = rte_pktmbuf_alloc(mp);
+ if ( unlikely(m==0) ) {
+ printf("ERROR no packets \n");
+ return (-1);
+ }
+ char *p = rte_pktmbuf_append(m, pkt_size);
+ assert(p);
+ /* set pkt data */
+ memcpy(p,pkt,pkt_size);
+
+ rte_mbuf_t *tx_pkts[32];
+ tx_pkts[0] = m;
+ uint8_t nb_pkts = 1;
+ uint16_t ret = rte_eth_tx_burst(0, 0, tx_pkts, nb_pkts);
+ (void)ret;
+ rte_pktmbuf_free(m);
+
+ return (0);
+}
+
+static int
+test_inject_udp_pkt(){
+ return (test_inject_pkt((uint8_t*)udp_pkt,sizeof(udp_pkt)));
+}
+
+void
+TrexStatelessDpCore::test_inject_dummy_pkt() {
+ test_inject_udp_pkt();
+}
+
+/***************************
+ * DP core
+ *
+ **************************/
+TrexStatelessDpCore::TrexStatelessDpCore(uint8_t core_id) : m_core_id(core_id) {
+}
+
+/**
+ * main function for DP core
+ *
+ */
+void
+TrexStatelessDpCore::run() {
+ printf("\nOn DP core %d\n", m_core_id);
+ while (true) {
+ test_inject_dummy_pkt();
+ rte_pause();
+ }
+}
+
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..4b09b752
--- /dev/null
+++ b/src/stateless/dp/trex_stateless_dp_core.h
@@ -0,0 +1,43 @@
+/*
+ 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 <stdint.h>
+
+/**
+ * stateless DP core object
+ *
+ */
+class TrexStatelessDpCore {
+public:
+
+ TrexStatelessDpCore(uint8_t core_id);
+
+ /* starts the DP core run */
+ void run();
+
+private:
+ void test_inject_dummy_pkt();
+ uint8_t m_core_id;
+};
+
+#endif /* __TREX_STATELESS_DP_CORE_H__ */
diff --git a/src/stateless/trex_stateless.cpp b/src/stateless/trex_stateless.cpp
deleted file mode 100644
index 0eb96f05..00000000
--- a/src/stateless/trex_stateless.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- 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_api.h>
-
-using namespace std;
-
-/***********************************************************
- * Trex stateless object
- *
- **********************************************************/
-TrexStateless::TrexStateless() {
- m_is_configured = false;
-}
-
-/**
- * one time configuration of the stateless object
- *
- */
-void TrexStateless::configure(uint8_t port_count) {
-
- TrexStateless& instance = get_instance_internal();
-
- if (instance.m_is_configured) {
- throw TrexException("re-configuration of stateless object is not allowed");
- }
-
- instance.m_port_count = port_count;
- instance.m_ports = new TrexStatelessPort*[port_count];
-
- for (int i = 0; i < instance.m_port_count; i++) {
- instance.m_ports[i] = new TrexStatelessPort(i);
- }
-
- instance.m_is_configured = true;
-}
-
-TrexStateless::~TrexStateless() {
- for (int i = 0; i < m_port_count; i++) {
- delete m_ports[i];
- }
-
- delete [] m_ports;
-}
-
-TrexStatelessPort * TrexStateless::get_port_by_id(uint8_t port_id) {
- if (port_id >= m_port_count) {
- throw TrexException("index out of range");
- }
-
- return m_ports[port_id];
-
-}
-
-uint8_t TrexStateless::get_port_count() {
- return m_port_count;
-}
-
-/***************************
- * trex stateless port
- *
- **************************/
-TrexStatelessPort::TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) {
- m_port_state = PORT_STATE_UP_IDLE;
- clear_owner();
- m_stats = {0};
-}
-
-
-/**
- * starts the traffic on the port
- *
- */
-TrexStatelessPort::rc_e
-TrexStatelessPort::start_traffic(void) {
-
- if (m_port_state != PORT_STATE_UP_IDLE) {
- return (RC_ERR_BAD_STATE_FOR_OP);
- }
-
- if (get_stream_table()->size() == 0) {
- return (RC_ERR_NO_STREAMS);
- }
-
- m_port_state = PORT_STATE_TRANSMITTING;
-
- /* real code goes here */
- return (RC_OK);
-}
-
-void
-TrexStatelessPort::stop_traffic(void) {
-
- /* real code goes here */
- if (m_port_state == PORT_STATE_TRANSMITTING) {
- m_port_state = PORT_STATE_UP_IDLE;
- }
-}
-
-/**
-* access the stream table
-*
-*/
-TrexStreamTable * TrexStatelessPort::get_stream_table() {
- return &m_stream_table;
-}
-
-
-std::string
-TrexStatelessPort::get_state_as_string() {
-
- switch (get_state()) {
- case PORT_STATE_DOWN:
- return "down";
-
- case PORT_STATE_UP_IDLE:
- return "idle";
-
- case PORT_STATE_TRANSMITTING:
- return "transmitting";
- }
-
- return "unknown";
-}
-
-void
-TrexStatelessPort::get_properties(string &driver, string &speed) {
-
- /* take this from DPDK */
- driver = "e1000";
- speed = "1 Gbps";
-}
-
-
-/**
- * generate a random connection handler
- *
- */
-std::string
-TrexStatelessPort::generate_handler() {
- std::stringstream ss;
-
- static const char alphanum[] =
- "0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz";
-
- /* generate 8 bytes of random handler */
- for (int i = 0; i < 8; ++i) {
- ss << alphanum[rand() % (sizeof(alphanum) - 1)];
- }
-
- return (ss.str());
-}
diff --git a/src/tuple_gen.h b/src/tuple_gen.h
index 4b181ad5..29adbd69 100755
--- a/src/tuple_gen.h
+++ b/src/tuple_gen.h
@@ -183,6 +183,7 @@ class CIpInfoBase {
void set_ip(uint32_t ip) {
m_ip = ip;
}
+ virtual ~CIpInfoBase() {}
protected:
uint32_t m_ip;
};
@@ -409,7 +410,7 @@ class CIpPool {
(ip<=ip_back->get_ip())) {
return(true);
}
- printf("invalid ip:%x, min_ip:%x, max_ip:%x, this:%x\n",
+ printf("invalid ip:%x, min_ip:%x, max_ip:%x, this:%p\n",
ip, ip_front->get_ip(),
ip_back->get_ip(),this);
return(false);