SOOO DRAFT....
authorimarom <[email protected]>
Mon, 31 Aug 2015 10:42:03 +0000 (13:42 +0300)
committerimarom <[email protected]>
Mon, 31 Aug 2015 10:42:03 +0000 (13:42 +0300)
linux/ws_main.py
linux_dpdk/ws_main.py
src/rpc-server/commands/trex_rpc_cmd_general.cpp
src/rpc-server/commands/trex_rpc_cmd_stream.cpp
src/rpc-server/commands/trex_rpc_cmd_test.cpp
src/rpc-server/trex_rpc_cmd.cpp
src/rpc-server/trex_rpc_cmd_api.h
src/stateless/trex_stateless.cpp [new file with mode: 0644]
src/stateless/trex_stateless_api.h [new file with mode: 0644]
src/stateless/trex_stream.cpp [new file with mode: 0644]
src/stateless/trex_stream_api.h [new file with mode: 0644]

index e2364be..6d8d75a 100755 (executable)
@@ -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']),
               ]
 
 
index 24ffe18..60c9a11 100755 (executable)
@@ -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/
index ac35bab..484cd2b 100644 (file)
@@ -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);
 }
 
index 58226a6..fcd91ab 100644 (file)
@@ -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);
 }
index e67de28..473cbb7 100644 (file)
@@ -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);
 }
 
index 1ad94fb..1ba36e3 100644 (file)
@@ -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));
 }
+
index 34e6ba0..40f839d 100644 (file)
@@ -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 &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 (file)
index 0000000..0593198
--- /dev/null
@@ -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 (file)
index 0000000..50cc394
--- /dev/null
@@ -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 (file)
index 0000000..09d2b66
--- /dev/null
@@ -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 (file)
index 0000000..ab7a8f2
--- /dev/null
@@ -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__ */
+