summaryrefslogtreecommitdiffstats
path: root/src/rpc-server
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpc-server')
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_general.cpp267
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_stream.cpp488
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_test.cpp51
-rw-r--r--src/rpc-server/commands/trex_rpc_cmds.h104
-rw-r--r--src/rpc-server/include/trex_rpc_cmd_api.h90
-rw-r--r--src/rpc-server/src/commands/trex_rpc_cmd_general.cpp49
-rw-r--r--src/rpc-server/src/commands/trex_rpc_cmd_test.cpp126
-rw-r--r--src/rpc-server/src/commands/trex_rpc_cmds.h89
-rw-r--r--src/rpc-server/trex_rpc_cmd.cpp317
-rw-r--r--src/rpc-server/trex_rpc_cmd_api.h241
-rw-r--r--src/rpc-server/trex_rpc_cmds_table.cpp (renamed from src/rpc-server/src/trex_rpc_cmds_table.cpp)20
-rw-r--r--src/rpc-server/trex_rpc_cmds_table.h (renamed from src/rpc-server/include/trex_rpc_cmds_table.h)0
-rw-r--r--src/rpc-server/trex_rpc_exception_api.h (renamed from src/rpc-server/include/trex_rpc_exception_api.h)3
-rw-r--r--src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp (renamed from src/rpc-server/src/trex_rpc_jsonrpc_v2_parser.cpp)53
-rw-r--r--src/rpc-server/trex_rpc_jsonrpc_v2_parser.h (renamed from src/rpc-server/include/trex_rpc_jsonrpc_v2_parser.h)17
-rw-r--r--src/rpc-server/trex_rpc_req_resp_server.cpp (renamed from src/rpc-server/src/trex_rpc_req_resp_server.cpp)32
-rw-r--r--src/rpc-server/trex_rpc_req_resp_server.h (renamed from src/rpc-server/include/trex_rpc_req_resp_server.h)4
-rw-r--r--src/rpc-server/trex_rpc_server.cpp (renamed from src/rpc-server/src/trex_rpc_server.cpp)5
-rw-r--r--src/rpc-server/trex_rpc_server_api.h (renamed from src/rpc-server/include/trex_rpc_server_api.h)15
-rw-r--r--src/rpc-server/trex_rpc_server_mock.cpp (renamed from src/rpc-server/src/trex_rpc_server_mock.cpp)7
20 files changed, 1612 insertions, 366 deletions
diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
new file mode 100644
index 00000000..106a167a
--- /dev/null
+++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
@@ -0,0 +1,267 @@
+/*
+ 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_rpc_cmds.h"
+#include <trex_rpc_server_api.h>
+#include <trex_stateless_api.h>
+#include <trex_rpc_cmds_table.h>
+
+#include <fstream>
+#include <iostream>
+#include <unistd.h>
+
+#ifndef TREX_RPC_MOCK_SERVER
+ #include <../linux_dpdk/version.h>
+#endif
+
+using namespace std;
+
+/**
+ * ping command
+ */
+trex_rpc_cmd_rc_e
+TrexRpcCmdPing::_run(const Json::Value &params, Json::Value &result) {
+
+ result["result"] = "ACK";
+ return (TREX_RPC_CMD_OK);
+}
+
+/**
+ * query command
+ */
+trex_rpc_cmd_rc_e
+TrexRpcCmdGetCmds::_run(const Json::Value &params, Json::Value &result) {
+ vector<string> cmds;
+
+ TrexRpcCommandsTable::get_instance().query(cmds);
+
+ Json::Value test = Json::arrayValue;
+ for (auto cmd : cmds) {
+ test.append(cmd);
+ }
+
+ result["result"] = test;
+
+ return (TREX_RPC_CMD_OK);
+}
+
+/**
+ * get version
+ *
+ */
+trex_rpc_cmd_rc_e
+TrexRpcCmdGetVersion::_run(const Json::Value &params, Json::Value &result) {
+
+ Json::Value &section = result["result"];
+
+ #ifndef TREX_RPC_MOCK_SERVER
+
+ section["version"] = VERSION_BUILD_NUM;
+ section["build_date"] = get_build_date();
+ section["build_time"] = get_build_time();
+ section["built_by"] = VERSION_USER;
+
+ #else
+
+ section["version"] = "v0.0";
+ section["build_date"] = __DATE__;
+ section["build_time"] = __TIME__;
+ section["built_by"] = "MOCK";
+
+ #endif
+
+ return (TREX_RPC_CMD_OK);
+}
+
+/**
+ * get the CPU model
+ *
+ */
+std::string
+TrexRpcCmdGetSysInfo::get_cpu_model() {
+
+ static const string cpu_prefix = "model name";
+ std::ifstream cpuinfo("/proc/cpuinfo");
+
+ if (cpuinfo.is_open()) {
+ while (cpuinfo.good()) {
+
+ std::string line;
+ getline(cpuinfo, line);
+
+ int pos = line.find(cpu_prefix);
+ if (pos == string::npos) {
+ continue;
+ }
+
+ /* trim it */
+ int index = cpu_prefix.size() + 1;
+ while ( (line[index] == ' ') || (line[index] == ':') ) {
+ index++;
+ }
+
+ return line.substr(index);
+ }
+ }
+
+ return "unknown";
+}
+
+void
+TrexRpcCmdGetSysInfo::get_hostname(string &hostname) {
+ char buffer[256];
+ buffer[0] = 0;
+
+ gethostname(buffer, sizeof(buffer));
+
+ /* write hostname */
+ hostname = buffer;
+}
+
+/**
+ * get system info
+ *
+ */
+trex_rpc_cmd_rc_e
+TrexRpcCmdGetSysInfo::_run(const Json::Value &params, Json::Value &result) {
+ string hostname;
+
+ TrexStateless & instance = TrexStateless::get_instance();
+
+ Json::Value &section = result["result"];
+
+ get_hostname(hostname);
+ section["hostname"] = hostname;
+
+ section["uptime"] = TrexRpcServer::get_server_uptime();
+
+ /* FIXME: core count */
+ section["dp_core_count"] = 1;
+ section["core_type"] = get_cpu_model();
+
+ /* ports */
+
+
+ section["port_count"] = instance.get_port_count();
+
+ section["ports"] = Json::arrayValue;
+
+ for (int i = 0; i < instance.get_port_count(); i++) {
+ string driver;
+ string speed;
+
+ TrexStatelessPort *port = instance.get_port_by_id(i);
+ port->get_properties(driver, speed);
+
+ section["ports"][i]["index"] = i;
+ section["ports"][i]["driver"] = driver;
+ section["ports"][i]["speed"] = speed;
+
+ section["ports"][i]["owner"] = port->get_owner();
+
+ switch (port->get_state()) {
+ case TrexStatelessPort::PORT_STATE_DOWN:
+ section["ports"][i]["status"] = "down";
+ break;
+
+ case TrexStatelessPort::PORT_STATE_UP_IDLE:
+ section["ports"][i]["status"] = "idle";
+ break;
+
+ case TrexStatelessPort::PORT_STATE_TRANSMITTING:
+ section["ports"][i]["status"] = "transmitting";
+ break;
+ }
+
+ }
+
+ return (TREX_RPC_CMD_OK);
+}
+
+/**
+ * returns the current owner of the device
+ *
+ * @author imarom (08-Sep-15)
+ *
+ * @param params
+ * @param result
+ *
+ * @return trex_rpc_cmd_rc_e
+ */
+trex_rpc_cmd_rc_e
+TrexRpcCmdGetOwner::_run(const Json::Value &params, Json::Value &result) {
+ Json::Value &section = result["result"];
+
+ uint8_t port_id = parse_port(params, result);
+
+ TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+ section["owner"] = port->get_owner();
+
+ return (TREX_RPC_CMD_OK);
+}
+
+/**
+ * acquire device
+ *
+ */
+trex_rpc_cmd_rc_e
+TrexRpcCmdAcquire::_run(const Json::Value &params, Json::Value &result) {
+
+ uint8_t port_id = parse_port(params, result);
+
+ const string &new_owner = parse_string(params, "user", result);
+ bool force = parse_bool(params, "force", result);
+
+ /* if not free and not you and not force - fail */
+ TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+
+ if ( (!port->is_free_to_aquire()) && (port->get_owner() != new_owner) && (!force)) {
+ generate_execute_err(result, "device is already taken by '" + port->get_owner() + "'");
+ }
+
+ port->set_owner(new_owner);
+
+ result["result"] = port->get_owner_handler();
+
+ return (TREX_RPC_CMD_OK);
+}
+
+/**
+ * release device
+ *
+ */
+trex_rpc_cmd_rc_e
+TrexRpcCmdRelease::_run(const Json::Value &params, Json::Value &result) {
+
+ uint8_t port_id = parse_port(params, result);
+
+ TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+
+ if (port->get_state() == TrexStatelessPort::PORT_STATE_TRANSMITTING) {
+ generate_execute_err(result, "cannot release a port during transmission");
+ }
+
+ port->clear_owner();
+
+ result["result"] = "ACK";
+
+ 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
new file mode 100644
index 00000000..1450e1a9
--- /dev/null
+++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
@@ -0,0 +1,488 @@
+/*
+ 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_rpc_cmds.h"
+#include <trex_rpc_server_api.h>
+#include <trex_stream_api.h>
+#include <trex_stateless_api.h>
+
+#include <iostream>
+
+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
+ *
+ **************************/
+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 */
+ const Json::Value &mode = parse_object(section, "mode", result);
+ string type = parse_string(mode, "type", result);
+
+ /* allocate a new stream based on the type */
+ TrexStream *stream = allocate_new_stream(section, port_id, stream_id, result);
+
+ /* save this for future queries */
+ stream->store_stream_json(section);
+
+ /* 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, "isg", result);
+
+ stream->m_next_stream_id = parse_int(section, "next_stream_id", 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_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_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);
+
+ stream->m_rx_check.m_enable = parse_bool(rx, "enabled", result);
+
+ /* if it is enabled - we need more fields */
+ if (stream->m_rx_check.m_enable) {
+ stream->m_rx_check.m_stream_id = parse_int(rx, "stream_id", result);
+ stream->m_rx_check.m_seq_enabled = parse_bool(rx, "seq_enabled", result);
+ stream->m_rx_check.m_latency = parse_bool(rx, "latency", result);
+ }
+
+ /* make sure this is a valid stream to add */
+ validate_stream(stream, result);
+
+ TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(stream->m_port_id);
+ port->get_stream_table()->add_stream(stream);
+
+ result["result"] = "ACK";
+
+ return (TREX_RPC_CMD_OK);
+}
+
+
+
+TrexStream *
+TrexRpcCmdAddStream::allocate_new_stream(const Json::Value &section, uint8_t port_id, uint32_t stream_id, Json::Value &result) {
+
+ TrexStream *stream;
+
+ const Json::Value &mode = parse_object(section, "mode", result);
+ std::string type = parse_string(mode, "type", result);
+
+ if (type == "continuous") {
+
+ double pps = parse_double(mode, "pps", result);
+ stream = new TrexStreamContinuous(port_id, stream_id, pps);
+
+ } else if (type == "single_burst") {
+
+ uint32_t total_pkts = parse_int(mode, "total_pkts", result);
+ double pps = parse_double(mode, "pps", result);
+
+ stream = new TrexStreamBurst(port_id, stream_id, total_pkts, pps);
+
+ } else if (type == "multi_burst") {
+
+ double pps = parse_double(mode, "pps", result);
+ double ibg_usec = parse_double(mode, "ibg", result);
+ uint32_t num_bursts = parse_int(mode, "number_of_bursts", result);
+ uint32_t pkts_per_burst = parse_int(mode, "pkts_per_burst", result);
+
+ stream = new TrexStreamMultiBurst(port_id, stream_id, pkts_per_burst, pps, num_bursts, ibg_usec);
+
+
+ } else {
+ generate_parse_err(result, "bad stream type provided: '" + type + "'");
+ }
+
+ /* make sure we were able to allocate the memory */
+ if (!stream) {
+ generate_internal_err(result, "unable to allocate memory");
+ }
+
+ return (stream);
+
+}
+
+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) ) {
+ std::stringstream ss;
+ ss << "bad packet size provided: should be between " << TrexStream::MIN_PKT_SIZE_BYTES << " and " << TrexStream::MAX_PKT_SIZE_BYTES;
+ delete stream;
+ generate_execute_err(result, ss.str());
+ }
+
+ /* port id should be between 0 and count - 1 */
+ if (stream->m_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;
+ delete stream;
+ generate_execute_err(result, ss.str());
+ }
+
+ /* add the stream to the port's stream table */
+ 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)) {
+ std::stringstream ss;
+ ss << "stream " << stream->m_stream_id << " already exists";
+ delete stream;
+ generate_execute_err(result, ss.str());
+ }
+
+}
+
+/***************************
+ * remove stream
+ *
+ **************************/
+trex_rpc_cmd_rc_e
+TrexRpcCmdRemoveStream::_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 " << stream_id << " does not exists";
+ generate_execute_err(result, ss.str());
+ }
+
+ port->get_stream_table()->remove_stream(stream);
+ delete stream;
+
+ result["result"] = "ACK";
+
+ return (TREX_RPC_CMD_OK);
+}
+
+/***************************
+ * remove all streams
+ * for a port
+ *
+ **************************/
+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 >= 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()->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());
+ }
+
+ /* return the stored stream json (instead of decoding it all over again) */
+ result["result"]["stream"] = stream->get_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::rc_e rc = port->start_traffic();
+
+ if (rc == TrexStatelessPort::RC_OK) {
+ result["result"] = "ACK";
+ } else {
+ std::stringstream ss;
+ switch (rc) {
+ case TrexStatelessPort::RC_ERR_BAD_STATE_FOR_OP:
+ ss << "bad state for operations: port is either transmitting traffic or down";
+ break;
+ case TrexStatelessPort::RC_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_cmd_test.cpp b/src/rpc-server/commands/trex_rpc_cmd_test.cpp
new file mode 100644
index 00000000..3cdddd31
--- /dev/null
+++ b/src/rpc-server/commands/trex_rpc_cmd_test.cpp
@@ -0,0 +1,51 @@
+/*
+ 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_rpc_cmds.h"
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+/**
+ * add command
+ *
+ */
+trex_rpc_cmd_rc_e
+TrexRpcCmdTestAdd::_run(const Json::Value &params, Json::Value &result) {
+
+ result["result"] = parse_int(params, "x", result) + parse_int(params, "y", result);
+
+ return (TREX_RPC_CMD_OK);
+}
+
+/**
+ * sub command
+ *
+ * @author imarom (16-Aug-15)
+ */
+trex_rpc_cmd_rc_e
+TrexRpcCmdTestSub::_run(const Json::Value &params, Json::Value &result) {
+
+ result["result"] = parse_int(params, "x", result) - parse_int(params, "y", result);
+
+ 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
new file mode 100644
index 00000000..e261d1c6
--- /dev/null
+++ b/src/rpc-server/commands/trex_rpc_cmds.h
@@ -0,0 +1,104 @@
+/*
+ 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_RPC_CMD_H__
+#define __TREX_RPC_CMD_H__
+
+#include <trex_rpc_cmd_api.h>
+#include <json/json.h>
+
+class TrexStream;
+
+/* all the RPC commands decl. goes here */
+
+/******************* test section ************/
+
+/**
+ * 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(class_name, cmd_name, param_count, needs_ownership) TREX_RPC_CMD_DEFINE_EXTENDED(class_name, cmd_name, param_count, needs_ownership, ;)
+
+/**
+ * test cmds
+ */
+TREX_RPC_CMD_DEFINE(TrexRpcCmdTestAdd, "test_add", 2, false);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdTestSub, "test_sub", 2, false);
+
+/**
+ * general cmds
+ */
+TREX_RPC_CMD_DEFINE(TrexRpcCmdPing, "ping", 0, false);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetCmds, "get_supported_cmds", 0, false);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetVersion, "get_version", 0, false);
+
+TREX_RPC_CMD_DEFINE_EXTENDED(TrexRpcCmdGetSysInfo, "get_system_info", 0, false,
+
+std::string get_cpu_model();
+void get_hostname(std::string &hostname);
+
+);
+
+/**
+ * ownership
+ */
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetOwner, "get_owner", 1, false);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdAcquire, "acquire", 3, false);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdRelease, "release", 1, true);
+
+
+/**
+ * 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_EXTENDED(TrexRpcCmdAddStream, "add_stream", 3, true,
+
+/* extended part */
+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, true);
+
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStream, "get_stream", 2, true);
+
+TREX_RPC_CMD_DEFINE(TrexRpcCmdStartTraffic, "start_traffic", 1, true);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdStopTraffic, "stop_traffic", 1, true);
+
+
+
+#endif /* __TREX_RPC_CMD_H__ */
diff --git a/src/rpc-server/include/trex_rpc_cmd_api.h b/src/rpc-server/include/trex_rpc_cmd_api.h
deleted file mode 100644
index c773b15f..00000000
--- a/src/rpc-server/include/trex_rpc_cmd_api.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- 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_RPC_CMD_API_H__
-#define __TREX_RPC_CMD_API_H__
-
-#include <string>
-#include <vector>
-#include <json/json.h>
-
-/**
- * interface for RPC command
- *
- * @author imarom (13-Aug-15)
- */
-class TrexRpcCommand {
-public:
-
- /**
- * describe different types of rc for run()
- */
- enum rpc_cmd_rc_e {
- RPC_CMD_OK,
- RPC_CMD_PARAM_COUNT_ERR = 1,
- RPC_CMD_PARAM_PARSE_ERR,
- RPC_CMD_INTERNAL_ERR
- };
-
- /**
- * method name and params
- */
- TrexRpcCommand(const std::string &method_name) : m_name(method_name) {
-
- }
-
- rpc_cmd_rc_e run(const Json::Value &params, Json::Value &result) {
- return _run(params, result);
- }
-
- const std::string &get_name() {
- return m_name;
- }
-
- virtual ~TrexRpcCommand() {}
-
-protected:
-
- /**
- * implemented by the dervied class
- *
- */
- virtual rpc_cmd_rc_e _run(const Json::Value &params, Json::Value &result) = 0;
-
- /**
- * error generating functions
- *
- */
- void genernate_err(Json::Value &result, const std::string &msg) {
- result["specific_err"] = msg;
- }
-
- void generate_err_param_count(Json::Value &result, int expected, int provided) {
- std::stringstream ss;
- ss << "method expects '" << expected << "' paramteres, '" << provided << "' provided";
- genernate_err(result, ss.str());
- }
-
- std::string m_name;
-};
-
-#endif /* __TREX_RPC_CMD_API_H__ */
-
diff --git a/src/rpc-server/src/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/src/commands/trex_rpc_cmd_general.cpp
deleted file mode 100644
index 193ce8db..00000000
--- a/src/rpc-server/src/commands/trex_rpc_cmd_general.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- 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_rpc_cmds.h"
-#include <../linux_dpdk/version.h>
-#include <trex_rpc_server_api.h>
-
-using namespace std;
-
-/**
- * get status
- *
- */
-TrexRpcCommand::rpc_cmd_rc_e
-TrexRpcCmdGetStatus::_run(const Json::Value &params, Json::Value &result) {
-
- /* validate count */
- if (params.size() != 0) {
- generate_err_param_count(result, 0, params.size());
- return (TrexRpcCommand::RPC_CMD_PARAM_COUNT_ERR);
- }
-
- Json::Value &section = result["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();
- return (RPC_CMD_OK);
-}
-
diff --git a/src/rpc-server/src/commands/trex_rpc_cmd_test.cpp b/src/rpc-server/src/commands/trex_rpc_cmd_test.cpp
deleted file mode 100644
index e2dc8959..00000000
--- a/src/rpc-server/src/commands/trex_rpc_cmd_test.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- 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_rpc_cmds.h"
-#include <iostream>
-#include <sstream>
-#include <trex_rpc_cmds_table.h>
-
-using namespace std;
-
-/**
- * add command
- *
- */
-TrexRpcCommand::rpc_cmd_rc_e
-TrexRpcCmdTestAdd::_run(const Json::Value &params, Json::Value &result) {
-
- const Json::Value &x = params["x"];
- const Json::Value &y = params["y"];
-
- /* validate count */
- if (params.size() != 2) {
- generate_err_param_count(result, 2, params.size());
- return (TrexRpcCommand::RPC_CMD_PARAM_COUNT_ERR);
- }
-
- /* check we have all the required paramters */
- if (!x.isInt()) {
- genernate_err(result, "'x' is either missing or not an integer");
- return (TrexRpcCommand::RPC_CMD_PARAM_PARSE_ERR);
- }
-
- if (!y.isInt()) {
- genernate_err(result, "'y' is either missing or not an integer");
- return (TrexRpcCommand::RPC_CMD_PARAM_PARSE_ERR);
- }
-
- result["result"] = x.asInt() + y.asInt();
- return (RPC_CMD_OK);
-}
-
-/**
- * sub command
- *
- * @author imarom (16-Aug-15)
- */
-TrexRpcCommand::rpc_cmd_rc_e
-TrexRpcCmdTestSub::_run(const Json::Value &params, Json::Value &result) {
-
- const Json::Value &x = params["x"];
- const Json::Value &y = params["y"];
-
- /* validate count */
- if (params.size() != 2) {
- generate_err_param_count(result, 2, params.size());
- return (TrexRpcCommand::RPC_CMD_PARAM_COUNT_ERR);
- }
-
- /* check we have all the required paramters */
- if (!x.isInt() || !y.isInt()) {
- return (TrexRpcCommand::RPC_CMD_PARAM_PARSE_ERR);
- }
-
- result["result"] = x.asInt() - y.asInt();
- return (RPC_CMD_OK);
-}
-
-/**
- * ping command
- */
-TrexRpcCommand::rpc_cmd_rc_e
-TrexRpcCmdPing::_run(const Json::Value &params, Json::Value &result) {
-
- /* validate count */
- if (params.size() != 0) {
- generate_err_param_count(result, 0, params.size());
- return (TrexRpcCommand::RPC_CMD_PARAM_COUNT_ERR);
- }
-
- result["result"] = "ACK";
- return (RPC_CMD_OK);
-}
-
-/**
- * query command
- */
-TrexRpcCommand::rpc_cmd_rc_e
-TrexRpcCmdGetReg::_run(const Json::Value &params, Json::Value &result) {
- vector<string> cmds;
-
- /* validate count */
- if (params.size() != 0) {
- generate_err_param_count(result, 0, params.size());
- return (TrexRpcCommand::RPC_CMD_PARAM_COUNT_ERR);
- }
-
-
- TrexRpcCommandsTable::get_instance().query(cmds);
-
- Json::Value test = Json::arrayValue;
- for (auto cmd : cmds) {
- test.append(cmd);
- }
-
- result["result"] = test;
-
- return (RPC_CMD_OK);
-}
-
diff --git a/src/rpc-server/src/commands/trex_rpc_cmds.h b/src/rpc-server/src/commands/trex_rpc_cmds.h
deleted file mode 100644
index e37e1cda..00000000
--- a/src/rpc-server/src/commands/trex_rpc_cmds.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- 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_RPC_CMD_H__
-#define __TREX_RPC_CMD_H__
-
-#include <trex_rpc_cmd_api.h>
-#include <json/json.h>
-
-/* all the RPC commands decl. goes here */
-
-/******************* test section ************/
-
-/**
- * add
- *
- */
-class TrexRpcCmdTestAdd : public TrexRpcCommand {
-public:
- TrexRpcCmdTestAdd() : TrexRpcCommand("test_add") {}
-protected:
- virtual rpc_cmd_rc_e _run(const Json::Value &params, Json::Value &result);
-};
-
-/**
- * sub
- *
- */
-class TrexRpcCmdTestSub : public TrexRpcCommand {
-public:
- TrexRpcCmdTestSub() : TrexRpcCommand("test_sub") {} ;
-protected:
- virtual rpc_cmd_rc_e _run(const Json::Value &params, Json::Value &result);
-};
-
-/**
- * ping
- *
- */
-class TrexRpcCmdPing : public TrexRpcCommand {
-public:
- TrexRpcCmdPing() : TrexRpcCommand("ping") {};
-protected:
- virtual rpc_cmd_rc_e _run(const Json::Value &params, Json::Value &result);
-};
-
-/**
- * get all registered commands
- *
- */
-class TrexRpcCmdGetReg : public TrexRpcCommand {
-public:
- TrexRpcCmdGetReg() : TrexRpcCommand("get_reg_cmds") {};
-protected:
- virtual rpc_cmd_rc_e _run(const Json::Value &params, Json::Value &result);
-};
-
-/**
- * get status
- *
- */
-class TrexRpcCmdGetStatus : public TrexRpcCommand {
-public:
- TrexRpcCmdGetStatus() : TrexRpcCommand("get_status") {};
-protected:
- virtual rpc_cmd_rc_e _run(const Json::Value &params, Json::Value &result);
-};
-
-
-/**************** test section end *************/
-#endif /* __TREX_RPC_CMD_H__ */
diff --git a/src/rpc-server/trex_rpc_cmd.cpp b/src/rpc-server/trex_rpc_cmd.cpp
new file mode 100644
index 00000000..6c355e70
--- /dev/null
+++ b/src/rpc-server/trex_rpc_cmd.cpp
@@ -0,0 +1,317 @@
+/*
+ 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_rpc_cmd_api.h>
+#include <trex_rpc_server_api.h>
+#include <trex_stateless_api.h>
+
+trex_rpc_cmd_rc_e
+TrexRpcCommand::run(const Json::Value &params, Json::Value &result) {
+ trex_rpc_cmd_rc_e rc;
+
+ /* the internal run can throw a parser error / other error */
+ try {
+
+ check_param_count(params, m_param_count, result);
+
+ if (m_needs_ownership) {
+ verify_ownership(params, result);
+ }
+
+ /* run the command itself*/
+ rc = _run(params, result);
+
+ } catch (TrexRpcCommandException &e) {
+ return e.get_rc();
+ }
+
+ return (rc);
+}
+
+void
+TrexRpcCommand::check_param_count(const Json::Value &params, int expected, Json::Value &result) {
+
+ if (params.size() != expected) {
+ std::stringstream ss;
+ ss << "method expects '" << expected << "' paramteres, '" << params.size() << "' provided";
+ generate_parse_err(result, ss.str());
+ }
+}
+
+void
+TrexRpcCommand::verify_ownership(const Json::Value &params, Json::Value &result) {
+ std::string handler = parse_string(params, "handler", result);
+ uint8_t port_id = parse_port(params, result);
+
+ TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
+
+ if (!port->verify_owner_handler(handler)) {
+ generate_execute_err(result, "invalid handler provided. please pass the handler given when calling 'acquire' or take ownership");
+ }
+}
+
+uint8_t
+TrexRpcCommand::parse_port(const Json::Value &params, Json::Value &result) {
+ uint8_t port_id = parse_byte(params, "port_id", result);
+ validate_port_id(port_id, result);
+
+ return (port_id);
+}
+
+void
+TrexRpcCommand::validate_port_id(uint8_t port_id, Json::Value &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());
+ }
+}
+
+const char *
+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:
+ return "int";
+ case FIELD_TYPE_DOUBLE:
+ return "double";
+ case FIELD_TYPE_OBJ:
+ return "object";
+ case FIELD_TYPE_STR:
+ return "string";
+ case FIELD_TYPE_ARRAY:
+ return "array";
+
+ default:
+ return "UNKNOWN";
+ }
+}
+
+const char *
+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:
+ return "real";
+ case Json::stringValue:
+ return "string";
+ case Json::booleanValue:
+ return "boolean";
+ case Json::arrayValue:
+ return "array";
+ case Json::objectValue:
+ return "object";
+
+ default:
+ return "UNKNOWN";
+ }
+
+}
+
+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();
+}
+
+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);
+ 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, 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");
+ }
+
+ 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 << "' is missing";
+ generate_parse_err(result, ss.str());
+ }
+
+ bool rc = true;
+
+ switch (type) {
+ case FIELD_TYPE_BYTE:
+ if ( (!field.isUInt()) || (field.asInt() > 0xFF)) {
+ rc = false;
+ }
+ break;
+
+ case FIELD_TYPE_UINT16:
+ if ( (!field.isUInt()) || (field.asInt() > 0xFFFF)) {
+ rc = false;
+ }
+ break;
+
+ case FIELD_TYPE_BOOL:
+ if (!field.isBool()) {
+ rc = false;
+ }
+ break;
+
+ case FIELD_TYPE_INT:
+ if (!field.isInt()) {
+ rc = false;
+ }
+ break;
+
+ case FIELD_TYPE_DOUBLE:
+ if (!field.isDouble()) {
+ rc = false;
+ }
+ break;
+
+ case FIELD_TYPE_OBJ:
+ if (!field.isObject()) {
+ rc = false;
+ }
+ break;
+
+ case FIELD_TYPE_STR:
+ if (!field.isString()) {
+ 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_parse_err(result, ss.str());
+ }
+
+}
+
+void
+TrexRpcCommand::generate_parse_err(Json::Value &result, const std::string &msg) {
+ result["specific_err"] = msg;
+ throw (TrexRpcCommandException(TREX_RPC_CMD_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));
+}
+
+void
+TrexRpcCommand::generate_execute_err(Json::Value &result, const std::string &msg) {
+ result["specific_err"] = msg;
+ throw (TrexRpcCommandException(TREX_RPC_CMD_EXECUTE_ERR));
+}
+
diff --git a/src/rpc-server/trex_rpc_cmd_api.h b/src/rpc-server/trex_rpc_cmd_api.h
new file mode 100644
index 00000000..3c718eaa
--- /dev/null
+++ b/src/rpc-server/trex_rpc_cmd_api.h
@@ -0,0 +1,241 @@
+/*
+ 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_RPC_CMD_API_H__
+#define __TREX_RPC_CMD_API_H__
+
+#include <string>
+#include <vector>
+#include <json/json.h>
+#include <trex_rpc_exception_api.h>
+
+/**
+ * describe different types of rc for run()
+ */
+typedef enum trex_rpc_cmd_rc_ {
+ TREX_RPC_CMD_OK,
+ TREX_RPC_CMD_PARSE_ERR,
+ TREX_RPC_CMD_EXECUTE_ERR,
+ TREX_RPC_CMD_INTERNAL_ERR
+} trex_rpc_cmd_rc_e;
+
+/**
+ * simple exception for RPC command processing
+ *
+ * @author imarom (23-Aug-15)
+ */
+class TrexRpcCommandException : TrexRpcException {
+public:
+ TrexRpcCommandException(trex_rpc_cmd_rc_e rc) : m_rc(rc) {
+
+ }
+
+ trex_rpc_cmd_rc_e get_rc() {
+ return m_rc;
+
+ }
+
+protected:
+ trex_rpc_cmd_rc_e m_rc;
+};
+
+/**
+ * interface for RPC command
+ *
+ * @author imarom (13-Aug-15)
+ */
+class TrexRpcCommand {
+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++;
+ }
+ }
+
+ /**
+ * entry point for executing RPC command
+ *
+ */
+ trex_rpc_cmd_rc_e run(const Json::Value &params, Json::Value &result);
+
+ const std::string &get_name() {
+ return m_name;
+ }
+
+ virtual ~TrexRpcCommand() {}
+
+protected:
+
+ /**
+ * different types of fields
+ */
+ enum field_type_e {
+ FIELD_TYPE_BYTE,
+ FIELD_TYPE_UINT16,
+ FIELD_TYPE_INT,
+ FIELD_TYPE_DOUBLE,
+ FIELD_TYPE_BOOL,
+ FIELD_TYPE_STR,
+ FIELD_TYPE_OBJ,
+ FIELD_TYPE_ARRAY
+ };
+
+ /**
+ * implemented by the dervied class
+ *
+ */
+ virtual trex_rpc_cmd_rc_e _run(const Json::Value &params, Json::Value &result) = 0;
+
+ /**
+ * check param count
+ */
+ void check_param_count(const Json::Value &params, int expected, Json::Value &result);
+
+ /**
+ * verify ownership
+ *
+ */
+ void verify_ownership(const Json::Value &params, Json::Value &result);
+
+ /**
+ * validate port id
+ *
+ */
+ void validate_port_id(uint8_t port_id, Json::Value &result);
+
+ /**
+ * parse functions
+ *
+ */
+ 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);
+ 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);
+ 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);
+ 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);
+
+ /* shortcut for parsing port id */
+ uint8_t parse_port(const Json::Value &params, 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);
+
+ /* dummy return value - does not matter, the above will throw exception */
+ return (*choices.begin());
+ }
+
+ /**
+ * check field type
+ *
+ */
+ 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
+ *
+ */
+ void generate_parse_err(Json::Value &result, const std::string &msg);
+
+
+ /**
+ * method execute error
+ *
+ */
+ void generate_execute_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
+ *
+ */
+ const char * type_to_str(field_type_e type);
+
+ /**
+ * translate JSON values to string
+ *
+ */
+ 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;
+};
+
+#endif /* __TREX_RPC_CMD_API_H__ */
+
diff --git a/src/rpc-server/src/trex_rpc_cmds_table.cpp b/src/rpc-server/trex_rpc_cmds_table.cpp
index 04a56389..170f0de1 100644
--- a/src/rpc-server/src/trex_rpc_cmds_table.cpp
+++ b/src/rpc-server/trex_rpc_cmds_table.cpp
@@ -30,9 +30,25 @@ TrexRpcCommandsTable::TrexRpcCommandsTable() {
/* add the test command (for gtest) */
register_command(new TrexRpcCmdTestAdd());
register_command(new TrexRpcCmdTestSub());
+
+
+ /* general */
register_command(new TrexRpcCmdPing());
- register_command(new TrexRpcCmdGetReg());
- register_command(new TrexRpcCmdGetStatus());
+ register_command(new TrexRpcCmdGetCmds());
+ register_command(new TrexRpcCmdGetVersion());
+ register_command(new TrexRpcCmdGetSysInfo());
+ register_command(new TrexRpcCmdGetOwner());
+ register_command(new TrexRpcCmdAcquire());
+ register_command(new TrexRpcCmdRelease());
+
+ /* stream commands */
+ 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/include/trex_rpc_cmds_table.h b/src/rpc-server/trex_rpc_cmds_table.h
index a41944f1..a41944f1 100644
--- a/src/rpc-server/include/trex_rpc_cmds_table.h
+++ b/src/rpc-server/trex_rpc_cmds_table.h
diff --git a/src/rpc-server/include/trex_rpc_exception_api.h b/src/rpc-server/trex_rpc_exception_api.h
index 8783c219..e349b980 100644
--- a/src/rpc-server/include/trex_rpc_exception_api.h
+++ b/src/rpc-server/trex_rpc_exception_api.h
@@ -32,6 +32,9 @@ limitations under the License.
class TrexRpcException : public std::runtime_error
{
public:
+ TrexRpcException() : std::runtime_error("") {
+
+ }
TrexRpcException(const std::string &what) : std::runtime_error(what) {
}
};
diff --git a/src/rpc-server/src/trex_rpc_jsonrpc_v2_parser.cpp b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp
index be1eb2f8..9d9de53a 100644
--- a/src/rpc-server/src/trex_rpc_jsonrpc_v2_parser.cpp
+++ b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp
@@ -37,7 +37,10 @@ enum {
JSONRPC_V2_ERR_INVALID_REQ = -32600,
JSONRPC_V2_ERR_METHOD_NOT_FOUND = -32601,
JSONRPC_V2_ERR_INVALID_PARAMS = -32602,
- JSONRPC_V2_ERR_INTERNAL_ERROR = -32603
+ JSONRPC_V2_ERR_INTERNAL_ERROR = -32603,
+
+ /* specific server errors */
+ JSONRPC_V2_ERR_EXECUTE_ERROR = -32000,
};
@@ -71,21 +74,26 @@ public:
virtual void _execute(Json::Value &response) {
Json::Value result;
- TrexRpcCommand::rpc_cmd_rc_e rc = m_cmd->run(m_params, result);
+ trex_rpc_cmd_rc_e rc = m_cmd->run(m_params, result);
switch (rc) {
- case TrexRpcCommand::RPC_CMD_OK:
+ case TREX_RPC_CMD_OK:
response["result"] = result["result"];
break;
- case TrexRpcCommand::RPC_CMD_PARAM_COUNT_ERR:
- case TrexRpcCommand::RPC_CMD_PARAM_PARSE_ERR:
+ case TREX_RPC_CMD_PARSE_ERR:
response["error"]["code"] = JSONRPC_V2_ERR_INVALID_PARAMS;
response["error"]["message"] = "Bad paramters for method";
response["error"]["specific_err"] = result["specific_err"];
break;
- case TrexRpcCommand::RPC_CMD_INTERNAL_ERR:
+ case TREX_RPC_CMD_EXECUTE_ERR:
+ response["error"]["code"] = JSONRPC_V2_ERR_EXECUTE_ERROR;
+ response["error"]["message"] = "Failed To Execute Method";
+ response["error"]["specific_err"] = result["specific_err"];
+ break;
+
+ case TREX_RPC_CMD_INTERNAL_ERR:
response["error"]["code"] = JSONRPC_V2_ERR_INTERNAL_ERROR;
response["error"]["message"] = "Internal Server Error";
response["error"]["specific_err"] = result["specific_err"];
@@ -192,3 +200,36 @@ 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);
+}
+
+void
+TrexJsonRpcV2Parser::generate_common_error(Json::Value &json, const std::string &specific_err) {
+ JsonRpcError err(Json::Value::null, JSONRPC_V2_ERR_INTERNAL_ERROR, specific_err, true);
+
+ err.execute(json);
+
+}
+
diff --git a/src/rpc-server/include/trex_rpc_jsonrpc_v2_parser.h b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.h
index 3367ad6a..0563f21d 100644
--- a/src/rpc-server/include/trex_rpc_jsonrpc_v2_parser.h
+++ b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.h
@@ -79,6 +79,23 @@ public:
*/
void parse(std::vector<TrexJsonRpcV2ParsedObject *> &commands);
+ /**
+ * will generate a valid JSON RPC v2 error message with
+ * generic error code and message
+ *
+ * @author imarom (16-Sep-15)
+ *
+ */
+ static void generate_common_error(Json::Value &json, const std::string &specific_err);
+
+ /**
+ * *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/src/trex_rpc_req_resp_server.cpp b/src/rpc-server/trex_rpc_req_resp_server.cpp
index 7484758d..3d52686c 100644
--- a/src/rpc-server/src/trex_rpc_req_resp_server.cpp
+++ b/src/rpc-server/trex_rpc_req_resp_server.cpp
@@ -82,10 +82,17 @@ void TrexRpcServerReqRes::_rpc_thread_cb() {
}
}
+ if (msg_size >= sizeof(m_msg_buffer)) {
+ std::stringstream ss;
+ ss << "RPC request of '" << msg_size << "' exceeds maximum message size which is '" << sizeof(m_msg_buffer) << "'";
+ handle_server_error(ss.str());
+ continue;
+ }
+
/* 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 +117,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,8 +147,28 @@ 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);
}
+
+/**
+ * handles a server error
+ *
+ */
+void
+TrexRpcServerReqRes::handle_server_error(const std::string &specific_err) {
+ Json::FastWriter writer;
+ Json::Value response;
+
+ /* generate error */
+ TrexJsonRpcV2Parser::generate_common_error(response, specific_err);
+
+ /* write the JSON to string and sever on ZMQ */
+ std::string response_str = writer.write(response);
+
+ verbose_json("Server Replied: ", response_str);
+
+ zmq_send(m_socket, response_str.c_str(), response_str.size(), 0);
+}
diff --git a/src/rpc-server/include/trex_rpc_req_resp_server.h b/src/rpc-server/trex_rpc_req_resp_server.h
index f12d0540..7c1d66d1 100644
--- a/src/rpc-server/include/trex_rpc_req_resp_server.h
+++ b/src/rpc-server/trex_rpc_req_resp_server.h
@@ -39,9 +39,11 @@ protected:
void _stop_rpc_thread();
private:
+
void handle_request(const std::string &request);
+ void handle_server_error(const std::string &specific_err);
- static const int RPC_MAX_MSG_SIZE = 2048;
+ static const int RPC_MAX_MSG_SIZE = (20 * 1024);
void *m_context;
void *m_socket;
uint8_t m_msg_buffer[RPC_MAX_MSG_SIZE];
diff --git a/src/rpc-server/src/trex_rpc_server.cpp b/src/rpc-server/trex_rpc_server.cpp
index 366bfc5b..6b8c200d 100644
--- a/src/rpc-server/src/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
*
diff --git a/src/rpc-server/include/trex_rpc_server_api.h b/src/rpc-server/trex_rpc_server_api.h
index 6bb81c73..06bbe10c 100644
--- a/src/rpc-server/include/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,18 @@ public:
return s_server_uptime;
}
+
+
+
private:
+ static std::string generate_handler();
+
std::vector<TrexRpcServerInterface *> m_servers;
bool m_verbose;
static const std::string s_server_uptime;
+
+ static std::string s_owner;
+ static std::string s_owner_handler;
};
#endif /* __TREX_RPC_SERVER_API_H__ */
diff --git a/src/rpc-server/src/trex_rpc_server_mock.cpp b/src/rpc-server/trex_rpc_server_mock.cpp
index fd4f051c..835e28b8 100644
--- a/src/rpc-server/src/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,9 +44,12 @@ 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") || (argc != 2) ) {
+ if (string(argv[1]) != "--ut") {
cout << "\n[Usage] " << argv[0] << ": " << " [--ut]\n\n";
exit(-1);
}