From 54f8323b3938bf4ab672cde01a06711bfc522a2e Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 9 Sep 2015 18:06:12 +0300 Subject: added ownership to RPC server --- src/gtest/rpc_test.cpp | 126 ++++++++++++++++------- src/rpc-server/commands/trex_rpc_cmd_general.cpp | 53 ++++++++++ src/rpc-server/commands/trex_rpc_cmd_stream.cpp | 4 +- src/rpc-server/commands/trex_rpc_cmds.h | 38 ++++--- src/rpc-server/trex_rpc_cmd.cpp | 18 ++++ src/rpc-server/trex_rpc_cmd_api.h | 18 +++- src/rpc-server/trex_rpc_cmds_table.cpp | 6 ++ src/rpc-server/trex_rpc_server.cpp | 20 ++++ src/rpc-server/trex_rpc_server_api.h | 28 ++++- src/stateless/trex_stream_api.h | 12 +-- 10 files changed, 262 insertions(+), 61 deletions(-) diff --git a/src/gtest/rpc_test.cpp b/src/gtest/rpc_test.cpp index 8a7e9176..767560b0 100644 --- a/src/gtest/rpc_test.cpp +++ b/src/gtest/rpc_test.cpp @@ -30,6 +30,32 @@ using namespace std; class RpcTest : public testing::Test { + void take_ownership(void) { + Json::Value request; + Json::Value response; + + create_request(request, "aquire", 1 , false); + + request["params"]["user"] = "test"; + request["params"]["force"] = true; + + send_request(request, response); + + EXPECT_TRUE(response["result"] != Json::nullValue); + m_ownership_handler = response["result"].asString(); + } + + void release_ownership() { + Json::Value request; + Json::Value response; + + create_request(request, "release", 1 , false); + request["params"]["handler"] = m_ownership_handler; + + send_request(request, response); + EXPECT_TRUE(response["result"] == "ACK"); + } + virtual void SetUp() { TrexRpcServerConfig cfg = TrexRpcServerConfig(TrexRpcServerConfig::RPC_PROT_TCP, 5050); @@ -39,6 +65,8 @@ class RpcTest : public testing::Test { m_context = zmq_ctx_new (); m_socket = zmq_socket (m_context, ZMQ_REQ); zmq_connect (m_socket, "tcp://localhost:5050"); + + take_ownership(); } virtual void TearDown() { @@ -50,6 +78,33 @@ class RpcTest : public testing::Test { } public: + + void create_request(Json::Value &request, const string &method, int id = 1, bool ownership = false) { + request.clear(); + + request["jsonrpc"] = "2.0"; + request["id"] = id; + request["method"] = method; + + if (ownership) { + request["params"]["handler"] = m_ownership_handler; + } + } + + void send_request(const Json::Value &request, Json::Value &response) { + Json::FastWriter writer; + Json::Reader reader; + + response.clear(); + + string request_str = writer.write(request); + string ret = send_msg(request_str); + + EXPECT_TRUE(reader.parse(ret, response, false)); + EXPECT_EQ(response["jsonrpc"], "2.0"); + EXPECT_EQ(response["id"], request["id"]); + } + string send_msg(const string &msg) { char buffer[512]; @@ -62,6 +117,7 @@ public: TrexRpcServer *m_rpc; void *m_context; void *m_socket; + string m_ownership_handler; }; TEST_F(RpcTest, basic_rpc_test) { @@ -230,42 +286,48 @@ TEST_F(RpcTest, add_stream) { Json::Value response; Json::Reader reader; - string resp_str; + create_request(request, "get_stream", 1, true); - // check the stream does not exists - string lookup_str = "{\"jsonrpc\":\"2.0\", \"id\":1, \"method\":\"get_stream\", \"params\":{\"port_id\":1, \"stream_id\":5}}"; - resp_str = send_msg(lookup_str); + request["params"]["port_id"] = 1; + request["params"]["stream_id"] = 5; + + send_request(request, response); - EXPECT_TRUE(reader.parse(resp_str, response, false)); EXPECT_EQ(response["jsonrpc"], "2.0"); EXPECT_EQ(response["id"], 1); - EXPECT_EQ(response["error"]["code"], -32000); // add it + create_request(request, "add_stream", 1, true); + request["params"]["port_id"] = 1; + request["params"]["stream_id"] = 5; + request["params"]["stream"]["mode"]["type"] = "continuous"; + request["params"]["stream"]["mode"]["pps"] = 3; + request["params"]["stream"]["isg"] = 4.3; + request["params"]["stream"]["enabled"] = true; + request["params"]["stream"]["self_start"] = true; + request["params"]["stream"]["next_stream_id"] = -1; + + request["params"]["stream"]["packet"]["meta"] = "dummy"; + request["params"]["stream"]["packet"]["binary"][0] = 4; + request["params"]["stream"]["packet"]["binary"][1] = 1; + request["params"]["stream"]["packet"]["binary"][2] = 255; + + request["params"]["stream"]["vm"] = Json::arrayValue; + request["params"]["stream"]["rx_stats"]["enabled"] = false; + + send_request(request, response); - string add_str = "{\"jsonrpc\":\"2.0\", \"id\":1, \"method\":\"add_stream\", \"params\":" - "{\"port_id\":1, \"stream_id\":5, \"stream\":{" - "\"mode\": {\"type\":\"continuous\", \"pps\":3}," - "\"isg\":4.3, \"enabled\":true, \"self_start\":true," - "\"next_stream_id\":-1," - "\"packet\":{\"binary\":[4,1,255], \"meta\":\"dummy\"}," - "\"vm\":[]," - "\"rx_stats\":{\"enabled\":false}}}}"; + EXPECT_EQ(response["result"], "ACK"); - resp_str = send_msg(add_str); + /* get it */ - EXPECT_TRUE(reader.parse(resp_str, response, false)); - EXPECT_EQ(response["jsonrpc"], "2.0"); - EXPECT_EQ(response["id"], 1); + create_request(request, "get_stream", 1, true); - EXPECT_EQ(response["result"], "ACK"); + request["params"]["port_id"] = 1; + request["params"]["stream_id"] = 5; - resp_str = send_msg(lookup_str); - - EXPECT_TRUE(reader.parse(resp_str, response, false)); - EXPECT_EQ(response["jsonrpc"], "2.0"); - EXPECT_EQ(response["id"], 1); + send_request(request, response); const Json::Value &stream = response["result"]["stream"]; @@ -286,23 +348,17 @@ TEST_F(RpcTest, add_stream) { EXPECT_EQ(stream["mode"]["pps"], 3); // remove it + create_request(request, "remove_stream", 1, true); - string remove_str = "{\"jsonrpc\":\"2.0\", \"id\":1, \"method\":\"remove_stream\", \"params\":{\"port_id\":1, \"stream_id\":5}}"; - resp_str = send_msg(remove_str); + request["params"]["port_id"] = 1; + request["params"]["stream_id"] = 5; - EXPECT_TRUE(reader.parse(resp_str, response, false)); - EXPECT_EQ(response["jsonrpc"], "2.0"); - EXPECT_EQ(response["id"], 1); + send_request(request, response); EXPECT_EQ(response["result"], "ACK"); - resp_str = send_msg(remove_str); - // should not be present anymore - - EXPECT_TRUE(reader.parse(resp_str, response, false)); - EXPECT_EQ(response["jsonrpc"], "2.0"); - EXPECT_EQ(response["id"], 1); + send_request(request, response); EXPECT_EQ(response["error"]["code"], -32000); diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index 32952b1a..d5aa3a90 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -63,3 +63,56 @@ TrexRpcCmdGetStatus::_run(const Json::Value ¶ms, Json::Value &result) { return (TREX_RPC_CMD_OK); } +/** + * returns the current owner of the device + * + * @author imarom (08-Sep-15) + * + * @param params + * @param result + * + * @return trex_rpc_cmd_rc_e + */ +trex_rpc_cmd_rc_e +TrexRpcCmdGetOwner::_run(const Json::Value ¶ms, Json::Value &result) { + Json::Value §ion = result["result"]; + + section["owner"] = TrexRpcServer::get_owner(); + + return (TREX_RPC_CMD_OK); +} + +/** + * acquire device + * + */ +trex_rpc_cmd_rc_e +TrexRpcCmdAcquire::_run(const Json::Value ¶ms, Json::Value &result) { + + const string &new_owner = parse_string(params, "user", result); + bool force = parse_bool(params, "force", result); + + /* if not free and not you and not force - fail */ + if ( (!TrexRpcServer::is_free_to_aquire()) && (TrexRpcServer::get_owner() != new_owner) && (!force)) { + generate_execute_err(result, "device is already taken by '" + TrexRpcServer::get_owner() + "'"); + } + + string handle = TrexRpcServer::set_owner(new_owner); + + result["result"] = handle; + + return (TREX_RPC_CMD_OK); +} + +/** + * release device + * + */ +trex_rpc_cmd_rc_e +TrexRpcCmdRelease::_run(const Json::Value ¶ms, Json::Value &result) { + TrexRpcServer::clear_owner(); + + result["result"] = "ACK"; + + 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 90b55ea8..b62d213b 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp @@ -136,13 +136,13 @@ TrexRpcCmdAddStream::allocate_new_stream(const Json::Value §ion, uint8_t por } else if (type == "single_burst") { uint32_t total_pkts = parse_int(mode, "total_pkts", result); - uint32_t pps = parse_int(mode, "pps", result); + double pps = parse_double(mode, "pps", result); stream = new TrexStreamBurst(port_id, stream_id, total_pkts, pps); } else if (type == "multi_burst") { - uint32_t pps = parse_int(mode, "pps", result); + double pps = parse_double(mode, "pps", result); double ibg_usec = parse_double(mode, "ibg", result); uint32_t num_bursts = parse_int(mode, "number_of_bursts", result); uint32_t pkts_per_burst = parse_int(mode, "pkts_per_burst", result); diff --git a/src/rpc-server/commands/trex_rpc_cmds.h b/src/rpc-server/commands/trex_rpc_cmds.h index f88631bc..32138195 100644 --- a/src/rpc-server/commands/trex_rpc_cmds.h +++ b/src/rpc-server/commands/trex_rpc_cmds.h @@ -35,37 +35,45 @@ class TrexStream; * syntactic sugar for creating a simple command */ -#define TREX_RPC_CMD_DEFINE_EXTENED(class_name, cmd_name, param_count, ext) \ +#define TREX_RPC_CMD_DEFINE_EXTENED(class_name, cmd_name, param_count, needs_ownership, ext) \ class class_name : public TrexRpcCommand { \ public: \ - class_name () : TrexRpcCommand(cmd_name, param_count) {} \ + class_name () : TrexRpcCommand(cmd_name, param_count, needs_ownership) {} \ protected: \ virtual trex_rpc_cmd_rc_e _run(const Json::Value ¶ms, Json::Value &result); \ ext \ } -#define TREX_RPC_CMD_DEFINE(class_name, cmd_name, param_count) TREX_RPC_CMD_DEFINE_EXTENED(class_name, cmd_name, param_count, ;) +#define TREX_RPC_CMD_DEFINE(class_name, cmd_name, param_count, needs_ownership) TREX_RPC_CMD_DEFINE_EXTENED(class_name, cmd_name, param_count, needs_ownership, ;) /** * test cmds */ -TREX_RPC_CMD_DEFINE(TrexRpcCmdTestAdd, "test_add", 2); -TREX_RPC_CMD_DEFINE(TrexRpcCmdTestSub, "test_sub", 2); +TREX_RPC_CMD_DEFINE(TrexRpcCmdTestAdd, "test_add", 2, false); +TREX_RPC_CMD_DEFINE(TrexRpcCmdTestSub, "test_sub", 2, false); /** * general cmds */ -TREX_RPC_CMD_DEFINE(TrexRpcCmdPing, "ping", 0); -TREX_RPC_CMD_DEFINE(TrexRpcCmdGetReg, "get_reg_cmds", 0); -TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStatus, "get_status", 0); +TREX_RPC_CMD_DEFINE(TrexRpcCmdPing, "ping", 0, false); +TREX_RPC_CMD_DEFINE(TrexRpcCmdGetReg, "get_reg_cmds", 0, false); +TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStatus, "get_status", 0, false); + +/** + * ownership + */ +TREX_RPC_CMD_DEFINE(TrexRpcCmdGetOwner, "get_owner", 0, false); +TREX_RPC_CMD_DEFINE(TrexRpcCmdAcquire, "acquire", 2, false); +TREX_RPC_CMD_DEFINE(TrexRpcCmdRelease, "release", 0, true); + /** * stream cmds */ -TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveAllStreams, "remove_all_streams", 1); -TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveStream, "remove_stream", 2); +TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveAllStreams, "remove_all_streams", 1, true); +TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveStream, "remove_stream", 2, true); -TREX_RPC_CMD_DEFINE_EXTENED(TrexRpcCmdAddStream, "add_stream", 3, +TREX_RPC_CMD_DEFINE_EXTENED(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); @@ -77,11 +85,11 @@ void parse_vm_instr_write_flow_var(const Json::Value &inst, TrexStream *stream, ); -TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStreamList, "get_stream_list", 1); +TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStreamList, "get_stream_list", 1, true); -TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStream, "get_stream", 2); +TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStream, "get_stream", 2, true); -TREX_RPC_CMD_DEFINE(TrexRpcCmdStartTraffic, "start_traffic", 1); -TREX_RPC_CMD_DEFINE(TrexRpcCmdStopTraffic, "stop_traffic", 1); +TREX_RPC_CMD_DEFINE(TrexRpcCmdStartTraffic, "start_traffic", 1, true); +TREX_RPC_CMD_DEFINE(TrexRpcCmdStopTraffic, "stop_traffic", 1, true); #endif /* __TREX_RPC_CMD_H__ */ diff --git a/src/rpc-server/trex_rpc_cmd.cpp b/src/rpc-server/trex_rpc_cmd.cpp index 3fc77f71..437e8b1a 100644 --- a/src/rpc-server/trex_rpc_cmd.cpp +++ b/src/rpc-server/trex_rpc_cmd.cpp @@ -19,6 +19,7 @@ See the License for the specific language governing permissions and limitations under the License. */ #include +#include trex_rpc_cmd_rc_e TrexRpcCommand::run(const Json::Value ¶ms, Json::Value &result) { @@ -26,8 +27,16 @@ TrexRpcCommand::run(const Json::Value ¶ms, Json::Value &result) { /* the internal run can throw a parser error / other error */ try { + check_param_count(params, m_param_count, result); + + if (m_needs_ownership) { + verify_ownership(params, result); + } + + /* run the command itself*/ rc = _run(params, result); + } catch (TrexRpcCommandException &e) { return e.get_rc(); } @@ -45,6 +54,15 @@ TrexRpcCommand::check_param_count(const Json::Value ¶ms, int expected, Json: } } +void +TrexRpcCommand::verify_ownership(const Json::Value ¶ms, Json::Value &result) { + std::string handler = parse_string(params, "handler", result); + + if (!TrexRpcServer::verify_owner_handler(handler)) { + generate_execute_err(result, "invalid handler provided. please pass the handler given when calling 'acquire' or take ownership"); + } +} + const char * TrexRpcCommand::type_to_str(field_type_e type) { switch (type) { diff --git a/src/rpc-server/trex_rpc_cmd_api.h b/src/rpc-server/trex_rpc_cmd_api.h index def52fca..c72b3e3b 100644 --- a/src/rpc-server/trex_rpc_cmd_api.h +++ b/src/rpc-server/trex_rpc_cmd_api.h @@ -68,8 +68,15 @@ public: /** * method name and params */ - TrexRpcCommand(const std::string &method_name, int param_count) : m_name(method_name), m_param_count(param_count) { - + TrexRpcCommand(const std::string &method_name, int param_count, bool needs_ownership) : + m_name(method_name), + m_param_count(param_count), + m_needs_ownership(needs_ownership) { + + /* if needs ownership - another field is needed (handler) */ + if (m_needs_ownership) { + m_param_count++; + } } /** @@ -111,6 +118,12 @@ protected: */ void check_param_count(const Json::Value ¶ms, int expected, Json::Value &result); + /** + * verify ownership + * + */ + void verify_ownership(const Json::Value ¶ms, Json::Value &result); + /** * parse functions * @@ -209,6 +222,7 @@ protected: /* RPC command name */ std::string m_name; int m_param_count; + bool m_needs_ownership; }; #endif /* __TREX_RPC_CMD_API_H__ */ diff --git a/src/rpc-server/trex_rpc_cmds_table.cpp b/src/rpc-server/trex_rpc_cmds_table.cpp index 71668994..f968bb74 100644 --- a/src/rpc-server/trex_rpc_cmds_table.cpp +++ b/src/rpc-server/trex_rpc_cmds_table.cpp @@ -30,9 +30,15 @@ TrexRpcCommandsTable::TrexRpcCommandsTable() { /* add the test command (for gtest) */ register_command(new TrexRpcCmdTestAdd()); register_command(new TrexRpcCmdTestSub()); + + + /* general */ register_command(new TrexRpcCmdPing()); register_command(new TrexRpcCmdGetReg()); register_command(new TrexRpcCmdGetStatus()); + register_command(new TrexRpcCmdGetOwner()); + register_command(new TrexRpcCmdAcquire()); + register_command(new TrexRpcCmdRelease()); /* stream commands */ register_command(new TrexRpcCmdAddStream()); diff --git a/src/rpc-server/trex_rpc_server.cpp b/src/rpc-server/trex_rpc_server.cpp index 149bb668..a5988cab 100644 --- a/src/rpc-server/trex_rpc_server.cpp +++ b/src/rpc-server/trex_rpc_server.cpp @@ -112,6 +112,7 @@ get_current_date_time() { const std::string TrexRpcServer::s_server_uptime = get_current_date_time(); std::string TrexRpcServer::s_owner = "none"; +std::string TrexRpcServer::s_owner_handler = ""; TrexRpcServer::TrexRpcServer(const TrexRpcServerConfig &req_resp_cfg) { @@ -157,3 +158,22 @@ void TrexRpcServer::set_verbose(bool verbose) { } } +/** + * generate a random connection handler + * + */ +std::string TrexRpcServer::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/rpc-server/trex_rpc_server_api.h b/src/rpc-server/trex_rpc_server_api.h index b4313670..c34ac0f8 100644 --- a/src/rpc-server/trex_rpc_server_api.h +++ b/src/rpc-server/trex_rpc_server_api.h @@ -172,25 +172,51 @@ public: return s_owner; } + /** + * owner handler + * for the connection + * + */ + static const std::string &get_owner_handler() { + return s_owner_handler; + } + + static bool is_free_to_aquire() { + return (s_owner == "none"); + } + /** * take ownership of the server array * this is static * ownership is total * */ - static void set_owner(const std::string &owner) { + static std::string set_owner(const std::string &owner) { s_owner = owner; + s_owner_handler = generate_handler(); + return (s_owner_handler); } static void clear_owner() { s_owner = "none"; + s_owner_handler = ""; + } + + static bool verify_owner_handler(const std::string &handler) { + + return ( (s_owner != "none") && (s_owner_handler == handler) ); + } private: + static std::string generate_handler(); + std::vector m_servers; bool m_verbose; static const std::string s_server_uptime; + static std::string s_owner; + static std::string s_owner_handler; }; #endif /* __TREX_RPC_SERVER_API_H__ */ diff --git a/src/stateless/trex_stream_api.h b/src/stateless/trex_stream_api.h index 26999751..0a955ff7 100644 --- a/src/stateless/trex_stream_api.h +++ b/src/stateless/trex_stream_api.h @@ -90,15 +90,15 @@ private: */ class TrexStreamContinuous : public TrexStream { public: - TrexStreamContinuous(uint8_t port_id, uint32_t stream_id, uint32_t pps) : TrexStream(port_id, stream_id), m_pps(pps) { + TrexStreamContinuous(uint8_t port_id, uint32_t stream_id, double pps) : TrexStream(port_id, stream_id), m_pps(pps) { } - uint32_t get_pps() { + double get_pps() { return m_pps; } protected: - uint32_t m_pps; + double m_pps; }; /** @@ -107,7 +107,7 @@ protected: */ class TrexStreamBurst : public TrexStream { public: - TrexStreamBurst(uint8_t port_id, uint32_t stream_id, uint32_t total_pkts, uint32_t pps) : + TrexStreamBurst(uint8_t port_id, uint32_t stream_id, uint32_t total_pkts, double pps) : TrexStream(port_id, stream_id), m_total_pkts(total_pkts), m_pps(pps) { @@ -115,7 +115,7 @@ public: protected: uint32_t m_total_pkts; - uint32_t m_pps; + double m_pps; }; /** @@ -127,7 +127,7 @@ public: TrexStreamMultiBurst(uint8_t port_id, uint32_t stream_id, uint32_t pkts_per_burst, - uint32_t pps, + double pps, uint32_t num_bursts, double ibg_usec) : TrexStreamBurst(port_id, stream_id, pkts_per_burst, pps), m_num_bursts(num_bursts), m_ibg_usec(ibg_usec) { -- cgit 1.2.3-korg From dd99c3890d3bb7b4aab833927e85648cd6e86c85 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 16 Sep 2015 16:22:48 +0300 Subject: added many tests to the RPC server also, few tweaks for handling RPC server errors --- .../client_utils/jsonrpc_client.py | 2 +- src/gtest/rpc_test.cpp | 355 +++++++++++++++------ src/rpc-server/commands/trex_rpc_cmd_general.cpp | 161 +++++++++- src/rpc-server/commands/trex_rpc_cmd_stream.cpp | 40 +-- src/rpc-server/commands/trex_rpc_cmd_test.cpp | 30 -- src/rpc-server/commands/trex_rpc_cmds.h | 21 +- src/rpc-server/trex_rpc_cmds_table.cpp | 5 +- src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp | 8 + src/rpc-server/trex_rpc_jsonrpc_v2_parser.h | 9 + src/rpc-server/trex_rpc_req_resp_server.cpp | 27 ++ src/rpc-server/trex_rpc_req_resp_server.h | 4 +- src/stateless/trex_stateless.cpp | 30 +- src/stateless/trex_stateless_api.h | 51 ++- src/stateless/trex_stream.cpp | 11 + src/stateless/trex_stream_api.h | 12 +- 15 files changed, 565 insertions(+), 201 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 b44b1268..aff6b36e 100644 --- a/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py +++ b/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py @@ -145,7 +145,7 @@ class JsonRpcClient(object): return self.invoke_rpc_method("get_status") def query_rpc_server(self): - return self.invoke_rpc_method("get_reg_cmds") + return self.invoke_rpc_method("get_supported_cmds") def set_verbose(self, mode): diff --git a/src/gtest/rpc_test.cpp b/src/gtest/rpc_test.cpp index 767560b0..02d88eae 100644 --- a/src/gtest/rpc_test.cpp +++ b/src/gtest/rpc_test.cpp @@ -30,33 +30,16 @@ using namespace std; class RpcTest : public testing::Test { - void take_ownership(void) { - Json::Value request; - Json::Value response; - - create_request(request, "aquire", 1 , false); - - request["params"]["user"] = "test"; - request["params"]["force"] = true; - - send_request(request, response); - - EXPECT_TRUE(response["result"] != Json::nullValue); - m_ownership_handler = response["result"].asString(); - } - - void release_ownership() { - Json::Value request; - Json::Value response; +protected: - create_request(request, "release", 1 , false); - request["params"]["handler"] = m_ownership_handler; - - send_request(request, response); - EXPECT_TRUE(response["result"] == "ACK"); + void set_verbose(bool verbose) { + m_verbose = verbose; } - + virtual void SetUp() { + + m_verbose = false; + TrexRpcServerConfig cfg = TrexRpcServerConfig(TrexRpcServerConfig::RPC_PROT_TCP, 5050); m_rpc = new TrexRpcServer(cfg); @@ -66,7 +49,6 @@ class RpcTest : public testing::Test { m_socket = zmq_socket (m_context, ZMQ_REQ); zmq_connect (m_socket, "tcp://localhost:5050"); - take_ownership(); } virtual void TearDown() { @@ -79,16 +61,13 @@ class RpcTest : public testing::Test { public: - void create_request(Json::Value &request, const string &method, int id = 1, bool ownership = false) { + void create_request(Json::Value &request, const string &method, int id = 1) { request.clear(); request["jsonrpc"] = "2.0"; request["id"] = id; request["method"] = method; - if (ownership) { - request["params"]["handler"] = m_ownership_handler; - } } void send_request(const Json::Value &request, Json::Value &response) { @@ -98,15 +77,24 @@ public: response.clear(); string request_str = writer.write(request); + + if (m_verbose) { + cout << "\n" << request_str << "\n"; + } + string ret = send_msg(request_str); + if (m_verbose) { + cout << "\n" << ret << "\n"; + } + EXPECT_TRUE(reader.parse(ret, response, false)); EXPECT_EQ(response["jsonrpc"], "2.0"); EXPECT_EQ(response["id"], request["id"]); } string send_msg(const string &msg) { - char buffer[512]; + char buffer[1024 * 20]; zmq_send (m_socket, msg.c_str(), msg.size(), 0); int len = zmq_recv(m_socket, buffer, sizeof(buffer), 0); @@ -117,10 +105,55 @@ public: TrexRpcServer *m_rpc; void *m_context; void *m_socket; + bool m_verbose; +}; + +class RpcTestOwned : public RpcTest { +public: + + void create_request(Json::Value &request, const string &method, int id = 1) { + RpcTest::create_request(request, method, id); + request["params"]["handler"] = m_ownership_handler; + } + +protected: + + virtual void SetUp() { + RpcTest::SetUp(); + take_ownership(); + } + + + void take_ownership(void) { + Json::Value request; + Json::Value response; + + RpcTest::create_request(request, "acquire", 1); + + request["params"]["user"] = "test"; + request["params"]["force"] = true; + + send_request(request, response); + + EXPECT_TRUE(response["result"] != Json::nullValue); + m_ownership_handler = response["result"].asString(); + } + + void release_ownership() { + Json::Value request; + Json::Value response; + + RpcTest::create_request(request, "release", 1); + request["params"]["handler"] = m_ownership_handler; + + send_request(request, response); + EXPECT_TRUE(response["result"] == "ACK"); + } + string m_ownership_handler; }; -TEST_F(RpcTest, basic_rpc_test) { +TEST_F(RpcTest, basic_rpc_negative_cases) { Json::Value request; Json::Value response; Json::Reader reader; @@ -179,53 +212,38 @@ TEST_F(RpcTest, test_add_command) { Json::Value response; Json::Reader reader; - string req_str; - string resp_str; - - /* simple add - missing paramters */ - req_str = "{\"jsonrpc\": \"2.0\", \"method\": \"test_add\", \"id\": 488}"; - resp_str = send_msg(req_str); + /* missing parameters */ + create_request(request, "test_add"); + send_request(request, response); - EXPECT_TRUE(reader.parse(resp_str, response, false)); EXPECT_EQ(response["jsonrpc"], "2.0"); - EXPECT_EQ(response["id"], 488); EXPECT_EQ(response["error"]["code"], -32602); - /* simple add that works */ - req_str = "{\"jsonrpc\": \"2.0\", \"method\": \"test_add\", \"params\": {\"x\": 17, \"y\": -13} , \"id\": \"itay\"}"; - resp_str = send_msg(req_str); - - EXPECT_TRUE(reader.parse(resp_str, response, false)); - EXPECT_EQ(response["jsonrpc"], "2.0"); - EXPECT_EQ(response["id"], "itay"); - EXPECT_EQ(response["result"], 4); - - /* add with bad paratemers types */ - req_str = "{\"jsonrpc\": \"2.0\", \"method\": \"test_add\", \"params\": {\"x\": \"blah\", \"y\": -13} , \"id\": 17}"; - resp_str = send_msg(req_str); + /* bad paramters */ + create_request(request, "test_add"); + request["params"]["x"] = 5; + request["params"]["y"] = "itay"; + send_request(request, response); - EXPECT_TRUE(reader.parse(resp_str, response, false)); EXPECT_EQ(response["jsonrpc"], "2.0"); - EXPECT_EQ(response["id"], 17); EXPECT_EQ(response["error"]["code"], -32602); - /* add with invalid count of parameters */ - req_str = "{\"jsonrpc\": \"2.0\", \"method\": \"test_add\", \"params\": {\"y\": -13} , \"id\": 17}"; - resp_str = send_msg(req_str); + /* simple add that works */ + create_request(request, "test_add"); + request["params"]["x"] = 5; + request["params"]["y"] = -13; + send_request(request, response); - EXPECT_TRUE(reader.parse(resp_str, response, false)); EXPECT_EQ(response["jsonrpc"], "2.0"); - EXPECT_EQ(response["id"], 17); - EXPECT_EQ(response["error"]["code"], -32602); - + EXPECT_EQ(response["result"], -8); /* big numbers */ - req_str = "{\"jsonrpc\": \"2.0\", \"method\": \"test_add\", \"params\": {\"x\": 4827371, \"y\": -39181273} , \"id\": \"itay\"}"; - resp_str = send_msg(req_str); + create_request(request, "test_add"); + request["params"]["x"] = 4827371; + request["params"]["y"] = -39181273; + send_request(request, response); - EXPECT_TRUE(reader.parse(resp_str, response, false)); EXPECT_EQ(response["jsonrpc"], "2.0"); - EXPECT_EQ(response["id"], "itay"); EXPECT_EQ(response["result"], -34353902); } @@ -281,12 +299,174 @@ TEST_F(RpcTest, batch_rpc_test) { return; } -TEST_F(RpcTest, add_stream) { +/* ping command */ +TEST_F(RpcTest, ping) { + Json::Value request; + Json::Value response; + Json::Reader reader; + + create_request(request, "ping"); + send_request(request, response); + EXPECT_TRUE(response["result"] == "ACK"); +} + +static bool +find_member_in_array(const Json::Value &array, const string &member) { + for (auto x : array) { + if (x == member) { + return true; + } + } + + return false; +} + +/* get registered commands */ +TEST_F(RpcTest, get_supported_cmds) { + Json::Value request; + Json::Value response; + Json::Reader reader; + + create_request(request, "get_supported_cmds"); + send_request(request, response); + EXPECT_TRUE(response["result"].size() > 0); + + EXPECT_TRUE(find_member_in_array(response["result"], "ping")); + EXPECT_TRUE(find_member_in_array(response["result"], "get_supported_cmds")); +} + +/* get version */ +TEST_F(RpcTest, get_version) { Json::Value request; Json::Value response; Json::Reader reader; - create_request(request, "get_stream", 1, true); + create_request(request, "get_version"); + send_request(request, response); + + EXPECT_TRUE(response["result"] != Json::nullValue); + EXPECT_TRUE(response["result"]["built_by"] == "MOCK"); + EXPECT_TRUE(response["result"]["version"] == "v0.0"); +} + +/* get system info */ +TEST_F(RpcTest, get_system_info) { + Json::Value request; + Json::Value response; + Json::Reader reader; + + create_request(request, "get_system_info"); + send_request(request, response); + + EXPECT_TRUE(response["result"] != Json::nullValue); + EXPECT_TRUE(response["result"]["core_type"].isString()); + EXPECT_TRUE(response["result"]["hostname"].isString()); + EXPECT_TRUE(response["result"]["uptime"].isString()); + EXPECT_TRUE(response["result"]["dp_core_count"] > 0); + EXPECT_TRUE(response["result"]["port_count"] > 0); + + EXPECT_TRUE(response["result"]["ports"].isArray()); + + const Json::Value &ports = response["result"]["ports"]; + + + for (int i = 0; i < ports.size(); i++) { + EXPECT_TRUE(ports[i]["index"] == i); + EXPECT_TRUE(ports[i]["driver"].isString()); + EXPECT_TRUE(ports[i]["speed"].isString()); + } +} + +/* get owner, acquire and release */ +TEST_F(RpcTest, get_owner_acquire_release) { + Json::Value request; + Json::Value response; + Json::Reader reader; + + /* no user before acquring */ + create_request(request, "get_owner"); + send_request(request, response); + EXPECT_TRUE(response["result"] != Json::nullValue); + + EXPECT_TRUE(response["result"]["owner"] == "none"); + + /* soft acquire */ + create_request(request, "acquire"); + request["params"]["user"] = "itay"; + request["params"]["force"] = false; + + send_request(request, response); + EXPECT_TRUE(response["result"] != Json::nullValue); + + create_request(request, "get_owner"); + send_request(request, response); + EXPECT_TRUE(response["result"] != Json::nullValue); + + EXPECT_TRUE(response["result"]["owner"] == "itay"); + + /* hard acquire */ + create_request(request, "acquire"); + request["params"]["user"] = "moshe"; + request["params"]["force"] = false; + + send_request(request, response); + EXPECT_TRUE(response["result"] == Json::nullValue); + + request["params"]["force"] = true; + + send_request(request, response); + EXPECT_TRUE(response["result"] != Json::nullValue); + + string handler = response["result"].asString(); + + /* make sure */ + create_request(request, "get_owner"); + send_request(request, response); + EXPECT_TRUE(response["result"] != Json::nullValue); + + EXPECT_TRUE(response["result"]["owner"] == "moshe"); + + /* release */ + create_request(request, "release"); + request["params"]["handler"] = handler; + send_request(request, response); + + EXPECT_TRUE(response["result"] == "ACK"); +} + + +static void +create_simple_stream(Json::Value &obj) { + obj["mode"]["type"] = "continuous"; + obj["mode"]["pps"] = (rand() % 1000 + 1) * 0.99; + obj["isg"] = (rand() % 100 + 1) * 0.99;; + obj["enabled"] = true; + obj["self_start"] = true; + obj["next_stream_id"] = -1; + + obj["packet"]["meta"] = "dummy"; + + int packet_size = (rand() % 1500 + 1); + for (int i = 0; i < packet_size; i++) { + obj["packet"]["binary"][i] = (rand() % 0xff); + } + + obj["vm"] = Json::arrayValue; + obj["rx_stats"]["enabled"] = false; +} + +static bool +compare_streams(const Json::Value &s1, const Json::Value &s2) { + return s1 == s2; +} + +TEST_F(RpcTestOwned, add_remove_stream) { + Json::Value request; + Json::Value response; + Json::Reader reader; + + /* verify no such stream */ + create_request(request, "get_stream", 1); request["params"]["port_id"] = 1; request["params"]["stream_id"] = 5; @@ -297,58 +477,31 @@ TEST_F(RpcTest, add_stream) { EXPECT_EQ(response["id"], 1); EXPECT_EQ(response["error"]["code"], -32000); - // add it - create_request(request, "add_stream", 1, true); + /* add it */ + create_request(request, "add_stream", 1); request["params"]["port_id"] = 1; request["params"]["stream_id"] = 5; - request["params"]["stream"]["mode"]["type"] = "continuous"; - request["params"]["stream"]["mode"]["pps"] = 3; - request["params"]["stream"]["isg"] = 4.3; - request["params"]["stream"]["enabled"] = true; - request["params"]["stream"]["self_start"] = true; - request["params"]["stream"]["next_stream_id"] = -1; - request["params"]["stream"]["packet"]["meta"] = "dummy"; - request["params"]["stream"]["packet"]["binary"][0] = 4; - request["params"]["stream"]["packet"]["binary"][1] = 1; - request["params"]["stream"]["packet"]["binary"][2] = 255; - - request["params"]["stream"]["vm"] = Json::arrayValue; - request["params"]["stream"]["rx_stats"]["enabled"] = false; + Json::Value stream; + create_simple_stream(stream); + request["params"]["stream"] = stream; send_request(request, response); EXPECT_EQ(response["result"], "ACK"); /* get it */ - - create_request(request, "get_stream", 1, true); + create_request(request, "get_stream", 1); request["params"]["port_id"] = 1; request["params"]["stream_id"] = 5; send_request(request, response); - const Json::Value &stream = response["result"]["stream"]; - - EXPECT_EQ(stream["enabled"], true); - EXPECT_EQ(stream["self_start"], true); - - EXPECT_EQ(stream["packet"]["binary"][0], 4); - EXPECT_EQ(stream["packet"]["binary"][1], 1); - EXPECT_EQ(stream["packet"]["binary"][2], 255); - - EXPECT_EQ(stream["packet"]["meta"], "dummy"); - EXPECT_EQ(stream["next_stream_id"], -1); - - double delta = stream["isg"].asDouble() - 4.3; - EXPECT_TRUE(delta < 0.0001); - - EXPECT_EQ(stream["mode"]["type"], "continuous"); - EXPECT_EQ(stream["mode"]["pps"], 3); + EXPECT_TRUE(compare_streams(stream, response["result"]["stream"])); // remove it - create_request(request, "remove_stream", 1, true); + create_request(request, "remove_stream", 1); request["params"]["port_id"] = 1; request["params"]["stream_id"] = 5; diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index d5aa3a90..afa15973 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -18,9 +18,17 @@ 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_rpc_cmds.h" #include #include +#include + +#include +#include +#include + +//#include #ifndef TREX_RPC_MOCK_SERVER #include <../linux_dpdk/version.h> @@ -29,36 +37,161 @@ limitations under the License. using namespace std; /** - * get status + * ping command + */ +trex_rpc_cmd_rc_e +TrexRpcCmdPing::_run(const Json::Value ¶ms, Json::Value &result) { + + result["result"] = "ACK"; + return (TREX_RPC_CMD_OK); +} + +/** + * query command + */ +trex_rpc_cmd_rc_e +TrexRpcCmdGetCmds::_run(const Json::Value ¶ms, Json::Value &result) { + vector cmds; + + TrexRpcCommandsTable::get_instance().query(cmds); + + Json::Value test = Json::arrayValue; + for (auto cmd : cmds) { + test.append(cmd); + } + + result["result"] = test; + + return (TREX_RPC_CMD_OK); +} + +/** + * get version * */ trex_rpc_cmd_rc_e -TrexRpcCmdGetStatus::_run(const Json::Value ¶ms, Json::Value &result) { +TrexRpcCmdGetVersion::_run(const Json::Value ¶ms, Json::Value &result) { Json::Value §ion = result["result"]; #ifndef TREX_RPC_MOCK_SERVER - section["general"]["version"] = VERSION_BUILD_NUM; - section["general"]["build_date"] = get_build_date(); - section["general"]["build_time"] = get_build_time(); - section["general"]["built_by"] = VERSION_USER; + section["version"] = VERSION_BUILD_NUM; + section["build_date"] = get_build_date(); + section["build_time"] = get_build_time(); + section["built_by"] = VERSION_USER; #else - section["general"]["version"] = "v0.0"; - section["general"]["build_date"] = __DATE__; - section["general"]["build_time"] = __TIME__; - section["general"]["version_user"] = "MOCK"; + section["version"] = "v0.0"; + section["build_date"] = __DATE__; + section["build_time"] = __TIME__; + section["built_by"] = "MOCK"; #endif - section["general"]["uptime"] = TrexRpcServer::get_server_uptime(); - section["general"]["owner"] = TrexRpcServer::get_owner(); + return (TREX_RPC_CMD_OK); +} + +/** + * get the CPU model + * + */ +std::string +TrexRpcCmdGetSysInfo::get_cpu_model() { + + static const string cpu_prefix = "model name"; + std::ifstream cpuinfo("/proc/cpuinfo"); + + if (cpuinfo.is_open()) { + while (cpuinfo.good()) { + + std::string line; + getline(cpuinfo, line); + + int pos = line.find(cpu_prefix); + if (pos == string::npos) { + continue; + } - // ports + /* trim it */ + int index = cpu_prefix.size() + 1; + while ( (line[index] == ' ') || (line[index] == ':') ) { + index++; + } - section["ports"]["count"] = TrexStateless::get_instance().get_port_count(); + return line.substr(index); + } + } + + return "unknown"; +} + +void +TrexRpcCmdGetSysInfo::get_hostname(string &hostname) { + char buffer[256]; + buffer[0] = 0; + + gethostname(buffer, sizeof(buffer)); + + /* write hostname */ + hostname = buffer; +} + +/** + * get system info + * + */ +trex_rpc_cmd_rc_e +TrexRpcCmdGetSysInfo::_run(const Json::Value ¶ms, Json::Value &result) { + string hostname; + + TrexStateless & instance = TrexStateless::get_instance(); + + Json::Value §ion = result["result"]; + + get_hostname(hostname); + section["hostname"] = hostname; + + section["uptime"] = TrexRpcServer::get_server_uptime(); + + /* FIXME: core count */ + section["dp_core_count"] = 1; + section["core_type"] = get_cpu_model(); + + /* ports */ + + + section["port_count"] = instance.get_port_count(); + + section["ports"] = Json::arrayValue; + + for (int i = 0; i < instance.get_port_count(); i++) { + string driver; + string speed; + + TrexStatelessPort *port = instance.get_port_by_id(i); + port->get_properties(driver, speed); + + section["ports"][i]["index"] = i; + section["ports"][i]["driver"] = driver; + section["ports"][i]["speed"] = speed; + + switch (port->get_state()) { + case TrexStatelessPort::PORT_STATE_DOWN: + section["ports"][i]["status"] = "down"; + break; + + case TrexStatelessPort::PORT_STATE_UP_IDLE: + section["ports"][i]["status"] = "idle"; + break; + + case TrexStatelessPort::PORT_STATE_TRANSMITTING: + section["ports"][i]["status"] = "transmitting"; + break; + } + + } 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 b62d213b..41567509 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp @@ -63,6 +63,9 @@ TrexRpcCmdAddStream::_run(const Json::Value ¶ms, Json::Value &result) { /* allocate a new stream based on the type */ TrexStream *stream = allocate_new_stream(section, port_id, stream_id, result); + /* save this for future queries */ + stream->store_stream_json(section); + /* some fields */ stream->m_enabled = parse_bool(section, "enabled", result); stream->m_self_start = parse_bool(section, "self_start", result); @@ -130,7 +133,7 @@ TrexRpcCmdAddStream::allocate_new_stream(const Json::Value §ion, uint8_t por if (type == "continuous") { - uint32_t pps = parse_int(mode, "pps", result); + double pps = parse_double(mode, "pps", result); stream = new TrexStreamContinuous(port_id, stream_id, pps); } else if (type == "single_burst") { @@ -413,30 +416,11 @@ TrexRpcCmdGetStream::_run(const Json::Value ¶ms, Json::Value &result) { generate_execute_err(result, ss.str()); } - Json::Value stream_json; - - stream_json["enabled"] = stream->m_enabled; - stream_json["self_start"] = stream->m_self_start; - - stream_json["isg"] = stream->m_isg_usec; - stream_json["next_stream_id"] = stream->m_next_stream_id; - - stream_json["packet"]["binary"] = Json::arrayValue; - for (int i = 0; i < stream->m_pkt.len; i++) { - stream_json["packet"]["binary"].append(stream->m_pkt.binary[i]); - } - - stream_json["packet"]["meta"] = stream->m_pkt.meta; - - if (TrexStreamContinuous *cont = dynamic_cast(stream)) { - stream_json["mode"]["type"] = "continuous"; - stream_json["mode"]["pps"] = cont->get_pps(); - - } - - result["result"]["stream"] = stream_json; + /* return the stored stream json (instead of decoding it all over again) */ + result["result"]["stream"] = stream->get_stream_json(); return (TREX_RPC_CMD_OK); + } /*************************** @@ -455,17 +439,17 @@ TrexRpcCmdStartTraffic::_run(const Json::Value ¶ms, Json::Value &result) { TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id); - TrexStatelessPort::traffic_rc_e rc = port->start_traffic(); + TrexStatelessPort::rc_e rc = port->start_traffic(); - if (rc == TrexStatelessPort::TRAFFIC_OK) { + if (rc == TrexStatelessPort::RC_OK) { result["result"] = "ACK"; } else { std::stringstream ss; switch (rc) { - case TrexStatelessPort::TRAFFIC_ERR_ALREADY_STARTED: - ss << "traffic has already started on that port"; + case TrexStatelessPort::RC_ERR_BAD_STATE_FOR_OP: + ss << "bad state for operations: port is either transmitting traffic or down"; break; - case TrexStatelessPort::TRAFFIC_ERR_NO_STREAMS: + case TrexStatelessPort::RC_ERR_NO_STREAMS: ss << "no active streams on that port"; break; default: diff --git a/src/rpc-server/commands/trex_rpc_cmd_test.cpp b/src/rpc-server/commands/trex_rpc_cmd_test.cpp index 3153317e..3cdddd31 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_test.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_test.cpp @@ -21,7 +21,6 @@ limitations under the License. #include "trex_rpc_cmds.h" #include #include -#include using namespace std; @@ -50,32 +49,3 @@ TrexRpcCmdTestSub::_run(const Json::Value ¶ms, Json::Value &result) { return (TREX_RPC_CMD_OK); } -/** - * ping command - */ -trex_rpc_cmd_rc_e -TrexRpcCmdPing::_run(const Json::Value ¶ms, Json::Value &result) { - - result["result"] = "ACK"; - return (TREX_RPC_CMD_OK); -} - -/** - * query command - */ -trex_rpc_cmd_rc_e -TrexRpcCmdGetReg::_run(const Json::Value ¶ms, Json::Value &result) { - vector cmds; - - TrexRpcCommandsTable::get_instance().query(cmds); - - Json::Value test = Json::arrayValue; - for (auto cmd : cmds) { - test.append(cmd); - } - - result["result"] = test; - - 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 32138195..643aa22d 100644 --- a/src/rpc-server/commands/trex_rpc_cmds.h +++ b/src/rpc-server/commands/trex_rpc_cmds.h @@ -35,7 +35,7 @@ class TrexStream; * syntactic sugar for creating a simple command */ -#define TREX_RPC_CMD_DEFINE_EXTENED(class_name, cmd_name, param_count, needs_ownership, ext) \ +#define TREX_RPC_CMD_DEFINE_EXTENDED(class_name, cmd_name, param_count, needs_ownership, ext) \ class class_name : public TrexRpcCommand { \ public: \ class_name () : TrexRpcCommand(cmd_name, param_count, needs_ownership) {} \ @@ -44,7 +44,7 @@ class TrexStream; ext \ } -#define TREX_RPC_CMD_DEFINE(class_name, cmd_name, param_count, needs_ownership) TREX_RPC_CMD_DEFINE_EXTENED(class_name, cmd_name, param_count, needs_ownership, ;) +#define TREX_RPC_CMD_DEFINE(class_name, cmd_name, param_count, needs_ownership) TREX_RPC_CMD_DEFINE_EXTENDED(class_name, cmd_name, param_count, needs_ownership, ;) /** * test cmds @@ -55,9 +55,16 @@ TREX_RPC_CMD_DEFINE(TrexRpcCmdTestSub, "test_sub", 2, false); /** * general cmds */ -TREX_RPC_CMD_DEFINE(TrexRpcCmdPing, "ping", 0, false); -TREX_RPC_CMD_DEFINE(TrexRpcCmdGetReg, "get_reg_cmds", 0, false); -TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStatus, "get_status", 0, false); +TREX_RPC_CMD_DEFINE(TrexRpcCmdPing, "ping", 0, false); +TREX_RPC_CMD_DEFINE(TrexRpcCmdGetCmds, "get_supported_cmds", 0, false); +TREX_RPC_CMD_DEFINE(TrexRpcCmdGetVersion, "get_version", 0, false); + +TREX_RPC_CMD_DEFINE_EXTENDED(TrexRpcCmdGetSysInfo, "get_system_info", 0, false, + +std::string get_cpu_model(); +void get_hostname(std::string &hostname); + +); /** * ownership @@ -73,7 +80,7 @@ TREX_RPC_CMD_DEFINE(TrexRpcCmdRelease, "release", 0, true); TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveAllStreams, "remove_all_streams", 1, true); TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveStream, "remove_stream", 2, true); -TREX_RPC_CMD_DEFINE_EXTENED(TrexRpcCmdAddStream, "add_stream", 3, true, +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); @@ -92,4 +99,6 @@ TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStream, "get_stream", 2, true); TREX_RPC_CMD_DEFINE(TrexRpcCmdStartTraffic, "start_traffic", 1, true); TREX_RPC_CMD_DEFINE(TrexRpcCmdStopTraffic, "stop_traffic", 1, true); + + #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 f968bb74..170f0de1 100644 --- a/src/rpc-server/trex_rpc_cmds_table.cpp +++ b/src/rpc-server/trex_rpc_cmds_table.cpp @@ -34,8 +34,9 @@ TrexRpcCommandsTable::TrexRpcCommandsTable() { /* general */ register_command(new TrexRpcCmdPing()); - register_command(new TrexRpcCmdGetReg()); - register_command(new TrexRpcCmdGetStatus()); + register_command(new TrexRpcCmdGetCmds()); + register_command(new TrexRpcCmdGetVersion()); + register_command(new TrexRpcCmdGetSysInfo()); register_command(new TrexRpcCmdGetOwner()); register_command(new TrexRpcCmdAcquire()); register_command(new TrexRpcCmdRelease()); diff --git a/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp index 928baca6..9d9de53a 100644 --- a/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp +++ b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp @@ -225,3 +225,11 @@ std::string TrexJsonRpcV2Parser::pretty_json_str(const std::string &json_str) { return writer.write(value); } +void +TrexJsonRpcV2Parser::generate_common_error(Json::Value &json, const std::string &specific_err) { + JsonRpcError err(Json::Value::null, JSONRPC_V2_ERR_INTERNAL_ERROR, specific_err, true); + + err.execute(json); + +} + diff --git a/src/rpc-server/trex_rpc_jsonrpc_v2_parser.h b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.h index ebffaeb7..0563f21d 100644 --- a/src/rpc-server/trex_rpc_jsonrpc_v2_parser.h +++ b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.h @@ -79,6 +79,15 @@ public: */ void parse(std::vector &commands); + /** + * will generate a valid JSON RPC v2 error message with + * generic error code and message + * + * @author imarom (16-Sep-15) + * + */ + static void generate_common_error(Json::Value &json, const std::string &specific_err); + /** * *tries* to generate a pretty string from JSON * if json_str is not a valid JSON string diff --git a/src/rpc-server/trex_rpc_req_resp_server.cpp b/src/rpc-server/trex_rpc_req_resp_server.cpp index c4d9dfdb..3d52686c 100644 --- a/src/rpc-server/trex_rpc_req_resp_server.cpp +++ b/src/rpc-server/trex_rpc_req_resp_server.cpp @@ -82,6 +82,13 @@ void TrexRpcServerReqRes::_rpc_thread_cb() { } } + if (msg_size >= sizeof(m_msg_buffer)) { + std::stringstream ss; + ss << "RPC request of '" << msg_size << "' exceeds maximum message size which is '" << sizeof(m_msg_buffer) << "'"; + handle_server_error(ss.str()); + continue; + } + /* transform it to a string */ std::string request((const char *)m_msg_buffer, msg_size); @@ -145,3 +152,23 @@ void TrexRpcServerReqRes::handle_request(const std::string &request) { zmq_send(m_socket, response_str.c_str(), response_str.size(), 0); } + +/** + * handles a server error + * + */ +void +TrexRpcServerReqRes::handle_server_error(const std::string &specific_err) { + Json::FastWriter writer; + Json::Value response; + + /* generate error */ + TrexJsonRpcV2Parser::generate_common_error(response, specific_err); + + /* write the JSON to string and sever on ZMQ */ + std::string response_str = writer.write(response); + + verbose_json("Server Replied: ", response_str); + + zmq_send(m_socket, response_str.c_str(), response_str.size(), 0); +} diff --git a/src/rpc-server/trex_rpc_req_resp_server.h b/src/rpc-server/trex_rpc_req_resp_server.h index f12d0540..7c1d66d1 100644 --- a/src/rpc-server/trex_rpc_req_resp_server.h +++ b/src/rpc-server/trex_rpc_req_resp_server.h @@ -39,9 +39,11 @@ protected: void _stop_rpc_thread(); private: + void handle_request(const std::string &request); + void handle_server_error(const std::string &specific_err); - static const int RPC_MAX_MSG_SIZE = 2048; + static const int RPC_MAX_MSG_SIZE = (20 * 1024); void *m_context; void *m_socket; uint8_t m_msg_buffer[RPC_MAX_MSG_SIZE]; diff --git a/src/stateless/trex_stateless.cpp b/src/stateless/trex_stateless.cpp index 2ab0c5d9..b51c4e69 100644 --- a/src/stateless/trex_stateless.cpp +++ b/src/stateless/trex_stateless.cpp @@ -20,6 +20,8 @@ limitations under the License. */ #include +using namespace std; + /*********************************************************** * Trex stateless object * @@ -76,7 +78,7 @@ uint8_t TrexStateless::get_port_count() { * **************************/ TrexStatelessPort::TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) { - m_started = false; + m_port_state = PORT_STATE_DOWN; } @@ -84,25 +86,29 @@ TrexStatelessPort::TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) { * starts the traffic on the port * */ -TrexStatelessPort::traffic_rc_e +TrexStatelessPort::rc_e TrexStatelessPort::start_traffic(void) { - if (m_started) { - return (TRAFFIC_ERR_ALREADY_STARTED); + + if (m_port_state != PORT_STATE_UP_IDLE) { + return (RC_ERR_BAD_STATE_FOR_OP); } if (get_stream_table()->size() == 0) { - return (TRAFFIC_ERR_NO_STREAMS); + return (RC_ERR_NO_STREAMS); } - m_started = true; + m_port_state = PORT_STATE_TRANSMITTING; - return (TRAFFIC_OK); + /* real code goes here */ + return (RC_OK); } void TrexStatelessPort::stop_traffic(void) { - if (m_started) { - m_started = false; + + /* real code goes here */ + if (m_port_state = PORT_STATE_TRANSMITTING) { + m_port_state = PORT_STATE_UP_IDLE; } } @@ -114,4 +120,10 @@ TrexStreamTable * TrexStatelessPort::get_stream_table() { return &m_stream_table; } +void +TrexStatelessPort::get_properties(string &driver, string &speed) { + /* take this from DPDK */ + driver = "Unknown Driver"; + speed = "Unknown Speed"; +} diff --git a/src/stateless/trex_stateless_api.h b/src/stateless/trex_stateless_api.h index 358ab339..60d26878 100644 --- a/src/stateless/trex_stateless_api.h +++ b/src/stateless/trex_stateless_api.h @@ -50,19 +50,36 @@ class TrexStatelessPort { public: /** - * describess error codes for starting traffic + * port state */ - enum traffic_rc_e { - TRAFFIC_OK, - TRAFFIC_ERR_ALREADY_STARTED, - TRAFFIC_ERR_NO_STREAMS, - TRAFFIC_ERR_FAILED_TO_COMPILE_STREAMS + enum port_state_e { + PORT_STATE_DOWN, + PORT_STATE_UP_IDLE, + PORT_STATE_TRANSMITTING + }; + + /** + * describess different error codes for port operations + */ + enum rc_e { + RC_OK, + RC_ERR_BAD_STATE_FOR_OP, + RC_ERR_NO_STREAMS, + RC_ERR_FAILED_TO_COMPILE_STREAMS }; TrexStatelessPort(uint8_t port_id); - traffic_rc_e start_traffic(void); + /** + * start traffic + * + */ + rc_e start_traffic(void); + /** + * stop traffic + * + */ void stop_traffic(void); /** @@ -71,10 +88,28 @@ public: */ TrexStreamTable *get_stream_table(); + /** + * get the port state + * + */ + port_state_e get_state() { + return m_port_state; + } + + /** + * fill up properties of the port + * + * @author imarom (16-Sep-15) + * + * @param driver + * @param speed + */ + void get_properties(std::string &driver, std::string &speed); + private: TrexStreamTable m_stream_table; uint8_t m_port_id; - bool m_started; + port_state_e m_port_state; }; /** diff --git a/src/stateless/trex_stream.cpp b/src/stateless/trex_stream.cpp index 2b5b2424..8bf04748 100644 --- a/src/stateless/trex_stream.cpp +++ b/src/stateless/trex_stream.cpp @@ -45,6 +45,17 @@ TrexStream::~TrexStream() { } } +void +TrexStream::store_stream_json(const Json::Value &stream_json) { + /* deep copy */ + m_stream_json = stream_json; +} + +const Json::Value & +TrexStream::get_stream_json() { + return m_stream_json; +} + /************************************** * stream table *************************************/ diff --git a/src/stateless/trex_stream_api.h b/src/stateless/trex_stream_api.h index 0a955ff7..d3c0fb29 100644 --- a/src/stateless/trex_stream_api.h +++ b/src/stateless/trex_stream_api.h @@ -26,6 +26,8 @@ limitations under the License. #include #include +#include + #include class TrexRpcCmdAddStream; @@ -48,7 +50,13 @@ public: static const uint32_t MIN_PKT_SIZE_BYTES = 1; static const uint32_t MAX_PKT_SIZE_BYTES = 9000; -private: + /* provides storage for the stream json*/ + void store_stream_json(const Json::Value &stream_json); + + /* access the stream json */ + const Json::Value & get_stream_json(); + +protected: /* basic */ uint8_t m_port_id; uint32_t m_stream_id; @@ -82,6 +90,8 @@ private: } m_rx_check; + /* original template provided by requester */ + Json::Value m_stream_json; }; /** -- cgit 1.2.3-korg From 3b372bbe45931b853f3f906352a0cbdc89952c41 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 16 Sep 2015 17:12:30 +0300 Subject: enabled all warnings for the mock RPC server target --- linux/ws_main.py | 3 +- src/common/captureFile.cpp | 2 +- src/gtest/rpc_test.cpp | 61 ++++++++++++++++++++++++ src/rpc-server/commands/trex_rpc_cmd_general.cpp | 2 - src/rpc-server/trex_rpc_cmd_api.h | 3 ++ src/stateless/trex_stateless.cpp | 2 +- 6 files changed, 68 insertions(+), 5 deletions(-) diff --git a/linux/ws_main.py b/linux/ws_main.py index e9f21d11..789895d9 100755 --- a/linux/ws_main.py +++ b/linux/ws_main.py @@ -368,7 +368,8 @@ build_types = [ #build_option(name = "bp-sim", src = bp, debug_mode= RELEASE_,platform = PLATFORM_32, is_pie = False), build_option(name = "bp-sim", src = bp, debug_mode= RELEASE_,platform = PLATFORM_64, is_pie = False), - build_option(name = "mock-rpc-server", use = ['zmq'], src = rpc_server_mock, debug_mode= DEBUG_,platform = PLATFORM_64, is_pie = False, flags = ['-DTREX_RPC_MOCK_SERVER'], + build_option(name = "mock-rpc-server", use = ['zmq'], src = rpc_server_mock, debug_mode= DEBUG_,platform = PLATFORM_64, is_pie = False, + flags = ['-DTREX_RPC_MOCK_SERVER', '-Wall', '-Wno-sign-compare', '-Werror'], rpath = ['.']), ] diff --git a/src/common/captureFile.cpp b/src/common/captureFile.cpp index a4fe78be..00625181 100755 --- a/src/common/captureFile.cpp +++ b/src/common/captureFile.cpp @@ -110,7 +110,7 @@ void CCapPktRaw::CloneShalow(CCapPktRaw *obj){ } void CCapPktRaw::Dump(FILE *fd,int verbose){ - fprintf(fd," =>pkt (%p) %llu , len %d, time [%x:%x] \n",raw,pkt_cnt,pkt_len,time_sec,time_nsec); + fprintf(fd," =>pkt (%p) %llu , len %d, time [%x:%x] \n",raw, (unsigned long long)pkt_cnt,pkt_len,time_sec,time_nsec); if (verbose) { utl_DumpBuffer(fd,raw,pkt_len,0); } diff --git a/src/gtest/rpc_test.cpp b/src/gtest/rpc_test.cpp index 02d88eae..58197000 100644 --- a/src/gtest/rpc_test.cpp +++ b/src/gtest/rpc_test.cpp @@ -25,6 +25,8 @@ limitations under the License. #include #include #include +#include +#include using namespace std; @@ -518,3 +520,62 @@ TEST_F(RpcTestOwned, add_remove_stream) { } +TEST_F(RpcTestOwned, get_stream_id_list) { + Json::Value request; + Json::Value response; + Json::Reader reader; + + + /* add stream 1 */ + create_request(request, "add_stream"); + request["params"]["port_id"] = 1; + + + Json::Value stream; + create_simple_stream(stream); + + request["params"]["stream"] = stream; + + request["params"]["stream_id"] = 5; + send_request(request, response); + EXPECT_EQ(response["result"], "ACK"); + + request["params"]["stream_id"] = 12; + send_request(request, response); + EXPECT_EQ(response["result"], "ACK"); + + request["params"]["stream_id"] = 19; + send_request(request, response); + EXPECT_EQ(response["result"], "ACK"); + + + create_request(request, "get_stream_list"); + request["params"]["port_id"] = 1; + send_request(request, response); + + EXPECT_TRUE(response["result"].isArray()); + vector vec; + for (auto x : response["result"]) { + vec.push_back(x.asInt()); + } + + sort(vec.begin(), vec.end()); + + EXPECT_EQ(vec[0], 5); + EXPECT_EQ(vec[1], 12); + EXPECT_EQ(vec[2], 19); + + create_request(request, "remove_all_streams"); + request["params"]["port_id"] = 1; + send_request(request, response); + + EXPECT_TRUE(response["result"] == "ACK"); + + /* make sure the lights are off ... */ + create_request(request, "get_stream_list"); + request["params"]["port_id"] = 1; + send_request(request, response); + + EXPECT_TRUE(response["result"].isArray()); + EXPECT_TRUE(response["result"].size() == 0); +} diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index afa15973..fcdb7acf 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -28,8 +28,6 @@ limitations under the License. #include #include -//#include - #ifndef TREX_RPC_MOCK_SERVER #include <../linux_dpdk/version.h> #endif diff --git a/src/rpc-server/trex_rpc_cmd_api.h b/src/rpc-server/trex_rpc_cmd_api.h index c72b3e3b..cab50cfd 100644 --- a/src/rpc-server/trex_rpc_cmd_api.h +++ b/src/rpc-server/trex_rpc_cmd_api.h @@ -177,6 +177,9 @@ protected: s.pop_back(); s += "]"; generate_parse_err(result, s); + + /* dummy return value - does not matter, the above will throw exception */ + return (*choices.begin()); } /** diff --git a/src/stateless/trex_stateless.cpp b/src/stateless/trex_stateless.cpp index b51c4e69..537dfa4a 100644 --- a/src/stateless/trex_stateless.cpp +++ b/src/stateless/trex_stateless.cpp @@ -107,7 +107,7 @@ void TrexStatelessPort::stop_traffic(void) { /* real code goes here */ - if (m_port_state = PORT_STATE_TRANSMITTING) { + if (m_port_state == PORT_STATE_TRANSMITTING) { m_port_state = PORT_STATE_UP_IDLE; } } -- cgit 1.2.3-korg From 1e723ff84bb6cdf6dd3a58650af059b6814b5331 Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 17 Sep 2015 11:09:44 +0300 Subject: added more tests --- src/gtest/rpc_test.cpp | 94 +++++++++++++++++++++--- src/rpc-server/commands/trex_rpc_cmd_general.cpp | 1 + src/rpc-server/commands/trex_rpc_cmd_stream.cpp | 3 +- src/stateless/trex_stateless.cpp | 2 +- 4 files changed, 86 insertions(+), 14 deletions(-) diff --git a/src/gtest/rpc_test.cpp b/src/gtest/rpc_test.cpp index 58197000..015da2f8 100644 --- a/src/gtest/rpc_test.cpp +++ b/src/gtest/rpc_test.cpp @@ -113,9 +113,11 @@ public: class RpcTestOwned : public RpcTest { public: - void create_request(Json::Value &request, const string &method, int id = 1) { + void create_request(Json::Value &request, const string &method, int id = 1, bool owned = true) { RpcTest::create_request(request, method, id); - request["params"]["handler"] = m_ownership_handler; + if (owned) { + request["params"]["handler"] = m_ownership_handler; + } } protected: @@ -212,7 +214,6 @@ TEST_F(RpcTest, basic_rpc_negative_cases) { TEST_F(RpcTest, test_add_command) { Json::Value request; Json::Value response; - Json::Reader reader; /* missing parameters */ create_request(request, "test_add"); @@ -305,7 +306,6 @@ TEST_F(RpcTest, batch_rpc_test) { TEST_F(RpcTest, ping) { Json::Value request; Json::Value response; - Json::Reader reader; create_request(request, "ping"); send_request(request, response); @@ -327,7 +327,6 @@ find_member_in_array(const Json::Value &array, const string &member) { TEST_F(RpcTest, get_supported_cmds) { Json::Value request; Json::Value response; - Json::Reader reader; create_request(request, "get_supported_cmds"); send_request(request, response); @@ -341,7 +340,6 @@ TEST_F(RpcTest, get_supported_cmds) { TEST_F(RpcTest, get_version) { Json::Value request; Json::Value response; - Json::Reader reader; create_request(request, "get_version"); send_request(request, response); @@ -355,7 +353,6 @@ TEST_F(RpcTest, get_version) { TEST_F(RpcTest, get_system_info) { Json::Value request; Json::Value response; - Json::Reader reader; create_request(request, "get_system_info"); send_request(request, response); @@ -383,7 +380,6 @@ TEST_F(RpcTest, get_system_info) { TEST_F(RpcTest, get_owner_acquire_release) { Json::Value request; Json::Value response; - Json::Reader reader; /* no user before acquring */ create_request(request, "get_owner"); @@ -465,7 +461,6 @@ compare_streams(const Json::Value &s1, const Json::Value &s2) { TEST_F(RpcTestOwned, add_remove_stream) { Json::Value request; Json::Value response; - Json::Reader reader; /* verify no such stream */ create_request(request, "get_stream", 1); @@ -523,14 +518,11 @@ TEST_F(RpcTestOwned, add_remove_stream) { TEST_F(RpcTestOwned, get_stream_id_list) { Json::Value request; Json::Value response; - Json::Reader reader; - /* add stream 1 */ create_request(request, "add_stream"); request["params"]["port_id"] = 1; - Json::Value stream; create_simple_stream(stream); @@ -579,3 +571,81 @@ TEST_F(RpcTestOwned, get_stream_id_list) { EXPECT_TRUE(response["result"].isArray()); EXPECT_TRUE(response["result"].size() == 0); } + + +TEST_F(RpcTestOwned, start_stop_traffic) { + Json::Value request; + Json::Value response; + + /* add stream #1 */ + create_request(request, "add_stream"); + request["params"]["port_id"] = 1; + request["params"]["stream_id"] = 5; + + Json::Value stream; + create_simple_stream(stream); + + request["params"]["stream"] = stream; + + send_request(request, response); + EXPECT_EQ(response["result"], "ACK"); + + /* add stream #1 */ + create_request(request, "add_stream"); + request["params"]["port_id"] = 3; + request["params"]["stream_id"] = 12; + request["params"]["stream"] = stream; + + send_request(request, response); + EXPECT_EQ(response["result"], "ACK"); + + /* start port 1 */ + create_request(request, "start_traffic"); + request["params"]["port_id"] = 1; + send_request(request, response); + EXPECT_EQ(response["result"], "ACK"); + + + /* start port 3 */ + request["params"]["port_id"] = 3; + send_request(request, response); + EXPECT_EQ(response["result"], "ACK"); + + /* start not configured port */ + + request["params"]["port_id"] = 2; + send_request(request, response); + EXPECT_EQ(response["error"]["code"], -32000); + + /* stop port 1 */ + create_request(request, "stop_traffic"); + request["params"]["port_id"] = 1; + send_request(request, response); + EXPECT_EQ(response["result"], "ACK"); + + /* stop port 3 */ + request["params"]["port_id"] = 3; + send_request(request, response); + EXPECT_EQ(response["result"], "ACK"); + + /* start 1 again */ + create_request(request, "start_traffic"); + request["params"]["port_id"] = 1; + send_request(request, response); + EXPECT_EQ(response["result"], "ACK"); + + /* start 1 twice (error) */ + send_request(request, response); + EXPECT_EQ(response["error"]["code"], -32000); + + /* make sure you cannot release while traffic is active */ + //create_request(request, "release"); + //send_request(request, response); + //EXPECT_EQ(response["error"]["code"], -32000); + + /* done */ + create_request(request, "stop_traffic"); + request["params"]["port_id"] = 1; + send_request(request, response); + EXPECT_EQ(response["result"], "ACK"); +} diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index fcdb7acf..97ccae06 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -241,6 +241,7 @@ TrexRpcCmdAcquire::_run(const Json::Value ¶ms, Json::Value &result) { */ trex_rpc_cmd_rc_e TrexRpcCmdRelease::_run(const Json::Value ¶ms, Json::Value &result) { + TrexRpcServer::clear_owner(); result["result"] = "ACK"; diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp index 41567509..1450e1a9 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp @@ -429,7 +429,8 @@ TrexRpcCmdGetStream::_run(const Json::Value ¶ms, Json::Value &result) { **************************/ trex_rpc_cmd_rc_e TrexRpcCmdStartTraffic::_run(const Json::Value ¶ms, Json::Value &result) { - uint8_t port_id = parse_byte(params, "port_id", result); + + uint8_t port_id = parse_byte(params, "port_id", result); if (port_id >= TrexStateless::get_instance().get_port_count()) { std::stringstream ss; diff --git a/src/stateless/trex_stateless.cpp b/src/stateless/trex_stateless.cpp index 537dfa4a..dcad1514 100644 --- a/src/stateless/trex_stateless.cpp +++ b/src/stateless/trex_stateless.cpp @@ -78,7 +78,7 @@ uint8_t TrexStateless::get_port_count() { * **************************/ TrexStatelessPort::TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) { - m_port_state = PORT_STATE_DOWN; + m_port_state = PORT_STATE_UP_IDLE; } -- cgit 1.2.3-korg From 96765d2bf2c416f652da904cf7524ff75b678aee Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 17 Sep 2015 16:27:47 +0300 Subject: moved 'owning states' to port granularity instead of machine --- src/gtest/rpc_test.cpp | 82 +++++++++++++----------- src/rpc-server/commands/trex_rpc_cmd_general.cpp | 29 +++++++-- src/rpc-server/commands/trex_rpc_cmds.h | 6 +- src/rpc-server/trex_rpc_cmd.cpp | 23 ++++++- src/rpc-server/trex_rpc_cmd_api.h | 9 +++ src/rpc-server/trex_rpc_server.cpp | 21 ------ src/rpc-server/trex_rpc_server_api.h | 44 +------------ src/stateless/trex_stateless.cpp | 23 +++++++ src/stateless/trex_stateless_api.h | 48 ++++++++++++++ 9 files changed, 174 insertions(+), 111 deletions(-) diff --git a/src/gtest/rpc_test.cpp b/src/gtest/rpc_test.cpp index 015da2f8..168ee936 100644 --- a/src/gtest/rpc_test.cpp +++ b/src/gtest/rpc_test.cpp @@ -113,10 +113,11 @@ public: class RpcTestOwned : public RpcTest { public: - void create_request(Json::Value &request, const string &method, int id = 1, bool owned = true) { + void create_request(Json::Value &request, const string &method, int id = 1, int port_id = 1, bool owned = true) { RpcTest::create_request(request, method, id); if (owned) { - request["params"]["handler"] = m_ownership_handler; + request["params"]["port_id"] = port_id; + request["params"]["handler"] = m_ownership_handler[port_id]; } } @@ -124,37 +125,43 @@ protected: virtual void SetUp() { RpcTest::SetUp(); - take_ownership(); + + for (int i = 0 ; i < 4; i++) { + m_ownership_handler[i] = take_ownership(i); + } } - void take_ownership(void) { + string take_ownership(uint8_t port_id) { Json::Value request; Json::Value response; RpcTest::create_request(request, "acquire", 1); + request["params"]["port_id"] = port_id; request["params"]["user"] = "test"; request["params"]["force"] = true; send_request(request, response); EXPECT_TRUE(response["result"] != Json::nullValue); - m_ownership_handler = response["result"].asString(); + return response["result"].asString(); } - void release_ownership() { + void release_ownership(uint8_t port_id) { Json::Value request; Json::Value response; RpcTest::create_request(request, "release", 1); + request["params"]["handler"] = m_ownership_handler; + request["params"]["port_id"] = port_id; send_request(request, response); EXPECT_TRUE(response["result"] == "ACK"); } - string m_ownership_handler; + string m_ownership_handler[4]; }; TEST_F(RpcTest, basic_rpc_negative_cases) { @@ -383,6 +390,7 @@ TEST_F(RpcTest, get_owner_acquire_release) { /* no user before acquring */ create_request(request, "get_owner"); + request["params"]["port_id"] = 1; send_request(request, response); EXPECT_TRUE(response["result"] != Json::nullValue); @@ -390,6 +398,7 @@ TEST_F(RpcTest, get_owner_acquire_release) { /* soft acquire */ create_request(request, "acquire"); + request["params"]["port_id"] = 1; request["params"]["user"] = "itay"; request["params"]["force"] = false; @@ -397,6 +406,7 @@ TEST_F(RpcTest, get_owner_acquire_release) { EXPECT_TRUE(response["result"] != Json::nullValue); create_request(request, "get_owner"); + request["params"]["port_id"] = 1; send_request(request, response); EXPECT_TRUE(response["result"] != Json::nullValue); @@ -404,6 +414,7 @@ TEST_F(RpcTest, get_owner_acquire_release) { /* hard acquire */ create_request(request, "acquire"); + request["params"]["port_id"] = 1; request["params"]["user"] = "moshe"; request["params"]["force"] = false; @@ -419,6 +430,7 @@ TEST_F(RpcTest, get_owner_acquire_release) { /* make sure */ create_request(request, "get_owner"); + request["params"]["port_id"] = 1; send_request(request, response); EXPECT_TRUE(response["result"] != Json::nullValue); @@ -426,6 +438,7 @@ TEST_F(RpcTest, get_owner_acquire_release) { /* release */ create_request(request, "release"); + request["params"]["port_id"] = 1; request["params"]["handler"] = handler; send_request(request, response); @@ -463,9 +476,8 @@ TEST_F(RpcTestOwned, add_remove_stream) { Json::Value response; /* verify no such stream */ - create_request(request, "get_stream", 1); + create_request(request, "get_stream", 1, 1); - request["params"]["port_id"] = 1; request["params"]["stream_id"] = 5; send_request(request, response); @@ -475,8 +487,7 @@ TEST_F(RpcTestOwned, add_remove_stream) { EXPECT_EQ(response["error"]["code"], -32000); /* add it */ - create_request(request, "add_stream", 1); - request["params"]["port_id"] = 1; + create_request(request, "add_stream", 1, 1); request["params"]["stream_id"] = 5; Json::Value stream; @@ -488,9 +499,8 @@ TEST_F(RpcTestOwned, add_remove_stream) { EXPECT_EQ(response["result"], "ACK"); /* get it */ - create_request(request, "get_stream", 1); + create_request(request, "get_stream", 1, 1); - request["params"]["port_id"] = 1; request["params"]["stream_id"] = 5; send_request(request, response); @@ -498,9 +508,8 @@ TEST_F(RpcTestOwned, add_remove_stream) { EXPECT_TRUE(compare_streams(stream, response["result"]["stream"])); // remove it - create_request(request, "remove_stream", 1); + create_request(request, "remove_stream", 1, 1); - request["params"]["port_id"] = 1; request["params"]["stream_id"] = 5; send_request(request, response); @@ -520,7 +529,7 @@ TEST_F(RpcTestOwned, get_stream_id_list) { Json::Value response; /* add stream 1 */ - create_request(request, "add_stream"); + create_request(request, "add_stream", 1); request["params"]["port_id"] = 1; Json::Value stream; @@ -578,8 +587,7 @@ TEST_F(RpcTestOwned, start_stop_traffic) { Json::Value response; /* add stream #1 */ - create_request(request, "add_stream"); - request["params"]["port_id"] = 1; + create_request(request, "add_stream", 1, 1); request["params"]["stream_id"] = 5; Json::Value stream; @@ -590,9 +598,8 @@ TEST_F(RpcTestOwned, start_stop_traffic) { send_request(request, response); EXPECT_EQ(response["result"], "ACK"); - /* add stream #1 */ - create_request(request, "add_stream"); - request["params"]["port_id"] = 3; + /* add stream #1 */ + create_request(request, "add_stream", 1, 3); request["params"]["stream_id"] = 12; request["params"]["stream"] = stream; @@ -600,52 +607,53 @@ TEST_F(RpcTestOwned, start_stop_traffic) { EXPECT_EQ(response["result"], "ACK"); /* start port 1 */ - create_request(request, "start_traffic"); - request["params"]["port_id"] = 1; + create_request(request, "start_traffic", 1, 1); send_request(request, response); EXPECT_EQ(response["result"], "ACK"); /* start port 3 */ - request["params"]["port_id"] = 3; + create_request(request, "start_traffic", 1, 3); send_request(request, response); EXPECT_EQ(response["result"], "ACK"); /* start not configured port */ - - request["params"]["port_id"] = 2; + create_request(request, "start_traffic", 1, 2); send_request(request, response); EXPECT_EQ(response["error"]["code"], -32000); /* stop port 1 */ - create_request(request, "stop_traffic"); - request["params"]["port_id"] = 1; + create_request(request, "stop_traffic", 1, 1); send_request(request, response); EXPECT_EQ(response["result"], "ACK"); /* stop port 3 */ - request["params"]["port_id"] = 3; + create_request(request, "stop_traffic", 1, 3); send_request(request, response); EXPECT_EQ(response["result"], "ACK"); /* start 1 again */ - create_request(request, "start_traffic"); - request["params"]["port_id"] = 1; + create_request(request, "start_traffic", 1, 1); send_request(request, response); EXPECT_EQ(response["result"], "ACK"); /* start 1 twice (error) */ + create_request(request, "start_traffic", 1, 1); send_request(request, response); EXPECT_EQ(response["error"]["code"], -32000); /* make sure you cannot release while traffic is active */ - //create_request(request, "release"); - //send_request(request, response); - //EXPECT_EQ(response["error"]["code"], -32000); + create_request(request, "release", 1, 1); + send_request(request, response); + EXPECT_EQ(response["error"]["code"], -32000); - /* done */ - create_request(request, "stop_traffic"); - request["params"]["port_id"] = 1; + /* stop traffic on port #1 */ + create_request(request, "stop_traffic",1 ,1); + send_request(request, response); + EXPECT_EQ(response["result"], "ACK"); + + /* release */ + create_request(request, "release", 1, 1); send_request(request, response); EXPECT_EQ(response["result"], "ACK"); } diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index 97ccae06..106a167a 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -175,6 +175,8 @@ TrexRpcCmdGetSysInfo::_run(const Json::Value ¶ms, Json::Value &result) { section["ports"][i]["driver"] = driver; section["ports"][i]["speed"] = speed; + section["ports"][i]["owner"] = port->get_owner(); + switch (port->get_state()) { case TrexStatelessPort::PORT_STATE_DOWN: section["ports"][i]["status"] = "down"; @@ -208,7 +210,10 @@ trex_rpc_cmd_rc_e TrexRpcCmdGetOwner::_run(const Json::Value ¶ms, Json::Value &result) { Json::Value §ion = result["result"]; - section["owner"] = TrexRpcServer::get_owner(); + uint8_t port_id = parse_port(params, result); + + TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id); + section["owner"] = port->get_owner(); return (TREX_RPC_CMD_OK); } @@ -220,17 +225,21 @@ TrexRpcCmdGetOwner::_run(const Json::Value ¶ms, Json::Value &result) { trex_rpc_cmd_rc_e TrexRpcCmdAcquire::_run(const Json::Value ¶ms, Json::Value &result) { + uint8_t port_id = parse_port(params, result); + const string &new_owner = parse_string(params, "user", result); bool force = parse_bool(params, "force", result); /* if not free and not you and not force - fail */ - if ( (!TrexRpcServer::is_free_to_aquire()) && (TrexRpcServer::get_owner() != new_owner) && (!force)) { - generate_execute_err(result, "device is already taken by '" + TrexRpcServer::get_owner() + "'"); + TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id); + + if ( (!port->is_free_to_aquire()) && (port->get_owner() != new_owner) && (!force)) { + generate_execute_err(result, "device is already taken by '" + port->get_owner() + "'"); } - string handle = TrexRpcServer::set_owner(new_owner); + port->set_owner(new_owner); - result["result"] = handle; + result["result"] = port->get_owner_handler(); return (TREX_RPC_CMD_OK); } @@ -242,7 +251,15 @@ TrexRpcCmdAcquire::_run(const Json::Value ¶ms, Json::Value &result) { trex_rpc_cmd_rc_e TrexRpcCmdRelease::_run(const Json::Value ¶ms, Json::Value &result) { - TrexRpcServer::clear_owner(); + uint8_t port_id = parse_port(params, result); + + TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id); + + if (port->get_state() == TrexStatelessPort::PORT_STATE_TRANSMITTING) { + generate_execute_err(result, "cannot release a port during transmission"); + } + + port->clear_owner(); result["result"] = "ACK"; diff --git a/src/rpc-server/commands/trex_rpc_cmds.h b/src/rpc-server/commands/trex_rpc_cmds.h index 643aa22d..e261d1c6 100644 --- a/src/rpc-server/commands/trex_rpc_cmds.h +++ b/src/rpc-server/commands/trex_rpc_cmds.h @@ -69,9 +69,9 @@ void get_hostname(std::string &hostname); /** * ownership */ -TREX_RPC_CMD_DEFINE(TrexRpcCmdGetOwner, "get_owner", 0, false); -TREX_RPC_CMD_DEFINE(TrexRpcCmdAcquire, "acquire", 2, false); -TREX_RPC_CMD_DEFINE(TrexRpcCmdRelease, "release", 0, true); +TREX_RPC_CMD_DEFINE(TrexRpcCmdGetOwner, "get_owner", 1, false); +TREX_RPC_CMD_DEFINE(TrexRpcCmdAcquire, "acquire", 3, false); +TREX_RPC_CMD_DEFINE(TrexRpcCmdRelease, "release", 1, true); /** diff --git a/src/rpc-server/trex_rpc_cmd.cpp b/src/rpc-server/trex_rpc_cmd.cpp index 437e8b1a..6c355e70 100644 --- a/src/rpc-server/trex_rpc_cmd.cpp +++ b/src/rpc-server/trex_rpc_cmd.cpp @@ -20,6 +20,7 @@ limitations under the License. */ #include #include +#include trex_rpc_cmd_rc_e TrexRpcCommand::run(const Json::Value ¶ms, Json::Value &result) { @@ -57,12 +58,32 @@ TrexRpcCommand::check_param_count(const Json::Value ¶ms, int expected, Json: void TrexRpcCommand::verify_ownership(const Json::Value ¶ms, Json::Value &result) { std::string handler = parse_string(params, "handler", result); + uint8_t port_id = parse_port(params, result); - if (!TrexRpcServer::verify_owner_handler(handler)) { + TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id); + + if (!port->verify_owner_handler(handler)) { generate_execute_err(result, "invalid handler provided. please pass the handler given when calling 'acquire' or take ownership"); } } +uint8_t +TrexRpcCommand::parse_port(const Json::Value ¶ms, Json::Value &result) { + uint8_t port_id = parse_byte(params, "port_id", result); + validate_port_id(port_id, result); + + return (port_id); +} + +void +TrexRpcCommand::validate_port_id(uint8_t port_id, Json::Value &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()); + } +} + const char * TrexRpcCommand::type_to_str(field_type_e type) { switch (type) { diff --git a/src/rpc-server/trex_rpc_cmd_api.h b/src/rpc-server/trex_rpc_cmd_api.h index cab50cfd..3c718eaa 100644 --- a/src/rpc-server/trex_rpc_cmd_api.h +++ b/src/rpc-server/trex_rpc_cmd_api.h @@ -124,6 +124,12 @@ protected: */ void verify_ownership(const Json::Value ¶ms, Json::Value &result); + /** + * validate port id + * + */ + void validate_port_id(uint8_t port_id, Json::Value &result); + /** * parse functions * @@ -146,6 +152,9 @@ protected: const Json::Value & parse_object(const Json::Value &parent, int index, Json::Value &result); const Json::Value & parse_array(const Json::Value &parent, int index, Json::Value &result); + /* shortcut for parsing port id */ + uint8_t parse_port(const Json::Value ¶ms, Json::Value &result); + /** * parse a field from choices * diff --git a/src/rpc-server/trex_rpc_server.cpp b/src/rpc-server/trex_rpc_server.cpp index a5988cab..6b8c200d 100644 --- a/src/rpc-server/trex_rpc_server.cpp +++ b/src/rpc-server/trex_rpc_server.cpp @@ -111,8 +111,6 @@ get_current_date_time() { } const std::string TrexRpcServer::s_server_uptime = get_current_date_time(); -std::string TrexRpcServer::s_owner = "none"; -std::string TrexRpcServer::s_owner_handler = ""; TrexRpcServer::TrexRpcServer(const TrexRpcServerConfig &req_resp_cfg) { @@ -158,22 +156,3 @@ void TrexRpcServer::set_verbose(bool verbose) { } } -/** - * generate a random connection handler - * - */ -std::string TrexRpcServer::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/rpc-server/trex_rpc_server_api.h b/src/rpc-server/trex_rpc_server_api.h index c34ac0f8..06bbe10c 100644 --- a/src/rpc-server/trex_rpc_server_api.h +++ b/src/rpc-server/trex_rpc_server_api.h @@ -164,49 +164,7 @@ public: } - /** - * query for ownership - * - */ - static const std::string &get_owner() { - return s_owner; - } - - /** - * owner handler - * for the connection - * - */ - static const std::string &get_owner_handler() { - return s_owner_handler; - } - - static bool is_free_to_aquire() { - return (s_owner == "none"); - } - - /** - * take ownership of the server array - * this is static - * ownership is total - * - */ - static std::string set_owner(const std::string &owner) { - s_owner = owner; - s_owner_handler = generate_handler(); - return (s_owner_handler); - } - - static void clear_owner() { - s_owner = "none"; - s_owner_handler = ""; - } - - static bool verify_owner_handler(const std::string &handler) { - - return ( (s_owner != "none") && (s_owner_handler == handler) ); - - } + private: static std::string generate_handler(); diff --git a/src/stateless/trex_stateless.cpp b/src/stateless/trex_stateless.cpp index dcad1514..6a3169d4 100644 --- a/src/stateless/trex_stateless.cpp +++ b/src/stateless/trex_stateless.cpp @@ -79,6 +79,7 @@ uint8_t TrexStateless::get_port_count() { **************************/ TrexStatelessPort::TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) { m_port_state = PORT_STATE_UP_IDLE; + clear_owner(); } @@ -127,3 +128,25 @@ TrexStatelessPort::get_properties(string &driver, string &speed) { driver = "Unknown Driver"; speed = "Unknown Speed"; } + + +/** + * 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/stateless/trex_stateless_api.h b/src/stateless/trex_stateless_api.h index 60d26878..e02e93da 100644 --- a/src/stateless/trex_stateless_api.h +++ b/src/stateless/trex_stateless_api.h @@ -106,10 +106,58 @@ public: */ void get_properties(std::string &driver, std::string &speed); + /** + * query for ownership + * + */ + const std::string &get_owner() { + return m_owner; + } + + /** + * owner handler + * for the connection + * + */ + const std::string &get_owner_handler() { + return m_owner_handler; + } + + bool is_free_to_aquire() { + return (m_owner == "none"); + } + + /** + * take ownership of the server array + * this is static + * ownership is total + * + */ + void set_owner(const std::string &owner) { + m_owner = owner; + m_owner_handler = generate_handler(); + } + + void clear_owner() { + m_owner = "none"; + m_owner_handler = ""; + } + + bool verify_owner_handler(const std::string &handler) { + + return ( (m_owner != "none") && (m_owner_handler == handler) ); + + } + private: + + std::string generate_handler(); + TrexStreamTable m_stream_table; uint8_t m_port_id; port_state_e m_port_state; + std::string m_owner; + std::string m_owner_handler; }; /** -- cgit 1.2.3-korg