From 34cb66c9f06c7a43e68a17b4a8802f8d34298a65 Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 25 Dec 2016 12:54:09 +0200 Subject: refactor layer config on prot attributes added guard against unconfigured MAC when going up with empty config file Signed-off-by: imarom --- .../trex_control_plane/stl/console/trex_console.py | 9 +- .../rx_services/trex_stl_rx_service_arp.py | 15 +- .../rx_services/trex_stl_rx_service_icmp.py | 8 +- .../stl/trex_stl_lib/trex_stl_client.py | 9 +- .../stl/trex_stl_lib/trex_stl_hltapi.py | 16 +- .../trex_stl_lib/trex_stl_packet_builder_scapy.py | 14 +- .../stl/trex_stl_lib/trex_stl_port.py | 91 ++++----- .../stl/trex_stl_lib/trex_stl_std.py | 5 + src/bp_sim.h | 4 +- src/main_dpdk.cpp | 12 +- src/stateless/cp/trex_stateless_port.cpp | 30 ++- src/trex_port_attr.cpp | 174 +++++++++-------- src/trex_port_attr.h | 214 ++++++++++++++++----- 13 files changed, 359 insertions(+), 242 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 627761ff..7d47128b 100755 --- a/scripts/automation/trex_control_plane/stl/console/trex_console.py +++ b/scripts/automation/trex_control_plane/stl/console/trex_console.py @@ -373,8 +373,13 @@ class TRexConsole(TRexGeneralCmd): print("No ports acquired\n") return - with self.stateless_client.logger.supress(): - table = stl_map_ports(self.stateless_client, ports = ports) + + try: + with self.stateless_client.logger.supress(): + table = stl_map_ports(self.stateless_client, ports = ports) + except STLError as e: + print(format_text(e.brief() + "\n", 'bold')) + return print(format_text('\nAcquired ports topology:\n', 'bold', 'underline')) diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/rx_services/trex_stl_rx_service_arp.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/rx_services/trex_stl_rx_service_arp.py index 2c159313..3cf97045 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/rx_services/trex_stl_rx_service_arp.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/rx_services/trex_stl_rx_service_arp.py @@ -16,15 +16,16 @@ class RXServiceARP(RXServiceAPI): def pre_execute (self): - self.dst = self.port.get_dst_addr() - self.src = self.port.get_src_addr() - + self.layer_cfg = dict(self.port.get_layer_cfg()) return self.port.ok() # return a list of streams for request def generate_request (self): - base_pkt = Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(psrc = self.src['ipv4'], pdst = self.dst['ipv4'], hwsrc = self.src['mac']) + base_pkt = Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(psrc = self.layer_cfg['ipv4']['src'], + pdst = self.layer_cfg['ipv4']['dst'], + hwsrc = self.layer_cfg['ether']['src']) + s1 = STLStream( packet = STLPktBuilder(pkt = base_pkt), mode = STLTXSingleBurst(total_pkts = 1) ) return [s1] @@ -41,13 +42,11 @@ class RXServiceARP(RXServiceAPI): arp = scapy_pkt['ARP'] # check this is the right ARP (ARP reply with the address) - if (arp.op != 2) or (arp.psrc != self.dst['ipv4']): + if (arp.op != 2) or (arp.psrc != self.layer_cfg['ipv4']['dst']): return None - + # return the data gathered from the ARP response return self.port.ok({'psrc' : arp.psrc, 'hwsrc': arp.hwsrc}) - - #return self.port.ok('Port {0} - Recieved ARP reply from: {1}, hw: {2}'.format(self.port.port_id, arp.psrc, arp.hwsrc)) def on_timeout_err (self, retries): diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/rx_services/trex_stl_rx_service_icmp.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/rx_services/trex_stl_rx_service_icmp.py index 486cd458..be5b6665 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/rx_services/trex_stl_rx_service_icmp.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/rx_services/trex_stl_rx_service_icmp.py @@ -23,9 +23,7 @@ class RXServiceICMP(RXServiceAPI): if not self.port.is_resolved(): return self.port.err('ping - port has an unresolved destination, cannot determine next hop MAC address') - self.src = self.port.get_src_addr() - self.dst = self.port.get_dst_addr() - + self.layer_cfg = dict(self.port.get_layer_cfg()) return self.port.ok() @@ -33,7 +31,7 @@ class RXServiceICMP(RXServiceAPI): # return a list of streams for request def generate_request (self): - base_pkt = Ether(dst = self.dst['mac'])/IP(src = self.src['ipv4'], dst = self.ping_ip)/ICMP(type = 8) + base_pkt = Ether(dst = self.layer_cfg['ether']['dst'])/IP(src = self.layer_cfg['ipv4']['src'], dst = self.layer_cfg['ipv4']['dst'])/ICMP(type = 8) pad = max(0, self.pkt_size - len(base_pkt)) base_pkt = base_pkt / (pad * 'x') @@ -51,7 +49,7 @@ class RXServiceICMP(RXServiceAPI): return None ip = scapy_pkt['IP'] - if ip.dst != self.src['ipv4']: + if ip.dst != self.layer_cfg['ipv4']['src']: return None icmp = scapy_pkt['ICMP'] 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 f86fff26..79ed3a36 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 @@ -1396,8 +1396,13 @@ class STLClient(object): def get_resolvable_ports (self): return [port_id for port_id, port_obj in self.ports.items() - if port_obj.is_acquired() and port_obj.get_dst_addr()['ipv4'] is not None] - + if port_obj.is_acquired() and port_obj.is_l3_mode()] + + def get_resolved_ports (self): + return [port_id + for port_id, port_obj in self.ports.items() + if port_obj.is_acquired() and port_obj.is_resolved()] + def get_service_enabled_ports(self): return [port_id diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py index 464869aa..cf594948 100755 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py @@ -1089,10 +1089,10 @@ def generate_packet(**user_kwargs): fix_ipv4_checksum = True ip_src_addr = kwargs['ip_src_addr'] if type(ip_src_addr) is str: - ip_src_addr = ipv4_str_to_num(is_valid_ipv4(ip_src_addr)) + ip_src_addr = ipv4_str_to_num(is_valid_ipv4_ret(ip_src_addr)) step = kwargs['ip_src_step'] if type(step) is str: - step = ipv4_str_to_num(is_valid_ipv4(step)) + step = ipv4_str_to_num(is_valid_ipv4_ret(step)) if step < 1: raise STLError('ip_src_step has to be at least 1') @@ -1129,11 +1129,11 @@ def generate_packet(**user_kwargs): fix_ipv4_checksum = True ip_dst_addr = kwargs['ip_dst_addr'] if type(ip_dst_addr) is str: - ip_dst_addr = ipv4_str_to_num(is_valid_ipv4(ip_dst_addr)) + ip_dst_addr = ipv4_str_to_num(is_valid_ipv4_ret(ip_dst_addr)) step = kwargs['ip_dst_step'] if type(step) is str: - step = ipv4_str_to_num(is_valid_ipv4(step)) + step = ipv4_str_to_num(is_valid_ipv4_ret(step)) if step < 1: raise STLError('ip_dst_step has to be at least 1') @@ -1188,11 +1188,11 @@ def generate_packet(**user_kwargs): if count < 0: raise STLError('ipv6_src_count has to be at least 1') if count > 0 or kwargs['ipv6_src_mode'] == 'random': - ipv6_src_addr_num = ipv4_str_to_num(is_valid_ipv6(kwargs['ipv6_src_addr'])[-4:]) + ipv6_src_addr_num = ipv4_str_to_num(is_valid_ipv6_ret(kwargs['ipv6_src_addr'])[-4:]) step = kwargs['ipv6_src_step'] if type(step) is str: # convert ipv6 step to number - step = ipv4_str_to_num(is_valid_ipv6(step)[-4:]) + step = ipv4_str_to_num(is_valid_ipv6_ret(step)[-4:]) if step < 1: raise STLError('ipv6_src_step has to be at least 1') @@ -1226,11 +1226,11 @@ def generate_packet(**user_kwargs): if count < 0: raise STLError('ipv6_dst_count has to be at least 1') if count > 0 or kwargs['ipv6_dst_mode'] == 'random': - ipv6_dst_addr_num = ipv4_str_to_num(is_valid_ipv6(kwargs['ipv6_dst_addr'])[-4:]) + ipv6_dst_addr_num = ipv4_str_to_num(is_valid_ipv6_ret(kwargs['ipv6_dst_addr'])[-4:]) step = kwargs['ipv6_dst_step'] if type(step) is str: # convert ipv6 step to number - step = ipv4_str_to_num(is_valid_ipv6(step)[-4:]) + step = ipv4_str_to_num(is_valid_ipv6_ret(step)[-4:]) if step < 1: raise STLError('ipv6_dst_step has to be at least 1') diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py index 6431b74a..c5fbab90 100755 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py @@ -57,7 +57,7 @@ def mac_str_to_num (mac_buffer): return _buffer_to_num(mac_buffer) -def is_valid_ipv4(ip_addr): +def is_valid_ipv4_ret(ip_addr): """ Return buffer in network order """ @@ -75,7 +75,7 @@ def is_valid_ipv4(ip_addr): raise CTRexPacketBuildException(-10,"Not valid ipv4 format"); -def is_valid_ipv6(ipv6_addr): +def is_valid_ipv6_ret(ipv6_addr): """ Return buffer in network order """ @@ -136,8 +136,8 @@ class CTRexScIpv4SimpleRange(CTRexScFieldRangeBase): super(CTRexScIpv4SimpleRange, self).__init__(field_name,field_type) self.min_ip = min_ip self.max_ip = max_ip - mmin=ipv4_str_to_num (is_valid_ipv4(min_ip)) - mmax=ipv4_str_to_num (is_valid_ipv4(max_ip)) + mmin=ipv4_str_to_num (is_valid_ipv4_ret(min_ip)) + mmax=ipv4_str_to_num (is_valid_ipv4_ret(max_ip)) if mmin > mmax : raise CTRexPacketBuildException(-11, 'CTRexScIpv4SimpleRange m_min ip is bigger than max'); @@ -152,8 +152,8 @@ class CTRexScIpv4TupleGen(CTRexScriptsBase): super(CTRexScIpv4TupleGen, self).__init__() self.min_ip = min_ipv4 self.max_ip = max_ipv4 - mmin=ipv4_str_to_num (is_valid_ipv4(min_ipv4)) - mmax=ipv4_str_to_num (is_valid_ipv4(max_ipv4)) + mmin=ipv4_str_to_num (is_valid_ipv4_ret(min_ipv4)) + mmax=ipv4_str_to_num (is_valid_ipv4_ret(max_ipv4)) if mmin > mmax : raise CTRexPacketBuildException(-11, 'CTRexScIpv4SimpleRange m_min ip is bigger than max'); @@ -619,7 +619,7 @@ def convert_val (val): if is_integer(val): return val if type(val) == str: - return ipv4_str_to_num (is_valid_ipv4(val)) + return ipv4_str_to_num (is_valid_ipv4_ret(val)) raise CTRexPacketBuildException(-11,("init val invalid %s ") % val ); def check_for_int (val): 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 d4275cb1..07587b9f 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 @@ -539,14 +539,14 @@ class Port(object): @writeable - def set_l3_mode (self, src_addr, dest_addr, resolved_mac = None): + def set_l3_mode (self, src_addr, dst_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, "src_addr": src_addr, - "dst_addr": dest_addr} + "dst_addr": dst_addr} if resolved_mac: params["resolved_mac"] = resolved_mac @@ -767,7 +767,10 @@ class Port(object): if not self.is_l3_mode(): return self.err('port is not configured with L3') - return self.set_l3_mode(self.get_src_addr()['ipv4'], self.get_dst_addr()['ipv4']) + layer_cfg = self.get_layer_cfg() + + # reconfigure server with unresolved IPv4 information + return self.set_l3_mode(layer_cfg['ipv4']['src'], layer_cfg['ipv4']['dst']) @@ -869,29 +872,32 @@ class Port(object): # RX filter mode info['rx_filter_mode'] = 'hardware match' if attr['rx_filter_mode'] == 'hw' else 'fetch all' - info['layer_mode'] = 'IPv4' if self.is_l3_mode() else 'Ethernet' - - # src MAC and IPv4 - info['src_mac'] = attr['src_mac'] - info['src_ipv4'] = attr['src_ipv4'] + # holds the information about all the layers configured for the port + layer_cfg = attr['layer_cfg'] + + info['src_mac'] = attr['layer_cfg']['ether']['src'] + + # pretty show per mode - if info['src_ipv4'] is None: - info['src_ipv4'] = '-' - - # dest - dest = attr['dest'] - if dest['type'] == 'mac': - info['dest'] = dest['mac'] - info['arp'] = '-' + if layer_cfg['ipv4']['state'] == 'none': + info['layer_mode'] = 'Ethernet' + info['src_ipv4'] = '-' + info['dest'] = layer_cfg['ether']['dst'] if layer_cfg['ether']['state'] == 'configured' else 'unconfigured' + info['arp'] = '-' - elif dest['type'] == 'ipv4': - info['dest'] = dest['ipv4'] - info['arp'] = dest['arp'] + elif layer_cfg['ipv4']['state'] == 'unresolved': + info['layer_mode'] = 'IPv4' + info['src_ipv4'] = layer_cfg['ipv4']['src'] + info['dest'] = layer_cfg['ipv4']['dst'] + info['arp'] = 'unresolved' - elif dest['type'] == 'ipv4_u': - info['dest'] = dest['ipv4'] - info['arp'] = 'unresolved' + elif layer_cfg['ipv4']['state'] == 'resolved': + info['layer_mode'] = 'IPv4' + info['src_ipv4'] = layer_cfg['ipv4']['src'] + info['dest'] = layer_cfg['ipv4']['dst'] + info['arp'] = layer_cfg['ether']['dst'] + # RX info rx_info = self.status['rx_info'] @@ -919,41 +925,24 @@ class Port(object): def get_port_state_name(self): return self.STATES_MAP.get(self.state, "Unknown") - def get_src_addr (self): - src_mac = self.__attr['src_mac'] - src_ipv4 = self.__attr['src_ipv4'] - - return {'mac': src_mac, 'ipv4': src_ipv4} + def get_layer_cfg (self): + return self.__attr['layer_cfg'] def get_rx_filter_mode (self): return self.__attr['rx_filter_mode'] - def get_dst_addr (self): - dest = self.__attr['dest'] - - if dest['type'] == 'mac': - return {'ipv4': None, 'mac': dest['mac']} - - elif dest['type'] == 'ipv4': - return {'ipv4': dest['ipv4'], 'mac': dest['arp']} - - elif dest['type'] == 'ipv4_u': - return {'ipv4': dest['ipv4'], 'mac': None} - - else: - assert(0) - def is_l3_mode (self): - return self.get_dst_addr()['ipv4'] is not None + return self.get_layer_cfg()['ipv4']['state'] != 'none' - # port is considered resolved if it's dest is either MAC or resolved IPv4 def is_resolved (self): - return (self.get_dst_addr()['mac'] is not None) + # for L3 + if self.is_l3_mode(): + return self.get_layer_cfg()['ipv4']['state'] != 'unresolved' + # for L2 + else: + return self.get_layer_cfg()['ether']['state'] != 'unconfigured' + - # return True if the port is valid for resolve (has an IPv4 address as dest) - def is_resolvable (self): - return (self.get_dst_addr()['ipv4'] is not None) - @writeable def arp_resolve (self, retries): @@ -971,7 +960,7 @@ class Port(object): return rc # update the port with L3 full configuration - rc = self.set_l3_mode(self.get_src_addr()['ipv4'], self.get_dst_addr()['ipv4'], arp_rc['hwsrc']) + rc = self.set_l3_mode(self.get_layer_cfg()['ipv4']['src'], self.get_layer_cfg()['ipv4']['dst'], arp_rc['hwsrc']) if not rc: return rc @@ -996,7 +985,7 @@ class Port(object): "description": info.get('description', 'N/A')[:18], "src MAC": info['src_mac'], "src IPv4": info['src_ipv4'], - "Destination": info['dest'], + "Destination": format_text("{0}".format(info['dest']), 'bold', 'red' if info['dest'] == 'unconfigured' else None), "ARP Resolution": format_text("{0}".format(info['arp']), 'bold', 'red' if info['arp'] == 'unresolved' else None), "PCI Address": info['pci_addr'], "NUMA Node": info['numa'], diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_std.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_std.py index 30fdb2dd..16f10026 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_std.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_std.py @@ -1,5 +1,6 @@ from .trex_stl_streams import * from .trex_stl_packet_builder_scapy import * +from .utils.common import * # map ports # will destroy all streams/data on the ports @@ -8,6 +9,10 @@ def stl_map_ports (client, ports = None): if ports is None: ports = client.get_all_ports() + unresolved_ports = list_difference(ports, client.get_resolved_ports()) + if unresolved_ports: + raise STLError("Port(s) {0} have unresolved destination addresses".format(unresolved_ports)) + stl_send_3_pkts(client, ports) tx_pkts = {} diff --git a/src/bp_sim.h b/src/bp_sim.h index a41349d0..328820cd 100755 --- a/src/bp_sim.h +++ b/src/bp_sim.h @@ -635,7 +635,8 @@ private: typedef struct mac_align_t_ { uint8_t dest[6]; uint8_t src[6]; - uint8_t pad[4]; + uint8_t is_set; + uint8_t pad[3]; } mac_align_t ; struct CMacAddrCfg { @@ -643,6 +644,7 @@ public: CMacAddrCfg (){ memset(u.m_data,0,sizeof(u.m_data)); u.m_mac.dest[3]=1; + u.m_mac.is_set = 0; } union { mac_align_t m_mac; diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index ffeec82a..95ab22b1 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -1762,7 +1762,7 @@ bool DpdkTRexPortAttr::update_link_status_nowait(){ /* in case of link status change - notify the dest object */ if (new_link.link_status != m_link.link_status) { - get_dest().on_link_down(); + on_link_down(); } } @@ -3407,8 +3407,8 @@ void CGlobalTRex::pre_test() { m_trex_stateless->get_port_by_id(port_id)->set_l3_mode(src_ipv4, dg, dst_mac); } - /* L2 mode */ - } else { + /* L2 mode */ + } else if (CGlobalInfo::m_options.m_mac_addr[port_id].u.m_mac.is_set) { m_trex_stateless->get_port_by_id(port_id)->set_l2_mode(dst_mac); } } @@ -4041,7 +4041,7 @@ 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) { + if (memcmp(m_ports[i].get_port_attr()->get_layer_cfg().get_ether().get_src(), mac, 6) == 0) { port_id = i; return true; } @@ -5364,6 +5364,8 @@ int update_global_info_from_platform_file(){ for (i=0; im_mac_info[i].copy_src(( char *)CGlobalInfo::m_options.m_mac_addr[i].u.m_mac.src) ; cg->m_mac_info[i].copy_dest(( char *)CGlobalInfo::m_options.m_mac_addr[i].u.m_mac.dest) ; + CGlobalInfo::m_options.m_mac_addr[i].u.m_mac.is_set = 1; + CGlobalInfo::m_options.m_ip_cfg[i].set_def_gw(cg->m_mac_info[i].get_def_gw()); CGlobalInfo::m_options.m_ip_cfg[i].set_ip(cg->m_mac_info[i].get_ip()); CGlobalInfo::m_options.m_ip_cfg[i].set_mask(cg->m_mac_info[i].get_mask()); @@ -7441,7 +7443,7 @@ int DpdkTRexPortAttr::set_rx_filter_mode(rx_filter_mode_e rx_filter_mode) { bool DpdkTRexPortAttr::is_loopback() const { uint8_t port_id; - return g_trex.lookup_port_by_mac(m_dest.get_dest_mac(), port_id); + return g_trex.lookup_port_by_mac(m_layer_cfg.get_ether().get_dst(), port_id); } /** diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index e9b3c6d4..7d331c6e 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -1012,12 +1012,10 @@ TrexStatelessPort::set_l2_mode(const uint8_t *dest_mac) { /* not valid under traffic */ verify_state(PORT_STATE_IDLE | PORT_STATE_STREAMS, "set_l2_mode"); - /* no IPv4 src */ - getPortAttrObj()->set_src_ipv4(0); - - /* set destination as MAC */ - getPortAttrObj()->get_dest().set_dest(dest_mac); - + /* configure port attributes for L2 */ + getPortAttrObj()->set_l2_mode(dest_mac); + + /* update RX core */ TrexStatelessRxSetL2Mode *msg = new TrexStatelessRxSetL2Mode(m_port_id); send_message_to_rx( (TrexStatelessCpToRxMsgBase *)msg ); } @@ -1031,15 +1029,12 @@ TrexStatelessPort::set_l3_mode(uint32_t src_ipv4, uint32_t dest_ipv4) { /* not valid under traffic */ verify_state(PORT_STATE_IDLE | PORT_STATE_STREAMS, "set_l3_mode"); - /* set src IPv4 */ - getPortAttrObj()->set_src_ipv4(src_ipv4); - - /* set dest IPv4 */ - getPortAttrObj()->get_dest().set_dest(dest_ipv4); - + /* configure port attributes with L3 */ + getPortAttrObj()->set_l3_mode(src_ipv4, dest_ipv4); + /* send RX core the relevant info */ CManyIPInfo ip_info; - ip_info.insert(COneIPv4Info(src_ipv4, 0, getPortAttrObj()->get_src_mac())); + ip_info.insert(COneIPv4Info(src_ipv4, 0, getPortAttrObj()->get_layer_cfg().get_ether().get_src())); TrexStatelessRxSetL3Mode *msg = new TrexStatelessRxSetL3Mode(m_port_id, ip_info, false); send_message_to_rx( (TrexStatelessCpToRxMsgBase *)msg ); @@ -1054,15 +1049,12 @@ TrexStatelessPort::set_l3_mode(uint32_t src_ipv4, uint32_t dest_ipv4, const uint verify_state(PORT_STATE_IDLE | PORT_STATE_STREAMS, "set_l3_mode"); - /* set src IPv4 */ - getPortAttrObj()->set_src_ipv4(src_ipv4); - - /* set dest IPv4 + resolved MAC */ - getPortAttrObj()->get_dest().set_dest(dest_ipv4, resolved_mac); + /* configure port attributes with L3 */ + getPortAttrObj()->set_l3_mode(src_ipv4, dest_ipv4, resolved_mac); /* send RX core the relevant info */ CManyIPInfo ip_info; - ip_info.insert(COneIPv4Info(src_ipv4, 0, getPortAttrObj()->get_src_mac())); + ip_info.insert(COneIPv4Info(src_ipv4, 0, getPortAttrObj()->get_layer_cfg().get_ether().get_src())); bool is_grat_arp_needed = !getPortAttrObj()->is_loopback(); diff --git a/src/trex_port_attr.cpp b/src/trex_port_attr.cpp index 2a68fcb9..4c5ac9e4 100644 --- a/src/trex_port_attr.cpp +++ b/src/trex_port_attr.cpp @@ -17,96 +17,118 @@ limitations under the License. #include "trex_port_attr.h" #include "bp_sim.h" -DestAttr::DestAttr(uint8_t port_id) { - m_port_id = port_id; +LayerConfigMAC::LayerConfigMAC(uint8_t port_id) { + /* use this for container (DP copies from here) */ + m_src_mac = CGlobalInfo::m_options.m_mac_addr[port_id].u.m_mac.src; + m_dst_mac = CGlobalInfo::m_options.m_mac_addr[port_id].u.m_mac.dest; - m_mac = CGlobalInfo::m_options.m_mac_addr[port_id].u.m_mac.dest; - m_type = DEST_TYPE_MAC; - - /* save the default */ - memcpy(m_default_mac, m_mac, 6); -} - - -/** - * set dest as an IPv4 unresolved - */ -void -DestAttr::set_dest(uint32_t ipv4) { - assert(ipv4 != 0); - - m_ipv4 = ipv4; - memset(m_mac, 0, 6); // just to be on the safe side - m_type = DEST_TYPE_IPV4_UNRESOLVED; + m_state = STATE_UNCONFIGRED; } -/** - * set dest as a resolved IPv4 - */ -void -DestAttr::set_dest(uint32_t ipv4, const uint8_t *mac) { - assert(ipv4 != 0); - - m_ipv4 = ipv4; +Json::Value +LayerConfigMAC::to_json() const { + Json::Value output; + + output["src"] = utl_macaddr_to_str(m_src_mac); + output["dst"] = utl_macaddr_to_str(m_dst_mac); + + switch (m_state) { + case STATE_CONFIGURED: + output["state"] = "configured"; + break; + case STATE_UNCONFIGRED: + output["state"] = "unconfigured"; + break; + + default: + assert(0); + } - /* source might be the same as dest (this shadows the datapath memory) */ - memmove(m_mac, mac, 6); - m_type = DEST_TYPE_IPV4; -} - -/** - * dest dest as MAC - * - */ -void -DestAttr::set_dest(const uint8_t *mac) { - - m_ipv4 = 0; - /* source might be the same as dest (this shadows the datapath memory) */ - memmove(m_mac, mac, 6); - m_type = DEST_TYPE_MAC; + return output; } -void -DestAttr::to_json(Json::Value &output) const { - switch (m_type) { +Json::Value +LayerConfigIPv4::to_json() const { + Json::Value output; - case DEST_TYPE_IPV4: - output["type"] = "ipv4"; - output["ipv4"] = utl_uint32_to_ipv4(m_ipv4); - output["arp"] = utl_macaddr_to_str(m_mac); + switch (m_state) { + case STATE_NONE: + output["state"] = "none"; break; - case DEST_TYPE_IPV4_UNRESOLVED: - output["type"] = "ipv4_u"; - output["ipv4"] = utl_uint32_to_ipv4(m_ipv4); + case STATE_UNRESOLVED: + output["state"] = "unresolved"; break; - - case DEST_TYPE_MAC: - output["type"] = "mac"; - output["mac"] = utl_macaddr_to_str(m_mac); + + case STATE_RESOLVED: + output["state"] = "resolved"; break; - + default: assert(0); } + + if (m_state != STATE_NONE) { + output["src"] = utl_uint32_to_ipv4(m_src_ipv4); + output["dst"] = utl_uint32_to_ipv4(m_dst_ipv4); + } + + return output; +} + +void LayerConfig::set_l2_mode(const uint8_t *dst_mac) { + /* set dst MAC */ + m_l2_config.set_dst(dst_mac); + m_l2_config.set_state(LayerConfigMAC::STATE_CONFIGURED); + + /* remove any IPv4 configuration*/ + m_l3_ipv4_config.set_state(LayerConfigIPv4::STATE_NONE); +} +void LayerConfig::set_l3_mode(uint32_t src_ipv4, uint32_t dst_ipv4) { + + /* L2 config */ + m_l2_config.set_state(LayerConfigMAC::STATE_UNCONFIGRED); + + /* L3 config */ + m_l3_ipv4_config.set_src(src_ipv4); + m_l3_ipv4_config.set_dst(dst_ipv4); + m_l3_ipv4_config.set_state(LayerConfigIPv4::STATE_UNRESOLVED); } -const uint8_t * -TRexPortAttr::get_src_mac() const { - return CGlobalInfo::m_options.get_src_mac_addr(m_port_id); +void LayerConfig::set_l3_mode(uint32_t src_ipv4, uint32_t dst_ipv4, const uint8_t *resolved_mac) { + + /* L2 config */ + m_l2_config.set_dst(resolved_mac); + m_l2_config.set_state(LayerConfigMAC::STATE_CONFIGURED); + + /* L3 config */ + m_l3_ipv4_config.set_src(src_ipv4); + m_l3_ipv4_config.set_dst(dst_ipv4); + m_l3_ipv4_config.set_state(LayerConfigIPv4::STATE_RESOLVED); } void -TRexPortAttr::set_src_ipv4(uint32_t addr) { - m_src_ipv4 = addr; +LayerConfig::on_link_down() { + + m_l2_config.set_state(LayerConfigMAC::STATE_UNCONFIGRED); - /* when IP source changes - consider this as link down */ - m_dest.on_link_down(); + if (m_l3_ipv4_config.get_state() == LayerConfigIPv4::STATE_RESOLVED) { + m_l3_ipv4_config.set_state(LayerConfigIPv4::STATE_UNRESOLVED); + } } + +Json::Value +LayerConfig::to_json() const { + Json::Value output; + output["ether"] = m_l2_config.to_json(); + output["ipv4"] = m_l3_ipv4_config.to_json(); + + return output; +} + std::string TRexPortAttr::get_rx_filter_mode() const { switch (m_rx_filter_mode) { @@ -119,34 +141,24 @@ TRexPortAttr::get_rx_filter_mode() const { } } +void +TRexPortAttr::on_link_down() { + m_layer_cfg.on_link_down(); +} 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() / 1000; // make sure we have no cards of less than 1 Gbps 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"] = Json::nullValue; - } - - int mode; get_flow_ctrl(mode); output["fc"]["mode"] = mode; - m_dest.to_json(output["dest"]); - + output["layer_cfg"] = m_layer_cfg.to_json(); } -void -TRexPortAttr::update_src_dst_mac(uint8_t *raw_pkt) const { - memcpy(raw_pkt, m_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 7336befa..01ffe424 100755 --- a/src/trex_port_attr.h +++ b/src/trex_port_attr.h @@ -27,84 +27,168 @@ limitations under the License. #include /** - * destination port attribute - * + * holds L2 MAC configuration */ -class DestAttr { - +class LayerConfigMAC { public: - - DestAttr(uint8_t port_id); /** - * dest can be either MAC IPv4, or IPv4 unresolved + * IPv4 state of resolution */ - enum dest_type_e { - DEST_TYPE_IPV4 = 1, - DEST_TYPE_IPV4_UNRESOLVED, - DEST_TYPE_MAC, + enum ether_state_e { + STATE_UNCONFIGRED, + STATE_CONFIGURED }; - /** - * set dest as an IPv4 unresolved - */ - void set_dest(uint32_t ipv4); + LayerConfigMAC(uint8_t port_id); + + void set_src(const uint8_t *src_mac) { + memcpy(m_src_mac, src_mac, 6); + } + + void set_dst(const uint8_t *dst_mac) { + memcpy(m_dst_mac, dst_mac, 6); + } + + const uint8_t *get_src() const { + return m_src_mac; + } + + const uint8_t *get_dst() const { + return m_dst_mac; + } + + void set_state(ether_state_e state) { + m_state = state; + } + + ether_state_e get_state() const { + return m_state; + } + + Json::Value to_json() const; + +private: + uint8_t *m_src_mac; + uint8_t *m_dst_mac; + ether_state_e m_state; +}; + +/** + * holds L3 IPv4 configuration + */ +class LayerConfigIPv4 { + +public: /** - * set dest as a resolved IPv4 + * IPv4 state of resolution */ - void set_dest(uint32_t ipv4, const uint8_t *mac); + enum ipv4_state_e { + STATE_NONE, + STATE_UNRESOLVED, + STATE_RESOLVED + }; + + LayerConfigIPv4() { + m_state = STATE_NONE; + } + + void set_src(uint32_t src_ipv4) { + m_src_ipv4 = src_ipv4; + } + + void set_dst(uint32_t dst_ipv4) { + m_dst_ipv4 = dst_ipv4; + } + + void set_state(ipv4_state_e state) { + m_state = state; + } + + uint32_t get_src() const { + return m_src_ipv4; + } + + uint32_t get_dst() const { + return m_dst_ipv4; + } + + ipv4_state_e get_state() const { + return m_state; + } + + Json::Value to_json() const; + +private: + ipv4_state_e m_state; + uint32_t m_src_ipv4; + uint32_t m_dst_ipv4; +}; + +/** + * holds all layer configuration + * + * @author imarom (12/25/2016) + */ +class LayerConfig { +public: + + LayerConfig(uint8_t port_id) : m_l2_config(port_id) { + m_port_id = port_id; + } /** - * set dest as a plain MAC + * configure port for L2 (no L3) + * */ - void set_dest(const uint8_t *mac); + void set_l2_mode(const uint8_t *dst_mac); - /** - * return true if destination is resolved + * configure port IPv4 (unresolved) + * */ - bool is_resolved() const { - return (m_type != DEST_TYPE_IPV4_UNRESOLVED); - } + void set_l3_mode(uint32_t src_ipv4, uint32_t dst_ipv4); /** - * get the dest mac - * if the dest is not resolved - * it will return the default MAC + * configure port IPv4 (resolved) + * */ - const uint8_t *get_dest_mac() const { - return m_mac; - } + void set_l3_mode(uint32_t src_ipv4, uint32_t dst_ipv4, const uint8_t *resolved_mac); /** - * when link gets down - this should be called + * event handler in case of a link down event * + * @author imarom (12/22/2016) */ - void on_link_down() { - if (m_type == DEST_TYPE_IPV4) { - /* reset the IPv4 dest with no resolution */ - set_dest(m_ipv4); - } + void on_link_down(); + + const LayerConfigMAC& get_ether() const { + return m_l2_config; } - void to_json(Json::Value &output) const; + const LayerConfigIPv4& get_ipv4() const { + return m_l3_ipv4_config; + } + /** + * write state to JSON + * + */ + Json::Value to_json() const; + private: - uint32_t m_ipv4; - uint8_t *m_mac; - dest_type_e m_type; - uint8_t m_port_id; -private: - uint8_t m_default_mac[6]; + uint8_t m_port_id; + LayerConfigMAC m_l2_config; + LayerConfigIPv4 m_l3_ipv4_config; }; class TRexPortAttr { public: - TRexPortAttr(uint8_t port_id) : m_dest(port_id) { + TRexPortAttr(uint8_t port_id) : m_layer_cfg(port_id) { m_src_ipv4 = 0; } @@ -135,15 +219,8 @@ public: 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;} - - 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) const; - /* SETTERS */ virtual int set_promiscuous(bool enabled) = 0; virtual int add_mac(char * mac) = 0; @@ -152,8 +229,34 @@ public: virtual int set_led(bool on) = 0; virtual int set_rx_filter_mode(rx_filter_mode_e mode) = 0; - void set_src_ipv4(uint32_t addr); + /** + * configures port for L2 mode + * + */ + void set_l2_mode(const uint8_t *dest_mac) { + m_layer_cfg.set_l2_mode(dest_mac); + } + + /** + * configures port in L3 mode + * unresolved + */ + void set_l3_mode(uint32_t src_ipv4, uint32_t dst_ipv4) { + m_layer_cfg.set_l3_mode(src_ipv4, dst_ipv4); + } + /** + * configure port for L3 mode + * resolved + */ + void set_l3_mode(uint32_t src_ipv4, uint32_t dst_ipv4, const uint8_t *resolved_mac) { + m_layer_cfg.set_l3_mode(src_ipv4, dst_ipv4, resolved_mac); + } + + const LayerConfig & get_layer_cfg() const { + return m_layer_cfg; + } + /* DUMPS */ virtual void dump_link(FILE *fd) = 0; @@ -164,12 +267,17 @@ public: return m_port_id; } + /** + * event handler for link down event + */ + void on_link_down(); + protected: uint8_t m_port_id; rte_eth_link m_link; uint32_t m_src_ipv4; - DestAttr m_dest; + LayerConfig m_layer_cfg; struct rte_eth_dev_info dev_info; -- cgit 1.2.3-korg