summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py58
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py2
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py60
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py52
-rwxr-xr-xscripts/dpdk_nic_bind.py7
-rwxr-xr-xscripts/dpdk_setup_ports.py6
-rwxr-xr-xscripts/t-rex-649
-rw-r--r--src/debug.cpp7
-rw-r--r--src/internal_api/trex_platform_api.h41
-rw-r--r--src/main_dpdk.cpp244
-rw-r--r--src/main_dpdk.h14
-rw-r--r--src/rpc-server/commands/trex_rpc_cmd_general.cpp86
-rw-r--r--src/rpc-server/commands/trex_rpc_cmds.h8
-rw-r--r--src/rpc-server/trex_rpc_cmd.cpp2
-rw-r--r--src/rpc-server/trex_rpc_cmds_table.cpp2
-rw-r--r--src/stateless/cp/trex_stateless.h14
-rw-r--r--src/stateless/cp/trex_stateless_port.cpp22
-rw-r--r--src/stateless/cp/trex_stateless_port.h9
-rw-r--r--src/trex_defs.h3
-rwxr-xr-xsrc/trex_port_attr.h91
20 files changed, 600 insertions, 137 deletions
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 82aa932d..b11ddbe3 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
@@ -560,11 +560,14 @@ class STLClient(object):
self.util_stats = trex_stl_stats.CUtilStats(self)
+ self.xstats = trex_stl_stats.CXStats(self)
+
self.stats_generator = trex_stl_stats.CTRexInfoGenerator(self.global_stats,
self.ports,
self.flow_stats,
self.latency_stats,
self.util_stats,
+ self.xstats,
self.async_client.monitor)
@@ -1785,6 +1788,25 @@ class STLClient(object):
self.logger.pre_cmd('Getting Utilization stats')
return self.util_stats.get_stats()
+ @__api_check(True)
+ def get_xstats(self, port_id):
+ print(port_id)
+ """
+ Get extended stats of port: all the counters as dict.
+
+ :parameters:
+ port_id: int
+
+ :returns:
+ Dict with names of counters as keys and values of uint64. Actual keys may vary per NIC.
+
+ :raises:
+ + :exc:`STLError`
+
+ """
+ self.logger.pre_cmd('Getting xstats')
+ return self.xstats.get_stats(port_id)
+
@__api_check(True)
def reset(self, ports = None):
@@ -2462,7 +2484,7 @@ class STLClient(object):
@__api_check(False)
- def clear_stats (self, ports = None, clear_global = True, clear_flow_stats = True, clear_latency_stats = True):
+ def clear_stats (self, ports = None, clear_global = True, clear_flow_stats = True, clear_latency_stats = True, clear_xstats = True):
"""
Clear stats on port(s)
@@ -2572,12 +2594,15 @@ class STLClient(object):
@__api_check(True)
- def set_port_attr (self, ports = None, promiscuous = None):
+ def set_port_attr (self, ports = None, promiscuous = None, link_up = None, led_on = None, flow_ctrl = None):
"""
Set port attributes
:parameters:
promiscuous - True or False
+ link_up - True or False
+ led_on - True or False
+ flow_ctrl - 0: disable all, 1: enable tx side, 2: enable rx side, 3: full enable
:raises:
None
@@ -2589,11 +2614,20 @@ class STLClient(object):
# check arguments
validate_type('promiscuous', promiscuous, (bool, type(None)))
+ validate_type('link_up', link_up, (bool, type(None)))
+ validate_type('led_on', led_on, (bool, type(None)))
+ validate_type('flow_ctrl', flow_ctrl, (int, type(None)))
# build attributes
attr_dict = {}
if promiscuous is not None:
- attr_dict['promiscuous'] = {'enabled': bool(promiscuous)}
+ attr_dict['promiscuous'] = {'enabled': promiscuous}
+ if link_up is not None:
+ attr_dict['link_status'] = {'up': link_up}
+ if led_on is not None:
+ attr_dict['led_status'] = {'on': led_on}
+ if flow_ctrl is not None:
+ attr_dict['flow_ctrl_mode'] = {'mode': flow_ctrl}
# no attributes to set
if not attr_dict:
@@ -3167,20 +3201,28 @@ class STLClient(object):
"port_attr",
self.set_port_attr_line.__doc__,
parsing_opts.PORT_LIST_WITH_ALL,
- parsing_opts.PROMISCUOUS_SWITCH)
+ parsing_opts.PROMISCUOUS,
+ parsing_opts.LINK_STATUS,
+ parsing_opts.LED_STATUS,
+ parsing_opts.FLOW_CTRL,
+ )
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)
+
# if no attributes - fall back to printing the status
- if opts.prom is None:
+ if not filter(lambda x:x is not None, [opts.prom, opts.link, opts.led, opts.flow_ctrl]):
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)
- return RC_OK()
-
+ return self.set_port_attr(opts.ports, opts.prom, opts.link, opts.led, opts.flow_ctrl)
+
@__console
def show_profile_line (self, line):
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py
index aa002d59..dc06f9fb 100755
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py
@@ -738,8 +738,8 @@ class STLVmFlowVarRepetableRandom(CTRexVmDescBase):
.. code-block:: python
- :caption: Example1
+ # Example1
# input , 1 byte or random with limit of 5
STLVmFlowVarRepetableRandom("var1",size=1,limit=5)
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 5d9cdcaa..eaa5e8b0 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
@@ -147,12 +147,13 @@ class CTRexInfoGenerator(object):
STLClient and the ports.
"""
- def __init__(self, global_stats_ref, ports_dict_ref, rx_stats_ref, latency_stats_ref, util_stats_ref, async_monitor):
+ def __init__(self, global_stats_ref, ports_dict_ref, rx_stats_ref, latency_stats_ref, util_stats_ref, xstats_ref, async_monitor):
self._global_stats = global_stats_ref
self._ports_dict = ports_dict_ref
self._rx_stats_ref = rx_stats_ref
self._latency_stats_ref = latency_stats_ref
self._util_stats_ref = util_stats_ref
+ self._xstats_ref = xstats_ref
self._async_monitor = async_monitor
def generate_single_statistic(self, port_id_list, statistic_type):
@@ -1003,6 +1004,7 @@ class CPortStats(CTRexStats):
def _update(self, snapshot):
+ speed = self._port_obj.get_speed_bps()
# L1 bps
tx_bps = snapshot.get("m_total_tx_bps")
@@ -1015,22 +1017,34 @@ class CPortStats(CTRexStats):
bps_rx_L1 = calc_bps_L1(rx_bps, rx_pps)
snapshot['m_total_tx_bps_L1'] = bps_tx_L1
- snapshot['m_tx_util'] = (bps_tx_L1 / self._port_obj.get_speed_bps()) * 100.0
+ if speed:
+ snapshot['m_tx_util'] = (bps_tx_L1 / speed) * 100.0
+ else:
+ snapshot['m_tx_util'] = 0
snapshot['m_total_rx_bps_L1'] = bps_rx_L1
- snapshot['m_rx_util'] = (bps_rx_L1 / self._port_obj.get_speed_bps()) * 100.0
+ if speed:
+ snapshot['m_rx_util'] = (bps_rx_L1 / speed) * 100.0
+ else:
+ snapshot['m_rx_util'] = 0
# TX line util not smoothed
diff_tx_pkts = snapshot.get('opackets', 0) - self.latest_stats.get('opackets', 0)
diff_tx_bytes = snapshot.get('obytes', 0) - self.latest_stats.get('obytes', 0)
tx_bps_L1 = calc_bps_L1(8.0 * diff_tx_bytes / ts_diff, float(diff_tx_pkts) / ts_diff)
- snapshot['tx_percentage'] = 100.0 * tx_bps_L1 / self._port_obj.get_speed_bps()
+ if speed:
+ snapshot['tx_percentage'] = 100.0 * tx_bps_L1 / speed
+ else:
+ snapshot['tx_percentage'] = 0
# RX line util not smoothed
diff_rx_pkts = snapshot.get('ipackets', 0) - self.latest_stats.get('ipackets', 0)
diff_rx_bytes = snapshot.get('ibytes', 0) - self.latest_stats.get('ibytes', 0)
rx_bps_L1 = calc_bps_L1(8.0 * diff_rx_bytes / ts_diff, float(diff_rx_pkts) / ts_diff)
- snapshot['rx_percentage'] = 100.0 * rx_bps_L1 / self._port_obj.get_speed_bps()
+ if speed:
+ snapshot['rx_percentage'] = 100.0 * rx_bps_L1 / speed
+ else:
+ snapshot['rx_percentage'] = 0
# simple...
self.latest_stats = snapshot
@@ -1417,7 +1431,7 @@ class CUtilStats(CTRexStats):
self.client = client
self.history = deque(maxlen = 1)
self.mbuf_types_list = None
- self.last_update_ts = 0
+ self.last_update_ts = -999
def get_stats(self, use_1sec_cache = False):
time_now = time.time()
@@ -1433,6 +1447,40 @@ class CUtilStats(CTRexStats):
return self.history[-1]
+class CXStats(CTRexStats):
+
+ def __init__(self, client):
+ super(CXStats, self).__init__()
+ self.client = client
+ self.history = deque(maxlen = 1)
+ self.names = {}
+ self.last_update_ts = -999
+
+ def get_stats(self, port_id, use_1sec_cache = False):
+ time_now = time.time()
+ if self.last_update_ts + 1 < time_now or not self.history 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)
+ 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)
+ 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({})
+
+ stats = {}
+ for key, val in self.history[-1].items():
+ stats[key] = self.history[-1][key] - self.reference_stats.get(key, 0)
+ return stats
+
if __name__ == "__main__":
pass
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 8ae86981..148f7715 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
@@ -1,5 +1,5 @@
import argparse
-from collections import namedtuple
+from collections import namedtuple, OrderedDict
from .common import list_intersect, list_difference
from .text_opts import format_text
from ..trex_stl_types import *
@@ -11,6 +11,18 @@ 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
@@ -32,14 +44,15 @@ IPG = 16
SPEEDUP = 17
COUNT = 18
PROMISCUOUS = 19
-NO_PROMISCUOUS = 20
-PROMISCUOUS_SWITCH = 21
+LINK_STATUS = 20
+LED_STATUS = 21
TUNABLES = 22
REMOTE_FILE = 23
LOCKED = 24
PIN_CORES = 25
CORE_MASK = 26
DUAL = 27
+FLOW_CTRL = 28
GLOBAL_STATS = 50
PORT_STATS = 51
@@ -282,10 +295,21 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
'type': int}),
PROMISCUOUS: ArgumentPack(['--prom'],
- {'help': "Sets port promiscuous on",
- 'dest': "prom",
- 'default': None,
- 'action': "store_true"}),
+ {'help': "Set port promiscuous on/off",
+ 'choices': on_off_dict}),
+
+ LINK_STATUS: ArgumentPack(['--link'],
+ {'help': 'Set link status on/off',
+ 'choices': on_off_dict}),
+
+ LED_STATUS: ArgumentPack(['--led'],
+ {'help': 'Set LED status on/off',
+ 'choices': on_off_dict}),
+
+ FLOW_CTRL: ArgumentPack(['--fc'],
+ {'help': 'Set Flow Control type',
+ 'dest': 'flow_ctrl',
+ 'choices': flow_ctrl_dict}),
TUNABLES: ArgumentPack(['-t'],
{'help': "Sets tunables for a profile. Example: '-t fsize=100,pg_id=7'",
@@ -295,12 +319,6 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
'action': 'merge',
'type': decode_tunables}),
- NO_PROMISCUOUS: ArgumentPack(['--no-prom', '--no_prom'],
- {'help': "Sets port promiscuous off",
- 'dest': "prom",
- 'default': None,
- 'action': "store_false"}),
-
PORT_LIST: ArgumentPack(['--port', '-p'],
{"nargs": '+',
'dest':'ports',
@@ -424,12 +442,6 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
'default': None,
'help': "Core mask - only cores responding to the bit mask will be active"}),
-
- # promiscuous
- PROMISCUOUS_SWITCH: ArgumentGroup(MUTEX, [PROMISCUOUS,
- NO_PROMISCUOUS],
- {'required': False}),
-
# advanced options
PORT_LIST_WITH_ALL: ArgumentGroup(MUTEX, [PORT_LIST,
ALL_PORTS],
@@ -462,6 +474,8 @@ class _MergeAction(argparse._AppendAction):
items.extend(values)
elif type(items) is dict and type(values) is dict: # tunables are dict
items.update(values)
+ else:
+ raise Exception("Argparser 'merge' option should be used on dict or list.")
setattr(namespace, self.dest, items)
diff --git a/scripts/dpdk_nic_bind.py b/scripts/dpdk_nic_bind.py
index 44d4e82d..ed0462ec 100755
--- a/scripts/dpdk_nic_bind.py
+++ b/scripts/dpdk_nic_bind.py
@@ -629,6 +629,13 @@ def show_table():
table.add_row([id, d['NUMA'], d['Slot_str'], d.get('MAC', ''), d['Device_str'], d.get('Driver_str', ''), d['Interface'], d['Active']])
print(table.draw())
+# dumps pci address and description (user friendly device name)
+def dump_pci_description():
+ if not devices:
+ get_nic_details()
+ for d in devices.values():
+ print('%s - %s' % (d['Slot'], d['Device_str']))
+
def parse_args():
'''Parses the command-line arguments given by the user and takes the
appropriate action for each'''
diff --git a/scripts/dpdk_setup_ports.py b/scripts/dpdk_setup_ports.py
index 58d58690..2782384c 100755
--- a/scripts/dpdk_setup_ports.py
+++ b/scripts/dpdk_setup_ports.py
@@ -699,6 +699,8 @@ 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("-i", "--interactive", action='store_true',
help=""" Create TRex config in interactive mode """,
)
@@ -786,6 +788,10 @@ def main ():
dpdk_nic_bind.show_table()
return
+ if map_driver.args.dump_pci_desc:
+ dpdk_nic_bind.dump_pci_description()
+ return
+
obj =CIfMap(map_driver.cfg_file);
if map_driver.args.create_interfaces is not None:
diff --git a/scripts/t-rex-64 b/scripts/t-rex-64
index 4e5c0fae..4d0d7813 100755
--- a/scripts/t-rex-64
+++ b/scripts/t-rex-64
@@ -12,6 +12,15 @@ if [ $RESULT -ne 0 ]; then
exit $RESULT
fi
+pci_desc_re='^(\S+) - (.+)$'
+source find_python.sh
+while read line
+do
+ if [[ "$line" =~ $pci_desc_re ]]; then
+ pci_name="pci$(echo ${BASH_REMATCH[1]} | tr ':' '_' | tr '.' '_')" # make alphanumeric name
+ export $pci_name="${BASH_REMATCH[2]}"
+ fi
+done <<< "$($PYTHON dpdk_setup_ports.py --dump-pci-description)"
cd $(dirname $0)
export LD_LIBRARY_PATH=$PWD
diff --git a/src/debug.cpp b/src/debug.cpp
index 542d2fa1..3a9cd506 100644
--- a/src/debug.cpp
+++ b/src/debug.cpp
@@ -213,8 +213,11 @@ int CTrexDebug::test_send_pkts(rte_mbuf_t *m, uint16_t queue_id, int num_pkts, i
int CTrexDebug::set_promisc_all(bool enable) {
int i;
for (i=0; i < m_max_ports; i++) {
- CPhyEthIF *_if = &m_ports[i];
- _if->set_promiscuous(enable);
+ if (enable) {
+ rte_eth_promiscuous_enable(i);
+ }else{
+ rte_eth_promiscuous_disable(i);
+ }
}
return 0;
diff --git a/src/internal_api/trex_platform_api.h b/src/internal_api/trex_platform_api.h
index a55e8cd7..998b6d49 100644
--- a/src/internal_api/trex_platform_api.h
+++ b/src/internal_api/trex_platform_api.h
@@ -123,7 +123,6 @@ public:
*/
struct intf_info_st {
std::string driver_name;
- uint32_t speed;
mac_cfg_st mac_info;
std::string pci_addr;
int numa_node;
@@ -149,14 +148,22 @@ 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 void set_promiscuous(uint8_t port_id, bool enabled) 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 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() {}
};
@@ -188,14 +195,23 @@ 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;
- void set_promiscuous(uint8_t port_id, bool enabled) 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;
+
+ 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;
};
@@ -221,7 +237,6 @@ public:
virtual void get_interface_info(uint8_t interface_id, intf_info_st &info) const {
info.driver_name = "TEST";
- info.speed = 10000;
info.has_crc = true;
info.numa_node = 0;
@@ -251,11 +266,18 @@ 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;};
- void set_promiscuous(uint8_t port_id, bool enabled) const {
+ 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 {
}
@@ -265,6 +287,15 @@ public:
CFlowStatParser *get_flow_stat_parser() const {return new CFlowStatParser();}
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 46fa7335..9ef08cf1 100644
--- a/src/main_dpdk.cpp
+++ b/src/main_dpdk.cpp
@@ -76,7 +76,10 @@ extern "C" {
#include "pre_test.h"
#include "stateful_rx_core.h"
#include "debug.h"
+<<<<<<< 653629bee578b4888bd0c144386c03a4b0d08eef
#include "pkt_gen.h"
+#include "trex_port_attr.h"
+>>>>>>> 73cffaf2cc2f21cb902dbd672e93577878c9f6b1
#include "internal_api/trex_platform_api.h"
#include "main_dpdk.h"
#include "trex_watchdog.h"
@@ -120,6 +123,15 @@ static inline int get_is_rx_thread_enabled() {
struct port_cfg_t;
+#define MAX_DPDK_ARGS 40
+static CPlatformYamlInfo global_platform_cfg_info;
+static int global_dpdk_args_num ;
+static char * global_dpdk_args[MAX_DPDK_ARGS];
+static char global_cores_str[100];
+static char global_prefix_str[100];
+static char global_loglevel_str[20];
+
+
class CTRexExtendedDriverBase {
public:
@@ -158,6 +170,7 @@ public:
virtual int verify_fw_ver(int i) {return 0;}
virtual CFlowStatParser *get_flow_stat_parser();
virtual int set_rcv_all(CPhyEthIF * _if, bool set_on)=0;
+ TRexPortAttr * m_port_attr;
};
@@ -165,6 +178,7 @@ class CTRexExtendedDriverBase1G : public CTRexExtendedDriverBase {
public:
CTRexExtendedDriverBase1G(){
+ m_port_attr = new TRexPortAttr(global_platform_cfg_info.m_if_list.size(), false);
}
static CTRexExtendedDriverBase * create(){
@@ -210,6 +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);
}
virtual bool has_crc_added() {
@@ -255,6 +270,7 @@ public:
class CTRexExtendedDriverBase10G : public CTRexExtendedDriverBase {
public:
CTRexExtendedDriverBase10G(){
+ m_port_attr = new TRexPortAttr(global_platform_cfg_info.m_if_list.size(), false);
}
static CTRexExtendedDriverBase * create(){
@@ -296,6 +312,7 @@ 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);
}
static CTRexExtendedDriverBase * create(){
@@ -345,6 +362,7 @@ private:
class CTRexExtendedDriverBaseVIC : public CTRexExtendedDriverBase40G {
public:
CTRexExtendedDriverBaseVIC(){
+ m_port_attr = new TRexPortAttr(global_platform_cfg_info.m_if_list.size(), false);
}
static CTRexExtendedDriverBase * create(){
@@ -413,12 +431,12 @@ private:
register_driver(std::string("rte_ixgbe_pmd"),CTRexExtendedDriverBase10G::create);
register_driver(std::string("rte_igb_pmd"),CTRexExtendedDriverBase1G::create);
register_driver(std::string("rte_i40e_pmd"),CTRexExtendedDriverBase40G::create);
+ register_driver(std::string("rte_enic_pmd"),CTRexExtendedDriverBaseVIC::create);
/* virtual devices */
register_driver(std::string("rte_em_pmd"),CTRexExtendedDriverBase1GVm::create);
register_driver(std::string("rte_vmxnet3_pmd"),CTRexExtendedDriverBase1GVm::create);
register_driver(std::string("rte_virtio_pmd"),CTRexExtendedDriverBase1GVm::create);
- register_driver(std::string("rte_enic_pmd"),CTRexExtendedDriverBaseVIC::create);
@@ -488,14 +506,6 @@ static inline int get_min_sample_rate(void){
return ( get_ex_drv()->get_min_sample_rate());
}
-#define MAX_DPDK_ARGS 40
-static CPlatformYamlInfo global_platform_cfg_info;
-static int global_dpdk_args_num ;
-static char * global_dpdk_args[MAX_DPDK_ARGS];
-static char global_cores_str[100];
-static char global_prefix_str[100];
-static char global_loglevel_str[20];
-
// cores =0==1,1*2,2,3,4,5,6
// An enum for all the option types
enum { OPT_HELP,
@@ -1443,63 +1453,158 @@ void CPhyEthIF::disable_flow_control(){
ret, m_port_id);
}
+// Get user frienly devices description from saved env. var
+void TRexPortAttr::update_info(){
+ struct rte_pci_addr pci_addr;
+ char pci[16];
+ char * envvar;
+ std::string pci_envvar_name;
+ for (uint8_t port_id=0; port_id<total_ports; port_id++) {
+ pci_addr = rte_eth_devices[port_id].pci_dev->addr;
+ snprintf(pci, sizeof(pci), "%04x:%02x:%02x.%d", pci_addr.domain, pci_addr.bus, pci_addr.devid, pci_addr.function);
+ intf_info_st[port_id].pci_addr = pci;
+ pci_envvar_name = "pci" + intf_info_st[port_id].pci_addr;
+ std::replace(pci_envvar_name.begin(), pci_envvar_name.end(), ':', '_');
+ std::replace(pci_envvar_name.begin(), pci_envvar_name.end(), '.', '_');
+ envvar = std::getenv(pci_envvar_name.c_str());
+ if (envvar) {
+ intf_info_st[port_id].description = envvar;
+ } else {
+ intf_info_st[port_id].description = "Unknown";
+ }
+ if ( CGlobalInfo::m_options.preview.getVMode() > 0){
+ printf("port %d desc: %s\n", port_id, intf_info_st[port_id].description.c_str());
+ }
+ }
+}
+
+int TRexPortAttr::set_led(uint8_t port_id, bool on){
+ if (on) {
+ return rte_eth_led_on(port_id);
+ }else{
+ return rte_eth_led_off(port_id);
+ }
+}
+
+int TRexPortAttr::get_flow_ctrl(uint8_t port_id, enum rte_eth_fc_mode *mode) {
+ int ret = rte_eth_dev_flow_ctrl_get(port_id, &fc_conf_tmp);
+ if (ret) {
+ return ret;
+ }
+ *mode = fc_conf_tmp.mode;
+ return 0;
+}
+
+int TRexPortAttr::set_flow_ctrl(uint8_t port_id, const enum rte_eth_fc_mode mode) {
+ int ret = rte_eth_dev_flow_ctrl_get(port_id, &fc_conf_tmp);
+ if (ret) {
+ return ret;
+ }
+ fc_conf_tmp.mode = mode;
+ return rte_eth_dev_flow_ctrl_set(port_id, &fc_conf_tmp);
+}
+void TRexPortAttr::reset_xstats(uint8_t port_id) {
+ rte_eth_xstats_reset(port_id);
+}
-void CPhyEthIF::dump_link(FILE *fd){
- fprintf(fd,"port : %d \n",(int)m_port_id);
+int TRexPortAttr::get_xstats_values(uint8_t port_id, xstats_values_t &xstats_values) {
+ int size = rte_eth_xstats_get(port_id, NULL, 0);
+ if (size < 0) {
+ return size;
+ }
+ xstats_values_tmp.resize(size);
+ xstats_values.resize(size);
+ size = rte_eth_xstats_get(port_id, xstats_values_tmp.data(), size);
+ if (size < 0) {
+ return size;
+ }
+ for (int i=0; i<size; i++) {
+ xstats_values[xstats_values_tmp[i].id] = xstats_values_tmp[i].value;
+ }
+ return 0;
+}
+
+int TRexPortAttr::get_xstats_names(uint8_t port_id, xstats_names_t &xstats_names){
+ int size = rte_eth_xstats_get_names(port_id, NULL, 0);
+ if (size < 0) {
+ return size;
+ }
+ xstats_names_tmp.resize(size);
+ xstats_names.resize(size);
+ size = rte_eth_xstats_get_names(port_id, xstats_names_tmp.data(), size);
+ if (size < 0) {
+ return size;
+ }
+ for (int i=0; i<size; i++) {
+ xstats_names[i] = xstats_names_tmp[i].name;
+ }
+ return 0;
+}
+
+void TRexPortAttr::dump_link(uint8_t port_id, FILE *fd){
+ fprintf(fd,"port : %d \n",(int)port_id);
fprintf(fd,"------------\n");
fprintf(fd,"link : ");
- if (m_link.link_status) {
+ if (m_link[port_id].link_status) {
fprintf(fd," link : Link Up - speed %u Mbps - %s\n",
- (unsigned) m_link.link_speed,
- (m_link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
+ (unsigned) m_link[port_id].link_speed,
+ (m_link[port_id].link_duplex == ETH_LINK_FULL_DUPLEX) ?
("full-duplex") : ("half-duplex\n"));
} else {
fprintf(fd," Link Down\n");
}
- fprintf(fd,"promiscuous : %d \n",get_promiscuous());
+ fprintf(fd,"promiscuous : %d \n",get_promiscuous(port_id));
}
-void CPhyEthIF::update_link_status(){
- rte_eth_link_get(m_port_id, &m_link);
+void TRexPortAttr::update_link_status(uint8_t port_id){
+ rte_eth_link_get(port_id, &m_link[port_id]);
}
-void CPhyEthIF::update_link_status_nowait(){
- rte_eth_link_get_nowait(m_port_id, &m_link);
+void TRexPortAttr::update_link_status_nowait(uint8_t port_id){
+ rte_eth_link_get_nowait(port_id, &m_link[port_id]);
}
-void CPhyEthIF::add_mac(char * mac){
+int TRexPortAttr::add_mac(uint8_t port_id, char * mac){
struct ether_addr mac_addr;
- int i=0;
- for (i=0; i<6;i++) {
+ for (int i=0; i<6;i++) {
mac_addr.addr_bytes[i] =mac[i];
}
- rte_eth_dev_mac_addr_add(m_port_id, &mac_addr,0);
+ return rte_eth_dev_mac_addr_add(port_id, &mac_addr,0);
}
-void CPhyEthIF::set_promiscuous(bool enable){
+int TRexPortAttr::set_promiscuous(uint8_t port_id, bool enable){
if (enable) {
- rte_eth_promiscuous_enable(m_port_id);
+ rte_eth_promiscuous_enable(port_id);
+ }else{
+ rte_eth_promiscuous_disable(port_id);
+ }
+ return 0;
+}
+
+int TRexPortAttr::set_link_up(uint8_t port_id, bool up){
+ if (up) {
+ return rte_eth_dev_set_link_up(port_id);
}else{
- rte_eth_promiscuous_disable(m_port_id);
+ return rte_eth_dev_set_link_down(port_id);
}
}
-bool CPhyEthIF::get_promiscuous(){
- int ret=rte_eth_promiscuous_get(m_port_id);
+bool TRexPortAttr::get_promiscuous(uint8_t port_id){
+ int ret=rte_eth_promiscuous_get(port_id);
if (ret<0) {
rte_exit(EXIT_FAILURE, "rte_eth_promiscuous_get: "
"err=%d, port=%u\n",
- ret, m_port_id);
+ ret, port_id);
}
return ( ret?true:false);
}
-void CPhyEthIF::macaddr_get(struct ether_addr *mac_addr){
- rte_eth_macaddr_get(m_port_id , mac_addr);
+void TRexPortAttr::macaddr_get(uint8_t port_id, struct ether_addr *mac_addr){
+ rte_eth_macaddr_get(port_id , mac_addr);
}
int CPhyEthIF::dump_fdir_global_stats(FILE *fd) {
@@ -1929,12 +2034,22 @@ int CCoreEthIF::send_pkt_lat(CCorePerPort *lp_port, rte_mbuf_t *m, CVirtualIFPer
int ret = lp_port->m_port->tx_burst(lp_port->m_tx_queue_id_lat, &m, 1);
+#ifdef DELAY_IF_NEEDED
while ( unlikely( ret != 1 ) ){
rte_delay_us(1);
lp_stats->m_tx_queue_full += 1;
ret = lp_port->m_port->tx_burst(lp_port->m_tx_queue_id_lat, &m, 1);
}
+#else
+ if ( unlikely( ret != 1 ) ) {
+ lp_stats->m_tx_drop ++;
+ rte_pktmbuf_free(m);
+ return 0;
+ }
+
+#endif
+
return ret;
}
@@ -2867,6 +2982,8 @@ public:
CLatencyManager m_mg; // statefull RX core
CRxCoreStateless m_rx_sl; // stateless RX core
CTrexGlobalIoMode m_io_modes;
+ CTRexExtendedDriverBase * m_drv;
+ TRexPortAttr * m_port_attr;
private:
CLatencyHWPort m_latency_vports[TREX_MAX_PORTS]; /* read hardware driver */
@@ -3000,11 +3117,11 @@ bool CGlobalTRex::is_all_links_are_up(bool dump){
int i;
for (i=0; i<m_max_ports; i++) {
CPhyEthIF * _if=&m_ports[i];
- _if->update_link_status();
+ m_port_attr->update_link_status(i);
if ( dump ){
_if->dump_stats(stdout);
}
- if ( _if->is_link_up() == false){
+ if ( m_port_attr->is_link_up(i) == false){
all_link_are=false;
break;
}
@@ -3238,7 +3355,7 @@ int CGlobalTRex::ixgbe_start(void){
_if->disable_flow_control();
}
- _if->add_mac((char *)CGlobalInfo::m_options.get_src_mac_addr(i));
+ m_port_attr->add_mac(i, (char *)CGlobalInfo::m_options.get_src_mac_addr(i));
fflush(stdout);
}
@@ -3247,7 +3364,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) ){
+ if ( !is_all_links_are_up(true) && !get_is_stateless()){
dump_links_status(stdout);
rte_exit(EXIT_FAILURE, " "
" one of the link is down \n");
@@ -3478,10 +3595,13 @@ 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++) {
- if (CTRexExtendedDriverDb::Ins()->get_drv()->verify_fw_ver(i) < 0) {
+ if (m_drv->verify_fw_ver(i) < 0) {
// error message printed by verify_fw_ver
exit(1);
}
@@ -3552,9 +3672,8 @@ void CGlobalTRex::dump_config(FILE *fd){
void CGlobalTRex::dump_links_status(FILE *fd){
for (int i=0; i<m_max_ports; i++) {
- CPhyEthIF * _if=&m_ports[i];
- _if->update_link_status_nowait();
- _if->dump_link(fd);
+ m_port_attr->update_link_status_nowait(i);
+ m_port_attr->dump_link(i, fd);
}
}
@@ -4006,6 +4125,10 @@ void
CGlobalTRex::handle_slow_path() {
m_stats_cnt+=1;
+ // update speed, link up/down etc.
+ for (int i=0; i<m_max_ports; i++) {
+ m_port_attr->update_link_status_nowait(i);
+ }
if ( CGlobalInfo::m_options.preview.get_no_keyboard() ==false ) {
if ( m_io_modes.handle_io_modes() ) {
@@ -6203,6 +6326,21 @@ static void trex_termination_handler(int signum) {
* TODO: REMOVE THIS TO A SEPERATE FILE
*
**********************************************************/
+int TrexDpdkPlatformApi::get_xstats_values(uint8_t port_id, xstats_values_t &xstats_values) const {
+ return g_trex.m_port_attr->get_xstats_values(port_id, xstats_values);
+}
+
+int TrexDpdkPlatformApi::get_xstats_names(uint8_t port_id, xstats_names_t &xstats_names) const {
+ 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;
}
@@ -6248,19 +6386,22 @@ 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 {
struct ether_addr rte_mac_addr;
info.driver_name = CTRexExtendedDriverDb::Ins()->get_driver_name();
- g_trex.m_ports[interface_id].update_link_status_nowait();
- g_trex.m_ports[interface_id].get_link_speed(&info.speed);
info.has_crc = CTRexExtendedDriverDb::Ins()->get_drv()->has_crc_added();
/* mac INFO */
/* hardware */
- g_trex.m_ports[interface_id].macaddr_get(&rte_mac_addr);
+ g_trex.m_port_attr->macaddr_get(interface_id, &rte_mac_addr);
assert(ETHER_ADDR_LEN == 6);
/* software */
@@ -6329,12 +6470,25 @@ 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);
}
-void TrexDpdkPlatformApi::set_promiscuous(uint8_t port_id, bool enabled) const {
- g_trex.m_ports[port_id].set_promiscuous(enabled);
+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_ports[port_id].get_promiscuous();
+ 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 {
diff --git a/src/main_dpdk.h b/src/main_dpdk.h
index 97994c47..640c73e4 100644
--- a/src/main_dpdk.h
+++ b/src/main_dpdk.h
@@ -87,7 +87,6 @@ class CPhyEthIF {
void configure(uint16_t nb_rx_queue,
uint16_t nb_tx_queue,
const struct rte_eth_conf *eth_conf);
- void macaddr_get(struct ether_addr *mac_addr);
void get_stats(CPhyEthIFStats *stats);
int dump_fdir_global_stats(FILE *fd);
int reset_hw_flow_stats();
@@ -106,19 +105,7 @@ class CPhyEthIF {
void configure_rx_duplicate_rules();
void start();
void stop();
- void update_link_status();
- void update_link_status_nowait();
- bool is_link_up(){
- return (m_link.link_status?true:false);
- }
- void get_link_speed(uint32_t *link_speed){
- *link_speed = m_link.link_speed;
- }
- void dump_link(FILE *fd);
void disable_flow_control();
- void set_promiscuous(bool enable);
- void add_mac(char * mac);
- bool get_promiscuous();
void dump_stats(FILE *fd);
void set_ignore_stats_base(CPreTestStats &pre_stats);
void update_counters();
@@ -182,7 +169,6 @@ class CPhyEthIF {
const std::vector<std::pair<uint8_t, uint8_t>> & get_core_list();
private:
- struct rte_eth_link m_link;
uint8_t m_port_id;
uint8_t m_rx_queue;
uint64_t m_sw_try_tx_pkt;
diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
index 342ec594..f6b088a5 100644
--- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp
+++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp
@@ -346,18 +346,38 @@ trex_rpc_cmd_rc_e
TrexRpcCmdSetPortAttr::_run(const Json::Value &params, Json::Value &result) {
uint8_t port_id = parse_port(params, result);
- TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
const Json::Value &attr = parse_object(params, "attr", result);
-
+ int ret = 0;
/* iterate over all attributes in the dict */
for (const std::string &name : attr.getMemberNames()) {
-
- /* handle promiscuous */
if (name == "promiscuous") {
bool enabled = parse_bool(attr[name], "enabled", result);
- port->set_promiscuous(enabled);
+ ret = get_stateless_obj()->get_platform_api()->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);
+ }
+ 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);
+ } 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);
+ } else {
+ generate_execute_err(result, "Not recognized attribute: " + name);
+ break;
}
+ if (ret != 0){
+ if ( ret == -ENOTSUP ) {
+ generate_execute_err(result, "Error applying " + name + ": operation is not supported for this NIC.");
+ }
+ else if (ret) {
+ generate_execute_err(result, "Error applying " + name + " attribute, return value: " + to_string(ret));
+ }
+ }
+ break;
}
result["result"] = Json::objectValue;
@@ -437,6 +457,60 @@ TrexRpcCmdRelease::_run(const Json::Value &params, Json::Value &result) {
}
/**
+ * get port extended stats names (keys of dict)
+ *
+ */
+trex_rpc_cmd_rc_e
+TrexRpcCmdGetPortXStatsNames::_run(const Json::Value &params, Json::Value &result) {
+
+ uint8_t port_id = parse_port(params, result);
+ xstats_names_t xstats_names;
+
+ int ret = get_stateless_obj()->get_platform_api()->get_xstats_names(port_id, xstats_names);
+ if (ret < 0) {
+ if ( ret == -ENOTSUP ) {
+ generate_execute_err(result, "Operation not supported");
+ }
+ else if (ret) {
+ generate_execute_err(result, "Operation failed, error code: " + to_string(ret));
+ }
+ } else {
+ for (int i=0; i<xstats_names.size(); i++) {
+ result["result"]["xstats_names"].append(xstats_names[i]);
+ }
+ }
+
+ return (TREX_RPC_CMD_OK);
+}
+
+/**
+ * get port extended stats (values of dict)
+ *
+ */
+trex_rpc_cmd_rc_e
+TrexRpcCmdGetPortXStatsValues::_run(const Json::Value &params, Json::Value &result) {
+
+ uint8_t port_id = parse_port(params, result);
+ xstats_values_t xstats_values;
+
+ int ret = get_stateless_obj()->get_platform_api()->get_xstats_values(port_id, xstats_values);
+ if (ret < 0) {
+ if ( ret == -ENOTSUP ) {
+ generate_execute_err(result, "Operation not supported");
+ }
+ else if (ret) {
+ generate_execute_err(result, "Operation failed, error code: " + to_string(ret));
+ }
+ } else {
+ for (int i=0; i<xstats_values.size(); i++) {
+ result["result"]["xstats_values"].append((Json::Value::UInt64) xstats_values[i]);
+ }
+ }
+
+ return (TREX_RPC_CMD_OK);
+}
+
+/**
* get port stats
*
*/
@@ -477,7 +551,7 @@ TrexRpcCmdGetPortStatus::_run(const Json::Value &params, Json::Value &result) {
result["result"]["max_stream_id"] = port->get_max_stream_id();
/* attributes */
- result["result"]["attr"]["promiscuous"]["enabled"] = port->get_promiscuous();
+ result["result"]["attr"]["promiscuous"]["enabled"] = get_stateless_obj()->get_platform_api()->get_promiscuous(port_id);
return (TREX_RPC_CMD_OK);
}
diff --git a/src/rpc-server/commands/trex_rpc_cmds.h b/src/rpc-server/commands/trex_rpc_cmds.h
index a68796ae..5fde1d0c 100644
--- a/src/rpc-server/commands/trex_rpc_cmds.h
+++ b/src/rpc-server/commands/trex_rpc_cmds.h
@@ -87,9 +87,11 @@ TREX_RPC_CMD_DEFINE(TrexRpcCmdRelease, "release", 1, true, APIClass:
/**
* port commands
*/
-TREX_RPC_CMD_DEFINE(TrexRpcCmdGetPortStats, "get_port_stats", 1, false, APIClass::API_CLASS_TYPE_CORE);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdGetPortStatus, "get_port_status", 1, false, APIClass::API_CLASS_TYPE_CORE);
-TREX_RPC_CMD_DEFINE(TrexRpcCmdSetPortAttr, "set_port_attr", 3, false, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetPortStats, "get_port_stats", 1, false, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetPortStatus, "get_port_status", 1, false, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdSetPortAttr, "set_port_attr", 2, true, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetPortXStatsValues, "get_port_xstats_values", 1, false, APIClass::API_CLASS_TYPE_CORE);
+TREX_RPC_CMD_DEFINE(TrexRpcCmdGetPortXStatsNames, "get_port_xstats_names", 1, false, APIClass::API_CLASS_TYPE_CORE);
/**
* stream cmds
diff --git a/src/rpc-server/trex_rpc_cmd.cpp b/src/rpc-server/trex_rpc_cmd.cpp
index 28145f13..265d426b 100644
--- a/src/rpc-server/trex_rpc_cmd.cpp
+++ b/src/rpc-server/trex_rpc_cmd.cpp
@@ -87,7 +87,7 @@ TrexRpcCommand::check_param_count(const Json::Value &params, int expected, Json:
if (params.size() < expected) {
std::stringstream ss;
- ss << "method expects at least '" << expected << "' parameter(s), '" << params.size() << "' provided";
+ ss << "method '" << m_name << "' expects at least " << expected << " parameter(s), " << params.size() << " provided";
generate_parse_err(result, ss.str());
}
}
diff --git a/src/rpc-server/trex_rpc_cmds_table.cpp b/src/rpc-server/trex_rpc_cmds_table.cpp
index 762dd614..cddf19b9 100644
--- a/src/rpc-server/trex_rpc_cmds_table.cpp
+++ b/src/rpc-server/trex_rpc_cmds_table.cpp
@@ -47,6 +47,8 @@ TrexRpcCommandsTable::TrexRpcCommandsTable() {
register_command(new TrexRpcCmdGetPortStats());
register_command(new TrexRpcCmdGetPortStatus());
register_command(new TrexRpcCmdSetPortAttr());
+ register_command(new TrexRpcCmdGetPortXStatsValues());
+ register_command(new TrexRpcCmdGetPortXStatsNames());
/* stream commands */
diff --git a/src/stateless/cp/trex_stateless.h b/src/stateless/cp/trex_stateless.h
index 7ea669df..070cd6de 100644
--- a/src/stateless/cp/trex_stateless.h
+++ b/src/stateless/cp/trex_stateless.h
@@ -91,7 +91,7 @@ public:
}
const TrexRpcServerConfig *m_rpc_req_resp_cfg;
- const TrexPlatformApi *m_platform_api;
+ TrexPlatformApi *m_platform_api;
bool m_rpc_server_verbose;
uint8_t m_port_count;
TrexPublisher *m_publisher;
@@ -137,6 +137,18 @@ public:
void shutdown();
/**
+ * fetch xstats names (keys of dict)
+ *
+ */
+ void encode_xstats_names(Json::Value &global);
+
+ /**
+ * fetch xstats values
+ *
+ */
+ void encode_xstats_values(Json::Value &global);
+
+ /**
* fetch all the stats
*
*/
diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp
index 58410fea..8c6a1573 100644
--- a/src/stateless/cp/trex_stateless_port.cpp
+++ b/src/stateless/cp/trex_stateless_port.cpp
@@ -153,7 +153,7 @@ private:
* trex stateless port
*
**************************/
-TrexStatelessPort::TrexStatelessPort(uint8_t port_id, const TrexPlatformApi *api) : m_dp_events(this) {
+TrexStatelessPort::TrexStatelessPort(uint8_t port_id, const TrexPlatformApi *api) : platform_api(api), m_dp_events(this) {
std::vector<std::pair<uint8_t, uint8_t>> core_pair_list;
m_port_id = port_id;
@@ -581,7 +581,7 @@ void
TrexStatelessPort::get_properties(std::string &driver, uint32_t &speed) {
driver = m_api_info.driver_name;
- speed = m_api_info.speed;
+ speed = platform_api->get_link_speed(m_port_id);
}
bool
@@ -609,10 +609,8 @@ TrexStatelessPort::change_state(port_state_e new_state) {
void
TrexStatelessPort::encode_stats(Json::Value &port) {
- const TrexPlatformApi *api = get_stateless_obj()->get_platform_api();
-
TrexPlatformInterfaceStats stats;
- api->get_interface_stats(m_port_id, stats);
+ platform_api->get_interface_stats(m_port_id, stats);
port["tx_bps"] = stats.m_stats.m_tx_bps;
port["rx_bps"] = stats.m_stats.m_rx_bps;
@@ -664,7 +662,7 @@ TrexStatelessPort::send_message_to_rx(TrexStatelessCpToRxMsgBase *msg) {
uint64_t
TrexStatelessPort::get_port_speed_bps() const {
- return (uint64_t) m_api_info.speed * 1000 * 1000;
+ return (uint64_t) platform_api->get_link_speed(m_port_id) * 1000 * 1000;
}
static inline double
@@ -869,18 +867,6 @@ TrexStatelessPort::get_port_effective_rate(double &pps,
}
-
-void
-TrexStatelessPort::set_promiscuous(bool enabled) {
- get_stateless_obj()->get_platform_api()->set_promiscuous(m_port_id, enabled);
-}
-
-bool
-TrexStatelessPort::get_promiscuous() {
- return get_stateless_obj()->get_platform_api()->get_promiscuous(m_port_id);
-}
-
-
void
TrexStatelessPort::get_macaddr(std::string &hw_macaddr,
std::string &src_macaddr,
diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h
index 147efc70..00139973 100644
--- a/src/stateless/cp/trex_stateless_port.h
+++ b/src/stateless/cp/trex_stateless_port.h
@@ -363,14 +363,6 @@ public:
double &percentage);
- /**
- * set port promiscuous on/off
- *
- * @param enabled
- */
- void set_promiscuous(bool enabled);
- bool get_promiscuous();
-
void get_macaddr(std::string &hw_macaddr,
std::string &src_macaddr,
std::string &dst_macaddr);
@@ -443,6 +435,7 @@ private:
port_state_e m_port_state;
TrexPlatformApi::intf_info_st m_api_info;
+ const TrexPlatformApi *platform_api;
uint16_t m_rx_count_num;
uint16_t m_rx_caps;
diff --git a/src/trex_defs.h b/src/trex_defs.h
index c659c337..d8139a83 100644
--- a/src/trex_defs.h
+++ b/src/trex_defs.h
@@ -16,6 +16,7 @@ limitations under the License.
#include <set>
#include <queue>
#include <vector>
+#include <string>
#ifndef __TREX_DEFS_H__
#define __TREX_DEFS_H__
@@ -52,5 +53,7 @@ struct cpu_vct_st {
typedef std::set<uint32_t> flow_stat_active_t;
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;
#endif
diff --git a/src/trex_port_attr.h b/src/trex_port_attr.h
new file mode 100755
index 00000000..037a3de3
--- /dev/null
+++ b/src/trex_port_attr.h
@@ -0,0 +1,91 @@
+/*
+Copyright (c) 2015-2015 Cisco Systems, Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#ifndef __TREX_PORT_ATTR_H__
+#define __TREX_PORT_ATTR_H__
+
+#include <string>
+#include <vector>
+#include <rte_ethdev.h>
+#include "trex_defs.h"
+
+
+class TRexPortAttr {
+public:
+ TRexPortAttr(uint8_t total_ports, bool is_virtual = false) : total_ports(total_ports) {
+ flag_is_virtual = is_virtual;
+ m_link.resize(total_ports);
+ intf_info_st.resize(total_ports);
+ }
+
+/* UPDATES */
+ virtual void update_link_status(uint8_t port_id);
+ virtual void update_link_status_nowait(uint8_t port_id);
+ virtual void reset_xstats(uint8_t port_id);
+ virtual void update_info();
+
+/* GETTERS */
+ virtual bool get_promiscuous(uint8_t port_id);
+ virtual void macaddr_get(uint8_t port_id, struct ether_addr *mac_addr);
+ virtual uint32_t get_link_speed(uint8_t port_id) { return m_link[port_id].link_speed; } // L1 Mbps
+ virtual bool is_link_duplex(uint8_t port_id) { return (m_link[port_id].link_duplex ? true : false); }
+ virtual bool is_link_autoneg(uint8_t port_id) { return (m_link[port_id].link_autoneg ? true : false); }
+ 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);
+
+/* 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_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<struct rte_eth_xstat> xstats_values_tmp;
+ std::vector<struct rte_eth_xstat_name> xstats_names_tmp;
+
+ struct mac_cfg_st {
+ uint8_t hw_macaddr[6];
+ uint8_t src_macaddr[6];
+ uint8_t dst_macaddr[6];
+ };
+
+ struct intf_info_st_type {
+ mac_cfg_st mac_info;
+ std::string pci_addr;
+ std::string description;
+ int numa_node;
+ };
+
+ std::vector <intf_info_st_type> intf_info_st;
+
+};
+
+
+#endif /* __TREX_PORT_ATTR_H__ */