summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2016-04-03 18:19:20 +0300
committerimarom <imarom@cisco.com>2016-04-04 09:49:54 +0300
commit4eacb570cf24927de536d23671f50609f1a9ffa5 (patch)
tree83b8dcd86994c7668a054413d0ba0449a1cf2816
parent0eb15b2e851b5f50669633678143c5a1d3a7d95b (diff)
API classes (versions)
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py41
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_jsonrpc_client.py25
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py16
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py5
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py2
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py2
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py2
-rwxr-xr-xsrc/common/basic_utils.cpp23
-rwxr-xr-xsrc/common/basic_utils.h4
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_general.cpp44
-rw-r--r--src/rpc-server/commands/trex_rpc_cmds.h77
-rw-r--r--src/rpc-server/trex_rpc_cmd.cpp46
-rw-r--r--src/rpc-server/trex_rpc_cmd_api.h39
-rw-r--r--src/rpc-server/trex_rpc_cmds_table.cpp1
-rw-r--r--src/rpc-server/trex_rpc_exception_api.h10
-rw-r--r--src/sim/trex_sim_stateless.cpp1
-rw-r--r--src/stateless/cp/trex_api_class.h110
-rw-r--r--src/stateless/cp/trex_exception.h41
-rw-r--r--src/stateless/cp/trex_stateless.cpp3
-rw-r--r--src/stateless/cp/trex_stateless.h38
-rw-r--r--src/stateless/cp/trex_stateless_port.cpp21
-rw-r--r--src/stateless/cp/trex_stateless_port.h4
22 files changed, 419 insertions, 136 deletions
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py
index 7fbd2808..bddc4ad0 100755
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py
@@ -320,11 +320,11 @@ class AsyncEventHandler(object):
class CCommLink(object):
"""Describes the connectivity of the stateless client method"""
- def __init__(self, server="localhost", port=5050, virtual=False, prn_func = None):
+ def __init__(self, server="localhost", port=5050, virtual=False, client = None):
self.virtual = virtual
self.server = server
self.port = port
- self.rpc_link = JsonRpcClient(self.server, self.port, prn_func)
+ self.rpc_link = JsonRpcClient(self.server, self.port, client)
@property
def is_connected(self):
@@ -347,25 +347,25 @@ class CCommLink(object):
if not self.virtual:
return self.rpc_link.disconnect()
- def transmit(self, method_name, params={}):
+ def transmit(self, method_name, params = None, api_class = 'core'):
if self.virtual:
self._prompt_virtual_tx_msg()
- _, msg = self.rpc_link.create_jsonrpc_v2(method_name, params)
+ _, msg = self.rpc_link.create_jsonrpc_v2(method_name, params, api_class)
print(msg)
return
else:
- return self.rpc_link.invoke_rpc_method(method_name, params)
+ return self.rpc_link.invoke_rpc_method(method_name, params, api_class)
def transmit_batch(self, batch_list):
if self.virtual:
self._prompt_virtual_tx_msg()
print([msg
- for _, msg in [self.rpc_link.create_jsonrpc_v2(command.method, command.params)
+ for _, msg in [self.rpc_link.create_jsonrpc_v2(command.method, command.params, command.api_class)
for command in batch_list]])
else:
batch = self.rpc_link.create_batch()
for command in batch_list:
- batch.add(command.method, command.params)
+ batch.add(command.method, command.params, command.api_class)
# invoke the batch
return batch.invoke()
@@ -449,7 +449,7 @@ class STLClient(object):
self.comm_link = CCommLink(server,
sync_port,
virtual,
- self.logger)
+ self)
# async event handler manager
self.event_handler = AsyncEventHandler(self)
@@ -481,7 +481,11 @@ class STLClient(object):
self.flow_stats)
-
+ # API classes
+ self.api_vers = [ {'type': 'core', 'major': 1, 'minor':0 }
+ ]
+ self.api_h = {'core': None}
+
############# private functions - used by the class itself ###########
# some preprocessing for port argument
@@ -668,6 +672,7 @@ class STLClient(object):
return rc
+
# connect to server
def __connect(self):
@@ -686,12 +691,22 @@ class STLClient(object):
if not rc:
return rc
+
+ # API sync
+ rc = self._transmit("api_sync", params = {'api_vers': self.api_vers}, api_class = None)
+ if not rc:
+ return rc
+
+ # decode
+ for api in rc.data()['api_vers']:
+ self.api_h[ api['type'] ] = api['api_h']
+
+
# version
rc = self._transmit("get_version")
if not rc:
return rc
-
self.server_version = rc.data()
self.global_stats.server_version = rc.data()
@@ -817,8 +832,8 @@ class STLClient(object):
# transmit request on the RPC link
- def _transmit(self, method_name, params={}):
- return self.comm_link.transmit(method_name, params)
+ def _transmit(self, method_name, params = None, api_class = 'core'):
+ return self.comm_link.transmit(method_name, params, api_class)
# transmit batch request on the RPC link
def _transmit_batch(self, batch_list):
@@ -1304,7 +1319,7 @@ class STLClient(object):
self.logger.pre_cmd( "Pinging the server on '{0}' port '{1}': ".format(self.connection_info['server'],
self.connection_info['sync_port']))
- rc = self._transmit("ping")
+ rc = self._transmit("ping", api_class = None)
self.logger.post_cmd(rc)
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_jsonrpc_client.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_jsonrpc_client.py
index 166fd64e..bd5ba8e7 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_jsonrpc_client.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_jsonrpc_client.py
@@ -26,9 +26,9 @@ class BatchMessage(object):
self.rpc_client = rpc_client
self.batch_list = []
- def add (self, method_name, params={}):
+ def add (self, method_name, params = None, api_class = 'core'):
- id, msg = self.rpc_client.create_jsonrpc_v2(method_name, params, encode = False)
+ id, msg = self.rpc_client.create_jsonrpc_v2(method_name, params, api_class, encode = False)
self.batch_list.append(msg)
def invoke(self, block = False):
@@ -46,8 +46,9 @@ class JsonRpcClient(object):
MSG_COMPRESS_THRESHOLD = 4096
MSG_COMPRESS_HEADER_MAGIC = 0xABE85CEA
- def __init__ (self, default_server, default_port, logger):
- self.logger = logger
+ def __init__ (self, default_server, default_port, client):
+ self.client = client
+ self.logger = client.logger
self.connected = False
# default values
@@ -93,14 +94,18 @@ class JsonRpcClient(object):
def create_batch (self):
return BatchMessage(self)
- def create_jsonrpc_v2 (self, method_name, params = {}, encode = True):
+ def create_jsonrpc_v2 (self, method_name, params = None, api_class = 'core', encode = True):
msg = {}
msg["jsonrpc"] = "2.0"
msg["method"] = method_name
+ msg["id"] = next(self.id_gen)
- msg["params"] = params
+ msg["params"] = params if params is not None else {}
- msg["id"] = next(self.id_gen)
+ # if this RPC has an API class - add it's handler
+ if api_class:
+ msg["params"]["api_h"] = self.client.api_h[api_class]
+
if encode:
return id, json.dumps(msg)
@@ -108,11 +113,11 @@ class JsonRpcClient(object):
return id, msg
- def invoke_rpc_method (self, method_name, params = {}):
+ def invoke_rpc_method (self, method_name, params = None, api_class = 'core'):
if not self.connected:
return RC_ERR("Not connected to server")
- id, msg = self.create_jsonrpc_v2(method_name, params)
+ id, msg = self.create_jsonrpc_v2(method_name, params, api_class)
return self.send_msg(msg)
@@ -273,7 +278,7 @@ class JsonRpcClient(object):
self.connected = True
- rc = self.invoke_rpc_method('ping')
+ rc = self.invoke_rpc_method('ping', api_class = None)
if not rc:
self.connected = False
return rc
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py
index 049929ae..89ad2663 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py
@@ -81,8 +81,7 @@ class Port(object):
"session_id": self.session_id,
"force": force}
- command = RpcCmdData("acquire", params)
- rc = self.transmit(command.method, command.params)
+ rc = self.transmit("acquire", params)
if rc.good():
self.handler = rc.data()
return self.ok()
@@ -94,8 +93,7 @@ class Port(object):
params = {"port_id": self.port_id,
"handler": self.handler}
- command = RpcCmdData("release", params)
- rc = self.transmit(command.method, command.params)
+ rc = self.transmit("release", params)
self.handler = None
if rc.good():
@@ -119,8 +117,7 @@ class Port(object):
def sync(self):
params = {"port_id": self.port_id}
- command = RpcCmdData("get_port_status", params)
- rc = self.transmit(command.method, command.params)
+ rc = self.transmit("get_port_status", params)
if rc.bad():
return self.err(rc.err())
@@ -149,8 +146,7 @@ class Port(object):
# sync the streams
params = {"port_id": self.port_id}
- command = RpcCmdData("get_all_streams", params)
- rc = self.transmit(command.method, command.params)
+ rc = self.transmit("get_all_streams", params)
if rc.bad():
return self.err(rc.err())
@@ -224,7 +220,7 @@ class Port(object):
"stream_id": stream_id,
"stream": stream_json}
- cmd = RpcCmdData('add_stream', params)
+ cmd = RpcCmdData('add_stream', params, 'core')
batch.append(cmd)
@@ -276,7 +272,7 @@ class Port(object):
"port_id": self.port_id,
"stream_id": stream_id}
- cmd = RpcCmdData('remove_stream', params)
+ cmd = RpcCmdData('remove_stream', params, 'core')
batch.append(cmd)
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py
index 18678e3e..1d89a599 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py
@@ -39,7 +39,7 @@ class BpSimException(Exception):
# stateless simulation
class STLSim(object):
- def __init__ (self, bp_sim_path = None, handler = 0, port_id = 0):
+ def __init__ (self, bp_sim_path = None, handler = 0, port_id = 0, api_h = "dummy"):
if not bp_sim_path:
# auto find scripts
@@ -54,6 +54,7 @@ class STLSim(object):
# dummies
self.handler = handler
+ self.api_h = api_h
self.port_id = port_id
@@ -62,6 +63,7 @@ class STLSim(object):
"jsonrpc": "2.0",
"method": "start_traffic",
"params": {"handler": self.handler,
+ "api_h" : self.api_h,
"force": force,
"port_id": self.port_id,
"mul": parsing_opts.decode_multiplier(mult),
@@ -168,6 +170,7 @@ class STLSim(object):
"jsonrpc": "2.0",
"method": "add_stream",
"params": {"handler": self.handler,
+ "api_h": self.api_h,
"port_id": self.port_id,
"stream_id": stream_id,
"stream": stream_json}
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py
index a1ccf4e6..a4bb64db 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py
@@ -3,8 +3,6 @@
from .utils import text_tables
from .utils.text_opts import format_text, format_threshold, format_num
-from .trex_stl_async_client import CTRexAsyncStats
-
from collections import namedtuple, OrderedDict, deque
import sys
import copy
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py
index aeeddc49..3ce876ad 100755
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py
@@ -833,7 +833,7 @@ class STLProfile(object):
return '\n'.join([str(stream) for stream in self.streams])
def is_pauseable (self):
- return all([x.get_mode() == "Continuous" for x in (self.get_streams())])
+ return all([x.get_mode() == "Continuous" for x in self.get_streams()])
def has_flow_stats (self):
return any([x.has_flow_stats() for x in self.get_streams()])
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py
index e5305c78..cd15b831 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py
@@ -4,7 +4,7 @@ from .utils.text_opts import *
from .trex_stl_exceptions import *
import types
-RpcCmdData = namedtuple('RpcCmdData', ['method', 'params'])
+RpcCmdData = namedtuple('RpcCmdData', ['method', 'params', 'api_class'])
TupleRC = namedtuple('RCT', ['rc', 'data', 'is_warn'])
class RpcResponseStatus(namedtuple('RpcResponseStatus', ['success', 'id', 'msg'])):
diff --git a/src/common/basic_utils.cpp b/src/common/basic_utils.cpp
index 34c37755..4f5578a6 100755
--- a/src/common/basic_utils.cpp
+++ b/src/common/basic_utils.cpp
@@ -17,6 +17,7 @@ limitations under the License.
#include <ctype.h>
#include <stdio.h>
#include <string>
+#include <sstream>
bool utl_is_file_exists (const std::string& name) {
if (FILE *file = fopen(name.c_str(), "r")) {
@@ -175,3 +176,25 @@ void utl_macaddr_to_str(const uint8_t *macaddr, std::string &output) {
}
}
+
+/**
+ * generate a random connection handler
+ *
+ */
+std::string
+utl_generate_random_str(unsigned int &seed, int len) {
+ std::stringstream ss;
+
+ static const char alphanum[] =
+ "0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz";
+
+ /* generate 8 bytes of random handler */
+ for (int i = 0; i < len; ++i) {
+ ss << alphanum[rand_r(&seed) % (sizeof(alphanum) - 1)];
+ }
+
+ return (ss.str());
+}
+
diff --git a/src/common/basic_utils.h b/src/common/basic_utils.h
index 77282eea..63e858ab 100755
--- a/src/common/basic_utils.h
+++ b/src/common/basic_utils.h
@@ -21,8 +21,6 @@ limitations under the License.
#include <stdio.h>
#include <string>
-
-
/**
* the round must be power 2 e.g 2,4,8...
*
@@ -87,6 +85,8 @@ bool utl_is_file_exists (const std::string& name) ;
void utl_macaddr_to_str(const uint8_t *macaddr, std::string &output);
+std::string utl_generate_random_str(unsigned int &seed, int len);
+
#endif
diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
index f054c0ed..f7a23188 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
@@ -38,6 +38,50 @@ limitations under the License.
using namespace std;
/**
+ * API sync
+ */
+trex_rpc_cmd_rc_e
+TrexRpcCmdAPISync::_run(const Json::Value &params, Json::Value &result) {
+ const Json::Value &api_vers = parse_array(params, "api_vers", result);
+
+ Json::Value api_ver_rc = Json::arrayValue;
+
+ /* for every element in the list - generate the appropirate API handler */
+ for (const auto api_ver : api_vers) {
+ Json::Value single_rc;
+
+ /* only those are supported */
+ const std::string type = parse_choice(api_ver, "type", {"core"}, result);
+
+ int major = parse_int(api_ver, "major", result);
+ int minor = parse_int(api_ver, "minor", result);
+ APIClass::type_e api_type;
+
+ /* decode type of API */
+ if (type == "core") {
+ api_type = APIClass::API_CLASS_TYPE_CORE;
+ }
+
+ single_rc["type"] = type;
+
+ /* this section might throw exception in case versions do not match */
+ try {
+ single_rc["api_h"] = get_stateless_obj()->verify_api(api_type, major, minor);
+
+ } catch (const TrexAPIException &e) {
+ generate_execute_err(result, e.what());
+ }
+
+ /* add to the response */
+ api_ver_rc.append(single_rc);
+ }
+
+ result["result"]["api_vers"] = api_ver_rc;
+
+ return (TREX_RPC_CMD_OK);
+}
+
+/**
* ping command
*/
trex_rpc_cmd_rc_e
diff --git a/src/rpc-server/commands/trex_rpc_cmds.h b/src/rpc-server/commands/trex_rpc_cmds.h
index dbf90fef..428bdd7b 100644
--- a/src/rpc-server/commands/trex_rpc_cmds.h
+++ b/src/rpc-server/commands/trex_rpc_cmds.h
@@ -36,33 +36,39 @@ class TrexStream;
* syntactic sugar for creating a simple command
*/
-#define TREX_RPC_CMD_DEFINE_EXTENDED(class_name, cmd_name, param_count, needs_ownership, ext) \
- class class_name : public TrexRpcCommand { \
- public: \
- class_name () : TrexRpcCommand(cmd_name, param_count, needs_ownership) {} \
- protected: \
- virtual trex_rpc_cmd_rc_e _run(const Json::Value &params, Json::Value &result); \
- ext \
+#define TREX_RPC_CMD_DEFINE_EXTENDED(class_name, cmd_name, param_count, needs_ownership, api_type, ext) \
+ class class_name : public TrexRpcCommand { \
+ public: \
+ class_name () : TrexRpcCommand(cmd_name, param_count, needs_ownership, api_type) {} \
+ protected: \
+ virtual trex_rpc_cmd_rc_e _run(const Json::Value &params, Json::Value &result); \
+ ext \
}
-#define TREX_RPC_CMD_DEFINE(class_name, cmd_name, param_count, needs_ownership) TREX_RPC_CMD_DEFINE_EXTENDED(class_name, cmd_name, param_count, needs_ownership, ;)
+#define TREX_RPC_CMD_DEFINE(class_name, cmd_name, param_count, needs_ownership, api_type) TREX_RPC_CMD_DEFINE_EXTENDED(class_name, cmd_name, param_count, needs_ownership, api_type, ;)
/**
* test cmds
*/
-TREX_RPC_CMD_DEFINE(TrexRpcCmdTestAdd, "test_add", 2, false);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdTestSub, "test_sub", 2, false);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdTestAdd, "test_add", 2, false, APIClass::API_CLASS_TYPE_NO_API);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdTestSub, "test_sub", 2, false, APIClass::API_CLASS_TYPE_NO_API);
+
+/**
+ * api_sync command always present and valid and also ping....
+ */
+TREX_RPC_CMD_DEFINE(TrexRpcCmdAPISync, "api_sync", 1, false, APIClass::API_CLASS_TYPE_NO_API);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdPing, "ping", 0, false, APIClass::API_CLASS_TYPE_NO_API);
/**
* general cmds
*/
-TREX_RPC_CMD_DEFINE(TrexRpcCmdPing, "ping", 0, false);
-TREX_RPC_CMD_DEFINE(TrexRpcPublishNow, "publish_now", 2, false);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdGetCmds, "get_supported_cmds", 0, false);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdGetVersion, "get_version", 0, false);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdGetActivePGIds, "get_active_pgids",0, false);
-TREX_RPC_CMD_DEFINE_EXTENDED(TrexRpcCmdGetSysInfo, "get_system_info", 0, false,
+TREX_RPC_CMD_DEFINE(TrexRpcPublishNow, "publish_now", 2, false, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetCmds, "get_supported_cmds", 0, false, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetVersion, "get_version", 0, false, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetActivePGIds, "get_active_pgids", 0, false, APIClass::API_CLASS_TYPE_CORE);
+
+TREX_RPC_CMD_DEFINE_EXTENDED(TrexRpcCmdGetSysInfo, "get_system_info", 0, false, APIClass::API_CLASS_TYPE_CORE,
std::string get_cpu_model();
void get_hostname(std::string &hostname);
@@ -72,25 +78,25 @@ void get_hostname(std::string &hostname);
/**
* ownership
*/
-TREX_RPC_CMD_DEFINE(TrexRpcCmdGetOwner, "get_owner", 1, false);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdAcquire, "acquire", 4, false);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdRelease, "release", 1, true);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetOwner, "get_owner", 1, false, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdAcquire, "acquire", 4, false, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdRelease, "release", 1, true, APIClass::API_CLASS_TYPE_CORE);
/**
* port commands
*/
-TREX_RPC_CMD_DEFINE(TrexRpcCmdGetPortStats, "get_port_stats", 1, false);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdGetPortStatus, "get_port_status", 1, false);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdSetPortAttr, "set_port_attr", 3, false);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetPortStats, "get_port_stats", 1, false, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetPortStatus, "get_port_status", 1, false, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdSetPortAttr, "set_port_attr", 3, false, APIClass::API_CLASS_TYPE_CORE);
/**
* stream cmds
*/
-TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveAllStreams, "remove_all_streams", 1, true);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveStream, "remove_stream", 2, true);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveAllStreams, "remove_all_streams", 1, true, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveStream, "remove_stream", 2, true, APIClass::API_CLASS_TYPE_CORE);
-TREX_RPC_CMD_DEFINE_EXTENDED(TrexRpcCmdAddStream, "add_stream", 3, true,
+TREX_RPC_CMD_DEFINE_EXTENDED(TrexRpcCmdAddStream, "add_stream", 3, true, APIClass::API_CLASS_TYPE_CORE,
/* extended part */
std::unique_ptr<TrexStream> allocate_new_stream(const Json::Value &section, uint8_t port_id, uint32_t stream_id, Json::Value &result);
@@ -107,21 +113,22 @@ void parse_vm_instr_write_mask_flow_var(const Json::Value &inst, std::unique_ptr
);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStreamList, "get_stream_list", 1, false);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdGetAllStreams, "get_all_streams", 1, false);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStreamList, "get_stream_list", 1, false, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetAllStreams, "get_all_streams", 1, false, APIClass::API_CLASS_TYPE_CORE);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStream, "get_stream", 3, false);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStream, "get_stream", 3, false, APIClass::API_CLASS_TYPE_CORE);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdStartTraffic, "start_traffic", 4, true);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdStopTraffic, "stop_traffic", 1, true);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveRXFilters, "remove_rx_filters", 1, true);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdPauseTraffic, "pause_traffic", 1, true);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdResumeTraffic, "resume_traffic", 1, true);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdStartTraffic, "start_traffic", 4, true, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdStopTraffic, "stop_traffic", 1, true, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveRXFilters, "remove_rx_filters", 1, true, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdPauseTraffic, "pause_traffic", 1, true, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdResumeTraffic, "resume_traffic", 1, true, APIClass::API_CLASS_TYPE_CORE);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdUpdateTraffic, "update_traffic", 3, true);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdUpdateTraffic, "update_traffic", 3, true, APIClass::API_CLASS_TYPE_CORE);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdValidate, "validate", 2, false);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdValidate, "validate", 2, false, APIClass::API_CLASS_TYPE_CORE);
#endif /* __TREX_RPC_CMD_H__ */
+
diff --git a/src/rpc-server/trex_rpc_cmd.cpp b/src/rpc-server/trex_rpc_cmd.cpp
index caf161e3..902e63c7 100644
--- a/src/rpc-server/trex_rpc_cmd.cpp
+++ b/src/rpc-server/trex_rpc_cmd.cpp
@@ -23,6 +23,32 @@ limitations under the License.
#include <trex_stateless.h>
#include <trex_stateless_port.h>
+/**
+ * method name and params
+ *
+ */
+TrexRpcCommand::TrexRpcCommand(const std::string &method_name,
+ int param_count,
+ bool needs_ownership,
+ APIClass::type_e type) : m_name(method_name),
+ m_param_count(param_count),
+ m_needs_ownership(needs_ownership) {
+
+ /* if needs ownership - another field is needed (handler) */
+ if (m_needs_ownership) {
+ m_param_count++;
+ }
+
+ /* API verification */
+ m_api_type = type;
+
+ if (type != APIClass::API_CLASS_TYPE_NO_API) {
+ m_api_handler = get_stateless_obj()->get_api_handler(type);
+ m_param_count++;
+ }
+
+}
+
trex_rpc_cmd_rc_e
TrexRpcCommand::run(const Json::Value &params, Json::Value &result) {
trex_rpc_cmd_rc_e rc;
@@ -30,12 +56,18 @@ TrexRpcCommand::run(const Json::Value &params, Json::Value &result) {
/* the internal run can throw a parser error / other error */
try {
- check_param_count(params, m_param_count, result);
+ /* verify API handler is correct (version mismatch) */
+ if ( (m_api_type != APIClass::API_CLASS_TYPE_NO_API) && !g_test_override_api ) {
+ verify_api_handler(params, result);
+ }
+ /* verify ownership */
if (m_needs_ownership && !g_test_override_ownership) {
verify_ownership(params, result);
}
+ check_param_count(params, m_param_count, result);
+
/* run the command itself*/
rc = _run(params, result);
@@ -72,6 +104,17 @@ TrexRpcCommand::verify_ownership(const Json::Value &params, Json::Value &result)
}
}
+void
+TrexRpcCommand::verify_api_handler(const Json::Value &params, Json::Value &result) {
+ std::string api_handler = parse_string(params, "api_h", result);
+
+ if (m_api_handler != api_handler) {
+ std::stringstream ss;
+ ss << "API verification failed - API handler provided mismatch for class: '" << APIClass::type_to_name(m_api_type) << "'";
+ generate_execute_err(result, ss.str());
+ }
+}
+
uint8_t
TrexRpcCommand::parse_port(const Json::Value &params, Json::Value &result) {
uint8_t port_id = parse_byte(params, "port_id", result);
@@ -281,3 +324,4 @@ TrexRpcCommand::generate_execute_err(Json::Value &result, const std::string &msg
* by default this is off
*/
bool TrexRpcCommand::g_test_override_ownership = false;
+bool TrexRpcCommand::g_test_override_api = false;
diff --git a/src/rpc-server/trex_rpc_cmd_api.h b/src/rpc-server/trex_rpc_cmd_api.h
index 7e694768..25920c6c 100644
--- a/src/rpc-server/trex_rpc_cmd_api.h
+++ b/src/rpc-server/trex_rpc_cmd_api.h
@@ -27,6 +27,8 @@ limitations under the License.
#include <json/json.h>
#include <trex_rpc_exception_api.h>
+#include "trex_api_class.h"
+
/**
* describe different types of rc for run()
*/
@@ -68,16 +70,10 @@ public:
/**
* method name and params
*/
- TrexRpcCommand(const std::string &method_name, int param_count, bool needs_ownership) :
- m_name(method_name),
- m_param_count(param_count),
- m_needs_ownership(needs_ownership) {
-
- /* if needs ownership - another field is needed (handler) */
- if (m_needs_ownership) {
- m_param_count++;
- }
- }
+ TrexRpcCommand(const std::string &method_name,
+ int param_count,
+ bool needs_ownership,
+ APIClass::type_e type);
/**
* entry point for executing RPC command
@@ -99,6 +95,10 @@ public:
g_test_override_ownership = enable;
}
+ static void test_set_override_api(bool enable) {
+ g_test_override_api = enable;
+ }
+
virtual ~TrexRpcCommand() {}
protected:
@@ -131,11 +131,18 @@ protected:
void check_param_count(const Json::Value &params, int expected, Json::Value &result);
/**
+ * verify API handler
+ *
+ */
+ void verify_api_handler(const Json::Value &params, Json::Value &result);
+
+ /**
* verify ownership
*
*/
void verify_ownership(const Json::Value &params, Json::Value &result);
+
/**
* validate port id
*
@@ -360,11 +367,13 @@ protected:
const char * json_type_to_name(const Json::Value &value);
/* RPC command name */
- std::string m_name;
- int m_param_count;
- bool m_needs_ownership;
-
- static bool g_test_override_ownership;
+ std::string m_name;
+ int m_param_count;
+ bool m_needs_ownership;
+ std::string m_api_handler;
+ APIClass::type_e m_api_type;
+ static bool g_test_override_ownership;
+ static bool g_test_override_api;
};
#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 c9b41595..924503f2 100644
--- a/src/rpc-server/trex_rpc_cmds_table.cpp
+++ b/src/rpc-server/trex_rpc_cmds_table.cpp
@@ -33,6 +33,7 @@ TrexRpcCommandsTable::TrexRpcCommandsTable() {
/* general */
+ register_command(new TrexRpcCmdAPISync());
register_command(new TrexRpcCmdPing());
register_command(new TrexRpcPublishNow());
register_command(new TrexRpcCmdGetCmds());
diff --git a/src/rpc-server/trex_rpc_exception_api.h b/src/rpc-server/trex_rpc_exception_api.h
index e349b980..ebc9b411 100644
--- a/src/rpc-server/trex_rpc_exception_api.h
+++ b/src/rpc-server/trex_rpc_exception_api.h
@@ -25,17 +25,19 @@ limitations under the License.
#include <string>
#include <stdexcept>
+#include "trex_exception.h"
+
/**
* generic exception for RPC errors
*
*/
-class TrexRpcException : public std::runtime_error
-{
+class TrexRpcException : public TrexException {
+
public:
- TrexRpcException() : std::runtime_error("") {
+ TrexRpcException() : TrexException("") {
}
- TrexRpcException(const std::string &what) : std::runtime_error(what) {
+ TrexRpcException(const std::string &what) : TrexException(what) {
}
};
diff --git a/src/sim/trex_sim_stateless.cpp b/src/sim/trex_sim_stateless.cpp
index ffe377f4..fa13401d 100644
--- a/src/sim/trex_sim_stateless.cpp
+++ b/src/sim/trex_sim_stateless.cpp
@@ -117,6 +117,7 @@ SimStateless::SimStateless() {
/* override ownership checks */
TrexRpcCommand::test_set_override_ownership(true);
+ TrexRpcCommand::test_set_override_api(true);
}
diff --git a/src/stateless/cp/trex_api_class.h b/src/stateless/cp/trex_api_class.h
new file mode 100644
index 00000000..78933d23
--- /dev/null
+++ b/src/stateless/cp/trex_api_class.h
@@ -0,0 +1,110 @@
+/*
+ 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_API_CLASS_H__
+#define __TREX_API_CLASS_H__
+
+#include <assert.h>
+
+#include "common/basic_utils.h"
+#include "trex_exception.h"
+
+/**
+ * API exception
+ *
+ * @author imarom (03-Apr-16)
+ */
+class TrexAPIException : public TrexException {
+public:
+ TrexAPIException(const std::string &what) : TrexException(what) {
+ }
+};
+
+/**
+ * define an API class
+ *
+ * @author imarom (03-Apr-16)
+ */
+class APIClass {
+public:
+
+ enum type_e {
+ API_CLASS_TYPE_CORE = 0,
+ API_CLASS_TYPE_MAX,
+
+ API_CLASS_TYPE_NO_API
+ };
+
+ static const char * type_to_name(type_e type) {
+ switch (type) {
+ case API_CLASS_TYPE_CORE:
+ return "core";
+ default:
+ assert(0);
+ }
+ }
+
+ APIClass() {
+ /* invalid */
+ m_type = API_CLASS_TYPE_MAX;
+ }
+
+ void init(type_e type, int major, int minor) {
+ m_type = type;
+ m_major = major;
+ m_minor = minor;
+
+ unsigned int seed = time(NULL);
+ m_handler = utl_generate_random_str(seed, 8);
+ }
+
+ std::string & verify_api(int major, int minor) {
+ std::stringstream ss;
+ ss << "API type '" << type_to_name(m_type) << "': ";
+
+ assert(m_type < API_CLASS_TYPE_MAX);
+
+ /* for now a simple major check */
+ if (major < m_major) {
+ ss << "server has a major newer API version - server: '" << m_major << "', client: '" << major << "'";
+ throw TrexAPIException(ss.str());
+ }
+
+ if (major > m_major) {
+ ss << "server has an older API version - server: '" << m_major << "', client: '" << major << "'";
+ throw TrexAPIException(ss.str());
+ }
+
+ return get_api_handler();
+ }
+
+ std::string & get_api_handler() {
+ return m_handler;
+ }
+
+private:
+ type_e m_type;
+ int m_major;
+ int m_minor;
+ std::string m_handler;
+
+};
+
+#endif /* __TREX_API_CLASS_H__ */
diff --git a/src/stateless/cp/trex_exception.h b/src/stateless/cp/trex_exception.h
new file mode 100644
index 00000000..b9e20761
--- /dev/null
+++ b/src/stateless/cp/trex_exception.h
@@ -0,0 +1,41 @@
+/*
+ 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_EXCEPTION_H__
+#define __TREX_EXCEPTION_H__
+
+#include <stdexcept>
+#include <string>
+
+/**
+ * generic exception for errors
+ * TODO: move this to a better place
+ */
+class TrexException : public std::runtime_error
+{
+public:
+ TrexException() : std::runtime_error("") {
+
+ }
+ TrexException(const std::string &what) : std::runtime_error(what) {
+ }
+};
+
+#endif /* __TREX_EXCEPTION_H__ */
diff --git a/src/stateless/cp/trex_stateless.cpp b/src/stateless/cp/trex_stateless.cpp
index 9df57a50..f6f81b96 100644
--- a/src/stateless/cp/trex_stateless.cpp
+++ b/src/stateless/cp/trex_stateless.cpp
@@ -53,6 +53,8 @@ TrexStateless::TrexStateless(const TrexStatelessCfg &cfg) {
m_platform_api = cfg.m_platform_api;
m_publisher = cfg.m_publisher;
+ /* API core version */
+ m_api_classes[APIClass::API_CLASS_TYPE_CORE].init(APIClass::API_CLASS_TYPE_CORE, 1, 0);
}
/**
@@ -175,3 +177,4 @@ TrexStateless::generate_publish_snapshot(std::string &snapshot) {
snapshot = writer.write(root);
}
+
diff --git a/src/stateless/cp/trex_stateless.h b/src/stateless/cp/trex_stateless.h
index 7db86174..b506da61 100644
--- a/src/stateless/cp/trex_stateless.h
+++ b/src/stateless/cp/trex_stateless.h
@@ -27,27 +27,18 @@ limitations under the License.
#include <mutex>
-#include <trex_stream.h>
-#include <trex_stateless_port.h>
-#include <trex_rpc_server_api.h>
-#include <publisher/trex_publisher.h>
+#include "trex_stream.h"
+#include "trex_stateless_port.h"
+#include "trex_rpc_server_api.h"
-#include <flow_stat.h>
-#include <internal_api/trex_platform_api.h>
+#include "publisher/trex_publisher.h"
+#include "internal_api/trex_platform_api.h"
-/**
- * generic exception for errors
- * TODO: move this to a better place
- */
-class TrexException : public std::runtime_error
-{
-public:
- TrexException() : std::runtime_error("") {
+#include "flow_stat.h"
- }
- TrexException(const std::string &what) : std::runtime_error(what) {
- }
-};
+
+#include "trex_exception.h"
+#include "trex_api_class.h"
class TrexStatelessPort;
@@ -81,6 +72,7 @@ public:
} m_stats;
};
+
/**
* config object for stateless object
*
@@ -167,6 +159,14 @@ public:
return m_rpc_server;
}
+ const std::string & verify_api(APIClass::type_e type, int major, int minor) {
+ return m_api_classes[type].verify_api(major, minor);
+ }
+
+ const std::string & get_api_handler(APIClass::type_e type) {
+ return m_api_classes[type].get_api_handler();
+ }
+
CFlowStatRuleMgr m_rx_flow_stat;
protected:
@@ -187,6 +187,8 @@ protected:
TrexPublisher *m_publisher;
+ /* API */
+ APIClass m_api_classes[APIClass::API_CLASS_TYPE_MAX];
};
/**
diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp
index 6a33fcee..2239f3f6 100644
--- a/src/stateless/cp/trex_stateless_port.cpp
+++ b/src/stateless/cp/trex_stateless_port.cpp
@@ -781,26 +781,5 @@ TrexPortOwner::TrexPortOwner() {
m_seed = time(NULL);
}
-/**
- * generate a random connection handler
- *
- */
-std::string
-TrexPortOwner::generate_handler() {
- std::stringstream ss;
-
- static const char alphanum[] =
- "0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz";
-
- /* generate 8 bytes of random handler */
- for (int i = 0; i < 8; ++i) {
- ss << alphanum[rand_r(&m_seed) % (sizeof(alphanum) - 1)];
- }
-
- return (ss.str());
-}
-
const std::string TrexPortOwner::g_unowned_name = "<FREE>";
const std::string TrexPortOwner::g_unowned_handler = "";
diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h
index 7aa3bfa8..2167e735 100644
--- a/src/stateless/cp/trex_stateless_port.h
+++ b/src/stateless/cp/trex_stateless_port.h
@@ -21,6 +21,7 @@ limitations under the License.
#ifndef __TREX_STATELESS_PORT_H__
#define __TREX_STATELESS_PORT_H__
+#include "common/basic_utils.h"
#include "internal_api/trex_platform_api.h"
#include "trex_dp_port_events.h"
#include "trex_stream.h"
@@ -65,7 +66,7 @@ public:
m_owner_name = owner_name;
/* internal data */
- m_handler = generate_handler();
+ m_handler = utl_generate_random_str(m_seed, 8);
m_is_free = false;
}
@@ -83,7 +84,6 @@ public:
private:
- std::string generate_handler();
/* is this port owned by someone ? */
bool m_is_free;