summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2015-09-16 16:22:48 +0300
committerimarom <imarom@cisco.com>2015-09-16 16:22:48 +0300
commitdd99c3890d3bb7b4aab833927e85648cd6e86c85 (patch)
tree35712a3a46eab3cde24fbe06ca6426ed351e0e41
parent54f8323b3938bf4ab672cde01a06711bfc522a2e (diff)
added many tests to the RPC server
also, few tweaks for handling RPC server errors
-rw-r--r--scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py2
-rw-r--r--src/gtest/rpc_test.cpp355
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_general.cpp161
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_stream.cpp40
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_test.cpp30
-rw-r--r--src/rpc-server/commands/trex_rpc_cmds.h21
-rw-r--r--src/rpc-server/trex_rpc_cmds_table.cpp5
-rw-r--r--src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp8
-rw-r--r--src/rpc-server/trex_rpc_jsonrpc_v2_parser.h9
-rw-r--r--src/rpc-server/trex_rpc_req_resp_server.cpp27
-rw-r--r--src/rpc-server/trex_rpc_req_resp_server.h4
-rw-r--r--src/stateless/trex_stateless.cpp30
-rw-r--r--src/stateless/trex_stateless_api.h51
-rw-r--r--src/stateless/trex_stream.cpp11
-rw-r--r--src/stateless/trex_stream_api.h12
15 files changed, 565 insertions, 201 deletions
diff --git a/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py b/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py
index b44b1268..aff6b36e 100644
--- a/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py
+++ b/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py
@@ -145,7 +145,7 @@ class JsonRpcClient(object):
return self.invoke_rpc_method("get_status")
def query_rpc_server(self):
- return self.invoke_rpc_method("get_reg_cmds")
+ return self.invoke_rpc_method("get_supported_cmds")
def set_verbose(self, mode):
diff --git a/src/gtest/rpc_test.cpp b/src/gtest/rpc_test.cpp
index 767560b0..02d88eae 100644
--- a/src/gtest/rpc_test.cpp
+++ b/src/gtest/rpc_test.cpp
@@ -30,33 +30,16 @@ using namespace std;
class RpcTest : public testing::Test {
- void take_ownership(void) {
- Json::Value request;
- Json::Value response;
-
- create_request(request, "aquire", 1 , false);
-
- request["params"]["user"] = "test";
- request["params"]["force"] = true;
-
- send_request(request, response);
-
- EXPECT_TRUE(response["result"] != Json::nullValue);
- m_ownership_handler = response["result"].asString();
- }
-
- void release_ownership() {
- Json::Value request;
- Json::Value response;
+protected:
- create_request(request, "release", 1 , false);
- request["params"]["handler"] = m_ownership_handler;
-
- send_request(request, response);
- EXPECT_TRUE(response["result"] == "ACK");
+ void set_verbose(bool verbose) {
+ m_verbose = verbose;
}
-
+
virtual void SetUp() {
+
+ m_verbose = false;
+
TrexRpcServerConfig cfg = TrexRpcServerConfig(TrexRpcServerConfig::RPC_PROT_TCP, 5050);
m_rpc = new TrexRpcServer(cfg);
@@ -66,7 +49,6 @@ class RpcTest : public testing::Test {
m_socket = zmq_socket (m_context, ZMQ_REQ);
zmq_connect (m_socket, "tcp://localhost:5050");
- take_ownership();
}
virtual void TearDown() {
@@ -79,16 +61,13 @@ class RpcTest : public testing::Test {
public:
- void create_request(Json::Value &request, const string &method, int id = 1, bool ownership = false) {
+ void create_request(Json::Value &request, const string &method, int id = 1) {
request.clear();
request["jsonrpc"] = "2.0";
request["id"] = id;
request["method"] = method;
- if (ownership) {
- request["params"]["handler"] = m_ownership_handler;
- }
}
void send_request(const Json::Value &request, Json::Value &response) {
@@ -98,15 +77,24 @@ public:
response.clear();
string request_str = writer.write(request);
+
+ if (m_verbose) {
+ cout << "\n" << request_str << "\n";
+ }
+
string ret = send_msg(request_str);
+ if (m_verbose) {
+ cout << "\n" << ret << "\n";
+ }
+
EXPECT_TRUE(reader.parse(ret, response, false));
EXPECT_EQ(response["jsonrpc"], "2.0");
EXPECT_EQ(response["id"], request["id"]);
}
string send_msg(const string &msg) {
- char buffer[512];
+ char buffer[1024 * 20];
zmq_send (m_socket, msg.c_str(), msg.size(), 0);
int len = zmq_recv(m_socket, buffer, sizeof(buffer), 0);
@@ -117,10 +105,55 @@ public:
TrexRpcServer *m_rpc;
void *m_context;
void *m_socket;
+ bool m_verbose;
+};
+
+class RpcTestOwned : public RpcTest {
+public:
+
+ void create_request(Json::Value &request, const string &method, int id = 1) {
+ RpcTest::create_request(request, method, id);
+ request["params"]["handler"] = m_ownership_handler;
+ }
+
+protected:
+
+ virtual void SetUp() {
+ RpcTest::SetUp();
+ take_ownership();
+ }
+
+
+ void take_ownership(void) {
+ Json::Value request;
+ Json::Value response;
+
+ RpcTest::create_request(request, "acquire", 1);
+
+ request["params"]["user"] = "test";
+ request["params"]["force"] = true;
+
+ send_request(request, response);
+
+ EXPECT_TRUE(response["result"] != Json::nullValue);
+ m_ownership_handler = response["result"].asString();
+ }
+
+ void release_ownership() {
+ Json::Value request;
+ Json::Value response;
+
+ RpcTest::create_request(request, "release", 1);
+ request["params"]["handler"] = m_ownership_handler;
+
+ send_request(request, response);
+ EXPECT_TRUE(response["result"] == "ACK");
+ }
+
string m_ownership_handler;
};
-TEST_F(RpcTest, basic_rpc_test) {
+TEST_F(RpcTest, basic_rpc_negative_cases) {
Json::Value request;
Json::Value response;
Json::Reader reader;
@@ -179,53 +212,38 @@ TEST_F(RpcTest, test_add_command) {
Json::Value response;
Json::Reader reader;
- string req_str;
- string resp_str;
-
- /* simple add - missing paramters */
- req_str = "{\"jsonrpc\": \"2.0\", \"method\": \"test_add\", \"id\": 488}";
- resp_str = send_msg(req_str);
+ /* missing parameters */
+ create_request(request, "test_add");
+ send_request(request, response);
- EXPECT_TRUE(reader.parse(resp_str, response, false));
EXPECT_EQ(response["jsonrpc"], "2.0");
- EXPECT_EQ(response["id"], 488);
EXPECT_EQ(response["error"]["code"], -32602);
- /* simple add that works */
- req_str = "{\"jsonrpc\": \"2.0\", \"method\": \"test_add\", \"params\": {\"x\": 17, \"y\": -13} , \"id\": \"itay\"}";
- resp_str = send_msg(req_str);
-
- EXPECT_TRUE(reader.parse(resp_str, response, false));
- EXPECT_EQ(response["jsonrpc"], "2.0");
- EXPECT_EQ(response["id"], "itay");
- EXPECT_EQ(response["result"], 4);
-
- /* add with bad paratemers types */
- req_str = "{\"jsonrpc\": \"2.0\", \"method\": \"test_add\", \"params\": {\"x\": \"blah\", \"y\": -13} , \"id\": 17}";
- resp_str = send_msg(req_str);
+ /* bad paramters */
+ create_request(request, "test_add");
+ request["params"]["x"] = 5;
+ request["params"]["y"] = "itay";
+ send_request(request, response);
- EXPECT_TRUE(reader.parse(resp_str, response, false));
EXPECT_EQ(response["jsonrpc"], "2.0");
- EXPECT_EQ(response["id"], 17);
EXPECT_EQ(response["error"]["code"], -32602);
- /* add with invalid count of parameters */
- req_str = "{\"jsonrpc\": \"2.0\", \"method\": \"test_add\", \"params\": {\"y\": -13} , \"id\": 17}";
- resp_str = send_msg(req_str);
+ /* simple add that works */
+ create_request(request, "test_add");
+ request["params"]["x"] = 5;
+ request["params"]["y"] = -13;
+ send_request(request, response);
- EXPECT_TRUE(reader.parse(resp_str, response, false));
EXPECT_EQ(response["jsonrpc"], "2.0");
- EXPECT_EQ(response["id"], 17);
- EXPECT_EQ(response["error"]["code"], -32602);
-
+ EXPECT_EQ(response["result"], -8);
/* big numbers */
- req_str = "{\"jsonrpc\": \"2.0\", \"method\": \"test_add\", \"params\": {\"x\": 4827371, \"y\": -39181273} , \"id\": \"itay\"}";
- resp_str = send_msg(req_str);
+ create_request(request, "test_add");
+ request["params"]["x"] = 4827371;
+ request["params"]["y"] = -39181273;
+ send_request(request, response);
- EXPECT_TRUE(reader.parse(resp_str, response, false));
EXPECT_EQ(response["jsonrpc"], "2.0");
- EXPECT_EQ(response["id"], "itay");
EXPECT_EQ(response["result"], -34353902);
}
@@ -281,12 +299,174 @@ TEST_F(RpcTest, batch_rpc_test) {
return;
}
-TEST_F(RpcTest, add_stream) {
+/* ping command */
+TEST_F(RpcTest, ping) {
+ Json::Value request;
+ Json::Value response;
+ Json::Reader reader;
+
+ create_request(request, "ping");
+ send_request(request, response);
+ EXPECT_TRUE(response["result"] == "ACK");
+}
+
+static bool
+find_member_in_array(const Json::Value &array, const string &member) {
+ for (auto x : array) {
+ if (x == member) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* get registered commands */
+TEST_F(RpcTest, get_supported_cmds) {
+ Json::Value request;
+ Json::Value response;
+ Json::Reader reader;
+
+ create_request(request, "get_supported_cmds");
+ send_request(request, response);
+ EXPECT_TRUE(response["result"].size() > 0);
+
+ EXPECT_TRUE(find_member_in_array(response["result"], "ping"));
+ EXPECT_TRUE(find_member_in_array(response["result"], "get_supported_cmds"));
+}
+
+/* get version */
+TEST_F(RpcTest, get_version) {
Json::Value request;
Json::Value response;
Json::Reader reader;
- create_request(request, "get_stream", 1, true);
+ create_request(request, "get_version");
+ send_request(request, response);
+
+ EXPECT_TRUE(response["result"] != Json::nullValue);
+ EXPECT_TRUE(response["result"]["built_by"] == "MOCK");
+ EXPECT_TRUE(response["result"]["version"] == "v0.0");
+}
+
+/* get system info */
+TEST_F(RpcTest, get_system_info) {
+ Json::Value request;
+ Json::Value response;
+ Json::Reader reader;
+
+ create_request(request, "get_system_info");
+ send_request(request, response);
+
+ EXPECT_TRUE(response["result"] != Json::nullValue);
+ EXPECT_TRUE(response["result"]["core_type"].isString());
+ EXPECT_TRUE(response["result"]["hostname"].isString());
+ EXPECT_TRUE(response["result"]["uptime"].isString());
+ EXPECT_TRUE(response["result"]["dp_core_count"] > 0);
+ EXPECT_TRUE(response["result"]["port_count"] > 0);
+
+ EXPECT_TRUE(response["result"]["ports"].isArray());
+
+ const Json::Value &ports = response["result"]["ports"];
+
+
+ for (int i = 0; i < ports.size(); i++) {
+ EXPECT_TRUE(ports[i]["index"] == i);
+ EXPECT_TRUE(ports[i]["driver"].isString());
+ EXPECT_TRUE(ports[i]["speed"].isString());
+ }
+}
+
+/* get owner, acquire and release */
+TEST_F(RpcTest, get_owner_acquire_release) {
+ Json::Value request;
+ Json::Value response;
+ Json::Reader reader;
+
+ /* no user before acquring */
+ create_request(request, "get_owner");
+ send_request(request, response);
+ EXPECT_TRUE(response["result"] != Json::nullValue);
+
+ EXPECT_TRUE(response["result"]["owner"] == "none");
+
+ /* soft acquire */
+ create_request(request, "acquire");
+ request["params"]["user"] = "itay";
+ request["params"]["force"] = false;
+
+ send_request(request, response);
+ EXPECT_TRUE(response["result"] != Json::nullValue);
+
+ create_request(request, "get_owner");
+ send_request(request, response);
+ EXPECT_TRUE(response["result"] != Json::nullValue);
+
+ EXPECT_TRUE(response["result"]["owner"] == "itay");
+
+ /* hard acquire */
+ create_request(request, "acquire");
+ request["params"]["user"] = "moshe";
+ request["params"]["force"] = false;
+
+ send_request(request, response);
+ EXPECT_TRUE(response["result"] == Json::nullValue);
+
+ request["params"]["force"] = true;
+
+ send_request(request, response);
+ EXPECT_TRUE(response["result"] != Json::nullValue);
+
+ string handler = response["result"].asString();
+
+ /* make sure */
+ create_request(request, "get_owner");
+ send_request(request, response);
+ EXPECT_TRUE(response["result"] != Json::nullValue);
+
+ EXPECT_TRUE(response["result"]["owner"] == "moshe");
+
+ /* release */
+ create_request(request, "release");
+ request["params"]["handler"] = handler;
+ send_request(request, response);
+
+ EXPECT_TRUE(response["result"] == "ACK");
+}
+
+
+static void
+create_simple_stream(Json::Value &obj) {
+ obj["mode"]["type"] = "continuous";
+ obj["mode"]["pps"] = (rand() % 1000 + 1) * 0.99;
+ obj["isg"] = (rand() % 100 + 1) * 0.99;;
+ obj["enabled"] = true;
+ obj["self_start"] = true;
+ obj["next_stream_id"] = -1;
+
+ obj["packet"]["meta"] = "dummy";
+
+ int packet_size = (rand() % 1500 + 1);
+ for (int i = 0; i < packet_size; i++) {
+ obj["packet"]["binary"][i] = (rand() % 0xff);
+ }
+
+ obj["vm"] = Json::arrayValue;
+ obj["rx_stats"]["enabled"] = false;
+}
+
+static bool
+compare_streams(const Json::Value &s1, const Json::Value &s2) {
+ return s1 == s2;
+}
+
+TEST_F(RpcTestOwned, add_remove_stream) {
+ Json::Value request;
+ Json::Value response;
+ Json::Reader reader;
+
+ /* verify no such stream */
+ create_request(request, "get_stream", 1);
request["params"]["port_id"] = 1;
request["params"]["stream_id"] = 5;
@@ -297,58 +477,31 @@ TEST_F(RpcTest, add_stream) {
EXPECT_EQ(response["id"], 1);
EXPECT_EQ(response["error"]["code"], -32000);
- // add it
- create_request(request, "add_stream", 1, true);
+ /* add it */
+ create_request(request, "add_stream", 1);
request["params"]["port_id"] = 1;
request["params"]["stream_id"] = 5;
- request["params"]["stream"]["mode"]["type"] = "continuous";
- request["params"]["stream"]["mode"]["pps"] = 3;
- request["params"]["stream"]["isg"] = 4.3;
- request["params"]["stream"]["enabled"] = true;
- request["params"]["stream"]["self_start"] = true;
- request["params"]["stream"]["next_stream_id"] = -1;
- request["params"]["stream"]["packet"]["meta"] = "dummy";
- request["params"]["stream"]["packet"]["binary"][0] = 4;
- request["params"]["stream"]["packet"]["binary"][1] = 1;
- request["params"]["stream"]["packet"]["binary"][2] = 255;
-
- request["params"]["stream"]["vm"] = Json::arrayValue;
- request["params"]["stream"]["rx_stats"]["enabled"] = false;
+ Json::Value stream;
+ create_simple_stream(stream);
+ request["params"]["stream"] = stream;
send_request(request, response);
EXPECT_EQ(response["result"], "ACK");
/* get it */
-
- create_request(request, "get_stream", 1, true);
+ create_request(request, "get_stream", 1);
request["params"]["port_id"] = 1;
request["params"]["stream_id"] = 5;
send_request(request, response);
- const Json::Value &stream = response["result"]["stream"];
-
- EXPECT_EQ(stream["enabled"], true);
- EXPECT_EQ(stream["self_start"], true);
-
- EXPECT_EQ(stream["packet"]["binary"][0], 4);
- EXPECT_EQ(stream["packet"]["binary"][1], 1);
- EXPECT_EQ(stream["packet"]["binary"][2], 255);
-
- EXPECT_EQ(stream["packet"]["meta"], "dummy");
- EXPECT_EQ(stream["next_stream_id"], -1);
-
- double delta = stream["isg"].asDouble() - 4.3;
- EXPECT_TRUE(delta < 0.0001);
-
- EXPECT_EQ(stream["mode"]["type"], "continuous");
- EXPECT_EQ(stream["mode"]["pps"], 3);
+ EXPECT_TRUE(compare_streams(stream, response["result"]["stream"]));
// remove it
- create_request(request, "remove_stream", 1, true);
+ create_request(request, "remove_stream", 1);
request["params"]["port_id"] = 1;
request["params"]["stream_id"] = 5;
diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
index d5aa3a90..afa15973 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
@@ -18,9 +18,17 @@ 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>
+
+//#include <netdb.h>
#ifndef TREX_RPC_MOCK_SERVER
#include <../linux_dpdk/version.h>
@@ -29,36 +37,161 @@ limitations under the License.
using namespace std;
/**
- * get status
+ * 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
-TrexRpcCmdGetStatus::_run(const Json::Value &params, Json::Value &result) {
+TrexRpcCmdGetVersion::_run(const Json::Value &params, Json::Value &result) {
Json::Value &section = result["result"];
#ifndef TREX_RPC_MOCK_SERVER
- section["general"]["version"] = VERSION_BUILD_NUM;
- section["general"]["build_date"] = get_build_date();
- section["general"]["build_time"] = get_build_time();
- section["general"]["built_by"] = VERSION_USER;
+ section["version"] = VERSION_BUILD_NUM;
+ section["build_date"] = get_build_date();
+ section["build_time"] = get_build_time();
+ section["built_by"] = VERSION_USER;
#else
- section["general"]["version"] = "v0.0";
- section["general"]["build_date"] = __DATE__;
- section["general"]["build_time"] = __TIME__;
- section["general"]["version_user"] = "MOCK";
+ section["version"] = "v0.0";
+ section["build_date"] = __DATE__;
+ section["build_time"] = __TIME__;
+ section["built_by"] = "MOCK";
#endif
- section["general"]["uptime"] = TrexRpcServer::get_server_uptime();
- section["general"]["owner"] = TrexRpcServer::get_owner();
+ 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;
+ }
- // ports
+ /* trim it */
+ int index = cpu_prefix.size() + 1;
+ while ( (line[index] == ' ') || (line[index] == ':') ) {
+ index++;
+ }
- section["ports"]["count"] = TrexStateless::get_instance().get_port_count();
+ 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;
+
+ 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);
}
diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
index b62d213b..41567509 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp
@@ -63,6 +63,9 @@ TrexRpcCmdAddStream::_run(const Json::Value &params, Json::Value &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);
@@ -130,7 +133,7 @@ TrexRpcCmdAddStream::allocate_new_stream(const Json::Value &section, uint8_t por
if (type == "continuous") {
- uint32_t pps = parse_int(mode, "pps", result);
+ double pps = parse_double(mode, "pps", result);
stream = new TrexStreamContinuous(port_id, stream_id, pps);
} else if (type == "single_burst") {
@@ -413,30 +416,11 @@ TrexRpcCmdGetStream::_run(const Json::Value &params, Json::Value &result) {
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 the stored stream json (instead of decoding it all over again) */
+ result["result"]["stream"] = stream->get_stream_json();
return (TREX_RPC_CMD_OK);
+
}
/***************************
@@ -455,17 +439,17 @@ TrexRpcCmdStartTraffic::_run(const Json::Value &params, Json::Value &result) {
TrexStatelessPort *port = TrexStateless::get_instance().get_port_by_id(port_id);
- TrexStatelessPort::traffic_rc_e rc = port->start_traffic();
+ TrexStatelessPort::rc_e rc = port->start_traffic();
- if (rc == TrexStatelessPort::TRAFFIC_OK) {
+ if (rc == TrexStatelessPort::RC_OK) {
result["result"] = "ACK";
} else {
std::stringstream ss;
switch (rc) {
- case TrexStatelessPort::TRAFFIC_ERR_ALREADY_STARTED:
- ss << "traffic has already started on that port";
+ case TrexStatelessPort::RC_ERR_BAD_STATE_FOR_OP:
+ ss << "bad state for operations: port is either transmitting traffic or down";
break;
- case TrexStatelessPort::TRAFFIC_ERR_NO_STREAMS:
+ case TrexStatelessPort::RC_ERR_NO_STREAMS:
ss << "no active streams on that port";
break;
default:
diff --git a/src/rpc-server/commands/trex_rpc_cmd_test.cpp b/src/rpc-server/commands/trex_rpc_cmd_test.cpp
index 3153317e..3cdddd31 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_test.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_test.cpp
@@ -21,7 +21,6 @@ limitations under the License.
#include "trex_rpc_cmds.h"
#include <iostream>
#include <sstream>
-#include <trex_rpc_cmds_table.h>
using namespace std;
@@ -50,32 +49,3 @@ TrexRpcCmdTestSub::_run(const Json::Value &params, Json::Value &result) {
return (TREX_RPC_CMD_OK);
}
-/**
- * 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
-TrexRpcCmdGetReg::_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);
-}
-
diff --git a/src/rpc-server/commands/trex_rpc_cmds.h b/src/rpc-server/commands/trex_rpc_cmds.h
index 32138195..643aa22d 100644
--- a/src/rpc-server/commands/trex_rpc_cmds.h
+++ b/src/rpc-server/commands/trex_rpc_cmds.h
@@ -35,7 +35,7 @@ class TrexStream;
* syntactic sugar for creating a simple command
*/
-#define TREX_RPC_CMD_DEFINE_EXTENED(class_name, cmd_name, param_count, needs_ownership, ext) \
+#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) {} \
@@ -44,7 +44,7 @@ class TrexStream;
ext \
}
-#define TREX_RPC_CMD_DEFINE(class_name, cmd_name, param_count, needs_ownership) TREX_RPC_CMD_DEFINE_EXTENED(class_name, cmd_name, param_count, needs_ownership, ;)
+#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
@@ -55,9 +55,16 @@ TREX_RPC_CMD_DEFINE(TrexRpcCmdTestSub, "test_sub", 2, false);
/**
* general cmds
*/
-TREX_RPC_CMD_DEFINE(TrexRpcCmdPing, "ping", 0, false);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdGetReg, "get_reg_cmds", 0, false);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdGetStatus, "get_status", 0, false);
+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
@@ -73,7 +80,7 @@ TREX_RPC_CMD_DEFINE(TrexRpcCmdRelease, "release", 0, true);
TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveAllStreams, "remove_all_streams", 1, true);
TREX_RPC_CMD_DEFINE(TrexRpcCmdRemoveStream, "remove_stream", 2, true);
-TREX_RPC_CMD_DEFINE_EXTENED(TrexRpcCmdAddStream, "add_stream", 3, 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);
@@ -92,4 +99,6 @@ 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/trex_rpc_cmds_table.cpp b/src/rpc-server/trex_rpc_cmds_table.cpp
index f968bb74..170f0de1 100644
--- a/src/rpc-server/trex_rpc_cmds_table.cpp
+++ b/src/rpc-server/trex_rpc_cmds_table.cpp
@@ -34,8 +34,9 @@ TrexRpcCommandsTable::TrexRpcCommandsTable() {
/* 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());
diff --git a/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp
index 928baca6..9d9de53a 100644
--- a/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp
+++ b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.cpp
@@ -225,3 +225,11 @@ std::string TrexJsonRpcV2Parser::pretty_json_str(const std::string &json_str) {
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/trex_rpc_jsonrpc_v2_parser.h b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.h
index ebffaeb7..0563f21d 100644
--- a/src/rpc-server/trex_rpc_jsonrpc_v2_parser.h
+++ b/src/rpc-server/trex_rpc_jsonrpc_v2_parser.h
@@ -80,6 +80,15 @@ 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
diff --git a/src/rpc-server/trex_rpc_req_resp_server.cpp b/src/rpc-server/trex_rpc_req_resp_server.cpp
index c4d9dfdb..3d52686c 100644
--- a/src/rpc-server/trex_rpc_req_resp_server.cpp
+++ b/src/rpc-server/trex_rpc_req_resp_server.cpp
@@ -82,6 +82,13 @@ 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);
@@ -145,3 +152,23 @@ void TrexRpcServerReqRes::handle_request(const std::string &request) {
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/trex_rpc_req_resp_server.h b/src/rpc-server/trex_rpc_req_resp_server.h
index f12d0540..7c1d66d1 100644
--- a/src/rpc-server/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/stateless/trex_stateless.cpp b/src/stateless/trex_stateless.cpp
index 2ab0c5d9..b51c4e69 100644
--- a/src/stateless/trex_stateless.cpp
+++ b/src/stateless/trex_stateless.cpp
@@ -20,6 +20,8 @@ limitations under the License.
*/
#include <trex_stateless_api.h>
+using namespace std;
+
/***********************************************************
* Trex stateless object
*
@@ -76,7 +78,7 @@ uint8_t TrexStateless::get_port_count() {
*
**************************/
TrexStatelessPort::TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) {
- m_started = false;
+ m_port_state = PORT_STATE_DOWN;
}
@@ -84,25 +86,29 @@ TrexStatelessPort::TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) {
* starts the traffic on the port
*
*/
-TrexStatelessPort::traffic_rc_e
+TrexStatelessPort::rc_e
TrexStatelessPort::start_traffic(void) {
- if (m_started) {
- return (TRAFFIC_ERR_ALREADY_STARTED);
+
+ if (m_port_state != PORT_STATE_UP_IDLE) {
+ return (RC_ERR_BAD_STATE_FOR_OP);
}
if (get_stream_table()->size() == 0) {
- return (TRAFFIC_ERR_NO_STREAMS);
+ return (RC_ERR_NO_STREAMS);
}
- m_started = true;
+ m_port_state = PORT_STATE_TRANSMITTING;
- return (TRAFFIC_OK);
+ /* real code goes here */
+ return (RC_OK);
}
void
TrexStatelessPort::stop_traffic(void) {
- if (m_started) {
- m_started = false;
+
+ /* real code goes here */
+ if (m_port_state = PORT_STATE_TRANSMITTING) {
+ m_port_state = PORT_STATE_UP_IDLE;
}
}
@@ -114,4 +120,10 @@ TrexStreamTable * TrexStatelessPort::get_stream_table() {
return &m_stream_table;
}
+void
+TrexStatelessPort::get_properties(string &driver, string &speed) {
+ /* take this from DPDK */
+ driver = "Unknown Driver";
+ speed = "Unknown Speed";
+}
diff --git a/src/stateless/trex_stateless_api.h b/src/stateless/trex_stateless_api.h
index 358ab339..60d26878 100644
--- a/src/stateless/trex_stateless_api.h
+++ b/src/stateless/trex_stateless_api.h
@@ -50,19 +50,36 @@ class TrexStatelessPort {
public:
/**
- * describess error codes for starting traffic
+ * port state
*/
- enum traffic_rc_e {
- TRAFFIC_OK,
- TRAFFIC_ERR_ALREADY_STARTED,
- TRAFFIC_ERR_NO_STREAMS,
- TRAFFIC_ERR_FAILED_TO_COMPILE_STREAMS
+ enum port_state_e {
+ PORT_STATE_DOWN,
+ PORT_STATE_UP_IDLE,
+ PORT_STATE_TRANSMITTING
+ };
+
+ /**
+ * describess different error codes for port operations
+ */
+ enum rc_e {
+ RC_OK,
+ RC_ERR_BAD_STATE_FOR_OP,
+ RC_ERR_NO_STREAMS,
+ RC_ERR_FAILED_TO_COMPILE_STREAMS
};
TrexStatelessPort(uint8_t port_id);
- traffic_rc_e start_traffic(void);
+ /**
+ * start traffic
+ *
+ */
+ rc_e start_traffic(void);
+ /**
+ * stop traffic
+ *
+ */
void stop_traffic(void);
/**
@@ -71,10 +88,28 @@ public:
*/
TrexStreamTable *get_stream_table();
+ /**
+ * get the port state
+ *
+ */
+ port_state_e get_state() {
+ return m_port_state;
+ }
+
+ /**
+ * fill up properties of the port
+ *
+ * @author imarom (16-Sep-15)
+ *
+ * @param driver
+ * @param speed
+ */
+ void get_properties(std::string &driver, std::string &speed);
+
private:
TrexStreamTable m_stream_table;
uint8_t m_port_id;
- bool m_started;
+ port_state_e m_port_state;
};
/**
diff --git a/src/stateless/trex_stream.cpp b/src/stateless/trex_stream.cpp
index 2b5b2424..8bf04748 100644
--- a/src/stateless/trex_stream.cpp
+++ b/src/stateless/trex_stream.cpp
@@ -45,6 +45,17 @@ TrexStream::~TrexStream() {
}
}
+void
+TrexStream::store_stream_json(const Json::Value &stream_json) {
+ /* deep copy */
+ m_stream_json = stream_json;
+}
+
+const Json::Value &
+TrexStream::get_stream_json() {
+ return m_stream_json;
+}
+
/**************************************
* stream table
*************************************/
diff --git a/src/stateless/trex_stream_api.h b/src/stateless/trex_stream_api.h
index 0a955ff7..d3c0fb29 100644
--- a/src/stateless/trex_stream_api.h
+++ b/src/stateless/trex_stream_api.h
@@ -26,6 +26,8 @@ limitations under the License.
#include <stdint.h>
#include <string>
+#include <json/json.h>
+
#include <trex_stream_vm.h>
class TrexRpcCmdAddStream;
@@ -48,7 +50,13 @@ public:
static const uint32_t MIN_PKT_SIZE_BYTES = 1;
static const uint32_t MAX_PKT_SIZE_BYTES = 9000;
-private:
+ /* provides storage for the stream json*/
+ void store_stream_json(const Json::Value &stream_json);
+
+ /* access the stream json */
+ const Json::Value & get_stream_json();
+
+protected:
/* basic */
uint8_t m_port_id;
uint32_t m_stream_id;
@@ -82,6 +90,8 @@ private:
} m_rx_check;
+ /* original template provided by requester */
+ Json::Value m_stream_json;
};
/**