From ab28fccc187c6134eeb0400ce0b113a77e498bb2 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 9 Nov 2016 18:19:09 +0200 Subject: RX features - added port attributes for IPv4 and DG Signed-off-by: imarom --- .../stl/trex_stl_lib/trex_stl_client.py | 94 ++++++++++++++++------ .../stl/trex_stl_lib/trex_stl_port.py | 23 ++++-- .../stl/trex_stl_lib/trex_stl_stats.py | 10 ++- .../stl/trex_stl_lib/utils/common.py | 7 ++ .../stl/trex_stl_lib/utils/parsing_opts.py | 8 ++ src/common/basic_utils.cpp | 31 +++++++ src/common/basic_utils.h | 5 ++ src/main_dpdk.cpp | 26 +++--- src/rpc-server/commands/trex_rpc_cmd_general.cpp | 49 +++++------ src/rpc-server/commands/trex_rpc_cmds.h | 2 +- src/trex_port_attr.h | 71 +++++++++++++--- 11 files changed, 240 insertions(+), 86 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 b607ce23..d4d09cd7 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 @@ -12,7 +12,7 @@ from .trex_stl_types import * from .trex_stl_async_client import CTRexAsyncClient from .utils import parsing_opts, text_tables, common -from .utils.common import list_intersect, list_difference, is_sub_list, PassiveTimer +from .utils.common import list_intersect, list_difference, is_sub_list, PassiveTimer, is_valid_ipv4 from .utils.text_opts import * from functools import wraps @@ -336,7 +336,7 @@ class EventsHandler(object): new_info = self.client.ports[port_id].get_formatted_info(sync = False) ev = "port {0} attributes changed".format(port_id) for key, old_val in old_info.items(): - new_val = new_info[key] + new_val = new_info.get(key, 'N/A') if old_val != new_val: ev += '\n {key}: {old} -> {new}'.format( key = key, @@ -811,8 +811,8 @@ class STLClient(object): port_id_list = self.__ports(port_id_list) rc = RC() - for port_id in port_id_list: - rc.add(self.ports[port_id].set_attr(attr_dict)) + for port_id, port_attr_dict in zip(port_id_list, attr_dict): + rc.add(self.ports[port_id].set_attr(port_attr_dict)) return rc @@ -1775,6 +1775,9 @@ class STLClient(object): self.reset(ports = [0, 1]) + self.set_port_attr(ports = [0, 1], ipv4 = ['5.5.5.5', '6.6.6.6']) + return + self.set_rx_queue(ports = [0], size = 1000, rxf = 'all') #base_pkt = Ether()/ARP()/('x'*50) @@ -1914,7 +1917,7 @@ class STLClient(object): @__api_check(True) - def reset(self, ports = None): + def reset(self, ports = None, restart = False): """ Force acquire ports, stop the traffic, remove all streams and clear stats @@ -1922,7 +1925,9 @@ class STLClient(object): ports : list Ports on which to execute the command - + restart: bool + Restart the NICs (link down / up) + :raises: + :exc:`STLError` @@ -1939,7 +1944,7 @@ class STLClient(object): self.clear_stats(ports) self.set_port_attr(ports, promiscuous = False, - #link_up = True, + link_up = True if restart else None, rxf = 'hw') self.remove_rx_sniffer(ports) self.remove_rx_queue(ports) @@ -2720,16 +2725,23 @@ class STLClient(object): link_up = None, led_on = None, flow_ctrl = None, - rxf = None): + rxf = None, + ipv4 = None, + default_gateway = 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 - rxf - 'hw' for hardware rules matching packets only or 'all' all packets + 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 + rxf - 'hw' for hardware rules matching packets only or 'all' all packets + ipv4 - configure IPv4 address for port(s). for multiple ports should be a list + of IPv4 addresses in the same length of the ports array + default_gateway - configure default gateway for port(s). for multiple ports should be a list + in the same length of the ports array :raises: + :exe:'STLError' @@ -2744,22 +2756,55 @@ class STLClient(object): validate_type('led_on', led_on, (bool, type(None))) validate_type('flow_ctrl', flow_ctrl, (int, type(None))) validate_choice('rxf', rxf, ['hw', 'all']) - - # build attributes - attr_dict = {} + + # common attributes for all ports + cmn_attr_dict = {} if promiscuous is not None: - attr_dict['promiscuous'] = {'enabled': promiscuous} + cmn_attr_dict['promiscuous'] = {'enabled': promiscuous} + if link_up is not None: - attr_dict['link_status'] = {'up': link_up} + cmn_attr_dict['link_status'] = {'up': link_up} + if led_on is not None: - attr_dict['led_status'] = {'on': led_on} + cmn_attr_dict['led_status'] = {'on': led_on} + if flow_ctrl is not None: - attr_dict['flow_ctrl_mode'] = {'mode': flow_ctrl} + cmn_attr_dict['flow_ctrl_mode'] = {'mode': flow_ctrl} + if rxf is not None: - attr_dict['rx_filter_mode'] = {'mode': rxf} + cmn_attr_dict['rx_filter_mode'] = {'mode': rxf} + # each port starts with a set of the common attributes + attr_dict = [dict(cmn_attr_dict) for _ in ports] + + # IPv4 + if ipv4 is not None: + ipv4_list = listify(ipv4) + + if len(ipv4_list) != len(ports): + raise STLError("'ipv4' must be a list in the same length of ports - 'ports': {0}, 'ip': {1}".format(ports, ipv4_list)) + + for ipv4, port_attr in zip(ipv4_list, attr_dict): + if not is_valid_ipv4(ipv4): + raise STLError("invalid IPv4 address provided: '{0}'".format(ipv4)) + port_attr['ipv4'] = {'addr': ipv4} + + + # default gateway + if default_gateway is not None: + dg_list = listfy(default_gateway) + + if len(dg_list) != len(ports): + raise STLError("'default_gateway' must be a list in the same length of ports - 'ports': {0}, 'default_gateway': {1}".format(ports, dg_list)) + + for dg, port_attr in zip(dg_list, attr_dict): + if not is_valid_ipv4(dg): + raise STLError("invalid IPv4 address provided: '{0}'".format(ipv4)) + port_attr['default_gateway'] = {'addr': dg} + + # no attributes to set - if not attr_dict: + if not any(attr_dict): return self.logger.pre_cmd("Applying attributes on port(s) {0}:".format(ports)) @@ -3076,13 +3121,14 @@ class STLClient(object): parser = parsing_opts.gen_parser(self, "reset", self.reset_line.__doc__, - parsing_opts.PORT_LIST_WITH_ALL) + parsing_opts.PORT_LIST_WITH_ALL, + parsing_opts.PORT_RESTART) opts = parser.parse_args(line.split(), default_ports = self.get_acquired_ports(), verify_acquired = True) if not opts: return opts - self.reset(ports = opts.ports) + self.reset(ports = opts.ports, restart = opts.restart) return RC_OK() diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py index 96c5e832..418ee5a6 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py @@ -785,10 +785,15 @@ class Port(object): else: info['rx_filter_mode'] = 'N/A' + + info['mac_addr'] = attr.get('mac_addr', 'N/A') + info['ipv4'] = attr.get('ipv4', 'N/A') + info['default_gateway'] = attr.get('default_gateway', 'N/A') + info['next_hop_mac'] = attr.get('next_hop_mac', 'N/A') + # RX info rx_info = self.status['rx_info'] - # RX sniffer if 'sniffer' in rx_info: sniffer = rx_info['sniffer'] @@ -819,16 +824,18 @@ class Port(object): info = self.get_formatted_info() - return {"driver": info['driver'], - "description": info.get('description', 'N/A')[:18], - "HW src mac": info['hw_macaddr'], - "SW src mac": info['src_macaddr'], - "SW dst mac": info['dst_macaddr'], - "PCI Address": info['pci_addr'], - "NUMA Node": info['numa'], + return {"driver": info['driver'], + "description": info.get('description', 'N/A')[:18], + "MAC addr": info['mac_addr'], + "Next hop MAC": info['next_hop_mac'], + "IPv4": info['ipv4'], + "Default gateway": info['default_gateway'], + "PCI Address": info['pci_addr'], + "NUMA Node": info['numa'], "--": "", "---": "", "----": "", + "-----": "", "link speed": info['speed'], "port status": info['status'], "link status": info['link'], 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 5e71b7f2..55620689 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 @@ -670,13 +670,15 @@ class CTRexInfoGenerator(object): ("promiscuous", []), ("flow ctrl", []), ("--", []), - ("HW src mac", []), - ("SW src mac", []), - ("SW dst mac", []), + ("MAC addr", []), + ("Next hop MAC", []), ("---", []), + ("IPv4", []), + ("Default gateway", []), + ("----", []), ("PCI Address", []), ("NUMA Node", []), - ("----", []), + ("-----", []), ("RX Filter Mode", []), ("RX Queueing", []), ("RX sniffer", []), diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/common.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/common.py index 72ee8972..f0da9a08 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/common.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/common.py @@ -3,6 +3,7 @@ import sys import string import random import time +import socket try: import pwd @@ -86,3 +87,9 @@ class PassiveTimer(object): return (time.time() > self.expr_sec) +def is_valid_ipv4 (addr): + try: + socket.inet_pton(socket.AF_INET, addr) + return True + except socket.error: + return False 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 715a741e..b93a797d 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 @@ -45,9 +45,11 @@ FLOW_CTRL = 28 SUPPORTED = 29 RX_FILTER_MODE = 30 + OUTPUT_FILENAME = 31 ALL_FILES = 32 LIMIT = 33 +PORT_RESTART = 34 GLOBAL_STATS = 50 PORT_STATS = 51 @@ -322,6 +324,12 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'], 'type': str}), + PORT_RESTART: ArgumentPack(['-r', '--restart'], + {'help': 'hard restart port(s)', + 'dest': 'restart', + 'default': False, + 'action': 'store_true'}), + ALL_FILES: ArgumentPack(['--all'], {'help': 'change RX port filter to fetch all packets', diff --git a/src/common/basic_utils.cpp b/src/common/basic_utils.cpp index f169c29f..52988131 100755 --- a/src/common/basic_utils.cpp +++ b/src/common/basic_utils.cpp @@ -20,6 +20,10 @@ limitations under the License. #include #include +#include "pal_utl.h" + +int my_inet_pton4(const char *src, unsigned char *dst); + bool utl_is_file_exists (const std::string& name) { if (FILE *file = fopen(name.c_str(), "r")) { fclose(file); @@ -190,6 +194,13 @@ void utl_macaddr_to_str(const uint8_t *macaddr, std::string &output) { } +std::string utl_macaddr_to_str(const uint8_t *macaddr) { + std::string tmp; + utl_macaddr_to_str(macaddr, tmp); + + return tmp; +} + /** * generate a random connection handler * @@ -248,3 +259,23 @@ void utl_set_coredump_size(long size, bool map_huge_pages) { fprintf(fp, "%08x\n", mask); fclose(fp); } + +uint32_t utl_ipv4_to_uint32(const char *ipv4_str, uint32_t &ipv4_num) { + + uint32_t tmp; + + int rc = my_inet_pton4(ipv4_str, (unsigned char *)&tmp); + if (!rc) { + return (0); + } + + ipv4_num = PAL_NTOHL(tmp); + + return (1); +} + +std::string utl_uint32_to_ipv4(uint32_t ipv4_addr) { + std::stringstream ss; + ss << ((ipv4_addr >> 24) & 0xff) << "." << ((ipv4_addr >> 16) & 0xff) << "." << ((ipv4_addr >> 8) & 0xff) << "." << (ipv4_addr & 0xff); + return ss.str(); +} diff --git a/src/common/basic_utils.h b/src/common/basic_utils.h index f6250a2b..fdbd2f08 100755 --- a/src/common/basic_utils.h +++ b/src/common/basic_utils.h @@ -86,6 +86,8 @@ bool utl_is_file_exists (const std::string& name) ; void utl_macaddr_to_str(const uint8_t *macaddr, std::string &output); +std::string utl_macaddr_to_str(const uint8_t *macaddr); + std::string utl_generate_random_str(unsigned int &seed, int len); /** @@ -98,6 +100,9 @@ std::string utl_generate_random_str(unsigned int &seed, int len); */ void utl_set_coredump_size(long size, bool map_huge_pages = false); +uint32_t utl_ipv4_to_uint32(const char *ipv4_str, uint32_t &ipv4_num); +std::string utl_uint32_to_ipv4(uint32_t ipv4_addr); + #endif diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index fcee6a58..406b9c20 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -308,7 +308,7 @@ public: | TrexPlatformApi::IF_STAT_PAYLOAD; } virtual CFlowStatParser *get_flow_stat_parser(); - virtual int set_rcv_all(CPhyEthIF * _if, bool set_on) {return 0;} + virtual int set_rcv_all(CPhyEthIF * _if, bool set_on) {return -ENOTSUP;} }; class CTRexExtendedDriverBase40G : public CTRexExtendedDriverBase10G { @@ -1507,6 +1507,7 @@ int DpdkTRexPortAttr::set_led(bool on){ int DpdkTRexPortAttr::get_flow_ctrl(int &mode) { int ret = rte_eth_dev_flow_ctrl_get(m_port_id, &fc_conf_tmp); if (ret) { + mode = -1; return ret; } mode = (int) fc_conf_tmp.mode; @@ -3100,6 +3101,8 @@ void CGlobalTRex::pre_test() { exit(1); } memcpy(CGlobalInfo::m_options.m_mac_addr[port_id].u.m_mac.dest, mac, ETHER_ADDR_LEN); + m_ports[port_id].get_port_attr()->set_next_hop_mac(mac); + // if port is connected in loopback, no need to send gratuitous ARP. It will only confuse our ingress counters. if (pretest.is_loopback(port_id)) CGlobalInfo::m_options.m_ip_cfg[port_id].set_grat_arp_needed(false); @@ -4170,20 +4173,9 @@ CGlobalTRex:: publish_async_port_attr_changed(uint8_t port_id) { Json::Value data; data["port_id"] = port_id; TRexPortAttr * _attr = m_ports[port_id].get_port_attr(); - - /* attributes */ - data["attr"]["speed"] = _attr->get_link_speed(); - data["attr"]["promiscuous"]["enabled"] = _attr->get_promiscuous(); - data["attr"]["link"]["up"] = _attr->is_link_up(); - data["attr"]["rx_filter_mode"] = _attr->get_rx_filter_mode(); - - int mode; - int ret = _attr->get_flow_ctrl(mode); - if (ret != 0) { - mode = -1; - } - data["attr"]["fc"]["mode"] = mode; - + + _attr->to_json(data["attr"]); + m_zmq_publisher.publish_event(TrexPublisher::EVENT_PORT_ATTR_CHANGED, data); } @@ -4687,6 +4679,10 @@ bool CPhyEthIF::Create(uint8_t portid) { m_last_tx_pps = 0.0; m_port_attr = g_trex.m_drv->create_port_attr(portid); + + m_port_attr->set_ipv4(CGlobalInfo::m_options.m_ip_cfg[m_port_id].get_ip()); + m_port_attr->set_default_gateway(CGlobalInfo::m_options.m_ip_cfg[m_port_id].get_def_gw()); + return true; } diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index b63c2faa..5ee853b8 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -292,9 +292,6 @@ TrexRpcCmdGetSysInfo::_run(const Json::Value ¶ms, Json::Value &result) { for (int i = 0; i < main->get_port_count(); i++) { string driver; - string hw_macaddr; - string src_macaddr; - string dst_macaddr; string pci_addr; string description; supp_speeds_t supp_speeds; @@ -303,7 +300,6 @@ TrexRpcCmdGetSysInfo::_run(const Json::Value ¶ms, Json::Value &result) { TrexStatelessPort *port = main->get_port_by_id(i); port->get_properties(driver); - port->get_macaddr(hw_macaddr, src_macaddr, dst_macaddr); port->get_pci_info(pci_addr, numa); main->get_platform_api()->getPortAttrObj(i)->get_description(description); @@ -313,9 +309,6 @@ TrexRpcCmdGetSysInfo::_run(const Json::Value ¶ms, Json::Value &result) { section["ports"][i]["driver"] = driver; section["ports"][i]["description"] = description; - section["ports"][i]["hw_macaddr"] = hw_macaddr; - section["ports"][i]["src_macaddr"] = src_macaddr; - section["ports"][i]["dst_macaddr"] = dst_macaddr; section["ports"][i]["pci_addr"] = pci_addr; section["ports"][i]["numa"] = numa; @@ -363,6 +356,23 @@ TrexRpcCmdSetPortAttr::parse_rx_filter_mode(const Json::Value &msg, uint8_t port return get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_rx_filter_mode(filter_mode); } +int +TrexRpcCmdSetPortAttr::parse_ipv4(const Json::Value &msg, uint8_t port_id, Json::Value &result) { + + const std::string ipv4_str = parse_string(msg, "addr", result); + + uint32_t ipv4_addr; + if (!utl_ipv4_to_uint32(ipv4_str.c_str(), ipv4_addr)) { + std::stringstream ss; + ss << "invalid IPv4 address: '" << ipv4_str << "'"; + generate_parse_err(result, ss.str()); + } + + get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_ipv4(ipv4_addr); + return (0); +} + + /** * set port commands * @@ -408,15 +418,20 @@ TrexRpcCmdSetPortAttr::_run(const Json::Value ¶ms, Json::Value &result) { ret = parse_rx_filter_mode(attr[name], port_id, result); } + else if (name == "ipv4") { + ret = parse_ipv4(attr[name], port_id, result); + } + + /* unknown attribute */ else { generate_execute_err(result, "Not recognized attribute: " + name); break; } + /* check error code */ if ( ret == -ENOTSUP ) { generate_execute_err(result, "Error applying " + name + ": operation is not supported for this NIC."); - } - else if (ret) { + } else if (ret) { generate_execute_err(result, "Error applying " + name + " attribute, return value: " + to_string(ret)); } } @@ -592,20 +607,8 @@ 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"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->get_promiscuous(); - result["result"]["attr"]["link"]["up"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->is_link_up(); - result["result"]["attr"]["speed"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->get_link_speed(); - - int mode; - int ret = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->get_flow_ctrl(mode); - if (ret != 0) { - mode = -1; - } - result["result"]["attr"]["fc"]["mode"] = mode; - - /* RX filter */ - result["result"]["attr"]["rx_filter_mode"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->get_rx_filter_mode(); - + get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->to_json(result["result"]["attr"]); + /* RX info */ port->get_rx_features().to_json(result["result"]["rx_info"]); diff --git a/src/rpc-server/commands/trex_rpc_cmds.h b/src/rpc-server/commands/trex_rpc_cmds.h index b8a5d323..49610eb8 100644 --- a/src/rpc-server/commands/trex_rpc_cmds.h +++ b/src/rpc-server/commands/trex_rpc_cmds.h @@ -96,7 +96,7 @@ TREX_RPC_CMD_DEFINE(TrexRpcCmdGetPortXStatsNames, "get_port_xstats_names", 1, TREX_RPC_CMD_DEFINE_EXTENDED(TrexRpcCmdSetPortAttr, "set_port_attr", 2, true, APIClass::API_CLASS_TYPE_CORE, int parse_rx_filter_mode(const Json::Value &msg, uint8_t port_id, Json::Value &result); - + int parse_ipv4(const Json::Value &msg, uint8_t port_id, Json::Value &result); ); diff --git a/src/trex_port_attr.h b/src/trex_port_attr.h index 5ba4f7e2..ccf12ae2 100755 --- a/src/trex_port_attr.h +++ b/src/trex_port_attr.h @@ -21,10 +21,17 @@ limitations under the License. #include #include "rte_ethdev_includes.h" #include "trex_defs.h" - +#include "common/basic_utils.h" class TRexPortAttr { public: + + TRexPortAttr() { + m_ipv4 = 0; + m_default_gateway = 0; + memset(m_next_hop_mac, 0, sizeof(m_next_hop_mac)); + } + virtual ~TRexPortAttr(){} /* UPDATES */ @@ -50,7 +57,10 @@ public: virtual bool is_link_change_supported() { return flag_is_link_change_supported; } virtual void get_description(std::string &description) { description = intf_info_st.description; } virtual void get_supported_speeds(supp_speeds_t &supp_speeds) = 0; - + uint32_t get_ipv4() {return m_ipv4;} + uint32_t get_default_gateway() {return m_default_gateway;} + const uint8_t * get_next_hop_mac() {return m_next_hop_mac;} + virtual std::string get_rx_filter_mode() { switch (m_rx_filter_mode) { case RX_FILTER_MODE_ALL: @@ -70,21 +80,60 @@ public: virtual int set_flow_ctrl(int mode) = 0; virtual int set_led(bool on) = 0; virtual int set_rx_filter_mode(rx_filter_mode_e mode) = 0; - + + void set_ipv4(uint32_t addr) { + m_ipv4 = addr; + } + + void set_default_gateway(uint32_t addr) { + m_default_gateway = addr; + } + + void set_next_hop_mac(const uint8_t *next_hop_mac) { + memcpy(m_next_hop_mac, next_hop_mac, sizeof(m_next_hop_mac)); + } + /* DUMPS */ virtual void dump_link(FILE *fd) = 0; + /* dump object status to JSON */ + void to_json(Json::Value &output) { + struct ether_addr dpdk_mac_addr; + macaddr_get(&dpdk_mac_addr); + + uint8_t mac_addr[6]; + memcpy(mac_addr, dpdk_mac_addr.addr_bytes, 6); + + output["mac_addr"] = utl_macaddr_to_str(mac_addr); + output["next_hop_mac"] = utl_macaddr_to_str(m_next_hop_mac); + output["promiscuous"]["enabled"] = get_promiscuous(); + output["link"]["up"] = is_link_up(); + output["speed"] = get_link_speed(); + output["rx_filter_mode"] = get_rx_filter_mode(); + output["ipv4"] = utl_uint32_to_ipv4(get_ipv4()); + output["default_gateway"] = utl_uint32_to_ipv4(get_default_gateway()); + + int mode; + get_flow_ctrl(mode); + output["fc"]["mode"] = mode; + + } + protected: - uint8_t m_port_id; - rte_eth_link m_link; - struct rte_eth_dev_info dev_info; - + + uint8_t m_port_id; + rte_eth_link m_link; + uint32_t m_ipv4; + uint32_t m_default_gateway; + uint8_t m_next_hop_mac[6]; + struct rte_eth_dev_info dev_info; + rx_filter_mode_e m_rx_filter_mode; - bool flag_is_virtual; - bool flag_is_fc_change_supported; - bool flag_is_led_change_supported; - bool flag_is_link_change_supported; + bool flag_is_virtual; + bool flag_is_fc_change_supported; + bool flag_is_led_change_supported; + bool flag_is_link_change_supported; struct intf_info_st { -- cgit 1.2.3-korg