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

alpm_128.c (284539B)


      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  * File:    alpm_128.c
      7  * Purpose: Primitives for LPM management in ALPM - Mode for IPv6-128.
      8  * Requires:
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <soc/mem.h>
     14 #include <soc/drv.h>
     15 #include <soc/debug.h>
     16 #include <soc/error.h>
     17 #include <soc/lpm.h>
     18 #include <soc/trident2.h>
     19 #ifdef ALPM_ENABLE
     20 #include <shared/util.h>
     21 #include <shared/l3.h>
     22 #include <soc/alpm.h>
     23 #include <soc/esw/alpm_int.h>
     24 #include <soc/esw/trie.h>
     25 
     26 
     27 #define ALPM_USE_RAW_VIEW
     28 /* indicate whether HIT flag is supported */
     29 
     30 #define SHR_SHIFT_LEFT(val, count) \
     31     (((count) == 32) ? 0 : (val) << (count))
     32 
     33 #define SHR_SHIFT_RIGHT(val, count) \
     34     (((count) == 32) ? 0 : (val) >> (count))
     35 
     36 /* Add support for Extended based on Flex Counter support type */
     37 #define SOC_ALPM_TABLE_MEM_128(_u_, _v6_, _mem_)             \
     38             _mem_ = L3_DEFIP_ALPM_IPV6_128m
     39 
     40 /* Add suport for Extended */
     41 #define SOC_ALPM_ENTRY_BUF_128(_v6_, _mem_, _buf_, _v4ent_, _v6ent_)  \
     42             _buf_ = ((uint32 *) &(_v6ent_))
     43 
     44 /* this is a left shift of the prefix by 32/64 - length  and convert to
     45    brcm order of ip words */
     46 #define ALPM_TRIE_TO_NORMAL_IP_128(prefix, length, v6) \
     47     _soc_alpm_128_trie_to_normal_ip((prefix), (length), (v6))
     48 
     49 
     50 /***********************************************************************
     51  ***********************************************************************
     52  *              TCAM Management and ALPM Memory Mangement              *
     53  */
     54 
     55 void soc_alpm_128_lpm_state_dump(int u);
     56 static int soc_alpm_128_lpm_insert(int u, void *entry_data, int *lpm_index,
     57                                    int src_default, int src_discard, int bpm_len);
     58 static int soc_alpm_128_lpm_delete(int u, void *key_data);
     59 static int _soc_alpm_128_fill_aux_entry_for_op(int u,
     60                void *key_data,
     61                int ipv6,    /* Entry is ipv6. */
     62                int db_type, /* database type */
     63                int ent_type,
     64                int replace_len, /* used for DElete propagate */
     65                defip_aux_scratch_entry_t *aux_entry);
     66 
     67 static int _soc_alpm_128_lpm_match(int u,
     68                void *key_data,
     69                void *e,         /* return entry data if found */
     70                int *index_ptr,  /* return key location */
     71                int *pfx_len,    /* Key prefix length. vrf + 32 + prefix len for IPV6*/
     72                int *ipv6);       /* Entry is ipv6. */
     73 static int soc_alpm_128_lpm_match(int u,
     74                void *key_data,
     75                void *e,         /* return entry data if found */
     76                int *index_ptr);  /* return key location */
     77 static int _soc_alpm_128_mem_ent_init(int unit, void *lpm_entry, 
     78                        void *alpm_entry, void *alpm_sip_entry, soc_mem_t mem,
     79                        uint32 src_flags, uint32 *default_route);
     80 static int
     81 _soc_alpm_128_lpm_ent_init(int unit, void *alpm_entry, soc_mem_t mem, int ipv6, int vrf,
     82                        int bucket, int index, void *lpm_entry, int flex);
     83 static int
     84 _soc_alpm_128_lpm_ent_key_init(int unit, uint32 *key, int len, int vrf, int ipv6,
     85                       defip_pair_128_entry_t *lpm_entry, int nh_ecmp_idx, int init);
     86 
     87 static int soc_alpm_128_vrf_delete(int u, int vrf, int v6);
     88 
     89 
     90 #define FB_LPM_128_HASH_SUPPORT 1
     91 
     92 typedef struct soc_alpm_128_lpm_state_s {
     93     int start;  /* start index for this prefix length */
     94     int end;    /* End index for this prefix length */
     95     int prev;   /* Previous (Lo to Hi) prefix length with non zero entry count*/
     96     int next;   /* Next (Hi to Lo) prefix length with non zero entry count */
     97     int vent;   /* valid entries */
     98     int fent;   /* free entries */
     99 } soc_alpm_128_lpm_state_t, *soc_alpm_128_lpm_state_p;
    100 
    101 #define SOC_MEM_128_COMPARE_RETURN(a, b) {          \
    102         if ((a) < (b)) { return -1; }           \
    103         if ((a) > (b)) { return  1; }           \
    104 }
    105 
    106 /* Can move to SOC Control structures */
    107 static soc_alpm_128_lpm_state_p soc_alpm_128_lpm_state[SOC_MAX_NUM_DEVICES];
    108 
    109 #define IPV6_128_PFX_ZERO                0
    110 #define MAX_PFX_ENTRIES_128              (3 * (128 + 2 + 1))
    111 #define MAX_PFX_INDEX_128                (MAX_PFX_ENTRIES_128 - 1)
    112 #define MAX_VRF_PFX_INDEX_128            ((MAX_PFX_ENTRIES_128/3) - 1)
    113 #define SOC_ALPM_128_LPM_INIT_CHECK(u)    (soc_alpm_128_lpm_state[(u)] != NULL)
    114 #define SOC_ALPM_128_LPM_STATE(u)             (soc_alpm_128_lpm_state[(u)])
    115 #define SOC_ALPM_128_LPM_STATE_START(u, pfx)  \
    116     (soc_alpm_128_lpm_state[(u)][(pfx)].start)
    117 #define SOC_ALPM_128_LPM_STATE_END(u, pfx)    \
    118     (soc_alpm_128_lpm_state[(u)][(pfx)].end)
    119 #define SOC_ALPM_128_LPM_STATE_PREV(u, pfx)  \
    120     (soc_alpm_128_lpm_state[(u)][(pfx)].prev)
    121 #define SOC_ALPM_128_LPM_STATE_NEXT(u, pfx)  \
    122     (soc_alpm_128_lpm_state[(u)][(pfx)].next)
    123 #define SOC_ALPM_128_LPM_STATE_VENT(u, pfx)  \
    124     (soc_alpm_128_lpm_state[(u)][(pfx)].vent)
    125 #define SOC_ALPM_128_LPM_STATE_FENT(u, pfx)  \
    126     (soc_alpm_128_lpm_state[(u)][(pfx)].fent)
    127 
    128 #define SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(m, f) soc_field_info_t * m##f
    129 #define SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(m_u, s, m, f) \
    130                 (s)->m##f = soc_mem_fieldinfo_get(m_u, m, f)
    131 
    132 typedef struct soc_lpm_128_field_cache_s {
    133     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, CLASS_IDf);
    134     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, DST_DISCARDf);
    135     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ECMPf);
    136     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ECMP_COUNTf);
    137     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ECMP_PTRf);
    138     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, GLOBAL_ROUTEf);
    139     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MULTICAST_ROUTEf);
    140     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, RPA_IDf);
    141     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, EXPECTED_L3_IIFf);    
    142     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf);
    143     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf);
    144     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, L3MC_INDEXf);
    145     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, HITf);
    146     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IP_ADDR0_UPRf);
    147     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IP_ADDR1_UPRf);
    148     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IP_ADDR0_LWRf);
    149     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IP_ADDR1_LWRf);
    150     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IP_ADDR_MASK0_UPRf);
    151     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IP_ADDR_MASK1_UPRf);
    152     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IP_ADDR_MASK0_LWRf);
    153     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IP_ADDR_MASK1_LWRf);
    154     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MODE0_UPRf);
    155     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MODE1_UPRf);
    156     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MODE0_LWRf);
    157     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MODE1_LWRf);
    158     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MODE_MASK0_UPRf);
    159     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MODE_MASK1_UPRf);
    160     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MODE_MASK0_LWRf);
    161     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MODE_MASK1_LWRf);
    162     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, NEXT_HOP_INDEXf);
    163     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, PRIf);
    164     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, RPEf);
    165     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VALID0_UPRf);
    166     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VALID1_UPRf);
    167     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VALID0_LWRf);
    168     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VALID1_LWRf);
    169     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VRF_ID_0_UPRf);
    170     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VRF_ID_1_UPRf);
    171     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VRF_ID_0_LWRf);
    172     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VRF_ID_1_LWRf);
    173     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VRF_ID_MASK0_UPRf);
    174     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VRF_ID_MASK1_UPRf);
    175     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VRF_ID_MASK0_LWRf);
    176     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VRF_ID_MASK1_LWRf);
    177     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, GLOBAL_HIGHf);
    178     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ALG_HIT_IDXf);
    179     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ALG_BKT_PTRf);
    180     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, DEFAULT_MISSf);
    181     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, FLEX_CTR_BASE_COUNTER_IDXf);
    182     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, FLEX_CTR_OFFSET_MODEf);
    183     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, FLEX_CTR_POOL_NUMBERf);
    184     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ENTRY_TYPE_MASK0_LWRf);
    185     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ENTRY_TYPE_MASK1_LWRf);
    186     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ENTRY_TYPE_MASK0_UPRf);
    187     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ENTRY_TYPE_MASK1_UPRf);
    188     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ENTRY_TYPE0_LWRf);
    189     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ENTRY_TYPE1_LWRf);
    190     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ENTRY_TYPE0_UPRf);
    191     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ENTRY_TYPE1_UPRf);
    192     SOC_ALPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ENTRY_VIEWf);
    193 } soc_lpm_128_field_cache_t, *soc_lpm_128_field_cache_p;
    194 
    195 static soc_lpm_128_field_cache_p 
    196                         soc_lpm_128_field_cache_state[SOC_MAX_NUM_DEVICES];
    197 
    198 #define SOC_MEM_OPT_F32_GET_128(m_unit, m_mem, m_entry_data, m_field) \
    199         soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), (soc_lpm_128_field_cache_state[(m_unit)]->m_mem##m_field))
    200 
    201 #define SOC_MEM_OPT_F32_SET_128(m_unit, m_mem, m_entry_data, m_field, m_val) \
    202         soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), (soc_lpm_128_field_cache_state[(m_unit)]->m_mem##m_field), (m_val))
    203 
    204 
    205 #define SOC_MEM_OPT_FIELD_VALID_128(m_unit, m_mem, m_field) \
    206         ((soc_lpm_128_field_cache_state[(m_unit)]->m_mem##m_field) != NULL)
    207 
    208 
    209 #ifdef FB_LPM_128_HASH_SUPPORT
    210 typedef struct _soc_alpm_128_lpm_hash_s {
    211     int         unit;
    212     int         entry_count;    /* Number entries in hash table */
    213     int         index_count;    /* Hash index max value + 1 */
    214     uint16      *table;         /* Hash table with 16 bit index */
    215     uint16      *link_table;    /* To handle collisions */
    216 } _soc_alpm_128_lpm_hash_t;
    217 
    218 typedef uint32 _soc_alpm_128_lpm_hash_entry_t[9];
    219 typedef int (*_soc_alpm_128_lpm_hash_compare_fn)
    220      (_soc_alpm_128_lpm_hash_entry_t key1, _soc_alpm_128_lpm_hash_entry_t key2);
    221 static _soc_alpm_128_lpm_hash_t *_fb_lpm_128_hash_tab[SOC_MAX_NUM_DEVICES];
    222 
    223 #define SOC_ALPM_128_LPM_STATE_HASH(u)           (_fb_lpm_128_hash_tab[(u)])
    224 
    225 #define TD2_ALPM_128_HASH_INDEX_NULL  (0xFFFF)
    226 #define TD2_ALPM_128_HASH_INDEX_MASK  (0x3FFF)
    227 #define TD2_ALPM_128_HASH_IPV6_MASK   (0x8000)
    228 
    229 #define SOC_FB_LPM_128_HASH_ENTRY_GET_IPV6(u, entry_data, odata) \
    230     odata[0] = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, entry_data, \
    231                IP_ADDR0_LWRf);\
    232     odata[1] = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, entry_data, \
    233                IP_ADDR0_UPRf);\
    234     odata[2] = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, entry_data, \
    235                IP_ADDR_MASK0_LWRf);\
    236     odata[3] = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, entry_data, \
    237                IP_ADDR_MASK0_UPRf);\
    238     odata[4] = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, entry_data, \
    239                IP_ADDR1_LWRf);\
    240     odata[5] = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, entry_data, \
    241                IP_ADDR1_UPRf);\
    242     odata[6] = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, entry_data, \
    243                IP_ADDR_MASK1_LWRf);\
    244     odata[7] = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, entry_data, \
    245                IP_ADDR_MASK1_UPRf);\
    246     if ( (!(SOC_IS_HURRICANE(u))) &&   \
    247         (SOC_MEM_OPT_FIELD_VALID_128(u, L3_DEFIP_PAIR_128m, VRF_ID_0_LWRf))) { \
    248         int m_vrf;\
    249         (void) soc_alpm_128_lpm_vrf_get(u, entry_data, (int *)&odata[8], &m_vrf); \
    250     } else {                                                                 \
    251         odata[8] = 0;                                                        \
    252     }                                                                       
    253 
    254 #define SOC_FB_LPM_128_HASH_ENTRY_GET _soc_alpm_128_lpm_hash_entry_get
    255 
    256 static void 
    257 _soc_alpm_128_lpm_hash_entry_get(int u, void *e,
    258                              int index, _soc_alpm_128_lpm_hash_entry_t r_entry,
    259                              int *v);
    260 static uint16 
    261 _soc_alpm_128_lpm_hash_compute(uint8 *data, int data_nbits);
    262 static int 
    263 _soc_alpm_128_lpm_hash_create(int unit, int entry_count, int index_count,
    264                             _soc_alpm_128_lpm_hash_t **fb_lpm_hash_ptr);
    265 static int 
    266 _soc_alpm_128_lpm_hash_destroy(_soc_alpm_128_lpm_hash_t *fb_lpm_hash);
    267 static int 
    268 _soc_alpm_128_lpm_hash_lookup(_soc_alpm_128_lpm_hash_t *hash,
    269                             _soc_alpm_128_lpm_hash_compare_fn key_cmp_fn,
    270                             _soc_alpm_128_lpm_hash_entry_t    entry,
    271                             int pfx, uint16 *key_index);
    272 static
    273 int _soc_alpm_128_lpm_hash_insert(_soc_alpm_128_lpm_hash_t *hash,
    274                             _soc_alpm_128_lpm_hash_compare_fn key_cmp_fn,
    275                             _soc_alpm_128_lpm_hash_entry_t entry,
    276                             int pfx, uint16 old_index, uint16 new_index,
    277                             uint32 *rvt_index);
    278 static
    279 int _soc_alpm_128_lpm_hash_revert(_soc_alpm_128_lpm_hash_t *hash,
    280                             _soc_alpm_128_lpm_hash_compare_fn key_cmp_fn,
    281                             _soc_alpm_128_lpm_hash_entry_t entry,
    282                             uint16 new_index,
    283                             uint32 rvt_index);
    284 static
    285 int _soc_alpm_128_lpm_hash_delete(_soc_alpm_128_lpm_hash_t *hash,
    286                             _soc_alpm_128_lpm_hash_compare_fn key_cmp_fn,
    287                             _soc_alpm_128_lpm_hash_entry_t entry,
    288                             int pfx, uint16 delete_index);
    289 static
    290 int _soc_alpm_128_lpm_hash_verify(_soc_alpm_128_lpm_hash_t *hash,
    291                             _soc_alpm_128_lpm_hash_compare_fn key_cmp_fn,
    292                             _soc_alpm_128_lpm_hash_entry_t entry,
    293                             int    pfx,
    294                             uint16 index);
    295 
    296 int
    297 _soc_alpm_128_ip6_mask_len_get(int u, const void *entry, int *pfx)
    298 {
    299     int     i, rv;
    300     int     field[4] = {IP_ADDR_MASK0_LWRf, IP_ADDR_MASK1_LWRf, 
    301                         IP_ADDR_MASK0_UPRf, IP_ADDR_MASK1_UPRf};
    302     uint32  ipv4a;
    303 
    304     ipv4a = soc_mem_field32_get(u, L3_DEFIP_PAIR_128m, entry, field[0]);
    305     if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) {
    306         LOG_ERROR(BSL_LS_SOC_ALPM,
    307                   (BSL_META_U(u,
    308                           "_ipmask2pfx fails mask0 0x%x pfx %d\n"),
    309                           ipv4a, *pfx));
    310         return(rv);
    311     }
    312     for (i = 1; i < 4; i++) {
    313         ipv4a = soc_mem_field32_get(u, L3_DEFIP_PAIR_128m, entry, field[i]);
    314         if (*pfx) {
    315             if (ipv4a != 0xffffffff)  {
    316                 LOG_ERROR(BSL_LS_SOC_ALPM,
    317                           (BSL_META_U(u,
    318                                   "ip6_mask_len_get fails i %d mask 0x%x pfx %d\n"),
    319                                   i, ipv4a, *pfx));
    320                 return(SOC_E_PARAM);
    321             }
    322             *pfx += 32;
    323         } else {
    324             if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) {
    325                 LOG_ERROR(BSL_LS_SOC_ALPM,
    326                           (BSL_META_U(u,
    327                                   "_ipmask2pfx fails mask%d 0x%x pfx %d\n"),
    328                                   i, ipv4a, *pfx));
    329                 return(rv);
    330             }
    331         }
    332     }
    333     return SOC_E_NONE;
    334 }
    335 
    336 static void
    337 _soc_alpm_128_trie_to_normal_ip(uint32 *result, int length, int v6)
    338 {
    339     uint32 pfx_shift, tmp, start, prefix[5];
    340     int i;
    341 
    342     sal_memcpy(prefix, result, sizeof(uint32) * BITS2WORDS(_MAX_KEY_LEN_144_));
    343     sal_memset(result, 0, sizeof(uint32) * BITS2WORDS(_MAX_KEY_LEN_144_));
    344 
    345     /* shift entire prefix left to add trailing 0s in prefix */
    346     pfx_shift = 128 - length;
    347     start = (pfx_shift + 31) / 32;
    348     /* fix corner case: */
    349     if ((pfx_shift % 32) == 0) {
    350         start++;
    351     }
    352     pfx_shift = pfx_shift % 32;
    353     for (i = start; i <= 4; i++) {
    354         prefix[i] <<= pfx_shift;
    355         if (i < 4) {
    356             tmp = prefix[i+1] & ~(0xffffffff >> pfx_shift);
    357             tmp = SHR_SHIFT_RIGHT(tmp, 32 - pfx_shift);
    358             prefix[i] |= tmp;
    359         }
    360     } 
    361     /* make shift left justified and reversed, i.e, lsw goes to index 0 */
    362     for (i = start; i <= 4; i++) {
    363         result[3 - (i - start)] = prefix[i];
    364     }
    365 }
    366 
    367 static void
    368 _soc_alpm_128_pfx_len_to_mask(int unit, void *lpm_entry, int pfx_len)
    369 {
    370     int i;
    371     soc_field_t mask_field[4] = {IP_ADDR_MASK0_LWRf, IP_ADDR_MASK1_LWRf,
    372                                  IP_ADDR_MASK0_UPRf, IP_ADDR_MASK1_UPRf};
    373     /* initialize mask field to 0, in case same entry is first being filled with
    374      * associated data first and then key later
    375      */
    376     for (i = 0; i < 4; i++) {
    377         soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, mask_field[i], 0);
    378     }
    379     for (i = 0; i < 4; i++) {
    380         if (pfx_len <= 32) break;
    381         soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry,
    382                             mask_field[3-i], 0xffffffff);
    383         pfx_len -= 32;
    384     }
    385 
    386     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, mask_field[3-i],
    387                         ~SHR_SHIFT_RIGHT(0xffffffff, pfx_len));
    388 }
    389 
    390 /* Create Prefix */
    391 /* Prefix is created based on the trie key packing expectations */
    392 /* Prefix[0] will have higher order Word, Prefix[1] will have lower order word
    393  * in case of IPV6. For IPV4 prefix[0] will contain the prefix
    394  */
    395 static int
    396 _alpm_128_prefix_create(int u, void *entry, uint32 *result, uint32 *pfx_len, 
    397                     int *default_route)
    398 {
    399     int i;
    400     int pfx = 0, start;
    401     int rv = SOC_E_NONE;
    402     uint32 pfx_shift, tmp;
    403     uint32  prefix[5];
    404 
    405     sal_memset(result, 0, sizeof(uint32) * BITS2WORDS(_MAX_KEY_LEN_144_));
    406     sal_memset(prefix, 0, sizeof(uint32) * BITS2WORDS(_MAX_KEY_LEN_144_));
    407 
    408     /* Form Prefix based on the entry */
    409     prefix[0] = soc_mem_field32_get(u, L3_DEFIP_PAIR_128m, entry, 
    410                                     IP_ADDR0_LWRf);
    411     prefix[1] = soc_mem_field32_get(u, L3_DEFIP_PAIR_128m, entry, 
    412                                     IP_ADDR1_LWRf);
    413     prefix[2] = soc_mem_field32_get(u, L3_DEFIP_PAIR_128m, entry, 
    414                                     IP_ADDR0_UPRf);
    415     prefix[3] = soc_mem_field32_get(u, L3_DEFIP_PAIR_128m, entry, 
    416                                     IP_ADDR1_UPRf);
    417 
    418     /* Obtain prefix length */
    419     rv = _soc_alpm_128_ip6_mask_len_get(u, entry, &pfx);
    420     if (SOC_FAILURE(rv)) {
    421         return rv;
    422     }
    423 
    424     /* shift entire prefix right to remove trailing 0s in prefix */
    425     /* to simplify, words which are all 0s are ignored to begin with, so
    426      * a right shift of say 46 is a right shift of 46-32 = 14, but starting
    427      * from word 1. Once all shifting is done, shift all words to right by 1 
    428      */
    429     pfx_shift = 128 - pfx;
    430     start = pfx_shift / 32;
    431     pfx_shift = pfx_shift % 32;
    432     for (i = start; i < 4; i++) {
    433         prefix[i] >>= pfx_shift;
    434         tmp = prefix[i+1] & ((1 << pfx_shift) - 1);
    435         tmp = SHR_SHIFT_LEFT(tmp, 32 - pfx_shift);
    436         prefix[i] |= tmp;
    437     } 
    438     /* make shift right justified and also reverse order for trie. 
    439      * Also, note trie sees key only in words 1 to 4
    440      */
    441     for (i = start; i < 4; i++) {
    442         result[4 - (i - start)] = prefix[i];
    443     }
    444     *pfx_len = pfx;
    445     if (default_route != NULL) {
    446         *default_route = (prefix[0] == 0) && (prefix[1] == 0) &&
    447                          (prefix[2] == 0) && (prefix[3] == 0) && (pfx == 0);
    448     }
    449     return SOC_E_NONE;
    450 }
    451 
    452 static int _soc_alpm_128_sw_pivot_find(int u, uint32 *prefix, uint32 length, int ipv6,
    453                                 int vrf, int *hit, int *tcam_index, 
    454                                 int *bucket_index)
    455 {
    456     int rv = SOC_E_NONE;
    457     trie_t  *pivot_trie;
    458     trie_node_t *lpmp = NULL;
    459     alpm_pivot_t *pivot_pyld;
    460 
    461     pivot_trie = VRF_PIVOT_TRIE_IPV6_128(u, vrf);
    462     rv = trie_find_lpm(pivot_trie, prefix, length, &lpmp);
    463     if (SOC_FAILURE(rv)) {
    464         LOG_ERROR(BSL_LS_SOC_ALPM,
    465                   (BSL_META_U(u,
    466                               "Pivot find failed\n")));
    467         return rv;
    468     }
    469     pivot_pyld = (alpm_pivot_t *)lpmp;
    470     
    471     *hit = 1;
    472     *tcam_index = PIVOT_TCAM_INDEX(pivot_pyld);
    473     *bucket_index = PIVOT_BUCKET_INDEX(pivot_pyld);
    474     
    475     return SOC_E_NONE;
    476 }
    477 
    478 int
    479 _soc_alpm_128_sw_prefix_check(int u,
    480                               soc_mem_t mem,      /* Mem type for ALPM */
    481                               int v6,
    482                               void *key_data,     /* TCAM entry data */
    483                               int vrf_id,
    484                               int vrf)
    485 {
    486     int         rv = SOC_E_NONE;
    487     uint32 prefix[5], length;
    488     int default_route = 0;
    489     trie_t  *pivot_trie, *bkt_trie;
    490     trie_node_t *lpmp = NULL;
    491     alpm_pivot_t *pivot_node;
    492 
    493     if (vrf_id == 0) {
    494         if (soc_alpm_mode_get(u)) {
    495             /* cannot have 0 as a VRF in parallel mode */
    496             return SOC_E_PARAM;
    497         }
    498     }
    499 
    500     if (vrf_id != SOC_L3_VRF_OVERRIDE) {
    501         /* Create Prefix */
    502         rv = _alpm_128_prefix_create(u, key_data, prefix, &length,
    503                                  &default_route);
    504         if (SOC_FAILURE(rv)) {
    505             LOG_ERROR(BSL_LS_SOC_ALPM,
    506                       (BSL_META_U(u,
    507                                   "_soc_alpm_128_sw_prefix_check: prefix create failed\n")));
    508             return rv;
    509         }
    510 
    511         pivot_trie = VRF_PIVOT_TRIE_IPV6_128(u, vrf);
    512 
    513         rv = trie_find_lpm(pivot_trie, prefix, length, &lpmp);
    514         if (SOC_FAILURE(rv)) {
    515             LOG_ERROR(BSL_LS_SOC_ALPM,
    516                       (BSL_META_U(u,
    517                                   "_soc_alpm_128_sw_prefix_check: Pivot find failed\n")));
    518             return rv;
    519         }
    520         pivot_node = (alpm_pivot_t *)lpmp;
    521         bkt_trie = pivot_node->bucket->bucket_trie;
    522         if (bkt_trie != NULL) {
    523             rv = trie_search(bkt_trie, prefix, length,
    524                              (trie_node_t **)&bkt_trie);
    525             if (SOC_FAILURE(rv)){
    526                 LOG_ERROR(BSL_LS_SOC_ALPM,
    527                           (BSL_META_U(u,
    528                                       "_soc_alpm_128_sw_prefix_check: prefix find failed\n")));
    529             }
    530         } else {
    531             LOG_ERROR(BSL_LS_SOC_ALPM,
    532                       (BSL_META_U(u,
    533                                   "_soc_alpm_128_sw_prefix_check: bkt trie doesn't exist\n")));
    534         }
    535     }
    536     return rv;
    537 }
    538 
    539 
    540 /*
    541  * Find and read the match in the database.
    542  * Returns SOC_E_NONE, if found.
    543  * SOC_E_NOT_FOUND if not found
    544  * SOC_E_FAIL, if lookup failed.
    545  */
    546 static int
    547 _soc_alpm_128_find(int u,
    548                    void *key_data,     /* TCAM entry data */
    549                    soc_mem_t mem,      /* Mem type for ALPM */
    550                    void *alpm_data,    /* Alpm data if match */
    551                    int *tcam_index,    /* TCAM INDEX */
    552                    int *bucket_index,  /* return Bucket Index*/
    553                    int *index_ptr,     /* return key location */
    554                    int sw_find         /* 1: search from trie, 0: search from aux */
    555                   )     
    556 {
    557     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
    558     int         vrf_id, vrf, v6;
    559     int         key_index ;
    560     uint32      db_type, ent_type, bank_disable;
    561     int         rv = SOC_E_NONE;
    562     int         hit = 0;
    563 
    564     v6 = L3_DEFIP_MODE_128;
    565 
    566     SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
    567     if (vrf_id == 0) {
    568         if (soc_alpm_mode_get(u)) {
    569             /* cannot have 0 as a VRF in parallel mode */
    570             return SOC_E_PARAM;
    571         }
    572     }
    573 
    574     soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
    575     bank_disable = soc_alpm_bank_dis(u, vrf);
    576 
    577     /* For VRF_OVERRIDE (Global High) entries, software needs to maintain the
    578      * index */
    579     /* Prefix resides in TCAM directly */
    580     if (vrf_id != SOC_L3_VRF_OVERRIDE) {
    581         if (sw_find) {
    582             uint32 prefix[5], length;
    583             int default_route = 0;
    584         
    585             /* Create Prefix */
    586             rv = _alpm_128_prefix_create(u, key_data, prefix, &length, &default_route);
    587             if (SOC_FAILURE(rv)) {
    588                 LOG_ERROR(BSL_LS_SOC_ALPM,
    589                           (BSL_META_U(u,
    590                                   "_soc_alpm_insert: prefix create failed\n")));
    591                 return rv;
    592             }
    593         
    594             rv = _soc_alpm_128_sw_pivot_find(u, prefix, length, v6, vrf, &hit,
    595                                              tcam_index, bucket_index);
    596             SOC_IF_ERROR_RETURN(rv);
    597         } else {
    598             defip_aux_scratch_entry_t aux_entry;
    599             /* Fill in AUX Scratch and perform Lookup Operation */
    600             SOC_IF_ERROR_RETURN(
    601                 _soc_alpm_128_fill_aux_entry_for_op(u, key_data, v6, db_type,
    602                                                     ent_type, 0, &aux_entry));
    603             SOC_IF_ERROR_RETURN(
    604                 _soc_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry, TRUE, &hit, 
    605                                  tcam_index, bucket_index, 0));
    606         }
    607 
    608         if (hit) { /* Entry is found in the bucket_index */
    609 
    610             /* Fill entry for lookup */
    611             _soc_alpm_128_mem_ent_init(u, key_data, e, 0, mem, 0, 0);
    612 
    613             /* Perform lookup */
    614             rv = _soc_alpm_find_in_bkt(u, mem, *bucket_index, bank_disable,
    615                                        e, alpm_data, &key_index, v6);
    616             if (SOC_SUCCESS(rv)) {
    617                 *index_ptr = key_index;
    618             } 
    619         } else {
    620             rv = SOC_E_NOT_FOUND;
    621         }
    622     }
    623     return rv;
    624 }
    625 
    626 /*
    627  * Find and update the match in the database.
    628  * Returns SOC_E_NONE, if found and updated.
    629  * SOC_E_NOT_FOUND if not found
    630  * SOC_E_FAIL, if update failed.
    631  */
    632 static int
    633 _soc_alpm_128_find_and_update(int u,
    634                               void *key_data,  /* TCAM entry data */
    635                               void *alpm_data, /* Alpm data to be updated with */
    636                               void *alpm_sip_data,
    637                               soc_mem_t mem,   /* Mem view for ALPM data */
    638                               int key_index)  /* key location */
    639 {
    640     defip_aux_scratch_entry_t aux_entry;
    641     int         vrf_id, v6, vrf;
    642     int         bucket_index;
    643     uint32      db_type, ent_type;
    644     int         hit = 0, tmp = 0;
    645     int         tcam_index;
    646     int         aux_flags = 0;
    647 
    648     v6 = L3_DEFIP_MODE_128;
    649     SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
    650     soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
    651 
    652     /* For VRF_OVERRIDE (Global High) entries */
    653     if (vrf_id != SOC_L3_VRF_OVERRIDE) {
    654         /* Fill in AUX Scratch and perform Lookup Operation */
    655         SOC_IF_ERROR_RETURN(
    656            _soc_alpm_128_fill_aux_entry_for_op(u, key_data, v6, db_type,
    657                                 ent_type, 0, &aux_entry));
    658 
    659             /* Perform lookup */
    660             /* Update the entry */
    661             SOC_IF_ERROR_RETURN(
    662                 soc_mem_write(u, mem, MEM_BLOCK_ANY, key_index, 
    663                               alpm_data));
    664 
    665             if (SOC_URPF_STATUS_GET(u)) {
    666                 /* Update the sip entry */
    667                 SOC_IF_ERROR_RETURN(soc_mem_write(u, mem, MEM_BLOCK_ANY, 
    668                                     _soc_alpm_rpf_entry(u, key_index), 
    669                                     alpm_sip_data));
    670                 if (soc_mem_field32_get(u, mem, alpm_sip_data, DEFAULTROUTEf)) {
    671                     aux_flags |= SOC_ALPM_AUX_DEF_ROUTE;
    672                 }
    673                 if (soc_mem_field32_get(u, mem, alpm_sip_data, SRC_DISCARDf)) {
    674                     aux_flags |= SOC_ALPM_AUX_SRC_DISCARD;
    675                 }
    676             }
    677             /* set REPLACE_LEN field to correct value */
    678             tmp = soc_mem_field32_get(u, L3_DEFIP_AUX_SCRATCHm, 
    679                                      &aux_entry, IP_LENGTHf);
    680             soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, &aux_entry, 
    681                                 REPLACE_LENf, tmp);
    682 
    683             SOC_IF_ERROR_RETURN(
    684                 _soc_alpm_aux_op(u, DELETE_PROPAGATE, &aux_entry, TRUE, &hit,
    685                                  &tcam_index, &bucket_index, aux_flags));
    686     }
    687     return SOC_E_NONE;
    688 }
    689 
    690 
    691 
    692 /* create shadow entry copy of primary tcam entry at index */
    693 static int
    694 _soc_alpm_128_tcam_shadow_ent_init(int u, int s_index, int index, void *entry, 
    695                                    defip_aux_table_entry_t *shadow, int bpm_len)
    696 {
    697     uint32 tmp, db_type, ent_type, urpf = 0;
    698     soc_mem_t mem = L3_DEFIP_PAIR_128m;
    699     soc_mem_t s_mem = L3_DEFIP_AUX_TABLEm;
    700     int rv = SOC_E_NONE, pfx, vrf_id, vrf;
    701     void *s1, *s2;
    702 
    703     s1 = (void *) shadow;
    704     s2 = (void *) (shadow + 1);
    705 
    706     s_index = soc_alpm_physical_idx(u, L3_DEFIP_PAIR_128m, s_index, 1);
    707 
    708     SOC_IF_ERROR_RETURN(soc_mem_read(u, s_mem, MEM_BLOCK_ANY, 
    709                         SOC_ALPM_128_ADDR_LWR(u, s_index), shadow));
    710     SOC_IF_ERROR_RETURN(soc_mem_read(u, s_mem, MEM_BLOCK_ANY, 
    711                         SOC_ALPM_128_ADDR_UPR(u, s_index), shadow + 1));
    712 
    713     if (bpm_len == INVALID_BPM_LEN) {
    714         /* Clean dirty data */
    715         if (soc_mem_field32_get(u, s_mem, s1, VALID0f) == 0) {
    716             soc_mem_field32_set(u, s_mem, s1, BPM_LENGTH0f, 0);
    717         }
    718 
    719         if (soc_mem_field32_get(u, s_mem, s1, VALID1f) == 0) {
    720             soc_mem_field32_set(u, s_mem, s1, BPM_LENGTH1f, 0);
    721         }
    722 
    723         if (soc_mem_field32_get(u, s_mem, s2, VALID0f) == 0) {
    724             soc_mem_field32_set(u, s_mem, s2, BPM_LENGTH0f, 0);
    725         }
    726 
    727         if (soc_mem_field32_get(u, s_mem, s2, VALID1f) == 0) {
    728             soc_mem_field32_set(u, s_mem, s2, BPM_LENGTH1f, 0);
    729         }
    730     } else {
    731         soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, s1, BPM_LENGTH0f, bpm_len);
    732         soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, s1, BPM_LENGTH1f, bpm_len);
    733         soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, s2, BPM_LENGTH0f, bpm_len);
    734         soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, s2, BPM_LENGTH1f, bpm_len);
    735     }
    736 
    737     tmp = soc_mem_field32_get(u, mem, entry, VRF_ID_0_LWRf);
    738     soc_mem_field32_set(u, s_mem, s1, VRF0f, tmp);
    739     tmp = soc_mem_field32_get(u, mem, entry, VRF_ID_1_LWRf);
    740     soc_mem_field32_set(u, s_mem, s1, VRF1f, tmp);
    741 
    742     tmp = soc_mem_field32_get(u, mem, entry, VRF_ID_0_UPRf);
    743     soc_mem_field32_set(u, s_mem, s2, VRF0f, tmp);
    744     tmp = soc_mem_field32_get(u, mem, entry, VRF_ID_1_UPRf);
    745     soc_mem_field32_set(u, s_mem, s2, VRF1f, tmp);
    746 
    747     tmp = soc_mem_field32_get(u, mem, entry, MODE0_LWRf);
    748     soc_mem_field32_set(u, s_mem, s1, MODE0f, tmp);
    749     tmp = soc_mem_field32_get(u, mem, entry, MODE1_LWRf);
    750     soc_mem_field32_set(u, s_mem, s1, MODE1f, tmp);
    751 
    752     tmp = soc_mem_field32_get(u, mem, entry, MODE0_UPRf);
    753     soc_mem_field32_set(u, s_mem, s2, MODE0f, tmp);
    754     tmp = soc_mem_field32_get(u, mem, entry, MODE1_UPRf);
    755     soc_mem_field32_set(u, s_mem, s2, MODE1f, tmp);
    756 
    757     /* for now simply copy all fields. Let caller decide which half to use */
    758     tmp = soc_mem_field32_get(u, mem, entry, VALID0_LWRf);
    759     soc_mem_field32_set(u, s_mem, s1, VALID0f, tmp);
    760     tmp = soc_mem_field32_get(u, mem, entry, VALID1_LWRf);
    761     soc_mem_field32_set(u, s_mem, s1, VALID1f, tmp);
    762 
    763     tmp = soc_mem_field32_get(u, mem, entry, VALID0_UPRf);
    764     soc_mem_field32_set(u, s_mem, s2, VALID0f, tmp);
    765     tmp = soc_mem_field32_get(u, mem, entry, VALID1_UPRf);
    766     soc_mem_field32_set(u, s_mem, s2, VALID1f, tmp);
    767 
    768     
    769     /* IP_LENGTH */
    770     rv = _soc_alpm_128_ip6_mask_len_get(u, entry, &pfx);
    771     SOC_IF_ERROR_RETURN(rv);
    772 
    773     soc_mem_field32_set(u, s_mem, s1, IP_LENGTH0f, pfx);
    774     soc_mem_field32_set(u, s_mem, s1, IP_LENGTH1f, pfx);
    775     soc_mem_field32_set(u, s_mem, s2, IP_LENGTH0f, pfx);
    776     soc_mem_field32_set(u, s_mem, s2, IP_LENGTH1f, pfx);
    777         
    778     /* IP_ADDR */
    779     tmp = soc_mem_field32_get(u, mem, entry, IP_ADDR0_LWRf);
    780     soc_mem_field32_set(u, s_mem, s1, IP_ADDR0f, tmp);
    781     tmp = soc_mem_field32_get(u, mem, entry, IP_ADDR1_LWRf);
    782     soc_mem_field32_set(u, s_mem, s1, IP_ADDR1f, tmp);
    783 
    784     tmp = soc_mem_field32_get(u, mem, entry, IP_ADDR0_UPRf);
    785     soc_mem_field32_set(u, s_mem, s2, IP_ADDR0f, tmp);
    786     tmp = soc_mem_field32_get(u, mem, entry, IP_ADDR1_UPRf);
    787     soc_mem_field32_set(u, s_mem, s2, IP_ADDR1f, tmp);
    788 
    789 
    790     /* DB_TYPE */
    791     /* for v4 need to be careful */
    792     rv = soc_alpm_128_lpm_vrf_get(u, entry, &vrf_id, &vrf);
    793     SOC_IF_ERROR_RETURN(rv);
    794 
    795     if (SOC_URPF_STATUS_GET(u)) {
    796         if (index >= (soc_mem_index_count(u, L3_DEFIP_PAIR_128m) >> 1)) {
    797             urpf = 1;
    798         }
    799     }
    800 
    801     soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
    802 
    803     if (vrf_id == SOC_L3_VRF_OVERRIDE ||
    804         (soc_feature(u, soc_feature_ipmc_defip) &&
    805          soc_mem_field32_get(u, mem, entry, MULTICAST_ROUTEf))) {
    806         soc_mem_field32_set(u, s_mem, s1, VALID0f, 0);
    807         soc_mem_field32_set(u, s_mem, s1, VALID1f, 0);
    808         soc_mem_field32_set(u, s_mem, s2, VALID0f, 0);
    809         soc_mem_field32_set(u, s_mem, s2, VALID1f, 0);
    810         db_type = 0; /* don't care */
    811     } else {
    812         if (urpf) {
    813             db_type ++;
    814         }
    815     }
    816 
    817     soc_mem_field32_set(u, s_mem, s1, DB_TYPE0f, db_type);
    818     soc_mem_field32_set(u, s_mem, s1, DB_TYPE1f, db_type);
    819     soc_mem_field32_set(u, s_mem, s2, DB_TYPE0f, db_type);
    820     soc_mem_field32_set(u, s_mem, s2, DB_TYPE1f, db_type);
    821 
    822     /* ENTRY_TYPE */
    823     tmp = soc_mem_field32_get(u, mem, entry, ENTRY_TYPE0_LWRf);
    824     soc_mem_field32_set(u, s_mem, s1, ENTRY_TYPE0f, tmp | ent_type);
    825     tmp = soc_mem_field32_get(u, mem, entry, ENTRY_TYPE1_LWRf);
    826     soc_mem_field32_set(u, s_mem, s1, ENTRY_TYPE1f, tmp | ent_type);
    827 
    828     tmp = soc_mem_field32_get(u, mem, entry, ENTRY_TYPE0_UPRf);
    829     soc_mem_field32_set(u, s_mem, s2, ENTRY_TYPE0f, tmp | ent_type);
    830     tmp = soc_mem_field32_get(u, mem, entry, ENTRY_TYPE1_UPRf);
    831     soc_mem_field32_set(u, s_mem, s2, ENTRY_TYPE1f, tmp | ent_type);
    832 
    833 
    834     /* modify bucket index if urpf is enabled */
    835     if (urpf) {
    836         tmp = soc_mem_field32_get(u, mem, entry, ALG_BKT_PTRf);
    837         /* modify only valid bucket pointer */
    838         if (tmp && tmp < SOC_ALPM_BUCKET_COUNT(u)) {
    839             tmp += SOC_ALPM_BUCKET_COUNT(u);
    840             soc_mem_field32_set(u, mem, entry, ALG_BKT_PTRf, tmp);
    841         }
    842     }
    843 
    844     /* BPM_LENGTH */
    845     /* don't modify, preserve existing values */
    846     return SOC_E_NONE;
    847 }
    848 
    849 #define ALPM_INVALID_INDEX      -1
    850 #define WRITE_PIVOT_WITH_SRC_INDEX                0
    851 #define WRITE_PIVOT_WITH_SRC_INDEX_CONVERT        1
    852 #define WRITE_PIVOT_WITH_URPF_PARAMS              2
    853 #define WRITE_PIVOT_WITHOUT_INSERT_HASH           0x80000000
    854 
    855 
    856 static int
    857 _soc_alpm_128_write_pivot_aux(int u, int s_index, int index, void *entry, int bpm_len)
    858 {
    859     defip_aux_table_entry_t shadow[2];
    860 
    861     SOC_IF_ERROR_RETURN(_soc_alpm_128_tcam_shadow_ent_init(u,
    862                     s_index, index, entry, &shadow[0], bpm_len));
    863     SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_PAIR_128m(u, MEM_BLOCK_ANY, 
    864                          index, entry));
    865 
    866     index = soc_alpm_physical_idx(u, L3_DEFIP_PAIR_128m, index, 1);
    867     SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ANY, 
    868                          SOC_ALPM_128_ADDR_LWR(u, index), shadow));
    869     SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ANY, 
    870                          SOC_ALPM_128_ADDR_UPR(u, index), shadow+1));
    871     return SOC_E_NONE;
    872 }
    873 
    874 
    875 #ifdef ALPM_USE_RAW_VIEW
    876 
    877 static void
    878 _soc_alpm_128_raw_bucket_prepare_undo(int u,
    879                                       alpm_mem_prefix_array_t **alloc_pfx_array,
    880                                       void **alloc_raw_bkt,
    881                                       int  **alloc_new_index)
    882 {
    883     if (*alloc_raw_bkt) {
    884         sal_free(*alloc_raw_bkt);
    885     }
    886     if (*alloc_pfx_array) {
    887         sal_free(*alloc_pfx_array);
    888         *alloc_pfx_array = NULL;
    889     }
    890     if (*alloc_new_index) {
    891         sal_free(*alloc_new_index);
    892         *alloc_new_index = NULL;
    893     }
    894 }
    895 
    896 static int
    897 _soc_alpm_128_raw_bucket_prepare(int u, soc_mem_t mem,
    898                                  trie_t *bkt_trie,
    899                                  int bucket_index_from,
    900                                  int bucket_index_to,
    901                                  uint32 bank_disable,
    902                                  void *alpm_data,
    903                                  void *alpm_sip_data,
    904                                  alpm_mem_prefix_array_t **alloc_pfx_array,
    905                                  void **alloc_raw_bkt,
    906                                  int  **alloc_new_index,
    907                                  int  *new_index_pos,
    908                                  int  to_exist)
    909 {
    910     int     i, j = 0, rv = SOC_E_NONE;
    911     int raw_size, raw_bkt_size, alloc_size;
    912     void *raw_ent;
    913     void *raw_bkt[RAW_BKT_NUM] = {NULL};
    914     int  raw_id = 0;
    915     int  ent_id = 0;
    916     int key_index;
    917     /* allocation pointers all set to NULL */
    918     alpm_mem_prefix_array_t *pfx_array = NULL;
    919     int  *index_array = NULL;
    920     int   v6 = L3_DEFIP_MODE_128;
    921     /* Search Result buffers */
    922     defip_alpm_ipv6_128_entry_t alpmv6_entry, alpmv6_sip_entry;
    923     defip_alpm_ipv6_128_entry_t alpmv6_entry2;
    924     void *bufp = NULL, *sip_bufp = NULL;
    925     void *bufp2 = NULL;
    926     int max_count = 0;
    927 
    928     /* Assign entry buf based on table being used */
    929     SOC_ALPM_ENTRY_BUF_128(v6, mem, bufp, 0, alpmv6_entry);
    930     SOC_ALPM_ENTRY_BUF_128(v6, mem, sip_bufp, 0, alpmv6_sip_entry);
    931     SOC_ALPM_ENTRY_BUF_128(v6, mem, bufp2, 0, alpmv6_entry2);
    932 
    933     *alloc_raw_bkt   = NULL;
    934     *alloc_new_index = NULL;
    935     *alloc_pfx_array = NULL;
    936 
    937     /* Alloc prefix array */
    938     alloc_size = sizeof(alpm_mem_prefix_array_t);
    939     pfx_array = sal_alloc(alloc_size, "prefix array");
    940     if (pfx_array == NULL) {
    941         goto cleanup;
    942     }
    943 
    944     /* Fill prefix array */
    945     sal_memset(pfx_array, 0, alloc_size);
    946     rv = trie_traverse(bkt_trie, alpm_mem_prefix_array_cb,
    947                        pfx_array, _TRIE_INORDER_TRAVERSE);
    948     if (SOC_FAILURE(rv)) {
    949         goto cleanup;
    950     }
    951 
    952     /* Alloc index array */
    953     alloc_size = sizeof(int) * pfx_array->count;
    954     index_array = sal_alloc(alloc_size, "index_array");
    955     if (index_array == NULL) {
    956         goto cleanup;
    957     }
    958     sal_memset(index_array, -1, alloc_size);
    959 
    960     raw_size = sizeof(defip_alpm_raw_entry_t);
    961     raw_bkt_size = raw_size * ALPM_RAW_BKT_COUNT_DW;
    962     raw_bkt[0] = sal_alloc(RAW_BKT_NUM * raw_bkt_size, "Raw memory buffer");
    963     if (raw_bkt[0] == NULL) {
    964         rv = SOC_E_MEMORY;
    965         goto cleanup;
    966     }
    967     sal_memset(raw_bkt[0], 0, RAW_BKT_NUM * raw_bkt_size);
    968     for (i = 1; i < RAW_BKT_NUM; i++) {
    969         raw_bkt[i] = (uint8 *)raw_bkt[0] + raw_bkt_size * i;
    970     }
    971 
    972     rv = _soc_alpm_raw_bucket_read(u, mem, bucket_index_from,
    973                                    raw_bkt[RAW_OLD_BKT_DIP],
    974                                    raw_bkt[RAW_OLD_BKT_SIP]);
    975     if (SOC_FAILURE(rv)) {
    976         goto cleanup;
    977     }
    978     sal_memcpy(raw_bkt[RAW_RB_BKT_DIP], raw_bkt[RAW_OLD_BKT_DIP], raw_bkt_size);
    979     sal_memcpy(raw_bkt[RAW_RB_BKT_SIP], raw_bkt[RAW_OLD_BKT_SIP], raw_bkt_size);
    980 
    981     if (to_exist) {
    982         rv = _soc_alpm_raw_bucket_read(u, mem, bucket_index_to,
    983                                        raw_bkt[RAW_NEW_BKT_DIP],
    984                                        raw_bkt[RAW_NEW_BKT_SIP]);
    985         if (SOC_FAILURE(rv)) {
    986             goto cleanup;
    987         }
    988         max_count = _soc_alpm_bkt_entry_cnt(u, mem);
    989     }
    990 
    991     for (i = 0; i < pfx_array->count; i++) {
    992         payload_t *pfx = pfx_array->prefix[i];
    993         if (pfx->index > 0) {
    994             /* if this is the new prefix it does not exist in the
    995              * bucket, no point reading */
    996             SOC_ALPM_RAW_INDEX_DECODE(u, v6, pfx->index, raw_id, ent_id);
    997             raw_ent = (uint8 *)raw_bkt[RAW_OLD_BKT_DIP] + raw_id * raw_size;
    998             _soc_alpm_raw_mem_read(u, mem, raw_ent, ent_id, bufp);
    999             _soc_alpm_raw_mem_write(u, mem, raw_ent, pfx->index,
   1000                                     ent_id, soc_mem_entry_null(u, mem));
   1001 
   1002             if (SOC_URPF_STATUS_GET(u)) {
   1003                 raw_ent = (uint8 *)raw_bkt[RAW_OLD_BKT_SIP] + raw_id * raw_size;
   1004                 _soc_alpm_raw_mem_read(u, mem, raw_ent, ent_id, sip_bufp);
   1005                 _soc_alpm_raw_mem_write(u, mem, raw_ent,
   1006                                         _soc_alpm_rpf_entry(u, pfx->index),
   1007                                         ent_id, soc_mem_entry_null(u, mem));
   1008             }
   1009 
   1010             if (to_exist) {
   1011                 for (;j < max_count; j++) {
   1012                     rv = _soc_alpm_mem_index(u, mem, bucket_index_to, j,
   1013                                              bank_disable, &key_index);
   1014                     if (SOC_FAILURE(rv)) {
   1015                         goto cleanup;
   1016                     }
   1017                     SOC_ALPM_RAW_INDEX_DECODE(u, v6, key_index, raw_id, ent_id);
   1018                     raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_DIP] + raw_id * raw_size;
   1019                     _soc_alpm_raw_mem_read(u, mem, raw_ent, ent_id, bufp2);
   1020                     if (soc_mem_field32_get(u, mem, bufp2, VALIDf) == 0) {
   1021                         break;
   1022                     }
   1023                 }
   1024                 if (j == max_count) {
   1025                     rv = SOC_E_INTERNAL;
   1026                     goto cleanup;
   1027                 }
   1028                 _soc_alpm_raw_mem_write(u, mem, raw_ent,
   1029                                         key_index, ent_id, bufp);
   1030                 if (SOC_URPF_STATUS_GET(u)) {
   1031                     raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_SIP] + raw_id * raw_size;
   1032                     _soc_alpm_raw_mem_write(u, mem, raw_ent,
   1033                                             _soc_alpm_rpf_entry(u, key_index),
   1034                                             ent_id, sip_bufp);
   1035                 }
   1036             } else {
   1037                 rv = _soc_alpm_mem_index(u, mem, bucket_index_to, i,
   1038                                          bank_disable, &key_index);
   1039                 if (SOC_FAILURE(rv)) {
   1040                     goto cleanup;
   1041                 }
   1042                 SOC_ALPM_RAW_INDEX_DECODE(u, v6, key_index, raw_id, ent_id);
   1043                 raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_DIP] + raw_id * raw_size;
   1044                 _soc_alpm_raw_mem_write(u, mem, raw_ent,
   1045                                         key_index, ent_id, bufp);
   1046                 if (SOC_URPF_STATUS_GET(u)) {
   1047                     raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_SIP] + raw_id * raw_size;
   1048                     _soc_alpm_raw_mem_write(u, mem, raw_ent,
   1049                                             _soc_alpm_rpf_entry(u, key_index),
   1050                                             ent_id, sip_bufp);
   1051                 }
   1052             }
   1053         } else {
   1054             rv = _soc_alpm_mem_index(u, mem, bucket_index_to, i,
   1055                                      bank_disable, &key_index);
   1056             if (SOC_FAILURE(rv)) {
   1057                 goto cleanup;
   1058             }
   1059 
   1060             if (!new_index_pos) {
   1061                 rv = SOC_E_PARAM;
   1062                 goto cleanup;
   1063             }
   1064             *new_index_pos = i;
   1065 
   1066             /* New entry, need to take care of Parity for raw view */
   1067             _soc_alpm_raw_parity_set(u, mem, alpm_data);
   1068             SOC_ALPM_RAW_INDEX_DECODE(u, v6, key_index, raw_id, ent_id);
   1069             raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_DIP] + raw_id * raw_size;
   1070             _soc_alpm_raw_mem_write(u, mem, raw_ent,
   1071                                     key_index, ent_id, alpm_data);
   1072             if (SOC_URPF_STATUS_GET(u)) {
   1073                 _soc_alpm_raw_parity_set(u, mem, alpm_sip_data);
   1074                 raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_SIP] + raw_id * raw_size;
   1075                 _soc_alpm_raw_mem_write(u, mem, raw_ent,
   1076                                         _soc_alpm_rpf_entry(u, key_index),
   1077                                         ent_id, alpm_sip_data);
   1078             }
   1079         }
   1080         index_array[i] = key_index;
   1081     }
   1082 
   1083     for (i = 0; i < RAW_BKT_NUM; i++) {
   1084         alloc_raw_bkt[i] = raw_bkt[i];
   1085     }
   1086     *alloc_new_index = index_array;
   1087     *alloc_pfx_array = pfx_array;
   1088 
   1089     return rv;
   1090 
   1091 cleanup:
   1092     if (raw_bkt[0]) {
   1093         sal_free(raw_bkt[0]);
   1094     }
   1095     if (index_array) {
   1096         sal_free(index_array);
   1097     }
   1098     if (pfx_array) {
   1099         sal_free(pfx_array);
   1100     }
   1101     return rv;
   1102 }
   1103 
   1104 
   1105 static void
   1106 _soc_alpm_128_raw_bucket_copy_undo(int u, soc_mem_t mem,
   1107                                    int bucket_index,
   1108                                    uint32 bank_disable,
   1109                                    void *new_raw_bufp, void *new_raw_sip_bufp,
   1110                                    int *new_index, int index_count)
   1111 {
   1112     int  i;
   1113     int  raw_size = sizeof(defip_alpm_raw_entry_t);
   1114     int  raw_id = 0;
   1115     int  ent_id = 0;
   1116     void *raw_ent;
   1117     int  v6 = L3_DEFIP_MODE_128;
   1118 
   1119     /* Restore the new bucket to null */
   1120     for (i = 0; i < index_count; i++) {
   1121         if (new_index[i] < 0) {
   1122             continue;
   1123         }
   1124 
   1125         SOC_ALPM_RAW_INDEX_DECODE(u, v6, new_index[i], raw_id, ent_id);
   1126         raw_ent = (uint8 *)new_raw_bufp + raw_id * raw_size;
   1127         _soc_alpm_raw_mem_write(u, mem, raw_ent,
   1128                                 new_index[i], ent_id, soc_mem_entry_null(u, mem));
   1129         if (SOC_URPF_STATUS_GET(u)) {
   1130             raw_ent = (uint8 *)new_raw_sip_bufp + raw_id * raw_size;
   1131             _soc_alpm_raw_mem_write(u, mem, raw_ent,
   1132                                     _soc_alpm_rpf_entry(u, new_index[i]),
   1133                                     ent_id, soc_mem_entry_null(u, mem));
   1134         }
   1135     }
   1136 
   1137     (void)_soc_alpm_raw_bucket_write(u, mem, bucket_index, bank_disable,
   1138                                      new_raw_bufp, new_raw_sip_bufp, MAX_RAW_COUNT);
   1139 }
   1140 
   1141 /* Populate entries in pfx array to logical bucket */
   1142 static int
   1143 _soc_alpm_128_raw_bucket_copy(int u, soc_mem_t mem,
   1144                               int       bucket_index,
   1145                               uint32    bank_disable,
   1146                               void      *new_raw_bufp,
   1147                               void      *new_raw_sip_bufp,
   1148                               int       *new_index, /* for undo */
   1149                               int       index_count)
   1150 {
   1151     int                             rv;
   1152     rv = _soc_alpm_raw_bucket_write(u, mem, bucket_index, bank_disable,
   1153                                     new_raw_bufp, new_raw_sip_bufp, MAX_RAW_COUNT);
   1154 
   1155     if (SOC_FAILURE(rv)) {
   1156         /* Delete entries in new bucket */
   1157         _soc_alpm_128_raw_bucket_copy_undo(u, mem, bucket_index, bank_disable,
   1158                                            new_raw_bufp, new_raw_sip_bufp,
   1159                                            new_index, index_count);
   1160     }
   1161     return rv;
   1162 }
   1163 
   1164 
   1165 
   1166 static INLINE void
   1167 _soc_alpm_128_raw_bucket_inval_undo(int u, soc_mem_t mem, int bucket_index,
   1168                                     uint32 bank_disable,
   1169                                     void *old_raw_bufp, void *old_raw_sip_bufp)
   1170 {
   1171 
   1172     (void)_soc_alpm_raw_bucket_write(u, mem, bucket_index,
   1173                                      bank_disable, (void *)old_raw_bufp,
   1174                                      (void *)old_raw_sip_bufp, MAX_RAW_COUNT);
   1175     return;
   1176 }
   1177 static int
   1178 _soc_alpm_128_raw_bucket_inval(int u, soc_mem_t mem, int bucket_index,
   1179                            uint32 bank_disable,
   1180                            void *old_bufp,
   1181                            void *old_sip_bufp,
   1182                            void *rb_bufp, /* for undo */
   1183                            void *rb_sip_bufp /* for undo */
   1184                            )
   1185 {
   1186     int rv = SOC_E_NONE;
   1187 
   1188     /* Invalidation process
   1189      * 1. Erase old copied entries
   1190      * 2. Re-validate those entries if invalidation fails
   1191      */
   1192 
   1193     /* Update old bucket with split entries invalidated */
   1194     rv =  _soc_alpm_raw_bucket_write(u, mem, bucket_index,
   1195                                      bank_disable, old_bufp,
   1196                                      old_sip_bufp, MAX_RAW_COUNT);
   1197     /* re-validate old bucket entries */
   1198     if (SOC_FAILURE(rv)) {
   1199         _soc_alpm_128_raw_bucket_inval_undo(u, mem, bucket_index,
   1200                                             bank_disable, rb_bufp,
   1201                                             rb_sip_bufp);
   1202     }
   1203 
   1204     return rv;
   1205 }
   1206 
   1207 #else
   1208 
   1209 static void
   1210 _soc_alpm_128_bucket_prepare_undo(int u,
   1211                                   alpm_mem_prefix_array_t **alloc_pfx_array,
   1212                                   void **alloc_bufp,
   1213                                   void **alloc_sip_bufp,
   1214                                   int  **alloc_new_index)
   1215 {
   1216     if (*alloc_pfx_array) {
   1217         sal_free(*alloc_pfx_array);
   1218         *alloc_pfx_array = NULL;
   1219     }
   1220     if (*alloc_bufp) {
   1221         sal_free(*alloc_bufp);
   1222         *alloc_bufp = NULL;
   1223     }
   1224     if (*alloc_sip_bufp) {
   1225         sal_free(*alloc_sip_bufp);
   1226         *alloc_sip_bufp = NULL;
   1227     }
   1228     if (*alloc_new_index) {
   1229         sal_free(*alloc_new_index);
   1230         *alloc_new_index = NULL;
   1231     }
   1232 }
   1233 
   1234 
   1235 static int
   1236 _soc_alpm_128_bucket_prepare(int u, soc_mem_t mem,
   1237                              trie_t *bkt_trie,
   1238                              alpm_mem_prefix_array_t **alloc_pfx_array,
   1239                              void **alloc_bufp,
   1240                              void **alloc_sip_bufp,
   1241                              int  **alloc_new_index)
   1242 {
   1243     int i, rv = SOC_E_NONE;
   1244     int entry_size;
   1245     int alloc_size;
   1246     /* allocation pointers all set to NULL */
   1247     void *bufp = NULL, *sip_bufp = NULL;
   1248     int  *index_array = NULL;
   1249     alpm_mem_prefix_array_t *pfx_array = NULL;
   1250 
   1251     *alloc_bufp      = NULL;
   1252     *alloc_sip_bufp  = NULL;
   1253     *alloc_new_index = NULL;
   1254     *alloc_pfx_array = NULL;
   1255 
   1256     /* Alloc prefix array */
   1257     alloc_size = sizeof(alpm_mem_prefix_array_t);
   1258     pfx_array = sal_alloc(alloc_size, "prefix array");
   1259     if (pfx_array == NULL) {
   1260         goto cleanup;
   1261     }
   1262 
   1263     /* Fill prefix array */
   1264     sal_memset(pfx_array, 0, alloc_size);
   1265     rv = trie_traverse(bkt_trie, alpm_mem_prefix_array_cb,
   1266                        pfx_array, _TRIE_INORDER_TRAVERSE);
   1267     if (SOC_FAILURE(rv)) {
   1268         goto cleanup;
   1269     }
   1270 
   1271     /* Alloc index array */
   1272     alloc_size = sizeof(int) * pfx_array->count;
   1273     index_array = sal_alloc(alloc_size, "index_array");
   1274     if (index_array == NULL) {
   1275         goto cleanup;
   1276     }
   1277     sal_memset(index_array, -1, alloc_size);
   1278 
   1279     /* Alloc bufp & sip_bufp */
   1280     entry_size = sizeof(defip_alpm_ipv6_128_entry_t);
   1281 
   1282     alloc_size = entry_size * pfx_array->count;
   1283     bufp = sal_alloc(alloc_size, "alloc_bufp");
   1284     if (bufp == NULL) {
   1285         goto cleanup;
   1286     }
   1287     if (SOC_URPF_STATUS_GET(u)) {
   1288         sip_bufp  = sal_alloc(alloc_size, "alloc_sip_bufp");
   1289         if (sip_bufp == NULL) {
   1290             goto cleanup;
   1291         }
   1292     }
   1293 
   1294     /* Fill bufp & sip bufp */
   1295     for (i = 0; i < pfx_array->count; i++) {
   1296         payload_t *pfx = pfx_array->prefix[i];
   1297 
   1298         if (pfx->index > 0) { /* old pfx */
   1299             rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, pfx->index,
   1300                                     (uint8 *)bufp + i * entry_size);
   1301 
   1302             if (SOC_FAILURE(rv)) {
   1303                 break;
   1304             }
   1305 
   1306             if (SOC_URPF_STATUS_GET(u)) {
   1307                 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY,
   1308                         _soc_alpm_rpf_entry(u, pfx->index),
   1309                         (uint8 *)sip_bufp + i * entry_size);
   1310                 if (SOC_FAILURE(rv)) {
   1311                     break;
   1312                 }
   1313             }
   1314         }
   1315     }
   1316     if (SOC_FAILURE(rv)) {
   1317         goto cleanup;
   1318     }
   1319 
   1320     *alloc_bufp      = bufp;
   1321     *alloc_sip_bufp  = sip_bufp;
   1322     *alloc_new_index = index_array;
   1323     *alloc_pfx_array = pfx_array;
   1324 
   1325     return rv;
   1326 
   1327 cleanup:
   1328     if (bufp) {
   1329         sal_free(bufp);
   1330     }
   1331     if (sip_bufp) {
   1332         sal_free(sip_bufp);
   1333     }
   1334     if (index_array) {
   1335         sal_free(index_array);
   1336     }
   1337     if (pfx_array) {
   1338         sal_free(pfx_array);
   1339     }
   1340     return rv;
   1341 }
   1342 
   1343 
   1344 static void
   1345 _soc_alpm_128_bucket_copy_undo(int u, soc_mem_t mem, int count, int *new_index)
   1346 {
   1347     int i;
   1348 
   1349     for (i = 0; i < count; i++) {
   1350         if (new_index[i] < 0) {
   1351             continue;
   1352         }
   1353         soc_mem_write(u, mem, MEM_BLOCK_ANY, new_index[i],
   1354                       soc_mem_entry_null(u, mem));
   1355         if (SOC_URPF_STATUS_GET(u)) {
   1356             soc_mem_write(u, mem, MEM_BLOCK_ANY,
   1357                           _soc_alpm_rpf_entry(u, new_index[i]),
   1358                           soc_mem_entry_null(u, mem));
   1359         }
   1360     }
   1361 }
   1362 
   1363 /* Populate entries in pfx array to logical bucket */
   1364 static int
   1365 _soc_alpm_128_bucket_copy(int u, soc_mem_t mem, int vrf,
   1366                           alpm_mem_prefix_array_t *pfx_array,
   1367                           int       bucket_index,
   1368                           void      *old_bufp,
   1369                           void      *old_sip_bufp,
   1370                           void      *new_bufp,
   1371                           void      *new_sip_bufp,
   1372                           int       *new_index,
   1373                           int       *new_index_pos)
   1374 {
   1375     int                             rv;
   1376     void                            *bufp, *sip_bufp;
   1377     int                             entsz, key_index;
   1378     uint32                          bank_disable = 0;
   1379     int                             v6, i;
   1380     uint32                          e[SOC_MAX_MEM_FIELD_WORDS];
   1381     bank_disable = soc_alpm_bank_dis(u, vrf);
   1382 
   1383     v6 = L3_DEFIP_MODE_128;
   1384 
   1385     entsz = sizeof(defip_alpm_ipv6_128_entry_t);
   1386 
   1387     for (i = 0; i < pfx_array->count; i++) {
   1388         if (pfx_array->prefix[i]->index > 0) { /* old prefix */
   1389 
   1390             bufp = (uint8 *)old_bufp + i * entsz;
   1391             if (SOC_URPF_STATUS_GET(u)) {
   1392                 sip_bufp = (uint8 *)old_sip_bufp + i * entsz;
   1393             }
   1394 
   1395             /* entry shouldn't exist, insert the entry into the RAM */
   1396             rv = _soc_alpm_insert_in_bkt(u, mem, bucket_index,
   1397                                          bank_disable, bufp, sip_bufp, e,
   1398                                          &key_index, v6);
   1399         } else { /* for split case only */
   1400             if (!new_bufp || !new_index_pos) {
   1401                 rv = SOC_E_PARAM;
   1402                 goto _rollback;
   1403             }
   1404             *new_index_pos = i;
   1405             rv = _soc_alpm_insert_in_bkt(u, mem, bucket_index,
   1406                                          bank_disable, new_bufp, new_sip_bufp, e,
   1407                                          &key_index, v6);
   1408         }
   1409         if (SOC_FAILURE(rv)) {
   1410             LOG_ERROR(BSL_LS_SOC_ALPM,
   1411                       (BSL_META_U(u,
   1412                                   "Failed to insert prefix "
   1413                                   "0x%08x 0x%08x 0x%08x 0x%08x to bucket %d\n"),
   1414                        pfx_array->prefix[i]->key[1],
   1415                        pfx_array->prefix[i]->key[2],
   1416                        pfx_array->prefix[i]->key[3],
   1417                        pfx_array->prefix[i]->key[4], bucket_index));
   1418 
   1419             goto _rollback;
   1420         }
   1421         new_index[i] = key_index;
   1422     }
   1423 
   1424 _rollback:
   1425     if (SOC_FAILURE(rv)) {
   1426         /* Delete entries in new bucket */
   1427         _soc_alpm_128_bucket_copy_undo(u, mem, pfx_array->count, new_index);
   1428     }
   1429 
   1430     return rv;
   1431 }
   1432 
   1433 
   1434 
   1435 
   1436 
   1437 static void
   1438 _soc_alpm_128_bucket_inval_undo(int u, soc_mem_t mem,
   1439                                 alpm_mem_prefix_array_t *pfx_array,
   1440                                 void *old_bufp, void *old_sip_bufp)
   1441 {
   1442     int i;
   1443     int entry_size = sizeof(defip_alpm_ipv6_128_entry_t);
   1444 
   1445     for (i = 0; i < pfx_array->count; i++) {
   1446         payload_t *prefix = pfx_array->prefix[i];
   1447 
   1448         if (prefix->index > 0) {
   1449             soc_mem_write(u, mem, MEM_BLOCK_ALL, prefix->index,
   1450                           (uint8 *)old_bufp + i * entry_size);
   1451 
   1452             if (SOC_URPF_STATUS_GET(u)) {
   1453                 /* UPRF entry */
   1454                 soc_mem_write(u, mem, MEM_BLOCK_ALL,
   1455                               _soc_alpm_rpf_entry(u, prefix->index),
   1456                               (uint8 *)old_sip_bufp + i * entry_size);
   1457             }
   1458         }
   1459     }
   1460     return;
   1461 }
   1462 static int
   1463 _soc_alpm_128_bucket_inval(int u, soc_mem_t mem,
   1464                            alpm_mem_prefix_array_t *pfx_array,
   1465                            void *old_bufp, void *old_sip_bufp)
   1466 {
   1467     int i, rv = SOC_E_NONE;
   1468 
   1469     /* Invalidation process
   1470      * 1. Erase old copied entries
   1471      * 2. Re-validate those entries if invalidation fails
   1472      */
   1473 
   1474     for (i = 0; i < pfx_array->count; i ++) {
   1475         payload_t *prefix = pfx_array->prefix[i];
   1476 
   1477         if (prefix->index >= 0) {
   1478             /* zero out old entries now that split is done */
   1479             rv = soc_mem_write(u, mem, MEM_BLOCK_ALL, prefix->index,
   1480                                soc_mem_entry_null(u, mem));
   1481             if (SOC_FAILURE(rv)) {
   1482                 break;
   1483             }
   1484             if (SOC_URPF_STATUS_GET(u)) {
   1485                 rv = soc_mem_write(u, mem, MEM_BLOCK_ANY,
   1486                                    _soc_alpm_rpf_entry(u, prefix->index),
   1487                                    soc_mem_entry_null(u, mem));
   1488                 if (SOC_FAILURE(rv)) {
   1489                     break;
   1490                 }
   1491             }
   1492         }
   1493     }
   1494     /* re-validate old bucket entries */
   1495     if (SOC_FAILURE(rv)) {
   1496         _soc_alpm_128_bucket_inval_undo(u, mem, pfx_array, old_bufp, old_sip_bufp);
   1497     }
   1498 
   1499     return rv;
   1500 }
   1501 
   1502 
   1503 #endif /* ALPM_USE_RAW_VIEW */
   1504 
   1505 
   1506 
   1507 
   1508 STATIC int
   1509 _soc_alpm_128_split_lpm_init(int             u,
   1510                              int             vrf,
   1511                              int             bucket_index,
   1512                              void            *alpm_data,
   1513                              void            *alpm_sip_data,
   1514                              uint32          *pivot,
   1515                              int             length,
   1516                              defip_pair_128_entry_t  *lpm_entry,
   1517                              uint32          *bpm_len,
   1518                              uint32          *src_discard,
   1519                              uint32          *src_default)
   1520 {
   1521     int                             rv = SOC_E_NONE, v6;
   1522     trie_node_t                     *lpm = NULL;
   1523     payload_t                       *bkt_lpm = NULL;
   1524     trie_t                          *pfx_trie;
   1525     defip_alpm_ipv6_128_entry_t     alpmv6_entry, alpmv6_sip_entry;
   1526     uint32                          tmp_pivot[5] = {0};
   1527 
   1528     v6 = L3_DEFIP_MODE_128;
   1529 
   1530     /* prefix trie */
   1531     pfx_trie = VRF_PREFIX_TRIE_IPV6_128(u, vrf);
   1532 
   1533     /* find longest prefix that covers pivot */
   1534     lpm = NULL;
   1535     rv = trie_find_lpm(pfx_trie, pivot, length, &lpm);
   1536     if (SOC_FAILURE(rv)) {
   1537         LOG_ERROR(BSL_LS_SOC_ALPM,
   1538                   (BSL_META_U(u,
   1539                               "unit %d Unable to find lpm for pivot: "
   1540                               "0x%08x 0x%08x\n 0x%08x 0x%08x 0x%08x length: %d\n"),
   1541                    u, pivot[0], pivot[1], pivot[2], pivot[3], pivot[4],
   1542                    length));
   1543 
   1544         return rv;
   1545     }
   1546     bkt_lpm = ((payload_t *)lpm)->bkt_ptr;
   1547 
   1548     /* Initialize the lpm entry to insert */
   1549     if (bkt_lpm) {
   1550         int             index, vrf_id;
   1551         void            *bufp = NULL, *sip_bufp = NULL;
   1552         soc_mem_t       mem;
   1553 
   1554         /* Get table memory. */
   1555         SOC_ALPM_TABLE_MEM_128(u, v6, mem);
   1556         SOC_ALPM_ENTRY_BUF_128(v6, mem, bufp, 0, alpmv6_entry);
   1557         SOC_ALPM_ENTRY_BUF_128(v6, mem, sip_bufp, 0, alpmv6_sip_entry);
   1558         /* this means this bucket default route is an actual route */
   1559         /* initialize new pivot's associated data with data of lpm match */
   1560         index = bkt_lpm->index;
   1561         if (index == -1) {
   1562             /* this means the new route is the bucket's default */
   1563             if (alpm_data == NULL || alpm_sip_data == NULL) {
   1564                 return SOC_E_PARAM;
   1565             }
   1566             sal_memcpy(bufp, alpm_data, sizeof(defip_alpm_ipv6_128_entry_t));
   1567             if (SOC_URPF_STATUS_GET(u)) {
   1568                 *src_default = soc_mem_field32_get(u, mem, alpm_sip_data,
   1569                                                           DEFAULTROUTEf);
   1570                 *src_discard = soc_mem_field32_get(u, mem, alpm_sip_data,
   1571                                                           SRC_DISCARDf);
   1572             }
   1573         } else {
   1574             rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, index, bufp);
   1575             if (SOC_FAILURE(rv)) {
   1576                 return rv;
   1577             }
   1578             if (SOC_URPF_STATUS_GET(u)) {
   1579                 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY,
   1580                                         _soc_alpm_rpf_entry(u, index),
   1581                                         sip_bufp);
   1582                 *src_default = soc_mem_field32_get(u, mem, sip_bufp,
   1583                                                           DEFAULTROUTEf);
   1584                 *src_discard = soc_mem_field32_get(u, mem, sip_bufp,
   1585                                                           SRC_DISCARDf);
   1586             }
   1587         }
   1588         if (SOC_FAILURE(rv)) {
   1589             return rv;
   1590         }
   1591 
   1592         vrf_id = vrf;
   1593         if (vrf == (SOC_VRF_MAX(u) + 1)) {
   1594             vrf_id = SOC_L3_VRF_GLOBAL;
   1595         }
   1596         rv = _soc_alpm_128_lpm_ent_init(u, bufp, mem, v6, vrf_id, bucket_index,
   1597                                     0, lpm_entry,
   1598                                     VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 1));
   1599         if (SOC_FAILURE(rv)) {
   1600             return rv;
   1601         }
   1602         /* remember the bpm_len of this pivot. Need to put in shadow */
   1603         *bpm_len = bkt_lpm->len;
   1604     } else {
   1605         defip_pair_128_entry_t *lpm_key;
   1606         lpm_key = VRF_TRIE_DEFAULT_ROUTE_IPV6_128(u, vrf);
   1607         sal_memcpy(lpm_entry, lpm_key, sizeof(defip_pair_128_entry_t));
   1608 
   1609         /* the sip ad does not matter here */
   1610         soc_L3_DEFIP_PAIR_128m_field32_set(u, lpm_entry, ALG_BKT_PTRf, bucket_index);
   1611     }
   1612 
   1613     /* Convert is a self-modified op, thus use tmp one */
   1614     sal_memcpy(tmp_pivot, pivot, sizeof(tmp_pivot));
   1615 
   1616     /* Convert from trie format to h/w format */
   1617     ALPM_TRIE_TO_NORMAL_IP_128(tmp_pivot, length, v6);
   1618     (void) _soc_alpm_128_lpm_ent_key_init(u, tmp_pivot, length, vrf, v6,
   1619                           lpm_entry, 0, 0);
   1620 
   1621     return rv;
   1622 }
   1623 
   1624 static int
   1625 _soc_alpm_128_split_pivot_create_undo(int u, int v6, int vrf, uint32 *pivot,
   1626                                       uint32 length, alpm_pivot_t *alpm_pivot,
   1627                                       int clear)
   1628 {
   1629     int                         rv = SOC_E_NONE, pivot_index;
   1630     alpm_bucket_handle_t        *bucket_handle;
   1631     trie_t                      *pivot_trie = NULL;
   1632     trie_node_t                 *delp = NULL;
   1633 
   1634     pivot_trie = VRF_PIVOT_TRIE_IPV6_128(u, vrf);
   1635 
   1636     if (alpm_pivot == NULL) {
   1637         rv = trie_delete(pivot_trie, pivot, length, &delp);
   1638         alpm_pivot = (alpm_pivot_t *) delp;
   1639     }
   1640     if (SOC_SUCCESS(rv)) {
   1641         bucket_handle   = alpm_pivot->bucket;
   1642         pivot_index     = PIVOT_TCAM_INDEX(alpm_pivot);
   1643 
   1644         trie_destroy(PIVOT_BUCKET_TRIE(alpm_pivot));
   1645         sal_free(alpm_pivot);
   1646         sal_free(bucket_handle);
   1647 
   1648         /* For normal destroy (other than rollback) when the entry is deleted
   1649          * from lpm. The pivot_index is already replaced to another index.
   1650          */
   1651         if (clear) {
   1652             ALPM_TCAM_PIVOT(u, pivot_index) = NULL;
   1653         }
   1654     }
   1655 
   1656     return rv;
   1657 }
   1658 static int
   1659 _soc_alpm_128_split_pivot_create(int u, int v6, int vrf, int bucket_index,
   1660                                  trie_node_t     *split_trie_root,
   1661                                  uint32          *pivot,
   1662                                  uint32          length,
   1663                                  uint32          bpm_len,
   1664                                  alpm_pivot_t    **new_pivot)
   1665 {
   1666     int                             rv = SOC_E_NONE;
   1667     alpm_pivot_t                    *pivot_pyld;
   1668     alpm_bucket_handle_t            *bucket_handle;
   1669     trie_t                          *pivot_trie = NULL;
   1670 
   1671     pivot_trie = VRF_PIVOT_TRIE_IPV6_128(u, vrf);
   1672 
   1673 
   1674     /* Add New Pivot to the pivot trie */
   1675     bucket_handle = sal_alloc(sizeof(alpm_bucket_handle_t),
   1676                              "ALPM Bucket Handle");
   1677     if (bucket_handle == NULL) {
   1678         LOG_ERROR(BSL_LS_SOC_ALPM,
   1679                   (BSL_META_U(u,
   1680                               "Unable to allocate memory "
   1681                               "for PIVOT trie node \n")));
   1682         return SOC_E_MEMORY;
   1683     }
   1684     sal_memset(bucket_handle, 0, sizeof(*bucket_handle));
   1685     pivot_pyld = sal_alloc(sizeof(alpm_pivot_t),
   1686                             "Payload for new Pivot");
   1687     if (pivot_pyld == NULL) {
   1688         LOG_ERROR(BSL_LS_SOC_ALPM,
   1689                   (BSL_META_U(u,
   1690                               "Unable to allocate memory "
   1691                               "for PIVOT trie node \n")));
   1692         sal_free(bucket_handle);
   1693         return SOC_E_MEMORY;
   1694     }
   1695     sal_memset(pivot_pyld, 0, sizeof(*pivot_pyld));
   1696     PIVOT_BUCKET_HANDLE(pivot_pyld) = bucket_handle;
   1697     (void) trie_init(_MAX_KEY_LEN_144_, &PIVOT_BUCKET_TRIE(pivot_pyld));
   1698     PIVOT_BUCKET_TRIE(pivot_pyld)->trie = split_trie_root;
   1699     PIVOT_BUCKET_INDEX(pivot_pyld) = bucket_index;
   1700     PIVOT_BUCKET_VRF(pivot_pyld) = vrf;
   1701     PIVOT_BUCKET_IPV6(pivot_pyld) = v6;
   1702     PIVOT_BUCKET_DEF(pivot_pyld) = FALSE;
   1703     PIVOT_TCAM_BPMLEN(pivot_pyld)= bpm_len;
   1704 
   1705     (pivot_pyld)->key[0] = pivot[0];
   1706     (pivot_pyld)->key[1] = pivot[1];
   1707     (pivot_pyld)->key[2] = pivot[2];
   1708     (pivot_pyld)->key[3] = pivot[3];
   1709     (pivot_pyld)->key[4] = pivot[4];
   1710     (pivot_pyld)->len    = length;
   1711 
   1712     /* insert into pivot trie */
   1713     rv = trie_insert(pivot_trie, pivot, NULL, length,
   1714                      (trie_node_t *)pivot_pyld);
   1715     if (SOC_SUCCESS(rv)) {
   1716         if (new_pivot) {
   1717             *new_pivot = pivot_pyld;
   1718         }
   1719     } else {
   1720         LOG_ERROR(BSL_LS_SOC_ALPM,
   1721                   (BSL_META_U(u,
   1722                               "failed to insert into pivot trie\n")));
   1723         _soc_alpm_128_split_pivot_create_undo(u, v6, vrf, pivot,
   1724                                               length, pivot_pyld, 1);
   1725     }
   1726 
   1727     return rv;
   1728 }
   1729 
   1730 /* Connect TCAM entry to a bucket ID */
   1731 static int
   1732 _soc_alpm_128_bucket_link(int u, int v6, int pivot_index, int bucket_index)
   1733 {
   1734     int             rv = SOC_E_NONE;
   1735     int             lpm_index;
   1736     soc_mem_t       lpm_mem = L3_DEFIP_PAIR_128m;
   1737     defip_pair_128_entry_t   lpm_entry;
   1738 
   1739     /* Connect TCAM entry to new bucket */
   1740     lpm_index = soc_alpm_logical_idx(u, lpm_mem,
   1741                     SOC_ALPM_128_DEFIP_TO_PAIR(u, pivot_index >> 1), 1);
   1742 
   1743     rv = _soc_mem_alpm_read(u, L3_DEFIP_PAIR_128m,
   1744                             MEM_BLOCK_ANY, lpm_index, &lpm_entry);
   1745     SOC_IF_ERROR_RETURN(rv);
   1746     soc_mem_field32_set(u, lpm_mem, &lpm_entry, ALG_BKT_PTRf, bucket_index);
   1747     rv = WRITE_L3_DEFIP_PAIR_128m(u, MEM_BLOCK_ANY, lpm_index, &lpm_entry);
   1748     SOC_IF_ERROR_RETURN(rv);
   1749 
   1750     if (SOC_URPF_STATUS_GET(u)) {
   1751         int _urpf_index = lpm_index + (soc_mem_index_count(u, lpm_mem) >> 1);
   1752         rv = _soc_mem_alpm_read(u, L3_DEFIP_PAIR_128m,
   1753                                 MEM_BLOCK_ANY, _urpf_index, &lpm_entry);
   1754         SOC_IF_ERROR_RETURN(rv);
   1755 
   1756         soc_mem_field32_set(u, lpm_mem, &lpm_entry, ALG_BKT_PTRf,
   1757                             bucket_index + SOC_ALPM_BUCKET_COUNT(u));
   1758         rv = WRITE_L3_DEFIP_PAIR_128m(u, MEM_BLOCK_ANY, _urpf_index, &lpm_entry);
   1759         SOC_IF_ERROR_RETURN(rv);
   1760     }
   1761 
   1762     return rv;
   1763 }
   1764 /* Merge entries from one logical bucket to another */
   1765 int
   1766 _soc_alpm_128_bucket_merge(int u, soc_mem_t mem, int pivot_idx_from,
   1767                            int pivot_idx_to, soc_alpm_merge_type_t merge_dir,
   1768                            int *shuffled)
   1769 {
   1770     int                     *new_index = NULL;
   1771     int                     rv = SOC_E_NONE;
   1772     int                     bucket_index_from, bucket_index_to;
   1773     int                     v6, i;
   1774     int                     vrf = 0;
   1775     alpm_mem_prefix_array_t *pfx_array = NULL;
   1776     defip_pair_128_entry_t  lpm_entry;
   1777     alpm_pivot_t            *from_pivot, *to_pivot;
   1778     alpm_pivot_t            *parent_pivot = NULL, *child_pivot = NULL;
   1779     uint32                  bank_disable;
   1780     enum {
   1781         _MERGE_NONE,
   1782         _MERGE_PREPARE,
   1783         _MERGE_COPY,
   1784         _MERGE_LPM_LINK,
   1785         _MERGE_INVALIDATE,
   1786         _MERGE_CHILD_TRIE_MERGED,
   1787         _MERGE_CHILD_LPM_DELETED,
   1788         _MERGE_CHILD_PIVOT_DESTROYED
   1789     } doing = _MERGE_NONE, done = _MERGE_NONE;
   1790     void                    *raw_bkt[RAW_BKT_NUM] = {0};
   1791     v6 = L3_DEFIP_MODE_128;
   1792 
   1793     from_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_from);
   1794     to_pivot   = ALPM_TCAM_PIVOT(u, pivot_idx_to);
   1795 
   1796     bucket_index_from = PIVOT_BUCKET_INDEX(from_pivot);
   1797     bucket_index_to   = PIVOT_BUCKET_INDEX(to_pivot);
   1798 
   1799     vrf = PIVOT_BUCKET_VRF(from_pivot);
   1800     bank_disable = soc_alpm_bank_dis(u, vrf);
   1801 
   1802     /**
   1803      * Invalidate need to happen only after all the entries are
   1804      * written to the new pivot and the new pivot is valid. Otherwise
   1805      * there is a chance of MISS.
   1806      *
   1807      * hitless move:
   1808      * - Copy entries to new bucket.
   1809      * - activate new pivot
   1810      * - delete entries from old bucket
   1811      */
   1812 
   1813     doing = _MERGE_PREPARE;
   1814     rv = _soc_alpm_128_raw_bucket_prepare(u, mem, PIVOT_BUCKET_TRIE(from_pivot),
   1815                                           bucket_index_from, bucket_index_to,
   1816                                           bank_disable, NULL, NULL,
   1817                                           &pfx_array, raw_bkt, &new_index, NULL, 1);
   1818     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   1819 
   1820     doing = _MERGE_COPY;
   1821     rv = _soc_alpm_128_raw_bucket_copy(u, mem, bucket_index_to,
   1822                                        bank_disable, raw_bkt[RAW_NEW_BKT_DIP],
   1823                                        raw_bkt[RAW_NEW_BKT_SIP],
   1824                                        new_index, pfx_array->count);
   1825     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   1826 
   1827     /* Connect TCAM entry to new bucket.
   1828      * This is a must step even for merge child to parent
   1829      */
   1830     doing = _MERGE_LPM_LINK;
   1831     rv = _soc_alpm_128_bucket_link(u, v6, pivot_idx_from, bucket_index_to);
   1832     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   1833 
   1834     /* Invalide old entries */
   1835     doing = _MERGE_INVALIDATE;
   1836     rv = _soc_alpm_128_raw_bucket_inval(u, mem, bucket_index_from,
   1837                                     bank_disable,
   1838                                     raw_bkt[RAW_OLD_BKT_DIP],
   1839                                     raw_bkt[RAW_OLD_BKT_SIP],
   1840                                     raw_bkt[RAW_RB_BKT_DIP],
   1841                                     raw_bkt[RAW_RB_BKT_SIP]);
   1842     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   1843 
   1844     if (merge_dir != MERGE_PHY) {
   1845         uint32          hw_key[5] = {0};
   1846         int             child_vrf;
   1847 
   1848         if (merge_dir == MERGE_LOG_PARENT_TO_CHILD) {
   1849             parent_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_from);
   1850             child_pivot  = ALPM_TCAM_PIVOT(u, pivot_idx_to);
   1851         } else {
   1852             child_pivot  = ALPM_TCAM_PIVOT(u, pivot_idx_from);
   1853             parent_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_to);
   1854         }
   1855 
   1856         /* SW bucket merge: not expect to fail */
   1857         doing = _MERGE_CHILD_TRIE_MERGED;
   1858         rv = trie_merge(PIVOT_BUCKET_TRIE(parent_pivot),
   1859                         PIVOT_BUCKET_TRIE(child_pivot)->trie,
   1860                         child_pivot->key,
   1861                         child_pivot->len);
   1862         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   1863 
   1864         sal_memcpy(hw_key, child_pivot->key, sizeof(hw_key));
   1865         ALPM_TRIE_TO_NORMAL_IP_128(hw_key, child_pivot->len, v6);
   1866 
   1867         child_vrf = PIVOT_BUCKET_VRF(child_pivot);
   1868 
   1869         (void) _soc_alpm_128_lpm_ent_key_init(u, hw_key, child_pivot->len,
   1870                                       child_vrf, v6, &lpm_entry, 0, 1);
   1871 
   1872         /* Delete child lpm entry from TCAM */
   1873         doing = _MERGE_CHILD_LPM_DELETED;
   1874         rv = soc_alpm_128_lpm_delete(u, &lpm_entry);
   1875         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   1876         if (shuffled) {
   1877             *shuffled = 1;
   1878         }
   1879 
   1880         /* Destroy child pivot from trie */
   1881         doing = _MERGE_CHILD_PIVOT_DESTROYED;
   1882         rv = _soc_alpm_128_split_pivot_create_undo
   1883                     (u, v6, child_vrf, child_pivot->key, child_pivot->len, NULL, 0);
   1884 
   1885         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   1886     }
   1887 
   1888     /* Update TCAM mgmt info: set new logical bucket */
   1889     if (merge_dir != MERGE_LOG_CHILD_TO_PARENT && ALPM_TCAM_PIVOT(u, pivot_idx_from)) {
   1890         PIVOT_BUCKET_INDEX(ALPM_TCAM_PIVOT(u, pivot_idx_from)) = bucket_index_to;
   1891     }
   1892 
   1893     alpm_bucket_release(u, bucket_index_from, v6);
   1894 
   1895     /* Update new index */
   1896     for (i = 0; i < pfx_array->count; i++) {
   1897         pfx_array->prefix[i]->index = new_index[i];
   1898     }
   1899 
   1900     _soc_alpm_128_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index);
   1901     return rv;
   1902 
   1903 _rollback:
   1904 
   1905     /* fall through on all cases */
   1906     switch (done)  {
   1907     case _MERGE_CHILD_LPM_DELETED:
   1908         if (merge_dir != MERGE_PHY) {
   1909             /* not expecting any failure after lpm deleted */
   1910         }
   1911 
   1912     case _MERGE_CHILD_TRIE_MERGED:
   1913         if (merge_dir != MERGE_PHY) {
   1914             uint32      pivot[5], length;
   1915             trie_split2(PIVOT_BUCKET_TRIE(parent_pivot),
   1916                         child_pivot->key,
   1917                         child_pivot->len,
   1918                         pivot, &length,
   1919                         &(PIVOT_BUCKET_TRIE(child_pivot)->trie),
   1920                         PIVOT_BUCKET_COUNT(child_pivot), 1);
   1921         }
   1922 
   1923     case _MERGE_INVALIDATE:
   1924         _soc_alpm_128_raw_bucket_inval_undo(u, mem, bucket_index_from,
   1925                                             bank_disable,
   1926                                             raw_bkt[RAW_RB_BKT_DIP],
   1927                                             raw_bkt[RAW_RB_BKT_SIP]);
   1928 
   1929     case _MERGE_LPM_LINK:
   1930         /* Connect TCAM back to original bucket */
   1931         _soc_alpm_128_bucket_link(u, v6, pivot_idx_from, bucket_index_from);
   1932 
   1933     case _MERGE_COPY:
   1934         /* Delete entries in new bucket */
   1935         _soc_alpm_128_raw_bucket_copy_undo(u, mem, bucket_index_to, bank_disable,
   1936                                            raw_bkt[RAW_NEW_BKT_DIP],
   1937                                            raw_bkt[RAW_NEW_BKT_SIP], new_index,
   1938                                            pfx_array->count);
   1939 
   1940     case _MERGE_PREPARE:
   1941         _soc_alpm_128_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index);
   1942 
   1943     case _MERGE_NONE:
   1944     default:
   1945         break;
   1946     }
   1947 
   1948     /* Error dump */
   1949     switch (doing)  {
   1950     case _MERGE_LPM_LINK:
   1951         LOG_ERROR(BSL_LS_SOC_ALPM,
   1952                   (BSL_META_U(u,
   1953                               "_soc_alpm_128_bucket_link failed, pivot %d log_bkt %d\n"),
   1954                               pivot_idx_from, bucket_index_to));
   1955         break;
   1956 
   1957     case _MERGE_INVALIDATE:
   1958         LOG_ERROR(BSL_LS_SOC_ALPM,
   1959                   (BSL_META_U(u,
   1960                               "_soc_alpm_128_bucket_inval failed\n")));
   1961         break;
   1962     case _MERGE_CHILD_TRIE_MERGED:
   1963         break;
   1964 
   1965     case _MERGE_CHILD_PIVOT_DESTROYED:
   1966         LOG_ERROR(BSL_LS_SOC_ALPM,
   1967                   (BSL_META_U(u,
   1968                               "Pivot destroy fail, something not expected\n")));
   1969 
   1970     default:
   1971         LOG_ERROR(BSL_LS_SOC_ALPM,
   1972                   (BSL_META_U(u,
   1973                               "Merge fails at step %d\n"), doing));
   1974         break;
   1975     }
   1976 
   1977     return rv;
   1978 }
   1979 
   1980 
   1981 int
   1982 _soc_alpm_128_lpm_free_entries(int u, int vrf)
   1983 {
   1984     int curr_pfx, min_pfx;
   1985     int total_fent = 0;
   1986 
   1987     curr_pfx = MAX_PFX_INDEX_128;
   1988     min_pfx  = 0;
   1989     if (soc_alpm_mode_get(u) == SOC_ALPM_MODE_PARALLEL) {
   1990         if (vrf == (SOC_VRF_MAX(u) + 1)) { /* Global VRF */
   1991             min_pfx  = MAX_VRF_PFX_INDEX_128 + 1;
   1992         } else {
   1993             curr_pfx = MAX_VRF_PFX_INDEX_128;
   1994         }
   1995     }
   1996     while (curr_pfx >= min_pfx) {
   1997         total_fent += SOC_ALPM_128_LPM_STATE_FENT(u, curr_pfx);
   1998         curr_pfx = SOC_ALPM_128_LPM_STATE_NEXT(u, curr_pfx);
   1999     }
   2000 
   2001     return total_fent;
   2002 }
   2003 
   2004 
   2005 /* Move partial entries from one logical bucket to another */
   2006 int
   2007 _soc_alpm_128_bucket_repartition(int u, soc_mem_t mem, int pivot_idx_from,
   2008                                  int pivot_idx_to, trie_node_t **new_trie,
   2009                                  int *shuffled)
   2010 {
   2011     trie_node_t             *split_trie_root = NULL;
   2012     uint32                  length, bpm_len = 0;
   2013     uint32                  pivot[5];
   2014     defip_pair_128_entry_t  lpm_entry;
   2015     alpm_mem_prefix_array_t *pfx_array = NULL;
   2016     int                     *new_index = NULL;
   2017     int                     rv = SOC_E_NONE, i;
   2018     int                     tcam_index, pivot_index;
   2019     int                     bucket_index_from, bucket_index_to;
   2020     int                     vrf = 0;
   2021     uint32                  src_discard, src_default;
   2022 
   2023     alpm_pivot_t            *new_pivot, *parent_pivot, *child_pivot;
   2024     uint32                  bank_disable = 0;
   2025     int                     v6 = L3_DEFIP_MODE_128;
   2026     enum {
   2027         _REPART_TRIE_NONE,
   2028         _REPART_TRIE_SPLIT,
   2029         _REPART_LPM_INIT,
   2030         _REPART_PIVOT_CREATE,
   2031         _REPART_PREPARE,
   2032         _REPART_COPY,
   2033         _REPART_LPM_INSERT,
   2034         _REPART_INVALIDATE,
   2035         _REPART_CHILD_TRIE_MERGED,
   2036         _REPART_CHILD_LPM_DELETED,
   2037         _REPART_CHILD_PIVOT_DESTROYED
   2038     } doing = _REPART_TRIE_NONE, done = _REPART_TRIE_NONE;
   2039     void                    *raw_bkt[RAW_BKT_NUM] = {0};
   2040 
   2041     parent_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_from);
   2042     child_pivot  = ALPM_TCAM_PIVOT(u, pivot_idx_to);
   2043     bucket_index_from = PIVOT_BUCKET_INDEX(parent_pivot);
   2044     bucket_index_to   = PIVOT_BUCKET_INDEX(child_pivot);
   2045 
   2046     doing = _REPART_TRIE_SPLIT;
   2047     rv = trie_split2(PIVOT_BUCKET_TRIE(parent_pivot),
   2048                      child_pivot->key,
   2049                      child_pivot->len,
   2050                      pivot, &length,
   2051                      &split_trie_root,
   2052                      1024, 0);
   2053     if (SOC_FAILURE(rv)) {
   2054         /* Non repartable is nothing fatal, just return and keep searching */
   2055         if (rv == SOC_E_NOT_FOUND) {
   2056             rv = SOC_E_NONE;
   2057         }
   2058         /* Must return */
   2059         return rv;
   2060     }
   2061     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2062 
   2063     vrf = PIVOT_BUCKET_VRF(parent_pivot);
   2064     doing = _REPART_LPM_INIT;
   2065 
   2066     rv = _soc_alpm_128_split_lpm_init(u, vrf, bucket_index_to, NULL, NULL,
   2067                                       pivot, length, &lpm_entry, &bpm_len,
   2068                                       &src_discard, &src_default);
   2069     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2070 
   2071 
   2072     doing = _REPART_PIVOT_CREATE;
   2073     rv = _soc_alpm_128_split_pivot_create(u, v6, vrf, bucket_index_to,
   2074                                           split_trie_root, pivot, length,
   2075                                           bpm_len, &new_pivot);
   2076     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2077 
   2078     bank_disable = soc_alpm_bank_dis(u, vrf);
   2079 
   2080     doing = _REPART_PREPARE;
   2081     rv = _soc_alpm_128_raw_bucket_prepare(u, mem, PIVOT_BUCKET_TRIE(new_pivot),
   2082                                           bucket_index_from, bucket_index_to,
   2083                                           bank_disable, NULL, NULL,
   2084                                           &pfx_array, raw_bkt, &new_index, NULL, 1);
   2085     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2086 
   2087     doing = _REPART_COPY;
   2088     rv = _soc_alpm_128_raw_bucket_copy(u, mem, bucket_index_to,
   2089                                        bank_disable, raw_bkt[RAW_NEW_BKT_DIP],
   2090                                        raw_bkt[RAW_NEW_BKT_SIP],
   2091                                        new_index, pfx_array->count);
   2092     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2093 
   2094     doing = _REPART_LPM_INSERT;
   2095     rv = soc_alpm_128_lpm_insert(u, &lpm_entry, &tcam_index,
   2096                                  src_default, src_discard, bpm_len);
   2097     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2098     if (shuffled) {
   2099         *shuffled = 1;
   2100     }
   2101 
   2102     /* TCAM index from lpm code is logical.  Convert to global idx */
   2103     tcam_index = soc_alpm_physical_idx(u, L3_DEFIP_PAIR_128m, tcam_index, v6);
   2104 
   2105     pivot_index = SOC_ALPM_128_ADDR_LWR(u, tcam_index) << 1;;
   2106     PIVOT_TCAM_INDEX(new_pivot)         = pivot_index;
   2107     ALPM_TCAM_PIVOT(u, pivot_index)     = new_pivot;
   2108 
   2109     /* Invalide old entries */
   2110     doing = _REPART_INVALIDATE;
   2111     rv = _soc_alpm_128_raw_bucket_inval(u, mem, bucket_index_from,
   2112                                     bank_disable,
   2113                                     raw_bkt[RAW_OLD_BKT_DIP],
   2114                                     raw_bkt[RAW_OLD_BKT_SIP],
   2115                                     raw_bkt[RAW_RB_BKT_DIP],
   2116                                     raw_bkt[RAW_RB_BKT_SIP]);
   2117     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2118 
   2119     /* Delete old lpm entry */
   2120     {
   2121         uint32          hw_key[5] = {0};
   2122         int             child_vrf;
   2123 
   2124         /* SW bucket merge: not expect to fail */
   2125         doing = _REPART_CHILD_TRIE_MERGED;
   2126         rv = trie_merge(PIVOT_BUCKET_TRIE(new_pivot),
   2127                         PIVOT_BUCKET_TRIE(child_pivot)->trie,
   2128                         child_pivot->key,
   2129                         child_pivot->len);
   2130         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2131 
   2132         sal_memcpy(hw_key, child_pivot->key, sizeof(hw_key));
   2133         ALPM_TRIE_TO_NORMAL_IP_128(hw_key, child_pivot->len, v6);
   2134 
   2135         child_vrf = PIVOT_BUCKET_VRF(child_pivot);
   2136 
   2137         (void) _soc_alpm_128_lpm_ent_key_init(u, hw_key, child_pivot->len,
   2138                                       child_vrf, v6, &lpm_entry, 0, 1);
   2139 
   2140         doing = _REPART_CHILD_LPM_DELETED;
   2141         rv = soc_alpm_128_lpm_delete(u, &lpm_entry);
   2142         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2143 
   2144         pivot_index = PIVOT_TCAM_INDEX(new_pivot);
   2145 
   2146         /* Destroy child pivot */
   2147         doing = _REPART_CHILD_PIVOT_DESTROYED;
   2148         rv = _soc_alpm_128_split_pivot_create_undo
   2149                     (u, v6, child_vrf, child_pivot->key, child_pivot->len, NULL, 0);
   2150 
   2151         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2152     }
   2153 
   2154     /* Update new index */
   2155     for (i = 0; i < pfx_array->count; i++) {
   2156         pfx_array->prefix[i]->index = new_index[i];
   2157     }
   2158 
   2159     _soc_alpm_128_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index);
   2160     *new_trie = (trie_node_t *) new_pivot;
   2161 
   2162     return rv;
   2163 
   2164 _rollback:
   2165     /* fall through on all cases */
   2166     switch (done)  {
   2167     case _REPART_CHILD_LPM_DELETED:
   2168         /* Not expect any failure after trie_merge */
   2169 
   2170     case _REPART_CHILD_TRIE_MERGED: {
   2171             uint32      pivot2[5], length2;
   2172             trie_split2(PIVOT_BUCKET_TRIE(parent_pivot),
   2173                         child_pivot->key,
   2174                         child_pivot->len,
   2175                         pivot2, &length2,
   2176                         &(PIVOT_BUCKET_TRIE(child_pivot)->trie),
   2177                         PIVOT_BUCKET_COUNT(child_pivot), 1);
   2178         }
   2179 
   2180     case _REPART_INVALIDATE:
   2181         _soc_alpm_128_raw_bucket_inval_undo(u, mem, bucket_index_from,
   2182                                             bank_disable,
   2183                                             raw_bkt[RAW_RB_BKT_DIP],
   2184                                             raw_bkt[RAW_RB_BKT_SIP]);
   2185 
   2186     case _REPART_LPM_INSERT:
   2187         soc_alpm_128_lpm_delete(u, &lpm_entry);
   2188 
   2189     case _REPART_COPY:
   2190         /* Delete entries in new bucket */
   2191         _soc_alpm_128_raw_bucket_copy_undo(u, mem, bucket_index_to, bank_disable,
   2192                                            raw_bkt[RAW_NEW_BKT_DIP],
   2193                                            raw_bkt[RAW_NEW_BKT_SIP], new_index,
   2194                                            pfx_array->count);
   2195 
   2196     case _REPART_PREPARE:
   2197         _soc_alpm_128_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index);
   2198 
   2199     case _REPART_PIVOT_CREATE:
   2200         _soc_alpm_128_split_pivot_create_undo(u, v6, vrf, pivot, length, NULL, 0);
   2201 
   2202     case _REPART_LPM_INIT:
   2203         /* nothing to undo */
   2204 
   2205     case _REPART_TRIE_SPLIT:
   2206         trie_merge(PIVOT_BUCKET_TRIE(parent_pivot), split_trie_root, pivot, length);
   2207     default:
   2208         break;
   2209     }
   2210 
   2211     LOG_ERROR(BSL_LS_SOC_ALPM,
   2212               (BSL_META_U(u,
   2213                           "Repartition fails at step %d\n"), doing));
   2214 
   2215     return rv;
   2216 }
   2217 
   2218 static int
   2219 _soc_alpm_128_bucket_split(int u, alpm_pfx_info_t *pfx_info, int *index_ptr)
   2220 {
   2221     trie_node_t             *split_trie_root;
   2222     uint32                  e[SOC_MAX_MEM_FIELD_WORDS];
   2223     uint32                  length, bpm_len = 0;
   2224     uint32                  bank_disable = 0;
   2225     uint32                  pivot[5] = {0};
   2226     uint32                  src_discard, src_default;
   2227     int                     key_index, i;
   2228     trie_t                  *bkt_trie;
   2229     defip_pair_128_entry_t  lpm_entry;
   2230     alpm_mem_prefix_array_t *pfx_array = NULL;
   2231     int                     *new_index = NULL;
   2232     int                     rv = SOC_E_NONE, new_index_pos = -1;
   2233     int                     tcam_index, pivot_index;
   2234     alpm_pivot_t            *new_pivot = NULL;
   2235     int                     v6 = L3_DEFIP_MODE_128;
   2236 #ifdef ALPM_USE_RAW_VIEW
   2237     void                    *raw_bkt[RAW_BKT_NUM] = {0};
   2238 #else
   2239     void                    *bufp = NULL, *sip_bufp = NULL;
   2240 #endif
   2241     enum {
   2242         _SPLIT_TRIE_NONE,
   2243         _SPLIT_TRIE_SPLIT,
   2244         _SPLIT_LPM_INIT,
   2245         _SPLIT_PIVOT_CREATE,
   2246         _SPLIT_PREPARE,
   2247         _SPLIT_COPY,
   2248         _SPLIT_LPM_INSERT,
   2249         _SPLIT_INVALIDATE
   2250     } doing = _SPLIT_TRIE_NONE, done = _SPLIT_TRIE_NONE;
   2251 
   2252     doing = _SPLIT_TRIE_SPLIT;
   2253     bkt_trie = PIVOT_BUCKET_TRIE(ALPM_TCAM_PIVOT(u, pfx_info->pivot_idx_from));
   2254     rv = trie_split(bkt_trie, _MAX_KEY_LEN_144_, FALSE,
   2255                     pivot, &length, &split_trie_root, NULL, FALSE, 1024);
   2256     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2257 
   2258     doing = _SPLIT_LPM_INIT;
   2259     rv = _soc_alpm_128_split_lpm_init(u,
   2260                                       pfx_info->vrf,
   2261                                       pfx_info->log_bkt_to,
   2262                                       pfx_info->alpm_data,
   2263                                       pfx_info->alpm_sip_data,
   2264                                       pivot, length,
   2265                                       &lpm_entry, &bpm_len,
   2266                                       &src_discard, &src_default);
   2267 
   2268     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2269 
   2270     doing = _SPLIT_PIVOT_CREATE;
   2271     rv = _soc_alpm_128_split_pivot_create(u, v6, pfx_info->vrf, pfx_info->log_bkt_to,
   2272                                           split_trie_root, pivot, length, bpm_len,
   2273                                           &new_pivot);
   2274     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2275 
   2276     /* Optimized Memory invalidate,
   2277      * Invalidate need to happen only after all the entries are
   2278      * written to the new pivot and the new pivot is valid. Otherwise
   2279      * there is a chance of MISS.
   2280      *
   2281      * hitless move:
   2282      * - Move entries to new bucket.
   2283      * - activate new pivot
   2284      * - delete entries from old bucket
   2285      */
   2286     bank_disable = soc_alpm_bank_dis(u, pfx_info->vrf);
   2287 
   2288     doing = _SPLIT_PREPARE;
   2289 #ifdef ALPM_USE_RAW_VIEW
   2290     rv = _soc_alpm_128_raw_bucket_prepare(u, pfx_info->mem, PIVOT_BUCKET_TRIE(new_pivot),
   2291                                           pfx_info->log_bkt_from, pfx_info->log_bkt_to,
   2292                                           bank_disable,
   2293                                           pfx_info->alpm_data, pfx_info->alpm_sip_data,
   2294                                           &pfx_array, raw_bkt, &new_index,
   2295                                           &new_index_pos, 0);
   2296 #else
   2297     rv = _soc_alpm_128_bucket_prepare(u, pfx_info->mem, PIVOT_BUCKET_TRIE(new_pivot),
   2298                                       &pfx_array, &bufp, &sip_bufp, &new_index);
   2299 #endif
   2300     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2301 
   2302     doing = _SPLIT_COPY;
   2303 
   2304 #ifdef ALPM_USE_RAW_VIEW
   2305     rv = _soc_alpm_128_raw_bucket_copy(u, pfx_info->mem, pfx_info->log_bkt_to,
   2306                                        bank_disable, raw_bkt[RAW_NEW_BKT_DIP],
   2307                                        raw_bkt[RAW_NEW_BKT_SIP],
   2308                                        new_index, pfx_array->count);
   2309 #else
   2310     rv = _soc_alpm_128_bucket_copy(u, pfx_info->mem, pfx_info->vrf, pfx_array, pfx_info->log_bkt_to,
   2311                                    bufp, sip_bufp, pfx_info->alpm_data,
   2312                                    pfx_info->alpm_sip_data, new_index, &new_index_pos);
   2313 #endif
   2314     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2315 
   2316     doing = _SPLIT_LPM_INSERT;
   2317     rv = soc_alpm_128_lpm_insert(u, &lpm_entry, &tcam_index,
   2318                                  src_default, src_discard, bpm_len);
   2319     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2320 
   2321     /* TCAM index from lpm code is logical. Convert to physical idx */
   2322     tcam_index = soc_alpm_physical_idx(u, L3_DEFIP_PAIR_128m, tcam_index, v6);
   2323     pivot_index = SOC_ALPM_128_ADDR_LWR(u, tcam_index) << 1;;
   2324     PIVOT_TCAM_INDEX(new_pivot)         = pivot_index;
   2325     ALPM_TCAM_PIVOT(u, pivot_index)     = new_pivot;
   2326 
   2327     doing = _SPLIT_INVALIDATE;
   2328 #ifdef ALPM_USE_RAW_VIEW
   2329     rv = _soc_alpm_128_raw_bucket_inval(u, pfx_info->mem, pfx_info->log_bkt_from,
   2330                                     bank_disable,
   2331                                     raw_bkt[RAW_OLD_BKT_DIP],
   2332                                     raw_bkt[RAW_OLD_BKT_SIP],
   2333                                     raw_bkt[RAW_RB_BKT_DIP],
   2334                                     raw_bkt[RAW_RB_BKT_SIP]);
   2335 #else
   2336     rv = _soc_alpm_128_bucket_inval(u, pfx_info->mem, pfx_array, bufp, sip_bufp);
   2337     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2338 #endif
   2339 
   2340     if (new_index_pos != -1) { /* New prefix goes to new split bucket */
   2341         *index_ptr = new_index[new_index_pos];
   2342     } else { /* To old parent bucket, do actual insert */
   2343         /* Add Entry to old bucket RAM */
   2344         rv = _soc_alpm_insert_in_bkt(u, pfx_info->mem, pfx_info->log_bkt_from, /* this should be from old pivot*/
   2345                                      bank_disable, pfx_info->alpm_data, pfx_info->alpm_sip_data,
   2346                                      e, &key_index, v6);
   2347 
   2348         if (SOC_FAILURE(rv)) {
   2349             /* recover by matching trie state to h/w state */
   2350             LOG_ERROR(BSL_LS_SOC_ALPM,
   2351                       (BSL_META_U(u, "Could not insert new "
   2352                                   "prefix into trie after split\n")));
   2353             /* since split was successful, leave split state as-is */
   2354             pfx_info->log_bkt_to = -1;
   2355             return rv;
   2356         }
   2357 
   2358         *index_ptr = key_index;
   2359     }
   2360 
   2361     PIVOT_BUCKET_ENT_CNT_UPDATE(new_pivot);
   2362     VRF_BUCKET_SPLIT_INC(u, pfx_info->vrf, v6);
   2363 
   2364     /* Update new index */
   2365     for (i = 0; i < pfx_array->count; i++) {
   2366         pfx_array->prefix[i]->index = new_index[i];
   2367     }
   2368 #ifdef ALPM_USE_RAW_VIEW
   2369     _soc_alpm_128_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index);
   2370 #else
   2371     _soc_alpm_128_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index);
   2372 #endif
   2373 
   2374     return rv;
   2375 
   2376 _rollback:
   2377     /* fall through on all cases */
   2378     switch (done)  {
   2379     case _SPLIT_LPM_INSERT:
   2380         soc_alpm_128_lpm_delete(u, &lpm_entry);
   2381 
   2382     case _SPLIT_COPY:
   2383         /* Delete entries in new bucket */
   2384 #ifdef ALPM_USE_RAW_VIEW
   2385         _soc_alpm_128_raw_bucket_copy_undo(u, pfx_info->mem, pfx_info->log_bkt_to, bank_disable,
   2386                                            raw_bkt[RAW_NEW_BKT_DIP],
   2387                                            raw_bkt[RAW_NEW_BKT_SIP], new_index, pfx_array->count);
   2388 #else
   2389         _soc_alpm_128_bucket_copy_undo(u, pfx_info->mem, pfx_array->count, new_index);
   2390 #endif
   2391 
   2392     case _SPLIT_PREPARE:
   2393 #ifdef ALPM_USE_RAW_VIEW
   2394         _soc_alpm_128_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index);
   2395 #else
   2396         _soc_alpm_128_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index);
   2397 #endif
   2398 
   2399     case _SPLIT_PIVOT_CREATE:
   2400         _soc_alpm_128_split_pivot_create_undo(u, v6, pfx_info->vrf, pivot, length, NULL, 0);
   2401 
   2402     case _SPLIT_LPM_INIT:
   2403         /* nothing to undo */
   2404 
   2405     case _SPLIT_TRIE_SPLIT:
   2406         trie_merge(bkt_trie, split_trie_root, pivot, length);
   2407 
   2408     case _SPLIT_TRIE_NONE:
   2409     default:
   2410         /* nothing to rollback for first step */
   2411         break;
   2412     }
   2413 
   2414     switch (doing) {
   2415     case _SPLIT_TRIE_SPLIT:
   2416         LOG_ERROR(BSL_LS_SOC_ALPM,
   2417                   (BSL_META_U(u,
   2418                               "Could not split bucket")));
   2419         break;
   2420 
   2421     case _SPLIT_PIVOT_CREATE:
   2422         LOG_ERROR(BSL_LS_SOC_ALPM,
   2423                   (BSL_META_U(u, "failed to insert into pivot bkt_trie\n")));
   2424         break;
   2425 
   2426     case _SPLIT_LPM_INSERT:
   2427         LOG_ERROR(BSL_LS_SOC_ALPM,
   2428                   (BSL_META_U(u,
   2429                               "Unable to add new pivot to tcam\n")));
   2430 
   2431         if (rv == SOC_E_FULL) {
   2432             VRF_PIVOT_FULL_INC(u, pfx_info->vrf, v6);
   2433         }
   2434         break;
   2435     default:
   2436         LOG_ERROR(BSL_LS_SOC_ALPM,
   2437                   (BSL_META_U(u,
   2438                               "Split fails at step %d\n"), doing));
   2439         break;
   2440     }
   2441 
   2442     return rv;
   2443 }
   2444 
   2445 
   2446 /*
   2447  * Insert entry into ALPM database.
   2448  * Returns SOC_E_NONE, if found and updated.
   2449  * SOC_E_FAIL, if insert failed.
   2450  */
   2451 static int
   2452 _soc_alpm_128_insert(int u,
   2453                      void *key_data,  /* TCAM entry data */
   2454                      soc_mem_t mem,   /* Mem view for ALPM data */
   2455                      void *alpm_data, /* Alpm data to be updated with */
   2456                      void *alpm_sip_data,
   2457                      int *index_ptr,
   2458                      int bucket_index,
   2459                      int tcam_index)
   2460 {
   2461     alpm_pivot_t *old_pivot;
   2462     defip_aux_scratch_entry_t aux_entry;
   2463     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   2464     uint32      prefix[5], length;
   2465     int         v6, vrf, vrf_id;
   2466     int         key_index;
   2467     int         rv = SOC_E_NONE;
   2468     uint32      db_type, ent_type, bank_disable;
   2469     int         hit =0;
   2470     int         split = 0;
   2471     trie_t      *bkt_trie = NULL , *pfx_trie = NULL;
   2472     trie_node_t *lpmp = NULL, *lpmp2 = NULL;
   2473     payload_t   *bkt_payload = NULL, *pfx_payload = NULL, *tmp_pyld;
   2474     int         default_route = 0;
   2475     /* Search Result buffers */
   2476     alpm_pfx_info_t pfx_info;
   2477     int         new_bucket_index = -1;
   2478     int         bkt_trie_inserted = 0, pfx_trie_inserted = 0;
   2479     int         shuffled = 0;
   2480     int         aux_flags = 0;
   2481 
   2482     v6 = L3_DEFIP_MODE_128;
   2483     SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   2484     bank_disable = soc_alpm_bank_dis(u, vrf);
   2485     soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
   2486 
   2487     /* Get table memory. */
   2488     SOC_ALPM_TABLE_MEM_128(u, v6, mem);
   2489 
   2490     /* Insert the prefix into the bucket trie, whether the insert was
   2491      * successul or resulted in Split. Spliting the trie after insertion
   2492      * yeilds better pivot and better split.
   2493      */
   2494     /* Create Prefix */
   2495     rv = _alpm_128_prefix_create(u, key_data, prefix, &length, &default_route);
   2496     if (SOC_FAILURE(rv)) {
   2497         LOG_ERROR(BSL_LS_SOC_ALPM,
   2498                   (BSL_META_U(u,
   2499                               "prefix create failed\n")));
   2500         return rv;
   2501     }
   2502 
   2503     /* Fill in AUX Scratch and perform PREFIX Operation */
   2504     sal_memset(&aux_entry, 0, sizeof(defip_aux_scratch_entry_t));
   2505     SOC_IF_ERROR_RETURN(
   2506        _soc_alpm_128_fill_aux_entry_for_op(u, key_data, v6, db_type, ent_type, 0,
   2507                                        &aux_entry));
   2508 
   2509     if (bucket_index == 0) {
   2510         if (SOC_ALPM_SW_LOOKUP(u)) {
   2511             rv = _soc_alpm_128_sw_pivot_find(u, prefix, length, v6, vrf, &hit,
   2512                                              &tcam_index, &bucket_index);
   2513             SOC_IF_ERROR_RETURN(rv);
   2514         } else {
   2515             /* no cookie provided */
   2516             SOC_IF_ERROR_RETURN(_soc_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry,
   2517                                 TRUE, &hit, &tcam_index, &bucket_index, 0));
   2518         }
   2519 
   2520         if (hit == 0) {
   2521             LOG_ERROR(BSL_LS_SOC_ALPM,
   2522                       (BSL_META_U(u,
   2523                                   "_soc_alpm_128_insert: "
   2524                                   " Could not find bucket to insert prefix\n")));
   2525             return SOC_E_NOT_FOUND;
   2526         }
   2527     }
   2528     bucket_index &= ~SOC_ALPM_V6_SCALE_CHECK(u, v6);
   2529 
   2530     /* entry shouldn't exist, insert the entry into the RAM */
   2531     rv = _soc_alpm_insert_in_bkt(u, mem, bucket_index,
   2532                                  bank_disable, alpm_data, alpm_sip_data,
   2533                                  e, &key_index, v6);
   2534 
   2535     if (rv == SOC_E_NONE)  {
   2536         *index_ptr = key_index;
   2537     } else if (rv == SOC_E_FULL) {
   2538 
   2539         rv = soc_alpm_assign(u, vrf, mem, &new_bucket_index, &shuffled);
   2540         SOC_IF_ERROR_RETURN(rv);
   2541         if (shuffled) {
   2542             if (SOC_ALPM_SW_LOOKUP(u)) {
   2543                 rv = _soc_alpm_128_sw_pivot_find(u, prefix, length, v6, vrf, &hit,
   2544                                                  &tcam_index, &bucket_index);
   2545             } else {
   2546                 rv = _soc_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry, TRUE, &hit,
   2547                                       &tcam_index, &bucket_index, 0);
   2548             }
   2549             SOC_IF_ERROR_RETURN(rv);
   2550         }
   2551 
   2552         split = 1;
   2553         /* this indicates a new route, which will be used to decide
   2554          * if the new route happens to be new pivot.
   2555          */
   2556         key_index = -1;
   2557     } else {
   2558         return rv;
   2559     }
   2560 
   2561     old_pivot = ALPM_TCAM_PIVOT(u, tcam_index);
   2562     if (old_pivot == NULL) {
   2563         LOG_ERROR(BSL_LS_SOC_ALPM,
   2564                   (BSL_META_U(u, "ins: pivot index %d bkt %d is not valid \n"),
   2565                   tcam_index, bucket_index));
   2566         return SOC_E_PARAM;
   2567     }
   2568 
   2569     /* Allocate Payload */
   2570     bkt_payload = sal_alloc(sizeof(payload_t), "Payload for 128b Key");
   2571     if (bkt_payload == NULL) {
   2572         LOG_ERROR(BSL_LS_SOC_ALPM,
   2573                  (BSL_META_U(u,
   2574                  "Unable to allocate memory for "
   2575                   "bkt_trie node \n")));
   2576         rv = SOC_E_MEMORY;
   2577         goto _rollback;
   2578     }
   2579     pfx_payload = sal_alloc(sizeof(payload_t), "Payload for pfx trie 128b key");
   2580     if (pfx_payload == NULL) {
   2581         LOG_ERROR(BSL_LS_SOC_ALPM,
   2582                   (BSL_META_U(u,
   2583                    "Unable to allocate memory for "
   2584                   "pfx trie node \n")));
   2585         rv = SOC_E_MEMORY;
   2586         goto _rollback;
   2587     }
   2588     sal_memset(bkt_payload, 0, sizeof(*bkt_payload));
   2589     sal_memset(pfx_payload, 0, sizeof(*pfx_payload));
   2590     sal_memcpy(bkt_payload->key, prefix, sizeof(prefix));
   2591     bkt_payload->len    = length;
   2592     /* Needs update for split case, updated below */
   2593     bkt_payload->index  = key_index;
   2594     /* create duplicate for prefix bkt_trie */
   2595     sal_memcpy(pfx_payload, bkt_payload, sizeof(*bkt_payload));
   2596     pfx_payload->bkt_ptr = bkt_payload;
   2597 
   2598     /* Insert the prefix */
   2599     /* bucket trie insert */
   2600     bkt_trie = PIVOT_BUCKET_TRIE(old_pivot);
   2601     rv = trie_insert(bkt_trie, prefix, NULL, length, (trie_node_t *)bkt_payload);
   2602     if (SOC_SUCCESS(rv)) {
   2603         bkt_trie_inserted = 1;
   2604     } else {
   2605         goto _rollback;
   2606     }
   2607 
   2608     /* prefix trie insert */
   2609     pfx_trie = VRF_PREFIX_TRIE_IPV6_128(u, vrf);
   2610     if (!default_route) {
   2611         /* default route already in trie */
   2612         rv = trie_insert(pfx_trie, prefix, NULL, length, 
   2613                         (trie_node_t *)pfx_payload);
   2614         if (SOC_SUCCESS(rv)) {
   2615             pfx_trie_inserted = 1;
   2616         }
   2617     } else {
   2618         /* update the default route */
   2619         lpmp = NULL;
   2620         rv = trie_find_lpm(pfx_trie, 0, 0, &lpmp);
   2621         tmp_pyld = (payload_t *) lpmp;
   2622         if (SOC_SUCCESS(rv)) {
   2623             tmp_pyld->bkt_ptr = bkt_payload;
   2624         }
   2625     }
   2626     if (SOC_FAILURE(rv)) {
   2627         goto _rollback;
   2628     }
   2629 
   2630     /* Performs lazy splitting */
   2631     if (split) { /* Split */
   2632         sal_memset(&pfx_info, 0, sizeof(pfx_info));
   2633         pfx_info.pivot_idx_from   = tcam_index;
   2634         pfx_info.alpm_data        = alpm_data;
   2635         pfx_info.alpm_sip_data    = alpm_sip_data;
   2636         pfx_info.log_bkt_from     = bucket_index;
   2637         pfx_info.log_bkt_to       = new_bucket_index;
   2638         pfx_info.vrf              = vrf;
   2639         pfx_info.mem              = mem;
   2640         rv = _soc_alpm_128_bucket_split(u, &pfx_info, index_ptr);
   2641         if (rv != SOC_E_NONE) {
   2642             new_bucket_index = pfx_info.log_bkt_to;
   2643             goto _rollback;
   2644         }
   2645         bkt_payload->index  = *index_ptr;
   2646         /* New Pivot */
   2647         soc_alpm_dbg_cnt[u].bkt_split++;
   2648     }
   2649 
   2650     /* from here on, we don't expect any failure */
   2651 
   2652     /* propagate the insertion */
   2653     if (default_route) {
   2654         /* also free unused pfx_payload pointer */
   2655         sal_free(pfx_payload);
   2656     }
   2657 
   2658     if (SOC_URPF_STATUS_GET(u)) {
   2659         if (soc_mem_field32_get(u, mem, alpm_sip_data, DEFAULTROUTEf)) {
   2660             aux_flags |= SOC_ALPM_AUX_DEF_ROUTE;
   2661         }
   2662         if (soc_mem_field32_get(u, mem, alpm_sip_data, SRC_DISCARDf)) {
   2663             aux_flags |= SOC_ALPM_AUX_SRC_DISCARD;
   2664         }
   2665     }
   2666 
   2667     SOC_IF_ERROR_RETURN(_soc_alpm_aux_op(u, INSERT_PROPAGATE, &aux_entry,
   2668                         TRUE, &hit, &tcam_index, &bucket_index, aux_flags));
   2669 
   2670     /* For debug, update the old pivot's counter */
   2671     PIVOT_BUCKET_ENT_CNT_UPDATE(old_pivot);
   2672     return rv;
   2673 
   2674 _rollback:
   2675     if (!default_route && pfx_trie_inserted) {
   2676         (void)trie_delete(pfx_trie, prefix, length, &lpmp);
   2677     }
   2678 
   2679     if (bkt_trie_inserted) {
   2680         (void)trie_delete(bkt_trie, prefix, length, &lpmp2);
   2681     }
   2682 
   2683     if (pfx_payload) {
   2684         sal_free(pfx_payload);
   2685     }
   2686 
   2687     if (bkt_payload) {
   2688         sal_free(bkt_payload);
   2689     }
   2690 
   2691     if (split && new_bucket_index != -1) {
   2692         /* for non-split case, the new logical bucket is taking effect and thus
   2693          * should not be released
   2694          */
   2695          (void)alpm_bucket_release(u, new_bucket_index, v6);
   2696     }
   2697     return rv;
   2698 }
   2699 
   2700 
   2701 
   2702 /* Build an LPM entry, from a key */
   2703 /* Mostly used for the match */
   2704 static int
   2705 _soc_alpm_128_lpm_ent_key_init(int unit, uint32 *key, int len, int vrf, int ipv6,
   2706                       defip_pair_128_entry_t *lpm_entry, int nh_ecmp_idx, int init)
   2707 {
   2708     uint32 tmp; 
   2709 
   2710     /* Zero buffers. */
   2711     if (init) {
   2712         sal_memset(lpm_entry, 0, sizeof(defip_pair_128_entry_t));
   2713     }
   2714 
   2715     /* and with mask to ensure global vrf gets set to 0 */
   2716     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, VRF_ID_0_LWRf, 
   2717                               vrf & SOC_VRF_MAX(unit));
   2718     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, VRF_ID_1_LWRf, 
   2719                               vrf & SOC_VRF_MAX(unit));
   2720     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, VRF_ID_0_UPRf, 
   2721                               vrf & SOC_VRF_MAX(unit));
   2722     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, VRF_ID_1_UPRf, 
   2723                               vrf & SOC_VRF_MAX(unit));
   2724 
   2725     if (vrf == (SOC_VRF_MAX(unit) + 1)) {
   2726         tmp = 0;
   2727         /* for global routes */
   2728     } else {
   2729         tmp = SOC_VRF_MAX(unit);
   2730     }
   2731     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, VRF_ID_MASK0_LWRf, tmp);
   2732     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, VRF_ID_MASK1_LWRf, tmp);
   2733     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, VRF_ID_MASK0_UPRf, tmp);
   2734     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, VRF_ID_MASK1_UPRf, tmp);
   2735 
   2736     /* Set address to the buffer. */
   2737     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, IP_ADDR0_LWRf, key[0]);
   2738     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, IP_ADDR1_LWRf, key[1]);
   2739     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, IP_ADDR0_UPRf, key[2]);
   2740     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, IP_ADDR1_UPRf, key[3]);
   2741 
   2742     /* Set mode to ipv6-128 */
   2743     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, MODE0_LWRf, 3);
   2744     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, MODE1_LWRf, 3);
   2745     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, MODE0_UPRf, 3);
   2746     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, MODE1_UPRf, 3);
   2747 
   2748     _soc_alpm_128_pfx_len_to_mask(unit, (void *)lpm_entry, len);
   2749 
   2750     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, VALID0_LWRf, 1);
   2751     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, VALID1_LWRf, 1);
   2752     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, VALID0_UPRf, 1);
   2753     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, VALID1_UPRf, 1);
   2754 
   2755     /* Set Mode Masks */
   2756     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, MODE_MASK0_LWRf, 
   2757                         (1 << soc_mem_field_length(unit, L3_DEFIP_PAIR_128m, 
   2758                         MODE_MASK0_LWRf)) - 1);
   2759     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, MODE_MASK1_LWRf, 
   2760                         (1 << soc_mem_field_length(unit, L3_DEFIP_PAIR_128m, 
   2761                         MODE_MASK1_LWRf)) - 1);
   2762     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, MODE_MASK0_UPRf, 
   2763                         (1 << soc_mem_field_length(unit, L3_DEFIP_PAIR_128m, 
   2764                         MODE_MASK0_UPRf)) - 1);
   2765     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, MODE_MASK1_UPRf, 
   2766                         (1 << soc_mem_field_length(unit, L3_DEFIP_PAIR_128m, 
   2767                         MODE_MASK1_UPRf)) - 1);
   2768 
   2769     /* Set Entry Type Masks */
   2770     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   2771                         ENTRY_TYPE_MASK0_LWRf, 
   2772                         (1 << soc_mem_field_length(unit, L3_DEFIP_PAIR_128m,
   2773                         ENTRY_TYPE_MASK0_LWRf)) - 1);
   2774     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   2775                         ENTRY_TYPE_MASK1_LWRf, 
   2776                         (1 << soc_mem_field_length(unit, L3_DEFIP_PAIR_128m,
   2777                         ENTRY_TYPE_MASK1_LWRf)) - 1);
   2778     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   2779                         ENTRY_TYPE_MASK0_UPRf, 
   2780                        (1 << soc_mem_field_length(unit, L3_DEFIP_PAIR_128m,
   2781                         ENTRY_TYPE_MASK0_UPRf)) - 1);
   2782     SOC_MEM_OPT_F32_SET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   2783                         ENTRY_TYPE_MASK1_UPRf, 
   2784                         (1 << soc_mem_field_length(unit, L3_DEFIP_PAIR_128m,
   2785                         ENTRY_TYPE_MASK1_UPRf)) - 1);
   2786     return (SOC_E_NONE);
   2787 }
   2788 
   2789 
   2790 #ifdef CHECK_CLEAN_BKT
   2791 static int
   2792 _soc_alpm_128_bkt_count(int u, soc_mem_t mem, int bkt_idx, void *bufp) 
   2793 {
   2794     int bank, entry;
   2795     int addr, rv;
   2796     int count = 0;
   2797 
   2798     for (bank = 0; bank < 4; bank++) {
   2799       for (entry = 0; entry < 2; entry++) {
   2800         addr = (entry << 16) | (bkt_idx << 2) | (bank & 3);
   2801         rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, addr, bufp);
   2802         SOC_IF_ERROR_RETURN(rv);
   2803         if (soc_mem_field32_get(u, mem, bufp, VALIDf)) {
   2804             count++;
   2805         }
   2806       }
   2807     }
   2808     return count;
   2809 }
   2810 #endif /* CHECK_CLEAN_BKT */
   2811 
   2812 /*
   2813  * Delete entry from ALPM database.
   2814  * Returns SOC_E_NONE, if found and updated.
   2815  * SOC_E_FAIL, if insert failed.
   2816  * If default route replace with internal default 
   2817  */
   2818 static int
   2819 _soc_alpm_128_delete(int u,
   2820                     void *key_data, int bucket_index,
   2821                     int tcam_index, int key_index, int propagate)  /* TCAM entry data */
   2822 {
   2823     alpm_pivot_t *pivot_pyld;
   2824     /* Search Result buffer */    
   2825     defip_alpm_ipv6_128_entry_t alpmv6_entry, alpmv62, alpmv6_sip_entry;
   2826     defip_aux_scratch_entry_t aux_entry;
   2827     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   2828     soc_mem_t mem;
   2829     void      *bufp, *bufp2, *sip_bufp = NULL;
   2830     int       vrf_id;
   2831     int       ipv6;
   2832     int       rv = SOC_E_NONE, rv2 = SOC_E_NONE;
   2833     uint32    prop_pfx[5], prefix[5];
   2834     int       v6, vrf;
   2835     uint32    length;
   2836     int       delete_bucket;
   2837     uint32    db_type, ent_type, bank_disable;
   2838     int       hit, default_route = 0;
   2839     trie_t    *trie, *pfx_trie;
   2840     uint32    bpm_pfx_len;
   2841     defip_pair_128_entry_t lpm_entry, *lpm_key;
   2842     payload_t *payload = NULL, *pfx_pyld = NULL, *tmp_pyld = NULL;
   2843     trie_node_t *delp = NULL, *lpmp = NULL;
   2844     trie_t    *pivot_trie = NULL;
   2845     int       aux_flags = 0;
   2846 
   2847     ipv6 = v6 = L3_DEFIP_MODE_128;
   2848 
   2849     SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   2850     soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
   2851     /* For VRF_OVERRIDE (Global High) entries, software needs to maintain the
   2852      * index, Prefix resides in TCAM directly. Handling of these functions are
   2853      * taken care by main insert */
   2854     if (vrf_id != SOC_L3_VRF_OVERRIDE) {
   2855         bank_disable = soc_alpm_bank_dis(u, vrf);
   2856 
   2857         /* Create Prefix */
   2858         rv = _alpm_128_prefix_create(u, key_data, prefix, &length, 
   2859                                      &default_route);
   2860 
   2861         if (SOC_FAILURE(rv)) {
   2862             LOG_ERROR(BSL_LS_SOC_ALPM,
   2863                       (BSL_META_U(u,
   2864                                   "_soc_alpm_128_delete: prefix create failed\n")));
   2865             return rv;
   2866         }
   2867         if (!soc_alpm_mode_get(u)) {
   2868             if (vrf_id != SOC_L3_VRF_GLOBAL) {
   2869                 /* allow default deletion only at end */
   2870                 if (VRF_TRIE_ROUTES_CNT(u, vrf_id, vrf, v6) > 1) {
   2871                     if (default_route) {
   2872                         LOG_ERROR(BSL_LS_SOC_ALPM,
   2873                                   (BSL_META_U(u,
   2874                                               "VRF %d: Cannot v6-128 delete "
   2875                                               "default route if other routes are present "
   2876                                               "in this mode"), vrf));
   2877                         return SOC_E_PARAM;
   2878                     }
   2879                 }
   2880             }
   2881         }
   2882 
   2883         /* Get table memory. */
   2884         SOC_ALPM_TABLE_MEM_128(u, v6, mem);
   2885      
   2886         /* Assign entry buf based on table being used */
   2887         SOC_ALPM_ENTRY_BUF_128(v6, mem, bufp, alpmv4_entry, alpmv6_entry);
   2888 
   2889         SOC_ALPM_LPM_LOCK(u);
   2890 
   2891         if (bucket_index == 0) {
   2892             /* Search the entry */
   2893             rv = _soc_alpm_128_find(u, key_data, mem, bufp, &tcam_index,
   2894                                 &bucket_index, &key_index,
   2895                                 SOC_ALPM_SW_LOOKUP(u));
   2896         } else {
   2897             rv = _soc_alpm_128_mem_ent_init(u, key_data, bufp, 0, mem, 0, 0);
   2898         }
   2899 
   2900         /* save results as they are lost later */
   2901         sal_memcpy(&alpmv62, bufp, sizeof(alpmv62));
   2902         
   2903         bufp2 = &alpmv62;
   2904 
   2905         if (SOC_FAILURE(rv)) {
   2906             SOC_ALPM_LPM_UNLOCK(u);
   2907             LOG_ERROR(BSL_LS_SOC_ALPM,
   2908                       (BSL_META_U(u,
   2909                                   "_soc_alpm_128_delete: Unable to find "
   2910                                   "prefix for delete\n")));
   2911             return rv;
   2912         }
   2913 
   2914         /* Entry found
   2915          * 1> Delete entry from trie 
   2916          * 2> Find Best Prefix Match 
   2917          * 3> Update bpm using replacement prefix op
   2918          * 4> Invalidate Entry in the ALPM database
   2919          */
   2920         /* Delete the prefix from trie*/
   2921         /* Store index to invalidate the prefix */
   2922         delete_bucket = bucket_index & ~SOC_ALPM_V6_SCALE_CHECK(u, v6);
   2923 
   2924         pivot_pyld = ALPM_TCAM_PIVOT(u, tcam_index);
   2925         if (pivot_pyld == NULL) {
   2926             LOG_ERROR(BSL_LS_SOC_ALPM,
   2927                 (BSL_META_U(u, "del128: pivot index %d bkt %d is not valid \n"), 
   2928                 tcam_index, bucket_index));
   2929             SOC_ALPM_LPM_UNLOCK(u);
   2930             return SOC_E_PARAM;
   2931         }
   2932 
   2933         trie = PIVOT_BUCKET_TRIE(pivot_pyld);
   2934 
   2935         rv = trie_delete(trie, prefix, length,  &delp);
   2936         payload = (payload_t *) delp;
   2937         if (rv != SOC_E_NONE) {
   2938             LOG_ERROR(BSL_LS_SOC_ALPM,
   2939                       (BSL_META_U(u,
   2940                                   "_soc_alpm_128_delete: Error prefix not "
   2941                                   "present in trie \n")));
   2942             SOC_ALPM_LPM_UNLOCK(u);
   2943             return rv;
   2944         } 
   2945 
   2946         /* prefix trie delete */
   2947         pfx_trie = VRF_PREFIX_TRIE_IPV6_128(u, vrf);
   2948         pivot_trie = VRF_PIVOT_TRIE_IPV6_128(u, vrf);
   2949         if (!default_route) {
   2950             rv = trie_delete(pfx_trie, prefix, length, &delp);
   2951             pfx_pyld = (payload_t *) delp;
   2952 
   2953             if (SOC_FAILURE(rv)) {
   2954                 /* continue anyway to minimize state mismatch */
   2955                 LOG_ERROR(BSL_LS_SOC_ALPM,
   2956                           (BSL_META_U(u,
   2957                                       "_soc_alpm_128_delete: Prefix not present "
   2958                                       "in pfx trie: 0x%08x 0x%08x 0x%08x 0x%08x\n"), 
   2959                            prefix[1], prefix[2], prefix[3], prefix[4]));
   2960                 goto recover_bkt_trie;
   2961             }
   2962             if (propagate) {
   2963                 /* Find Best prefix match for the prefix */
   2964                 lpmp = NULL;
   2965                 rv = trie_find_lpm(pfx_trie, prefix, length, &lpmp);
   2966                 tmp_pyld = (payload_t *) lpmp;
   2967                 if (SOC_SUCCESS(rv)) {
   2968                     payload_t *t = (payload_t *)(tmp_pyld->bkt_ptr);
   2969                     if (t != NULL) {
   2970                         /* this means a real default route exists */
   2971                         bpm_pfx_len = t->len;
   2972                     } else {
   2973                         /* only internal default route exists */
   2974                         /* this should happen only if the lpm is a default route */
   2975                         bpm_pfx_len = 0;
   2976                     }
   2977                 } else {
   2978                     LOG_ERROR(BSL_LS_SOC_ALPM,
   2979                               (BSL_META_U(u,
   2980                                           "_soc_alpm_128_delete: Could not find"
   2981                                           " replacement bpm for prefix: 0x%08x 0x%08x "
   2982                                           "0x%08x 0x%08x\n"), prefix[1], prefix[2],
   2983                                prefix[3], prefix[4]));
   2984                     goto recover_pfx_trie;
   2985                 }
   2986 
   2987                 /* Initialize an lpm enty to perform a match */
   2988                 /* not expected to fail */
   2989                 sal_memcpy(prop_pfx, prefix, sizeof(prefix));
   2990                 ALPM_TRIE_TO_NORMAL_IP_128(prop_pfx, length, v6);
   2991                 (void) _soc_alpm_128_lpm_ent_key_init(u, prop_pfx, bpm_pfx_len, vrf, ipv6,
   2992                                         &lpm_entry, 0, 1);
   2993 
   2994                 /* Find Associated data for the bpm */
   2995                 rv = _soc_alpm_128_find(u, &lpm_entry, mem, bufp, &tcam_index,
   2996                                     &bucket_index, &key_index,
   2997                                     SOC_ALPM_SW_LOOKUP(u));
   2998 
   2999                 if (SOC_SUCCESS(rv)) {
   3000                     /* convert associated data to lpm entry format */
   3001                     (void) _soc_alpm_128_lpm_ent_init(u, bufp, mem, ipv6, vrf_id,
   3002                                                 bucket_index, 0, &lpm_entry, 0);
   3003 
   3004                     /* set key to the prefix being deleted */
   3005                     (void) _soc_alpm_128_lpm_ent_key_init(u, prop_pfx, length, vrf, ipv6,
   3006                                                &lpm_entry, 0, 0);
   3007 
   3008                     if (SOC_URPF_STATUS_GET(u)) {
   3009                         SOC_ALPM_ENTRY_BUF_128(v6, mem, sip_bufp, 0,
   3010                                                alpmv6_sip_entry);
   3011                         rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY,
   3012                                  _soc_alpm_rpf_entry(u, key_index), sip_bufp);
   3013                         if (soc_mem_field32_get(u, mem, sip_bufp, DEFAULTROUTEf)) {
   3014                             aux_flags |= SOC_ALPM_AUX_DEF_ROUTE;
   3015                         }
   3016                         if (soc_mem_field32_get(u, mem, sip_bufp, SRC_DISCARDf)) {
   3017                             aux_flags |= SOC_ALPM_AUX_SRC_DISCARD;
   3018                         }
   3019                     }
   3020 
   3021                 } else if (bpm_pfx_len == 0) {
   3022                     /* could not find a default route. Use internal default */
   3023                     /* default route's associated data */
   3024 
   3025                     lpm_key = VRF_TRIE_DEFAULT_ROUTE_IPV6_128(u, vrf);
   3026                     sal_memcpy(&lpm_entry, lpm_key, sizeof(lpm_entry));
   3027                     /* set key to the prefix being deleted */
   3028                     (void) _soc_alpm_128_lpm_ent_key_init(u, prop_pfx, length, vrf,
   3029                                                    ipv6, &lpm_entry, 0, 0);
   3030                     /* the sip ad does not matter here */
   3031                     rv = SOC_E_NONE;
   3032                 }
   3033 
   3034                 if (SOC_FAILURE(rv)) {
   3035                     LOG_ERROR(BSL_LS_SOC_ALPM,
   3036                               (BSL_META_U(u,
   3037                                           "_soc_alpm_128_delete: Could not find "
   3038                                           "replacement prefix for "
   3039                                           "prefix: 0x%08x 0x%08x 0x%08x 0x%08x "
   3040                                           "prop_pfx: 0x%08x 0x%08x 0x%08x 0x%08x "
   3041                                           "bmp_len %d\n"),
   3042                                           prefix[1], prefix[2], prefix[3], prefix[4],
   3043                                           prop_pfx[0], prop_pfx[1], prop_pfx[2], prop_pfx[3],
   3044                                           bpm_pfx_len));
   3045                     goto recover_pfx_trie;
   3046                 }
   3047 
   3048                 lpm_key = &lpm_entry;
   3049             }
   3050         } else { /* !default_route */
   3051             /* remove the real default route reference if any */
   3052             lpmp = NULL;
   3053             rv = trie_find_lpm(pfx_trie, prefix, length, &lpmp);
   3054             tmp_pyld = (payload_t *) lpmp;
   3055             if (SOC_FAILURE(rv)) {
   3056                 LOG_ERROR(BSL_LS_SOC_ALPM,
   3057                           (BSL_META_U(u,
   3058                                       "_soc_alpm_128_delete: Could not find "
   3059                                       "default route in the trie for vrf %d\n"), vrf));
   3060                 goto recover_bkt_trie;
   3061             }
   3062             tmp_pyld->bkt_ptr = 0;
   3063             bpm_pfx_len = 0;
   3064             lpm_key = VRF_TRIE_DEFAULT_ROUTE_IPV6_128(u, vrf);
   3065         }
   3066 
   3067         if (propagate) {
   3068             rv = _soc_alpm_128_fill_aux_entry_for_op(u, lpm_key, v6, db_type,
   3069                                             ent_type, bpm_pfx_len, &aux_entry);
   3070             if (SOC_FAILURE(rv)) {
   3071                 goto recover_pfx_trie;
   3072             }
   3073 
   3074             /* Perform Delete propagate */
   3075             rv = _soc_alpm_aux_op(u, DELETE_PROPAGATE, &aux_entry, TRUE, &hit,
   3076                                   &tcam_index, &bucket_index, aux_flags);
   3077 
   3078             if (SOC_FAILURE(rv)) {
   3079                 goto recover_pfx_trie;
   3080             }
   3081         }
   3082 
   3083         /* From here on don't try to recover trie state */
   3084         sal_free(payload);
   3085         if (!default_route) {
   3086             sal_free(pfx_pyld);
   3087         }
   3088 
   3089         /* For debug, update the pivot's counter */
   3090         PIVOT_BUCKET_ENT_CNT_UPDATE(pivot_pyld);
   3091 
   3092         if ((pivot_pyld->len != 0) && (trie->trie == NULL)) { /* Empty bucket */
   3093             uint32 hw_key[5];
   3094             sal_memcpy(hw_key, pivot_pyld->key, sizeof(hw_key));
   3095             ALPM_TRIE_TO_NORMAL_IP_128(hw_key, pivot_pyld->len, ipv6);
   3096             
   3097             /* Initialize an lpm entry to perform a match */
   3098             (void) _soc_alpm_128_lpm_ent_key_init(u, hw_key, pivot_pyld->len, vrf, ipv6,
   3099                                       &lpm_entry, 0, 1);
   3100 
   3101             /* delete entry from TCAM */
   3102             rv = soc_alpm_128_lpm_delete(u, &lpm_entry);
   3103             if (SOC_FAILURE(rv)) {
   3104                 LOG_ERROR(BSL_LS_SOC_ALPM,
   3105                           (BSL_META_U(u,
   3106                                       "_soc_alpm_128_delete: Unable to "
   3107                                       "delete pivot 0x%08x 0x%08x 0x%08x 0x%08x \n"),
   3108                            pivot_pyld->key[1], pivot_pyld->key[2],
   3109                            pivot_pyld->key[3], pivot_pyld->key[4]));
   3110                 /* continue to clean up still */
   3111             }
   3112         }
   3113 
   3114         /* Invalidate the route */
   3115         rv = _soc_alpm_delete_in_bkt(u, mem, delete_bucket, bank_disable, 
   3116                                      bufp2, e, &key_index, v6);
   3117         if (!SOC_SUCCESS(rv)) {
   3118             LOG_ERROR(BSL_LS_SOC_ALPM,
   3119                       (BSL_META_U(u,
   3120                                   "_soc_alpm_128_delete_in_bkt: Unable to "
   3121                                   "delete phy bkt 0x%08x \n"), delete_bucket));
   3122             SOC_ALPM_LPM_UNLOCK(u);
   3123             rv = SOC_E_FAIL;
   3124             return rv;
   3125         }
   3126 
   3127         /* delete corresponding RPF entry if it exists */
   3128         if (SOC_URPF_STATUS_GET(u)) {
   3129             /* hit is an unused variable */
   3130             rv = _soc_alpm_delete_in_bkt(u, mem,
   3131                                          SOC_ALPM_RPF_BKT_IDX(u, delete_bucket),
   3132                                          bank_disable,
   3133                                          bufp2, e, &hit, v6);
   3134             if (!SOC_SUCCESS(rv)) {
   3135                 LOG_ERROR(BSL_LS_SOC_ALPM,
   3136                           (BSL_META_U(u,
   3137                                       "_soc_alpm_128_delete_in_bkt: Unable to "
   3138                                       "delete phy bkt 0x%08x \n"), delete_bucket));
   3139                 SOC_ALPM_LPM_UNLOCK(u);
   3140                 rv = SOC_E_FAIL;
   3141                 return rv;
   3142             }
   3143         }
   3144 
   3145         if ((pivot_pyld->len != 0) && (trie->trie == NULL)) { /* Empty bucket */
   3146             /* Release Bucket */
   3147             rv = alpm_bucket_release(u, PIVOT_BUCKET_INDEX(pivot_pyld), v6);
   3148             if (SOC_FAILURE(rv)) {
   3149                 LOG_ERROR(BSL_LS_SOC_ALPM,
   3150                           (BSL_META_U(u,
   3151                                       "_soc_alpm_128_delete: Unable to release"
   3152                                       "empty bucket: %d\n"), PIVOT_BUCKET_INDEX(pivot_pyld)));
   3153                 /* we lose this bucket */
   3154             }
   3155 
   3156             /* remove pivot from pivot trie */
   3157             rv = trie_delete(pivot_trie, pivot_pyld->key, pivot_pyld->len, &delp);
   3158             if (SOC_FAILURE(rv)) {
   3159                 LOG_ERROR(BSL_LS_SOC_ALPM,
   3160                           (BSL_META_U(u,
   3161                                       "could not delete pivot from pivot trie\n")));
   3162             }
   3163 
   3164             /* Free up Bucket trie */
   3165             trie_destroy(PIVOT_BUCKET_TRIE(pivot_pyld));
   3166 
   3167             /* Free up Bucket handle */
   3168             sal_free(PIVOT_BUCKET_HANDLE(pivot_pyld));
   3169 
   3170             /* free Pivot structure */
   3171             sal_free(pivot_pyld);
   3172 
   3173 #ifdef CHECK_CLEAN_BKT
   3174             assert(_soc_alpm_128_bkt_count(u, mem, delete_bucket, bufp) 
   3175                                                                     == 0);
   3176 #endif /* CHECK_CLEAN_BKT */
   3177         }
   3178     }
   3179     VRF_TRIE_ROUTES_DEC(u, vrf_id, vrf, v6);
   3180     if (VRF_TRIE_ROUTES_CNT(u, vrf_id, vrf, v6) == 0) {
   3181         /* vrf is empty. Release resources */
   3182         rv = soc_alpm_128_vrf_delete(u, vrf, v6);
   3183     }
   3184     SOC_ALPM_LPM_UNLOCK(u);
   3185     return rv;
   3186 
   3187 /* Recovery from error: */
   3188     /* add back pivot bucket trie entry */
   3189     /* add back prefix trie entry */
   3190 recover_pfx_trie:
   3191     rv2 = trie_insert(pfx_trie, prefix, NULL, length, (trie_node_t *) 
   3192                      pfx_pyld);
   3193     if (SOC_FAILURE(rv2)) {
   3194         LOG_ERROR(BSL_LS_SOC_ALPM,
   3195                   (BSL_META_U(u,
   3196                               "_soc_alpm_128_delete: Unable to reinsert"
   3197                               "prefix 0x%08x 0x%08x 0x%08x 0x%08x into pfx trie\n"), 
   3198                    prefix[1], prefix[2], prefix[3], prefix[4]));
   3199     }
   3200 recover_bkt_trie:
   3201     rv2 = trie_insert(trie, prefix, NULL, length,  (trie_node_t *) payload);
   3202     if (SOC_FAILURE(rv2)) {
   3203         LOG_ERROR(BSL_LS_SOC_ALPM,
   3204                   (BSL_META_U(u,
   3205                               "_soc_alpm_128_delete: Unable to reinsert"
   3206                               "prefix 0x%08x 0x%08x 0x%08x 0x%08x into pfx trie\n"), 
   3207                    prefix[1], prefix[2], prefix[3], prefix[4]));
   3208     }
   3209     
   3210     SOC_ALPM_LPM_UNLOCK(u);
   3211     return rv;
   3212 }
   3213 
   3214 /* Initialize ALPM Subsytem */
   3215 int 
   3216 soc_alpm_128_init(int u)
   3217 {
   3218     int rv = SOC_E_NONE;
   3219 
   3220     /* Initialize TCAM Memory management */
   3221     rv = soc_alpm_128_lpm_init(u);
   3222     SOC_IF_ERROR_RETURN(rv);
   3223 
   3224     return rv;
   3225 }
   3226 
   3227 
   3228 /* clear only v6-128 alpm related internal state. Don't clean up common
   3229  * containing structures here. Allow v4/v6-64 clear code to do that
   3230  */
   3231 int soc_alpm_128_state_clear(int u)
   3232 {
   3233     int i, rv;
   3234     
   3235     /* clear all pivot state */
   3236     /* done in common code */
   3237 
   3238     /* clear all prefix tries */
   3239     for (i = 0; i <= SOC_VRF_MAX(u) + 1; i++) {
   3240         rv = trie_traverse(VRF_PREFIX_TRIE_IPV6_128(u, i), alpm_delete_node_cb,
   3241                            NULL, _TRIE_INORDER_TRAVERSE);
   3242         if (SOC_SUCCESS(rv)) {
   3243             trie_destroy(VRF_PREFIX_TRIE_IPV6_128(u, i));
   3244         } else {
   3245             LOG_ERROR(BSL_LS_SOC_ALPM,
   3246                       (BSL_META_U(u,
   3247                                   "unit: %d Unable to clear v6_128 pfx trie for "
   3248                                   "vrf %d\n"), u, i));
   3249             return rv;
   3250         }
   3251         if (VRF_TRIE_DEFAULT_ROUTE_IPV6_128(u, i) != NULL) {
   3252             sal_free(VRF_TRIE_DEFAULT_ROUTE_IPV6_128(u, i));
   3253         }
   3254     }
   3255     return SOC_E_NONE;
   3256 }
   3257 
   3258 /* De-Init ALPM Subsytem */
   3259 int 
   3260 soc_alpm_128_deinit(int u)
   3261 {
   3262     soc_alpm_128_lpm_deinit(u);
   3263 
   3264     SOC_IF_ERROR_RETURN(soc_alpm_128_state_clear(u));
   3265     return SOC_E_NONE;
   3266 }
   3267 
   3268 
   3269 /*
   3270  * soc_alpm_128_vrf_add
   3271  * Add a VRF default route when a L3 VRF is added
   3272  * Adds a 0.0 entry into VRF
   3273  */
   3274 static int
   3275 soc_alpm_128_vrf_add(int u, int vrf, int v6)
   3276 {
   3277     defip_pair_128_entry_t *lpm_entry = NULL, tmp_lpm;
   3278     int bucket_pointer;
   3279     int index;
   3280     int rv = SOC_E_NONE;
   3281     uint32 key[5] = {0, 0, 0, 0, 0};
   3282     uint32 length;
   3283     alpm_bucket_handle_t *bucket_handle = NULL;
   3284     alpm_pivot_t *pivot_pyld = NULL;
   3285     payload_t   *pfx_pyld = NULL;
   3286     trie_t  *prefix_root = NULL, *bucket_root = NULL;
   3287     int prefix_root_inserted = 0;
   3288     trie_t *pivot_root = NULL;
   3289     int pivot_root_inserted = 0;
   3290 
   3291     rv = soc_alpm_assign(u, vrf, L3_DEFIP_ALPM_IPV6_128m, &bucket_pointer, NULL);
   3292     if (SOC_FAILURE(rv)) {
   3293         return rv;
   3294     }
   3295 
   3296     /* Allocate bucket handle */
   3297     bucket_handle = sal_alloc(sizeof(alpm_bucket_handle_t), "ALPM Bucket Handle");
   3298     if (bucket_handle == NULL) {
   3299         LOG_ERROR(BSL_LS_SOC_ALPM,
   3300                   (BSL_META_U(u,
   3301                               "soc_alpm_128_vrf_add: Unable to allocate memory "
   3302                               "for bucket handle \n")));
   3303         rv = SOC_E_MEMORY;
   3304         goto cleanup;
   3305     }
   3306     sal_memset(bucket_handle, 0, sizeof(*bucket_handle));
   3307 
   3308     /* Allocate PIVOT Payload */
   3309     pivot_pyld = sal_alloc(sizeof(alpm_pivot_t), "Payload for Pivot");
   3310     if (pivot_pyld == NULL) {
   3311         LOG_ERROR(BSL_LS_SOC_ALPM,
   3312                   (BSL_META_U(u,
   3313                               "soc_alpm_128_vrf_add: Unable to allocate memory "
   3314                               "for PIVOT trie node \n")));
   3315         rv = SOC_E_MEMORY;
   3316         goto cleanup;
   3317     }
   3318     sal_memset(pivot_pyld, 0, sizeof(*pivot_pyld));
   3319     PIVOT_BUCKET_HANDLE(pivot_pyld) = bucket_handle;
   3320 
   3321     /* Allocate Prefix Payload */
   3322     pfx_pyld = sal_alloc(sizeof(payload_t), "Payload for pfx trie key");
   3323     if (pfx_pyld == NULL) {
   3324         LOG_ERROR(BSL_LS_SOC_ALPM,
   3325                   (BSL_META_U(u,
   3326                               "soc_alpm_128_vrf_add: Unable to allocate memory "
   3327                               "for pfx trie node \n")));
   3328         rv = SOC_E_MEMORY;
   3329         goto cleanup;
   3330     }
   3331 
   3332     sal_memset(pfx_pyld, 0, sizeof(*pfx_pyld));
   3333 
   3334     /* Initialize VRF PIVOT IPV6 trie */
   3335     rv = trie_init(_MAX_KEY_LEN_144_, &VRF_PIVOT_TRIE_IPV6_128(u, vrf));
   3336     pivot_root = VRF_PIVOT_TRIE_IPV6_128(u, vrf);
   3337     if (SOC_FAILURE(rv)) {
   3338         goto cleanup;
   3339     }
   3340     /* Initialize VRF PREFIX IPV6 trie */
   3341     rv = trie_init(_MAX_KEY_LEN_144_, &VRF_PREFIX_TRIE_IPV6_128(u, vrf));
   3342     prefix_root = VRF_PREFIX_TRIE_IPV6_128(u, vrf);
   3343     if (SOC_FAILURE(rv)) {
   3344         goto cleanup;
   3345     }
   3346 
   3347     /* Initialize BUCKET IPV6 trie */
   3348     rv = trie_init(_MAX_KEY_LEN_144_, &PIVOT_BUCKET_TRIE(pivot_pyld));
   3349     bucket_root = PIVOT_BUCKET_TRIE(pivot_pyld);
   3350     if (SOC_FAILURE(rv)) {
   3351         goto cleanup;
   3352     }
   3353     PIVOT_BUCKET_INDEX(pivot_pyld) = bucket_pointer;
   3354     PIVOT_BUCKET_VRF(pivot_pyld) = vrf;
   3355     PIVOT_BUCKET_IPV6(pivot_pyld) = v6;
   3356     PIVOT_BUCKET_DEF(pivot_pyld) = TRUE;
   3357 
   3358     /* 0 for default * route */
   3359     length = 0;
   3360     pivot_pyld->key[0] = pfx_pyld->key[0] = key[0];
   3361     pivot_pyld->key[1] = pfx_pyld->key[1] = key[1];
   3362     pivot_pyld->key[2] = pfx_pyld->key[2] = key[2];
   3363     pivot_pyld->key[3] = pfx_pyld->key[3] = key[3];
   3364     pivot_pyld->key[4] = pfx_pyld->key[4] = key[4];
   3365     pivot_pyld->len = pfx_pyld->len    = length;
   3366     rv = trie_insert(prefix_root, key, NULL, length, &(pfx_pyld->node));
   3367     /* no internal default in bucket trie */
   3368     if (SOC_FAILURE(rv)) {
   3369         goto cleanup;
   3370     }
   3371     prefix_root_inserted = 1;
   3372 
   3373     /* insert into trie of pivots */
   3374     rv = trie_insert(pivot_root, key, NULL, length, (trie_node_t *)pivot_pyld);
   3375     if (SOC_FAILURE(rv)) {
   3376         goto cleanup;
   3377     }
   3378     pivot_root_inserted = 1;
   3379 
   3380     /* Initialize an lpm entry to perform a match */
   3381     (void) _soc_alpm_128_lpm_ent_key_init(u, key, 0, vrf, v6, &tmp_lpm, 0, 1);
   3382 
   3383     /* for global VRF */
   3384     if (vrf == SOC_VRF_MAX(u) + 1) {
   3385         soc_L3_DEFIP_PAIR_128m_field32_set(u, &tmp_lpm, GLOBAL_ROUTEf, 1);
   3386     } else {
   3387         /* Set default miss to global route only for non global routes */
   3388         soc_L3_DEFIP_PAIR_128m_field32_set(u, &tmp_lpm, DEFAULT_MISSf, 1);
   3389     }
   3390     soc_L3_DEFIP_PAIR_128m_field32_set(u, &tmp_lpm, ENTRY_VIEWf,
   3391                                        VRF_FLEX_IS_SET(u, vrf, vrf, v6, 1));
   3392 
   3393     soc_L3_DEFIP_PAIR_128m_field32_set(u, &tmp_lpm, ALG_BKT_PTRf,
   3394                                        bucket_pointer);
   3395 
   3396     /* Allocate default lpm entry */
   3397     lpm_entry = sal_alloc(sizeof(*lpm_entry), "Default 128 LPM entry");
   3398     if (lpm_entry == NULL) {
   3399         LOG_ERROR(BSL_LS_SOC_ALPM,
   3400                   (BSL_META_U(u,
   3401                               "soc_alpm_128_vrf_add: unable to allocate memory "
   3402                               "for IPv6-128 LPM entry\n")));
   3403         rv = SOC_E_MEMORY;
   3404         goto cleanup;
   3405     }
   3406     sal_memcpy(lpm_entry, &tmp_lpm, sizeof(tmp_lpm));
   3407 
   3408     /* add Entry into tcam as default routes for the VRF */
   3409     /* urpf could modify the lpm entry. So use tmp one */
   3410     rv = soc_alpm_128_lpm_insert(u, &tmp_lpm, &index, 0, 0, INVALID_BPM_LEN);
   3411     if (SOC_FAILURE(rv)) {
   3412         goto cleanup;
   3413     }
   3414 
   3415     VRF_TRIE_DEFAULT_ROUTE_IPV6_128(u, vrf) = lpm_entry;
   3416     /* get physical index */
   3417     index = soc_alpm_physical_idx(u, L3_DEFIP_PAIR_128m, index, v6);
   3418     ALPM_TCAM_PIVOT(u, SOC_ALPM_128_ADDR_LWR(u, index) << 1) = pivot_pyld;
   3419     PIVOT_TCAM_INDEX(pivot_pyld) = SOC_ALPM_128_ADDR_LWR(u, index) << 1;
   3420     PIVOT_TCAM_BPMLEN(pivot_pyld) = length;
   3421 
   3422     VRF_TRIE_INIT_DONE(u, vrf, v6, 1);
   3423 
   3424     return SOC_E_NONE;
   3425 
   3426 cleanup:
   3427     if (lpm_entry) {
   3428         sal_free(lpm_entry);
   3429     }
   3430 
   3431     if (pivot_root_inserted) {
   3432         trie_node_t *delp = NULL;
   3433         (void) trie_delete(pivot_root, key, length, &delp);
   3434     }
   3435 
   3436     if (prefix_root_inserted) {
   3437         trie_node_t *delp = NULL;
   3438         (void) trie_delete(prefix_root, key, length, &delp);
   3439     }
   3440 
   3441     /* destroy inited tries */
   3442     if (bucket_root) {
   3443         (void) trie_destroy(bucket_root);
   3444         PIVOT_BUCKET_TRIE(pivot_pyld) = NULL;
   3445     }
   3446     if (prefix_root) {
   3447         (void) trie_destroy(prefix_root);
   3448         VRF_PREFIX_TRIE_IPV6_128(u, vrf) = NULL;
   3449     }
   3450     if (pivot_root) {
   3451         (void) trie_destroy(pivot_root);
   3452         VRF_PIVOT_TRIE_IPV6_128(u, vrf) = NULL;
   3453     }
   3454 
   3455     if (pfx_pyld) {
   3456         sal_free(pfx_pyld);
   3457     }
   3458     if (pivot_pyld) {
   3459         sal_free(pivot_pyld);
   3460     }
   3461     if (bucket_handle) {
   3462         sal_free(bucket_handle);
   3463     }
   3464 
   3465     (void) alpm_bucket_release(u, bucket_pointer, v6);
   3466     return rv;
   3467 }
   3468 
   3469 /*
   3470  * soc_alpm_vrf_delete
   3471  * Delete the VRF default route when a L3 VRF is destroyed 
   3472  */
   3473 static int
   3474 soc_alpm_128_vrf_delete(int u, int vrf, int v6)
   3475 {
   3476     defip_pair_128_entry_t *lpm_entry;
   3477     int bucket_pointer;
   3478     int idx;
   3479     int rv = SOC_E_NONE;
   3480     uint32 key[2] = {0, 0}, result[SOC_MAX_MEM_FIELD_WORDS];
   3481     payload_t *payload;
   3482     alpm_pivot_t *pivot_pyld1;
   3483     trie_node_t *delp;
   3484     trie_t  *root;
   3485     trie_t *pivot_root = NULL;
   3486 
   3487     lpm_entry = VRF_TRIE_DEFAULT_ROUTE_IPV6_128(u, vrf);
   3488 
   3489     /* find bucket pointers and release them */
   3490     bucket_pointer = soc_L3_DEFIP_PAIR_128m_field32_get(u, lpm_entry, 
   3491                                                         ALG_BKT_PTRf);
   3492     rv = alpm_bucket_release(u, bucket_pointer, v6);
   3493 
   3494     /* add Entry into tcam as default routes for the VRF */
   3495     rv = soc_alpm_128_lpm_match(u, lpm_entry, (void *) result, &idx);
   3496     if (SOC_FAILURE(rv)) {
   3497         LOG_ERROR(BSL_LS_SOC_ALPM,
   3498                   (BSL_META_U(u,
   3499                               "soc_alpm_vrf_delete: unable to get internal"
   3500                               " pivot idx for vrf %d/%d\n"), vrf, v6));
   3501         idx = -1;
   3502     }
   3503 
   3504     idx = soc_alpm_physical_idx(u, L3_DEFIP_PAIR_128m, idx, v6);
   3505     pivot_pyld1 = ALPM_TCAM_PIVOT(u, SOC_ALPM_128_ADDR_LWR(u, idx) << 1);
   3506 
   3507     rv = soc_alpm_128_lpm_delete(u, lpm_entry);
   3508     if (SOC_FAILURE(rv)) {
   3509         LOG_ERROR(BSL_LS_SOC_ALPM,
   3510                   (BSL_META_U(u,
   3511                               "soc_alpm_128_vrf_delete: unable to delete lpm "
   3512                               "entry for internal default for vrf %d/%d\n"), vrf, v6));
   3513     }
   3514 
   3515     sal_free(lpm_entry);
   3516 
   3517     VRF_TRIE_DEFAULT_ROUTE_IPV6_128(u, vrf)  = NULL;
   3518     root = VRF_PREFIX_TRIE_IPV6_128(u, vrf);
   3519     VRF_PREFIX_TRIE_IPV6_128(u, vrf) = NULL;
   3520     VRF_TRIE_INIT_DONE(u, vrf, v6, 0);
   3521 
   3522     rv = trie_delete(root, key, 0, &delp);
   3523     payload = (payload_t *) delp;
   3524     if (SOC_FAILURE(rv)) {
   3525         LOG_ERROR(BSL_LS_SOC_ALPM,
   3526                   (BSL_META_U(u,
   3527                               "Unable to delete internal default for 128b vrf "
   3528                               " %d/%d\n"), vrf, v6));
   3529     }
   3530     sal_free(payload);
   3531 
   3532     (void) trie_destroy(root);
   3533 
   3534     pivot_root = VRF_PIVOT_TRIE_IPV6_128(u, vrf);
   3535     VRF_PIVOT_TRIE_IPV6_128(u, vrf) = NULL;
   3536     
   3537     delp = NULL;
   3538     rv = trie_delete(pivot_root, key, 0, &delp);
   3539     if (SOC_FAILURE(rv)) {
   3540         LOG_ERROR(BSL_LS_SOC_ALPM,
   3541                   (BSL_META_U(u,
   3542                               "Unable to delete internal pivot node for vrf"
   3543                               " %d/%d\n"), vrf, v6)); 
   3544     }
   3545     (void) trie_destroy(pivot_root);
   3546 
   3547     (void) trie_destroy(PIVOT_BUCKET_TRIE(pivot_pyld1));
   3548     sal_free(PIVOT_BUCKET_HANDLE(pivot_pyld1));
   3549     sal_free(pivot_pyld1);
   3550 
   3551     return rv;
   3552 }
   3553 
   3554 /*
   3555  * soc_alpm_128_insert
   3556  * Moving multiple entries around in h/w vs  doing a linear search in s/w
   3557  */
   3558 int
   3559 soc_alpm_128_insert(int u, void *entry_data, uint32 flags, int bkt_idx,
   3560                     int pivot_info)
   3561 {
   3562     /* Search Result buffer */
   3563     defip_alpm_ipv6_128_entry_t alpmv6_entry, alpmv6_sip_entry; 
   3564     soc_mem_t mem;
   3565     void      *bufp, *bufp2;
   3566     int       vrf_id, vrf;
   3567     int       index;
   3568     int       ipv6;
   3569     int       rv = SOC_E_NONE; 
   3570     uint32    default_route;
   3571     int       ipmc_route = 0;
   3572 
   3573     ipv6 = L3_DEFIP_MODE_128;
   3574 
   3575     /* Get table memory. */
   3576     SOC_ALPM_TABLE_MEM_128(unit, ipv6, mem);
   3577  
   3578     /* Assign entry buf based on table being used */
   3579     SOC_ALPM_ENTRY_BUF_128(ipv6, mem, bufp, 0, alpmv6_entry);
   3580     SOC_ALPM_ENTRY_BUF_128(ipv6, mem, bufp2, 0, alpmv6_sip_entry);
   3581 
   3582     SOC_IF_ERROR_RETURN(
   3583         _soc_alpm_128_mem_ent_init(u, entry_data, bufp, bufp2, mem, flags,
   3584                                &default_route));
   3585 
   3586     /* If the entry is override, then insert into TCAM directly */
   3587     SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_vrf_get(u, entry_data, &vrf_id, &vrf));
   3588 
   3589     if (VRF_FLEX_COMPLETED(u, vrf_id, vrf, ipv6)) {
   3590         if (VRF_FLEX_IS_SET(u, vrf_id, vrf, ipv6, 1) != !!(flags & SOC_ALPM_STAT_FLEX)) {
   3591             LOG_ERROR(BSL_LS_SOC_ALPM,
   3592                       (BSL_META_U(u,
   3593                                   "soc_alpm_128_insert:Flex flag conflict\n"
   3594                                   )));
   3595             return SOC_E_PARAM;
   3596         }
   3597     } else {
   3598         VRF_FLEX_SET(u, vrf_id, vrf, ipv6, flags & SOC_ALPM_STAT_FLEX);
   3599     }
   3600 
   3601     if (soc_feature(u, soc_feature_ipmc_defip)) {
   3602         ipmc_route = soc_mem_field32_get(u, L3_DEFIP_PAIR_128m, 
   3603                                          entry_data, MULTICAST_ROUTEf);
   3604     }
   3605 
   3606     if ((vrf_id != SOC_L3_VRF_OVERRIDE) && (vrf == 0) && soc_alpm_mode_get(u)) {
   3607         /* cannot have 0 as a VRF in parallel mode */
   3608         LOG_ERROR(BSL_LS_SOC_ALPM,
   3609                   (BSL_META_U(u,
   3610                               "VRF=0 cannot be added in Parallel mode\n")));
   3611         return SOC_E_PARAM;
   3612     }
   3613 
   3614     /* For VRF_OVERRIDE (Global High) entries, and IPMC route
   3615      * software needs to maintain the index 
   3616      */
   3617     /* Prefix resides in TCAM directly */
   3618     if ((vrf_id == SOC_L3_VRF_OVERRIDE) || (ipmc_route)) {
   3619 
   3620         /* Insert into TCAM directly and return */
   3621         /* search in the hash table */
   3622         rv = soc_alpm_128_lpm_insert(u, entry_data, &index, 0,
   3623                                      flags & SOC_ALPM_RPF_SRC_DISCARD,
   3624                                      INVALID_BPM_LEN);
   3625         if (SOC_SUCCESS(rv) && !(pivot_info & SOC_ALPM_LPM_LOOKUP_HIT)) {
   3626             VRF_TRIE_ROUTES_INC(u, vrf_id, vrf, ipv6);
   3627         }
   3628         if (rv == SOC_E_FULL) {
   3629             VRF_PIVOT_FULL_INC(u, MAX_VRF_ID, ipv6);
   3630         }
   3631         return(rv);
   3632     }
   3633 
   3634     /* combined search mode protection */
   3635     if (vrf_id != SOC_L3_VRF_GLOBAL) {
   3636         if (!soc_alpm_mode_get(u)) {
   3637             /* for emtpy DB allow insert only if route is default */
   3638             if (VRF_TRIE_ROUTES_CNT(u, vrf_id, vrf, ipv6) == 0) {
   3639                 /* check if route is default, else throw error */
   3640                 if (!default_route) {
   3641                     LOG_ERROR(BSL_LS_SOC_ALPM,
   3642                               (BSL_META_U(u,
   3643                                           "VRF %d: First route in a VRF has to "
   3644                                           " be a default route in this mode\n"), vrf_id));
   3645                     return SOC_E_PARAM;
   3646                 }
   3647             }
   3648         }
   3649     }
   3650     
   3651     /* non override entries, goes into ALPM memory */
   3652     if (!VRF_TRIE_INIT_COMPLETED(u, vrf, ipv6)) {
   3653         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   3654                     (BSL_META_U(u,
   3655                                 "soc_alpm_128_insert:VRF %d is not "
   3656                                 "initialized\n"), vrf));
   3657         rv = soc_alpm_128_vrf_add(u, vrf, ipv6);
   3658         if (SOC_FAILURE(rv)) {
   3659             LOG_ERROR(BSL_LS_SOC_ALPM,
   3660                       (BSL_META_U(u,
   3661                                   "soc_alpm_128_insert:VRF %d/%d trie init \n"
   3662                                   "failed\n"), vrf, ipv6));
   3663             return rv;
   3664         }
   3665         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   3666                     (BSL_META_U(u,
   3667                                 "soc_alpm_128_insert:VRF %d/%d trie init "
   3668                                 "completed\n"), vrf, ipv6));
   3669     }
   3670 
   3671     /* Find and update the entry */
   3672     if (pivot_info & SOC_ALPM_LOOKUP_HIT) {
   3673         rv = _soc_alpm_128_find_and_update(u, entry_data, bufp, bufp2, mem, 
   3674                                            bkt_idx);
   3675     } else {
   3676         /* entry is not found in database */
   3677         /* Insert the entry into the database, if FULL, split the bucket */
   3678         /* Insert prefix into trie */
   3679         /* Split trie : Insertion into trie results into Split */
   3680         /* Allocate a TCAM entry for PIVOT and bucket and move entries */
   3681         if (bkt_idx == -1) {
   3682             /* internally 0 is invalid bucket index */
   3683             bkt_idx = 0;
   3684         }
   3685         rv = _soc_alpm_128_insert(u, entry_data, mem, bufp, bufp2, &index,
   3686                               SOC_ALPM_BKT_ENTRY_TO_IDX(bkt_idx), pivot_info);
   3687         if (SOC_SUCCESS(rv)) {
   3688             VRF_TRIE_ROUTES_INC(u, vrf_id, vrf, ipv6);
   3689         }
   3690     }
   3691 
   3692     if (rv != SOC_E_NONE) {
   3693         LOG_WARN(BSL_LS_SOC_ALPM,
   3694                  (BSL_META_U(u,
   3695                              "unit %d :soc_alpm_128_insert: "
   3696                              "Route Insertion Failed :%s\n"),
   3697                   u, soc_errmsg(rv)));
   3698     }
   3699     return(rv);
   3700 }
   3701 
   3702 
   3703 /*
   3704  * soc_alpm_lookup
   3705  * For IPV4 assume only both IP_ADDR0 is valid
   3706  * Moving multiple entries around in h/w vs  doing a linear search in s/w
   3707  */
   3708 int
   3709 soc_alpm_128_lookup(int u, 
   3710                 void *key_data,
   3711                 void *e,         /* return entry data if found */
   3712                 int *index_ptr,
   3713                 int *cookie)
   3714 {
   3715     defip_alpm_ipv6_128_entry_t alpmv6_entry; /* Search Result buffer */
   3716     soc_mem_t mem;
   3717     int       bucket_index;
   3718     int       tcam_index = -1;
   3719     void      *bufp;
   3720     int       vrf_id, vrf;
   3721     int       ipv6 = 2, pfx;
   3722     int       rv = SOC_E_NONE;
   3723     int       ipmc_route = 0;
   3724     int       flex;
   3725 
   3726     /* If the entry is override, then insert into TCAM directly */
   3727     SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   3728 
   3729     /* First launch lookup directly into tcam. If hit comes from override
   3730      * vrf just return it. Else launch lookup into alpm pivots
   3731      */
   3732     /* For VRF_OVERRIDE (Global High) entries, software needs to maintain the
   3733      * index */
   3734     /* Prefix resides in TCAM directly */
   3735     
   3736     /* search in the hash table */
   3737     *index_ptr = 0;
   3738     rv = _soc_alpm_128_lpm_match(u, key_data, e,
   3739                              index_ptr, &pfx, &ipv6);
   3740     /*
   3741      * If entry is ipv4 copy to the "zero" half of the, 
   3742      * buffer, "zero" half of lpm_entry if the  original entry
   3743      * is in the "one" half.
   3744      */
   3745     if (SOC_SUCCESS(rv)) {
   3746         if (soc_feature(u, soc_feature_ipmc_defip)) {
   3747             ipmc_route = soc_L3_DEFIP_PAIR_128m_field32_get(u, e, 
   3748                                                             MULTICAST_ROUTEf);
   3749         }
   3750     }
   3751     if ((vrf_id == SOC_L3_VRF_OVERRIDE) || (ipmc_route)) {
   3752         *cookie = 0;
   3753         if (SOC_SUCCESS(rv)) {
   3754             *cookie |= SOC_ALPM_LPM_LOOKUP_HIT;
   3755         }
   3756         return rv;
   3757     }
   3758 
   3759     /* either no hit in OVERRIDE or hit in pivot tcam */
   3760     /* non override entries, go to into ALPM memory */
   3761     if (!VRF_TRIE_INIT_COMPLETED(u, vrf, ipv6)) {
   3762         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   3763                     (BSL_META_U(u,
   3764                                 "soc_alpm_lookup:VRF %d is not "
   3765                                 "initialized\n"), vrf));
   3766         *index_ptr = 0;
   3767         *cookie = 0;
   3768         return SOC_E_NOT_FOUND;
   3769     }
   3770     /* Get table memory. */
   3771     SOC_ALPM_TABLE_MEM_128(u, ipv6, mem);
   3772  
   3773     /* Assign entry buf based on table being used */
   3774     SOC_ALPM_ENTRY_BUF_128(ipv6, mem, bufp, 0, alpmv6_entry);
   3775 
   3776     SOC_ALPM_LPM_LOCK(u);
   3777     /* Find and update the entry */
   3778     rv = _soc_alpm_128_find(u, key_data, mem, bufp, &tcam_index, &bucket_index, 
   3779                             index_ptr,
   3780                             SOC_ALPM_SW_LOOKUP(u));
   3781     SOC_ALPM_LPM_UNLOCK(u);
   3782 
   3783     if (SOC_FAILURE(rv)) {
   3784         *cookie = tcam_index;
   3785         *index_ptr = bucket_index << 2; 
   3786         return rv;
   3787     }
   3788     flex = VRF_FLEX_IS_SET(u, vrf_id, vrf, ipv6, 0);
   3789     /* Copy ALPM memory to LPM entry */
   3790     rv =  _soc_alpm_128_lpm_ent_init(u, bufp, mem, ipv6, vrf_id, 
   3791                                  bucket_index, *index_ptr, e, flex);
   3792     *cookie = SOC_ALPM_LOOKUP_HIT | tcam_index;
   3793     if (flex) {
   3794         *cookie |= SOC_ALPM_COOKIE_FLEX;
   3795     }
   3796     return(rv);
   3797 }
   3798 
   3799 /* Find a LPM Global low or VRF route in ALPM memory */ 
   3800 static int
   3801 _soc_alpm_128_find_best_match(int u, 
   3802                               void *key_data,
   3803                               void *e,      /* return entry data if found */
   3804                               int vrf_id,
   3805                               int *tcam_index,
   3806                               int *bucket_index, 
   3807                               int *key_index, 
   3808                               int do_urpf)
   3809 {
   3810     int rv = SOC_E_NONE;
   3811     int i, j, v6, hit = 0;
   3812     uint32 db_type, ent_type, bank_disable;
   3813     defip_aux_scratch_entry_t aux_entry;
   3814     int global, mvrf, vrf;
   3815     int index;
   3816     soc_mem_t mem, lpm_mem;
   3817     int hw_len, sw_len, ent_num;
   3818 
   3819     soc_field_t ip_addr_fld[4] = {
   3820         IP_ADDR0_LWRf,
   3821         IP_ADDR1_LWRf, 
   3822         IP_ADDR0_UPRf, 
   3823         IP_ADDR1_UPRf 
   3824     };    
   3825 
   3826     /* Used for keeping Longest Matched entry in Bucket */
   3827     uint32  alpm_bufp[SOC_MAX_MEM_FIELD_WORDS] = {0};
   3828     int     alpm_len = -1;
   3829     int     alpm_index = 0;
   3830     
   3831     v6 = L3_DEFIP_MODE_128;
   3832     lpm_mem = L3_DEFIP_PAIR_128m;
   3833     global = soc_mem_field32_get(u, lpm_mem, key_data, GLOBAL_ROUTEf);
   3834     mvrf = soc_mem_field32_get(u, lpm_mem, key_data, VRF_ID_0_LWRf);
   3835     vrf = (vrf_id == SOC_L3_VRF_GLOBAL) ? SOC_VRF_MAX(u) + 1 : mvrf;
   3836 
   3837     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   3838                 (BSL_META_U(u, "Prefare AUX Scratch for searching TCAM in "
   3839                 "%s region, Key data: v6 %d global %d vrf %d\n"), 
   3840                 vrf_id == SOC_L3_VRF_GLOBAL ? "Global" : "VRF",
   3841                 v6, global, mvrf));
   3842     soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
   3843     if (vrf_id == SOC_L3_VRF_GLOBAL) {
   3844         /* Crack these value to use _fill_aux routine */
   3845         soc_mem_field32_set(u, lpm_mem, key_data, GLOBAL_ROUTEf, 1);
   3846         soc_mem_field32_set(u, lpm_mem, key_data, VRF_ID_0_LWRf, 0);        
   3847     }
   3848     bank_disable = soc_alpm_bank_dis(u, vrf);
   3849 
   3850     if (do_urpf) {
   3851         db_type ++;
   3852     }
   3853 
   3854     SOC_IF_ERROR_RETURN(
   3855         _soc_alpm_128_fill_aux_entry_for_op(u, key_data, v6, db_type, ent_type,
   3856         0, &aux_entry));
   3857     /* Recover to original value */
   3858     if (vrf_id == SOC_L3_VRF_GLOBAL) {
   3859         soc_mem_field32_set(u, lpm_mem, key_data, GLOBAL_ROUTEf, global);
   3860         soc_mem_field32_set(u, lpm_mem, key_data, VRF_ID_0_LWRf, mvrf);
   3861     }
   3862 
   3863     /* Start shadow table engine to search */
   3864     SOC_IF_ERROR_RETURN(
   3865         _soc_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry, TRUE, &hit, tcam_index, 
   3866                          bucket_index, 0));
   3867     
   3868     if (hit == 0) {
   3869         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   3870                     (BSL_META_U(u, "Could not find bucket\n")));
   3871         return SOC_E_NOT_FOUND;
   3872     }
   3873 
   3874     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   3875                 (BSL_META_U(u, "Hit in memory %s, index %d, "
   3876                 "bucket_index %d\n"), SOC_MEM_NAME(u, lpm_mem), 
   3877                 soc_alpm_logical_idx(u, lpm_mem, 
   3878                     SOC_ALPM_128_DEFIP_TO_PAIR(u, (*tcam_index) >> 1), 1),
   3879                 *bucket_index));
   3880 
   3881     /* Found, check ALPM bucket */
   3882     mem = L3_DEFIP_ALPM_IPV6_128m;
   3883     rv = _soc_alpm_128_ip6_mask_len_get(u, key_data, &sw_len);
   3884     if (SOC_FAILURE(rv)) {
   3885         return rv;
   3886     }
   3887     ent_num = SOC_ALPM_V6_SCALE_CHECK(u, v6) ? 16 : 8;
   3888 
   3889     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   3890                 (BSL_META_U(u, "Start searching mem %s bucket %d(count %d) "
   3891                 "for Length %d\n"), 
   3892                 SOC_MEM_NAME(u, mem), *bucket_index, ent_num, sw_len));
   3893     
   3894     for (i = 0; i < ent_num; i++) {
   3895         uint32 bufp[SOC_MAX_MEM_FIELD_WORDS] = {0};
   3896         uint32 mask[4] = {0};
   3897         uint32 hkey[4] = {0};
   3898         uint32 skey[4] = {0};
   3899         int valid;
   3900         
   3901         rv = _soc_alpm_mem_index(u, mem, *bucket_index, i, bank_disable, &index);
   3902         if (rv == SOC_E_FULL) {
   3903             continue;
   3904         }
   3905 
   3906         SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY,
   3907                                                index, (void *)&bufp));
   3908         valid = soc_mem_field32_get(u, mem, &bufp, VALIDf);
   3909         hw_len = soc_mem_field32_get(u, mem, &bufp, LENGTHf);
   3910 
   3911         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   3912                     (BSL_META_U(u, "Bucket %5d Index %6d: Valid %d, Length %d\n"), 
   3913                     *bucket_index, index, valid, hw_len));
   3914 
   3915         if (!valid || (hw_len > sw_len)) {
   3916             continue;
   3917         }
   3918 
   3919         /* Length in ALPM <= given length */
   3920         SHR_BITSET_RANGE(mask, 128 - hw_len, hw_len);
   3921         (void)soc_mem_field_get(u, mem, (uint32 *)&bufp, KEYf, (uint32 *)hkey);
   3922         skey[3] = soc_mem_field32_get(u, lpm_mem, key_data, ip_addr_fld[3]);
   3923         skey[2] = soc_mem_field32_get(u, lpm_mem, key_data, ip_addr_fld[2]);
   3924         skey[1] = soc_mem_field32_get(u, lpm_mem, key_data, ip_addr_fld[1]);
   3925         skey[0] = soc_mem_field32_get(u, lpm_mem, key_data, ip_addr_fld[0]);
   3926 
   3927         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   3928                     (BSL_META_U(u, 
   3929                     "\tmask %08x %08x %08x %08x \n"
   3930                     "\t key %08x %08x %08x %08x \n"
   3931                     "\thost %08x %08x %08x %08x \n"), 
   3932                     mask[3], mask[2], mask[1], mask[0],
   3933                     hkey[3], hkey[2], hkey[1], hkey[0], 
   3934                     skey[3], skey[2], skey[1], skey[0]));
   3935         
   3936         for (j = 3; j >= 0; j--) {
   3937             if ((skey[j] & mask[j]) != (hkey[j] & mask[j])) {
   3938                 break;
   3939             }
   3940         }
   3941 
   3942         /* Hardware key doesn't match to software key */
   3943         if (j >= 0) {
   3944             continue;
   3945         }
   3946 
   3947         /* Matched, store and keep searching, 
   3948          * could be Longer prefix in following entries */
   3949         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   3950                     (BSL_META_U(u, "Found a match in mem %s bucket %d, "
   3951                     "index %d\n"), SOC_MEM_NAME(u, mem), *bucket_index, index));
   3952         
   3953         /* Keep longest matched route */
   3954         if (alpm_len == -1 || alpm_len < hw_len) {
   3955             alpm_len = hw_len;
   3956             alpm_index = index;            
   3957             sal_memcpy(alpm_bufp, bufp, sizeof(bufp));
   3958         }        
   3959     }
   3960 
   3961     /* Found */
   3962     if (alpm_len != -1) {
   3963         rv = _soc_alpm_128_lpm_ent_init(u, &alpm_bufp, mem, v6, vrf_id,
   3964                                         *bucket_index, alpm_index, e,
   3965                                         VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 0));
   3966         if (SOC_SUCCESS(rv)) {
   3967             *key_index = alpm_index;
   3968             if (bsl_check(bslLayerSoc, bslSourceAlpm, bslSeverityVerbose, u)) {
   3969                 LOG_VERBOSE(BSL_LS_SOC_ALPM,
   3970                             (BSL_META_U(u, "Hit mem %s bucket %d, index %d\n"), 
   3971                             SOC_MEM_NAME(u, mem), *bucket_index, alpm_index));
   3972             }
   3973         }
   3974         return rv;
   3975     }
   3976 
   3977     /* Miss in bucket, use associate data */
   3978     *key_index = soc_alpm_logical_idx(u, lpm_mem, 
   3979                     SOC_ALPM_128_DEFIP_TO_PAIR(u, (*tcam_index) >> 1), 1);
   3980     SOC_IF_ERROR_RETURN(
   3981         _soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY, *key_index, (void *)e));
   3982 
   3983     return SOC_E_NONE;
   3984 }
   3985 
   3986 /*
   3987  * soc_alpm_128_find_best_match
   3988  * 
   3989  * It's an indenpendent routine, to simalute HW process for incoming packets. 
   3990  * Considering possible mismatch between SW and HW, we need to go through 
   3991  * hardware for lookup regardless of software state.
   3992  */
   3993 int
   3994 soc_alpm_128_find_best_match(int u, 
   3995                              void *key_data,
   3996                              void *e,   /* return entry data if found */
   3997                              int *index_ptr,
   3998                              int do_urpf)
   3999 {
   4000     int rv = SOC_E_NONE;
   4001     int i, j; 
   4002     int index_min, index_cnt;
   4003     defip_pair_128_entry_t lpm128_ent;
   4004     uint32 hmsk, hkey, skey;
   4005     int hw_len, sw_len;
   4006     int global_hi, global_rt;
   4007     int vrf_id, vrf = 0;
   4008     int tcam_index, bucket_index;
   4009     soc_mem_t lpm_mem;
   4010 
   4011 #define ALPM_128_KEY_FIELD_NUM  4
   4012     soc_field_t msk_fld[ALPM_128_KEY_FIELD_NUM] = {
   4013         IP_ADDR_MASK1_UPRf, 
   4014         IP_ADDR_MASK0_UPRf, 
   4015         IP_ADDR_MASK1_LWRf, 
   4016         IP_ADDR_MASK0_LWRf
   4017     };
   4018     soc_field_t val_fld[ALPM_128_KEY_FIELD_NUM] = {
   4019         IP_ADDR1_UPRf, 
   4020         IP_ADDR0_UPRf, 
   4021         IP_ADDR1_LWRf, 
   4022         IP_ADDR0_LWRf
   4023     };
   4024 
   4025     lpm_mem = L3_DEFIP_PAIR_128m;
   4026     if (!SOC_URPF_STATUS_GET(u) && do_urpf) {
   4027         return SOC_E_PARAM;
   4028     }
   4029 
   4030     /* Since L3_DEFIP_* tables are not support for DMA, 
   4031      * we do PIO search instead */
   4032     index_min = soc_mem_index_min(u, lpm_mem);
   4033     index_cnt = soc_mem_index_count(u, lpm_mem);
   4034     if (SOC_URPF_STATUS_GET(u)) {
   4035         index_cnt >>= 1;
   4036     }
   4037     /* in Parallel mode search from second half */
   4038     if (soc_alpm_mode_get(u)) {
   4039         index_cnt >>= 1;
   4040         index_min += index_cnt;        
   4041     }
   4042 
   4043     if (do_urpf) {
   4044         index_min += soc_mem_index_count(u, lpm_mem) / 2;
   4045     }
   4046 
   4047     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   4048                 (BSL_META_U(u, "Start LPM searchng from %d, count %d\n"), 
   4049                 index_min, index_cnt));
   4050 
   4051     /* Searching for Global High routes */
   4052     for (i = index_min; i < index_min + index_cnt; i++) {
   4053         SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY, i,
   4054                             (void *)&lpm128_ent));
   4055 
   4056         if (!soc_mem_field32_get(u, lpm_mem, &lpm128_ent, VALID0_LWRf)) {
   4057             continue;
   4058         }
   4059 
   4060         /* Found, all Key matched */
   4061         global_hi = soc_mem_field32_get(u, lpm_mem, &lpm128_ent, GLOBAL_HIGHf);
   4062         global_rt = soc_mem_field32_get(u, lpm_mem, &lpm128_ent, GLOBAL_ROUTEf);
   4063         /* No need to compare key if not Global High route */
   4064         if (!global_rt || !global_hi) {
   4065             continue;
   4066         }
   4067 
   4068         rv = _soc_alpm_128_ip6_mask_len_get(u, key_data, &sw_len);
   4069         rv = _soc_alpm_128_ip6_mask_len_get(u, &lpm128_ent, &hw_len);
   4070         if (SOC_FAILURE(rv) || (hw_len > sw_len)) {
   4071             continue;
   4072         }
   4073 
   4074         for (j = 0; j < ALPM_128_KEY_FIELD_NUM; j++) {
   4075             hmsk = soc_mem_field32_get(u, lpm_mem, &lpm128_ent, msk_fld[j]);
   4076             hkey = soc_mem_field32_get(u, lpm_mem, &lpm128_ent, val_fld[j]);
   4077             skey = soc_mem_field32_get(u, lpm_mem, key_data, val_fld[j]);
   4078             if ((skey & hmsk) != (hkey & hmsk)) {
   4079                 break;
   4080             }
   4081         }
   4082 
   4083         /* Not match */
   4084         if (j < ALPM_128_KEY_FIELD_NUM) {
   4085             continue;
   4086         }
   4087 
   4088         /* Found, all Key matched */
   4089         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   4090                     (BSL_META_U(u, "Hit Global High route in index = %d\n"), j));
   4091         sal_memcpy(e, &lpm128_ent, sizeof(lpm128_ent));
   4092         *index_ptr = i;
   4093         return SOC_E_NONE;
   4094     }
   4095 
   4096     /* Global High lookup miss, use AUX to search Global Low and VRF route */
   4097     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   4098                 (BSL_META_U(u, "Global high lookup miss, use AUX engine to "
   4099                 "search for Global Low and VRF routes\n")));
   4100     
   4101     /* Fill in AUX Scratch and perform PREFIX Operation */
   4102     SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   4103     rv = _soc_alpm_128_find_best_match(u, key_data, e, vrf_id, &tcam_index,
   4104                                        &bucket_index, index_ptr, do_urpf);
   4105     if (rv == SOC_E_NOT_FOUND) {
   4106         vrf = SOC_L3_VRF_GLOBAL;
   4107         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   4108                     (BSL_META_U(u, "Not found in VRF region, try Global "
   4109                     "region\n")));
   4110         rv = _soc_alpm_128_find_best_match(u, key_data, e, vrf_id, &tcam_index,
   4111                                            &bucket_index, index_ptr, do_urpf);
   4112     }
   4113 
   4114     if (SOC_SUCCESS(rv)) {
   4115         tcam_index = soc_alpm_logical_idx(u, lpm_mem, 
   4116                         SOC_ALPM_128_DEFIP_TO_PAIR(u, tcam_index >> 1), 1);
   4117         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   4118                     (BSL_META_U(u, "Hit in %s region in TCAM index %d, "
   4119                     "buckekt_index %d\n"), 
   4120                     vrf == SOC_L3_VRF_GLOBAL ? "Global Low" : "VRF", 
   4121                     tcam_index, bucket_index));
   4122     } else {
   4123         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   4124                     (BSL_META_U(u, "Search miss for given address\n")));
   4125     }
   4126 
   4127     return(rv);
   4128 }
   4129 
   4130 /*
   4131  * soc_alpm_delete
   4132  */
   4133 int
   4134 soc_alpm_128_delete(int u, void *key_data, int bkt_idx, int pivot_info)
   4135 {
   4136     int       vrf_id, vrf;
   4137     int       ipv6;
   4138     int       rv = SOC_E_NONE;
   4139     int       propagate = 0;
   4140     int       ipmc_route = 0;
   4141 
   4142     ipv6 = L3_DEFIP_MODE_128;
   4143 
   4144     if (soc_feature(u, soc_feature_ipmc_defip)) {
   4145         ipmc_route = soc_mem_field32_get(u, L3_DEFIP_PAIR_128m, 
   4146                                           key_data, MULTICAST_ROUTEf);
   4147     }
   4148     /* If the entry is override, then Lookup into TCAM directly */
   4149     SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   4150     /* For VRF_OVERRIDE (Global High) entries, and IPMC route
   4151      * software needs to maintain the index 
   4152      */
   4153     /* Prefix resides in TCAM directly */
   4154     if ((vrf_id == SOC_L3_VRF_OVERRIDE) || (ipmc_route)) {
   4155         /* TCAM Direct lookup */
   4156         /* search in the hash table */
   4157         rv = soc_alpm_128_lpm_delete(u, key_data);
   4158         if (SOC_SUCCESS(rv)) {
   4159             VRF_TRIE_ROUTES_DEC(u, vrf_id, vrf, ipv6);
   4160         }
   4161         return(rv);
   4162     } else { /* non override entries, go to into ALPM memory */
   4163         int tcam_index;
   4164         if (!VRF_TRIE_INIT_COMPLETED(u, vrf, ipv6)) {
   4165             LOG_VERBOSE(BSL_LS_SOC_ALPM,
   4166                         (BSL_META_U(u,
   4167                                     "soc_alpm_128_delete:VRF %d/%d is not "
   4168                                     "initialized\n"), vrf, ipv6));
   4169             return SOC_E_NONE;
   4170         }
   4171         if (bkt_idx == -1) {
   4172             /* internally 0 is invalid bucket index */
   4173             bkt_idx = 0;
   4174         }
   4175         /* deleting all skip propagation to reduce overall time */
   4176         propagate = !(pivot_info & SOC_ALPM_DELETE_ALL);
   4177         tcam_index = pivot_info & SOC_ALPM_TCAM_INDEX_MASK;
   4178         rv = _soc_alpm_128_delete(u, key_data, 
   4179                                   SOC_ALPM_BKT_ENTRY_TO_IDX(bkt_idx),
   4180                                   tcam_index, bkt_idx,
   4181                                   propagate);
   4182     }
   4183     return(rv);
   4184 }
   4185 
   4186 /**********************************************
   4187 * TCAM Management functions *
   4188  */
   4189 
   4190 /*
   4191  * TCAM based PIVOT implementation. Each table entry can hold two IPV4 PIVOTs or
   4192  * one IPV6 PIVOT entry. VRF independent routes placed at the beginning or 
   4193  * at the end of table based on application provided entry vrf id 
   4194  * (SOC_L3_VRF_OVERRIDE/SOC_L3_VRF_GLOBAL).   
   4195  *
   4196  *              ALPM_MAX_PFX_INDEX
   4197  * lpm_prefix_index[98].begin ---> ===============================
   4198  *                                 ==                           ==
   4199  *                                 ==    0                      ==
   4200  * lpm_prefix_index[98].end   ---> ===============================
   4201  *
   4202  * lpm_prefix_index[97].begin ---> ===============================
   4203  *                                 ==                           ==
   4204  *                                 ==    IPV6  Prefix Len = 64  ==
   4205  * lpm_prefix_index[97].end   ---> ===============================
   4206  *
   4207  *
   4208  *
   4209  * lpm_prefix_index[x].begin --->  ===============================
   4210  *                                 ==                           ==
   4211  *                                 ==                           ==
   4212  * lpm_prefix_index[x].end   --->  ===============================
   4213  *
   4214  *
   4215  *              ALPM_IPV6_PFX_ZERO
   4216  * lpm_prefix_index[33].begin ---> ===============================
   4217  *                                 ==                           ==
   4218  *                                 ==    IPV6  Prefix Len = 0   ==
   4219  * lpm_prefix_index[33].end   ---> ===============================
   4220  *
   4221  *
   4222  * lpm_prefix_index[32].begin ---> ===============================
   4223  *                                 ==                           ==
   4224  *                                 ==    IPV4  Prefix Len = 32  ==
   4225  * lpm_prefix_index[32].end   ---> ===============================
   4226  *
   4227  *
   4228  *
   4229  * lpm_prefix_index[0].begin --->  ===============================
   4230  *                                 ==                           ==
   4231  *                                 ==    IPV4  Prefix Len = 0   ==
   4232  * lpm_prefix_index[0].end   --->  ===============================
   4233  */
   4234 
   4235 
   4236 /*
   4237  *      Extract key data from an entry at the given index.
   4238  */
   4239 static
   4240 void _soc_alpm_128_lpm_hash_entry_get(int u, void *e,
   4241                              int index, _soc_alpm_128_lpm_hash_entry_t r_entry,
   4242                              int *v)
   4243 {
   4244     SOC_FB_LPM_128_HASH_ENTRY_GET_IPV6(u, e, r_entry);
   4245     if (v) {
   4246         *v = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, e, VALID0_LWRf) &&
   4247              SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, e, VALID1_LWRf) &&
   4248              SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, e, VALID0_UPRf) &&
   4249              SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, e, VALID1_UPRf);
   4250     }
   4251 }
   4252 
   4253 /*
   4254  * Function:
   4255  *      _soc_alpm_128_lpm_hash_compare_key
   4256  * Purpose:
   4257  *      Comparison function for AVL shadow table operations.
   4258  */
   4259 static
   4260 int _soc_alpm_128_lpm_hash_compare_key(_soc_alpm_128_lpm_hash_entry_t key1,
   4261                                  _soc_alpm_128_lpm_hash_entry_t key2)
   4262 {
   4263     int idx;
   4264 
   4265     for (idx = 0; idx < 9; idx++) { 
   4266         SOC_MEM_128_COMPARE_RETURN(key1[idx], key2[idx]);
   4267     }
   4268     return (0);
   4269 }
   4270 
   4271 #ifdef FB_LPM_DEBUG      
   4272 #define H_INDEX_MATCH_128(str, tab_index, match_index)      \
   4273     LOG_ERROR(BSL_LS_SOC_ALPM, \
   4274               (BSL_META("%s index: H %d A %d\n"),                      \
   4275                str, (int)tab_index, match_index))
   4276 #else
   4277 #define H_INDEX_MATCH_128(str, tab_index, match_index)
   4278 #endif
   4279 
   4280 #define LPM_128_NO_MATCH_INDEX 0x4000
   4281 #define LPM_128_HASH_INSERT(u, entry_data, tab_index, rvt_index)       \
   4282     soc_alpm_128_lpm_hash_insert(u, entry_data, tab_index, \
   4283                             LPM_128_NO_MATCH_INDEX, 0, rvt_index)
   4284 
   4285 #define LPM_128_HASH_REVERT(u, entry_data, tab_index, rvt_index)       \
   4286     soc_alpm_128_lpm_hash_revert(u, entry_data, tab_index, rvt_index)
   4287 
   4288 #define LPM_128_HASH_DELETE(u, key_data, tab_index)         \
   4289     soc_alpm_128_lpm_hash_delete(u, key_data, tab_index)
   4290 
   4291 #define LPM_128_HASH_LOOKUP(u, key_data, pfx, tab_index)    \
   4292     soc_alpm_128_lpm_hash_lookup(u, key_data, pfx, tab_index)
   4293 
   4294 #define LPM_128_HASH_VERIFY(u, key_data, tab_index)    \
   4295     soc_alpm_128_lpm_hash_verify(u, key_data, tab_index)
   4296 
   4297 #define INDEX_DELETE_128(hash, hash_idx, del_idx)                   \
   4298     hash->table[hash_idx] =                                     \
   4299         hash->link_table[del_idx & TD2_ALPM_128_HASH_INDEX_MASK];     \
   4300     hash->link_table[del_idx & TD2_ALPM_128_HASH_INDEX_MASK] =        \
   4301         TD2_ALPM_128_HASH_INDEX_NULL
   4302 
   4303 #define INDEX_DELETE_LINK_128(hash, prev_idx, del_idx)              \
   4304     hash->link_table[prev_idx & TD2_ALPM_128_HASH_INDEX_MASK] =       \
   4305         hash->link_table[del_idx & TD2_ALPM_128_HASH_INDEX_MASK];     \
   4306     hash->link_table[del_idx & TD2_ALPM_128_HASH_INDEX_MASK] =        \
   4307         TD2_ALPM_128_HASH_INDEX_NULL
   4308 
   4309 
   4310 static
   4311 void soc_alpm_128_lpm_hash_insert(int u, void *entry_data, uint32 tab_index,
   4312                             uint32 old_index, int pfx, uint32 *rvt_index)
   4313 {
   4314     _soc_alpm_128_lpm_hash_entry_t    key_hash;
   4315 
   4316     /* IPV6 entry */
   4317     if (SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, entry_data, 
   4318                                 VALID1_LWRf) &&
   4319         SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, entry_data, 
   4320                                 VALID0_LWRf) &&
   4321         SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, entry_data, 
   4322                                 VALID1_UPRf) &&
   4323         SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, entry_data, 
   4324                                 VALID0_UPRf)) {
   4325         SOC_FB_LPM_128_HASH_ENTRY_GET_IPV6(u, entry_data, key_hash);
   4326         _soc_alpm_128_lpm_hash_insert(
   4327                     SOC_ALPM_128_LPM_STATE_HASH(u),
   4328                     _soc_alpm_128_lpm_hash_compare_key,
   4329                     key_hash,
   4330                     pfx,
   4331                     old_index,
   4332                     tab_index,
   4333                     rvt_index);
   4334     }
   4335 }
   4336 
   4337 
   4338 
   4339 static
   4340 void soc_alpm_128_lpm_hash_revert(int u, void *entry_data, uint32 tab_index,
   4341                                   uint32 rvt_index)
   4342 {
   4343     _soc_alpm_128_lpm_hash_entry_t    key_hash;
   4344 
   4345     /* IPV6 entry */
   4346     if (SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, entry_data, 
   4347                                 VALID1_LWRf) &&
   4348         SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, entry_data, 
   4349                                 VALID0_LWRf) &&
   4350         SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, entry_data, 
   4351                                 VALID1_UPRf) &&
   4352         SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, entry_data, 
   4353                                 VALID0_UPRf)) {
   4354         SOC_FB_LPM_128_HASH_ENTRY_GET_IPV6(u, entry_data, key_hash);
   4355         _soc_alpm_128_lpm_hash_revert(
   4356                     SOC_ALPM_128_LPM_STATE_HASH(u),
   4357                     _soc_alpm_128_lpm_hash_compare_key,
   4358                     key_hash,
   4359                     tab_index,
   4360                     rvt_index);
   4361     }
   4362 }
   4363 
   4364 static
   4365 void soc_alpm_128_lpm_hash_delete(int u, void *key_data, uint32 tab_index)
   4366 {
   4367     _soc_alpm_128_lpm_hash_entry_t    key_hash;
   4368     int                         pfx = -1;
   4369     int                         rv;
   4370     uint16                      index;
   4371 
   4372     SOC_FB_LPM_128_HASH_ENTRY_GET_IPV6(u, key_data, key_hash);
   4373     index = tab_index;
   4374 
   4375     rv = _soc_alpm_128_lpm_hash_delete(SOC_ALPM_128_LPM_STATE_HASH(u),
   4376                                  _soc_alpm_128_lpm_hash_compare_key,
   4377                                  key_hash, pfx, index);
   4378     if (SOC_FAILURE(rv)) {
   4379         LOG_ERROR(BSL_LS_SOC_ALPM,
   4380                   (BSL_META_U(u,
   4381                               "\ndel  index: H %d error %d\n"), index, rv));
   4382     }
   4383 }
   4384 
   4385 static
   4386 int soc_alpm_128_lpm_hash_lookup(int u, void *key_data, int pfx, int *key_index)
   4387 {
   4388     _soc_alpm_128_lpm_hash_entry_t    key_hash;
   4389     int rv;
   4390     uint16  index = TD2_ALPM_128_HASH_INDEX_NULL;
   4391 
   4392     SOC_FB_LPM_128_HASH_ENTRY_GET_IPV6(u, key_data, key_hash);
   4393 
   4394     rv = _soc_alpm_128_lpm_hash_lookup(SOC_ALPM_128_LPM_STATE_HASH(u),
   4395                                        _soc_alpm_128_lpm_hash_compare_key,
   4396                                        key_hash, pfx, &index);
   4397     if (SOC_FAILURE(rv)) {
   4398         *key_index = 0xFFFFFFFF;
   4399         return(rv);
   4400     }
   4401 
   4402     *key_index = index;
   4403 
   4404     return(SOC_E_NONE);
   4405 }
   4406 
   4407 static
   4408 int soc_alpm_128_lpm_hash_verify(int u, void *key_data, uint32 tab_index)
   4409 {
   4410     _soc_alpm_128_lpm_hash_entry_t    key_hash;
   4411     int                         pfx = -1;
   4412     int                         rv;
   4413     uint16                      index;
   4414 
   4415     SOC_FB_LPM_128_HASH_ENTRY_GET_IPV6(u, key_data, key_hash);
   4416     index = tab_index;
   4417 
   4418     rv = _soc_alpm_128_lpm_hash_verify(SOC_ALPM_128_LPM_STATE_HASH(u),
   4419                                        _soc_alpm_128_lpm_hash_compare_key,
   4420                                        key_hash, pfx, index);
   4421     if (SOC_FAILURE(rv)) {
   4422         LOG_ERROR(BSL_LS_SOC_ALPM,
   4423                   (BSL_META_U(u,
   4424                               "\nveri index: H %d error %d\n"), index, rv));
   4425     }
   4426     return rv;
   4427 }
   4428 
   4429 
   4430 /* 
   4431  * Function:
   4432  *      _soc_alpm_128_lpm_hash_compute
   4433  * Purpose:
   4434  *      Compute CRC hash for key data.
   4435  * Parameters:
   4436  *      data - Key data
   4437  *      data_nbits - Number of data bits
   4438  * Returns:
   4439  *      Computed 16 bit hash
   4440  */
   4441 static
   4442 uint16 _soc_alpm_128_lpm_hash_compute(uint8 *data, int data_nbits)
   4443 {
   4444     return (_shr_crc16b(0, data, data_nbits));
   4445 }
   4446 
   4447 /* 
   4448  * Function:
   4449  *      _soc_alpm_128_lpm_hash_create
   4450  * Purpose:
   4451  *      Create an empty hash table
   4452  * Parameters:
   4453  *      unit  - Device unit
   4454  *      entry_count - Limit for number of entries in table
   4455  *      index_count - Hash index max + 1. (index_count <= count)
   4456  *      fb_lpm_hash_ptr - Return pointer (handle) to new Hash Table
   4457  * Returns:
   4458  *      SOC_E_NONE       Success
   4459  *      SOC_E_MEMORY     Out of memory (system allocator)
   4460  */
   4461 
   4462 static
   4463 int _soc_alpm_128_lpm_hash_create(int unit,
   4464                             int entry_count,
   4465                             int index_count,
   4466                             _soc_alpm_128_lpm_hash_t **fb_lpm_hash_ptr)
   4467 {
   4468     _soc_alpm_128_lpm_hash_t  *hash;
   4469     int                 index;
   4470 
   4471     if (index_count > entry_count) {
   4472         return SOC_E_MEMORY;
   4473     }
   4474     hash = sal_alloc(sizeof (_soc_alpm_128_lpm_hash_t), "lpm_hash");
   4475     if (hash == NULL) {
   4476         return SOC_E_MEMORY;
   4477     }
   4478 
   4479     sal_memset(hash, 0, sizeof (*hash));
   4480 
   4481     hash->unit = unit;
   4482     hash->entry_count = entry_count;
   4483     hash->index_count = index_count;
   4484 
   4485     /*
   4486      * Pre-allocate the hash table storage.
   4487      */
   4488     hash->table = sal_alloc(hash->index_count * sizeof(*(hash->table)),
   4489                             "hash_table");
   4490 
   4491     if (hash->table == NULL) {
   4492         sal_free(hash);
   4493         return SOC_E_MEMORY;
   4494     }
   4495     /*
   4496      * In case where all the entries should hash into the same bucket
   4497      * this will prevent the hash table overflow
   4498      */
   4499     hash->link_table = sal_alloc(
   4500                             hash->entry_count * sizeof(*(hash->link_table)),
   4501                             "link_table");
   4502     if (hash->link_table == NULL) {
   4503         sal_free(hash->table);
   4504         sal_free(hash);
   4505         return SOC_E_MEMORY;
   4506     }
   4507 
   4508     /*
   4509      * Set the entries in the hash table to TD2_ALPM_128_HASH_INDEX_NULL
   4510      * Link the entries beyond hash->index_max for handling collisions
   4511      */
   4512     for(index = 0; index < hash->index_count; index++) {
   4513         hash->table[index] = TD2_ALPM_128_HASH_INDEX_NULL;
   4514     }
   4515     for(index = 0; index < hash->entry_count; index++) {
   4516         hash->link_table[index] = TD2_ALPM_128_HASH_INDEX_NULL;
   4517     }
   4518     *fb_lpm_hash_ptr = hash;
   4519     return SOC_E_NONE;
   4520 }
   4521 
   4522 /* 
   4523  * Function:
   4524  *      _soc_alpm_128_lpm_hash_destroy
   4525  * Purpose:
   4526  *      Destroy the hash table
   4527  * Parameters:
   4528  *      fb_lpm_hash - Pointer (handle) to Hash Table
   4529  * Returns:
   4530  *      SOC_E_NONE       Success
   4531  */
   4532 static
   4533 int _soc_alpm_128_lpm_hash_destroy(_soc_alpm_128_lpm_hash_t *fb_lpm_hash)
   4534 {
   4535     if (fb_lpm_hash != NULL) {
   4536         sal_free(fb_lpm_hash->table);
   4537         sal_free(fb_lpm_hash->link_table);
   4538         sal_free(fb_lpm_hash);
   4539     }
   4540 
   4541     return SOC_E_NONE;
   4542 }
   4543 
   4544 /*
   4545  * Function:
   4546  *      _soc_alpm_128_lpm_hash_lookup
   4547  * Purpose:
   4548  *      Look up a key in the hash table
   4549  * Parameters:
   4550  *      hash - Pointer (handle) to Hash Table
   4551  *      key_cmp_fn - Compare function which should compare key
   4552  *      entry   - The key to lookup
   4553  *      pfx     - Prefix length for lookup acceleration.
   4554  *      key_index - (OUT)       Index where the key was found.
   4555  * Returns:
   4556  *      SOC_E_NONE      Key found
   4557  *      SOC_E_NOT_FOUND Key not found
   4558  */
   4559 
   4560 static
   4561 int _soc_alpm_128_lpm_hash_lookup(_soc_alpm_128_lpm_hash_t *hash,
   4562                             _soc_alpm_128_lpm_hash_compare_fn key_cmp_fn,
   4563                             _soc_alpm_128_lpm_hash_entry_t entry, int pfx,
   4564                             uint16 *key_index)
   4565 {
   4566     int u = hash->unit, v, i = 0;
   4567 
   4568     uint16 hash_val;
   4569     uint16 index;
   4570 
   4571     hash_val = _soc_alpm_128_lpm_hash_compute((uint8 *)entry,
   4572                                         (32 * 9)) % hash->index_count;
   4573     index = hash->table[hash_val];
   4574     H_INDEX_MATCH_128("lhash", entry[0], hash_val);
   4575     H_INDEX_MATCH_128("lkup ", entry[0], index);
   4576     while(index != TD2_ALPM_128_HASH_INDEX_NULL && i++ < hash->entry_count) {
   4577         uint32  e[SOC_MAX_MEM_FIELD_WORDS];
   4578         _soc_alpm_128_lpm_hash_entry_t  r_entry;
   4579         int     rindex;
   4580 
   4581         rindex = index; 
   4582         /*
   4583          * Check prefix length and skip index if not valid for given length
   4584         if ((SOC_ALPM_LPM_STATE_START(u, pfx) <= rindex) &&
   4585             (SOC_ALPM_LPM_STATE_END(u, pfx) >= rindex)) {
   4586          */
   4587         SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIP_PAIR_128m,
   4588                                                MEM_BLOCK_ANY, rindex, e));
   4589         SOC_FB_LPM_128_HASH_ENTRY_GET(u, e, index, r_entry, &v);
   4590         if (v == 0) {
   4591             LOG_ERROR(BSL_LS_SOC_ALPM,
   4592                       (BSL_META_U(u,
   4593                                 "Empty entry[%d] in link_table. hash_val %d ridx %d \n"),
   4594                                 index, hash_val, rindex));
   4595         }
   4596         if ((*key_cmp_fn)(entry, r_entry) == 0) {
   4597             *key_index = index;
   4598             H_INDEX_MATCH_128("found", entry[0], index);
   4599             return(SOC_E_NONE);
   4600         }
   4601         /*
   4602         }
   4603         */
   4604         index = hash->link_table[index & TD2_ALPM_128_HASH_INDEX_MASK];
   4605         H_INDEX_MATCH_128("lkup1", entry[0], index);
   4606     }
   4607     if (i > hash->entry_count) {
   4608         LOG_ERROR(BSL_LS_SOC_ALPM,
   4609                   (BSL_META_U(u,
   4610                             "Hash loop\n")));
   4611     }
   4612     H_INDEX_MATCH_128("not_found", entry[0], index);
   4613     return(SOC_E_NOT_FOUND);
   4614 }
   4615 
   4616 /*
   4617  * Function:
   4618  *      _soc_alpm_128_lpm_hash_insert
   4619  * Purpose:
   4620  *      Insert/Update a key index in the hash table
   4621  * Parameters:
   4622  *      hash - Pointer (handle) to Hash Table
   4623  *      key_cmp_fn - Compare function which should compare key
   4624  *      entry   - The key to lookup
   4625  *      pfx     - Prefix length for lookup acceleration.
   4626  *      old_index - Index where the key was moved from.
   4627  *                  TD2_ALPM_128_HASH_INDEX_NULL if new entry.
   4628  *      new_index - Index where the key was moved to.
   4629  * Returns:
   4630  *      SOC_E_NONE      Key found
   4631  */
   4632 /*
   4633  *      Should be caled before updating the LPM table so that the
   4634  *      data in the hash table is consistent with the LPM table
   4635  */
   4636 static
   4637 int _soc_alpm_128_lpm_hash_insert(_soc_alpm_128_lpm_hash_t *hash,
   4638                             _soc_alpm_128_lpm_hash_compare_fn key_cmp_fn,
   4639                             _soc_alpm_128_lpm_hash_entry_t entry,
   4640                             int    pfx,
   4641                             uint16 old_index,
   4642                             uint16 new_index,
   4643                             uint32 *rvt_index)
   4644 {
   4645 
   4646 #define INDEX_ADD_128(hash, hash_idx, new_idx)                      \
   4647     hash->link_table[new_idx & TD2_ALPM_128_HASH_INDEX_MASK] =        \
   4648         hash->table[hash_idx];                                  \
   4649     hash->table[hash_idx] = new_idx
   4650 
   4651 #define INDEX_ADD_LINK_128(hash, t_index, new_idx)                  \
   4652     hash->link_table[new_idx & TD2_ALPM_128_HASH_INDEX_MASK] =        \
   4653         hash->link_table[t_index & TD2_ALPM_128_HASH_INDEX_MASK];     \
   4654     hash->link_table[t_index & TD2_ALPM_128_HASH_INDEX_MASK] = new_idx
   4655 
   4656 #define INDEX_UPDATE_128(hash, hash_idx, old_idx, new_idx)          \
   4657     hash->table[hash_idx] = new_idx;                            \
   4658     hash->link_table[new_idx & TD2_ALPM_128_HASH_INDEX_MASK] =        \
   4659         hash->link_table[old_idx & TD2_ALPM_128_HASH_INDEX_MASK];     \
   4660     hash->link_table[old_idx & TD2_ALPM_128_HASH_INDEX_MASK] = TD2_ALPM_128_HASH_INDEX_NULL
   4661 
   4662 #define INDEX_UPDATE_LINK_128(hash, prev_idx, old_idx, new_idx)             \
   4663     hash->link_table[prev_idx & TD2_ALPM_128_HASH_INDEX_MASK] = new_idx;      \
   4664     hash->link_table[new_idx & TD2_ALPM_128_HASH_INDEX_MASK] =                \
   4665         hash->link_table[old_idx & TD2_ALPM_128_HASH_INDEX_MASK];             \
   4666     hash->link_table[old_idx & TD2_ALPM_128_HASH_INDEX_MASK] = TD2_ALPM_128_HASH_INDEX_NULL
   4667 
   4668 
   4669     int u = hash->unit, v, i = 0;
   4670 
   4671     uint16 hash_val;
   4672     uint16 index;
   4673     uint16 prev_index;
   4674 
   4675     if (rvt_index) {
   4676         *rvt_index = TD2_ALPM_128_HASH_INDEX_NULL;
   4677     }
   4678     hash_val = _soc_alpm_128_lpm_hash_compute((uint8 *)entry,
   4679                                         (32 * 9)) % hash->index_count;
   4680     index = hash->table[hash_val];
   4681     H_INDEX_MATCH_128("ihash", entry[0], hash_val);
   4682     H_INDEX_MATCH_128("ins  ", entry[0], new_index);
   4683     H_INDEX_MATCH_128("ins1 ", index, new_index);
   4684     prev_index = TD2_ALPM_128_HASH_INDEX_NULL;
   4685     if (old_index != TD2_ALPM_128_HASH_INDEX_NULL) {
   4686         while(index != TD2_ALPM_128_HASH_INDEX_NULL && i++ < hash->entry_count) {
   4687             uint32  e[SOC_MAX_MEM_FIELD_WORDS];
   4688             _soc_alpm_128_lpm_hash_entry_t  r_entry;
   4689             int     rindex;
   4690             
   4691             rindex = index;
   4692 
   4693             /*
   4694              * Check prefix length and skip index if not valid for given length
   4695             if ((SOC_ALPM_LPM_STATE_START(u, pfx) <= rindex) &&
   4696                 (SOC_ALPM_LPM_STATE_END(u, pfx) >= rindex)) {
   4697              */
   4698             SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIP_PAIR_128m,
   4699                                                    MEM_BLOCK_ANY, rindex, e));
   4700             SOC_FB_LPM_128_HASH_ENTRY_GET(u, e, index, r_entry, &v);
   4701             if (v == 0) {
   4702                 LOG_ERROR(BSL_LS_SOC_ALPM,
   4703                           (BSL_META_U(u,
   4704                                     "Empty entry[%d] in link_table. hash_val %d ridx %d nidx %d\n"),
   4705                                     index, hash_val, rindex, new_index));
   4706             }
   4707             if (v && ((*key_cmp_fn)(entry, r_entry) == 0)) {
   4708                 /* assert(old_index == index);*/
   4709                 if (new_index != index) {
   4710                     H_INDEX_MATCH_128("imove", prev_index, new_index);
   4711                     if (prev_index == TD2_ALPM_128_HASH_INDEX_NULL) {
   4712                         INDEX_UPDATE_128(hash, hash_val, index, new_index);
   4713                     } else {
   4714                         INDEX_UPDATE_LINK_128(hash, prev_index, index, 
   4715                                           new_index);
   4716                     }
   4717                 }
   4718                 if (rvt_index) {
   4719                     *rvt_index = index;
   4720                 }
   4721                 H_INDEX_MATCH_128("imtch", index, new_index);
   4722                 return(SOC_E_NONE);
   4723             }
   4724             /*
   4725             }
   4726             */
   4727             prev_index = index;
   4728             index = hash->link_table[index & TD2_ALPM_128_HASH_INDEX_MASK];
   4729             H_INDEX_MATCH_128("ins2 ", index, new_index);
   4730         }
   4731     }
   4732     if (i > hash->entry_count) {
   4733         LOG_ERROR(BSL_LS_SOC_ALPM,
   4734                   (BSL_META_U(u,
   4735                             "Hash loop\n")));
   4736         return SOC_E_INTERNAL;
   4737     }
   4738     INDEX_ADD_128(hash, hash_val, new_index);  /* new entry */
   4739     return(SOC_E_NONE);
   4740 }
   4741 
   4742 
   4743 
   4744 /*
   4745  * Function:
   4746  *      _soc_alpm_128_lpm_hash_revert
   4747  * Purpose:
   4748  *      Revert a key index in the hash table
   4749  * Parameters:
   4750  *      hash - Pointer (handle) to Hash Table
   4751  *      key_cmp_fn - Compare function which should compare key
   4752  *      entry   - The key to delete
   4753  *      pfx     - Prefix length for lookup acceleration.
   4754  *      delete_index - Index to delete.
   4755  * Returns:
   4756  *      SOC_E_NONE      Success
   4757  *      SOC_E_NOT_FOUND Key index not found.
   4758  */
   4759 static
   4760 int _soc_alpm_128_lpm_hash_revert(_soc_alpm_128_lpm_hash_t *hash,
   4761                             _soc_alpm_128_lpm_hash_compare_fn key_cmp_fn,
   4762                             _soc_alpm_128_lpm_hash_entry_t entry,
   4763                             uint16 new_index,
   4764                             uint32 rvt_index)
   4765 {
   4766     int u = hash->unit, i = 0;
   4767     uint16 hash_val;
   4768     uint16 index;
   4769     uint16 prev_index;
   4770 
   4771     hash_val = _soc_alpm_128_lpm_hash_compute((uint8 *)entry,
   4772                                         (32 * 9)) % hash->index_count;
   4773     index = hash->table[hash_val];
   4774     H_INDEX_MATCH_128("rhash", entry[0], hash_val);
   4775     H_INDEX_MATCH_128("rvt  ", entry[0], index);
   4776     prev_index = TD2_ALPM_128_HASH_INDEX_NULL;
   4777     while(index != TD2_ALPM_128_HASH_INDEX_NULL && i++ < hash->entry_count) {
   4778         if (new_index == index) {
   4779             H_INDEX_MATCH_128("dfoun", entry[0], index);
   4780             if (rvt_index == TD2_ALPM_128_HASH_INDEX_NULL) {
   4781                 if (prev_index == TD2_ALPM_128_HASH_INDEX_NULL) {
   4782                     INDEX_DELETE_128(hash, hash_val, new_index);
   4783                 } else {
   4784                     INDEX_DELETE_LINK_128(hash, prev_index, new_index);
   4785                 }
   4786             } else {
   4787                 if (prev_index == TD2_ALPM_128_HASH_INDEX_NULL) {
   4788                     INDEX_UPDATE_128(hash, hash_val, new_index, rvt_index);
   4789                 } else {
   4790                     INDEX_UPDATE_LINK_128(hash, prev_index, new_index,
   4791                                       rvt_index);
   4792                 }
   4793             }
   4794             return(SOC_E_NONE);
   4795         }
   4796         prev_index = index;
   4797         index = hash->link_table[index & TD2_ALPM_128_HASH_INDEX_MASK];
   4798         H_INDEX_MATCH_128("rvt1 ", entry[0], index);
   4799     }
   4800     if (i > hash->entry_count) {
   4801         LOG_ERROR(BSL_LS_SOC_ALPM,
   4802                   (BSL_META_U(u,
   4803                             "Hash loop\n")));
   4804     }
   4805     return(SOC_E_NOT_FOUND);
   4806 }
   4807 
   4808 
   4809 
   4810 /*
   4811  * Function:
   4812  *      _soc_alpm_128_lpm_hash_delete
   4813  * Purpose:
   4814  *      Delete a key index in the hash table
   4815  * Parameters:
   4816  *      hash - Pointer (handle) to Hash Table
   4817  *      key_cmp_fn - Compare function which should compare key
   4818  *      entry   - The key to delete
   4819  *      pfx     - Prefix length for lookup acceleration.
   4820  *      delete_index - Index to delete.
   4821  * Returns:
   4822  *      SOC_E_NONE      Success
   4823  *      SOC_E_NOT_FOUND Key index not found.
   4824  */
   4825 static
   4826 int _soc_alpm_128_lpm_hash_delete(_soc_alpm_128_lpm_hash_t *hash,
   4827                             _soc_alpm_128_lpm_hash_compare_fn key_cmp_fn,
   4828                             _soc_alpm_128_lpm_hash_entry_t entry,
   4829                             int    pfx,
   4830                             uint16 delete_index)
   4831 {
   4832     int u = hash->unit, i = 0;
   4833     uint16 hash_val;
   4834     uint16 index;
   4835     uint16 prev_index;
   4836 
   4837     hash_val = _soc_alpm_128_lpm_hash_compute((uint8 *)entry,
   4838                                         (32 * 9)) % hash->index_count;
   4839     index = hash->table[hash_val];
   4840     H_INDEX_MATCH_128("dhash", entry[0], hash_val);
   4841     H_INDEX_MATCH_128("del  ", entry[0], index);
   4842     prev_index = TD2_ALPM_128_HASH_INDEX_NULL;
   4843     while(index != TD2_ALPM_128_HASH_INDEX_NULL && i++ < hash->entry_count) {
   4844         if (delete_index == index) {
   4845             H_INDEX_MATCH_128("dfoun", entry[0], index);
   4846             if (prev_index == TD2_ALPM_128_HASH_INDEX_NULL) {
   4847                 INDEX_DELETE_128(hash, hash_val, delete_index);
   4848             } else {
   4849                 INDEX_DELETE_LINK_128(hash, prev_index, delete_index);
   4850             }
   4851             return(SOC_E_NONE);
   4852         }
   4853         prev_index = index;
   4854         index = hash->link_table[index & TD2_ALPM_128_HASH_INDEX_MASK];
   4855         H_INDEX_MATCH_128("del1 ", entry[0], index);
   4856     }
   4857     if (i > hash->entry_count) {
   4858         LOG_ERROR(BSL_LS_SOC_ALPM,
   4859                   (BSL_META_U(u,
   4860                             "Hash loop\n")));
   4861     }
   4862     return(SOC_E_NOT_FOUND);
   4863 }
   4864 
   4865 
   4866 /*
   4867  * Function:
   4868  *      _soc_alpm_128_lpm_hash_verify
   4869  * Purpose:
   4870  *      Verify a key index in the hash table
   4871  * Parameters:
   4872  *      hash - Pointer (handle) to Hash Table
   4873  *      key_cmp_fn - Compare function which should compare key
   4874  *      entry   - The key to verify
   4875  *      pfx     - Prefix length for lookup acceleration.
   4876  *      verify_index   - Index to verify.
   4877  * Returns:
   4878  *      SOC_E_NONE      Success
   4879  *      SOC_E_NOT_FOUND Key index not found.
   4880  */
   4881 static
   4882 int _soc_alpm_128_lpm_hash_verify(_soc_alpm_128_lpm_hash_t *hash,
   4883                             _soc_alpm_128_lpm_hash_compare_fn key_cmp_fn,
   4884                             _soc_alpm_128_lpm_hash_entry_t entry,
   4885                             int    pfx,
   4886                             uint16 verify_index)
   4887 {
   4888     int u = hash->unit, i = 0;
   4889     uint16 hash_val;
   4890     uint16 index;
   4891 
   4892     hash_val = _soc_alpm_128_lpm_hash_compute((uint8 *)entry,
   4893                                         (32 * 9)) % hash->index_count;
   4894     index = hash->table[hash_val];
   4895     H_INDEX_MATCH_128("vhash", entry[0], hash_val);
   4896     H_INDEX_MATCH_128("veri ", entry[0], index);
   4897     while(index != TD2_ALPM_128_HASH_INDEX_NULL && i++ < hash->entry_count) {
   4898         if (verify_index == index) {
   4899             H_INDEX_MATCH_128("vfoun", entry[0], index);
   4900             return(SOC_E_NONE);
   4901         }
   4902         index = hash->link_table[index & TD2_ALPM_128_HASH_INDEX_MASK];
   4903         H_INDEX_MATCH_128("veri1", entry[0], index);
   4904     }
   4905     if (i > hash->entry_count) {
   4906         LOG_ERROR(BSL_LS_SOC_ALPM,
   4907                   (BSL_META_U(u,
   4908                             "Hash loop\n")));
   4909     }
   4910     return(SOC_E_NOT_FOUND);
   4911 }
   4912 
   4913 #else
   4914 #define LPM_128_HASH_INSERT(u, entry_data, tab_index, rvt_index)
   4915 #define LPM_128_HASH_REVERT(u, entry_data, tab_index, rvt_index)
   4916 #define LPM_128_HASH_DELETE(u, key_data, tab_index)
   4917 #define LPM_128_HASH_LOOKUP(u, key_data, pfx, tab_index)
   4918 #define LPM_128_HASH_VERIFY(u, key_data, tab_index)
   4919 #endif /* FB_LPM_128_HASH_SUPPORT */
   4920 
   4921 void
   4922 soc_alpm_128_lpm_state_dump(int u)
   4923 {
   4924     int i;
   4925     int max_pfx_len;
   4926     max_pfx_len = MAX_PFX_INDEX_128;
   4927 
   4928     if (!bsl_check(bslLayerSoc, bslSourceAlpm, bslSeverityVerbose, u)) {
   4929         return;
   4930     }
   4931     for(i = max_pfx_len; i >= 0 ; i--) {
   4932         if ((i != MAX_PFX_INDEX_128) && (SOC_ALPM_128_LPM_STATE_START(u, i) == -1)) {
   4933             continue;
   4934         }
   4935         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   4936                     (BSL_META_U(u,
   4937                                 "PFX = %d P = %d N = %d START = %d "
   4938                                 "END = %d VENT = %d FENT = %d\n"),
   4939                      i,
   4940                      SOC_ALPM_128_LPM_STATE_PREV(u, i),
   4941                      SOC_ALPM_128_LPM_STATE_NEXT(u, i),
   4942                      SOC_ALPM_128_LPM_STATE_START(u, i),
   4943                      SOC_ALPM_128_LPM_STATE_END(u, i),
   4944                      SOC_ALPM_128_LPM_STATE_VENT(u, i),
   4945                      SOC_ALPM_128_LPM_STATE_FENT(u, i)));
   4946     }
   4947 }
   4948 
   4949 /*
   4950  * Function:
   4951  *      _lpm_128_fb_urpf_entry_replicate
   4952  * Purpose:
   4953  *      Replicate entry to the second half of the tcam if URPF check is ON.
   4954  * Parameters:
   4955  *      u           - (IN)  SOC unit number.
   4956  *      index:      - (IN)  corresponding dip target index
   4957  *      e           - (IN|OUT) input dip entry, could be modified for sip
   4958  *      src_index   - (IN)  if ALPM_INVALID_INDEX use input e,
   4959  *                          otherwise copy from src_index.
   4960  *      src_default - (IN)  used only if src_index = ALPM_INVALID_INDEX
   4961  *                          0 - caculate using entry_data's mask (legacy way)
   4962  *                          1 - force set (split case)
   4963  *      src_discard - (IN)  used only if src_index = ALPM_INVALID_INDEX.
   4964  * Returns:
   4965  *      BCM_E_XXX
   4966  */
   4967 
   4968 static 
   4969 int _lpm_128_fb_urpf_entry_replicate(int u, int src_index, int index, uint32 *e,
   4970                                      int src_default, int src_discard, int bpm_len)
   4971 {
   4972     int src_tcam_offset;  /* Defip memory size/2 urpf source lookup offset */
   4973     uint32 mask0, mask2, mask3;   /* Mask field values.                    */
   4974     uint32 mask1;         /* Mask 1 field value.                           */
   4975     int def_gw_flag;      /* Entry is default gateway.                     */
   4976 
   4977     if(!SOC_URPF_STATUS_GET(u)) {   
   4978         return (SOC_E_NONE);
   4979     }
   4980 
   4981      src_tcam_offset = (soc_mem_index_count(u, L3_DEFIP_PAIR_128m) >> 1);
   4982 
   4983     if (src_index != ALPM_INVALID_INDEX) {
   4984 #ifdef FB_LPM_TABLE_CACHED
   4985         SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, L3_DEFIP_PAIR_128m,
   4986                                 MEM_BLOCK_ANY,
   4987                                 src_index + src_tcam_offset));
   4988 #endif /* FB_LPM_TABLE_CACHED */    
   4989         SOC_IF_ERROR_RETURN(
   4990             _soc_mem_alpm_read(u, L3_DEFIP_PAIR_128m, MEM_BLOCK_ANY,
   4991                                src_index + src_tcam_offset, e));
   4992 
   4993         /* Write entry to the second half of the tcam. */
   4994         return _soc_alpm_128_write_pivot_aux(u, index, index + src_tcam_offset, e, bpm_len);
   4995     }
   4996 
   4997     src_default = src_default ? 1 : 0;
   4998     src_discard = src_discard ? 1 : 0;
   4999 
   5000     /* Set/Reset default gateway flag based on ip mask value. */
   5001     mask0 = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, e, 
   5002                                     IP_ADDR_MASK0_LWRf);
   5003     mask1 = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, e, 
   5004                                     IP_ADDR_MASK1_LWRf);
   5005     mask2 = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, e, 
   5006                                     IP_ADDR_MASK0_UPRf);
   5007     mask3 = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, e, 
   5008                                     IP_ADDR_MASK1_UPRf);
   5009 
   5010     def_gw_flag = ((!mask0) &&  (!mask1) && (!mask2) && (!mask3)) ? 1 : 0;
   5011     mask0 = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, e, VALID0_LWRf);
   5012     mask1 = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, e, VALID0_UPRf);
   5013     mask2 = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, e, VALID1_UPRf);
   5014     mask3 = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, e, VALID1_UPRf);
   5015     if (mask0 && mask1 && mask2 && mask3) {
   5016         SOC_MEM_OPT_F32_SET_128(u, L3_DEFIP_PAIR_128m, e, RPEf, 
   5017                                 src_default | def_gw_flag);
   5018         if (SOC_MEM_OPT_FIELD_VALID_128(u, L3_DEFIP_PAIR_128m, DST_DISCARDf)) {
   5019             SOC_MEM_OPT_F32_SET_128(u, L3_DEFIP_PAIR_128m, e, DST_DISCARDf,
   5020                                     src_discard);
   5021         }
   5022     }
   5023 
   5024     /* Write entry to the second half of the tcam. */
   5025     return _soc_alpm_128_write_pivot_aux(u, index, index + src_tcam_offset, e, bpm_len);
   5026 }
   5027 
   5028 
   5029 static int
   5030 _soc_alpm_128_write_pivot_with_bpm(int u, int src_index, int index, void *entry,
   5031                                    uint32 op, int src_default, int src_discard, int bpm_len)
   5032 {
   5033     int src_index_uprf = src_index;
   5034     int rv;
   5035     uint32 rvt_index = 0;
   5036 
   5037     switch (op & (~WRITE_PIVOT_WITHOUT_INSERT_HASH)) {
   5038     case WRITE_PIVOT_WITH_SRC_INDEX:
   5039         src_default = -1;
   5040         src_discard = -1;
   5041         break;
   5042     case WRITE_PIVOT_WITH_URPF_PARAMS:
   5043         src_index_uprf = ALPM_INVALID_INDEX;
   5044         break;
   5045     default:
   5046         return SOC_E_INTERNAL;
   5047     }
   5048 
   5049     if (!(op & WRITE_PIVOT_WITHOUT_INSERT_HASH)) {
   5050         LPM_128_HASH_INSERT(u, entry, index, &rvt_index);
   5051     }
   5052     rv = _soc_alpm_128_write_pivot_aux(u, src_index, index, entry, bpm_len);
   5053 
   5054     if (rv >= 0) {
   5055         rv = _lpm_128_fb_urpf_entry_replicate(u, src_index_uprf, index, entry,
   5056                                               src_default, src_discard, bpm_len);
   5057     }
   5058     if (!(op & WRITE_PIVOT_WITHOUT_INSERT_HASH) && rv < 0) {
   5059         LPM_128_HASH_REVERT(u, entry, index, rvt_index);
   5060     }
   5061 
   5062     return rv;
   5063 }
   5064 static int
   5065 _soc_alpm_128_write_pivot(int u, int src_index, int index, void *entry,
   5066                           uint32 op, int src_default, int src_discard)
   5067 {
   5068     return _soc_alpm_128_write_pivot_with_bpm
   5069         (u, src_index, index, entry, op, src_default, src_discard, INVALID_BPM_LEN);
   5070 }
   5071 /* used for moving either 2 v4 entries or 1 v6 entry. */
   5072 static void
   5073 _soc_alpm_128_move_pivot(int u, int src, int dst)
   5074 {
   5075     alpm_pivot_t *src_pivot;
   5076 
   5077     src = soc_alpm_physical_idx(u, L3_DEFIP_PAIR_128m, src, 1);
   5078     dst = soc_alpm_physical_idx(u, L3_DEFIP_PAIR_128m, dst, 1);
   5079     src = SOC_ALPM_128_ADDR_LWR(u, src) << 1;
   5080     dst = SOC_ALPM_128_ADDR_LWR(u, dst) << 1;
   5081 
   5082     /* Track full-entry move */
   5083     src_pivot = ALPM_TCAM_PIVOT(u, src);
   5084     if (src_pivot) {
   5085         PIVOT_TCAM_INDEX(src_pivot) = dst;
   5086     }
   5087 
   5088     ALPM_TCAM_PIVOT(u, dst) = src_pivot;
   5089     ALPM_TCAM_PIVOT(u, src) = NULL;
   5090     return;
   5091 }
   5092 
   5093 
   5094 /*
   5095  *      Create a slot for the new entry rippling the entries if required
   5096  */
   5097 static
   5098 int _lpm_128_fb_entry_shift(int u, int from_ent, int to_ent)
   5099 {
   5100     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   5101 
   5102     if (from_ent == to_ent) {
   5103         return SOC_E_NONE;
   5104     }
   5105 
   5106 #ifdef FB_LPM_TABLE_CACHED
   5107     SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, L3_DEFIP_PAIR_128m,
   5108                                        MEM_BLOCK_ANY, from_ent));
   5109 #endif /* FB_LPM_TABLE_CACHED */
   5110 
   5111     SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIP_PAIR_128m,
   5112                                            MEM_BLOCK_ANY, from_ent, e));
   5113     SOC_IF_ERROR_RETURN(_soc_alpm_128_write_pivot(u, from_ent, to_ent, e,
   5114                                           WRITE_PIVOT_WITH_SRC_INDEX, 0, 0));
   5115 
   5116     _soc_alpm_128_move_pivot(u, from_ent, to_ent);
   5117     
   5118     return (SOC_E_NONE);
   5119 }
   5120 
   5121 
   5122 /*
   5123  *      Shift prefix entries 1 entry UP, while preserving  
   5124  *      last half empty IPv4 entry if any.
   5125  */
   5126 static
   5127 int _lpm_128_fb_shift_pfx_up(int u, int pfx, int ipv6)
   5128 {
   5129     int         from_ent;
   5130     int         to_ent;
   5131 
   5132     to_ent = SOC_ALPM_128_LPM_STATE_END(u, pfx) + 1;
   5133 
   5134     from_ent = SOC_ALPM_128_LPM_STATE_START(u, pfx);
   5135     if (from_ent != to_ent) {
   5136         SOC_IF_ERROR_RETURN(_lpm_128_fb_entry_shift(u, from_ent, to_ent));
   5137         /* Store Shift counter in MAX_VRF_ID */
   5138         VRF_PIVOT_SHIFT_INC(u, MAX_VRF_ID, ipv6);
   5139     } 
   5140     SOC_ALPM_128_LPM_STATE_START(u, pfx) += 1;
   5141     SOC_ALPM_128_LPM_STATE_END(u, pfx) += 1;
   5142     return (SOC_E_NONE);
   5143 }
   5144 
   5145 /*
   5146  *      Shift prefix entries 1 entry DOWN, while preserving  
   5147  *      last half empty IPv4 entry if any.
   5148  */
   5149 static
   5150 int _lpm_128_fb_shift_pfx_down(int u, int pfx, int ipv6)
   5151 {
   5152     int         from_ent;
   5153     int         to_ent;
   5154 
   5155     to_ent = SOC_ALPM_128_LPM_STATE_START(u, pfx) - 1;
   5156 
   5157     /* Don't move empty prefix . */ 
   5158     if (SOC_ALPM_128_LPM_STATE_VENT(u, pfx) == 0) {
   5159         SOC_ALPM_128_LPM_STATE_START(u, pfx) = to_ent;
   5160         SOC_ALPM_128_LPM_STATE_END(u, pfx) = to_ent - 1;
   5161         return (SOC_E_NONE);
   5162     }
   5163 
   5164     from_ent = SOC_ALPM_128_LPM_STATE_END(u, pfx);
   5165     SOC_IF_ERROR_RETURN(_lpm_128_fb_entry_shift(u, from_ent, to_ent));
   5166     /* Store Shift counter in MAX_VRF_ID */
   5167     VRF_PIVOT_SHIFT_INC(u, MAX_VRF_ID, ipv6);
   5168 
   5169     SOC_ALPM_128_LPM_STATE_START(u, pfx) -= 1;
   5170     SOC_ALPM_128_LPM_STATE_END(u, pfx) -= 1;
   5171 
   5172     return (SOC_E_NONE);
   5173 }
   5174 
   5175 /*
   5176  *      Create a slot for the new entry rippling the entries if required
   5177  */
   5178 static
   5179 int _lpm_128_free_slot_create(int u, int pfx, int ipv6, void *e, int *free_slot)
   5180 {
   5181     int         prev_pfx;
   5182     int         next_pfx;
   5183     int         free_pfx;
   5184     int         curr_pfx;
   5185 
   5186 
   5187     if (SOC_ALPM_128_LPM_STATE_VENT(u, pfx) == 0) {
   5188         /*
   5189          * Find the  prefix position. Only prefix with valid
   5190          * entries are in the list.
   5191          * next -> high to low prefix. low to high index
   5192          * prev -> low to high prefix. high to low index
   5193          * Unused prefix length MAX_PFX_INDEX_128 is the head of the
   5194          * list and is node corresponding to this is always
   5195          * present.
   5196          */
   5197         curr_pfx = MAX_PFX_INDEX_128;
   5198         if (soc_alpm_mode_get(u) == SOC_ALPM_MODE_PARALLEL) {
   5199             if (pfx <= MAX_VRF_PFX_INDEX_128) {
   5200                 curr_pfx = MAX_VRF_PFX_INDEX_128;
   5201             }
   5202         }
   5203         while (SOC_ALPM_128_LPM_STATE_NEXT(u, curr_pfx) > pfx) {
   5204             curr_pfx = SOC_ALPM_128_LPM_STATE_NEXT(u, curr_pfx);
   5205         }
   5206         /* Insert the new prefix */
   5207         next_pfx = SOC_ALPM_128_LPM_STATE_NEXT(u, curr_pfx);
   5208         if (next_pfx != -1) {
   5209             SOC_ALPM_128_LPM_STATE_PREV(u, next_pfx) = pfx;
   5210         }
   5211         SOC_ALPM_128_LPM_STATE_NEXT(u, pfx) = SOC_ALPM_128_LPM_STATE_NEXT(u, curr_pfx);
   5212         SOC_ALPM_128_LPM_STATE_PREV(u, pfx) = curr_pfx;
   5213         SOC_ALPM_128_LPM_STATE_NEXT(u, curr_pfx) = pfx;
   5214 
   5215         SOC_ALPM_128_LPM_STATE_FENT(u, pfx) =  (SOC_ALPM_128_LPM_STATE_FENT(u, curr_pfx) + 1) / 2;
   5216         SOC_ALPM_128_LPM_STATE_FENT(u, curr_pfx) -= SOC_ALPM_128_LPM_STATE_FENT(u, pfx);
   5217         SOC_ALPM_128_LPM_STATE_START(u, pfx) =  SOC_ALPM_128_LPM_STATE_END(u, curr_pfx) +
   5218                                        SOC_ALPM_128_LPM_STATE_FENT(u, curr_pfx) + 1;
   5219         SOC_ALPM_128_LPM_STATE_END(u, pfx) = SOC_ALPM_128_LPM_STATE_START(u, pfx) - 1;
   5220         SOC_ALPM_128_LPM_STATE_VENT(u, pfx) = 0;
   5221     } 
   5222 
   5223     free_pfx = pfx;
   5224     while(SOC_ALPM_128_LPM_STATE_FENT(u, free_pfx) == 0) {
   5225         free_pfx = SOC_ALPM_128_LPM_STATE_NEXT(u, free_pfx);
   5226         if (free_pfx == -1) {
   5227             /* No free entries on this side try the other side */
   5228             free_pfx = pfx;
   5229             break;
   5230         }
   5231     }
   5232 
   5233     while(SOC_ALPM_128_LPM_STATE_FENT(u, free_pfx) == 0) {
   5234         free_pfx = SOC_ALPM_128_LPM_STATE_PREV(u, free_pfx);
   5235         if (free_pfx == -1) {
   5236             if (SOC_ALPM_128_LPM_STATE_VENT(u, pfx) == 0) {
   5237                 /* We failed to allocate entries for a newly allocated prefix.*/
   5238                 prev_pfx = SOC_ALPM_128_LPM_STATE_PREV(u, pfx);
   5239                 next_pfx = SOC_ALPM_128_LPM_STATE_NEXT(u, pfx);
   5240                 if (-1 != prev_pfx) {
   5241                     SOC_ALPM_128_LPM_STATE_NEXT(u, prev_pfx) = next_pfx;
   5242                 }
   5243                 if (-1 != next_pfx) {
   5244                     SOC_ALPM_128_LPM_STATE_PREV(u, next_pfx) = prev_pfx;
   5245                 }
   5246             }
   5247             return(SOC_E_FULL);
   5248         }
   5249     }
   5250 
   5251     /*
   5252      * Ripple entries to create free space
   5253      */
   5254     while (free_pfx > pfx) {
   5255         next_pfx = SOC_ALPM_128_LPM_STATE_NEXT(u, free_pfx); 
   5256         SOC_IF_ERROR_RETURN(_lpm_128_fb_shift_pfx_down(u, next_pfx, ipv6));
   5257         SOC_ALPM_128_LPM_STATE_FENT(u, free_pfx) -= 1;
   5258         SOC_ALPM_128_LPM_STATE_FENT(u, next_pfx) += 1;
   5259         free_pfx = next_pfx;
   5260     }
   5261 
   5262     while (free_pfx < pfx) {
   5263         SOC_IF_ERROR_RETURN(_lpm_128_fb_shift_pfx_up(u, free_pfx, ipv6));
   5264         SOC_ALPM_128_LPM_STATE_FENT(u, free_pfx) -= 1;
   5265         prev_pfx = SOC_ALPM_128_LPM_STATE_PREV(u, free_pfx); 
   5266         SOC_ALPM_128_LPM_STATE_FENT(u, prev_pfx) += 1;
   5267         free_pfx = prev_pfx;
   5268     }
   5269 
   5270     SOC_ALPM_128_LPM_STATE_VENT(u, pfx) += 1;
   5271     SOC_ALPM_128_LPM_STATE_FENT(u, pfx) -= 1;
   5272     SOC_ALPM_128_LPM_STATE_END(u, pfx) += 1;
   5273     *free_slot = SOC_ALPM_128_LPM_STATE_END(u, pfx);
   5274     sal_memcpy(e, soc_mem_entry_null(u, L3_DEFIP_PAIR_128m),
   5275                soc_mem_entry_words(u,L3_DEFIP_PAIR_128m) * 4);
   5276 
   5277     return(SOC_E_NONE);
   5278 }
   5279 
   5280 /*
   5281  *      Delete a slot and adjust entry pointers if required.
   5282  *      e - has the contents of entry at slot(useful for IPV4 only)
   5283  */
   5284 static
   5285 int _lpm_128_free_slot_delete(int u, int pfx, int ipv6, void *e, int slot)
   5286 {
   5287     int         prev_pfx;
   5288     int         next_pfx;
   5289     int         from_ent;
   5290     int         to_ent;
   5291     uint32      ef[SOC_MAX_MEM_FIELD_WORDS];
   5292     int         rv = SOC_E_NONE;
   5293 
   5294     from_ent = SOC_ALPM_128_LPM_STATE_END(u, pfx);
   5295     to_ent = slot;
   5296     SOC_ALPM_128_LPM_STATE_VENT(u, pfx) -= 1;
   5297     SOC_ALPM_128_LPM_STATE_FENT(u, pfx) += 1;
   5298     SOC_ALPM_128_LPM_STATE_END(u, pfx) -= 1;
   5299     if (to_ent != from_ent) {
   5300 #ifdef FB_LPM_TABLE_CACHED
   5301         if ((rv = soc_mem_cache_invalidate(u, L3_DEFIP_PAIR_128m,
   5302                                            MEM_BLOCK_ANY, from_ent)) < 0) {
   5303             return rv;
   5304         }
   5305 #endif /* FB_LPM_TABLE_CACHED */
   5306         if ((rv = _soc_mem_alpm_read(u, L3_DEFIP_PAIR_128m,
   5307                                      MEM_BLOCK_ANY, from_ent, ef)) < 0) {
   5308             return rv;
   5309         }
   5310         /* coverity[copy_paste_error : FALSE] */
   5311         SOC_IF_ERROR_RETURN(_soc_alpm_128_write_pivot(u, from_ent, to_ent, ef,
   5312                                           WRITE_PIVOT_WITH_SRC_INDEX, 0, 0));
   5313     }
   5314 
   5315     sal_memcpy(ef, soc_mem_entry_null(u, L3_DEFIP_PAIR_128m),
   5316                soc_mem_entry_words(u,L3_DEFIP_PAIR_128m) * 4);
   5317     SOC_IF_ERROR_RETURN(_soc_alpm_128_write_pivot(u, from_ent, from_ent, ef,
   5318                                           WRITE_PIVOT_WITH_URPF_PARAMS, 0, 0));
   5319 
   5320     _soc_alpm_128_move_pivot(u, from_ent, to_ent);
   5321 
   5322     if (SOC_ALPM_128_LPM_STATE_VENT(u, pfx) == 0) {
   5323         /* remove from the list */
   5324         prev_pfx = SOC_ALPM_128_LPM_STATE_PREV(u, pfx); /* Always present */
   5325         assert(prev_pfx != -1);
   5326         next_pfx = SOC_ALPM_128_LPM_STATE_NEXT(u, pfx);
   5327         SOC_ALPM_128_LPM_STATE_NEXT(u, prev_pfx) = next_pfx;
   5328         SOC_ALPM_128_LPM_STATE_FENT(u, prev_pfx) += 
   5329                                             SOC_ALPM_128_LPM_STATE_FENT(u, pfx);
   5330         SOC_ALPM_128_LPM_STATE_FENT(u, pfx) = 0;
   5331         if (next_pfx != -1) {
   5332             SOC_ALPM_128_LPM_STATE_PREV(u, next_pfx) = prev_pfx;
   5333         }
   5334         SOC_ALPM_128_LPM_STATE_NEXT(u, pfx) = -1;
   5335         SOC_ALPM_128_LPM_STATE_PREV(u, pfx) = -1;
   5336         SOC_ALPM_128_LPM_STATE_START(u, pfx) = -1;
   5337         SOC_ALPM_128_LPM_STATE_END(u, pfx) = -1;
   5338     }
   5339 
   5340     return(rv);
   5341 }
   5342 
   5343 /*
   5344  * Function:
   5345  *      soc_alpm_128_lpm_vrf_get
   5346  * Purpose:
   5347  *      Service routine used to translate hw specific vrf id to API format.
   5348  * Parameters:
   5349  *      unit      - (IN)SOC unit number.
   5350  *      lpm_entry - (IN)Route info buffer from hw.
   5351  *      vrf_id    - (OUT)Virtual router id.
   5352  * Returns:
   5353  *      BCM_E_XXX
   5354  */
   5355 int
   5356 soc_alpm_128_lpm_vrf_get(int unit, void *lpm_entry, int *vrf_id, int *vrf)
   5357 {
   5358     int mem_vrf;
   5359 
   5360     /* Get Virtual Router id if supported. */
   5361     if (SOC_MEM_OPT_FIELD_VALID_128(unit, L3_DEFIP_PAIR_128m,
   5362                                             VRF_ID_MASK0_LWRf)){
   5363         mem_vrf = SOC_MEM_OPT_F32_GET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry,
   5364                                          VRF_ID_0_LWRf);
   5365 
   5366         /* Special vrf_id's handling. */
   5367         if (SOC_MEM_OPT_F32_GET_128(unit, L3_DEFIP_PAIR_128m, lpm_entry,
   5368                                     VRF_ID_MASK0_LWRf)) {
   5369             *vrf_id = mem_vrf;
   5370         } else if (!SOC_MEM_OPT_F32_GET_128(unit, L3_DEFIP_PAIR_128m,
   5371                 lpm_entry, GLOBAL_HIGHf)) {
   5372             *vrf_id = SOC_L3_VRF_GLOBAL;
   5373         } else {
   5374             *vrf_id = SOC_L3_VRF_OVERRIDE;
   5375         }
   5376         if (vrf) {
   5377             if (*vrf_id == SOC_L3_VRF_GLOBAL) {
   5378                 *vrf = SOC_VRF_MAX(unit) + 1;
   5379             } else {
   5380                 *vrf = mem_vrf;
   5381             }
   5382         }
   5383     } else {
   5384         /* No vrf support on this device. */
   5385         *vrf_id = SOC_L3_VRF_DEFAULT;
   5386     }
   5387     return (SOC_E_NONE);
   5388 }
   5389 
   5390 /*
   5391  * _soc_alpm_128_lpm_prefix_length_get (Extract vrf weighted  prefix lenght from the 
   5392  * hw entry based on ip, mask & vrf)
   5393  */
   5394 static int
   5395 _soc_alpm_128_lpm_prefix_length_get(int u, void *entry, int *pfx_len) 
   5396 {
   5397     int         pfx=0;
   5398     int         rv;
   5399     int         vrf_id;
   5400     int         mode;
   5401 
   5402     rv = _soc_alpm_128_ip6_mask_len_get(u, entry, &pfx);
   5403     if (rv < 0) {
   5404         return rv;
   5405     }
   5406     pfx += IPV6_128_PFX_ZERO; /* Now only v6-128 */
   5407 
   5408     SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_vrf_get(u, entry, &vrf_id, &rv));
   5409 
   5410     /* In ALPM the arragnement of VRF is at he begining followed by VRF
   5411      * override and global */
   5412     mode = soc_alpm_mode_get(u);
   5413     switch (vrf_id) {
   5414         case SOC_L3_VRF_GLOBAL:
   5415             if (mode == SOC_ALPM_MODE_PARALLEL) {
   5416                 *pfx_len = pfx + (MAX_PFX_ENTRIES_128 / 3);
   5417             } else {
   5418                 *pfx_len = pfx;
   5419             }
   5420             break;
   5421         case SOC_L3_VRF_OVERRIDE:
   5422             *pfx_len = pfx +  2 * (MAX_PFX_ENTRIES_128 / 3);
   5423             break;
   5424         default:
   5425             if (mode == SOC_ALPM_MODE_PARALLEL) {
   5426                 *pfx_len = pfx;
   5427             } else {
   5428                 *pfx_len = pfx +  (MAX_PFX_ENTRIES_128 / 3);
   5429             }
   5430             break;
   5431     }
   5432     return (SOC_E_NONE);
   5433 }
   5434 
   5435 
   5436 /*
   5437  * _soc_alpm_128_lpm_match (Exact match for the key. Will match both IP address
   5438  * and mask)
   5439  */
   5440 static int
   5441 _soc_alpm_128_lpm_match(int u,
   5442                void *key_data,
   5443                void *e,         /* return entry data if found */
   5444                int *index_ptr,  /* return key location */
   5445                int *pfx_len,    /* Key prefix length. vrf + 32 + prefix len for IPV6*/
   5446                int *ipv6)       /* Entry is ipv6. */
   5447 {
   5448     int         rv;
   5449     int         key_index;
   5450     int         pfx = 0;
   5451 
   5452     *ipv6 = L3_DEFIP_MODE_128;
   5453 
   5454     /* Calculate vrf weighted prefix lengh. */
   5455     _soc_alpm_128_lpm_prefix_length_get(u, key_data, &pfx); 
   5456     *pfx_len = pfx; 
   5457 
   5458 #ifdef FB_LPM_128_HASH_SUPPORT
   5459     if (LPM_128_HASH_LOOKUP(u, key_data, pfx, &key_index) == SOC_E_NONE) {
   5460         *index_ptr = key_index;
   5461         if ((rv = _soc_mem_alpm_read(u, L3_DEFIP_PAIR_128m, MEM_BLOCK_ANY,
   5462                       (*ipv6) ? *index_ptr : (*index_ptr >> 1), e)) < 0) {
   5463             return rv;
   5464         }
   5465 #ifndef  FB_LPM_CHECKER_ENABLE
   5466         return(SOC_E_NONE);
   5467 #endif
   5468     } else {
   5469 #ifndef  FB_LPM_CHECKER_ENABLE
   5470         return(SOC_E_NOT_FOUND);
   5471 #endif
   5472     }
   5473 #endif /* FB_LPM_128_HASH_SUPPORT */
   5474 }
   5475 
   5476 /**
   5477  * IPMC_MISS signal is never asserted after an unsuccessful L3_DEFIP table 
   5478  * lookup for IPMC packets when IPMC (PIM-SM, PIM-BIDIR) forwarding is enabled 
   5479  * in TD2+. Due to this, the forwarding logic miss forwards IPMC 
   5480  * packets to an incorrect (or invalid) IPMC group. 
   5481  *
   5482  * WAR: Add two default rules as last entries in L3_DEFIP (TCAM) table such that
   5483  * all IPV4 and IPV6 multicast packets will, by default, hit these entries, if 
   5484  * any specific IPMC were not added in the L3_DEFIP table. Thus L3_DEFIP lookup 
   5485  * for IPMC packets will never result in a miss.
   5486  * 
   5487  * Packets copied to CPU due to IPMC_MISS will have OPCODE set as 4 
   5488  * (IP Multicast) as opposed to 3 (L2 Multicast). This may cause some mismatches 
   5489  * in case of CPU bound packets compared to legacy XGS devices. 
   5490  */
   5491 int
   5492 soc_alpm_128_ipmc_war(int unit, int install)
   5493 {
   5494     int index = -1;
   5495     defip_pair_128_entry_t lpm_entry;
   5496     soc_mem_t mem = L3_DEFIP_PAIR_128m;
   5497     int num_rp = 63;
   5498 
   5499     if (!(soc_feature(unit, soc_feature_alpm) &&
   5500           soc_feature(unit, soc_feature_td2p_a0_sw_war) &&
   5501           soc_property_get(unit, spn_L3_ALPM_ENABLE, 0))) {
   5502         return SOC_E_NONE;
   5503     }
   5504 
   5505     if (!SOC_ALPM_128_LPM_INIT_CHECK(unit)) {
   5506         return SOC_E_NONE;
   5507     }
   5508 
   5509     if (soc_mem_index_count(unit, L3_DEFIP_PAIR_128m) <= 0) {
   5510         return SOC_E_NONE;
   5511     }
   5512 
   5513     if (!SOC_IS_TRIDENT2PLUS(unit)) {
   5514         return SOC_E_NONE;
   5515     }
   5516 
   5517     if (SOC_WARM_BOOT(unit)) {
   5518         return SOC_E_NONE;
   5519     }
   5520 
   5521     num_rp = soc_mem_field_length(unit, 
   5522                 ING_ACTIVE_L3_IIF_PROFILEm, RPA_ID_PROFILEf);    
   5523 
   5524     /* Zero Buffer */
   5525     sal_memset(&lpm_entry, 0, soc_mem_entry_words(unit, mem) * 4);
   5526 
   5527     soc_mem_field32_set(unit, mem, &lpm_entry, VALID0_LWRf, 1);
   5528     soc_mem_field32_set(unit, mem, &lpm_entry, VALID1_LWRf, 1);
   5529     soc_mem_field32_set(unit, mem, &lpm_entry, VALID0_UPRf, 1);
   5530     soc_mem_field32_set(unit, mem, &lpm_entry, VALID1_UPRf, 1);
   5531 
   5532     soc_mem_field32_set(unit, mem, &lpm_entry, MODE0_LWRf, 3);
   5533     soc_mem_field32_set(unit, mem, &lpm_entry, MODE1_LWRf, 3);
   5534     soc_mem_field32_set(unit, mem, &lpm_entry, MODE0_UPRf, 3);
   5535     soc_mem_field32_set(unit, mem, &lpm_entry, MODE1_UPRf, 3);
   5536     soc_mem_field32_set(unit, mem, &lpm_entry, MODE_MASK0_LWRf, 3);
   5537     soc_mem_field32_set(unit, mem, &lpm_entry, MODE_MASK1_LWRf, 3);
   5538     soc_mem_field32_set(unit, mem, &lpm_entry, MODE_MASK0_UPRf, 3);
   5539     soc_mem_field32_set(unit, mem, &lpm_entry, MODE_MASK1_UPRf, 3);
   5540 
   5541     soc_mem_field32_set(unit, mem, &lpm_entry, ENTRY_TYPE_MASK0_LWRf, 1);
   5542     soc_mem_field32_set(unit, mem, &lpm_entry, ENTRY_TYPE_MASK1_LWRf, 1);
   5543     soc_mem_field32_set(unit, mem, &lpm_entry, ENTRY_TYPE_MASK0_UPRf, 1);
   5544     soc_mem_field32_set(unit, mem, &lpm_entry, ENTRY_TYPE_MASK1_UPRf, 1);    
   5545     
   5546     soc_mem_field32_set(unit, mem, &lpm_entry, MULTICAST_ROUTEf, 1);
   5547     soc_mem_field32_set(unit, mem, &lpm_entry, GLOBAL_ROUTEf, 1);
   5548     
   5549     soc_mem_field32_set(unit, mem, &lpm_entry, RPA_IDf, num_rp - 1);
   5550     /* 16383 indicate a max field value which is used as an invalid value */
   5551     soc_mem_field32_set(unit, mem, &lpm_entry, EXPECTED_L3_IIFf, 16383);
   5552 
   5553     soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR0_LWRf, 0);
   5554     soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR1_LWRf, 0);
   5555     soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR0_UPRf, 0);
   5556     /* IPv6 multicast route address starts from ff00 for default match */
   5557     soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR1_UPRf, 0xff000000);
   5558         
   5559     soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR_MASK0_LWRf, 0);
   5560     soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR_MASK1_UPRf, 0);
   5561     soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR_MASK0_LWRf, 0);
   5562     soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR_MASK1_UPRf, 0xff000000);
   5563 
   5564     if (install) {
   5565         if (soc_feature(unit, soc_feature_alpm_flex_stat)) {
   5566             soc_mem_field32_set(unit, mem, &lpm_entry, ENTRY_VIEWf, 0x1);
   5567             VRF_FLEX_SET(unit, SOC_L3_VRF_GLOBAL, SOC_VRF_MAX(unit) + 1, L3_DEFIP_MODE_128, 1);
   5568         }
   5569         SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_insert(unit, &lpm_entry, &index,
   5570                                                     0, 0, INVALID_BPM_LEN));
   5571     } else {
   5572         SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_delete(unit, &lpm_entry));
   5573     }
   5574 
   5575     return SOC_E_NONE;
   5576 }
   5577 
   5578 /*
   5579  * Initialize the start/end tracking pointers for each prefix length
   5580  */
   5581 int
   5582 soc_alpm_128_lpm_init(int u)
   5583 {
   5584     int max_pfx_len;
   5585     int i;
   5586     int defip_table_size;
   5587     int pfx_state_size;
   5588 
   5589     if (! soc_feature(u, soc_feature_lpm_tcam)) {
   5590         return(SOC_E_UNAVAIL);
   5591     }
   5592 
   5593     max_pfx_len = MAX_PFX_ENTRIES_128;
   5594 
   5595     pfx_state_size = sizeof(soc_alpm_128_lpm_state_t) * (max_pfx_len);
   5596 
   5597     if (SOC_ALPM_128_LPM_INIT_CHECK(u)) {
   5598         /* this is a reinit. clean up old state */
   5599         SOC_IF_ERROR_RETURN(soc_alpm_128_deinit(u));
   5600     }
   5601     soc_lpm_128_field_cache_state[u] = 
   5602            sal_alloc(sizeof(soc_lpm_128_field_cache_t), "lpm_128_field_state");
   5603     if (NULL == soc_lpm_128_field_cache_state[u]) {
   5604         return (SOC_E_MEMORY);
   5605     }
   5606     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5607                                     L3_DEFIP_PAIR_128m, CLASS_IDf);
   5608     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5609                                     L3_DEFIP_PAIR_128m, DST_DISCARDf);
   5610     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5611                                     L3_DEFIP_PAIR_128m, ECMPf);
   5612     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5613                                     L3_DEFIP_PAIR_128m, ECMP_COUNTf);
   5614     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5615                                     L3_DEFIP_PAIR_128m, ECMP_PTRf);
   5616     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5617                                     L3_DEFIP_PAIR_128m, GLOBAL_ROUTEf);
   5618     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5619                                     L3_DEFIP_PAIR_128m, MULTICAST_ROUTEf);
   5620     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5621                                     L3_DEFIP_PAIR_128m, RPA_IDf);
   5622     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5623                                     L3_DEFIP_PAIR_128m, EXPECTED_L3_IIFf);    
   5624     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5625                                     L3_DEFIP_PAIR_128m, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf);
   5626     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5627                                     L3_DEFIP_PAIR_128m, IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf);
   5628     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5629                                     L3_DEFIP_PAIR_128m, L3MC_INDEXf);
   5630     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5631                                     L3_DEFIP_PAIR_128m, HITf);
   5632     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5633                                     L3_DEFIP_PAIR_128m, IP_ADDR0_LWRf);
   5634     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5635                                     L3_DEFIP_PAIR_128m, IP_ADDR0_UPRf);
   5636     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5637                                     L3_DEFIP_PAIR_128m, IP_ADDR1_LWRf);
   5638     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5639                                     L3_DEFIP_PAIR_128m, IP_ADDR1_UPRf);
   5640     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5641                                     L3_DEFIP_PAIR_128m, IP_ADDR_MASK0_LWRf);
   5642     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5643                                     L3_DEFIP_PAIR_128m, IP_ADDR_MASK0_UPRf);
   5644     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5645                                     L3_DEFIP_PAIR_128m, IP_ADDR_MASK1_LWRf);
   5646     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5647                                     L3_DEFIP_PAIR_128m, IP_ADDR_MASK1_UPRf);
   5648     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5649                                     L3_DEFIP_PAIR_128m, MODE0_LWRf);
   5650     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5651                                     L3_DEFIP_PAIR_128m, MODE0_UPRf);
   5652     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5653                                     L3_DEFIP_PAIR_128m, MODE1_LWRf);
   5654     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5655                                     L3_DEFIP_PAIR_128m, MODE1_UPRf);
   5656     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5657                                     L3_DEFIP_PAIR_128m, MODE_MASK0_LWRf);
   5658     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5659                                     L3_DEFIP_PAIR_128m, MODE_MASK0_UPRf);
   5660     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5661                                     L3_DEFIP_PAIR_128m, MODE_MASK1_LWRf);
   5662     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5663                                     L3_DEFIP_PAIR_128m, MODE_MASK1_UPRf);
   5664     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5665                                     L3_DEFIP_PAIR_128m, NEXT_HOP_INDEXf);
   5666     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5667                                     L3_DEFIP_PAIR_128m, PRIf);
   5668     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5669                                     L3_DEFIP_PAIR_128m, RPEf);
   5670     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5671                                     L3_DEFIP_PAIR_128m, VALID0_LWRf);
   5672     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5673                                     L3_DEFIP_PAIR_128m, VALID0_UPRf);
   5674     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5675                                     L3_DEFIP_PAIR_128m, VALID1_LWRf);
   5676     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5677                                     L3_DEFIP_PAIR_128m, VALID1_UPRf);
   5678     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5679                                     L3_DEFIP_PAIR_128m, VRF_ID_0_LWRf);
   5680     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5681                                     L3_DEFIP_PAIR_128m, VRF_ID_0_UPRf);
   5682     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5683                                     L3_DEFIP_PAIR_128m, VRF_ID_1_LWRf);
   5684     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5685                                     L3_DEFIP_PAIR_128m, VRF_ID_1_UPRf);
   5686     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5687                                     L3_DEFIP_PAIR_128m, VRF_ID_MASK0_LWRf);
   5688     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5689                                     L3_DEFIP_PAIR_128m, VRF_ID_MASK0_UPRf);
   5690     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5691                                     L3_DEFIP_PAIR_128m, VRF_ID_MASK1_LWRf);
   5692     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5693                                     L3_DEFIP_PAIR_128m, VRF_ID_MASK1_UPRf);
   5694     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5695                                     L3_DEFIP_PAIR_128m, GLOBAL_HIGHf);
   5696     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5697                                     L3_DEFIP_PAIR_128m, ALG_HIT_IDXf);
   5698     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5699                                     L3_DEFIP_PAIR_128m, ALG_BKT_PTRf);
   5700     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5701                                     L3_DEFIP_PAIR_128m, DEFAULT_MISSf);
   5702     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5703                                     L3_DEFIP_PAIR_128m,
   5704                                     FLEX_CTR_BASE_COUNTER_IDXf);
   5705     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5706                                     L3_DEFIP_PAIR_128m,
   5707                                     FLEX_CTR_OFFSET_MODEf);
   5708     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5709                                     L3_DEFIP_PAIR_128m,
   5710                                     FLEX_CTR_POOL_NUMBERf);
   5711 
   5712     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5713                                     L3_DEFIP_PAIR_128m,
   5714                                     ENTRY_TYPE_MASK0_LWRf);
   5715     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5716                                     L3_DEFIP_PAIR_128m,
   5717                                     ENTRY_TYPE_MASK1_LWRf);
   5718     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5719                                     L3_DEFIP_PAIR_128m,
   5720                                     ENTRY_TYPE_MASK0_UPRf);
   5721     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5722                                     L3_DEFIP_PAIR_128m,
   5723                                     ENTRY_TYPE_MASK1_UPRf);
   5724     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5725                                     L3_DEFIP_PAIR_128m,
   5726                                     ENTRY_TYPE0_LWRf);
   5727     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5728                                     L3_DEFIP_PAIR_128m,
   5729                                     ENTRY_TYPE1_LWRf);
   5730     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5731                                     L3_DEFIP_PAIR_128m,
   5732                                     ENTRY_TYPE0_UPRf);
   5733     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5734                                     L3_DEFIP_PAIR_128m,
   5735                                     ENTRY_TYPE1_UPRf);
   5736     SOC_ALPM_128_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_128_field_cache_state[u],
   5737                                     L3_DEFIP_PAIR_128m,
   5738                                     ENTRY_VIEWf);
   5739 
   5740     SOC_ALPM_128_LPM_STATE(u) = sal_alloc(pfx_state_size, 
   5741                                           "LPM 128 prefix info");
   5742     if (NULL == SOC_ALPM_128_LPM_STATE(u)) {
   5743         sal_free(soc_lpm_128_field_cache_state[u]);
   5744         soc_lpm_128_field_cache_state[u] = NULL;
   5745         return (SOC_E_MEMORY);
   5746     }
   5747 
   5748 #ifdef FB_LPM_TABLE_CACHED
   5749     SOC_IF_ERROR_RETURN (soc_mem_cache_set(u, L3_DEFIP_PAIR_128m, 
   5750                                            MEM_BLOCK_ALL, TRUE));
   5751 #endif /* FB_LPM_TABLE_CACHED */
   5752     SOC_ALPM_LPM_LOCK(u);
   5753 
   5754     sal_memset(SOC_ALPM_128_LPM_STATE(u), 0, pfx_state_size);
   5755     for(i = 0; i < max_pfx_len; i++) {
   5756         SOC_ALPM_128_LPM_STATE_START(u, i) = -1;
   5757         SOC_ALPM_128_LPM_STATE_END(u, i) = -1;
   5758         SOC_ALPM_128_LPM_STATE_PREV(u, i) = -1;
   5759         SOC_ALPM_128_LPM_STATE_NEXT(u, i) = -1;
   5760         SOC_ALPM_128_LPM_STATE_VENT(u, i) = 0;
   5761         SOC_ALPM_128_LPM_STATE_FENT(u, i) = 0;
   5762     }
   5763 
   5764     defip_table_size = soc_mem_index_count(u, L3_DEFIP_PAIR_128m);
   5765 
   5766     /* RPF supported, then the table is partitioned for DIP and SIP */
   5767     if (SOC_URPF_STATUS_GET(u)) {
   5768         defip_table_size >>= 1;
   5769     }
   5770 
   5771     if (soc_alpm_mode_get(u) == SOC_ALPM_MODE_PARALLEL) {
   5772         
   5773         /* For Parallel search, the TCAM is hard paritioned.
   5774         * First half are for VRF specific, the bottom half for override and 
   5775         * global. Start of Global entries start at the bottom half of TCAM
   5776         */
   5777         SOC_ALPM_128_LPM_STATE_END(u, MAX_PFX_INDEX_128) = 
   5778                                                     (defip_table_size>>1) - 1;
   5779 
   5780         /* Free entries for VRF */
   5781         SOC_ALPM_128_LPM_STATE_FENT(u, (MAX_VRF_PFX_INDEX_128)) = 
   5782                                                     defip_table_size >> 1;
   5783 
   5784         /* Remaining entries are assigned to Global entries */
   5785         SOC_ALPM_128_LPM_STATE_FENT(u, (MAX_PFX_INDEX_128)) = 
   5786           (defip_table_size - SOC_ALPM_128_LPM_STATE_FENT(u, 
   5787                                                      (MAX_VRF_PFX_INDEX_128)));
   5788     } else {
   5789         /* Remaining entries are assigned to Global entries */
   5790         SOC_ALPM_128_LPM_STATE_FENT(u, (MAX_PFX_INDEX_128)) = defip_table_size;
   5791     }
   5792 
   5793 #ifdef FB_LPM_128_HASH_SUPPORT
   5794     if (SOC_ALPM_128_LPM_STATE_HASH(u) != NULL) {
   5795         if (_soc_alpm_128_lpm_hash_destroy(SOC_ALPM_128_LPM_STATE_HASH(u)) < 0){
   5796             SOC_ALPM_LPM_UNLOCK(u);
   5797             return SOC_E_INTERNAL;
   5798         }
   5799         SOC_ALPM_128_LPM_STATE_HASH(u) = NULL;
   5800     }
   5801 
   5802     if (_soc_alpm_128_lpm_hash_create(u, defip_table_size * 2, defip_table_size,
   5803                                 &SOC_ALPM_128_LPM_STATE_HASH(u)) < 0) {
   5804         SOC_ALPM_LPM_UNLOCK(u);
   5805         return SOC_E_MEMORY;
   5806     }
   5807 #endif
   5808 
   5809     (void)soc_alpm_128_ipmc_war(u, TRUE);
   5810 
   5811     SOC_ALPM_LPM_UNLOCK(u);
   5812     return(SOC_E_NONE);
   5813 }
   5814 
   5815 /*
   5816  * De-initialize the start/end tracking pointers for each prefix length
   5817  */
   5818 int
   5819 soc_alpm_128_lpm_deinit(int u)
   5820 {
   5821     if (!soc_feature(u, soc_feature_lpm_tcam)) {
   5822         return(SOC_E_UNAVAIL);
   5823     }
   5824 
   5825     SOC_ALPM_LPM_LOCK(u);
   5826 
   5827 #ifdef FB_LPM_128_HASH_SUPPORT
   5828     if (SOC_ALPM_128_LPM_STATE_HASH(u) != NULL) {
   5829         _soc_alpm_128_lpm_hash_destroy(SOC_ALPM_128_LPM_STATE_HASH(u));
   5830         SOC_ALPM_128_LPM_STATE_HASH(u) = NULL;
   5831     }
   5832 #endif
   5833 
   5834     if (SOC_ALPM_128_LPM_INIT_CHECK(u)) {
   5835         sal_free(soc_lpm_128_field_cache_state[u]);
   5836         soc_lpm_128_field_cache_state[u] = NULL;
   5837         sal_free(SOC_ALPM_128_LPM_STATE(u));
   5838         SOC_ALPM_128_LPM_STATE(u) = NULL;
   5839     }
   5840 
   5841     SOC_ALPM_LPM_UNLOCK(u);
   5842 
   5843     return(SOC_E_NONE);
   5844 }
   5845 
   5846 /*
   5847  * Implementation using soc_mem_read/write using entry rippling technique
   5848  * Advantage: A completely sorted table is not required. Lookups can be slow
   5849  * as it will perform a linear search on the entries for a given prefix length.
   5850  * No device access necessary for the search if the table is cached. Auxiliary
   5851  * hash table can be maintained to speed up search(Not implemented) instead of
   5852  * performing a linear search.
   5853  * Small number of entries need to be moved around (97 worst case)
   5854  * for performing insert/update/delete. However CPU needs to do all
   5855  * the work to move the entries.
   5856  */
   5857 
   5858 
   5859 /*
   5860  * soc_alpm_128_lpm_insert
   5861  * Moving multiple entries around in h/w vs  doing a linear search in s/w
   5862  * src_default: for sip entry if any
   5863  *              0 - caculate using entry_data's mask (legacy way)
   5864  *              1 - force set (split case)
   5865  * src_discard: for sip entry if any
   5866  */
   5867 static int
   5868 soc_alpm_128_lpm_insert(int u, void *entry_data, int *lpm_index,
   5869                         int src_default, int src_discard, int bpm_len)
   5870 {
   5871     int         pfx;
   5872     int         index;
   5873     int         ipv6;
   5874     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   5875     int         rv = SOC_E_NONE;
   5876     int         found = 0;
   5877     int         vrf, vrf_id;
   5878 			
   5879     sal_memcpy(e, soc_mem_entry_null(u, L3_DEFIP_PAIR_128m),
   5880                soc_mem_entry_words(u,L3_DEFIP_PAIR_128m) * 4);
   5881     SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_vrf_get(u, entry_data, &vrf_id, &vrf));
   5882 
   5883     SOC_ALPM_LPM_LOCK(u);
   5884     rv = _soc_alpm_128_lpm_match(u, entry_data, e, &index, &pfx, &ipv6);
   5885     if (rv == SOC_E_NOT_FOUND) {
   5886         rv = _lpm_128_free_slot_create(u, pfx, ipv6, e, &index);
   5887         if (rv < 0) {
   5888             SOC_ALPM_LPM_UNLOCK(u);
   5889             return(rv);
   5890         }
   5891     } else {
   5892         found = 1;
   5893     }
   5894 
   5895     *lpm_index = index;
   5896 
   5897     if (rv == SOC_E_NONE) {
   5898         /* Entry already present. Update the entry */
   5899         soc_alpm_128_lpm_state_dump(u);
   5900         LOG_INFO(BSL_LS_SOC_ALPM,
   5901                  (BSL_META_U(u,
   5902                              "\nsoc_alpm_128_lpm_insert: %d %d\n"),
   5903                   index, pfx));
   5904 
   5905         rv = _soc_alpm_128_write_pivot_with_bpm(u, index,
   5906                                 index, entry_data,
   5907                                 WRITE_PIVOT_WITH_URPF_PARAMS | 
   5908                                 (found ? WRITE_PIVOT_WITHOUT_INSERT_HASH : 0),
   5909                                 src_default, src_discard, bpm_len);
   5910         if (!found && SOC_SUCCESS(rv)) {
   5911             VRF_PIVOT_REF_INC(u, vrf_id, vrf, ipv6);
   5912         }
   5913     }
   5914 
   5915     SOC_ALPM_LPM_UNLOCK(u);
   5916 
   5917     return(rv);
   5918 }
   5919 
   5920 /*
   5921  * soc_alpm_128_lpm_delete
   5922  */
   5923 static int
   5924 soc_alpm_128_lpm_delete(int u, void *key_data)
   5925 {
   5926     int         pfx;
   5927     int         index;
   5928     int         ipv6;
   5929     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   5930     int         rv = SOC_E_NONE;
   5931     int         vrf, vrf_id;
   5932 
   5933     SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   5934 
   5935     SOC_ALPM_LPM_LOCK(u);
   5936     rv = _soc_alpm_128_lpm_match(u, key_data, e, &index, &pfx, &ipv6);
   5937     if (rv == SOC_E_NONE) {
   5938         LOG_INFO(BSL_LS_SOC_ALPM,
   5939                  (BSL_META_U(u,
   5940                              "\nsoc_alpm_lpm_delete: %d %d\n"),
   5941                   index, pfx));
   5942         LPM_128_HASH_DELETE(u, key_data, index);
   5943         rv = _lpm_128_free_slot_delete(u, pfx, ipv6, e, index);
   5944     }
   5945     if (SOC_SUCCESS(rv)) {
   5946         VRF_PIVOT_REF_DEC(u, vrf_id, vrf, ipv6);
   5947     }
   5948     soc_alpm_128_lpm_state_dump(u);
   5949     SOC_ALPM_LPM_UNLOCK(u);
   5950     return(rv);
   5951 }
   5952 
   5953 /*
   5954  * soc_alpm_128_lpm_match (Exact match for the key. Will match both IP
   5955  *                   address and mask)
   5956  */
   5957 static int
   5958 soc_alpm_128_lpm_match(int u,
   5959                void *key_data,
   5960                void *e,         /* return entry data if found */
   5961                int *index_ptr)  /* return key location */
   5962 {
   5963     int        pfx;
   5964     int        rv;
   5965     int        ipv6;
   5966 
   5967     SOC_ALPM_LPM_LOCK(u);
   5968     rv = _soc_alpm_128_lpm_match(u, key_data, e, index_ptr, &pfx, &ipv6);
   5969     SOC_ALPM_LPM_UNLOCK(u);
   5970     return(rv);
   5971 }
   5972 
   5973 /* Fill Aux entry for operation */
   5974 static int
   5975 _soc_alpm_128_fill_aux_entry_for_op(int unit,
   5976                void *key_data,
   5977                int ipv6,    /* Entry is ipv6. */
   5978                int db_type, /* database type */
   5979                int ent_type,
   5980                int replace_len, /* used for DElete propagate */
   5981                defip_aux_scratch_entry_t *aux_entry)       
   5982 {
   5983     uint32 ipv4a;
   5984     uint32 ip6_word[4] = {0, 0, 0, 0};
   5985     int    pfx = 0;
   5986     int    rv = SOC_E_NONE;
   5987 
   5988     sal_memset(aux_entry, 0, sizeof(defip_aux_scratch_entry_t));
   5989 
   5990     /* pick one of 4 valid bits */
   5991     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data, 
   5992                                 VALID0_LWRf);
   5993     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, VALIDf, ipv4a);
   5994 
   5995     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data, MODE0_LWRf);
   5996     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, MODEf, ipv4a);
   5997 
   5998     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data, 
   5999                                 ENTRY_TYPE0_LWRf);
   6000     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry,
   6001                         ENTRY_TYPEf, ent_type);
   6002 
   6003     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data, 
   6004                                 GLOBAL_ROUTEf);
   6005     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, 
   6006                         GLOBAL_ROUTEf, ipv4a);
   6007 
   6008     if (soc_feature(unit, soc_feature_ipmc_defip)) {
   6009         
   6010         ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data,
   6011                 EXPECTED_L3_IIFf);
   6012         soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry,
   6013                 EXPECTED_L3_IIFf, ipv4a);
   6014         ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data,
   6015                 RPA_IDf);
   6016         soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry,
   6017                 RPA_IDf, ipv4a);
   6018         ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data,
   6019                 IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf);
   6020         soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry,
   6021                 IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf, ipv4a);
   6022         ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data,
   6023                 IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf);
   6024         soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry,
   6025                 IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf, ipv4a);
   6026         ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data,
   6027                 L3MC_INDEXf);
   6028         soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry,
   6029                 L3MC_INDEXf, ipv4a);
   6030     }
   6031 
   6032     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data, ECMPf);
   6033     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, ECMPf, ipv4a);
   6034 
   6035     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data, ECMP_PTRf);
   6036     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, ECMP_PTRf, ipv4a);
   6037 
   6038     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data, 
   6039                                 NEXT_HOP_INDEXf);
   6040     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, 
   6041                         NEXT_HOP_INDEXf, ipv4a);
   6042 
   6043     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data, PRIf);
   6044     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, PRIf, ipv4a);
   6045 
   6046     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data, RPEf);
   6047     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, RPEf, ipv4a);
   6048 
   6049     ipv4a =soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data, 
   6050                                VRF_ID_0_LWRf);
   6051     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, VRFf, ipv4a);
   6052 
   6053     /* Set Database type */
   6054     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, DB_TYPEf, 
   6055                         db_type);
   6056 
   6057     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data, 
   6058                                 DST_DISCARDf);
   6059     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, DST_DISCARDf, 
   6060                         ipv4a);
   6061 
   6062     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data,
   6063                                 DEFAULT_MISSf);
   6064     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, DEFAULT_MISSf,
   6065                         ipv4a);
   6066 
   6067     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data, CLASS_IDf);
   6068     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, CLASS_IDf, 
   6069                         ipv4a);
   6070 
   6071     /* Set IP Address and IP length */
   6072     ip6_word[0] = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data, 
   6073                                       IP_ADDR0_LWRf);
   6074     ip6_word[1] = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data, 
   6075                                       IP_ADDR1_LWRf);
   6076     ip6_word[2] = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data, 
   6077                                       IP_ADDR0_UPRf);
   6078     ip6_word[3] = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, key_data, 
   6079                                       IP_ADDR1_UPRf);
   6080     soc_mem_field_set(unit, L3_DEFIP_AUX_SCRATCHm, (uint32*)aux_entry,
   6081                       IP_ADDRf, (uint32*)ip6_word);
   6082 
   6083     rv = _soc_alpm_128_ip6_mask_len_get(unit, key_data, &pfx);
   6084     if (SOC_FAILURE(rv)) {
   6085         return rv;
   6086     }
   6087     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, IP_LENGTHf,pfx);
   6088     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, REPLACE_LENf,
   6089                         replace_len);
   6090 
   6091     ipv4a = SOC_MEM_OPT_F32_GET_128(unit, L3_DEFIP_PAIR_128m, key_data, FLEX_CTR_BASE_COUNTER_IDXf);
   6092     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, FLEX_CTR_BASE_COUNTER_IDXf, ipv4a);
   6093 
   6094     ipv4a = SOC_MEM_OPT_F32_GET_128(unit, L3_DEFIP_PAIR_128m, key_data, FLEX_CTR_OFFSET_MODEf);
   6095     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, FLEX_CTR_OFFSET_MODEf, ipv4a);
   6096 
   6097     ipv4a = SOC_MEM_OPT_F32_GET_128(unit, L3_DEFIP_PAIR_128m, key_data, FLEX_CTR_POOL_NUMBERf);
   6098     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, FLEX_CTR_POOL_NUMBERf, ipv4a);
   6099 
   6100     return (SOC_E_NONE);
   6101 }
   6102 
   6103 
   6104 /* Initialize the ALPM memory from a TCAM entry */
   6105 static int
   6106 _soc_alpm_128_mem_ent_init(int unit, void *lpm_entry, 
   6107                        void *alpm_entry, void *alpm_sip_entry, soc_mem_t mem,
   6108                        uint32 src_flags, uint32 *is_default)
   6109 {
   6110     uint32 ipv4a;
   6111     uint32 ip6_word[4];
   6112     int    pfx = 0;
   6113     int    rv = SOC_E_NONE;
   6114     uint32 default_route = 0;
   6115 
   6116     /* Zero Buffer */
   6117     sal_memset(alpm_entry, 0, soc_mem_entry_words(unit, mem) * 4);
   6118 
   6119     if (!soc_feature(unit, soc_feature_alpm_hit_bits_not_support)) {
   6120         ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, HITf);
   6121         soc_mem_field32_set(unit, mem, alpm_entry, HITf, ipv4a);
   6122     }
   6123 
   6124     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6125             VALID0_LWRf);
   6126     soc_mem_field32_set(unit, mem, alpm_entry, VALIDf, ipv4a);
   6127 
   6128     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, ECMPf);
   6129     soc_mem_field32_set(unit, mem, alpm_entry, ECMPf, ipv4a);
   6130 
   6131     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, ECMP_PTRf);
   6132     soc_mem_field32_set(unit, mem, alpm_entry, ECMP_PTRf, ipv4a);
   6133 
   6134     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6135                                 NEXT_HOP_INDEXf);
   6136     soc_mem_field32_set(unit, mem, alpm_entry, NEXT_HOP_INDEXf, ipv4a);
   6137 
   6138     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, PRIf);
   6139     soc_mem_field32_set(unit, mem, alpm_entry, PRIf, ipv4a);
   6140 
   6141     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, RPEf);
   6142     soc_mem_field32_set(unit, mem, alpm_entry, RPEf, ipv4a);
   6143 
   6144     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6145                                 DST_DISCARDf);
   6146     soc_mem_field32_set(unit, mem, alpm_entry, DST_DISCARDf, ipv4a);
   6147 
   6148     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6149                                 SRC_DISCARDf);
   6150     soc_mem_field32_set(unit, mem, alpm_entry, SRC_DISCARDf, ipv4a);
   6151 
   6152     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, CLASS_IDf);
   6153     soc_mem_field32_set(unit, mem, alpm_entry, CLASS_IDf, ipv4a);
   6154 
   6155     /* Set IP Address and IP length */
   6156     ip6_word[0] = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6157                                       IP_ADDR0_LWRf);
   6158     ip6_word[1] = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6159                                       IP_ADDR1_LWRf);
   6160     ip6_word[2] = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6161                                       IP_ADDR0_UPRf);
   6162     ip6_word[3] = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6163                                       IP_ADDR1_UPRf);
   6164     soc_mem_field_set(unit, mem, (uint32*)alpm_entry, KEYf, (uint32*)ip6_word);
   6165 
   6166     rv = _soc_alpm_128_ip6_mask_len_get(unit, lpm_entry, &pfx);
   6167     if (SOC_FAILURE(rv)) {
   6168         return rv;
   6169     }
   6170 
   6171     if ((pfx == 0) && (ip6_word[0] == 0) && (ip6_word[1] == 0) && 
   6172         (ip6_word[2] == 0) && (ip6_word[3] == 0)) {
   6173         default_route = 1;
   6174     }
   6175     if (is_default != NULL) {
   6176         *is_default = default_route;
   6177     }
   6178     soc_mem_field32_set(unit, mem, alpm_entry, LENGTHf, pfx);
   6179 
   6180     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, FLEX_CTR_BASE_COUNTER_IDXf);
   6181     soc_mem_field32_set(unit, mem, alpm_entry, FLEX_CTR_BASE_COUNTER_IDXf, ipv4a);
   6182 
   6183     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, FLEX_CTR_OFFSET_MODEf);
   6184     soc_mem_field32_set(unit, mem, alpm_entry, FLEX_CTR_OFFSET_MODEf, ipv4a);
   6185 
   6186     ipv4a = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, FLEX_CTR_POOL_NUMBERf);
   6187     soc_mem_field32_set(unit, mem, alpm_entry, FLEX_CTR_POOL_NUMBERf, ipv4a);
   6188 
   6189     if (alpm_sip_entry == NULL) {
   6190         return (SOC_E_NONE);
   6191     }
   6192     if (SOC_URPF_STATUS_GET(unit)) {
   6193         sal_memset(alpm_sip_entry, 0, soc_mem_entry_words(unit, mem) * 4);
   6194         sal_memcpy(alpm_sip_entry, alpm_entry, soc_mem_entry_words(unit, mem) * 4);
   6195         soc_mem_field32_set(unit, mem, alpm_sip_entry, DST_DISCARDf, 0);
   6196         soc_mem_field32_set(unit, mem, alpm_sip_entry, RPEf, 0);
   6197 
   6198         soc_mem_field32_set(unit, mem, alpm_sip_entry, SRC_DISCARDf, 
   6199                             src_flags & SOC_ALPM_RPF_SRC_DISCARD);
   6200         soc_mem_field32_set(unit, mem, alpm_sip_entry, DEFAULTROUTEf, 
   6201                             default_route);
   6202     }
   6203     return (SOC_E_NONE);
   6204 }
   6205 
   6206 /* Initialize the TCAM entry from ALPM memory */
   6207 static int
   6208 _soc_alpm_128_lpm_ent_init(int unit, void *alpm_entry, soc_mem_t mem, int ipv6, 
   6209                        int vrf_id, int bucket, int index, void *lpm_entry,
   6210                        int flex)
   6211 {
   6212     uint32 ipv4a;
   6213     uint32 ip6_word[4];
   6214     uint32 mvrf, mvrf_mask;
   6215 
   6216     /* Zero Buffer */
   6217     sal_memset(lpm_entry, 0, soc_mem_entry_words(unit, L3_DEFIP_PAIR_128m) * 4);
   6218 
   6219     if (!soc_feature(unit, soc_feature_alpm_hit_bits_not_support)) {
   6220         ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, HITf);
   6221         soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, HITf, ipv4a);
   6222     }
   6223 
   6224     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, VALIDf);
   6225     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6226                         VALID0_LWRf, ipv4a);
   6227     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6228                         VALID1_LWRf, ipv4a);
   6229     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6230                         VALID0_UPRf, ipv4a);
   6231     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6232                         VALID1_UPRf, ipv4a);
   6233 
   6234     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, ECMPf);
   6235     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, ECMPf, ipv4a);
   6236 
   6237     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, ECMP_PTRf);
   6238     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, ECMP_PTRf, ipv4a);
   6239 
   6240     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, NEXT_HOP_INDEXf);
   6241     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6242                         NEXT_HOP_INDEXf, ipv4a);
   6243 
   6244     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, PRIf);
   6245     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, PRIf, ipv4a);
   6246 
   6247     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, RPEf);
   6248     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, RPEf, ipv4a);
   6249 
   6250     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, DST_DISCARDf);
   6251     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, DST_DISCARDf, ipv4a);
   6252 
   6253     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, SRC_DISCARDf);
   6254     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, SRC_DISCARDf, ipv4a);
   6255 
   6256     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, CLASS_IDf);
   6257     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, CLASS_IDf, ipv4a);
   6258 
   6259     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, ALG_BKT_PTRf, 
   6260                         bucket);
   6261     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, ALG_HIT_IDXf, 
   6262                         index);
   6263 
   6264     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6265                         MODE_MASK0_LWRf, 3);
   6266     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6267                         MODE_MASK1_LWRf, 3);
   6268     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6269                         MODE_MASK0_UPRf, 3);
   6270     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6271                         MODE_MASK1_UPRf, 3);
   6272 
   6273     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6274                         ENTRY_TYPE_MASK0_LWRf, 1);
   6275     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6276                         ENTRY_TYPE_MASK1_LWRf, 1);
   6277     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6278                         ENTRY_TYPE_MASK0_UPRf, 1);
   6279     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6280                         ENTRY_TYPE_MASK1_UPRf, 1);
   6281 
   6282     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, MODE0_LWRf, 3);
   6283     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, MODE1_LWRf, 3);
   6284     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, MODE0_UPRf, 3);
   6285     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, MODE1_UPRf, 3);
   6286 
   6287     /* Set IP Address and IP length */
   6288     soc_mem_field_get(unit, mem, alpm_entry, KEYf, ip6_word);
   6289     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, IP_ADDR0_LWRf,
   6290                         ip6_word[0]);
   6291     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, IP_ADDR1_LWRf,
   6292                         ip6_word[1]);
   6293     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, IP_ADDR0_UPRf,
   6294                         ip6_word[2]);
   6295     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, IP_ADDR1_UPRf,
   6296                         ip6_word[3]);
   6297 
   6298     ip6_word[0] = ip6_word[1] = ip6_word[2] = ip6_word[3] = 0;
   6299 
   6300     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, LENGTHf);
   6301     _soc_alpm_128_pfx_len_to_mask(unit, lpm_entry, ipv4a);
   6302 
   6303     if (vrf_id == SOC_L3_VRF_OVERRIDE) {
   6304         soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry,
   6305                             GLOBAL_HIGHf, 1);
   6306         soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry,
   6307                             GLOBAL_ROUTEf, 1);
   6308         mvrf = 0;
   6309         mvrf_mask = 0;
   6310     } else  if (vrf_id == SOC_L3_VRF_GLOBAL) {
   6311         soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry,
   6312                             GLOBAL_ROUTEf, 1);
   6313         mvrf = 0;
   6314         mvrf_mask = 0;
   6315     } else {
   6316         mvrf = vrf_id;
   6317         mvrf_mask = SOC_VRF_MAX(unit);
   6318     }
   6319     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, ENTRY_VIEWf, flex);
   6320     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6321                         VRF_ID_0_LWRf, mvrf);
   6322     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6323                         VRF_ID_1_LWRf, mvrf);
   6324     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6325                         VRF_ID_0_UPRf, mvrf);
   6326     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6327                         VRF_ID_1_UPRf, mvrf);
   6328 
   6329     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6330                         VRF_ID_MASK0_LWRf, mvrf_mask);
   6331     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6332                         VRF_ID_MASK1_LWRf, mvrf_mask);
   6333     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6334                         VRF_ID_MASK0_UPRf, mvrf_mask);
   6335     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, 
   6336                         VRF_ID_MASK1_UPRf, mvrf_mask);
   6337 
   6338 
   6339     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, FLEX_CTR_BASE_COUNTER_IDXf);
   6340     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, FLEX_CTR_BASE_COUNTER_IDXf, ipv4a);
   6341 
   6342     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, FLEX_CTR_OFFSET_MODEf);
   6343     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, FLEX_CTR_OFFSET_MODEf, ipv4a);
   6344 
   6345     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, FLEX_CTR_POOL_NUMBERf);
   6346     soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, lpm_entry, FLEX_CTR_POOL_NUMBERf, ipv4a);
   6347 
   6348     return (SOC_E_NONE);
   6349 }
   6350 
   6351 int 
   6352 soc_alpm_128_warmboot_pivot_add(int unit,
   6353                                 int ipv6,
   6354                                 void *lpm_entry,
   6355                                 int tcam_idx, 
   6356                                 int bckt_idx)
   6357 {
   6358     int                  rv = SOC_E_NONE;
   6359     uint32               key[4] = {0, 0, 0, 0};
   6360     alpm_pivot_t         *pivot = NULL;
   6361     alpm_bucket_handle_t *bucket_handle = NULL;
   6362     int                  vrf_id = 0, vrf = 0;
   6363     uint32               length2;
   6364     trie_t               *pivot_root = NULL;
   6365     uint32               prefix[5] = {0};
   6366     uint32               bpm_len = 0;
   6367     int                  default_route = 0;
   6368     defip_aux_table_entry_t aux_ent;
   6369 
   6370     rv = _alpm_128_prefix_create(unit, lpm_entry, prefix, &length2, &default_route);
   6371     SOC_IF_ERROR_RETURN(rv);
   6372 
   6373     SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf));
   6374     tcam_idx = soc_alpm_physical_idx(unit, L3_DEFIP_PAIR_128m, tcam_idx, ipv6);
   6375 
   6376     /* Allocate bucket handle */
   6377     bucket_handle = sal_alloc(sizeof(alpm_bucket_handle_t), "ALPM Bucket Handle");
   6378     if (bucket_handle == NULL) {
   6379         LOG_ERROR(BSL_LS_SOC_ALPM,
   6380                   (BSL_META_U(unit,
   6381                               "Unable to allocate memory for PIVOT trie node \n")));
   6382         return SOC_E_NONE;
   6383     }
   6384     sal_memset(bucket_handle, 0, sizeof(*bucket_handle));
   6385 
   6386     /* Allocate pivot Payload */
   6387     pivot = sal_alloc(sizeof(alpm_pivot_t), "Payload for Pivot");
   6388     if (pivot == NULL) {
   6389         LOG_ERROR(BSL_LS_SOC_ALPM,
   6390                   (BSL_META_U(unit,
   6391                               "Unable to allocate memory for PIVOT trie node \n")));
   6392         sal_free(bucket_handle);
   6393         return SOC_E_MEMORY;
   6394     }
   6395     sal_memset(pivot, 0, sizeof(*pivot));
   6396 
   6397     /* Save bucket_handle in pivot->bucket_trie */
   6398     PIVOT_BUCKET_HANDLE(pivot) = bucket_handle;
   6399    
   6400     trie_init(_MAX_KEY_LEN_144_, &PIVOT_BUCKET_TRIE(pivot));
   6401 
   6402     /* Set address to the buffer. */
   6403     key[0] = soc_L3_DEFIP_PAIR_128m_field32_get(unit, lpm_entry, IP_ADDR0_LWRf);
   6404     key[1] = soc_L3_DEFIP_PAIR_128m_field32_get(unit, lpm_entry, IP_ADDR1_LWRf);
   6405     key[2] = soc_L3_DEFIP_PAIR_128m_field32_get(unit, lpm_entry, IP_ADDR0_UPRf);
   6406     key[3] = soc_L3_DEFIP_PAIR_128m_field32_get(unit, lpm_entry, IP_ADDR1_UPRf);
   6407 
   6408     /* Save bucket index into pivot->bucket->bucket_index */
   6409     PIVOT_BUCKET_INDEX(pivot) = bckt_idx;
   6410    
   6411     /* Save tcam index into pivot->tcam_index */
   6412     PIVOT_TCAM_INDEX(pivot) = SOC_ALPM_128_ADDR_LWR(unit, tcam_idx) << 1;
   6413 
   6414     if (vrf_id != SOC_L3_VRF_OVERRIDE) {
   6415         pivot_root = VRF_PIVOT_TRIE_IPV6_128(unit, vrf);
   6416         if (pivot_root == NULL) {
   6417             trie_init(_MAX_KEY_LEN_144_, &VRF_PIVOT_TRIE_IPV6_128(unit, vrf));
   6418             pivot_root = VRF_PIVOT_TRIE_IPV6_128(unit, vrf);
   6419         }
   6420 
   6421         sal_memcpy(pivot->key, prefix, sizeof(prefix));
   6422         pivot->len    = length2;
   6423 
   6424         /* insert into pivot trie */
   6425         rv = soc_mem_read(unit, L3_DEFIP_AUX_TABLEm, SOC_BLOCK_ANY,
   6426                           SOC_ALPM_128_ADDR_LWR(unit, tcam_idx), &aux_ent);
   6427         if (SOC_SUCCESS(rv)) {
   6428             bpm_len = soc_mem_field32_get(unit, L3_DEFIP_AUX_TABLEm,
   6429                                           &aux_ent, BPM_LENGTH0f);
   6430         }
   6431 
   6432         rv = trie_insert(pivot_root, pivot->key, NULL, pivot->len, 
   6433                          (trie_node_t *)pivot);
   6434         if (SOC_FAILURE(rv)) {
   6435             sal_free(bucket_handle);
   6436             sal_free(pivot);
   6437             return rv;
   6438         }
   6439     }
   6440 
   6441     PIVOT_TCAM_BPMLEN(pivot) = bpm_len;
   6442     /* Insert pivot into global pivot array indexed by tcam_idx */
   6443     ALPM_TCAM_PIVOT(unit, SOC_ALPM_128_ADDR_LWR(unit, tcam_idx) << 1) = pivot;
   6444 
   6445     PIVOT_BUCKET_VRF(pivot) = vrf;
   6446     PIVOT_BUCKET_IPV6(pivot) = ipv6;
   6447     PIVOT_BUCKET_ENT_CNT_UPDATE(pivot);
   6448     if (key[0] == 0 && key[1] == 0 && key[2] == 0 && key[3] == 0) {
   6449         PIVOT_BUCKET_DEF(pivot) = TRUE;
   6450     }
   6451 
   6452     return rv;
   6453 }
   6454 
   6455 static int
   6456 _soc_alpm_128_warmboot_insert(int unit,
   6457                               int ipv6,
   6458                               void *lpm_entry, 
   6459                               void *alpm_entry, /* ALPM (SRAM) entry data */
   6460                               soc_mem_t mem,    /* Mem view for ALPM data */
   6461                               int tcam_idx,     /* TCAM index             */
   6462                               int bckt_idx,     /* Bucket index           */
   6463                               int alpm_idx )    /* ALPM entry index       */
   6464 {
   6465     int          vrf_id;   /* Internal API representation of VRF id           */
   6466     int          vrf;      /* VRF in 0 to (MAX_VRF + 1) range;                */
   6467                            /* VRF = (MAX_VRF + 1), software rep of GLOBAL VRF */
   6468     int          rv = SOC_E_NONE;
   6469     int          default_route = 0;
   6470     uint32       prefix[5] = {0, 0, 0, 0, 0};
   6471     uint32       length;
   6472     void         *temp_lpm_entry = NULL;
   6473     trie_t       *bkt_trie = NULL;
   6474     trie_t       *pfx_trie = NULL;
   6475     trie_node_t  *delp = NULL;
   6476     payload_t    *bkt_payload = NULL;
   6477     payload_t    *pfx_payload = NULL;
   6478     alpm_pivot_t *pivot_pyld = NULL;
   6479     defip_pair_128_entry_t *def_entry = NULL;
   6480 
   6481     /* Check function params */
   6482     if ((NULL == lpm_entry) || (NULL == alpm_entry)) {
   6483         return SOC_E_PARAM;
   6484     }
   6485 
   6486     /* Get VRF */
   6487     SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf));
   6488 
   6489     /* Get ALPM table memory. */
   6490     SOC_ALPM_TABLE_MEM_128(unit, ipv6, mem);
   6491 
   6492     temp_lpm_entry = sal_alloc(sizeof(defip_pair_128_entry_t), "Temp Defip Pair lpm_entry");
   6493     if (NULL == temp_lpm_entry) {
   6494         return SOC_E_MEMORY;
   6495     }
   6496 
   6497     /* Convert alpm_entry into lpm_entry to extract prefix */ 
   6498     SOC_IF_ERROR_RETURN(_soc_alpm_128_lpm_ent_init(unit, alpm_entry,  mem, ipv6, 
   6499                                                    vrf_id, bckt_idx, tcam_idx,
   6500                                                    temp_lpm_entry, 0));
   6501    
   6502     /* Create Prefix */
   6503     rv = _alpm_128_prefix_create(unit, temp_lpm_entry, prefix, &length, &default_route);
   6504     if (SOC_FAILURE(rv)) {
   6505         LOG_ERROR(BSL_LS_SOC_ALPM,
   6506                   (BSL_META_U(unit,
   6507                               "prefix create failed\n")));
   6508         return rv;
   6509     }
   6510 
   6511     sal_free(temp_lpm_entry);
   6512    
   6513     tcam_idx = soc_alpm_physical_idx(unit, L3_DEFIP_PAIR_128m, tcam_idx, ipv6);
   6514 
   6515     /* Get TCAM pivot */ 
   6516     pivot_pyld = ALPM_TCAM_PIVOT(unit, SOC_ALPM_128_ADDR_LWR(unit, tcam_idx) << 1);
   6517     
   6518     /* Get bucket trie from pivot */ 
   6519     bkt_trie = PIVOT_BUCKET_TRIE(pivot_pyld);
   6520    
   6521     /* Allocate bucket payload */
   6522     bkt_payload = sal_alloc(sizeof(payload_t), "Payload for Key");
   6523     if (NULL == bkt_payload) {
   6524         LOG_ERROR(BSL_LS_SOC_ALPM,
   6525                   (BSL_META_U(unit,
   6526                               "Unable to allocate memory for trie node.\n")));
   6527         return SOC_E_MEMORY;
   6528     }
   6529 
   6530     /* Allocate prefix trie payload */
   6531     pfx_payload = sal_alloc(sizeof(payload_t), "Payload for pfx trie key");
   6532     if (NULL == pfx_payload) {
   6533         LOG_ERROR(BSL_LS_SOC_ALPM,
   6534                   (BSL_META_U(unit,
   6535                               "Unable to allocate memory for pfx trie node\n")));
   6536         sal_free(bkt_payload);
   6537         return SOC_E_MEMORY;
   6538     }
   6539   
   6540     /* Clear allocated payloads */ 
   6541     sal_memset(bkt_payload, 0, sizeof(*bkt_payload));
   6542     sal_memset(pfx_payload, 0, sizeof(*pfx_payload));
   6543 
   6544     bkt_payload->key[0] = prefix[0]; 
   6545     bkt_payload->key[1] = prefix[1]; 
   6546     bkt_payload->key[2] = prefix[2]; 
   6547     bkt_payload->key[3] = prefix[3]; 
   6548     bkt_payload->key[4] = prefix[4]; 
   6549     bkt_payload->len    = length;
   6550     bkt_payload->index  = alpm_idx;
   6551  
   6552     /* Create duplicate for prefix trie */
   6553     sal_memcpy(pfx_payload, bkt_payload, sizeof(*bkt_payload));
   6554     pfx_payload->bkt_ptr = bkt_payload;
   6555 
   6556     /* Insert prefix into bucket-trie */
   6557     rv = trie_insert(bkt_trie, prefix, NULL, length, 
   6558                     (trie_node_t *)bkt_payload);
   6559     if (SOC_FAILURE(rv)) {
   6560         goto free_memory;
   6561     }
   6562 
   6563     /* Insert prefix into prefix-trie */
   6564     if (ipv6) {
   6565         pfx_trie = VRF_PREFIX_TRIE_IPV6_128(unit, vrf);
   6566     } 
   6567     
   6568     if (!default_route) {
   6569         /* Default route already in prefix trie */
   6570         rv = trie_insert(pfx_trie, prefix, NULL, length, 
   6571                         (trie_node_t *)pfx_payload);
   6572         if (SOC_FAILURE(rv)) {
   6573             goto delete_bkt_trie;
   6574         }
   6575     }
   6576 
   6577     /* Update bucket index for VRF default route entry */
   6578     if (VRF_TRIE_INIT_COMPLETED(unit, vrf, ipv6)) {
   6579         def_entry = VRF_TRIE_DEFAULT_ROUTE_IPV6_128(unit, vrf);
   6580 
   6581         if (0 == soc_L3_DEFIP_PAIR_128m_field32_get(unit, def_entry,
   6582                                                     ALG_BKT_PTRf)) {
   6583             default_route = 0;
   6584             rv = _alpm_128_prefix_create(unit, lpm_entry, prefix,
   6585                                          &length, &default_route);
   6586             if (SOC_SUCCESS(rv) && default_route) {
   6587                 soc_L3_DEFIP_PAIR_128m_field32_set(unit, def_entry,
   6588                                                    ALG_BKT_PTRf, bckt_idx);
   6589             }
   6590         }
   6591     }
   6592 
   6593     /* Return success */
   6594     return rv;
   6595 
   6596 delete_bkt_trie:
   6597     (void) trie_delete(bkt_trie, prefix, length, &delp);
   6598     bkt_payload = (payload_t *) delp;
   6599 
   6600 free_memory:
   6601     sal_free(bkt_payload);
   6602     sal_free(pfx_payload);
   6603     return rv;
   6604 }
   6605 
   6606 /*
   6607  * soc_alpm_warmboot_vrf_add
   6608  */
   6609 static int
   6610 soc_alpm_128_warmboot_vrf_add(int unit, 
   6611                           int v6,
   6612                           int vrf,
   6613                           int idx,
   6614                           int bkt_ptr)
   6615 {
   6616 
   6617     int           rv = SOC_E_NONE;
   6618     uint32        length;
   6619     uint32        key[5] = {0, 0, 0, 0, 0};
   6620     trie_t        *pfx_root = NULL;
   6621     payload_t     *pfx_pyld = NULL;
   6622     defip_pair_128_entry_t *lpm_entry = NULL;
   6623 
   6624     /* Initialize VRF PIVOT IPV4 trie */
   6625     lpm_entry = sal_alloc(sizeof(defip_pair_128_entry_t), "Default LPM entry");
   6626     if (lpm_entry == NULL) {
   6627         LOG_ERROR(BSL_LS_SOC_ALPM,
   6628                   (BSL_META_U(unit,
   6629                               "unable to allocate memory for LPM entry\n")));
   6630         return SOC_E_MEMORY;
   6631     }
   6632 
   6633     /* Initialize an lpm entry to perform a match */
   6634     (void) _soc_alpm_128_lpm_ent_key_init(unit, key, 0, vrf, v6, lpm_entry, 0, 1);
   6635 
   6636     /* for global VRF */
   6637     if (vrf == SOC_VRF_MAX(unit) + 1) {
   6638         soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, GLOBAL_ROUTEf, 1);
   6639     } else {
   6640         /* Set default miss to global route only for non global routes */
   6641         soc_L3_DEFIP_PAIR_128m_field32_set(unit, lpm_entry, DEFAULT_MISSf, 1);
   6642     }
   6643     
   6644     VRF_TRIE_DEFAULT_ROUTE_IPV6_128(unit, vrf) = lpm_entry;
   6645     
   6646     trie_init(_MAX_KEY_LEN_144_, &VRF_PREFIX_TRIE_IPV6_128(unit, vrf));
   6647     
   6648     pfx_root = VRF_PREFIX_TRIE_IPV6_128(unit, vrf);
   6649   
   6650     pfx_pyld = sal_alloc(sizeof(payload_t), "Payload for pfx trie key");
   6651     if (pfx_pyld == NULL) {
   6652         LOG_ERROR(BSL_LS_SOC_ALPM,
   6653                   (BSL_META_U(unit,
   6654                               "Unable to allocate memory for pfx trie node \n")));
   6655         return SOC_E_MEMORY;
   6656     }
   6657 
   6658     sal_memset(pfx_pyld,   0, sizeof(*pfx_pyld));
   6659 
   6660     length = 0;
   6661     pfx_pyld->key[0] = key[0]; 
   6662     pfx_pyld->key[1] = key[1]; 
   6663     pfx_pyld->len    = length;
   6664 
   6665     rv = trie_insert(pfx_root, key, NULL, length, &(pfx_pyld->node));
   6666     if (SOC_FAILURE(rv)) {
   6667         sal_free(pfx_pyld);
   6668         return rv;
   6669     }
   6670 
   6671     VRF_TRIE_INIT_DONE(unit, vrf, v6, 1);
   6672     
   6673     return rv;
   6674 }
   6675 
   6676 /*
   6677  * soc_alpm_128_warmboot_prefix_insert
   6678  */
   6679 int
   6680 soc_alpm_128_warmboot_prefix_insert(int unit, 
   6681                                 int  ipv6,
   6682                                 void *lpm_entry, 
   6683                                 void *alpm_entry, 
   6684                                 int tcam_idx, 
   6685                                 int bckt_idx, 
   6686                                 int alpm_idx)
   6687 {
   6688     int       vrf_id;   /* Internal API representation of VRF id */
   6689     int       vrf;      /* VRF in (0 - (MAX_VRF + 1)) range */
   6690     int       rv = SOC_E_NONE;
   6691     soc_mem_t mem;
   6692 
   6693     /* Get ALPM table memory. */
   6694     SOC_ALPM_TABLE_MEM_128(unit, ipv6, mem);
   6695     
   6696     /* Get VRF */
   6697     SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf));
   6698     
   6699     /* For VRF_OVERRIDE (Global High) entries,  Prefix resides in TCAM directly */
   6700     if (vrf_id == SOC_L3_VRF_OVERRIDE) {
   6701         return(rv);
   6702     }
   6703 
   6704     /* Non override entries, goes into ALPM memory */
   6705     if (!VRF_TRIE_INIT_COMPLETED(unit, vrf, ipv6)) {
   6706         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   6707                     (BSL_META_U(unit,
   6708                                 "VRF %d is not initialized\n"), vrf));
   6709         rv = soc_alpm_128_warmboot_vrf_add(unit, ipv6, vrf, tcam_idx, bckt_idx);
   6710         if (SOC_FAILURE(rv)) {
   6711             LOG_ERROR(BSL_LS_SOC_ALPM,
   6712                       (BSL_META_U(unit,
   6713                                   "VRF %d/%d trie init \n"
   6714                                   "failed\n"), vrf, ipv6));
   6715             return rv;
   6716         }
   6717 
   6718         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   6719                     (BSL_META_U(unit,
   6720                                 "VRF %d/%d trie init "
   6721                                 "completed\n"), vrf, ipv6));
   6722     }
   6723  
   6724     rv = _soc_alpm_128_warmboot_insert(unit, ipv6, lpm_entry, alpm_entry, mem,
   6725                                        tcam_idx, bckt_idx, alpm_idx);
   6726     if (rv != SOC_E_NONE) {
   6727         LOG_WARN(BSL_LS_SOC_ALPM,
   6728                  (BSL_META_U(unit,
   6729                              "unit %d : Route Insertion Failed :%s\n"),
   6730                   unit, soc_errmsg(rv)));
   6731 
   6732         return(rv);
   6733     }
   6734     VRF_TRIE_ROUTES_INC(unit, vrf_id, vrf, ipv6);
   6735     return(rv);
   6736 }
   6737 
   6738 /*
   6739  * alpm_warmboot_bucket_bitmap_set
   6740  * This function will set bit position in bucket bitmap
   6741  */
   6742 int  
   6743 soc_alpm_128_warmboot_bucket_bitmap_set(int u,       /* Unit         */
   6744                                         int v6,      /* Flag v4/v6   */
   6745                                         int bkt_idx) /* Bucket index */
   6746 {
   6747     int step_count = 1;
   6748 
   6749     /*
   6750      * In combined search mode, with urpf disabled, need to allocate even and 
   6751      * odd bucket pointers
   6752      */
   6753     if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) {
   6754         step_count = 2;
   6755     }
   6756     if (SOC_ALPM_BUCKET_BMAP(u) == NULL) {
   6757         return SOC_E_INTERNAL;
   6758     }
   6759 
   6760     /* Set bit position */
   6761     SHR_BITSET_RANGE(SOC_ALPM_BUCKET_BMAP(u), bkt_idx, step_count);
   6762     
   6763     return SOC_E_NONE;
   6764 }
   6765 
   6766 int
   6767 soc_alpm_128_warmboot_lpm_reinit_done(int unit)
   6768 {
   6769     int idx;
   6770     int prev_idx = MAX_PFX_INDEX_128;
   6771 
   6772     int defip_table_size = soc_mem_index_count(unit, L3_DEFIP_PAIR_128m);
   6773     
   6774     if (SOC_URPF_STATUS_GET(unit)) {
   6775         defip_table_size >>= 1;
   6776     } 
   6777     
   6778     /* returns 0 for combined search mode and 1 for parallel search mode */
   6779     if (!soc_alpm_mode_get(unit)) {
   6780         /* Combined search mode */
   6781         SOC_ALPM_128_LPM_STATE_PREV(unit, MAX_PFX_INDEX_128) = -1;
   6782 
   6783         for (idx = MAX_PFX_INDEX_128; idx > -1; idx--) {
   6784             if (-1 == SOC_ALPM_128_LPM_STATE_START(unit, idx)) {
   6785                 continue;
   6786             }
   6787 
   6788             SOC_ALPM_128_LPM_STATE_PREV(unit, idx) = prev_idx;
   6789             SOC_ALPM_128_LPM_STATE_NEXT(unit, prev_idx) = idx;
   6790 
   6791             SOC_ALPM_128_LPM_STATE_FENT(unit, prev_idx) =                    \
   6792                               SOC_ALPM_128_LPM_STATE_START(unit, idx) -      \
   6793                               SOC_ALPM_128_LPM_STATE_END(unit, prev_idx) - 1;
   6794             prev_idx = idx;
   6795             
   6796         }
   6797 
   6798         SOC_ALPM_128_LPM_STATE_NEXT(unit, prev_idx) = -1;
   6799         SOC_ALPM_128_LPM_STATE_FENT(unit, prev_idx) =                       \
   6800                               defip_table_size -                   \
   6801                               SOC_ALPM_128_LPM_STATE_END(unit, prev_idx) - 1;
   6802     } else {
   6803         /* Parallel search mode 
   6804          * 
   6805          *    Configured VRF Range 
   6806          *    {0 - (MAX_PFX_INDEX_128/3)}
   6807          *    Global VRF Range 
   6808          *    {((MAX_PFX_INDEX_128/1) + 1) - (MAX_PFX_INDEX_128/2) }
   6809          *    Override VRF Range 
   6810          *    {((MAX_PFX_INDEX_128/2) + 1) - (MAX_PFX_INDEX_128) }
   6811          */
   6812 
   6813         /*
   6814          * Global and Overide VRF range are treated as single block and
   6815          * both blocks will be linked 
   6816          */
   6817         
   6818         SOC_ALPM_128_LPM_STATE_PREV(unit, MAX_PFX_INDEX_128) = -1;
   6819         for (idx = MAX_PFX_INDEX_128; idx > (MAX_PFX_INDEX_128/3) ; idx--) {
   6820             if (-1 == SOC_ALPM_128_LPM_STATE_START(unit, idx)) {
   6821                 continue;
   6822             }
   6823 
   6824             SOC_ALPM_128_LPM_STATE_PREV(unit, idx) = prev_idx;
   6825             SOC_ALPM_128_LPM_STATE_NEXT(unit, prev_idx) = idx;
   6826 
   6827             SOC_ALPM_128_LPM_STATE_FENT(unit, prev_idx) =                    \
   6828                               SOC_ALPM_128_LPM_STATE_START(unit, idx) -      \
   6829                               SOC_ALPM_128_LPM_STATE_END(unit, prev_idx) - 1;
   6830                               
   6831             prev_idx = idx;
   6832         }
   6833         SOC_ALPM_128_LPM_STATE_NEXT(unit, prev_idx) = -1;
   6834         SOC_ALPM_128_LPM_STATE_FENT(unit, prev_idx) =                       \
   6835                               defip_table_size -                        \
   6836                               SOC_ALPM_128_LPM_STATE_END(unit, prev_idx) - 1;
   6837 
   6838         /* Configured VRF range */
   6839         prev_idx = (MAX_PFX_INDEX_128/3);
   6840         SOC_ALPM_128_LPM_STATE_PREV(unit, (MAX_PFX_INDEX_128/3)) = -1;
   6841         for (idx = ((MAX_PFX_INDEX_128/3)-1); idx > -1; idx--) {
   6842             if (-1 == SOC_ALPM_128_LPM_STATE_START(unit, idx)) {
   6843                 continue;
   6844             }
   6845 
   6846             SOC_ALPM_128_LPM_STATE_PREV(unit, idx) = prev_idx;
   6847             SOC_ALPM_128_LPM_STATE_NEXT(unit, prev_idx) = idx;
   6848 
   6849             SOC_ALPM_128_LPM_STATE_FENT(unit, prev_idx) =                    \
   6850                               SOC_ALPM_128_LPM_STATE_START(unit, idx) -      \
   6851                               SOC_ALPM_128_LPM_STATE_END(unit, prev_idx) - 1;
   6852             prev_idx = idx;
   6853         }
   6854         SOC_ALPM_128_LPM_STATE_NEXT(unit, prev_idx) = -1;
   6855         SOC_ALPM_128_LPM_STATE_FENT(unit, prev_idx) =                         \
   6856                               (defip_table_size >> 1) -                   \
   6857                               SOC_ALPM_128_LPM_STATE_END(unit, prev_idx) - 1;
   6858     }
   6859 
   6860     return (SOC_E_NONE);
   6861 }
   6862 
   6863 int
   6864 soc_alpm_128_warmboot_lpm_reinit(int unit,
   6865                              int ipv6,
   6866                              int idx,
   6867                              void *lpm_entry)
   6868 {
   6869     int pfx_len;
   6870     int flex;
   6871     int vrf, vrf_id;
   6872 
   6873     LPM_128_HASH_INSERT(unit, lpm_entry, idx, NULL);
   6874 
   6875     SOC_IF_ERROR_RETURN
   6876         (_soc_alpm_128_lpm_prefix_length_get(unit, lpm_entry, &pfx_len));
   6877 
   6878     SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf));
   6879 
   6880     if (!VRF_FLEX_COMPLETED(unit, vrf_id, vrf, ipv6)) {
   6881         flex = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, lpm_entry, ENTRY_VIEWf);
   6882         VRF_FLEX_SET(unit, vrf_id, vrf, ipv6, flex);
   6883     }
   6884     VRF_PIVOT_REF_INC(unit, vrf_id, vrf, ipv6);
   6885 
   6886     if (SOC_ALPM_128_LPM_STATE_VENT(unit, pfx_len) == 0) {
   6887         SOC_ALPM_128_LPM_STATE_START(unit, pfx_len) = idx;
   6888         SOC_ALPM_128_LPM_STATE_END(unit, pfx_len) = idx;
   6889     } else {
   6890         SOC_ALPM_128_LPM_STATE_END(unit, pfx_len) = idx;
   6891     }
   6892 
   6893     SOC_ALPM_128_LPM_STATE_VENT(unit, pfx_len)++;
   6894 
   6895     return (SOC_E_NONE);
   6896 }
   6897 
   6898 #ifdef ALPM_WARM_BOOT_DEBUG
   6899 
   6900 /*
   6901  * Function:
   6902  *     soc_alpm_128_warmboot_lpm_sw_dump
   6903  * Purpose:
   6904  *     Displays FB LPM information maintained by software.
   6905  * Parameters:
   6906  *     unit - Device unit number
   6907  * Returns:
   6908  *     None
   6909  */
   6910 void
   6911 soc_alpm_128_warmboot_lpm_sw_dump(int unit)
   6912 {
   6913     int i;
   6914     _soc_alpm_128_lpm_hash_t *hash128;
   6915     soc_alpm_128_lpm_state_p lpm_state_128;
   6916      
   6917     /* Dump v6-128 lpm state */
   6918     LOG_CLI((BSL_META_U(unit,
   6919                         "V6-128 LPM STATE DUMP.\n")));
   6920     lpm_state_128 = soc_alpm_128_lpm_state[unit];
   6921     
   6922     if (lpm_state_128 != NULL) {
   6923         for (i = 0; i < MAX_PFX_ENTRIES_128; i++) {
   6924             if (lpm_state_128[i].vent != 0 ) {
   6925                 LOG_CLI((BSL_META_U(unit,
   6926                                     "Prefix %d\n"), i));
   6927                 LOG_CLI((BSL_META_U(unit,
   6928                                     "  Start : %d\n"), lpm_state_128[i].start));
   6929                 LOG_CLI((BSL_META_U(unit,
   6930                                     "  End   : %d\n"), lpm_state_128[i].end));
   6931                 LOG_CLI((BSL_META_U(unit,
   6932                                     "  Prev  : %d\n"), lpm_state_128[i].prev));
   6933                 LOG_CLI((BSL_META_U(unit,
   6934                                     "  Next  : %d\n"), lpm_state_128[i].next));
   6935                 LOG_CLI((BSL_META_U(unit,
   6936                                     "  Valid : %d\n"), lpm_state_128[i].vent));
   6937                 LOG_CLI((BSL_META_U(unit,
   6938                                     "  Free  : %d\n"), lpm_state_128[i].fent));
   6939             }
   6940         }
   6941     }
   6942     LOG_CLI((BSL_META_U(unit,
   6943                         "V6-128 LPM STATE DUMP DONE.\n\n")));
   6944 
   6945     /* Dump LPM HASH 128 table */
   6946     LOG_CLI((BSL_META_U(unit,
   6947                         "LPM HASH 128 TABLE DUMP.\n")));
   6948     hash128 = _fb_lpm_128_hash_tab[unit];
   6949     for(i = 0; i < hash128->index_count; i++) {
   6950         if (hash128->table[i] != TD2_ALPM_128_HASH_INDEX_NULL) {
   6951             LOG_CLI((BSL_META_U(unit,
   6952                                 "hash_indx_128 = 0x%x Data = 0x%x\n"),
   6953                      i,  hash128->table[i]));
   6954         }
   6955     }
   6956     LOG_CLI((BSL_META_U(unit,
   6957                         "LPM HASH 128 TABLE DUMP DONE.\n\n")));
   6958 
   6959     return;
   6960 }
   6961 #endif
   6962 
   6963 
   6964 /*
   6965  * Function:
   6966  *      _soc_alpm_128_sanity_check
   6967  * Purpose:
   6968  *      Sanity check for ALPM with L3_DEFIP
   6969  * Parameters:
   6970  *      u           - Device unit
   6971  *      min         - Min index of L3_DEFIP
   6972  *      max         - Max index of L3_DEFIP
   6973  *      check_sw    - Check software
   6974  *      bkt_ptr_arr - bucket ptr array
   6975  * Returns:
   6976  *      SOC_E_XXX defined in error.h
   6977  */
   6978 int
   6979 _soc_alpm_128_sanity_check(int u, int min, int max, int check_sw, int *bkt_ptr_arr)
   6980 {
   6981     int             rv = SOC_E_NONE;
   6982     int             lpm_idx, lpm_idx2, fd_lpm_idx2, alpm_idx;
   6983     int             j, ipv6;
   6984     int             vrf_id, vrf;
   6985     int             fd_lpm_idx, fd_bkt_ptr, fd_alpm_idx;
   6986     int             ent, ent_num, bkt_ptr;
   6987     int             error1 = 0, error2 = 0, error = 0, success = 0;
   6988     int             used;
   6989     int             bpm_len, ip_len;
   6990     int             trie_bpm_len, default_route;
   6991     int             alloc_size;
   6992     uint32          bank_disable = 0;
   6993     uint32          e[SOC_MAX_MEM_FIELD_WORDS] = {0};
   6994     uint32          shadow[SOC_MAX_MEM_FIELD_WORDS] = {0};
   6995     uint32          prefix[5], length;
   6996     trie_t          *pfx_trie  = NULL;
   6997     trie_node_t     *lpmp      = NULL;
   6998     payload_t       *tmp_pyld  = NULL;
   6999     uint32          data0[10] = {0};
   7000     uint32          data1[10] = {0};
   7001     char            *buffer = NULL;
   7002     defip_pair_128_entry_t   *lpm_entry, lpm_entry2, lpm_bmp;
   7003     soc_mem_t       bkt_mem_type;
   7004     soc_mem_t       alpm_mem = L3_DEFIP_ALPM_IPV6_128m;
   7005     int             bpm_check = 0;
   7006 
   7007     /* Calculate table size. */
   7008     alloc_size = sizeof(defip_pair_128_entry_t) * (max - min + 1);
   7009 
   7010     /* Allocate memory buffer. */
   7011     buffer = soc_cm_salloc(u, alloc_size, "lpm_tbl");
   7012     if (buffer == NULL) {
   7013         return (SOC_E_MEMORY);
   7014     }
   7015 
   7016     /* Reset allocated buffer. */
   7017     sal_memset(buffer, 0, alloc_size);
   7018 
   7019     SOC_ALPM_LPM_LOCK(u);
   7020 
   7021     /* Read table to the buffer. */
   7022     if (soc_mem_read_range(u, L3_DEFIP_PAIR_128m, MEM_BLOCK_ANY,
   7023                            min, max, buffer) < 0) {
   7024         soc_cm_sfree(u, buffer);
   7025         SOC_ALPM_LPM_UNLOCK(u);
   7026         return (SOC_E_INTERNAL);
   7027     }
   7028 
   7029     ipv6 = L3_DEFIP_MODE_128;
   7030     ent_num = 8;
   7031     if (SOC_ALPM_V6_SCALE_CHECK(u, ipv6)) {
   7032         ent_num <<= 1;
   7033     }
   7034 
   7035     for (lpm_idx = min; lpm_idx <= max; lpm_idx++) {
   7036         if (error1) {
   7037             LOG_ERROR(BSL_LS_SOC_ALPM,
   7038                     (BSL_META_U(u,
   7039                      "\tL3_DEFIP_PAIR_128 index:%d check failed. error count %d\n"),
   7040                      lpm_idx - 1, error1));
   7041             error = 1;
   7042         } else if (success) {
   7043             LOG_INFO(BSL_LS_SOC_ALPM,(BSL_META_U(u,
   7044                      "\tL3_DEFIP_PAIR_128 index:%d check passed. success count %d\n"),
   7045                      lpm_idx - 1, success));
   7046         }
   7047 
   7048         error1 = error2 = success = 0;
   7049         lpm_entry = soc_mem_table_idx_to_pointer(u, L3_DEFIP_PAIR_128m,
   7050                                  defip_pair_128_entry_t *, buffer, lpm_idx - min);
   7051 
   7052         bkt_ptr = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, lpm_entry, ALG_BKT_PTRf);
   7053         if (!SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, lpm_entry, VALID0_LWRf)) {
   7054             continue;
   7055         } else {
   7056             /* cache coherency check */
   7057             defip_pair_128_entry_t hw_ent, sw_ent;
   7058             soc_mem_t cmem = L3_DEFIP_PAIR_128m;
   7059             sal_memset(&hw_ent, 0, sizeof(hw_ent));
   7060             sal_memset(&sw_ent, 0, sizeof(sw_ent));
   7061             rv = _soc_mem_alpm_read_cache(u, cmem, SOC_BLOCK_ANY,
   7062                                           lpm_idx, &sw_ent);
   7063             if (SOC_SUCCESS(rv)) {
   7064                 rv = soc_mem_read_no_cache(u, 0, cmem, 0, SOC_BLOCK_ANY,
   7065                                            lpm_idx, &hw_ent);
   7066                 if (SOC_SUCCESS(rv)) {
   7067                     if (soc_mem_field_valid(u, cmem, EVEN_PARITYf)) {
   7068                         soc_mem_field32_set(u, cmem, &hw_ent, EVEN_PARITYf, 0);
   7069                         soc_mem_field32_set(u, cmem, &sw_ent, EVEN_PARITYf, 0);
   7070                     } else if (soc_mem_field_valid(u, cmem, PARITYf)) {
   7071                         soc_mem_field32_set(u, cmem, &hw_ent, PARITYf, 0);
   7072                         soc_mem_field32_set(u, cmem, &sw_ent, PARITYf, 0);
   7073                     }
   7074                     soc_mem_field32_set(u, cmem, &hw_ent, HITf, 0);
   7075                     soc_mem_field32_set(u, cmem, &sw_ent, HITf, 0);
   7076                     if (sal_memcmp(&sw_ent, &hw_ent,
   7077                                    soc_mem_entry_bytes(u, cmem)) != 0) {
   7078                         LOG_ERROR(BSL_LS_SOC_ALPM,
   7079                             (BSL_META_U(u, "\t%s index:[%d], ipv6(%d)"
   7080                             " cache mismatch\n"), SOC_MEM_NAME(u, cmem),
   7081                             lpm_idx, ipv6));
   7082                         error1 ++;
   7083                     }
   7084                 }
   7085             }
   7086 
   7087             /* We can just use defip_pair_128_entry_t because it's always
   7088              * longer than aux_entry_t */
   7089             cmem = L3_DEFIP_AUX_TABLEm;
   7090             sal_memset(&hw_ent, 0, sizeof(hw_ent));
   7091             sal_memset(&sw_ent, 0, sizeof(sw_ent));
   7092             lpm_idx2 = soc_alpm_physical_idx(u, L3_DEFIP_PAIR_128m, lpm_idx, 1);
   7093             rv = _soc_mem_alpm_read_cache(u, cmem, SOC_BLOCK_ANY,
   7094                     SOC_ALPM_128_ADDR_LWR(u, lpm_idx2), &sw_ent);
   7095             if (SOC_SUCCESS(rv)) {
   7096                 rv = soc_mem_read_no_cache(u, 0, cmem, 0, SOC_BLOCK_ANY,
   7097                         SOC_ALPM_128_ADDR_LWR(u, lpm_idx2), &hw_ent);
   7098                 if (SOC_SUCCESS(rv)) {
   7099                     if (soc_mem_field_valid(u, cmem, EVEN_PARITYf)) {
   7100                         soc_mem_field32_set(u, cmem, &hw_ent,
   7101                                             EVEN_PARITYf, 0);
   7102                         soc_mem_field32_set(u, cmem, &sw_ent,
   7103                                             EVEN_PARITYf, 0);
   7104                     } else if (soc_mem_field_valid(u, cmem, PARITYf)) {
   7105                         soc_mem_field32_set(u, cmem, &hw_ent, PARITYf, 0);
   7106                         soc_mem_field32_set(u, cmem, &sw_ent, PARITYf, 0);
   7107                     }
   7108                     if (sal_memcmp(&sw_ent, &hw_ent,
   7109                                    soc_mem_entry_bytes(u, cmem)) != 0) {
   7110                         LOG_ERROR(BSL_LS_SOC_ALPM,
   7111                             (BSL_META_U(u, "\t%s index:[%d], ipv6(%d)"
   7112                             " cache mismatch\n"), SOC_MEM_NAME(u, cmem),
   7113                             SOC_ALPM_128_ADDR_LWR(u, lpm_idx2), ipv6));
   7114                         error1 ++;
   7115                     }
   7116                 }
   7117             }
   7118             sal_memset(&hw_ent, 0, sizeof(hw_ent));
   7119             sal_memset(&sw_ent, 0, sizeof(sw_ent));
   7120             rv = _soc_mem_alpm_read_cache(u, cmem, SOC_BLOCK_ANY,
   7121                     SOC_ALPM_128_ADDR_UPR(u, lpm_idx2), &sw_ent);
   7122             if (SOC_SUCCESS(rv)) {
   7123                 rv = soc_mem_read_no_cache(u, 0, cmem, 0, SOC_BLOCK_ANY,
   7124                         SOC_ALPM_128_ADDR_UPR(u, lpm_idx2), &hw_ent);
   7125                 if (SOC_SUCCESS(rv)) {
   7126                     if (soc_mem_field_valid(u, cmem, EVEN_PARITYf)) {
   7127                         soc_mem_field32_set(u, cmem, &hw_ent,
   7128                                             EVEN_PARITYf, 0);
   7129                         soc_mem_field32_set(u, cmem, &sw_ent,
   7130                                             EVEN_PARITYf, 0);
   7131                     } else if (soc_mem_field_valid(u, cmem, PARITYf)) {
   7132                         soc_mem_field32_set(u, cmem, &hw_ent, PARITYf, 0);
   7133                         soc_mem_field32_set(u, cmem, &sw_ent, PARITYf, 0);
   7134                     }
   7135 
   7136                     if (sal_memcmp(&sw_ent, &hw_ent,
   7137                                    soc_mem_entry_bytes(u, cmem)) != 0) {
   7138                         LOG_ERROR(BSL_LS_SOC_ALPM,
   7139                             (BSL_META_U(u, "\t%s index:[%d], ipv6(%d)"
   7140                             " cache mismatch\n"), SOC_MEM_NAME(u, cmem),
   7141                             SOC_ALPM_128_ADDR_UPR(u, lpm_idx2), ipv6));
   7142                         error1 ++;
   7143                     }
   7144                 }
   7145             }
   7146         }
   7147 
   7148         if (SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, lpm_entry, GLOBAL_HIGHf) ||
   7149             (soc_feature(u, soc_feature_ipmc_defip) &&
   7150              SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, lpm_entry, MULTICAST_ROUTEf))) {
   7151             if (bkt_ptr != 0) {
   7152                 LOG_ERROR(BSL_LS_SOC_ALPM,
   7153                           (BSL_META_U(u, "\tWrong bkt_ptr %d\n"), 
   7154                           bkt_ptr));
   7155                 error1 ++;
   7156             }
   7157             continue;
   7158         }
   7159         if (bkt_ptr == 0) {
   7160             LOG_ERROR(BSL_LS_SOC_ALPM,
   7161                       (BSL_META_U(u, "\tWrong bkt_ptr2 %d\n"), 
   7162                       bkt_ptr));
   7163             error1 ++;
   7164         }
   7165 
   7166         j = 0;
   7167         data0[j++] = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, lpm_entry, ECMPf);
   7168         data0[j++] = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, lpm_entry, ECMP_PTRf);
   7169         data0[j++] = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, lpm_entry, NEXT_HOP_INDEXf);
   7170         data0[j++] = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, lpm_entry, PRIf);
   7171         data0[j++] = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, lpm_entry, RPEf);
   7172         data0[j++] = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, lpm_entry, DST_DISCARDf);
   7173         data0[j++] = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, lpm_entry, CLASS_IDf);
   7174         /* Check if bucket pointer duplicated */
   7175         bkt_ptr = SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, lpm_entry, ALG_BKT_PTRf);
   7176 
   7177         if (bkt_ptr_arr) {
   7178             if (bkt_ptr_arr[bkt_ptr] == -1) {
   7179                 bkt_ptr_arr[bkt_ptr] = lpm_idx;
   7180                 if (SOC_ALPM_V6_SCALE_CHECK(u, ipv6)) {
   7181                     bkt_ptr_arr[bkt_ptr + 1] = lpm_idx;
   7182                 }
   7183                 success ++;
   7184             } else {
   7185                 LOG_ERROR(BSL_LS_SOC_ALPM,
   7186                           (BSL_META_U(u, "\tConflict bucket pointer %d: "
   7187                           "was %d now %d\n"), bkt_ptr,
   7188                           bkt_ptr_arr[bkt_ptr], lpm_idx));
   7189                 error1 ++;
   7190             }
   7191         }
   7192 
   7193         (void) soc_alpm_128_lpm_vrf_get(u, lpm_entry, &vrf_id, &vrf);
   7194 
   7195         /* read shadow table for bpm length */
   7196         lpm_idx2 = soc_alpm_physical_idx(u, L3_DEFIP_PAIR_128m, lpm_idx, 1);
   7197         rv = soc_mem_read(u, L3_DEFIP_AUX_TABLEm, MEM_BLOCK_ANY,
   7198                           SOC_ALPM_128_ADDR_LWR(u, lpm_idx2), shadow);
   7199         bpm_len = -1;
   7200         bpm_check = 0;
   7201         if (SOC_SUCCESS(rv)) {
   7202             bpm_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm,
   7203                                           shadow, BPM_LENGTH0f);
   7204             ip_len  = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm,
   7205                                           shadow, IP_LENGTH0f);
   7206 
   7207             if (bpm_len > ip_len) {
   7208                 LOG_ERROR(BSL_LS_SOC_ALPM,
   7209                           (BSL_META_U(u, "\tAUX Table corrupted\n")));
   7210                 error1 ++;
   7211             } else {
   7212                 success ++;
   7213             }
   7214 
   7215             bpm_check = 1;
   7216             if (bpm_len == 0 &&
   7217                 SOC_MEM_OPT_F32_GET_128(u, L3_DEFIP_PAIR_128m, lpm_entry, DEFAULT_MISSf)) {
   7218                 bpm_check = 0;
   7219             }
   7220         }
   7221 
   7222         if (bpm_check) {
   7223             sal_memcpy(&lpm_bmp, lpm_entry, sizeof(defip_pair_128_entry_t));
   7224             _soc_alpm_128_pfx_len_to_mask(u, &lpm_bmp, bpm_len);
   7225 
   7226             fd_lpm_idx = fd_bkt_ptr = fd_alpm_idx = -1;
   7227             rv = _soc_alpm_128_find(u, &lpm_bmp, alpm_mem, e, &fd_lpm_idx,
   7228                     &fd_bkt_ptr, &fd_alpm_idx, FALSE);
   7229             if (fd_lpm_idx > 0) {
   7230                 fd_lpm_idx = soc_alpm_logical_idx(
   7231                                  u, L3_DEFIP_PAIR_128m,
   7232                                  SOC_ALPM_128_DEFIP_TO_PAIR(u, fd_lpm_idx >> 1), 1);
   7233             }
   7234             if (SOC_SUCCESS(rv)) {
   7235                 j = 0;
   7236                 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, ECMPf);
   7237                 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, ECMP_PTRf);
   7238                 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, NEXT_HOP_INDEXf);
   7239                 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, PRIf);
   7240                 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, RPEf);
   7241                 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, DST_DISCARDf);
   7242                 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, CLASS_IDf);
   7243 
   7244                 if (sal_memcmp(data0, data1, sizeof(data0)) != 0) {
   7245                     LOG_ERROR(BSL_LS_SOC_ALPM,
   7246                               (BSL_META_U(u,
   7247                               "\tData mismatch: "
   7248                               "lpm_idx %d find_lpm_idx %d "
   7249                               "find_alpm_idx %d find_bkt_ptr %d\n"),
   7250                               lpm_idx, fd_lpm_idx,
   7251                               fd_alpm_idx, fd_bkt_ptr));
   7252                     error1 ++;
   7253                 } else {
   7254                     success ++;
   7255                 }
   7256             } else {
   7257                 if (rv == SOC_E_NOT_FOUND &&
   7258                     (vrf_id == SOC_L3_VRF_GLOBAL || soc_alpm_mode_get(u))) {
   7259                     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7260                           (BSL_META_U(u,
   7261                           "\t_soc_alpm_128_find rv=%d: "
   7262                           "lpm_idx %d find_lpm_idx %d "
   7263                           "find_alpm_idx %d find_bkt_ptr %d,"
   7264                           "(Possible: global route or !combined "
   7265                           "without default)\n"),
   7266                           rv, lpm_idx, fd_lpm_idx,
   7267                           fd_alpm_idx, fd_bkt_ptr));
   7268                 } else {
   7269                     LOG_ERROR(BSL_LS_SOC_ALPM,
   7270                           (BSL_META_U(u,
   7271                           "\t_soc_alpm_128_find rv=%d: "
   7272                           "lpm_idx %d find_lpm_idx %d "
   7273                           "find_alpm_idx %d find_bkt_ptr %d\n"),
   7274                           rv, lpm_idx, fd_lpm_idx,
   7275                           fd_alpm_idx, fd_bkt_ptr));
   7276                     error1 ++;
   7277                 }
   7278             }
   7279         }
   7280 
   7281         bank_disable = soc_alpm_bank_dis(u, vrf);
   7282         /* Traverse bucket */
   7283         for (ent = 0; ent < ent_num; ent++) {
   7284             (void) _soc_alpm_mem_index(u, alpm_mem, bkt_ptr, ent, bank_disable,
   7285                                        &alpm_idx);
   7286 
   7287             rv = _soc_mem_alpm_read(u, alpm_mem, MEM_BLOCK_ANY, alpm_idx, e);
   7288             if (SOC_FAILURE(rv)) {
   7289                 continue;
   7290             }
   7291 
   7292             if (!soc_mem_field32_get(u, alpm_mem, e, VALIDf)) {
   7293                 continue;
   7294             }
   7295 
   7296             (void) _soc_alpm_128_lpm_ent_init(u, e, alpm_mem, ipv6, vrf_id,
   7297                                               bkt_ptr, 0, &lpm_entry2, 0);
   7298 
   7299             if (check_sw) {
   7300                 rv = _soc_alpm_128_sw_prefix_check(u, alpm_mem, ipv6, &lpm_entry2, vrf_id, vrf);
   7301                 if (SOC_FAILURE(rv)) {
   7302                     error1 ++;
   7303                     error2 ++;
   7304                     LOG_ERROR(BSL_LS_SOC_ALPM,
   7305                               (BSL_META_U(u,
   7306                               "_soc_alpm_128_sw_prefix_check rv=%d: v6 = %d, vrf_id = %d, vrf = %d\n"),
   7307                                rv, ipv6, vrf_id, vrf));
   7308                 }
   7309             }
   7310             fd_lpm_idx2 = fd_lpm_idx = fd_bkt_ptr = fd_alpm_idx = -1;
   7311             rv = _soc_alpm_128_find(u, &lpm_entry2, alpm_mem, e,
   7312                                     &fd_lpm_idx, &fd_bkt_ptr,
   7313                                     &fd_alpm_idx, FALSE);
   7314 
   7315             if (SOC_SUCCESS(rv)) {
   7316                 fd_lpm_idx2 = soc_alpm_logical_idx(u, L3_DEFIP_PAIR_128m,
   7317                             SOC_ALPM_128_DEFIP_TO_PAIR(u, fd_lpm_idx >> 1), 1);
   7318             }
   7319             if (SOC_FAILURE(rv) ||
   7320                 fd_bkt_ptr  != bkt_ptr ||
   7321                 fd_lpm_idx2 != lpm_idx ||
   7322                 SOC_ALPM_128_DEFIP_TO_PAIR(u, fd_lpm_idx >> 1) != lpm_idx2 ||
   7323                 fd_alpm_idx != alpm_idx) {
   7324 
   7325                 error1 ++;
   7326                 error2 ++;
   7327                 LOG_ERROR(BSL_LS_SOC_ALPM,
   7328                           (BSL_META_U(u,
   7329                           "\t_soc_alpm_128_find2 rv=%d: "
   7330                           "fl [%d,%d] fa %d fb %d "
   7331                           "l [%d,%d] a %d b %d\n"),
   7332                           rv,
   7333                           SOC_ALPM_128_DEFIP_TO_PAIR(u, fd_lpm_idx >> 1),
   7334                           fd_lpm_idx2, fd_alpm_idx, fd_bkt_ptr,
   7335                           lpm_idx2, lpm_idx, alpm_idx, bkt_ptr));
   7336             }
   7337         }
   7338         if (error2 == 0) {
   7339             success ++;
   7340         }
   7341 
   7342         if (!check_sw) {
   7343             continue;
   7344         }
   7345 
   7346         /*
   7347          * Check hardware table above.
   7348          * Check software table below.
   7349  */
   7350 
   7351         /* lpm hash */
   7352 
   7353 #ifdef FB_LPM_128_HASH_SUPPORT
   7354         rv = LPM_128_HASH_VERIFY(u, lpm_entry, lpm_idx);
   7355         if (SOC_FAILURE(rv)) {
   7356             LOG_ERROR(BSL_LS_SOC_ALPM,
   7357                       (BSL_META_U(u, "\tLPM Hash check failed: rv %d "
   7358                                   "lpm_idx %d\n"),
   7359                                   rv, lpm_idx));
   7360             error1 ++;
   7361         } else {
   7362             success ++;
   7363         }
   7364 #endif
   7365 
   7366         /* bucket bitmap */
   7367         rv = alpm_bucket_is_assigned(u, bkt_ptr, ipv6, &used);
   7368         if (SOC_FAILURE(rv)) {
   7369             LOG_ERROR(BSL_LS_SOC_ALPM,
   7370                     (BSL_META_U(u, "\tInvalid bucket pointer %d "
   7371                      "detected, in memory %s index %d\n"), bkt_ptr,
   7372                      SOC_MEM_NAME(u, L3_DEFIP_PAIR_128m), lpm_idx));
   7373             error1 ++;
   7374         } else if (used == 0) {
   7375             /* If bucket was already freed */
   7376             LOG_ERROR(BSL_LS_SOC_ALPM,
   7377                     (BSL_META_U(u, "\tFreed bucket pointer %d "
   7378                      "detected, in memory %s index %d\n"), bkt_ptr,
   7379                      SOC_MEM_NAME(u, L3_DEFIP_PAIR_128m), lpm_idx));
   7380             error1 ++;
   7381         } else {
   7382             success ++;
   7383         }
   7384 
   7385         /* bucket view map */
   7386         bkt_mem_type = _soc_trident2_alpm_bkt_view_get(u, bkt_ptr << 2);
   7387         if (alpm_mem != bkt_mem_type) {
   7388             LOG_ERROR(BSL_LS_SOC_ALPM,
   7389                     (BSL_META_U(u, "\tMismatched alpm view "
   7390                      "in bucket %d, expected %s, was %s\n"), bkt_ptr,
   7391                      SOC_MEM_NAME(u, alpm_mem),
   7392                      SOC_MEM_NAME(u, bkt_mem_type)));
   7393             error1 ++;
   7394         } else {
   7395             success ++;
   7396         }
   7397 
   7398         /* Check bpm len information */
   7399         rv = _alpm_128_prefix_create(u, lpm_entry, prefix,
   7400                                      &length, &default_route);
   7401 
   7402         if (SOC_SUCCESS(rv)) {
   7403             pfx_trie = VRF_PREFIX_TRIE_IPV6_128(u, vrf);
   7404             lpmp = NULL;
   7405             if (pfx_trie) {
   7406                 rv = trie_find_lpm(pfx_trie, prefix, length, &lpmp);
   7407             }
   7408             if (SOC_SUCCESS(rv) && lpmp){
   7409                 tmp_pyld = (payload_t *) lpmp;
   7410                 if (tmp_pyld->bkt_ptr != NULL) {
   7411                     trie_bpm_len = ((payload_t *)(tmp_pyld->bkt_ptr))->len;
   7412                     if (trie_bpm_len != bpm_len) {
   7413                         LOG_ERROR(BSL_LS_SOC_ALPM,
   7414                                 (BSL_META_U(u, "\tBPM len mismatch: lpm_idx %d"
   7415                                  " alpm_idx %d bpm_len %d trie_bpm_len %d\n"),
   7416                                  lpm_idx, alpm_idx, bpm_len, trie_bpm_len));
   7417                         error1 ++;
   7418                     } else {
   7419                         success ++;
   7420                     }
   7421                 } else {
   7422                     success ++;
   7423                 }
   7424             } else {
   7425                 LOG_ERROR(BSL_LS_SOC_ALPM,
   7426                         (BSL_META_U(u, "\ttrie_find_lpm failed: "
   7427                                     "lpm_idx %d alpm_idx %d lpmp %p\n"),
   7428                          lpm_idx, alpm_idx, lpmp));
   7429                 error1 ++;
   7430             }
   7431         } else {
   7432             LOG_ERROR(BSL_LS_SOC_ALPM,
   7433                     (BSL_META_U(u, "\tPrefix creating failed: "
   7434                                 "lpm_idx %d alpm_idx %d\n" ), lpm_idx, alpm_idx));
   7435             error1 ++;
   7436         }
   7437     }
   7438     if (error1) {
   7439         LOG_ERROR(BSL_LS_SOC_ALPM,
   7440                 (BSL_META_U(u,
   7441                  "\tL3_DEFIP_PAIR_128 index:%d check failed. error count %d\n"),
   7442                  lpm_idx - 1, error1));
   7443         error = 1;
   7444     } else if (success) {
   7445         LOG_INFO(BSL_LS_SOC_ALPM,(BSL_META_U(u,
   7446                  "\tL3_DEFIP_PAIR_128 index:%d check passed. success count %d\n"),
   7447                  lpm_idx - 1, success));
   7448     }
   7449 
   7450     SOC_ALPM_LPM_UNLOCK(u);
   7451     soc_cm_sfree(u, buffer);
   7452 
   7453     return (error ? SOC_E_FAIL: SOC_E_NONE);
   7454 }
   7455 
   7456 
   7457 #endif /* ALPM_ENABLE */