diff options
author | Yaroslav Brustinov <ybrustin@cisco.com> | 2016-10-13 06:53:19 +0300 |
---|---|---|
committer | Yaroslav Brustinov <ybrustin@cisco.com> | 2016-10-28 14:38:32 +0200 |
commit | 00bfc58e6f76f7a67a6b62f297f72792534fef52 (patch) | |
tree | 60624bd2f75ed2ae4de1c962ef195b173ae628a8 | |
parent | 653629bee578b4888bd0c144386c03a4b0d08eef (diff) |
new port attr commands: flow control, link status, led status
add user friendly description to ports
add xstats
enable start with link down at stateless. in CPP status will update itself upon link up, in Python need to restart client at this phase.
Signed-off-by: Yaroslav Brustinov <ybrustin@cisco.com>
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 ¶ms, 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 ¶ms, Json::Value &result) { } /** + * get port extended stats names (keys of dict) + * + */ +trex_rpc_cmd_rc_e +TrexRpcCmdGetPortXStatsNames::_run(const Json::Value ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms, 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__ */ |