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/rpc-server/trex_rpc_cmd.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/rpc-server/trex_rpc_cmd.cpp') 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) { -- 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(-) (limited to 'src/rpc-server/trex_rpc_cmd.cpp') 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