diff options
author | Yaroslav Brustinov <ybrustin@cisco.com> | 2016-04-19 03:19:28 +0300 |
---|---|---|
committer | Yaroslav Brustinov <ybrustin@cisco.com> | 2016-04-19 03:19:28 +0300 |
commit | 6840551a8733fefdd8b3f235e4a802524ecc39d9 (patch) | |
tree | 2208741daedb73a0e630cdd284091dd3b5c76633 | |
parent | 6c46ecabec713485954dc7394e8a9808309fb4bc (diff) | |
parent | e6d1ca8bc126b2efc5a15268cd2d9926f1be3ab9 (diff) |
Merge remote-tracking branch 'origin/master'
12 files changed, 197 insertions, 62 deletions
diff --git a/scripts/automation/trex_control_plane/doc_stl/api/client_code.rst b/scripts/automation/trex_control_plane/doc_stl/api/client_code.rst index 4ae2b9fd..d3e48dab 100755 --- a/scripts/automation/trex_control_plane/doc_stl/api/client_code.rst +++ b/scripts/automation/trex_control_plane/doc_stl/api/client_code.rst @@ -82,6 +82,11 @@ STLClient snippet # block until done c.wait_on_traffic(ports = [0, 1]) + # check for any warnings + if c.get_warnings(): + # handle warnings here + pass + finally: c.disconnect() diff --git a/scripts/automation/trex_control_plane/stl/console/trex_console.py b/scripts/automation/trex_control_plane/stl/console/trex_console.py index 2b53b7ec..a126bf35 100755 --- a/scripts/automation/trex_control_plane/stl/console/trex_console.py +++ b/scripts/automation/trex_control_plane/stl/console/trex_console.py @@ -289,7 +289,7 @@ class TRexConsole(TRexGeneralCmd): @verify_connected def do_ping (self, line): '''Ping the server\n''' - self.stateless_client.ping() + self.stateless_client.ping_line(line) # set verbose on / off @@ -421,6 +421,9 @@ class TRexConsole(TRexGeneralCmd): '''Release ports\n''' self.stateless_client.release_line(line) + def do_reacquire (self, line): + '''reacquire all the ports under your logged user name''' + self.stateless_client.reacquire_line(line) def help_acquire (self): self.do_acquire("-h") @@ -428,6 +431,9 @@ class TRexConsole(TRexGeneralCmd): def help_release (self): self.do_release("-h") + def help_reacquire (self): + self.do_reacquire("-h") + ############### start def complete_start(self, text, line, begidx, endidx): @@ -774,7 +780,29 @@ def setParserOptions(): return parser - +# a simple info printed on log on +def show_intro (logger, c): + x = c.get_server_system_info() + ver = c.get_server_version().get('version', 'N/A') + + # find out which NICs the server has + port_types = {} + for port in x['ports']: + key = (port['speed'], port['driver']) + if not key in port_types: + port_types[key] = 0 + port_types[key] += 1 + + port_line = '' + for k, v in port_types.items(): + port_line += "{0} x {1}Gbps @ {2}".format(v, k[0], k[1]) + + logger.log(format_text("\nServer Info:\n", 'underline')) + logger.log("Server version: {:>}".format(format_text(ver, 'bold'))) + logger.log("Server CPU: {:>}".format(format_text("{:>} x {:>}".format(x.get('dp_core_count'), x.get('core_type')), 'bold'))) + logger.log("Ports count: {:>}".format(format_text(port_line, 'bold'))) + + def main(): parser = setParserOptions() options = parser.parse_args() @@ -824,6 +852,9 @@ def main(): if options.readonly: logger.log(format_text("\nRead only mode - only few commands will be available", 'bold')) + show_intro(logger, stateless_client) + + # a script mode if options.batch: cont = run_script_file(options.batch[0], stateless_client) diff --git a/scripts/automation/trex_control_plane/stl/console/trex_tui.py b/scripts/automation/trex_control_plane/stl/console/trex_tui.py index effcf55e..cbaae392 100644 --- a/scripts/automation/trex_control_plane/stl/console/trex_tui.py +++ b/scripts/automation/trex_control_plane/stl/console/trex_tui.py @@ -73,7 +73,10 @@ class TrexTUIDashBoard(TrexTUIPanel): self.key_actions['o'] = {'action': self.action_show_owned, 'legend': 'owned ports', 'show': True} self.key_actions['a'] = {'action': self.action_show_all, 'legend': 'all ports', 'show': True} - self.ports_filter = self.FILTER_ALL + if self.stateless_client.get_acquired_ports(): + self.ports_filter = self.FILTER_ACQUIRED + else: + self.ports_filter = self.FILTER_ALL def get_ports (self): @@ -99,7 +102,7 @@ class TrexTUIDashBoard(TrexTUIPanel): allowed['o'] = self.key_actions['o'] allowed['a'] = self.key_actions['a'] - if self.ports_filter == self.FILTER_ALL: + if self.ports_filter == self.FILTER_ALL and self.stateless_client.get_acquired_ports() != self.stateless_client.get_all_ports(): return allowed if len(self.stateless_client.get_transmitting_ports()) > 0: @@ -201,7 +204,7 @@ class TrexTUIPort(TrexTUIPanel): allowed['c'] = self.key_actions['c'] allowed['t'] = self.key_actions['t'] - if self.stateless_client.is_all_ports_acquired(): + if self.port_id not in self.stateless_client.get_acquired_ports(): return allowed if self.port.state == self.port.STATE_TX: @@ -535,7 +538,9 @@ class TrexTUI(): sys.stdout = old_stdout self.clear_screen() + print(mystdout.getvalue()) + sys.stdout.flush() self.draw_policer = 0 diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py index aa95f037..77fa40bb 100755 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py @@ -264,22 +264,55 @@ class EventsHandler(object): self.__async_event_port_job_done(port_id) show_event = True - # port was stolen... + # port was acquired - maybe stolen... elif (type == 5): session_id = data['session_id'] - # false alarm, its us + port_id = int(data['port_id']) + who = data['who'] + force = data['force'] + + # if we hold the port and it was not taken by this session - show it + if port_id in self.client.get_acquired_ports() and session_id != self.client.session_id: + show_event = True + + # format the thief/us... if session_id == self.client.session_id: - return + user = 'you' + elif who == self.client.username: + user = 'another session of you' + else: + user = "'{0}'".format(who) - port_id = int(data['port_id']) - who = data['who'] + if force: + ev = "Port {0} was forcely taken by {1}".format(port_id, user) + else: + ev = "Port {0} was taken by {1}".format(port_id, user) - ev = "Port {0} was forcely taken by '{1}'".format(port_id, who) + # call the handler in case its not this session + if session_id != self.client.session_id: + self.__async_event_port_acquired(port_id, who) + + + # port was released + elif (type == 6): + port_id = int(data['port_id']) + who = data['who'] + session_id = data['session_id'] + + if session_id == self.client.session_id: + user = 'you' + elif who == self.client.username: + user = 'another session of you' + else: + user = "'{0}'".format(who) + + ev = "Port {0} was released by {1}".format(port_id, user) + + # call the handler in case its not this session + if session_id != self.client.session_id: + self.__async_event_port_released(port_id) - # call the handler - self.__async_event_port_forced_acquired(port_id, who) - show_event = True # server stopped elif (type == 100): @@ -317,9 +350,11 @@ class EventsHandler(object): self.client.ports[port_id].async_event_port_resumed() - def __async_event_port_forced_acquired (self, port_id, who): - self.client.ports[port_id].async_event_forced_acquired(who) + def __async_event_port_acquired (self, port_id, who): + self.client.ports[port_id].async_event_acquired(who) + def __async_event_port_released (self, port_id): + self.client.ports[port_id].async_event_released() def __async_event_server_stopped (self): self.client.connected = False @@ -506,7 +541,7 @@ class STLClient(object): # API classes - self.api_vers = [ {'type': 'core', 'major': 1, 'minor':1 } + self.api_vers = [ {'type': 'core', 'major': 1, 'minor':2 } ] self.api_h = {'core': None} @@ -2038,6 +2073,11 @@ class STLClient(object): return wrap + @__console + def ping_line (self, line): + '''pings the server''' + self.ping() + return True @__console def connect_line (self, line): @@ -2117,6 +2157,28 @@ class STLClient(object): @__console + def reacquire_line (self, line): + '''reacquire all the ports under your username which are not acquired by your session''' + + parser = parsing_opts.gen_parser(self, + "reacquire", + self.reacquire_line.__doc__) + + opts = parser.parse_args(line.split()) + if opts is None: + return + + # find all the on-owned ports under your name + my_unowned_ports = list_difference([k for k, v in self.ports.items() if v.get_owner() == self.username], self.get_acquired_ports()) + if not my_unowned_ports: + self.logger.log("reacquire - no unowned ports under '{0}'".format(self.username)) + return + + self.acquire(ports = my_unowned_ports, force = True) + return True + + + @__console def disconnect_line (self, line): self.disconnect() @@ -2491,15 +2553,20 @@ class STLClient(object): '''Sets port attributes ''' parser = parsing_opts.gen_parser(self, - "port", + "port_attr", self.set_port_attr_line.__doc__, parsing_opts.PORT_LIST_WITH_ALL, parsing_opts.PROMISCUOUS_SWITCH) - opts = parser.parse_args(line.split()) + opts = parser.parse_args(line.split(), default_ports = self.get_acquired_ports(), verify_acquired = True) if opts is None: return + # if no attributes - fall back to printing the status + if opts.prom is None: + self.show_stats_line("--ps --port {0}".format(' '.join(str(port) for port in opts.ports))) + return + self.set_port_attr(opts.ports, opts.prom) @@ -2592,5 +2659,4 @@ class STLClient(object): if opts.clear: self.clear_events() - self.logger.log(format_text("\nEvent log was cleared\n")) - +
\ No newline at end of file diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py index 6f6f50b1..16e55d73 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py @@ -96,9 +96,12 @@ class Port(object): "handler": self.handler} rc = self.transmit("release", params) - self.handler = None - + if rc.good(): + + self.handler = None + self.owner = '' + return self.ok() else: return self.err(rc.err()) @@ -679,7 +682,10 @@ class Port(object): if not self.is_acquired(): self.state = self.STATE_TX - def async_event_forced_acquired (self, who): + def async_event_acquired (self, who): self.handler = None self.owner = who + def async_event_released (self): + self.owner = '' + diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py index 6b1185ef..4057c50d 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py @@ -201,6 +201,10 @@ class CTRexInfoGenerator(object): def _get_rational_block_char(value, range_start, interval): # in Konsole, utf-8 is sometimes printed with artifacts, return ascii for now #return 'X' if value >= range_start + float(interval) / 2 else ' ' + + if sys.__stdout__.encoding != 'UTF-8': + return 'X' if value >= range_start + float(interval) / 2 else ' ' + value -= range_start ratio = float(value) / interval if ratio <= 0.0625: @@ -532,7 +536,12 @@ class CTRexStats(object): v = self.get_trend(field, use_raw) value = abs(v) - arrow = u'\u25b2' if v > 0 else u'\u25bc' + + # use arrows if utf-8 is supported + if sys.__stdout__.encoding == 'UTF-8': + arrow = u'\u25b2' if v > 0 else u'\u25bc' + else: + arrow = '' if sys.version_info < (3,0): arrow = arrow.encode('utf-8') diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_opts.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_opts.py index bc2d44f4..5c0dfb14 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_opts.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_opts.py @@ -124,16 +124,9 @@ def underline(text): def text_attribute(text, attribute): - if isinstance(text, str): - return "{start}{txt}{stop}".format(start=TEXT_CODES[attribute]['start'], - txt=text, - stop=TEXT_CODES[attribute]['end']) - elif isinstance(text, unicode): - return u"{start}{txt}{stop}".format(start=TEXT_CODES[attribute]['start'], - txt=text, - stop=TEXT_CODES[attribute]['end']) - else: - raise Exception("not a string") + return "{start}{txt}{stop}".format(start=TEXT_CODES[attribute]['start'], + txt=text, + stop=TEXT_CODES[attribute]['end']) FUNC_DICT = {'blue': blue, diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index bb9c3bac..1496513d 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -2335,25 +2335,25 @@ private: std::string CGlobalStats::get_field(std::string name,float &f){ char buff[200]; - sprintf(buff,"\"%s\":%.1f,",name.c_str(),f); + snprintf(buff, sizeof(buff), "\"%s\":%.1f,",name.c_str(),f); return (std::string(buff)); } std::string CGlobalStats::get_field(std::string name,uint64_t &f){ char buff[200]; - sprintf(buff,"\"%s\":%llu,",name.c_str(), (unsigned long long)f); + snprintf(buff, sizeof(buff), "\"%s\":%llu,",name.c_str(), (unsigned long long)f); return (std::string(buff)); } std::string CGlobalStats::get_field_port(int port,std::string name,float &f){ char buff[200]; - sprintf(buff,"\"%s-%d\":%.1f,",name.c_str(),port,f); + snprintf(buff, sizeof(buff), "\"%s-%d\":%.1f,",name.c_str(),port,f); return (std::string(buff)); } std::string CGlobalStats::get_field_port(int port,std::string name,uint64_t &f){ char buff[200]; - sprintf(buff,"\"%s-%d\":%llu,",name.c_str(),port, (unsigned long long)f); + snprintf(buff, sizeof(buff), "\"%s-%d\":%llu,",name.c_str(),port, (unsigned long long)f); return (std::string(buff)); } @@ -2368,6 +2368,10 @@ void CGlobalStats::dump_json(std::string & json, bool baseline,uint32_t stats_ti json +="\"data\":{"; + char ts_buff[200]; + snprintf(ts_buff , sizeof(ts_buff), "\"ts\":{\"value\":%lu, \"freq\":%lu},", os_get_hr_tick_64(), os_get_hr_freq()); + json+= std::string(ts_buff); + #define GET_FIELD(f) get_field(std::string(#f),f) #define GET_FIELD_PORT(p,f) get_field_port(p,std::string(#f),lp->f) @@ -4339,7 +4343,7 @@ int update_dpdk_args(void){ lpsock->dump(stdout); } - sprintf(global_cores_str,"0x%llx",(unsigned long long)lpsock->get_cores_mask()); + snprintf(global_cores_str, sizeof(global_cores_str), "0x%llx" ,(unsigned long long)lpsock->get_cores_mask()); if (core_mask_sanity(strtol(global_cores_str, NULL, 16)) < 0) { return -1; } @@ -4355,11 +4359,11 @@ int update_dpdk_args(void){ if ( CGlobalInfo::m_options.preview.getVMode() == 0 ) { global_dpdk_args[5]=(char *)"--log-level"; - sprintf(global_loglevel_str,"%d",4); + snprintf(global_loglevel_str, sizeof(global_loglevel_str), "%d", 4); global_dpdk_args[6]=(char *)global_loglevel_str; }else{ global_dpdk_args[5]=(char *)"--log-level"; - sprintf(global_loglevel_str,"%d",CGlobalInfo::m_options.preview.getVMode()+1); + snprintf(global_loglevel_str, sizeof(global_loglevel_str), "%d", CGlobalInfo::m_options.preview.getVMode()+1); global_dpdk_args[6]=(char *)global_loglevel_str; } @@ -4375,7 +4379,7 @@ int update_dpdk_args(void){ if ( lpop->prefix.length() ){ global_dpdk_args[global_dpdk_args_num++]=(char *)"--file-prefix"; - sprintf(global_prefix_str,"%s",lpop->prefix.c_str()); + snprintf(global_prefix_str, sizeof(global_prefix_str), "%s", lpop->prefix.c_str()); global_dpdk_args[global_dpdk_args_num++]=(char *)global_prefix_str; global_dpdk_args[global_dpdk_args_num++]=(char *)"-m"; if (global_platform_cfg_info.m_limit_memory.length()) { diff --git a/src/publisher/trex_publisher.h b/src/publisher/trex_publisher.h index f086babb..f8843758 100644 --- a/src/publisher/trex_publisher.h +++ b/src/publisher/trex_publisher.h @@ -46,7 +46,8 @@ public: EVENT_PORT_PAUSED = 2, EVENT_PORT_RESUMED = 3, EVENT_PORT_FINISHED_TX = 4, - EVENT_PORT_FORCE_ACQUIRED = 5, + EVENT_PORT_ACQUIRED = 5, + EVENT_PORT_RELEASED = 6, EVENT_SERVER_STOPPED = 100, diff --git a/src/stateless/cp/trex_stateless.cpp b/src/stateless/cp/trex_stateless.cpp index c86c5f65..5bbe9faf 100644 --- a/src/stateless/cp/trex_stateless.cpp +++ b/src/stateless/cp/trex_stateless.cpp @@ -54,7 +54,7 @@ TrexStateless::TrexStateless(const TrexStatelessCfg &cfg) { m_publisher = cfg.m_publisher; /* API core version */ - m_api_classes[APIClass::API_CLASS_TYPE_CORE].init(APIClass::API_CLASS_TYPE_CORE, 1, 1); + m_api_classes[APIClass::API_CLASS_TYPE_CORE].init(APIClass::API_CLASS_TYPE_CORE, 1, 2); } /** diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 605995ae..90142d9b 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -119,23 +119,10 @@ TrexStatelessPort::~TrexStatelessPort() { void TrexStatelessPort::acquire(const std::string &user, uint32_t session_id, bool force) { - /* if port is free - just take it */ - if (get_owner().is_free()) { - get_owner().own(user); - return; - } - - if (force) { - get_owner().own(user); - - /* inform the other client of the steal... */ - Json::Value data; + bool used_force = !get_owner().is_free() && force; - data["port_id"] = m_port_id; - data["who"] = user; - data["session_id"] = session_id; - - get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_FORCE_ACQUIRED, data); + if (get_owner().is_free() || force) { + get_owner().own(user, session_id); } else { /* not same user or session id and not force - report error */ @@ -146,11 +133,30 @@ TrexStatelessPort::acquire(const std::string &user, uint32_t session_id, bool fo } } + Json::Value data; + + data["port_id"] = m_port_id; + data["who"] = user; + data["session_id"] = session_id; + data["force"] = used_force; + + get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_ACQUIRED, data); + } void TrexStatelessPort::release(void) { + + + Json::Value data; + + data["port_id"] = m_port_id; + data["who"] = get_owner().get_name(); + data["session_id"] = get_owner().get_session_id(); + get_owner().release(); + + get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_RELEASED, data); } /** @@ -776,6 +782,7 @@ TrexStatelessPort::remove_and_delete_all_streams() { TrexPortOwner::TrexPortOwner() { m_is_free = true; + m_session_id = 0; /* for handlers random generation */ m_seed = time(NULL); diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 2167e735..520940d8 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -54,16 +54,18 @@ public: m_is_free = true; m_owner_name = ""; m_handler = ""; + m_session_id = 0; } bool is_owned_by(const std::string &user) { return ( !m_is_free && (m_owner_name == user) ); } - void own(const std::string &owner_name) { + void own(const std::string &owner_name, uint32_t session_id) { /* save user data */ m_owner_name = owner_name; + m_session_id = session_id; /* internal data */ m_handler = utl_generate_random_str(m_seed, 8); @@ -82,6 +84,9 @@ public: return (!m_is_free ? m_handler : g_unowned_handler); } + const uint32_t get_session_id() { + return m_session_id; + } private: @@ -91,6 +96,9 @@ private: /* user provided info */ std::string m_owner_name; + /* which session of the user holds this port*/ + uint32_t m_session_id; + /* handler genereated internally */ std::string m_handler; |