summaryrefslogtreecommitdiffstats
path: root/src/sim/trex_sim_stateless.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sim/trex_sim_stateless.cpp')
-rw-r--r--src/sim/trex_sim_stateless.cpp190
1 files changed, 173 insertions, 17 deletions
diff --git a/src/sim/trex_sim_stateless.cpp b/src/sim/trex_sim_stateless.cpp
index 2821644f..215315e0 100644
--- a/src/sim/trex_sim_stateless.cpp
+++ b/src/sim/trex_sim_stateless.cpp
@@ -26,9 +26,34 @@ limitations under the License.
#include <json/json.h>
#include <stdexcept>
#include <sstream>
+#include <trex_streams_compiler.h>
using namespace std;
+/****** utils ******/
+static string format_num(double num, const string &suffix = "") {
+ const char x[] = {' ','K','M','G','T','P'};
+
+ double my_num = num;
+
+ for (int i = 0; i < sizeof(x); i++) {
+ if (std::abs(my_num) < 1000.0) {
+ stringstream ss;
+
+ char buf[100];
+ snprintf(buf, sizeof(buf), "%.2f", my_num);
+
+ ss << buf << " " << x[i] << suffix;
+ return ss.str();
+
+ } else {
+ my_num /= 1000.0;
+ }
+ }
+
+ return "NaN";
+}
+
TrexStateless * get_stateless_obj() {
return SimStateless::get_instance().get_stateless_obj();
}
@@ -57,8 +82,12 @@ public:
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 {
+ driver_name = "TEST";
+ speed = TrexPlatformApi::SPEED_10G;
}
+
virtual void get_interface_stats(uint8_t interface_id, TrexPlatformInterfaceStats &stats) const {
}
@@ -120,6 +149,8 @@ SimStateless::SimStateless() {
m_dp_core_count = -1;
m_dp_core_index = -1;
m_port_count = -1;
+ m_limit = 0;
+ m_is_dry_run = false;
/* override ownership checks */
TrexRpcCommand::test_set_override_ownership(true);
@@ -131,15 +162,20 @@ SimStateless::run(const string &json_filename,
const string &out_filename,
int port_count,
int dp_core_count,
- int dp_core_index) {
+ int dp_core_index,
+ int limit,
+ bool is_dry_run) {
assert(dp_core_count > 0);
- assert(dp_core_index >= 0);
- assert(dp_core_index < dp_core_count);
+
+ /* -1 means its not set or positive value between 0 and the dp core count - 1*/
+ assert( (dp_core_index == -1) || ( in_range(dp_core_index, 0, dp_core_count - 1)) );
m_dp_core_count = dp_core_count;
m_dp_core_index = dp_core_index;
m_port_count = port_count;
+ m_limit = limit;
+ m_is_dry_run = is_dry_run;
prepare_dataplane();
prepare_control_plane();
@@ -216,7 +252,11 @@ SimStateless::prepare_dataplane() {
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);
+ if (should_capture_core(i)) {
+ m_fl.m_threads_info[i]->set_vif(&m_erf_vif);
+ } else {
+ m_fl.m_threads_info[i]->set_vif(&m_null_erf_vif);
+ }
}
}
@@ -263,36 +303,125 @@ SimStateless::validate_response(const Json::Value &resp) {
}
+static inline bool is_debug() {
+ #ifdef DEBUG
+ return true;
+ #else
+ return false;
+ #endif
+}
+
+void
+SimStateless::show_intro(const std::string &out_filename) {
+ uint64_t bps = 0;
+ uint64_t pps = 0;
+
+ std::cout << "\nGeneral info:\n";
+ std::cout << "------------\n\n";
+
+ std::cout << "image type: " << (is_debug() ? "debug" : "release") << "\n";
+ std::cout << "I/O output: " << (m_is_dry_run ? "*DRY*" : out_filename) << "\n";
+
+ if (m_limit > 0) {
+ std::cout << "packet limit: " << m_limit << "\n";
+ } else {
+ std::cout << "packet limit: " << "*NO LIMIT*" << "\n";
+ }
+
+ if (m_dp_core_index != -1) {
+ std::cout << "core recording: " << m_dp_core_index << "\n";
+ } else {
+ std::cout << "core recording: merge all\n";
+ }
+
+ std::cout << "\nConfiguration info:\n";
+ std::cout << "-------------------\n\n";
+
+ std::cout << "ports: " << m_port_count << "\n";
+ std::cout << "cores: " << m_dp_core_count << "\n";
+
+
+ std::cout << "\nPort Config:\n";
+ std::cout << "------------\n\n";
+
+ TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(0);
+
+ std::cout << "stream count: " << port->get_stream_count() << "\n";
+
+ port->get_port_effective_rate(bps, pps);
+
+ std::cout << "max BPS: " << format_num(bps, "bps") << "\n";
+ std::cout << "max PPS: " << format_num(pps, "pps") << "\n";
+
+ std::cout << "\n\nStarting simulation...\n";
+}
void
SimStateless::run_dp(const std::string &out_filename) {
+ uint64_t simulated_pkts_cnt = 0;
+ uint64_t written_pkts_cnt = 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");
+ show_intro(out_filename);
+
+ if (is_multiple_capture()) {
+ for (int i = 0; i < m_dp_core_count; i++) {
+ std::stringstream ss;
+ ss << out_filename << "-" << i;
+ run_dp_core(i, ss.str(), simulated_pkts_cnt, written_pkts_cnt);
+ }
+
+ } else {
+ for (int i = 0; i < m_dp_core_count; i++) {
+ run_dp_core(i, out_filename, simulated_pkts_cnt, written_pkts_cnt);
}
}
- CFlowGenListPerThread *lpt = m_fl.m_threads_info[m_dp_core_index];
-
+ std::cout << "\n\nSimulation summary:\n";
+ std::cout << "-------------------\n\n";
+ std::cout << "simulated " << simulated_pkts_cnt << " packets\n";
+
+ if (m_is_dry_run) {
+ std::cout << "*DRY RUN* - no packets were written\n";
+ } else {
+ std::cout << "written " << written_pkts_cnt << " packets " << "to '" << out_filename << "'\n\n";
+ }
+
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";
+}
+
+
+uint64_t
+SimStateless::get_limit_per_core(int core_index) {
+ /* global no limit ? */
+ if (m_limit == 0) {
+ return (0);
+ } else {
+ uint64_t l = std::max((uint64_t)1, m_limit / m_dp_core_count);
+ if (core_index == 0) {
+ l += (m_limit % m_dp_core_count);
+ }
+ return l;
+ }
}
void
-SimStateless::run_dp_core(int core_index, const std::string &out_filename) {
+SimStateless::run_dp_core(int core_index,
+ const std::string &out_filename,
+ uint64_t &simulated_pkts,
+ uint64_t &written_pkts) {
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_simulation_file((std::string)out_filename, CGlobalInfo::m_options.preview, get_limit_per_core(core_index));
lpt->start_stateless_daemon_simulation();
flush_dp_to_cp_messages_core(core_index);
+
+ simulated_pkts += lpt->m_node_gen.m_cnt;
+
+ if (should_capture_core(core_index)) {
+ written_pkts += lpt->m_node_gen.m_cnt;
+ }
}
@@ -316,3 +445,30 @@ SimStateless::flush_dp_to_cp_messages_core(int core_index) {
delete msg;
}
}
+
+bool
+SimStateless::should_capture_core(int i) {
+
+ /* dry run - no core should be recordered */
+ if (m_is_dry_run) {
+ return false;
+ }
+
+ /* no specific core index ? record all */
+ if (m_dp_core_index == -1) {
+ return true;
+ } else {
+ return (i == m_dp_core_index);
+ }
+}
+
+bool
+SimStateless::is_multiple_capture() {
+ /* dry run - no core should be recordered */
+ if (m_is_dry_run) {
+ return false;
+ }
+
+ return ( (m_dp_core_count > 1) && (m_dp_core_index == -1) );
+}
+