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

l3.c (88555B)


      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:     Triumph L3 function implementations
      9  */
     10 
     11 
     12 #include <soc/defs.h>
     13 
     14 #include <assert.h>
     15 
     16 #include <sal/core/libc.h>
     17 #if defined(BCM_TRIUMPH_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 
     29 #include <bcm/l3.h>
     30 #include <bcm/tunnel.h>
     31 #include <bcm/debug.h>
     32 #include <bcm/error.h>
     33 #include <bcm/stack.h>
     34 
     35 #include <bcm_int/esw/mbcm.h>
     36 #include <bcm_int/esw/firebolt.h>
     37 #include <bcm_int/esw/trx.h>
     38 #include <bcm_int/esw/triumph.h>
     39 #include <bcm_int/esw/l3.h>
     40 #include <bcm_int/esw/xgs3.h>
     41 #include <bcm_int/esw_dispatch.h>
     42 #if defined(BCM_TRIUMPH2_SUPPORT)
     43 #include <bcm_int/esw/triumph2.h>
     44 #endif /* BCM_TRIUMPH2_SUPPORT */
     45 #if defined(BCM_KATANA_SUPPORT)
     46 #include <bcm_int/esw/katana.h>
     47 #endif /* BCM_KATANA_SUPPORT */
     48 #if defined(BCM_TRIDENT2_SUPPORT)
     49 #include <bcm_int/esw/trident2.h>
     50 #endif /* BCM_TRIDENT2_SUPPORT */
     51 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
     52 #include <bcm_int/esw/flex_ctr.h>
     53 #endif
     54 #ifdef BCM_TRIDENT2_SUPPORT
     55 #define _BCM_TD2_IP_OPTIONS_PROFILE_MASK  0x3ff   /* 10 bits width */
     56 #define _BCM_TD2_IP_OPTIONS_BITS_WIDTH    8  /* IP options size = 8 */
     57 #endif /* BCM_TRIDENT2_SUPPORT */
     58 /*
     59  * Function:
     60  *      _bcm_tr_defip_init
     61  * Purpose:
     62  *      Initialize L3 DEFIP table for triumph devices.
     63  * Parameters:
     64  *      unit    - (IN)  SOC unit number.
     65  * Returns:
     66  *      BCM_E_XXX
     67  */
     68 int
     69 _bcm_tr_defip_init(int unit)
     70 {
     71     soc_mem_t mem_v4;      /* IPv4 Route table memory.             */
     72     soc_mem_t mem_v6;      /* IPv6 Route table memory.             */
     73     soc_mem_t mem_v6_128;  /* IPv6 full prefix route table memory. */
     74     int index_min, index_max;
     75 #if defined(BCM_KATANA_SUPPORT)
     76     int ipv6_lpm_128b_enable;
     77 #endif
     78 
     79     /* Get memory for IPv4 entries. */
     80     BCM_IF_ERROR_RETURN(_bcm_tr_l3_defip_mem_get(unit, 0, 0, &mem_v4));
     81 
     82     /* Initialize IPv4 entries lookup engine. */
     83     if (L3_DEFIPm == mem_v4) {
     84         BCM_IF_ERROR_RETURN(soc_fb_lpm_init(unit));
     85     } else {
     86         BCM_IF_ERROR_RETURN(_bcm_tr_ext_lpm_init(unit, mem_v4));
     87     }
     88 
     89     /* Get memory for IPv6 entries. */
     90     BCM_IF_ERROR_RETURN
     91         (_bcm_tr_l3_defip_mem_get(unit, BCM_L3_IP6, 0, &mem_v6));
     92 
     93     /* Initialize IPv6 entries lookup engine. */
     94     if (L3_DEFIPm == mem_v6) {
     95         if (mem_v4 != mem_v6) {
     96             BCM_IF_ERROR_RETURN(soc_fb_lpm_init(unit));
     97         }
     98     } else {
     99         BCM_IF_ERROR_RETURN(_bcm_tr_ext_lpm_init(unit, mem_v6));
    100     }
    101 
    102     /* Get memory for IPv6 entries with prefix length > 64. */
    103     BCM_IF_ERROR_RETURN
    104         (_bcm_tr_l3_defip_mem_get(unit, BCM_L3_IP6,
    105                                   BCM_XGS3_L3_IPV6_PREFIX_LEN,
    106                                   &mem_v6_128));
    107 
    108     /* Initialize IPv6 entries lookup engine. */
    109     if (mem_v6 != mem_v6_128) {
    110         if (SOC_IS_TD2_TT2(unit)) {  
    111             return BCM_E_NONE;
    112         }
    113 #if defined(BCM_KATANA_SUPPORT)
    114         ipv6_lpm_128b_enable =
    115             soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 0);
    116         if (SOC_IS_KATANA(unit) && (ipv6_lpm_128b_enable)) {
    117             /* Initialize pair memory for IPv6 entries with prefix length > 64. */
    118             BCM_IF_ERROR_RETURN(_bcm_kt_defip_pair128_init(unit));
    119             BCM_IF_ERROR_RETURN(_bcm_trx_defip_128_init(unit));
    120         } else
    121 #endif
    122         {
    123             BCM_IF_ERROR_RETURN(_bcm_trx_defip_128_init(unit));
    124         }
    125     }
    126 
    127     /* Update defip size in l3 book keeping if ESM present */
    128     if (soc_feature(unit, soc_feature_esm_support) && (L3_DEFIPm != mem_v4)) {
    129         index_min = soc_mem_index_min(unit, mem_v4);
    130         index_max = soc_mem_index_max(unit, mem_v4);
    131         BCM_XGS3_L3_DEFIP_TBL_SIZE(unit) = index_max - index_min + 1;
    132     }
    133     return (BCM_E_NONE);
    134 }
    135 
    136 
    137 /*
    138  * Function:
    139  *      _bcm_tr_defip_deinit
    140  * Purpose:
    141  *      De-initialize L3 DEFIP table for triumph devices.
    142  * Parameters:
    143  *      unit    - (IN)  SOC unit number.
    144  * Returns:
    145  *      BCM_E_XXX
    146  */
    147 int
    148 _bcm_tr_defip_deinit(int unit)
    149 {
    150     soc_mem_t mem_v4;      /* IPv4 Route table memory.             */
    151     soc_mem_t mem_v6;      /* IPv6 Route table memory.             */
    152     soc_mem_t mem_v6_128;  /* IPv6 full prefix route table memory. */
    153 #if defined(BCM_KATANA_SUPPORT)
    154     int ipv6_lpm_128b_enable;
    155 #endif
    156 
    157     /* Get memory for IPv4 entries. */
    158     BCM_IF_ERROR_RETURN(_bcm_tr_l3_defip_mem_get(unit, 0, 0, &mem_v4));
    159 
    160     /* Initialize IPv4 entries lookup engine. */
    161     if (L3_DEFIPm == mem_v4) {
    162         BCM_IF_ERROR_RETURN(soc_fb_lpm_deinit(unit));
    163     } else {
    164         BCM_IF_ERROR_RETURN(_bcm_tr_ext_lpm_deinit(unit, mem_v4));
    165     }
    166 
    167     /* Get memory for IPv6 entries. */
    168     BCM_IF_ERROR_RETURN
    169         (_bcm_tr_l3_defip_mem_get(unit, BCM_L3_IP6, 0, &mem_v6));
    170 
    171     /* Initialize IPv6 entries lookup engine. */
    172     if ((L3_DEFIPm == mem_v6) && (mem_v4 != mem_v6)) {
    173         BCM_IF_ERROR_RETURN(soc_fb_lpm_deinit(unit));
    174     } else {
    175         BCM_IF_ERROR_RETURN(_bcm_tr_ext_lpm_deinit(unit, mem_v6));
    176     }
    177 
    178     /* Get memory for IPv6 entries with prefix length > 64. */
    179     BCM_IF_ERROR_RETURN
    180         (_bcm_tr_l3_defip_mem_get(unit, BCM_L3_IP6,
    181                                   BCM_XGS3_L3_IPV6_PREFIX_LEN,
    182                                   &mem_v6_128));
    183 
    184     /* Initialize IPv6 entries lookup engine. */
    185     if (mem_v6 != mem_v6_128) {
    186 #if defined(BCM_KATANA_SUPPORT)
    187         ipv6_lpm_128b_enable =
    188             soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 0);
    189         if (SOC_IS_KATANA(unit) && (ipv6_lpm_128b_enable)) {
    190             BCM_IF_ERROR_RETURN(_bcm_kt_defip_pair128_deinit(unit));
    191             BCM_IF_ERROR_RETURN(_bcm_trx_defip_128_deinit(unit));
    192         } else
    193 #endif
    194         {
    195             BCM_IF_ERROR_RETURN(_bcm_trx_defip_128_deinit(unit));
    196         }
    197     }
    198     return (BCM_E_NONE);
    199 }
    200 
    201 /*
    202  * Function:
    203  *      _bcm_tr_l3_ingress_interface_get
    204  * Purpose:
    205  *      Get ingress interface config.
    206  * Parameters:
    207  *      unit     - (IN) BCM unit number.
    208  *      hw_entry - (IN) Entry data of the specified index.
    209  *      iif      - (IN) Interface configuration.
    210  * Returns:
    211  *      BCM_E_XXX.
    212  */
    213 int
    214 _bcm_tr_l3_ingress_interface_get(int unit, 
    215                                  iif_entry_t *hw_entry,
    216                                 _bcm_l3_ingress_intf_t *iif)
    217 {
    218 
    219 #ifdef BCM_TRIDENT2_SUPPORT
    220     uint32 index;
    221     void *entries[1];
    222     iif_profile_entry_t l3_iif_profile;
    223     int                 hw_idx;
    224 #endif
    225     iif_entry_t entry;       /* HW entry buffer.        */
    226     int intf_id;             /* Interface id.           */
    227     int rv = BCM_E_NONE;     /* Operation return status.*/
    228     int hw_map_idx=0;
    229     int no_trust_idx=0;
    230     int bit_num = 0;
    231     int vrf_valid = 1;
    232 #ifdef BCM_TOMAHAWK3_SUPPORT
    233     uint8 int_flag = 0;
    234 #endif
    235     
    236     /* Input parameters sanity check. */
    237     if (NULL == iif) {
    238         return (BCM_E_PARAM);
    239     }
    240     if ((iif->intf_id > soc_mem_index_max(unit, L3_IIFm)) || 
    241         (iif->intf_id < soc_mem_index_min(unit, L3_IIFm))) {
    242         return (BCM_E_PARAM);
    243     }
    244 
    245     intf_id = iif->intf_id;
    246     sal_memset(iif, 0, sizeof(_bcm_l3_ingress_intf_t));
    247     sal_memcpy(&entry,  soc_mem_entry_null(unit, L3_IIFm),
    248                sizeof(iif_entry_t));
    249 
    250     /* if H/W Entry pointer is valid, do not read
    251      * This is done to speed up time by avoiding PIO reads for
    252      * individual entries */
    253     if (NULL != hw_entry) {
    254         sal_memcpy(&entry, hw_entry, sizeof(iif_entry_t));
    255     } else {
    256 
    257         /* Read interface config from hw. */
    258         rv = soc_mem_read(unit, L3_IIFm, MEM_BLOCK_ANY, intf_id, (uint32 *)&entry);
    259         BCM_IF_ERROR_RETURN(rv);
    260     }
    261 
    262     /* Get class id value. */
    263     if (soc_mem_field_valid(unit, L3_IIFm, CLASS_IDf)) {
    264         iif->if_class = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry, CLASS_IDf);
    265     }
    266 
    267     /* Get vrf id value. */
    268     if (soc_mem_field_valid(unit, L3_IIFm, VRFf)) {
    269         iif->vrf = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry, VRFf);
    270     }
    271 
    272     if (soc_mem_field_valid(unit, L3_IIFm, VRF_VALIDf)) {
    273         vrf_valid = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry, VRF_VALIDf);
    274     }
    275 
    276     if (vrf_valid == 0) {
    277         iif->vrf    = BCM_L3_VRF_INVALID;
    278     }
    279 
    280     /* Get vrf id value. */
    281     if (soc_mem_field_valid(unit, L3_IIFm, ALLOW_GLOBAL_ROUTEf)) {
    282         if (1 == soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry,
    283                                      ALLOW_GLOBAL_ROUTEf)) {
    284             iif->flags |= BCM_L3_INGRESS_GLOBAL_ROUTE;
    285         }
    286     }
    287 
    288 #ifdef BCM_TOMAHAWK3_SUPPORT
    289     if (soc_feature(unit, soc_feature_inband_network_telemetry)) {
    290         int_flag = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry,
    291                                          INT_ENABLEf);
    292         if (int_flag) {
    293             iif->flags |= BCM_L3_INGRESS_INT;
    294         }
    295     }
    296 #endif
    297 
    298 
    299 #ifdef BCM_TRIDENT2_SUPPORT
    300     if (SOC_IS_TD2_TT2(unit)) { /* Get l3 iif profile entry */
    301         entries[0] = &l3_iif_profile;
    302         index = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry,
    303                                     L3_IIF_PROFILE_INDEXf); 
    304         (void)_bcm_l3_iif_profile_entry_get(unit, index, 1, entries);
    305         /* Get vrf id value. */
    306         if (soc_mem_field32_get(unit, L3_IIF_PROFILEm, 
    307                                 &l3_iif_profile, ALLOW_GLOBAL_ROUTEf)) {
    308             iif->flags |= BCM_L3_INGRESS_GLOBAL_ROUTE; 
    309         }
    310 
    311         if (soc_mem_field_valid(unit, L3_IIF_PROFILEm, URPF_DEFAULTROUTECHECKf)) {
    312 
    313         if (soc_mem_field32_get(unit, L3_IIF_PROFILEm, 
    314                                 &l3_iif_profile, URPF_DEFAULTROUTECHECKf)) {
    315             iif->flags |= BCM_L3_INGRESS_URPF_DEFAULT_ROUTE_CHECK; 
    316         }
    317         }
    318 
    319         if (0 == soc_mem_field32_get(unit, L3_IIF_PROFILEm, 
    320                                      &l3_iif_profile, IPV4L3_ENABLEf)) {
    321             iif->flags |= BCM_L3_INGRESS_ROUTE_DISABLE_IP4_UCAST; 
    322         }
    323 
    324         if (0 == soc_mem_field32_get(unit, L3_IIF_PROFILEm, 
    325                                      &l3_iif_profile, IPMCV4_ENABLEf)) {
    326             iif->flags |= BCM_L3_INGRESS_ROUTE_DISABLE_IP4_MCAST; 
    327         }
    328 
    329         if (0 == soc_mem_field32_get(unit, L3_IIF_PROFILEm, 
    330                                      &l3_iif_profile, IPV6L3_ENABLEf)) {
    331             iif->flags |= BCM_L3_INGRESS_ROUTE_DISABLE_IP6_UCAST; 
    332         }
    333 
    334         if (0 == soc_mem_field32_get(unit, L3_IIF_PROFILEm, 
    335                                      &l3_iif_profile, IPMCV6_ENABLEf)) {
    336             iif->flags |= BCM_L3_INGRESS_ROUTE_DISABLE_IP6_MCAST; 
    337         }
    338 
    339         if (soc_mem_field32_get(unit, L3_IIF_PROFILEm, 
    340                                 &l3_iif_profile, UNKNOWN_IPV4_MC_TOCPUf)) {
    341             iif->flags |= BCM_L3_INGRESS_UNKNOWN_IP4_MCAST_TOCPU; 
    342         }
    343 
    344         if (soc_mem_field32_get(unit, L3_IIF_PROFILEm, 
    345                                 &l3_iif_profile, UNKNOWN_IPV6_MC_TOCPUf)) {
    346             iif->flags |= BCM_L3_INGRESS_UNKNOWN_IP6_MCAST_TOCPU; 
    347         }
    348 
    349 #ifdef BCM_TOMAHAWK_SUPPORT
    350         if (soc_mem_field_valid(unit, L3_IIF_PROFILEm, IPMC_MISS_AS_L2MCf)) {
    351             if (soc_mem_field32_get(unit, L3_IIF_PROFILEm,
    352                                     &l3_iif_profile, IPMC_MISS_AS_L2MCf)) {
    353                 iif->flags |= BCM_L3_INGRESS_UNKNOWN_IPMC_AS_L2MC;
    354             }
    355         }
    356 #endif
    357 
    358         if (soc_mem_field32_get(unit, L3_IIF_PROFILEm, 
    359                                 &l3_iif_profile, ICMP_REDIRECT_TOCPUf)) {
    360             iif->flags |= BCM_L3_INGRESS_ICMP_REDIRECT_TOCPU; 
    361         }
    362 
    363         if (soc_mem_field32_get(unit, L3_IIF_PROFILEm, 
    364                                 &l3_iif_profile, L3_OVERRIDE_IPMC_DO_VLANf)) {
    365             iif->flags |= BCM_L3_INGRESS_IPMC_DO_VLAN_DISABLE; 
    366         }
    367  
    368         /* Retrieve IP option Profile Index */
    369         if (soc_feature(unit, soc_feature_l3_ip4_options_profile)) {
    370             hw_idx = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry,
    371                                          IP_OPTION_PROFILE_INDEXf);
    372             hw_idx <<= _BCM_TD2_IP_OPTIONS_BITS_WIDTH;
    373             hw_idx &= _BCM_TD2_IP_OPTIONS_PROFILE_MASK;
    374             BCM_IF_ERROR_RETURN(
    375                 _bcm_td2_l3_ip4_options_profile_idx2id(
    376                     unit, hw_idx, &(iif->ip4_options_profile_id)));
    377         }
    378         if (soc_feature(unit, soc_feature_nat) && 
    379                         SOC_MEM_FIELD_VALID(unit, L3_IIFm, SRC_REALM_IDf)) {
    380             /* Get the nat source realm id value. */
    381             iif->nat_realm_id = soc_mem_field32_get(unit, L3_IIFm, 
    382                                                (uint32 *)&entry, SRC_REALM_IDf);
    383         }
    384     } 
    385 #endif
    386 
    387     /* Get Trust QoS Map Id Value. */
    388     if (soc_mem_field_valid(unit, L3_IIFm, TRUST_DSCP_PTRf)) {
    389         hw_map_idx = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry,
    390                                          TRUST_DSCP_PTRf);
    391     }
    392 #ifdef BCM_TRIDENT2_SUPPORT
    393     if (SOC_IS_TD2_TT2(unit)) {
    394         hw_map_idx = soc_mem_field32_get(unit, L3_IIF_PROFILEm,
    395                                          &l3_iif_profile, TRUST_DSCP_PTRf);
    396     }
    397 #endif
    398     if (BCM_VLAN_INVALID > iif->intf_id) {
    399         if (soc_mem_field_valid(unit, L3_IIFm, TRUST_DSCP_PTRf)) {
    400             bit_num = soc_mem_field_length(unit, L3_IIFm, TRUST_DSCP_PTRf);
    401             switch (bit_num) {
    402                 case _BCM_TR_L3_TRUST_DSCP_PTR_BIT_SIZE:
    403                     /* DSCP_TABLE size vary across Chariot and Enduro, but Do not trust value is identical */
    404                     no_trust_idx = 63;
    405                     break;
    406                 case _BCM_TD_L3_TRUST_DSCP_PTR_BIT_SIZE:
    407                     /* Trident and Triumph3 */
    408                     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_GREYHOUND2(unit)) {
    409                         no_trust_idx = 127;
    410                     } else {
    411                         no_trust_idx = 0;
    412                     }
    413                     break;
    414                 default:
    415                     break;
    416             }
    417         }
    418 #ifdef BCM_TRIDENT2_SUPPORT
    419         if (SOC_IS_TD2_TT2(unit)) {
    420             no_trust_idx = 127;
    421         }
    422 #endif
    423     } else {
    424         /* for iif->intf_id > 4096 condition */
    425         if (soc_mem_field_valid(unit, L3_IIFm, TRUST_DSCP_PTRf)) {
    426             bit_num = soc_mem_field_length(unit, L3_IIFm, TRUST_DSCP_PTRf);
    427             switch (bit_num) {
    428                 case _BCM_TR_L3_TRUST_DSCP_PTR_BIT_SIZE:
    429                     /* DSCP_TABLE size vary across Chariot and Enduro, but Do not trust value is identical */
    430                     no_trust_idx = 63;
    431                     break;
    432                 case _BCM_TD_L3_TRUST_DSCP_PTR_BIT_SIZE:
    433                     /* Trident and Triumph3 */
    434                     no_trust_idx = 127;
    435                     break;
    436                 default:
    437                     break;
    438             }
    439         }
    440 #ifdef BCM_TRIDENT2_SUPPORT
    441         if (SOC_IS_TD2_TT2(unit)) {
    442             no_trust_idx = ((soc_mem_index_count(unit, DSCP_TABLEm) / 64)) - 1;
    443         }
    444 #endif
    445     }
    446 
    447     if (hw_map_idx != no_trust_idx) {
    448         if (SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit)) {
    449             rv = _bcm_tr_qos_idx2id(unit, hw_map_idx, 0x3,
    450                 &iif->qos_map_id);
    451         } else {
    452 #ifdef BCM_TRIUMPH2_SUPPORT
    453             rv = _bcm_tr2_qos_idx2id(unit, hw_map_idx, 0x3,
    454                 &iif->qos_map_id);
    455 #endif /*BCM_TRIUMPH2_SUPPORT*/
    456         }
    457         if (BCM_SUCCESS(rv) && (iif->qos_map_id != 0)) {
    458             iif->flags |= BCM_L3_INGRESS_DSCP_TRUST;
    459         }
    460     } else {
    461         iif->qos_map_id = 0;
    462     }
    463 
    464 #ifdef BCM_TRIUMPH2_SUPPORT
    465     if (soc_mem_field_valid(unit, L3_IIFm, IPMC_L3_IIFf)) {
    466         iif->ipmc_intf_id =
    467             soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry, IPMC_L3_IIFf);
    468     }
    469 #endif /* BCM_TRIUMPH2_SUPPORT */
    470 
    471 #ifdef BCM_GREYHOUND2_SUPPORT
    472     if (soc_mem_field_valid(unit, L3_IIFm, ICMP_REDIRECT_TO_CPUf)) {
    473         if (soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry,
    474                                 ICMP_REDIRECT_TO_CPUf)) {
    475             iif->flags |= BCM_L3_INGRESS_ICMP_REDIRECT_TOCPU;
    476         }
    477     }
    478 #endif /* BCM_GREYHOUND2_SUPPORT */
    479 
    480 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
    481     if (soc_mem_field_valid(unit, L3_IIFm, URPF_DEFAULTROUTECHECKf)) {
    482          if (1 == soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry,
    483                                   URPF_DEFAULTROUTECHECKf)) {
    484               iif->flags |= BCM_L3_INGRESS_URPF_DEFAULT_ROUTE_CHECK;
    485          }
    486     }
    487     if (soc_mem_field_valid(unit, L3_IIFm, URPF_MODEf)) {
    488          iif->urpf_mode = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry,
    489                              URPF_MODEf); 
    490     }
    491 #endif  /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */
    492 
    493 #ifdef BCM_TRIDENT2_SUPPORT
    494     if (SOC_IS_TD2_TT2(unit)) {
    495         if (1 == soc_mem_field32_get(unit, L3_IIF_PROFILEm,
    496                                      &l3_iif_profile,
    497                                      ALLOW_GLOBAL_ROUTEf)) {
    498             iif->flags |= BCM_L3_INGRESS_GLOBAL_ROUTE;
    499         }
    500         if (soc_mem_field_valid(unit, L3_IIF_PROFILEm, URPF_DEFAULTROUTECHECKf)) {
    501         if (1 == soc_mem_field32_get(unit, L3_IIF_PROFILEm,
    502                                      &l3_iif_profile,
    503                                      URPF_DEFAULTROUTECHECKf)) {
    504             iif->flags |= BCM_L3_INGRESS_URPF_DEFAULT_ROUTE_CHECK;
    505         }
    506         iif->urpf_mode = soc_mem_field32_get(unit, L3_IIF_PROFILEm, 
    507                                      &l3_iif_profile, URPF_MODEf);
    508     }
    509     }
    510 #endif
    511 #ifdef BCM_TOMAHAWK_SUPPORT
    512     if (soc_mem_field_valid(unit, L3_IIFm, ECN_DECAP_MAPPING_PTRf)) {
    513         iif->tunnel_term_ecn_map_id = 
    514             soc_mem_field32_get(unit, L3_IIFm, &entry,
    515                                 ECN_DECAP_MAPPING_PTRf);
    516     }
    517 #endif
    518     /* Set interface id. */
    519     iif->intf_id = intf_id;
    520 
    521     return (BCM_E_NONE);
    522 }
    523 
    524 #ifdef BCM_TRIDENT2_SUPPORT
    525 /*
    526  * Function:
    527  *      _bcm_l3_iif_profile_recover
    528  * Purpose:
    529  *      Add entry into profile index table. 
    530  * Parameters:
    531  *      unit     - (IN) BCM unit number.
    532  *      iif      - (IN) Interface configuration.
    533  *      profile_index - (IN) Index into Profile table
    534  * Returns:
    535  *      BCM_E_XXX.
    536  */
    537 
    538 int
    539 _bcm_l3_iif_profile_recover(int unit, iif_profile_entry_t *l3_iif_profile,
    540                             uint8 profile_index)
    541 {
    542     uint32 index;
    543     void *entries[1];
    544     int rv = BCM_E_NONE;
    545 
    546     /* Input parameters sanity check. */
    547     if (NULL == l3_iif_profile) {
    548         return (BCM_E_PARAM);
    549     }   
    550     
    551     entries[0] = l3_iif_profile;
    552     index = profile_index;
    553 
    554     /* Create new profile entry if not existent or updating failed */
    555     rv = _bcm_l3_iif_profile_sw_state_set(unit, entries, 1, index);
    556     return rv;
    557 }
    558 
    559 /*
    560  * Function:
    561  *      _bcm_l3_iif_profile_add
    562  * Purpose:
    563  *      Add entry into profile index table. 
    564  * Parameters:
    565  *      unit     - (IN) BCM unit number.
    566  *      iif      - (IN) Interface configuration.
    567  *      profile_index - (OUT) Index into Profile table
    568  * Returns:
    569  *      BCM_E_XXX.
    570  */
    571 
    572 STATIC int
    573 _bcm_l3_iif_profile_add(int unit, _bcm_l3_ingress_intf_t *iif, 
    574                         iif_entry_t *iif_hw_entry, 
    575                         uint8 *profile_index)
    576 {
    577     uint32 index;
    578     uint8 value;                /* Enable/disable boolean. */
    579     void *entries[1];
    580     iif_entry_t iif_entry;      /* HW iif_entry buffer.        */
    581     iif_profile_entry_t l3_iif_profile;
    582     int hw_map_idx=0;
    583     int no_trust_idx=0;
    584     int rv = BCM_E_NONE;
    585 
    586     /* Input parameters sanity check. */
    587     if ((NULL == iif) || (NULL == profile_index)) {
    588         return (BCM_E_PARAM);
    589     }
    590 
    591     *profile_index = 0;
    592 
    593     if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    594         if (iif_hw_entry) {
    595             sal_memcpy(&iif_entry, iif_hw_entry, sizeof(iif_entry_t));
    596         } else {
    597             /* Read interface entry from hw. */
    598             rv = soc_mem_read(unit, L3_IIFm, MEM_BLOCK_ANY, iif->intf_id,
    599                               (uint32 *)&iif_entry);
    600         }
    601 
    602         if (SOC_SUCCESS(rv)) {
    603             /* Get profile_index from interface entry*/
    604             index = soc_mem_field32_get(unit, L3_IIFm,
    605                                         (uint32 *)&iif_entry,
    606                                         L3_IIF_PROFILE_INDEXf);
    607 
    608             if (iif->profile_flags & _BCM_L3_IIF_PROFILE_DO_NOT_UPDATE) {
    609                 *profile_index = (uint8)index;
    610                 return BCM_E_NONE;
    611             }
    612         } else {
    613             LOG_ERROR(BSL_LS_BCM_L3, 
    614               (BSL_META_U(unit,
    615               "Profile Add: soc_mem_read for L3_IIF failed for index=(%d)\n"),
    616                          iif->intf_id));
    617             return rv;
    618         }
    619 
    620         entries[0] = &l3_iif_profile;
    621         sal_memset(&l3_iif_profile, 0, sizeof(iif_profile_entry_t));
    622 
    623         /* Set Trust QoS Map Id Value. */
    624         if (iif->flags & BCM_L3_INGRESS_DSCP_TRUST) {
    625             BCM_IF_ERROR_RETURN
    626                  (_bcm_tr2_qos_id2idx(unit, iif->qos_map_id, &hw_map_idx));
    627             soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile,
    628                                 TRUST_DSCP_PTRf, hw_map_idx);
    629         } else {
    630             if (BCM_VLAN_INVALID > iif->intf_id) {
    631                 uint32 dscp_val = 127;
    632 #ifdef BCM_TOMAHAWK3_SUPPORT
    633                if (SOC_IS_TOMAHAWK3(unit)) {
    634                    dscp_val = 63;
    635                }
    636 #endif
    637                 soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile,
    638                                 TRUST_DSCP_PTRf, dscp_val);
    639             } else {
    640                 /* Trident2 : 7 bit*/
    641                 if (SOC_IS_TRIDENT3X(unit)) {
    642                     /* TD3TBD NOT SURE HOW TD3 handle this, email sent to ARCHI already */
    643                     /* TRUST bit still 7 bits - yet we now have 132 ports - follow
    644                      * equation below will out bound filed TRUST_DSCP_PTR
    645                      * Hard coded to 127 according to reg file for now.
    646                      */
    647                     no_trust_idx = ((soc_mem_index_count(unit, PHB_MAPPING_TBL_2m) / 64)) - 1;
    648                     no_trust_idx = 127;
    649                 } else {
    650                     no_trust_idx = ((soc_mem_index_count(unit, DSCP_TABLEm) / 64)) - 1;
    651                 }
    652                 soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile, 
    653                                     TRUST_DSCP_PTRf, no_trust_idx);
    654             }
    655         }
    656 
    657         if (soc_mem_field_valid(unit, L3_IIF_PROFILEm, URPF_DEFAULTROUTECHECKf)) {
    658         /* Set URPF. */
    659         value = (iif->flags &
    660             BCM_L3_INGRESS_URPF_DEFAULT_ROUTE_CHECK) ? 1 : 0;
    661         soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile, 
    662                                     URPF_DEFAULTROUTECHECKf, value);
    663         soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile,
    664                              URPF_MODEf, iif->urpf_mode); 
    665         }
    666 
    667         /* Set enable global route value. */
    668         value = (iif->flags & BCM_L3_INGRESS_GLOBAL_ROUTE) ? 1 : 0;
    669         soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile,
    670                             ALLOW_GLOBAL_ROUTEf, value); 
    671 
    672         /* enable IPv4 and IPv6 Unicast and MC */
    673         soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile,
    674                             IPV4L3_ENABLEf,
    675                             (iif->flags & BCM_L3_INGRESS_ROUTE_DISABLE_IP4_UCAST)
    676                             ? 0 : 1); 
    677         soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile,
    678                             IPMCV4_ENABLEf,
    679                             (iif->flags & BCM_L3_INGRESS_ROUTE_DISABLE_IP4_MCAST)
    680                             ? 0 : 1); 
    681         soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile,
    682                             IPV6L3_ENABLEf,
    683                             (iif->flags & BCM_L3_INGRESS_ROUTE_DISABLE_IP6_UCAST)
    684                             ? 0 : 1); 
    685         soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile,
    686                             IPMCV6_ENABLEf,
    687                             (iif->flags & BCM_L3_INGRESS_ROUTE_DISABLE_IP6_MCAST)
    688                             ? 0 : 1); 
    689 
    690         /* Set ICMP redirect to CPU */
    691         soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile,
    692                             ICMP_REDIRECT_TOCPUf,
    693                             (iif->flags & BCM_L3_INGRESS_ICMP_REDIRECT_TOCPU)
    694                             ? 1 : 0);
    695 
    696         /* Set Unknown IPMC to CPU */
    697         soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile,
    698                             UNKNOWN_IPV4_MC_TOCPUf,
    699                             (iif->flags & BCM_L3_INGRESS_UNKNOWN_IP4_MCAST_TOCPU)
    700                             ? 1 : 0);
    701 
    702         soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile,
    703                             UNKNOWN_IPV6_MC_TOCPUf,
    704                             (iif->flags & BCM_L3_INGRESS_UNKNOWN_IP6_MCAST_TOCPU)
    705                             ? 1 : 0); 
    706 
    707 #ifdef BCM_TOMAHAWK_SUPPORT
    708         /* Set Unknown IPMC as L2MC */
    709         if (soc_mem_field_valid(unit, L3_IIF_PROFILEm, IPMC_MISS_AS_L2MCf)) {
    710             soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile,
    711                                 IPMC_MISS_AS_L2MCf,
    712                                 (iif->flags & BCM_L3_INGRESS_UNKNOWN_IPMC_AS_L2MC)
    713                                 ? 1 : 0);
    714         }
    715 #endif
    716 
    717         /* set L3_OVERRIDE_IPMC_DO_VLAN */
    718         soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile,
    719                             L3_OVERRIDE_IPMC_DO_VLANf,
    720                             (iif->flags & BCM_L3_INGRESS_IPMC_DO_VLAN_DISABLE)
    721                             ? 1 : 0);
    722 
    723         if (BCM_SUCCESS(rv)) {
    724             /* If profile entry exist and not shared, update it */
    725             rv = _bcm_l3_iif_profile_entry_update(unit, entries, &index);
    726             if (BCM_SUCCESS(rv)) {
    727                 *profile_index = (uint8)index;
    728                 return BCM_E_NONE;
    729             }
    730         }
    731 
    732         /* Create new profile entry if not existent or updating failed */
    733         rv = _bcm_l3_iif_profile_entry_add(unit, entries, 1, &index);
    734         if (BCM_SUCCESS(rv)) {
    735             *profile_index = (uint8)index;
    736         }
    737     }
    738     return rv;
    739 
    740 }
    741 #endif /* BCM_TRIDENT2_SUPPORT */
    742 
    743 
    744 /*
    745  * Function:
    746  *      _bcm_tr_l3_ingress_interface_set
    747  * Purpose:
    748  *      Set ingress interface config.
    749  * Parameters:
    750  *      unit         - (IN) BCM unit number.
    751  *      iif          - (IN) Interface configuration.
    752  *      iif_hw_entry - (IN) H/W entry for specified iif index
    753  *      hw_copy      - (OUT) Updated H/W entry contents to be written
    754  * Returns:
    755  *      BCM_E_XXX.
    756  * Note:
    757  *      For avoiding PIO Reads by this function at init time, 
    758  *      iif_hw_entry and hw_copy arguments should be non null.
    759  *      iif_hw_entry should contain the contents of current H/W 
    760  *      entry and hw_copy is updated by function with the new 
    761  *      H/W entry data to be written.
    762  *      Other than Init time the calls to this function may be using
    763  *      the last 2 arguments as NULL.
    764  */
    765 int
    766 _bcm_tr_l3_ingress_interface_set(int unit, _bcm_l3_ingress_intf_t *iif,
    767                                 iif_entry_t *iif_hw_entry,
    768                                 iif_entry_t *hw_copy)
    769 {
    770     iif_entry_t entry, iif_entry;     /* HW entry buffer.        */
    771     uint8 value = 0;                  /* Enable/disable boolean. */
    772 #ifdef BCM_TRIDENT2_SUPPORT
    773     uint8 old_profile_index = 0;
    774 #endif
    775     int hw_map_idx=0;
    776     int rv = BCM_E_NONE;
    777 #if defined(BCM_KATANA_SUPPORT) ||      \
    778     defined(BCM_TRIUMPH3_SUPPORT) ||    \
    779     defined(BCM_TRIDENT2_SUPPORT)
    780     int rv2 = BCM_E_NONE;
    781 #endif
    782 #ifdef BCM_TRIUMPH2_SUPPORT
    783     int mode=0;
    784 #endif
    785     int bit_num=0;
    786 
    787 #ifdef BCM_TRIDENT2_SUPPORT
    788     int use_hw_copy = 0;
    789 #endif
    790 #ifdef BCM_TRIDENT3_SUPPORT
    791     _bcm_l3_bookkeeping_t *l3;
    792 #endif
    793     /* Input parameters sanity check. */
    794     if (NULL == iif) {
    795         return (BCM_E_PARAM);
    796     }
    797     if ((iif->intf_id > soc_mem_index_max(unit, L3_IIFm)) || 
    798         (iif->intf_id < soc_mem_index_min(unit, L3_IIFm))) {
    799         return (BCM_E_PARAM);
    800     }
    801 
    802 #ifdef BCM_TRIUMPH2_SUPPORT
    803     if (soc_mem_field_valid(unit, L3_IIFm, IPMC_L3_IIFf)) {
    804         rv = bcm_xgs3_l3_ingress_mode_get(unit, &mode);
    805         if (rv < 0) {
    806             return rv;
    807         }
    808         if (mode) {
    809             if (!SOC_MEM_FIELD32_VALUE_FIT(unit, L3_IIFm,
    810                                            IPMC_L3_IIFf, iif->ipmc_intf_id)) {
    811                 return (BCM_E_PARAM);
    812             }
    813         } else {
    814             if (!SOC_MEM_FIELD32_VALUE_FIT(unit, L3_IIFm,
    815                                            IPMC_L3_IIFf, iif->intf_id)) {
    816                 return (BCM_E_PARAM);
    817             }
    818         }
    819     }
    820 #endif /* BCM_TRIUMPH2_SUPPORT */
    821     /* Make sure both hw_copy and iif_entry parameters are same */
    822     if ((iif_hw_entry && !hw_copy) ||
    823         (!iif_hw_entry && hw_copy)) {
    824             return (BCM_E_PARAM);
    825     }
    826 
    827 #ifdef BCM_TRIDENT2_SUPPORT
    828     if (iif_hw_entry) {
    829         use_hw_copy = TRUE;
    830     }
    831 #endif
    832 
    833     sal_memcpy(&entry,  soc_mem_entry_null(unit, L3_IIFm),
    834                sizeof(iif_entry_t));
    835     sal_memcpy(&iif_entry,  soc_mem_entry_null(unit, L3_IIFm),
    836                sizeof(iif_entry_t));
    837     
    838     /* Set class id value. */
    839     if (SOC_MEM_FIELD_VALID(unit, L3_IIFm, CLASS_IDf)) {
    840         soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, CLASS_IDf,
    841                         iif->if_class);
    842     } else {
    843         /* for device support L3_IIFm without CLASS_IDf
    844          *  - Allow init value=0 only.
    845          *  - Return BCM_E_UNAVAIL for other value.
    846          */
    847         if (iif->if_class != 0) {
    848             return (BCM_E_UNAVAIL);
    849         }
    850     }
    851 
    852     /* Set vrf id value. */
    853     if (SOC_MEM_FIELD_VALID(unit, L3_IIFm, VRFf)) {
    854 
    855 #ifdef BCM_TRIDENT3_SUPPORT
    856         l3 = &_bcm_l3_bk_info[unit];
    857 
    858         /*VRF_VALID not set during initialization. Set only when called from API */
    859         if (SOC_MEM_FIELD_VALID(unit, L3_IIFm, VRF_VALIDf)) {
    860             if (((!(l3->riot_enable)) || SOC_IS_DONE_INIT(unit))
    861                                                    && (iif->vrf != BCM_L3_VRF_INVALID)) {
    862                 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, VRF_VALIDf, 1);
    863             } else {
    864                 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, VRF_VALIDf, 0);
    865             }
    866         }
    867 #endif
    868         if (BCM_L3_VRF_INVALID != iif->vrf) {
    869             soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, VRFf, iif->vrf);
    870         } else {
    871             soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, VRFf, 0);
    872         }
    873     } else {
    874         /* for device support L3_IIFm without VRFf
    875          *  - Allow init value=0 only.
    876          *  - Return BCM_E_UNAVAIL for other value.
    877          */
    878         if (iif->vrf != 0) {
    879             return (BCM_E_UNAVAIL);
    880         }
    881     }
    882 
    883     /* Set Trust QoS Map Id Value. */
    884     if (iif->flags & BCM_L3_INGRESS_DSCP_TRUST) {
    885          if (SOC_MEM_FIELD_VALID(unit, L3_IIFm, TRUST_DSCP_PTRf)) {
    886              if (SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit) ||
    887                  SOC_IS_HURRICANE3(unit)) {
    888                  BCM_IF_ERROR_RETURN
    889                      (_bcm_tr_qos_id2idx(unit, iif->qos_map_id, &hw_map_idx));
    890              } else {
    891 #ifdef BCM_TRIUMPH2_SUPPORT
    892                  BCM_IF_ERROR_RETURN
    893                      (_bcm_tr2_qos_id2idx(unit, iif->qos_map_id, &hw_map_idx));
    894 #endif /* BCM_TRIUMPH2_SUPPORT */
    895              }
    896              soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
    897                                  TRUST_DSCP_PTRf, hw_map_idx);
    898          }
    899     } else {
    900          if (BCM_VLAN_INVALID > iif->intf_id) {
    901              if (soc_mem_field_valid(unit, L3_IIFm, TRUST_DSCP_PTRf)) {
    902                  bit_num = soc_mem_field_length(unit, L3_IIFm, TRUST_DSCP_PTRf);
    903                  switch (bit_num) {
    904                      case _BCM_TR_L3_TRUST_DSCP_PTR_BIT_SIZE:
    905                           /* DSCP_TABLE size vary across Chariot and Enduro, but Do not trust value is identical */
    906                           soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 
    907                                           TRUST_DSCP_PTRf, 63);
    908                           break;
    909                      case _BCM_TD_L3_TRUST_DSCP_PTR_BIT_SIZE:
    910                           /* Trident and Triumph3 */
    911                          
    912                          if (SOC_IS_TRIUMPH3(unit) || SOC_IS_GREYHOUND2(unit)) {
    913                              soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 
    914                                                  TRUST_DSCP_PTRf, 127);
    915                          } else {
    916                              soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 
    917                                                  TRUST_DSCP_PTRf, 0);
    918                          }
    919                          break;
    920 
    921                      default:
    922                          break;
    923                  }
    924              }
    925          } else {
    926             /* case for iif->intf_id >= 4096 */
    927             if (soc_mem_field_valid(unit, L3_IIFm, TRUST_DSCP_PTRf)) {
    928                 bit_num = soc_mem_field_length(unit, L3_IIFm, TRUST_DSCP_PTRf);
    929                 switch (bit_num) {
    930                     case _BCM_TR_L3_TRUST_DSCP_PTR_BIT_SIZE:
    931                          /* DSCP_TABLE size vary across Chariot and Enduro, but Do not trust value is identical */
    932                          soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 
    933                                          TRUST_DSCP_PTRf, 63);
    934                          break;
    935                     case _BCM_TD_L3_TRUST_DSCP_PTR_BIT_SIZE:
    936                          /* Trident and Triumph3 */
    937                         soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 
    938                                            TRUST_DSCP_PTRf, 127);
    939                          break;
    940 
    941                     default:
    942                           break;
    943                 }
    944             }
    945          }
    946     }
    947     /* Set identity mapping for IPMC L3 IIF */
    948 #ifdef BCM_TRIUMPH2_SUPPORT
    949     if (soc_mem_field_valid(unit, L3_IIFm, IPMC_L3_IIFf)) {
    950         rv = bcm_xgs3_l3_ingress_mode_get(unit, &mode);
    951         if (rv < 0) {
    952             return rv;
    953         }
    954         if (mode) {
    955             soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
    956                                 IPMC_L3_IIFf, iif->ipmc_intf_id);
    957         } else {
    958             soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
    959                                 IPMC_L3_IIFf, iif->intf_id);
    960         }
    961     }
    962 #endif /* BCM_TRIUMPH2_SUPPORT */
    963 
    964 #ifdef BCM_GREYHOUND2_SUPPORT
    965     if (soc_mem_field_valid(unit, L3_IIFm, ICMP_REDIRECT_TO_CPUf)) {
    966         value = (iif->flags & BCM_L3_INGRESS_ICMP_REDIRECT_TOCPU) ? 1 : 0;
    967         soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
    968                             ICMP_REDIRECT_TO_CPUf, value);
    969     }
    970 #endif /* BCM_GREYHOUND2_SUPPORT */
    971 
    972 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
    973     if (soc_mem_field_valid(unit, L3_IIFm, URPF_DEFAULTROUTECHECKf)) {
    974          value  = (iif->flags & BCM_L3_INGRESS_URPF_DEFAULT_ROUTE_CHECK) ?  1 : 0;
    975          soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
    976                              URPF_DEFAULTROUTECHECKf, value); 
    977     }
    978     if (soc_mem_field_valid(unit, L3_IIFm, URPF_MODEf)) {
    979          soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
    980                              URPF_MODEf, iif->urpf_mode); 
    981     }
    982 #endif  /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */
    983 
    984     /* Set enable global route value. */
    985     if (soc_mem_field_valid(unit, L3_IIFm, ALLOW_GLOBAL_ROUTEf)) {
    986         value  = (iif->flags & BCM_L3_INGRESS_GLOBAL_ROUTE) ?  1 : 0;
    987         soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
    988                             ALLOW_GLOBAL_ROUTEf, value); 
    989     }
    990 
    991 #ifdef BCM_TRIDENT2_SUPPORT
    992     if (use_hw_copy) {
    993         sal_memcpy(&iif_entry, iif_hw_entry, sizeof(iif_entry_t));
    994 
    995     } else {
    996         /* Read interface entry from hw. */
    997         rv2 = soc_mem_read(unit, L3_IIFm, MEM_BLOCK_ANY, iif->intf_id,
    998                           (uint32 *)&iif_entry);
    999         if (SOC_FAILURE(rv2)) {
   1000             LOG_ERROR(BSL_LS_BCM_L3,
   1001                     (BSL_META_U(unit,
   1002                         "Mem read for L3_IIF failed for index=(%d)\n"),
   1003                          iif->intf_id));
   1004             return rv2;
   1005         }
   1006     }
   1007 #elif defined (BCM_KATANA_SUPPORT) || defined (BCM_TRIUMPH3_SUPPORT)
   1008         /* Read interface entry from hw. */
   1009         rv2 = soc_mem_read(unit, L3_IIFm, MEM_BLOCK_ANY, iif->intf_id,
   1010                       (uint32 *)&iif_entry);
   1011         if (SOC_FAILURE(rv2)) {
   1012             LOG_ERROR(BSL_LS_BCM_L3,
   1013                     (BSL_META_U(unit,
   1014                         "Mem read for L3_IIF failed for index=(%d)\n"),
   1015                          iif->intf_id));
   1016             return rv2;
   1017         }
   1018 #endif
   1019 
   1020 #ifdef BCM_TRIDENT2_SUPPORT
   1021     /* TD2 L3_IIF_PROFILE  and IP Option Profile*/
   1022     if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   1023         if (soc_feature(unit, soc_feature_nat) &&
   1024                         SOC_MEM_FIELD_VALID(unit, L3_IIFm, SRC_REALM_IDf)) {
   1025             if ((iif->nat_realm_id < 0) || (iif->nat_realm_id > 3)) {
   1026                 return BCM_E_PARAM;
   1027             }
   1028             /* Set the nat source realm id value. */
   1029             soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, SRC_REALM_IDf,
   1030                                 iif->nat_realm_id);
   1031             if (iif->flags & BCM_L3_INGRESS_SRC_DST_NAT_REALM_ID) {
   1032                 BCM_IF_ERROR_RETURN(
   1033                     _bcm_td2_nh_nat_id_update_by_l3_iif(unit, iif->intf_id,
   1034                                                         iif->nat_realm_id));
   1035             }
   1036         }
   1037 
   1038         if (BCM_SUCCESS(rv2)) {
   1039             /* Get profile_index from interface entry*/
   1040             old_profile_index = soc_mem_field32_get(unit, L3_IIFm,
   1041                                                     (uint32 *)&iif_entry,
   1042                                                     L3_IIF_PROFILE_INDEXf);
   1043         }
   1044 
   1045         if (use_hw_copy) {
   1046             rv = _bcm_l3_iif_profile_add(unit, iif, iif_hw_entry, &value);
   1047         } else {
   1048             rv = _bcm_l3_iif_profile_add(unit, iif, NULL, &value);
   1049         }
   1050 
   1051         if (BCM_FAILURE(rv)) {
   1052             return rv;
   1053         }
   1054         if ((value < soc_mem_index_min(unit, L3_IIF_PROFILEm)) ||
   1055             (value > soc_mem_index_max(unit, L3_IIF_PROFILEm))) {
   1056             return BCM_E_FAIL;
   1057         }
   1058         if (soc_mem_field_valid(unit, L3_IIFm, L3_IIF_PROFILE_INDEXf)) {
   1059             soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
   1060                                 L3_IIF_PROFILE_INDEXf, value);
   1061         }
   1062 
   1063         /* Program IP option Profile Index */
   1064         if (soc_feature(unit, soc_feature_l3_ip4_options_profile)) {
   1065             int index;
   1066 
   1067             /* Get the hardware index for the profile */
   1068             rv = _bcm_td2_l3_ip4_options_profile_id2idx(unit, 
   1069                                                 iif->ip4_options_profile_id,
   1070                                                 &index);
   1071             if (BCM_SUCCESS(rv)) {
   1072                 /* Program the upper 2 bits */
   1073                 index &= _BCM_TD2_IP_OPTIONS_PROFILE_MASK;
   1074                 /*
   1075                 * COVERITY
   1076                 *
   1077                 * The operands don't affect result. It is kept intentionally
   1078                 * as a defensive default for future development.
   1079                 */
   1080                 /* coverity[result_independent_of_operands] */
   1081                 index = index >> _BCM_TD2_IP_OPTIONS_BITS_WIDTH;
   1082                 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
   1083                                     IP_OPTION_PROFILE_INDEXf, index);
   1084             }
   1085         }
   1086     }
   1087 
   1088     if (soc_feature(unit, soc_feature_pim_bidir) &&
   1089         SOC_MEM_FIELD_VALID(unit, L3_IIFm, ACTIVE_L3_IIF_PROFILE_INDEXf) &&
   1090         BCM_SUCCESS(rv2)) {
   1091         int active_profile_index = 0;
   1092         active_profile_index = soc_mem_field32_get(unit, L3_IIFm,
   1093             (uint32 *)&iif_entry, ACTIVE_L3_IIF_PROFILE_INDEXf);
   1094 
   1095         soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
   1096                             ACTIVE_L3_IIF_PROFILE_INDEXf,
   1097                             active_profile_index);
   1098     }
   1099 #endif
   1100 
   1101 #if defined(BCM_TOMAHAWK_SUPPORT)
   1102     if (soc_feature(unit, soc_feature_ecn_wred) && 
   1103         soc_mem_field_valid(unit, L3_IIFm, ECN_DECAP_MAPPING_PTRf)) {
   1104         if (iif->flags & BCM_L3_INGRESS_TUNNEL_TERM_ECN_MAP) {
   1105             soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
   1106                                 ECN_DECAP_MAPPING_PTRf, 
   1107                                 iif->tunnel_term_ecn_map_id);
   1108         }
   1109     }
   1110 #endif
   1111 
   1112 #ifdef BCM_TOMAHAWK3_SUPPORT
   1113     if (soc_feature(unit, soc_feature_inband_network_telemetry)) {
   1114         if (iif->flags & BCM_L3_INGRESS_INT) {
   1115             rv = soc_mem_read(unit, L3_IIFm, MEM_BLOCK_ANY, iif->intf_id, (uint32 *)&entry);
   1116             if (SOC_MEM_FIELD_VALID(unit, L3_IIFm, INT_ENABLEf)) {
   1117                 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, INT_ENABLEf, 1);
   1118                 rv = soc_mem_write(unit, L3_IIFm, MEM_BLOCK_ALL, iif->intf_id, (uint32 *)&entry);
   1119                 BCM_IF_ERROR_RETURN(rv);
   1120             }
   1121         }
   1122     }
   1123 #endif
   1124 
   1125 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   1126     if (soc_feature(unit,soc_feature_advanced_flex_counter) &&
   1127         BCM_SUCCESS(rv2)) {
   1128         uint32 flex_ctr_offset_mode, flex_ctr_pool_number, flex_ctr_base_idx;
   1129         /* 1 Store the old flex counter */
   1130         BCM_IF_ERROR_RETURN(
   1131             _bcm_esw_get_flex_counter_fields_values(unit, iif->intf_id,
   1132                                                     L3_IIFm, 
   1133                                                     &iif_entry,
   1134                                                     0,
   1135                                                     &flex_ctr_offset_mode, 
   1136                                                     &flex_ctr_pool_number, 
   1137                                                     &flex_ctr_base_idx));
   1138         /* 2 Restore flex counter in new entry */
   1139         BCM_IF_ERROR_RETURN(
   1140             _bcm_esw_set_flex_counter_fields_values(unit, iif->intf_id, 
   1141                                                     L3_IIFm, 
   1142                                                     &entry,
   1143                                                     0,
   1144                                                     flex_ctr_offset_mode, 
   1145                                                     flex_ctr_pool_number, 
   1146                                                     flex_ctr_base_idx));
   1147     }
   1148 #endif
   1149 
   1150 #ifdef BCM_TRIDENT2_SUPPORT
   1151     if (use_hw_copy) {
   1152         /* Need to skip this step */
   1153     } else
   1154 #endif
   1155     {
   1156         /* Write  updated entry back to hw.*/
   1157         rv = soc_mem_write(unit, L3_IIFm, MEM_BLOCK_ALL, iif->intf_id, 
   1158                               (uint32 *)&entry);
   1159     }
   1160 #ifdef BCM_TRIDENT2_SUPPORT
   1161     if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   1162         if (soc_feature(unit, soc_feature_l3_iif_profile)) {
   1163             if (BCM_SUCCESS(rv)) {
   1164                 /* delete old entry if its valid and different than new entry*/
   1165                 if ((value != old_profile_index) && old_profile_index) {
   1166                     _bcm_l3_iif_profile_entry_delete(unit, old_profile_index);
   1167                 }
   1168             } else {
   1169                 /* if hw write fails for new entry then old entry is still vaild*/
   1170                 /* we may have to remove the new entry which was added above. */
   1171                 _bcm_l3_iif_profile_entry_delete(unit, value);
   1172             }
   1173         }
   1174     }
   1175 #endif
   1176 
   1177 #ifdef BCM_TRIDENT2_SUPPORT
   1178     /* Update the entry copy if hw_entry is used */
   1179     if (use_hw_copy) {
   1180         sal_memcpy(hw_copy, &entry, sizeof(iif_entry_t));
   1181     }
   1182 #endif
   1183 
   1184     return rv;
   1185 }
   1186 
   1187 /*
   1188  * Function:
   1189  *      _bcm_tr_l3_ingress_interface_clr
   1190  * Purpose:
   1191  *      Set ingress interface config.
   1192  * Parameters:
   1193  *      unit     - (IN) BCM unit number.
   1194  *      iif      - (IN) Interface configuration.
   1195  * Returns:
   1196  *      BCM_E_XXX.
   1197  */
   1198 int
   1199 _bcm_tr_l3_ingress_interface_clr(int unit, int intf_id)
   1200 {
   1201     int bit_num;
   1202     iif_entry_t entry;          /* HW entry buffer.        */
   1203 #ifdef BCM_TRIDENT2_SUPPORT
   1204     uint8 index;
   1205     int ref_cnt = 0;
   1206 #endif /* BCM_TRIDENT2_SUPPORT */
   1207 
   1208     /* Input parameters sanity check. */
   1209     if ((intf_id > soc_mem_index_max(unit, L3_IIFm)) || 
   1210         (intf_id < soc_mem_index_min(unit, L3_IIFm))) {
   1211         return (BCM_E_PARAM);
   1212     }
   1213 #ifdef BCM_TRIDENT2_SUPPORT
   1214     if (SOC_IS_TD2_TT2(unit)) {
   1215         BCM_IF_ERROR_RETURN(
   1216             soc_mem_read(unit, L3_IIFm, MEM_BLOCK_ANY, intf_id, (uint32 *)&entry));
   1217         index = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry,
   1218                                     L3_IIF_PROFILE_INDEXf); 
   1219         /* Since there will be 1:1 mapping for 4k vlans to ingress L3_IIF,
   1220          * all these 4k vlans will be mapped to default L3_IIF_PROFILE index 0.
   1221          * So, this default entry should be removed only when ref_cnt of profile
   1222          * index 0 is greater than 4k.
   1223          */
   1224         if (!index) {
   1225             (void)_bcm_l3_iif_profile_entry_reference_get(unit, index,
   1226                                                           &ref_cnt);
   1227             if (ref_cnt > BCM_VLAN_COUNT) {
   1228                 (void)_bcm_l3_iif_profile_entry_delete(unit, index);
   1229             }
   1230         } else {
   1231             (void)_bcm_l3_iif_profile_entry_delete(unit, index);
   1232         }
   1233     }
   1234 #endif
   1235 
   1236     /* Restore the IIF entry to its defaults */
   1237     sal_memcpy(&entry,  soc_mem_entry_null(unit, L3_IIFm),
   1238                sizeof(iif_entry_t));
   1239 
   1240     if (BCM_XGS3_L3_INGRESS_INTF_MAP_MODE_ISSET(unit)) {
   1241         /* 
   1242          * When BCM_XGS3_L3_INGRESS_INTF_MAP_MODE_ISSET,
   1243          * the application is expected to have a complete control of 
   1244          * l3_iif and the mapping between l3_iif and vlan.
   1245          */
   1246 
   1247         if (soc_feature(unit, soc_feature_l3_iif_under_4k) && 
   1248                 soc_mem_field_valid(unit, L3_IIFm, TRUST_DSCP_PTRf)) {
   1249             bit_num = soc_mem_field_length(unit, L3_IIFm, TRUST_DSCP_PTRf);
   1250             /* max value for TRUST_DSCP_PTRf is special value as inactive */
   1251             soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
   1252                                     TRUST_DSCP_PTRf, ((1 << bit_num) - 1));
   1253         }
   1254 
   1255         return  soc_mem_write(unit, L3_IIFm, MEM_BLOCK_ALL, intf_id, 
   1256                               (uint32 *)&entry);
   1257     }
   1258     
   1259     /* Set enable global route value. */
   1260     if (soc_mem_field_valid(unit, L3_IIFm, ALLOW_GLOBAL_ROUTEf)) {
   1261         soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
   1262                             ALLOW_GLOBAL_ROUTEf, 1);
   1263     }
   1264 
   1265     /* Set identity mapping for IPMC L3 IIF */
   1266 #ifdef BCM_TRIUMPH2_SUPPORT
   1267     if (soc_mem_field_valid(unit, L3_IIFm, IPMC_L3_IIFf)) {
   1268         soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
   1269                             IPMC_L3_IIFf, intf_id);
   1270     }
   1271 #endif /* BCM_TRIUMPH2_SUPPORT */
   1272 
   1273 #ifdef BCM_GREYHOUND2_SUPPORT
   1274     if (soc_mem_field_valid(unit, L3_IIFm, ICMP_REDIRECT_TO_CPUf)) {
   1275         soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
   1276                             ICMP_REDIRECT_TO_CPUf, 0);
   1277     }
   1278 #endif /* BCM_GREYHOUND2_SUPPORT */
   1279 
   1280 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
   1281     if (soc_mem_field_valid(unit, L3_IIFm, URPF_DEFAULTROUTECHECKf)) {
   1282          soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
   1283                              URPF_DEFAULTROUTECHECKf, 1);
   1284     }
   1285 #endif  /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */
   1286 
   1287     /* Set appropriate default TRUST_DSCP_PTR mapping */
   1288     if (soc_mem_field_valid(unit, L3_IIFm, TRUST_DSCP_PTRf)) {
   1289         bit_num = soc_mem_field_length(unit, L3_IIFm, TRUST_DSCP_PTRf);
   1290 
   1291         switch (bit_num) {
   1292             case _BCM_TR_L3_TRUST_DSCP_PTR_BIT_SIZE:
   1293                 /* DSCP_TABLE size vary across Chariot and Enduro,
   1294                  * but Do not trust value is identical */
   1295                 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
   1296                                     TRUST_DSCP_PTRf, 63);
   1297                 break;
   1298             case _BCM_TD_L3_TRUST_DSCP_PTR_BIT_SIZE:
   1299                 /* Trident and Triumph3 */
   1300                 if ((BCM_VLAN_INVALID < intf_id) || SOC_IS_TRIUMPH3(unit)) {
   1301                     soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
   1302                                         TRUST_DSCP_PTRf, 127);
   1303                 } else {
   1304                     /* For Trident, if intf_id < BCM_VLAN_INVALID */
   1305                     soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry,
   1306                                         TRUST_DSCP_PTRf, 0);
   1307                 }
   1308                 break;
   1309             default:
   1310                 break;
   1311         }
   1312     }
   1313 
   1314     /* Write  updated entry back to hw.*/
   1315     return  soc_mem_write(unit, L3_IIFm, MEM_BLOCK_ALL, intf_id, 
   1316                           (uint32 *)&entry);
   1317 }
   1318 
   1319 /*
   1320  * Function:
   1321  *      _bcm_tr_l3_intf_class_set
   1322  * Purpose:
   1323  *      Set classigication class to the interface. 
   1324  * Parameters:
   1325  *      unit       - (IN) SOC unit number.
   1326  *      vid        - (IN) vlan id.
   1327  *      intf_class - (IN) Interface class id.
   1328  * Returns:
   1329  *      BCM_E_XXX.
   1330  */
   1331 int
   1332 _bcm_tr_l3_intf_class_set(int unit, bcm_vlan_t vid, uint32 intf_class)
   1333 {
   1334     _bcm_l3_ingress_intf_t iif; /* Ingress interface config.*/
   1335     int ret_val;                /* Operation return value.  */
   1336 
   1337     /* Input parameters sanity check. */
   1338     if ((vid > soc_mem_index_max(unit, L3_IIFm)) || 
   1339         (vid < soc_mem_index_min(unit, L3_IIFm))) {
   1340         return (BCM_E_PARAM);
   1341     }
   1342 
   1343     if (intf_class> SOC_INTF_CLASS_MAX(unit)) {
   1344         return (BCM_E_PARAM);
   1345     }
   1346     
   1347     iif.intf_id = vid;
   1348     soc_mem_lock(unit, L3_IIFm);
   1349 
   1350     ret_val = _bcm_tr_l3_ingress_interface_get(unit, NULL, &iif);
   1351     if (BCM_FAILURE(ret_val)) {
   1352         soc_mem_unlock(unit, L3_IIFm);
   1353         return (ret_val);
   1354     }
   1355 
   1356     iif.if_class = intf_class;
   1357 #if defined(BCM_TRIDENT2_SUPPORT)
   1358     if (soc_feature(unit, soc_feature_l3_iif_profile)) {
   1359         iif.profile_flags |= _BCM_L3_IIF_PROFILE_DO_NOT_UPDATE;
   1360     }
   1361 #endif /* BCM_TRIDENT2_SUPPORT */
   1362     ret_val = _bcm_tr_l3_ingress_interface_set(unit, &iif, NULL, NULL);
   1363 
   1364     soc_mem_unlock(unit, L3_IIFm);
   1365 
   1366     return (ret_val);
   1367 }
   1368 
   1369 /*
   1370  * Function:
   1371  *      _bcm_tr_l3_intf_global_route_enable_get
   1372  * Purpose:
   1373  *      Get the global route enable flag for the specified L3 interface
   1374  * Parameters:
   1375  *      unit      - (IN)SOC unit number.
   1376  *      vid       - (IN)Vlan id. 
   1377  *      enable    - (OUT)enable. 
   1378  * Returns:
   1379  *      BCM_E_XXX.
   1380  */
   1381 int
   1382 _bcm_tr_l3_intf_global_route_enable_get(int unit, bcm_vlan_t vid, int *enable)
   1383 {
   1384     _bcm_l3_ingress_intf_t iif; /* Ingress interface config.*/
   1385 
   1386     /* Input parameters sanity check. */
   1387     if ((vid > soc_mem_index_max(unit, L3_IIFm)) || 
   1388         (vid < soc_mem_index_min(unit, L3_IIFm))) {
   1389         return (BCM_E_PARAM);
   1390     }
   1391 
   1392     iif.intf_id = vid;
   1393 
   1394     BCM_IF_ERROR_RETURN(_bcm_tr_l3_ingress_interface_get(unit, NULL, &iif));
   1395 
   1396     *enable = (iif.flags & BCM_L3_INGRESS_GLOBAL_ROUTE) ? 1 : 0;
   1397     return (BCM_E_NONE);
   1398 }
   1399 
   1400 /*
   1401  * Function:
   1402  *      _bcm_tr_l3_intf_global_route_enable_set
   1403  * Purpose:
   1404  *      Set global route enable flag for the L3 interface. 
   1405  * Parameters:
   1406  *      unit      - (IN)SOC unit number.
   1407  *      vid       - (IN)Vlan id. 
   1408  *      enable    - (IN)Enable. 
   1409  * Returns:
   1410  *      BCM_E_XXX.
   1411  */
   1412 int
   1413 _bcm_tr_l3_intf_global_route_enable_set(int unit, bcm_vlan_t vid, int enable)  
   1414 {
   1415     _bcm_l3_ingress_intf_t iif; /* Ingress interface config.*/
   1416     int ret_val;                /* Operation return value.  */
   1417 
   1418     /* Input parameters sanity check. */
   1419     if ((vid > soc_mem_index_max(unit, L3_IIFm)) || 
   1420         (vid < soc_mem_index_min(unit, L3_IIFm))) {
   1421         return (BCM_E_PARAM);
   1422     }
   1423 
   1424     iif.intf_id = vid;
   1425     soc_mem_lock(unit, L3_IIFm);
   1426 
   1427     ret_val = _bcm_tr_l3_ingress_interface_get(unit, NULL, &iif);
   1428     if (BCM_FAILURE(ret_val)) {
   1429         soc_mem_unlock(unit, L3_IIFm);
   1430         return (ret_val);
   1431     }
   1432 
   1433     if (enable) {
   1434        iif.flags |= BCM_L3_INGRESS_GLOBAL_ROUTE;
   1435     } else {
   1436        iif.flags &= ~BCM_L3_INGRESS_GLOBAL_ROUTE;
   1437     }
   1438 
   1439     ret_val = _bcm_tr_l3_ingress_interface_set(unit, &iif, NULL, NULL);
   1440 
   1441     soc_mem_unlock(unit, L3_IIFm);
   1442 
   1443     return (ret_val);
   1444 }
   1445 
   1446 #if defined (BCM_TRIDENT2_SUPPORT)
   1447 /*
   1448  * Function:
   1449  *      _bcm_tr_l3_intf_nat_realm_id_get
   1450  * Purpose:
   1451  *      Get the src_realm_id for the specified L3 interface
   1452  * Parameters:
   1453  *      unit            - (IN)SOC unit number.
   1454  *      vid             - (IN)Vlan id. 
   1455  *      nat_realm_id    - (OUT)realm_id. 
   1456  * Returns:
   1457  *      BCM_E_XXX.
   1458  */
   1459 int
   1460 _bcm_tr_l3_intf_nat_realm_id_get(int unit, bcm_vlan_t vid, int *realm_id)
   1461 {
   1462     _bcm_l3_ingress_intf_t iif; /* Ingress interface config.*/
   1463 
   1464     if (!soc_feature(unit, soc_feature_nat)) {
   1465         return BCM_E_UNAVAIL;
   1466     }
   1467 
   1468     /* Input parameters sanity check. */
   1469     if ((vid > soc_mem_index_max(unit, L3_IIFm)) || 
   1470         (vid < soc_mem_index_min(unit, L3_IIFm))) {
   1471         return (BCM_E_PARAM);
   1472     }
   1473 
   1474     iif.intf_id = vid;
   1475 
   1476     BCM_IF_ERROR_RETURN(_bcm_tr_l3_ingress_interface_get(unit, NULL, &iif));
   1477 
   1478     *realm_id = iif.nat_realm_id;
   1479     return (BCM_E_NONE);
   1480 }
   1481 
   1482 /*
   1483  * Function:
   1484  *      _bcm_tr_l3_intf_nat_realm_id_set
   1485  * Purpose:
   1486  *      Bind interface to the VRF & update if info.
   1487  * Parameters:
   1488  *      unit      - (IN)SOC unit number.
   1489  *      vid       - (IN)Vlan id. 
   1490  *      vrf       - (OUT)Vrf. 
   1491  * Returns:
   1492  *      BCM_E_XXX.
   1493  */
   1494 int
   1495 _bcm_tr_l3_intf_nat_realm_id_set(int unit, bcm_vlan_t vid, int realm_id)  
   1496 {
   1497     _bcm_l3_ingress_intf_t iif; /* Ingress interface config.*/
   1498     int ret_val;                /* Operation return value.  */
   1499 
   1500     if (!soc_feature(unit, soc_feature_nat)) {
   1501         return BCM_E_UNAVAIL;
   1502     }
   1503 
   1504     /* Input parameters sanity check. */
   1505     if ((vid > soc_mem_index_max(unit, L3_IIFm)) || 
   1506         (vid < soc_mem_index_min(unit, L3_IIFm))) {
   1507         return (BCM_E_PARAM);
   1508     }
   1509 
   1510     if ((realm_id < 0) || (realm_id > 3)) {
   1511         return (BCM_E_PARAM);
   1512     }
   1513     
   1514     iif.intf_id = vid;
   1515     soc_mem_lock(unit, L3_IIFm);
   1516 
   1517     ret_val = _bcm_tr_l3_ingress_interface_get(unit, NULL, &iif);
   1518     if (BCM_FAILURE(ret_val)) {
   1519         soc_mem_unlock(unit, L3_IIFm);
   1520         return (ret_val);
   1521     }
   1522 
   1523     iif.nat_realm_id = realm_id;
   1524     if (soc_feature(unit, soc_feature_l3_iif_profile)) {
   1525         iif.profile_flags |= _BCM_L3_IIF_PROFILE_DO_NOT_UPDATE;
   1526     }
   1527 
   1528     ret_val = _bcm_tr_l3_ingress_interface_set(unit, &iif, NULL, NULL);
   1529 
   1530     soc_mem_unlock(unit, L3_IIFm);
   1531 
   1532     return (ret_val);
   1533 }
   1534 #endif /* BCM_TRIDENT2_SUPPORT */
   1535 
   1536 
   1537 /*
   1538  * Function:
   1539  *      _bcm_tr_l3_intf_vrf_get
   1540  * Purpose:
   1541  *      Get the VRF,flags info for the specified L3 interface
   1542  * Parameters:
   1543  *      unit      - (IN)SOC unit number.
   1544  *      vid       - (IN)Vlan id. 
   1545  *      vrf       - (OUT)Vrf. 
   1546  * Returns:
   1547  *      BCM_E_XXX.
   1548  */
   1549 int
   1550 _bcm_tr_l3_intf_vrf_get(int unit, bcm_vlan_t vid, bcm_vrf_t *vrf)
   1551 {
   1552     _bcm_l3_ingress_intf_t iif; /* Ingress interface config.*/
   1553 
   1554     /* Input parameters sanity check. */
   1555     if ((vid > soc_mem_index_max(unit, L3_IIFm)) || 
   1556         (vid < soc_mem_index_min(unit, L3_IIFm))) {
   1557         return (BCM_E_PARAM);
   1558     }
   1559 
   1560     iif.intf_id = vid;
   1561 
   1562     BCM_IF_ERROR_RETURN(_bcm_tr_l3_ingress_interface_get(unit, NULL, &iif));
   1563 
   1564     *vrf = iif.vrf;
   1565     return (BCM_E_NONE);
   1566 }
   1567 
   1568 /*
   1569  * Function:
   1570  *      _bcm_tr_l3_intf_vrf_bind
   1571  * Purpose:
   1572  *      Bind interface to the VRF & update if info.
   1573  * Parameters:
   1574  *      unit      - (IN)SOC unit number.
   1575  *      vid       - (IN)Vlan id. 
   1576  *      vrf       - (OUT)Vrf. 
   1577  * Returns:
   1578  *      BCM_E_XXX.
   1579  */
   1580 int
   1581 _bcm_tr_l3_intf_vrf_bind(int unit, bcm_vlan_t vid, bcm_vrf_t vrf)  
   1582 {
   1583     _bcm_l3_ingress_intf_t iif; /* Ingress interface config.*/
   1584     int ret_val;                /* Operation return value.  */
   1585 
   1586     /* Input parameters sanity check. */
   1587     if ((vid > soc_mem_index_max(unit, L3_IIFm)) || 
   1588         (vid < soc_mem_index_min(unit, L3_IIFm))) {
   1589         return (BCM_E_PARAM);
   1590     }
   1591 
   1592     if (vrf > SOC_VRF_MAX(unit)) {
   1593         return (BCM_E_PARAM);
   1594     }
   1595     
   1596     iif.intf_id = vid;
   1597     soc_mem_lock(unit, L3_IIFm);
   1598 
   1599     ret_val = _bcm_tr_l3_ingress_interface_get(unit, NULL, &iif);
   1600     if (BCM_FAILURE(ret_val)) {
   1601         soc_mem_unlock(unit, L3_IIFm);
   1602         return (ret_val);
   1603     }
   1604 
   1605     iif.vrf = vrf;
   1606 #if defined(BCM_TRIDENT2_SUPPORT)
   1607     if (soc_feature(unit, soc_feature_l3_iif_profile)) {
   1608         iif.profile_flags |= _BCM_L3_IIF_PROFILE_DO_NOT_UPDATE;
   1609     }
   1610 #endif /* BCM_TRIDENT2_SUPPORT */
   1611 
   1612     ret_val = _bcm_tr_l3_ingress_interface_set(unit, &iif, NULL, NULL);
   1613 
   1614     soc_mem_unlock(unit, L3_IIFm);
   1615 
   1616     return (ret_val);
   1617 }
   1618 
   1619 /*
   1620  * Function:
   1621  *      _bcm_tr_l3_defip_mem_get
   1622  * Purpose:
   1623  *      Resolve route table memory for a given route entry.
   1624  * Parameters:
   1625  *      unit       - (IN)SOC unit number.
   1626  *      flags      - (IN)IPv6/IPv4 route.
   1627  *      plen       - (IN)Prefix length.
   1628  *      mem        - (OUT)Route table memory.
   1629  * Returns:
   1630  *      BCM_E_XXX
   1631  */
   1632 int
   1633 _bcm_tr_l3_defip_mem_get(int unit, uint32 flags, int plen, soc_mem_t *mem)
   1634 {
   1635     soc_mem_t defip_mem = L3_DEFIPm, defip_128_mem = L3_DEFIP_128m;
   1636 #if defined(BCM_VALKYRIE_SUPPORT) || defined(BCM_ENDURO_SUPPORT) || \
   1637     defined(BCM_APOLLO_SUPPORT) || defined(BCM_VALKYRIE2_SUPPORT) || \
   1638     defined(BCM_TRIDENT_SUPPORT)
   1639     if (soc_mem_is_valid(unit, L3_DEFIP_LEVEL1m)) {
   1640         defip_mem = L3_DEFIP_LEVEL1m;
   1641         defip_128_mem = L3_DEFIP_PAIR_LEVEL1m;
   1642     }
   1643     if (!soc_feature(unit, soc_feature_esm_support)) {
   1644         if (flags & BCM_L3_IP6) {
   1645 #ifdef BCM_KATANA2_SUPPORT
   1646             if (SOC_IS_KATANA2(unit)) {
   1647                 *mem = L3_DEFIPm;
   1648             } else
   1649 #endif /* BCM_KATANA2_SUPPORT */
   1650             if (plen > 64) {
   1651                 *mem = defip_128_mem;
   1652             } else {  /* IPv6 prefix length < 64 bit. */
   1653                 *mem = defip_mem;
   1654             }
   1655         } else { /* IPv4 route. */
   1656             *mem = defip_mem;
   1657         }
   1658         return (BCM_E_NONE);
   1659     }
   1660 #endif
   1661     if (flags & BCM_L3_IP6) {
   1662         if (plen > 64) {
   1663             *mem = defip_128_mem;
   1664             if (soc_feature(unit, soc_feature_esm_support) &&
   1665                 SOC_MEM_IS_ENABLED(unit, EXT_IPV6_128_DEFIPm)) {
   1666                 if (soc_mem_index_count(unit, EXT_IPV6_128_DEFIPm)) {
   1667                     *mem = EXT_IPV6_128_DEFIPm;
   1668                 }
   1669             } 
   1670         } else {  /* IPv6 prefix length < 64 bit. */
   1671             if (soc_feature(unit, soc_feature_esm_support) && 
   1672                 (SOC_MEM_IS_ENABLED(unit, EXT_IPV6_128_DEFIPm) ||
   1673                  SOC_MEM_IS_ENABLED(unit, EXT_IPV6_64_DEFIPm))) {
   1674                 if (soc_mem_index_count(unit, EXT_IPV6_128_DEFIPm)) {
   1675                     *mem = EXT_IPV6_128_DEFIPm;
   1676                 } else if (soc_mem_index_count(unit, EXT_IPV6_64_DEFIPm)) {
   1677                     *mem = EXT_IPV6_64_DEFIPm;
   1678                 } else { /* Defaults to internal memory even if soc feature esm
   1679                          is enabled, but device not configured to use ext mem */
   1680                     *mem = defip_mem;
   1681                 }
   1682             } else {
   1683                 *mem = defip_mem;
   1684             }
   1685         }
   1686     } else { /* IPv4 route. */
   1687         *mem = L3_DEFIPm; 
   1688         if (soc_feature(unit, soc_feature_esm_support) &&
   1689             SOC_MEM_IS_ENABLED(unit, EXT_IPV4_DEFIPm)) {
   1690             if (soc_mem_index_count(unit, EXT_IPV4_DEFIPm)) {
   1691                 *mem = EXT_IPV4_DEFIPm;
   1692             }
   1693         } 
   1694     }
   1695     return (BCM_E_NONE);
   1696 }
   1697 
   1698 /*
   1699  * Function:
   1700  *      _bcm_tr_l3_enable
   1701  * Purpose:
   1702  *      Resolve route table memory for a given route entry.
   1703  * Parameters:
   1704  *      unit       - (IN)BCM device number.
   1705  *      port       - (IN)Port number.
   1706  *      flags      - (IN)IPv6/IPv4 flag.
   1707  *      enable     - (IN)Enable /Disable 
   1708  * Returns:
   1709  *      BCM_E_XXX
   1710  */
   1711 int
   1712 _bcm_tr_l3_enable(int unit, bcm_port_t port, uint32 flags, int enable)
   1713 {
   1714     int rv;
   1715     soc_field_t fields[2];
   1716     uint32 values[2] = {1, 0};
   1717     uint32 rval;
   1718 
   1719     if (!soc_feature(unit, soc_feature_esm_support)) {
   1720         /* No esm on this devices. */
   1721         return (BCM_E_NONE);
   1722     }
   1723 
   1724     BCM_IF_ERROR_RETURN(READ_ESM_KEYGEN_CTLr(unit, &rval));
   1725 
   1726     if (flags & BCM_L3_IP6) {
   1727         fields[0] = IPV6_FWD_MODEf;
   1728         fields[1] = IPV6_128_ENf;
   1729 
   1730         if (enable) {
   1731             
   1732             values[0] = 2; /* L3 forwarding mode */
   1733             /* Enable 128 bit forwarding if 128 bit table is present.*/
   1734             if (soc_mem_index_count(unit, EXT_IPV6_128_DEFIPm)) {
   1735                 values[1] = 1;
   1736             }
   1737         } else {
   1738             values[0] = 1; /* use L2 to forward IPv6 packet */
   1739         }
   1740         rv = soc_reg_fields32_modify(unit, ESM_MODE_PER_PORTr, port,
   1741                                      2, fields, values);
   1742     } else {
   1743         fields[0] = IPV4_FWD_MODEf;
   1744         if (enable) {
   1745             
   1746             values[0] = 2; /* L3 forwarding mode */
   1747         } else {
   1748             values[0] = 1; /* use L2 to forward IPv4 packet */
   1749         }
   1750         rv = soc_reg_fields32_modify(unit, ESM_MODE_PER_PORTr, port, 
   1751                                      1, fields, values);
   1752     }
   1753     return rv;
   1754 }
   1755 
   1756 /*
   1757  * Function:
   1758  *      _bcm_tr_l3_clear_hit
   1759  * Purpose:
   1760  *      Clear hit bit on l3 entry
   1761  * Parameters:
   1762  *      unit      - (IN)SOC unit number.
   1763  *      mem       - (IN)L3 table memory.
   1764  *      l3cfg     - (IN)l3 entry info. 
   1765  *      l3x_entry - (IN)l3 entry filled hw buffer.
   1766  * Returns:
   1767  *      BCM_E_XXX
   1768  */
   1769 STATIC int
   1770 _bcm_tr_l3_clear_hit(int unit, soc_mem_t mem,
   1771                        _bcm_l3_cfg_t *l3cfg, void *l3x_entry)
   1772 {
   1773     uint32 *buf_p;                /* HW buffer address.       */ 
   1774     int mcast;                    /* Entry is multicast flag. */ 
   1775     int ipv6;                     /* Entry is IPv6 flag.      */
   1776     int idx;                      /* Iterator index.          */
   1777     soc_field_t hitf[] = { HIT_0f, HIT_1f, HIT_2f, HIT_3f };
   1778 
   1779     /* Input parameters check */
   1780     if ((NULL == l3cfg) || (NULL == l3x_entry)) {
   1781         return (BCM_E_PARAM);
   1782     }
   1783 
   1784     /* Get entry type. */
   1785     ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6);
   1786     mcast = (l3cfg->l3c_flags & BCM_L3_IPMC);
   1787 
   1788     /* Init memory pointers. */ 
   1789     buf_p = (uint32 *)l3x_entry;
   1790 
   1791     /* If entry was not hit  there is nothing to clear */
   1792     if (!(l3cfg->l3c_flags & BCM_L3_HIT)) {
   1793         return (BCM_E_NONE);
   1794     }
   1795 
   1796     /* Reset entry hit bit in hw. */
   1797     if (ipv6 && mcast) {
   1798         /* IPV6 multicast entry hit reset. */
   1799         for (idx = 1; idx < 4; idx++) {
   1800             soc_mem_field32_set(unit, mem, buf_p, hitf[idx], 0);
   1801         }
   1802     } else if (ipv6 || mcast) {
   1803         /* Reset IPV6 unicast  hit bit. */
   1804         for (idx = 1; idx < 2; idx++) {
   1805             soc_mem_field32_set(unit, mem, buf_p, hitf[idx], 0);
   1806         }
   1807     }
   1808 
   1809     /* Reset hit bit. */
   1810     soc_mem_field32_set(unit, mem, buf_p, hitf[0], 0);
   1811 
   1812     /* Write entry back to hw. */
   1813     return BCM_XGS3_MEM_WRITE(unit, mem, l3cfg->l3c_hw_index, buf_p);
   1814 }
   1815 
   1816 /*
   1817  * Function:
   1818  *      _bcm_tr_l3_ipmc_ent_init
   1819  * Purpose:
   1820  *      Set GROUP/SOURCE/VID/IMPC flag in the entry.
   1821  * Parameters:
   1822  *      unit      - (IN)SOC unit number.
   1823  *      l3x_entry - (IN/OUT) IPMC entry to fill. 
   1824  *      l3cfg     - (IN) Api IPMC data. 
   1825  * Returns:
   1826  *    BCM_E_XXX
   1827  */
   1828 void
   1829 _bcm_tr_l3_ipmc_ent_init(int unit, uint32 *buf_p,
   1830                              _bcm_l3_cfg_t *l3cfg)
   1831 {
   1832     soc_mem_t mem;                     /* IPMC table memory.    */
   1833     int ipv6;                          /* IPv6 entry indicator. */
   1834     int idx;                           /* Iteration index.      */
   1835     soc_field_t typef[] = { KEY_TYPE_0f, KEY_TYPE_1f, 
   1836                             KEY_TYPE_2f, KEY_TYPE_3f };
   1837     soc_field_t validf[] = { VALID_0f, VALID_1f, VALID_2f, VALID_3f };
   1838 
   1839     /* Get entry type. */
   1840     ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6);
   1841 
   1842     /* Get table memory. */
   1843     mem =  (ipv6) ? L3_ENTRY_IPV6_MULTICASTm : L3_ENTRY_IPV4_MULTICASTm;
   1844     sal_memset(buf_p, 0, (ipv6) ?  BCM_XGS3_L3_ENT_SZ(unit, ipmc_v6) : \
   1845                                    BCM_XGS3_L3_ENT_SZ(unit, ipmc_v4));
   1846     if (ipv6) {
   1847         /* Set group address. */
   1848         soc_mem_ip6_addr_set(unit, mem, buf_p, GROUP_IP_ADDR_LWR_64f,
   1849                              l3cfg->l3c_ip6, SOC_MEM_IP6_LOWER_ONLY);
   1850         l3cfg->l3c_ip6[0] = 0x0;    /* Don't write ff entry already mcast. */
   1851         soc_mem_ip6_addr_set(unit, mem, buf_p, GROUP_IP_ADDR_UPR_56f, 
   1852                              l3cfg->l3c_ip6, SOC_MEM_IP6_UPPER_ONLY);
   1853         l3cfg->l3c_ip6[0] = 0xff;    /* Restore The entry  */
   1854 
   1855         /* Set source  address. */
   1856         soc_mem_ip6_addr_set(unit, mem, buf_p, SOURCE_IP_ADDR_LWR_64f, 
   1857                              l3cfg->l3c_sip6, SOC_MEM_IP6_LOWER_ONLY);
   1858         soc_mem_ip6_addr_set(unit, mem, buf_p, SOURCE_IP_ADDR_UPR_64f, 
   1859                              l3cfg->l3c_sip6, SOC_MEM_IP6_UPPER_ONLY);
   1860 
   1861         for (idx = 0; idx < 4; idx++) {
   1862             /* Set key type */
   1863             soc_mem_field32_set(unit, mem, buf_p, typef[idx], 
   1864                                 TR_L3_HASH_KEY_TYPE_V6MC);
   1865 
   1866             /* Set entry valid bit. */
   1867             soc_mem_field32_set(unit, mem, buf_p, validf[idx], 1);
   1868 
   1869         }
   1870     } else {
   1871         /* Set group id. */
   1872         soc_mem_field32_set(unit, mem, buf_p, GROUP_IP_ADDRf,
   1873                             l3cfg->l3c_ip_addr);
   1874 
   1875         /* Set source address. */
   1876         soc_mem_field32_set(unit, mem, buf_p, SOURCE_IP_ADDRf,
   1877                             l3cfg->l3c_src_ip_addr);
   1878 
   1879         for (idx = 0; idx < 2; idx++) {
   1880             /* Set key type */
   1881             soc_mem_field32_set(unit, mem, buf_p, typef[idx], 
   1882                                 TR_L3_HASH_KEY_TYPE_V4MC);
   1883 
   1884             /* Set entry valid bit. */
   1885             soc_mem_field32_set(unit, mem, buf_p, validf[idx], 1);
   1886         }
   1887     }
   1888 
   1889     /* Set vlan id or L3_IIF. */
   1890 #ifdef BCM_GREYHOUND2_SUPPORT
   1891     /*
   1892      * Since Greyhound2 B0 increase field IPMC_L3_IIFf in L3_IIFm, which
   1893      * the IPMC "L3_IIF" lookup will compare with the L3_IIF field instead of VLAN.
   1894      */
   1895     if (SOC_IS_GREYHOUND2(unit) && SOC_MEM_FIELD_VALID(unit, L3_IIFm,
   1896                                                        IPMC_L3_IIFf)) {
   1897         if (l3cfg->l3c_ing_intf > 0) {
   1898             if (l3cfg->l3c_ing_intf > soc_mem_index_count(unit, L3_IIFm)) {
   1899                 LOG_ERROR(BSL_LS_BCM_L3,
   1900                           (BSL_META_U(
   1901                             unit,
   1902                             "Mem L3_IIF Entry %d exceed maximum index=(%d)\n"),
   1903                             l3cfg->l3c_ing_intf,
   1904                             soc_mem_index_count(unit, L3_IIFm)));
   1905                 return;
   1906             }
   1907             soc_mem_field32_set(unit, mem, buf_p, L3_IIFf, l3cfg->l3c_ing_intf);
   1908         } else if (l3cfg->l3c_vid < 4096) {
   1909             soc_mem_field32_set(unit, mem, buf_p, VLAN_IDf, l3cfg->l3c_vid);
   1910         } else if (soc_mem_field_valid(unit, mem, L3_IIFf)) {
   1911             soc_mem_field32_set(unit, mem, buf_p, L3_IIFf, l3cfg->l3c_vid);
   1912         }
   1913     } else
   1914 #endif /* BCM_GREYHOUND2_SUPPORT */
   1915     {
   1916         if (l3cfg->l3c_vid < 4096) {
   1917             soc_mem_field32_set(unit, mem, buf_p, VLAN_IDf, l3cfg->l3c_vid);
   1918         } else if (!(SOC_IS_METROLITE(unit)) && soc_mem_field_valid(unit, mem,
   1919                                                                     L3_IIFf)) {
   1920             soc_mem_field32_set(unit, mem, buf_p, L3_IIFf, l3cfg->l3c_vid);
   1921         }
   1922     }
   1923 
   1924     /* Set virtual router id. */
   1925     if (SOC_MEM_FIELD_VALID(unit, mem, VRF_IDf)) {
   1926         soc_mem_field32_set(unit, mem, buf_p, VRF_IDf, l3cfg->l3c_vrf);
   1927     }
   1928     return;
   1929 }
   1930 
   1931 /*
   1932  * Function:
   1933  *      _bcm_tr_l3_ipmc_ent_parse
   1934  * Purpose:
   1935  *      Service routine used to parse hw l3 ipmc entry to api format.
   1936  * Parameters:
   1937  *      unit      - (IN)SOC unit number. 
   1938  *      l3cfg     - (IN/OUT)l3 entry parsing destination buf.
   1939  *      l3x_entry - (IN/OUT)hw buffer.
   1940  * Returns:
   1941  *      void
   1942  */
   1943 STATIC INLINE void
   1944 _bcm_tr_l3_ipmc_ent_parse(int unit, _bcm_l3_cfg_t *l3cfg,
   1945                           l3_entry_ipv6_multicast_entry_t *l3x_entry)
   1946 {
   1947     soc_mem_t mem;                     /* IPMC table memory.    */
   1948     uint32 *buf_p;                     /* HW buffer address.    */
   1949     int ipv6;                          /* IPv6 entry indicator. */
   1950     int idx;                           /* Iteration index.      */
   1951     soc_field_t hitf[] = {HIT_1f, HIT_2f, HIT_3f };
   1952 
   1953     buf_p = (uint32 *)l3x_entry;
   1954 
   1955     /* Get entry type. */
   1956     ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6);
   1957 
   1958     /* Get table memory. */
   1959     mem =  (ipv6) ? L3_ENTRY_IPV6_MULTICASTm : L3_ENTRY_IPV4_MULTICASTm;
   1960 
   1961     /* Mark entry as multicast & clear rest of the flags. */
   1962     l3cfg->l3c_flags = BCM_L3_IPMC;
   1963     if (ipv6) {
   1964        l3cfg->l3c_flags |= BCM_L3_IP6;
   1965     }
   1966 
   1967     /* Read hit value. */
   1968     if(soc_mem_field32_get(unit, mem, buf_p, HIT_0f)) { 
   1969         l3cfg->l3c_flags |= BCM_L3_HIT;
   1970     } else if (ipv6) {
   1971         /* Get hit bit. */
   1972         for (idx = 0; idx < 3; idx++) {
   1973             if(soc_mem_field32_get(unit, mem, buf_p, hitf[idx])) { 
   1974                 l3cfg->l3c_flags |= BCM_L3_HIT;
   1975                 break;
   1976             }
   1977         }
   1978     }
   1979 
   1980     /* Set ipv6 group address to multicast. */
   1981     if (ipv6) {
   1982         l3cfg->l3c_ip6[0] = 0xff;   /* Set entry ip to mcast address. */
   1983     }
   1984 
   1985     /* Read priority override */
   1986     if(soc_mem_field32_get(unit, mem, buf_p, RPEf)) { 
   1987         l3cfg->l3c_flags |= BCM_L3_RPE;
   1988     }
   1989 
   1990     /* Read destination discard bit. */
   1991     if(soc_mem_field32_get(unit, mem, buf_p, DST_DISCARDf)) { 
   1992         l3cfg->l3c_flags |= BCM_L3_DST_DISCARD;
   1993     }
   1994 
   1995     /* Read Virtual Router Id. */
   1996     if(!(SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit))) { 
   1997         l3cfg->l3c_vrf = soc_mem_field32_get(unit, mem, buf_p, VRF_IDf);
   1998     }
   1999 
   2000     /* Pointer to ipmc replication table. */
   2001     l3cfg->l3c_ipmc_ptr = soc_mem_field32_get(unit, mem, buf_p, L3MC_INDEXf);
   2002 
   2003     /* Classification lookup class id. */
   2004     l3cfg->l3c_lookup_class = soc_mem_field32_get(unit, mem, buf_p, CLASS_IDf);
   2005 
   2006     /* Read priority value. */
   2007     l3cfg->l3c_prio = soc_mem_field32_get(unit, mem, buf_p, PRIf);
   2008     return;
   2009 }
   2010 
   2011 /*
   2012  * Function:
   2013  *      _bcm_tr_l3_ipmc_get
   2014  * Purpose:
   2015  *      Get l3 multicast entry.
   2016  * Parameters:
   2017  *      unit      - (IN)SOC unit number.
   2018  *      l3cfg     - (IN/OUT)Group/Source key & Get result buffer.
   2019  * Returns:
   2020  *    BCM_E_XXX
   2021  */
   2022 int
   2023 _bcm_tr_l3_ipmc_get(int unit, _bcm_l3_cfg_t *l3cfg)
   2024 {
   2025     l3_entry_ipv6_multicast_entry_t l3x_key;    /* Lookup key buffer.    */
   2026     l3_entry_ipv6_multicast_entry_t l3x_entry;  /* Search result buffer. */
   2027     int clear_hit;                              /* Clear hit flag.       */
   2028     soc_mem_t mem;                              /* IPMC table memory.    */
   2029     int ipv6;                                   /* IPv6 entry indicator. */
   2030     int rv;                                     /* Return value.         */
   2031 
   2032     /* Get entry type. */
   2033     ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6);
   2034 
   2035     /* Get table memory. */
   2036     mem =  (ipv6) ? L3_ENTRY_IPV6_MULTICASTm : L3_ENTRY_IPV4_MULTICASTm;
   2037 
   2038     /*  Zero buffers. */
   2039     sal_memcpy(&l3x_key, soc_mem_entry_null(unit, mem), 
   2040                    soc_mem_entry_words(unit,mem) * 4);
   2041     sal_memcpy(&l3x_entry, soc_mem_entry_null(unit, mem), 
   2042                    soc_mem_entry_words(unit,mem) * 4);
   2043 
   2044     /* Check if clear hit bit is required. */
   2045     clear_hit = l3cfg->l3c_flags & BCM_L3_HIT_CLEAR;
   2046 
   2047     /* Lookup Key preparation. */
   2048     _bcm_tr_l3_ipmc_ent_init(unit, (uint32 *)&l3x_key, l3cfg);
   2049 
   2050     /* Perform hw lookup. */
   2051     MEM_LOCK(unit, mem);
   2052     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l3cfg->l3c_hw_index,
   2053                         &l3x_key, &l3x_entry, 0);
   2054     MEM_UNLOCK(unit, mem);
   2055     BCM_XGS3_LKUP_IF_ERROR_RETURN(rv, BCM_E_NOT_FOUND);
   2056 
   2057 #ifdef BCM_TRIDENT_SUPPORT
   2058     if (SOC_IS_TRIDENT(unit)) {
   2059         soc_mem_t mem_y;
   2060         l3_entry_ipv6_multicast_entry_t l3x_entry_y;
   2061         uint32 hit;
   2062         mem_y = ipv6 ? L3_ENTRY_IPV6_MULTICAST_Ym : L3_ENTRY_IPV4_MULTICAST_Ym;
   2063         BCM_IF_ERROR_RETURN
   2064             (BCM_XGS3_MEM_READ(unit, mem_y, l3cfg->l3c_hw_index,
   2065                                &l3x_entry_y));
   2066         hit = soc_mem_field32_get(unit, mem, &l3x_entry, HIT_0f);
   2067         hit |= soc_mem_field32_get(unit, mem_y, &l3x_entry_y, HIT_0f);
   2068         soc_mem_field32_set(unit, mem, &l3x_entry, HIT_0f, hit);
   2069         hit = soc_mem_field32_get(unit, mem, &l3x_entry, HIT_1f);
   2070         hit |= soc_mem_field32_get(unit, mem_y, &l3x_entry_y, HIT_1f);
   2071         soc_mem_field32_set(unit, mem, &l3x_entry, HIT_1f, hit);
   2072         if (ipv6) {
   2073             hit = soc_mem_field32_get(unit, mem, &l3x_entry, HIT_2f);
   2074             hit |= soc_mem_field32_get(unit, mem_y, &l3x_entry_y, HIT_2f);
   2075             soc_mem_field32_set(unit, mem, &l3x_entry, HIT_2f, hit);
   2076             hit = soc_mem_field32_get(unit, mem, &l3x_entry, HIT_3f);
   2077             hit |= soc_mem_field32_get(unit, mem_y, &l3x_entry_y, HIT_3f);
   2078             soc_mem_field32_set(unit, mem, &l3x_entry, HIT_3f, hit);
   2079         }
   2080     }
   2081 #endif /* BCM_TRIDENT_SUPPORT */
   2082 
   2083     /* Extract buffer information. */
   2084     _bcm_tr_l3_ipmc_ent_parse(unit, l3cfg, &l3x_entry);
   2085 
   2086     /* Clear the HIT bit */
   2087     if (clear_hit) {
   2088         BCM_IF_ERROR_RETURN(_bcm_tr_l3_clear_hit(unit, mem, l3cfg, &l3x_entry));
   2089     }
   2090     return rv;
   2091 }
   2092 
   2093 /*
   2094  * Function:
   2095  *      _bcm_tr_l3_ipmc_add
   2096  * Purpose:
   2097  *      Add l3 multicast entry.
   2098  * Parameters:
   2099  *      unit      - (IN)SOC unit number.
   2100  *      l3cfg     - (IN/OUT)Group/Source key.
   2101  * Returns:
   2102  *    BCM_E_XXX
   2103  */
   2104 int
   2105 _bcm_tr_l3_ipmc_add(int unit, _bcm_l3_cfg_t *l3cfg)
   2106 {
   2107     l3_entry_ipv6_multicast_entry_t l3x_entry;  /* Write entry buffer.   */
   2108     soc_mem_t mem;                              /* IPMC table memory.    */
   2109     uint32 *buf_p;                              /* HW buffer address.    */
   2110     int ipv6;                                   /* IPv6 entry indicator. */
   2111     int idx;                                    /* Iteration index.      */
   2112     int idx_max;                                /* Iteration index max.  */
   2113     int rv;                                     /* Return value.         */
   2114     soc_field_t hitf[] = { HIT_0f, HIT_1f, HIT_2f, HIT_3f };
   2115 
   2116     /* Get entry type. */
   2117     ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6);
   2118 
   2119     /* Get table memory. */
   2120     mem =  (ipv6) ? L3_ENTRY_IPV6_MULTICASTm : L3_ENTRY_IPV4_MULTICASTm;
   2121 
   2122     /*  Zero buffers. */
   2123     buf_p = (uint32 *)&l3x_entry; 
   2124     sal_memcpy(buf_p, soc_mem_entry_null(unit, mem), 
   2125                    soc_mem_entry_words(unit,mem) * 4);
   2126 
   2127    /* Prepare entry to write. */
   2128     _bcm_tr_l3_ipmc_ent_init(unit, (uint32 *)&l3x_entry, l3cfg);
   2129 
   2130     /* Set priority override bit. */
   2131     if (l3cfg->l3c_flags & BCM_L3_RPE) {
   2132         soc_mem_field32_set(unit, mem, buf_p, RPEf, 1);
   2133     }
   2134 
   2135     /* Set destination discard. */
   2136     if (l3cfg->l3c_flags & BCM_L3_DST_DISCARD) {
   2137         soc_mem_field32_set(unit, mem, buf_p, DST_DISCARDf, 1);
   2138     }
   2139 	
   2140     if(!(SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit))) { 
   2141         /* Virtual router id. */
   2142         soc_mem_field32_set(unit, mem, buf_p, VRF_IDf, l3cfg->l3c_vrf);
   2143     }	
   2144 
   2145     /* Set priority. */
   2146     soc_mem_field32_set(unit, mem, buf_p, PRIf, l3cfg->l3c_prio);
   2147 
   2148     /* Pointer to ipmc table. */
   2149     soc_mem_field32_set(unit, mem, buf_p, L3MC_INDEXf, l3cfg->l3c_ipmc_ptr);
   2150 
   2151     /* Classification lookup class id. */
   2152     soc_mem_field32_set(unit, mem, buf_p, CLASS_IDf, l3cfg->l3c_lookup_class);
   2153 
   2154     idx_max = (ipv6) ? 4 : 2;
   2155     for (idx = 0; idx < idx_max; idx++) {
   2156         /* Set hit bit. */
   2157         if (l3cfg->l3c_flags & BCM_L3_HIT) {
   2158             soc_mem_field32_set(unit, mem, buf_p, hitf[idx], 1);
   2159         }
   2160     }
   2161 
   2162     /* Write entry to the hw. */
   2163     MEM_LOCK(unit, mem);
   2164     /* Handle replacement. */
   2165     if (BCM_XGS3_L3_INVALID_INDEX != l3cfg->l3c_hw_index) {
   2166         rv = BCM_XGS3_MEM_WRITE(unit, mem, l3cfg->l3c_hw_index, buf_p);
   2167     } else {
   2168         rv = soc_mem_insert(unit, mem, MEM_BLOCK_ANY, (void *)buf_p);
   2169     }
   2170 
   2171     /* Increment number of ipmc routes. */
   2172     if (BCM_SUCCESS(rv) && (BCM_XGS3_L3_INVALID_INDEX == l3cfg->l3c_hw_index)) {
   2173         (ipv6) ? BCM_XGS3_L3_IP6_IPMC_CNT(unit)++ : \
   2174                  BCM_XGS3_L3_IP4_IPMC_CNT(unit)++;
   2175     }
   2176     /*    coverity[overrun-local : FALSE]    */
   2177     MEM_UNLOCK(unit, mem);
   2178     return rv;
   2179 }
   2180 
   2181 /*
   2182  * Function:
   2183  *      _bcm_tr_l3_ipmc_del
   2184  * Purpose:
   2185  *      Delete l3 multicast entry.
   2186  * Parameters:
   2187  *      unit      - (IN)SOC unit number.
   2188  *      l3cfg     - (IN)Group/Source deletion key.
   2189  * Returns:
   2190  *    BCM_E_XXX
   2191  */
   2192 int
   2193 _bcm_tr_l3_ipmc_del(int unit, _bcm_l3_cfg_t *l3cfg)
   2194 {
   2195     l3_entry_ipv6_multicast_entry_t l3x_entry;  /* Delete buffer.          */
   2196     soc_mem_t mem;                              /* IPMC table memory.      */
   2197     int ipv6;                                   /* IPv6 entry indicator.   */
   2198     int rv;                                     /* Operation return value. */
   2199 
   2200     /* Get entry type. */
   2201     ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6);
   2202 
   2203     /* Get table memory. */
   2204     mem =  (ipv6) ? L3_ENTRY_IPV6_MULTICASTm : L3_ENTRY_IPV4_MULTICASTm;
   2205 
   2206     /*  Zero entry buffer. */
   2207     sal_memcpy(&l3x_entry, soc_mem_entry_null(unit, mem), 
   2208                soc_mem_entry_words(unit,mem) * 4);
   2209 
   2210 
   2211     /* Key preparation. */
   2212     _bcm_tr_l3_ipmc_ent_init(unit, (uint32 *)&l3x_entry, l3cfg);
   2213 
   2214     /* Delete the entry from hw. */
   2215     MEM_LOCK(unit, mem);
   2216 
   2217     rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, (void *)&l3x_entry);
   2218 
   2219     /* Decrement number of ipmc routes. */
   2220     if (BCM_SUCCESS(rv)) {
   2221         (ipv6) ? BCM_XGS3_L3_IP6_IPMC_CNT(unit)-- : \
   2222             BCM_XGS3_L3_IP4_IPMC_CNT(unit)--;
   2223     }
   2224     MEM_UNLOCK(unit, mem);
   2225     return rv;
   2226 }
   2227 
   2228 /*
   2229  * Function:
   2230  *      _bcm_tr_l3_ipmc_get_by_idx
   2231  * Purpose:
   2232  *      Get l3 multicast entry by entry index.
   2233  * Parameters:
   2234  *      unit      - (IN)SOC unit number.
   2235  *      dma_ptr  - (IN)Table pointer in dma. 
   2236  *      idx       - (IN)Index to read. 
   2237  *      l3cfg     - (IN/OUT)Entry data.
   2238  * Returns:
   2239  *    BCM_E_XXX
   2240  */
   2241 int
   2242 _bcm_tr_l3_ipmc_get_by_idx(int unit, void *dma_ptr,
   2243                            int idx, _bcm_l3_cfg_t *l3cfg)
   2244 {
   2245     l3_entry_ipv6_multicast_entry_t *l3x_entry_p; /* Read buffer address.    */
   2246     l3_entry_ipv6_multicast_entry_t l3x_entry;    /* Read buffer.            */
   2247     soc_mem_t mem;                                /* IPMC table memory.      */
   2248     uint32 ipv6;                                  /* IPv6 entry indicator.   */
   2249     int clear_hit;                                /* Clear hit bit indicator.*/
   2250     int key_type;
   2251 
   2252     /* Get entry type. */
   2253     ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6);
   2254 
   2255     /* Get table memory. */
   2256     mem =  (ipv6) ? L3_ENTRY_IPV6_MULTICASTm : L3_ENTRY_IPV4_MULTICASTm;
   2257 
   2258     /* Check if clear hit is required. */
   2259     clear_hit = l3cfg->l3c_flags & BCM_L3_HIT_CLEAR;
   2260 
   2261     if (NULL == dma_ptr) {             /* Read from hardware. */
   2262         /* Zero buffers. */
   2263         l3x_entry_p = &l3x_entry;
   2264         sal_memcpy(l3x_entry_p, soc_mem_entry_null(unit, mem), 
   2265                    soc_mem_entry_words(unit,mem) * 4);
   2266 
   2267         /* Read entry from hw. */
   2268         BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, mem, idx, l3x_entry_p));
   2269     } else {                    /* Read from dma. */
   2270         l3x_entry_p =
   2271             soc_mem_table_idx_to_pointer(unit, mem,
   2272                                          l3_entry_ipv6_multicast_entry_t *,
   2273                                          dma_ptr, idx);
   2274     }
   2275 #ifdef BCM_TRIDENT_SUPPORT
   2276     if (SOC_IS_TRIDENT(unit)) {
   2277         soc_mem_t mem_y;
   2278         l3_entry_ipv6_multicast_entry_t l3x_entry_y;
   2279         uint32 hit;
   2280         mem_y = ipv6 ? L3_ENTRY_IPV6_MULTICAST_Ym : L3_ENTRY_IPV4_MULTICAST_Ym;
   2281         BCM_IF_ERROR_RETURN
   2282             (BCM_XGS3_MEM_READ(unit, mem_y, idx, &l3x_entry_y));
   2283         hit = soc_mem_field32_get(unit, mem, l3x_entry_p, HIT_0f);
   2284         hit |= soc_mem_field32_get(unit, mem_y, &l3x_entry_y, HIT_0f);
   2285         soc_mem_field32_set(unit, mem, l3x_entry_p, HIT_0f, hit);
   2286         hit = soc_mem_field32_get(unit, mem, l3x_entry_p, HIT_1f);
   2287         hit |= soc_mem_field32_get(unit, mem_y, &l3x_entry_y, HIT_1f);
   2288         soc_mem_field32_set(unit, mem, l3x_entry_p, HIT_1f, hit);
   2289         if (ipv6) {
   2290             hit = soc_mem_field32_get(unit, mem, l3x_entry_p, HIT_2f);
   2291             hit |= soc_mem_field32_get(unit, mem_y, &l3x_entry_y, HIT_2f);
   2292             soc_mem_field32_set(unit, mem, l3x_entry_p, HIT_2f, hit);
   2293             hit = soc_mem_field32_get(unit, mem, l3x_entry_p, HIT_3f);
   2294             hit |= soc_mem_field32_get(unit, mem_y, &l3x_entry_y, HIT_3f);
   2295             soc_mem_field32_set(unit, mem, l3x_entry_p, HIT_3f, hit);
   2296         }
   2297     }
   2298 #endif /* BCM_TRIDENT_SUPPORT */
   2299 
   2300     /* Ignore invalid entries. */
   2301     if (!soc_mem_field32_get(unit, mem, l3x_entry_p, VALID_0f)) {
   2302         return (BCM_E_NOT_FOUND);
   2303     }
   2304 
   2305 
   2306     key_type = soc_mem_field32_get(unit, L3_ENTRY_ONLYm,
   2307                                    l3x_entry_p, KEY_TYPEf);
   2308 
   2309     switch (key_type) {
   2310       case TR_L3_HASH_KEY_TYPE_V4MC:
   2311           l3cfg->l3c_flags = BCM_L3_IPMC;
   2312           break;
   2313       case TR_L3_HASH_KEY_TYPE_V6UC:
   2314           l3cfg->l3c_flags = BCM_L3_IP6;
   2315           break;
   2316       case TR_L3_HASH_KEY_TYPE_V6MC:
   2317           l3cfg->l3c_flags = BCM_L3_IP6 | BCM_L3_IPMC;
   2318           break;
   2319       default:
   2320           /* Catch all other key types, set flags to zero so that the 
   2321            * following flag check is effective for all key types */
   2322           l3cfg->l3c_flags = 0;  
   2323           break;
   2324     }
   2325 
   2326     /* Ignore protocol mismatch & multicast entries. */
   2327     if ((ipv6  != (l3cfg->l3c_flags & BCM_L3_IP6)) ||
   2328         (!(l3cfg->l3c_flags & BCM_L3_IPMC))) {
   2329         return (BCM_E_NOT_FOUND);
   2330     }
   2331 
   2332     /* Set index to l3cfg. */
   2333     l3cfg->l3c_hw_index = idx;
   2334 
   2335     if (ipv6) {
   2336         /* Get group address. */
   2337         soc_mem_ip6_addr_get(unit, mem, l3x_entry_p, GROUP_IP_ADDR_LWR_64f,
   2338                              l3cfg->l3c_ip6, SOC_MEM_IP6_LOWER_ONLY);
   2339 
   2340         soc_mem_ip6_addr_get(unit, mem, l3x_entry_p, GROUP_IP_ADDR_UPR_56f,
   2341                              l3cfg->l3c_ip6, SOC_MEM_IP6_UPPER_ONLY);
   2342 
   2343         /* Get source  address. */
   2344         soc_mem_ip6_addr_get(unit, mem, l3x_entry_p, SOURCE_IP_ADDR_LWR_64f, 
   2345                              l3cfg->l3c_sip6, SOC_MEM_IP6_LOWER_ONLY);
   2346         soc_mem_ip6_addr_get(unit, mem, l3x_entry_p, SOURCE_IP_ADDR_UPR_64f, 
   2347                              l3cfg->l3c_sip6, SOC_MEM_IP6_UPPER_ONLY);
   2348 
   2349         l3cfg->l3c_ip6[0] = 0xff;    /* Set entry to multicast*/
   2350     } else {
   2351         /* Get group id. */
   2352         l3cfg->l3c_ip_addr =
   2353             soc_mem_field32_get(unit, mem, l3x_entry_p, GROUP_IP_ADDRf);
   2354 
   2355         /* Get source address. */
   2356         l3cfg->l3c_src_ip_addr =
   2357             soc_mem_field32_get(unit, mem,  l3x_entry_p, SOURCE_IP_ADDRf);
   2358     }
   2359 
   2360     /* Get L3_IIF or vlan id. */
   2361     if (!(SOC_IS_METROLITE(unit)) && soc_mem_field_valid(unit, mem, L3_IIFf)) {
   2362         l3cfg->l3c_vid = soc_mem_field32_get(unit, mem, l3x_entry_p, L3_IIFf);
   2363     } else {
   2364         l3cfg->l3c_vid = soc_mem_field32_get(unit, mem, l3x_entry_p, VLAN_IDf);
   2365     }
   2366 
   2367     /* Parse entry data. */
   2368     _bcm_tr_l3_ipmc_ent_parse(unit, l3cfg, l3x_entry_p);
   2369 
   2370     /* Clear the HIT bit */
   2371     if (clear_hit) {
   2372         BCM_IF_ERROR_RETURN(_bcm_tr_l3_clear_hit(unit, mem, l3cfg, l3x_entry_p));
   2373     }
   2374     return (BCM_E_NONE);
   2375 }
   2376 
   2377 /*
   2378  * Function:
   2379  *      _bcm_tr_l3_intf_mtu_set
   2380  * Purpose:
   2381  *      Set  L3 interface MTU value. 
   2382  * Parameters:
   2383  *      unit      - (IN)SOC unit number.
   2384  *      intf_info - (IN)Interface information.
   2385  * Returns:
   2386  *      BCM_E_XXX
   2387  */
   2388 int
   2389 _bcm_tr_l3_intf_mtu_set(int unit, _bcm_l3_intf_cfg_t *intf_info)
   2390 {
   2391     mtu_values_entry_t mtu_value_buf;  /* Buffer to write mtu. */
   2392     uint32  *mtu_value_buf_p;          /* Write buffer address.*/
   2393     void *null_entry = soc_mem_entry_null(unit, L3_MTU_VALUESm);
   2394     int  mtu_index;
   2395     int  interface_map_mode = 0;
   2396 
   2397     /* Input parameters check */
   2398     if (NULL == intf_info) {
   2399         return (BCM_E_PARAM);
   2400     }
   2401     
   2402     if (soc_feature(unit, soc_feature_l3_ingress_interface)) {
   2403       BCM_IF_ERROR_RETURN(
   2404           bcm_xgs3_l3_ingress_intf_map_get(unit, &interface_map_mode));
   2405     }
   2406     /* coverity[dead_error_begin : FALSE] */
   2407     if(!SOC_MEM_FIELD32_VALUE_FIT(unit, L3_MTU_VALUESm, 
   2408                                   MTU_SIZEf, intf_info->l3i_mtu)) {
   2409         return (BCM_E_PARAM);
   2410     }
   2411     if ((!BCM_XGS3_L3_INTF_VLAN_SPLIT_EGRESS_MODE_ISSET(unit)) && 
   2412         (BCM_VLAN_VALID(intf_info->l3i_vid)) && !interface_map_mode) {
   2413 
   2414         if ((intf_info->l3i_vid < soc_mem_index_min(unit, L3_MTU_VALUESm)) || 
   2415             (intf_info->l3i_vid > soc_mem_index_max(unit, L3_MTU_VALUESm))) {
   2416             return (BCM_E_PARAM);
   2417         }
   2418     } else {
   2419         if ((intf_info->l3i_index < soc_mem_index_min(unit, L3_MTU_VALUESm)) || 
   2420             (intf_info->l3i_index > soc_mem_index_max(unit, L3_MTU_VALUESm))) {
   2421             return (BCM_E_PARAM);
   2422         }
   2423     }
   2424 
   2425     /* Reset the buffer to default value. */
   2426     mtu_value_buf_p = (uint32 *)&mtu_value_buf;
   2427     sal_memcpy(mtu_value_buf_p, null_entry, sizeof(mtu_values_entry_t));
   2428 
   2429     if (soc_feature(unit, soc_feature_l3_mtu_size_default) &&
   2430             intf_info->l3i_mtu == 0) {
   2431         intf_info->l3i_mtu =
   2432             (1 << soc_mem_field_length(unit, L3_MTU_VALUESm, MTU_SIZEf)) - 1;
   2433     }
   2434 
   2435     if (intf_info->l3i_mtu) {
   2436         /* Set mtu. */
   2437         soc_mem_field32_set(unit, L3_MTU_VALUESm, mtu_value_buf_p, 
   2438                             MTU_SIZEf, intf_info->l3i_mtu);
   2439     }
   2440     if (!BCM_XGS3_L3_INTF_VLAN_SPLIT_EGRESS_MODE_ISSET(unit)) {
   2441         if (!interface_map_mode) {
   2442             mtu_index = intf_info->l3i_vid;
   2443         } else {
   2444             mtu_index = intf_info->l3i_index;
   2445         }
   2446         return BCM_XGS3_MEM_WRITE(unit, L3_MTU_VALUESm,
   2447                             mtu_index, mtu_value_buf_p);
   2448     } else {
   2449         /* MTU index to be based on L3 IIF Index */
   2450         return BCM_XGS3_MEM_WRITE(unit, L3_MTU_VALUESm, 
   2451                                   intf_info->l3i_index, mtu_value_buf_p);
   2452     }
   2453 }
   2454 
   2455 /*
   2456  * Function:
   2457  *      _bcm_tr_l3_intf_mtu_get
   2458  * Purpose:
   2459  *      Get  L3 interface MTU value. 
   2460  * Parameters:
   2461  *      unit      - (IN)SOC unit number.
   2462  *      intf_info - (IN/OUT)Interface information with updated mtu.
   2463  * Returns:
   2464  *      BCM_E_XXX
   2465  */
   2466 int
   2467 _bcm_tr_l3_intf_mtu_get(int unit, _bcm_l3_intf_cfg_t *intf_info)
   2468 {
   2469     mtu_values_entry_t mtu_value_buf;  /* Buffer to write mtu. */
   2470     uint32  *mtu_value_buf_p;          /* Write buffer address.           */
   2471     int  mtu_index;
   2472     int  interface_map_mode = 0;
   2473 
   2474     /* Input parameters check */
   2475     if (NULL == intf_info) {
   2476         return (BCM_E_PARAM);
   2477     }
   2478 
   2479     if (soc_feature(unit, soc_feature_l3_ingress_interface)) {
   2480       BCM_IF_ERROR_RETURN(
   2481           bcm_xgs3_l3_ingress_intf_map_get(unit, &interface_map_mode));
   2482     }
   2483 
   2484     if ((!BCM_XGS3_L3_INTF_VLAN_SPLIT_EGRESS_MODE_ISSET(unit)) && 
   2485         (BCM_VLAN_VALID(intf_info->l3i_vid)) && !interface_map_mode) {
   2486 
   2487         if ((intf_info->l3i_vid < soc_mem_index_min(unit, L3_MTU_VALUESm)) || 
   2488             (intf_info->l3i_vid > soc_mem_index_max(unit, L3_MTU_VALUESm))) {
   2489             return (BCM_E_PARAM);
   2490         }
   2491     } else {
   2492         if ((intf_info->l3i_index < soc_mem_index_min(unit, L3_MTU_VALUESm)) || 
   2493             (intf_info->l3i_index > soc_mem_index_max(unit, L3_MTU_VALUESm))) {
   2494             return (BCM_E_PARAM);
   2495         }
   2496     }
   2497     
   2498     /* Zero the buffer. */
   2499     mtu_value_buf_p = (uint32 *)&mtu_value_buf;
   2500     sal_memset(mtu_value_buf_p, 0, sizeof(mtu_values_entry_t));
   2501     
   2502     if (!BCM_XGS3_L3_INTF_VLAN_SPLIT_EGRESS_MODE_ISSET(unit)) {
   2503         if (!interface_map_mode) {
   2504             mtu_index = intf_info->l3i_vid;
   2505         } else {
   2506             mtu_index = intf_info->l3i_index;
   2507         }
   2508         /* MTU index to be based on L3 IIF Index */
   2509         /* Read mtu table entry by index. */
   2510         BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, L3_MTU_VALUESm,
   2511                                               mtu_index, mtu_value_buf_p));
   2512     } else {
   2513         BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, L3_MTU_VALUESm,
   2514                                               intf_info->l3i_index, 
   2515                                               mtu_value_buf_p));
   2516     }
   2517     intf_info->l3i_mtu = 
   2518         soc_mem_field32_get(unit, L3_MTU_VALUESm, mtu_value_buf_p, MTU_SIZEf);
   2519 
   2520     return (BCM_E_NONE);
   2521 }
   2522 
   2523 #else /* BCM_TRIUMPH_SUPPORT && INCLUDE_L3 */
   2524 int bcm_esw_triumph_l3_not_empty;
   2525 #endif /* BCM_TRIUMPH_SUPPORT && INCLUDE_L3 */