From 558ce764c2a5feaf376b562e455a2e9c1115701a Mon Sep 17 00:00:00 2001 From: imarom Date: Tue, 15 Nov 2016 19:20:10 +0200 Subject: RX features - another refinement Signed-off-by: imarom --- linux/ws_main.py | 1 + linux_dpdk/ws_main.py | 1 + .../stl/trex_stl_lib/trex_stl_client.py | 59 ++++++- .../stl/trex_stl_lib/trex_stl_port.py | 189 +++++++++++++++++++-- .../stl/trex_stl_lib/trex_stl_stats.py | 8 +- src/internal_api/trex_platform_api.h | 10 +- src/main_dpdk.cpp | 15 +- src/rpc-server/commands/trex_rpc_cmd_general.cpp | 37 +++- src/rpc-server/commands/trex_rpc_cmds.h | 1 + src/rpc-server/trex_rpc_cmds_table.cpp | 2 + src/stateless/cp/trex_stateless_port.cpp | 14 +- src/stateless/cp/trex_stateless_port.h | 13 +- src/stateless/dp/trex_stateless_dp_core.cpp | 29 ++-- src/stateless/rx/trex_stateless_rx_defs.h | 9 +- src/trex_port_attr.cpp | 71 ++++++++ src/trex_port_attr.h | 75 ++++---- 16 files changed, 417 insertions(+), 117 deletions(-) create mode 100644 src/trex_port_attr.cpp diff --git a/linux/ws_main.py b/linux/ws_main.py index 79e26915..9e77485d 100755 --- a/linux/ws_main.py +++ b/linux/ws_main.py @@ -119,6 +119,7 @@ main_src = SrcGroup(dir='src', 'utl_json.cpp', 'utl_cpuu.cpp', 'msg_manager.cpp', + 'trex_port_attr.cpp', 'publisher/trex_publisher.cpp', 'stateful_rx_core.cpp', 'flow_stat.cpp', diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py index 91cd728a..7477065e 100755 --- a/linux_dpdk/ws_main.py +++ b/linux_dpdk/ws_main.py @@ -132,6 +132,7 @@ main_src = SrcGroup(dir='src', 'nat_check.cpp', 'nat_check_flow_table.cpp', 'msg_manager.cpp', + 'trex_port_attr.cpp', 'publisher/trex_publisher.cpp', 'pal/linux_dpdk/pal_utl.cpp', 'pal/linux_dpdk/mbuf.cpp', 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 2ee5225c..3a37524c 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 @@ -804,6 +804,17 @@ class STLClient(object): return rc + def __resolve (self, port_id_list = None, retries = 0): + port_id_list = self.__ports(port_id_list) + + rc = RC() + + for port_id in port_id_list: + rc.add(self.ports[port_id].resolve(retries)) + + return rc + + def __set_port_attr (self, port_id_list = None, attr_dict = None): port_id_list = self.__ports(port_id_list) @@ -1770,6 +1781,9 @@ class STLClient(object): raise STLError(rc) def test (self): + self.resolve() + return + #rc = self.ports[0].resolve() #if not rc: # raise STLError(rc) @@ -1827,7 +1841,8 @@ class STLClient(object): + :exc:`STLError` """ - self.test() + self.resolve() + return self.logger.pre_cmd("Pinging the server on '{0}' port '{1}': ".format(self.connection_info['server'], self.connection_info['sync_port'])) @@ -2151,7 +2166,7 @@ class STLClient(object): validate_type('core_mask', core_mask, (int, list)) # verify link status - ports_link_down = [port_id for port_id in ports if self.ports[port_id].attr.get('link',{}).get('up') == False] + ports_link_down = [port_id for port_id in ports if not self.ports[port_id].is_up()] if not force and ports_link_down: raise STLError("Port(s) %s - link DOWN - check the connection or specify 'force'" % ports_link_down) @@ -2807,6 +2822,36 @@ class STLClient(object): raise STLError(rc) + @__api_check(True) + def resolve (self, ports = None, retries = 0): + """ + Resolves ports (ARP resolution) + + :parameters: + ports - for which ports to apply a unique sniffer (each port gets a unique file) + retires - how many times to retry on each port (intervals of 100 milliseconds) + :raises: + + :exe:'STLError' + + """ + # by default - resolve all the ports that are configured with IPv4 dest + if ports is None: + ports = [port_id for port_id in self.get_acquired_ports() if self.ports[port_id].get_dest()['type'] == 'ipv4'] + + ports = self._validate_port_list(ports) + + + self.logger.pre_cmd("Resolving destination on port(s) {0}:".format(ports)) + with self.logger.supress(): + rc = self.__resolve(ports, retries) + self.logger.post_cmd(rc) + + if not rc: + raise STLError(rc) + + + + @__api_check(True) def set_rx_sniffer (self, ports = None, base_filename = 'rx_capture', limit = 1000, rxf = None): """ @@ -2871,7 +2916,7 @@ class STLClient(object): The queue is cyclic and will hold last 'size' packets :parameters: - ports - for which ports to apply a unique sniffer (each port gets a unique file) + ports - for which ports to apply a queue size - size of the queue rxf - which RX filter to use on those ports: 'hw' or 'all' :raises: @@ -2905,6 +2950,8 @@ class STLClient(object): """ Removes RX queue from port(s) + :parameters: + ports - for which ports to remove the RX queue :raises: + :exe:'STLError' @@ -2927,7 +2974,10 @@ class STLClient(object): Returns any packets queued on the RX side by the server return value is a dictonary per port + :parameters: + ports - for which ports to fetch """ + ports = ports if ports is not None else self.get_acquired_ports() ports = self._validate_port_list(ports) @@ -3667,3 +3717,6 @@ class STLClient(object): else: return "{0} {1}>".format(prefix, self.get_acquired_ports()) + + + 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 3fd00391..e19eebe1 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 @@ -2,15 +2,18 @@ from collections import namedtuple, OrderedDict from .trex_stl_packet_builder_scapy import STLPktBuilder -from .trex_stl_streams import STLStream +from .trex_stl_streams import STLStream, STLTXSingleBurst from .trex_stl_types import * from . import trex_stl_stats from .utils.constants import FLOW_CTRL_DICT_REVERSED +from scapy.layers.l2 import Ether, ARP + import base64 import copy from datetime import datetime, timedelta import threading +import time StreamOnPort = namedtuple('StreamOnPort', ['compiled_stream', 'metadata']) @@ -143,7 +146,7 @@ class Port(object): return (self.handler != None) def is_up (self): - return (self.state != self.STATE_DOWN) + return self.__attr['link']['up'] def is_active(self): return (self.state == self.STATE_TX ) or (self.state == self.STATE_PAUSE) or (self.state == self.STATE_PCAP_TX) @@ -171,7 +174,6 @@ class Port(object): # take the port - @up def acquire(self, force = False, sync_streams = True): params = {"port_id": self.port_id, "user": self.user, @@ -191,7 +193,6 @@ class Port(object): # sync all the streams with the server - @up def sync_streams (self): params = {"port_id": self.port_id} @@ -207,7 +208,6 @@ class Port(object): return self.ok() # release the port - @up def release(self): params = {"port_id": self.port_id, "handler": self.handler} @@ -225,7 +225,6 @@ class Port(object): - @up def sync(self): params = {"port_id": self.port_id} @@ -510,6 +509,21 @@ class Port(object): return self.ok() + @owned + def set_arp_resolution (self, ipv4, mac): + + params = {"handler": self.handler, + "port_id": self.port_id, + "ipv4": ipv4, + "mac": mac} + + rc = self.transmit("set_arp_resolution", params) + if rc.bad(): + return self.err(rc.err()) + + return self.ok() + + @owned def remove_rx_sniffer (self): params = {"handler": self.handler, @@ -658,11 +672,11 @@ class Port(object): if kwargs.get('promiscuous') is not None: json_attr['promiscuous'] = {'enabled': kwargs.get('promiscuous')} - if kwargs.get('link_up') is not None: - json_attr['link_status'] = {'up': kwargs.get('link_up')} + if kwargs.get('link_status') is not None: + json_attr['link_status'] = {'up': kwargs.get('link_status')} - if kwargs.get('led_on') is not None: - json_attr['led_status'] = {'on': kwargs.get('led_on')} + if kwargs.get('led_status') is not None: + json_attr['led_status'] = {'on': kwargs.get('led_status')} if kwargs.get('flow_ctrl_mode') is not None: json_attr['flow_ctrl_mode'] = {'on': kwargs.get('flow_ctrl_mode')} @@ -713,7 +727,35 @@ class Port(object): def get_profile (self): return self.profile - + # invalidates the current ARP + def invalidate_arp (self): + dest = self.__attr['dest'] + + if dest['type'] != 'mac': + return self.set_attr(dest = dest['addr']) + else: + return self.ok() + + + @writeable + def add_arp_request (self): + ipv4 = self.__attr['src_ipv4'] + dest = self.__attr['dest'] + mac = self.__attr['src_mac'] + + if ipv4 == 'none': + return self.err('port must have a configured IPv4') + + if dest['type'] == 'mac': + return self.err('port must have an IPv4 destination') + + + base_pkt = Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(psrc = ipv4, pdst = dest['addr'], hwsrc = mac) + s1 = STLStream( packet = STLPktBuilder(pkt = base_pkt), mode = STLTXSingleBurst(total_pkts = 1) ) + + return self.add_streams([s1]) + + def print_profile (self, mult, duration): if not self.get_profile(): return @@ -874,10 +916,17 @@ class Port(object): src_ipv4 = None return src_ipv4 + + def get_dest (self): + return self.__attr['dest'] def get_src_mac (self): return self.__attr['src_mac'] - + + + def resolve (self, retries): + return ARPResolver(self).resolve(retries) + ################# stats handler ###################### def generate_port_stats(self): @@ -944,7 +993,7 @@ class Port(object): return {"streams" : OrderedDict(sorted(data.items())) } - + ######## attributes are a complex type (dict) that might be manipulated through the async thread ############# # get in a thread safe manner a duplication of attributes @@ -1017,3 +1066,117 @@ class Port(object): def async_event_released (self): self.owner = '' + +# a class to handle port ARP resolution +class ARPResolver(object): + def __init__ (self, port): + self.port = port + + # some sanity checks before resolving + def sanity (self): + if self.port.get_dest()['type'] == 'mac': + return self.port.err('resolve - port does not have an IPv4 as destination') + + if self.port.get_src_ipv4() is None: + return self.port.err('resolve - port does not have an IPv4 address configured') + + return self.port.ok() + + # main resolve function + def resolve (self, retries): + rc = self.sanity() + if not rc: + return rc + + # invalidate the current ARP resolution (if exists) + rc = self.port.invalidate_arp() + if not rc: + return rc + + rc = self.port.remove_all_streams() + if not rc: + return rc + + rc = self.port.set_rx_queue(size = 100) + if not rc: + return rc + + rc = self.port.add_arp_request() + if not rc: + return rc + + + # retry for 'retries' + index = 0 + while True: + response = self.resolve_iteration() + if response: + break + + if index >= retries: + return self.port.err('failed to receive ARP response ({0} retries)'.format(retries)) + + index += 1 + time.sleep(0.1) + + + # set ARP resolution result + rc = self.port.set_arp_resolution(response['ipv4'], response['mac']) + if not rc: + return rc + + return self.port.ok() + + + def resolve_iteration (self): + + mult = {'op': 'abs', 'type' : 'percentage', 'value': 100} + rc = self.port.start(mul = mult, force = False, duration = -1, mask = 0xffffffff) + if not rc: + return rc + + # block until traffic finishes + while self.port.is_active(): + time.sleep(0.01) + + return self.wait_for_rx_response() + + + def wait_for_rx_response (self): + + # we try to fetch response for 5 times + polling = 5 + + while polling > 0: + rx_pkts = self.port.get_rx_queue_pkts() + response = self.find_arp_response(rx_pkts) + + if response: + return response + + if polling == 0: + return None + + polling -= 1 + time.sleep(0.1) + + + # search in 'pkts' for an ARP response that matches the dest + def find_arp_response (self, pkts): + + for pkt in pkts: + scapy_pkt = Ether(pkt) + if not 'ARP' in scapy_pkt: + continue + + arp = scapy_pkt['ARP'] + dest = self.port.get_dest() + + # check this is the right ARP (ARP reply with the address) + if (arp.op != 2) or (arp.psrc != dest['addr']): + continue + + return {'ipv4': arp.psrc, 'mac': arp.hwsrc} + + return None + 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 f0293016..2efb5a84 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 @@ -1109,13 +1109,7 @@ class CPortStats(CTRexStats): port_state = format_text(port_state, 'bold') if self._port_obj: - if 'link' in self._port_obj.attr: - if self._port_obj.attr.get('link', {}).get('up') == False: - link_state = format_text('DOWN', 'red', 'bold') - else: - link_state = 'UP' - else: - link_state = 'N/A' + link_state = 'UP' if self._port_obj.is_up() else format_text('DOWN', 'red', 'bold') else: link_state = '' diff --git a/src/internal_api/trex_platform_api.h b/src/internal_api/trex_platform_api.h index 1445d3e9..5723503c 100644 --- a/src/internal_api/trex_platform_api.h +++ b/src/internal_api/trex_platform_api.h @@ -113,19 +113,13 @@ public: IF_STAT_RX_BYTES_COUNT = 8, // Card support counting rx bytes }; - struct mac_cfg_st { - uint8_t hw_macaddr[6]; - uint8_t src_macaddr[6]; - uint8_t dst_macaddr[6]; - }; - /** * interface static info * */ struct intf_info_st { std::string driver_name; - mac_cfg_st mac_info; + uint8_t hw_macaddr[6]; std::string pci_addr; int numa_node; bool has_crc; @@ -235,7 +229,7 @@ public: info.has_crc = true; info.numa_node = 0; - memset(&info.mac_info, 0, sizeof(info.mac_info)); + memset(&info.hw_macaddr, 0, sizeof(info.hw_macaddr)); } virtual void get_interface_stats(uint8_t interface_id, TrexPlatformInterfaceStats &stats) const { diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index 8f887006..fed7a348 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -1659,7 +1659,7 @@ bool DpdkTRexPortAttr::get_promiscuous(){ } -void DpdkTRexPortAttr::macaddr_get(struct ether_addr *mac_addr){ +void DpdkTRexPortAttr::get_hw_src_mac(struct ether_addr *mac_addr){ rte_eth_macaddr_get(m_port_id , mac_addr); } @@ -6502,19 +6502,10 @@ TrexDpdkPlatformApi::get_interface_info(uint8_t interface_id, intf_info_st &info /* mac INFO */ /* hardware */ - g_trex.m_ports[interface_id].get_port_attr()->macaddr_get(&rte_mac_addr); + g_trex.m_ports[interface_id].get_port_attr()->get_hw_src_mac(&rte_mac_addr); assert(ETHER_ADDR_LEN == 6); - /* software */ - uint8_t sw_macaddr[12]; - memcpy(sw_macaddr, CGlobalInfo::m_options.get_dst_src_mac_addr(interface_id), 12); - - for (int i = 0; i < 6; i++) { - info.mac_info.hw_macaddr[i] = rte_mac_addr.addr_bytes[i]; - info.mac_info.dst_macaddr[i] = sw_macaddr[i]; - info.mac_info.src_macaddr[i] = sw_macaddr[6 + i]; - - } + memcpy(info.hw_macaddr, rte_mac_addr.addr_bytes, 6); info.numa_node = g_trex.m_ports[interface_id].m_dev_info.pci_dev->numa_node; struct rte_pci_addr *loc = &g_trex.m_ports[interface_id].m_dev_info.pci_dev->addr; diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index 8d61ecba..e7f0de7b 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -846,8 +846,12 @@ TrexRpcCmdGetRxQueuePkts::_run(const Json::Value ¶ms, Json::Value &result) { TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id); try { - RxPacketBuffer *pkt_buffer = port->get_rx_queue_pkts(); - result["result"]["pkts"] = pkt_buffer->to_json(); + const RxPacketBuffer *pkt_buffer = port->get_rx_queue_pkts(); + if (pkt_buffer) { + result["result"]["pkts"] = pkt_buffer->to_json(); + } else { + result["result"]["pkts"] = Json::arrayValue; + } } catch (const TrexException &ex) { generate_execute_err(result, ex.what()); @@ -856,3 +860,32 @@ TrexRpcCmdGetRxQueuePkts::_run(const Json::Value ¶ms, Json::Value &result) { return (TREX_RPC_CMD_OK); } + +trex_rpc_cmd_rc_e +TrexRpcCmdSetARPRes::_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); + + 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()); + } + + uint8_t mac[6]; + if (!utl_str_to_macaddr(mac_str, mac)) { + std::stringstream ss; + ss << "'invalid MAC address: '" << mac_str << "'"; + generate_parse_err(result, ss.str()); + } + + port->getPortAttrObj()->get_dest().set_dest_ipv4(ipv4_addr, mac); + + 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 9fb4d551..fab81f67 100644 --- a/src/rpc-server/commands/trex_rpc_cmds.h +++ b/src/rpc-server/commands/trex_rpc_cmds.h @@ -162,6 +162,7 @@ TREX_RPC_CMD_DEFINE_EXTENDED(TrexRpcCmdSetRxFeature, "set_rx_feature", 3, false, ); 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 f006a4cd..919be1f1 100644 --- a/src/rpc-server/trex_rpc_cmds_table.cpp +++ b/src/rpc-server/trex_rpc_cmds_table.cpp @@ -74,6 +74,8 @@ TrexRpcCommandsTable::TrexRpcCommandsTable() { register_command(new TrexRpcCmdSetRxFeature()); register_command(new TrexRpcCmdGetRxQueuePkts()); + + register_command(new TrexRpcCmdSetARPRes()); } diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index ff83087c..d4bc5c36 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -887,16 +887,6 @@ TrexStatelessPort::get_port_effective_rate(double &pps, } -void -TrexStatelessPort::get_macaddr(std::string &hw_macaddr, - std::string &src_macaddr, - std::string &dst_macaddr) { - - utl_macaddr_to_str(m_api_info.mac_info.hw_macaddr, hw_macaddr); - utl_macaddr_to_str(m_api_info.mac_info.src_macaddr, src_macaddr); - utl_macaddr_to_str(m_api_info.mac_info.dst_macaddr, dst_macaddr); -} - void TrexStatelessPort::get_pci_info(std::string &pci_addr, int &numa_node) { pci_addr = m_api_info.pci_addr; @@ -980,6 +970,10 @@ TrexStatelessPort::stop_rx_queue() { RxPacketBuffer * TrexStatelessPort::get_rx_queue_pkts() { + if (m_rx_features_info.m_rx_queue_info.is_empty()) { + return NULL; + } + /* ask RX core for the pkt queue */ TrexStatelessMsgReply msg_reply; diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index d71ba932..cf6b2716 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -362,11 +362,6 @@ public: double &bps_L2, double &percentage); - - void get_macaddr(std::string &hw_macaddr, - std::string &src_macaddr, - std::string &dst_macaddr); - void get_pci_info(std::string &pci_addr, int &numa_node); @@ -413,6 +408,14 @@ public: */ RxPacketBuffer *get_rx_queue_pkts(); + /** + * return the port attribute object + * + */ + TRexPortAttr *getPortAttrObj() { + return m_platform_api->getPortAttrObj(m_port_id); + } + private: bool is_core_active(int core_id); diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 857ac8f9..43b77bee 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -26,7 +26,7 @@ limitations under the License. #include "trex_stream_node.h" #include "trex_streams_compiler.h" #include "mbuf.h" - +#include "trex_stateless.h" @@ -495,12 +495,14 @@ bool TrexStatelessDpPerPort::push_pcap(uint8_t port_id, /* main port */ uint8_t mac_addr[12]; - m_core->m_node_gen.m_v_if->update_mac_addr_from_global_cfg(dir, mac_addr); - + TRexPortAttr *master_port_attr = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id); + master_port_attr->update_src_dst_mac(mac_addr); + /* for dual */ uint8_t slave_mac_addr[12]; - m_core->m_node_gen.m_v_if->update_mac_addr_from_global_cfg(dir ^ 0x1, slave_mac_addr); - + TRexPortAttr *slave_port_attr = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id ^ 0x1); + slave_port_attr->update_src_dst_mac(slave_mac_addr); + bool rc = pcap_node->create(port_id, dir, socket_id, @@ -823,8 +825,9 @@ void TrexStatelessDpCore::update_mac_addr(TrexStream * stream, CGenNodeStateless *node, pkt_dir_t dir, char *raw_pkt){ - bool ov_src = stream->get_override_src_mac_by_pkt_data(); - TrexStream::stream_dst_mac_t ov_dst = stream->get_override_dst_mac_mode(); + + bool ov_src = stream->get_override_src_mac_by_pkt_data(); + TrexStream::stream_dst_mac_t ov_dst = stream->get_override_dst_mac_mode(); if ( (ov_src == true) && (ov_dst == TrexStream::stPKT) ) { @@ -832,11 +835,13 @@ void TrexStatelessDpCore::update_mac_addr(TrexStream * stream, return; } - /* take from cfg_file */ + TRexPortAttr *port_attr = get_stateless_obj()->get_platform_api()->getPortAttrObj(node->get_port_id()); + + /* take from cfg_file */ if ( (ov_src == false) && (ov_dst == TrexStream::stCFG_FILE) ){ - - m_core->m_node_gen.m_v_if->update_mac_addr_from_global_cfg(dir,(uint8_t*)raw_pkt); + + port_attr->update_src_dst_mac((uint8_t *)raw_pkt); return; } @@ -844,8 +849,8 @@ void TrexStatelessDpCore::update_mac_addr(TrexStream * stream, char tmp_pkt[12]; memcpy(tmp_pkt,raw_pkt,12); - m_core->m_node_gen.m_v_if->update_mac_addr_from_global_cfg(dir,(uint8_t*)raw_pkt); - + port_attr->update_src_dst_mac((uint8_t *)raw_pkt); + if ((ov_src == true) && (ov_dst == TrexStream::stCFG_FILE)) { memcpy(raw_pkt+6,tmp_pkt+6,6); } diff --git a/src/stateless/rx/trex_stateless_rx_defs.h b/src/stateless/rx/trex_stateless_rx_defs.h index bdd86a72..7b1e0f32 100644 --- a/src/stateless/rx/trex_stateless_rx_defs.h +++ b/src/stateless/rx/trex_stateless_rx_defs.h @@ -79,6 +79,10 @@ public: m_limit = 0; } + bool is_empty() const { + return (m_shared_counter == 0); + } + void to_json(Json::Value &output) const { output["is_active"] = m_is_active; if (m_is_active) { @@ -114,7 +118,10 @@ public: m_size = 0; } - + bool is_empty() const { + return (m_shared_counter == 0); + } + void to_json(Json::Value &output) const { output["is_active"] = m_is_active; if (m_is_active) { diff --git a/src/trex_port_attr.cpp b/src/trex_port_attr.cpp new file mode 100644 index 00000000..08e151b6 --- /dev/null +++ b/src/trex_port_attr.cpp @@ -0,0 +1,71 @@ +/* +Copyright (c) 2015-2015 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "trex_port_attr.h" +#include "bp_sim.h" + +const uint8_t DestAttr::g_dummy_mac[6] = {0x0,0x0,0x0,0x1,0x0,0x0}; + + +const uint8_t * +TRexPortAttr::get_src_mac() const { + return CGlobalInfo::m_options.get_src_mac_addr(m_port_id); +} + + +std::string +TRexPortAttr::get_rx_filter_mode() const { + switch (m_rx_filter_mode) { + case RX_FILTER_MODE_ALL: + return "all"; + case RX_FILTER_MODE_HW: + return "hw"; + default: + assert(0); + } +} + + +void +TRexPortAttr::to_json(Json::Value &output) { + + output["src_mac"] = utl_macaddr_to_str(get_src_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(); + + if (get_src_ipv4() != 0) { + output["src_ipv4"] = utl_uint32_to_ipv4(get_src_ipv4()); + } else { + output["src_ipv4"] = "none"; + } + + + int mode; + get_flow_ctrl(mode); + output["fc"]["mode"] = mode; + + m_dest.to_json(output["dest"]); + +} + +void +TRexPortAttr::update_src_dst_mac(uint8_t *raw_pkt) { + memcpy(raw_pkt, get_dest().get_dest_mac(), 6); + memcpy(raw_pkt + 6, get_src_mac(), 6); +} + diff --git a/src/trex_port_attr.h b/src/trex_port_attr.h index cdbb466c..68f9f82e 100755 --- a/src/trex_port_attr.h +++ b/src/trex_port_attr.h @@ -22,18 +22,21 @@ limitations under the License. #include "rte_ethdev_includes.h" #include "trex_defs.h" #include "common/basic_utils.h" +#include +#include "trex_stateless_rx_defs.h" /** * destination port attribute * */ class DestAttr { +private: + static const uint8_t g_dummy_mac[6]; public: DestAttr() { /* use a dummy MAC as default */ - uint8_t dummy_mac [] = {0xff,0xff,0xff,0xff,0xff,0xff}; - set_dest_mac(dummy_mac); + set_dest_mac(g_dummy_mac); } enum dest_type_e { @@ -89,6 +92,20 @@ public: return false; } + /** + * get the dest mac + * if no MAC is configured and dest was not resolved + * will return a dummy + */ + const uint8_t *get_dest_mac() { + + if (is_resolved()) { + return m_mac; + } else { + return g_dummy_mac; + } + } + /** * when link gets down - this should be called * @@ -149,7 +166,7 @@ public: /* GETTERS */ virtual bool get_promiscuous() = 0; - virtual void macaddr_get(struct ether_addr *mac_addr) = 0; + virtual void get_hw_src_mac(struct ether_addr *mac_addr) = 0; virtual uint32_t get_link_speed() { return m_link.link_speed; } // L1 Mbps virtual bool is_link_duplex() { return (m_link.link_duplex ? true : false); } virtual bool is_link_autoneg() { return (m_link.link_autoneg ? true : false); } @@ -163,21 +180,16 @@ 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_src_ipv4() {return m_src_ipv4;} DestAttr & get_dest() {return m_dest;} - 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); - } - } - + const uint8_t *get_src_mac() const; + std::string get_rx_filter_mode() const; + /* for a raw packet, write the src/dst MACs */ + void update_src_dst_mac(uint8_t *raw_pkt); + /* SETTERS */ virtual int set_promiscuous(bool enabled) = 0; virtual int add_mac(char * mac) = 0; @@ -190,37 +202,12 @@ public: m_src_ipv4 = addr; } -/* DUMPS */ + /* 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["src_mac"] = utl_macaddr_to_str(mac_addr); - output["promiscuous"]["enabled"] = get_promiscuous(); - output["link"]["up"] = is_link_up(); - output["speed"] = get_link_speed(); - output["rx_filter_mode"] = get_rx_filter_mode(); - - if (get_src_ipv4() != 0) { - output["src_ipv4"] = utl_uint32_to_ipv4(get_src_ipv4()); - } else { - output["src_ipv4"] = "none"; - } - - - int mode; - get_flow_ctrl(mode); - output["fc"]["mode"] = mode; - - m_dest.to_json(output["dest"]); - - } + void to_json(Json::Value &output); + protected: @@ -273,7 +260,7 @@ public: /* GETTERS */ virtual bool get_promiscuous(); - virtual void macaddr_get(struct ether_addr *mac_addr); + virtual void get_hw_src_mac(struct ether_addr *mac_addr); virtual int get_xstats_values(xstats_values_t &xstats_values); virtual int get_xstats_names(xstats_names_t &xstats_names); virtual int get_flow_ctrl(int &mode); @@ -319,7 +306,7 @@ public: void reset_xstats() {} void update_description() {} bool get_promiscuous() { return false; } - void macaddr_get(struct ether_addr *mac_addr) {} + void get_hw_src_mac(struct ether_addr *mac_addr) {} int get_xstats_values(xstats_values_t &xstats_values) { return -ENOTSUP; } int get_xstats_names(xstats_names_t &xstats_names) { return -ENOTSUP; } int get_flow_ctrl(int &mode) { return -ENOTSUP; } -- cgit 1.2.3-korg