summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2016-01-04 09:49:37 -0500
committerimarom <imarom@cisco.com>2016-01-04 10:02:59 -0500
commit857bdcf05a920b99e1cf180c700176b04801da00 (patch)
treea524225219e462c12817e3a710905cb6e27d9c9d /src
parente134270a3bcf3c9498a2926ffea1d7bb0d4960eb (diff)
some additions to the stateless simulation mode
Diffstat (limited to 'src')
-rwxr-xr-xsrc/main.cpp69
-rw-r--r--src/sim/trex_sim.h17
-rw-r--r--src/sim/trex_sim_stateful.cpp1
-rw-r--r--src/sim/trex_sim_stateless.cpp97
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.cpp7
-rw-r--r--src/stateless/dp/trex_stateless_dp_core.h6
6 files changed, 158 insertions, 39 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 3fa7c7c3..ba6e258a 100755
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -35,7 +35,7 @@ using namespace std;
// An enum for all the option types
enum { OPT_HELP, OPT_CFG, OPT_NODE_DUMP, OP_STATS,
OPT_FILE_OUT, OPT_UT, OPT_PCAP, OPT_IPV6, OPT_MAC_FILE,
- OPT_SL};
+ OPT_SL, OPT_DP_CORE_COUNT, OPT_DP_CORE_INDEX};
@@ -59,18 +59,21 @@ typedef enum {
*/
static CSimpleOpt::SOption parser_options[] =
{
- { OPT_HELP, "-?", SO_NONE },
- { OPT_HELP, "-h", SO_NONE },
- { OPT_HELP, "--help", SO_NONE },
- { OPT_UT, "--ut", SO_NONE },
- { OP_STATS, "-s", SO_NONE },
- { OPT_CFG, "-f", SO_REQ_SEP},
- { OPT_MAC_FILE, "--mac", SO_REQ_SEP},
- { OPT_FILE_OUT , "-o", SO_REQ_SEP },
- { OPT_NODE_DUMP , "-v", SO_REQ_SEP },
- { OPT_PCAP, "--pcap", SO_NONE },
- { OPT_IPV6, "--ipv6", SO_NONE },
- { OPT_SL, "--sl", SO_NONE },
+ { OPT_HELP, "-?", SO_NONE },
+ { OPT_HELP, "-h", SO_NONE },
+ { OPT_HELP, "--help", SO_NONE },
+ { OPT_UT, "--ut", SO_NONE },
+ { OP_STATS, "-s", SO_NONE },
+ { OPT_CFG, "-f", SO_REQ_SEP },
+ { OPT_MAC_FILE, "--mac", SO_REQ_SEP },
+ { OPT_FILE_OUT , "-o", SO_REQ_SEP },
+ { OPT_NODE_DUMP , "-v", SO_REQ_SEP },
+ { OPT_PCAP, "--pcap", SO_NONE },
+ { OPT_IPV6, "--ipv6", SO_NONE },
+ { OPT_SL, "--sl", SO_NONE },
+ { OPT_DP_CORE_COUNT, "--cores", SO_REQ_SEP },
+ { OPT_DP_CORE_INDEX, "--core_index", SO_REQ_SEP },
+
SO_END_OF_OPTIONS
};
@@ -113,7 +116,13 @@ static int usage(){
}
-static int parse_options(int argc, char *argv[], CParserOption* po, opt_type_e &type) {
+static int parse_options(int argc,
+ char *argv[],
+ CParserOption* po,
+ opt_type_e &type,
+ int &dp_core_count,
+ int &dp_core_index) {
+
CSimpleOpt args(argc, argv, parser_options);
int a=0;
@@ -124,6 +133,9 @@ static int parse_options(int argc, char *argv[], CParserOption* po, opt_type_e &
/* by default - type is stateful */
type = OPT_TYPE_SF;
+ dp_core_count = 1;
+ dp_core_index = 0;
+
while ( args.Next() ){
if (args.LastError() == SO_SUCCESS) {
switch (args.OptionId()) {
@@ -166,6 +178,14 @@ static int parse_options(int argc, char *argv[], CParserOption* po, opt_type_e &
po->preview.set_pcap_mode_enable(true);
break;
+ case OPT_DP_CORE_COUNT:
+ dp_core_count = atoi(args.OptionArg());
+ break;
+
+ case OPT_DP_CORE_INDEX:
+ dp_core_index = atoi(args.OptionArg());
+ break;
+
default:
usage();
return -1;
@@ -194,6 +214,21 @@ static int parse_options(int argc, char *argv[], CParserOption* po, opt_type_e &
return -1;
}
}
+
+ if (dp_core_count != -1) {
+ if ( (dp_core_count < 1) || (dp_core_count > 8) ) {
+ printf("dp core count must be a value between 1 and 8\n");
+ return (-1);
+ }
+ }
+
+ if (dp_core_index != -1) {
+ if ( (dp_core_index < 0) || (dp_core_index >= dp_core_count) ) {
+ printf("dp core count must be a value between 0 and cores - 1\n");
+ return (-1);
+ }
+ }
+
return 0;
}
@@ -201,8 +236,10 @@ static int parse_options(int argc, char *argv[], CParserOption* po, opt_type_e &
int main(int argc , char * argv[]){
opt_type_e type;
+ int dp_core_count;
+ int dp_core_index;
- if ( parse_options(argc, argv, &CGlobalInfo::m_options , type) != 0) {
+ if ( parse_options(argc, argv, &CGlobalInfo::m_options , type, dp_core_count, dp_core_index) != 0) {
exit(-1);
}
@@ -222,7 +259,7 @@ int main(int argc , char * argv[]){
case OPT_TYPE_SL:
{
SimStateless &st = SimStateless::get_instance();
- return st.run(CGlobalInfo::m_options.cfg_file, CGlobalInfo::m_options.out_file);
+ return st.run(CGlobalInfo::m_options.cfg_file, CGlobalInfo::m_options.out_file, 2, dp_core_count, dp_core_index);
}
}
}
diff --git a/src/sim/trex_sim.h b/src/sim/trex_sim.h
index 02f62d79..cc02fd75 100644
--- a/src/sim/trex_sim.h
+++ b/src/sim/trex_sim.h
@@ -44,7 +44,6 @@ public:
time_init();
CGlobalInfo::m_socket.Create(0);
CGlobalInfo::init_pools(1000);
- assert( CMsgIns::Ins()->Create(4) );
}
virtual ~SimInterface() {
@@ -66,6 +65,7 @@ class SimGtest : public SimInterface {
public:
int run(int argc, char **argv) {
+ assert( CMsgIns::Ins()->Create(4) );
return gtest_main(argc, argv);
}
};
@@ -98,7 +98,11 @@ public:
}
- int run(const std::string &json_filename, const std::string &out_filename);
+ int run(const std::string &json_filename,
+ const std::string &out_filename,
+ int port_count,
+ int dp_core_count,
+ int dp_core_index);
TrexStateless * get_stateless_obj() {
return m_trex_stateless;
@@ -115,8 +119,11 @@ private:
void prepare_control_plane();
void prepare_dataplane();
void execute_json(const std::string &json_filename);
+
void run_dp(const std::string &out_filename);
- void flush_dp_to_cp_messages();
+ void run_dp_core(int core_index, const std::string &out_filename);
+
+ void flush_dp_to_cp_messages_core(int core_index);
void validate_response(const Json::Value &resp);
@@ -130,6 +137,10 @@ private:
CFlowGenList m_fl;
CErfIFStl m_erf_vif;
bool m_verbose;
+
+ int m_port_count;
+ int m_dp_core_count;
+ int m_dp_core_index;
};
#endif /* __TREX_SIM_H__ */
diff --git a/src/sim/trex_sim_stateful.cpp b/src/sim/trex_sim_stateful.cpp
index 35c17d6e..88698cd1 100644
--- a/src/sim/trex_sim_stateful.cpp
+++ b/src/sim/trex_sim_stateful.cpp
@@ -595,5 +595,6 @@ int merge_2_cap_files_sip() {
int
SimStateful::run() {
+ assert( CMsgIns::Ins()->Create(4) );
return load_list_of_cap_files(&CGlobalInfo::m_options);
}
diff --git a/src/sim/trex_sim_stateless.cpp b/src/sim/trex_sim_stateless.cpp
index 9803ccbc..2821644f 100644
--- a/src/sim/trex_sim_stateless.cpp
+++ b/src/sim/trex_sim_stateless.cpp
@@ -44,6 +44,33 @@ public:
}
};
+/*************** hook for platform API **************/
+class SimPlatformApi : public TrexPlatformApi {
+public:
+ SimPlatformApi(int dp_core_count) {
+ m_dp_core_count = dp_core_count;
+ }
+
+ virtual uint8_t get_dp_core_count() const {
+ return m_dp_core_count;
+ }
+
+ virtual void get_global_stats(TrexPlatformGlobalStats &stats) const {
+ }
+ virtual void get_interface_info(uint8_t interface_id, std::string &driver_name, driver_speed_e &speed) const {
+ }
+ virtual void get_interface_stats(uint8_t interface_id, TrexPlatformInterfaceStats &stats) const {
+ }
+
+ virtual void port_id_to_cores(uint8_t port_id, std::vector<std::pair<uint8_t, uint8_t>> &cores_id_list) const {
+ for (int i = 0; i < m_dp_core_count; i++) {
+ cores_id_list.push_back(std::make_pair(i, 0));
+ }
+ }
+
+private:
+ int m_dp_core_count;
+};
/**
* handler for DP to CP messages
@@ -90,6 +117,9 @@ SimStateless::SimStateless() {
m_publisher = NULL;
m_dp_to_cp_handler = NULL;
m_verbose = false;
+ m_dp_core_count = -1;
+ m_dp_core_index = -1;
+ m_port_count = -1;
/* override ownership checks */
TrexRpcCommand::test_set_override_ownership(true);
@@ -97,7 +127,20 @@ SimStateless::SimStateless() {
int
-SimStateless::run(const string &json_filename, const string &out_filename) {
+SimStateless::run(const string &json_filename,
+ const string &out_filename,
+ int port_count,
+ int dp_core_count,
+ int dp_core_index) {
+
+ assert(dp_core_count > 0);
+ assert(dp_core_index >= 0);
+ assert(dp_core_index < dp_core_count);
+
+ m_dp_core_count = dp_core_count;
+ m_dp_core_index = dp_core_index;
+ m_port_count = port_count;
+
prepare_dataplane();
prepare_control_plane();
@@ -105,13 +148,11 @@ SimStateless::run(const string &json_filename, const string &out_filename) {
execute_json(json_filename);
} catch (const SimRunException &e) {
std::cout << "*** test failed ***\n\n" << e.what() << "\n";
- exit(-1);
+ return (-1);
}
run_dp(out_filename);
- flush_dp_to_cp_messages();
-
return 0;
}
@@ -143,11 +184,11 @@ SimStateless::prepare_control_plane() {
TrexRpcServerConfig rpc_req_resp_cfg(TrexRpcServerConfig::RPC_PROT_MOCK, 0);
- cfg.m_port_count = 4;
+ cfg.m_port_count = m_port_count;
cfg.m_rpc_req_resp_cfg = &rpc_req_resp_cfg;
cfg.m_rpc_async_cfg = NULL;
cfg.m_rpc_server_verbose = false;
- cfg.m_platform_api = new TrexMockPlatformApi();
+ cfg.m_platform_api = new SimPlatformApi(m_dp_core_count);
cfg.m_publisher = m_publisher;
m_trex_stateless = new TrexStateless(cfg);
@@ -168,9 +209,15 @@ SimStateless::prepare_control_plane() {
void
SimStateless::prepare_dataplane() {
+ CGlobalInfo::m_options.m_expected_portd = m_port_count;
+
+ assert(CMsgIns::Ins()->Create(m_dp_core_count));
m_fl.Create();
- m_fl.generate_p_thread_info(1);
- m_fl.m_threads_info[0]->set_vif(&m_erf_vif);
+ m_fl.generate_p_thread_info(m_dp_core_count);
+
+ for (int i = 0; i < m_dp_core_count; i++) {
+ m_fl.m_threads_info[i]->set_vif(&m_erf_vif);
+ }
}
@@ -220,20 +267,39 @@ SimStateless::validate_response(const Json::Value &resp) {
void
SimStateless::run_dp(const std::string &out_filename) {
- CFlowGenListPerThread *lpt = m_fl.m_threads_info[0];
-
+ for (int i = 0; i < m_dp_core_count; i++) {
+ if (i == m_dp_core_index) {
+ run_dp_core(i, out_filename);
+ } else {
+ run_dp_core(i, "/dev/null");
+ }
+ }
+
+ CFlowGenListPerThread *lpt = m_fl.m_threads_info[m_dp_core_index];
+
+ std::cout << "\n";
+ std::cout << "ports: " << m_port_count << "\n";
+ std::cout << "cores: " << m_dp_core_count << "\n";
+ std::cout << "core index: " << m_dp_core_index << "\n";
+ std::cout << "\nwritten " << lpt->m_node_gen.m_cnt << " packets " << "to '" << out_filename << "'\n\n";
+}
+
+void
+SimStateless::run_dp_core(int core_index, const std::string &out_filename) {
+
+ CFlowGenListPerThread *lpt = m_fl.m_threads_info[core_index];
+
lpt->start_stateless_simulation_file((std::string)out_filename, CGlobalInfo::m_options.preview);
lpt->start_stateless_daemon_simulation();
- flush_dp_to_cp_messages();
-
- std::cout << "\nwritten " << lpt->m_node_gen.m_cnt << " packets " << "to '" << out_filename << "'\n\n";
+ flush_dp_to_cp_messages_core(core_index);
}
+
void
-SimStateless::flush_dp_to_cp_messages() {
+SimStateless::flush_dp_to_cp_messages_core(int core_index) {
- CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingDpToCp(0);
+ CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingDpToCp(core_index);
while ( true ) {
CGenNode * node = NULL;
@@ -249,5 +315,4 @@ SimStateless::flush_dp_to_cp_messages() {
delete msg;
}
-
}
diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp
index c211b9f5..0a9a88ab 100644
--- a/src/stateless/dp/trex_stateless_dp_core.cpp
+++ b/src/stateless/dp/trex_stateless_dp_core.cpp
@@ -353,8 +353,11 @@ void
TrexStatelessDpCore::idle_state_loop() {
while (m_state == STATE_IDLE) {
- periodic_check_for_cp_messages();
- delay(200);
+ bool had_msg = periodic_check_for_cp_messages();
+ /* if no message - backoff for some time */
+ if (!had_msg) {
+ delay(200);
+ }
}
}
diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h
index 7dc4a2b2..efdb364c 100644
--- a/src/stateless/dp/trex_stateless_dp_core.h
+++ b/src/stateless/dp/trex_stateless_dp_core.h
@@ -185,12 +185,12 @@ public:
*
* @author imarom (27-Oct-15)
*/
- void periodic_check_for_cp_messages() {
+ bool periodic_check_for_cp_messages() {
// doing this inline for performance reasons
/* fast path */
if ( likely ( m_ring_from_cp->isEmpty() ) ) {
- return;
+ return false;
}
while ( true ) {
@@ -204,6 +204,8 @@ public:
handle_cp_msg(msg);
}
+ return true;
+
}
/* quit the main loop, work in both stateless in stateful, don't free memory trigger from master */