diff options
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__ */ |