diff options
author | 2016-11-03 16:33:52 +0200 | |
---|---|---|
committer | 2016-11-03 16:33:52 +0200 | |
commit | 234779fd32e747f4ac918f3c39e59618dde0f2d7 (patch) | |
tree | 2ba641354b6d6c751f94de44f9453dcbec0e19aa | |
parent | 0ed685e077e8533ffe6d96f5d1fefcdd42626763 (diff) |
moved RX filter feature to port attr
Signed-off-by: imarom <imarom@cisco.com>
20 files changed, 368 insertions, 175 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 2e3f681c..907e405a 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 @@ -322,12 +322,16 @@ class EventsHandler(object): # port attr changed elif (event_type == 8): + port_id = int(data['port_id']) + if data['attr'] == self.client.ports[port_id].attr: return # false alarm - old_info = self.client.ports[port_id].get_info() + + old_info = self.client.ports[port_id].get_formatted_info() self.__async_event_port_attr_changed(port_id, data['attr']) - new_info = self.client.ports[port_id].get_info() + + new_info = self.client.ports[port_id].get_formatted_info() ev = "port {0} attributes changed".format(port_id) for key, old_val in old_info.items(): new_val = new_info[key] @@ -1739,10 +1743,6 @@ class STLClient(object): """ - rc = self.ports[0].set_rx_filter_mode("all") - if not rc: - raise STLError(rc) - self.logger.pre_cmd("Pinging the server on '{0}' port '{1}': ".format(self.connection_info['server'], self.connection_info['sync_port'])) rc = self._transmit("ping", api_class = None) @@ -2630,7 +2630,13 @@ class STLClient(object): @__api_check(True) - def set_port_attr (self, ports = None, promiscuous = None, link_up = None, led_on = None, flow_ctrl = None): + def set_port_attr (self, + ports = None, + promiscuous = None, + link_up = None, + led_on = None, + flow_ctrl = None, + rx_filter_mode = None): """ Set port attributes @@ -2639,7 +2645,7 @@ class STLClient(object): 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 - + rx_filter_mode - 'hw' for hardware rules matching packets only or 'all' all packets :raises: + :exe:'STLError' @@ -2653,6 +2659,7 @@ class STLClient(object): 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))) + validate_choice('rx_filter_mode', rx_filter_mode, ['hw', 'all']) # build attributes attr_dict = {} @@ -2664,7 +2671,9 @@ class STLClient(object): attr_dict['led_status'] = {'on': led_on} if flow_ctrl is not None: attr_dict['flow_ctrl_mode'] = {'mode': flow_ctrl} - + if rx_filter_mode is not None: + attr_dict['rx_filter_mode'] = {'mode': rx_filter_mode} + # no attributes to set if not attr_dict: return @@ -3234,7 +3243,7 @@ class STLClient(object): '''Sets port attributes ''' parser = parsing_opts.gen_parser(self, - "port_attr", + "portattr", self.set_port_attr_line.__doc__, parsing_opts.PORT_LIST_WITH_ALL, parsing_opts.PROMISCUOUS, @@ -3242,19 +3251,20 @@ class STLClient(object): parsing_opts.LED_STATUS, parsing_opts.FLOW_CTRL, parsing_opts.SUPPORTED, + parsing_opts.RX_FILTER_MODE, ) 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.UP_DOWN_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) + opts.prom = parsing_opts.ON_OFF_DICT.get(opts.prom) + opts.link = parsing_opts.UP_DOWN_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 not filter(lambda x:x is not None, [opts.prom, opts.link, opts.led, opts.flow_ctrl, opts.supp]): + if not list(filter(lambda x:x is not None, [opts.prom, opts.link, opts.led, opts.flow_ctrl, opts.supp, opts.rx_filter_mode])): self.show_stats_line("--ps --port {0}".format(' '.join(str(port) for port in opts.ports))) return @@ -3268,7 +3278,7 @@ class STLClient(object): print(' Flow control: %s' % info['fc_supported']) print('') else: - return self.set_port_attr(opts.ports, opts.prom, opts.link, opts.led, opts.flow_ctrl) + return self.set_port_attr(opts.ports, opts.prom, opts.link, opts.led, opts.flow_ctrl, opts.rx_filter_mode) 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 bf0251b8..59793495 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 @@ -128,10 +128,10 @@ class Port(object): return RC_OK(data) def get_speed_bps (self): - return (self.info['speed'] * 1000 * 1000 * 1000) + return (self.attr['speed'] * 1000 * 1000 * 1000) def get_formatted_speed (self): - return "{0} Gbps".format(self.info['speed']) + return "%g Gb/s" % (self.attr['speed'] / 1000) def is_acquired(self): return (self.handler != None) @@ -252,9 +252,6 @@ class Port(object): # attributes self.attr = rc.data()['attr'] - if 'speed' in rc.data(): - self.info['speed'] = rc.data()['speed'] // 1000 - return self.ok() @@ -487,14 +484,19 @@ class Port(object): return self.ok() + # @writeable - def set_rx_filter_mode (self, filter_mode): - assert(filter_mode in ["hw", "all"]) + def start_rx_capture (self, pcap_filename, limit): + + prefix, suffix = pcap_filename.split('.') + filename = "{0}-{1}.{2}".format(prefix, self.port_id, suffix) - params = {"handler": self.handler, - "port_id": self.port_id, - "type": "filter_mode", - "filter_type": filter_mode} + params = {"handler": self.handler, + "port_id": self.port_id, + "type": "capture", + "enabled": True, + "pcap_filename": filename, + "limit": limit} rc = self.transmit("set_rx_feature", params) if rc.bad(): @@ -675,8 +677,8 @@ class Port(object): format_time(exp_time_factor_sec))) print("\n") - # generate port info - def get_info (self): + # generate formatted (console friendly) port info + def get_formatted_info (self): info = dict(self.info) info['status'] = self.get_port_state_name() @@ -719,6 +721,13 @@ class Port(object): else: info['is_virtual'] = 'N/A' + if 'speed' in self.attr: + info['speed'] = self.get_formatted_speed() + else: + info['speed'] = 'N/A' + + info['rx_filter_mode'] = self.attr.get('rx_filter_mode', 'N/A') + return info @@ -731,7 +740,7 @@ class Port(object): def generate_port_status(self): - info = self.get_info() + info = self.get_formatted_info() return {"driver": info['driver'], "description": info.get('description', 'N/A')[:18], @@ -742,11 +751,14 @@ class Port(object): "NUMA Node": info['numa'], "--": "", "---": "", - "link speed": "{speed} Gb/s".format(speed=info['speed']), + "----": "", + "link speed": info['speed'], "port status": info['status'], "link status": info['link'], "promiscuous" : info['prom'], "flow ctrl" : info['fc'], + + "RX Filter Mode": info['rx_filter_mode'], } def clear_stats(self): @@ -792,7 +804,6 @@ class Port(object): self.last_factor_type = None def async_event_port_attr_changed (self, attr): - self.info['speed'] = attr['speed'] // 1000 self.attr = attr # rest of the events are used for TUI / read only sessions 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 9f601484..7e47eb61 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 @@ -676,6 +676,8 @@ class CTRexInfoGenerator(object): ("---", []), ("PCI Address", []), ("NUMA Node", []), + ("----", []), + ("RX Filter Mode", []), ] ) diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py index aa6c4218..81015ddc 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py @@ -135,6 +135,12 @@ def validate_type(arg_name, arg, valid_types): else: raise STLError('validate_type: valid_types should be type or list or tuple of types') + +def validate_choice (arg_name, arg, choices): + if arg is not None and not arg in choices: + raise STLError("validate_choice: argument '{0}' can only be one of '{1}'".format(arg_name, choices)) + + # throws STLError if not exactly one argument is present def verify_exclusive_arg (args_list): if not (len(list(filter(lambda x: x is not None, args_list))) == 1): 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 7eda8635..0d316c9e 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 @@ -43,6 +43,7 @@ CORE_MASK = 26 DUAL = 27 FLOW_CTRL = 28 SUPPORTED = 29 +RX_FILTER_MODE = 30 GLOBAL_STATS = 50 PORT_STATS = 51 @@ -303,6 +304,12 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'], 'dest': 'flow_ctrl', 'choices': FLOW_CTRL_DICT}), + RX_FILTER_MODE: ArgumentPack(['--rxf'], + {'help': 'Set RX filtering mode', + 'dest': 'rx_filter_mode', + 'choices': ['hw', 'all']}), + + SUPPORTED: ArgumentPack(['--supp'], {'help': 'Show which attributes are supported by current NICs', 'default': None, diff --git a/scripts/trex_show_threads.py b/scripts/trex_show_threads.py index fabe6d68..1824d073 100755 --- a/scripts/trex_show_threads.py +++ b/scripts/trex_show_threads.py @@ -58,8 +58,8 @@ def isnum (x): def find_trex_pid (): procs = [x for x in os.listdir('/proc/') if isnum(x)] for proc in procs: - cmd = open('/proc/{0}/{1}'.format(proc, 'cmdline')).readline() - if '_t-rex' in cmd: + cmd = open('/proc/{0}/{1}'.format(proc, 'comm')).readline() + if cmd.startswith('_t-rex-64'): return proc return None diff --git a/src/flow_stat.cpp b/src/flow_stat.cpp index 84be590f..dae29795 100644 --- a/src/flow_stat.cpp +++ b/src/flow_stat.cpp @@ -968,9 +968,9 @@ void CFlowStatRuleMgr::send_start_stop_msg_to_rx(bool is_start) { TrexStatelessCpToRxMsgBase *msg; if (is_start) { - msg = new TrexStatelessRxStartMsg(); + msg = new TrexStatelessRxEnableLatency(); } else { - msg = new TrexStatelessRxStopMsg(); + msg = new TrexStatelessRxDisableLatency(); } m_ring_to_rx->Enqueue((CGenNode *)msg); } diff --git a/src/internal_api/trex_platform_api.h b/src/internal_api/trex_platform_api.h index 4feb386f..1445d3e9 100644 --- a/src/internal_api/trex_platform_api.h +++ b/src/internal_api/trex_platform_api.h @@ -161,8 +161,6 @@ public: 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 void set_rx_filter_mode(uint8_t port_id, rx_filter_mode_e filter_mode) const = 0; - virtual ~TrexPlatformApi() {} }; @@ -200,7 +198,6 @@ public: int get_mbuf_util(Json::Value &result) const; void mark_for_shutdown() const; CFlowStatParser *get_flow_stat_parser() const; - void set_rx_filter_mode(uint8_t port_id, rx_filter_mode_e filter_mode) const; TRexPortAttr *getPortAttrObj(uint8_t port_id) const; int get_xstats_values(uint8_t port_id, xstats_values_t &xstats_values) const; @@ -281,8 +278,6 @@ public: 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;}; - void set_rx_filter_mode(uint8_t port_id, rx_filter_mode_e filter_mode) const {} - private: int m_dp_core_count; SimTRexPortAttr * m_port_attr; diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index ecf09b46..fcee6a58 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -4175,6 +4175,8 @@ CGlobalTRex:: publish_async_port_attr_changed(uint8_t port_id) { 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) { @@ -6595,6 +6597,21 @@ TRexPortAttr *TrexDpdkPlatformApi::getPortAttrObj(uint8_t port_id) const { return g_trex.m_ports[port_id].get_port_attr(); } + +int DpdkTRexPortAttr::set_rx_filter_mode(rx_filter_mode_e rx_filter_mode) { + + CPhyEthIF *_if = &g_trex.m_ports[m_port_id]; + bool recv_all = (rx_filter_mode == RX_FILTER_MODE_ALL); + int rc = CTRexExtendedDriverDb::Ins()->get_drv()->set_rcv_all(_if, recv_all); + if (rc != 0) { + return (rc); + } + + m_rx_filter_mode = rx_filter_mode; + + return (0); +} + /** * marks the control plane for a total server shutdown * @@ -6605,12 +6622,4 @@ void TrexDpdkPlatformApi::mark_for_shutdown() const { } -void TrexDpdkPlatformApi::set_rx_filter_mode(uint8_t port_id, rx_filter_mode_e filter_mode) const { - - CPhyEthIF *_if = &g_trex.m_ports[port_id]; - - bool recv_all = (filter_mode == RX_FILTER_MODE_ALL); - CTRexExtendedDriverDb::Ins()->get_drv()->set_rcv_all(_if, recv_all); -} - diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index 8599b61b..7baae899 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -291,7 +291,6 @@ TrexRpcCmdGetSysInfo::_run(const Json::Value ¶ms, Json::Value &result) { section["ports"] = Json::arrayValue; for (int i = 0; i < main->get_port_count(); i++) { - uint32_t speed; string driver; string hw_macaddr; string src_macaddr; @@ -302,7 +301,8 @@ TrexRpcCmdGetSysInfo::_run(const Json::Value ¶ms, Json::Value &result) { int numa; TrexStatelessPort *port = main->get_port_by_id(i); - port->get_properties(driver, speed); + + port->get_properties(driver); port->get_macaddr(hw_macaddr, src_macaddr, dst_macaddr); port->get_pci_info(pci_addr, numa); @@ -317,8 +317,8 @@ TrexRpcCmdGetSysInfo::_run(const Json::Value ¶ms, Json::Value &result) { 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; + section["ports"][i]["pci_addr"] = pci_addr; + section["ports"][i]["numa"] = numa; uint16_t caps = port->get_rx_caps(); section["ports"][i]["rx"]["caps"] = Json::arrayValue; @@ -332,7 +332,6 @@ TrexRpcCmdGetSysInfo::_run(const Json::Value ¶ms, Json::Value &result) { section["ports"][i]["rx"]["caps"].append("rx_bytes"); } section["ports"][i]["rx"]["counters"] = port->get_rx_count_num(); - section["ports"][i]["speed"] = (uint16_t) speed / 1000; section["ports"][i]["is_fc_supported"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(i)->is_fc_change_supported(); section["ports"][i]["is_led_supported"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(i)->is_led_change_supported(); section["ports"][i]["is_link_supported"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(i)->is_link_change_supported(); @@ -347,6 +346,23 @@ TrexRpcCmdGetSysInfo::_run(const Json::Value ¶ms, Json::Value &result) { return (TREX_RPC_CMD_OK); } + +int +TrexRpcCmdSetPortAttr::parse_rx_filter_mode(const Json::Value &msg, uint8_t port_id, Json::Value &result) { + const std::string type = parse_choice(msg, "mode", {"hw", "all"}, result); + + rx_filter_mode_e filter_mode; + if (type == "hw") { + filter_mode = RX_FILTER_MODE_HW; + } else if (type == "all") { + filter_mode = RX_FILTER_MODE_ALL; + } else { + assert(0); + } + + return get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_rx_filter_mode(filter_mode); +} + /** * set port commands * @@ -365,26 +381,39 @@ TrexRpcCmdSetPortAttr::_run(const Json::Value ¶ms, Json::Value &result) { const Json::Value &attr = parse_object(params, "attr", result); int ret = 0; bool changed = false; + /* iterate over all attributes in the dict */ for (const std::string &name : attr.getMemberNames()) { + if (name == "promiscuous") { bool enabled = parse_bool(attr[name], "enabled", result); ret = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_promiscuous(enabled); } + else if (name == "link_status") { bool up = parse_bool(attr[name], "up", result); ret = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_link_up(up); } + else if (name == "led_status") { bool on = parse_bool(attr[name], "on", result); ret = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_led(on); - } else if (name == "flow_ctrl_mode") { + } + + else if (name == "flow_ctrl_mode") { int mode = parse_int(attr[name], "mode", result); ret = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_flow_ctrl(mode); - } else { + } + + else if (name == "rx_filter_mode") { + ret = parse_rx_filter_mode(attr[name], port_id, result); + } + + 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."); @@ -570,11 +599,12 @@ TrexRpcCmdGetPortStatus::_run(const Json::Value ¶ms, Json::Value &result) { result["result"]["owner"] = (port->get_owner().is_free() ? "" : port->get_owner().get_name()); result["result"]["state"] = port->get_state_as_string(); result["result"]["max_stream_id"] = port->get_max_stream_id(); - result["result"]["speed"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->get_link_speed(); /* 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) { @@ -582,6 +612,9 @@ TrexRpcCmdGetPortStatus::_run(const Json::Value ¶ms, Json::Value &result) { } result["result"]["attr"]["fc"]["mode"] = mode; + /* RX data */ + result["result"]["attr"]["rx_filter_mode"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->get_rx_filter_mode(); + return (TREX_RPC_CMD_OK); } @@ -650,15 +683,13 @@ trex_rpc_cmd_rc_e TrexRpcCmdSetRxFeature::_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); + TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id); /* decide which feature is being set */ - const std::string type = parse_choice(params, "type", {"filter_mode", "record", "queue", "server"}, result); + const std::string type = parse_choice(params, "type", {"capture", "queue", "server"}, result); - if (type == "filter_mode") { - parse_filter_mode_msg(params, port, result); - } else if (type == "record") { - parse_record_msg(params, port, result); + if (type == "capture") { + parse_capture_msg(params, port, result); } else if (type == "queue") { parse_queue_msg(params, port, result); } else if (type == "server") { @@ -667,33 +698,39 @@ TrexRpcCmdSetRxFeature::_run(const Json::Value ¶ms, Json::Value &result) { assert(0); } - result["result"] = Json::objectValue; + result["result"] = Json::objectValue; return (TREX_RPC_CMD_OK); } void -TrexRpcCmdSetRxFeature::parse_filter_mode_msg(const Json::Value &msg, TrexStatelessPort *port, Json::Value &result) { - const std::string type = parse_choice(msg, "filter_type", {"hw", "all"}, result); - - rx_filter_mode_e filter_mode; - if (type == "hw") { - filter_mode = RX_FILTER_MODE_HW; - } else if (type == "all") { - filter_mode = RX_FILTER_MODE_ALL; - } else { - assert(0); - } - - try { - port->set_rx_filter_mode(filter_mode); - } catch (const TrexException &ex) { - generate_execute_err(result, ex.what()); +TrexRpcCmdSetRxFeature::parse_capture_msg(const Json::Value &msg, TrexStatelessPort *port, Json::Value &result) { + std::string pcap_filename = parse_string(msg, "pcap_filename", result); + bool enabled = parse_bool(msg, "enabled", result); + + if (enabled) { + + uint64_t limit = parse_uint32(msg, "limit", result); + if (limit == 0) { + generate_parse_err(result, "limit cannot be zero"); + } + + try { + port->start_rx_capture(pcap_filename, limit); + } catch (const TrexException &ex) { + generate_execute_err(result, ex.what()); + } + + } else { + + try { + port->stop_rx_capture(); + } catch (const TrexException &ex) { + generate_execute_err(result, ex.what()); + } + } -} -void -TrexRpcCmdSetRxFeature::parse_record_msg(const Json::Value &msg, TrexStatelessPort *port, Json::Value &result) { } void diff --git a/src/rpc-server/commands/trex_rpc_cmds.h b/src/rpc-server/commands/trex_rpc_cmds.h index 8d4aeb0c..26de717f 100644 --- a/src/rpc-server/commands/trex_rpc_cmds.h +++ b/src/rpc-server/commands/trex_rpc_cmds.h @@ -90,10 +90,16 @@ TREX_RPC_CMD_DEFINE(TrexRpcCmdRelease, "release", 1, true, APIClass: */ 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); +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); + +); + + /** * stream cmds */ @@ -146,10 +152,9 @@ TREX_RPC_CMD_DEFINE(TrexRpcCmdPushRemote, "push_remote", 6, true, APIClass::API_ TREX_RPC_CMD_DEFINE(TrexRpcCmdShutdown, "shutdown", 2, false, APIClass::API_CLASS_TYPE_CORE); TREX_RPC_CMD_DEFINE_EXTENDED(TrexRpcCmdSetRxFeature, "set_rx_feature", 3, false, APIClass::API_CLASS_TYPE_CORE, - void parse_filter_mode_msg(const Json::Value &msg, TrexStatelessPort *port, Json::Value &result); - void parse_record_msg(const Json::Value &msg, TrexStatelessPort *port, Json::Value &result); - void parse_queue_msg(const Json::Value &msg, TrexStatelessPort *port, Json::Value &result); - void parse_server_msg(const Json::Value &msg, TrexStatelessPort *port, Json::Value &result); + void parse_capture_msg(const Json::Value &msg, TrexStatelessPort *port, Json::Value &result); + void parse_queue_msg(const Json::Value &msg, TrexStatelessPort *port, Json::Value &result); + void parse_server_msg(const Json::Value &msg, TrexStatelessPort *port, Json::Value &result); ); diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 5d31abbf..c0156c12 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -157,9 +157,9 @@ private: TrexStatelessPort::TrexStatelessPort(uint8_t port_id, const TrexPlatformApi *api) : m_dp_events(this) { std::vector<std::pair<uint8_t, uint8_t>> core_pair_list; - m_port_id = port_id; - m_port_state = PORT_STATE_IDLE; - m_platform_api = api; + m_port_id = port_id; + m_port_state = PORT_STATE_IDLE; + m_platform_api = api; /* get the platform specific data */ api->get_interface_info(port_id, m_api_info); @@ -585,10 +585,9 @@ TrexStatelessPort::get_max_stream_id() const { } void -TrexStatelessPort::get_properties(std::string &driver, uint32_t &speed) { +TrexStatelessPort::get_properties(std::string &driver) { driver = m_api_info.driver_name; - speed = m_platform_api->getPortAttrObj(m_port_id)->get_link_speed(); } bool @@ -945,16 +944,15 @@ TrexStatelessPort::remove_and_delete_all_streams() { } } -/** - * set the filter type for a port - * - * @author imarom (10/31/2016) - * - * @param rx_sw_cfg - */ +void +TrexStatelessPort::start_rx_capture(const std::string &pcap_filename, uint64_t limit) { + TrexStatelessCpToRxMsgBase *msg = new TrexStatelessRxStartCapture(m_port_id, pcap_filename, limit); + send_message_to_rx(msg); +} + void -TrexStatelessPort::set_rx_filter_mode(rx_filter_mode_e filter_mode) { - TrexStatelessCpToRxMsgBase *msg = new TrexStatelessRxSetFilterMode(m_port_id, filter_mode); +TrexStatelessPort::stop_rx_capture() { + TrexStatelessCpToRxMsgBase *msg = new TrexStatelessRxStopCapture(m_port_id); send_message_to_rx(msg); } diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 41453caa..5a1935a1 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -257,11 +257,8 @@ public: * @author imarom (16-Sep-15) * * @param driver - * @param speed */ - void get_properties(std::string &driver, uint32_t &speed); - - + void get_properties(std::string &driver); /** * encode stats as JSON @@ -371,11 +368,18 @@ public: void get_pci_info(std::string &pci_addr, int &numa_node); + + /** + * enable RX capture on port + * + */ + void start_rx_capture(const std::string &pcap_filename, uint64_t limit); + /** - * set RX filter mode - * can be hardware or software + * disable RX capture if on + * */ - void set_rx_filter_mode(rx_filter_mode_e); + void stop_rx_capture(); /** * fetch the RX software packets from the queue @@ -515,9 +519,9 @@ public: static const std::initializer_list<std::string> g_types; static const std::initializer_list<std::string> g_ops; - mul_type_e m_type; - mul_op_e m_op; - double m_value; + mul_type_e m_type; + mul_op_e m_op; + double m_value; }; #endif /* __TREX_STATELESS_PORT_H__ */ diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index 10b4355b..6e7bfee5 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -241,13 +241,13 @@ TrexDpPortEventMsg::handle() { } /************************* messages from CP to RX **********************/ -bool TrexStatelessRxStartMsg::handle (CRxCoreStateless *rx_core) { - rx_core->work(); +bool TrexStatelessRxEnableLatency::handle (CRxCoreStateless *rx_core) { + rx_core->enable_latency(); return true; } -bool TrexStatelessRxStopMsg::handle (CRxCoreStateless *rx_core) { - rx_core->idle(); +bool TrexStatelessRxDisableLatency::handle (CRxCoreStateless *rx_core) { + rx_core->disable_latency(); return true; } @@ -263,8 +263,15 @@ TrexStatelessRxSwGetPkts::TrexStatelessRxSwGetPkts(uint8_t port_id, TrexStateles bool -TrexStatelessRxSetFilterMode::handle(CRxCoreStateless *rx_core) { - rx_core->set_rx_filter_mode(m_port_id, m_filter_mode); +TrexStatelessRxStartCapture::handle(CRxCoreStateless *rx_core) { + rx_core->start_capture(m_port_id, m_pcap_filename, m_limit); + + return true; +} + +bool +TrexStatelessRxStopCapture::handle(CRxCoreStateless *rx_core) { + rx_core->stop_capture(m_port_id); return true; } diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index 42a422b0..e96e83d6 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -408,11 +408,11 @@ public: }; -class TrexStatelessRxStartMsg : public TrexStatelessCpToRxMsgBase { +class TrexStatelessRxEnableLatency : public TrexStatelessCpToRxMsgBase { bool handle (CRxCoreStateless *rx_core); }; -class TrexStatelessRxStopMsg : public TrexStatelessCpToRxMsgBase { +class TrexStatelessRxDisableLatency : public TrexStatelessCpToRxMsgBase { bool handle (CRxCoreStateless *rx_core); }; @@ -421,17 +421,32 @@ class TrexStatelessRxQuit : public TrexStatelessCpToRxMsgBase { }; -class TrexStatelessRxSetFilterMode : public TrexStatelessCpToRxMsgBase { +class TrexStatelessRxStartCapture : public TrexStatelessCpToRxMsgBase { public: - TrexStatelessRxSetFilterMode(uint8_t port_id, rx_filter_mode_e filter_mode) { + TrexStatelessRxStartCapture(uint8_t port_id, const std::string &pcap_filename, uint64_t limit) : m_pcap_filename(pcap_filename) { m_port_id = port_id; - m_filter_mode = filter_mode; + m_limit = limit; } + + virtual bool handle(CRxCoreStateless *rx_core); + +private: + uint8_t m_port_id; + std::string m_pcap_filename; + uint64_t m_limit; +}; + + +class TrexStatelessRxStopCapture : public TrexStatelessCpToRxMsgBase { +public: + TrexStatelessRxStopCapture(uint8_t port_id) { + m_port_id = port_id; + } + virtual bool handle(CRxCoreStateless *rx_core); private: uint8_t m_port_id; - rx_filter_mode_e m_filter_mode; }; diff --git a/src/stateless/rx/trex_stateless_rx_core.cpp b/src/stateless/rx/trex_stateless_rx_core.cpp index ca39b8a0..ee9c64c4 100644 --- a/src/stateless/rx/trex_stateless_rx_core.cpp +++ b/src/stateless/rx/trex_stateless_rx_core.cpp @@ -121,10 +121,29 @@ bool CRxCoreStateless::periodic_check_for_cp_messages() { handle_cp_msg(msg); } + recalculate_next_state(); return true; } +void CRxCoreStateless::recalculate_next_state() { + if (m_state == STATE_QUIT) { + return; + } + + /* next state is determine by the question are there any ports with active features ? */ + m_state = (are_any_features_active() ? STATE_WORKING : STATE_IDLE); +} + +bool CRxCoreStateless::are_any_features_active() { + for (int i = 0; i < m_max_ports; i++) { + if (m_rx_port_mngr[i].has_features_set()) { + return true; + } + } + + return false; +} void CRxCoreStateless::idle_state_loop() { const int SHORT_DELAY_MS = 2; @@ -260,12 +279,12 @@ void CRxCoreStateless::try_rx_queues() { int CRxCoreStateless::process_all_pending_pkts(bool flush_rx) { - int total_pkts = 0; - for (int i = 0; i < m_max_ports; i++) { - total_pkts += m_rx_port_mngr[i].process_all_pending_pkts(flush_rx); - } + int total_pkts = 0; + for (int i = 0; i < m_max_ports; i++) { + total_pkts += m_rx_port_mngr[i].process_all_pending_pkts(flush_rx); + } - return total_pkts; + return total_pkts; } @@ -336,17 +355,27 @@ double CRxCoreStateless::get_cpu_util() { } -/** - * configure RX filtering mode (HW or software) - * - * @author imarom (11/1/2016) - * - * @param port_id - * @param filter_mode - */ void -CRxCoreStateless::set_rx_filter_mode(uint8_t port_id, rx_filter_mode_e filter_mode) { - const TrexPlatformApi *api = get_stateless_obj()->get_platform_api(); - api->set_rx_filter_mode(port_id, filter_mode); +CRxCoreStateless::start_capture(uint8_t port_id, const std::string &pcap_filename, uint64_t limit) { + m_rx_port_mngr[port_id].start_capture(pcap_filename, limit); +} + +void +CRxCoreStateless::stop_capture(uint8_t port_id) { + m_rx_port_mngr[port_id].stop_capture(); +} + +void +CRxCoreStateless::enable_latency() { + for (int i = 0; i < m_max_ports; i++) { + m_rx_port_mngr[i].enable_latency(); + } +} + +void +CRxCoreStateless::disable_latency() { + for (int i = 0; i < m_max_ports; i++) { + m_rx_port_mngr[i].disable_latency(); + } } diff --git a/src/stateless/rx/trex_stateless_rx_core.h b/src/stateless/rx/trex_stateless_rx_core.h index 2a59862b..425c15ae 100644 --- a/src/stateless/rx/trex_stateless_rx_core.h +++ b/src/stateless/rx/trex_stateless_rx_core.h @@ -103,11 +103,8 @@ class CRxCoreStateless { , TrexPlatformApi::driver_stat_cap_e type); int get_rfc2544_info(rfc2544_info_t *rfc2544_info, int min, int max, bool reset); int get_rx_err_cntrs(CRxCoreErrCntrs *rx_err); - void work() { - m_state = STATE_WORKING; - m_err_cntrs.reset(); // When starting to work, reset global counters - } - void idle() {m_state = STATE_IDLE;} + + void quit() {m_state = STATE_QUIT;} bool is_working() const {return (m_ack_start_work_msg == true);} void set_working_msg_ack(bool val); @@ -119,19 +116,33 @@ class CRxCoreStateless { } /** - * sets the port filter mode + * start capturing of RX packets on a specific port * - * @author imarom (10/31/2016) + * @author imarom (11/2/2016) * - * @param filter_mode + * @param port_id + * @param pcap_filename + * @param limit + */ + void start_capture(uint8_t port_id, const std::string &pcap_filename, uint64_t limit); + void stop_capture(uint8_t port_id); + + /** + * enable latency feature for RX packets + * will be apply to all ports */ - void set_rx_filter_mode(uint8_t port_id, rx_filter_mode_e filter_mode); + void enable_latency(); + void disable_latency(); private: void handle_cp_msg(TrexStatelessCpToRxMsgBase *msg); bool periodic_check_for_cp_messages(); void tickle(); void idle_state_loop(); + + void recalculate_next_state(); + bool are_any_features_active(); + void capture_pkt(rte_mbuf_t *m); void handle_rx_queue_msgs(uint8_t thread_id, CNodeRing * r); void handle_work_stage(bool do_try_rx_queue); @@ -145,14 +156,14 @@ class CRxCoreStateless { void try_rx_queues(); private: - TrexMonitor m_monitor; - uint32_t m_max_ports; - bool m_capture; - state_e m_state; - CNodeRing *m_ring_from_cp; - CNodeRing *m_ring_to_cp; - CCpuUtlDp m_cpu_dp_u; - CCpuUtlCp m_cpu_cp_u; + TrexMonitor m_monitor; + uint32_t m_max_ports; + bool m_capture; + state_e m_state; + CNodeRing *m_ring_from_cp; + CNodeRing *m_ring_to_cp; + CCpuUtlDp m_cpu_dp_u; + CCpuUtlCp m_cpu_cp_u; // Used for acking "work" (go out of idle) messages from cp volatile bool m_ack_start_work_msg __rte_cache_aligned; diff --git a/src/stateless/rx/trex_stateless_rx_port_mngr.cpp b/src/stateless/rx/trex_stateless_rx_port_mngr.cpp index 5b10eebf..35d331cf 100644 --- a/src/stateless/rx/trex_stateless_rx_port_mngr.cpp +++ b/src/stateless/rx/trex_stateless_rx_port_mngr.cpp @@ -148,7 +148,7 @@ RXPacketRecorder::~RXPacketRecorder() { } void -RXPacketRecorder::start(const std::string &pcap, uint32_t limit) { +RXPacketRecorder::start(const std::string &pcap, uint64_t limit) { m_writer = CCapWriterFactory::CreateWriter(LIBPCAP, (char *)pcap.c_str()); if (m_writer == NULL) { std::stringstream ss; @@ -206,7 +206,7 @@ void RXPortManager::handle_pkt(const rte_mbuf_t *m) { m_latency.handle_pkt(m); } - if (is_feature_set(RECORD)) { + if (is_feature_set(CAPTURE)) { m_recorder.handle_pkt(m); } diff --git a/src/stateless/rx/trex_stateless_rx_port_mngr.h b/src/stateless/rx/trex_stateless_rx_port_mngr.h index d197c423..7cc527d8 100644 --- a/src/stateless/rx/trex_stateless_rx_port_mngr.h +++ b/src/stateless/rx/trex_stateless_rx_port_mngr.h @@ -212,7 +212,7 @@ class RXPacketRecorder { public: RXPacketRecorder(); ~RXPacketRecorder(); - void start(const std::string &pcap, uint32_t limit); + void start(const std::string &pcap, uint64_t limit); void stop(); void handle_pkt(const rte_mbuf_t *m); @@ -235,16 +235,15 @@ class RXPortManager { public: enum features_t { LATENCY = 0x1, - RECORD = 0x2, + CAPTURE = 0x2, QUEUE = 0x4 }; RXPortManager() { - m_features = 0; - m_pkt_buffer = NULL; - m_io = NULL; - m_cpu_dp_u = NULL; - set_feature(LATENCY); + m_features = 0; + m_pkt_buffer = NULL; + m_io = NULL; + m_cpu_dp_u = NULL; } void create(CPortLatencyHWBase *io, @@ -264,16 +263,36 @@ public: return m_latency; } - void start_recorder(const std::string &pcap, uint32_t limit_pkts) { + void enable_latency() { + set_feature(LATENCY); + } + + void disable_latency() { + unset_feature(LATENCY); + } + + /** + * capturing of RX packets + * + * @author imarom (11/2/2016) + * + * @param pcap + * @param limit_pkts + */ + void start_capture(const std::string &pcap, uint64_t limit_pkts) { m_recorder.start(pcap, limit_pkts); - set_feature(RECORD); + set_feature(CAPTURE); } - void stop_recorder() { + void stop_capture() { m_recorder.stop(); - unset_feature(RECORD); + unset_feature(CAPTURE); } + /** + * queueing packets + * + */ void start_queue(uint32_t limit) { if (m_pkt_buffer) { delete m_pkt_buffer; @@ -329,6 +348,16 @@ public: */ void handle_pkt(const rte_mbuf_t *m); + + bool has_features_set() { + return (m_features != 0); + } + + + bool no_features_set() { + return (!has_features_set()); + } + private: @@ -344,10 +373,6 @@ private: return ( (m_features & feature) == feature ); } - bool no_features_set() { - return (m_features == 0); - } - uint32_t m_features; RXPacketRecorder m_recorder; RXLatency m_latency; diff --git a/src/trex_port_attr.h b/src/trex_port_attr.h index 9231e263..5ba4f7e2 100755 --- a/src/trex_port_attr.h +++ b/src/trex_port_attr.h @@ -33,7 +33,7 @@ public: virtual void update_device_info() = 0; virtual void reset_xstats() = 0; virtual void update_description() = 0; - + /* GETTERS */ virtual bool get_promiscuous() = 0; virtual void macaddr_get(struct ether_addr *mac_addr) = 0; @@ -51,12 +51,25 @@ public: virtual void get_description(std::string &description) { description = intf_info_st.description; } virtual void get_supported_speeds(supp_speeds_t &supp_speeds) = 0; + virtual std::string get_rx_filter_mode() { + switch (m_rx_filter_mode) { + case RX_FILTER_MODE_ALL: + return "all"; + case RX_FILTER_MODE_HW: + return "hw"; + default: + assert(0); + } + } + + /* SETTERS */ virtual int set_promiscuous(bool enabled) = 0; virtual int add_mac(char * mac) = 0; virtual int set_link_up(bool up) = 0; 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; /* DUMPS */ virtual void dump_link(FILE *fd) = 0; @@ -65,10 +78,14 @@ protected: uint8_t m_port_id; rte_eth_link m_link; 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; + struct intf_info_st { std::string pci_addr; @@ -82,7 +99,10 @@ class DpdkTRexPortAttr : public TRexPortAttr { public: DpdkTRexPortAttr(uint8_t port_id, bool is_virtual, bool fc_change_allowed) { + m_port_id = port_id; + m_rx_filter_mode = RX_FILTER_MODE_HW; + flag_is_virtual = is_virtual; int tmp; flag_is_fc_change_supported = fc_change_allowed && (get_flow_ctrl(tmp) != -ENOTSUP); @@ -114,6 +134,7 @@ public: virtual int set_flow_ctrl(int mode); virtual int set_led(bool on); + virtual int set_rx_filter_mode(rx_filter_mode_e mode); /* DUMPS */ virtual void dump_link(FILE *fd); @@ -158,6 +179,7 @@ public: int set_flow_ctrl(int mode) { return -ENOTSUP; } int set_led(bool on) { return -ENOTSUP; } void dump_link(FILE *fd) {} + int set_rx_filter_mode(rx_filter_mode_e mode) { return -ENOTSUP; } }; |