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 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