From 1f90e4ed08414c8aa423693c4ee8fa84e7675230 Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 24 Sep 2015 17:51:04 +0300 Subject: some improvements to the console --- .../trex_control_plane/console/trex_console.py | 112 ++++++++++++++++++++- 1 file changed, 108 insertions(+), 4 deletions(-) (limited to 'scripts/automation/trex_control_plane/console') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 3aeab901..9bf92174 100644 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -8,11 +8,96 @@ import random import string import sys +import tty, termios import trex_root_path + from client_utils.jsonrpc_client import TrexStatelessClient import trex_status +# + +def readch (choices = []): + + fd = sys.stdin.fileno() + old_settings = termios.tcgetattr(fd) + try: + tty.setraw(sys.stdin.fileno()) + while True: + ch = sys.stdin.read(1) + if (ord(ch) == 3) or (ord(ch) == 4): + return None + if ch in choices: + return ch + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + + return None + +class YesNoMenu(object): + def __init__ (self, caption): + self.caption = caption + + def show (self): + print "{0}".format(self.caption) + sys.stdout.write("[Y/y/N/n] : ") + ch = readch(choices = ['y', 'Y', 'n', 'N']) + if ch == None: + return None + + print "\n" + if ch == 'y' or ch == 'Y': + return True + else: + return False + +# multi level cmd menu +class CmdMenu(object): + def __init__ (self): + self.menus = [] + + + def add_menu (self, caption, options): + menu = {} + menu['caption'] = caption + menu['options'] = options + self.menus.append(menu) + + def show (self): + cur_level = 0 + print "\n" + + selected_path = [] + for menu in self.menus: + # show all the options + print "{0}\n".format(menu['caption']) + for i, option in enumerate(menu['options']): + print "{0}. {1}".format(i + 1, option) + + #print "\nPlease select an option: " + + choices = range(0, len(menu['options'])) + choices = [ chr(x + 48) for x in choices] + + print "" + ch = readch(choices) + print "" + + if ch == None: + return None + + selected_path.append(int(ch) - 1) + + return selected_path + + +class AddStreamMenu(CmdMenu): + def __init__ (self): + super(AddStreamMenu, self).__init__() + self.add_menu('Please select type of stream', ['a', 'b', 'c']) + self.add_menu('Please select ISG', ['d', 'e', 'f']) + +# main console object class TrexConsole(cmd.Cmd): """Trex Console""" @@ -108,6 +193,13 @@ class TrexConsole(cmd.Cmd): def do_acquire (self, line, force = False): '''Acquire ports\n''' + # make sure that the user wants to acquire all + if line == "": + ask = YesNoMenu('Do you want to acquire all ports ? ') + rc = ask.show() + if rc == False: + return + port_list = self.parse_ports_from_line(line) if not port_list: return @@ -313,12 +405,24 @@ class TrexConsole(cmd.Cmd): print "{:<30} {:<30}".format(cmd + " - ", help) - # do - #def do_snapshot (self, line): - #for key, value in self.rpc_client.snapshot()[1]['streams'].iteritems(): - #print str(key) + " " + str(value) + # adds a very simple stream + def do_add_simple_stream (self, line): + if line == "": + add_stream = AddStreamMenu() + add_stream.show() + return + params = line.split() + port_id = int(params[0]) + stream_id = int(params[1]) + + packet = [0xFF,0xFF,0xFF] + rc, msg = self.rpc_client.add_stream(port_id = port_id, stream_id = stream_id, isg = 1.1, next_stream_id = -1, packet = packet) + if rc: + print "\nServer Response:\n\n" + self.rpc_client.pretty_json(json.dumps(msg)) + "\n" + else: + print "\n*** " + msg + "\n" # aliasing do_exit = do_EOF = do_q = do_quit -- cgit 1.2.3-korg From 4d53d6e2633caed782067965b1b4422b45dab4a2 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 7 Oct 2015 14:57:48 +0200 Subject: added async publisher to the RPC server --- linux/ws_main.py | 1 + .../trex_control_plane/console/trex_status.py | 2 +- src/gtest/rpc_test.cpp | 5 +- src/rpc-server/commands/trex_rpc_cmd_general.cpp | 13 +- src/rpc-server/commands/trex_rpc_cmd_stream.cpp | 1 + src/rpc-server/trex_rpc_async_server.cpp | 36 +++- src/rpc-server/trex_rpc_async_server.h | 1 + src/rpc-server/trex_rpc_cmd.cpp | 1 + src/rpc-server/trex_rpc_server.cpp | 6 +- src/rpc-server/trex_rpc_server_api.h | 6 +- src/rpc-server/trex_rpc_server_mock.cpp | 6 +- src/stateless/trex_stateless.cpp | 122 ++++--------- src/stateless/trex_stateless_api.h | 203 +++++---------------- src/stateless/trex_stateless_port.cpp | 172 +++++++++++++++++ src/stateless/trex_stateless_port.h | 196 ++++++++++++++++++++ 15 files changed, 504 insertions(+), 267 deletions(-) create mode 100644 src/stateless/trex_stateless_port.cpp create mode 100644 src/stateless/trex_stateless_port.h (limited to 'scripts/automation/trex_control_plane/console') diff --git a/linux/ws_main.py b/linux/ws_main.py index f1d064cb..193a0d18 100755 --- a/linux/ws_main.py +++ b/linux/ws_main.py @@ -145,6 +145,7 @@ stateless_src = SrcGroup(dir='src/stateless/', src_list=['trex_stream.cpp', 'trex_stream_vm.cpp', 'trex_stateless.cpp', + 'trex_stateless_port.cpp' ]) # RPC code rpc_server_src = SrcGroup(dir='src/rpc-server/', diff --git a/scripts/automation/trex_control_plane/console/trex_status.py b/scripts/automation/trex_control_plane/console/trex_status.py index b881f9f5..2c5a648f 100644 --- a/scripts/automation/trex_control_plane/console/trex_status.py +++ b/scripts/automation/trex_control_plane/console/trex_status.py @@ -170,7 +170,7 @@ class PortsStatsPanel(TrexStatusPanel): port_stats = self.status_obj.stats.get_port_stats(port_index) if port_stats: - self.getwin().addstr(5 + (i * 4), 2, "{:^15} {:^15,} {:^15,} {:^15,} {:^15,} {:^15,} {:^15,}".format( + self.getwin().addstr(5 + (i * 4), 2, "{:^15} {:^15,.2f} {:^15,.2f} {:^15,} {:^15,.2f} {:^15,.2f} {:^15,}".format( "{0} ({1})".format(str(port_index), self.status_obj.server_sys_info["ports"][port_index]["speed"]), port_stats["tx_pps"], port_stats["tx_bps"], diff --git a/src/gtest/rpc_test.cpp b/src/gtest/rpc_test.cpp index 38d34320..4084b664 100644 --- a/src/gtest/rpc_test.cpp +++ b/src/gtest/rpc_test.cpp @@ -42,9 +42,10 @@ protected: m_verbose = false; - TrexRpcServerConfig cfg = TrexRpcServerConfig(TrexRpcServerConfig::RPC_PROT_TCP, 5050); + TrexRpcServerConfig req_resp_cfg = TrexRpcServerConfig(TrexRpcServerConfig::RPC_PROT_TCP, 5050); + TrexRpcServerConfig async_cfg = TrexRpcServerConfig(TrexRpcServerConfig::RPC_PROT_TCP, 5051); - m_rpc = new TrexRpcServer(cfg); + m_rpc = new TrexRpcServer(req_resp_cfg, async_cfg); m_rpc->start(); m_context = zmq_ctx_new (); diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index 7721526c..3a0a12f8 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -22,6 +22,7 @@ limitations under the License. #include "trex_rpc_cmds.h" #include #include +#include #include #include @@ -271,17 +272,7 @@ TrexRpcCmdGetPortStats::_run(const Json::Value ¶ms, Json::Value &result) { result["result"]["status"] = port->get_state_as_string(); - result["result"]["tx_bps"] = Json::Value::UInt64(port->get_stats().m_stats.tx_bps); - result["result"]["tx_pps"] = Json::Value::UInt64(port->get_stats().m_stats.tx_pps); - result["result"]["total_tx_pkts"] = Json::Value::UInt64(port->get_stats().m_stats.total_tx_pkts); - result["result"]["total_tx_bytes"] = Json::Value::UInt64(port->get_stats().m_stats.total_tx_bytes); - - result["result"]["rx_bps"] = Json::Value::UInt64(port->get_stats().m_stats.rx_bps); - result["result"]["rx_pps"] = Json::Value::UInt64(port->get_stats().m_stats.rx_pps); - result["result"]["total_rx_pkts"] = Json::Value::UInt64(port->get_stats().m_stats.total_rx_pkts); - result["result"]["total_rx_bytes"] = Json::Value::UInt64(port->get_stats().m_stats.total_rx_bytes); - - result["result"]["tx_rx_error"] = Json::Value::UInt64(port->get_stats().m_stats.tx_rx_errors); + port->encode_stats(result["result"]); 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 1450e1a9..97c2b791 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp @@ -22,6 +22,7 @@ limitations under the License. #include #include #include +#include #include diff --git a/src/rpc-server/trex_rpc_async_server.cpp b/src/rpc-server/trex_rpc_async_server.cpp index 76549cbd..40d16dfe 100644 --- a/src/rpc-server/trex_rpc_async_server.cpp +++ b/src/rpc-server/trex_rpc_async_server.cpp @@ -18,10 +18,19 @@ 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. */ + +/* required for sleep_for c++ 2011 + https://bugs.launchpad.net/ubuntu/+source/gcc-4.4/+bug/608145 +*/ +#define _GLIBCXX_USE_NANOSLEEP + #include +#include #include #include #include +#include +#include /** * ZMQ based publisher server @@ -32,6 +41,10 @@ TrexRpcServerAsync::TrexRpcServerAsync(const TrexRpcServerConfig &cfg) : TrexRpc m_context = zmq_ctx_new(); } +/** + * publisher thread + * + */ void TrexRpcServerAsync::_rpc_thread_cb() { std::stringstream ss; @@ -57,21 +70,30 @@ TrexRpcServerAsync::_rpc_thread_cb() { /* while the server is running - publish results */ while (m_is_running) { - /* update all ports for their stats */ - uint8_t port_count = TrexStateless::get_instance().get_port_count(); - for (uint8_t i = 0; i < port_count; i++) { - TrexStateless::get_instance().get_port_by_id(i).update_stats(); - const TrexPortStats &stats = TrexStateless::get_instance().get_port_by_id(i).get_stats(); + Json::Value snapshot; + Json::FastWriter writer; + + /* trigger a full update for stats */ + TrexStateless::get_instance().update_stats(); + + /* encode them to JSON */ + TrexStateless::get_instance().encode_stats(snapshot); + + /* write to string and publish */ + std::string snapshot_str = writer.write(snapshot); + zmq_send(m_socket, snapshot_str.c_str(), snapshot_str.size(), 0); + //std::cout << "sending " << snapshot_str << "\n"; + /* relax for some time */ + std::this_thread::sleep_for (std::chrono::milliseconds(1000)); - } } } void TrexRpcServerAsync::_stop_rpc_thread() { m_is_running = false; - this->m_thread.join(); + this->m_thread->join(); zmq_term(m_context); } diff --git a/src/rpc-server/trex_rpc_async_server.h b/src/rpc-server/trex_rpc_async_server.h index d0a1ee90..13525c01 100644 --- a/src/rpc-server/trex_rpc_async_server.h +++ b/src/rpc-server/trex_rpc_async_server.h @@ -23,6 +23,7 @@ limitations under the License. #define __TREX_RPC_ASYNC_SERVER_H__ #include +#include /** * async RPC server diff --git a/src/rpc-server/trex_rpc_cmd.cpp b/src/rpc-server/trex_rpc_cmd.cpp index 6c355e70..f7cb5259 100644 --- a/src/rpc-server/trex_rpc_cmd.cpp +++ b/src/rpc-server/trex_rpc_cmd.cpp @@ -21,6 +21,7 @@ limitations under the License. #include #include #include +#include trex_rpc_cmd_rc_e TrexRpcCommand::run(const Json::Value ¶ms, Json::Value &result) { diff --git a/src/rpc-server/trex_rpc_server.cpp b/src/rpc-server/trex_rpc_server.cpp index 6b8c200d..18265a0e 100644 --- a/src/rpc-server/trex_rpc_server.cpp +++ b/src/rpc-server/trex_rpc_server.cpp @@ -21,6 +21,7 @@ limitations under the License. #include #include +#include #include #include #include @@ -112,10 +113,13 @@ get_current_date_time() { const std::string TrexRpcServer::s_server_uptime = get_current_date_time(); -TrexRpcServer::TrexRpcServer(const TrexRpcServerConfig &req_resp_cfg) { +TrexRpcServer::TrexRpcServer(const TrexRpcServerConfig &req_resp_cfg, + const TrexRpcServerConfig &async_cfg) { /* add the request response server */ m_servers.push_back(new TrexRpcServerReqRes(req_resp_cfg)); + /* add async publisher */ + m_servers.push_back(new TrexRpcServerAsync(async_cfg)); } TrexRpcServer::~TrexRpcServer() { diff --git a/src/rpc-server/trex_rpc_server_api.h b/src/rpc-server/trex_rpc_server_api.h index 06bbe10c..5a7cad48 100644 --- a/src/rpc-server/trex_rpc_server_api.h +++ b/src/rpc-server/trex_rpc_server_api.h @@ -139,8 +139,10 @@ protected: class TrexRpcServer { public: - /* currently only request response server config is required */ - TrexRpcServer(const TrexRpcServerConfig &req_resp_cfg); + /* creates the collection of servers using configurations */ + TrexRpcServer(const TrexRpcServerConfig &req_resp_cfg, + const TrexRpcServerConfig &async_cfg); + ~TrexRpcServer(); /** diff --git a/src/rpc-server/trex_rpc_server_mock.cpp b/src/rpc-server/trex_rpc_server_mock.cpp index 835e28b8..16aa6774 100644 --- a/src/rpc-server/trex_rpc_server_mock.cpp +++ b/src/rpc-server/trex_rpc_server_mock.cpp @@ -59,8 +59,10 @@ int main(int argc, char *argv[]) { cout << "\n-= Starting RPC Server Mock =-\n\n"; cout << "Listening on tcp://localhost:5050 [ZMQ]\n\n"; - TrexRpcServerConfig rpc_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5050); - TrexRpcServer rpc(rpc_cfg); + TrexRpcServerConfig rpc_req_resp_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5050); + TrexRpcServerConfig rpc_async_cfg(TrexRpcServerConfig::RPC_PROT_TCP, 5051); + + TrexRpcServer rpc(rpc_req_resp_cfg, rpc_async_cfg); /* init the RPC server */ rpc.start(); diff --git a/src/stateless/trex_stateless.cpp b/src/stateless/trex_stateless.cpp index 3ec419ea..0b7947a0 100644 --- a/src/stateless/trex_stateless.cpp +++ b/src/stateless/trex_stateless.cpp @@ -19,6 +19,7 @@ See the License for the specific language governing permissions and limitations under the License. */ #include +#include using namespace std; @@ -73,107 +74,64 @@ uint8_t TrexStateless::get_port_count() { return m_port_count; } +void +TrexStateless::update_stats() { -/*************************** - * trex stateless port stats - * - **************************/ -TrexPortStats::TrexPortStats() { - m_stats = {0}; -} - -/*************************** - * trex stateless port - * - **************************/ -TrexStatelessPort::TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) { - m_port_state = PORT_STATE_UP_IDLE; - clear_owner(); -} - + /* update CPU util. */ + #ifdef TREX_RPC_MOCK_SERVER + m_stats.m_stats.m_cpu_util = 0; + #else + m_stats.m_stats.m_cpu_util = 0; + #endif -/** - * starts the traffic on the port - * - */ -TrexStatelessPort::rc_e -TrexStatelessPort::start_traffic(void) { + /* for every port update and accumulate */ + for (uint8_t i = 0; i < m_port_count; i++) { + m_ports[i]->update_stats(); - if (m_port_state != PORT_STATE_UP_IDLE) { - return (RC_ERR_BAD_STATE_FOR_OP); - } + const TrexPortStats & port_stats = m_ports[i]->get_stats(); - if (get_stream_table()->size() == 0) { - return (RC_ERR_NO_STREAMS); - } + m_stats.m_stats.m_tx_bps += port_stats.m_stats.m_tx_bps; + m_stats.m_stats.m_rx_bps += port_stats.m_stats.m_rx_bps; - m_port_state = PORT_STATE_TRANSMITTING; + m_stats.m_stats.m_tx_pps += port_stats.m_stats.m_tx_pps; + m_stats.m_stats.m_rx_pps += port_stats.m_stats.m_rx_pps; - /* real code goes here */ - return (RC_OK); -} + m_stats.m_stats.m_total_tx_pkts += port_stats.m_stats.m_total_tx_pkts; + m_stats.m_stats.m_total_rx_pkts += port_stats.m_stats.m_total_rx_pkts; -void -TrexStatelessPort::stop_traffic(void) { + m_stats.m_stats.m_total_tx_bytes += port_stats.m_stats.m_total_tx_bytes; + m_stats.m_stats.m_total_rx_bytes += port_stats.m_stats.m_total_rx_bytes; - /* real code goes here */ - if (m_port_state == PORT_STATE_TRANSMITTING) { - m_port_state = PORT_STATE_UP_IDLE; + m_stats.m_stats.m_tx_rx_errors += port_stats.m_stats.m_tx_rx_errors; } } -/** -* access the stream table -* -*/ -TrexStreamTable * TrexStatelessPort::get_stream_table() { - return &m_stream_table; -} - +void +TrexStateless::encode_stats(Json::Value &global) { -std::string -TrexStatelessPort::get_state_as_string() { + global["cpu_util"] = m_stats.m_stats.m_cpu_util; - switch (get_state()) { - case PORT_STATE_DOWN: - return "down"; + global["tx_bps"] = m_stats.m_stats.m_tx_bps; + global["rx_bps"] = m_stats.m_stats.m_rx_bps; - case PORT_STATE_UP_IDLE: - return "idle"; + global["tx_pps"] = m_stats.m_stats.m_tx_pps; + global["rx_pps"] = m_stats.m_stats.m_rx_pps; - case PORT_STATE_TRANSMITTING: - return "transmitting"; - } + global["total_tx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_pkts); + global["total_rx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_pkts); - return "unknown"; -} + global["total_tx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_bytes); + global["total_rx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_bytes); -void -TrexStatelessPort::get_properties(string &driver, string &speed) { + global["tx_rx_errors"] = Json::Value::UInt64(m_stats.m_stats.m_tx_rx_errors); - /* take this from DPDK */ - driver = "e1000"; - speed = "1 Gbps"; -} + for (uint8_t i = 0; i < m_port_count; i++) { + std::stringstream ss; + ss << "port " << i; + Json::Value &port_section = global[ss.str()]; -/** - * generate a random connection handler - * - */ -std::string -TrexStatelessPort::generate_handler() { - std::stringstream ss; - - static const char alphanum[] = - "0123456789" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz"; - - /* generate 8 bytes of random handler */ - for (int i = 0; i < 8; ++i) { - ss << alphanum[rand() % (sizeof(alphanum) - 1)]; + m_ports[i]->encode_stats(port_section); } - - return (ss.str()); } + diff --git a/src/stateless/trex_stateless_api.h b/src/stateless/trex_stateless_api.h index fd88baf7..e2bf4e1c 100644 --- a/src/stateless/trex_stateless_api.h +++ b/src/stateless/trex_stateless_api.h @@ -41,167 +41,36 @@ public: } }; -/** - * TRex stateless port stats - * - * @author imarom (24-Sep-15) - */ -class TrexPortStats { - -public: - TrexPortStats(); - -public: - struct { - uint64_t tx_pps; - uint64_t tx_bps; - uint64_t total_tx_pkts; - uint64_t total_tx_bytes; - - uint64_t rx_pps; - uint64_t rx_bps; - uint64_t total_rx_pkts; - uint64_t total_rx_bytes; - - uint64_t tx_rx_errors; - } m_stats; -}; +class TrexStatelessPort; /** - * describes a stateless port + * unified stats * - * @author imarom (31-Aug-15) + * @author imarom (06-Oct-15) */ -class TrexStatelessPort { +class TrexStatelessStats { public: - - /** - * port state - */ - 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); - - /** - * start traffic - * - */ - rc_e start_traffic(void); - - /** - * stop traffic - * - */ - void stop_traffic(void); - - /** - * access the stream table - * - */ - TrexStreamTable *get_stream_table(); - - /** - * get the port state - * - */ - port_state_e get_state() { - return m_port_state; + TrexStatelessStats() { + m_stats = {0}; } - /** - * port state as string - * - */ - std::string get_state_as_string(); - - /** - * fill up properties of the port - * - * @author imarom (16-Sep-15) - * - * @param driver - * @param speed - */ - void get_properties(std::string &driver, std::string &speed); - - /** - * query for ownership - * - */ - const std::string &get_owner() { - return m_owner; - } - - /** - * owner handler - * for the connection - * - */ - const std::string &get_owner_handler() { - return m_owner_handler; - } - - bool is_free_to_aquire() { - return (m_owner == "none"); - } - - /** - * take ownership of the server array - * this is static - * ownership is total - * - */ - void set_owner(const std::string &owner) { - m_owner = owner; - m_owner_handler = generate_handler(); - } - - void clear_owner() { - m_owner = "none"; - m_owner_handler = ""; - } - - bool verify_owner_handler(const std::string &handler) { - - return ( (m_owner != "none") && (m_owner_handler == handler) ); - - } - - /** - * update the values of the stats - * - * @author imarom (24-Sep-15) - */ - void update_stats(); - - const TrexPortStats & get_stats() { - return m_stats; - } - -private: - - std::string generate_handler(); - - TrexStreamTable m_stream_table; - uint8_t m_port_id; - port_state_e m_port_state; - std::string m_owner; - std::string m_owner_handler; - TrexPortStats m_stats; + struct { + double m_cpu_util; + + double m_tx_bps; + double m_rx_bps; + + double m_tx_pps; + double m_rx_pps; + + uint64_t m_total_tx_pkts; + uint64_t m_total_rx_pkts; + + uint64_t m_total_tx_bytes; + uint64_t m_total_rx_bytes; + + uint64_t m_tx_rx_errors; + } m_stats; }; /** @@ -232,8 +101,22 @@ public: return instance; } - TrexStatelessPort *get_port_by_id(uint8_t port_id); - uint8_t get_port_count(); + TrexStatelessPort * get_port_by_id(uint8_t port_id); + uint8_t get_port_count(); + + /** + * update all the stats (deep update) + * (include all the ports and global stats) + * + */ + void update_stats(); + + /** + * fetch all the stats + * + */ + void encode_stats(Json::Value &global); + protected: TrexStateless(); @@ -248,9 +131,11 @@ protected: TrexStateless(TrexStateless const&) = delete; void operator=(TrexStateless const&) = delete; - bool m_is_configured; - TrexStatelessPort **m_ports; - uint8_t m_port_count; + bool m_is_configured; + TrexStatelessPort **m_ports; + uint8_t m_port_count; + + TrexStatelessStats m_stats; }; #endif /* __TREX_STATELESS_API_H__ */ diff --git a/src/stateless/trex_stateless_port.cpp b/src/stateless/trex_stateless_port.cpp new file mode 100644 index 00000000..7322ef8a --- /dev/null +++ b/src/stateless/trex_stateless_port.cpp @@ -0,0 +1,172 @@ +/* + 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 +#include +#include + +using namespace std; + +/*************************** + * trex stateless port + * + **************************/ +TrexStatelessPort::TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) { + m_port_state = PORT_STATE_UP_IDLE; + clear_owner(); +} + + +/** + * starts the traffic on the port + * + */ +TrexStatelessPort::rc_e +TrexStatelessPort::start_traffic(void) { + + if (m_port_state != PORT_STATE_UP_IDLE) { + return (RC_ERR_BAD_STATE_FOR_OP); + } + + if (get_stream_table()->size() == 0) { + return (RC_ERR_NO_STREAMS); + } + + m_port_state = PORT_STATE_TRANSMITTING; + + /* real code goes here */ + return (RC_OK); +} + +void +TrexStatelessPort::stop_traffic(void) { + + /* real code goes here */ + if (m_port_state == PORT_STATE_TRANSMITTING) { + m_port_state = PORT_STATE_UP_IDLE; + } +} + +/** +* access the stream table +* +*/ +TrexStreamTable * TrexStatelessPort::get_stream_table() { + return &m_stream_table; +} + + +std::string +TrexStatelessPort::get_state_as_string() { + + switch (get_state()) { + case PORT_STATE_DOWN: + return "down"; + + case PORT_STATE_UP_IDLE: + return "idle"; + + case PORT_STATE_TRANSMITTING: + return "transmitting"; + } + + return "unknown"; +} + +void +TrexStatelessPort::get_properties(string &driver, string &speed) { + + /* take this from DPDK */ + driver = "e1000"; + speed = "1 Gbps"; +} + + +/** + * generate a random connection handler + * + */ +std::string +TrexStatelessPort::generate_handler() { + std::stringstream ss; + + static const char alphanum[] = + "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + + /* generate 8 bytes of random handler */ + for (int i = 0; i < 8; ++i) { + ss << alphanum[rand() % (sizeof(alphanum) - 1)]; + } + + return (ss.str()); +} + +/** + * update stats for the port + * + */ +void +TrexStatelessPort::update_stats() { + #ifdef TREX_RPC_MOCK_SERVER + /* do lies - its a mock */ + m_stats.m_stats.m_tx_bps = rand() % 10000; + m_stats.m_stats.m_rx_bps = rand() % 10000; + + m_stats.m_stats.m_tx_pps = m_stats.m_stats.m_tx_bps / (64 + rand() % 1000); + m_stats.m_stats.m_rx_pps = m_stats.m_stats.m_rx_bps / (64 + rand() % 1000); + + + m_stats.m_stats.m_total_tx_bytes += m_stats.m_stats.m_tx_bps; + m_stats.m_stats.m_total_rx_bytes += m_stats.m_stats.m_rx_bps; + + m_stats.m_stats.m_total_tx_pkts += m_stats.m_stats.m_tx_pps; + m_stats.m_stats.m_total_rx_pkts += m_stats.m_stats.m_rx_pps; + + #else + /* real update work */ + #endif +} + +const TrexPortStats & +TrexStatelessPort::get_stats() { + return m_stats; +} + +void +TrexStatelessPort::encode_stats(Json::Value &port) { + + port["tx_bps"] = m_stats.m_stats.m_tx_bps; + port["rx_bps"] = m_stats.m_stats.m_rx_bps; + + port["tx_pps"] = m_stats.m_stats.m_tx_pps; + port["rx_pps"] = m_stats.m_stats.m_rx_pps; + + port["total_tx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_pkts); + port["total_rx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_pkts); + + port["total_tx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_bytes); + port["total_rx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_bytes); + + port["tx_rx_errors"] = Json::Value::UInt64(m_stats.m_stats.m_tx_rx_errors); +} + + diff --git a/src/stateless/trex_stateless_port.h b/src/stateless/trex_stateless_port.h new file mode 100644 index 00000000..ea98ddae --- /dev/null +++ b/src/stateless/trex_stateless_port.h @@ -0,0 +1,196 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#ifndef __TREX_STATELESS_PORT_H__ +#define __TREX_STATELESS_PORT_H__ + +#include + +/** + * TRex stateless port stats + * + * @author imarom (24-Sep-15) + */ +class TrexPortStats { + +public: + TrexPortStats() { + m_stats = {0}; + } + +public: + struct { + + double m_tx_bps; + double m_rx_bps; + + double m_tx_pps; + double m_rx_pps; + + uint64_t m_total_tx_pkts; + uint64_t m_total_rx_pkts; + + uint64_t m_total_tx_bytes; + uint64_t m_total_rx_bytes; + + uint64_t m_tx_rx_errors; + } m_stats; +}; + +/** + * describes a stateless port + * + * @author imarom (31-Aug-15) + */ +class TrexStatelessPort { +public: + + /** + * port state + */ + 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); + + /** + * start traffic + * + */ + rc_e start_traffic(void); + + /** + * stop traffic + * + */ + void stop_traffic(void); + + /** + * access the stream table + * + */ + TrexStreamTable *get_stream_table(); + + /** + * get the port state + * + */ + port_state_e get_state() { + return m_port_state; + } + + /** + * port state as string + * + */ + std::string get_state_as_string(); + + /** + * fill up properties of the port + * + * @author imarom (16-Sep-15) + * + * @param driver + * @param speed + */ + void get_properties(std::string &driver, std::string &speed); + + /** + * query for ownership + * + */ + const std::string &get_owner() { + return m_owner; + } + + /** + * owner handler + * for the connection + * + */ + const std::string &get_owner_handler() { + return m_owner_handler; + } + + bool is_free_to_aquire() { + return (m_owner == "none"); + } + + /** + * take ownership of the server array + * this is static + * ownership is total + * + */ + void set_owner(const std::string &owner) { + m_owner = owner; + m_owner_handler = generate_handler(); + } + + void clear_owner() { + m_owner = "none"; + m_owner_handler = ""; + } + + bool verify_owner_handler(const std::string &handler) { + + return ( (m_owner != "none") && (m_owner_handler == handler) ); + + } + + /** + * update the values of the stats + * + */ + void update_stats(); + + const TrexPortStats & get_stats(); + + /** + * encode stats as JSON + */ + void encode_stats(Json::Value &port); + +private: + + std::string generate_handler(); + + TrexStreamTable m_stream_table; + uint8_t m_port_id; + port_state_e m_port_state; + std::string m_owner; + std::string m_owner_handler; + TrexPortStats m_stats; +}; + +#endif /* __TREX_STATELESS_PORT_H__ */ -- cgit 1.2.3-korg