diff options
-rwxr-xr-x | scripts/automation/trex_control_plane/stl/console/trex_console.py | 2 | ||||
-rw-r--r-- | scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py | 63 | ||||
-rwxr-xr-x | src/bp_sim.cpp | 5 | ||||
-rwxr-xr-x | src/main.cpp | 9 | ||||
-rwxr-xr-x | src/msg_manager.cpp | 15 | ||||
-rw-r--r-- | src/rpc-server/commands/trex_rpc_cmd_stream.cpp | 40 | ||||
-rw-r--r-- | src/rpc-server/commands/trex_rpc_cmds.h | 21 | ||||
-rw-r--r-- | src/sim/trex_sim.h | 61 | ||||
-rw-r--r-- | src/sim/trex_sim_stateless.cpp | 69 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless_port.cpp | 12 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless_port.h | 7 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream.cpp | 35 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream.h | 174 |
13 files changed, 318 insertions, 195 deletions
diff --git a/scripts/automation/trex_control_plane/stl/console/trex_console.py b/scripts/automation/trex_control_plane/stl/console/trex_console.py index 9e9dcf62..0beb10df 100755 --- a/scripts/automation/trex_control_plane/stl/console/trex_console.py +++ b/scripts/automation/trex_control_plane/stl/console/trex_console.py @@ -532,7 +532,7 @@ class TRexConsole(TRexGeneralCmd): info = self.stateless_client.get_connection_info() exe = './trex-console --top -t -q -s {0} -p {1} --async_port {2}'.format(info['server'], info['sync_port'], info['async_port']) - cmd = ['xterm', '-geometry', '111x42', '-sl', '0', '-title', 'trex_tui', '-e', exe] + cmd = ['xterm', '-geometry', '111x47', '-sl', '0', '-title', 'trex_tui', '-e', exe] self.terminal = subprocess.Popen(cmd) return diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py index e5578564..34c7a857 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py @@ -117,8 +117,10 @@ class CTRexInfoGenerator(object): per_field_stats = OrderedDict([("owner", []), ("state", []), ("--", []), - ("Tx bps", []), + ("Tx bps L2", []), + ("Tx bps L1", []), ("Tx pps", []), + ("Line Util.", []), ("---", []), ("Rx bps", []), @@ -313,7 +315,15 @@ class CTRexStats(object): # must be implemented by designated classes (such as port/ global stats) raise NotImplementedError() + def generate_extended_values (self, snapshot): + raise NotImplementedError() + + def update(self, snapshot): + + # some extended generated values (from base values) + self.generate_extended_values(snapshot) + # update self.latest_stats = snapshot @@ -326,6 +336,8 @@ class CTRexStats(object): if (not self.reference_stats) or (diff_time > 3): self.reference_stats = self.latest_stats + + self.last_update_ts = time.time() @@ -439,6 +451,20 @@ class CGlobalStats(CTRexStats): return stats + def generate_extended_values (self, snapshot): + # L1 bps + bps = snapshot.get("m_tx_bps") + pps = snapshot.get("m_tx_pps") + + if pps > 0: + avg_pkt_size = bps / (pps * 8.0) + bps_L1 = bps * ( (avg_pkt_size + 20.0) / avg_pkt_size ) + else: + bps_L1 = 0.0 + + snapshot['m_tx_bps_L1'] = bps_L1 + + def generate_stats(self): return OrderedDict([("connection", "{host}, Port {port}".format(host=self.connection_info.get("server"), port=self.connection_info.get("sync_port"))), @@ -450,8 +476,11 @@ class CGlobalStats(CTRexStats): (" ", ""), - ("total_tx", u"{0} {1}".format( self.get("m_tx_bps", format=True, suffix="b/sec"), - self.get_trend_gui("m_tx_bps"))), + ("total_tx_L2", u"{0} {1}".format( self.get("m_tx_bps", format=True, suffix="b/sec"), + self.get_trend_gui("m_tx_bps"))), + + ("total_tx_L1", u"{0} {1}".format( self.get("m_tx_bps_L1", format=True, suffix="b/sec"), + self.get_trend_gui("m_tx_bps_L1"))), ("total_rx", u"{0} {1}".format( self.get("m_rx_bps", format=True, suffix="b/sec"), self.get_trend_gui("m_rx_bps"))), @@ -532,6 +561,21 @@ class CPortStats(CTRexStats): return stats + def generate_extended_values (self, snapshot): + # L1 bps + bps = snapshot.get("m_total_tx_bps") + pps = snapshot.get("m_total_tx_pps") + + if pps > 0: + avg_pkt_size = bps / (pps * 8.0) + bps_L1 = bps * ( (avg_pkt_size + 20.0) / avg_pkt_size ) + else: + bps_L1 = 0.0 + + snapshot['m_total_tx_bps_L1'] = bps_L1 + snapshot['m_percentage'] = (bps_L1 / self._port_obj.get_speed_bps()) * 100 + + def generate_stats(self): state = self._port_obj.get_port_state_name() if self._port_obj else "" @@ -542,6 +586,7 @@ class CPortStats(CTRexStats): else: state = format_text(state, 'bold') + return {"owner": self._port_obj.user if self._port_obj else "", "state": "{0}".format(state), @@ -550,8 +595,16 @@ class CPortStats(CTRexStats): "----": " ", "-----": " ", - "Tx bps": u"{0} {1}".format(self.get_trend_gui("m_total_tx_bps", show_value = False), - self.get("m_total_tx_bps", format = True, suffix = "bps")), + "Tx bps L1": u"{0} {1}".format(self.get_trend_gui("m_total_tx_bps_L1", show_value = False), + self.get("m_total_tx_bps_L1", format = True, suffix = "bps")), + + "Tx bps L2": u"{0} {1}".format(self.get_trend_gui("m_total_tx_bps", show_value = False), + self.get("m_total_tx_bps", format = True, suffix = "bps")), + + "Line Util.": u"{0} {1}".format(self.get_trend_gui("m_percentage", show_value = False), + format_text( + self.get("m_percentage", format = True, suffix = "%") if self._port_obj else "", + 'bold')), "Rx bps": u"{0} {1}".format(self.get_trend_gui("m_total_rx_bps", show_value = False), self.get("m_total_rx_bps", format = True, suffix = "bps")), diff --git a/src/bp_sim.cpp b/src/bp_sim.cpp index a1851b55..88e2c3ad 100755 --- a/src/bp_sim.cpp +++ b/src/bp_sim.cpp @@ -4137,7 +4137,10 @@ void CFlowGenListPerThread::start_generate_stateful(std::string erf_file_name, void CFlowGenList::Delete(){ clean_p_thread_info(); Clean(); - delete CPluginCallback::callback; + if (CPluginCallback::callback) { + delete CPluginCallback::callback; + CPluginCallback::callback = NULL; + } } diff --git a/src/main.cpp b/src/main.cpp index 6ee3a03d..6a6b5721 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -82,6 +82,8 @@ static CSimpleOpt::SOption parser_options[] = SO_END_OF_OPTIONS }; +static TrexStateless *m_sim_statelss_obj; + static int usage(){ printf(" Usage: bp_sim [OPTION] -f cfg.yaml -o outfile.erf \n"); @@ -247,6 +249,13 @@ void set_default_mac_addr(){ } } +TrexStateless * get_stateless_obj() { + return m_sim_statelss_obj; +} + +void set_stateless_obj(TrexStateless *obj) { + m_sim_statelss_obj = obj; +} int main(int argc , char * argv[]){ diff --git a/src/msg_manager.cpp b/src/msg_manager.cpp index 5fe44771..9ade1bfc 100755 --- a/src/msg_manager.cpp +++ b/src/msg_manager.cpp @@ -52,8 +52,6 @@ bool CMessagingManager::Create(uint8_t num_dp_threads,std::string a_name){ } void CMessagingManager::Delete(){ - assert(m_cp_to_dp); - assert(m_dp_to_cp); int i; for (i=0; i<m_num_dp_threads; i++) { CNodeRing * lp; @@ -63,8 +61,16 @@ void CMessagingManager::Delete(){ lp->Delete(); } - delete []m_dp_to_cp; - delete []m_cp_to_dp; + if (m_dp_to_cp) { + delete [] m_dp_to_cp; + m_dp_to_cp = NULL; + } + + if (m_cp_to_dp) { + delete [] m_cp_to_dp; + m_cp_to_dp = NULL; + } + } CNodeRing * CMessagingManager::getRingCpToDp(uint8_t thread_id){ @@ -83,6 +89,7 @@ void CMsgIns::Free(){ if (m_ins) { m_ins->Delete(); delete m_ins; + m_ins = NULL; } } diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp index 74985883..0918ff0e 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp @@ -49,7 +49,7 @@ TrexRpcCmdAddStream::_run(const Json::Value ¶ms, Json::Value &result) { string type = parse_string(mode, "type", result); /* allocate a new stream based on the type */ - std::unique_ptr<TrexStream> stream( allocate_new_stream(section, port_id, stream_id, result) ); + std::unique_ptr<TrexStream> stream = allocate_new_stream(section, port_id, stream_id, result); /* save this for future queries */ stream->store_stream_json(section); @@ -98,7 +98,7 @@ TrexRpcCmdAddStream::_run(const Json::Value ¶ms, Json::Value &result) { /* parse VM */ const Json::Value &vm = parse_object(section ,"vm", result); - parse_vm(vm, stream.get(), result); + parse_vm(vm, stream, result); /* parse RX info */ const Json::Value &rx = parse_object(section, "rx_stats", result); @@ -113,7 +113,7 @@ TrexRpcCmdAddStream::_run(const Json::Value ¶ms, Json::Value &result) { } /* make sure this is a valid stream to add */ - validate_stream(stream.get(), result); + validate_stream(stream, result); TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(stream->m_port_id); @@ -131,10 +131,10 @@ TrexRpcCmdAddStream::_run(const Json::Value ¶ms, Json::Value &result) { -TrexStream * +std::unique_ptr<TrexStream> TrexRpcCmdAddStream::allocate_new_stream(const Json::Value §ion, uint8_t port_id, uint32_t stream_id, Json::Value &result) { - TrexStream *stream = NULL; + std::unique_ptr<TrexStream> stream; const Json::Value &mode = parse_object(section, "mode", result); std::string type = parse_string(mode, "type", result); @@ -142,13 +142,13 @@ TrexRpcCmdAddStream::allocate_new_stream(const Json::Value §ion, uint8_t por if (type == "continuous") { - stream = new TrexStream( TrexStream::stCONTINUOUS, port_id, stream_id); + stream.reset(new TrexStream( TrexStream::stCONTINUOUS, port_id, stream_id)); } else if (type == "single_burst") { uint32_t total_pkts = parse_int(mode, "total_pkts", result); - stream = new TrexStream(TrexStream::stSINGLE_BURST, port_id, stream_id); + stream.reset(new TrexStream(TrexStream::stSINGLE_BURST, port_id, stream_id)); stream->set_single_burst(total_pkts); @@ -158,7 +158,7 @@ TrexRpcCmdAddStream::allocate_new_stream(const Json::Value §ion, uint8_t por uint32_t num_bursts = parse_int(mode, "count", result); uint32_t pkts_per_burst = parse_int(mode, "pkts_per_burst", result); - stream = new TrexStream(TrexStream::stMULTI_BURST,port_id, stream_id ); + stream.reset(new TrexStream(TrexStream::stMULTI_BURST,port_id, stream_id )); stream->set_multi_burst(pkts_per_burst,num_bursts,ibg_usec); @@ -175,9 +175,14 @@ TrexRpcCmdAddStream::allocate_new_stream(const Json::Value §ion, uint8_t por } void -TrexRpcCmdAddStream::parse_rate(const Json::Value &rate, TrexStream *stream, Json::Value &result) { +TrexRpcCmdAddStream::parse_rate(const Json::Value &rate, std::unique_ptr<TrexStream> &stream, Json::Value &result) { - double value = parse_double(rate, "value", result); + double value = parse_double(rate, "value", result); + if (value <= 0) { + std::stringstream ss; + ss << "rate value must be a positive number - got: '" << value << "'"; + generate_parse_err(result, ss.str()); + } auto rate_types = {"pps", "bps_L1", "bps_L2", "percentage"}; std::string rate_type = parse_choice(rate, "type", rate_types, result); @@ -198,7 +203,7 @@ TrexRpcCmdAddStream::parse_rate(const Json::Value &rate, TrexStream *stream, Jso } void -TrexRpcCmdAddStream::parse_vm_instr_checksum(const Json::Value &inst, TrexStream *stream, Json::Value &result) { +TrexRpcCmdAddStream::parse_vm_instr_checksum(const Json::Value &inst, std::unique_ptr<TrexStream> &stream, Json::Value &result) { uint16_t pkt_offset = parse_uint16(inst, "pkt_offset", result); stream->m_vm.add_instruction(new StreamVmInstructionFixChecksumIpv4(pkt_offset)); @@ -206,7 +211,7 @@ TrexRpcCmdAddStream::parse_vm_instr_checksum(const Json::Value &inst, TrexStream void -TrexRpcCmdAddStream::parse_vm_instr_trim_pkt_size(const Json::Value &inst, TrexStream *stream, Json::Value &result){ +TrexRpcCmdAddStream::parse_vm_instr_trim_pkt_size(const Json::Value &inst, std::unique_ptr<TrexStream> &stream, Json::Value &result){ std::string flow_var_name = parse_string(inst, "name", result); @@ -215,7 +220,7 @@ TrexRpcCmdAddStream::parse_vm_instr_trim_pkt_size(const Json::Value &inst, TrexS void -TrexRpcCmdAddStream::parse_vm_instr_tuple_flow_var(const Json::Value &inst, TrexStream *stream, Json::Value &result){ +TrexRpcCmdAddStream::parse_vm_instr_tuple_flow_var(const Json::Value &inst, std::unique_ptr<TrexStream> &stream, Json::Value &result){ std::string flow_var_name = parse_string(inst, "name", result); @@ -239,7 +244,7 @@ TrexRpcCmdAddStream::parse_vm_instr_tuple_flow_var(const Json::Value &inst, Trex void -TrexRpcCmdAddStream::parse_vm_instr_flow_var(const Json::Value &inst, TrexStream *stream, Json::Value &result) { +TrexRpcCmdAddStream::parse_vm_instr_flow_var(const Json::Value &inst, std::unique_ptr<TrexStream> &stream, Json::Value &result) { std::string flow_var_name = parse_string(inst, "name", result); auto sizes = {1, 2, 4, 8}; @@ -326,7 +331,7 @@ TrexRpcCmdAddStream::parse_vm_instr_write_mask_flow_var(const Json::Value &inst, void -TrexRpcCmdAddStream::parse_vm_instr_write_flow_var(const Json::Value &inst, TrexStream *stream, Json::Value &result) { +TrexRpcCmdAddStream::parse_vm_instr_write_flow_var(const Json::Value &inst, std::unique_ptr<TrexStream> &stream, Json::Value &result) { std::string flow_var_name = parse_string(inst, "name", result); uint16_t pkt_offset = parse_uint16(inst, "pkt_offset", result); int add_value = parse_int(inst, "add_value", result); @@ -339,7 +344,7 @@ TrexRpcCmdAddStream::parse_vm_instr_write_flow_var(const Json::Value &inst, Trex } void -TrexRpcCmdAddStream::parse_vm(const Json::Value &vm, TrexStream *stream, Json::Value &result) { +TrexRpcCmdAddStream::parse_vm(const Json::Value &vm, std::unique_ptr<TrexStream> &stream, Json::Value &result) { const Json::Value &instructions = parse_array(vm ,"instructions", result); @@ -386,7 +391,7 @@ TrexRpcCmdAddStream::parse_vm(const Json::Value &vm, TrexStream *stream, Json::V } void -TrexRpcCmdAddStream::validate_stream(const TrexStream *stream, Json::Value &result) { +TrexRpcCmdAddStream::validate_stream(const std::unique_ptr<TrexStream> &stream, Json::Value &result) { /* add the stream to the port's stream table */ TrexStatelessPort * port = get_stateless_obj()->get_port_by_id(stream->m_port_id); @@ -395,7 +400,6 @@ TrexRpcCmdAddStream::validate_stream(const TrexStream *stream, Json::Value &resu if (port->get_stream_by_id(stream->m_stream_id)) { std::stringstream ss; ss << "stream " << stream->m_stream_id << " already exists"; - delete stream; generate_execute_err(result, ss.str()); } diff --git a/src/rpc-server/commands/trex_rpc_cmds.h b/src/rpc-server/commands/trex_rpc_cmds.h index 3da1e4fa..d90d880e 100644 --- a/src/rpc-server/commands/trex_rpc_cmds.h +++ b/src/rpc-server/commands/trex_rpc_cmds.h @@ -24,6 +24,7 @@ limitations under the License. #include <trex_rpc_cmd_api.h> #include <json/json.h> +#include <memory> class TrexStream; @@ -91,16 +92,16 @@ TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveStream, "remove_stream", 2, tru TREX_RPC_CMD_DEFINE_EXTENDED(TrexRpcCmdAddStream, "add_stream", 3, true, /* extended part */ -TrexStream * allocate_new_stream(const Json::Value §ion, uint8_t port_id, uint32_t stream_id, Json::Value &result); -void validate_stream(const TrexStream *stream, Json::Value &result); -void parse_vm(const Json::Value &vm, TrexStream *stream, Json::Value &result); -void parse_vm_instr_checksum(const Json::Value &inst, TrexStream *stream, Json::Value &result); -void parse_vm_instr_flow_var(const Json::Value &inst, TrexStream *stream, Json::Value &result); -void parse_vm_instr_tuple_flow_var(const Json::Value &inst, TrexStream *stream, Json::Value &result); -void parse_vm_instr_trim_pkt_size(const Json::Value &inst, TrexStream *stream, Json::Value &result); -void parse_rate(const Json::Value &inst, TrexStream *stream, Json::Value &result); -void parse_vm_instr_write_flow_var(const Json::Value &inst, TrexStream *stream, Json::Value &result); -void parse_vm_instr_write_mask_flow_var(const Json::Value &inst, TrexStream *stream, Json::Value &result); +std::unique_ptr<TrexStream> allocate_new_stream(const Json::Value §ion, uint8_t port_id, uint32_t stream_id, Json::Value &result); +void validate_stream(const std::unique_ptr<TrexStream> &stream, Json::Value &result); +void parse_vm(const Json::Value &vm, std::unique_ptr<TrexStream> &stream, Json::Value &result); +void parse_vm_instr_checksum(const Json::Value &inst, std::unique_ptr<TrexStream> &stream, Json::Value &result); +void parse_vm_instr_flow_var(const Json::Value &inst, std::unique_ptr<TrexStream> &stream, Json::Value &result); +void parse_vm_instr_tuple_flow_var(const Json::Value &inst, std::unique_ptr<TrexStream> &stream, Json::Value &result); +void parse_vm_instr_trim_pkt_size(const Json::Value &inst, std::unique_ptr<TrexStream> &stream, Json::Value &result); +void parse_rate(const Json::Value &inst, std::unique_ptr<TrexStream> &stream, Json::Value &result); +void parse_vm_instr_write_flow_var(const Json::Value &inst, std::unique_ptr<TrexStream> &stream, Json::Value &result); +void parse_vm_instr_write_mask_flow_var(const Json::Value &inst, std::unique_ptr<TrexStream> &stream, Json::Value &result); ); diff --git a/src/sim/trex_sim.h b/src/sim/trex_sim.h index 8feb7bc0..99bfb28e 100644 --- a/src/sim/trex_sim.h +++ b/src/sim/trex_sim.h @@ -25,6 +25,7 @@ limitations under the License. #include <os_time.h> #include <bp_sim.h> #include <json/json.h> +#include <trex_stateless.h> int gtest_main(int argc, char **argv); @@ -32,12 +33,49 @@ class TrexStateless; class TrexPublisher; class DpToCpHandler; +void set_stateless_obj(TrexStateless *obj); static inline bool in_range(int x, int low, int high) { return ( (x >= low) && (x <= high) ); } +/*************** 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 { + driver_name = "TEST"; + speed = TrexPlatformApi::SPEED_10G; + } + + 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)); + } + } + + virtual void publish_async_data_now(uint32_t key) const { + + } + +private: + int m_dp_core_count; +}; + /** * interface for a sim target * @@ -67,12 +105,27 @@ public: * * @author imarom (28-Dec-15) */ -class SimGtest : public SimInterface { +class SimGtest : SimInterface { public: int run(int argc, char **argv) { + TrexStatelessCfg cfg; + + cfg.m_port_count = 1; + cfg.m_rpc_req_resp_cfg = NULL; + cfg.m_rpc_async_cfg = NULL; + cfg.m_rpc_server_verbose = false; + cfg.m_platform_api = new SimPlatformApi(1);; + cfg.m_publisher = NULL; + + set_stateless_obj(new TrexStateless(cfg)); assert( CMsgIns::Ins()->Create(4) ); - return gtest_main(argc, argv); + int rc = gtest_main(argc, argv); + + delete get_stateless_obj(); + set_stateless_obj(NULL); + + return rc; } }; @@ -112,9 +165,6 @@ public: int limit, bool is_dry_run); - TrexStateless * get_stateless_obj() { - return m_trex_stateless; - } void set_verbose(bool enable) { m_verbose = enable; @@ -149,7 +199,6 @@ private: return m_verbose; } - TrexStateless *m_trex_stateless; DpToCpHandler *m_dp_to_cp_handler; TrexPublisher *m_publisher; CFlowGenList m_fl; diff --git a/src/sim/trex_sim_stateless.cpp b/src/sim/trex_sim_stateless.cpp index 897d1fec..a8316034 100644 --- a/src/sim/trex_sim_stateless.cpp +++ b/src/sim/trex_sim_stateless.cpp @@ -54,10 +54,6 @@ static string format_num(double num, const string &suffix = "") { return "NaN"; } -TrexStateless * get_stateless_obj() { - return SimStateless::get_instance().get_stateless_obj(); -} - class SimRunException : public std::runtime_error { @@ -69,41 +65,6 @@ 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 { - driver_name = "TEST"; - speed = TrexPlatformApi::SPEED_10G; - } - - 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)); - } - } - - virtual void publish_async_data_now(uint32_t key) const { - - } - -private: - int m_dp_core_count; -}; /** * handler for DP to CP messages @@ -146,7 +107,6 @@ public: ************************/ SimStateless::SimStateless() { - m_trex_stateless = NULL; m_publisher = NULL; m_dp_to_cp_handler = NULL; m_verbose = false; @@ -198,9 +158,10 @@ SimStateless::run(const string &json_filename, SimStateless::~SimStateless() { - if (m_trex_stateless) { - delete m_trex_stateless; - m_trex_stateless = NULL; + + if (get_stateless_obj()) { + delete get_stateless_obj(); + set_stateless_obj(NULL); } if (m_publisher) { @@ -231,11 +192,11 @@ SimStateless::prepare_control_plane() { cfg.m_platform_api = new SimPlatformApi(m_dp_core_count); cfg.m_publisher = m_publisher; - m_trex_stateless = new TrexStateless(cfg); + set_stateless_obj(new TrexStateless(cfg)); - m_trex_stateless->launch_control_plane(); + get_stateless_obj()->launch_control_plane(); - for (auto &port : m_trex_stateless->get_port_list()) { + for (auto &port : get_stateless_obj()->get_port_list()) { port->acquire("test", 0, true); } @@ -274,7 +235,7 @@ SimStateless::execute_json(const std::string &json_filename) { buffer << test.rdbuf(); try { - rep = m_trex_stateless->get_rpc_server()->test_inject_request(buffer.str()); + rep = get_stateless_obj()->get_rpc_server()->test_inject_request(buffer.str()); } catch (TrexRpcException &e) { throw SimRunException(e.what()); } @@ -321,8 +282,10 @@ static inline bool is_debug() { void SimStateless::show_intro(const std::string &out_filename) { - uint64_t bps = 0; - uint64_t pps = 0; + double pps; + double bps_L1; + double bps_L2; + double percentage; std::cout << "\nGeneral info:\n"; std::cout << "------------\n\n"; @@ -356,10 +319,12 @@ SimStateless::show_intro(const std::string &out_filename) { std::cout << "stream count: " << port->get_stream_count() << "\n"; - port->get_port_effective_rate(bps, pps); + port->get_port_effective_rate(pps, bps_L1, bps_L2, percentage); - std::cout << "max BPS: " << format_num(bps, "bps") << "\n"; - std::cout << "max PPS: " << format_num(pps, "pps") << "\n"; + std::cout << "max PPS : " << format_num(pps, "pps") << "\n"; + std::cout << "max BPS L1 : " << format_num(bps_L1, "bps") << "\n"; + std::cout << "max BPS L2 : " << format_num(bps_L2, "bps") << "\n"; + std::cout << "line util. : " << format_num(percentage, "%") << "\n"; std::cout << "\n\nStarting simulation...\n"; } diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 8ee46d29..75f77cf7 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -631,7 +631,10 @@ TrexStatelessPort::validate(void) { void -TrexStatelessPort::get_port_effective_rate(uint64_t &bps, uint64_t &pps) { +TrexStatelessPort::get_port_effective_rate(double &pps, + double &bps_L1, + double &bps_L2, + double &percentage) { if (get_stream_count() == 0) { return; @@ -641,8 +644,11 @@ TrexStatelessPort::get_port_effective_rate(uint64_t &bps, uint64_t &pps) { generate_streams_graph(); } - bps = m_graph_obj->get_max_bps_l2() * m_factor; - pps = m_graph_obj->get_max_pps() * m_factor; + pps = m_graph_obj->get_max_pps() * m_factor; + bps_L1 = m_graph_obj->get_max_bps_l1() * m_factor; + bps_L2 = m_graph_obj->get_max_bps_l2() * m_factor; + percentage = (bps_L1 / get_port_speed_bps()) * 100.0; + } /************* Trex Port Owner **************/ diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index b0b0ddf3..a101cef0 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -316,10 +316,11 @@ public: * * @author imarom (07-Jan-16) * - * @param bps - * @param pps */ - void get_port_effective_rate(uint64_t &bps, uint64_t &pps); + void get_port_effective_rate(double &pps, + double &bps_L1, + double &bps_L2, + double &percentage); private: diff --git a/src/stateless/cp/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp index f4a8e800..357a2885 100644 --- a/src/stateless/cp/trex_stream.cpp +++ b/src/stateless/cp/trex_stream.cpp @@ -106,16 +106,16 @@ void TrexStream::Dump(FILE *fd){ fprintf(fd," rate :\n\n"); - fprintf(fd," pps : %f\n", get_rate().get_pps()); - fprintf(fd," bps L1 : %f\n", get_rate().get_bps_L1()); - fprintf(fd," bps L2 : %f\n", get_rate().get_bps_L2()); - fprintf(fd," percentage : %f\n", get_rate().get_percentage()); + fprintf(fd," pps : %f\n", m_rate.get_pps()); + fprintf(fd," bps L1 : %f\n", m_rate.get_bps_L1()); + fprintf(fd," bps L2 : %f\n", m_rate.get_bps_L2()); + fprintf(fd," percentage : %f\n", m_rate.get_percentage()); } TrexStream::TrexStream(uint8_t type, - uint8_t port_id, uint32_t stream_id) : m_port_id(port_id), m_stream_id(stream_id) { + uint8_t port_id, uint32_t stream_id) : m_port_id(port_id), m_stream_id(stream_id) , m_rate(*this) { /* default values */ m_type = type; @@ -160,18 +160,6 @@ TrexStream::get_stream_json() { return m_stream_json; } -TrexStreamRate & -TrexStream::get_rate() { - - /* lazy calculation of the rate */ - if (!m_rate.is_calculated()) { - TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(m_port_id); - double pkt_size = get_pkt_size(); - m_rate.calculate(pkt_size, port->get_port_speed_bps()); - } - - return m_rate; -} /************************************** * stream table @@ -253,3 +241,16 @@ int TrexStreamTable::size() { } +/************************************** + * TrexStreamRate + *************************************/ +uint64_t +TrexStreamRate::get_line_speed_bps() { + TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(m_stream.m_port_id); + return port->get_port_speed_bps(); +} + +double +TrexStreamRate::get_pkt_size() { + return m_stream.get_pkt_size(); +} diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index f4739569..66f05b16 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -103,6 +103,8 @@ public: } }; +class TrexStream; + /** * describes a stream rate * @@ -121,9 +123,21 @@ public: RATE_PERCENTAGE }; - TrexStreamRate() { - m_base_rate_type = RATE_INVALID; - m_is_calculated = false; + TrexStreamRate(TrexStream &stream) : m_stream(stream) { + m_pps = 0; + m_bps_L1 = 0; + m_bps_L2 = 0; + m_percentage = 0; + } + + + TrexStreamRate& operator=(const TrexStreamRate& other) { + m_pps = other.m_pps; + m_bps_L1 = other.m_bps_L1; + m_bps_L2 = other.m_bps_L2; + m_percentage = other.m_percentage; + + return (*this); } /** @@ -132,121 +146,133 @@ public: * */ void set_base_rate(rate_type_e type, double value) { - m_base_rate_type = type; - m_value = value; - m_is_calculated = false; - } - + m_pps = 0; + m_bps_L1 = 0; + m_bps_L2 = 0; + m_percentage = 0; - /** - * calculates all the rates from the base rate - * - */ - void calculate(uint16_t pkt_size, uint64_t line_bps) { + assert(value > 0); - switch (m_base_rate_type) { - + switch (type) { case RATE_PPS: - calculate_from_pps(m_value, pkt_size, line_bps); + m_pps = value; break; - case RATE_BPS_L1: - calculate_from_bps_L1(m_value, pkt_size, line_bps); + m_bps_L1 = value; break; - case RATE_BPS_L2: - calculate_from_bps_L2(m_value, pkt_size, line_bps); + m_bps_L2 = value; break; - case RATE_PERCENTAGE: - calculate_from_percentage(m_value, pkt_size, line_bps); + m_percentage = value; break; default: assert(0); + } - - m_is_calculated = true; - } - - - bool is_calculated() const { - return m_is_calculated; - } - - - /* update the rate by a factor */ - void update_factor(double factor) { - assert(m_is_calculated); - - m_pps *= factor; - m_bps_L1 *= factor; - m_bps_L2 *= factor; - m_percentage *= factor; } double get_pps() { - assert(m_is_calculated); + if (m_pps == 0) { + calculate(); + } return (m_pps); } double get_bps_L1() { - assert(m_is_calculated); + if (m_bps_L1 == 0) { + calculate(); + } return (m_bps_L1); } double get_bps_L2() { - assert(m_is_calculated); + if (m_bps_L2 == 0) { + calculate(); + } return m_bps_L2; } double get_percentage() { - assert(m_is_calculated); + if (m_percentage == 0) { + calculate(); + } return m_percentage; } + + + /* update the rate by a factor */ + void update_factor(double factor) { + /* if all are non zero - it works, if only one (base) is also works */ + m_pps *= factor; + m_bps_L1 *= factor; + m_bps_L2 *= factor; + m_percentage *= factor; + } + + + private: - void calculate_from_pps(double pps, uint16_t pkt_size, uint64_t line_bps) { - m_pps = pps; - m_bps_L1 = m_pps * (pkt_size + 24) * 8; - m_bps_L2 = m_pps * (pkt_size + 4) * 8; - m_percentage = (m_bps_L1 / line_bps) * 100.0; + /** + * calculates all the rates from the base rate + * + */ + void calculate() { + + if (m_pps != 0) { + calculate_from_pps(); + } else if (m_bps_L1 != 0) { + calculate_from_bps_L1(); + } else if (m_bps_L2 != 0) { + calculate_from_bps_L2(); + } else if (m_percentage != 0) { + calculate_from_percentage(); + } else { + assert(0); + } } - void calculate_from_bps_L1(double bps_L1, uint16_t pkt_size, uint64_t line_bps) { - m_bps_L1 = bps_L1; - m_bps_L2 = m_bps_L1 * ( (pkt_size + 4.0) / (pkt_size + 24.0) ); - m_pps = m_bps_L2 / (8 * (pkt_size + 4)); - m_percentage = (m_bps_L1 / line_bps) * 100.0; + uint64_t get_line_speed_bps(); + double get_pkt_size(); + + void calculate_from_pps() { + m_bps_L1 = m_pps * (get_pkt_size() + 24) * 8; + m_bps_L2 = m_pps * (get_pkt_size() + 4) * 8; + m_percentage = (m_bps_L1 / get_line_speed_bps()) * 100.0; } - void calculate_from_bps_L2(double bps_L2, uint16_t pkt_size, uint64_t line_bps) { - m_bps_L2 = bps_L2; - m_bps_L1 = m_bps_L2 * ( (pkt_size + 24.0) / (pkt_size + 4.0)); - m_pps = m_bps_L2 / (8 * (pkt_size + 4)); - m_percentage = (m_bps_L1 / line_bps) * 100.0; + void calculate_from_bps_L1() { + m_bps_L2 = m_bps_L1 * ( (get_pkt_size() + 4.0) / (get_pkt_size() + 24.0) ); + m_pps = m_bps_L2 / (8 * (get_pkt_size() + 4)); + m_percentage = (m_bps_L1 / get_line_speed_bps()) * 100.0; } - void calculate_from_percentage(double percentage, uint16_t pkt_size, uint64_t line_bps) { - m_percentage = percentage; - m_bps_L1 = (m_percentage / 100.0) * line_bps; - m_bps_L2 = m_bps_L1 * ( (pkt_size + 4.0) / (pkt_size + 24.0) ); - m_pps = m_bps_L2 / (8 * (pkt_size + 4)); + void calculate_from_bps_L2() { + m_bps_L1 = m_bps_L2 * ( (get_pkt_size() + 24.0) / (get_pkt_size() + 4.0)); + m_pps = m_bps_L2 / (8 * (get_pkt_size() + 4)); + m_percentage = (m_bps_L1 / get_line_speed_bps()) * 100.0; } - rate_type_e m_base_rate_type; - double m_value; + void calculate_from_percentage() { + m_bps_L1 = (m_percentage / 100.0) * get_line_speed_bps(); + m_bps_L2 = m_bps_L1 * ( (get_pkt_size() + 4.0) / (get_pkt_size() + 24.0) ); + m_pps = m_bps_L2 / (8 * (get_pkt_size() + 4)); + + } - bool m_is_calculated; double m_pps; double m_bps_L1; double m_bps_L2; double m_percentage; + /* reference to the owner class */ + TrexStream &m_stream; }; /** @@ -254,6 +280,7 @@ private: * */ class TrexStream { +friend class TrexStreamRate; public: enum STREAM_TYPE { @@ -298,19 +325,19 @@ public: double get_pps() { - return get_rate().get_pps(); + return m_rate.get_pps(); } double get_bps_L1() { - return get_rate().get_bps_L1(); + return m_rate.get_bps_L1(); } double get_bps_L2() { - return get_rate().get_bps_L2(); + return m_rate.get_bps_L2(); } double get_bw_percentage() { - return get_rate().get_percentage(); + return m_rate.get_percentage(); } void set_rate(TrexStreamRate::rate_type_e type, double value) { @@ -318,7 +345,7 @@ public: } void update_rate_factor(double factor) { - get_rate().update_factor(factor); + m_rate.update_factor(factor); } void set_type(uint8_t type){ @@ -502,9 +529,6 @@ private: } - /* get (and calculate if need) the rate of the stream */ - TrexStreamRate & get_rate(); - /* no access to this without a lazy build method */ TrexStreamRate m_rate; }; |