diff options
-rwxr-xr-x | scripts/automation/trex_control_plane/client/trex_stateless_client.py | 88 | ||||
-rwxr-xr-x | scripts/automation/trex_control_plane/console/trex_console.py | 16 | ||||
-rw-r--r-- | src/rpc-server/commands/trex_rpc_cmd_stream.cpp | 49 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless_port.cpp | 27 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless_port.h | 14 | ||||
-rw-r--r-- | src/stateless/dp/trex_stateless_dp_core.cpp | 34 | ||||
-rw-r--r-- | src/stateless/dp/trex_stateless_dp_core.h | 16 | ||||
-rw-r--r-- | src/stateless/dp/trex_stream_node.h | 12 | ||||
-rw-r--r-- | src/stateless/messaging/trex_stateless_messaging.cpp | 16 | ||||
-rw-r--r-- | src/stateless/messaging/trex_stateless_messaging.h | 20 |
10 files changed, 243 insertions, 49 deletions
diff --git a/scripts/automation/trex_control_plane/client/trex_stateless_client.py b/scripts/automation/trex_control_plane/client/trex_stateless_client.py index 149d2855..c5b28f5b 100755 --- a/scripts/automation/trex_control_plane/client/trex_stateless_client.py +++ b/scripts/automation/trex_control_plane/client/trex_stateless_client.py @@ -164,7 +164,7 @@ class Port(object): return RC_OK() def get_speed_bps (self): - return (self.speed * 1000 * 1000) + return (self.speed * 1000 * 1000 * 1000) # take the port def acquire(self, force = False): @@ -293,6 +293,13 @@ class Port(object): return self.streams + def process_mul (self, mul): + # if percentage - translate + if mul['type'] == 'percentage': + mul['type'] = 'max_bps' + mul['max'] = self.get_speed_bps() * (mul['max'] / 100) + + # start traffic def start (self, mul, duration): if self.state == self.STATE_DOWN: @@ -304,11 +311,8 @@ class Port(object): if self.state == self.STATE_TX: return self.err("Unable to start traffic - port is already transmitting") - # if percentage - translate - if mul['type'] == 'percentage': - mul['type'] = 'max_bps' - mul['max'] = self.get_speed_bps() * (mul['max'] / 100) - + self.process_mul(mul) + params = {"handler": self.handler, "port_id": self.port_id, "mul": mul, @@ -358,6 +362,7 @@ class Port(object): return self.ok() + def resume (self): if (self.state != self.STATE_PAUSE) : @@ -375,6 +380,23 @@ class Port(object): return self.ok() + + def update (self, mul): + if (self.state != self.STATE_TX) : + return self.err("port is not transmitting") + + self.process_mul(mul) + + params = {"handler": self.handler, + "port_id": self.port_id, + "mul": mul} + + rc, data = self.transmit("update_traffic", params) + if not rc: + return self.err(data) + + return self.ok() + ################# events handler ###################### def async_event_port_stopped (self): self.state = self.STATE_STREAMS @@ -752,6 +774,17 @@ class CTRexStatelessClient(object): return rc + def update_traffic (self, mult, port_id_list = None, force = False): + + port_id_list = self.__ports(port_id_list) + rc = RC() + + for port_id in port_id_list: + rc.add(self.ports[port_id].update(mult)) + + return rc + + def get_port_stats(self, port_id=None): pass @@ -832,6 +865,25 @@ class CTRexStatelessClient(object): return RC_OK() + # update cmd + def cmd_update (self, port_id_list, mult): + + # find the relveant ports + active_ports = list(set(self.get_active_ports()).intersection(port_id_list)) + + if not active_ports: + msg = "No active traffic on porvided ports" + print format_text(msg, 'bold') + return RC_ERR(msg) + + rc = self.update_traffic(mult, active_ports) + rc.annotate("Updating traffic on port(s) {0}:".format(port_id_list)) + if rc.bad(): + return rc + + return RC_OK() + + # pause cmd def cmd_pause (self, port_id_list): @@ -968,7 +1020,8 @@ class CTRexStatelessClient(object): return RC_ERR("Failed to load stream pack") - if opts.total: + # total has no meaning with percentage - its linear + if opts.total and (mult['type'] != 'percentage'): # if total was set - divide it between the ports opts.mult['max'] = opts.mult['max'] / len(opts.ports) @@ -988,6 +1041,27 @@ class CTRexStatelessClient(object): return self.cmd_stop(opts.ports) + def cmd_update_line (self, line): + '''Update port(s) speed currently active\n''' + parser = parsing_opts.gen_parser(self, + "update", + self.cmd_update_line.__doc__, + parsing_opts.PORT_LIST_WITH_ALL, + parsing_opts.MULTIPLIER, + parsing_opts.TOTAL) + + opts = parser.parse_args(line.split()) + if opts is None: + return RC_ERR("bad command line paramters") + + # total has no meaning with percentage - its linear + if opts.total and (opts.mult['type'] != 'percentage'): + # if total was set - divide it between the ports + opts.mult['max'] = opts.mult['max'] / len(opts.ports) + + return self.cmd_update(opts.ports, opts.mult) + + def cmd_reset_line (self, line): return self.cmd_reset() diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index fc2c845a..9e44daac 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -313,6 +313,17 @@ class TRexConsole(TRexGeneralCmd): '''stops port(s) transmitting traffic\n''' self.stateless_client.cmd_stop_line(line) + def help_stop(self): + self.do_stop("-h") + + ############# update + def do_update(self, line): + '''update speed of port(s)currently transmitting traffic\n''' + self.stateless_client.cmd_update_line(line) + + def help_update (self): + self.do_update("-h") + ############# pause def do_pause(self, line): '''pause port(s) transmitting traffic\n''' @@ -323,10 +334,7 @@ class TRexConsole(TRexGeneralCmd): '''resume port(s) transmitting traffic\n''' self.stateless_client.cmd_resume_line(line) - - - def help_stop(self): - self.do_stop("-h") + ########## reset def do_reset (self, line): diff --git a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp index f148261c..96224d4e 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_stream.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_stream.cpp @@ -479,18 +479,26 @@ TrexRpcCmdStartTraffic::_run(const Json::Value ¶ms, Json::Value &result) { std::string mul_type = parse_string(mul, "type", result); double max_rate = parse_double(mul, "max", result); + + double m = 0; + /* dispatch according to type of multiplier */ + if (mul_type == "raw") { + m = max_rate; - try { - if (mul_type == "raw") { - port->start_traffic(max_rate, duration); + } else if (mul_type == "max_bps") { + m = port->calculate_m_from_bps(max_rate); - } else if (mul_type == "max_bps") { - port->start_traffic_max_bps(max_rate, duration); + } else if (mul_type == "max_pps") { + m = port->calculate_m_from_pps(max_rate); - } else if (mul_type == "max_pps") { - port->start_traffic_max_pps(max_rate, duration); - } + } else { + generate_parse_err(result, "multiplier type can be either 'raw', 'max_bps' or 'max_pps'"); + } + + + try { + port->start_traffic(m, duration); } catch (const TrexRpcException &ex) { generate_execute_err(result, ex.what()); @@ -633,7 +641,6 @@ trex_rpc_cmd_rc_e TrexRpcCmdUpdateTraffic::_run(const Json::Value ¶ms, Json::Value &result) { uint8_t port_id = parse_byte(params, "port_id", result); - double mul = parse_double(params, "mul", result); if (port_id >= get_stateless_obj()->get_port_count()) { std::stringstream ss; @@ -643,8 +650,30 @@ TrexRpcCmdUpdateTraffic::_run(const Json::Value ¶ms, Json::Value &result) { TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id); + /* multiplier */ + const Json::Value &mul = parse_object(params, "mul", result); + + std::string mul_type = parse_string(mul, "type", result); + double max_rate = parse_double(mul, "max", result); + + double m = 0; + + /* dispatch according to type of multiplier */ + if (mul_type == "raw") { + m = max_rate; + + } else if (mul_type == "max_bps") { + m = port->calculate_m_from_bps(max_rate); + + } else if (mul_type == "max_pps") { + m = port->calculate_m_from_pps(max_rate); + + } else { + generate_parse_err(result, "multiplier type can be either 'raw', 'max_bps' or 'max_pps'"); + } + try { - port->update_traffic(mul); + port->update_traffic(m); } catch (const TrexRpcException &ex) { generate_execute_err(result, ex.what()); } diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 2fd948fd..8e18a5bf 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -144,32 +144,29 @@ TrexStatelessPort::start_traffic(double mul, double duration) { get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_STARTED, data); } -void -TrexStatelessPort::start_traffic_max_bps(double max_bps, double duration) { + +double +TrexStatelessPort::calculate_m_from_bps(double max_bps) { /* fetch all the streams from the table */ vector<TrexStream *> streams; get_object_list(streams); TrexStreamsGraph graph; const TrexStreamsGraphObj &obj = graph.generate(streams); - double m = (max_bps / obj.get_max_bps()); - /* call the main function */ - start_traffic(m, duration); + return (max_bps / obj.get_max_bps()); } -void -TrexStatelessPort::start_traffic_max_pps(double max_pps, double duration) { +double +TrexStatelessPort::calculate_m_from_pps(double max_pps) { /* fetch all the streams from the table */ vector<TrexStream *> streams; get_object_list(streams); TrexStreamsGraph graph; const TrexStreamsGraphObj &obj = graph.generate(streams); - double m = (max_pps / obj.get_max_pps()); - /* call the main function */ - start_traffic(m, duration); + return (max_pps / obj.get_max_pps()); } /** @@ -239,16 +236,14 @@ TrexStatelessPort::resume_traffic(void) { void TrexStatelessPort::update_traffic(double mul) { - verify_state(PORT_STATE_STREAMS | PORT_STATE_TX | PORT_STATE_PAUSE); + verify_state(PORT_STATE_TX | PORT_STATE_PAUSE); - #if 0 /* generate a message to all the relevant DP cores to start transmitting */ - TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(m_port_id); + double per_core_mul = mul / m_cores_id_list.size(); + TrexStatelessCpToDpMsgBase *update_msg = new TrexStatelessDpUpdate(m_port_id, per_core_mul); - send_message_to_dp(stop_msg); + send_message_to_dp(update_msg); - m_port_state = PORT_STATE_UP_IDLE; - #endif } std::string diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 20acd927..b061a414 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -77,8 +77,18 @@ public: * throws TrexException in case of an error */ void start_traffic(double mul, double duration = -1); - void start_traffic_max_bps(double max_bps, double duration = -1); - void start_traffic_max_pps(double max_pps, double duration = -1); + + /** + * given a BPS rate calculate ther correct M for this port + * + */ + double calculate_m_from_bps(double max_bps); + + /** + * given a PPS rate calculate the correct M for this port + * + */ + double calculate_m_from_pps(double max_pps); /** * stop traffic diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 4e429c8f..dd4937cd 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -139,6 +139,20 @@ bool TrexStatelessDpPerPort::resume_traffic(uint8_t port_id){ return (true); } +bool TrexStatelessDpPerPort::update_traffic(uint8_t port_id, double mul) { + + assert( (m_state == TrexStatelessDpPerPort::ppSTATE_TRANSMITTING || + (m_state == TrexStatelessDpPerPort::ppSTATE_PAUSE)) ); + + for (auto dp_stream : m_active_nodes) { + CGenNodeStateless * node = dp_stream.m_node; + assert(node->get_port_id() == port_id); + + node->set_multiplier(mul); + } + + return (true); +} bool TrexStatelessDpPerPort::pause_traffic(uint8_t port_id){ @@ -402,9 +416,9 @@ TrexStatelessDpCore::add_port_duration(double duration, void -TrexStatelessDpCore::add_cont_stream(TrexStatelessDpPerPort * lp_port, - TrexStream * stream, - TrexStreamsCompiledObj *comp) { +TrexStatelessDpCore::add_stream(TrexStatelessDpPerPort * lp_port, + TrexStream * stream, + TrexStreamsCompiledObj *comp) { CGenNodeStateless *node = m_core->create_node_sl(); @@ -439,8 +453,8 @@ TrexStatelessDpCore::add_cont_stream(TrexStatelessDpPerPort * lp_port, node->m_pause =0; node->m_stream_type = stream->m_type; - node->m_next_time_offset = 1.0 / (stream->get_pps() * comp->get_multiplier()) ; - + node->m_base_pps = stream->get_pps(); + node->set_multiplier(comp->get_multiplier()); /* stateless specific fields */ switch ( stream->m_type ) { @@ -520,7 +534,7 @@ TrexStatelessDpCore::start_traffic(TrexStreamsCompiledObj *obj, for (auto single_stream : obj->get_objects()) { /* all commands should be for the same port */ assert(obj->get_port_id() == single_stream.m_stream->m_port_id); - add_cont_stream(lp_port,single_stream.m_stream,obj); + add_stream(lp_port,single_stream.m_stream,obj); } uint32_t nodes = lp_port->m_active_nodes.size(); @@ -582,6 +596,14 @@ TrexStatelessDpCore::pause_traffic(uint8_t port_id){ lp_port->pause_traffic(port_id); } +void +TrexStatelessDpCore::update_traffic(uint8_t port_id, double mul) { + + TrexStatelessDpPerPort * lp_port = get_port_db(port_id); + + lp_port->update_traffic(port_id, mul); +} + void TrexStatelessDpCore::stop_traffic(uint8_t port_id, diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index eda1ae59..563159b2 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -68,6 +68,8 @@ public: bool resume_traffic(uint8_t port_id); + bool update_traffic(uint8_t port_id, double mul); + bool stop_traffic(uint8_t port_id, bool stop_on_id, int event_id); @@ -159,6 +161,14 @@ public: /** + * update current traffic rate + * + * @author imarom (25-Nov-15) + * + */ + void update_traffic(uint8_t port_id, double mul); + + /** * * stop all traffic for this core * @@ -250,9 +260,9 @@ private: void add_global_duration(double duration); - void add_cont_stream(TrexStatelessDpPerPort * lp_port, - TrexStream * stream, - TrexStreamsCompiledObj *comp); + void add_stream(TrexStatelessDpPerPort * lp_port, + TrexStream * stream, + TrexStreamsCompiledObj *comp); uint8_t m_thread_id; uint8_t m_local_port_offset; diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h index ccf99eaa..5997376f 100644 --- a/src/stateless/dp/trex_stream_node.h +++ b/src/stateless/dp/trex_stream_node.h @@ -86,8 +86,9 @@ private: TrexStream * m_ref_stream_info; /* the stream info */ CGenNodeStateless * m_next_stream; + double m_base_pps; /* pad to match the size of CGenNode */ - uint8_t m_pad_end[56]; + uint8_t m_pad_end[48]; @@ -99,6 +100,15 @@ public: } + /** + * calculate the time offset based + * on the PPS and multiplier + * + */ + void set_multiplier(double mul) { + m_next_time_offset = 1.0 / (m_base_pps * mul) ; + } + /* we restart the stream, schedule it using stream isg */ inline void update_refresh_time(double cur_time){ m_time = cur_time + usec_to_sec(m_ref_stream_info->m_isg_usec); diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index ec8b7839..3210f29a 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -163,6 +163,22 @@ TrexStatelessDpCanQuit::clone(){ return new_msg; } +/************************* + update traffic message + ************************/ +bool +TrexStatelessDpUpdate::handle(TrexStatelessDpCore *dp_core) { + dp_core->update_traffic(m_port_id, m_mul); + + return true; +} + +TrexStatelessCpToDpMsgBase * +TrexStatelessDpUpdate::clone() { + TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpUpdate(m_port_id, m_mul); + + return new_msg; +} /************************* messages from DP to CP **********************/ bool diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index 6bd0dbe3..7390be60 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -225,6 +225,26 @@ public: }; +/** + * update message + */ +class TrexStatelessDpUpdate : public TrexStatelessCpToDpMsgBase { +public: + + TrexStatelessDpUpdate(uint8_t port_id, double mul) { + m_port_id = port_id; + m_mul = mul; + } + + virtual bool handle(TrexStatelessDpCore *dp_core); + + virtual TrexStatelessCpToDpMsgBase * clone(); + +private: + uint8_t m_port_id; + double m_mul; +}; + /************************* messages from DP to CP **********************/ |