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


      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.c
      7  * Purpose: Primitives for LPM management in ALPM - Mode.
      8  * Requires:
      9  */
     10 
     11 /* Implementation notes:
     12  */
     13 #include <shared/bsl.h>
     14 
     15 #include <soc/mem.h>
     16 #include <soc/drv.h>
     17 #include <soc/debug.h>
     18 #include <soc/error.h>
     19 #include <soc/lpm.h>
     20 #include <soc/trident2.h>
     21 #include <shared/bsl.h>
     22 #include <soc/l3x.h>
     23 #ifdef ALPM_ENABLE
     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 #include <soc/esw/alpm_trie_v6.h>
     30 
     31 
     32 
     33 #define ALPM_REPART_DEBUG
     34 #define ALPM_USE_RAW_VIEW
     35 /* indicate whether HIT flag is supported */
     36 
     37 #define SHR_SHIFT_LEFT(val, count) \
     38     (((count) == 32) ? 0 : (val) << (count))
     39 
     40 #define SHR_SHIFT_RIGHT(val, count) \
     41     (((count) == 32) ? 0 : (val) >> (count))
     42 
     43 #define SOC_ALPM_LPM_CACHE_FIELD_CREATE(m, f) soc_field_info_t * m##f
     44 #define SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(m_u, s, m, f) \
     45               (s)->m##f = soc_mem_fieldinfo_get(m_u, m, f)
     46 
     47 /* Add support for Extended based on Flex Counter support type */
     48 #define SOC_ALPM_TABLE_MEM(_u_, _v6_, _mem_, _flex_)             \
     49     _mem_ = (_v6_) ? ((_flex_) ? L3_DEFIP_ALPM_IPV6_64_1m : L3_DEFIP_ALPM_IPV6_64m) \
     50                    : ((_flex_) ? L3_DEFIP_ALPM_IPV4_1m : L3_DEFIP_ALPM_IPV4m)
     51 
     52 /* Add suport for Extended */
     53 #define SOC_ALPM_ENTRY_BUF(_v6_, _mem_, _buf_, _v4ent_, _v6ent_)  \
     54             _buf_ = ((_v6_) ? ((uint32 *)&(_v6ent_)) : ((uint32 *)&(_v4ent_)))
     55 
     56 
     57 /* this is a left shift of the prefix by 32/64 - length  and convert to
     58    brcm order of ip words */
     59 #define ALPM_TRIE_TO_NORMAL_IP(prefix, length, v6) \
     60 do {\
     61     if (!(v6)) {\
     62         prefix[0] = SHR_SHIFT_LEFT(prefix[1], 32 - length);\
     63         prefix[1] = 0;\
     64     } else {\
     65         int macro_pfx_shift = 64 - length;\
     66         int macro_tmp;\
     67         if (macro_pfx_shift < 32) {\
     68             /* get upper half shifted */\
     69             macro_tmp = prefix[3] << macro_pfx_shift;\
     70             /* isolate shifted stuff off lower half */\
     71             macro_tmp |= SHR_SHIFT_RIGHT(prefix[4], 32 - macro_pfx_shift);\
     72             /* swap the order of words */\
     73             prefix[0] = prefix[4] << macro_pfx_shift;\
     74             prefix[1] = macro_tmp;\
     75             prefix[2] = prefix[3] = prefix[4] = 0;\
     76         } else {\
     77             prefix[1] = SHR_SHIFT_LEFT(prefix[4], macro_pfx_shift - 32);\
     78             prefix[0] = prefix[2] = prefix[3] = prefix[4] = 0;\
     79         }\
     80     }\
     81 } while (0)
     82 
     83 
     84 soc_alpm_bucket_t soc_alpm_bucket[SOC_MAX_NUM_DEVICES];
     85 int l3_alpm_sw_prefix_lookup[SOC_MAX_NUM_DEVICES];
     86 _soc_alpm_ctrl_t soc_alpm_control[SOC_MAX_NUM_DEVICES] = {{0}};
     87 _alpm_int_dbg_cnt_t soc_alpm_dbg_cnt[SOC_MAX_NUM_DEVICES];
     88 
     89 void soc_alpm_lpm_state_dump(int u);
     90 static int soc_alpm_lpm_init(int u);
     91 static int soc_alpm_lpm_deinit(int u);
     92 static int soc_alpm_lpm_insert(int u, void *entry_data, int *index,
     93                                int src_default, int src_discard, int bpm_len);
     94 static int soc_alpm_lpm_delete(int u, void *key_data);
     95 static int _soc_alpm_fill_aux_entry_for_op(int u,
     96                void *key_data,
     97                int ipv6,    /* Entry is ipv6. */
     98                int db_type, /* database type */
     99                int ent_type,
    100                int replace_len, /* used for DElete propagate */
    101                defip_aux_scratch_entry_t *aux_entry);
    102 
    103 static int _soc_alpm_lpm_match(int u,
    104                void *key_data,
    105                void *e,         /* return entry data if found */
    106                int *index_ptr,  /* return key location */
    107                int *pfx_len,    /* Key prefix length. vrf + 32 + prefix len for IPV6*/
    108                int *ipv6);       /* Entry is ipv6. */
    109 static int soc_alpm_lpm_match(int u,
    110                void *key_data,
    111                void *e,         /* return entry data if found */
    112                int *index_ptr);  /* return key location */
    113 static int soc_alpm_shared_mem_init(int u);
    114 static int _soc_alpm_mem_ent_init(int unit, void *lpm_entry, 
    115                        void *alpm_entry, void *alpm_sip_entry, soc_mem_t mem,
    116                        uint32 src_flags, uint32 *default_route);
    117 static int
    118 _soc_alpm_lpm_ent_init(int unit, void *alpm_entry, soc_mem_t mem, int ipv6, int vrf_id,
    119                        int bucket, int index, void *lpm_entry, int flex);
    120 static int
    121 _soc_alpm_lpm_ent_key_init(int unit, uint32 *key, int len, int vrf, int ipv6,
    122                       defip_entry_t *lpm_entry, int init);
    123 
    124 static int soc_alpm_vrf_delete(int u, int vrf, int v6);
    125 static int _soc_alpm_lpm_prefix_length_get(int u, void *entry, int *pfx_len);
    126 
    127 
    128 #define FB_LPM_HASH_SUPPORT 1
    129 
    130 typedef struct soc_alpm_lpm_state_s {
    131     int start;  /* start index for this prefix length */
    132     int end;    /* End index for this prefix length */
    133     int prev;   /* Previous (Lo to Hi) prefix length with non zero entry count*/
    134     int next;   /* Next (Hi to Lo) prefix length with non zero entry count */
    135     int vent;   /* valid entries */
    136     int fent;   /* free entries */
    137 } soc_alpm_lpm_state_t, *soc_alpm_lpm_state_p;
    138 
    139 #define SOC_MEM_COMPARE_RETURN(a, b) {          \
    140         if ((a) < (b)) { return -1; }           \
    141         if ((a) > (b)) { return  1; }           \
    142 }
    143 
    144 /* Can move to SOC Control structures */
    145 static soc_alpm_lpm_state_p soc_alpm_lpm_state[SOC_MAX_NUM_DEVICES];
    146 
    147 #define ALPM_INVALID_INDEX      -1
    148 #define CONVERT_NONE            -1
    149 #define WRITE_PIVOT_WITH_SRC_INDEX                0
    150 #define WRITE_PIVOT_WITH_SRC_INDEX_CONVERT        1
    151 #define WRITE_PIVOT_WITH_URPF_PARAMS              2
    152 #define WRITE_PIVOT_WITHOUT_INSERT_HASH           0x80000000
    153 
    154 
    155 #define ALPM_IPV6_PFX_ZERO               33
    156 #define ALPM_MAX_VRF_PFX_ENTRIES         (64 + 32 + 2 + 1)
    157 #define ALPM_MAX_VRF_PFX_INDEX           (ALPM_MAX_VRF_PFX_ENTRIES - 1)
    158 #define ALPM_MAX_PFX_ENTRIES             (3 * ALPM_MAX_VRF_PFX_ENTRIES)
    159 #define ALPM_MAX_PFX_INDEX               (ALPM_MAX_PFX_ENTRIES - 1)
    160 #define SOC_ALPM_PFX_IS_V4(u, pfx)       (((pfx) % ALPM_MAX_VRF_PFX_ENTRIES) < ALPM_IPV6_PFX_ZERO)
    161 #define SOC_ALPM_PFX_IS_V6_64(u, pfx)    (((pfx) % ALPM_MAX_VRF_PFX_ENTRIES) >= ALPM_IPV6_PFX_ZERO && \
    162                                           (pfx) != ALPM_MAX_VRF_PFX_INDEX)
    163 
    164 #define SOC_ALPM_LPM_INIT_CHECK(u)        (soc_alpm_lpm_state[(u)] != NULL)
    165 #define SOC_ALPM_LPM_STATE(u)             (soc_alpm_lpm_state[(u)])
    166 #define SOC_ALPM_LPM_STATE_START(u, pfx)  (soc_alpm_lpm_state[(u)][(pfx)].start)
    167 #define SOC_ALPM_LPM_STATE_END(u, pfx)    (soc_alpm_lpm_state[(u)][(pfx)].end)
    168 #define SOC_ALPM_LPM_STATE_PREV(u, pfx)  (soc_alpm_lpm_state[(u)][(pfx)].prev)
    169 #define SOC_ALPM_LPM_STATE_NEXT(u, pfx)  (soc_alpm_lpm_state[(u)][(pfx)].next)
    170 #define SOC_ALPM_LPM_STATE_VENT(u, pfx)  (soc_alpm_lpm_state[(u)][(pfx)].vent)
    171 #define SOC_ALPM_LPM_STATE_FENT(u, pfx)  (soc_alpm_lpm_state[(u)][(pfx)].fent)
    172 
    173 typedef struct soc_lpm_field_cache_s {
    174     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, CLASS_ID0f);
    175     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, CLASS_ID1f);
    176     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DST_DISCARD0f);
    177     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DST_DISCARD1f);
    178     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP0f);
    179     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP1f);
    180     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_COUNT0f);
    181     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_COUNT1f);
    182     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_PTR0f);
    183     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_PTR1f);
    184     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_ROUTE0f);
    185     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_ROUTE1f);
    186     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MULTICAST_ROUTE0f);
    187     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MULTICAST_ROUTE1f);
    188     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPA_ID0f);
    189     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPA_ID1f);
    190     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, EXPECTED_L3_IIF0f);
    191     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, EXPECTED_L3_IIF1f);
    192     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f);
    193     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f);
    194     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f);
    195     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f);
    196     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, L3MC_INDEX0f);
    197     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, L3MC_INDEX1f);
    198     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, HIT0f);
    199     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, HIT1f);
    200     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR0f);
    201     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR1f);
    202     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR_MASK0f);
    203     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR_MASK1f);
    204     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MODE0f);
    205     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MODE1f);
    206     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MODE_MASK0f);
    207     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MODE_MASK1f);
    208     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, NEXT_HOP_INDEX0f);
    209     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, NEXT_HOP_INDEX1f);
    210     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, PRI0f);
    211     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, PRI1f);
    212     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPE0f);
    213     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPE1f);
    214     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VALID0f);
    215     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VALID1f);
    216     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_0f);
    217     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_1f);
    218     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_MASK0f);
    219     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_MASK1f);
    220     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_HIGH0f);
    221     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_HIGH1f);
    222     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_HIT_IDX0f);
    223     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_HIT_IDX1f);
    224     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_BKT_PTR0f);
    225     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_BKT_PTR1f);
    226     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DEFAULT_MISS0f);
    227     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DEFAULT_MISS1f);
    228     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_BASE_COUNTER_IDX0f);
    229     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_BASE_COUNTER_IDX1f);
    230     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_POOL_NUMBER0f);
    231     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_POOL_NUMBER1f);
    232     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_OFFSET_MODE0f);
    233     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_OFFSET_MODE1f);
    234     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_TYPE_MASK0f);
    235     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_TYPE_MASK1f);
    236     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_TYPE0f);
    237     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_TYPE1f);
    238     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_VIEW0f);
    239     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_VIEW1f);
    240     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, SRC_DISCARD0f);
    241     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, SRC_DISCARD1f);
    242 
    243 } soc_lpm_field_cache_t, *soc_lpm_field_cache_p;
    244 static soc_lpm_field_cache_p soc_lpm_field_cache_state[SOC_MAX_NUM_DEVICES];
    245 
    246 #define SOC_MEM_OPT_F32_GET(m_unit, m_mem, m_entry_data, m_field) \
    247         soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), (soc_lpm_field_cache_state[(m_unit)]->m_mem##m_field))
    248 
    249 #define SOC_MEM_OPT_F32_SET(m_unit, m_mem, m_entry_data, m_field, m_val) \
    250         soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), (soc_lpm_field_cache_state[(m_unit)]->m_mem##m_field), (m_val))
    251 
    252 
    253 #define SOC_MEM_OPT_FIELD_VALID(m_unit, m_mem, m_field) \
    254                 ((soc_lpm_field_cache_state[(m_unit)]->m_mem##m_field) != NULL)
    255 
    256 
    257 #ifdef FB_LPM_HASH_SUPPORT
    258 typedef struct _soc_alpm_lpm_hash_s {
    259     int         unit;
    260     int         entry_count;    /* Number entries in hash table */
    261     int         index_count;    /* Hash index max value + 1 */
    262     uint16      *table;         /* Hash table with 16 bit index */
    263     uint16      *link_table;    /* To handle collisions */
    264 } _soc_alpm_lpm_hash_t;
    265 
    266 typedef uint32 _soc_alpm_lpm_hash_entry_t[5];
    267 typedef int (*_soc_alpm_lpm_hash_compare_fn)(_soc_alpm_lpm_hash_entry_t key1,
    268                                            _soc_alpm_lpm_hash_entry_t key2);
    269 static _soc_alpm_lpm_hash_t *_fb_lpm_hash_tab[SOC_MAX_NUM_DEVICES];
    270 #define SOC_ALPM_LPM_STATE_HASH(u)           (_fb_lpm_hash_tab[(u)])
    271 
    272 #define TD2_ALPM_HASH_INDEX_NULL (0xFFFF)
    273 #define TD2_ALPM_HASH_INDEX_MASK (0x7FFF)
    274 #define TD2_ALPM_HASH_IPV6_MASK  (0x8000)
    275 
    276 #define SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, odata)                 \
    277     odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR0f);     \
    278     odata[1] =                                                               \
    279         SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK0f);       \
    280     odata[2] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR1f);     \
    281     odata[3] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK1f);\
    282     if ( (!(SOC_IS_HURRICANE(u))) &&   \
    283         (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f))) {                \
    284         int m_vrf;\
    285         (void) soc_alpm_lpm_vrf_get(u, entry_data, (int *)&odata[4], &m_vrf); \
    286     } else {                                                                 \
    287         odata[4] = 0;                                                        \
    288     }                                                                       
    289 
    290 
    291 #define SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, odata)               \
    292     odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR0f);     \
    293     odata[1] =                                                               \
    294         SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK0f);       \
    295     odata[2] = 0;                                                            \
    296     odata[3] = 0x80000001;                                                   \
    297     if ((!(SOC_IS_HURRICANE(u))) && \
    298         (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f))) {                \
    299         int m_vrf;\
    300         (void) soc_alpm_lpm_vrf_get(u, entry_data, (int *)&odata[4], &m_vrf); \
    301     } else {                                                                 \
    302         odata[4] = 0;                                                        \
    303     }                                                                       
    304 
    305 #define SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, odata)               \
    306     odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR1f);     \
    307     odata[1] =                                                               \
    308         SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK1f);       \
    309     odata[2] = 0;                                                            \
    310     odata[3] = 0x80000001;                                                   \
    311     if ((!(SOC_IS_HURRICANE(u))) &&  \
    312     (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_1f))) {                    \
    313         int m_vrf;\
    314         defip_entry_t m_tmp_ipv4;\
    315         (void )soc_alpm_lpm_ip4entry1_to_0(u, entry_data, &m_tmp_ipv4, 0);    \
    316         (void) soc_alpm_lpm_vrf_get(u, &m_tmp_ipv4, (int *)&odata[4], &m_vrf); \
    317     } else {                                                                 \
    318         odata[4] = 0;                                                        \
    319     }                                                                       
    320 
    321 #define SOC_FB_LPM_HASH_ENTRY_GET _soc_alpm_lpm_hash_entry_get
    322 
    323 static
    324 void _soc_alpm_lpm_hash_entry_get(int u, void *e,
    325                                 int index, _soc_alpm_lpm_hash_entry_t r_entry,
    326                                 int *v);
    327 static
    328 uint16 _soc_alpm_lpm_hash_compute(uint8 *data, int data_nbits);
    329 static
    330 int _soc_alpm_lpm_hash_create(int unit,
    331                             int entry_count,
    332                             int index_count,
    333                             _soc_alpm_lpm_hash_t **fb_lpm_hash_ptr);
    334 static
    335 int _soc_alpm_lpm_hash_destroy(_soc_alpm_lpm_hash_t *fb_lpm_hash);
    336 static
    337 int _soc_alpm_lpm_hash_lookup(_soc_alpm_lpm_hash_t          *hash,
    338                             _soc_alpm_lpm_hash_compare_fn key_cmp_fn,
    339                             _soc_alpm_lpm_hash_entry_t    entry,
    340                             int                         pfx,
    341                             uint16                      *key_index);
    342 static
    343 int _soc_alpm_lpm_hash_insert(_soc_alpm_lpm_hash_t *hash,
    344                             _soc_alpm_lpm_hash_compare_fn key_cmp_fn,
    345                             _soc_alpm_lpm_hash_entry_t entry,
    346                             int    pfx,
    347                             uint16 old_index,
    348                             uint16 new_index,
    349                             uint32 *rvt_index);
    350 static
    351 int _soc_alpm_lpm_hash_revert(_soc_alpm_lpm_hash_t *hash,
    352                             _soc_alpm_lpm_hash_compare_fn key_cmp_fn,
    353                             _soc_alpm_lpm_hash_entry_t entry,
    354                             uint16 new_index,
    355                             uint32 rvt_index);
    356 static
    357 int _soc_alpm_lpm_hash_delete(_soc_alpm_lpm_hash_t *hash,
    358                             _soc_alpm_lpm_hash_compare_fn key_cmp_fn,
    359                             _soc_alpm_lpm_hash_entry_t entry,
    360                             int    pfx,
    361                             uint16 delete_index);
    362 
    363 static
    364 int _soc_alpm_lpm_hash_verify(_soc_alpm_lpm_hash_t *hash,
    365                             _soc_alpm_lpm_hash_compare_fn key_cmp_fn,
    366                             _soc_alpm_lpm_hash_entry_t entry,
    367                             int    pfx,
    368                             uint16 index);
    369 
    370 /* Use MAX_VRF_ID to store VRF_OVERRIDE routes debug info */
    371 alpm_vrf_handle_t *alpm_vrf_handle[SOC_MAX_NUM_DEVICES];
    372 
    373 alpm_pivot_t **tcam_pivot[SOC_MAX_NUM_DEVICES];
    374 
    375 STATIC int
    376 _soc_alpm_sw_propagate_required(int unit)
    377 {
    378     int i, mem_cnt;
    379     soc_mem_t mem_chk[] = {
    380         L3_DEFIPm,
    381         L3_DEFIP_PAIR_128m,
    382         L3_DEFIP_AUX_TABLEm
    383     };
    384 
    385     mem_cnt = sizeof(mem_chk) / sizeof(mem_chk[0]);
    386     for (i = 0; i < mem_cnt; i++) {
    387         if (soc_mem_cache_get(unit, mem_chk[i], MEM_BLOCK_ANY)) {
    388             return TRUE;
    389         }
    390     }
    391     return FALSE;
    392 }
    393 
    394 STATIC int
    395 _soc_alpm_ctrl_init(int u)
    396 {
    397     sal_memset(&ALPM_CTRL(u), 0, sizeof(_soc_alpm_ctrl_t));
    398 
    399     ALPM_CTRL(u).trie_propagate = _soc_alpm_sw_propagate_required(u);
    400     ALPM_CTRL(u).hit_bits_skip = soc_property_get(u, spn_L3_ALPM_HIT_SKIP, 0);
    401 
    402     ALPM_CTRL(u).fld.key_mode0              = MODE0f;
    403     ALPM_CTRL(u).fld.key_mode1              = MODE1f;
    404     ALPM_CTRL(u).fld.key_mode_mask0         = MODE_MASK0f;
    405     ALPM_CTRL(u).fld.key_mode_mask1         = MODE_MASK1f;
    406     ALPM_CTRL(u).fld.key_type0              = ENTRY_TYPE0f;
    407     ALPM_CTRL(u).fld.key_type1              = ENTRY_TYPE1f;
    408     ALPM_CTRL(u).fld.key_type_mask0         = ENTRY_TYPE_MASK0f;
    409     ALPM_CTRL(u).fld.key_type_mask1         = ENTRY_TYPE_MASK1f;
    410     ALPM_CTRL(u).fld.key_mode0_upr          = MODE0_UPRf;
    411     ALPM_CTRL(u).fld.key_mode0_lwr          = MODE0_LWRf;
    412     ALPM_CTRL(u).fld.key_mode1_upr          = MODE1_UPRf;
    413     ALPM_CTRL(u).fld.key_mode1_lwr          = MODE1_LWRf;
    414     ALPM_CTRL(u).fld.key_mode_mask0_upr     = MODE_MASK0_UPRf;
    415     ALPM_CTRL(u).fld.key_mode_mask0_lwr     = MODE_MASK0_LWRf;
    416     ALPM_CTRL(u).fld.key_mode_mask1_upr     = MODE_MASK1_UPRf;
    417     ALPM_CTRL(u).fld.key_mode_mask1_lwr     = MODE_MASK1_LWRf;
    418     ALPM_CTRL(u).fld.key_type0_upr          = ENTRY_TYPE0_UPRf;
    419     ALPM_CTRL(u).fld.key_type0_lwr          = ENTRY_TYPE0_LWRf;
    420     ALPM_CTRL(u).fld.key_type1_upr          = ENTRY_TYPE1_UPRf;
    421     ALPM_CTRL(u).fld.key_type1_lwr          = ENTRY_TYPE1_LWRf;
    422     ALPM_CTRL(u).fld.key_type_mask0_upr     = ENTRY_TYPE_MASK0_UPRf;
    423     ALPM_CTRL(u).fld.key_type_mask0_lwr     = ENTRY_TYPE_MASK0_LWRf;
    424     ALPM_CTRL(u).fld.key_type_mask1_upr     = ENTRY_TYPE_MASK1_UPRf;
    425     ALPM_CTRL(u).fld.key_type_mask1_lwr     = ENTRY_TYPE_MASK1_LWRf;
    426     ALPM_CTRL(u).fld.key_mode               = MODEf;
    427     ALPM_CTRL(u).fld.key_type               = ENTRY_TYPEf;
    428 
    429     ALPM_CTRL(u).ctrl_inited = 1;
    430     return SOC_E_NONE;
    431 }
    432 
    433 STATIC int
    434 _soc_alpm_sw_propagate(int u, trie_t *pivot, void *prefix, uint32 len,
    435                           int insert, void *cb, void *user_data)
    436 {
    437     int rv = SOC_E_NONE;
    438     uint32 pivot_len = 0;
    439     trie_node_t *lpm_pvt = NULL;
    440     trie_bpm_cb_info_t cb_info;
    441 
    442     cb_info.pfx = (void *)prefix;
    443     cb_info.len = len;
    444     cb_info.user_data = user_data;
    445 
    446     /* Find longest prefix match(pivot) of route */
    447     SOC_IF_ERROR_RETURN(trie_find_lpm(pivot, prefix, len, &lpm_pvt));
    448     pivot_len = (TRIE_ELEMENT_GET(payload_t *, lpm_pvt, node))->len;
    449 
    450     if (pivot->v6_key) {
    451         rv = pvt_trie_v6_propagate_prefix(lpm_pvt, pivot_len,
    452                                           (void *)prefix, len, cb, &cb_info);
    453     } else {
    454         rv = pvt_trie_propagate_prefix(lpm_pvt, pivot_len,
    455                                        (void *)prefix, len, cb, &cb_info);
    456     }
    457 
    458     return rv;
    459 }
    460 
    461 STATIC int
    462 _soc_alpm_propagate_callback(trie_node_t *trie,
    463                              trie_bpm_cb_info_t *info)
    464 {
    465     int rv = SOC_E_NONE;
    466     int i, unit, mode;
    467     trie_bpm_cb_user_data_t *user_data;
    468     void *aux_entry;
    469     alpm_pivot_t *pivot_pyld;
    470     int tcam_index, lpm_index, aux_index;
    471     int aux_flags;
    472 
    473     /* use memory size to declear replace_data field value */
    474     defip_aux_scratch_entry_t replace_data;
    475     soc_mem_t aux_mem = L3_DEFIP_AUX_SCRATCHm;
    476 
    477     /* L3_DEFIP_AUX_TABLE variables */
    478     defip_aux_table_entry_t shadow_entry;
    479     uint32 pfx_len, rpl_bpm_len, pvt_bpm_len;
    480 
    481 #define _URPF_INDEX(urpf, index, mem) \
    482     (urpf ? (index + (soc_mem_index_count(unit, mem) >> 1)) : index)
    483 
    484     user_data = info->user_data;
    485     unit = user_data->unit;
    486     aux_entry = user_data->entry;
    487     aux_flags = user_data->flags;
    488 
    489     /* For uRPF case, DB_TYPE is odd, see soc_alpm_db_ent_type_encoding */
    490     if (soc_mem_field32_get(unit, aux_mem, aux_entry, DB_TYPEf) & 0x1) {
    491         return SOC_E_NONE;
    492     }
    493 
    494     pivot_pyld = (alpm_pivot_t *)trie;
    495     pvt_bpm_len = PIVOT_TCAM_BPMLEN(pivot_pyld);
    496     pfx_len = soc_mem_field32_get(unit, aux_mem, aux_entry, IP_LENGTHf);
    497 
    498     /* Addr & Mask has been screened by propagate function,
    499      * no need to do it again */
    500     if (user_data->aux_op == INSERT_PROPAGATE) {
    501         if (pvt_bpm_len > pfx_len) {
    502             /* Not qualified */
    503             return SOC_E_NONE;
    504         }
    505     }
    506 
    507     if (user_data->aux_op == DELETE_PROPAGATE) {
    508         if (pvt_bpm_len != pfx_len) {
    509             /* Not qualified */
    510             return SOC_E_NONE;
    511         }
    512     }
    513 
    514     rpl_bpm_len = soc_mem_field32_get(unit, aux_mem, aux_entry, REPLACE_LENf);
    515     if (user_data->aux_op == INSERT_PROPAGATE) {
    516         rpl_bpm_len = pfx_len;
    517     }
    518 
    519     /* Update bpm length accordingly */
    520     PIVOT_TCAM_BPMLEN(pivot_pyld) = rpl_bpm_len;
    521 
    522     /* update callback count, hw propagate is counting on this */
    523     user_data->count ++;
    524 
    525     sal_memset(&replace_data, 0, sizeof(replace_data));
    526     soc_mem_field_get(unit, aux_mem, aux_entry, REPLACE_DATAf,
    527                       (uint32 *)&replace_data);
    528     mode = soc_mem_field32_get(unit, aux_mem, aux_entry, MODEf);
    529 
    530     tcam_index = PIVOT_TCAM_INDEX(pivot_pyld);
    531     if (mode == 0 || mode == 1) {
    532         soc_mem_t lpm_mem = L3_DEFIPm;
    533         defip_entry_t lpm_entry;
    534 
    535         /* Update L3_DEFIPm */
    536         lpm_index = soc_alpm_logical_idx(unit, lpm_mem, tcam_index >> 1, 1);
    537         aux_index = tcam_index >> 1;
    538 
    539         LOG_INFO(BSL_LS_SOC_ALPM,
    540             (BSL_META_U(unit, "ALPM SW %s ppg cb: lpm_mem %s index %d ent %d,"
    541             "AUX_TABLE index %d\n"),
    542             (user_data->aux_op == INSERT_PROPAGATE) ? "Add" : "Del",
    543             SOC_MEM_NAME(unit, lpm_mem), lpm_index,
    544             (tcam_index & 1), aux_index));
    545 
    546         soc_mem_lock(unit, lpm_mem);
    547         rv = _soc_mem_alpm_read_cache(unit, lpm_mem, MEM_BLOCK_ANY,
    548                                       lpm_index, &lpm_entry);
    549         if (SOC_SUCCESS(rv)) {
    550             if (mode == 1) {
    551                 /* IPv6_64 */
    552                 soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry,
    553                     REPLACE_DATA0f, (uint32 *)&replace_data);
    554             } else {
    555                 /* IPv4 */
    556                 soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry,
    557                     (tcam_index & 1) ? REPLACE_DATA1f : REPLACE_DATA0f,
    558                     (uint32 *)&replace_data);
    559             }
    560             _soc_mem_alpm_write_cache(unit, lpm_mem, MEM_BLOCK_ALL,
    561                                       lpm_index, &lpm_entry);
    562             if (SOC_URPF_STATUS_GET(unit)) {
    563                 lpm_index = _URPF_INDEX(TRUE, lpm_index, L3_DEFIPm);
    564                 (void)_soc_mem_alpm_read_cache(unit, lpm_mem, MEM_BLOCK_ANY,
    565                                                lpm_index, &lpm_entry);
    566                 if (mode == 1) {
    567                     soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry,
    568                         REPLACE_DATA0f, (uint32 *)&replace_data);
    569                     soc_mem_field32_set(unit, lpm_mem, &lpm_entry,
    570                         RPE0f, (aux_flags & SOC_ALPM_AUX_DEF_ROUTE) ? 1 : 0);
    571                     soc_mem_field32_set(unit, lpm_mem,
    572                         &lpm_entry, SRC_DISCARD0f,
    573                         (aux_flags & SOC_ALPM_AUX_SRC_DISCARD) ? 1 : 0);
    574                 } else {
    575                     soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry,
    576                         (tcam_index & 1) ? REPLACE_DATA1f : REPLACE_DATA0f,
    577                         (uint32 *)&replace_data);
    578                     soc_mem_field32_set(unit, lpm_mem, &lpm_entry,
    579                         (tcam_index & 1) ? RPE1f : RPE0f,
    580                         (aux_flags & SOC_ALPM_AUX_DEF_ROUTE) ? 1 : 0);
    581                     soc_mem_field32_set(unit, lpm_mem, &lpm_entry,
    582                         (tcam_index & 1) ? SRC_DISCARD1f : SRC_DISCARD0f,
    583                         (aux_flags & SOC_ALPM_AUX_SRC_DISCARD) ? 1 : 0);
    584                 }
    585                 _soc_mem_alpm_write_cache(unit, lpm_mem, MEM_BLOCK_ALL,
    586                                           lpm_index, &lpm_entry);
    587             }
    588         }
    589         soc_mem_unlock(unit, lpm_mem);
    590 
    591         /* Update L3_DEFIP_AUX_TABLEm */
    592         lpm_mem = L3_DEFIP_AUX_TABLEm;
    593 
    594         soc_mem_lock(unit, lpm_mem);
    595         rv = _soc_mem_alpm_read_cache(unit, lpm_mem, MEM_BLOCK_ANY,
    596                                       aux_index, &shadow_entry);
    597         if (SOC_SUCCESS(rv)) {
    598             if (mode == 1) { /* IPv6_64 */
    599                 soc_mem_field32_set(unit, lpm_mem, &shadow_entry,
    600                     BPM_LENGTH0f, rpl_bpm_len);
    601                 soc_mem_field32_set(unit, lpm_mem, &shadow_entry,
    602                     BPM_LENGTH1f, rpl_bpm_len);
    603             } else { /* IPv4 */
    604                 soc_mem_field32_set(unit, lpm_mem, &shadow_entry,
    605                     (tcam_index & 1) ? BPM_LENGTH1f : BPM_LENGTH0f,
    606                     rpl_bpm_len);
    607             }
    608             _soc_mem_alpm_write_cache(unit, lpm_mem, MEM_BLOCK_ALL,
    609                                       aux_index, &shadow_entry);
    610             if (SOC_URPF_STATUS_GET(unit)) {
    611                 aux_index = _URPF_INDEX(TRUE, aux_index, L3_DEFIP_AUX_TABLEm);
    612                 (void)_soc_mem_alpm_read_cache(unit, lpm_mem, MEM_BLOCK_ANY,
    613                                                aux_index, &shadow_entry);
    614                 if (mode == 1) { /* IPv6_64 */
    615                     soc_mem_field32_set(unit, lpm_mem, &shadow_entry,
    616                         BPM_LENGTH0f, rpl_bpm_len);
    617                     soc_mem_field32_set(unit, lpm_mem, &shadow_entry,
    618                         BPM_LENGTH1f, rpl_bpm_len);
    619                 } else { /* IPv4 */
    620                     soc_mem_field32_set(unit, lpm_mem, &shadow_entry,
    621                         (tcam_index & 1) ? BPM_LENGTH1f : BPM_LENGTH0f,
    622                         rpl_bpm_len);
    623                 }
    624                 _soc_mem_alpm_write_cache(unit, lpm_mem, MEM_BLOCK_ALL,
    625                                           aux_index, &shadow_entry);
    626             }
    627         }
    628         soc_mem_unlock(unit, lpm_mem);
    629 
    630     } else if (mode == 3) {
    631         soc_mem_t lpm128_mem = L3_DEFIP_PAIR_128m;
    632         defip_pair_128_entry_t lpm128_entry;
    633 
    634         lpm_index = soc_alpm_logical_idx(unit, L3_DEFIP_PAIR_128m,
    635                         SOC_ALPM_128_DEFIP_TO_PAIR(unit, tcam_index >> 1), 1);
    636         aux_index = SOC_ALPM_128_DEFIP_TO_PAIR(unit, tcam_index >> 1);
    637         LOG_INFO(BSL_LS_SOC_ALPM,
    638             (BSL_META_U(unit, "ALPM SW %s ppg cb: lpm_mem %s index %d, "
    639             "AUX_TABLE index0 %d index1 %d\n"),
    640             (user_data->aux_op == INSERT_PROPAGATE) ? "Add" : "Del",
    641             SOC_MEM_NAME(unit, lpm128_mem), lpm_index,
    642             SOC_ALPM_128_ADDR_LWR(unit, aux_index),
    643             SOC_ALPM_128_ADDR_UPR(unit, aux_index)));
    644 
    645         /* Update L3_DEFIP_PAIR_128m */
    646         soc_mem_lock(unit, lpm128_mem);
    647         rv = _soc_mem_alpm_read_cache(unit, lpm128_mem, MEM_BLOCK_ANY,
    648                                       lpm_index, &lpm128_entry);
    649         if (SOC_SUCCESS(rv)) {
    650             soc_mem_field_set(unit, lpm128_mem, (uint32 *)&lpm128_entry,
    651                 REPLACE_DATAf, (uint32 *)&replace_data);
    652             _soc_mem_alpm_write_cache(unit, lpm128_mem, MEM_BLOCK_ALL,
    653                                       lpm_index, &lpm128_entry);
    654             if (SOC_URPF_STATUS_GET(unit)) {
    655                 lpm_index = _URPF_INDEX(TRUE, lpm_index, L3_DEFIP_PAIR_128m);
    656                 (void)_soc_mem_alpm_read_cache(unit, lpm128_mem, MEM_BLOCK_ANY,
    657                                                lpm_index, &lpm128_entry);
    658                 soc_mem_field_set(unit, lpm128_mem, (uint32 *)&lpm128_entry,
    659                     REPLACE_DATAf, (uint32 *)&replace_data);
    660                 soc_mem_field32_set(unit, lpm128_mem, &lpm128_entry,
    661                     RPEf, (aux_flags & SOC_ALPM_AUX_DEF_ROUTE) ? 1 : 0);
    662                 soc_mem_field32_set(unit, lpm128_mem,
    663                     &lpm128_entry, SRC_DISCARDf,
    664                     (aux_flags & SOC_ALPM_AUX_SRC_DISCARD) ? 1 : 0);
    665                 _soc_mem_alpm_write_cache(unit, lpm128_mem, MEM_BLOCK_ALL,
    666                     lpm_index, &lpm128_entry);
    667             }
    668         }
    669         soc_mem_unlock(unit, lpm128_mem);
    670 
    671         /* Update L3_DEFIP_AUX_TABLEm */
    672         lpm128_mem = L3_DEFIP_AUX_TABLEm;
    673 
    674         soc_mem_lock(unit, lpm128_mem);
    675         /* Needs to update 2 AUX_TABLE entries */
    676         for (i = 0; i < 2; i++) {
    677             int index;
    678             index = ((i == 0) ?
    679                      SOC_ALPM_128_ADDR_LWR(unit, aux_index) :
    680                      SOC_ALPM_128_ADDR_UPR(unit, aux_index));
    681             rv = _soc_mem_alpm_read_cache(unit, lpm128_mem, MEM_BLOCK_ANY,
    682                                           index, &shadow_entry);
    683             if (SOC_SUCCESS(rv)) {
    684                 soc_mem_field32_set(unit, lpm128_mem, &shadow_entry,
    685                     BPM_LENGTH0f, rpl_bpm_len);
    686                 soc_mem_field32_set(unit, lpm128_mem, &shadow_entry,
    687                     BPM_LENGTH1f, rpl_bpm_len);
    688                 _soc_mem_alpm_write_cache(unit, lpm128_mem, MEM_BLOCK_ALL,
    689                                           index, &shadow_entry);
    690                 if (SOC_URPF_STATUS_GET(unit)) {
    691                     index = _URPF_INDEX(TRUE, index, lpm128_mem);
    692                     (void)_soc_mem_alpm_read_cache(unit, lpm128_mem,
    693                                 MEM_BLOCK_ANY, index, &shadow_entry);
    694                     soc_mem_field32_set(unit, lpm128_mem, &shadow_entry,
    695                         BPM_LENGTH0f, rpl_bpm_len);
    696                     soc_mem_field32_set(unit, lpm128_mem, &shadow_entry,
    697                         BPM_LENGTH1f, rpl_bpm_len);
    698                     _soc_mem_alpm_write_cache(unit, lpm128_mem, MEM_BLOCK_ALL,
    699                                               index, &shadow_entry);
    700                 }
    701             }
    702         }
    703         soc_mem_unlock(unit, lpm128_mem);
    704     } else {
    705         return SOC_E_INTERNAL;
    706     }
    707 
    708     return SOC_E_NONE;
    709 }
    710 
    711 /*
    712  * ipv4:     ip6_word[4] =
    713  *               {IP_ADDR0f, 0, 0, 0}
    714  * ipv6-64:  ip6_word[4] =
    715  *               {0, 0, IP_ADDR0f, IP_ADDR1f}
    716  * ipv6-128: ip6_word[4] =
    717  *               {IP_ADDR0_LWRf, IP_ADDR1_LWRf, IP_ADDR0_UPRf, IP_ADDR1_UPRf}
    718  */
    719 STATIC void
    720 _soc_alpm_trie_prefix_create(int u, int mode, uint32 *ip6_word, uint32 len,
    721                                 uint32 *pfx)
    722 {
    723     int i;
    724     uint32 pfx_shift, tmp;
    725 
    726     pfx[0] = pfx[1] = pfx[2] = pfx[3] = pfx[4] = 0;
    727     /* Obtain prefix length */
    728     if (mode == 0) {
    729         pfx[1] = SHR_SHIFT_RIGHT(ip6_word[0], 32 - len);
    730         pfx[0] = 0;
    731     } else if (mode == 1) {
    732         pfx[4] = ip6_word[2];
    733         pfx[3] = ip6_word[3];
    734 
    735         pfx_shift = 64 - len;
    736         if (pfx_shift < 32) {
    737             /* get lower half shifted */
    738             pfx[4] >>= pfx_shift;
    739             /* isolate shifted stuff of upper half */
    740             tmp = SHR_SHIFT_LEFT(pfx[3], 32 - pfx_shift);
    741             pfx[3] >>= pfx_shift;
    742             pfx[4] |= tmp;
    743         } else {
    744             pfx[4] = SHR_SHIFT_RIGHT(pfx[3], pfx_shift - 32);
    745             pfx[3] = 0;
    746         }
    747     } else {
    748         /* PAIR_128 style, for both mode==2 and mode==3  */
    749         int start;
    750         uint32 tmp_pfx[5] = {0};
    751         tmp_pfx[0] = ip6_word[0];
    752         tmp_pfx[1] = ip6_word[1];
    753         tmp_pfx[2] = ip6_word[2];
    754         tmp_pfx[3] = ip6_word[3];
    755 
    756         /* shift entire prefix right to remove trailing 0s in prefix */
    757         /* to simplify, words which are all 0s are ignored to begin with, so
    758          * a right shift of say 46 is a right shift of 46-32 = 14, but starting
    759          * from word 1. Once all shifting is done, shift all words to right by 1
    760          */
    761         pfx_shift = 128 - len;
    762         start = pfx_shift / 32;
    763         pfx_shift = pfx_shift % 32;
    764         for (i = start; i < 4; i++) {
    765             tmp_pfx[i] >>= pfx_shift;
    766             tmp = tmp_pfx[i+1] & ((1 << pfx_shift) - 1);
    767             tmp = SHR_SHIFT_LEFT(tmp, 32 - pfx_shift);
    768             tmp_pfx[i] |= tmp;
    769         }
    770         /* make shift right justified and also reverse order for trie.
    771          * Also, note trie sees key only in words 1 to 4
    772          */
    773         for (i = start; i < 4; i++) {
    774             pfx[4 - (i - start)] = tmp_pfx[i];
    775         }
    776     }
    777     return ;
    778 }
    779 
    780 /* Create prefix & len in trie format from aux entry */
    781 STATIC void
    782 _soc_alpm_aux_prefix_create(int u, void *aux_entry, uint32 *pfx, uint32 *len)
    783 {
    784     uint32 ip6_word[4];
    785     int mode;
    786     soc_mem_t aux_mem = L3_DEFIP_AUX_SCRATCHm;
    787 
    788     soc_mem_field_get(u, aux_mem, aux_entry, IP_ADDRf, (uint32 *)ip6_word);
    789     *len = soc_mem_field32_get(u, aux_mem, aux_entry, IP_LENGTHf);
    790     mode = soc_mem_field32_get(u, aux_mem, aux_entry, MODEf);
    791 
    792     return _soc_alpm_trie_prefix_create(u, mode, ip6_word, *len, pfx);
    793 }
    794 
    795 /* Software propagation */
    796 STATIC int
    797 _soc_alpm_aux_sw_op(int u, _soc_aux_op_t aux_op, void *aux_entry,
    798                     int *match_cnt, int aux_flags)
    799 {
    800     trie_t *pivot;
    801     int rv = SOC_E_NONE;
    802     int vld, mode, dbt, vrf = 0;
    803     uint32 prefix[5];
    804     uint32 len;
    805     trie_bpm_cb_user_data_t user_data;
    806     soc_mem_t aux_mem = L3_DEFIP_AUX_SCRATCHm;
    807     int insert = 0;
    808 
    809     switch (aux_op) {
    810         case INSERT_PROPAGATE:
    811             insert = 1;
    812             break;
    813         case DELETE_PROPAGATE:
    814             insert = 0;
    815             break;
    816         case HITBIT_REPLACE:
    817         case PREFIX_LOOKUP:
    818         default:
    819             return SOC_E_NONE;
    820     }
    821 
    822     vld  = soc_mem_field32_get(u, aux_mem, aux_entry, VALIDf);
    823     mode = soc_mem_field32_get(u, aux_mem, aux_entry, MODEf);
    824     vrf  = soc_mem_field32_get(u, aux_mem, aux_entry, VRFf);
    825     dbt  = soc_mem_field32_get(u, aux_mem, aux_entry, DB_TYPEf);
    826 
    827     /* Need to distinguish vrf=0 and Global low */
    828     if ((vrf == 0) && (dbt <= 1)) {
    829         vrf = SOC_VRF_MAX(u) + 1;
    830     }
    831 
    832     /* Mode indicates entry type: 00:IPv4, 01: 64-Ipv6, 11: IPv6-128 */
    833     if (mode == 0) {
    834         pivot = VRF_PIVOT_TRIE_IPV4(u, vrf);
    835     } else if (mode == 1) {
    836         pivot = VRF_PIVOT_TRIE_IPV6(u, vrf);
    837     } else if (mode == 3) {
    838         pivot = VRF_PIVOT_TRIE_IPV6_128(u, vrf);
    839     } else {
    840         return SOC_E_INTERNAL;
    841     }
    842 
    843     _soc_alpm_aux_prefix_create(u, aux_entry, (void *)prefix, &len);
    844 
    845     sal_memset(&user_data, 0, sizeof(user_data));
    846     user_data.unit     = u;
    847     user_data.entry    = aux_entry;
    848     user_data.aux_op   = aux_op;
    849     user_data.flags    = aux_flags;
    850 
    851     if (vld && pivot) {
    852         rv = _soc_alpm_sw_propagate(u, pivot, prefix, len, insert,
    853                                     _soc_alpm_propagate_callback, &user_data);
    854     }
    855 
    856     if (insert) {
    857         soc_alpm_dbg_cnt[u].ppg_cb_insert += user_data.count;
    858     } else {
    859         soc_alpm_dbg_cnt[u].ppg_cb_delete += user_data.count;
    860     }
    861 
    862     if (match_cnt != NULL) {
    863         *match_cnt = user_data.count;
    864     }
    865 
    866     return rv;
    867 
    868 }
    869 
    870 
    871 /* returns 0 for Combined Search mode and 1 for Parallel Search mode */
    872 int
    873 soc_alpm_mode_get(int u)
    874 {
    875     if (soc_trident2_alpm_mode_get(u) == 1) {
    876         return 1;
    877     } else {
    878         return 0;
    879     }
    880 }
    881 
    882 
    883 int
    884 _soc_alpm_mask_len_get(int u, int ipv6, void *entry, int *pfx)
    885 {
    886     int     rv;
    887     uint32  ipv4a;
    888 
    889     if (ipv6) {
    890         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f);
    891         if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) {
    892             return(rv);
    893         }
    894         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK1f);
    895         if (*pfx) {
    896             if (ipv4a != 0xffffffff)  {
    897                 return(SOC_E_PARAM);
    898             }
    899             *pfx += 32;
    900         } else {
    901             if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) {
    902                 return(rv);
    903             }
    904         }
    905     } else {
    906         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f);
    907         if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) {
    908             return(rv);
    909         }
    910     }
    911 
    912     return SOC_E_NONE;
    913 }
    914 
    915 /**
    916  * Tomahawk & Trident2+ ALPM VRF[10], VRF[11] bit WAR, Trident2 no change.
    917  * Need to handle Warmboot as well.
    918  *
    919  * TH's Pivot Scan Engine is not comparing bit 10 of the VRF[10:0].
    920  * TD2+ also has this issue, it's Pivot Scan Engine is not comparing
    921  * bits 11:10 of VRF[11:0]
    922  *
    923  * Proposed WAR:
    924  * New DB_TYPE encodings. In TD2+ we sacrifice FCOE(ENTRY_TYPE=1) entry support
    925  * to get 4K VRF support.
    926  * 
    927  * Tips for future FCoE implementation:
    928  *   Mark VALID0/1 bits to 0 for FCoE entries, so we don't actually care 
    929  *   ENTRY_TYPE bits in L3_DEFIP_AUX_TABLE, like Global High routes.
    930  * 
    931  * ----------------------------------------------------------
    932  * |                        | No uRPF       | uRPF          |
    933  * ----------------------------------------------------------
    934  * | DB_TYPE(Global)        | 0             | 1             |
    935  * ----------------------------------------------------------
    936  * | DB_TYPE(VRF0-1023)     | 2             | 3             |    TD2
    937  * -------------------------------------------------------------------
    938  * | DB_TYPE(VRF1024-2047)  | 4             | 5             |    TH
    939  * -------------------------------------------------------------------
    940  * | DB_TYPE(VRF2048-3071)  | 6             | 7             |
    941  * ----------------------------------------------------------
    942  * | DB_TYPE(VRF3072-4095)  | 4+EntType=1   | 5+EntType=1   |    TD2+
    943  * -------------------------------------------------------------------
    944  */
    945 void
    946 soc_alpm_db_ent_type_encoding(int u, int vrf, uint32 *db_type, uint32 *ent_type)
    947 {
    948     int dbt, ent, vrf_msb;
    949     uint32 db_type_conf[4] = {2, 4, 6, 4};
    950     uint32 en_type_conf[4] = {0, 0, 0, 1};
    951 
    952     /* Global Low routes always use db_type 0 */
    953     if (vrf == (SOC_VRF_MAX(u) + 1)) {
    954         dbt = 0;
    955         ent = 0;
    956     } else if (SOC_IS_TRIDENT2PLUS(u) || SOC_IS_TOMAHAWKX(u)) {
    957         /* TD2+ and TH */
    958         vrf_msb = (vrf >> 10) & 0x3;
    959         dbt = db_type_conf[vrf_msb];
    960         ent = en_type_conf[vrf_msb];
    961     } else {
    962         /* other chips including TD2 (TD2,TH+,TH2,AP...) */
    963         dbt = 2;
    964         ent = 0;
    965     }
    966 
    967     if (db_type != NULL) {
    968         *db_type = dbt;
    969     }
    970 
    971     if (ent_type != NULL) {
    972         *ent_type = ent;
    973     }
    974 
    975     return ;
    976 }
    977 
    978 int
    979 _soc_alpm_rpf_entry(int u, int idx)
    980 {
    981     int bkt;
    982     bkt = (idx >> 2) & 0x3fff;
    983     bkt += SOC_ALPM_BUCKET_COUNT(u);
    984     /* form rpf alpm entry index */
    985     return (idx & ~(0x3fff << 2)) | (bkt << 2);
    986 }
    987 
    988 /* for v4 full = 0, for v6-64 full = 1 */
    989 int
    990 soc_alpm_physical_idx(int u, soc_mem_t mem, int index, int full)
    991 {
    992     int tmp = index & 1;
    993 
    994     if (full) {
    995         return soc_trident2_l3_defip_index_map(u, mem, index);
    996     }
    997     index >>= 1;
    998     index = soc_trident2_l3_defip_index_map(u, mem, index);
    999     index <<= 1;
   1000     index |= tmp;
   1001     return index;
   1002 }
   1003 
   1004 int
   1005 soc_alpm_logical_idx(int u, soc_mem_t mem, int index, int full)
   1006 {
   1007     int tmp = index & 1;
   1008 
   1009     if (full) {
   1010         return soc_trident2_l3_defip_index_remap(u, mem, index);
   1011     }
   1012     index >>= 1;
   1013     index = soc_trident2_l3_defip_index_remap(u, mem, index);
   1014     index <<= 1;
   1015     index |= tmp;
   1016     return index;
   1017 }
   1018 
   1019 static void
   1020 _soc_alpm_pfx_len_to_mask(int u, void *lpm_entry, int len, int ipv6)
   1021 {
   1022     uint32 mask = 0;
   1023 
   1024     if (ipv6) {
   1025         if (len >= 32) {
   1026             mask = 0xffffffff;
   1027             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, mask);
   1028             mask = ~SHR_SHIFT_RIGHT(0xffffffff, len - 32);
   1029             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, mask);
   1030         } else {
   1031             mask = ~(0xffffffff >> len);
   1032             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, mask);
   1033             /* make sure lower word of mask is 0 */
   1034             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, 0);
   1035         }
   1036     } else {
   1037         assert(len <= 32);
   1038         mask = (len == 32) ? 0xffffffff : ~(0xffffffff >> len);
   1039         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, mask);
   1040     }
   1041 }
   1042 /* Create Prefix */
   1043 /* Prefix is created based on the trie key packing expectations */
   1044 /* Prefix[0] will have higher order Word, Prefix[1] will have lower order word
   1045  * in case of IPV6. For IPV4 prefix[0] will contain the prefix
   1046  */
   1047 static int
   1048 _alpm_prefix_create(int u, void *entry, uint32 *prefix, uint32 *pfx_len, 
   1049                     int *default_route)
   1050 {
   1051     int ip, ip_mask, ipv6;
   1052     int pfx = 0;
   1053     int rv = SOC_E_NONE;
   1054     uint32 pfx_shift, tmp;
   1055 
   1056     prefix[0] = prefix[1] = prefix[2] = prefix[3] = prefix[4] = 0;
   1057 
   1058     ipv6 = soc_mem_field32_get(u, L3_DEFIPm, entry, MODE0f);
   1059 
   1060     /* Form Prefix based on the entry */
   1061     ip = soc_mem_field32_get(u, L3_DEFIPm, entry, IP_ADDR0f);
   1062     ip_mask = soc_mem_field32_get(u, L3_DEFIPm, entry, IP_ADDR_MASK0f);
   1063 
   1064     prefix[1] = ip;
   1065 
   1066     ip = soc_mem_field32_get(u, L3_DEFIPm, entry, IP_ADDR1f);
   1067     ip_mask = soc_mem_field32_get(u, L3_DEFIPm, entry, IP_ADDR_MASK1f);
   1068 
   1069     prefix[0] = ip;
   1070 
   1071     /* Obtain prefix length */
   1072     if (ipv6) {
   1073         prefix[4] = prefix[1];
   1074         prefix[3] = prefix[0];
   1075         prefix[1] = prefix[0] = 0;
   1076         ip_mask = soc_mem_field32_get(u, L3_DEFIPm, entry, IP_ADDR_MASK0f);
   1077         if ((rv = _ipmask2pfx(ip_mask, &pfx)) < 0) {
   1078             return(rv);
   1079         }
   1080         ip_mask = soc_mem_field32_get(u, L3_DEFIPm, entry, IP_ADDR_MASK1f);
   1081         if (pfx) {
   1082             if (ip_mask != 0xffffffff)  {
   1083                 return(SOC_E_PARAM);
   1084             }
   1085             pfx += 32;
   1086         } else {
   1087             if ((rv = _ipmask2pfx(ip_mask, &pfx)) < 0) {
   1088                 return(rv);
   1089             }
   1090         }
   1091         pfx_shift = 64 - pfx;
   1092         if (pfx_shift < 32) {
   1093             /* get lower half shifted */
   1094             prefix[4] >>= pfx_shift;
   1095             /* isolate shifted stuff of upper half */
   1096             tmp = SHR_SHIFT_LEFT(prefix[3], 32 - pfx_shift);
   1097             prefix[3] >>= pfx_shift;
   1098             prefix[4] |= tmp;
   1099         } else {
   1100             prefix[4] = SHR_SHIFT_RIGHT(prefix[3], pfx_shift - 32);
   1101             prefix[3] = 0;
   1102         }
   1103     } else {
   1104         ip_mask = soc_mem_field32_get(u, L3_DEFIPm, entry, IP_ADDR_MASK0f);
   1105         if ((rv = _ipmask2pfx(ip_mask, &pfx)) < 0) {
   1106             return(rv);
   1107         }
   1108         prefix[1] = SHR_SHIFT_RIGHT(prefix[1], 32 - pfx);
   1109         prefix[0] = 0;
   1110     }
   1111     *pfx_len = pfx;
   1112     *default_route = (prefix[0] == 0) && (prefix[1] == 0) && (pfx == 0);
   1113     return SOC_E_NONE;
   1114 }
   1115 
   1116 #if 0
   1117 extern int sh_process_command(int u,char * c);
   1118 extern void soc_alpm_lpm_sw_dump(int unit);
   1119 void soc_debug_collect(int u, int vrf, int v6, soc_mem_t mem, void *entry)
   1120 {
   1121     int i;
   1122 
   1123     sh_process_command(u, "debug =");
   1124 
   1125     LOG_CLI(("\n====Collecting info for unit(%d), vrf(%d), v6(%d), mem(%s), entry(%p)\n", 
   1126             u, vrf, v6, SOC_MEM_NAME(u, mem), entry));
   1127 
   1128     /* Dump system configuration */
   1129     LOG_CLI(("\n====Dumping current config.bcm\n"));
   1130     sh_process_command(u, "config show");
   1131 
   1132     /* Debug counter */
   1133     LOG_CLI(("\n====Dumping ALPM debug counters\n"));
   1134     for (i = 0; i < DEBUG_VAR_NUMBER; i++) {
   1135         if (debug_var2[i] != 0) {
   1136             LOG_CLI(("debug_var2[%2d] = %d\n", i, debug_var2[i]));
   1137         }
   1138     }
   1139 
   1140     /* Dump current entry */
   1141     if (entry != NULL) {
   1142         LOG_CLI(("\n====Dumping ALPM current operating entry\n"));
   1143         soc_mem_entry_dump_if_changed(u, mem, entry, "ALPM-DBG: ");
   1144     }
   1145 
   1146     /* Dump ALPM Memories */
   1147     LOG_CLI(("\n====Dumping ALPM memories\n"));
   1148     sh_process_command(u, "d chg L3_DEFIP");
   1149     sh_process_command(u, "d chg L3_DEFIP_pair_128");
   1150     sh_process_command(u, "d chg L3_DEFIP_aux_table");
   1151     sh_process_command(u, "d chg L3_DEFIP_AUX_SCRATCH");
   1152     sh_process_command(u, "d chg L3_DEFIP_alpm_ipv4");
   1153     sh_process_command(u, "d chg L3_DEFIP_alpm_ipv6_64");
   1154     sh_process_command(u, "d chg L3_DEFIP_alpm_ipv6_128");
   1155 
   1156     /* Dump Pivot trie */
   1157     LOG_CLI(("\n====Dumping ALPM Pivot trie-tree for VRF %d\n", vrf));
   1158     trie_dump(v6 ? VRF_PIVOT_TRIE_IPV6_128(u, vrf) : VRF_PIVOT_TRIE_IPV4(u, vrf), 
   1159               NULL, NULL);
   1160 
   1161     /* Dump VRF trie */
   1162     LOG_CLI(("\n====Dumping VRF route trie-tree for VRF %d\n", vrf));
   1163     trie_dump(v6 ? VRF_PREFIX_TRIE_IPV6_128(u, vrf) : VRF_PREFIX_TRIE_IPV4(u, vrf), 
   1164               NULL, NULL);
   1165 
   1166     /* Dump Bucket trie */
   1167     LOG_CLI(("\n====Dumping Bucket trie-tree for VRF %d\n", vrf));
   1168     for (i = 0; i < MAX_PIVOT_COUNT; i++) {
   1169         if (ALPM_TCAM_PIVOT(u, i) != NULL) {
   1170             trie_t *trie = PIVOT_BUCKET_TRIE(ALPM_TCAM_PIVOT(u, i));
   1171             LOG_CLI(("\t==Dumping Trie-tree for TCAM %d, index %d\n", i, 
   1172                     soc_alpm_logical_idx(u, L3_DEFIPm, i >> 1, 1)));
   1173             trie_dump(trie, NULL, NULL);
   1174         }
   1175     }
   1176 
   1177     /* Dump ALPM LPM SW state */
   1178     LOG_CLI(("\n====Dumping ALPM LPM SW state\n"));
   1179     soc_alpm_lpm_sw_dump(u);
   1180 
   1181     /* Running Sanity check */
   1182     LOG_CLI(("\n====Running Bucket Sanity check\n"));
   1183     soc_alpm_sanity_check(u, L3_DEFIPm, -1);
   1184 
   1185     return ;
   1186 }
   1187 #endif
   1188 
   1189 int
   1190 _soc_alpm_find_in_bkt(int u, soc_mem_t mem, int bucket_index, int bank_disable,
   1191                       uint32 *e, void *alpm_data, int *key_index, int v6)
   1192 {
   1193     int rv;
   1194     rv = soc_mem_alpm_lookup(u, mem, bucket_index,
   1195                              MEM_BLOCK_ANY,
   1196                              bank_disable,
   1197                              e, alpm_data, key_index);
   1198     if (SOC_SUCCESS(rv)) {
   1199         return rv;
   1200     }
   1201     if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) {
   1202         return soc_mem_alpm_lookup(u, mem, bucket_index + 1, MEM_BLOCK_ANY,
   1203                              bank_disable, e, alpm_data, key_index);
   1204     }
   1205     return rv;
   1206 }
   1207 
   1208 
   1209 static int
   1210 _soc_alpm_sw_pivot_find(int u, uint32 *prefix, uint32 length, int v6, int vrf, 
   1211                         int *hit, int *tcam_index, int *bucket_index)
   1212 {
   1213     int rv = SOC_E_NONE;
   1214     trie_t  *pivot_trie;
   1215     trie_node_t *lpmp = NULL;
   1216     alpm_pivot_t *pivot_pyld;
   1217 
   1218     if (v6) {
   1219         pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf);
   1220     } else {
   1221         pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf);
   1222     }
   1223     rv = trie_find_lpm(pivot_trie, prefix, length, &lpmp);
   1224     if (SOC_FAILURE(rv)) {
   1225         LOG_ERROR(BSL_LS_SOC_ALPM,
   1226                   (BSL_META_U(u,
   1227                               "Pivot find failed\n")));
   1228         return rv;
   1229     }
   1230     pivot_pyld = (alpm_pivot_t *)lpmp;
   1231     
   1232     *hit = 1;
   1233     *tcam_index = PIVOT_TCAM_INDEX(pivot_pyld);
   1234     *bucket_index = PIVOT_BUCKET_INDEX(pivot_pyld);
   1235     
   1236     return SOC_E_NONE;
   1237 }
   1238 
   1239 uint32
   1240 soc_alpm_bank_dis(int u, int vrf)
   1241 {
   1242     uint32 bank_disable;
   1243     int global = (vrf == SOC_VRF_MAX(u) + 1) ? 1 : 0;
   1244     if (soc_alpm_mode_get(u) == SOC_ALPM_MODE_PARALLEL &&
   1245         SOC_URPF_STATUS_GET(u)) {
   1246         bank_disable = global ? 0x3 : 0xC;
   1247     } else {
   1248         bank_disable = 0;
   1249     }
   1250     return bank_disable;
   1251 }
   1252 
   1253 int
   1254 _soc_alpm_sw_prefix_check(int u,
   1255                           soc_mem_t mem,      /* Mem type for ALPM */
   1256                           int v6,
   1257                           void *key_data,     /* TCAM entry data */
   1258                           int vrf_id,
   1259                           int vrf)
   1260 {
   1261     int         rv = SOC_E_NONE;
   1262     uint32 prefix[5], length;
   1263     int default_route = 0;
   1264     trie_t  *pivot_trie, *bkt_trie;
   1265     trie_node_t *lpmp = NULL;
   1266     alpm_pivot_t *pivot_node;
   1267 
   1268     if (vrf_id == 0) {
   1269         if (soc_alpm_mode_get(u)) {
   1270             /* cannot have 0 as a VRF in parallel mode */
   1271             return SOC_E_PARAM;
   1272         }
   1273     }
   1274 
   1275     if (vrf_id != SOC_L3_VRF_OVERRIDE) {
   1276         /* Create Prefix */
   1277         rv = _alpm_prefix_create(u, key_data, prefix, &length,
   1278                                  &default_route);
   1279         if (SOC_FAILURE(rv)) {
   1280             LOG_ERROR(BSL_LS_SOC_ALPM,
   1281                       (BSL_META_U(u,
   1282                                   "_soc_alpm_sw_prefix_check: prefix create failed\n")));
   1283             return rv;
   1284         }
   1285 
   1286         if (v6) {
   1287             pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf);
   1288         } else {
   1289             pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf);
   1290         }
   1291 
   1292         rv = trie_find_lpm(pivot_trie, prefix, length, &lpmp);
   1293         if (SOC_FAILURE(rv)) {
   1294             LOG_ERROR(BSL_LS_SOC_ALPM,
   1295                       (BSL_META_U(u,
   1296                                   "_soc_alpm_sw_prefix_check: Pivot find failed\n")));
   1297             return rv;
   1298         }
   1299         pivot_node = (alpm_pivot_t *)lpmp;
   1300         bkt_trie = pivot_node->bucket->bucket_trie;
   1301         if (bkt_trie != NULL) {
   1302             rv = trie_search(bkt_trie, prefix, length,
   1303                              (trie_node_t **)&bkt_trie);
   1304             if (SOC_FAILURE(rv)){
   1305                 LOG_ERROR(BSL_LS_SOC_ALPM,
   1306                           (BSL_META_U(u,
   1307                                       "_soc_alpm_sw_prefix_check: prefix find failed\n")));
   1308             }
   1309         } else {
   1310             LOG_ERROR(BSL_LS_SOC_ALPM,
   1311                       (BSL_META_U(u,
   1312                                   "_soc_alpm_sw_prefix_check: bkt trie doesn't exist\n")));
   1313         }
   1314     }
   1315     return rv;
   1316 }
   1317 
   1318 /*
   1319  * Find and read the match in the database.
   1320  * Returns SOC_E_NONE, if found.
   1321  * SOC_E_NOT_FOUND if not found
   1322  * SOC_E_FAIL, if lookup failed.
   1323  */
   1324 static int
   1325 _soc_alpm_find(int u,
   1326                void *key_data,     /* TCAM entry data */
   1327                soc_mem_t mem,      /* Mem type for ALPM */
   1328                void *alpm_data,    /* Alpm data if match */
   1329                int *tcam_index,    /* TCAM INDEX */
   1330                int *bucket_index,  /* return Bucket Index*/
   1331                int *index_ptr,     /* return key location */
   1332                int sw_find         /* 1: search from trie, 0: search from aux */
   1333               )
   1334 {
   1335     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   1336     int         vrf_id, vrf, v6;
   1337     int         key_index ;
   1338     uint32      db_type, ent_type, bank_disable;
   1339     int         rv = SOC_E_NONE;
   1340     int         hit = 0;
   1341 
   1342     v6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0f);
   1343     if (v6) {
   1344         if (!(v6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE1f))) {
   1345             return (SOC_E_PARAM);
   1346         }
   1347     }
   1348 
   1349     SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   1350     if (vrf_id == 0) {
   1351         if (soc_alpm_mode_get(u)) {
   1352             /* cannot have 0 as a VRF in parallel mode */
   1353             return SOC_E_PARAM;
   1354         }
   1355     }
   1356 
   1357     soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
   1358     bank_disable = soc_alpm_bank_dis(u, vrf);
   1359 
   1360     /* For VRF_OVERRIDE (Global High) entries, software needs to maintain the
   1361      * index */
   1362     /* Prefix resides in TCAM directly */
   1363     if (vrf_id != SOC_L3_VRF_OVERRIDE) {
   1364         if (sw_find) {
   1365             uint32 prefix[5], length;
   1366             int default_route = 0;
   1367             
   1368             /* Create Prefix */
   1369             rv = _alpm_prefix_create(u, key_data, prefix, &length, &default_route);
   1370             if (SOC_FAILURE(rv)) {
   1371                 LOG_ERROR(BSL_LS_SOC_ALPM,
   1372                           (BSL_META_U(u,
   1373                                       "_soc_alpm_insert: prefix create failed\n")));
   1374 
   1375                 return rv;
   1376             }
   1377             
   1378             rv = _soc_alpm_sw_pivot_find(u, prefix, length, v6, vrf, &hit,
   1379                                          tcam_index, bucket_index);
   1380             SOC_IF_ERROR_RETURN(rv);
   1381         } else {
   1382             defip_aux_scratch_entry_t aux_entry;
   1383             /* Fill in AUX Scratch and perform Lookup Operation */
   1384             SOC_IF_ERROR_RETURN(
   1385                 _soc_alpm_fill_aux_entry_for_op(u, key_data, v6, db_type,
   1386                                                 ent_type, 0, &aux_entry));
   1387             SOC_IF_ERROR_RETURN(
   1388                 _soc_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry, TRUE, &hit, 
   1389                                  tcam_index, bucket_index, 0));
   1390         }
   1391 
   1392         if (hit) { /* Entry is found in the bucket_index */
   1393             /* Fill entry for lookup */
   1394             _soc_alpm_mem_ent_init(u, key_data, e, 0, mem, 0, 0);
   1395 
   1396             /* Perform lookup */
   1397             rv = _soc_alpm_find_in_bkt(u, mem, *bucket_index, bank_disable,
   1398                                        e, alpm_data, &key_index, v6);
   1399             if (SOC_SUCCESS(rv)) {
   1400                 *index_ptr = key_index;
   1401             } 
   1402         } else {
   1403             rv = SOC_E_NOT_FOUND;
   1404         }
   1405     }
   1406     return rv;
   1407 }
   1408 
   1409 
   1410 /*
   1411  * Find and update the match in the database.
   1412  * Returns SOC_E_NONE, if found and updated.
   1413  * SOC_E_NOT_FOUND if not found
   1414  * SOC_E_FAIL, if update failed.
   1415  */
   1416 static int
   1417 _soc_alpm_find_and_update(int u,
   1418                           void *key_data,  /* TCAM entry data */
   1419                           void *alpm_data, /* Alpm data to be updated with */
   1420                           void *alpm_sip_data,
   1421                           soc_mem_t mem,   /* Mem view for ALPM data */
   1422                           int key_index)  /* key location */
   1423 {
   1424     defip_aux_scratch_entry_t aux_entry;
   1425     int         vrf_id, v6, vrf;
   1426     int         bucket_index;
   1427     uint32      db_type, ent_type;
   1428     int         rv = SOC_E_NONE;
   1429     int         hit = 0, tmp = 0;
   1430     int         tcam_index;
   1431     int         aux_flags = 0;
   1432 
   1433     v6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0f);
   1434     if (v6) {
   1435         if (!(v6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE1f))) {
   1436             return (SOC_E_PARAM);
   1437         }
   1438     }
   1439 
   1440     SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   1441     soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
   1442 
   1443     /* For VRF_OVERRIDE (Global High) entries */
   1444     if (vrf_id != SOC_L3_VRF_OVERRIDE) {
   1445         /* Fill in AUX Scratch and perform Lookup Operation */
   1446         SOC_IF_ERROR_RETURN(
   1447            _soc_alpm_fill_aux_entry_for_op(u, key_data, v6, db_type, ent_type,
   1448                                            0, &aux_entry));
   1449         /* Perform lookup */
   1450         /* Update the entry */
   1451         SOC_IF_ERROR_RETURN(
   1452             soc_mem_write(u, mem, MEM_BLOCK_ANY, key_index, 
   1453                           alpm_data));
   1454         if (SOC_URPF_STATUS_GET(u)) {
   1455             /* Update the sip entry */
   1456             SOC_IF_ERROR_RETURN(soc_mem_write(u, mem, MEM_BLOCK_ANY, 
   1457                                 _soc_alpm_rpf_entry(u, key_index), 
   1458                                 alpm_sip_data));
   1459         }
   1460         /* set REPLACE_LEN field to correct value */
   1461         tmp = soc_mem_field32_get(u, L3_DEFIP_AUX_SCRATCHm, 
   1462                                  &aux_entry, IP_LENGTHf);
   1463         soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, &aux_entry, 
   1464                             REPLACE_LENf, tmp);
   1465 
   1466         if (SOC_URPF_STATUS_GET(u)) {
   1467             if (soc_mem_field32_get(u, mem, alpm_sip_data, DEFAULTROUTEf)) {
   1468                 aux_flags |= SOC_ALPM_AUX_DEF_ROUTE;
   1469             }
   1470             if (soc_mem_field32_get(u, mem, alpm_sip_data, SRC_DISCARDf)) {
   1471                 aux_flags |= SOC_ALPM_AUX_SRC_DISCARD;
   1472             }
   1473         }
   1474 
   1475         SOC_IF_ERROR_RETURN(
   1476             _soc_alpm_aux_op(u, DELETE_PROPAGATE, &aux_entry, TRUE,
   1477                              &hit, &tcam_index, &bucket_index, aux_flags));
   1478     }
   1479     return rv;
   1480 }
   1481 
   1482 
   1483 /* Callback function for Traverse, to find Leaf nodes */
   1484 int 
   1485 alpm_mem_prefix_array_cb(trie_node_t *node, void *info)
   1486 {
   1487     alpm_mem_prefix_array_t *prefix_array = (alpm_mem_prefix_array_t *)info;
   1488     if (node->type == PAYLOAD) {
   1489         prefix_array->prefix[prefix_array->count] = (payload_t *)node;
   1490         prefix_array->count++;
   1491     }
   1492     return SOC_E_NONE;
   1493 }
   1494 
   1495 int 
   1496 alpm_delete_node_cb(trie_node_t *node, void *info)
   1497 {
   1498     if (node != NULL) {
   1499         sal_free(node);
   1500     }
   1501     return SOC_E_NONE;
   1502 }
   1503 
   1504 
   1505 /* src and dst can be same */
   1506 static int
   1507 _soc_alpm_aux_entry_convert(int u, void *src, void *dst, int convert)
   1508 {
   1509     soc_field_t f0[] = {
   1510                 VRF0f,
   1511                 MODE0f,
   1512                 VALID0f,
   1513                 IP_LENGTH0f,
   1514                 BPM_LENGTH0f,
   1515                 IP_ADDR0f,
   1516                 DB_TYPE0f,
   1517                 ENTRY_TYPE0f};
   1518     soc_field_t f1[] = {
   1519                 VRF1f,
   1520                 MODE1f,
   1521                 VALID1f,
   1522                 IP_LENGTH1f,
   1523                 BPM_LENGTH1f,
   1524                 IP_ADDR1f,
   1525                 DB_TYPE1f,
   1526                 ENTRY_TYPE1f};
   1527     soc_field_t *sf, *df;
   1528     int i = 0;
   1529     uint32 v;
   1530 
   1531     switch (convert) {
   1532     case 0:
   1533         sf = f0;
   1534         df = f0;
   1535         break;
   1536     case 1:
   1537         sf = f0;
   1538         df = f1;
   1539         break;
   1540     case 2:
   1541         sf = f1;
   1542         df = f0;
   1543         break;
   1544     case 3:
   1545         sf = f1;
   1546         df = f1;
   1547         break;
   1548     default:
   1549         return SOC_E_INTERNAL;
   1550     }
   1551 
   1552     for (i = 0; i < COUNTOF(f0); i++) {
   1553         v = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm, src, sf[i]);
   1554         soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, dst, df[i], v);
   1555     }
   1556 
   1557     return SOC_E_NONE;
   1558 }
   1559 
   1560 
   1561 /* create shadow entry copy of primary tcam entry at index */
   1562 static int
   1563 _soc_alpm_tcam_shadow_ent_init(int u, int s_index, int index, void *entry,
   1564                                int convert, void *shadow, int bpm_len, int v4_half)
   1565 {
   1566     uint32 tmp, ip_mask, v6, db_type, ent_type, urpf = 0;
   1567     soc_mem_t mem = L3_DEFIPm;
   1568     soc_mem_t s_mem = L3_DEFIP_AUX_TABLEm;
   1569     defip_entry_t tmp_ipv4;
   1570     int rv = SOC_E_NONE, pfx, pfx2, vrf_id, vrf_id2, vrf, vrf2;
   1571     defip_aux_table_entry_t src_shadow;
   1572     void *shadow_ptr = shadow;
   1573     int       flex_v6_64 = 0;
   1574 
   1575     /* convert from logical to physical indices */
   1576     s_index = soc_alpm_physical_idx(u, L3_DEFIPm, s_index, 1);
   1577 
   1578     if (convert == CONVERT_NONE) {
   1579         SOC_IF_ERROR_RETURN(soc_mem_read(u, s_mem, MEM_BLOCK_ANY, s_index, 
   1580                             shadow));
   1581     } else {
   1582         tmp = soc_alpm_physical_idx(u, L3_DEFIPm, index, 1);
   1583         SOC_IF_ERROR_RETURN(soc_mem_read(u, s_mem, MEM_BLOCK_ANY, tmp,
   1584                             shadow));
   1585         if (s_index != tmp) {
   1586             SOC_IF_ERROR_RETURN(soc_mem_read(u, s_mem, MEM_BLOCK_ANY, s_index, 
   1587                                 &src_shadow));
   1588             shadow_ptr = (void*) &src_shadow;
   1589         }
   1590 
   1591         SOC_IF_ERROR_RETURN(_soc_alpm_aux_entry_convert(u, shadow_ptr, shadow,
   1592                                                         convert));
   1593     }
   1594 
   1595     tmp = soc_mem_field32_get(u, mem, entry, VRF_ID_0f);
   1596     soc_mem_field32_set(u, s_mem, shadow, VRF0f, tmp);
   1597     tmp = soc_mem_field32_get(u, mem, entry, VRF_ID_1f);
   1598     soc_mem_field32_set(u, s_mem, shadow, VRF1f, tmp);
   1599 
   1600     tmp = soc_mem_field32_get(u, mem, entry, MODE0f);
   1601     soc_mem_field32_set(u, s_mem, shadow, MODE0f, tmp);
   1602     tmp = soc_mem_field32_get(u, mem, entry, MODE1f);
   1603     soc_mem_field32_set(u, s_mem, shadow, MODE1f, tmp);
   1604     v6 = tmp;
   1605 
   1606     if (bpm_len == INVALID_BPM_LEN) {
   1607         /* Clean dirty data */
   1608         if (soc_mem_field32_get(u, s_mem, shadow, VALID0f) == 0) {
   1609             soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH0f, 0);
   1610         }
   1611 
   1612         if (soc_mem_field32_get(u, s_mem, shadow, VALID1f) == 0) {
   1613             soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH1f, 0);
   1614         }
   1615     } else {
   1616         assert(v6 == (v4_half==0));
   1617         if (v6) {
   1618             soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH0f, bpm_len);
   1619             soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH1f, bpm_len);
   1620         } else {
   1621             if (v4_half & 1) {
   1622                 soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH1f, bpm_len);
   1623             } else {
   1624                 soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH0f, bpm_len);
   1625             }
   1626         }
   1627     }
   1628     /* for now simply copy all fields. Let caller decide which half to use */
   1629     tmp = soc_mem_field32_get(u, mem, entry, VALID0f);
   1630     soc_mem_field32_set(u, s_mem, shadow, VALID0f, tmp);
   1631     tmp = soc_mem_field32_get(u, mem, entry, VALID1f);
   1632     soc_mem_field32_set(u, s_mem, shadow, VALID1f, tmp);
   1633 
   1634     
   1635     /* IP_LENGTH */
   1636     tmp = soc_mem_field32_get(u, mem, entry, IP_ADDR_MASK0f);
   1637     if ((rv = _ipmask2pfx(tmp, &pfx)) < 0) {
   1638         LOG_ERROR(BSL_LS_SOC_ALPM,
   1639                   (BSL_META_U(u,
   1640                               "_ipmask2pfx fails mask0 0x%x pfx %d\n"),
   1641                               tmp, pfx));
   1642         return rv;
   1643     }
   1644     ip_mask = soc_mem_field32_get(u, mem, entry, IP_ADDR_MASK1f);
   1645     if ((rv = _ipmask2pfx(ip_mask, &pfx2)) < 0) {
   1646         LOG_ERROR(BSL_LS_SOC_ALPM,
   1647                   (BSL_META_U(u,
   1648                               "_ipmask2pfx fails mask1 0x%x pfx2 %d\n"),
   1649                               ip_mask, pfx2));
   1650         return rv;
   1651     }
   1652     if (v6) {
   1653         soc_mem_field32_set(u, s_mem, shadow, IP_LENGTH0f, pfx + pfx2);
   1654         soc_mem_field32_set(u, s_mem, shadow, IP_LENGTH1f, pfx + pfx2);
   1655     } else {
   1656         soc_mem_field32_set(u, s_mem, shadow, IP_LENGTH0f, pfx);
   1657         soc_mem_field32_set(u, s_mem, shadow, IP_LENGTH1f, pfx2);
   1658     }
   1659         
   1660     /* IP_ADDR */
   1661     tmp = soc_mem_field32_get(u, mem, entry, IP_ADDR0f);
   1662     soc_mem_field32_set(u, s_mem, shadow, IP_ADDR0f, tmp);
   1663     tmp = soc_mem_field32_get(u, mem, entry, IP_ADDR1f);
   1664     soc_mem_field32_set(u, s_mem, shadow, IP_ADDR1f, tmp);
   1665 
   1666     /* DB_TYPE & ENTRY_TYPE */
   1667     /* for v4 need to be careful */
   1668     if (!v6) {
   1669         sal_memcpy(&tmp_ipv4, entry, sizeof(tmp_ipv4));
   1670         /* vrf_id for ipv4 entry 0 */
   1671         rv = soc_alpm_lpm_vrf_get(u, (void *)&tmp_ipv4, &vrf_id, &vrf);
   1672         SOC_IF_ERROR_RETURN(rv);
   1673 
   1674         /* vrf_id for ipv4 entry 1 */
   1675         SOC_IF_ERROR_RETURN(soc_alpm_lpm_ip4entry1_to_0(u, &tmp_ipv4, 
   1676                             &tmp_ipv4, PRESERVE_HIT));
   1677         rv = soc_alpm_lpm_vrf_get(u, (void *)&tmp_ipv4, &vrf_id2, &vrf2);
   1678         SOC_IF_ERROR_RETURN(rv);
   1679     } else {
   1680         rv = soc_alpm_lpm_vrf_get(u, entry, &vrf_id, &vrf);
   1681     }
   1682     if (SOC_URPF_STATUS_GET(u)) {
   1683         if (index >= (soc_mem_index_count(u, L3_DEFIPm) >> 1)) {
   1684             urpf = 1;
   1685         }
   1686     }
   1687 
   1688     soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
   1689 
   1690     if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && v6 &&
   1691         soc_mem_field32_get(u, L3_DEFIPm, entry, ENTRY_VIEW0f)) {
   1692         if (pfx2 == 32 && pfx == 32) {
   1693             flex_v6_64 = 1;
   1694         }
   1695     }
   1696 
   1697     if (vrf_id == SOC_L3_VRF_OVERRIDE ||
   1698         (soc_feature(u, soc_feature_ipmc_defip) &&
   1699          soc_mem_field32_get(u, mem, entry, MULTICAST_ROUTE0f)) ||
   1700          flex_v6_64) {
   1701         soc_mem_field32_set(u, s_mem, shadow, VALID0f, 0);
   1702         db_type = 0;
   1703     } else {
   1704         if (urpf) {
   1705             db_type += 1;
   1706         }
   1707     }
   1708 
   1709     soc_mem_field32_set(u, s_mem, shadow, DB_TYPE0f, db_type);
   1710     tmp = soc_mem_field32_get(u, mem, entry, ENTRY_TYPE0f);
   1711     soc_mem_field32_set(u, s_mem, shadow, ENTRY_TYPE0f, tmp | ent_type);
   1712     if (!v6) {
   1713         soc_alpm_db_ent_type_encoding(u, vrf2, &db_type, &ent_type);
   1714 
   1715         if (vrf_id2 == SOC_L3_VRF_OVERRIDE ||
   1716             (soc_feature(u, soc_feature_ipmc_defip) &&
   1717              soc_mem_field32_get(u, mem, entry, MULTICAST_ROUTE1f))) {
   1718             soc_mem_field32_set(u, s_mem, shadow, VALID1f, 0);
   1719             db_type = 0; /* don't care */
   1720         } else {
   1721             /* Database to be searched is VRF - DIP */
   1722             if (urpf) {
   1723                 db_type += 1;
   1724             }
   1725         }
   1726         soc_mem_field32_set(u, s_mem, shadow, DB_TYPE1f, db_type);
   1727         tmp = soc_mem_field32_get(u, mem, entry, ENTRY_TYPE1f);
   1728         soc_mem_field32_set(u, s_mem, shadow, ENTRY_TYPE1f, tmp | ent_type);
   1729     } else {
   1730         if (vrf_id == SOC_L3_VRF_OVERRIDE ||
   1731             (soc_feature(u, soc_feature_ipmc_defip) &&
   1732              soc_mem_field32_get(u, mem, entry, MULTICAST_ROUTE1f)) ||
   1733              flex_v6_64) {
   1734             soc_mem_field32_set(u, s_mem, shadow, VALID1f, 0);
   1735         }
   1736         soc_mem_field32_set(u, s_mem, shadow, DB_TYPE1f, db_type);
   1737         tmp = soc_mem_field32_get(u, mem, entry, ENTRY_TYPE1f);
   1738         soc_mem_field32_set(u, s_mem, shadow, ENTRY_TYPE1f, tmp | ent_type);
   1739     }
   1740 
   1741     /* modify bucket index if urpf is enabled */
   1742     if (urpf) {
   1743         tmp = soc_mem_field32_get(u, mem, entry, ALG_BKT_PTR0f);
   1744         if (tmp && tmp < SOC_ALPM_BUCKET_COUNT(u)) {
   1745             tmp += SOC_ALPM_BUCKET_COUNT(u);
   1746             soc_mem_field32_set(u, mem, entry, ALG_BKT_PTR0f, tmp);
   1747         }
   1748         if (!v6) {
   1749             tmp = soc_mem_field32_get(u, mem, entry, ALG_BKT_PTR1f);
   1750             if (tmp && tmp < SOC_ALPM_BUCKET_COUNT(u)) {
   1751                 tmp += SOC_ALPM_BUCKET_COUNT(u);
   1752                 soc_mem_field32_set(u, mem, entry, ALG_BKT_PTR1f, tmp);
   1753             }
   1754         }
   1755     }
   1756 
   1757     /* BPM_LENGTH */
   1758     /* don't modify, preserve existing values */
   1759     return SOC_E_NONE;
   1760 }
   1761 
   1762 static int
   1763 _soc_alpm_write_pivot_aux(int u, int s_index, int index, void *entry,
   1764                           int convert, int bpm_len, int v4_half)
   1765 {
   1766     defip_aux_table_entry_t shadow;
   1767 
   1768     SOC_IF_ERROR_RETURN(_soc_alpm_tcam_shadow_ent_init(u, 
   1769             s_index, index, entry, convert, (void *)&shadow, bpm_len, v4_half));
   1770 
   1771     /* write to defip has to be logical */
   1772     SOC_IF_ERROR_RETURN(WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, 
   1773                          index, entry));
   1774 
   1775     /* write to shadow table has to be physical */
   1776     index = soc_alpm_physical_idx(u, L3_DEFIPm, index, 1);
   1777     SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ANY,
   1778                          index, &shadow));
   1779     return SOC_E_NONE;
   1780 }
   1781 
   1782 int
   1783 _soc_alpm_insert_in_bkt(int u, soc_mem_t mem, int bucket_index,
   1784                         int bank_disable, void *alpm_data, void *alpm_sip_data,
   1785                         uint32 *e, int *key_index, int v6)
   1786 {
   1787     int rv;
   1788 
   1789     rv = soc_mem_alpm_insert(u, mem, bucket_index,
   1790                              MEM_BLOCK_ANY,
   1791                              bank_disable,
   1792                              alpm_data, e, key_index);
   1793     if (rv == SOC_E_FULL) {
   1794         /* in combined search mode non-urpf try inserting into next bkt for v6*/
   1795         if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) {
   1796             rv = soc_mem_alpm_insert(u, mem, bucket_index+1,
   1797                              MEM_BLOCK_ANY,
   1798                              bank_disable,
   1799                              alpm_data, e, key_index);
   1800         }
   1801     }
   1802 
   1803     if (SOC_SUCCESS(rv)) {
   1804         if (SOC_URPF_STATUS_GET(u)) {
   1805             rv = soc_mem_write(u, mem, MEM_BLOCK_ANY,
   1806                                _soc_alpm_rpf_entry(u, *key_index),
   1807                                alpm_sip_data);
   1808         }
   1809     }
   1810     return rv;
   1811 }
   1812 
   1813 #define _TD2_ALPM_BANK_NUM      (4)
   1814 #define _TD2_ALPM_BANK_MASK     ((1 << _TD2_ALPM_BANK_NUM) - 1)
   1815 
   1816 /* ALPM Table Address Translation
   1817  * Bank     addr[1:0]
   1818  * Bucket   addr[15:2]
   1819  * Entry    addr[16]    L3_DEFIP_ALPM_IPV6_128m
   1820  *          addr[16:17] L3_DEFIP_ALPM_IPV6_64m
   1821  *          addr[16:18] L3_DEFIP_ALPM_IPV4m
   1822  */
   1823 int 
   1824 _soc_alpm_mem_index(int u, soc_mem_t mem, int bucket_index, int offset, 
   1825                     uint32 bank_disable, int *mem_index)
   1826 {
   1827     int i, bidx = 0;
   1828     int baddr_arr[4] = {0};
   1829     int bnk_index = 0;
   1830     int ent_index = 0;
   1831     int avail_bank_num;
   1832     
   1833     int v6 = 0;
   1834     int ent_cnt = 6;
   1835 
   1836     switch (mem) {
   1837     case L3_DEFIP_ALPM_IPV4m:
   1838         ent_cnt = 6;
   1839         v6 = 0;
   1840         break;
   1841     case L3_DEFIP_ALPM_IPV4_1m:
   1842         ent_cnt = 4;
   1843         v6 = 0;
   1844         break;
   1845     case L3_DEFIP_ALPM_IPV6_64m:
   1846         ent_cnt = 4;
   1847         v6 = 1;
   1848         break;
   1849     case L3_DEFIP_ALPM_IPV6_64_1m:
   1850         ent_cnt = 3;
   1851         v6 = 1;
   1852         break;
   1853     case L3_DEFIP_ALPM_IPV6_128m:
   1854         ent_cnt = 2;
   1855         v6 = 1;
   1856         break;
   1857     default:
   1858         break;
   1859     }
   1860 
   1861     if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) {
   1862         if (offset >= ALPM_RAW_BKT_COUNT * ent_cnt) {
   1863             bucket_index ++;
   1864             offset -= ALPM_RAW_BKT_COUNT * ent_cnt;
   1865         }
   1866     }
   1867 
   1868     avail_bank_num = _TD2_ALPM_BANK_NUM - 
   1869                      _shr_popcount(bank_disable & _TD2_ALPM_BANK_MASK); 
   1870 
   1871     if (bucket_index >= (1 << 16) || offset >= avail_bank_num * ent_cnt) {
   1872         return SOC_E_FULL;
   1873     }
   1874     ent_index = offset % ent_cnt;
   1875 
   1876     /* Prepare bank address array for offset */
   1877     for (i = 0; i < _TD2_ALPM_BANK_NUM; i++) {
   1878         if ((1 << i) & bank_disable) {
   1879             continue;
   1880         }
   1881 
   1882         baddr_arr[bidx++] = i;
   1883     }
   1884     bnk_index = baddr_arr[offset / ent_cnt];
   1885     
   1886     *mem_index = (ent_index << 16)      | 
   1887                  (bucket_index << 2)    |
   1888                  (bnk_index);
   1889     return SOC_E_NONE;
   1890 }
   1891 
   1892 #ifdef ALPM_USE_RAW_VIEW
   1893 
   1894 void
   1895 _soc_alpm_raw_mem_read(int unit, soc_mem_t mem, void *raw_entry,
   1896                        int ent_id, void *entry)
   1897 {
   1898 
   1899     soc_mem_info_t meminfo;
   1900     soc_field_info_t fieldinfo;
   1901     /* Exclude HIT bit */
   1902     int entry_bits = soc_mem_entry_bits(unit, mem) - 1;
   1903 
   1904     /* Construct presdo memory & field info, to take advantage of 
   1905      * socmem.c function get original view */
   1906     meminfo.flags = 0;
   1907     meminfo.bytes = sizeof(defip_alpm_raw_entry_t);
   1908     fieldinfo.flags = SOCF_LE;
   1909     fieldinfo.bp =  entry_bits * ent_id;
   1910     fieldinfo.len = entry_bits;
   1911 
   1912     (void)soc_meminfo_fieldinfo_field_get(raw_entry, &meminfo,
   1913                                           &fieldinfo, entry);
   1914 
   1915 }
   1916 
   1917 void
   1918 _soc_alpm_raw_mem_write(int unit, soc_mem_t mem, void *raw_entry,
   1919                         int index, int ent_id, void *entry)
   1920 {
   1921     soc_mem_info_t meminfo;
   1922     soc_field_info_t fieldinfo;
   1923     /* Exclude HIT bit */
   1924     int entry_bits = soc_mem_entry_bits(unit, mem) - 1;
   1925 
   1926     (void) soc_mem_cache_invalidate(unit, mem, MEM_BLOCK_ANY, index);
   1927 
   1928     meminfo.flags = 0;
   1929     meminfo.bytes = sizeof(defip_alpm_raw_entry_t);
   1930     fieldinfo.bp =  entry_bits * ent_id;
   1931     fieldinfo.len = entry_bits;
   1932     fieldinfo.flags = SOCF_LE;
   1933 
   1934     (void)soc_meminfo_fieldinfo_field_set(raw_entry, &meminfo,
   1935                                           &fieldinfo, entry);
   1936 
   1937 }
   1938 
   1939 int
   1940 _soc_alpm_raw_bucket_read(int u, soc_mem_t mem, int bucket_index, 
   1941                           void *raw_entry, void *raw_sip_entry)
   1942 {
   1943     int i, v6 = 1;
   1944     int raw_index, raw_sip_index;
   1945     defip_alpm_raw_entry_t *ent = raw_entry;
   1946     defip_alpm_raw_entry_t *entsip = raw_sip_entry;
   1947 
   1948     if (mem == L3_DEFIP_ALPM_IPV4m ||
   1949         mem == L3_DEFIP_ALPM_IPV4_1m) {
   1950         v6 = 0;
   1951     }
   1952     
   1953     /* Read all bucket entries by using ALPM_RAW view */
   1954     raw_index = SOC_ALPM_BKT_IDX_TO_ENTRY(bucket_index);
   1955     
   1956     for (i = 0; i < SOC_ALPM_RAW_BUCKET_SIZE(u, v6); i++) {
   1957         SOC_IF_ERROR_RETURN(
   1958             _soc_mem_alpm_read(u, L3_DEFIP_ALPM_RAWm, MEM_BLOCK_ANY,
   1959                                raw_index + i, &ent[i]));
   1960         if (SOC_URPF_STATUS_GET(u)) {
   1961             raw_sip_index = _soc_alpm_rpf_entry(u, raw_index + i);                
   1962             SOC_IF_ERROR_RETURN(
   1963                 _soc_mem_alpm_read(u, L3_DEFIP_ALPM_RAWm, MEM_BLOCK_ANY,
   1964                                    raw_sip_index, &entsip[i]));
   1965         }
   1966     }
   1967 
   1968     return SOC_E_NONE;
   1969 }
   1970 
   1971 int
   1972 _soc_alpm_raw_bucket_write(int u, soc_mem_t mem, int bucket_index, 
   1973                            uint32 bank_disable,
   1974                            void *raw_entry, void *raw_sip_entry, int entry_cnt)
   1975 {
   1976     int i = 0, bank, v6 = 1;
   1977     int raw_index, raw_sip_index, raw_ent_cnt;
   1978     defip_alpm_raw_entry_t *ent = raw_entry;
   1979     defip_alpm_raw_entry_t *entsip = raw_sip_entry;
   1980     int ent_per_bank = 6;
   1981 
   1982     switch (mem) {
   1983     case L3_DEFIP_ALPM_IPV4m:
   1984         ent_per_bank = 6;
   1985         v6 = 0;
   1986         break;
   1987     case L3_DEFIP_ALPM_IPV4_1m:
   1988         ent_per_bank = 4;
   1989         v6 = 0;
   1990         break;
   1991     case L3_DEFIP_ALPM_IPV6_64m:
   1992         ent_per_bank = 4;
   1993         v6 = 1;
   1994         break;
   1995     case L3_DEFIP_ALPM_IPV6_64_1m:
   1996         ent_per_bank = 3;
   1997         v6 = 1;
   1998         break;
   1999     case L3_DEFIP_ALPM_IPV6_128m:
   2000         ent_per_bank = 2;
   2001         v6 = 1;
   2002         break;
   2003     default:
   2004         break;
   2005     }
   2006 
   2007     /* Write all bucket entries by using ALPM_RAW view */
   2008     raw_index = SOC_ALPM_BKT_IDX_TO_ENTRY(bucket_index);
   2009     if (entry_cnt == MAX_RAW_COUNT) {
   2010         raw_ent_cnt = SOC_ALPM_RAW_BUCKET_SIZE(u, v6);
   2011     } else {
   2012         raw_ent_cnt = (entry_cnt / ent_per_bank) + 1;
   2013     }
   2014 
   2015     for (bank = 0; bank < SOC_ALPM_RAW_BUCKET_SIZE(u, v6); bank++) {
   2016         if ((1 << (bank % _TD2_ALPM_BANK_NUM)) & bank_disable) {
   2017             continue;
   2018         }
   2019         SOC_IF_ERROR_RETURN(soc_mem_write(u, L3_DEFIP_ALPM_RAWm, MEM_BLOCK_ANY, 
   2020                                     raw_index + bank, &ent[bank]));
   2021         _soc_trident2_alpm_bkt_view_set(u, raw_index + bank, mem);
   2022         if (SOC_URPF_STATUS_GET(u)) {
   2023             raw_sip_index = _soc_alpm_rpf_entry(u, raw_index + bank);
   2024             _soc_trident2_alpm_bkt_view_set(u, raw_sip_index, mem);
   2025             SOC_IF_ERROR_RETURN(soc_mem_write(u, L3_DEFIP_ALPM_RAWm, MEM_BLOCK_ANY, 
   2026                                     raw_sip_index, &entsip[bank]));
   2027         }
   2028         if (++i == raw_ent_cnt) {
   2029             break;
   2030         }
   2031     }
   2032 
   2033     return SOC_E_NONE;
   2034 }
   2035 
   2036 void _soc_alpm_raw_parity_set(int u, soc_mem_t mem, void *alpm_data)
   2037 {
   2038     int i, entry_words, bit1count = 0;
   2039     uint32 *entry = alpm_data;
   2040 
   2041     entry_words = soc_mem_entry_words(u, mem);
   2042 
   2043     /* Count bit1 number */
   2044     for (i = 0; i < entry_words; i++) {
   2045         bit1count += _shr_popcount(entry[i]);
   2046     }
   2047 
   2048     /* If the number is odd, we should set PARITY bit */
   2049     if (bit1count & 0x1) {
   2050         if (SOC_MEM_FIELD_VALID(u, mem, EVEN_PARITYf)) {
   2051             soc_mem_field32_set(u, mem, alpm_data, EVEN_PARITYf, 1);
   2052         }
   2053     }
   2054 }
   2055 
   2056 static void
   2057 _soc_alpm_raw_bucket_prepare_undo(int u,
   2058                                   alpm_mem_prefix_array_t **alloc_pfx_array,
   2059                                   void **alloc_raw_bkt,
   2060                                   int  **alloc_new_index)
   2061 {
   2062     if (*alloc_raw_bkt) {
   2063         sal_free(*alloc_raw_bkt);
   2064     }
   2065     if (*alloc_pfx_array) {
   2066         sal_free(*alloc_pfx_array);
   2067         *alloc_pfx_array = NULL;
   2068     }
   2069     if (*alloc_new_index) {
   2070         sal_free(*alloc_new_index);
   2071         *alloc_new_index = NULL;
   2072     }
   2073 }
   2074 
   2075 static int
   2076 _soc_alpm_raw_bucket_prepare(int u, soc_mem_t mem,
   2077                              trie_t     *bkt_trie,
   2078                              int         bucket_index_from,
   2079                              int         bucket_index_to,
   2080                              uint32     bank_disable,
   2081                              void       *alpm_data,
   2082                              void       *alpm_sip_data,
   2083                              alpm_mem_prefix_array_t **alloc_pfx_array,
   2084                              void       **alloc_raw_bkt,
   2085                              int        **alloc_new_index,
   2086                              int        *new_index_pos,
   2087                              int        to_exist)
   2088 {
   2089     int     i, j = 0, rv = SOC_E_NONE;
   2090     int     raw_size, raw_bkt_size, alloc_size;
   2091     void    *raw_ent;
   2092     void    *raw_bkt[RAW_BKT_NUM] = {NULL};
   2093     int     raw_id = 0;
   2094     int     ent_id = 0;
   2095     int     key_index;
   2096     /* allocation pointers all set to NULL */
   2097     alpm_mem_prefix_array_t *pfx_array = NULL;
   2098     int     *index_array = NULL;
   2099     int     v6 = SOC_ALPM_MEM_V6(mem);
   2100     /* Search Result buffers */
   2101     defip_alpm_ipv4_1_entry_t alpmv4_entry, alpmv4_sip_entry;
   2102     defip_alpm_ipv6_64_1_entry_t alpmv6_entry, alpmv6_sip_entry;
   2103     void  *bufp = NULL, *sip_bufp = NULL;
   2104     defip_alpm_ipv4_1_entry_t alpmv4_entry2;
   2105     defip_alpm_ipv6_64_1_entry_t alpmv6_entry2;
   2106     void  *bufp2 = NULL;
   2107     int   max_count = 0;
   2108 
   2109     /* Assign entry buf based on table being used */
   2110     SOC_ALPM_ENTRY_BUF(v6, mem, bufp, alpmv4_entry, alpmv6_entry);
   2111     SOC_ALPM_ENTRY_BUF(v6, mem, sip_bufp, alpmv4_sip_entry, alpmv6_sip_entry);
   2112     SOC_ALPM_ENTRY_BUF(v6, mem, bufp2, alpmv4_entry2, alpmv6_entry2);
   2113 
   2114     *alloc_raw_bkt   = NULL;
   2115     *alloc_new_index = NULL;
   2116     *alloc_pfx_array = NULL;
   2117 
   2118     /* Alloc prefix array */
   2119     alloc_size = sizeof(alpm_mem_prefix_array_t);
   2120     pfx_array = sal_alloc(alloc_size, "prefix array");
   2121     if (pfx_array == NULL) {
   2122         goto cleanup;
   2123     }
   2124 
   2125     /* Fill prefix array */
   2126     sal_memset(pfx_array, 0, alloc_size);
   2127     rv = trie_traverse(bkt_trie, alpm_mem_prefix_array_cb,
   2128                        pfx_array, _TRIE_INORDER_TRAVERSE);
   2129     if (SOC_FAILURE(rv)) {
   2130         goto cleanup;
   2131     }
   2132 
   2133     /* Alloc index array */
   2134     alloc_size = sizeof(int) * pfx_array->count;
   2135     index_array = sal_alloc(alloc_size, "index_array");
   2136     if (index_array == NULL) {
   2137         goto cleanup;
   2138     }
   2139     sal_memset(index_array, -1, alloc_size);
   2140 
   2141     raw_size = sizeof(defip_alpm_raw_entry_t);
   2142     raw_bkt_size = raw_size * ALPM_RAW_BKT_COUNT_DW;
   2143     raw_bkt[0] = sal_alloc(RAW_BKT_NUM * raw_bkt_size, "Raw memory buffer");
   2144     if (raw_bkt[0] == NULL) {
   2145         rv = SOC_E_MEMORY;
   2146         goto cleanup;
   2147     }
   2148     sal_memset(raw_bkt[0], 0, RAW_BKT_NUM * raw_bkt_size);
   2149     for (i = 1; i < RAW_BKT_NUM; i++) {
   2150         raw_bkt[i] = (uint8 *)raw_bkt[0] + raw_bkt_size * i;
   2151     }
   2152 
   2153     rv = _soc_alpm_raw_bucket_read(u, mem, bucket_index_from,
   2154                                    raw_bkt[RAW_OLD_BKT_DIP],
   2155                                    raw_bkt[RAW_OLD_BKT_SIP]);
   2156     if (SOC_FAILURE(rv)) {
   2157         goto cleanup;
   2158     }
   2159     sal_memcpy(raw_bkt[RAW_RB_BKT_DIP], raw_bkt[RAW_OLD_BKT_DIP], raw_bkt_size);
   2160     sal_memcpy(raw_bkt[RAW_RB_BKT_SIP], raw_bkt[RAW_OLD_BKT_SIP], raw_bkt_size);
   2161 
   2162     if (to_exist) {
   2163         rv = _soc_alpm_raw_bucket_read(u, mem, bucket_index_to,
   2164                                        raw_bkt[RAW_NEW_BKT_DIP],
   2165                                        raw_bkt[RAW_NEW_BKT_SIP]);
   2166         if (SOC_FAILURE(rv)) {
   2167             goto cleanup;
   2168         }
   2169         max_count = _soc_alpm_bkt_entry_cnt(u, mem);
   2170     }
   2171 
   2172     for (i = 0; i < pfx_array->count; i++) {
   2173         payload_t *pfx = pfx_array->prefix[i];
   2174         if (pfx->index > 0) {
   2175             /* if this is the new prefix it does not exist in the
   2176              * bucket, no point reading */
   2177             SOC_ALPM_RAW_INDEX_DECODE(u, v6, pfx->index, raw_id, ent_id);
   2178             raw_ent = (uint8 *)raw_bkt[RAW_OLD_BKT_DIP] + raw_id * raw_size;
   2179             _soc_alpm_raw_mem_read(u, mem, raw_ent, ent_id, bufp);
   2180             _soc_alpm_raw_mem_write(u, mem, raw_ent, pfx->index,
   2181                                     ent_id, soc_mem_entry_null(u, mem));
   2182 
   2183             if (SOC_URPF_STATUS_GET(u)) {
   2184                 raw_ent = (uint8 *)raw_bkt[RAW_OLD_BKT_SIP] + raw_id * raw_size;
   2185                 _soc_alpm_raw_mem_read(u, mem, raw_ent, ent_id, sip_bufp);
   2186                 _soc_alpm_raw_mem_write(u, mem, raw_ent,
   2187                                         _soc_alpm_rpf_entry(u, pfx->index),
   2188                                         ent_id, soc_mem_entry_null(u, mem));
   2189             }
   2190 
   2191             if (to_exist) {
   2192                 for (;j < max_count; j++) {
   2193                     rv = _soc_alpm_mem_index(u, mem, bucket_index_to, j,
   2194                                              bank_disable, &key_index);
   2195                     if (SOC_FAILURE(rv)) {
   2196                         goto cleanup;
   2197                     }
   2198                     SOC_ALPM_RAW_INDEX_DECODE(u, v6, key_index, raw_id, ent_id);
   2199                     raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_DIP] + raw_id * raw_size;
   2200                     _soc_alpm_raw_mem_read(u, mem, raw_ent, ent_id, bufp2);
   2201                     if (soc_mem_field32_get(u, mem, bufp2, VALIDf) == 0) {
   2202                         break;
   2203                     }
   2204                 }
   2205                 if (j == max_count) {
   2206                     rv = SOC_E_INTERNAL;
   2207                     goto cleanup;
   2208                 }
   2209                 _soc_alpm_raw_mem_write(u, mem, raw_ent,
   2210                                         key_index, ent_id, bufp);
   2211                 if (SOC_URPF_STATUS_GET(u)) {
   2212                     raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_SIP] + raw_id * raw_size;
   2213                     _soc_alpm_raw_mem_write(u, mem, raw_ent,
   2214                                             _soc_alpm_rpf_entry(u, key_index),
   2215                                             ent_id, sip_bufp);
   2216                 }
   2217             } else {
   2218                 rv = _soc_alpm_mem_index(u, mem, bucket_index_to, i,
   2219                                          bank_disable, &key_index);
   2220                 if (SOC_FAILURE(rv)) {
   2221                     goto cleanup;
   2222                 }
   2223                 SOC_ALPM_RAW_INDEX_DECODE(u, v6, key_index, raw_id, ent_id);
   2224                 raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_DIP] + raw_id * raw_size;
   2225                 _soc_alpm_raw_mem_write(u, mem, raw_ent,
   2226                                         key_index, ent_id, bufp);
   2227                 if (SOC_URPF_STATUS_GET(u)) {
   2228                     raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_SIP] + raw_id * raw_size;
   2229                     _soc_alpm_raw_mem_write(u, mem, raw_ent,
   2230                                             _soc_alpm_rpf_entry(u, key_index),
   2231                                             ent_id, sip_bufp);
   2232                 }
   2233             }
   2234         } else {
   2235             rv = _soc_alpm_mem_index(u, mem, bucket_index_to, i,
   2236                                      bank_disable, &key_index);
   2237             if (SOC_FAILURE(rv)) {
   2238                 goto cleanup;
   2239             }
   2240 
   2241             if (!new_index_pos) {
   2242                 rv = SOC_E_PARAM;
   2243                 goto cleanup;
   2244             }
   2245             *new_index_pos = i;
   2246 
   2247             /* New entry, need to take care of Parity for raw view */
   2248             _soc_alpm_raw_parity_set(u, mem, alpm_data);
   2249             SOC_ALPM_RAW_INDEX_DECODE(u, v6, key_index, raw_id, ent_id);
   2250             raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_DIP] + raw_id * raw_size;
   2251             _soc_alpm_raw_mem_write(u, mem, raw_ent,
   2252                                     key_index, ent_id, alpm_data);
   2253             if (SOC_URPF_STATUS_GET(u)) {
   2254                 _soc_alpm_raw_parity_set(u, mem, alpm_sip_data);
   2255                 raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_SIP] + raw_id * raw_size;
   2256                 _soc_alpm_raw_mem_write(u, mem, raw_ent,
   2257                                         _soc_alpm_rpf_entry(u, key_index),
   2258                                         ent_id, alpm_sip_data);
   2259             }
   2260         }
   2261         index_array[i] = key_index;
   2262     }
   2263 
   2264     for (i = 0; i < RAW_BKT_NUM; i++) {
   2265         alloc_raw_bkt[i] = raw_bkt[i];
   2266     }
   2267     *alloc_new_index = index_array;
   2268     *alloc_pfx_array = pfx_array;
   2269 
   2270     return rv;
   2271 
   2272 cleanup:
   2273     if (raw_bkt[0]) {
   2274         sal_free(raw_bkt[0]);
   2275     }
   2276     if (index_array) {
   2277         sal_free(index_array);
   2278     }
   2279     if (pfx_array) {
   2280         sal_free(pfx_array);
   2281     }
   2282     return rv;
   2283 }
   2284 
   2285 
   2286 static void
   2287 _soc_alpm_raw_bucket_copy_undo(int u, soc_mem_t mem,
   2288                                int bucket_index,
   2289                                uint32 bank_disable,
   2290                                void *new_raw_bufp, void *new_raw_sip_bufp,
   2291                                int *new_index, int index_count)
   2292 {
   2293     int  i;
   2294     int  raw_size = sizeof(defip_alpm_raw_entry_t);
   2295     int  raw_id = 0;
   2296     int  ent_id = 0;
   2297     void *raw_ent;
   2298     int  v6 = SOC_ALPM_MEM_V6(mem);
   2299 
   2300     /* Restore the new bucket to null */
   2301     for (i = 0; i < index_count; i++) {
   2302         if (new_index[i] < 0) {
   2303             continue;
   2304         }
   2305 
   2306         SOC_ALPM_RAW_INDEX_DECODE(u, v6, new_index[i], raw_id, ent_id);
   2307         raw_ent = (uint8 *)new_raw_bufp + raw_id * raw_size;
   2308         _soc_alpm_raw_mem_write(u, mem, raw_ent,
   2309                                 new_index[i], ent_id, soc_mem_entry_null(u, mem));
   2310         if (SOC_URPF_STATUS_GET(u)) {
   2311             raw_ent = (uint8 *)new_raw_sip_bufp + raw_id * raw_size;
   2312             _soc_alpm_raw_mem_write(u, mem, raw_ent,
   2313                                     _soc_alpm_rpf_entry(u, new_index[i]),
   2314                                     ent_id, soc_mem_entry_null(u, mem));
   2315         }
   2316     }
   2317 
   2318     (void)_soc_alpm_raw_bucket_write(u, mem, bucket_index, bank_disable,
   2319                                      new_raw_bufp, new_raw_sip_bufp, MAX_RAW_COUNT);
   2320 }
   2321 
   2322 /* Populate entries in pfx array to logical bucket */
   2323 static int
   2324 _soc_alpm_raw_bucket_copy(int u, soc_mem_t mem,
   2325                           int       bucket_index,
   2326                           uint32    bank_disable,
   2327                           void      *new_raw_bufp,
   2328                           void      *new_raw_sip_bufp,
   2329                           int       *new_index,
   2330                           int       index_count)
   2331 {
   2332     int                             rv;
   2333     rv = _soc_alpm_raw_bucket_write(u, mem, bucket_index, bank_disable,
   2334                                     new_raw_bufp, new_raw_sip_bufp, MAX_RAW_COUNT);
   2335 
   2336     if (SOC_FAILURE(rv)) {
   2337         /* Delete entries in new bucket */
   2338         _soc_alpm_raw_bucket_copy_undo(u, mem, bucket_index, bank_disable,
   2339                                        new_raw_bufp, new_raw_sip_bufp,
   2340                                        new_index, index_count);
   2341     }
   2342     return rv;
   2343 }
   2344 
   2345 
   2346 
   2347 static INLINE void
   2348 _soc_alpm_raw_bucket_inval_undo(int u, soc_mem_t mem, int bucket_index,
   2349                                 uint32 bank_disable,
   2350                                 void *old_raw_bufp, void *old_raw_sip_bufp)
   2351 {
   2352 
   2353     (void)_soc_alpm_raw_bucket_write(u, mem, bucket_index,
   2354                                      bank_disable, (void *)old_raw_bufp,
   2355                                      (void *)old_raw_sip_bufp, MAX_RAW_COUNT);
   2356     return;
   2357 }
   2358 static int
   2359 _soc_alpm_raw_bucket_inval(int u, soc_mem_t mem, int bucket_index,
   2360                            uint32 bank_disable,
   2361                            void *old_bufp,
   2362                            void *old_sip_bufp,
   2363                            void *rb_bufp,
   2364                            void *rb_sip_bufp)
   2365 {
   2366     int rv = SOC_E_NONE;
   2367 
   2368     /* Invalidation process
   2369      * 1. Erase old copied entries
   2370      * 2. Re-validate those entries if invalidation fails
   2371      */
   2372 
   2373     /* Update old bucket with split entries invalidated */
   2374     rv =  _soc_alpm_raw_bucket_write(u, mem, bucket_index,
   2375                                      bank_disable, old_bufp,
   2376                                      old_sip_bufp, MAX_RAW_COUNT);
   2377     /* re-validate old bucket entries */
   2378     if (SOC_FAILURE(rv)) {
   2379         _soc_alpm_raw_bucket_inval_undo(u, mem, bucket_index,
   2380                                         bank_disable, rb_bufp,
   2381                                         rb_sip_bufp);
   2382     }
   2383 
   2384     return rv;
   2385 }
   2386 
   2387 #else
   2388 
   2389 static void
   2390 _soc_alpm_bucket_prepare_undo(int u,
   2391                               alpm_mem_prefix_array_t **alloc_pfx_array,
   2392                               void **alloc_bufp,
   2393                               void **alloc_sip_bufp,
   2394                               int  **alloc_new_index)
   2395 {
   2396     if (*alloc_pfx_array) {
   2397         sal_free(*alloc_pfx_array);
   2398         *alloc_pfx_array = NULL;
   2399     }
   2400     if (*alloc_bufp) {
   2401         sal_free(*alloc_bufp);
   2402         *alloc_bufp = NULL;
   2403     }
   2404     if (*alloc_sip_bufp) {
   2405         sal_free(*alloc_sip_bufp);
   2406         *alloc_sip_bufp = NULL;
   2407     }
   2408     if (*alloc_new_index) {
   2409         sal_free(*alloc_new_index);
   2410         *alloc_new_index = NULL;
   2411     }
   2412 }
   2413 
   2414 static int
   2415 _soc_alpm_bucket_prepare(int u, soc_mem_t mem,
   2416                          trie_t *bkt_trie,
   2417                          alpm_mem_prefix_array_t **alloc_pfx_array,
   2418                          void **alloc_bufp,
   2419                          void **alloc_sip_bufp,
   2420                          int  **alloc_new_index)
   2421 {
   2422     int i, rv = SOC_E_NONE;
   2423     int entry_size;
   2424     int alloc_size;
   2425     /* allocation pointers all set to NULL */
   2426     void *bufp = NULL, *sip_bufp = NULL;
   2427     int  *index_array = NULL;
   2428     alpm_mem_prefix_array_t *pfx_array = NULL;
   2429 
   2430     *alloc_bufp      = NULL;
   2431     *alloc_sip_bufp  = NULL;
   2432     *alloc_new_index = NULL;
   2433     *alloc_pfx_array = NULL;
   2434 
   2435     /* Alloc prefix array */
   2436     alloc_size = sizeof(alpm_mem_prefix_array_t);
   2437     pfx_array = sal_alloc(alloc_size, "prefix array");
   2438     if (pfx_array == NULL) {
   2439         goto cleanup;
   2440     }
   2441 
   2442     /* Fill prefix array */
   2443     sal_memset(pfx_array, 0, alloc_size);
   2444     rv = trie_traverse(bkt_trie, alpm_mem_prefix_array_cb,
   2445                        pfx_array, _TRIE_INORDER_TRAVERSE);
   2446     if (SOC_FAILURE(rv)) {
   2447         goto cleanup;
   2448     }
   2449 
   2450     /* Alloc index array */
   2451     alloc_size = sizeof(int) * pfx_array->count;
   2452     index_array = sal_alloc(alloc_size, "index_array");
   2453     if (index_array == NULL) {
   2454         goto cleanup;
   2455     }
   2456     sal_memset(index_array, -1, alloc_size);
   2457 
   2458     /* Alloc bufp & sip_bufp */
   2459     entry_size = (L3_DEFIP_ALPM_IPV6_64m == mem ||
   2460                   L3_DEFIP_ALPM_IPV6_64_1m == mem) ?
   2461                   sizeof(defip_alpm_ipv6_64_1_entry_t) :
   2462                   sizeof(defip_alpm_ipv4_1_entry_t);
   2463 
   2464     alloc_size = entry_size * pfx_array->count;
   2465     bufp = sal_alloc(alloc_size, "alloc_bufp");
   2466     if (bufp == NULL) {
   2467         goto cleanup;
   2468     }
   2469     if (SOC_URPF_STATUS_GET(u)) {
   2470         sip_bufp  = sal_alloc(alloc_size, "alloc_sip_bufp");
   2471         if (sip_bufp == NULL) {
   2472             goto cleanup;
   2473         }
   2474     }
   2475 
   2476     /* Fill bufp & sip bufp */
   2477     for (i = 0; i < pfx_array->count; i++) {
   2478         payload_t *pfx = pfx_array->prefix[i];
   2479 
   2480         if (pfx->index > 0) { /* old pfx */
   2481             rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, pfx->index,
   2482                                     (uint8 *)bufp + i * entry_size);
   2483 
   2484             if (SOC_FAILURE(rv)) {
   2485                 break;
   2486             }
   2487 
   2488             if (SOC_URPF_STATUS_GET(u)) {
   2489                 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY,
   2490                         _soc_alpm_rpf_entry(u, pfx->index),
   2491                         (uint8 *)sip_bufp + i * entry_size);
   2492                 if (SOC_FAILURE(rv)) {
   2493                     break;
   2494                 }
   2495             }
   2496         }
   2497     }
   2498     if (SOC_FAILURE(rv)) {
   2499         goto cleanup;
   2500     }
   2501 
   2502     *alloc_bufp      = bufp;
   2503     *alloc_sip_bufp  = sip_bufp;
   2504     *alloc_new_index = index_array;
   2505     *alloc_pfx_array = pfx_array;
   2506 
   2507     return rv;
   2508 
   2509 cleanup:
   2510     if (bufp) {
   2511         sal_free(bufp);
   2512     }
   2513     if (sip_bufp) {
   2514         sal_free(sip_bufp);
   2515     }
   2516     if (index_array) {
   2517         sal_free(index_array);
   2518     }
   2519     if (pfx_array) {
   2520         sal_free(pfx_array);
   2521     }
   2522     return rv;
   2523 }
   2524 
   2525 
   2526 static void
   2527 _soc_alpm_bucket_copy_undo(int u, soc_mem_t mem, int count, int *new_index)
   2528 {
   2529     int i;
   2530 
   2531     for (i = 0; i < count; i++) {
   2532         if (new_index[i] < 0) {
   2533             continue;
   2534         }
   2535         soc_mem_write(u, mem, MEM_BLOCK_ANY, new_index[i],
   2536                       soc_mem_entry_null(u, mem));
   2537         if (SOC_URPF_STATUS_GET(u)) {
   2538             soc_mem_write(u, mem, MEM_BLOCK_ANY,
   2539                           _soc_alpm_rpf_entry(u, new_index[i]),
   2540                           soc_mem_entry_null(u, mem));
   2541         }
   2542     }
   2543 }
   2544 
   2545 /* Populate entries in pfx array to logical bucket */
   2546 static int
   2547 _soc_alpm_bucket_copy(int u, soc_mem_t mem, int vrf,
   2548                       alpm_mem_prefix_array_t *pfx_array,
   2549                       int       bucket_index,
   2550                       void      *old_bufp,
   2551                       void      *old_sip_bufp,
   2552                       void      *new_bufp,
   2553                       void      *new_sip_bufp,
   2554                       int       *new_index,
   2555                       int       *new_index_pos)
   2556 {
   2557     int                             rv;
   2558     void                            *bufp, *sip_bufp;
   2559     int                             entsz, key_index;
   2560     uint32                          bank_disable = 0;
   2561     int                             v6, i;
   2562     uint32                          e[SOC_MAX_MEM_FIELD_WORDS];
   2563     bank_disable = soc_alpm_bank_dis(u, vrf);
   2564 
   2565     v6 = SOC_ALPM_MEM_V6(mem);
   2566 
   2567     entsz = v6 ? sizeof(defip_alpm_ipv6_64_1_entry_t) :
   2568                  sizeof(defip_alpm_ipv4_1_entry_t);
   2569 
   2570     for (i = 0; i < pfx_array->count; i++) {
   2571         if (pfx_array->prefix[i]->index > 0) { /* old prefix */
   2572 
   2573             bufp = (uint8 *)old_bufp + i * entsz;
   2574             if (SOC_URPF_STATUS_GET(u)) {
   2575                 sip_bufp = (uint8 *)old_sip_bufp + i * entsz;
   2576             }
   2577 
   2578             /* entry shouldn't exist, insert the entry into the RAM */
   2579             rv = _soc_alpm_insert_in_bkt(u, mem, bucket_index,
   2580                                          bank_disable, bufp, sip_bufp, e,
   2581                                          &key_index, v6);
   2582         } else { /* for split case only */
   2583             if (!new_bufp || !new_index_pos) {
   2584                 rv = SOC_E_PARAM;
   2585                 goto _rollback;
   2586             }
   2587             *new_index_pos = i;
   2588             rv = _soc_alpm_insert_in_bkt(u, mem, bucket_index,
   2589                                          bank_disable, new_bufp, new_sip_bufp, e,
   2590                                          &key_index, v6);
   2591         }
   2592         if (SOC_FAILURE(rv)) {
   2593             LOG_ERROR(BSL_LS_SOC_ALPM,
   2594                       (BSL_META_U(u,
   2595                                   "Failed to insert prefix "
   2596                                   "0x%08x 0x%08x 0x%08x 0x%08x to bucket %d\n"),
   2597                        pfx_array->prefix[i]->key[1],
   2598                        pfx_array->prefix[i]->key[2],
   2599                        pfx_array->prefix[i]->key[3],
   2600                        pfx_array->prefix[i]->key[4], bucket_index));
   2601 
   2602             goto _rollback;
   2603         }
   2604         new_index[i] = key_index;
   2605     }
   2606 
   2607 _rollback:
   2608     if (SOC_FAILURE(rv)) {
   2609         /* Delete entries in new bucket */
   2610         _soc_alpm_bucket_copy_undo(u, mem, pfx_array->count, new_index);
   2611     }
   2612 
   2613     return rv;
   2614 }
   2615 
   2616 
   2617 
   2618 
   2619 
   2620 static void
   2621 _soc_alpm_bucket_inval_undo(int u, soc_mem_t mem,
   2622                             alpm_mem_prefix_array_t *pfx_array,
   2623                             void *old_bufp, void *old_sip_bufp)
   2624 {
   2625     int i;
   2626     int entry_size = (L3_DEFIP_ALPM_IPV6_64m == mem ||
   2627                       L3_DEFIP_ALPM_IPV6_64_1m == mem) ?
   2628                       sizeof(defip_alpm_ipv6_64_1_entry_t) :
   2629                       sizeof(defip_alpm_ipv4_1_entry_t);
   2630 
   2631     for (i = 0; i < pfx_array->count; i++) {
   2632         payload_t *prefix = pfx_array->prefix[i];
   2633 
   2634         if (prefix->index > 0) {
   2635             soc_mem_write(u, mem, MEM_BLOCK_ALL, prefix->index,
   2636                           (uint8 *)old_bufp + i * entry_size);
   2637 
   2638             if (SOC_URPF_STATUS_GET(u)) {
   2639                 /* UPRF entry */
   2640                 soc_mem_write(u, mem, MEM_BLOCK_ALL,
   2641                               _soc_alpm_rpf_entry(u, prefix->index),
   2642                               (uint8 *)old_sip_bufp + i * entry_size);
   2643             }
   2644         }
   2645     }
   2646     return;
   2647 }
   2648 static int
   2649 _soc_alpm_bucket_inval(int u, soc_mem_t mem,
   2650                        alpm_mem_prefix_array_t *pfx_array,
   2651                        void *old_bufp, void *old_sip_bufp)
   2652 {
   2653     int i, rv = SOC_E_NONE;
   2654 
   2655     /* Invalidation process
   2656      * 1. Erase old copied entries
   2657      * 2. Re-validate those entries if invalidation fails
   2658      */
   2659 
   2660     for (i = 0; i < pfx_array->count; i ++) {
   2661         payload_t *prefix = pfx_array->prefix[i];
   2662 
   2663         if (prefix->index >= 0) {
   2664             /* zero out old entries now that split is done */
   2665             rv = soc_mem_write(u, mem, MEM_BLOCK_ALL, prefix->index,
   2666                                soc_mem_entry_null(u, mem));
   2667             if (SOC_FAILURE(rv)) {
   2668                 break;
   2669             }
   2670             if (SOC_URPF_STATUS_GET(u)) {
   2671                 rv = soc_mem_write(u, mem, MEM_BLOCK_ANY, 
   2672                                    _soc_alpm_rpf_entry(u, prefix->index),
   2673                                    soc_mem_entry_null(u, mem));
   2674                 if (SOC_FAILURE(rv)) {
   2675                     break;
   2676                 }
   2677             }
   2678         }
   2679     }
   2680     /* re-validate old bucket entries */
   2681     if (SOC_FAILURE(rv)) {
   2682         _soc_alpm_bucket_inval_undo(u, mem, pfx_array, old_bufp, old_sip_bufp);
   2683     }
   2684 
   2685     return rv;
   2686 }
   2687 
   2688 
   2689 #endif /* ALPM_USE_RAW_VIEW */
   2690 
   2691 
   2692 
   2693 STATIC int
   2694 _soc_alpm_split_lpm_init(int             u,
   2695                          soc_mem_t       mem,
   2696                          int             vrf,
   2697                          int             bucket_index,
   2698                          void            *alpm_data,
   2699                          void            *alpm_sip_data,
   2700                          uint32          *pivot,
   2701                          int             length,
   2702                          defip_entry_t   *lpm_entry,
   2703                          uint32          *bpm_len,
   2704                          uint32          *src_discard,
   2705                          uint32          *src_default)
   2706 {
   2707     int                             rv = SOC_E_NONE, v6;
   2708     trie_node_t                     *lpm = NULL;
   2709     payload_t                       *bkt_lpm = NULL;
   2710     trie_t                          *pfx_trie;
   2711     uint32                          tmp_pivot[5] = {0};
   2712 
   2713     v6 = SOC_ALPM_MEM_V6(mem);
   2714 
   2715     /* prefix trie */
   2716     if (v6) {
   2717         pfx_trie = VRF_PREFIX_TRIE_IPV6(u, vrf);
   2718     } else {
   2719         pfx_trie = VRF_PREFIX_TRIE_IPV4(u, vrf);
   2720     }
   2721 
   2722 
   2723     /* find longest prefix that covers pivot */
   2724     lpm = NULL;
   2725     rv = trie_find_lpm(pfx_trie, pivot, length, &lpm);
   2726     if (SOC_FAILURE(rv)) {
   2727         LOG_ERROR(BSL_LS_SOC_ALPM,
   2728                   (BSL_META_U(u,
   2729                               "unit %d Unable to find lpm for pivot: "
   2730                               "0x%08x 0x%08x\n 0x%08x 0x%08x 0x%08x length: %d\n"),
   2731                    u, pivot[0], pivot[1], pivot[2], pivot[3], pivot[4],
   2732                    length));
   2733 
   2734         return rv;
   2735     }
   2736     bkt_lpm = ((payload_t *)lpm)->bkt_ptr;
   2737 
   2738     /* Initialize the lpm entry to insert */
   2739     if (bkt_lpm) {
   2740         defip_alpm_ipv4_1_entry_t alpmv4_entry, alpmv4_sip_entry;
   2741         defip_alpm_ipv6_64_1_entry_t alpmv6_entry, alpmv6_sip_entry;
   2742         int             index, vrf_id;
   2743         void            *bufp = NULL, *sip_bufp = NULL;
   2744 
   2745         SOC_ALPM_ENTRY_BUF(v6, mem, bufp, alpmv4_entry, alpmv6_entry);
   2746         SOC_ALPM_ENTRY_BUF(v6, mem, sip_bufp, alpmv4_sip_entry, alpmv6_sip_entry);
   2747 
   2748         /* this means this bucket default route is an actual route */
   2749         /* initialize new pivot's associated data with data of lpm match */
   2750         index = bkt_lpm->index;
   2751         if (index == -1) {
   2752             /* this means the new route is the bucket's default */
   2753             if (alpm_data == NULL || alpm_sip_data == NULL) {
   2754                 return SOC_E_PARAM;
   2755             }
   2756             sal_memcpy(bufp, alpm_data, v6 ?
   2757                        sizeof(defip_alpm_ipv6_64_1_entry_t) :
   2758                        sizeof(defip_alpm_ipv4_1_entry_t));
   2759             if (SOC_URPF_STATUS_GET(u)) {
   2760                 *src_default = soc_mem_field32_get(u, mem, alpm_sip_data,
   2761                                                           DEFAULTROUTEf);
   2762                 *src_discard = soc_mem_field32_get(u, mem, alpm_sip_data,
   2763                                                           SRC_DISCARDf);
   2764             }
   2765         } else {
   2766             rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, index, bufp);
   2767             if (SOC_FAILURE(rv)) {
   2768                 return rv;
   2769             }
   2770             if (SOC_URPF_STATUS_GET(u)) {
   2771                 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY,
   2772                                         _soc_alpm_rpf_entry(u, index),
   2773                                         sip_bufp);
   2774                 *src_default = soc_mem_field32_get(u, mem, sip_bufp,
   2775                                                           DEFAULTROUTEf);
   2776                 *src_discard = soc_mem_field32_get(u, mem, sip_bufp,
   2777                                                           SRC_DISCARDf);
   2778             }
   2779         }
   2780         if (SOC_FAILURE(rv)) {
   2781             return rv;
   2782         }
   2783 
   2784         vrf_id = vrf;
   2785         if (vrf == (SOC_VRF_MAX(u) + 1)) {
   2786             vrf_id = SOC_L3_VRF_GLOBAL;
   2787         }
   2788         rv = _soc_alpm_lpm_ent_init(u, bufp, mem, v6, vrf_id, bucket_index,
   2789                                     0, lpm_entry,
   2790                                     VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 1));
   2791         if (SOC_FAILURE(rv)) {
   2792             return rv;
   2793         }
   2794         /* remember the bpm_len of this pivot. Need to put in shadow */
   2795         *bpm_len = bkt_lpm->len;
   2796     } else {
   2797         defip_entry_t *lpm_key;
   2798 
   2799         lpm_key = v6 ? VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) :
   2800               VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf);
   2801         sal_memcpy(lpm_entry, lpm_key, sizeof(defip_entry_t));
   2802 
   2803         /* the sip ad does not matter here */
   2804         soc_L3_DEFIPm_field32_set(u, lpm_entry, ALG_BKT_PTR0f, bucket_index);
   2805     }
   2806 
   2807     /* Convert is a self-modified op, thus use tmp one */
   2808     sal_memcpy(tmp_pivot, pivot, sizeof(tmp_pivot));
   2809 
   2810     /* Convert from trie format to h/w format */
   2811     ALPM_TRIE_TO_NORMAL_IP(tmp_pivot, length, v6);
   2812     (void) _soc_alpm_lpm_ent_key_init(u, tmp_pivot, length, vrf, v6,
   2813                           lpm_entry, 0);
   2814 
   2815     return rv;
   2816 }
   2817 
   2818 static int
   2819 _soc_alpm_split_pivot_create_undo(int u, int v6, int vrf, uint32 *pivot,
   2820                                   uint32 length, alpm_pivot_t *alpm_pivot,
   2821                                   int clear)
   2822 {
   2823     int                         rv = SOC_E_NONE, pivot_index;
   2824     alpm_bucket_handle_t        *bucket_handle;
   2825     trie_t                      *pivot_trie = NULL;
   2826     trie_node_t                 *delp = NULL;
   2827 
   2828     if (v6) {
   2829         pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf);
   2830     } else {
   2831         pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf);
   2832     }
   2833 
   2834     if (alpm_pivot == NULL) {
   2835         rv = trie_delete(pivot_trie, pivot, length, &delp);
   2836         alpm_pivot = (alpm_pivot_t *) delp;
   2837     }
   2838     if (SOC_SUCCESS(rv)) {
   2839         bucket_handle   = alpm_pivot->bucket;
   2840         pivot_index     = PIVOT_TCAM_INDEX(alpm_pivot);
   2841 
   2842         trie_destroy(PIVOT_BUCKET_TRIE(alpm_pivot));
   2843         sal_free(alpm_pivot);
   2844         sal_free(bucket_handle);
   2845 
   2846         /* For normal destroy (other than rollback) when the entry is deleted
   2847          * from lpm. The pivot_index is already replaced to another index.
   2848          */
   2849         if (clear) {
   2850             ALPM_TCAM_PIVOT(u, pivot_index) = NULL;
   2851         }
   2852     }
   2853 
   2854     return rv;
   2855 }
   2856 static int
   2857 _soc_alpm_split_pivot_create(int u, int v6, int vrf, int bucket_index,
   2858                              trie_node_t     *split_trie_root,
   2859                              uint32          *pivot,
   2860                              uint32          length,
   2861                              uint32          bpm_len,
   2862                              alpm_pivot_t    **new_pivot)
   2863 {
   2864     int                             rv = SOC_E_NONE;
   2865     alpm_pivot_t                    *pivot_pyld;
   2866     alpm_bucket_handle_t            *bucket_handle;
   2867     trie_t                          *pivot_trie = NULL;
   2868     if (v6) {
   2869         pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf);
   2870     } else {
   2871         pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf);
   2872     }
   2873 
   2874     /* Add New Pivot to the pivot trie */
   2875     bucket_handle = sal_alloc(sizeof(alpm_bucket_handle_t),
   2876                              "ALPM Bucket Handle");
   2877     if (bucket_handle == NULL) {
   2878         LOG_ERROR(BSL_LS_SOC_ALPM,
   2879                   (BSL_META_U(u,
   2880                               "Unable to allocate memory "
   2881                               "for PIVOT trie node \n")));
   2882         return SOC_E_MEMORY;
   2883     }
   2884     sal_memset(bucket_handle, 0, sizeof(*bucket_handle));
   2885     pivot_pyld = sal_alloc(sizeof(alpm_pivot_t),
   2886                             "Payload for new Pivot");
   2887     if (pivot_pyld == NULL) {
   2888         LOG_ERROR(BSL_LS_SOC_ALPM,
   2889                   (BSL_META_U(u,
   2890                               "Unable to allocate memory "
   2891                               "for PIVOT trie node \n")));
   2892         sal_free(bucket_handle);
   2893         return SOC_E_MEMORY;
   2894     }
   2895     sal_memset(pivot_pyld, 0, sizeof(*pivot_pyld));
   2896     PIVOT_BUCKET_HANDLE(pivot_pyld) = bucket_handle;
   2897     (void) trie_init(v6 ? _MAX_KEY_LEN_144_ :_MAX_KEY_LEN_48_,
   2898                      &PIVOT_BUCKET_TRIE(pivot_pyld));
   2899     PIVOT_BUCKET_TRIE(pivot_pyld)->trie = split_trie_root;
   2900     PIVOT_BUCKET_INDEX(pivot_pyld) = bucket_index;
   2901     PIVOT_BUCKET_VRF(pivot_pyld) = vrf;
   2902     PIVOT_BUCKET_IPV6(pivot_pyld) = v6;
   2903     PIVOT_BUCKET_DEF(pivot_pyld) = FALSE;
   2904     PIVOT_TCAM_BPMLEN(pivot_pyld)= bpm_len;
   2905 
   2906     (pivot_pyld)->key[0] = pivot[0];
   2907     (pivot_pyld)->key[1] = pivot[1];
   2908     (pivot_pyld)->key[2] = pivot[2];
   2909     (pivot_pyld)->key[3] = pivot[3];
   2910     (pivot_pyld)->key[4] = pivot[4];
   2911     (pivot_pyld)->len    = length;
   2912 
   2913     /* insert into pivot trie */
   2914     rv = trie_insert(pivot_trie, pivot, NULL, length,
   2915                      (trie_node_t *)pivot_pyld);
   2916     if (SOC_SUCCESS(rv)) {
   2917         if (new_pivot) {
   2918             *new_pivot = pivot_pyld;
   2919         }
   2920     } else {
   2921         LOG_ERROR(BSL_LS_SOC_ALPM,
   2922                   (BSL_META_U(u,
   2923                               "failed to insert into pivot trie\n")));
   2924         _soc_alpm_split_pivot_create_undo(u, v6, vrf, pivot,
   2925                                           length, pivot_pyld, 1);
   2926     }
   2927 
   2928     return rv;
   2929 }
   2930 
   2931 static int
   2932 _soc_alpm_bucket_split(int u, alpm_pfx_info_t *pfx_info, int *index_ptr)
   2933 {
   2934     trie_node_t             *split_trie_root;
   2935     uint32                  e[SOC_MAX_MEM_FIELD_WORDS];
   2936     uint32                  length, bpm_len = 0;
   2937     uint32                  bank_disable = 0;
   2938     uint32                  pivot[5] = {0};
   2939     uint32                  src_discard, src_default;
   2940     int                     key_index, i;
   2941     trie_t                  *bkt_trie;
   2942     defip_entry_t           lpm_entry;
   2943     alpm_mem_prefix_array_t *pfx_array = NULL;
   2944     int                     *new_index = NULL;
   2945     int                     rv = SOC_E_NONE, new_index_pos = -1;
   2946     int                     tcam_index, pivot_index;
   2947     alpm_pivot_t            *new_pivot = NULL;
   2948     int         v6 = (L3_DEFIP_ALPM_IPV6_64m == pfx_info->mem ||
   2949                       L3_DEFIP_ALPM_IPV6_64_1m == pfx_info->mem ||
   2950                       L3_DEFIP_ALPM_IPV6_128m == pfx_info->mem);
   2951 #ifdef ALPM_USE_RAW_VIEW
   2952     void                    *raw_bkt[RAW_BKT_NUM] = {0};
   2953 #else
   2954     void                    *bufp = NULL, *sip_bufp = NULL;
   2955 #endif
   2956     enum {
   2957         _SPLIT_TRIE_NONE,
   2958         _SPLIT_TRIE_SPLIT,
   2959         _SPLIT_LPM_INIT,
   2960         _SPLIT_PIVOT_CREATE,
   2961         _SPLIT_PREPARE,
   2962         _SPLIT_COPY,
   2963         _SPLIT_LPM_INSERT,
   2964         _SPLIT_INVALIDATE
   2965     } doing = _SPLIT_TRIE_NONE, done = _SPLIT_TRIE_NONE;
   2966 
   2967     doing = _SPLIT_TRIE_SPLIT;
   2968     bkt_trie = PIVOT_BUCKET_TRIE(ALPM_TCAM_PIVOT(u, pfx_info->pivot_idx_from));
   2969     rv = trie_split(bkt_trie, v6 ? _MAX_KEY_LEN_144_ : _MAX_KEY_LEN_48_, FALSE,
   2970                     pivot, &length, &split_trie_root, NULL, FALSE, 1024);
   2971     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2972 
   2973     doing = _SPLIT_LPM_INIT;
   2974     rv = _soc_alpm_split_lpm_init(u,
   2975                                   pfx_info->mem,
   2976                                   pfx_info->vrf,
   2977                                   pfx_info->log_bkt_to,
   2978                                   pfx_info->alpm_data,
   2979                                   pfx_info->alpm_sip_data,
   2980                                   pivot, length,
   2981                                   &lpm_entry, &bpm_len,
   2982                                   &src_discard, &src_default);
   2983 
   2984     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2985 
   2986     doing = _SPLIT_PIVOT_CREATE;
   2987     rv = _soc_alpm_split_pivot_create(u, v6, pfx_info->vrf, pfx_info->log_bkt_to,
   2988                                       split_trie_root, pivot, length, bpm_len,
   2989                                       &new_pivot);
   2990     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   2991 
   2992     /* Optimized Memory invalidate,
   2993      * Invalidate need to happen only after all the entries are
   2994      * written to the new pivot and the new pivot is valid. Otherwise
   2995      * there is a chance of MISS.
   2996      *
   2997      * hitless move:
   2998      * - Move entries to new bucket.
   2999      * - activate new pivot
   3000      * - delete entries from old bucket
   3001      */
   3002     bank_disable = soc_alpm_bank_dis(u, pfx_info->vrf);
   3003 
   3004     doing = _SPLIT_PREPARE;
   3005 #ifdef ALPM_USE_RAW_VIEW
   3006     rv = _soc_alpm_raw_bucket_prepare(u, pfx_info->mem, PIVOT_BUCKET_TRIE(new_pivot),
   3007                                       pfx_info->log_bkt_from, pfx_info->log_bkt_to,
   3008                                       bank_disable,
   3009                                       pfx_info->alpm_data, pfx_info->alpm_sip_data,
   3010                                       &pfx_array, raw_bkt, &new_index,
   3011                                       &new_index_pos, 0);
   3012 #else
   3013     rv = _soc_alpm_bucket_prepare(u, pfx_info->mem, PIVOT_BUCKET_TRIE(new_pivot),
   3014                                   &pfx_array, &bufp, &sip_bufp, &new_index);
   3015 #endif
   3016     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3017 
   3018     doing = _SPLIT_COPY;
   3019 
   3020 #ifdef ALPM_USE_RAW_VIEW
   3021     rv = _soc_alpm_raw_bucket_copy(u, pfx_info->mem, pfx_info->log_bkt_to,
   3022                                    bank_disable, raw_bkt[RAW_NEW_BKT_DIP],
   3023                                    raw_bkt[RAW_NEW_BKT_SIP],
   3024                                    new_index, pfx_array->count);
   3025 #else
   3026     rv = _soc_alpm_bucket_copy(u, pfx_info->mem, pfx_info->vrf, pfx_array,
   3027                                pfx_info->log_bkt_to,
   3028                                bufp, sip_bufp, pfx_info->alpm_data,
   3029                                pfx_info->alpm_sip_data, new_index, &new_index_pos);
   3030 #endif
   3031     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3032 
   3033     doing = _SPLIT_LPM_INSERT;
   3034     rv = soc_alpm_lpm_insert(u, &lpm_entry, &tcam_index, src_default, src_discard, bpm_len);
   3035     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3036 
   3037     /* TCAM index from lpm code is logical. Convert to physical idx */
   3038     tcam_index = soc_alpm_physical_idx(u, L3_DEFIPm,  tcam_index, v6);
   3039     pivot_index = tcam_index << (v6 ? 1 : 0);
   3040     PIVOT_TCAM_INDEX(new_pivot)         = pivot_index;
   3041     ALPM_TCAM_PIVOT(u, pivot_index)     = new_pivot;
   3042 
   3043     doing = _SPLIT_INVALIDATE;
   3044 #ifdef ALPM_USE_RAW_VIEW
   3045     rv = _soc_alpm_raw_bucket_inval(u, pfx_info->mem, pfx_info->log_bkt_from,
   3046                                     bank_disable,
   3047                                     raw_bkt[RAW_OLD_BKT_DIP],
   3048                                     raw_bkt[RAW_OLD_BKT_SIP],
   3049                                     raw_bkt[RAW_RB_BKT_DIP],
   3050                                     raw_bkt[RAW_RB_BKT_SIP]);
   3051 #else
   3052     rv = _soc_alpm_bucket_inval(u, pfx_info->mem, pfx_array, bufp, sip_bufp);
   3053 #endif
   3054     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3055 
   3056     if (new_index_pos != -1) { /* New prefix goes to new split bucket */
   3057         *index_ptr = new_index[new_index_pos];
   3058     } else { /* To old parent bucket, do actual insert */
   3059         /* Add Entry to old bucket RAM */
   3060         rv = _soc_alpm_insert_in_bkt(u, pfx_info->mem, pfx_info->log_bkt_from, /* this should be from old pivot*/
   3061                                      bank_disable, pfx_info->alpm_data, pfx_info->alpm_sip_data,
   3062                                      e, &key_index, v6);
   3063 
   3064         if (SOC_FAILURE(rv)) {
   3065             /* recover by matching trie state to h/w state */
   3066             LOG_ERROR(BSL_LS_SOC_ALPM,
   3067                       (BSL_META_U(u, "Could not insert new "
   3068                                   "prefix into trie after split\n")));
   3069             /* since split was successful, leave split state as-is */
   3070             pfx_info->log_bkt_to = -1;
   3071             return rv;
   3072         }
   3073 
   3074         *index_ptr = key_index;
   3075     }
   3076 
   3077     PIVOT_BUCKET_ENT_CNT_UPDATE(new_pivot);
   3078     VRF_BUCKET_SPLIT_INC(u, pfx_info->vrf, v6);
   3079 
   3080     /* Update new index */
   3081     for (i = 0; i < pfx_array->count; i++) {
   3082         pfx_array->prefix[i]->index = new_index[i];
   3083     }
   3084 #ifdef ALPM_USE_RAW_VIEW
   3085     _soc_alpm_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index);
   3086 #else
   3087     _soc_alpm_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index);
   3088 #endif
   3089 
   3090     return rv;
   3091 
   3092 _rollback:
   3093     /* fall through on all cases */
   3094     switch (done)  {
   3095     case _SPLIT_LPM_INSERT:
   3096         soc_alpm_lpm_delete(u, &lpm_entry);
   3097 
   3098     case _SPLIT_COPY:
   3099         /* Delete entries in new bucket */
   3100 #ifdef ALPM_USE_RAW_VIEW
   3101         _soc_alpm_raw_bucket_copy_undo(u, pfx_info->mem, pfx_info->log_bkt_to, bank_disable,
   3102                                        raw_bkt[RAW_NEW_BKT_DIP],
   3103                                        raw_bkt[RAW_NEW_BKT_SIP], new_index, pfx_array->count);
   3104 #else
   3105         _soc_alpm_bucket_copy_undo(u, pfx_info->mem, pfx_array->count, new_index);
   3106 #endif
   3107 
   3108     case _SPLIT_PREPARE:
   3109 #ifdef ALPM_USE_RAW_VIEW
   3110         _soc_alpm_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index);
   3111 #else
   3112         _soc_alpm_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index);
   3113 #endif
   3114 
   3115     case _SPLIT_PIVOT_CREATE:
   3116         _soc_alpm_split_pivot_create_undo(u, v6, pfx_info->vrf, pivot, length, NULL, 0);
   3117 
   3118     case _SPLIT_LPM_INIT:
   3119         /* nothing to undo */
   3120 
   3121     case _SPLIT_TRIE_SPLIT:
   3122         trie_merge(bkt_trie, split_trie_root, pivot, length);
   3123 
   3124     case _SPLIT_TRIE_NONE:
   3125     default:
   3126         /* nothing to rollback for first step */
   3127         break;
   3128     }
   3129 
   3130     switch (doing) {
   3131     case _SPLIT_TRIE_SPLIT:
   3132         LOG_ERROR(BSL_LS_SOC_ALPM,
   3133                   (BSL_META_U(u,
   3134                               "Could not split bucket")));
   3135         break;
   3136 
   3137     case _SPLIT_PIVOT_CREATE:
   3138         LOG_ERROR(BSL_LS_SOC_ALPM,
   3139                   (BSL_META_U(u, "failed to insert into pivot bkt_trie\n")));
   3140         break;
   3141 
   3142     case _SPLIT_LPM_INSERT:
   3143         LOG_ERROR(BSL_LS_SOC_ALPM,
   3144                   (BSL_META_U(u,
   3145                               "Unable to add new pivot to tcam\n")));
   3146 
   3147         if (rv == SOC_E_FULL) {
   3148             VRF_PIVOT_FULL_INC(u, pfx_info->vrf, v6);
   3149         }
   3150         break;
   3151     default:
   3152         LOG_ERROR(BSL_LS_SOC_ALPM,
   3153                   (BSL_META_U(u,
   3154                               "Split fails at step %d\n"), doing));
   3155         break;
   3156     }
   3157 
   3158     return rv;
   3159 }
   3160 
   3161 
   3162 /*
   3163  * Insert entry into ALPM database.
   3164  * Returns SOC_E_NONE, if found and updated.
   3165  * SOC_E_FAIL, if insert failed.
   3166  */
   3167 static int
   3168 _soc_alpm_insert(int u,
   3169                  int v6,
   3170                  void *key_data,  /* TCAM entry data */
   3171                  soc_mem_t mem,   /* Mem view for ALPM data */
   3172                  void *alpm_data, /* Alpm data to be updated with */
   3173                  void *alpm_sip_data,
   3174                  int *index_ptr,
   3175                  int bucket_index,
   3176                  int tcam_index)
   3177 {
   3178     alpm_pivot_t *old_pivot;
   3179     defip_aux_scratch_entry_t aux_entry;
   3180     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   3181     uint32      prefix[5], length;
   3182     int         vrf, vrf_id;
   3183     int         key_index;
   3184     int         rv = SOC_E_NONE;
   3185     uint32      db_type, ent_type, bank_disable;
   3186     int         hit =0;
   3187     int         split = 0;
   3188     trie_t      *bkt_trie = NULL , *pfx_trie = NULL;
   3189     trie_node_t *lpmp = NULL, *lpmp2 = NULL;
   3190     payload_t   *bkt_payload = NULL, *pfx_payload = NULL, *tmp_pyld;
   3191     int         default_route = 0;
   3192     /* Search Result buffers */
   3193     alpm_pfx_info_t pfx_info;
   3194     int         new_bucket_index = -1;
   3195     int         bkt_trie_inserted = 0, pfx_trie_inserted = 0;
   3196     int         shuffled = 0;
   3197     int         aux_flags = 0;
   3198 
   3199     SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   3200     bank_disable = soc_alpm_bank_dis(u, vrf);
   3201     soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
   3202 
   3203     /* Get table memory. */
   3204     SOC_ALPM_TABLE_MEM(u, v6, mem, VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 1));
   3205 
   3206     /* Insert the prefix into the bucket trie, whether the insert was
   3207      * successul or resulted in Split. Spliting the trie after insertion
   3208      * yeilds better pivot and better split.
   3209      */
   3210     /* Create Prefix */
   3211     rv = _alpm_prefix_create(u, key_data, prefix, &length, &default_route);
   3212     if (SOC_FAILURE(rv)) {
   3213         LOG_ERROR(BSL_LS_SOC_ALPM,
   3214                   (BSL_META_U(u,
   3215                               "_soc_alpm_insert: prefix create failed\n")));
   3216         return rv;
   3217     }
   3218 
   3219     /* Fill in AUX Scratch and perform PREFIX Operation */
   3220     sal_memset(&aux_entry, 0, sizeof(defip_aux_scratch_entry_t));
   3221     SOC_IF_ERROR_RETURN(
   3222        _soc_alpm_fill_aux_entry_for_op(u, key_data, v6, db_type, ent_type, 0,
   3223                                        &aux_entry));
   3224 
   3225     if (bucket_index == 0) {
   3226         if (SOC_ALPM_SW_LOOKUP(u)) {
   3227             rv = _soc_alpm_sw_pivot_find(u, prefix, length, v6, vrf, &hit,
   3228                                          &tcam_index, &bucket_index);
   3229             SOC_IF_ERROR_RETURN(rv);
   3230         } else {
   3231             /* no cookie provided */
   3232             SOC_IF_ERROR_RETURN(_soc_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry,
   3233                                 TRUE, &hit, &tcam_index, &bucket_index, 0));
   3234         }
   3235 
   3236         if (hit == 0) {
   3237             LOG_ERROR(BSL_LS_SOC_ALPM,
   3238                       (BSL_META_U(u,
   3239                                   "_soc_alpm_insert: "
   3240                                   "Could not find bucket to insert prefix\n")));
   3241             return SOC_E_NOT_FOUND;
   3242         }
   3243     }
   3244     bucket_index &= ~SOC_ALPM_V6_SCALE_CHECK(u, v6);
   3245 
   3246     /* entry shouldn't exist, insert the entry into the RAM */
   3247     rv = _soc_alpm_insert_in_bkt(u, mem, bucket_index,
   3248                                  bank_disable, alpm_data, alpm_sip_data,
   3249                                  e, &key_index, v6);
   3250 
   3251     if (rv == SOC_E_NONE)  {
   3252         *index_ptr = key_index;
   3253     } else if (rv == SOC_E_FULL) {
   3254         /* The wish count is a matter of choice, but it must be bigger than
   3255          * old_count to yeild a better result: find a new home as much
   3256          * as possible to avoid split.
   3257          * The sense behind this is splitting will result in repartition,
   3258          * which is more costly.
   3259          */
   3260         rv = soc_alpm_assign(u, vrf, mem, &new_bucket_index, &shuffled);
   3261         SOC_IF_ERROR_RETURN(rv);
   3262         if (shuffled) {
   3263             if (SOC_ALPM_SW_LOOKUP(u)) {
   3264                 rv = _soc_alpm_sw_pivot_find(u, prefix, length, v6, vrf, &hit,
   3265                                              &tcam_index, &bucket_index);
   3266             } else {
   3267                 rv = _soc_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry, TRUE, &hit,
   3268                                       &tcam_index, &bucket_index, 0);
   3269             }
   3270             SOC_IF_ERROR_RETURN(rv);
   3271         }
   3272 
   3273         split = 1;
   3274         /* this indicates a new route, which will be used to decide
   3275          * if the new route happens to be new pivot.
   3276          */
   3277         key_index = -1;
   3278     } else {
   3279         return rv;
   3280     }
   3281 
   3282     old_pivot = ALPM_TCAM_PIVOT(u, tcam_index);
   3283     if (old_pivot == NULL) {
   3284         LOG_ERROR(BSL_LS_SOC_ALPM,
   3285                   (BSL_META_U(u, "ins: pivot index %d bkt %d is not valid \n"),
   3286                   tcam_index, bucket_index));
   3287         return SOC_E_PARAM;
   3288     }
   3289 
   3290     /* Allocate Payload */
   3291     bkt_payload = sal_alloc(sizeof(payload_t), "Payload for Key");
   3292     if (bkt_payload == NULL) {
   3293         LOG_ERROR(BSL_LS_SOC_ALPM,
   3294                   (BSL_META_U(u,
   3295                               "Unable to allocate memory for "
   3296                               "bkt_payload entry\n")));
   3297         rv = SOC_E_MEMORY;
   3298         goto _rollback;
   3299     }
   3300 
   3301     pfx_payload = sal_alloc(sizeof(payload_t), "Payload for pfx trie key");
   3302     if (pfx_payload == NULL) {
   3303         LOG_ERROR(BSL_LS_SOC_ALPM,
   3304                   (BSL_META_U(u,
   3305                               "Unable to allocate memory for "
   3306                               "pfx trie node\n")));
   3307         rv = SOC_E_MEMORY;
   3308         goto _rollback;
   3309     }
   3310     sal_memset(bkt_payload, 0, sizeof(*bkt_payload));
   3311     sal_memset(pfx_payload, 0, sizeof(*pfx_payload));
   3312     sal_memcpy(bkt_payload->key, prefix, sizeof(prefix));
   3313     bkt_payload->len    = length;
   3314     /* Needs update for split case, updated below */
   3315     bkt_payload->index  = key_index;
   3316     /* create duplicate for prefix bkt_trie */
   3317     sal_memcpy(pfx_payload, bkt_payload, sizeof(*bkt_payload));
   3318     pfx_payload->bkt_ptr = bkt_payload;
   3319 
   3320     /* Insert the prefix */
   3321     /* bucket trie insert */
   3322     bkt_trie = PIVOT_BUCKET_TRIE(old_pivot);
   3323     rv = trie_insert(bkt_trie, prefix, NULL, length, (trie_node_t *)bkt_payload);
   3324     if (SOC_SUCCESS(rv)) {
   3325         bkt_trie_inserted = 1;
   3326     } else {
   3327         goto _rollback;
   3328     }
   3329 
   3330     /* prefix trie insert */
   3331     if (v6) {
   3332         pfx_trie = VRF_PREFIX_TRIE_IPV6(u, vrf);
   3333     } else {
   3334         pfx_trie = VRF_PREFIX_TRIE_IPV4(u, vrf);
   3335     }
   3336     if (!default_route) {
   3337         /* default route already in trie */
   3338         rv = trie_insert(pfx_trie, prefix, NULL, length,
   3339                         (trie_node_t *)pfx_payload);
   3340         if (SOC_SUCCESS(rv)) {
   3341             pfx_trie_inserted = 1;
   3342         }
   3343     } else {
   3344         /* update the default route */
   3345         lpmp = NULL;
   3346         rv = trie_find_lpm(pfx_trie, 0, 0, &lpmp);
   3347         tmp_pyld = (payload_t *) lpmp;
   3348         if (SOC_SUCCESS(rv)) {
   3349             tmp_pyld->bkt_ptr = bkt_payload;
   3350         }
   3351     }
   3352     if (SOC_FAILURE(rv)) {
   3353         goto _rollback;
   3354     }
   3355 
   3356     /* Performs lazy splitting */
   3357     if (split) { /* Split */
   3358         sal_memset(&pfx_info, 0, sizeof(pfx_info));
   3359         pfx_info.pivot_idx_from   = tcam_index;
   3360         pfx_info.alpm_data        = alpm_data;
   3361         pfx_info.alpm_sip_data    = alpm_sip_data;
   3362         pfx_info.log_bkt_from     = bucket_index;
   3363         pfx_info.log_bkt_to       = new_bucket_index;
   3364         pfx_info.vrf              = vrf;
   3365         pfx_info.mem              = mem;
   3366         rv = _soc_alpm_bucket_split(u, &pfx_info, index_ptr);
   3367         if (rv != SOC_E_NONE) {
   3368             new_bucket_index = pfx_info.log_bkt_to;
   3369             goto _rollback;
   3370         }
   3371         bkt_payload->index  = *index_ptr;
   3372         /* New Pivot */
   3373         soc_alpm_dbg_cnt[u].bkt_split++;
   3374     }
   3375 
   3376     /* from here on, we don't expect any failure */
   3377 
   3378     /* propagate the insertion */
   3379     if (default_route) {
   3380         /* also free unused pfx_payload pointer */
   3381         sal_free(pfx_payload);
   3382     }
   3383 
   3384     if (SOC_URPF_STATUS_GET(u)) {
   3385         if (soc_mem_field32_get(u, mem, alpm_sip_data, DEFAULTROUTEf)) {
   3386             aux_flags |= SOC_ALPM_AUX_DEF_ROUTE;
   3387         }
   3388         if (soc_mem_field32_get(u, mem, alpm_sip_data, SRC_DISCARDf)) {
   3389             aux_flags |= SOC_ALPM_AUX_SRC_DISCARD;
   3390         }
   3391     }
   3392 
   3393     SOC_IF_ERROR_RETURN(_soc_alpm_aux_op(u, INSERT_PROPAGATE, &aux_entry,
   3394                         TRUE, &hit, &tcam_index, &bucket_index, aux_flags));
   3395 
   3396     /* For debug, update the old pivot's counter */
   3397     PIVOT_BUCKET_ENT_CNT_UPDATE(old_pivot);
   3398     return rv;
   3399 
   3400 _rollback:
   3401     if (!default_route && pfx_trie_inserted) {
   3402         (void)trie_delete(pfx_trie, prefix, length, &lpmp);
   3403     }
   3404 
   3405     if (bkt_trie_inserted) {
   3406         (void)trie_delete(bkt_trie, prefix, length, &lpmp2);
   3407     }
   3408 
   3409     if (pfx_payload) {
   3410         sal_free(pfx_payload);
   3411     }
   3412 
   3413     if (bkt_payload) {
   3414         sal_free(bkt_payload);
   3415     }
   3416 
   3417     if (split && new_bucket_index != -1) {
   3418         /* for non-split case, the new logical bucket is taking effect and thus
   3419          * should not be released
   3420          */
   3421          (void)alpm_bucket_release(u, new_bucket_index, v6);
   3422     }
   3423     return rv;
   3424 }
   3425 
   3426 
   3427 
   3428 /* Build an LPM entry, from a key */
   3429 /* Mostly used for the match */
   3430 static int
   3431 _soc_alpm_lpm_ent_key_init(int unit, uint32 *key, int len, int vrf, int ipv6,
   3432                            defip_entry_t *lpm_entry, int init)
   3433 {
   3434     uint32 mask;
   3435 
   3436     /* Zero buffers. */
   3437     if (init) {
   3438         sal_memset(lpm_entry, 0, sizeof(defip_entry_t));
   3439     }
   3440 
   3441     /* and with mask to ensure global vrf gets set to 0 */
   3442     SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, VRF_ID_0f,
   3443                               vrf & SOC_VRF_MAX(unit));
   3444     if (vrf == (SOC_VRF_MAX(unit) + 1)) {
   3445         /* for global routes */
   3446         SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f, 0);
   3447     } else {
   3448         SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f,
   3449                               SOC_VRF_MAX(unit));
   3450     }
   3451 
   3452     if (ipv6) {
   3453         /* Set address to the buffer. */
   3454         SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, IP_ADDR0f, key[0]);
   3455 
   3456         /* Set address to the buffer. */
   3457         SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, IP_ADDR1f, key[1]);
   3458         /* Set mode to ipv6 */
   3459         SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, MODE0f, 1);
   3460         SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, MODE1f, 1);
   3461 
   3462         /* Set Virtual Router id */
   3463         SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, VRF_ID_1f, vrf &
   3464                                   SOC_VRF_MAX(unit));
   3465         if (vrf == (SOC_VRF_MAX(unit) + 1)) {
   3466             /* for global routes */
   3467             SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK1f, 0);
   3468         } else {
   3469             SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK1f,
   3470                                   SOC_VRF_MAX(unit));
   3471         }
   3472         SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, VALID1f, 1);
   3473 
   3474         if (len >= 32) {
   3475             mask = 0xffffffff;
   3476             SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, mask);
   3477             mask = ~SHR_SHIFT_RIGHT(0xffffffff, len - 32);
   3478             SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, mask);
   3479         } else {
   3480             mask = ~(0xffffffff >> len);
   3481             SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, mask);
   3482             /* make sure lower word of mask is 0 */
   3483             SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, 0);
   3484         }
   3485     } else {
   3486         SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, IP_ADDR0f, key[0]);
   3487 
   3488         /* Set address to the buffer. */
   3489         assert(len <= 32);
   3490         mask = (len == 32) ? 0xffffffff : ~(0xffffffff >> len);
   3491         SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, mask);
   3492     }
   3493     SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, VALID0f, 1);
   3494 
   3495     /* Set Mode Masks */
   3496     SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, MODE_MASK0f,
   3497                         (1 << soc_mem_field_length(unit, L3_DEFIPm, MODE_MASK0f)) - 1);
   3498     SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, MODE_MASK1f,
   3499                         (1 << soc_mem_field_length(unit, L3_DEFIPm, MODE_MASK1f)) - 1);
   3500 
   3501     /* Set Entry Type Masks */
   3502     SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, ENTRY_TYPE_MASK0f,
   3503                         (1 << soc_mem_field_length(unit, L3_DEFIPm,
   3504                          ENTRY_TYPE_MASK0f)) - 1);
   3505     SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, ENTRY_TYPE_MASK1f,
   3506                         (1 << soc_mem_field_length(unit, L3_DEFIPm,
   3507                          ENTRY_TYPE_MASK1f)) - 1);
   3508     /*
   3509      * Note ipv4 entries are expected to reside in part 0 of the entry.
   3510      *      ipv6 entries both parts should be filled.
   3511      *      Hence if entry is ipv6 copy part 0 to part 1
   3512      */
   3513     return (SOC_E_NONE);
   3514 }
   3515 
   3516 
   3517 int
   3518 _soc_alpm_delete_in_bkt(int u, soc_mem_t mem, int delete_bucket,
   3519                         int bank_disable, void *bufp2, uint32 *e,
   3520                         int *key_index, int v6)
   3521 {
   3522     int rv;
   3523 
   3524     rv = soc_mem_alpm_delete(u, mem, delete_bucket, MEM_BLOCK_ALL,
   3525                              bank_disable, bufp2, e, key_index);
   3526     if (SOC_SUCCESS(rv)) {
   3527         return rv;
   3528     }
   3529     if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) {
   3530         return soc_mem_alpm_delete(u, mem, delete_bucket + 1, MEM_BLOCK_ALL,
   3531                                 bank_disable, bufp2, e, key_index);
   3532     }
   3533     return rv;
   3534 }
   3535 
   3536 
   3537 #ifdef CHECK_CLEAN_BKT
   3538 static int
   3539 _soc_alpm_bkt_count(int u, soc_mem_t mem, int bkt_idx, int v6, void *bufp)
   3540 {
   3541     int bank, entry;
   3542     int addr, rv;
   3543     int count = 0;
   3544 
   3545     for (bank = 0; bank < 4; bank++) {
   3546       for (entry = 0; entry < (v6 ? 4 : 6); entry++) {
   3547         addr = (entry << 16) | (bkt_idx << 2) | (bank & 3);
   3548         rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, addr, bufp);
   3549         SOC_IF_ERROR_RETURN(rv);
   3550         if (soc_mem_field32_get(u, mem, bufp, VALIDf)) {
   3551             count++;
   3552         }
   3553       }
   3554     }
   3555     return count;
   3556 }
   3557 #endif /* CHECK_CLEAN_BKT */
   3558 
   3559 /*
   3560  * Delete entry from ALPM database.
   3561  * Returns SOC_E_NONE, if found and updated.
   3562  * SOC_E_FAIL, if insert failed.
   3563  * If default route replace with internal default
   3564  */
   3565 static int
   3566 _soc_alpm_delete(int u, void *key_data, int bucket_index,
   3567                  int tcam_index, int key_index, int propagate)  /* TCAM entry data */
   3568 {
   3569     alpm_pivot_t *pivot_pyld;
   3570     /* Search Result buffer */
   3571     defip_alpm_ipv4_1_entry_t alpmv4_entry, alpmv4_sip_entry, alpmv42;
   3572     defip_alpm_ipv6_64_1_entry_t alpmv6_entry, alpmv6_sip_entry, alpmv62;
   3573     defip_aux_scratch_entry_t aux_entry;
   3574     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   3575     soc_mem_t mem;
   3576     void      *bufp, *bufp2, *sip_bufp = NULL;
   3577     int       vrf_id;
   3578     int       ipv6;
   3579     int       rv = SOC_E_NONE, rv2;
   3580     uint32    prop_pfx[5], prefix[5];
   3581     int       v6, vrf;
   3582     uint32    length;
   3583     int       delete_bucket;
   3584     uint32    db_type, ent_type, bank_disable;
   3585     int       hit, default_route = 0;
   3586     trie_t    *trie, *pfx_trie;
   3587     uint32    bpm_pfx_len;
   3588     defip_entry_t lpm_entry, *lpm_key;
   3589     payload_t *payload = NULL, *pfx_pyld = NULL, *tmp_pyld = NULL;
   3590     trie_node_t *delp = NULL, *lpmp = NULL;
   3591     trie_t    *pivot_trie = NULL;
   3592     int       aux_flags = 0;
   3593 
   3594     ipv6 = v6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0f);
   3595     if (v6) {
   3596         if (!(v6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE1f))) {
   3597             return (SOC_E_PARAM);
   3598         }
   3599     }
   3600 
   3601     SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   3602 
   3603     /* For VRF_OVERRIDE (Global High) entries, software needs to maintain the
   3604      * index, Prefix resides in TCAM directly. Handling of these functions are
   3605      * taken care by main insert */
   3606     soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
   3607     if (vrf_id != SOC_L3_VRF_OVERRIDE) {
   3608         bank_disable = soc_alpm_bank_dis(u, vrf);
   3609 
   3610         /* Create Prefix */
   3611         rv = _alpm_prefix_create(u, key_data, prefix, &length, &default_route);
   3612 
   3613         if (SOC_FAILURE(rv)) {
   3614             LOG_ERROR(BSL_LS_SOC_ALPM,
   3615                       (BSL_META_U(u,
   3616                                   "_soc_alpm_delete: prefix create failed\n")));
   3617             return rv;
   3618         }
   3619         if (!soc_alpm_mode_get(u)) {
   3620             if (vrf_id != SOC_L3_VRF_GLOBAL) {
   3621                 /* allow default deletion only at end */
   3622                 if (VRF_TRIE_ROUTES_CNT(u, vrf_id, vrf, v6) > 1) {
   3623                     if (default_route) {
   3624                         LOG_ERROR(BSL_LS_SOC_ALPM,
   3625                                   (BSL_META_U(u,
   3626                                               "VRF %d: Cannot delete default "
   3627                                               "route if other routes are present in "
   3628                                               "this mode"), vrf));
   3629                         return SOC_E_PARAM;
   3630                     }
   3631                 }
   3632             }
   3633         }
   3634 
   3635         /* Get table memory. */
   3636         SOC_ALPM_TABLE_MEM(u, v6, mem, VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 0));
   3637 
   3638         /* Assign entry buf based on table being used */
   3639         SOC_ALPM_ENTRY_BUF(v6, mem, bufp, alpmv4_entry, alpmv6_entry);
   3640         SOC_ALPM_ENTRY_BUF(v6, mem, bufp2, alpmv42, alpmv62);
   3641 
   3642         SOC_ALPM_LPM_LOCK(u);
   3643 
   3644         if (bucket_index == 0) {
   3645             /* Search the entry */
   3646             rv = _soc_alpm_find(u, key_data, mem, bufp, &tcam_index,
   3647                                 &bucket_index, &key_index,
   3648                                 SOC_ALPM_SW_LOOKUP(u));
   3649         } else {
   3650             /* key_data has all the info including search result */
   3651             rv = _soc_alpm_mem_ent_init(u, key_data, bufp, 0, mem, 0, 0);
   3652         }
   3653 
   3654         /* save results as they are lost later */
   3655         sal_memcpy(bufp2, bufp, v6 ? sizeof(alpmv6_entry) :
   3656                    sizeof(alpmv4_entry));
   3657 
   3658         if (SOC_FAILURE(rv)) {
   3659             SOC_ALPM_LPM_UNLOCK(u);
   3660             LOG_ERROR(BSL_LS_SOC_ALPM,
   3661                       (BSL_META_U(u,
   3662                                   "_soc_alpm_delete: Unable to find prefix for delete\n")));
   3663             return rv;
   3664         }
   3665 
   3666         /* Entry found
   3667          * 1> Delete entry from trie
   3668          * 2> Find Best Prefix Match
   3669          * 3> Update bpm using replacement prefix op
   3670          * 4> Invalidate Entry in the ALPM database
   3671          */
   3672         /* Delete the prefix from trie*/
   3673         /* Store index to invalidate the prefix */
   3674         delete_bucket = bucket_index & ~SOC_ALPM_V6_SCALE_CHECK(u, ipv6);
   3675 
   3676         pivot_pyld = ALPM_TCAM_PIVOT(u, tcam_index);
   3677         if (pivot_pyld == NULL) {
   3678             LOG_ERROR(BSL_LS_SOC_ALPM,
   3679                       (BSL_META_U(u, "del: pivot index %d bkt %d is not valid \n"),
   3680                       tcam_index, bucket_index));
   3681             SOC_ALPM_LPM_UNLOCK(u);
   3682             return SOC_E_PARAM;
   3683         }
   3684 
   3685         trie = PIVOT_BUCKET_TRIE(pivot_pyld);
   3686 
   3687         rv = trie_delete(trie, prefix, length,  &delp);
   3688         payload = (payload_t *) delp;
   3689         if (rv != SOC_E_NONE) {
   3690             LOG_ERROR(BSL_LS_SOC_ALPM,
   3691                       (BSL_META_U(u,
   3692                                   "_soc_alpm_delete: Error prefix not present in trie \n")));
   3693             SOC_ALPM_LPM_UNLOCK(u);
   3694             return rv;
   3695         }
   3696 
   3697         /* prefix trie delete */
   3698         if (v6) {
   3699             pfx_trie = VRF_PREFIX_TRIE_IPV6(u, vrf);
   3700         } else {
   3701             pfx_trie = VRF_PREFIX_TRIE_IPV4(u, vrf);
   3702         }
   3703 
   3704         if (v6) {
   3705             pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf);
   3706         } else {
   3707             pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf);
   3708         }
   3709 
   3710         if (!default_route) {
   3711             rv = trie_delete(pfx_trie, prefix, length, &delp);
   3712             pfx_pyld = (payload_t *) delp;
   3713 
   3714             if (SOC_FAILURE(rv)) {
   3715                 /* continue anyway to minimize state mismatch */
   3716                 LOG_ERROR(BSL_LS_SOC_ALPM,
   3717                           (BSL_META_U(u,
   3718                                       "_soc_alpm_delete: Prefix not present in pfx"
   3719                                       "trie: 0x%08x 0x%08x\n"),
   3720                            prefix[0], prefix[1]));
   3721                 goto recover_bkt_trie;
   3722             }
   3723 
   3724             if (propagate) {
   3725                 /* Find Best prefix match for the prefix */
   3726                 lpmp = NULL;
   3727                 rv = trie_find_lpm(pfx_trie, prefix, length, &lpmp);
   3728                 tmp_pyld = (payload_t *) lpmp;
   3729                 if (SOC_SUCCESS(rv)) {
   3730                     payload_t *t = (payload_t *)(tmp_pyld->bkt_ptr);
   3731                     if (t != NULL) {
   3732                         /* this means a real default route exists */
   3733                         bpm_pfx_len = t->len;
   3734                     } else {
   3735                         /* only internal default route exists */
   3736                         /* this should happen only if the lpm is a default route */
   3737                         bpm_pfx_len = 0;
   3738                     }
   3739                 } else {
   3740                     LOG_ERROR(BSL_LS_SOC_ALPM,
   3741                               (BSL_META_U(u,
   3742                                           "_soc_alpm_delete: Could not find replacement"
   3743                                           "bpm for prefix: 0x%08x 0x%08x\n"),
   3744                                prefix[0], prefix[1]));
   3745                     goto recover_pfx_trie;
   3746                 }
   3747 
   3748                 /* Initialize an lpm enty to perform a match */
   3749                 /* not expected to fail */
   3750 
   3751 
   3752                 sal_memcpy(prop_pfx, prefix, sizeof(prefix));
   3753                 ALPM_TRIE_TO_NORMAL_IP(prop_pfx, length, v6);
   3754                 (void) _soc_alpm_lpm_ent_key_init(u, prop_pfx, bpm_pfx_len, vrf, ipv6,
   3755                                         &lpm_entry, 1);
   3756 
   3757                 /* Find Associated data for the bpm */
   3758                 rv = _soc_alpm_find(u, &lpm_entry, mem, bufp, &tcam_index,
   3759                                      &bucket_index, &key_index,
   3760                                      SOC_ALPM_SW_LOOKUP(u));
   3761                 if (SOC_SUCCESS(rv)) {
   3762                     /* convert associated data to lpm entry format */
   3763                     (void) _soc_alpm_lpm_ent_init(u, bufp, mem, ipv6, vrf_id,
   3764                                                 bucket_index, 0, &lpm_entry, 0);
   3765 
   3766                     /* set key to the prefix being deleted */
   3767                     (void) _soc_alpm_lpm_ent_key_init(u, prop_pfx, length, vrf, ipv6,
   3768                                            &lpm_entry, 0);
   3769 
   3770                     if (SOC_URPF_STATUS_GET(u)) {
   3771                         SOC_ALPM_ENTRY_BUF(v6, mem, sip_bufp, alpmv4_sip_entry,
   3772                                            alpmv6_sip_entry);
   3773                         rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY,
   3774                                  _soc_alpm_rpf_entry(u, key_index), sip_bufp);
   3775 
   3776                         if (soc_mem_field32_get(u, mem, sip_bufp, DEFAULTROUTEf)) {
   3777                             aux_flags |= SOC_ALPM_AUX_DEF_ROUTE;
   3778                         }
   3779                         if (soc_mem_field32_get(u, mem, sip_bufp, SRC_DISCARDf)) {
   3780                             aux_flags |= SOC_ALPM_AUX_SRC_DISCARD;
   3781                         }
   3782                     }
   3783 
   3784                 } else if (bpm_pfx_len == 0) {
   3785                     /* could not find a default route. Use internal default */
   3786                     /* default route's associated data */
   3787 
   3788                     lpm_key = v6 ? VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) :
   3789                           VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf);
   3790                     sal_memcpy(&lpm_entry, lpm_key, sizeof(lpm_entry));
   3791                     /* set key to the prefix being deleted */
   3792                     (void) _soc_alpm_lpm_ent_key_init(u, prop_pfx, length, vrf, ipv6,
   3793                                            &lpm_entry, 0);
   3794                     /* the sip ad does not matter here */
   3795                     rv = SOC_E_NONE;
   3796                 }
   3797 
   3798                 if (SOC_FAILURE(rv)) {
   3799                     LOG_ERROR(BSL_LS_SOC_ALPM,
   3800                               (BSL_META_U(u,
   3801                                           "_soc_alpm_delete: Could not find replacement"
   3802                                           " prefix for prefix: 0x%08x 0x%08x, prop_pfx:"
   3803                                           " 0x%08x 0x%08x, bpm_len %d \n"),
   3804                                prefix[0], prefix[1],
   3805                                prop_pfx[0], prop_pfx[1], bpm_pfx_len));
   3806                     goto recover_pfx_trie;
   3807                 }
   3808 
   3809                 lpm_key = &lpm_entry;
   3810             }
   3811 
   3812         } else { /* !default_route */
   3813             /* remove the real default route reference if any */
   3814             lpmp = NULL;
   3815             rv = trie_find_lpm(pfx_trie, prefix, length, &lpmp);
   3816             tmp_pyld = (payload_t *) lpmp;
   3817             if (SOC_FAILURE(rv)) {
   3818                 LOG_ERROR(BSL_LS_SOC_ALPM,
   3819                           (BSL_META_U(u,
   3820                                       "_soc_alpm_delete: Could not find default "
   3821                                       "route in the trie for vrf %d\n"), vrf));
   3822                 goto recover_bkt_trie;
   3823             }
   3824             tmp_pyld->bkt_ptr = NULL;
   3825             bpm_pfx_len = 0;
   3826             lpm_key = v6 ? VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) :
   3827                       VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf);
   3828         }
   3829 
   3830         if (propagate) {
   3831             rv = _soc_alpm_fill_aux_entry_for_op(u, lpm_key, v6, db_type, ent_type,
   3832                                                  bpm_pfx_len, &aux_entry);
   3833             if (SOC_FAILURE(rv)) {
   3834                 goto recover_pfx_trie;
   3835             }
   3836 
   3837             /* Perform Delete propagate */
   3838             rv = _soc_alpm_aux_op(u, DELETE_PROPAGATE, &aux_entry, TRUE, &hit,
   3839                                   &tcam_index, &bucket_index, aux_flags);
   3840 
   3841             if (SOC_FAILURE(rv)) {
   3842                 goto recover_pfx_trie;
   3843             }
   3844         }
   3845 
   3846         /* From here on don't try to recover trie state */
   3847         sal_free(payload);
   3848         if (!default_route) {
   3849             sal_free(pfx_pyld);
   3850         }
   3851 
   3852         /* For debug, update the pivot's counter */
   3853         PIVOT_BUCKET_ENT_CNT_UPDATE(pivot_pyld);
   3854 
   3855         if ((pivot_pyld->len != 0) && (trie->trie == NULL)) { /* Empty bucket */
   3856             uint32 hw_key[5];
   3857             sal_memcpy(hw_key, pivot_pyld->key, sizeof(hw_key));
   3858             ALPM_TRIE_TO_NORMAL_IP(hw_key, pivot_pyld->len, ipv6);
   3859 
   3860             /* Initialize an lpm entry to perform a match */
   3861             (void) _soc_alpm_lpm_ent_key_init(u, hw_key, pivot_pyld->len,
   3862                               vrf, ipv6, &lpm_entry, 1);
   3863 
   3864             /* delete entry from TCAM */
   3865             rv = soc_alpm_lpm_delete(u, &lpm_entry);
   3866             if (SOC_FAILURE(rv)) {
   3867                 LOG_ERROR(BSL_LS_SOC_ALPM,
   3868                           (BSL_META_U(u,
   3869                                       "_soc_alpm_delete: Unable to "
   3870                                       "delete pivot 0x%08x 0x%08x \n"),
   3871                            pivot_pyld->key[0], pivot_pyld->key[1]));
   3872                 /* continue to clean up still */
   3873             }
   3874         }
   3875 
   3876         /* Invalidate the route */
   3877         rv = _soc_alpm_delete_in_bkt(u, mem, delete_bucket, bank_disable,
   3878                                      bufp2, e, &key_index, v6);
   3879         if (!SOC_SUCCESS(rv)) {
   3880             LOG_ERROR(BSL_LS_SOC_ALPM,
   3881                       (BSL_META_U(u,
   3882                                   "_soc_th_alpm_delete_in_bkt: Unable to "
   3883                                   "delete phy bkt 0x%08x \n"), delete_bucket)); 
   3884             SOC_ALPM_LPM_UNLOCK(u);
   3885             rv = SOC_E_FAIL;
   3886             return rv;
   3887         }
   3888 
   3889         /* delete corresponding RPF entry if it exists */
   3890         if (SOC_URPF_STATUS_GET(u)) {
   3891             /* hit is an unused variable */
   3892             rv = _soc_alpm_delete_in_bkt(u, mem,
   3893                                          SOC_ALPM_RPF_BKT_IDX(u, delete_bucket),
   3894                                          bank_disable,
   3895                                          bufp2, e, &hit, v6);
   3896             if (!SOC_SUCCESS(rv)) {
   3897                 LOG_ERROR(BSL_LS_SOC_ALPM,
   3898                           (BSL_META_U(u,
   3899                                       "_soc_th_alpm_delete_in_bkt: Unable to "
   3900                                       "delete phy bkt 0x%08x \n"),
   3901                            SOC_ALPM_RPF_BKT_IDX(u, delete_bucket))); 
   3902                 SOC_ALPM_LPM_UNLOCK(u);
   3903                 rv = SOC_E_FAIL;
   3904                 return rv;
   3905             }
   3906         }
   3907 
   3908         if ((pivot_pyld->len != 0) && (trie->trie == NULL)) { /* Empty bucket */
   3909             /* Release Bucket */
   3910             rv = alpm_bucket_release(u, PIVOT_BUCKET_INDEX(pivot_pyld), v6);
   3911             if (SOC_FAILURE(rv)) {
   3912                 LOG_ERROR(BSL_LS_SOC_ALPM,
   3913                           (BSL_META_U(u,
   3914                                       "_soc_alpm_delete: Unable to release"
   3915                                       "empty bucket: %d\n"),
   3916                            PIVOT_BUCKET_INDEX(pivot_pyld)));
   3917                 /* we lose this bucket */
   3918             }
   3919 
   3920             /* remove pivot from pivot trie */
   3921             rv = trie_delete(pivot_trie, pivot_pyld->key, pivot_pyld->len, &delp);
   3922             if (SOC_FAILURE(rv)) {
   3923                 LOG_ERROR(BSL_LS_SOC_ALPM,
   3924                           (BSL_META_U(u,
   3925                                       "could not delete pivot from pivot trie\n")));
   3926             }
   3927 
   3928             /* Free up Bucket trie */
   3929             trie_destroy(PIVOT_BUCKET_TRIE(pivot_pyld));
   3930 
   3931             /* Free up Bucket handle */
   3932             sal_free(PIVOT_BUCKET_HANDLE(pivot_pyld));
   3933 
   3934             /* free Pivot structure */
   3935             sal_free(pivot_pyld);
   3936 
   3937 #ifdef CHECK_CLEAN_BKT
   3938             /* make sure bucket is indeed empty */
   3939             assert(_soc_alpm_bkt_count(u, mem, delete_bucket, v6,
   3940                                             bufp) == 0);
   3941 #endif /* CHECK_CLEAN_BKT */
   3942         }
   3943     }
   3944     VRF_TRIE_ROUTES_DEC(u, vrf_id, vrf, v6);
   3945     if (VRF_TRIE_ROUTES_CNT(u, vrf_id, vrf, v6) == 0) {
   3946         /* vrf is empty. Release resources */
   3947         rv = soc_alpm_vrf_delete(u, vrf, v6);
   3948     }
   3949     SOC_ALPM_LPM_UNLOCK(u);
   3950     return rv;
   3951 
   3952 /* Recovery from error: */
   3953     /* add back pivot bucket trie entry */
   3954     /* add back prefix trie entry */
   3955 recover_pfx_trie:
   3956     rv2 = trie_insert(pfx_trie, prefix, NULL, length, (trie_node_t *)
   3957                      pfx_pyld);
   3958     if (SOC_FAILURE(rv2)) {
   3959         LOG_ERROR(BSL_LS_SOC_ALPM,
   3960                   (BSL_META_U(u,
   3961                               "_soc_alpm_delete: Unable to reinsert"
   3962                               "prefix 0x%08x 0x%08x into pfx trie\n"),
   3963                    prefix[0], prefix[1]));
   3964     }
   3965 recover_bkt_trie:
   3966     rv2 = trie_insert(trie, prefix, NULL, length,  (trie_node_t *) payload);
   3967     if (SOC_FAILURE(rv2)) {
   3968         LOG_ERROR(BSL_LS_SOC_ALPM,
   3969                   (BSL_META_U(u,
   3970                               "_soc_alpm_delete: Unable to reinsert"
   3971                               "prefix 0x%08x 0x%08x into bkt trie\n"),
   3972                    prefix[0], prefix[1]));
   3973     }
   3974 
   3975     SOC_ALPM_LPM_UNLOCK(u);
   3976     return rv;
   3977 }
   3978 
   3979 /**
   3980  * IPMC_MISS signal is never asserted after an unsuccessful L3_DEFIP table
   3981  * lookup for IPMC packets when IPMC (PIM-SM, PIM-BIDIR) forwarding is enabled
   3982  * in TD2+. Due to this, the forwarding logic miss forwards IPMC
   3983  * packets to an incorrect (or invalid) IPMC group.
   3984  *
   3985  * WAR: Add two default rules as last entries in L3_DEFIP (TCAM) table such that
   3986  * all IPV4 and IPV6 multicast packets will, by default, hit these entries, if
   3987  * any specific IPMC were not added in the L3_DEFIP table. Thus L3_DEFIP lookup
   3988  * for IPMC packets will never result in a miss.
   3989  *
   3990  * Packets copied to CPU due to IPMC_MISS will have OPCODE set as 4
   3991  * (IP Multicast) as opposed to 3 (L2 Multicast). This may cause some mismatches
   3992  * in case of CPU bound packets compared to legacy XGS devices.
   3993  */
   3994 int
   3995 soc_alpm_ipmc_war(int unit, int install)
   3996 {
   3997     int i, ipv6 = 0;
   3998     int index = -1;
   3999     defip_entry_t lpm_entry;
   4000     soc_mem_t mem = L3_DEFIPm;
   4001     int count = 1;
   4002     int num_rp = 63;
   4003 
   4004     if (!(soc_feature(unit, soc_feature_alpm) &&
   4005           soc_feature(unit, soc_feature_td2p_a0_sw_war) &&
   4006           soc_property_get(unit, spn_L3_ALPM_ENABLE, 0))) {
   4007         return SOC_E_NONE;
   4008     }
   4009 
   4010     if (!SOC_ALPM_LPM_INIT_CHECK(unit)) {
   4011         return SOC_E_NONE;
   4012     }
   4013 
   4014     if (!SOC_IS_TRIDENT2PLUS(unit)) {
   4015         return SOC_E_NONE;
   4016     }
   4017 
   4018     if (SOC_WARM_BOOT(unit)) {
   4019         return SOC_E_NONE;
   4020     }
   4021 
   4022     if (soc_mem_index_count(unit, L3_DEFIPm) <= 0) {
   4023         return SOC_E_NONE;
   4024     }
   4025 
   4026     if (soc_mem_index_count(unit, L3_DEFIP_PAIR_128m) <= 0) {
   4027         count = 2;
   4028     }
   4029 
   4030     num_rp = soc_mem_field_length(unit,
   4031                 ING_ACTIVE_L3_IIF_PROFILEm, RPA_ID_PROFILEf);
   4032 
   4033     /* First loop for ipv4, second loop for ipv6 */
   4034     for (i = 0; i < count; i++) {
   4035         /* Zero Buffer */
   4036         sal_memset(&lpm_entry, 0, soc_mem_entry_words(unit, mem) * 4);
   4037         ipv6 = i;
   4038 
   4039         soc_mem_field32_set(unit, mem, &lpm_entry, VALID0f, 1);
   4040         soc_mem_field32_set(unit, mem, &lpm_entry, MODE_MASK0f, 3);
   4041         soc_mem_field32_set(unit, mem, &lpm_entry, ENTRY_TYPE_MASK0f, 1);
   4042         soc_mem_field32_set(unit, mem, &lpm_entry, MULTICAST_ROUTE0f, 1);
   4043         soc_mem_field32_set(unit, mem, &lpm_entry, GLOBAL_ROUTE0f, 1);
   4044         soc_mem_field32_set(unit, mem, &lpm_entry, RPA_ID0f, num_rp - 1);
   4045         soc_mem_field32_set(unit, mem, &lpm_entry, EXPECTED_L3_IIF0f, 16383);
   4046 
   4047         if (ipv6) {
   4048             soc_mem_field32_set(unit, mem, &lpm_entry, VALID1f, 1);
   4049             soc_mem_field32_set(unit, mem, &lpm_entry, MODE0f, 1);
   4050             soc_mem_field32_set(unit, mem, &lpm_entry, MODE1f, 1);
   4051             soc_mem_field32_set(unit, mem, &lpm_entry, MODE_MASK1f, 3);
   4052             soc_mem_field32_set(unit, mem, &lpm_entry, ENTRY_TYPE_MASK1f, 1);
   4053             soc_mem_field32_set(unit, mem, &lpm_entry, MULTICAST_ROUTE1f, 1);
   4054             soc_mem_field32_set(unit, mem, &lpm_entry, GLOBAL_ROUTE1f, 1);
   4055             soc_mem_field32_set(unit, mem, &lpm_entry, RPA_ID1f, num_rp - 1);
   4056             /* 16383 indicate a max field value which is used as an invalid value */
   4057             soc_mem_field32_set(unit, mem, &lpm_entry, EXPECTED_L3_IIF1f, 16383);
   4058 
   4059             soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR0f, 0);
   4060             soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR_MASK0f, 0);
   4061             /* IPv6 multicast route address starts from ff00 for default match */
   4062             soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR1f, 0xff000000);
   4063             soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR_MASK1f, 0xff000000);
   4064         } else {
   4065             /* IPv4 multicast route address starts from 224 for default match */
   4066             soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR0f, 0xe0000000);
   4067             soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR_MASK0f, 0xe0000000);
   4068         }
   4069 
   4070         if (install) {
   4071             if (soc_feature(unit, soc_feature_alpm_flex_stat)) {
   4072                 soc_mem_field32_set(unit, mem, &lpm_entry, ENTRY_VIEW0f, 0x1);
   4073                 VRF_FLEX_SET(unit, SOC_L3_VRF_GLOBAL, SOC_VRF_MAX(unit) + 1, ipv6, 1);
   4074             }
   4075             SOC_IF_ERROR_RETURN(soc_alpm_lpm_insert(unit, &lpm_entry, &index,
   4076                                                     0, 0, INVALID_BPM_LEN));
   4077         } else {
   4078             SOC_IF_ERROR_RETURN(soc_alpm_lpm_delete(unit, &lpm_entry));
   4079         }
   4080     }
   4081 
   4082     return SOC_E_NONE;
   4083 }
   4084 
   4085 /* Initialize ALPM Subsytem */
   4086 int
   4087 soc_alpm_init(int u)
   4088 {
   4089     int i;
   4090     int rv = SOC_E_NONE;
   4091 
   4092     if (SOC_ALPM_LPM_INIT_CHECK(u)) {
   4093         /* this is a reinit. clean up old state */
   4094         if (soc_alpm_deinit(u) < 0) {
   4095             return SOC_E_INTERNAL;
   4096         }
   4097     }
   4098 
   4099     /* Initialize ALPM control */
   4100     rv = _soc_alpm_ctrl_init(u);
   4101     SOC_IF_ERROR_RETURN(rv);
   4102 
   4103     /* Initialize TCAM Memory management */
   4104     rv = soc_alpm_lpm_init(u);
   4105     SOC_IF_ERROR_RETURN(rv);
   4106 
   4107     /* Initialize ALPM memory management */
   4108     rv = soc_alpm_shared_mem_init(u);
   4109 
   4110     alpm_vrf_handle[u] = sal_alloc((MAX_VRF_ID + 1) * sizeof(alpm_vrf_handle_t), "ALPM VRF Handles");
   4111     if (alpm_vrf_handle[u] == NULL) {
   4112         return SOC_E_MEMORY;
   4113     }
   4114 
   4115     tcam_pivot[u] = sal_alloc(MAX_PIVOT_COUNT * sizeof(alpm_pivot_t *), "ALPM pivots");
   4116     if (tcam_pivot[u] == NULL) {
   4117         return SOC_E_MEMORY;
   4118     }
   4119     sal_memset(alpm_vrf_handle[u], 0, (MAX_VRF_ID + 1) * sizeof(alpm_vrf_handle_t));
   4120     sal_memset(tcam_pivot[u], 0, MAX_PIVOT_COUNT * sizeof(alpm_pivot_t *));
   4121     sal_memset(&soc_alpm_dbg_cnt[u], 0, sizeof(_alpm_int_dbg_cnt_t));
   4122 
   4123     /* Initialize PIVOT management */
   4124     for (i = 0; i < MAX_PIVOT_COUNT; i++) {
   4125         ALPM_TCAM_PIVOT(u, i) = NULL;
   4126     }
   4127 
   4128     if (SOC_CONTROL(u)->alpm_bulk_retry == NULL) {
   4129         SOC_CONTROL(u)->alpm_bulk_retry =
   4130             sal_sem_create("ALPM bulk retry", sal_sem_BINARY, 0);
   4131     }
   4132     if (SOC_CONTROL(u)->alpm_lookup_retry == NULL) {
   4133         SOC_CONTROL(u)->alpm_lookup_retry =
   4134             sal_sem_create("ALPM lookup retry", sal_sem_BINARY, 0);
   4135     }
   4136     if (SOC_CONTROL(u)->alpm_insert_retry == NULL) {
   4137         SOC_CONTROL(u)->alpm_insert_retry =
   4138             sal_sem_create("ALPM insert retry", sal_sem_BINARY, 0);
   4139     }
   4140     if (SOC_CONTROL(u)->alpm_delete_retry == NULL) {
   4141         SOC_CONTROL(u)->alpm_delete_retry =
   4142             sal_sem_create("ALPM delete retry", sal_sem_BINARY, 0);
   4143     }
   4144 
   4145     rv = soc_alpm_128_lpm_init(u);
   4146     SOC_IF_ERROR_RETURN(rv);
   4147 
   4148     (void)soc_alpm_ipmc_war(u, TRUE);
   4149 
   4150     return rv;
   4151 }
   4152 
   4153 
   4154 /* clear alpm related internal state */
   4155 static int soc_alpm_state_clear(int u)
   4156 {
   4157     int i, rv;
   4158     alpm_pivot_t *tmp;
   4159 
   4160     /* clear all pivot state */
   4161     for (i = 0; i < MAX_PIVOT_COUNT; i++) {
   4162         tmp = ALPM_TCAM_PIVOT(u, i);
   4163         if (tmp) {
   4164             if (PIVOT_BUCKET_HANDLE(tmp)) {
   4165                 if (PIVOT_BUCKET_TRIE(tmp)) {
   4166                     /* traverse bucket trie and clear it */
   4167                     rv = trie_traverse(PIVOT_BUCKET_TRIE(tmp),
   4168                             alpm_delete_node_cb, NULL, _TRIE_INORDER_TRAVERSE);
   4169                     if (SOC_SUCCESS(rv)) {
   4170                         trie_destroy(PIVOT_BUCKET_TRIE(tmp));
   4171                     } else {
   4172                         LOG_ERROR(BSL_LS_SOC_ALPM,
   4173                                   (BSL_META_U(u,
   4174                                               "Unable to clear trie state for unit %d\n"),
   4175                                    u));
   4176                         return rv;
   4177                     }
   4178                 }
   4179                 sal_free(PIVOT_BUCKET_HANDLE(tmp));
   4180             }
   4181             sal_free(ALPM_TCAM_PIVOT(u, i));
   4182             ALPM_TCAM_PIVOT(u, i) = NULL;
   4183         }
   4184     }
   4185 
   4186     /* clear all prefix tries */
   4187     for (i = 0; i <= SOC_VRF_MAX(u) + 1; i++) {
   4188         rv = trie_traverse(VRF_PREFIX_TRIE_IPV4(u, i), alpm_delete_node_cb,
   4189                            NULL, _TRIE_INORDER_TRAVERSE);
   4190         if (SOC_SUCCESS(rv)) {
   4191             trie_destroy(VRF_PREFIX_TRIE_IPV4(u, i));
   4192         } else {
   4193             LOG_ERROR(BSL_LS_SOC_ALPM,
   4194                       (BSL_META_U(u,
   4195                                   "unit: %d Unable to clear v4 pfx trie for vrf %d\n"),
   4196                        u, i));
   4197             return rv;
   4198         }
   4199         rv = trie_traverse(VRF_PREFIX_TRIE_IPV6(u, i), alpm_delete_node_cb,
   4200                            NULL, _TRIE_INORDER_TRAVERSE);
   4201         if (SOC_SUCCESS(rv)) {
   4202             trie_destroy(VRF_PREFIX_TRIE_IPV6(u, i));
   4203         } else {
   4204             LOG_ERROR(BSL_LS_SOC_ALPM,
   4205                       (BSL_META_U(u,
   4206                                   "unit: %d Unable to clear v6 pfx trie for vrf %d\n"),
   4207                        u, i));
   4208             return rv;
   4209         }
   4210         if (VRF_TRIE_DEFAULT_ROUTE_IPV4(u, i) != NULL) {
   4211             sal_free(VRF_TRIE_DEFAULT_ROUTE_IPV4(u, i));
   4212         }
   4213         if (VRF_TRIE_DEFAULT_ROUTE_IPV6(u, i) != NULL) {
   4214             sal_free(VRF_TRIE_DEFAULT_ROUTE_IPV6(u, i));
   4215         }
   4216         sal_memset(&alpm_vrf_handle[u][i], 0, sizeof(alpm_vrf_handle_t));
   4217     }
   4218 
   4219     /* Reset VRF_OVERRIDE debug counter */
   4220     sal_memset(&alpm_vrf_handle[u][MAX_VRF_ID], 0, sizeof(alpm_vrf_handle_t));
   4221     /* Mark Global Hi (VRF_OVERRIDE) for IPv4, IPv6-64, IPv6-128 inited for debug usage */
   4222     VRF_TRIE_INIT_DONE(u, MAX_VRF_ID, 0, 1);
   4223     VRF_TRIE_INIT_DONE(u, MAX_VRF_ID, 1, 1);
   4224     VRF_TRIE_INIT_DONE(u, MAX_VRF_ID, 2, 1);
   4225 
   4226     if (SOC_ALPM_BUCKET_BMAP(u) != NULL) {
   4227         sal_free(SOC_ALPM_BUCKET_BMAP(u));
   4228     }
   4229     sal_memset(&soc_alpm_bucket[u], 0, sizeof(soc_alpm_bucket_t));
   4230     sal_memset(&soc_alpm_dbg_cnt[u], 0, sizeof(_alpm_int_dbg_cnt_t));
   4231 
   4232     /* Free memory allocated for VRF handles and tcam pivots */
   4233     if (alpm_vrf_handle[u])
   4234         sal_free(alpm_vrf_handle[u]);
   4235     if (tcam_pivot[u])
   4236         sal_free(tcam_pivot[u]);
   4237     alpm_vrf_handle[u] = NULL;
   4238     tcam_pivot[u]      = NULL;
   4239     return SOC_E_NONE;
   4240 }
   4241 
   4242 /* De-Init ALPM Subsytem */
   4243 int
   4244 soc_alpm_deinit(int u)
   4245 {
   4246     soc_alpm_lpm_deinit(u);
   4247 
   4248     SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_deinit(u));
   4249 
   4250     SOC_IF_ERROR_RETURN(soc_alpm_128_state_clear(u));
   4251 
   4252     SOC_IF_ERROR_RETURN(soc_alpm_state_clear(u));
   4253 
   4254     if (SOC_CONTROL(u)->alpm_bulk_retry) {
   4255         sal_sem_destroy(SOC_CONTROL(u)->alpm_bulk_retry);
   4256         SOC_CONTROL(u)->alpm_bulk_retry = NULL;
   4257     }
   4258     if (SOC_CONTROL(u)->alpm_lookup_retry) {
   4259         sal_sem_destroy(SOC_CONTROL(u)->alpm_lookup_retry);
   4260         SOC_CONTROL(u)->alpm_lookup_retry = NULL;
   4261     }
   4262     if (SOC_CONTROL(u)->alpm_insert_retry) {
   4263         sal_sem_destroy(SOC_CONTROL(u)->alpm_insert_retry);
   4264         SOC_CONTROL(u)->alpm_insert_retry = NULL;
   4265     }
   4266     if (SOC_CONTROL(u)->alpm_delete_retry) {
   4267         sal_sem_destroy(SOC_CONTROL(u)->alpm_delete_retry);
   4268         SOC_CONTROL(u)->alpm_delete_retry = NULL;
   4269     }
   4270 
   4271     return SOC_E_NONE;
   4272 }
   4273 
   4274 
   4275 /*
   4276  * soc_alpm_vrf_add
   4277  * Add a VRF default route when a L3 VRF is added
   4278  * Adds a 0.0 entry into VRF
   4279  */
   4280 static int
   4281 soc_alpm_vrf_add(int u, int vrf, int v6)
   4282 {
   4283     defip_entry_t *lpm_entry = NULL, tmp_lpm;
   4284     int bucket_pointer;
   4285     int index;
   4286     int rv = SOC_E_NONE;
   4287     uint32 key[5] = {0};
   4288     uint32 length;
   4289     alpm_bucket_handle_t *bucket_handle = NULL;
   4290     alpm_pivot_t *pivot_pyld = NULL;
   4291     payload_t   *pfx_pyld = NULL;
   4292     trie_t  *prefix_root = NULL, *bucket_root = NULL;
   4293     int prefix_root_inserted = 0;
   4294     trie_t *pivot_root = NULL;
   4295     int pivot_root_inserted = 0;
   4296     soc_mem_t mem;
   4297 
   4298     SOC_ALPM_TABLE_MEM(u, v6, mem, VRF_FLEX_IS_SET(u, vrf, vrf, v6, 1));
   4299     rv = soc_alpm_assign(u, vrf, mem, &bucket_pointer, NULL);
   4300     if (SOC_FAILURE(rv)) {
   4301         return rv;
   4302     }
   4303 
   4304     /* Allocate bucket handle */
   4305     bucket_handle = sal_alloc(sizeof(alpm_bucket_handle_t), "ALPM Bucket Handle");
   4306     if (bucket_handle == NULL) {
   4307         LOG_ERROR(BSL_LS_SOC_ALPM,
   4308                   (BSL_META_U(u,
   4309                               "soc_alpm_vrf_add: Unable to allocate memory for "
   4310                               "PIVOT trie node \n")));
   4311         rv = SOC_E_MEMORY;
   4312         goto cleanup;
   4313     }
   4314     sal_memset(bucket_handle, 0, sizeof(*bucket_handle));
   4315 
   4316     /* Allocate PIVOT Payload */
   4317     pivot_pyld = sal_alloc(sizeof(alpm_pivot_t), "Payload for Pivot");
   4318     if (pivot_pyld == NULL) {
   4319         LOG_ERROR(BSL_LS_SOC_ALPM,
   4320                   (BSL_META_U(u,
   4321                               "soc_alpm_vrf_add: Unable to allocate memory for "
   4322                               "PIVOT trie node \n")));
   4323         rv = SOC_E_MEMORY;
   4324         goto cleanup;
   4325     }
   4326     sal_memset(pivot_pyld, 0, sizeof(*pivot_pyld));
   4327     PIVOT_BUCKET_HANDLE(pivot_pyld) = bucket_handle;
   4328 
   4329     /* Allocate Prefix Payload */
   4330     pfx_pyld = sal_alloc(sizeof(payload_t), "Payload for pfx trie key");
   4331     if (pfx_pyld == NULL) {
   4332         LOG_ERROR(BSL_LS_SOC_ALPM,
   4333                   (BSL_META_U(u,
   4334                               "soc_alpm_vrf_add: Unable to allocate memory for "
   4335                               "pfx trie node \n")));
   4336         rv = SOC_E_MEMORY;
   4337         goto cleanup;
   4338     }
   4339     sal_memset(pfx_pyld, 0, sizeof(*pfx_pyld));
   4340 
   4341     /* Initialize VRF pivot trie */
   4342     if (v6 == 0) {
   4343         rv = trie_init(_MAX_KEY_LEN_48_, &VRF_PIVOT_TRIE_IPV4(u, vrf));
   4344         pivot_root = VRF_PIVOT_TRIE_IPV4(u, vrf);
   4345     } else {
   4346         rv = trie_init(_MAX_KEY_LEN_144_, &VRF_PIVOT_TRIE_IPV6(u, vrf));
   4347         pivot_root = VRF_PIVOT_TRIE_IPV6(u, vrf);
   4348     }
   4349     if (SOC_FAILURE(rv)) {
   4350         goto cleanup;
   4351     }
   4352 
   4353     /* Initialize VRF prefix trie */
   4354     if (v6 == 0) {
   4355         rv = trie_init(_MAX_KEY_LEN_48_, &VRF_PREFIX_TRIE_IPV4(u, vrf));
   4356         prefix_root = VRF_PREFIX_TRIE_IPV4(u, vrf);
   4357     } else {
   4358         rv = trie_init(_MAX_KEY_LEN_144_, &VRF_PREFIX_TRIE_IPV6(u, vrf));
   4359         prefix_root = VRF_PREFIX_TRIE_IPV6(u, vrf);
   4360     }
   4361     if (SOC_FAILURE(rv)) {
   4362         goto cleanup;
   4363     }
   4364 
   4365     /* Initialize bucket trie */
   4366     if (v6) {
   4367         rv = trie_init(_MAX_KEY_LEN_144_, &PIVOT_BUCKET_TRIE(pivot_pyld));
   4368     } else {
   4369         rv = trie_init(_MAX_KEY_LEN_48_, &PIVOT_BUCKET_TRIE(pivot_pyld));
   4370     }
   4371     bucket_root = PIVOT_BUCKET_TRIE(pivot_pyld);
   4372     if (SOC_FAILURE(rv)) {
   4373         goto cleanup;
   4374     }
   4375     PIVOT_BUCKET_INDEX(pivot_pyld) = bucket_pointer;
   4376     PIVOT_BUCKET_VRF(pivot_pyld) = vrf;
   4377     PIVOT_BUCKET_IPV6(pivot_pyld) = v6;
   4378     PIVOT_BUCKET_DEF(pivot_pyld) = TRUE;
   4379 
   4380     /* 0 for default * route */
   4381     length = 0;
   4382     pivot_pyld->key[0] = pfx_pyld->key[0] = key[0];
   4383     pivot_pyld->key[1] = pfx_pyld->key[1] = key[1];
   4384     pivot_pyld->len = pfx_pyld->len    = length;
   4385     rv = trie_insert(prefix_root, key, NULL, length, &(pfx_pyld->node));
   4386     /* no internal default in bucket trie */
   4387     if (SOC_FAILURE(rv)) {
   4388         goto cleanup;
   4389     }
   4390     prefix_root_inserted = 1;
   4391 
   4392     /* insert into trie of pivots */
   4393     rv = trie_insert(pivot_root, key, NULL, length, (trie_node_t *)pivot_pyld);
   4394     if (SOC_FAILURE(rv)) {
   4395         goto cleanup;
   4396     }
   4397     pivot_root_inserted = 1;
   4398 
   4399     /* Initialize an lpm entry to perform a match */
   4400     (void) _soc_alpm_lpm_ent_key_init(u, key, 0, vrf, v6, &tmp_lpm, 1);
   4401 
   4402     /* for global VRF */
   4403     if (vrf == SOC_VRF_MAX(u) + 1) {
   4404         soc_L3_DEFIPm_field32_set(u, &tmp_lpm, GLOBAL_ROUTE0f, 1);
   4405     } else {
   4406         /* Set default miss to global route only for non global routes */
   4407         soc_L3_DEFIPm_field32_set(u, &tmp_lpm, DEFAULT_MISS0f, 1);
   4408     }
   4409     soc_L3_DEFIPm_field32_set(u, &tmp_lpm, ENTRY_VIEW0f,
   4410                               VRF_FLEX_IS_SET(u, vrf, vrf, v6, 1));
   4411 
   4412     soc_L3_DEFIPm_field32_set(u, &tmp_lpm, ALG_BKT_PTR0f, bucket_pointer);
   4413 
   4414     /* Allocate default lpm entry */
   4415     lpm_entry = sal_alloc(sizeof(defip_entry_t), "Default LPM entry");
   4416     if (lpm_entry == NULL) {
   4417         LOG_ERROR(BSL_LS_SOC_ALPM,
   4418                   (BSL_META_U(u,
   4419                               "soc_alpm_vrf_add: unable to allocate memory for "
   4420                               "IPv4 LPM entry\n")));
   4421         rv = SOC_E_MEMORY;
   4422         goto cleanup;
   4423     }
   4424     sal_memcpy(lpm_entry, &tmp_lpm, sizeof(tmp_lpm));
   4425 
   4426     /* add Entry into tcam as default routes for the VRF */
   4427     /* urpf could modify the lpm entry. So use tmp one */
   4428     rv = soc_alpm_lpm_insert(u, &tmp_lpm, &index, 0, 0, INVALID_BPM_LEN);
   4429     if (SOC_FAILURE(rv)) {
   4430         goto cleanup;
   4431     }
   4432 
   4433     if (v6 == 0) {
   4434         VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf) = lpm_entry;
   4435     } else {
   4436         VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) = lpm_entry;
   4437     }
   4438 
   4439     /* get physical index */
   4440     index = soc_alpm_physical_idx(u, L3_DEFIPm, index, v6);
   4441     if (v6 == 0) {
   4442         ALPM_TCAM_PIVOT(u, index) = pivot_pyld;
   4443         PIVOT_TCAM_INDEX(pivot_pyld) = index;
   4444     } else {
   4445         ALPM_TCAM_PIVOT(u, index << 1) = pivot_pyld;
   4446         PIVOT_TCAM_INDEX(pivot_pyld) = index << 1;
   4447     }
   4448 
   4449     PIVOT_TCAM_BPMLEN(pivot_pyld) = length;
   4450     VRF_TRIE_INIT_DONE(u, vrf, v6, 1);
   4451 
   4452     return SOC_E_NONE;
   4453 
   4454 cleanup:
   4455     if (lpm_entry) {
   4456         sal_free(lpm_entry);
   4457     }
   4458 
   4459     if (pivot_root_inserted) {
   4460         trie_node_t *delp = NULL;
   4461         (void) trie_delete(pivot_root, key, length, &delp);
   4462     }
   4463 
   4464     if (prefix_root_inserted) {
   4465         trie_node_t *delp = NULL;
   4466         (void) trie_delete(prefix_root, key, length, &delp);
   4467     }
   4468 
   4469     /* destroy inited tries */
   4470     if (bucket_root) {
   4471         (void) trie_destroy(bucket_root);
   4472         PIVOT_BUCKET_TRIE(pivot_pyld) = NULL;
   4473     }
   4474     if (prefix_root) {
   4475         (void) trie_destroy(prefix_root);
   4476         if (v6 == 0) {
   4477             VRF_PREFIX_TRIE_IPV4(u, vrf) = NULL;
   4478         } else {
   4479             VRF_PREFIX_TRIE_IPV6(u, vrf) = NULL;
   4480         }
   4481     }
   4482     if (pivot_root) {
   4483         (void) trie_destroy(pivot_root);
   4484         if (v6 == 0) {
   4485             VRF_PIVOT_TRIE_IPV4(u, vrf) = NULL;
   4486         } else {
   4487             VRF_PIVOT_TRIE_IPV6(u, vrf) = NULL;
   4488         }
   4489     }
   4490 
   4491     if (pfx_pyld) {
   4492         sal_free(pfx_pyld);
   4493     }
   4494     if (pivot_pyld) {
   4495         sal_free(pivot_pyld);
   4496     }
   4497     if (bucket_handle) {
   4498         sal_free(bucket_handle);
   4499     }
   4500 
   4501     (void) alpm_bucket_release(u, bucket_pointer, v6);
   4502     return rv;
   4503 }
   4504 
   4505 
   4506 /*
   4507  * soc_alpm_vrf_delete
   4508  * Delete the VRF default route when a L3 VRF is destroyed
   4509  */
   4510 static int
   4511 soc_alpm_vrf_delete(int u, int vrf, int v6)
   4512 {
   4513     defip_entry_t *lpm_entry;
   4514     int bucket_pointer;
   4515     int idx;
   4516     int rv = SOC_E_NONE;
   4517     uint32 key[5] = {0}, result[SOC_MAX_MEM_FIELD_WORDS];
   4518     payload_t *payload;
   4519     alpm_pivot_t *pivot_pyld1;
   4520     trie_node_t *delp;
   4521     trie_t  *root;
   4522     trie_t *pivot_root = NULL;
   4523 
   4524     if (v6 == 0) {
   4525         lpm_entry = VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf);
   4526     } else {
   4527         lpm_entry = VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf);
   4528     }
   4529 
   4530     /* find bucket pointers and release them */
   4531     bucket_pointer = soc_L3_DEFIPm_field32_get(u, lpm_entry, ALG_BKT_PTR0f);
   4532     rv = alpm_bucket_release(u, bucket_pointer, v6);
   4533 
   4534     /* add Entry into tcam as default routes for the VRF */
   4535     rv = soc_alpm_lpm_match(u, lpm_entry, (void *) result, &idx);
   4536     if (SOC_FAILURE(rv)) {
   4537         LOG_ERROR(BSL_LS_SOC_ALPM,
   4538                   (BSL_META_U(u,
   4539                               "soc_alpm_vrf_delete: unable to get internal"
   4540                               " pivot idx for vrf %d/%d\n"), vrf, v6));
   4541         idx = -1;
   4542     }
   4543 
   4544     idx = soc_alpm_physical_idx(u, L3_DEFIPm, idx, v6);
   4545     if (v6 == 0) {
   4546         pivot_pyld1 = ALPM_TCAM_PIVOT(u, idx);
   4547     } else {
   4548         pivot_pyld1 = ALPM_TCAM_PIVOT(u, idx << 1);
   4549     }
   4550 
   4551     rv = soc_alpm_lpm_delete(u, lpm_entry);
   4552     if (SOC_FAILURE(rv)) {
   4553         LOG_ERROR(BSL_LS_SOC_ALPM,
   4554                   (BSL_META_U(u,
   4555                               "soc_alpm_vrf_delete: unable to delete lpm entry "
   4556                               " for internal default for vrf %d/%d\n"), vrf, v6));
   4557     }
   4558 
   4559     sal_free(lpm_entry);
   4560 
   4561     if (v6 == 0) {
   4562         VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf) = NULL;
   4563         root = VRF_PREFIX_TRIE_IPV4(u, vrf);
   4564         VRF_PREFIX_TRIE_IPV4(u, vrf) = NULL;
   4565     } else {
   4566         VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf)  = NULL;
   4567         root = VRF_PREFIX_TRIE_IPV6(u, vrf);
   4568         VRF_PREFIX_TRIE_IPV6(u, vrf) = NULL;
   4569     }
   4570     VRF_TRIE_INIT_DONE(u, vrf, v6, 0);
   4571 
   4572     rv = trie_delete(root, key, 0, &delp);
   4573     payload = (payload_t *) delp;
   4574     if (SOC_FAILURE(rv)) {
   4575         LOG_ERROR(BSL_LS_SOC_ALPM,
   4576                   (BSL_META_U(u,
   4577                               "Unable to delete internal default for vrf "
   4578                               " %d/%d\n"), vrf, v6));
   4579     }
   4580     sal_free(payload);
   4581 
   4582     (void) trie_destroy(root);
   4583 
   4584     if (v6 == 0) {
   4585         pivot_root = VRF_PIVOT_TRIE_IPV4(u, vrf);
   4586         VRF_PIVOT_TRIE_IPV4(u, vrf) = NULL;
   4587     } else {
   4588         pivot_root = VRF_PIVOT_TRIE_IPV6(u, vrf);
   4589         VRF_PIVOT_TRIE_IPV6(u, vrf) = NULL;
   4590     }
   4591 
   4592     delp = NULL;
   4593     rv = trie_delete(pivot_root, key, 0, &delp);
   4594     if (SOC_FAILURE(rv)) {
   4595         LOG_ERROR(BSL_LS_SOC_ALPM,
   4596                   (BSL_META_U(u,
   4597                               "Unable to delete internal pivot node for vrf"
   4598                               " %d/%d\n"), vrf, v6));
   4599     }
   4600     (void) trie_destroy(pivot_root);
   4601 
   4602     (void) trie_destroy(PIVOT_BUCKET_TRIE(pivot_pyld1));
   4603     sal_free(PIVOT_BUCKET_HANDLE(pivot_pyld1));
   4604     sal_free(pivot_pyld1);
   4605 
   4606     return rv;
   4607 }
   4608 
   4609 /*
   4610  * soc_alpm_insert
   4611  * For IPV4 assume only both IP_ADDR0 is valid
   4612  * Moving multiple entries around in h/w vs  doing a linear search in s/w
   4613  */
   4614 int
   4615 soc_alpm_insert(int u, void *lpm_entry, uint32 flags, int bkt_idx,
   4616                 int pivot_info)
   4617 {
   4618     defip_alpm_ipv4_1_entry_t alpmv4_entry, alpmv4_sip_entry;
   4619     defip_alpm_ipv6_64_1_entry_t alpmv6_entry, alpmv6_sip_entry;
   4620     soc_mem_t mem;
   4621     void      *bufp, *bufp2;
   4622     int       vrf_id, vrf;
   4623     int       index;
   4624     int       ipv6;
   4625     int       rv = SOC_E_NONE;
   4626     uint32    default_route;
   4627     int       ipmc_route = 0;
   4628     int       flex_v6_64 = 0;
   4629 
   4630     ipv6 = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, MODE0f);
   4631 
   4632     /* Get table memory. */
   4633     SOC_ALPM_TABLE_MEM(u, ipv6, mem, flags & SOC_ALPM_STAT_FLEX);
   4634 
   4635     /* Assign entry buf based on table being used */
   4636     SOC_ALPM_ENTRY_BUF(ipv6, mem, bufp, alpmv4_entry, alpmv6_entry);
   4637     SOC_ALPM_ENTRY_BUF(ipv6, mem, bufp2, alpmv4_sip_entry, alpmv6_sip_entry);
   4638 
   4639     SOC_IF_ERROR_RETURN(
   4640         _soc_alpm_mem_ent_init(u, lpm_entry, bufp, bufp2, mem, flags,
   4641                                &default_route));
   4642 
   4643     /* If the entry is override, then insert into TCAM directly */
   4644     SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, lpm_entry, &vrf_id, &vrf));
   4645 
   4646     if (VRF_FLEX_COMPLETED(u, vrf_id, vrf, ipv6)) {
   4647         if (VRF_FLEX_IS_SET(u, vrf_id, vrf, ipv6, 1) != !!(flags & SOC_ALPM_STAT_FLEX)) {
   4648             LOG_ERROR(BSL_LS_SOC_ALPM,
   4649                       (BSL_META_U(u,
   4650                                   "soc_alpm_insert:Flex flag conflict\n"
   4651                                   )));
   4652             return SOC_E_PARAM;
   4653         }
   4654     } else {
   4655         VRF_FLEX_SET(u, vrf_id, vrf, ipv6, flags & SOC_ALPM_STAT_FLEX);
   4656     }
   4657 
   4658     if (soc_feature(u, soc_feature_ipmc_defip)) {
   4659         ipmc_route = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, MULTICAST_ROUTE0f);
   4660     }
   4661 
   4662     if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && ipv6 &&
   4663         (flags & SOC_ALPM_STAT_FLEX)) {
   4664         if (soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f) == 0xFFFFFFFF &&
   4665             soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f) == 0xFFFFFFFF) {
   4666             flex_v6_64 = 1;
   4667         }
   4668     }
   4669 
   4670     if ((vrf_id != SOC_L3_VRF_OVERRIDE) &&
   4671         (vrf == 0) && soc_alpm_mode_get(u)) {
   4672         /* cannot have 0 as a VRF in parallel mode */
   4673         LOG_ERROR(BSL_LS_SOC_ALPM,
   4674                   (BSL_META_U(u,
   4675                               "VRF=0 cannot be added in Parallel mode\n")));
   4676         return SOC_E_PARAM;
   4677     }
   4678 
   4679     /* For VRF_OVERRIDE (Global High) entries, and IPMC route
   4680      * software needs to maintain the index
   4681      */
   4682     /* Prefix resides in TCAM directly */
   4683     if ((vrf_id == SOC_L3_VRF_OVERRIDE) || (ipmc_route) || (flex_v6_64)) {
   4684 
   4685         /* Insert into TCAM directly and return */
   4686         /* search in the hash table */
   4687         rv = soc_alpm_lpm_insert(u, lpm_entry, &index, 0,
   4688                                  flags & SOC_ALPM_RPF_SRC_DISCARD, INVALID_BPM_LEN);
   4689         if (SOC_SUCCESS(rv) && !(pivot_info & SOC_ALPM_LPM_LOOKUP_HIT)) {
   4690             VRF_TRIE_ROUTES_INC(u, vrf_id, vrf, ipv6);
   4691         }
   4692 
   4693         if (rv == SOC_E_FULL) {
   4694             VRF_PIVOT_FULL_INC(u, MAX_VRF_ID, ipv6);
   4695         }
   4696         return(rv);
   4697     }
   4698 
   4699     /* combined search mode protection */
   4700     if (vrf_id != SOC_L3_VRF_GLOBAL) {
   4701         if (!soc_alpm_mode_get(u)) {
   4702             /* for emtpy DB allow insert only if route is default */
   4703             if (VRF_TRIE_ROUTES_CNT(u, vrf_id, vrf, ipv6) == 0) {
   4704                 /* check if route is default, else throw error */
   4705                 if (!default_route) {
   4706                     LOG_ERROR(BSL_LS_SOC_ALPM,
   4707                               (BSL_META_U(u,
   4708                                           "VRF %d: First route in a VRF has to "
   4709                                           " be a default route in this mode\n"), vrf_id));
   4710                     return SOC_E_PARAM;
   4711                 }
   4712             }
   4713         }
   4714     }
   4715 
   4716     /* non override entries, goes into ALPM memory */
   4717     if (!VRF_TRIE_INIT_COMPLETED(u, vrf, ipv6)) {
   4718         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   4719                     (BSL_META_U(u,
   4720                                 "soc_alpm_insert:VRF %d is not "
   4721                                 "initialized\n"), vrf));
   4722         rv = soc_alpm_vrf_add(u, vrf, ipv6);
   4723         if (SOC_FAILURE(rv)) {
   4724             LOG_ERROR(BSL_LS_SOC_ALPM,
   4725                       (BSL_META_U(u,
   4726                                   "soc_alpm_insert:VRF %d/%d trie init \n"
   4727                                   "failed\n"), vrf, ipv6));
   4728             return rv;
   4729         }
   4730         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   4731                     (BSL_META_U(u,
   4732                                 "soc_alpm_insert:VRF %d/%d trie init "
   4733                                 "completed\n"), vrf, ipv6));
   4734     }
   4735 
   4736     /* Find and update the entry */
   4737     if (pivot_info & SOC_ALPM_LOOKUP_HIT) {
   4738         rv = _soc_alpm_find_and_update(u, lpm_entry, bufp, bufp2, mem,
   4739                                        bkt_idx);
   4740     } else {
   4741         /* entry is not found in database */
   4742         /* Insert the entry into the database, if FULL, split the bucket */
   4743         /* Insert prefix into trie */
   4744         /* Split trie : Insertion into trie results into Split */
   4745         /* Allocate a TCAM entry for PIVOT and bucket and move entries */
   4746         if (bkt_idx == -1) {
   4747             /* internally 0 is invalid bucket index */
   4748             bkt_idx = 0;
   4749         }
   4750         rv = _soc_alpm_insert(u, ipv6, lpm_entry, mem, bufp, bufp2, &index,
   4751                               SOC_ALPM_BKT_ENTRY_TO_IDX(bkt_idx), pivot_info);
   4752         if (SOC_SUCCESS(rv)) {
   4753             VRF_TRIE_ROUTES_INC(u, vrf_id, vrf, ipv6);
   4754         }
   4755     }
   4756 
   4757     if (rv != SOC_E_NONE) {
   4758         LOG_WARN(BSL_LS_SOC_ALPM,
   4759                  (BSL_META_U(u,
   4760                              "unit %d :soc_alpm_insert: Route Insertion Failed :%s\n"),
   4761                   u, soc_errmsg(rv)));
   4762     }
   4763     return(rv);
   4764 }
   4765 
   4766 
   4767 /*
   4768  * soc_alpm_lookup
   4769  * For IPV4 assume only both IP_ADDR0 is valid
   4770  * Moving multiple entries around in h/w vs  doing a linear search in s/w
   4771  */
   4772 int
   4773 soc_alpm_lookup(int u,
   4774                 void *key_data,
   4775                 void *e,         /* return entry data if found */
   4776                 int *index_ptr,
   4777                 int *cookie)
   4778 {
   4779     defip_alpm_ipv4_1_entry_t alpmv4_entry; /* Search Result buffer */
   4780     defip_alpm_ipv6_64_1_entry_t alpmv6_entry; /* Search Result buffer */
   4781     soc_mem_t mem;
   4782     int       bucket_index;
   4783     int       tcam_index = -1;
   4784     void      *bufp;
   4785     int       vrf_id, vrf;
   4786     int       ipv6, pfx;
   4787     int       rv = SOC_E_NONE;
   4788     int       ipmc_route = 0;
   4789     int       flex_v6_64 = 0;
   4790     int       flex = 0;
   4791 
   4792     ipv6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0f);
   4793 
   4794     /* If the entry is override, then insert into TCAM directly */
   4795     SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   4796 
   4797     /* First launch lookup directly into tcam. If hit comes from override
   4798      * vrf just return it. Else launch lookup into alpm pivots
   4799      */
   4800     /* For VRF_OVERRIDE (Global High) entries, software needs to maintain the
   4801      * index */
   4802     /* Prefix resides in TCAM directly */
   4803 
   4804     /* search in the hash table */
   4805     *index_ptr = 0;
   4806     rv = _soc_alpm_lpm_match(u, key_data, e, index_ptr, &pfx, &ipv6);
   4807     /*
   4808      * If entry is ipv4 copy to the "zero" half of the,
   4809      * buffer, "zero" half of e if the  original entry
   4810      * is in the "one" half.
   4811      */
   4812     flex = VRF_FLEX_IS_SET(u, vrf_id, vrf, ipv6, 0);
   4813     if (SOC_SUCCESS(rv)) {
   4814         if (!ipv6 && (*index_ptr & 0x1)) {
   4815             rv = soc_alpm_lpm_ip4entry1_to_0(u, e, e, PRESERVE_HIT);
   4816         }
   4817         if (soc_feature(u, soc_feature_ipmc_defip)) {
   4818             ipmc_route = soc_mem_field32_get(u, L3_DEFIPm, e, MULTICAST_ROUTE0f);
   4819         }
   4820 
   4821         if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && ipv6 && flex) {
   4822             if (soc_mem_field32_get(u, L3_DEFIPm, key_data, IP_ADDR_MASK0f) == 0xFFFFFFFF &&
   4823                 soc_mem_field32_get(u, L3_DEFIPm, key_data, IP_ADDR_MASK1f) == 0xFFFFFFFF) {
   4824                 flex_v6_64 = 1;
   4825             }
   4826         }
   4827     }
   4828     if ((vrf_id == SOC_L3_VRF_OVERRIDE) || (ipmc_route) || (flex_v6_64)) {
   4829         *cookie = 0;
   4830         if (SOC_SUCCESS(rv)) {
   4831             *cookie |= SOC_ALPM_LPM_LOOKUP_HIT;
   4832         }
   4833         return rv;
   4834     }
   4835 
   4836     /* either no hit in OVERRIDE or hit in pivot tcam */
   4837     /* non override entries, go to into ALPM memory */
   4838     if (!VRF_TRIE_INIT_COMPLETED(u, vrf, ipv6)) {
   4839         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   4840                     (BSL_META_U(u,
   4841                                 "soc_alpm_lookup:VRF %d is not initialized\n"),
   4842                      vrf));
   4843         *cookie = 0;
   4844         return SOC_E_NOT_FOUND;
   4845     }
   4846     /* Get table memory. */
   4847     SOC_ALPM_TABLE_MEM(u, ipv6, mem, flex);
   4848 
   4849     /* Assign entry buf based on table being used */
   4850     SOC_ALPM_ENTRY_BUF(ipv6, mem, bufp, alpmv4_entry, alpmv6_entry);
   4851 
   4852     SOC_ALPM_LPM_LOCK(u);
   4853     /* Find and update the entry */
   4854     rv = _soc_alpm_find(u, key_data, mem, bufp, &tcam_index, &bucket_index,
   4855                         index_ptr, SOC_ALPM_SW_LOOKUP(u));
   4856     SOC_ALPM_LPM_UNLOCK(u);
   4857 
   4858     if (SOC_FAILURE(rv)) {
   4859         *cookie = tcam_index;
   4860         *index_ptr = bucket_index << 2;
   4861         return rv;
   4862     }
   4863     /* Copy ALPM memory to LPM entry */
   4864     rv =  _soc_alpm_lpm_ent_init(u, bufp, mem, ipv6, vrf_id,
   4865                                  bucket_index, *index_ptr, e, flex);
   4866     *cookie = SOC_ALPM_LOOKUP_HIT | tcam_index;
   4867     if (flex) {
   4868         *cookie |= SOC_ALPM_COOKIE_FLEX;
   4869     }
   4870     return(rv);
   4871 }
   4872 
   4873 /* Find a LPM Global low or VRF route in ALPM memory */
   4874 static int
   4875 _soc_alpm_find_best_match(int u,
   4876                           void *key_data,
   4877                           void *e,          /* return entry data if found */
   4878                           int vrf_id,
   4879                           int *tcam_index,
   4880                           int *bucket_index,
   4881                           int *key_index,
   4882                           int do_urpf)
   4883 {
   4884     int rv = SOC_E_NONE;
   4885     int i, j, v6, hit = 0;
   4886     uint32 db_type, ent_type, bank_disable;
   4887     defip_aux_scratch_entry_t aux_entry;
   4888     int global, mvrf, vrf;
   4889     int index;
   4890     soc_mem_t mem, lpm_mem;
   4891     int hw_len, sw_len;
   4892     int ent_num;
   4893 
   4894     /* Used for keeping Longest Matched entry in Bucket */
   4895     uint32  alpm_bufp[SOC_MAX_MEM_FIELD_WORDS] = {0};
   4896     int     alpm_len = -1;
   4897     int     alpm_index = 0;
   4898     int     flex;
   4899 
   4900     soc_field_t ip_addr_fld[2] = {
   4901         IP_ADDR0f,
   4902         IP_ADDR1f,
   4903     };
   4904 
   4905     lpm_mem = L3_DEFIPm;
   4906     v6 = soc_mem_field32_get(u, lpm_mem, key_data, MODE0f);
   4907     global = soc_mem_field32_get(u, lpm_mem, key_data, GLOBAL_ROUTE0f);
   4908     mvrf = soc_mem_field32_get(u, lpm_mem, key_data, VRF_ID_0f);
   4909     vrf = (vrf_id == SOC_L3_VRF_GLOBAL) ? (SOC_VRF_MAX(u) + 1) : mvrf;
   4910 
   4911     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   4912                 (BSL_META_U(u,
   4913                 "Prefare AUX Scratch for searching TCAM in "
   4914                 "%s region, Key data: v6 %d global %d vrf %d:\n"),
   4915                 vrf_id == SOC_L3_VRF_GLOBAL ? "Global" : "VRF",
   4916                 v6, global, mvrf));
   4917     soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
   4918     if (do_urpf) {
   4919         db_type ++;
   4920     }
   4921     if (vrf_id == SOC_L3_VRF_GLOBAL) {
   4922         /* Crack these value to use _fill_aux routine */
   4923         soc_mem_field32_set(u, lpm_mem, key_data, GLOBAL_ROUTE0f, 1);
   4924         soc_mem_field32_set(u, lpm_mem, key_data, VRF_ID_0f, 0);
   4925     }
   4926 
   4927     bank_disable = soc_alpm_bank_dis(u, vrf);
   4928 
   4929     SOC_IF_ERROR_RETURN(
   4930         _soc_alpm_fill_aux_entry_for_op(u, key_data, v6, db_type, ent_type,
   4931                                         0, &aux_entry));
   4932     /* Recover to original value */
   4933     if (vrf_id == SOC_L3_VRF_GLOBAL) {
   4934         soc_mem_field32_set(u, lpm_mem, key_data, GLOBAL_ROUTE0f, global);
   4935         soc_mem_field32_set(u, lpm_mem, key_data, VRF_ID_0f, mvrf);
   4936     }
   4937 
   4938     /* Start shadow table engine to search */
   4939     SOC_IF_ERROR_RETURN(
   4940         _soc_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry, TRUE, &hit, tcam_index,
   4941                          bucket_index, 0));
   4942 
   4943     if (hit == 0) {
   4944         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   4945                     (BSL_META_U(u,"Could not find bucket\n")));
   4946         return SOC_E_NOT_FOUND;
   4947     }
   4948 
   4949     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   4950                 (BSL_META_U(u, "Hit in memory %s, index %d, "
   4951                 "bucket_index %d\n"), SOC_MEM_NAME(u, lpm_mem),
   4952                 soc_alpm_logical_idx(u, lpm_mem, (*tcam_index) >> 1, 1),
   4953                 *bucket_index));
   4954 
   4955     /* Found, check ALPM bucket */
   4956     flex = VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 0);
   4957     SOC_ALPM_TABLE_MEM(u, v6, mem, flex);
   4958     rv = _soc_alpm_mask_len_get(u, v6, key_data, &sw_len);
   4959     if (SOC_FAILURE(rv)) {
   4960         return rv;
   4961     }
   4962 
   4963     if (v6) {
   4964         if (flex) {
   4965             ent_num = ALPM_IPV6_64_BKT_COUNT_FLEX;
   4966         } else {
   4967             ent_num = ALPM_IPV6_64_BKT_COUNT;
   4968         }
   4969     } else {
   4970         if (flex) {
   4971             ent_num = ALPM_IPV4_BKT_COUNT_FLEX;
   4972         } else {
   4973             ent_num = ALPM_IPV4_BKT_COUNT;
   4974         }
   4975     }
   4976     if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) {
   4977         ent_num <<= 1;
   4978     }
   4979 
   4980     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   4981                 (BSL_META_U(u, "Start searching mem %s bucket %d(count %d) "
   4982                 "for Length %d\n"),
   4983                 SOC_MEM_NAME(u, mem), *bucket_index, ent_num, sw_len));
   4984 
   4985     for (i = 0; i < ent_num; i++) {
   4986         uint32 bufp[SOC_MAX_MEM_FIELD_WORDS] = {0};
   4987         uint32 mask[2] = {0};
   4988         uint32 hkey[2] = {0};
   4989         uint32 skey[2] = {0};
   4990         int valid;
   4991 
   4992         rv = _soc_alpm_mem_index(u, mem, *bucket_index, i, bank_disable, &index);
   4993         if (rv == SOC_E_FULL) {
   4994             continue;
   4995         }
   4996 
   4997         SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY,
   4998                                                index, (void *)bufp));
   4999         valid = soc_mem_field32_get(u, mem, bufp, VALIDf);
   5000         hw_len = soc_mem_field32_get(u, mem, bufp, LENGTHf);
   5001 
   5002         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   5003                     (BSL_META_U(u, "Bucket %5d Index %6d: Valid %d, Length %d\n"),
   5004                     *bucket_index, index, valid, hw_len));
   5005 
   5006         if (!valid || (hw_len > sw_len)) {
   5007             continue;
   5008         }
   5009 
   5010         /* Length in ALPM <= given length */
   5011         SHR_BITSET_RANGE(mask, (v6 ? 64 : 32) - hw_len, hw_len);
   5012         (void)soc_mem_field_get(u, mem, (uint32 *)bufp, KEYf, (uint32 *)hkey);
   5013         skey[1] = soc_mem_field32_get(u, lpm_mem, key_data, ip_addr_fld[1]);
   5014         skey[0] = soc_mem_field32_get(u, lpm_mem, key_data, ip_addr_fld[0]);
   5015 
   5016         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   5017                     (BSL_META_U(u, "\tmask %08x %08x\n\t key %08x %08x\n"
   5018                     "\thost %08x %08x\n"),
   5019                     mask[1], mask[0], hkey[1], hkey[0], skey[1], skey[0]));
   5020 
   5021         for (j = v6 ? 1 : 0; j >= 0; j--) {
   5022             if ((skey[j] & mask[j]) != (hkey[j] & mask[j])) {
   5023                 break;
   5024             }
   5025         }
   5026 
   5027         /* Hardware key doesn't match to software key */
   5028         if (j >= 0) {
   5029             continue;
   5030         }
   5031 
   5032         /* Matched, store and keep searching,
   5033          * could be Longer prefix in following entries */
   5034         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   5035                     (BSL_META_U(u, "Found a match in mem %s bucket %d, "
   5036                     "index %d\n"), SOC_MEM_NAME(u, mem), *bucket_index, index));
   5037 
   5038         /* Keep longest matched route */
   5039         if (alpm_len == -1 || alpm_len < hw_len) {
   5040             alpm_len = hw_len;
   5041             alpm_index = index;
   5042             sal_memcpy(alpm_bufp, bufp, sizeof(bufp));
   5043         }
   5044     }
   5045 
   5046     /* Found */
   5047     if (alpm_len != -1) {
   5048         rv = _soc_alpm_lpm_ent_init(u, alpm_bufp, mem, v6, vrf_id, *bucket_index,
   5049                                     alpm_index, e, flex);
   5050         if (SOC_SUCCESS(rv)) {
   5051             *key_index = alpm_index;
   5052             if (bsl_check(bslLayerSoc, bslSourceAlpm, bslSeverityVerbose, u)) {
   5053                 LOG_VERBOSE(BSL_LS_SOC_ALPM,
   5054                             (BSL_META_U(u, "Hit mem %s bucket %d, index %d\n"),
   5055                             SOC_MEM_NAME(u, mem), *bucket_index, alpm_index));
   5056             }
   5057         }
   5058         return rv;
   5059     }
   5060 
   5061     /* Missed */
   5062     *key_index = soc_alpm_logical_idx(u, lpm_mem, (*tcam_index) >> 1, 1);
   5063     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   5064                 (BSL_META_U(u,"Miss in mem %s bucket %d, use associate data "
   5065                 "in mem %s LOG index %d\n"), SOC_MEM_NAME(u, mem), *bucket_index,
   5066                 SOC_MEM_NAME(u, lpm_mem), *key_index));
   5067     
   5068     /* Miss in bucket, use associate data */
   5069     SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY,
   5070                                            *key_index, (void *)e));
   5071     if ((!v6) && ((*tcam_index) & 1)) {
   5072         /* move entry to 0 half */
   5073         rv = soc_alpm_lpm_ip4entry1_to_0(u, e, e, PRESERVE_HIT);
   5074     }
   5075 
   5076     return SOC_E_NONE;
   5077 }
   5078 
   5079 /*
   5080  * soc_alpm_find_best_match
   5081  *
   5082  * It's an indenpendent routine, to simalute HW process for incoming packets.
   5083  * Considering possible mismatch between SW and HW, we need to go through
   5084  * hardware for lookup regardless of software state.
   5085  */
   5086 int
   5087 soc_alpm_find_best_match(int u,
   5088                          void *key_data,
   5089                          void *e,           /* return entry data if found */
   5090                          int *index_ptr,
   5091                          int do_urpf)
   5092 {
   5093     int rv = SOC_E_NONE;
   5094     int i, index_min, index_cnt;
   5095     defip_entry_t lpm_ent;
   5096     uint32 mem_mask[2];
   5097     uint32 mem_addr[2];
   5098     uint32 mask[2];
   5099     uint32 addr[2];
   5100     uint32 glb_hi, glb_rt;
   5101 
   5102     int vrf_id, vrf = 0;
   5103     int vld[2] = {0};
   5104     int tcam_index, bucket_index;
   5105     soc_mem_t lpm_mem = L3_DEFIPm;
   5106     int ent, v6, hw_v6, match = 0;
   5107     int flex_v6_64;
   5108 
   5109     soc_field_t glb_hi_fld[] = {
   5110         GLOBAL_HIGH0f,
   5111         GLOBAL_HIGH1f
   5112     };
   5113     soc_field_t glb_rt_fld[] = {
   5114         GLOBAL_ROUTE0f,
   5115         GLOBAL_ROUTE1f
   5116     };
   5117 
   5118     v6 = soc_mem_field32_get(u, lpm_mem, key_data, MODE0f);
   5119     if (!SOC_URPF_STATUS_GET(u) && do_urpf) {
   5120         return SOC_E_PARAM;
   5121     }
   5122 
   5123     /* Since L3_DEFIP_* tables are not support for DMA,
   5124      * we do PIO search instead */
   5125     index_min = soc_mem_index_min(u, lpm_mem);
   5126     index_cnt = soc_mem_index_count(u, lpm_mem);
   5127     if (SOC_URPF_STATUS_GET(u)) {
   5128         index_cnt >>= 1;
   5129     }
   5130     /* in Parallel mode search from second half */
   5131     if (soc_alpm_mode_get(u)) {
   5132         index_cnt >>= 1;
   5133         index_min += index_cnt;
   5134     }
   5135 
   5136     if (do_urpf) {
   5137         index_min += soc_mem_index_count(u, lpm_mem) / 2;
   5138     }
   5139 
   5140     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   5141                 (BSL_META_U(u, "Launch LPM searching from index %d count %d\n"),
   5142                 index_min, index_cnt));
   5143 
   5144     mask[0] = soc_mem_field32_get(u, lpm_mem, key_data, IP_ADDR_MASK0f);
   5145     mask[1] = soc_mem_field32_get(u, lpm_mem, key_data, IP_ADDR_MASK1f);
   5146     addr[0] = soc_mem_field32_get(u, lpm_mem, key_data, IP_ADDR0f);
   5147     addr[1] = soc_mem_field32_get(u, lpm_mem, key_data, IP_ADDR1f);
   5148 
   5149     /* Scanning for Global High routes */
   5150     for (i = index_min; i < index_min + index_cnt; i++) {
   5151         SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY,
   5152                             i, (void *)&lpm_ent));
   5153         vld[0] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, VALID0f);
   5154         vld[1] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, VALID1f);
   5155         if (vld[0] == 0 && vld[1] == 0) {
   5156             continue;
   5157         }
   5158 
   5159         hw_v6 = soc_mem_field32_get(u, lpm_mem, &lpm_ent, MODE0f);
   5160         if (hw_v6 != v6) {
   5161             continue;
   5162         }
   5163 
   5164         for (ent = 0; ent < (v6 ? 1 : 2); ent++) {
   5165             if (vld[ent] == 0) {
   5166                 continue;
   5167             }
   5168             glb_hi = soc_mem_field32_get(u, lpm_mem, &lpm_ent, glb_hi_fld[ent]);
   5169             glb_rt = soc_mem_field32_get(u, lpm_mem, &lpm_ent, glb_rt_fld[ent]);
   5170             flex_v6_64 = 0;
   5171             if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && v6 &&
   5172                 soc_mem_field32_get(u, lpm_mem, &lpm_ent, ENTRY_VIEW0f)) {
   5173                 if (soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR_MASK0f) == 0xFFFFFFFF &&
   5174                     soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR_MASK1f) == 0xFFFFFFFF) {
   5175                     flex_v6_64 = 1;
   5176                 }
   5177             }
   5178 
   5179             /* No need to compare key if not Global High route */
   5180             if (!(glb_hi && glb_rt) && !flex_v6_64) {
   5181                 continue;
   5182             }
   5183 
   5184             LOG_VERBOSE(BSL_LS_SOC_ALPM,
   5185                         (BSL_META_U(u, "Match a Global High route: ent %d\n"),
   5186                         ent));
   5187 
   5188             mem_mask[0] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR_MASK0f);
   5189             mem_mask[1] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR_MASK1f);
   5190             mem_addr[0] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR0f);
   5191             mem_addr[1] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR1f);
   5192 
   5193             LOG_VERBOSE(BSL_LS_SOC_ALPM,
   5194                         (BSL_META_U(u, "\thmsk %08x %08x\n\thkey %08x %08x\n"
   5195                         "\tsmsk %08x %08x\n\tskey %08x %08x\n"),
   5196                         mem_mask[1], mem_mask[0], mem_addr[1], mem_addr[0],
   5197                         mask[1], mask[0], addr[1], addr[0]));
   5198 
   5199             /* match condition: mem mask equal to or shorten than match mask
   5200              *                  mem masked addrs are equal.
   5201              */
   5202             if (v6) {
   5203                 match = (mem_mask[1] <= mask[1] && mem_mask[0] <= mask[0] &&
   5204                         ((addr[0] & mem_mask[0]) == (mem_addr[0] & mem_mask[0])) &&
   5205                         ((addr[1] & mem_mask[1]) == (mem_addr[1] & mem_mask[1])));
   5206             } else {
   5207                 match = (mem_mask[ent] <= mask[0] &&
   5208                          ((addr[0] & mem_mask[ent]) == (mem_addr[ent] & mem_mask[ent])));
   5209             }
   5210             if (match) {
   5211                 /* Found, all Key matched */
   5212                 LOG_VERBOSE(BSL_LS_SOC_ALPM,
   5213                             (BSL_META_U(u,"Hit Global High route in index = %d(%d)\n"),
   5214                             i, ent));
   5215                 sal_memcpy(e, &lpm_ent, sizeof(lpm_ent));
   5216                 if (!v6 && ent == 1) {
   5217                     /* ent == 1 indicate it's sencond half of the entry */
   5218                     rv = soc_alpm_lpm_ip4entry1_to_0(u, e, e, PRESERVE_HIT);
   5219                 }
   5220                 *index_ptr = i;
   5221                 return rv;
   5222             }
   5223         }
   5224     }
   5225 
   5226     /* Global High lookup miss, use AUX to search Global Low and VRF route */
   5227     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   5228                 (BSL_META_U(u,"Global high lookup miss, use AUX engine to "
   5229                 "search for VRF and Global Low routes\n")));
   5230 
   5231     /* Fill in AUX Scratch and perform PREFIX Operation */
   5232     SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   5233     rv = _soc_alpm_find_best_match(u, key_data, e, vrf_id, &tcam_index,
   5234                                    &bucket_index, index_ptr, do_urpf);
   5235     if (rv == SOC_E_NOT_FOUND) {
   5236         vrf = SOC_L3_VRF_GLOBAL;
   5237         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   5238                     (BSL_META_U(u,"Not found in VRF region, trying Global "
   5239                     "region\n")));
   5240         rv = _soc_alpm_find_best_match(u, key_data, e, vrf_id, &tcam_index,
   5241                                        &bucket_index, index_ptr, do_urpf);
   5242     }
   5243 
   5244     if (SOC_SUCCESS(rv)) {
   5245         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   5246                     (BSL_META_U(u,"Hit in %s region in TCAM index %d, "
   5247                     "buckekt_index %d\n"),
   5248                     vrf == SOC_L3_VRF_GLOBAL ? "Global Low" : "VRF",
   5249                     tcam_index, bucket_index));
   5250     } else {
   5251         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   5252                     (BSL_META_U(u,"Search miss for given address\n")));
   5253     }
   5254 
   5255     return(rv);
   5256 }
   5257 
   5258 
   5259 /*
   5260  * soc_alpm_delete
   5261  */
   5262 int
   5263 soc_alpm_delete(int u, void *key_data, int bkt_idx, int pivot_info)
   5264 {
   5265     int       vrf_id, vrf;
   5266     int       ipv6;
   5267     int       rv = SOC_E_NONE;
   5268     int       propagate = 0;
   5269     int       ipmc_route = 0;
   5270     int       flex_v6_64 = 0;
   5271 
   5272     ipv6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0f);
   5273 
   5274     if (soc_feature(u, soc_feature_ipmc_defip)) {
   5275         ipmc_route = soc_mem_field32_get(u, L3_DEFIPm, key_data, MULTICAST_ROUTE0f);
   5276     }
   5277     /* If the entry is override, then Lookup into TCAM directly */
   5278     SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   5279 
   5280     if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && ipv6 &&
   5281         VRF_FLEX_IS_SET(u, vrf_id, vrf, ipv6, 0)) {
   5282         if (soc_mem_field32_get(u, L3_DEFIPm, key_data, IP_ADDR_MASK0f) == 0xFFFFFFFF &&
   5283             soc_mem_field32_get(u, L3_DEFIPm, key_data, IP_ADDR_MASK1f) == 0xFFFFFFFF) {
   5284             flex_v6_64 = 1;
   5285         }
   5286     }
   5287 
   5288     /* For VRF_OVERRIDE (Global High) entries, and IPMC route
   5289      * software needs to maintain the index
   5290      */
   5291     /* Prefix resides in TCAM directly */
   5292     if ((vrf_id == SOC_L3_VRF_OVERRIDE) || (ipmc_route) || (flex_v6_64)) {
   5293         /* TCAM Direct lookup */
   5294         /* search in the hash table */
   5295         rv = soc_alpm_lpm_delete(u, key_data);
   5296         if (SOC_SUCCESS(rv)) {
   5297             VRF_TRIE_ROUTES_DEC(u, vrf_id, vrf, ipv6);
   5298         }
   5299         return(rv);
   5300     } else { /* non override entries, go to into ALPM memory */
   5301         int tcam_index;
   5302         if (!VRF_TRIE_INIT_COMPLETED(u, vrf, ipv6)) {
   5303             LOG_VERBOSE(BSL_LS_SOC_ALPM,
   5304                         (BSL_META_U(u,
   5305                                     "soc_alpm_delete:VRF %d/%d is not initialized\n"),
   5306                          vrf, ipv6));
   5307             return SOC_E_NONE;
   5308         }
   5309         if (bkt_idx == -1) {
   5310             /* internally 0 is invalid bucket index */
   5311             bkt_idx = 0;
   5312         }
   5313         /* deleting all skip propagation to reduce overall time */
   5314         propagate = !(pivot_info & SOC_ALPM_DELETE_ALL);
   5315         tcam_index = pivot_info & SOC_ALPM_TCAM_INDEX_MASK;
   5316         rv = _soc_alpm_delete(u, key_data, SOC_ALPM_BKT_ENTRY_TO_IDX(bkt_idx),
   5317                               tcam_index, bkt_idx,
   5318                               propagate);
   5319     }
   5320     return(rv);
   5321 }
   5322 
   5323 
   5324 /* Initialize shared bucket management */
   5325 static int
   5326 soc_alpm_shared_mem_init(int u)
   5327 {
   5328     int defip_table_size;
   5329 
   5330     /* Maximm number of IPv4 pivots */
   5331     SOC_ALPM_BUCKET_COUNT(u) = SOC_TD2_ALPM_MAX_BKTS;
   5332 
   5333     if (SOC_URPF_STATUS_GET(u)) {
   5334         /* remaining half buckets are the src buckets */
   5335         SOC_ALPM_BUCKET_COUNT(u) >>= 1;
   5336     }
   5337 
   5338     /* number bytes to manage the max buckets */
   5339     SOC_ALPM_BUCKET_BMAP_SIZE(u) = SHR_BITALLOCSIZE(SOC_ALPM_BUCKET_COUNT(u));
   5340 
   5341     SOC_ALPM_BUCKET_BMAP(u) =
   5342              sal_alloc(SOC_ALPM_BUCKET_BMAP_SIZE(u),
   5343                        "alpm_shared_bucket_bitmap");
   5344     if (SOC_ALPM_BUCKET_BMAP(u) == NULL) {
   5345         LOG_WARN(BSL_LS_SOC_ALPM,
   5346                  (BSL_META_U(u,
   5347                              "soc_alpm_shared_mem_init: Memory allocation for "
   5348                              "bucket bitmap management failed\n")));
   5349         return SOC_E_MEMORY;
   5350     }
   5351 
   5352     /* Mark all buckets as free */
   5353     sal_memset(SOC_ALPM_BUCKET_BMAP(u), 0, SOC_ALPM_BUCKET_BMAP_SIZE(u));
   5354 
   5355     /* Bucket 0 is reserved. Just assign it */
   5356     alpm_bucket_assign(u, 1, &defip_table_size);
   5357     return SOC_E_NONE;
   5358 }
   5359 
   5360 STATIC int
   5361 _soc_alpm_lpm_free_entries(int u, soc_mem_t mem, int vrf)
   5362 {
   5363     int curr_pfx, min_pfx;
   5364     int total_fent = 0;
   5365 
   5366     if (mem == L3_DEFIP_ALPM_IPV6_128m) {
   5367         return _soc_alpm_128_lpm_free_entries(u, vrf);
   5368     }
   5369 
   5370     curr_pfx = ALPM_MAX_PFX_INDEX;
   5371     min_pfx  = 0;
   5372     if (soc_alpm_mode_get(u) == SOC_ALPM_MODE_PARALLEL) {
   5373         if (vrf == (SOC_VRF_MAX(u) + 1)) { /* Global VRF */
   5374             min_pfx  = ALPM_MAX_VRF_PFX_INDEX + 1;
   5375         } else {
   5376             curr_pfx = ALPM_MAX_VRF_PFX_INDEX;
   5377         }
   5378     }
   5379     while (curr_pfx >= min_pfx) {
   5380         total_fent += SOC_ALPM_LPM_STATE_FENT(u, curr_pfx);
   5381         curr_pfx = SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx);
   5382     }
   5383     return total_fent;
   5384 }
   5385 
   5386 
   5387 /* Connect TCAM entry to a bucket ID */
   5388 STATIC int
   5389 _soc_alpm_bucket_link(int u, int v6, int pivot_index, int bucket_index)
   5390 {
   5391     int             rv = SOC_E_NONE;
   5392     int             lpm_index;
   5393     soc_mem_t       lpm_mem = L3_DEFIPm;
   5394     defip_entry_t   lpm_entry;
   5395 
   5396     /* Connect TCAM entry to new bucket */
   5397     lpm_index = soc_alpm_logical_idx(u, lpm_mem, pivot_index >> 1, 1);
   5398 
   5399     rv = _soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY, lpm_index, &lpm_entry);
   5400     SOC_IF_ERROR_RETURN(rv);
   5401     if ((!v6) && (pivot_index & 1)) {
   5402         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, &lpm_entry, ALG_BKT_PTR1f, bucket_index);
   5403     } else {
   5404         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, &lpm_entry, ALG_BKT_PTR0f, bucket_index);
   5405     }
   5406     rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, lpm_index, &lpm_entry);
   5407     SOC_IF_ERROR_RETURN(rv);
   5408 
   5409     if (SOC_URPF_STATUS_GET(u)) {
   5410         int _urpf_index = lpm_index + (soc_mem_index_count(u, lpm_mem) >> 1);
   5411         rv = _soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY,
   5412                                 _urpf_index, &lpm_entry);
   5413         SOC_IF_ERROR_RETURN(rv);
   5414 
   5415         if ((!v6) && (pivot_index & 1)) {
   5416             soc_mem_field32_set(u, lpm_mem, &lpm_entry, ALG_BKT_PTR1f,
   5417                                 bucket_index + SOC_ALPM_BUCKET_COUNT(u));
   5418         } else {
   5419             soc_mem_field32_set(u, lpm_mem, &lpm_entry, ALG_BKT_PTR0f,
   5420                                 bucket_index + SOC_ALPM_BUCKET_COUNT(u));
   5421         }
   5422 
   5423         rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, _urpf_index, &lpm_entry);
   5424         SOC_IF_ERROR_RETURN(rv);
   5425     }
   5426 
   5427     return rv;
   5428 }
   5429 
   5430 
   5431 /* Merge entries from one logical bucket to another */
   5432 static int
   5433 _soc_alpm_bucket_merge(int u, soc_mem_t mem, int pivot_idx_from, int pivot_idx_to,
   5434                        soc_alpm_merge_type_t merge_dir, int *shuffled)
   5435 {
   5436     int                     *new_index = NULL;
   5437     int                     rv = SOC_E_NONE;
   5438     int                     bucket_index_from, bucket_index_to;
   5439     int                     v6, i;
   5440     int                     vrf = 0;
   5441     alpm_mem_prefix_array_t *pfx_array = NULL;
   5442     defip_entry_t           lpm_entry;
   5443     alpm_pivot_t            *from_pivot, *to_pivot;
   5444     alpm_pivot_t            *parent_pivot = NULL, *child_pivot = NULL;
   5445     uint32                  bank_disable;
   5446     enum {
   5447         _MERGE_NONE,
   5448         _MERGE_PREPARE,
   5449         _MERGE_COPY,
   5450         _MERGE_LPM_LINK,
   5451         _MERGE_INVALIDATE,
   5452         _MERGE_CHILD_TRIE_MERGED,
   5453         _MERGE_CHILD_LPM_DELETED,
   5454         _MERGE_CHILD_PIVOT_DESTROYED
   5455     } doing = _MERGE_NONE, done = _MERGE_NONE;
   5456     void                    *raw_bkt[RAW_BKT_NUM] = {0};
   5457     v6 = (L3_DEFIP_ALPM_IPV6_64m == mem ||
   5458           L3_DEFIP_ALPM_IPV6_64_1m == mem ||
   5459           L3_DEFIP_ALPM_IPV6_128m == mem);
   5460 
   5461     from_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_from);
   5462     to_pivot   = ALPM_TCAM_PIVOT(u, pivot_idx_to);
   5463 
   5464     bucket_index_from = PIVOT_BUCKET_INDEX(from_pivot);
   5465     bucket_index_to   = PIVOT_BUCKET_INDEX(to_pivot);
   5466 
   5467     vrf = PIVOT_BUCKET_VRF(from_pivot);
   5468     bank_disable = soc_alpm_bank_dis(u, vrf);
   5469 
   5470     /**
   5471      * Invalidate need to happen only after all the entries are
   5472      * written to the new pivot and the new pivot is valid. Otherwise
   5473      * there is a chance of MISS.
   5474      *
   5475      * hitless move:
   5476      * - Copy entries to new bucket.
   5477      * - activate new pivot
   5478      * - delete entries from old bucket
   5479      */
   5480 
   5481     doing = _MERGE_PREPARE;
   5482     rv = _soc_alpm_raw_bucket_prepare(u, mem, PIVOT_BUCKET_TRIE(from_pivot),
   5483                                       bucket_index_from, bucket_index_to,
   5484                                       bank_disable, NULL, NULL,
   5485                                       &pfx_array, raw_bkt, &new_index, NULL, 1);
   5486     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5487 
   5488     doing = _MERGE_COPY;
   5489     rv = _soc_alpm_raw_bucket_copy(u, mem, bucket_index_to,
   5490                                    bank_disable, raw_bkt[RAW_NEW_BKT_DIP],
   5491                                    raw_bkt[RAW_NEW_BKT_SIP],
   5492                                    new_index, pfx_array->count);
   5493     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5494 
   5495     /* Connect TCAM entry to new bucket.
   5496      * This is a must step even for merge child to parent
   5497      */
   5498     doing = _MERGE_LPM_LINK;
   5499     rv = _soc_alpm_bucket_link(u, v6, pivot_idx_from, bucket_index_to);
   5500     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5501 
   5502     /* Invalide old entries */
   5503     doing = _MERGE_INVALIDATE;
   5504     rv = _soc_alpm_raw_bucket_inval(u, mem, bucket_index_from,
   5505                                     bank_disable,
   5506                                     raw_bkt[RAW_OLD_BKT_DIP],
   5507                                     raw_bkt[RAW_OLD_BKT_SIP],
   5508                                     raw_bkt[RAW_RB_BKT_DIP],
   5509                                     raw_bkt[RAW_RB_BKT_SIP]);
   5510     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5511 
   5512     if (merge_dir != MERGE_PHY) {
   5513         uint32          hw_key[5] = {0};
   5514         int             child_vrf;
   5515 
   5516         if (merge_dir == MERGE_LOG_PARENT_TO_CHILD) {
   5517             parent_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_from);
   5518             child_pivot  = ALPM_TCAM_PIVOT(u, pivot_idx_to);
   5519         } else if (merge_dir == MERGE_LOG_CHILD_TO_PARENT) {
   5520             child_pivot  = ALPM_TCAM_PIVOT(u, pivot_idx_from);
   5521             parent_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_to);
   5522         }
   5523 
   5524         /* SW bucket merge: not expect to fail */
   5525         doing = _MERGE_CHILD_TRIE_MERGED;
   5526         rv = trie_merge(PIVOT_BUCKET_TRIE(parent_pivot),
   5527                         PIVOT_BUCKET_TRIE(child_pivot)->trie,
   5528                         child_pivot->key,
   5529                         child_pivot->len);
   5530         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5531 
   5532         sal_memcpy(hw_key, child_pivot->key, sizeof(hw_key));
   5533         ALPM_TRIE_TO_NORMAL_IP(hw_key, child_pivot->len, v6);
   5534 
   5535         child_vrf = PIVOT_BUCKET_VRF(child_pivot);
   5536 
   5537         (void) _soc_alpm_lpm_ent_key_init(u, hw_key, child_pivot->len,
   5538                                           child_vrf, v6, &lpm_entry, 1);
   5539 
   5540         /* Delete child lpm entry from TCAM */
   5541         doing = _MERGE_CHILD_LPM_DELETED;
   5542         rv = soc_alpm_lpm_delete(u, &lpm_entry);
   5543         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5544         if (shuffled) {
   5545             *shuffled = 1;
   5546         }
   5547 
   5548         /* Destroy child pivot from trie */
   5549         doing = _MERGE_CHILD_PIVOT_DESTROYED;
   5550         rv = _soc_alpm_split_pivot_create_undo
   5551                     (u, v6, child_vrf, child_pivot->key, child_pivot->len, NULL, 0);
   5552 
   5553         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5554     }
   5555 
   5556     /* Update TCAM mgmt info: set new logical bucket */
   5557     if (merge_dir != MERGE_LOG_CHILD_TO_PARENT && ALPM_TCAM_PIVOT(u, pivot_idx_from)) {
   5558         PIVOT_BUCKET_INDEX(ALPM_TCAM_PIVOT(u, pivot_idx_from)) = bucket_index_to;
   5559     }
   5560 
   5561     alpm_bucket_release(u, bucket_index_from, v6);
   5562 
   5563     /* Update new index */
   5564     for (i = 0; i < pfx_array->count; i++) {
   5565         pfx_array->prefix[i]->index = new_index[i];
   5566     }
   5567 
   5568     _soc_alpm_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index);
   5569     return rv;
   5570 
   5571 _rollback:
   5572 
   5573     /* fall through on all cases */
   5574     switch (done)  {
   5575     case _MERGE_CHILD_LPM_DELETED:
   5576         if (merge_dir != MERGE_PHY) {
   5577             /* not expecting any failure after lpm deleted */
   5578         }
   5579 
   5580     case _MERGE_CHILD_TRIE_MERGED:
   5581         if (merge_dir != MERGE_PHY) {
   5582             uint32      pivot[5], length;
   5583             trie_split2(PIVOT_BUCKET_TRIE(parent_pivot),
   5584                         child_pivot->key,
   5585                         child_pivot->len,
   5586                         pivot, &length,
   5587                         &(PIVOT_BUCKET_TRIE(child_pivot)->trie),
   5588                         PIVOT_BUCKET_COUNT(child_pivot),
   5589                         1);
   5590         }
   5591 
   5592     case _MERGE_INVALIDATE:
   5593         _soc_alpm_raw_bucket_inval_undo(u, mem, bucket_index_from,
   5594                                         bank_disable,
   5595                                         raw_bkt[RAW_RB_BKT_DIP],
   5596                                         raw_bkt[RAW_RB_BKT_SIP]);
   5597 
   5598     case _MERGE_LPM_LINK:
   5599         /* Connect TCAM back to original bucket */
   5600         _soc_alpm_bucket_link(u, v6, pivot_idx_from, bucket_index_from);
   5601 
   5602     case _MERGE_COPY:
   5603         /* Delete entries in new bucket */
   5604         _soc_alpm_raw_bucket_copy_undo(u, mem, bucket_index_to, bank_disable,
   5605                                        raw_bkt[RAW_NEW_BKT_DIP],
   5606                                        raw_bkt[RAW_NEW_BKT_SIP], new_index,
   5607                                        pfx_array->count);
   5608 
   5609     case _MERGE_PREPARE:
   5610         _soc_alpm_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index);
   5611 
   5612     case _MERGE_NONE:
   5613     default:
   5614         break;
   5615     }
   5616 
   5617     /* Error dump */
   5618     switch (doing)  {
   5619     case _MERGE_LPM_LINK:
   5620         LOG_ERROR(BSL_LS_SOC_ALPM,
   5621                   (BSL_META_U(u,
   5622                               "_soc_alpm_bucket_link failed, pivot %d log_bkt %d\n"),
   5623                               pivot_idx_from, bucket_index_to));
   5624         break;
   5625 
   5626     case _MERGE_INVALIDATE:
   5627         LOG_ERROR(BSL_LS_SOC_ALPM,
   5628                   (BSL_META_U(u,
   5629                               "_soc_alpm_bucket_inval failed\n")));
   5630         break;
   5631     case _MERGE_CHILD_TRIE_MERGED:
   5632         break;
   5633 
   5634     case _MERGE_CHILD_PIVOT_DESTROYED:
   5635         LOG_ERROR(BSL_LS_SOC_ALPM,
   5636                   (BSL_META_U(u,
   5637                               "Pivot destroy fail, something not expected\n")));
   5638     default:
   5639         LOG_ERROR(BSL_LS_SOC_ALPM,
   5640                   (BSL_META_U(u,
   5641                               "Merge fails at step %d\n"), doing));
   5642         break;
   5643     }
   5644 
   5645     return rv;
   5646 }
   5647 
   5648 
   5649 /* Move partial entries from one logical bucket to another */
   5650 static int
   5651 _soc_alpm_bucket_repartition(int u, soc_mem_t mem, int pivot_idx_from,
   5652                              int pivot_idx_to, trie_node_t **new_trie,
   5653                              int *shuffled)
   5654 {
   5655     trie_node_t             *split_trie_root = NULL;
   5656     uint32                  length, bpm_len = 0;
   5657     uint32                  pivot[5];
   5658     defip_entry_t           lpm_entry;
   5659     alpm_mem_prefix_array_t *pfx_array = NULL;
   5660     int                     *new_index = NULL;
   5661     int                     rv = SOC_E_NONE, i;
   5662     int                     tcam_index, pivot_index;
   5663     int                     bucket_index_from, bucket_index_to;
   5664     int                     vrf = 0;
   5665     uint32                  src_discard, src_default;
   5666     void                    *raw_bkt[RAW_BKT_NUM] = {0};
   5667     alpm_pivot_t            *new_pivot, *parent_pivot, *child_pivot;
   5668     uint32                  bank_disable = 0;
   5669     int         v6 = (L3_DEFIP_ALPM_IPV6_64m == mem ||
   5670                       L3_DEFIP_ALPM_IPV6_64_1m == mem ||
   5671                       L3_DEFIP_ALPM_IPV6_128m == mem);
   5672     enum {
   5673         _REPART_TRIE_NONE,
   5674         _REPART_TRIE_SPLIT,
   5675         _REPART_LPM_INIT,
   5676         _REPART_PIVOT_CREATE,
   5677         _REPART_PREPARE,
   5678         _REPART_COPY,
   5679         _REPART_LPM_INSERT,
   5680         _REPART_INVALIDATE,
   5681         _REPART_CHILD_TRIE_MERGED,
   5682         _REPART_CHILD_LPM_DELETED,
   5683         _REPART_CHILD_PIVOT_DESTROYED
   5684     } doing = _REPART_TRIE_NONE, done = _REPART_TRIE_NONE;
   5685 
   5686     parent_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_from);
   5687     child_pivot  = ALPM_TCAM_PIVOT(u, pivot_idx_to);
   5688     bucket_index_from = PIVOT_BUCKET_INDEX(parent_pivot);
   5689     bucket_index_to   = PIVOT_BUCKET_INDEX(child_pivot);
   5690 
   5691     doing = _REPART_TRIE_SPLIT;
   5692     rv = trie_split2(PIVOT_BUCKET_TRIE(parent_pivot),
   5693                      child_pivot->key,
   5694                      child_pivot->len,
   5695                      pivot, &length,
   5696                      &split_trie_root,
   5697                      1024, 0);
   5698     if (SOC_FAILURE(rv)) {
   5699         /* Non repartable is nothing fatal, just return and keep searching */
   5700         if (rv == SOC_E_NOT_FOUND) {
   5701             rv = SOC_E_NONE;
   5702         }
   5703         /* Must return */
   5704         return rv;
   5705     }
   5706     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5707 
   5708     vrf = PIVOT_BUCKET_VRF(parent_pivot);
   5709     doing = _REPART_LPM_INIT;
   5710 
   5711     rv = _soc_alpm_split_lpm_init(u, mem, vrf, bucket_index_to, NULL, NULL,
   5712                                   pivot, length, &lpm_entry, &bpm_len,
   5713                                   &src_discard, &src_default);
   5714     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5715 
   5716 
   5717     doing = _REPART_PIVOT_CREATE;
   5718     rv = _soc_alpm_split_pivot_create(u, v6, vrf, bucket_index_to,
   5719                                       split_trie_root, pivot, length,
   5720                                       bpm_len, &new_pivot);
   5721     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5722 
   5723     bank_disable = soc_alpm_bank_dis(u, vrf);
   5724 
   5725     doing = _REPART_PREPARE;
   5726     rv = _soc_alpm_raw_bucket_prepare(u, mem, PIVOT_BUCKET_TRIE(new_pivot),
   5727                                       bucket_index_from, bucket_index_to,
   5728                                       bank_disable, NULL, NULL,
   5729                                       &pfx_array, raw_bkt, &new_index, NULL, 1);
   5730     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5731 
   5732     doing = _REPART_COPY;
   5733     rv = _soc_alpm_raw_bucket_copy(u, mem, bucket_index_to,
   5734                                    bank_disable, raw_bkt[RAW_NEW_BKT_DIP],
   5735                                    raw_bkt[RAW_NEW_BKT_SIP],
   5736                                    new_index, pfx_array->count);
   5737     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5738 
   5739     doing = _REPART_LPM_INSERT;
   5740     rv = soc_alpm_lpm_insert(u, &lpm_entry, &tcam_index,
   5741                              src_default, src_discard, bpm_len);
   5742     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5743     if (shuffled) {
   5744         *shuffled = 1;
   5745     }
   5746 
   5747     /* TCAM index from lpm code is logical.  Convert to global idx */
   5748     tcam_index = soc_alpm_physical_idx(u, L3_DEFIPm, tcam_index, v6);
   5749     pivot_index = tcam_index << (v6 ? 1 : 0);
   5750     PIVOT_TCAM_INDEX(new_pivot)         = pivot_index;
   5751     ALPM_TCAM_PIVOT(u, pivot_index)     = new_pivot;
   5752 
   5753     /* Invalide old entries */
   5754     doing = _REPART_INVALIDATE;
   5755     rv = _soc_alpm_raw_bucket_inval(u, mem, bucket_index_from,
   5756                                     bank_disable,
   5757                                     raw_bkt[RAW_OLD_BKT_DIP],
   5758                                     raw_bkt[RAW_OLD_BKT_SIP],
   5759                                     raw_bkt[RAW_RB_BKT_DIP],
   5760                                     raw_bkt[RAW_RB_BKT_SIP]);
   5761     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5762 
   5763     /* Delete old lpm entry */
   5764     {
   5765         uint32          hw_key[5] = {0};
   5766         int             child_vrf;
   5767 
   5768         /* SW bucket merge: not expect to fail */
   5769         doing = _REPART_CHILD_TRIE_MERGED;
   5770         rv = trie_merge(PIVOT_BUCKET_TRIE(new_pivot),
   5771                         PIVOT_BUCKET_TRIE(child_pivot)->trie,
   5772                         child_pivot->key,
   5773                         child_pivot->len);
   5774         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5775 
   5776         sal_memcpy(hw_key, child_pivot->key, sizeof(hw_key));
   5777         ALPM_TRIE_TO_NORMAL_IP(hw_key, child_pivot->len, v6);
   5778 
   5779         child_vrf = PIVOT_BUCKET_VRF(child_pivot);
   5780 
   5781         (void) _soc_alpm_lpm_ent_key_init(u, hw_key, child_pivot->len,
   5782                                       child_vrf, v6, &lpm_entry, 1);
   5783 
   5784         doing = _REPART_CHILD_LPM_DELETED;
   5785         rv = soc_alpm_lpm_delete(u, &lpm_entry);
   5786         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5787 
   5788         pivot_index = PIVOT_TCAM_INDEX(new_pivot);
   5789 
   5790         /* Destroy child pivot */
   5791         doing = _REPART_CHILD_PIVOT_DESTROYED;
   5792         rv = _soc_alpm_split_pivot_create_undo
   5793                     (u, v6, child_vrf, child_pivot->key, child_pivot->len, NULL, 0);
   5794 
   5795         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5796     }
   5797 
   5798 
   5799     /* Update new index */
   5800     for (i = 0; i < pfx_array->count; i++) {
   5801         pfx_array->prefix[i]->index = new_index[i];
   5802     }
   5803 
   5804     _soc_alpm_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index);
   5805     *new_trie = (trie_node_t *) new_pivot;
   5806 
   5807 /*    LOG_CLI((" Do repartition for two buckets OK\n"));*/
   5808 
   5809     return rv;
   5810 
   5811 _rollback:
   5812 
   5813     /* fall through on all cases */
   5814     switch (done)  {
   5815     case _REPART_CHILD_LPM_DELETED:
   5816         /* Not expect any failure after trie_merge */
   5817 
   5818     case _REPART_CHILD_TRIE_MERGED: {
   5819             uint32      pivot2[5], length2;
   5820             trie_split2(PIVOT_BUCKET_TRIE(parent_pivot),
   5821                         child_pivot->key,
   5822                         child_pivot->len,
   5823                         pivot2, &length2,
   5824                         &(PIVOT_BUCKET_TRIE(child_pivot)->trie),
   5825                         PIVOT_BUCKET_COUNT(child_pivot), 1);
   5826         }
   5827 
   5828     case _REPART_INVALIDATE:
   5829         _soc_alpm_raw_bucket_inval_undo(u, mem, bucket_index_from,
   5830                                         bank_disable,
   5831                                         raw_bkt[RAW_RB_BKT_DIP],
   5832                                         raw_bkt[RAW_RB_BKT_SIP]);
   5833 
   5834     case _REPART_LPM_INSERT:
   5835         soc_alpm_lpm_delete(u, &lpm_entry);
   5836 
   5837     case _REPART_COPY:
   5838         /* Delete entries in new bucket */
   5839         _soc_alpm_raw_bucket_copy_undo(u, mem, bucket_index_to, bank_disable,
   5840                                        raw_bkt[RAW_NEW_BKT_DIP],
   5841                                        raw_bkt[RAW_NEW_BKT_SIP], new_index,
   5842                                        pfx_array->count);
   5843 
   5844     case _REPART_PREPARE:
   5845         _soc_alpm_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index);
   5846 
   5847     case _REPART_PIVOT_CREATE:
   5848         _soc_alpm_split_pivot_create_undo(u, v6, vrf, pivot, length, NULL, 0);
   5849 
   5850     case _REPART_LPM_INIT:
   5851         /* nothing to undo */
   5852 
   5853     case _REPART_TRIE_SPLIT:
   5854         trie_merge(PIVOT_BUCKET_TRIE(parent_pivot), split_trie_root, pivot, length);
   5855     default:
   5856         break;
   5857     }
   5858 
   5859     LOG_ERROR(BSL_LS_SOC_ALPM,
   5860               (BSL_META_U(u,
   5861                           "Repartition fails at step %d\n"), doing));
   5862 
   5863     return rv;
   5864 }
   5865 
   5866 
   5867 static int
   5868 _soc_alpm_repartition_cb(trie_node_t *ptrie, trie_node_t *trie,
   5869                          trie_traverse_states_e_t *state, void *info,
   5870                          trie_node_t **new_trie)
   5871 {
   5872     int             rv;
   5873     int             max_count;
   5874     int             pivot_idx_from, pivot_idx_to, pivot_idx_parent, pivot_idx_child;
   5875     int             bucket_index_from;
   5876     int             do_repartition = 0; /* 0: merge. 1: repartition */
   5877     int             child_count = 0, parent_count = 0;
   5878     soc_alpm_merge_info_t *repart = (soc_alpm_merge_info_t *)info;
   5879     alpm_pivot_t *parent_pivot  = (alpm_pivot_t *)ptrie;
   5880     alpm_pivot_t *child_pivot   = (alpm_pivot_t *)trie;
   5881     soc_alpm_merge_type_t merge_dir = MERGE_PHY;
   5882 
   5883 #ifdef ALPM_REPART_DEBUG
   5884 {
   5885     trie_t          *pivot_trie;
   5886     trie_node_t     *lpm = NULL;
   5887     switch (repart->v6) {
   5888         case L3_DEFIP_MODE_V4:
   5889             pivot_trie = VRF_PIVOT_TRIE_IPV4(repart->u, repart->vrf);
   5890             break;
   5891         case L3_DEFIP_MODE_64:
   5892             pivot_trie = VRF_PIVOT_TRIE_IPV6(repart->u, repart->vrf);
   5893             break;
   5894         default:
   5895             pivot_trie = VRF_PIVOT_TRIE_IPV6_128(repart->u, repart->vrf);
   5896             break;
   5897     }
   5898     trie_find_lpm2(pivot_trie, child_pivot->key, child_pivot->len, &lpm);
   5899     ptrie = lpm;
   5900     parent_pivot  = (alpm_pivot_t *)ptrie;
   5901 }
   5902 #endif
   5903 
   5904     if (!parent_pivot) { /* no parent, this is a root */
   5905         return SOC_E_NONE;
   5906     }
   5907 
   5908     /* Reset state everytime */
   5909     *state = TRIE_TRAVERSE_STATE_NONE;
   5910 
   5911     max_count = repart->max_count;
   5912 
   5913     if (PIVOT_BUCKET_TRIE(parent_pivot)->trie == NULL) {
   5914         merge_dir    = MERGE_LOG_PARENT_TO_CHILD;
   5915     }
   5916 
   5917     if (PIVOT_BUCKET_TRIE(child_pivot)->trie == NULL) {
   5918         merge_dir   = MERGE_LOG_CHILD_TO_PARENT;
   5919     }
   5920 
   5921     if (merge_dir == MERGE_PHY) {
   5922         parent_count = PIVOT_BUCKET_COUNT(parent_pivot);
   5923         child_count = PIVOT_BUCKET_COUNT(child_pivot);
   5924         if (parent_count + child_count < max_count) {
   5925             if (parent_count > child_count) {
   5926                 merge_dir   = MERGE_LOG_CHILD_TO_PARENT;
   5927             } else {
   5928                 merge_dir   = MERGE_LOG_PARENT_TO_CHILD;
   5929             }
   5930         } else {
   5931             /* Merge is not qualified, try repartition */
   5932             merge_dir = MERGE_LOG_PARENT_TO_CHILD;
   5933             do_repartition = 1;
   5934         }
   5935     }
   5936 
   5937     pivot_idx_parent = PIVOT_TCAM_INDEX(parent_pivot);
   5938     pivot_idx_child  = PIVOT_TCAM_INDEX(child_pivot);
   5939 
   5940     if (merge_dir == MERGE_LOG_CHILD_TO_PARENT) {
   5941         pivot_idx_from = pivot_idx_child;
   5942         pivot_idx_to   = pivot_idx_parent;
   5943         bucket_index_from = PIVOT_BUCKET_INDEX(child_pivot);
   5944     } else {
   5945         /* repartition always go here */
   5946         pivot_idx_from = pivot_idx_parent;
   5947         pivot_idx_to   = pivot_idx_child;
   5948         bucket_index_from = PIVOT_BUCKET_INDEX(parent_pivot);
   5949     }
   5950 
   5951     if (do_repartition == 0) { /* Bucket merge */
   5952         if (repart->mem == L3_DEFIP_ALPM_IPV6_128m) {
   5953             rv = _soc_alpm_128_bucket_merge(repart->u, repart->mem,
   5954                                             pivot_idx_from, pivot_idx_to, merge_dir,
   5955                                             &repart->shuffled);
   5956         } else {
   5957             rv = _soc_alpm_bucket_merge(repart->u, repart->mem,
   5958                                         pivot_idx_from, pivot_idx_to, merge_dir,
   5959                                         &repart->shuffled);
   5960         }
   5961         if (SOC_FAILURE(rv)) {
   5962             LOG_ERROR(BSL_LS_SOC_ALPM,
   5963                       (BSL_META_U(repart->u,
   5964                                   "Bucket merge fail %d\n"), rv));
   5965             return rv;
   5966         }
   5967 
   5968         repart->log_bkt = bucket_index_from;
   5969         *state = TRIE_TRAVERSE_STATE_DELETED;
   5970         if (++repart->merge_count >= REPART_THRESHOLD) {
   5971             *state = TRIE_TRAVERSE_STATE_DONE;
   5972         }
   5973         soc_alpm_dbg_cnt[repart->u].bkt_merge2++;
   5974     } else { /* Repartition */
   5975         /* Repartition is an intermediate stage, not a goal.
   5976          * Also note, repartition may result in trie modified
   5977          * (old node deleted, new node added).
   5978          */
   5979         if (repart->mem == L3_DEFIP_ALPM_IPV6_128m) {
   5980             rv = _soc_alpm_128_bucket_repartition(repart->u, repart->mem,
   5981                                                   pivot_idx_from, pivot_idx_to,
   5982                                                   new_trie, &repart->shuffled);
   5983         } else {
   5984             rv = _soc_alpm_bucket_repartition(repart->u, repart->mem,
   5985                                               pivot_idx_from, pivot_idx_to,
   5986                                               new_trie, &repart->shuffled);
   5987         }
   5988         if (SOC_FAILURE(rv)) {
   5989             LOG_ERROR(BSL_LS_SOC_ALPM,
   5990                       (BSL_META_U(repart->u,
   5991                                   "Bucket repartition fail %d\n"), rv));
   5992         }
   5993         /* keep searching if not repartable */
   5994         if (repart->shuffled) {
   5995             soc_alpm_dbg_cnt[repart->u].bkt_repart++;
   5996         }
   5997     }
   5998 
   5999     return rv;
   6000 }
   6001 
   6002 
   6003 static int
   6004 _soc_alpm_repartition(int u, soc_mem_t mem, int vrf, int *bucket_index, int *shuffled)
   6005 {
   6006     int                             rv = SOC_E_NONE;
   6007     soc_alpm_merge_info_t           info;
   6008     trie_t                          *pivot_trie = NULL;
   6009 
   6010     sal_memset(&info, 0, sizeof(info));
   6011     info.log_bkt     = -1; /* Initialize to non-eligible bucket_index */
   6012     info.u           = u;
   6013     info.mem         = mem;
   6014     info.orig_vrf    = vrf;
   6015     info.v6          = SOC_ALPM_MEM_V6(mem);
   6016     info.vrf         = vrf;
   6017     info.max_count   = _soc_alpm_bkt_entry_cnt(u, mem);
   6018 
   6019     pivot_trie =
   6020         (info.v6 == L3_DEFIP_MODE_V4 ? VRF_PIVOT_TRIE_IPV4(u, info.vrf) :
   6021          info.v6 == L3_DEFIP_MODE_64 ? VRF_PIVOT_TRIE_IPV6(u, info.vrf) :
   6022                                    VRF_PIVOT_TRIE_IPV6_128(u, info.vrf));
   6023     if (pivot_trie == NULL || pivot_trie->trie == NULL) {
   6024         return SOC_E_FULL;
   6025     }
   6026     /* Choose post-order traverse for repartition.
   6027      * All orders are delete safe.
   6028      * But only the post-order is modify safe.
   6029      */
   6030     rv = trie_repartition(pivot_trie, _soc_alpm_repartition_cb,
   6031                           &info, _TRIE_POSTORDER_TRAVERSE);
   6032     if (info.shuffled && shuffled) {
   6033         *shuffled = 1;
   6034     }
   6035     if (SOC_FAILURE(rv)) {
   6036         LOG_ERROR(BSL_LS_SOC_ALPM,
   6037                   (BSL_META_U(u, "Logic bucket repartition fails."\
   6038                                  "rv %d vrf %d v6 %d\n"), rv, info.vrf, info.v6));
   6039         return rv;
   6040     } else if (info.log_bkt != -1) {
   6041         /* This indicates one and only one merge happened.
   6042          * Note repartition don't set bucket_index.
   6043          */
   6044         *bucket_index = info.log_bkt;
   6045         return SOC_E_NONE;
   6046     }
   6047     return SOC_E_FULL;
   6048 }
   6049 
   6050 static int
   6051 _soc_alpm_merge_cb(trie_node_t *ptrie, trie_node_t *trie,
   6052                    trie_traverse_states_e_t *state, void *info)
   6053 {
   6054     int             rv;
   6055     int             max_count;
   6056     int             pivot_idx_from, pivot_idx_to, pivot_idx_parent, pivot_idx_child;
   6057     int             bucket_index_from;
   6058     int             child_count = 0, parent_count = 0;
   6059     soc_alpm_merge_info_t *merge = (soc_alpm_merge_info_t *)info;
   6060     alpm_pivot_t *parent_pivot = (alpm_pivot_t *)ptrie;
   6061     alpm_pivot_t *child_pivot = (alpm_pivot_t *)trie;
   6062     soc_alpm_merge_type_t merge_dir = MERGE_PHY;
   6063 
   6064     if (!parent_pivot) {
   6065         return SOC_E_NONE;
   6066     }
   6067 
   6068     /* Reset state everytime */
   6069     *state = TRIE_TRAVERSE_STATE_NONE;
   6070 
   6071     max_count = merge->max_count;
   6072 
   6073     if (PIVOT_BUCKET_TRIE(parent_pivot)->trie == NULL) {
   6074         merge_dir    = MERGE_LOG_PARENT_TO_CHILD;
   6075     }
   6076 
   6077     if (PIVOT_BUCKET_TRIE(child_pivot)->trie == NULL) {
   6078         merge_dir   = MERGE_LOG_CHILD_TO_PARENT;
   6079     }
   6080 
   6081     if (merge_dir == MERGE_PHY) {
   6082         parent_count = PIVOT_BUCKET_COUNT(parent_pivot);
   6083         child_count = PIVOT_BUCKET_COUNT(child_pivot);
   6084         if (parent_count + child_count < max_count) {
   6085             if (parent_count > child_count) {
   6086                 merge_dir   = MERGE_LOG_CHILD_TO_PARENT;
   6087             } else {
   6088                 merge_dir   = MERGE_LOG_PARENT_TO_CHILD;
   6089             }
   6090         } else {
   6091             return SOC_E_NONE;
   6092         }
   6093     }
   6094 
   6095     pivot_idx_parent = PIVOT_TCAM_INDEX(parent_pivot);
   6096     pivot_idx_child  = PIVOT_TCAM_INDEX(child_pivot);
   6097 
   6098     if (merge_dir == MERGE_LOG_CHILD_TO_PARENT) {
   6099         pivot_idx_from = pivot_idx_child;
   6100         pivot_idx_to   = pivot_idx_parent;
   6101         bucket_index_from = PIVOT_BUCKET_INDEX(child_pivot);
   6102     } else {
   6103         pivot_idx_from = pivot_idx_parent;
   6104         pivot_idx_to   = pivot_idx_child;
   6105         bucket_index_from = PIVOT_BUCKET_INDEX(parent_pivot);
   6106     }
   6107 
   6108     /* Do logical bucket merge */
   6109     if (merge->mem == L3_DEFIP_ALPM_IPV6_128m) {
   6110         rv = _soc_alpm_128_bucket_merge(merge->u, merge->mem,
   6111                                         pivot_idx_from, pivot_idx_to, merge_dir,
   6112                                         &merge->shuffled);
   6113     } else {
   6114         rv = _soc_alpm_bucket_merge(merge->u, merge->mem,
   6115                                     pivot_idx_from, pivot_idx_to, merge_dir,
   6116                                     &merge->shuffled);
   6117     }
   6118 
   6119     if (SOC_FAILURE(rv)) { /* traverse stops on callback failure */
   6120         LOG_CLI(("Merge fails %d (not expecting this )\n", rv));
   6121         return rv;
   6122     }
   6123 
   6124     merge->log_bkt = bucket_index_from;
   6125     *state = TRIE_TRAVERSE_STATE_DELETED;
   6126     if (++merge->merge_count >= MERGE_THRESHOLD) {
   6127         *state = TRIE_TRAVERSE_STATE_DONE;
   6128     }
   6129     soc_alpm_dbg_cnt[merge->u].bkt_merge++;
   6130 
   6131     return SOC_E_NONE;
   6132 }
   6133 
   6134 
   6135 static int
   6136 _soc_alpm_merge(int u, soc_mem_t mem, int vrf, int *bucket_index, int *shuffled)
   6137 {
   6138     int                             rv = SOC_E_NONE;
   6139     soc_alpm_merge_info_t           info;
   6140     trie_t                          *pivot_trie = NULL;
   6141 
   6142     sal_memset(&info, 0, sizeof(info));
   6143     info.log_bkt     = -1; /* Initialize to non-eligible bucket_index */
   6144     info.u           = u;
   6145     info.mem         = mem;
   6146     info.orig_vrf    = vrf;
   6147     info.v6          = SOC_ALPM_MEM_V6(mem);
   6148     info.vrf         = vrf;
   6149     info.max_count   = _soc_alpm_bkt_entry_cnt(u, mem);
   6150 
   6151     pivot_trie =
   6152         (info.v6 == L3_DEFIP_MODE_V4 ? VRF_PIVOT_TRIE_IPV4(u, info.vrf) :
   6153          info.v6 == L3_DEFIP_MODE_64 ? VRF_PIVOT_TRIE_IPV6(u, info.vrf) :
   6154                                    VRF_PIVOT_TRIE_IPV6_128(u, info.vrf));
   6155     if (pivot_trie == NULL || pivot_trie->trie == NULL) {
   6156         return SOC_E_FULL;
   6157     }
   6158     rv = trie_traverse2(pivot_trie, _soc_alpm_merge_cb,
   6159                         &info, _TRIE_POSTORDER_TRAVERSE);
   6160     if (info.shuffled && shuffled) {
   6161         *shuffled = 1;
   6162     }
   6163     if (SOC_FAILURE(rv)) {
   6164         LOG_ERROR(BSL_LS_SOC_ALPM,
   6165                   (BSL_META_U(u, "Logic bucket merge fails."\
   6166                                  "rv %d vrf %d v6 %d\n"), rv, info.vrf, info.v6));
   6167         return rv;
   6168     } else if (info.log_bkt != -1) {
   6169         /* This indicates one and only one merge happened. */
   6170         *bucket_index = info.log_bkt;
   6171         return SOC_E_NONE;
   6172     }
   6173     return SOC_E_FULL;
   6174 }
   6175 
   6176 
   6177 
   6178 static int
   6179 _soc_alpm_assign(int u, soc_mem_t mem, int vrf, int *bucket_index, int *o_shuffled)
   6180 {
   6181     int                 rv = SOC_E_FULL;
   6182     int                 shuffled = 0;
   6183     int                 lpm_free_count = 0;
   6184 
   6185     /* Logical bucket merge on condition. */
   6186     rv = _soc_alpm_merge(u, mem, vrf, bucket_index, &shuffled);
   6187 
   6188     if (rv == SOC_E_FULL) {
   6189         /* Logical bucket repartition on condition. */
   6190         lpm_free_count = _soc_alpm_lpm_free_entries(u, mem, vrf);
   6191         if (lpm_free_count >= 1 && lpm_free_count <= 5) {
   6192             rv = _soc_alpm_repartition(u, mem, vrf, bucket_index, &shuffled);
   6193         }
   6194     }
   6195 
   6196     if (o_shuffled) {
   6197         *o_shuffled = shuffled;
   6198     }
   6199     return rv;
   6200 }
   6201 
   6202 /* Get the free bucket to allocate to the PIVOT */
   6203 int
   6204 alpm_bucket_assign(int u, int v6, int *bucket_pointer)
   6205 {
   6206     int i, step_count = 1, used = 0;
   6207 
   6208     /*
   6209      * in combined search mode, with urpf disabled, need to allocate even and 
   6210      * odd bucket pointers
   6211      */
   6212 
   6213     if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) {
   6214         step_count = 2;
   6215     }
   6216     for (i = 0; i < SOC_ALPM_BUCKET_COUNT(u); i += step_count) {
   6217         SHR_BITTEST_RANGE(SOC_ALPM_BUCKET_BMAP(u), i, step_count, used);
   6218         if (0 == used) {
   6219             break;
   6220         }
   6221     }
   6222     if (i == SOC_ALPM_BUCKET_COUNT(u)) {
   6223         return SOC_E_FULL;
   6224     }
   6225     SHR_BITSET_RANGE(SOC_ALPM_BUCKET_BMAP(u), i, step_count);
   6226     *bucket_pointer = i;
   6227     SOC_ALPM_BUCKET_NEXT_FREE(u) = i;
   6228     return SOC_E_NONE;
   6229 }
   6230 
   6231 int
   6232 soc_alpm_assign(int u, int vrf, soc_mem_t mem, int *bucket_pointer, int *shuffled)
   6233 {
   6234     int rv;
   6235     int step_count = 1;
   6236     int v6 = SOC_ALPM_MEM_V6(mem);
   6237 
   6238     rv = alpm_bucket_assign(u, v6, bucket_pointer);
   6239 
   6240     if (SOC_SUCCESS(rv)) {
   6241         if (_soc_alpm_lpm_free_entries(u, mem, vrf) == 0) {
   6242             rv = _soc_alpm_merge(u, mem, vrf, &step_count, shuffled);
   6243             if (rv == SOC_E_FULL && !v6) {
   6244                 rv = SOC_E_NONE;
   6245             } else if (SOC_FAILURE(rv)) {
   6246                 (void) alpm_bucket_release(u, *bucket_pointer, v6);
   6247             }
   6248         }
   6249     } else if (rv == SOC_E_FULL) {
   6250         rv =  _soc_alpm_assign(u, mem, vrf, bucket_pointer, shuffled);
   6251         /* Reclaim the physical bucket in case it has been freed */
   6252         if (SOC_SUCCESS(rv)) {
   6253             if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) {
   6254                 step_count = 2;
   6255             }
   6256             SHR_BITSET_RANGE(SOC_ALPM_BUCKET_BMAP(u), *bucket_pointer, step_count);
   6257             SOC_ALPM_BUCKET_NEXT_FREE(u) = *bucket_pointer;
   6258         }
   6259     }
   6260     return rv;
   6261 }
   6262 
   6263 
   6264 /* Release the bucket to the pool*/
   6265 int
   6266 alpm_bucket_release(int u, int bucket_pointer, int v6)
   6267 {
   6268     int step_count = 1, used = 0;
   6269 
   6270     /* Check if the bucket pointer is valid */
   6271     if ((bucket_pointer < 1) ||
   6272                 (bucket_pointer > SOC_ALPM_BUCKET_MAX_INDEX(u))) {
   6273         LOG_ERROR(BSL_LS_SOC_ALPM,
   6274                   (BSL_META_U(u,
   6275                               "Unit %d\n, freeing invalid bucket index %d\n"),
   6276                    u, bucket_pointer));
   6277         return SOC_E_PARAM;
   6278     }
   6279     /* in combined search mode, with urpf disabled, need to free even and odd
   6280      * bucket pointers
   6281      */
   6282     if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) {
   6283         step_count = 2;
   6284     }
   6285     SHR_BITTEST_RANGE(SOC_ALPM_BUCKET_BMAP(u), bucket_pointer, step_count, 
   6286                       used);
   6287     if (!used) {
   6288         return SOC_E_PARAM;
   6289     }
   6290     SHR_BITCLR_RANGE(SOC_ALPM_BUCKET_BMAP(u), bucket_pointer, step_count);
   6291     _soc_trident2_alpm_bkt_view_set(u, bucket_pointer << 2, INVALIDm);
   6292     if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) {
   6293         _soc_trident2_alpm_bkt_view_set(u, (bucket_pointer + 1) << 2,
   6294                                         INVALIDm);
   6295     }
   6296 
   6297     if (SOC_URPF_STATUS_GET(u)) {
   6298         _soc_trident2_alpm_bkt_view_set(u,
   6299                         _soc_alpm_rpf_entry(u, bucket_pointer << 2), INVALIDm);
   6300         if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) {
   6301             _soc_trident2_alpm_bkt_view_set(u,
   6302                         _soc_alpm_rpf_entry(u, (bucket_pointer + 1) << 2), INVALIDm);
   6303         }
   6304     }
   6305     return SOC_E_NONE;
   6306 }
   6307 
   6308 int
   6309 alpm_bucket_is_assigned(int u, int bucket_ptr, int ipv6, int *used)
   6310 {
   6311     int step_count = 1;
   6312 
   6313     /* Check if the bucket pointer is valid */
   6314     if ((bucket_ptr < 1) || (bucket_ptr > SOC_ALPM_BUCKET_MAX_INDEX(u))) {
   6315         return SOC_E_PARAM;
   6316     }
   6317     
   6318     /* in combined search mode, with urpf disabled, need to allocate even and 
   6319      * odd bucket pointers */
   6320     if (ipv6) {
   6321         if (!soc_alpm_mode_get(u) && !SOC_URPF_STATUS_GET(u)) {
   6322             step_count = 2;
   6323         }
   6324     }
   6325     
   6326     SHR_BITTEST_RANGE(SOC_ALPM_BUCKET_BMAP(u), bucket_ptr, step_count, *used);
   6327     return SOC_E_NONE;
   6328 }
   6329 
   6330 /**********************************************
   6331 * TCAM Management functions *
   6332  */
   6333 
   6334 /*
   6335  * TCAM based PIVOT implementation. Each table entry can hold two IPV4 PIVOTs or
   6336  * one IPV6 PIVOT entry. VRF independent routes placed at the beginning or 
   6337  * at the end of table based on application provided entry vrf id 
   6338  * (SOC_L3_VRF_OVERRIDE/SOC_L3_VRF_GLOBAL).   
   6339  *
   6340  *              ALPM_MAX_PFX_INDEX
   6341  * lpm_prefix_index[98].begin ---> ===============================
   6342  *                                 ==                           ==
   6343  *                                 ==    0                      ==
   6344  * lpm_prefix_index[98].end   ---> ===============================
   6345  *
   6346  * lpm_prefix_index[97].begin ---> ===============================
   6347  *                                 ==                           ==
   6348  *                                 ==    IPV6  Prefix Len = 64  ==
   6349  * lpm_prefix_index[97].end   ---> ===============================
   6350  *
   6351  *
   6352  *
   6353  * lpm_prefix_index[x].begin --->  ===============================
   6354  *                                 ==                           ==
   6355  *                                 ==                           ==
   6356  * lpm_prefix_index[x].end   --->  ===============================
   6357  *
   6358  *
   6359  *              ALPM_IPV6_PFX_ZERO
   6360  * lpm_prefix_index[33].begin ---> ===============================
   6361  *                                 ==                           ==
   6362  *                                 ==    IPV6  Prefix Len = 0   ==
   6363  * lpm_prefix_index[33].end   ---> ===============================
   6364  *
   6365  *
   6366  * lpm_prefix_index[32].begin ---> ===============================
   6367  *                                 ==                           ==
   6368  *                                 ==    IPV4  Prefix Len = 32  ==
   6369  * lpm_prefix_index[32].end   ---> ===============================
   6370  *
   6371  *
   6372  *
   6373  * lpm_prefix_index[0].begin --->  ===============================
   6374  *                                 ==                           ==
   6375  *                                 ==    IPV4  Prefix Len = 0   ==
   6376  * lpm_prefix_index[0].end   --->  ===============================
   6377  */
   6378 
   6379 
   6380 /*
   6381  *      Extract key data from an entry at the given index.
   6382  */
   6383 static
   6384 void _soc_alpm_lpm_hash_entry_get(int u, void *e,
   6385                                 int index, _soc_alpm_lpm_hash_entry_t r_entry,
   6386                                 int *v)
   6387 {
   6388     if (index & TD2_ALPM_HASH_IPV6_MASK) {
   6389         SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, e, r_entry);
   6390         if (v) {
   6391             *v =  SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f) &&
   6392                   SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f);
   6393         }
   6394     } else {
   6395         if (index & 0x1) {
   6396             SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, e, r_entry);
   6397             if (v) {
   6398                 *v =  SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f);
   6399             }
   6400         } else {
   6401             SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, e, r_entry);
   6402             if (v) {
   6403                 *v =  SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f);
   6404             }
   6405         }
   6406     }
   6407 }
   6408 
   6409 /*
   6410  * Function:
   6411  *      _soc_alpm_lpm_hash_compare_key
   6412  * Purpose:
   6413  *      Comparison function for AVL shadow table operations.
   6414  */
   6415 static
   6416 int _soc_alpm_lpm_hash_compare_key(_soc_alpm_lpm_hash_entry_t key1,
   6417                                  _soc_alpm_lpm_hash_entry_t key2)
   6418 {
   6419     int idx;
   6420 
   6421     for (idx = 0; idx < 5; idx++) { 
   6422         SOC_MEM_COMPARE_RETURN(key1[idx], key2[idx]);
   6423     }
   6424     return (0);
   6425 }
   6426 
   6427 #ifdef FB_LPM_DEBUG      
   6428 #define H_INDEX_MATCH(str, tab_index, match_index)      \
   6429     LOG_ERROR(BSL_LS_SOC_ALPM, \
   6430               (BSL_META("%s index: H %d A %d\n"),              \
   6431                str, (int)tab_index, match_index))
   6432 #else
   6433 #define H_INDEX_MATCH(str, tab_index, match_index)
   6434 #endif
   6435 
   6436 #define LPM_NO_MATCH_INDEX 0x4000
   6437 #define LPM_HASH_INSERT(u, entry_data, tab_index, rvt_index0, rvt_index1)     \
   6438     soc_alpm_lpm_hash_insert(u, entry_data, tab_index, LPM_NO_MATCH_INDEX, 0, \
   6439                              rvt_index0, rvt_index1)
   6440 
   6441 #define LPM_HASH_REVERT(u, entry_data, tab_index, rvt_index0, rvt_index1)     \
   6442     soc_alpm_lpm_hash_revert(u, entry_data, tab_index, \
   6443                              rvt_index0, rvt_index1)
   6444 
   6445 #define LPM_HASH_DELETE(u, key_data, tab_index)         \
   6446     soc_alpm_lpm_hash_delete(u, key_data, tab_index)
   6447 
   6448 #define LPM_HASH_LOOKUP(u, key_data, pfx, tab_index)    \
   6449     soc_alpm_lpm_hash_lookup(u, key_data, pfx, tab_index)
   6450 
   6451 #define LPM_HASH_VERIFY(u, key_data, tab_index)    \
   6452     soc_alpm_lpm_hash_verify(u, key_data, tab_index)
   6453 
   6454 #define INDEX_DELETE(hash, hash_idx, del_idx)                   \
   6455     hash->table[hash_idx] =                                     \
   6456         hash->link_table[del_idx & TD2_ALPM_HASH_INDEX_MASK];     \
   6457     hash->link_table[del_idx & TD2_ALPM_HASH_INDEX_MASK] =        \
   6458         TD2_ALPM_HASH_INDEX_NULL
   6459 
   6460 #define INDEX_DELETE_LINK(hash, prev_idx, del_idx)              \
   6461     hash->link_table[prev_idx & TD2_ALPM_HASH_INDEX_MASK] =       \
   6462         hash->link_table[del_idx & TD2_ALPM_HASH_INDEX_MASK];     \
   6463     hash->link_table[del_idx & TD2_ALPM_HASH_INDEX_MASK] =        \
   6464         TD2_ALPM_HASH_INDEX_NULL
   6465 
   6466 
   6467 static void soc_alpm_lpm_hash_insert(int u, void *entry_data, uint32 tab_index,
   6468                                      uint32 old_index, int pfx,
   6469                                      uint32 *rvt_index0, uint32 *rvt_index1)
   6470 {
   6471     _soc_alpm_lpm_hash_entry_t    key_hash;
   6472 
   6473     if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, MODE0f)) {
   6474         /* IPV6 entry */
   6475         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID1f) &&
   6476             SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID0f)) {
   6477             SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, key_hash);
   6478             _soc_alpm_lpm_hash_insert(
   6479                         SOC_ALPM_LPM_STATE_HASH(u),
   6480                         _soc_alpm_lpm_hash_compare_key,
   6481                         key_hash,
   6482                         pfx,
   6483                         old_index,
   6484                         ((uint16)tab_index << 1) | TD2_ALPM_HASH_IPV6_MASK,
   6485                         rvt_index0);
   6486         }
   6487     } else {
   6488         /* IPV4 entry */
   6489         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID0f)) {
   6490             SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, key_hash);
   6491             _soc_alpm_lpm_hash_insert(SOC_ALPM_LPM_STATE_HASH(u),
   6492                                     _soc_alpm_lpm_hash_compare_key,
   6493                                     key_hash,
   6494                                     pfx,
   6495                                     old_index,
   6496                                     ((uint16)tab_index << 1),
   6497                                     rvt_index0);
   6498         }
   6499         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID1f)) {
   6500             SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, key_hash);
   6501             _soc_alpm_lpm_hash_insert(SOC_ALPM_LPM_STATE_HASH(u),
   6502                                     _soc_alpm_lpm_hash_compare_key,
   6503                                     key_hash,
   6504                                     pfx,
   6505                                     old_index,
   6506                                     (((uint16)tab_index << 1) + 1),
   6507                                     rvt_index1);
   6508         }
   6509     }
   6510 }
   6511 
   6512 
   6513 
   6514 
   6515 static void soc_alpm_lpm_hash_revert(int u, void *entry_data, uint32 tab_index,
   6516                                      uint32 rvt_index0, uint32 rvt_index1)
   6517 {
   6518     _soc_alpm_lpm_hash_entry_t    key_hash;
   6519 
   6520     if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, MODE0f)) {
   6521         /* IPV6 entry */
   6522         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID1f) &&
   6523             SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID0f)) {
   6524             SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, key_hash);
   6525             _soc_alpm_lpm_hash_revert(
   6526                         SOC_ALPM_LPM_STATE_HASH(u),
   6527                         _soc_alpm_lpm_hash_compare_key,
   6528                         key_hash,
   6529                         ((uint16)tab_index << 1) | TD2_ALPM_HASH_IPV6_MASK,
   6530                         rvt_index0);
   6531         }
   6532     } else {
   6533         /* IPV4 entry */
   6534         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID0f)) {
   6535             SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, key_hash);
   6536             _soc_alpm_lpm_hash_revert(SOC_ALPM_LPM_STATE_HASH(u),
   6537                                     _soc_alpm_lpm_hash_compare_key,
   6538                                     key_hash,
   6539                                     ((uint16)tab_index << 1),
   6540                                     rvt_index0);
   6541         }
   6542         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID1f)) {
   6543             SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, key_hash);
   6544             _soc_alpm_lpm_hash_revert(SOC_ALPM_LPM_STATE_HASH(u),
   6545                                     _soc_alpm_lpm_hash_compare_key,
   6546                                     key_hash,
   6547                                     (((uint16)tab_index << 1) + 1),
   6548                                     rvt_index1);
   6549         }
   6550     }
   6551 }
   6552 
   6553 
   6554 static void soc_alpm_lpm_hash_delete(int u, void *key_data, uint32 tab_index)
   6555 {
   6556     _soc_alpm_lpm_hash_entry_t    key_hash;
   6557     int                         pfx = -1;
   6558     int                         rv;
   6559     uint16                      index;
   6560 
   6561     if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, MODE0f)) {
   6562         SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, key_data, key_hash);
   6563         index = (tab_index << 1) | TD2_ALPM_HASH_IPV6_MASK;
   6564     } else {
   6565         SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, key_data, key_hash);
   6566         index = tab_index;
   6567     }
   6568 
   6569     rv = _soc_alpm_lpm_hash_delete(SOC_ALPM_LPM_STATE_HASH(u),
   6570                                  _soc_alpm_lpm_hash_compare_key,
   6571                                  key_hash, pfx, index);
   6572     if (SOC_FAILURE(rv)) {
   6573         LOG_ERROR(BSL_LS_SOC_ALPM,
   6574                   (BSL_META_U(u,
   6575                               "\ndel  index: H %d error %d\n"), index, rv));
   6576     }
   6577 }
   6578 
   6579 static int soc_alpm_lpm_hash_lookup(int u, void *key_data, int pfx, int *key_index)
   6580 {
   6581     _soc_alpm_lpm_hash_entry_t    key_hash;
   6582     int                         is_ipv6;
   6583     int                         rv;
   6584     uint16                      index = TD2_ALPM_HASH_INDEX_NULL;
   6585 
   6586     is_ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, MODE0f);
   6587     if (is_ipv6) {
   6588         SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, key_data, key_hash);
   6589     } else {
   6590         SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, key_data, key_hash);
   6591     }
   6592 
   6593     rv = _soc_alpm_lpm_hash_lookup(SOC_ALPM_LPM_STATE_HASH(u),
   6594                                  _soc_alpm_lpm_hash_compare_key,
   6595                                  key_hash, pfx, &index);
   6596     if (SOC_FAILURE(rv)) {
   6597         *key_index = 0xFFFFFFFF;
   6598         return(rv);
   6599     }
   6600 
   6601     *key_index = index;
   6602 
   6603     return(SOC_E_NONE);
   6604 }
   6605 
   6606 static int soc_alpm_lpm_hash_verify(int u, void *key_data, uint32 tab_index)
   6607 {
   6608     _soc_alpm_lpm_hash_entry_t    key_hash;
   6609     int                         pfx = -1;
   6610     int                         rv;
   6611     uint16                      index;
   6612 
   6613     if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, MODE0f)) {
   6614         SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, key_data, key_hash);
   6615         index = (tab_index << 1) | TD2_ALPM_HASH_IPV6_MASK;
   6616     } else {
   6617         SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, key_data, key_hash);
   6618         index = tab_index;
   6619     }
   6620 
   6621     rv = _soc_alpm_lpm_hash_verify(SOC_ALPM_LPM_STATE_HASH(u),
   6622                                  _soc_alpm_lpm_hash_compare_key,
   6623                                  key_hash, pfx, index);
   6624     if (SOC_FAILURE(rv)) {
   6625         LOG_ERROR(BSL_LS_SOC_ALPM,
   6626                   (BSL_META_U(u,
   6627                               "\nveri index: H %d error %d\n"), index, rv));
   6628     }
   6629     return rv;
   6630 }
   6631 
   6632 /* 
   6633  * Function:
   6634  *      _soc_alpm_lpm_hash_compute
   6635  * Purpose:
   6636  *      Compute CRC hash for key data.
   6637  * Parameters:
   6638  *      data - Key data
   6639  *      data_nbits - Number of data bits
   6640  * Returns:
   6641  *      Computed 16 bit hash
   6642  */
   6643 static
   6644 uint16 _soc_alpm_lpm_hash_compute(uint8 *data, int data_nbits)
   6645 {
   6646     return (_shr_crc16b(0, data, data_nbits));
   6647 }
   6648 
   6649 /* 
   6650  * Function:
   6651  *      _soc_alpm_lpm_hash_create
   6652  * Purpose:
   6653  *      Create an empty hash table
   6654  * Parameters:
   6655  *      unit  - Device unit
   6656  *      entry_count - Limit for number of entries in table
   6657  *      index_count - Hash index max + 1. (index_count <= count)
   6658  *      fb_lpm_hash_ptr - Return pointer (handle) to new Hash Table
   6659  * Returns:
   6660  *      SOC_E_NONE       Success
   6661  *      SOC_E_MEMORY     Out of memory (system allocator)
   6662  */
   6663 
   6664 static
   6665 int _soc_alpm_lpm_hash_create(int unit,
   6666                             int entry_count,
   6667                             int index_count,
   6668                             _soc_alpm_lpm_hash_t **fb_lpm_hash_ptr)
   6669 {
   6670     _soc_alpm_lpm_hash_t  *hash;
   6671     int                 index;
   6672 
   6673     if (index_count > entry_count) {
   6674         return SOC_E_MEMORY;
   6675     }
   6676     hash = sal_alloc(sizeof (_soc_alpm_lpm_hash_t), "lpm_hash");
   6677     if (hash == NULL) {
   6678         return SOC_E_MEMORY;
   6679     }
   6680 
   6681     sal_memset(hash, 0, sizeof (*hash));
   6682 
   6683     hash->unit = unit;
   6684     hash->entry_count = entry_count;
   6685     hash->index_count = index_count;
   6686 
   6687     /*
   6688      * Pre-allocate the hash table storage.
   6689      */
   6690     hash->table = sal_alloc(hash->index_count * sizeof(*(hash->table)),
   6691                             "hash_table");
   6692 
   6693     if (hash->table == NULL) {
   6694         sal_free(hash);
   6695         return SOC_E_MEMORY;
   6696     }
   6697     /*
   6698      * In case where all the entries should hash into the same bucket
   6699      * this will prevent the hash table overflow
   6700      */
   6701     hash->link_table = sal_alloc(
   6702                             hash->entry_count * sizeof(*(hash->link_table)),
   6703                             "link_table");
   6704     if (hash->link_table == NULL) {
   6705         sal_free(hash->table);
   6706         sal_free(hash);
   6707         return SOC_E_MEMORY;
   6708     }
   6709 
   6710     /*
   6711      * Set the entries in the hash table to TD2_ALPM_HASH_INDEX_NULL
   6712      * Link the entries beyond hash->index_max for handling collisions
   6713      */
   6714     for(index = 0; index < hash->index_count; index++) {
   6715         hash->table[index] = TD2_ALPM_HASH_INDEX_NULL;
   6716     }
   6717     for(index = 0; index < hash->entry_count; index++) {
   6718         hash->link_table[index] = TD2_ALPM_HASH_INDEX_NULL;
   6719     }
   6720     *fb_lpm_hash_ptr = hash;
   6721     return SOC_E_NONE;
   6722 }
   6723 
   6724 /* 
   6725  * Function:
   6726  *      _soc_alpm_lpm_hash_destroy
   6727  * Purpose:
   6728  *      Destroy the hash table
   6729  * Parameters:
   6730  *      fb_lpm_hash - Pointer (handle) to Hash Table
   6731  * Returns:
   6732  *      SOC_E_NONE       Success
   6733  */
   6734 static
   6735 int _soc_alpm_lpm_hash_destroy(_soc_alpm_lpm_hash_t *fb_lpm_hash)
   6736 {
   6737     if (fb_lpm_hash != NULL) {
   6738         sal_free(fb_lpm_hash->table);
   6739         sal_free(fb_lpm_hash->link_table);
   6740         sal_free(fb_lpm_hash);
   6741     }
   6742 
   6743     return SOC_E_NONE;
   6744 }
   6745 
   6746 /*
   6747  * Function:
   6748  *      _soc_alpm_lpm_hash_lookup
   6749  * Purpose:
   6750  *      Look up a key in the hash table
   6751  * Parameters:
   6752  *      hash - Pointer (handle) to Hash Table
   6753  *      key_cmp_fn - Compare function which should compare key
   6754  *      entry   - The key to lookup
   6755  *      pfx     - Prefix length for lookup acceleration.
   6756  *      key_index - (OUT)       Index where the key was found.
   6757  * Returns:
   6758  *      SOC_E_NONE      Key found
   6759  *      SOC_E_NOT_FOUND Key not found
   6760  */
   6761 
   6762 static
   6763 int _soc_alpm_lpm_hash_lookup(_soc_alpm_lpm_hash_t          *hash,
   6764                             _soc_alpm_lpm_hash_compare_fn key_cmp_fn,
   6765                             _soc_alpm_lpm_hash_entry_t    entry,
   6766                             int                         pfx,
   6767                             uint16                      *key_index)
   6768 {
   6769     int u = hash->unit, v, i = 0;
   6770 
   6771     uint16 hash_val;
   6772     uint16 index;
   6773 
   6774     hash_val = _soc_alpm_lpm_hash_compute((uint8 *)entry,
   6775                                         (32 * 5)) % hash->index_count;
   6776     index = hash->table[hash_val];
   6777     H_INDEX_MATCH("lhash", entry[0], hash_val);
   6778     H_INDEX_MATCH("lkup ", entry[0], index);
   6779     while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   6780         uint32  e[SOC_MAX_MEM_FIELD_WORDS];
   6781         _soc_alpm_lpm_hash_entry_t  r_entry;
   6782         int     rindex;
   6783 
   6784         rindex = (index & TD2_ALPM_HASH_INDEX_MASK) >> 1;
   6785         /*
   6786          * Check prefix length and skip index if not valid for given length
   6787         if ((SOC_ALPM_LPM_STATE_START(u, pfx) <= rindex) &&
   6788             (SOC_ALPM_LPM_STATE_END(u, pfx) >= rindex)) {
   6789          */
   6790         SOC_IF_ERROR_RETURN(
   6791             _soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY, rindex, e));
   6792         SOC_FB_LPM_HASH_ENTRY_GET(u, e, index, r_entry, &v);
   6793         if (v == 0) {
   6794             LOG_ERROR(BSL_LS_SOC_ALPM,
   6795                       (BSL_META_U(u,
   6796                                 "Empty entry[%d] in link_table. hash_val %d ridx %d \n"),
   6797                                 index, hash_val, rindex));
   6798         }
   6799         if ((*key_cmp_fn)(entry, r_entry) == 0) {
   6800             *key_index = (index & TD2_ALPM_HASH_INDEX_MASK) >> 
   6801                             ((index & TD2_ALPM_HASH_IPV6_MASK) ? 1 : 0);
   6802             H_INDEX_MATCH("found", entry[0], index);
   6803             return(SOC_E_NONE);
   6804         }
   6805         /*
   6806         }
   6807         */
   6808         index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK];
   6809         H_INDEX_MATCH("lkup1", entry[0], index);
   6810     }
   6811     if (i > hash->entry_count) {
   6812         LOG_ERROR(BSL_LS_SOC_ALPM,
   6813                   (BSL_META_U(u,
   6814                             "Hash loop\n")));
   6815     }
   6816     H_INDEX_MATCH("not_found", entry[0], index);
   6817     return(SOC_E_NOT_FOUND);
   6818 }
   6819 
   6820 /*
   6821  * Function:
   6822  *      _soc_alpm_lpm_hash_insert
   6823  * Purpose:
   6824  *      Insert/Update a key index in the hash table
   6825  * Parameters:
   6826  *      hash - Pointer (handle) to Hash Table
   6827  *      key_cmp_fn - Compare function which should compare key
   6828  *      entry   - The key to lookup
   6829  *      pfx     - Prefix length for lookup acceleration.
   6830  *      old_index - Index where the key was moved from.
   6831  *                  TD2_ALPM_HASH_INDEX_NULL if new entry.
   6832  *      new_index - Index where the key was moved to.
   6833  * Returns:
   6834  *      SOC_E_NONE      Key found
   6835  */
   6836 /*
   6837  *      Should be caled before updating the LPM table so that the
   6838  *      data in the hash table is consistent with the LPM table
   6839  */
   6840 static
   6841 int _soc_alpm_lpm_hash_insert(_soc_alpm_lpm_hash_t *hash,
   6842                             _soc_alpm_lpm_hash_compare_fn key_cmp_fn,
   6843                             _soc_alpm_lpm_hash_entry_t entry,
   6844                             int    pfx,
   6845                             uint16 old_index,
   6846                             uint16 new_index,
   6847                             uint32 *rvt_index)
   6848 {
   6849 
   6850 #define INDEX_ADD(hash, hash_idx, new_idx)                      \
   6851     hash->link_table[new_idx & TD2_ALPM_HASH_INDEX_MASK] =        \
   6852         hash->table[hash_idx];                                  \
   6853     hash->table[hash_idx] = new_idx
   6854 
   6855 #define INDEX_ADD_LINK(hash, t_index, new_idx)                  \
   6856     hash->link_table[new_idx & TD2_ALPM_HASH_INDEX_MASK] =        \
   6857         hash->link_table[t_index & TD2_ALPM_HASH_INDEX_MASK];     \
   6858     hash->link_table[t_index & TD2_ALPM_HASH_INDEX_MASK] = new_idx
   6859 
   6860 #define INDEX_UPDATE(hash, hash_idx, old_idx, new_idx)          \
   6861     hash->table[hash_idx] = new_idx;                            \
   6862     hash->link_table[new_idx & TD2_ALPM_HASH_INDEX_MASK] =        \
   6863         hash->link_table[old_idx & TD2_ALPM_HASH_INDEX_MASK];     \
   6864     hash->link_table[old_idx & TD2_ALPM_HASH_INDEX_MASK] = TD2_ALPM_HASH_INDEX_NULL
   6865 
   6866 #define INDEX_UPDATE_LINK(hash, prev_idx, old_idx, new_idx)             \
   6867     hash->link_table[prev_idx & TD2_ALPM_HASH_INDEX_MASK] = new_idx;      \
   6868     hash->link_table[new_idx & TD2_ALPM_HASH_INDEX_MASK] =                \
   6869         hash->link_table[old_idx & TD2_ALPM_HASH_INDEX_MASK];             \
   6870     hash->link_table[old_idx & TD2_ALPM_HASH_INDEX_MASK] = TD2_ALPM_HASH_INDEX_NULL
   6871 
   6872 
   6873     int u = hash->unit, v, i = 0;
   6874 
   6875     uint16 hash_val;
   6876     uint16 index;
   6877     uint16 prev_index;
   6878 
   6879     if (rvt_index) {
   6880         *rvt_index = TD2_ALPM_HASH_INDEX_NULL;
   6881     }
   6882     hash_val = _soc_alpm_lpm_hash_compute((uint8 *)entry,
   6883                                         (32 * 5)) % hash->index_count;
   6884     index = hash->table[hash_val];
   6885     H_INDEX_MATCH("ihash", entry[0], hash_val);
   6886     H_INDEX_MATCH("ins  ", entry[0], new_index);
   6887     H_INDEX_MATCH("ins1 ", index, new_index);
   6888     prev_index = TD2_ALPM_HASH_INDEX_NULL;
   6889     if (old_index != TD2_ALPM_HASH_INDEX_NULL) {
   6890         while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   6891             uint32  e[SOC_MAX_MEM_FIELD_WORDS];
   6892             _soc_alpm_lpm_hash_entry_t  r_entry;
   6893             int     rindex;
   6894             
   6895             rindex = (index & TD2_ALPM_HASH_INDEX_MASK) >> 1;
   6896 
   6897             /*
   6898              * Check prefix length and skip index if not valid for given length
   6899             if ((SOC_ALPM_LPM_STATE_START(u, pfx) <= rindex) &&
   6900                 (SOC_ALPM_LPM_STATE_END(u, pfx) >= rindex)) {
   6901              */
   6902             SOC_IF_ERROR_RETURN(
   6903                 _soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY, rindex, e));
   6904             SOC_FB_LPM_HASH_ENTRY_GET(u, e, index, r_entry, &v);
   6905             if (v == 0) {
   6906                 if ((index & TD2_ALPM_HASH_IPV6_MASK) ||
   6907                     !((new_index & 1) && (new_index == (index + 1)))) {
   6908                     LOG_ERROR(BSL_LS_SOC_ALPM,
   6909                           (BSL_META_U(u,
   6910                                     "Empty entry[%d] in link_table. hash_val %d ridx %d nidx %d\n"),
   6911                                     index, hash_val, rindex, new_index));
   6912                 }
   6913             }
   6914             if (v && ((*key_cmp_fn)(entry, r_entry) == 0)) {
   6915                 /* assert(old_index == index);*/
   6916                 if (new_index != index) {
   6917                     H_INDEX_MATCH("imove", prev_index, new_index);
   6918                     if (prev_index == TD2_ALPM_HASH_INDEX_NULL) {
   6919                         INDEX_UPDATE(hash, hash_val, index, new_index);
   6920                     } else {
   6921                         INDEX_UPDATE_LINK(hash, prev_index, index, new_index);
   6922                     }
   6923                 }
   6924                 if (rvt_index) {
   6925                     *rvt_index = index;
   6926                 }
   6927                 H_INDEX_MATCH("imtch", index, new_index);
   6928                 return(SOC_E_NONE);
   6929             }
   6930             /*
   6931             }
   6932             */
   6933             prev_index = index;
   6934             index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK];
   6935             H_INDEX_MATCH("ins2 ", index, new_index);
   6936         }
   6937     }
   6938     if (i > hash->entry_count) {
   6939         LOG_ERROR(BSL_LS_SOC_ALPM,
   6940                   (BSL_META_U(u,
   6941                             "Hash loop\n")));
   6942         return SOC_E_INTERNAL;
   6943     }
   6944     INDEX_ADD(hash, hash_val, new_index);  /* new entry */
   6945     return(SOC_E_NONE);
   6946 }
   6947 
   6948 /*
   6949  * Function:
   6950  *      _soc_alpm_lpm_hash_revert
   6951  * Purpose:
   6952  *      Revert a key index in the hash table
   6953  * Parameters:
   6954  *      hash - Pointer (handle) to Hash Table
   6955  *      key_cmp_fn - Compare function which should compare key
   6956  *      entry   - The key to delete
   6957  *      pfx     - Prefix length for lookup acceleration.
   6958  *      delete_index - Index to delete.
   6959  * Returns:
   6960  *      SOC_E_NONE      Success
   6961  *      SOC_E_NOT_FOUND Key index not found.
   6962  */
   6963 static
   6964 int _soc_alpm_lpm_hash_revert(_soc_alpm_lpm_hash_t *hash,
   6965                             _soc_alpm_lpm_hash_compare_fn key_cmp_fn,
   6966                             _soc_alpm_lpm_hash_entry_t entry,
   6967                             uint16 new_index,
   6968                             uint32 rvt_index)
   6969 {
   6970     int u = hash->unit, i = 0;
   6971     uint16 hash_val;
   6972     uint16 index;
   6973     uint16 prev_index;
   6974 
   6975     hash_val = _soc_alpm_lpm_hash_compute((uint8 *)entry,
   6976                                         (32 * 5)) % hash->index_count;
   6977     index = hash->table[hash_val];
   6978     H_INDEX_MATCH("rhash", entry[0], hash_val);
   6979     H_INDEX_MATCH("rvt  ", entry[0], index);
   6980     prev_index = TD2_ALPM_HASH_INDEX_NULL;
   6981     while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   6982         if (new_index == index) {
   6983             H_INDEX_MATCH("dfoun", entry[0], index);
   6984             if (rvt_index == TD2_ALPM_HASH_INDEX_NULL) {
   6985                 if (prev_index == TD2_ALPM_HASH_INDEX_NULL) {
   6986                     INDEX_DELETE(hash, hash_val, new_index);
   6987                 } else {
   6988                     INDEX_DELETE_LINK(hash, prev_index, new_index);
   6989                     }
   6990             } else {
   6991                 if (prev_index == TD2_ALPM_HASH_INDEX_NULL) {
   6992                     INDEX_UPDATE(hash, hash_val, new_index, rvt_index);
   6993                 } else {
   6994                     INDEX_UPDATE_LINK(hash, prev_index, new_index, rvt_index);
   6995                 }
   6996             }
   6997             return(SOC_E_NONE);
   6998         }
   6999         prev_index = index;
   7000         index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK];
   7001         H_INDEX_MATCH("rvt1 ", entry[0], index);
   7002     }
   7003     if (i > hash->entry_count) {
   7004         LOG_ERROR(BSL_LS_SOC_ALPM,
   7005                   (BSL_META_U(u,
   7006                             "Hash loop\n")));
   7007     }
   7008     return(SOC_E_NOT_FOUND);
   7009 }
   7010 
   7011 
   7012 
   7013 /*
   7014  * Function:
   7015  *      _soc_alpm_lpm_hash_delete
   7016  * Purpose:
   7017  *      Delete a key index in the hash table
   7018  * Parameters:
   7019  *      hash - Pointer (handle) to Hash Table
   7020  *      key_cmp_fn - Compare function which should compare key
   7021  *      entry   - The key to delete
   7022  *      pfx     - Prefix length for lookup acceleration.
   7023  *      delete_index - Index to delete.
   7024  * Returns:
   7025  *      SOC_E_NONE      Success
   7026  *      SOC_E_NOT_FOUND Key index not found.
   7027  */
   7028 static
   7029 int _soc_alpm_lpm_hash_delete(_soc_alpm_lpm_hash_t *hash,
   7030                             _soc_alpm_lpm_hash_compare_fn key_cmp_fn,
   7031                             _soc_alpm_lpm_hash_entry_t entry,
   7032                             int    pfx,
   7033                             uint16 delete_index)
   7034 {
   7035     int u = hash->unit, i = 0;
   7036     uint16 hash_val;
   7037     uint16 index;
   7038     uint16 prev_index;
   7039 
   7040     hash_val = _soc_alpm_lpm_hash_compute((uint8 *)entry,
   7041                                         (32 * 5)) % hash->index_count;
   7042     index = hash->table[hash_val];
   7043     H_INDEX_MATCH("dhash", entry[0], hash_val);
   7044     H_INDEX_MATCH("del  ", entry[0], index);
   7045     prev_index = TD2_ALPM_HASH_INDEX_NULL;
   7046     while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   7047         if (delete_index == index) {
   7048             H_INDEX_MATCH("dfoun", entry[0], index);
   7049             if (prev_index == TD2_ALPM_HASH_INDEX_NULL) {
   7050                 INDEX_DELETE(hash, hash_val, delete_index);
   7051             } else {
   7052                 INDEX_DELETE_LINK(hash, prev_index, delete_index);
   7053             }
   7054             return(SOC_E_NONE);
   7055         }
   7056         prev_index = index;
   7057         index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK];
   7058         H_INDEX_MATCH("del1 ", entry[0], index);
   7059     }
   7060     if (i > hash->entry_count) {
   7061         LOG_ERROR(BSL_LS_SOC_ALPM,
   7062                   (BSL_META_U(u,
   7063                             "Hash loop\n")));
   7064     }
   7065     return(SOC_E_NOT_FOUND);
   7066 }
   7067 
   7068 
   7069 /*
   7070  * Function:
   7071  *      _soc_alpm_lpm_hash_verify
   7072  * Purpose:
   7073  *      Verify a key index in the hash table
   7074  * Parameters:
   7075  *      hash - Pointer (handle) to Hash Table
   7076  *      key_cmp_fn - Compare function which should compare key
   7077  *      entry   - The key to delete
   7078  *      pfx     - Prefix length for lookup acceleration.
   7079  *      verify_index   - Index to verify.
   7080  * Returns:
   7081  *      SOC_E_NONE      Success
   7082  *      SOC_E_NOT_FOUND Key index not found.
   7083  */
   7084 static
   7085 int _soc_alpm_lpm_hash_verify(_soc_alpm_lpm_hash_t *hash,
   7086                             _soc_alpm_lpm_hash_compare_fn key_cmp_fn,
   7087                             _soc_alpm_lpm_hash_entry_t entry,
   7088                             int    pfx,
   7089                             uint16 verify_index)
   7090 {
   7091     int u = hash->unit, i = 0;
   7092     uint16 hash_val;
   7093     uint16 index;
   7094 
   7095     hash_val = _soc_alpm_lpm_hash_compute((uint8 *)entry,
   7096                                         (32 * 5)) % hash->index_count;
   7097     index = hash->table[hash_val];
   7098     H_INDEX_MATCH("vhash", entry[0], hash_val);
   7099     H_INDEX_MATCH("veri ", entry[0], index);
   7100     while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   7101         if (verify_index == index) {
   7102             H_INDEX_MATCH("vfoun", entry[0], index);
   7103             return(SOC_E_NONE);
   7104         }
   7105         index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK];
   7106         H_INDEX_MATCH("veri1", entry[0], index);
   7107     }
   7108     if (i > hash->entry_count) {
   7109         LOG_ERROR(BSL_LS_SOC_ALPM,
   7110                   (BSL_META_U(u,
   7111                             "Hash loop\n")));
   7112     }
   7113     return(SOC_E_NOT_FOUND);
   7114 }
   7115 #else
   7116 #define LPM_HASH_INSERT(u, entry_data, tab_index, rvt_index0, rvt_index1)
   7117 #define LPM_HASH_REVERT(u, entry_data, tab_index, rvt_index0, rvt_index1)
   7118 #define LPM_HASH_DELETE(u, key_data, tab_index)
   7119 #define LPM_HASH_LOOKUP(u, key_data, pfx, tab_index)
   7120 #define LPM_HASH_VERIFY(u, key_data, tab_index)
   7121 #endif /* FB_LPM_HASH_SUPPORT */
   7122 
   7123 int
   7124 _ipmask2pfx(uint32 ipv4m, int *mask_len)
   7125 {
   7126     *mask_len = 0;
   7127     while (ipv4m & (1 << 31)) {
   7128         *mask_len += 1;
   7129         ipv4m <<= 1;
   7130     }
   7131 
   7132     return ((ipv4m) ? SOC_E_PARAM : SOC_E_NONE);
   7133 }
   7134 
   7135 /* src and dst can be same */
   7136 int
   7137 soc_alpm_lpm_ip4entry0_to_0(int u, void *src, void *dst, int copy_hit)
   7138 {
   7139     uint32      ipv4a;
   7140 
   7141     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VALID0f);
   7142     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VALID0f, ipv4a);
   7143 
   7144     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MODE0f);
   7145     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MODE0f, ipv4a);
   7146     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, MODE_MASK0f)) {
   7147         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MODE_MASK0f);
   7148         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MODE_MASK0f, ipv4a);
   7149     }
   7150 
   7151     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, GLOBAL_ROUTE0f)) {
   7152         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_ROUTE0f);
   7153         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_ROUTE0f, ipv4a);
   7154     }
   7155 
   7156     if (soc_feature(u, soc_feature_ipmc_defip)) {
   7157         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MULTICAST_ROUTE0f);
   7158         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MULTICAST_ROUTE0f, ipv4a);
   7159 
   7160         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPA_ID0f);
   7161         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPA_ID0f, ipv4a);
   7162 
   7163         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, EXPECTED_L3_IIF0f);
   7164         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, EXPECTED_L3_IIF0f, ipv4a);
   7165 
   7166         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f);
   7167         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f, ipv4a);
   7168 
   7169         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f);
   7170         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f, ipv4a);
   7171 
   7172         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, L3MC_INDEX0f);
   7173         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, L3MC_INDEX0f, ipv4a);
   7174     }
   7175 
   7176     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR0f);
   7177     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR0f, ipv4a);
   7178 
   7179     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR_MASK0f);
   7180     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR_MASK0f, ipv4a);
   7181 
   7182     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP0f)) {
   7183         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP0f);
   7184         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP0f, ipv4a);
   7185     }
   7186 
   7187     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP_COUNT0f)) {
   7188             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_COUNT0f);
   7189             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_COUNT0f, ipv4a);
   7190 
   7191             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_PTR0f);
   7192             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_PTR0f, ipv4a);
   7193     } else {
   7194         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, NEXT_HOP_INDEX0f);
   7195         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, NEXT_HOP_INDEX0f, ipv4a);
   7196     }
   7197 
   7198     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, PRI0f);
   7199     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, PRI0f, ipv4a);
   7200 
   7201     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPE0f);
   7202     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPE0f, ipv4a);
   7203 
   7204     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f)) {
   7205         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_0f);
   7206         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_0f, ipv4a);
   7207         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_MASK0f);
   7208         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_MASK0f, ipv4a);
   7209     }
   7210 
   7211     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD0f)) {
   7212         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DST_DISCARD0f);
   7213         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DST_DISCARD0f, ipv4a);
   7214     }
   7215     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, CLASS_ID0f)) {
   7216         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, CLASS_ID0f);
   7217         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, CLASS_ID0f, ipv4a);
   7218     }
   7219     if (copy_hit) {
   7220         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, HIT0f);
   7221         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, HIT0f, ipv4a);
   7222     }
   7223 
   7224     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_HIGH0f);
   7225     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_HIGH0f, ipv4a);
   7226 
   7227     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ALG_HIT_IDX0f);
   7228     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ALG_HIT_IDX0f, ipv4a);
   7229 
   7230     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ALG_BKT_PTR0f);
   7231     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ALG_BKT_PTR0f, ipv4a);
   7232 
   7233     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DEFAULT_MISS0f);
   7234     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DEFAULT_MISS0f, ipv4a);
   7235 
   7236     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_BASE_COUNTER_IDX0f);
   7237     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_BASE_COUNTER_IDX0f, ipv4a);
   7238 
   7239     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_POOL_NUMBER0f);
   7240     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_POOL_NUMBER0f, ipv4a);
   7241 
   7242     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_OFFSET_MODE0f);
   7243     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_OFFSET_MODE0f, ipv4a);
   7244 
   7245     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ENTRY_VIEW0f);
   7246     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ENTRY_VIEW0f, ipv4a);
   7247 
   7248     return(SOC_E_NONE);
   7249 }
   7250 
   7251 int
   7252 soc_alpm_lpm_ip4entry1_to_1(int u, void *src, void *dst, int copy_hit)
   7253 {
   7254     uint32      ipv4a;
   7255 
   7256     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VALID1f);
   7257     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VALID1f, ipv4a);
   7258 
   7259     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MODE1f);
   7260     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MODE1f, ipv4a);
   7261     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, MODE_MASK1f)) {
   7262         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MODE_MASK1f);
   7263         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MODE_MASK1f, ipv4a);
   7264     }
   7265 
   7266     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, GLOBAL_ROUTE1f)) {
   7267         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_ROUTE1f);
   7268         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_ROUTE1f, ipv4a);
   7269     }
   7270 
   7271     if (soc_feature(u, soc_feature_ipmc_defip)) {
   7272         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MULTICAST_ROUTE1f);
   7273         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MULTICAST_ROUTE1f, ipv4a);
   7274 
   7275         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPA_ID1f);
   7276         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPA_ID1f, ipv4a);
   7277 
   7278         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, EXPECTED_L3_IIF1f);
   7279         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, EXPECTED_L3_IIF1f, ipv4a);
   7280 
   7281         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f);
   7282         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f, ipv4a);
   7283 
   7284         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f);
   7285         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f, ipv4a);
   7286 
   7287         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, L3MC_INDEX1f);
   7288         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, L3MC_INDEX1f, ipv4a);
   7289     }
   7290 
   7291     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR1f);
   7292     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR1f, ipv4a);
   7293 
   7294     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR_MASK1f);
   7295     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR_MASK1f, ipv4a);
   7296 
   7297     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP1f)) {
   7298         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP1f);
   7299         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP1f, ipv4a);
   7300     }
   7301 
   7302     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP_COUNT1f)) {
   7303         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_COUNT1f);
   7304         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_COUNT1f, ipv4a);
   7305 
   7306         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_PTR1f);
   7307         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_PTR1f, ipv4a);
   7308     } else {
   7309         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, NEXT_HOP_INDEX1f);
   7310         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, NEXT_HOP_INDEX1f, ipv4a);
   7311     }
   7312 
   7313     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, PRI1f);
   7314     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, PRI1f, ipv4a);
   7315 
   7316     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPE1f);
   7317     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPE1f, ipv4a);
   7318 
   7319     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_1f)) {
   7320         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_1f);
   7321         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_1f, ipv4a);
   7322         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_MASK1f);
   7323         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_MASK1f, ipv4a);
   7324     }
   7325 
   7326     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD1f)) {
   7327         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DST_DISCARD1f);
   7328         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DST_DISCARD1f, ipv4a);
   7329     }
   7330     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, CLASS_ID1f)) {
   7331         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, CLASS_ID1f);
   7332         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, CLASS_ID1f, ipv4a);
   7333     }
   7334     if (copy_hit) {
   7335         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, HIT1f);
   7336         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, HIT1f, ipv4a);
   7337     }
   7338 
   7339     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_HIGH1f);
   7340     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_HIGH1f, ipv4a);
   7341 
   7342     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ALG_HIT_IDX1f);
   7343     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ALG_HIT_IDX1f, ipv4a);
   7344 
   7345     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ALG_BKT_PTR1f);
   7346     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ALG_BKT_PTR1f, ipv4a);
   7347 
   7348     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DEFAULT_MISS1f);
   7349     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DEFAULT_MISS1f, ipv4a);
   7350 
   7351     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_BASE_COUNTER_IDX1f);
   7352     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_BASE_COUNTER_IDX1f, ipv4a);
   7353 
   7354     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_POOL_NUMBER1f);
   7355     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_POOL_NUMBER1f, ipv4a);
   7356 
   7357     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_OFFSET_MODE1f);
   7358     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_OFFSET_MODE1f, ipv4a);
   7359 
   7360     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ENTRY_VIEW1f);
   7361     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ENTRY_VIEW1f, ipv4a);
   7362 
   7363     return(SOC_E_NONE);
   7364 }
   7365 
   7366 /* src and dst can be same */
   7367 int
   7368 soc_alpm_lpm_ip4entry0_to_1(int u, void *src, void *dst, int copy_hit)
   7369 {
   7370     uint32      ipv4a;
   7371 
   7372     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VALID0f);
   7373     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VALID1f, ipv4a);
   7374 
   7375     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MODE0f);
   7376     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MODE1f, ipv4a);
   7377     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, MODE_MASK0f)) {
   7378         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MODE_MASK0f);
   7379         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MODE_MASK1f, ipv4a);
   7380     }
   7381     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, GLOBAL_ROUTE0f)) {
   7382         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_ROUTE0f);
   7383         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_ROUTE1f, ipv4a);
   7384     }
   7385 
   7386     if (soc_feature(u, soc_feature_ipmc_defip)) {
   7387         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MULTICAST_ROUTE0f);
   7388         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MULTICAST_ROUTE1f, ipv4a);
   7389 
   7390         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPA_ID0f);
   7391         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPA_ID1f, ipv4a);
   7392 
   7393         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, EXPECTED_L3_IIF0f);
   7394         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, EXPECTED_L3_IIF1f, ipv4a);
   7395 
   7396         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f);
   7397         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f, ipv4a);
   7398 
   7399         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f);
   7400         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f, ipv4a);
   7401 
   7402         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, L3MC_INDEX0f);
   7403         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, L3MC_INDEX1f, ipv4a);
   7404     }
   7405 
   7406     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR0f);
   7407     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR1f, ipv4a);
   7408 
   7409     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR_MASK0f);
   7410     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR_MASK1f, ipv4a);
   7411 
   7412     if (!SOC_IS_HURRICANE(u)) {
   7413         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP0f);
   7414         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP1f, ipv4a);
   7415     }
   7416 
   7417     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP_COUNT0f)) {
   7418         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_COUNT0f);
   7419         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_COUNT1f, ipv4a);
   7420 
   7421         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_PTR0f);
   7422         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_PTR1f, ipv4a);
   7423     } else {
   7424         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, NEXT_HOP_INDEX0f);
   7425         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, NEXT_HOP_INDEX1f, ipv4a);
   7426     }
   7427 
   7428     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, PRI0f);
   7429     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, PRI1f, ipv4a);
   7430 
   7431     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPE0f);
   7432     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPE1f, ipv4a);
   7433 
   7434     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f)) {
   7435         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_0f);
   7436         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_1f, ipv4a);
   7437         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_MASK0f);
   7438         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_MASK1f, ipv4a);
   7439     }
   7440 
   7441     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD0f)) {
   7442         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DST_DISCARD0f);
   7443         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DST_DISCARD1f, ipv4a);
   7444     }
   7445 
   7446     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, CLASS_ID0f)) {
   7447         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, CLASS_ID0f);
   7448         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, CLASS_ID1f, ipv4a);
   7449     }
   7450     if (copy_hit) {
   7451         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, HIT0f);
   7452         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, HIT1f, ipv4a);
   7453     }
   7454 
   7455     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_HIGH0f);
   7456     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_HIGH1f, ipv4a);
   7457 
   7458     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ALG_HIT_IDX0f);
   7459     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ALG_HIT_IDX1f, ipv4a);
   7460 
   7461     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ALG_BKT_PTR0f);
   7462     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ALG_BKT_PTR1f, ipv4a);
   7463 
   7464     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DEFAULT_MISS0f);
   7465     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DEFAULT_MISS1f, ipv4a);
   7466 
   7467     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_BASE_COUNTER_IDX0f);
   7468     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_BASE_COUNTER_IDX1f, ipv4a);
   7469 
   7470     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_POOL_NUMBER0f);
   7471     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_POOL_NUMBER1f, ipv4a);
   7472 
   7473     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_OFFSET_MODE0f);
   7474     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_OFFSET_MODE1f, ipv4a);
   7475 
   7476     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ENTRY_VIEW0f);
   7477     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ENTRY_VIEW1f, ipv4a);
   7478 
   7479     return(SOC_E_NONE);
   7480 }
   7481 
   7482 /* src and dst can be same */
   7483 int
   7484 soc_alpm_lpm_ip4entry1_to_0(int u, void *src, void *dst, int copy_hit)
   7485 {
   7486     uint32      ipv4a;
   7487 
   7488     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VALID1f);
   7489     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VALID0f, ipv4a);
   7490 
   7491     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MODE1f);
   7492     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MODE0f, ipv4a);
   7493     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, MODE_MASK0f)) {
   7494         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MODE_MASK1f);
   7495         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MODE_MASK0f, ipv4a);
   7496     }
   7497     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, GLOBAL_ROUTE1f)) {
   7498         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_ROUTE1f);
   7499         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_ROUTE0f, ipv4a);
   7500     }
   7501 
   7502     if (soc_feature(u, soc_feature_ipmc_defip)) {
   7503         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MULTICAST_ROUTE1f);
   7504         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MULTICAST_ROUTE0f, ipv4a);
   7505 
   7506         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPA_ID1f);
   7507         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPA_ID0f, ipv4a);
   7508 
   7509         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, EXPECTED_L3_IIF1f);
   7510         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, EXPECTED_L3_IIF0f, ipv4a);
   7511 
   7512         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f);
   7513         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f, ipv4a);
   7514 
   7515         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f);
   7516         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f, ipv4a);
   7517 
   7518         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, L3MC_INDEX1f);
   7519         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, L3MC_INDEX0f, ipv4a);
   7520     }
   7521 
   7522     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR1f);
   7523     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR0f, ipv4a);
   7524 
   7525     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR_MASK1f);
   7526     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR_MASK0f, ipv4a);
   7527 
   7528     if (!SOC_IS_HURRICANE(u)) {
   7529         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP1f);
   7530         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP0f, ipv4a);
   7531     }
   7532 
   7533     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP_COUNT1f)) {
   7534         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_COUNT1f);
   7535         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_COUNT0f, ipv4a);
   7536 
   7537         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_PTR1f);
   7538         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_PTR0f, ipv4a);
   7539     } else {
   7540         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, NEXT_HOP_INDEX1f);
   7541         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, NEXT_HOP_INDEX0f, ipv4a);
   7542     }
   7543 
   7544     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, PRI1f);
   7545     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, PRI0f, ipv4a);
   7546 
   7547     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPE1f);
   7548     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPE0f, ipv4a);
   7549 
   7550     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_1f)) {
   7551         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_1f);
   7552         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_0f, ipv4a);
   7553         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_MASK1f);
   7554         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_MASK0f, ipv4a);
   7555     }
   7556 
   7557     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD1f)) {
   7558         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DST_DISCARD1f);
   7559         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DST_DISCARD0f, ipv4a);
   7560     }
   7561 
   7562     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, CLASS_ID1f)) {
   7563         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, CLASS_ID1f);
   7564         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, CLASS_ID0f, ipv4a);
   7565     }
   7566     if (copy_hit) {
   7567         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, HIT1f);
   7568         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, HIT0f, ipv4a);
   7569     }
   7570 
   7571     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_HIGH1f);
   7572     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_HIGH0f, ipv4a);
   7573 
   7574     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ALG_HIT_IDX1f);
   7575     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ALG_HIT_IDX0f, ipv4a);
   7576 
   7577     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ALG_BKT_PTR1f);
   7578     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ALG_BKT_PTR0f, ipv4a);
   7579 
   7580     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DEFAULT_MISS1f);
   7581     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DEFAULT_MISS0f, ipv4a);
   7582 
   7583     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_BASE_COUNTER_IDX1f);
   7584     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_BASE_COUNTER_IDX0f, ipv4a);
   7585 
   7586     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_POOL_NUMBER1f);
   7587     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_POOL_NUMBER0f, ipv4a);
   7588 
   7589     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_OFFSET_MODE1f);
   7590     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_OFFSET_MODE0f, ipv4a);
   7591 
   7592     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ENTRY_VIEW1f);
   7593     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ENTRY_VIEW0f, ipv4a);
   7594 
   7595     return(SOC_E_NONE);
   7596 }
   7597 
   7598 void
   7599 soc_alpm_lpm_state_dump(int u)
   7600 {
   7601     int i;
   7602     int max_pfx_len;
   7603     max_pfx_len = ALPM_MAX_PFX_INDEX;
   7604 
   7605 #ifndef BCM_WARM_BOOT_SUPPORT_SW_DUMP
   7606     if (!bsl_check(bslLayerSoc, bslSourceAlpm, bslSeverityVerbose, u)) {
   7607         return;
   7608     }
   7609 #endif
   7610 
   7611     for(i = max_pfx_len; i >= 0 ; i--) {
   7612         if ((i != ALPM_MAX_PFX_INDEX) && (SOC_ALPM_LPM_STATE_START(u, i) == -1)) {
   7613             continue;
   7614         }
   7615 
   7616 #ifdef ALPM_WARM_BOOT_DEBUG
   7617         LOG_ERROR(BSL_LS_SOC_ALPM,
   7618                   (BSL_META_U(u,
   7619                               "PFX = %d P = %d N = %d START = %d END = %d VENT = %d FENT = %d\n"),
   7620                    i,
   7621                    SOC_ALPM_LPM_STATE_PREV(u, i),
   7622                    SOC_ALPM_LPM_STATE_NEXT(u, i),
   7623                    SOC_ALPM_LPM_STATE_START(u, i),
   7624                    SOC_ALPM_LPM_STATE_END(u, i),
   7625                    SOC_ALPM_LPM_STATE_VENT(u, i),
   7626                    SOC_ALPM_LPM_STATE_FENT(u, i)));
   7627 #else
   7628         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7629                     (BSL_META_U(u,
   7630                                 "PFX = %d P = %d N = %d START = %d END = %d VENT = %d FENT = %d\n"),
   7631                      i,
   7632                      SOC_ALPM_LPM_STATE_PREV(u, i),
   7633                      SOC_ALPM_LPM_STATE_NEXT(u, i),
   7634                      SOC_ALPM_LPM_STATE_START(u, i),
   7635                      SOC_ALPM_LPM_STATE_END(u, i),
   7636                      SOC_ALPM_LPM_STATE_VENT(u, i),
   7637                      SOC_ALPM_LPM_STATE_FENT(u, i)));
   7638 #endif        
   7639     }
   7640 }
   7641 
   7642 
   7643 /*
   7644  * Function:
   7645  *      _lpm_fb_urpf_entry_replicate
   7646  * Purpose:
   7647  *      Replicate entry to the second half of the tcam if URPF check is ON.
   7648  * Parameters:
   7649  *      u           - (IN)  SOC unit number.
   7650  *      index:      - (IN)  corresponding dip target index
   7651  *      e           - (IN|OUT) input dip entry, could be modified for sip
   7652  *      src_index   - (IN)  if ALPM_INVALID_INDEX use input e,
   7653  *                          otherwise copy from src_index.
   7654  *      convert     - (IN)  Used if src_index != ALPM_INVALID_INDEX.
   7655  *      src_default - (IN)  Used if src_index = ALPM_INVALID_INDEX.
   7656  *                            0 - caculate using entry_data's mask (legacy way)
   7657  *                            1 - force set (split case) 
   7658  *      src_discard - (IN)  Used if src_index = ALPM_INVALID_INDEX.
   7659  * Returns:
   7660  *      BCM_E_XXX
   7661  */
   7662 static 
   7663 int _lpm_fb_urpf_entry_replicate(int u, int src_index, int index, uint32 *e,
   7664                                  int convert, int src_default, int src_discard,
   7665                                  int bpm_len, int v4_half)
   7666 {
   7667     int src_tcam_offset;  /* Defip memory size/2 urpf source lookup offset */
   7668     int ipv6;             /* IPv6 entry.                                   */
   7669     uint32 mask0;         /* Mask 0 field value.                           */
   7670     uint32 mask1;         /* Mask 1 field value.                           */
   7671     int def_gw_flag;      /* Entry is default gateway.                     */ 
   7672     defip_entry_t urpf;
   7673 
   7674     if(!SOC_URPF_STATUS_GET(u)) {
   7675         return (SOC_E_NONE);
   7676     }
   7677 
   7678     src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1);
   7679 
   7680     ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, MODE0f);
   7681  
   7682     if (src_index != ALPM_INVALID_INDEX) {
   7683 #ifdef FB_LPM_TABLE_CACHED
   7684         SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, L3_DEFIPm,
   7685                                 MEM_BLOCK_ANY,
   7686                                 src_index + src_tcam_offset));
   7687 #endif /* FB_LPM_TABLE_CACHED */
   7688 
   7689         SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY,
   7690                             src_index + src_tcam_offset,
   7691                             &urpf));
   7692         switch (convert) {
   7693         case CONVERT_NONE:
   7694             sal_memcpy(e, &urpf, sizeof(defip_entry_t));
   7695             break;
   7696         case 0:
   7697             mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, &urpf, RPE0f);
   7698             mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, &urpf, DST_DISCARD0f);
   7699             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE0f, mask0);
   7700             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD0f, mask1);
   7701             break;
   7702         case 1:
   7703             mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, &urpf, RPE0f);
   7704             mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, &urpf, DST_DISCARD0f);
   7705             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE1f, mask0);
   7706             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD1f, mask1);
   7707             break;
   7708         case 2:
   7709             mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, &urpf, RPE1f);
   7710             mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, &urpf, DST_DISCARD1f);
   7711             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE0f, mask0);
   7712             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD0f, mask1);
   7713             break;
   7714         case 3:
   7715             mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, &urpf, RPE1f);
   7716             mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, &urpf, DST_DISCARD1f);
   7717             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE1f, mask0);
   7718             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD1f, mask1);
   7719             break;
   7720         default:
   7721             return SOC_E_INTERNAL;
   7722         }
   7723 
   7724         /* Write entry to the second half of the tcam. */
   7725         /* Better use index instead of (index + src_tcam_offset) for src_index, 
   7726          * because the entry at index is just written, and we can simply form
   7727          * aux based on it, it's simple. 
   7728          * But if we use (index + src_tcam_offset), we have to do convert again.
   7729          */
   7730         return _soc_alpm_write_pivot_aux(u, index, index + src_tcam_offset, e,
   7731                                          CONVERT_NONE, bpm_len, v4_half);
   7732     }
   7733 
   7734     src_default = src_default ? 1 : 0;
   7735     src_discard = src_discard ? 1 : 0;
   7736 
   7737     /* Set/Reset default gateway flag based on ip mask value. */
   7738     mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, IP_ADDR_MASK0f);
   7739     mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, IP_ADDR_MASK1f);
   7740 
   7741     if (!ipv6) {
   7742         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f)) {
   7743             def_gw_flag = (!mask0) ? 1 : 0;
   7744             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE0f, src_default | def_gw_flag);
   7745             if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD0f)) {
   7746                 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD0f, src_discard);
   7747             }
   7748         }
   7749 
   7750         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f)) {
   7751             def_gw_flag = (!mask1) ? 1 : 0;
   7752             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE1f, src_default | def_gw_flag);
   7753             if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD1f)) {
   7754                 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD1f, src_discard);
   7755             }
   7756         }
   7757     } else {
   7758         def_gw_flag = ((!mask0) &&  (!mask1)) ? 1 : 0;
   7759         mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f);
   7760         mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f);
   7761         if (mask0 && mask1) {
   7762             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE0f, src_default | def_gw_flag);
   7763             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE1f, src_default | def_gw_flag);
   7764             if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD0f)) {
   7765                 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD0f, src_discard);
   7766                 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD1f, src_discard);
   7767             }
   7768         }
   7769     }
   7770     /* Write entry to the second half of the tcam. */
   7771     return _soc_alpm_write_pivot_aux(u, index, index + src_tcam_offset, e,
   7772                                      CONVERT_NONE, bpm_len, v4_half);
   7773 }
   7774 
   7775 static int
   7776 _soc_alpm_write_pivot_with_bpm(int u, int src_index, int index, void *entry,
   7777                                uint32 op, int src_default_or_convert,
   7778                                int src_discard, int bpm_len, int v4_half)
   7779 {
   7780 
   7781     int convert = CONVERT_NONE;
   7782     int src_index_uprf = ALPM_INVALID_INDEX;
   7783     int sdefault = 0, sdiscard = 0;
   7784     uint32  rvt_index0 = 0, rvt_index1 = 0;
   7785     int rv;
   7786 
   7787     switch (op & (~WRITE_PIVOT_WITHOUT_INSERT_HASH)) {
   7788     case WRITE_PIVOT_WITH_SRC_INDEX:
   7789         src_index_uprf = src_index;
   7790         break;
   7791     case WRITE_PIVOT_WITH_SRC_INDEX_CONVERT:
   7792         src_index_uprf = src_index;
   7793         convert        = src_default_or_convert;
   7794         break;
   7795     case WRITE_PIVOT_WITH_URPF_PARAMS:
   7796         sdefault = src_default_or_convert;
   7797         sdiscard = src_discard;
   7798         break;
   7799     default:
   7800         return SOC_E_INTERNAL;
   7801     }
   7802 
   7803     if (!(op & WRITE_PIVOT_WITHOUT_INSERT_HASH)) {
   7804         LPM_HASH_INSERT(u, entry, index, &rvt_index0, &rvt_index1);
   7805     }
   7806 
   7807     /* Do not use src_index_urpf because it can be invalid.
   7808      * For aux entry, reading src from HW is required for BPM_LENGTH.
   7809      */
   7810     rv = (_soc_alpm_write_pivot_aux(u, src_index, index, entry, convert, bpm_len, v4_half));
   7811 
   7812     if (rv >= 0) {
   7813         rv = (_lpm_fb_urpf_entry_replicate(u, src_index_uprf, index, entry,
   7814                                           convert, sdefault, sdiscard, bpm_len, v4_half));
   7815     }
   7816     if (!(op & WRITE_PIVOT_WITHOUT_INSERT_HASH) && rv < 0) {
   7817         LPM_HASH_REVERT(u, entry, index, rvt_index0, rvt_index1);
   7818     }
   7819 
   7820     return rv;
   7821 }
   7822 static int
   7823 _soc_alpm_write_pivot(int u, int src_index, int index, void *entry,
   7824                       uint32 op, int src_default_or_convert, int src_discard)
   7825 {
   7826     return _soc_alpm_write_pivot_with_bpm(u, src_index, index, entry, op,
   7827                         src_default_or_convert, src_discard, INVALID_BPM_LEN, 0);
   7828 }
   7829 static void
   7830 _soc_alpm_move_pivot(int u, int src, int dst, int src_half, int dst_half)
   7831 {
   7832     alpm_pivot_t *src_pivot;
   7833 
   7834     src = soc_alpm_physical_idx((u), L3_DEFIPm, (src), 1) << 1;
   7835     dst = soc_alpm_physical_idx((u), L3_DEFIPm, (dst), 1) << 1;
   7836     src += src_half ? 1 : 0; 
   7837     dst += dst_half ? 1 : 0;
   7838 
   7839     src_pivot = ALPM_TCAM_PIVOT(u, src);
   7840     if (src_pivot) { 
   7841         PIVOT_TCAM_INDEX(src_pivot) = dst;
   7842     }
   7843 
   7844     ALPM_TCAM_PIVOT(u, dst) = src_pivot;
   7845     ALPM_TCAM_PIVOT(u, src) = NULL;
   7846 
   7847     return;
   7848 }
   7849 
   7850 /*
   7851  *      Create a slot for the new entry rippling the entries if required
   7852  */
   7853 static
   7854 int _lpm_fb_entry_shift(int u, int from_ent, int to_ent)
   7855 {
   7856     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   7857 
   7858     if (from_ent == to_ent) {
   7859         return SOC_E_NONE;
   7860     }
   7861 
   7862 #ifdef FB_LPM_TABLE_CACHED
   7863     SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, L3_DEFIPm,
   7864                                        MEM_BLOCK_ANY, from_ent));
   7865 #endif /* FB_LPM_TABLE_CACHED */
   7866 
   7867     SOC_IF_ERROR_RETURN(
   7868         _soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY, from_ent, e));
   7869 
   7870     SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, to_ent, e,
   7871                                               WRITE_PIVOT_WITH_SRC_INDEX, 0, 0));
   7872 
   7873     /* from_ent != to_ent */
   7874     _soc_alpm_move_pivot(u, from_ent, to_ent, 0, 0);
   7875     _soc_alpm_move_pivot(u, from_ent, to_ent, 1, 1);
   7876     return (SOC_E_NONE);
   7877 }
   7878 
   7879 
   7880 /*
   7881  *      Shift prefix entries 1 entry UP, while preserving  
   7882  *      last half empty IPv4 entry if any.
   7883  */
   7884 static
   7885 int _lpm_fb_shift_pfx_up(int u, int pfx, int ipv6)
   7886 {
   7887     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   7888     int         from_ent;
   7889     int         to_ent;
   7890     uint32      v0, v1;
   7891 
   7892     to_ent = SOC_ALPM_LPM_STATE_END(u, pfx) + 1;
   7893 
   7894     ipv6 = SOC_ALPM_PFX_IS_V6_64(u, pfx);
   7895     if (!ipv6) {
   7896         from_ent = SOC_ALPM_LPM_STATE_END(u, pfx);
   7897 #ifdef FB_LPM_TABLE_CACHED
   7898         SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, L3_DEFIPm,
   7899                                                      MEM_BLOCK_ANY, from_ent));
   7900 #endif /* FB_LPM_TABLE_CACHED */
   7901         SOC_IF_ERROR_RETURN(
   7902             _soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY, from_ent, e));
   7903         v0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f);
   7904         v1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f);
   7905 
   7906         if ((v0 == 0) || (v1 == 0)) {
   7907             /* Last entry is half full -> keep it last. */
   7908             SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, to_ent, e,
   7909                                           WRITE_PIVOT_WITH_SRC_INDEX, 0, 0));
   7910 
   7911             /* track pivot state movement */
   7912             /* from_ent != to_ent */
   7913             _soc_alpm_move_pivot(u, from_ent, to_ent, v1, 0);
   7914             to_ent--;
   7915         }
   7916     }
   7917 
   7918     from_ent = SOC_ALPM_LPM_STATE_START(u, pfx);
   7919     if (from_ent != to_ent) {
   7920         SOC_IF_ERROR_RETURN(_lpm_fb_entry_shift(u, from_ent, to_ent));
   7921         VRF_PIVOT_SHIFT_INC(u, MAX_VRF_ID, ipv6);
   7922     } 
   7923     SOC_ALPM_LPM_STATE_START(u, pfx) += 1;
   7924     SOC_ALPM_LPM_STATE_END(u, pfx) += 1;
   7925     return (SOC_E_NONE);
   7926 }
   7927 
   7928 /*
   7929  *      Shift prefix entries 1 entry DOWN, while preserving  
   7930  *      last half empty IPv4 entry if any.
   7931  */
   7932 static
   7933 int _lpm_fb_shift_pfx_down(int u, int pfx, int ipv6)
   7934 {
   7935     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   7936     int         from_ent;
   7937     int         to_ent;
   7938     int         prev_ent;
   7939     uint32      v0, v1;
   7940 
   7941     to_ent = SOC_ALPM_LPM_STATE_START(u, pfx) - 1;
   7942 
   7943     /* Don't move empty prefix . */ 
   7944     if (SOC_ALPM_LPM_STATE_VENT(u, pfx) == 0) {
   7945         SOC_ALPM_LPM_STATE_START(u, pfx) = to_ent;
   7946         SOC_ALPM_LPM_STATE_END(u, pfx) = to_ent - 1;
   7947         return (SOC_E_NONE);
   7948     }
   7949 
   7950     ipv6 = SOC_ALPM_PFX_IS_V6_64(u, pfx);
   7951     if ((!ipv6) && (SOC_ALPM_LPM_STATE_END(u, pfx) != SOC_ALPM_LPM_STATE_START(u, pfx))) {
   7952 
   7953         from_ent = SOC_ALPM_LPM_STATE_END(u, pfx);
   7954 
   7955 #ifdef FB_LPM_TABLE_CACHED
   7956         SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, L3_DEFIPm,
   7957                                                      MEM_BLOCK_ANY, from_ent));
   7958 #endif /* FB_LPM_TABLE_CACHED */
   7959         SOC_IF_ERROR_RETURN(
   7960             _soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY, from_ent, e));
   7961         v0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f);
   7962         v1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f);
   7963 
   7964         if ((v0 == 0) || (v1 == 0)) {
   7965             /* Last entry is half full -> keep it last. */
   7966             /* Shift entry before last to start - 1 position. */
   7967             prev_ent = from_ent - 1;
   7968             SOC_IF_ERROR_RETURN(_lpm_fb_entry_shift(u, prev_ent, to_ent));
   7969             VRF_PIVOT_SHIFT_INC(u, MAX_VRF_ID, ipv6);
   7970 
   7971 
   7972             SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, prev_ent, e,
   7973                                             WRITE_PIVOT_WITH_SRC_INDEX, 0, 0));
   7974 
   7975             /* from_ent != prev_ent */
   7976             _soc_alpm_move_pivot(u, from_ent, prev_ent, v1, 0);
   7977         } else {
   7978             /* Last entry is full -> just shift it to start - 1  position. */
   7979 
   7980             SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, to_ent, e,
   7981                                             WRITE_PIVOT_WITH_SRC_INDEX, 0, 0));
   7982 
   7983             /* Track full-entry move */
   7984             /* from_ent != to_ent */
   7985             _soc_alpm_move_pivot(u, from_ent, to_ent, 0, 0);
   7986             _soc_alpm_move_pivot(u, from_ent, to_ent, 1, 1);
   7987         }
   7988 
   7989     } else  { 
   7990 
   7991         from_ent = SOC_ALPM_LPM_STATE_END(u, pfx);
   7992         SOC_IF_ERROR_RETURN(_lpm_fb_entry_shift(u, from_ent, to_ent));
   7993         VRF_PIVOT_SHIFT_INC(u, MAX_VRF_ID, ipv6);
   7994 
   7995     }
   7996     SOC_ALPM_LPM_STATE_START(u, pfx) -= 1;
   7997     SOC_ALPM_LPM_STATE_END(u, pfx) -= 1;
   7998 
   7999     return (SOC_E_NONE);
   8000 }
   8001 
   8002 /*
   8003  *      Create a slot for the new entry rippling the entries if required
   8004  */
   8005 static
   8006 int _lpm_free_slot_create(int u, int pfx, int ipv6, void *e, int *free_slot)
   8007 {
   8008     int         prev_pfx;
   8009     int         next_pfx;
   8010     int         free_pfx;
   8011     int         curr_pfx;
   8012     int         from_ent;
   8013     uint32      v0, v1;
   8014     int         rv;
   8015 
   8016 
   8017     if (SOC_ALPM_LPM_STATE_VENT(u, pfx) == 0) {
   8018         /*
   8019          * Find the  prefix position. Only prefix with valid
   8020          * entries are in the list.
   8021          * next -> high to low prefix. low to high index
   8022          * prev -> low to high prefix. high to low index
   8023          * Unused prefix length ALPM_MAX_PFX_INDEX is the head of the
   8024          * list and is node corresponding to this is always
   8025          * present.
   8026          */
   8027         curr_pfx = ALPM_MAX_PFX_INDEX;
   8028         if (soc_alpm_mode_get(u) == SOC_ALPM_MODE_PARALLEL) {
   8029             if (pfx <= ALPM_MAX_VRF_PFX_INDEX) {
   8030                 curr_pfx = ALPM_MAX_VRF_PFX_INDEX;
   8031             }
   8032         }
   8033         while (SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx) > pfx) {
   8034             curr_pfx = SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx);
   8035         }
   8036         /* Insert the new prefix */
   8037         next_pfx = SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx);
   8038         if (next_pfx != -1) {
   8039             SOC_ALPM_LPM_STATE_PREV(u, next_pfx) = pfx;
   8040         }
   8041         SOC_ALPM_LPM_STATE_NEXT(u, pfx) = SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx);
   8042         SOC_ALPM_LPM_STATE_PREV(u, pfx) = curr_pfx;
   8043         SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx) = pfx;
   8044 
   8045         SOC_ALPM_LPM_STATE_FENT(u, pfx) =  (SOC_ALPM_LPM_STATE_FENT(u, curr_pfx) + 1) / 2;
   8046         SOC_ALPM_LPM_STATE_FENT(u, curr_pfx) -= SOC_ALPM_LPM_STATE_FENT(u, pfx);
   8047         SOC_ALPM_LPM_STATE_START(u, pfx) =  SOC_ALPM_LPM_STATE_END(u, curr_pfx) +
   8048                                        SOC_ALPM_LPM_STATE_FENT(u, curr_pfx) + 1;
   8049         SOC_ALPM_LPM_STATE_END(u, pfx) = SOC_ALPM_LPM_STATE_START(u, pfx) - 1;
   8050         SOC_ALPM_LPM_STATE_VENT(u, pfx) = 0;
   8051     } else if (!ipv6) {
   8052         /* For IPv4 Check if alternate entry is free */
   8053         from_ent = SOC_ALPM_LPM_STATE_START(u, pfx);
   8054 #ifdef FB_LPM_TABLE_CACHED
   8055         if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm,
   8056                                            MEM_BLOCK_ANY, from_ent)) < 0) {
   8057             return rv;
   8058         }
   8059 #endif /* FB_LPM_TABLE_CACHED */
   8060         if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm,
   8061                                      MEM_BLOCK_ANY, from_ent, e)) < 0) {
   8062             return rv;
   8063         }
   8064         v0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f);
   8065         v1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f);
   8066 
   8067         if ((v0 == 0) || (v1 == 0)) {
   8068             *free_slot = (from_ent << 1) + ((v1 == 0) ? 1 : 0);
   8069             return(SOC_E_NONE);
   8070         }
   8071 
   8072         from_ent = SOC_ALPM_LPM_STATE_END(u, pfx);
   8073 #ifdef FB_LPM_TABLE_CACHED
   8074         if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm,
   8075                                            MEM_BLOCK_ANY, from_ent)) < 0) {
   8076             return rv;
   8077         }
   8078 #endif /* FB_LPM_TABLE_CACHED */
   8079         if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm,
   8080                                      MEM_BLOCK_ANY, from_ent, e)) < 0) {
   8081             return rv;
   8082         }
   8083         v0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f);
   8084         v1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f);
   8085 
   8086         if ((v0 == 0) || (v1 == 0)) {
   8087             *free_slot = (from_ent << 1) + ((v1 == 0) ? 1 : 0);
   8088             return(SOC_E_NONE);
   8089         }
   8090     }
   8091 
   8092     free_pfx = pfx;
   8093     while(SOC_ALPM_LPM_STATE_FENT(u, free_pfx) == 0) {
   8094         free_pfx = SOC_ALPM_LPM_STATE_NEXT(u, free_pfx);
   8095         if (free_pfx == -1) {
   8096             /* No free entries on this side try the other side */
   8097             free_pfx = pfx;
   8098             break;
   8099         }
   8100     }
   8101 
   8102     while(SOC_ALPM_LPM_STATE_FENT(u, free_pfx) == 0) {
   8103         free_pfx = SOC_ALPM_LPM_STATE_PREV(u, free_pfx);
   8104         if (free_pfx == -1) {
   8105             if (SOC_ALPM_LPM_STATE_VENT(u, pfx) == 0) {
   8106                 /* We failed to allocate entries for a newly allocated prefix.*/
   8107                 prev_pfx = SOC_ALPM_LPM_STATE_PREV(u, pfx);
   8108                 next_pfx = SOC_ALPM_LPM_STATE_NEXT(u, pfx);
   8109                 if (-1 != prev_pfx) {
   8110                     SOC_ALPM_LPM_STATE_NEXT(u, prev_pfx) = next_pfx;
   8111                 }
   8112                 if (-1 != next_pfx) {
   8113                     SOC_ALPM_LPM_STATE_PREV(u, next_pfx) = prev_pfx;
   8114                 }
   8115             }
   8116             return(SOC_E_FULL);
   8117         }
   8118     }
   8119 
   8120     /*
   8121      * Ripple entries to create free space
   8122      */
   8123     while (free_pfx > pfx) {
   8124         next_pfx = SOC_ALPM_LPM_STATE_NEXT(u, free_pfx); 
   8125         SOC_IF_ERROR_RETURN(_lpm_fb_shift_pfx_down(u, next_pfx, ipv6));
   8126         SOC_ALPM_LPM_STATE_FENT(u, free_pfx) -= 1;
   8127         SOC_ALPM_LPM_STATE_FENT(u, next_pfx) += 1;
   8128         free_pfx = next_pfx;
   8129     }
   8130 
   8131     while (free_pfx < pfx) {
   8132         SOC_IF_ERROR_RETURN(_lpm_fb_shift_pfx_up(u, free_pfx, ipv6));
   8133         SOC_ALPM_LPM_STATE_FENT(u, free_pfx) -= 1;
   8134         prev_pfx = SOC_ALPM_LPM_STATE_PREV(u, free_pfx); 
   8135         SOC_ALPM_LPM_STATE_FENT(u, prev_pfx) += 1;
   8136         free_pfx = prev_pfx;
   8137     }
   8138 
   8139     SOC_ALPM_LPM_STATE_VENT(u, pfx) += 1;
   8140     SOC_ALPM_LPM_STATE_FENT(u, pfx) -= 1;
   8141     SOC_ALPM_LPM_STATE_END(u, pfx) += 1;
   8142     *free_slot = SOC_ALPM_LPM_STATE_END(u, pfx) <<  ((ipv6) ? 0 : 1);
   8143     sal_memcpy(e, soc_mem_entry_null(u, L3_DEFIPm),
   8144                soc_mem_entry_words(u,L3_DEFIPm) * 4);
   8145 
   8146     return(SOC_E_NONE);
   8147 }
   8148 
   8149 /*
   8150  *      Delete a slot and adjust entry pointers if required.
   8151  *      e - has the contents of entry at slot(useful for IPV4 only)
   8152  */
   8153 static
   8154 int _lpm_free_slot_delete(int u, int pfx, int ipv6, void *e, int slot)
   8155 {
   8156     int         prev_pfx;
   8157     int         next_pfx;
   8158     int         from_ent;
   8159     int         to_ent;
   8160     uint32      ef[SOC_MAX_MEM_FIELD_WORDS];
   8161     uint32      sf[SOC_MAX_MEM_FIELD_WORDS];
   8162     uint32      st[SOC_MAX_MEM_FIELD_WORDS];
   8163     void        *et;
   8164     int         rv = SOC_E_NONE;
   8165     int         bpm_len;
   8166     int         src_half = 0, dst_half = 0;
   8167 
   8168     from_ent = SOC_ALPM_LPM_STATE_END(u, pfx);
   8169     to_ent = slot;
   8170     if (!ipv6) { /* IPV4 */
   8171         to_ent >>= 1;
   8172 #ifdef FB_LPM_TABLE_CACHED
   8173         if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm,
   8174                                            MEM_BLOCK_ANY, from_ent)) < 0) {
   8175             return rv;
   8176         }
   8177 #endif /* FB_LPM_TABLE_CACHED */
   8178         if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm,
   8179                                      MEM_BLOCK_ANY, from_ent, ef)) < 0) {
   8180             return rv;
   8181         }
   8182         /* get bpm_len of entry that is about to move */
   8183         if ((rv = READ_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ANY, 
   8184                 soc_alpm_physical_idx(u, L3_DEFIPm, from_ent, 1), sf)) < 0) {
   8185             return rv;
   8186         }
   8187         if ((rv = READ_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ANY, 
   8188                 soc_alpm_physical_idx(u, L3_DEFIPm, to_ent, 1), st)) < 0) {
   8189             return rv;
   8190         }
   8191         et =  (to_ent == from_ent) ? ef : e;
   8192         src_half = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef, VALID1f);
   8193         dst_half = (slot & 1);
   8194         if (src_half) {
   8195             bpm_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm, 
   8196                                                         sf, BPM_LENGTH1f);
   8197             if (dst_half) {
   8198                 rv = soc_alpm_lpm_ip4entry1_to_1(u, ef, et, PRESERVE_HIT);
   8199                 soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, st, BPM_LENGTH1f,
   8200                                     bpm_len);
   8201             } else {
   8202                 rv = soc_alpm_lpm_ip4entry1_to_0(u, ef, et, PRESERVE_HIT);
   8203                 soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, st, BPM_LENGTH0f,
   8204                                     bpm_len);
   8205             }
   8206             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, ef, VALID1f, 0);
   8207         } else {
   8208             bpm_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm, 
   8209                                                         sf, BPM_LENGTH0f);
   8210             if (dst_half) {
   8211                 rv = soc_alpm_lpm_ip4entry0_to_1(u, ef, et, PRESERVE_HIT);
   8212                 soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, st, BPM_LENGTH1f,
   8213                                     bpm_len);
   8214             } else {
   8215                 rv = soc_alpm_lpm_ip4entry0_to_0(u, ef, et, PRESERVE_HIT);
   8216                 soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, st, BPM_LENGTH0f,
   8217                                     bpm_len);
   8218             }
   8219             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, ef, VALID0f, 0);
   8220             SOC_ALPM_LPM_STATE_VENT(u, pfx) -= 1;
   8221             SOC_ALPM_LPM_STATE_FENT(u, pfx) += 1;
   8222             SOC_ALPM_LPM_STATE_END(u, pfx) -= 1;
   8223         }
   8224 
   8225         /* update bpm_len at target */
   8226         if ((rv = WRITE_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ALL, 
   8227                 soc_alpm_physical_idx(u, L3_DEFIPm, to_ent, 1), st)) < 0) {
   8228             return rv;
   8229         }
   8230 
   8231         if (to_ent == from_ent) {
   8232             SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, from_ent, ef,
   8233                                   WRITE_PIVOT_WITH_SRC_INDEX_CONVERT,
   8234                                   ((src_half << 1) | dst_half), 0));
   8235         } else {
   8236             SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, to_ent, et,
   8237                                   WRITE_PIVOT_WITH_SRC_INDEX_CONVERT, 
   8238                                   ((src_half << 1) | dst_half), 0));
   8239 
   8240             /* Use WRITE_PIVOT_WITH_URPF_PARAMS because it's faster */
   8241             SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, from_ent, ef,
   8242                                   WRITE_PIVOT_WITH_URPF_PARAMS, 0, 0));
   8243         }
   8244 
   8245         _soc_alpm_move_pivot(u, from_ent, to_ent, src_half, dst_half);
   8246 
   8247     } else { /* IPV6 */
   8248         SOC_ALPM_LPM_STATE_VENT(u, pfx) -= 1;
   8249         SOC_ALPM_LPM_STATE_FENT(u, pfx) += 1;
   8250         SOC_ALPM_LPM_STATE_END(u, pfx) -= 1;
   8251         if (to_ent != from_ent) {
   8252 #ifdef FB_LPM_TABLE_CACHED
   8253             if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm,
   8254                                                MEM_BLOCK_ANY, from_ent)) < 0) {
   8255                 return rv;
   8256             }
   8257 #endif /* FB_LPM_TABLE_CACHED */
   8258             if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm,
   8259                                          MEM_BLOCK_ANY, from_ent, ef)) < 0) {
   8260                 return rv;
   8261             }
   8262 
   8263             SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, to_ent, ef,
   8264                                   WRITE_PIVOT_WITH_SRC_INDEX, 0, 0));
   8265         }
   8266 
   8267         /* set from_ent invalid */
   8268         sal_memcpy(ef, soc_mem_entry_null(u, L3_DEFIPm),
   8269                    soc_mem_entry_words(u,L3_DEFIPm) * 4);
   8270 
   8271         SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, from_ent, ef,
   8272                              WRITE_PIVOT_WITH_URPF_PARAMS, 0, 0));
   8273 
   8274         _soc_alpm_move_pivot(u, from_ent, to_ent, 0, 0);
   8275         _soc_alpm_move_pivot(u, from_ent, to_ent, 1, 1);
   8276     }
   8277 
   8278     if (SOC_ALPM_LPM_STATE_VENT(u, pfx) == 0) {
   8279         /* remove from the list */
   8280         prev_pfx = SOC_ALPM_LPM_STATE_PREV(u, pfx); /* Always present */
   8281         assert(prev_pfx != -1);
   8282         next_pfx = SOC_ALPM_LPM_STATE_NEXT(u, pfx);
   8283         SOC_ALPM_LPM_STATE_NEXT(u, prev_pfx) = next_pfx;
   8284         SOC_ALPM_LPM_STATE_FENT(u, prev_pfx) += SOC_ALPM_LPM_STATE_FENT(u, pfx);
   8285         SOC_ALPM_LPM_STATE_FENT(u, pfx) = 0;
   8286         if (next_pfx != -1) {
   8287             SOC_ALPM_LPM_STATE_PREV(u, next_pfx) = prev_pfx;
   8288         }
   8289         SOC_ALPM_LPM_STATE_NEXT(u, pfx) = -1;
   8290         SOC_ALPM_LPM_STATE_PREV(u, pfx) = -1;
   8291         SOC_ALPM_LPM_STATE_START(u, pfx) = -1;
   8292         SOC_ALPM_LPM_STATE_END(u, pfx) = -1;
   8293     }
   8294 
   8295     return(rv);
   8296 }
   8297 
   8298 
   8299 /*
   8300  * Function:
   8301  *      soc_alpm_lpm_vrf_get
   8302  * Purpose:
   8303  *      Service routine used to translate hw specific vrf id to API format.
   8304  * Parameters:
   8305  *      unit      - (IN)SOC unit number.
   8306  *      lpm_entry - (IN)Route info buffer from hw.
   8307  *      vrf_id    - (OUT)Virtual router id.
   8308  * Returns:
   8309  *      BCM_E_XXX
   8310  */
   8311 int
   8312 soc_alpm_lpm_vrf_get(int unit, void *lpm_entry, int *vrf_id, int *vrf)
   8313 {
   8314     int mem_vrf;
   8315 
   8316     /* Get Virtual Router id if supported. */
   8317     if (SOC_MEM_OPT_FIELD_VALID(unit, L3_DEFIPm, VRF_ID_MASK0f)){
   8318         mem_vrf = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VRF_ID_0f);
   8319 
   8320         /* Special vrf's handling. */
   8321         if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f)) {
   8322             *vrf_id = mem_vrf;
   8323         } else if (!SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, 
   8324                                                     GLOBAL_HIGH0f)) {
   8325             *vrf_id = SOC_L3_VRF_GLOBAL;
   8326         } else {
   8327             *vrf_id = SOC_L3_VRF_OVERRIDE;
   8328         }
   8329         if (vrf) {
   8330             if (*vrf_id == SOC_L3_VRF_GLOBAL) {
   8331                 *vrf = SOC_VRF_MAX(unit) + 1;
   8332             } else {
   8333                 *vrf = mem_vrf;
   8334             }
   8335         }
   8336     } else {
   8337         /* No vrf support on this device. */
   8338         *vrf_id = SOC_L3_VRF_DEFAULT;
   8339     }
   8340     return (SOC_E_NONE);
   8341 }
   8342 
   8343 /*
   8344  * _soc_alpm_lpm_prefix_length_get (Extract vrf weighted  prefix lenght from the 
   8345  * hw entry based on ip, mask & vrf)
   8346  */
   8347 static int
   8348 _soc_alpm_lpm_prefix_length_get(int u, void *entry, int *pfx_len) 
   8349 {
   8350     int         pfx;
   8351     int         rv;
   8352     int         ipv6;
   8353     uint32      ipv4a;
   8354     int         vrf_id;
   8355     int         mode;
   8356 
   8357     ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, MODE0f);
   8358 
   8359     if (ipv6) {
   8360         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f);
   8361         if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
   8362             return(rv);
   8363         }
   8364         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK1f);
   8365         if (pfx) {
   8366             if (ipv4a != 0xffffffff)  {
   8367                 return(SOC_E_PARAM);
   8368             }
   8369             pfx += 32;
   8370         } else {
   8371             if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
   8372                 return(rv);
   8373             }
   8374         }
   8375         pfx += ALPM_IPV6_PFX_ZERO; /* First 33 are for IPV4 addresses */
   8376     } else {
   8377         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f);
   8378         if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
   8379             return(rv);
   8380         }
   8381     }
   8382 
   8383     SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, entry, &vrf_id, NULL));
   8384 
   8385     /* In ALPM the arragnement of VRF is at he begining followed by VRF
   8386      * override and global */
   8387     mode = soc_alpm_mode_get(u);
   8388     switch (vrf_id) {
   8389         case SOC_L3_VRF_GLOBAL:
   8390             if (mode == SOC_ALPM_MODE_PARALLEL) {
   8391                 *pfx_len = pfx + (ALPM_MAX_PFX_ENTRIES / 3);
   8392             } else {
   8393                 *pfx_len = pfx;
   8394             }
   8395             break;
   8396         case SOC_L3_VRF_OVERRIDE:
   8397             *pfx_len = pfx +  2 * (ALPM_MAX_PFX_ENTRIES / 3);
   8398             break;
   8399         default:
   8400             if (mode == SOC_ALPM_MODE_PARALLEL) {
   8401                 *pfx_len = pfx;
   8402             } else {
   8403                 *pfx_len = pfx +  (ALPM_MAX_PFX_ENTRIES / 3);
   8404             }
   8405             break;
   8406     }
   8407     return (SOC_E_NONE);
   8408 }
   8409 
   8410 
   8411 /*
   8412  * _soc_alpm_lpm_match (Exact match for the key. Will match both IP address
   8413  * and mask)
   8414  */
   8415 static int
   8416 _soc_alpm_lpm_match(int u,
   8417                void *key_data,
   8418                void *e,         /* return entry data if found */
   8419                int *index_ptr,  /* return key location */
   8420                int *pfx_len,    /* Key prefix length. vrf + 32 + prefix len for IPV6*/
   8421                int *ipv6)       /* Entry is ipv6. */
   8422 {
   8423     int         rv;
   8424     int         v6;
   8425     int         key_index;
   8426     int         pfx = 0;
   8427 
   8428     v6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, MODE0f);
   8429 
   8430     if (v6) {
   8431         if (!(v6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, MODE1f))) {
   8432             return (SOC_E_PARAM);
   8433         }
   8434     }
   8435     *ipv6 = v6;
   8436 
   8437     /* Calculate vrf weighted prefix lengh. */
   8438     _soc_alpm_lpm_prefix_length_get(u, key_data, &pfx); 
   8439     *pfx_len = pfx; 
   8440 
   8441 #ifdef FB_LPM_HASH_SUPPORT
   8442     if (LPM_HASH_LOOKUP(u, key_data, pfx, &key_index) == SOC_E_NONE) {
   8443         *index_ptr = key_index;
   8444         if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY,
   8445                      (*ipv6) ? *index_ptr : (*index_ptr >> 1), e)) < 0) {
   8446             return rv;
   8447         }
   8448 #ifndef  FB_LPM_CHECKER_ENABLE
   8449         return(SOC_E_NONE);
   8450 #endif
   8451     } else {
   8452 #ifndef  FB_LPM_CHECKER_ENABLE
   8453         return(SOC_E_NOT_FOUND);
   8454 #endif
   8455     }
   8456 #endif /* FB_LPM_HASH_SUPPORT */
   8457 }
   8458 
   8459 /*
   8460  * Initialize the start/end tracking pointers for each prefix length
   8461  */
   8462 static int
   8463 soc_alpm_lpm_init(int u)
   8464 {
   8465     int max_pfx_len;
   8466     int i;
   8467     int defip_table_size;
   8468     int pfx_state_size;
   8469     uint32 rval = 0;
   8470     uint32 mode;
   8471 
   8472     if (! soc_feature(u, soc_feature_lpm_tcam)) {
   8473         return(SOC_E_UNAVAIL);
   8474     }
   8475 
   8476     if ((mode = soc_property_get(u, spn_L3_ALPM_ENABLE, 0))) {
   8477         /* Set DEFIP mode to ALPM */
   8478         SOC_IF_ERROR_RETURN(READ_L3_DEFIP_RPF_CONTROLr(u, &rval));
   8479         soc_reg_field_set(u, L3_DEFIP_RPF_CONTROLr, &rval, LPM_MODEf, 1);
   8480         /* Parallel mode */
   8481         if (mode == SOC_ALPM_MODE_PARALLEL) {
   8482             soc_reg_field_set(u, L3_DEFIP_RPF_CONTROLr, &rval, LOOKUP_MODEf, 1);
   8483         } else {
   8484             /* combined search mode */
   8485             soc_reg_field_set(u, L3_DEFIP_RPF_CONTROLr, &rval, LOOKUP_MODEf, 0);
   8486         }
   8487         SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_RPF_CONTROLr(u, rval));
   8488         SOC_ALPM_SW_LOOKUP(u) = soc_property_get(u, "l3_alpm_sw_prefix_lookup", 1);
   8489 
   8490         rval = 0;
   8491         if (SOC_URPF_STATUS_GET(u)) {
   8492             soc_reg_field_set(u, L3_DEFIP_KEY_SELr, &rval, 
   8493                             URPF_LOOKUP_CAM4f, 0x1);
   8494             soc_reg_field_set(u, L3_DEFIP_KEY_SELr, &rval, 
   8495                             URPF_LOOKUP_CAM5f, 0x1);
   8496             soc_reg_field_set(u, L3_DEFIP_KEY_SELr, &rval, 
   8497                             URPF_LOOKUP_CAM6f, 0x1);
   8498             soc_reg_field_set(u, L3_DEFIP_KEY_SELr, &rval, 
   8499                             URPF_LOOKUP_CAM7f, 0x1);
   8500         }
   8501         SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_KEY_SELr(u, rval));
   8502         
   8503         rval = 0;
   8504         if (mode == SOC_ALPM_MODE_PARALLEL) {
   8505             if (SOC_URPF_STATUS_GET(u)) {
   8506                 /* 4 DIPs, 4 SIPs */
   8507                 /* *DIP */
   8508                 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM2_SELf, 1);
   8509                 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM3_SELf, 1);
   8510                 /* VRF SIP */
   8511                 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM4_SELf, 2);
   8512                 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM5_SELf, 2);
   8513                 /* *SIP */
   8514                 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM6_SELf, 3);
   8515                 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM7_SELf, 3);
   8516             } else {
   8517                 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM4_SELf, 1);
   8518                 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM5_SELf, 1);
   8519                 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM6_SELf, 1);
   8520                 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM7_SELf, 1);
   8521             }
   8522         } else {
   8523             if (SOC_URPF_STATUS_GET(u)) {
   8524                 /* 4 DIPs, 4 SIPs */
   8525                 /* DIP */
   8526                 /* VRF SIP */
   8527                 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM4_SELf, 2);
   8528                 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM5_SELf, 2);
   8529                 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM6_SELf, 2);
   8530                 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM7_SELf, 2);
   8531             } 
   8532         }
   8533         SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_ALPM_CFGr(u, rval));
   8534         if (SOC_ALPM_128B_ENABLE(u)) {
   8535             uint32 defip_key_sel_val = 0;
   8536 
   8537             SOC_IF_ERROR_RETURN(READ_L3_DEFIP_KEY_SELr(u, &defip_key_sel_val));
   8538             /* Supports mixed IPv4, IPv6 128 bit prefix IPv6 routes.
   8539             * upto 16K IPv4 pivots only or
   8540             * upto 2K 128 bit IPv6 and upto 8k v4 pivots, or */
   8541             /* all tcams in paired mode */
   8542             soc_reg_field_set(u, L3_DEFIP_KEY_SELr, &defip_key_sel_val,
   8543                                 V6_KEY_SEL_CAM0_1f, 0x1);
   8544             soc_reg_field_set(u, L3_DEFIP_KEY_SELr, &defip_key_sel_val,
   8545                                 V6_KEY_SEL_CAM2_3f, 0x1);
   8546             soc_reg_field_set(u, L3_DEFIP_KEY_SELr, &defip_key_sel_val,
   8547                                 V6_KEY_SEL_CAM4_5f, 0x1);
   8548             soc_reg_field_set(u, L3_DEFIP_KEY_SELr, &defip_key_sel_val,
   8549                                 V6_KEY_SEL_CAM6_7f, 0x1);
   8550             SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_KEY_SELr(u, defip_key_sel_val));
   8551         }
   8552     }
   8553 
   8554     max_pfx_len = ALPM_MAX_PFX_ENTRIES;
   8555 
   8556     SOC_ALPM_LPM_LOCK(u);
   8557     pfx_state_size = sizeof(soc_alpm_lpm_state_t) * (max_pfx_len);
   8558 
   8559     soc_lpm_field_cache_state[u] = 
   8560                 sal_alloc(sizeof(soc_lpm_field_cache_t), "lpm_field_state");
   8561     if (NULL == soc_lpm_field_cache_state[u]) {
   8562         SOC_ALPM_LPM_UNLOCK(u);
   8563         return (SOC_E_MEMORY);
   8564     }
   8565     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8566                                     CLASS_ID0f);
   8567     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8568                                     CLASS_ID1f);
   8569     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8570                                     DST_DISCARD0f);
   8571     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8572                                     DST_DISCARD1f);
   8573     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8574                                     ECMP0f);
   8575     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8576                                     ECMP1f);
   8577     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8578                                     ECMP_COUNT0f);
   8579     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8580                                     ECMP_COUNT1f);
   8581     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8582                                     ECMP_PTR0f);
   8583     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8584                                     ECMP_PTR1f);
   8585     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8586                                     GLOBAL_ROUTE0f);
   8587     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8588                                     GLOBAL_ROUTE1f);
   8589     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8590                                     MULTICAST_ROUTE0f);
   8591     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8592                                     MULTICAST_ROUTE1f);
   8593     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8594                                     RPA_ID0f);
   8595     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8596                                     RPA_ID1f);
   8597     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8598                                     EXPECTED_L3_IIF0f);
   8599     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8600                                     EXPECTED_L3_IIF1f);
   8601     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8602                                     IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f);
   8603     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8604                                     IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f);
   8605     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8606                                     IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f);
   8607     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8608                                     IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f);
   8609     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8610                                     L3MC_INDEX0f);
   8611     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8612                                     L3MC_INDEX1f);
   8613     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8614                                     HIT0f);
   8615     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8616                                     HIT1f);
   8617     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8618                                     IP_ADDR0f);
   8619     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8620                                     IP_ADDR1f);
   8621     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8622                                     IP_ADDR_MASK0f);
   8623     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8624                                     IP_ADDR_MASK1f);
   8625     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8626                                     MODE0f);
   8627     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8628                                     MODE1f);
   8629     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8630                                     MODE_MASK0f);
   8631     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8632                                     MODE_MASK1f);
   8633     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8634                                     NEXT_HOP_INDEX0f);
   8635     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8636                                     NEXT_HOP_INDEX1f);
   8637     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8638                                     PRI0f);
   8639     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8640                                     PRI1f);
   8641     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8642                                     RPE0f);
   8643     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8644                                     RPE1f);
   8645     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8646                                     VALID0f);
   8647     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8648                                     VALID1f);
   8649     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8650                                     VRF_ID_0f);
   8651     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8652                                     VRF_ID_1f);
   8653     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8654                                     VRF_ID_MASK0f);
   8655     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8656                                     VRF_ID_MASK1f);
   8657     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8658                                     GLOBAL_HIGH0f);
   8659     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8660                                     GLOBAL_HIGH1f);
   8661     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8662                                     ALG_HIT_IDX0f);
   8663     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8664                                     ALG_HIT_IDX1f);
   8665     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8666                                     ALG_BKT_PTR0f);
   8667     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8668                                     ALG_BKT_PTR1f);
   8669     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8670                                     DEFAULT_MISS0f);
   8671     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 
   8672                                     DEFAULT_MISS1f);
   8673     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8674                                     FLEX_CTR_BASE_COUNTER_IDX0f);
   8675     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8676                                     FLEX_CTR_BASE_COUNTER_IDX1f);
   8677     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8678                                     FLEX_CTR_POOL_NUMBER0f);
   8679     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8680                                     FLEX_CTR_POOL_NUMBER1f);
   8681     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8682                                     FLEX_CTR_OFFSET_MODE0f);
   8683     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8684                                     FLEX_CTR_OFFSET_MODE1f);
   8685     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8686                                     SRC_DISCARD0f);
   8687     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8688                                     SRC_DISCARD1f);
   8689     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8690                                     ENTRY_TYPE_MASK0f);
   8691     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8692                                     ENTRY_TYPE_MASK1f);
   8693     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8694                                     ENTRY_TYPE0f);
   8695     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8696                                     ENTRY_TYPE1f);
   8697     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8698                                     ENTRY_VIEW0f);
   8699     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   8700                                     ENTRY_VIEW1f);
   8701 
   8702     SOC_ALPM_LPM_STATE(u) = sal_alloc(pfx_state_size, "LPM prefix info");
   8703     if (NULL == SOC_ALPM_LPM_STATE(u)) {
   8704         sal_free(soc_lpm_field_cache_state[u]);
   8705         soc_lpm_field_cache_state[u] = NULL;
   8706         SOC_ALPM_LPM_UNLOCK(u);
   8707         return (SOC_E_MEMORY);
   8708     }
   8709 
   8710 #ifdef FB_LPM_TABLE_CACHED
   8711     rv = soc_mem_cache_set(u, L3_DEFIPm, MEM_BLOCK_ALL, TRUE);
   8712     if (SOC_FAILURE(rv)) {
   8713         SOC_ALPM_LPM_UNLOCK(u);
   8714         return rv;
   8715     }
   8716 #endif /* FB_LPM_TABLE_CACHED */
   8717 
   8718     sal_memset(SOC_ALPM_LPM_STATE(u), 0, pfx_state_size);
   8719     for(i = 0; i < max_pfx_len; i++) {
   8720         SOC_ALPM_LPM_STATE_START(u, i) = -1;
   8721         SOC_ALPM_LPM_STATE_END(u, i) = -1;
   8722         SOC_ALPM_LPM_STATE_PREV(u, i) = -1;
   8723         SOC_ALPM_LPM_STATE_NEXT(u, i) = -1;
   8724         SOC_ALPM_LPM_STATE_VENT(u, i) = 0;
   8725         SOC_ALPM_LPM_STATE_FENT(u, i) = 0;
   8726     }
   8727 
   8728     defip_table_size = soc_mem_index_count(u, L3_DEFIPm);
   8729 
   8730     /* RPF supported, then the table is partitioned for DIP and SIP */
   8731     if (SOC_URPF_STATUS_GET(u)) {
   8732         defip_table_size >>= 1;
   8733     }
   8734 
   8735     if (mode == SOC_ALPM_MODE_PARALLEL) {
   8736         /* For Parallel search, the TCAM is hard paritioned.
   8737         * First half are for VRF specific, the bottom half for override and 
   8738         * global. Start of Global entries start at the bottom half of TCAM
   8739         */
   8740         SOC_ALPM_LPM_STATE_END(u, ALPM_MAX_PFX_INDEX) = (defip_table_size>>1) - 1;
   8741 
   8742         /* Free entries for VRF */
   8743         SOC_ALPM_LPM_STATE_FENT(u, (ALPM_MAX_VRF_PFX_INDEX)) = defip_table_size >> 1;
   8744 
   8745         /* Remaining entries are assigned to Global entries */
   8746         SOC_ALPM_LPM_STATE_FENT(u, (ALPM_MAX_PFX_INDEX)) = 
   8747           (defip_table_size - SOC_ALPM_LPM_STATE_FENT(u, (ALPM_MAX_VRF_PFX_INDEX)));
   8748     } else {
   8749         /* Remaining entries are assigned to Global entries */
   8750         SOC_ALPM_LPM_STATE_FENT(u, (ALPM_MAX_PFX_INDEX)) = defip_table_size;
   8751     }
   8752 
   8753 #ifdef FB_LPM_HASH_SUPPORT
   8754     if (SOC_ALPM_LPM_STATE_HASH(u) != NULL) {
   8755         if (_soc_alpm_lpm_hash_destroy(SOC_ALPM_LPM_STATE_HASH(u)) < 0) {
   8756             SOC_ALPM_LPM_UNLOCK(u);
   8757             return SOC_E_INTERNAL;
   8758         }
   8759         SOC_ALPM_LPM_STATE_HASH(u) = NULL;
   8760     }
   8761 
   8762     if (_soc_alpm_lpm_hash_create(u, defip_table_size * 2, defip_table_size,
   8763                                 &SOC_ALPM_LPM_STATE_HASH(u)) < 0) {
   8764         SOC_ALPM_LPM_UNLOCK(u);
   8765         return SOC_E_MEMORY;
   8766     }
   8767 #endif
   8768 
   8769 
   8770     SOC_ALPM_LPM_UNLOCK(u);
   8771     return(SOC_E_NONE);
   8772 }
   8773 
   8774 /*
   8775  * De-initialize the start/end tracking pointers for each prefix length
   8776  */
   8777 static int
   8778 soc_alpm_lpm_deinit(int u)
   8779 {
   8780     if (!soc_feature(u, soc_feature_lpm_tcam)) {
   8781         return(SOC_E_UNAVAIL);
   8782     }
   8783 
   8784     SOC_ALPM_LPM_LOCK(u);
   8785 
   8786 #ifdef FB_LPM_HASH_SUPPORT
   8787     if (SOC_ALPM_LPM_STATE_HASH(u) != NULL) {
   8788         _soc_alpm_lpm_hash_destroy(SOC_ALPM_LPM_STATE_HASH(u));
   8789         SOC_ALPM_LPM_STATE_HASH(u) = NULL;
   8790     }
   8791 #endif
   8792 
   8793     if (SOC_ALPM_LPM_INIT_CHECK(u)) {
   8794         sal_free(soc_lpm_field_cache_state[u]);
   8795         soc_lpm_field_cache_state[u] = NULL;
   8796         sal_free(SOC_ALPM_LPM_STATE(u));
   8797         SOC_ALPM_LPM_STATE(u) = NULL;
   8798     }
   8799 
   8800     SOC_ALPM_LPM_UNLOCK(u);
   8801 
   8802     return(SOC_E_NONE);
   8803 }
   8804 
   8805 /*
   8806  * Implementation using soc_mem_read/write using entry rippling technique
   8807  * Advantage: A completely sorted table is not required. Lookups can be slow
   8808  * as it will perform a linear search on the entries for a given prefix length.
   8809  * No device access necessary for the search if the table is cached. Auxiliary
   8810  * hash table can be maintained to speed up search(Not implemented) instead of
   8811  * performing a linear search.
   8812  * Small number of entries need to be moved around (97 worst case)
   8813  * for performing insert/update/delete. However CPU needs to do all
   8814  * the work to move the entries.
   8815  */
   8816 
   8817 /*
   8818  * soc_alpm_lpm_insert
   8819  * For IPV4 assume only both IP_ADDR0 is valid
   8820  * Moving multiple entries around in h/w vs  doing a linear search in s/w
   8821  * src_default: for sip entry if any
   8822  *              0 - caculate using entry_data's mask (legacy way)
   8823  *              1 - force set (split case)
   8824  * src_discard: for sip entry if any
   8825  */
   8826 static int
   8827 soc_alpm_lpm_insert(int u, void *entry_data, int *lpm_index,
   8828                     int src_default, int src_discard, int bpm_len)
   8829 {
   8830     int         pfx;
   8831     int         index;
   8832     int         ipv6, v4_half = 0;
   8833     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   8834     int         rv = SOC_E_NONE;
   8835     int         found = 0;
   8836     int         vrf, vrf_id;
   8837 
   8838     sal_memcpy(e, soc_mem_entry_null(u, L3_DEFIPm),
   8839                soc_mem_entry_words(u, L3_DEFIPm) * 4);
   8840 
   8841     SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, entry_data, &vrf_id, &vrf));
   8842 
   8843     SOC_ALPM_LPM_LOCK(u);
   8844     rv = _soc_alpm_lpm_match(u, entry_data, e, &index, &pfx, &ipv6);
   8845     if (rv == SOC_E_NOT_FOUND) {
   8846         rv = _lpm_free_slot_create(u, pfx, ipv6, e, &index);
   8847         if (rv < 0) {
   8848             SOC_ALPM_LPM_UNLOCK(u);
   8849             return(rv);
   8850         }
   8851     } else {
   8852         found = 1;
   8853     }
   8854 
   8855     *lpm_index = index;
   8856 
   8857     if (rv == SOC_E_NONE) {
   8858         if (!ipv6) {
   8859             /* IPV4 entry */
   8860             if (index & 1) {
   8861                 rv = soc_alpm_lpm_ip4entry0_to_1(u, entry_data, e, 
   8862                                                  PRESERVE_HIT);
   8863                 v4_half = 3;
   8864             } else {
   8865                 rv = soc_alpm_lpm_ip4entry0_to_0(u, entry_data, e, 
   8866                                                  PRESERVE_HIT);
   8867                 v4_half = 2;
   8868             }
   8869 
   8870             if (rv < 0) {
   8871                 SOC_ALPM_LPM_UNLOCK(u);
   8872                 return(rv);
   8873             }
   8874             entry_data = (void *)e;
   8875             index >>= 1;
   8876         }
   8877         soc_alpm_lpm_state_dump(u);
   8878         LOG_INFO(BSL_LS_SOC_ALPM,
   8879                  (BSL_META_U(u,
   8880                              "\nsoc_alpm_lpm_insert: %d %d\n"),
   8881                              index, pfx));
   8882         rv = _soc_alpm_write_pivot_with_bpm(u, index, index, entry_data,
   8883                              WRITE_PIVOT_WITH_URPF_PARAMS | 
   8884                              (found ? WRITE_PIVOT_WITHOUT_INSERT_HASH : 0),
   8885                              src_default, src_discard, bpm_len, v4_half);
   8886         if (!found && SOC_SUCCESS(rv)) {
   8887             VRF_PIVOT_REF_INC(u, vrf_id, vrf, ipv6);
   8888         }
   8889     }
   8890 
   8891     SOC_ALPM_LPM_UNLOCK(u);
   8892 
   8893     return(rv);
   8894 }
   8895 
   8896 /*
   8897  * soc_alpm_lpm_delete
   8898  */
   8899 static int
   8900 soc_alpm_lpm_delete(int u, void *key_data)
   8901 {
   8902     int         pfx;
   8903     int         index;
   8904     int         ipv6;
   8905     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   8906     int         rv = SOC_E_NONE;
   8907     int         vrf, vrf_id;
   8908 
   8909     SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf));    
   8910     SOC_ALPM_LPM_LOCK(u);
   8911     rv = _soc_alpm_lpm_match(u, key_data, e, &index, &pfx, &ipv6);
   8912     if (rv == SOC_E_NONE) {
   8913         LOG_INFO(BSL_LS_SOC_ALPM,
   8914                  (BSL_META_U(u,
   8915                              "\nsoc_alpm_lpm_delete: %d %d\n"),
   8916                              index, pfx));
   8917         LPM_HASH_DELETE(u, key_data, index);
   8918         rv = _lpm_free_slot_delete(u, pfx, ipv6, e, index);
   8919     }
   8920     if (SOC_SUCCESS(rv)) {
   8921         VRF_PIVOT_REF_DEC(u, vrf_id, vrf, ipv6);
   8922     }
   8923     soc_alpm_lpm_state_dump(u);
   8924     SOC_ALPM_LPM_UNLOCK(u);
   8925     return(rv);
   8926 }
   8927 
   8928 /*
   8929  * soc_alpm_lpm_match (Exact match for the key. Will match both IP
   8930  *                   address and mask)
   8931  */
   8932 static int
   8933 soc_alpm_lpm_match(int u,
   8934                void *key_data,
   8935                void *e,         /* return entry data if found */
   8936                int *index_ptr)  /* return key location */
   8937 {
   8938     int        pfx;
   8939     int        rv;
   8940     int        ipv6;
   8941 
   8942     SOC_ALPM_LPM_LOCK(u);
   8943     rv = _soc_alpm_lpm_match(u, key_data, e, index_ptr, &pfx, &ipv6);
   8944     SOC_ALPM_LPM_UNLOCK(u);
   8945     return(rv);
   8946 }
   8947 
   8948 
   8949 /* Fill Aux entry for operation */
   8950 static int
   8951 _soc_alpm_fill_aux_entry_for_op(int unit,
   8952                void *key_data,
   8953                int ipv6,            /* Entry is ipv6. */
   8954                int db_type,         /* database type */
   8955                int ent_type,
   8956                int replace_len,     /* used for Delete propagate */
   8957                defip_aux_scratch_entry_t *aux_entry)
   8958 {
   8959     uint32 ipv4a;
   8960     uint32 ip6_word[4] = {0, 0, 0, 0};
   8961     int    pfx = 0;
   8962     int    rv = SOC_E_NONE;
   8963 
   8964     sal_memset(aux_entry, 0, sizeof(defip_aux_scratch_entry_t));
   8965 
   8966     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, VALID0f);
   8967     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, VALIDf, ipv4a);
   8968 
   8969     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, MODE0f);
   8970     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, MODEf, ipv4a);
   8971 
   8972     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, ENTRY_TYPE0f);
   8973     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, ENTRY_TYPEf, ent_type);
   8974 
   8975     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, GLOBAL_ROUTE0f);
   8976     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, GLOBAL_ROUTEf, ipv4a);
   8977 
   8978     if (soc_feature(unit, soc_feature_ipmc_defip)) {
   8979         ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, RPA_ID0f);
   8980         soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, RPA_IDf, ipv4a);
   8981 
   8982         ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, EXPECTED_L3_IIF0f);
   8983         soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, EXPECTED_L3_IIFf, ipv4a);
   8984 
   8985         ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f);
   8986         soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf, ipv4a);
   8987 
   8988         ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f);
   8989         soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf, ipv4a);
   8990 
   8991         ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, L3MC_INDEX0f);
   8992         soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, L3MC_INDEXf, ipv4a);
   8993     }
   8994 
   8995     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, ECMP0f);
   8996     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, ECMPf, ipv4a);
   8997 
   8998     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, ECMP_PTR0f);
   8999     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, ECMP_PTRf, ipv4a);
   9000 
   9001     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, NEXT_HOP_INDEX0f);
   9002     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, NEXT_HOP_INDEXf, ipv4a);
   9003 
   9004     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, PRI0f);
   9005     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, PRIf, ipv4a);
   9006 
   9007     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, RPE0f);
   9008     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, RPEf, ipv4a);
   9009 
   9010     ipv4a =soc_mem_field32_get(unit, L3_DEFIPm, key_data, VRF_ID_0f);
   9011     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, VRFf, ipv4a);
   9012 
   9013     /* Set Database type */
   9014     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, DB_TYPEf, db_type);
   9015 
   9016     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, DST_DISCARD0f);
   9017     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, DST_DISCARDf, ipv4a);
   9018 
   9019     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, DEFAULT_MISS0f);
   9020     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, DEFAULT_MISSf, ipv4a);
   9021 
   9022     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, CLASS_ID0f);
   9023     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, CLASS_IDf, ipv4a);
   9024 
   9025 
   9026     /* Set IP Address and IP length */
   9027     if (ipv6) {
   9028         ip6_word[2] = soc_mem_field32_get(unit, L3_DEFIPm, key_data, IP_ADDR0f);
   9029         ip6_word[3] = soc_mem_field32_get(unit, L3_DEFIPm, key_data, IP_ADDR1f);
   9030     } else {
   9031         ip6_word[0] = soc_mem_field32_get(unit, L3_DEFIPm, key_data, IP_ADDR0f);
   9032     }
   9033     soc_mem_field_set(unit, L3_DEFIP_AUX_SCRATCHm, (uint32*)aux_entry,
   9034                       IP_ADDRf, (uint32*)ip6_word);
   9035 
   9036     if (ipv6) {
   9037         ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, IP_ADDR_MASK0f);
   9038         if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
   9039             return(rv);
   9040         }
   9041         ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, IP_ADDR_MASK1f);
   9042         if (pfx) {
   9043             if (ipv4a != 0xffffffff)  {
   9044                 return(SOC_E_PARAM);
   9045             }
   9046             pfx += 32;
   9047         } else {
   9048             if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
   9049                 return(rv);
   9050             }
   9051         }
   9052     } else {
   9053         ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, IP_ADDR_MASK0f);
   9054         if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
   9055             return(rv);
   9056         }
   9057     }
   9058     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, IP_LENGTHf, pfx);
   9059     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, REPLACE_LENf,
   9060                         replace_len);
   9061 
   9062     ipv4a = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, key_data, FLEX_CTR_BASE_COUNTER_IDX0f);
   9063     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, FLEX_CTR_BASE_COUNTER_IDXf, ipv4a);
   9064 
   9065     ipv4a = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, key_data, FLEX_CTR_OFFSET_MODE0f);
   9066     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, FLEX_CTR_OFFSET_MODEf, ipv4a);
   9067 
   9068     ipv4a = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, key_data, FLEX_CTR_POOL_NUMBER0f);
   9069     soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, FLEX_CTR_POOL_NUMBERf, ipv4a);
   9070 
   9071     return (SOC_E_NONE);
   9072 }
   9073 
   9074 #define _SOC_ALPM_AUX_OP_RETRY_TO           1000000
   9075 #define _SOC_ALPM_AUX_OP_RETRY_COUNT        100
   9076 #define _TD2_PIPES_PER_DEV                  2
   9077 
   9078 /* Using binary search with DMA read to retrieve corrupted index */
   9079 int
   9080 _soc_alpm_aux_error_index(int u, int pipe, int *index, soc_mem_t *mem)
   9081 {
   9082     char *dmabuf = NULL;
   9083     soc_mem_t mem_to_search[2] = {L3_DEFIP_AUX_TABLEm, L3_DEFIP_DATA_ONLYm};
   9084     int min, max;
   9085     uint32 ser_flags;
   9086     int i = 0;
   9087     int found_index = FALSE;
   9088     int mem_wsz = 0;
   9089 
   9090     switch (pipe) {
   9091         case 0:
   9092             ser_flags = _SOC_MEM_ADDR_ACC_TYPE_PIPE_X;
   9093             break;
   9094         case 1:
   9095             ser_flags = _SOC_MEM_ADDR_ACC_TYPE_PIPE_Y;
   9096             break;
   9097         default:
   9098             ser_flags = _SOC_MEM_ADDR_ACC_TYPE_PIPE_X;
   9099             break;
   9100     }
   9101 
   9102     ser_flags |= _SOC_SER_FLAG_DMA_ERR_RETURN;
   9103     ser_flags |= _SOC_SER_FLAG_DISCARD_READ;
   9104     ser_flags |= _SOC_SER_FLAG_MULTI_PIPE;
   9105 
   9106     for (i = 0; i < 2; i++) {
   9107         min = soc_mem_index_min(u, mem_to_search[i]);
   9108         if (mem_to_search[i] == L3_DEFIP_DATA_ONLYm) {
   9109             max = soc_mem_index_max(u, L3_DEFIP_DATA_ONLYm) +
   9110                   soc_mem_index_max(u,L3_DEFIP_PAIR_128_DATA_ONLYm) * 2;
   9111         } else {
   9112             max = soc_mem_index_max(u, mem_to_search[i]);
   9113         }
   9114 
   9115         mem_wsz = sizeof(uint32) * soc_mem_entry_words(u, mem_to_search[i]);
   9116         dmabuf = soc_cm_salloc(u, max * mem_wsz, "auxtbl_dmabuf");
   9117         if (dmabuf == NULL) {
   9118             return SOC_E_MEMORY;
   9119         }
   9120 
   9121         while (min <= max) {
   9122             int mid = min + (max - min) / 2;
   9123             if (soc_mem_ser_read_range(u, mem_to_search[i], MEM_BLOCK_ALL, min, mid, ser_flags,
   9124                                        dmabuf) < 0) {
   9125                 if (max == min) {
   9126                     *index = min;
   9127                     found_index = TRUE;
   9128                     break;
   9129                 }
   9130                 max = mid;
   9131             } else {
   9132                 min = mid + 1;
   9133             }
   9134         }
   9135 
   9136         soc_cm_sfree(u, dmabuf);
   9137 
   9138         if (found_index) {
   9139             *mem = mem_to_search[i];
   9140             break;
   9141         }
   9142     }
   9143 
   9144     if (min > max) {
   9145         /* Not found */
   9146         LOG_WARN(BSL_LS_SOC_ALPM,
   9147             (BSL_META_U(u, "No corrupted index in L3_DEFIP_AUX_TABLE or"
   9148                            "L3_DEFIP_DATA_ONLY Pipe %d\n"), pipe));
   9149         return SOC_E_NOT_FOUND;
   9150     } else {
   9151         LOG_WARN(BSL_LS_SOC_ALPM,
   9152             (BSL_META_U(u, "Found corrupted Index %d in %s Table Pipe %d\n"),
   9153             *index, SOC_MEM_NAME(u, *mem), pipe));
   9154         return SOC_E_NONE;
   9155     }
   9156 }
   9157 
   9158 /* Perform an ALPM hardware operation */
   9159 int
   9160 _soc_alpm_aux_hw_op(int u, _soc_aux_op_t aux_op,
   9161                     defip_aux_scratch_entry_t *aux_entry, int update_scratch,
   9162                     int *hit, int *tcam_index, int *bucket_index)
   9163 {
   9164     soc_timeout_t  to;
   9165     int pipe, rv = SOC_E_NONE;
   9166     int _soc_alpm_aux_op_retry = 0;
   9167 
   9168     uint32 rval[_TD2_PIPES_PER_DEV];
   9169     int value[_TD2_PIPES_PER_DEV];
   9170     int err[_TD2_PIPES_PER_DEV];
   9171 
   9172     uint32 baddr;
   9173     int block;
   9174     uint8 acc_type;
   9175     soc_mem_t mem = INVALIDm;
   9176 
   9177     /* Write to Aux Scratch before performing the operation */
   9178     if (update_scratch) {
   9179         SOC_IF_ERROR_RETURN(
   9180             WRITE_L3_DEFIP_AUX_SCRATCHm(u, MEM_BLOCK_ANY, 0, aux_entry));
   9181     }
   9182 
   9183 #ifdef AUX_OPTIMIZATIONS_OFF
   9184     SOC_IF_ERROR_RETURN(READ_L3_DEFIP_AUX_CTRLr(u, &rval[0]));
   9185     if (soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr, rval[0], STARTf)) {
   9186         /* Aux op in porgress */
   9187         return SOC_E_BUSY;
   9188     }
   9189 #endif /* OPTIMIZATIONS_OFF */
   9190 
   9191 _retry:
   9192     switch (aux_op) {
   9193     case INSERT_PROPAGATE:
   9194         value[0] = 0;
   9195         break;
   9196     case DELETE_PROPAGATE:
   9197         value[0] = 1;
   9198         break;
   9199     case PREFIX_LOOKUP:
   9200         value[0] = 2;
   9201         break;
   9202     case HITBIT_REPLACE:
   9203         value[0] = 3;
   9204         break;
   9205     default:
   9206         return SOC_E_PARAM;
   9207     }
   9208 
   9209     rval[0] = 0;
   9210 
   9211     /* set opcode */
   9212     soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[0], OPCODEf, value[0]);
   9213 
   9214     /* Start opertation */
   9215     soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[0], STARTf, 1);
   9216 
   9217     /* Write to Aux ctrl reg */
   9218     SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_AUX_CTRLr(u, rval[0]));
   9219     soc_timeout_init(&to, 50000, 5);
   9220 
   9221     /* Check for Operation complete */
   9222     sal_memset(value, 0, sizeof(value));
   9223     sal_memset(err, 0, sizeof(err));
   9224     baddr = soc_reg_addr_get(u, L3_DEFIP_AUX_CTRLr, REG_PORT_ANY, 0,
   9225                              SOC_REG_ADDR_OPTION_NONE,
   9226                              &block, &acc_type);
   9227     do {
   9228         for (pipe = 0; pipe < _TD2_PIPES_PER_DEV; pipe++) {
   9229             SOC_IF_ERROR_RETURN
   9230                 (_soc_reg32_get(u, block, pipe + 1, baddr, &rval[pipe]));
   9231             value[pipe] = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr,
   9232                                             rval[pipe], DONEf);
   9233             err[pipe] = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr,
   9234                                           rval[pipe], ERRORf);
   9235             if (value[pipe] != 1) {
   9236                 break;
   9237             }
   9238         }
   9239 
   9240         /* All DONE */
   9241         if (pipe >= _TD2_PIPES_PER_DEV) {
   9242             rv = SOC_E_NONE;
   9243             break;
   9244         }
   9245 
   9246         if (soc_timeout_check(&to)) {
   9247             sal_memset(value, 0, sizeof(value));
   9248             sal_memset(err, 0, sizeof(err));
   9249             for (pipe = 0; pipe < _TD2_PIPES_PER_DEV; pipe++) {
   9250                 SOC_IF_ERROR_RETURN
   9251                     (_soc_reg32_get(u, block, pipe + 1, baddr, &rval[pipe]));
   9252                 value[pipe] = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr,
   9253                                                 rval[pipe], DONEf);
   9254                 err[pipe] = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr,
   9255                                               rval[pipe], ERRORf);
   9256                 if (value[pipe] != 1) {
   9257                     break;
   9258                 }
   9259             }
   9260 
   9261             if (pipe >= _TD2_PIPES_PER_DEV) {
   9262                 rv = SOC_E_NONE;
   9263             } else {
   9264                 LOG_WARN(BSL_LS_SOC_ALPM,
   9265                          (BSL_META_U(u, "unit %d : DEFIP AUX Operation "
   9266                          "timeout, Pipe %d\n"), u, pipe));
   9267                 rv = SOC_E_TIMEOUT;
   9268             }
   9269             break;
   9270         }
   9271     } while (1);
   9272 
   9273     if (SOC_SUCCESS(rv)) {
   9274         for (pipe = 0; pipe < _TD2_PIPES_PER_DEV; pipe++) {
   9275             if (err[pipe]) {
   9276                 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[pipe], STARTf, 0);
   9277                 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[pipe], ERRORf, 0);
   9278                 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[pipe], DONEf, 0);
   9279 
   9280                 SOC_IF_ERROR_RETURN
   9281                     (_soc_reg32_set(u, block, pipe + 1, baddr, rval[pipe]));
   9282                 LOG_WARN(BSL_LS_SOC_ALPM,
   9283                          (BSL_META_U(u, "DEFIP AUX Operation encountered "
   9284                                      "parity error in Pipe %d!!\n"), pipe));
   9285                 _soc_alpm_aux_op_retry++;
   9286                 if (SOC_CONTROL(u)->alpm_bulk_retry) {
   9287                     sal_sem_take(SOC_CONTROL(u)->alpm_bulk_retry, _SOC_ALPM_AUX_OP_RETRY_TO);
   9288                 }
   9289                 if (_soc_alpm_aux_op_retry < _SOC_ALPM_AUX_OP_RETRY_COUNT) {
   9290                     int err_index;
   9291                     if (_soc_alpm_aux_error_index(u, pipe, &err_index, &mem) >= 0) {
   9292                         /* Call inline correction with err_index and pipe */
   9293                         rv = soc_mem_alpm_aux_table_correction(u, pipe, err_index, mem);
   9294                         if (rv < 0) {
   9295                             LOG_ERROR(BSL_LS_SOC_ALPM,
   9296                                 (BSL_META_U(u, "_soc_th_alpm_aux_error_index "
   9297                                 "pipe %d index %d failed\n"), pipe, err_index));
   9298                         }
   9299                     }
   9300                     LOG_WARN(BSL_LS_SOC_ALPM,
   9301                         (BSL_META_U(u, "Retry DEFIP AUX Operation in "
   9302                         "Pipe %d.\n"), pipe));
   9303                     goto _retry;
   9304                 } else {
   9305                     LOG_ERROR(BSL_LS_SOC_ALPM,
   9306                         (BSL_META_U(u, "unit %d: Aborting DEFIP AUX Operation "
   9307                         "due to un-correctable error !!\n"), u));
   9308                     return SOC_E_INTERNAL;
   9309                 }
   9310             }
   9311         }
   9312 
   9313         if (aux_op == PREFIX_LOOKUP) {
   9314             if (hit && tcam_index) {
   9315                 /* Get the hit bit and Bucket index for lookup operations */
   9316                 *hit = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr, rval[0], HITf);
   9317                 *tcam_index = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr,
   9318                                                 rval[0], BKT_INDEXf);
   9319                 SOC_IF_ERROR_RETURN(READ_L3_DEFIP_AUX_CTRL_1r(u, &rval[1]));
   9320                 *bucket_index = soc_reg_field_get(u, L3_DEFIP_AUX_CTRL_1r,
   9321                                                   rval[1], BKT_PTRf);
   9322             }
   9323         }
   9324     }
   9325 #ifdef AUX_OPTIMIZATIONS_OFF
   9326     /* clear AUX ctrl register */
   9327     soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[0], STARTf, 0);
   9328     soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[0], DONEf, 0);
   9329     SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_AUX_CTRLr(u, rval[0]));
   9330 #endif /* OPTIMIZATIONS_OFF */
   9331     return rv;
   9332 }
   9333 
   9334 int
   9335 _soc_alpm_aux_op(int u, _soc_aux_op_t aux_op,
   9336                  defip_aux_scratch_entry_t *aux_entry, int update_scratch,
   9337                  int *hit, int *tcam_index, int *log_bkt, int aux_flags)
   9338 {
   9339     int rv = SOC_E_NONE;
   9340     int cb_cnt = 1;
   9341 
   9342     /*
   9343      * SW propagation:
   9344      * Callback only being proceeded when cache of LPM TCAM tables is
   9345      * turn on.
   9346      */
   9347     if (ALPM_CTRL(u).trie_propagate) {
   9348         rv = _soc_alpm_aux_sw_op(u, aux_op, aux_entry,
   9349                                  &cb_cnt, aux_flags);
   9350     }
   9351 
   9352     /* Hareware assists only needed when matched pivot is hit. */
   9353     if (SOC_SUCCESS(rv) && cb_cnt > 0) {
   9354         uint32 val;
   9355 
   9356         if (SOC_IS_TRIDENT2(u) && (aux_op == INSERT_PROPAGATE)) {
   9357             /*
   9358              * Do DELETE propagation to update existing default datas
   9359              * Since INSERT Propagate doesn't handle '==' case
   9360              */
   9361             rv = _soc_alpm_aux_hw_op(u, DELETE_PROPAGATE, aux_entry,
   9362                                      update_scratch, hit, tcam_index, log_bkt);
   9363             if (SOC_SUCCESS(rv)) {
   9364                 rv = _soc_alpm_aux_hw_op(u, aux_op, aux_entry, FALSE,
   9365                                          hit, tcam_index, log_bkt);
   9366             }
   9367         } else {
   9368             rv = _soc_alpm_aux_hw_op(u, aux_op, aux_entry, update_scratch,
   9369                                      hit, tcam_index, log_bkt);
   9370         }
   9371 
   9372         if ((aux_op == INSERT_PROPAGATE || aux_op == DELETE_PROPAGATE) &&
   9373             SOC_SUCCESS(rv) && SOC_URPF_STATUS_GET(u)) {
   9374             soc_mem_t mem = L3_DEFIP_AUX_SCRATCHm;
   9375             val = soc_mem_field32_get(u, mem, aux_entry, DB_TYPEf);
   9376             soc_mem_field32_set(u, mem, aux_entry, DB_TYPEf, val + 1);
   9377 
   9378             val = (aux_flags & SOC_ALPM_AUX_DEF_ROUTE) ? 1 : 0;
   9379             soc_mem_field32_set(u, mem, aux_entry, DEFAULTROUTEf, val);
   9380 
   9381             val = (aux_flags & SOC_ALPM_AUX_SRC_DISCARD) ? 1 : 0;
   9382             soc_mem_field32_set(u, mem, aux_entry, SRC_DISCARDf, val);
   9383 
   9384             if (SOC_IS_TRIDENT2(u) && (aux_op == INSERT_PROPAGATE)) {
   9385                 /*
   9386                  * Do DELETE propagation to update existing default datas
   9387                  * Since INSERT Propagate doesn't handle '==' case.
   9388                  */
   9389                 rv = _soc_alpm_aux_hw_op(u, DELETE_PROPAGATE, aux_entry,
   9390                                          TRUE, NULL, NULL, NULL);
   9391                 if (SOC_SUCCESS(rv)) {
   9392                     rv = _soc_alpm_aux_hw_op(u, aux_op, aux_entry, FALSE,
   9393                                              NULL, NULL, NULL);
   9394                 }
   9395             } else {
   9396                 rv = _soc_alpm_aux_hw_op(u, aux_op, aux_entry, TRUE,
   9397                                          NULL, NULL, NULL);
   9398             }
   9399         }
   9400     }
   9401 
   9402     return rv;
   9403 }
   9404 
   9405 /* Perform an ALPM mem read operation */
   9406 int
   9407 _soc_mem_alpm_read(int unit, soc_mem_t mem, int copyno,
   9408                    int index, void *entry_data)
   9409 {
   9410     int rv = SOC_E_NONE;
   9411     int read_no_cache = FALSE;
   9412 
   9413     switch (mem) {
   9414         case L3_DEFIPm:
   9415         case L3_DEFIP_PAIR_128m:
   9416         case L3_DEFIP_ALPM_RAWm:
   9417         case L3_DEFIP_ALPM_IPV4m:
   9418         case L3_DEFIP_ALPM_IPV4_1m:
   9419         case L3_DEFIP_ALPM_IPV6_64m:
   9420         case L3_DEFIP_ALPM_IPV6_64_1m:
   9421         case L3_DEFIP_ALPM_IPV6_128m:
   9422             if (!ALPM_CTRL(unit).hit_bits_skip) {
   9423                 /* Be sure to get hit information */
   9424                 read_no_cache = TRUE;
   9425             }
   9426             break;
   9427         default:
   9428             break;
   9429     }
   9430 
   9431     if (read_no_cache) {
   9432         rv = soc_mem_read_no_cache(unit, 0, mem, 0, copyno, index, entry_data);
   9433     } else {
   9434         rv = soc_mem_read(unit, mem, copyno, index, entry_data);
   9435     }
   9436 
   9437     return rv;
   9438 }
   9439 
   9440 /* Initialize the ALPM memory from a TCAM entry */
   9441 static int
   9442 _soc_alpm_mem_ent_init(int unit, void *lpm_entry, 
   9443                        void *alpm_entry, void *alpm_sip_entry, soc_mem_t mem,
   9444                        uint32 flags, uint32 *is_default)
   9445 {
   9446     uint32 ipv4a;
   9447     uint32 ip6_word[4] = {0, 0};
   9448     int    pfx = 0;
   9449     int    rv = SOC_E_NONE;
   9450     int ipv6;
   9451     uint32 default_route = 0;
   9452 
   9453     ipv6 = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, MODE0f);
   9454 
   9455     /* Zero Buffer */
   9456     sal_memset(alpm_entry, 0, soc_mem_entry_words(unit, mem) * 4);
   9457 
   9458     if (!soc_feature(unit, soc_feature_alpm_hit_bits_not_support)) {
   9459         ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, HIT0f);
   9460         soc_mem_field32_set(unit, mem, alpm_entry, HITf, ipv4a);
   9461     }
   9462 
   9463     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, VALID0f);
   9464     soc_mem_field32_set(unit, mem, alpm_entry, VALIDf, ipv4a);
   9465 
   9466     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, ECMP0f);
   9467     soc_mem_field32_set(unit, mem, alpm_entry, ECMPf, ipv4a);
   9468 
   9469     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, ECMP_PTR0f);
   9470     soc_mem_field32_set(unit, mem, alpm_entry, ECMP_PTRf, ipv4a);
   9471 
   9472     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, NEXT_HOP_INDEX0f);
   9473     soc_mem_field32_set(unit, mem, alpm_entry, NEXT_HOP_INDEXf, ipv4a);
   9474 
   9475     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, PRI0f);
   9476     soc_mem_field32_set(unit, mem, alpm_entry, PRIf, ipv4a);
   9477 
   9478     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, RPE0f);
   9479     soc_mem_field32_set(unit, mem, alpm_entry, RPEf, ipv4a);
   9480 
   9481     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, DST_DISCARD0f);
   9482     soc_mem_field32_set(unit, mem, alpm_entry, DST_DISCARDf, ipv4a);
   9483 
   9484     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, SRC_DISCARD0f);
   9485     soc_mem_field32_set(unit, mem, alpm_entry, SRC_DISCARDf, ipv4a);
   9486 
   9487     ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, CLASS_ID0f);
   9488     soc_mem_field32_set(unit, mem, alpm_entry, CLASS_IDf, ipv4a);
   9489 
   9490     /* Set IP Address and IP length */
   9491     ip6_word[0] = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, IP_ADDR0f);
   9492     if (ipv6) {
   9493         ip6_word[1] = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, IP_ADDR1f);
   9494     }
   9495     soc_mem_field_set(unit, mem, (uint32*)alpm_entry, KEYf, (uint32*)ip6_word);
   9496 
   9497     if (ipv6) {
   9498         ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f);
   9499         if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
   9500             return(rv);
   9501         }
   9502         ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f);
   9503         if (pfx) {
   9504             if (ipv4a != 0xffffffff)  {
   9505                 return(SOC_E_PARAM);
   9506             }
   9507             pfx += 32;
   9508         } else {
   9509             if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
   9510                 return(rv);
   9511             }
   9512         }
   9513     } else {
   9514         ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f);
   9515         if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
   9516             return(rv);
   9517         }
   9518     }
   9519     if ((pfx == 0) && (ip6_word[0] == 0) && (ip6_word[1] == 0)) {
   9520         default_route = 1;
   9521     }
   9522     if (is_default != NULL) {
   9523         *is_default = default_route;
   9524     }
   9525     soc_mem_field32_set(unit, mem, alpm_entry, LENGTHf, pfx);
   9526 
   9527     if (mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64_1m) {
   9528         ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, FLEX_CTR_BASE_COUNTER_IDX0f);
   9529         soc_mem_field32_set(unit, mem, alpm_entry, FLEX_CTR_BASE_COUNTER_IDXf, ipv4a);
   9530 
   9531         ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, FLEX_CTR_OFFSET_MODE0f);
   9532         soc_mem_field32_set(unit, mem, alpm_entry, FLEX_CTR_OFFSET_MODEf, ipv4a);
   9533 
   9534         ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, FLEX_CTR_POOL_NUMBER0f);
   9535         soc_mem_field32_set(unit, mem, alpm_entry, FLEX_CTR_POOL_NUMBERf, ipv4a);
   9536     }
   9537 
   9538     if (alpm_sip_entry == NULL) {
   9539         return (SOC_E_NONE);
   9540     }
   9541     if (SOC_URPF_STATUS_GET(unit)) {
   9542         sal_memset(alpm_sip_entry, 0, soc_mem_entry_words(unit, mem) * 4);
   9543         sal_memcpy(alpm_sip_entry, alpm_entry, soc_mem_entry_words(unit, mem) * 4);
   9544         soc_mem_field32_set(unit, mem, alpm_sip_entry, DST_DISCARDf, 0);
   9545         soc_mem_field32_set(unit, mem, alpm_sip_entry, RPEf, 0);
   9546 
   9547         soc_mem_field32_set(unit, mem, alpm_sip_entry, SRC_DISCARDf,
   9548                             flags & SOC_ALPM_RPF_SRC_DISCARD);
   9549         soc_mem_field32_set(unit, mem, alpm_sip_entry, DEFAULTROUTEf,
   9550                             default_route);
   9551     }
   9552 
   9553     return (SOC_E_NONE);
   9554 }
   9555 
   9556 /* Initialize the TCAM entry from ALPM memory */
   9557 static int
   9558 _soc_alpm_lpm_ent_init(int unit, void *alpm_entry, soc_mem_t mem, int ipv6, 
   9559                        int vrf_id, int bucket, int index, void *lpm_entry,
   9560                        int flex)
   9561 {
   9562     uint32 ipv4a;
   9563     uint32 ip6_word[4] = {0, 0};
   9564     uint32 pfx = 0;
   9565 
   9566     /* Zero Buffer */
   9567     sal_memset(lpm_entry, 0, soc_mem_entry_words(unit, L3_DEFIPm) * 4);
   9568 
   9569     if (!soc_feature(unit, soc_feature_alpm_hit_bits_not_support)) {
   9570         ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, HITf);
   9571         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, HIT0f, ipv4a);
   9572         if (ipv6) {
   9573             soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, HIT1f, ipv4a);
   9574         }
   9575     }
   9576 
   9577     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, VALIDf);
   9578     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, VALID0f, ipv4a);
   9579     if (ipv6) {
   9580         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, VALID1f, ipv4a);
   9581     }
   9582 
   9583     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, ECMPf);
   9584     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, ECMP0f, ipv4a);
   9585 
   9586     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, ECMP_PTRf);
   9587     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, ECMP_PTR0f, ipv4a);
   9588 
   9589     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, NEXT_HOP_INDEXf);
   9590     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, NEXT_HOP_INDEX0f, ipv4a);
   9591 
   9592     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, PRIf);
   9593     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, PRI0f, ipv4a);
   9594 
   9595     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, RPEf);
   9596     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, RPE0f, ipv4a);
   9597 
   9598     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, DST_DISCARDf);
   9599     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, DST_DISCARD0f, ipv4a);
   9600 
   9601     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, SRC_DISCARDf);
   9602     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, SRC_DISCARD0f, ipv4a);
   9603 
   9604     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, CLASS_IDf);
   9605     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, CLASS_ID0f, ipv4a);
   9606 
   9607     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, ALG_BKT_PTR0f, bucket);
   9608     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, ALG_HIT_IDX0f, index);
   9609     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, MODE_MASK0f, 3);
   9610     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, ENTRY_TYPE_MASK0f, 1);
   9611 
   9612     if (ipv6) {
   9613         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, MODE0f, 1);
   9614         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, MODE1f, 1);
   9615     }
   9616 
   9617     /* Set IP Address and IP length */
   9618     soc_mem_field_get(unit, mem, alpm_entry, KEYf, ip6_word);
   9619     if (ipv6) {
   9620         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, IP_ADDR1f, 
   9621                             ip6_word[1]);
   9622     }
   9623     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, IP_ADDR0f, ip6_word[0]);
   9624 
   9625     ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, LENGTHf);
   9626     if (ipv6) {
   9627         if (ipv4a >= 32) {
   9628             pfx = 0xffffffff;
   9629             soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, pfx);
   9630             pfx = ~SHR_SHIFT_RIGHT(0xffffffff, ipv4a - 32);
   9631             soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, pfx);
   9632         } else {
   9633             pfx = ~(0xffffffff >> ipv4a);
   9634             soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, pfx);
   9635         }
   9636     } else {
   9637         assert(ipv4a <= 32);
   9638         pfx = ~SHR_SHIFT_RIGHT(0xffffffff, ipv4a);
   9639         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, pfx);
   9640     }
   9641 
   9642     soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, ENTRY_VIEW0f, flex);
   9643 
   9644     if (vrf_id == SOC_L3_VRF_OVERRIDE) {
   9645         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, GLOBAL_HIGH0f, 1);
   9646         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f, 1);
   9647         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, VRF_ID_0f, 0);
   9648         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f, 0);
   9649     } else  if (vrf_id == SOC_L3_VRF_GLOBAL) {
   9650         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f, 1);
   9651         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, VRF_ID_0f, 0);
   9652         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f, 0);
   9653     } else {
   9654         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, VRF_ID_0f, vrf_id);
   9655         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f,
   9656                             SOC_VRF_MAX(unit));
   9657     }
   9658 
   9659     if (mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64_1m) {
   9660         ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, FLEX_CTR_BASE_COUNTER_IDXf);
   9661         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, FLEX_CTR_BASE_COUNTER_IDX0f, ipv4a);
   9662 
   9663         ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, FLEX_CTR_OFFSET_MODEf);
   9664         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, FLEX_CTR_OFFSET_MODE0f, ipv4a);
   9665 
   9666         ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, FLEX_CTR_POOL_NUMBERf);
   9667         soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, FLEX_CTR_POOL_NUMBER0f, ipv4a);
   9668     }
   9669 
   9670     return (SOC_E_NONE);
   9671 }
   9672 
   9673 int 
   9674 soc_alpm_warmboot_pivot_add(int unit,
   9675                             int ipv6,
   9676                             void *lpm_entry,
   9677                             int tcam_idx, 
   9678                             int bckt_idx)
   9679 {
   9680     int                  rv = SOC_E_NONE;
   9681     uint32               key[2] = {0, 0};
   9682     alpm_pivot_t         *pivot = NULL;
   9683     alpm_bucket_handle_t *bucket_handle = NULL;
   9684     int                  vrf_id = 0, vrf = 0;
   9685     uint32               length2;
   9686     trie_t               *pivot_root = NULL;
   9687     uint32               prefix[5] = {0};
   9688     uint32               bpm_len = 0;
   9689     int                  default_route = 0;
   9690     defip_aux_table_entry_t aux_ent;
   9691 
   9692     rv = _alpm_prefix_create(unit, lpm_entry, prefix, &length2, &default_route);
   9693     SOC_IF_ERROR_RETURN(rv);    
   9694 
   9695     SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf));
   9696     tcam_idx = soc_alpm_physical_idx(unit, L3_DEFIPm, tcam_idx, ipv6);
   9697 
   9698     /* Allocate bucket handle */
   9699     bucket_handle = sal_alloc(sizeof(alpm_bucket_handle_t), "ALPM Bucket Handle");
   9700     if (bucket_handle == NULL) {
   9701         LOG_ERROR(BSL_LS_SOC_ALPM,
   9702                   (BSL_META_U(unit,
   9703                               "Unable to allocate memory for "
   9704                               "PIVOT trie node \n")));
   9705         return SOC_E_NONE;
   9706     }
   9707     sal_memset(bucket_handle, 0, sizeof(*bucket_handle));
   9708 
   9709     /* Allocate pivot Payload */
   9710     pivot = sal_alloc(sizeof(alpm_pivot_t), "Payload for Pivot");
   9711     if (pivot == NULL) {
   9712         LOG_ERROR(BSL_LS_SOC_ALPM,
   9713                   (BSL_META_U(unit,
   9714                               "Unable to allocate memory for "
   9715                               "PIVOT trie node \n")));
   9716         sal_free(bucket_handle);
   9717         return SOC_E_MEMORY;
   9718     }
   9719     sal_memset(pivot, 0, sizeof(*pivot));
   9720 
   9721     /* Save bucket_handle in pivot->bucket_trie */
   9722     PIVOT_BUCKET_HANDLE(pivot) = bucket_handle;
   9723     
   9724     if (ipv6) {
   9725         trie_init(_MAX_KEY_LEN_144_, &PIVOT_BUCKET_TRIE(pivot));
   9726 
   9727         /* Set address to the buffer. */
   9728         key[0] = soc_L3_DEFIPm_field32_get(unit, lpm_entry, IP_ADDR0f);
   9729 
   9730         /* Set address to the buffer. */
   9731         key[1] = soc_L3_DEFIPm_field32_get(unit, lpm_entry, IP_ADDR1f);
   9732     } else {
   9733         trie_init(_MAX_KEY_LEN_48_, &PIVOT_BUCKET_TRIE(pivot));
   9734 
   9735         /* Set address to the buffer. */
   9736         key[0] = soc_L3_DEFIPm_field32_get(unit, lpm_entry, IP_ADDR0f);
   9737     }
   9738     
   9739     /* Save bucket index into pivot->bucket->bucket_index */
   9740     PIVOT_BUCKET_INDEX(pivot) = bckt_idx;
   9741    
   9742     /* Save tcam index into pivot->tcam_index */
   9743     PIVOT_TCAM_INDEX(pivot) = tcam_idx;
   9744 
   9745     if (vrf_id != SOC_L3_VRF_OVERRIDE) {
   9746         if (ipv6 == 0) {
   9747             pivot_root = VRF_PIVOT_TRIE_IPV4(unit, vrf);
   9748             if (pivot_root == NULL) {
   9749                 trie_init(_MAX_KEY_LEN_48_, &VRF_PIVOT_TRIE_IPV4(unit, vrf));
   9750                 pivot_root = VRF_PIVOT_TRIE_IPV4(unit, vrf);
   9751             }
   9752         } else {
   9753             pivot_root = VRF_PIVOT_TRIE_IPV6(unit, vrf);
   9754             if (pivot_root == NULL) {
   9755                 trie_init(_MAX_KEY_LEN_144_, &VRF_PIVOT_TRIE_IPV6(unit, vrf));
   9756                 pivot_root = VRF_PIVOT_TRIE_IPV6(unit, vrf);
   9757             }
   9758         }
   9759 
   9760         sal_memcpy(pivot->key, prefix, sizeof(prefix));
   9761         pivot->len    = length2;
   9762         
   9763         /* insert into pivot trie */
   9764         rv = soc_mem_read(unit, L3_DEFIP_AUX_TABLEm, SOC_BLOCK_ANY,
   9765                           tcam_idx >> 1, &aux_ent);
   9766         if (SOC_SUCCESS(rv)) {
   9767             bpm_len = soc_mem_field32_get(unit, L3_DEFIP_AUX_TABLEm, &aux_ent,
   9768                                 ipv6 ? BPM_LENGTH0f :
   9769                                 (tcam_idx & 1) ? BPM_LENGTH1f : BPM_LENGTH0f);
   9770         }
   9771 
   9772         rv = trie_insert(pivot_root, pivot->key, NULL, pivot->len, 
   9773                          (trie_node_t *)pivot);
   9774         if (SOC_FAILURE(rv)) {
   9775             sal_free(bucket_handle);
   9776             sal_free(pivot);
   9777             return rv;
   9778         }
   9779     }
   9780 
   9781     PIVOT_TCAM_BPMLEN(pivot) = bpm_len;
   9782     /* Insert pivot into global pivot array indexed by tcam_idx */
   9783     ALPM_TCAM_PIVOT(unit, tcam_idx) = pivot;
   9784     PIVOT_BUCKET_VRF(pivot) = vrf;
   9785     PIVOT_BUCKET_IPV6(pivot) = ipv6;
   9786     
   9787     PIVOT_BUCKET_ENT_CNT_UPDATE(pivot);
   9788     if (key[0] == 0 && key[1] == 0) {
   9789         PIVOT_BUCKET_DEF(pivot) = TRUE;
   9790     }
   9791 
   9792     return rv;
   9793 }
   9794 
   9795 
   9796 static int
   9797 _soc_alpm_warmboot_insert(int unit,
   9798                           int ipv6,
   9799                           int  flex,
   9800                           void *lpm_entry, 
   9801                           void *alpm_entry, /* ALPM (SRAM) entry data */
   9802                           int tcam_idx,     /* TCAM index             */
   9803                           int bckt_idx,     /* Bucket index           */
   9804                           int alpm_idx )    /* ALPM entry index       */
   9805 {
   9806     int          vrf_id;  /* Internal API representation of VRF id           */
   9807     int          vrf;      /* VRF in 0 to (MAX_VRF + 1) range;                */
   9808                            /* VRF = (MAX_VRF + 1), software rep of GLOBAL VRF */
   9809     int          rv = SOC_E_NONE;
   9810     int          default_route = 0;
   9811     uint32       prefix[5] = {0, 0, 0, 0, 0};
   9812     uint32       length;
   9813     defip_entry_t temp_lpm_entry;
   9814     trie_t       *bkt_trie = NULL;
   9815     trie_t       *pfx_trie = NULL;
   9816     trie_node_t  *delp = NULL;
   9817     payload_t    *bkt_payload = NULL;
   9818     payload_t    *pfx_payload = NULL;
   9819     alpm_pivot_t *pivot_pyld = NULL;
   9820     soc_mem_t    mem;
   9821     defip_entry_t *def_entry = NULL;
   9822 
   9823     /* Check function params */
   9824     if ((NULL == lpm_entry) || (NULL == alpm_entry)) {
   9825         return SOC_E_PARAM;
   9826     }
   9827 
   9828     /* Check IPv6 */
   9829     if (ipv6) {
   9830         if (!(ipv6 = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, MODE1f))) {
   9831             return (SOC_E_PARAM);
   9832         }
   9833     }
   9834 
   9835     /* Get VRF */
   9836     SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf));
   9837 
   9838     /* Get ALPM table memory. */
   9839     SOC_ALPM_TABLE_MEM(unit, ipv6, mem, flex);
   9840 
   9841     /* Convert alpm_entry into lpm_entry to extract prefix */ 
   9842     SOC_IF_ERROR_RETURN(_soc_alpm_lpm_ent_init(unit, alpm_entry,  mem, ipv6, 
   9843                                                vrf_id, bckt_idx, tcam_idx,
   9844                                                &temp_lpm_entry, 0));
   9845    
   9846     /* Create Prefix */
   9847     rv = _alpm_prefix_create(unit, &temp_lpm_entry, prefix, &length, &default_route);
   9848     if (SOC_FAILURE(rv)) {
   9849         LOG_ERROR(BSL_LS_SOC_ALPM,
   9850                   (BSL_META_U(unit,
   9851                               "prefix create failed\n")));
   9852         return rv;
   9853     }
   9854    
   9855     /* Get TCAM pivot */ 
   9856     pivot_pyld = ALPM_TCAM_PIVOT(unit, tcam_idx);
   9857     
   9858     /* Get bucket trie from pivot */ 
   9859     bkt_trie = PIVOT_BUCKET_TRIE(pivot_pyld);
   9860    
   9861     /* Allocate bucket payload */
   9862     bkt_payload = sal_alloc(sizeof(payload_t), "Payload for Key");
   9863     if (NULL == bkt_payload) {
   9864         LOG_ERROR(BSL_LS_SOC_ALPM,
   9865                   (BSL_META_U(unit,
   9866                               "Unable to allocate memory for trie node.\n")));
   9867         return SOC_E_MEMORY;
   9868     }
   9869 
   9870     /* Allocate prefix trie payload */
   9871     pfx_payload = sal_alloc(sizeof(payload_t), "Payload for pfx trie key");
   9872     if (NULL == pfx_payload) {
   9873         LOG_ERROR(BSL_LS_SOC_ALPM,
   9874                   (BSL_META_U(unit,
   9875                               "Unable to allocate memory for pfx trie node\n")));
   9876         sal_free(bkt_payload);
   9877         return SOC_E_MEMORY;
   9878     }
   9879   
   9880     /* Clear allocated payloads */ 
   9881     sal_memset(bkt_payload, 0, sizeof(*bkt_payload));
   9882     sal_memset(pfx_payload, 0, sizeof(*pfx_payload));
   9883 
   9884     bkt_payload->key[0] = prefix[0]; 
   9885     bkt_payload->key[1] = prefix[1]; 
   9886     bkt_payload->key[2] = prefix[2]; 
   9887     bkt_payload->key[3] = prefix[3]; 
   9888     bkt_payload->key[4] = prefix[4]; 
   9889     bkt_payload->len    = length;
   9890     bkt_payload->index  = alpm_idx;
   9891  
   9892 #ifdef ALPM_WARM_BOOT_DEBUG_EXTENSIVE
   9893     LOG_ERROR(BSL_LS_SOC_ALPM,
   9894               (BSL_META_U(unit,
   9895                           "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, length = 0x%x alpm_idx = 0x%x\n"),
   9896                bkt_payload->key[0], bkt_payload->key[1], bkt_payload->key[2],
   9897                bkt_payload->key[3], bkt_payload->key[4],
   9898                length, alpm_idx));
   9899 #endif
   9900 
   9901     /* Create duplicate for prefix trie */
   9902     sal_memcpy(pfx_payload, bkt_payload, sizeof(*bkt_payload));
   9903     pfx_payload->bkt_ptr = bkt_payload;
   9904 
   9905     /* Insert prefix into bucket-trie */
   9906     rv = trie_insert(bkt_trie, prefix, NULL, length, 
   9907                     (trie_node_t *)bkt_payload);
   9908     if (SOC_FAILURE(rv)) {
   9909         goto free_memory;
   9910     }
   9911 
   9912     /* Insert prefix into prefix-trie */
   9913     if (ipv6) {
   9914         pfx_trie = VRF_PREFIX_TRIE_IPV6(unit, vrf);
   9915     } else {
   9916         pfx_trie = VRF_PREFIX_TRIE_IPV4(unit, vrf);
   9917     }
   9918     
   9919     if (!default_route) {
   9920         /* Default route already in prefix trie */
   9921         rv = trie_insert(pfx_trie, prefix, NULL, length, 
   9922                         (trie_node_t *)pfx_payload);
   9923         if (SOC_FAILURE(rv)) {
   9924             goto delete_bkt_trie;
   9925         }
   9926     }
   9927 
   9928     /* Update bucket index for VRF default route entry */
   9929     if (VRF_TRIE_INIT_COMPLETED(unit, vrf, ipv6)) {
   9930         if (ipv6 == 0) {
   9931             def_entry = VRF_TRIE_DEFAULT_ROUTE_IPV4(unit, vrf);
   9932         } else {
   9933             def_entry = VRF_TRIE_DEFAULT_ROUTE_IPV6(unit, vrf);
   9934         }
   9935 
   9936         if (0 == soc_L3_DEFIPm_field32_get(unit, def_entry, ALG_BKT_PTR0f)) {
   9937             default_route = 0;
   9938             rv = _alpm_prefix_create(unit, lpm_entry, prefix,
   9939                                      &length, &default_route);
   9940             if (SOC_SUCCESS(rv) && default_route) {
   9941                 soc_L3_DEFIPm_field32_set(unit, def_entry,
   9942                                           ALG_BKT_PTR0f, bckt_idx);
   9943             }
   9944         }
   9945     }
   9946 
   9947     /* Return success */
   9948     return rv;
   9949 
   9950 delete_bkt_trie:
   9951     (void) trie_delete(bkt_trie, prefix, length, &delp);
   9952     bkt_payload = (payload_t *) delp;
   9953 
   9954 free_memory:
   9955     sal_free(bkt_payload);
   9956     sal_free(pfx_payload);
   9957     return rv;
   9958 }
   9959 
   9960 /*
   9961  * soc_alpm_warmboot_vrf_add
   9962  */
   9963 static int
   9964 soc_alpm_warmboot_vrf_add(int unit, 
   9965                           int v6,
   9966                           int vrf,
   9967                           int idx,
   9968                           int bkt_ptr)
   9969 {
   9970 
   9971     int           rv = SOC_E_NONE;
   9972     uint32        length;
   9973     uint32        key[5] = {0};
   9974     trie_t        *pfx_root = NULL;
   9975     payload_t     *pfx_pyld = NULL;
   9976     defip_entry_t *lpm_entry = NULL;
   9977 
   9978     /* Initialize VRF PIVOT IPV4 trie */
   9979     lpm_entry = sal_alloc(sizeof(defip_entry_t), "Default LPM entry");
   9980     if (lpm_entry == NULL) {
   9981         LOG_ERROR(BSL_LS_SOC_ALPM,
   9982                   (BSL_META_U(unit,
   9983                               "unable to allocate memory for LPM entry\n")));
   9984         return SOC_E_MEMORY;
   9985     }
   9986 
   9987     /* Initialize an lpm entry to perform a match */
   9988     (void) _soc_alpm_lpm_ent_key_init(unit, key, 0, vrf, v6, lpm_entry, 1);
   9989 
   9990     /* for global VRF */
   9991     if (vrf == SOC_VRF_MAX(unit) + 1) {
   9992         soc_L3_DEFIPm_field32_set(unit, lpm_entry, GLOBAL_ROUTE0f, 1);
   9993     } else {
   9994         /* Set default miss to global route only for non global routes */
   9995         soc_L3_DEFIPm_field32_set(unit, lpm_entry, DEFAULT_MISS0f, 1);
   9996     }
   9997     
   9998     if (v6 == 0) {
   9999         VRF_TRIE_DEFAULT_ROUTE_IPV4(unit, vrf) = lpm_entry;
  10000         trie_init(_MAX_KEY_LEN_48_, &VRF_PREFIX_TRIE_IPV4(unit, vrf));
  10001         pfx_root = VRF_PREFIX_TRIE_IPV4(unit, vrf);
  10002     } else {
  10003         VRF_TRIE_DEFAULT_ROUTE_IPV6(unit, vrf) = lpm_entry;
  10004         trie_init(_MAX_KEY_LEN_144_, &VRF_PREFIX_TRIE_IPV6(unit, vrf));
  10005         pfx_root = VRF_PREFIX_TRIE_IPV6(unit, vrf);
  10006     }
  10007   
  10008     pfx_pyld = sal_alloc(sizeof(payload_t), "Payload for pfx trie key");
  10009     if (pfx_pyld == NULL) {
  10010         LOG_ERROR(BSL_LS_SOC_ALPM,
  10011                   (BSL_META_U(unit,
  10012                               "Unable to allocate memory for pfx trie node \n")));
  10013         return SOC_E_MEMORY;
  10014     }
  10015 
  10016     sal_memset(pfx_pyld,   0, sizeof(*pfx_pyld));
  10017 
  10018     length = 0;
  10019     pfx_pyld->key[0] = key[0]; 
  10020     pfx_pyld->key[1] = key[1]; 
  10021     pfx_pyld->len    = length;
  10022 
  10023     rv = trie_insert(pfx_root, key, NULL, length, &(pfx_pyld->node));
  10024     if (SOC_FAILURE(rv)) {
  10025         sal_free(pfx_pyld);
  10026         return rv;
  10027     }
  10028 
  10029     VRF_TRIE_INIT_DONE(unit, vrf, v6, 1);
  10030     
  10031     return rv;
  10032 }
  10033 /*
  10034  * soc_alpm_warmboot_prefix_insert
  10035  */
  10036 int
  10037 soc_alpm_warmboot_prefix_insert(int unit, 
  10038                                 int  ipv6,
  10039                                 int  flex,
  10040                                 void *lpm_entry, 
  10041                                 void *alpm_entry, 
  10042                                 int tcam_idx, 
  10043                                 int bckt_idx, 
  10044                                 int alpm_idx)
  10045 {
  10046     int       vrf_id;  /* Internal API representation of VRF id */
  10047     int       vrf;      /* VRF in (0 - (MAX_VRF + 1)) range */
  10048     int       rv = SOC_E_NONE; 
  10049 
  10050     tcam_idx = soc_alpm_physical_idx(unit, L3_DEFIPm, tcam_idx, ipv6);
  10051  
  10052     /* Get VRF */
  10053     SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf));
  10054     
  10055     /* For VRF_OVERRIDE (Global High) entries,  Prefix resides in TCAM directly */
  10056     if (vrf_id == SOC_L3_VRF_OVERRIDE) {
  10057         return(rv);
  10058     }
  10059     /* Non override entries, goes into ALPM memory */
  10060     if (!VRF_TRIE_INIT_COMPLETED(unit, vrf, ipv6)) {
  10061         LOG_VERBOSE(BSL_LS_SOC_ALPM,
  10062                     (BSL_META_U(unit,
  10063                                 "VRF %d is not initialized\n"),
  10064                      vrf));
  10065         rv = soc_alpm_warmboot_vrf_add(unit, ipv6, vrf, tcam_idx, bckt_idx);
  10066         if (SOC_FAILURE(rv)) {
  10067             LOG_ERROR(BSL_LS_SOC_ALPM,
  10068                       (BSL_META_U(unit,
  10069                                   "VRF %d/%d trie init \n"
  10070                                   "failed\n"), vrf, ipv6));
  10071             return rv;
  10072         }
  10073 
  10074         LOG_VERBOSE(BSL_LS_SOC_ALPM,
  10075                     (BSL_META_U(unit,
  10076                                 "VRF %d/%d trie init completed\n"),
  10077                      vrf, ipv6));
  10078     }
  10079  
  10080     rv = _soc_alpm_warmboot_insert(unit, ipv6, flex, lpm_entry, alpm_entry,
  10081                                    tcam_idx, bckt_idx, alpm_idx);
  10082     if (rv != SOC_E_NONE) {
  10083         LOG_WARN(BSL_LS_SOC_ALPM,
  10084                  (BSL_META_U(unit,
  10085                              "unit %d : Route Insertion Failed :%s\n"),
  10086                   unit, soc_errmsg(rv)));
  10087 
  10088         return(rv);
  10089     }
  10090     VRF_TRIE_ROUTES_INC(unit, vrf_id, vrf, ipv6);
  10091     return(rv);
  10092 }
  10093 
  10094 /*
  10095  * alpm_warmboot_bucket_bitmap_set
  10096  * This function will set bit position in bucket bitmap
  10097  */
  10098 int  
  10099 soc_alpm_warmboot_bucket_bitmap_set(int u,       /* Unit         */
  10100                                     int v6,      /* Flag v4/v6   */
  10101                                     int bkt_idx) /* Bucket index */
  10102 {
  10103     int step_count = 1;
  10104 
  10105     /*
  10106      * In combined search mode, with urpf disabled, need to allocate even and 
  10107      * odd bucket pointers
  10108      */
  10109     if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) {
  10110         step_count = 2;
  10111     }
  10112 
  10113     if (SOC_ALPM_BUCKET_BMAP(u) == NULL) {
  10114         return SOC_E_INTERNAL;
  10115     }
  10116 
  10117     /* Set bit position */
  10118     SHR_BITSET_RANGE(SOC_ALPM_BUCKET_BMAP(u), bkt_idx, step_count);
  10119     
  10120     return SOC_E_NONE;
  10121 }
  10122 
  10123 int
  10124 soc_alpm_warmboot_lpm_reinit_done(int unit)
  10125 {
  10126     int idx;
  10127     int prev_idx = ALPM_MAX_PFX_INDEX;
  10128 
  10129     int defip_table_size = soc_mem_index_count(unit, L3_DEFIPm);
  10130     
  10131     if (SOC_URPF_STATUS_GET(unit)) {
  10132         defip_table_size >>= 1;
  10133     } 
  10134     
  10135     /* returns 0 for combined search mode and 1 for parallel search mode */
  10136     if (!soc_alpm_mode_get(unit)) {
  10137         /* Combined search mode */
  10138         SOC_ALPM_LPM_STATE_PREV(unit, ALPM_MAX_PFX_INDEX) = -1;
  10139 
  10140         for (idx = ALPM_MAX_PFX_INDEX; idx > -1; idx--) {
  10141             if (-1 == SOC_ALPM_LPM_STATE_START(unit, idx)) {
  10142                 continue;
  10143             }
  10144 
  10145             SOC_ALPM_LPM_STATE_PREV(unit, idx) = prev_idx;
  10146             SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = idx;
  10147 
  10148             SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) =                    \
  10149                               SOC_ALPM_LPM_STATE_START(unit, idx) -      \
  10150                               SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1;
  10151             prev_idx = idx;
  10152             
  10153         }
  10154 
  10155         SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = -1;
  10156         SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) =                       \
  10157                               defip_table_size -                   \
  10158                               SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1;
  10159     } else {
  10160         /* Parallel search mode 
  10161          * 
  10162          *    Configured VRF Range 
  10163          *    {0 - (ALPM_MAX_PFX_INDEX/3)}
  10164          *    Global VRF Range 
  10165          *    {((ALPM_MAX_PFX_INDEX/1) + 1) - (ALPM_MAX_PFX_INDEX/2) }
  10166          *    Override VRF Range 
  10167          *    {((ALPM_MAX_PFX_INDEX/2) + 1) - (ALPM_MAX_PFX_INDEX) }
  10168          */
  10169 
  10170         /*
  10171          * Global and Overide VRF range are treated as single block and
  10172          * both blocks will be linked 
  10173          */
  10174         SOC_ALPM_LPM_STATE_PREV(unit, ALPM_MAX_PFX_INDEX) = -1;
  10175         for (idx = ALPM_MAX_PFX_INDEX; idx > (ALPM_MAX_PFX_INDEX/3) ; idx--) {
  10176             if (-1 == SOC_ALPM_LPM_STATE_START(unit, idx)) {
  10177                 continue;
  10178             }
  10179 
  10180             SOC_ALPM_LPM_STATE_PREV(unit, idx) = prev_idx;
  10181             SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = idx;
  10182 
  10183             SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) =                    \
  10184                               SOC_ALPM_LPM_STATE_START(unit, idx) -      \
  10185                               SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1;
  10186                               
  10187             prev_idx = idx;
  10188         }
  10189         SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = -1;
  10190         SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) =                       \
  10191                               defip_table_size -                        \
  10192                               SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1;
  10193 
  10194         /* Configured VRF range */
  10195         prev_idx = (ALPM_MAX_PFX_INDEX/3);
  10196         SOC_ALPM_LPM_STATE_PREV(unit, (ALPM_MAX_PFX_INDEX/3)) = -1;
  10197         for (idx = ((ALPM_MAX_PFX_INDEX/3)-1); idx > -1; idx--) {
  10198             if (-1 == SOC_ALPM_LPM_STATE_START(unit, idx)) {
  10199                 continue;
  10200             }
  10201 
  10202             SOC_ALPM_LPM_STATE_PREV(unit, idx) = prev_idx;
  10203             SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = idx;
  10204 
  10205             SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) =                    \
  10206                               SOC_ALPM_LPM_STATE_START(unit, idx) -      \
  10207                               SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1;
  10208             prev_idx = idx;
  10209         }
  10210         SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = -1;
  10211         SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) =                         \
  10212                               (defip_table_size >> 1) -                   \
  10213                               SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1;
  10214     }
  10215 
  10216     return (SOC_E_NONE);
  10217 }
  10218 
  10219 int
  10220 soc_alpm_warmboot_lpm_reinit(int unit,
  10221                              int ipv6,
  10222                              int idx,
  10223                              void *lpm_entry)
  10224 {
  10225     int pfx_len;
  10226     int flex;
  10227     defip_entry_t lpm_entry_hi;
  10228     int vrf_id, vrf;
  10229     
  10230     if (soc_L3_DEFIPm_field32_get(unit, lpm_entry, VALID0f) ||
  10231         soc_L3_DEFIPm_field32_get(unit, lpm_entry, VALID1f)) {
  10232     
  10233             LPM_HASH_INSERT(unit, lpm_entry, idx, NULL, NULL);
  10234     }
  10235 
  10236     if (ipv6) {
  10237         if (soc_L3_DEFIPm_field32_get(unit, lpm_entry, VALID0f)) {
  10238             SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf));
  10239             if (!VRF_FLEX_COMPLETED(unit, vrf_id, vrf, ipv6)) {
  10240                 flex = soc_L3_DEFIPm_field32_get(unit, lpm_entry, ENTRY_VIEW0f);
  10241                 VRF_FLEX_SET(unit, vrf_id, vrf, ipv6, flex);
  10242             }
  10243             VRF_PIVOT_REF_INC(unit, vrf_id, vrf, ipv6);
  10244         }
  10245     } else {
  10246         if (soc_L3_DEFIPm_field32_get(unit, lpm_entry, VALID0f)) {
  10247             SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf));
  10248             if (!VRF_FLEX_COMPLETED(unit, vrf_id, vrf, ipv6)) {
  10249                 flex = soc_L3_DEFIPm_field32_get(unit, lpm_entry, ENTRY_VIEW0f);
  10250                 VRF_FLEX_SET(unit, vrf_id, vrf, ipv6, flex);
  10251             }
  10252             VRF_PIVOT_REF_INC(unit, vrf_id, vrf, ipv6);
  10253         }
  10254         if (soc_L3_DEFIPm_field32_get(unit, lpm_entry, VALID1f)) {
  10255             soc_alpm_lpm_ip4entry1_to_0(unit, lpm_entry, &lpm_entry_hi, TRUE);
  10256             SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(unit, &lpm_entry_hi, &vrf_id, &vrf));
  10257             if (!VRF_FLEX_COMPLETED(unit, vrf_id, vrf, ipv6)) {
  10258                 flex = soc_L3_DEFIPm_field32_get(unit, lpm_entry, ENTRY_VIEW1f);
  10259                 VRF_FLEX_SET(unit, vrf_id, vrf, ipv6, flex);
  10260             }
  10261             VRF_PIVOT_REF_INC(unit, vrf_id, vrf, ipv6);
  10262         }
  10263     }
  10264 
  10265     if (soc_L3_DEFIPm_field32_get(unit, lpm_entry, VALID0f)) {
  10266         
  10267         SOC_IF_ERROR_RETURN
  10268             (_soc_alpm_lpm_prefix_length_get(unit, lpm_entry, &pfx_len));
  10269 
  10270         if (SOC_ALPM_LPM_STATE_VENT(unit, pfx_len) == 0) {
  10271             SOC_ALPM_LPM_STATE_START(unit, pfx_len) = idx;
  10272             SOC_ALPM_LPM_STATE_END(unit, pfx_len) = idx;
  10273         } else {
  10274             SOC_ALPM_LPM_STATE_END(unit, pfx_len) = idx;
  10275         }
  10276 
  10277         SOC_ALPM_LPM_STATE_VENT(unit, pfx_len)++;
  10278 
  10279         if (ipv6) {
  10280             /* IPv6 entry */
  10281             return (SOC_E_NONE);
  10282         }
  10283     } else {
  10284         /* Check upper half of lpm_entry */
  10285         if (soc_L3_DEFIPm_field32_get(unit, lpm_entry, VALID1f)) {
  10286             if (ipv6) {
  10287                 return SOC_E_NONE;
  10288             }
  10289 
  10290             /* Get prefix length */
  10291             SOC_IF_ERROR_RETURN
  10292                 (_soc_alpm_lpm_prefix_length_get(unit, &lpm_entry_hi, &pfx_len));
  10293 
  10294             if (SOC_ALPM_LPM_STATE_VENT(unit, pfx_len) == 0) {
  10295                 SOC_ALPM_LPM_STATE_START(unit, pfx_len) = idx;
  10296                 SOC_ALPM_LPM_STATE_END(unit, pfx_len) = idx;
  10297             } else {
  10298                 SOC_ALPM_LPM_STATE_END(unit, pfx_len) = idx;
  10299             }
  10300       
  10301             SOC_ALPM_LPM_STATE_VENT(unit, pfx_len)++;
  10302         }
  10303     } 
  10304     return (SOC_E_NONE);
  10305 }
  10306 
  10307 /* Helper structure for Debug Counter */
  10308 typedef struct _alpm_dbg_cnt_s {
  10309     int v4;         /* Counter for IPv4 */
  10310     int v6_64;      
  10311     int v6_128;     
  10312     int v4t;        /* Totaled counter for IPv4 per VRF */
  10313     int v6_64t;
  10314     int v6_128t;
  10315     int used;
  10316 } _alpm_dbg_cnt_t;
  10317 
  10318 typedef enum _alpm_pvt_cnt_type_e {
  10319     SOC_ALPM_DEBUG_CNT_ADD = 0,
  10320     SOC_ALPM_DEBUG_CNT_DEL,
  10321     SOC_ALPM_DEBUG_CNT_SPLIT,
  10322     SOC_ALPM_DEBUG_CNT_USED,
  10323     SOC_ALPM_DEBUG_CNT_LPM_SHIFT,
  10324     SOC_ALPM_DEBUG_CNT_LPM_FULL
  10325 } _alpm_pvt_cnt_type_t;
  10326 
  10327 
  10328 #define _ALPM_DBG_CNT_ADD(dst_dc, src_dc)       \
  10329     do {                                        \
  10330         (dst_dc)->v4 += (src_dc)->v4;           \
  10331         (dst_dc)->v4t += (src_dc)->v4t;         \
  10332         (dst_dc)->v6_64 += (src_dc)->v6_64;     \
  10333         (dst_dc)->v6_64t += (src_dc)->v6_64t;   \
  10334         (dst_dc)->v6_128 += (src_dc)->v6_128;   \
  10335         (dst_dc)->v6_128t += (src_dc)->v6_128t; \
  10336     } while (0)
  10337 
  10338 /* Common debug counter print */
  10339 #define PRINT_SPLIT_LINE(u)    \
  10340     LOG_CLI((BSL_META_U(u, "-----------------------------------------------\n")))
  10341 #define PRINT_VRF_HEADER(u)    \
  10342     LOG_CLI((BSL_META_U(u, "\n      VRF  v4      v6-64   v6-128  |   AVG\n")))
  10343 #define PRINT_VRF_NOT_FOUND(u) \
  10344     LOG_CLI((BSL_META_U(u, "%9s\n"), "Specific VRF not found"))
  10345 
  10346 /* Print Bucket Occupancy */
  10347 #define BKT_PERCENT(used, tot) \
  10348     (tot) ? (used) * 100 / (tot) : 0, (tot) ? (used) * 1000 / (tot) % 10 : 0
  10349 #define PRINT_BKT_OCCU_ITEM(u, vrf, tmp_dc) \
  10350     do { \
  10351         LOG_CLI((BSL_META_U(u, \
  10352                             "%9d  %02d.%d%%   %02d.%d%%   %02d.%d%%   |   %02d.%d%% %5s\n"), \
  10353                  (vrf), BKT_PERCENT(tmp_dc->v4, tmp_dc->v4t), \
  10354                  BKT_PERCENT(tmp_dc->v6_64, tmp_dc->v6_64t), \
  10355                  BKT_PERCENT(tmp_dc->v6_128, tmp_dc->v6_128t), \
  10356                  BKT_PERCENT((tmp_dc->v4+tmp_dc->v6_64+tmp_dc->v6_128),\
  10357                  (tmp_dc->v4t+tmp_dc->v6_64t+tmp_dc->v6_128t)), \
  10358                  (vrf) == SOC_VRF_MAX(u)+1 ? "GLo" : "")); \
  10359     } while (0)
  10360 #define PRINT_BKT_OCCU_ITEM_TOT(u, all_dc) \
  10361     do { \
  10362         LOG_CLI((BSL_META_U(u, \
  10363                             "%9s  %02d.%d%%   %02d.%d%%   %02d.%d%%   |   %02d.%d%% \n"), \
  10364                  "AVG", BKT_PERCENT((all_dc)->v4, (all_dc)->v4t), \
  10365                  BKT_PERCENT((all_dc)->v6_64, (all_dc)->v6_64t), \
  10366                  BKT_PERCENT((all_dc)->v6_128, (all_dc)->v6_128t), \
  10367                  BKT_PERCENT(((all_dc)->v4+(all_dc)->v6_64+(all_dc)->v6_128),\
  10368                  ((all_dc)->v4t+(all_dc)->v6_64t+(all_dc)->v6_128t)))); \
  10369     } while (0)
  10370 
  10371 /* Print VRF based debug counter */
  10372 #define PRINT_VRF_ITEM(u, vrf, v4, v6_64, v6_128, total) \
  10373     do { \
  10374         LOG_CLI((BSL_META_U(u, \
  10375                             "%9d  %-7d %-7d %-7d |   %-7d %s\n"), \
  10376                  (vrf == MAX_VRF_ID ? -1 : vrf), (v4), (v6_64),\
  10377                  (v6_128), (total), (vrf) == MAX_VRF_ID ? "GHi" : \
  10378                  (vrf) == SOC_VRF_MAX(u)+1 ? "GLo" : "")); \
  10379     } while (0)
  10380 #define PRINT_VRF_ITEM_TOT(u, v4, v6_64, v6_128, total) \
  10381     do { \
  10382         LOG_CLI((BSL_META_U(u, \
  10383                             "%9s  %-7d %-7d %-7d |   %-7d \n"), "Total", (v4), (v6_64),\
  10384                  (v6_128), (total))); \
  10385     } while (0)
  10386 
  10387 #define PRINT_BUCKET_HEADER(u) \
  10388     do { \
  10389         LOG_CLI((BSL_META_U(u, \
  10390                             "\n  BKT/VRF  Min     Max     Cur     |   Comment\n"))); \
  10391     } while (0)
  10392 #define PRINT_BUCKET_ITEM(u, bkt, vrf, min, max, cur, def) \
  10393     do { \
  10394         LOG_CLI((BSL_META_U(u, \
  10395                             "%5d/%-4d %-7d %-7d %-7d |   %-7s\n"), bkt, vrf, \
  10396                  min, max, cur, def ? "Def" : \
  10397                  (vrf) == SOC_VRF_MAX(u)+1 ? "GLo" : "")); \
  10398     } while (0)
  10399 
  10400 /* Get max available IPv4, IPv6-64, IPv6-128 entry numbers */
  10401 static void
  10402 _soc_alpm_pivot_max_get(int u, alpm_vrf_counter_t *pvt_max)
  10403 {
  10404     pvt_max->v4 = soc_mem_index_count(u, L3_DEFIPm) * 2;
  10405     pvt_max->v6_128 = soc_mem_index_count(u, L3_DEFIP_PAIR_128m);
  10406 
  10407     if (SOC_ALPM_128B_ENABLE(u)) {
  10408         pvt_max->v6_64 = pvt_max->v6_128;
  10409     } else {
  10410         pvt_max->v6_64 = pvt_max->v4 >> 1;
  10411     }
  10412     
  10413     if (SOC_URPF_STATUS_GET(u)) {
  10414         pvt_max->v4 >>= 1;
  10415         pvt_max->v6_128 >>= 1;
  10416         pvt_max->v6_64 >>= 1;
  10417     }
  10418 }
  10419 
  10420 static void
  10421 _soc_alpm_pivot_debug_dump(int u, int vrf_id, alpm_vrf_handle_t *vh,
  10422                                    _alpm_pvt_cnt_type_t pct)
  10423 {
  10424     alpm_vrf_counter_t *vc;
  10425     int i, tv4c, tv6_64c, tv6_128c;
  10426     int found = 0;
  10427 
  10428     alpm_vrf_counter_t pvt_max;
  10429 
  10430     /* Print Pivot debug info header */
  10431     switch (pct) {
  10432     case SOC_ALPM_DEBUG_CNT_ADD:
  10433         LOG_CLI((BSL_META_U(u,
  10434                             "\nAdd Counter:\n")));
  10435         break;
  10436     case SOC_ALPM_DEBUG_CNT_DEL:
  10437         LOG_CLI((BSL_META_U(u,
  10438                             "\nDelete Counter:\n"))); 
  10439         break;
  10440     case SOC_ALPM_DEBUG_CNT_SPLIT:
  10441         LOG_CLI((BSL_META_U(u,
  10442                             "\nInternal Debug Counter - Split:\n")));
  10443         break;
  10444     case SOC_ALPM_DEBUG_CNT_USED:
  10445         _soc_alpm_pivot_max_get(u, &pvt_max);
  10446         LOG_CLI((BSL_META_U(u,
  10447                             "\nPivot Occupancy: Max v4/v6-64/v6-128 = %d/%d/%d\n"), 
  10448                  pvt_max.v4, pvt_max.v6_64, pvt_max.v6_128));        
  10449         break;
  10450     case SOC_ALPM_DEBUG_CNT_LPM_SHIFT:
  10451         LOG_CLI((BSL_META_U(u,
  10452                             "\nInternal Debug Counter - LPM Shift:\n"))); 
  10453         break;
  10454     case SOC_ALPM_DEBUG_CNT_LPM_FULL:
  10455         LOG_CLI((BSL_META_U(u,
  10456                             "\nInternal Debug Counter - LPM Full:\n"))); 
  10457         break;
  10458     default:
  10459         break;
  10460     }
  10461     PRINT_VRF_HEADER(u);
  10462     PRINT_SPLIT_LINE(u); 
  10463 
  10464     tv4c = tv6_64c = tv6_128c = 0;    
  10465     for (i = 0; i < MAX_VRF_ID + 1; i++) {
  10466         int v4c, v6_64c, v6_128c;
  10467         if (vh[i].init_done == 0 && i != MAX_VRF_ID) {
  10468             continue;
  10469         }
  10470         if (vrf_id != -1 && vrf_id != i) {
  10471             continue;
  10472         }
  10473 
  10474         found = 1;
  10475 
  10476         switch (pct) {
  10477         case SOC_ALPM_DEBUG_CNT_ADD:
  10478             vc = &vh[i].add;
  10479             break;
  10480         case SOC_ALPM_DEBUG_CNT_DEL:
  10481             vc = &vh[i].del;
  10482             break;
  10483         case SOC_ALPM_DEBUG_CNT_SPLIT:
  10484             vc = &vh[i].bkt_split;
  10485             break;
  10486         case SOC_ALPM_DEBUG_CNT_LPM_SHIFT:
  10487             vc = &vh[i].lpm_shift;
  10488             break;
  10489         case SOC_ALPM_DEBUG_CNT_LPM_FULL:
  10490             vc = &vh[i].lpm_full;
  10491             break;            
  10492         case SOC_ALPM_DEBUG_CNT_USED:
  10493             vc = &vh[i].pivot_used;
  10494             break;
  10495         default:
  10496             vc = &vh[i].pivot_used;
  10497             break;
  10498         }
  10499             
  10500         v4c = vc->v4;
  10501         v6_64c = vc->v6_64;
  10502         v6_128c = vc->v6_128;
  10503 
  10504         tv4c += v4c;
  10505         tv6_64c += v6_64c;
  10506         tv6_128c += v6_128c;
  10507 
  10508         PRINT_VRF_ITEM(u, i, v4c, v6_64c, v6_128c, (v4c+v6_64c+v6_128c));
  10509     }
  10510     if (found == 0) {
  10511         PRINT_VRF_NOT_FOUND(u);
  10512     } else {        
  10513         PRINT_SPLIT_LINE(u);
  10514         PRINT_VRF_ITEM_TOT(u, tv4c, tv6_64c, tv6_128c, (tv4c+tv6_64c+tv6_128c));
  10515     }
  10516 
  10517     return ;
  10518 }
  10519 
  10520 int
  10521 soc_alpm_debug_show(int u, int vrf_id, uint32 flags)
  10522 {
  10523     int i, alloc_sz, found = 0;
  10524     _alpm_dbg_cnt_t *alpm_dc_arr;
  10525     _alpm_dbg_cnt_t bkt_ent_max;
  10526     _alpm_dbg_cnt_t all_dc;
  10527 
  10528     if (vrf_id > (SOC_VRF_MAX(u) + 1)) {
  10529         return SOC_E_PARAM;
  10530     }
  10531 
  10532     alloc_sz = MAX_VRF_ID * sizeof(_alpm_dbg_cnt_t);
  10533     alpm_dc_arr = sal_alloc(alloc_sz, "_alpm_dbg_cnt");
  10534     if (alpm_dc_arr == NULL) {
  10535         return SOC_E_MEMORY;
  10536     }
  10537     sal_memset(alpm_dc_arr, 0, alloc_sz);
  10538 
  10539     /* Collect data */
  10540     bkt_ent_max.v4 = ALPM_IPV4_BKT_COUNT;
  10541     bkt_ent_max.v6_64 = ALPM_IPV6_64_BKT_COUNT;
  10542     bkt_ent_max.v6_128 = ALPM_IPV6_128_BKT_COUNT;    
  10543 
  10544     if (!soc_alpm_mode_get(u) && !SOC_URPF_STATUS_GET(u)) {
  10545         bkt_ent_max.v6_64  <<= 1;
  10546         bkt_ent_max.v6_128 <<= 1;
  10547     }
  10548 
  10549     /* 1. Bucket Occupancy */
  10550     if (flags & (SOC_ALPM_DEBUG_SHOW_FLAG_BKT)) {
  10551         LOG_CLI((BSL_META_U(u,
  10552                             "\nBucket Occupancy:\n")));
  10553         PRINT_BUCKET_HEADER(u);
  10554         PRINT_SPLIT_LINE(u);
  10555     }
  10556     for (i = 0; i < MAX_PIVOT_COUNT; i++) {
  10557         alpm_pivot_t *p = ALPM_TCAM_PIVOT(u, i);
  10558         if (p != NULL) {
  10559             _alpm_dbg_cnt_t *tmp_dc;
  10560             int vrf = PIVOT_BUCKET_VRF(p);
  10561 
  10562             if (vrf < 0 || vrf > (SOC_VRF_MAX(u) + 1)) {
  10563                 continue;
  10564             }
  10565             
  10566             if (vrf_id != -1 && vrf_id != vrf) {
  10567                 continue;
  10568             }
  10569 
  10570             if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_BKT) {
  10571                 found = 1;
  10572                 PRINT_BUCKET_ITEM(u, i, vrf, 
  10573                                   PIVOT_BUCKET_MIN(p), 
  10574                                   PIVOT_BUCKET_MAX(p), 
  10575                                   PIVOT_BUCKET_COUNT(p), 
  10576                                   PIVOT_BUCKET_DEF(p));
  10577             }
  10578 
  10579             tmp_dc = &alpm_dc_arr[vrf];
  10580             if (PIVOT_BUCKET_IPV6(p) == L3_DEFIP_MODE_128) {
  10581                 tmp_dc->v6_128 += PIVOT_BUCKET_COUNT(p);
  10582                 tmp_dc->v6_128t += bkt_ent_max.v6_128;
  10583             } else if (PIVOT_BUCKET_IPV6(p) == L3_DEFIP_MODE_64) {
  10584                 tmp_dc->v6_64 += PIVOT_BUCKET_COUNT(p);
  10585                 tmp_dc->v6_64t += bkt_ent_max.v6_64;
  10586             } else {
  10587                 tmp_dc->v4 += PIVOT_BUCKET_COUNT(p);
  10588                 tmp_dc->v4t += bkt_ent_max.v4;
  10589             }
  10590             tmp_dc->used = TRUE;
  10591         }
  10592     }
  10593 
  10594     if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_BKT) {
  10595         if (found == 0) {
  10596             PRINT_VRF_NOT_FOUND(u);
  10597         }
  10598     }
  10599 
  10600     sal_memset(&all_dc, 0, sizeof(all_dc));
  10601     found = 0;
  10602 
  10603     if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_BKTUSG) {
  10604         LOG_CLI((BSL_META_U(u,
  10605                             "\nBucket Usage:\n")));
  10606         PRINT_VRF_HEADER(u);
  10607         PRINT_SPLIT_LINE(u);
  10608         for (i = 0; i < MAX_VRF_ID; i++) {
  10609             _alpm_dbg_cnt_t *tmp_dc;
  10610             if (alpm_dc_arr[i].used != TRUE) {
  10611                 continue;
  10612             }
  10613             if (vrf_id != -1 && vrf_id != i) {
  10614                 continue;
  10615             }
  10616 
  10617             found = 1;
  10618             tmp_dc = &alpm_dc_arr[i];
  10619             _ALPM_DBG_CNT_ADD(&all_dc, tmp_dc);
  10620             PRINT_BKT_OCCU_ITEM(u, i, tmp_dc);
  10621         }
  10622         if (found == 0) {
  10623             PRINT_VRF_NOT_FOUND(u);
  10624         } else {
  10625             PRINT_SPLIT_LINE(u);
  10626             PRINT_BKT_OCCU_ITEM_TOT(u, &all_dc);
  10627         }
  10628     }
  10629 
  10630     /* 2. Pivot Occupancy */
  10631     if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_PVT) {
  10632         _soc_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 
  10633                                            SOC_ALPM_DEBUG_CNT_USED);
  10634     }
  10635 
  10636     /* 3. Add/Delete counters per VRF/ip type */
  10637     if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_CNT) {
  10638         _soc_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 
  10639                                    SOC_ALPM_DEBUG_CNT_ADD);
  10640         
  10641         _soc_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 
  10642                                    SOC_ALPM_DEBUG_CNT_DEL);
  10643     }
  10644 
  10645     /* 4. Total No. of bucket splits per VRF/ip type */
  10646     if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_INTDBG) {
  10647         _soc_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 
  10648                                    SOC_ALPM_DEBUG_CNT_SPLIT);
  10649         _soc_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 
  10650                                    SOC_ALPM_DEBUG_CNT_LPM_FULL);
  10651         _soc_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 
  10652                                    SOC_ALPM_DEBUG_CNT_LPM_SHIFT);        
  10653     }
  10654 
  10655     sal_free(alpm_dc_arr);
  10656     
  10657     return SOC_E_NONE;
  10658 }
  10659 
  10660 void
  10661 soc_alpm_debug_cntr_show(int u)
  10662 {
  10663     LOG_CLI(("====ALPM=Internal=Debug=Counter====\n"));
  10664     LOG_CLI(("%-24s%d\n", "Bucket Split:", soc_alpm_dbg_cnt[u].bkt_split));
  10665     LOG_CLI(("%-24s%d\n", "Bucket Merge:", soc_alpm_dbg_cnt[u].bkt_merge));
  10666     LOG_CLI(("%-24s%d\n", "Bucket MergeDuringRp:", soc_alpm_dbg_cnt[u].bkt_merge2));
  10667     LOG_CLI(("%-24s%d\n", "Bucket Repartition:", soc_alpm_dbg_cnt[u].bkt_repart));
  10668     LOG_CLI(("%-24s%d\n", "Propagation Insert CB:",
  10669             soc_alpm_dbg_cnt[u].ppg_cb_insert));
  10670     LOG_CLI(("%-24s%d\n", "Propagation Delete CB:",
  10671             soc_alpm_dbg_cnt[u].ppg_cb_delete));
  10672 }
  10673 
  10674 int
  10675 soc_alpm_debug_brief_show(int u, int phy_bkt, int index)
  10676 {
  10677     int i = 0, j = 0, rv = SOC_E_NONE;
  10678     uint32 rval = 0, alpm = 0, mode = 0;
  10679     uint32 urpf = 0, bit128 = 0, fv = 0, bnkbits = 0xf;
  10680     int v4used = 0, v4max = 0;
  10681     int v6_64used = 0, v6_64max = 0;
  10682     int v6_128used = 0, v6_128max = 0;
  10683     int bucket_used = 0, bucket_max = 0;
  10684     char *lpm_tbl_ptr = NULL;
  10685     defip_entry_t *lpm_entry = NULL;
  10686     defip_pair_128_entry_t *lpm_entry_p128 = NULL;
  10687     int ipv6, bkt_ptr, gh, gr, use_alpm;
  10688     int *bktref = NULL;
  10689     int glb_hi_cnt = 0, glb_lo_cnt = 0;
  10690     soc_mem_t lpm_mem;
  10691     int alloc_size = 0;
  10692     uint32 e[SOC_MAX_MEM_FIELD_WORDS];
  10693     soc_field_t fldv, fldb, fldg, fldr;
  10694     int alpm_bkt_bits = SOC_ALPM_BUCKET_BITS(u);
  10695 
  10696     char *mode_str[] = {
  10697         "LPM",
  10698         "ALPM-Combined",
  10699         "ALPM-Parallel",
  10700         "ALPM-Invalid",
  10701         "ALPM-Invalid"
  10702     };
  10703 
  10704     SOC_IF_ERROR_RETURN(READ_L3_DEFIP_RPF_CONTROLr(u, &rval));
  10705     alpm = soc_reg_field_get(u, L3_DEFIP_RPF_CONTROLr, rval, LPM_MODEf);
  10706     if (alpm != 0) {
  10707         mode = soc_reg_field_get(u, L3_DEFIP_RPF_CONTROLr, rval, LOOKUP_MODEf);
  10708     }
  10709     urpf = soc_reg_field_get(u, L3_DEFIP_RPF_CONTROLr, rval, DEFIP_RPF_ENABLEf);
  10710 
  10711     LOG_CLI(("\n"));
  10712     LOG_CLI(("%-24s%s\n", "Mode:", mode_str[alpm + mode]));
  10713     LOG_CLI(("%-24s%s\n", "uRPF:", urpf ? "Enable" : "Disable"));
  10714     bit128 = !!soc_mem_index_count(u, L3_DEFIP_PAIR_128m);
  10715     LOG_CLI(("%-24s%d\n", "IPv6 Bits:", bit128 ? 128 : 64));
  10716 
  10717     if (alpm == 0) {
  10718         return SOC_E_NONE;
  10719     }
  10720     LOG_CLI(("%-24s%s\n", "IPv4 Wide:", "Single"));
  10721 
  10722     if (mode == 0 && !urpf) {
  10723         fv = 1;
  10724     } else {
  10725         fv = 0;
  10726     }
  10727     LOG_CLI(("%-24s%s\n", "IPv6 Wide:", fv ? "Double" : "Single"));
  10728 
  10729     LOG_CLI(("%-24s%d\n", "Banks:", 4));
  10730 
  10731     /* Calculate utilization */
  10732     v4max = 2 * soc_mem_index_count(u, L3_DEFIPm);
  10733     v6_64max = bit128 ? soc_mem_index_count(u, L3_DEFIP_PAIR_128m) :
  10734                         soc_mem_index_count(u, L3_DEFIPm);
  10735     v6_128max = soc_mem_index_count(u, L3_DEFIP_PAIR_128m);
  10736     bucket_max = SOC_TD2_ALPM_MAX_BKTS;
  10737     if (urpf) {
  10738         v4max       >>= 1;
  10739         v6_64max    >>= 1;
  10740         v6_128max   >>= 1;
  10741         bucket_max  >>= 1;
  10742     }
  10743 
  10744     bktref = sal_alloc(bucket_max * sizeof(int), "bktref");
  10745     if (bktref == NULL) {
  10746         return SOC_E_MEMORY;
  10747     }
  10748     sal_memset(bktref, 0, bucket_max * sizeof(int));
  10749 
  10750     /* DMA LPM table to software copy */
  10751     lpm_mem = L3_DEFIPm;
  10752     alloc_size = WORDS2BYTES(soc_mem_entry_words(u, lpm_mem)) *
  10753                  soc_mem_index_count(u, lpm_mem);
  10754     lpm_tbl_ptr = soc_cm_salloc(u, alloc_size, "lpm_tbl");
  10755     if (lpm_tbl_ptr == NULL) {
  10756         rv = SOC_E_MEMORY;
  10757         goto _free_mem;
  10758     }
  10759     /* Reset allocated buffer. */
  10760     sal_memset(lpm_tbl_ptr, 0, alloc_size);
  10761 
  10762     /* Read table to the buffer. */
  10763     if (v4max && soc_mem_read_range(u, lpm_mem, MEM_BLOCK_ANY,
  10764                            soc_mem_index_min(u, lpm_mem),
  10765                            soc_mem_index_max(u, lpm_mem), lpm_tbl_ptr) < 0) {
  10766         rv = (SOC_E_INTERNAL);
  10767         goto _free_mem;
  10768     }
  10769 
  10770     for (i = 0; i < (v4max / 2); i++) {
  10771         /* Calculate entry offset */
  10772         lpm_entry =
  10773             soc_mem_table_idx_to_pointer(u, lpm_mem,
  10774                                          defip_entry_t *, lpm_tbl_ptr, i);
  10775         ipv6 = soc_mem_field32_get(u, lpm_mem, lpm_entry, MODE0f);
  10776 
  10777         for (j = 0; j < (ipv6 ? 1 : 2); j++) {
  10778             if (j == 1) {
  10779                 fldv = VALID1f;
  10780             } else {
  10781                 fldv = VALID0f;
  10782             }
  10783             /* Make sure entry is valid. */
  10784             if (!soc_mem_field32_get(u, lpm_mem, lpm_entry, fldv)) {
  10785                 continue;
  10786             }
  10787 
  10788             if (ipv6) {
  10789                 v6_64used++;
  10790             } else {
  10791                 v4used++;
  10792             }
  10793 
  10794             if (j == 0) {
  10795                 fldg = GLOBAL_HIGH0f;
  10796                 fldb = ALG_BKT_PTR0f;
  10797                 fldr = GLOBAL_ROUTE0f;
  10798             } else {
  10799                 fldg = GLOBAL_HIGH1f;
  10800                 fldb = ALG_BKT_PTR1f;
  10801                 fldr = GLOBAL_ROUTE1f;
  10802             }
  10803 
  10804             gh = soc_mem_field32_get(u, lpm_mem, lpm_entry, fldg);
  10805             gr = soc_mem_field32_get(u, lpm_mem, lpm_entry, fldr);
  10806             if (gr) {
  10807                 if (gh) {
  10808                     glb_hi_cnt++;
  10809                     use_alpm = 0;
  10810                 } else {
  10811                     glb_lo_cnt++;
  10812                     use_alpm = 1;
  10813                 }
  10814             } else {
  10815                 use_alpm = 1;
  10816             }
  10817 
  10818             if (use_alpm) {
  10819                 bkt_ptr = soc_mem_field32_get(u, lpm_mem, lpm_entry, fldb);
  10820                 if (bkt_ptr > bucket_max) {
  10821                     LOG_CLI(("Invalid phy_bkt pointer in %s index %d\n",
  10822                              SOC_MEM_NAME(u, lpm_mem), i));
  10823                 } else {
  10824                     if (bktref[bkt_ptr]) {
  10825                         LOG_CLI(("Invalid bucket sharing in %s index %d\n",
  10826                                  SOC_MEM_NAME(u, lpm_mem), i));
  10827                     } else {
  10828                         bktref[bkt_ptr]++;
  10829                         bucket_used++;
  10830                     }
  10831                 }
  10832             }
  10833         }
  10834     }
  10835 
  10836     soc_cm_sfree(u, lpm_tbl_ptr);
  10837 
  10838     /* l3_defip_pair_128 */
  10839     lpm_tbl_ptr = NULL;
  10840     lpm_mem = L3_DEFIP_PAIR_128m;
  10841     alloc_size = WORDS2BYTES(soc_mem_entry_words(u, lpm_mem)) *
  10842                  soc_mem_index_count(u, lpm_mem);
  10843     lpm_tbl_ptr = soc_cm_salloc(u, alloc_size, "lpm_tbl_p128");
  10844     if (lpm_tbl_ptr == NULL) {
  10845         rv = SOC_E_MEMORY;
  10846         goto _free_mem;
  10847     }
  10848     /* Reset allocated buffer. */
  10849     sal_memset(lpm_tbl_ptr, 0, alloc_size);
  10850 
  10851     /* Read table to the buffer. */
  10852     if (v6_128max && soc_mem_read_range(u, lpm_mem, MEM_BLOCK_ANY,
  10853                            soc_mem_index_min(u, lpm_mem),
  10854                            soc_mem_index_max(u, lpm_mem), lpm_tbl_ptr) < 0) {
  10855         rv = (SOC_E_INTERNAL);
  10856         goto _free_mem;
  10857     }
  10858 
  10859     for (i = 0; i < v6_128max; i++) {
  10860         /* Calculate entry offset */
  10861         lpm_entry_p128 =
  10862             soc_mem_table_idx_to_pointer(u, lpm_mem,
  10863                                 defip_pair_128_entry_t *, lpm_tbl_ptr, i);
  10864         /* Verify if read LPM entry is IPv6-128 entry */
  10865         if (0x03 != soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, MODE1_UPRf)) {
  10866             continue;
  10867         };
  10868 
  10869         /* Verify if LPM entry is valid */
  10870         if (!soc_mem_field32_get(u, lpm_mem, lpm_entry_p128,
  10871                                     VALID1_LWRf) ||
  10872             !soc_mem_field32_get(u, lpm_mem, lpm_entry_p128,
  10873                                     VALID0_LWRf) ||
  10874             !soc_mem_field32_get(u, lpm_mem, lpm_entry_p128,
  10875                                     VALID1_UPRf) ||
  10876             !soc_mem_field32_get(u, lpm_mem, lpm_entry_p128,
  10877                                     VALID0_UPRf)) {
  10878             continue;
  10879         };
  10880 
  10881         v6_128used++;
  10882 
  10883         gh = soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, GLOBAL_HIGHf);
  10884         gr = soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, GLOBAL_ROUTEf);
  10885         if (gr) {
  10886             if (gh) {
  10887                 glb_hi_cnt++;
  10888                 use_alpm = 0;
  10889             } else {
  10890                 glb_lo_cnt++;
  10891                 use_alpm = 1;
  10892             }
  10893         } else {
  10894             use_alpm = 1;
  10895         }
  10896 
  10897         if (use_alpm) {
  10898             bkt_ptr = soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, ALG_BKT_PTRf);
  10899             if (bkt_ptr > bucket_max) {
  10900                 LOG_CLI(("Invalid phy_bkt pointer in %s index %d\n",
  10901                          SOC_MEM_NAME(u, lpm_mem), i));
  10902             } else {
  10903                 if (bktref[bkt_ptr]) {
  10904                     LOG_CLI(("Invalid bucket sharing in %s index %d\n",
  10905                              SOC_MEM_NAME(u, lpm_mem), i));
  10906                 } else {
  10907                     bktref[bkt_ptr]++;
  10908                     bucket_used++;
  10909                 }
  10910             }
  10911         }
  10912     }
  10913 
  10914     LOG_CLI(("\n"));
  10915     LOG_CLI(("%-24s%d/%-4d\n", "IPv4 Pivots:", v4used, v4max));
  10916     LOG_CLI(("%-24s%d/%-4d\n", "IPv6-64 Pivots:", v6_64used, v6_64max));
  10917     LOG_CLI(("%-24s%d/%-4d\n", "IPv6-128 Pivots:", v6_128used, v6_128max));
  10918     LOG_CLI(("%-24s%d/%-4d\n", "Buckets:", bucket_used, bucket_max));
  10919     LOG_CLI(("%-24s%d\n", "Global High:", glb_hi_cnt));
  10920     LOG_CLI(("%-24s%d\n", "Global Low:", glb_lo_cnt));
  10921     LOG_CLI(("\n"));
  10922     soc_alpm_debug_cntr_show(u);
  10923     LOG_CLI(("\n\n"));
  10924 
  10925 _free_mem:
  10926     if (bktref) {
  10927         sal_free(bktref);
  10928         bktref = NULL;
  10929     }
  10930 
  10931     if (lpm_tbl_ptr) {
  10932         soc_cm_sfree(u, lpm_tbl_ptr);
  10933         lpm_tbl_ptr = NULL;
  10934     }
  10935 
  10936     if (phy_bkt != -1) {
  10937         int bank, entmax, tmp;
  10938 
  10939         lpm_mem = _soc_trident2_alpm_bkt_view_get(u, phy_bkt << 2);
  10940         LOG_CLI(("Bucket = %4d (View %s)\n", phy_bkt, lpm_mem == -1 ? "INVALID" :
  10941                 SOC_MEM_NAME(u, lpm_mem)));
  10942         LOG_CLI(("------------------------------------------------------------\n"));
  10943         LOG_CLI(("Index distribution (* indicates occupied)\n"));
  10944 
  10945         switch (lpm_mem) {
  10946         case L3_DEFIP_ALPM_IPV4m:
  10947             entmax = 6;
  10948             break;
  10949         case L3_DEFIP_ALPM_IPV4_1m:
  10950             entmax = 4;
  10951             break;
  10952         case L3_DEFIP_ALPM_IPV6_64m:
  10953             entmax = 4;
  10954             break;
  10955         case L3_DEFIP_ALPM_IPV6_64_1m:
  10956             entmax = 3;
  10957             break;
  10958         case L3_DEFIP_ALPM_IPV6_128m:
  10959             entmax = 2;
  10960             break;
  10961         default:
  10962             lpm_mem = L3_DEFIP_ALPM_IPV4m;
  10963             entmax = 6;
  10964             break;
  10965         }
  10966 
  10967         for (bank = 0; bank < 4; bank++) {
  10968             if (!(bnkbits & (1 << bank))) {
  10969                 continue;
  10970             }
  10971 
  10972             LOG_CLI(("Bank%d: ", bank));
  10973             for (i = 0; i < entmax; i++) {
  10974                 int rv1;
  10975                 tmp = (_shr_popcount(bnkbits) + 1) / 2;
  10976                 j = (i << (tmp + alpm_bkt_bits)) |
  10977                     (phy_bkt << tmp) | bank;
  10978                 rv1 = _soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY, j, e);
  10979                 if (rv1 == 0 &&
  10980                     soc_mem_field32_get(u, lpm_mem, e, VALIDf)) {
  10981                     tmp = 1;
  10982                 } else {
  10983                     tmp = 0;
  10984                 }
  10985                 if (tmp) {
  10986                     LOG_CLI(("%d(*) ", j));
  10987                 } else {
  10988                     LOG_CLI(("%d( ) ", j));
  10989                 }
  10990             }
  10991             LOG_CLI(("\n"));
  10992         }
  10993     }
  10994 
  10995     LOG_CLI(("\n"));
  10996     if (index != -1) {
  10997         int log_bkt;
  10998         LOG_CLI(("Index = %8d\n", index));
  10999         LOG_CLI(("------------------------------------------------------------\n"));
  11000         lpm_mem = _soc_trident2_alpm_bkt_view_get(u, index);
  11001         LOG_CLI(("%-24s%s\n", "Type", lpm_mem == -1 ? "INVALID" :
  11002                 SOC_MEM_NAME(u, lpm_mem)));
  11003         LOG_CLI(("%-24s%d\n", "Bucket:", (index >> 2) & 0x3fff));
  11004         LOG_CLI(("%-24s%d\n", "Bank:", index & (_shr_popcount(bnkbits) - 1)));
  11005         log_bkt = (_shr_popcount(bnkbits) + 1) / 2 + alpm_bkt_bits;
  11006         LOG_CLI(("%-24s%d\n", "Entry:", index >> log_bkt));
  11007         LOG_CLI(("\n"));
  11008     }
  11009 
  11010     return rv;
  11011 }
  11012 
  11013 /*
  11014  * Function:
  11015  *     soc_alpm_lpm_sw_dump
  11016  * Purpose:
  11017  *     Displays FB LPM information maintained by software.
  11018  * Parameters:
  11019  *     unit - Device unit number
  11020  * Returns:
  11021  *     None
  11022  */
  11023 void
  11024 soc_alpm_lpm_sw_dump(int unit)
  11025 {
  11026     soc_alpm_lpm_state_p  lpm_state;
  11027     int                   i, j;
  11028     alpm_pivot_t          *pivot_pyld = NULL;
  11029     _soc_alpm_lpm_hash_t  *hash;
  11030     int idx;
  11031 
  11032     /* Dump v4/v6 lpm state */
  11033     LOG_CLI((BSL_META_U(unit, "V4 LPM STATE DUMP.\n")));
  11034     lpm_state = soc_alpm_lpm_state[unit];
  11035 
  11036     if (lpm_state != NULL) {
  11037         for (i = 0; i < ALPM_MAX_PFX_ENTRIES; i++) {
  11038             if (lpm_state[i].vent != 0) {
  11039                 LOG_CLI((BSL_META_U(unit, "Prefix %d\n"), i));
  11040                 LOG_CLI((BSL_META_U(unit, "  Start : %d\n"), lpm_state[i].start));
  11041                 LOG_CLI((BSL_META_U(unit, "  End   : %d\n"), lpm_state[i].end));
  11042                 LOG_CLI((BSL_META_U(unit, "  Prev  : %d\n"), lpm_state[i].prev));
  11043                 LOG_CLI((BSL_META_U(unit, "  Next  : %d\n"), lpm_state[i].next));
  11044                 LOG_CLI((BSL_META_U(unit, "  Valid : %d\n"), lpm_state[i].vent));
  11045                 LOG_CLI((BSL_META_U(unit, "  Free  : %d\n"), lpm_state[i].fent));
  11046             }
  11047         }
  11048     }
  11049     LOG_CLI((BSL_META_U(unit, "V4 LPM STATE DUMP DONE.\n\n")));
  11050 
  11051     /* Dump LPM HASH table */
  11052     LOG_CLI((BSL_META_U(unit, "LPM HASH TABLE DUMP.\n")));
  11053     hash = SOC_ALPM_LPM_STATE_HASH(unit);
  11054     for(idx = 0; idx < hash->index_count; idx++) {
  11055         j = 0;
  11056         if (hash->table[idx] != TD2_ALPM_HASH_INDEX_NULL) {
  11057             LOG_CLI((
  11058                 BSL_META_U(unit, "\nhash_idx = 0x%04x Data = 0x%04x"),
  11059                 idx, hash->table[idx]));
  11060         }
  11061         i = hash->table[idx];
  11062         while ((i != TD2_ALPM_HASH_INDEX_NULL) && (j++ < hash->entry_count)) {
  11063             if ((j - 1) % 8 == 0) {
  11064                 LOG_CLI((BSL_META_U(unit, "\nlink_idx =")));
  11065             }
  11066             LOG_CLI((BSL_META_U(unit, " 0x%04x"), i));
  11067             i = hash->link_table[i & TD2_ALPM_HASH_INDEX_MASK];
  11068         }
  11069     }
  11070     LOG_CLI((BSL_META_U(unit, "\nLPM HASH TABLE DUMP DONE.\n\n")));
  11071 
  11072     /* Dump TCAM pivot table */
  11073     LOG_CLI((BSL_META_U(unit, "TCAM PIVOT DUMP.\n")));
  11074     for(idx = 0; idx < MAX_PIVOT_COUNT; idx++) {
  11075         /* Get TCAM pivot */
  11076         pivot_pyld = ALPM_TCAM_PIVOT(unit, idx);
  11077         if (NULL == pivot_pyld) {
  11078             continue;
  11079         }
  11080         if (PIVOT_BUCKET_HANDLE(pivot_pyld) == NULL) {
  11081             continue;
  11082         }
  11083 
  11084         /* Get bucket trie from pivot */
  11085         LOG_CLI((
  11086             BSL_META_U(unit, "tcam_idex = 0x%04x\n"), pivot_pyld->tcam_index));
  11087         LOG_CLI((BSL_META_U(unit, "  len = 0x%02x\t"), pivot_pyld->len));
  11088         LOG_CLI((BSL_META_U(unit, "bpm_len = 0x%02x\t"), pivot_pyld->bpm_len));
  11089         LOG_CLI((
  11090             BSL_META_U(unit, "bkt_idx = 0x%04x\n"),
  11091             PIVOT_BUCKET_INDEX(pivot_pyld)));
  11092         LOG_CLI((
  11093             BSL_META_U(unit, "  vrf = 0x%04x\t"), PIVOT_BUCKET_VRF(pivot_pyld)));
  11094         LOG_CLI((
  11095             BSL_META_U(unit, "v6 = 0x%x\t"), PIVOT_BUCKET_IPV6(pivot_pyld)));
  11096         LOG_CLI((BSL_META_U(unit, "Key : {")));
  11097         if (pivot_pyld->len < 32) {
  11098             LOG_CLI((
  11099                 BSL_META_U(unit, "0x%x/%d"),
  11100                 pivot_pyld->key[0], pivot_pyld->len));
  11101         } else {
  11102             for (i=0; i < (((pivot_pyld->len)/32) + 1); i++)
  11103                 LOG_CLI((BSL_META_U(unit, " 0x%x"), pivot_pyld->key[i]));
  11104                 LOG_CLI((BSL_META_U(unit, "/%d"), pivot_pyld->len));
  11105         }
  11106         LOG_CLI((BSL_META_U(unit, "}\n")));
  11107     }
  11108     LOG_CLI((BSL_META_U(unit, "TCAM PIVOT DUMP DONE.\n\n")));
  11109 
  11110     /* Print VRF count/default route infomation */
  11111     LOG_CLI((BSL_META_U(unit, "VRF ROUTE DUMP.\n")));
  11112     for (idx = 0; idx < (SOC_VRF_MAX(unit) + 2); idx++) {
  11113        if (alpm_vrf_handle[unit][idx].count_v4 != 0) {
  11114            LOG_CLI((
  11115                BSL_META_U(unit, "V4-32 VRF = %d, Routes = %d Default Route:\n"),
  11116                idx, alpm_vrf_handle[unit][idx].count_v4));
  11117            if (VRF_TRIE_DEFAULT_ROUTE_IPV4(unit, idx)) {
  11118                soc_mem_entry_dump(unit, L3_DEFIPm,
  11119                                   VRF_TRIE_DEFAULT_ROUTE_IPV4(unit, idx),
  11120                                   BSL_LSS_CLI);
  11121            }
  11122        }
  11123 
  11124        if (alpm_vrf_handle[unit][idx].count_v6_64 !=0) {
  11125            LOG_CLI((
  11126                BSL_META_U(unit, "V6-64 VRF = %d, Routes = %d Default Route:\n"),
  11127                idx, alpm_vrf_handle[unit][idx].count_v6_64));
  11128            if (VRF_TRIE_DEFAULT_ROUTE_IPV6(unit, idx)) {
  11129                soc_mem_entry_dump(unit, L3_DEFIPm,
  11130                                   VRF_TRIE_DEFAULT_ROUTE_IPV6(unit, idx),
  11131                                   BSL_LSS_CLI);
  11132            }
  11133        }
  11134 
  11135        if (alpm_vrf_handle[unit][idx].count_v6_128 != 0) {
  11136            LOG_CLI((
  11137                BSL_META_U(unit, "V6-128 VRF = %d, Routes = %d Default Route:\n"),
  11138                idx, alpm_vrf_handle[unit][idx].count_v6_128));
  11139            if (VRF_TRIE_DEFAULT_ROUTE_IPV6_128(unit, idx)) {
  11140                soc_mem_entry_dump(unit, L3_DEFIP_PAIR_128m,
  11141                                   VRF_TRIE_DEFAULT_ROUTE_IPV6_128(unit, idx),
  11142                                   BSL_LSS_CLI);
  11143            }
  11144        }
  11145     }
  11146     LOG_CLI((BSL_META_U(unit, "VRF ROUTE DUMP DONE.\n")));
  11147 
  11148     return;
  11149 }
  11150 
  11151 /*
  11152  * Function:
  11153  *     soc_alpm_bucket_sw_dump
  11154  * Purpose:
  11155  *     Displays ALPM bucket information maintained by software.
  11156  * Parameters:
  11157  *     unit - Device unit number
  11158  * Returns:
  11159  *     None
  11160  */
  11161 void
  11162 soc_alpm_bucket_sw_dump(int unit)
  11163 {
  11164     int                 i = 0, bkt= 0, used = 0;
  11165     soc_mem_t           lpm_mem;
  11166 
  11167     LOG_CLI((BSL_META_U(unit, "\n")));
  11168 
  11169     LOG_CLI((BSL_META_U(unit,
  11170             "=================================================\n")));
  11171     LOG_CLI((BSL_META_U(unit,
  11172             "  %s[%s]\n"), "VRF Route bucket idx", "mem_view"));
  11173     LOG_CLI((BSL_META_U(unit,
  11174             "=================================================\n")));
  11175 
  11176     for (i = 0; i < SOC_ALPM_BUCKET_COUNT(unit); i++) {
  11177         SHR_BITTEST_RANGE(SOC_ALPM_BUCKET_BMAP(unit), i, 1, used);
  11178         if (0 != used) {
  11179             lpm_mem = _soc_trident2_alpm_bkt_view_get(unit, i << 2);
  11180 
  11181             LOG_CLI((
  11182                 BSL_META_U(unit, "  0x%04x[%24s]\n"),
  11183                 i, lpm_mem == -1 ? "INVALID" : SOC_MEM_NAME(unit, lpm_mem)));
  11184             bkt++;
  11185         }
  11186     }
  11187 
  11188     if (bkt == 0) {
  11189         LOG_CLI((BSL_META_U(unit, "- None -\n")));
  11190     }
  11191 
  11192     return;
  11193 }
  11194 
  11195 
  11196 #ifndef BCM_SW_STATE_DUMP_DISABLE
  11197 /*
  11198  * Function:
  11199  *     soc_alpm_sw_dump
  11200  * Purpose:
  11201  *     Displays ALPM state maintained by software.
  11202  * Parameters:
  11203  *     unit - Device unit number
  11204  * Returns:
  11205  *     None
  11206  */
  11207 void
  11208 soc_alpm_sw_dump(int unit)
  11209 {
  11210     LOG_CLI((BSL_META_U(unit, "\n  ALPM Info -\n")));
  11211 
  11212     soc_alpm_lpm_sw_dump(unit);
  11213 
  11214     soc_alpm_bucket_sw_dump(unit);
  11215 
  11216     return;
  11217 }
  11218 #endif /* BCM_SW_STATE_DUMP_DISABLE */
  11219 
  11220 /*
  11221  * Function:
  11222  *      _soc_alpm_sanity_check
  11223  * Purpose:
  11224  *      Sanity check for ALPM with L3_DEFIP
  11225  * Parameters:
  11226  *      u           - Device unit
  11227  *      min         - Min index of L3_DEFIP
  11228  *      max         - Max index of L3_DEFIP
  11229  *      check_sw    - Check software
  11230  *      bkt_ptr_arr - bucket ptr array
  11231  * Returns:
  11232  *      SOC_E_XXX defined in error.h
  11233  */
  11234 STATIC int
  11235 _soc_alpm_sanity_check(int u, int min, int max, int check_sw, int *bkt_ptr_arr)
  11236 {
  11237     int             rv = SOC_E_NONE;
  11238     int             lpm_idx, lpm_idx2, fd_lpm_idx2, alpm_idx, prev_idx = 0;
  11239     int             i, j, ipv6, prev_v6 = 0, prev_i = 0;
  11240     int             vrf_id, vrf;
  11241     int             fd_lpm_idx, fd_bkt_ptr, fd_alpm_idx;
  11242     int             ent, ent_num, bkt_ptr;
  11243     int             error1 = 0, error2 = 0, error = 0, success = 0;
  11244     int             used;
  11245     int             bpm_len, ip_len;
  11246     int             trie_bpm_len, default_route;
  11247     int             alloc_size;
  11248     uint32          bank_disable = 0;
  11249     uint32          e[SOC_MAX_MEM_FIELD_WORDS] = {0};
  11250     uint32          shadow[SOC_MAX_MEM_FIELD_WORDS] = {0};
  11251     uint32          prefix[5], length;
  11252     trie_t          *pfx_trie  = NULL;
  11253     trie_node_t     *lpmp      = NULL;
  11254     payload_t       *tmp_pyld  = NULL;
  11255     uint32          data0[10] = {0};
  11256     uint32          data1[10] = {0};
  11257     char            *buffer = NULL;
  11258     defip_entry_t   *lpm_entry, lpm_entry2, lpm_bmp;
  11259     soc_mem_t       bkt_mem_type;
  11260     soc_mem_t       alpm_mem;
  11261     int             flex;
  11262     int             bpm_check = 0;
  11263     int             flex_v6_64;
  11264 
  11265     /* Calculate table size. */
  11266     alloc_size = sizeof(defip_entry_t) * (max - min + 1);
  11267 
  11268     /* Allocate memory buffer. */
  11269     buffer = soc_cm_salloc(u, alloc_size, "lpm_tbl");
  11270     if (buffer == NULL) {
  11271         return (SOC_E_MEMORY);
  11272     }
  11273 
  11274     /* Reset allocated buffer. */
  11275     sal_memset(buffer, 0, alloc_size);
  11276 
  11277     SOC_ALPM_LPM_LOCK(u);
  11278 
  11279     /* Read table to the buffer. */
  11280     if (soc_mem_read_range(u, L3_DEFIPm, MEM_BLOCK_ANY,
  11281                            min, max, buffer) < 0) {
  11282         soc_cm_sfree(u, buffer);
  11283         SOC_ALPM_LPM_UNLOCK(u);
  11284         return (SOC_E_INTERNAL);
  11285     }
  11286 
  11287     for (lpm_idx = min; lpm_idx <= max; lpm_idx++) {
  11288         lpm_entry = soc_mem_table_idx_to_pointer(u, L3_DEFIPm,
  11289                                                  defip_entry_t *, buffer,
  11290                                                  lpm_idx - min);
  11291 
  11292         ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, MODE0f);
  11293 
  11294         for (i = 0; i <= (ipv6 ? 0 : 1); i++) {
  11295             if (error1) {
  11296                 LOG_ERROR(BSL_LS_SOC_ALPM,
  11297                           (BSL_META_U(u,
  11298                           "\tL3_DEFIP index:[%d,%d] check failed. ipv6 %d error count %d\n"),
  11299                           prev_idx, prev_i, prev_v6, error1));
  11300                 error = 1;
  11301             } else if (success) {
  11302                 LOG_INFO(BSL_LS_SOC_ALPM,(BSL_META_U(u,
  11303                         "\tL3_DEFIP index:[%d,%d] check passed. ipv6 %d success count %d\n"),
  11304                          prev_idx, prev_i, prev_v6, success));
  11305             }
  11306             error1 = error2 = success = 0;
  11307             prev_v6  = ipv6;
  11308             prev_idx = lpm_idx;
  11309             prev_i   = i;
  11310 
  11311             /* cache coherency check */
  11312             if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, VALID0f) ||
  11313                 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, VALID1f)) {
  11314                 defip_entry_t hw_ent, sw_ent;
  11315                 soc_mem_t cmem = L3_DEFIPm;
  11316                 sal_memset(&hw_ent, 0, sizeof(hw_ent));
  11317                 sal_memset(&sw_ent, 0, sizeof(sw_ent));
  11318                 rv = _soc_mem_alpm_read_cache(u, cmem, SOC_BLOCK_ANY,
  11319                                               lpm_idx, &sw_ent);
  11320                 if (SOC_SUCCESS(rv)) {
  11321                     rv = soc_mem_read_no_cache(u, 0, cmem, 0, SOC_BLOCK_ANY,
  11322                                                lpm_idx, &hw_ent);
  11323                     if (SOC_SUCCESS(rv)) {
  11324                         if (soc_mem_field_valid(u, cmem, EVEN_PARITYf)) {
  11325                             soc_mem_field32_set(u, cmem, &hw_ent,
  11326                                                 EVEN_PARITYf, 0);
  11327                             soc_mem_field32_set(u, cmem, &sw_ent,
  11328                                                 EVEN_PARITYf, 0);
  11329                         } else if (soc_mem_field_valid(u, cmem, PARITY0f)) {
  11330                             soc_mem_field32_set(u, cmem, &hw_ent, PARITY0f, 0);
  11331                             soc_mem_field32_set(u, cmem, &sw_ent, PARITY0f, 0);
  11332                             soc_mem_field32_set(u, cmem, &hw_ent, PARITY1f, 0);
  11333                             soc_mem_field32_set(u, cmem, &sw_ent, PARITY1f, 0);
  11334                         }
  11335                         soc_mem_field32_set(u, cmem, &hw_ent, HIT0f, 0);
  11336                         soc_mem_field32_set(u, cmem, &sw_ent, HIT0f, 0);
  11337                         soc_mem_field32_set(u, cmem, &hw_ent, HIT1f, 0);
  11338                         soc_mem_field32_set(u, cmem, &sw_ent, HIT1f, 0);
  11339                         if (sal_memcmp(&sw_ent, &hw_ent,
  11340                                        soc_mem_entry_bytes(u, cmem)) != 0) {
  11341                             LOG_ERROR(BSL_LS_SOC_ALPM,
  11342                                 (BSL_META_U(u, "\t%s index:[%d], ipv6(%d)"
  11343                                 " cache mismatch\n"), SOC_MEM_NAME(u, cmem),
  11344                                 lpm_idx, ipv6));
  11345                             error1 ++;
  11346                         }
  11347                     }
  11348                 }
  11349 
  11350                 /* We can just use defip_entry_t because it's always longer
  11351                  * than aux_entry_t */
  11352                 cmem = L3_DEFIP_AUX_TABLEm;
  11353                 sal_memset(&hw_ent, 0, sizeof(hw_ent));
  11354                 sal_memset(&sw_ent, 0, sizeof(sw_ent));
  11355                 lpm_idx2 = soc_alpm_physical_idx(u, L3_DEFIPm, lpm_idx, 1);
  11356                 rv = _soc_mem_alpm_read_cache(u, cmem, SOC_BLOCK_ANY,
  11357                                               lpm_idx2, &sw_ent);
  11358                 if (SOC_SUCCESS(rv)) {
  11359                     rv = soc_mem_read_no_cache(u, 0, cmem, 0, SOC_BLOCK_ANY,
  11360                                                lpm_idx2, &hw_ent);
  11361                     if (SOC_SUCCESS(rv)) {
  11362                         if (soc_mem_field_valid(u, cmem, EVEN_PARITYf)) {
  11363                             soc_mem_field32_set(u, cmem, &hw_ent,
  11364                                                 EVEN_PARITYf, 0);
  11365                             soc_mem_field32_set(u, cmem, &sw_ent,
  11366                                                 EVEN_PARITYf, 0);
  11367                         } else if (soc_mem_field_valid(u, cmem, PARITYf)) {
  11368                             soc_mem_field32_set(u, cmem, &hw_ent, PARITYf, 0);
  11369                             soc_mem_field32_set(u, cmem, &sw_ent, PARITYf, 0);
  11370                         }
  11371                         if (sal_memcmp(&sw_ent, &hw_ent,
  11372                                        soc_mem_entry_bytes(u, cmem)) != 0) {
  11373                             LOG_ERROR(BSL_LS_SOC_ALPM,
  11374                                 (BSL_META_U(u, "\t%s index:[%d], ipv6(%d)"
  11375                                 " cache mismatch\n"), SOC_MEM_NAME(u, cmem),
  11376                                 lpm_idx2, ipv6));
  11377                             error1 ++;
  11378                         }
  11379                     }
  11380                 }
  11381             }
  11382 
  11383             if (i == 1) {
  11384                 soc_alpm_lpm_ip4entry1_to_0(u, lpm_entry, lpm_entry, PRESERVE_HIT);
  11385             }
  11386             bkt_ptr = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ALG_BKT_PTR0f);
  11387             if (!SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, VALID0f)) {
  11388                 continue;
  11389             }
  11390             flex = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, ENTRY_VIEW0f);
  11391             flex_v6_64 = 0;
  11392             if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && ipv6 && flex) {
  11393                 if (soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f) == 0xFFFFFFFF &&
  11394                     soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f) == 0xFFFFFFFF) {
  11395                     flex_v6_64 = 1;
  11396                 }
  11397             }
  11398 
  11399             if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, GLOBAL_HIGH0f) ||
  11400                 (soc_feature(u, soc_feature_ipmc_defip) &&
  11401                  SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, MULTICAST_ROUTE0f)) ||
  11402                  flex_v6_64) {
  11403                 if (bkt_ptr != 0) {
  11404                     LOG_ERROR(BSL_LS_SOC_ALPM,
  11405                               (BSL_META_U(u, "\tWrong bkt_ptr %d\n"), 
  11406                               bkt_ptr));
  11407                     error1 ++;
  11408                 }
  11409                 continue;
  11410             }
  11411             if (bkt_ptr == 0) {
  11412                 LOG_ERROR(BSL_LS_SOC_ALPM,
  11413                           (BSL_META_U(u, "\tWrong bkt_ptr2 %d\n"), 
  11414                           bkt_ptr));
  11415                 error1 ++;
  11416             }
  11417 
  11418             j = 0;
  11419             data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ECMP0f);
  11420             data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ECMP_PTR0f);
  11421             data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, NEXT_HOP_INDEX0f);
  11422             data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, PRI0f);
  11423             data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, RPE0f);
  11424             data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, DST_DISCARD0f);
  11425             data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, CLASS_ID0f);
  11426 
  11427             /* Check if bucket pointer duplicated */
  11428             if (bkt_ptr_arr) {
  11429                 if (bkt_ptr_arr[bkt_ptr] == -1) {
  11430                     bkt_ptr_arr[bkt_ptr] = lpm_idx;
  11431                     if (SOC_ALPM_V6_SCALE_CHECK(u, ipv6)) {
  11432                         bkt_ptr_arr[bkt_ptr + 1] = lpm_idx;
  11433                     }
  11434                     success ++;
  11435                 } else {
  11436                     LOG_ERROR(BSL_LS_SOC_ALPM,
  11437                               (BSL_META_U(u, "\tConflict bucket pointer %d: "
  11438                               "was %d now %d\n"), bkt_ptr,
  11439                               bkt_ptr_arr[bkt_ptr], lpm_idx));
  11440                     error1 ++;
  11441                 }
  11442             }
  11443 
  11444             if (ipv6) {
  11445                 if (flex) {
  11446                     alpm_mem = L3_DEFIP_ALPM_IPV6_64_1m;
  11447                     ent_num = ALPM_IPV6_64_BKT_COUNT_FLEX;
  11448                 } else {
  11449                     alpm_mem = L3_DEFIP_ALPM_IPV6_64m;
  11450                     ent_num = ALPM_IPV6_64_BKT_COUNT;
  11451                 }
  11452             } else {
  11453                 if (flex) {
  11454                     alpm_mem = L3_DEFIP_ALPM_IPV4_1m;
  11455                     ent_num = ALPM_IPV4_BKT_COUNT_FLEX;
  11456                 } else {
  11457                     alpm_mem = L3_DEFIP_ALPM_IPV4m;
  11458                     ent_num = ALPM_IPV4_BKT_COUNT;
  11459                 }
  11460             }
  11461             if (SOC_ALPM_V6_SCALE_CHECK(u, ipv6)) {
  11462                 ent_num <<= 1;
  11463             }
  11464 
  11465             (void) soc_alpm_lpm_vrf_get(u, lpm_entry, &vrf_id, &vrf);
  11466 
  11467             /* read shadow table for bpm length */
  11468             lpm_idx2 = soc_alpm_physical_idx(u, L3_DEFIPm, lpm_idx, 1);
  11469             rv = soc_mem_read(u, L3_DEFIP_AUX_TABLEm, MEM_BLOCK_ANY,
  11470                               lpm_idx2, shadow);
  11471             bpm_len = -1;
  11472             bpm_check = 0;
  11473             if (SOC_SUCCESS(rv)) {
  11474                 if (i == 0) {
  11475                     bpm_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm,
  11476                                                   shadow, BPM_LENGTH0f);
  11477                     ip_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm,
  11478                                                   shadow, IP_LENGTH0f);
  11479                 } else {
  11480                     bpm_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm,
  11481                                                   shadow, BPM_LENGTH1f);
  11482                     ip_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm,
  11483                                                   shadow, IP_LENGTH1f);
  11484                 }
  11485                 if (bpm_len > ip_len) {
  11486                     LOG_ERROR(BSL_LS_SOC_ALPM,
  11487                               (BSL_META_U(u, "\tAUX Table corrupted\n")));
  11488                     error1 ++;
  11489                 } else {
  11490                     success ++;
  11491                 }
  11492 
  11493                 bpm_check = 1;
  11494                 if (bpm_len == 0 &&
  11495                     SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, DEFAULT_MISS0f)) {
  11496                     bpm_check = 0;
  11497                 }
  11498             }
  11499 
  11500             if (bpm_check) {
  11501                 sal_memcpy(&lpm_bmp, lpm_entry, sizeof(defip_entry_t));
  11502                 _soc_alpm_pfx_len_to_mask(u, &lpm_bmp, bpm_len, ipv6);
  11503 
  11504                 fd_lpm_idx = fd_bkt_ptr = fd_alpm_idx = -1;
  11505                 rv = _soc_alpm_find(u, &lpm_bmp, alpm_mem, e, &fd_lpm_idx,
  11506                                     &fd_bkt_ptr, &fd_alpm_idx, FALSE);
  11507 
  11508                 if (fd_lpm_idx > 0) {
  11509                     fd_lpm_idx = soc_alpm_logical_idx(u, L3_DEFIPm,
  11510                                                       fd_lpm_idx >> 1, 1);
  11511                 }
  11512 
  11513                 if (SOC_SUCCESS(rv)) {
  11514                     j = 0;
  11515                     data1[j++] = soc_mem_field32_get(u, alpm_mem, e, ECMPf);
  11516                     data1[j++] = soc_mem_field32_get(u, alpm_mem, e, ECMP_PTRf);
  11517                     data1[j++] = soc_mem_field32_get(u, alpm_mem, e, NEXT_HOP_INDEXf);
  11518                     data1[j++] = soc_mem_field32_get(u, alpm_mem, e, PRIf);
  11519                     data1[j++] = soc_mem_field32_get(u, alpm_mem, e, RPEf);
  11520                     data1[j++] = soc_mem_field32_get(u, alpm_mem, e, DST_DISCARDf);
  11521                     data1[j++] = soc_mem_field32_get(u, alpm_mem, e, CLASS_IDf);
  11522 
  11523                     if (sal_memcmp(data0, data1, sizeof(data0)) != 0) {
  11524                         LOG_ERROR(BSL_LS_SOC_ALPM,
  11525                                   (BSL_META_U(u,
  11526                                   "\tData mismatch: "
  11527                                   "lpm_idx %d find_lpm_idx %d "
  11528                                   "find_alpm_idx %d find_bkt_ptr %d\n"),
  11529                                   lpm_idx, fd_lpm_idx,
  11530                                   fd_alpm_idx, fd_bkt_ptr));
  11531                         error1 ++;
  11532                     } else {
  11533                         success ++;
  11534                     }
  11535                 } else {
  11536                     if (rv == SOC_E_NOT_FOUND &&
  11537                         (vrf_id == SOC_L3_VRF_GLOBAL || soc_alpm_mode_get(u))) {
  11538                         LOG_VERBOSE(BSL_LS_SOC_ALPM,
  11539                               (BSL_META_U(u,
  11540                               "\t_soc_alpm_find rv=%d: "
  11541                               "lpm_idx %d find_lpm_idx %d "
  11542                               "find_alpm_idx %d find_bkt_ptr %d,"
  11543                               "(Possible: global route or !combined "
  11544                               "without default)\n"),
  11545                               rv, lpm_idx, fd_lpm_idx,
  11546                               fd_alpm_idx, fd_bkt_ptr));
  11547                     } else {
  11548                         LOG_ERROR(BSL_LS_SOC_ALPM,
  11549                               (BSL_META_U(u,
  11550                               "\t_soc_alpm_find rv=%d: "
  11551                               "lpm_idx %d find_lpm_idx %d "
  11552                               "find_alpm_idx %d find_bkt_ptr %d\n"),
  11553                               rv, lpm_idx, fd_lpm_idx,
  11554                               fd_alpm_idx, fd_bkt_ptr));
  11555                         error1 ++;
  11556                     }
  11557                 }
  11558             }
  11559 
  11560             bank_disable = soc_alpm_bank_dis(u, vrf);
  11561             /* Traverse bucket */
  11562             for (ent = 0; ent < ent_num; ent++) {
  11563                 (void) _soc_alpm_mem_index(u, alpm_mem, bkt_ptr, ent, bank_disable, &alpm_idx);
  11564 
  11565                 rv = _soc_mem_alpm_read(u, alpm_mem,
  11566                                         MEM_BLOCK_ANY, alpm_idx, e);
  11567                 if (SOC_FAILURE(rv)) {
  11568                     continue;
  11569                 }
  11570 
  11571                 if (!soc_mem_field32_get(u, alpm_mem, e, VALIDf)) {
  11572                     continue;
  11573                 }
  11574 
  11575                 (void) _soc_alpm_lpm_ent_init(u, e, alpm_mem, ipv6, vrf_id,
  11576                                               bkt_ptr, 0, &lpm_entry2, 0);
  11577 
  11578                 if (check_sw) {
  11579                     rv = _soc_alpm_sw_prefix_check(u, alpm_mem, ipv6, &lpm_entry2, vrf_id, vrf);
  11580                     if (SOC_FAILURE(rv)) {
  11581                         error1 ++;
  11582                         error2 ++;
  11583                         LOG_ERROR(BSL_LS_SOC_ALPM,
  11584                                   (BSL_META_U(u,
  11585                                   "_soc_alpm_sw_prefix_check rv=%d: v6 = %d, vrf_id = %d, vrf = %d\n"),
  11586                                   rv, ipv6, vrf_id, vrf));
  11587                     }
  11588                 }
  11589 
  11590                 fd_lpm_idx2 = fd_lpm_idx = fd_bkt_ptr = fd_alpm_idx = -1;
  11591                 rv = _soc_alpm_find(u, &lpm_entry2, alpm_mem, e,
  11592                                     &fd_lpm_idx, &fd_bkt_ptr,
  11593                                     &fd_alpm_idx, FALSE);
  11594 
  11595                 if (SOC_SUCCESS(rv)) {
  11596                     fd_lpm_idx2 = soc_alpm_logical_idx(u,
  11597                         L3_DEFIPm, fd_lpm_idx >> 1, 1);
  11598                 }
  11599 
  11600                 if (SOC_FAILURE(rv) ||
  11601                     fd_bkt_ptr  != bkt_ptr ||
  11602                     fd_lpm_idx2 != lpm_idx  ||
  11603                     fd_lpm_idx >> 1  != lpm_idx2 || /* for map remap */
  11604                     fd_alpm_idx != alpm_idx) {
  11605 
  11606                     error1 ++;
  11607                     error2 ++;
  11608                     LOG_ERROR(BSL_LS_SOC_ALPM,
  11609                               (BSL_META_U(u,
  11610                               "\t_soc_alpm_find2 rv=%d: "
  11611                               "fl [%d,%d] fa %d fb %d "
  11612                               "l [%d,%d] a %d b %d\n"),
  11613                               rv,
  11614                               fd_lpm_idx >> 1, fd_lpm_idx2, fd_alpm_idx, fd_bkt_ptr,
  11615                               lpm_idx2, lpm_idx, alpm_idx, bkt_ptr));
  11616                 }
  11617             }
  11618             if (error2 == 0) {
  11619                 success ++;
  11620             }
  11621 
  11622             if (!check_sw) {
  11623                 continue;
  11624             }
  11625 
  11626             /*
  11627              * Check hardware table above.
  11628              * Check software table below.
  11629  */
  11630 
  11631             /* lpm hash */
  11632 
  11633 #ifdef FB_LPM_HASH_SUPPORT
  11634             rv = LPM_HASH_VERIFY(u, lpm_entry,
  11635                                  ipv6 ? lpm_idx : ((lpm_idx << 1) + i));
  11636             if (SOC_FAILURE(rv)) {
  11637                 LOG_ERROR(BSL_LS_SOC_ALPM,
  11638                           (BSL_META_U(u, "\tLPM Hash check failed: rv %d "
  11639                           "lpm_idx %d\n"),
  11640                           rv, lpm_idx));
  11641                 error1 ++;
  11642             } else {
  11643                 success ++;
  11644             }
  11645 #endif
  11646 
  11647             /* bucket bitmap */
  11648             rv = alpm_bucket_is_assigned(u, bkt_ptr, ipv6, &used);
  11649             if (SOC_FAILURE(rv)) {
  11650                 LOG_ERROR(BSL_LS_SOC_ALPM,
  11651                           (BSL_META_U(u, "\tInvalid bucket pointer %d "
  11652                           "detected, in memory %s index %d\n"), bkt_ptr,
  11653                           SOC_MEM_NAME(u, L3_DEFIPm), lpm_idx));
  11654                 error1 ++;
  11655             } else if (used == 0) {
  11656                 /* If bucket was already freed */
  11657                 LOG_ERROR(BSL_LS_SOC_ALPM,
  11658                           (BSL_META_U(u, "\tFreed bucket pointer %d "
  11659                           "detected, in memory %s index %d\n"), bkt_ptr,
  11660                           SOC_MEM_NAME(u, L3_DEFIPm), lpm_idx));
  11661                 error1 ++;
  11662             } else {
  11663                 success ++;
  11664             }
  11665 
  11666             /* bucket view map */
  11667             bkt_mem_type = _soc_trident2_alpm_bkt_view_get(u, bkt_ptr << 2);
  11668             if (alpm_mem != bkt_mem_type) {
  11669                 LOG_ERROR(BSL_LS_SOC_ALPM,
  11670                           (BSL_META_U(u, "\tMismatched alpm view "
  11671                            "in bucket %d, expected %s, was %s\n"), bkt_ptr,
  11672                            SOC_MEM_NAME(u, alpm_mem),
  11673                            SOC_MEM_NAME(u, bkt_mem_type)));
  11674                 error1 ++;
  11675             } else {
  11676                 success ++;
  11677             }
  11678 
  11679             /* Check bpm len information */
  11680             rv = _alpm_prefix_create(u, lpm_entry, prefix,
  11681                                      &length, &default_route);
  11682             if (SOC_SUCCESS(rv)) {
  11683                 if (ipv6) {
  11684                     pfx_trie = VRF_PREFIX_TRIE_IPV6(u, vrf);
  11685                 } else {
  11686                     pfx_trie = VRF_PREFIX_TRIE_IPV4(u, vrf);
  11687                 }
  11688                 lpmp = NULL;
  11689                 if (pfx_trie) {
  11690                     rv = trie_find_lpm(pfx_trie, prefix, length, &lpmp);
  11691                 }
  11692                 if (SOC_SUCCESS(rv) && lpmp){
  11693                     tmp_pyld = (payload_t *) lpmp;
  11694                     if (tmp_pyld->bkt_ptr != NULL) {
  11695                         trie_bpm_len = ((payload_t *)(tmp_pyld->bkt_ptr))->len;
  11696                         if (trie_bpm_len != bpm_len) {
  11697                             LOG_ERROR(BSL_LS_SOC_ALPM,
  11698                                       (BSL_META_U(u, "\tBPM len mismatch: lpm_idx %d"
  11699                                       " alpm_idx %d bpm_len %d trie_bpm_len %d\n"),
  11700                                       lpm_idx, alpm_idx, bpm_len, trie_bpm_len));
  11701                             error1 ++;
  11702                         } else {
  11703                             success ++;
  11704                         }
  11705                     } else {
  11706                         success ++;
  11707                     }
  11708                 } else {
  11709                     LOG_ERROR(BSL_LS_SOC_ALPM,
  11710                               (BSL_META_U(u, "\ttrie_find_lpm failed: "
  11711                               "lpm_idx %d alpm_idx %d lpmp %p\n"),
  11712                               lpm_idx, alpm_idx, lpmp));
  11713                     error1 ++;
  11714                 }
  11715             } else {
  11716                 LOG_ERROR(BSL_LS_SOC_ALPM,
  11717                           (BSL_META_U(u, "\tPrefix creating failed: "
  11718                           "lpm_idx %d alpm_idx %d\n" ), lpm_idx, alpm_idx));
  11719                 error1 ++;
  11720             }
  11721         }
  11722     }
  11723 
  11724     if (error1) {
  11725         LOG_ERROR(BSL_LS_SOC_ALPM,
  11726                   (BSL_META_U(u,
  11727                   "\tL3_DEFIP index:[%d,%d] check failed. ipv6 %d error count %d\n"),
  11728                   prev_idx, prev_i, prev_v6, error1));
  11729         error = 1;
  11730     } else if (success) {
  11731         LOG_INFO(BSL_LS_SOC_ALPM,(BSL_META_U(u,
  11732                 "\tL3_DEFIP index:[%d,%d] check passed. ipv6 %d success count %d\n"),
  11733                  prev_idx, prev_i, prev_v6, success));
  11734     }
  11735 
  11736     SOC_ALPM_LPM_UNLOCK(u);
  11737     soc_cm_sfree(u, buffer);
  11738 
  11739     return (error ? SOC_E_FAIL: SOC_E_NONE);
  11740 }
  11741 
  11742 extern int _soc_alpm_128_sanity_check(int u, int min, int max,
  11743                                       int check_sw, int *bkt_ptr_arr);
  11744 
  11745 /*
  11746  * Function:
  11747  *      soc_alpm_sanity_check
  11748  * Purpose:
  11749  *      Sanity check for ALPM
  11750  * Parameters:
  11751  *      u       - Device unit
  11752  *      mem     -   L3_DEFIP/L3_DEFIP_PAIR_128 memory
  11753  *      index   -   -2 indicates full check to both table,
  11754  *                  -1 indicates full check to given table
  11755  *                  other indicates single entry check to given table
  11756  *      check_sw -  Check SW tables as well. 
  11757  */
  11758 int
  11759 soc_alpm_sanity_check(int u, soc_mem_t mem, int index, int check_sw)
  11760 {
  11761     int         rv           = SOC_E_NONE;
  11762     int         rv2          = SOC_E_NONE;
  11763     int         index_min    = -1, index_max  = -1;
  11764     int         index_min2   = -1, index_max2 = -1;
  11765     int         *bkt_ptr_arr = NULL;
  11766 #ifdef ALPM_SANITY_SENSITIVE
  11767     int         i;
  11768     soc_mem_t   bkt_view;
  11769 #endif
  11770 
  11771     if ((mem == L3_DEFIPm || index == -2) && 
  11772         soc_mem_index_max(u, L3_DEFIPm) != -1) {
  11773         index_min  = soc_mem_index_min(u, L3_DEFIPm);
  11774         index_max  = soc_mem_index_max(u, L3_DEFIPm);
  11775         /* Don't check urpf */
  11776         if (SOC_URPF_STATUS_GET(u)) {
  11777             index_max >>= 1;
  11778         }
  11779         if (index < -2 || index > index_max) {
  11780             return SOC_E_PARAM;
  11781         }
  11782         if (index >= index_min && index <= index_max) {
  11783             index_min = index;
  11784             index_max = index;
  11785         }
  11786     }
  11787 
  11788     if ((mem == L3_DEFIP_PAIR_128m || index == -2) && 
  11789         soc_mem_index_max(u, L3_DEFIP_PAIR_128m) != -1) {
  11790         index_min2 = soc_mem_index_min(u, L3_DEFIP_PAIR_128m);
  11791         index_max2 = soc_mem_index_max(u, L3_DEFIP_PAIR_128m);
  11792         /* Don't check urpf */
  11793         if (SOC_URPF_STATUS_GET(u)) {
  11794             index_max2 >>= 1;
  11795         }
  11796         if (index < -2 || index > index_max2) {
  11797             return SOC_E_PARAM;
  11798         }
  11799         if (index >= index_min2 && index <= index_max2) {
  11800             index_min2 = index;
  11801             index_max2 = index;
  11802         }
  11803     }
  11804 
  11805     if (index_max == -1 && index_max2 == -1) {
  11806         return SOC_E_PARAM;
  11807     }
  11808 
  11809     L3_LOCK(u);
  11810     bkt_ptr_arr = sal_alloc(sizeof(int) * MAX_PIVOT_COUNT, "Bucket ptr array");
  11811     if (bkt_ptr_arr == NULL) {
  11812         return SOC_E_MEMORY;
  11813     }
  11814     sal_memset(bkt_ptr_arr, 0xff, sizeof(int) * MAX_PIVOT_COUNT);
  11815 
  11816     if (index_max != -1) {
  11817         LOG_CLI(("Processing ALPM sanity check L3_DEFIP "
  11818                  "from index:%d to index:%d\n",
  11819                  index_min, index_max));
  11820         rv = _soc_alpm_sanity_check(u, index_min, index_max, check_sw, bkt_ptr_arr);
  11821         LOG_CLI(("ALPM sanity check L3_DEFIP %s. \n\n",
  11822                  SOC_SUCCESS(rv) ? "passed" : "failed"));
  11823     }
  11824 
  11825     if (index_max2 != -1) {
  11826         LOG_CLI(("Processing ALPM sanity check L3_DEFIP_PAIR_128 "
  11827                  "from index:%d to index:%d\n",
  11828                  index_min2, index_max2));
  11829         rv2 = _soc_alpm_128_sanity_check(u, index_min2, index_max2, check_sw, bkt_ptr_arr);
  11830         LOG_CLI(("ALPM sanity check L3_DEFIP_PAIR_128 %s. \n",
  11831                  SOC_SUCCESS(rv2) ? "passed" : "failed"));
  11832     }
  11833 
  11834 #ifdef ALPM_SANITY_SENSITIVE
  11835     /* This check is very sensitive, turn it off for now. */
  11836     /* In case full check to both table, the bkt ptr is fully collected */
  11837     if (index == -2 &&  SOC_SUCCESS(rv) && SOC_SUCCESS(rv2)) {
  11838         for (i = 0; i < MAX_PIVOT_COUNT; i++) {
  11839             if (bkt_ptr_arr[i] != -1) {
  11840                 continue;
  11841             }
  11842             bkt_view = _soc_trident2_alpm_bkt_view_get(u, i << 2);
  11843             if (bkt_view != INVALIDm){
  11844                 LOG_ERROR(BSL_LS_SOC_ALPM,
  11845                           (BSL_META_U(u,
  11846                           "\tBucket view corrupted: bkt_ptr %d, view %s.\n"),
  11847                           i, SOC_MEM_NAME(u, bkt_view)));
  11848             }
  11849         }
  11850     }
  11851 #endif
  11852 
  11853     sal_free(bkt_ptr_arr);
  11854     L3_UNLOCK(u);
  11855     return SOC_SUCCESS(rv) ? rv2: rv;
  11856 }
  11857 
  11858 
  11859 /* Get entry No. per bucket based on various setting */
  11860 int
  11861 _soc_alpm_bkt_entry_cnt(int u, soc_mem_t mem)
  11862 {
  11863     int bkt_cnt = 0;
  11864     int v6;
  11865 
  11866     switch (mem) {
  11867     case L3_DEFIP_ALPM_IPV4m:
  11868         bkt_cnt = ALPM_IPV4_BKT_COUNT;
  11869         v6 = 0;
  11870         break;
  11871     case L3_DEFIP_ALPM_IPV4_1m:
  11872         bkt_cnt = ALPM_IPV4_BKT_COUNT_FLEX;
  11873         v6 = 0;
  11874         break;
  11875     case L3_DEFIP_ALPM_IPV6_64m:
  11876         bkt_cnt = ALPM_IPV6_64_BKT_COUNT;
  11877         v6 = 1;
  11878         break;
  11879     case L3_DEFIP_ALPM_IPV6_64_1m:
  11880         bkt_cnt = ALPM_IPV6_64_BKT_COUNT_FLEX;
  11881         v6 = 1;
  11882         break;
  11883     case L3_DEFIP_ALPM_IPV6_128m:
  11884         bkt_cnt = ALPM_IPV6_128_BKT_COUNT;
  11885         v6 = 1;
  11886         break;
  11887     default:
  11888         return SOC_E_INTERNAL;
  11889     }
  11890 
  11891     if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) {
  11892         bkt_cnt <<= 1;
  11893     }
  11894 
  11895     if (soc_alpm_mode_get(u) == SOC_ALPM_MODE_PARALLEL &&
  11896         SOC_URPF_STATUS_GET(u)) {
  11897         bkt_cnt >>= 1;
  11898     }
  11899 
  11900     return bkt_cnt;
  11901 }
  11902 
  11903 /*
  11904  * Function:
  11905  *      soc_alpm_route_capacity_get
  11906  * Purpose:
  11907  *      Get the capacity for ALPM from tables:
  11908  * L3_DEFIP_ALPM_IPV4, L3_DEFIP_ALPM_IPV6_64, L3_DEFIP_ALPM_IPV6_128
  11909  * L3_DEFIP, L3_DEFIP_PAIR_128
  11910  * Parameters:
  11911  *      unit         - Device unit
  11912  *      route_type   - 0: v4, 1: v6-64, 2: v6-128
  11913  *      cap_type     - 0: max capacity, 1: min guaranteed capacity
  11914  *      max_entries  - Maximum result returned.
  11915  *      min_entries  - Minimum result returned.
  11916  */
  11917 int
  11918 soc_alpm_route_capacity_get(int unit, soc_mem_t mem,
  11919                             int *max_entries, int *min_entries)
  11920 {
  11921     int rv = SOC_E_NONE;
  11922     int num_ent, num_pivot, num_bkt_max, num_bkt_min;
  11923 
  11924     if (max_entries == NULL && min_entries == NULL) {
  11925         return SOC_E_PARAM;
  11926     }
  11927 
  11928     switch (mem) {
  11929     case L3_DEFIP_ALPM_IPV4m:
  11930     case L3_DEFIP_ALPM_IPV4_1m:
  11931         num_ent = soc_mem_index_count(unit, L3_DEFIPm) * 2;
  11932         break;
  11933     case L3_DEFIP_ALPM_IPV6_64m:
  11934     case L3_DEFIP_ALPM_IPV6_64_1m:
  11935         num_ent = soc_mem_index_count(unit, L3_DEFIP_PAIR_128m);
  11936         if (num_ent == 0) {
  11937             num_ent = soc_mem_index_count(unit, L3_DEFIPm);
  11938         }
  11939         break;
  11940     case L3_DEFIP_ALPM_IPV6_128m:
  11941         num_ent = soc_mem_index_count(unit, L3_DEFIP_PAIR_128m);
  11942         break;
  11943     default:
  11944         return SOC_E_UNAVAIL;
  11945     }
  11946 
  11947     num_pivot = num_ent >> SOC_URPF_STATUS_GET(unit);
  11948     num_bkt_max = _soc_alpm_bkt_entry_cnt(unit, mem);
  11949     num_bkt_min = num_bkt_max / 2;
  11950 
  11951     if (max_entries != NULL) {
  11952         *max_entries = num_pivot * num_bkt_max;
  11953     }
  11954     if (min_entries != NULL) {
  11955         *min_entries = num_pivot * num_bkt_min;
  11956     }
  11957 
  11958     return rv; 
  11959 }
  11960 
  11961 #endif /* ALPM_ENABLE */