From 40461a9752437ee541d797f76d2fba77cad9d0e2 Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 31 Aug 2015 17:26:08 +0300 Subject: ...draft... --- src/rpc-server/commands/trex_rpc_cmd_general.cpp | 3 - src/rpc-server/commands/trex_rpc_cmd_stream.cpp | 143 ++++++++++++++++++----- src/rpc-server/commands/trex_rpc_cmd_test.cpp | 10 -- src/rpc-server/commands/trex_rpc_cmds.h | 38 ++++-- src/rpc-server/trex_rpc_cmd.cpp | 17 ++- src/rpc-server/trex_rpc_cmd_api.h | 18 ++- src/rpc-server/trex_rpc_cmds_table.cpp | 1 + src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp | 14 ++- src/stateless/trex_stream.cpp | 26 +++-- src/stateless/trex_stream_api.h | 67 +++++++---- 10 files changed, 238 insertions(+), 99 deletions(-) diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index 484cd2b9..6b765aca 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -34,9 +34,6 @@ using namespace std; trex_rpc_cmd_rc_e TrexRpcCmdGetStatus::_run(const Json::Value ¶ms, Json::Value &result) { - /* validate count */ - check_param_count(params, 0, result); - Json::Value §ion = result["result"]; #ifndef TREX_RPC_MOCK_SERVER diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp index fcd91ab7..25dee501 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp @@ -35,65 +35,148 @@ using namespace std; trex_rpc_cmd_rc_e TrexRpcCmdAddStream::_run(const Json::Value ¶ms, Json::Value &result) { - TrexStream *stream; - - check_param_count(params, 1, result); - const Json::Value §ion = parse_object(params, "stream", result); /* get the type of the stream */ const Json::Value &mode = parse_object(section, "mode", result); string type = parse_string(mode, "type", result); + TrexStream *stream = allocate_new_stream(section, result); + + /* create a new steram and populate it */ + + stream->m_isg_usec = parse_double(section, "Is", result); + + stream->m_next_stream_id = parse_int(section, "next_stream_id", result); + stream->m_loop_count = parse_int(section, "loop_count", result); + + const Json::Value &pkt = parse_array(section, "packet", result); + + /* fetch the packet from the message */ + + stream->m_pkt_len = pkt.size(); + stream->m_pkt = new uint8_t[pkt.size()]; + if (!stream->m_pkt) { + generate_internal_err(result, "unable to allocate memory"); + } + + for (int i = 0; i < pkt.size(); i++) { + stream->m_pkt[i] = parse_byte(pkt, i, result); + } + + /* make sure this is a valid stream to add */ + validate_stream(stream, result); + + TrexStatelessPort *port = get_trex_stateless()->get_port_by_id(stream->m_port_id); + port->get_stream_table()->add_stream(stream); + + result["result"] = "ACK"; + + return (TREX_RPC_CMD_OK); +} + + + +TrexStream * +TrexRpcCmdAddStream::allocate_new_stream(const Json::Value §ion, Json::Value &result) { + + uint8_t port_id = parse_int(section, "port_id", result); + uint32_t stream_id = parse_int(section, "stream_id", result); + + TrexStream *stream; + + const Json::Value &mode = parse_object(section, "mode", result); + std::string type = parse_string(mode, "type", result); + if (type == "continuous") { - stream = new TrexStreamContinuous(); + + uint32_t pps = parse_int(mode, "pps", result); + stream = new TrexStreamContinuous(port_id, stream_id, pps); + } else if (type == "single_burst") { - stream = new TrexStreamSingleBurst(); + + uint32_t pps = parse_int(mode, "pps", result); + uint32_t packets = parse_int(type, "packets", result); + + stream = new TrexStreamSingleBurst(port_id, stream_id, pps, packets); + } else if (type == "multi_burst") { - stream = new TrexStreamMultiBurst(); + + uint32_t pps = parse_int(mode, "pps", result); + double ibg_usec = parse_double(mode, "ibg", result); + uint32_t num_bursts = parse_int(mode, "number_of_bursts", result); + uint32_t pkt_per_burst = parse_int(mode, "pkt_per_burst", result); + + stream = new TrexStreamMultiBurst(port_id, stream_id, pps, ibg_usec, num_bursts, pkt_per_burst); + + } else { - generate_err(result, "bad stream type provided: '" + type + "'"); + generate_parse_err(result, "bad stream type provided: '" + type + "'"); } if (!stream) { generate_internal_err(result, "unable to allocate memory"); } - /* create a new steram and populate it */ - stream->stream_id = parse_int(section, "stream_id", result); - stream->port_id = parse_int(section, "port_id", result); - stream->isg_usec = parse_double(section, "Is", result); + return (stream); - stream->next_stream_id = parse_int(section, "next_stream_id", result); - stream->loop_count = parse_int(section, "loop_count", result); +} - const Json::Value &pkt = parse_array(section, "packet", result); +void +TrexRpcCmdAddStream::validate_stream(const TrexStream *stream, Json::Value &result) { - if ( (pkt.size() < TrexStream::MIN_PKT_SIZE_BYTES) || (pkt.size() > TrexStream::MAX_PKT_SIZE_BYTES) ) { - generate_err(result, "bad packet size provided: should be between 64B and 9K"); + /* check packet size */ + if ( (stream->m_pkt_len < TrexStream::MIN_PKT_SIZE_BYTES) || (stream->m_pkt_len > TrexStream::MAX_PKT_SIZE_BYTES) ) { + std::stringstream ss; + ss << "bad packet size provided: should be between " << TrexStream::MIN_PKT_SIZE_BYTES << " and " << TrexStream::MAX_PKT_SIZE_BYTES; + delete stream; + generate_execute_err(result, ss.str()); } - stream->pkt = new uint8_t[pkt.size()]; - if (!stream->pkt) { - generate_internal_err(result, "unable to allocate memory"); + /* port id should be between 0 and count - 1 */ + if (stream->m_port_id >= get_trex_stateless()->get_port_count()) { + std::stringstream ss; + ss << "invalid port id - should be between 0 and " << (int)get_trex_stateless()->get_port_count() - 1; + delete stream; + generate_execute_err(result, ss.str()); } - for (int i = 0; i < pkt.size(); i++) { - stream->pkt[i] = parse_byte(pkt, i, result); + /* add the stream to the port's stream table */ + TrexStatelessPort * port = get_trex_stateless()->get_port_by_id(stream->m_port_id); + + /* does such a stream exists ? */ + if (port->get_stream_table()->get_stream_by_id(stream->m_stream_id)) { + std::stringstream ss; + ss << "stream " << stream->m_stream_id << " already exists"; + delete stream; + generate_execute_err(result, ss.str()); } - /* register the stream to the port */ +} + +trex_rpc_cmd_rc_e +TrexRpcCmdRemoveStream::_run(const Json::Value ¶ms, Json::Value &result) { + uint8_t port_id = parse_byte(params, "port_id", result); + uint32_t stream_id = parse_int(params, "stream_id", result); + - /* port id should be between 0 and count - 1 */ - if (stream->port_id >= get_trex_stateless()->get_port_count()) { + if (port_id >= get_trex_stateless()->get_port_count()) { std::stringstream ss; - ss << "invalid port id - should be between 0 and " << get_trex_stateless()->get_port_count(); - generate_err(result, ss.str()); + ss << "invalid port id - should be between 0 and " << (int)get_trex_stateless()->get_port_count() - 1; + generate_execute_err(result, ss.str()); } - TrexStatelessPort * port = get_trex_stateless()->get_port_by_id(stream->port_id); - port->get_stream_table()->add_stream(stream); + TrexStatelessPort *port = get_trex_stateless()->get_port_by_id(port_id); + TrexStream *stream = port->get_stream_table()->get_stream_by_id(stream_id); - return (TREX_RPC_CMD_OK); + if (!stream) { + std::stringstream ss; + ss << "stream " << stream_id << " does not exists"; + generate_execute_err(result, ss.str()); + } + + port->get_stream_table()->remove_stream(stream); + + result["result"] = "ACK"; } diff --git a/src/rpc-server/commands/trex_rpc_cmd_test.cpp b/src/rpc-server/commands/trex_rpc_cmd_test.cpp index 473cbb70..382279ba 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_test.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_test.cpp @@ -35,8 +35,6 @@ TrexRpcCmdTestAdd::_run(const Json::Value ¶ms, Json::Value &result) { const Json::Value &x = params["x"]; const Json::Value &y = params["y"]; - check_param_count(params, 2, result); - result["result"] = parse_int(params, "x", result) + parse_int(params, "y", result); return (TREX_RPC_CMD_OK); @@ -53,8 +51,6 @@ TrexRpcCmdTestSub::_run(const Json::Value ¶ms, Json::Value &result) { const Json::Value &x = params["x"]; const Json::Value &y = params["y"]; - check_param_count(params, 2, result); - result["result"] = parse_int(params, "x", result) - parse_int(params, "y", result); return (TREX_RPC_CMD_OK); @@ -66,9 +62,6 @@ TrexRpcCmdTestSub::_run(const Json::Value ¶ms, Json::Value &result) { trex_rpc_cmd_rc_e TrexRpcCmdPing::_run(const Json::Value ¶ms, Json::Value &result) { - /* validate count */ - check_param_count(params, 0, result); - result["result"] = "ACK"; return (TREX_RPC_CMD_OK); } @@ -80,9 +73,6 @@ trex_rpc_cmd_rc_e TrexRpcCmdGetReg::_run(const Json::Value ¶ms, Json::Value &result) { vector cmds; - /* validate count */ - check_param_count(params, 0, result); - TrexRpcCommandsTable::get_instance().query(cmds); Json::Value test = Json::arrayValue; diff --git a/src/rpc-server/commands/trex_rpc_cmds.h b/src/rpc-server/commands/trex_rpc_cmds.h index 5c425856..7ec8aba3 100644 --- a/src/rpc-server/commands/trex_rpc_cmds.h +++ b/src/rpc-server/commands/trex_rpc_cmds.h @@ -25,6 +25,8 @@ limitations under the License. #include #include +class TrexStream; + /* all the RPC commands decl. goes here */ /******************* test section ************/ @@ -32,31 +34,43 @@ limitations under the License. /** * syntactic sugar for creating a simple command */ -#define TREX_RPC_CMD_DEFINE(class_name, cmd_name) \ - class class_name : public TrexRpcCommand { \ - public: \ - class_name () : TrexRpcCommand(cmd_name) {} \ - protected: \ - virtual trex_rpc_cmd_rc_e _run(const Json::Value ¶ms, Json::Value &result); \ + +#define TREX_RPC_CMD_DEFINE_EXTENED(class_name, cmd_name, param_count, ext) \ + class class_name : public TrexRpcCommand { \ + public: \ + class_name () : TrexRpcCommand(cmd_name, param_count) {} \ + 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, ;) /** * test cmds */ -TREX_RPC_CMD_DEFINE(TrexRpcCmdTestAdd, "test_add"); -TREX_RPC_CMD_DEFINE(TrexRpcCmdTestSub, "test_sub"); +TREX_RPC_CMD_DEFINE(TrexRpcCmdTestAdd, "test_add", 2); +TREX_RPC_CMD_DEFINE(TrexRpcCmdTestSub, "test_sub", 2); /** * general cmds */ -TREX_RPC_CMD_DEFINE(TrexRpcCmdPing, "ping"); -TREX_RPC_CMD_DEFINE(TrexRpcCmdGetReg, "get_reg_cmds"); -TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStatus, "get_status"); +TREX_RPC_CMD_DEFINE(TrexRpcCmdPing, "ping", 0); +TREX_RPC_CMD_DEFINE(TrexRpcCmdGetReg, "get_reg_cmds", 0); +TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStatus, "get_status", 0); /** * stream cmds */ -TREX_RPC_CMD_DEFINE(TrexRpcCmdAddStream, "add_stream"); +TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveStream, "remove_stream", 2); + +TREX_RPC_CMD_DEFINE_EXTENED(TrexRpcCmdAddStream, "add_stream", 1, + +/* extended part */ +TrexStream * allocate_new_stream(const Json::Value §ion, Json::Value &result); +void validate_stream(const TrexStream *stream, Json::Value &result); + +); + #endif /* __TREX_RPC_CMD_H__ */ diff --git a/src/rpc-server/trex_rpc_cmd.cpp b/src/rpc-server/trex_rpc_cmd.cpp index 1ba36e32..6988cba7 100644 --- a/src/rpc-server/trex_rpc_cmd.cpp +++ b/src/rpc-server/trex_rpc_cmd.cpp @@ -26,6 +26,7 @@ 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); rc = _run(params, result); } catch (TrexRpcCommandException &e) { return e.get_rc(); @@ -40,7 +41,7 @@ TrexRpcCommand::check_param_count(const Json::Value ¶ms, int expected, Json: if (params.size() != expected) { std::stringstream ss; ss << "method expects '" << expected << "' paramteres, '" << params.size() << "' provided"; - generate_err(result, ss.str()); + generate_parse_err(result, ss.str()); } } @@ -177,7 +178,7 @@ TrexRpcCommand::check_field_type_common(const Json::Value &field, const std::str /* first check if field exists */ if (field == Json::Value::null) { ss << "field '" << name << "' is missing"; - generate_err(result, ss.str()); + generate_parse_err(result, ss.str()); } bool rc = true; @@ -232,15 +233,15 @@ TrexRpcCommand::check_field_type_common(const Json::Value &field, const std::str } if (!rc) { ss << "error at offset: " << field.getOffsetStart() << " - '" << name << "' is '" << json_type_to_name(field) << "', expecting '" << type_to_str(type) << "'"; - generate_err(result, ss.str()); + generate_parse_err(result, ss.str()); } } void -TrexRpcCommand::generate_err(Json::Value &result, const std::string &msg) { +TrexRpcCommand::generate_parse_err(Json::Value &result, const std::string &msg) { result["specific_err"] = msg; - throw (TrexRpcCommandException(TREX_RPC_CMD_PARAM_PARSE_ERR)); + throw (TrexRpcCommandException(TREX_RPC_CMD_PARSE_ERR)); } void @@ -249,3 +250,9 @@ TrexRpcCommand::generate_internal_err(Json::Value &result, const std::string &ms throw (TrexRpcCommandException(TREX_RPC_CMD_INTERNAL_ERR)); } +void +TrexRpcCommand::generate_execute_err(Json::Value &result, const std::string &msg) { + result["specific_err"] = msg; + throw (TrexRpcCommandException(TREX_RPC_CMD_EXECUTE_ERR)); +} + diff --git a/src/rpc-server/trex_rpc_cmd_api.h b/src/rpc-server/trex_rpc_cmd_api.h index 40f839df..da895809 100644 --- a/src/rpc-server/trex_rpc_cmd_api.h +++ b/src/rpc-server/trex_rpc_cmd_api.h @@ -32,8 +32,8 @@ limitations under the License. */ typedef enum trex_rpc_cmd_rc_ { TREX_RPC_CMD_OK, - TREX_RPC_CMD_PARAM_COUNT_ERR = 1, - TREX_RPC_CMD_PARAM_PARSE_ERR, + TREX_RPC_CMD_PARSE_ERR, + TREX_RPC_CMD_EXECUTE_ERR, TREX_RPC_CMD_INTERNAL_ERR } trex_rpc_cmd_rc_e; @@ -68,7 +68,7 @@ public: /** * method name and params */ - TrexRpcCommand(const std::string &method_name) : m_name(method_name) { + TrexRpcCommand(const std::string &method_name, int param_count) : m_name(method_name), m_param_count(param_count) { } @@ -142,15 +142,22 @@ protected: * error generating functions * */ - void generate_err(Json::Value &result, const std::string &msg); + void generate_parse_err(Json::Value &result, const std::string &msg); + /** + * method execute error + * + */ + void generate_execute_err(Json::Value &result, const std::string &msg); + /** * internal error * */ void generate_internal_err(Json::Value &result, const std::string &msg); + /** * translate enum to string * @@ -164,7 +171,8 @@ protected: const char * json_type_to_name(const Json::Value &value); /* RPC command name */ - std::string m_name; + std::string m_name; + int m_param_count; }; #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 ac419bfd..e586c3d6 100644 --- a/src/rpc-server/trex_rpc_cmds_table.cpp +++ b/src/rpc-server/trex_rpc_cmds_table.cpp @@ -36,6 +36,7 @@ TrexRpcCommandsTable::TrexRpcCommandsTable() { /* stream commands */ register_command(new TrexRpcCmdAddStream()); + register_command(new TrexRpcCmdRemoveStream()); } TrexRpcCommandsTable::~TrexRpcCommandsTable() { diff --git a/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp index bf6056d5..3831bb37 100644 --- a/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp +++ b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp @@ -37,7 +37,10 @@ enum { JSONRPC_V2_ERR_INVALID_REQ = -32600, JSONRPC_V2_ERR_METHOD_NOT_FOUND = -32601, JSONRPC_V2_ERR_INVALID_PARAMS = -32602, - JSONRPC_V2_ERR_INTERNAL_ERROR = -32603 + JSONRPC_V2_ERR_INTERNAL_ERROR = -32603, + + /* specific server errors */ + JSONRPC_V2_ERR_EXECUTE_ERROR = -32000, }; @@ -78,13 +81,18 @@ public: response["result"] = result["result"]; break; - case TREX_RPC_CMD_PARAM_COUNT_ERR: - case TREX_RPC_CMD_PARAM_PARSE_ERR: + case TREX_RPC_CMD_PARSE_ERR: response["error"]["code"] = JSONRPC_V2_ERR_INVALID_PARAMS; response["error"]["message"] = "Bad paramters for method"; response["error"]["specific_err"] = result["specific_err"]; break; + case TREX_RPC_CMD_EXECUTE_ERR: + response["error"]["code"] = JSONRPC_V2_ERR_EXECUTE_ERROR; + response["error"]["message"] = "Failed To Execute Method"; + response["error"]["specific_err"] = result["specific_err"]; + break; + case TREX_RPC_CMD_INTERNAL_ERR: response["error"]["code"] = JSONRPC_V2_ERR_INTERNAL_ERROR; response["error"]["message"] = "Internal Server Error"; diff --git a/src/stateless/trex_stream.cpp b/src/stateless/trex_stream.cpp index 09d2b662..1a78ab34 100644 --- a/src/stateless/trex_stream.cpp +++ b/src/stateless/trex_stream.cpp @@ -24,13 +24,25 @@ limitations under the License. /************************************** * stream *************************************/ -TrexStream::TrexStream() { - pkt = NULL; +TrexStream::TrexStream(uint8_t port_id, uint32_t stream_id) : m_port_id(port_id), m_stream_id(stream_id) { + + /* default values */ + m_isg_usec = 0; + m_next_stream_id = -1; + m_loop_count = 0; + m_enable = false; + m_start = false; + + m_pkt = NULL; + m_pkt_len = 0; + + m_rx_check.m_enable = false; + } TrexStream::~TrexStream() { - if (pkt) { - delete [] pkt; + if (m_pkt) { + delete [] m_pkt; } } @@ -48,17 +60,17 @@ TrexStreamTable::~TrexStreamTable() { } void TrexStreamTable::add_stream(TrexStream *stream) { - TrexStream *old_stream = get_stream_by_id(stream->stream_id); + TrexStream *old_stream = get_stream_by_id(stream->m_stream_id); if (old_stream) { remove_stream(old_stream); delete old_stream; } - m_stream_table[stream->stream_id] = stream; + m_stream_table[stream->m_stream_id] = stream; } void TrexStreamTable::remove_stream(TrexStream *stream) { - m_stream_table.erase(stream->stream_id); + m_stream_table.erase(stream->m_stream_id); } TrexStream * TrexStreamTable::get_stream_by_id(uint32_t stream_id) { diff --git a/src/stateless/trex_stream_api.h b/src/stateless/trex_stream_api.h index ab7a8f26..7ae25c6e 100644 --- a/src/stateless/trex_stream_api.h +++ b/src/stateless/trex_stream_api.h @@ -36,38 +36,41 @@ class TrexStream { friend class TrexStreamTable; public: - TrexStream(); + TrexStream(uint8_t port_id, uint32_t stream_id); virtual ~TrexStream() = 0; - static const uint32_t MIN_PKT_SIZE_BYTES = 64; + static const uint32_t MIN_PKT_SIZE_BYTES = 1; static const uint32_t MAX_PKT_SIZE_BYTES = 9000; private: - /* config */ - uint32_t stream_id; - uint8_t port_id; - double isg_usec; - uint32_t next_stream_id; - uint32_t loop_count; + /* basic */ + uint8_t m_port_id; + uint32_t m_stream_id; + + + /* config fields */ + double m_isg_usec; + uint32_t m_next_stream_id; + uint32_t m_loop_count; /* indicators */ - bool enable; - bool start; + bool m_enable; + bool m_start; /* pkt */ - uint8_t *pkt; - uint16_t pkt_len; + uint8_t *m_pkt; + uint16_t m_pkt_len; /* VM */ /* RX check */ struct { - bool enable; - bool seq_enable; - bool latency; - uint32_t stream_id; + bool m_enable; + bool m_seq_enable; + bool m_latency; + uint32_t m_stream_id; - } rx_check; + } m_rx_check; }; @@ -76,8 +79,11 @@ 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) { + } protected: - uint32_t pps; + uint32_t m_pps; }; /** @@ -85,9 +91,13 @@ protected: * */ class TrexStreamSingleBurst : public TrexStream { +public: + TrexStreamSingleBurst(uint8_t port_id, uint32_t stream_id, uint32_t packets, uint32_t pps) : TrexStream(port_id, stream_id), m_pps(pps), m_packets(packets) { + } protected: - uint32_t packets; - uint32_t pps; + uint32_t m_pps; + uint32_t m_packets; + }; /** @@ -95,11 +105,20 @@ protected: * */ class TrexStreamMultiBurst : public TrexStream { +public: + TrexStreamMultiBurst(uint8_t port_id, + uint32_t stream_id, + uint32_t pps, + double ibg_usec, + uint32_t pkts_per_burst, + uint32_t num_bursts) : TrexStream(port_id, stream_id), m_pps(pps), m_ibg_usec(ibg_usec), m_num_bursts(num_bursts), m_pkts_per_burst(pkts_per_burst) { + + } protected: - uint32_t pps; - double ibg_usec; - uint32_t number_of_bursts; - uint32_t pkts_per_burst; + uint32_t m_pps; + double m_ibg_usec; + uint32_t m_num_bursts; + uint32_t m_pkts_per_burst; }; /** -- cgit 1.2.3-korg