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 (57621B)


      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:     Katana L3 function implementations
      9  */
     10 
     11 
     12 #include <soc/defs.h>
     13 
     14 #include <assert.h>
     15 #include <shared/bsl.h>
     16 #include <sal/core/libc.h>
     17 #if defined(BCM_KATANA_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/debug.h>
     31 #include <bcm/error.h>
     32 #include <bcm/stack.h>
     33 
     34 #include <bcm_int/esw/mbcm.h>
     35 #include <bcm_int/esw/firebolt.h>
     36 #include <bcm_int/esw/trx.h>
     37 #include <bcm_int/esw/katana.h>
     38 #include <bcm_int/esw/l3.h>
     39 #include <bcm_int/esw/xgs3.h>
     40 #include <bcm_int/esw_dispatch.h>
     41 
     42 
     43 _bcm_l3_defip_pair128_table_t *l3_kt_defip_pair128[BCM_MAX_NUM_UNITS];
     44 
     45 /*
     46  * Function:
     47  *      _kt_defip_pair128_hash
     48  * Purpose:
     49  *      Calculate an entry 8 bit hash.
     50  * Parameters:
     51  *      unit        - (IN)SOC unit number.
     52  *      lpm_cfg     - (IN)Buffer to fill defip information. 
     53  *      entry_hash  - (OUT)Entry hash
     54  * Returns:
     55  *      BCM_E_XXX
     56  */
     57 STATIC int
     58 _kt_defip_pair128_hash(int unit, _bcm_defip_cfg_t *lpm_cfg, uint8 *hash) 
     59 {
     60     uint32 key[BCM_KT_DEFIP_PAIR128_HASH_SZ];
     61 
     62     if (hash == NULL) {
     63         return (BCM_E_PARAM);
     64     }
     65 
     66     SAL_IP6_ADDR_TO_UINT32(lpm_cfg->defip_ip6_addr, key);
     67     key[4] = lpm_cfg->defip_sub_len;
     68     key[5] = lpm_cfg->defip_vrf;
     69 
     70     *hash = (_shr_crc16b(0, (void *)key,
     71                          WORDS2BITS((BCM_KT_DEFIP_PAIR128_HASH_SZ))) & 0xff);
     72     return (BCM_E_NONE);
     73 }
     74 
     75 #ifdef BCM_WARM_BOOT_SUPPORT
     76 /*
     77  * Function:
     78  *      _kt_defip_pair128_reinit
     79  * Purpose:
     80  *      Re-Initialize sw image for L3_DEFIP_PAIR_128 internal tcam.
     81  *      during warm boot. 
     82  * Parameters:
     83  *      unit    - (IN)SOC unit number.
     84  *      idx     - (IN)Entry index   
     85  *      lpm_cfg - (IN)Inserted entry. 
     86  * Returns:
     87  *      BCM_E_XXX
     88  */
     89 STATIC int 
     90 _kt_defip_pair128_reinit(int unit, int idx, _bcm_defip_cfg_t *lpm_cfg)
     91 {
     92     int   lkup_plen;         /* Vrf weighted lookup prefix. */
     93     uint8 hash;              /* Entry hash value.           */
     94 
     95     /* Calculate vrf weighted prefix length. */
     96     lkup_plen = lpm_cfg->defip_sub_len * 
     97         ((BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) ? 2 : 1);
     98 
     99     /* Calculate entry lookup hash. */
    100     BCM_IF_ERROR_RETURN(_kt_defip_pair128_hash(unit, lpm_cfg, &hash));
    101 
    102     /* Set software structure info. */
    103     BCM_KT_DEFIP_PAIR128_ENTRY_SET(unit, idx, lkup_plen, hash);
    104 
    105     /* Update software usage counter. */
    106     BCM_KT_DEFIP_PAIR128_USED_COUNT(unit)++;
    107 
    108     return (BCM_E_NONE);
    109 }
    110 
    111 #endif /* BCM_WARM_BOOT_SUPPORT */
    112 
    113 /*
    114  * Function:
    115  *      _bcm_kt_defip_pair128_init
    116  * Purpose:
    117  *      Initialize sw image for L3_DEFIP_PAIR_128 internal tcam.
    118  * Parameters:
    119  *      unit        - (IN)SOC unit number.
    120  * Returns:
    121  *      BCM_E_XXX
    122  */
    123 int 
    124 _bcm_kt_defip_pair128_init(int unit)
    125 {   
    126     int mem_sz;    /* Memory allocation size     */
    127     int rv;        /* Internal operation status. */
    128     soc_kt_lpm_ipv6_info_t *lpm_ipv6_info = soc_kt_lpm_ipv6_info_get(unit);
    129 
    130     if (lpm_ipv6_info->ipv6_128b.depth == 0) {
    131        /* We cannot use L3_DEFIP for storing IPv6 LPM 128b entries */
    132        return BCM_E_NONE;
    133     }
    134 
    135     /* De-allocate any existing structures. */
    136     if (BCM_KT_DEFIP_PAIR128(unit) != NULL) {
    137         rv = _bcm_kt_defip_pair128_deinit(unit);
    138         BCM_IF_ERROR_RETURN(rv);
    139     }
    140 
    141     /* Allocate cam control structure. */
    142     mem_sz = sizeof(_bcm_l3_defip_pair128_table_t);
    143     BCM_KT_DEFIP_PAIR128(unit) = sal_alloc(mem_sz, "l3_kt_defip_pair128");
    144     if (BCM_KT_DEFIP_PAIR128(unit) == NULL) {
    145         return (BCM_E_MEMORY);
    146     }
    147 
    148     /* Reset cam control structure. */
    149     sal_memset(BCM_KT_DEFIP_PAIR128(unit), 0, mem_sz);
    150 
    151     BCM_KT_DEFIP_PAIR128_TOTAL(unit) =
    152         soc_mem_index_count(unit, L3_DEFIP_PAIR_128m);
    153     BCM_KT_DEFIP_PAIR128_URPF_OFFSET(unit) =
    154         lpm_ipv6_info->ipv6_128b.sip_start_offset;
    155     BCM_KT_DEFIP_PAIR128_IDX_MAX(unit) = lpm_ipv6_info->ipv6_128b.depth - 1;
    156 
    157     mem_sz = lpm_ipv6_info->ipv6_128b.depth *
    158              sizeof(_bcm_l3_defip_pair128_entry_t);
    159     BCM_KT_DEFIP_PAIR128_ARR(unit) = 
    160                             sal_alloc(mem_sz, "l3_defip_pair128_entry_array");
    161     if (BCM_KT_DEFIP_PAIR128_ARR(unit) == NULL) {
    162         BCM_IF_ERROR_RETURN(_bcm_kt_defip_pair128_deinit(unit));
    163         return (BCM_E_MEMORY);
    164     }
    165     sal_memset(BCM_KT_DEFIP_PAIR128_ARR(unit), 0, mem_sz);
    166 
    167     return (BCM_E_NONE);
    168 }
    169 
    170 /*
    171  * Function:
    172  *      _bcm_kt_defip_pair128_deinit
    173  * Purpose:
    174  *      De-initialize sw image for L3_DEFIP_PAIR_128 internal tcam.
    175  * Parameters:
    176  *      unit        - (IN)SOC unit number.
    177  * Returns:
    178  *      BCM_E_XXX
    179  */
    180 int 
    181 _bcm_kt_defip_pair128_deinit(int unit)
    182 {
    183     uint32 ipv6_lpm_128b_enable;
    184     
    185     ipv6_lpm_128b_enable = soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 0);
    186     if (!ipv6_lpm_128b_enable) {
    187        /* We cannot use L3_DEFIP for storing IPv6 LPM 128b entries */
    188        return BCM_E_NONE;
    189     }
    190 
    191     if (BCM_KT_DEFIP_PAIR128(unit) == NULL) {
    192         return (BCM_E_NONE);
    193     }
    194 
    195     /* De-allocate any existing structures. */
    196     if (BCM_KT_DEFIP_PAIR128_ARR(unit) != NULL) {
    197         sal_free(BCM_KT_DEFIP_PAIR128_ARR(unit));
    198         BCM_KT_DEFIP_PAIR128_ARR(unit) = NULL;
    199     }
    200     sal_free(BCM_KT_DEFIP_PAIR128(unit));
    201     BCM_KT_DEFIP_PAIR128(unit) = NULL;
    202 
    203     return (BCM_E_NONE);
    204 }
    205 
    206 /*
    207  * Function:    
    208  *     _kt_defip_pair128_ip6_mask_set
    209  * Purpose:  
    210  *     Set IP6 mask field in memory from ip6 addr type. 
    211  * Parameters: 
    212  *     unit  - (IN) BCM device number. 
    213  *     mem   - (IN) Memory id.
    214  *     entry - (IN) HW entry buffer.
    215  *     ip6   - (IN) SW ip6 address buffer.
    216  * Returns:      void
    217  */
    218  
    219 void
    220 
    221 _kt_defip_pair128_ip6_mask_set(int unit, soc_mem_t mem, uint32 *entry, 
    222                                 const ip6_addr_t ip6)
    223 {
    224     uint32              ip6_field[4];
    225     ip6_field[3] = ((ip6[12] << 24)| (ip6[13] << 16) |
    226                     (ip6[14] << 8) | (ip6[15] << 0));
    227     soc_mem_field_set(unit, mem, entry, IP_ADDR_MASK0_LWRf, &ip6_field[3]);
    228     ip6_field[2] = ((ip6[8] << 24) | (ip6[9] << 16) |
    229                     (ip6[10] << 8) | (ip6[11] << 0));
    230     soc_mem_field_set(unit, mem, entry, IP_ADDR_MASK1_LWRf, &ip6_field[2]);
    231     ip6_field[1] = ((ip6[4] << 24) | (ip6[5] << 16) |
    232                     (ip6[6] << 8)  | (ip6[7] << 0));
    233     soc_mem_field_set(unit, mem, entry, IP_ADDR_MASK0_UPRf, &ip6_field[1]);
    234     ip6_field[0] = ((ip6[0] << 24) | (ip6[1] << 16) |
    235                     (ip6[2] << 8)  | (ip6[3] << 0));
    236     soc_mem_field_set(unit, mem, entry, IP_ADDR_MASK1_UPRf, ip6_field);
    237 }
    238 
    239 /*
    240  * Function:    
    241  *     _kt_defip_pair128_ip6_mask_get
    242  * Purpose:  
    243  *     Read IP6 mask field from memory field to ip6_addr_t buffer. 
    244  * Parameters: 
    245  *     unit  - (IN) BCM device number. 
    246  *     mem   - (IN) Memory id.
    247  *     entry - (IN) HW entry buffer.
    248  *     ip6   - (OUT) SW ip6 address buffer.
    249  * Returns:      void
    250  */
    251 void
    252 
    253 _kt_defip_pair128_ip6_mask_get(int unit, soc_mem_t mem, const void *entry, 
    254                                 ip6_addr_t ip6)
    255 {
    256     uint32              ip6_field[4];
    257     soc_mem_field_get(unit, mem, entry, IP_ADDR_MASK0_LWRf, (uint32 *)&ip6_field[3]);
    258     ip6[12] = (uint8) (ip6_field[3] >> 24);
    259     ip6[13] = (uint8) (ip6_field[3] >> 16 & 0xff);
    260     ip6[14] = (uint8) (ip6_field[3] >> 8 & 0xff);
    261     ip6[15] = (uint8) (ip6_field[3] & 0xff);
    262     soc_mem_field_get(unit, mem, entry, IP_ADDR_MASK1_LWRf, (uint32 *)&ip6_field[2]);
    263     ip6[8] = (uint8) (ip6_field[2] >> 24);
    264     ip6[9] = (uint8) (ip6_field[2] >> 16 & 0xff);
    265     ip6[10] = (uint8) (ip6_field[2] >> 8 & 0xff);
    266     ip6[11] = (uint8) (ip6_field[2] & 0xff);
    267     soc_mem_field_get(unit, mem, entry, IP_ADDR_MASK0_UPRf, (uint32 *)&ip6_field[1]);
    268     ip6[4] = (uint8) (ip6_field[1] >> 24);
    269     ip6[5] = (uint8) (ip6_field[1] >> 16 & 0xff);
    270     ip6[6] =(uint8) (ip6_field[1] >> 8 & 0xff);
    271     ip6[7] =(uint8) (ip6_field[1] & 0xff);
    272     soc_mem_field_get(unit, mem, entry, IP_ADDR_MASK1_UPRf, ip6_field);
    273     ip6[0] =(uint8) (ip6_field[0] >> 24);
    274     ip6[1] =(uint8) (ip6_field[0] >> 16 & 0xff);
    275     ip6[2] =(uint8) (ip6_field[0] >> 8 & 0xff);
    276     ip6[3] =(uint8) (ip6_field[0] & 0xff);
    277 }
    278 
    279 
    280 /*
    281  * Function:    
    282  *     _kt_defip_pair128_ip6_addr_set
    283  * Purpose:  
    284  *     Set IP6 address field in memory from ip6 addr type. 
    285  * Parameters: 
    286  *     unit  - (IN) BCM device number. 
    287  *     mem   - (IN) Memory id.
    288  *     entry - (IN) HW entry buffer.
    289  *     ip6   - (IN) SW ip6 address buffer.
    290  * Returns:      void
    291  */
    292 
    293 void
    294 _kt_defip_pair128_ip6_addr_set(int unit, soc_mem_t mem, uint32 *entry, 
    295                                 const ip6_addr_t ip6)
    296 {
    297     uint32              ip6_field[4];
    298     ip6_field[3] = ((ip6[12] << 24)| (ip6[13] << 16) |
    299                     (ip6[14] << 8) | (ip6[15] << 0));
    300     soc_mem_field_set(unit, mem, entry, IP_ADDR0_LWRf, &ip6_field[3]);
    301     ip6_field[2] = ((ip6[8] << 24) | (ip6[9] << 16) |
    302                     (ip6[10] << 8) | (ip6[11] << 0));
    303     soc_mem_field_set(unit, mem, entry, IP_ADDR1_LWRf, &ip6_field[2]);
    304     ip6_field[1] = ((ip6[4] << 24) | (ip6[5] << 16) |
    305                     (ip6[6] << 8)  | (ip6[7] << 0));
    306     soc_mem_field_set(unit, mem, entry, IP_ADDR0_UPRf, &ip6_field[1]);
    307     ip6_field[0] = ((ip6[0] << 24) | (ip6[1] << 16) |
    308                     (ip6[2] << 8)  | (ip6[3] << 0));
    309     soc_mem_field_set(unit, mem, entry, IP_ADDR1_UPRf, ip6_field);
    310 }
    311 
    312 /*
    313  * Function:    
    314  *     _kt_defip_pair128_ip6_addr_get
    315  * Purpose:  
    316  *     Read IP6 address field from memory field to ip6_addr_t buffer. 
    317  * Parameters: 
    318  *     unit  - (IN) BCM device number. 
    319  *     mem   - (IN) Memory id.
    320  *     entry - (IN) HW entry buffer.
    321  *     ip6   - (OUT) SW ip6 address buffer.
    322  * Returns:      void
    323  */
    324 void
    325 
    326 _kt_defip_pair128_ip6_addr_get(int unit, soc_mem_t mem, const void *entry, 
    327                                 ip6_addr_t ip6)
    328 {
    329     uint32              ip6_field[4];
    330     soc_mem_field_get(unit, mem, entry, IP_ADDR0_LWRf, (uint32 *)&ip6_field[3]);
    331     ip6[12] = (uint8) (ip6_field[3] >> 24);
    332     ip6[13] = (uint8) (ip6_field[3] >> 16 & 0xff);
    333     ip6[14] = (uint8) (ip6_field[3] >> 8 & 0xff);
    334     ip6[15] = (uint8) (ip6_field[3] & 0xff);
    335     soc_mem_field_get(unit, mem, entry, IP_ADDR1_LWRf, (uint32 *)&ip6_field[2]);
    336     ip6[8] = (uint8) (ip6_field[2] >> 24);
    337     ip6[9] = (uint8) (ip6_field[2] >> 16 & 0xff);
    338     ip6[10] = (uint8) (ip6_field[2] >> 8 & 0xff);
    339     ip6[11] = (uint8) (ip6_field[2] & 0xff);
    340     soc_mem_field_get(unit, mem, entry, IP_ADDR0_UPRf, (uint32 *)&ip6_field[1]);
    341     ip6[4] = (uint8) (ip6_field[1] >> 24);
    342     ip6[5] = (uint8) (ip6_field[1] >> 16 & 0xff);
    343     ip6[6] =(uint8) (ip6_field[1] >> 8 & 0xff);
    344     ip6[7] =(uint8) (ip6_field[1] & 0xff);
    345     soc_mem_field_get(unit, mem, entry, IP_ADDR1_UPRf, ip6_field);
    346     ip6[0] =(uint8) (ip6_field[0] >> 24);
    347     ip6[1] =(uint8) (ip6_field[0] >> 16 & 0xff);
    348     ip6[2] =(uint8) (ip6_field[0] >> 8 & 0xff);
    349     ip6[3] =(uint8) (ip6_field[0] & 0xff);
    350 }
    351 
    352 /*
    353  * Function:
    354  *      _kt_defip_pair128_get_key
    355  * Purpose:
    356  *      Parse route entry key from L3_DEFIP_PAIR_128 table.
    357  * Parameters:
    358  *      unit        - (IN)SOC unit number.
    359  *      entry       - (IN)Hw entry buffer. 
    360  *      lpm_cfg     - (IN/OUT)Buffer to fill defip information. 
    361  * Returns:
    362  *      BCM_E_XXX
    363  */
    364 STATIC int 
    365 _kt_defip_pair128_get_key(int unit, uint32 *hw_entry, 
    366                        _bcm_defip_cfg_t *lpm_cfg)
    367 {
    368     soc_mem_t mem = L3_DEFIP_PAIR_128m;  /* Route table memory. */ 
    369     bcm_ip6_t mask;                      /* Subnet mask.        */
    370 
    371     /* Input parameters check. */
    372     if ((lpm_cfg == NULL) || (hw_entry == NULL)) {
    373         return (BCM_E_PARAM);
    374     }
    375 
    376     /* Extract ip6 address. */
    377     _kt_defip_pair128_ip6_addr_get(unit,mem, hw_entry, lpm_cfg->defip_ip6_addr);
    378 
    379     /* Extract subnet mask. */
    380     _kt_defip_pair128_ip6_mask_get(unit, mem, hw_entry, mask);
    381     lpm_cfg->defip_sub_len = bcm_ip6_mask_length(mask);
    382 
    383     /* Extract vrf id & vrf mask. */
    384     if(!soc_mem_field32_get(unit, mem, hw_entry, VRF_ID_MASK0_LWRf)) {
    385         lpm_cfg->defip_vrf = BCM_L3_VRF_OVERRIDE;
    386     } else {
    387         lpm_cfg->defip_vrf = soc_mem_field32_get(unit, mem, hw_entry, VRF_ID_0_LWRf);
    388     }
    389     return (BCM_E_NONE);
    390 }
    391 
    392 /*
    393  * Function:
    394  *      _kt_defip_pair128_parse
    395  * Purpose:
    396  *      Parse route entry from L3_DEFIP_PAIR_128 table to sw structure.
    397  * Parameters:
    398  *      unit        - (IN)SOC unit number.
    399  *      hw_entry    - (IN)Hw entry buffer. 
    400  *      lpm_cfg     - (IN/OUT)Buffer to fill defip information. 
    401  *      nh_ecmp_idx - (OUT)Next hop ecmp table index. 
    402  * Returns:
    403  *      BCM_E_XXX
    404  */
    405 STATIC INLINE int 
    406 _kt_defip_pair128_parse(int unit, uint32 *hw_entry,
    407                      _bcm_defip_cfg_t *lpm_cfg, int *nh_ecmp_idx)
    408 {
    409     soc_mem_t mem = L3_DEFIP_PAIR_128m;  /* Route table memory. */ 
    410 
    411     /* Input parameters check. */
    412     if ((lpm_cfg == NULL) || (hw_entry == NULL)) {
    413         return (BCM_E_PARAM);
    414     }
    415 
    416     /* Reset entry flags first. */
    417     lpm_cfg->defip_flags = 0;
    418 
    419     /* Check if entry points to ecmp group. */
    420     if (soc_mem_field32_get(unit, mem, hw_entry, ECMPf)) {
    421         /* Mark entry as ecmp */
    422         lpm_cfg->defip_ecmp = TRUE;
    423         lpm_cfg->defip_flags |= BCM_L3_MULTIPATH;
    424 
    425         /* Get ecmp group id. */
    426         if (nh_ecmp_idx != NULL) {
    427             *nh_ecmp_idx = soc_mem_field32_get(unit, mem, hw_entry, ECMP_PTRf);
    428         }
    429     } else {
    430         /* Mark entry as non-ecmp. */
    431         lpm_cfg->defip_ecmp = 0;
    432 
    433         /* Reset ecmp group next hop count. */
    434         lpm_cfg->defip_ecmp_count = 0;
    435 
    436         /* Get next hop index. */
    437         if (nh_ecmp_idx != NULL) {
    438             *nh_ecmp_idx =
    439                 soc_mem_field32_get(unit, mem, hw_entry, NEXT_HOP_INDEXf);
    440         }
    441     }
    442 
    443     /* Mark entry as IPv6 */
    444     lpm_cfg->defip_flags |= BCM_L3_IP6;
    445 
    446     /* Get entry priority. */
    447     lpm_cfg->defip_prio = soc_mem_field32_get(unit, mem, hw_entry, PRIf);
    448 
    449     /* Get classification group id. */
    450     lpm_cfg->defip_lookup_class = 
    451         soc_mem_field32_get(unit, mem, hw_entry, CLASS_IDf);
    452 
    453     /* Get hit bit. */
    454     if ((soc_mem_field32_get(unit, mem, hw_entry, HIT0f) &&
    455          soc_mem_field32_get(unit, mem, hw_entry, HIT1f))) {
    456         lpm_cfg->defip_flags |= BCM_L3_HIT;
    457     }
    458 
    459     /* Get priority override bit. */
    460     if (soc_mem_field32_get(unit, mem, hw_entry, RPEf)) {
    461         lpm_cfg->defip_flags |= BCM_L3_RPE;
    462     }
    463 
    464     /* Get destination discard field. */
    465     if(soc_mem_field32_get(unit, mem, hw_entry, DST_DISCARDf)) {
    466         lpm_cfg->defip_flags |= BCM_L3_DST_DISCARD;
    467     }
    468     return (BCM_E_NONE);
    469 }
    470 
    471 /*
    472  * Function:
    473  *      _kt_trx_defip_128_get_key
    474  * Purpose:
    475  *      Parse route entry key from L3_DEFIP_128 table.
    476  * Parameters:
    477  *      unit        - (IN)SOC unit number.
    478  *      entry       - (IN)Hw entry buffer. 
    479  *      lpm_cfg     - (IN/OUT)Buffer to fill defip information. 
    480  * Returns:
    481  *      BCM_E_XXX
    482  */
    483 STATIC int 
    484 _kt_trx_defip_128_get_key(int unit, uint32 *hw_entry, 
    485                        _bcm_defip_cfg_t *lpm_cfg)
    486 {
    487     soc_mem_t mem = L3_DEFIP_128m;  /* Route table memory. */ 
    488     bcm_ip6_t mask;                 /* Subnet mask.        */
    489 
    490     /* Input parameters check. */
    491     if ((NULL == lpm_cfg) || (NULL == hw_entry)) {
    492         return (BCM_E_PARAM);
    493     }
    494 
    495     /* Extract ip6 address. */
    496     soc_mem_ip6_addr_get(unit, mem, hw_entry, IP_ADDRf, lpm_cfg->defip_ip6_addr,
    497                          SOC_MEM_IP6_FULL_ADDR);
    498 
    499     /* Extract subnet mask. */
    500     soc_mem_ip6_addr_get(unit, mem, hw_entry, IP_ADDR_MASKf, mask,
    501                          SOC_MEM_IP6_FULL_ADDR);
    502     lpm_cfg->defip_sub_len = bcm_ip6_mask_length(mask);
    503 
    504     /* Extract vrf id & vrf mask. */
    505     if(!soc_mem_field32_get(unit, mem, hw_entry, VRF_ID_MASKf)) {
    506         lpm_cfg->defip_vrf = BCM_L3_VRF_OVERRIDE;
    507     } else {
    508         lpm_cfg->defip_vrf = soc_mem_field32_get(unit, mem, hw_entry, VRF_IDf);
    509     }
    510     return (BCM_E_NONE);
    511 }
    512 
    513 /*
    514  * Function:
    515  *      _kt_trx_defip_128_parse
    516  * Purpose:
    517  *      Parse route entry from L3_DEFIP_128 table to sw structure.
    518  * Parameters:
    519  *      unit        - (IN)SOC unit number.
    520  *      hw_entry    - (IN)Hw entry buffer. 
    521  *      lpm_cfg     - (IN/OUT)Buffer to fill defip information. 
    522  *      nh_ecmp_idx - (OUT)Next hop ecmp table index. 
    523  * Returns:
    524  *      BCM_E_XXX
    525  */
    526 STATIC INLINE int 
    527 _kt_trx_defip_128_parse(int unit, uint32 *hw_entry,
    528                      _bcm_defip_cfg_t *lpm_cfg, int *nh_ecmp_idx)
    529 {
    530     soc_mem_t mem = L3_DEFIP_128m;  /* Route table memory. */ 
    531 
    532 
    533     /* Input parameters check. */
    534     if ((NULL == hw_entry) || (NULL == lpm_cfg)) {
    535         return (BCM_E_PARAM);
    536     }
    537 
    538     /* Reset entry flags first. */
    539     lpm_cfg->defip_flags = 0;
    540 
    541     /* Check if entry points to ecmp group. */
    542     if (soc_mem_field32_get(unit, mem, hw_entry, ECMPf)) {
    543         /* Mark entry as ecmp */
    544         lpm_cfg->defip_ecmp = TRUE;
    545         lpm_cfg->defip_flags |= BCM_L3_MULTIPATH;
    546 
    547         /* Get ecmp group id. */
    548         if (NULL != nh_ecmp_idx) {
    549             *nh_ecmp_idx = soc_mem_field32_get(unit, mem, hw_entry, ECMP_PTRf);
    550         }
    551     } else {
    552         /* Mark entry as non-ecmp. */
    553         lpm_cfg->defip_ecmp = 0;
    554 
    555         /* Reset ecmp group next hop count. */
    556         lpm_cfg->defip_ecmp_count = 0;
    557 
    558         /* Get next hop index. */
    559         if (NULL != nh_ecmp_idx) {
    560             *nh_ecmp_idx =
    561                 soc_mem_field32_get(unit, mem, hw_entry, NEXT_HOP_INDEXf);
    562         }
    563     }
    564 
    565     /* Mark entry as IPv6 */
    566     lpm_cfg->defip_flags |= BCM_L3_IP6;
    567 
    568     /* Get entry priority. */
    569     lpm_cfg->defip_prio = soc_mem_field32_get(unit, mem, hw_entry, PRIf);
    570 
    571     /* Get classification group id. */
    572     lpm_cfg->defip_lookup_class = 
    573         soc_mem_field32_get(unit, mem, hw_entry, CLASS_IDf);
    574 
    575     /* Get hit bit. */
    576     if (soc_mem_field32_get(unit, mem, hw_entry, HITf)) {
    577         lpm_cfg->defip_flags |= BCM_L3_HIT;
    578     }
    579 
    580     /* Get priority override bit. */
    581     if (soc_mem_field32_get(unit, mem, hw_entry, RPEf)) {
    582         lpm_cfg->defip_flags |= BCM_L3_RPE;
    583     }
    584 
    585     /* Get destination discard field. */
    586     if(soc_mem_field32_get(unit, mem, hw_entry, DST_DISCARDf)) {
    587         lpm_cfg->defip_flags |= BCM_L3_DST_DISCARD;
    588     }
    589     return (BCM_E_NONE);
    590 }
    591 
    592 /*
    593  * Function:
    594  *      _kt_defip_pair128_match
    595  * Purpose:
    596  *      Lookup route entry from L3_DEFIP_PAIR_128 table.
    597  * Parameters:
    598  *      unit        - (IN)SOC unit number.
    599  *      lpm_cfg     - (IN)Buffer to fill defip information. 
    600  *      hw_entry    - (OUT)Matching hw entry. 
    601  *      hw_index    - (OUT)HW table index. 
    602  * Returns:
    603  *      BCM_E_XXX
    604  */
    605 STATIC int 
    606 _kt_defip_pair128_match(int unit, _bcm_defip_cfg_t *lpm_cfg, 
    607                      uint32 *hw_entry, int *hw_index)
    608 {
    609     _bcm_defip_cfg_t candidate;        /* Match condidate.            */
    610     int   lkup_plen;                   /* Vrf weighted lookup prefix. */
    611     int   index;                       /* Table iteration index.      */
    612     uint8 hash;                        /* Entry hash value.           */
    613     int   rv = BCM_E_NONE;             /* Internal operation status.  */
    614 
    615 
    616     /* Initialization */
    617     sal_memset(&candidate, 0, sizeof(_bcm_defip_cfg_t));
    618     
    619     /* Calculate vrf weighted prefix length. */
    620     lkup_plen = lpm_cfg->defip_sub_len * 
    621         ((BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) ? 2 : 1);
    622 
    623     /* Calculate entry lookup hash. */
    624     BCM_IF_ERROR_RETURN(_kt_defip_pair128_hash(unit, lpm_cfg, &hash));
    625 
    626     /*    coverity[assignment : FALSE]    */
    627     for (index = 0; index <= BCM_KT_DEFIP_PAIR128_IDX_MAX(unit); index++) {
    628 
    629         /* Route prefix length comparison. */
    630         if (lkup_plen != BCM_KT_DEFIP_PAIR128_ARR(unit)[index].prefix_len) {
    631             continue;
    632         }
    633 
    634         /* Route lookup key hash comparison. */
    635         if (hash != BCM_KT_DEFIP_PAIR128_ARR(unit)[index].entry_hash) {
    636             continue;
    637         }
    638 
    639         /* Hash & prefix length match -> read and compare hw entry itself. */
    640         rv = BCM_XGS3_MEM_READ(unit, L3_DEFIP_PAIR_128m, index, hw_entry);
    641         if (BCM_FAILURE(rv)) {
    642             break;
    643         }
    644 
    645         /* Make sure entry is valid.  */
    646         if ((!soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, hw_entry, VALID0_LWRf)) ||
    647             (!soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, hw_entry, VALID1_LWRf)) ||
    648             (!soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, hw_entry, VALID0_UPRf)) ||
    649             (!soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, hw_entry, VALID1_UPRf))
    650             ) {
    651             /* Too bad sw image doesn't match hardware. */
    652             continue;
    653         }
    654 
    655         /* Extract entry address vrf */
    656         rv =  _kt_defip_pair128_get_key(unit, hw_entry, &candidate);
    657         if (BCM_FAILURE(rv)) {
    658             break;
    659         }
    660 
    661 
    662         /* Address & Vrf comparison. */
    663         if (lpm_cfg->defip_vrf != candidate.defip_vrf) {
    664             continue;
    665         }
    666 
    667         /* Subnet mask comparison. */
    668         if (lpm_cfg->defip_sub_len != candidate.defip_sub_len) {
    669             continue;
    670         }
    671 
    672 
    673         if (sal_memcmp(lpm_cfg->defip_ip6_addr, candidate.defip_ip6_addr,
    674                        sizeof(bcm_ip6_t))) {
    675             continue;
    676         }
    677 
    678 
    679         /* Matching entry found. */
    680         break;
    681 
    682     }
    683 
    684     BCM_IF_ERROR_RETURN(rv);
    685 
    686     if (index > BCM_KT_DEFIP_PAIR128_IDX_MAX(unit))  {
    687         return (BCM_E_NOT_FOUND);
    688     }
    689 
    690     *hw_index = index;
    691     return (BCM_E_NONE);
    692 }
    693 
    694 /*
    695  * Function:
    696  *      _kt_defip_pair128_entry_clear
    697  * Purpose:
    698  *      Clear/Reset a single route entry. 
    699  * Parameters:
    700  *      unit      - (IN)SOC unit number.
    701  *      hw_index  - (IN)Entry index in the tcam. 
    702  * Returns:
    703  *      BCM_E_XXX
    704  */
    705 STATIC int 
    706 _kt_defip_pair128_entry_clear(int unit, int hw_index)  
    707 {
    708     soc_mem_t mem = L3_DEFIP_PAIR_128m;
    709     uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS];
    710     soc_field_t key_field[4], mask_field[4];
    711     int field_count, i;
    712     uint64 val64;
    713     key_field[0] = KEY0_UPRf;
    714     key_field[1] = KEY1_UPRf;
    715     key_field[2] = KEY0_LWRf;
    716     key_field[3] = KEY1_LWRf;
    717     mask_field[0] = MASK0_UPRf;
    718     mask_field[1] = MASK1_UPRf;
    719     mask_field[2] = MASK0_LWRf;
    720     mask_field[3] = MASK1_LWRf;
    721     field_count = 4;
    722     sal_memset(hw_entry, 0, WORDS2BYTES(SOC_MAX_MEM_FIELD_WORDS));
    723     COMPILER_64_ZERO(val64);
    724     for (i = 0; i < field_count; i++) {
    725         soc_mem_field64_set(unit, mem, hw_entry, key_field[i], val64);
    726         soc_mem_field64_set(unit, mem, hw_entry, mask_field[i], val64);
    727     }
    728 
    729     /* Reset hw entry. */
    730     BCM_IF_ERROR_RETURN
    731         (BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, hw_index,
    732                             &soc_mem_entry_null(unit, L3_DEFIP_PAIR_128m)));
    733     BCM_IF_ERROR_RETURN
    734         (BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, hw_index, hw_entry));
    735 
    736     /* Reset sw entry. */
    737     BCM_KT_DEFIP_PAIR128_ENTRY_SET(unit, hw_index, 0, 0);
    738 
    739     /* Reset urpf source lookup entry. */
    740     if (SOC_URPF_STATUS_GET(unit)) {
    741         BCM_IF_ERROR_RETURN
    742             (BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, 
    743                             (hw_index + BCM_KT_DEFIP_PAIR128_URPF_OFFSET(unit)),
    744                             &soc_mem_entry_null(unit, L3_DEFIP_PAIR_128m)));
    745         BCM_IF_ERROR_RETURN
    746             (BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, 
    747                  (hw_index+ BCM_KT_DEFIP_PAIR128_URPF_OFFSET(unit)), hw_entry));
    748     }
    749     return (BCM_E_NONE);
    750 }
    751 /*
    752  * Function:
    753  *      _kt_defip_pair128_shift
    754  * Purpose:
    755  *      Shift entries in the tcam. 
    756  * Parameters:
    757  *      unit    - (IN)SOC unit number.
    758  *      idx_src     - (IN)Entry source. 
    759  *      idx_dest    - (IN)Entry destination.
    760  * Returns:
    761  *      BCM_E_XXX
    762  */
    763 STATIC int 
    764 _kt_defip_pair128_shift(int unit, int idx_src, int idx_dest)  
    765 {
    766     uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer. */
    767 
    768     /* Don't copy uninstalled entries. */
    769     if (0 != BCM_KT_DEFIP_PAIR128_ARR(unit)[idx_src].prefix_len) {
    770         /* Read entry from source index. */
    771         BCM_IF_ERROR_RETURN
    772             (BCM_XGS3_MEM_READ(unit, L3_DEFIP_PAIR_128m, idx_src, hw_entry));
    773 
    774         /* Write entry to the destination index. */
    775         BCM_IF_ERROR_RETURN
    776             (BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, idx_dest, hw_entry));
    777 
    778         /* Shift corresponding  URPF/source lookup entries. */
    779         if (SOC_URPF_STATUS_GET(unit)) {
    780             /* Read entry from source index + half tcam. */
    781             BCM_IF_ERROR_RETURN
    782                 (BCM_XGS3_MEM_READ(unit, L3_DEFIP_PAIR_128m, 
    783                                    idx_src + BCM_KT_DEFIP_PAIR128_URPF_OFFSET(unit),
    784                                    hw_entry));
    785 
    786             /* Write entry to the destination index + half tcam. */
    787             BCM_IF_ERROR_RETURN
    788                 (BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, 
    789                                     idx_dest +  BCM_KT_DEFIP_PAIR128_URPF_OFFSET(unit),
    790                                     hw_entry));
    791         }
    792     }
    793     /* Copy software portion of the entry. */ 
    794     sal_memcpy (&BCM_KT_DEFIP_PAIR128_ARR(unit)[idx_dest],
    795                 &BCM_KT_DEFIP_PAIR128_ARR(unit)[idx_src], 
    796                 sizeof(_bcm_l3_defip_pair128_entry_t));
    797 
    798     return (BCM_E_NONE);
    799 }
    800 
    801 /*
    802  * Function:
    803  *      _kt_defip_pair128_shift_range
    804  * Purpose:
    805  *      Shift entries in the tcam. 
    806  * Parameters:
    807  *      unit        - (IN)SOC unit number.
    808  *      idx_start   - (IN)Start index
    809  *      idx_end     - (IN)End index
    810  * Returns:
    811  *      BCM_E_XXX
    812  */
    813 STATIC int 
    814 _kt_defip_pair128_shift_range(int unit, int idx_start, int idx_end)  
    815 {
    816     int idx;     /* Iteration index. */
    817     int rv = BCM_E_NONE;   /* Operaton status. */ 
    818 
    819     /* Shift entries down (1 index up) */
    820     if (idx_end > idx_start) {
    821         for (idx = idx_end - 1; idx >= idx_start; idx--) {
    822             rv = _kt_defip_pair128_shift(unit, idx, idx + 1);  
    823             if (BCM_FAILURE(rv)) { 
    824                 break;
    825             }
    826         }
    827         /* Delete last entry from hardware & software. */
    828         rv = _kt_defip_pair128_entry_clear(unit, idx_start);
    829     }
    830 
    831     /* Shift entries up (1 index down) */
    832     if (idx_end < idx_start) {
    833         for (idx = idx_end + 1; idx <= idx_start; idx++) {
    834             rv = _kt_defip_pair128_shift(unit, idx, idx - 1);  
    835             if (BCM_FAILURE(rv)) { 
    836                 break;
    837             }
    838         }
    839         /* Delete last entry from hardware & software. */
    840         rv = _kt_defip_pair128_entry_clear(unit, idx_start);
    841     }
    842 
    843     return (rv);
    844 }
    845 /*
    846  * Function:
    847  *      _kt_defip_pair128_idx_alloc
    848  * Purpose:
    849  *      Shuffle the tcam in order to insert a new entry 
    850  *      based on vrf weighted prefix length.
    851  * Parameters:
    852  *      unit        - (IN)SOC unit number.
    853  *      lpm_cfg     - (IN)Route info 
    854  *      hw_index    - (OUT)Allocated hw index. 
    855  * Returns:
    856  *      BCM_E_XXX
    857  */
    858 STATIC int 
    859 _kt_defip_pair128_idx_alloc(int unit, _bcm_defip_cfg_t *lpm_cfg, int *hw_index,
    860                             int nh_ecmp_idx)
    861 {
    862     int  lkup_plen;                   /* Vrf weighted lookup prefix.    */
    863     uint8 hash;                       /* Entry hash value.              */
    864     int  idx;                         /* Table iteration index.         */
    865     int  rv;                          /* Operation return status.       */
    866     int  shift_min = 0;               /* Minimum entry shift required.  */
    867     int  range_start = 0;             /* First valid location for pfx.  */
    868     int  range_end = BCM_KT_DEFIP_PAIR128_IDX_MAX(unit);
    869                                       /* Last valid location for pfx.   */
    870     int  free_idx_before = -1;        /* Free index before range_start. */
    871     int  free_idx_after  = -1;        /* Free index after range_end.    */
    872     uint32 temp_hw_entry[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer. */
    873     _bcm_defip_cfg_t temp_lpm;
    874     int temp_nh_ecmp_idx;
    875 
    876     /* Input parameters check. */
    877     if ((lpm_cfg == NULL) || (hw_index == NULL)) {
    878         return (BCM_E_PARAM);
    879     }
    880 
    881     /* Calculate vrf weighted prefix length. */
    882     lkup_plen = lpm_cfg->defip_sub_len * 
    883         ((BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) ? 2 : 1);
    884 
    885     /* Calculate entry hash. */
    886     BCM_IF_ERROR_RETURN(_kt_defip_pair128_hash(unit, lpm_cfg, &hash));
    887 
    888     
    889     /* Make sure at least one slot is available. */
    890     if (BCM_KT_DEFIP_PAIR128_USED_COUNT(unit) == ( range_end + 1)) {
    891         /* L3_DEFIP_PAIR_128 table is full */
    892         /* a. Copy entry at index 0 of L3_DEFIP_PAIR_128
    893            b. Add the copied entry to L3_DEFIP_128 table
    894            c. Delete entry at index 0 from the L3_DEFIP_PAIR_128 table
    895            d. Add the new entry to L3_DEFIP_PAIR_128 table
    896         */
    897         rv = BCM_XGS3_MEM_READ(unit, L3_DEFIP_PAIR_128m, 0, &temp_hw_entry);
    898         BCM_IF_ERROR_RETURN(rv);
    899 
    900         sal_memset(&temp_lpm, 0, sizeof(_bcm_defip_cfg_t));
    901 
    902         /* Parse entry. */
    903         rv = _kt_defip_pair128_parse(unit, temp_hw_entry, &temp_lpm, &temp_nh_ecmp_idx);
    904         BCM_IF_ERROR_RETURN(rv);
    905         
    906         /* Extract entry address vrf */
    907         rv =  _kt_defip_pair128_get_key(unit, temp_hw_entry, &temp_lpm);
    908         BCM_IF_ERROR_RETURN(rv);
    909         
    910 
    911         /* Add the copied entry to L3_DEFIP_128 table */
    912         temp_lpm.defip_index = BCM_XGS3_L3_INVALID_INDEX;
    913         rv = _bcm_trx_defip_128_add(unit, &temp_lpm, temp_nh_ecmp_idx);
    914         BCM_IF_ERROR_RETURN(rv);
    915 
    916         /* Delete entry from hardware & software. */
    917         rv = _kt_defip_pair128_entry_clear(unit, 0);
    918         if (BCM_SUCCESS(rv)) {
    919             BCM_XGS3_L3_DEFIP_CNT_DEC(unit, TRUE);
    920             BCM_KT_DEFIP_PAIR128_USED_COUNT(unit)--;
    921         }
    922     }
    923 
    924     /* 
    925      *  Find first valid index for the prefix;
    926      */ 
    927     for (idx = 0; idx <= BCM_KT_DEFIP_PAIR128_IDX_MAX(unit); idx++) {
    928         /* Remember free entry before installation location. */
    929         if (0 == BCM_KT_DEFIP_PAIR128_ARR(unit)[idx].prefix_len) {
    930             free_idx_before = idx;
    931             continue;
    932         }
    933         /* Route prefix length comparison. */
    934         if (lkup_plen < BCM_KT_DEFIP_PAIR128_ARR(unit)[idx].prefix_len) {
    935             range_start = idx;
    936             continue;
    937         }
    938         break;
    939     }
    940 
    941     /* 
    942      *  Find last valid index for the prefix;
    943      */ 
    944     for (idx = BCM_KT_DEFIP_PAIR128_IDX_MAX(unit); idx >= 0; idx--) {
    945 
    946         /* Remeber free entry after installation location. */
    947         if (0 == BCM_KT_DEFIP_PAIR128_ARR(unit)[idx].prefix_len) {
    948             free_idx_after = idx;
    949             continue;
    950         }
    951         /* Route prefix length comparison. */
    952         if (lkup_plen >  BCM_KT_DEFIP_PAIR128_ARR(unit)[idx].prefix_len) {
    953             range_end = idx;
    954             continue;
    955         }
    956         break;
    957     }
    958 
    959     /* Check if entry should be inserted at the end. */
    960     if (range_start == BCM_KT_DEFIP_PAIR128_IDX_MAX(unit)) {
    961         /* Shift all entries from free_idx_before till the end 1 up. */   
    962         rv = _kt_defip_pair128_shift_range(unit, BCM_KT_DEFIP_PAIR128_IDX_MAX(unit), free_idx_before);
    963 
    964         if (BCM_SUCCESS(rv)) { 
    965             /* Allocated index is last TCAM entry. */
    966             *hw_index = BCM_KT_DEFIP_PAIR128_IDX_MAX(unit);
    967             BCM_KT_DEFIP_PAIR128_ENTRY_SET(unit, *hw_index, lkup_plen, hash);
    968         }
    969         return (rv);
    970     }
    971 
    972     /* Check if entry should be inserted at the beginning. */
    973     if (range_end < 0) {
    974         /* Shift all entries from 0 till free_idx_after 1 down. */
    975         rv = _kt_defip_pair128_shift_range(unit, 0, free_idx_after);
    976 
    977         if (BCM_SUCCESS(rv)) {
    978             /* Allocated index is first TCAM entry. */
    979             *hw_index = 0;
    980             BCM_KT_DEFIP_PAIR128_ENTRY_SET(unit, 0, lkup_plen, hash);
    981         }
    982         return (rv);
    983     }
    984 
    985     /* Find if there is any free index in range. */
    986     for (idx = range_start; idx <= range_end; idx++) {
    987         if (0 == BCM_KT_DEFIP_PAIR128_ARR(unit)[idx].prefix_len) {
    988             *hw_index = idx;
    989             BCM_KT_DEFIP_PAIR128_ENTRY_SET(unit, idx, lkup_plen, hash);
    990             return (BCM_E_NONE);
    991         }
    992     }
    993 
    994     /* Check if entry should be inserted at the end of range. */
    995     if ((free_idx_after > range_end) && (free_idx_after != -1))  {
    996         shift_min = free_idx_after - range_end;
    997     } 
    998 
    999     /* Check if entry should be inserted in the beginning. */
   1000     if ((free_idx_before < range_start) && (free_idx_before != -1))  {
   1001         if((shift_min > (range_start - free_idx_before)) || (free_idx_after == -1)) {
   1002             shift_min = -1;
   1003         }
   1004     }
   1005 
   1006     if (shift_min <= 0) {
   1007         rv = _kt_defip_pair128_shift_range(unit, range_start, free_idx_before);
   1008         if (BCM_SUCCESS(rv)) {
   1009             *hw_index= range_start;
   1010             BCM_KT_DEFIP_PAIR128_ENTRY_SET(unit, range_start, lkup_plen, hash);
   1011         }
   1012     } else {
   1013         rv = _kt_defip_pair128_shift_range(unit, range_end, free_idx_after);
   1014         if (BCM_SUCCESS(rv)) {
   1015             *hw_index = range_end;
   1016             BCM_KT_DEFIP_PAIR128_ENTRY_SET(unit, range_end, lkup_plen, hash);
   1017         }
   1018     }
   1019     return (rv);
   1020 }
   1021 /*
   1022  * Function:
   1023  *      _bcm_kt_defip_pair128_get
   1024  * Purpose:
   1025  *      Get an entry from L3_DEFIP_PAIR_128 table.
   1026  * Parameters:
   1027  *      unit        - (IN)SOC unit number.
   1028  *      lpm_cfg     - (IN)Buffer to fill defip information. 
   1029  *      nh_ecmp_idx - (IN)Next hop or ecmp group index
   1030  * Returns:
   1031  *      BCM_E_XXX
   1032  */
   1033 int 
   1034 _bcm_kt_defip_pair128_get(int unit, _bcm_defip_cfg_t *lpm_cfg, 
   1035                        int *nh_ecmp_idx) 
   1036 {
   1037     uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS];/* Hw entry buffer.          */
   1038     bcm_ip6_t mask;                          /* Subnet mask.              */
   1039     int clear_hit;                           /* Clear entry hit bit flag. */
   1040     int hw_index = 0;                        /* Entry offset in the TCAM. */ 
   1041     int rv;                                  /* Internal operation status.*/
   1042     soc_kt_lpm_ipv6_info_t *lpm_ipv6_info = soc_kt_lpm_ipv6_info_get(unit);
   1043 
   1044     /* Input parameters check. */
   1045     if (lpm_cfg == NULL) {
   1046         return (BCM_E_PARAM);
   1047     }
   1048 
   1049     if (lpm_ipv6_info->ipv6_128b.depth == 0) {
   1050        /* We cannot use L3_DEFIP for storing IPv6 128b lookup */
   1051        return BCM_E_NOT_FOUND;
   1052     }
   1053 
   1054     rv = _bcm_trx_defip_128_get(unit, lpm_cfg, nh_ecmp_idx);
   1055 
   1056     if (rv == BCM_E_NOT_FOUND) {
   1057 
   1058         /* Check if clear hit bit required. */
   1059         clear_hit = lpm_cfg->defip_flags & BCM_L3_HIT_CLEAR;
   1060 
   1061         /* Create mask from prefix length. */
   1062         bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len);
   1063 
   1064         /* Apply mask on address. */
   1065         bcm_xgs3_l3_mask6_apply(mask, lpm_cfg->defip_ip6_addr);
   1066 
   1067         /* Search for matching entry in the cam. */
   1068         rv =  _kt_defip_pair128_match(unit, lpm_cfg, hw_entry, &hw_index);
   1069         BCM_IF_ERROR_RETURN(rv);
   1070 
   1071         lpm_cfg->defip_index = hw_index;
   1072 
   1073         /* Parse matched entry. */
   1074         rv = _kt_defip_pair128_parse(unit, hw_entry, lpm_cfg, nh_ecmp_idx);
   1075         BCM_IF_ERROR_RETURN(rv);
   1076 
   1077         /* Clear the HIT bit */
   1078         if (clear_hit) {
   1079             soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, hw_entry, HIT0f, 0);
   1080             soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, hw_entry, HIT1f, 0);
   1081 
   1082             rv = BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, hw_index, hw_entry);
   1083         }
   1084     }
   1085 
   1086     return (rv);
   1087 }
   1088 
   1089 /*
   1090  * Function:
   1091  *      _bcm_kt_defip_pair128_add
   1092  * Purpose:
   1093  *      Add an entry to internal L3_DEFIP_PAIR_128 table.
   1094  * Parameters:
   1095  *      unit        - (IN)SOC unit number.
   1096  *      lpm_cfg     - (IN)Buffer to fill defip information. 
   1097  *      nh_ecmp_idx - (IN)Next hop or ecmp group index.
   1098  * Returns:
   1099  *      BCM_E_XXX
   1100  */
   1101 int 
   1102 _bcm_kt_defip_pair128_add(int unit, _bcm_defip_cfg_t *lpm_cfg,
   1103                        int nh_ecmp_idx) 
   1104 {
   1105     uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS];   /* New entry hw buffer.      */
   1106     bcm_ip6_t mask;                             /* Subnet mask.              */
   1107     int hw_index = 0;                           /* Entry offset in the TCAM. */ 
   1108     int rv;                                     /* Operation return status.  */
   1109     soc_mem_t mem = L3_DEFIP_PAIR_128m;              /* Route table memory.       */
   1110     int  lkup_plen;                   /* Vrf weighted lookup prefix.    */
   1111     int  range_end;                   /* Last valid location for pfx.   */
   1112     soc_kt_lpm_ipv6_info_t *lpm_ipv6_info = soc_kt_lpm_ipv6_info_get(unit);
   1113 
   1114     /* Input parameters check. */
   1115     if (lpm_cfg == NULL) {
   1116         return (BCM_E_PARAM);
   1117     }
   1118 
   1119     /* No support for routes matchin AFTER vrf specific. */
   1120     if (BCM_L3_VRF_GLOBAL == lpm_cfg->defip_vrf) {
   1121         return (BCM_E_UNAVAIL);
   1122     }
   1123 
   1124     if (lpm_ipv6_info->ipv6_128b.depth == 0) {
   1125        /* We cannot use L3_DEFIP for storing IPv6 128b lookup */
   1126        return BCM_E_FULL;
   1127     }   
   1128 
   1129     /* Zero buffers. */
   1130     sal_memset(hw_entry, 0, WORDS2BYTES(SOC_MAX_MEM_FIELD_WORDS));
   1131 
   1132     /* Create mask from prefix length. */
   1133     bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len);
   1134 
   1135     /* Apply mask on address. */
   1136     bcm_xgs3_l3_mask6_apply(mask, lpm_cfg->defip_ip6_addr);
   1137 
   1138     /* Allocate a new index for inserted entry. */
   1139     if (BCM_XGS3_L3_INVALID_INDEX == lpm_cfg->defip_index) {
   1140         range_end = BCM_KT_DEFIP_PAIR128_IDX_MAX(unit) + 1;
   1141         if (BCM_KT_DEFIP_PAIR128_USED_COUNT(unit) == range_end) {
   1142             /* If L3_DEFIP_PAIR_128 table is full and weighted prefix length
   1143              * of new entry is >= that of 0th entry in L3_DEFIP_PAIR_128 table
   1144              * then add the new entry in L3_DEFIP_128 table */
   1145             lkup_plen = lpm_cfg->defip_sub_len * 
   1146                 ((BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) ? 2 : 1);
   1147             if (lkup_plen >= BCM_KT_DEFIP_PAIR128_ARR(unit)[0].prefix_len) {
   1148                 return _bcm_trx_defip_128_add(unit, lpm_cfg, nh_ecmp_idx);
   1149             }
   1150         }
   1151         rv = _kt_defip_pair128_idx_alloc(unit, lpm_cfg, &hw_index, nh_ecmp_idx);
   1152         BCM_IF_ERROR_RETURN(rv);
   1153     } else {
   1154         hw_index = lpm_cfg->defip_index;
   1155     }
   1156 
   1157     /* Set hit bit. */
   1158     if (lpm_cfg->defip_flags & BCM_L3_HIT) {
   1159         soc_mem_field32_set(unit, mem, hw_entry, HIT0f, 1);
   1160         soc_mem_field32_set(unit, mem, hw_entry, HIT1f, 1);
   1161     }
   1162 
   1163     /* Set priority override bit. */
   1164     if (lpm_cfg->defip_flags & BCM_L3_RPE) {
   1165         soc_mem_field32_set(unit, mem, hw_entry, RPEf, 1);
   1166     }
   1167 
   1168     /* Set classification group id. */
   1169     soc_mem_field32_set(unit, mem, hw_entry, CLASS_IDf, 
   1170                         lpm_cfg->defip_lookup_class);
   1171 
   1172 
   1173     /* Write priority field. */
   1174     soc_mem_field32_set(unit, mem, hw_entry, PRIf, lpm_cfg->defip_prio);
   1175 
   1176 
   1177     /* Fill next hop information. */
   1178     if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) {
   1179         soc_mem_field32_set(unit, mem, hw_entry, ECMP_PTRf, nh_ecmp_idx);
   1180         soc_mem_field32_set(unit, mem, hw_entry, ECMPf, 1);
   1181     } else {
   1182         soc_mem_field32_set(unit, mem, hw_entry, NEXT_HOP_INDEXf, nh_ecmp_idx);
   1183     }
   1184 
   1185     /* Set destination discard flag. */
   1186     if (lpm_cfg->defip_flags & BCM_L3_DST_DISCARD) {
   1187         soc_mem_field32_set(unit, mem, hw_entry, DST_DISCARDf, 1);
   1188     }
   1189 
   1190     /* Set mode bits to indicate IP v6 128b pair mode */
   1191     soc_mem_field32_set(unit, mem, hw_entry, MODE0_LWRf, 1);
   1192     soc_mem_field32_set(unit, mem, hw_entry, MODE1_LWRf, 1);
   1193     soc_mem_field32_set(unit, mem, hw_entry, MODE0_UPRf, 1);
   1194     soc_mem_field32_set(unit, mem, hw_entry, MODE1_UPRf, 1);
   1195     soc_mem_field32_set(unit, mem, hw_entry, MODE_MASK0_LWRf, 1);
   1196     soc_mem_field32_set(unit, mem, hw_entry, MODE_MASK1_LWRf, 1);
   1197     soc_mem_field32_set(unit, mem, hw_entry, MODE_MASK0_UPRf, 1);
   1198     soc_mem_field32_set(unit, mem, hw_entry, MODE_MASK1_UPRf, 1);
   1199 
   1200     /* Set valid bits. */
   1201     soc_mem_field32_set(unit, mem, hw_entry, VALID0_LWRf, 1);
   1202     soc_mem_field32_set(unit, mem, hw_entry, VALID1_LWRf, 1);
   1203     soc_mem_field32_set(unit, mem, hw_entry, VALID0_UPRf, 1);
   1204     soc_mem_field32_set(unit, mem, hw_entry, VALID1_UPRf, 1);
   1205 
   1206     /* Set destination/source ip address. */
   1207     _kt_defip_pair128_ip6_addr_set(unit, mem, hw_entry, lpm_cfg->defip_ip6_addr);
   1208 
   1209     /* Set ip mask. */
   1210     _kt_defip_pair128_ip6_mask_set(unit, mem, hw_entry, mask);
   1211 
   1212     /* Set vrf id & vrf mask. */
   1213     if (BCM_L3_VRF_OVERRIDE != lpm_cfg->defip_vrf) {
   1214         soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_0_LWRf, lpm_cfg->defip_vrf);
   1215         soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_1_LWRf, lpm_cfg->defip_vrf);
   1216         soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_0_UPRf, lpm_cfg->defip_vrf);
   1217         soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_1_UPRf, lpm_cfg->defip_vrf);
   1218         soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASK0_LWRf,
   1219                             (1 << soc_mem_field_length(unit, mem,
   1220                                                        VRF_ID_MASK0_LWRf)) - 1);
   1221         soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASK1_LWRf,
   1222                             (1 << soc_mem_field_length(unit, mem,
   1223                                                        VRF_ID_MASK1_LWRf)) - 1);
   1224         soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASK0_UPRf,
   1225                             (1 << soc_mem_field_length(unit, mem,
   1226                                                        VRF_ID_MASK0_UPRf)) - 1);
   1227         soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASK1_LWRf,
   1228                             (1 << soc_mem_field_length(unit, mem,
   1229                                                        VRF_ID_MASK1_UPRf)) - 1);
   1230         if (SOC_MEM_FIELD_VALID(unit, mem, GLOBAL_ROUTEf)) {
   1231             soc_mem_field32_set(unit, mem, hw_entry, GLOBAL_ROUTEf, 0);
   1232         }
   1233     } else {
   1234         soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_0_LWRf, 0);
   1235         soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_1_LWRf, 0);
   1236         soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_0_UPRf, 0);
   1237         soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_1_UPRf, 0);
   1238         soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASK0_LWRf, 0);
   1239         soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASK1_LWRf, 0);
   1240         soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASK0_UPRf, 0);
   1241         soc_mem_field32_set(unit, mem, hw_entry, VRF_ID_MASK1_UPRf, 0);
   1242     }
   1243 
   1244     /* Write buffer to hw. */
   1245     rv = BCM_XGS3_MEM_WRITE(unit, mem, hw_index, hw_entry);
   1246     if (BCM_FAILURE(rv)) {
   1247         BCM_KT_DEFIP_PAIR128_ENTRY_SET(unit, hw_index, 0, 0);
   1248         return (rv);
   1249     }
   1250 
   1251     /* Write source lookup portion of the entry. */
   1252     if (SOC_URPF_STATUS_GET(unit)) {
   1253         soc_mem_field32_set(unit, mem, hw_entry, SRC_DISCARDf, 0);
   1254         rv = BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, 
   1255                                 (hw_index + BCM_KT_DEFIP_PAIR128_URPF_OFFSET(unit)),
   1256                                 hw_entry);
   1257         if (BCM_FAILURE(rv)) {
   1258             _kt_defip_pair128_entry_clear(unit, hw_index);
   1259             return (rv);
   1260         }
   1261     }
   1262 
   1263     /* If new route added increment total number of routes.  */
   1264     /* Lack of index indicates a new route. */
   1265     if (BCM_XGS3_L3_INVALID_INDEX == lpm_cfg->defip_index) {
   1266         BCM_XGS3_L3_DEFIP_CNT_INC(unit, TRUE);
   1267         BCM_KT_DEFIP_PAIR128_USED_COUNT(unit)++;
   1268     }
   1269 
   1270     return rv;
   1271 }
   1272 
   1273 
   1274 /*
   1275  * Function:
   1276  *      _bcm_kt_defip_pair128_delete
   1277  * Purpose:
   1278  *      Delete an entry from L3_DEFIP_PAIR_128 table.
   1279  * Parameters:
   1280  *      unit    - (IN)SOC unit number.
   1281  *      lpm_cfg - (IN)Buffer to fill defip information. 
   1282  * Returns:
   1283  *      BCM_E_XXX
   1284  */
   1285 int 
   1286 _bcm_kt_defip_pair128_delete(int unit, _bcm_defip_cfg_t *lpm_cfg) 
   1287 {
   1288     uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS];/* Hw entry buffer.          */
   1289     uint32 temp_hw_entry[SOC_MAX_MEM_FIELD_WORDS];/* Hw entry buffer.          */
   1290     bcm_ip6_t mask;                          /* Subnet mask.              */
   1291     int hw_index = 0;                        /* Entry offset in the TCAM. */ 
   1292     int rv, rv1;                             /* Internal operation status.*/
   1293     _bcm_defip_cfg_t temp_lpm;
   1294     int temp_nh_ecmp_idx, idx;
   1295     soc_kt_lpm_ipv6_info_t *lpm_ipv6_info;
   1296 
   1297     /* Input parameters check. */
   1298     if (lpm_cfg == NULL) {
   1299         return (BCM_E_PARAM);
   1300     }
   1301 
   1302     lpm_ipv6_info = soc_kt_lpm_ipv6_info_get(unit);
   1303 
   1304     if (lpm_ipv6_info->ipv6_128b.depth == 0) {
   1305        /* We cannot use L3_DEFIP for storing IPv6 128b lookup */
   1306        return BCM_E_NOT_FOUND;
   1307     }    
   1308 
   1309 
   1310     /* First search for matching entry in L3_DEFIP_128 table.
   1311      * If found then delete it. If it is not found in L3_DEFIP_128 table
   1312      * then search in L3_DEFIP_PAIR_128 table and delete matching entry. */
   1313 
   1314     /* First try to delete from L3_DEFIP_128 table. If successful then exit.
   1315      * If not found in L3_DEFIP_128m then search the L3_DEFIP_PAIR_128 table.
   1316      * If it is found in L3_DEFIP_PAIR_128m then delete it. */  
   1317     rv =  _bcm_trx_defip_128_delete(unit, lpm_cfg);
   1318     if (rv == BCM_E_NOT_FOUND) {
   1319         /* Create mask from prefix length. */
   1320         bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len);
   1321 
   1322         /* Apply mask on address. */
   1323         bcm_xgs3_l3_mask6_apply(mask, lpm_cfg->defip_ip6_addr);
   1324         /* Search for matching entry in theL3_DEFIP_PAIR_128  cam.  */
   1325         rv1 =  _kt_defip_pair128_match(unit, lpm_cfg, hw_entry, &hw_index);
   1326         if (BCM_FAILURE(rv1)) {
   1327             return (rv1);
   1328         }
   1329         /* Delete entry from hardware & software (L3_DEFIP_PAIR_128m). */
   1330         rv1 = _kt_defip_pair128_entry_clear(unit, hw_index);
   1331         if (BCM_SUCCESS(rv1)) {
   1332             BCM_XGS3_L3_DEFIP_CNT_DEC(unit, TRUE);
   1333             BCM_KT_DEFIP_PAIR128_USED_COUNT(unit)--;
   1334             /* Delete valid entry at highest index (or lowest LPM) in 
   1335              * L3_DEFIP_128m table if available
   1336              * and add it to L3_DEFIP_PAIR_128m */
   1337             if (_bcm_trx_defip128_used_count_get(unit) > 0) {
   1338                 hw_index = _bcm_trx_defip128_idx_max_get(unit);
   1339                 for (idx = _bcm_trx_defip128_idx_max_get(unit);
   1340                     idx >=0; idx--) {
   1341                     if (_bcm_trx_defip128_array_idx_prefix_len_get(unit, idx)
   1342                             == 0) {
   1343                         hw_index =  idx - 1;
   1344                         continue;
   1345                     }
   1346                     break;
   1347                 }
   1348                 rv = BCM_XGS3_MEM_READ(unit, L3_DEFIP_128m, hw_index, &temp_hw_entry);
   1349                 BCM_IF_ERROR_RETURN(rv);
   1350                 sal_memset(&temp_lpm, 0, sizeof(_bcm_defip_cfg_t));
   1351                 /* Parse entry. */
   1352                 rv = _kt_trx_defip_128_parse(unit, temp_hw_entry, &temp_lpm, &temp_nh_ecmp_idx);
   1353                 BCM_IF_ERROR_RETURN(rv);
   1354                 
   1355                 /* Extract entry address vrf */
   1356                 rv =  _kt_trx_defip_128_get_key(unit, temp_hw_entry, &temp_lpm);
   1357                 BCM_IF_ERROR_RETURN(rv);
   1358 
   1359                 /* Add the copied entry to L3_DEFIP_PAIR_128 table */
   1360                 temp_lpm.defip_index = BCM_XGS3_L3_INVALID_INDEX;
   1361                 rv = _bcm_kt_defip_pair128_add(unit, &temp_lpm, temp_nh_ecmp_idx);
   1362                 BCM_IF_ERROR_RETURN(rv);
   1363 
   1364                 /* Delete entry from L3_DEFIP_128 table. */
   1365                 temp_lpm.defip_index = hw_index;
   1366                 rv = _bcm_trx_defip_128_delete(unit, &temp_lpm);
   1367                 return rv;
   1368             }
   1369         }
   1370         return rv1;
   1371     } 
   1372     return (rv);
   1373 }
   1374 
   1375 
   1376 /*
   1377  * Function:
   1378  *      _bcm_kt_defip_pair128_update_match
   1379  * Purpose:
   1380  *      Update/Delete all entries in defip table matching a certain rule.
   1381  * Parameters:
   1382  *      unit     - (IN)SOC unit number.
   1383  *      trv_data - (IN)Delete pattern + compare,act,notify routines.  
   1384  * Returns:
   1385  *      BCM_E_XXX
   1386  */
   1387 int
   1388 _bcm_kt_defip_pair128_update_match(int unit, _bcm_l3_trvrs_data_t *trv_data)
   1389 {
   1390     int idx;                                 /* Iteration index.           */
   1391     int rv;                                  /* Operation return status.   */
   1392     int cmp_result;                          /* Test routine result.       */
   1393     int nh_ecmp_idx;                         /* Next hop/Ecmp group index. */
   1394     uint32 *hw_entry;                        /* Hw entry buffer.           */
   1395     char *lpm_tbl_ptr;                       /* Dma table pointer.         */
   1396     int defip_pair128_tbl_size;                    /* Defip table size.          */
   1397     _bcm_defip_cfg_t lpm_cfg;                /* Buffer to fill route info. */
   1398     soc_mem_t mem = L3_DEFIP_PAIR_128m;           /* Route table memory.        */ 
   1399     soc_kt_lpm_ipv6_info_t *lpm_ipv6_info = soc_kt_lpm_ipv6_info_get(unit);
   1400 
   1401     if (lpm_ipv6_info->ipv6_128b.depth == 0) {
   1402        /* L3_DEFIP table is not used for storing IPv6 128b lookup */
   1403        return BCM_E_NONE;
   1404     }
   1405 
   1406     /* Table DMA the LPM table to software copy */
   1407     BCM_IF_ERROR_RETURN
   1408         (bcm_xgs3_l3_tbl_dma(unit, mem, BCM_L3_MEM_ENT_SIZE(unit, mem),
   1409                              "lpm_tbl", &lpm_tbl_ptr, &defip_pair128_tbl_size));
   1410 
   1411     if (SOC_URPF_STATUS_GET(unit)) {
   1412         defip_pair128_tbl_size >>= 1;
   1413     } 
   1414 
   1415     for (idx = 0; idx < defip_pair128_tbl_size; idx++) {
   1416         /* Calculate entry ofset. */
   1417         hw_entry = soc_mem_table_idx_to_pointer(unit, mem, uint32 *,
   1418                                                 lpm_tbl_ptr, idx);
   1419 
   1420         /* Make sure entry is valid. */
   1421         if (!soc_mem_field32_get (unit, mem, hw_entry, VALID0_LWRf)) {
   1422             continue;
   1423         }
   1424 
   1425         /* Zero destination buffer first. */
   1426         sal_memset(&lpm_cfg, 0, sizeof(_bcm_defip_cfg_t));
   1427 
   1428         /* Parse  the entry. */
   1429         _kt_defip_pair128_parse(unit, hw_entry, &lpm_cfg, &nh_ecmp_idx);
   1430         lpm_cfg.defip_index = idx;
   1431 
   1432         /* Fill entry ip address &  subnet mask. */
   1433         _kt_defip_pair128_get_key(unit, hw_entry, &lpm_cfg);
   1434 
   1435         /* Execute operation routine if any. */
   1436         if (trv_data->op_cb) {
   1437             rv = (*trv_data->op_cb) (unit, (void *)trv_data,
   1438                                      (void *)&lpm_cfg,
   1439                                      (void *)&nh_ecmp_idx, &cmp_result);
   1440             if (BCM_FAILURE(rv)) {
   1441                 soc_cm_sfree(unit, lpm_tbl_ptr);
   1442                 return rv;
   1443             }
   1444         }
   1445 #ifdef BCM_WARM_BOOT_SUPPORT
   1446         if (SOC_WARM_BOOT(unit)) {
   1447             rv = _kt_defip_pair128_reinit(unit, idx, &lpm_cfg);
   1448             if (BCM_FAILURE(rv)) {
   1449                 soc_cm_sfree(unit, lpm_tbl_ptr);
   1450                 return rv;
   1451             }
   1452         }
   1453 #endif /* BCM_WARM_BOOT_SUPPORT */
   1454     }
   1455     
   1456 #ifdef BCM_WARM_BOOT_SUPPORT
   1457     if (SOC_WARM_BOOT(unit)) {
   1458         SOC_IF_ERROR_RETURN(soc_fb_lpm_reinit_done(unit, 1));
   1459     }
   1460 #endif /* BCM_WARM_BOOT_SUPPORT */
   1461     soc_cm_sfree(unit, lpm_tbl_ptr);
   1462     return (BCM_E_NONE);
   1463 }
   1464 
   1465 int
   1466 _bcm_kt_defip_pair128_used_count_get(int unit)
   1467 {
   1468     return BCM_KT_DEFIP_PAIR128_USED_COUNT(unit);
   1469 }
   1470 
   1471 /*
   1472  * Function:
   1473  *      _bcm_kt_l3_info_dump
   1474  * Purpose:
   1475  *      Dump the status of hardware.
   1476  * Parameters:
   1477  *      unit   - (IN)SOC unit number
   1478  * Returns:
   1479  *      BCM_E_XXX.
   1480  */
   1481 int
   1482 _bcm_kt_l3_info_dump(int unit)
   1483 {
   1484     uint32 ipv6_lpm_128b_enable;
   1485     uint32 ipv6_64b_free = 0;
   1486     uint32 ipv6_64b_used = 0;
   1487     uint32 ipv6_128b_free = 0;
   1488     uint32 ipv6_128b_used = 0;
   1489     uint32 ipv6_128b_total = 0;
   1490     uint32 ipv4_free = 0;
   1491     uint32 ipv4_used = 0;
   1492     uint32 trx_defip128_idx_max = 0;
   1493     uint32 trx_defip128_used_count = 0;
   1494     soc_kt_lpm_ipv6_info_t *lpm_ipv6_info;
   1495 
   1496     /*  Make sure module was initialized. */
   1497     if (!BCM_XGS3_L3_INITIALIZED(unit)) {
   1498         return (BCM_E_INIT);
   1499     }
   1500 
   1501     trx_defip128_idx_max = SOC_IS_KATANA(unit) ?
   1502         _bcm_trx_defip128_idx_max_get(unit) : 0;
   1503 
   1504     trx_defip128_used_count = SOC_IS_KATANA(unit) ?
   1505         _bcm_trx_defip128_used_count_get(unit) : 0;
   1506 
   1507     if (SOC_IS_KATANA(unit)) {
   1508         ipv6_lpm_128b_enable =
   1509             soc_property_get(unit,spn_IPV6_LPM_128B_ENABLE, 0);
   1510         LOG_CLI((BSL_META_U(unit,
   1511                             "\n*************************************************")));
   1512         LOG_CLI((BSL_META_U(unit,
   1513                             "\nURPF check \t\t\t\t= %s"),
   1514                  SOC_URPF_STATUS_GET(unit) ? "ENABLED" : "DISABLED"));
   1515         LOG_CLI((BSL_META_U(unit,
   1516                             "\nconfig ipv6_lpm_128b_enable \t\t= %d"),
   1517                  ipv6_lpm_128b_enable));
   1518         LOG_CLI((BSL_META_U(unit,
   1519                             "\n*************************************************")));
   1520         LOG_CLI((BSL_META_U(unit,
   1521                             "\nMaximum LPM entries types")));
   1522         LOG_CLI((BSL_META_U(unit,
   1523                             "\n     IPv4 * IPv6 64 bit *IPv6 128 bit")));
   1524         if (SOC_URPF_STATUS_GET(unit)) {
   1525             if (ipv6_lpm_128b_enable == 0 ) {
   1526                 LOG_CLI((BSL_META_U(unit,
   1527                                     "\nupto 6144   3072         128")));
   1528             } else {
   1529                 LOG_CLI((BSL_META_U(unit,
   1530                                     "\nupto 2048   1024         1152")));
   1531             }
   1532         } else {
   1533             if (ipv6_lpm_128b_enable == 0) {
   1534                 LOG_CLI((BSL_META_U(unit,
   1535                                     "\nupto 12288  6144         256")));
   1536             } else {
   1537                 LOG_CLI((BSL_META_U(unit,
   1538                                     "\nupto 4096   2048         2304")));
   1539             }
   1540         }
   1541 
   1542         lpm_ipv6_info = soc_kt_lpm_ipv6_info_get(unit);
   1543         /* IPv4, IPv6 64b and IPv6 pair128b entries share L3_DEFIPm 
   1544          * Ipv6 64b and IPv6 pair128b are stored in mutually exclusive entries*/
   1545         if (lpm_ipv6_info->ipv6_128b.depth > 0) {
   1546             ipv6_128b_total = lpm_ipv6_info->ipv6_128b.depth +
   1547                 trx_defip128_idx_max + 1;
   1548             ipv6_128b_used = BCM_KT_DEFIP_PAIR128_USED_COUNT(unit) + 
   1549                             trx_defip128_used_count;
   1550             ipv6_128b_free = ipv6_128b_total - ipv6_128b_used;
   1551         } else {
   1552             ipv6_128b_total = trx_defip128_idx_max + 1;
   1553             ipv6_128b_used = trx_defip128_used_count;
   1554             ipv6_128b_free = ipv6_128b_total - ipv6_128b_used;
   1555         }
   1556         ipv6_64b_used = BCM_XGS3_L3_DEFIP_IP6_CNT(unit) - ipv6_128b_used;
   1557         ipv4_used = BCM_XGS3_L3_DEFIP_IP4_CNT(unit);        
   1558         ipv6_64b_free = lpm_ipv6_info->ipv6_64b.depth -
   1559                         ((ipv4_used+1)/2 + ipv6_64b_used);
   1560         ipv4_free = ipv6_64b_free * 2;
   1561 
   1562         LOG_CLI((BSL_META_U(unit,
   1563                             "\n*************************************************")));
   1564         LOG_CLI((BSL_META_U(unit,
   1565                             "\nIPv4 LPM entries in use \t\t= %5d"), ipv4_used));
   1566         LOG_CLI((BSL_META_U(unit,
   1567                             "\nIPv4 LPM entries free \t\t\t= %5d"), ipv4_free));
   1568         LOG_CLI((BSL_META_U(unit,
   1569                             "\nIPv4 LPM entries total \t\t\t= %5d"),
   1570                  ipv4_free + ipv4_used));
   1571         LOG_CLI((BSL_META_U(unit,
   1572                             "\n**********")));
   1573         LOG_CLI((BSL_META_U(unit,
   1574                             "\nIPv6 64 bit LPM entries in use \t\t= %5d"),
   1575                  ipv6_64b_used));
   1576         LOG_CLI((BSL_META_U(unit,
   1577                             "\nIPv6 64 bit LPM entries free \t\t= %5d"),
   1578                  ipv6_64b_free));
   1579         LOG_CLI((BSL_META_U(unit,
   1580                             "\n64 bit LPM DEFIP entries total \t\t= %5d"),
   1581                  ipv6_64b_used + ipv6_64b_free));
   1582         LOG_CLI((BSL_META_U(unit,
   1583                             "\n**********")));
   1584         LOG_CLI((BSL_META_U(unit,
   1585                             "\nIPv6 128 bit LPM entries in use \t= %5d"),
   1586                  ipv6_128b_used));
   1587         LOG_CLI((BSL_META_U(unit,
   1588                             "\nIPv6 128 bit LPM entries free \t\t= %5d"),
   1589                  ipv6_128b_free));
   1590         LOG_CLI((BSL_META_U(unit,
   1591                             "\nIPv6 128 bit LPM entries total \t\t= %5d"),
   1592                  (ipv6_128b_used + ipv6_128b_free)));
   1593         LOG_CLI((BSL_META_U(unit,
   1594                             "\n**********")));
   1595         LOG_CLI((BSL_META_U(unit,
   1596                             "\nTotal IPv6 LPM entries in use \t\t= %5d"),
   1597                  BCM_XGS3_L3_DEFIP_IP6_CNT(unit)));
   1598         LOG_CLI((BSL_META_U(unit,
   1599                             "\nTotal IPv6 LPM entries free \t\t= %5d"), 
   1600                  (ipv6_64b_free + ipv6_128b_free)));
   1601         LOG_CLI((BSL_META_U(unit,
   1602                             "\nTotal IPv6 LPM entries \t\t\t= %5d\n"),
   1603                  BCM_XGS3_L3_DEFIP_IP6_CNT(unit) +
   1604                  (ipv6_64b_free + ipv6_128b_free)));
   1605     }
   1606     return (BCM_E_NONE);
   1607 }
   1608 
   1609 /*
   1610  * Function:
   1611  *      bcmi_kt_extended_queue_config_destroy
   1612  * Purpose:
   1613  *      Destroy cosq settings done as part of l3 egress.
   1614  * Parameters:
   1615  *      unit   - (IN)SOC unit number
   1616  *      idx    - (IN)Egress obj id.
   1617  * Returns:
   1618  *      BCM_E_XXX.
   1619  */
   1620 int
   1621 bcmi_kt_extended_queue_config_destroy(int unit, bcm_if_t idx)
   1622 {
   1623     ing_queue_map_entry_t ing_queue_entry;
   1624     ing_l3_next_hop_entry_t in_entry;
   1625     int old_queue_id = 0;
   1626     int mem = ING_L3_NEXT_HOPm;
   1627 
   1628     sal_memset(&in_entry, 0, BCM_XGS3_L3_ENT_SZ(unit, nh));
   1629     /* Read ingress next hop entry. */
   1630     BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, mem, idx, &in_entry));
   1631 
   1632     old_queue_id = soc_mem_field32_get(unit, mem, &in_entry,
   1633                                   EH_QUEUE_TAGf);
   1634     if (old_queue_id > 0) {
   1635         /*  ING_QUEUE_MAP needs to be reset */
   1636         sal_memset(&ing_queue_entry, 0, sizeof(ing_queue_map_entry_t));
   1637         BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_WRITE(unit, ING_QUEUE_MAPm,
   1638                                   old_queue_id, &ing_queue_entry));
   1639     }
   1640     return BCM_E_NONE;
   1641 }
   1642 
   1643 #else /* BCM_KT_SUPPORT && INCLUDE_L3 */
   1644 int bcm_kt_l3_not_empty;
   1645 #endif /* BCM_KT_SUPPORT && INCLUDE_L3 */
   1646