openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

alpm_th.c (502564B)


      1 /*
      2  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      3  * 
      4  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      5  * 
      6  * File:    alpm.c
      7  * Purpose: Tomahawk 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 <soc/tomahawk.h>
     22 #include <soc/trident3.h>
     23 #include <soc/apache.h>
     24 #include <shared/bsl.h>
     25 #include <soc/l3x.h>
     26 
     27 #ifdef ALPM_ENABLE
     28 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT)
     29 #include <shared/util.h>
     30 #include <shared/l3.h>
     31 #include <soc/alpm.h>
     32 #include <soc/esw/alpm_int.h>
     33 #include <soc/esw/trie.h>
     34 #include <soc/esw/alpm_trie_v6.h>
     35 
     36 #define ALPM_REPART_DEBUG
     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 /* Add suport for Extended */
     57 #define SOC_ALPM_ENTRY_BUF_128(_v6_, _mem_, _buf_, _v4ent_, _v6ent_)  \
     58             _buf_ = ((uint32 *) &(_v6ent_))
     59 
     60 /* this is a left shift of the prefix by 32/64 - length  and convert to
     61    brcm order of ip words */
     62 #define ALPM_TRIE_TO_NORMAL_IP(prefix, length, v6) \
     63     do {\
     64         if (!(v6)) {\
     65             prefix[0] = SHR_SHIFT_LEFT(prefix[1], 32 - length);\
     66             prefix[1] = 0;\
     67         } else {\
     68             int macro_pfx_shift = 64 - length;\
     69             int macro_tmp;\
     70             if (macro_pfx_shift < 32) {\
     71                 /* get upper half shifted */\
     72                 macro_tmp = prefix[3] << macro_pfx_shift;\
     73                 /* isolate shifted stuff off lower half */\
     74                 macro_tmp |= SHR_SHIFT_RIGHT(prefix[4], 32 - macro_pfx_shift);\
     75                 /* swap the order of words */\
     76                 prefix[0] = prefix[4] << macro_pfx_shift;\
     77                 prefix[1] = macro_tmp;\
     78                 prefix[2] = prefix[3] = prefix[4] = 0;\
     79             } else {\
     80                 prefix[1] = SHR_SHIFT_LEFT(prefix[4], macro_pfx_shift - 32);\
     81                 prefix[0] = prefix[2] = prefix[3] = prefix[4] = 0;\
     82             }\
     83         }\
     84     } while (0)
     85 
     86 #define SOC_ALPM_MOVE_PIVOT_HALF(u, v1, src, dst)\
     87     do {\
     88         int _src = soc_th_alpm_physical_idx((u), L3_DEFIPm, (src), 1)*2; \
     89         int _dst = soc_th_alpm_physical_idx((u), L3_DEFIPm, (dst), 1)*2; \
     90         if ((v1)) {\
     91             _src++;\
     92         }\
     93         ALPM_TCAM_PIVOT((u), _dst) = ALPM_TCAM_PIVOT((u), _src);\
     94         if (ALPM_TCAM_PIVOT((u), _dst)) { \
     95             PIVOT_TCAM_INDEX(ALPM_TCAM_PIVOT((u), _dst)) = _dst;\
     96             SOC_ALPM_BU_PIVOT_IDX_UPDATE(u, _dst); \
     97         } \
     98         ALPM_TCAM_PIVOT((u), _src) = NULL;\
     99     } while (0)
    100 
    101 /* used for moving either 2 v4 entries or 1 v6 entry. */
    102 #define SOC_ALPM_MOVE_PIVOT_FULL(u, src, dst)\
    103     do {\
    104         int _src = soc_th_alpm_physical_idx((u), L3_DEFIPm, (src), 1);\
    105         int _dst = soc_th_alpm_physical_idx((u), L3_DEFIPm, (dst), 1);\
    106         /* Track full-entry move */\
    107         ALPM_TCAM_PIVOT(u, _dst<<1) = ALPM_TCAM_PIVOT(u, _src<<1);\
    108         ALPM_TCAM_PIVOT(u, (_dst<<1) + 1) = \
    109                                 ALPM_TCAM_PIVOT(u, (_src<<1) + 1);\
    110         if (ALPM_TCAM_PIVOT((u), _dst<<1)) { \
    111             PIVOT_TCAM_INDEX(ALPM_TCAM_PIVOT((u), _dst<<1)) = _dst<<1;\
    112             SOC_ALPM_BU_PIVOT_IDX_UPDATE(u, (_dst<<1)); \
    113         } \
    114         if (ALPM_TCAM_PIVOT((u), (_dst<<1) + 1)) { \
    115             PIVOT_TCAM_INDEX(ALPM_TCAM_PIVOT((u), (_dst<<1) + 1)) = \
    116                              (_dst<<1) + 1;\
    117             SOC_ALPM_BU_PIVOT_IDX_UPDATE(u, (_dst<<1) + 1); \
    118         } \
    119         ALPM_TCAM_PIVOT(u, _src<<1) = NULL;\
    120         ALPM_TCAM_PIVOT(u, (_src<<1) + 1) = NULL;\
    121     } while (0)
    122 
    123 #define FB_LPM_HASH_SUPPORT 1
    124 
    125 typedef struct soc_th_alpm_lpm_state_s {
    126     int start;  /* start index for this prefix length */
    127     int end;    /* End index for this prefix length */
    128     int prev;   /* Previous (Lo to Hi) prefix length with non zero entry count*/
    129     int next;   /* Next (Hi to Lo) prefix length with non zero entry count */
    130     int vent;   /* valid entries */
    131     int fent;   /* free entries */
    132 } soc_th_alpm_lpm_state_t, *soc_th_alpm_lpm_state_p;
    133 
    134 /* Can move to SOC Control structures */
    135 static soc_th_alpm_lpm_state_p soc_th_alpm_lpm_state[SOC_MAX_NUM_DEVICES];
    136 
    137 #define ALPM_IPV6_PFX_ZERO               33
    138 #define ALPM_MAX_VRF_PFX_ENTRIES         (64 + 32 + 2 + 1)
    139 #define ALPM_MAX_VRF_PFX_INDEX           (ALPM_MAX_VRF_PFX_ENTRIES - 1)
    140 #define ALPM_MAX_PFX_ENTRIES             (3 * ALPM_MAX_VRF_PFX_ENTRIES)
    141 #define ALPM_MAX_PFX_INDEX               (ALPM_MAX_PFX_ENTRIES - 1)
    142 #define SOC_ALPM_PFX_IS_V4(u, pfx)       (((pfx) % ALPM_MAX_VRF_PFX_ENTRIES) < ALPM_IPV6_PFX_ZERO)
    143 #define SOC_ALPM_PFX_IS_V6_64(u, pfx)    (((pfx) % ALPM_MAX_VRF_PFX_ENTRIES) >= ALPM_IPV6_PFX_ZERO && \
    144                                           (pfx) != ALPM_MAX_VRF_PFX_INDEX)
    145 #define SOC_ALPM_LPM_INIT_CHECK(u)        (soc_th_alpm_lpm_state[(u)] != NULL)
    146 #define SOC_ALPM_LPM_STATE(u)             (soc_th_alpm_lpm_state[(u)])
    147 #define SOC_ALPM_LPM_STATE_START(u, pfx)  (soc_th_alpm_lpm_state[(u)][(pfx)].start)
    148 #define SOC_ALPM_LPM_STATE_END(u, pfx)    (soc_th_alpm_lpm_state[(u)][(pfx)].end)
    149 #define SOC_ALPM_LPM_STATE_PREV(u, pfx)  (soc_th_alpm_lpm_state[(u)][(pfx)].prev)
    150 #define SOC_ALPM_LPM_STATE_NEXT(u, pfx)  (soc_th_alpm_lpm_state[(u)][(pfx)].next)
    151 #define SOC_ALPM_LPM_STATE_VENT(u, pfx)  (soc_th_alpm_lpm_state[(u)][(pfx)].vent)
    152 #define SOC_ALPM_LPM_STATE_FENT(u, pfx)  (soc_th_alpm_lpm_state[(u)][(pfx)].fent)
    153 
    154 typedef struct soc_th_lpm_field_cache_s {
    155     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, CLASS_ID0f);
    156     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, CLASS_ID1f);
    157     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DST_DISCARD0f);
    158     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DST_DISCARD1f);
    159     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP0f);
    160     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP1f);
    161     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_COUNT0f);
    162     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_COUNT1f);
    163     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_PTR0f);
    164     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_PTR1f);
    165     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_ROUTE0f);
    166     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_ROUTE1f);
    167     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MULTICAST_ROUTE0f);
    168     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MULTICAST_ROUTE1f);
    169     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPA_ID0f);
    170     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPA_ID1f);
    171     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, EXPECTED_L3_IIF0f);
    172     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, EXPECTED_L3_IIF1f);
    173     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f);
    174     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f);
    175     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f);
    176     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f);
    177     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, L3MC_INDEX0f);
    178     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, L3MC_INDEX1f);
    179     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, HIT0f);
    180     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, HIT1f);
    181     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR0f);
    182     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR1f);
    183     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR_MASK0f);
    184     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR_MASK1f);
    185     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, NEXT_HOP_INDEX0f);
    186     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, NEXT_HOP_INDEX1f);
    187     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, PRI0f);
    188     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, PRI1f);
    189     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPE0f);
    190     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPE1f);
    191     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VALID0f);
    192     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VALID1f);
    193     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_0f);
    194     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_1f);
    195     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_MASK0f);
    196     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_MASK1f);
    197     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_HIGH0f);
    198     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_HIGH1f);
    199     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_HIT_IDX0f);
    200     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_HIT_IDX1f);
    201     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_BKT_PTR0f);
    202     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_BKT_PTR1f);
    203     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_SUB_BKT_PTR0f);
    204     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_SUB_BKT_PTR1f);
    205     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DEFAULT_MISS0f);
    206     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DEFAULT_MISS1f);
    207     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_BASE_COUNTER_IDX0f);
    208     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_BASE_COUNTER_IDX1f);
    209     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_POOL_NUMBER0f);
    210     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_POOL_NUMBER1f);
    211     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_OFFSET_MODE0f);
    212     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_OFFSET_MODE1f);
    213     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, SRC_DISCARD0f);
    214     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, SRC_DISCARD1f);
    215     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DESTINATION0f);
    216     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DESTINATION1f);
    217     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_VIEW0f);
    218     SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_VIEW1f);
    219 
    220 } soc_th_lpm_field_cache_t, *soc_lpm_field_cache_p;
    221 static soc_lpm_field_cache_p soc_lpm_field_cache_state[SOC_MAX_NUM_DEVICES];
    222 
    223 #define SOC_MEM_OPT_F32_GET(m_unit, m_mem, m_entry_data, m_field) \
    224         soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), \
    225             (m_entry_data), (soc_lpm_field_cache_state[(m_unit)]->m_mem##m_field))
    226 
    227 #define SOC_MEM_OPT_F32_SET(m_unit, m_mem, m_entry_data, m_field, m_val) \
    228         soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), \
    229             (m_entry_data), (soc_lpm_field_cache_state[(m_unit)]->m_mem##m_field), (m_val))
    230 
    231 
    232 #define SOC_MEM_OPT_FIELD_VALID(m_unit, m_mem, m_field) \
    233                 ((soc_lpm_field_cache_state[(m_unit)]->m_mem##m_field) != NULL)
    234 
    235 
    236 #ifdef FB_LPM_HASH_SUPPORT
    237 typedef struct _soc_th_alpm_lpm_hash_s {
    238     int         unit;
    239     int         entry_count;    /* Number entries in hash table */
    240     int         index_count;    /* Hash index max value + 1 */
    241     uint16      *table;         /* Hash table with 16 bit index */
    242     uint16      *link_table;    /* To handle collisions */
    243 } _soc_th_alpm_lpm_hash_t;
    244 
    245 typedef uint32 _soc_th_alpm_lpm_hash_entry_t[5];
    246 typedef int (*_soc_th_alpm_lpm_hash_compare_fn)(_soc_th_alpm_lpm_hash_entry_t key1,
    247                                            _soc_th_alpm_lpm_hash_entry_t key2);
    248 static _soc_th_alpm_lpm_hash_t *_fb_lpm_hash_tab[SOC_MAX_NUM_DEVICES];
    249 #define SOC_ALPM_LPM_STATE_HASH(u)           (_fb_lpm_hash_tab[(u)])
    250 
    251 #define TD2_ALPM_HASH_INDEX_NULL (0xFFFF)
    252 #define TD2_ALPM_HASH_INDEX_MASK (0x7FFF)
    253 #define TD2_ALPM_HASH_IPV6_MASK  (0x8000)
    254 
    255 #define SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, odata)                 \
    256     odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR0f);     \
    257     odata[1] =                                                               \
    258         SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK0f);       \
    259     odata[2] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR1f);     \
    260     odata[3] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK1f);\
    261     if ( (!(SOC_IS_HURRICANE(u))) &&   \
    262         (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f))) {                \
    263         int m_vrf;\
    264         (void)soc_th_alpm_lpm_vrf_get(u, entry_data, (int *)&odata[4], &m_vrf); \
    265     } else {                                                                 \
    266         odata[4] = 0;                                                        \
    267     }
    268 
    269 #define SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, odata)               \
    270     odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR0f);     \
    271     odata[1] =                                                               \
    272         SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK0f);       \
    273     odata[2] = 0;                                                            \
    274     odata[3] = 0x80000001;                                                   \
    275     if ((!(SOC_IS_HURRICANE(u))) && \
    276         (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f))) {                \
    277         int m_vrf;\
    278         (void)soc_th_alpm_lpm_vrf_get(u, entry_data, (int *)&odata[4], &m_vrf); \
    279     } else {                                                                 \
    280         odata[4] = 0;                                                        \
    281     }
    282 
    283 #define SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, odata)               \
    284     odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR1f);     \
    285     odata[1] =                                                               \
    286         SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK1f);       \
    287     odata[2] = 0;                                                            \
    288     odata[3] = 0x80000001;                                                   \
    289     if ((!(SOC_IS_HURRICANE(u))) &&  \
    290     (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_1f))) {                    \
    291         int m_vrf;\
    292         defip_entry_t m_tmp_ipv4;\
    293         (void)soc_th_alpm_lpm_ip4entry1_to_0(u, entry_data, &m_tmp_ipv4, 0);    \
    294         (void)soc_th_alpm_lpm_vrf_get(u, &m_tmp_ipv4, (int *)&odata[4], &m_vrf); \
    295     } else {                                                                 \
    296         odata[4] = 0;                                                        \
    297     }
    298 
    299 #define SOC_FB_LPM_HASH_ENTRY_GET _soc_th_alpm_lpm_hash_entry_get
    300 
    301 /* ALPM Software control block */
    302 soc_alpm_bucket_t soc_th_alpm_bucket[SOC_MAX_NUM_DEVICES];
    303 int l3_alpm_ipv4_double_wide[SOC_MAX_NUM_DEVICES];
    304 extern int l3_alpm_sw_prefix_lookup[SOC_MAX_NUM_DEVICES];
    305 
    306 /* Bucket sharing global vars */
    307 alpm_bkt_usg_t  *bkt_usage[SOC_MAX_NUM_DEVICES];
    308 alpm_bkt_bmp_t  *global_bkt_usage[SOC_MAX_NUM_DEVICES][SOC_TH_MAX_ALPM_VIEWS];
    309 
    310 /* ALPM internel debug counter */
    311 _alpm_int_dbg_cnt_t _alpm_dbg_cntr[SOC_MAX_NUM_DEVICES];
    312 
    313 /* Functions and externs */
    314 static
    315 void _soc_th_alpm_lpm_hash_entry_get(int u, void *e,
    316                                 int index, _soc_th_alpm_lpm_hash_entry_t r_entry,
    317                                 int *v);
    318 static
    319 uint16 _soc_th_alpm_lpm_hash_compute(uint8 *data, int data_nbits);
    320 static
    321 int _soc_th_alpm_lpm_hash_create(int unit,
    322                             int entry_count,
    323                             int index_count,
    324                             _soc_th_alpm_lpm_hash_t **fb_lpm_hash_ptr);
    325 static
    326 int _soc_th_alpm_lpm_hash_destroy(_soc_th_alpm_lpm_hash_t *fb_lpm_hash);
    327 static
    328 int _soc_th_alpm_lpm_hash_lookup(_soc_th_alpm_lpm_hash_t          *hash,
    329                             _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn,
    330                             _soc_th_alpm_lpm_hash_entry_t    entry,
    331                             int                         pfx,
    332                             uint16                      *key_index);
    333 static
    334 int _soc_th_alpm_lpm_hash_insert(_soc_th_alpm_lpm_hash_t *hash,
    335                             _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn,
    336                             _soc_th_alpm_lpm_hash_entry_t entry,
    337                             int    pfx,
    338                             uint16 old_index,
    339                             uint16 new_index,
    340                             uint32 *rvt_index);
    341 static
    342 int _soc_th_alpm_lpm_hash_revert(_soc_th_alpm_lpm_hash_t *hash,
    343                             _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn,
    344                             _soc_th_alpm_lpm_hash_entry_t entry,
    345                             uint16 new_index,
    346                             uint32 rvt_index);
    347 static
    348 int _soc_th_alpm_lpm_hash_delete(_soc_th_alpm_lpm_hash_t *hash,
    349                             _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn,
    350                             _soc_th_alpm_lpm_hash_entry_t entry,
    351                             int    pfx,
    352                             uint16 delete_index);
    353 static
    354 int _soc_th_alpm_lpm_hash_verify(_soc_th_alpm_lpm_hash_t *hash,
    355                             _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn,
    356                             _soc_th_alpm_lpm_hash_entry_t entry,
    357                             int    pfx,
    358                             uint16 index);
    359 static int
    360 _soc_th_alpm_lpm_prefix_length_get(int , int , void *, int *, int *, int *);
    361 
    362 static int soc_th_alpm_lpm_init(int u);
    363 static int soc_th_alpm_lpm_deinit(int u);
    364 static int soc_th_alpm_lpm_insert(int u, void *entry_data, int *index, int bpm_len,
    365                                   int src_default, int src_discard);
    366 static int soc_th_alpm_lpm_delete(int u, void *key_data);
    367 static int _soc_th_alpm_fill_aux_entry_for_op(int u,
    368                void *key_data,
    369                int ipv6,    /* Entry is ipv6. */
    370                int db_type, /* database type */
    371                int ent_type,
    372                int replace_len, /* used for delete propagate */
    373                defip_aux_scratch_entry_t *aux_entry);
    374 static int
    375 _soc_th_alpm_lpm_match(int u,
    376                void *key_data,
    377                void *e,         /* return entry data if found */
    378                int *index_ptr,  /* return key location */
    379                int *pfx_len,    /* Key prefix length. vrf + 32 + prefix len for IPV6*/
    380                int *ipv6,       /* Entry is ipv6. */
    381                int *vrf_id,     /* (OUT) */
    382                int *vrf);       /* (OUT) */
    383 static int soc_th_alpm_lpm_match(int u,
    384                void *key_data,
    385                void *e,         /* return entry data if found */
    386                int *index_ptr);  /* return key location */
    387 static int soc_th_alpm_shared_mem_init(int u);
    388 static int _soc_th_alpm_mem_ent_init(int unit, int ipv6, void *lpm_entry,
    389                        void *alpm_entry, void *alpm_sip_entry, soc_mem_t mem,
    390                        uint32 src_flags, uint32 *default_route, int bucket_id);
    391 static int _soc_th_alpm_lpm_ent_init(int unit, void *alpm_entry, soc_mem_t mem,
    392                                      int ipv6, int vrf_id, int bucket, int index,
    393                                      void *lpm_entry, int flex);
    394 static int _soc_th_alpm_lpm_ent_key_init(int unit, uint32 *key, int len, int vrf,
    395                                     int ipv6, defip_entry_t *lpm_entry, int init);
    396 static int soc_th_alpm_vrf_delete(int u, int vrf, int v6);
    397 int soc_th_alpm_lpm_delete(int u, void *key_data);
    398 
    399 /* Use MAX_VRF_ID to store VRF_OVERRIDE routes debug info */
    400 extern alpm_vrf_handle_t *alpm_vrf_handle[SOC_MAX_NUM_DEVICES];
    401 extern alpm_pivot_t **tcam_pivot[SOC_MAX_NUM_DEVICES];
    402 
    403 extern int soc_tomahawk_alpm_mode_get(int unit);
    404 extern int _soc_th_alpm_128_prefix_create(int u, void *entry, uint32 *result,
    405                                    uint32 *pfx_len, int *default_route);
    406 
    407 #if 0
    408 extern int sh_process_command(int u,char * c);
    409 extern void soc_th_alpm_lpm_sw_dump(int unit);
    410 void soc_th_debug_collect(int u, int vrf, int v6, soc_mem_t mem, void *entry)
    411 {
    412     int i;
    413 
    414     sh_process_command(u, "debug =");
    415 
    416     LOG_CLI(("\n====Collecting info for unit(%d), vrf(%d), v6(%d), mem(%s), entry(%p)\n",
    417             u, vrf, v6, SOC_MEM_NAME(u, mem), entry));
    418 
    419     /* Dump system configuration */
    420     LOG_CLI(("\n====Dumping current config.bcm\n"));
    421     sh_process_command(u, "config show");
    422 
    423     /* Debug counter */
    424     LOG_CLI(("\n====Dumping ALPM debug counters\n"));
    425     for (i = 0; i < DEBUG_VAR_NUMBER; i++) {
    426         if (debug_var[i] != 0) {
    427             LOG_CLI(("debug_var[%2d] = %d\n", i, debug_var[i]));
    428         }
    429     }
    430 
    431     /* Dump current entry */
    432     if (entry != NULL) {
    433         LOG_CLI(("\n====Dumping ALPM current operating entry\n"));
    434         soc_mem_entry_dump_if_changed(u, mem, entry, "ALPM-DBG: ");
    435     }
    436 
    437     /* Dump ALPM Memories */
    438     LOG_CLI(("\n====Dumping ALPM memories\n"));
    439     sh_process_command(u, "d chg L3_DEFIP");
    440     sh_process_command(u, "d chg L3_DEFIP_pair_128");
    441     sh_process_command(u, "d chg L3_DEFIP_aux_table");
    442     sh_process_command(u, "d chg L3_DEFIP_AUX_SCRATCH");
    443     sh_process_command(u, "d chg L3_DEFIP_alpm_ipv4");
    444     sh_process_command(u, "d chg L3_DEFIP_alpm_ipv6_64");
    445     sh_process_command(u, "d chg L3_DEFIP_alpm_ipv6_128");
    446 
    447     /* Dump Pivot trie */
    448     LOG_CLI(("\n====Dumping ALPM Pivot trie-tree for VRF %d\n", vrf));
    449     trie_dump(v6 ? VRF_PIVOT_TRIE_IPV6_128(u, vrf) : VRF_PIVOT_TRIE_IPV4(u, vrf),
    450               NULL, NULL);
    451 
    452     /* Dump VRF trie */
    453     LOG_CLI(("\n====Dumping VRF route trie-tree for VRF %d\n", vrf));
    454     trie_dump(v6 ? VRF_PREFIX_TRIE_IPV6_128(u, vrf) : VRF_PREFIX_TRIE_IPV4(u, vrf),
    455               NULL, NULL);
    456 
    457     /* Dump Bucket trie */
    458     LOG_CLI(("\n====Dumping Bucket trie-tree for VRF %d\n", vrf));
    459     for (i = 0; i < TH_MAX_PIVOT_COUNT(u); i++) {
    460         if (ALPM_TCAM_PIVOT(u, i) != NULL) {
    461             trie_t *trie = PIVOT_BUCKET_TRIE(ALPM_TCAM_PIVOT(u, i));
    462             LOG_CLI(("\t==Dumping Trie-tree for TCAM %d, index %d\n", i,
    463                     soc_th_alpm_logical_idx(u, L3_DEFIPm, i >> 1, 1)));
    464             trie_dump(trie, NULL, NULL);
    465         }
    466     }
    467 
    468     /* Dump ALPM LPM SW state */
    469     LOG_CLI(("\n====Dumping ALPM LPM SW state\n"));
    470     soc_th_alpm_lpm_sw_dump(u);
    471 
    472     /* Running Sanity check */
    473     LOG_CLI(("\n====Running Bucket Sanity check\n"));
    474     soc_th_alpm_bucket_sanity_check(u, L3_DEFIPm, -1);
    475 
    476     LOG_CLI(("\n====Running Pivot Sanity check\n"));
    477     soc_th_alpm_pivot_sanity_check(u, L3_DEFIPm, -1);
    478 
    479     return ;
    480 }
    481 #endif
    482 
    483 int
    484 _soc_th_alpm_lpm_entry_view_get(int u, int ipv6, int flex)
    485 {
    486     int entry_view = flex;
    487 
    488     if (SOC_IS_TRIDENT3X(u)) {
    489         switch (ipv6) {
    490             case L3_DEFIP_MODE_128:
    491                 entry_view = 0;
    492                 break;
    493             case L3_DEFIP_MODE_64:
    494                 entry_view = flex ? 1 : 2;
    495                 break;
    496             case L3_DEFIP_MODE_V4:
    497             default:
    498                 entry_view = flex ? 3 : 4;
    499         }
    500     }
    501 
    502     return entry_view;
    503 }
    504 
    505 int
    506 _soc_th_alpm_lpm_flex_get(int u, int ipv6, int entry_view)
    507 {
    508     int flex = entry_view;
    509 
    510     if (SOC_IS_TRIDENT3X(u)) {
    511         switch (ipv6) {
    512             case L3_DEFIP_MODE_128:
    513                 flex = 0;
    514                 break;
    515             case L3_DEFIP_MODE_64:
    516                 flex = (entry_view == 1) ? 1 : 0;
    517                 break;
    518             case L3_DEFIP_MODE_V4:
    519             default:
    520                 flex = (entry_view == 3) ? 1 : 0;
    521         }
    522     }
    523 
    524     return flex;
    525 }
    526 
    527 
    528 STATIC int
    529 _soc_th_alpm_sw_propagate_required(int unit)
    530 {
    531     int i, mem_cnt;
    532     soc_mem_t mem_chk[] = {
    533         L3_DEFIPm,
    534         L3_DEFIP_PAIR_128m,
    535         L3_DEFIP_AUX_TABLEm
    536     };
    537 
    538     mem_cnt = sizeof(mem_chk) / sizeof(mem_chk[0]);
    539     for (i = 0; i < mem_cnt; i++) {
    540         if (soc_mem_cache_get(unit, mem_chk[i], MEM_BLOCK_ANY)) {
    541             return TRUE;
    542         }
    543     }
    544 
    545     return FALSE;
    546 }
    547 
    548 STATIC int
    549 _soc_th_alpm_sw_hitbit_upd_required(int unit)
    550 {
    551     int i, mem_cnt;
    552     soc_mem_t mem_chk[] = {
    553         L3_DEFIPm,
    554         L3_DEFIP_PAIR_128m
    555     };
    556 
    557     mem_cnt = sizeof(mem_chk) / sizeof(mem_chk[0]);
    558     for (i = 0; i < mem_cnt; i++) {
    559         if (soc_mem_cache_get(unit, mem_chk[i], MEM_BLOCK_ANY)) {
    560             return TRUE;
    561         }
    562     }
    563 
    564     return FALSE;
    565 }
    566 
    567 STATIC int
    568 _soc_th_alpm_ctrl_init(int u)
    569 {
    570     int i, mode;
    571     sal_memset(&ALPM_CTRL(u), 0, sizeof(_soc_alpm_ctrl_t));
    572 
    573     ALPM_CTRL(u).trie_propagate = _soc_th_alpm_sw_propagate_required(u);
    574     /* Don't set trie_user_ppg = 0, it's for debug purpose only */
    575     ALPM_CTRL(u).trie_user_ppg = soc_property_get(u, "l3_alpm_trie_user_ppg", 1);
    576     ALPM_CTRL(u).hit_idx_upd = _soc_th_alpm_sw_hitbit_upd_required(u);
    577     ALPM_CTRL(u).force_aux_op = soc_property_get(u, "l3_alpm_force_aux_op", 0);
    578     ALPM_CTRL(u).hit_bits_skip = soc_property_get(u, spn_L3_ALPM_HIT_SKIP, 0);
    579     ALPM_CTRL(u).alpm_scaling = soc_property_get(u, "l3_alpm_scaling", 1);
    580     ALPM_CTRL(u).aux_enable = ALPM_CTRL(u).trie_propagate ?
    581                               soc_property_get(u, "l3_alpm_aux_enable", 1) : 1;
    582 
    583     /* soc_alpm_cmn_mode_get1(u); */
    584     mode = soc_property_get(u, spn_L3_ALPM_ENABLE, 0);
    585     switch (mode) {
    586         case 1:     /* Parallel mode */
    587             ALPM_CTRL(u).alpm_mode = SOC_ALPM_MODE_PARALLEL;
    588             ALPM_CTRL(u).gp_zoned = TRUE;
    589             break;
    590         case 3:     /* TCAM/ALPM mode */
    591             ALPM_CTRL(u).alpm_mode = SOC_ALPM_MODE_TCAM_ALPM;
    592             l3_alpm_ipv4_double_wide[u] = 1;
    593             ALPM_CTRL(u).gp_zoned = TRUE;
    594             break;
    595         case 2:     /* Combined mode */
    596             ALPM_CTRL(u).alpm_mode = SOC_ALPM_MODE_COMBINED;
    597             break;
    598         default:    /* LPM */
    599             ALPM_CTRL(u).alpm_mode = SOC_ALPM_MODE_INVALID;
    600             break;
    601     }
    602 
    603     /* Fetch bank number and bits */
    604     ALPM_CTRL(u).num_banks = soc_alpm_cmn_banks_get(u);
    605     for (i = 0; i < 32; i++) {
    606         if (1 << i == ALPM_CTRL(u).num_banks) {
    607             break;
    608         }
    609     }
    610     if (i < 32) {
    611         ALPM_CTRL(u).bank_bits = i;
    612     }
    613 
    614     if (ALPM_CTRL(u).num_banks == 8) {
    615         ALPM_CTRL(u).half_bkt_mode = 0;
    616     } else if (ALPM_CTRL(u).num_banks == 4) {
    617         if (SOC_IS_TRIDENT3X(u)) {
    618             ALPM_CTRL(u).half_bkt_mode = 1;
    619         } else {
    620             ALPM_CTRL(u).half_bkt_mode = 0;
    621         }
    622     } else if (ALPM_CTRL(u).num_banks == 2) {
    623         ALPM_CTRL(u).half_bkt_mode = 1;
    624     }
    625 
    626     /* Fetch bank sharing mode */
    627     if (SOC_MEM_FIELD_VALID(u, L3_DEFIPm, ALG_SUB_BKT_PTR0f)) {
    628         ALPM_CTRL(u).bkt_sharing = TRUE;
    629     }
    630 
    631     /* Bucket mask SOC_TH_ALPM_BKT_MASK */
    632     if (SOC_IS_TOMAHAWKX(u)) {
    633         ALPM_CTRL(u).bkt_mask = SOC_TH_ALPM_BKT_MASK(u);
    634         ALPM_CTRL(u).num_bkts = SOC_TH_ALPM_MAX_BKTS(u);
    635     } else if (SOC_IS_TRIDENT3X(u)) {
    636         ALPM_CTRL(u).bkt_mask = SOC_TD3_ALPM_BKT_MASK(u);
    637         ALPM_CTRL(u).num_bkts = SOC_TD3_ALPM_MAX_BKTS(u);
    638     } else if (SOC_IS_APACHE(u)) {
    639         ALPM_CTRL(u).bkt_mask = SOC_APACHE_ALPM_BKT_MASK;
    640         ALPM_CTRL(u).num_bkts = SOC_APACHE_ALPM_MAX_BKTS;
    641     } else {
    642         ALPM_CTRL(u).bkt_mask = SOC_TD2_ALPM_BKT_MASK;
    643         ALPM_CTRL(u).num_bkts = SOC_TD2_ALPM_MAX_BKTS;
    644     }
    645 
    646     ALPM_CTRL(u).bkt_bits = _shr_popcount(ALPM_CTRL(u).bkt_mask);
    647 
    648     /* Bank disable bitmap */
    649     soc_th_alpm_bank_dis(u, SOC_VRF_MAX(u) + 1,
    650         &ALPM_CTRL(u).bank_disable_bmp[0],
    651         &ALPM_CTRL(u).bank_disable_bmp_8b[0]);
    652     soc_th_alpm_bank_dis(u, 1,
    653         &ALPM_CTRL(u).bank_disable_bmp[1],
    654         &ALPM_CTRL(u).bank_disable_bmp_8b[1]);
    655 
    656     /* Double Wide */
    657     /* SOC_TH_ALPM_SCALE_CHECK1(u, ipv6) */
    658     l3_alpm_ipv4_double_wide[u] =
    659         soc_property_get(u, "l3_alpm_ipv4_double_wide", 1);
    660     if (SOC_IS_TRIDENT3X(u)) {
    661         /* Force to IPv4 Double wide mode in TD3 */
    662         l3_alpm_ipv4_double_wide[u] = 1;
    663     }
    664     for (i = 0; i <= L3_DEFIP_MODE_128; i++) {
    665         if (SOC_TH_ALPM_SCALE_CHECK(u, i)) {
    666             ALPM_CTRL(u).double_wide[i] = 1;
    667         }
    668     }
    669 
    670     /* ent_per_bank */
    671     ALPM_CTRL(u).ent_per_bank[L3_DEFIP_MODE_V4] = 6;
    672     ALPM_CTRL(u).ent_per_bank[L3_DEFIP_MODE_64] = 4;
    673     ALPM_CTRL(u).ent_per_bank[L3_DEFIP_MODE_128] = 2;
    674 
    675     /* cnt_ent_per_bkt */
    676     ALPM_CTRL(u).cnt_ent_per_bkt[L3_DEFIP_MODE_V4] =
    677         _soc_th_alpm_bkt_entry_cnt(u, L3_DEFIP_ALPM_IPV4m);
    678     ALPM_CTRL(u).cnt_ent_per_bkt[L3_DEFIP_MODE_64] =
    679         _soc_th_alpm_bkt_entry_cnt(u, L3_DEFIP_ALPM_IPV6_64m);
    680     ALPM_CTRL(u).cnt_ent_per_bkt[L3_DEFIP_MODE_128] =
    681         _soc_th_alpm_bkt_entry_cnt(u, L3_DEFIP_ALPM_IPV6_128m);
    682 
    683     /* l3_alpm_sw_prefix_lookup */
    684     if (SOC_IS_TRIDENT3X(u)) {
    685         /* Force TD3 to use sw lookup */
    686         ALPM_CTRL(u).sw_prefix_lkup = 1;
    687     } else {
    688         ALPM_CTRL(u).sw_prefix_lkup =
    689             soc_property_get(u, "l3_alpm_sw_prefix_lookup", 1);
    690     }
    691 
    692     /* Flex key
    693      * ENTRY_TYPE -> KEY_TYPE
    694      * MODE -> KEY_MODE
    695      */
    696     if (SOC_MEM_FIELD_VALID(u, L3_DEFIPm, KEY_TYPE0f)) {
    697         ALPM_CTRL(u).fld.key_mode0              = KEY_MODE0f;
    698         ALPM_CTRL(u).fld.key_mode1              = KEY_MODE1f;
    699         ALPM_CTRL(u).fld.key_mode_mask0         = KEY_MODE_MASK0f;
    700         ALPM_CTRL(u).fld.key_mode_mask1         = KEY_MODE_MASK1f;
    701         ALPM_CTRL(u).fld.key_type0              = KEY_TYPE0f;
    702         ALPM_CTRL(u).fld.key_type1              = KEY_TYPE1f;
    703         ALPM_CTRL(u).fld.key_type_mask0         = KEY_TYPE_MASK0f;
    704         ALPM_CTRL(u).fld.key_type_mask1         = KEY_TYPE_MASK1f;
    705         ALPM_CTRL(u).fld.key_mode0_upr          = KEY_MODE0_UPRf;
    706         ALPM_CTRL(u).fld.key_mode0_lwr          = KEY_MODE0_LWRf;
    707         ALPM_CTRL(u).fld.key_mode1_upr          = KEY_MODE1_UPRf;
    708         ALPM_CTRL(u).fld.key_mode1_lwr          = KEY_MODE1_LWRf;
    709         ALPM_CTRL(u).fld.key_mode_mask0_upr     = KEY_MODE_MASK0_UPRf;
    710         ALPM_CTRL(u).fld.key_mode_mask0_lwr     = KEY_MODE_MASK0_LWRf;
    711         ALPM_CTRL(u).fld.key_mode_mask1_upr     = KEY_MODE_MASK1_UPRf;
    712         ALPM_CTRL(u).fld.key_mode_mask1_lwr     = KEY_MODE_MASK1_LWRf;
    713         ALPM_CTRL(u).fld.key_type0_upr          = KEY_TYPE0_UPRf;
    714         ALPM_CTRL(u).fld.key_type0_lwr          = KEY_TYPE0_LWRf;
    715         ALPM_CTRL(u).fld.key_type1_upr          = KEY_TYPE1_UPRf;
    716         ALPM_CTRL(u).fld.key_type1_lwr          = KEY_TYPE1_LWRf;
    717         ALPM_CTRL(u).fld.key_type_mask0_upr     = KEY_TYPE_MASK0_UPRf;
    718         ALPM_CTRL(u).fld.key_type_mask0_lwr     = KEY_TYPE_MASK0_LWRf;
    719         ALPM_CTRL(u).fld.key_type_mask1_upr     = KEY_TYPE_MASK1_UPRf;
    720         ALPM_CTRL(u).fld.key_type_mask1_lwr     = KEY_TYPE_MASK1_LWRf;
    721         ALPM_CTRL(u).fld.key_mode               = KEY_MODEf;
    722         ALPM_CTRL(u).fld.key_type               = KEY_TYPEf;
    723     } else {
    724         ALPM_CTRL(u).fld.key_mode0              = MODE0f;
    725         ALPM_CTRL(u).fld.key_mode1              = MODE1f;
    726         ALPM_CTRL(u).fld.key_mode_mask0         = MODE_MASK0f;
    727         ALPM_CTRL(u).fld.key_mode_mask1         = MODE_MASK1f;
    728         ALPM_CTRL(u).fld.key_type0              = ENTRY_TYPE0f;
    729         ALPM_CTRL(u).fld.key_type1              = ENTRY_TYPE1f;
    730         ALPM_CTRL(u).fld.key_type_mask0         = ENTRY_TYPE_MASK0f;
    731         ALPM_CTRL(u).fld.key_type_mask1         = ENTRY_TYPE_MASK1f;
    732         ALPM_CTRL(u).fld.key_mode0_upr          = MODE0_UPRf;
    733         ALPM_CTRL(u).fld.key_mode0_lwr          = MODE0_LWRf;
    734         ALPM_CTRL(u).fld.key_mode1_upr          = MODE1_UPRf;
    735         ALPM_CTRL(u).fld.key_mode1_lwr          = MODE1_LWRf;
    736         ALPM_CTRL(u).fld.key_mode_mask0_upr     = MODE_MASK0_UPRf;
    737         ALPM_CTRL(u).fld.key_mode_mask0_lwr     = MODE_MASK0_LWRf;
    738         ALPM_CTRL(u).fld.key_mode_mask1_upr     = MODE_MASK1_UPRf;
    739         ALPM_CTRL(u).fld.key_mode_mask1_lwr     = MODE_MASK1_LWRf;
    740         ALPM_CTRL(u).fld.key_type0_upr          = ENTRY_TYPE0_UPRf;
    741         ALPM_CTRL(u).fld.key_type0_lwr          = ENTRY_TYPE0_LWRf;
    742         ALPM_CTRL(u).fld.key_type1_upr          = ENTRY_TYPE1_UPRf;
    743         ALPM_CTRL(u).fld.key_type1_lwr          = ENTRY_TYPE1_LWRf;
    744         ALPM_CTRL(u).fld.key_type_mask0_upr     = ENTRY_TYPE_MASK0_UPRf;
    745         ALPM_CTRL(u).fld.key_type_mask0_lwr     = ENTRY_TYPE_MASK0_LWRf;
    746         ALPM_CTRL(u).fld.key_type_mask1_upr     = ENTRY_TYPE_MASK1_UPRf;
    747         ALPM_CTRL(u).fld.key_type_mask1_lwr     = ENTRY_TYPE_MASK1_LWRf;
    748         ALPM_CTRL(u).fld.key_mode               = MODEf;
    749         ALPM_CTRL(u).fld.key_type               = ENTRY_TYPEf;
    750     }
    751     ALPM_CTRL(u)._alpm_128b = SOC_ALPM_128B_ENABLE(u);
    752     if (ALPM_CTRL(u)._alpm_128b) {
    753         ALPM_CTRL(u)._alpm_128b_bkt_rsvd =
    754             soc_property_get(u, spn_L3_ALPM_IPV6_128B_BKT_RSVD, 0);
    755         if (ALPM_CTRL(u)._alpm_128b_bkt_rsvd) {
    756             ALPM_CTRL(u)._alpm_128b_bkt_rsvd_cnt = SOC_L3_DEFIP_MAX_128B_ENTRIES(u);
    757         }
    758     }
    759 
    760     ALPM_CTRL(u).ctrl_inited = 1;
    761     return SOC_E_NONE;
    762 }
    763 
    764 STATIC int
    765 _soc_th_alpm_sw_propagate(int u, trie_t *pivot, void *prefix, uint32 len,
    766                           int insert, void *cb, void *user_data)
    767 {
    768     int rv = SOC_E_NONE;
    769     uint32 pivot_len = 0;
    770     trie_node_t *lpm_pvt = NULL;
    771     trie_bpm_cb_info_t cb_info;
    772 
    773     cb_info.pfx = (void *)prefix;
    774     cb_info.len = len;
    775     cb_info.user_data = user_data;
    776 
    777     /* Find longest prefix match(pivot) of route */
    778     SOC_IF_ERROR_RETURN(trie_find_lpm(pivot, prefix, len, &lpm_pvt));
    779     pivot_len = (TRIE_ELEMENT_GET(payload_t *, lpm_pvt, node))->len;
    780 
    781     if (ALPM_CTRL(u).trie_user_ppg) {
    782         if (pivot->v6_key) {
    783             rv = pvt_trie_v6_propagate_prefix(lpm_pvt, pivot_len,
    784                     (void *)prefix, len, cb, &cb_info);
    785         } else {
    786             rv = pvt_trie_propagate_prefix(lpm_pvt, pivot_len,
    787                     (void *)prefix, len, cb, &cb_info);
    788         }
    789     } else {
    790         if (pivot->v6_key) {
    791             rv = trie_v6_pivot_propagate_prefix(lpm_pvt, pivot_len,
    792                     (void *)prefix, len, insert, cb, &cb_info);
    793         } else {
    794             rv = trie_pivot_propagate_prefix(lpm_pvt, pivot_len,
    795                     (void *)prefix, len, insert, cb, &cb_info);
    796         }
    797     }
    798 
    799     return rv;
    800 }
    801 
    802 /* Perform an ALPM mem read operation during sw propagation */
    803 STATIC int
    804 _soc_th_mem_alpm_read_on_sw_propagate(int unit, soc_mem_t mem, int copyno,
    805                                       int index, void *entry_data)
    806 {
    807     int rv = SOC_E_NONE;
    808 
    809     if (ALPM_CTRL(unit).aux_enable) {
    810         rv = _soc_mem_alpm_read_cache(unit, mem,copyno, index, entry_data);
    811     } else {
    812         rv = _soc_mem_alpm_read(unit, mem,copyno, index, entry_data);
    813     }
    814 
    815     return rv;
    816 }
    817 
    818 /* Perform an ALPM mem write operation during sw propagation */
    819 STATIC int
    820 _soc_th_mem_alpm_write_on_sw_propagate(int unit, soc_mem_t mem, int copyno,
    821                                        int index, void *entry_data)
    822 {
    823     int rv = SOC_E_NONE;
    824 
    825     if (ALPM_CTRL(unit).aux_enable) {
    826         _soc_mem_alpm_write_cache(unit, mem, copyno, index, entry_data);
    827     } else {
    828         rv = soc_mem_write(unit, mem, copyno, index, entry_data);
    829     }
    830 
    831     return rv;
    832 }
    833 
    834 STATIC int
    835 _soc_th_alpm_hit_bits_callback(trie_node_t *trie, trie_bpm_cb_info_t *info)
    836 {
    837     int rv, unit, ipv6;
    838     trie_bpm_cb_user_data_t *user_data;
    839     alpm_pivot_t *pivot_pyld;
    840     int tcam_index, lpm_index, hit_idx;
    841     uint32 pvt_bpm_len, pfx_len;
    842 
    843     user_data = info->user_data;
    844     unit = user_data->unit;
    845     ipv6 = user_data->ipv6;
    846     pfx_len = user_data->pfx_len;
    847     user_data->count++;
    848 
    849     pivot_pyld = (alpm_pivot_t *)trie;
    850     tcam_index = PIVOT_TCAM_INDEX(pivot_pyld);
    851     pvt_bpm_len = PIVOT_TCAM_BPMLEN(pivot_pyld);
    852 
    853     if (ALPM_CTRL(unit).trie_user_ppg) {
    854         /* Addr & Mask has been screened by propagate function,
    855          * no need to do it again */
    856         if (user_data->aux_op == INSERT_PROPAGATE) {
    857             if (pvt_bpm_len > pfx_len) {
    858                 /* Not qualified */
    859                 return SOC_E_LIMIT;
    860             }
    861         }
    862 
    863         if (user_data->aux_op == DELETE_PROPAGATE) {
    864             if (pvt_bpm_len != pfx_len) {
    865                 /* Not qualified */
    866                 return (pvt_bpm_len > pfx_len) ? SOC_E_LIMIT : SOC_E_NONE;
    867             }
    868         }
    869     }
    870 
    871     if (ipv6 == L3_DEFIP_MODE_V4 || ipv6 == L3_DEFIP_MODE_64) {
    872         soc_mem_t lpm_mem = L3_DEFIPm;
    873         defip_entry_t lpm_entry;
    874 
    875         /* Update L3_DEFIPm */
    876         lpm_index = soc_th_alpm_logical_idx(unit, lpm_mem, tcam_index >> 1, 1);
    877 
    878         LOG_INFO(BSL_LS_SOC_ALPM,
    879              (BSL_META_U(unit, "ALPM SW hit cb: lpm_mem %s index %d ent %d\n"),
    880              SOC_MEM_NAME(unit, lpm_mem), lpm_index, (tcam_index & 1)));
    881 
    882         soc_mem_lock(unit, lpm_mem);
    883 
    884         rv = _soc_th_mem_alpm_read_on_sw_propagate(
    885                  unit, lpm_mem, MEM_BLOCK_ANY, lpm_index, &lpm_entry);
    886         if (SOC_SUCCESS(rv)) {
    887             if (ipv6 == L3_DEFIP_MODE_64) { /* IPv6_64 */
    888                 hit_idx = soc_mem_field32_get(unit, lpm_mem,
    889                             (uint32 *)&lpm_entry, ALG_HIT_IDX0f);
    890                 if (hit_idx == user_data->old_idx) {
    891                     soc_mem_field32_set(unit, lpm_mem, (uint32 *)&lpm_entry,
    892                         ALG_HIT_IDX0f, user_data->new_idx);
    893                     /* Hardware doesn't update ALG_HIT_IDX1f for IPv6-64
    894                     soc_mem_field32_set(unit, lpm_mem, (uint32 *)&lpm_entry,
    895                         ALG_HIT_IDX1f, user_data->new_idx);
    896                      */
    897                 }
    898             } else { /* IPv4 */
    899                 soc_field_t hit_fld = (tcam_index & 1) ?
    900                                          ALG_HIT_IDX1f :
    901                                          ALG_HIT_IDX0f;
    902 
    903                 hit_idx = soc_mem_field32_get(unit, lpm_mem,
    904                             (uint32 *)&lpm_entry, hit_fld);
    905                 if (hit_idx == user_data->old_idx) {
    906                     soc_mem_field32_set(unit, lpm_mem, (uint32 *)&lpm_entry,
    907                         hit_fld, user_data->new_idx);
    908                 }
    909             }
    910             (void) _soc_th_mem_alpm_write_on_sw_propagate(
    911                        unit, lpm_mem, MEM_BLOCK_ALL, lpm_index, &lpm_entry);
    912 
    913             if (SOC_URPF_STATUS_GET(unit)) {
    914                 lpm_index += (soc_mem_index_count(unit, lpm_mem) >> 1);
    915                 rv = _soc_th_mem_alpm_read_on_sw_propagate(
    916                          unit, lpm_mem, MEM_BLOCK_ANY, lpm_index, &lpm_entry);
    917                 if (SOC_SUCCESS(rv)) {
    918                     if (ipv6 == L3_DEFIP_MODE_64) {
    919                         soc_mem_field32_set(unit, lpm_mem, (uint32 *)&lpm_entry,
    920                             ALG_HIT_IDX0f,
    921                             _soc_th_alpm_rpf_entry(unit, user_data->new_idx));
    922                         /* Hardware doesn't update ALG_HIT_IDX1f for IPv6-64
    923                         soc_mem_field32_set(unit, lpm_mem, (uint32 *)&lpm_entry,
    924                             ALG_HIT_IDX1f,
    925                             _soc_th_alpm_rpf_entry(unit, user_data->new_idx));
    926                          */
    927                     } else {
    928                         soc_field_t hit_fld = (tcam_index & 1) ?
    929                                                  ALG_HIT_IDX1f :
    930                                                  ALG_HIT_IDX0f;
    931                         soc_mem_field32_set(unit, lpm_mem, (uint32 *)&lpm_entry,
    932                             hit_fld,
    933                             _soc_th_alpm_rpf_entry(unit, user_data->new_idx));
    934                     }
    935                     (void) _soc_th_mem_alpm_write_on_sw_propagate(
    936                                unit, lpm_mem, MEM_BLOCK_ALL,
    937                                lpm_index, &lpm_entry);
    938                 }
    939             }
    940         }
    941         soc_mem_unlock(unit, lpm_mem);
    942     } else if (ipv6 == L3_DEFIP_MODE_128) {
    943         soc_mem_t lpm128_mem = L3_DEFIP_PAIR_128m;
    944         defip_pair_128_entry_t lpm128_entry;
    945 
    946         lpm_index = soc_th_alpm_logical_idx(unit, lpm128_mem,
    947                         SOC_ALPM_128_DEFIP_TO_PAIR(unit, tcam_index >> 1), 1);
    948 
    949         /* Update L3_DEFIP_PAIR_128m */
    950         soc_mem_lock(unit, lpm128_mem);
    951         rv = _soc_th_mem_alpm_read_on_sw_propagate(
    952                  unit, lpm128_mem, MEM_BLOCK_ANY, lpm_index, &lpm128_entry);
    953         if (SOC_SUCCESS(rv)) {
    954             hit_idx = soc_mem_field32_get(unit, lpm128_mem,
    955                         (uint32 *)&lpm128_entry, ALG_HIT_IDXf);
    956             if (hit_idx == user_data->old_idx) {
    957                 soc_mem_field32_set(unit, lpm128_mem, (uint32 *)&lpm128_entry,
    958                                     ALG_HIT_IDXf, user_data->new_idx);
    959             }
    960             (void) _soc_th_mem_alpm_write_on_sw_propagate(
    961                        unit, lpm128_mem, MEM_BLOCK_ALL,
    962                        lpm_index, &lpm128_entry);
    963             if (SOC_URPF_STATUS_GET(unit)) {
    964                 lpm_index += (soc_mem_index_count(unit, lpm128_mem) >> 1);
    965                 rv = _soc_th_mem_alpm_read_on_sw_propagate(
    966                          unit, lpm128_mem, MEM_BLOCK_ANY,
    967                          lpm_index, &lpm128_entry);
    968                 if (SOC_SUCCESS(rv)) {
    969                     soc_mem_field32_set(
    970                         unit, lpm128_mem, (uint32 *)&lpm128_entry, ALG_HIT_IDXf,
    971                         _soc_th_alpm_rpf_entry(unit, user_data->new_idx));
    972                     (void) _soc_th_mem_alpm_write_on_sw_propagate(
    973                                unit, lpm128_mem, MEM_BLOCK_ALL,
    974                                lpm_index, &lpm128_entry);
    975                 }
    976             }
    977         }
    978         soc_mem_unlock(unit, lpm128_mem);
    979 
    980         LOG_INFO(BSL_LS_SOC_ALPM,
    981              (BSL_META_U(unit, "ALPM SW hit cb: lpm_mem %s index %d\n"),
    982              SOC_MEM_NAME(unit, lpm128_mem), lpm_index));
    983     } else {
    984         return SOC_E_INTERNAL;
    985     }
    986 
    987     return SOC_E_NONE;
    988 
    989 }
    990 
    991 /* Update L3_DEFIP_* memory cache when cache is on */
    992 STATIC int
    993 _soc_th_alpm_hit_bits_sw_update(int u, alpm_mem_prefix_array_t *pa,
    994                                 int *new_idx, int *match_num,
    995                                 int ipv6, int vrf)
    996 {
    997     int rv = SOC_E_NONE;
    998     int i, count;
    999     payload_t *pfx = NULL;
   1000     trie_t *pivot = NULL;
   1001     trie_bpm_cb_user_data_t user_data;
   1002 
   1003     count = pa->count;
   1004     if (ipv6 == L3_DEFIP_MODE_V4) {
   1005         pivot = VRF_PIVOT_TRIE_IPV4(u, vrf);
   1006     } else if (ipv6 == L3_DEFIP_MODE_64) {
   1007         pivot = VRF_PIVOT_TRIE_IPV6(u, vrf);
   1008     } else if (ipv6 == L3_DEFIP_MODE_128) {
   1009         pivot = VRF_PIVOT_TRIE_IPV6_128(u, vrf);
   1010     } else {
   1011         return SOC_E_INTERNAL;
   1012     }
   1013 
   1014     sal_memset(&user_data, 0, sizeof(user_data));
   1015     user_data.unit      = u;
   1016     user_data.aux_op    = INSERT_PROPAGATE;
   1017 
   1018     for (i = 0; i < count; i++) {
   1019         pfx = pa->prefix[i];
   1020         if (pfx->index <= 0) {
   1021             continue;
   1022         }
   1023         user_data.old_idx = pfx->index;
   1024         user_data.new_idx = new_idx[i];
   1025         user_data.ipv6    = ipv6;
   1026         user_data.pfx_len = pfx->len;
   1027         /* hit bits update are only required for insert case */
   1028         rv = _soc_th_alpm_sw_propagate(u, pivot, pfx->key, pfx->len,
   1029                 0, _soc_th_alpm_hit_bits_callback, &user_data);
   1030         if (rv < 0) {
   1031             break;
   1032         }
   1033     }
   1034 
   1035     _alpm_dbg_cntr[u].ppg_cb_hitbit += user_data.count;
   1036     if (match_num != NULL) {
   1037         *match_num = user_data.count;
   1038     }
   1039 
   1040     return rv;
   1041 }
   1042 
   1043 STATIC int
   1044 _soc_th_alpm_propagate_callback(trie_node_t *trie,
   1045                                 trie_bpm_cb_info_t *info)
   1046 {
   1047     int rv = SOC_E_NONE;
   1048     int i, unit, mode;
   1049     trie_bpm_cb_user_data_t *user_data;
   1050     void *aux_entry;
   1051     alpm_pivot_t *pivot_pyld;
   1052     int tcam_index, lpm_index, aux_index;
   1053     int aux_flags;
   1054 
   1055     /* use memory size to declear replace_data field value */
   1056     defip_aux_scratch_entry_t replace_data;
   1057     soc_mem_t aux_mem = L3_DEFIP_AUX_SCRATCHm;
   1058 
   1059     /* L3_DEFIP_AUX_TABLE variables */
   1060     defip_aux_table_entry_t shadow_entry;
   1061     uint32 pfx_len, rpl_bpm_len, pvt_bpm_len, hit_idx;
   1062 
   1063 #define _URPF_INDEX(urpf, index, mem) \
   1064     (urpf ? (index + (soc_mem_index_count(unit, mem) >> 1)) : index)
   1065 
   1066     user_data = info->user_data;
   1067     unit = user_data->unit;
   1068     aux_entry = user_data->entry;
   1069     aux_flags = user_data->flags;
   1070 
   1071     /* For uRPF case, DB_TYPE is odd, see soc_alpm_db_ent_type_encoding */
   1072     if (soc_mem_field32_get(unit, aux_mem, aux_entry, DB_TYPEf) & 0x1) {
   1073         return SOC_E_NONE;
   1074     }
   1075 
   1076     pivot_pyld = (alpm_pivot_t *)trie;
   1077     pvt_bpm_len = PIVOT_TCAM_BPMLEN(pivot_pyld);
   1078     pfx_len = soc_mem_field32_get(unit, aux_mem, aux_entry, IP_LENGTHf);
   1079     rpl_bpm_len = soc_mem_field32_get(unit, aux_mem, aux_entry, REPLACE_LENf);
   1080     if (user_data->aux_op == INSERT_PROPAGATE) {
   1081         rpl_bpm_len = pfx_len;
   1082     }
   1083 
   1084     if (ALPM_CTRL(unit).trie_user_ppg) {
   1085         /* Addr & Mask has been screened by propagate function,
   1086          * no need to do it again */
   1087         if (user_data->aux_op == INSERT_PROPAGATE) {
   1088             if (pvt_bpm_len > pfx_len) {
   1089                 /* Not qualified */
   1090                 return SOC_E_LIMIT;
   1091             }
   1092         }
   1093 
   1094         if (user_data->aux_op == DELETE_PROPAGATE) {
   1095             if (pvt_bpm_len != pfx_len) {
   1096                 /* Not qualified */
   1097                 return (pvt_bpm_len > pfx_len) ? SOC_E_LIMIT : SOC_E_NONE;
   1098             }
   1099         }
   1100     }
   1101 
   1102     /* Update bpm length accordingly */
   1103     PIVOT_TCAM_BPMLEN(pivot_pyld) = rpl_bpm_len;
   1104 
   1105     /* update callback count, hw propagate is counting on this */
   1106     user_data->count ++;
   1107 
   1108     sal_memset(&replace_data, 0, sizeof(replace_data));
   1109     soc_mem_field_get(unit, aux_mem, aux_entry, REPLACE_DATAf,
   1110                       (uint32 *)&replace_data);
   1111     hit_idx = soc_mem_field32_get(unit, aux_mem, aux_entry, ALG_HIT_IDXf);
   1112     if (hit_idx > 0) {
   1113         hit_idx = _soc_th_alpm_rpf_entry(unit, hit_idx);
   1114     }
   1115     mode = soc_mem_field32_get(unit, aux_mem, aux_entry, MODE_f(unit));
   1116 
   1117     tcam_index = PIVOT_TCAM_INDEX(pivot_pyld);
   1118     if (mode == 0 || mode == 1) {
   1119         soc_mem_t lpm_mem = L3_DEFIPm;
   1120         defip_entry_t lpm_entry;
   1121 
   1122         /* Update L3_DEFIPm */
   1123         lpm_index = soc_th_alpm_logical_idx(unit, lpm_mem, tcam_index >> 1, 1);
   1124         aux_index = tcam_index >> 1;
   1125 
   1126         LOG_INFO(BSL_LS_SOC_ALPM,
   1127             (BSL_META_U(unit, "ALPM SW %s ppg cb: lpm_mem %s index %d ent %d,"
   1128             "AUX_TABLE index %d\n"),
   1129             (user_data->aux_op == INSERT_PROPAGATE) ? "Add" : "Del",
   1130             SOC_MEM_NAME(unit, lpm_mem), lpm_index,
   1131             (tcam_index & 1), aux_index));
   1132 
   1133         soc_mem_lock(unit, lpm_mem);
   1134         rv = _soc_th_mem_alpm_read_on_sw_propagate(
   1135                  unit, lpm_mem, MEM_BLOCK_ANY, lpm_index, &lpm_entry);
   1136         if (SOC_SUCCESS(rv)) {
   1137             if (mode == 1) {
   1138                 /* IPv6_64 */
   1139                 soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry,
   1140                     REPLACE_DATA0f, (uint32 *)&replace_data);
   1141                 /* Hardware doesn't update entry1 for IPv6-64
   1142                 soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry,
   1143                     REPLACE_DATA1f, (uint32 *)&replace_data);
   1144                  */
   1145             } else {
   1146                 /* IPv4 */
   1147                 soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry,
   1148                     (tcam_index & 1) ? REPLACE_DATA1f : REPLACE_DATA0f,
   1149                     (uint32 *)&replace_data);
   1150             }
   1151             (void) _soc_th_mem_alpm_write_on_sw_propagate(
   1152                        unit, lpm_mem, MEM_BLOCK_ALL, lpm_index, &lpm_entry);
   1153             if (SOC_URPF_STATUS_GET(unit)) {
   1154                 lpm_index = _URPF_INDEX(TRUE, lpm_index, L3_DEFIPm);
   1155                 rv = _soc_th_mem_alpm_read_on_sw_propagate(
   1156                         unit, lpm_mem, MEM_BLOCK_ANY, lpm_index, &lpm_entry);
   1157                 if (SOC_SUCCESS(rv)) {
   1158                     if (mode == 1) {
   1159                         soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry,
   1160                             REPLACE_DATA0f, (uint32 *)&replace_data);
   1161                         soc_mem_field32_set(unit, lpm_mem, &lpm_entry,
   1162                             RPE0f, (aux_flags & SOC_ALPM_AUX_DEF_ROUTE) ? 1 : 0);
   1163                         soc_mem_field32_set(unit, lpm_mem, &lpm_entry,
   1164                             ALG_HIT_IDX0f, hit_idx);
   1165                         soc_mem_field32_set(unit, lpm_mem,
   1166                             &lpm_entry, SRC_DISCARD0f,
   1167                             (aux_flags & SOC_ALPM_AUX_SRC_DISCARD) ? 1 : 0);
   1168                         /* Hardware doesn't update entry1 for IPv6-64
   1169                         soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry,
   1170                             REPLACE_DATA1f, (uint32 *)&replace_data);
   1171                         soc_mem_field32_set(unit, lpm_mem, &lpm_entry,
   1172                             RPE1f, pfx_len == 0 ? 1 : 0);
   1173                         soc_mem_field32_set(unit, lpm_mem, &lpm_entry,
   1174                             ALG_HIT_IDX1f, hit_idx);
   1175                         */
   1176                     } else {
   1177                         soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry,
   1178                             (tcam_index & 1) ? REPLACE_DATA1f : REPLACE_DATA0f,
   1179                             (uint32 *)&replace_data);
   1180                         soc_mem_field32_set(unit, lpm_mem, &lpm_entry,
   1181                             (tcam_index & 1) ? RPE1f : RPE0f,
   1182                             (aux_flags & SOC_ALPM_AUX_DEF_ROUTE) ? 1 : 0);
   1183                         soc_mem_field32_set(unit, lpm_mem, &lpm_entry,
   1184                             (tcam_index & 1) ? ALG_HIT_IDX1f : ALG_HIT_IDX0f,
   1185                             hit_idx);
   1186                         soc_mem_field32_set(unit, lpm_mem, &lpm_entry,
   1187                             (tcam_index & 1) ? SRC_DISCARD1f : SRC_DISCARD0f,
   1188                             (aux_flags & SOC_ALPM_AUX_SRC_DISCARD) ? 1 : 0);
   1189                     }
   1190                     (void) _soc_th_mem_alpm_write_on_sw_propagate(
   1191                                unit, lpm_mem, MEM_BLOCK_ALL,
   1192                                lpm_index, &lpm_entry);
   1193                 }
   1194             }
   1195         }
   1196         soc_mem_unlock(unit, lpm_mem);
   1197 
   1198         /* Do not update L3_DEFIP_AUX_TABLEm if aux table is disabled */
   1199         if (!ALPM_CTRL(unit).aux_enable) {
   1200             return SOC_E_NONE;
   1201         }
   1202 
   1203         /* Update L3_DEFIP_AUX_TABLEm */
   1204         lpm_mem = L3_DEFIP_AUX_TABLEm;
   1205 
   1206         soc_mem_lock(unit, lpm_mem);
   1207         rv = _soc_th_mem_alpm_read_on_sw_propagate(
   1208                  unit, lpm_mem, MEM_BLOCK_ANY, aux_index, &shadow_entry);
   1209         if (SOC_SUCCESS(rv)) {
   1210             if (mode == 1) { /* IPv6_64 */
   1211                 soc_mem_field32_set(unit, lpm_mem, &shadow_entry,
   1212                     BPM_LENGTH0f, rpl_bpm_len);
   1213                 soc_mem_field32_set(unit, lpm_mem, &shadow_entry,
   1214                     BPM_LENGTH1f, rpl_bpm_len);
   1215             } else { /* IPv4 */
   1216                 soc_mem_field32_set(unit, lpm_mem, &shadow_entry,
   1217                     (tcam_index & 1) ? BPM_LENGTH1f : BPM_LENGTH0f,
   1218                     rpl_bpm_len);
   1219             }
   1220             (void) _soc_th_mem_alpm_write_on_sw_propagate(
   1221                        unit, lpm_mem, MEM_BLOCK_ALL, aux_index, &shadow_entry);
   1222             if (SOC_URPF_STATUS_GET(unit)) {
   1223                 aux_index = _URPF_INDEX(TRUE, aux_index, L3_DEFIP_AUX_TABLEm);
   1224                 rv = _soc_th_mem_alpm_read_on_sw_propagate(
   1225                          unit, lpm_mem, MEM_BLOCK_ANY, aux_index, &shadow_entry);
   1226                 if (SOC_SUCCESS(rv)) {
   1227                     if (mode == 1) { /* IPv6_64 */
   1228                         soc_mem_field32_set(unit, lpm_mem, &shadow_entry,
   1229                             BPM_LENGTH0f, rpl_bpm_len);
   1230                         soc_mem_field32_set(unit, lpm_mem, &shadow_entry,
   1231                             BPM_LENGTH1f, rpl_bpm_len);
   1232                     } else { /* IPv4 */
   1233                         soc_mem_field32_set(unit, lpm_mem, &shadow_entry,
   1234                             (tcam_index & 1) ? BPM_LENGTH1f : BPM_LENGTH0f,
   1235                             rpl_bpm_len);
   1236                     }
   1237                     (void) _soc_th_mem_alpm_write_on_sw_propagate(
   1238                                unit, lpm_mem, MEM_BLOCK_ALL,
   1239                                aux_index, &shadow_entry);
   1240                 }
   1241             }
   1242         }
   1243         soc_mem_unlock(unit, lpm_mem);
   1244 
   1245     } else if (mode == 3) {
   1246         soc_mem_t lpm128_mem = L3_DEFIP_PAIR_128m;
   1247         defip_pair_128_entry_t lpm128_entry;
   1248 
   1249         lpm_index = soc_th_alpm_logical_idx(unit, L3_DEFIP_PAIR_128m,
   1250                         SOC_ALPM_128_DEFIP_TO_PAIR(unit, tcam_index >> 1), 1);
   1251         aux_index = SOC_ALPM_128_DEFIP_TO_PAIR(unit, tcam_index >> 1);
   1252         LOG_INFO(BSL_LS_SOC_ALPM,
   1253             (BSL_META_U(unit, "ALPM SW %s ppg cb: lpm_mem %s index %d, "
   1254             "AUX_TABLE index0 %d index1 %d\n"),
   1255             (user_data->aux_op == INSERT_PROPAGATE) ? "Add" : "Del",
   1256             SOC_MEM_NAME(unit, lpm128_mem), lpm_index,
   1257             SOC_ALPM_128_ADDR_LWR(unit, aux_index),
   1258             SOC_ALPM_128_ADDR_UPR(unit, aux_index)));
   1259 
   1260         /* Update L3_DEFIP_PAIR_128m */
   1261         soc_mem_lock(unit, lpm128_mem);
   1262         rv = _soc_th_mem_alpm_read_on_sw_propagate(
   1263                  unit, lpm128_mem, MEM_BLOCK_ANY, lpm_index, &lpm128_entry);
   1264         if (SOC_SUCCESS(rv)) {
   1265             soc_mem_field_set(unit, lpm128_mem, (uint32 *)&lpm128_entry,
   1266                 REPLACE_DATAf, (uint32 *)&replace_data);
   1267             (void) _soc_th_mem_alpm_write_on_sw_propagate(
   1268                        unit, lpm128_mem, MEM_BLOCK_ALL,
   1269                        lpm_index, &lpm128_entry);
   1270             if (SOC_URPF_STATUS_GET(unit)) {
   1271                 lpm_index = _URPF_INDEX(TRUE, lpm_index, L3_DEFIP_PAIR_128m);
   1272                 rv = _soc_th_mem_alpm_read_on_sw_propagate(
   1273                          unit, lpm128_mem, MEM_BLOCK_ANY,
   1274                          lpm_index, &lpm128_entry);
   1275                 if (SOC_SUCCESS(rv)) {
   1276                     soc_mem_field_set(unit, lpm128_mem, (uint32 *)&lpm128_entry,
   1277                         REPLACE_DATAf, (uint32 *)&replace_data);
   1278                     soc_mem_field32_set(unit, lpm128_mem, &lpm128_entry,
   1279                         RPEf, (aux_flags & SOC_ALPM_AUX_DEF_ROUTE) ? 1 : 0);
   1280                     soc_mem_field32_set(unit, lpm128_mem, &lpm128_entry,
   1281                         ALG_HIT_IDXf, hit_idx);
   1282                     soc_mem_field32_set(unit, lpm128_mem,
   1283                         &lpm128_entry, SRC_DISCARDf,
   1284                         (aux_flags & SOC_ALPM_AUX_SRC_DISCARD) ? 1 : 0);
   1285                     (void) _soc_th_mem_alpm_write_on_sw_propagate(
   1286                                unit, lpm128_mem, MEM_BLOCK_ALL,
   1287                                lpm_index, &lpm128_entry);
   1288 
   1289                 }
   1290             }
   1291         }
   1292         soc_mem_unlock(unit, lpm128_mem);
   1293 
   1294         /* Do not update L3_DEFIP_AUX_TABLEm if aux table is disabled */
   1295         if (!ALPM_CTRL(unit).aux_enable) {
   1296             return SOC_E_NONE;
   1297         }
   1298 
   1299         /* Update L3_DEFIP_AUX_TABLEm */
   1300         lpm128_mem = L3_DEFIP_AUX_TABLEm;
   1301 
   1302         soc_mem_lock(unit, lpm128_mem);
   1303         /* Needs to update 2 AUX_TABLE entries */
   1304         for (i = 0; i < 2; i++) {
   1305             int index;
   1306             index = ((i == 0) ?
   1307                      SOC_ALPM_128_ADDR_LWR(unit, aux_index) :
   1308                      SOC_ALPM_128_ADDR_UPR(unit, aux_index));
   1309             rv = _soc_th_mem_alpm_read_on_sw_propagate(
   1310                      unit, lpm128_mem, MEM_BLOCK_ANY, index, &shadow_entry);
   1311             if (SOC_SUCCESS(rv)) {
   1312                 soc_mem_field32_set(unit, lpm128_mem, &shadow_entry,
   1313                     BPM_LENGTH0f, rpl_bpm_len);
   1314                 soc_mem_field32_set(unit, lpm128_mem, &shadow_entry,
   1315                     BPM_LENGTH1f, rpl_bpm_len);
   1316                 (void) _soc_th_mem_alpm_write_on_sw_propagate(
   1317                            unit, lpm128_mem, MEM_BLOCK_ALL,
   1318                            index, &shadow_entry);
   1319                 if (SOC_URPF_STATUS_GET(unit)) {
   1320                     index = _URPF_INDEX(TRUE, index, lpm128_mem);
   1321                     rv = _soc_th_mem_alpm_read_on_sw_propagate(
   1322                              unit, lpm128_mem, MEM_BLOCK_ANY,
   1323                              index, &shadow_entry);
   1324                     if (SOC_SUCCESS(rv)) {
   1325                         soc_mem_field32_set(unit, lpm128_mem, &shadow_entry,
   1326                             BPM_LENGTH0f, rpl_bpm_len);
   1327                         soc_mem_field32_set(unit, lpm128_mem, &shadow_entry,
   1328                             BPM_LENGTH1f, rpl_bpm_len);
   1329                         (void) _soc_th_mem_alpm_write_on_sw_propagate(
   1330                                    unit, lpm128_mem, MEM_BLOCK_ALL,
   1331                                    index, &shadow_entry);
   1332                     }
   1333                 }
   1334             }
   1335         }
   1336         soc_mem_unlock(unit, lpm128_mem);
   1337     } else {
   1338         return SOC_E_INTERNAL;
   1339     }
   1340 
   1341     return SOC_E_NONE;
   1342 }
   1343 
   1344 /*
   1345  * ipv4:     ip6_word[4] =
   1346  *               {IP_ADDR0f, 0, 0, 0}
   1347  * ipv6-64:  ip6_word[4] =
   1348  *               {0, 0, IP_ADDR0f, IP_ADDR1f}
   1349  * ipv6-128: ip6_word[4] =
   1350  *               {IP_ADDR0_LWRf, IP_ADDR1_LWRf, IP_ADDR0_UPRf, IP_ADDR1_UPRf}
   1351  */
   1352 STATIC void
   1353 _soc_th_alpm_trie_prefix_create(int u, int mode, uint32 *ip6_word, uint32 len,
   1354                                 uint32 *pfx)
   1355 {
   1356     int i;
   1357     uint32 pfx_shift, tmp;
   1358 
   1359     pfx[0] = pfx[1] = pfx[2] = pfx[3] = pfx[4] = 0;
   1360     /* Obtain prefix length */
   1361     if (mode == 0) {
   1362         pfx[1] = SHR_SHIFT_RIGHT(ip6_word[0], 32 - len);
   1363         pfx[0] = 0;
   1364     } else if (mode == 1) {
   1365         pfx[4] = ip6_word[2];
   1366         pfx[3] = ip6_word[3];
   1367 
   1368         pfx_shift = 64 - len;
   1369         if (pfx_shift < 32) {
   1370             /* get lower half shifted */
   1371             pfx[4] >>= pfx_shift;
   1372             /* isolate shifted stuff of upper half */
   1373             tmp = SHR_SHIFT_LEFT(pfx[3], 32 - pfx_shift);
   1374             pfx[3] >>= pfx_shift;
   1375             pfx[4] |= tmp;
   1376         } else {
   1377             pfx[4] = SHR_SHIFT_RIGHT(pfx[3], pfx_shift - 32);
   1378             pfx[3] = 0;
   1379         }
   1380     } else {
   1381         /* PAIR_128 style, for both mode==2 and mode==3  */
   1382         int start;
   1383         uint32 tmp_pfx[5] = {0};
   1384         tmp_pfx[0] = ip6_word[0];
   1385         tmp_pfx[1] = ip6_word[1];
   1386         tmp_pfx[2] = ip6_word[2];
   1387         tmp_pfx[3] = ip6_word[3];
   1388 
   1389         /* shift entire prefix right to remove trailing 0s in prefix */
   1390         /* to simplify, words which are all 0s are ignored to begin with, so
   1391          * a right shift of say 46 is a right shift of 46-32 = 14, but starting
   1392          * from word 1. Once all shifting is done, shift all words to right by 1
   1393          */
   1394         pfx_shift = 128 - len;
   1395         start = pfx_shift / 32;
   1396         pfx_shift = pfx_shift % 32;
   1397         for (i = start; i < 4; i++) {
   1398             tmp_pfx[i] >>= pfx_shift;
   1399             tmp = tmp_pfx[i+1] & ((1 << pfx_shift) - 1);
   1400             tmp = SHR_SHIFT_LEFT(tmp, 32 - pfx_shift);
   1401             tmp_pfx[i] |= tmp;
   1402         }
   1403         /* make shift right justified and also reverse order for trie.
   1404          * Also, note trie sees key only in words 1 to 4
   1405          */
   1406         for (i = start; i < 4; i++) {
   1407             pfx[4 - (i - start)] = tmp_pfx[i];
   1408         }
   1409     }
   1410     return ;
   1411 }
   1412 
   1413 void
   1414 _soc_th_alpm_mask_prefix_create(int u, int mode, uint32 mask_len, uint32 *mask)
   1415 {
   1416     int len;
   1417     uint32 ip6_word[4] = {0};
   1418 
   1419     len = mask_len;
   1420     if (mode == 0) {
   1421         ip6_word[0] = (len == 32) ? 0x1 : (0xffffffff >> len) + 1;
   1422     } else if (mode == 1) {
   1423         if (len >= 32) {
   1424             ip6_word[3] = 0;
   1425             ip6_word[2] = SHR_SHIFT_RIGHT(0xffffffff, len - 32) + 1;
   1426         } else {
   1427             ip6_word[3] = (0xffffffff >> len) + 1;
   1428             ip6_word[2] = 0;
   1429         }
   1430     } else {
   1431         /* Compatible of hardware mode value and L3_DEFIP_MODE_128 */
   1432         int i;
   1433         for (i = 0; i < 4; i++) {
   1434             if (len <= 32) break;
   1435             ip6_word[3-i] = 0;
   1436             len -= 32;
   1437         }
   1438         ip6_word[3-i] = SHR_SHIFT_RIGHT(0xffffffff, len) + 1;
   1439     }
   1440 
   1441     return _soc_th_alpm_trie_prefix_create(u, mode, ip6_word, mask_len, mask);
   1442 
   1443 }
   1444 
   1445 /* Create prefix & len in trie format from aux entry */
   1446 STATIC void
   1447 _soc_th_alpm_aux_prefix_create(int u, void *aux_entry, uint32 *pfx, uint32 *len)
   1448 {
   1449     uint32 ip6_word[4];
   1450     int mode;
   1451     soc_mem_t aux_mem = L3_DEFIP_AUX_SCRATCHm;
   1452 
   1453     soc_mem_field_get(u, aux_mem, aux_entry, IP_ADDRf, (uint32 *)ip6_word);
   1454     *len = soc_mem_field32_get(u, aux_mem, aux_entry, IP_LENGTHf);
   1455     mode = soc_mem_field32_get(u, aux_mem, aux_entry, MODE_f(u));
   1456 
   1457     return _soc_th_alpm_trie_prefix_create(u, mode, ip6_word, *len, pfx);
   1458 }
   1459 
   1460 /* Software propagation */
   1461 STATIC int
   1462 _soc_th_alpm_aux_sw_op(int u, _soc_aux_op_t aux_op, void *aux_entry,
   1463                        int *match_cnt, int aux_flags)
   1464 {
   1465     trie_t *pivot;
   1466     int rv = SOC_E_NONE;
   1467     int vld, mode, dbt, vrf = 0;
   1468     uint32 prefix[5];
   1469     uint32 len;
   1470     trie_bpm_cb_user_data_t user_data;
   1471     soc_mem_t aux_mem = L3_DEFIP_AUX_SCRATCHm;
   1472     int insert = 0;
   1473 
   1474     switch (aux_op) {
   1475         case INSERT_PROPAGATE:
   1476             insert = 1;
   1477             break;
   1478         case DELETE_PROPAGATE:
   1479             insert = 0;
   1480             break;
   1481         case HITBIT_REPLACE:
   1482         case PREFIX_LOOKUP:
   1483         default:
   1484             return SOC_E_NONE;
   1485     }
   1486 
   1487     vld  = soc_mem_field32_get(u, aux_mem, aux_entry, VALIDf);
   1488     mode = soc_mem_field32_get(u, aux_mem, aux_entry, MODE_f(u));
   1489     vrf  = soc_mem_field32_get(u, aux_mem, aux_entry, VRFf);
   1490     dbt  = soc_mem_field32_get(u, aux_mem, aux_entry, DB_TYPEf);
   1491 
   1492     /* Need to distinguish vrf=0 and Global low */
   1493     if (vrf == 0 && dbt <= 1) {
   1494         vrf = SOC_VRF_MAX(u) + 1;
   1495     }
   1496 
   1497     /* Mode indicates entry type: 00:IPv4, 01: 64-Ipv6, 11: IPv6-128 */
   1498     if (mode == 0) {
   1499         pivot = VRF_PIVOT_TRIE_IPV4(u, vrf);
   1500     } else if (mode == 1) {
   1501         pivot = VRF_PIVOT_TRIE_IPV6(u, vrf);
   1502     } else if (mode == 3) {
   1503         pivot = VRF_PIVOT_TRIE_IPV6_128(u, vrf);
   1504     } else {
   1505         return SOC_E_INTERNAL;
   1506     }
   1507 
   1508     _soc_th_alpm_aux_prefix_create(u, aux_entry, (void *)prefix, &len);
   1509 
   1510     sal_memset(&user_data, 0, sizeof(user_data));
   1511     user_data.unit     = u;
   1512     user_data.entry    = aux_entry;
   1513     user_data.aux_op   = aux_op;
   1514     user_data.flags    = aux_flags;
   1515 
   1516     if (vld && pivot) {
   1517         rv = _soc_th_alpm_sw_propagate(u, pivot, prefix, len, insert,
   1518                 _soc_th_alpm_propagate_callback, &user_data);
   1519     }
   1520 
   1521     if (insert) {
   1522         _alpm_dbg_cntr[u].ppg_cb_insert += user_data.count;
   1523     } else {
   1524         _alpm_dbg_cntr[u].ppg_cb_delete += user_data.count;
   1525     }
   1526 
   1527     if (match_cnt != NULL) {
   1528         *match_cnt = user_data.count;
   1529     }
   1530 
   1531     return rv;
   1532 
   1533 }
   1534 
   1535 STATIC void
   1536 _alpm_128_trie_to_normal_ip(uint32 *result, int length)
   1537 {
   1538     uint32 pfx_shift, tmp, start, prefix[6];
   1539     int i;
   1540 
   1541     sal_memcpy(prefix, result, sizeof(uint32) * BITS2WORDS(_MAX_KEY_LEN_144_));
   1542     sal_memset(result, 0, sizeof(uint32) * BITS2WORDS(_MAX_KEY_LEN_144_));
   1543 
   1544     /* shift entire prefix left to add trailing 0s in prefix */
   1545     pfx_shift = 128 - length;
   1546     start = (pfx_shift + 31) / 32;
   1547     /* fix corner case: */
   1548     if ((pfx_shift % 32) == 0) {
   1549         start++;
   1550     }
   1551     pfx_shift = pfx_shift % 32;
   1552     for (i = start; i <= 4; i++) {
   1553         prefix[i] <<= pfx_shift;
   1554         tmp = prefix[i+1] & ~(0xffffffff >> pfx_shift);
   1555         tmp = SHR_SHIFT_RIGHT(tmp, 32 - pfx_shift);
   1556         if (i < 4) {
   1557             prefix[i] |= tmp;
   1558         }
   1559     }
   1560     /* make shift left justified and reversed, i.e, lsw goes to index 0 */
   1561     for (i = start; i <= 4; i++) {
   1562         result[3 - (i - start)] = prefix[i];
   1563     }
   1564 }
   1565 
   1566 STATIC int
   1567 _soc_alpm_pivot_traverse_check_cb(trie_node_t *trie, void *datum)
   1568 {
   1569     trie_bpm_cb_user_data_t *cbdata;
   1570     trie_t *pivot;
   1571     alpm_pivot_t *pivot_pyld;
   1572     soc_mem_t mem = L3_DEFIP_AUX_TABLEm;
   1573     soc_field_t fld = BPM_LENGTH0f;
   1574     defip_aux_table_entry_t ent;
   1575     int u, index, lpm_idx, quiet;
   1576     int v6, vrf, rv = SOC_E_NONE;
   1577 
   1578     cbdata = datum;
   1579     pivot = cbdata->entry;
   1580     u = cbdata->unit;
   1581     v6 = cbdata->ipv6;
   1582     quiet = cbdata->count;
   1583     vrf = cbdata->aux_op;
   1584     if (trie->type == PAYLOAD) {
   1585         uint32 addr[5];
   1586         uint32 hw_bpm_len, bpm_len = -1;
   1587         pivot_pyld = (alpm_pivot_t *)trie;
   1588 
   1589         sal_memcpy(addr, pivot_pyld->key, sizeof(addr));
   1590         if (v6 == L3_DEFIP_MODE_128) {
   1591             _alpm_128_trie_to_normal_ip(addr, pivot_pyld->len);
   1592         } else {
   1593             ALPM_TRIE_TO_NORMAL_IP(addr, pivot_pyld->len, v6);
   1594         }
   1595 
   1596         index = PIVOT_TCAM_INDEX(pivot_pyld) >> 1;
   1597         if (v6 == L3_DEFIP_MODE_128) {
   1598             index = SOC_ALPM_128_DEFIP_TO_PAIR(u, index);
   1599             lpm_idx = soc_th_alpm_logical_idx(u, L3_DEFIP_PAIR_128m, index, 1);
   1600             index = SOC_ALPM_128_ADDR_LWR(u, index);
   1601         } else {
   1602             lpm_idx = soc_th_alpm_logical_idx(u, L3_DEFIPm, index, 1);
   1603         }
   1604 
   1605         if (!v6 && (PIVOT_TCAM_INDEX(pivot_pyld) & 1)) {
   1606             fld = BPM_LENGTH1f;
   1607         }
   1608 
   1609         if (ALPM_CTRL(u).trie_user_ppg) {
   1610             bpm_len = PIVOT_TCAM_BPMLEN(pivot_pyld);
   1611         } else {
   1612             rv = trie_find_prefix_bpm(pivot, pivot_pyld->key,
   1613                                       pivot_pyld->len, &bpm_len);
   1614             if (rv < 0) {
   1615                 cli_out("Searching bpm[vrf %d] failed, AUX[%d]->LOG[%d]: "
   1616                         "0x%08x.0x%08x.0x%08x.0x%08x/%d, rv = %d\n", vrf,
   1617                         index, lpm_idx,
   1618                         addr[3], addr[2], addr[1], addr[0], pivot_pyld->len, rv);
   1619                 return SOC_E_NONE;
   1620             }
   1621         }
   1622 
   1623         SOC_IF_ERROR_RETURN(soc_mem_read(u, mem, MEM_BLOCK_ANY, index, &ent));
   1624         hw_bpm_len = soc_mem_field32_get(u, mem, &ent, fld);
   1625 
   1626         if (!quiet || (hw_bpm_len != bpm_len)) {
   1627             cli_out("Touching AUX[%d]->LOG[%d]: vrf %d v6 %d addr:",
   1628                     index, lpm_idx, vrf, v6);
   1629             if (v6 == L3_DEFIP_MODE_128) {
   1630                 cli_out("0x%08x 0x%08x 0x%08x 0x%08x/%d\n", addr[3], addr[2],
   1631                         addr[1], addr[0], pivot_pyld->len);
   1632             } else if (v6 == L3_DEFIP_MODE_64) {
   1633                 cli_out("0x%08x 0x%08x/%d\n", addr[1], addr[0], pivot_pyld->len);
   1634             } else {
   1635                 cli_out("0x%08x/%d\n", addr[0], pivot_pyld->len);
   1636             }
   1637         }
   1638 
   1639         if (hw_bpm_len != bpm_len) {
   1640             cli_out("\t==> bpm_len mismatch hw %d trie %d\n",
   1641                     hw_bpm_len, bpm_len);
   1642         } else {
   1643             if (!quiet) {
   1644                 cli_out("\t==> bpm_len %d\n", bpm_len);
   1645             }
   1646         }
   1647     }
   1648     return SOC_E_NONE;
   1649 }
   1650 
   1651 void
   1652 soc_alpm_pivot_traverse_check(int u, int quiet)
   1653 {
   1654     int rv, vrf, v6;
   1655     trie_t *pivot = NULL;
   1656     trie_bpm_cb_user_data_t cbdata;
   1657 
   1658     for (vrf = 0; vrf <= SOC_VRF_MAX(u) + 1; vrf++) {
   1659         for (v6 = L3_DEFIP_MODE_V4; v6 <= L3_DEFIP_MODE_128; v6++) {
   1660             if (v6 == L3_DEFIP_MODE_V4) {
   1661                 pivot = VRF_PIVOT_TRIE_IPV4(u, vrf);
   1662             } else if (v6 == L3_DEFIP_MODE_64) {
   1663                 pivot = VRF_PIVOT_TRIE_IPV6(u, vrf);
   1664             } else if (v6 == L3_DEFIP_MODE_128) {
   1665                 pivot = VRF_PIVOT_TRIE_IPV6_128(u, vrf);
   1666             }
   1667 
   1668             if (pivot == NULL) {
   1669                 continue;
   1670             }
   1671 
   1672             sal_memset(&cbdata, 0, sizeof(cbdata));
   1673             cbdata.unit = u;
   1674             cbdata.ipv6 = v6;
   1675             cbdata.entry = pivot;
   1676             cbdata.count = quiet;
   1677             cbdata.aux_op = vrf;
   1678 
   1679             rv = trie_traverse(pivot, _soc_alpm_pivot_traverse_check_cb,
   1680                                &cbdata, _TRIE_INORDER_TRAVERSE);
   1681             if (SOC_FAILURE(rv)) {
   1682                 cli_out("Traverse Pivot v6 %d vrf %d failed rv=%d\n", v6, vrf, rv);
   1683             }
   1684         }
   1685     }
   1686 }
   1687 
   1688 static int
   1689 _soc_th_alpm_mask_len_get(int u, int ipv6, void *entry, int *pfx)
   1690 {
   1691     int     rv;
   1692     uint32  ipv4a;
   1693 
   1694     if (ipv6) {
   1695         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f);
   1696         if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) {
   1697             return(rv);
   1698         }
   1699         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK1f);
   1700         if (*pfx) {
   1701             if (ipv4a != 0xffffffff)  {
   1702                 return(SOC_E_PARAM);
   1703             }
   1704             *pfx += 32;
   1705         } else {
   1706             if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) {
   1707                 return(rv);
   1708             }
   1709         }
   1710     } else {
   1711         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f);
   1712         if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) {
   1713             return(rv);
   1714         }
   1715     }
   1716 
   1717     return SOC_E_NONE;
   1718 }
   1719 
   1720 
   1721 void
   1722 soc_th_alpm_bank_dis(int u, int vrf, uint32 *bnk_dis_4b, uint32 *bnk_dis_8b)
   1723 {
   1724     uint32 b4 = 0, b8 = 0;
   1725     int global = (vrf == SOC_VRF_MAX(u) + 1) ? 1 : 0;
   1726 
   1727     /* TD3 Only has room for 4 bits.
   1728      * In full bank mode (UFT_SHARED_BANKS_CONTROL__ALPM_MODE == 0),
   1729      *   Bit 0 disables banks 0,1.
   1730      *   Bit 1 disables banks 2,3.
   1731      *   Bit 2 disables banks 4,5.
   1732      *   Bit 3 disables banks 6,7.
   1733      * In half bank mode, (UFT_SHARED_BANKS_CONTROL__ALPM_MODE == 1)
   1734      *   Bit 0 disables bank 0.
   1735      *   Bit 1 disables bank 1.
   1736      *   Bit 2 disables bank 2.
   1737      *   Bit 3 disables bank 3.
   1738      */
   1739 
   1740     if (ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_PARALLEL &&
   1741         SOC_URPF_STATUS_GET(u)) {
   1742         if (ALPM_CTRL(u).num_banks <= 2) {
   1743             b4 = global ? 0xD : 0xE; /* 1101 : 1110 */
   1744             b8 = b4;
   1745         } else if (ALPM_CTRL(u).num_banks <= 4) {
   1746             b4 = global ? 0x3 : 0xC; /* 0011 : 1100 */
   1747             if (SOC_IS_TRIDENT3X(u)) {
   1748                 b8 = global ? 0xF3 : 0xFC; /* 11110011 : 11111100 */
   1749             } else {
   1750                 b8 = b4;
   1751             }
   1752         } else {    /* 8 Banks mode */
   1753             b4 = global ? 0x3 : 0xC; /* 0011 : 1100 */
   1754             if (SOC_IS_TRIDENT3X(u)) {
   1755                 b8 = global ? 0xF : 0xF0; /* 00001111 : 11110000 */
   1756             } else {
   1757                 b8 = b4;
   1758             }
   1759         }
   1760     } else {
   1761         if (ALPM_CTRL(u).num_banks <= 2) {
   1762             b4 = 0xC; /* 1100 */
   1763             b8 = b4;
   1764         } else if (ALPM_CTRL(u).num_banks <= 4) {
   1765             b4 = 0;
   1766             if (SOC_IS_TRIDENT3X(u)) {
   1767                 b8 = 0xF0;
   1768             } else {
   1769                 b8 = b4;
   1770             }
   1771         } else {
   1772             b4 = 0;
   1773             b8 = b4;
   1774         }
   1775     }
   1776 
   1777     if (bnk_dis_4b != NULL) {
   1778         *bnk_dis_4b = b4;
   1779     }
   1780 
   1781     if (bnk_dis_8b != NULL) {
   1782         *bnk_dis_8b = b8;
   1783     }
   1784 
   1785     return ;
   1786 }
   1787 
   1788 int
   1789 _soc_th_alpm_rpf_entry(int u, int idx)
   1790 {
   1791     int bkt;
   1792     int bank_bits = ALPM_CTRL(u).bank_bits;
   1793     bkt = (idx >> bank_bits) & ALPM_CTRL(u).bkt_mask;
   1794     bkt += SOC_TH_ALPM_BUCKET_COUNT(u);
   1795     /* form rpf alpm entry index */
   1796     return (idx & ~(ALPM_CTRL(u).bkt_mask << bank_bits)) | (bkt << bank_bits);
   1797 }
   1798 
   1799 /* for v4 full = 0, for v6-64 full = 1 */
   1800 int
   1801 soc_th_alpm_physical_idx(int u, soc_mem_t mem, int index, int full)
   1802 {
   1803     int tmp = index & 1;
   1804 
   1805     if (full) {
   1806         return soc_alpm_l3_defip_index_map(u, mem, index);
   1807     }
   1808     index >>= 1;
   1809     index = soc_alpm_l3_defip_index_map(u, mem, index);
   1810     index <<= 1;
   1811     index |= tmp;
   1812     return index;
   1813 }
   1814 
   1815 int
   1816 soc_th_alpm_logical_idx(int u, soc_mem_t mem, int index, int full)
   1817 {
   1818     int tmp = index & 1;
   1819 
   1820     if (full) {
   1821         return soc_alpm_l3_defip_index_remap(u, mem, index);
   1822     }
   1823     index >>= 1;
   1824     index = soc_alpm_l3_defip_index_remap(u, mem, index);
   1825     index <<= 1;
   1826     index |= tmp;
   1827     return index;
   1828 }
   1829 
   1830 static void
   1831 _soc_th_alpm_pfx_len_to_mask(int u, void *lpm_entry, int len, int ipv6)
   1832 {
   1833     uint32 mask = 0;
   1834 
   1835     if (ipv6) {
   1836         if (len >= 32) {
   1837             mask = 0xffffffff;
   1838             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, mask);
   1839             mask = ~SHR_SHIFT_RIGHT(0xffffffff, len - 32);
   1840             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, mask);
   1841         } else {
   1842             mask = ~(0xffffffff >> len);
   1843             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, mask);
   1844             /* make sure lower word of mask is 0 */
   1845             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, 0);
   1846         }
   1847     } else {
   1848         assert(len <= 32);
   1849         mask = (len == 32) ? 0xffffffff : ~(0xffffffff >> len);
   1850         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, mask);
   1851     }
   1852 }
   1853 /* Create Prefix */
   1854 /* Prefix is created based on the trie key packing expectations */
   1855 /* Prefix[0] will have higher order Word, Prefix[1] will have lower order word
   1856  * in case of IPV6. For IPV4 prefix[0] will contain the prefix
   1857  */
   1858 static int
   1859 _soc_th_alpm_prefix_create(int u, int ipv6, void *entry, uint32 *prefix,
   1860                            uint32 *pfx_len, int *default_route)
   1861 {
   1862     int ip, ip_mask;
   1863     int pfx = 0;
   1864     int rv = SOC_E_NONE;
   1865     uint32 pfx_shift, tmp;
   1866 
   1867     prefix[0] = prefix[1] = prefix[2] = prefix[3] = prefix[4] = 0;
   1868 
   1869     /* Form Prefix based on the entry */
   1870     ip = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR0f);
   1871     ip_mask = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f);
   1872 
   1873     prefix[1] = ip;
   1874 
   1875     ip = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR1f);
   1876     ip_mask = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK1f);
   1877 
   1878     prefix[0] = ip;
   1879 
   1880     /* Obtain prefix length */
   1881     if (ipv6) {
   1882         prefix[4] = prefix[1];
   1883         prefix[3] = prefix[0];
   1884         prefix[1] = prefix[0] = 0;
   1885         ip_mask = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f);
   1886         if ((rv = _ipmask2pfx(ip_mask, &pfx)) < 0) {
   1887             return(rv);
   1888         }
   1889         ip_mask = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK1f);
   1890         if (pfx) {
   1891             if (ip_mask != 0xffffffff)  {
   1892                 return(SOC_E_PARAM);
   1893             }
   1894             pfx += 32;
   1895         } else {
   1896             if ((rv = _ipmask2pfx(ip_mask, &pfx)) < 0) {
   1897                 return(rv);
   1898             }
   1899         }
   1900         pfx_shift = 64 - pfx;
   1901         if (pfx_shift < 32) {
   1902             /* get lower half shifted */
   1903             prefix[4] >>= pfx_shift;
   1904             /* isolate shifted stuff of upper half */
   1905             tmp = SHR_SHIFT_LEFT(prefix[3], 32 - pfx_shift);
   1906             prefix[3] >>= pfx_shift;
   1907             prefix[4] |= tmp;
   1908         } else {
   1909             prefix[4] = SHR_SHIFT_RIGHT(prefix[3], pfx_shift - 32);
   1910             prefix[3] = 0;
   1911         }
   1912     } else {
   1913         ip_mask = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f);
   1914         if ((rv = _ipmask2pfx(ip_mask, &pfx)) < 0) {
   1915             return(rv);
   1916         }
   1917         prefix[1] = SHR_SHIFT_RIGHT(prefix[1], 32 - pfx);
   1918         prefix[0] = 0;
   1919     }
   1920     *pfx_len = pfx;
   1921     *default_route = (prefix[0] == 0) && (prefix[1] == 0) && (pfx == 0);
   1922     return SOC_E_NONE;
   1923 }
   1924 
   1925 int
   1926 _soc_th_alpm_find_in_bkt(int u, soc_mem_t mem, int log_bkt, int bank_disable,
   1927                       uint32 *e, void *alpm_data, int *key_index, int v6)
   1928 {
   1929     int rv;
   1930     rv = soc_mem_alpm_lookup(u, mem, ALPM_PHY_BKT(u, log_bkt),
   1931                              MEM_BLOCK_ANY,
   1932                              bank_disable,
   1933                              e, alpm_data, key_index);
   1934     if (SOC_SUCCESS(rv)) {
   1935         return rv;
   1936     }
   1937     if (ALPM_CTRL(u).double_wide[v6]) {
   1938         return soc_mem_alpm_lookup(u, mem, ALPM_PHY_BKT(u, log_bkt) + 1,
   1939                                    MEM_BLOCK_ANY, bank_disable, e, alpm_data,
   1940                                    key_index);
   1941     }
   1942     return rv;
   1943 }
   1944 
   1945 static int
   1946 _soc_th_alpm_sw_pivot_find(int u, uint32 *prefix, uint32 length, int v6, int vrf,
   1947                            int *hit, int *tcam_index, int *log_bkt)
   1948 {
   1949     int rv = SOC_E_NONE;
   1950     trie_t  *pivot_trie;
   1951     trie_node_t *lpmp = NULL;
   1952     alpm_pivot_t *pivot_pyld;
   1953 
   1954     if (v6) {
   1955         pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf);
   1956     } else {
   1957         pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf);
   1958     }
   1959     rv = trie_find_lpm(pivot_trie, prefix, length, &lpmp);
   1960     if (SOC_FAILURE(rv)) {
   1961         LOG_ERROR(BSL_LS_SOC_ALPM,
   1962                   (BSL_META_U(u,
   1963                               "Pivot find failed\n")));
   1964         return rv;
   1965     }
   1966     pivot_pyld = (alpm_pivot_t *)lpmp;
   1967 
   1968     *hit = 1;
   1969     *tcam_index = PIVOT_TCAM_INDEX(pivot_pyld);
   1970     *log_bkt = PIVOT_BUCKET_INDEX(pivot_pyld);
   1971 
   1972     return SOC_E_NONE;
   1973 }
   1974 
   1975 
   1976 
   1977 int
   1978 _soc_th_alpm_sw_prefix_check(int u,
   1979                              soc_mem_t mem,      /* Mem type for ALPM */
   1980                              int v6,
   1981                              void *key_data,     /* TCAM entry data */
   1982                              int vrf_id,
   1983                              int vrf)
   1984 {
   1985     int         rv = SOC_E_NONE;
   1986     uint32 prefix[5], length;
   1987     int default_route = 0;
   1988     trie_t  *pivot_trie, *bkt_trie;
   1989     trie_node_t *lpmp = NULL;
   1990     alpm_pivot_t *pivot_node;
   1991     if (vrf_id == 0) {
   1992         if (soc_alpm_cmn_mode_get(u) == SOC_ALPM_MODE_PARALLEL ||
   1993             soc_alpm_cmn_mode_get(u) == SOC_ALPM_MODE_TCAM_ALPM) {
   1994             return SOC_E_PARAM;
   1995         }
   1996     }
   1997     if (!(ALPM_PREFIX_IN_TCAM(u, vrf_id))) {
   1998         rv = _soc_th_alpm_prefix_create(u, v6, key_data, prefix, &length,
   1999                                         &default_route);
   2000         if (SOC_FAILURE(rv)) {
   2001             LOG_ERROR(BSL_LS_SOC_ALPM,
   2002                       (BSL_META_U(u,
   2003                                   "_soc_th_alpm_sw_prefix_check: prefix create failed\n")));
   2004             return rv;
   2005         }
   2006         if (v6) {
   2007             pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf);
   2008         } else {
   2009             pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf);
   2010         }
   2011         rv = trie_find_lpm(pivot_trie, prefix, length, &lpmp);
   2012         if (SOC_FAILURE(rv)) {
   2013             LOG_ERROR(BSL_LS_SOC_ALPM,
   2014                       (BSL_META_U(u,
   2015                                   "_soc_th_alpm_sw_prefix_check: Pivot find failed\n")));
   2016             return rv;
   2017         }
   2018         pivot_node = (alpm_pivot_t *)lpmp;
   2019         bkt_trie = pivot_node->bucket->bucket_trie;
   2020         if (bkt_trie != NULL) {
   2021             rv = trie_search(bkt_trie, prefix, length,
   2022                              (trie_node_t **)&bkt_trie);
   2023             if (SOC_FAILURE(rv)){
   2024                 LOG_ERROR(BSL_LS_SOC_ALPM,
   2025                           (BSL_META_U(u,
   2026                                       "_soc_th_alpm_sw_prefix_check: prefix find failed\n")));
   2027             }
   2028         } else {
   2029             LOG_ERROR(BSL_LS_SOC_ALPM,
   2030                       (BSL_META_U(u,
   2031                                   "_soc_th_alpm_sw_prefix_check: bkt trie doesn't exist\n")));
   2032         }
   2033     }
   2034     return rv;
   2035 }
   2036 
   2037 /*
   2038  * Find and read the match in the database.
   2039  * Returns SOC_E_NONE, if found.
   2040  * SOC_E_NOT_FOUND if not found
   2041  * SOC_E_FAIL, if lookup failed.
   2042  */
   2043 
   2044 static int
   2045 _soc_th_alpm_find(int u,
   2046                   soc_mem_t mem,      /* Mem type for ALPM */
   2047                   int v6,
   2048                   void *key_data,     /* TCAM entry data */
   2049                   int vrf_id,
   2050                   int vrf,
   2051                   void *alpm_data,    /* Alpm data if match */
   2052                   int *tcam_index,    /* TCAM INDEX */
   2053                   int *log_bkt,         /* return Bucket ID */
   2054                   int *index_ptr,     /* return key location */
   2055                   int sw_find)
   2056 {
   2057     uint32      *e = NULL;
   2058     defip_aux_scratch_entry_t *aux_entry = NULL;
   2059     int         key_index ;
   2060     uint32      db_type, ent_type, bank_disable;
   2061     int         rv = SOC_E_NONE;
   2062     int         hit = 0;
   2063 
   2064     e = sal_alloc(sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS, "buf_tmp");
   2065     if (e == NULL) {
   2066         rv = SOC_E_MEMORY;
   2067         goto clean_up;
   2068     }
   2069 
   2070     sal_memset(e, 0, sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS);
   2071 
   2072     if (vrf_id == 0) {
   2073         if (ALPM_CTRL(u).gp_zoned) {
   2074             /* cannot have 0 as a VRF in parallel mode */
   2075             return SOC_E_PARAM;
   2076         }
   2077     }
   2078 
   2079     bank_disable = ALPM_CTRL(u).bank_disable_bmp[vrf != (SOC_VRF_MAX(u) + 1)];
   2080     soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
   2081 
   2082     /* For VRF_OVERRIDE (Global High) entries, software needs to maintain the
   2083      * index */
   2084     /* Prefix resides in TCAM directly */
   2085     if (!(ALPM_PREFIX_IN_TCAM(u, vrf_id))) {
   2086         if (sw_find) {
   2087             uint32 prefix[5], length;
   2088             int default_route = 0;
   2089 
   2090             /* Create Prefix */
   2091             rv = _soc_th_alpm_prefix_create(u, v6, key_data, prefix, &length,
   2092                                             &default_route);
   2093             if (SOC_FAILURE(rv)) {
   2094                 LOG_ERROR(BSL_LS_SOC_ALPM,
   2095                           (BSL_META_U(u,
   2096                                       "_soc_alpm_insert: prefix create failed\n")));
   2097                 goto clean_up;
   2098             }
   2099 
   2100             SOC_IF_ERROR_RETURN(_soc_th_alpm_sw_pivot_find(u, prefix, length, v6,
   2101                                                            vrf, &hit, tcam_index,
   2102                                                            log_bkt));
   2103         } else {
   2104             /* Fill in AUX Scratch and perform Lookup Operation */
   2105             aux_entry = sal_alloc(sizeof(defip_aux_scratch_entry_t), "aux_entry");
   2106             if (aux_entry == NULL) {
   2107                 rv = SOC_E_MEMORY;
   2108                 goto clean_up;
   2109             }
   2110             sal_memset(aux_entry, 0, sizeof(defip_aux_scratch_entry_t));
   2111             SOC_IF_ERROR_RETURN(
   2112                 _soc_th_alpm_fill_aux_entry_for_op(u, key_data, v6, db_type, ent_type,
   2113                                                    0, aux_entry));
   2114             SOC_IF_ERROR_RETURN(
   2115                 _soc_th_alpm_aux_op(u, PREFIX_LOOKUP, aux_entry, TRUE, &hit,
   2116                                     tcam_index, log_bkt, 0));
   2117         }
   2118         if (hit) { /* Entry is found in the log_bkt */
   2119             /* Fill entry for lookup */
   2120             _soc_th_alpm_mem_ent_init(u, v6, key_data, e, 0, mem, 0, 0, *log_bkt);
   2121 
   2122             /* Perform lookup */
   2123             rv = _soc_th_alpm_find_in_bkt(u, mem, *log_bkt, bank_disable,
   2124                                           e, alpm_data, &key_index, v6);
   2125             if (SOC_SUCCESS(rv)) {
   2126                 *index_ptr = key_index;
   2127             }
   2128         } else {
   2129             rv = SOC_E_NOT_FOUND;
   2130         }
   2131     }
   2132 clean_up:
   2133     if (e) {
   2134         sal_free(e);
   2135     }
   2136     if (aux_entry) {
   2137         sal_free(aux_entry);
   2138     }
   2139     return rv;
   2140 }
   2141 
   2142 /*
   2143  * Find and update the match in the database.
   2144  * Returns SOC_E_NONE, if found and updated.
   2145  * SOC_E_NOT_FOUND if not found
   2146  * SOC_E_FAIL, if update failed.
   2147  */
   2148 static int
   2149 _soc_th_alpm_find_and_update(int u,
   2150                              int v6,
   2151                              void *key_data,  /* TCAM entry data */
   2152                              void *alpm_data, /* Alpm data to be updated with */
   2153                              void *alpm_sip_data,
   2154                              soc_mem_t mem,   /* Mem view for ALPM data */
   2155                              int key_index)   /* key location */
   2156 {
   2157     defip_aux_scratch_entry_t aux_entry;
   2158     int         vrf_id, vrf;
   2159     int         log_bkt;
   2160     uint32      db_type, ent_type;
   2161     int         rv = SOC_E_NONE;
   2162     int         hit = 0, tmp = 0;
   2163     int         tcam_index, index;
   2164     int         aux_flags = 0;
   2165     uint32      alpm_ent[SOC_MAX_MEM_FIELD_WORDS];
   2166 
   2167     SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   2168     soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
   2169     /* For VRF_OVERRIDE (Global High) entries */
   2170     if (!(ALPM_PREFIX_IN_TCAM(u, vrf_id))) {
   2171         /* Fill in AUX Scratch and perform Lookup Operation */
   2172         sal_memset(&aux_entry, 0, sizeof(defip_aux_scratch_entry_t));
   2173         SOC_IF_ERROR_RETURN(
   2174            _soc_th_alpm_fill_aux_entry_for_op(u, key_data, v6, db_type,
   2175                         ent_type, 0, &aux_entry));
   2176         /* Perform lookup */
   2177         SOC_ALPM_LPM_LOCK(u);
   2178         /* Find and update the entry */
   2179         rv = _soc_th_alpm_find(u, mem, v6, key_data, vrf_id, vrf, alpm_ent,
   2180                                &tcam_index, &log_bkt, &index, TRUE);
   2181         SOC_ALPM_LPM_UNLOCK(u);
   2182         SOC_IF_ERROR_RETURN(rv);
   2183         if (ALPM_CTRL(u).bkt_sharing) {
   2184             soc_mem_field32_set(u, mem, alpm_data, SUB_BKT_PTRf,
   2185                                 ALPM_SUB_BKT(u, log_bkt));
   2186         }
   2187         /* Update the entry */
   2188         SOC_IF_ERROR_RETURN(
   2189             soc_mem_write(u, mem, MEM_BLOCK_ANY, ALPM_ENT_INDEX(key_index),
   2190                           alpm_data));
   2191         if (SOC_URPF_STATUS_GET(u)) {
   2192             if (ALPM_CTRL(u).bkt_sharing) {
   2193                 soc_mem_field32_set(u, mem, alpm_sip_data, SUB_BKT_PTRf,
   2194                                     ALPM_SUB_BKT(u, log_bkt));
   2195             }
   2196             /* Update the sip entry */
   2197             SOC_IF_ERROR_RETURN(soc_mem_write(u, mem, MEM_BLOCK_ANY,
   2198                                 _soc_th_alpm_rpf_entry(u, ALPM_ENT_INDEX(key_index)),
   2199                                 alpm_sip_data));
   2200             if (rv != SOC_E_NONE) {
   2201                 return SOC_E_FAIL;
   2202             }
   2203         }
   2204         /* set REPLACE_LEN field to correct value */
   2205         tmp = soc_mem_field32_get(u, L3_DEFIP_AUX_SCRATCHm,
   2206                                  &aux_entry, IP_LENGTHf);
   2207         soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, &aux_entry,
   2208                             REPLACE_LENf, tmp);
   2209         soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, &aux_entry, ALG_HIT_IDXf,
   2210                             ALPM_ENT_INDEX(key_index));
   2211 
   2212         /* We used DELETE_PROPAGATE before because in TD2, INSERT Propagate
   2213          * doesn't handle '==' case, so we need DELETE instead.
   2214          * but DELETE can't be used against software trie-tree for non-delete
   2215          * purpose.
   2216          *
   2217          * So need to bring INSERT back.
   2218          *
   2219          * *** For Trident2, don't turn on TCAM cache. ***
   2220          */
   2221         if (SOC_URPF_STATUS_GET(u)) {
   2222             if (soc_mem_field32_get(u, mem, alpm_sip_data, DEFAULTROUTEf)) {
   2223                 aux_flags |= SOC_ALPM_AUX_DEF_ROUTE;
   2224             }
   2225             if (soc_mem_field32_get(u, mem, alpm_sip_data, SRC_DISCARDf)) {
   2226                 aux_flags |= SOC_ALPM_AUX_SRC_DISCARD;
   2227             }
   2228         }
   2229 
   2230         SOC_IF_ERROR_RETURN(_soc_th_alpm_aux_op(u,
   2231             SOC_IS_TRIDENT2(u) ? DELETE_PROPAGATE : INSERT_PROPAGATE,
   2232             &aux_entry, TRUE, &hit, &tcam_index, &log_bkt, aux_flags));
   2233 
   2234         if (0) { /* uRPF case */
   2235             /* propagate SIP too */
   2236             /* Check default route */
   2237             soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, &aux_entry,
   2238                                 DEFAULTROUTEf, tmp == 0 ? 1 : 0);
   2239 
   2240             soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, &aux_entry,
   2241                                 DB_TYPEf, db_type + 1);
   2242             tmp = soc_mem_field32_get(u, L3_DEFIP_AUX_SCRATCHm, &aux_entry,
   2243                                       ALG_HIT_IDXf);
   2244             if (tmp > 0) {
   2245                 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, &aux_entry,
   2246                     ALG_HIT_IDXf, _soc_th_alpm_rpf_entry(u, tmp));
   2247             }
   2248             SOC_IF_ERROR_RETURN(_soc_th_alpm_aux_op(u,
   2249                 SOC_IS_TRIDENT2(u) ? DELETE_PROPAGATE : INSERT_PROPAGATE,
   2250                 &aux_entry, TRUE, &hit, &tcam_index, &log_bkt, 0));
   2251         }
   2252     }
   2253     return rv;
   2254 }
   2255 
   2256 /* Update hit bits in batch */
   2257 STATIC int
   2258 _soc_th_alpm_hit_bits_hw_update(int u, alpm_mem_prefix_array_t *pa,
   2259                                 int *new_index, int urpf)
   2260 {
   2261     int i, index, old_index;
   2262     defip_aux_hitbit_update_entry_t entry;
   2263     soc_mem_t mem = L3_DEFIP_AUX_HITBIT_UPDATEm;
   2264     int batch_count = soc_mem_index_count(u, mem);
   2265 
   2266     for (i = 0, index = 0; i < pa->count; i++) {
   2267         old_index = pa->prefix[i]->index;
   2268         sal_memset(&entry, 0, sizeof(entry));
   2269         if (old_index > 0) {
   2270             soc_mem_field32_set(u, mem, &entry, VALIDf, 1);
   2271             if (!urpf) {
   2272                 soc_mem_field32_set(u, mem, &entry, HITBIT_PTRf,
   2273                                     old_index);
   2274                 soc_mem_field32_set(u, mem, &entry, REPLACEMENT_PTRf,
   2275                                     new_index[i]);
   2276             } else {
   2277                 soc_mem_field32_set(u, mem, &entry, HITBIT_PTRf,
   2278                                     _soc_th_alpm_rpf_entry(u, old_index));
   2279                 soc_mem_field32_set(u, mem, &entry, REPLACEMENT_PTRf,
   2280                                     _soc_th_alpm_rpf_entry(u, new_index[i]));
   2281             }
   2282         }
   2283         SOC_IF_ERROR_RETURN(
   2284             soc_mem_write(u, mem, MEM_BLOCK_ANY, index, &entry));
   2285 
   2286         if (++index == batch_count) {
   2287             SOC_IF_ERROR_RETURN(_soc_th_alpm_aux_op(u, HITBIT_REPLACE, NULL,
   2288                                     FALSE, NULL, NULL, NULL, 0));
   2289             index = 0;
   2290         }
   2291     }
   2292 
   2293     if (index) {
   2294         /* Reset trailing entries */
   2295         for (i = index; i < batch_count; i++) {
   2296             sal_memset(&entry, 0, sizeof(entry));
   2297             SOC_IF_ERROR_RETURN(
   2298                 soc_mem_write(u, mem, MEM_BLOCK_ANY, i, &entry));
   2299         }
   2300         SOC_IF_ERROR_RETURN(_soc_th_alpm_aux_op(u, HITBIT_REPLACE, NULL,
   2301                                 FALSE, NULL, NULL, NULL, 0));
   2302     }
   2303     return SOC_E_NONE;
   2304 }
   2305 
   2306 int
   2307 soc_th_alpm_hit_bits_update(int u, alpm_mem_prefix_array_t *pa, int *new_idx,
   2308                             int ipv6, int vrf)
   2309 {
   2310     int rv = SOC_E_NONE;
   2311     int cb_cnt = 1;
   2312 
   2313     /* Skip to update hit bits */
   2314     if (ALPM_CTRL(u).hit_bits_skip) {
   2315         return rv;
   2316     }
   2317 
   2318     /* Only required when TCAM table cache is on */
   2319     if (ALPM_CTRL(u).hit_idx_upd) {
   2320         rv = _soc_th_alpm_hit_bits_sw_update(u, pa, new_idx, &cb_cnt, ipv6, vrf);
   2321     }
   2322 
   2323     /* No Hardware propagation if aux table is disabled */
   2324     if (!ALPM_CTRL(u).aux_enable) {
   2325         return rv;
   2326     }
   2327 
   2328     if ((SOC_SUCCESS(rv) && cb_cnt > 0)  || ALPM_CTRL(u).force_aux_op) {
   2329         rv = _soc_th_alpm_hit_bits_hw_update(u, pa, new_idx, 0);
   2330         if (SOC_URPF_STATUS_GET(u) && SOC_SUCCESS(rv)) {
   2331             rv = _soc_th_alpm_hit_bits_hw_update(u, pa, new_idx, 1);
   2332         }
   2333     }
   2334 
   2335     return rv;
   2336 }
   2337 
   2338 /* Callback function for Traverse, to find Leaf nodes */
   2339 int
   2340 _soc_th_alpm_mem_prefix_array_cb(trie_node_t *node, void *info)
   2341 {
   2342     alpm_mem_prefix_array_t *prefix_array = (alpm_mem_prefix_array_t *)info;
   2343     if (node->type == PAYLOAD) {
   2344         prefix_array->prefix[prefix_array->count] = (payload_t *)node;
   2345         prefix_array->count++;
   2346     }
   2347     return SOC_E_NONE;
   2348 }
   2349 
   2350 /* Get entry No. per bucket based on various setting */
   2351 int
   2352 _soc_th_alpm_bkt_entry_cnt(int u, soc_mem_t mem)
   2353 {
   2354     int bkt_ent_max = 0;
   2355     int v6 = 0;
   2356 
   2357     /* Base entry number */
   2358     switch (mem) {
   2359     case L3_DEFIP_ALPM_IPV4m:
   2360         bkt_ent_max = ALPM_IPV4_BKT_COUNT;
   2361         v6 = 0;
   2362         break;
   2363     case L3_DEFIP_ALPM_IPV4_1m:
   2364         bkt_ent_max = ALPM_IPV4_BKT_COUNT_FLEX;
   2365         v6 = 0;
   2366         break;
   2367     case L3_DEFIP_ALPM_IPV6_64m:
   2368         bkt_ent_max = ALPM_IPV6_64_BKT_COUNT;
   2369         v6 = 1;
   2370         break;
   2371     case L3_DEFIP_ALPM_IPV6_64_1m:
   2372         bkt_ent_max = ALPM_IPV6_64_BKT_COUNT_FLEX;
   2373         v6 = 1;
   2374         break;
   2375     case L3_DEFIP_ALPM_IPV6_128m:
   2376         bkt_ent_max = ALPM_IPV6_128_BKT_COUNT;
   2377         v6 = 1;
   2378         break;
   2379     default:
   2380         bkt_ent_max = ALPM_IPV4_BKT_COUNT;
   2381         break;
   2382     }
   2383 
   2384     /* TD3 has 8 banks */
   2385     if (SOC_IS_TRIDENT3X(u)) {
   2386         bkt_ent_max <<= 1;
   2387     }
   2388 
   2389     /* Double-wide mode check */
   2390     if (ALPM_CTRL(u).double_wide[v6]) {
   2391         bkt_ent_max <<= 1;
   2392     }
   2393 
   2394     /* 2-bank mode check */
   2395     if (ALPM_CTRL(u).half_bkt_mode) {
   2396         bkt_ent_max >>= 1;
   2397     }
   2398 
   2399     /* Global & vrf sharing & uRPF mode check */
   2400     if (ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_PARALLEL &&
   2401         SOC_URPF_STATUS_GET(u)) {
   2402         bkt_ent_max >>= 1;
   2403     }
   2404 
   2405     return bkt_ent_max;
   2406 }
   2407 
   2408 
   2409 /* Connect TCAM entry to a bucket ID */
   2410 STATIC int
   2411 _soc_th_alpm_bucket_link(int u, int v6, int pivot_index, int log_bkt)
   2412 {
   2413     int             rv = SOC_E_NONE;
   2414     int             lpm_index;
   2415     soc_mem_t       lpm_mem = L3_DEFIPm;
   2416     defip_entry_t   lpm_entry;
   2417     int             phy_bkt, sub_bkt;
   2418 
   2419     phy_bkt = ALPM_PHY_BKT(u, log_bkt);
   2420     sub_bkt = ALPM_SUB_BKT(u, log_bkt);
   2421 
   2422     /* Connect TCAM entry to new bucket */
   2423     lpm_index = soc_th_alpm_logical_idx(u, lpm_mem, pivot_index >> 1, 1);
   2424 
   2425     rv = _soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY, lpm_index, &lpm_entry);
   2426     SOC_IF_ERROR_RETURN(rv);
   2427     if ((!v6) && (pivot_index & 1)) {
   2428         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, &lpm_entry, ALG_BKT_PTR1f, phy_bkt);
   2429         if (ALPM_CTRL(u).bkt_sharing) {
   2430             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, &lpm_entry, ALG_SUB_BKT_PTR1f, sub_bkt);
   2431         }
   2432     } else {
   2433         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, &lpm_entry, ALG_BKT_PTR0f, phy_bkt);
   2434         if (ALPM_CTRL(u).bkt_sharing) {
   2435             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, &lpm_entry, ALG_SUB_BKT_PTR0f, sub_bkt);
   2436         }
   2437     }
   2438     rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, lpm_index, &lpm_entry);
   2439     SOC_IF_ERROR_RETURN(rv);
   2440 
   2441     if (SOC_URPF_STATUS_GET(u)) {
   2442         int _urpf_index = soc_th_alpm_logical_idx(u, lpm_mem, pivot_index >> 1, 1)
   2443                             + (soc_mem_index_count(u, lpm_mem) >> 1);
   2444         rv = _soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY,
   2445                                 _urpf_index, &lpm_entry);
   2446         SOC_IF_ERROR_RETURN(rv);
   2447 
   2448         if ((!v6) && (pivot_index & 1)) {
   2449             soc_mem_field32_set(u, lpm_mem, &lpm_entry, ALG_BKT_PTR1f,
   2450                                 phy_bkt + SOC_TH_ALPM_BUCKET_COUNT(u));
   2451             if (ALPM_CTRL(u).bkt_sharing) {
   2452                 soc_mem_field32_set(u, lpm_mem, &lpm_entry, ALG_SUB_BKT_PTR1f, sub_bkt);
   2453             }
   2454         } else {
   2455             soc_mem_field32_set(u, lpm_mem, &lpm_entry, ALG_BKT_PTR0f,
   2456                                 phy_bkt + SOC_TH_ALPM_BUCKET_COUNT(u));
   2457             if (ALPM_CTRL(u).bkt_sharing) {
   2458                 soc_mem_field32_set(u, lpm_mem, &lpm_entry, ALG_SUB_BKT_PTR0f, sub_bkt);
   2459             }
   2460         }
   2461 
   2462         rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, _urpf_index, &lpm_entry);
   2463         SOC_IF_ERROR_RETURN(rv);
   2464     }
   2465 
   2466     return rv;
   2467 }
   2468 
   2469 
   2470 static void
   2471 _soc_th_alpm_bucket_prepare_undo(int u,
   2472                                  alpm_mem_prefix_array_t **alloc_pfx_array,
   2473                                  void **alloc_bufp,
   2474                                  void **alloc_sip_bufp,
   2475                                  int  **alloc_new_index)
   2476 {
   2477     if (*alloc_pfx_array) {
   2478         sal_free(*alloc_pfx_array);
   2479         *alloc_pfx_array = NULL;
   2480     }
   2481     if (*alloc_bufp) {
   2482         sal_free(*alloc_bufp);
   2483         *alloc_bufp = NULL;
   2484     }
   2485     if (*alloc_sip_bufp) {
   2486         sal_free(*alloc_sip_bufp);
   2487         *alloc_sip_bufp = NULL;
   2488     }
   2489     if (*alloc_new_index) {
   2490         sal_free(*alloc_new_index);
   2491         *alloc_new_index = NULL;
   2492     }
   2493 }
   2494 
   2495 
   2496 static int
   2497 _soc_th_alpm_bucket_prepare(int u, soc_mem_t mem,
   2498                             trie_t *bkt_trie,
   2499                             alpm_mem_prefix_array_t **alloc_pfx_array,
   2500                             void **alloc_bufp,
   2501                             void **alloc_sip_bufp,
   2502                             int  **alloc_new_index)
   2503 {
   2504     int i, rv = SOC_E_NONE;
   2505     int entry_size;
   2506     int alloc_size;
   2507     /* allocation pointers all set to NULL */
   2508     void *bufp = NULL, *sip_bufp = NULL;
   2509     int  *index_array = NULL;
   2510     alpm_mem_prefix_array_t *pfx_array = NULL;
   2511 
   2512     *alloc_bufp      = NULL;
   2513     *alloc_sip_bufp  = NULL;
   2514     *alloc_new_index = NULL;
   2515     *alloc_pfx_array = NULL;
   2516 
   2517     /* Alloc prefix array */
   2518     alloc_size = sizeof(alpm_mem_prefix_array_t);
   2519     pfx_array = sal_alloc(alloc_size, "prefix array");
   2520     if (pfx_array == NULL) {
   2521         goto cleanup;
   2522     }
   2523 
   2524     /* Fill prefix array */
   2525     sal_memset(pfx_array, 0, alloc_size);
   2526     rv = trie_traverse(bkt_trie, _soc_th_alpm_mem_prefix_array_cb,
   2527                        pfx_array, _TRIE_INORDER_TRAVERSE);
   2528     if (SOC_FAILURE(rv)) {
   2529         goto cleanup;
   2530     }
   2531 
   2532     /* Alloc index array */
   2533     alloc_size = sizeof(int) * pfx_array->count;
   2534     index_array = sal_alloc(alloc_size, "index_array");
   2535     if (index_array == NULL) {
   2536         goto cleanup;
   2537     }
   2538     sal_memset(index_array, -1, alloc_size);
   2539 
   2540     /* Alloc bufp & sip_bufp */
   2541     entry_size = (L3_DEFIP_ALPM_IPV6_64m == mem ||
   2542                   L3_DEFIP_ALPM_IPV6_64_1m == mem) ?
   2543                   sizeof(defip_alpm_ipv6_64_1_entry_t) :
   2544                   sizeof(defip_alpm_ipv4_1_entry_t);
   2545 
   2546     alloc_size = entry_size * pfx_array->count;
   2547     bufp = sal_alloc(alloc_size, "alloc_bufp");
   2548     if (bufp == NULL) {
   2549         goto cleanup;
   2550     }
   2551     if (SOC_URPF_STATUS_GET(u)) {
   2552         sip_bufp  = sal_alloc(alloc_size, "alloc_sip_bufp");
   2553         if (sip_bufp == NULL) {
   2554             goto cleanup;
   2555         }
   2556     }
   2557 
   2558     /* Fill bufp & sip bufp */
   2559     for (i = 0; i < pfx_array->count; i++) {
   2560         payload_t *prefix = pfx_array->prefix[i];
   2561 
   2562         if (prefix->index > 0) { /* old prefix */
   2563             rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, prefix->index,
   2564                               (uint8 *)bufp + i * entry_size);
   2565 
   2566             if (SOC_FAILURE(rv)) {
   2567                 break;
   2568             }
   2569 
   2570             if (SOC_URPF_STATUS_GET(u)) {
   2571                 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY,
   2572                         _soc_th_alpm_rpf_entry(u, prefix->index),
   2573                         (uint8 *)sip_bufp + i * entry_size);
   2574                 if (SOC_FAILURE(rv)) {
   2575                     break;
   2576                 }
   2577             }
   2578         }
   2579     }
   2580     if (SOC_FAILURE(rv)) {
   2581         goto cleanup;
   2582     }
   2583 
   2584     *alloc_bufp      = bufp;
   2585     *alloc_sip_bufp  = sip_bufp;
   2586     *alloc_new_index = index_array;
   2587     *alloc_pfx_array = pfx_array;
   2588 
   2589     return rv;
   2590 
   2591 cleanup:
   2592     if (bufp) {
   2593         sal_free(bufp);
   2594     }
   2595     if (sip_bufp) {
   2596         sal_free(sip_bufp);
   2597     }
   2598     if (index_array) {
   2599         sal_free(index_array);
   2600     }
   2601     if (pfx_array) {
   2602         sal_free(pfx_array);
   2603     }
   2604     return rv;
   2605 }
   2606 
   2607 static void
   2608 _soc_th_alpm_bucket_inval_undo(int u, soc_mem_t mem,
   2609                                alpm_mem_prefix_array_t *pfx_array,
   2610                                void *old_bufp, void *old_sip_bufp)
   2611 {
   2612     int i;
   2613     int entry_size = (L3_DEFIP_ALPM_IPV6_64m == mem ||
   2614                       L3_DEFIP_ALPM_IPV6_64_1m == mem) ?
   2615                       sizeof(defip_alpm_ipv6_64_1_entry_t) :
   2616                       sizeof(defip_alpm_ipv4_1_entry_t);
   2617 
   2618     for (i = 0; i < pfx_array->count; i++) {
   2619         payload_t *prefix = pfx_array->prefix[i];
   2620 
   2621         if (prefix->index > 0) {
   2622             soc_mem_write(u, mem, MEM_BLOCK_ALL, prefix->index,
   2623                           (uint8 *)old_bufp + i * entry_size);
   2624 
   2625             if (SOC_URPF_STATUS_GET(u)) {
   2626                 /* UPRF entry */
   2627                 soc_mem_write(u, mem, MEM_BLOCK_ALL,
   2628                               _soc_th_alpm_rpf_entry(u, prefix->index),
   2629                               (uint8 *)old_sip_bufp + i * entry_size);
   2630             }
   2631         }
   2632     }
   2633     return;
   2634 }
   2635 
   2636 
   2637 static int
   2638 _soc_th_alpm_bucket_inval(int u, soc_mem_t mem,
   2639                           alpm_mem_prefix_array_t *pfx_array,
   2640                           void *old_bufp, void *old_sip_bufp)
   2641 {
   2642     int i, rv = SOC_E_NONE;
   2643 
   2644     /* Invalidation process
   2645      * 1. Erase old copied entries
   2646      * 2. Re-validate those entries if invalidation fails
   2647      */
   2648 
   2649     for (i = 0; i < pfx_array->count; i++) {
   2650         payload_t *prefix = pfx_array->prefix[i];
   2651 
   2652         if (prefix->index >= 0) {
   2653             /* zero out old entries now that split is done */
   2654             rv = soc_mem_write(u, mem, MEM_BLOCK_ALL, prefix->index,
   2655                                soc_mem_entry_null(u, mem));
   2656             if (SOC_FAILURE(rv)) {
   2657                 break;
   2658             }
   2659             if (SOC_URPF_STATUS_GET(u)) {
   2660                 rv = soc_mem_write(u, mem, MEM_BLOCK_ANY,
   2661                                    _soc_th_alpm_rpf_entry(u, prefix->index),
   2662                                    soc_mem_entry_null(u, mem));
   2663                 if (SOC_FAILURE(rv)) {
   2664                     break;
   2665                 }
   2666             }
   2667         }
   2668     }
   2669 
   2670     /* re-validate old bucket entries */
   2671     if (SOC_FAILURE(rv)) {
   2672         _soc_th_alpm_bucket_inval_undo(u, mem, pfx_array, old_bufp, old_sip_bufp);
   2673     }
   2674 
   2675     return rv;
   2676 }
   2677 
   2678 STATIC int
   2679 _soc_th_alpm_split_lpm_init(int             u,
   2680                             soc_mem_t       mem,
   2681                             int             pivot_idx_from,
   2682                             int             vrf,
   2683                             int             log_bkt,
   2684                             void            *alpm_data,
   2685                             void            *alpm_sip_data,
   2686                             uint32          *pivot,
   2687                             int             length,
   2688                             defip_entry_t   *lpm_entry,
   2689                             uint32          *bpm_len,
   2690                             uint32          *bpm,
   2691                             uint32          *src_discard,
   2692                             uint32          *src_default)
   2693 {
   2694     int                             rv = SOC_E_NONE, v6;
   2695     trie_node_t                     *lpm = NULL;
   2696     payload_t                       *bkt_lpm = NULL;
   2697     trie_t                          *pfx_trie;
   2698     defip_alpm_ipv4_1_entry_t       alpmv4_entry, alpmv4_sip_entry;
   2699     defip_alpm_ipv6_64_1_entry_t    alpmv6_entry, alpmv6_sip_entry;
   2700     uint32                          tmp_pivot[5] = {0};
   2701 
   2702     v6 = SOC_ALPM_MEM_V6(mem);
   2703 
   2704     /* prefix trie */
   2705     if (v6) {
   2706         pfx_trie = VRF_PREFIX_TRIE_IPV6(u, vrf);
   2707     } else {
   2708         pfx_trie = VRF_PREFIX_TRIE_IPV4(u, vrf);
   2709     }
   2710 
   2711     /* find longest prefix that covers pivot */
   2712     lpm = NULL;
   2713     rv = trie_find_lpm(pfx_trie, pivot, length, &lpm);
   2714     if (SOC_FAILURE(rv)) {
   2715         LOG_ERROR(BSL_LS_SOC_ALPM,
   2716                   (BSL_META_U(u,
   2717                               "unit %d Unable to find lpm for pivot: "
   2718                               "0x%08x 0x%08x\n 0x%08x 0x%08x 0x%08x length: %d\n"),
   2719                    u, pivot[0], pivot[1], pivot[2], pivot[3], pivot[4],
   2720                    length));
   2721 
   2722         return rv;
   2723     }
   2724     bkt_lpm = ((payload_t *)lpm)->bkt_ptr;
   2725 
   2726     /* Initialize the lpm entry to insert */
   2727     if (bkt_lpm) {
   2728         int             index, vrf_id;
   2729         void            *bufp, *sip_bufp = NULL;
   2730 
   2731         SOC_ALPM_ENTRY_BUF(v6, mem, bufp, alpmv4_entry, alpmv6_entry);
   2732         SOC_ALPM_ENTRY_BUF(v6, mem, sip_bufp, alpmv4_sip_entry, alpmv6_sip_entry);
   2733 
   2734         /* this means this bucket default route is an actual route */
   2735         /* initialize new pivot's associated data with data of lpm match */
   2736         index = bkt_lpm->index;
   2737         if (index == -1) {
   2738             /* this means the new route is the bucket's default */
   2739             if (alpm_data == NULL || alpm_sip_data == NULL) {
   2740                 return SOC_E_PARAM;
   2741             }
   2742             sal_memcpy(bufp, alpm_data, v6 ?
   2743                        sizeof(defip_alpm_ipv6_64_1_entry_t) :
   2744                        sizeof(defip_alpm_ipv4_1_entry_t));
   2745              if (SOC_URPF_STATUS_GET(u)) {
   2746                 *src_default = soc_mem_field32_get(u, mem, alpm_sip_data,
   2747                                                           DEFAULTROUTEf);
   2748                 *src_discard = soc_mem_field32_get(u, mem, alpm_sip_data,
   2749                                                           SRC_DISCARDf);
   2750             }
   2751         } else {
   2752             rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, index, bufp);
   2753             if (SOC_FAILURE(rv)) {
   2754                 return rv;
   2755             }
   2756             if (SOC_URPF_STATUS_GET(u)) {
   2757                 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY,
   2758                                         _soc_th_alpm_rpf_entry(u, index),
   2759                                         sip_bufp);
   2760                 *src_default = soc_mem_field32_get(u, mem, sip_bufp,
   2761                                                           DEFAULTROUTEf);
   2762                 *src_discard = soc_mem_field32_get(u, mem, sip_bufp,
   2763                                                           SRC_DISCARDf);
   2764             }
   2765         }
   2766         if (SOC_FAILURE(rv)) {
   2767             return rv;
   2768         }
   2769 
   2770         vrf_id = vrf;
   2771         if (vrf == (SOC_VRF_MAX(u) + 1)) {
   2772             vrf_id = SOC_L3_VRF_GLOBAL;
   2773         }
   2774         rv = _soc_th_alpm_lpm_ent_init(u, bufp, mem, v6, vrf_id, log_bkt,
   2775                                        index, lpm_entry,
   2776                                        VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 1));
   2777         if (SOC_FAILURE(rv)) {
   2778             return rv;
   2779         }
   2780         /* remember the bpm_len of this pivot. Need to put in shadow */
   2781         *bpm_len = bkt_lpm->len;
   2782         if (ALPM_CTRL(u).trie_propagate) {
   2783             (void)trie_bpm_mask_get(pfx_trie, bkt_lpm->key, *bpm_len, bpm);
   2784         }
   2785     } else {
   2786         /* read default data of current pivot */
   2787         /* This case is for those route without default route 0.0.0.0/0,
   2788          * e.g. Parallel mode / (Combined mode + global low)
   2789          * An internal assiciated data is used.
   2790          */
   2791         rv = _soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY,
   2792                    soc_th_alpm_logical_idx(u, L3_DEFIPm, pivot_idx_from >> 1, 1),
   2793                    lpm_entry);
   2794         if (SOC_FAILURE(rv)) {
   2795             return rv;
   2796         }
   2797         if ((!v6) && (pivot_idx_from & 1)) {
   2798             /* move entry to 0 half */
   2799             rv = soc_th_alpm_lpm_ip4entry1_to_0(u, lpm_entry, lpm_entry, 0);
   2800         }
   2801         /* Need to reset ALG_HIT_IDX0 to 0. */
   2802         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ALG_HIT_IDX0f, 0);
   2803 
   2804         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ALG_BKT_PTR0f,
   2805                             ALPM_PHY_BKT(u, log_bkt));
   2806         if (ALPM_CTRL(u).bkt_sharing) {
   2807             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ALG_SUB_BKT_PTR0f,
   2808                                 ALPM_SUB_BKT(u, log_bkt));
   2809         }
   2810     }
   2811 
   2812     /* Convert is a self-modified op, thus use tmp one */
   2813     sal_memcpy(tmp_pivot, pivot, sizeof(tmp_pivot));
   2814 
   2815     /* Convert from trie format to h/w format */
   2816     ALPM_TRIE_TO_NORMAL_IP(tmp_pivot, length, v6);
   2817     _soc_th_alpm_lpm_ent_key_init(u, tmp_pivot, length, vrf, v6,
   2818                                   lpm_entry, 0);
   2819 
   2820     return rv;
   2821 }
   2822 
   2823 
   2824 static int
   2825 _soc_th_alpm_split_pivot_create_undo(int u, int v6, int vrf, uint32 *pivot,
   2826                                      uint32 length, alpm_pivot_t *alpm_pivot,
   2827                                      int clear)
   2828 {
   2829     int                         rv = SOC_E_NONE, pivot_index;
   2830     alpm_bucket_handle_t        *bucket_handle;
   2831     trie_t                      *pivot_trie = NULL;
   2832     trie_node_t                 *delp = NULL;
   2833 
   2834     if (v6) {
   2835         pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf);
   2836     } else {
   2837         pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf);
   2838     }
   2839 
   2840     if (alpm_pivot == NULL) {
   2841         rv = trie_delete(pivot_trie, pivot, length, &delp);
   2842         alpm_pivot = (alpm_pivot_t *) delp;
   2843     }
   2844     if (SOC_SUCCESS(rv)) {
   2845         bucket_handle   = alpm_pivot->bucket;
   2846         pivot_index     = PIVOT_TCAM_INDEX(alpm_pivot);
   2847 
   2848         trie_destroy(PIVOT_BUCKET_TRIE(alpm_pivot));
   2849         sal_free(alpm_pivot);
   2850         sal_free(bucket_handle);
   2851 
   2852         /* For normal destroy (other than rollback) when the entry is deleted
   2853          * from lpm. The pivot_index is already replaced to another index.
   2854          */
   2855         if (clear) {
   2856             ALPM_TCAM_PIVOT(u, pivot_index) = NULL;
   2857         }
   2858     }
   2859 
   2860     return rv;
   2861 }
   2862 
   2863 
   2864 
   2865 static int
   2866 _soc_th_alpm_split_pivot_create(int u, int v6, int vrf, int log_bkt_to,
   2867                                 trie_node_t     *split_trie_root,
   2868                                 uint32          *pivot,
   2869                                 uint32          length,
   2870                                 uint32          bpm_len,
   2871                                 uint32          *bpm,
   2872                                 alpm_pivot_t    **new_pivot)
   2873 {
   2874     int                             rv = SOC_E_NONE;
   2875     alpm_pivot_t                    *pivot_pyld_new;
   2876     alpm_bucket_handle_t            *bucket_handle;
   2877     trie_t                          *pivot_trie = NULL;
   2878     if (v6) {
   2879         pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf);
   2880     } else {
   2881         pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf);
   2882     }
   2883 
   2884     /* Add New Pivot to the pivot trie */
   2885     bucket_handle = sal_alloc(sizeof(alpm_bucket_handle_t),
   2886                              "ALPM Bucket Handle");
   2887     if (bucket_handle == 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         return SOC_E_MEMORY;
   2893     }
   2894     sal_memset(bucket_handle, 0, sizeof(*bucket_handle));
   2895     pivot_pyld_new = sal_alloc(sizeof(alpm_pivot_t),
   2896                             "Payload for new Pivot");
   2897     if (pivot_pyld_new == NULL) {
   2898         LOG_ERROR(BSL_LS_SOC_ALPM,
   2899                   (BSL_META_U(u,
   2900                               "Unable to allocate memory "
   2901                               "for PIVOT trie node \n")));
   2902         sal_free(bucket_handle);
   2903         return SOC_E_MEMORY;
   2904     }
   2905     sal_memset(pivot_pyld_new, 0, sizeof(*pivot_pyld_new));
   2906     PIVOT_BUCKET_HANDLE(pivot_pyld_new) = bucket_handle;
   2907     (void) trie_init(v6 ? _MAX_KEY_LEN_144_ :_MAX_KEY_LEN_48_,
   2908                      &PIVOT_BUCKET_TRIE(pivot_pyld_new));
   2909     PIVOT_BUCKET_TRIE(pivot_pyld_new)->trie  = split_trie_root;
   2910     PIVOT_BUCKET_INDEX(pivot_pyld_new)       = log_bkt_to;
   2911     PIVOT_BUCKET_VRF(pivot_pyld_new)         = vrf;
   2912     PIVOT_BUCKET_IPV6(pivot_pyld_new)        = v6;
   2913     PIVOT_BUCKET_DEF(pivot_pyld_new)         = FALSE;
   2914     PIVOT_TCAM_BPMLEN(pivot_pyld_new)        = bpm_len;
   2915 
   2916     (pivot_pyld_new)->key[0] = pivot[0];
   2917     (pivot_pyld_new)->key[1] = pivot[1];
   2918     (pivot_pyld_new)->key[2] = pivot[2];
   2919     (pivot_pyld_new)->key[3] = pivot[3];
   2920     (pivot_pyld_new)->key[4] = pivot[4];
   2921     (pivot_pyld_new)->len    = length;
   2922 
   2923     rv = trie_insert(pivot_trie, pivot,
   2924                      ALPM_CTRL(u).trie_propagate ? bpm : NULL,
   2925                      length, (trie_node_t *)pivot_pyld_new);
   2926 
   2927     if (SOC_SUCCESS(rv)) {
   2928         if (new_pivot) {
   2929             *new_pivot = pivot_pyld_new;
   2930         }
   2931     } else {
   2932         LOG_ERROR(BSL_LS_SOC_ALPM,
   2933                   (BSL_META_U(u, "could not initialize pivot")));
   2934         _soc_th_alpm_split_pivot_create_undo(u, v6, vrf, pivot,
   2935                                              length, pivot_pyld_new, 1);
   2936     }
   2937 
   2938     return rv;
   2939 }
   2940 
   2941 
   2942 static void
   2943 _soc_th_alpm_bucket_copy_undo(int u, soc_mem_t mem, int count, int *new_index)
   2944 {
   2945     int i;
   2946     for (i = 0; i < count; i++) {
   2947         if (new_index[i] < 0) {
   2948             continue;
   2949         }
   2950         soc_mem_write(u, mem, MEM_BLOCK_ANY, new_index[i],
   2951                       soc_mem_entry_null(u, mem));
   2952         if (SOC_URPF_STATUS_GET(u)) {
   2953             soc_mem_write(u, mem, MEM_BLOCK_ANY,
   2954                           _soc_th_alpm_rpf_entry(u, new_index[i]),
   2955                           soc_mem_entry_null(u, mem));
   2956         }
   2957     }
   2958 }
   2959 
   2960 
   2961 /* Populate entries in pfx array to logical bucket */
   2962 static int
   2963 _soc_th_alpm_bucket_copy(int u, soc_mem_t mem, int vrf,
   2964                          alpm_mem_prefix_array_t *pfx_array,
   2965                          int log_bkt_to,
   2966                          void *old_bufp,
   2967                          void *old_sip_bufp,
   2968                          void *new_bufp,
   2969                          void *new_sip_bufp,
   2970                          int *new_index,
   2971                          int *new_index_pos)
   2972 {
   2973     int                             rv = SOC_E_NONE;
   2974     defip_alpm_ipv4_1_entry_t       alpmv4_entry, alpmv4_sip_entry;
   2975     defip_alpm_ipv6_64_1_entry_t    alpmv6_entry, alpmv6_sip_entry;
   2976     void                            *bufp, *sip_bufp;
   2977     int                             sub_bkt_to;
   2978     int                             entsz, key_index;
   2979     uint32                          bank_disable = 0;
   2980     int                             v6, i;
   2981     uint32                          e[SOC_MAX_MEM_FIELD_WORDS];
   2982 
   2983     sub_bkt_to = ALPM_SUB_BKT(u, log_bkt_to);
   2984 
   2985     bank_disable =
   2986         ALPM_CTRL(u).bank_disable_bmp[vrf != (SOC_VRF_MAX(u) + 1)];
   2987 
   2988     v6 = (L3_DEFIP_ALPM_IPV6_64m == mem ||
   2989           L3_DEFIP_ALPM_IPV6_64_1m == mem ||
   2990           L3_DEFIP_ALPM_IPV6_128m == mem);
   2991 
   2992     SOC_ALPM_ENTRY_BUF(v6, mem, bufp, alpmv4_entry, alpmv6_entry);
   2993     SOC_ALPM_ENTRY_BUF(v6, mem, sip_bufp, alpmv4_sip_entry, alpmv6_sip_entry);
   2994     entsz = v6 ? sizeof(defip_alpm_ipv6_64_1_entry_t) :
   2995                  sizeof(defip_alpm_ipv4_1_entry_t);
   2996 
   2997     for (i = 0; i < pfx_array->count; i++) {
   2998         if (pfx_array->prefix[i]->index > 0) { /* old prefix */
   2999             sal_memcpy(bufp, (uint8 *)old_bufp + i * entsz, entsz);
   3000             soc_mem_field32_set(u, mem, bufp, SUB_BKT_PTRf, sub_bkt_to);
   3001             /* entry shouldn't exist, insert the entry into the RAM */
   3002 
   3003             if (SOC_URPF_STATUS_GET(u)) {
   3004                 sal_memcpy(sip_bufp, (uint8 *)old_sip_bufp + i * entsz, entsz);
   3005             }
   3006 
   3007             rv = _soc_th_alpm_insert_in_bkt(u, mem, log_bkt_to,
   3008                                             bank_disable, bufp, sip_bufp, e,
   3009                                             &key_index, v6);
   3010 
   3011 
   3012         } else { /* for split case only */
   3013             if (!new_bufp || !new_index_pos) {
   3014                 rv = SOC_E_PARAM;
   3015                 goto _rollback;
   3016             }
   3017             *new_index_pos = i;
   3018             soc_mem_field32_set(u, mem, new_bufp, SUB_BKT_PTRf, sub_bkt_to);
   3019             rv = _soc_th_alpm_insert_in_bkt(u, mem, log_bkt_to,
   3020                                             bank_disable, new_bufp, new_sip_bufp, e,
   3021                                             &key_index, v6);
   3022         }
   3023         if (SOC_FAILURE(rv)) {
   3024             LOG_ERROR(BSL_LS_SOC_ALPM,
   3025                       (BSL_META_U(u,
   3026                                   "Failed to insert prefix "
   3027                                   "0x%08x 0x%08x 0x%08x 0x%08x to bucket %d\n"),
   3028                        pfx_array->prefix[i]->key[1],
   3029                        pfx_array->prefix[i]->key[2],
   3030                        pfx_array->prefix[i]->key[3],
   3031                        pfx_array->prefix[i]->key[4], log_bkt_to));
   3032 
   3033             goto _rollback;
   3034         }
   3035         new_index[i] = key_index;
   3036     }
   3037 
   3038 _rollback:
   3039     if (SOC_FAILURE(rv)) {
   3040         /* Delete entries in new bucket */
   3041         _soc_th_alpm_bucket_copy_undo(u, mem, pfx_array->count, new_index);
   3042     }
   3043 
   3044     return rv;
   3045 }
   3046 
   3047 
   3048 /* Merge entries from one logical bucket to another */
   3049 static int
   3050 _soc_th_alpm_bucket_merge(int u, soc_mem_t mem, int log_bkt_from,
   3051                           int log_bkt_to, soc_alpm_merge_type_t merge_dir,
   3052                           int *shuffled)
   3053 {
   3054     int                     *new_index = NULL;
   3055     int                     rv = SOC_E_NONE;
   3056     int                     pivot_idx_from, pivot_idx_to;
   3057     int                     v6, i;
   3058     int                     vrf = 0;
   3059     int                     phy_bkt_from, sub_bkt_from, phy_bkt_to, sub_bkt_to;
   3060     void                    *bufp = NULL, *sip_bufp = NULL;
   3061     alpm_mem_prefix_array_t *pfx_array = NULL;
   3062     defip_entry_t           lpm_entry;
   3063     alpm_pivot_t            *from_pivot;
   3064     alpm_pivot_t            *parent_pivot = NULL, *child_pivot = NULL;
   3065     enum {
   3066         _MERGE_NONE,
   3067         _MERGE_PREPARE,
   3068         _MERGE_COPY,
   3069         _MERGE_LPM_LINK,
   3070         _MERGE_INVALIDATE,
   3071         _MERGE_CHILD_TRIE_MERGED,
   3072         _MERGE_CHILD_LPM_DELETED,
   3073         _MERGE_CHILD_PIVOT_DESTROYED
   3074     } doing = _MERGE_NONE, done = _MERGE_NONE;
   3075 
   3076     phy_bkt_from  = ALPM_PHY_BKT(u, log_bkt_from);
   3077     sub_bkt_from  = ALPM_SUB_BKT(u, log_bkt_from);
   3078     phy_bkt_to    = ALPM_PHY_BKT(u, log_bkt_to);
   3079     sub_bkt_to    = ALPM_SUB_BKT(u, log_bkt_to);
   3080 
   3081     v6 = (L3_DEFIP_ALPM_IPV6_64m == mem ||
   3082           L3_DEFIP_ALPM_IPV6_64_1m == mem ||
   3083           L3_DEFIP_ALPM_IPV6_128m == mem);
   3084 
   3085     pivot_idx_from = SOC_ALPM_BU_PIVOT_IDX(u, phy_bkt_from, sub_bkt_from);
   3086     pivot_idx_to = SOC_ALPM_BU_PIVOT_IDX(u, phy_bkt_to, sub_bkt_to);
   3087 
   3088     from_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_from);
   3089 
   3090     vrf = PIVOT_BUCKET_VRF(from_pivot);
   3091 
   3092     /**
   3093      * Invalidate need to happen only after all the entries are
   3094      * written to the new pivot and the new pivot is valid. Otherwise
   3095      * there is a chance of MISS.
   3096      *
   3097      * hitless move:
   3098      * - Copy entries to new bucket.
   3099      * - activate new pivot
   3100      * - delete entries from old bucket
   3101      */
   3102 
   3103     doing = _MERGE_PREPARE;
   3104     rv = _soc_th_alpm_bucket_prepare(u, mem, PIVOT_BUCKET_TRIE(from_pivot),
   3105                                      &pfx_array, &bufp, &sip_bufp, &new_index);
   3106     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3107 
   3108     doing = _MERGE_COPY;
   3109     rv = _soc_th_alpm_bucket_copy(u, mem, vrf, pfx_array,
   3110                                   log_bkt_to, bufp, sip_bufp,
   3111                                   NULL, NULL, new_index, NULL);
   3112     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3113 
   3114     /* Connect TCAM entry to new bucket.
   3115      * This is a must step even for merge child to parent
   3116      */
   3117     doing = _MERGE_LPM_LINK;
   3118     rv = _soc_th_alpm_bucket_link(u, v6, pivot_idx_from, log_bkt_to);
   3119     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3120 
   3121     /* Invalide old entries */
   3122     doing = _MERGE_INVALIDATE;
   3123     rv = _soc_th_alpm_bucket_inval(u, mem, pfx_array, bufp, sip_bufp);
   3124     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3125 
   3126     if (merge_dir != MERGE_PHY) {
   3127         uint32          hw_key[5] = {0};
   3128         int             child_vrf;
   3129 
   3130         if (merge_dir == MERGE_LOG_PARENT_TO_CHILD) {
   3131             parent_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_from);
   3132             child_pivot  = ALPM_TCAM_PIVOT(u, pivot_idx_to);
   3133         } else if (merge_dir == MERGE_LOG_CHILD_TO_PARENT) {
   3134             child_pivot  = ALPM_TCAM_PIVOT(u, pivot_idx_from);
   3135             parent_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_to);
   3136         }
   3137 
   3138         /* SW bucket merge: not expect to fail */
   3139         doing = _MERGE_CHILD_TRIE_MERGED;
   3140         rv = trie_merge(PIVOT_BUCKET_TRIE(parent_pivot),
   3141                         PIVOT_BUCKET_TRIE(child_pivot)->trie,
   3142                         child_pivot->key,
   3143                         child_pivot->len);
   3144         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3145 
   3146         sal_memcpy(hw_key, child_pivot->key, sizeof(hw_key));
   3147         ALPM_TRIE_TO_NORMAL_IP(hw_key, child_pivot->len, v6);
   3148 
   3149         child_vrf = PIVOT_BUCKET_VRF(child_pivot);
   3150 
   3151         (void) _soc_th_alpm_lpm_ent_key_init(u, hw_key, child_pivot->len,
   3152                                       child_vrf, v6, &lpm_entry, 1);
   3153 
   3154         /* Delete child lpm entry from TCAM */
   3155         doing = _MERGE_CHILD_LPM_DELETED;
   3156         rv = soc_th_alpm_lpm_delete(u, &lpm_entry);
   3157         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3158         if (shuffled) {
   3159             *shuffled = 1;
   3160         }
   3161 
   3162         /* Destroy child pivot from trie */
   3163         doing = _MERGE_CHILD_PIVOT_DESTROYED;
   3164         rv = _soc_th_alpm_split_pivot_create_undo
   3165                     (u, v6, child_vrf, child_pivot->key, child_pivot->len, NULL, 0);
   3166 
   3167         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3168     }
   3169 
   3170     /* Update hit bits */
   3171     rv = soc_th_alpm_hit_bits_update(u, pfx_array, new_index, v6, vrf);
   3172     if (SOC_FAILURE(rv)) {
   3173         LOG_ERROR(BSL_LS_SOC_ALPM,
   3174                   (BSL_META_U(u, "update_hit_bits failed, count %d\n"),
   3175                               pfx_array->count));
   3176         rv = SOC_E_NONE;
   3177     }
   3178 
   3179     /* Update TCAM mgmt info: set new logical bucket */
   3180     if (merge_dir != MERGE_LOG_CHILD_TO_PARENT && ALPM_TCAM_PIVOT(u, pivot_idx_from)) {
   3181         PIVOT_BUCKET_INDEX(ALPM_TCAM_PIVOT(u, pivot_idx_from)) = log_bkt_to;
   3182     }
   3183 
   3184     soc_th_alpm_bucket_usage_decr(u, log_bkt_from, TRUE, vrf, mem, pfx_array->count, log_bkt_to);
   3185     soc_th_alpm_bucket_usage_incr(u, log_bkt_to,
   3186                                   (merge_dir == MERGE_LOG_CHILD_TO_PARENT) ?
   3187                                   pivot_idx_to : pivot_idx_from,
   3188                                   vrf, mem, pfx_array->count);
   3189 
   3190     /* Update new index */
   3191     for (i = 0; i < pfx_array->count; i++) {
   3192         pfx_array->prefix[i]->index = new_index[i];
   3193     }
   3194 
   3195     _soc_th_alpm_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index);
   3196     return rv;
   3197 
   3198 _rollback:
   3199 
   3200     /* fall through on all cases */
   3201     switch (done)  {
   3202     case _MERGE_CHILD_LPM_DELETED:
   3203         if (merge_dir != MERGE_PHY) {
   3204             /* not expecting any failure after lpm deleted */
   3205         }
   3206 
   3207     case _MERGE_CHILD_TRIE_MERGED:
   3208         if (merge_dir != MERGE_PHY) {
   3209             uint32      pivot[5], length;
   3210             trie_split2(PIVOT_BUCKET_TRIE(parent_pivot),
   3211                         child_pivot->key,
   3212                         child_pivot->len,
   3213                         pivot, &length,
   3214                         &(PIVOT_BUCKET_TRIE(child_pivot)->trie),
   3215                         PIVOT_BUCKET_COUNT(child_pivot),
   3216                         1);
   3217         }
   3218 
   3219     case _MERGE_INVALIDATE:
   3220         _soc_th_alpm_bucket_inval_undo(u, mem, pfx_array, bufp, sip_bufp);
   3221 
   3222     case _MERGE_LPM_LINK:
   3223         /* Connect TCAM back to original bucket */
   3224         _soc_th_alpm_bucket_link(u, v6, pivot_idx_from, log_bkt_from);
   3225 
   3226     case _MERGE_COPY:
   3227         /* Delete entries in new bucket */
   3228         _soc_th_alpm_bucket_copy_undo(u, mem, pfx_array->count, new_index);
   3229 
   3230     case _MERGE_PREPARE:
   3231         _soc_th_alpm_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index);
   3232 
   3233     case _MERGE_NONE:
   3234     default:
   3235         break;
   3236     }
   3237 
   3238     /* Error dump */
   3239     switch (doing)  {
   3240     case _MERGE_LPM_LINK:
   3241         LOG_ERROR(BSL_LS_SOC_ALPM,
   3242                   (BSL_META_U(u,
   3243                               "_soc_th_alpm_bucket_link failed, pivot %d log_bkt %d\n"),
   3244                               pivot_idx_from, log_bkt_to));
   3245         break;
   3246 
   3247     case _MERGE_INVALIDATE:
   3248         LOG_ERROR(BSL_LS_SOC_ALPM,
   3249                   (BSL_META_U(u,
   3250                               "_soc_th_alpm_bucket_inval failed\n")));
   3251         break;
   3252     case _MERGE_CHILD_TRIE_MERGED:
   3253         break;
   3254 
   3255     case _MERGE_CHILD_PIVOT_DESTROYED:
   3256         LOG_ERROR(BSL_LS_SOC_ALPM,
   3257                   (BSL_META_U(u,
   3258                               "Pivot destroy fail, something not expected\n")));
   3259     default:
   3260         LOG_ERROR(BSL_LS_SOC_ALPM,
   3261                   (BSL_META_U(u,
   3262                               "Merge fails at step %d\n"), doing));
   3263         break;
   3264     }
   3265 
   3266     return rv;
   3267 }
   3268 
   3269 /* Merge physical bucket 1 to bucket 2 */
   3270 STATIC int
   3271 _soc_th_alpm_bucket_share(int u, soc_mem_t mem, int phy_bkt_from, int phy_bkt_to)
   3272 {
   3273     /* if we go to here, the following condition MUST be met:
   3274      * 1) Total subbucket num of two buckets <= 4.
   3275      * 2) Total entry num of two buckets <= max entry of this bucket view
   3276      * 3) Same bucket view for these two buckets.
   3277      *
   3278      * We don't check condition here. Caller does.
   3279      */
   3280 
   3281     /* Use add-move-invalidate to avoid traffic interrupt */
   3282     int rv = SOC_E_NONE;
   3283     int sub_bkt_from, sub_bkt_to;
   3284 
   3285     /* 1) Get used sub bucket from bucket1 */
   3286     for (sub_bkt_from = 0; sub_bkt_from < SOC_TH_MAX_SUB_BUCKETS; sub_bkt_from++) {
   3287         /* Skip non-exist sub buckets */
   3288         if (!(SOC_ALPM_BU_SUB_BKT_IS_SET(u, phy_bkt_from, sub_bkt_from))) {
   3289             continue;
   3290         }
   3291         for (sub_bkt_to = 0; sub_bkt_to < SOC_TH_MAX_SUB_BUCKETS; sub_bkt_to++) {
   3292             if (SOC_ALPM_BU_SUB_BKT_IS_SET(u, phy_bkt_to, sub_bkt_to)) {
   3293                 continue;
   3294             }
   3295 
   3296             if (mem == L3_DEFIP_ALPM_IPV6_128m) {
   3297                 rv = _soc_th_alpm_128_bucket_merge(u, mem, ALPM_LOG_BKT(phy_bkt_from, sub_bkt_from),
   3298                                                    ALPM_LOG_BKT(phy_bkt_to, sub_bkt_to), MERGE_PHY,
   3299                                                    NULL);
   3300             } else {
   3301                 rv = _soc_th_alpm_bucket_merge(u, mem,
   3302                                                ALPM_LOG_BKT(phy_bkt_from, sub_bkt_from),
   3303                                                ALPM_LOG_BKT(phy_bkt_to, sub_bkt_to),
   3304                                                MERGE_PHY, NULL);
   3305             }
   3306             SOC_IF_ERROR_RETURN(rv);
   3307             break;
   3308         }
   3309     }
   3310 
   3311     _alpm_dbg_cntr[u].bkt_share++;
   3312 
   3313     return SOC_E_NONE;
   3314 }
   3315 
   3316 STATIC int
   3317 _soc_th_alpm_can_buckets_share(int u, int phy_bkt1, int phy_bkt2)
   3318 {
   3319     if (phy_bkt1 != phy_bkt2 &&
   3320         SOC_ALPM_BU_COUNT(u, phy_bkt1) && SOC_ALPM_BU_COUNT(u, phy_bkt2) &&
   3321         /* both Private or both Global*/
   3322         (SOC_ALPM_BU_GLOBAL(u, phy_bkt1) == SOC_ALPM_BU_GLOBAL(u, phy_bkt2)) &&
   3323         (_shr_popcount((uint32)SOC_ALPM_BU_SUB_BKTS(u, phy_bkt1)) +
   3324          _shr_popcount((uint32)SOC_ALPM_BU_SUB_BKTS(u, phy_bkt2)) <=
   3325          SOC_TH_MAX_SUB_BUCKETS)) {
   3326          return 1;
   3327     }
   3328     return 0;
   3329 }
   3330 
   3331 /* Find two qualified physical buckets and merge them into one,
   3332  * such that one of them become free.
   3333  */
   3334 static int
   3335 _soc_th_alpm_share(int u, soc_mem_t mem, int *log_bkt)
   3336 {
   3337     int                 cnt, cnt2, bkt_cnt;
   3338     int                 phy_bkt, phy_bkt1, phy_bkt2, view;
   3339     SHR_BITDCL          *bkt_bmp, *bkt_bmp2;
   3340     /* be consistent with SOC_ALPM_MEM_VIEW */
   3341     soc_mem_t           alpm_mem[] =   {L3_DEFIP_ALPM_IPV4m,
   3342                                         L3_DEFIP_ALPM_IPV6_64m,
   3343                                         L3_DEFIP_ALPM_IPV6_128m,
   3344                                         L3_DEFIP_ALPM_IPV4_1m,
   3345                                         L3_DEFIP_ALPM_IPV6_64_1m};
   3346 
   3347     for (view = 0; view < SOC_TH_MAX_ALPM_VIEWS; view++) {
   3348         if (ALPM_CTRL(u)._alpm_128b_bkt_rsvd &&
   3349             ((!!SOC_ALPM_MEM_V6(mem)) != (!!SOC_ALPM_MEM_V6(alpm_mem[view])))) {
   3350             continue;
   3351         }
   3352         bkt_cnt = _soc_th_alpm_bkt_entry_cnt(u, alpm_mem[view]);
   3353 
   3354         /* Assure total count of two buckets won't exceed max */
   3355         for (cnt = 1; cnt <= (bkt_cnt / 2); cnt++) {
   3356             phy_bkt1 = phy_bkt2 = 0;
   3357 
   3358             /* Skip empty entry */
   3359             if (SOC_ALPM_GBU_BKT_COUNT(u, view, cnt) <= 0) {
   3360                 continue;
   3361             }
   3362             bkt_bmp = SOC_ALPM_GBU_BKT_BMP(u, view, cnt);
   3363 
   3364             for (phy_bkt = 1; phy_bkt < ALPM_CTRL(u).num_bkts; phy_bkt++) {
   3365                 if (SHR_BITGET(bkt_bmp, phy_bkt) &&
   3366                     SOC_ALPM_BU_SUB_BKTS(u, phy_bkt) != 0xF) {
   3367 
   3368                     if (phy_bkt1 == 0) {
   3369                         phy_bkt1 = phy_bkt;
   3370                     } else if (_soc_th_alpm_can_buckets_share(u, phy_bkt1, phy_bkt)) {
   3371                         phy_bkt2 = phy_bkt;
   3372                         break;
   3373                     }
   3374                 }
   3375             }
   3376 
   3377             if (phy_bkt1 == 0) {
   3378                 continue;
   3379             }
   3380 
   3381             /* First physical bucket is found, now find second one */
   3382             for (cnt2 = cnt + 1;
   3383                  cnt2 <= (bkt_cnt - cnt) && phy_bkt2 == 0;
   3384                  cnt2++) {
   3385 
   3386                 /* Skip empty entry */
   3387                 if (SOC_ALPM_GBU_BKT_COUNT(u, view, cnt2) <= 0) {
   3388                     continue;
   3389                 }
   3390                 bkt_bmp2 = SOC_ALPM_GBU_BKT_BMP(u, view, cnt2);
   3391 
   3392                 for (phy_bkt = 1; phy_bkt < ALPM_CTRL(u).num_bkts; phy_bkt++) {
   3393                     if (SHR_BITGET(bkt_bmp2, phy_bkt) &&
   3394                         SOC_ALPM_BU_SUB_BKTS(u, phy_bkt) != 0xF) {
   3395 
   3396                         if (_soc_th_alpm_can_buckets_share(u, phy_bkt1, phy_bkt)) {
   3397                             phy_bkt2 = phy_bkt;
   3398                             break;
   3399                         }
   3400                     }
   3401                 }
   3402             }
   3403 
   3404             if (phy_bkt2) {
   3405                 /* Move all entries in phy_bkt1 to phy_bkt2,
   3406                  * and return phy_bkt1 as an empty bucket.
   3407                  */
   3408                 SOC_IF_ERROR_RETURN(
   3409                     _soc_th_alpm_bucket_share(u, alpm_mem[view], phy_bkt1, phy_bkt2));
   3410                 *log_bkt = ALPM_LOG_BKT(phy_bkt1, 0);
   3411                 return SOC_E_NONE;
   3412             }
   3413         } /* for cnt */
   3414     }
   3415 
   3416     return SOC_E_FULL;
   3417 }
   3418 
   3419 
   3420 STATIC int
   3421 _soc_th_alpm_lpm_free_entries(int u, soc_mem_t mem, int vrf)
   3422 {
   3423     int curr_pfx, min_pfx;
   3424     int total_fent = 0;
   3425 
   3426     if (mem == L3_DEFIP_ALPM_IPV6_128m) {
   3427         return _soc_th_alpm_128_lpm_free_entries(u, vrf);
   3428     }
   3429 
   3430     curr_pfx = ALPM_MAX_PFX_INDEX;
   3431     min_pfx  = 0;
   3432     if (ALPM_CTRL(u).gp_zoned) {
   3433         if (vrf == (SOC_VRF_MAX(u) + 1)) { /* Global VRF */
   3434             min_pfx  = ALPM_MAX_VRF_PFX_INDEX + 1;
   3435         } else {
   3436             curr_pfx = ALPM_MAX_VRF_PFX_INDEX;
   3437         }
   3438     }
   3439     while (curr_pfx >= min_pfx) {
   3440         total_fent += SOC_ALPM_LPM_STATE_FENT(u, curr_pfx);
   3441         curr_pfx = SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx);
   3442     }
   3443 
   3444     return total_fent;
   3445 }
   3446 
   3447 
   3448 /* Move partial entries from one logical bucket to another */
   3449 static int
   3450 _soc_th_alpm_bucket_repartition(int u, soc_mem_t mem, int log_bkt_from,
   3451                                 int log_bkt_to, int max_count,
   3452                                 trie_node_t **new_trie,
   3453                                 int *shuffled)
   3454 {
   3455     trie_node_t             *split_trie_root = NULL;
   3456     uint32                  length, bpm_len = 0;
   3457     uint32                  pivot[5];
   3458     uint32                  bpm[5] = {0};
   3459     defip_entry_t           lpm_entry;
   3460     alpm_mem_prefix_array_t *pfx_array = NULL;
   3461     int                     *new_index = NULL;
   3462     int                     rv = SOC_E_NONE, i;
   3463     int                     tcam_index, pivot_index;
   3464     int                     pivot_idx_from, pivot_idx_to;
   3465     int                     vrf = 0;
   3466     void                    *bufp = NULL, *sip_bufp = NULL;
   3467     uint32                  src_discard, src_default;
   3468     int                     phy_bkt_from, sub_bkt_from, phy_bkt_to, sub_bkt_to;
   3469     int                     max_split_count;
   3470     alpm_pivot_t            *new_pivot, *parent_pivot, *child_pivot;
   3471     int         v6 = (L3_DEFIP_ALPM_IPV6_64m == mem ||
   3472                       L3_DEFIP_ALPM_IPV6_64_1m == mem ||
   3473                       L3_DEFIP_ALPM_IPV6_128m == mem);
   3474     enum {
   3475         _REPART_TRIE_NONE,
   3476         _REPART_TRIE_SPLIT,
   3477         _REPART_LPM_INIT,
   3478         _REPART_PIVOT_CREATE,
   3479         _REPART_PREPARE,
   3480         _REPART_COPY,
   3481         _REPART_LPM_INSERT,
   3482         _REPART_INVALIDATE,
   3483         _REPART_CHILD_TRIE_MERGED,
   3484         _REPART_CHILD_LPM_DELETED,
   3485         _REPART_CHILD_PIVOT_DESTROYED
   3486     } doing = _REPART_TRIE_NONE, done = _REPART_TRIE_NONE;
   3487 
   3488     phy_bkt_from  = ALPM_PHY_BKT(u, log_bkt_from);
   3489     sub_bkt_from  = ALPM_SUB_BKT(u, log_bkt_from);
   3490     phy_bkt_to    = ALPM_PHY_BKT(u, log_bkt_to);
   3491     sub_bkt_to    = ALPM_SUB_BKT(u, log_bkt_to);
   3492 
   3493     pivot_idx_from = SOC_ALPM_BU_PIVOT_IDX(u, phy_bkt_from, sub_bkt_from);
   3494     pivot_idx_to   = SOC_ALPM_BU_PIVOT_IDX(u, phy_bkt_to, sub_bkt_to);
   3495 
   3496     parent_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_from);
   3497     child_pivot  = ALPM_TCAM_PIVOT(u, pivot_idx_to);
   3498 
   3499     max_split_count = max_count - SOC_ALPM_BU_COUNT(u, phy_bkt_to);
   3500     assert(max_split_count >= 0);
   3501     if (max_split_count == 0) {
   3502         return SOC_E_NONE;
   3503     }
   3504 
   3505     doing = _REPART_TRIE_SPLIT;
   3506     rv = trie_split2(PIVOT_BUCKET_TRIE(parent_pivot),
   3507                      child_pivot->key,
   3508                      child_pivot->len,
   3509                      pivot, &length,
   3510                      &split_trie_root,
   3511                      max_split_count, 0);
   3512     if (SOC_FAILURE(rv)) {
   3513         /* Non repartable is nothing fatal, just return and keep searching */
   3514         if (rv == SOC_E_NOT_FOUND) {
   3515             rv = SOC_E_NONE;
   3516         }
   3517         /* Must return */
   3518         return rv;
   3519     }
   3520     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3521 
   3522     vrf = PIVOT_BUCKET_VRF(ALPM_TCAM_PIVOT(u, pivot_idx_from));
   3523     doing = _REPART_LPM_INIT;
   3524     rv = _soc_th_alpm_split_lpm_init(u, mem, pivot_idx_from,
   3525                                      vrf, log_bkt_to, NULL, NULL,
   3526                                      pivot, length, &lpm_entry, &bpm_len, bpm,
   3527                                      &src_discard, &src_default);
   3528     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3529 
   3530 
   3531     doing = _REPART_PIVOT_CREATE;
   3532     rv = _soc_th_alpm_split_pivot_create(u, v6, vrf, log_bkt_to,
   3533                                          split_trie_root, pivot, length,
   3534                                          bpm_len, bpm, &new_pivot);
   3535     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3536 
   3537     doing = _REPART_PREPARE;
   3538     rv = _soc_th_alpm_bucket_prepare(u, mem, PIVOT_BUCKET_TRIE(new_pivot),
   3539                                      &pfx_array, &bufp, &sip_bufp, &new_index);
   3540     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3541 
   3542     doing = _REPART_COPY;
   3543     rv = _soc_th_alpm_bucket_copy(u, mem, vrf, pfx_array,
   3544                                   log_bkt_to, bufp, sip_bufp,
   3545                                   NULL, NULL, new_index, NULL);
   3546     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3547 
   3548     doing = _REPART_LPM_INSERT;
   3549     rv = soc_th_alpm_lpm_insert(u, &lpm_entry, &tcam_index, bpm_len,
   3550                                 src_default, src_discard);
   3551     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3552     if (shuffled) {
   3553         *shuffled = 1;
   3554     }
   3555 
   3556     /* TCAM index from lpm code is logical. Convert to physical idx */
   3557     tcam_index = soc_th_alpm_physical_idx(u, L3_DEFIPm, tcam_index, v6);
   3558     pivot_index = tcam_index << (v6 ? 1 : 0);
   3559     PIVOT_TCAM_INDEX(new_pivot)         = pivot_index;
   3560     ALPM_TCAM_PIVOT(u, pivot_index)     = new_pivot;
   3561 
   3562     /* Invalide old entries */
   3563     doing = _REPART_INVALIDATE;
   3564     rv = _soc_th_alpm_bucket_inval(u, mem, pfx_array, bufp, sip_bufp);
   3565     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3566 
   3567     /* Delete old lpm entry */
   3568     {
   3569         uint32          hw_key[5] = {0};
   3570         int             child_vrf;
   3571 
   3572         /* SW bucket merge: not expect to fail */
   3573         doing = _REPART_CHILD_TRIE_MERGED;
   3574         rv = trie_merge(PIVOT_BUCKET_TRIE(new_pivot),
   3575                         PIVOT_BUCKET_TRIE(child_pivot)->trie,
   3576                         child_pivot->key,
   3577                         child_pivot->len);
   3578         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3579 
   3580         sal_memcpy(hw_key, child_pivot->key, sizeof(hw_key));
   3581         ALPM_TRIE_TO_NORMAL_IP(hw_key, child_pivot->len, v6);
   3582 
   3583         child_vrf = PIVOT_BUCKET_VRF(child_pivot);
   3584 
   3585         (void) _soc_th_alpm_lpm_ent_key_init(u, hw_key, child_pivot->len,
   3586                                       child_vrf, v6, &lpm_entry, 1);
   3587 
   3588         doing = _REPART_CHILD_LPM_DELETED;
   3589         rv = soc_th_alpm_lpm_delete(u, &lpm_entry);
   3590         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3591 
   3592         pivot_index = PIVOT_TCAM_INDEX(new_pivot);
   3593 
   3594         /* Destroy child pivot */
   3595         doing = _REPART_CHILD_PIVOT_DESTROYED;
   3596         rv = _soc_th_alpm_split_pivot_create_undo
   3597                     (u, v6, child_vrf, child_pivot->key, child_pivot->len, NULL, 0);
   3598 
   3599         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   3600     }
   3601 
   3602     /* Update hit bits */
   3603     rv = soc_th_alpm_hit_bits_update(u, pfx_array, new_index, v6, vrf);
   3604     if (SOC_FAILURE(rv)) {
   3605         LOG_ERROR(BSL_LS_SOC_ALPM,
   3606                   (BSL_META_U(u, "update_hit_bits failed, count %d\n"),
   3607                               pfx_array->count));
   3608         rv = SOC_E_NONE;
   3609     }
   3610     soc_th_alpm_bucket_usage_decr(u, log_bkt_from, FALSE, vrf, mem, pfx_array->count, log_bkt_to);
   3611     soc_th_alpm_bucket_usage_incr(u, log_bkt_to, pivot_index, vrf, mem, pfx_array->count);
   3612 
   3613     /* Update new index */
   3614     for (i = 0; i < pfx_array->count; i++) {
   3615         pfx_array->prefix[i]->index = new_index[i];
   3616     }
   3617 
   3618     _soc_th_alpm_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index);
   3619     *new_trie = (trie_node_t *) new_pivot;
   3620 
   3621     return rv;
   3622 
   3623 _rollback:
   3624 
   3625     /* fall through on all cases */
   3626     switch (done)  {
   3627     case _REPART_CHILD_LPM_DELETED:
   3628         /* Not expect any failure after trie_merge */
   3629 
   3630     case _REPART_CHILD_TRIE_MERGED: {
   3631             uint32      pivot2[5], length2;
   3632             trie_split2(PIVOT_BUCKET_TRIE(parent_pivot),
   3633                         child_pivot->key,
   3634                         child_pivot->len,
   3635                         pivot2, &length2,
   3636                         &(PIVOT_BUCKET_TRIE(child_pivot)->trie),
   3637                         PIVOT_BUCKET_COUNT(child_pivot), 1);
   3638         }
   3639 
   3640     case _REPART_INVALIDATE:
   3641         _soc_th_alpm_bucket_inval_undo(u, mem, pfx_array, bufp, sip_bufp);
   3642 
   3643     case _REPART_LPM_INSERT:
   3644         soc_th_alpm_lpm_delete(u, &lpm_entry);
   3645 
   3646     case _REPART_COPY:
   3647         /* Delete entries in new bucket */
   3648         _soc_th_alpm_bucket_copy_undo(u, mem, pfx_array->count, new_index);
   3649 
   3650     case _REPART_PREPARE:
   3651         _soc_th_alpm_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index);
   3652 
   3653     case _REPART_PIVOT_CREATE:
   3654         _soc_th_alpm_split_pivot_create_undo(u, v6, vrf, pivot, length, NULL, 0);
   3655 
   3656     case _REPART_LPM_INIT:
   3657         /* nothing to undo */
   3658 
   3659     case _REPART_TRIE_SPLIT:
   3660         trie_merge(PIVOT_BUCKET_TRIE(parent_pivot), split_trie_root, pivot, length);
   3661     default:
   3662         break;
   3663     }
   3664 
   3665     LOG_ERROR(BSL_LS_SOC_ALPM,
   3666               (BSL_META_U(u,
   3667                           "Repartition fails at step %d\n"), doing));
   3668 
   3669     return rv;
   3670 }
   3671 
   3672 
   3673 
   3674 static int
   3675 _soc_th_alpm_max_free_log_bkt(int u, soc_mem_t mem, int bkt_cnt, int vrf,
   3676                               int *log_bkt, int *free_count)
   3677 {
   3678     int                 cnt, sub_bkt;
   3679     int                 phy_bkt, view;
   3680     SHR_BITDCL          *bkt_bmp;
   3681 
   3682     /*
   3683      * Try to alloc a sub bucket from least occupied bucket of
   3684      * same memory view.
   3685      */
   3686     view = SOC_ALPM_MEM_VIEW(mem);
   3687     for (cnt = 1; cnt < bkt_cnt - 1; cnt++) { /* at least two free entry */
   3688         if (SOC_ALPM_GBU_BKT_COUNT(u, view, cnt) <= 0) {
   3689             continue;
   3690         }
   3691 
   3692         bkt_bmp = SOC_ALPM_GBU_BKT_BMP(u, view, cnt);
   3693 
   3694         for (phy_bkt = 1; phy_bkt < ALPM_CTRL(u).num_bkts; phy_bkt++) {
   3695             if (SHR_BITGET(bkt_bmp, phy_bkt) &&
   3696                 SOC_ALPM_BU_GLOBAL(u, phy_bkt) ==
   3697                 (vrf == (SOC_VRF_MAX(u) + 1))) {
   3698                 if (SOC_ALPM_BU_SUB_BKTS(u, phy_bkt) != 0xF) {
   3699                     break;
   3700                 }
   3701             }
   3702         }
   3703 
   3704         if (phy_bkt < ALPM_CTRL(u).num_bkts) {
   3705             for (sub_bkt = 0; sub_bkt < SOC_TH_MAX_SUB_BUCKETS; sub_bkt++) {
   3706                 if (!SOC_ALPM_BU_SUB_BKT_IS_SET(u, phy_bkt, sub_bkt)) {
   3707                     *log_bkt = ALPM_LOG_BKT(phy_bkt, sub_bkt);
   3708                     *free_count = bkt_cnt - cnt;
   3709                     return SOC_E_NONE;
   3710                 }
   3711             }
   3712         }
   3713     }
   3714     return SOC_E_FULL;
   3715 }
   3716 
   3717 
   3718 static int
   3719 _soc_th_alpm_repartition_cb(trie_node_t *ptrie, trie_node_t *trie,
   3720                             trie_traverse_states_e_t *state, void *info,
   3721                             trie_node_t **new_trie)
   3722 {
   3723     int             rv;
   3724     int             parent_phy_bkt, child_phy_bkt;
   3725     int             max_count;
   3726     int             parent_free_count, child_free_count, free_count = 0;
   3727     int             log_bkt_from, log_bkt_to, log_bkt_parent, log_bkt_child;
   3728     int             do_repartition = 0; /* 0: merge. 1: repartition */
   3729     int             child_count = 0, parent_count = 0;
   3730     soc_alpm_merge_info_t *repart = (soc_alpm_merge_info_t *)info;
   3731     alpm_pivot_t *parent_pivot  = (alpm_pivot_t *)ptrie;
   3732     alpm_pivot_t *child_pivot   = (alpm_pivot_t *)trie;
   3733     soc_alpm_merge_type_t merge_dir = MERGE_PHY;
   3734     int             shuffled = 0;
   3735 
   3736 #ifdef ALPM_REPART_DEBUG
   3737 {
   3738     trie_t          *pivot_trie;
   3739     trie_node_t     *lpm = NULL;
   3740     switch (repart->v6) {
   3741         case L3_DEFIP_MODE_V4:
   3742             pivot_trie = VRF_PIVOT_TRIE_IPV4(repart->u, repart->vrf);
   3743             break;
   3744         case L3_DEFIP_MODE_64:
   3745             pivot_trie = VRF_PIVOT_TRIE_IPV6(repart->u, repart->vrf);
   3746             break;
   3747         default:
   3748             pivot_trie = VRF_PIVOT_TRIE_IPV6_128(repart->u, repart->vrf);
   3749             break;
   3750     }
   3751     trie_find_lpm2(pivot_trie, child_pivot->key, child_pivot->len, &lpm);
   3752     ptrie = lpm;
   3753     parent_pivot  = (alpm_pivot_t *)ptrie;
   3754 }
   3755 #endif
   3756     if (!parent_pivot) { /* no parent, this is a root */
   3757         return SOC_E_NONE;
   3758     }
   3759 
   3760     /* Reset state everytime */
   3761     *state = TRIE_TRAVERSE_STATE_NONE;
   3762 
   3763     max_count = repart->max_count;
   3764 
   3765     parent_phy_bkt = ALPM_PHY_BKT(repart->u, PIVOT_BUCKET_INDEX(parent_pivot));
   3766     child_phy_bkt = ALPM_PHY_BKT(repart->u, PIVOT_BUCKET_INDEX(child_pivot));
   3767 
   3768     if (PIVOT_BUCKET_TRIE(parent_pivot)->trie == NULL) {
   3769         merge_dir    = MERGE_LOG_PARENT_TO_CHILD;
   3770     }
   3771 
   3772     if (PIVOT_BUCKET_TRIE(child_pivot)->trie == NULL) {
   3773         merge_dir   = MERGE_LOG_CHILD_TO_PARENT;
   3774     }
   3775 
   3776     if (merge_dir == MERGE_PHY) {
   3777         parent_count = PIVOT_BUCKET_COUNT(parent_pivot);
   3778         child_count = PIVOT_BUCKET_COUNT(child_pivot);
   3779         parent_free_count = max_count - SOC_ALPM_BU_COUNT(repart->u, parent_phy_bkt);
   3780         child_free_count = max_count - SOC_ALPM_BU_COUNT(repart->u, child_phy_bkt);
   3781 
   3782         if (child_count <= parent_free_count) {
   3783             merge_dir = MERGE_LOG_CHILD_TO_PARENT;
   3784         } else if (parent_count <= child_free_count) {
   3785             merge_dir = MERGE_LOG_PARENT_TO_CHILD;
   3786         } else {
   3787             /* Merge is not qualified, try repartition */
   3788             merge_dir = MERGE_LOG_PARENT_TO_CHILD;
   3789             do_repartition = 1;
   3790         }
   3791     }
   3792     log_bkt_parent = PIVOT_BUCKET_INDEX(parent_pivot);
   3793     log_bkt_child  = PIVOT_BUCKET_INDEX(child_pivot);
   3794 
   3795     if (merge_dir == MERGE_LOG_CHILD_TO_PARENT) {
   3796         log_bkt_from = log_bkt_child;
   3797         log_bkt_to   = log_bkt_parent;
   3798     } else {
   3799         /* repartition always go here */
   3800         log_bkt_from = log_bkt_parent;
   3801         log_bkt_to   = log_bkt_child;
   3802     }
   3803 
   3804     if (do_repartition == 0) { /* Bucket merge */
   3805         if (repart->mem == L3_DEFIP_ALPM_IPV6_128m) {
   3806             rv = _soc_th_alpm_128_bucket_merge(repart->u, repart->mem,
   3807                                                log_bkt_from, log_bkt_to, merge_dir,
   3808                                                &shuffled);
   3809         } else {
   3810             rv = _soc_th_alpm_bucket_merge(repart->u, repart->mem,
   3811                                            log_bkt_from, log_bkt_to, merge_dir,
   3812                                            &shuffled);
   3813         }
   3814         if (SOC_FAILURE(rv)) {
   3815             LOG_ERROR(BSL_LS_SOC_ALPM,
   3816                       (BSL_META_U(repart->u,
   3817                                   "Bucket merge fail %d\n"), rv));
   3818             return rv;
   3819         }
   3820 
   3821         if (merge_dir == MERGE_LOG_CHILD_TO_PARENT) {
   3822             free_count = max_count - SOC_ALPM_BU_COUNT(repart->u, child_phy_bkt);
   3823         } else {
   3824             free_count = max_count - SOC_ALPM_BU_COUNT(repart->u, parent_phy_bkt);
   3825         }
   3826 
   3827         *state = TRIE_TRAVERSE_STATE_DELETED;
   3828         repart->free_count = free_count;
   3829         repart->log_bkt    = log_bkt_from;
   3830         if (++repart->merge_count >= REPART_THRESHOLD) {
   3831             *state = TRIE_TRAVERSE_STATE_DONE;
   3832         }
   3833         _alpm_dbg_cntr[repart->u].bkt_merge2++;
   3834     } else { /* Repartition */
   3835         /* Repartition is an intermediate stage, not a goal.
   3836          * Also note, repartition may result in trie modified
   3837          * (old node deleted, new node added).
   3838          */
   3839         if (repart->mem == L3_DEFIP_ALPM_IPV6_128m) {
   3840             rv = _soc_th_alpm_128_bucket_repartition(repart->u, repart->mem,
   3841                                                      log_bkt_from, log_bkt_to, max_count,
   3842                                                      new_trie, &shuffled);
   3843         } else {
   3844             rv = _soc_th_alpm_bucket_repartition(repart->u, repart->mem,
   3845                                                  log_bkt_from, log_bkt_to, max_count,
   3846                                                  new_trie, &shuffled);
   3847         }
   3848         if (SOC_FAILURE(rv)) {
   3849             LOG_ERROR(BSL_LS_SOC_ALPM,
   3850                       (BSL_META_U(repart->u,
   3851                                   "Bucket repartition fail %d\n"), rv));
   3852             return rv;
   3853         }
   3854         /* keep searching if not repartable */
   3855         if (shuffled) {
   3856             _alpm_dbg_cntr[repart->u].bkt_repart++;
   3857         }
   3858     }
   3859 
   3860     if (shuffled) {
   3861         repart->shuffled = 1;
   3862     }
   3863 
   3864     return SOC_E_NONE;
   3865 }
   3866 
   3867 
   3868 static int
   3869 _soc_th_alpm_repartition(int u, soc_mem_t mem, int vrf, int max_count, int *log_bkt,
   3870                          int *shuffled, int *free_count)
   3871 {
   3872     int                             rv = SOC_E_NONE;
   3873     soc_alpm_merge_info_t           info;
   3874     trie_t                          *pivot_trie = NULL;
   3875 
   3876     sal_memset(&info, 0, sizeof(info));
   3877     info.log_bkt     = -1; /* Initialize to non-eligible log_bkt */
   3878     info.u           = u;
   3879     info.mem         = mem;
   3880     info.orig_vrf    = vrf;
   3881     info.v6          = SOC_ALPM_MEM_V6(mem);
   3882     info.vrf         = vrf;
   3883     info.max_count   = max_count;
   3884 
   3885     pivot_trie =
   3886         (info.v6 == L3_DEFIP_MODE_V4 ? VRF_PIVOT_TRIE_IPV4(u, info.vrf) :
   3887          info.v6 == L3_DEFIP_MODE_64 ? VRF_PIVOT_TRIE_IPV6(u, info.vrf) :
   3888                                    VRF_PIVOT_TRIE_IPV6_128(u, info.vrf));
   3889     if (pivot_trie == NULL || pivot_trie->trie == NULL) {
   3890         return SOC_E_FULL;
   3891     }
   3892     /* Choose post-order traverse for repartition.
   3893      * All orders are delete safe.
   3894      * But only the post-order is modify safe.
   3895      */
   3896     rv = trie_repartition(pivot_trie, _soc_th_alpm_repartition_cb,
   3897                           &info, _TRIE_POSTORDER_TRAVERSE);
   3898     if (info.shuffled && shuffled) {
   3899         *shuffled = 1;
   3900     }
   3901     if (SOC_FAILURE(rv)) {
   3902         LOG_ERROR(BSL_LS_SOC_ALPM,
   3903                   (BSL_META_U(u, "Logic bucket repartition fails."\
   3904                                  "rv %d vrf %d v6 %d\n"), rv, info.vrf, info.v6));
   3905         return rv;
   3906     } else if (info.log_bkt != -1) {
   3907         /* This indicates at least one merge happened.
   3908          * Note repartition don't set log_bkt.
   3909          */
   3910         *log_bkt = info.log_bkt;
   3911         return _soc_th_alpm_max_free_log_bkt(u, mem, max_count, vrf,
   3912                                              log_bkt, free_count);
   3913     }
   3914     return SOC_E_FULL;
   3915 }
   3916 
   3917 
   3918 static int
   3919 _soc_th_alpm_merge_cb(trie_node_t *ptrie, trie_node_t *trie,
   3920                       trie_traverse_states_e_t *state, void *info)
   3921 {
   3922     int             rv;
   3923     int             parent_phy_bkt, child_phy_bkt;
   3924     int             max_count;
   3925     int             parent_free_count, child_free_count, free_count = 0;
   3926     int             log_bkt_from, log_bkt_to, log_bkt_parent, log_bkt_child;
   3927     int             child_count = 0, parent_count = 0;
   3928     soc_alpm_merge_info_t *merge = (soc_alpm_merge_info_t *)info;
   3929     alpm_pivot_t *parent_pivot = (alpm_pivot_t *)ptrie;
   3930     alpm_pivot_t *child_pivot = (alpm_pivot_t *)trie;
   3931     soc_alpm_merge_type_t merge_dir = MERGE_PHY;
   3932     int             shuffled = 0;
   3933 
   3934     if (!parent_pivot) {
   3935         return SOC_E_NONE;
   3936     }
   3937 
   3938     /* Reset state everytime */
   3939     *state = TRIE_TRAVERSE_STATE_NONE;
   3940     max_count = merge->max_count;
   3941 
   3942     parent_phy_bkt = ALPM_PHY_BKT(merge->u, PIVOT_BUCKET_INDEX(parent_pivot));
   3943     child_phy_bkt = ALPM_PHY_BKT(merge->u, PIVOT_BUCKET_INDEX(child_pivot));
   3944 
   3945     if (PIVOT_BUCKET_TRIE(parent_pivot)->trie == NULL) {
   3946         merge_dir    = MERGE_LOG_PARENT_TO_CHILD;
   3947     }
   3948 
   3949     if (PIVOT_BUCKET_TRIE(child_pivot)->trie == NULL) {
   3950         merge_dir   = MERGE_LOG_CHILD_TO_PARENT;
   3951     }
   3952 
   3953     if (merge_dir == MERGE_PHY) {
   3954         parent_count = PIVOT_BUCKET_COUNT(parent_pivot);
   3955         child_count = PIVOT_BUCKET_COUNT(child_pivot);
   3956         parent_free_count = max_count - SOC_ALPM_BU_COUNT(merge->u, parent_phy_bkt);
   3957         child_free_count = max_count - SOC_ALPM_BU_COUNT(merge->u, child_phy_bkt);
   3958 
   3959         if (child_count <= parent_free_count) {
   3960             merge_dir   = MERGE_LOG_CHILD_TO_PARENT;
   3961         } else if (parent_count <= child_free_count) {
   3962             merge_dir   = MERGE_LOG_PARENT_TO_CHILD;
   3963         } else {
   3964             return SOC_E_NONE;
   3965         }
   3966     }
   3967 
   3968     log_bkt_parent = PIVOT_BUCKET_INDEX(parent_pivot);
   3969     log_bkt_child  = PIVOT_BUCKET_INDEX(child_pivot);
   3970 
   3971     if (merge_dir == MERGE_LOG_CHILD_TO_PARENT) {
   3972         log_bkt_from = log_bkt_child;
   3973         log_bkt_to   = log_bkt_parent;
   3974     } else {
   3975         log_bkt_from = log_bkt_parent;
   3976         log_bkt_to   = log_bkt_child;
   3977     }
   3978 
   3979     if (merge->mem == L3_DEFIP_ALPM_IPV6_128m) {
   3980         rv = _soc_th_alpm_128_bucket_merge(merge->u, merge->mem,
   3981                                            log_bkt_from, log_bkt_to, merge_dir,
   3982                                            &shuffled);
   3983     } else {
   3984         rv = _soc_th_alpm_bucket_merge(merge->u, merge->mem,
   3985                                        log_bkt_from, log_bkt_to, merge_dir,
   3986                                        &shuffled);
   3987     }
   3988 
   3989     if (SOC_FAILURE(rv)) { /* traverse stops on callback failure */
   3990         LOG_ERROR(BSL_LS_SOC_ALPM,
   3991                   (BSL_META_U(merge->u, "Merge fails %d (not expecting this )\n"), rv));
   3992         return rv;
   3993     }
   3994 
   3995     /* This indicates the trie node is freed */
   3996     *state = TRIE_TRAVERSE_STATE_DELETED;
   3997 
   3998     if (merge_dir == MERGE_LOG_CHILD_TO_PARENT) {
   3999         free_count = max_count - SOC_ALPM_BU_COUNT(merge->u, child_phy_bkt);
   4000     } else {
   4001         free_count = max_count - SOC_ALPM_BU_COUNT(merge->u, parent_phy_bkt);
   4002     }
   4003 
   4004     merge->free_count = free_count;
   4005     merge->log_bkt    = log_bkt_from;
   4006 
   4007     if (++merge->merge_count >= MERGE_THRESHOLD) {
   4008         *state = TRIE_TRAVERSE_STATE_DONE;
   4009     }
   4010 
   4011     if (shuffled) {
   4012         merge->shuffled = 1;
   4013     }
   4014 
   4015     _alpm_dbg_cntr[merge->u].bkt_merge++;
   4016     return SOC_E_NONE;
   4017 }
   4018 
   4019 
   4020 static int
   4021 _soc_th_alpm_merge(int u, soc_mem_t mem, int vrf, int max_count, int *log_bkt,
   4022                    int *shuffled, int *free_count)
   4023 {
   4024     int                             rv = SOC_E_NONE;
   4025     soc_alpm_merge_info_t           info;
   4026     trie_t                          *pivot_trie = NULL;
   4027 
   4028     sal_memset(&info, 0, sizeof(info));
   4029     info.log_bkt     = -1; /* Initialize to non-eligible log_bkt */
   4030     info.u           = u;
   4031     info.mem         = mem;
   4032     info.orig_vrf    = vrf;
   4033     info.v6          = SOC_ALPM_MEM_V6(mem);
   4034     info.vrf         = vrf;
   4035     info.max_count   = max_count;
   4036 
   4037     pivot_trie =
   4038         (info.v6 == L3_DEFIP_MODE_V4 ? VRF_PIVOT_TRIE_IPV4(u, info.vrf) :
   4039          info.v6 == L3_DEFIP_MODE_64 ? VRF_PIVOT_TRIE_IPV6(u, info.vrf) :
   4040                                    VRF_PIVOT_TRIE_IPV6_128(u, info.vrf));
   4041     if (pivot_trie == NULL || pivot_trie->trie == NULL) {
   4042         return SOC_E_FULL;
   4043     }
   4044     rv = trie_traverse2(pivot_trie, _soc_th_alpm_merge_cb,
   4045                         &info, _TRIE_POSTORDER_TRAVERSE);
   4046     if (info.shuffled && shuffled) {
   4047         *shuffled = 1;
   4048     }
   4049     if (SOC_FAILURE(rv)) {
   4050         LOG_ERROR(BSL_LS_SOC_ALPM,
   4051                   (BSL_META_U(u, "Logic bucket merge fails."\
   4052                                  "rv %d vrf %d v6 %d\n"), rv, info.vrf, info.v6));
   4053         return rv;
   4054     } else if (info.log_bkt != -1) {
   4055         /* This indicates at least one merge happened. */
   4056         *log_bkt = info.log_bkt;
   4057         return _soc_th_alpm_max_free_log_bkt(u, mem, max_count, vrf,
   4058                                              log_bkt, free_count);
   4059     }
   4060 
   4061     return SOC_E_FULL;
   4062 }
   4063 
   4064 
   4065 static int
   4066 _soc_th_alpm_assign(int u, soc_mem_t mem, int vrf,
   4067                     int *log_bkt, int *o_shuffled, int *o_free_count)
   4068 {
   4069     int                 rv = SOC_E_FULL;
   4070     int                 free_lpm_count = 0;
   4071     int                 free_count = 0;
   4072     int                 shuffled = 0;
   4073     int                 max_count = _soc_th_alpm_bkt_entry_cnt(u, mem);
   4074 
   4075 
   4076     free_count = max_count;
   4077 
   4078     switch (ALPM_CTRL(u).alpm_scaling) {
   4079     case 1:
   4080         rv = _soc_th_alpm_merge(u, mem, vrf, max_count, log_bkt,
   4081                                 &shuffled, &free_count);
   4082 
   4083         if (rv == SOC_E_FULL) {
   4084             free_lpm_count = _soc_th_alpm_lpm_free_entries(u, mem, vrf);
   4085             if (free_lpm_count >= 1 && free_lpm_count <= 5) {
   4086                 rv = _soc_th_alpm_repartition(u, mem, vrf, max_count,
   4087                                               log_bkt, &shuffled, &free_count);
   4088             }
   4089         }
   4090 
   4091         if (rv == SOC_E_FULL) {
   4092             rv = _soc_th_alpm_share(u, mem, log_bkt);
   4093         }
   4094 
   4095         if (rv == SOC_E_FULL) {
   4096             rv = _soc_th_alpm_max_free_log_bkt(u, mem, max_count, vrf,
   4097                                                log_bkt, &free_count);
   4098         }
   4099         break;
   4100     default:
   4101         rv = _soc_th_alpm_share(u, mem, log_bkt);
   4102 
   4103         if (rv == SOC_E_FULL) {
   4104             rv = _soc_th_alpm_max_free_log_bkt(u, mem, max_count, vrf,
   4105                                                log_bkt, &free_count);
   4106         }
   4107         break;
   4108     }
   4109 
   4110     if (o_free_count) {
   4111         *o_free_count = free_count;
   4112     }
   4113     if (o_shuffled) {
   4114         *o_shuffled = shuffled;
   4115     }
   4116 
   4117     return rv;
   4118 
   4119 }
   4120 
   4121 #ifdef CHECK_CLEAN_BKT
   4122 STATIC int
   4123 _soc_th_alpm_phy_bkt_trie_count(int u, int phy_bkt)
   4124 {
   4125     int pivot_idx, sub_bkt;
   4126     alpm_pivot_t *pivot;
   4127     trie_t       *bkt_trie = NULL;
   4128     alpm_mem_prefix_array_t prefix_array;
   4129     int count = 0;
   4130 
   4131     for (sub_bkt = 0; sub_bkt < SOC_TH_MAX_SUB_BUCKETS; sub_bkt++) {
   4132         if (SOC_ALPM_BU_SUB_BKT_IS_SET(u, phy_bkt, sub_bkt)) {
   4133             pivot_idx = SOC_ALPM_BU_PIVOT_IDX(u, phy_bkt, sub_bkt);
   4134             pivot = ALPM_TCAM_PIVOT(u, (pivot_idx));
   4135             assert(ALPM_LOG_BKT(phy_bkt, sub_bkt) == PIVOT_BUCKET_INDEX(pivot));
   4136             bkt_trie = PIVOT_BUCKET_TRIE(pivot);
   4137 
   4138             sal_memset(&prefix_array, 0, sizeof(prefix_array));
   4139             trie_traverse(bkt_trie, _soc_th_alpm_mem_prefix_array_cb,
   4140                           &prefix_array, _TRIE_INORDER_TRAVERSE);
   4141             count += prefix_array.count;
   4142         }
   4143     }
   4144     return count;
   4145 }
   4146 #endif
   4147 
   4148 /* Update bucket usage bookeeping info */
   4149 void
   4150 soc_th_alpm_bucket_usage_incr(int u, int log_bkt, int pivot_index, int vrf, soc_mem_t mem, int diff)
   4151 {
   4152     int phy_bkt, sub_bkt;
   4153     int count, view;
   4154 
   4155     phy_bkt = ALPM_PHY_BKT(u, log_bkt);
   4156     sub_bkt = ALPM_SUB_BKT(u, log_bkt);
   4157     view = SOC_ALPM_MEM_VIEW(mem);
   4158 
   4159     count = SOC_ALPM_BU_COUNT(u, phy_bkt);
   4160     if (count > 0) {
   4161         SOC_ALPM_GBU_BKT_COUNT(u, view, count)--;
   4162         SHR_BITCLR(SOC_ALPM_GBU_BKT_BMP(u, view, count), phy_bkt);
   4163     } else { /* count == 0 */
   4164         SOC_ALPM_BU_GLOBAL(u, phy_bkt) = (vrf == (SOC_VRF_MAX(u) + 1));
   4165     }
   4166 
   4167     SOC_ALPM_BU_COUNT(u, phy_bkt) += diff;
   4168     SOC_ALPM_BU_SUB_BKT_SET(u, phy_bkt, sub_bkt);
   4169     SOC_ALPM_BU_PIVOT_IDX(u, phy_bkt, sub_bkt) = pivot_index;
   4170 
   4171     count = SOC_ALPM_BU_COUNT(u, phy_bkt);
   4172     if (count > 0) {
   4173         SOC_ALPM_GBU_BKT_COUNT(u, view, count)++;
   4174         SHR_BITSET(SOC_ALPM_GBU_BKT_BMP(u, view, count), phy_bkt);
   4175     }
   4176 
   4177 #ifdef CHECK_CLEAN_BKT
   4178     assert(count == _soc_th_alpm_phy_bkt_trie_count(u, phy_bkt));
   4179 #endif
   4180     return;
   4181 }
   4182 
   4183 /* Update bucket usage bookeeping info */
   4184 void
   4185 soc_th_alpm_bucket_usage_decr(int u, int log_bkt, int clear, int vrf, soc_mem_t mem, int diff, int log_bkt_to)
   4186 {
   4187     int phy_bkt;
   4188     int count, view, v6;
   4189 
   4190     phy_bkt = ALPM_PHY_BKT(u, log_bkt);
   4191     view = SOC_ALPM_MEM_VIEW(mem);
   4192     v6 = SOC_ALPM_MEM_V6(mem);
   4193 
   4194     count = SOC_ALPM_BU_COUNT(u, phy_bkt);
   4195     if (count > 0) {
   4196         SOC_ALPM_GBU_BKT_COUNT(u, view, count)--;
   4197         SHR_BITCLR(SOC_ALPM_GBU_BKT_BMP(u, view, count), phy_bkt);
   4198     }
   4199 
   4200     SOC_ALPM_BU_COUNT(u, phy_bkt) -= diff;
   4201     if (clear) {
   4202         soc_th_alpm_bucket_release(u, log_bkt, vrf, v6);
   4203     }
   4204 
   4205     count = SOC_ALPM_BU_COUNT(u, phy_bkt);
   4206     if (count > 0) {
   4207         SOC_ALPM_GBU_BKT_COUNT(u, view, count)++;
   4208         SHR_BITSET(SOC_ALPM_GBU_BKT_BMP(u, view, count), phy_bkt);
   4209     }
   4210 
   4211 #ifdef CHECK_CLEAN_BKT
   4212     if (phy_bkt != ALPM_PHY_BKT(u, log_bkt_to)) {
   4213         /* Some cases, this has to wait for incr done. */
   4214         assert(count == _soc_th_alpm_phy_bkt_trie_count(u, phy_bkt));
   4215     }
   4216 #endif
   4217     return;
   4218 }
   4219 
   4220 /* Dump bucket sharing bookeeping info */
   4221 void
   4222 soc_th_alpm_bucket_sw_dump(int u)
   4223 {
   4224     int                 i, view, ent, bkt, conflict = 0;
   4225     int                 step_count = 1, used = 0;
   4226     alpm_bkt_bmp_t      *glb_bu = NULL;
   4227     alpm_bkt_usg_t      *bu = NULL;
   4228     int                 *pivot;
   4229     soc_mem_t           lpm_mem;
   4230     uint8               ipv;
   4231 
   4232     /* be consistent with SOC_ALPM_MEM_VIEW */
   4233     char *view_str[] = {"IPv4", "IPv6-64", "IPv6-128", "IPv4 Flex", "IPv6-64 Flex"};
   4234 
   4235     pivot = sal_alloc(sizeof(int) * 16384, "pivot");
   4236     if (pivot == NULL) {
   4237         return;
   4238     }
   4239     sal_memset(pivot, 0, sizeof(int) * 16384);
   4240 
   4241     /* global_bkt_usage info */
   4242     for (view = 0; view < SOC_TH_MAX_ALPM_VIEWS; view++) {
   4243         LOG_CLI((BSL_META_U(u, "\n[- %8s -]\n"), view_str[view]));
   4244         LOG_CLI((BSL_META_U(u,
   4245                 "=================================================\n")));
   4246         LOG_CLI((BSL_META_U(u, " %5s | %5s %10s\n"), "entry", "count", "1st-bktbmp"));
   4247         LOG_CLI((BSL_META_U(u,
   4248                 "=================================================\n")));
   4249         bkt = 0;
   4250         for (ent = 0; ent < SOC_TH_MAX_BUCKET_ENTRIES(u); ent++) {
   4251             glb_bu = &global_bkt_usage[u][view][ent];
   4252             if (glb_bu->bkt_count == 0) {
   4253                 continue;
   4254             }
   4255 
   4256             bkt ++;
   4257             LOG_CLI((BSL_META_U(u, " %5d   %5d"), ent, glb_bu->bkt_count));
   4258             for (i = 0; i < ALPM_CTRL(u).num_bkts; i++) {
   4259                 if (SHR_BITGET(glb_bu->bkt_bmp, i)) {
   4260                     LOG_CLI((BSL_META_U(u, " 0x%08x\n"), glb_bu->bkt_bmp[i / SHR_BITWID]));
   4261                     break;
   4262                 }
   4263             }
   4264         }
   4265 
   4266         if (bkt == 0) {
   4267             LOG_CLI((BSL_META_U(u, "- None - \n")));
   4268         }
   4269     }
   4270 
   4271     /* bkt_usage info */
   4272     ent = 0;
   4273     LOG_CLI((BSL_META_U(u, "%5s | %s\n"), "bkt", "(sub-bkt-idx, tcam-idx)"));
   4274     LOG_CLI((BSL_META_U(u, "=================================================\n")));
   4275     for (bkt = 0; bkt < ALPM_CTRL(u).num_bkts; bkt++) {
   4276         bu = &bkt_usage[u][bkt];
   4277         if (bu->count == 0) {
   4278             continue;
   4279         }
   4280 
   4281         ent ++;
   4282         conflict = 0;
   4283         LOG_CLI((BSL_META_U(u, "%5d | "), bkt));
   4284         for (i = 0; i < 4; i++) {
   4285             if (bu->sub_bkts & (1 << i)) {
   4286                 LOG_CLI((BSL_META_U(u, "(%d, %5d) "), i, bu->pivots[i]));
   4287                 if (pivot[bu->pivots[i]] != 0) {
   4288                     conflict = i + 1;
   4289                 } else {
   4290                     pivot[bu->pivots[i]] = bkt;
   4291                 }
   4292             }
   4293         }
   4294         LOG_CLI((BSL_META_U(u, "\n")));
   4295         if (conflict) {
   4296             LOG_CLI((BSL_META_U(u, "Error: multi-buckets were linked to pivot %d, prev %d, curr %d\n"),
   4297                     bu->pivots[conflict - 1], pivot[bu->pivots[conflict - 1]], bkt));
   4298         }
   4299     }
   4300 
   4301     if (ent == 0) {
   4302         LOG_CLI((BSL_META_U(u, "- None -")));
   4303     }
   4304 
   4305     LOG_CLI((BSL_META_U(u, "\n")));
   4306 
   4307     LOG_CLI((BSL_META_U(u,
   4308             "=================================================\n")));
   4309     LOG_CLI((BSL_META_U(u,
   4310             "  %s[%s]\n"), "VRF Route bucket idx", "mem_view"));
   4311     LOG_CLI((BSL_META_U(u,
   4312             "=================================================\n")));
   4313 
   4314     bkt = 0;
   4315     for (ipv = ALPM_IPV4; ipv < ALPM_IPVERS; ipv++) {
   4316         if (ipv == ALPM_IPV6 &&
   4317             SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4) ==
   4318             SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6)) {
   4319             break;
   4320         }
   4321         for (i = 0; i < SOC_TH_ALPM_BUCKET_COUNT(u); i += step_count) {
   4322             SHR_BITTEST_RANGE(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv), i,
   4323                               step_count, used);
   4324             if (used) {
   4325                 lpm_mem =
   4326                     soc_alpm_cmn_bkt_view_get(u,
   4327                     SOC_TH_ALPM_AIDX(u, i, 0, 0, 0));
   4328                 LOG_CLI((
   4329                     BSL_META_U(u, "  0x%04x[%24s]\n"),
   4330                     i, lpm_mem == -1 ? "INVALID" : SOC_MEM_NAME(u, lpm_mem)));
   4331                 bkt++;
   4332             }
   4333         }
   4334     }
   4335 
   4336     if (bkt == 0) {
   4337         LOG_CLI((BSL_META_U(u, "- None -\n")));
   4338     }
   4339 
   4340     if (ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_PARALLEL &&
   4341         SOC_URPF_STATUS_GET(u)) {
   4342 
   4343         LOG_CLI((BSL_META_U(u,
   4344                 "=================================================\n")));
   4345         LOG_CLI((BSL_META_U(u,
   4346                 "  %s[%s]\n"), "Global Route bucket idx", "mem_view"));
   4347         LOG_CLI((BSL_META_U(u,
   4348                 "=================================================\n")));
   4349 
   4350         bkt = 0;
   4351         for (ipv = ALPM_IPV4; ipv < ALPM_IPVERS; ipv++) {
   4352             if (ipv == ALPM_IPV6 &&
   4353                 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4) ==
   4354                 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6)) {
   4355                 break;
   4356             }
   4357             for (i = 0; i < SOC_TH_ALPM_BUCKET_COUNT(u); i += step_count) {
   4358                 SHR_BITTEST_RANGE(
   4359                     SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv), i, step_count, used);
   4360                 if (used) {
   4361                     lpm_mem = soc_alpm_cmn_bkt_view_get(
   4362                         u, SOC_TH_ALPM_AIDX(u, i, 0, 0, 0));
   4363                     LOG_CLI((
   4364                         BSL_META_U(u, "  0x%04x[%24s]\n"),
   4365                         i, lpm_mem == -1 ? "INVALID" : SOC_MEM_NAME(u, lpm_mem)));
   4366                     bkt++;
   4367                 }
   4368             }
   4369 
   4370         }
   4371 
   4372         if (bkt == 0) {
   4373             LOG_CLI((BSL_META_U(u, "- None -\n")));
   4374         }
   4375     }
   4376 
   4377     sal_free(pivot);
   4378 
   4379     return;
   4380 }
   4381 
   4382 /* Update bucket/hit index of tcam entry if urpf is enabled */
   4383 STATIC void
   4384 _soc_th_alpm_urpf_tcam_info_update(int u, void *entry)
   4385 {
   4386     uint32    value = 0;
   4387 
   4388     value = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, ALG_BKT_PTR0f);
   4389     if (value) {
   4390         value += SOC_TH_ALPM_BUCKET_COUNT(u);
   4391         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, entry, ALG_BKT_PTR0f, value);
   4392     }
   4393     if (ALPM_CTRL(u).bkt_sharing) {
   4394         value = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, ALG_SUB_BKT_PTR0f);
   4395         if (value) {
   4396             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, entry,
   4397                                 ALG_SUB_BKT_PTR0f, value);
   4398         }
   4399     }
   4400 
   4401     /* modify only valid hit index, both _0 and _1 need to be updated */
   4402     value = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, ALG_HIT_IDX0f);
   4403     if (value) {
   4404         value = _soc_th_alpm_rpf_entry(u, value);
   4405         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, entry, ALG_HIT_IDX0f, value);
   4406     }
   4407     value = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, ALG_HIT_IDX1f);
   4408     if (value) {
   4409         value = _soc_th_alpm_rpf_entry(u, value);
   4410         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, entry, ALG_HIT_IDX1f, value);
   4411     }
   4412     if (!soc_mem_field32_get(u, L3_DEFIPm, entry, MODE0_f(u))) {
   4413         value = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, ALG_BKT_PTR1f);
   4414         if (value) {
   4415             value += SOC_TH_ALPM_BUCKET_COUNT(u);
   4416             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, entry,
   4417                                 ALG_BKT_PTR1f, value);
   4418         }
   4419         if (ALPM_CTRL(u).bkt_sharing) {
   4420             value = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm,
   4421                                         entry, ALG_SUB_BKT_PTR1f);
   4422             if (value) {
   4423                 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, entry,
   4424                                     ALG_SUB_BKT_PTR1f, value);
   4425             }
   4426         }
   4427     }
   4428 
   4429     return;
   4430 }
   4431 
   4432 /* create shadow entry copy of primary tcam entry at index */
   4433 static int
   4434 _soc_th_alpm_tcam_shadow_ent_init(int u, int r_index, void *entry, void *shadow,
   4435                                   int w_index, int bpm_len, int v4_half)
   4436 {
   4437     uint32 tmp, ip_mask, v6, db_type, ent_type, urpf = 0;
   4438     soc_mem_t s_mem = L3_DEFIP_AUX_TABLEm;
   4439     defip_entry_t tmp_ipv4;
   4440     int is_ipmc = 0;
   4441     int rv = SOC_E_NONE, pfx, pfx2, vrf_id, vrf_id2, vrf, vrf2;
   4442     int       flex_v6_64 = 0;
   4443 
   4444     SOC_IF_ERROR_RETURN(soc_mem_read(u, s_mem, MEM_BLOCK_ANY, r_index,
   4445                         shadow));
   4446     tmp = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, VRF_ID_0f);
   4447     soc_mem_field32_set(u, s_mem, shadow, VRF0f, tmp);
   4448     tmp = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, VRF_ID_1f);
   4449     soc_mem_field32_set(u, s_mem, shadow, VRF1f, tmp);
   4450 
   4451     tmp = soc_mem_field32_get(u, L3_DEFIPm, entry, MODE0_f(u));
   4452     soc_mem_field32_set(u, s_mem, shadow, MODE0_f(u), tmp);
   4453     tmp = soc_mem_field32_get(u, L3_DEFIPm, entry, MODE1_f(u));
   4454     soc_mem_field32_set(u, s_mem, shadow, MODE1_f(u), tmp);
   4455     v6 = tmp;
   4456 
   4457     if (bpm_len == INVALID_BPM_LEN) {
   4458         /* Clean dirty data */
   4459         if (soc_mem_field32_get(u, s_mem, shadow, VALID0f) == 0) {
   4460             soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH0f, 0);
   4461         }
   4462 
   4463         if (soc_mem_field32_get(u, s_mem, shadow, VALID1f) == 0) {
   4464             soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH1f, 0);
   4465         }
   4466     } else {
   4467         assert(v6 == (v4_half==0));
   4468         if (v6) {
   4469             soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH0f, bpm_len);
   4470             soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH1f, bpm_len);
   4471         } else {
   4472             if (v4_half & 1) {
   4473                 soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH1f, bpm_len);
   4474             } else {
   4475                 soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH0f, bpm_len);
   4476             }
   4477         }
   4478     }
   4479     /* for now simply copy all fields. Let caller decide which half to use */
   4480     tmp = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, VALID0f);
   4481     soc_mem_field32_set(u, s_mem, shadow, VALID0f, tmp);
   4482     tmp = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, VALID1f);
   4483     soc_mem_field32_set(u, s_mem, shadow, VALID1f, tmp);
   4484 
   4485 
   4486     /* IP_LENGTH */
   4487     tmp = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f);
   4488     if ((rv = _ipmask2pfx(tmp, &pfx)) < 0) {
   4489         LOG_ERROR(BSL_LS_SOC_ALPM,
   4490                   (BSL_META_U(u,
   4491                               "_ipmask2pfx fails mask0 0x%x pfx %d\n"),
   4492                               tmp, pfx));
   4493         return rv;
   4494     }
   4495     ip_mask = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK1f);
   4496     if ((rv = _ipmask2pfx(ip_mask, &pfx2)) < 0) {
   4497         LOG_ERROR(BSL_LS_SOC_ALPM,
   4498                   (BSL_META_U(u,
   4499                               "_ipmask2pfx fails mask1 0x%x pfx2 %d\n"),
   4500                               ip_mask, pfx2));
   4501         return rv;
   4502     }
   4503     if (v6) {
   4504         soc_mem_field32_set(u, s_mem, shadow, IP_LENGTH0f, pfx + pfx2);
   4505         soc_mem_field32_set(u, s_mem, shadow, IP_LENGTH1f, pfx + pfx2);
   4506     } else {
   4507         soc_mem_field32_set(u, s_mem, shadow, IP_LENGTH0f, pfx);
   4508         soc_mem_field32_set(u, s_mem, shadow, IP_LENGTH1f, pfx2);
   4509     }
   4510 
   4511     /* IP_ADDR */
   4512     tmp = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR0f);
   4513     soc_mem_field32_set(u, s_mem, shadow, IP_ADDR0f, tmp);
   4514     tmp = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR1f);
   4515     soc_mem_field32_set(u, s_mem, shadow, IP_ADDR1f, tmp);
   4516 
   4517     /* DB_TYPE & ENTRY_TYPE */
   4518     /* for v4 need to be careful */
   4519     if (!v6) {
   4520         sal_memcpy(&tmp_ipv4, entry, sizeof(tmp_ipv4));
   4521         /* vrf for ipv4 entry 0 */
   4522         rv = soc_th_alpm_lpm_vrf_get(u, (void *)&tmp_ipv4, &vrf_id, &vrf);
   4523         SOC_IF_ERROR_RETURN(rv);
   4524 
   4525         /* vrf for ipv4 entry 1 */
   4526         SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_ip4entry1_to_0(u, &tmp_ipv4,
   4527                             &tmp_ipv4, PRESERVE_HIT));
   4528         rv = soc_th_alpm_lpm_vrf_get(u, (void *)&tmp_ipv4, &vrf_id2, &vrf2);
   4529         SOC_IF_ERROR_RETURN(rv);
   4530     } else {
   4531         rv = soc_th_alpm_lpm_vrf_get(u, entry, &vrf_id, &vrf);
   4532     }
   4533     if (SOC_URPF_STATUS_GET(u)) {
   4534         if (w_index >= (soc_mem_index_count(u, L3_DEFIPm) >> 1)) {
   4535             urpf = 1;
   4536         }
   4537     }
   4538 
   4539     soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
   4540 
   4541     if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && v6) {
   4542         uint32 entry_view, flex;
   4543 
   4544         entry_view = soc_mem_field32_get(u, L3_DEFIPm, entry, ENTRY_VIEW0f);
   4545         flex = _soc_th_alpm_lpm_flex_get(u, v6, entry_view);
   4546         if (flex) {
   4547             if (pfx2 == 32 && pfx == 32) {
   4548                 flex_v6_64 = 1;
   4549             }
   4550         }
   4551     }
   4552 
   4553     if (soc_feature(u, soc_feature_ipmc_defip)) {
   4554         is_ipmc = 0;
   4555         if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE0f)) {
   4556             is_ipmc = soc_mem_field32_get(u, L3_DEFIPm, entry, MULTICAST_ROUTE0f);
   4557         } else if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE0f)) {
   4558             if (soc_mem_field32_get(u, L3_DEFIPm, entry, DATA_TYPE0f) == 2) {
   4559                 is_ipmc = 1;
   4560             } else {
   4561                 is_ipmc = 0;
   4562             }
   4563         }
   4564     }
   4565 
   4566     if (ALPM_PREFIX_IN_TCAM(u, vrf_id) || is_ipmc || flex_v6_64) {
   4567         soc_mem_field32_set(u, s_mem, shadow, VALID0f, 0);
   4568         db_type = 0; /* don't care */
   4569     } else {
   4570         if (urpf) {
   4571             db_type += 1;
   4572         }
   4573     }
   4574 
   4575     soc_mem_field32_set(u, s_mem, shadow, DB_TYPE0f, db_type);
   4576     tmp = soc_mem_field32_get(u, L3_DEFIPm, entry, ENTRY_TYPE0_f(u));
   4577     soc_mem_field32_set(u, s_mem, shadow, ENTRY_TYPE0_f(u), tmp | ent_type);
   4578     if (!v6) {
   4579         soc_alpm_db_ent_type_encoding(u, vrf2, &db_type, &ent_type);
   4580         if (soc_feature(u, soc_feature_ipmc_defip)) {
   4581             is_ipmc = 0;
   4582             if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE1f)) {
   4583                 is_ipmc = soc_mem_field32_get(u, L3_DEFIPm, entry, MULTICAST_ROUTE1f);
   4584             } else if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE1f)) {
   4585                 if (soc_mem_field32_get(u, L3_DEFIPm, entry, DATA_TYPE1f) == 2) {
   4586                     is_ipmc = 1;
   4587                 } else {
   4588                     is_ipmc = 0;
   4589                 }
   4590             }
   4591         }
   4592 
   4593         if (ALPM_PREFIX_IN_TCAM(u, vrf_id2) || is_ipmc) {
   4594             soc_mem_field32_set(u, s_mem, shadow, VALID1f, 0);
   4595             db_type = 0; /* don't care */
   4596         } else {
   4597             /* Database to be searched is VRF - DIP */
   4598             if (urpf) {
   4599                 db_type += 1;
   4600             }
   4601         }
   4602 
   4603         soc_mem_field32_set(u, s_mem, shadow, DB_TYPE1f, db_type);
   4604         tmp = soc_mem_field32_get(u, L3_DEFIPm, entry, ENTRY_TYPE1_f(u));
   4605         soc_mem_field32_set(u, s_mem, shadow, ENTRY_TYPE1_f(u), tmp | ent_type);
   4606     } else {
   4607         if (soc_feature(u, soc_feature_ipmc_defip)) {
   4608             if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE1f)) {
   4609                 is_ipmc = soc_mem_field32_get(u, L3_DEFIPm, entry, MULTICAST_ROUTE1f);
   4610             } else if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE1f)) {
   4611                 if (soc_mem_field32_get(u, L3_DEFIPm, entry, DATA_TYPE1f) == 2) {
   4612                     is_ipmc = 1;
   4613                 }
   4614             }
   4615         }
   4616 
   4617         if (ALPM_PREFIX_IN_TCAM(u, vrf_id) || is_ipmc || flex_v6_64) {
   4618             soc_mem_field32_set(u, s_mem, shadow, VALID1f, 0);
   4619         }
   4620         soc_mem_field32_set(u, s_mem, shadow, DB_TYPE1f, db_type);
   4621         tmp = soc_mem_field32_get(u, L3_DEFIPm, entry, ENTRY_TYPE1_f(u));
   4622         soc_mem_field32_set(u, s_mem, shadow, ENTRY_TYPE1_f(u), tmp | ent_type);
   4623     }
   4624 
   4625     /* modify bucket index if urpf is enabled */
   4626     if (urpf) {
   4627         _soc_th_alpm_urpf_tcam_info_update(u, entry);
   4628     }
   4629 
   4630     /* BPM_LENGTH */
   4631     /* don't modify, preserve existing values */
   4632     return SOC_E_NONE;
   4633 }
   4634 
   4635 static INLINE int
   4636 _soc_th_alpm_write_pivot_with_bpm_aux(int u, int copyno, int index, int s_index, void *entry,
   4637                                   int bpm_len, int v4_half)
   4638 {
   4639     defip_aux_table_entry_t shadow;
   4640 
   4641     if (SOC_IS_TRIDENT3(u) && SOC_URPF_STATUS_GET(u) &&
   4642         (index >= (soc_mem_index_count(u, L3_DEFIPm) >> 1))) {
   4643         soc_mem_t mem = L3_DEFIPm;
   4644         soc_mem_field32_set(u, mem, entry, FLEX_CTR_BASE_COUNTER_IDX0f, 0);
   4645         soc_mem_field32_set(u, mem, entry, FLEX_CTR_BASE_COUNTER_IDX1f, 0);
   4646     }
   4647     if (!ALPM_CTRL(u).aux_enable) {
   4648         /* update defip entry */
   4649         if (SOC_URPF_STATUS_GET(u) &&
   4650             (index >= (soc_mem_index_count(u, L3_DEFIPm) >> 1))) {
   4651             _soc_th_alpm_urpf_tcam_info_update(u, entry);
   4652         }
   4653 
   4654         SOC_IF_ERROR_RETURN(WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, index, entry));
   4655     } else {
   4656         /* convert from logical to physical indices */
   4657         s_index = soc_th_alpm_physical_idx(u, L3_DEFIPm, s_index, 1);
   4658         SOC_IF_ERROR_RETURN(_soc_th_alpm_tcam_shadow_ent_init(u, s_index, entry,
   4659                             (void *)&shadow, index, bpm_len, v4_half));
   4660 
   4661         /* write to defip has to be logical */
   4662         SOC_IF_ERROR_RETURN(WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, index, entry));
   4663 
   4664         /* write to shadow table has to be physical */
   4665         index = soc_th_alpm_physical_idx(u, L3_DEFIPm, index, 1);
   4666         SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ANY,
   4667                             index, &shadow));
   4668     }
   4669 
   4670     return SOC_E_NONE;
   4671 
   4672 }
   4673 
   4674 /*
   4675  *      Replicate entry to the second half of the tcam if URPF check is ON.
   4676  */
   4677 static INLINE int
   4678 _lpm_fb_urpf_entry_replicate_with_bpm(int u, int index, uint32 *e, int bpm_len, int v4_half,
   4679                                       int src_default, int src_discard)
   4680 {
   4681     int src_tcam_offset;  /* Defip memory size/2 urpf source lookup offset */
   4682     int ipv6;             /* IPv6 entry.                                   */
   4683     uint32 mask0;         /* Mask 0 field value.                           */
   4684     uint32 mask1;         /* Mask 1 field value.                           */
   4685     int def_gw_flag;      /* Entry is default gateway.                     */
   4686     int src_default_0 = 0, src_default_1 = 0;
   4687     int src_discard_0 = 0, src_discard_1 = 0;
   4688 
   4689     if(!SOC_URPF_STATUS_GET(u)) {
   4690         return (SOC_E_NONE);
   4691     }
   4692 
   4693     if (soc_feature(u, soc_feature_l3_defip_hole)) {
   4694          src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1);
   4695     } else if (SOC_IS_APOLLO(u)) {
   4696          src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1) + 0x0400;
   4697     } else {
   4698          src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1);
   4699     }
   4700 
   4701     ipv6 = soc_mem_field32_get(u, L3_DEFIPm, e, MODE0_f(u));
   4702 
   4703     /* Reset destination discard bit. */
   4704     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD0f)) {
   4705         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD0f, 0);
   4706         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD1f, 0);
   4707     }
   4708 
   4709     /* Set/Reset default gateway flag based on ip mask value. */
   4710     mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, IP_ADDR_MASK0f);
   4711     mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, IP_ADDR_MASK1f);
   4712 
   4713     if (!ipv6) {
   4714         src_default_0 = src_default & (1 << 0) ? 1 : 0;
   4715         src_default_1 = src_default & (1 << 1) ? 1 : 0;
   4716         src_discard_0 = src_discard & (1 << 0) ? 1 : 0;
   4717         src_discard_1 = src_discard & (1 << 1) ? 1 : 0;
   4718         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f)) {
   4719             def_gw_flag = (!mask0) ? 1 : 0;
   4720             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE0f, src_default_0 | def_gw_flag);
   4721             if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD0f)) {
   4722                 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD0f, src_discard_0);
   4723             }
   4724             if (SOC_IS_TRIDENT3X(u)) {
   4725                 soc_mem_field32_set(u, L3_DEFIPm, e, DATA_TYPE0f, 1);
   4726             }
   4727         }
   4728         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f)) {
   4729             def_gw_flag = (!mask1) ? 1 : 0;
   4730             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE1f, src_default_1 | def_gw_flag);
   4731             if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD1f)) {
   4732                 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD1f, src_discard_1);
   4733             }
   4734             if (SOC_IS_TRIDENT3X(u)) {
   4735                 soc_mem_field32_set(u, L3_DEFIPm, e, DATA_TYPE1f, 1);
   4736             }
   4737         }
   4738     } else {
   4739         src_default = src_default ? 1 : 0;
   4740         src_discard = src_discard ? 1 : 0;
   4741         def_gw_flag = ((!mask0) &&  (!mask1)) ? 1 : 0;
   4742         mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f);
   4743         mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f);
   4744         if (mask0 && mask1) {
   4745             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE0f, src_default | def_gw_flag);
   4746             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE1f, src_default | def_gw_flag);
   4747             if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD0f)) {
   4748                 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD0f, src_discard);
   4749                 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD1f, src_discard);
   4750             }
   4751             if (SOC_IS_TRIDENT3X(u)) {
   4752                 soc_mem_field32_set(u, L3_DEFIPm, e, DATA_TYPE0f, 1);
   4753                 soc_mem_field32_set(u, L3_DEFIPm, e, DATA_TYPE1f, 1);
   4754             }
   4755         }
   4756     }
   4757     /* Write entry to the second half of the tcam. */
   4758     return _soc_th_alpm_write_pivot_with_bpm_aux(u, MEM_BLOCK_ANY, index + src_tcam_offset,
   4759                                              index, e, bpm_len, v4_half);
   4760 }
   4761 
   4762 /*
   4763  *      Replicate entry to the second half of the tcam if URPF check is ON.
   4764  */
   4765 static
   4766 int _lpm_fb_urpf_entry_replicate(int u, int index, uint32 *e,
   4767                                  int sdefault, int sdiscard)
   4768 {
   4769     return _lpm_fb_urpf_entry_replicate_with_bpm(u, index, e, INVALID_BPM_LEN, 0,
   4770                                                  sdefault, sdiscard);
   4771 }
   4772 
   4773 static INLINE int
   4774 _soc_th_alpm_write_pivot_with_bpm(int u, int copyno, int index, int s_index, void *entry,
   4775                                   int bpm_len, int v4_half, int src_default,
   4776                                   int src_discard)
   4777 {
   4778     int rv;
   4779     rv = _soc_th_alpm_write_pivot_with_bpm_aux
   4780         (u, copyno, index, s_index, entry, bpm_len, v4_half);
   4781 
   4782     if (rv >= 0) {
   4783         if (bpm_len == INVALID_BPM_LEN) {
   4784             rv = _lpm_fb_urpf_entry_replicate(u, index, entry,
   4785                     src_default, src_discard);
   4786         } else {
   4787             rv = _lpm_fb_urpf_entry_replicate_with_bpm(u, index, entry,
   4788                     bpm_len, v4_half,
   4789                     src_default, src_discard);
   4790         }
   4791     }
   4792     return rv;
   4793 }
   4794 
   4795 
   4796 static int
   4797 _soc_th_alpm_write_pivot(int u, int copyno, int index, int s_index, void *entry,
   4798                         int src_default, int src_discard)
   4799 {
   4800     return _soc_th_alpm_write_pivot_with_bpm
   4801             (u, copyno, index, s_index, entry, INVALID_BPM_LEN, 0, src_default,
   4802             src_discard);
   4803 }
   4804 
   4805 
   4806 
   4807 int
   4808 _soc_th_alpm_insert_in_bkt(int u, soc_mem_t mem, int log_bkt,
   4809                         int bank_disable, void *alpm_data, void *alpm_sip_data,
   4810                         uint32 *e, int *key_index, int v6)
   4811 {
   4812     int rv;
   4813 
   4814     rv = soc_mem_alpm_insert(u, mem, ALPM_PHY_BKT(u, log_bkt),
   4815                              MEM_BLOCK_ANY, bank_disable, alpm_data, e,
   4816                              key_index);
   4817     if (rv == SOC_E_FULL) {
   4818         /* in combined search mode non-urpf try inserting into next bkt for v6*/
   4819         if (ALPM_CTRL(u).double_wide[v6]) {
   4820             rv = soc_mem_alpm_insert(u, mem, ALPM_PHY_BKT(u, log_bkt) + 1,
   4821                              MEM_BLOCK_ANY,
   4822                              bank_disable,
   4823                              alpm_data, e, key_index);
   4824         }
   4825     }
   4826 
   4827     if (SOC_SUCCESS(rv)) {
   4828         if (SOC_URPF_STATUS_GET(u)) {
   4829             soc_mem_field32_set(u, mem, alpm_sip_data, SUB_BKT_PTRf,
   4830                                 ALPM_SUB_BKT(u, log_bkt));
   4831             rv = soc_mem_write(u, mem, MEM_BLOCK_ANY,
   4832                                _soc_th_alpm_rpf_entry(u, *key_index),
   4833                                alpm_sip_data);
   4834         }
   4835     }
   4836     return rv;
   4837 }
   4838 
   4839 
   4840 /* ALPM Table Address Translation
   4841  * Bank     addr[1:0]
   4842  * Bucket   addr[15:2]
   4843  * Entry    addr[16]    L3_DEFIP_ALPM_IPV6_128m
   4844  *          addr[16:17] L3_DEFIP_ALPM_IPV6_64m
   4845  *          addr[16:18] L3_DEFIP_ALPM_IPV4m
   4846  */
   4847 int
   4848 _soc_th_alpm_mem_index(int u, soc_mem_t mem, int bkt, int offset,
   4849                        uint32 bank_disable, int *mem_index)
   4850 {
   4851     int i = 0;
   4852     int bank = 0;
   4853     int ent = 0;
   4854     int bank_enable_count;
   4855 
   4856     int ent_count = 6;
   4857     int ent_pos;
   4858     int bkt_bts = ALPM_CTRL(u).bkt_bits;
   4859 
   4860     switch (mem) {
   4861     case L3_DEFIP_ALPM_IPV4m:
   4862         ent_count = 6;
   4863         break;
   4864     case L3_DEFIP_ALPM_IPV4_1m:
   4865         ent_count = 4;
   4866         break;
   4867     case L3_DEFIP_ALPM_IPV6_64m:
   4868         ent_count = 4;
   4869         break;
   4870     case L3_DEFIP_ALPM_IPV6_64_1m:
   4871         ent_count = 3;
   4872         break;
   4873     case L3_DEFIP_ALPM_IPV6_128m:
   4874         ent_count = 2;
   4875         break;
   4876     default:
   4877         break;
   4878     }
   4879 
   4880     /* Prepare ent */
   4881     ent = offset % ent_count;
   4882 
   4883     /* Prepare bkt position and ent position */
   4884     ent_pos = bkt_bts + ALPM_CTRL(u).bank_bits;
   4885 
   4886     /* Prepare bank enable count */
   4887     bank_enable_count = MAX_BANK_COUNT(u) - _shr_popcount(bank_disable & 0xFF);
   4888 
   4889     /* Prepare bkt and check range */
   4890     i = offset / (bank_enable_count * ent_count);
   4891     if (i == 1) {
   4892         offset -= bank_enable_count * ent_count;
   4893         bkt++;
   4894     } else if (i > 1) {
   4895         return SOC_E_PARAM;
   4896     }
   4897 
   4898     if (bkt >= (1 << bkt_bts)) {
   4899         return SOC_E_PARAM;
   4900     }
   4901 
   4902     /* Prepare bank */
   4903     i = offset / ent_count;
   4904     for (bank = 0; bank < ALPM_CTRL(u).num_banks; bank++) {
   4905         if ((1 << bank) & bank_disable) {
   4906             continue;
   4907         }
   4908 
   4909         if (0 == i--) {
   4910             break;
   4911         }
   4912     }
   4913 
   4914     *mem_index = (ent << ent_pos) | (bkt << ALPM_CTRL(u).bank_bits) | (bank);
   4915 
   4916     return SOC_E_NONE;
   4917 }
   4918 
   4919 
   4920 
   4921 static int
   4922 _soc_th_alpm_bucket_split(int u, alpm_pfx_info_t *pfx_info, int *index_ptr)
   4923 {
   4924     trie_node_t             *split_trie_root;
   4925     uint32                  e[SOC_MAX_MEM_FIELD_WORDS];
   4926     uint32                  length, bpm_len = 0;
   4927     uint32                  bank_disable = 0;
   4928     uint32                  pivot[5] = {0};
   4929     uint32                  bpm[5] = {0};
   4930     uint32                  src_discard, src_default;
   4931     int                     key_index, i;
   4932     trie_t                  *bkt_trie;
   4933     defip_entry_t           lpm_entry;
   4934     alpm_mem_prefix_array_t *pfx_array = NULL;
   4935     int                     *new_index = NULL;
   4936     int                     rv = SOC_E_NONE, new_index_pos = -1;
   4937     int                     tcam_index, pivot_index;
   4938     void                    *bufp = NULL, *sip_bufp = NULL;
   4939     int                     max_split_count;
   4940     alpm_pivot_t            *new_pivot = NULL;
   4941     int                     max_split_length = 0;
   4942     int         v6 = (L3_DEFIP_ALPM_IPV6_64m == pfx_info->mem ||
   4943                       L3_DEFIP_ALPM_IPV6_64_1m == pfx_info->mem ||
   4944                       L3_DEFIP_ALPM_IPV6_128m == pfx_info->mem);
   4945     enum {
   4946         _SPLIT_TRIE_NONE,
   4947         _SPLIT_TRIE_SPLIT,
   4948         _SPLIT_LPM_INIT,
   4949         _SPLIT_PIVOT_CREATE,
   4950         _SPLIT_PREPARE,
   4951         _SPLIT_COPY,
   4952         _SPLIT_LPM_INSERT,
   4953         _SPLIT_INVALIDATE
   4954     } doing = _SPLIT_TRIE_NONE, done = _SPLIT_TRIE_NONE;
   4955 
   4956     bkt_trie = PIVOT_BUCKET_TRIE(ALPM_TCAM_PIVOT(u, pfx_info->pivot_idx_from));
   4957 
   4958     /* If free space is less than a single bucket capacity (start
   4959      * using sub bucket 1..., )
   4960      * We need to limit the split_trie_root payload count
   4961      */
   4962     max_split_count = _soc_th_alpm_bkt_entry_cnt(u, pfx_info->mem) -
   4963                       SOC_ALPM_BU_COUNT(u, ALPM_PHY_BKT(u, pfx_info->log_bkt_to));
   4964 
   4965     max_split_length = (v6 ? 64 : 32) - 1;
   4966 
   4967     doing = _SPLIT_TRIE_SPLIT;
   4968     rv = trie_split(bkt_trie, max_split_length, FALSE,
   4969                     pivot, &length, &split_trie_root, NULL, FALSE, max_split_count);
   4970     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   4971 
   4972     if (length > max_split_length) {
   4973         rv = SOC_E_FULL;
   4974         _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   4975     }
   4976 
   4977     doing = _SPLIT_LPM_INIT;
   4978     rv = _soc_th_alpm_split_lpm_init(u,
   4979                                      pfx_info->mem,
   4980                                      pfx_info->pivot_idx_from,
   4981                                      pfx_info->vrf,
   4982                                      pfx_info->log_bkt_to,
   4983                                      pfx_info->alpm_data,
   4984                                      pfx_info->alpm_sip_data,
   4985                                      pivot, length,
   4986                                      &lpm_entry, &bpm_len, bpm,
   4987                                      &src_discard, &src_default);
   4988 
   4989     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   4990 
   4991     doing = _SPLIT_PIVOT_CREATE;
   4992     rv = _soc_th_alpm_split_pivot_create(u, v6, pfx_info->vrf, pfx_info->log_bkt_to,
   4993                                          split_trie_root, pivot, length,
   4994                                          bpm_len, bpm, &new_pivot);
   4995     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   4996 
   4997     doing = _SPLIT_PREPARE;
   4998     rv = _soc_th_alpm_bucket_prepare(u, pfx_info->mem, PIVOT_BUCKET_TRIE(new_pivot),
   4999                                      &pfx_array, &bufp, &sip_bufp, &new_index);
   5000 
   5001     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5002 
   5003     doing = _SPLIT_COPY;
   5004     rv = _soc_th_alpm_bucket_copy(u, pfx_info->mem, pfx_info->vrf, pfx_array,
   5005                                   pfx_info->log_bkt_to,
   5006                                   bufp, sip_bufp, pfx_info->alpm_data,
   5007                                   pfx_info->alpm_sip_data, new_index, &new_index_pos);
   5008     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5009 
   5010     doing = _SPLIT_LPM_INSERT;
   5011     rv = soc_th_alpm_lpm_insert(u, &lpm_entry, &tcam_index, bpm_len, src_default,
   5012                                 src_discard);
   5013     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5014 
   5015     /* TCAM index from lpm code is logical.  Convert to global idx */
   5016     tcam_index = soc_th_alpm_physical_idx(u, L3_DEFIPm, tcam_index, v6);
   5017     pivot_index = tcam_index << (v6 ? 1 : 0);
   5018     PIVOT_TCAM_INDEX(new_pivot)         = pivot_index;
   5019     ALPM_TCAM_PIVOT(u, pivot_index)     = new_pivot;
   5020 
   5021     doing = _SPLIT_INVALIDATE;
   5022     rv = _soc_th_alpm_bucket_inval(u, pfx_info->mem, pfx_array, bufp, sip_bufp);
   5023     _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing);
   5024 
   5025     /* Don't try rollback from here on, since split is successful. */
   5026     rv = soc_th_alpm_hit_bits_update(u, pfx_array, new_index, v6, pfx_info->vrf);
   5027     if (SOC_FAILURE(rv)) {
   5028         LOG_ERROR(BSL_LS_SOC_ALPM,
   5029                   (BSL_META_U(u, "update_hit_bits failed, count %d\n"),
   5030                               pfx_array->count));
   5031         rv = SOC_E_NONE;
   5032     }
   5033 
   5034     if (new_index_pos != -1) { /* New prefix goes to new split bucket */
   5035         *index_ptr = new_index[new_index_pos];
   5036     } else { /* To old parent bucket, do actual insert */
   5037         /* Add Entry to old bucket RAM */
   5038         soc_mem_field32_set(u, pfx_info->mem, pfx_info->alpm_data, SUB_BKT_PTRf,
   5039                             ALPM_SUB_BKT(u, pfx_info->log_bkt_from));
   5040         /* entry shouldn't exist, insert the entry into the RAM */
   5041         bank_disable =
   5042             ALPM_CTRL(u).bank_disable_bmp[pfx_info->vrf != (SOC_VRF_MAX(u) + 1)];
   5043         rv = _soc_th_alpm_insert_in_bkt(u, pfx_info->mem, pfx_info->log_bkt_from,
   5044                                         bank_disable, pfx_info->alpm_data,
   5045                                         pfx_info->alpm_sip_data, e, &key_index, v6);
   5046 
   5047         assert(rv == 0);
   5048         if (SOC_FAILURE(rv)) {
   5049             /* recover by matching trie state to h/w state */
   5050             LOG_ERROR(BSL_LS_SOC_ALPM,
   5051                       (BSL_META_U(u, "Could not insert new "
   5052                                   "prefix into trie after split\n")));
   5053             /* since split was successful, leave split state as-is */
   5054             pfx_info->log_bkt_to = -1;
   5055             return rv;
   5056         }
   5057 
   5058         *index_ptr = key_index;
   5059     }
   5060 
   5061     /* Update old bucket usage */
   5062     soc_th_alpm_bucket_usage_decr(u, pfx_info->log_bkt_from,
   5063                                   FALSE, pfx_info->vrf,
   5064                                   pfx_info->mem, pfx_array->count - 1,
   5065                                   pfx_info->log_bkt_to);
   5066     /* Update new bucket usage */
   5067     soc_th_alpm_bucket_usage_incr(u, pfx_info->log_bkt_to,
   5068                                   pivot_index, pfx_info->vrf,
   5069                                   pfx_info->mem, pfx_array->count);
   5070 
   5071     PIVOT_BUCKET_ENT_CNT_UPDATE(new_pivot);
   5072     VRF_BUCKET_SPLIT_INC(u, pfx_info->vrf, v6);
   5073 
   5074     /* Update new index */
   5075     for (i = 0; i < pfx_array->count; i++) {
   5076         pfx_array->prefix[i]->index = new_index[i];
   5077     }
   5078 
   5079     _soc_th_alpm_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index);
   5080     return rv;
   5081 
   5082 _rollback:
   5083     /* fall through on all cases */
   5084     switch (done)  {
   5085     case _SPLIT_LPM_INSERT:
   5086         soc_th_alpm_lpm_delete(u, &lpm_entry);
   5087 
   5088     case _SPLIT_COPY:
   5089         /* Delete entries in new bucket */
   5090         _soc_th_alpm_bucket_copy_undo(u, pfx_info->mem, pfx_array->count, new_index);
   5091 
   5092     case _SPLIT_PREPARE:
   5093         _soc_th_alpm_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index);
   5094 
   5095     case _SPLIT_PIVOT_CREATE:
   5096         _soc_th_alpm_split_pivot_create_undo(u, v6, pfx_info->vrf, pivot, length, NULL, 0);
   5097 
   5098     case _SPLIT_LPM_INIT:
   5099         /* nothing to undo */
   5100     case _SPLIT_TRIE_SPLIT:
   5101         trie_merge(bkt_trie, split_trie_root, pivot, length);
   5102 
   5103     case _SPLIT_TRIE_NONE:
   5104     default:
   5105         /* nothing to rollback for first step */
   5106         break;
   5107     }
   5108 
   5109     switch (doing) {
   5110     case _SPLIT_TRIE_SPLIT:
   5111         LOG_ERROR(BSL_LS_SOC_ALPM,
   5112                   (BSL_META_U(u,
   5113                               "Could not split bucket")));
   5114         break;
   5115 
   5116     case _SPLIT_PIVOT_CREATE:
   5117         LOG_ERROR(BSL_LS_SOC_ALPM,
   5118                   (BSL_META_U(u, "failed to insert into pivot bkt_trie\n")));
   5119         break;
   5120 
   5121     case _SPLIT_LPM_INSERT:
   5122         LOG_ERROR(BSL_LS_SOC_ALPM,
   5123                   (BSL_META_U(u,
   5124                               "Unable to add new pivot to tcam\n")));
   5125 
   5126         if (rv == SOC_E_FULL) {
   5127             VRF_PIVOT_FULL_INC(u, pfx_info->vrf, v6);
   5128         }
   5129         break;
   5130     default:
   5131         LOG_ERROR(BSL_LS_SOC_ALPM,
   5132                   (BSL_META_U(u,
   5133                               "Split fails at step %d\n"), doing));
   5134         break;
   5135     }
   5136 
   5137     return rv;
   5138 }
   5139 
   5140 /*
   5141  * Insert entry into ALPM database.
   5142  * Returns SOC_E_NONE, if found and updated.
   5143  * SOC_E_FAIL, if insert failed.
   5144  */
   5145 static int
   5146 _soc_th_alpm_insert(int u,
   5147                     int v6,
   5148                     void *key_data,  /* TCAM entry data */
   5149                     soc_mem_t mem,   /* Mem view for ALPM data */
   5150                     void *alpm_data, /* Alpm data to be updated with */
   5151                     void *alpm_sip_data,
   5152                     int *index_ptr,
   5153                     int log_bkt,
   5154                     int tcam_index)  /* return key location */
   5155 {
   5156     alpm_pivot_t *old_pivot;
   5157     defip_aux_scratch_entry_t aux_entry;
   5158     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   5159     uint32      prefix[5], length;
   5160     int         vrf, vrf_id;
   5161     int         key_index;
   5162     int         rv = SOC_E_NONE;
   5163     uint32      db_type, ent_type, bank_disable;
   5164     int         hit = 0;
   5165     int         free_count, old_count = 0;
   5166     int         split = 0;
   5167     trie_t      *bkt_trie = NULL, *pfx_trie = NULL;
   5168     trie_node_t *lpmp = NULL, *lpmp2 = NULL;
   5169     payload_t   *bkt_payload = NULL, *pfx_payload = NULL, *tmp_pyld;
   5170     int         default_route = 0;
   5171     /* Search Result buffers */
   5172     alpm_pfx_info_t pfx_info;
   5173     int         new_log_bkt = -1;
   5174     int         bkt_trie_inserted = 0, pfx_trie_inserted = 0;
   5175     int         shuffled = 0, aux_flags = 0;
   5176 
   5177     SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   5178     bank_disable =
   5179             ALPM_CTRL(u).bank_disable_bmp[vrf != (SOC_VRF_MAX(u) + 1)];
   5180     soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
   5181 
   5182     /* Get table memory. */
   5183     SOC_ALPM_TABLE_MEM(u, v6, mem, VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 1));
   5184 
   5185     /* Insert the prefix into the bucket trie, whether the insert was
   5186      * successul or resulted in Split. Spliting the trie after insertion
   5187      * yeilds better pivot and better split.
   5188      */
   5189     /* Create Prefix */
   5190     rv = _soc_th_alpm_prefix_create(u, v6, key_data, prefix, &length,
   5191                                     &default_route);
   5192     if (SOC_FAILURE(rv)) {
   5193         LOG_ERROR(BSL_LS_SOC_ALPM,
   5194                   (BSL_META_U(u,
   5195                               "_soc_th_alpm_insert: prefix create failed\n")));
   5196         return rv;
   5197     }
   5198 
   5199     /* Fill in AUX Scratch and perform PREFIX Operation */
   5200     sal_memset(&aux_entry, 0, sizeof(defip_aux_scratch_entry_t));
   5201     SOC_IF_ERROR_RETURN(
   5202        _soc_th_alpm_fill_aux_entry_for_op(u, key_data, v6, db_type, ent_type, 0,
   5203                                           &aux_entry));
   5204 
   5205     /* we need to do sw pivot find again, or we may miss sub_bkt info */
   5206     if (log_bkt == 0) {
   5207         if (ALPM_CTRL(u).sw_prefix_lkup) {
   5208             rv = _soc_th_alpm_sw_pivot_find(u, prefix, length, v6, vrf, &hit,
   5209                                             &tcam_index, &log_bkt);
   5210         } else {
   5211             rv = _soc_th_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry, TRUE, &hit,
   5212                                      &tcam_index, &log_bkt, 0);
   5213         }
   5214         SOC_IF_ERROR_RETURN(rv);
   5215         soc_mem_field32_set(u, mem, alpm_data, SUB_BKT_PTRf,
   5216                             ALPM_SUB_BKT(u, log_bkt));
   5217     }
   5218 
   5219     /* entry shouldn't exist, insert the entry into the RAM */
   5220     rv = _soc_th_alpm_insert_in_bkt(u, mem, log_bkt,
   5221                                     bank_disable, alpm_data, alpm_sip_data,
   5222                                     e, &key_index, v6);
   5223 
   5224     old_pivot = ALPM_TCAM_PIVOT(u, tcam_index);
   5225 
   5226     if (rv == SOC_E_NONE) {
   5227         *index_ptr = key_index;
   5228     } else if (rv == SOC_E_FULL) {
   5229 
   5230         rv = soc_th_alpm_assign(u, vrf, mem, &new_log_bkt,
   5231                                 &shuffled, &free_count);
   5232         SOC_IF_ERROR_RETURN(rv);
   5233 
   5234         if (shuffled) {
   5235             if (ALPM_CTRL(u).sw_prefix_lkup) {
   5236                 rv = _soc_th_alpm_sw_pivot_find(u, prefix, length, v6, vrf, &hit,
   5237                                                 &tcam_index, &log_bkt);
   5238             } else {
   5239                 rv = _soc_th_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry, TRUE, &hit,
   5240                                          &tcam_index, &log_bkt, 0);
   5241             }
   5242             SOC_IF_ERROR_RETURN(rv);
   5243             soc_mem_field32_set(u, mem, alpm_data, SUB_BKT_PTRf,
   5244                                 ALPM_SUB_BKT(u, log_bkt));
   5245 
   5246             old_pivot = ALPM_TCAM_PIVOT(u, tcam_index);
   5247         }
   5248 
   5249         if (PIVOT_BUCKET_TRIE(old_pivot)->trie == NULL ||
   5250             (((old_count = (PIVOT_BUCKET_COUNT(old_pivot)) + 1)) <= free_count &&
   5251              _soc_th_alpm_lpm_free_entries(u, mem, vrf) == 0)) { /* find a new home*/
   5252             LOG_DEBUG(BSL_LS_SOC_ALPM,
   5253                         (BSL_META_U(u,
   5254                                     "Find new home free_count %d old_count + 1 %d\n"
   5255                                     ), free_count, old_count + 1));
   5256             rv = _soc_th_alpm_bucket_merge(u, mem, log_bkt, new_log_bkt, MERGE_PHY, NULL);
   5257             if (SOC_FAILURE(rv)) {
   5258                 soc_th_alpm_bucket_release(u, new_log_bkt, vrf, v6);
   5259                 return rv;
   5260             }
   5261             log_bkt = new_log_bkt;
   5262             soc_mem_field32_set(u, mem, alpm_data, SUB_BKT_PTRf,
   5263                                 ALPM_SUB_BKT(u, log_bkt));
   5264             /* entry shouldn't exist, insert the entry into the RAM */
   5265             rv = _soc_th_alpm_insert_in_bkt(u, mem, log_bkt,
   5266                                             bank_disable, alpm_data, alpm_sip_data,
   5267                                             e, &key_index, v6);
   5268             if (SOC_SUCCESS(rv)) {
   5269                 *index_ptr = key_index;
   5270             } else {
   5271                 return rv;
   5272             }
   5273         } else {
   5274             split = 1;
   5275             /* this indicates a new route, which will be used to decide
   5276              * if the new route happens to be new pivot.
   5277              */
   5278             key_index = -1;
   5279         }
   5280     } else {
   5281         return rv;
   5282     }
   5283 
   5284     /* Allocate Payload */
   5285     bkt_payload = sal_alloc(sizeof(payload_t), "Payload for Key");
   5286     if (bkt_payload == NULL) {
   5287         LOG_ERROR(BSL_LS_SOC_ALPM,
   5288                   (BSL_META_U(u,
   5289                               "Unable to allocate memory for "
   5290                               "bkt_payload entry\n")));
   5291         rv = SOC_E_MEMORY;
   5292         goto _rollback;
   5293     }
   5294 
   5295     pfx_payload = sal_alloc(sizeof(payload_t), "Payload for pfx trie key");
   5296     if (pfx_payload == NULL) {
   5297         LOG_ERROR(BSL_LS_SOC_ALPM,
   5298                   (BSL_META_U(u,
   5299                               "Unable to allocate memory for "
   5300                               "pfx trie node\n")));
   5301         rv = SOC_E_MEMORY;
   5302         goto _rollback;
   5303     }
   5304     sal_memset(bkt_payload, 0, sizeof(*bkt_payload));
   5305     sal_memset(pfx_payload, 0, sizeof(*pfx_payload));
   5306     sal_memcpy(bkt_payload->key, prefix, sizeof(prefix));
   5307     bkt_payload->len    = length;
   5308     /* Needs update for split case, updated below */
   5309     bkt_payload->index  = key_index;
   5310     /* create duplicate for prefix bkt_trie */
   5311     sal_memcpy(pfx_payload, bkt_payload, sizeof(*bkt_payload));
   5312     pfx_payload->bkt_ptr = bkt_payload;
   5313 
   5314     /* Insert the prefix */
   5315     /* bucket trie insert */
   5316     bkt_trie = PIVOT_BUCKET_TRIE(old_pivot);
   5317     rv = trie_insert(bkt_trie, prefix, NULL, length, (trie_node_t *)bkt_payload);
   5318     if (SOC_SUCCESS(rv)) {
   5319         bkt_trie_inserted = 1;
   5320     } else {
   5321         goto _rollback;
   5322     }
   5323 
   5324     /* prefix trie insert */
   5325     if (v6) {
   5326         pfx_trie = VRF_PREFIX_TRIE_IPV6(u, vrf);
   5327     } else {
   5328         pfx_trie = VRF_PREFIX_TRIE_IPV4(u, vrf);
   5329     }
   5330     if (!default_route) {
   5331         /* default route already in trie */
   5332         uint32 bpm[5];
   5333         _soc_th_alpm_mask_prefix_create(u, v6, length, bpm);
   5334         rv = trie_insert(pfx_trie, prefix,
   5335                          ALPM_CTRL(u).trie_propagate ? bpm : NULL,
   5336                          length, (trie_node_t *)pfx_payload);
   5337         if (SOC_SUCCESS(rv)) {
   5338             pfx_trie_inserted = 1;
   5339         }
   5340     } else {
   5341         /* update the default route */
   5342         lpmp = NULL;
   5343         rv = trie_find_lpm(pfx_trie, 0, 0, &lpmp);
   5344         tmp_pyld = (payload_t *)lpmp;
   5345         if (SOC_SUCCESS(rv)) {
   5346             tmp_pyld->bkt_ptr = bkt_payload;
   5347         }
   5348     }
   5349     if (SOC_FAILURE(rv)) {
   5350         goto _rollback;
   5351     }
   5352 
   5353     /* Performs lazy splitting */
   5354     if (split) {
   5355         pfx_info.pivot_idx_from   = tcam_index;
   5356         pfx_info.alpm_data        = alpm_data;
   5357         pfx_info.alpm_sip_data    = alpm_sip_data;
   5358         pfx_info.log_bkt_from     = log_bkt;
   5359         pfx_info.log_bkt_to       = new_log_bkt;
   5360         pfx_info.vrf              = vrf;
   5361         pfx_info.mem              = mem;
   5362         rv = _soc_th_alpm_bucket_split(u, &pfx_info, index_ptr);
   5363         if (rv != SOC_E_NONE) {
   5364             new_log_bkt = pfx_info.log_bkt_to;
   5365             goto _rollback;
   5366         }
   5367         bkt_payload->index  = *index_ptr;
   5368         /* New Pivot */
   5369         _alpm_dbg_cntr[u].bkt_split++;
   5370     } else {
   5371         soc_th_alpm_bucket_usage_incr(u, log_bkt, tcam_index, vrf, mem, 1);
   5372     }
   5373 
   5374     /* from here on, we don't expect any failure */
   5375 
   5376     /* propagate the insertion */
   5377     if (default_route) {
   5378         /* also free unused pfx_payload pointer */
   5379         sal_free(pfx_payload);
   5380     }
   5381     /* do insert propagation to update existing default datas */
   5382     soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, &aux_entry, ALG_HIT_IDXf,
   5383                         *index_ptr);
   5384 
   5385      if (SOC_URPF_STATUS_GET(u)) {
   5386         if (soc_mem_field32_get(u, mem, alpm_sip_data, DEFAULTROUTEf)) {
   5387             aux_flags |= SOC_ALPM_AUX_DEF_ROUTE;
   5388         }
   5389         if (soc_mem_field32_get(u, mem, alpm_sip_data, SRC_DISCARDf)) {
   5390             aux_flags |= SOC_ALPM_AUX_SRC_DISCARD;
   5391         }
   5392     }
   5393 
   5394     SOC_IF_ERROR_RETURN(_soc_th_alpm_aux_op(u, INSERT_PROPAGATE, &aux_entry,
   5395                         TRUE, &hit, &tcam_index, &log_bkt, aux_flags));
   5396 
   5397     /* For debug, update the old pivot's counter */
   5398     PIVOT_BUCKET_ENT_CNT_UPDATE(old_pivot);
   5399     return rv;
   5400 
   5401 _rollback:
   5402     if (!default_route && pfx_trie_inserted) {
   5403         (void)trie_delete(pfx_trie, prefix, length, &lpmp);
   5404     }
   5405 
   5406     if (bkt_trie_inserted) {
   5407         (void)trie_delete(bkt_trie, prefix, length, &lpmp2);
   5408     }
   5409 
   5410     if (pfx_payload) {
   5411         sal_free(pfx_payload);
   5412     }
   5413 
   5414     if (bkt_payload) {
   5415         sal_free(bkt_payload);
   5416     }
   5417 
   5418     if (split && new_log_bkt != -1) {
   5419         /* for non-split case, the new logical bucket is taking effect and thus
   5420          * should not be released
   5421          */
   5422          (void)soc_th_alpm_bucket_release(u, new_log_bkt, vrf, v6);
   5423     }
   5424     return rv;
   5425 }
   5426 
   5427 /* Build an LPM entry, from a key */
   5428 /* Mostly used for the match */
   5429 static int
   5430 _soc_th_alpm_lpm_ent_key_init(int u, uint32 *addr, int len, int vrf, int ipv6,
   5431                               defip_entry_t *lpm_entry, int init)
   5432 {
   5433     uint32 mask;
   5434     soc_mem_t mem = L3_DEFIPm;
   5435 
   5436     /* Zero buffers. */
   5437     if (init) {
   5438         sal_memset(lpm_entry, 0, sizeof(defip_entry_t));
   5439     }
   5440 
   5441     /* and with mask to ensure global vrf gets set to 0 */
   5442     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_0f,
   5443                               vrf & SOC_VRF_MAX(u));
   5444     if (vrf == (SOC_VRF_MAX(u) + 1)) {
   5445         /* for global routes */
   5446         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f, 0);
   5447     } else {
   5448         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f,
   5449                             SOC_VRF_MAX(u));
   5450     }
   5451 
   5452     if (SOC_MEM_FIELD_VALID(u, mem, DWf)) {
   5453         soc_mem_field32_set(u, mem, lpm_entry, DWf, 0);
   5454     }
   5455 
   5456     if (ipv6) {
   5457 
   5458         /* Set address to the buffer. */
   5459         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR0f, addr[0]);
   5460 
   5461         /* Set address to the buffer. */
   5462         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR1f, addr[1]);
   5463 
   5464         /* Set mode to ipv6 */
   5465         soc_mem_field32_set(u, mem, lpm_entry, MODE0_f(u), 1);
   5466         soc_mem_field32_set(u, mem, lpm_entry, MODE1_f(u), 1);
   5467 
   5468         /* Set Virtual Router id */
   5469         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_1f, vrf &
   5470                                   SOC_VRF_MAX(u));
   5471         if (vrf == (SOC_VRF_MAX(u) + 1)) {
   5472             /* for global routes */
   5473             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_MASK1f, 0);
   5474         } else {
   5475             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_MASK1f,
   5476                                   SOC_VRF_MAX(u));
   5477         }
   5478         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VALID1f, 1);
   5479 
   5480         if (len >= 32) {
   5481             mask = 0xffffffff;
   5482             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, mask);
   5483             mask = ~SHR_SHIFT_RIGHT(0xffffffff, len - 32);
   5484             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, mask);
   5485         } else {
   5486             mask = ~(0xffffffff >> len);
   5487             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, mask);
   5488             /* make sure lower word of mask is 0 */
   5489             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, 0);
   5490         }
   5491     } else {
   5492         /* Set address to the buffer. */
   5493         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR0f, addr[0]);
   5494 
   5495         assert(len <= 32);
   5496         mask = (len == 32) ? 0xffffffff : ~(0xffffffff >> len);
   5497         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, mask);
   5498     }
   5499     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VALID0f, 1);
   5500 
   5501     /* Set Mode Masks */
   5502     soc_mem_field32_set(u, mem, lpm_entry, MODE_MASK0_f(u),
   5503                         (1 << soc_mem_field_length(u, mem, MODE_MASK0_f(u))) - 1);
   5504     soc_mem_field32_set(u, mem, lpm_entry, MODE_MASK1_f(u),
   5505                         (1 << soc_mem_field_length(u, mem, MODE_MASK1_f(u))) - 1);
   5506 
   5507     /* Set Entry Type Masks */
   5508     soc_mem_field32_set(u, mem, lpm_entry, ENTRY_TYPE_MASK0_f(u),
   5509                         (1 << soc_mem_field_length(u, mem,
   5510                          ENTRY_TYPE_MASK0_f(u))) - 1);
   5511     soc_mem_field32_set(u, mem, lpm_entry, ENTRY_TYPE_MASK1_f(u),
   5512                         (1 << soc_mem_field_length(u, mem,
   5513                          ENTRY_TYPE_MASK1_f(u))) - 1);
   5514     /*
   5515      * Note ipv4 entries are expected to reside in part 0 of the entry.
   5516      *      ipv6 entries both parts should be filled.
   5517      *      Hence if entry is ipv6 copy part 0 to part 1
   5518      */
   5519     return (SOC_E_NONE);
   5520 }
   5521 
   5522 int
   5523 _soc_th_alpm_delete_in_bkt(int u, soc_mem_t mem, int phy_bkt,
   5524                         int bank_disable, void *bufp2, uint32 *e,
   5525                         int *key_index, int v6)
   5526 {
   5527     int rv;
   5528 
   5529     rv = soc_mem_alpm_delete(u, mem, phy_bkt, MEM_BLOCK_ALL,
   5530                              bank_disable, bufp2, e, key_index);
   5531     if (SOC_SUCCESS(rv)) {
   5532         return rv;
   5533     }
   5534     if (ALPM_CTRL(u).double_wide[v6]) {
   5535         return soc_mem_alpm_delete(u, mem, phy_bkt + 1,
   5536                                    MEM_BLOCK_ALL, bank_disable, bufp2, e,
   5537                                    key_index);
   5538     }
   5539     return rv;
   5540 }
   5541 
   5542 
   5543 #ifdef CHECK_CLEAN_BKT
   5544 static int
   5545 _soc_th_alpm_bkt_count(int u, soc_mem_t mem, int is_log_bkt, int bkt, int vrf, void *bufp)
   5546 {
   5547     int bank_num;
   5548     int entry_num;
   5549     int bank_count;
   5550     int bank_bits;
   5551     int alpm_bkt_bits = ALPM_CTRL(u).bkt_bits;
   5552     int bkt_count;
   5553     int phy_bkt;
   5554     int sub_bkt;
   5555     int addr;
   5556     int rv;
   5557     int entry_count;
   5558     uint32 bank_disable;
   5559     int count = 0;
   5560 
   5561     if (is_log_bkt) {
   5562         phy_bkt = ALPM_PHY_BKT(u, bkt);
   5563         sub_bkt = ALPM_SUB_BKT(u, bkt);
   5564     } else {
   5565         phy_bkt = bkt;
   5566         sub_bkt = -1;
   5567     }
   5568 
   5569     bank_disable = ALPM_CTRL(u).bank_disable_bmp_8b[vrf != (SOC_VRF_MAX(u) + 1)];
   5570     bank_count  = ALPM_CTRL(u).num_banks;
   5571     bank_bits   = ALPM_CTRL(u).bank_bits;
   5572 
   5573     ALPM_FIRST_AVAIL_BANK(bank_num, bank_count, bank_disable);
   5574 
   5575     switch (mem) {
   5576     case L3_DEFIP_ALPM_IPV4m:
   5577         entry_count = 6;
   5578         break;
   5579     case L3_DEFIP_ALPM_IPV4_1m:
   5580         entry_count = 4;
   5581         break;
   5582     case L3_DEFIP_ALPM_IPV6_64m:
   5583         entry_count = 4;
   5584         break;
   5585     case L3_DEFIP_ALPM_IPV6_64_1m:
   5586         entry_count = 3;
   5587         break;
   5588     case L3_DEFIP_ALPM_IPV6_128m:
   5589     default:
   5590         entry_count = 2;
   5591         break;
   5592     }
   5593     bkt_count   = _soc_th_alpm_bkt_entry_cnt(u, mem);
   5594     entry_num   = 0;
   5595     while (bkt_count--) {
   5596         addr = (entry_num << (bank_bits + alpm_bkt_bits)) |
   5597                (phy_bkt << bank_bits) |
   5598                (bank_num & ((1U << bank_bits) - 1));
   5599         entry_num++;
   5600         if (entry_num == entry_count) {
   5601             entry_num = 0;
   5602             ALPM_NEXT_AVAIL_BANK(bank_num, bank_count, bank_disable);
   5603             if (bank_num == bank_count) {
   5604                 ALPM_FIRST_AVAIL_BANK(bank_num, bank_count, bank_disable);
   5605                 phy_bkt ++;
   5606             }
   5607         }
   5608 
   5609         rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, addr, bufp);
   5610         SOC_IF_ERROR_RETURN(rv); /* If fail, the rv < 0, and check also fails */
   5611 
   5612         if (sub_bkt != -1 && sub_bkt !=
   5613             soc_mem_field32_get(u, mem, bufp, SUB_BKT_PTRf)) {
   5614             continue;
   5615         }
   5616 
   5617         if (soc_mem_field32_get(u, mem, bufp, VALIDf)) {
   5618             LOG_CLI(("mem %s bkt %d vrf %d bank_disable %d bkt_count %d "
   5619                      "entry_num %d, bank_num %d, addr %d\n",
   5620                      SOC_MEM_NAME(u, mem), bkt, vrf, bank_disable, bkt_count,
   5621                      entry_num, bank_num, addr));
   5622             count++;
   5623         }
   5624     }
   5625 
   5626     return count;
   5627 }
   5628 #endif /* CHECK_CLEAN_BKT */
   5629 
   5630 /*
   5631  * Delete entry from ALPM database.
   5632  * Returns SOC_E_NONE, if found and updated.
   5633  * SOC_E_FAIL, if insert failed.
   5634  * If default route replace with internal default
   5635  */
   5636 static int
   5637 _soc_th_alpm_delete(int u, int v6, void *key_data, int log_bkt,
   5638                     int tcam_index, int key_index)  /* TCAM entry data */
   5639 {
   5640     alpm_pivot_t *pivot_pyld;
   5641     /* Search Result buffer */
   5642     defip_alpm_ipv4_1_entry_t *alpmv4_entry = NULL, *alpmv4_sip_entry = NULL, *alpmv42 = NULL;
   5643     defip_alpm_ipv6_64_1_entry_t *alpmv6_entry = NULL, *alpmv6_sip_entry = NULL, *alpmv62 = NULL;
   5644     defip_aux_scratch_entry_t *aux_entry = NULL;
   5645     uint32      *e = NULL;
   5646     soc_mem_t mem;
   5647     void      *bufp, *bufp2, *sip_bufp = NULL;
   5648     int       vrf_id;
   5649     int       rv = SOC_E_NONE, rv2;
   5650     uint32    prop_pfx[5], prefix[5], bpm[5];
   5651     int       vrf;
   5652     uint32    length;
   5653     int       delete_bucket, delete_phy_bkt;
   5654     uint32    db_type, ent_type, bank_disable;
   5655     int       hit, default_route = 0;
   5656     trie_t    *trie, *pfx_trie;
   5657     uint32    bpm_pfx_len;
   5658     defip_entry_t lpm_entry, *lpm_key;
   5659     payload_t *payload = NULL, *pfx_pyld = NULL, *tmp_pyld = NULL;
   5660     trie_node_t *delp = NULL, *lpmp = NULL;
   5661     trie_t    *pivot_trie = NULL;
   5662     int       empty_bucket, aux_flags = 0;
   5663 
   5664     alpmv4_entry = sal_alloc(sizeof(defip_alpm_ipv4_1_entry_t), "alpmv4_entry");
   5665     if (alpmv4_entry == NULL) {
   5666         rv = SOC_E_MEMORY;
   5667         goto clean_up;
   5668     }
   5669 
   5670     alpmv4_sip_entry = sal_alloc(sizeof(defip_alpm_ipv4_1_entry_t), "alpmv4_sip_entry");
   5671     if (alpmv4_sip_entry == NULL) {
   5672         rv = SOC_E_MEMORY;
   5673         goto clean_up;
   5674     }
   5675 
   5676     alpmv42 = sal_alloc(sizeof(defip_alpm_ipv4_1_entry_t), "alpmv42");
   5677     if (alpmv42 == NULL) {
   5678         rv = SOC_E_MEMORY;
   5679         goto clean_up;
   5680     }
   5681 
   5682     alpmv6_entry = sal_alloc(sizeof(defip_alpm_ipv6_64_1_entry_t), "alpmv6_entry");
   5683     if (alpmv6_entry == NULL) {
   5684         rv = SOC_E_MEMORY;
   5685         goto clean_up;
   5686     }
   5687 
   5688     alpmv6_sip_entry = sal_alloc(sizeof(defip_alpm_ipv6_64_1_entry_t), "alpmv6_sip_entry");
   5689     if (alpmv6_sip_entry == NULL) {
   5690         rv = SOC_E_MEMORY;
   5691         goto clean_up;
   5692     }
   5693 
   5694     alpmv62 = sal_alloc(sizeof(defip_alpm_ipv6_64_1_entry_t), "alpmv62");
   5695     if (alpmv62 == NULL) {
   5696         rv = SOC_E_MEMORY;
   5697         goto clean_up;
   5698     }
   5699 
   5700     aux_entry = sal_alloc(sizeof(defip_aux_scratch_entry_t), "aux_entry");
   5701     if (aux_entry == NULL) {
   5702         rv = SOC_E_MEMORY;
   5703         goto clean_up;
   5704     }
   5705 
   5706     e = sal_alloc(sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS, "buf_tmp");
   5707     if (e == NULL) {
   5708         rv = SOC_E_MEMORY;
   5709         goto clean_up;
   5710     }
   5711 
   5712     SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   5713 
   5714     /* For VRF_OVERRIDE (Global High) entries, software needs to maintain the
   5715      * index, Prefix resides in TCAM directly. Handling of these functions are
   5716      * taken care by main insert */
   5717     if (!(ALPM_PREFIX_IN_TCAM(u, vrf_id))) {
   5718         bank_disable = ALPM_CTRL(u).bank_disable_bmp[vrf != SOC_VRF_MAX(u) + 1];
   5719         soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
   5720         /* Create Prefix */
   5721         rv = _soc_th_alpm_prefix_create(u, v6, key_data, prefix, &length,
   5722                                         &default_route);
   5723         if (SOC_FAILURE(rv)) {
   5724             LOG_ERROR(BSL_LS_SOC_ALPM,
   5725                       (BSL_META_U(u,
   5726                                   "_soc_alpm_delete: prefix create failed\n")));
   5727             goto clean_up;
   5728         }
   5729         if (ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_COMBINED) {
   5730             if (vrf_id != SOC_L3_VRF_GLOBAL) {
   5731                 /* allow default deletion only at end */
   5732                 if (VRF_TRIE_ROUTES_CNT(u, vrf_id, vrf, v6) > 1) {
   5733                     if (default_route) {
   5734                         LOG_ERROR(BSL_LS_SOC_ALPM,
   5735                                   (BSL_META_U(u,
   5736                                               "VRF %d: Cannot delete default "
   5737                                               "route if other routes are present in "
   5738                                               "this mode\n"), vrf));
   5739                         rv = SOC_E_PARAM;
   5740                         goto clean_up;
   5741                     }
   5742                 }
   5743             }
   5744         }
   5745 
   5746         /* Get table memory. */
   5747         SOC_ALPM_TABLE_MEM(u, v6, mem, VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 0));
   5748 
   5749         /* Assign entry buf based on table being used */
   5750         SOC_ALPM_ENTRY_BUF(v6, mem, bufp, *alpmv4_entry, *alpmv6_entry);
   5751         SOC_ALPM_ENTRY_BUF(v6, mem, bufp2, *alpmv42, *alpmv62);
   5752 
   5753         SOC_ALPM_LPM_LOCK(u);
   5754 
   5755         if (log_bkt == 0) {
   5756             /* Search the entry */
   5757             rv = _soc_th_alpm_find(u, mem, v6, key_data, vrf_id, vrf, bufp,
   5758                                    &tcam_index, &log_bkt, &key_index, TRUE);
   5759         } else {
   5760             /* key_data has all the info including search result */
   5761             rv = _soc_th_alpm_mem_ent_init(u, v6, key_data, bufp, 0, mem,
   5762                                            0, 0, log_bkt);
   5763         }
   5764 
   5765         /* save results as they are lost later */
   5766         sal_memcpy(bufp2, bufp, v6 ? sizeof(defip_alpm_ipv6_64_1_entry_t) :
   5767                    sizeof(defip_alpm_ipv4_1_entry_t));
   5768 
   5769         if (SOC_FAILURE(rv)) {
   5770             SOC_ALPM_LPM_UNLOCK(u);
   5771             LOG_ERROR(BSL_LS_SOC_ALPM,
   5772                       (BSL_META_U(u,
   5773                                   "_soc_alpm_delete: Unable to find prefix for delete\n")));
   5774             goto clean_up;
   5775         }
   5776 
   5777         /* Entry found
   5778          * 1> Delete entry from trie
   5779          * 2> Find Best Prefix Match
   5780          * 3> Update bpm using replacement prefix op
   5781          * 4> Invalidate Entry in the ALPM database
   5782          */
   5783         /* Delete the prefix from trie*/
   5784         /* Store index to invalidate the prefix */
   5785         delete_bucket = log_bkt;
   5786 
   5787         pivot_pyld = ALPM_TCAM_PIVOT(u, tcam_index);
   5788         trie = PIVOT_BUCKET_TRIE(pivot_pyld);
   5789 
   5790         rv = trie_delete(trie, prefix, length,  &delp);
   5791         payload = (payload_t *) delp;
   5792         if (rv != SOC_E_NONE) {
   5793             LOG_ERROR(BSL_LS_SOC_ALPM,
   5794                       (BSL_META_U(u,
   5795                                   "_soc_alpm_delete: Error prefix not present in trie \n")));
   5796             SOC_ALPM_LPM_UNLOCK(u);
   5797             goto clean_up;
   5798         }
   5799 
   5800         /* prefix trie delete */
   5801         if (v6) {
   5802             pfx_trie = VRF_PREFIX_TRIE_IPV6(u, vrf);
   5803         } else {
   5804             pfx_trie = VRF_PREFIX_TRIE_IPV4(u, vrf);
   5805         }
   5806 
   5807         if (v6) {
   5808             pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf);
   5809         } else {
   5810             pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf);
   5811         }
   5812 
   5813         if (!default_route) {
   5814             rv = trie_delete(pfx_trie, prefix, length, &delp);
   5815             pfx_pyld = (payload_t *) delp;
   5816             if (SOC_FAILURE(rv)) {
   5817                 /* continue anyway to minimize state mismatch */
   5818                 LOG_ERROR(BSL_LS_SOC_ALPM,
   5819                           (BSL_META_U(u,
   5820                                       "_soc_alpm_delete: Prefix not present in pfx"
   5821                                       "trie: 0x%08x 0x%08x\n"),
   5822                            prefix[0], prefix[1]));
   5823                 goto recover_bkt_trie;
   5824             }
   5825 
   5826             /* Find Best prefix match for the prefix */
   5827             lpmp = NULL;
   5828             rv = trie_find_lpm(pfx_trie, prefix, length, &lpmp);
   5829             tmp_pyld = (payload_t *) lpmp;
   5830             if (SOC_SUCCESS(rv)) {
   5831                 payload_t *t = (payload_t *)(tmp_pyld->bkt_ptr);
   5832                 if (t != NULL) {
   5833                     /* this means a real default route exists */
   5834                     bpm_pfx_len = t->len;
   5835                 } else {
   5836                     /* only internal default route exists */
   5837                     /* this should happen only if the lpm is a default route */
   5838                     bpm_pfx_len = 0;
   5839                 }
   5840             } else {
   5841                 LOG_ERROR(BSL_LS_SOC_ALPM,
   5842                           (BSL_META_U(u,
   5843                                       "_soc_alpm_delete: Could not find replacement"
   5844                                       "bpm for prefix: 0x%08x 0x%08x\n"),
   5845                            prefix[0], prefix[1]));
   5846                 goto recover_pfx_trie;
   5847             }
   5848 
   5849             /* Initialize an lpm enty to perform a match */
   5850             /* not expected to fail */
   5851             sal_memcpy(prop_pfx, prefix, sizeof(prefix));
   5852             ALPM_TRIE_TO_NORMAL_IP(prop_pfx, length, v6);
   5853             rv = _soc_th_alpm_lpm_ent_key_init(u, prop_pfx, bpm_pfx_len, vrf, v6,
   5854                                                &lpm_entry, 1);
   5855 
   5856             /* Find Associated data for the bpm */
   5857             rv2 = _soc_th_alpm_find(u, mem, v6, &lpm_entry, vrf_id, vrf, bufp,
   5858                                     &tcam_index, &log_bkt, &key_index, TRUE);
   5859             if (rv2) {
   5860                 if (vrf_id != SOC_L3_VRF_GLOBAL &&
   5861                     ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_COMBINED) {
   5862                     soc_mem_entry_dump_if_changed(u, L3_DEFIPm, &lpm_entry, "ALPM-DBG: ");
   5863                     LOG_ERROR(BSL_LS_SOC_ALPM,
   5864                             (BSL_META_U(u,
   5865                             "Find associated data for next bpm failed."
   5866                             "prefix: 0x%08x 0x%08x, length %d\n"),
   5867                             prop_pfx[0], prop_pfx[1], bpm_pfx_len));
   5868                 } else {
   5869                     key_index = 0;
   5870                 }
   5871             }
   5872 
   5873             /* convert associated data to lpm entry format */
   5874             (void) _soc_th_alpm_lpm_ent_init(u, bufp, mem, v6, vrf_id,
   5875                                              log_bkt, 0, &lpm_entry, 0);
   5876 
   5877             /* set key to the prefix being deleted */
   5878             (void) _soc_th_alpm_lpm_ent_key_init(u, prop_pfx, length, vrf, v6,
   5879                                                  &lpm_entry, 0);
   5880             if (SOC_URPF_STATUS_GET(u)) {
   5881                 SOC_ALPM_ENTRY_BUF(v6, mem, sip_bufp, *alpmv4_sip_entry,
   5882                         *alpmv6_sip_entry);
   5883                 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY,
   5884                         _soc_th_alpm_rpf_entry(u, key_index), sip_bufp);
   5885 
   5886                 if (soc_mem_field32_get(u, mem, sip_bufp, DEFAULTROUTEf)) {
   5887                     aux_flags |= SOC_ALPM_AUX_DEF_ROUTE;
   5888                 }
   5889                 if (soc_mem_field32_get(u, mem, sip_bufp, SRC_DISCARDf)) {
   5890                     aux_flags |= SOC_ALPM_AUX_SRC_DISCARD;
   5891                 }
   5892             }
   5893 
   5894             if ((bpm_pfx_len == 0)  && SOC_FAILURE(rv2)) {
   5895                 /* could not find a default route. Use internal default */
   5896                 /* default route's associated data */
   5897                 lpm_key = v6 ? VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) :
   5898                                VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf);
   5899                 sal_memcpy(&lpm_entry, lpm_key, sizeof(lpm_entry));
   5900                 /* copy key info over again */
   5901                 rv = _soc_th_alpm_lpm_ent_key_init(u, prop_pfx, length, vrf, v6,
   5902                                                    &lpm_entry, 0);
   5903             }
   5904 
   5905             if (SOC_FAILURE(rv)) {
   5906                 LOG_ERROR(BSL_LS_SOC_ALPM,
   5907                           (BSL_META_U(u,
   5908                                       "_soc_alpm_delete: Could not find replacement"
   5909                                       " prefix for prefix: 0x%08x 0x%08x\n"),
   5910                            prefix[0], prefix[1]));
   5911                 goto recover_pfx_trie;
   5912             }
   5913 
   5914             lpm_key = &lpm_entry;
   5915         } else { /* !default_route */
   5916             /* remove the real default route reference if any */
   5917 
   5918             lpmp = NULL;
   5919             rv = trie_find_lpm(pfx_trie, prefix, length, &lpmp);
   5920             tmp_pyld = (payload_t *) lpmp;
   5921             if (SOC_FAILURE(rv)) {
   5922                 LOG_ERROR(BSL_LS_SOC_ALPM,
   5923                           (BSL_META_U(u,
   5924                                       "_soc_alpm_delete: Could not find default "
   5925                                       "route in the trie for vrf %d\n"), vrf));
   5926                 goto recover_bkt_trie;
   5927             }
   5928             tmp_pyld->bkt_ptr = NULL;
   5929             bpm_pfx_len = 0;
   5930             lpm_key = v6 ? VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) :
   5931                       VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf);
   5932             key_index = 0;
   5933         }
   5934         rv = _soc_th_alpm_fill_aux_entry_for_op(u, lpm_key, v6, db_type,
   5935                                     ent_type, bpm_pfx_len, aux_entry);
   5936         if (SOC_FAILURE(rv)) {
   5937             goto recover_pfx_trie;
   5938         }
   5939 
   5940         /* Perform Delete propagate */
   5941         soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, ALG_HIT_IDXf,
   5942                             ALPM_ENT_INDEX(key_index));
   5943         rv = _soc_th_alpm_aux_op(u, DELETE_PROPAGATE, aux_entry, TRUE, &hit,
   5944                                  &tcam_index, &log_bkt, aux_flags);
   5945         if (SOC_FAILURE(rv)) {
   5946             goto recover_pfx_trie;
   5947         }
   5948 
   5949         /* perform SIP delete propagate */
   5950         if (0) {
   5951             uint32 tmp;
   5952             /* only SRC bits are different from DIP entry. Copy them over if
   5953                internal default is not being used */
   5954             soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry,
   5955                                 DB_TYPEf, db_type + 1);
   5956             soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry,
   5957                                 ALG_HIT_IDXf, _soc_th_alpm_rpf_entry(u,
   5958                                 ALPM_ENT_INDEX(key_index)));
   5959             tmp = soc_mem_field32_get(u, L3_DEFIP_AUX_SCRATCHm, aux_entry,
   5960                                       IP_LENGTHf);
   5961             soc_mem_field32_set(u, mem, aux_entry, DEFAULTROUTEf,
   5962                                 tmp == 0 ? 1 : 0);
   5963 
   5964             rv = _soc_th_alpm_aux_op(u, DELETE_PROPAGATE, aux_entry, TRUE,
   5965                                      &hit, &tcam_index, &log_bkt, 0);
   5966             if (SOC_FAILURE(rv)) {
   5967                 goto recover_pfx_trie;
   5968             }
   5969         }
   5970 
   5971         /* From here on don't trie to recover trie state */
   5972         sal_free(payload);
   5973         if (!default_route) {
   5974             sal_free(pfx_pyld);
   5975         }
   5976 
   5977         /* For debug, update the pivot's counter */
   5978         PIVOT_BUCKET_ENT_CNT_UPDATE(pivot_pyld);
   5979 
   5980         empty_bucket = (pivot_pyld->len != 0) && (trie->trie == NULL);
   5981         if (empty_bucket) { /* Empty bucket */
   5982             uint32 hw_key[5];
   5983             sal_memcpy(hw_key, pivot_pyld->key, sizeof(hw_key));
   5984             ALPM_TRIE_TO_NORMAL_IP(hw_key, pivot_pyld->len, v6);
   5985 
   5986             /* Initialize an lpm entry to perform a match */
   5987             _soc_th_alpm_lpm_ent_key_init(u, hw_key, pivot_pyld->len,
   5988                                      vrf, v6, &lpm_entry, 1);
   5989 
   5990             /* delete entry from TCAM */
   5991             rv = soc_th_alpm_lpm_delete(u, &lpm_entry);
   5992             if (SOC_FAILURE(rv)) {
   5993                 LOG_ERROR(BSL_LS_SOC_ALPM,
   5994                           (BSL_META_U(u,
   5995                                       "_soc_alpm_delete: Unable to "
   5996                                       "delete pivot 0x%08x 0x%08x \n"),
   5997                            pivot_pyld->key[0], pivot_pyld->key[1]));
   5998                 /* continue to clean up still */
   5999             }
   6000         }
   6001 
   6002         /* Invalidate the route */
   6003         delete_phy_bkt = ALPM_PHY_BKT(u, delete_bucket);
   6004         rv = _soc_th_alpm_delete_in_bkt(u, mem, delete_phy_bkt, bank_disable,
   6005                                         bufp2, e, &key_index, v6);
   6006         if (SOC_FAILURE(rv)) {
   6007             LOG_ERROR(BSL_LS_SOC_ALPM,
   6008                       (BSL_META_U(u,
   6009                                   "_soc_th_alpm_delete_in_bkt: Unable to "
   6010                                   "delete phy bkt 0x%08x \n"), delete_phy_bkt));
   6011             SOC_ALPM_LPM_UNLOCK(u);
   6012             goto clean_up;
   6013         }
   6014 
   6015         /* delete corresponding RPF entry if it exists */
   6016         if (SOC_URPF_STATUS_GET(u)) {
   6017             /* hit is an unused variable */
   6018             delete_phy_bkt = SOC_TH_ALPM_RPF_BKT_IDX(u, delete_phy_bkt);
   6019             rv = _soc_th_alpm_delete_in_bkt(u, mem, delete_phy_bkt, bank_disable,
   6020                                             bufp2, e, &hit, v6);
   6021             if (SOC_FAILURE(rv)) {
   6022                 LOG_ERROR(BSL_LS_SOC_ALPM,
   6023                           (BSL_META_U(u,
   6024                                       "_soc_th_alpm_delete_in_bkt: Unable to "
   6025                                       "delete phy bkt 0x%08x \n"), delete_phy_bkt));
   6026                 SOC_ALPM_LPM_UNLOCK(u);
   6027                 goto clean_up;
   6028             }
   6029         }
   6030 
   6031         /* Update usage stat */
   6032         soc_th_alpm_bucket_usage_decr(u, PIVOT_BUCKET_INDEX(pivot_pyld), empty_bucket, vrf, mem, 1, 0);
   6033         if (empty_bucket) { /* Empty bucket */
   6034 
   6035             /* remove pivot from pivot trie */
   6036             rv = trie_delete(pivot_trie, pivot_pyld->key, pivot_pyld->len, &delp);
   6037             if (SOC_FAILURE(rv)) {
   6038                 LOG_ERROR(BSL_LS_SOC_ALPM,
   6039                           (BSL_META_U(u,
   6040                                       "could not delete pivot from pivot trie\n")));
   6041             }
   6042 
   6043             /* Free up Bucket trie */
   6044             trie_destroy(PIVOT_BUCKET_TRIE(pivot_pyld));
   6045 
   6046             /* Free up Bucket handle */
   6047             sal_free(PIVOT_BUCKET_HANDLE(pivot_pyld));
   6048 
   6049             /* free Pivot structure */
   6050             sal_free(pivot_pyld);
   6051 
   6052 #ifdef CHECK_CLEAN_BKT
   6053             /* make sure bucket is indeed empty */
   6054             assert(_soc_th_alpm_bkt_count(u, mem, 1, delete_bucket, vrf,
   6055                                             bufp) == 0);
   6056 #endif /* CHECK_CLEAN_BKT */
   6057         }
   6058     }
   6059 
   6060     VRF_TRIE_ROUTES_DEC(u, vrf_id, vrf, v6);
   6061     if (VRF_TRIE_ROUTES_CNT(u, vrf_id, vrf, v6) == 0) {
   6062         /* vrf is empty. Release resources */
   6063         rv = soc_th_alpm_vrf_delete(u, vrf, v6);
   6064     }
   6065     SOC_ALPM_LPM_UNLOCK(u);
   6066     goto clean_up;
   6067 
   6068     /* Recovery from error: */
   6069     /* add back pivot bucket trie entry */
   6070     /* add back prefix trie entry */
   6071 recover_pfx_trie:
   6072         LOG_ERROR(BSL_LS_SOC_ALPM,
   6073                   (BSL_META_U(u,
   6074                    "recovering soc_th_alpm_vrf_delete failed\n ")));
   6075 
   6076     _soc_th_alpm_mask_prefix_create(u, v6, length, bpm);
   6077     rv2 = trie_insert(pfx_trie, prefix,
   6078                       ALPM_CTRL(u).trie_propagate ? bpm : NULL,
   6079                       length, (trie_node_t *)pfx_pyld);
   6080     if (SOC_FAILURE(rv2)) {
   6081         LOG_ERROR(BSL_LS_SOC_ALPM,
   6082                   (BSL_META_U(u,
   6083                               "_soc_alpm_delete: Unable to reinsert"
   6084                               "prefix 0x%08x 0x%08x into pfx trie\n"),
   6085                    prefix[0], prefix[1]));
   6086     }
   6087 recover_bkt_trie:
   6088     rv2 = trie_insert(trie, prefix, NULL, length,  (trie_node_t *) payload);
   6089     if (SOC_FAILURE(rv2)) {
   6090         LOG_ERROR(BSL_LS_SOC_ALPM,
   6091                   (BSL_META_U(u,
   6092                               "_soc_alpm_delete: Unable to reinsert"
   6093                               "prefix 0x%08x 0x%08x into bkt trie\n"),
   6094                    prefix[0], prefix[1]));
   6095     }
   6096     SOC_ALPM_LPM_UNLOCK(u);
   6097 clean_up:
   6098     if (alpmv4_entry) {
   6099         sal_free(alpmv4_entry);
   6100     }
   6101     if (alpmv4_sip_entry) {
   6102         sal_free(alpmv4_sip_entry);
   6103     }
   6104     if (alpmv42) {
   6105         sal_free(alpmv42);
   6106     }
   6107     if (alpmv6_entry) {
   6108         sal_free(alpmv6_entry);
   6109     }
   6110     if (alpmv6_sip_entry) {
   6111         sal_free(alpmv6_sip_entry);
   6112     }
   6113     if (alpmv62) {
   6114         sal_free(alpmv62);
   6115     }
   6116     if (aux_entry) {
   6117         sal_free(aux_entry);
   6118     }
   6119     if (e) {
   6120         sal_free(e);
   6121     }
   6122     return rv;
   6123 }
   6124 
   6125 void
   6126 soc_th_alpm_mem_free(int u)
   6127 {
   6128     int i, j;
   6129     if (alpm_vrf_handle[u] != NULL) {
   6130         sal_free(alpm_vrf_handle[u]);
   6131         alpm_vrf_handle[u] = NULL;
   6132     }
   6133     if (tcam_pivot[u] != NULL) {
   6134         sal_free(tcam_pivot[u]);
   6135         tcam_pivot[u] = NULL;
   6136     }
   6137     if (bkt_usage[u] != NULL) {
   6138         sal_free(bkt_usage[u]);
   6139         bkt_usage[u] = NULL;
   6140     }
   6141     for (i = 0; i < SOC_TH_MAX_ALPM_VIEWS; i++) {
   6142         if (global_bkt_usage[u][i] != NULL) {
   6143             for (j = 0; j < SOC_TH_MAX_BUCKET_ENTRIES(u); j++) {
   6144                 if (global_bkt_usage[u][i][j].bkt_bmp != NULL) {
   6145                     sal_free(global_bkt_usage[u][i][j].bkt_bmp);
   6146                     global_bkt_usage[u][i][j].bkt_bmp = NULL;
   6147                 }
   6148             }
   6149             sal_free(global_bkt_usage[u][i]);
   6150             global_bkt_usage[u][i] = NULL;
   6151         }
   6152     }
   6153 }
   6154 
   6155 /* Initialize ALPM Subsytem */
   6156 int
   6157 soc_th_alpm_init(int u)
   6158 {
   6159     int i, j;
   6160     int rv = SOC_E_NONE;
   6161     uint32 sz, sz2;
   6162 
   6163     if (SOC_ALPM_LPM_INIT_CHECK(u)) {
   6164         /* this is a reinit. clean up old state */
   6165         if (soc_th_alpm_deinit(u) < 0) {
   6166             return SOC_E_INTERNAL;
   6167         }
   6168     }
   6169 
   6170     rv = _soc_th_alpm_ctrl_init(u);
   6171     SOC_IF_ERROR_RETURN(rv);
   6172 
   6173     /* Initialize TCAM Memory management */
   6174     rv = soc_th_alpm_lpm_init(u);
   6175     SOC_IF_ERROR_RETURN(rv);
   6176 
   6177     /* Initialize ALPM memory management */
   6178     rv = soc_th_alpm_shared_mem_init(u);
   6179 
   6180     soc_th_alpm_mem_free(u);
   6181     alpm_vrf_handle[u] = sal_alloc((MAX_VRF_ID + 1) * sizeof(alpm_vrf_handle_t), "ALPM VRF Handles");
   6182     if (alpm_vrf_handle[u] == NULL) {
   6183         rv = SOC_E_MEMORY;
   6184         goto _free_exit;
   6185     }
   6186 
   6187     tcam_pivot[u] = sal_alloc(TH_MAX_PIVOT_COUNT(u) * sizeof(alpm_pivot_t *), "ALPM pivots");
   6188     if (tcam_pivot[u] == NULL) {
   6189         rv = SOC_E_MEMORY;
   6190         goto _free_exit;
   6191     }
   6192     sal_memset(alpm_vrf_handle[u], 0, (MAX_VRF_ID + 1) * sizeof(alpm_vrf_handle_t));
   6193     sal_memset(tcam_pivot[u], 0, TH_MAX_PIVOT_COUNT(u) * sizeof(alpm_pivot_t *));
   6194 
   6195     /* Bucket sharing structure */
   6196     sz = ALPM_CTRL(u).num_bkts * sizeof(alpm_bkt_usg_t);
   6197     bkt_usage[u] = sal_alloc(sz, "ALPM_BS");
   6198     if (bkt_usage[u] == NULL) {
   6199         rv = SOC_E_MEMORY;
   6200         goto _free_exit;
   6201     }
   6202     sal_memset(bkt_usage[u], 0, sz);
   6203 
   6204     sz = SOC_TH_MAX_BUCKET_ENTRIES(u) * sizeof(alpm_bkt_bmp_t);
   6205     sz2 = SHR_BITALLOCSIZE(ALPM_CTRL(u).num_bkts);
   6206     for (i = 0; i < SOC_TH_MAX_ALPM_VIEWS; i++) {
   6207         global_bkt_usage[u][i] = sal_alloc(sz, "ALPM_BS");
   6208         if (global_bkt_usage[u][i] == NULL) {
   6209             rv = SOC_E_MEMORY;
   6210             goto _free_exit;
   6211         }
   6212         sal_memset(global_bkt_usage[u][i], 0, sz);
   6213 
   6214         for (j = 0; j < SOC_TH_MAX_BUCKET_ENTRIES(u); j++) {
   6215             global_bkt_usage[u][i][j].bkt_bmp = sal_alloc(sz2, "ALPM BS bkt_bmp");
   6216             if (global_bkt_usage[u][i][j].bkt_bmp == NULL) {
   6217                 rv = SOC_E_MEMORY;
   6218                 goto _free_exit;
   6219             }
   6220             sal_memset(global_bkt_usage[u][i][j].bkt_bmp, 0, sz2);
   6221         }
   6222     }
   6223 
   6224     sal_memset(&_alpm_dbg_cntr[u], 0, sizeof(_alpm_int_dbg_cnt_t));
   6225 
   6226     /* Initialize PIVOT management */
   6227     for (i = 0; i < TH_MAX_PIVOT_COUNT(u); i++) {
   6228         ALPM_TCAM_PIVOT(u, i) = NULL;
   6229     }
   6230 
   6231     if (SOC_CONTROL(u)->alpm_bulk_retry == NULL) {
   6232         SOC_CONTROL(u)->alpm_bulk_retry =
   6233             sal_sem_create("ALPM bulk retry", sal_sem_BINARY, 0);
   6234     }
   6235     if (SOC_CONTROL(u)->alpm_lookup_retry == NULL) {
   6236         SOC_CONTROL(u)->alpm_lookup_retry =
   6237             sal_sem_create("ALPM lookup retry", sal_sem_BINARY, 0);
   6238     }
   6239     if (SOC_CONTROL(u)->alpm_insert_retry == NULL) {
   6240         SOC_CONTROL(u)->alpm_insert_retry =
   6241             sal_sem_create("ALPM insert retry", sal_sem_BINARY, 0);
   6242     }
   6243     if (SOC_CONTROL(u)->alpm_delete_retry == NULL) {
   6244         SOC_CONTROL(u)->alpm_delete_retry =
   6245             sal_sem_create("ALPM delete retry", sal_sem_BINARY, 0);
   6246     }
   6247 
   6248     rv = soc_th_alpm_128_lpm_init(u);
   6249     if (SOC_FAILURE(rv)) {
   6250         goto _free_exit;
   6251     }
   6252     return rv;
   6253 
   6254 _free_exit:
   6255     soc_th_alpm_mem_free(u);
   6256     return rv;
   6257 }
   6258 
   6259 /* clear alpm related internal state */
   6260 static int soc_th_alpm_state_clear(int u)
   6261 {
   6262     int i, rv;
   6263     alpm_pivot_t *tmp;
   6264     uint8 ipv;
   6265 
   6266     /* clear all pivot state */
   6267     for (i = 0; i < TH_MAX_PIVOT_COUNT(u); i++) {
   6268         tmp = ALPM_TCAM_PIVOT(u, i);
   6269         if (tmp) {
   6270             if (PIVOT_BUCKET_HANDLE(tmp)) {
   6271                 if (PIVOT_BUCKET_TRIE(tmp)) {
   6272                     /* traverse bucket trie and clear it */
   6273                     rv = trie_traverse(PIVOT_BUCKET_TRIE(tmp),
   6274                             alpm_delete_node_cb, NULL, _TRIE_INORDER_TRAVERSE);
   6275                     if (SOC_SUCCESS(rv)) {
   6276                         trie_destroy(PIVOT_BUCKET_TRIE(tmp));
   6277                     } else {
   6278                         LOG_ERROR(BSL_LS_SOC_ALPM,
   6279                                   (BSL_META_U(u,
   6280                                               "Unable to clear trie state for unit %d\n"),
   6281                                    u));
   6282 
   6283                         return rv;
   6284                     }
   6285                 }
   6286                 sal_free(PIVOT_BUCKET_HANDLE(tmp));
   6287             }
   6288             sal_free(ALPM_TCAM_PIVOT(u, i));
   6289             ALPM_TCAM_PIVOT(u, i) = NULL;
   6290         }
   6291     }
   6292 
   6293     /* clear all prefix tries */
   6294     for (i = 0; i <= SOC_VRF_MAX(u) + 1; i++) {
   6295         rv = trie_traverse(VRF_PREFIX_TRIE_IPV4(u, i), alpm_delete_node_cb,
   6296                            NULL, _TRIE_INORDER_TRAVERSE);
   6297         if (SOC_SUCCESS(rv)) {
   6298             trie_destroy(VRF_PREFIX_TRIE_IPV4(u, i));
   6299         } else {
   6300             LOG_ERROR(BSL_LS_SOC_ALPM,
   6301                       (BSL_META_U(u,
   6302                                   "unit: %d Unable to clear v4 pfx trie for vrf %d\n"),
   6303                        u, i));
   6304             return rv;
   6305         }
   6306         rv = trie_traverse(VRF_PREFIX_TRIE_IPV6(u, i), alpm_delete_node_cb,
   6307                            NULL, _TRIE_INORDER_TRAVERSE);
   6308         if (SOC_SUCCESS(rv)) {
   6309             trie_destroy(VRF_PREFIX_TRIE_IPV6(u, i));
   6310         } else {
   6311             LOG_ERROR(BSL_LS_SOC_ALPM,
   6312                       (BSL_META_U(u,
   6313                                   "unit: %d Unable to clear v4 pfx trie for vrf %d\n"),
   6314                        u, i));
   6315             return rv;
   6316         }
   6317         if (VRF_TRIE_DEFAULT_ROUTE_IPV4(u, i) != NULL) {
   6318             sal_free(VRF_TRIE_DEFAULT_ROUTE_IPV4(u, i));
   6319         }
   6320         if (VRF_TRIE_DEFAULT_ROUTE_IPV6(u, i) != NULL) {
   6321             sal_free(VRF_TRIE_DEFAULT_ROUTE_IPV6(u, i));
   6322         }
   6323         sal_memset(&alpm_vrf_handle[u][i], 0, sizeof(alpm_vrf_handle_t));
   6324     }
   6325 
   6326     /* Reset VRF_OVERRIDE debug counter */
   6327     sal_memset(&alpm_vrf_handle[u][MAX_VRF_ID], 0, sizeof(alpm_vrf_handle_t));
   6328     /* Mark Global Hi (VRF_OVERRIDE) for IPv4, IPv6-64, IPv6-128 inited for debug usage */
   6329     VRF_TRIE_INIT_DONE(u, MAX_VRF_ID, 0, 1);
   6330     VRF_TRIE_INIT_DONE(u, MAX_VRF_ID, 1, 1);
   6331     VRF_TRIE_INIT_DONE(u, MAX_VRF_ID, 2, 1);
   6332 
   6333     for (ipv = ALPM_IPV4; ipv < ALPM_IPVERS; ipv++) {
   6334         if (ipv == ALPM_IPV6 && !ALPM_CTRL(u)._alpm_128b_bkt_rsvd) {
   6335             SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv) = NULL;
   6336             SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv) = NULL;
   6337             break;
   6338         }
   6339         if (SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv) != NULL) {
   6340             if (SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv) !=
   6341                 SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv)) {
   6342                 sal_free(SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv));
   6343             }
   6344             SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv) = NULL;
   6345             sal_free(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv));
   6346             SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv) = NULL;
   6347         }
   6348     }
   6349     sal_memset(&soc_th_alpm_bucket[u], 0, sizeof(soc_alpm_bucket_t));
   6350     sal_memset(&_alpm_dbg_cntr[u], 0, sizeof(_alpm_int_dbg_cnt_t));
   6351 
   6352     /* Free memory allocated for VRF handles and tcam pivots */
   6353     soc_th_alpm_mem_free(u);
   6354 
   6355     return SOC_E_NONE;
   6356 }
   6357 
   6358 /* De-Init ALPM Subsytem */
   6359 int
   6360 soc_th_alpm_deinit(int u)
   6361 {
   6362     soc_th_alpm_lpm_deinit(u);
   6363 
   6364     SOC_IF_ERROR_RETURN(soc_th_alpm_128_lpm_deinit(u));
   6365 
   6366     SOC_IF_ERROR_RETURN(soc_th_alpm_128_state_clear(u));
   6367 
   6368     SOC_IF_ERROR_RETURN(soc_th_alpm_state_clear(u));
   6369 
   6370     if (SOC_CONTROL(u)->alpm_bulk_retry) {
   6371         sal_sem_destroy(SOC_CONTROL(u)->alpm_bulk_retry);
   6372         SOC_CONTROL(u)->alpm_bulk_retry = NULL;
   6373     }
   6374     if (SOC_CONTROL(u)->alpm_lookup_retry) {
   6375         sal_sem_destroy(SOC_CONTROL(u)->alpm_lookup_retry);
   6376         SOC_CONTROL(u)->alpm_lookup_retry = NULL;
   6377     }
   6378     if (SOC_CONTROL(u)->alpm_insert_retry) {
   6379         sal_sem_destroy(SOC_CONTROL(u)->alpm_insert_retry);
   6380         SOC_CONTROL(u)->alpm_insert_retry = NULL;
   6381     }
   6382     if (SOC_CONTROL(u)->alpm_delete_retry) {
   6383         sal_sem_destroy(SOC_CONTROL(u)->alpm_delete_retry);
   6384         SOC_CONTROL(u)->alpm_delete_retry = NULL;
   6385     }
   6386     return SOC_E_NONE;
   6387 }
   6388 
   6389 /*
   6390  * soc_th_alpm_vrf_add
   6391  * Add a VRF default route when a L3 VRF is added
   6392  * Adds a 0.0 entry into VRF
   6393  */
   6394 static int
   6395 soc_th_alpm_vrf_add(int u, int vrf, int v6)
   6396 {
   6397     defip_entry_t           *lpm_entry = NULL, tmp_lpm;
   6398     int                     log_bkt = 0;
   6399     int                     index;
   6400     int                     rv = SOC_E_NONE;
   6401     uint32                  key[5] = {0};
   6402     uint32                  length;
   6403     alpm_bucket_handle_t    *bucket_handle = NULL;
   6404     alpm_pivot_t            *pivot_pyld = NULL;
   6405     payload_t               *pfx_pyld = NULL;
   6406     trie_t                  *root = NULL;
   6407     trie_t                  *pivot_root = NULL;
   6408     trie_t                  *bucket_root = NULL;
   6409     soc_mem_t               mem;
   6410 
   6411     if (v6 == 0) {
   6412         trie_init(_MAX_KEY_LEN_48_, &VRF_PIVOT_TRIE_IPV4(u, vrf));
   6413         pivot_root = VRF_PIVOT_TRIE_IPV4(u, vrf);
   6414     } else {
   6415         trie_init(_MAX_KEY_LEN_144_, &VRF_PIVOT_TRIE_IPV6(u, vrf));
   6416         pivot_root = VRF_PIVOT_TRIE_IPV6(u, vrf);
   6417     }
   6418 
   6419     /* Initialize VRF PIVOT IPV4 trie */
   6420     if (v6 == 0) {
   6421         trie_init(_MAX_KEY_LEN_48_, &VRF_PREFIX_TRIE_IPV4(u, vrf));
   6422         root = VRF_PREFIX_TRIE_IPV4(u, vrf);
   6423     } else {
   6424         trie_init(_MAX_KEY_LEN_144_, &VRF_PREFIX_TRIE_IPV6(u, vrf));
   6425         root = VRF_PREFIX_TRIE_IPV6(u, vrf);
   6426     }
   6427 
   6428     lpm_entry = sal_alloc(sizeof(defip_entry_t), "Default LPM entry");
   6429     if (lpm_entry == NULL) {
   6430         LOG_ERROR(BSL_LS_SOC_ALPM,
   6431                   (BSL_META_U(u,
   6432                               "soc_alpm_vrf_add: unable to allocate memory for "
   6433                               "IPv4 LPM entry\n")));
   6434         return SOC_E_MEMORY;
   6435     }
   6436 
   6437     /* Initialize an lpm entry to perform a match */
   6438     _soc_th_alpm_lpm_ent_key_init(u, key, 0, vrf, v6, lpm_entry, 1);
   6439 
   6440     if (v6 == 0) {
   6441         VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf) = lpm_entry;
   6442     } else {
   6443         VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) = lpm_entry;
   6444     }
   6445 
   6446     /* for global VRF */
   6447     if (vrf == SOC_VRF_MAX(u) + 1) {
   6448         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f, 1);
   6449     } else {
   6450         /* Set default miss to global route only for non global routes */
   6451         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, DEFAULT_MISS0f, 1);
   6452     }
   6453     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ENTRY_VIEW0f,
   6454         _soc_th_alpm_lpm_entry_view_get(u, v6,
   6455         VRF_FLEX_IS_SET(u, vrf, vrf, v6, 1)));
   6456 
   6457     SOC_ALPM_TABLE_MEM(u, v6, mem, VRF_FLEX_IS_SET(u, vrf, vrf, v6, 1));
   6458     rv = soc_th_alpm_assign(u, vrf, mem, &log_bkt, NULL, NULL);
   6459     if (SOC_FAILURE(rv)) {
   6460         goto _err_exit;
   6461     }
   6462     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ALG_BKT_PTR0f,
   6463                         ALPM_PHY_BKT(u, log_bkt));
   6464     if (ALPM_CTRL(u).bkt_sharing) {
   6465         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ALG_SUB_BKT_PTR0f,
   6466                             ALPM_SUB_BKT(u, log_bkt));
   6467     }
   6468 
   6469     /* add Entry into tcam as default routes for the VRF */
   6470     /* urpf could modify the lpm entry. So use tmp one */
   6471     sal_memcpy(&tmp_lpm, lpm_entry, sizeof(tmp_lpm));
   6472     rv = soc_th_alpm_lpm_insert(u, &tmp_lpm, &index, INVALID_BPM_LEN, 0, 0);
   6473     if (SOC_FAILURE(rv)) {
   6474         goto _err_exit;
   6475     }
   6476 
   6477     /* Insert Pivot into the pivot tries */
   6478     bucket_handle = sal_alloc(sizeof(alpm_bucket_handle_t), "ALPM Bucket Handle");
   6479     if (bucket_handle == NULL) {
   6480         LOG_ERROR(BSL_LS_SOC_ALPM,
   6481                    (BSL_META_U(u,
   6482                      "soc_th_alpm_vrf_add: Unable to allocate memory for "
   6483                                                     "PIVOT trie node \n")));
   6484         rv = SOC_E_MEMORY;
   6485         goto _err_exit;
   6486     }
   6487     sal_memset(bucket_handle, 0, sizeof(*bucket_handle));
   6488 
   6489     /* Allocate PIVOT Payload */
   6490     pivot_pyld = sal_alloc(sizeof(alpm_pivot_t), "Payload for Pivot");
   6491     if (pivot_pyld == NULL) {
   6492         LOG_ERROR(BSL_LS_SOC_ALPM,
   6493                   (BSL_META_U(u,
   6494                               "soc_alpm_vrf_add: Unable to allocate memory for "
   6495                               "PIVOT trie node \n")));
   6496         rv = SOC_E_MEMORY;
   6497         goto _err_exit;
   6498     }
   6499 
   6500     pfx_pyld = sal_alloc(sizeof(payload_t), "Payload for pfx trie key");
   6501     if (pfx_pyld == NULL) {
   6502         LOG_ERROR(BSL_LS_SOC_ALPM,
   6503                   (BSL_META_U(u,
   6504                               "soc_alpm_vrf_add: Unable to allocate memory for "
   6505                               "pfx trie node \n")));
   6506         rv = SOC_E_MEMORY;
   6507         goto _err_exit;
   6508     }
   6509     sal_memset(pivot_pyld, 0, sizeof(*pivot_pyld));
   6510     sal_memset(pfx_pyld, 0, sizeof(*pfx_pyld));
   6511 
   6512     /* 0 for default * route */
   6513     length = 0;
   6514     PIVOT_BUCKET_HANDLE(pivot_pyld) = bucket_handle;
   6515     if (v6) {
   6516         trie_init(_MAX_KEY_LEN_144_, &PIVOT_BUCKET_TRIE(pivot_pyld));
   6517     } else {
   6518         trie_init(_MAX_KEY_LEN_48_, &PIVOT_BUCKET_TRIE(pivot_pyld));
   6519     }
   6520     bucket_root = PIVOT_BUCKET_TRIE(pivot_pyld);
   6521     PIVOT_BUCKET_INDEX(pivot_pyld) = log_bkt;
   6522     PIVOT_BUCKET_VRF(pivot_pyld) = vrf;
   6523     PIVOT_BUCKET_IPV6(pivot_pyld) = v6;
   6524     PIVOT_BUCKET_DEF(pivot_pyld) = TRUE;
   6525 
   6526     pivot_pyld->key[0] = pfx_pyld->key[0] = key[0];
   6527     pivot_pyld->key[1] = pfx_pyld->key[1] = key[1];
   6528     pivot_pyld->len = pfx_pyld->len    = length;
   6529     /* no need to convert key in trie format since it's all 0s */
   6530     rv = trie_insert(root, key, ALPM_CTRL(u).trie_propagate ? key : NULL,
   6531                      length, &(pfx_pyld->node));
   6532 
   6533     /* no internal default in bucket trie */
   6534 
   6535     if (SOC_FAILURE(rv)) {
   6536         /* free alloced memory */
   6537         goto _err_exit;
   6538     }
   6539 
   6540     /* insert into trie of pivots */
   6541     /* no need to convert key in trie format since it's all 0s */
   6542     rv = trie_insert(pivot_root, key, ALPM_CTRL(u).trie_propagate ? key : NULL,
   6543                      length, (trie_node_t *)pivot_pyld);
   6544     if (SOC_FAILURE(rv)) {
   6545         trie_node_t *delp = NULL;
   6546         (void) trie_delete(root, key, length, &delp);
   6547         /* free alloced memory */
   6548         goto _err_exit;
   6549     }
   6550 
   6551     /* get physical index */
   6552     index = soc_th_alpm_physical_idx(u, L3_DEFIPm, index, v6);
   6553     if (v6 == 0) {
   6554         ALPM_TCAM_PIVOT(u, index) = pivot_pyld;
   6555         PIVOT_TCAM_INDEX(pivot_pyld) = index;
   6556     } else {
   6557         ALPM_TCAM_PIVOT(u, index << 1) = pivot_pyld;
   6558         PIVOT_TCAM_INDEX(pivot_pyld) = index << 1;
   6559     }
   6560     PIVOT_TCAM_BPMLEN(pivot_pyld) = length;
   6561 
   6562     VRF_TRIE_INIT_DONE(u, vrf, v6, 1);
   6563     return rv;
   6564 
   6565 _err_exit:
   6566     if (pfx_pyld != NULL) {
   6567         sal_free(pfx_pyld);
   6568     }
   6569     if (pivot_pyld != NULL) {
   6570         sal_free(pivot_pyld);
   6571     }
   6572     if (bucket_handle != NULL) {
   6573         sal_free(bucket_handle);
   6574     }
   6575     if (lpm_entry != NULL) {
   6576         sal_free(lpm_entry);
   6577     }
   6578     if (v6 == 0) {
   6579         VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf) = NULL;
   6580     } else {
   6581         VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) = NULL;
   6582     }
   6583     if (bucket_root != NULL) {
   6584         trie_destroy(bucket_root);
   6585         PIVOT_BUCKET_TRIE(pivot_pyld) = NULL;
   6586     }
   6587     if (root != NULL) {
   6588         trie_destroy(root);
   6589         if (v6 == 0) {
   6590             VRF_PREFIX_TRIE_IPV4(u, vrf) = NULL;
   6591         } else {
   6592             VRF_PREFIX_TRIE_IPV6(u, vrf) = NULL;
   6593         }
   6594     }
   6595     if (pivot_root != NULL) {
   6596         trie_destroy(pivot_root);
   6597         if (v6 == 0) {
   6598             VRF_PIVOT_TRIE_IPV4(u, vrf) = NULL;
   6599         } else {
   6600             VRF_PIVOT_TRIE_IPV6(u, vrf) = NULL;
   6601         }
   6602     }
   6603 
   6604     return rv;
   6605 }
   6606 
   6607 /*
   6608  * soc_th_alpm_vrf_delete
   6609  * Delete the VRF default route when a L3 VRF is destroyed
   6610  */
   6611 static int
   6612 soc_th_alpm_vrf_delete(int u, int vrf, int v6)
   6613 {
   6614     defip_entry_t *lpm_entry;
   6615     int idx, vrf_id, _vrf;
   6616     int rv = SOC_E_NONE;
   6617     uint32 key[5] = {0}, result[SOC_MAX_MEM_FIELD_WORDS];
   6618     payload_t *payload;
   6619     alpm_pivot_t *pivot_pyld1;
   6620     trie_node_t *delp;
   6621     trie_t *root;
   6622     trie_t *pivot_root = NULL;
   6623 
   6624     soc_mem_t mem;
   6625     int tcam_index, log_bkt, index;
   6626     uint32 alpm_ent[SOC_MAX_MEM_FIELD_WORDS];
   6627 
   6628     if (v6 == 0) {
   6629         lpm_entry = VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf);
   6630     } else {
   6631         lpm_entry = VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf);
   6632     }
   6633 
   6634     SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(u, lpm_entry, &vrf_id, &_vrf));
   6635     SOC_ALPM_TABLE_MEM(u, v6, mem, VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 0));
   6636     rv = _soc_th_alpm_find(u, mem, v6, lpm_entry, vrf_id, _vrf, alpm_ent,
   6637                            &tcam_index, &log_bkt, &index, TRUE);
   6638 
   6639     /* find bucket pointers and release them */
   6640     rv = soc_th_alpm_bucket_release(u, log_bkt, vrf, v6);
   6641     if (SOC_FAILURE(rv)) {
   6642         LOG_ERROR(BSL_LS_SOC_ALPM,
   6643                   (BSL_META_U(u, "soc_th_alpm_bucket_release: unable to free"
   6644                               " bucket %d vrf %d v6 %d\n"), log_bkt, vrf, v6));
   6645     }
   6646 
   6647     /* add Entry into tcam as default routes for the VRF */
   6648     rv = soc_th_alpm_lpm_match(u, lpm_entry, (void *) result, &idx);
   6649     if (SOC_FAILURE(rv)) {
   6650         LOG_ERROR(BSL_LS_SOC_ALPM,
   6651                   (BSL_META_U(u, "soc_alpm_vrf_delete: unable to get internal"
   6652                               " pivot idx for vrf %d/%d\n"), vrf, v6));
   6653         idx = -1;
   6654     }
   6655 
   6656     idx = soc_th_alpm_physical_idx(u, L3_DEFIPm, idx, v6);
   6657     if (v6 == 0) {
   6658         pivot_pyld1 = ALPM_TCAM_PIVOT(u, idx);
   6659     } else {
   6660         pivot_pyld1 = ALPM_TCAM_PIVOT(u, idx << 1);
   6661     }
   6662 
   6663     rv = soc_th_alpm_lpm_delete(u, lpm_entry);
   6664     if (SOC_FAILURE(rv)) {
   6665         LOG_ERROR(BSL_LS_SOC_ALPM,
   6666                   (BSL_META_U(u,
   6667                               "soc_alpm_vrf_delete: unable to delete lpm entry "
   6668                               " for internal default for vrf %d/%d\n"), vrf, v6));
   6669     }
   6670 
   6671     sal_free(lpm_entry);
   6672 
   6673     if (v6 == 0) {
   6674         VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf) = NULL;
   6675         root = VRF_PREFIX_TRIE_IPV4(u, vrf);
   6676         VRF_PREFIX_TRIE_IPV4(u, vrf) = NULL;
   6677     } else {
   6678         VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf)  = NULL;
   6679         root = VRF_PREFIX_TRIE_IPV6(u, vrf);
   6680         VRF_PREFIX_TRIE_IPV6(u, vrf) = NULL;
   6681     }
   6682     VRF_TRIE_INIT_DONE(u, vrf, v6, 0);
   6683 
   6684     rv = trie_delete(root, key, 0, &delp);
   6685     payload = (payload_t *) delp;
   6686     if (SOC_FAILURE(rv)) {
   6687         LOG_ERROR(BSL_LS_SOC_ALPM,
   6688                   (BSL_META_U(u,
   6689                               "Unable to delete internal default for vrf "
   6690                               " %d/%d\n"), vrf, v6));
   6691     }
   6692     sal_free(payload);
   6693 
   6694     (void) trie_destroy(root);
   6695 
   6696     if (v6 == 0) {
   6697         pivot_root = VRF_PIVOT_TRIE_IPV4(u, vrf);
   6698         VRF_PIVOT_TRIE_IPV4(u, vrf) = NULL;
   6699     } else {
   6700         pivot_root = VRF_PIVOT_TRIE_IPV6(u, vrf);
   6701         VRF_PIVOT_TRIE_IPV6(u, vrf) = NULL;
   6702     }
   6703 
   6704     delp = NULL;
   6705     rv = trie_delete(pivot_root, key, 0, &delp);
   6706     if (SOC_FAILURE(rv)) {
   6707         LOG_ERROR(BSL_LS_SOC_ALPM,
   6708                   (BSL_META_U(u,
   6709                               "Unable to delete internal pivot node for vrf"
   6710                               " %d/%d\n"), vrf, v6));
   6711     }
   6712     (void) trie_destroy(pivot_root);
   6713 
   6714     (void) trie_destroy(PIVOT_BUCKET_TRIE(pivot_pyld1));
   6715     sal_free(PIVOT_BUCKET_HANDLE(pivot_pyld1));
   6716     sal_free(pivot_pyld1);
   6717 
   6718     return rv;
   6719 }
   6720 
   6721 /*
   6722  * soc_th_alpm_insert
   6723  * For IPV4 assume only both IP_ADDR0 is valid
   6724  * Moving multiple entries around in h/w vs  doing a linear search in s/w
   6725  */
   6726 int
   6727 soc_th_alpm_insert(int u, void *lpm_entry, uint32 flags, int ent_index,
   6728                    int pivot_info)
   6729 {
   6730     defip_alpm_ipv4_1_entry_t alpmv4_entry, alpmv4_sip_entry;
   6731     defip_alpm_ipv6_64_1_entry_t alpmv6_entry, alpmv6_sip_entry;
   6732     soc_mem_t mem;
   6733     void      *bufp, *bufp2;
   6734     int       vrf_id, vrf;
   6735     int       index;
   6736     int       ipv6;
   6737     int       rv = SOC_E_NONE;
   6738     uint32    default_route;
   6739     int       log_bkt = 0, phy_bkt = 0;
   6740     int       ipmc_route = 0;
   6741     int       flex_v6_64 = 0;
   6742 
   6743     ipv6 = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, MODE0_f(u));
   6744 
   6745     /* Get table memory. */
   6746     SOC_ALPM_TABLE_MEM(u, ipv6, mem, flags & SOC_ALPM_STAT_FLEX);
   6747 
   6748     /* Assign entry buf based on table being used */
   6749     SOC_ALPM_ENTRY_BUF(ipv6, mem, bufp, alpmv4_entry, alpmv6_entry);
   6750     SOC_ALPM_ENTRY_BUF(ipv6, mem, bufp2, alpmv4_sip_entry, alpmv6_sip_entry);
   6751 
   6752     if (ent_index != -1) {
   6753         log_bkt = SOC_TH_ALPM_AIDX_TO_LOG_BKT(u, ent_index);
   6754     }
   6755     SOC_IF_ERROR_RETURN(
   6756         _soc_th_alpm_mem_ent_init(u, ipv6, lpm_entry, bufp, bufp2, mem,
   6757                                   flags, &default_route, log_bkt));
   6758 
   6759     /* If the entry is override, then insert into TCAM directly */
   6760     SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(u, lpm_entry, &vrf_id, &vrf));
   6761 
   6762     if (VRF_FLEX_COMPLETED(u, vrf_id, vrf, ipv6)) {
   6763         if (VRF_FLEX_IS_SET(u, vrf_id, vrf, ipv6, 1) != !!(flags & SOC_ALPM_STAT_FLEX)) {
   6764             LOG_ERROR(BSL_LS_SOC_ALPM,
   6765                       (BSL_META_U(u,
   6766                                   "soc_alpm_insert:Flex flag conflict\n"
   6767                                   )));
   6768             return SOC_E_PARAM;
   6769         }
   6770     } else {
   6771         VRF_FLEX_SET(u, vrf_id, vrf, ipv6, flags & SOC_ALPM_STAT_FLEX);
   6772     }
   6773 
   6774     if (soc_feature(u, soc_feature_ipmc_defip)) {
   6775         ipmc_route = 0;
   6776         if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE0f)) {
   6777             ipmc_route = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, MULTICAST_ROUTE0f);
   6778         } else if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE0f)) {
   6779             if (soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, DATA_TYPE0f) == 2) {
   6780                 ipmc_route = 1;
   6781             } else {
   6782                 ipmc_route = 0;
   6783             }
   6784         }
   6785     }
   6786 
   6787     if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && ipv6 &&
   6788         (flags & SOC_ALPM_STAT_FLEX)) {
   6789         if (soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f) == 0xFFFFFFFF &&
   6790             soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f) == 0xFFFFFFFF) {
   6791             flex_v6_64 = 1;
   6792         }
   6793     }
   6794 
   6795     /* For VRF_OVERRIDE (Global High) entries and IPMC route,
   6796        software needs to maintain the index */
   6797     /* Global High and Global Low Prefixes reside in TCAM directly,
   6798        in TCAM / ALPM mode */
   6799     /* Global High Prefixes reside in TCAM directly, in Parallel mode */
   6800     if (ALPM_PREFIX_IN_TCAM(u, vrf_id) || (ipmc_route) || (flex_v6_64)) {
   6801         /* Insert into TCAM directly and return */
   6802         /* search in the hash table */
   6803         rv = soc_th_alpm_lpm_insert(u, lpm_entry, &index, INVALID_BPM_LEN, 0,
   6804                                     flags & SOC_ALPM_RPF_SRC_DISCARD);
   6805         if (SOC_SUCCESS(rv) && !(pivot_info & SOC_ALPM_LPM_LOOKUP_HIT)) {
   6806             VRF_TRIE_ROUTES_INC(u, vrf_id, vrf, ipv6);
   6807         }
   6808         if (rv == SOC_E_FULL) {
   6809             if (vrf_id == SOC_L3_VRF_OVERRIDE) {
   6810                 VRF_PIVOT_FULL_INC(u, MAX_VRF_ID, ipv6);
   6811             } else {
   6812                 VRF_PIVOT_FULL_INC(u, vrf, ipv6);
   6813             }
   6814         }
   6815         return(rv);
   6816     } else if (vrf == 0) {
   6817         if (ALPM_CTRL(u).gp_zoned) {
   6818             /* cannot have 0 as a VRF in parallel mode */
   6819             LOG_ERROR(BSL_LS_SOC_ALPM,
   6820                       (BSL_META_U(u,
   6821                                   "VRF=0 cannot be added in current mode\n")));
   6822             return SOC_E_PARAM;
   6823         }
   6824     }
   6825 
   6826     /* combined search mode protection */
   6827     if (vrf_id != SOC_L3_VRF_GLOBAL) {
   6828         if (ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_COMBINED) {
   6829             /* for emtpy DB allow insert only if route is default */
   6830             if (VRF_TRIE_ROUTES_CNT(u, vrf_id, vrf, ipv6) == 0) {
   6831                 /* check if route is default, else throw error */
   6832                 if (!default_route) {
   6833                     LOG_ERROR(BSL_LS_SOC_ALPM,
   6834                               (BSL_META_U(u,
   6835                               "VRF %d: First route in a VRF has to "
   6836                               " be a default route in this mode\n"), vrf_id));
   6837                     return SOC_E_PARAM;
   6838                 }
   6839             }
   6840         }
   6841     }
   6842 
   6843     /* non override entries, goes into ALPM memory */
   6844     if (!VRF_TRIE_INIT_COMPLETED(u, vrf, ipv6)) {
   6845         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   6846                     (BSL_META_U(u,
   6847                                 "soc_alpm_insert:VRF %d is not "
   6848                                 "initialized\n"), vrf));
   6849         rv = soc_th_alpm_vrf_add(u, vrf, ipv6);
   6850         if (SOC_FAILURE(rv)) {
   6851             LOG_ERROR(BSL_LS_SOC_ALPM,
   6852                       (BSL_META_U(u,
   6853                                   "soc_alpm_insert:VRF %d/%d trie init \n"
   6854                                   "failed\n"), vrf, ipv6));
   6855             return rv;
   6856         }
   6857         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   6858                     (BSL_META_U(u,
   6859                                 "soc_alpm_insert:VRF %d/%d trie init "
   6860                                 "completed\n"), vrf, ipv6));
   6861 
   6862     }
   6863 
   6864     /* Find and update the entry */
   6865     if (pivot_info & SOC_ALPM_LOOKUP_HIT) {
   6866         rv = _soc_th_alpm_find_and_update(u, ipv6, lpm_entry, bufp, bufp2, mem,
   6867                                           ent_index);
   6868     } else {
   6869         /* entry is not found in database */
   6870         /* Insert the entry into the database, if FULL, split the bucket */
   6871         /* Insert prefix into trie */
   6872         /* Split trie : Insertion into trie results into Split */
   6873         /* Allocate a TCAM entry for PIVOT and bucket and move entries */
   6874         if (ent_index == -1) {
   6875             /* internally 0 is invalid bucket index */
   6876             ent_index = 0;
   6877         }
   6878         phy_bkt = SOC_TH_ALPM_AIDX_TO_PHY_BKT(u, ent_index);
   6879         /* In double wide mode, the ent_index could come from second
   6880          * bucket, need to adjust to first bucket */
   6881         if (ALPM_CTRL(u).double_wide[ipv6] && (phy_bkt & 0x1)) {
   6882             phy_bkt &= ~0x1;
   6883         }
   6884         log_bkt = ALPM_LOG_BKT(phy_bkt,
   6885                                SOC_TH_ALPM_AIDX_TO_SUB_BKT(u, ent_index));
   6886 
   6887         rv = _soc_th_alpm_insert(u, ipv6, lpm_entry, mem, bufp, bufp2, &index,
   6888                                  log_bkt, pivot_info);
   6889         if (SOC_SUCCESS(rv)) {
   6890             VRF_TRIE_ROUTES_INC(u, vrf_id, vrf, ipv6);
   6891         }
   6892     }
   6893 
   6894     if (rv == SOC_E_FULL) {
   6895         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   6896                     (BSL_META_U(u,
   6897                     "unit %d :soc_alpm_insert: Route Insertion Failed :%s\n"),
   6898                     u, soc_errmsg(rv)));
   6899     } else if (rv != SOC_E_NONE) {
   6900         LOG_ERROR(BSL_LS_SOC_ALPM,
   6901                  (BSL_META_U(u,
   6902                  "unit %d :soc_alpm_insert: Route Insertion Failed :%s\n"),
   6903                  u, soc_errmsg(rv)));
   6904     }
   6905     return(rv);
   6906 }
   6907 
   6908 /*
   6909  * soc_th_alpm_lookup
   6910  * For IPV4 assume only both IP_ADDR0 is valid
   6911  * Moving multiple entries around in h/w vs  doing a linear search in s/w
   6912  */
   6913 int
   6914 soc_th_alpm_lookup(int u,
   6915                 void *key_data,
   6916                 void *e,         /* return entry data if found */
   6917                 int *index_ptr,
   6918                 int *cookie)
   6919 {
   6920     defip_alpm_ipv4_1_entry_t alpmv4_entry; /* Search Result buffer */
   6921     defip_alpm_ipv6_64_1_entry_t alpmv6_entry; /* Search Result buffer */
   6922     soc_mem_t mem;
   6923     int       log_bkt = 0;
   6924     int       tcam_index = -1;
   6925     void      *bufp;
   6926     int       vrf_id, vrf;
   6927     int       ipv6, pfx;
   6928     int       rv = SOC_E_NONE;
   6929     int       ipmc_route = 0;
   6930     int       flex_v6_64 = 0;
   6931     int       flex;
   6932 
   6933     /* First launch lookup directly into tcam. If hit comes from override
   6934      * vrf just return it. Else launch lookup into alpm pivots
   6935      */
   6936     /* For VRF_OVERRIDE (Global High) entries, software needs to maintain the
   6937      * index */
   6938     /* Prefix resides in TCAM directly */
   6939 
   6940     /* search in the hash table */
   6941     *index_ptr = 0;
   6942     rv = _soc_th_alpm_lpm_match(u, key_data, e, index_ptr, &pfx, &ipv6,
   6943                                 &vrf_id, &vrf);
   6944     /*
   6945      * If entry is ipv4 copy to the "zero" half of the,
   6946      * buffer, "zero" half of lpm_entry if the  original entry
   6947      * is in the "one" half.
   6948      */
   6949     flex = VRF_FLEX_IS_SET(u, vrf_id, vrf, ipv6, 0);
   6950     if (SOC_SUCCESS(rv)) {
   6951         if (!ipv6 && (*index_ptr & 0x1)) {
   6952             rv = soc_th_alpm_lpm_ip4entry1_to_0(u, e, e, PRESERVE_HIT);
   6953         }
   6954         if (soc_feature(u, soc_feature_ipmc_defip)) {
   6955             ipmc_route = 0;
   6956             if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE0f)) {
   6957                 ipmc_route = soc_mem_field32_get(u, L3_DEFIPm, e, MULTICAST_ROUTE0f);
   6958             } else if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE0f)) {
   6959                 if (soc_mem_field32_get(u, L3_DEFIPm, e, DATA_TYPE0f) == 2) {
   6960                     ipmc_route = 1;
   6961                 } else {
   6962                     ipmc_route = 0;
   6963                 }
   6964             }
   6965         }
   6966 
   6967         if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && ipv6 && flex) {
   6968             if (soc_mem_field32_get(u, L3_DEFIPm, key_data, IP_ADDR_MASK0f) == 0xFFFFFFFF &&
   6969                 soc_mem_field32_get(u, L3_DEFIPm, key_data, IP_ADDR_MASK1f) == 0xFFFFFFFF) {
   6970                 flex_v6_64 = 1;
   6971             }
   6972         }
   6973     }
   6974     if (ALPM_PREFIX_IN_TCAM(u, vrf_id) || (ipmc_route) || (flex_v6_64)) {
   6975         *cookie = 0;
   6976         if (SOC_SUCCESS(rv)) {
   6977             *cookie |= SOC_ALPM_LPM_LOOKUP_HIT;
   6978         }
   6979         return rv;
   6980     }
   6981 
   6982     /* either no hit in OVERRIDE or hit in pivot tcam */
   6983 
   6984     /* non override entries, go to into ALPM memory */
   6985     if (!VRF_TRIE_INIT_COMPLETED(u, vrf, ipv6)) {
   6986         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   6987                     (BSL_META_U(u, "soc_alpm_lookup:VRF %d is not initialized\n"),
   6988                      vrf));
   6989         *cookie = 0;
   6990         return SOC_E_NOT_FOUND;
   6991     }
   6992     /* Get table memory. */
   6993     SOC_ALPM_TABLE_MEM(u, ipv6, mem, flex);
   6994 
   6995     /* Assign entry buf based on table being used */
   6996     SOC_ALPM_ENTRY_BUF(ipv6, mem, bufp, alpmv4_entry, alpmv6_entry);
   6997 
   6998     SOC_ALPM_LPM_LOCK(u);
   6999     /* Find and update the entry */
   7000     rv = _soc_th_alpm_find(u, mem, ipv6, key_data, vrf_id, vrf, bufp,
   7001                            &tcam_index, &log_bkt, index_ptr, TRUE);
   7002     SOC_ALPM_LPM_UNLOCK(u);
   7003     if (SOC_FAILURE(rv)) {
   7004         *cookie = tcam_index;
   7005         *index_ptr = SOC_TH_ALPM_AIDX(u, ALPM_PHY_BKT(u, log_bkt),
   7006                                       ALPM_SUB_BKT(u, log_bkt), 0, 0);
   7007         return rv;
   7008     }
   7009     /* Copy ALPM memory to LPM entry */
   7010     rv =  _soc_th_alpm_lpm_ent_init(u, bufp, mem, ipv6, vrf_id, log_bkt,
   7011                                     *index_ptr, e, flex);
   7012     *cookie = SOC_ALPM_LOOKUP_HIT | tcam_index;
   7013     if (flex) {
   7014         *cookie |= SOC_ALPM_COOKIE_FLEX;
   7015     }
   7016     *index_ptr = (ALPM_SUB_BKT(u, log_bkt) << ALPM_ENT_INDEX_BITS) | *index_ptr;
   7017 
   7018     return(rv);
   7019 }
   7020 
   7021 /* Find a LPM Global low or VRF route in ALPM memory */
   7022 static int
   7023 _soc_th_alpm_find_best_match(int u,
   7024                              void *key_data,
   7025                              void *e,          /* return entry data if found */
   7026                              int vrf_id,
   7027                              int *tcam_index,
   7028                              int *log_bkt,
   7029                              int *key_index,
   7030                              int do_urpf)
   7031 {
   7032     int rv = SOC_E_NONE;
   7033     int i, j, v6, hit = 0;
   7034     uint32 db_type, ent_type, bank_disable;
   7035     defip_aux_scratch_entry_t aux_entry;
   7036     int global, mvrf, vrf;
   7037     int index;
   7038     soc_mem_t mem, lpm_mem;
   7039     int hw_len, sw_len;
   7040     int ent_num = ALPM_IPV4_BKT_COUNT;
   7041     int flex;
   7042 
   7043     /* Used for keeping Longest Matched entry in Bucket */
   7044     uint32  alpm_bufp[SOC_MAX_MEM_FIELD_WORDS] = {0};
   7045     int     alpm_len = -1;
   7046     int     alpm_index = 0;
   7047 
   7048     soc_field_t ip_addr_fld[2] = {
   7049         IP_ADDR0f,
   7050         IP_ADDR1f,
   7051     };
   7052 
   7053     lpm_mem = L3_DEFIPm;
   7054     v6 = soc_mem_field32_get(u, lpm_mem, key_data, MODE0_f(u));
   7055     global = soc_mem_field32_get(u, lpm_mem, key_data, GLOBAL_ROUTE0f);
   7056     mvrf = soc_mem_field32_get(u, lpm_mem, key_data, VRF_ID_0f);
   7057     vrf = (vrf_id == SOC_L3_VRF_GLOBAL) ? (SOC_VRF_MAX(u) + 1) : mvrf;
   7058 
   7059     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7060                 (BSL_META_U(u,
   7061                 "Prefare AUX Scratch for searching TCAM in "
   7062                 "%s region, Key data: v6 %d global %d vrf %d:\n"),
   7063                 vrf_id == SOC_L3_VRF_GLOBAL ? "Global" : "VRF",
   7064                 v6, global, mvrf));
   7065 
   7066     bank_disable = ALPM_CTRL(u).bank_disable_bmp_8b[vrf != SOC_VRF_MAX(u) + 1];
   7067 
   7068     if (ALPM_CTRL(u).sw_prefix_lkup) {
   7069         uint32 prefix[5] = {0};
   7070         uint32 length = 0;
   7071         int    default_route = 0;
   7072 
   7073         if (!VRF_TRIE_INIT_COMPLETED(u, vrf, v6)) {
   7074             LOG_VERBOSE(BSL_LS_SOC_ALPM, (BSL_META_U(u,
   7075                 "_soc_th_alpm_find_best_match: VRF %d is not initialized\n"),
   7076                 vrf));
   7077             return SOC_E_NOT_FOUND;
   7078         }
   7079 
   7080         /* Create Prefix */
   7081         rv = _soc_th_alpm_prefix_create(u, v6, key_data, prefix, &length,
   7082                                         &default_route);
   7083         if (SOC_FAILURE(rv)) {
   7084             LOG_ERROR(BSL_LS_SOC_ALPM, (BSL_META_U(u,
   7085                 "_soc_th_alpm_128_find_best_match: prefix create failed\n")));
   7086             return rv;
   7087         }
   7088         SOC_IF_ERROR_RETURN(_soc_th_alpm_sw_pivot_find(u, prefix, length, v6,
   7089                                                        vrf, &hit, tcam_index,
   7090                                                        log_bkt));
   7091     } else {
   7092         soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type);
   7093         if (do_urpf) {
   7094             db_type += 1;
   7095         }
   7096         if (vrf_id == SOC_L3_VRF_GLOBAL) {
   7097             /* Crack these value to use _fill_aux routine */
   7098             soc_mem_field32_set(u, lpm_mem, key_data, GLOBAL_ROUTE0f, 1);
   7099             soc_mem_field32_set(u, lpm_mem, key_data, VRF_ID_0f, 0);
   7100         }
   7101 
   7102         sal_memset(&aux_entry, 0, sizeof(defip_aux_scratch_entry_t));
   7103         SOC_IF_ERROR_RETURN(
   7104             _soc_th_alpm_fill_aux_entry_for_op(u, key_data, v6, db_type,
   7105                                                ent_type, 0, &aux_entry));
   7106         /* Recover to original value */
   7107         if (vrf_id == SOC_L3_VRF_GLOBAL) {
   7108             soc_mem_field32_set(u, lpm_mem, key_data, GLOBAL_ROUTE0f, global);
   7109             soc_mem_field32_set(u, lpm_mem, key_data, VRF_ID_0f, mvrf);
   7110         }
   7111 
   7112         /* Start shadow table engine to search */
   7113         SOC_IF_ERROR_RETURN(
   7114             _soc_th_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry, TRUE, &hit,
   7115                                 tcam_index, log_bkt, 0));
   7116     }
   7117 
   7118     if (hit == 0) {
   7119         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7120                     (BSL_META_U(u,"Could not find bucket\n")));
   7121         return SOC_E_NOT_FOUND;
   7122     }
   7123 
   7124     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7125                 (BSL_META_U(u, "Hit in memory %s, index %d, "
   7126                 "bucket [%d,%d]\n"), SOC_MEM_NAME(u, lpm_mem),
   7127                 soc_th_alpm_logical_idx(u, lpm_mem, (*tcam_index) >> 1, 1),
   7128                 ALPM_PHY_BKT(u, *log_bkt), ALPM_SUB_BKT(u, *log_bkt)));
   7129 
   7130     /* Found, check ALPM bucket */
   7131     flex = VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 0);
   7132     SOC_ALPM_TABLE_MEM(u, v6, mem, flex);
   7133     rv = _soc_th_alpm_mask_len_get(u, v6, key_data, &sw_len);
   7134     if (SOC_FAILURE(rv)) {
   7135         return rv;
   7136     }
   7137 
   7138     switch (mem) {
   7139     case L3_DEFIP_ALPM_IPV4m:
   7140         ent_num = ALPM_IPV4_BKT_COUNT;
   7141         break;
   7142     case L3_DEFIP_ALPM_IPV4_1m:
   7143         ent_num = ALPM_IPV4_BKT_COUNT_FLEX;
   7144         break;
   7145     case L3_DEFIP_ALPM_IPV6_64m:
   7146         ent_num = ALPM_IPV6_64_BKT_COUNT;
   7147         break;
   7148     case L3_DEFIP_ALPM_IPV6_64_1m:
   7149         ent_num = ALPM_IPV6_64_BKT_COUNT_FLEX;
   7150         break;
   7151     /* coverity[dead_error_begin: FALSE] */
   7152     default:
   7153         break;
   7154     }
   7155 
   7156     /* TD3 doubles the bank count */
   7157     if (SOC_IS_TRIDENT3X(u)) {
   7158         ent_num <<= 1;
   7159     }
   7160 
   7161     /* Double-wide mode check */
   7162     if ((ALPM_CTRL(u).double_wide[v6])) {
   7163         ent_num <<= 1;
   7164     }
   7165 
   7166     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7167                 (BSL_META_U(u, "Start searching mem %s bucket [%d,%d](count %d) "
   7168                 "for Length %d\n"),
   7169                 SOC_MEM_NAME(u, mem), ALPM_PHY_BKT(u, *log_bkt),
   7170                 ALPM_SUB_BKT(u, *log_bkt), ent_num, sw_len));
   7171 
   7172     for (i = 0; i < ent_num; i++) {
   7173         uint32 bufp[SOC_MAX_MEM_FIELD_WORDS] = {0};
   7174         uint32 mask[2] = {0};
   7175         uint32 hkey[2] = {0};
   7176         uint32 skey[2] = {0};
   7177         int valid;
   7178 
   7179         rv = _soc_th_alpm_mem_index(u, mem, ALPM_PHY_BKT(u, *log_bkt),
   7180                                     i, bank_disable, &index);
   7181         if (rv == SOC_E_FULL) {
   7182             continue;
   7183         }
   7184 
   7185         SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY,
   7186                                                index, (void *)bufp));
   7187         valid = soc_mem_field32_get(u, mem, bufp, VALIDf);
   7188         hw_len = soc_mem_field32_get(u, mem, bufp, LENGTHf);
   7189 
   7190         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7191                     (BSL_META_U(u, "Bucket [%d,%d] index %6d: Valid %d, Length %d\n"),
   7192                     ALPM_PHY_BKT(u, *log_bkt), ALPM_SUB_BKT(u, *log_bkt),
   7193                     index, valid, hw_len));
   7194 
   7195         if (!valid || (hw_len > sw_len)) {
   7196             continue;
   7197         }
   7198 
   7199         /* Length in ALPM <= given length */
   7200         SHR_BITSET_RANGE(mask, (v6 ? 64 : 32) - hw_len, hw_len);
   7201         (void)soc_mem_field_get(u, mem, (uint32 *)bufp, KEYf, (uint32 *)hkey);
   7202         skey[1] = soc_mem_field32_get(u, lpm_mem, key_data, ip_addr_fld[1]);
   7203         skey[0] = soc_mem_field32_get(u, lpm_mem, key_data, ip_addr_fld[0]);
   7204 
   7205         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7206                     (BSL_META_U(u, "\tmask %08x %08x\n\t key %08x %08x\n"
   7207                     "\thost %08x %08x\n"),
   7208                     mask[1], mask[0], hkey[1], hkey[0], skey[1], skey[0]));
   7209 
   7210         for (j = v6 ? 1 : 0; j >= 0; j--) {
   7211             if ((skey[j] & mask[j]) != (hkey[j] & mask[j])) {
   7212                 break;
   7213             }
   7214         }
   7215 
   7216         /* Hardware key doesn't match to software key */
   7217         if (j >= 0) {
   7218             continue;
   7219         }
   7220 
   7221         /* Matched, store and keep searching,
   7222          * could be Longer prefix in following entries */
   7223         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7224                     (BSL_META_U(u, "Found a match in mem %s bucket [%d,%d], "
   7225                     "index %d\n"), SOC_MEM_NAME(u, mem),
   7226                     ALPM_PHY_BKT(u, *log_bkt), ALPM_SUB_BKT(u, *log_bkt),
   7227                     index));
   7228 
   7229         /* Keep longest matched route */
   7230         if (alpm_len == -1 || alpm_len < hw_len) {
   7231             alpm_len = hw_len;
   7232             alpm_index = index;
   7233             sal_memcpy(alpm_bufp, bufp, sizeof(bufp));
   7234         }
   7235     }
   7236 
   7237     /* Found */
   7238     if (alpm_len != -1) {
   7239         rv = _soc_th_alpm_lpm_ent_init(u, alpm_bufp, mem, v6, vrf_id, *log_bkt,
   7240                                        alpm_index, e, flex);
   7241         if (SOC_SUCCESS(rv)) {
   7242             *key_index = alpm_index;
   7243             if (bsl_check(bslLayerSoc, bslSourceAlpm, bslSeverityVerbose, u)) {
   7244                 LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7245                             (BSL_META_U(u, "Hit mem %s bucket [%d,%d], index %d\n"),
   7246                             SOC_MEM_NAME(u, mem), ALPM_PHY_BKT(u, *log_bkt),
   7247                             ALPM_SUB_BKT(u, *log_bkt), alpm_index));
   7248             }
   7249         }
   7250         return rv;
   7251     }
   7252 
   7253     /* Missed */
   7254     *key_index = soc_th_alpm_logical_idx(u, lpm_mem, (*tcam_index) >> 1, 1);
   7255     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7256                 (BSL_META_U(u,"Miss in mem %s bucket [%d,%d], use associate data "
   7257                 "in mem %s LOG index %d\n"), SOC_MEM_NAME(u, mem),
   7258                 ALPM_PHY_BKT(u, *log_bkt), ALPM_SUB_BKT(u, *log_bkt),
   7259                 SOC_MEM_NAME(u, lpm_mem), *key_index));
   7260 
   7261     /* Miss in bucket, use associate data */
   7262     SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY, *key_index,
   7263                                            (void *)e));
   7264     if ((!v6) && ((*tcam_index) & 1)) {
   7265         /* move entry to 0 half */
   7266         rv = soc_th_alpm_lpm_ip4entry1_to_0(u, e, e, PRESERVE_HIT);
   7267     }
   7268 
   7269     return SOC_E_NONE;
   7270 }
   7271 
   7272 /*
   7273  * soc_th_alpm_find_best_match
   7274  *
   7275  * It's an indenpendent routine, to simalute HW process for incoming packets.
   7276  * Considering possible mismatch between SW and HW, we need to go through
   7277  * hardware for lookup regardless of software state.
   7278  */
   7279 int
   7280 soc_th_alpm_find_best_match(int u,
   7281                             void *key_data,
   7282                             void *e,           /* return entry data if found */
   7283                             int *index_ptr,
   7284                             int do_urpf)
   7285 {
   7286     int rv = SOC_E_NONE;
   7287     int i, index_min, index_cnt;
   7288     defip_entry_t lpm_ent;
   7289     uint32 mem_mask[2];
   7290     uint32 mem_addr[2];
   7291     uint32 mask[2];
   7292     uint32 addr[2];
   7293     uint32 glb_hi, glb_rt;
   7294 
   7295     int vrf_id, vrf = 0;
   7296     int vld[2] = {0};
   7297     int tcam_index, log_bkt;
   7298     soc_mem_t lpm_mem = L3_DEFIPm;
   7299     int ent, v6, hw_v6, match = 0;
   7300     int flex_v6_64;
   7301 
   7302     soc_field_t glb_hi_fld[] = {
   7303         GLOBAL_HIGH0f,
   7304         GLOBAL_HIGH1f
   7305     };
   7306     soc_field_t glb_rt_fld[] = {
   7307         GLOBAL_ROUTE0f,
   7308         GLOBAL_ROUTE1f
   7309     };
   7310 
   7311     v6 = soc_mem_field32_get(u, lpm_mem, key_data, MODE0_f(u));
   7312     if (!SOC_URPF_STATUS_GET(u) && do_urpf) {
   7313         return SOC_E_PARAM;
   7314     }
   7315 
   7316     /* Since L3_DEFIP_* tables are not support for DMA,
   7317      * we do PIO search instead */
   7318     index_min = soc_mem_index_min(u, lpm_mem);
   7319     index_cnt = soc_mem_index_count(u, lpm_mem);
   7320     if (SOC_URPF_STATUS_GET(u)) {
   7321         index_cnt >>= 1;
   7322     }
   7323     /* in Parallel mode search from second half */
   7324     if (ALPM_CTRL(u).gp_zoned) {
   7325         index_cnt >>= 1;
   7326         index_min += index_cnt;
   7327     }
   7328 
   7329     if (do_urpf) {
   7330         index_min += soc_mem_index_count(u, lpm_mem) / 2;
   7331     }
   7332 
   7333     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7334                 (BSL_META_U(u, "Launch LPM searching from index %d count %d\n"),
   7335                 index_min, index_cnt));
   7336 
   7337     mask[0] = soc_mem_field32_get(u, lpm_mem, key_data, IP_ADDR_MASK0f);
   7338     mask[1] = soc_mem_field32_get(u, lpm_mem, key_data, IP_ADDR_MASK1f);
   7339     addr[0] = soc_mem_field32_get(u, lpm_mem, key_data, IP_ADDR0f);
   7340     addr[1] = soc_mem_field32_get(u, lpm_mem, key_data, IP_ADDR1f);
   7341 
   7342     /* Scanning for Global High routes */
   7343     for (i = index_min; i < index_min + index_cnt; i++) {
   7344         SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY,
   7345                             i, (void *)&lpm_ent));
   7346         vld[0] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, VALID0f);
   7347         vld[1] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, VALID1f);
   7348         if (vld[0] == 0 && vld[1] == 0) {
   7349             continue;
   7350         }
   7351 
   7352         hw_v6 = soc_mem_field32_get(u, lpm_mem, &lpm_ent, MODE0_f(u));
   7353         if (hw_v6 != v6) {
   7354             continue;
   7355         }
   7356 
   7357         for (ent = 0; ent < (v6 ? 1 : 2); ent++) {
   7358             if (vld[ent] == 0) {
   7359                 continue;
   7360             }
   7361             glb_hi = soc_mem_field32_get(u, lpm_mem, &lpm_ent, glb_hi_fld[ent]);
   7362             glb_rt = soc_mem_field32_get(u, lpm_mem, &lpm_ent, glb_rt_fld[ent]);
   7363 
   7364             flex_v6_64 = 0;
   7365             if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && v6) {
   7366                 uint32 entry_view, flex;
   7367                 entry_view = soc_mem_field32_get(u, lpm_mem, &lpm_ent, ENTRY_VIEW0f);
   7368                 flex = _soc_th_alpm_lpm_flex_get(u, v6, entry_view);
   7369                 if (flex) {
   7370                     if (soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR_MASK0f) == 0xFFFFFFFF &&
   7371                         soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR_MASK1f) == 0xFFFFFFFF) {
   7372                         flex_v6_64 = 1;
   7373                     }
   7374                 }
   7375             }
   7376 
   7377             /* No need to compare key if not Global High route,*/
   7378             if (!(ALPM_CTRL(u).alpm_mode != SOC_ALPM_MODE_TCAM_ALPM &&
   7379                   glb_hi && glb_rt) &&
   7380                 !(ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_TCAM_ALPM &&
   7381                   glb_rt) &&
   7382                 !flex_v6_64) {
   7383                 continue;
   7384             }
   7385 
   7386             LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7387                         (BSL_META_U(u, "Match a Global High route: ent %d\n"),
   7388                         ent));
   7389 
   7390             mem_mask[0] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR_MASK0f);
   7391             mem_mask[1] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR_MASK1f);
   7392             mem_addr[0] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR0f);
   7393             mem_addr[1] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR1f);
   7394 
   7395             LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7396                         (BSL_META_U(u, "\thmsk %08x %08x\n\thkey %08x %08x\n"
   7397                         "\tsmsk %08x %08x\n\tskey %08x %08x\n"),
   7398                         mem_mask[1], mem_mask[0], mem_addr[1], mem_addr[0],
   7399                         mask[1], mask[0], addr[1], addr[0]));
   7400 
   7401             /* match condition: mem mask equal to or shorten than match mask
   7402              *                  mem masked addrs are equal.
   7403              */
   7404             if (v6) {
   7405                 match = (mem_mask[1] <= mask[1] && mem_mask[0] <= mask[0] &&
   7406                         ((addr[0] & mem_mask[0]) == (mem_addr[0] & mem_mask[0])) &&
   7407                         ((addr[1] & mem_mask[1]) == (mem_addr[1] & mem_mask[1])));
   7408             } else {
   7409                 match = (mem_mask[ent] <= mask[0] &&
   7410                          ((addr[0] & mem_mask[ent]) == (mem_addr[ent] & mem_mask[ent])));
   7411             }
   7412             if (match) {
   7413                 /* Found, all Key matched */
   7414                 LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7415                             (BSL_META_U(u,"Hit Global High route in index = %d(%d)\n"),
   7416                             i, ent));
   7417                 sal_memcpy(e, &lpm_ent, sizeof(lpm_ent));
   7418                 if (!v6 && ent == 1) {
   7419                     /* ent == 1 indicate it's sencond half of the entry */
   7420                     rv = soc_th_alpm_lpm_ip4entry1_to_0(u, e, e, PRESERVE_HIT);
   7421                 }
   7422                 *index_ptr = i;
   7423                 return rv;
   7424             }
   7425         }
   7426     }
   7427 
   7428     /* Global High lookup miss, use AUX to search Global Low and VRF route */
   7429     LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7430                 (BSL_META_U(u,"Global high lookup miss, use AUX engine to "
   7431                 "search for VRF and Global Low routes\n")));
   7432 
   7433     /* Fill in AUX Scratch and perform PREFIX Operation */
   7434     SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   7435     rv = _soc_th_alpm_find_best_match(u, key_data, e, vrf_id, &tcam_index,
   7436                                       &log_bkt, index_ptr, do_urpf);
   7437     if (rv == SOC_E_NOT_FOUND) {
   7438         vrf = SOC_L3_VRF_GLOBAL;
   7439         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7440                     (BSL_META_U(u,"Not found in VRF region, trying Global "
   7441                     "region\n")));
   7442         rv = _soc_th_alpm_find_best_match(u, key_data, e, vrf_id, &tcam_index,
   7443                                           &log_bkt, index_ptr, do_urpf);
   7444     }
   7445 
   7446     if (SOC_SUCCESS(rv)) {
   7447         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7448                     (BSL_META_U(u,"Hit in %s region in TCAM index %d, "
   7449                     "bucket [%d,%d]\n"),
   7450                     vrf == SOC_L3_VRF_GLOBAL ? "Global Low" : "VRF",
   7451                     tcam_index, ALPM_PHY_BKT(u, log_bkt),
   7452                     ALPM_SUB_BKT(u, log_bkt)));
   7453     } else {
   7454         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7455                     (BSL_META_U(u,"Search miss for given address\n")));
   7456     }
   7457 
   7458     return(rv);
   7459 }
   7460 
   7461 
   7462 /*
   7463  * soc_th_alpm_delete
   7464  */
   7465 int
   7466 soc_th_alpm_delete(int u, void *key_data, int key_idx, int pivot_info)
   7467 {
   7468     int       log_bkt, phy_bkt;
   7469     int       vrf_id, vrf;
   7470     int       ipv6;
   7471     int       rv = SOC_E_NONE;
   7472     int       ipmc_route = 0;
   7473     int       flex_v6_64 = 0;
   7474 
   7475     ipv6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0_f(u));
   7476 
   7477     if (soc_feature(u, soc_feature_ipmc_defip)) {
   7478         ipmc_route = 0;
   7479         if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE0f)) {
   7480             ipmc_route = soc_mem_field32_get(u, L3_DEFIPm, key_data, MULTICAST_ROUTE0f);
   7481         } else if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE0f)) {
   7482             if (soc_mem_field32_get(u, L3_DEFIPm, key_data, DATA_TYPE0f) == 2) {
   7483                 ipmc_route = 1;
   7484             } else {
   7485                 ipmc_route = 0;
   7486             }
   7487         }
   7488     }
   7489 
   7490     /* If the entry is override, then insert into TCAM directly */
   7491     SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf));
   7492     if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && ipv6 &&
   7493         VRF_FLEX_IS_SET(u, vrf_id, vrf, ipv6, 0)) {
   7494         if (soc_mem_field32_get(u, L3_DEFIPm, key_data, IP_ADDR_MASK0f) == 0xFFFFFFFF &&
   7495             soc_mem_field32_get(u, L3_DEFIPm, key_data, IP_ADDR_MASK1f) == 0xFFFFFFFF) {
   7496             flex_v6_64 = 1;
   7497         }
   7498     }
   7499 
   7500     /* For VRF_OVERRIDE (Global High) entries, software needs to maintain the
   7501      * index */
   7502     /* Prefix resides in TCAM directly */
   7503     if (ALPM_PREFIX_IN_TCAM(u, vrf_id) || (ipmc_route) || (flex_v6_64)) {
   7504         /* search in the hash table */
   7505         rv = soc_th_alpm_lpm_delete(u, key_data);
   7506         if (SOC_SUCCESS(rv)) {
   7507             VRF_TRIE_ROUTES_DEC(u, vrf_id, vrf, ipv6);
   7508         }
   7509         return(rv);
   7510     } else { /* non override entries, go to into ALPM memory */
   7511         int tcam_index;
   7512         if (!VRF_TRIE_INIT_COMPLETED(u, vrf, ipv6)) {
   7513             LOG_VERBOSE(BSL_LS_SOC_ALPM,
   7514                         (BSL_META_U(u,
   7515                                     "soc_alpm_delete:VRF %d/%d is not initialized\n"),
   7516                          vrf, ipv6));
   7517             return SOC_E_NONE;
   7518         }
   7519         if (key_idx == -1) {
   7520             /* internally 0 is invalid bucket index */
   7521             key_idx = 0;
   7522         }
   7523         phy_bkt = SOC_TH_ALPM_AIDX_TO_PHY_BKT(u, key_idx);
   7524         /* In double wide mode, the key_idx could come from second
   7525          * bucket, need to adjust to first bucket */
   7526         if (ALPM_CTRL(u).double_wide[ipv6] && (phy_bkt & 0x1)) {
   7527             phy_bkt &= ~0x1;
   7528         }
   7529 
   7530         log_bkt = ALPM_LOG_BKT(phy_bkt, SOC_TH_ALPM_AIDX_TO_SUB_BKT(u, key_idx));
   7531         tcam_index = pivot_info & SOC_ALPM_TCAM_INDEX_MASK;
   7532         rv = _soc_th_alpm_delete(u, ipv6, key_data, log_bkt, tcam_index, key_idx);
   7533     }
   7534     return(rv);
   7535 }
   7536 
   7537 
   7538 /* Initialize shared bucket management */
   7539 static int
   7540 soc_th_alpm_shared_mem_init(int u)
   7541 {
   7542     int defip_table_size;
   7543     int v4_bkt_cnt, v6_bkt_cnt;
   7544     int rv;
   7545 
   7546     /* Get Table Size */
   7547     defip_table_size = soc_mem_index_count(u, L3_DEFIPm)
   7548                             + soc_mem_index_count(u, L3_DEFIP_PAIR_128m) * 2;
   7549     SOC_TH_ALPM_BUCKET_COUNT(u) = ALPM_CTRL(u).num_bkts;
   7550     SOC_TH_ALPM_V6_RESV_BUCKET_COUNT(u) = ALPM_CTRL(u)._alpm_128b_bkt_rsvd_cnt;
   7551 
   7552     if (SOC_URPF_STATUS_GET(u)) {
   7553         /* remaining half buckets are the src buckets */
   7554         defip_table_size >>= 1;
   7555         SOC_TH_ALPM_BUCKET_COUNT(u) >>= 1;
   7556         SOC_TH_ALPM_V6_RESV_BUCKET_COUNT(u) >>= 1;
   7557     }
   7558 
   7559     /* number bytes to manage the max buckets */
   7560     SOC_TH_ALPM_BUCKET_BMAP_SIZE(u) = SHR_BITALLOCSIZE(SOC_TH_ALPM_BUCKET_COUNT(u));
   7561 
   7562     SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4) =
   7563              sal_alloc(SOC_TH_ALPM_BUCKET_BMAP_SIZE(u),
   7564                        "alpm_vrf_shared_bucket_bitmap");
   7565     if (SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4) == NULL) {
   7566         return SOC_E_MEMORY;
   7567     }
   7568 
   7569     /* Mark all buckets as free */
   7570     sal_memset(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4), 0,
   7571                SOC_TH_ALPM_BUCKET_BMAP_SIZE(u));
   7572 
   7573     if (ALPM_CTRL(u).double_wide[ALPM_IPV6]) {
   7574         defip_table_size = 2;
   7575     } else {
   7576         defip_table_size = 1;
   7577     }
   7578     /* Bucket 0 is reserved. Just assign it */
   7579     SHR_BITSET_RANGE(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4),
   7580                      0, defip_table_size);
   7581     v6_bkt_cnt = SOC_TH_ALPM_V6_RESV_BUCKET_COUNT(u);
   7582     v4_bkt_cnt = SOC_TH_ALPM_BUCKET_COUNT(u) - v6_bkt_cnt;
   7583     if (ALPM_CTRL(u)._alpm_128b_bkt_rsvd) {
   7584         SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6) =
   7585                  sal_alloc(SOC_TH_ALPM_BUCKET_BMAP_SIZE(u),
   7586                            "alpm_vrf_shared_bucket_bitmap");
   7587         if (SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6) == NULL) {
   7588             rv = SOC_E_MEMORY;
   7589             goto error;
   7590         }
   7591         /* Mark all buckets as free */
   7592         sal_memset(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6), 0,
   7593                    SOC_TH_ALPM_BUCKET_BMAP_SIZE(u));
   7594 
   7595         SHR_BITSET_RANGE(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4),
   7596                          v4_bkt_cnt, v6_bkt_cnt);
   7597 
   7598         SHR_BITSET_RANGE(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6),
   7599                          0, v4_bkt_cnt);
   7600     } else {
   7601         SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6) =
   7602             SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4);
   7603     }
   7604 
   7605     /* If Parallel uRPF mode, we share bucket between Global low and VRF */
   7606     if (soc_property_get(u, "l3_alpm_vrf_share_bucket", 0) &&
   7607         ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_PARALLEL &&
   7608         SOC_URPF_STATUS_GET(u)) {
   7609         SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4) =
   7610              sal_alloc(SOC_TH_ALPM_BUCKET_BMAP_SIZE(u), "alpm_glb_shr_bkt_bmap");
   7611         if (SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4) == NULL) {
   7612             rv = SOC_E_MEMORY;
   7613             goto error;
   7614         }
   7615         /* Mark all buckets as free */
   7616         sal_memset(SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4), 0,
   7617                    SOC_TH_ALPM_BUCKET_BMAP_SIZE(u));
   7618         /* Bucket 0 is reserved. Just assign it */
   7619         SHR_BITSET_RANGE(SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4),
   7620                          0, defip_table_size);
   7621         if (ALPM_CTRL(u)._alpm_128b_bkt_rsvd) {
   7622             SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6) =
   7623                      sal_alloc(SOC_TH_ALPM_BUCKET_BMAP_SIZE(u),
   7624                                "alpm_vrf_shared_bucket_bitmap");
   7625             if (SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6) == NULL) {
   7626                 rv = SOC_E_MEMORY;
   7627                 goto error;
   7628             }
   7629             /* Mark all buckets as free */
   7630             sal_memset(SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6), 0,
   7631                        SOC_TH_ALPM_BUCKET_BMAP_SIZE(u));
   7632 
   7633             SHR_BITSET_RANGE(SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4),
   7634                              v4_bkt_cnt, v6_bkt_cnt);
   7635 
   7636             SHR_BITSET_RANGE(SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6),
   7637                              0, v4_bkt_cnt);
   7638         } else {
   7639             SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6) =
   7640                 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4);
   7641         }
   7642     } else {
   7643         SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4) =
   7644             SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4);
   7645         SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6) =
   7646             SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6);
   7647     }
   7648 
   7649     return SOC_E_NONE;
   7650 error:
   7651     if (SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4)) {
   7652         if (ALPM_CTRL(u)._alpm_128b_bkt_rsvd &&
   7653             SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6) !=
   7654             SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4)) {
   7655             sal_free(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6));
   7656         }
   7657         SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6) = NULL;
   7658 
   7659         sal_free(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4));
   7660         SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4) = NULL;
   7661     }
   7662 
   7663     if (SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4)) {
   7664         if (ALPM_CTRL(u)._alpm_128b_bkt_rsvd &&
   7665             SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6) !=
   7666             SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4)) {
   7667             sal_free(SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6));
   7668         }
   7669         SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6) = NULL;
   7670         sal_free(SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4));
   7671         SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4) = NULL;
   7672     }
   7673 
   7674     return rv;
   7675 }
   7676 
   7677 
   7678 /* Get the free bucket to allocate to the PIVOT */
   7679 int
   7680 soc_th_alpm_bucket_assign(int u, int vrf, int v6, int *log_bkt)
   7681 {
   7682     int i, step_count = 1, used = 0;
   7683     uint8 ipv = !!v6;
   7684     SHR_BITDCL *bkt_bmap = SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv);
   7685     if (vrf == SOC_VRF_MAX(u) + 1) {
   7686         bkt_bmap = SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv);
   7687     }
   7688 
   7689     /*
   7690      * in combined search mode, with urpf disabled, need to allocate even and
   7691      * odd bucket pointers
   7692      */
   7693     if (ALPM_CTRL(u).double_wide[v6]) {
   7694         step_count = 2;
   7695     }
   7696 
   7697     for (i = 0; i < SOC_TH_ALPM_BUCKET_COUNT(u); i += step_count) {
   7698         SHR_BITTEST_RANGE(bkt_bmap, i, step_count, used);
   7699         if (0 == used) {
   7700             break;
   7701         }
   7702     }
   7703     if (i == SOC_TH_ALPM_BUCKET_COUNT(u)) {
   7704         return SOC_E_FULL;
   7705     }
   7706 
   7707     SHR_BITSET_RANGE(bkt_bmap, i, step_count);
   7708     *log_bkt = ALPM_LOG_BKT(i, 0);
   7709     SOC_TH_ALPM_BUCKET_NEXT_FREE(u) = i;
   7710     return SOC_E_NONE;
   7711 }
   7712 
   7713 
   7714 /* Get the free bucket to allocate to the PIVOT */
   7715 int
   7716 soc_th_alpm_assign(int u, int vrf, soc_mem_t mem,
   7717                    int *log_bkt, int *shuffled, int *free_count)
   7718 {
   7719     int rv;
   7720     int phy_bkt, step_count = 1;
   7721     int v6 = SOC_ALPM_MEM_V6(mem);
   7722     uint8 ipv = !!v6;
   7723 
   7724     rv = soc_th_alpm_bucket_assign(u, vrf, v6, log_bkt);
   7725 
   7726     if (SOC_SUCCESS(rv)) {
   7727         int max_count = _soc_th_alpm_bkt_entry_cnt(u, mem);
   7728         if (_soc_th_alpm_lpm_free_entries(u, mem, vrf) == 0) {
   7729             rv = _soc_th_alpm_merge(u, mem, vrf, max_count, &phy_bkt, shuffled, &step_count);
   7730             if (rv == SOC_E_FULL && !v6) {
   7731                 rv = SOC_E_NONE;
   7732             } else if (SOC_FAILURE(rv)){
   7733                 (void) soc_th_alpm_bucket_release(u, *log_bkt, vrf, v6);
   7734             }
   7735         }
   7736         if (free_count) {
   7737             *free_count = max_count;
   7738         }
   7739     } else if (rv == SOC_E_FULL) {
   7740         rv =  _soc_th_alpm_assign(u, mem, vrf, log_bkt, shuffled, free_count);
   7741         /* Reclaim the physical bucket in case it has been freed */
   7742         if (SOC_SUCCESS(rv)) {
   7743             SHR_BITDCL *bkt_bmap = SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv);
   7744             if (vrf == SOC_VRF_MAX(u) + 1) {
   7745                 bkt_bmap = SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv);
   7746             }
   7747             if (ALPM_CTRL(u).double_wide[v6]) {
   7748                 step_count = 2;
   7749             }
   7750             phy_bkt = ALPM_PHY_BKT(u, *log_bkt);
   7751             SHR_BITSET_RANGE(bkt_bmap, phy_bkt, step_count);
   7752             SOC_TH_ALPM_BUCKET_NEXT_FREE(u) = phy_bkt;
   7753         }
   7754     }
   7755 
   7756     return rv;
   7757 }
   7758 
   7759 
   7760 /* Free a logical bucket (bucket ID), if bucket becomes empty, then
   7761  * free the physical bucket */
   7762 int
   7763 soc_th_alpm_bucket_release(int u, int log_bkt, int vrf, int v6)
   7764 {
   7765     int step_count = 1, used = 0;
   7766     int key_index;
   7767     int phy_bkt, sub_bkt;
   7768     uint8 ipv = !!v6;
   7769     SHR_BITDCL *bkt_bmap = SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv);
   7770 
   7771     phy_bkt = ALPM_PHY_BKT(u, log_bkt);
   7772     sub_bkt = ALPM_SUB_BKT(u, log_bkt);
   7773 
   7774     SOC_ALPM_BU_SUB_BKT_CLR(u, phy_bkt, sub_bkt);
   7775     SOC_ALPM_BU_PIVOT_IDX(u, phy_bkt, sub_bkt) = 0;
   7776 
   7777     if (SOC_ALPM_BU_COUNT(u, phy_bkt)) {
   7778         return SOC_E_NONE;
   7779     }
   7780 
   7781     /* Check if the bucket pointer is valid */
   7782     if ((phy_bkt < 1) ||
   7783         (phy_bkt > SOC_TH_ALPM_BUCKET_MAX_INDEX(u))) {
   7784         return SOC_E_PARAM;
   7785     }
   7786 
   7787     if (vrf == SOC_VRF_MAX(u) + 1) {
   7788         bkt_bmap = SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv);
   7789     }
   7790 
   7791     /* in combined search mode, with urpf disabled, need to free even and odd
   7792      * bucket pointers
   7793      */
   7794     if (ALPM_CTRL(u).double_wide[v6]) {
   7795         step_count = 2;
   7796     }
   7797     SHR_BITTEST_RANGE(bkt_bmap, phy_bkt, step_count, used);
   7798     if (!used) {
   7799         return SOC_E_PARAM;
   7800     }
   7801     SHR_BITCLR_RANGE(bkt_bmap, phy_bkt, step_count);
   7802 
   7803     key_index = SOC_TH_ALPM_AIDX(u, phy_bkt, 0, 0, 0);
   7804     soc_alpm_cmn_bkt_view_set(u, key_index, INVALIDm);
   7805     if (SOC_URPF_STATUS_GET(u)) {
   7806         soc_alpm_cmn_bkt_view_set(u, _soc_th_alpm_rpf_entry(u, key_index),
   7807                                   INVALIDm);
   7808     }
   7809     if (step_count == 2) {
   7810         key_index = SOC_TH_ALPM_AIDX(u, phy_bkt + 1, 0, 0, 0);
   7811         soc_alpm_cmn_bkt_view_set(u, key_index, INVALIDm);
   7812         if (SOC_URPF_STATUS_GET(u)) {
   7813             soc_alpm_cmn_bkt_view_set(u, _soc_th_alpm_rpf_entry(u, key_index),
   7814                                       INVALIDm);
   7815         }
   7816     }
   7817 
   7818     return SOC_E_NONE;
   7819 }
   7820 
   7821 int
   7822 soc_th_alpm_bucket_is_assigned(int u, int log_bkt, int vrf, int v6, int *used)
   7823 {
   7824     int step_count = 1;
   7825     uint8 ipv = !!v6;
   7826     SHR_BITDCL *bkt_bmap = SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv);
   7827     int phy_bkt, sub_bkt;
   7828 
   7829     phy_bkt = ALPM_PHY_BKT(u, log_bkt);
   7830     sub_bkt = ALPM_SUB_BKT(u, log_bkt);
   7831 
   7832     if (vrf == SOC_VRF_MAX(u) + 1) {
   7833         bkt_bmap = SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv);
   7834     }
   7835 
   7836     /* Check if the bucket pointer is valid */
   7837     if ((phy_bkt < 1) || (phy_bkt > SOC_TH_ALPM_BUCKET_MAX_INDEX(u))) {
   7838         return SOC_E_PARAM;
   7839     }
   7840 
   7841     /* in combined search mode, with urpf disabled, need to allocate even and
   7842      * odd bucket pointers */
   7843     if (ALPM_CTRL(u).double_wide[v6]) {
   7844         step_count = 2;
   7845     }
   7846 
   7847     SHR_BITTEST_RANGE(bkt_bmap, phy_bkt, step_count, *used);
   7848     *used = *used && SOC_ALPM_BU_SUB_BKT_IS_SET(u, phy_bkt, sub_bkt);
   7849 
   7850     return SOC_E_NONE;
   7851 }
   7852 
   7853 /**********************************************
   7854 * TCAM Management functions *
   7855  */
   7856 
   7857 /*
   7858  * TCAM based PIVOT implementation. Each table entry can hold two IPV4 PIVOTs or
   7859  * one IPV6 PIVOT entry. VRF independent routes placed at the beginning or
   7860  * at the end of table based on application provided entry vrf id
   7861  * (SOC_L3_VRF_OVERRIDE/SOC_L3_VRF_GLOBAL).
   7862  *
   7863  *              ALPM_MAX_PFX_INDEX
   7864  * lpm_prefix_index[98].begin ---> ===============================
   7865  *                                 ==                           ==
   7866  *                                 ==    0                      ==
   7867  * lpm_prefix_index[98].end   ---> ===============================
   7868  *
   7869  * lpm_prefix_index[97].begin ---> ===============================
   7870  *                                 ==                           ==
   7871  *                                 ==    IPV6  Prefix Len = 64  ==
   7872  * lpm_prefix_index[97].end   ---> ===============================
   7873  *
   7874  *
   7875  *
   7876  * lpm_prefix_index[x].begin --->  ===============================
   7877  *                                 ==                           ==
   7878  *                                 ==                           ==
   7879  * lpm_prefix_index[x].end   --->  ===============================
   7880  *
   7881  *
   7882  *              ALPM_IPV6_PFX_ZERO
   7883  * lpm_prefix_index[33].begin ---> ===============================
   7884  *                                 ==                           ==
   7885  *                                 ==    IPV6  Prefix Len = 0   ==
   7886  * lpm_prefix_index[33].end   ---> ===============================
   7887  *
   7888  *
   7889  * lpm_prefix_index[32].begin ---> ===============================
   7890  *                                 ==                           ==
   7891  *                                 ==    IPV4  Prefix Len = 32  ==
   7892  * lpm_prefix_index[32].end   ---> ===============================
   7893  *
   7894  *
   7895  *
   7896  * lpm_prefix_index[0].begin --->  ===============================
   7897  *                                 ==                           ==
   7898  *                                 ==    IPV4  Prefix Len = 0   ==
   7899  * lpm_prefix_index[0].end   --->  ===============================
   7900  */
   7901 
   7902 
   7903 /*
   7904  *      Extract key data from an entry at the given index.
   7905  */
   7906 static
   7907 void _soc_th_alpm_lpm_hash_entry_get(int u, void *e,
   7908                                 int index, _soc_th_alpm_lpm_hash_entry_t r_entry,
   7909                                 int *v)
   7910 {
   7911     if (index & TD2_ALPM_HASH_IPV6_MASK) {
   7912         SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, e, r_entry);
   7913         if (v) {
   7914             *v =  SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f) &&
   7915                   SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f);
   7916         }
   7917     } else {
   7918         if (index & 0x1) {
   7919             SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, e, r_entry);
   7920             if (v) {
   7921                 *v =  SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f);
   7922             }
   7923         } else {
   7924             SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, e, r_entry);
   7925             if (v) {
   7926                 *v =  SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f);
   7927             }
   7928         }
   7929     }
   7930 }
   7931 
   7932 /*
   7933  * Function:
   7934  *      _soc_th_alpm_lpm_hash_compare_key
   7935  * Purpose:
   7936  *      Comparison function for AVL shadow table operations.
   7937  */
   7938 static
   7939 int _soc_th_alpm_lpm_hash_compare_key(_soc_th_alpm_lpm_hash_entry_t key1,
   7940                                  _soc_th_alpm_lpm_hash_entry_t key2)
   7941 {
   7942     int idx;
   7943 
   7944     for (idx = 0; idx < 5; idx++) {
   7945         if (key1[idx] < key2[idx]) {
   7946             return -1;
   7947         }
   7948         if (key1[idx] > key2[idx]) {
   7949             return  1;
   7950         }
   7951     }
   7952     return (0);
   7953 }
   7954 
   7955 #ifdef FB_LPM_DEBUG
   7956 #define H_INDEX_MATCH(str, tab_index, match_index)      \
   7957     LOG_ERROR(BSL_LS_SOC_ALPM, \
   7958               (BSL_META("%s index: H %d A %d\n"),              \
   7959                str, (int)tab_index, match_index))
   7960 #else
   7961 #define H_INDEX_MATCH(str, tab_index, match_index)
   7962 #endif
   7963 
   7964 #define LPM_NO_MATCH_INDEX 0x4000
   7965 #define LPM_HASH_INSERT(u, entry_data, tab_index, rvt_index0, rvt_index1)   \
   7966     soc_th_alpm_lpm_hash_insert(u, entry_data, tab_index, LPM_NO_MATCH_INDEX, 0,\
   7967                                 rvt_index0, rvt_index1)
   7968 
   7969 #define LPM_HASH_REVERT(u, entry_data, tab_index, rvt_index0, rvt_index1)   \
   7970     soc_th_alpm_lpm_hash_revert(u, entry_data, tab_index, \
   7971                                 rvt_index0, rvt_index1)
   7972 
   7973 #define LPM_HASH_DELETE(u, key_data, tab_index)         \
   7974     soc_th_alpm_lpm_hash_delete(u, key_data, tab_index)
   7975 
   7976 #define LPM_HASH_LOOKUP(u, key_data, pfx, tab_index)    \
   7977     soc_th_alpm_lpm_hash_lookup(u, key_data, pfx, tab_index)
   7978 
   7979 #define LPM_HASH_VERIFY(u, key_data, tab_index)    \
   7980     soc_th_alpm_lpm_hash_verify(u, key_data, tab_index)
   7981 
   7982 #define INDEX_DELETE(hash, hash_idx, del_idx)                   \
   7983     hash->table[hash_idx] =                                     \
   7984         hash->link_table[del_idx & TD2_ALPM_HASH_INDEX_MASK];     \
   7985     hash->link_table[del_idx & TD2_ALPM_HASH_INDEX_MASK] =        \
   7986         TD2_ALPM_HASH_INDEX_NULL
   7987 
   7988 #define INDEX_DELETE_LINK(hash, prev_idx, del_idx)              \
   7989     hash->link_table[prev_idx & TD2_ALPM_HASH_INDEX_MASK] =       \
   7990         hash->link_table[del_idx & TD2_ALPM_HASH_INDEX_MASK];     \
   7991     hash->link_table[del_idx & TD2_ALPM_HASH_INDEX_MASK] =        \
   7992         TD2_ALPM_HASH_INDEX_NULL
   7993 
   7994 
   7995 static void soc_th_alpm_lpm_hash_insert(int u, void *entry_data, uint32 tab_index,
   7996                                      uint32 old_index, int pfx,
   7997                                      uint32 *rvt_index0, uint32 *rvt_index1)
   7998 {
   7999     _soc_th_alpm_lpm_hash_entry_t    key_hash;
   8000 
   8001     if (soc_mem_field32_get(u, L3_DEFIPm, entry_data, MODE0_f(u))) {
   8002         /* IPV6 entry */
   8003         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID1f) &&
   8004             SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID0f)) {
   8005             SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, key_hash);
   8006             _soc_th_alpm_lpm_hash_insert(
   8007                         SOC_ALPM_LPM_STATE_HASH(u),
   8008                         _soc_th_alpm_lpm_hash_compare_key,
   8009                         key_hash,
   8010                         pfx,
   8011                         old_index,
   8012                         ((uint16)tab_index << 1) | TD2_ALPM_HASH_IPV6_MASK,
   8013                         rvt_index0);
   8014         }
   8015     } else {
   8016         /* IPV4 entry */
   8017         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID0f)) {
   8018             SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, key_hash);
   8019             _soc_th_alpm_lpm_hash_insert(SOC_ALPM_LPM_STATE_HASH(u),
   8020                                     _soc_th_alpm_lpm_hash_compare_key,
   8021                                     key_hash,
   8022                                     pfx,
   8023                                     old_index,
   8024                                     ((uint16)tab_index << 1),
   8025                                     rvt_index0);
   8026         }
   8027         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID1f)) {
   8028             SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, key_hash);
   8029             _soc_th_alpm_lpm_hash_insert(SOC_ALPM_LPM_STATE_HASH(u),
   8030                                     _soc_th_alpm_lpm_hash_compare_key,
   8031                                     key_hash,
   8032                                     pfx,
   8033                                     old_index,
   8034                                     (((uint16)tab_index << 1) + 1),
   8035                                     rvt_index1);
   8036         }
   8037     }
   8038 }
   8039 
   8040 
   8041 static void soc_th_alpm_lpm_hash_revert(int u, void *entry_data, uint32 tab_index,
   8042                                      uint32 rvt_index0, uint32 rvt_index1)
   8043 {
   8044     _soc_th_alpm_lpm_hash_entry_t    key_hash;
   8045 
   8046     if (soc_mem_field32_get(u, L3_DEFIPm, entry_data, MODE0_f(u))) {
   8047         /* IPV6 entry */
   8048         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID1f) &&
   8049             SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID0f)) {
   8050             SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, key_hash);
   8051             _soc_th_alpm_lpm_hash_revert(
   8052                         SOC_ALPM_LPM_STATE_HASH(u),
   8053                         _soc_th_alpm_lpm_hash_compare_key,
   8054                         key_hash,
   8055                         ((uint16)tab_index << 1) | TD2_ALPM_HASH_IPV6_MASK,
   8056                         rvt_index0);
   8057         }
   8058     } else {
   8059         /* IPV4 entry */
   8060         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID0f)) {
   8061             SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, key_hash);
   8062             _soc_th_alpm_lpm_hash_revert(SOC_ALPM_LPM_STATE_HASH(u),
   8063                                     _soc_th_alpm_lpm_hash_compare_key,
   8064                                     key_hash,
   8065                                     ((uint16)tab_index << 1),
   8066                                     rvt_index0);
   8067         }
   8068         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID1f)) {
   8069             SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, key_hash);
   8070             _soc_th_alpm_lpm_hash_revert(SOC_ALPM_LPM_STATE_HASH(u),
   8071                                     _soc_th_alpm_lpm_hash_compare_key,
   8072                                     key_hash,
   8073                                     (((uint16)tab_index << 1) + 1),
   8074                                     rvt_index1);
   8075         }
   8076     }
   8077 }
   8078 
   8079 
   8080 static void soc_th_alpm_lpm_hash_delete(int u, void *key_data, uint32 tab_index)
   8081 {
   8082     _soc_th_alpm_lpm_hash_entry_t    key_hash;
   8083     int                         pfx = -1;
   8084     int                         rv;
   8085     uint16                      index;
   8086 
   8087     if (soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0_f(u))) {
   8088         SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, key_data, key_hash);
   8089         index = (tab_index << 1) | TD2_ALPM_HASH_IPV6_MASK;
   8090     } else {
   8091         SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, key_data, key_hash);
   8092         index = tab_index;
   8093     }
   8094 
   8095     rv = _soc_th_alpm_lpm_hash_delete(SOC_ALPM_LPM_STATE_HASH(u),
   8096                                  _soc_th_alpm_lpm_hash_compare_key,
   8097                                  key_hash, pfx, index);
   8098     if (SOC_FAILURE(rv)) {
   8099         LOG_ERROR(BSL_LS_SOC_ALPM,
   8100                   (BSL_META_U(u,
   8101                               "\ndel  index: H %d error %d\n"), index, rv));
   8102     }
   8103 }
   8104 
   8105 static int soc_th_alpm_lpm_hash_lookup(int u, void *key_data, int pfx, int *key_index)
   8106 {
   8107     _soc_th_alpm_lpm_hash_entry_t    key_hash;
   8108     int                         is_ipv6;
   8109     int                         rv;
   8110     uint16                      index = TD2_ALPM_HASH_INDEX_NULL;
   8111 
   8112     is_ipv6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0_f(u));
   8113     if (is_ipv6) {
   8114         SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, key_data, key_hash);
   8115     } else {
   8116         SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, key_data, key_hash);
   8117     }
   8118 
   8119     rv = _soc_th_alpm_lpm_hash_lookup(SOC_ALPM_LPM_STATE_HASH(u),
   8120                                  _soc_th_alpm_lpm_hash_compare_key,
   8121                                  key_hash, pfx, &index);
   8122     if (SOC_FAILURE(rv)) {
   8123         *key_index = 0xFFFFFFFF;
   8124         return(rv);
   8125     }
   8126 
   8127     *key_index = index;
   8128 
   8129     return(SOC_E_NONE);
   8130 }
   8131 
   8132 static int soc_th_alpm_lpm_hash_verify(int u, void *key_data, uint32 tab_index)
   8133 {
   8134     _soc_th_alpm_lpm_hash_entry_t    key_hash;
   8135     int                         pfx = -1;
   8136     int                         rv;
   8137     uint16                      index;
   8138 
   8139     if (soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0_f(u))) {
   8140         SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, key_data, key_hash);
   8141         index = (tab_index << 1) | TD2_ALPM_HASH_IPV6_MASK;
   8142     } else {
   8143         SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, key_data, key_hash);
   8144         index = tab_index;
   8145     }
   8146 
   8147     rv = _soc_th_alpm_lpm_hash_verify(SOC_ALPM_LPM_STATE_HASH(u),
   8148                                  _soc_th_alpm_lpm_hash_compare_key,
   8149                                  key_hash, pfx, index);
   8150     if (SOC_FAILURE(rv)) {
   8151         LOG_ERROR(BSL_LS_SOC_ALPM,
   8152                   (BSL_META_U(u,
   8153                               "\nveri index: H %d error %d\n"), index, rv));
   8154     }
   8155     return rv;
   8156 }
   8157 /*
   8158  * Function:
   8159  *      _soc_th_alpm_lpm_hash_compute
   8160  * Purpose:
   8161  *      Compute CRC hash for key data.
   8162  * Parameters:
   8163  *      data - Key data
   8164  *      data_nbits - Number of data bits
   8165  * Returns:
   8166  *      Computed 16 bit hash
   8167  */
   8168 static
   8169 uint16 _soc_th_alpm_lpm_hash_compute(uint8 *data, int data_nbits)
   8170 {
   8171     return (_shr_crc16b(0, data, data_nbits));
   8172 }
   8173 
   8174 /*
   8175  * Function:
   8176  *      _soc_th_alpm_lpm_hash_create
   8177  * Purpose:
   8178  *      Create an empty hash table
   8179  * Parameters:
   8180  *      unit  - Device unit
   8181  *      entry_count - Limit for number of entries in table
   8182  *      index_count - Hash index max + 1. (index_count <= count)
   8183  *      fb_lpm_hash_ptr - Return pointer (handle) to new Hash Table
   8184  * Returns:
   8185  *      SOC_E_NONE       Success
   8186  *      SOC_E_MEMORY     Out of memory (system allocator)
   8187  */
   8188 
   8189 static
   8190 int _soc_th_alpm_lpm_hash_create(int unit,
   8191                             int entry_count,
   8192                             int index_count,
   8193                             _soc_th_alpm_lpm_hash_t **fb_lpm_hash_ptr)
   8194 {
   8195     _soc_th_alpm_lpm_hash_t  *hash;
   8196     int                 index;
   8197 
   8198     if (index_count > entry_count) {
   8199         return SOC_E_MEMORY;
   8200     }
   8201     hash = sal_alloc(sizeof (_soc_th_alpm_lpm_hash_t), "lpm_hash");
   8202     if (hash == NULL) {
   8203         return SOC_E_MEMORY;
   8204     }
   8205 
   8206     sal_memset(hash, 0, sizeof (*hash));
   8207 
   8208     hash->unit = unit;
   8209     hash->entry_count = entry_count;
   8210     hash->index_count = index_count;
   8211 
   8212     /*
   8213      * Pre-allocate the hash table storage.
   8214      */
   8215     hash->table = sal_alloc(hash->index_count * sizeof(*(hash->table)),
   8216                             "hash_table");
   8217 
   8218     if (hash->table == NULL) {
   8219         sal_free(hash);
   8220         return SOC_E_MEMORY;
   8221     }
   8222     /*
   8223      * In case where all the entries should hash into the same bucket
   8224      * this will prevent the hash table overflow
   8225      */
   8226     hash->link_table = sal_alloc(
   8227                             hash->entry_count * sizeof(*(hash->link_table)),
   8228                             "link_table");
   8229     if (hash->link_table == NULL) {
   8230         sal_free(hash->table);
   8231         sal_free(hash);
   8232         return SOC_E_MEMORY;
   8233     }
   8234 
   8235     /*
   8236      * Set the entries in the hash table to TD2_ALPM_HASH_INDEX_NULL
   8237      * Link the entries beyond hash->index_max for handling collisions
   8238      */
   8239     for(index = 0; index < hash->index_count; index++) {
   8240         hash->table[index] = TD2_ALPM_HASH_INDEX_NULL;
   8241     }
   8242     for(index = 0; index < hash->entry_count; index++) {
   8243         hash->link_table[index] = TD2_ALPM_HASH_INDEX_NULL;
   8244     }
   8245     *fb_lpm_hash_ptr = hash;
   8246     return SOC_E_NONE;
   8247 }
   8248 
   8249 /*
   8250  * Function:
   8251  *      _soc_th_alpm_lpm_hash_destroy
   8252  * Purpose:
   8253  *      Destroy the hash table
   8254  * Parameters:
   8255  *      fb_lpm_hash - Pointer (handle) to Hash Table
   8256  * Returns:
   8257  *      SOC_E_NONE       Success
   8258  */
   8259 static
   8260 int _soc_th_alpm_lpm_hash_destroy(_soc_th_alpm_lpm_hash_t *fb_lpm_hash)
   8261 {
   8262     if (fb_lpm_hash != NULL) {
   8263         sal_free(fb_lpm_hash->table);
   8264         sal_free(fb_lpm_hash->link_table);
   8265         sal_free(fb_lpm_hash);
   8266     }
   8267 
   8268     return SOC_E_NONE;
   8269 }
   8270 
   8271 /*
   8272  * Function:
   8273  *      _soc_th_alpm_lpm_hash_lookup
   8274  * Purpose:
   8275  *      Look up a key in the hash table
   8276  * Parameters:
   8277  *      hash - Pointer (handle) to Hash Table
   8278  *      key_cmp_fn - Compare function which should compare key
   8279  *      entry   - The key to lookup
   8280  *      pfx     - Prefix length for lookup acceleration.
   8281  *      key_index - (OUT)       Index where the key was found.
   8282  * Returns:
   8283  *      SOC_E_NONE      Key found
   8284  *      SOC_E_NOT_FOUND Key not found
   8285  */
   8286 
   8287 static
   8288 int _soc_th_alpm_lpm_hash_lookup(_soc_th_alpm_lpm_hash_t          *hash,
   8289                             _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn,
   8290                             _soc_th_alpm_lpm_hash_entry_t    entry,
   8291                             int                         pfx,
   8292                             uint16                      *key_index)
   8293 {
   8294     int u = hash->unit, v, i = 0;
   8295 
   8296     uint16 hash_val;
   8297     uint16 index;
   8298 
   8299     hash_val = _soc_th_alpm_lpm_hash_compute((uint8 *)entry,
   8300                                         (32 * 5)) % hash->index_count;
   8301     index = hash->table[hash_val];
   8302     H_INDEX_MATCH("lhash", entry[0], hash_val);
   8303     H_INDEX_MATCH("lkup ", entry[0], index);
   8304     while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   8305         uint32  e[SOC_MAX_MEM_FIELD_WORDS];
   8306         _soc_th_alpm_lpm_hash_entry_t  r_entry;
   8307         int     rindex;
   8308 
   8309         rindex = (index & TD2_ALPM_HASH_INDEX_MASK) >> 1;
   8310         /*
   8311          * Check prefix length and skip index if not valid for given length
   8312         if ((SOC_ALPM_LPM_STATE_START(u, pfx) <= rindex) &&
   8313             (SOC_ALPM_LPM_STATE_END(u, pfx) >= rindex)) {
   8314          */
   8315         SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm,
   8316                                                MEM_BLOCK_ANY, rindex, e));
   8317         SOC_FB_LPM_HASH_ENTRY_GET(u, e, index, r_entry, &v);
   8318         if (v == 0) {
   8319             LOG_ERROR(BSL_LS_SOC_ALPM,
   8320                       (BSL_META_U(u,
   8321                                 "Empty entry[%d] in link_table. hash_val %d ridx %d \n"),
   8322                                 index, hash_val, rindex));
   8323         }
   8324         if ((*key_cmp_fn)(entry, r_entry) == 0) {
   8325             *key_index = (index & TD2_ALPM_HASH_INDEX_MASK) >>
   8326                             ((index & TD2_ALPM_HASH_IPV6_MASK) ? 1 : 0);
   8327             H_INDEX_MATCH("found", entry[0], index);
   8328             return(SOC_E_NONE);
   8329         }
   8330         /*
   8331         }
   8332         */
   8333         index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK];
   8334         H_INDEX_MATCH("lkup1", entry[0], index);
   8335     }
   8336     if (i > hash->entry_count) {
   8337         LOG_ERROR(BSL_LS_SOC_ALPM,
   8338                   (BSL_META_U(u,
   8339                             "Hash loop\n")));
   8340     }
   8341     H_INDEX_MATCH("not_found", entry[0], index);
   8342     return(SOC_E_NOT_FOUND);
   8343 }
   8344 
   8345 /*
   8346  * Function:
   8347  *      _soc_th_alpm_lpm_hash_insert
   8348  * Purpose:
   8349  *      Insert/Update a key index in the hash table
   8350  * Parameters:
   8351  *      hash - Pointer (handle) to Hash Table
   8352  *      key_cmp_fn - Compare function which should compare key
   8353  *      entry   - The key to lookup
   8354  *      pfx     - Prefix length for lookup acceleration.
   8355  *      old_index - Index where the key was moved from.
   8356  *                  TD2_ALPM_HASH_INDEX_NULL if new entry.
   8357  *      new_index - Index where the key was moved to.
   8358  * Returns:
   8359  *      SOC_E_NONE      Key found
   8360  */
   8361 /*
   8362  *      Should be caled before updating the LPM table so that the
   8363  *      data in the hash table is consistent with the LPM table
   8364  */
   8365 static
   8366 int _soc_th_alpm_lpm_hash_insert(_soc_th_alpm_lpm_hash_t *hash,
   8367                             _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn,
   8368                             _soc_th_alpm_lpm_hash_entry_t entry,
   8369                             int    pfx,
   8370                             uint16 old_index,
   8371                             uint16 new_index,
   8372                             uint32 *rvt_index)
   8373 {
   8374 
   8375 #define INDEX_ADD(hash, hash_idx, new_idx)                      \
   8376     hash->link_table[new_idx & TD2_ALPM_HASH_INDEX_MASK] =        \
   8377         hash->table[hash_idx];                                  \
   8378     hash->table[hash_idx] = new_idx
   8379 
   8380 #define INDEX_ADD_LINK(hash, t_index, new_idx)                  \
   8381     hash->link_table[new_idx & TD2_ALPM_HASH_INDEX_MASK] =        \
   8382         hash->link_table[t_index & TD2_ALPM_HASH_INDEX_MASK];     \
   8383     hash->link_table[t_index & TD2_ALPM_HASH_INDEX_MASK] = new_idx
   8384 
   8385 #define INDEX_UPDATE(hash, hash_idx, old_idx, new_idx)          \
   8386     hash->table[hash_idx] = new_idx;                            \
   8387     hash->link_table[new_idx & TD2_ALPM_HASH_INDEX_MASK] =        \
   8388         hash->link_table[old_idx & TD2_ALPM_HASH_INDEX_MASK];     \
   8389     hash->link_table[old_idx & TD2_ALPM_HASH_INDEX_MASK] = TD2_ALPM_HASH_INDEX_NULL
   8390 
   8391 #define INDEX_UPDATE_LINK(hash, prev_idx, old_idx, new_idx)             \
   8392     hash->link_table[prev_idx & TD2_ALPM_HASH_INDEX_MASK] = new_idx;      \
   8393     hash->link_table[new_idx & TD2_ALPM_HASH_INDEX_MASK] =                \
   8394         hash->link_table[old_idx & TD2_ALPM_HASH_INDEX_MASK];             \
   8395     hash->link_table[old_idx & TD2_ALPM_HASH_INDEX_MASK] = TD2_ALPM_HASH_INDEX_NULL
   8396 
   8397 
   8398     int u = hash->unit, v, i = 0;
   8399 
   8400     uint16 hash_val;
   8401     uint16 index;
   8402     uint16 prev_index;
   8403 
   8404     if (rvt_index) {
   8405         *rvt_index = TD2_ALPM_HASH_INDEX_NULL;
   8406     }
   8407     hash_val = _soc_th_alpm_lpm_hash_compute((uint8 *)entry,
   8408                                         (32 * 5)) % hash->index_count;
   8409     index = hash->table[hash_val];
   8410     H_INDEX_MATCH("ihash", entry[0], hash_val);
   8411     H_INDEX_MATCH("ins  ", entry[0], new_index);
   8412     H_INDEX_MATCH("ins1 ", index, new_index);
   8413     prev_index = TD2_ALPM_HASH_INDEX_NULL;
   8414     if (old_index != TD2_ALPM_HASH_INDEX_NULL) {
   8415         while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   8416             uint32  e[SOC_MAX_MEM_FIELD_WORDS];
   8417             _soc_th_alpm_lpm_hash_entry_t  r_entry;
   8418             int     rindex;
   8419 
   8420             rindex = (index & TD2_ALPM_HASH_INDEX_MASK) >> 1;
   8421 
   8422             /*
   8423              * Check prefix length and skip index if not valid for given length
   8424             if ((SOC_ALPM_LPM_STATE_START(u, pfx) <= rindex) &&
   8425                 (SOC_ALPM_LPM_STATE_END(u, pfx) >= rindex)) {
   8426              */
   8427             SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY,
   8428                                                    rindex, e));
   8429             SOC_FB_LPM_HASH_ENTRY_GET(u, e, index, r_entry, &v);
   8430             if (v == 0) {
   8431                 if ((index & TD2_ALPM_HASH_IPV6_MASK) ||
   8432                     !((new_index & 1) && (new_index == (index + 1)))) {
   8433                     LOG_ERROR(BSL_LS_SOC_ALPM,
   8434                           (BSL_META_U(u,
   8435                                     "Empty entry[%d] in link_table. hash_val %d ridx %d nidx %d\n"),
   8436                                     index, hash_val, rindex, new_index));
   8437                 }
   8438             }
   8439             if (v && ((*key_cmp_fn)(entry, r_entry) == 0)) {
   8440                 /* assert(old_index == index);*/
   8441                 if (new_index != index) {
   8442                     H_INDEX_MATCH("imove", prev_index, new_index);
   8443                     if (prev_index == TD2_ALPM_HASH_INDEX_NULL) {
   8444                         INDEX_UPDATE(hash, hash_val, index, new_index);
   8445                     } else {
   8446                         INDEX_UPDATE_LINK(hash, prev_index, index, new_index);
   8447                     }
   8448                 }
   8449                 if (rvt_index) {
   8450                     *rvt_index = index;
   8451                 }
   8452                 H_INDEX_MATCH("imtch", index, new_index);
   8453                 return(SOC_E_NONE);
   8454             }
   8455             /*
   8456             }
   8457             */
   8458             prev_index = index;
   8459             index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK];
   8460             H_INDEX_MATCH("ins2 ", index, new_index);
   8461         }
   8462     }
   8463     if (i > hash->entry_count) {
   8464         LOG_ERROR(BSL_LS_SOC_ALPM,
   8465                   (BSL_META_U(u,
   8466                             "Hash loop\n")));
   8467         return SOC_E_INTERNAL;
   8468     }
   8469     INDEX_ADD(hash, hash_val, new_index);  /* new entry */
   8470     return(SOC_E_NONE);
   8471 }
   8472 
   8473 /*
   8474  * Function:
   8475  *      _soc_th_alpm_lpm_hash_delete
   8476  * Purpose:
   8477  *      Delete a key index in the hash table
   8478  * Parameters:
   8479  *      hash - Pointer (handle) to Hash Table
   8480  *      key_cmp_fn - Compare function which should compare key
   8481  *      entry   - The key to delete
   8482  *      pfx     - Prefix length for lookup acceleration.
   8483  *      delete_index - Index to delete.
   8484  * Returns:
   8485  *      SOC_E_NONE      Success
   8486  *      SOC_E_NOT_FOUND Key index not found.
   8487  */
   8488 static
   8489 int _soc_th_alpm_lpm_hash_delete(_soc_th_alpm_lpm_hash_t *hash,
   8490                             _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn,
   8491                             _soc_th_alpm_lpm_hash_entry_t entry,
   8492                             int    pfx,
   8493                             uint16 delete_index)
   8494 {
   8495     int u = hash->unit, i = 0;
   8496     uint16 hash_val;
   8497     uint16 index;
   8498     uint16 prev_index;
   8499 
   8500     hash_val = _soc_th_alpm_lpm_hash_compute((uint8 *)entry,
   8501                                         (32 * 5)) % hash->index_count;
   8502     index = hash->table[hash_val];
   8503     H_INDEX_MATCH("dhash", entry[0], hash_val);
   8504     H_INDEX_MATCH("del  ", entry[0], index);
   8505     prev_index = TD2_ALPM_HASH_INDEX_NULL;
   8506     while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   8507         if (delete_index == index) {
   8508             H_INDEX_MATCH("dfoun", entry[0], index);
   8509             if (prev_index == TD2_ALPM_HASH_INDEX_NULL) {
   8510                 INDEX_DELETE(hash, hash_val, delete_index);
   8511             } else {
   8512                 INDEX_DELETE_LINK(hash, prev_index, delete_index);
   8513             }
   8514             return(SOC_E_NONE);
   8515         }
   8516         prev_index = index;
   8517         index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK];
   8518         H_INDEX_MATCH("del1 ", entry[0], index);
   8519     }
   8520     if (i > hash->entry_count) {
   8521         LOG_ERROR(BSL_LS_SOC_ALPM,
   8522                   (BSL_META_U(u,
   8523                             "Hash loop\n")));
   8524     }
   8525     return(SOC_E_NOT_FOUND);
   8526 }
   8527 
   8528 static
   8529 int _soc_th_alpm_lpm_hash_revert(_soc_th_alpm_lpm_hash_t *hash,
   8530                             _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn,
   8531                             _soc_th_alpm_lpm_hash_entry_t entry,
   8532                             uint16 new_index,
   8533                             uint32 rvt_index)
   8534 {
   8535     int u = hash->unit, i = 0;
   8536     uint16 hash_val;
   8537     uint16 index;
   8538     uint16 prev_index;
   8539 
   8540     hash_val = _soc_th_alpm_lpm_hash_compute((uint8 *)entry,
   8541                                         (32 * 5)) % hash->index_count;
   8542     index = hash->table[hash_val];
   8543     H_INDEX_MATCH("rhash", entry[0], hash_val);
   8544     H_INDEX_MATCH("rvt  ", entry[0], index);
   8545     prev_index = TD2_ALPM_HASH_INDEX_NULL;
   8546     while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   8547         if (new_index == index) {
   8548             H_INDEX_MATCH("dfoun", entry[0], index);
   8549             if (rvt_index == TD2_ALPM_HASH_INDEX_NULL) {
   8550                 if (prev_index == TD2_ALPM_HASH_INDEX_NULL) {
   8551                     INDEX_DELETE(hash, hash_val, new_index);
   8552                 } else {
   8553                     INDEX_DELETE_LINK(hash, prev_index, new_index);
   8554                 }
   8555             } else {
   8556                 if (prev_index == TD2_ALPM_HASH_INDEX_NULL) {
   8557                     INDEX_UPDATE(hash, hash_val, new_index, rvt_index);
   8558                 } else {
   8559                     INDEX_UPDATE_LINK(hash, prev_index, new_index, rvt_index);
   8560                 }
   8561             }
   8562             return(SOC_E_NONE);
   8563         }
   8564         prev_index = index;
   8565         index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK];
   8566         H_INDEX_MATCH("rvt1 ", entry[0], index);
   8567     }
   8568     if (i > hash->entry_count) {
   8569         LOG_ERROR(BSL_LS_SOC_ALPM,
   8570                   (BSL_META_U(u,
   8571                             "Hash loop\n")));
   8572     }
   8573     return(SOC_E_NOT_FOUND);
   8574 }
   8575 
   8576 
   8577 /*
   8578  * Function:
   8579  *      _soc_th_alpm_lpm_hash_verify
   8580  * Purpose:
   8581  *      Verify a key index in the hash table
   8582  * Parameters:
   8583  *      hash - Pointer (handle) to Hash Table
   8584  *      key_cmp_fn - Compare function which should compare key
   8585  *      entry   - The key to delete
   8586  *      pfx     - Prefix length for lookup acceleration.
   8587  *      verify_index   - Index to verify.
   8588  * Returns:
   8589  *      SOC_E_NONE      Success
   8590  *      SOC_E_NOT_FOUND Key index not found.
   8591  */
   8592 static
   8593 int _soc_th_alpm_lpm_hash_verify(_soc_th_alpm_lpm_hash_t *hash,
   8594                             _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn,
   8595                             _soc_th_alpm_lpm_hash_entry_t entry,
   8596                             int    pfx,
   8597                             uint16 verify_index)
   8598 {
   8599     int u = hash->unit, i = 0;
   8600     uint16 hash_val;
   8601     uint16 index;
   8602 
   8603     hash_val = _soc_th_alpm_lpm_hash_compute((uint8 *)entry,
   8604                                         (32 * 5)) % hash->index_count;
   8605     index = hash->table[hash_val];
   8606     H_INDEX_MATCH("vhash", entry[0], hash_val);
   8607     H_INDEX_MATCH("veri ", entry[0], index);
   8608     while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   8609         if (verify_index == index) {
   8610             H_INDEX_MATCH("vfoun", entry[0], index);
   8611             return(SOC_E_NONE);
   8612         }
   8613         index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK];
   8614         H_INDEX_MATCH("veri1", entry[0], index);
   8615     }
   8616     if (i > hash->entry_count) {
   8617         LOG_ERROR(BSL_LS_SOC_ALPM,
   8618                   (BSL_META_U(u,
   8619                             "Hash loop\n")));
   8620     }
   8621     return(SOC_E_NOT_FOUND);
   8622 }
   8623 #else
   8624 #define LPM_HASH_INSERT(u, entry_data, tab_index, rvt_index0, rvt_index1)
   8625 #define LPM_HASH_REVERT(u, entry_data, tab_index, rvt_index0, rvt_index1)
   8626 #define LPM_HASH_DELETE(u, key_data, tab_index)
   8627 #define LPM_HASH_LOOKUP(u, key_data, pfx, tab_index)
   8628 #define LPM_HASH_VERIFY(u, key_data, tab_index)
   8629 #endif /* FB_LPM_HASH_SUPPORT */
   8630 
   8631 /* src and dst can be same */
   8632 #define _COPY_FIELD32(src_fld, dst_fld)                     \
   8633     do {                                                    \
   8634         uint32 val;                                         \
   8635         val = soc_mem_field32_get(u, mem, src, src_fld);    \
   8636         soc_mem_field32_set(u, mem, dst, dst_fld, val);     \
   8637     } while (0)
   8638 
   8639 #define _COPY_FIELD(src_fld, dst_fld)                       \
   8640     do {                                                    \
   8641         uint32 vals[5];                                     \
   8642         sal_memset(vals, 0, sizeof(vals));                  \
   8643         soc_mem_field_get(u, mem, src, src_fld, vals);      \
   8644         soc_mem_field_set(u, mem, dst, dst_fld, vals);      \
   8645     } while (0)
   8646 
   8647 int
   8648  soc_th_alpm_lpm_ip4entry0_to_0(int u, void *src, void *dst, int copy_hit)
   8649 {
   8650     soc_mem_t mem = L3_DEFIPm;
   8651 
   8652     _COPY_FIELD32(VALID0f, VALID0f);
   8653     _COPY_FIELD32(ALG_BKT_PTR0f, ALG_BKT_PTR0f);
   8654     _COPY_FIELD32(GLOBAL_HIGH0f, GLOBAL_HIGH0f);
   8655     _COPY_FIELD32(ALG_HIT_IDX0f, ALG_HIT_IDX0f);
   8656     _COPY_FIELD32(ENTRY_VIEW0f, ENTRY_VIEW0f);
   8657     if (ALPM_CTRL(u).bkt_sharing) {
   8658         _COPY_FIELD32(ALG_SUB_BKT_PTR0f, ALG_SUB_BKT_PTR0f);
   8659     }
   8660     if (soc_feature(u, soc_feature_ipmc_defip)) {
   8661         if (soc_mem_field_valid(u, mem, MULTICAST_ROUTE0f)) {
   8662             _COPY_FIELD32(MULTICAST_ROUTE0f, MULTICAST_ROUTE0f);
   8663         }
   8664     }
   8665     if (copy_hit) {
   8666         _COPY_FIELD32(HIT0f, HIT0f);
   8667     }
   8668 
   8669     _COPY_FIELD(KEY0f, KEY0f);
   8670     _COPY_FIELD(MASK0f, MASK0f);
   8671     _COPY_FIELD(REPLACE_DATA0f, REPLACE_DATA0f);
   8672 
   8673     if (soc_mem_field_valid(u, mem, DATA_TYPE0f)) {
   8674         _COPY_FIELD(DATA_TYPE0f, DATA_TYPE0f);
   8675     }
   8676 
   8677     return(SOC_E_NONE);
   8678 }
   8679 
   8680 int
   8681 soc_th_alpm_lpm_ip4entry1_to_1(int u, void *src, void *dst, int copy_hit)
   8682 {
   8683     soc_mem_t mem = L3_DEFIPm;
   8684 
   8685     _COPY_FIELD32(VALID1f, VALID1f);
   8686     _COPY_FIELD32(ALG_BKT_PTR1f, ALG_BKT_PTR1f);
   8687     _COPY_FIELD32(GLOBAL_HIGH1f, GLOBAL_HIGH1f);
   8688     _COPY_FIELD32(ALG_HIT_IDX1f, ALG_HIT_IDX1f);
   8689     _COPY_FIELD32(ENTRY_VIEW1f, ENTRY_VIEW1f);
   8690     if (ALPM_CTRL(u).bkt_sharing) {
   8691         _COPY_FIELD32(ALG_SUB_BKT_PTR1f, ALG_SUB_BKT_PTR1f);
   8692     }
   8693     if (soc_feature(u, soc_feature_ipmc_defip)) {
   8694         if (soc_mem_field_valid(u, mem, MULTICAST_ROUTE1f)) {
   8695             _COPY_FIELD32(MULTICAST_ROUTE1f, MULTICAST_ROUTE1f);
   8696         }
   8697     }
   8698     if (copy_hit) {
   8699         _COPY_FIELD32(HIT1f, HIT1f);
   8700     }
   8701 
   8702     _COPY_FIELD(KEY1f, KEY1f);
   8703     _COPY_FIELD(MASK1f, MASK1f);
   8704     _COPY_FIELD(REPLACE_DATA1f, REPLACE_DATA1f);
   8705 
   8706     if (soc_mem_field_valid(u, mem, DATA_TYPE1f)) {
   8707         _COPY_FIELD(DATA_TYPE1f, DATA_TYPE1f);
   8708     }
   8709 
   8710     return(SOC_E_NONE);
   8711 }
   8712 
   8713 /* src and dst can be same */
   8714 int
   8715 soc_th_alpm_lpm_ip4entry0_to_1(int u, void *src, void *dst, int copy_hit)
   8716 {
   8717     soc_mem_t mem = L3_DEFIPm;
   8718 
   8719     _COPY_FIELD32(VALID0f, VALID1f);
   8720     _COPY_FIELD32(ALG_BKT_PTR0f, ALG_BKT_PTR1f);
   8721     _COPY_FIELD32(GLOBAL_HIGH0f, GLOBAL_HIGH1f);
   8722     _COPY_FIELD32(ALG_HIT_IDX0f, ALG_HIT_IDX1f);
   8723     _COPY_FIELD32(ENTRY_VIEW0f, ENTRY_VIEW1f);
   8724     if (ALPM_CTRL(u).bkt_sharing) {
   8725         _COPY_FIELD32(ALG_SUB_BKT_PTR0f, ALG_SUB_BKT_PTR1f);
   8726     }
   8727     if (soc_feature(u, soc_feature_ipmc_defip)) {
   8728         if (soc_mem_field_valid(u, mem, MULTICAST_ROUTE1f)) {
   8729             _COPY_FIELD32(MULTICAST_ROUTE0f, MULTICAST_ROUTE1f);
   8730         }
   8731     }
   8732     if (copy_hit) {
   8733         _COPY_FIELD32(HIT0f, HIT1f);
   8734     }
   8735 
   8736     _COPY_FIELD(KEY0f, KEY1f);
   8737     _COPY_FIELD(MASK0f, MASK1f);
   8738     _COPY_FIELD(REPLACE_DATA0f, REPLACE_DATA1f);
   8739 
   8740     if (soc_mem_field_valid(u, mem, DATA_TYPE0f)) {
   8741         _COPY_FIELD(DATA_TYPE0f, DATA_TYPE1f);
   8742     }
   8743 
   8744     return(SOC_E_NONE);
   8745 }
   8746 
   8747 /* src and dst can be same */
   8748 int
   8749 soc_th_alpm_lpm_ip4entry1_to_0(int u, void *src, void *dst, int copy_hit)
   8750 {
   8751     soc_mem_t mem = L3_DEFIPm;
   8752 
   8753     _COPY_FIELD32(VALID1f, VALID0f);
   8754     _COPY_FIELD32(ALG_BKT_PTR1f, ALG_BKT_PTR0f);
   8755     _COPY_FIELD32(GLOBAL_HIGH1f, GLOBAL_HIGH0f);
   8756     _COPY_FIELD32(ALG_HIT_IDX1f, ALG_HIT_IDX0f);
   8757     _COPY_FIELD32(ENTRY_VIEW1f, ENTRY_VIEW0f);
   8758     if (ALPM_CTRL(u).bkt_sharing) {
   8759         _COPY_FIELD32(ALG_SUB_BKT_PTR1f, ALG_SUB_BKT_PTR0f);
   8760     }
   8761     if (soc_feature(u, soc_feature_ipmc_defip)) {
   8762         if (soc_mem_field_valid(u, mem, MULTICAST_ROUTE1f)) {
   8763             _COPY_FIELD32(MULTICAST_ROUTE1f, MULTICAST_ROUTE0f);
   8764         }
   8765     }
   8766     if (copy_hit) {
   8767         _COPY_FIELD32(HIT1f, HIT0f);
   8768     }
   8769 
   8770     _COPY_FIELD(KEY1f, KEY0f);
   8771     _COPY_FIELD(MASK1f, MASK0f);
   8772     _COPY_FIELD(REPLACE_DATA1f, REPLACE_DATA0f);
   8773 
   8774     if (soc_mem_field_valid(u, mem, DATA_TYPE0f)) {
   8775         _COPY_FIELD(DATA_TYPE1f, DATA_TYPE0f);
   8776     }
   8777 
   8778     return(SOC_E_NONE);
   8779 }
   8780 
   8781 void
   8782 soc_th_alpm_lpm_state_dump(int u)
   8783 {
   8784     int i;
   8785     int max_pfx_len;
   8786     max_pfx_len = ALPM_MAX_PFX_INDEX;
   8787 
   8788 #ifndef BCM_WARM_BOOT_SUPPORT_SW_DUMP
   8789     if (!bsl_check(bslLayerSoc, bslSourceAlpm, bslSeverityVerbose, u)) {
   8790         return;
   8791     }
   8792 #endif
   8793 
   8794     for(i = max_pfx_len; i >= 0 ; i--) {
   8795         if ((i != ALPM_MAX_PFX_INDEX) && (SOC_ALPM_LPM_STATE_START(u, i) == -1)) {
   8796             continue;
   8797         }
   8798 
   8799 #ifdef ALPM_WARM_BOOT_DEBUG
   8800         LOG_ERROR(BSL_LS_SOC_ALPM,
   8801                   (BSL_META_U(u,
   8802                               "PFX = %d P = %d N = %d START = %d END = %d VENT = %d FENT = %d\n"),
   8803                    i,
   8804                    SOC_ALPM_LPM_STATE_PREV(u, i),
   8805                    SOC_ALPM_LPM_STATE_NEXT(u, i),
   8806                    SOC_ALPM_LPM_STATE_START(u, i),
   8807                    SOC_ALPM_LPM_STATE_END(u, i),
   8808                    SOC_ALPM_LPM_STATE_VENT(u, i),
   8809                    SOC_ALPM_LPM_STATE_FENT(u, i)));
   8810 #else
   8811         LOG_VERBOSE(BSL_LS_SOC_ALPM,
   8812                     (BSL_META_U(u,
   8813                                 "PFX = %d P = %d N = %d START = %d END = %d VENT = %d FENT = %d\n"),
   8814                      i,
   8815                      SOC_ALPM_LPM_STATE_PREV(u, i),
   8816                      SOC_ALPM_LPM_STATE_NEXT(u, i),
   8817                      SOC_ALPM_LPM_STATE_START(u, i),
   8818                      SOC_ALPM_LPM_STATE_END(u, i),
   8819                      SOC_ALPM_LPM_STATE_VENT(u, i),
   8820                      SOC_ALPM_LPM_STATE_FENT(u, i)));
   8821 #endif
   8822     }
   8823 }
   8824 
   8825 /*
   8826  *      Create a slot for the new entry rippling the entries if required
   8827  */
   8828 static
   8829 int _lpm_fb_entry_shift(int u, int from_ent, int to_ent)
   8830 {
   8831     uint32      e[SOC_MAX_MEM_FIELD_WORDS], e_urpf[SOC_MAX_MEM_FIELD_WORDS];
   8832     uint32      rvt_index0 = 0, rvt_index1 = 0;
   8833     int src_default = 0, src_discard = 0;
   8834     int src_tcam_offset = 0;
   8835     int rv;
   8836 #ifdef FB_LPM_TABLE_CACHED
   8837     SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, L3_DEFIPm,
   8838                                        MEM_BLOCK_ANY, from_ent));
   8839 #endif /* FB_LPM_TABLE_CACHED */
   8840 
   8841     SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm,
   8842                                            MEM_BLOCK_ANY, from_ent, e));
   8843     if (SOC_URPF_STATUS_GET(u)) {
   8844         if (soc_feature(u, soc_feature_l3_defip_hole)) {
   8845              src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1);
   8846         } else if (SOC_IS_APOLLO(u)) {
   8847              src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1) + 0x0400;
   8848         } else {
   8849              src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1);
   8850         }
   8851         SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm,
   8852                                                MEM_BLOCK_ANY,
   8853                                                from_ent + src_tcam_offset,
   8854                                                e_urpf));
   8855         src_default = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, RPE0f) |
   8856                       (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, RPE1f) << 1);
   8857         src_discard = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, SRC_DISCARD0f) |
   8858                       (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, SRC_DISCARD1f) << 1);
   8859     }
   8860 
   8861     LPM_HASH_INSERT(u, e, to_ent, &rvt_index0, &rvt_index1);
   8862     rv = _soc_th_alpm_write_pivot(u, MEM_BLOCK_ANY, to_ent, from_ent, e, src_default, src_discard);
   8863     if (rv < 0) {
   8864         LPM_HASH_REVERT(u, e, to_ent, rvt_index0, rvt_index1);
   8865         return rv;
   8866     }
   8867 
   8868     SOC_ALPM_MOVE_PIVOT_FULL(u, from_ent, to_ent);
   8869 
   8870     return (SOC_E_NONE);
   8871 }
   8872 
   8873 
   8874 /*
   8875  *      Shift prefix entries 1 entry UP, while preserving
   8876  *      last half empty IPv4 entry if any.
   8877  */
   8878 static
   8879 int _lpm_fb_shift_pfx_up(int u, int pfx, int ipv6)
   8880 {
   8881     uint32      e[SOC_MAX_MEM_FIELD_WORDS], e_urpf[SOC_MAX_MEM_FIELD_WORDS];
   8882     int         from_ent;
   8883     int         to_ent;
   8884     uint32      v0, v1;
   8885     uint32      rvt_index0 = 0, rvt_index1 = 0;
   8886     int         rv;
   8887     int src_default = 0, src_discard = 0;
   8888     int src_tcam_offset = 0;
   8889 
   8890     if (SOC_URPF_STATUS_GET(u)) {
   8891         if (soc_feature(u, soc_feature_l3_defip_hole)) {
   8892              src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1);
   8893         } else if (SOC_IS_APOLLO(u)) {
   8894              src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1) + 0x0400;
   8895         } else {
   8896              src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1);
   8897         }
   8898     }
   8899 
   8900     to_ent = SOC_ALPM_LPM_STATE_END(u, pfx) + 1;
   8901 
   8902     ipv6 = SOC_ALPM_PFX_IS_V6_64(u, pfx);
   8903     if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity) && !ipv6) {
   8904         from_ent = SOC_ALPM_LPM_STATE_END(u, pfx);
   8905 #ifdef FB_LPM_TABLE_CACHED
   8906         SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, L3_DEFIPm,
   8907                                                      MEM_BLOCK_ANY, from_ent));
   8908 #endif /* FB_LPM_TABLE_CACHED */
   8909         SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm,
   8910                                                MEM_BLOCK_ANY, from_ent, e));
   8911         if (SOC_URPF_STATUS_GET(u)) {
   8912             SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm,
   8913                                                    MEM_BLOCK_ANY,
   8914                                                    from_ent + src_tcam_offset,
   8915                                                    e_urpf));
   8916             src_default = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, RPE0f) |
   8917                           (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, RPE1f) << 1);
   8918             src_discard = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, SRC_DISCARD0f) |
   8919                           (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, SRC_DISCARD1f) << 1);
   8920         }
   8921 
   8922         v0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f);
   8923         v1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f);
   8924 
   8925         if ((v0 == 0) || (v1 == 0)) {
   8926             /* Last entry is half full -> keep it last. */
   8927             LPM_HASH_INSERT(u, e, to_ent, &rvt_index0, &rvt_index1);
   8928             rv = _soc_th_alpm_write_pivot(u, MEM_BLOCK_ANY, to_ent, from_ent, e,
   8929                                           src_default, src_discard);
   8930             if (rv < 0) {
   8931                 LPM_HASH_REVERT(u, e, to_ent, rvt_index0, rvt_index1);
   8932                 return rv;
   8933             }
   8934 
   8935             /* track pivot state movement */
   8936             SOC_ALPM_MOVE_PIVOT_HALF(u, v1, from_ent, to_ent);
   8937             to_ent--;
   8938         }
   8939     }
   8940 
   8941     from_ent = SOC_ALPM_LPM_STATE_START(u, pfx);
   8942     if (from_ent != to_ent) {
   8943         SOC_IF_ERROR_RETURN(_lpm_fb_entry_shift(u, from_ent, to_ent));
   8944         VRF_PIVOT_SHIFT_INC(u, MAX_VRF_ID, ipv6);
   8945     }
   8946     SOC_ALPM_LPM_STATE_START(u, pfx) += 1;
   8947     SOC_ALPM_LPM_STATE_END(u, pfx) += 1;
   8948     return (SOC_E_NONE);
   8949 }
   8950 
   8951 /*
   8952  *      Shift prefix entries 1 entry DOWN, while preserving
   8953  *      last half empty IPv4 entry if any.
   8954  */
   8955 static
   8956 int _lpm_fb_shift_pfx_down(int u, int pfx, int ipv6)
   8957 {
   8958     uint32      e[SOC_MAX_MEM_FIELD_WORDS], e_urpf[SOC_MAX_MEM_FIELD_WORDS];
   8959     int         from_ent;
   8960     int         to_ent;
   8961     int         prev_ent;
   8962     uint32      v0, v1;
   8963     uint32      rvt_index0 = 0, rvt_index1 = 0;
   8964     int         rv;
   8965     int src_default = 0, src_discard = 0;
   8966     int src_tcam_offset = 0;
   8967 
   8968     if (SOC_URPF_STATUS_GET(u)) {
   8969         if (soc_feature(u, soc_feature_l3_defip_hole)) {
   8970              src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1);
   8971         } else if (SOC_IS_APOLLO(u)) {
   8972              src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1) + 0x0400;
   8973         } else {
   8974              src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1);
   8975         }
   8976     }
   8977 
   8978     to_ent = SOC_ALPM_LPM_STATE_START(u, pfx) - 1;
   8979 
   8980     /* Don't move empty prefix . */
   8981     if (SOC_ALPM_LPM_STATE_VENT(u, pfx) == 0) {
   8982         SOC_ALPM_LPM_STATE_START(u, pfx) = to_ent;
   8983         SOC_ALPM_LPM_STATE_END(u, pfx) = to_ent - 1;
   8984         return (SOC_E_NONE);
   8985     }
   8986     ipv6 = SOC_ALPM_PFX_IS_V6_64(u, pfx);
   8987 
   8988     if ((!ipv6) && (SOC_ALPM_LPM_STATE_END(u, pfx) != SOC_ALPM_LPM_STATE_START(u, pfx))) {
   8989 
   8990         from_ent = SOC_ALPM_LPM_STATE_END(u, pfx);
   8991 
   8992 #ifdef FB_LPM_TABLE_CACHED
   8993         SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, L3_DEFIPm,
   8994                                                      MEM_BLOCK_ANY, from_ent));
   8995 #endif /* FB_LPM_TABLE_CACHED */
   8996         SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm,
   8997                                                MEM_BLOCK_ANY, from_ent, e));
   8998         if (SOC_URPF_STATUS_GET(u)) {
   8999             SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm,
   9000                                                    MEM_BLOCK_ANY,
   9001                                                    from_ent + src_tcam_offset,
   9002                                                    e_urpf));
   9003             src_default = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, RPE0f) |
   9004                           (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, RPE1f) << 1);
   9005             src_discard = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, SRC_DISCARD0f) |
   9006                           (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, SRC_DISCARD1f) << 1);
   9007         }
   9008 
   9009         v0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f);
   9010         v1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f);
   9011 
   9012         if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity) &&
   9013             ((v0 == 0) || (v1 == 0))) {
   9014             /* Last entry is half full -> keep it last. */
   9015             /* Shift entry before last to start - 1 position. */
   9016             prev_ent = from_ent - 1;
   9017             SOC_IF_ERROR_RETURN(_lpm_fb_entry_shift(u, prev_ent, to_ent));
   9018             VRF_PIVOT_SHIFT_INC(u, MAX_VRF_ID, ipv6);
   9019 
   9020             LPM_HASH_INSERT(u, e, prev_ent, &rvt_index0, &rvt_index1);
   9021             rv = _soc_th_alpm_write_pivot(u, MEM_BLOCK_ANY, prev_ent, from_ent, e,
   9022                                           src_default, src_discard);
   9023             if (rv < 0) {
   9024                 LPM_HASH_REVERT(u, e, prev_ent, rvt_index0, rvt_index1);
   9025                 return rv;
   9026             }
   9027             SOC_ALPM_MOVE_PIVOT_HALF(u, v1, from_ent, prev_ent);
   9028         } else {
   9029             /* Last entry is full -> just shift it to start - 1  position. */
   9030             LPM_HASH_INSERT(u, e, to_ent, &rvt_index0, &rvt_index1);
   9031             rv = _soc_th_alpm_write_pivot(u, MEM_BLOCK_ANY, to_ent, from_ent, e,
   9032                                           src_default, src_discard);
   9033             if (rv < 0) {
   9034                 LPM_HASH_REVERT(u, e, to_ent, rvt_index0, rvt_index1);
   9035                 return rv;
   9036             }
   9037 
   9038             /* Track full-entry move */
   9039             SOC_ALPM_MOVE_PIVOT_FULL(u, from_ent, to_ent);
   9040         }
   9041 
   9042     } else  {
   9043 
   9044         from_ent = SOC_ALPM_LPM_STATE_END(u, pfx);
   9045         SOC_IF_ERROR_RETURN(_lpm_fb_entry_shift(u, from_ent, to_ent));
   9046         VRF_PIVOT_SHIFT_INC(u, MAX_VRF_ID, ipv6);
   9047 
   9048     }
   9049     SOC_ALPM_LPM_STATE_START(u, pfx) -= 1;
   9050     SOC_ALPM_LPM_STATE_END(u, pfx) -= 1;
   9051 
   9052     return (SOC_E_NONE);
   9053 }
   9054 
   9055 /*
   9056  *      Create a slot for the new entry rippling the entries if required
   9057  */
   9058 static
   9059 int _lpm_free_slot_create(int u, int pfx, int ipv6, void *e, int *free_slot)
   9060 {
   9061     int         prev_pfx;
   9062     int         next_pfx;
   9063     int         free_pfx;
   9064     int         curr_pfx;
   9065     int         from_ent;
   9066     uint32      v0, v1;
   9067     int         rv;
   9068 
   9069 
   9070     if (SOC_ALPM_LPM_STATE_VENT(u, pfx) == 0) {
   9071         /*
   9072          * Find the  prefix position. Only prefix with valid
   9073          * entries are in the list.
   9074          * next -> high to low prefix. low to high index
   9075          * prev -> low to high prefix. high to low index
   9076          * Unused prefix length ALPM_MAX_PFX_INDEX is the head of the
   9077          * list and is node corresponding to this is always
   9078          * present.
   9079          */
   9080         curr_pfx = ALPM_MAX_PFX_INDEX;
   9081         if (ALPM_CTRL(u).gp_zoned) {
   9082             if (pfx <= ALPM_MAX_VRF_PFX_INDEX) {
   9083                 curr_pfx = ALPM_MAX_VRF_PFX_INDEX;
   9084             }
   9085         }
   9086         while (SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx) > pfx) {
   9087             curr_pfx = SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx);
   9088         }
   9089         /* Insert the new prefix */
   9090         next_pfx = SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx);
   9091         if (next_pfx != -1) {
   9092             SOC_ALPM_LPM_STATE_PREV(u, next_pfx) = pfx;
   9093         }
   9094         SOC_ALPM_LPM_STATE_NEXT(u, pfx) = SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx);
   9095         SOC_ALPM_LPM_STATE_PREV(u, pfx) = curr_pfx;
   9096         SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx) = pfx;
   9097 
   9098         SOC_ALPM_LPM_STATE_FENT(u, pfx) =  (SOC_ALPM_LPM_STATE_FENT(u, curr_pfx) + 1) / 2;
   9099         SOC_ALPM_LPM_STATE_FENT(u, curr_pfx) -= SOC_ALPM_LPM_STATE_FENT(u, pfx);
   9100         SOC_ALPM_LPM_STATE_START(u, pfx) =  SOC_ALPM_LPM_STATE_END(u, curr_pfx) +
   9101                                        SOC_ALPM_LPM_STATE_FENT(u, curr_pfx) + 1;
   9102         SOC_ALPM_LPM_STATE_END(u, pfx) = SOC_ALPM_LPM_STATE_START(u, pfx) - 1;
   9103         SOC_ALPM_LPM_STATE_VENT(u, pfx) = 0;
   9104     } else if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity) &&
   9105                !ipv6) {
   9106         /* For IPv4 Check if alternate entry is free */
   9107         from_ent = SOC_ALPM_LPM_STATE_START(u, pfx);
   9108 #ifdef FB_LPM_TABLE_CACHED
   9109         if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm,
   9110                                            MEM_BLOCK_ANY, from_ent)) < 0) {
   9111             return rv;
   9112         }
   9113 #endif /* FB_LPM_TABLE_CACHED */
   9114         if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm,
   9115                                      MEM_BLOCK_ANY, from_ent, e)) < 0) {
   9116             return rv;
   9117         }
   9118         v0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f);
   9119         v1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f);
   9120 
   9121         if ((v0 == 0) || (v1 == 0)) {
   9122             *free_slot = (from_ent << 1) + ((v1 == 0) ? 1 : 0);
   9123             return(SOC_E_NONE);
   9124         }
   9125 
   9126         from_ent = SOC_ALPM_LPM_STATE_END(u, pfx);
   9127 #ifdef FB_LPM_TABLE_CACHED
   9128         if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm,
   9129                                            MEM_BLOCK_ANY, from_ent)) < 0) {
   9130             return rv;
   9131         }
   9132 #endif /* FB_LPM_TABLE_CACHED */
   9133         if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm,
   9134                                      MEM_BLOCK_ANY, from_ent, e)) < 0) {
   9135             return rv;
   9136         }
   9137         v0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f);
   9138         v1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f);
   9139 
   9140         if ((v0 == 0) || (v1 == 0)) {
   9141             *free_slot = (from_ent << 1) + ((v1 == 0) ? 1 : 0);
   9142             return(SOC_E_NONE);
   9143         }
   9144     }
   9145 
   9146     free_pfx = pfx;
   9147     while(SOC_ALPM_LPM_STATE_FENT(u, free_pfx) == 0) {
   9148         free_pfx = SOC_ALPM_LPM_STATE_NEXT(u, free_pfx);
   9149         if (free_pfx == -1) {
   9150             /* No free entries on this side try the other side */
   9151             free_pfx = pfx;
   9152             break;
   9153         }
   9154     }
   9155 
   9156     while(SOC_ALPM_LPM_STATE_FENT(u, free_pfx) == 0) {
   9157         free_pfx = SOC_ALPM_LPM_STATE_PREV(u, free_pfx);
   9158         if (free_pfx == -1) {
   9159             if (SOC_ALPM_LPM_STATE_VENT(u, pfx) == 0) {
   9160                 /* We failed to allocate entries for a newly allocated prefix.*/
   9161                 prev_pfx = SOC_ALPM_LPM_STATE_PREV(u, pfx);
   9162                 next_pfx = SOC_ALPM_LPM_STATE_NEXT(u, pfx);
   9163                 if (-1 != prev_pfx) {
   9164                     SOC_ALPM_LPM_STATE_NEXT(u, prev_pfx) = next_pfx;
   9165                 }
   9166                 if (-1 != next_pfx) {
   9167                     SOC_ALPM_LPM_STATE_PREV(u, next_pfx) = prev_pfx;
   9168                 }
   9169             }
   9170             return(SOC_E_FULL);
   9171         }
   9172     }
   9173 
   9174     /*
   9175      * Ripple entries to create free space
   9176      */
   9177     while (free_pfx > pfx) {
   9178         next_pfx = SOC_ALPM_LPM_STATE_NEXT(u, free_pfx);
   9179         SOC_IF_ERROR_RETURN(_lpm_fb_shift_pfx_down(u, next_pfx, ipv6));
   9180         SOC_ALPM_LPM_STATE_FENT(u, free_pfx) -= 1;
   9181         SOC_ALPM_LPM_STATE_FENT(u, next_pfx) += 1;
   9182         free_pfx = next_pfx;
   9183     }
   9184 
   9185     while (free_pfx < pfx) {
   9186         SOC_IF_ERROR_RETURN(_lpm_fb_shift_pfx_up(u, free_pfx, ipv6));
   9187         SOC_ALPM_LPM_STATE_FENT(u, free_pfx) -= 1;
   9188         prev_pfx = SOC_ALPM_LPM_STATE_PREV(u, free_pfx);
   9189         SOC_ALPM_LPM_STATE_FENT(u, prev_pfx) += 1;
   9190         free_pfx = prev_pfx;
   9191     }
   9192 
   9193     SOC_ALPM_LPM_STATE_VENT(u, pfx) += 1;
   9194     SOC_ALPM_LPM_STATE_FENT(u, pfx) -= 1;
   9195     SOC_ALPM_LPM_STATE_END(u, pfx) += 1;
   9196     *free_slot = SOC_ALPM_LPM_STATE_END(u, pfx) <<  ((ipv6) ? 0 : 1);
   9197 #ifdef BCM_TOMAHAWK2_SUPPORT
   9198     if (soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
   9199         *free_slot += (ipv6) ? 0 : 1;
   9200     }
   9201 #endif
   9202     sal_memcpy(e, soc_mem_entry_null(u, L3_DEFIPm),
   9203                soc_mem_entry_words(u,L3_DEFIPm) * 4);
   9204 
   9205     return(SOC_E_NONE);
   9206 }
   9207 
   9208 /*
   9209  *      Delete a slot and adjust entry pointers if required.
   9210  *      e - has the contents of entry at slot(useful for IPV4 only)
   9211  */
   9212 static
   9213 int _lpm_free_slot_delete(int u, int pfx, int ipv6, void *e, int slot)
   9214 {
   9215     int         prev_pfx;
   9216     int         next_pfx;
   9217     int         from_ent;
   9218     int         to_ent;
   9219     uint32      *ef = NULL;
   9220     uint32      *ef_urpf = NULL;
   9221     uint32      *sf = NULL;
   9222     uint32      *st = NULL;
   9223     void        *et;
   9224     int         rv;
   9225     int         src_pivot, bpm_len;
   9226     uint32      rvt_index0 = 0, rvt_index1 = 0;
   9227     int         upper_half = 0;
   9228     int src_default = 0, src_discard = 0;
   9229     int src_tcam_offset = 0;
   9230 
   9231     ef = sal_alloc(sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS, "buf_tmp");
   9232     if (ef == NULL) {
   9233         rv = SOC_E_MEMORY;
   9234         goto clean_up;
   9235     }
   9236 
   9237     ef_urpf = sal_alloc(sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS, "buf_tmp_urpf");
   9238     if (ef_urpf == NULL) {
   9239         rv = SOC_E_MEMORY;
   9240         goto clean_up;
   9241     }
   9242 
   9243     sf = sal_alloc(sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS, "buf_tmp_from");
   9244     if (sf == NULL) {
   9245         rv = SOC_E_MEMORY;
   9246         goto clean_up;
   9247     }
   9248 
   9249     st = sal_alloc(sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS, "buf_tmp_to");
   9250     if (st == NULL) {
   9251         rv = SOC_E_MEMORY;
   9252         goto clean_up;
   9253     }
   9254 
   9255     if (SOC_URPF_STATUS_GET(u)) {
   9256         if (soc_feature(u, soc_feature_l3_defip_hole)) {
   9257              src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1);
   9258         } else if (SOC_IS_APOLLO(u)) {
   9259              src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1) + 0x0400;
   9260         } else {
   9261              src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1);
   9262         }
   9263     }
   9264 
   9265     from_ent = SOC_ALPM_LPM_STATE_END(u, pfx);
   9266     to_ent = slot;
   9267     if (!ipv6) { /* IPV4 */
   9268         to_ent >>= 1;
   9269 #ifdef FB_LPM_TABLE_CACHED
   9270         if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm,
   9271                                            MEM_BLOCK_ANY, from_ent)) < 0) {
   9272             goto clean_up;
   9273         }
   9274 #endif /* FB_LPM_TABLE_CACHED */
   9275         if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm,
   9276                                      MEM_BLOCK_ANY, from_ent, ef)) < 0) {
   9277             goto clean_up;
   9278         }
   9279         if (SOC_URPF_STATUS_GET(u)) {
   9280             SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm,
   9281                                                    MEM_BLOCK_ANY,
   9282                                                    from_ent + src_tcam_offset,
   9283                                                    ef_urpf));
   9284             src_default = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef_urpf, RPE0f) |
   9285                           (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef_urpf, RPE1f) << 1);
   9286             src_discard = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef_urpf, SRC_DISCARD0f) |
   9287                           (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef_urpf, SRC_DISCARD1f) << 1);
   9288         }
   9289         et =  (to_ent == from_ent) ? ef : e;
   9290         upper_half =  SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef, VALID1f);
   9291         if (upper_half) {
   9292             if (slot & 1) {
   9293                 rv = soc_th_alpm_lpm_ip4entry1_to_1(u, ef, et, PRESERVE_HIT);
   9294             } else {
   9295                 rv = soc_th_alpm_lpm_ip4entry1_to_0(u, ef, et, PRESERVE_HIT);
   9296             }
   9297 #ifdef BCM_TOMAHAWK2_SUPPORT
   9298             if (soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
   9299                 SOC_ALPM_LPM_STATE_VENT(u, pfx) -= 1;
   9300                 SOC_ALPM_LPM_STATE_FENT(u, pfx) += 1;
   9301                 SOC_ALPM_LPM_STATE_END(u, pfx) -= 1;
   9302             }
   9303 #endif
   9304             src_pivot = (from_ent << 1) + 1;
   9305             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, ef, VALID1f, 0);
   9306         } else {
   9307             if (slot & 1) {
   9308                 rv = soc_th_alpm_lpm_ip4entry0_to_1(u, ef, et, PRESERVE_HIT);
   9309             } else {
   9310                 rv = soc_th_alpm_lpm_ip4entry0_to_0(u, ef, et, PRESERVE_HIT);
   9311             }
   9312             src_pivot = from_ent << 1;
   9313             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, ef, VALID0f, 0);
   9314             SOC_ALPM_LPM_STATE_VENT(u, pfx) -= 1;
   9315             SOC_ALPM_LPM_STATE_FENT(u, pfx) += 1;
   9316             SOC_ALPM_LPM_STATE_END(u, pfx) -= 1;
   9317         }
   9318 
   9319         src_pivot = soc_th_alpm_physical_idx(u, L3_DEFIPm, src_pivot, 0);
   9320         slot = soc_th_alpm_physical_idx(u, L3_DEFIPm, slot, 0);
   9321 
   9322        /* assert(ALPM_TCAM_PIVOT(u, slot) != 0); not true for OVERRIDE routes */
   9323         ALPM_TCAM_PIVOT(u, slot) = ALPM_TCAM_PIVOT(u, src_pivot);
   9324         if (ALPM_TCAM_PIVOT(u, slot)) {
   9325             PIVOT_TCAM_INDEX(ALPM_TCAM_PIVOT(u, slot)) = slot;
   9326             SOC_ALPM_BU_PIVOT_IDX_UPDATE(u, slot);
   9327         }
   9328         ALPM_TCAM_PIVOT(u, src_pivot) = NULL;
   9329 
   9330         if (ALPM_CTRL(u).aux_enable) {
   9331             /* get bpm_len of entry that is about to move */
   9332             SOC_IF_ERROR_RETURN(READ_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ANY,
   9333                 soc_th_alpm_physical_idx(u, L3_DEFIPm, from_ent, 1), sf));
   9334             SOC_IF_ERROR_RETURN(READ_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ANY,
   9335                 soc_th_alpm_physical_idx(u, L3_DEFIPm, to_ent, 1), st));
   9336 
   9337             if (upper_half) {
   9338                 bpm_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm,
   9339                                               sf, BPM_LENGTH1f);
   9340                 if (slot & 1) {
   9341                     soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, st,
   9342                                         BPM_LENGTH1f, bpm_len);
   9343                 } else {
   9344                     soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, st,
   9345                                         BPM_LENGTH0f, bpm_len);
   9346                 }
   9347             } else {
   9348                 bpm_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm,
   9349                                               sf, BPM_LENGTH0f);
   9350                 if (slot & 1) {
   9351                     soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, st,
   9352                                         BPM_LENGTH1f, bpm_len);
   9353                 } else {
   9354                     soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, st,
   9355                                         BPM_LENGTH0f, bpm_len);
   9356                 }
   9357             }
   9358 
   9359             /* update bpm_len at target */
   9360             SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ALL,
   9361                 soc_th_alpm_physical_idx(u, L3_DEFIPm, to_ent, 1), st));
   9362         }
   9363 
   9364         if (to_ent != from_ent) {
   9365             LPM_HASH_INSERT(u, et, to_ent, &rvt_index0, &rvt_index1);
   9366             rv = _soc_th_alpm_write_pivot(u, MEM_BLOCK_ANY, to_ent, to_ent,
   9367                                           et, src_default, src_discard);
   9368             if (rv < 0)
   9369             {
   9370                 LPM_HASH_REVERT(u, et, to_ent, rvt_index0, rvt_index1);
   9371                 goto clean_up;
   9372             }
   9373         }
   9374         LPM_HASH_INSERT(u, ef, from_ent, &rvt_index0, &rvt_index1);
   9375         if ((rv = _soc_th_alpm_write_pivot(u, MEM_BLOCK_ANY, from_ent, from_ent, ef, 0, 0)) < 0) {
   9376             LPM_HASH_REVERT(u, ef, from_ent, rvt_index0, rvt_index1);
   9377             goto clean_up;
   9378         }
   9379     } else { /* IPV6 */
   9380         SOC_ALPM_LPM_STATE_VENT(u, pfx) -= 1;
   9381         SOC_ALPM_LPM_STATE_FENT(u, pfx) += 1;
   9382         SOC_ALPM_LPM_STATE_END(u, pfx) -= 1;
   9383         if (to_ent != from_ent) {
   9384 #ifdef FB_LPM_TABLE_CACHED
   9385             if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm,
   9386                                                MEM_BLOCK_ANY, from_ent)) < 0) {
   9387                 goto clean_up;
   9388             }
   9389 #endif /* FB_LPM_TABLE_CACHED */
   9390             if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm,
   9391                                          MEM_BLOCK_ANY, from_ent, ef)) < 0) {
   9392                 goto clean_up;
   9393             }
   9394             if (SOC_URPF_STATUS_GET(u)) {
   9395                 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm,
   9396                                                        MEM_BLOCK_ANY,
   9397                                                        from_ent + src_tcam_offset,
   9398                                                        ef_urpf));
   9399                 src_default = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef_urpf, RPE0f) |
   9400                               (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef_urpf, RPE1f) << 1);
   9401                 src_discard = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef_urpf, SRC_DISCARD0f) |
   9402                               (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef_urpf, SRC_DISCARD1f) << 1);
   9403             }
   9404             LPM_HASH_INSERT(u, ef, to_ent, &rvt_index0, &rvt_index1);
   9405             rv = _soc_th_alpm_write_pivot(u, MEM_BLOCK_ANY, to_ent, from_ent,
   9406                                           ef, src_default, src_discard);
   9407             if (rv < 0)
   9408             {
   9409                 LPM_HASH_REVERT(u, ef, to_ent, rvt_index0, rvt_index1);
   9410                 goto clean_up;
   9411             }
   9412         }
   9413         /* v6-64 indices are still raw in pivot tcam */
   9414         /* tmp variables: */
   9415         slot = soc_th_alpm_physical_idx(u, L3_DEFIPm, to_ent, 1);
   9416         src_pivot = soc_th_alpm_physical_idx(u, L3_DEFIPm, from_ent, 1);
   9417         ALPM_TCAM_PIVOT(u, slot << 1) = ALPM_TCAM_PIVOT(u, src_pivot << 1);
   9418         ALPM_TCAM_PIVOT(u, src_pivot << 1) = NULL;
   9419         if (ALPM_TCAM_PIVOT(u, slot << 1)) {
   9420             PIVOT_TCAM_INDEX(ALPM_TCAM_PIVOT(u, slot << 1)) = slot << 1;
   9421             SOC_ALPM_BU_PIVOT_IDX_UPDATE(u, slot << 1);
   9422         }
   9423 
   9424         sal_memcpy(ef, soc_mem_entry_null(u, L3_DEFIPm),
   9425                    soc_mem_entry_words(u,L3_DEFIPm) * 4);
   9426         LPM_HASH_INSERT(u, ef, from_ent, &rvt_index0, &rvt_index1);
   9427         if ((rv = _soc_th_alpm_write_pivot(u, MEM_BLOCK_ANY, from_ent, from_ent, ef, 0, 0)) < 0) {
   9428             LPM_HASH_REVERT(u, ef, from_ent, rvt_index0, rvt_index1);
   9429             goto clean_up;
   9430         }
   9431     }
   9432 
   9433     if (SOC_ALPM_LPM_STATE_VENT(u, pfx) == 0) {
   9434         /* remove from the list */
   9435         prev_pfx = SOC_ALPM_LPM_STATE_PREV(u, pfx); /* Always present */
   9436         assert(prev_pfx != -1);
   9437         next_pfx = SOC_ALPM_LPM_STATE_NEXT(u, pfx);
   9438         SOC_ALPM_LPM_STATE_NEXT(u, prev_pfx) = next_pfx;
   9439         SOC_ALPM_LPM_STATE_FENT(u, prev_pfx) += SOC_ALPM_LPM_STATE_FENT(u, pfx);
   9440         SOC_ALPM_LPM_STATE_FENT(u, pfx) = 0;
   9441         if (next_pfx != -1) {
   9442             SOC_ALPM_LPM_STATE_PREV(u, next_pfx) = prev_pfx;
   9443         }
   9444         SOC_ALPM_LPM_STATE_NEXT(u, pfx) = -1;
   9445         SOC_ALPM_LPM_STATE_PREV(u, pfx) = -1;
   9446         SOC_ALPM_LPM_STATE_START(u, pfx) = -1;
   9447         SOC_ALPM_LPM_STATE_END(u, pfx) = -1;
   9448     }
   9449 clean_up:
   9450     if (ef) {
   9451         sal_free(ef);
   9452     }
   9453     if (ef_urpf) {
   9454         sal_free(ef_urpf);
   9455     }
   9456     if (sf) {
   9457         sal_free(sf);
   9458     }
   9459     if (st) {
   9460         sal_free(st);
   9461     }
   9462     return(rv);
   9463 }
   9464 
   9465 
   9466 
   9467 
   9468 /*
   9469  * Function:
   9470  *      soc_th_alpm_lpm_vrf_get
   9471  * Purpose:
   9472  *      Service routine used to translate hw specific vrf id to API format.
   9473  * Parameters:
   9474  *      unit      - (IN)SOC unit number.
   9475  *      lpm_entry - (IN)Route info buffer from hw.
   9476  *      vrf_id    - (OUT)Virtual router id.
   9477  * Returns:
   9478  *      BCM_E_XXX
   9479  */
   9480 int
   9481 soc_th_alpm_lpm_vrf_get(int unit, void *lpm_entry, int *vrf_id, int *vrf)
   9482 {
   9483     int mem_vrf;
   9484 
   9485     /* Get Virtual Router id if supported. */
   9486     if (SOC_MEM_OPT_FIELD_VALID(unit, L3_DEFIPm, VRF_ID_MASK0f)){
   9487         mem_vrf = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VRF_ID_0f);
   9488 
   9489         /* Special vrf's handling. */
   9490         if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f)) {
   9491             *vrf_id = mem_vrf;
   9492         } else if (!SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry,
   9493                                                     GLOBAL_HIGH0f)) {
   9494             *vrf_id = SOC_L3_VRF_GLOBAL;
   9495         } else {
   9496             *vrf_id = SOC_L3_VRF_OVERRIDE;
   9497         }
   9498         if (vrf) {
   9499             if (*vrf_id == SOC_L3_VRF_GLOBAL) {
   9500                 *vrf = SOC_VRF_MAX(unit) + 1;
   9501             } else {
   9502                 *vrf = mem_vrf;
   9503             }
   9504         }
   9505     } else {
   9506         /* No vrf support on this device. */
   9507         *vrf_id = SOC_L3_VRF_DEFAULT;
   9508     }
   9509     return (SOC_E_NONE);
   9510 }
   9511 
   9512 /*
   9513  * _soc_th_alpm_lpm_prefix_length_get (Extract vrf weighted
   9514  * prefix lenght from the hw entry based on ip, mask & vrf)
   9515  */
   9516 static int
   9517 _soc_th_alpm_lpm_prefix_length_get(int u, int ipv6, void *entry, int *pfx_len,
   9518                                    int *vrf_id, int *vrf)
   9519 {
   9520     int         pfx;
   9521     int         rv;
   9522     uint32      ipv4a;
   9523     int         vrfid;
   9524     int         mode;
   9525 
   9526     if (ipv6) {
   9527         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f);
   9528         if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
   9529             return(rv);
   9530         }
   9531         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK1f);
   9532         if (pfx) {
   9533             if (ipv4a != 0xffffffff)  {
   9534                 return(SOC_E_PARAM);
   9535             }
   9536             pfx += 32;
   9537         } else {
   9538             if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
   9539                 return(rv);
   9540             }
   9541         }
   9542         pfx += ALPM_IPV6_PFX_ZERO; /* First 33 are for IPV4 addresses */
   9543     } else {
   9544         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f);
   9545         if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
   9546             return(rv);
   9547         }
   9548     }
   9549 
   9550     SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(u, entry, &vrfid, &rv));
   9551     if (vrf_id != NULL) {
   9552         *vrf_id = vrfid;
   9553     }
   9554     if (vrf != NULL) {
   9555         *vrf = rv;
   9556     }
   9557 
   9558     /* In ALPM the arragnement of VRF is at he begining followed by VRF
   9559      * override and global */
   9560     mode = ALPM_CTRL(u).alpm_mode;
   9561     switch (vrfid) {
   9562       case SOC_L3_VRF_GLOBAL:
   9563           if ((mode == SOC_ALPM_MODE_PARALLEL) || (mode == SOC_ALPM_MODE_TCAM_ALPM)) {
   9564             *pfx_len = pfx + (ALPM_MAX_PFX_ENTRIES / 3);
   9565           } else {
   9566             *pfx_len = pfx;
   9567           }
   9568           break;
   9569       case SOC_L3_VRF_OVERRIDE:
   9570             *pfx_len = pfx +  2 * (ALPM_MAX_PFX_ENTRIES / 3);
   9571           break;
   9572       default:
   9573           if ((mode == SOC_ALPM_MODE_PARALLEL) || (mode == SOC_ALPM_MODE_TCAM_ALPM)) {
   9574             *pfx_len = pfx;
   9575           } else {
   9576             *pfx_len = pfx +  (ALPM_MAX_PFX_ENTRIES / 3);
   9577           }
   9578           break;
   9579     }
   9580     return (SOC_E_NONE);
   9581 }
   9582 
   9583 /*
   9584  * _soc_th_alpm_lpm_match (Exact match for the key. Will match both IP address
   9585  * and mask)
   9586  */
   9587 static int
   9588 _soc_th_alpm_lpm_match(int u,
   9589                void *key_data,
   9590                void *e,         /* return entry data if found */
   9591                int *index_ptr,  /* return key location */
   9592                int *pfx_len,    /* Key prefix length. vrf + 32 + prefix len for IPV6*/
   9593                int *ipv6,       /* Entry is ipv6. */
   9594                int *vrf_id,     /* (OUT) */
   9595                int *vrf)        /* (OUT) */
   9596 {
   9597     int         rv;
   9598     int         v6;
   9599     int         key_index;
   9600     int         pfx = 0;
   9601 
   9602     v6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0_f(u));
   9603     if (v6) {
   9604         if (!(v6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE1_f(u)))) {
   9605             return (SOC_E_PARAM);
   9606         }
   9607     }
   9608     *ipv6 = v6;
   9609 
   9610     /* Calculate vrf weighted prefix lengh. */
   9611     _soc_th_alpm_lpm_prefix_length_get(u, v6, key_data, &pfx, vrf_id, vrf);
   9612     *pfx_len = pfx;
   9613 
   9614 #ifdef FB_LPM_HASH_SUPPORT
   9615     if (LPM_HASH_LOOKUP(u, key_data, pfx, &key_index) == SOC_E_NONE) {
   9616         *index_ptr = key_index;
   9617         if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY,
   9618                          (*ipv6) ? *index_ptr : (*index_ptr >> 1), e)) < 0) {
   9619             return rv;
   9620         }
   9621 #ifndef  FB_LPM_CHECKER_ENABLE
   9622         return(SOC_E_NONE);
   9623 #endif
   9624     } else {
   9625 #ifndef  FB_LPM_CHECKER_ENABLE
   9626         return(SOC_E_NOT_FOUND);
   9627 #endif
   9628     }
   9629 #endif /* FB_LPM_HASH_SUPPORT */
   9630 }
   9631 
   9632 STATIC int
   9633 soc_alpm_key_sel_reg_init(int u)
   9634 {
   9635     int i, urpf_enb, lpm_128b;
   9636     soc_reg_t kselr = L3_DEFIP_KEY_SELr;
   9637     uint32 rval = 0;
   9638     soc_field_t pcamf[4] = {
   9639         INVALIDf,
   9640         INVALIDf,
   9641         INVALIDf,
   9642         INVALIDf
   9643     };
   9644 
   9645     /* URPF[bit1], 128B[bit0] */
   9646     int key_sel[4] = {
   9647         2,  /* 0x00b non-URPF + lpm-64b     */
   9648         0,  /* 0x01b non-URPF + lpm-128b    */
   9649         3,  /* 0x10b uRPF + lpm-64b         */
   9650         1   /* 0x11b uRPF + lpm-128b        */
   9651     };
   9652 
   9653     urpf_enb = !!SOC_URPF_STATUS_GET(u);
   9654     lpm_128b = !!SOC_ALPM_128B_ENABLE(u);
   9655 
   9656     if (soc_reg_field_valid(u, kselr, KEY_SEL_CAM0_1f)) {
   9657         i = lpm_128b;
   9658         soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM0_1f, key_sel[i]);
   9659         soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM2_3f, key_sel[i]);
   9660         soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM4_5f, key_sel[i]);
   9661         soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM6_7f, key_sel[i]);
   9662         if (urpf_enb) {
   9663             i = (urpf_enb << 1) | lpm_128b;
   9664             soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM4_5f, key_sel[i]);
   9665             soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM6_7f, key_sel[i]);
   9666         }
   9667     } else {
   9668         if (urpf_enb) {
   9669             soc_reg_field_set(u, kselr, &rval, URPF_LOOKUP_CAM4f, 0x1);
   9670             soc_reg_field_set(u, kselr, &rval, URPF_LOOKUP_CAM5f, 0x1);
   9671             soc_reg_field_set(u, kselr, &rval, URPF_LOOKUP_CAM6f, 0x1);
   9672             soc_reg_field_set(u, kselr, &rval, URPF_LOOKUP_CAM7f, 0x1);
   9673         }
   9674     }
   9675     if (lpm_128b) {
   9676         if (soc_reg_field_valid(u, kselr, V6_KEY_SEL_CAM0_1f)) {
   9677             pcamf[0] = V6_KEY_SEL_CAM0_1f;
   9678             pcamf[1] = V6_KEY_SEL_CAM2_3f;
   9679             pcamf[2] = V6_KEY_SEL_CAM4_5f;
   9680             pcamf[3] = V6_KEY_SEL_CAM6_7f;
   9681         }
   9682         /* Supports mixed IPv4, IPv6 128 bit prefix IPv6 routes.
   9683          * upto 16K IPv4 pivots only or
   9684          * upto 2K 128 bit IPv6 and upto 8k v4 pivots, or */
   9685         /* all tcams in paired mode */
   9686         for (i = 0; i < 4; i++) {
   9687             if (pcamf[i] != INVALIDf) {
   9688                 soc_reg_field_set(u, kselr, &rval, pcamf[i], 0x1);
   9689             }
   9690         }
   9691     }
   9692     SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_KEY_SELr(u, rval));
   9693     return SOC_E_NONE;
   9694 }
   9695 
   9696 STATIC int
   9697 soc_alpm_cfg_reg_init(int u)
   9698 {
   9699     soc_reg_t creg = L3_DEFIP_ALPM_CFGr;
   9700     uint32 rval = 0;
   9701     if (ALPM_CTRL(u).gp_zoned) {
   9702         if (SOC_URPF_STATUS_GET(u)) {
   9703             /* 4 DIPs, 4 SIPs */
   9704             if (soc_reg_field_valid(u, creg, CAM0_1_SELf)) {
   9705                 /* *DIP */
   9706                 soc_reg_field_set(u, creg, &rval, CAM2_3_SELf, 1);
   9707                 /* VRF SIP */
   9708                 soc_reg_field_set(u, creg, &rval, CAM4_5_SELf, 2);
   9709                 /* *SIP */
   9710                 soc_reg_field_set(u, creg, &rval, CAM6_7_SELf, 3);
   9711             } else {
   9712                 /* *DIP */
   9713                 soc_reg_field_set(u, creg, &rval, TCAM2_SELf, 1);
   9714                 soc_reg_field_set(u, creg, &rval, TCAM3_SELf, 1);
   9715                 /* VRF SIP */
   9716                 soc_reg_field_set(u, creg, &rval, TCAM4_SELf, 2);
   9717                 soc_reg_field_set(u, creg, &rval, TCAM5_SELf, 2);
   9718                 /* *SIP */
   9719                 soc_reg_field_set(u, creg, &rval, TCAM6_SELf, 3);
   9720                 soc_reg_field_set(u, creg, &rval, TCAM7_SELf, 3);
   9721             }
   9722         } else {
   9723             if (soc_reg_field_valid(u, creg, CAM0_1_SELf)) {
   9724                 soc_reg_field_set(u, creg, &rval, CAM4_5_SELf, 1);
   9725                 soc_reg_field_set(u, creg, &rval, CAM6_7_SELf, 1);
   9726             } else {
   9727                 soc_reg_field_set(u, creg, &rval, TCAM4_SELf, 1);
   9728                 soc_reg_field_set(u, creg, &rval, TCAM5_SELf, 1);
   9729                 soc_reg_field_set(u, creg, &rval, TCAM6_SELf, 1);
   9730                 soc_reg_field_set(u, creg, &rval, TCAM7_SELf, 1);
   9731             }
   9732         }
   9733     } else {
   9734         if (SOC_URPF_STATUS_GET(u)) {
   9735             /* 4 DIPs, 4 SIPs */
   9736             if (soc_reg_field_valid(u, creg, CAM0_1_SELf)) {
   9737                 soc_reg_field_set(u, creg, &rval, CAM4_5_SELf, 2);
   9738                 soc_reg_field_set(u, creg, &rval, CAM6_7_SELf, 2);
   9739             } else {
   9740                 /* DIP */
   9741                 /* VRF SIP */
   9742                 soc_reg_field_set(u, creg, &rval, TCAM4_SELf, 2);
   9743                 soc_reg_field_set(u, creg, &rval, TCAM5_SELf, 2);
   9744                 soc_reg_field_set(u, creg, &rval, TCAM6_SELf, 2);
   9745                 soc_reg_field_set(u, creg, &rval, TCAM7_SELf, 2);
   9746             }
   9747         }
   9748     }
   9749     SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_ALPM_CFGr(u, rval));
   9750 
   9751     return SOC_E_NONE;
   9752 }
   9753 
   9754 /*
   9755  * Initialize the start/end tracking pointers for each prefix length
   9756  */
   9757 static int
   9758 soc_th_alpm_lpm_init(int u)
   9759 {
   9760     int max_pfx_len;
   9761     int i;
   9762     int defip_table_size;
   9763     int pfx_state_size;
   9764     uint32 rval, mode;
   9765 #define _ALPM_MODE_PARALLEL 1
   9766 #define _ALPM_MODE_COMBINED 2
   9767 #define _ALPM_MODE_TCAM_ALPM 3
   9768 
   9769     if (! soc_feature(u, soc_feature_lpm_tcam)) {
   9770         return(SOC_E_UNAVAIL);
   9771     }
   9772 
   9773     mode = ALPM_CTRL(u).alpm_mode;
   9774     if (mode != SOC_ALPM_MODE_INVALID) {
   9775         /* Set DEFIP mode to ALPM */
   9776         SOC_IF_ERROR_RETURN(READ_L3_DEFIP_RPF_CONTROLr(u, &rval));
   9777         soc_reg_field_set(u, L3_DEFIP_RPF_CONTROLr, &rval, LPM_MODEf, 1);
   9778         if (mode == SOC_ALPM_MODE_PARALLEL) {
   9779             /* Parallel mode */
   9780             soc_reg_field_set(u, L3_DEFIP_RPF_CONTROLr, &rval, LOOKUP_MODEf, 1);
   9781         } else if (mode == SOC_ALPM_MODE_COMBINED) {
   9782             /* Combined search mode */
   9783             soc_reg_field_set(u, L3_DEFIP_RPF_CONTROLr, &rval, LOOKUP_MODEf, 0);
   9784             l3_alpm_ipv4_double_wide[u] = soc_property_get(u, "l3_alpm_ipv4_double_wide", 1);
   9785             if (l3_alpm_ipv4_double_wide[u]) {
   9786                 if (SOC_REG_FIELD_VALID(u, L3_DEFIP_RPF_CONTROLr,
   9787                                         ENABLE_DOUBLE_WIDE_BUCKETS_FOR_IPV4f)) {
   9788                     soc_reg_field_set(u, L3_DEFIP_RPF_CONTROLr, &rval,
   9789                                       ENABLE_DOUBLE_WIDE_BUCKETS_FOR_IPV4f, 1);
   9790                 }
   9791             }
   9792         } else if (mode == SOC_ALPM_MODE_TCAM_ALPM) {
   9793             /* TCAM_ALPM search mode */
   9794             l3_alpm_ipv4_double_wide[u] = 1;
   9795             soc_reg_field_set(u, L3_DEFIP_RPF_CONTROLr, &rval, LOOKUP_MODEf, 2);
   9796         }
   9797         SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_RPF_CONTROLr(u, rval));
   9798 
   9799         SOC_IF_ERROR_RETURN(soc_alpm_key_sel_reg_init(u));
   9800         SOC_IF_ERROR_RETURN(soc_alpm_cfg_reg_init(u));
   9801     }
   9802 
   9803     max_pfx_len = ALPM_MAX_PFX_ENTRIES;
   9804 
   9805     SOC_ALPM_LPM_LOCK(u);
   9806     pfx_state_size = sizeof(soc_th_alpm_lpm_state_t) * (max_pfx_len);
   9807 
   9808     soc_lpm_field_cache_state[u] =
   9809                 sal_alloc(sizeof(soc_th_lpm_field_cache_t), "lpm_field_state");
   9810     if (NULL == soc_lpm_field_cache_state[u]) {
   9811         SOC_ALPM_LPM_UNLOCK(u);
   9812         return (SOC_E_MEMORY);
   9813     }
   9814     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9815                                     CLASS_ID0f);
   9816     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9817                                     CLASS_ID1f);
   9818     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9819                                     DST_DISCARD0f);
   9820     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9821                                     DST_DISCARD1f);
   9822     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9823                                     ECMP0f);
   9824     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9825                                     ECMP1f);
   9826     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9827                                     ECMP_COUNT0f);
   9828     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9829                                     ECMP_COUNT1f);
   9830     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9831                                     ECMP_PTR0f);
   9832     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9833                                     ECMP_PTR1f);
   9834     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9835                                     GLOBAL_ROUTE0f);
   9836     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9837                                     GLOBAL_ROUTE1f);
   9838     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9839                                     MULTICAST_ROUTE0f);
   9840     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9841                                     MULTICAST_ROUTE1f);
   9842     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9843                                     RPA_ID0f);
   9844     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9845                                     RPA_ID1f);
   9846     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9847                                     EXPECTED_L3_IIF0f);
   9848     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9849                                     EXPECTED_L3_IIF1f);
   9850     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9851                                     IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f);
   9852     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9853                                     IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f);
   9854     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9855                                     IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f);
   9856     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9857                                     IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f);
   9858     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9859                                     L3MC_INDEX0f);
   9860     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9861                                     L3MC_INDEX1f);
   9862     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9863                                     HIT0f);
   9864     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9865                                     HIT1f);
   9866     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9867                                     IP_ADDR0f);
   9868     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9869                                     IP_ADDR1f);
   9870     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9871                                     IP_ADDR_MASK0f);
   9872     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9873                                     IP_ADDR_MASK1f);
   9874     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9875                                     NEXT_HOP_INDEX0f);
   9876     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9877                                     NEXT_HOP_INDEX1f);
   9878     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9879                                     PRI0f);
   9880     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9881                                     PRI1f);
   9882     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9883                                     RPE0f);
   9884     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9885                                     RPE1f);
   9886     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9887                                     VALID0f);
   9888     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9889                                     VALID1f);
   9890     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9891                                     VRF_ID_0f);
   9892     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9893                                     VRF_ID_1f);
   9894     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9895                                     VRF_ID_MASK0f);
   9896     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9897                                     VRF_ID_MASK1f);
   9898     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9899                                     GLOBAL_HIGH0f);
   9900     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9901                                     GLOBAL_HIGH1f);
   9902     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9903                                     ALG_HIT_IDX0f);
   9904     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9905                                     ALG_HIT_IDX1f);
   9906     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9907                                     ALG_BKT_PTR0f);
   9908     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9909                                     ALG_BKT_PTR1f);
   9910     if (ALPM_CTRL(u).bkt_sharing) {
   9911         SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9912                                         ALG_SUB_BKT_PTR0f);
   9913         SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9914                                         ALG_SUB_BKT_PTR1f);
   9915     }
   9916     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9917                                     DEFAULT_MISS0f);
   9918     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9919                                     DEFAULT_MISS1f);
   9920     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9921                                     FLEX_CTR_BASE_COUNTER_IDX0f);
   9922     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9923                                     FLEX_CTR_BASE_COUNTER_IDX1f);
   9924     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9925                                     FLEX_CTR_POOL_NUMBER0f);
   9926     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9927                                     FLEX_CTR_POOL_NUMBER1f);
   9928     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9929                                     FLEX_CTR_OFFSET_MODE0f);
   9930     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9931                                     FLEX_CTR_OFFSET_MODE1f);
   9932     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9933                                     SRC_DISCARD0f);
   9934     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9935                                     SRC_DISCARD1f);
   9936     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9937                                     ENTRY_VIEW0f);
   9938     SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm,
   9939                                     ENTRY_VIEW1f);
   9940 
   9941     if (soc_feature(u, soc_feature_generic_dest)) {
   9942         SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u],
   9943             L3_DEFIPm, DESTINATION0f);
   9944         SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u],
   9945             L3_DEFIPm, DESTINATION1f);
   9946     }
   9947 
   9948     SOC_ALPM_LPM_STATE(u) = sal_alloc(pfx_state_size, "LPM prefix info");
   9949     if (NULL == SOC_ALPM_LPM_STATE(u)) {
   9950         sal_free(soc_lpm_field_cache_state[u]);
   9951         soc_lpm_field_cache_state[u] = NULL;
   9952         SOC_ALPM_LPM_UNLOCK(u);
   9953         return (SOC_E_MEMORY);
   9954     }
   9955 
   9956 #ifdef FB_LPM_TABLE_CACHED
   9957     rv = soc_mem_cache_set(u, L3_DEFIPm, MEM_BLOCK_ALL, TRUE);
   9958     if (SOC_FAILURE(rv)) {
   9959         SOC_ALPM_LPM_UNLOCK(u);
   9960         return rv;
   9961     }
   9962 #endif /* FB_LPM_TABLE_CACHED */
   9963 
   9964     sal_memset(SOC_ALPM_LPM_STATE(u), 0, pfx_state_size);
   9965     for(i = 0; i < max_pfx_len; i++) {
   9966         SOC_ALPM_LPM_STATE_START(u, i) = -1;
   9967         SOC_ALPM_LPM_STATE_END(u, i) = -1;
   9968         SOC_ALPM_LPM_STATE_PREV(u, i) = -1;
   9969         SOC_ALPM_LPM_STATE_NEXT(u, i) = -1;
   9970         SOC_ALPM_LPM_STATE_VENT(u, i) = 0;
   9971         SOC_ALPM_LPM_STATE_FENT(u, i) = 0;
   9972     }
   9973 
   9974     defip_table_size = soc_mem_index_count(u, L3_DEFIPm);
   9975 
   9976     /* RPF supported, then the table is partitioned for DIP and SIP */
   9977     if (SOC_URPF_STATUS_GET(u)) {
   9978         defip_table_size >>= 1;
   9979     }
   9980 
   9981     if (ALPM_CTRL(u).gp_zoned) {
   9982         /* For Parallel search, the TCAM is hard paritioned.
   9983         * First half are for VRF specific, the bottom half for override and
   9984         * global. Start of Global entries start at the bottom half of TCAM
   9985         */
   9986         SOC_ALPM_LPM_STATE_END(u, ALPM_MAX_PFX_INDEX) = (defip_table_size>>1) - 1;
   9987 
   9988         /* Free entries for VRF */
   9989         SOC_ALPM_LPM_STATE_FENT(u, (ALPM_MAX_VRF_PFX_INDEX)) = defip_table_size >> 1;
   9990 
   9991         /* Remaining entries are assigned to Global entries */
   9992         SOC_ALPM_LPM_STATE_FENT(u, (ALPM_MAX_PFX_INDEX)) =
   9993           (defip_table_size - SOC_ALPM_LPM_STATE_FENT(u, (ALPM_MAX_VRF_PFX_INDEX)));
   9994     } else {
   9995         /* Remaining entries are assigned to Global entries */
   9996         SOC_ALPM_LPM_STATE_FENT(u, (ALPM_MAX_PFX_INDEX)) = defip_table_size;
   9997     }
   9998 
   9999     if (SOC_ALPM_LPM_STATE_HASH(u) != NULL) {
  10000         if (_soc_th_alpm_lpm_hash_destroy(SOC_ALPM_LPM_STATE_HASH(u)) < 0) {
  10001             SOC_ALPM_LPM_UNLOCK(u);
  10002             return SOC_E_INTERNAL;
  10003         }
  10004         SOC_ALPM_LPM_STATE_HASH(u) = NULL;
  10005     }
  10006 
  10007     if (_soc_th_alpm_lpm_hash_create(u, defip_table_size * 2, defip_table_size,
  10008                                      &SOC_ALPM_LPM_STATE_HASH(u)) < 0) {
  10009         SOC_ALPM_LPM_UNLOCK(u);
  10010         return SOC_E_MEMORY;
  10011     }
  10012 
  10013     SOC_ALPM_LPM_UNLOCK(u);
  10014 
  10015     return(SOC_E_NONE);
  10016 }
  10017 
  10018 /*
  10019  * De-initialize the start/end tracking pointers for each prefix length
  10020  */
  10021 static int
  10022 soc_th_alpm_lpm_deinit(int u)
  10023 {
  10024     if (!soc_feature(u, soc_feature_lpm_tcam)) {
  10025         return(SOC_E_UNAVAIL);
  10026     }
  10027 
  10028     SOC_ALPM_LPM_LOCK(u);
  10029 
  10030     if (SOC_ALPM_LPM_STATE_HASH(u) != NULL) {
  10031         _soc_th_alpm_lpm_hash_destroy(SOC_ALPM_LPM_STATE_HASH(u));
  10032         SOC_ALPM_LPM_STATE_HASH(u) = NULL;
  10033     }
  10034 
  10035     if (SOC_ALPM_LPM_INIT_CHECK(u)) {
  10036         sal_free(soc_lpm_field_cache_state[u]);
  10037         soc_lpm_field_cache_state[u] = NULL;
  10038         sal_free(SOC_ALPM_LPM_STATE(u));
  10039         SOC_ALPM_LPM_STATE(u) = NULL;
  10040     }
  10041 
  10042     SOC_ALPM_LPM_UNLOCK(u);
  10043 
  10044     return(SOC_E_NONE);
  10045 }
  10046 
  10047 /*
  10048  * Implementation using soc_mem_read/write using entry rippling technique
  10049  * Advantage: A completely sorted table is not required. Lookups can be slow
  10050  * as it will perform a linear search on the entries for a given prefix length.
  10051  * No device access necessary for the search if the table is cached. Auxiliary
  10052  * hash table can be maintained to speed up search(Not implemented) instead of
  10053  * performing a linear search.
  10054  * Small number of entries need to be moved around (97 worst case)
  10055  * for performing insert/update/delete. However CPU needs to do all
  10056  * the work to move the entries.
  10057  */
  10058 
  10059 /*
  10060  * soc_th_alpm_lpm_insert
  10061  * For IPV4 assume only both IP_ADDR0 is valid
  10062  * Moving multiple entries around in h/w vs  doing a linear search in s/w
  10063  */
  10064 static int
  10065 soc_th_alpm_lpm_insert(int u, void *entry_data, int *lpm_index, int bpm_len,
  10066                       int src_default, int src_discard)
  10067 {
  10068     int         pfx;
  10069     int         index, v4_half = 0;
  10070     int         ipv6;
  10071     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
  10072     int         rv = SOC_E_NONE;
  10073     int         found = 0;
  10074     uint32      rvt_index0 = 0, rvt_index1 = 0;
  10075     int         vrf, vrf_id;
  10076 
  10077     sal_memcpy(e, soc_mem_entry_null(u, L3_DEFIPm),
  10078                soc_mem_entry_words(u,L3_DEFIPm) * 4);
  10079 
  10080     SOC_ALPM_LPM_LOCK(u);
  10081     rv = _soc_th_alpm_lpm_match(u, entry_data, e, &index, &pfx, &ipv6, &vrf_id, &vrf);
  10082     if (rv == SOC_E_NOT_FOUND) {
  10083         rv = _lpm_free_slot_create(u, pfx, ipv6, e, &index);
  10084         if (rv < 0) {
  10085             SOC_ALPM_LPM_UNLOCK(u);
  10086             return(rv);
  10087         }
  10088     } else {
  10089         found = 1;
  10090     }
  10091 
  10092     *lpm_index = index;
  10093 
  10094     if (rv == SOC_E_NONE) {
  10095         /* Entry already present. Update the entry */
  10096         if (!ipv6) {
  10097             /* IPV4 entry */
  10098             if (index & 1) {
  10099                 rv = soc_th_alpm_lpm_ip4entry0_to_1(u, entry_data, e,
  10100                                                  PRESERVE_HIT);
  10101                 v4_half = 3;
  10102             } else {
  10103                 rv = soc_th_alpm_lpm_ip4entry0_to_0(u, entry_data, e,
  10104                                                  PRESERVE_HIT);
  10105                 v4_half = 2;
  10106             }
  10107 
  10108             if (rv < 0) {
  10109                 SOC_ALPM_LPM_UNLOCK(u);
  10110                 return(rv);
  10111             }
  10112             entry_data = (void *)e;
  10113             index >>= 1;
  10114         }
  10115         soc_th_alpm_lpm_state_dump(u);
  10116         LOG_VERBOSE(BSL_LS_SOC_ALPM,
  10117                     (BSL_META_U(u,
  10118                              "soc_alpm_lpm_insert: %d %d\n"),
  10119                              index, pfx));
  10120 
  10121         if (!found) {
  10122             LPM_HASH_INSERT(u, entry_data, index, &rvt_index0, &rvt_index1);
  10123         }
  10124         rv = _soc_th_alpm_write_pivot_with_bpm(u, MEM_BLOCK_ANY, index, index,
  10125                                                entry_data, bpm_len, v4_half,
  10126                                                src_default, src_discard);
  10127         if (!found) {
  10128             if (SOC_SUCCESS(rv)) {
  10129                 VRF_PIVOT_REF_INC(u, vrf_id, vrf, ipv6);
  10130             } else {
  10131                 LPM_HASH_REVERT(u, entry_data, index, rvt_index0, rvt_index1);
  10132             }
  10133         }
  10134     }
  10135 
  10136     SOC_ALPM_LPM_UNLOCK(u);
  10137 
  10138     return(rv);
  10139 }
  10140 
  10141 /*
  10142  * soc_th_alpm_lpm_delete
  10143  */
  10144 static int
  10145 soc_th_alpm_lpm_delete(int u, void *key_data)
  10146 {
  10147     int         pfx;
  10148     int         index;
  10149     int         ipv6;
  10150     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
  10151     int         rv = SOC_E_NONE;
  10152     int         vrf, vrf_id;
  10153 
  10154     SOC_ALPM_LPM_LOCK(u);
  10155     rv = _soc_th_alpm_lpm_match(u, key_data, e, &index, &pfx, &ipv6, &vrf_id, &vrf);
  10156     if (rv == SOC_E_NONE) {
  10157         LOG_VERBOSE(BSL_LS_SOC_ALPM,
  10158                     (BSL_META_U(u,
  10159                     "soc_alpm_lpm_delete: %d %d\n"),
  10160                     index, pfx));
  10161         LPM_HASH_DELETE(u, key_data, index);
  10162         rv = _lpm_free_slot_delete(u, pfx, ipv6, e, index);
  10163     }
  10164     if (SOC_SUCCESS(rv)) {
  10165         VRF_PIVOT_REF_DEC(u, vrf_id, vrf, ipv6);
  10166     }
  10167     soc_th_alpm_lpm_state_dump(u);
  10168     SOC_ALPM_LPM_UNLOCK(u);
  10169 
  10170     return(rv);
  10171 }
  10172 
  10173 /*
  10174  * soc_th_alpm_lpm_match (Exact match for the key. Will match both IP
  10175  *                   address and mask)
  10176  */
  10177 static int
  10178 soc_th_alpm_lpm_match(int u,
  10179                void *key_data,
  10180                void *e,         /* return entry data if found */
  10181                int *index_ptr)  /* return key location */
  10182 {
  10183     int        pfx;
  10184     int        rv;
  10185     int        ipv6;
  10186 
  10187     SOC_ALPM_LPM_LOCK(u);
  10188     rv = _soc_th_alpm_lpm_match(u, key_data, e, index_ptr, &pfx, &ipv6, 0, 0);
  10189     SOC_ALPM_LPM_UNLOCK(u);
  10190     return(rv);
  10191 }
  10192 
  10193 
  10194 /* Fill Aux entry for operation */
  10195 static int
  10196 _soc_th_alpm_fill_aux_entry_for_op(int u,
  10197                void *key_data,
  10198                int ipv6,    /* Entry is ipv6. */
  10199                int db_type, /* database type */
  10200                int ent_type,
  10201                int replace_len, /* used for DElete propagate */
  10202                defip_aux_scratch_entry_t *aux_entry)
  10203 {
  10204     uint32 ipv4a;
  10205     uint32 ip6_word[4] = {0, 0, 0, 0};
  10206     int    pfx = 0;
  10207     int    rv = SOC_E_NONE;
  10208 
  10209     sal_memset(aux_entry, 0, sizeof(defip_aux_scratch_entry_t));
  10210     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, VALID0f);
  10211     soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, VALIDf, ipv4a);
  10212 
  10213     ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0_f(u));
  10214     soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, MODE_f(u), ipv4a);
  10215 
  10216     ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, ENTRY_TYPE0_f(u));
  10217     soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, ENTRY_TYPE_f(u), ent_type);
  10218 
  10219     if (SOC_IS_TRIDENT3X(u)) {
  10220         ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, DATA_TYPE0f);
  10221         soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, DATA_TYPEf, ipv4a);
  10222     }
  10223 
  10224     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, GLOBAL_ROUTE0f);
  10225     soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, GLOBAL_ROUTEf, ipv4a);
  10226 
  10227     if (soc_feature(u, soc_feature_ipmc_defip)) {
  10228         ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, RPA_ID0f);
  10229         soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, RPA_IDf, ipv4a);
  10230 
  10231         ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, EXPECTED_L3_IIF0f);
  10232         soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, EXPECTED_L3_IIFf, ipv4a);
  10233 
  10234         ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f);
  10235         soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf, ipv4a);
  10236 
  10237         ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f);
  10238         soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf, ipv4a);
  10239 
  10240         if (soc_mem_field_valid(u, L3_DEFIPm, L3MC_INDEX0f)) {
  10241             ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, L3MC_INDEX0f);
  10242             soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, L3MC_INDEXf, ipv4a);
  10243         }
  10244     }
  10245 
  10246     if (soc_feature(u, soc_feature_generic_dest)) {
  10247         ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, DESTINATION0f);
  10248         soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry,
  10249                             DESTINATIONf, ipv4a);
  10250     } else {
  10251         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, ECMP0f);
  10252         soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, ECMPf, ipv4a);
  10253 
  10254         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, ECMP_PTR0f);
  10255         soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, ECMP_PTRf, ipv4a);
  10256 
  10257         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, NEXT_HOP_INDEX0f);
  10258         soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, NEXT_HOP_INDEXf, ipv4a);
  10259     }
  10260 
  10261     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, PRI0f);
  10262     soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, PRIf, ipv4a);
  10263 
  10264     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, RPE0f);
  10265     soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, RPEf, ipv4a);
  10266 
  10267     ipv4a =SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, VRF_ID_0f);
  10268     soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, VRFf, ipv4a);
  10269 
  10270     /* Set Database type */
  10271     soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, DB_TYPEf, db_type);
  10272 
  10273     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, DST_DISCARD0f);
  10274     soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, DST_DISCARDf, ipv4a);
  10275 
  10276     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, CLASS_ID0f);
  10277     soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, CLASS_IDf, ipv4a);
  10278 
  10279 
  10280     /* Set IP Address and IP length */
  10281     if (ipv6) {
  10282         ip6_word[2] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, IP_ADDR0f);
  10283         ip6_word[3] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, IP_ADDR1f);
  10284     } else {
  10285         ip6_word[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, IP_ADDR0f);
  10286     }
  10287     soc_mem_field_set(u, L3_DEFIP_AUX_SCRATCHm, (uint32*)aux_entry,
  10288                       IP_ADDRf, (uint32*)ip6_word);
  10289 
  10290     if (ipv6) {
  10291         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, IP_ADDR_MASK0f);
  10292         if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
  10293             return(rv);
  10294         }
  10295         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, IP_ADDR_MASK1f);
  10296         if (pfx) {
  10297             if (ipv4a != 0xffffffff)  {
  10298                 return(SOC_E_PARAM);
  10299             }
  10300             pfx += 32;
  10301         } else {
  10302             if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
  10303                 return(rv);
  10304             }
  10305         }
  10306     } else {
  10307         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, IP_ADDR_MASK0f);
  10308         if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
  10309             return(rv);
  10310         }
  10311     }
  10312     soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, IP_LENGTHf, pfx);
  10313     soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, REPLACE_LENf,
  10314                         replace_len);
  10315 
  10316     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, FLEX_CTR_BASE_COUNTER_IDX0f);
  10317     soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, FLEX_CTR_BASE_COUNTER_IDXf, ipv4a);
  10318 
  10319     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, FLEX_CTR_OFFSET_MODE0f);
  10320     soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, FLEX_CTR_OFFSET_MODEf, ipv4a);
  10321 
  10322     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, FLEX_CTR_POOL_NUMBER0f);
  10323     soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, FLEX_CTR_POOL_NUMBERf, ipv4a);
  10324 
  10325     return (SOC_E_NONE);
  10326 }
  10327 
  10328 #define _SOC_ALPM_AUX_OP_RETRY_TO           1000000
  10329 #define _SOC_ALPM_AUX_OP_RETRY_COUNT        100
  10330 
  10331 /* Using binary search with DMA read to retrieve corrupted index */
  10332 int
  10333 _soc_th_alpm_aux_error_index(int u, int pipe, int *index, soc_mem_t *mem)
  10334 {
  10335     char *dmabuf = NULL;
  10336     soc_mem_t mem_to_search[2] = {L3_DEFIP_AUX_TABLEm, L3_DEFIP_DATA_ONLYm};
  10337     int min, max;
  10338     uint32 ser_flags;
  10339     int i = 0;
  10340     int found_index = FALSE;
  10341     int mem_wsz = 0;
  10342 
  10343     switch (pipe) {
  10344         case 0:
  10345             ser_flags = _SOC_MEM_ADDR_ACC_TYPE_PIPE_0;
  10346             break;
  10347         case 1:
  10348             ser_flags = _SOC_MEM_ADDR_ACC_TYPE_PIPE_1;
  10349             break;
  10350         case 2:
  10351             ser_flags = _SOC_MEM_ADDR_ACC_TYPE_PIPE_2;
  10352             break;
  10353         case 3:
  10354             ser_flags = _SOC_MEM_ADDR_ACC_TYPE_PIPE_3;
  10355             break;
  10356         default:
  10357             ser_flags = _SOC_MEM_ADDR_ACC_TYPE_PIPE_0;
  10358             break;
  10359     }
  10360 
  10361     ser_flags |= _SOC_SER_FLAG_DMA_ERR_RETURN;
  10362     ser_flags |= _SOC_SER_FLAG_DISCARD_READ;
  10363     ser_flags |= _SOC_SER_FLAG_MULTI_PIPE;
  10364 
  10365     for (i = 0; i < 2; i++) {
  10366         min = soc_mem_index_min(u, mem_to_search[i]);
  10367         if (mem_to_search[i] == L3_DEFIP_DATA_ONLYm) {
  10368             max = soc_mem_index_max(u, L3_DEFIP_DATA_ONLYm) +
  10369                   soc_mem_index_max(u, L3_DEFIP_PAIR_128_DATA_ONLYm) * 2;
  10370         } else {
  10371             max = soc_mem_index_max(u, mem_to_search[i]);
  10372         }
  10373 
  10374         mem_wsz = sizeof(uint32) * soc_mem_entry_words(u, mem_to_search[i]);
  10375         dmabuf = soc_cm_salloc(u, max * mem_wsz, "auxtbl_dmabuf");
  10376         if (dmabuf == NULL) {
  10377             return SOC_E_MEMORY;
  10378         }
  10379 
  10380         while (min <= max) {
  10381             int mid = min + (max - min) / 2;
  10382             if (soc_mem_ser_read_range(u, mem_to_search[i], MEM_BLOCK_ALL, min, mid,
  10383                                        ser_flags, dmabuf) < 0) {
  10384                 if (max == min) {
  10385                     *index = min;
  10386                     found_index = TRUE;
  10387                     break;
  10388                 }
  10389                 max = mid;
  10390             } else {
  10391                 min = mid + 1;
  10392             }
  10393         }
  10394         soc_cm_sfree(u, dmabuf);
  10395 
  10396         if (found_index) {
  10397             *mem = mem_to_search[i];
  10398             break;
  10399         }
  10400     }
  10401 
  10402     if (min > max) {
  10403         /* Not found */
  10404         LOG_WARN(BSL_LS_SOC_ALPM,
  10405             (BSL_META_U(u, "No corrupted index in L3_DEFIP_AUX_TABLE or "
  10406                            "L3_DEFIP_DATA_ONLY Pipe %d\n"), pipe));
  10407         return SOC_E_NOT_FOUND;
  10408     } else {
  10409         LOG_WARN(BSL_LS_SOC_ALPM,
  10410             (BSL_META_U(u, "Found corrupted Index %d in %s Table Pipe %d\n"),
  10411             *index, SOC_MEM_NAME(u, *mem),pipe));
  10412         return SOC_E_NONE;
  10413     }
  10414 }
  10415 
  10416 /* Perform an ALPM hardware operation */
  10417 int
  10418 _soc_th_alpm_aux_hw_op(int u, _soc_aux_op_t aux_op,
  10419         defip_aux_scratch_entry_t *aux_entry, int update_scratch,
  10420         int *hit, int *tcam_index, int *log_bkt)
  10421 {
  10422     soc_timeout_t  to;
  10423     int pipe, rv = SOC_E_NONE;
  10424     int _soc_alpm_aux_op_retry = 0;
  10425 
  10426     uint32 rval[_TH_PIPES_PER_DEV];
  10427     int value[_TH_PIPES_PER_DEV];
  10428     int err[_TH_PIPES_PER_DEV];
  10429 
  10430     uint32 baddr;
  10431     int block;
  10432     uint8 acc_type;
  10433     int num_pipe;
  10434     soc_mem_t mem = INVALIDm;
  10435 
  10436     /* Write to Aux Scratch before performing the operation */
  10437     if (update_scratch) {
  10438         SOC_IF_ERROR_RETURN(
  10439             WRITE_L3_DEFIP_AUX_SCRATCHm(u, MEM_BLOCK_ANY, 0, aux_entry));
  10440     }
  10441 
  10442     num_pipe = SOC_INFO(u).num_pipe;
  10443 
  10444 _retry:
  10445     switch (aux_op) {
  10446     case INSERT_PROPAGATE:
  10447         value[0] = 0;
  10448         break;
  10449     case DELETE_PROPAGATE:
  10450         value[0] = 1;
  10451         break;
  10452     case PREFIX_LOOKUP:
  10453         value[0] = 2;
  10454         break;
  10455     case HITBIT_REPLACE:
  10456         value[0] = 3;
  10457         break;
  10458     default:
  10459         return SOC_E_PARAM;
  10460     }
  10461 
  10462     rval[0] = 0;
  10463 
  10464     /* set opcode */
  10465     soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[0], OPCODEf, value[0]);
  10466 
  10467     /* Start opertation */
  10468     soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[0], STARTf, 1);
  10469 
  10470     /* Write to Aux ctrl reg */
  10471     SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_AUX_CTRLr(u, rval[0]));
  10472     soc_timeout_init(&to, 50000, 5);
  10473 
  10474     /* Check for Operation complete */
  10475     sal_memset(value, 0, sizeof(value));
  10476     sal_memset(err, 0, sizeof(err));
  10477     baddr = soc_reg_addr_get(u, L3_DEFIP_AUX_CTRLr, REG_PORT_ANY, 0,
  10478                              SOC_REG_ADDR_OPTION_NONE,
  10479                              &block, &acc_type);
  10480 
  10481     do {
  10482         for (pipe = 0; pipe < num_pipe; pipe++) {
  10483             if (SAL_BOOT_SIMULATION) {
  10484                 value[pipe] = 1;
  10485                 err[pipe] = 0;
  10486             } else {
  10487                 SOC_IF_ERROR_RETURN
  10488                     (_soc_reg32_get(u, block, pipe, baddr, &rval[pipe]));
  10489                 value[pipe] = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr,
  10490                                                 rval[pipe], DONEf);
  10491                 err[pipe] = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr,
  10492                                               rval[pipe], ERRORf);
  10493             }
  10494             if (value[pipe] != 1) {
  10495                 break;
  10496             }
  10497         }
  10498 
  10499         /* All DONE */
  10500         if (pipe >= num_pipe) {
  10501             rv = SOC_E_NONE;
  10502             break;
  10503         }
  10504 
  10505         if (soc_timeout_check(&to)) {
  10506             sal_memset(value, 0, sizeof(value));
  10507             sal_memset(err, 0, sizeof(err));
  10508             for (pipe = 0; pipe < num_pipe; pipe++) {
  10509                 SOC_IF_ERROR_RETURN
  10510                     (_soc_reg32_get(u, block, pipe, baddr, &rval[pipe]));
  10511                 value[pipe] = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr,
  10512                                                 rval[pipe], DONEf);
  10513                 err[pipe] = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr,
  10514                                               rval[pipe], ERRORf);
  10515                 if (value[pipe] != 1) {
  10516                     break;
  10517                 }
  10518             }
  10519 
  10520             if (pipe >= num_pipe) {
  10521                 rv = SOC_E_NONE;
  10522             } else {
  10523                 LOG_WARN(BSL_LS_SOC_ALPM,
  10524                     (BSL_META_U(u, "unit %d : DEFIP AUX Operation timeout, "
  10525                     "Pipe %d\n"), u, pipe));
  10526                 rv = SOC_E_TIMEOUT;
  10527             }
  10528             break;
  10529         }
  10530     } while (1);
  10531 
  10532     if (SOC_SUCCESS(rv)) {
  10533         for (pipe = 0; pipe < num_pipe; pipe++) {
  10534             if (err[pipe]) {
  10535                 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[pipe], STARTf, 0);
  10536                 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[pipe], ERRORf, 0);
  10537                 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[pipe], DONEf, 0);
  10538                 SOC_IF_ERROR_RETURN
  10539                     (_soc_reg32_set(u, block, pipe, baddr, rval[pipe]));
  10540                 LOG_WARN(BSL_LS_SOC_ALPM,
  10541                          (BSL_META_U(u, "DEFIP AUX Operation encountered "
  10542                                      "parity error in Pipe %d!!\n"), pipe));
  10543                 _soc_alpm_aux_op_retry++;
  10544                 if (SOC_CONTROL(u)->alpm_bulk_retry) {
  10545                     sal_sem_take(SOC_CONTROL(u)->alpm_bulk_retry, _SOC_ALPM_AUX_OP_RETRY_TO);
  10546                 }
  10547                 if (_soc_alpm_aux_op_retry < _SOC_ALPM_AUX_OP_RETRY_COUNT) {
  10548                     int err_index;
  10549                     if (_soc_th_alpm_aux_error_index(u, pipe, &err_index, &mem) >= 0) {
  10550                         /* Call inline correction with err_index and pipe */
  10551                         rv = soc_mem_alpm_aux_table_correction(u, pipe, err_index, mem);
  10552                         if (rv < 0) {
  10553                             LOG_ERROR(BSL_LS_SOC_ALPM,
  10554                                 (BSL_META_U(u, "_soc_th_alpm_aux_error_index "
  10555                                 "pipe %d index %d failed\n"), pipe, err_index));
  10556                         }
  10557                     }
  10558                     LOG_WARN(BSL_LS_SOC_ALPM,
  10559                         (BSL_META_U(u, "Retry DEFIP AUX Operation in Pipe %d.\n"),
  10560                         pipe));
  10561                     goto _retry;
  10562                 } else {
  10563                     LOG_ERROR(BSL_LS_SOC_ALPM,
  10564                         (BSL_META_U(u, "unit %d: Aborting DEFIP AUX Operation "
  10565                         "due to un-correctable error !!\n"), u));
  10566                     return SOC_E_INTERNAL;
  10567                 }
  10568             }
  10569         }
  10570 
  10571         if (aux_op == PREFIX_LOOKUP) {
  10572             if (hit && tcam_index) {
  10573                 int sub_bkt_ptr = 0;
  10574                 /* Get the hit bit and Bucket index for lookup operations */
  10575                 *hit = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr, rval[0], HITf);
  10576                 *tcam_index = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr,
  10577                                                 rval[0], BKT_INDEXf);
  10578                 SOC_IF_ERROR_RETURN(READ_L3_DEFIP_AUX_CTRL_1r(u, &rval[1]));
  10579                 if (ALPM_CTRL(u).bkt_sharing) {
  10580                     sub_bkt_ptr = soc_reg_field_get(u, L3_DEFIP_AUX_CTRL_1r,
  10581                                                     rval[1], SUB_BKT_PTRf);
  10582                 }
  10583                 *log_bkt = ALPM_LOG_BKT(
  10584                                 soc_reg_field_get(u, L3_DEFIP_AUX_CTRL_1r,
  10585                                 rval[1], BKT_PTRf), sub_bkt_ptr);
  10586             }
  10587         }
  10588     }
  10589 
  10590     return rv;
  10591 }
  10592 
  10593 int
  10594 _soc_th_alpm_aux_op(int u, _soc_aux_op_t aux_op,
  10595         defip_aux_scratch_entry_t *aux_entry, int update_scratch,
  10596         int *hit, int *tcam_index, int *log_bkt, int aux_flags)
  10597 {
  10598     int rv = SOC_E_NONE;
  10599     int cb_cnt = 1;
  10600 
  10601     /* SW propagation:
  10602      *
  10603      * Callback only being proceeded when cache of LPM TCAM tables is
  10604      * turn on.
  10605      */
  10606     if (ALPM_CTRL(u).trie_propagate) {
  10607         rv = _soc_th_alpm_aux_sw_op(u, aux_op, aux_entry, &cb_cnt, aux_flags);
  10608     }
  10609 
  10610     /* No Hardware propagation if aux table is disabled */
  10611     if (!ALPM_CTRL(u).aux_enable) {
  10612         return rv;
  10613     }
  10614 
  10615     /* Hareware assists only needed when matched pivot is hit. */
  10616     if ((SOC_SUCCESS(rv) && cb_cnt > 0) || ALPM_CTRL(u).force_aux_op) {
  10617         uint32 val;
  10618         rv = _soc_th_alpm_aux_hw_op(u, aux_op, aux_entry, update_scratch, hit,
  10619                                     tcam_index, log_bkt);
  10620         if ((aux_op == INSERT_PROPAGATE || aux_op == DELETE_PROPAGATE) &&
  10621             SOC_SUCCESS(rv) && SOC_URPF_STATUS_GET(u)) {
  10622             soc_mem_t mem = L3_DEFIP_AUX_SCRATCHm;
  10623             val = soc_mem_field32_get(u, mem, aux_entry, DB_TYPEf);
  10624             soc_mem_field32_set(u, mem, aux_entry, DB_TYPEf, val + 1);
  10625             val = (aux_flags & SOC_ALPM_AUX_DEF_ROUTE) ? 1 : 0;
  10626             soc_mem_field32_set(u, mem, aux_entry, DEFAULTROUTEf, val);
  10627             val = (aux_flags & SOC_ALPM_AUX_SRC_DISCARD) ? 1 : 0;
  10628             soc_mem_field32_set(u, mem, aux_entry, SRC_DISCARDf, val);
  10629             val = soc_mem_field32_get(u, mem, aux_entry, ALG_HIT_IDXf);
  10630             if (val > 0) {
  10631                 val = _soc_th_alpm_rpf_entry(u, val);
  10632                 soc_mem_field32_set(u, mem, aux_entry, ALG_HIT_IDXf, val);
  10633             }
  10634             rv = _soc_th_alpm_aux_hw_op(u, aux_op, aux_entry, TRUE, NULL,
  10635                                         NULL, NULL);
  10636         }
  10637     }
  10638 
  10639     return rv;
  10640 }
  10641 
  10642 /* Initialize the ALPM memory from a TCAM entry */
  10643 static int
  10644 _soc_th_alpm_mem_ent_init(int u, int ipv6, void *lpm_entry,
  10645                        void *alpm_entry, void *alpm_sip_entry, soc_mem_t mem,
  10646                        uint32 src_flags, uint32 *is_default, int bucket_id)
  10647 {
  10648     uint32 ipv4a;
  10649     uint32 ip6_word[4] = {0, 0};
  10650     int    pfx = 0;
  10651     int    rv = SOC_E_NONE;
  10652     uint32 default_route = 0;
  10653 
  10654     /* Zero Buffer */
  10655     sal_memset(alpm_entry, 0, soc_mem_entry_words(u, mem) * 4);
  10656 
  10657     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, HIT0f);
  10658     soc_mem_field32_set(u, mem, alpm_entry, HITf, ipv4a);
  10659 
  10660     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, VALID0f);
  10661     soc_mem_field32_set(u, mem, alpm_entry, VALIDf, ipv4a);
  10662 
  10663     if (soc_feature(u, soc_feature_generic_dest)) {
  10664         ipv4a = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry,
  10665                                     DESTINATION0f);
  10666         soc_mem_field32_set(u, mem, alpm_entry, DESTINATIONf, ipv4a);
  10667     } else {
  10668         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ECMP0f);
  10669         soc_mem_field32_set(u, mem, alpm_entry, ECMPf, ipv4a);
  10670 
  10671         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ECMP_PTR0f);
  10672         soc_mem_field32_set(u, mem, alpm_entry, ECMP_PTRf, ipv4a);
  10673 
  10674         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, NEXT_HOP_INDEX0f);
  10675         soc_mem_field32_set(u, mem, alpm_entry, NEXT_HOP_INDEXf, ipv4a);
  10676     }
  10677 
  10678     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, PRI0f);
  10679     soc_mem_field32_set(u, mem, alpm_entry, PRIf, ipv4a);
  10680 
  10681     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, RPE0f);
  10682     soc_mem_field32_set(u, mem, alpm_entry, RPEf, ipv4a);
  10683 
  10684     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, DST_DISCARD0f);
  10685     soc_mem_field32_set(u, mem, alpm_entry, DST_DISCARDf, ipv4a);
  10686 
  10687     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, SRC_DISCARD0f);
  10688     soc_mem_field32_set(u, mem, alpm_entry, SRC_DISCARDf, ipv4a);
  10689 
  10690     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, CLASS_ID0f);
  10691     soc_mem_field32_set(u, mem, alpm_entry, CLASS_IDf, ipv4a);
  10692 
  10693     soc_mem_field32_set(u, mem, alpm_entry, SUB_BKT_PTRf,
  10694                         ALPM_SUB_BKT(u, bucket_id));
  10695 
  10696     /* Set IP Address and IP length */
  10697     ip6_word[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, IP_ADDR0f);
  10698     if (ipv6) {
  10699         ip6_word[1] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, IP_ADDR1f);
  10700     }
  10701     soc_mem_field_set(u, mem, (uint32*)alpm_entry, KEYf, (uint32*)ip6_word);
  10702 
  10703     if (ipv6) {
  10704         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f);
  10705         if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
  10706             return(rv);
  10707         }
  10708         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f);
  10709         if (pfx) {
  10710             if (ipv4a != 0xffffffff)  {
  10711                 return(SOC_E_PARAM);
  10712             }
  10713             pfx += 32;
  10714         } else {
  10715             if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
  10716                 return(rv);
  10717             }
  10718         }
  10719     } else {
  10720         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f);
  10721         if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
  10722             return(rv);
  10723         }
  10724     }
  10725     if ((pfx == 0) && (ip6_word[0] == 0) && (ip6_word[1] == 0)) {
  10726         default_route = 1;
  10727     }
  10728     if (is_default != NULL) {
  10729         *is_default = default_route;
  10730     }
  10731     soc_mem_field32_set(u, mem, alpm_entry, LENGTHf, pfx);
  10732 
  10733     if (mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64_1m) {
  10734         ipv4a = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, FLEX_CTR_BASE_COUNTER_IDX0f);
  10735         soc_mem_field32_set(u, mem, alpm_entry, FLEX_CTR_BASE_COUNTER_IDXf, ipv4a);
  10736 
  10737         ipv4a = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, FLEX_CTR_OFFSET_MODE0f);
  10738         soc_mem_field32_set(u, mem, alpm_entry, FLEX_CTR_OFFSET_MODEf, ipv4a);
  10739 
  10740         ipv4a = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, FLEX_CTR_POOL_NUMBER0f);
  10741         soc_mem_field32_set(u, mem, alpm_entry, FLEX_CTR_POOL_NUMBERf, ipv4a);
  10742     }
  10743 
  10744     if (alpm_sip_entry == NULL) {
  10745         return (SOC_E_NONE);
  10746     }
  10747     if (SOC_URPF_STATUS_GET(u)) {
  10748         sal_memset(alpm_sip_entry, 0, soc_mem_entry_words(u, mem) * 4);
  10749         sal_memcpy(alpm_sip_entry, alpm_entry, soc_mem_entry_words(u, mem) * 4);
  10750         soc_mem_field32_set(u, mem, alpm_sip_entry, DST_DISCARDf, 0);
  10751         soc_mem_field32_set(u, mem, alpm_sip_entry, RPEf, 0);
  10752 
  10753         soc_mem_field32_set(u, mem, alpm_sip_entry, SRC_DISCARDf,
  10754                             src_flags & SOC_ALPM_RPF_SRC_DISCARD);
  10755         soc_mem_field32_set(u, mem, alpm_sip_entry, DEFAULTROUTEf,
  10756                             default_route);
  10757 #if defined(BCM_TRIDENT3_SUPPORT)
  10758         if (SOC_IS_TRIDENT3X(u)) {
  10759             if (SOC_MEM_FIELD_VALID(u, mem, FLEX_CTR_BASE_COUNTER_IDXf)) {
  10760                 soc_mem_field32_set(u, mem, alpm_sip_entry,
  10761                     FLEX_CTR_BASE_COUNTER_IDXf, 0);
  10762             }
  10763             if (SOC_MEM_FIELD_VALID(u, mem, FLEX_CTR_BASE_COUNTER_IDX0f)) {
  10764                 soc_mem_field32_set(u, mem, alpm_sip_entry,
  10765                     FLEX_CTR_BASE_COUNTER_IDX0f, 0);
  10766             }
  10767             if (SOC_MEM_FIELD_VALID(u, mem, FLEX_CTR_BASE_COUNTER_IDX1f)) {
  10768                 soc_mem_field32_set(u, mem, alpm_sip_entry,
  10769                     FLEX_CTR_BASE_COUNTER_IDX1f, 0);
  10770             }
  10771         }
  10772 #endif
  10773     }
  10774     return (SOC_E_NONE);
  10775 }
  10776 
  10777 /* Initialize the TCAM entry from ALPM memory */
  10778 static int
  10779 _soc_th_alpm_lpm_ent_init(int u, void *alpm_entry, soc_mem_t mem, int ipv6,
  10780                           int vrf_id, int log_bkt, int index, void *lpm_entry,
  10781                           int flex)
  10782 {
  10783     uint32 ipv4a;
  10784     uint32 ip6_word[4] = {0, 0};
  10785     uint32 pfx = 0;
  10786 
  10787     /* Zero Buffer */
  10788     sal_memset(lpm_entry, 0, soc_mem_entry_words(u, L3_DEFIPm) * 4);
  10789 
  10790     ipv4a = soc_mem_field32_get(u, mem, alpm_entry, HITf);
  10791     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, HIT0f, ipv4a);
  10792     if (ipv6) {
  10793         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, HIT1f, ipv4a);
  10794     }
  10795 
  10796     ipv4a = soc_mem_field32_get(u, mem, alpm_entry, VALIDf);
  10797     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VALID0f, ipv4a);
  10798     if (ipv6) {
  10799         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VALID1f, ipv4a);
  10800     }
  10801 
  10802     if (soc_feature(u, soc_feature_generic_dest)) {
  10803         ipv4a = soc_mem_field32_get(u, mem, alpm_entry, DESTINATIONf);
  10804         soc_mem_field32_set(u, L3_DEFIPm, lpm_entry, DESTINATION0f, ipv4a);
  10805     } else {
  10806         ipv4a = soc_mem_field32_get(u, mem, alpm_entry, ECMPf);
  10807         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ECMP0f, ipv4a);
  10808 
  10809         ipv4a = soc_mem_field32_get(u, mem, alpm_entry, ECMP_PTRf);
  10810         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ECMP_PTR0f, ipv4a);
  10811 
  10812         ipv4a = soc_mem_field32_get(u, mem, alpm_entry, NEXT_HOP_INDEXf);
  10813         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, NEXT_HOP_INDEX0f, ipv4a);
  10814     }
  10815 
  10816     ipv4a = soc_mem_field32_get(u, mem, alpm_entry, PRIf);
  10817     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, PRI0f, ipv4a);
  10818 
  10819     ipv4a = soc_mem_field32_get(u, mem, alpm_entry, RPEf);
  10820     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, RPE0f, ipv4a);
  10821 
  10822     ipv4a = soc_mem_field32_get(u, mem, alpm_entry, DST_DISCARDf);
  10823     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, DST_DISCARD0f, ipv4a);
  10824 
  10825     ipv4a = soc_mem_field32_get(u, mem, alpm_entry, SRC_DISCARDf);
  10826     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, SRC_DISCARD0f, ipv4a);
  10827 
  10828     ipv4a = soc_mem_field32_get(u, mem, alpm_entry, CLASS_IDf);
  10829     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, CLASS_ID0f, ipv4a);
  10830 
  10831     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ALG_BKT_PTR0f,
  10832                         ALPM_PHY_BKT(u, log_bkt));
  10833     if (ALPM_CTRL(u).bkt_sharing) {
  10834         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ALG_SUB_BKT_PTR0f,
  10835                             ALPM_SUB_BKT(u, log_bkt));
  10836     }
  10837     if (index > 0) {
  10838         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ALG_HIT_IDX0f, index);
  10839     }
  10840     soc_mem_field32_set(u, L3_DEFIPm, lpm_entry, MODE_MASK0_f(u), 3);
  10841     soc_mem_field32_set(u, L3_DEFIPm, lpm_entry, ENTRY_TYPE_MASK0_f(u), 1);
  10842     if (ipv6) {
  10843         soc_mem_field32_set(u, L3_DEFIPm, lpm_entry, MODE0_f(u), 1);
  10844         soc_mem_field32_set(u, L3_DEFIPm, lpm_entry, MODE1_f(u), 1);
  10845     }
  10846 
  10847     /* Set IP Address and IP length */
  10848     soc_mem_field_get(u, mem, alpm_entry, KEYf, ip6_word);
  10849     if (ipv6) {
  10850         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR1f,
  10851                             ip6_word[1]);
  10852     }
  10853     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR0f, ip6_word[0]);
  10854 
  10855     ipv4a = soc_mem_field32_get(u, mem, alpm_entry, LENGTHf);
  10856     if (ipv6) {
  10857         if (ipv4a >= 32) {
  10858             pfx = 0xffffffff;
  10859             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, pfx);
  10860             pfx = ~SHR_SHIFT_RIGHT(0xffffffff, ipv4a - 32);
  10861             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, pfx);
  10862         } else {
  10863             pfx = ~(0xffffffff >> ipv4a);
  10864             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, pfx);
  10865         }
  10866     } else {
  10867         assert(ipv4a <= 32);
  10868         pfx = ~SHR_SHIFT_RIGHT(0xffffffff, ipv4a);
  10869         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, pfx);
  10870     }
  10871 
  10872     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ENTRY_VIEW0f,
  10873         _soc_th_alpm_lpm_entry_view_get(u, ipv6, flex));
  10874 
  10875     if (vrf_id == SOC_L3_VRF_OVERRIDE) {
  10876         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, GLOBAL_HIGH0f, 1);
  10877         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f, 1);
  10878         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_0f, 0);
  10879         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f, 0);
  10880     } else  if (vrf_id == SOC_L3_VRF_GLOBAL) {
  10881         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f, 1);
  10882         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_0f, 0);
  10883         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f, 0);
  10884     } else {
  10885         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_0f, vrf_id);
  10886         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f,
  10887                             SOC_VRF_MAX(u));
  10888     }
  10889 
  10890     if (mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64_1m) {
  10891         ipv4a = soc_mem_field32_get(u, mem, alpm_entry, FLEX_CTR_BASE_COUNTER_IDXf);
  10892         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, FLEX_CTR_BASE_COUNTER_IDX0f, ipv4a);
  10893 
  10894         ipv4a = soc_mem_field32_get(u, mem, alpm_entry, FLEX_CTR_OFFSET_MODEf);
  10895         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, FLEX_CTR_OFFSET_MODE0f, ipv4a);
  10896 
  10897         ipv4a = soc_mem_field32_get(u, mem, alpm_entry, FLEX_CTR_POOL_NUMBERf);
  10898         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, FLEX_CTR_POOL_NUMBER0f, ipv4a);
  10899     }
  10900     return (SOC_E_NONE);
  10901 }
  10902 
  10903 STATIC int
  10904 _soc_th_alpm_pivot_bmp_len_get(int unit, int ipv6,
  10905                                void *lpm_entry, uint32 *bpm_len)
  10906 {
  10907     int                  rv = SOC_E_NONE;
  10908     int                  vrf_id = 0, vrf = 0;
  10909     uint32               length;
  10910     uint32               prefix[5] = {0};
  10911     int                  default_route = 0;
  10912     trie_t               *pfx_root = NULL;
  10913     trie_node_t          *lpmp = NULL;
  10914     payload_t            *tmp_pyld = NULL;
  10915 
  10916     *bpm_len = 0;
  10917 
  10918     SOC_IF_ERROR_RETURN(
  10919         soc_th_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf));
  10920 
  10921     if ((ALPM_PREFIX_IN_TCAM(unit, vrf_id))) {
  10922         return rv;
  10923     }
  10924 
  10925     SOC_IF_ERROR_RETURN(
  10926         _soc_th_alpm_prefix_create(unit, ipv6, lpm_entry,
  10927                                    prefix, &length, &default_route));
  10928     if (ipv6) {
  10929         pfx_root = VRF_PREFIX_TRIE_IPV6(unit, vrf);
  10930     } else {
  10931         pfx_root = VRF_PREFIX_TRIE_IPV4(unit, vrf);
  10932     }
  10933 
  10934     /* find longest prefix that covers pivot */
  10935     rv = trie_find_lpm(pfx_root, prefix, length, &lpmp);
  10936     if (SOC_FAILURE(rv)) {
  10937         return rv;
  10938     }
  10939 
  10940     tmp_pyld = (payload_t *)lpmp;
  10941 
  10942     if (tmp_pyld->bkt_ptr) {
  10943         *bpm_len = ((payload_t *)(tmp_pyld->bkt_ptr))->len;
  10944     }
  10945 
  10946     return rv;
  10947 }
  10948 
  10949 int
  10950 soc_th_alpm_warmboot_pivot_bmp_len_update(int unit, int ipv6,
  10951                                           void *lpm_entry, int tcam_idx)
  10952 {
  10953     int                  rv = SOC_E_NONE;
  10954     alpm_pivot_t         *pivot = NULL;
  10955     uint32               bpm_len = 0;
  10956 
  10957     SOC_IF_ERROR_RETURN(
  10958         _soc_th_alpm_pivot_bmp_len_get(unit, ipv6, lpm_entry, &bpm_len));
  10959 
  10960     tcam_idx = soc_th_alpm_physical_idx(unit, L3_DEFIPm, tcam_idx, ipv6);
  10961 
  10962     pivot = ALPM_TCAM_PIVOT(unit, tcam_idx);
  10963 
  10964     /* update bpm_len */
  10965     PIVOT_TCAM_BPMLEN(pivot) = bpm_len;
  10966 
  10967     return rv;
  10968 }
  10969 
  10970 int
  10971 soc_th_alpm_warmboot_pivot_add(int unit,
  10972                             int ipv6,
  10973                             void *lpm_entry,
  10974                             int tcam_idx,
  10975                             int log_bkt)
  10976 {
  10977     int                  rv = SOC_E_NONE;
  10978     uint32               key[2] = {0};
  10979     alpm_pivot_t         *pivot = NULL;
  10980     alpm_bucket_handle_t *bucket_handle = NULL;
  10981     int                  vrf_id = 0, vrf = 0;
  10982 
  10983     uint32               length2;
  10984     trie_t               *pivot_root = NULL;
  10985     uint32               prefix[5] = {0};
  10986     uint32               bpm[5] = {0};
  10987     int                  default_route = 0;
  10988 
  10989     SOC_IF_ERROR_RETURN(_soc_th_alpm_prefix_create(unit, ipv6, lpm_entry,
  10990                                 prefix, &length2, &default_route));
  10991 
  10992     SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf));
  10993     tcam_idx = soc_th_alpm_physical_idx(unit, L3_DEFIPm, tcam_idx, ipv6);
  10994 
  10995     /* Allocate bucket handle */
  10996     bucket_handle = sal_alloc(sizeof(alpm_bucket_handle_t), "ALPM Bucket Handle");
  10997     if (bucket_handle == NULL) {
  10998         LOG_ERROR(BSL_LS_SOC_ALPM,
  10999                   (BSL_META_U(unit,
  11000                               "Unable to allocate memory for "
  11001                               "PIVOT trie node \n")));
  11002         return SOC_E_NONE;
  11003     }
  11004     sal_memset(bucket_handle, 0, sizeof(*bucket_handle));
  11005 
  11006     /* Allocate pivot Payload */
  11007     pivot = sal_alloc(sizeof(alpm_pivot_t), "Payload for Pivot");
  11008     if (pivot == NULL) {
  11009         LOG_ERROR(BSL_LS_SOC_ALPM,
  11010                   (BSL_META_U(unit,
  11011                               "Unable to allocate memory for "
  11012                               "PIVOT trie node \n")));
  11013         sal_free(bucket_handle);
  11014         return SOC_E_MEMORY;
  11015     }
  11016     sal_memset(pivot, 0, sizeof(*pivot));
  11017 
  11018     /* Save bucket_handle in pivot->bucket_trie */
  11019     PIVOT_BUCKET_HANDLE(pivot) = bucket_handle;
  11020 
  11021     if (ipv6) {
  11022         trie_init(_MAX_KEY_LEN_144_, &PIVOT_BUCKET_TRIE(pivot));
  11023 
  11024         /* Set address to the buffer. */
  11025         key[0] = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, IP_ADDR0f);
  11026 
  11027         /* Set address to the buffer. */
  11028         key[1] = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, IP_ADDR1f);
  11029     } else {
  11030         trie_init(_MAX_KEY_LEN_48_, &PIVOT_BUCKET_TRIE(pivot));
  11031 
  11032         /* Set address to the buffer. */
  11033         key[0] = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, IP_ADDR0f);
  11034     }
  11035 
  11036     /* Save bucket index into pivot->bucket->bucket_index */
  11037     PIVOT_BUCKET_INDEX(pivot) = log_bkt;
  11038 
  11039     /* Save tcam index into pivot->tcam_index */
  11040     PIVOT_TCAM_INDEX(pivot) = tcam_idx;
  11041 
  11042     if (!(ALPM_PREFIX_IN_TCAM(unit, vrf_id))) {
  11043         if (ipv6 == 0) {
  11044             pivot_root = VRF_PIVOT_TRIE_IPV4(unit, vrf);
  11045             if (pivot_root == NULL) {
  11046                 trie_init(_MAX_KEY_LEN_48_, &VRF_PIVOT_TRIE_IPV4(unit, vrf));
  11047                 pivot_root = VRF_PIVOT_TRIE_IPV4(unit, vrf);
  11048             }
  11049         } else {
  11050             pivot_root = VRF_PIVOT_TRIE_IPV6(unit, vrf);
  11051             if (pivot_root == NULL) {
  11052                 trie_init(_MAX_KEY_LEN_144_, &VRF_PIVOT_TRIE_IPV6(unit, vrf));
  11053                 pivot_root = VRF_PIVOT_TRIE_IPV6(unit, vrf);
  11054             }
  11055         }
  11056 
  11057         sal_memcpy(pivot->key, prefix, sizeof(prefix));
  11058         pivot->len    = length2;
  11059 
  11060         /* insert into pivot trie */
  11061         rv = trie_insert(pivot_root, pivot->key,
  11062                 ALPM_CTRL(unit).trie_propagate ? bpm : NULL,
  11063                 pivot->len, (trie_node_t *)pivot);
  11064         if (SOC_FAILURE(rv)) {
  11065             sal_free(bucket_handle);
  11066             sal_free(pivot);
  11067             return rv;
  11068         }
  11069     }
  11070 
  11071     /* Insert pivot into global pivot array indexed by tcam_idx */
  11072     ALPM_TCAM_PIVOT(unit, tcam_idx) = pivot;
  11073     PIVOT_BUCKET_VRF(pivot) = vrf;
  11074     PIVOT_BUCKET_IPV6(pivot) = ipv6;
  11075 
  11076     PIVOT_BUCKET_ENT_CNT_UPDATE(pivot);
  11077     if (key[0] == 0 && key[1] == 0) {
  11078         PIVOT_BUCKET_DEF(pivot) = TRUE;
  11079     }
  11080 
  11081     return rv;
  11082 }
  11083 
  11084 
  11085 static int
  11086 _soc_th_alpm_warmboot_insert(int unit,
  11087                              int ipv6,
  11088                              int flex,
  11089                              void *lpm_entry,
  11090                              void *alpm_entry, /* ALPM (SRAM) entry data */
  11091                              int tcam_idx,     /* TCAM index             */
  11092                              int log_bkt,      /* Bucket index           */
  11093                              int alpm_idx )    /* ALPM entry index       */
  11094 {
  11095     int          vrf_id;   /* Internal API representation of VRF id           */
  11096     int          vrf;      /* VRF in 0 to (MAX_VRF + 1) range;                */
  11097                            /* VRF = (MAX_VRF + 1), software rep of GLOBAL VRF */
  11098     int          rv = SOC_E_NONE;
  11099     int          default_route = 0;
  11100     uint32       prefix[5] = {0, 0, 0, 0, 0};
  11101     uint32       length;
  11102     defip_entry_t temp_lpm_entry;
  11103     trie_t       *bkt_trie = NULL;
  11104     trie_t       *pfx_trie = NULL;
  11105     trie_node_t  *delp = NULL;
  11106     payload_t    *bkt_payload = NULL;
  11107     payload_t    *pfx_payload = NULL;
  11108     alpm_pivot_t *pivot_pyld = NULL;
  11109     soc_mem_t    mem;
  11110 
  11111     /* Check function params */
  11112     if ((NULL == lpm_entry) || (NULL == alpm_entry)) {
  11113         return SOC_E_PARAM;
  11114     }
  11115 
  11116     /* Check IPv6 */
  11117     if (ipv6) {
  11118         if (!(ipv6 = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, MODE1_f(unit)))) {
  11119             return (SOC_E_PARAM);
  11120         }
  11121     }
  11122 
  11123     /* Get VRF */
  11124     SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf));
  11125 
  11126     /* Get ALPM table memory. */
  11127     SOC_ALPM_TABLE_MEM(unit, ipv6, mem, flex);
  11128 
  11129     /* Convert alpm_entry into lpm_entry to extract prefix */
  11130     SOC_IF_ERROR_RETURN(_soc_th_alpm_lpm_ent_init(unit, alpm_entry, mem, ipv6,
  11131                                                   vrf_id, log_bkt, tcam_idx,
  11132                                                   &temp_lpm_entry, 0));
  11133 
  11134     /* Create Prefix */
  11135     rv = _soc_th_alpm_prefix_create(unit, ipv6, &temp_lpm_entry, prefix,
  11136                                     &length, &default_route);
  11137     if (SOC_FAILURE(rv)) {
  11138         LOG_ERROR(BSL_LS_SOC_ALPM,
  11139                   (BSL_META_U(unit,
  11140                               "prefix create failed\n")));
  11141         return rv;
  11142     }
  11143 
  11144     /* Get TCAM pivot */
  11145     pivot_pyld = ALPM_TCAM_PIVOT(unit, tcam_idx);
  11146 
  11147     /* Get bucket trie from pivot */
  11148     bkt_trie = PIVOT_BUCKET_TRIE(pivot_pyld);
  11149 
  11150     /* Allocate bucket payload */
  11151     bkt_payload = sal_alloc(sizeof(payload_t), "Payload for Key");
  11152     if (NULL == bkt_payload) {
  11153         LOG_ERROR(BSL_LS_SOC_ALPM,
  11154                   (BSL_META_U(unit,
  11155                               "Unable to allocate memory for trie node.\n")));
  11156         return SOC_E_MEMORY;
  11157     }
  11158 
  11159     /* Allocate prefix trie payload */
  11160     pfx_payload = sal_alloc(sizeof(payload_t), "Payload for pfx trie key");
  11161     if (NULL == pfx_payload) {
  11162         LOG_ERROR(BSL_LS_SOC_ALPM,
  11163                   (BSL_META_U(unit,
  11164                               "Unable to allocate memory for pfx trie node\n")));
  11165         sal_free(bkt_payload);
  11166         return SOC_E_MEMORY;
  11167     }
  11168 
  11169     /* Clear allocated payloads */
  11170     sal_memset(bkt_payload, 0, sizeof(*bkt_payload));
  11171     sal_memset(pfx_payload, 0, sizeof(*pfx_payload));
  11172 
  11173     bkt_payload->key[0] = prefix[0];
  11174     bkt_payload->key[1] = prefix[1];
  11175     bkt_payload->key[2] = prefix[2];
  11176     bkt_payload->key[3] = prefix[3];
  11177     bkt_payload->key[4] = prefix[4];
  11178     bkt_payload->len    = length;
  11179     bkt_payload->index  = alpm_idx;
  11180 
  11181 #ifdef ALPM_WARM_BOOT_DEBUG_EXTENSIVE
  11182     LOG_ERROR(BSL_LS_SOC_ALPM,
  11183               (BSL_META_U(unit,
  11184                           "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, length = 0x%x alpm_idx = 0x%x\n"),
  11185                bkt_payload->key[0], bkt_payload->key[1], bkt_payload->key[2],
  11186                bkt_payload->key[3], bkt_payload->key[4],
  11187                length, alpm_idx));
  11188 #endif
  11189 
  11190     /* Create duplicate for prefix trie */
  11191     sal_memcpy(pfx_payload, bkt_payload, sizeof(*bkt_payload));
  11192     pfx_payload->bkt_ptr = bkt_payload;
  11193 
  11194     /* Insert prefix into bucket-trie */
  11195     rv = trie_insert(bkt_trie, prefix, NULL, length,
  11196                     (trie_node_t *)bkt_payload);
  11197     if (SOC_FAILURE(rv)) {
  11198         goto free_memory;
  11199     }
  11200 
  11201     /* Insert prefix into prefix-trie */
  11202     if (ipv6) {
  11203         pfx_trie = VRF_PREFIX_TRIE_IPV6(unit, vrf);
  11204     } else {
  11205         pfx_trie = VRF_PREFIX_TRIE_IPV4(unit, vrf);
  11206     }
  11207 
  11208     if (!default_route) {
  11209         uint32 bpm[5];
  11210 
  11211         _soc_th_alpm_mask_prefix_create(unit, ipv6, length, bpm);
  11212         /* Default route already in prefix trie */
  11213         rv = trie_insert(pfx_trie, prefix,
  11214                          ALPM_CTRL(unit).trie_propagate ? bpm : NULL,
  11215                          length, (trie_node_t *)pfx_payload);
  11216         if (SOC_FAILURE(rv)) {
  11217             goto delete_bkt_trie;
  11218         }
  11219     }
  11220 
  11221     /* Return success */
  11222     return rv;
  11223 
  11224 delete_bkt_trie:
  11225     (void) trie_delete(bkt_trie, prefix, length, &delp);
  11226     bkt_payload = (payload_t *) delp;
  11227 
  11228 free_memory:
  11229     sal_free(bkt_payload);
  11230     sal_free(pfx_payload);
  11231     return rv;
  11232 }
  11233 
  11234 /*
  11235  * soc_th_alpm_warmboot_vrf_add
  11236  */
  11237 static int
  11238 soc_th_alpm_warmboot_vrf_add(int unit,
  11239                           int v6,
  11240                           int vrf,
  11241                           int idx,
  11242                           int log_bkt)
  11243 {
  11244 
  11245     int           rv = SOC_E_NONE;
  11246     uint32        length;
  11247     uint32        key[5] = {0};
  11248     trie_t        *pfx_root = NULL;
  11249     payload_t     *pfx_pyld = NULL;
  11250     defip_entry_t *lpm_entry = NULL;
  11251 
  11252     /* Initialize VRF PIVOT IPV4 trie */
  11253     lpm_entry = sal_alloc(sizeof(defip_entry_t), "Default LPM entry");
  11254     if (lpm_entry == NULL) {
  11255         LOG_ERROR(BSL_LS_SOC_ALPM,
  11256                   (BSL_META_U(unit,
  11257                               "unable to allocate memory for LPM entry\n")));
  11258         return SOC_E_MEMORY;
  11259     }
  11260 
  11261     /* Initialize an lpm entry to perform a match */
  11262     _soc_th_alpm_lpm_ent_key_init(unit, key, 0, vrf, v6, lpm_entry, 1);
  11263 
  11264     /* for global VRF */
  11265     if (vrf == SOC_VRF_MAX(unit) + 1) {
  11266         SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f, 1);
  11267     } else {
  11268         /* Set default miss to global route only for non global routes */
  11269         SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, DEFAULT_MISS0f, 1);
  11270     }
  11271 
  11272     SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, ALG_BKT_PTR0f,
  11273                         ALPM_PHY_BKT(unit, log_bkt));
  11274     if (ALPM_CTRL(unit).bkt_sharing) {
  11275         SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, ALG_SUB_BKT_PTR0f,
  11276                             ALPM_SUB_BKT(unit, log_bkt));
  11277     }
  11278 
  11279     if (v6 == 0) {
  11280         VRF_TRIE_DEFAULT_ROUTE_IPV4(unit, vrf) = lpm_entry;
  11281         trie_init(_MAX_KEY_LEN_48_, &VRF_PREFIX_TRIE_IPV4(unit, vrf));
  11282         pfx_root = VRF_PREFIX_TRIE_IPV4(unit, vrf);
  11283     } else {
  11284         VRF_TRIE_DEFAULT_ROUTE_IPV6(unit, vrf) = lpm_entry;
  11285         trie_init(_MAX_KEY_LEN_144_, &VRF_PREFIX_TRIE_IPV6(unit, vrf));
  11286         pfx_root = VRF_PREFIX_TRIE_IPV6(unit, vrf);
  11287     }
  11288 
  11289     pfx_pyld = sal_alloc(sizeof(payload_t), "Payload for pfx trie key");
  11290     if (pfx_pyld == NULL) {
  11291         LOG_ERROR(BSL_LS_SOC_ALPM,
  11292                   (BSL_META_U(unit,
  11293                               "Unable to allocate memory for pfx trie node \n")));
  11294         return SOC_E_MEMORY;
  11295     }
  11296 
  11297     sal_memset(pfx_pyld,   0, sizeof(*pfx_pyld));
  11298 
  11299     length = 0;
  11300     pfx_pyld->key[0] = key[0];
  11301     pfx_pyld->key[1] = key[1];
  11302     pfx_pyld->len    = length;
  11303 
  11304     rv = trie_insert(pfx_root, key, ALPM_CTRL(unit).trie_propagate ? key : NULL,
  11305                      length, &(pfx_pyld->node));
  11306     if (SOC_FAILURE(rv)) {
  11307         sal_free(pfx_pyld);
  11308         return rv;
  11309     }
  11310 
  11311     VRF_TRIE_INIT_DONE(unit, vrf, v6, 1);
  11312 
  11313     return rv;
  11314 }
  11315 /*
  11316  * soc_th_alpm_warmboot_prefix_insert
  11317  */
  11318 int
  11319 soc_th_alpm_warmboot_prefix_insert(int unit,
  11320                                 int  ipv6,
  11321                                 int  flex,
  11322                                 void *lpm_entry,
  11323                                 void *alpm_entry,
  11324                                 int tcam_idx,
  11325                                 int log_bkt,
  11326                                 int alpm_idx)
  11327 {
  11328     int       vrf_id;  /* Internal API representation of VRF id */
  11329     int       vrf;      /* VRF in (0 - (MAX_VRF + 1)) range */
  11330     int       rv = SOC_E_NONE;
  11331     soc_mem_t mem;
  11332 
  11333     tcam_idx = soc_th_alpm_physical_idx(unit, L3_DEFIPm, tcam_idx, ipv6);
  11334 
  11335     /* Get ALPM table memory. */
  11336     SOC_ALPM_TABLE_MEM(unit, ipv6, mem, flex);
  11337 
  11338     /* Get VRF */
  11339     SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf));
  11340 
  11341     /* For VRF_OVERRIDE (Global High) entries,  Prefix resides in TCAM directly */
  11342     if (ALPM_PREFIX_IN_TCAM(unit, vrf_id)) {
  11343         return(rv);
  11344     }
  11345     /* Non override entries, goes into ALPM memory */
  11346     if (!VRF_TRIE_INIT_COMPLETED(unit, vrf, ipv6)) {
  11347         LOG_VERBOSE(BSL_LS_SOC_ALPM,
  11348                     (BSL_META_U(unit,
  11349                                 "VRF %d is not initialized\n"),
  11350                      vrf));
  11351         rv = soc_th_alpm_warmboot_vrf_add(unit, ipv6, vrf, tcam_idx, log_bkt);
  11352         if (SOC_FAILURE(rv)) {
  11353             LOG_ERROR(BSL_LS_SOC_ALPM,
  11354                       (BSL_META_U(unit,
  11355                                   "VRF %d/%d trie init \n"
  11356                                   "failed\n"), vrf, ipv6));
  11357             return rv;
  11358         }
  11359 
  11360         LOG_VERBOSE(BSL_LS_SOC_ALPM,
  11361                     (BSL_META_U(unit,
  11362                                 "VRF %d/%d trie init completed\n"),
  11363                      vrf, ipv6));
  11364     }
  11365 
  11366     rv = _soc_th_alpm_warmboot_insert(unit, ipv6, flex, lpm_entry, alpm_entry,
  11367                                       tcam_idx, log_bkt, alpm_idx);
  11368     if (rv != SOC_E_NONE) {
  11369         LOG_WARN(BSL_LS_SOC_ALPM,
  11370                  (BSL_META_U(unit,
  11371                              "unit %d : Route Insertion Failed :%s\n"),
  11372                   unit, soc_errmsg(rv)));
  11373 
  11374         return(rv);
  11375     }
  11376 
  11377     soc_th_alpm_bucket_usage_incr(unit, log_bkt, tcam_idx, vrf, mem, 1);
  11378 
  11379     VRF_TRIE_ROUTES_INC(unit, vrf_id, vrf, ipv6);
  11380     return(rv);
  11381 }
  11382 
  11383 /*
  11384  * alpm_warmboot_bucket_bitmap_set
  11385  * This function will set bit position in bucket bitmap
  11386  */
  11387 int
  11388 soc_th_alpm_warmboot_bucket_bitmap_set(int u,       /* Unit         */
  11389                                        int vrf,     /* VRF          */
  11390                                        int v6,      /* Flag v4/v6   */
  11391                                        int phy_bkt) /* Bucket index */
  11392 {
  11393     int step_count = 1;
  11394     uint8 ipv = !!v6;
  11395     SHR_BITDCL *bkt_bmap = SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv);
  11396 
  11397     if (vrf == SOC_VRF_MAX(u) + 1) {
  11398         bkt_bmap = SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv);
  11399     }
  11400 
  11401     /*
  11402      * In combined search mode, with urpf disabled, need to allocate even and
  11403      * odd bucket pointers
  11404      */
  11405     if (ALPM_CTRL(u).double_wide[v6]) {
  11406         step_count = 2;
  11407     }
  11408 
  11409     /* Set bit position */
  11410     SHR_BITSET_RANGE(bkt_bmap, phy_bkt, step_count);
  11411 
  11412     return SOC_E_NONE;
  11413 }
  11414 
  11415 int
  11416 soc_th_alpm_warmboot_lpm_reinit_done(int unit)
  11417 {
  11418     int idx;
  11419     int prev_idx = ALPM_MAX_PFX_INDEX;
  11420     int alpm_mode;
  11421     int defip_table_size = soc_mem_index_count(unit, L3_DEFIPm);
  11422 
  11423     if (SOC_URPF_STATUS_GET(unit)) {
  11424         defip_table_size >>= 1;
  11425     }
  11426 
  11427     /* returns 0 for combined search mode and 1 for parallel search mode */
  11428     alpm_mode = ALPM_CTRL(unit).alpm_mode;
  11429     if (alpm_mode == SOC_ALPM_MODE_COMBINED) {
  11430         /* Combined search mode */
  11431         SOC_ALPM_LPM_STATE_PREV(unit, ALPM_MAX_PFX_INDEX) = -1;
  11432 
  11433         for (idx = ALPM_MAX_PFX_INDEX; idx > -1; idx--) {
  11434             if (-1 == SOC_ALPM_LPM_STATE_START(unit, idx)) {
  11435                 continue;
  11436             }
  11437 
  11438             SOC_ALPM_LPM_STATE_PREV(unit, idx) = prev_idx;
  11439             SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = idx;
  11440 
  11441             SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) =                    \
  11442                               SOC_ALPM_LPM_STATE_START(unit, idx) -      \
  11443                               SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1;
  11444             prev_idx = idx;
  11445 
  11446         }
  11447 
  11448         SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = -1;
  11449         SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) =                       \
  11450                               defip_table_size -                   \
  11451                               SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1;
  11452     } else if ((alpm_mode == SOC_ALPM_MODE_PARALLEL) ||
  11453                (alpm_mode == SOC_ALPM_MODE_TCAM_ALPM)) {
  11454         /* Parallel search mode or TCAM/ALPM mode
  11455          *
  11456          *    Configured VRF Range
  11457          *    {0 - (ALPM_MAX_PFX_INDEX/3)}
  11458          *    Global VRF Range
  11459          *    {((ALPM_MAX_PFX_INDEX/1) + 1) - (ALPM_MAX_PFX_INDEX/2) }
  11460          *    Override VRF Range
  11461          *    {((ALPM_MAX_PFX_INDEX/2) + 1) - (ALPM_MAX_PFX_INDEX) }
  11462          */
  11463 
  11464         /*
  11465          * Global and Overide VRF range are treated as single block and
  11466          * both blocks will be linked
  11467          */
  11468         SOC_ALPM_LPM_STATE_PREV(unit, ALPM_MAX_PFX_INDEX) = -1;
  11469         for (idx = ALPM_MAX_PFX_INDEX; idx > (ALPM_MAX_PFX_INDEX/3) ; idx--) {
  11470             if (-1 == SOC_ALPM_LPM_STATE_START(unit, idx)) {
  11471                 continue;
  11472             }
  11473 
  11474             SOC_ALPM_LPM_STATE_PREV(unit, idx) = prev_idx;
  11475             SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = idx;
  11476 
  11477             SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) =                    \
  11478                               SOC_ALPM_LPM_STATE_START(unit, idx) -      \
  11479                               SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1;
  11480 
  11481             prev_idx = idx;
  11482         }
  11483         SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = -1;
  11484         SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) =                       \
  11485                               defip_table_size -                        \
  11486                               SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1;
  11487 
  11488         /* Configured VRF range */
  11489         prev_idx = (ALPM_MAX_PFX_INDEX/3);
  11490         SOC_ALPM_LPM_STATE_PREV(unit, (ALPM_MAX_PFX_INDEX/3)) = -1;
  11491         for (idx = ((ALPM_MAX_PFX_INDEX/3)-1); idx > -1; idx--) {
  11492             if (-1 == SOC_ALPM_LPM_STATE_START(unit, idx)) {
  11493                 continue;
  11494             }
  11495 
  11496             SOC_ALPM_LPM_STATE_PREV(unit, idx) = prev_idx;
  11497             SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = idx;
  11498 
  11499             SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) =                    \
  11500                               SOC_ALPM_LPM_STATE_START(unit, idx) -      \
  11501                               SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1;
  11502             prev_idx = idx;
  11503         }
  11504         SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = -1;
  11505         SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) =                         \
  11506                               (defip_table_size >> 1) -                   \
  11507                               SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1;
  11508     }
  11509 
  11510     return (SOC_E_NONE);
  11511 }
  11512 
  11513 int
  11514 soc_th_alpm_warmboot_lpm_reinit(int unit,
  11515                              int ipv6,
  11516                              int idx,
  11517                              void *lpm_entry)
  11518 {
  11519     int pfx_len;
  11520     int flex;
  11521     defip_entry_t lpm_entry_hi;
  11522     int vrf_id, vrf;
  11523 
  11524     if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VALID0f) ||
  11525         SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VALID1f)) {
  11526             LPM_HASH_INSERT(unit, lpm_entry, idx, NULL, NULL);
  11527     }
  11528 
  11529     if (ipv6) {
  11530         if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VALID0f)) {
  11531             SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf));
  11532             if (!VRF_FLEX_COMPLETED(unit, vrf_id, vrf, ipv6)) {
  11533                 flex = _soc_th_alpm_lpm_flex_get(unit, ipv6,
  11534                             SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm,
  11535                             lpm_entry, ENTRY_VIEW0f));
  11536                 VRF_FLEX_SET(unit, vrf_id, vrf, ipv6, flex);
  11537             }
  11538             VRF_PIVOT_REF_INC(unit, vrf_id, vrf, ipv6);
  11539         }
  11540     } else {
  11541         if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VALID0f)) {
  11542             SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf));
  11543             if (!VRF_FLEX_COMPLETED(unit, vrf_id, vrf, ipv6)) {
  11544                 flex = _soc_th_alpm_lpm_flex_get(unit, ipv6,
  11545                             SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm,
  11546                             lpm_entry, ENTRY_VIEW0f));
  11547                 VRF_FLEX_SET(unit, vrf_id, vrf, ipv6, flex);
  11548             }
  11549             VRF_PIVOT_REF_INC(unit, vrf_id, vrf, ipv6);
  11550         }
  11551         if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VALID1f)) {
  11552             soc_th_alpm_lpm_ip4entry1_to_0(unit, lpm_entry, &lpm_entry_hi, TRUE);
  11553             SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(unit, &lpm_entry_hi, &vrf_id, &vrf));
  11554             if (!VRF_FLEX_COMPLETED(unit, vrf_id, vrf, ipv6)) {
  11555                 flex = _soc_th_alpm_lpm_flex_get(unit, ipv6,
  11556                             SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm,
  11557                             lpm_entry, ENTRY_VIEW1f));
  11558                 VRF_FLEX_SET(unit, vrf_id, vrf, ipv6, flex);
  11559             }
  11560             VRF_PIVOT_REF_INC(unit, vrf_id, vrf, ipv6);
  11561         }
  11562     }
  11563 
  11564     if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VALID0f)) {
  11565         SOC_IF_ERROR_RETURN
  11566             (_soc_th_alpm_lpm_prefix_length_get(unit, ipv6, lpm_entry,
  11567                                                 &pfx_len, 0, 0));
  11568 
  11569         if (SOC_ALPM_LPM_STATE_VENT(unit, pfx_len) == 0) {
  11570             SOC_ALPM_LPM_STATE_START(unit, pfx_len) = idx;
  11571             SOC_ALPM_LPM_STATE_END(unit, pfx_len) = idx;
  11572         } else {
  11573             SOC_ALPM_LPM_STATE_END(unit, pfx_len) = idx;
  11574         }
  11575 
  11576         SOC_ALPM_LPM_STATE_VENT(unit, pfx_len)++;
  11577 
  11578         if (ipv6) {
  11579             /* IPv6 entry */
  11580             return (SOC_E_NONE);
  11581         }
  11582     } else {
  11583         /* Check upper half of lpm_entry */
  11584         if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VALID1f)) {
  11585             if (ipv6) {
  11586                 return SOC_E_NONE;
  11587             }
  11588 
  11589             /* Get prefix length */
  11590             SOC_IF_ERROR_RETURN
  11591                 (_soc_th_alpm_lpm_prefix_length_get(unit, ipv6, &lpm_entry_hi,
  11592                                                     &pfx_len, 0, 0));
  11593 
  11594             if (SOC_ALPM_LPM_STATE_VENT(unit, pfx_len) == 0) {
  11595                 SOC_ALPM_LPM_STATE_START(unit, pfx_len) = idx;
  11596                 SOC_ALPM_LPM_STATE_END(unit, pfx_len) = idx;
  11597             } else {
  11598                 SOC_ALPM_LPM_STATE_END(unit, pfx_len) = idx;
  11599             }
  11600 
  11601             SOC_ALPM_LPM_STATE_VENT(unit, pfx_len)++;
  11602         }
  11603     }
  11604     return (SOC_E_NONE);
  11605 }
  11606 
  11607 /* Walk through all ALPM table to check if uRPF entries is installing well */
  11608 void
  11609 soc_th_alpm_dbg_urpf(int u)
  11610 {
  11611     int         rv = SOC_E_NONE;
  11612     soc_mem_t   mem;
  11613     int         i, phy_bkt;
  11614     int         index;
  11615     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
  11616     uint32      eu[SOC_MAX_MEM_FIELD_WORDS];
  11617 
  11618     int         good = 0, bad = 0;
  11619 
  11620     if (!SOC_URPF_STATUS_GET(u)) {
  11621         LOG_CLI((BSL_META_U(u, "Only supported in uRPF mode\n")));
  11622         return ;
  11623     }
  11624 
  11625     for (phy_bkt = 0; phy_bkt <= ALPM_CTRL(u).num_bkts / 2; phy_bkt++) {
  11626         index = SOC_TH_ALPM_AIDX(u, phy_bkt, 0, 0, 0);
  11627         mem = soc_alpm_cmn_bkt_view_get(u, index);
  11628 
  11629         /* Iter entry based on memory type */
  11630         for (i = 0; i < SOC_TH_MAX_BUCKET_ENTRIES(u) - 1; i++) {
  11631             rv = _soc_th_alpm_mem_index(u, mem, phy_bkt, i, 0, &index);
  11632             if (SOC_FAILURE(rv)) {
  11633                 continue;
  11634             }
  11635 
  11636             sal_memset(e, 0, sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS);
  11637             sal_memset(eu, 0, sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS);
  11638 
  11639             rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, index, e);
  11640             if (SOC_FAILURE(rv)) {
  11641                 continue;
  11642             }
  11643             if (soc_mem_field32_get(u, mem, e, VALIDf) == 0) {
  11644                 continue;
  11645             }
  11646 
  11647             soc_mem_field32_set(u, mem, e, HITf, 0);
  11648 
  11649             rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, _soc_th_alpm_rpf_entry(u, index), eu);
  11650             if (SOC_FAILURE(rv)) {
  11651                 continue;
  11652             }
  11653             soc_mem_field32_set(u, mem, eu, HITf, 0);
  11654             soc_mem_field32_set(u, mem, eu, RPEf, 0);
  11655 
  11656             if (sal_memcmp(e, eu, sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS) != 0) {
  11657                 LOG_CLI((BSL_META_U(u,
  11658                             "uRPF sanity check failed: bucket %4d mem %s index %d uRPF index %d\n"),
  11659                             phy_bkt, SOC_MEM_NAME(u, mem), index, _soc_th_alpm_rpf_entry(u, index)));
  11660                 bad ++;
  11661             } else {
  11662                 good ++;
  11663             }
  11664         }
  11665     }
  11666 
  11667     LOG_CLI((BSL_META_U(u, "uRPF Sanity check finished, good %d bad %d\n"), good, bad));
  11668 
  11669     return ;
  11670 }
  11671 
  11672 /* Helper structure for Debug Counter */
  11673 typedef struct _alpm_dbg_cnt_s {
  11674     int v4;         /* Counter for IPv4 */
  11675     int v6_64;
  11676     int v6_128;
  11677     int v4t;        /* Totaled counter for IPv4 per VRF */
  11678     int v6_64t;
  11679     int v6_128t;
  11680     int used;
  11681 } _alpm_dbg_cnt_t;
  11682 
  11683 typedef enum _alpm_pvt_cnt_type_e {
  11684     SOC_ALPM_DEBUG_CNT_ADD = 0,
  11685     SOC_ALPM_DEBUG_CNT_DEL,
  11686     SOC_ALPM_DEBUG_CNT_SPLIT,
  11687     SOC_ALPM_DEBUG_CNT_USED,
  11688     SOC_ALPM_DEBUG_CNT_LPM_SHIFT,
  11689     SOC_ALPM_DEBUG_CNT_LPM_FULL
  11690 } _alpm_pvt_cnt_type_t;
  11691 
  11692 
  11693 #define _ALPM_DBG_CNT_ADD(dst_dc, src_dc)       \
  11694     do {                                        \
  11695         (dst_dc)->v4 += (src_dc)->v4;           \
  11696         (dst_dc)->v4t += (src_dc)->v4t;         \
  11697         (dst_dc)->v6_64 += (src_dc)->v6_64;     \
  11698         (dst_dc)->v6_64t += (src_dc)->v6_64t;   \
  11699         (dst_dc)->v6_128 += (src_dc)->v6_128;   \
  11700         (dst_dc)->v6_128t += (src_dc)->v6_128t; \
  11701     } while (0)
  11702 
  11703 /* Common debug counter print */
  11704 #define PRINT_SPLIT_LINE(u)    \
  11705     LOG_CLI((BSL_META_U(u, "-----------------------------------------------\n")))
  11706 #define PRINT_VRF_HEADER(u)    \
  11707     LOG_CLI((BSL_META_U(u, "\n      VRF  v4      v6-64   v6-128  |   AVG\n")))
  11708 #define PRINT_VRF_NOT_FOUND(u) \
  11709     LOG_CLI((BSL_META_U(u, "%9s\n"), "Specific VRF not found"))
  11710 
  11711 /* Print Bucket Occupancy */
  11712 #define BKT_PERCENT(used, tot) \
  11713     (tot) ? (used) * 100 / (tot) : 0, (tot) ? (used) * 1000 / (tot) % 10 : 0
  11714 #define PRINT_BKT_OCCU_ITEM(u, vrf, tmp_dc) \
  11715     do { \
  11716         LOG_CLI((BSL_META_U(u, \
  11717                             "%9d  %02d.%d%%   %02d.%d%%   %02d.%d%%   |   %02d.%d%% %5s\n"), \
  11718                  (vrf), BKT_PERCENT(tmp_dc->v4, tmp_dc->v4t), \
  11719                  BKT_PERCENT(tmp_dc->v6_64, tmp_dc->v6_64t), \
  11720                  BKT_PERCENT(tmp_dc->v6_128, tmp_dc->v6_128t), \
  11721                  BKT_PERCENT((tmp_dc->v4+tmp_dc->v6_64+tmp_dc->v6_128),\
  11722                  (tmp_dc->v4t+tmp_dc->v6_64t+tmp_dc->v6_128t)), \
  11723                  (vrf) == SOC_VRF_MAX(u)+1 ? "GLo" : "")); \
  11724     } while (0)
  11725 #define PRINT_BKT_OCCU_ITEM_TOT(u, all_dc) \
  11726     do { \
  11727         LOG_CLI((BSL_META_U(u, \
  11728                             "%9s  %02d.%d%%   %02d.%d%%   %02d.%d%%   |   %02d.%d%% \n"), \
  11729                  "AVG", BKT_PERCENT((all_dc)->v4, (all_dc)->v4t), \
  11730                  BKT_PERCENT((all_dc)->v6_64, (all_dc)->v6_64t), \
  11731                  BKT_PERCENT((all_dc)->v6_128, (all_dc)->v6_128t), \
  11732                  BKT_PERCENT(((all_dc)->v4+(all_dc)->v6_64+(all_dc)->v6_128),\
  11733                  ((all_dc)->v4t+(all_dc)->v6_64t+(all_dc)->v6_128t)))); \
  11734     } while (0)
  11735 
  11736 
  11737 /* Print VRF based debug counter */
  11738 #define PRINT_VRF_ITEM(u, vrf, v4, v6_64, v6_128, total) \
  11739     do { \
  11740         LOG_CLI((BSL_META_U(u, \
  11741                             "%9d  %-7d %-7d %-7d |   %-7d %s\n"), \
  11742                  (vrf == MAX_VRF_ID ? -1 : vrf), (v4), (v6_64),\
  11743                  (v6_128), (total), (vrf) == MAX_VRF_ID ? "GHi" : \
  11744                  (vrf) == SOC_VRF_MAX(u)+1 ? "GLo" : "")); \
  11745     } while (0)
  11746 #define PRINT_VRF_ITEM_TOT(u, v4, v6_64, v6_128, total) \
  11747     do { \
  11748         LOG_CLI((BSL_META_U(u, \
  11749                             "%9s  %-7d %-7d %-7d |   %-7d \n"), "Total", (v4), (v6_64),\
  11750                  (v6_128), (total))); \
  11751     } while (0)
  11752 
  11753 #define PRINT_BUCKET_HEADER(u) \
  11754    do { \
  11755         LOG_CLI((BSL_META_U(u, \
  11756                             "\nPivot/VRF  Min     Max     Cur     |   Comment\n"))); \
  11757     } while (0)
  11758 #define PRINT_BUCKET_ITEM(u, bkt, vrf, min, max, cur, def) \
  11759     do { \
  11760         LOG_CLI((BSL_META_U(u, \
  11761                             "%5d/%-4d %-7d %-7d %-7d |   %-7s\n"), bkt, vrf, \
  11762                  min, max, cur, def ? "Def" : \
  11763                  (vrf) == SOC_VRF_MAX(u)+1 ? "GLo" : "")); \
  11764     } while (0)
  11765 
  11766 /* Get max available IPv4, IPv6-64, IPv6-128 entry numbers */
  11767 static void
  11768 _soc_th_alpm_pivot_max_get(int u, alpm_vrf_counter_t *pvt_max)
  11769 {
  11770     pvt_max->v4 = soc_mem_index_count(u, L3_DEFIPm) * 2;
  11771     pvt_max->v6_128 = soc_mem_index_count(u, L3_DEFIP_PAIR_128m);
  11772 
  11773     if (SOC_ALPM_128B_ENABLE(u)) {
  11774         pvt_max->v6_64 = pvt_max->v6_128;
  11775     } else {
  11776         pvt_max->v6_64 = pvt_max->v4 >> 1;
  11777     }
  11778 
  11779     if (SOC_URPF_STATUS_GET(u)) {
  11780         pvt_max->v4 >>= 1;
  11781         pvt_max->v6_128 >>= 1;
  11782         pvt_max->v6_64 >>= 1;
  11783     }
  11784 }
  11785 
  11786 static void
  11787 _soc_th_alpm_pivot_debug_dump(int u, int vrf_id, alpm_vrf_handle_t *vh,
  11788                                    _alpm_pvt_cnt_type_t pct)
  11789 {
  11790     alpm_vrf_counter_t *vc;
  11791     int i, tv4c, tv6_64c, tv6_128c;
  11792     int found = 0;
  11793 
  11794     alpm_vrf_counter_t pvt_max;
  11795 
  11796     /* Print Pivot debug info header */
  11797     switch (pct) {
  11798     case SOC_ALPM_DEBUG_CNT_ADD:
  11799         LOG_CLI((BSL_META_U(u,
  11800                             "\nAdd Counter:\n")));
  11801         break;
  11802     case SOC_ALPM_DEBUG_CNT_DEL:
  11803         LOG_CLI((BSL_META_U(u,
  11804                             "\nDelete Counter:\n")));
  11805         break;
  11806     case SOC_ALPM_DEBUG_CNT_SPLIT:
  11807         LOG_CLI((BSL_META_U(u,
  11808                             "\nInternal Debug Counter - Split:\n")));
  11809         break;
  11810     case SOC_ALPM_DEBUG_CNT_USED:
  11811         _soc_th_alpm_pivot_max_get(u, &pvt_max);
  11812         LOG_CLI((BSL_META_U(u,
  11813                             "\nPivot Occupancy: Max v4/v6-64/v6-128 = %d/%d/%d\n"),
  11814                  pvt_max.v4, pvt_max.v6_64, pvt_max.v6_128));
  11815         break;
  11816     case SOC_ALPM_DEBUG_CNT_LPM_SHIFT:
  11817         LOG_CLI((BSL_META_U(u,
  11818                             "\nInternal Debug Counter - LPM Shift:\n")));
  11819         break;
  11820     case SOC_ALPM_DEBUG_CNT_LPM_FULL:
  11821         LOG_CLI((BSL_META_U(u,
  11822                             "\nInternal Debug Counter - LPM Full:\n")));
  11823         break;
  11824     default:
  11825         break;
  11826     }
  11827     PRINT_VRF_HEADER(u);
  11828     PRINT_SPLIT_LINE(u);
  11829 
  11830     tv4c = tv6_64c = tv6_128c = 0;
  11831     for (i = 0; i < MAX_VRF_ID + 1; i++) {
  11832         int v4c, v6_64c, v6_128c;
  11833         if (vh[i].init_done == 0 && i != MAX_VRF_ID) {
  11834             continue;
  11835         }
  11836         if (vrf_id != -1 && vrf_id != i) {
  11837             continue;
  11838         }
  11839 
  11840         found = 1;
  11841 
  11842         switch (pct) {
  11843         case SOC_ALPM_DEBUG_CNT_ADD:
  11844             vc = &vh[i].add;
  11845             break;
  11846         case SOC_ALPM_DEBUG_CNT_DEL:
  11847             vc = &vh[i].del;
  11848             break;
  11849         case SOC_ALPM_DEBUG_CNT_SPLIT:
  11850             vc = &vh[i].bkt_split;
  11851             break;
  11852         case SOC_ALPM_DEBUG_CNT_LPM_SHIFT:
  11853             vc = &vh[i].lpm_shift;
  11854             break;
  11855         case SOC_ALPM_DEBUG_CNT_LPM_FULL:
  11856             vc = &vh[i].lpm_full;
  11857             break;
  11858         case SOC_ALPM_DEBUG_CNT_USED:
  11859             vc = &vh[i].pivot_used;
  11860             break;
  11861         default:
  11862             vc = &vh[i].pivot_used;
  11863             break;
  11864         }
  11865 
  11866         v4c = vc->v4;
  11867         v6_64c = vc->v6_64;
  11868         v6_128c = vc->v6_128;
  11869 
  11870         tv4c += v4c;
  11871         tv6_64c += v6_64c;
  11872         tv6_128c += v6_128c;
  11873 
  11874         PRINT_VRF_ITEM(u, i, v4c, v6_64c, v6_128c, (v4c+v6_64c+v6_128c));
  11875     }
  11876     if (found == 0) {
  11877         PRINT_VRF_NOT_FOUND(u);
  11878     } else {
  11879         PRINT_SPLIT_LINE(u);
  11880         PRINT_VRF_ITEM_TOT(u, tv4c, tv6_64c, tv6_128c, (tv4c+tv6_64c+tv6_128c));
  11881     }
  11882 
  11883     return ;
  11884 }
  11885 
  11886 /* vrf_id -1 indicates all vrf */
  11887 int
  11888 soc_th_alpm_debug_show(int u, int vrf_id, uint32 flags)
  11889 {
  11890     int i, alloc_sz, found = 0;
  11891     _alpm_dbg_cnt_t *alpm_dc_arr;
  11892     _alpm_dbg_cnt_t bkt_ent_max;
  11893     _alpm_dbg_cnt_t all_dc;
  11894 
  11895     if (vrf_id > (SOC_VRF_MAX(u) + 1)) {
  11896         return SOC_E_PARAM;
  11897     }
  11898 
  11899     alloc_sz = MAX_VRF_ID * sizeof(_alpm_dbg_cnt_t);
  11900     alpm_dc_arr = sal_alloc(alloc_sz, "_alpm_dbg_cnt");
  11901     if (alpm_dc_arr == NULL) {
  11902         return SOC_E_MEMORY;
  11903     }
  11904     sal_memset(alpm_dc_arr, 0, alloc_sz);
  11905 
  11906     /* Collect data */
  11907     bkt_ent_max.v4 = ALPM_IPV4_BKT_COUNT;
  11908     bkt_ent_max.v6_64 = ALPM_IPV6_64_BKT_COUNT;
  11909     bkt_ent_max.v6_128 = ALPM_IPV6_128_BKT_COUNT;
  11910 
  11911     if (SOC_IS_TRIDENT3X(u)) {
  11912         bkt_ent_max.v4 <<= 1;
  11913         bkt_ent_max.v6_64  <<= 1;
  11914         bkt_ent_max.v6_128 <<= 1;
  11915     }
  11916 
  11917     if (ALPM_CTRL(u).double_wide[L3_DEFIP_MODE_V4]) {
  11918         bkt_ent_max.v4 <<= 1;
  11919     }
  11920     if (ALPM_CTRL(u).double_wide[L3_DEFIP_MODE_64]) {
  11921         bkt_ent_max.v6_64 <<= 1;
  11922     }
  11923     if (ALPM_CTRL(u).double_wide[L3_DEFIP_MODE_128]) {
  11924         bkt_ent_max.v6_128 <<= 1;
  11925     }
  11926 
  11927     /* 1. Bucket Occupancy */
  11928     if (flags & (SOC_ALPM_DEBUG_SHOW_FLAG_BKT)) {
  11929         LOG_CLI((BSL_META_U(u,
  11930                             "\nBucket Occupancy:\n")));
  11931         PRINT_BUCKET_HEADER(u);
  11932         PRINT_SPLIT_LINE(u);
  11933     }
  11934     for (i = 0; i < TH_MAX_PIVOT_COUNT(u); i++) {
  11935         alpm_pivot_t *p = ALPM_TCAM_PIVOT(u, i);
  11936         if (p != NULL) {
  11937             _alpm_dbg_cnt_t *tmp_dc;
  11938             int vrf = PIVOT_BUCKET_VRF(p);
  11939 
  11940             if (vrf < 0 || vrf > (SOC_VRF_MAX(u) + 1)) {
  11941                 continue;
  11942             }
  11943 
  11944             if (vrf_id != -1 && vrf_id != vrf) {
  11945                 continue;
  11946             }
  11947 
  11948             if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_BKT) {
  11949                 found = 1;
  11950                 PRINT_BUCKET_ITEM(u, i, vrf,
  11951                                   PIVOT_BUCKET_MIN(p),
  11952                                   PIVOT_BUCKET_MAX(p),
  11953                                   PIVOT_BUCKET_COUNT(p),
  11954                                   PIVOT_BUCKET_DEF(p));
  11955             }
  11956 
  11957             tmp_dc = &alpm_dc_arr[vrf];
  11958             if (PIVOT_BUCKET_IPV6(p) == L3_DEFIP_MODE_128) {
  11959                 tmp_dc->v6_128 += PIVOT_BUCKET_COUNT(p);
  11960                 tmp_dc->v6_128t += bkt_ent_max.v6_128;
  11961             } else if (PIVOT_BUCKET_IPV6(p) == L3_DEFIP_MODE_64) {
  11962                 tmp_dc->v6_64 += PIVOT_BUCKET_COUNT(p);
  11963                 tmp_dc->v6_64t += bkt_ent_max.v6_64;
  11964             } else {
  11965                 tmp_dc->v4 += PIVOT_BUCKET_COUNT(p);
  11966                 tmp_dc->v4t += bkt_ent_max.v4;
  11967             }
  11968             tmp_dc->used = TRUE;
  11969         }
  11970     }
  11971 
  11972     if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_BKT) {
  11973         if (found == 0) {
  11974             PRINT_VRF_NOT_FOUND(u);
  11975         }
  11976     }
  11977 
  11978     sal_memset(&all_dc, 0, sizeof(all_dc));
  11979     found = 0;
  11980 
  11981     if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_BKTUSG) {
  11982         LOG_CLI((BSL_META_U(u,
  11983                             "\nBucket Usage:\n")));
  11984         PRINT_VRF_HEADER(u);
  11985         PRINT_SPLIT_LINE(u);
  11986         for (i = 0; i < MAX_VRF_ID; i++) {
  11987             _alpm_dbg_cnt_t *tmp_dc;
  11988             if (alpm_dc_arr[i].used != TRUE) {
  11989                 continue;
  11990             }
  11991             if (vrf_id != -1 && vrf_id != i) {
  11992                 continue;
  11993             }
  11994 
  11995             found = 1;
  11996             tmp_dc = &alpm_dc_arr[i];
  11997             _ALPM_DBG_CNT_ADD(&all_dc, tmp_dc);
  11998             PRINT_BKT_OCCU_ITEM(u, i, tmp_dc);
  11999         }
  12000         if (found == 0) {
  12001             PRINT_VRF_NOT_FOUND(u);
  12002         } else {
  12003             PRINT_SPLIT_LINE(u);
  12004             PRINT_BKT_OCCU_ITEM_TOT(u, &all_dc);
  12005         }
  12006     }
  12007 
  12008     /* 2. Pivot Occupancy */
  12009     if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_PVT) {
  12010         _soc_th_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u],
  12011                                            SOC_ALPM_DEBUG_CNT_USED);
  12012     }
  12013 
  12014     /* 3. Add/Delete counters per VRF/ip type */
  12015     if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_CNT) {
  12016         _soc_th_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u],
  12017                                    SOC_ALPM_DEBUG_CNT_ADD);
  12018 
  12019         _soc_th_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u],
  12020                                    SOC_ALPM_DEBUG_CNT_DEL);
  12021     }
  12022 
  12023     /* 4. Total No. of bucket splits per VRF/ip type */
  12024     if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_INTDBG) {
  12025         _soc_th_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u],
  12026                                    SOC_ALPM_DEBUG_CNT_SPLIT);
  12027         _soc_th_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u],
  12028                                    SOC_ALPM_DEBUG_CNT_LPM_FULL);
  12029         _soc_th_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u],
  12030                                    SOC_ALPM_DEBUG_CNT_LPM_SHIFT);
  12031     }
  12032 
  12033     sal_free(alpm_dc_arr);
  12034 
  12035     return SOC_E_NONE;
  12036 }
  12037 
  12038 void
  12039 soc_th_alpm_debug_cntr_show(int u)
  12040 {
  12041     LOG_CLI(("====ALPM=Internal=Debug=Counter====\n"));
  12042     LOG_CLI(("%-24s%d\n", "Bucket Split:", _alpm_dbg_cntr[u].bkt_split));
  12043     LOG_CLI(("%-24s%d\n", "Bucket Share:", _alpm_dbg_cntr[u].bkt_share));
  12044     LOG_CLI(("%-24s%d\n", "Bucket Merge:", _alpm_dbg_cntr[u].bkt_merge));
  12045     LOG_CLI(("%-24s%d\n", "Bucket MergeDuringRp:", _alpm_dbg_cntr[u].bkt_merge2));
  12046     LOG_CLI(("%-24s%d\n", "Bucket Repartition:", _alpm_dbg_cntr[u].bkt_repart));
  12047     LOG_CLI(("%-24s%d\n", "Propagation Insert CB:",
  12048             _alpm_dbg_cntr[u].ppg_cb_insert));
  12049     LOG_CLI(("%-24s%d\n", "Propagation Delete CB:",
  12050             _alpm_dbg_cntr[u].ppg_cb_delete));
  12051     LOG_CLI(("%-24s%d\n", "Propagation Hitbit CB:",
  12052             _alpm_dbg_cntr[u].ppg_cb_hitbit));
  12053 }
  12054 
  12055 int
  12056 soc_th_alpm_debug_index_mapping(int u)
  12057 {
  12058     int idx, m, err = 0;
  12059     int log_idx, phy_idx;
  12060     soc_mem_t mem[2] = {L3_DEFIPm, L3_DEFIP_PAIR_128m};
  12061     int max_index = SOC_L3_DEFIP_TCAM_DEPTH_GET(u) *
  12062                     SOC_L3_DEFIP_MAX_TCAMS_GET(u);
  12063 
  12064     for (m = 0; m < 2; m++) {
  12065         for (idx = 0; idx < soc_mem_index_count(u, mem[m]); idx++) {
  12066             phy_idx = soc_th_alpm_physical_idx(u, mem[m], idx, 1);
  12067             log_idx = soc_th_alpm_logical_idx(u, mem[m], phy_idx, 1);
  12068             if (phy_idx < 0 || phy_idx >= max_index || idx != log_idx) {
  12069                 LOG_CLI(("ALPM index mapping testing failed %17s "
  12070                          "loc(%d)->phy(%d)->loc(%d)\n",
  12071                          SOC_MEM_NAME(u, mem[m]), idx, phy_idx, log_idx));
  12072                 err++;
  12073                 break;
  12074             }
  12075         }
  12076     }
  12077 
  12078     if (!err) {
  12079         LOG_CLI(("ALPM index mapping testing passed\n"));
  12080     }
  12081 
  12082     if (err) {
  12083         return SOC_E_FAIL;
  12084     } else {
  12085         return SOC_E_NONE;
  12086     }
  12087 }
  12088 
  12089 int
  12090 soc_th_alpm_debug_brief_show(int u, int phy_bkt, int index)
  12091 {
  12092     int i, j, rv = SOC_E_NONE;
  12093     uint32 rval, alpm = 0, mode = 0, urpf, bit128, fv, bnkbits;
  12094     int v4used = 0, v4max;
  12095     int v6_64used = 0, v6_64max;
  12096     int v6_128used = 0, v6_128max;
  12097     int bucket_used = 0, bucket_max;
  12098     char *lpm_tbl_ptr = NULL;
  12099     defip_entry_t *lpm_entry;               /* Hw entry buffer.             */
  12100     defip_pair_128_entry_t *lpm_entry_p128; /* Hw entry buffer.             */
  12101     int ipv6, bkt_ptr, gh, gr, use_alpm;
  12102     int *bktref = NULL;
  12103     int glb_hi_cnt = 0, glb_lo_cnt = 0;
  12104     soc_mem_t lpm_mem;
  12105     int bs11 = 0, bs21 = 0, bs31 = 0, bs41 = 0, alloc_size;
  12106     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
  12107     soc_field_t fldv, fldb, fldg, fldr;
  12108     int alpm_bkt_bits = ALPM_CTRL(u).bkt_bits;
  12109 
  12110     char *mode_str[] = {
  12111         "LPM",
  12112         "ALPM-Combined",
  12113         "ALPM-Parallel",
  12114         "ALPM-TCAM_ALPM",
  12115         "ALPM-Invalid"
  12116     };
  12117     char *ipver_str[] = {
  12118         "IPv4",
  12119         "IPv6-64",
  12120         "IPv6-128"
  12121     };
  12122 
  12123     char *rtype_str[] = {
  12124         "Global",
  12125         "Private"
  12126     };
  12127 
  12128     char *dw_str = "Double Wide";
  12129     char *sw_str = "Single Wide";
  12130 
  12131     LOG_CLI(("\n"));
  12132     LOG_CLI(("SW Status:\n"));
  12133     LOG_CLI(("%-24s", "Mode:"));
  12134 
  12135     if (ALPM_CTRL(u).ctrl_inited) {
  12136         switch (ALPM_CTRL(u).alpm_mode) {
  12137             case -1:
  12138                 LOG_CLI(("%s\n", mode_str[0]));
  12139                 break;
  12140             case SOC_ALPM_MODE_COMBINED:
  12141                 LOG_CLI(("%s\n", mode_str[1]));
  12142                 break;
  12143             case SOC_ALPM_MODE_PARALLEL:
  12144                 LOG_CLI(("%s\n", mode_str[2]));
  12145                 break;
  12146             case SOC_ALPM_MODE_TCAM_ALPM:
  12147                 LOG_CLI(("%s\n", mode_str[3]));
  12148                 break;
  12149             default:
  12150                 break;
  12151         }
  12152     } else {
  12153         LOG_CLI(("%s\n", mode_str[0]));
  12154     }
  12155     urpf = SOC_URPF_STATUS_GET(u);
  12156     LOG_CLI(("%-24s%s\n", "uRPF:", urpf ? "Enable" : "Disable"));
  12157     bit128 = !!soc_mem_index_count(u, L3_DEFIP_PAIR_128m);
  12158     LOG_CLI(("%-24s%d\n", "IPv6 Bits:", bit128 ? 128 : 64));
  12159     for (i = 0; i <= L3_DEFIP_MODE_128; i++) {
  12160         LOG_CLI(("%-24s%s | %2d EPBkt | %2d EPBnk\n",
  12161                 ipver_str[i],
  12162                 ALPM_CTRL(u).double_wide[i] ? dw_str : sw_str,
  12163                 ALPM_CTRL(u).cnt_ent_per_bkt[i],
  12164                 ALPM_CTRL(u).ent_per_bank[i]));
  12165     }
  12166     LOG_CLI(("%-24s%d\n", "Num Banks:", ALPM_CTRL(u).num_banks));
  12167     LOG_CLI(("%-24s%d\n", "Bank bits:", ALPM_CTRL(u).bank_bits));
  12168     LOG_CLI(("%-24s%d\n", "Num Buckets:", ALPM_CTRL(u).num_bkts));
  12169     LOG_CLI(("%-24s%d\n", "Bucket bits:", ALPM_CTRL(u).bkt_bits));
  12170     LOG_CLI(("%-24s0x%x\n", "Bucket Mask:", ALPM_CTRL(u).bkt_mask));
  12171     LOG_CLI(("%-24s%s\n", "Bucket sharing:",
  12172             ALPM_CTRL(u).bkt_sharing ? "Enable" : "Disable"));
  12173     LOG_CLI(("Disabled bank bitmap:\n"));
  12174     for (i = 0; i < 2; i++) {
  12175         LOG_CLI(("\t%-16s0x%2x\n", rtype_str[i],
  12176                 ALPM_CTRL(u).bank_disable_bmp[i]));
  12177     }
  12178     LOG_CLI(("Disabled bank bitmap(8b):\n"));
  12179     for (i = 0; i < 2; i++) {
  12180         LOG_CLI(("\t%-16s0x%2x\n", rtype_str[i],
  12181                 ALPM_CTRL(u).bank_disable_bmp_8b[i]));
  12182     }
  12183     LOG_CLI(("%-24s%s\n", "Global/Private Zoned:",
  12184             ALPM_CTRL(u).gp_zoned ? "Yes" : "No"));
  12185     LOG_CLI(("%-24s%s\n", "SW Prefix Lookup:",
  12186             ALPM_CTRL(u).sw_prefix_lkup ? "Yes" : "No"));
  12187 
  12188     soc_th_alpm_debug_index_mapping(u);
  12189 
  12190     LOG_CLI(("\n"));
  12191     LOG_CLI(("HW Status:\n"));
  12192 
  12193     SOC_IF_ERROR_RETURN(READ_L3_DEFIP_RPF_CONTROLr(u, &rval));
  12194     alpm = soc_reg_field_get(u, L3_DEFIP_RPF_CONTROLr, rval, LPM_MODEf);
  12195     if (alpm != 0) {
  12196         mode = soc_reg_field_get(u, L3_DEFIP_RPF_CONTROLr, rval, LOOKUP_MODEf);
  12197     }
  12198     urpf = soc_reg_field_get(u, L3_DEFIP_RPF_CONTROLr, rval, DEFIP_RPF_ENABLEf);
  12199 
  12200     LOG_CLI(("\n"));
  12201     LOG_CLI(("%-24s%s\n", "Mode:", mode_str[alpm + mode]));
  12202     LOG_CLI(("%-24s%s\n", "uRPF:", urpf ? "Enable" : "Disable"));
  12203     bit128 = !!soc_mem_index_count(u, L3_DEFIP_PAIR_128m);
  12204     LOG_CLI(("%-24s%d\n", "IPv6 Bits:", bit128 ? 128 : 64));
  12205     if (alpm == 0) {
  12206         return SOC_E_NONE;
  12207     }
  12208 
  12209     if (mode == 0 && !urpf) {       /* Combined mode && uRPF */
  12210         if (SOC_IS_TRIDENT3X(u)) {
  12211             fv = 1;
  12212         } else {
  12213             fv = soc_reg_field_get(u, L3_DEFIP_RPF_CONTROLr, rval,
  12214                                    ENABLE_DOUBLE_WIDE_BUCKETS_FOR_IPV4f);
  12215         }
  12216     } else if (mode == 2) {         /* TCAM/ALPM mode */
  12217         fv = 1;
  12218     } else {                        /* Parallel mode */
  12219         fv = 0;
  12220     }
  12221     LOG_CLI(("%-24s%s\n", "IPv4:", fv ? dw_str : sw_str));
  12222 
  12223     if (mode == 0 && !urpf) {       /* Combined mode && uRPF */
  12224         fv = 1;
  12225     } else if (mode == 2) {         /* TCAM/ALPM mode */
  12226         fv = 1;
  12227     } else {                        /* Parallel mode */
  12228         fv = 0;
  12229     }
  12230     LOG_CLI(("%-24s%s\n", "IPv6-64:", fv ? dw_str : sw_str));
  12231     LOG_CLI(("%-24s%s\n", "IPv6-128:", fv ? dw_str : sw_str));
  12232 
  12233     if (SOC_REG_IS_VALID(u, ISS_LOG_TO_PHY_BANK_MAP_2r)) {
  12234         SOC_IF_ERROR_RETURN(READ_ISS_LOG_TO_PHY_BANK_MAP_2r(u, &rval));
  12235         bnkbits = soc_reg_field_get(u, ISS_LOG_TO_PHY_BANK_MAP_2r, rval,
  12236                                     ALPM_BANK_MODEf);
  12237     } else {
  12238         SOC_IF_ERROR_RETURN(READ_ISS_LOG_TO_PHY_BANK_MAPr(u, &rval));
  12239         bnkbits = soc_reg_field_get(u, ISS_LOG_TO_PHY_BANK_MAPr, rval,
  12240                                     ALPM_BANK_MODEf);
  12241     }
  12242     if (SOC_IS_TRIDENT3X(u)) {
  12243         LOG_CLI(("%-24s%d\n", "Num Banks:", bnkbits == 0 ? 8 : 4));
  12244     } else {
  12245         LOG_CLI(("%-24s%d\n", "Num Banks:", bnkbits == 0 ? 4 : 2));
  12246     }
  12247     if (bnkbits == 0) {
  12248         bnkbits = SOC_IS_TRIDENT3X(u) ? 0xff : 0xf;
  12249     } else {
  12250         bnkbits = SOC_IS_TRIDENT3X(u) ? 0xf : 0x3;
  12251     }
  12252     LOG_CLI(("---------------------------------------\n"));
  12253     /* Calculate utilization */
  12254     v4max = 2 * soc_mem_index_count(u, L3_DEFIPm);
  12255     v6_64max = bit128 ? soc_mem_index_count(u, L3_DEFIP_PAIR_128m) :
  12256                         soc_mem_index_count(u, L3_DEFIPm);
  12257     v6_128max = soc_mem_index_count(u, L3_DEFIP_PAIR_128m);
  12258     bucket_max = ALPM_CTRL(u).num_bkts;
  12259     if (urpf) {
  12260         v4max       >>= 1;
  12261         v6_64max    >>= 1;
  12262         v6_128max   >>= 1;
  12263         bucket_max  >>= 1;
  12264     }
  12265 
  12266     bktref = sal_alloc(bucket_max * sizeof(int), "bktref");
  12267     if (bktref == NULL) {
  12268         return SOC_E_MEMORY;
  12269     }
  12270     sal_memset(bktref, 0, bucket_max * sizeof(int));
  12271 
  12272     /* DMA LPM table to software copy */
  12273     lpm_mem = L3_DEFIPm;
  12274     alloc_size = WORDS2BYTES(soc_mem_entry_words(u, lpm_mem)) *
  12275                  soc_mem_index_count(u, lpm_mem);
  12276     lpm_tbl_ptr = soc_cm_salloc(u, alloc_size, "lpm_tbl");
  12277     if (lpm_tbl_ptr == NULL) {
  12278         rv = SOC_E_MEMORY;
  12279         goto _free_mem;
  12280     }
  12281     /* Reset allocated buffer. */
  12282     sal_memset(lpm_tbl_ptr, 0, alloc_size);
  12283 
  12284     /* Read table to the buffer. */
  12285     if (v4max && soc_mem_read_range(u, lpm_mem, MEM_BLOCK_ANY,
  12286                            soc_mem_index_min(u, lpm_mem),
  12287                            soc_mem_index_max(u, lpm_mem), lpm_tbl_ptr) < 0) {
  12288         rv = (SOC_E_INTERNAL);
  12289         goto _free_mem;
  12290     }
  12291 
  12292     for (i = 0; i < (v4max / 2); i++) {
  12293         /* Calculate entry offset */
  12294         lpm_entry =
  12295             soc_mem_table_idx_to_pointer(u, lpm_mem,
  12296                                          defip_entry_t *, lpm_tbl_ptr, i);
  12297         ipv6 = soc_mem_field32_get(u, lpm_mem, lpm_entry, MODE0_f(u));
  12298 
  12299         for (j = 0; j < (ipv6 ? 1 : 2); j++) {
  12300             if (j == 1) {
  12301                 fldv = VALID1f;
  12302             } else {
  12303                 fldv = VALID0f;
  12304             }
  12305             /* Make sure entry is valid. */
  12306             if (!soc_mem_field32_get(u, lpm_mem, lpm_entry, fldv)) {
  12307                 continue;
  12308             }
  12309 
  12310             if (ipv6) {
  12311                 v6_64used ++;
  12312             } else {
  12313                 v4used ++;
  12314             }
  12315 
  12316             if (j == 0) {
  12317                 fldg = GLOBAL_HIGH0f;
  12318                 fldb = ALG_BKT_PTR0f;
  12319                 fldr = GLOBAL_ROUTE0f;
  12320             } else {
  12321                 fldg = GLOBAL_HIGH1f;
  12322                 fldb = ALG_BKT_PTR1f;
  12323                 fldr = GLOBAL_ROUTE1f;
  12324             }
  12325 
  12326             gh = soc_mem_field32_get(u, lpm_mem, lpm_entry, fldg);
  12327             gr = soc_mem_field32_get(u, lpm_mem, lpm_entry, fldr);
  12328             if (gr) {
  12329                 if (gh) {
  12330                     glb_hi_cnt ++;
  12331                     use_alpm = 0;
  12332                 } else {
  12333                     glb_lo_cnt ++;
  12334                     use_alpm = (mode == 2) ? 0 : 1;
  12335                 }
  12336             } else {
  12337                 use_alpm = 1;
  12338             }
  12339 
  12340             if (use_alpm) {
  12341                 bkt_ptr = soc_mem_field32_get(u, lpm_mem, lpm_entry, fldb);
  12342                 if (bkt_ptr > bucket_max) {
  12343                     LOG_CLI(("Invalid phy_bkt pointer in %s index %d\n",
  12344                              SOC_MEM_NAME(u, lpm_mem), i));
  12345                 } else {
  12346                     bktref[bkt_ptr] ++;
  12347                 }
  12348             }
  12349         }
  12350     }
  12351 
  12352     soc_cm_sfree(u, lpm_tbl_ptr);
  12353 
  12354     /* l3_defip_pair_128 */
  12355     lpm_tbl_ptr = NULL;
  12356     lpm_mem = L3_DEFIP_PAIR_128m;
  12357     alloc_size = WORDS2BYTES(soc_mem_entry_words(u, lpm_mem)) *
  12358                  soc_mem_index_count(u, lpm_mem);
  12359     lpm_tbl_ptr = soc_cm_salloc(u, alloc_size, "lpm_tbl_p128");
  12360     if (lpm_tbl_ptr == NULL) {
  12361         rv = SOC_E_MEMORY;
  12362         goto _free_mem;
  12363     }
  12364     /* Reset allocated buffer. */
  12365     sal_memset(lpm_tbl_ptr, 0, alloc_size);
  12366 
  12367     /* Read table to the buffer. */
  12368     if (v6_128max && soc_mem_read_range(u, lpm_mem, MEM_BLOCK_ANY,
  12369                            soc_mem_index_min(u, lpm_mem),
  12370                            soc_mem_index_max(u, lpm_mem), lpm_tbl_ptr) < 0) {
  12371         rv = (SOC_E_INTERNAL);
  12372         goto _free_mem;
  12373     }
  12374 
  12375     for (i = 0; i < v6_128max; i++) {
  12376         /* Calculate entry offset */
  12377         lpm_entry_p128 =
  12378             soc_mem_table_idx_to_pointer(u, lpm_mem,
  12379                                 defip_pair_128_entry_t *, lpm_tbl_ptr, i);
  12380         /* Verify if read LPM entry is IPv6-128 entry */
  12381         if (0x03 != soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, MODE1_UPR_f(u))) {
  12382             continue;
  12383         };
  12384 
  12385         /* Verify if LPM entry is valid */
  12386         if (!soc_mem_field32_get(u, lpm_mem, lpm_entry_p128,
  12387                                     VALID1_LWRf) ||
  12388             !soc_mem_field32_get(u, lpm_mem, lpm_entry_p128,
  12389                                     VALID0_LWRf) ||
  12390             !soc_mem_field32_get(u, lpm_mem, lpm_entry_p128,
  12391                                     VALID1_UPRf) ||
  12392             !soc_mem_field32_get(u, lpm_mem, lpm_entry_p128,
  12393                                     VALID0_UPRf)) {
  12394             continue;
  12395         };
  12396 
  12397         v6_128used ++;
  12398 
  12399         gh = soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, GLOBAL_HIGHf);
  12400         gr = soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, GLOBAL_ROUTEf);
  12401         if (gr) {
  12402             if (gh) {
  12403                 glb_hi_cnt ++;
  12404                 use_alpm = 0;
  12405             } else {
  12406                 glb_lo_cnt ++;
  12407                 use_alpm = (mode == 2) ? 0 : 1;
  12408             }
  12409         } else {
  12410             use_alpm = 1;
  12411         }
  12412 
  12413         if (use_alpm) {
  12414             bkt_ptr = soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, ALG_BKT_PTRf);
  12415             if (bkt_ptr > bucket_max) {
  12416                 LOG_CLI(("Invalid phy_bkt pointer in %s index %d\n",
  12417                          SOC_MEM_NAME(u, lpm_mem), i));
  12418             } else {
  12419                 bktref[bkt_ptr] ++;
  12420             }
  12421         }
  12422     }
  12423 
  12424     for (i = 0; i < bucket_max; i++) {
  12425         if (bktref[i] != 0) {
  12426             bucket_used ++;
  12427         }
  12428         if (bktref[i] == 4) {
  12429             bs41 ++;
  12430         }
  12431         if (bktref[i] == 3) {
  12432             bs31 ++;
  12433         }
  12434         if (bktref[i] == 2) {
  12435             bs21 ++;
  12436         }
  12437         if (bktref[i] == 1) {
  12438             bs11 ++;
  12439         }
  12440     }
  12441 
  12442     if (ALPM_CTRL(u).double_wide[0]) {
  12443         bucket_max  >>= 1;
  12444     }
  12445 
  12446     LOG_CLI(("\n"));
  12447     LOG_CLI(("%-24s%d/%-4d\n", "IPv4 Pivots:", v4used, v4max));
  12448     LOG_CLI(("%-24s%d/%-4d\n", "IPv6-64 Pivots:", v6_64used, v6_64max));
  12449     LOG_CLI(("%-24s%d/%-4d\n", "IPv6-128 Pivots:", v6_128used, v6_128max));
  12450     LOG_CLI(("%-24s%d/%-4d\n", "Buckets:", bucket_used, bucket_max));
  12451     LOG_CLI(("%-24s%d\n", "Global High:", glb_hi_cnt));
  12452     LOG_CLI(("%-24s%d\n", "Global Low:", glb_lo_cnt));
  12453     LOG_CLI(("\n"));
  12454     LOG_CLI(("%s\n", "Bucket Sharing:"));
  12455     LOG_CLI(("%-24s%d\n", "1->1:", bs11));
  12456     LOG_CLI(("%-24s%d\n", "2->1:", bs21));
  12457     LOG_CLI(("%-24s%d\n", "3->1:", bs31));
  12458     LOG_CLI(("%-24s%d\n", "4->1:", bs41));
  12459     LOG_CLI(("\n"));
  12460     soc_th_alpm_debug_cntr_show(u);
  12461     LOG_CLI(("\n\n"));
  12462 
  12463 _free_mem:
  12464     if (bktref) {
  12465         sal_free(bktref);
  12466         bktref = NULL;
  12467     }
  12468 
  12469     if (lpm_tbl_ptr) {
  12470         soc_cm_sfree(u, lpm_tbl_ptr);
  12471         lpm_tbl_ptr = NULL;
  12472     }
  12473 
  12474     if (phy_bkt != -1) {
  12475         int bank, entmax, tmp;
  12476 
  12477         lpm_mem = soc_alpm_cmn_bkt_view_get(u,
  12478             SOC_TH_ALPM_AIDX(u, phy_bkt, 0, 0, 0));
  12479         LOG_CLI(("Bucket = %4d (View %s)\n", phy_bkt, lpm_mem == -1 ? "INVALID" :
  12480                 SOC_MEM_NAME(u, lpm_mem)));
  12481         LOG_CLI(("------------------------------------------------------------\n"));
  12482         LOG_CLI(("Index distribution (* indicates occupied)\n"));
  12483 
  12484         switch (lpm_mem) {
  12485         case L3_DEFIP_ALPM_IPV4m:
  12486             entmax = 6;
  12487             break;
  12488         case L3_DEFIP_ALPM_IPV4_1m:
  12489             entmax = 4;
  12490             break;
  12491         case L3_DEFIP_ALPM_IPV6_64m:
  12492             entmax = 4;
  12493             break;
  12494         case L3_DEFIP_ALPM_IPV6_64_1m:
  12495             entmax = 3;
  12496             break;
  12497         case L3_DEFIP_ALPM_IPV6_128m:
  12498             entmax = 2;
  12499             break;
  12500         default:
  12501             lpm_mem = L3_DEFIP_ALPM_IPV4m;
  12502             entmax = 6;
  12503             break;
  12504         }
  12505 
  12506         for (bank = 0; bank < MAX_BANK_COUNT(u); bank++) {
  12507             if (!(bnkbits & (1 << bank))) {
  12508                 continue;
  12509             }
  12510 
  12511             LOG_CLI(("Bank%d: ", bank));
  12512             for (i = 0; i < entmax; i++) {
  12513                 int rv1;
  12514                 j = SOC_TH_ALPM_AIDX(u, phy_bkt, 0, bank, i);
  12515                 rv1 = _soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY, j, e);
  12516                 if (rv1 == 0 &&
  12517                     soc_mem_field32_get(u, lpm_mem, e, VALIDf)) {
  12518                     tmp = 1;
  12519                 } else {
  12520                     tmp = 0;
  12521                 }
  12522                 if (tmp) {
  12523                     LOG_CLI(("%d(*) ", j));
  12524                 } else {
  12525                     LOG_CLI(("%d( ) ", j));
  12526                 }
  12527             }
  12528             LOG_CLI(("\n"));
  12529         }
  12530     }
  12531 
  12532     LOG_CLI(("\n"));
  12533     if (index != -1) {
  12534         int log_bkt;
  12535         LOG_CLI(("Index = %8d\n", index));
  12536         LOG_CLI(("------------------------------------------------------------\n"));
  12537         lpm_mem = soc_alpm_cmn_bkt_view_get(u, index);
  12538         LOG_CLI(("%-24s%s\n", "Type", lpm_mem == -1 ? "INVALID" :
  12539                 SOC_MEM_NAME(u, lpm_mem)));
  12540         LOG_CLI(("%-24s%d\n", "Bucket:", SOC_TH_ALPM_AIDX_TO_PHY_BKT(u, index)));
  12541         LOG_CLI(("%-24s%d\n", "Sub-Bucket:", SOC_TH_ALPM_AIDX_TO_SUB_BKT(u, index)));
  12542         LOG_CLI(("%-24s%d\n", "Bank:", index & ALPM_CTRL(u).bank_bits));
  12543         log_bkt = (_shr_popcount(bnkbits) + 1) / 2 + alpm_bkt_bits;
  12544         LOG_CLI(("%-24s%d\n", "Entry:", index >> log_bkt));
  12545         LOG_CLI(("\n"));
  12546     }
  12547 
  12548     return rv;
  12549 }
  12550 
  12551 /*
  12552  * Function:
  12553  *     soc_th_alpm_lpm_sw_dump
  12554  * Purpose:
  12555  *     Displays FB LPM information maintained by software.
  12556  * Parameters:
  12557  *     unit - Device unit number
  12558  * Returns:
  12559  *     None
  12560  */
  12561 void
  12562 soc_th_alpm_lpm_sw_dump(int unit)
  12563 {
  12564     soc_th_alpm_lpm_state_p lpm_state;
  12565     int                   i, j;
  12566     alpm_pivot_t          *pivot_pyld = NULL;
  12567     _soc_th_alpm_lpm_hash_t  *hash;
  12568     int idx;
  12569 
  12570     /* Dump v4/v6 lpm state */
  12571     LOG_CLI((BSL_META_U(unit, "V4 LPM STATE DUMP.\n")));
  12572     lpm_state = soc_th_alpm_lpm_state[unit];
  12573 
  12574     if (lpm_state != NULL) {
  12575         for (i = 0; i < ALPM_MAX_PFX_ENTRIES; i++) {
  12576             if (lpm_state[i].vent != 0) {
  12577                 LOG_CLI((BSL_META_U(unit, "Prefix %d\n"), i));
  12578                 LOG_CLI((BSL_META_U(unit, "  Start : %d\n"), lpm_state[i].start));
  12579                 LOG_CLI((BSL_META_U(unit, "  End   : %d\n"), lpm_state[i].end));
  12580                 LOG_CLI((BSL_META_U(unit, "  Prev  : %d\n"), lpm_state[i].prev));
  12581                 LOG_CLI((BSL_META_U(unit, "  Next  : %d\n"), lpm_state[i].next));
  12582                 LOG_CLI((BSL_META_U(unit, "  Valid : %d\n"), lpm_state[i].vent));
  12583                 LOG_CLI((BSL_META_U(unit, "  Free  : %d\n"), lpm_state[i].fent));
  12584             }
  12585         }
  12586     }
  12587     LOG_CLI((BSL_META_U(unit, "V4 LPM STATE DUMP DONE.\n\n")));
  12588 
  12589     /* Dump LPM HASH table */
  12590     LOG_CLI((BSL_META_U(unit, "LPM HASH TABLE DUMP.\n")));
  12591     hash = SOC_ALPM_LPM_STATE_HASH(unit);
  12592     for(idx = 0; idx < hash->index_count; idx++) {
  12593         j = 0;
  12594         if (hash->table[idx] != TD2_ALPM_HASH_INDEX_NULL) {
  12595             LOG_CLI((
  12596                 BSL_META_U(unit, "\nhash_idx = 0x%04x Data = 0x%04x"),
  12597                 idx, hash->table[idx]));
  12598         }
  12599         i = hash->table[idx];
  12600         while ((i != TD2_ALPM_HASH_INDEX_NULL) && (j++ < hash->entry_count)) {
  12601             if ((j - 1) % 8 == 0) {
  12602                 LOG_CLI((BSL_META_U(unit, "\nlink_idx =")));
  12603             }
  12604             LOG_CLI((BSL_META_U(unit, " 0x%04x"), i));
  12605             i = hash->link_table[i & TD2_ALPM_HASH_INDEX_MASK];
  12606         }
  12607     }
  12608     LOG_CLI((BSL_META_U(unit, "\nLPM HASH TABLE DUMP DONE.\n\n")));
  12609 
  12610     /* Dump TCAM pivot table */
  12611     LOG_CLI((BSL_META_U(unit, "TCAM PIVOT DUMP.\n")));
  12612     for(idx = 0; idx < TH_MAX_PIVOT_COUNT(unit); idx++) {
  12613         /* Get TCAM pivot */
  12614         pivot_pyld = ALPM_TCAM_PIVOT(unit, idx);
  12615         if (NULL == pivot_pyld) {
  12616             continue;
  12617         }
  12618         if (PIVOT_BUCKET_HANDLE(pivot_pyld) == NULL) {
  12619             continue;
  12620         }
  12621 
  12622         /* Get bucket trie from pivot */
  12623         LOG_CLI((
  12624             BSL_META_U(unit, "tcam_idex = 0x%04x\n"), pivot_pyld->tcam_index));
  12625         LOG_CLI((BSL_META_U(unit, "  len = 0x%02x\t"), pivot_pyld->len));
  12626         LOG_CLI((BSL_META_U(unit, "bpm_len = 0x%02x\t"), pivot_pyld->bpm_len));
  12627         LOG_CLI((
  12628             BSL_META_U(unit, "bkt_idx = 0x%04x\n"),
  12629             PIVOT_BUCKET_INDEX(pivot_pyld)));
  12630         LOG_CLI((
  12631             BSL_META_U(unit, "  vrf = 0x%04x\t"), PIVOT_BUCKET_VRF(pivot_pyld)));
  12632         LOG_CLI((
  12633             BSL_META_U(unit, "v6 = 0x%0x\t"), PIVOT_BUCKET_IPV6(pivot_pyld)));
  12634         LOG_CLI((BSL_META_U(unit, "Key : {")));
  12635         if (pivot_pyld->len < 32) {
  12636             LOG_CLI((
  12637                 BSL_META_U(unit, "0x%x/%d"),
  12638                 pivot_pyld->key[0], pivot_pyld->len));
  12639         } else {
  12640             for (i=0; i < (((pivot_pyld->len)/32) + 1); i++)
  12641                 LOG_CLI((BSL_META_U(unit, " 0x%x"), pivot_pyld->key[i]));
  12642                 LOG_CLI((BSL_META_U(unit, "/%d"), pivot_pyld->len));
  12643         }
  12644         LOG_CLI((BSL_META_U(unit, "}\n")));
  12645     }
  12646     LOG_CLI((BSL_META_U(unit, "TCAM PIVOT DUMP DONE.\n\n")));
  12647 
  12648     /* Print VRF count/default route infomation */
  12649     LOG_CLI((BSL_META_U(unit, "VRF ROUTE DUMP.\n")));
  12650     for (idx = 0; idx < (SOC_VRF_MAX(unit) + 2); idx++) {
  12651        if (alpm_vrf_handle[unit][idx].count_v4 != 0) {
  12652            LOG_CLI((
  12653                BSL_META_U(unit, "V4-32 VRF = %d, Routes = %d Default Route:\n"),
  12654                idx, alpm_vrf_handle[unit][idx].count_v4));
  12655            if (VRF_TRIE_DEFAULT_ROUTE_IPV4(unit, idx)) {
  12656                soc_mem_entry_dump(unit, L3_DEFIPm,
  12657                                   VRF_TRIE_DEFAULT_ROUTE_IPV4(unit, idx),
  12658                                   BSL_LSS_CLI);
  12659            }
  12660        }
  12661 
  12662        if (alpm_vrf_handle[unit][idx].count_v6_64 !=0) {
  12663            LOG_CLI((
  12664                BSL_META_U(unit, "V6-64 VRF = %d, Routes = %d Default Route:\n"),
  12665                idx, alpm_vrf_handle[unit][idx].count_v6_64));
  12666            if (VRF_TRIE_DEFAULT_ROUTE_IPV6(unit, idx)) {
  12667                soc_mem_entry_dump(unit, L3_DEFIPm,
  12668                                   VRF_TRIE_DEFAULT_ROUTE_IPV6(unit, idx),
  12669                                   BSL_LSS_CLI);
  12670            }
  12671        }
  12672 
  12673        if (alpm_vrf_handle[unit][idx].count_v6_128 != 0) {
  12674            LOG_CLI((
  12675                BSL_META_U(unit, "V6-128 VRF = %d, Routes = %d Default Route:\n"),
  12676                idx, alpm_vrf_handle[unit][idx].count_v6_128));
  12677            if (VRF_TRIE_DEFAULT_ROUTE_IPV6_128(unit, idx)) {
  12678                soc_mem_entry_dump(unit, L3_DEFIP_PAIR_128m,
  12679                                   VRF_TRIE_DEFAULT_ROUTE_IPV6_128(unit, idx),
  12680                                   BSL_LSS_CLI);
  12681            }
  12682        }
  12683     }
  12684     LOG_CLI((BSL_META_U(unit, "VRF ROUTE DUMP DONE.\n")));
  12685 
  12686     return;
  12687 }
  12688 
  12689 #ifndef BCM_SW_STATE_DUMP_DISABLE
  12690 /*
  12691  * Function:
  12692  *     soc_th_alpm_sw_dump
  12693  * Purpose:
  12694  *     Displays ALPM state maintained by software.
  12695  * Parameters:
  12696  *     unit - Device unit number
  12697  * Returns:
  12698  *     None
  12699  */
  12700 void
  12701 soc_th_alpm_sw_dump(int unit)
  12702 {
  12703     LOG_CLI((BSL_META_U(unit, "\n  ALPM Info -\n")));
  12704 
  12705     soc_th_alpm_lpm_sw_dump(unit);
  12706 
  12707     soc_th_alpm_bucket_sw_dump(unit);
  12708 
  12709     return;
  12710 }
  12711 #endif /* BCM_SW_STATE_DUMP_DISABLE */
  12712 
  12713 /*
  12714  * Function:
  12715  *      _soc_th_alpm_sanity_check
  12716  * Purpose:
  12717  *      Sanity check for ALPM with L3_DEFIP
  12718  * Parameters:
  12719  *      u           - Device unit
  12720  *      min         - Min index of L3_DEFIP
  12721  *      max         - Max index of L3_DEFIP
  12722  *      check_sw    - Check software
  12723  *      bkt_ptr_arr - bucket ptr array
  12724  * Returns:
  12725  *      SOC_E_XXX defined in error.h
  12726  */
  12727 STATIC int
  12728 _soc_th_alpm_sanity_check(int u, int min, int max, int check_sw,
  12729                           int *bkt_ptr_arr, alpm_bkt_usg_t  *bkt_usg)
  12730 {
  12731     int             rv = SOC_E_NONE;
  12732     int             lpm_idx, lpm_idx2, fd_lpm_idx2, alpm_idx, prev_idx = 0;
  12733     int             i, j, ipv6, prev_v6 = 0, prev_i = 0;
  12734     int             vrf_id, vrf;
  12735     int             fd_lpm_idx, fd_bkt_ptr, fd_alpm_idx;
  12736     int             ent, ent_num, bkt_ptr, sub_bkt_ptr;
  12737     int             error1 = 0, error2 = 0, error = 0, success = 0;
  12738     int             used;
  12739     int             bpm_len, ip_len;
  12740     int             trie_bpm_len, default_route;
  12741     int             alloc_size;
  12742     uint32          bank_disable = 0;
  12743     uint32          *e = NULL;
  12744     uint32          *shadow = NULL;
  12745     uint32          prefix[5], length;
  12746     trie_t          *pfx_trie  = NULL;
  12747     trie_node_t     *lpmp      = NULL;
  12748     payload_t       *tmp_pyld  = NULL;
  12749     uint32          data0[10] = {0};
  12750     uint32          data1[10] = {0};
  12751     char            *buffer = NULL;
  12752     defip_entry_t   *lpm_entry, lpm_entry2, lpm_bmp;
  12753     soc_mem_t       bkt_mem_type;
  12754     soc_mem_t       alpm_mem;
  12755     int             flex;
  12756     int             bpm_check = 0;
  12757     int             flex_v6_64;
  12758     int             ipmc_route = 0;
  12759 
  12760     e = sal_alloc(sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS, "buf_tmp");
  12761     if (e == NULL) {
  12762         return (SOC_E_MEMORY);
  12763     }
  12764 
  12765     shadow = sal_alloc(sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS, "shadow_buf_tmp");
  12766     if (shadow == NULL) {
  12767         sal_free(e);
  12768         return (SOC_E_MEMORY);
  12769     }
  12770     /* Calculate table size. */
  12771     alloc_size = sizeof(defip_entry_t) * (max - min + 1);
  12772 
  12773     /* Allocate memory buffer. */
  12774     buffer = soc_cm_salloc(u, alloc_size, "lpm_tbl");
  12775     if (buffer == NULL) {
  12776         sal_free(e);
  12777         sal_free(shadow);
  12778         return (SOC_E_MEMORY);
  12779     }
  12780 
  12781     /* Reset allocated buffer. */
  12782     sal_memset(buffer, 0, alloc_size);
  12783 
  12784     SOC_ALPM_LPM_LOCK(u);
  12785 
  12786     /* Read table to the buffer. */
  12787     if (soc_mem_read_range(u, L3_DEFIPm, MEM_BLOCK_ANY,
  12788                            min, max, buffer) < 0) {
  12789         sal_free(e);
  12790         sal_free(shadow);
  12791         soc_cm_sfree(u, buffer);
  12792         SOC_ALPM_LPM_UNLOCK(u);
  12793         return (SOC_E_INTERNAL);
  12794     }
  12795 
  12796     for (lpm_idx = min; lpm_idx <= max; lpm_idx++) {
  12797         lpm_entry = soc_mem_table_idx_to_pointer(u, L3_DEFIPm,
  12798                                                  defip_entry_t *, buffer,
  12799                                                  lpm_idx - min);
  12800 
  12801         ipv6 = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, MODE0_f(u));
  12802 
  12803 
  12804         for (i = 0; i <= (ipv6 ? 0 : 1); i++) {
  12805             if (error1) {
  12806                 LOG_ERROR(BSL_LS_SOC_ALPM,
  12807                           (BSL_META_U(u,
  12808                           "\tL3_DEFIP index:[%d,%d] check failed. ipv6 %d error count %d\n"),
  12809                           prev_idx, prev_i, prev_v6, error1));
  12810                 error = 1;
  12811             } else if (success) {
  12812                 LOG_INFO(BSL_LS_SOC_ALPM,(BSL_META_U(u,
  12813                         "\tL3_DEFIP index:[%d,%d] check passed. ipv6 %d success count %d\n"),
  12814                          prev_idx, prev_i, prev_v6, success));
  12815             }
  12816             error1 = error2 = success = 0;
  12817             prev_v6  = ipv6;
  12818             prev_idx = lpm_idx;
  12819             prev_i   = i;
  12820 
  12821             /* cache coherency check */
  12822             if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, VALID0f) ||
  12823                 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, VALID1f)) {
  12824                 defip_entry_t hw_ent, sw_ent;
  12825                 soc_mem_t cmem = L3_DEFIPm;
  12826                 sal_memset(&hw_ent, 0, sizeof(hw_ent));
  12827                 sal_memset(&sw_ent, 0, sizeof(sw_ent));
  12828                 rv = _soc_mem_alpm_read_cache(u, cmem, SOC_BLOCK_ANY,
  12829                                               lpm_idx, &sw_ent);
  12830                 if (SOC_SUCCESS(rv)) {
  12831                     rv = soc_mem_read_no_cache(u, 0, cmem, 0, SOC_BLOCK_ANY,
  12832                                                lpm_idx, &hw_ent);
  12833                     if (SOC_SUCCESS(rv)) {
  12834                         soc_mem_parity_field_clear(
  12835                             u, cmem, (void *)&hw_ent, (void *)&sw_ent);
  12836                         if (sal_memcmp(&sw_ent, &hw_ent,
  12837                                        soc_mem_entry_bytes(u, cmem)) != 0) {
  12838                             LOG_ERROR(BSL_LS_SOC_ALPM,
  12839                                 (BSL_META_U(u, "\t%s index:[%d], ipv6(%d)"
  12840                                 " cache mismatch\n"), SOC_MEM_NAME(u, cmem),
  12841                                 lpm_idx, ipv6));
  12842                             error1 ++;
  12843                         }
  12844                     }
  12845                 }
  12846 
  12847                 /* We can just use defip_entry_t because it's always longer
  12848                  * than aux_entry_t */
  12849                 cmem = L3_DEFIP_AUX_TABLEm;
  12850                 sal_memset(&hw_ent, 0, sizeof(hw_ent));
  12851                 sal_memset(&sw_ent, 0, sizeof(sw_ent));
  12852                 lpm_idx2 = soc_th_alpm_physical_idx(u, L3_DEFIPm, lpm_idx, 1);
  12853                 rv = _soc_mem_alpm_read_cache(u, cmem, SOC_BLOCK_ANY,
  12854                                               lpm_idx2, &sw_ent);
  12855                 if (SOC_SUCCESS(rv)) {
  12856                     rv = soc_mem_read_no_cache(u, 0, cmem, 0, SOC_BLOCK_ANY,
  12857                                                lpm_idx2, &hw_ent);
  12858                     if (SOC_SUCCESS(rv)) {
  12859                         soc_mem_parity_field_clear(
  12860                             u, cmem, (void *)&hw_ent, (void *)&sw_ent);
  12861                         if (sal_memcmp(&sw_ent, &hw_ent,
  12862                                        soc_mem_entry_bytes(u, cmem)) != 0) {
  12863                             LOG_ERROR(BSL_LS_SOC_ALPM,
  12864                                 (BSL_META_U(u, "\t%s index:[%d], ipv6(%d)"
  12865                                 " cache mismatch\n"), SOC_MEM_NAME(u, cmem),
  12866                                 lpm_idx2, ipv6));
  12867                             error1 ++;
  12868                         }
  12869                     }
  12870                 }
  12871             }
  12872 
  12873             if (i == 1) {
  12874                 soc_th_alpm_lpm_ip4entry1_to_0(u, lpm_entry, lpm_entry, PRESERVE_HIT);
  12875             }
  12876             bkt_ptr = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ALG_BKT_PTR0f);
  12877             if (!SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, VALID0f)) {
  12878                 continue;
  12879             }
  12880 
  12881             flex = _soc_th_alpm_lpm_flex_get(u, ipv6,
  12882                         soc_mem_field32_get(u, L3_DEFIPm,
  12883                         lpm_entry, ENTRY_VIEW0f));
  12884             flex_v6_64 = 0;
  12885             if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && ipv6 && flex) {
  12886                 if (soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f) == 0xFFFFFFFF &&
  12887                     soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f) == 0xFFFFFFFF) {
  12888                     flex_v6_64 = 1;
  12889                 }
  12890             }
  12891 
  12892             if (soc_feature(u, soc_feature_ipmc_defip)) {
  12893                 ipmc_route = 0;
  12894                 if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE0f)) {
  12895                     ipmc_route = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, MULTICAST_ROUTE0f);
  12896                 } else if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE0f)) {
  12897                     if (soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, DATA_TYPE0f) == 2) {
  12898                         ipmc_route = 1;
  12899                     } else {
  12900                         ipmc_route = 0;
  12901                     }
  12902                 }
  12903             }
  12904 
  12905             if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, GLOBAL_HIGH0f) ||
  12906                 ipmc_route ||
  12907                 (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f) &&
  12908                  ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_TCAM_ALPM) ||
  12909                  flex_v6_64) {
  12910                 if (bkt_ptr != 0) {
  12911                     LOG_ERROR(BSL_LS_SOC_ALPM,
  12912                               (BSL_META_U(u, "\tWrong bkt_ptr %d\n"),
  12913                               bkt_ptr));
  12914                     error1 ++;
  12915                 }
  12916                 continue;
  12917             }
  12918             if (bkt_ptr == 0) {
  12919                 LOG_ERROR(BSL_LS_SOC_ALPM,
  12920                           (BSL_META_U(u, "\tWrong bkt_ptr2 %d\n"),
  12921                           bkt_ptr));
  12922                 error1 ++;
  12923             }
  12924 
  12925             j = 0;
  12926             if (soc_feature(u, soc_feature_generic_dest)) {
  12927                 uint32 val, dest_type = SOC_MEM_FIF_DEST_NEXTHOP;
  12928                 val = soc_mem_field32_dest_get(u, L3_DEFIPm, lpm_entry,
  12929                                                DESTINATION0f, &dest_type);
  12930                 if (dest_type == SOC_MEM_FIF_DEST_ECMP) {
  12931                     data0[j++] = 1;
  12932                 } else {
  12933                     data0[j++] = 0;
  12934                 }
  12935                 data0[j++] = val;
  12936                 data0[j++] = val;
  12937             } else {
  12938                 data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ECMP0f);
  12939                 data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ECMP_PTR0f);
  12940                 data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, NEXT_HOP_INDEX0f);
  12941             }
  12942             data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, PRI0f);
  12943             data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, RPE0f);
  12944             data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, DST_DISCARD0f);
  12945             data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, CLASS_ID0f);
  12946 
  12947             /* Check if bucket pointer duplicated */
  12948             if (ALPM_CTRL(u).bkt_sharing) {
  12949                 sub_bkt_ptr = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ALG_SUB_BKT_PTR0f);
  12950             } else {
  12951                 sub_bkt_ptr = 0;
  12952             }
  12953             if (bkt_ptr_arr) {
  12954                 if (bkt_ptr_arr[bkt_ptr * SOC_TH_MAX_SUB_BUCKETS + sub_bkt_ptr] == -1) {
  12955                     bkt_ptr_arr[bkt_ptr * SOC_TH_MAX_SUB_BUCKETS + sub_bkt_ptr] = lpm_idx;
  12956                     if (ALPM_CTRL(u).double_wide[ipv6]) {
  12957                         bkt_ptr_arr[(bkt_ptr + 1) * SOC_TH_MAX_SUB_BUCKETS + sub_bkt_ptr] = lpm_idx;
  12958                     }
  12959                     success ++;
  12960                 } else {
  12961                     LOG_ERROR(BSL_LS_SOC_ALPM,
  12962                               (BSL_META_U(u, "\tConflict bucket pointer [%d,%d]: "
  12963                               "was %d now %d\n"), bkt_ptr, sub_bkt_ptr,
  12964                               bkt_ptr_arr[bkt_ptr * SOC_TH_MAX_SUB_BUCKETS + sub_bkt_ptr],
  12965                               lpm_idx));
  12966                     error1 ++;
  12967                 }
  12968             }
  12969             if (ipv6) {
  12970                 if (flex) {
  12971                     alpm_mem = L3_DEFIP_ALPM_IPV6_64_1m;
  12972                 } else {
  12973                     alpm_mem = L3_DEFIP_ALPM_IPV6_64m;
  12974                 }
  12975             } else {
  12976                 if (flex) {
  12977                     alpm_mem = L3_DEFIP_ALPM_IPV4_1m;
  12978                 } else {
  12979                     alpm_mem = L3_DEFIP_ALPM_IPV4m;
  12980                 }
  12981             }
  12982 
  12983             (void) soc_th_alpm_lpm_vrf_get(u, lpm_entry, &vrf_id, &vrf);
  12984 
  12985             /* read shadow table for bpm length */
  12986             lpm_idx2 = soc_th_alpm_physical_idx(u, L3_DEFIPm, lpm_idx, 1);
  12987 
  12988             if (bkt_usg) {
  12989                 if (bkt_usg[bkt_ptr].sub_bkts == 0) {
  12990                     bkt_usg[bkt_ptr].global = (vrf == SOC_VRF_MAX(u) + 1);
  12991                 }
  12992                 bkt_usg[bkt_ptr].sub_bkts |= 1U << sub_bkt_ptr;
  12993                 bkt_usg[bkt_ptr].pivots[sub_bkt_ptr] = (lpm_idx2 << 1) + i;
  12994             }
  12995 
  12996             bpm_len = -1;
  12997             bpm_check = 0;
  12998             if (!ALPM_CTRL(u).aux_enable) {
  12999                 rv = _soc_th_alpm_pivot_bmp_len_get(
  13000                          u, ipv6, lpm_entry, (uint32 *)&bpm_len);
  13001                 if (SOC_SUCCESS(rv)) {
  13002                     bpm_check = 1;
  13003                 }
  13004             } else {
  13005                 rv = soc_mem_read(u, L3_DEFIP_AUX_TABLEm, MEM_BLOCK_ANY,
  13006                                   lpm_idx2, shadow);
  13007                 if (SOC_SUCCESS(rv)) {
  13008                     if (i == 0) {
  13009                         bpm_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm,
  13010                                                       shadow, BPM_LENGTH0f);
  13011                         ip_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm,
  13012                                                       shadow, IP_LENGTH0f);
  13013                     } else {
  13014                         bpm_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm,
  13015                                                       shadow, BPM_LENGTH1f);
  13016                         ip_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm,
  13017                                                       shadow, IP_LENGTH1f);
  13018                     }
  13019                     if (bpm_len > ip_len) {
  13020                         LOG_ERROR(BSL_LS_SOC_ALPM,
  13021                                   (BSL_META_U(u, "\tAUX Table corrupted\n")));
  13022                         error1 ++;
  13023                     } else {
  13024                         success ++;
  13025                     }
  13026                     bpm_check = 1;
  13027                 }
  13028             }
  13029 
  13030             if ((bpm_check == 1) && (bpm_len == 0) &&
  13031                 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, DEFAULT_MISS0f)) {
  13032                 bpm_check = 0;
  13033             }
  13034 
  13035             if (bpm_check) {
  13036                 sal_memcpy(&lpm_bmp, lpm_entry, sizeof(defip_entry_t));
  13037                 _soc_th_alpm_pfx_len_to_mask(u, &lpm_bmp, bpm_len, ipv6);
  13038 
  13039                 fd_lpm_idx = fd_bkt_ptr = fd_alpm_idx = -1;
  13040                 rv = _soc_th_alpm_find(
  13041                          u, alpm_mem, ipv6, &lpm_bmp, vrf_id, vrf,
  13042                          e, &fd_lpm_idx, &fd_bkt_ptr, &fd_alpm_idx,
  13043                          (SOC_IS_TRIDENT3X(u) ? TRUE :
  13044                          (ALPM_CTRL(u).aux_enable ? FALSE : TRUE)));
  13045                 if (fd_lpm_idx > 0) {
  13046                     fd_lpm_idx = soc_th_alpm_logical_idx(u, L3_DEFIPm,
  13047                                                          fd_lpm_idx >> 1, 1);
  13048                 }
  13049                 if (SOC_SUCCESS(rv)) {
  13050                     j = 0;
  13051                     if (soc_feature(u, soc_feature_generic_dest)) {
  13052                         uint32 val, dest_type = SOC_MEM_FIF_DEST_NEXTHOP;
  13053                         val = soc_mem_field32_dest_get(u, alpm_mem, e,
  13054                                                        DESTINATIONf, &dest_type);
  13055                         if (dest_type == SOC_MEM_FIF_DEST_ECMP) {
  13056                             data1[j++] = 1;
  13057                         } else {
  13058                             data1[j++] = 0;
  13059                         }
  13060                         data1[j++] = val;
  13061                         data1[j++] = val;
  13062                     } else {
  13063                         data1[j++] = soc_mem_field32_get(u, alpm_mem, e, ECMPf);
  13064                         data1[j++] = soc_mem_field32_get(u, alpm_mem, e, ECMP_PTRf);
  13065                         data1[j++] = soc_mem_field32_get(u, alpm_mem, e, NEXT_HOP_INDEXf);
  13066                     }
  13067                     data1[j++] = soc_mem_field32_get(u, alpm_mem, e, PRIf);
  13068                     data1[j++] = soc_mem_field32_get(u, alpm_mem, e, RPEf);
  13069                     data1[j++] = soc_mem_field32_get(u, alpm_mem, e, DST_DISCARDf);
  13070                     data1[j++] = soc_mem_field32_get(u, alpm_mem, e, CLASS_IDf);
  13071 
  13072                     if (sal_memcmp(data0, data1, sizeof(data0)) != 0) {
  13073                         LOG_ERROR(BSL_LS_SOC_ALPM,
  13074                                   (BSL_META_U(u,
  13075                                   "\tData mismatch: "
  13076                                   "lpm_idx %d find_lpm_idx %d "
  13077                                   "find_alpm_idx %d find_bkt_ptr %d\n"),
  13078                                   lpm_idx, fd_lpm_idx,
  13079                                   fd_alpm_idx, fd_bkt_ptr));
  13080                         error1 ++;
  13081                     } else {
  13082                         success ++;
  13083                     }
  13084                 } else {
  13085                     if (rv == SOC_E_NOT_FOUND &&
  13086                         (vrf_id == SOC_L3_VRF_GLOBAL || ALPM_CTRL(u).gp_zoned)) {
  13087                         LOG_VERBOSE(BSL_LS_SOC_ALPM,
  13088                                   (BSL_META_U(u,
  13089                                   "\t_soc_th_alpm_find rv=%d: "
  13090                                   "lpm_idx %d find_lpm_idx %d "
  13091                                   "find_alpm_idx %d find_bkt_ptr %d,"
  13092                                   "(Possible: global route or !combined "
  13093                                   "without default)\n"),
  13094                                   rv, lpm_idx, fd_lpm_idx,
  13095                                   fd_alpm_idx, fd_bkt_ptr));
  13096                     } else {
  13097                         LOG_ERROR(BSL_LS_SOC_ALPM,
  13098                                   (BSL_META_U(u,
  13099                                   "\t_soc_th_alpm_find rv=%d: "
  13100                                   "lpm_idx %d find_lpm_idx %d "
  13101                                   "find_alpm_idx %d find_bkt_ptr %d\n"),
  13102                                   rv, lpm_idx, fd_lpm_idx,
  13103                                   fd_alpm_idx, fd_bkt_ptr));
  13104                         error1 ++;
  13105                     }
  13106                 }
  13107             }
  13108 
  13109             bank_disable =
  13110                 ALPM_CTRL(u).bank_disable_bmp_8b[vrf != SOC_VRF_MAX(u) + 1];
  13111             ent_num = _soc_th_alpm_bkt_entry_cnt(u, alpm_mem);
  13112 
  13113             /* Traverse bucket */
  13114             for (ent = 0; ent < ent_num; ent++) {
  13115                 rv = _soc_th_alpm_mem_index(u, alpm_mem, bkt_ptr, ent,
  13116                                               bank_disable, &alpm_idx);
  13117 
  13118                 if (SOC_FAILURE(rv)) {
  13119                     LOG_ERROR(BSL_LS_SOC_ALPM,
  13120                               (BSL_META_U(u, "\tALPM mem index get failure: rv %d "
  13121                               "bkt_ptr %d, ent %d, bank_dis %d\n"),
  13122                               rv, bkt_ptr, ent, bank_disable));
  13123                     error1 ++;
  13124                     error2 ++;
  13125                 }
  13126 
  13127                 rv = _soc_mem_alpm_read(u, alpm_mem, MEM_BLOCK_ANY, alpm_idx, e);
  13128                 if (SOC_FAILURE(rv)) {
  13129                     continue;
  13130                 }
  13131 
  13132                 if (!soc_mem_field32_get(u, alpm_mem, e, VALIDf)) {
  13133                     continue;
  13134                 }
  13135 
  13136                 if (sub_bkt_ptr !=
  13137                     soc_mem_field32_get(u, alpm_mem, e, SUB_BKT_PTRf)) {
  13138                     continue;
  13139                 }
  13140 
  13141                 if (bkt_usg) {
  13142                     bkt_usg[bkt_ptr].count++;
  13143                 }
  13144 
  13145                 (void) _soc_th_alpm_lpm_ent_init(u, e, alpm_mem, ipv6, vrf_id,
  13146                                                  ALPM_LOG_BKT(bkt_ptr, sub_bkt_ptr),
  13147                                                  0, &lpm_entry2, 0);
  13148 
  13149                 if (check_sw) {
  13150                     rv = _soc_th_alpm_sw_prefix_check(u, alpm_mem, ipv6, &lpm_entry2, vrf_id, vrf);
  13151                     if (SOC_FAILURE(rv)) {
  13152                         error1 ++;
  13153                         error2 ++;
  13154                         LOG_ERROR(BSL_LS_SOC_ALPM,
  13155                                   (BSL_META_U(u,
  13156                                   "_soc_th_alpm_sw_prefix_check rv=%d: v6 = %d, vrf_id = %d, vrf = %d\n"),
  13157                                   rv, ipv6, vrf_id, vrf));
  13158                     }
  13159                 }
  13160 
  13161                 fd_lpm_idx2 = fd_lpm_idx = fd_bkt_ptr = fd_alpm_idx = -1;
  13162                 rv = _soc_th_alpm_find(
  13163                          u, alpm_mem, ipv6, &lpm_entry2, vrf_id, vrf,
  13164                          e, &fd_lpm_idx, &fd_bkt_ptr, &fd_alpm_idx,
  13165                          (SOC_IS_TRIDENT3X(u) ? TRUE :
  13166                          (ALPM_CTRL(u).aux_enable ? FALSE : TRUE)));
  13167                 if (SOC_SUCCESS(rv)) {
  13168                     fd_lpm_idx2 = soc_th_alpm_logical_idx(u,
  13169                         L3_DEFIPm, fd_lpm_idx >> 1, 1);
  13170                 }
  13171 
  13172                 if (SOC_FAILURE(rv) ||
  13173                     fd_bkt_ptr  != ALPM_LOG_BKT(bkt_ptr, sub_bkt_ptr) ||
  13174                     fd_lpm_idx2 != lpm_idx  ||
  13175                     fd_lpm_idx >> 1  != lpm_idx2 || /* for map remap */
  13176                     fd_alpm_idx != alpm_idx) {
  13177 
  13178                     error1 ++;
  13179                     error2 ++;
  13180                     LOG_ERROR(BSL_LS_SOC_ALPM,
  13181                               (BSL_META_U(u,
  13182                               "\t_soc_th_alpm_find2 rv=%d: "
  13183                               "fl [%d,%d] fa %d fb [%d,%d] "
  13184                               "l [%d,%d] a %d b [%d,%d]\n"),
  13185                               rv,
  13186                               fd_lpm_idx >> 1, fd_lpm_idx2, fd_alpm_idx,
  13187                               ALPM_PHY_BKT(u, fd_bkt_ptr), ALPM_SUB_BKT(u, fd_bkt_ptr),
  13188                               lpm_idx2, lpm_idx, alpm_idx, bkt_ptr, sub_bkt_ptr));
  13189                 }
  13190             }
  13191             if (error2 == 0) {
  13192                 success ++;
  13193             }
  13194 
  13195             if (!check_sw) {
  13196                 continue;
  13197             }
  13198 
  13199             /*
  13200              * Check hardware table above.
  13201              * Check software table below.
  13202  */
  13203 
  13204             /* lpm hash */
  13205 
  13206             rv = LPM_HASH_VERIFY(u, lpm_entry,
  13207                                  ipv6 ? lpm_idx : ((lpm_idx << 1) + i));
  13208             if (SOC_FAILURE(rv)) {
  13209                 LOG_ERROR(BSL_LS_SOC_ALPM,
  13210                           (BSL_META_U(u, "\tLPM Hash check failed: rv %d "
  13211                           "lpm_idx %d\n"),
  13212                           rv, lpm_idx));
  13213                 error1 ++;
  13214             } else {
  13215                 success ++;
  13216             }
  13217 
  13218             /* bucket bitmap */
  13219             rv = soc_th_alpm_bucket_is_assigned(u, ALPM_LOG_BKT(bkt_ptr, sub_bkt_ptr),
  13220                                                 vrf, ipv6, &used);
  13221             if (SOC_FAILURE(rv) || sub_bkt_ptr >= SOC_TH_MAX_SUB_BUCKETS) {
  13222                 LOG_ERROR(BSL_LS_SOC_ALPM,
  13223                           (BSL_META_U(u, "\tInvalid bucket pointer [%d,%d] "
  13224                           "detected, in memory %s index %d\n"),
  13225                           bkt_ptr, sub_bkt_ptr,
  13226                           SOC_MEM_NAME(u, L3_DEFIPm), lpm_idx));
  13227                 error1 ++;
  13228             } else if (used == 0) {
  13229                 /* If bucket was already freed */
  13230                 LOG_ERROR(BSL_LS_SOC_ALPM,
  13231                           (BSL_META_U(u, "\tFreed bucket pointer %d "
  13232                           "detected, in memory %s index %d\n"), bkt_ptr,
  13233                           SOC_MEM_NAME(u, L3_DEFIPm), lpm_idx));
  13234                 error1 ++;
  13235             } else {
  13236                 success ++;
  13237             }
  13238 
  13239             /* bucket view map */
  13240             bkt_mem_type = soc_alpm_cmn_bkt_view_get(u,
  13241                 SOC_TH_ALPM_AIDX(u, bkt_ptr, 0, 0, 0));
  13242             if (alpm_mem != bkt_mem_type) {
  13243                 LOG_ERROR(BSL_LS_SOC_ALPM,
  13244                           (BSL_META_U(u, "\tMismatched alpm view "
  13245                            "in bucket %d, expected %s, was %s\n"), bkt_ptr,
  13246                            SOC_MEM_NAME(u, alpm_mem),
  13247                            SOC_MEM_NAME(u, bkt_mem_type)));
  13248                 error1 ++;
  13249             } else {
  13250                 success ++;
  13251             }
  13252 
  13253             /* Check bpm len information */
  13254             rv = _soc_th_alpm_prefix_create(u, ipv6, lpm_entry, prefix,
  13255                                             &length, &default_route);
  13256             if (SOC_SUCCESS(rv)) {
  13257                 if (ipv6) {
  13258                     pfx_trie = VRF_PREFIX_TRIE_IPV6(u, vrf);
  13259                 } else {
  13260                     pfx_trie = VRF_PREFIX_TRIE_IPV4(u, vrf);
  13261                 }
  13262                 lpmp = NULL;
  13263                 if (pfx_trie) {
  13264                     rv = trie_find_lpm(pfx_trie, prefix, length, &lpmp);
  13265                 }
  13266                 if (SOC_SUCCESS(rv) && lpmp){
  13267                     tmp_pyld = (payload_t *) lpmp;
  13268                     if (tmp_pyld->bkt_ptr != NULL) {
  13269                         trie_bpm_len = ((payload_t *)(tmp_pyld->bkt_ptr))->len;
  13270                         if (trie_bpm_len != bpm_len) {
  13271                             LOG_ERROR(BSL_LS_SOC_ALPM,
  13272                                       (BSL_META_U(u, "\tBPM len mismatch: lpm_idx %d"
  13273                                       " alpm_idx %d bpm_len %d trie_bpm_len %d\n"),
  13274                                       lpm_idx, alpm_idx, bpm_len, trie_bpm_len));
  13275                             error1 ++;
  13276                         } else {
  13277                             success ++;
  13278                         }
  13279                     } else {
  13280                         success ++;
  13281                     }
  13282                 } else {
  13283                     LOG_ERROR(BSL_LS_SOC_ALPM,
  13284                               (BSL_META_U(u, "\ttrie_find_lpm failed: "
  13285                               "lpm_idx %d alpm_idx %d lpmp %p\n"),
  13286                               lpm_idx, alpm_idx, lpmp));
  13287                     error1 ++;
  13288                 }
  13289             } else {
  13290                 LOG_ERROR(BSL_LS_SOC_ALPM,
  13291                           (BSL_META_U(u, "\tPrefix creating failed: "
  13292                           "lpm_idx %d alpm_idx %d\n" ), lpm_idx, alpm_idx));
  13293                 error1 ++;
  13294             }
  13295         }
  13296     }
  13297 
  13298     if (error1) {
  13299         LOG_ERROR(BSL_LS_SOC_ALPM,
  13300                   (BSL_META_U(u,
  13301                   "\tL3_DEFIP index:[%d,%d] check failed. ipv6 %d error count %d\n"),
  13302                   prev_idx, prev_i, prev_v6, error1));
  13303         error = 1;
  13304     } else if (success) {
  13305         LOG_INFO(BSL_LS_SOC_ALPM,(BSL_META_U(u,
  13306                 "\tL3_DEFIP index:[%d,%d] check passed. ipv6 %d success count %d\n"),
  13307                  prev_idx, prev_i, prev_v6, success));
  13308     }
  13309 
  13310     SOC_ALPM_LPM_UNLOCK(u);
  13311     sal_free(e);
  13312     sal_free(shadow);
  13313     soc_cm_sfree(u, buffer);
  13314 
  13315     return (error ? SOC_E_FAIL: SOC_E_NONE);
  13316 }
  13317 
  13318 extern int _soc_th_alpm_128_sanity_check(int u, int min, int max,
  13319                                          int check_sw, int *bkt_ptr_arr,
  13320                                          alpm_bkt_usg_t  *bkt_usg);
  13321 
  13322 /*
  13323  * Function:
  13324  *      soc_th_alpm_sanity_check
  13325  * Purpose:
  13326  *      Sanity check for ALPM
  13327  * Parameters:
  13328  *      u       - Device unit
  13329  *      mem     -   L3_DEFIP/L3_DEFIP_PAIR_128 memory
  13330  *      index   -   -2 indicates full check to both table,
  13331  *                  -1 indicates full check to given table
  13332  *                  other indicates single entry check to given table
  13333  *      check_sw -  Check SW tables as well.
  13334  */
  13335 int
  13336 soc_th_alpm_sanity_check(int u, soc_mem_t mem, int index, int check_sw)
  13337 {
  13338     int         alloc_size;
  13339     int         rv           = SOC_E_NONE;
  13340     int         rv2          = SOC_E_NONE;
  13341     int         index_min    = -1, index_max  = -1;
  13342     int         index_min2   = -1, index_max2 = -1;
  13343     int         *bkt_ptr_arr = NULL;
  13344 #ifdef ALPM_SANITY_SENSITIVE
  13345     int         i, j;
  13346     soc_mem_t   bkt_view;
  13347 #endif
  13348     alpm_bkt_usg_t  *bkt_usg = NULL;
  13349     int         error, bkt_ptr;
  13350 
  13351     if ((mem == L3_DEFIPm || index == -2) &&
  13352         soc_mem_index_max(u, L3_DEFIPm) != -1) {
  13353         index_min = soc_mem_index_min(u, L3_DEFIPm);
  13354         index_max = soc_mem_index_max(u, L3_DEFIPm);
  13355         /* Don't check urpf */
  13356         if (SOC_URPF_STATUS_GET(u)) {
  13357             index_max >>= 1;
  13358         }
  13359         if (index < -2 || index > index_max) {
  13360             return SOC_E_PARAM;
  13361         }
  13362         if (index >= index_min && index <= index_max) {
  13363             index_min = index;
  13364             index_max = index;
  13365         }
  13366     }
  13367 
  13368     if ((mem == L3_DEFIP_PAIR_128m || index == -2) &&
  13369         soc_mem_index_max(u, L3_DEFIP_PAIR_128m) != -1) {
  13370         index_min2 = soc_mem_index_min(u, L3_DEFIP_PAIR_128m);
  13371         index_max2 = soc_mem_index_max(u, L3_DEFIP_PAIR_128m);
  13372         /* Don't check urpf */
  13373         if (SOC_URPF_STATUS_GET(u)) {
  13374             index_max2 >>= 1;
  13375         }
  13376         if (index < -2 || index > index_max2) {
  13377             return SOC_E_PARAM;
  13378         }
  13379         if (index >= index_min2 && index <= index_max2) {
  13380             index_min2 = index;
  13381             index_max2 = index;
  13382         }
  13383     }
  13384 
  13385     if (index_max == -1 && index_max2 == -1) {
  13386         return SOC_E_PARAM;
  13387     }
  13388 
  13389     L3_LOCK(u);
  13390     alloc_size = sizeof(int) * ALPM_CTRL(u).num_bkts * SOC_TH_MAX_SUB_BUCKETS;
  13391     bkt_ptr_arr = sal_alloc(alloc_size, "Bucket ptr array");
  13392     if (bkt_ptr_arr == NULL) {
  13393         return SOC_E_MEMORY;
  13394     }
  13395     sal_memset(bkt_ptr_arr, 0xff, alloc_size);
  13396 
  13397     alloc_size = ALPM_CTRL(u).num_bkts * sizeof(alpm_bkt_usg_t);
  13398     bkt_usg = sal_alloc(alloc_size, "ALPM bucket usage");
  13399     if (bkt_usg == NULL) {
  13400         sal_free(bkt_ptr_arr);
  13401         return SOC_E_MEMORY;
  13402     }
  13403     sal_memset(bkt_usg, 0, alloc_size);
  13404 
  13405     if (index_max != -1) {
  13406         LOG_CLI(("Processing ALPM sanity check L3_DEFIP "
  13407                  "from index:%d to index:%d\n",
  13408                  index_min, index_max));
  13409         rv = _soc_th_alpm_sanity_check(u, index_min, index_max, check_sw, bkt_ptr_arr, bkt_usg);
  13410         LOG_CLI(("ALPM sanity check L3_DEFIP %s. \n\n",
  13411                  SOC_SUCCESS(rv) ? "passed" : "failed"));
  13412     }
  13413 
  13414     if (index_max2 != -1) {
  13415         LOG_CLI(("Processing ALPM sanity check L3_DEFIP_PAIR_128 "
  13416                  "from index:%d to index:%d\n",
  13417                  index_min2, index_max2));
  13418         rv2 = _soc_th_alpm_128_sanity_check(u, index_min2, index_max2, check_sw, bkt_ptr_arr, bkt_usg);
  13419         LOG_CLI(("ALPM sanity check L3_DEFIP_PAIR_128 %s. \n",
  13420                  SOC_SUCCESS(rv2) ? "passed" : "failed"));
  13421     }
  13422 
  13423 #ifdef ALPM_SANITY_SENSITIVE
  13424     /* This check is very sensitive, turn it off for now. */
  13425     /* In case full check to both table, the bkt ptr is fully collected */
  13426     if (index == -2 && SOC_SUCCESS(rv) && SOC_SUCCESS(rv2)) {
  13427         for (i = 0; i < ALPM_CTRL(u).num_bkts; i++) {
  13428             for (j = 0; j < SOC_TH_MAX_SUB_BUCKETS; j++) {
  13429                 if (bkt_ptr_arr[i * SOC_TH_MAX_SUB_BUCKETS + j] != -1) {
  13430                     break;
  13431                 }
  13432             }
  13433             if (j < SOC_TH_MAX_SUB_BUCKETS) {
  13434                 continue;
  13435             }
  13436 
  13437             bkt_view = soc_alpm_cmn_bkt_view_get(u,
  13438                                                  SOC_TH_ALPM_AIDX(u, i, 0, 0, 0));
  13439             if (bkt_view != INVALIDm){
  13440                 LOG_ERROR(BSL_LS_SOC_ALPM,
  13441                           (BSL_META_U(u,
  13442                           "\tBucket view corrupted: bkt_ptr %d, view %s.\n"),
  13443                           i, SOC_MEM_NAME(u, bkt_view)));
  13444             }
  13445         }
  13446     }
  13447 #endif
  13448 
  13449     /* In case full check to both table and software check is enabled,
  13450      * the bucket usage data is fully collected
  13451      */
  13452     error = 0;
  13453     if (index == -2 && SOC_SUCCESS(rv) && SOC_SUCCESS(rv2) && check_sw) {
  13454         for (bkt_ptr = 0; bkt_ptr < ALPM_CTRL(u).num_bkts; bkt_ptr++) {
  13455             if (bkt_usg[bkt_ptr].count != SOC_ALPM_BU_COUNT(u, bkt_ptr)) {
  13456                 LOG_ERROR(BSL_LS_SOC_ALPM,
  13457                           (BSL_META_U(u, "\tBucket count conflict: "\
  13458                           "phy_bkt %d hw-sw %d-%d\n"),
  13459                           bkt_ptr, bkt_usg[bkt_ptr].count,
  13460                           SOC_ALPM_BU_COUNT(u, bkt_ptr)));
  13461                 error ++;
  13462             }
  13463 
  13464             if (bkt_usg[bkt_ptr].sub_bkts != SOC_ALPM_BU_SUB_BKTS(u, bkt_ptr)) {
  13465                 LOG_ERROR(BSL_LS_SOC_ALPM,
  13466                           (BSL_META_U(u, "\tBucket sub_bkts conflict: "\
  13467                           "phy_bkt %d hw-sw 0x%x-0x%x\n"),
  13468                           bkt_ptr, bkt_usg[bkt_ptr].sub_bkts,
  13469                           SOC_ALPM_BU_SUB_BKTS(u, bkt_ptr)));
  13470                 error ++;
  13471             }
  13472 
  13473             if (bkt_usg[bkt_ptr].pivots[0] != SOC_ALPM_BU_PIVOT_IDX(u, bkt_ptr, 0) ||
  13474                 bkt_usg[bkt_ptr].pivots[1] != SOC_ALPM_BU_PIVOT_IDX(u, bkt_ptr, 1) ||
  13475                 bkt_usg[bkt_ptr].pivots[2] != SOC_ALPM_BU_PIVOT_IDX(u, bkt_ptr, 2) ||
  13476                 bkt_usg[bkt_ptr].pivots[3] != SOC_ALPM_BU_PIVOT_IDX(u, bkt_ptr, 3)) {
  13477                 LOG_ERROR(BSL_LS_SOC_ALPM,
  13478                           (BSL_META_U(u, "\tBucket pivots conflict: "\
  13479                           "phy_bkt %d hw-sw %d-%d %d-%d %d-%d %d-%d\n"),
  13480                           bkt_ptr,
  13481                           bkt_usg[bkt_ptr].pivots[0],
  13482                           SOC_ALPM_BU_PIVOT_IDX(u, bkt_ptr, 0),
  13483                           bkt_usg[bkt_ptr].pivots[1],
  13484                           SOC_ALPM_BU_PIVOT_IDX(u, bkt_ptr, 1),
  13485                           bkt_usg[bkt_ptr].pivots[2],
  13486                           SOC_ALPM_BU_PIVOT_IDX(u, bkt_ptr, 2),
  13487                           bkt_usg[bkt_ptr].pivots[3],
  13488                           SOC_ALPM_BU_PIVOT_IDX(u, bkt_ptr, 3)));
  13489                 error ++;
  13490             }
  13491         }
  13492         LOG_CLI(("ALPM sanity check bucket usage %s. \n",
  13493                  error == 0 ? "passed" : "failed"));
  13494     }
  13495 
  13496     sal_free(bkt_ptr_arr);
  13497     sal_free(bkt_usg);
  13498     L3_UNLOCK(u);
  13499     return SOC_FAILURE(rv)  ? rv  :
  13500            SOC_FAILURE(rv2) ? rv2 :
  13501            error ? SOC_E_FAIL : SOC_E_NONE;
  13502 }
  13503 
  13504 
  13505 STATIC int
  13506 _soc_th_alpm_route_resource_get(int unit, soc_mem_t mem,
  13507                                 int *num_pivots, int *num_bkts)
  13508 {
  13509     int tcam_ent = 0, tot_bkt = 0;
  13510     int tcam_alpm = 0, parallel = 0;
  13511     int urpf = SOC_URPF_STATUS_GET(unit);
  13512     int v6;
  13513 
  13514     switch (ALPM_CTRL(unit).alpm_mode) {
  13515         case SOC_ALPM_MODE_PARALLEL:
  13516             parallel = 1;
  13517             break;
  13518         case SOC_ALPM_MODE_TCAM_ALPM:
  13519             tcam_alpm = 1;
  13520         case SOC_ALPM_MODE_COMBINED:
  13521             break;
  13522         default:
  13523             return SOC_E_INTERNAL;
  13524     }
  13525 
  13526     tot_bkt = ALPM_CTRL(unit).num_bkts;
  13527 
  13528     switch (mem) {
  13529     case L3_DEFIP_ALPM_IPV4m:
  13530     case L3_DEFIP_ALPM_IPV4_1m:
  13531         tcam_ent = soc_mem_index_count(unit, L3_DEFIPm) * 2;
  13532 #ifdef BCM_TOMAHAWK2_SUPPORT
  13533         if (soc_feature(unit, soc_feature_half_of_l3_defip_ipv4_capacity)) {
  13534             tcam_ent >>= 1;
  13535         }
  13536 #endif
  13537         if (ALPM_CTRL(unit)._alpm_128b_bkt_rsvd) {
  13538             tot_bkt -= ALPM_CTRL(unit)._alpm_128b_bkt_rsvd_cnt;
  13539         }
  13540         break;
  13541 
  13542     case L3_DEFIP_ALPM_IPV6_64m:
  13543     case L3_DEFIP_ALPM_IPV6_64_1m:
  13544         tcam_ent = soc_mem_index_count(unit, L3_DEFIP_PAIR_128m);
  13545         if (ALPM_CTRL(unit)._alpm_128b_bkt_rsvd) {
  13546             tot_bkt = ALPM_CTRL(unit)._alpm_128b_bkt_rsvd_cnt;
  13547         }
  13548 
  13549         if (tcam_ent == 0) {
  13550             tcam_ent = soc_mem_index_count(unit, L3_DEFIPm);
  13551             tot_bkt = ALPM_CTRL(unit).num_bkts;
  13552         }
  13553         v6 = 1;
  13554         break;
  13555 
  13556     case L3_DEFIP_ALPM_IPV6_128m:
  13557         tcam_ent = soc_mem_index_count(unit, L3_DEFIP_PAIR_128m);
  13558         if (ALPM_CTRL(unit)._alpm_128b_bkt_rsvd) {
  13559             tot_bkt = ALPM_CTRL(unit)._alpm_128b_bkt_rsvd_cnt;
  13560         }
  13561 
  13562         v6 = 1;
  13563         break;
  13564 
  13565     default:
  13566         break;
  13567     }
  13568 
  13569     if (tcam_alpm) {
  13570         tcam_ent >>= 1;
  13571     }
  13572 
  13573     if (urpf) {
  13574         tcam_ent >>= 1;
  13575     }
  13576 
  13577     if (urpf) {
  13578         if (!parallel) {
  13579             tot_bkt >>= 1;
  13580         }
  13581     } else {
  13582         if (SOC_TH_ALPM_SCALE_CHECK(unit, v6)) {
  13583             tot_bkt >>= 1;
  13584         }
  13585     }
  13586 
  13587     if (num_pivots) {
  13588         *num_pivots = tcam_ent;
  13589     }
  13590 
  13591     if (num_bkts) {
  13592         *num_bkts = tot_bkt;
  13593     }
  13594 
  13595     return SOC_E_NONE;
  13596 }
  13597 
  13598 
  13599 STATIC int
  13600 _soc_th_alpm_route_capacity_max(int unit, soc_mem_t mem)
  13601 {
  13602     int max_ent = 0, ent_num = 0;
  13603     int num_pivots = 0, num_bkts = 0;
  13604     int rv;
  13605 
  13606     rv = _soc_th_alpm_route_resource_get(unit, mem, &num_pivots, &num_bkts);
  13607     if (SOC_FAILURE(rv)) {
  13608         max_ent = -1;
  13609         return max_ent;
  13610     }
  13611 
  13612     ent_num = _soc_th_alpm_bkt_entry_cnt(unit, mem);
  13613 
  13614     if (num_pivots) {
  13615         /* if number of pivots is larger than half of that of buckets,
  13616          * then the MAX buckets allowed is limited by the number of
  13617          * physical buckets
  13618          */
  13619         if (num_pivots <= num_bkts) {
  13620             max_ent = ent_num * num_pivots;
  13621         } else {
  13622             max_ent = ent_num * num_bkts;
  13623         }
  13624 
  13625         if (ALPM_CTRL(unit).alpm_mode == SOC_ALPM_MODE_TCAM_ALPM) {
  13626             max_ent += num_pivots;
  13627         }
  13628     } else {
  13629         max_ent = 0;
  13630     }
  13631 
  13632     return max_ent;
  13633 }
  13634 
  13635 
  13636 STATIC int
  13637 _soc_th_alpm_route_capacity_min(int unit, soc_mem_t mem)
  13638 {
  13639 #define UTIL_50(x) ((x) / 2)
  13640 #define UTIL_75(x) ((x) * 3 / 4)
  13641 #define UTIL_87(x) ((x) * 87 / 100)
  13642 #define UTIL_93(x) ((x) * 93 / 100)
  13643 
  13644     int min_ent = 0, ent_num = 0;
  13645     int num_pivots = 0, num_bkts = 0;
  13646     int rv;
  13647 
  13648     rv = _soc_th_alpm_route_resource_get(unit, mem, &num_pivots, &num_bkts);
  13649     if (SOC_FAILURE(rv)) {
  13650         min_ent = -1;
  13651         return min_ent;
  13652     }
  13653 
  13654     ent_num = _soc_th_alpm_bkt_entry_cnt(unit, mem);
  13655 
  13656     if (num_pivots) {
  13657         if (num_pivots <= num_bkts) {
  13658             /* less than 1:1 */
  13659             min_ent = UTIL_50(ent_num * num_pivots);
  13660         } else {
  13661             if (num_pivots < num_bkts * 2) {
  13662                 /* less than 2:1 */
  13663                 min_ent = UTIL_50(ent_num * num_bkts);
  13664             } else if (num_pivots < num_bkts * 3) {
  13665                 /* less than 3:1 */
  13666                 min_ent = UTIL_75(ent_num * num_bkts);
  13667             } else if (num_pivots < num_bkts * 4) {
  13668                 /* less than 4:1 */
  13669                 min_ent = UTIL_87(ent_num * num_bkts);
  13670             } else {
  13671                 min_ent = UTIL_93(ent_num * num_bkts);
  13672             }
  13673         }
  13674 
  13675         if (ALPM_CTRL(unit).alpm_mode == SOC_ALPM_MODE_TCAM_ALPM) {
  13676             min_ent += num_pivots;
  13677         }
  13678     } else {
  13679         min_ent = 0;
  13680     }
  13681 
  13682     return min_ent;
  13683 }
  13684 /*
  13685  * Function:
  13686  *      soc_th_alpm_route_capacity_get
  13687  * Purpose:
  13688  *      Get the capacity for ALPM from tables:
  13689  * L3_DEFIP_ALPM_IPV4, L3_DEFIP_ALPM_IPV6_64, L3_DEFIP_ALPM_IPV6_128
  13690  * L3_DEFIP, L3_DEFIP_PAIR_128
  13691  * Parameters:
  13692  *      unit         - Device unit
  13693  *      route_type   - 0: v4, 1: v6-64, 2: v6-128
  13694  *      cap_type     - 0: max capacity, 1: min guaranteed capacity
  13695  *      max_entries  - Maximum result returned.
  13696  *      min_entries  - Minimum result returned.
  13697  */
  13698 int
  13699 soc_th_alpm_route_capacity_get(int unit, soc_mem_t mem,
  13700                                int *max_entries, int *min_entries)
  13701 {
  13702 
  13703     if (max_entries == NULL && min_entries == NULL) {
  13704         return SOC_E_PARAM;
  13705     }
  13706     switch (mem) {
  13707     case L3_DEFIP_ALPM_IPV4m:
  13708     case L3_DEFIP_ALPM_IPV4_1m:
  13709     case L3_DEFIP_ALPM_IPV6_64m:
  13710     case L3_DEFIP_ALPM_IPV6_64_1m:
  13711     case L3_DEFIP_ALPM_IPV6_128m:
  13712         break;
  13713     default:
  13714         return SOC_E_UNAVAIL;
  13715     }
  13716     if (min_entries) {
  13717         *min_entries = _soc_th_alpm_route_capacity_min(unit, mem);
  13718         if (*min_entries < 0) {
  13719             return SOC_E_INTERNAL;
  13720         }
  13721     }
  13722 
  13723     if (max_entries != NULL) {
  13724         *max_entries = _soc_th_alpm_route_capacity_max(unit, mem);
  13725         if (*max_entries < 0) {
  13726             return SOC_E_INTERNAL;
  13727         }
  13728     }
  13729 
  13730     return SOC_E_NONE;
  13731 }
  13732 
  13733 #endif /* TOMAHAWK APACHE */
  13734 #endif /* ALPM_ENABLE */