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_th_128.c (284326B)


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