summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYaroslav Brustinov <ybrustin@cisco.com>2016-10-22 10:38:27 +0200
committerYaroslav Brustinov <ybrustin@cisco.com>2016-10-28 14:38:32 +0200
commit2dab6b6d09f9f1474d2ade6b465ebfa5ce3b3f5e (patch)
treebab2898d6b631d5495c62a8ad4b86ccea4eae786
parent00bfc58e6f76f7a67a6b62f297f72792534fef52 (diff)
dpdk_setup_ports.py: fix add of help in case of "t-rex-64 --help"
dpdk_setup_ports.py: fix warning of TRex is already running if different NICs are being used singleton_daemon.py: fix error socket in use immediately after check if in use trex-console: fix crash in case of "tui --help" trex-console: try-catch commands instead of crashing add async notification on port status/atttibutes change add port xstats support add description of interfaces main_dpdk.cpp: fix --client_cfg not working with Python API Signed-off-by: Yaroslav Brustinov <ybrustin@cisco.com>
-rwxr-xr-xscripts/automation/trex_control_plane/server/singleton_daemon.py1
-rwxr-xr-xscripts/automation/trex_control_plane/stl/console/trex_console.py37
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py45
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_jsonrpc_client.py2
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py59
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py144
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/common.py15
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/utils/constants.py26
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py43
-rwxr-xr-xscripts/dpdk_setup_ports.py23
-rw-r--r--src/dpdk/drivers/net/virtio/virtio_ethdev.c2
-rw-r--r--src/dpdk/drivers/net/vmxnet3/vmxnet3_ethdev.c2
-rw-r--r--src/internal_api/trex_platform_api.h45
-rw-r--r--src/main_dpdk.cpp138
-rw-r--r--src/pal/linux/rte_ethdev_includes.h23
-rw-r--r--src/pal/linux_dpdk/rte_ethdev_includes.h1
-rw-r--r--src/publisher/trex_publisher.h1
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_general.cpp39
-rw-r--r--src/stateless/cp/trex_stateless_port.cpp11
-rw-r--r--src/stateless/cp/trex_streams_compiler.h6
-rw-r--r--src/trex_defs.h1
-rwxr-xr-xsrc/trex_port_attr.h39
22 files changed, 492 insertions, 211 deletions
diff --git a/scripts/automation/trex_control_plane/server/singleton_daemon.py b/scripts/automation/trex_control_plane/server/singleton_daemon.py
index cd16d173..507967aa 100755
--- a/scripts/automation/trex_control_plane/server/singleton_daemon.py
+++ b/scripts/automation/trex_control_plane/server/singleton_daemon.py
@@ -37,6 +37,7 @@ class SingletonDaemon(object):
lock_socket.close()
except socket.error: # Unix socket in use
return True
+ sleep(0.5)
# Unix socket is not used, but maybe it's old version of daemon not using socket
return bool(self.get_pid_by_listening_port())
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 5d23d8da..b23b5f1f 100755
--- a/scripts/automation/trex_control_plane/stl/console/trex_console.py
+++ b/scripts/automation/trex_control_plane/stl/console/trex_console.py
@@ -230,14 +230,17 @@ class TRexConsole(TRexGeneralCmd):
self.save_console_history()
lines = line.split(';')
-
- for line in lines:
- stop = self.onecmd(line)
- stop = self.postcmd(stop, line)
- if stop:
- return "quit"
-
- return ""
+ try:
+ for line in lines:
+ stop = self.onecmd(line)
+ stop = self.postcmd(stop, line)
+ if stop:
+ return "quit"
+
+ return ""
+ except STLError as e:
+ print(e)
+ return ''
def postcmd(self, stop, line):
@@ -364,7 +367,7 @@ class TRexConsole(TRexGeneralCmd):
'help': "an history item index",
'default': 0})
- parser = parsing_opts.gen_parser(self,
+ parser = parsing_opts.gen_parser(self.stateless_client,
"history",
self.do_history.__doc__,
item)
@@ -551,16 +554,16 @@ class TRexConsole(TRexGeneralCmd):
@verify_connected
def do_tui (self, line):
'''Shows a graphical console\n'''
- parser = parsing_opts.gen_parser(self,
+ parser = parsing_opts.gen_parser(self.stateless_client,
"tui",
self.do_tui.__doc__,
parsing_opts.XTERM,
parsing_opts.LOCKED)
opts = parser.parse_args(line.split())
- if opts is None:
- return
+ if not opts:
+ return opts
if opts.xterm:
if not os.path.exists('/usr/bin/xterm'):
print(format_text("XTERM does not exists on this machine", 'bold'))
@@ -784,14 +787,18 @@ def show_intro (logger, c):
# 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:
+ if 'supp_speeds' in port:
+ speed = max(port['supp_speeds']) // 1000
+ else:
+ speed = port['speed']
+ key = (speed, port.get('description', port['driver']))
+ if key not 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])
+ port_line += "{0} x {1}Gbps @ {2}\t".format(v, k[0], k[1])
logger.log(format_text("\nServer Info:\n", 'underline'))
logger.log("Server version: {:>}".format(format_text(ver, 'bold')))
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 b11ddbe3..ec7e6eef 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
@@ -320,6 +320,13 @@ class EventsHandler(object):
ev = "port {0} job failed".format(port_id)
show_event = True
+ # port attr changed
+ elif (type == 8):
+ port_id = int(data['port_id'])
+ ev = "port {0} attributes changed".format(port_id)
+ show_event = True
+ self.__async_event_port_attr_changed(port_id, data['attr'])
+
# server stopped
elif (type == 100):
ev = "Server has stopped"
@@ -372,6 +379,9 @@ class EventsHandler(object):
def __async_event_server_stopped (self):
self.client.connected = False
+ def __async_event_port_attr_changed (self, port_id, attr):
+ if port_id in self.client.ports:
+ self.client.ports[port_id].async_event_port_attr_changed(attr)
# add event to log
def __add_event_log (self, origin, ev_type, msg, show = False):
@@ -887,7 +897,7 @@ class STLClient(object):
# clear stats
- def __clear_stats(self, port_id_list, clear_global, clear_flow_stats, clear_latency_stats):
+ def __clear_stats(self, port_id_list, clear_global, clear_flow_stats, clear_latency_stats, clear_xstats):
# we must be sync with the server
self.async_client.barrier()
@@ -904,6 +914,9 @@ class STLClient(object):
if clear_latency_stats:
self.latency_stats.clear_stats()
+ if clear_xstats:
+ self.xstats.clear_stats()
+
self.logger.log_cmd("Clearing stats on port(s) {0}:".format(port_id_list))
return RC
@@ -2501,6 +2514,9 @@ class STLClient(object):
clear_latency_stats : bool
Clear the latency stats
+ clear_xstats : bool
+ Clear the extended stats
+
:raises:
+ :exc:`STLError`
@@ -2513,7 +2529,7 @@ class STLClient(object):
if not type(clear_global) is bool:
raise STLArgumentError('clear_global', clear_global)
- rc = self.__clear_stats(ports, clear_global, clear_flow_stats, clear_latency_stats)
+ rc = self.__clear_stats(ports, clear_global, clear_flow_stats, clear_latency_stats, clear_xstats)
if not rc:
raise STLError(rc)
@@ -2605,7 +2621,7 @@ class STLClient(object):
flow_ctrl - 0: disable all, 1: enable tx side, 2: enable rx side, 3: full enable
:raises:
- None
+ + :exe:'STLError'
"""
@@ -3205,23 +3221,34 @@ class STLClient(object):
parsing_opts.LINK_STATUS,
parsing_opts.LED_STATUS,
parsing_opts.FLOW_CTRL,
+ parsing_opts.SUPPORTED,
)
opts = parser.parse_args(line.split(), default_ports = self.get_acquired_ports(), verify_acquired = True)
if not opts:
return opts
- opts.prom = parsing_opts.on_off_dict.get(opts.prom)
- opts.link = parsing_opts.on_off_dict.get(opts.link)
- opts.led = parsing_opts.on_off_dict.get(opts.led)
- opts.flow_ctrl = parsing_opts.flow_ctrl_dict.get(opts.flow_ctrl)
+ opts.prom = parsing_opts.ON_OFF_DICT.get(opts.prom)
+ opts.link = parsing_opts.UP_DOWN_DICT.get(opts.link)
+ opts.led = parsing_opts.ON_OFF_DICT.get(opts.led)
+ opts.flow_ctrl = parsing_opts.FLOW_CTRL_DICT.get(opts.flow_ctrl)
# if no attributes - fall back to printing the status
- if not filter(lambda x:x is not None, [opts.prom, opts.link, opts.led, opts.flow_ctrl]):
+ if not filter(lambda x:x is not None, [opts.prom, opts.link, opts.led, opts.flow_ctrl, opts.supp]):
self.show_stats_line("--ps --port {0}".format(' '.join(str(port) for port in opts.ports)))
return
- return self.set_port_attr(opts.ports, opts.prom, opts.link, opts.led, opts.flow_ctrl)
+ if opts.supp:
+ info = self.ports[0].get_info() # assume for now all ports are same
+ print('')
+ print('Supported attributes for current NICs:')
+ print(' Promiscuous: yes')
+ print(' Link status: %s' % info['link_change_supported'])
+ print(' LED status: %s' % info['led_change_supported'])
+ print(' Flow control: %s' % info['fc_supported'])
+ print('')
+ else:
+ return self.set_port_attr(opts.ports, opts.prom, opts.link, opts.led, opts.flow_ctrl)
@__console
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_jsonrpc_client.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_jsonrpc_client.py
index 609ea076..1461fcec 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_jsonrpc_client.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_jsonrpc_client.py
@@ -182,7 +182,7 @@ class JsonRpcClient(object):
tries += 1
if tries > 5:
self.disconnect()
- return RC_ERR("*** [RPC] - Failed to get server response at {0}".format(self.transport))
+ return RC_ERR("*** [RPC] - Failed to get server response from {0}".format(self.transport))
return response
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 f0e3b109..4a094c5d 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
@@ -5,6 +5,7 @@ from .trex_stl_packet_builder_scapy import STLPktBuilder
from .trex_stl_streams import STLStream
from .trex_stl_types import *
from . import trex_stl_stats
+from .utils.constants import FLOW_CTRL_DICT_REVERSED
import base64
import copy
@@ -250,9 +251,10 @@ class Port(object):
self.next_available_id = int(rc.data()['max_stream_id']) + 1
# attributes
- self.attr = rc.data()['attr']
+ self.attr = ['attr']
+ if 'speed' in rc.data():
+ self.info['speed'] = rc.data()['speed'] // 1000
-
return self.ok()
@@ -577,7 +579,7 @@ class Port(object):
return self.err(rc.err())
- self.attr.update(attr_dict)
+ #self.attr.update(attr_dict)
return self.ok()
@@ -650,13 +652,48 @@ class Port(object):
def get_info (self):
info = dict(self.info)
- info['status'] = self.get_port_state_name()
+ info['status'] = self.get_port_state_name()
+ if 'link' in self.attr:
+ info['link'] = 'UP' if self.attr['link']['up'] else 'DOWN'
+ else:
+ info['link'] = 'N/A'
+
+ if 'fc' in self.attr:
+ info['fc'] = FLOW_CTRL_DICT_REVERSED.get(self.attr['fc']['mode'], 'N/A')
+ else:
+ info['fc'] = 'N/A'
- if self.attr.get('promiscuous'):
+ if 'promiscuous' in self.attr:
info['prom'] = "on" if self.attr['promiscuous']['enabled'] else "off"
else:
info['prom'] = "N/A"
+ if 'description' in info:
+ if len(info['description']) > 18:
+ info['description'] = info['description'][:18]
+ else:
+ info['description'] = "N/A"
+
+ if 'is_fc_supported' in info:
+ info['fc_supported'] = 'yes' if info['is_fc_supported'] else 'no'
+ else:
+ info['fc_supported'] = 'N/A'
+
+ if 'is_led_supported' in info:
+ info['led_change_supported'] = 'yes' if info['is_led_supported'] else 'no'
+ else:
+ info['led_change_supported'] = 'N/A'
+
+ if 'is_link_supported' in info:
+ info['link_change_supported'] = 'yes' if info['is_link_supported'] else 'no'
+ else:
+ info['link_change_supported'] = 'N/A'
+
+ if 'is_virtual' in info:
+ info['is_virtual'] = 'yes' if info['is_virtual'] else 'no'
+ else:
+ info['is_virtual'] = 'N/A'
+
return info
@@ -672,6 +709,7 @@ class Port(object):
info = self.get_info()
return {"driver": info['driver'],
+ "description": info.get('description', 'N/A'),
"HW src mac": info['hw_macaddr'],
"SW src mac": info['src_macaddr'],
"SW dst mac": info['dst_macaddr'],
@@ -679,9 +717,10 @@ class Port(object):
"NUMA Node": info['numa'],
"--": "",
"---": "",
- "maximum": "{speed} Gb/s".format(speed=info['speed']),
- "status": info['status'],
- "promiscuous" : info['prom']
+ "link speed": "{speed} Gb/s".format(speed=info['speed']),
+ "status": '%s (link %s)' % (info['status'], info['link']),
+ "promiscuous" : info['prom'],
+ "flow ctrl" : info['fc'],
}
def clear_stats(self):
@@ -726,6 +765,10 @@ class Port(object):
self.state = self.STATE_STREAMS
self.last_factor_type = None
+ def async_event_port_attr_changed (self, attr):
+ self.info['speed'] = attr['speed'] // 1000
+ self.attr = attr
+
# rest of the events are used for TUI / read only sessions
def async_event_port_stopped (self):
if not self.is_acquired():
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 eaa5e8b0..783387ca 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
@@ -3,6 +3,7 @@
from .utils import text_tables
from .utils.text_opts import format_text, format_threshold, format_num
from .trex_stl_types import StatNotAvailable, is_integer
+from .trex_stl_exceptions import STLError
from collections import namedtuple, OrderedDict, deque
import sys
@@ -23,8 +24,10 @@ LATENCY_STATS = 'ls'
LATENCY_HISTOGRAM = 'lh'
CPU_STATS = 'c'
MBUF_STATS = 'm'
+EXTENDED_STATS = 'x'
+EXTENDED_INC_ZERO_STATS = 'xz'
-ALL_STATS_OPTS = [GLOBAL_STATS, PORT_STATS, PORT_STATUS, STREAMS_STATS, LATENCY_STATS, PORT_GRAPH, LATENCY_HISTOGRAM, CPU_STATS, MBUF_STATS]
+ALL_STATS_OPTS = [GLOBAL_STATS, PORT_STATS, PORT_STATUS, STREAMS_STATS, LATENCY_STATS, PORT_GRAPH, LATENCY_HISTOGRAM, CPU_STATS, MBUF_STATS, EXTENDED_STATS, EXTENDED_INC_ZERO_STATS]
COMPACT = [GLOBAL_STATS, PORT_STATS]
GRAPH_PORT_COMPACT = [GLOBAL_STATS, PORT_GRAPH]
SS_COMPAT = [GLOBAL_STATS, STREAMS_STATS] # stream stats
@@ -184,6 +187,12 @@ class CTRexInfoGenerator(object):
elif statistic_type == MBUF_STATS:
return self._generate_mbuf_util_stats()
+ elif statistic_type == EXTENDED_STATS:
+ return self._generate_xstats(port_id_list, include_zero_lines = False)
+
+ elif statistic_type == EXTENDED_INC_ZERO_STATS:
+ return self._generate_xstats(port_id_list, include_zero_lines = True)
+
else:
# ignore by returning empty object
return {}
@@ -206,7 +215,7 @@ class CTRexInfoGenerator(object):
def _generate_global_stats(self):
global_stats = self._global_stats
- stats_data = OrderedDict([("connection", "{host}, Port {port}".format(host=global_stats.connection_info.get("server"),
+ stats_data_left = OrderedDict([("connection", "{host}, Port {port}".format(host=global_stats.connection_info.get("server"),
port=global_stats.connection_info.get("sync_port"))),
("version", "{ver}, UUID: {uuid}".format(ver=global_stats.server_version.get("version", "N/A"),
uuid="N/A")),
@@ -222,14 +231,13 @@ class CTRexInfoGenerator(object):
("async_util.", "{0}% / {1}".format( format_threshold(round_float(self._async_monitor.get_cpu_util()), [85, 100], [0, 85]),
format_num(self._async_monitor.get_bps() / 8.0, suffix = "B/sec"))),
-
-
- (" ", ""),
+ ])
+ stats_data_right = OrderedDict([
("total_tx_L2", "{0} {1}".format( global_stats.get("m_tx_bps", format=True, suffix="b/sec"),
global_stats.get_trend_gui("m_tx_bps"))),
- ("total_tx_L1", "{0} {1}".format( global_stats.get("m_tx_bps_L1", format=True, suffix="b/sec"),
+ ("total_tx_L1", "{0} {1}".format( global_stats.get("m_tx_bps_L1", format=True, suffix="b/sec"),
global_stats.get_trend_gui("m_tx_bps_L1"))),
("total_rx", "{0} {1}".format( global_stats.get("m_rx_bps", format=True, suffix="b/sec"),
@@ -238,8 +246,6 @@ class CTRexInfoGenerator(object):
("total_pps", "{0} {1}".format( global_stats.get("m_tx_pps", format=True, suffix="pkt/sec"),
global_stats.get_trend_gui("m_tx_pps"))),
- #(" ", ""),
-
("drop_rate", "{0}".format( format_num(global_stats.get("m_rx_drop_bps"),
suffix = 'b/sec',
opts = 'green' if (global_stats.get("m_rx_drop_bps")== 0) else 'red'),
@@ -249,19 +255,29 @@ class CTRexInfoGenerator(object):
suffix = 'pkts',
compact = False,
opts = 'green' if (global_stats.get_rel("m_total_queue_full")== 0) else 'red'))),
-
- ]
- )
+ ])
# build table representation
stats_table = text_tables.TRexTextInfo()
stats_table.set_cols_align(["l", "l"])
+ stats_table.set_deco(0)
+ stats_table.set_cols_width([50, 45])
+ max_lines = max(len(stats_data_left), len(stats_data_right))
+ for line_num in range(max_lines):
+ row = []
+ if line_num < len(stats_data_left):
+ key = list(stats_data_left.keys())[line_num]
+ row.append('{:<12} : {}'.format(key, stats_data_left[key]))
+ else:
+ row.append('')
+ if line_num < len(stats_data_right):
+ key = list(stats_data_right.keys())[line_num]
+ row.append('{:<12} : {}'.format(key, stats_data_right[key]))
+ else:
+ row.append('')
+ stats_table.add_row(row)
- stats_table.add_rows([[k.replace("_", " ").title(), v]
- for k, v in stats_data.items()],
- header=False)
-
- return {"global_statistics": ExportableStats(stats_data, stats_table)}
+ return {"global_statistics": ExportableStats(None, stats_table)}
def _generate_streams_stats (self):
flow_stats = self._rx_stats_ref
@@ -505,6 +521,29 @@ class CTRexInfoGenerator(object):
stats_table.add_row(['No Data.'])
return {'mbuf_util': ExportableStats(None, stats_table)}
+ def _generate_xstats(self, port_id_list, include_zero_lines = False):
+ relevant_ports = [port.port_id for port in self.__get_relevant_ports(port_id_list)]
+ # get the data on relevant ports
+ xstats_data = OrderedDict()
+ for port_id in relevant_ports:
+ for key, val in self._xstats_ref.get_stats(port_id).items():
+ if key not in xstats_data:
+ xstats_data[key] = []
+ xstats_data[key].append(val)
+
+ # put into table
+ stats_table = text_tables.TRexTextTable()
+ stats_table.header(['Name:'] + ['Port %s:' % port_id for port_id in relevant_ports])
+ stats_table.set_cols_align(['l'] + ['r'] * len(relevant_ports))
+ stats_table.set_cols_width([30] + [15] * len(relevant_ports))
+ stats_table.set_cols_dtype(['t'] * (len(relevant_ports) + 1))
+ for key, arr in xstats_data.items():
+ if include_zero_lines or list(filter(None, arr)):
+ if len(key) > 28:
+ key = key[:28]
+ stats_table.add_row([key] + arr)
+ return {'xstats:': ExportableStats(None, stats_table)}
+
@staticmethod
def _get_rational_block_char(value, range_start, interval):
# in Konsole, utf-8 is sometimes printed with artifacts, return ascii for now
@@ -558,6 +597,7 @@ class CTRexInfoGenerator(object):
return_stats_data = {}
per_field_stats = OrderedDict([("owner", []),
+ ('link', []),
("state", []),
("speed", []),
("CPU util.", []),
@@ -585,8 +625,7 @@ class CTRexInfoGenerator(object):
("oerrors", []),
("ierrors", []),
- ]
- )
+ ])
total_stats = CPortStats(None)
@@ -626,9 +665,11 @@ class CTRexInfoGenerator(object):
return_stats_data = {}
per_field_status = OrderedDict([("driver", []),
- ("maximum", []),
+ ("description", []),
+ ("link speed", []),
("status", []),
("promiscuous", []),
+ ("flow ctrl", []),
("--", []),
("HW src mac", []),
("SW src mac", []),
@@ -1054,13 +1095,24 @@ class CPortStats(CTRexStats):
def generate_stats(self):
- state = self._port_obj.get_port_state_name() if self._port_obj else ""
- if state == "ACTIVE":
- state = format_text(state, 'green', 'bold')
- elif state == "PAUSE":
- state = format_text(state, 'magenta', 'bold')
+ port_state = self._port_obj.get_port_state_name() if self._port_obj else ""
+ if port_state == "ACTIVE":
+ port_state = format_text('TRANSMITTING', 'green', 'bold')
+ elif port_state == "PAUSE":
+ port_state = format_text(port_state, 'magenta', 'bold')
+ else:
+ port_state = format_text(port_state, 'bold')
+
+ if self._port_obj:
+ if 'link' in self._port_obj.attr:
+ if self._port_obj.attr.get('link', {}).get('up') == False:
+ link_state = format_text('DOWN', 'red', 'bold')
+ else:
+ link_state = 'UP'
+ else:
+ link_state = 'N/A'
else:
- state = format_text(state, 'bold')
+ link_state = ''
# default rate format modifiers
rate_format = {'bpsl1': None, 'bps': None, 'pps': None, 'percentage': 'bold'}
@@ -1077,7 +1129,8 @@ class CPortStats(CTRexStats):
return {"owner": owner,
- "state": "{0}".format(state),
+ "state": "{0}".format(port_state),
+ 'link': link_state,
"speed": self._port_obj.get_formatted_speed() if self._port_obj else '',
"CPU util.": "{0} {1}%".format(self.get_trend_gui("m_cpu_util", use_raw = True),
format_threshold(round_float(self.get("m_cpu_util")), [85, 100], [0, 85])) if self._port_obj else '' ,
@@ -1439,7 +1492,7 @@ class CUtilStats(CTRexStats):
if self.client.is_connected():
rc = self.client._transmit('get_utilization')
if not rc:
- raise Exception(rc)
+ raise STLError(rc)
self.last_update_ts = time_now
self.history.append(rc.data())
else:
@@ -1452,33 +1505,44 @@ class CXStats(CTRexStats):
def __init__(self, client):
super(CXStats, self).__init__()
self.client = client
- self.history = deque(maxlen = 1)
- self.names = {}
+ self.names = []
self.last_update_ts = -999
- def get_stats(self, port_id, use_1sec_cache = False):
+ def clear_stats(self, port_id = None):
+ if port_id == None:
+ ports = self.client.get_all_ports()
+ elif type(port_id) is list:
+ ports = port_id
+ else:
+ ports = [port_id]
+
+ for port_id in ports:
+ self.reference_stats[port_id] = self.get_stats(port_id, relative = False)
+
+ def get_stats(self, port_id, use_1sec_cache = False, relative = True):
time_now = time.time()
- if self.last_update_ts + 1 < time_now or not self.history or not use_1sec_cache:
+ if self.last_update_ts + 1 < time_now or not self.latest_stats or not use_1sec_cache:
if self.client.is_connected():
rc = self.client._transmit('get_port_xstats_values', params = {'port_id': port_id})
if not rc:
- raise Exception(rc)
+ raise STLError(rc)
self.last_update_ts = time_now
values = rc.data().get('xstats_values', [])
if len(values) != len(self.names): # need to update names ("keys")
rc = self.client._transmit('get_port_xstats_names', params = {'port_id': port_id})
if not rc:
- raise Exception(rc)
+ raise STLError(rc)
self.names = rc.data().get('xstats_names', [])
if len(values) != len(self.names):
- raise Exception('Length of get_xstats_names: %s and get_port_xstats_values: %s' % (len(self.names), len(values)))
- self.history.append(dict([(key, val) for key, val in zip(self.names, values)]))
- else:
- self.history.append({})
+ raise STLError('Length of get_xstats_names: %s and get_port_xstats_values: %s' % (len(self.names), len(values)))
+ self.latest_stats[port_id] = OrderedDict([(key, val) for key, val in zip(self.names, values)])
- stats = {}
- for key, val in self.history[-1].items():
- stats[key] = self.history[-1][key] - self.reference_stats.get(key, 0)
+ stats = OrderedDict()
+ for key, val in self.latest_stats[port_id].items():
+ if relative:
+ stats[key] = self.get_rel([port_id, key])
+ else:
+ stats[key] = self.get([port_id, key])
return stats
if __name__ == "__main__":
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/common.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/common.py
index 638684c3..0214d7d7 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/common.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/common.py
@@ -27,7 +27,7 @@ def user_input():
return raw_input()
-def random_id_gen(length=8):
+def random_id_gen_unsafe(length=8):
"""
A generator for creating a random chars id of specific length
@@ -47,6 +47,19 @@ def random_id_gen(length=8):
return_id += random.choice(id_chars)
yield return_id
+
+class random_id_gen:
+ """ Thread safe version of random_id_gen_unsafe """
+ def __init__(self, length=8):
+ self.id_chars = string.ascii_lowercase + string.digits
+ self.length = length
+
+ def next(self):
+ return ''.join(random.choice(self.id_chars) for _ in range(self.length))
+
+ __next__ = next
+
+
# try to get number from input, return None in case of fail
def get_number(input):
try:
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/constants.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/constants.py
new file mode 100755
index 00000000..a4942094
--- /dev/null
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/constants.py
@@ -0,0 +1,26 @@
+from collections import OrderedDict
+
+ON_OFF_DICT = OrderedDict([
+ ('on', True),
+ ('off', False),
+])
+
+UP_DOWN_DICT = OrderedDict([
+ ('up', True),
+ ('down', False),
+])
+
+FLOW_CTRL_DICT = OrderedDict([
+ ('none', 0), # Disable flow control
+ ('tx', 1), # Enable flowctrl on TX side (RX pause frames)
+ ('rx', 2), # Enable flowctrl on RX side (TX pause frames)
+ ('full', 3), # Enable flow control on both sides
+])
+
+
+
+# generate reverse dicts
+
+for var_name in list(vars().keys()):
+ if var_name.endswith('_DICT'):
+ exec('{0}_REVERSED = OrderedDict([(val, key) for key, val in {0}.items()])'.format(var_name))
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py
index 148f7715..7eda8635 100755
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py
@@ -3,6 +3,7 @@ from collections import namedtuple, OrderedDict
from .common import list_intersect, list_difference
from .text_opts import format_text
from ..trex_stl_types import *
+from .constants import ON_OFF_DICT, UP_DOWN_DICT, FLOW_CTRL_DICT
import sys
import re
@@ -11,18 +12,6 @@ import os
ArgumentPack = namedtuple('ArgumentPack', ['name_or_flags', 'options'])
ArgumentGroup = namedtuple('ArgumentGroup', ['type', 'args', 'options'])
-on_off_dict = OrderedDict([
- ('on', True),
- ('off', False),
-])
-
-flow_ctrl_dict = OrderedDict([
- ('none', 0), # Disable flow control
- ('tx', 1), # Enable flowctrl on TX side (RX pause frames)
- ('rx', 2), # Enable flowctrl on RX side (TX pause frames)
- ('full', 3), # Enable flow control on both sides
-])
-
# list of available parsing options
MULTIPLIER = 1
@@ -53,6 +42,7 @@ PIN_CORES = 25
CORE_MASK = 26
DUAL = 27
FLOW_CTRL = 28
+SUPPORTED = 29
GLOBAL_STATS = 50
PORT_STATS = 51
@@ -61,6 +51,8 @@ STREAMS_STATS = 53
STATS_MASK = 54
CPU_STATS = 55
MBUF_STATS = 56
+EXTENDED_STATS = 57
+EXTENDED_INC_ZERO_STATS = 58
STREAMS_MASK = 60
CORE_MASK_GROUP = 61
@@ -296,20 +288,25 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
PROMISCUOUS: ArgumentPack(['--prom'],
{'help': "Set port promiscuous on/off",
- 'choices': on_off_dict}),
+ 'choices': ON_OFF_DICT}),
LINK_STATUS: ArgumentPack(['--link'],
- {'help': 'Set link status on/off',
- 'choices': on_off_dict}),
+ {'help': 'Set link status up/down',
+ 'choices': UP_DOWN_DICT}),
LED_STATUS: ArgumentPack(['--led'],
{'help': 'Set LED status on/off',
- 'choices': on_off_dict}),
+ 'choices': ON_OFF_DICT}),
FLOW_CTRL: ArgumentPack(['--fc'],
{'help': 'Set Flow Control type',
'dest': 'flow_ctrl',
- 'choices': flow_ctrl_dict}),
+ 'choices': FLOW_CTRL_DICT}),
+
+ SUPPORTED: ArgumentPack(['--supp'],
+ {'help': 'Show which attributes are supported by current NICs',
+ 'default': None,
+ 'action': 'store_true'}),
TUNABLES: ArgumentPack(['-t'],
{'help': "Sets tunables for a profile. Example: '-t fsize=100,pg_id=7'",
@@ -419,6 +416,14 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
{'action': 'store_true',
'help': "Fetch only MBUF utilization stats"}),
+ EXTENDED_STATS: ArgumentPack(['-x'],
+ {'action': 'store_true',
+ 'help': "Fetch xstats of port, excluding lines with zero values"}),
+
+ EXTENDED_INC_ZERO_STATS: ArgumentPack(['--xz'],
+ {'action': 'store_true',
+ 'help': "Fetch xstats of port, including lines with zero values"}),
+
STREAMS_MASK: ArgumentPack(['--streams'],
{"nargs": '+',
'dest':'streams',
@@ -455,7 +460,9 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
PORT_STATUS,
STREAMS_STATS,
CPU_STATS,
- MBUF_STATS],
+ MBUF_STATS,
+ EXTENDED_STATS,
+ EXTENDED_INC_ZERO_STATS,],
{}),
diff --git a/scripts/dpdk_setup_ports.py b/scripts/dpdk_setup_ports.py
index 2782384c..5bbbdb28 100755
--- a/scripts/dpdk_setup_ports.py
+++ b/scripts/dpdk_setup_ports.py
@@ -358,11 +358,13 @@ Other network devices
if if_list and map_driver.args.parent and dpdk_nic_bind.get_igb_uio_usage():
pid = dpdk_nic_bind.get_pid_using_pci(if_list)
- cmdline = dpdk_nic_bind.read_pid_cmdline(pid)
- print('Some or all of given interfaces are in use by following process:\npid: %s, cmd: %s' % (pid, cmdline))
- if not dpdk_nic_bind.confirm('Ignore and proceed (y/N):'):
- sys.exit(1)
-
+ if pid:
+ cmdline = dpdk_nic_bind.read_pid_cmdline(pid)
+ print('Some or all of given interfaces are in use by following process:\npid: %s, cmd: %s' % (pid, cmdline))
+ if not dpdk_nic_bind.confirm('Ignore and proceed (y/N):'):
+ sys.exit(1)
+ else:
+ print('WARNING: Some other program is using DPDK driver.\nIf it is TRex and you did not configure it for dual run, current command will fail.')
def do_return_to_linux(self):
if not self.m_devices:
@@ -459,11 +461,14 @@ Other network devices
wanted_interfaces.append(dev)
unbound = []
+ dpdk_bound = []
for interface in wanted_interfaces:
if 'Driver_str' not in interface:
unbound.append(interface['Slot'])
- if unbound:
- for pci, info in dpdk_nic_bind.get_info_from_trex(unbound).items():
+ elif interface.get('Driver_str') in dpdk_nic_bind.dpdk_drivers:
+ dpdk_bound.append(interface['Slot'])
+ if unbound or dpdk_bound:
+ for pci, info in dpdk_nic_bind.get_info_from_trex(unbound + dpdk_bound).items():
if pci not in self.m_devices:
raise DpdkSetup('Internal error: PCI %s is not found among devices' % pci)
self.m_devices[pci].update(info)
@@ -653,7 +658,7 @@ Other network devices
def parse_parent_cfg (parent_cfg):
- parent_parser = argparse.ArgumentParser()
+ parent_parser = argparse.ArgumentParser(add_help = False)
parent_parser.add_argument('--cfg', default='')
parent_parser.add_argument('--dump-interfaces', nargs='*', default=None)
args, unkown = parent_parser.parse_known_args(shlex.split(parent_cfg))
@@ -699,7 +704,7 @@ To see more detailed info on interfaces (table):
help=argparse.SUPPRESS
)
- parser.add_argument('--dump-pci-description', help='suppress', dest='dump_pci_desc', action='store_true')
+ parser.add_argument('--dump-pci-description', help=argparse.SUPPRESS, dest='dump_pci_desc', action='store_true')
parser.add_argument("-i", "--interactive", action='store_true',
help=""" Create TRex config in interactive mode """,
diff --git a/src/dpdk/drivers/net/virtio/virtio_ethdev.c b/src/dpdk/drivers/net/virtio/virtio_ethdev.c
index 07d64497..35e67b90 100644
--- a/src/dpdk/drivers/net/virtio/virtio_ethdev.c
+++ b/src/dpdk/drivers/net/virtio/virtio_ethdev.c
@@ -1550,6 +1550,8 @@ virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
dev_info->default_txconf = (struct rte_eth_txconf) {
.txq_flags = ETH_TXQ_FLAGS_NOOFFLOADS
};
+ /* TRex patch */
+ dev_info->speed_capa = ETH_LINK_SPEED_10G;
}
/*
diff --git a/src/dpdk/drivers/net/vmxnet3/vmxnet3_ethdev.c b/src/dpdk/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 58742153..47fdc3ec 100644
--- a/src/dpdk/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/src/dpdk/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -706,6 +706,8 @@ vmxnet3_dev_info_get(__attribute__((unused))struct rte_eth_dev *dev,
dev_info->min_rx_bufsize = 1518 + RTE_PKTMBUF_HEADROOM;
dev_info->max_rx_pktlen = 16384; /* includes CRC, cf MAXFRS register */
dev_info->max_mac_addrs = VMXNET3_MAX_MAC_ADDRS;
+ /* TRex patch */
+ dev_info->speed_capa = ETH_LINK_SPEED_10G;
dev_info->default_txconf.txq_flags = ETH_TXQ_FLAGS_NOXSUMSCTP;
dev_info->flow_type_rss_offloads = VMXNET3_RSS_OFFLOAD_ALL;
diff --git a/src/internal_api/trex_platform_api.h b/src/internal_api/trex_platform_api.h
index 998b6d49..0141186e 100644
--- a/src/internal_api/trex_platform_api.h
+++ b/src/internal_api/trex_platform_api.h
@@ -28,6 +28,7 @@ limitations under the License.
#include <string.h>
#include "flow_stat_parser.h"
#include "trex_defs.h"
+#include "trex_port_attr.h"
#include <json/json.h>
/**
@@ -136,6 +137,7 @@ public:
virtual void get_interface_info(uint8_t interface_id, intf_info_st &info) const = 0;
virtual void publish_async_data_now(uint32_t key, bool baseline) const = 0;
+ virtual void publish_async_port_attr_changed(uint8_t port_id) const = 0;
virtual uint8_t get_dp_core_count() const = 0;
virtual void get_interface_stat_info(uint8_t interface_id, uint16_t &num_counters, uint16_t &capabilities) const =0;
virtual int get_flow_stats(uint8_t port_id, void *stats, void *tx_stats, int min, int max, bool reset
@@ -148,22 +150,15 @@ public:
, uint8_t ipv6_next_h, uint16_t id) const = 0;
virtual int del_rx_flow_stat_rule(uint8_t port_id, uint16_t l3_type, uint8_t l4_proto
, uint8_t ipv6_next_h, uint16_t id) const = 0;
- virtual int set_promiscuous(uint8_t port_id, bool enabled) const = 0;
- virtual int set_link_status(uint8_t port_id, bool up) const = 0;
- virtual bool get_promiscuous(uint8_t port_id) const = 0;
- virtual bool get_link_status(uint8_t port_id) const = 0;
virtual void flush_dp_messages() const = 0;
virtual int get_active_pgids(flow_stat_active_t &result) const = 0;
virtual int get_cpu_util_full(cpu_util_full_t &result) const = 0;
virtual int get_mbuf_util(Json::Value &result) const = 0;
virtual CFlowStatParser *get_flow_stat_parser() const = 0;
+ virtual TRexPortAttr *getPortAttrObj() const = 0;
virtual void mark_for_shutdown() const = 0;
virtual int get_xstats_values(uint8_t port_id, xstats_values_t &xstats_values) const = 0;
virtual int get_xstats_names(uint8_t port_id, xstats_names_t &xstats_names) const = 0;
- virtual int get_flow_ctrl(uint8_t port_id, int &mode) const = 0;
- virtual int set_flow_ctrl(uint8_t port_id, int mode) const = 0;
- virtual int set_led_status(uint8_t port_id, bool on) const = 0;
- virtual uint32_t get_link_speed(uint8_t port_id) const = 0;
virtual ~TrexPlatformApi() {}
};
@@ -183,6 +178,7 @@ public:
void get_interface_info(uint8_t interface_id, intf_info_st &info) const;
void publish_async_data_now(uint32_t key, bool baseline) const;
+ void publish_async_port_attr_changed(uint8_t port_id) const;
uint8_t get_dp_core_count() const;
void get_interface_stat_info(uint8_t interface_id, uint16_t &num_counters, uint16_t &capabilities) const;
int get_flow_stats(uint8_t port_id, void *stats, void *tx_stats, int min, int max, bool reset
@@ -195,23 +191,16 @@ public:
, uint8_t ipv6_next_h, uint16_t id) const;
virtual int del_rx_flow_stat_rule(uint8_t port_id, uint16_t l3_type, uint8_t l4_proto
, uint8_t ipv6_next_h, uint16_t id) const;
- int set_promiscuous(uint8_t port_id, bool enabled) const;
- int set_link_status(uint8_t port_id, bool up) const;
- bool get_promiscuous(uint8_t port_id) const;
- bool get_link_status(uint8_t port_id) const;
void flush_dp_messages() const;
int get_active_pgids(flow_stat_active_t &result) const;
int get_cpu_util_full(cpu_util_full_t &result) const;
int get_mbuf_util(Json::Value &result) const;
void mark_for_shutdown() const;
CFlowStatParser *get_flow_stat_parser() const;
+ TRexPortAttr *getPortAttrObj() const;
int get_xstats_values(uint8_t port_id, xstats_values_t &xstats_values) const;
int get_xstats_names(uint8_t port_id, xstats_names_t &xstats_names) const;
- int get_flow_ctrl(uint8_t port_id, int &mode) const;
- int set_flow_ctrl(uint8_t port_id, int mode) const;
- int set_led_status(uint8_t port_id, bool on) const;
- uint32_t get_link_speed(uint8_t port_id) const;
};
@@ -256,6 +245,10 @@ public:
virtual void publish_async_data_now(uint32_t key, bool baseline) const {
}
+
+ virtual void publish_async_port_attr_changed(uint8_t port_id) const {
+ }
+
int get_flow_stats(uint8_t port_id, void *stats, void *tx_stats, int min, int max, bool reset
, TrexPlatformApi::driver_stat_cap_e type) const {return 0;};
virtual int get_rfc2544_info(void *rfc2544_info, int min, int max, bool reset) const {return 0;};
@@ -266,18 +259,6 @@ public:
, uint8_t ipv6_next_h, uint16_t id) const {return 0;};
virtual int del_rx_flow_stat_rule(uint8_t port_id, uint16_t l3_type, uint8_t l4_proto
, uint8_t ipv6_next_h, uint16_t id) const {return 0;};
- int set_promiscuous(uint8_t port_id, bool enabled) const {
- return 0;
- }
- int set_link_status(uint8_t port_id, bool on) const {
- return 0;
- }
- bool get_promiscuous(uint8_t port_id) const {
- return false;
- }
- bool get_link_status(uint8_t port_id) const {
- return false;
- }
void flush_dp_messages() const {
}
@@ -285,17 +266,11 @@ public:
int get_cpu_util_full(cpu_util_full_t &result) const {return 0;}
int get_mbuf_util(Json::Value &result) const {return 0;}
CFlowStatParser *get_flow_stat_parser() const {return new CFlowStatParser();}
+ TRexPortAttr *getPortAttrObj() const {printf("Port attributes should not be used in simulation\n"); return NULL;} // dummy
void mark_for_shutdown() const {}
int get_xstats_values(uint8_t port_id, xstats_values_t &xstats_values) const {return 0;};
int get_xstats_names(uint8_t port_id, xstats_names_t &xstats_names) const {return 0;};
- int get_flow_ctrl(uint8_t port_id, int &mode) const {return 0;};
- int set_flow_ctrl(uint8_t port_id, int mode) const {return 0;};
- int set_led_status(uint8_t port_id, bool on) const {return 0;};
- uint32_t get_link_speed(uint8_t port_id) const {
- return 0;
- }
-
private:
int m_dp_core_count;
diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp
index 9ef08cf1..cd4c782b 100644
--- a/src/main_dpdk.cpp
+++ b/src/main_dpdk.cpp
@@ -159,7 +159,7 @@ public:
virtual void clear_extended_stats(CPhyEthIF * _if)=0;
virtual int wait_for_stable_link();
virtual void wait_after_link_up();
- virtual bool flow_control_disable_supported(){return true;}
+ virtual bool flow_control_disable_supported(){return m_port_attr->is_fc_change_supported();}
virtual bool hw_rx_stat_supported(){return false;}
virtual int get_rx_stats(CPhyEthIF * _if, uint32_t *pkts, uint32_t *prev_pkts, uint32_t *bytes, uint32_t *prev_bytes
, int min, int max) {return -1;}
@@ -178,7 +178,7 @@ class CTRexExtendedDriverBase1G : public CTRexExtendedDriverBase {
public:
CTRexExtendedDriverBase1G(){
- m_port_attr = new TRexPortAttr(global_platform_cfg_info.m_if_list.size(), false);
+ m_port_attr = new TRexPortAttr(global_platform_cfg_info.m_if_list.size(), false, true);
}
static CTRexExtendedDriverBase * create(){
@@ -224,7 +224,7 @@ public:
CTRexExtendedDriverBase1GVm(){
/* we are working in mode that we have 1 queue for rx and one queue for tx*/
CGlobalInfo::m_options.preview.set_vm_one_queue_enable(true);
- m_port_attr = new TRexPortAttr(global_platform_cfg_info.m_if_list.size(), true);
+ m_port_attr = new TRexPortAttr(global_platform_cfg_info.m_if_list.size(), true, true);
}
virtual bool has_crc_added() {
@@ -270,7 +270,7 @@ public:
class CTRexExtendedDriverBase10G : public CTRexExtendedDriverBase {
public:
CTRexExtendedDriverBase10G(){
- m_port_attr = new TRexPortAttr(global_platform_cfg_info.m_if_list.size(), false);
+ m_port_attr = new TRexPortAttr(global_platform_cfg_info.m_if_list.size(), false, true);
}
static CTRexExtendedDriverBase * create(){
@@ -312,7 +312,8 @@ public:
// If we want to support more counters in case of card having less interfaces, we
// Will have to identify the number of interfaces dynamically.
m_if_per_card = 4;
- m_port_attr = new TRexPortAttr(global_platform_cfg_info.m_if_list.size(), false);
+ // disabling flow control on 40G using DPDK API causes the interface to malfunction
+ m_port_attr = new TRexPortAttr(global_platform_cfg_info.m_if_list.size(), false, false);
}
static CTRexExtendedDriverBase * create(){
@@ -342,8 +343,6 @@ public:
return TrexPlatformApi::IF_STAT_IPV4_ID | TrexPlatformApi::IF_STAT_PAYLOAD;
}
virtual int wait_for_stable_link();
- // disabling flow control on 40G using DPDK API causes the interface to malfunction
- virtual bool flow_control_disable_supported(){return false;}
virtual bool hw_rx_stat_supported(){return true;}
virtual int verify_fw_ver(int i);
virtual CFlowStatParser *get_flow_stat_parser();
@@ -362,7 +361,7 @@ private:
class CTRexExtendedDriverBaseVIC : public CTRexExtendedDriverBase40G {
public:
CTRexExtendedDriverBaseVIC(){
- m_port_attr = new TRexPortAttr(global_platform_cfg_info.m_if_list.size(), false);
+ m_port_attr = new TRexPortAttr(global_platform_cfg_info.m_if_list.size(), false, false);
}
static CTRexExtendedDriverBase * create(){
@@ -375,8 +374,6 @@ public:
virtual int verify_fw_ver(int i) {return 0;}
- bool flow_control_disable_supported(){return false;}
-
virtual void update_configuration(port_cfg_t * cfg);
};
@@ -599,6 +596,7 @@ static CSimpleOpt::SOption parser_options[] =
{ OPT_NO_FLOW_CONTROL, "--no-flow-control-change", SO_NONE },
{ OPT_VLAN, "--vlan", SO_NONE },
{ OPT_CLIENT_CFG_FILE, "--client_cfg", SO_REQ_SEP },
+ { OPT_CLIENT_CFG_FILE, "--client-cfg", SO_REQ_SEP },
{ OPT_NO_KEYBOARD_INPUT ,"--no-key", SO_NONE },
{ OPT_VIRT_ONE_TX_RX_QUEUE, "--vm-sim", SO_NONE },
{ OPT_PREFIX, "--prefix", SO_REQ_SEP },
@@ -1453,8 +1451,11 @@ void CPhyEthIF::disable_flow_control(){
ret, m_port_id);
}
-// Get user frienly devices description from saved env. var
-void TRexPortAttr::update_info(){
+/*
+Get user frienly devices description from saved env. var
+Changes certain attributes based on description
+*/
+void TRexPortAttr::update_descriptions(){
struct rte_pci_addr pci_addr;
char pci[16];
char * envvar;
@@ -1472,6 +1473,13 @@ void TRexPortAttr::update_info(){
} else {
intf_info_st[port_id].description = "Unknown";
}
+ if (intf_info_st[port_id].description.find("82599ES") != std::string::npos) { // works for 82599EB etc. DPDK does not distinguish them
+ flag_is_link_change_supported = false;
+ }
+ if (intf_info_st[port_id].description.find("82545EM") != std::string::npos) { // in virtual E1000, DPDK claims fc is supported, but it's not
+ flag_is_fc_change_supported = false;
+ flag_is_led_change_supported = false;
+ }
if ( CGlobalInfo::m_options.preview.getVMode() > 0){
printf("port %d desc: %s\n", port_id, intf_info_st[port_id].description.c_str());
}
@@ -1486,21 +1494,21 @@ int TRexPortAttr::set_led(uint8_t port_id, bool on){
}
}
-int TRexPortAttr::get_flow_ctrl(uint8_t port_id, enum rte_eth_fc_mode *mode) {
+int TRexPortAttr::get_flow_ctrl(uint8_t port_id, int &mode) {
int ret = rte_eth_dev_flow_ctrl_get(port_id, &fc_conf_tmp);
if (ret) {
return ret;
}
- *mode = fc_conf_tmp.mode;
+ mode = (int) fc_conf_tmp.mode;
return 0;
}
-int TRexPortAttr::set_flow_ctrl(uint8_t port_id, const enum rte_eth_fc_mode mode) {
+int TRexPortAttr::set_flow_ctrl(uint8_t port_id, int mode) {
int ret = rte_eth_dev_flow_ctrl_get(port_id, &fc_conf_tmp);
if (ret) {
return ret;
}
- fc_conf_tmp.mode = mode;
+ fc_conf_tmp.mode = (enum rte_eth_fc_mode) mode;
return rte_eth_dev_flow_ctrl_set(port_id, &fc_conf_tmp);
}
@@ -1558,12 +1566,38 @@ void TRexPortAttr::dump_link(uint8_t port_id, FILE *fd){
fprintf(fd,"promiscuous : %d \n",get_promiscuous(port_id));
}
+void TRexPortAttr::update_device_info(uint8_t port_id){
+ rte_eth_dev_info_get(port_id, &dev_info[port_id]);
+}
+
+void TRexPortAttr::get_supported_speeds(uint8_t port_id, supp_speeds_t &supp_speeds){
+ uint32_t speed_capa = dev_info[port_id].speed_capa;
+ if (speed_capa & ETH_LINK_SPEED_1G)
+ supp_speeds.push_back(ETH_SPEED_NUM_1G);
+ if (speed_capa & ETH_LINK_SPEED_10G)
+ supp_speeds.push_back(ETH_SPEED_NUM_10G);
+ if (speed_capa & ETH_LINK_SPEED_40G)
+ supp_speeds.push_back(ETH_SPEED_NUM_40G);
+ if (speed_capa & ETH_LINK_SPEED_100G)
+ supp_speeds.push_back(ETH_SPEED_NUM_100G);
+}
+
void TRexPortAttr::update_link_status(uint8_t port_id){
rte_eth_link_get(port_id, &m_link[port_id]);
}
-void TRexPortAttr::update_link_status_nowait(uint8_t port_id){
- rte_eth_link_get_nowait(port_id, &m_link[port_id]);
+bool TRexPortAttr::update_link_status_nowait(uint8_t port_id){
+ rte_eth_link new_link;
+ bool changed = false;
+ rte_eth_link_get_nowait(port_id, &new_link);
+ if (new_link.link_speed != m_link[port_id].link_speed ||
+ new_link.link_duplex != m_link[port_id].link_duplex ||
+ new_link.link_autoneg != m_link[port_id].link_autoneg ||
+ new_link.link_status != m_link[port_id].link_status) {
+ changed = true;
+ }
+ m_link[port_id] = new_link;
+ return changed;
}
int TRexPortAttr::add_mac(uint8_t port_id, char * mac){
@@ -2941,6 +2975,7 @@ public:
void publish_async_data(bool sync_now, bool baseline = false);
void publish_async_barrier(uint32_t key);
+ void publish_async_port_attr_changed(uint8_t port_id);
void dump_stats(FILE *fd,
CGlobalStats::DumpFormat format);
@@ -3364,7 +3399,7 @@ int CGlobalTRex::ixgbe_start(void){
/* wait for ports to be stable */
get_ex_drv()->wait_for_stable_link();
- if ( !is_all_links_are_up(true) && !get_is_stateless()){
+ if ( !is_all_links_are_up(true) /*&& !get_is_stateless()*/ ){ // disable start with link down for now
dump_links_status(stdout);
rte_exit(EXIT_FAILURE, " "
" one of the link is down \n");
@@ -3597,7 +3632,6 @@ int CGlobalTRex::ixgbe_prob_init(void){
CTRexExtendedDriverDb::Ins()->set_driver_name(dev_info.driver_name);
m_drv = CTRexExtendedDriverDb::Ins()->get_drv();
m_port_attr = m_drv->m_port_attr;
- m_port_attr->update_info();
// check if firmware version is new enough
for (i = 0; i < m_max_ports; i++) {
@@ -4120,6 +4154,24 @@ CGlobalTRex::publish_async_barrier(uint32_t key) {
m_zmq_publisher.publish_barrier(key);
}
+void
+CGlobalTRex:: publish_async_port_attr_changed(uint8_t port_id) {
+ Json::Value data;
+ data["port_id"] = port_id;
+
+ /* attributes */
+ data["attr"]["speed"] = m_port_attr->get_link_speed(port_id);
+ data["attr"]["promiscuous"]["enabled"] = m_port_attr->get_promiscuous(port_id);
+ data["attr"]["link"]["up"] = m_port_attr->is_link_up(port_id);
+ int mode;
+ int ret = get_stateless_obj()->get_platform_api()->getPortAttrObj()->get_flow_ctrl(port_id, mode);
+ if (ret != 0) {
+ mode = -1;
+ }
+ data["attr"]["fc"]["mode"] = mode;
+
+ m_zmq_publisher.publish_event(TrexPublisher::EVENT_PORT_ATTR_CHANGED, data);
+}
void
CGlobalTRex::handle_slow_path() {
@@ -4127,7 +4179,10 @@ CGlobalTRex::handle_slow_path() {
// update speed, link up/down etc.
for (int i=0; i<m_max_ports; i++) {
- m_port_attr->update_link_status_nowait(i);
+ bool changed = m_port_attr->update_link_status_nowait(i);
+ if (changed) {
+ publish_async_port_attr_changed(i);
+ }
}
if ( CGlobalInfo::m_options.preview.get_no_keyboard() ==false ) {
@@ -6334,12 +6389,6 @@ int TrexDpdkPlatformApi::get_xstats_names(uint8_t port_id, xstats_names_t &xstat
return g_trex.m_port_attr->get_xstats_names(port_id, xstats_names);
}
-int TrexDpdkPlatformApi::get_flow_ctrl(uint8_t port_id, int &mode) const{
- return g_trex.m_port_attr->get_flow_ctrl(port_id, (enum rte_eth_fc_mode *) &mode);
-}
-int TrexDpdkPlatformApi::set_flow_ctrl(uint8_t port_id, int mode) const {
- return g_trex.m_port_attr->set_flow_ctrl(port_id, (enum rte_eth_fc_mode) mode);
-}
void TrexDpdkPlatformApi::get_port_num(uint8_t &port_num) const {
port_num = g_trex.m_max_ports;
@@ -6386,10 +6435,6 @@ TrexDpdkPlatformApi::port_id_to_cores(uint8_t port_id, std::vector<std::pair<uin
cores_id_list = lpt->get_core_list();
}
-uint32_t
-TrexDpdkPlatformApi::get_link_speed(uint8_t port_id) const {
- return g_trex.m_port_attr->get_link_speed(port_id);
-}
void
TrexDpdkPlatformApi::get_interface_info(uint8_t interface_id, intf_info_st &info) const {
@@ -6409,6 +6454,7 @@ TrexDpdkPlatformApi::get_interface_info(uint8_t interface_id, intf_info_st &info
memcpy(sw_macaddr, CGlobalInfo::m_options.get_dst_src_mac_addr(interface_id), 12);
for (int i = 0; i < 6; i++) {
+ info.mac_info.hw_macaddr[i] = rte_mac_addr.addr_bytes[i];
info.mac_info.dst_macaddr[i] = sw_macaddr[i];
info.mac_info.src_macaddr[i] = sw_macaddr[6 + i];
@@ -6430,6 +6476,11 @@ TrexDpdkPlatformApi::publish_async_data_now(uint32_t key, bool baseline) const {
}
void
+TrexDpdkPlatformApi::publish_async_port_attr_changed(uint8_t port_id) const {
+ g_trex.publish_async_port_attr_changed(port_id);
+}
+
+void
TrexDpdkPlatformApi::get_interface_stat_info(uint8_t interface_id, uint16_t &num_counters, uint16_t &capabilities) const {
num_counters = CTRexExtendedDriverDb::Ins()->get_drv()->get_stat_counters_num();
capabilities = CTRexExtendedDriverDb::Ins()->get_drv()->get_rx_stat_capabilities();
@@ -6470,27 +6521,6 @@ int TrexDpdkPlatformApi::del_rx_flow_stat_rule(uint8_t port_id, uint16_t l3_type
->add_del_rx_flow_stat_rule(port_id, RTE_ETH_FILTER_DELETE, l3_type, l4_proto, ipv6_next_h, id);
}
-int TrexDpdkPlatformApi::set_promiscuous(uint8_t port_id, bool enabled) const {
- g_trex.m_port_attr->set_promiscuous(port_id, enabled);
- return 0;
-}
-
-bool TrexDpdkPlatformApi::get_promiscuous(uint8_t port_id) const {
- return g_trex.m_port_attr->get_promiscuous(port_id);
-}
-
-int TrexDpdkPlatformApi::set_link_status(uint8_t port_id, bool up) const {
- return g_trex.m_port_attr->set_link_up(port_id, up);
-}
-
-bool TrexDpdkPlatformApi::get_link_status(uint8_t port_id) const {
- return g_trex.m_port_attr->is_link_up(port_id);
-}
-
-int TrexDpdkPlatformApi::set_led_status(uint8_t port_id, bool on) const {
- return g_trex.m_port_attr->set_led(port_id, on);
-}
-
void TrexDpdkPlatformApi::flush_dp_messages() const {
g_trex.check_for_dp_messages();
}
@@ -6530,6 +6560,10 @@ CFlowStatParser *TrexDpdkPlatformApi::get_flow_stat_parser() const {
return CTRexExtendedDriverDb::Ins()->get_drv()->get_flow_stat_parser();
}
+TRexPortAttr *TrexDpdkPlatformApi::getPortAttrObj() const {
+ return g_trex.m_port_attr;
+}
+
/**
* marks the control plane for a total server shutdown
*
diff --git a/src/pal/linux/rte_ethdev_includes.h b/src/pal/linux/rte_ethdev_includes.h
new file mode 100644
index 00000000..de115d77
--- /dev/null
+++ b/src/pal/linux/rte_ethdev_includes.h
@@ -0,0 +1,23 @@
+struct rte_eth_link {
+ int link_autoneg;
+ int link_speed;
+ int link_duplex;
+ int link_status;
+};
+
+
+enum rte_eth_fc_mode {
+};
+
+struct rte_eth_xstat {
+};
+
+struct rte_eth_xstat_name {
+};
+
+struct rte_eth_fc_conf {
+};
+
+struct rte_eth_dev_info {
+};
+
diff --git a/src/pal/linux_dpdk/rte_ethdev_includes.h b/src/pal/linux_dpdk/rte_ethdev_includes.h
new file mode 100644
index 00000000..025ce8fc
--- /dev/null
+++ b/src/pal/linux_dpdk/rte_ethdev_includes.h
@@ -0,0 +1 @@
+#include <rte_ethdev.h>
diff --git a/src/publisher/trex_publisher.h b/src/publisher/trex_publisher.h
index fb7226c4..522c8c69 100644
--- a/src/publisher/trex_publisher.h
+++ b/src/publisher/trex_publisher.h
@@ -49,6 +49,7 @@ public:
EVENT_PORT_ACQUIRED = 5,
EVENT_PORT_RELEASED = 6,
EVENT_PORT_ERROR = 7,
+ EVENT_PORT_ATTR_CHANGED = 8,
EVENT_SERVER_STOPPED = 100,
diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
index f6b088a5..e4510a0a 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
@@ -295,6 +295,8 @@ TrexRpcCmdGetSysInfo::_run(const Json::Value &params, Json::Value &result) {
string src_macaddr;
string dst_macaddr;
string pci_addr;
+ string description;
+ supp_speeds_t supp_speeds;
int numa;
TrexStatelessPort *port = main->get_port_by_id(i);
@@ -302,10 +304,13 @@ TrexRpcCmdGetSysInfo::_run(const Json::Value &params, Json::Value &result) {
port->get_macaddr(hw_macaddr, src_macaddr, dst_macaddr);
port->get_pci_info(pci_addr, numa);
+ main->get_platform_api()->getPortAttrObj()->get_description(i, description);
+ main->get_platform_api()->getPortAttrObj()->get_supported_speeds(i, supp_speeds);
section["ports"][i]["index"] = i;
section["ports"][i]["driver"] = driver;
+ section["ports"][i]["description"] = description;
section["ports"][i]["hw_macaddr"] = hw_macaddr;
section["ports"][i]["src_macaddr"] = src_macaddr;
section["ports"][i]["dst_macaddr"] = dst_macaddr;
@@ -326,6 +331,14 @@ TrexRpcCmdGetSysInfo::_run(const Json::Value &params, Json::Value &result) {
}
section["ports"][i]["rx"]["counters"] = port->get_rx_count_num();
section["ports"][i]["speed"] = (uint16_t) speed / 1000;
+ section["ports"][i]["is_fc_supported"] = get_stateless_obj()->get_platform_api()->getPortAttrObj()->is_fc_change_supported();
+ section["ports"][i]["is_led_supported"] = get_stateless_obj()->get_platform_api()->getPortAttrObj()->is_led_change_supported();
+ section["ports"][i]["is_link_supported"] = get_stateless_obj()->get_platform_api()->getPortAttrObj()->is_link_change_supported();
+ section["ports"][i]["is_virtual"] = get_stateless_obj()->get_platform_api()->getPortAttrObj()->is_virtual();
+ section["ports"][i]["supp_speeds"] = Json::arrayValue;
+ for (int speed_id=0; speed_id<supp_speeds.size(); speed_id++) {
+ section["ports"][i]["supp_speeds"].append(supp_speeds[speed_id]);
+ }
}
@@ -349,22 +362,23 @@ TrexRpcCmdSetPortAttr::_run(const Json::Value &params, Json::Value &result) {
const Json::Value &attr = parse_object(params, "attr", result);
int ret = 0;
+ bool changed = false;
/* iterate over all attributes in the dict */
for (const std::string &name : attr.getMemberNames()) {
if (name == "promiscuous") {
bool enabled = parse_bool(attr[name], "enabled", result);
- ret = get_stateless_obj()->get_platform_api()->set_promiscuous(port_id, enabled);
+ ret = get_stateless_obj()->get_platform_api()->getPortAttrObj()->set_promiscuous(port_id, enabled);
}
else if (name == "link_status") {
bool up = parse_bool(attr[name], "up", result);
- ret = get_stateless_obj()->get_platform_api()->set_link_status(port_id, up);
+ ret = get_stateless_obj()->get_platform_api()->getPortAttrObj()->set_link_up(port_id, up);
}
else if (name == "led_status") {
bool on = parse_bool(attr[name], "on", result);
- ret = get_stateless_obj()->get_platform_api()->set_led_status(port_id, on);
+ ret = get_stateless_obj()->get_platform_api()->getPortAttrObj()->set_led(port_id, on);
} else if (name == "flow_ctrl_mode") {
int mode = parse_int(attr[name], "mode", result);
- ret = get_stateless_obj()->get_platform_api()->set_flow_ctrl(port_id, mode);
+ ret = get_stateless_obj()->get_platform_api()->getPortAttrObj()->set_flow_ctrl(port_id, mode);
} else {
generate_execute_err(result, "Not recognized attribute: " + name);
break;
@@ -376,8 +390,13 @@ TrexRpcCmdSetPortAttr::_run(const Json::Value &params, Json::Value &result) {
else if (ret) {
generate_execute_err(result, "Error applying " + name + " attribute, return value: " + to_string(ret));
}
+ break;
+ } else {
+ changed = true;
}
- break;
+ }
+ if (changed) {
+ get_stateless_obj()->get_platform_api()->publish_async_port_attr_changed(port_id);
}
result["result"] = Json::objectValue;
@@ -549,9 +568,17 @@ TrexRpcCmdGetPortStatus::_run(const Json::Value &params, Json::Value &result) {
result["result"]["owner"] = (port->get_owner().is_free() ? "" : port->get_owner().get_name());
result["result"]["state"] = port->get_state_as_string();
result["result"]["max_stream_id"] = port->get_max_stream_id();
+ result["result"]["speed"] = get_stateless_obj()->get_platform_api()->getPortAttrObj()->get_link_speed(port_id);
/* attributes */
- result["result"]["attr"]["promiscuous"]["enabled"] = get_stateless_obj()->get_platform_api()->get_promiscuous(port_id);
+ result["result"]["attr"]["promiscuous"]["enabled"] = get_stateless_obj()->get_platform_api()->getPortAttrObj()->get_promiscuous(port_id);
+ result["result"]["attr"]["link"]["up"] = get_stateless_obj()->get_platform_api()->getPortAttrObj()->is_link_up(port_id);
+ int mode;
+ int ret = get_stateless_obj()->get_platform_api()->getPortAttrObj()->get_flow_ctrl(port_id, mode);
+ if (ret != 0) {
+ mode = -1;
+ }
+ result["result"]["attr"]["fc"]["mode"] = mode;
return (TREX_RPC_CMD_OK);
}
diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp
index 8c6a1573..1a92b309 100644
--- a/src/stateless/cp/trex_stateless_port.cpp
+++ b/src/stateless/cp/trex_stateless_port.cpp
@@ -255,6 +255,11 @@ TrexStatelessPort::start_traffic(const TrexPortMultiplier &mul, double duration,
/* caclulate the effective factor for DP */
double factor = calculate_effective_factor(mul, force);
+ /* zero factor */
+ if (factor == 0) {
+ throw TrexException("Zero multiplier, nothing to send.");
+ }
+
StreamsFeeder feeder(this);
/* compiler it */
@@ -278,7 +283,7 @@ TrexStatelessPort::start_traffic(const TrexPortMultiplier &mul, double duration,
feeder.set_status(true);
- /* generate a message to all the relevant DP cores to start transmitting */
+ /* generate a message to all the relevant DP cores to stop transmitting */
assert(m_pending_async_stop_event == TrexDpPortEvents::INVALID_ID);
m_pending_async_stop_event = m_dp_events.create_event(new AsyncStopEvent());
@@ -581,7 +586,7 @@ void
TrexStatelessPort::get_properties(std::string &driver, uint32_t &speed) {
driver = m_api_info.driver_name;
- speed = platform_api->get_link_speed(m_port_id);
+ speed = platform_api->getPortAttrObj()->get_link_speed(m_port_id);
}
bool
@@ -662,7 +667,7 @@ TrexStatelessPort::send_message_to_rx(TrexStatelessCpToRxMsgBase *msg) {
uint64_t
TrexStatelessPort::get_port_speed_bps() const {
- return (uint64_t) platform_api->get_link_speed(m_port_id) * 1000 * 1000;
+ return (uint64_t) platform_api->getPortAttrObj()->get_link_speed(m_port_id) * 1000 * 1000;
}
static inline double
diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h
index c944df4a..43fee09b 100644
--- a/src/stateless/cp/trex_streams_compiler.h
+++ b/src/stateless/cp/trex_streams_compiler.h
@@ -309,7 +309,7 @@ public:
}
double get_factor_pps(double req_pps) const {
- if ( (req_pps - m_fixed.m_pps) <= 0 ) {
+ if ( (req_pps - m_fixed.m_pps) < 0 ) {
std::stringstream ss;
ss << "current stream configuration enforces a minimum rate of '" << m_fixed.m_pps << "' pps";
throw TrexException(ss.str());
@@ -319,7 +319,7 @@ public:
}
double get_factor_bps_l1(double req_bps_l1) const {
- if ( (req_bps_l1 - m_fixed.m_bps_l1) <= 0 ) {
+ if ( (req_bps_l1 - m_fixed.m_bps_l1) < 0 ) {
std::stringstream ss;
ss << "current stream configuration enforces a minimum rate of '" << m_fixed.m_bps_l1 << "' BPS L1";
throw TrexException(ss.str());
@@ -329,7 +329,7 @@ public:
}
double get_factor_bps_l2(double req_bps_l2) const {
- if ( (req_bps_l2 - m_fixed.m_bps_l2) <= 0 ) {
+ if ( (req_bps_l2 - m_fixed.m_bps_l2) < 0 ) {
std::stringstream ss;
ss << "current stream configuration enforces a minimum rate of '" << m_fixed.m_bps_l2 << "' BPS L2";
throw TrexException(ss.str());
diff --git a/src/trex_defs.h b/src/trex_defs.h
index d8139a83..8a4bf664 100644
--- a/src/trex_defs.h
+++ b/src/trex_defs.h
@@ -55,5 +55,6 @@ typedef std::set<uint32_t>::iterator flow_stat_active_it_t;
typedef std::vector<cpu_vct_st> cpu_util_full_t;
typedef std::vector<std::string> xstats_names_t;
typedef std::vector<uint64_t> xstats_values_t;
+typedef std::vector<uint32_t> supp_speeds_t;
#endif
diff --git a/src/trex_port_attr.h b/src/trex_port_attr.h
index 037a3de3..cc267104 100755
--- a/src/trex_port_attr.h
+++ b/src/trex_port_attr.h
@@ -19,23 +19,33 @@ limitations under the License.
#include <string>
#include <vector>
-#include <rte_ethdev.h>
+#include "rte_ethdev_includes.h"
#include "trex_defs.h"
class TRexPortAttr {
public:
- TRexPortAttr(uint8_t total_ports, bool is_virtual = false) : total_ports(total_ports) {
+ TRexPortAttr(uint8_t total_ports, bool is_virtual, bool fc_change_allowed) : total_ports(total_ports) {
flag_is_virtual = is_virtual;
m_link.resize(total_ports);
intf_info_st.resize(total_ports);
+ dev_info.resize(total_ports);
+ int tmp;
+ flag_is_fc_change_supported = fc_change_allowed && (get_flow_ctrl(0, tmp) != -ENOTSUP);
+ flag_is_led_change_supported = (set_led(0, true) != -ENOTSUP);
+ flag_is_link_change_supported = (set_link_up(0, true) != -ENOTSUP);
+ update_descriptions();
+ for (int i=0; i<total_ports; i++) {
+ update_device_info(i);
+ }
}
/* UPDATES */
virtual void update_link_status(uint8_t port_id);
- virtual void update_link_status_nowait(uint8_t port_id);
+ virtual bool update_link_status_nowait(uint8_t port_id); // returns true if the status was changed
+ virtual void update_device_info(uint8_t port_id);
virtual void reset_xstats(uint8_t port_id);
- virtual void update_info();
+ virtual void update_descriptions();
/* GETTERS */
virtual bool get_promiscuous(uint8_t port_id);
@@ -46,29 +56,36 @@ public:
virtual bool is_link_up(uint8_t port_id) { return (m_link[port_id].link_status ? true : false); }
virtual int get_xstats_values(uint8_t port_id, xstats_values_t &xstats_values);
virtual int get_xstats_names(uint8_t port_id, xstats_names_t &xstats_names);
- virtual int get_flow_ctrl(uint8_t port_id, enum rte_eth_fc_mode *mode);
+ virtual int get_flow_ctrl(uint8_t port_id, int &mode);
+ virtual bool is_virtual() { return flag_is_virtual; }
+ virtual bool is_fc_change_supported() { return flag_is_fc_change_supported; }
+ virtual bool is_led_change_supported() { return flag_is_led_change_supported; }
+ virtual bool is_link_change_supported() { return flag_is_link_change_supported; }
+ virtual void get_description(uint8_t port_id, std::string &description) { description = intf_info_st[port_id].description; }
+ virtual void get_supported_speeds(uint8_t port_id, supp_speeds_t &supp_speeds);
/* SETTERS */
virtual int set_promiscuous(uint8_t port_id, bool enabled);
virtual int add_mac(uint8_t port_id, char * mac);
virtual int set_link_up(uint8_t port_id, bool up);
- virtual int set_flow_ctrl(uint8_t port_id, const enum rte_eth_fc_mode mode);
+ virtual int set_flow_ctrl(uint8_t port_id, int mode);
virtual int set_led(uint8_t port_id, bool on);
/* DUMPS */
virtual void dump_link(uint8_t port_id, FILE *fd);
- virtual bool is_virtual() {
- return flag_is_virtual;
- }
private:
- bool flag_is_virtual;
const uint8_t total_ports;
rte_eth_fc_conf fc_conf_tmp;
- std::vector <rte_eth_link> m_link;
+ std::vector<rte_eth_link> m_link;
+ std::vector<struct rte_eth_dev_info> dev_info;
std::vector<struct rte_eth_xstat> xstats_values_tmp;
std::vector<struct rte_eth_xstat_name> xstats_names_tmp;
+ bool flag_is_virtual;
+ bool flag_is_fc_change_supported;
+ bool flag_is_led_change_supported;
+ bool flag_is_link_change_supported;
struct mac_cfg_st {
uint8_t hw_macaddr[6];