summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYaroslav Brustinov <ybrustin@cisco.com>2016-04-19 03:19:28 +0300
committerYaroslav Brustinov <ybrustin@cisco.com>2016-04-19 03:19:28 +0300
commit6840551a8733fefdd8b3f235e4a802524ecc39d9 (patch)
tree2208741daedb73a0e630cdd284091dd3b5c76633
parent6c46ecabec713485954dc7394e8a9808309fb4bc (diff)
parente6d1ca8bc126b2efc5a15268cd2d9926f1be3ab9 (diff)
Merge remote-tracking branch 'origin/master'
-rwxr-xr-xscripts/automation/trex_control_plane/doc_stl/api/client_code.rst5
-rwxr-xr-xscripts/automation/trex_control_plane/stl/console/trex_console.py35
-rw-r--r--scripts/automation/trex_control_plane/stl/console/trex_tui.py11
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py98
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py12
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py11
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_opts.py13
-rw-r--r--src/main_dpdk.cpp20
-rw-r--r--src/publisher/trex_publisher.h3
-rw-r--r--src/stateless/cp/trex_stateless.cpp2
-rw-r--r--src/stateless/cp/trex_stateless_port.cpp39
-rw-r--r--src/stateless/cp/trex_stateless_port.h10
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;