openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

tunnel.c (23845B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        l3.c
      8  * Purpose:     Triumph2 L3 function implementations
      9  */
     10 
     11 
     12 #include <soc/defs.h>
     13 
     14 #include <assert.h>
     15 #include <shared/bsl.h>
     16 #include <sal/core/libc.h>
     17 #if defined(BCM_TRIUMPH2_SUPPORT)  && defined(INCLUDE_L3)
     18 
     19 #include <shared/util.h>
     20 #include <soc/mem.h>
     21 #include <soc/cm.h>
     22 #include <soc/drv.h>
     23 #include <soc/register.h>
     24 #include <soc/memory.h>
     25 #include <soc/l3x.h>
     26 #include <soc/lpm.h>
     27 #include <soc/tnl_term.h>
     28 #include <soc/defragment.h>
     29 
     30 #include <bcm/l3.h>
     31 #include <bcm/tunnel.h>
     32 #include <bcm/debug.h>
     33 #include <bcm/error.h>
     34 #include <bcm/stack.h>
     35 
     36 #include <bcm_int/esw/mbcm.h>
     37 #include <bcm_int/esw/firebolt.h>
     38 #include <bcm_int/esw/trx.h>
     39 #include <bcm_int/esw/triumph2.h>
     40 #include <bcm_int/esw/l3.h>
     41 #include <bcm_int/esw/xgs3.h>
     42 #include <bcm_int/esw/stack.h>
     43 #include <bcm_int/esw_dispatch.h>
     44 #if defined(BCM_TRIDENT2_SUPPORT)
     45 #include <bcm_int/esw/trident2.h>
     46 #endif /* BCM_TRIDENT2_SUPPORT*/
     47 #if defined(BCM_TOMAHAWK_SUPPORT)
     48 #include <bcm_int/esw/tomahawk.h>
     49 #endif /* BCM_TOMAHAWK_SUPPORT */
     50 #include <bcm_int/esw/ecn.h>
     51 
     52 static soc_profile_mem_t *_bcm_tnl_port_bitmap_profile[BCM_MAX_NUM_UNITS];
     53 
     54 soc_profile_mem_t *_bcm_get_tnl_port_bitmap_profile(int unit) {
     55     return _bcm_tnl_port_bitmap_profile[unit];
     56 }
     57 
     58 int
     59 _bcm_tnl_port_bitmap_profile_init(int unit)
     60 {
     61     int i, idx;
     62     soc_mem_t mem;
     63     int entry_words[1];
     64     void *entries[1];
     65     allowed_port_bitmap_profile_entry_t allowed_ports_profile;
     66     void *prof_entry;
     67     uint32 ent_sz;
     68     int temp_idx = 0, key_type = 0;
     69     uint32 entry_ptr[SOC_MAX_MEM_WORDS];
     70     uint32 temp_index = 0;
     71     soc_mem_t tunnel_mem = L3_TUNNEL_DOUBLEm;
     72 
     73     /* Create profile table cache (or re-init if it already exists) */
     74     mem = ALLOWED_PORT_BITMAP_PROFILEm;
     75     ent_sz = sizeof(allowed_port_bitmap_profile_entry_t);
     76     prof_entry = &allowed_ports_profile;
     77 
     78     if (_bcm_tnl_port_bitmap_profile[unit] == NULL) {
     79         _bcm_tnl_port_bitmap_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
     80                                              "TUNNEL Port bitmap Profile Mem");
     81         if (_bcm_tnl_port_bitmap_profile[unit] == NULL) {
     82             return BCM_E_MEMORY;
     83         }
     84         soc_profile_mem_t_init(_bcm_tnl_port_bitmap_profile[unit]);
     85     }
     86 
     87     /* Create profile table cache (or re-init if it already exists) */
     88     entry_words[0] = ent_sz / sizeof(uint32);
     89     SOC_IF_ERROR_RETURN(
     90         soc_profile_mem_create(unit, &mem, entry_words, 1,
     91                            _bcm_tnl_port_bitmap_profile[unit]));
     92 
     93     if (SOC_WARM_BOOT(unit)) {
     94 
     95         /* One extra increment to preserve location
     96          * ING_ACTION_PROFILE_DEFAULT */
     97         SOC_PROFILE_MEM_REFERENCE(unit, _bcm_tnl_port_bitmap_profile[unit],
     98                                   0, 1);
     99 
    100         for (i = 0; i < soc_mem_index_count(unit, tunnel_mem); i++) {
    101 
    102             sal_memset(prof_entry, 0, ent_sz);
    103             SOC_IF_ERROR_RETURN
    104                 (READ_L3_TUNNEL_DOUBLEm(unit, MEM_BLOCK_ANY, i, &entry_ptr));
    105                 idx = soc_mem_field32_get(unit, tunnel_mem,
    106                              &entry_ptr, BASE_VALID_0f);
    107             if (idx == 0) {
    108                 continue;
    109             }
    110 
    111             key_type = soc_mem_field32_get(unit, tunnel_mem,
    112                              &entry_ptr, KEY_TYPEf);
    113             if (key_type == 0) {
    114                 continue;
    115             }
    116             /* Check key type to know memory type. */
    117             tunnel_mem = ((key_type == 2) ?
    118                               L3_TUNNEL_QUADm : L3_TUNNEL_DOUBLEm);
    119 
    120             if (tunnel_mem == L3_TUNNEL_QUADm) {
    121                /* If this is quad entry then divide the index by 2. */
    122                temp_idx = i/2;
    123                /* Move one index further as two indexes will be used here.*/
    124                i++;
    125                SOC_IF_ERROR_RETURN(
    126                    soc_mem_read(unit, tunnel_mem, MEM_BLOCK_ANY,
    127                        temp_idx, &entry_ptr));
    128             }
    129 
    130             /* Get the index of ALLOWED_PORT_BITMAP_PROFILE table. */
    131             idx = soc_mem_field32_get(unit, tunnel_mem, entry_ptr,
    132                         (tunnel_mem == L3_TUNNEL_DOUBLEm) ?
    133                         IPV4__ALLOWED_PORT_BITMAP_PROFILE_PTRf:
    134                         IPV6__ALLOWED_PORT_BITMAP_PROFILE_PTRf);
    135 
    136             SOC_PROFILE_MEM_REFERENCE(unit, _bcm_tnl_port_bitmap_profile[unit], idx, 1);
    137             SOC_PROFILE_MEM_ENTRIES_PER_SET(unit, _bcm_tnl_port_bitmap_profile[unit], idx, 1);
    138 
    139        }
    140     } else {
    141         sal_memset(prof_entry, 0, ent_sz);
    142         entries[0] = prof_entry;
    143         SOC_IF_ERROR_RETURN
    144             (soc_profile_mem_add(unit, _bcm_tnl_port_bitmap_profile[unit],
    145                                  (void *) &entries, 1, &temp_index));
    146 
    147         SOC_PROFILE_MEM_REFERENCE(unit, _bcm_tnl_port_bitmap_profile[unit],
    148             0,
    149             soc_mem_index_count(unit, tunnel_mem));
    150     }
    151 
    152     return BCM_E_NONE;
    153 }
    154 
    155 
    156 /*
    157  * Function:
    158  *      _bcm_th3_l3_tnl_term_entry_init
    159  * Purpose:
    160  *      Initialize soc tunnel terminator entry key portion.
    161  * Parameters:
    162  *      unit     - (IN)  BCM device number.
    163  *      tnl_info - (IN)  BCM buffer with tunnel info.
    164  *      entry    - (OUT) SOC buffer with key filled in.
    165  * Returns:
    166  *      BCM_E_XXX
    167  */
    168 int
    169 _bcm_th3_l3_tnl_term_entry_init(int unit, bcm_tunnel_terminator_t *tnl_info,
    170                                 soc_tunnel_term_t *entry)
    171 {
    172     uint32    *entry_ptr;         /* Filled entry pointer.      */
    173     _bcm_tnl_term_type_t tnl_type;/* Tunnel type.               */
    174     soc_mem_t mem = L3_TUNNEL_DOUBLEm;
    175     uint32              ip6_field[4];
    176     uint8 *ip6 = NULL;
    177     soc_field_t protocol_f = IPV4__PROTOCOLf;
    178     soc_field_t Bfd_enable_f = IPV4__BFD_ENABLEf;
    179 
    180     /* Input parameters check. */
    181     if ((NULL == tnl_info) || (NULL == entry)) {
    182         return (BCM_E_PARAM);
    183     }
    184 
    185     /* Get tunnel type & sub_type. */
    186     BCM_IF_ERROR_RETURN
    187         (_bcm_xgs3_l3_set_tnl_term_type(unit, tnl_info, &tnl_type));
    188 
    189     if (tnl_type.tnl_outer_hdr_ipv6 == 1) {
    190        mem = L3_TUNNEL_QUADm;
    191     } else {
    192        mem = L3_TUNNEL_DOUBLEm;
    193     }
    194 
    195     /* Reset destination structure. */
    196     sal_memset(entry, 0, sizeof(soc_tunnel_term_t));
    197 
    198     /* Set Destination/Source pair. */
    199     entry_ptr = (uint32 *)&entry->entry_arr[0];
    200     if (tnl_type.tnl_outer_hdr_ipv6 == 1) {
    201         protocol_f = IPV6__PROTOCOLf;
    202         Bfd_enable_f = IPV6__BFD_ENABLEf;
    203         ip6 = tnl_info->sip6;
    204 
    205         ip6_field[2] = (((ip6[4] & 0x3) << 24) | (ip6[5] << 16) |
    206                         (ip6[6] << 8)  | (ip6[7] << 0));
    207         ip6_field[1] = ((ip6[8] << 24) | (ip6[9] << 16) |
    208                         (ip6[10] << 8) | (ip6[11] << 0));
    209         ip6_field[0] = ((ip6[12] << 24)| (ip6[13] << 16) |
    210                         (ip6[14] << 8) | (ip6[15] << 0));
    211 
    212         /* SIP [0-89] */
    213         soc_mem_field_set(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__SIP_LWR_90f, ip6_field);
    214         /* SIP [90-127] */
    215         ip6_field[1] = (ip6[0] >> 2);
    216         ip6_field[0] = ((ip6[1] << 24)| (ip6[2] << 16) |
    217                         (ip6[3] << 8) | (ip6[4] & 0xfc));
    218         ip6_field[0] = ((ip6[0] & 3) << 30) | (ip6_field[0] >> 2);
    219         soc_mem_field_set(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__SIP_UPR_38f, ip6_field);
    220         ip6 = tnl_info->dip6;
    221 
    222         ip6_field[2] = (((ip6[4] & 0x3) << 24) | (ip6[5] << 16) |
    223                         (ip6[6] << 8)  | (ip6[7] << 0));
    224         ip6_field[1] = ((ip6[8] << 24) | (ip6[9] << 16) |
    225                         (ip6[10] << 8) | (ip6[11] << 0));
    226         ip6_field[0] = ((ip6[12] << 24)| (ip6[13] << 16) |
    227                         (ip6[14] << 8) | (ip6[15] << 0));
    228         /* DIP [0-89] */
    229         soc_mem_field_set(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__DIP_LWR_90f, ip6_field);
    230         /* DIP [90-127] */
    231         ip6_field[1] = (ip6[0] >> 2);
    232         ip6_field[0] = ((ip6[1] << 24)| (ip6[2] << 16) |
    233                         (ip6[3] << 8) | (ip6[4] & 0xfc));
    234         ip6_field[0] = ((ip6[0] & 3) << 30) | (ip6_field[0] >> 2);
    235         soc_mem_field_set(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__DIP_UPR_38f, ip6_field);
    236 
    237         soc_mem_field32_set(unit, mem, entry_ptr, IPV6__SUB_TUNNEL_TYPEf,
    238                                    tnl_type.tnl_sub_type);
    239 
    240         /* Set tunnel type. */
    241         soc_mem_field32_set(unit, mem, entry_ptr, IPV6__TUNNEL_TYPEf,
    242                                    tnl_type.tnl_auto);
    243     }  else if (tnl_type.tnl_outer_hdr_ipv6 == 0) {
    244 
    245         /* Set destination ip. */
    246         soc_mem_field32_set(unit, mem, entry_ptr, IPV4__DIPf, tnl_info->dip);
    247 
    248         /* Set source ip. */
    249         soc_mem_field32_set(unit, mem, entry_ptr, IPV4__SIPf, tnl_info->sip);
    250 
    251         /* Set tunnel subtype. */
    252         soc_mem_field32_set(unit, mem, entry_ptr, IPV4__SUB_TUNNEL_TYPEf,
    253                                    tnl_type.tnl_sub_type);
    254 
    255         /* Set tunnel type. */
    256         soc_mem_field32_set(unit, mem, entry_ptr, IPV4__TUNNEL_TYPEf,
    257                                    tnl_type.tnl_auto);
    258     }
    259 
    260 
    261     /* Set valid bit. */
    262     soc_mem_field32_set(unit, mem, entry_ptr, BASE_VALID_0f, 1);
    263     soc_mem_field32_set(unit, mem, entry_ptr, BASE_VALID_1f, 2);
    264 
    265     if (tnl_type.tnl_outer_hdr_ipv6 == 1) {
    266         soc_mem_field32_set(unit, mem, entry_ptr, BASE_VALID_2f, 2);
    267         soc_mem_field32_set(unit, mem, entry_ptr, BASE_VALID_3f, 2);
    268     }
    269 
    270 
    271     /* Set entry mode. */
    272 
    273     if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) {
    274         soc_mem_field32_set(unit, mem, entry_ptr, KEY_TYPEf,
    275                 tnl_type.tnl_outer_hdr_ipv6 + 1);
    276     }
    277 
    278     /* Set the PROTOCOL field */
    279     if ((tnl_info->type == bcmTunnelTypeIpAnyIn4) ||
    280         (tnl_info->type == bcmTunnelTypeIpAnyIn6))
    281     {
    282       /* Set PROTOCOL and PROTOCOL_MASK field to zero for IpAnyInx tunnel type*/
    283        soc_mem_field32_set(unit, mem, entry_ptr, protocol_f, 0x0);
    284     } else {
    285         soc_mem_field32_set(unit, mem, entry_ptr, protocol_f,
    286                                    tnl_type.tnl_protocol);
    287     }
    288 
    289     if (SOC_MEM_FIELD_VALID(unit, mem, Bfd_enable_f)) {
    290         soc_mem_field32_set(unit, mem, entry_ptr, Bfd_enable_f, 0);
    291     }
    292 
    293     /* AMT tunnels not supported */
    294 
    295     /* Set GRE payload */
    296     if (tnl_type.tnl_gre) {
    297         if (tnl_type.tnl_outer_hdr_ipv6 == 1) {
    298             /* GRE IPv6 payload is allowed. */
    299             soc_mem_field32_set(unit, mem, entry_ptr, IPV6__GRE_PAYLOAD_IPV6f,
    300                                        tnl_type.tnl_gre_v6_payload);
    301 
    302             /* GRE IPv6 payload is allowed. */
    303             soc_mem_field32_set(unit, mem, entry_ptr, IPV6__GRE_PAYLOAD_IPV4f,
    304                                        tnl_type.tnl_gre_v4_payload);
    305             /* Save vlan id for ipmc lookup.*/
    306             if((tnl_info->vlan) && SOC_MEM_FIELD_VALID(unit, mem, IPV6__L3_IIFf)) {
    307                 soc_mem_field32_set(unit, mem, entry_ptr, IPV6__L3_IIFf, tnl_info->vlan);
    308             }
    309 
    310         } else {
    311 
    312             /* GRE IPv6 payload is allowed. */
    313             soc_mem_field32_set(unit, mem, entry_ptr, IPV4__GRE_PAYLOAD_IPV6f,
    314                                        tnl_type.tnl_gre_v6_payload);
    315 
    316             /* GRE IPv6 payload is allowed. */
    317             soc_mem_field32_set(unit, mem, entry_ptr, IPV4__GRE_PAYLOAD_IPV4f,
    318                                        tnl_type.tnl_gre_v4_payload);
    319 
    320             /* Save vlan id for ipmc lookup.*/
    321             if((tnl_info->vlan) && SOC_MEM_FIELD_VALID(unit, mem, IPV4__L3_IIFf)) {
    322                 soc_mem_field32_set(unit, mem, entry_ptr, IPV4__L3_IIFf, tnl_info->vlan);
    323             }
    324         }
    325     }
    326     return (BCM_E_NONE);
    327 }
    328 
    329 /*
    330  * Function:
    331  *      _bcm_th3_l3_tnl_term_add
    332  * Purpose:
    333  *      Add tunnel termination entry to the hw.
    334  * Parameters:
    335  *      unit     - (IN)SOC unit number.
    336  *      tnl_info - (IN)Tunnel terminator parameters.
    337  * Returns:
    338  *      BCM_E_XXX
    339  */
    340 int
    341 _bcm_th3_l3_tnl_term_add(int unit, uint32 *entry_ptr, bcm_tunnel_terminator_t *tnl_info)
    342 {
    343     bcm_module_t mod_in, mod_out, my_mod;
    344     bcm_port_t port_in, port_out;
    345     int wlan;
    346     int rv;
    347 
    348     /* Program remote port */
    349     if ((tnl_info->type == bcmTunnelTypeWlanWtpToAc) ||
    350         (tnl_info->type == bcmTunnelTypeWlanAcToAc) ||
    351         (tnl_info->type == bcmTunnelTypeWlanWtpToAc6) ||
    352         (tnl_info->type == bcmTunnelTypeWlanAcToAc6)) {
    353         wlan = 1;
    354     } else {
    355         wlan = 0;
    356     }
    357 
    358     if (wlan) {
    359         if (tnl_info->flags & BCM_TUNNEL_TERM_WLAN_REMOTE_TERMINATE) {
    360             if (!BCM_GPORT_IS_MODPORT(tnl_info->remote_port)) {
    361                 return BCM_E_PARAM;
    362             }
    363             mod_in = BCM_GPORT_MODPORT_MODID_GET(tnl_info->remote_port);
    364             port_in = BCM_GPORT_MODPORT_PORT_GET(tnl_info->remote_port);
    365             BCM_IF_ERROR_RETURN
    366                 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, mod_in,
    367                                         port_in, &mod_out, &port_out));
    368             if (!SOC_MODID_ADDRESSABLE(unit, mod_out)) {
    369                 return (BCM_E_BADID);
    370             }
    371             if (!SOC_PORT_ADDRESSABLE(unit, port_out)) {
    372                 return (BCM_E_PORT);
    373             }
    374             soc_L3_TUNNELm_field32_set(unit, entry_ptr, REMOTE_TERM_GPPf,
    375                                        (mod_out << 6) | port_out);
    376         } else {
    377             /* Send to the local loopback port */
    378             rv = bcm_esw_stk_my_modid_get(unit, &my_mod);
    379             BCM_IF_ERROR_RETURN(rv);
    380             port_in = 54;
    381             mod_in = my_mod;
    382             rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, mod_in,
    383                                         port_in, &mod_out, &port_out);
    384             BCM_IF_ERROR_RETURN(rv);
    385 
    386             soc_L3_TUNNELm_field32_set(unit, entry_ptr, REMOTE_TERM_GPPf,
    387                                        (mod_out << 6) | port_out);
    388         }
    389 #if 0
    390         /* Program tunnel id */
    391         if (tnl_info->flags & BCM_TUNNEL_TERM_TUNNEL_WITH_ID) {
    392             if (!BCM_GPORT_IS_TUNNEL(tnl_info->tunnel_id)) {
    393                 return BCM_E_PARAM;
    394             }
    395             if (SOC_MEM_FIELD_VALID(unit, L3_TUNNELm, TUNNEL_IDf)) {
    396                 tunnel = BCM_GPORT_TUNNEL_ID_GET(tnl_info->tunnel_id);
    397                 soc_L3_TUNNELm_field32_set(unit, entry_ptr, TUNNEL_IDf,
    398                                            tunnel);
    399             }
    400         }
    401 #endif
    402 
    403     }
    404     return (BCM_E_NONE);
    405 }
    406 
    407 /*
    408  * Function:
    409  *      _bcm_tr2_l3_tnl_term_entry_parse
    410  * Purpose:
    411  *      Parse tunnel terminator entry portion.
    412  * Parameters:
    413  *      unit     - (IN)  BCM device number.
    414  *      entry    - (IN)  SOC buffer with tunne information.
    415  *      tnl_info - (OUT) BCM buffer with tunnel info.
    416  * Returns:
    417  *      BCM_E_XXX
    418  */
    419 int
    420 _bcm_th3_l3_tnl_term_entry_parse(int unit, soc_tunnel_term_t *entry,
    421                                   bcm_tunnel_terminator_t *tnl_info)
    422 {
    423     uint32              ip6_field[4];
    424     _bcm_tnl_term_type_t tnl_type;     /* Tunnel type information.   */
    425     uint32 *entry_ptr;                 /* Filled entry pointer.      */
    426     uint8 *ip6 = NULL;
    427     soc_mem_t mem = L3_TUNNEL_DOUBLEm;
    428     allowed_port_bitmap_profile_entry_t allowed_ports_profile;
    429     void *profile_entries[1];
    430     int prof_id;
    431 
    432     /* Input parameters check. */
    433     if ((NULL == tnl_info) || (NULL == entry)) {
    434         return (BCM_E_PARAM);
    435     }
    436 
    437     /* Reset destination structure. */
    438     bcm_tunnel_terminator_t_init(tnl_info);
    439     sal_memset(&tnl_type, 0, sizeof(_bcm_tnl_term_type_t));
    440 
    441     entry_ptr = (uint32 *)&entry->entry_arr[0];
    442 
    443     /* Get valid bit. */
    444     if (!soc_mem_field32_get(unit, mem, entry_ptr, BASE_VALID_0f)) {
    445         return (BCM_E_NOT_FOUND);
    446     }
    447 
    448     if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) {
    449         tnl_type.tnl_outer_hdr_ipv6 =
    450             soc_mem_field32_get(unit, mem, entry_ptr, KEY_TYPEf) - 1;
    451 
    452     }
    453 
    454     /* Get Destination/Source pair. */
    455     if (tnl_type.tnl_outer_hdr_ipv6 == 1) {
    456         mem = L3_TUNNEL_QUADm;
    457         ip6 = tnl_info->sip6;
    458         /* SIP [0-89] */
    459         soc_mem_field_get(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__SIP_LWR_90f, ip6_field);
    460 
    461         ip6[4] = (ip6_field[2]  >> 24) & 0x3;
    462         ip6[5] = (ip6_field[2]  >> 16) & 0xff;
    463         ip6[6] = (ip6_field[2]  >> 8) & 0xff;
    464         ip6[7] = (ip6_field[2] & 0xff);
    465 
    466         ip6[8] = (ip6_field[1] >> 24) & 0xff;
    467         ip6[9] = (ip6_field[1]  >> 16) & 0xff;
    468         ip6[10] = (ip6_field[1]  >> 8) & 0xff;
    469         ip6[11] = (ip6_field[1] & 0xff);
    470 
    471         ip6[12] = (ip6_field[0] >> 24) & 0xff;
    472         ip6[13] = (ip6_field[0]  >> 16) & 0xff;
    473         ip6[14] = (ip6_field[0]  >> 8) & 0xff;
    474         ip6[15] = (ip6_field[0] & 0xff);
    475 
    476         /* SIP [90-127] */
    477         soc_mem_field_get(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__SIP_UPR_38f, ip6_field);
    478         ip6[0] = (ip6_field[0] >> 30);
    479         ip6_field[1] <<= 2;
    480         ip6_field[0] <<= 2;
    481         ip6[0] |= (ip6_field[1] & 0xff);
    482         ip6[1] = (ip6_field[0]  >> 24) & 0xff;
    483         ip6[2] = (ip6_field[0]  >> 16) & 0xff;
    484         ip6[3] = (ip6_field[0]  >> 8) & 0xff;
    485         ip6[4] |= (ip6_field[0] & 0xff);
    486 
    487         ip6 = tnl_info->dip6;
    488         /* DIP [0-89] */
    489         soc_mem_field_get(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__DIP_LWR_90f, ip6_field);
    490         ip6[4] = (ip6_field[2]  >> 24) & 0x3;
    491         ip6[5] = (ip6_field[2]  >> 16) & 0xff;
    492         ip6[6] = (ip6_field[2]  >> 8) & 0xff;
    493         ip6[7] = (ip6_field[2] & 0xff);
    494 
    495         ip6[8] = (ip6_field[1] >> 24) & 0xff;
    496         ip6[9] = (ip6_field[1]  >> 16) & 0xff;
    497         ip6[10] = (ip6_field[1]  >> 8) & 0xff;
    498         ip6[11] = (ip6_field[1] & 0xff);
    499 
    500         ip6[12] = (ip6_field[0] >> 24) & 0xff;
    501         ip6[13] = (ip6_field[0]  >> 16) & 0xff;
    502         ip6[14] = (ip6_field[0]  >> 8) & 0xff;
    503         ip6[15] = (ip6_field[0] & 0xff);
    504 
    505         /* DIP [90-127] */
    506         soc_mem_field_get(unit, mem, (uint32 *)&entry->entry_arr[0], IPV6__DIP_UPR_38f, ip6_field);
    507         ip6[0] = (ip6_field[0] >> 30);
    508         ip6_field[1] <<= 2;
    509         ip6_field[0] <<= 2;
    510         ip6[0] |= (ip6_field[1] & 0xff);
    511         ip6[1] = (ip6_field[0]  >> 24) & 0xff;
    512         ip6[2] = (ip6_field[0]  >> 16) & 0xff;
    513         ip6[3] = (ip6_field[0]  >> 8) & 0xff;
    514         ip6[4] |= (ip6_field[0] & 0xff);
    515 
    516     }  else if (tnl_type.tnl_outer_hdr_ipv6 == 0) {
    517         /* Get destination ip. */
    518         tnl_info->dip = soc_mem_field32_get(unit, mem, entry_ptr, IPV4__DIPf);
    519 
    520         /* Get source ip. */
    521         tnl_info->sip = soc_mem_field32_get(unit, mem, entry_ptr, IPV4__SIPf);
    522 
    523         /* Destination subnet mask. */
    524         tnl_info->dip_mask = BCM_XGS3_L3_IP4_FULL_MASK;
    525 
    526     }
    527 
    528     /* Get tunnel subtype. */
    529     tnl_type.tnl_sub_type =
    530         soc_mem_field32_get(unit, mem, entry_ptr, (mem == L3_TUNNEL_DOUBLEm) ? IPV4__SUB_TUNNEL_TYPEf:IPV6__SUB_TUNNEL_TYPEf);
    531 
    532     prof_id = soc_mem_field32_get(unit, mem, entry_ptr,
    533                             (mem == L3_TUNNEL_DOUBLEm) ?
    534                             IPV4__ALLOWED_PORT_BITMAP_PROFILE_PTRf:
    535                             IPV6__ALLOWED_PORT_BITMAP_PROFILE_PTRf);
    536     profile_entries[0] = &allowed_ports_profile;
    537     soc_profile_mem_get(unit, _bcm_get_tnl_port_bitmap_profile(unit), prof_id,
    538                         1, profile_entries);
    539     soc_mem_pbmp_field_get(unit, ALLOWED_PORT_BITMAP_PROFILEm,
    540                            &allowed_ports_profile,
    541                            ING_PORT_BITMAPf, &tnl_info->pbmp);
    542 
    543     /* Get UDP tunnel type. */
    544     if (soc_mem_field_valid(unit, mem, IPV4__UDP_TUNNEL_TYPEf)) {
    545         tnl_type.tnl_udp_type =
    546             soc_mem_field32_get(unit, mem, entry_ptr, IPV4__UDP_TUNNEL_TYPEf);
    547     }
    548     /* Get tunnel type. */
    549     tnl_type.tnl_auto =
    550         soc_mem_field32_get(unit, mem, entry_ptr, (mem == L3_TUNNEL_DOUBLEm) ? IPV4__TUNNEL_TYPEf: IPV6__TUNNEL_TYPEf);
    551 
    552     /* Copy DSCP from outer header flag. */
    553     if (soc_mem_field32_get(unit, mem, entry_ptr, (mem == L3_TUNNEL_DOUBLEm) ? IPV4__USE_OUTER_HDR_DSCPf: IPV6__USE_OUTER_HDR_DSCPf)) {
    554         tnl_info->flags |= BCM_TUNNEL_TERM_USE_OUTER_DSCP;
    555     }
    556     /* Copy TTL from outer header flag. */
    557     if (soc_mem_field32_get(unit, mem, entry_ptr, (mem == L3_TUNNEL_DOUBLEm) ? IPV4__USE_OUTER_HDR_TTLf: IPV6__USE_OUTER_HDR_TTLf)) {
    558         tnl_info->flags |= BCM_TUNNEL_TERM_USE_OUTER_TTL;
    559     }
    560     /* Keep inner header DSCP flag. */
    561     if (soc_mem_field32_get(unit, mem, entry_ptr,
    562                                    (mem == L3_TUNNEL_DOUBLEm) ? IPV4__DONOT_CHANGE_INNER_HDR_DSCPf:IPV6__DONOT_CHANGE_INNER_HDR_DSCPf)) {
    563         tnl_info->flags |= BCM_TUNNEL_TERM_KEEP_INNER_DSCP;
    564     }
    565 
    566     /* Tunnel or IPMC lookup vlan id */
    567     tnl_info->vlan = soc_mem_field32_get(unit, mem, entry_ptr, (mem == L3_TUNNEL_DOUBLEm) ? IPV4__IINTFf:IPV6__IINTFf);
    568 
    569     /*  Get trust dscp per tunnel */
    570     if (soc_mem_field32_get(unit, mem, entry_ptr, (mem == L3_TUNNEL_DOUBLEm) ? IPV4__USE_OUTER_HDR_DSCPf:IPV6__USE_OUTER_HDR_DSCPf)) {
    571         tnl_info->flags |= BCM_TUNNEL_TERM_DSCP_TRUST;
    572     }
    573 
    574     /* Get Tunnel class id for VFP match */
    575         tnl_info->tunnel_class = soc_mem_field32_get(unit, mem, entry_ptr,
    576                                (mem == L3_TUNNEL_DOUBLEm) ? IPV4__TUNNEL_CLASS_IDf:IPV6__TUNNEL_CLASS_IDf);
    577 
    578     /* Get the protocol field and make some decisions */
    579     tnl_type.tnl_protocol = soc_mem_field32_get(unit, mem, entry_ptr,
    580                                (mem == L3_TUNNEL_DOUBLEm) ? IPV4__PROTOCOLf:IPV6__PROTOCOLf);
    581     switch (tnl_type.tnl_protocol) {
    582         case 0x2F:
    583             tnl_type.tnl_gre = 1;
    584             break;
    585         case 0x67:
    586             tnl_type.tnl_pim_sm = 1;
    587         default:
    588             break;
    589     }
    590     /* Get gre IPv4 payload allowed. */
    591     tnl_type.tnl_gre_v4_payload =
    592         soc_mem_field32_get(unit, mem, entry_ptr, (mem == L3_TUNNEL_DOUBLEm) ? IPV4__GRE_PAYLOAD_IPV4f:IPV6__GRE_PAYLOAD_IPV4f);
    593 
    594     /* Get gre IPv6 payload allowed. */
    595     tnl_type.tnl_gre_v6_payload =
    596         soc_mem_field32_get(unit, mem, entry_ptr, (mem == L3_TUNNEL_DOUBLEm) ? IPV4__GRE_PAYLOAD_IPV6f:IPV6__GRE_PAYLOAD_IPV6f);
    597 
    598     /* Get the L4 data */
    599     if (soc_mem_field_valid (unit, mem, L4_SRC_PORTf)) {
    600         tnl_info->udp_src_port = soc_mem_field32_get(unit, mem, entry_ptr,
    601                                                         (mem == L3_TUNNEL_DOUBLEm) ? IPV4__L4_SRC_PORTf:IPV6__L4_SRC_PORTf);
    602     }
    603     if (soc_mem_field_valid (unit, mem, L4_DEST_PORTf)) {
    604         tnl_info->udp_dst_port = soc_mem_field32_get(unit, mem, entry_ptr,
    605                                                         (mem == L3_TUNNEL_DOUBLEm) ? IPV4__L4_DEST_PORTf:IPV6__L4_DEST_PORTf);
    606     }
    607 
    608     /* Get tunnel type, sub_type and protocol. */
    609     BCM_IF_ERROR_RETURN
    610         (_bcm_xgs3_l3_get_tnl_term_type(unit, tnl_info, &tnl_type));
    611     /* Get IIF if l3 ingress mode is not set */
    612     if (!BCM_XGS3_L3_INGRESS_MODE_ISSET(unit) &&
    613         BCM_XGS3_L3_ING_IF_TBL_SIZE(unit) && (tnl_info->vlan > BCM_VLAN_MAX)) {
    614         _bcm_l3_ingress_intf_t iif;
    615         sal_memset(&iif, 0, sizeof(_bcm_l3_ingress_intf_t));
    616         iif.intf_id = tnl_info->vlan;
    617         BCM_IF_ERROR_RETURN(_bcm_tr_l3_ingress_interface_get(unit, NULL, &iif));
    618 
    619         tnl_info->vrf = iif.vrf;
    620         tnl_info->if_class = iif.if_class;
    621         tnl_info->qos_map_id = iif.qos_map_id;
    622         if (SOC_IS_TOMAHAWKX(unit) && soc_feature(unit, soc_feature_ecn_wred)) {
    623             if (bcmi_xgs5_ecn_map_used_get(unit, iif.tunnel_term_ecn_map_id,
    624                                            _bcmEcnmapTypeTunnelTerm)) {
    625                 tnl_info->tunnel_term_ecn_map_id = iif.tunnel_term_ecn_map_id |
    626                     _BCM_XGS5_ECN_MAP_TYPE_TUNNEL_TERM;
    627                 tnl_info->flags |= BCM_TUNNEL_TERM_ECN_MAP;
    628             }
    629         }
    630     }
    631 
    632     return (BCM_E_NONE);
    633 }
    634 
    635 #endif