new port attr commands: flow control, link status, led status
authorYaroslav Brustinov <[email protected]>
Thu, 13 Oct 2016 03:53:19 +0000 (06:53 +0300)
committerYaroslav Brustinov <[email protected]>
Fri, 28 Oct 2016 12:38:32 +0000 (14:38 +0200)
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 <[email protected]>
20 files changed:
scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py
scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py
scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py
scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py
scripts/dpdk_nic_bind.py
scripts/dpdk_setup_ports.py
scripts/t-rex-64
src/debug.cpp
src/internal_api/trex_platform_api.h
src/main_dpdk.cpp
src/main_dpdk.h
src/rpc-server/commands/trex_rpc_cmd_general.cpp
src/rpc-server/commands/trex_rpc_cmds.h
src/rpc-server/trex_rpc_cmd.cpp
src/rpc-server/trex_rpc_cmds_table.cpp
src/stateless/cp/trex_stateless.h
src/stateless/cp/trex_stateless_port.cpp
src/stateless/cp/trex_stateless_port.h
src/trex_defs.h
src/trex_port_attr.h [new file with mode: 0755]

index 82aa932..b11ddbe 100755 (executable)
@@ -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):
index aa002d5..dc06f9f 100755 (executable)
@@ -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)
index 5d9cdca..eaa5e8b 100644 (file)
@@ -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
 
index 8ae8698..148f771 100755 (executable)
@@ -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)
 
index 44d4e82..ed0462e 100755 (executable)
@@ -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'''
index 58d5869..2782384 100755 (executable)
@@ -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:
index 4e5c0fa..4d0d781 100755 (executable)
@@ -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
index 542d2fa..3a9cd50 100644 (file)
@@ -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;
index a55e8cd..998b6d4 100644 (file)
@@ -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;
index 46fa733..9ef08cf 100644 (file)
@@ -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 {
index 97994c4..640c73e 100644 (file)
@@ -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;
index 342ec59..f6b088a 100644 (file)
@@ -346,18 +346,38 @@ trex_rpc_cmd_rc_e
 TrexRpcCmdSetPortAttr::_run(const Json::Value &params, Json::Value &result) {
 
     uint8_t port_id = parse_port(params, result);
-    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
 
     const Json::Value &attr = parse_object(params, "attr", result);
-
+    int ret = 0;
     /* iterate over all attributes in the dict */
     for (const std::string &name : attr.getMemberNames()) {
-
-        /* handle promiscuous */
         if (name == "promiscuous") {
             bool enabled = parse_bool(attr[name], "enabled", result);
-            port->set_promiscuous(enabled);
+            ret = get_stateless_obj()->get_platform_api()->set_promiscuous(port_id, enabled);
+        }
+        else if (name == "link_status") {
+            bool up = parse_bool(attr[name], "up", result);
+            ret = get_stateless_obj()->get_platform_api()->set_link_status(port_id, up);
+        }
+        else if (name == "led_status") {
+            bool on = parse_bool(attr[name], "on", result);
+            ret = get_stateless_obj()->get_platform_api()->set_led_status(port_id, on);
+        } else if (name == "flow_ctrl_mode") {
+            int mode = parse_int(attr[name], "mode", result);
+            ret = get_stateless_obj()->get_platform_api()->set_flow_ctrl(port_id, mode);
+        } else {
+            generate_execute_err(result, "Not recognized attribute: " + name);
+            break;
         }
+        if (ret != 0){
+            if ( ret == -ENOTSUP ) {
+                generate_execute_err(result, "Error applying " + name + ": operation is not supported for this NIC.");
+            }
+            else if (ret) {
+                generate_execute_err(result, "Error applying " + name + " attribute, return value: " + to_string(ret));
+            }
+        }
+        break;
     }
 
     result["result"] = Json::objectValue;
@@ -436,6 +456,60 @@ TrexRpcCmdRelease::_run(const Json::Value &params, Json::Value &result) {
     return (TREX_RPC_CMD_OK);
 }
 
+/**
+ * get port extended stats names (keys of dict)
+ *
+ */
+trex_rpc_cmd_rc_e
+TrexRpcCmdGetPortXStatsNames::_run(const Json::Value &params, Json::Value &result) {
+
+    uint8_t port_id = parse_port(params, result);
+    xstats_names_t xstats_names;
+
+    int ret = get_stateless_obj()->get_platform_api()->get_xstats_names(port_id, xstats_names);
+    if (ret < 0) {
+        if ( ret == -ENOTSUP ) {
+            generate_execute_err(result, "Operation not supported");
+        }
+        else if (ret) {
+            generate_execute_err(result, "Operation failed, error code: " + to_string(ret));
+        }
+    } else {
+        for (int i=0; i<xstats_names.size(); i++) {
+            result["result"]["xstats_names"].append(xstats_names[i]);
+        }
+    }
+
+    return (TREX_RPC_CMD_OK);
+}
+
+/**
+ * get port extended stats (values of dict)
+ *
+ */
+trex_rpc_cmd_rc_e
+TrexRpcCmdGetPortXStatsValues::_run(const Json::Value &params, Json::Value &result) {
+
+    uint8_t port_id = parse_port(params, result);
+    xstats_values_t xstats_values;
+
+    int ret = get_stateless_obj()->get_platform_api()->get_xstats_values(port_id, xstats_values);
+    if (ret < 0) {
+        if ( ret == -ENOTSUP ) {
+            generate_execute_err(result, "Operation not supported");
+        }
+        else if (ret) {
+            generate_execute_err(result, "Operation failed, error code: " + to_string(ret));
+        }
+    } else {
+        for (int i=0; i<xstats_values.size(); i++) {
+            result["result"]["xstats_values"].append((Json::Value::UInt64) xstats_values[i]);
+        }
+    }
+
+    return (TREX_RPC_CMD_OK);
+}
+
 /**
  * get port stats
  *
@@ -477,7 +551,7 @@ TrexRpcCmdGetPortStatus::_run(const Json::Value &params, Json::Value &result) {
     result["result"]["max_stream_id"] = port->get_max_stream_id();
 
     /* attributes */
-    result["result"]["attr"]["promiscuous"]["enabled"] = port->get_promiscuous();
+    result["result"]["attr"]["promiscuous"]["enabled"] = get_stateless_obj()->get_platform_api()->get_promiscuous(port_id);
 
     return (TREX_RPC_CMD_OK);
 }
index a68796a..5fde1d0 100644 (file)
@@ -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
index 28145f1..265d426 100644 (file)
@@ -87,7 +87,7 @@ TrexRpcCommand::check_param_count(const Json::Value &params, int expected, Json:
 
     if (params.size() < expected) {
         std::stringstream ss;
-        ss << "method expects at least '" << expected << "' parameter(s), '" << params.size() << "' provided";
+        ss << "method '" << m_name << "' expects at least " << expected << " parameter(s), " << params.size() << " provided";
         generate_parse_err(result, ss.str());
     }
 }
index 762dd61..cddf19b 100644 (file)
@@ -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 */
index 7ea669d..070cd6d 100644 (file)
@@ -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;
@@ -136,6 +136,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
      * 
index 58410fe..8c6a157 100644 (file)
@@ -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,
index 147efc7..0013997 100644 (file)
@@ -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;
index c659c33..d8139a8 100644 (file)
@@ -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 (executable)
index 0000000..037a3de
--- /dev/null
@@ -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__ */