From c625b6e4f6d71176ef1db5aab93f4e66939d7a25 Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 6 Sep 2015 15:23:40 +0300 Subject: trex stateless changed to singleton. added some more commands (remove all, get list of streams) --- .../client_utils/jsonrpc_client.py | 6 +- src/rpc-server/commands/trex_rpc_cmd_general.cpp | 12 +++- src/rpc-server/commands/trex_rpc_cmd_stream.cpp | 74 +++++++++++++++++----- src/rpc-server/commands/trex_rpc_cmds.h | 2 + src/rpc-server/trex_rpc_cmds_table.cpp | 1 + src/rpc-server/trex_rpc_server.cpp | 1 + src/rpc-server/trex_rpc_server_api.h | 24 +++++++ src/rpc-server/trex_rpc_server_mock.cpp | 5 ++ src/stateless/trex_stateless.cpp | 32 ++++++---- src/stateless/trex_stateless_api.h | 40 +++++++++--- src/stateless/trex_stream.cpp | 16 +++-- src/stateless/trex_stream_api.h | 18 +++++- 12 files changed, 182 insertions(+), 49 deletions(-) diff --git a/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py b/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py index 054dc1a2..b44b1268 100644 --- a/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py +++ b/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py @@ -44,12 +44,12 @@ class JsonRpcClient(object): try: # int numbers - pretty_str = re.sub(r'([ ]*:[ ]*)(\-?[1-9][0-9]*[^.])',r'\1{0}\2{1}'.format(bcolors.BLUE, bcolors.ENDC), pretty_str) + pretty_str = re.sub(r'([ ]*:[ ]+)(\-?[1-9][0-9]*[^.])',r'\1{0}\2{1}'.format(bcolors.BLUE, bcolors.ENDC), pretty_str) # float - pretty_str = re.sub(r'([ ]*:[ ]*)(\-?[1-9][0-9]*\.[0-9]+)',r'\1{0}\2{1}'.format(bcolors.MAGENTA, bcolors.ENDC), pretty_str) + pretty_str = re.sub(r'([ ]*:[ ]+)(\-?[1-9][0-9]*\.[0-9]+)',r'\1{0}\2{1}'.format(bcolors.MAGENTA, bcolors.ENDC), pretty_str) # strings - pretty_str = re.sub(r'([ ]*:[ ]*)("[^"]*")',r'\1{0}\2{1}'.format(bcolors.RED, bcolors.ENDC), pretty_str) + pretty_str = re.sub(r'([ ]*:[ ]+)("[^"]*")',r'\1{0}\2{1}'.format(bcolors.RED, bcolors.ENDC), pretty_str) pretty_str = re.sub(r"('[^']*')", r'{0}\1{1}'.format(bcolors.MAGENTA, bcolors.RED), pretty_str) except : pass diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index 6b765aca..32952b1a 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -20,6 +20,7 @@ limitations under the License. */ #include "trex_rpc_cmds.h" #include +#include #ifndef TREX_RPC_MOCK_SERVER #include <../linux_dpdk/version.h> @@ -41,8 +42,7 @@ TrexRpcCmdGetStatus::_run(const Json::Value ¶ms, Json::Value &result) { section["general"]["version"] = VERSION_BUILD_NUM; section["general"]["build_date"] = get_build_date(); section["general"]["build_time"] = get_build_time(); - section["general"]["version_user"] = VERSION_USER; - section["general"]["uptime"] = TrexRpcServer::get_server_uptime(); + section["general"]["built_by"] = VERSION_USER; #else @@ -50,10 +50,16 @@ TrexRpcCmdGetStatus::_run(const Json::Value ¶ms, Json::Value &result) { section["general"]["build_date"] = __DATE__; section["general"]["build_time"] = __TIME__; section["general"]["version_user"] = "MOCK"; - section["general"]["uptime"] = TrexRpcServer::get_server_uptime(); #endif + section["general"]["uptime"] = TrexRpcServer::get_server_uptime(); + section["general"]["owner"] = TrexRpcServer::get_owner(); + + // ports + + section["ports"]["count"] = TrexStateless::get_instance().get_port_count(); + 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 3ddf07fa..6dfebe6d 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp @@ -52,21 +52,25 @@ TrexRpcCmdAddStream::_run(const Json::Value ¶ms, Json::Value &result) { stream->m_next_stream_id = parse_int(section, "next_stream_id", result); - const Json::Value &pkt = parse_array(section, "packet", result); + const Json::Value &pkt = parse_object(section, "packet", result); + const Json::Value &pkt_binary = parse_array(pkt, "binary", result); /* fetch the packet from the message */ - stream->m_pkt_len = pkt.size(); - stream->m_pkt = new uint8_t[pkt.size()]; - if (!stream->m_pkt) { + stream->m_pkt.len = pkt_binary.size(); + stream->m_pkt.binary = new uint8_t[pkt_binary.size()]; + if (!stream->m_pkt.binary) { generate_internal_err(result, "unable to allocate memory"); } /* parse the packet */ - for (int i = 0; i < pkt.size(); i++) { - stream->m_pkt[i] = parse_byte(pkt, i, result); + for (int i = 0; i < pkt_binary.size(); i++) { + stream->m_pkt.binary[i] = parse_byte(pkt_binary, i, result); } + /* meta data */ + stream->m_pkt.meta = parse_string(pkt, "meta", result); + /* parse RX info */ const Json::Value &rx = parse_object(section, "rx_stats", result); @@ -82,7 +86,7 @@ TrexRpcCmdAddStream::_run(const Json::Value ¶ms, Json::Value &result) { /* make sure this is a valid stream to add */ validate_stream(stream, result); - TrexStatelessPort *port = get_trex_stateless()->get_port_by_id(stream->m_port_id); + TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(stream->m_port_id); port->get_stream_table()->add_stream(stream); result["result"] = "ACK"; @@ -142,7 +146,7 @@ void TrexRpcCmdAddStream::validate_stream(const TrexStream *stream, Json::Value &result) { /* check packet size */ - if ( (stream->m_pkt_len < TrexStream::MIN_PKT_SIZE_BYTES) || (stream->m_pkt_len > TrexStream::MAX_PKT_SIZE_BYTES) ) { + if ( (stream->m_pkt.len < TrexStream::MIN_PKT_SIZE_BYTES) || (stream->m_pkt.len > TrexStream::MAX_PKT_SIZE_BYTES) ) { std::stringstream ss; ss << "bad packet size provided: should be between " << TrexStream::MIN_PKT_SIZE_BYTES << " and " << TrexStream::MAX_PKT_SIZE_BYTES; delete stream; @@ -150,15 +154,15 @@ TrexRpcCmdAddStream::validate_stream(const TrexStream *stream, Json::Value &resu } /* port id should be between 0 and count - 1 */ - if (stream->m_port_id >= get_trex_stateless()->get_port_count()) { + if (stream->m_port_id >= TrexStateless::get_instance().get_port_count()) { std::stringstream ss; - ss << "invalid port id - should be between 0 and " << (int)get_trex_stateless()->get_port_count() - 1; + ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1; delete stream; generate_execute_err(result, ss.str()); } /* add the stream to the port's stream table */ - TrexStatelessPort * port = get_trex_stateless()->get_port_by_id(stream->m_port_id); + TrexStatelessPort * port = TrexStateless::get_instance().get_port_by_id(stream->m_port_id); /* does such a stream exists ? */ if (port->get_stream_table()->get_stream_by_id(stream->m_stream_id)) { @@ -180,13 +184,13 @@ TrexRpcCmdRemoveStream::_run(const Json::Value ¶ms, Json::Value &result) { uint32_t stream_id = parse_int(params, "stream_id", result); - if (port_id >= get_trex_stateless()->get_port_count()) { + if (port_id >= TrexStateless::get_instance().get_port_count()) { std::stringstream ss; - ss << "invalid port id - should be between 0 and " << (int)get_trex_stateless()->get_port_count() - 1; + ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1; generate_execute_err(result, ss.str()); } - TrexStatelessPort *port = get_trex_stateless()->get_port_by_id(port_id); + TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id); TrexStream *stream = port->get_stream_table()->get_stream_by_id(stream_id); if (!stream) { @@ -198,6 +202,8 @@ TrexRpcCmdRemoveStream::_run(const Json::Value ¶ms, Json::Value &result) { port->get_stream_table()->remove_stream(stream); result["result"] = "ACK"; + + return (TREX_RPC_CMD_OK); } /*************************** @@ -209,15 +215,49 @@ trex_rpc_cmd_rc_e TrexRpcCmdRemoveAllStreams::_run(const Json::Value ¶ms, Json::Value &result) { uint8_t port_id = parse_byte(params, "port_id", result); - if (port_id >= get_trex_stateless()->get_port_count()) { + if (port_id >= TrexStateless::get_instance().get_port_count()) { std::stringstream ss; - ss << "invalid port id - should be between 0 and " << (int)get_trex_stateless()->get_port_count() - 1; + ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1; generate_execute_err(result, ss.str()); } - TrexStatelessPort *port = get_trex_stateless()->get_port_by_id(port_id); + TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id); port->get_stream_table()->remove_and_delete_all_streams(); result["result"] = "ACK"; + + return (TREX_RPC_CMD_OK); +} + +/*************************** + * get all streams configured + * on specific port + * + **************************/ +trex_rpc_cmd_rc_e +TrexRpcCmdGetStreamList::_run(const Json::Value ¶ms, Json::Value &result) { + std::vector stream_list; + + uint8_t port_id = parse_byte(params, "port_id", result); + + if (port_id >= TrexStateless::get_instance().get_port_count()) { + std::stringstream ss; + ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1; + generate_execute_err(result, ss.str()); + } + + TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id); + + port->get_stream_table()->get_stream_list(stream_list); + + Json::Value json_list = Json::arrayValue; + + for (auto stream_id : stream_list) { + json_list.append(stream_id); + } + + result["result"] = json_list; + + return (TREX_RPC_CMD_OK); } diff --git a/src/rpc-server/commands/trex_rpc_cmds.h b/src/rpc-server/commands/trex_rpc_cmds.h index 64551fac..e9666f21 100644 --- a/src/rpc-server/commands/trex_rpc_cmds.h +++ b/src/rpc-server/commands/trex_rpc_cmds.h @@ -74,4 +74,6 @@ void validate_stream(const TrexStream *stream, Json::Value &result); ); +TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStreamList, "get_stream_list", 1); + #endif /* __TREX_RPC_CMD_H__ */ diff --git a/src/rpc-server/trex_rpc_cmds_table.cpp b/src/rpc-server/trex_rpc_cmds_table.cpp index 7d5d49ae..fc6d7b87 100644 --- a/src/rpc-server/trex_rpc_cmds_table.cpp +++ b/src/rpc-server/trex_rpc_cmds_table.cpp @@ -38,6 +38,7 @@ TrexRpcCommandsTable::TrexRpcCommandsTable() { register_command(new TrexRpcCmdAddStream()); register_command(new TrexRpcCmdRemoveStream()); register_command(new TrexRpcCmdRemoveAllStreams()); + register_command(new TrexRpcCmdGetStreamList()); } TrexRpcCommandsTable::~TrexRpcCommandsTable() { diff --git a/src/rpc-server/trex_rpc_server.cpp b/src/rpc-server/trex_rpc_server.cpp index 6b8c200d..149bb668 100644 --- a/src/rpc-server/trex_rpc_server.cpp +++ b/src/rpc-server/trex_rpc_server.cpp @@ -111,6 +111,7 @@ get_current_date_time() { } const std::string TrexRpcServer::s_server_uptime = get_current_date_time(); +std::string TrexRpcServer::s_owner = "none"; TrexRpcServer::TrexRpcServer(const TrexRpcServerConfig &req_resp_cfg) { diff --git a/src/rpc-server/trex_rpc_server_api.h b/src/rpc-server/trex_rpc_server_api.h index ab1bc454..b4313670 100644 --- a/src/rpc-server/trex_rpc_server_api.h +++ b/src/rpc-server/trex_rpc_server_api.h @@ -163,10 +163,34 @@ public: return s_server_uptime; } + + /** + * query for ownership + * + */ + static const std::string &get_owner() { + return s_owner; + } + + /** + * take ownership of the server array + * this is static + * ownership is total + * + */ + static void set_owner(const std::string &owner) { + s_owner = owner; + } + + static void clear_owner() { + s_owner = "none"; + } + private: std::vector m_servers; bool m_verbose; static const std::string s_server_uptime; + static std::string s_owner; }; #endif /* __TREX_RPC_SERVER_API_H__ */ diff --git a/src/rpc-server/trex_rpc_server_mock.cpp b/src/rpc-server/trex_rpc_server_mock.cpp index 98d1f35d..a248558e 100644 --- a/src/rpc-server/trex_rpc_server_mock.cpp +++ b/src/rpc-server/trex_rpc_server_mock.cpp @@ -20,6 +20,8 @@ limitations under the License. */ #include +#include + #include #include @@ -54,6 +56,9 @@ int main(int argc, char *argv[]) { cout << "\n-= Starting RPC Server Mock =-\n\n"; cout << "Listening on tcp://localhost:5050 [ZMQ]\n\n"; + /* configure the stateless object with 4 ports */ + TrexStateless::configure(4); + TrexRpcServerConfig rpc_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5050); TrexRpcServer rpc(rpc_cfg); diff --git a/src/stateless/trex_stateless.cpp b/src/stateless/trex_stateless.cpp index 05931983..ff469d7e 100644 --- a/src/stateless/trex_stateless.cpp +++ b/src/stateless/trex_stateless.cpp @@ -24,13 +24,30 @@ limitations under the License. * Trex stateless object * **********************************************************/ -TrexStateless::TrexStateless(uint8_t port_count) : m_port_count(port_count) { +TrexStateless::TrexStateless() { + m_is_configured = false; +} - m_ports = new TrexStatelessPort*[port_count]; +/** + * one time configuration of the stateless object + * + */ +void TrexStateless::configure(uint8_t port_count) { - for (int i = 0; i < m_port_count; i++) { - m_ports[i] = new TrexStatelessPort(i); + 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() { @@ -54,10 +71,3 @@ uint8_t TrexStateless::get_port_count() { return m_port_count; } -/******** HACK - REMOVE ME ***********/ -TrexStateless * get_trex_stateless() { - static TrexStateless trex_stateless(8); - return &trex_stateless; - -} - diff --git a/src/stateless/trex_stateless_api.h b/src/stateless/trex_stateless_api.h index 6406a946..edd7b051 100644 --- a/src/stateless/trex_stateless_api.h +++ b/src/stateless/trex_stateless_api.h @@ -71,26 +71,48 @@ private: */ class TrexStateless { public: + /** - * create a T-Rex stateless object - * - * @author imarom (31-Aug-15) + * 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 * - * @param port_count */ - TrexStateless(uint8_t port_count); - ~TrexStateless(); + 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; }; -/****** HACK *******/ -TrexStateless *get_trex_stateless(); - #endif /* __TREX_STATELESS_API_H__ */ diff --git a/src/stateless/trex_stream.cpp b/src/stateless/trex_stream.cpp index 1465b1ba..b3919770 100644 --- a/src/stateless/trex_stream.cpp +++ b/src/stateless/trex_stream.cpp @@ -32,16 +32,16 @@ TrexStream::TrexStream(uint8_t port_id, uint32_t stream_id) : m_port_id(port_id) m_enabled = false; m_self_start = false; - m_pkt = NULL; - m_pkt_len = 0; + m_pkt.binary = NULL; + m_pkt.len = 0; m_rx_check.m_enable = false; } TrexStream::~TrexStream() { - if (m_pkt) { - delete [] m_pkt; + if (m_pkt.binary) { + delete [] m_pkt.binary; } } @@ -91,3 +91,11 @@ TrexStream * TrexStreamTable::get_stream_by_id(uint32_t stream_id) { return NULL; } } + +void TrexStreamTable::get_stream_list(std::vector &stream_list) { + stream_list.clear(); + + for (auto stream : m_stream_table) { + stream_list.push_back(stream.first); + } +} diff --git a/src/stateless/trex_stream_api.h b/src/stateless/trex_stream_api.h index f57b7aae..97e0b7f7 100644 --- a/src/stateless/trex_stream_api.h +++ b/src/stateless/trex_stream_api.h @@ -22,7 +22,9 @@ limitations under the License. #define __TREX_STREAM_API_H__ #include +#include #include +#include class TrexRpcCmdAddStream; @@ -58,8 +60,11 @@ private: bool m_self_start; /* pkt */ - uint8_t *m_pkt; - uint16_t m_pkt_len; + struct { + uint8_t *binary; + uint16_t len; + std::string meta; + } m_pkt; /* VM */ @@ -157,6 +162,15 @@ public: */ TrexStream * get_stream_by_id(uint32_t stream_id); + /** + * populate a list with all the stream IDs + * + * @author imarom (06-Sep-15) + * + * @param stream_list + */ + void get_stream_list(std::vector &stream_list); + private: /** * holds all the stream in a hash table by stream id -- cgit 1.2.3-korg