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_th.c (124204B)


      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: Tomahawk L3 function implementations
      9  */
     10 
     11 #include <soc/defs.h>
     12 #include <shared/bsl.h>
     13 
     14 #if defined(INCLUDE_L3) && defined(ALPM_ENABLE)
     15 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT)
     16 
     17 #include <soc/drv.h>
     18 #include <bcm/vlan.h>
     19 #include <bcm/error.h>
     20 
     21 #include <bcm/l3.h>
     22 #include <soc/l3x.h>
     23 #include <soc/lpm.h>
     24 
     25 #include <soc/alpm.h>
     26 #include <soc/esw/alpm_int.h>
     27 
     28 #include <soc/tomahawk.h>
     29 #include <bcm/tunnel.h>
     30 #include <bcm/debug.h>
     31 #include <bcm/error.h>
     32 #include <bcm/stack.h>
     33 #include <soc/trident2.h>
     34 
     35 #include <bcm_int/esw/tomahawk.h>
     36 #include <bcm_int/esw/trident2.h>
     37 #include <bcm_int/esw/firebolt.h>
     38 #include <bcm_int/esw/triumph.h>
     39 #include <bcm_int/esw/triumph2.h>
     40 #include <bcm_int/esw/stack.h>
     41 #include <bcm_int/esw/flex_ctr.h>
     42 #include <bcm_int/esw_dispatch.h>
     43 #include <bcm_int/esw/flex_ctr.h>
     44 #include <bcm_int/esw/virtual.h>
     45 #include <bcm_int/esw/qos.h>
     46 
     47 #if defined(BCM_TRX_SUPPORT) 
     48 #include <bcm_int/esw/trx.h>
     49 #endif /* BCM_TRX_SUPPORT */
     50 
     51 extern int l3_alpm_ipv4_double_wide[SOC_MAX_NUM_DEVICES];
     52 
     53 /*
     54  * Function:
     55  *      _bcm_th_alpm_lpm_vrf_init
     56  * Purpose:
     57  *      Service routine used to translate API vrf id to hw specific.
     58  * Parameters:
     59  *      unit      - (IN)SOC unit number.
     60  *      lpm_cfg   - (IN)Prefix info.
     61  *      vrf_id    - (OUT)Internal vrf id.
     62  *      vrf_mask  - (OUT)Internal vrf mask.
     63  * Returns:
     64  *      BCM_E_XXX
     65  */
     66 STATIC int
     67 _bcm_th_alpm_lpm_vrf_init(int unit, _bcm_defip_cfg_t *lpm_cfg,
     68                           int *vrf_id, int *vrf_mask)
     69 {
     70     /* Handle special vrf id cases. */
     71     switch (lpm_cfg->defip_vrf) {
     72       case BCM_L3_VRF_OVERRIDE:
     73       case BCM_L3_VRF_GLOBAL: /* only for td2 */
     74           *vrf_id = 0;
     75           *vrf_mask = 0;
     76           break;
     77       default:
     78           *vrf_id = lpm_cfg->defip_vrf;
     79           *vrf_mask = SOC_VRF_MAX(unit);
     80           break;
     81     }
     82 
     83     /* In any case vrf id shouldn't exceed max field mask. */
     84     if ((*vrf_id < 0) || (*vrf_id > SOC_VRF_MAX(unit))) {
     85         return (BCM_E_PARAM);
     86     }
     87     return (BCM_E_NONE);
     88 }
     89 
     90 /*
     91  * Function:
     92  *     _bcm_th_alpm_lpm64_key_init
     93  * Purpose:
     94  *    Set an IP6 address field in L3_DEFIPm
     95  * Parameters:
     96  *    unit    - (IN) SOC unit number;
     97  *    lpm_key - (OUT) Buffer to fill.
     98  *    lpm_cfg - (IN) Route information.
     99  *    alpm_entry - (OUT) ALPM entry to fill
    100  * Note:
    101  *    See soc_mem_ip6_addr_set()
    102  */
    103 STATIC void
    104 _bcm_th_alpm_lpm64_key_init(int unit, _bcm_defip_cfg_t *lpm_cfg,
    105                             defip_entry_t *lpm_key)
    106 {
    107     bcm_ip6_t mask;                      /* Subnet mask.        */
    108     uint8 *ip6;                 /* Ip6 address.       */
    109     uint32 ip6_word[2];         /* Temp storage.      */
    110     int idx;                    /* Iteration index .  */
    111 
    112     /* Just to keep variable name short. */
    113     ip6 = lpm_cfg->defip_ip6_addr;
    114 
    115     /* Create mask from prefix length. */
    116     bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len);
    117 
    118     /* Apply subnet mask */
    119     idx = lpm_cfg->defip_sub_len / 8;   /* Unchanged byte count.    */
    120     ip6[idx] &= mask[idx];      /* Apply mask on next byte. */
    121     for (idx++; idx < BCM_IP6_ADDRLEN; idx++) {
    122         ip6[idx] = 0;           /* Reset rest of bytes.     */
    123     }
    124 
    125     ip6_word[1] = ((ip6[0] << 24) | (ip6[1] << 16) | (ip6[2] << 8) | (ip6[3]));
    126     ip6_word[0]= ((ip6[4] << 24) | (ip6[5] << 16) | (ip6[6] << 8) | (ip6[7]));
    127 
    128     /* Set IP Addr */
    129     soc_L3_DEFIPm_field_set(unit, lpm_key, IP_ADDR1f, (void *)&ip6_word[1]);
    130     soc_L3_DEFIPm_field_set(unit, lpm_key, IP_ADDR0f, (void *)&ip6_word[0]);
    131 
    132     /* Set IP MASK */
    133     ip6_word[0] = ((mask[0] << 24) | (mask[1] << 16) | (mask[2] << 8) | (mask[3]));
    134     soc_L3_DEFIPm_field_set(unit, lpm_key, IP_ADDR_MASK1f, (void *)&ip6_word[0]);
    135 
    136     ip6_word[0] = ((mask[4] << 24) | (mask[5] << 16) | (mask[6] << 8) | (mask[7]));
    137     soc_L3_DEFIPm_field_set(unit, lpm_key, IP_ADDR_MASK0f, (void *)&ip6_word[0]);
    138 }
    139 
    140 
    141 /*
    142  * Function:
    143  *      _bcm_th_alpm_lpm_init
    144  * Purpose:
    145  *      Service routine used to initialize lkup key for lpm entry.
    146  *      Also initializes the ALPM SRAM entry.
    147  * Parameters:
    148  *      unit      - (IN)SOC unit number.
    149  *      lpm_cfg   - (IN)Prefix info.
    150  *      lpm_entry - (OUT)Hw buffer to fill.
    151  * Returns:
    152  *      BCM_E_XXX
    153  */
    154 STATIC int
    155 _bcm_th_alpm_lpm_init(int unit, _bcm_defip_cfg_t *lpm_cfg,
    156                       defip_entry_t *lpm_entry, int nh_ecmp_idx, uint32 *flags)
    157 {
    158     bcm_ip_t ip4_mask;
    159     int vrf_id;
    160     int vrf_mask;
    161     int ipv6;
    162 
    163     ipv6 = lpm_cfg->defip_flags & BCM_L3_IP6;
    164 
    165     /* Extract entry  vrf id  & vrf mask. */
    166     BCM_IF_ERROR_RETURN
    167         (_bcm_th_alpm_lpm_vrf_init(unit, lpm_cfg, &vrf_id, &vrf_mask));
    168 
    169 
    170     /* Zero buffers. */
    171     sal_memset(lpm_entry, 0, BCM_XGS3_L3_ENT_SZ(unit, defip));
    172 
    173     /* Set hit bit. */
    174     if (lpm_cfg->defip_flags & BCM_L3_HIT) {
    175         soc_L3_DEFIPm_field32_set(unit, lpm_entry, HIT0f, 1);
    176     }
    177 
    178     /* Set priority override bit. */
    179     if (lpm_cfg->defip_flags & BCM_L3_RPE) {
    180         soc_L3_DEFIPm_field32_set(unit, lpm_entry, RPE0f, 1);
    181     }
    182 
    183     /* Write priority field. */
    184     soc_L3_DEFIPm_field32_set(unit, lpm_entry, PRI0f, lpm_cfg->defip_prio);
    185 
    186     /* Fill next hop information. */
    187     if (soc_feature(unit, soc_feature_generic_dest)) {
    188         uint32 dest_type = SOC_MEM_FIF_DEST_NEXTHOP;
    189         uint32 dest_val  = 0;
    190         if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) {
    191             dest_type = SOC_MEM_FIF_DEST_ECMP;
    192             dest_val  = nh_ecmp_idx;
    193         } else if (!(lpm_cfg->defip_flags & BCM_L3_IPMC)) {
    194             dest_type = SOC_MEM_FIF_DEST_NEXTHOP;
    195             dest_val  = nh_ecmp_idx;
    196         } else {
    197             dest_type = SOC_MEM_FIF_DEST_INVALID;
    198         }
    199 
    200         if (dest_type != SOC_MEM_FIF_DEST_INVALID) {
    201             soc_mem_field32_dest_set(unit, L3_DEFIPm, lpm_entry,
    202                                      DESTINATION0f, dest_type, dest_val);
    203         }
    204     } else {
    205         if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) {
    206             soc_L3_DEFIPm_field32_set(unit, lpm_entry, ECMP0f, 1);
    207             soc_L3_DEFIPm_field32_set(unit, lpm_entry, NEXT_HOP_INDEX0f,
    208                                       nh_ecmp_idx);
    209         } else if (!(lpm_cfg->defip_flags & BCM_L3_IPMC)) {
    210             soc_L3_DEFIPm_field32_set(unit, lpm_entry, NEXT_HOP_INDEX0f,
    211                                       nh_ecmp_idx);
    212         }
    213     }
    214 
    215     /* Set destination discard flag. */
    216     if (lpm_cfg->defip_flags & BCM_L3_DST_DISCARD) {
    217         soc_L3_DEFIPm_field32_set(unit, lpm_entry, DST_DISCARD0f, 1);
    218     }
    219 
    220     /* remember src discard flag */
    221     if (lpm_cfg->defip_flags & BCM_L3_SRC_DISCARD) {
    222         *flags |= SOC_ALPM_RPF_SRC_DISCARD;
    223     }
    224 
    225     if (soc_feature(unit, soc_feature_alpm_flex_stat)) {
    226         *flags |= SOC_ALPM_STAT_FLEX;
    227         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, ENTRY_VIEW0f,
    228             _soc_th_alpm_lpm_entry_view_get(unit, ipv6, 0x1));
    229     }
    230 
    231     /* Set classification group id. */
    232     soc_L3_DEFIPm_field32_set(unit, lpm_entry, CLASS_ID0f, 
    233                               lpm_cfg->defip_lookup_class);
    234 
    235     /* Set Global route flag. */
    236     if (BCM_L3_VRF_GLOBAL == lpm_cfg->defip_vrf) {
    237         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f, 0x1);
    238     }
    239 
    240     /* Indicate this is an override entry */
    241     if (BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) {
    242         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, GLOBAL_HIGH0f, 0x1);
    243         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f, 0x1);
    244     }
    245 
    246     /* Set VRF */
    247     soc_L3_DEFIPm_field32_set(unit, lpm_entry, VRF_ID_0f, vrf_id);
    248     soc_L3_DEFIPm_field32_set(unit, lpm_entry, VRF_ID_MASK0f, vrf_mask);
    249 
    250     if (soc_feature(unit, soc_feature_ipmc_defip) &&
    251             (lpm_cfg->defip_flags & BCM_L3_IPMC)) {
    252         if (soc_mem_field_valid(unit, L3_DEFIPm, MULTICAST_ROUTE0f)) {
    253             soc_L3_DEFIPm_field32_set(unit, lpm_entry, MULTICAST_ROUTE0f, 1);
    254         } else if (soc_mem_field_valid(unit, L3_DEFIPm, DATA_TYPE0f)) {
    255             soc_L3_DEFIPm_field32_set(unit, lpm_entry, DATA_TYPE0f, 2);
    256         }
    257 
    258         if (soc_feature(unit, soc_feature_generic_dest)) {
    259             if (lpm_cfg->defip_mc_group > 0) {
    260                 soc_mem_field32_dest_set(unit, L3_DEFIPm, lpm_entry, DESTINATION0f,
    261                     SOC_MEM_FIF_DEST_IPMC, lpm_cfg->defip_mc_group);
    262             }
    263         } else {
    264             soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, L3MC_INDEX0f, lpm_cfg->defip_mc_group);
    265         }
    266 
    267         /*
    268          * RP ID needs uplift by _BCM_L3_DEFIP_RP_ID_BASE value,
    269          * Now it wil fit in EXPECTED_L3_IIFf
    270          */
    271         if (lpm_cfg->defip_l3a_rp != BCM_IPMC_RP_ID_INVALID) {
    272             soc_L3_DEFIPm_field32_set(unit, lpm_entry, EXPECTED_L3_IIF0f,
    273                     _BCM_DEFIP_IPMC_RP_SET(lpm_cfg->defip_l3a_rp));
    274         } else if ((lpm_cfg->defip_ipmc_flags & BCM_IPMC_POST_LOOKUP_RPF_CHECK)
    275                 && (lpm_cfg->defip_expected_intf != 0))  {
    276 
    277             soc_L3_DEFIPm_field32_set(unit, lpm_entry, EXPECTED_L3_IIF0f,
    278                     lpm_cfg->defip_expected_intf);
    279 
    280             if (lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_DROP) {
    281                 soc_L3_DEFIPm_field32_set(unit, lpm_entry,
    282                         IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f, 1);
    283             }
    284             if (lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_TOCPU) {
    285                 soc_L3_DEFIPm_field32_set(unit, lpm_entry,
    286                         IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f, 1);
    287             }
    288         }
    289     }
    290 
    291     if (ipv6) {
    292         /* Set prefix ip address & mask. */
    293         _bcm_th_alpm_lpm64_key_init(unit, lpm_cfg, lpm_entry);
    294 
    295         /* Set second part valid bit. */
    296         soc_L3_DEFIPm_field32_set(unit, lpm_entry, VALID1f, 1);
    297 
    298         /* Set mode to ipv6 */
    299         soc_L3_DEFIPm_field32_set(unit, lpm_entry, MODE0_f(unit), 1);
    300         soc_L3_DEFIPm_field32_set(unit, lpm_entry, MODE1_f(unit), 1);
    301 
    302         /* Set Virtual Router id */
    303         soc_L3_DEFIPm_field32_set(unit, lpm_entry, VRF_ID_1f, vrf_id);
    304         soc_L3_DEFIPm_field32_set(unit, lpm_entry, VRF_ID_MASK1f, vrf_mask);
    305     } else {
    306         ip4_mask = BCM_IP4_MASKLEN_TO_ADDR(lpm_cfg->defip_sub_len);
    307         /* Apply subnet mask. */
    308         lpm_cfg->defip_ip_addr &= ip4_mask;
    309 
    310         /* Set address to the buffer. */
    311         soc_L3_DEFIPm_field32_set(unit, lpm_entry, IP_ADDR0f,
    312                                   lpm_cfg->defip_ip_addr);
    313         soc_L3_DEFIPm_field32_set(unit, lpm_entry, IP_ADDR_MASK0f, ip4_mask);
    314     }
    315     soc_L3_DEFIPm_field32_set(unit, lpm_entry, VALID0f, 1);
    316     if (SOC_MEM_FIELD_VALID(unit, L3_DEFIPm, DWf)) {
    317         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, DWf, 0);
    318     }
    319 
    320     /* Set Mode Masks */
    321     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, MODE_MASK0_f(unit),
    322                         (1 << soc_mem_field_length(unit, L3_DEFIPm, MODE_MASK0_f(unit))) - 1);
    323     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, MODE_MASK1_f(unit),
    324                         (1 << soc_mem_field_length(unit, L3_DEFIPm, MODE_MASK1_f(unit))) - 1);
    325 
    326     /* Set Entry Type Masks */
    327     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, ENTRY_TYPE0_f(unit),
    328                         (1 << soc_mem_field_length(unit, L3_DEFIPm, ENTRY_TYPE0_f(unit))) - 1);
    329     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, ENTRY_TYPE1_f(unit),
    330                         (1 << soc_mem_field_length(unit, L3_DEFIPm, ENTRY_TYPE1_f(unit))) - 1);
    331     /* 
    332      * Note ipv4 entries are expected to reside in part 0 of the entry.
    333      */
    334 
    335     /* Base counter index. */
    336     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, FLEX_CTR_BASE_COUNTER_IDX0f,
    337                         lpm_cfg->defip_flex_ctr_base_id);
    338     /* Counter offset mode. */
    339     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, FLEX_CTR_OFFSET_MODE0f,
    340                         lpm_cfg->defip_flex_ctr_mode);
    341     /* Counter pool number. */
    342     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, FLEX_CTR_POOL_NUMBER0f,
    343                         lpm_cfg->defip_flex_ctr_pool);
    344 
    345     return (BCM_E_NONE);
    346 }
    347 
    348 
    349 /*
    350  * Function:
    351  *     _bcm_th_alpm_lpm128_addr_init
    352  * Purpose:
    353  *     Set IP6 address field in memory from ip6 addr type.
    354  * Parameters:
    355  *     unit  - (IN) BCM device number.
    356  *     mem   - (IN) Memory id.
    357  *     entry - (IN) HW entry buffer.
    358  *     ip6   - (IN) SW ip6 address buffer.
    359  * Returns:      void
    360  */
    361 STATIC void
    362 _bcm_th_alpm_lpm128_addr_init(int unit, soc_mem_t mem, uint32 *entry,
    363                               const ip6_addr_t ip6)
    364 {
    365     uint32              ip6_field[4];
    366     ip6_field[3] = ((ip6[12] << 24)| (ip6[13] << 16) |
    367                     (ip6[14] << 8) | (ip6[15] << 0));
    368     soc_mem_field_set(unit, mem, entry, IP_ADDR0_LWRf, &ip6_field[3]);
    369     ip6_field[2] = ((ip6[8] << 24) | (ip6[9] << 16) |
    370                     (ip6[10] << 8) | (ip6[11] << 0));
    371     soc_mem_field_set(unit, mem, entry, IP_ADDR1_LWRf, &ip6_field[2]);
    372     ip6_field[1] = ((ip6[4] << 24) | (ip6[5] << 16) |
    373                     (ip6[6] << 8)  | (ip6[7] << 0));
    374     soc_mem_field_set(unit, mem, entry, IP_ADDR0_UPRf, &ip6_field[1]);
    375     ip6_field[0] = ((ip6[0] << 24) | (ip6[1] << 16) |
    376                     (ip6[2] << 8)  | (ip6[3] << 0));
    377     soc_mem_field_set(unit, mem, entry, IP_ADDR1_UPRf, ip6_field);
    378 }
    379 
    380 /*
    381  * Function:
    382  *     _bcm_th_alpm_lpm128_mask_init
    383  * Purpose:
    384  *     Set IP6 mask field in memory from ip6 addr type.
    385  * Parameters:
    386  *     unit  - (IN) BCM device number.
    387  *     mem   - (IN) Memory id.
    388  *     entry - (IN) HW entry buffer.
    389  *     ip6   - (IN) SW ip6 address buffer.
    390  * Returns:      void
    391  */
    392 STATIC void
    393 _bcm_th_alpm_lpm128_mask_init(int unit, soc_mem_t mem, uint32 *entry,
    394                               const ip6_addr_t ip6)
    395 {
    396     uint32              ip6_field[4];
    397     ip6_field[3] = ((ip6[12] << 24)| (ip6[13] << 16) |
    398                     (ip6[14] << 8) | (ip6[15] << 0));
    399     soc_mem_field_set(unit, mem, entry, IP_ADDR_MASK0_LWRf, &ip6_field[3]);
    400     ip6_field[2] = ((ip6[8] << 24) | (ip6[9] << 16) |
    401                     (ip6[10] << 8) | (ip6[11] << 0));
    402     soc_mem_field_set(unit, mem, entry, IP_ADDR_MASK1_LWRf, &ip6_field[2]);
    403     ip6_field[1] = ((ip6[4] << 24) | (ip6[5] << 16) |
    404                     (ip6[6] << 8)  | (ip6[7] << 0));
    405     soc_mem_field_set(unit, mem, entry, IP_ADDR_MASK0_UPRf, &ip6_field[1]);
    406     ip6_field[0] = ((ip6[0] << 24) | (ip6[1] << 16) |
    407                     (ip6[2] << 8)  | (ip6[3] << 0));
    408     soc_mem_field_set(unit, mem, entry, IP_ADDR_MASK1_UPRf, ip6_field);
    409 }
    410 
    411 STATIC int
    412 _bcm_th_alpm_lpm128_init(int unit, _bcm_defip_cfg_t *lpm_cfg,
    413              defip_pair_128_entry_t *lpm_entry, int nh_ecmp_idx, uint32 *flags)
    414 {
    415     int vrf_id;
    416     int vrf_mask;
    417     bcm_ip6_t mask;                          /* Subnet mask.              */
    418 
    419     /* Extract entry  vrf id  & vrf mask. */
    420     BCM_IF_ERROR_RETURN
    421         (_bcm_th_alpm_lpm_vrf_init(unit, lpm_cfg, &vrf_id, &vrf_mask));
    422 
    423     /* Zero buffers. */
    424     sal_memset(lpm_entry, 0, sizeof(*lpm_entry));
    425 
    426     /* Set hit bit. */
    427     if (lpm_cfg->defip_flags & BCM_L3_HIT) {
    428         soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, HITf, 1);
    429     }
    430 
    431     /* Set priority override bit. */
    432     if (lpm_cfg->defip_flags & BCM_L3_RPE) {
    433         soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, RPEf, 1);
    434     }
    435 
    436     /* Write priority field. */
    437     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, PRIf, lpm_cfg->defip_prio);
    438 
    439     /* Fill next hop information. */
    440     if (soc_feature(unit, soc_feature_generic_dest)) {
    441         uint32 dest_type = SOC_MEM_FIF_DEST_NEXTHOP;
    442         uint32 dest_val  = 0;
    443         if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) {
    444             dest_type = SOC_MEM_FIF_DEST_ECMP;
    445             dest_val  = nh_ecmp_idx;
    446         } else if (!(lpm_cfg->defip_flags & BCM_L3_IPMC)) {
    447             dest_type = SOC_MEM_FIF_DEST_NEXTHOP;
    448             dest_val  = nh_ecmp_idx;
    449         } else {
    450             dest_type = SOC_MEM_FIF_DEST_INVALID;
    451         }
    452 
    453         if (dest_type != SOC_MEM_FIF_DEST_INVALID) {
    454             soc_mem_field32_dest_set(unit, L3_DEFIP_PAIR_128m, lpm_entry,
    455                                      DESTINATIONf, dest_type, dest_val);
    456         }
    457     } else {
    458         if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) {
    459             soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, ECMPf, 1);
    460             soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, NEXT_HOP_INDEXf,
    461                                       nh_ecmp_idx);
    462         } else if (!(lpm_cfg->defip_flags & BCM_L3_IPMC)) {
    463             soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, NEXT_HOP_INDEXf,
    464                                       nh_ecmp_idx);
    465         }
    466     }
    467 
    468     /* Set destination discard flag. */
    469     if (lpm_cfg->defip_flags & BCM_L3_DST_DISCARD) {
    470         soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, DST_DISCARDf, 1);
    471     }
    472 
    473     /* remember src discard flag */
    474     if (lpm_cfg->defip_flags & BCM_L3_SRC_DISCARD) {
    475         *flags |= SOC_ALPM_RPF_SRC_DISCARD;
    476     }
    477 
    478     if (soc_feature(unit, soc_feature_alpm_flex_stat)) {
    479         *flags |= SOC_ALPM_STAT_FLEX;
    480         soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, ENTRY_VIEWf,
    481             _soc_th_alpm_lpm_entry_view_get(unit, L3_DEFIP_MODE_128, 0x1));
    482     }
    483 
    484     /* Set classification group id. */
    485     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, CLASS_IDf, 
    486                               lpm_cfg->defip_lookup_class);
    487 
    488     /* Set Global route flag. */
    489     if (BCM_L3_VRF_GLOBAL == lpm_cfg->defip_vrf) {
    490         soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, GLOBAL_ROUTEf, 0x1);
    491     }
    492 
    493     /* Indicate this is an override entry */
    494     if (BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) {
    495         soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, GLOBAL_HIGHf, 0x1);
    496         soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, GLOBAL_ROUTEf, 0x1);
    497     }
    498 
    499     if (soc_feature(unit, soc_feature_ipmc_defip) &&
    500             (lpm_cfg->defip_flags & BCM_L3_IPMC)) {
    501         if (soc_mem_field_valid(unit, L3_DEFIP_PAIR_128m, MULTICAST_ROUTEf)) {
    502             soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry,
    503                     MULTICAST_ROUTEf, 1);
    504         } else if (soc_mem_field_valid(unit, L3_DEFIP_PAIR_128m, DATA_TYPEf)) {
    505             soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry,
    506                     DATA_TYPEf, 2);
    507         }
    508 
    509         if (soc_feature(unit, soc_feature_generic_dest)) {
    510             if (lpm_cfg->defip_mc_group > 0) {
    511                 soc_mem_field32_dest_set(unit, L3_DEFIP_PAIR_128m, lpm_entry,
    512                                          DESTINATIONf, SOC_MEM_FIF_DEST_IPMC,
    513                                          lpm_cfg->defip_mc_group);
    514             }
    515         } else {
    516             soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, L3MC_INDEXf,
    517                     lpm_cfg->defip_mc_group);
    518         }
    519 
    520         /*
    521          * RP ID needs uplift by _BCM_L3_DEFIP_RP_ID_BASE value,
    522          * Now it wil fit in EXPECTED_L3_IIFf
    523          */
    524         if (lpm_cfg->defip_l3a_rp != BCM_IPMC_RP_ID_INVALID) {
    525             soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry,
    526                     EXPECTED_L3_IIFf, _BCM_DEFIP_IPMC_RP_SET(lpm_cfg->defip_l3a_rp));
    527         } else if ((lpm_cfg->defip_ipmc_flags & BCM_IPMC_POST_LOOKUP_RPF_CHECK) &&
    528                 (lpm_cfg->defip_expected_intf != 0))  {
    529 
    530             soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry,
    531                     EXPECTED_L3_IIFf, lpm_cfg->defip_expected_intf);
    532 
    533             if (lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_DROP) {
    534                 soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry,
    535                         IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf, 1);
    536             }
    537             if (lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_TOCPU) {
    538                 soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry,
    539                         IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf, 1);
    540             }
    541         }
    542     }
    543 
    544     /* Create mask from prefix length. */
    545     bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len);
    546 
    547     /* Apply mask on address. */
    548     bcm_xgs3_l3_mask6_apply(mask, lpm_cfg->defip_ip6_addr);
    549 
    550     /* Set prefix ip address & mask. */
    551     _bcm_th_alpm_lpm128_addr_init(unit, L3_DEFIP_PAIR_128m,
    552                                   (uint32 *)lpm_entry,
    553                                   lpm_cfg->defip_ip6_addr);
    554 
    555     _bcm_th_alpm_lpm128_mask_init(unit, L3_DEFIP_PAIR_128m,
    556                                   (uint32 *)lpm_entry, mask);
    557 
    558     /* Set Virtual Router id */
    559     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, VRF_ID_0_LWRf, vrf_id);
    560     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, VRF_ID_1_LWRf, vrf_id);
    561     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, VRF_ID_0_UPRf, vrf_id);
    562     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, VRF_ID_1_UPRf, vrf_id);
    563 
    564     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, VRF_ID_MASK0_LWRf, 
    565                                        vrf_mask);
    566     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, VRF_ID_MASK1_LWRf, 
    567                                        vrf_mask);
    568     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, VRF_ID_MASK0_UPRf, 
    569                                        vrf_mask);
    570     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, VRF_ID_MASK1_UPRf, 
    571                                        vrf_mask);
    572 
    573     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, VALID0_LWRf, 1);
    574     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, VALID1_LWRf, 1);
    575     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, VALID0_UPRf, 1);
    576     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, VALID1_UPRf, 1);
    577     if (SOC_MEM_FIELD_VALID(unit, L3_DEFIP_PAIR_128m, DWf)) {
    578         soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, DWf, 1);
    579     }
    580 
    581     /* Set mode to ipv6-128 */
    582     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, MODE0_LWR_f(unit), 3);
    583     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, MODE1_LWR_f(unit), 3);
    584     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, MODE0_UPR_f(unit), 3);
    585     soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, MODE1_UPR_f(unit), 3);
    586 
    587     /* Set Mode Masks */
    588     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, MODE_MASK0_LWR_f(unit),
    589     (1 << soc_mem_field_length(unit, L3_DEFIP_PAIR_128m, MODE_MASK0_LWR_f(unit))) - 1);
    590     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, MODE_MASK1_LWR_f(unit),
    591     (1 << soc_mem_field_length(unit, L3_DEFIP_PAIR_128m, MODE_MASK1_LWR_f(unit))) - 1);
    592     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, MODE_MASK0_UPR_f(unit),
    593     (1 << soc_mem_field_length(unit, L3_DEFIP_PAIR_128m, MODE_MASK0_UPR_f(unit))) - 1);
    594     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, MODE_MASK1_UPR_f(unit),
    595     (1 << soc_mem_field_length(unit, L3_DEFIP_PAIR_128m, MODE_MASK1_UPR_f(unit))) - 1);
    596 
    597     /* Set Entry Type Masks */
    598     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, ENTRY_TYPE0_LWR_f(unit),
    599      (1<<soc_mem_field_length(unit, L3_DEFIP_PAIR_128m, ENTRY_TYPE0_LWR_f(unit))) - 1);
    600     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, ENTRY_TYPE1_LWR_f(unit),
    601      (1<<soc_mem_field_length(unit, L3_DEFIP_PAIR_128m, ENTRY_TYPE1_LWR_f(unit))) - 1);
    602     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, ENTRY_TYPE0_UPR_f(unit),
    603      (1<<soc_mem_field_length(unit, L3_DEFIP_PAIR_128m, ENTRY_TYPE0_UPR_f(unit))) - 1);
    604     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, ENTRY_TYPE1_UPR_f(unit),
    605      (1<<soc_mem_field_length(unit, L3_DEFIP_PAIR_128m, ENTRY_TYPE1_UPR_f(unit))) - 1);
    606 
    607     /* Base counter index. */
    608     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, FLEX_CTR_BASE_COUNTER_IDXf,
    609                         lpm_cfg->defip_flex_ctr_base_id);
    610     /* Counter offset mode. */
    611     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, FLEX_CTR_OFFSET_MODEf,
    612                         lpm_cfg->defip_flex_ctr_mode);
    613     /* Counter pool number. */
    614     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, FLEX_CTR_POOL_NUMBERf,
    615                         lpm_cfg->defip_flex_ctr_pool);
    616     return (BCM_E_NONE);
    617 }
    618 
    619 /*
    620  * Function:
    621  *     _bcm_th_alpm_lpm64_key_parse
    622  * Purpose:
    623  *    Set an IP6 address field in L3_DEFIPm
    624  * Note:
    625  *    See soc_mem_ip6_addr_set()
    626  */
    627 STATIC void
    628 _bcm_th_alpm_lpm64_key_parse(int unit, const void *lpm_key,
    629                              _bcm_defip_cfg_t *lpm_cfg)
    630 {
    631     uint8 *ip6;                 /* Ip6 address.       */
    632     uint8 mask[BCM_IP6_ADDRLEN];        /* Subnet mask.       */
    633     uint32 ip6_word;            /* Temp storage.      */
    634 
    635     sal_memset(mask, 0, sizeof (bcm_ip6_t));
    636 
    637     /* Just to keep variable name short. */
    638     ip6 = lpm_cfg->defip_ip6_addr;
    639     sal_memset(ip6, 0, sizeof (bcm_ip6_t));
    640 
    641     soc_L3_DEFIPm_field_get(unit, lpm_key, IP_ADDR1f, &ip6_word);
    642     ip6[0] = (uint8) ((ip6_word >> 24) & 0xff);
    643     ip6[1] = (uint8) ((ip6_word >> 16) & 0xff);
    644     ip6[2] = (uint8) ((ip6_word >> 8) & 0xff);
    645     ip6[3] = (uint8) (ip6_word & 0xff);
    646 
    647     soc_L3_DEFIPm_field_get(unit, lpm_key, IP_ADDR0f, &ip6_word);
    648     ip6[4] = (uint8) ((ip6_word >> 24) & 0xff);
    649     ip6[5] = (uint8) ((ip6_word >> 16) & 0xff);
    650     ip6[6] = (uint8) ((ip6_word >> 8) & 0xff);
    651     ip6[7] = (uint8) (ip6_word & 0xff);
    652 
    653     soc_L3_DEFIPm_field_get(unit, lpm_key, IP_ADDR_MASK1f, &ip6_word);
    654     mask[0] = (uint8) ((ip6_word >> 24) & 0xff);
    655     mask[1] = (uint8) ((ip6_word >> 16) & 0xff);
    656     mask[2] = (uint8) ((ip6_word >> 8) & 0xff);
    657     mask[3] = (uint8) (ip6_word & 0xff);
    658 
    659     soc_L3_DEFIPm_field_get(unit, lpm_key, IP_ADDR_MASK0f, &ip6_word);
    660     mask[4] = (uint8) ((ip6_word >> 24) & 0xff);
    661     mask[5] = (uint8) ((ip6_word >> 16) & 0xff);
    662     mask[6] = (uint8) ((ip6_word >> 8) & 0xff);
    663     mask[7] = (uint8) (ip6_word & 0xff);
    664 
    665     lpm_cfg->defip_sub_len = bcm_ip6_mask_length(mask);
    666 }
    667 
    668 /*
    669  * Function:
    670  *      _bcm_th_alpm_lpm_key_parse
    671  * Purpose:
    672  *      Parse entry key from DEFIP table.
    673  * Parameters:
    674  *      unit        - (IN)SOC unit number.
    675  *      lpm_cfg     - (OUT)Buffer to fill defip information.
    676  *      lpm_entry   - (IN) Buffer read from hw.
    677  * Returns:
    678  *      void
    679  */
    680 STATIC void
    681 _bcm_th_alpm_lpm_key_parse(int unit, _bcm_defip_cfg_t *lpm_cfg,
    682                            defip_entry_t *lpm_entry)
    683 {
    684     bcm_ip_t v4_mask;
    685     int ipv6 = lpm_cfg->defip_flags & BCM_L3_IP6, tmp;
    686 
    687     /* Set prefix ip address & mask. */
    688     if (ipv6) {
    689         _bcm_th_alpm_lpm64_key_parse(unit, lpm_entry, lpm_cfg);
    690     } else {
    691         /* Get ipv4 address. */
    692         lpm_cfg->defip_ip_addr =
    693             soc_L3_DEFIPm_field32_get(unit, lpm_entry, IP_ADDR0f);
    694 
    695         /* Get subnet mask. */
    696         v4_mask = soc_L3_DEFIPm_field32_get(unit, lpm_entry, IP_ADDR_MASK0f);
    697 
    698         /* Fill mask length. */
    699         lpm_cfg->defip_sub_len = bcm_ip_mask_length(v4_mask);
    700     }
    701 
    702     /* Get Virtual Router id */
    703     (void)soc_th_alpm_lpm_vrf_get(unit, lpm_entry, &lpm_cfg->defip_vrf, &tmp);
    704 
    705     return;
    706 }
    707 
    708 
    709 /*
    710  * Function:
    711  *      _bcm_th_alpm_lpm_data_parse
    712  * Purpose:
    713  *      Parse an entry from DEFIP table.
    714  * Parameters:
    715  *      unit        - (IN)SOC unit number.
    716  *      lpm_cfg     - (OUT)Buffer to fill defip information.
    717  *      nh_ecmp_idx - (OUT)Next hop index or ecmp group id.
    718  *      lpm_entry   - (IN) Buffer read from hw.
    719  * Returns:
    720  *      void
    721  */
    722 STATIC INLINE void
    723 _bcm_th_alpm_lpm_data_parse(int unit, _bcm_defip_cfg_t *lpm_cfg,
    724                             int *p_nh_ecmp_idx, defip_entry_t *lpm_entry)
    725 {
    726     int is_ecmp = 0;
    727     uint32 nh_ecmp_idx = 0;
    728     int ipv6 = soc_L3_DEFIPm_field32_get(unit, lpm_entry, MODE0_f(unit));
    729 
    730     /* Reset entry flags first. */
    731     lpm_cfg->defip_flags = 0;
    732 
    733     /* Check if entry points to ecmp group. */
    734     if (soc_feature(unit, soc_feature_generic_dest)) {
    735         uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
    736         nh_ecmp_idx = soc_mem_field32_dest_get(unit, L3_DEFIPm, lpm_entry,
    737                                                DESTINATION0f, &dest_type);
    738         if (dest_type == SOC_MEM_FIF_DEST_ECMP) {
    739             is_ecmp = 1;
    740         } else if (dest_type != SOC_MEM_FIF_DEST_NEXTHOP) {
    741             nh_ecmp_idx = 0;
    742         }
    743     } else {
    744         is_ecmp = soc_L3_DEFIPm_field32_get(unit, lpm_entry, ECMP0f);
    745         if (is_ecmp) {
    746             nh_ecmp_idx = soc_L3_DEFIPm_field32_get(unit, lpm_entry, ECMP_PTR0f);
    747         } else {
    748             nh_ecmp_idx = soc_L3_DEFIPm_field32_get(unit, lpm_entry, NEXT_HOP_INDEX0f);
    749         }
    750     }
    751 
    752     /* Check if entry points to ecmp group. */
    753     if (is_ecmp) {
    754         /* Mark entry as ecmp */
    755         lpm_cfg->defip_ecmp = 1;
    756         lpm_cfg->defip_flags |= BCM_L3_MULTIPATH;
    757 
    758         /* Get ecmp group id. */
    759         if (p_nh_ecmp_idx) {
    760             *p_nh_ecmp_idx = nh_ecmp_idx;
    761         }
    762     } else {
    763         /* Mark entry as non-ecmp. */
    764         lpm_cfg->defip_ecmp = 0;
    765 
    766         /* Reset ecmp group next hop count. */
    767         lpm_cfg->defip_ecmp_count = 0;
    768 
    769         /* Get next hop index. */
    770         if (p_nh_ecmp_idx) {
    771             *p_nh_ecmp_idx = nh_ecmp_idx;
    772         }
    773     }
    774     /* Get entry priority. */
    775     lpm_cfg->defip_prio = soc_L3_DEFIPm_field32_get(unit, lpm_entry, PRI0f);
    776 
    777     /* Get hit bit. */
    778     if (!ALPM_CTRL(unit).hit_bits_skip &&
    779         soc_L3_DEFIPm_field32_get(unit, lpm_entry, HIT0f)) {
    780         lpm_cfg->defip_flags |= BCM_L3_HIT;
    781     }
    782 
    783     /* Get priority override bit. */
    784     if (soc_L3_DEFIPm_field32_get(unit, lpm_entry, RPE0f)) {
    785         lpm_cfg->defip_flags |= BCM_L3_RPE;
    786     }
    787 
    788     /* Get destination discard flag. */
    789     if (SOC_MEM_FIELD_VALID(unit, L3_DEFIPm, DST_DISCARD0f)) {
    790         if(soc_L3_DEFIPm_field32_get(unit, lpm_entry, DST_DISCARD0f)) {
    791             lpm_cfg->defip_flags |= BCM_L3_DST_DISCARD;
    792         }
    793     }
    794 
    795 #if defined(BCM_TRX_SUPPORT)
    796     /* Set classification group id. */
    797     if (SOC_MEM_FIELD_VALID(unit, L3_DEFIPm, CLASS_ID0f)) {
    798         lpm_cfg->defip_lookup_class =
    799             soc_L3_DEFIPm_field32_get(unit, lpm_entry, CLASS_ID0f);
    800     }
    801 #endif /* BCM_TRX_SUPPORT */
    802 
    803 
    804     if (ipv6) {
    805         lpm_cfg->defip_flags |= BCM_L3_IP6;
    806         /* Get hit bit from the second part of the entry. */
    807         if (!ALPM_CTRL(unit).hit_bits_skip &&
    808             soc_L3_DEFIPm_field32_get(unit, lpm_entry, HIT1f)) {
    809             lpm_cfg->defip_flags |= BCM_L3_HIT;
    810         }
    811 
    812         /* Get priority override bit from the second part of the entry. */
    813         if (soc_L3_DEFIPm_field32_get(unit, lpm_entry, RPE1f)) {
    814             lpm_cfg->defip_flags |= BCM_L3_RPE;
    815         }
    816     }
    817 
    818     if (soc_feature(unit, soc_feature_ipmc_defip)) {
    819         int ipmc_route = 0;
    820         if (soc_mem_field_valid(unit, L3_DEFIPm, MULTICAST_ROUTE0f)) {
    821             ipmc_route = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, MULTICAST_ROUTE0f);
    822         } else if (soc_mem_field_valid(unit, L3_DEFIPm, DATA_TYPE0f)) {
    823             if (soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, DATA_TYPE0f) == 2) {
    824                 ipmc_route = 1;
    825             } else {
    826                 ipmc_route = 0;
    827             }
    828         }
    829 
    830         if (ipmc_route) {
    831             int val;
    832             lpm_cfg->defip_flags |= BCM_L3_IPMC;
    833 
    834             if (p_nh_ecmp_idx) {
    835                 *p_nh_ecmp_idx = BCM_XGS3_L3_INVALID_INDEX;
    836             }
    837             if (soc_L3_DEFIPm_field32_get(unit,
    838                         lpm_entry, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f)) {
    839                 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RPF_FAIL_DROP;
    840             }
    841             if (soc_L3_DEFIPm_field32_get(unit,
    842                         lpm_entry, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f)) {
    843                 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RPF_FAIL_TOCPU;
    844             }
    845             /*
    846              * RP ID and ExpectedIIF are overlaid.
    847              */
    848             val = soc_L3_DEFIPm_field32_get(unit,
    849                                                    lpm_entry, EXPECTED_L3_IIF0f);
    850             if (soc_feature(unit, soc_feature_l3defip_rp_l3iif_resolve)) {
    851                 int rpa_id_mask = (1 << soc_mem_field_length(unit, L3_DEFIPm, RPA_ID0f)) - 1;
    852                 /*
    853                  * 1) If value is more than RPA_ID field then its l3_iif.
    854                  *    N/A for TD3/MV2/HX5 to support warmboot.
    855                  * 2) When RPF FAIL DROP/TOCPU flags are set then its l3iif valid
    856                  */
    857                 if ((lpm_cfg->defip_ipmc_flags &
    858                      (BCM_IPMC_RPF_FAIL_DROP | BCM_IPMC_RPF_FAIL_TOCPU)) ||
    859                     (!(SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit) ||
    860                        SOC_IS_HELIX5(unit)) && (val > rpa_id_mask))) {
    861                     lpm_cfg->defip_expected_intf = val;
    862                     if (0 != lpm_cfg->defip_expected_intf) {
    863                         lpm_cfg->defip_ipmc_flags |= BCM_IPMC_POST_LOOKUP_RPF_CHECK;
    864                     }
    865                     lpm_cfg->defip_l3a_rp = BCM_IPMC_RP_ID_INVALID;
    866                 } else {
    867                     lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RP_ID_EXPECTED_INTF_RESOLVE;
    868                     lpm_cfg->defip_l3a_rp = val & rpa_id_mask;
    869                     lpm_cfg->defip_expected_intf = val;
    870                 }
    871             } else if (_BCM_DEFIP_IPMC_RP_IS_SET(val)) {
    872                 lpm_cfg->defip_l3a_rp = _BCM_DEFIP_IPMC_RP_GET(val);
    873             } else {
    874                 lpm_cfg->defip_expected_intf = val;
    875 
    876                 if (0 != lpm_cfg->defip_expected_intf) {
    877                     lpm_cfg->defip_ipmc_flags |= BCM_IPMC_POST_LOOKUP_RPF_CHECK;
    878                 }
    879                 lpm_cfg->defip_l3a_rp = BCM_IPMC_RP_ID_INVALID;
    880             }
    881 
    882             if (soc_feature(unit, soc_feature_generic_dest)) {
    883                 uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
    884                 uint32 dest_value = 0;
    885                 dest_value = soc_mem_field32_dest_get(unit,
    886                         L3_DEFIPm, lpm_entry,
    887                         DESTINATION0f, &dest_type);
    888                 if (dest_type == SOC_MEM_FIF_DEST_IPMC) {
    889                     lpm_cfg->defip_mc_group = dest_value;
    890                 } else {
    891                     lpm_cfg->defip_mc_group = 0;
    892                 }
    893             } else {
    894                 lpm_cfg->defip_mc_group = soc_mem_field32_get(unit, L3_DEFIPm,
    895                                             lpm_entry, L3MC_INDEX0f);
    896             }
    897         }
    898     }
    899 
    900     /* Read base counter index. */
    901     lpm_cfg->defip_flex_ctr_base_id =
    902         soc_L3_DEFIPm_field32_get(unit, lpm_entry, FLEX_CTR_BASE_COUNTER_IDX0f);
    903     /* Read counter offset mode. */
    904     lpm_cfg->defip_flex_ctr_mode =
    905         soc_L3_DEFIPm_field32_get(unit, lpm_entry, FLEX_CTR_OFFSET_MODE0f);
    906     /* Read counter pool number. */
    907     lpm_cfg->defip_flex_ctr_pool =
    908         soc_L3_DEFIPm_field32_get(unit, lpm_entry, FLEX_CTR_POOL_NUMBER0f);
    909 
    910 
    911     return;
    912 }
    913 
    914 /*
    915  * Function:
    916  *     _bcm_th_alpm_lpm128_mask_parse
    917  * Purpose:
    918  *     Read IP6 mask field from memory field to ip6_addr_t buffer.
    919  * Parameters:
    920  *     unit  - (IN) BCM device number.
    921  *     mem   - (IN) Memory id.
    922  *     entry - (IN) HW entry buffer.
    923  *     ip6   - (OUT) SW ip6 address buffer.
    924  * Returns:      void
    925  */
    926 STATIC void
    927 _bcm_th_alpm_lpm128_mask_parse(int unit, soc_mem_t mem, const void *entry,
    928                                ip6_addr_t ip6)
    929 {
    930     uint32              ip6_field[4];
    931     soc_mem_field_get(unit, mem, entry, IP_ADDR_MASK0_LWRf, (uint32 *)&ip6_field[3]);
    932     ip6[12] = (uint8) (ip6_field[3] >> 24);
    933     ip6[13] = (uint8) (ip6_field[3] >> 16 & 0xff);
    934     ip6[14] = (uint8) (ip6_field[3] >> 8 & 0xff);
    935     ip6[15] = (uint8) (ip6_field[3] & 0xff);
    936     soc_mem_field_get(unit, mem, entry, IP_ADDR_MASK1_LWRf, (uint32 *)&ip6_field[2]);
    937     ip6[8] = (uint8) (ip6_field[2] >> 24);
    938     ip6[9] = (uint8) (ip6_field[2] >> 16 & 0xff);
    939     ip6[10] = (uint8) (ip6_field[2] >> 8 & 0xff);
    940     ip6[11] = (uint8) (ip6_field[2] & 0xff);
    941     soc_mem_field_get(unit, mem, entry, IP_ADDR_MASK0_UPRf, (uint32 *)&ip6_field[1]);
    942     ip6[4] = (uint8) (ip6_field[1] >> 24);
    943     ip6[5] = (uint8) (ip6_field[1] >> 16 & 0xff);
    944     ip6[6] =(uint8) (ip6_field[1] >> 8 & 0xff);
    945     ip6[7] =(uint8) (ip6_field[1] & 0xff);
    946     soc_mem_field_get(unit, mem, entry, IP_ADDR_MASK1_UPRf, ip6_field);
    947     ip6[0] =(uint8) (ip6_field[0] >> 24);
    948     ip6[1] =(uint8) (ip6_field[0] >> 16 & 0xff);
    949     ip6[2] =(uint8) (ip6_field[0] >> 8 & 0xff);
    950     ip6[3] =(uint8) (ip6_field[0] & 0xff);
    951 }
    952 
    953 /*
    954  * Function:
    955  *     _bcm_th_alpm_lpm128_addr_parse
    956  * Purpose:
    957  *     Read IP6 address field from memory field to ip6_addr_t buffer.
    958  * Parameters:
    959  *     unit  - (IN) BCM device number.
    960  *     mem   - (IN) Memory id.
    961  *     entry - (IN) HW entry buffer.
    962  *     ip6   - (OUT) SW ip6 address buffer.
    963  * Returns:      void
    964  */
    965 STATIC void
    966 _bcm_th_alpm_lpm128_addr_parse(int unit, soc_mem_t mem, const void *entry,
    967                                ip6_addr_t ip6)
    968 {
    969     uint32              ip6_field[4];
    970     soc_mem_field_get(unit, mem, entry, IP_ADDR0_LWRf, (uint32 *)&ip6_field[3]);
    971     ip6[12] = (uint8) (ip6_field[3] >> 24);
    972     ip6[13] = (uint8) (ip6_field[3] >> 16 & 0xff);
    973     ip6[14] = (uint8) (ip6_field[3] >> 8 & 0xff);
    974     ip6[15] = (uint8) (ip6_field[3] & 0xff);
    975     soc_mem_field_get(unit, mem, entry, IP_ADDR1_LWRf, (uint32 *)&ip6_field[2]);
    976     ip6[8] = (uint8) (ip6_field[2] >> 24);
    977     ip6[9] = (uint8) (ip6_field[2] >> 16 & 0xff);
    978     ip6[10] = (uint8) (ip6_field[2] >> 8 & 0xff);
    979     ip6[11] = (uint8) (ip6_field[2] & 0xff);
    980     soc_mem_field_get(unit, mem, entry, IP_ADDR0_UPRf, (uint32 *)&ip6_field[1]);
    981     ip6[4] = (uint8) (ip6_field[1] >> 24);
    982     ip6[5] = (uint8) (ip6_field[1] >> 16 & 0xff);
    983     ip6[6] =(uint8) (ip6_field[1] >> 8 & 0xff);
    984     ip6[7] =(uint8) (ip6_field[1] & 0xff);
    985     soc_mem_field_get(unit, mem, entry, IP_ADDR1_UPRf, ip6_field);
    986     ip6[0] =(uint8) (ip6_field[0] >> 24);
    987     ip6[1] =(uint8) (ip6_field[0] >> 16 & 0xff);
    988     ip6[2] =(uint8) (ip6_field[0] >> 8 & 0xff);
    989     ip6[3] =(uint8) (ip6_field[0] & 0xff);
    990 }
    991 
    992 
    993 /*
    994  * Function:
    995  *      _bcm_th_alpm_lpm128_key_parse
    996  * Purpose:
    997  *      Parse route entry key from L3_DEFIP_PAIR_128 table.
    998  * Parameters:
    999  *      unit        - (IN)SOC unit number.
   1000  *      entry       - (IN)Hw entry buffer.
   1001  *      lpm_cfg     - (IN/OUT)Buffer to fill defip information.
   1002  * Returns:
   1003  *      BCM_E_XXX
   1004  */
   1005 STATIC int
   1006 _bcm_th_alpm_lpm128_key_parse(int unit, uint32 *hw_entry,
   1007                               _bcm_defip_cfg_t *lpm_cfg)
   1008 {
   1009     soc_mem_t mem = L3_DEFIP_PAIR_128m;  /* Route table memory. */
   1010     bcm_ip6_t mask;                      /* Subnet mask.        */
   1011 
   1012     /* Input parameters check. */
   1013     if ((lpm_cfg == NULL) || (hw_entry == NULL)) {
   1014         return (BCM_E_PARAM);
   1015     }
   1016 
   1017     /* Extract ip6 address. */
   1018     _bcm_th_alpm_lpm128_addr_parse(unit, mem, hw_entry,
   1019                                    lpm_cfg->defip_ip6_addr);
   1020 
   1021     /* Extract subnet mask. */
   1022     _bcm_th_alpm_lpm128_mask_parse(unit, mem, hw_entry, mask);
   1023     lpm_cfg->defip_sub_len = bcm_ip6_mask_length(mask);
   1024 
   1025     /* Extract vrf id & vrf mask. */
   1026     if(!soc_mem_field32_get(unit, mem, hw_entry, VRF_ID_MASK0_LWRf)) {
   1027         lpm_cfg->defip_vrf = BCM_L3_VRF_OVERRIDE;
   1028     } else {
   1029         lpm_cfg->defip_vrf = soc_mem_field32_get(unit, mem, hw_entry,
   1030                                                  VRF_ID_0_LWRf);
   1031     }
   1032     return (BCM_E_NONE);
   1033 }
   1034 
   1035 STATIC INLINE void
   1036 _bcm_th_alpm_lpm128_data_parse(int unit, _bcm_defip_cfg_t *lpm_cfg,
   1037                                int *p_nh_ecmp_idx, defip_pair_128_entry_t *lpm_entry)
   1038 {
   1039     int is_ecmp = 0;
   1040     uint32 nh_ecmp_idx = 0;
   1041     soc_mem_t mem = L3_DEFIP_PAIR_128m;
   1042     int ipv6 = soc_mem_field32_get(unit, mem, lpm_entry, MODE0_LWR_f(unit));
   1043 
   1044     /* Reset entry flags first. */
   1045     lpm_cfg->defip_flags = 0;
   1046 
   1047     if (soc_feature(unit, soc_feature_generic_dest)) {
   1048         uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
   1049         nh_ecmp_idx = soc_mem_field32_dest_get(unit, mem, lpm_entry,
   1050                                                DESTINATIONf, &dest_type);
   1051         if (dest_type == SOC_MEM_FIF_DEST_ECMP) {
   1052             is_ecmp = 1;
   1053         } else if (dest_type != SOC_MEM_FIF_DEST_NEXTHOP) {
   1054             nh_ecmp_idx = 0;
   1055         }
   1056     } else {
   1057         is_ecmp = soc_mem_field32_get(unit, mem, lpm_entry, ECMPf);
   1058         if (is_ecmp) {
   1059             nh_ecmp_idx = soc_mem_field32_get(unit, mem, lpm_entry, ECMP_PTRf);
   1060         } else {
   1061             nh_ecmp_idx = soc_mem_field32_get(unit, mem, lpm_entry, NEXT_HOP_INDEXf);
   1062         }
   1063     }
   1064 
   1065     /* Check if entry points to ecmp group. */
   1066     if (is_ecmp) {
   1067         /* Mark entry as ecmp */
   1068         lpm_cfg->defip_ecmp = 1;
   1069         lpm_cfg->defip_flags |= BCM_L3_MULTIPATH;
   1070 
   1071         /* Get ecmp group id. */
   1072         if (p_nh_ecmp_idx) {
   1073             *p_nh_ecmp_idx = nh_ecmp_idx;
   1074         }
   1075     } else {
   1076         /* Mark entry as non-ecmp. */
   1077         lpm_cfg->defip_ecmp = 0;
   1078 
   1079         /* Reset ecmp group next hop count. */
   1080         lpm_cfg->defip_ecmp_count = 0;
   1081 
   1082         /* Get next hop index. */
   1083         if (p_nh_ecmp_idx) {
   1084             *p_nh_ecmp_idx = nh_ecmp_idx;
   1085         }
   1086     }
   1087     /* Get entry priority. */
   1088     lpm_cfg->defip_prio =
   1089                     soc_L3_DEFIP_PAIR_128m_field32_get(unit, lpm_entry, PRIf);
   1090 
   1091     /* Get hit bit. */
   1092     if (!ALPM_CTRL(unit).hit_bits_skip &&
   1093         soc_L3_DEFIP_PAIR_128m_field32_get(unit, lpm_entry, HITf)) {
   1094         lpm_cfg->defip_flags |= BCM_L3_HIT;
   1095     }
   1096 
   1097     /* Get priority override bit. */
   1098     if (soc_L3_DEFIP_PAIR_128m_field32_get(unit, lpm_entry, RPEf)) {
   1099         lpm_cfg->defip_flags |= BCM_L3_RPE;
   1100     }
   1101 
   1102     /* Get destination discard flag. */
   1103     if (SOC_MEM_FIELD_VALID(unit, L3_DEFIP_PAIR_128m, DST_DISCARDf)) {
   1104         if(soc_L3_DEFIP_PAIR_128m_field32_get(unit, lpm_entry, DST_DISCARDf)) {
   1105             lpm_cfg->defip_flags |= BCM_L3_DST_DISCARD;
   1106         }
   1107     }
   1108 
   1109 #if defined(BCM_TRX_SUPPORT)
   1110     /* Set classification group id. */
   1111     if (SOC_MEM_FIELD_VALID(unit, L3_DEFIP_PAIR_128m, CLASS_IDf)) {
   1112         lpm_cfg->defip_lookup_class =
   1113             soc_L3_DEFIP_PAIR_128m_field32_get(unit, lpm_entry, CLASS_IDf);
   1114     }
   1115 #endif /* BCM_TRX_SUPPORT */
   1116 
   1117     if (ipv6) {
   1118         lpm_cfg->defip_flags |= BCM_L3_IP6;
   1119         /* Get hit bit from the second part of the entry. */
   1120         if (!ALPM_CTRL(unit).hit_bits_skip &&
   1121             soc_L3_DEFIP_PAIR_128m_field32_get(unit, lpm_entry, HITf)) {
   1122             lpm_cfg->defip_flags |= BCM_L3_HIT;
   1123         }
   1124 
   1125         /* Get priority override bit from the second part of the entry. */
   1126         if (soc_L3_DEFIP_PAIR_128m_field32_get(unit, lpm_entry, RPEf)) {
   1127             lpm_cfg->defip_flags |= BCM_L3_RPE;
   1128         }
   1129     }
   1130 
   1131     if (soc_feature(unit, soc_feature_ipmc_defip)) {
   1132         int ipmc_route = 0;
   1133         if (soc_mem_field_valid(unit, L3_DEFIP_PAIR_128m, MULTICAST_ROUTEf)) {
   1134             ipmc_route = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   1135                                           lpm_entry, MULTICAST_ROUTEf);
   1136         } else if (soc_mem_field_valid(unit, L3_DEFIP_PAIR_128m, DATA_TYPEf)) {
   1137             if (soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   1138                                     lpm_entry, DATA_TYPEf) == 2) {
   1139                 ipmc_route = 1;
   1140             } else {
   1141                 ipmc_route = 0;
   1142             }
   1143         }
   1144 
   1145         if (ipmc_route) {
   1146             int val;
   1147             lpm_cfg->defip_flags |= BCM_L3_IPMC;
   1148 
   1149             if (p_nh_ecmp_idx) {
   1150                 *p_nh_ecmp_idx = BCM_XGS3_L3_INVALID_INDEX;
   1151             }
   1152             if (soc_L3_DEFIP_PAIR_128m_field32_get(unit,
   1153                         lpm_entry, IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf)) {
   1154                 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RPF_FAIL_DROP;
   1155             }
   1156             if (soc_L3_DEFIP_PAIR_128m_field32_get(unit,
   1157                         lpm_entry, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf)) {
   1158                 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RPF_FAIL_TOCPU;
   1159             }
   1160             /*
   1161              * RP ID and ExpectedIIF are overlaid.
   1162              */
   1163             val = soc_L3_DEFIP_PAIR_128m_field32_get(unit,
   1164                                                    lpm_entry, EXPECTED_L3_IIFf);
   1165 
   1166             if (soc_feature(unit, soc_feature_l3defip_rp_l3iif_resolve)) {
   1167                 int rpa_id_mask =
   1168                     (1 << soc_mem_field_length(unit, L3_DEFIP_PAIR_128m, RPA_IDf)) - 1;
   1169                 /*
   1170                  * 1) If value is more than RPA_ID field then its l3_iif.
   1171                  *    N/A for TD3/MV2/HX5 to support warmboot.
   1172                  * 2) When RPF FAIL DROP/TOCPU flags are set then its l3iif valid
   1173                  */
   1174                 if ((lpm_cfg->defip_ipmc_flags &
   1175                      (BCM_IPMC_RPF_FAIL_DROP | BCM_IPMC_RPF_FAIL_TOCPU)) ||
   1176                     (!(SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit) ||
   1177                        SOC_IS_HELIX5(unit)) && (val > rpa_id_mask))) {
   1178                     lpm_cfg->defip_expected_intf = val;
   1179                     if (0 != lpm_cfg->defip_expected_intf) {
   1180                         lpm_cfg->defip_ipmc_flags |= BCM_IPMC_POST_LOOKUP_RPF_CHECK;
   1181                     }
   1182                     lpm_cfg->defip_l3a_rp = BCM_IPMC_RP_ID_INVALID;
   1183                 } else {
   1184                     lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RP_ID_EXPECTED_INTF_RESOLVE;
   1185                     lpm_cfg->defip_l3a_rp = val & rpa_id_mask;
   1186                     lpm_cfg->defip_expected_intf = val;
   1187                 }
   1188             } else if (_BCM_DEFIP_IPMC_RP_IS_SET(val)) {
   1189                 lpm_cfg->defip_l3a_rp = _BCM_DEFIP_IPMC_RP_GET(val);
   1190             } else {
   1191                 lpm_cfg->defip_expected_intf = val;
   1192 
   1193                 if (0 != lpm_cfg->defip_expected_intf) {
   1194                     lpm_cfg->defip_ipmc_flags |= BCM_IPMC_POST_LOOKUP_RPF_CHECK;
   1195                 }
   1196                 lpm_cfg->defip_l3a_rp = BCM_IPMC_RP_ID_INVALID;
   1197             }
   1198 
   1199             if (soc_feature(unit, soc_feature_generic_dest)) {
   1200                 uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
   1201                 uint32 dest_value = 0;
   1202                 dest_value = soc_mem_field32_dest_get(unit,
   1203                         L3_DEFIP_PAIR_128m, lpm_entry,
   1204                         DESTINATIONf, &dest_type);
   1205                 if (dest_type == SOC_MEM_FIF_DEST_IPMC) {
   1206                     lpm_cfg->defip_mc_group = dest_value;
   1207                 } else {
   1208                     lpm_cfg->defip_mc_group = 0;
   1209                 }
   1210             } else {
   1211                 lpm_cfg->defip_mc_group =
   1212                     soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   1213                                         lpm_entry, L3MC_INDEXf);
   1214             }
   1215         }
   1216     }
   1217 
   1218     /* Read base counter index. */
   1219     lpm_cfg->defip_flex_ctr_base_id =
   1220         soc_L3_DEFIP_PAIR_128m_field32_get(unit, lpm_entry, FLEX_CTR_BASE_COUNTER_IDXf);
   1221     /* Read counter offset mode. */
   1222     lpm_cfg->defip_flex_ctr_mode =
   1223         soc_L3_DEFIP_PAIR_128m_field32_get(unit, lpm_entry, FLEX_CTR_OFFSET_MODEf);
   1224     /* Read counter pool number. */
   1225     lpm_cfg->defip_flex_ctr_pool =
   1226         soc_L3_DEFIP_PAIR_128m_field32_get(unit, lpm_entry, FLEX_CTR_POOL_NUMBERf);
   1227 
   1228     return;
   1229 }
   1230 
   1231 
   1232 
   1233 /*
   1234  * Function:
   1235  *     _bcm_th_alpm_ent64_key_parse
   1236  * Purpose:
   1237  *    Set an IP6 address field in an ALPM memory
   1238  * Note:
   1239  *    See soc_mem_ip6_addr_set()
   1240  */
   1241 STATIC void
   1242 _bcm_th_alpm_ent64_key_parse(int unit, const void *alpm_key, soc_mem_t mem,
   1243                               _bcm_defip_cfg_t *lpm_cfg)
   1244 {
   1245     uint8 *ip6;                 /* Ip6 address.       */
   1246     uint8 mask[BCM_IP6_ADDRLEN];        /* Subnet mask.       */
   1247     uint32 ip6_word[2];            /* Temp storage.      */
   1248 
   1249     sal_memset(mask, 0, sizeof (bcm_ip6_t));
   1250 
   1251     /* Just to keep variable name short. */
   1252     ip6 = lpm_cfg->defip_ip6_addr;
   1253     sal_memset(ip6, 0, sizeof (bcm_ip6_t));
   1254 
   1255     soc_mem_field_get(unit, mem, alpm_key, KEYf, &ip6_word[0]);
   1256     ip6[0] = (uint8) ((ip6_word[1] >> 24) & 0xff);
   1257     ip6[1] = (uint8) ((ip6_word[1] >> 16) & 0xff);
   1258     ip6[2] = (uint8) ((ip6_word[1] >> 8) & 0xff);
   1259     ip6[3] = (uint8) (ip6_word[1] & 0xff);
   1260 
   1261     ip6[4] = (uint8) ((ip6_word[0] >> 24) & 0xff);
   1262     ip6[5] = (uint8) ((ip6_word[0] >> 16) & 0xff);
   1263     ip6[6] = (uint8) ((ip6_word[0] >> 8) & 0xff);
   1264     ip6[7] = (uint8) (ip6_word[0] & 0xff);
   1265 
   1266     lpm_cfg->defip_sub_len = soc_mem_field32_get(unit, mem, alpm_key, LENGTHf);
   1267 }
   1268 
   1269 /*
   1270  * Function:
   1271  *      _bcm_th_alpm_ent_key_parse
   1272  * Purpose:
   1273  *      Parse entry key from ALPM table.
   1274  * Parameters:
   1275  *      unit        - (IN) SOC unit number.
   1276  *      lpm_cfg     - (OUT)Buffer to fill defip information.
   1277  *      *lpm_entry  - (IN) Pointer to lpm buffer read from hw.
   1278  *      alpm_mem    - (IN) ALPM memory type.
   1279  *      *alpm_entry - (IN) Pointer to alpm entry read from SRAM bank.
   1280  * Returns:
   1281  *      void
   1282  */
   1283 STATIC void
   1284 _bcm_th_alpm_ent_key_parse(int unit, _bcm_defip_cfg_t *lpm_cfg,
   1285                            defip_entry_t *lpm_entry, soc_mem_t alpm_mem,
   1286                            void *alpm_entry)
   1287 {
   1288     bcm_ip_t v4_mask;
   1289     int ipv6 = lpm_cfg->defip_flags & BCM_L3_IP6;
   1290 
   1291     /* Set prefix ip address & mask. */
   1292     if (ipv6) {
   1293         _bcm_th_alpm_ent64_key_parse(unit, alpm_entry, alpm_mem, lpm_cfg);
   1294     } else {
   1295         /* Get ipv4 address. */
   1296         lpm_cfg->defip_ip_addr = soc_mem_field32_get(unit, alpm_mem,
   1297                                                      alpm_entry, KEYf);
   1298 
   1299         /* Get subnet mask. */
   1300         v4_mask = soc_mem_field32_get(unit, alpm_mem, alpm_entry, LENGTHf);
   1301         if (v4_mask) {
   1302             v4_mask = ~((1 << (32 - v4_mask)) - 1);
   1303         }
   1304 
   1305         /* Fill mask length. */
   1306         lpm_cfg->defip_sub_len = bcm_ip_mask_length(v4_mask);
   1307     }
   1308 
   1309     /* Get Virtual Router id */
   1310     (void)soc_th_alpm_lpm_vrf_get(unit, lpm_entry, &lpm_cfg->defip_vrf, &ipv6);
   1311 
   1312     return;
   1313 }
   1314 
   1315 
   1316 /*
   1317  * Function:
   1318  *      _bcm_th_alpm_ent_data_parse
   1319  * Purpose:
   1320  *      Parse an entry from DEFIP table.
   1321  * Parameters:
   1322  *      unit        - (IN)SOC unit number.
   1323  *      lpm_cfg     - (OUT)Buffer to fill defip information.
   1324  *      nh_ecmp_idx - (OUT)Next hop index or ecmp group id.
   1325  *      lpm_entry   - (IN) Buffer read from hw.
   1326  * Returns:
   1327  *      void
   1328  */
   1329 STATIC void
   1330 _bcm_th_alpm_ent_data_parse(int unit, _bcm_defip_cfg_t *lpm_cfg, int *p_nh_ecmp_idx,
   1331                             soc_mem_t alpm_mem, void *alpm_entry)
   1332 {
   1333     int is_ecmp = 0;
   1334     uint32 nh_ecmp_idx = 0;
   1335 
   1336     /* Check if entry points to ecmp group. */
   1337     if (soc_feature(unit, soc_feature_generic_dest)) {
   1338         uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
   1339         nh_ecmp_idx = soc_mem_field32_dest_get(unit, alpm_mem, alpm_entry,
   1340                                                DESTINATIONf, &dest_type);
   1341         if (dest_type == SOC_MEM_FIF_DEST_ECMP) {
   1342             is_ecmp = 1;
   1343         } else if (dest_type != SOC_MEM_FIF_DEST_NEXTHOP) {
   1344             nh_ecmp_idx = 0;
   1345         }
   1346     } else {
   1347         is_ecmp = soc_mem_field32_get(unit, alpm_mem, alpm_entry, ECMPf);
   1348         if (is_ecmp) {
   1349             nh_ecmp_idx =
   1350                 soc_mem_field32_get(unit, alpm_mem, alpm_entry, ECMP_PTRf);
   1351         } else {
   1352             nh_ecmp_idx =
   1353                 soc_mem_field32_get(unit, alpm_mem, alpm_entry,
   1354                                     NEXT_HOP_INDEXf);
   1355         }
   1356     }
   1357 
   1358     /* Reset entry flags first. */
   1359     lpm_cfg->defip_flags = 0;
   1360 
   1361     /* Check if entry points to ecmp group. */
   1362     if (is_ecmp) {
   1363         /* Mark entry as ecmp */
   1364         lpm_cfg->defip_ecmp = 1;
   1365         lpm_cfg->defip_flags |= BCM_L3_MULTIPATH;
   1366 
   1367         /* Get ecmp group id. */
   1368         if (p_nh_ecmp_idx) {
   1369             *p_nh_ecmp_idx = nh_ecmp_idx;
   1370         }
   1371     } else {
   1372         /* Mark entry as non-ecmp. */
   1373         lpm_cfg->defip_ecmp = 0;
   1374 
   1375         /* Reset ecmp group next hop count. */
   1376         lpm_cfg->defip_ecmp_count = 0;
   1377 
   1378         /* Get next hop index. */
   1379         if (p_nh_ecmp_idx) {
   1380             *p_nh_ecmp_idx = nh_ecmp_idx;
   1381         }
   1382     }
   1383     /* Get entry priority. */
   1384     lpm_cfg->defip_prio = soc_mem_field32_get(unit, alpm_mem, alpm_entry,
   1385                                               PRIf);
   1386 
   1387     /* Get hit bit. */
   1388     if (!ALPM_CTRL(unit).hit_bits_skip &&
   1389         soc_mem_field32_get(unit, alpm_mem, alpm_entry, HITf)) {
   1390         lpm_cfg->defip_flags |= BCM_L3_HIT;
   1391     }
   1392     /* Get priority override bit. */
   1393     if (soc_mem_field32_get(unit, alpm_mem, alpm_entry, RPEf)) {
   1394         lpm_cfg->defip_flags |= BCM_L3_RPE;
   1395     }
   1396 
   1397     /* Get destination discard flag. */
   1398     if (SOC_MEM_FIELD_VALID(unit, alpm_mem, DST_DISCARDf)) {
   1399         if(soc_mem_field32_get(unit, alpm_mem, alpm_entry, DST_DISCARDf)) {
   1400             lpm_cfg->defip_flags |= BCM_L3_DST_DISCARD;
   1401         }
   1402     }
   1403 
   1404     /* Set classification group id. */
   1405     lpm_cfg->defip_lookup_class = soc_mem_field32_get(unit, alpm_mem,
   1406                                                        alpm_entry, CLASS_IDf);
   1407 
   1408     if (alpm_mem == L3_DEFIP_ALPM_IPV6_64m ||
   1409         alpm_mem == L3_DEFIP_ALPM_IPV6_64_1m ||
   1410         alpm_mem == L3_DEFIP_ALPM_IPV6_128m) {
   1411         lpm_cfg->defip_flags |= BCM_L3_IP6;
   1412     }
   1413     return;
   1414 }
   1415 
   1416 
   1417 STATIC int
   1418 _bcm_th_alpm_ent128_key_parse(int unit, soc_mem_t mem, uint32 *alpm_entry,
   1419                               _bcm_defip_cfg_t *lpm_cfg)
   1420 {
   1421     uint32 ip6_word[4];
   1422 
   1423     uint8 *ip6;
   1424 
   1425     ip6 = lpm_cfg->defip_ip6_addr;
   1426 
   1427     soc_mem_field_get(unit, mem, alpm_entry, KEYf, ip6_word);
   1428     ip6[0] = (ip6_word[3] >> 24);
   1429     ip6[1] = (ip6_word[3] >> 16) & 0xff;
   1430     ip6[2] = (ip6_word[3] >> 8) & 0xff;
   1431     ip6[3] = ip6_word[3];
   1432 
   1433     ip6[4] = ip6_word[2] >> 24;
   1434     ip6[5] = (ip6_word[2] >> 16) & 0xff;
   1435     ip6[6] = (ip6_word[2] >> 8) & 0xff;
   1436     ip6[7] = ip6_word[2];
   1437 
   1438     ip6[8] = ip6_word[1] >> 24;
   1439     ip6[9] = (ip6_word[1] >> 16) & 0xff;
   1440     ip6[10] = (ip6_word[1] >> 8) & 0xff;
   1441     ip6[11] = ip6_word[1];
   1442 
   1443     ip6[12] = ip6_word[0] >> 24;
   1444     ip6[13] = (ip6_word[0] >> 16) & 0xff;
   1445     ip6[14] = (ip6_word[0] >> 8) & 0xff;
   1446     ip6[15] = ip6_word[0];
   1447 
   1448     lpm_cfg->defip_sub_len =
   1449                     soc_mem_field32_get(unit, mem, alpm_entry, LENGTHf);
   1450 
   1451     return SOC_E_NONE;
   1452 }
   1453 
   1454 STATIC int
   1455 _bcm_th_alpm_ent128_data_parse(int unit, soc_mem_t mem, uint32 *hw_entry,
   1456                                _bcm_defip_cfg_t *lpm_cfg, int *p_nh_ecmp_idx)
   1457 {
   1458     int is_ecmp = 0;
   1459     uint32 nh_ecmp_idx = 0;
   1460 
   1461     /* Input parameters check. */
   1462     if ((lpm_cfg == NULL) || (hw_entry == NULL)) {
   1463         return (BCM_E_PARAM);
   1464     }
   1465 
   1466     /* Check if entry points to ecmp group. */
   1467     if (soc_feature(unit, soc_feature_generic_dest)) {
   1468         uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
   1469         nh_ecmp_idx = soc_mem_field32_dest_get(unit, mem, hw_entry,
   1470                                                DESTINATIONf, &dest_type);
   1471         if (dest_type == SOC_MEM_FIF_DEST_ECMP) {
   1472             is_ecmp = 1;
   1473         } else if (dest_type != SOC_MEM_FIF_DEST_NEXTHOP) {
   1474             nh_ecmp_idx = 0;
   1475         }
   1476     } else {
   1477         is_ecmp = soc_mem_field32_get(unit, mem, hw_entry, ECMPf);
   1478         if (is_ecmp) {
   1479             nh_ecmp_idx = soc_mem_field32_get(unit, mem, hw_entry, ECMP_PTRf);
   1480         } else {
   1481             nh_ecmp_idx = soc_mem_field32_get(unit, mem, hw_entry, NEXT_HOP_INDEXf);
   1482         }
   1483     }
   1484 
   1485     /* Reset entry flags first. */
   1486     lpm_cfg->defip_flags = 0;
   1487 
   1488     /* Check if entry points to ecmp group. */
   1489     if (is_ecmp) {
   1490         /* Mark entry as ecmp */
   1491         lpm_cfg->defip_ecmp = TRUE;
   1492         lpm_cfg->defip_flags |= BCM_L3_MULTIPATH;
   1493 
   1494         /* Get ecmp group id. */
   1495         if (p_nh_ecmp_idx != NULL) {
   1496             *p_nh_ecmp_idx = nh_ecmp_idx;
   1497         }
   1498     } else {
   1499         /* Mark entry as non-ecmp. */
   1500         lpm_cfg->defip_ecmp = 0;
   1501 
   1502         /* Reset ecmp group next hop count. */
   1503         lpm_cfg->defip_ecmp_count = 0;
   1504 
   1505         /* Get next hop index. */
   1506         if (p_nh_ecmp_idx != NULL) {
   1507             *p_nh_ecmp_idx = nh_ecmp_idx;
   1508         }
   1509     }
   1510 
   1511     /* Mark entry as IPv6 */
   1512     lpm_cfg->defip_flags |= BCM_L3_IP6;
   1513 
   1514     /* Get entry priority. */
   1515     lpm_cfg->defip_prio = soc_mem_field32_get(unit, mem, hw_entry, PRIf);
   1516 
   1517     /* Get classification group id. */
   1518     lpm_cfg->defip_lookup_class =
   1519         soc_mem_field32_get(unit, mem, hw_entry, CLASS_IDf);
   1520     /* Get hit bit. */
   1521     if (!ALPM_CTRL(unit).hit_bits_skip &&
   1522         soc_mem_field32_get(unit, mem, hw_entry, HITf)) {
   1523         lpm_cfg->defip_flags |= BCM_L3_HIT;
   1524     }
   1525 
   1526     /* Get priority override bit. */
   1527     if (soc_mem_field32_get(unit, mem, hw_entry, RPEf)) {
   1528         lpm_cfg->defip_flags |= BCM_L3_RPE;
   1529     }
   1530 
   1531     /* Get destination discard field. */
   1532     if(soc_mem_field32_get(unit, mem, hw_entry, DST_DISCARDf)) {
   1533         lpm_cfg->defip_flags |= BCM_L3_DST_DISCARD;
   1534     }
   1535     return (BCM_E_NONE);
   1536 }
   1537 
   1538 /* As part of ALPM VRF WAR */
   1539 STATIC int
   1540 _bcm_th_alpm_warmboot_db_type_update(int unit)
   1541 {
   1542     int rv = BCM_E_NONE;
   1543 
   1544 #if 0
   1545     int i, defip_table_size = 0;
   1546     char *aux_tbl_ptr = NULL;
   1547     defip_aux_table_entry_t *aux_entry;
   1548     int is_urpf_entry, urpf = 0;
   1549     uint32 vrf, valid, db_type, ndb_type, nent_type;
   1550     soc_mem_t mem = L3_DEFIP_AUX_TABLEm;
   1551     int updated = 0;
   1552 
   1553     if (!SOC_IS_TOMAHAWKX(unit)) {
   1554         return rv;
   1555     }
   1556 #endif
   1557 
   1558     return rv;
   1559 #if 0
   1560     if (SOC_URPF_STATUS_GET(unit)) {
   1561         urpf = 1;
   1562     }
   1563 
   1564     rv = bcm_xgs3_l3_tbl_dma(unit, mem,
   1565                              sizeof(defip_aux_table_entry_t), "aux_tbl",
   1566                              &aux_tbl_ptr, &defip_table_size);
   1567     if (BCM_FAILURE(rv)) {
   1568         goto cleanup;
   1569     }
   1570 
   1571     for (i = 0; i < defip_table_size; i++) {
   1572         aux_entry = soc_mem_table_idx_to_pointer(unit, mem,
   1573                         defip_aux_table_entry_t *, aux_tbl_ptr, i);
   1574         if (urpf && i >= defip_table_size / 2) {
   1575             is_urpf_entry = 1;
   1576         } else {
   1577             is_urpf_entry = 0;
   1578         }
   1579 
   1580         /* Entry 0 */
   1581         valid = soc_mem_field32_get(unit, mem, aux_entry, VALID0f);
   1582         if (valid) {
   1583             vrf = soc_mem_field32_get(unit, mem, aux_entry, VRF0f);
   1584             db_type = soc_mem_field32_get(unit, mem, aux_entry, DB_TYPE0f);
   1585             if (db_type > 0) { /* > 0 means Private routes */
   1586                 soc_alpm_db_ent_type_encoding(unit, vrf, &ndb_type, &nent_type);
   1587                 if (is_urpf_entry) {
   1588                     ndb_type ++;
   1589                 }
   1590                 /* Old value is only 2(3), new value could be 4(5), 6(7) */
   1591                 if (db_type != ndb_type) {
   1592                     soc_mem_field32_set(unit, mem, aux_entry, DB_TYPE0f, ndb_type);
   1593                     soc_mem_field32_set(unit, mem, aux_entry, ENTRY_TYPE0_f(unit), nent_type);
   1594                     updated = 1;
   1595                 }
   1596             }
   1597         }
   1598 
   1599         /* Entry 1 */
   1600         valid = soc_mem_field32_get(unit, mem, aux_entry, VALID1f);
   1601         if (valid) {
   1602             vrf = soc_mem_field32_get(unit, mem, aux_entry, VRF1f);
   1603             db_type = soc_mem_field32_get(unit, mem, aux_entry, DB_TYPE1f);
   1604             if (db_type > 0) { /* > 0 means Private routes */
   1605                 soc_alpm_db_ent_type_encoding(unit, vrf, &ndb_type, &nent_type);
   1606                 if (is_urpf_entry) {
   1607                     ndb_type ++;
   1608                 }
   1609                 /* Old value is only 2(3), new value could be 4(5), 6(7) */
   1610                 if (db_type != ndb_type) {
   1611                     soc_mem_field32_set(unit, mem, aux_entry, DB_TYPE1f, ndb_type);
   1612                     soc_mem_field32_set(unit, mem, aux_entry, ENTRY_TYPE1_f(unit), nent_type);
   1613                     updated = 1;
   1614                 }
   1615             }
   1616         }
   1617     }
   1618 
   1619     if (updated) {
   1620         rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL,
   1621                 soc_mem_index_min(unit, mem),
   1622                 soc_mem_index_max(unit, mem), aux_tbl_ptr);
   1623     }
   1624 
   1625 cleanup:
   1626     if (aux_tbl_ptr) {
   1627         soc_cm_sfree(unit, aux_tbl_ptr);
   1628     }
   1629     return rv;
   1630 #endif
   1631 }
   1632 
   1633 /*
   1634  * Function:
   1635  *      _bcm_th_alpm_warmboot_walk
   1636  * Purpose:
   1637  *      Recover LPM and ALPM entries
   1638  * Parameters:
   1639  *      unit     - (IN)SOC unit number.
   1640  *      trv_data - (IN)pattern + compare,act,notify routines.
   1641  * Returns:
   1642  *      BCM_E_XXX
   1643  */
   1644 STATIC int
   1645 _bcm_th_alpm_warmboot_walk(int unit, _bcm_l3_trvrs_data_t *trv_data)
   1646 {
   1647     int ipv6;                   /* IPv6 flag.                   */
   1648     int idx;                    /* Iteration index.             */
   1649     int tmp_idx;                /* IPv4 entries iterator.       */
   1650     int vrf, vrf_id;            /*                              */
   1651     int idx_end;                /*                              */
   1652     int bkt_addr;               /*                              */
   1653     int bkt_count;              /*                              */
   1654     int bkti = 0;               /*                              */
   1655     int bkt_ptr2, bkt_ptr = 0;  /* Bucket pointer               */
   1656     int sub_bkt_idx = 0;        /* Sub bucket pointer           */
   1657     int bank_num = 0;           /* Number of active SRAM banks  */
   1658     int pivot_idx = 0;          /* Pivot Index                  */
   1659     int entry_num = 0;          /* ALPM entry number in bucket  */
   1660     int nh_ecmp_idx;            /* Next hop/Ecmp group index.   */
   1661     int entry_count;            /* ALPM entry count in bucket   */
   1662     int bank_count;             /* SRAM bank count              */
   1663     int step_count;             /*                              */
   1664     int cmp_result;             /* Test routine result.         */
   1665     int rv = BCM_E_FAIL;        /* Operation return status.     */
   1666     int defip_table_size = 0;   /* Defip table size.            */
   1667     char *lpm_tbl_ptr = NULL;   /* DMA table pointer.           */
   1668     void *alpm_entry = NULL;    /*                              */
   1669     soc_mem_t alpm_mem;         /*                              */
   1670     _bcm_defip_cfg_t lpm_cfg;   /* Buffer to fill route info.   */
   1671     defip_entry_t *lpm_entry;   /* Hw entry buffer.             */
   1672     int bank_bits;              /* 2 bank mode, or 4 bank mode  */
   1673     uint32 bank_disable;        /* Bank disable mask            */
   1674     int ipmc_route = 0;         /* Route is ip multicast type   */
   1675     int flex = 0;               /* Route can be with stat flex  */
   1676     int alpm_bkt_bits = ALPM_CTRL(unit).bkt_bits;
   1677 
   1678     defip_alpm_ipv4_1_entry_t    alpm_entry_v4;
   1679     defip_alpm_ipv6_64_1_entry_t alpm_entry_v6_64;
   1680     defip_entry_t                local_lpm_entry;
   1681     int bkt_ptr_tmp = 0;
   1682     uint8 bkt_occupied = 0;
   1683 
   1684     _bcm_th_alpm_warmboot_db_type_update(unit);
   1685 
   1686     /* DMA LPM table to software copy */
   1687     rv = bcm_xgs3_l3_tbl_dma(unit, BCM_XGS3_L3_MEM(unit, defip),
   1688                              BCM_XGS3_L3_ENT_SZ(unit, defip), "lpm_tbl",
   1689                              &lpm_tbl_ptr, &defip_table_size);
   1690     if (BCM_FAILURE(rv)) {
   1691         goto free_lpm_table;
   1692     }
   1693 
   1694     if (SOC_URPF_STATUS_GET(unit)) {
   1695         defip_table_size >>= 1;
   1696     }
   1697 
   1698     idx_end    = defip_table_size;
   1699     bank_count = ALPM_CTRL(unit).num_banks;
   1700     bank_bits  = ALPM_CTRL(unit).bank_bits;
   1701 
   1702     /* Walk all lpm entries */
   1703     for (idx = 0; idx < idx_end; idx++) {
   1704         /* Calculate entry ofset */
   1705         lpm_entry =
   1706             soc_mem_table_idx_to_pointer(unit, BCM_XGS3_L3_MEM(unit, defip),
   1707                                          defip_entry_t *, lpm_tbl_ptr, idx);
   1708 
   1709         /* Avoid to modify the Hw entry buffer*/
   1710         sal_memcpy(&local_lpm_entry, lpm_entry, sizeof(defip_entry_t));
   1711 
   1712         lpm_entry = &local_lpm_entry;
   1713 
   1714         ipv6 = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, MODE0_f(unit));
   1715 
   1716         /* Calculate LPM table traverse step count */
   1717         step_count = ipv6 ? 1 : 2;
   1718       
   1719         /* Insert LPM entry into HASH table and init LPM trackers */ 
   1720         if (soc_th_alpm_warmboot_lpm_reinit(unit, ipv6, idx, lpm_entry) < 0) {
   1721             goto free_lpm_table;
   1722         }
   1723 
   1724         bkt_occupied = 0;
   1725  
   1726         /*
   1727          * This loop is used for two purposes
   1728          *  1. IPv4, DEFIP entry has two IPv4 entries.
   1729          *  2. IPv6 double wide mode, walk next bucket.
   1730          */
   1731         for (tmp_idx = 0; tmp_idx < step_count; tmp_idx++) {
   1732             if (tmp_idx) {  /* If index == 1 */
   1733                 /* Copy upper half of lpm entry to lower half */
   1734                 soc_th_alpm_lpm_ip4entry1_to_0(unit, lpm_entry, lpm_entry, TRUE);
   1735                
   1736                 /* Invalidate upper half */
   1737                 soc_L3_DEFIPm_field32_set(unit, lpm_entry, VALID1f, 0);
   1738             }
   1739     
   1740             /* Make sure entry is valid. */
   1741             if (!soc_L3_DEFIPm_field32_get(unit, lpm_entry, VALID0f)) {
   1742                 continue;
   1743             }
   1744 
   1745             /* Extract bucket pointer from LPM entry */
   1746             bkt_ptr = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, 
   1747                                           ALG_BKT_PTR0f);
   1748             bkt_ptr_tmp = bkt_ptr;
   1749 
   1750             if (ALPM_CTRL(unit).bkt_sharing) {
   1751                 sub_bkt_idx = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry,
   1752                                                   ALG_SUB_BKT_PTR0f);
   1753             }
   1754 
   1755             if (soc_feature(unit, soc_feature_ipmc_defip)) {
   1756                 /* Skip reserved ipmc entry */
   1757                 int ipmc_index = 0;
   1758                 ipmc_route = 0;
   1759                 if (soc_mem_field_valid(unit, L3_DEFIPm, MULTICAST_ROUTE0f)) {
   1760                     ipmc_route = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, MULTICAST_ROUTE0f);
   1761                 } else if (soc_mem_field_valid(unit, L3_DEFIPm, DATA_TYPE0f)) {
   1762                     if (soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, DATA_TYPE0f) == 2) {
   1763                         ipmc_route = 1;
   1764                     } else {
   1765                         ipmc_route = 0;
   1766                     }
   1767                 }
   1768 
   1769                 if (soc_feature(unit, soc_feature_generic_dest)) {
   1770                     uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
   1771                     uint32 dest_value = 0;
   1772                     dest_value = soc_mem_field32_dest_get(unit,
   1773                             L3_DEFIPm, lpm_entry,
   1774                             DESTINATION0f, &dest_type);
   1775                     if (dest_type == SOC_MEM_FIF_DEST_IPMC) {
   1776                         ipmc_index = dest_value;
   1777                     } else {
   1778                         ipmc_index = 0;
   1779                     }
   1780                 } else {
   1781                     ipmc_index = soc_mem_field32_get(unit, L3_DEFIPm,
   1782                                     lpm_entry, L3MC_INDEX0f);
   1783                 }
   1784 
   1785                 if (ipmc_route && (ipmc_index == 0)) {
   1786                     continue;
   1787                 }
   1788             }
   1789 
   1790             /* Extract VRF from LPM entry*/
   1791             if (soc_th_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf) < 0) {
   1792                 goto free_lpm_table;
   1793             }
   1794             bank_disable =
   1795                 ALPM_CTRL(unit).bank_disable_bmp_8b[vrf != (SOC_VRF_MAX(unit) + 1)];
   1796 
   1797             /* VRF_OVERRIDE (Global High) entries, and IP multicast prefix
   1798              * resides in TCAM */
   1799             if (bkt_ptr == 0) {
   1800                 VRF_TRIE_ROUTES_INC(unit, vrf_id, vrf, ipv6);
   1801                 sal_memset(&lpm_cfg, 0, sizeof(_bcm_defip_cfg_t));
   1802                 _bcm_th_alpm_lpm_data_parse(unit, &lpm_cfg, &nh_ecmp_idx,
   1803                                             lpm_entry);
   1804                 _bcm_th_alpm_lpm_key_parse(unit, &lpm_cfg, lpm_entry);
   1805                 lpm_cfg.defip_index = idx;
   1806 
   1807                 if (!!ipv6 == !!(lpm_cfg.defip_flags & BCM_L3_IP6)) {
   1808                     if (trv_data->op_cb) {
   1809                         (void) (*trv_data->op_cb)(unit, (void *)trv_data,
   1810                                                   (void *)&lpm_cfg,
   1811                                                   (void *)&nh_ecmp_idx,
   1812                                                   &cmp_result);
   1813                     }
   1814                 }
   1815                 continue;
   1816             }
   1817 
   1818             pivot_idx = (idx << 1) + tmp_idx;
   1819 
   1820             /* TCAM pivot recovery */
   1821             if (soc_th_alpm_warmboot_pivot_add(unit, ipv6, lpm_entry, 
   1822                     pivot_idx, ALPM_LOG_BKT(bkt_ptr, sub_bkt_idx)) < 0) {
   1823                 goto free_lpm_table;
   1824             }
   1825 
   1826             /* Set bucket bitmap */ 
   1827             if (soc_th_alpm_warmboot_bucket_bitmap_set(unit, vrf, ipv6, bkt_ptr) < 0) {
   1828                 goto free_lpm_table;
   1829             }
   1830 
   1831             flex = _soc_th_alpm_lpm_flex_get(unit, ipv6,
   1832                         soc_mem_field32_get(unit, L3_DEFIPm,
   1833                         lpm_entry, ENTRY_VIEW0f));
   1834             if (ipv6) {
   1835                 if (flex) {
   1836                     alpm_mem = L3_DEFIP_ALPM_IPV6_64_1m;
   1837                     entry_count = 3;
   1838                     alpm_entry = &alpm_entry_v6_64;
   1839                 } else {
   1840                     alpm_mem = L3_DEFIP_ALPM_IPV6_64m;
   1841                     entry_count = 4;
   1842                     alpm_entry = &alpm_entry_v6_64;
   1843                 }
   1844 
   1845             } else {
   1846                 if (flex) {
   1847                     alpm_mem = L3_DEFIP_ALPM_IPV4_1m;
   1848                     entry_count = 4;
   1849                     alpm_entry = &alpm_entry_v4;
   1850                 } else {
   1851                     alpm_mem = L3_DEFIP_ALPM_IPV4m;
   1852                     entry_count = 6;
   1853                     alpm_entry = &alpm_entry_v4;
   1854                 }
   1855             }
   1856             bkt_count = _soc_th_alpm_bkt_entry_cnt(unit, alpm_mem);
   1857 
   1858             ALPM_FIRST_AVAIL_BANK(bank_num, bank_count, bank_disable);
   1859 
   1860             /* Get the bucket pointer from lpm entry */
   1861             bkt_ptr2 = bkt_ptr;
   1862             entry_num = 0;
   1863             for (bkti = 0; bkti < bkt_count; bkti++) {
   1864                 /* Calculate bucket memory address */
   1865                 /* Increment so next bucket address can be calculated */
   1866                 bkt_addr = (entry_num << (bank_bits + alpm_bkt_bits)) | 
   1867                            (bkt_ptr2 << bank_bits) | 
   1868                            (bank_num & ((1U << bank_bits) - 1));
   1869 
   1870                 entry_num++;
   1871                 if (entry_num == entry_count) {
   1872                     entry_num = 0;
   1873                     ALPM_NEXT_AVAIL_BANK(bank_num, bank_count, bank_disable);
   1874                     if (bank_num == bank_count) {
   1875                         ALPM_FIRST_AVAIL_BANK(bank_num, bank_count, bank_disable);
   1876                         bkt_ptr2 ++;
   1877                     }
   1878                 }
   1879 
   1880                 /* Read entry from bucket memory */
   1881                 if (soc_mem_read_no_cache(unit, 0, alpm_mem, 0, MEM_BLOCK_ANY,
   1882                                           bkt_addr, alpm_entry) < 0) {
   1883                     goto free_lpm_table;
   1884                 }
   1885 
   1886                 bkt_occupied = 1;
   1887 
   1888                 /* Check if ALPM entry is valid */
   1889                 if (!soc_mem_field32_get(unit, alpm_mem, alpm_entry, VALIDf)) {
   1890                     continue;
   1891                 }
   1892 
   1893                 if (ALPM_CTRL(unit).bkt_sharing && sub_bkt_idx !=
   1894                     soc_mem_field32_get(unit, alpm_mem, alpm_entry, SUB_BKT_PTRf)) {
   1895                     continue;
   1896                 }
   1897 
   1898                 /* Zero destination buffer first. */
   1899                 sal_memset(&lpm_cfg, 0, sizeof(_bcm_defip_cfg_t));
   1900 
   1901                 /* Parse the entry. */
   1902                 _bcm_th_alpm_ent_data_parse(unit, &lpm_cfg, &nh_ecmp_idx,
   1903                                             alpm_mem, alpm_entry);
   1904 
   1905                 /* Execute operation routine if any. */
   1906                 if (trv_data->op_cb) {
   1907                     rv = (*trv_data->op_cb) (unit, (void *)trv_data,
   1908                                             (void *)&lpm_cfg,
   1909                                             (void *)&nh_ecmp_idx, &cmp_result);
   1910 #ifdef BCM_CB_ABORT_ON_ERR
   1911                     if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   1912                         continue;
   1913                     }
   1914 #endif
   1915                 }
   1916 
   1917                 if (soc_th_alpm_warmboot_prefix_insert(unit, ipv6, flex, lpm_entry,
   1918                                                        alpm_entry, pivot_idx, 
   1919                                                        ALPM_LOG_BKT(bkt_ptr, sub_bkt_idx),
   1920                                                        bkt_addr) < 0) {
   1921                     continue;
   1922                 }
   1923 
   1924             } /* End of bucket walk loop*/
   1925             if (bkt_occupied) {
   1926                 /* If double wide,  two alpm bkt views should be set */
   1927                 if (SOC_TH_ALPM_SCALE_CHECK(unit, ipv6)) {
   1928                     soc_alpm_cmn_bkt_view_set(unit, bkt_ptr_tmp << 2, alpm_mem);
   1929                     soc_alpm_cmn_bkt_view_set(unit, (bkt_ptr_tmp + 1) << 2, alpm_mem);
   1930                 } else {
   1931                     soc_alpm_cmn_bkt_view_set(unit, bkt_ptr_tmp << 2, alpm_mem);
   1932                 }
   1933             }
   1934         } /* End of lpm entry upper/lower half traversal */
   1935     } /* End of lpm table traversal */
   1936 
   1937 
   1938     /* Update bpm_len of pivot after perfix trie is restored */
   1939     for (idx = 0; idx < idx_end; idx++) {
   1940         /* Calculate entry ofset */
   1941         lpm_entry =
   1942             soc_mem_table_idx_to_pointer(unit, BCM_XGS3_L3_MEM(unit, defip),
   1943                                          defip_entry_t *, lpm_tbl_ptr, idx);
   1944 
   1945         ipv6 = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, MODE0_f(unit));
   1946 
   1947         /* Calculate LPM table traverse step count */
   1948         step_count = ipv6 ? 1 : 2;
   1949 
   1950         for (tmp_idx = 0; tmp_idx < step_count; tmp_idx++) {
   1951             if (tmp_idx) {
   1952                 /* Copy upper half of lpm entry to lower half */
   1953                 (void) soc_th_alpm_lpm_ip4entry1_to_0(unit, lpm_entry,
   1954                                                       lpm_entry, TRUE);
   1955                 /* Invalidate upper half */
   1956                 soc_L3_DEFIPm_field32_set(unit, lpm_entry, VALID1f, 0);
   1957             }
   1958 
   1959             /* Make sure entry is valid. */
   1960             if (!soc_L3_DEFIPm_field32_get(unit, lpm_entry, VALID0f)) {
   1961                 continue;
   1962             }
   1963 
   1964             if (soc_feature(unit, soc_feature_ipmc_defip)) {
   1965                 /* Skip reserved ipmc entry */
   1966                 int ipmc_index = 0;
   1967                 ipmc_route = 0;
   1968                 if (soc_mem_field_valid(unit, L3_DEFIPm, MULTICAST_ROUTE0f)) {
   1969                     ipmc_route = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, MULTICAST_ROUTE0f);
   1970                 } else if (soc_mem_field_valid(unit, L3_DEFIPm, DATA_TYPE0f)) {
   1971                     if (soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, DATA_TYPE0f) == 2) {
   1972                         ipmc_route = 1;
   1973                     } else {
   1974                         ipmc_route = 0;
   1975                     }
   1976                 }
   1977 
   1978                 if (soc_feature(unit, soc_feature_generic_dest)) {
   1979                     uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
   1980                     uint32 dest_value = 0;
   1981                     dest_value = soc_mem_field32_dest_get(unit,
   1982                             L3_DEFIPm, lpm_entry,
   1983                             DESTINATION0f, &dest_type);
   1984                     if (dest_type == SOC_MEM_FIF_DEST_IPMC) {
   1985                         ipmc_index = dest_value;
   1986                     } else {
   1987                         ipmc_index = 0;
   1988                     }
   1989                 } else {
   1990                     ipmc_index = soc_mem_field32_get(unit, L3_DEFIPm,
   1991                                     lpm_entry, L3MC_INDEX0f);
   1992                 }
   1993 
   1994                 if (ipmc_route && (ipmc_index == 0)) {
   1995                     continue;
   1996                 }
   1997             }
   1998 
   1999             /* VRF_OVERRIDE (Global High) entries, and IP multicast prefix
   2000              * resides in TCAM */
   2001             if(soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry,
   2002                                    ALG_BKT_PTR0f) == 0) {
   2003                continue;
   2004             }
   2005 
   2006             pivot_idx = (idx << 1) + tmp_idx;
   2007 
   2008             /* TCAM pivot recovery */
   2009             if (soc_th_alpm_warmboot_pivot_bmp_len_update(
   2010                     unit, ipv6, lpm_entry, pivot_idx) < 0) {
   2011                 goto free_lpm_table;
   2012             }
   2013         }
   2014     }
   2015 
   2016     if (soc_th_alpm_warmboot_lpm_reinit_done(unit) < 0) {
   2017         goto free_lpm_table;
   2018     }
   2019 
   2020 #ifdef ALPM_WARM_BOOT_DEBUG
   2021     soc_alpm_lpm_sw_dump(unit);
   2022 #endif /* ALPM_WARM_BOOT_DEBUG  */
   2023 
   2024     rv = BCM_E_NONE;
   2025 
   2026 free_lpm_table:
   2027     if (lpm_tbl_ptr) {
   2028         soc_cm_sfree(unit, lpm_tbl_ptr);
   2029     }
   2030 
   2031     return (rv);
   2032 }
   2033 
   2034 /*
   2035  * Function:
   2036  *      _bcm_th_alpm_128_warmboot_walk
   2037  * Purpose:
   2038  *      Recover IPv6-128Bit LPM and ALPM entries
   2039  * Parameters:
   2040  *      unit     - (IN)SOC unit number.
   2041  *      trv_data - (IN)pattern + compare,act,notify routines.  
   2042  * Returns:
   2043  *      BCM_E_XXX
   2044  */
   2045 STATIC int
   2046 _bcm_th_alpm_128_warmboot_walk(int unit, _bcm_l3_trvrs_data_t *trv_data)
   2047 {
   2048     int ipv6 = 2;               /* IPv6 flag.                   */
   2049     int idx;                    /* Iteration index.             */
   2050     int tmp_idx;                /* IPv4 entries iterator.       */
   2051     int vrf, vrf_id;            /*                              */
   2052     int idx_end;                /*                              */
   2053     int bkt_addr;               /*                              */
   2054     int bkt_count;              /*                              */
   2055     int bkti = 0;               /*                              */
   2056     int bkt_ptr2, bkt_ptr = 0;  /* Bucket pointer               */
   2057     int sub_bkt_idx = 0;        /* Sub bucket pointer           */
   2058     int bank_num = 0;           /* Number of active SRAM banks  */
   2059     int entry_num = 0;          /* ALPM entry number in bucket  */
   2060     int nh_ecmp_idx;            /* Next hop/Ecmp group index.   */
   2061     int entry_count;            /* ALPM entry count in bucket   */
   2062     int bank_count;             /* SRAM bank count              */
   2063     int step_count = 1;         /*                              */
   2064     int cmp_result;             /* Test routine result.         */
   2065     int rv = BCM_E_FAIL;        /* Operation return status.     */
   2066     int defip_table_size = 0;   /* Defip table size.            */
   2067     char *lpm_tbl_ptr = NULL;   /* DMA table pointer.           */
   2068     void *alpm_entry = NULL;    /*                              */
   2069     uint32 rval;                /*                              */
   2070     soc_mem_t alpm_mem;         /*                              */
   2071     _bcm_defip_cfg_t lpm_cfg;   /* Buffer to fill route info.   */
   2072     int bank_bits;              /* 2 bank mode, or 4 bank mode  */
   2073     uint32 bank_disable;        /* Bank disable mask            */
   2074     int alpm_bkt_bits = ALPM_CTRL(unit).bkt_bits;
   2075 
   2076     defip_pair_128_entry_t *lpm_entry; /* Hw entry buffer.      */
   2077     defip_alpm_ipv6_128_entry_t alpm_entry_v6_128; /* ALPM 128  */
   2078     int ipmc_route = 0;         /* Route is ip multicast type   */
   2079     int bkt_ptr_tmp = 0;
   2080     uint8 bkt_occupied = 0;
   2081 
   2082     /* DMA LPM table to software copy */
   2083     rv = bcm_xgs3_l3_tbl_dma(unit, L3_DEFIP_PAIR_128m,
   2084                     WORDS2BYTES(soc_mem_entry_words(unit, L3_DEFIP_PAIR_128m)), 
   2085                     "lpm_128_warmboot_tbl",
   2086                     &lpm_tbl_ptr, &defip_table_size);
   2087     if (BCM_FAILURE(rv)) {
   2088         goto free_lpm_table;
   2089     }
   2090 
   2091     if(BCM_FAILURE(READ_L3_DEFIP_RPF_CONTROLr(unit, &rval))) {
   2092         goto free_lpm_table;
   2093     }
   2094 
   2095     if (SOC_URPF_STATUS_GET(unit)) {
   2096         defip_table_size >>= 1;
   2097     }
   2098 
   2099     idx_end     = defip_table_size;
   2100     alpm_mem    = L3_DEFIP_ALPM_IPV6_128m;
   2101     alpm_entry  = &alpm_entry_v6_128;
   2102     entry_count = 2;
   2103     bank_count  = ALPM_CTRL(unit).num_banks;
   2104     bank_bits   = ALPM_CTRL(unit).bank_bits;
   2105     bkt_count   = _soc_th_alpm_bkt_entry_cnt(unit, alpm_mem);
   2106     
   2107     /* Walk all lpm entries */
   2108     for (idx = 0; idx < idx_end; idx++) {
   2109         /* Calculate entry ofset */
   2110         lpm_entry =
   2111             soc_mem_table_idx_to_pointer(unit, L3_DEFIP_PAIR_128m,
   2112                                          defip_pair_128_entry_t *, lpm_tbl_ptr, idx);
   2113 
   2114         /* Verify if read LPM entry is IPv6-128 entry */
   2115         if (0x03 != soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry,
   2116                                         MODE1_UPR_f(unit))) {
   2117             continue;
   2118         };
   2119 
   2120         /* Verify if LPM entry is valid */
   2121         if (!soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry,
   2122                                     VALID1_LWRf) ||
   2123             !soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry,
   2124                                     VALID0_LWRf) ||
   2125             !soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   2126                                     VALID1_UPRf) || 
   2127             !soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry,
   2128                                     VALID0_UPRf)) {
   2129             continue;
   2130         };
   2131 
   2132         /* Insert LPM entry into HASH table and init LPM trackers */ 
   2133         if (soc_th_alpm_128_warmboot_lpm_reinit(unit, ipv6, idx, lpm_entry) < 0) {
   2134             goto free_lpm_table;
   2135         }
   2136 
   2137         bkt_occupied = 0;
   2138 
   2139         /*  If IPv6 double wide mode, walk next bucket.*/
   2140         for (tmp_idx = 0; tmp_idx < step_count; tmp_idx++) {
   2141             /* Extract bucket pointer from LPM entry */
   2142             bkt_ptr = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry,
   2143                                           ALG_BKT_PTRf);
   2144             bkt_ptr_tmp = bkt_ptr;
   2145             if (ALPM_CTRL(unit).bkt_sharing) {
   2146                 sub_bkt_idx = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   2147                                                   lpm_entry, ALG_SUB_BKT_PTRf);
   2148             } else {
   2149                 sub_bkt_idx = 0;
   2150             }
   2151 
   2152             if (soc_feature(unit, soc_feature_ipmc_defip)) {
   2153                 /* Skip reserved ipmc entry */
   2154                 int ipmc_index = 0;
   2155                 ipmc_route = 0;
   2156                 if (soc_mem_field_valid(unit, L3_DEFIP_PAIR_128m, MULTICAST_ROUTEf)) {
   2157                     ipmc_route = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   2158                                                   lpm_entry, MULTICAST_ROUTEf);
   2159                 } else if (soc_mem_field_valid(unit, L3_DEFIP_PAIR_128m, DATA_TYPEf)) {
   2160                     if (soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   2161                                             lpm_entry, DATA_TYPEf) == 2) {
   2162                         ipmc_route = 1;
   2163                     } else {
   2164                         ipmc_route = 0;
   2165                     }
   2166                 }
   2167 
   2168                 if (soc_feature(unit, soc_feature_generic_dest)) {
   2169                     uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
   2170                     uint32 dest_value = 0;
   2171                     dest_value = soc_mem_field32_dest_get(unit,
   2172                             L3_DEFIP_PAIR_128m, lpm_entry,
   2173                             DESTINATIONf, &dest_type);
   2174                     if (dest_type == SOC_MEM_FIF_DEST_IPMC) {
   2175                         ipmc_index = dest_value;
   2176                     } else {
   2177                         ipmc_index = 0;
   2178                     }
   2179                 } else {
   2180                     ipmc_index = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   2181                                     lpm_entry, L3MC_INDEXf);
   2182                 }
   2183 
   2184                 if (ipmc_route && ipmc_index == 0) {
   2185                     continue;
   2186                 }
   2187             }
   2188 
   2189             /* Extract VRF from LPM entry*/
   2190             if (soc_th_alpm_128_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf) < 0) {
   2191                 goto free_lpm_table;
   2192             }
   2193 
   2194             /* VRF_OVERRIDE (Global High) entries, and IP multicast prefix
   2195              * resides in TCAM */
   2196             if (bkt_ptr == 0) {
   2197                 VRF_TRIE_ROUTES_INC(unit, vrf_id, vrf, ipv6);
   2198 
   2199                 /* TCAM Routes Processing */
   2200                 sal_memset(&lpm_cfg, 0, sizeof(_bcm_defip_cfg_t));
   2201                 (void) _bcm_th_alpm_lpm128_key_parse(unit, (uint32 *)lpm_entry,
   2202                                                      &lpm_cfg);
   2203                 (void) soc_th_alpm_128_lpm_vrf_get(unit, lpm_entry,
   2204                                             &lpm_cfg.defip_vrf, &nh_ecmp_idx);
   2205                 _bcm_th_alpm_lpm128_data_parse(unit, &lpm_cfg, &nh_ecmp_idx,
   2206                                                lpm_entry);
   2207                 lpm_cfg.defip_index = idx;
   2208                 if (trv_data->op_cb) {
   2209                     (void) (*trv_data->op_cb)(unit, (void *)trv_data,
   2210                                               (void *)&lpm_cfg,
   2211                                               (void *)&nh_ecmp_idx, &cmp_result);
   2212                 }
   2213                 continue;
   2214             }
   2215 
   2216             bank_disable =
   2217                 ALPM_CTRL(unit).bank_disable_bmp_8b[vrf != (SOC_VRF_MAX(unit) + 1)];
   2218 
   2219             /* TCAM pivot recovery */
   2220             if (soc_th_alpm_128_warmboot_pivot_add(unit, ipv6, lpm_entry, 
   2221                     idx, ALPM_LOG_BKT(bkt_ptr, sub_bkt_idx)) < 0) {
   2222                 goto free_lpm_table;
   2223             }
   2224 
   2225             /* Set bucket bitmap */ 
   2226             if (soc_th_alpm_128_warmboot_bucket_bitmap_set(unit, vrf, ipv6, 
   2227                                                            bkt_ptr) < 0) {
   2228                 goto free_lpm_table;
   2229             }
   2230 
   2231 
   2232             ALPM_FIRST_AVAIL_BANK(bank_num, bank_count, bank_disable);
   2233 
   2234             entry_num = 0;
   2235             bkt_ptr2 = bkt_ptr;
   2236             /* Get the bucket pointer from lpm entry */
   2237             for (bkti = 0; bkti < bkt_count; bkti++) {
   2238                 /* calculate bucket memory address */
   2239                 /* also increment so next bucket address can be calculated */
   2240                 bkt_addr = (entry_num << (bank_bits + alpm_bkt_bits)) | 
   2241                            (bkt_ptr2 << bank_bits) | 
   2242                            (bank_num & ((1U << bank_bits) - 1));
   2243                 
   2244                 entry_num++; 
   2245                 if (entry_num == entry_count) {
   2246                     entry_num = 0;
   2247                     ALPM_NEXT_AVAIL_BANK(bank_num, bank_count, bank_disable);
   2248                     if (bank_num == bank_count) {
   2249                         ALPM_FIRST_AVAIL_BANK(bank_num, bank_count, bank_disable);
   2250                         bkt_ptr2 ++;
   2251                     }                    
   2252                 }
   2253 
   2254                 /* Read entry from bucket memory */
   2255                 if (soc_mem_read_no_cache(unit, 0, alpm_mem, 0, MEM_BLOCK_ANY,
   2256                                           bkt_addr, alpm_entry) < 0) {
   2257                     goto free_lpm_table;
   2258                 }
   2259 
   2260                 /*
   2261                  * In Tomahawk URPF mode, valid bits will make sure
   2262                  * SIP entries in buckets are included in this walk
   2263                  */
   2264 
   2265                 /* Check if ALPM entry is valid */
   2266                 if (!soc_mem_field32_get(unit, alpm_mem, alpm_entry, VALIDf)) {
   2267                     continue;
   2268                 }
   2269                 if (ALPM_CTRL(unit).bkt_sharing && sub_bkt_idx !=
   2270                     soc_mem_field32_get(unit, alpm_mem, alpm_entry, SUB_BKT_PTRf)) {
   2271                     continue;
   2272                 }
   2273 
   2274                 bkt_occupied = 1;
   2275 
   2276                 /* Zero destination buffer first. */
   2277                 sal_memset(&lpm_cfg, 0, sizeof(_bcm_defip_cfg_t));
   2278 
   2279 
   2280                 /* Fill entry IP address and subnet mask. */
   2281                 _bcm_th_alpm_ent128_key_parse(unit, alpm_mem, alpm_entry,
   2282                                               &lpm_cfg);
   2283 
   2284                 (void)soc_th_alpm_128_lpm_vrf_get(unit, lpm_entry, &lpm_cfg.defip_vrf, &vrf);
   2285                 /* get associated data */
   2286                 _bcm_th_alpm_ent128_data_parse(unit, alpm_mem, alpm_entry,
   2287                                                &lpm_cfg, &nh_ecmp_idx);
   2288 
   2289                 /* Execute operation routine if any. */
   2290                 if (trv_data->op_cb) {
   2291                     rv = (*trv_data->op_cb)(unit, (void *)trv_data,
   2292                                             (void *)&lpm_cfg,
   2293                                             (void *)&nh_ecmp_idx, &cmp_result);
   2294 #ifdef BCM_CB_ABORT_ON_ERR
   2295                     if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   2296                         continue;
   2297                     }
   2298 #endif
   2299                 }
   2300 
   2301                 if (soc_th_alpm_128_warmboot_prefix_insert(unit, ipv6, lpm_entry,
   2302                        alpm_entry, idx, ALPM_LOG_BKT(bkt_ptr, sub_bkt_idx),
   2303                        bkt_addr) < 0) {
   2304                     continue;
   2305                 }
   2306 
   2307             } /* End of bucket walk loop*/
   2308             if (bkt_occupied) {
   2309                 /* If double wide,  two alpm bkt views should be set */
   2310                 if (SOC_TH_ALPM_SCALE_CHECK(unit, ipv6)) {
   2311                     soc_alpm_cmn_bkt_view_set(unit, bkt_ptr_tmp << 2, alpm_mem);
   2312                     soc_alpm_cmn_bkt_view_set(unit, (bkt_ptr_tmp + 1) << 2, alpm_mem);
   2313                 } else {
   2314                     soc_alpm_cmn_bkt_view_set(unit, bkt_ptr_tmp << 2, alpm_mem);
   2315                 }
   2316             }
   2317         } /* End of lpm entry upper/lower half traversal */
   2318     } /* End of lpm table traversal */
   2319 
   2320     /* Update bpm_len of pivot after perfix trie is restored */
   2321     for (idx = 0; idx < idx_end; idx++) {
   2322         /* Calculate entry ofset */
   2323         lpm_entry = soc_mem_table_idx_to_pointer(unit, L3_DEFIP_PAIR_128m,
   2324                                                  defip_pair_128_entry_t *,
   2325                                                  lpm_tbl_ptr, idx);
   2326 
   2327         /* Verify if read LPM entry is IPv6-128 entry */
   2328         if (0x03 != soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   2329                                         lpm_entry, MODE1_UPR_f(unit))) {
   2330             continue;
   2331         }
   2332 
   2333         /* Verify if LPM entry is valid */
   2334         if (!soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   2335                                  lpm_entry, VALID1_LWRf) ||
   2336             !soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   2337                                  lpm_entry, VALID0_LWRf) ||
   2338             !soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   2339                                  lpm_entry, VALID1_UPRf) ||
   2340             !soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   2341                                  lpm_entry, VALID0_UPRf)) {
   2342             continue;
   2343         }
   2344 
   2345         for (tmp_idx = 0; tmp_idx < step_count; tmp_idx++) {
   2346             if (soc_feature(unit, soc_feature_ipmc_defip)) {
   2347                 /* Skip reserved ipmc entry */
   2348                 int ipmc_index = 0;
   2349                 ipmc_route = 0;
   2350                 if (soc_mem_field_valid(unit, L3_DEFIP_PAIR_128m, MULTICAST_ROUTEf)) {
   2351                     ipmc_route = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   2352                                                   lpm_entry, MULTICAST_ROUTEf);
   2353                 } else if (soc_mem_field_valid(unit, L3_DEFIP_PAIR_128m, DATA_TYPEf)) {
   2354                     if (soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   2355                                             lpm_entry, DATA_TYPEf) == 2) {
   2356                         ipmc_route = 1;
   2357                     } else {
   2358                         ipmc_route = 0;
   2359                     }
   2360                 }
   2361 
   2362                 if (soc_feature(unit, soc_feature_generic_dest)) {
   2363                     uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
   2364                     uint32 dest_value = 0;
   2365                     dest_value = soc_mem_field32_dest_get(unit,
   2366                             L3_DEFIP_PAIR_128m, lpm_entry,
   2367                             DESTINATIONf, &dest_type);
   2368                     if (dest_type == SOC_MEM_FIF_DEST_IPMC) {
   2369                         ipmc_index = dest_value;
   2370                     } else {
   2371                         ipmc_index = 0;
   2372                     }
   2373                 } else {
   2374                     ipmc_index = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   2375                                     lpm_entry, L3MC_INDEXf);
   2376                 }
   2377 
   2378                 if ((ipmc_route) && ipmc_index == 0) {
   2379                     continue;
   2380                 }
   2381             }
   2382 
   2383             /* VRF_OVERRIDE (Global High) entries, and IP multicast prefix
   2384              * resides in TCAM */
   2385             if (soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry,
   2386                                     ALG_BKT_PTRf) == 0) {
   2387                 continue;
   2388             }
   2389 
   2390             /* TCAM pivot recovery */
   2391             if (soc_th_alpm_128_warmboot_pivot_bmp_len_update(
   2392                     unit, ipv6, lpm_entry, idx) < 0) {
   2393                 goto free_lpm_table;
   2394             }
   2395         }
   2396     }
   2397 
   2398     if (soc_th_alpm_128_warmboot_lpm_reinit_done(unit) < 0) {
   2399         goto free_lpm_table;
   2400     }
   2401 
   2402 #ifdef ALPM_WARM_BOOT_DEBUG
   2403     soc_alpm_lpm_sw_dump(unit);
   2404 #endif /* ALPM_WARM_BOOT_DEBUG  */
   2405 
   2406     rv = BCM_E_NONE;
   2407 free_lpm_table:
   2408     if (lpm_tbl_ptr) {
   2409         soc_cm_sfree(unit, lpm_tbl_ptr);
   2410     }
   2411 
   2412     return (rv);
   2413 }
   2414 
   2415 STATIC int
   2416 _bcm_th_alpm_128_update_match(int unit, _bcm_l3_trvrs_data_t *trv_data)
   2417 {
   2418     uint32 ipv6;                /* Iterate over ipv6 only flag. */
   2419     int idx;                    /* Iteration index.             */
   2420     int tmp_idx;                /* ipv4 entries iterator.       */
   2421     char *lpm_tbl_ptr;          /* Dma table pointer.           */
   2422     int nh_ecmp_idx;            /* Next hop/Ecmp group index.   */
   2423     int cmp_result;             /* Test routine result.         */
   2424     defip_pair_128_entry_t *lpm_entry = NULL;   /* Hw entry buffer.    */
   2425     _bcm_defip_cfg_t lpm_cfg;   /* Buffer to fill route info.   */
   2426     int defip_table_size;       /* Defip table size.            */
   2427     int rv = BCM_E_NONE;        /* Operation return status.     */
   2428     int idx_start = 0;
   2429     int idx_end = 0, bkt_idx, bkt_count, bkt_ptr = 0, bkt_addr;
   2430     int entry_num, bank_num, entry_count, bank_count, bank_bits;
   2431     defip_alpm_ipv6_128_entry_t alpm_entry_v6_128;
   2432     void *alpm_entry;
   2433     soc_mem_t alpm_mem, pivot_mem = L3_DEFIP_PAIR_128m;
   2434     int step_count = 1;
   2435     int def_arr_idx = 0;
   2436     int def_rte_arr_sz;
   2437     typedef struct _alpm_def_route_info_s {
   2438         int idx;
   2439         int bkt_addr;
   2440     } _alpm_def_route_info_t;
   2441     _alpm_def_route_info_t *def_rte_arr = NULL;
   2442     int sub_bkt = 0;
   2443     uint32 bank_disable;
   2444     int alpm_bkt_bits = ALPM_CTRL(unit).bkt_bits;
   2445 
   2446     ipv6 = (trv_data->flags & BCM_L3_IP6);
   2447     if (!ipv6) {
   2448         return SOC_E_NONE;
   2449     }
   2450 
   2451     /* LPM table DMA to software copy if callback is not for 'delete all' */
   2452     rv = bcm_xgs3_l3_tbl_dma(unit, L3_DEFIP_PAIR_128m,
   2453                     WORDS2BYTES(soc_mem_entry_words(unit, L3_DEFIP_PAIR_128m)), 
   2454                              "lpm_128_tbl", &lpm_tbl_ptr, &defip_table_size);
   2455     if (BCM_FAILURE(rv)) {
   2456         goto cleanup;
   2457     }
   2458 
   2459     /* Allocate memory to store default route meta data*/
   2460     def_rte_arr_sz = SOC_VRF_MAX(unit) * sizeof(_alpm_def_route_info_t);
   2461     def_rte_arr = sal_alloc(def_rte_arr_sz, "alpm_def_rte_arry"); 
   2462     if (NULL == def_rte_arr) {
   2463         rv = BCM_E_MEMORY;
   2464         goto cleanup;
   2465     }
   2466     sal_memset(def_rte_arr, 0, def_rte_arr_sz);
   2467 
   2468     if (SOC_URPF_STATUS_GET(unit)) {
   2469         defip_table_size >>= 1;
   2470     }
   2471 
   2472     idx_end     = defip_table_size;
   2473     alpm_mem    = L3_DEFIP_ALPM_IPV6_128m;
   2474     idx_start   = 0;
   2475     bank_num    = 0;
   2476     entry_num   = 0;
   2477     bank_count  = ALPM_CTRL(unit).num_banks;
   2478     entry_count = 2;
   2479     alpm_entry  = &alpm_entry_v6_128;
   2480     bank_bits   = ALPM_CTRL(unit).bank_bits;
   2481     bkt_count   = _soc_th_alpm_bkt_entry_cnt(unit, alpm_mem);
   2482 
   2483     /* if v6 loop twice once with with defip and once with defip_pair */
   2484     for (idx = (idx_end - 1); idx >= idx_start; idx--) {    
   2485 
   2486         /* Calculate entry ofset. */
   2487         lpm_entry =
   2488             soc_mem_table_idx_to_pointer(unit, L3_DEFIP_PAIR_128m,
   2489                                     defip_pair_128_entry_t *, lpm_tbl_ptr, idx);
   2490 
   2491         /* Make sure entry is valid. */
   2492         if (!soc_mem_field32_get(unit, pivot_mem, lpm_entry, VALID0_LWRf)) {
   2493             continue;
   2494         }
   2495 
   2496         /* Skip reserved ipmc entry */
   2497         if (soc_feature(unit, soc_feature_ipmc_defip)) {
   2498             /* Skip reserved ipmc entry */
   2499             int ipmc_route = 0;
   2500             int ipmc_index = 0;
   2501             if (soc_mem_field_valid(unit, L3_DEFIP_PAIR_128m, MULTICAST_ROUTEf)) {
   2502                 ipmc_route = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   2503                                                  lpm_entry, MULTICAST_ROUTEf);
   2504             } else if (soc_mem_field_valid(unit, L3_DEFIP_PAIR_128m, DATA_TYPEf)) {
   2505                 if (soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   2506                                         lpm_entry, DATA_TYPEf) == 2) {
   2507                     ipmc_route = 1;
   2508                 } else {
   2509                     ipmc_route = 0;
   2510                 }
   2511             }
   2512 
   2513             if (soc_feature(unit, soc_feature_generic_dest)) {
   2514                 uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
   2515                 uint32 dest_value = 0;
   2516                 dest_value = soc_mem_field32_dest_get(unit,
   2517                         L3_DEFIP_PAIR_128m, lpm_entry,
   2518                         DESTINATIONf, &dest_type);
   2519                 if (dest_type == SOC_MEM_FIF_DEST_IPMC) {
   2520                     ipmc_index = dest_value;
   2521                 } else {
   2522                     ipmc_index = 0;
   2523                 }
   2524             } else {
   2525                 ipmc_index = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m,
   2526                                 lpm_entry, L3MC_INDEXf);
   2527             }
   2528 
   2529             if (ipmc_route && ipmc_index == 0) {
   2530                 continue;
   2531             }
   2532         }
   2533         for (tmp_idx = 0; tmp_idx < step_count; tmp_idx++) {
   2534             bkt_ptr = soc_mem_field32_get(unit, pivot_mem, lpm_entry, ALG_BKT_PTRf);
   2535             if (ALPM_CTRL(unit).bkt_sharing) {
   2536                 sub_bkt = soc_mem_field32_get(unit, pivot_mem, lpm_entry, ALG_SUB_BKT_PTRf);
   2537             }
   2538             (void)soc_th_alpm_128_lpm_vrf_get(unit, lpm_entry, &lpm_cfg.defip_vrf,
   2539                                               &cmp_result);
   2540             bank_disable =
   2541                 ALPM_CTRL(unit).bank_disable_bmp_8b[cmp_result != (SOC_VRF_MAX(unit) + 1)];
   2542 
   2543             if (bkt_ptr == 0) {
   2544 
   2545                 /* OVERRIDE VRF Processing */ 
   2546 
   2547                 (void) _bcm_th_alpm_lpm128_key_parse(unit, (uint32 *) lpm_entry,
   2548                                                      &lpm_cfg);
   2549                 /* defip_vrf adjust */
   2550                 (void) soc_th_alpm_128_lpm_vrf_get(unit, lpm_entry,
   2551                                           &lpm_cfg.defip_vrf, &nh_ecmp_idx);
   2552                 _bcm_th_alpm_lpm128_data_parse(unit, &lpm_cfg, &nh_ecmp_idx,
   2553                                                lpm_entry);
   2554 
   2555                 lpm_cfg.defip_index = idx;
   2556                 
   2557                 if (trv_data->op_cb) {
   2558                     rv = (*trv_data->op_cb) (unit, (void *)trv_data,
   2559                                                (void *)&lpm_cfg,
   2560                                                (void *)&nh_ecmp_idx, &cmp_result);
   2561 #ifdef BCM_CB_ABORT_ON_ERR
   2562                     if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   2563                         break;
   2564                     }
   2565 #endif
   2566                 }
   2567 
   2568                 continue;
   2569             }
   2570 
   2571             entry_num = 0;
   2572             ALPM_FIRST_AVAIL_BANK(bank_num, bank_count, bank_disable);
   2573 
   2574             /* get the bucket pointer from lpm mem  entry */
   2575             for (bkt_idx = 0; bkt_idx < bkt_count; bkt_idx++) {
   2576                 /* calculate bucket memory address */
   2577                 /* also increment so next bucket address can be calculated */
   2578                 bkt_addr = (entry_num << (bank_bits + alpm_bkt_bits)) | 
   2579                            (bkt_ptr << bank_bits) | 
   2580                            (bank_num & ((1U << bank_bits) - 1));
   2581                 
   2582                 entry_num++; 
   2583                 if (entry_num == entry_count) {
   2584                     entry_num = 0;
   2585                     ALPM_NEXT_AVAIL_BANK(bank_num, bank_count, bank_disable);
   2586                     if (bank_num == bank_count) {
   2587                         ALPM_FIRST_AVAIL_BANK(bank_num, bank_count, bank_disable);
   2588                         bkt_ptr ++;
   2589                     }                    
   2590                 }
   2591 
   2592                 /* read entry from bucket memory */
   2593                 rv = soc_mem_read_no_cache(unit, 0, alpm_mem, 0, MEM_BLOCK_ANY,
   2594                                            bkt_addr, alpm_entry);
   2595                 if (SOC_FAILURE(rv)) {
   2596                     break;
   2597                 }
   2598 
   2599                 if (!soc_mem_field32_get(unit, alpm_mem, alpm_entry, VALIDf)) {
   2600                     continue;
   2601                 }
   2602 
   2603                 if (ALPM_CTRL(unit).bkt_sharing && sub_bkt !=
   2604                     soc_mem_field32_get(unit, alpm_mem, alpm_entry, SUB_BKT_PTRf)) {
   2605                     continue;
   2606                 }
   2607 
   2608                 /* Zero destination buffer first. */
   2609                 sal_memset(&lpm_cfg, 0, sizeof(_bcm_defip_cfg_t));
   2610 
   2611                 /* Parse  the entry. */
   2612                 /* Fill entry ip address &  subnet mask. */
   2613                 _bcm_th_alpm_ent128_key_parse(unit, alpm_mem, alpm_entry,
   2614                                               &lpm_cfg);
   2615 
   2616                 (void)soc_th_alpm_128_lpm_vrf_get(unit, lpm_entry, &lpm_cfg.defip_vrf,
   2617                                                   &cmp_result);
   2618                 
   2619                 /* get associated data */
   2620                 _bcm_th_alpm_ent128_data_parse(unit, alpm_mem, alpm_entry,
   2621                                                &lpm_cfg, &nh_ecmp_idx);
   2622                 /* If protocol doesn't match skip the entry. */
   2623                 if ((lpm_cfg.defip_flags & BCM_L3_IP6) != ipv6) {
   2624                     continue;
   2625                 }
   2626 
   2627                 lpm_cfg.defip_index = bkt_addr;
   2628 
   2629                 /* Check if this is default route */
   2630                 /* Subnet length zero will indicate default route */
   2631                 if (0 == lpm_cfg.defip_sub_len) {
   2632                     if (def_arr_idx < SOC_VRF_MAX(unit)) {
   2633                         def_rte_arr[def_arr_idx].bkt_addr = bkt_addr;
   2634                         def_rte_arr[def_arr_idx].idx = idx;
   2635                         def_arr_idx ++;
   2636                     }
   2637                 } else {
   2638                     /* Execute operation routine if any. */
   2639                     if (trv_data->op_cb) {
   2640                         rv = (*trv_data->op_cb) (unit, (void *)trv_data,
   2641                                                 (void *)&lpm_cfg,
   2642                                                 (void *)&nh_ecmp_idx, &cmp_result);
   2643 #ifdef BCM_CB_ABORT_ON_ERR
   2644                         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   2645                             break;
   2646                         }
   2647 #endif
   2648                     }
   2649                 }
   2650             }
   2651         }
   2652     }
   2653    
   2654     /* Process Default routes */
   2655     for (idx = 0; idx < def_arr_idx; idx++) {
   2656 
   2657         /* Calculate entry offset. */
   2658         lpm_entry = soc_mem_table_idx_to_pointer(unit, L3_DEFIP_PAIR_128m,
   2659                                     defip_pair_128_entry_t *, lpm_tbl_ptr,
   2660                                     def_rte_arr[idx].idx);
   2661 
   2662         /* Make sure entry is valid. */
   2663         if (!soc_mem_field32_get(unit, pivot_mem, lpm_entry, VALID0_LWRf)) {
   2664             continue;
   2665         }
   2666 
   2667         bkt_addr = def_rte_arr[idx].bkt_addr;
   2668         
   2669         /* read entry from bucket memory */
   2670         rv = soc_mem_read_no_cache(unit, 0, alpm_mem, 0, MEM_BLOCK_ANY,
   2671                                    bkt_addr, alpm_entry);
   2672         if (SOC_FAILURE(rv)) {
   2673             break;
   2674         }
   2675 
   2676         if (!soc_mem_field32_get(unit, alpm_mem, alpm_entry, VALIDf)) {
   2677             continue;
   2678         }
   2679 
   2680         /* Zero destination buffer first. */
   2681         sal_memset(&lpm_cfg, 0, sizeof(_bcm_defip_cfg_t));
   2682 
   2683         /* Fill entry ip address & subnet mask. */
   2684         _bcm_th_alpm_ent128_key_parse(unit, alpm_mem, alpm_entry, &lpm_cfg);
   2685         /* Parse  the entry. */
   2686         (void)soc_th_alpm_128_lpm_vrf_get(unit, lpm_entry, &lpm_cfg.defip_vrf,
   2687                                           &cmp_result);
   2688         _bcm_th_alpm_ent128_data_parse(unit, alpm_mem, alpm_entry, &lpm_cfg,
   2689                                        &nh_ecmp_idx);
   2690 
   2691         /* If protocol doesn't match skip the entry. */
   2692         if ((lpm_cfg.defip_flags & BCM_L3_IP6) != ipv6) {
   2693             continue;
   2694         }
   2695 
   2696         /* Execute operation routine if any. */
   2697         if (trv_data->op_cb) {
   2698             rv = (*trv_data->op_cb) (unit, (void *)trv_data,
   2699                                     (void *)&lpm_cfg,
   2700                                     (void *)&nh_ecmp_idx, &cmp_result);
   2701 #ifdef BCM_CB_ABORT_ON_ERR
   2702             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   2703                 break;
   2704             }
   2705 #endif
   2706         }
   2707     }
   2708 
   2709 cleanup:
   2710     if (def_rte_arr) {
   2711         sal_free(def_rte_arr);
   2712     }
   2713     if (lpm_tbl_ptr) {
   2714         soc_cm_sfree(unit, lpm_tbl_ptr);
   2715     }
   2716     
   2717     return (rv);
   2718 }
   2719 
   2720 /*
   2721  * Function:
   2722  *      _bcm_th_alpm_update_match
   2723  * Purpose:
   2724  *      Update/Delete all entries in defip table matching a certain rule.
   2725  * Parameters:
   2726  *      unit     - (IN)SOC unit number.
   2727  *      trv_data - (IN)Delete pattern + compare,act,notify routines.  
   2728  * Returns:
   2729  *      BCM_E_XXX
   2730  */
   2731 int
   2732 _bcm_th_alpm_update_match(int unit, _bcm_l3_trvrs_data_t *trv_data)
   2733 {
   2734     uint32 ipv6 = 0;            /* Iterate over ipv6 only flag. */
   2735     int idx;                    /* Iteration index.             */
   2736     int tmp_idx;                /* ipv4 entries iterator.       */
   2737     int tmp_start;              /* Iteration start.             */
   2738     int tmp_end;                /* Iteration end.               */
   2739     int tmp_delta;              /* Iteration delta.             */
   2740     char *lpm_tbl_ptr;          /* Dma table pointer.           */
   2741     int nh_ecmp_idx;            /* Next hop/Ecmp group index.   */
   2742     int cmp_result;             /* Test routine result.         */
   2743     defip_entry_t *lpm_entry;   /* Hw entry buffer.             */
   2744     defip_entry_t lpm_entry_data; /* Hw entry buffer.           */
   2745     _bcm_defip_cfg_t lpm_cfg;   /* Buffer to fill route info.   */
   2746     int defip_table_size;       /* Defip table size.            */
   2747     int rv = BCM_E_NONE;        /* Operation return status.     */
   2748     int idx_start = 0;
   2749     int idx_end = 0, bkt_idx, bkt_count, bkt_ptr = 0, bkt_addr;
   2750     int entry_num, bank_num, entry_count, bank_count;
   2751     defip_alpm_ipv4_1_entry_t alpm_entry_v4;
   2752     defip_alpm_ipv6_64_1_entry_t alpm_entry_v6_64;
   2753     void *alpm_entry;
   2754     soc_mem_t alpm_mem;
   2755     int step_count;
   2756     int def_arr_idx = 0;
   2757     int def_rte_arr_sz;
   2758     int bank_bits;
   2759     int sub_bkt = 0;
   2760     uint32 bank_disable;
   2761     int alpm_bkt_bits = ALPM_CTRL(unit).bkt_bits;
   2762     typedef struct _alpm_def_route_info_s {
   2763         int idx;
   2764         int bkt_addr;
   2765         defip_entry_t lpm_entry;
   2766     } _alpm_def_route_info_t;
   2767 
   2768     _alpm_def_route_info_t *def_rte_arr = NULL;
   2769     int flex;
   2770     int size = 0;
   2771 
   2772 
   2773 #ifdef BCM_WARM_BOOT_SUPPORT
   2774     if (SOC_WARM_BOOT(unit)) {
   2775         if (soc_mem_index_count(unit, BCM_XGS3_L3_MEM(unit, defip)) != 0) {
   2776             rv = _bcm_th_alpm_warmboot_walk(unit, trv_data);
   2777             if (rv < 0) {
   2778                 LOG_ERROR(BSL_LS_SOC_ALPM,
   2779                           (BSL_META_U(unit,
   2780                           "ERROR!  ALPM Warmboot recovery failed")));
   2781                 return (rv);
   2782             }
   2783         }
   2784 
   2785         if (soc_mem_index_count(unit, L3_DEFIP_PAIR_128m) != 0) {
   2786             /* v6-128 entries */
   2787             rv = _bcm_th_alpm_128_warmboot_walk(unit, trv_data);
   2788             if (rv < 0) {
   2789                 LOG_ERROR(BSL_LS_SOC_ALPM,
   2790                          (BSL_META_U(unit,
   2791                          "ERROR!  ALPM Warmboot V6-128 recovery failed")));
   2792             }
   2793         }
   2794         return (rv);
   2795     }
   2796 #endif
   2797 
   2798     ipv6 = trv_data->flags & BCM_L3_IP6;
   2799 
   2800     if (ipv6 && soc_mem_index_count(unit, L3_DEFIP_PAIR_128m) != 0) {
   2801         /* first get v6-128 entries */
   2802         rv = _bcm_th_alpm_128_update_match(unit, trv_data);
   2803 #ifdef BCM_CB_ABORT_ON_ERR
   2804         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   2805             return rv;
   2806         }
   2807 #endif
   2808     }
   2809 
   2810     if (soc_mem_index_count(unit, BCM_XGS3_L3_MEM(unit, defip)) == 0) {
   2811         return BCM_E_NONE;
   2812     }
   2813 
   2814     /* Table DMA the LPM table to software copy */
   2815     rv = bcm_xgs3_l3_tbl_dma(unit, BCM_XGS3_L3_MEM(unit, defip),
   2816                              BCM_XGS3_L3_ENT_SZ(unit, defip), "lpm_tbl",
   2817                              &lpm_tbl_ptr, &defip_table_size);
   2818     if (BCM_FAILURE(rv)) {
   2819         goto cleanup;
   2820     }
   2821 
   2822     /* Allocate memory to store default route meta data*/
   2823     def_rte_arr_sz = SOC_VRF_MAX(unit) * sizeof(_alpm_def_route_info_t);
   2824     def_rte_arr = sal_alloc(def_rte_arr_sz, "alpm_def_rte_arry"); 
   2825     if (NULL == def_rte_arr) {
   2826         rv = BCM_E_MEMORY;
   2827         goto cleanup;
   2828     }
   2829     sal_memset(def_rte_arr, 0, def_rte_arr_sz);
   2830 
   2831     if (SOC_URPF_STATUS_GET(unit)) {
   2832         defip_table_size >>= 1;
   2833     }
   2834 
   2835     idx_end     = defip_table_size;
   2836     bank_num    = 0;
   2837     entry_num   = 0;
   2838     bank_count  = ALPM_CTRL(unit).num_banks;
   2839     bank_bits   = ALPM_CTRL(unit).bank_bits;
   2840 
   2841     step_count = ipv6 ? 1 : 2;
   2842 
   2843     /* Walk all lpm entries */
   2844     for (idx = (idx_end - 1); idx >= idx_start; idx--) {
   2845             /* Calculate entry ofset. */
   2846         lpm_entry =
   2847                 soc_mem_table_idx_to_pointer(unit, BCM_XGS3_L3_MEM(unit, defip),
   2848                                              defip_entry_t *, lpm_tbl_ptr, idx);
   2849         sal_memcpy (&lpm_entry_data, lpm_entry, sizeof (lpm_entry_data));
   2850 
   2851         if (ipv6 && (soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, MODE0_f(unit)) == 0)) {
   2852            /*
   2853             * Function called for IPv6 LPM/ALPM walk and LPM entry is IPv4; Continue;
   2854             */
   2855            continue;
   2856         }
   2857         
   2858         /* Each LPM index has two IPv4 entries*/
   2859         if (ipv6) {
   2860            tmp_start = 0;
   2861            tmp_end   = step_count;
   2862            tmp_delta = 1;
   2863         } else {
   2864            tmp_start = step_count - 1;
   2865            tmp_end   = -1;
   2866            tmp_delta = -1;
   2867         }
   2868 
   2869         for (tmp_idx = tmp_start; tmp_idx != tmp_end; tmp_idx += tmp_delta) {
   2870             if (!ipv6) {
   2871                 if (tmp_idx) {
   2872                     /* Check second part of the entry. */
   2873                     soc_th_alpm_lpm_ip4entry1_to_0(unit, &lpm_entry_data, lpm_entry, TRUE);
   2874                 } else {
   2875                     soc_th_alpm_lpm_ip4entry0_to_0(unit, &lpm_entry_data, lpm_entry, TRUE);            
   2876                 }
   2877             }
   2878 
   2879             /* Make sure entry is valid. */
   2880             if (!soc_L3_DEFIPm_field32_get(unit, lpm_entry, VALID0f)) {
   2881                 continue;
   2882             }
   2883 
   2884             if (soc_feature(unit, soc_feature_ipmc_defip)) {
   2885                 /* Skip reserved ipmc entry */
   2886                 int ipmc_index = 0;
   2887                 int ipmc_route = 0;
   2888                 if (soc_mem_field_valid(unit, L3_DEFIPm, MULTICAST_ROUTE0f)) {
   2889                     ipmc_route = soc_mem_field32_get(unit, L3_DEFIPm,
   2890                                                      lpm_entry, MULTICAST_ROUTE0f);
   2891                 } else if (soc_mem_field_valid(unit, L3_DEFIPm, DATA_TYPE0f)) {
   2892                     if (soc_mem_field32_get(unit, L3_DEFIPm,
   2893                                             lpm_entry, DATA_TYPE0f) == 2) {
   2894                         ipmc_route = 1;
   2895                     } else {
   2896                         ipmc_route = 0;
   2897                     }
   2898                 }
   2899 
   2900                 if (soc_feature(unit, soc_feature_generic_dest)) {
   2901                     uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
   2902                     uint32 dest_value = 0;
   2903                     dest_value = soc_mem_field32_dest_get(unit,
   2904                             L3_DEFIPm, lpm_entry,
   2905                             DESTINATION0f, &dest_type);
   2906                     if (dest_type == SOC_MEM_FIF_DEST_IPMC) {
   2907                         ipmc_index = dest_value;
   2908                     } else {
   2909                         ipmc_index = 0;
   2910                     }
   2911                 } else {
   2912                     ipmc_index = soc_mem_field32_get(unit, L3_DEFIPm,
   2913                                     lpm_entry, L3MC_INDEX0f);
   2914                 }
   2915 
   2916                 if (ipmc_route && (ipmc_index == 0)) {
   2917                     continue;
   2918                 }
   2919             }
   2920 
   2921             cmp_result = ipv6 ? 1 : 0;
   2922             if (cmp_result != (soc_mem_field32_get(unit, L3_DEFIPm,
   2923                                                 lpm_entry, MODE0_f(unit)))) {
   2924                 continue;
   2925             }
   2926 
   2927             (void)soc_th_alpm_lpm_vrf_get(unit, lpm_entry, &lpm_cfg.defip_vrf,
   2928                                           &cmp_result);
   2929             bank_disable =
   2930                 ALPM_CTRL(unit).bank_disable_bmp_8b[cmp_result != (SOC_VRF_MAX(unit) + 1)];
   2931 
   2932             bkt_ptr = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry,
   2933                                       ALG_BKT_PTR0f);
   2934             if (ALPM_CTRL(unit).bkt_sharing) {
   2935                 sub_bkt = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry,
   2936                                               ALG_SUB_BKT_PTR0f);
   2937             }
   2938 
   2939             if (bkt_ptr == 0) {
   2940                 sal_memset(&lpm_cfg, 0, sizeof(_bcm_defip_cfg_t));
   2941                 _bcm_th_alpm_lpm_data_parse(unit, &lpm_cfg, &nh_ecmp_idx,
   2942                                             lpm_entry);
   2943                 _bcm_th_alpm_lpm_key_parse(unit, &lpm_cfg, lpm_entry);
   2944 
   2945                 lpm_cfg.defip_index = idx;
   2946 
   2947                 if (ipv6 == (lpm_cfg.defip_flags & BCM_L3_IP6)) {
   2948                     if (trv_data->op_cb) {
   2949                         rv = (*trv_data->op_cb)(unit, (void *)trv_data,
   2950                                             (void *)&lpm_cfg,
   2951                                             (void *)&nh_ecmp_idx, &cmp_result);
   2952 #ifdef BCM_CB_ABORT_ON_ERR
   2953                         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   2954                             break;
   2955                         }
   2956 #endif
   2957                     }
   2958                 }
   2959                 continue;
   2960             }
   2961 
   2962             flex = _soc_th_alpm_lpm_flex_get(unit, ipv6 ? L3_DEFIP_MODE_64 : 0,
   2963                         soc_mem_field32_get(unit, L3_DEFIPm,
   2964                         lpm_entry, ENTRY_VIEW0f));
   2965             if (ipv6) {
   2966                 if (flex) {
   2967                     alpm_mem = L3_DEFIP_ALPM_IPV6_64_1m;
   2968                     entry_count = 3;
   2969                     alpm_entry = &alpm_entry_v6_64;
   2970                     size = sizeof(alpm_entry_v6_64);
   2971                 } else {
   2972                     alpm_mem = L3_DEFIP_ALPM_IPV6_64m;
   2973                     entry_count = 4;
   2974                     alpm_entry = &alpm_entry_v6_64;
   2975                     size = sizeof(alpm_entry_v6_64);
   2976                 }
   2977 
   2978             } else {
   2979                 if (flex) {
   2980                     alpm_mem = L3_DEFIP_ALPM_IPV4_1m;
   2981                     entry_count = 4;
   2982                     alpm_entry = &alpm_entry_v4;
   2983                     size = sizeof(alpm_entry_v4);
   2984                 } else {
   2985                     alpm_mem = L3_DEFIP_ALPM_IPV4m;
   2986                     entry_count = 6;
   2987                     alpm_entry = &alpm_entry_v4;
   2988                     size = sizeof(alpm_entry_v4);
   2989                 }
   2990             }
   2991 
   2992             entry_num = 0;
   2993             bkt_count   = _soc_th_alpm_bkt_entry_cnt(unit, alpm_mem);
   2994             ALPM_FIRST_AVAIL_BANK(bank_num, bank_count, bank_disable);
   2995 
   2996             /* Get the bucket pointer from lpm mem entry */
   2997             for (bkt_idx = 0; bkt_idx < bkt_count; bkt_idx++) {
   2998                 /* Calculate bucket memory address */
   2999                 /* Increment so next bucket address can be calculated */
   3000                 bkt_addr = (entry_num << (bank_bits + alpm_bkt_bits)) |
   3001                            (bkt_ptr << bank_bits) |
   3002                            (bank_num & ((1U << bank_bits) - 1));
   3003                 entry_num++;
   3004                 if (entry_num == entry_count) {
   3005                     entry_num = 0;
   3006                     ALPM_NEXT_AVAIL_BANK(bank_num, bank_count, bank_disable);
   3007                     if (bank_num == bank_count) {
   3008                         ALPM_FIRST_AVAIL_BANK(bank_num, bank_count, bank_disable);
   3009                         bkt_ptr ++;
   3010                     }
   3011                 }
   3012 
   3013                 sal_memset(alpm_entry, 0x00, size);
   3014                 /* Read entry from bucket memory */
   3015                 rv = soc_mem_read_no_cache(unit, 0, alpm_mem, 0, MEM_BLOCK_ANY,
   3016                                            bkt_addr, alpm_entry);
   3017                 if (SOC_FAILURE(rv)) {
   3018                     break;
   3019                 }
   3020 
   3021                 if (!soc_mem_field32_get(unit, alpm_mem, alpm_entry, VALIDf)) {
   3022                     continue;
   3023                 }
   3024 
   3025                 if (ALPM_CTRL(unit).bkt_sharing && sub_bkt !=
   3026                     soc_mem_field32_get(unit, alpm_mem, alpm_entry, SUB_BKT_PTRf)) {
   3027                     continue;
   3028                 }
   3029 
   3030                 /* Zero destination buffer first. */
   3031                 sal_memset(&lpm_cfg, 0, sizeof(_bcm_defip_cfg_t));
   3032 
   3033                 /* Parse the entry. */
   3034                 _bcm_th_alpm_ent_data_parse(unit, &lpm_cfg, &nh_ecmp_idx,
   3035                                             alpm_mem, alpm_entry);
   3036 
   3037                 /* If protocol doesn't match skip the entry. */
   3038                 if ((lpm_cfg.defip_flags & BCM_L3_IP6) != ipv6) {
   3039                     continue;
   3040                 }
   3041                  
   3042                 /* Fill entry IP address and subnet mask. */
   3043                 _bcm_th_alpm_ent_key_parse(unit, &lpm_cfg, lpm_entry,
   3044                                            alpm_mem, alpm_entry);
   3045 
   3046                 lpm_cfg.defip_index = bkt_addr;
   3047 
   3048                 /* Check if this is default route */
   3049                 /* Subnet length zero will indicate default route */
   3050                 if (0 == lpm_cfg.defip_sub_len) {
   3051                     if (def_arr_idx < SOC_VRF_MAX(unit)) {
   3052                         def_rte_arr[def_arr_idx].bkt_addr = bkt_addr;
   3053                         def_rte_arr[def_arr_idx].idx = idx;
   3054                         sal_memcpy(&def_rte_arr[def_arr_idx].lpm_entry,
   3055                                    lpm_entry, sizeof(*lpm_entry));
   3056                         def_arr_idx ++;
   3057                     }
   3058                 } else {
   3059                     /* Execute operation routine if any. */
   3060                     if (trv_data->op_cb) {
   3061                         rv = (*trv_data->op_cb) (unit, (void *)trv_data,
   3062                                                 (void *)&lpm_cfg,
   3063                                                 (void *)&nh_ecmp_idx, &cmp_result);
   3064 #ifdef BCM_CB_ABORT_ON_ERR
   3065                         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   3066                             break;
   3067                         }
   3068 #endif
   3069                     }
   3070                 }
   3071             }
   3072         }
   3073     }
   3074 
   3075     /* Process Default routes */
   3076     for (idx = 0; idx < def_arr_idx; idx++) {
   3077 
   3078         /* Calculate entry ofset. */
   3079         lpm_entry = &def_rte_arr[idx].lpm_entry;
   3080 
   3081         cmp_result = ipv6 ? 1 : 0;
   3082         if (cmp_result != (soc_mem_field32_get(unit, L3_DEFIPm,
   3083                                             lpm_entry, MODE0_f(unit)))) {
   3084             /*
   3085              * Function called for IPv6 LPM/ALPM walk and LPM entry is IPv4; 
   3086              * Continue;
   3087              */
   3088             continue;
   3089         }
   3090         bkt_addr = def_rte_arr[idx].bkt_addr;
   3091 
   3092         flex = _soc_th_alpm_lpm_flex_get(unit, ipv6 ? L3_DEFIP_MODE_64 : 0,
   3093                     soc_mem_field32_get(unit, L3_DEFIPm,
   3094                     lpm_entry, ENTRY_VIEW0f));
   3095         if (ipv6) {
   3096             if (flex) {
   3097                 alpm_mem = L3_DEFIP_ALPM_IPV6_64_1m;
   3098                 alpm_entry = &alpm_entry_v6_64;
   3099                 size = sizeof(alpm_entry_v6_64);
   3100             } else {
   3101                 alpm_mem = L3_DEFIP_ALPM_IPV6_64m;
   3102                 alpm_entry = &alpm_entry_v6_64;
   3103                 size = sizeof(alpm_entry_v6_64);
   3104             }
   3105 
   3106         } else {
   3107             if (flex) {
   3108                 alpm_mem = L3_DEFIP_ALPM_IPV4_1m;
   3109                 alpm_entry = &alpm_entry_v4;
   3110                 size = sizeof(alpm_entry_v4);
   3111             } else {
   3112                 alpm_mem = L3_DEFIP_ALPM_IPV4m;
   3113                 alpm_entry = &alpm_entry_v4;
   3114                 size = sizeof(alpm_entry_v4);
   3115             }
   3116         }
   3117         sal_memset(alpm_entry, 0x00, size);
   3118         /* read entry from bucket memory */
   3119         rv = soc_mem_read_no_cache(unit, 0, alpm_mem, 0, MEM_BLOCK_ANY,
   3120                                    bkt_addr, alpm_entry);
   3121         if (SOC_FAILURE(rv)) {
   3122             break;
   3123         }
   3124 
   3125         if (!soc_mem_field32_get(unit, alpm_mem, alpm_entry, VALIDf)) {
   3126             continue;
   3127         }
   3128 
   3129         /* Zero destination buffer first. */
   3130         sal_memset(&lpm_cfg, 0, sizeof(_bcm_defip_cfg_t));
   3131 
   3132         (void)soc_th_alpm_lpm_vrf_get(unit, lpm_entry, &lpm_cfg.defip_vrf,
   3133                                       &cmp_result);
   3134         /* Parse  the entry. */
   3135         _bcm_th_alpm_ent_data_parse(unit, &lpm_cfg, &nh_ecmp_idx,
   3136                                     alpm_mem, alpm_entry);
   3137 
   3138         /* If protocol doesn't match skip the entry. */
   3139         if ((lpm_cfg.defip_flags & BCM_L3_IP6) != ipv6) {
   3140             continue;
   3141         }
   3142 
   3143         /* Fill entry ip address & subnet mask. */
   3144         _bcm_th_alpm_ent_key_parse(unit, &lpm_cfg, lpm_entry,
   3145                                    alpm_mem, alpm_entry);
   3146 
   3147         /* Execute operation routine if any. */
   3148         if (trv_data->op_cb) {
   3149             rv = (*trv_data->op_cb) (unit, (void *)trv_data,
   3150                                     (void *)&lpm_cfg,
   3151                                     (void *)&nh_ecmp_idx, &cmp_result);
   3152 #ifdef BCM_CB_ABORT_ON_ERR
   3153             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   3154                 break;
   3155             }
   3156 #endif
   3157         }
   3158     }
   3159 
   3160 #ifdef ALPM_WARM_BOOT_DEBUG
   3161     soc_alpm_lpm_sw_dump(unit);
   3162 #endif /* ALPM_WARM_BOOT_DEBUG  */
   3163 
   3164 cleanup:
   3165     if (def_rte_arr != NULL) {
   3166         sal_free(def_rte_arr);
   3167     }
   3168     if (lpm_tbl_ptr != NULL) {
   3169         soc_cm_sfree(unit, lpm_tbl_ptr);
   3170     }
   3171 
   3172     return (rv);
   3173 }
   3174 
   3175 /*
   3176  * Function:
   3177  *      _bcm_th_alpm_find
   3178  * Purpose:
   3179  *      Get an entry from DEFIP table.
   3180  * Parameters:
   3181  *      unit        - (IN)SOC unit number.
   3182  *      lpm_cfg     - (IN)Buffer to fill defip information. 
   3183  *      nh_ecmp_idx - (IN)Next hop or ecmp group index
   3184  * Returns:
   3185  *      BCM_E_XXX
   3186  */
   3187 int
   3188 _bcm_th_alpm_find(int unit, _bcm_defip_cfg_t *lpm_cfg, int *nh_ecmp_idx)
   3189 {
   3190     defip_entry_t lpm_key;      /* Route lookup key.        */
   3191     defip_entry_t lpm_entry;    /* Search result buffer.    */
   3192     defip_pair_128_entry_t lpm_128_key;
   3193     defip_pair_128_entry_t lpm_128_entry;
   3194     int do_urpf = 0;            /* Find uRPF region */
   3195     int rv;                     /* Operation return status. */
   3196     uint32 flags = 0;
   3197     soc_mem_t mem;
   3198     int lpm_mode, tmp;
   3199     uint32 rval;
   3200 
   3201     /* Input parameters check */
   3202     if (NULL == lpm_cfg) {
   3203         return (BCM_E_PARAM);
   3204     }
   3205 
   3206     SOC_IF_ERROR_RETURN(READ_L3_DEFIP_RPF_CONTROLr(unit, &rval));
   3207     lpm_mode  = soc_reg_field_get(unit, L3_DEFIP_RPF_CONTROLr, rval, LPM_MODEf);
   3208     /* Not supported in Legacy LPM mode */
   3209     if (lpm_mode == 0) {
   3210         return (BCM_E_UNAVAIL);
   3211     }
   3212     
   3213     /* Zero buffers. */
   3214     sal_memset(&lpm_entry, 0, sizeof(defip_entry_t));
   3215     sal_memset(&lpm_key, 0, sizeof(defip_entry_t));
   3216     sal_memset(&lpm_128_entry, 0, sizeof(defip_pair_128_entry_t));
   3217     sal_memset(&lpm_128_key, 0, sizeof(defip_pair_128_entry_t));
   3218 
   3219     /* Default value */
   3220     mem = L3_DEFIPm;
   3221     if ((lpm_cfg->defip_flags & BCM_L3_IP6)) {
   3222         if (soc_mem_index_count(unit, L3_DEFIP_PAIR_128m) > 0) {
   3223             mem = L3_DEFIP_PAIR_128m;
   3224         }
   3225     }
   3226     
   3227     switch (mem) {
   3228     case L3_DEFIP_PAIR_128m:
   3229         /* Initialize lkup key. */
   3230         BCM_IF_ERROR_RETURN(_bcm_th_alpm_lpm128_init(unit, lpm_cfg,
   3231                                             &lpm_128_key, 0, &flags));
   3232         /* Perform hw lookup. */
   3233         rv = soc_th_alpm_128_find_best_match(unit, &lpm_128_key, &lpm_128_entry, 
   3234                                              &lpm_cfg->defip_index, do_urpf);
   3235         BCM_IF_ERROR_RETURN(rv);
   3236 
   3237         /* Parse hw buffer to defip entry. */
   3238         _bcm_th_alpm_lpm128_data_parse(unit, lpm_cfg, nh_ecmp_idx,
   3239                                        &lpm_128_entry);
   3240         /* OVERRIDE VRF Processing */
   3241         _bcm_th_alpm_lpm128_key_parse(unit, (uint32 *)&lpm_128_entry, lpm_cfg);
   3242         soc_th_alpm_128_lpm_vrf_get(unit, &lpm_128_entry, &lpm_cfg->defip_vrf, &tmp);
   3243 
   3244         break;
   3245     default:
   3246         /* Initialize lkup key. */
   3247         BCM_IF_ERROR_RETURN(_bcm_th_alpm_lpm_init(unit, lpm_cfg, &lpm_key, 0,
   3248                                                   &flags));
   3249         /* Perform hw lookup. */
   3250         rv = soc_th_alpm_find_best_match(unit, &lpm_key, &lpm_entry, 
   3251                                       &lpm_cfg->defip_index, do_urpf);
   3252         BCM_IF_ERROR_RETURN(rv);
   3253     
   3254         /* Parse hw buffer to defip entry. */
   3255         _bcm_th_alpm_lpm_data_parse(unit, lpm_cfg, nh_ecmp_idx, &lpm_entry);
   3256         _bcm_th_alpm_lpm_key_parse(unit, lpm_cfg, &lpm_entry);
   3257 
   3258         break;
   3259     }
   3260     
   3261     return (BCM_E_NONE);
   3262 }
   3263 
   3264 #endif /* defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) */
   3265 #endif /* INCLUDE_L3 && ALPM_ENABLE */
   3266