From 2adc8696b8f1a9f9038a1e6377ac23e1bfd03ceb Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 24 Aug 2015 15:32:53 +0300 Subject: moved files to be on a single directory --- src/rpc-server/commands/trex_rpc_cmd_test.cpp | 99 +++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/rpc-server/commands/trex_rpc_cmd_test.cpp (limited to 'src/rpc-server/commands/trex_rpc_cmd_test.cpp') diff --git a/src/rpc-server/commands/trex_rpc_cmd_test.cpp b/src/rpc-server/commands/trex_rpc_cmd_test.cpp new file mode 100644 index 00000000..e67de286 --- /dev/null +++ b/src/rpc-server/commands/trex_rpc_cmd_test.cpp @@ -0,0 +1,99 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +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 + +using namespace std; + +/** + * add command + * + */ +trex_rpc_cmd_rc_e +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); + check_field_type(params, "x", FIELD_TYPE_INT, result); + check_field_type(params, "y", FIELD_TYPE_INT, result); + + result["result"] = x.asInt() + y.asInt(); + return (TREX_RPC_CMD_OK); +} + +/** + * sub command + * + * @author imarom (16-Aug-15) + */ +trex_rpc_cmd_rc_e +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); + check_field_type(params, "x", TrexRpcCommand::FIELD_TYPE_INT, result); + check_field_type(params, "y", TrexRpcCommand::FIELD_TYPE_INT, result); + + result["result"] = x.asInt() - y.asInt(); + return (TREX_RPC_CMD_OK); +} + +/** + * ping command + */ +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); +} + +/** + * query command + */ +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; + for (auto cmd : cmds) { + test.append(cmd); + } + + result["result"] = test; + + return (TREX_RPC_CMD_OK); +} + -- cgit 1.2.3-korg From 499b4d6221c023d656663fe441bbf5d194886efb Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 31 Aug 2015 13:42:03 +0300 Subject: SOOO DRAFT.... --- linux/ws_main.py | 14 +- linux_dpdk/ws_main.py | 1 + src/rpc-server/commands/trex_rpc_cmd_general.cpp | 17 ++- src/rpc-server/commands/trex_rpc_cmd_stream.cpp | 160 ++++++++--------------- src/rpc-server/commands/trex_rpc_cmd_test.cpp | 10 +- src/rpc-server/trex_rpc_cmd.cpp | 115 ++++++++++++++-- src/rpc-server/trex_rpc_cmd_api.h | 33 ++++- src/stateless/trex_stateless.cpp | 63 +++++++++ src/stateless/trex_stateless_api.h | 93 +++++++++++++ src/stateless/trex_stream.cpp | 72 ++++++++++ src/stateless/trex_stream_api.h | 143 ++++++++++++++++++++ 11 files changed, 594 insertions(+), 127 deletions(-) create mode 100644 src/stateless/trex_stateless.cpp create mode 100644 src/stateless/trex_stateless_api.h create mode 100644 src/stateless/trex_stream.cpp create mode 100644 src/stateless/trex_stream_api.h (limited to 'src/rpc-server/commands/trex_rpc_cmd_test.cpp') diff --git a/linux/ws_main.py b/linux/ws_main.py index e2364be4..6d8d75a0 100755 --- a/linux/ws_main.py +++ b/linux/ws_main.py @@ -138,6 +138,11 @@ net_src = SrcGroup(dir='src/common/Network/Packet', 'MacAddress.cpp', 'VLANHeader.cpp']); +# stateless code +stateless_src = SrcGroup(dir='src/stateless/', + src_list=['trex_stream.cpp', + 'trex_stateless.cpp' + ]) # RPC code rpc_server_src = SrcGroup(dir='src/rpc-server/', src_list=[ @@ -169,6 +174,7 @@ json_src = SrcGroup(dir='external_libs/json', rpc_server_mock = SrcGroups([cmn_src, rpc_server_src, rpc_server_mock_src, + stateless_src, json_src ]) @@ -225,6 +231,7 @@ cxxflags_base =['-DWIN_UCODE_SIM', includes_path =''' ../src/pal/linux/ ../src/ ../src/rpc-server/ + ../src/stateless/ ../external_libs/json/ ../external_libs/zmq/include/ ../external_libs/yaml-cpp/include/ @@ -242,13 +249,14 @@ PLATFORM_32 = "32" class build_option: - def __init__(self, name, src, platform, debug_mode, is_pie, use = []): + def __init__(self, name, src, platform, debug_mode, is_pie, use = [], flags = []): self.mode = debug_mode; ##debug,release self.platform = platform; #['32','64'] self.is_pie = is_pie self.name = name self.src = src self.use = use + self.flags = flags def __str__(self): s=self.mode+","+self.platform; @@ -313,6 +321,8 @@ class build_option: if self.isPIE(): result += ['-fPIE', '-DPATCH_FOR_PIE'] + result += self.flags + return result; def get_use_libs (self): @@ -353,7 +363,7 @@ 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), + 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']), ] diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py index 24ffe18e..60c9a114 100755 --- a/linux_dpdk/ws_main.py +++ b/linux_dpdk/ws_main.py @@ -402,6 +402,7 @@ includes_path =''' ../src/pal/linux_dpdk/ ../src/ ../src/rpc-server/ + ../src/stateless/ ../external_libs/yaml-cpp/include/ ../external_libs/zmq/include/ diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index ac35babf..484cd2b9 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -19,9 +19,12 @@ See the License for the specific language governing permissions and limitations under the License. */ #include "trex_rpc_cmds.h" -#include <../linux_dpdk/version.h> #include +#ifndef TREX_RPC_MOCK_SERVER + #include <../linux_dpdk/version.h> +#endif + using namespace std; /** @@ -36,12 +39,24 @@ TrexRpcCmdGetStatus::_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"]["version_user"] = VERSION_USER; section["general"]["uptime"] = TrexRpcServer::get_server_uptime(); + #else + + section["general"]["version"] = "v0.0"; + section["general"]["build_date"] = __DATE__; + section["general"]["build_time"] = __TIME__; + section["general"]["version_user"] = "MOCK"; + section["general"]["uptime"] = TrexRpcServer::get_server_uptime(); + + #endif + 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 58226a6b..fcd91ab7 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp @@ -21,134 +21,78 @@ limitations under the License. #include "trex_rpc_cmds.h" #include <../linux_dpdk/version.h> #include +#include +#include -using namespace std; +#include -/** - * Stateless stream mode - * abstract class - */ -class TrexStreamMode { -public: - enum mode_e { - CONTINUOUS, - SINGLE_BURST, - MULTI_BURST - }; - - virtual mode_e get_runtime_type() = 0; - virtual ~TrexStreamMode() {} -}; +using namespace std; /** - * stream mode continuous + * add new stream * - * @author imarom (30-Aug-15) */ -class TrexStreamModeContinuous : public TrexStreamMode { -public: - mode_e get_runtime_type() { - return (CONTINUOUS); - } -private: - uint32_t pps; -}; +trex_rpc_cmd_rc_e +TrexRpcCmdAddStream::_run(const Json::Value ¶ms, Json::Value &result) { -/** - * single burst mode - * - */ -class TrexStreamModeSingleBurst : public TrexStreamMode { -public: - mode_e get_runtime_type() { - return (SINGLE_BURST); - } -private: + TrexStream *stream; - uint32_t packets; - uint32_t pps; -}; + check_param_count(params, 1, result); + + const Json::Value §ion = parse_object(params, "stream", result); -class TrexStreamModeMultiBurst : public TrexStreamMode { -public: + /* get the type of the stream */ + const Json::Value &mode = parse_object(section, "mode", result); + string type = parse_string(mode, "type", result); + + if (type == "continuous") { + stream = new TrexStreamContinuous(); + } else if (type == "single_burst") { + stream = new TrexStreamSingleBurst(); + } else if (type == "multi_burst") { + stream = new TrexStreamMultiBurst(); + } else { + generate_err(result, "bad stream type provided: '" + type + "'"); + } - mode_e get_runtime_type() { - return (MULTI_BURST); + if (!stream) { + generate_internal_err(result, "unable to allocate memory"); } -private: + /* 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); - uint32_t pps; - double ibg_usec; - uint32_t number_of_bursts; - uint32_t pkts_per_burst; -}; + 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); -/** - * Stateless Stream - * - */ -class TrexStatelessStream { - friend class TrexRpcCmdAddStream; - -public: - -private: - /* config */ - uint32_t stream_id; - uint8_t port_id; - double isg_usec; - uint32_t next_stream_id; - uint32_t loop_count; - - /* indicators */ - bool enable; - bool start; - - /* pkt */ - uint8_t *pkt; - uint16_t pkt_len; - - /* stream mode */ - TrexStreamMode *mode; - - /* VM */ - - /* RX check */ - struct { - bool enable; - bool seq_enable; - bool latency; - uint32_t stream_id; - - } rx_check; - -}; -/** - * add new stream - * - */ -trex_rpc_cmd_rc_e -TrexRpcCmdAddStream::_run(const Json::Value ¶ms, 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"); + } - TrexStatelessStream stream; + stream->pkt = new uint8_t[pkt.size()]; + if (!stream->pkt) { + generate_internal_err(result, "unable to allocate memory"); + } - check_param_count(params, 1, result); - check_field_type(params, "stream", FIELD_TYPE_OBJ, result); + for (int i = 0; i < pkt.size(); i++) { + stream->pkt[i] = parse_byte(pkt, i, result); + } - Json::Value §ion = result["stream"]; - - /* create a new steram and populate it */ - - check_field_type(section, "stream_id", FIELD_TYPE_INT, result); - stream.stream_id = section["stream_id"].asInt(); + /* register the stream to the port */ - check_field_type(section, "port_id", FIELD_TYPE_INT, result); - stream.port_id = section["port_id"].asInt(); + /* port id should be between 0 and count - 1 */ + if (stream->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()); + } - check_field_type(section, "Is", FIELD_TYPE_DOUBLE, result); - stream.isg_usec = section["Is"].asDouble(); + TrexStatelessPort * port = get_trex_stateless()->get_port_by_id(stream->port_id); + port->get_stream_table()->add_stream(stream); return (TREX_RPC_CMD_OK); } diff --git a/src/rpc-server/commands/trex_rpc_cmd_test.cpp b/src/rpc-server/commands/trex_rpc_cmd_test.cpp index e67de286..473cbb70 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_test.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_test.cpp @@ -36,10 +36,9 @@ TrexRpcCmdTestAdd::_run(const Json::Value ¶ms, Json::Value &result) { const Json::Value &y = params["y"]; check_param_count(params, 2, result); - check_field_type(params, "x", FIELD_TYPE_INT, result); - check_field_type(params, "y", FIELD_TYPE_INT, result); - result["result"] = x.asInt() + y.asInt(); + result["result"] = parse_int(params, "x", result) + parse_int(params, "y", result); + return (TREX_RPC_CMD_OK); } @@ -55,10 +54,9 @@ TrexRpcCmdTestSub::_run(const Json::Value ¶ms, Json::Value &result) { const Json::Value &y = params["y"]; check_param_count(params, 2, result); - check_field_type(params, "x", TrexRpcCommand::FIELD_TYPE_INT, result); - check_field_type(params, "y", TrexRpcCommand::FIELD_TYPE_INT, result); - result["result"] = x.asInt() - y.asInt(); + result["result"] = parse_int(params, "x", result) - parse_int(params, "y", result); + return (TREX_RPC_CMD_OK); } diff --git a/src/rpc-server/trex_rpc_cmd.cpp b/src/rpc-server/trex_rpc_cmd.cpp index 1ad94fb5..1ba36e32 100644 --- a/src/rpc-server/trex_rpc_cmd.cpp +++ b/src/rpc-server/trex_rpc_cmd.cpp @@ -41,13 +41,14 @@ TrexRpcCommand::check_param_count(const Json::Value ¶ms, int expected, Json: std::stringstream ss; ss << "method expects '" << expected << "' paramteres, '" << params.size() << "' provided"; generate_err(result, ss.str()); - throw TrexRpcCommandException(TREX_RPC_CMD_PARAM_COUNT_ERR); } } const char * TrexRpcCommand::type_to_str(field_type_e type) { switch (type) { + case FIELD_TYPE_BYTE: + return "byte"; case FIELD_TYPE_BOOL: return "bool"; case FIELD_TYPE_INT: @@ -58,7 +59,7 @@ TrexRpcCommand::type_to_str(field_type_e type) { return "object"; case FIELD_TYPE_STR: return "string"; - case FILED_TYPE_ARRAY: + case FIELD_TYPE_ARRAY: return "array"; default: @@ -72,6 +73,8 @@ TrexRpcCommand::json_type_to_name(const Json::Value &value) { switch(value.type()) { case Json::nullValue: return "null"; + case Json::intValue: + return "int"; case Json::uintValue: return "uint"; case Json::realValue: @@ -90,23 +93,102 @@ TrexRpcCommand::json_type_to_name(const Json::Value &value) { } } + +uint8_t +TrexRpcCommand::parse_byte(const Json::Value &parent, const std::string &name, Json::Value &result) { + check_field_type(parent, name, FIELD_TYPE_BYTE, result); + return parent[name].asUInt(); +} + +uint8_t +TrexRpcCommand::parse_byte(const Json::Value &parent, int index, Json::Value &result) { + check_field_type(parent, index, FIELD_TYPE_BYTE, result); + return parent[index].asUInt(); +} + +int +TrexRpcCommand::parse_int(const Json::Value &parent, const std::string &name, Json::Value &result) { + check_field_type(parent, name, FIELD_TYPE_INT, result); + return parent[name].asInt(); +} + +bool +TrexRpcCommand::parse_bool(const Json::Value &parent, const std::string &name, Json::Value &result) { + check_field_type(parent, name, FIELD_TYPE_BOOL, result); + return parent[name].asBool(); +} + +double +TrexRpcCommand::parse_double(const Json::Value &parent, const std::string &name, Json::Value &result) { + check_field_type(parent, name, FIELD_TYPE_DOUBLE, result); + return parent[name].asDouble(); +} + +const std::string +TrexRpcCommand::parse_string(const Json::Value &parent, const std::string &name, Json::Value &result) { + check_field_type(parent, name, FIELD_TYPE_STR, result); + return parent[name].asString(); +} + +const Json::Value & +TrexRpcCommand::parse_object(const Json::Value &parent, const std::string &name, Json::Value &result) { + check_field_type(parent, name, FIELD_TYPE_OBJ, result); + return parent[name]; +} + +const Json::Value & +TrexRpcCommand::parse_array(const Json::Value &parent, const std::string &name, Json::Value &result) { + check_field_type(parent, name, FIELD_TYPE_ARRAY, result); + return parent[name]; +} + +/** + * for index element (array) + */ void -TrexRpcCommand::check_field_type(const Json::Value &parent, const std::string &name, field_type_e type, Json::Value &result) { +TrexRpcCommand::check_field_type(const Json::Value &parent, int index, field_type_e type, Json::Value &result) { + + /* should never get here without parent being array */ + if (!parent.isArray()) { + throw TrexRpcException("internal parsing error"); + } + + const Json::Value &field = parent[index]; + std::stringstream ss; + ss << "array element: " << (index + 1) << " "; + check_field_type_common(field, ss.str(), type, result); +} + +void +TrexRpcCommand::check_field_type(const Json::Value &parent, const std::string &name, field_type_e type, Json::Value &result) { + /* should never get here without parent being object */ + if (!parent.isObject()) { + throw TrexRpcException("internal parsing error"); + } - /* check if field exists , does not add the field because its const */ const Json::Value &field = parent[name]; + check_field_type_common(field, name, type, result); +} +void +TrexRpcCommand::check_field_type_common(const Json::Value &field, const std::string &name, field_type_e type, Json::Value &result) { + std::stringstream ss; /* first check if field exists */ if (field == Json::Value::null) { - ss << "field '" << name << "' missing"; + ss << "field '" << name << "' is missing"; generate_err(result, ss.str()); - throw (TrexRpcCommandException(TREX_RPC_CMD_PARAM_PARSE_ERR)); } bool rc = true; switch (type) { + case FIELD_TYPE_BYTE: + if ( (!field.isUInt()) || (field.asInt() > 0xFF)) { + rc = false; + } + break; + case FIELD_TYPE_BOOL: if (!field.isBool()) { rc = false; @@ -136,12 +218,21 @@ TrexRpcCommand::check_field_type(const Json::Value &parent, const std::string &n rc = false; } break; - } + case FIELD_TYPE_ARRAY: + if (!field.isArray()) { + rc = false; + } + break; + + default: + throw TrexRpcException("unhandled type"); + break; + + } 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()); - throw (TrexRpcCommandException(TREX_RPC_CMD_PARAM_PARSE_ERR)); } } @@ -149,4 +240,12 @@ TrexRpcCommand::check_field_type(const Json::Value &parent, const std::string &n void TrexRpcCommand::generate_err(Json::Value &result, const std::string &msg) { result["specific_err"] = msg; + throw (TrexRpcCommandException(TREX_RPC_CMD_PARAM_PARSE_ERR)); +} + +void +TrexRpcCommand::generate_internal_err(Json::Value &result, const std::string &msg) { + result["specific_err"] = msg; + throw (TrexRpcCommandException(TREX_RPC_CMD_INTERNAL_ERR)); } + diff --git a/src/rpc-server/trex_rpc_cmd_api.h b/src/rpc-server/trex_rpc_cmd_api.h index 34e6ba0a..40f839df 100644 --- a/src/rpc-server/trex_rpc_cmd_api.h +++ b/src/rpc-server/trex_rpc_cmd_api.h @@ -90,12 +90,13 @@ protected: * different types of fields */ enum field_type_e { + FIELD_TYPE_BYTE, FIELD_TYPE_INT, FIELD_TYPE_DOUBLE, FIELD_TYPE_BOOL, FIELD_TYPE_STR, FIELD_TYPE_OBJ, - FILED_TYPE_ARRAY + FIELD_TYPE_ARRAY }; /** @@ -109,12 +110,33 @@ protected: */ void check_param_count(const Json::Value ¶ms, int expected, Json::Value &result); + /** + * parse functions + * + */ + uint8_t parse_byte(const Json::Value &parent, const std::string &name, Json::Value &result); + int parse_int(const Json::Value &parent, const std::string &name, Json::Value &result); + double parse_double(const Json::Value &parent, const std::string &name, Json::Value &result); + bool parse_bool(const Json::Value &parent, const std::string &name, Json::Value &result); + const std::string parse_string(const Json::Value &parent, const std::string &name, Json::Value &result); + const Json::Value & parse_object(const Json::Value &parent, const std::string &name, Json::Value &result); + const Json::Value & parse_array(const Json::Value &parent, const std::string &name, Json::Value &result); + + uint8_t parse_byte(const Json::Value &parent, int index, Json::Value &result); + int parse_int(const Json::Value &parent, int index, Json::Value &result); + double parse_double(const Json::Value &parent, int index, Json::Value &result); + bool parse_bool(const Json::Value &parent, int index, Json::Value &result); + const std::string parse_string(const Json::Value &parent, int index, Json::Value &result); + 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); + /** * check field type * */ - //void check_field_type(const Json::Value &field, field_type_e type, Json::Value &result); void check_field_type(const Json::Value &parent, const std::string &name, field_type_e type, Json::Value &result); + void check_field_type(const Json::Value &parent, int index, field_type_e type, Json::Value &result); + void check_field_type_common(const Json::Value &field, const std::string &name, field_type_e type, Json::Value &result); /** * error generating functions @@ -122,6 +144,13 @@ protected: */ void generate_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 * diff --git a/src/stateless/trex_stateless.cpp b/src/stateless/trex_stateless.cpp new file mode 100644 index 00000000..05931983 --- /dev/null +++ b/src/stateless/trex_stateless.cpp @@ -0,0 +1,63 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +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 stateless object + * + **********************************************************/ +TrexStateless::TrexStateless(uint8_t port_count) : m_port_count(port_count) { + + m_ports = new TrexStatelessPort*[port_count]; + + for (int i = 0; i < m_port_count; i++) { + m_ports[i] = new TrexStatelessPort(i); + } +} + +TrexStateless::~TrexStateless() { + for (int i = 0; i < m_port_count; i++) { + delete m_ports[i]; + } + + delete m_ports; +} + +TrexStatelessPort * TrexStateless::get_port_by_id(uint8_t port_id) { + if (port_id >= m_port_count) { + throw TrexException("index out of range"); + } + + return m_ports[port_id]; + +} + +uint8_t TrexStateless::get_port_count() { + return m_port_count; +} + +/******** HACK - REMOVE ME ***********/ +TrexStateless * get_trex_stateless() { + static TrexStateless trex_stateless(8); + return &trex_stateless; + +} + diff --git a/src/stateless/trex_stateless_api.h b/src/stateless/trex_stateless_api.h new file mode 100644 index 00000000..50cc3947 --- /dev/null +++ b/src/stateless/trex_stateless_api.h @@ -0,0 +1,93 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +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. +*/ +#ifndef __TREX_STATELESS_API_H__ +#define __TREX_STATELESS_API_H__ + +#include +#include +#include + +#include + +/** + * generic exception for errors + * + */ +class TrexException : public std::runtime_error +{ +public: + TrexException() : std::runtime_error("") { + + } + TrexException(const std::string &what) : std::runtime_error(what) { + } +}; + +/** + * + * + * @author imarom (31-Aug-15) + */ +class TrexStatelessPort { +public: + + TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) { + } + + TrexStreamTable *get_stream_table() { + return &m_stream_table; + } + +private: + /* a stream table per port */ + TrexStreamTable m_stream_table; + uint8_t m_port_id; +}; + +/** + * defines the T-Rex stateless operation mode + * + */ +class TrexStateless { +public: + /** + * create a T-Rex stateless object + * + * @author imarom (31-Aug-15) + * + * @param port_count + */ + TrexStateless(uint8_t port_count); + ~TrexStateless(); + + TrexStatelessPort *get_port_by_id(uint8_t port_id); + uint8_t get_port_count(); + +protected: + TrexStatelessPort **m_ports; + uint8_t m_port_count; +}; + +/****** HACK *******/ +TrexStateless *get_trex_stateless(); + +#endif /* __TREX_STATELESS_API_H__ */ + diff --git a/src/stateless/trex_stream.cpp b/src/stateless/trex_stream.cpp new file mode 100644 index 00000000..09d2b662 --- /dev/null +++ b/src/stateless/trex_stream.cpp @@ -0,0 +1,72 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +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 +#include + +/************************************** + * stream + *************************************/ +TrexStream::TrexStream() { + pkt = NULL; +} + +TrexStream::~TrexStream() { + if (pkt) { + delete [] pkt; + } +} + +/************************************** + * stream table + *************************************/ +TrexStreamTable::TrexStreamTable() { + +} + +TrexStreamTable::~TrexStreamTable() { + for (auto stream : m_stream_table) { + delete stream.second; + } +} + +void TrexStreamTable::add_stream(TrexStream *stream) { + TrexStream *old_stream = get_stream_by_id(stream->stream_id); + if (old_stream) { + remove_stream(old_stream); + delete old_stream; + } + + m_stream_table[stream->stream_id] = stream; +} + +void TrexStreamTable::remove_stream(TrexStream *stream) { + m_stream_table.erase(stream->stream_id); +} + +TrexStream * TrexStreamTable::get_stream_by_id(uint32_t stream_id) { + auto search = m_stream_table.find(stream_id); + + if (search != m_stream_table.end()) { + return search->second; + } else { + return NULL; + } +} diff --git a/src/stateless/trex_stream_api.h b/src/stateless/trex_stream_api.h new file mode 100644 index 00000000..ab7a8f26 --- /dev/null +++ b/src/stateless/trex_stream_api.h @@ -0,0 +1,143 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +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. +*/ +#ifndef __TREX_STREAM_API_H__ +#define __TREX_STREAM_API_H__ + +#include +#include + +class TrexRpcCmdAddStream; + +/** + * Stateless Stream + * + */ +class TrexStream { + /* provide the RPC parser a way to access private fields */ + friend class TrexRpcCmdAddStream; + friend class TrexStreamTable; + +public: + TrexStream(); + virtual ~TrexStream() = 0; + + static const uint32_t MIN_PKT_SIZE_BYTES = 64; + 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; + + /* indicators */ + bool enable; + bool start; + + /* pkt */ + uint8_t *pkt; + uint16_t pkt_len; + + /* VM */ + + /* RX check */ + struct { + bool enable; + bool seq_enable; + bool latency; + uint32_t stream_id; + + } rx_check; + +}; + +/** + * continuous stream + * + */ +class TrexStreamContinuous : public TrexStream { +protected: + uint32_t pps; +}; + +/** + * single burst + * + */ +class TrexStreamSingleBurst : public TrexStream { +protected: + uint32_t packets; + uint32_t pps; +}; + +/** + * multi burst + * + */ +class TrexStreamMultiBurst : public TrexStream { +protected: + uint32_t pps; + double ibg_usec; + uint32_t number_of_bursts; + uint32_t pkts_per_burst; +}; + +/** + * holds all the streams + * + */ +class TrexStreamTable { +public: + + TrexStreamTable(); + ~TrexStreamTable(); + + /** + * add a stream + * if a previous one exists, the old one will be deleted + */ + void add_stream(TrexStream *stream); + + /** + * remove a stream + * + */ + void remove_stream(TrexStream *stream); + + /** + * fetch a stream if exists + * o.w NULL + * + */ + TrexStream * get_stream_by_id(uint32_t stream_id); + +private: + /** + * holds all the stream in a hash table by stream id + * + */ + std::unordered_map m_stream_table; +}; + +#endif /* __TREX_STREAM_API_H__ */ + -- cgit 1.2.3-korg 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(-) (limited to 'src/rpc-server/commands/trex_rpc_cmd_test.cpp') 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 From c17add108ead1ffbdf0c909684c5f8b18632f3d8 Mon Sep 17 00:00:00 2001 From: imarom Date: Tue, 1 Sep 2015 17:16:27 +0300 Subject: draft --- linux_dpdk/ws_main.py | 2 -- src/rpc-server/commands/trex_rpc_cmd_stream.cpp | 45 +++++++++++++++++++++++-- src/rpc-server/commands/trex_rpc_cmd_test.cpp | 8 +---- src/rpc-server/commands/trex_rpc_cmds.h | 3 +- src/rpc-server/trex_rpc_cmds_table.cpp | 1 + src/stateless/trex_stream.cpp | 10 ++++++ src/stateless/trex_stream_api.h | 9 +++-- 7 files changed, 63 insertions(+), 15 deletions(-) (limited to 'src/rpc-server/commands/trex_rpc_cmd_test.cpp') diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py index 60c9a114..e1aa8eaf 100755 --- a/linux_dpdk/ws_main.py +++ b/linux_dpdk/ws_main.py @@ -345,8 +345,6 @@ bp =SrcGroups([ main_src, cmn_src , net_src , - rpc_server_src, - json_src, yaml_src, version_src ]); diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp index 57fa23d4..cda917ac 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp @@ -28,10 +28,10 @@ limitations under the License. using namespace std; -/** +/*************************** * add new stream * - */ + **************************/ trex_rpc_cmd_rc_e TrexRpcCmdAddStream::_run(const Json::Value ¶ms, Json::Value &result) { @@ -63,10 +63,23 @@ TrexRpcCmdAddStream::_run(const Json::Value ¶ms, Json::Value &result) { generate_internal_err(result, "unable to allocate memory"); } + /* parse the packet */ for (int i = 0; i < pkt.size(); i++) { stream->m_pkt[i] = parse_byte(pkt, i, result); } + /* parse RX info */ + const Json::Value &rx = parse_object(section, "rx_stats", result); + + stream->m_rx_check.m_enable = parse_bool(rx, "enabled", result); + + /* if it is enabled - we need more fields */ + if (stream->m_rx_check.m_enable) { + stream->m_rx_check.m_stream_id = parse_int(rx, "stream_id", result); + stream->m_rx_check.m_seq_enabled = parse_bool(rx, "seq_enabled", result); + stream->m_rx_check.m_latency = parse_bool(rx, "latency", result); + } + /* make sure this is a valid stream to add */ validate_stream(stream, result); @@ -117,6 +130,7 @@ TrexRpcCmdAddStream::allocate_new_stream(const Json::Value §ion, Json::Value generate_parse_err(result, "bad stream type provided: '" + type + "'"); } + /* make sure we were able to allocate the memory */ if (!stream) { generate_internal_err(result, "unable to allocate memory"); } @@ -157,6 +171,10 @@ TrexRpcCmdAddStream::validate_stream(const TrexStream *stream, Json::Value &resu } +/*************************** + * remove stream + * + **************************/ trex_rpc_cmd_rc_e TrexRpcCmdRemoveStream::_run(const Json::Value ¶ms, Json::Value &result) { uint8_t port_id = parse_byte(params, "port_id", result); @@ -170,7 +188,7 @@ TrexRpcCmdRemoveStream::_run(const Json::Value ¶ms, Json::Value &result) { } TrexStatelessPort *port = get_trex_stateless()->get_port_by_id(port_id); - TrexStream *stream = port->get_stream_table()->get_stream_by_id(stream_id); + TrexStream *stream = port->get_stream_table()->get_stream_by_id(stream_id); if (!stream) { std::stringstream ss; @@ -183,3 +201,24 @@ TrexRpcCmdRemoveStream::_run(const Json::Value ¶ms, Json::Value &result) { result["result"] = "ACK"; } +/*************************** + * remove all streams + * for a port + * + **************************/ +trex_rpc_cmd_rc_e +TrexRpcCmdRemoveAllStreams::_run(const Json::Value ¶ms, Json::Value &result) { + uint8_t port_id = parse_byte(params, "port_id", result); + + if (port_id >= get_trex_stateless()->get_port_count()) { + std::stringstream ss; + 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(port_id); + port->get_stream_table()->remove_and_delete_all_streams(); + + 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 382279ba..3153317e 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_test.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_test.cpp @@ -32,11 +32,8 @@ using namespace std; trex_rpc_cmd_rc_e TrexRpcCmdTestAdd::_run(const Json::Value ¶ms, Json::Value &result) { - const Json::Value &x = params["x"]; - const Json::Value &y = params["y"]; - result["result"] = parse_int(params, "x", result) + parse_int(params, "y", result); - + return (TREX_RPC_CMD_OK); } @@ -48,9 +45,6 @@ TrexRpcCmdTestAdd::_run(const Json::Value ¶ms, Json::Value &result) { trex_rpc_cmd_rc_e TrexRpcCmdTestSub::_run(const Json::Value ¶ms, Json::Value &result) { - const Json::Value &x = params["x"]; - const Json::Value &y = params["y"]; - result["result"] = parse_int(params, "x", result) - parse_int(params, "y", result); 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 7ec8aba3..64551fac 100644 --- a/src/rpc-server/commands/trex_rpc_cmds.h +++ b/src/rpc-server/commands/trex_rpc_cmds.h @@ -62,7 +62,8 @@ TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStatus, "get_status", 0); /** * stream cmds */ -TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveStream, "remove_stream", 2); +TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveAllStreams, "remove_all_streams", 1); +TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveStream, "remove_stream", 2); TREX_RPC_CMD_DEFINE_EXTENED(TrexRpcCmdAddStream, "add_stream", 1, diff --git a/src/rpc-server/trex_rpc_cmds_table.cpp b/src/rpc-server/trex_rpc_cmds_table.cpp index e586c3d6..7d5d49ae 100644 --- a/src/rpc-server/trex_rpc_cmds_table.cpp +++ b/src/rpc-server/trex_rpc_cmds_table.cpp @@ -37,6 +37,7 @@ TrexRpcCommandsTable::TrexRpcCommandsTable() { /* stream commands */ register_command(new TrexRpcCmdAddStream()); register_command(new TrexRpcCmdRemoveStream()); + register_command(new TrexRpcCmdRemoveAllStreams()); } TrexRpcCommandsTable::~TrexRpcCommandsTable() { diff --git a/src/stateless/trex_stream.cpp b/src/stateless/trex_stream.cpp index 5bc9421f..1465b1ba 100644 --- a/src/stateless/trex_stream.cpp +++ b/src/stateless/trex_stream.cpp @@ -72,6 +72,16 @@ void TrexStreamTable::remove_stream(TrexStream *stream) { m_stream_table.erase(stream->m_stream_id); } + +void TrexStreamTable::remove_and_delete_all_streams() { + + for (auto stream : m_stream_table) { + delete stream.second; + } + + m_stream_table.clear(); +} + TrexStream * TrexStreamTable::get_stream_by_id(uint32_t stream_id) { auto search = m_stream_table.find(stream_id); diff --git a/src/stateless/trex_stream_api.h b/src/stateless/trex_stream_api.h index bae82862..f57b7aae 100644 --- a/src/stateless/trex_stream_api.h +++ b/src/stateless/trex_stream_api.h @@ -66,7 +66,7 @@ private: /* RX check */ struct { bool m_enable; - bool m_seq_enable; + bool m_seq_enabled; bool m_latency; uint32_t m_stream_id; @@ -141,10 +141,15 @@ public: /** * remove a stream - * */ void remove_stream(TrexStream *stream); + /** + * remove all streams on the table + * memory will be deleted + */ + void remove_and_delete_all_streams(); + /** * fetch a stream if exists * o.w NULL -- cgit 1.2.3-korg