diff options
author | 2016-12-13 18:15:22 +0200 | |
---|---|---|
committer | 2016-12-13 18:15:22 +0200 | |
commit | 0fdd81a94d62592b0ec9888022d793f670c8476f (patch) | |
tree | ec52cd0f090793e26f67bc017d402b737acd71b5 | |
parent | 0c45815234abbb79b147b8093eb19e274ee65f52 (diff) |
Major refactor - L2 / L3 modes for ports
Signed-off-by: imarom <imarom@cisco.com>
21 files changed, 496 insertions, 255 deletions
diff --git a/scripts/automation/trex_control_plane/stl/console/trex_console.py b/scripts/automation/trex_control_plane/stl/console/trex_console.py index 1a97ad0c..627761ff 100755 --- a/scripts/automation/trex_control_plane/stl/console/trex_console.py +++ b/scripts/automation/trex_control_plane/stl/console/trex_console.py @@ -330,23 +330,21 @@ class TRexConsole(TRexGeneralCmd): self.do_portattr("-h") @verify_connected - def do_source (self, line): - '''Configure source address for port(s)\n''' - self.stateless_client.set_source_addr_line(line) - - def help_source (self): - self.do_source("-h") - + def do_l2 (self, line): + '''Configures a port in L2 mode''' + self.stateless_client.set_l2_mode_line(line) + def help_l2 (self): + self.do_l2("-h") + @verify_connected - def do_dest (self, line): - '''Configure destination address for port(s)\n''' - self.stateless_client.set_dest_addr_line(line) - - def help_dest (self): - self.do_dest("-h") - - + def do_l3 (self, line): + '''Configures a port in L3 mode''' + self.stateless_client.set_l3_mode_line(line) + + def help_l3 (self): + self.do_l3("-h") + @verify_connected def do_set_rx_sniffer (self, line): 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 80daadd2..ee5db1f0 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 @@ -1843,15 +1843,14 @@ class STLClient(object): raise STLError(rc) - @__api_check(True) - def set_source_addr (self, port, addr): + def set_l2_mode (self, port, dst_mac): """ - Configures a port with a source address + Sets the port mode to L2 :parameters: - port - the port to set the source address - addr - source address. currently only IPv4 is supported + port - the port to set the source address + dst_mac - destination MAC :raises: + :exc:`STLError` """ @@ -1859,33 +1858,27 @@ class STLClient(object): validate_type('port', port, int) if port not in self.get_all_ports(): raise STLError("port {0} is not a valid port id".format(port)) - - if not is_valid_ipv4(addr): - raise STLError("addr is not a valid IPv4 address: '{0}'".format(addr)) - - self.logger.pre_cmd("Setting port {0} source address as '{1}': ".format(port, addr)) - rc = self.ports[port].set_source_addr(addr) - self.logger.post_cmd(rc) + + if not is_valid_mac(dst_mac): + raise STLError("dest_mac is not a valid MAC address: '{0}'".format(dst_mac)) + + self.logger.pre_cmd("Setting port {0} in L2 mode: ".format(port)) + rc = self.ports[port].set_l2_mode(dst_mac) + self.logger.post_cmd(rc) if not rc: raise STLError(rc) - - # for MAC dest - no resolve - if not self.ports[port].get_dst_addr()['ipv4']: - return rc - # resolve the address - return self.resolve(ports = port, verbose = False) - @__api_check(True) - def set_dest_addr (self, port, addr): + def set_l3_mode (self, port, src_ipv4, dst_ipv4): """ - Configures a port with a destination address + Sets the port mode to L3 :parameters: - port - the port to set the destination address - addr - destination address. can be either MAC or IPv4 + port - the port to set the source address + src_ipv4 - IPv4 source address for the port + dst_ipv4 - IPv4 destination address :raises: + :exc:`STLError` """ @@ -1893,24 +1886,29 @@ class STLClient(object): validate_type('port', port, int) if port not in self.get_all_ports(): raise STLError("port {0} is not a valid port id".format(port)) - - if not is_valid_ipv4(addr) and not is_valid_mac(addr): - raise STLError("addr is not a valid IPv4 address or a MAC address: '{0}'".format(addr)) - - if is_valid_ipv4(addr) and not self.ports[port].get_src_addr()['ipv4']: - raise STLError("cannot configure destination as IPv4 address without IPv4 source address") - self.logger.pre_cmd("Setting port {0} destination address as '{1}': ".format(port, addr)) - rc = self.ports[port].set_dest_addr(addr) - self.logger.post_cmd(rc) + if not is_valid_ipv4(src_ipv4): + raise STLError("src_ipv4 is not a valid IPv4 address: '{0}'".format(src_ipv4)) + + if not is_valid_ipv4(dst_ipv4): + raise STLError("dst_ipv4 is not a valid IPv4 address: '{0}'".format(dst_ipv4)) + + self.logger.pre_cmd("Setting port {0} in L3 mode: ".format(port)) + rc = self.ports[port].set_l3_mode(src_ipv4, dst_ipv4) + self.logger.post_cmd(rc) if not rc: raise STLError(rc) - - # resolve the address - return self.resolve(ports = port, verbose = False) - - + + # try to resolve + with self.logger.supress(level = LoggerApi.VERBOSE_REGULAR_SYNC): + self.logger.pre_cmd("ARP resolving address '{0}': ".format(dst_ipv4)) + rc = self.ports[port].arp_resolve(0) + self.logger.post_cmd(rc) + if not rc: + raise STLError(rc) + + @__api_check(True) def ping_ip (self, src_port, dst_ipv4, pkt_size = 64, count = 5): """ @@ -3177,7 +3175,7 @@ class STLClient(object): parser = parsing_opts.gen_parser(self, "ping", self.ping_line.__doc__, - parsing_opts.SOURCE_PORT, + parsing_opts.SINGLE_PORT, parsing_opts.PING_IPV4, parsing_opts.PKT_SIZE, parsing_opts.PING_COUNT) @@ -3808,41 +3806,46 @@ class STLClient(object): @__console - def set_source_addr_line (self, line): - '''Configures source address for port(s)''' + def set_l2_mode_line (self, line): + '''Configures a port in L2 mode''' parser = parsing_opts.gen_parser(self, - "source", - self.set_source_addr_line.__doc__, - parsing_opts.SOURCE_PORT, - parsing_opts.IPV4) + "port", + self.set_l2_mode_line.__doc__, + parsing_opts.SINGLE_PORT, + parsing_opts.DST_MAC, + ) opts = parser.parse_args(line.split()) if not opts: return opts + # source ports maps to ports as a single port - self.set_source_addr(opts.ports[0], opts.ipv4) + self.set_l2_mode(opts.ports[0], dst_mac = opts.dst_mac) return RC_OK() @__console - def set_dest_addr_line (self, line): - '''Configures destination address for port(s)''' + def set_l3_mode_line (self, line): + '''Configures a port in L3 mode''' parser = parsing_opts.gen_parser(self, - "dest", - self.set_dest_addr_line.__doc__, - parsing_opts.SOURCE_PORT, - parsing_opts.DEST) + "port", + self.set_l3_mode_line.__doc__, + parsing_opts.SINGLE_PORT, + parsing_opts.SRC_IPV4, + parsing_opts.DST_IPV4, + ) opts = parser.parse_args(line.split()) if not opts: return opts + # source ports maps to ports as a single port - self.set_dest_addr(opts.ports[0], opts.dest) + self.set_l3_mode(opts.ports[0], src_ipv4 = opts.src_ipv4, dst_ipv4 = opts.dst_ipv4) 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 5ec1f852..e44fe801 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 @@ -519,39 +519,40 @@ class Port(object): return self.ok() - @owned - def set_source_addr (self, addr): + def set_l2_mode (self, dst_mac): if not self.is_service_mode_on(): - return self.err('port service mode must be enabled for configuring source address. Please enable service mode') + return self.err('port service mode must be enabled for configuring L2 mode. Please enable service mode') - return self.set_attr(ipv4 = addr) - + params = {"handler": self.handler, + "port_id": self.port_id, + "dst_mac": dst_mac} - @owned - def set_dest_addr (self, addr): - if not self.is_service_mode_on(): - return self.err('port service mode must be enabled for configuring destination address. Please enable service mode') - - return self.set_attr(dest = addr) + rc = self.transmit("set_l2", params) + if rc.bad(): + return self.err(rc.err()) + + return self.sync() @owned - def set_arp_resolution (self, ipv4, mac): - + def set_l3_mode (self, src_addr, dest_addr, resolved_mac = None): + if not self.is_service_mode_on(): + return self.err('port service mode must be enabled for configuring L3 mode. Please enable service mode') + params = {"handler": self.handler, "port_id": self.port_id, - "ipv4": ipv4, - "mac": mac} + "src_addr": src_addr, + "dst_addr": dest_addr} - rc = self.transmit("set_arp_resolution", params) + if resolved_mac: + params["resolved_mac"] = resolved_mac + + rc = self.transmit("set_l3", params) if rc.bad(): return self.err(rc.err()) - # instead of updating manualy - let's sync with the server return self.sync() - - @owned @@ -700,15 +701,6 @@ class Port(object): if kwargs.get('rx_filter_mode') is not None: json_attr['rx_filter_mode'] = {'mode': kwargs.get('rx_filter_mode')} - if kwargs.get('ipv4') is not None: - json_attr['ipv4'] = {'addr': kwargs.get('ipv4')} - - if kwargs.get('dest') is not None: - if not self.is_service_mode_on(): - return self.err('setting destination requires port to be in service mode') - - json_attr['dest'] = {'addr': kwargs.get('dest')} - params = {"handler": self.handler, "port_id": self.port_id, @@ -879,7 +871,7 @@ class Port(object): info['src_ipv4'] = attr['src_ipv4'] if info['src_ipv4'] is None: - info['src_ipv4'] = 'Not Configured' + info['src_ipv4'] = '-' # dest dest = attr['dest'] @@ -908,6 +900,14 @@ class Port(object): queue = rx_info['queue'] info['rx_queue'] = '[{0} / {1}]'.format(queue['count'], queue['size']) if queue['is_active'] else 'off' + # Grat ARP + grat_arp = rx_info['grat_arp'] + if grat_arp['is_active']: + info['grat_arp'] = grat_arp['interval_sec'] + else: + info['grat_arp'] = "off" + + return info @@ -991,6 +991,7 @@ class Port(object): "RX Filter Mode": info['rx_filter_mode'], "RX Queueing": info['rx_queue'], "RX sniffer": info['rx_sniffer'], + "Grat ARP": info['grat_arp'], } diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_rx_features.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_rx_features.py index e0fc1724..ec83de5d 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_rx_features.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_rx_features.py @@ -164,7 +164,8 @@ class ARPResolver(Resolver): return None - rc = self.port.set_arp_resolution(arp.psrc, arp.hwsrc) + # update the port with L3 full configuration + rc = self.port.set_l3_mode(self.src['ipv4'], self.dst['ipv4'], arp.hwsrc) if not rc: return rc 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 6a59126f..c08a0af8 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 @@ -682,6 +682,7 @@ class CTRexInfoGenerator(object): ("RX Filter Mode", []), ("RX Queueing", []), ("RX sniffer", []), + ("Grat ARP", []), ] ) 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 c5f53d68..0a7b510f 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 @@ -49,17 +49,20 @@ OUTPUT_FILENAME = 31 LIMIT = 33 PORT_RESTART = 34 -IPV4 = 35 -DEST = 36 RETRIES = 37 -SOURCE_PORT = 39 +SINGLE_PORT = 38 +DST_MAC = 39 + PING_IPV4 = 40 PING_COUNT = 41 PKT_SIZE = 42 SERVICE_OFF = 43 +SRC_IPV4 = 44 +DST_IPV4 = 45 + GLOBAL_STATS = 50 PORT_STATS = 51 PORT_STATUS = 52 @@ -250,9 +253,9 @@ def check_pkt_size (pkt_size): return pkt_size -def check_dest_addr (addr): - if not (is_valid_ipv4(addr) or is_valid_mac(addr)): - raise argparse.ArgumentTypeError("not a valid IPv4 or MAC address: '{0}'".format(addr)) +def check_mac_addr (addr): + if not is_valid_mac(addr): + raise argparse.ArgumentTypeError("not a valid MAC address: '{0}'".format(addr)) return addr @@ -341,18 +344,24 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'], 'dest': 'flow_ctrl', 'choices': FLOW_CTRL_DICT}), - IPV4: ArgumentPack(['--ipv4'], - {'help': 'IPv4 address(s) for the port(s)', - 'dest': 'ipv4', - 'required': True, - 'type': check_ipv4_addr}), - - DEST: ArgumentPack(['--addr'], - {'help': 'Destination address(s) for the port(s) in either IPv4 or MAC format', - 'metavar': 'addr', - 'dest': 'dest', - 'required' : True, - 'type': check_dest_addr}), + SRC_IPV4: ArgumentPack(['--src'], + {'help': 'Configure source IPv4 address', + 'dest': 'src_ipv4', + 'required': True, + 'type': check_ipv4_addr}), + + DST_IPV4: ArgumentPack(['--dst'], + {'help': 'Configure destination IPv4 address', + 'dest': 'dst_ipv4', + 'required': True, + 'type': check_ipv4_addr}), + + + DST_MAC: ArgumentPack(['--dst'], + {'help': 'Configure destination MAC address', + 'dest': 'dst_mac', + 'required': True, + 'type': check_mac_addr}), RETRIES: ArgumentPack(['-r', '--retries'], {'help': 'retries count [default is zero]', @@ -405,7 +414,7 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'], 'default': []}), - SOURCE_PORT: ArgumentPack(['--port', '-p'], + SINGLE_PORT: ArgumentPack(['--port', '-p'], {'dest':'ports', 'type': int, 'metavar': 'PORT', diff --git a/src/bp_sim.h b/src/bp_sim.h index 454f5f19..00699cd9 100755 --- a/src/bp_sim.h +++ b/src/bp_sim.h @@ -668,6 +668,7 @@ class CPerPortIPCfg { uint16_t m_vlan; }; + class CParserOption { public: @@ -4239,6 +4240,32 @@ inline pkt_dir_t CGenNode::cur_interface_dir(){ } } +class CRXCoreIgnoreStat { + friend class CCPortLatency; + friend class CLatencyManager; + friend class RXGratARP; + public: + inline CRXCoreIgnoreStat operator- (const CRXCoreIgnoreStat &t_in) const { + CRXCoreIgnoreStat t_out; + t_out.m_tx_arp = this->m_tx_arp - t_in.m_tx_arp; + t_out.m_tx_ipv6_n_solic = this->m_tx_ipv6_n_solic - t_in.m_tx_ipv6_n_solic; + t_out.m_tot_bytes = this->m_tot_bytes - t_in.m_tot_bytes; + return t_out; + } + uint64_t get_tx_bytes() {return m_tot_bytes;} + uint64_t get_tx_pkts() {return m_tx_arp + m_tx_ipv6_n_solic;} + uint64_t get_tx_arp() {return m_tx_arp;} + uint64_t get_tx_n_solic() {return m_tx_ipv6_n_solic;} + void clear() { + m_tx_arp = 0; + m_tx_ipv6_n_solic = 0; + m_tot_bytes = 0; + } + private: + uint64_t m_tx_arp; + uint64_t m_tx_ipv6_n_solic; + uint64_t m_tot_bytes; +}; #endif diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index 03c41431..e26aaa22 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -3092,6 +3092,8 @@ public: void dump_config(FILE *fd); void dump_links_status(FILE *fd); + bool lookup_port_by_mac(const uint8_t *mac, uint8_t &port_id); + public: port_cfg_t m_port_cfg; uint32_t m_max_ports; /* active number of ports supported options are 2,4,8,10,12 */ @@ -3910,6 +3912,16 @@ void CGlobalTRex::dump_links_status(FILE *fd){ } } +bool CGlobalTRex::lookup_port_by_mac(const uint8_t *mac, uint8_t &port_id) { + for (int i = 0; i < m_max_ports; i++) { + if (memcmp(m_ports[i].get_port_attr()->get_src_mac(), mac, 6) == 0) { + port_id = i; + return true; + } + } + + return false; +} void CGlobalTRex::dump_post_test_stats(FILE *fd){ uint64_t pkt_out=0; @@ -4848,7 +4860,13 @@ static CGlobalTRex g_trex; void CPhyEthIF::update_counters() { get_ex_drv()->get_extended_stats(this, &m_stats); CRXCoreIgnoreStat ign_stats; - g_trex.m_mg.get_ignore_stats(m_port_id, ign_stats, true); + + if (get_is_stateless()) { + g_trex.m_rx_sl.get_ignore_stats(m_port_id, ign_stats, true); + } else { + g_trex.m_mg.get_ignore_stats(m_port_id, ign_stats, true); + } + m_stats.obytes -= ign_stats.get_tx_bytes(); m_stats.opackets -= ign_stats.get_tx_pkts(); m_ignore_stats.opackets += ign_stats.get_tx_pkts(); @@ -7256,6 +7274,11 @@ int DpdkTRexPortAttr::set_rx_filter_mode(rx_filter_mode_e rx_filter_mode) { return (0); } +bool DpdkTRexPortAttr::is_loopback() const { + uint8_t port_id; + return g_trex.lookup_port_by_mac(m_dest.get_dest_mac(), port_id); +} + /** * marks the control plane for a total server shutdown * @@ -7264,3 +7287,4 @@ int DpdkTRexPortAttr::set_rx_filter_mode(rx_filter_mode_e rx_filter_mode) { void TrexDpdkPlatformApi::mark_for_shutdown() const { g_trex.mark_for_shutdown(CGlobalTRex::SHUTDOWN_RPC_REQ); } + diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index 5c397fcd..c8b4841a 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -357,53 +357,6 @@ 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()); - } - - TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id); - port->set_src_ipv4(ipv4_addr); - - return (0); -} - -int -TrexRpcCmdSetPortAttr::parse_dest(const Json::Value &msg, uint8_t port_id, Json::Value &result) { - - /* can be either IPv4 or MAC */ - const std::string addr = parse_string(msg, "addr", result); - - TRexPortAttr *port_attr = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id); - - /* try IPv4 */ - uint32_t ipv4_addr; - uint8_t mac[6]; - - if (utl_ipv4_to_uint32(addr.c_str(), ipv4_addr)) { - port_attr->get_dest().set_dest(ipv4_addr); - - } else if (utl_str_to_macaddr(addr, mac)) { - port_attr->get_dest().set_dest(mac); - - } else { - std::stringstream ss; - ss << "'dest' is not an IPv4 address or a MAC address: '" << addr << "'"; - generate_parse_err(result, ss.str()); - } - - - return (0); -} - - /** * set port commands * @@ -451,16 +404,6 @@ TrexRpcCmdSetPortAttr::_run(const Json::Value ¶ms, Json::Value &result) { ret = parse_rx_filter_mode(rx, port_id, result); } - else if (name == "ipv4") { - const Json::Value &ipv4 = parse_object(attr, name, result); - ret = parse_ipv4(ipv4, port_id, result); - } - - else if (name == "dest") { - const Json::Value &dest = parse_object(attr, name, result); - ret = parse_dest(dest, port_id, result); - } - /* unknown attribute */ else { generate_execute_err(result, "unknown attribute type: '" + name + "'"); @@ -836,31 +779,78 @@ TrexRpcCmdGetRxQueuePkts::_run(const Json::Value ¶ms, Json::Value &result) { return (TREX_RPC_CMD_OK); } + +/** + * configures a port in L2 mode + * + */ trex_rpc_cmd_rc_e -TrexRpcCmdSetARPRes::_run(const Json::Value ¶ms, Json::Value &result) { +TrexRpcCmdSetL2::_run(const Json::Value ¶ms, Json::Value &result) { uint8_t port_id = parse_port(params, result); TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id); - const std::string ipv4_str = parse_string(params, "ipv4", result); - const std::string mac_str = parse_string(params, "mac", result); + const std::string dst_mac_str = parse_string(params, "dst_mac", result); + + uint8_t dst_mac[6]; + if (!utl_str_to_macaddr(dst_mac_str, dst_mac)) { + std::stringstream ss; + ss << "'invalid MAC address: '" << dst_mac_str << "'"; + generate_parse_err(result, ss.str()); + } + + port->set_l2_mode(dst_mac); + + return (TREX_RPC_CMD_OK); +} + +/** + * configures a port in L3 mode + * + */ +trex_rpc_cmd_rc_e +TrexRpcCmdSetL3::_run(const Json::Value ¶ms, Json::Value &result) { + uint8_t port_id = parse_port(params, result); + + TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id); + + const std::string src_ipv4_str = parse_string(params, "src_addr", result); + const std::string dst_ipv4_str = parse_string(params, "dst_addr", result); - uint32_t ipv4_addr; - if (!utl_ipv4_to_uint32(ipv4_str.c_str(), ipv4_addr)) { + uint32_t src_ipv4; + if (!utl_ipv4_to_uint32(src_ipv4_str.c_str(), src_ipv4)) { std::stringstream ss; - ss << "invalid IPv4 address: '" << ipv4_str << "'"; + ss << "invalid source IPv4 address: '" << src_ipv4_str << "'"; generate_parse_err(result, ss.str()); } - uint8_t mac[6]; - if (!utl_str_to_macaddr(mac_str, mac)) { + uint32_t dst_ipv4; + if (!utl_ipv4_to_uint32(dst_ipv4_str.c_str(), dst_ipv4)) { std::stringstream ss; - ss << "'invalid MAC address: '" << mac_str << "'"; + ss << "invalid destination IPv4 address: '" << dst_ipv4_str << "'"; generate_parse_err(result, ss.str()); - } + } + + - port->getPortAttrObj()->get_dest().set_dest(ipv4_addr, mac); + /* did we get a resolved MAC as well ? */ + if (params["resolved_mac"] != Json::Value::null) { + const std::string resolved_mac = parse_string(params, "resolved_mac", result); + + uint8_t mac[6]; + if (!utl_str_to_macaddr(resolved_mac, mac)) { + std::stringstream ss; + ss << "'invalid MAC address: '" << resolved_mac << "'"; + generate_parse_err(result, ss.str()); + } - return (TREX_RPC_CMD_OK); + port->set_l3_mode(src_ipv4, dst_ipv4, mac); + + } else { + + port->set_l3_mode(src_ipv4, dst_ipv4); + } + + return (TREX_RPC_CMD_OK); } diff --git a/src/rpc-server/commands/trex_rpc_cmds.h b/src/rpc-server/commands/trex_rpc_cmds.h index 2b2178e2..6639be7b 100644 --- a/src/rpc-server/commands/trex_rpc_cmds.h +++ b/src/rpc-server/commands/trex_rpc_cmds.h @@ -96,8 +96,6 @@ 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); - int parse_dest(const Json::Value &msg, uint8_t port_id, Json::Value &result); ); @@ -159,8 +157,9 @@ TREX_RPC_CMD_DEFINE_EXTENDED(TrexRpcCmdSetRxFeature, "set_rx_feature", 3, false, ); +TREX_RPC_CMD_DEFINE(TrexRpcCmdSetL2, "set_l2", 2, false, APIClass::API_CLASS_TYPE_CORE); +TREX_RPC_CMD_DEFINE(TrexRpcCmdSetL3, "set_l3", 3, false, APIClass::API_CLASS_TYPE_CORE); TREX_RPC_CMD_DEFINE(TrexRpcCmdGetRxQueuePkts, "get_rx_queue_pkts", 2, false, APIClass::API_CLASS_TYPE_CORE); -TREX_RPC_CMD_DEFINE(TrexRpcCmdSetARPRes, "set_arp_resolution", 2, false, APIClass::API_CLASS_TYPE_CORE); #endif /* __TREX_RPC_CMD_H__ */ diff --git a/src/rpc-server/trex_rpc_cmds_table.cpp b/src/rpc-server/trex_rpc_cmds_table.cpp index 919be1f1..94a3e1b9 100644 --- a/src/rpc-server/trex_rpc_cmds_table.cpp +++ b/src/rpc-server/trex_rpc_cmds_table.cpp @@ -75,7 +75,8 @@ TrexRpcCommandsTable::TrexRpcCommandsTable() { register_command(new TrexRpcCmdSetRxFeature()); register_command(new TrexRpcCmdGetRxQueuePkts()); - register_command(new TrexRpcCmdSetARPRes()); + register_command(new TrexRpcCmdSetL2()); + register_command(new TrexRpcCmdSetL3()); } diff --git a/src/stateful_rx_core.h b/src/stateful_rx_core.h index 2df406de..8744a58a 100644 --- a/src/stateful_rx_core.h +++ b/src/stateful_rx_core.h @@ -32,33 +32,6 @@ limitations under the License. class TrexWatchDog; -class CRXCoreIgnoreStat { - friend class CCPortLatency; - friend class CLatencyManager; - public: - inline CRXCoreIgnoreStat operator- (const CRXCoreIgnoreStat &t_in) { - CRXCoreIgnoreStat t_out; - t_out.m_tx_arp = this->m_tx_arp - t_in.m_tx_arp; - t_out.m_tx_ipv6_n_solic = this->m_tx_ipv6_n_solic - t_in.m_tx_ipv6_n_solic; - t_out.m_tot_bytes = this->m_tot_bytes - t_in.m_tot_bytes; - return t_out; - } - uint64_t get_tx_bytes() {return m_tot_bytes;} - uint64_t get_tx_pkts() {return m_tx_arp + m_tx_ipv6_n_solic;} - uint64_t get_tx_arp() {return m_tx_arp;} - uint64_t get_tx_n_solic() {return m_tx_ipv6_n_solic;} - void clear() { - m_tx_arp = 0; - m_tx_ipv6_n_solic = 0; - m_tot_bytes = 0; - } - - private: - uint64_t m_tx_arp; - uint64_t m_tx_ipv6_n_solic; - uint64_t m_tot_bytes; -}; - class CLatencyPktInfo { public: void Create(class CLatencyPktMode *m_l_pkt_info); diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 057f6521..62805dbc 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -988,18 +988,67 @@ TrexStatelessPort::get_rx_queue_pkts() { } +/** + * configures port in L2 mode + * + */ +void +TrexStatelessPort::set_l2_mode(const uint8_t *dest_mac) { + + /* no IPv4 src */ + getPortAttrObj()->set_src_ipv4(0); + + /* set destination as MAC */ + getPortAttrObj()->get_dest().set_dest(dest_mac); + + TrexStatelessRxSetL2Mode *msg = new TrexStatelessRxSetL2Mode(m_port_id); + send_message_to_rx( (TrexStatelessCpToRxMsgBase *)msg ); +} + +/** + * configures port in L3 mode - unresolved + */ +void +TrexStatelessPort::set_l3_mode(uint32_t src_ipv4, uint32_t dest_ipv4) { + + /* set src IPv4 */ + getPortAttrObj()->set_src_ipv4(src_ipv4); + + /* set dest IPv4 */ + getPortAttrObj()->get_dest().set_dest(dest_ipv4); + + /* send RX core the relevant info */ + CManyIPInfo ip_info; + ip_info.insert(COneIPv4Info(src_ipv4, 0, getPortAttrObj()->get_src_mac())); + + TrexStatelessRxSetL3Mode *msg = new TrexStatelessRxSetL3Mode(m_port_id, ip_info, false); + send_message_to_rx( (TrexStatelessCpToRxMsgBase *)msg ); +} + +/** + * configures port in L3 mode - resolved + * + */ void -TrexStatelessPort::set_src_ipv4(uint32_t ipv4) { +TrexStatelessPort::set_l3_mode(uint32_t src_ipv4, uint32_t dest_ipv4, const uint8_t *resolved_mac) { - getPortAttrObj()->set_src_ipv4(ipv4); + /* set src IPv4 */ + getPortAttrObj()->set_src_ipv4(src_ipv4); - CManyIPInfo src_addr; - src_addr.insert(COneIPv4Info(ipv4, 0, getPortAttrObj()->get_src_mac(), m_port_id)); + /* set dest IPv4 + resolved MAC */ + getPortAttrObj()->get_dest().set_dest(dest_ipv4, resolved_mac); - TrexStatelessRxUpdateSrcAddr *msg = new TrexStatelessRxUpdateSrcAddr(m_port_id, src_addr); + /* send RX core the relevant info */ + CManyIPInfo ip_info; + ip_info.insert(COneIPv4Info(src_ipv4, 0, getPortAttrObj()->get_src_mac())); + + bool is_grat_arp_needed = !getPortAttrObj()->is_loopback(); + + TrexStatelessRxSetL3Mode *msg = new TrexStatelessRxSetL3Mode(m_port_id, ip_info, is_grat_arp_needed); send_message_to_rx( (TrexStatelessCpToRxMsgBase *)msg ); } + Json::Value TrexStatelessPort::rx_features_to_json() { static MsgReply<Json::Value> reply; diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 3ae74f5a..317f4f70 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -400,10 +400,17 @@ public: const RXPacketBuffer *get_rx_queue_pkts(); /** - * sets an IPv4 source address + * configures port for L2 mode * */ - void set_src_ipv4(uint32_t ipv4); + void set_l2_mode(const uint8_t *dest_mac); + + /** + * configures port in L3 mode + * + */ + void set_l3_mode(uint32_t src_ipv4, uint32_t dest_ipv4); + void set_l3_mode(uint32_t src_ipv4, uint32_t dest_ipv4, const uint8_t *resolved_mac); /** * generate a JSON describing the status diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index dc656e67..2b8e93bb 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -317,7 +317,16 @@ TrexStatelessRxFeaturesToJson::handle(CRxCoreStateless *rx_core) { } bool -TrexStatelessRxUpdateSrcAddr::handle(CRxCoreStateless *rx_core) { - rx_core->get_rx_port_mngr(m_port_id).update_src_addr(m_src_addr); +TrexStatelessRxSetL2Mode::handle(CRxCoreStateless *rx_core) { + rx_core->get_rx_port_mngr(m_port_id).set_l2_mode(); + return true; } + +bool +TrexStatelessRxSetL3Mode::handle(CRxCoreStateless *rx_core) { + rx_core->get_rx_port_mngr(m_port_id).set_l3_mode(m_src_addr, m_is_grat_arp_needed); + + return true; +} + diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index 5f00c244..dbdd9b56 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -569,13 +569,33 @@ private: }; -class TrexStatelessRxUpdateSrcAddr : public TrexStatelessCpToRxMsgBase { +/** + * updates the RX core that we are in L2 mode + */ +class TrexStatelessRxSetL2Mode : public TrexStatelessCpToRxMsgBase { public: - TrexStatelessRxUpdateSrcAddr(uint8_t port_id, - const CManyIPInfo &src_addr) { - + TrexStatelessRxSetL2Mode(uint8_t port_id) { m_port_id = port_id; - m_src_addr = src_addr; + } + + virtual bool handle(CRxCoreStateless *rx_core); + +private: + uint8_t m_port_id; +}; + +/** + * updates the RX core that we are in a L3 mode + */ +class TrexStatelessRxSetL3Mode : public TrexStatelessCpToRxMsgBase { +public: + TrexStatelessRxSetL3Mode(uint8_t port_id, + const CManyIPInfo &src_addr, + bool is_grat_arp_needed) { + + m_port_id = port_id; + m_src_addr = src_addr; + m_is_grat_arp_needed = is_grat_arp_needed; } virtual bool handle(CRxCoreStateless *rx_core); @@ -583,6 +603,7 @@ public: private: uint8_t m_port_id; CManyIPInfo m_src_addr; + bool m_is_grat_arp_needed; }; /** diff --git a/src/stateless/rx/trex_stateless_rx_core.cpp b/src/stateless/rx/trex_stateless_rx_core.cpp index 31fef68f..502af9c1 100644 --- a/src/stateless/rx/trex_stateless_rx_core.cpp +++ b/src/stateless/rx/trex_stateless_rx_core.cpp @@ -185,17 +185,30 @@ void CRxCoreStateless::port_manager_tick() { } } +/** + * for each port handle the grat ARP mechansim + * + */ +void CRxCoreStateless::handle_grat_arp() { + for (int i = 0; i < m_max_ports; i++) { + m_rx_port_mngr[i].send_next_grat_arp(); + } +} + void CRxCoreStateless::handle_work_stage() { /* set the next sync time to */ dsec_t sync_time_sec = now_sec() + (1.0 / 1000); dsec_t tick_time_sec = now_sec() + 1.0; - + dsec_t grat_arp_sec = now_sec() + (double)CGlobalInfo::m_options.m_arp_ref_per; + while (m_state == STATE_WORKING) { process_all_pending_pkts(); dsec_t now = now_sec(); + /* until a scheduler is added here - dirty IFs */ + if ( (now - sync_time_sec) > 0 ) { periodic_check_for_cp_messages(); } @@ -204,7 +217,12 @@ void CRxCoreStateless::handle_work_stage() { port_manager_tick(); tick_time_sec = now + 1.0; } - + + if ( (now - grat_arp_sec) > 0) { + handle_grat_arp(); + grat_arp_sec = now + (double)CGlobalInfo::m_options.m_arp_ref_per; + } + rte_pause(); } @@ -346,3 +364,8 @@ CRxCoreStateless::get_rx_port_mngr(uint8_t port_id) { return m_rx_port_mngr[port_id]; } + +void +CRxCoreStateless::get_ignore_stats(int port_id, CRXCoreIgnoreStat &stat, bool get_diff) { + get_rx_port_mngr(port_id).get_ignore_stats(stat, get_diff); +} diff --git a/src/stateless/rx/trex_stateless_rx_core.h b/src/stateless/rx/trex_stateless_rx_core.h index 96e511b4..4eed59a1 100644 --- a/src/stateless/rx/trex_stateless_rx_core.h +++ b/src/stateless/rx/trex_stateless_rx_core.h @@ -21,6 +21,7 @@ #ifndef __TREX_STATELESS_RX_CORE_H__ #define __TREX_STATELESS_RX_CORE_H__ #include <stdint.h> + #include "stateful_rx_core.h" #include "os_time.h" #include "pal/linux/sanb_atomic.h" @@ -153,6 +154,12 @@ class CRxCoreStateless { RXPortManager &get_rx_port_mngr(uint8_t port_id); + /** + * fetch the ignored stats for a port + * + */ + void get_ignore_stats(int port_id, CRXCoreIgnoreStat &stat, bool get_diff); + private: void handle_cp_msg(TrexStatelessCpToRxMsgBase *msg); bool periodic_check_for_cp_messages(); @@ -166,7 +173,8 @@ class CRxCoreStateless { void handle_rx_queue_msgs(uint8_t thread_id, CNodeRing * r); void handle_work_stage(); void port_manager_tick(); - + void handle_grat_arp(); + int process_all_pending_pkts(bool flush_rx = false); void flush_all_pending_pkts() { diff --git a/src/stateless/rx/trex_stateless_rx_port_mngr.cpp b/src/stateless/rx/trex_stateless_rx_port_mngr.cpp index e36f825d..4c54a132 100644 --- a/src/stateless/rx/trex_stateless_rx_port_mngr.cpp +++ b/src/stateless/rx/trex_stateless_rx_port_mngr.cpp @@ -661,10 +661,15 @@ RXServer::duplicate_mbuf(const rte_mbuf_t *m) { * *************************************/ void -RXGratARP::create(uint8_t port_id, CPortLatencyHWBase *io, CManyIPInfo *src_addr) { - m_io = io; - m_port_id = port_id; - m_src_addr = src_addr; +RXGratARP::create(uint8_t port_id, + CPortLatencyHWBase *io, + CManyIPInfo *src_addr, + CRXCoreIgnoreStat *ign_stats) { + + m_port_id = port_id; + m_io = io; + m_src_addr = src_addr; + m_ign_stats = ign_stats; } void @@ -689,9 +694,19 @@ RXGratARP::send_next_grat_arp() { CTestPktGen::create_arp_req(p, sip, sip, src_mac, vlan, m_port_id); - m_io->tx(m); + if (m_io->tx(m) == 0) { + m_ign_stats->m_tx_arp += 1; + m_ign_stats->m_tot_bytes += 64; + } +} + +Json::Value +RXGratARP::to_json() const { + Json::Value output = Json::objectValue; + output["interval_sec"] = (double)CGlobalInfo::m_options.m_arp_ref_per; + return output; } /************************************** @@ -729,11 +744,10 @@ RXPortManager::create(const TRexPortAttr *port_attr, /* init features */ m_latency.create(rfc2544, err_cntrs); m_server.create(m_port_id, io, &m_src_addr); - m_grat_arp.create(m_port_id, io, &m_src_addr); + m_grat_arp.create(m_port_id, io, &m_src_addr, &m_ign_stats); - /* by default, server feature is always on */ + /* by default, server is always on */ set_feature(SERVER); - set_feature(GRAT_ARP); } void RXPortManager::handle_pkt(const rte_mbuf_t *m) { @@ -797,13 +811,43 @@ RXPortManager::tick() { if (is_feature_set(RECORDER)) { m_recorder.flush_to_disk(); } - +} + +void +RXPortManager::send_next_grat_arp() { if (is_feature_set(GRAT_ARP)) { m_grat_arp.send_next_grat_arp(); } } + +void +RXPortManager::set_l2_mode() { + + /* no IPv4 addresses */ + m_src_addr.clear(); + + /* stop grat arp */ + stop_grat_arp(); +} + +void +RXPortManager::set_l3_mode(const CManyIPInfo &ip_info, bool is_grat_arp_needed) { + + /* copy L3 address */ + m_src_addr = ip_info; + + if (is_grat_arp_needed) { + start_grat_arp(); + } + else { + stop_grat_arp(); + } + +} + + Json::Value RXPortManager::to_json() const { Json::Value output = Json::objectValue; @@ -829,7 +873,23 @@ RXPortManager::to_json() const { output["queue"]["is_active"] = false; } + if (is_feature_set(GRAT_ARP)) { + output["grat_arp"] = m_grat_arp.to_json(); + output["grat_arp"]["is_active"] = true; + } else { + output["grat_arp"]["is_active"] = false; + } + return output; } +void RXPortManager::get_ignore_stats(CRXCoreIgnoreStat &stat, bool get_diff) { + if (get_diff) { + stat = m_ign_stats - m_ign_stats_prev; + m_ign_stats_prev = m_ign_stats; + } else { + stat = m_ign_stats; + } +} + diff --git a/src/stateless/rx/trex_stateless_rx_port_mngr.h b/src/stateless/rx/trex_stateless_rx_port_mngr.h index e72b0ff0..8947def7 100644 --- a/src/stateless/rx/trex_stateless_rx_port_mngr.h +++ b/src/stateless/rx/trex_stateless_rx_port_mngr.h @@ -284,12 +284,16 @@ private: class RXGratARP { public: RXGratARP() { - m_io = NULL; - m_port_id = UINT8_MAX; - m_src_addr = NULL; + m_io = NULL; + m_port_id = UINT8_MAX; + m_src_addr = NULL; + m_ign_stats = NULL; } - void create(uint8_t port_id, CPortLatencyHWBase *io, CManyIPInfo *src_addr); + void create(uint8_t port_id, + CPortLatencyHWBase *io, + CManyIPInfo *src_addr, + CRXCoreIgnoreStat *ignore_stats); /** @@ -298,10 +302,13 @@ public: */ void send_next_grat_arp(); + Json::Value to_json() const; + private: + uint8_t m_port_id; CPortLatencyHWBase *m_io; CManyIPInfo *m_src_addr; - uint8_t m_port_id; + CRXCoreIgnoreStat *m_ign_stats; }; /************************ manager ***************************/ @@ -389,7 +396,13 @@ public: return m_queue.fetch(); } + void start_grat_arp() { + set_feature(GRAT_ARP); + } + void stop_grat_arp() { + unset_feature(GRAT_ARP); + } /** * fetch and process all packets @@ -421,14 +434,25 @@ public: void tick(); /** - * updates the source addresses registered with the port + * send next grat arp (if on) * + * @author imarom (12/13/2016) */ - void update_src_addr(const CManyIPInfo &new_src_addr) { - /* deep copy */ - m_src_addr = new_src_addr; - } + void send_next_grat_arp(); + + /** + * set port mode to L2 + */ + void set_l2_mode(); + /** + * set port mode to L3 + * + * @author imarom (12/13/2016) + */ + void set_l3_mode(const CManyIPInfo &ip_info, bool is_grat_arp_needed); + + bool has_features_set() { return (m_features != NO_FEATURES); } @@ -439,6 +463,12 @@ public: } /** + * returns ignored set of stats + * (grat ARP, PING response and etc.) + */ + void get_ignore_stats(CRXCoreIgnoreStat &stat, bool get_diff); + + /** * write the status to a JSON format */ Json::Value to_json() const; @@ -475,6 +505,10 @@ private: CCpuUtlDp *m_cpu_dp_u; CPortLatencyHWBase *m_io; CManyIPInfo m_src_addr; + + /* stats to ignore (ARP and etc.) */ + CRXCoreIgnoreStat m_ign_stats; + CRXCoreIgnoreStat m_ign_stats_prev; }; diff --git a/src/trex_port_attr.h b/src/trex_port_attr.h index 437fa8c7..7336befa 100755 --- a/src/trex_port_attr.h +++ b/src/trex_port_attr.h @@ -133,7 +133,8 @@ 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; - + virtual bool is_loopback() const = 0; + uint32_t get_src_ipv4() const {return m_src_ipv4;} DestAttr & get_dest() {return m_dest;} @@ -219,7 +220,8 @@ public: virtual int get_xstats_names(xstats_names_t &xstats_names); virtual int get_flow_ctrl(int &mode); virtual void get_supported_speeds(supp_speeds_t &supp_speeds); - + virtual bool is_loopback() const; + /* SETTERS */ virtual int set_promiscuous(bool enabled); virtual int add_mac(char * mac); @@ -273,6 +275,7 @@ public: int set_led(bool on) { return -ENOTSUP; } void dump_link(FILE *fd) {} int set_rx_filter_mode(rx_filter_mode_e mode) { return -ENOTSUP; } + virtual bool is_loopback() const { return false; } }; |