refactor layer config on prot attributes 09/5209/1
authorimarom <[email protected]>
Sun, 25 Dec 2016 10:54:09 +0000 (12:54 +0200)
committerimarom <[email protected]>
Sun, 25 Dec 2016 11:50:56 +0000 (13:50 +0200)
added guard against unconfigured MAC when going up with empty config
file

Signed-off-by: imarom <[email protected]>
13 files changed:
scripts/automation/trex_control_plane/stl/console/trex_console.py
scripts/automation/trex_control_plane/stl/trex_stl_lib/rx_services/trex_stl_rx_service_arp.py
scripts/automation/trex_control_plane/stl/trex_stl_lib/rx_services/trex_stl_rx_service_icmp.py
scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py
scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py
scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py
scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py
scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_std.py
src/bp_sim.h
src/main_dpdk.cpp
src/stateless/cp/trex_stateless_port.cpp
src/trex_port_attr.cpp
src/trex_port_attr.h

index 627761f..7d47128 100755 (executable)
@@ -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'))
index 2c15931..3cf9704 100644 (file)
@@ -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):
index 486cd45..be5b666 100644 (file)
@@ -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']
index f86fff2..79ed3a3 100755 (executable)
@@ -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
index 464869a..cf59494 100755 (executable)
@@ -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')
index 6431b74..c5fbab9 100755 (executable)
@@ -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):
index d4275cb..07587b9 100644 (file)
@@ -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'],
index 30fdb2d..16f1002 100644 (file)
@@ -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 = {}
index a41349d..328820c 100755 (executable)
@@ -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;
index ffeec82..95ab22b 100644 (file)
@@ -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; i<port_size; i++){
             cg->m_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);
 }
 
 /**
index e9b3c6d..7d331c6 100644 (file)
@@ -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();
     
index 2a68fcb..4c5ac9e 100644 (file)
@@ -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);
-}
 
index 7336bef..01ffe42 100755 (executable)
@@ -27,84 +27,168 @@ limitations under the License.
 #include <string.h>
 
 /**
- * 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;