summaryrefslogtreecommitdiffstats
path: root/src/rpc-server
diff options
context:
space:
mode:
authorHanoh Haim <hhaim@cisco.com>2015-09-10 07:54:05 +0300
committerHanoh Haim <hhaim@cisco.com>2015-09-10 07:54:05 +0300
commita360a1734c459d62bd4c204a6005214ce8944f85 (patch)
treee06cad6cf63a52701aff303c19024cde1d541ebd /src/rpc-server
parent15b4f7cd7c3e9176c1f24fc632791e833cb588b8 (diff)
parente33befcf222fd2108d589dede11069d4256bb21a (diff)
Merge branch 'master' of csi-sceasr-b45:/auto/proj-pcube-b/apps/PL-b/tools/repo//trex-core
Conflicts: linux/ws_main.py
Diffstat (limited to 'src/rpc-server')
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_general.cpp12
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_stream.cpp326
-rw-r--r--src/rpc-server/commands/trex_rpc_cmds.h16
-rw-r--r--src/rpc-server/trex_rpc_cmd.cpp20
-rw-r--r--src/rpc-server/trex_rpc_cmd_api.h36
-rw-r--r--src/rpc-server/trex_rpc_cmds_table.cpp4
-rw-r--r--src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp25
-rw-r--r--src/rpc-server/trex_rpc_jsonrpc_v2_parser.h8
-rw-r--r--src/rpc-server/trex_rpc_req_resp_server.cpp5
-rw-r--r--src/rpc-server/trex_rpc_server.cpp6
-rw-r--r--src/rpc-server/trex_rpc_server_api.h31
-rw-r--r--src/rpc-server/trex_rpc_server_mock.cpp5
12 files changed, 463 insertions, 31 deletions
diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
index 6b765aca..32952b1a 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
@@ -20,6 +20,7 @@ limitations under the License.
*/
#include "trex_rpc_cmds.h"
#include <trex_rpc_server_api.h>
+#include <trex_stateless_api.h>
#ifndef TREX_RPC_MOCK_SERVER
#include <../linux_dpdk/version.h>
@@ -41,8 +42,7 @@ TrexRpcCmdGetStatus::_run(const Json::Value &params, Json::Value &result) {
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();
+ section["general"]["built_by"] = VERSION_USER;
#else
@@ -50,10 +50,16 @@ TrexRpcCmdGetStatus::_run(const Json::Value &params, Json::Value &result) {
section["general"]["build_date"] = __DATE__;
section["general"]["build_time"] = __TIME__;
section["general"]["version_user"] = "MOCK";
- section["general"]["uptime"] = TrexRpcServer::get_server_uptime();
#endif
+ section["general"]["uptime"] = TrexRpcServer::get_server_uptime();
+ section["general"]["owner"] = TrexRpcServer::get_owner();
+
+ // ports
+
+ section["ports"]["count"] = TrexStateless::get_instance().get_port_count();
+
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 d1dffc44..90b55ea8 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
@@ -27,6 +27,23 @@ limitations under the License.
using namespace std;
+/**
+ * simple parser of string to number
+ * only difference is that it enforces whole number
+ * and not partial
+ *
+ */
+static uint64_t str2num(const string &str) {
+ size_t index;
+
+ uint64_t num = std::stoull(str, &index, 0);
+ if (index != str.size()) {
+ throw invalid_argument("could not parse string to number");
+ }
+
+ return (num);
+}
+
/***************************
* add new stream
*
@@ -34,6 +51,9 @@ using namespace std;
trex_rpc_cmd_rc_e
TrexRpcCmdAddStream::_run(const Json::Value &params, Json::Value &result) {
+ uint8_t port_id = parse_int(params, "port_id", result);
+ uint32_t stream_id = parse_int(params, "stream_id", result);
+
const Json::Value &section = parse_object(params, "stream", result);
/* get the type of the stream */
@@ -41,32 +61,40 @@ TrexRpcCmdAddStream::_run(const Json::Value &params, Json::Value &result) {
string type = parse_string(mode, "type", result);
/* allocate a new stream based on the type */
- TrexStream *stream = allocate_new_stream(section, result);
+ TrexStream *stream = allocate_new_stream(section, port_id, stream_id, result);
/* some fields */
stream->m_enabled = parse_bool(section, "enabled", result);
stream->m_self_start = parse_bool(section, "self_start", result);
/* inter stream gap */
- stream->m_isg_usec = parse_double(section, "Is", result);
+ stream->m_isg_usec = parse_double(section, "isg", result);
stream->m_next_stream_id = parse_int(section, "next_stream_id", result);
- const Json::Value &pkt = parse_array(section, "packet", result);
+ const Json::Value &pkt = parse_object(section, "packet", result);
+ const Json::Value &pkt_binary = parse_array(pkt, "binary", result);
/* fetch the packet from the message */
- stream->m_pkt_len = pkt.size();
- stream->m_pkt = new uint8_t[pkt.size()];
- if (!stream->m_pkt) {
+ stream->m_pkt.len = pkt_binary.size();
+ stream->m_pkt.binary = new uint8_t[pkt_binary.size()];
+ if (!stream->m_pkt.binary) {
generate_internal_err(result, "unable to allocate memory");
}
/* parse the packet */
- for (int i = 0; i < pkt.size(); i++) {
- stream->m_pkt[i] = parse_byte(pkt, i, result);
+ for (int i = 0; i < pkt_binary.size(); i++) {
+ stream->m_pkt.binary[i] = parse_byte(pkt_binary, i, result);
}
+ /* meta data */
+ stream->m_pkt.meta = parse_string(pkt, "meta", result);
+
+ /* parse VM */
+ const Json::Value &vm = parse_array(section ,"vm", result);
+ parse_vm(vm, stream, result);
+
/* parse RX info */
const Json::Value &rx = parse_object(section, "rx_stats", result);
@@ -82,7 +110,7 @@ TrexRpcCmdAddStream::_run(const Json::Value &params, Json::Value &result) {
/* make sure this is a valid stream to add */
validate_stream(stream, result);
- TrexStatelessPort *port = get_trex_stateless()->get_port_by_id(stream->m_port_id);
+ TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(stream->m_port_id);
port->get_stream_table()->add_stream(stream);
result["result"] = "ACK";
@@ -93,10 +121,7 @@ TrexRpcCmdAddStream::_run(const Json::Value &params, Json::Value &result) {
TrexStream *
-TrexRpcCmdAddStream::allocate_new_stream(const Json::Value &section, Json::Value &result) {
-
- uint8_t port_id = parse_int(section, "port_id", result);
- uint32_t stream_id = parse_int(section, "stream_id", result);
+TrexRpcCmdAddStream::allocate_new_stream(const Json::Value &section, uint8_t port_id, uint32_t stream_id, Json::Value &result) {
TrexStream *stream;
@@ -138,11 +163,114 @@ TrexRpcCmdAddStream::allocate_new_stream(const Json::Value &section, Json::Value
}
+void
+TrexRpcCmdAddStream::parse_vm_instr_checksum(const Json::Value &inst, TrexStream *stream, Json::Value &result) {
+
+ uint16_t pkt_offset = parse_uint16(inst, "pkt_offset", result);
+ stream->m_vm.add_instruction(new StreamVmInstructionFixChecksumIpv4(pkt_offset));
+}
+
+void
+TrexRpcCmdAddStream::parse_vm_instr_flow_var(const Json::Value &inst, TrexStream *stream, Json::Value &result) {
+ std::string flow_var_name = parse_string(inst, "name", result);
+
+ auto sizes = {1, 2, 4, 8};
+ uint8_t flow_var_size = parse_choice(inst, "size", sizes, result);
+
+ auto ops = {"inc", "dec", "random"};
+ std::string op_type_str = parse_choice(inst, "op", ops, result);
+
+ StreamVmInstructionFlowMan::flow_var_op_e op_type;
+
+ if (op_type_str == "inc") {
+ op_type = StreamVmInstructionFlowMan::FLOW_VAR_OP_INC;
+ } else if (op_type_str == "dec") {
+ op_type = StreamVmInstructionFlowMan::FLOW_VAR_OP_DEC;
+ } else if (op_type_str == "random") {
+ op_type = StreamVmInstructionFlowMan::FLOW_VAR_OP_RANDOM;
+ } else {
+ throw TrexRpcException("internal error");
+ }
+
+ std::string init_value_str = parse_string(inst, "init_value", result);
+ std::string min_value_str = parse_string(inst, "min_value", result);
+ std::string max_value_str = parse_string(inst, "max_value", result);
+
+ uint64_t init_value;
+ uint64_t min_value;
+ uint64_t max_value;
+
+ try {
+ init_value = str2num(init_value_str);
+ } catch (invalid_argument) {
+ generate_parse_err(result, "failed to parse 'init_value' as a number");
+ }
+
+ try {
+ min_value = str2num(min_value_str);
+ } catch (invalid_argument) {
+ generate_parse_err(result, "failed to parse 'min_value' as a number");
+ }
+
+ try {
+ max_value = str2num(max_value_str);
+ } catch (invalid_argument) {
+ generate_parse_err(result, "failed to parse 'max_value' as a number");
+ }
+
+ stream->m_vm.add_instruction(new StreamVmInstructionFlowMan(flow_var_name,
+ flow_var_size,
+ op_type,
+ init_value,
+ min_value,
+ max_value
+ ));
+}
+
+void
+TrexRpcCmdAddStream::parse_vm_instr_write_flow_var(const Json::Value &inst, TrexStream *stream, Json::Value &result) {
+ std::string flow_var_name = parse_string(inst, "flow_var_name", result);
+ uint16_t pkt_offset = parse_uint16(inst, "pkt_offset", result);
+ int add_value = parse_int(inst, "add_value", result);
+ bool is_big_endian = parse_bool(inst, "is_big_endian", result);
+
+ stream->m_vm.add_instruction(new StreamVmInstructionWriteToPkt(flow_var_name,
+ pkt_offset,
+ add_value,
+ is_big_endian));
+}
+
+void
+TrexRpcCmdAddStream::parse_vm(const Json::Value &vm, TrexStream *stream, Json::Value &result) {
+ /* array of VM instructions on vm */
+ for (int i = 0; i < vm.size(); i++) {
+ const Json::Value & inst = vm[i];
+
+ auto vm_types = {"fix_checksum_ipv4", "flow_var", "write_flow_var"};
+ std::string vm_type = parse_choice(inst, "type", vm_types, result);
+
+ // checksum instruction
+ if (vm_type == "fix_checksum_ipv4") {
+ parse_vm_instr_checksum(inst, stream, result);
+
+ } else if (vm_type == "flow_var") {
+ parse_vm_instr_flow_var(inst, stream, result);
+
+ } else if (vm_type == "write_flow_var") {
+ parse_vm_instr_write_flow_var(inst, stream, result);
+
+ } else {
+ /* internal error */
+ throw TrexRpcException("internal error");
+ }
+ }
+}
+
void
TrexRpcCmdAddStream::validate_stream(const TrexStream *stream, Json::Value &result) {
/* check packet size */
- if ( (stream->m_pkt_len < TrexStream::MIN_PKT_SIZE_BYTES) || (stream->m_pkt_len > TrexStream::MAX_PKT_SIZE_BYTES) ) {
+ if ( (stream->m_pkt.len < TrexStream::MIN_PKT_SIZE_BYTES) || (stream->m_pkt.len > TrexStream::MAX_PKT_SIZE_BYTES) ) {
std::stringstream ss;
ss << "bad packet size provided: should be between " << TrexStream::MIN_PKT_SIZE_BYTES << " and " << TrexStream::MAX_PKT_SIZE_BYTES;
delete stream;
@@ -150,15 +278,15 @@ TrexRpcCmdAddStream::validate_stream(const TrexStream *stream, Json::Value &resu
}
/* port id should be between 0 and count - 1 */
- if (stream->m_port_id >= get_trex_stateless()->get_port_count()) {
+ if (stream->m_port_id >= TrexStateless::get_instance().get_port_count()) {
std::stringstream ss;
- ss << "invalid port id - should be between 0 and " << (int)get_trex_stateless()->get_port_count() - 1;
+ ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1;
delete stream;
generate_execute_err(result, ss.str());
}
/* add the stream to the port's stream table */
- TrexStatelessPort * port = get_trex_stateless()->get_port_by_id(stream->m_port_id);
+ TrexStatelessPort * port = TrexStateless::get_instance().get_port_by_id(stream->m_port_id);
/* does such a stream exists ? */
if (port->get_stream_table()->get_stream_by_id(stream->m_stream_id)) {
@@ -180,13 +308,13 @@ TrexRpcCmdRemoveStream::_run(const Json::Value &params, Json::Value &result) {
uint32_t stream_id = parse_int(params, "stream_id", result);
- if (port_id >= get_trex_stateless()->get_port_count()) {
+ if (port_id >= TrexStateless::get_instance().get_port_count()) {
std::stringstream ss;
- ss << "invalid port id - should be between 0 and " << (int)get_trex_stateless()->get_port_count() - 1;
+ ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1;
generate_execute_err(result, ss.str());
}
- TrexStatelessPort *port = get_trex_stateless()->get_port_by_id(port_id);
+ TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
TrexStream *stream = port->get_stream_table()->get_stream_by_id(stream_id);
if (!stream) {
@@ -196,8 +324,11 @@ TrexRpcCmdRemoveStream::_run(const Json::Value &params, Json::Value &result) {
}
port->get_stream_table()->remove_stream(stream);
+ delete stream;
result["result"] = "ACK";
+
+ return (TREX_RPC_CMD_OK);
}
/***************************
@@ -209,15 +340,164 @@ trex_rpc_cmd_rc_e
TrexRpcCmdRemoveAllStreams::_run(const Json::Value &params, Json::Value &result) {
uint8_t port_id = parse_byte(params, "port_id", result);
- if (port_id >= get_trex_stateless()->get_port_count()) {
+ if (port_id >= TrexStateless::get_instance().get_port_count()) {
std::stringstream ss;
- ss << "invalid port id - should be between 0 and " << (int)get_trex_stateless()->get_port_count() - 1;
+ ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1;
generate_execute_err(result, ss.str());
}
- TrexStatelessPort *port = get_trex_stateless()->get_port_by_id(port_id);
+ TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
port->get_stream_table()->remove_and_delete_all_streams();
result["result"] = "ACK";
+
+ return (TREX_RPC_CMD_OK);
+}
+
+/***************************
+ * get all streams configured
+ * on a specific port
+ *
+ **************************/
+trex_rpc_cmd_rc_e
+TrexRpcCmdGetStreamList::_run(const Json::Value &params, Json::Value &result) {
+ std::vector<uint32_t> stream_list;
+
+ uint8_t port_id = parse_byte(params, "port_id", result);
+
+ if (port_id >= TrexStateless::get_instance().get_port_count()) {
+ std::stringstream ss;
+ ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1;
+ generate_execute_err(result, ss.str());
+ }
+
+ TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+
+ port->get_stream_table()->get_stream_list(stream_list);
+
+ Json::Value json_list = Json::arrayValue;
+
+ for (auto stream_id : stream_list) {
+ json_list.append(stream_id);
+ }
+
+ result["result"] = json_list;
+
+ return (TREX_RPC_CMD_OK);
+}
+
+/***************************
+ * get stream by id
+ * on a specific port
+ *
+ **************************/
+trex_rpc_cmd_rc_e
+TrexRpcCmdGetStream::_run(const Json::Value &params, Json::Value &result) {
+ uint8_t port_id = parse_byte(params, "port_id", result);
+
+ uint32_t stream_id = parse_int(params, "stream_id", result);
+
+ if (port_id >= TrexStateless::get_instance().get_port_count()) {
+ std::stringstream ss;
+ ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1;
+ generate_execute_err(result, ss.str());
+ }
+
+ TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+
+ TrexStream *stream = port->get_stream_table()->get_stream_by_id(stream_id);
+
+ if (!stream) {
+ std::stringstream ss;
+ ss << "stream id " << stream_id << " on port " << (int)port_id << " does not exists";
+ generate_execute_err(result, ss.str());
+ }
+
+ Json::Value stream_json;
+
+ stream_json["enabled"] = stream->m_enabled;
+ stream_json["self_start"] = stream->m_self_start;
+
+ stream_json["isg"] = stream->m_isg_usec;
+ stream_json["next_stream_id"] = stream->m_next_stream_id;
+
+ stream_json["packet"]["binary"] = Json::arrayValue;
+ for (int i = 0; i < stream->m_pkt.len; i++) {
+ stream_json["packet"]["binary"].append(stream->m_pkt.binary[i]);
+ }
+
+ stream_json["packet"]["meta"] = stream->m_pkt.meta;
+
+ if (TrexStreamContinuous *cont = dynamic_cast<TrexStreamContinuous *>(stream)) {
+ stream_json["mode"]["type"] = "continuous";
+ stream_json["mode"]["pps"] = cont->get_pps();
+
+ }
+
+ result["result"]["stream"] = stream_json;
+
+ return (TREX_RPC_CMD_OK);
+}
+
+/***************************
+ * start traffic on port
+ *
+ **************************/
+trex_rpc_cmd_rc_e
+TrexRpcCmdStartTraffic::_run(const Json::Value &params, Json::Value &result) {
+ uint8_t port_id = parse_byte(params, "port_id", result);
+
+ if (port_id >= TrexStateless::get_instance().get_port_count()) {
+ std::stringstream ss;
+ ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1;
+ generate_execute_err(result, ss.str());
+ }
+
+ TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+
+ TrexStatelessPort::traffic_rc_e rc = port->start_traffic();
+
+ if (rc == TrexStatelessPort::TRAFFIC_OK) {
+ result["result"] = "ACK";
+ } else {
+ std::stringstream ss;
+ switch (rc) {
+ case TrexStatelessPort::TRAFFIC_ERR_ALREADY_STARTED:
+ ss << "traffic has already started on that port";
+ break;
+ case TrexStatelessPort::TRAFFIC_ERR_NO_STREAMS:
+ ss << "no active streams on that port";
+ break;
+ default:
+ ss << "failed to start traffic";
+ break;
+ }
+
+ generate_execute_err(result, ss.str());
+ }
+
+ return (TREX_RPC_CMD_OK);
+}
+
+/***************************
+ * start traffic on port
+ *
+ **************************/
+trex_rpc_cmd_rc_e
+TrexRpcCmdStopTraffic::_run(const Json::Value &params, Json::Value &result) {
+ uint8_t port_id = parse_byte(params, "port_id", result);
+
+ if (port_id >= TrexStateless::get_instance().get_port_count()) {
+ std::stringstream ss;
+ ss << "invalid port id - should be between 0 and " << (int)TrexStateless::get_instance().get_port_count() - 1;
+ generate_execute_err(result, ss.str());
+ }
+
+ TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+
+ port->stop_traffic();
+ result["result"] = "ACK";
+
+ return (TREX_RPC_CMD_OK);
}
diff --git a/src/rpc-server/commands/trex_rpc_cmds.h b/src/rpc-server/commands/trex_rpc_cmds.h
index 64551fac..f88631bc 100644
--- a/src/rpc-server/commands/trex_rpc_cmds.h
+++ b/src/rpc-server/commands/trex_rpc_cmds.h
@@ -65,13 +65,23 @@ TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStatus, "get_status", 0);
TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveAllStreams, "remove_all_streams", 1);
TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveStream, "remove_stream", 2);
-TREX_RPC_CMD_DEFINE_EXTENED(TrexRpcCmdAddStream, "add_stream", 1,
+TREX_RPC_CMD_DEFINE_EXTENED(TrexRpcCmdAddStream, "add_stream", 3,
/* extended part */
-TrexStream * allocate_new_stream(const Json::Value &section, Json::Value &result);
+TrexStream * allocate_new_stream(const Json::Value &section, uint8_t port_id, uint32_t stream_id, Json::Value &result);
void validate_stream(const TrexStream *stream, Json::Value &result);
-
+void parse_vm(const Json::Value &vm, TrexStream *stream, Json::Value &result);
+void parse_vm_instr_checksum(const Json::Value &inst, TrexStream *stream, Json::Value &result);
+void parse_vm_instr_flow_var(const Json::Value &inst, TrexStream *stream, Json::Value &result);
+void parse_vm_instr_write_flow_var(const Json::Value &inst, TrexStream *stream, Json::Value &result);
);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStreamList, "get_stream_list", 1);
+
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStream, "get_stream", 2);
+
+TREX_RPC_CMD_DEFINE(TrexRpcCmdStartTraffic, "start_traffic", 1);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdStopTraffic, "stop_traffic", 1);
+
#endif /* __TREX_RPC_CMD_H__ */
diff --git a/src/rpc-server/trex_rpc_cmd.cpp b/src/rpc-server/trex_rpc_cmd.cpp
index 6988cba7..3fc77f71 100644
--- a/src/rpc-server/trex_rpc_cmd.cpp
+++ b/src/rpc-server/trex_rpc_cmd.cpp
@@ -50,6 +50,8 @@ TrexRpcCommand::type_to_str(field_type_e type) {
switch (type) {
case FIELD_TYPE_BYTE:
return "byte";
+ case FIELD_TYPE_UINT16:
+ return "uint16";
case FIELD_TYPE_BOOL:
return "bool";
case FIELD_TYPE_INT:
@@ -107,6 +109,18 @@ TrexRpcCommand::parse_byte(const Json::Value &parent, int index, Json::Value &re
return parent[index].asUInt();
}
+uint16_t
+TrexRpcCommand::parse_uint16(const Json::Value &parent, const std::string &name, Json::Value &result) {
+ check_field_type(parent, name, FIELD_TYPE_UINT16, result);
+ return parent[name].asUInt();
+}
+
+uint16_t
+TrexRpcCommand::parse_uint16(const Json::Value &parent, int index, Json::Value &result) {
+ check_field_type(parent, index, FIELD_TYPE_UINT16, 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);
@@ -190,6 +204,12 @@ TrexRpcCommand::check_field_type_common(const Json::Value &field, const std::str
}
break;
+ case FIELD_TYPE_UINT16:
+ if ( (!field.isUInt()) || (field.asInt() > 0xFFFF)) {
+ rc = false;
+ }
+ break;
+
case FIELD_TYPE_BOOL:
if (!field.isBool()) {
rc = false;
diff --git a/src/rpc-server/trex_rpc_cmd_api.h b/src/rpc-server/trex_rpc_cmd_api.h
index da895809..def52fca 100644
--- a/src/rpc-server/trex_rpc_cmd_api.h
+++ b/src/rpc-server/trex_rpc_cmd_api.h
@@ -91,6 +91,7 @@ protected:
*/
enum field_type_e {
FIELD_TYPE_BYTE,
+ FIELD_TYPE_UINT16,
FIELD_TYPE_INT,
FIELD_TYPE_DOUBLE,
FIELD_TYPE_BOOL,
@@ -115,6 +116,7 @@ protected:
*
*/
uint8_t parse_byte(const Json::Value &parent, const std::string &name, Json::Value &result);
+ uint16_t parse_uint16(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);
@@ -123,6 +125,7 @@ protected:
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);
+ uint16_t parse_uint16(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);
@@ -131,6 +134,39 @@ protected:
const Json::Value & parse_array(const Json::Value &parent, int index, Json::Value &result);
/**
+ * parse a field from choices
+ *
+ */
+ template<typename T> T parse_choice(const Json::Value &params, const std::string &name, std::initializer_list<T> choices, Json::Value &result) {
+ const Json::Value &field = params[name];
+
+ if (field == Json::Value::null) {
+ std::stringstream ss;
+ ss << "field '" << name << "' is missing";
+ generate_parse_err(result, ss.str());
+ }
+
+ for (auto x : choices) {
+ if (field == x) {
+ return (x);
+ }
+ }
+
+ std::stringstream ss;
+
+ ss << "field '" << name << "' can only be one of [";
+ for (auto x : choices) {
+ ss << "'" << x << "' ,";
+ }
+
+ std::string s = ss.str();
+ s.pop_back();
+ s.pop_back();
+ s += "]";
+ generate_parse_err(result, s);
+ }
+
+ /**
* check field type
*
*/
diff --git a/src/rpc-server/trex_rpc_cmds_table.cpp b/src/rpc-server/trex_rpc_cmds_table.cpp
index 7d5d49ae..71668994 100644
--- a/src/rpc-server/trex_rpc_cmds_table.cpp
+++ b/src/rpc-server/trex_rpc_cmds_table.cpp
@@ -38,6 +38,10 @@ TrexRpcCommandsTable::TrexRpcCommandsTable() {
register_command(new TrexRpcCmdAddStream());
register_command(new TrexRpcCmdRemoveStream());
register_command(new TrexRpcCmdRemoveAllStreams());
+ register_command(new TrexRpcCmdGetStreamList());
+ register_command(new TrexRpcCmdGetStream());
+ register_command(new TrexRpcCmdStartTraffic());
+ register_command(new TrexRpcCmdStopTraffic());
}
TrexRpcCommandsTable::~TrexRpcCommandsTable() {
diff --git a/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp
index 3831bb37..928baca6 100644
--- a/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp
+++ b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp
@@ -200,3 +200,28 @@ void TrexJsonRpcV2Parser::parse_single_request(Json::Value &request,
commands.push_back(new JsonRpcMethod(msg_id, rpc_cmd, request["params"]));
}
+/**
+ * tries to pretty a JSON str
+ *
+ * @author imarom (03-Sep-15)
+ *
+ * @param json_str
+ *
+ * @return std::string
+ */
+std::string TrexJsonRpcV2Parser::pretty_json_str(const std::string &json_str) {
+ Json::Reader reader;
+ Json::Value value;
+
+ /* basic JSON parsing */
+ bool rc = reader.parse(json_str, value, false);
+ if (!rc) {
+ /* duplicate the soruce */
+ return json_str;
+ }
+
+ /* successfully parsed */
+ Json::StyledWriter writer;
+ return writer.write(value);
+}
+
diff --git a/src/rpc-server/trex_rpc_jsonrpc_v2_parser.h b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.h
index 3367ad6a..ebffaeb7 100644
--- a/src/rpc-server/trex_rpc_jsonrpc_v2_parser.h
+++ b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.h
@@ -79,6 +79,14 @@ public:
*/
void parse(std::vector<TrexJsonRpcV2ParsedObject *> &commands);
+ /**
+ * *tries* to generate a pretty string from JSON
+ * if json_str is not a valid JSON string
+ * it will duplicate the source
+ *
+ */
+ static std::string pretty_json_str(const std::string &json_str);
+
private:
/**
diff --git a/src/rpc-server/trex_rpc_req_resp_server.cpp b/src/rpc-server/trex_rpc_req_resp_server.cpp
index 7484758d..c4d9dfdb 100644
--- a/src/rpc-server/trex_rpc_req_resp_server.cpp
+++ b/src/rpc-server/trex_rpc_req_resp_server.cpp
@@ -85,7 +85,7 @@ void TrexRpcServerReqRes::_rpc_thread_cb() {
/* transform it to a string */
std::string request((const char *)m_msg_buffer, msg_size);
- verbose_msg("Server Received: " + request);
+ verbose_json("Server Received: ", TrexJsonRpcV2Parser::pretty_json_str(request));
handle_request(request);
}
@@ -110,6 +110,7 @@ void TrexRpcServerReqRes::_stop_rpc_thread() {
*/
void TrexRpcServerReqRes::handle_request(const std::string &request) {
std::vector<TrexJsonRpcV2ParsedObject *> commands;
+
Json::FastWriter writer;
Json::Value response;
@@ -139,7 +140,7 @@ void TrexRpcServerReqRes::handle_request(const std::string &request) {
response_str = writer.write(response);
}
- verbose_msg("Server Replied: " + response_str);
+ verbose_json("Server Replied: ", response_str);
zmq_send(m_socket, response_str.c_str(), response_str.size(), 0);
diff --git a/src/rpc-server/trex_rpc_server.cpp b/src/rpc-server/trex_rpc_server.cpp
index 366bfc5b..149bb668 100644
--- a/src/rpc-server/trex_rpc_server.cpp
+++ b/src/rpc-server/trex_rpc_server.cpp
@@ -21,6 +21,7 @@ limitations under the License.
#include <trex_rpc_server_api.h>
#include <trex_rpc_req_resp_server.h>
+#include <trex_rpc_jsonrpc_v2_parser.h>
#include <unistd.h>
#include <zmq.h>
#include <sstream>
@@ -47,6 +48,10 @@ void TrexRpcServerInterface::verbose_msg(const std::string &msg) {
std::cout << "[verbose][" << m_name << "] " << msg << "\n";
}
+void TrexRpcServerInterface::verbose_json(const std::string &msg, const std::string &json_str) {
+ verbose_msg(msg + "\n\n" + TrexJsonRpcV2Parser::pretty_json_str(json_str));
+}
+
/**
* starts a RPC specific server
*
@@ -106,6 +111,7 @@ get_current_date_time() {
}
const std::string TrexRpcServer::s_server_uptime = get_current_date_time();
+std::string TrexRpcServer::s_owner = "none";
TrexRpcServer::TrexRpcServer(const TrexRpcServerConfig &req_resp_cfg) {
diff --git a/src/rpc-server/trex_rpc_server_api.h b/src/rpc-server/trex_rpc_server_api.h
index 6bb81c73..b4313670 100644
--- a/src/rpc-server/trex_rpc_server_api.h
+++ b/src/rpc-server/trex_rpc_server_api.h
@@ -115,6 +115,13 @@ protected:
*/
void verbose_msg(const std::string &msg);
+ /**
+ * prints a verbose message with a JSON to be converted to
+ * string
+ *
+ */
+ void verbose_json(const std::string &msg, const std::string &json_str);
+
TrexRpcServerConfig m_cfg;
bool m_is_running;
bool m_is_verbose;
@@ -156,10 +163,34 @@ public:
return s_server_uptime;
}
+
+ /**
+ * query for ownership
+ *
+ */
+ static const std::string &get_owner() {
+ return s_owner;
+ }
+
+ /**
+ * take ownership of the server array
+ * this is static
+ * ownership is total
+ *
+ */
+ static void set_owner(const std::string &owner) {
+ s_owner = owner;
+ }
+
+ static void clear_owner() {
+ s_owner = "none";
+ }
+
private:
std::vector<TrexRpcServerInterface *> m_servers;
bool m_verbose;
static const std::string s_server_uptime;
+ static std::string s_owner;
};
#endif /* __TREX_RPC_SERVER_API_H__ */
diff --git a/src/rpc-server/trex_rpc_server_mock.cpp b/src/rpc-server/trex_rpc_server_mock.cpp
index 98d1f35d..835e28b8 100644
--- a/src/rpc-server/trex_rpc_server_mock.cpp
+++ b/src/rpc-server/trex_rpc_server_mock.cpp
@@ -20,6 +20,8 @@ limitations under the License.
*/
#include <trex_rpc_server_api.h>
+#include <trex_stateless_api.h>
+
#include <iostream>
#include <unistd.h>
@@ -42,6 +44,9 @@ int gtest_main(int argc, char **argv);
int main(int argc, char *argv[]) {
+ /* configure the stateless object with 4 ports */
+ TrexStateless::configure(4);
+
// gtest ?
if (argc > 1) {
if (string(argv[1]) != "--ut") {