summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2015-08-31 13:42:03 +0300
committerimarom <imarom@cisco.com>2015-08-31 13:42:03 +0300
commit499b4d6221c023d656663fe441bbf5d194886efb (patch)
tree971c0738a56adfd9d39790b843ef1d1a83b88229
parentc9381643e7bf9b3dc690bf3e012ad6176ee32b8c (diff)
SOOO DRAFT....
-rwxr-xr-xlinux/ws_main.py14
-rwxr-xr-xlinux_dpdk/ws_main.py1
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_general.cpp17
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_stream.cpp160
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_test.cpp10
-rw-r--r--src/rpc-server/trex_rpc_cmd.cpp115
-rw-r--r--src/rpc-server/trex_rpc_cmd_api.h33
-rw-r--r--src/stateless/trex_stateless.cpp63
-rw-r--r--src/stateless/trex_stateless_api.h93
-rw-r--r--src/stateless/trex_stream.cpp72
-rw-r--r--src/stateless/trex_stream_api.h143
11 files changed, 594 insertions, 127 deletions
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 <trex_rpc_server_api.h>
+#ifndef TREX_RPC_MOCK_SERVER
+ #include <../linux_dpdk/version.h>
+#endif
+
using namespace std;
/**
@@ -36,12 +39,24 @@ TrexRpcCmdGetStatus::_run(const Json::Value &params, Json::Value &result) {
Json::Value &section = 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 <trex_rpc_server_api.h>
+#include <trex_stream_api.h>
+#include <trex_stateless_api.h>
-using namespace std;
+#include <iostream>
-/**
- * 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 &params, 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 &section = 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 &params, 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 &section = 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 &params, 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 &params, 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 &params, 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
};
/**
@@ -110,11 +111,32 @@ protected:
void check_param_count(const Json::Value &params, 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_api.h>
+
+/***********************************************************
+ * 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 <stdint.h>
+#include <string>
+#include <stdexcept>
+
+#include <trex_stream_api.h>
+
+/**
+ * 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 <trex_stream_api.h>
+#include <cstddef>
+
+/**************************************
+ * 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 <unordered_map>
+#include <stdint.h>
+
+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<int, TrexStream *> m_stream_table;
+};
+
+#endif /* __TREX_STREAM_API_H__ */
+