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

lpm.c (477920B)


      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  * Firebolt LPM TCAM table insert/delete/lookup routines
      7  * soc_fb_lpm_init - Called from bcm_l3_init
      8  * soc_fb_lpm_insert - Insert/Update an IPv4/IPV6 route entry into LPM table
      9  * soc_fb_lpm_delete - Delete an IPv4/IPV6 route entry from LPM table
     10  * soc_fb_lpm_match  - (Exact match for the key. Will match both IP address
     11  *                      and mask)
     12  * soc_fb_lpm_lookup (LPM search) - Not Implemented
     13  *
     14  * Hit bit preservation - May loose HIT bit state when entries are moved
     15  * around due to race condition. This happens if the HIT bit gets set in
     16  * hardware after reading the entry to be moved and before the move is
     17  * completed. If the HIT bit for an entry is already set when the move is
     18  * initiated then it is preserved.
     19  */
     20 
     21 #include <shared/bsl.h>
     22 
     23 #include <soc/mem.h>
     24 #include <soc/drv.h>
     25 #include <soc/debug.h>
     26 #include <soc/error.h>
     27 #include <soc/lpm.h>
     28 #include <soc/format.h>
     29 #include <shared/util.h>
     30 #include <shared/avl.h>
     31 #include <shared/l3.h>
     32 #include <shared/bsl.h>
     33 #if defined(BCM_TRIDENT3_SUPPORT)
     34 #include <soc/trident3.h>
     35 #include <bcm_int/esw/trident3.h>
     36 #endif /* BCM_TRIDENT3_SUPPORT */
     37 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_L3)
     38 static soc_kt_lpm_ipv6_info_t *kt_lpm_ipv6_info[SOC_MAX_NUM_DEVICES];
     39 #define L3_DEFIP_TCAM_SIZE 1024
     40 #endif
     41 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
     42 /* Matches with _BCM_TR3_DEFIP_TCAM_DEPTH in triumph3.h */
     43 #define _SOC_TR3_DEFIP_TCAM_DEPTH 1024 
     44 #endif
     45 #ifdef BCM_FIREBOLT_SUPPORT
     46 #if defined(INCLUDE_L3)
     47 soc_field_t defip_mode0_bit[SOC_MAX_NUM_DEVICES];
     48 soc_field_t defip_mode1_bit[SOC_MAX_NUM_DEVICES];
     49 soc_field_t defip_mode_mask0_bit[SOC_MAX_NUM_DEVICES];
     50 soc_field_t defip_mode_mask1_bit[SOC_MAX_NUM_DEVICES];
     51 /*
     52  * TCAM based LPM implementation. Each table entry can hold two IPV4 entries or
     53  * one IPV6 entry. VRF independent routes placed at the beginning or 
     54  * at the end of table based on application provided entry vrf id 
     55  * (SOC_L3_VRF_OVERRIDE/SOC_L3_VRF_GLOBAL).   
     56  *
     57  *              MAX_PFX_INDEX
     58  * lpm_prefix_index[98].begin ---> ===============================
     59  *                                 ==                           ==
     60  *                                 ==    0                      ==
     61  * lpm_prefix_index[98].end   ---> ===============================
     62  *
     63  * lpm_prefix_index[97].begin ---> ===============================
     64  *                                 ==                           ==
     65  *                                 ==    IPV6  Prefix Len = 64  ==
     66  * lpm_prefix_index[97].end   ---> ===============================
     67  *
     68  *
     69  *
     70  * lpm_prefix_index[x].begin --->  ===============================
     71  *                                 ==                           ==
     72  *                                 ==                           ==
     73  * lpm_prefix_index[x].end   --->  ===============================
     74  *
     75  *
     76  *              IPV6_PFX_ZERO
     77  * lpm_prefix_index[33].begin ---> ===============================
     78  *                                 ==                           ==
     79  *                                 ==    IPV6  Prefix Len = 0   ==
     80  * lpm_prefix_index[33].end   ---> ===============================
     81  *
     82  *
     83  * lpm_prefix_index[32].begin ---> ===============================
     84  *                                 ==                           ==
     85  *                                 ==    IPV4  Prefix Len = 32  ==
     86  * lpm_prefix_index[32].end   ---> ===============================
     87  *
     88  *
     89  *
     90  * lpm_prefix_index[0].begin --->  ===============================
     91  *                                 ==                           ==
     92  *                                 ==    IPV4  Prefix Len = 0   ==
     93  * lpm_prefix_index[0].end   --->  ===============================
     94  */
     95 
     96 #if defined(FB_LPM_HASH_SUPPORT)
     97 #undef FB_LPM_AVL_SUPPORT
     98 #elif defined(FB_LPM_AVL_SUPPORT)
     99 #else
    100 #define FB_LPM_HASH_SUPPORT 1
    101 #endif
    102 
    103 #ifdef FB_LPM_CHECKER_ENABLE
    104 #define FB_LPM_AVL_SUPPORT 1
    105 #define FB_LPM_HASH_SUPPORT 1
    106 #endif
    107 
    108 #define SOC_MEM_COMPARE_RETURN(a, b) {          \
    109         if ((a) < (b)) { return -1; }           \
    110         if ((a) > (b)) { return  1; }           \
    111 }
    112 
    113 /* Can move to SOC Control structures */
    114 soc_lpm_state_p soc_lpm_state[SOC_MAX_NUM_DEVICES];
    115 soc_lpm128_table_t *soc_lpm128_state_table[SOC_MAX_NUM_DEVICES];
    116 int *soc_lpm128_index_to_pfx_group[SOC_MAX_NUM_DEVICES];
    117 soc_lpm_stat_p soc_lpm_stat[SOC_MAX_NUM_DEVICES];
    118 soc_ext_lpm_stat_p soc_ext_lpm_stat[SOC_MAX_NUM_DEVICES];
    119 
    120 #define SOC_LPM_CACHE_FIELD_CREATE(m, f) soc_field_info_t * m##f
    121 #define SOC_LPM_CACHE_FIELD_ASSIGN(m_u, s, m, f)  {\
    122          if (SOC_MEM_IS_VALID(m_u,L3_DEFIP_LEVEL1m)) { \
    123                 (s)->m##f = soc_mem_fieldinfo_get(m_u, L3_DEFIP_LEVEL1m, f); \
    124          } else { \
    125                 (s)->m##f = soc_mem_fieldinfo_get(m_u, m, f); \
    126          } \
    127      }
    128 
    129 typedef struct soc_lpm_field_cache_s {
    130     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, CLASS_ID0f);
    131     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, CLASS_ID1f);
    132     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DST_DISCARD0f);
    133     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DST_DISCARD1f);
    134     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP0f);
    135     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP1f);
    136     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_COUNT0f);
    137     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_COUNT1f);
    138     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_PTR0f);
    139     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_PTR1f);
    140     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_ROUTE0f);
    141     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_ROUTE1f);
    142 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
    143     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MULTICAST_ROUTE0f);
    144     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MULTICAST_ROUTE1f);
    145     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f);
    146     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f);
    147     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f);
    148     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f);
    149     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, EXPECTED_L3_IIF0f);
    150     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, EXPECTED_L3_IIF1f);
    151     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPA_ID0f);
    152     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPA_ID1f);
    153     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, L3MC_INDEX0f);
    154     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, L3MC_INDEX1f);
    155 #endif
    156     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, HIT0f);
    157     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, HIT1f);
    158     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR0f);
    159     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR1f);
    160     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR_MASK0f);
    161     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR_MASK1f);
    162     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MODE0f);
    163     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MODE1f);
    164     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, defip_mode0_field);
    165     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, defip_mode1_field);
    166     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, defip_mode_mask0_field);
    167     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, defip_mode_mask1_field);
    168     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, NEXT_HOP_INDEX0f);
    169     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, NEXT_HOP_INDEX1f);
    170     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, PRI0f);
    171     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, PRI1f);
    172     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPE0f);
    173     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPE1f);
    174     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VALID0f);
    175     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VALID1f);
    176     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_0f);
    177     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_1f);
    178     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_MASK0f);
    179     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_MASK1f);
    180     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_TYPE0f);
    181     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_TYPE1f);
    182     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_TYPE_MASK0f);
    183     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_TYPE_MASK1f);
    184     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, D_ID0f);
    185     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, D_ID1f);
    186     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, D_ID_MASK0f);
    187     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, D_ID_MASK1f);
    188     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DEFAULTROUTE0f);
    189     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DEFAULTROUTE1f);
    190 #if defined(BCM_TRIDENT3_SUPPORT)
    191     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, KEY_MODE0f);
    192     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, KEY_MODE1f);
    193     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DESTINATION0f);
    194     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DESTINATION1f);
    195     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DATA_TYPE0f);
    196     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DATA_TYPE1f);
    197 #endif
    198 #if defined(BCM_TRIDENT2_SUPPORT)
    199     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_OFFSET_MODE0f);
    200     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_OFFSET_MODE1f);
    201     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_POOL_NUMBER0f);
    202     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_POOL_NUMBER1f);
    203     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_BASE_COUNTER_IDX0f);
    204     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_BASE_COUNTER_IDX1f);
    205 #endif
    206 #if defined(BCM_TOMAHAWK3_SUPPORT)
    207     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIP_LEVEL1m, HIT0f);
    208     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIP_LEVEL1m, HIT1f);
    209     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIP_LEVEL1m, VALID0f);
    210     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIP_LEVEL1m, VALID1f);
    211     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIP_LEVEL1m, KEY0f);
    212     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIP_LEVEL1m, KEY1f);
    213     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIP_LEVEL1m, MASK0f);
    214     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIP_LEVEL1m, MASK1f);
    215     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIP_LEVEL1m, ASSOC_DATA0f);
    216     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIP_LEVEL1m, ASSOC_DATA1f);
    217     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIP_LEVEL1m, FIXED_DATA0f);
    218     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIP_LEVEL1m, FIXED_DATA1f);
    219     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIP_LEVEL1m, ALPM1_DATA0f);
    220     SOC_LPM_CACHE_FIELD_CREATE(L3_DEFIP_LEVEL1m, ALPM1_DATA1f);
    221 #endif
    222 } soc_lpm_field_cache_t, *soc_lpm_field_cache_p;
    223 static soc_lpm_field_cache_p soc_lpm_field_cache_state[SOC_MAX_NUM_DEVICES];
    224 
    225 #define SOC_TH3_MEM_OPT_F64_GET(m_unit, m_mem, m_entry_data, m_field, pval64) \
    226         soc_meminfo_fieldinfo_field_get((m_entry_data), (&SOC_MEM_INFO(m_unit, m_mem)), (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIP_LEVEL1m##m_field), (pval64))
    227 
    228 #define SOC_TH3_MEM_OPT_F64_SET(m_unit, m_mem, m_entry_data, m_field, m_val) \
    229         soc_meminfo_fieldinfo_field_set((m_entry_data), (&SOC_MEM_INFO(m_unit, m_mem)), (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIP_LEVEL1m##m_field), (m_val))
    230 
    231 #define SOC_TH3_MEM_OPT_F32_GET(m_unit, m_mem, m_entry_data, m_field) \
    232         soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIP_LEVEL1m##m_field))
    233 
    234 #define SOC_TH3_MEM_OPT_F32_SET(m_unit, m_mem, m_entry_data, m_field, m_val) \
    235         soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), ((soc_lpm_field_cache_state[(m_unit)]->L3_DEFIP_LEVEL1m##m_field)), (m_val))
    236 
    237 
    238 #define SOC_MEM_OPT_F32_GET(m_unit, m_mem, m_entry_data, m_field) \
    239         soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPm##m_field))
    240 
    241 #define SOC_MEM_OPT_F32_SET(m_unit, m_mem, m_entry_data, m_field, m_val) \
    242         soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPm##m_field, (m_val))
    243 
    244 #if defined(BCM_TOMAHAWK3_SUPPORT)
    245 #define SOC_MEM_OPT_F32_VALID0_GET(m_unit, m_mem, m_entry_data) \
    246         soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), ((m_mem == L3_DEFIPm) ? \
    247                                           (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPmVALID0f) : soc_lpm_field_cache_state[(m_unit)]->L3_DEFIP_LEVEL1mVALID0f))
    248 
    249 #define SOC_MEM_OPT_F32_VALID0_SET(m_unit, m_mem, m_entry_data, m_val) \
    250         soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), ((m_mem == L3_DEFIPm) ? \
    251                                           (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPmVALID0f) : (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIP_LEVEL1mVALID0f)), (m_val))
    252 
    253 #define SOC_MEM_OPT_F32_VALID1_GET(m_unit, m_mem, m_entry_data) \
    254         soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), ((m_mem == L3_DEFIPm) ? \
    255                                           (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPmVALID1f) : (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIP_LEVEL1mVALID1f)))
    256 
    257 #define SOC_MEM_OPT_F32_VALID1_SET(m_unit, m_mem, m_entry_data, m_val) \
    258         soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), ((m_mem == L3_DEFIPm) ? \
    259                                           (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPmVALID1f) : (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIP_LEVEL1mVALID1f)), (m_val))
    260 
    261 #define SOC_MEM_OPT_F32_HIT0_GET(m_unit, m_mem, m_entry_data) \
    262         soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), ((m_mem == L3_DEFIPm) ? \
    263                                           (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPmHIT0f) : (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIP_LEVEL1mHIT0f)))
    264 
    265 #define SOC_MEM_OPT_F32_HIT0_SET(m_unit, m_mem, m_entry_data, m_val) \
    266         soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), ((m_mem == L3_DEFIPm) ? \
    267                                           (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPmHIT0f) : (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIP_LEVEL1mHIT0f)), (m_val))
    268 
    269 #define SOC_MEM_OPT_F32_HIT1_GET(m_unit, m_mem, m_entry_data) \
    270         soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), ((m_mem == L3_DEFIPm) ? \
    271                                           (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPmHIT1f) : (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIP_LEVEL1mHIT1f)))
    272 
    273 #define SOC_MEM_OPT_F32_HIT1_SET(m_unit, m_mem, m_entry_data, m_val) \
    274         soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), ((m_mem == L3_DEFIPm) ? \
    275                                           (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPmHIT1f) : (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIP_LEVEL1mHIT1f)), (m_val))
    276 #else
    277 
    278 #define SOC_MEM_OPT_F32_VALID0_GET(m_unit, m_mem, m_entry_data) \
    279         soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPmVALID0f)
    280 
    281 #define SOC_MEM_OPT_F32_VALID0_SET(m_unit, m_mem, m_entry_data, m_val) \
    282         soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPmVALID0f, (m_val))
    283 
    284 #define SOC_MEM_OPT_F32_VALID1_GET(m_unit, m_mem, m_entry_data) \
    285         soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPmVALID1f)
    286 
    287 #define SOC_MEM_OPT_F32_VALID1_SET(m_unit, m_mem, m_entry_data, m_val) \
    288         soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPmVALID1f), (m_val))
    289 
    290 #define SOC_MEM_OPT_F32_HIT0_GET(m_unit, m_mem, m_entry_data) \
    291         soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPmHIT0f))
    292 
    293 #define SOC_MEM_OPT_F32_HIT0_SET(m_unit, m_mem, m_entry_data, m_val) \
    294         soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPmHIT0f), (m_val))
    295 
    296 #define SOC_MEM_OPT_F32_HIT1_GET(m_unit, m_mem, m_entry_data) \
    297         soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPmHIT1f))
    298 
    299 #define SOC_MEM_OPT_F32_HIT1_SET(m_unit, m_mem, m_entry_data, m_val) \
    300         soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), (soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPmHIT1f), (m_val))
    301 #endif
    302 #define SOC_MEM_OPT_FIELD_VALID(m_unit, m_mem, m_field) \
    303                 ((soc_lpm_field_cache_state[(m_unit)]->L3_DEFIPm##m_field) != NULL)
    304 
    305 #if defined(FB_LPM_AVL_SUPPORT)
    306 typedef struct soc_lpm_avl_state_s {
    307     uint32      mask0;
    308     uint32      mask1;
    309     uint32      ip0;
    310     uint32      ip1;
    311     uint32      vrf_id;
    312     uint32      index;
    313 } soc_lpm_avl_state_t, *soc_lpm_avl_state_p;
    314 
    315 static shr_avl_t   *avl[SOC_MAX_NUM_DEVICES];   /* AVL tree to track entries */
    316 
    317 #define SOC_LPM_STATE_AVL(u)         (avl[(u)])
    318 /*
    319  * Function:
    320  *      soc_fb_lpm_avl_compare_key
    321  * Purpose:
    322  *      Comparison function for AVL shadow table operations.
    323  */
    324 int
    325 soc_fb_lpm_avl_compare_key(void *user_data,
    326                           shr_avl_datum_t *datum1,
    327                           shr_avl_datum_t *datum2)
    328 {
    329     soc_lpm_avl_state_p d1, d2;
    330     
    331     /* COMPILER_REFERENCE(user_data);*/
    332     d1 = (soc_lpm_avl_state_p)datum1;
    333     d2 = (soc_lpm_avl_state_p)datum2;
    334 
    335     SOC_MEM_COMPARE_RETURN(d1->vrf_id, d2->vrf_id);
    336     SOC_MEM_COMPARE_RETURN(d1->mask1, d2->mask1);
    337     SOC_MEM_COMPARE_RETURN(d1->mask0, d2->mask0);
    338     SOC_MEM_COMPARE_RETURN(d1->ip1, d2->ip1);
    339     SOC_MEM_COMPARE_RETURN(d1->ip0, d2->ip0);
    340 
    341     return(0);
    342 }
    343 
    344 #define LPM_AVL_INSERT_IPV6(u, entry_data, tab_index)                        \
    345 {                                                                            \
    346     soc_lpm_avl_state_t     d;                                               \
    347     d.ip0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR0f);        \
    348     d.ip1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR1f);        \
    349     d.mask0 =                                                                \
    350         SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK0f);       \
    351     d.mask1 =                                                                \
    352         SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK1f);       \
    353     if ((!(SOC_IS_HURRICANE(u))) && \
    354 	 (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f))) {                      \
    355         d.vrf_id = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VRF_ID_0f); \
    356     } else {                                                                 \
    357         d.vrf_id = 0;                                                        \
    358     }                                                                        \
    359     d.index = tab_index;                                                     \
    360     if (shr_avl_insert(SOC_LPM_STATE_AVL(u),                                 \
    361                        soc_fb_lpm_avl_compare_key,                           \
    362                        (shr_avl_datum_t *)&d)) {                             \
    363     }                                                                        \
    364 }
    365 
    366 #define LPM_AVL_INSERT_IPV4_0(u, entry_data, tab_index)                      \
    367 {                                                                            \
    368     soc_lpm_avl_state_t     d;                                               \
    369     d.ip0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR0f);        \
    370     d.mask0 =                                                                \
    371         SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK0f);       \
    372     d.ip1 = 0;                                                               \
    373     d.mask1 = 0x80000001;                                                    \
    374     if ((!(SOC_IS_HURRICANE(u))) && \
    375 	 (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f))) {                      \
    376         d.vrf_id = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VRF_ID_0f); \
    377     } else {                                                                 \
    378         d.vrf_id = 0;                                                        \
    379     }                                                                        \
    380     d.index = (tab_index << 1);                                              \
    381     if (shr_avl_insert(SOC_LPM_STATE_AVL(u),                                 \
    382                        soc_fb_lpm_avl_compare_key,                           \
    383                        (shr_avl_datum_t *)&d)) {                             \
    384     }                                                                        \
    385 }
    386 
    387 #define LPM_AVL_INSERT_IPV4_1(u, entry_data, tab_index)                      \
    388 {                                                                            \
    389     soc_lpm_avl_state_t     d;                                               \
    390     d.ip0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR1f);        \
    391     d.mask0 =                                                                \
    392         SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK1f);       \
    393     d.ip1 = 0;                                                               \
    394     d.mask1 = 0x80000001;                                                    \
    395     if ((!(SOC_IS_HURRICANE(u))) && \
    396 	 (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_1f))) {                      \
    397         d.vrf_id = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VRF_ID_1f); \
    398     } else {                                                                 \
    399         d.vrf_id = 0;                                                        \
    400     }                                                                        \
    401     d.index = (tab_index << 1) + 1;                                          \
    402     if (shr_avl_insert(SOC_LPM_STATE_AVL(u),                                 \
    403                        soc_fb_lpm_avl_compare_key,                           \
    404                        (shr_avl_datum_t *)&d)) {                             \
    405     }                                                                        \
    406 }
    407 
    408 #define LPM_AVL_INSERT(u, entry_data, tab_index)                        \
    409         soc_fb_lpm_avl_insert(u, entry_data, tab_index)
    410 #define LPM_AVL_DELETE(u, entry_data, tab_index)                        \
    411         soc_fb_lpm_avl_delete(u, entry_data)
    412 #define LPM_AVL_LOOKUP(u, key_data, pfx, tab_index)                     \
    413         soc_fb_lpm_avl_lookup(u, key_data, tab_index)
    414 
    415 
    416 void soc_fb_lpm_avl_insert(int u, void *entry_data, uint32 tab_index)
    417 {
    418     uint8 mode;
    419     soc_mem_t mem = L3_DEFIPm;
    420 
    421 #if defined(BCM_TOMAHAWK3_SUPPORT)
    422     if (SOC_IS_TOMAHAWK3(u)) {
    423         uint32 _key_data[2] = {0, 0};
    424         mem  = L3_DEFIP_LEVEL1m;
    425         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, key_data, KEY0f,_key_data);
    426         mode = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf);
    427     } else
    428 #endif
    429     {
    430         mode = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, defip_mode0_field);
    431     }
    432     if (mode) {
    433         /* IPV6 entry */
    434         if (SOC_MEM_OPT_F32_VALID1_GET(u, mem, entry_data) &&
    435             SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data)) {
    436             LPM_AVL_INSERT_IPV6(u, entry_data, tab_index)
    437         }
    438     } else {
    439         /* IPV4 entry */                                                
    440         if (SOC_MEM_OPT_F32_VALID1_GET(u, mem, entry_data)) {
    441             LPM_AVL_INSERT_IPV4_1(u, entry_data, tab_index)
    442         }
    443         if (SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data)) {
    444             LPM_AVL_INSERT_IPV4_0(u, entry_data, tab_index)
    445         }
    446     }
    447 }
    448 
    449 void soc_fb_lpm_avl_delete(int u, void *key_data)
    450 {
    451     soc_lpm_avl_state_t     d;
    452 
    453 #if defined(BCM_TOMAHAWK3_SUPPORT)
    454     if (SOC_IS_TOMAHAWK3(u)) {
    455         uint32 _key_data[2] = {0, 0};
    456         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, key_data, KEY0f, _key_data);
    457         d.ip0 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);
    458         d.vrf_id = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, VRF_IDf);
    459         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, key_data, MASK0f, _key_data);
    460         d.mask0 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);
    461         if (soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf)) {
    462             SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, key_data, KEY1f, _key_data);
    463             d.ip1 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);
    464            SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, key_data, MASK1f, _key_data);
    465             d.mask1 =
    466                 SOC_MEM_OPT_F32_GET(u, L3_DEFIP_LEVEL1m, key_data, IP_ADDR1f);
    467         } else {
    468             d.ip1 = 0;
    469             d.mask1 = 0x80000001;
    470         }
    471     } else
    472 #endif
    473     {
    474         d.ip0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, IP_ADDR0f);
    475         d.mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, IP_ADDR_MASK0f);
    476 
    477         if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f)) {
    478             d.vrf_id = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, VRF_ID_0f);
    479         } else {
    480             d.vrf_id = 0;
    481         }
    482         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, defip_mode0_field)) {
    483             d.ip1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, IP_ADDR1f);
    484             d.mask1 =
    485                 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, IP_ADDR_MASK1f);
    486         } else {
    487             d.ip1 = 0;
    488             d.mask1 = 0x80000001;
    489         }
    490     }
    491     if (shr_avl_delete(SOC_LPM_STATE_AVL(u),
    492                        soc_fb_lpm_avl_compare_key,
    493                        (shr_avl_datum_t *)&d)) {
    494     }
    495 }
    496 
    497 int soc_fb_lpm_avl_lookup(int u, void *key_data, int *tab_index)
    498 {
    499     soc_lpm_avl_state_t     d;
    500 
    501 #if defined(BCM_TOMAHAWK3_SUPPORT)
    502     if (SOC_MEM_IS_VALID(u, L3_DEFIP_LEVEL1m)) {
    503         uint32 _key_data[2] = {0, 0};
    504         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, key_data, KEY0f, _key_data);
    505         d.ip0 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);
    506         d.vrf_id = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, VRF_IDf);
    507 
    508         /* Entry Type: IPv4/IPv6 */
    509         if (soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf) != 0) {
    510             SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, key_data, KEY1f, _key_data);
    511             d.ip1 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);
    512             SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, key_data, MASK1f, _key_data);
    513             d.mask1 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);
    514         } else {
    515             d.ip1 = 0;
    516             d.mask1 = 0x80000001;
    517         }
    518     } else
    519 #endif
    520     {
    521 
    522         d.ip0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, IP_ADDR0f);
    523         d.mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm,  key_data, IP_ADDR_MASK0f);
    524 
    525         if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f)) {
    526             d.vrf_id = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, VRF_ID_0f);
    527         } else {
    528             d.vrf_id = 0;
    529         }
    530 
    531         /* Entry Type: IPv4/IPv6 */
    532         if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, defip_mode0_field)) {
    533             d.ip1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm,  key_data, IP_ADDR1f);
    534             d.mask1 =
    535                 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm,  key_data, IP_ADDR_MASK1f);
    536         } else {
    537             d.ip1 = 0;
    538             d.mask1 = 0x80000001;
    539         }
    540     }
    541     if (shr_avl_lookup(SOC_LPM_STATE_AVL(u),
    542                        soc_fb_lpm_avl_compare_key,
    543                        (shr_avl_datum_t *)&d)) {
    544         *tab_index = d.index;
    545     } else {
    546         return SOC_E_NOT_FOUND;
    547     }
    548     return SOC_E_NONE;
    549 }
    550 #else
    551 #define LPM_AVL_INSERT(u, entry_data, tab_index)
    552 #define LPM_AVL_DELETE(u, entry_data, tab_index)
    553 #define LPM_AVL_LOOKUP(u, key_data, pfx, tab_index)
    554 #endif /* FB_LPM_AVL_SUPPORT */
    555 /* #define FB_LPM_DEBUG */
    556 #ifdef FB_LPM_HASH_SUPPORT
    557 #define _SOC_LPM128_HASH_KEY_LEN_IN_WORDS 10
    558 typedef struct _soc_fb_lpm_hash_s {
    559     int         unit;
    560     int         entry_count;    /* Number entries in hash table */
    561     int         index_count;    /* Hash index max value + 1 */
    562     uint32      *table;         /* Hash table with 32 bit index */
    563     uint32      *link_table;    /* To handle collisions */
    564 #ifdef FB_LPM_DEBUG
    565     uint32      *check_table;   /* To help sanity check */
    566 #endif
    567 } _soc_fb_lpm_hash_t;
    568 
    569 typedef uint32 _soc_fb_lpm_hash_entry_t[6];
    570 typedef uint32 _soc_fb_lpm128_hash_entry_t[_SOC_LPM128_HASH_KEY_LEN_IN_WORDS];
    571 typedef int (*_soc_fb_lpm_hash_compare_fn)(_soc_fb_lpm_hash_entry_t key1,
    572                                            _soc_fb_lpm_hash_entry_t key2);
    573 typedef int (*_soc_fb_lpm128_hash_compare_fn)(_soc_fb_lpm128_hash_entry_t key1,
    574                                            _soc_fb_lpm128_hash_entry_t key2);
    575 static _soc_fb_lpm_hash_t *_fb_lpm_hash_tab[SOC_MAX_NUM_DEVICES];
    576 static _soc_fb_lpm_hash_t *_fb_lpm128_hash_tab[SOC_MAX_NUM_DEVICES];
    577 
    578 static uint32 fb_lpm_hash_index_mask[SOC_MAX_NUM_DEVICES] = {0};
    579 
    580 #define SOC_LPM_STATE_HASH(u)           (_fb_lpm_hash_tab[(u)])
    581 #define SOC_LPM128_STATE_HASH(u)           (_fb_lpm128_hash_tab[(u)])
    582 
    583 #if defined(BCM_TOMAHAWK3_SUPPORT)
    584 #define SOC_TH3_LPM128_HASH_ENTRY_IPV6_GET(u, entry_data, entry_data_upr, odata) {       \
    585         uint32 _key_data[2] = {0, 0};                                                             \
    586         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data_upr, KEY1f, _key_data);  \
    587         odata[0] = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf); \
    588         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data_upr, MASK1f, _key_data); \
    589         odata[1] = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf); \
    590         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data_upr, KEY0f, _key_data);  \
    591         odata[2] = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, entry_data_upr,       \
    592                                                                               IP_ADDRf); \
    593         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data_upr, MASK0f, _key_data);        \
    594         odata[3] = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf); \
    595         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, KEY1f, _key_data);      \
    596         odata[4] = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf); \
    597         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, MASK1f, _key_data);     \
    598         odata[5] = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf); \
    599         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, KEY0f, _key_data);      \
    600         odata[6] = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, entry_data_upr,       \
    601                                                                               IP_ADDRf); \
    602         odata[8] = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, entry_data_upr,       \
    603                                                                               VRF_IDf);  \
    604         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, MASK0f, _key_data);     \
    605         odata[7] = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf); \
    606     }
    607 
    608 #define SOC_TH3_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, odata)             \
    609     uint32 _key_data[2] = {0, 0};                                                     \
    610     SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, KEY0f, _key_data); \
    611     odata[0] =                                                               \
    612         soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);\
    613     soc_fb_lpm_hash_vrf_0_get(u, entry_data, &odata[5]);                     \
    614     odata[4] =                                                               \
    615         soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, VRF_IDf); \
    616     SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, MASK0f, _key_data); \
    617     odata[1] =                                                               \
    618         soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);\
    619     SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, KEY1f, _key_data); \
    620     odata[2] =                                                               \
    621         soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);   \
    622     SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, MASK1f, _key_data);\
    623     odata[3] =                                                                  \
    624         soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);   \
    625 
    626 #define SOC_TH3_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, odata)           \
    627     uint32 _key_data[2] = {0, 0};                                                     \
    628     SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, KEY0f, _key_data); \
    629     odata[0] =                                                               \
    630         soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);\
    631     odata[4] =                                                               \
    632         soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, VRF_IDf); \
    633     SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, MASK0f, _key_data); \
    634     odata[1] =                                                               \
    635         soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);\
    636     odata[2] = 0;                                                            \
    637     odata[3] = 0x80000001;                                                   \
    638     soc_fb_lpm_hash_vrf_0_get(u, entry_data, &odata[5]);
    639 
    640 #define SOC_TH3_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, odata)           \
    641     uint32 _key_data[2] = {0, 0};                                                     \
    642     SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, KEY1f, _key_data);       \
    643     odata[0] =                                                               \
    644         soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);\
    645     odata[4] =                                                               \
    646         soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, VRF_IDf); \
    647     SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, MASK1f, _key_data);     \
    648     odata[1] =                                                               \
    649         soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);\
    650     odata[2] = 0;                                                            \
    651     odata[3] = 0x80000001;                                                   \
    652     soc_fb_lpm_hash_vrf_1_get(u, entry_data, &odata[5]);
    653 #else
    654 #define SOC_TH3_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, odata)
    655 #define SOC_TH3_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, odata)
    656 #define SOC_TH3_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, odata)
    657 #define SOC_TH3_LPM128_HASH_ENTRY_IPV6_GET(u, entry_data, entry_data_upr, odata)
    658 #endif
    659 
    660 #define SOC_FB_LPM128_HASH_ENTRY_IPV6_GET(u, entry_data, entry_data_upr, odata)         \
    661     if (SOC_IS_TOMAHAWK3(u)) {                                                          \
    662         SOC_TH3_LPM128_HASH_ENTRY_IPV6_GET(u, entry_data, entry_data_upr, odata)        \
    663     } else {                                                                            \
    664         odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data_upr, IP_ADDR1f);        \
    665         odata[1] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data_upr, IP_ADDR_MASK1f);   \
    666         odata[2] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data_upr, IP_ADDR0f);        \
    667         odata[3] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data_upr, IP_ADDR_MASK0f);   \
    668         odata[4] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR1f);            \
    669         odata[5] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK1f);       \
    670         odata[6] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR0f);            \
    671         odata[7] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK0f);\
    672         if ( (!(SOC_IS_HURRICANE(u))) &&                                         \
    673             (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f))) {                \
    674             odata[8] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VRF_ID_0f); \
    675             soc_fb_lpm_hash_vrf_0_get(u, entry_data, &odata[9]);                 \
    676         } else {                                                                 \
    677             odata[8] = 0;                                                        \
    678             odata[9] = 0;                                                        \
    679         }                                                                        \
    680     }
    681 
    682 #define SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, odata)                     \
    683     if (SOC_MEM_IS_VALID(u, L3_DEFIP_LEVEL1m)) {                                 \
    684         SOC_TH3_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, odata)                    \
    685     } else {                                                                     \
    686         odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR0f);     \
    687         odata[1] =                                                               \
    688             SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK0f);       \
    689         odata[2] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR1f);     \
    690         odata[3] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK1f);\
    691         if ( (!(SOC_IS_HURRICANE(u))) &&                                         \
    692             (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f))) {                \
    693             odata[4] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VRF_ID_0f); \
    694             soc_fb_lpm_hash_vrf_0_get(u, entry_data, &odata[5]);                 \
    695         } else {                                                                 \
    696             odata[4] = 0;                                                        \
    697             odata[5] = 0;                                                        \
    698         }                                                                        \
    699     }
    700 
    701 #define SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, odata)               \
    702     if (SOC_MEM_IS_VALID(u, L3_DEFIP_LEVEL1m)) {                                 \
    703         SOC_TH3_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, odata)                 \
    704     } else {                                                                     \
    705         odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR0f);     \
    706         odata[1] =                                                               \
    707             SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK0f);       \
    708         odata[2] = 0;                                                            \
    709         odata[3] = 0x80000001;                                                   \
    710         if ((!(SOC_IS_HURRICANE(u))) &&                                          \
    711             (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f))) {                \
    712             odata[4] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VRF_ID_0f); \
    713             soc_fb_lpm_hash_vrf_0_get(u, entry_data, &odata[5]);                 \
    714         } else {                                                                 \
    715             odata[4] = 0;                                                        \
    716             odata[5] = 0;                                                        \
    717         }                                                                        \
    718     }
    719 
    720 #define SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, odata)               \
    721     if (SOC_MEM_IS_VALID(u, L3_DEFIP_LEVEL1m)) {                                 \
    722         SOC_TH3_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, odata)               \
    723     } else {                                                                     \
    724         odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR1f);     \
    725         odata[1] =                                                               \
    726             SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK1f);       \
    727         odata[2] = 0;                                                            \
    728         odata[3] = 0x80000001;                                                   \
    729         if ((!(SOC_IS_HURRICANE(u))) &&  \
    730             (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_1f))) {                \
    731             odata[4] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VRF_ID_1f); \
    732             soc_fb_lpm_hash_vrf_1_get(u, entry_data, &odata[5]);                 \
    733         } else {                                                                 \
    734             odata[4] = 0;                                                        \
    735             odata[5] = 0;                                                        \
    736         }                                                                        \
    737     }
    738 #ifdef FB_LPM_DEBUG
    739 #define INDEX_ADD_DEBUG(hash, hash_idx, new_idx)                        \
    740     if (hash->check_table[new_idx & FB_LPM_HASH_INDEX_MASK] != 0) {     \
    741         LOG_CLI(("INDEX ADD new_idx %d hash_idx %d check_idx %d\n",     \
    742         new_idx, hash_idx, hash->check_table[new_idx & FB_LPM_HASH_INDEX_MASK]));\
    743         soc_fb_lpm_debug_collect(hash->unit);                           \
    744     } else {                                                            \
    745         hash->check_table[new_idx & FB_LPM_HASH_INDEX_MASK] = 1;        \
    746     }
    747 
    748 #define INDEX_UPDATE_DEBUG(hash, hash_idx, old_idx, new_idx)            \
    749     if (hash->check_table[new_idx & FB_LPM_HASH_INDEX_MASK] != 0 ||     \
    750         hash->check_table[old_idx & FB_LPM_HASH_INDEX_MASK] == 0) {     \
    751         LOG_CLI(("INDEX UPDATE new_idx %d old_idx %d hash_idx %d check_idx %d %d\n", \
    752         new_idx, old_idx, hash_idx, hash->check_table[new_idx & FB_LPM_HASH_INDEX_MASK],\
    753         hash->check_table[old_idx & FB_LPM_HASH_INDEX_MASK]));          \
    754         soc_fb_lpm_debug_collect(hash->unit);                           \
    755     } else {                                                            \
    756         hash->check_table[new_idx & FB_LPM_HASH_INDEX_MASK] = 1;        \
    757         hash->check_table[old_idx & FB_LPM_HASH_INDEX_MASK] = 0;        \
    758     }
    759 
    760 #define INDEX_UPDATE_LINK_DEBUG(hash, prev_idx, old_idx, new_idx)       \
    761     if (hash->check_table[new_idx & FB_LPM_HASH_INDEX_MASK] != 0 ||     \
    762         hash->check_table[old_idx & FB_LPM_HASH_INDEX_MASK] == 0 ||     \
    763         hash->check_table[prev_idx & FB_LPM_HASH_INDEX_MASK] == 0) {    \
    764         LOG_CLI(("INDEX UPDATE_LINK new_idx %d old_idx %d prev_idx %d " \
    765                  "check_idx %d %d %d\n",                                \
    766         new_idx, old_idx, prev_idx,                                     \
    767         hash->check_table[new_idx & FB_LPM_HASH_INDEX_MASK],            \
    768         hash->check_table[old_idx & FB_LPM_HASH_INDEX_MASK],            \
    769         hash->check_table[prev_idx & FB_LPM_HASH_INDEX_MASK]));         \
    770         soc_fb_lpm_debug_collect(hash->unit);                           \
    771     } else {                                                            \
    772         hash->check_table[new_idx & FB_LPM_HASH_INDEX_MASK] = 1;        \
    773         hash->check_table[old_idx & FB_LPM_HASH_INDEX_MASK] = 0;        \
    774     }
    775 
    776 #define INDEX_DELETE_DEBUG(hash, hash_idx, del_idx)                     \
    777     if (hash->check_table[del_idx & FB_LPM_HASH_INDEX_MASK] == 0) {     \
    778         LOG_CLI(("INDEX DELETE del_idx %d hash_idx %d check_idx %d\n",  \
    779         del_idx, hash_idx,                                              \
    780         hash->check_table[del_idx & FB_LPM_HASH_INDEX_MASK]));          \
    781         soc_fb_lpm_debug_collect(hash->unit);                           \
    782     } else {                                                            \
    783         hash->check_table[del_idx & FB_LPM_HASH_INDEX_MASK] = 0;        \
    784     } 
    785 
    786 #define INDEX_DELETE_LINK_DEBUG(hash, prev_idx, del_idx)                \
    787     if (hash->check_table[prev_idx & FB_LPM_HASH_INDEX_MASK] == 0 ||    \
    788         hash->check_table[del_idx & FB_LPM_HASH_INDEX_MASK] == 0) {     \
    789         LOG_CLI(("INDEX DELETE LINK prev_idx %d del_idx %d check_idx %d %d\n", \
    790         prev_idx, del_idx,                                              \
    791         hash->check_table[prev_idx & FB_LPM_HASH_INDEX_MASK],           \
    792         hash->check_table[del_idx & FB_LPM_HASH_INDEX_MASK]));          \
    793         soc_fb_lpm_debug_collect(hash->unit);                           \
    794     } else {                                                            \
    795         hash->check_table[del_idx & FB_LPM_HASH_INDEX_MASK] = 0;        \
    796     }
    797 #else
    798 #define INDEX_ADD_DEBUG(hash, hash_idx, new_idx)
    799 #define INDEX_UPDATE_DEBUG(hash, hash_idx, old_idx, new_idx)
    800 #define INDEX_UPDATE_LINK_DEBUG(hash, prev_idx, old_idx, new_idx)
    801 #define INDEX_DELETE_DEBUG(hash, hash_idx, del_idx)
    802 #define INDEX_DELETE_LINK_DEBUG(hash, prev_idx, del_idx)
    803 #endif
    804 
    805 #define INDEX_ADD(hash, hash_idx, new_idx)                      \
    806     INDEX_ADD_DEBUG(hash, hash_idx, new_idx)                    \
    807     hash->link_table[new_idx & FB_LPM_HASH_INDEX_MASK] =        \
    808         hash->table[hash_idx];                                  \
    809     hash->table[hash_idx] = new_idx
    810 
    811 #define INDEX_ADD_LINK(hash, t_index, new_idx)                  \
    812     hash->link_table[new_idx & FB_LPM_HASH_INDEX_MASK] =        \
    813         hash->link_table[t_index & FB_LPM_HASH_INDEX_MASK];     \
    814     hash->link_table[t_index & FB_LPM_HASH_INDEX_MASK] = new_idx
    815 
    816 #define INDEX_UPDATE(hash, hash_idx, old_idx, new_idx)          \
    817     INDEX_UPDATE_DEBUG(hash, hash_idx, old_idx, new_idx)        \
    818     hash->table[hash_idx] = new_idx;                            \
    819     hash->link_table[new_idx & FB_LPM_HASH_INDEX_MASK] =        \
    820         hash->link_table[old_idx & FB_LPM_HASH_INDEX_MASK];     \
    821     hash->link_table[old_idx & FB_LPM_HASH_INDEX_MASK] = FB_LPM_HASH_INDEX_NULL
    822 
    823 #define INDEX_UPDATE_LINK(hash, prev_idx, old_idx, new_idx)             \
    824     INDEX_UPDATE_LINK_DEBUG(hash, prev_idx, old_idx, new_idx)           \
    825     hash->link_table[prev_idx & FB_LPM_HASH_INDEX_MASK] = new_idx;      \
    826     hash->link_table[new_idx & FB_LPM_HASH_INDEX_MASK] =                \
    827         hash->link_table[old_idx & FB_LPM_HASH_INDEX_MASK];             \
    828     hash->link_table[old_idx & FB_LPM_HASH_INDEX_MASK] = FB_LPM_HASH_INDEX_NULL
    829 
    830 #define INDEX_DELETE(hash, hash_idx, del_idx)                   \
    831     INDEX_DELETE_DEBUG(hash, hash_idx, del_idx)                 \
    832     hash->table[hash_idx] =                                     \
    833         hash->link_table[del_idx & FB_LPM_HASH_INDEX_MASK];     \
    834     hash->link_table[del_idx & FB_LPM_HASH_INDEX_MASK] =        \
    835         FB_LPM_HASH_INDEX_NULL
    836 
    837 #define INDEX_DELETE_LINK(hash, prev_idx, del_idx)              \
    838     INDEX_DELETE_LINK_DEBUG(hash, prev_idx, del_idx)            \
    839     hash->link_table[prev_idx & FB_LPM_HASH_INDEX_MASK] =       \
    840         hash->link_table[del_idx & FB_LPM_HASH_INDEX_MASK];     \
    841     hash->link_table[del_idx & FB_LPM_HASH_INDEX_MASK] =        \
    842         FB_LPM_HASH_INDEX_NULL
    843 
    844 /*
    845  * Function:
    846  *      soc_fb_lpm_hash_vrf_0_get and soc_fb_lpm_hash_vrf_1_get
    847  * Purpose:
    848  *      Service routine used to determine the vrf type 
    849  * Parameters:
    850  *      unit      - (IN)SOC unit number.
    851  *      lpm_entry - (IN)Route info buffer from hw.
    852  *      vrf_id    - (OUT)Virtual router id.
    853  * Returns:
    854  *      BCM_E_XXX
    855  */
    856 STATIC void
    857 soc_fb_lpm_hash_vrf_0_get(int unit, void *lpm_entry, uint32 *vrf)
    858 {
    859     int vrf_id;
    860 
    861     /* Get Virtual Router id if supported. */
    862 #if defined(BCM_TOMAHAWK3_SUPPORT)
    863     if (!SOC_MEM_IS_VALID(unit, L3_DEFIPm)) {
    864         uint32 _key_data[2] = {0, 0};
    865         int vrf_level;
    866         SOC_TH3_MEM_OPT_F64_GET(unit, L3_DEFIP_LEVEL1m, lpm_entry, FIXED_DATA0f, _key_data);
    867         vrf_level = soc_format_field32_get(unit, FIXED_DATAfmt, _key_data, SUB_DB_PRIORITYf);
    868 
    869         /* Special vrf's handling. */
    870         if (1 == vrf_level) {
    871             *vrf = _SOC_HASH_L3_VRF_SPECIFIC;
    872         } else if (2 == vrf_level) {
    873             *vrf = _SOC_HASH_L3_VRF_GLOBAL;
    874         } else if (0 == vrf_level) {
    875             *vrf = _SOC_HASH_L3_VRF_OVERRIDE;
    876         } else {
    877             *vrf = _SOC_HASH_L3_VRF_DEFAULT;
    878         }
    879     } else 
    880 #endif
    881     if (SOC_MEM_OPT_FIELD_VALID(unit,L3_DEFIPm, VRF_ID_MASK0f)){
    882         vrf_id = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VRF_ID_0f);
    883 
    884         /* Special vrf's handling. */
    885         if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f)) {
    886             *vrf = _SOC_HASH_L3_VRF_SPECIFIC;
    887         } else if (SOC_VRF_MAX(unit) == vrf_id) {
    888             *vrf = _SOC_HASH_L3_VRF_GLOBAL;
    889         } else {
    890             *vrf = _SOC_HASH_L3_VRF_OVERRIDE;
    891             if (SOC_MEM_OPT_FIELD_VALID(unit, L3_DEFIPm, GLOBAL_ROUTE0f)) {
    892                 if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f)) {
    893                     *vrf = _SOC_HASH_L3_VRF_GLOBAL;
    894                 }
    895             }
    896         }
    897     } else {
    898         /* No vrf support on this device. */
    899         *vrf = _SOC_HASH_L3_VRF_DEFAULT;
    900     }
    901 }
    902 
    903 STATIC void
    904 soc_fb_lpm_hash_vrf_1_get(int unit, void *lpm_entry, uint32 *vrf)
    905 {
    906     int vrf_id;
    907 
    908     /* Get Virtual Router id if supported. */
    909 #if defined(BCM_TOMAHAWK3_SUPPORT)
    910     if (!SOC_MEM_IS_VALID(unit, L3_DEFIPm)) {
    911         uint32 _key_data[2] = {0, 0};
    912         int vrf_level;
    913         SOC_TH3_MEM_OPT_F64_GET(unit, L3_DEFIP_LEVEL1m, lpm_entry, FIXED_DATA1f, _key_data);
    914         vrf_level = soc_format_field32_get(unit, FIXED_DATAfmt, _key_data, SUB_DB_PRIORITYf);
    915 
    916         /* Special vrf's handling. */
    917         if (1 == vrf_level) {
    918             *vrf = _SOC_HASH_L3_VRF_SPECIFIC;
    919         } else if (2 == vrf_level) {
    920             *vrf = _SOC_HASH_L3_VRF_GLOBAL;
    921         } else if (0 == vrf_level) {
    922             *vrf = _SOC_HASH_L3_VRF_OVERRIDE;
    923             if (SOC_MEM_OPT_FIELD_VALID(unit, L3_DEFIPm, GLOBAL_ROUTE0f)) {
    924                 if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f)) {
    925                     *vrf = _SOC_HASH_L3_VRF_GLOBAL;
    926                 }
    927             }
    928         } else {
    929             *vrf = _SOC_HASH_L3_VRF_DEFAULT;
    930         }
    931     } else
    932 #endif
    933     if (SOC_MEM_OPT_FIELD_VALID(unit, L3_DEFIPm, VRF_ID_MASK1f)){
    934         vrf_id = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VRF_ID_1f);
    935 
    936         /* Special vrf's handling. */
    937         if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK1f)) {
    938             *vrf = _SOC_HASH_L3_VRF_SPECIFIC;    
    939         } else if (SOC_VRF_MAX(unit) == vrf_id) {
    940             *vrf = _SOC_HASH_L3_VRF_GLOBAL;
    941         } else {
    942             *vrf = _SOC_HASH_L3_VRF_OVERRIDE;    
    943             if (SOC_MEM_OPT_FIELD_VALID(unit, L3_DEFIPm, GLOBAL_ROUTE1f)) {
    944                 if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE1f)) {
    945                     *vrf = _SOC_HASH_L3_VRF_GLOBAL; 
    946                 }
    947             }
    948         }
    949     } else {
    950         /* No vrf support on this device. */
    951         *vrf = _SOC_HASH_L3_VRF_DEFAULT;
    952     }
    953 }
    954 
    955 
    956 #define SOC_FB_LPM_HASH_ENTRY_GET _soc_fb_lpm_hash_entry_get
    957 #define SOC_FB_LPM128_HASH_ENTRY_GET _soc_fb_lpm128_hash_entry_get
    958 
    959 static
    960 void _soc_fb_lpm_hash_entry_get(int u, void *e,
    961                                 int index, _soc_fb_lpm_hash_entry_t r_entry,
    962                                 int *v);
    963 static
    964 unsigned int _soc_fb_lpm_hash_compute(uint8 *data, int data_nbits);
    965 static
    966 int _soc_fb_lpm_hash_create(int unit,
    967                             int entry_count,
    968                             int index_count,
    969                             _soc_fb_lpm_hash_t **fb_lpm_hash_ptr);
    970 static
    971 int _soc_fb_lpm_hash_destroy(_soc_fb_lpm_hash_t *fb_lpm_hash);
    972 static
    973 int _soc_fb_lpm_hash_lookup(_soc_fb_lpm_hash_t          *hash,
    974                             _soc_fb_lpm_hash_compare_fn key_cmp_fn,
    975                             _soc_fb_lpm_hash_entry_t    entry,
    976                             int                         pfx,
    977                             uint32                      *key_index);
    978 static
    979 int _soc_fb_lpm_hash_insert(_soc_fb_lpm_hash_t *hash,
    980                             _soc_fb_lpm_hash_compare_fn key_cmp_fn,
    981                             _soc_fb_lpm_hash_entry_t entry,
    982                             int    pfx,
    983                             uint32 old_index,
    984                             uint32 new_index,
    985                             uint32 *rvt_index);
    986 static
    987 int _soc_fb_lpm_hash_revert(_soc_fb_lpm_hash_t *hash,
    988                             _soc_fb_lpm_hash_compare_fn key_cmp_fn,
    989                             _soc_fb_lpm_hash_entry_t entry,
    990                             uint32 new_index,
    991                             uint32 rvt_index);
    992 
    993 static
    994 int _soc_fb_lpm128_hash_insert(_soc_fb_lpm_hash_t *hash,
    995                             _soc_fb_lpm_hash_compare_fn key_cmp_fn,
    996                             _soc_fb_lpm128_hash_entry_t entry,
    997                             int    pfx,
    998                             uint32 old_index,
    999                             uint32 new_index,
   1000                             uint32 *rvt_index);
   1001 
   1002 static
   1003 int _soc_fb_lpm128_hash_revert(_soc_fb_lpm_hash_t *hash,
   1004                             _soc_fb_lpm_hash_compare_fn key_cmp_fn,
   1005                             _soc_fb_lpm128_hash_entry_t entry,
   1006                             uint32 new_index,
   1007                             uint32 rvt_index);
   1008 
   1009 
   1010 static
   1011 int _soc_fb_lpm_hash_delete(_soc_fb_lpm_hash_t *hash,
   1012                             _soc_fb_lpm_hash_compare_fn key_cmp_fn,
   1013                             _soc_fb_lpm_hash_entry_t entry,
   1014                             int    pfx,
   1015                             uint32 delete_index);
   1016 
   1017 /*
   1018  *      Extract key data from an entry at the given index.
   1019  */
   1020 static
   1021 void _soc_fb_lpm_hash_entry_get(int u, void *e,
   1022                                 int index, _soc_fb_lpm_hash_entry_t r_entry,
   1023                                 int *v)
   1024 {
   1025     soc_mem_t mem = L3_DEFIPm;
   1026 
   1027     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   1028         mem = L3_DEFIP_LEVEL1m;
   1029     }
   1030 
   1031     if (index & FB_LPM_HASH_IPV6_MASK) {
   1032 
   1033 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1034         if (SOC_MEM_IS_VALID(u, L3_DEFIP_LEVEL1m)) {
   1035             SOC_TH3_LPM_HASH_ENTRY_IPV6_GET(u, e, r_entry);
   1036         } else
   1037 #endif
   1038         {
   1039             SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, e, r_entry);
   1040         }
   1041         if (v) {
   1042             *v =  SOC_MEM_OPT_F32_VALID0_GET(u, mem, e) &&
   1043                   SOC_MEM_OPT_F32_VALID1_GET(u, mem, e);
   1044         }
   1045     } else {
   1046         if (index & 0x1) {
   1047             SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, e, r_entry);
   1048             if (v) {
   1049                 *v =  SOC_MEM_OPT_F32_VALID1_GET(u, mem, e);
   1050             }
   1051         } else {
   1052             SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, e, r_entry);
   1053             if (v) {
   1054                 *v =  SOC_MEM_OPT_F32_VALID0_GET(u, mem, e);
   1055             }
   1056         }
   1057     }
   1058 }
   1059 
   1060 
   1061 /*
   1062  * Function:
   1063  *      _soc_fb_lpm_hash_compare_key
   1064  * Purpose:
   1065  *      Comparison function for AVL shadow table operations.
   1066  */
   1067 static
   1068 int _soc_fb_lpm_hash_compare_key(_soc_fb_lpm_hash_entry_t key1,
   1069                                  _soc_fb_lpm_hash_entry_t key2)
   1070 {
   1071     int idx;
   1072 
   1073     for (idx = 0; idx < 6; idx++) { 
   1074         SOC_MEM_COMPARE_RETURN(key1[idx], key2[idx]);
   1075     }
   1076     return (0);
   1077 }
   1078 
   1079 /*
   1080  * Function:
   1081  *      _soc_fb_lpm_hash_compare_key
   1082  * Purpose:
   1083  *      Comparison function for AVL shadow table operations.
   1084  */
   1085 static
   1086 int _soc_fb_lpm128_hash_compare_key(_soc_fb_lpm128_hash_entry_t key1,
   1087                                  _soc_fb_lpm128_hash_entry_t key2)
   1088 {
   1089     int idx;
   1090 
   1091     for (idx = 0; idx < _SOC_LPM128_HASH_KEY_LEN_IN_WORDS; idx++) { 
   1092         SOC_MEM_COMPARE_RETURN(key1[idx], key2[idx]);
   1093     }
   1094     return (0);
   1095 }
   1096 
   1097 
   1098 #define SOC_LPM_STATE_S(lpm_state, pfx) (lpm_state[pfx].start)
   1099 #define SOC_LPM_STATE_E(lpm_state, pfx) (lpm_state[pfx].end)
   1100 #define SOC_LPM_STATE_P(lpm_state, pfx) (lpm_state[pfx].prev)
   1101 #define SOC_LPM_STATE_N(lpm_state, pfx) (lpm_state[pfx].next)
   1102 #define SOC_LPM_STATE_V(lpm_state, pfx) (lpm_state[pfx].vent)
   1103 #define SOC_LPM_STATE_F(lpm_state, pfx) (lpm_state[pfx].fent)
   1104 
   1105 #define LPM128_TCAM_NUM(u, i)       ((i) / SOC_L3_DEFIP_TCAM_DEPTH_GET(u))
   1106 #define LPM128_IN_ODD_TCAM(u, i)    (LPM128_TCAM_NUM(u, i) & 1)
   1107 #define LPM128_IN_EVEN_TCAM(u, i)   (!LPM128_IN_ODD_TCAM(u, i))
   1108 #define LPM128_IN_ODD_TCAM_FIRST(u, i)  \
   1109         (LPM128_IN_ODD_TCAM(u, i) && (((i) % SOC_L3_DEFIP_TCAM_DEPTH_GET(u)) == 0))
   1110 #define LPM128_IN_EVEN_TCAM_FIRST(u, i)  \
   1111         (LPM128_IN_EVEN_TCAM(u, i) && (((i) % SOC_L3_DEFIP_TCAM_DEPTH_GET(u)) == 0))
   1112 
   1113 
   1114 #ifdef FB_LPM_DEBUG      
   1115 #define H_INDEX_MATCH(str, tab_index, match_index)      \
   1116     LOG_INFO(BSL_LS_SOC_LPM, \
   1117               (BSL_META("%s index: H %d A %d\n"),                  \
   1118                str, (int)tab_index, match_index))
   1119 int *dbg_soc_lpm128_index_to_pfx_group[SOC_MAX_NUM_DEVICES];
   1120 soc_lpm128_state_p dbg_soc_lpm128_state[SOC_MAX_NUM_DEVICES];
   1121 soc_lpm128_state_p dbg_soc_lpm128_unreserved_state[SOC_MAX_NUM_DEVICES];
   1122 defip_entry_t *dbg_l3_defip[SOC_MAX_NUM_DEVICES];
   1123 static _soc_fb_lpm_hash_t *_dbg_fb_lpm_hash_tab[SOC_MAX_NUM_DEVICES];
   1124 static _soc_fb_lpm_hash_t *_dbg_fb_lpm128_hash_tab[SOC_MAX_NUM_DEVICES];
   1125 soc_lpm_state_p dbg_soc_lpm_state[SOC_MAX_NUM_DEVICES];
   1126 
   1127 #define DBG_SOC_LPM128_STATE(u)             \
   1128         (dbg_soc_lpm128_state[(u)])
   1129 #define DBG_SOC_LPM128_UNRESERVED_STATE(u)  \
   1130         (dbg_soc_lpm128_unreserved_state[(u)])
   1131 #define DBG_SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u) \
   1132         dbg_soc_lpm128_index_to_pfx_group[(u)]
   1133 #define DBG_SOC_LPM128_INDEX_TO_PFX_GROUP(u, index)\
   1134         dbg_soc_lpm128_index_to_pfx_group[(u)][(index)]
   1135 #define DBG_SOC_L3_DEFIP(u)\
   1136         dbg_l3_defip[(u)]
   1137 #define DBG_SOC_LPM_STATE_HASH(u)           (_dbg_fb_lpm_hash_tab[(u)])
   1138 #define DBG_SOC_LPM128_STATE_HASH(u)        (_dbg_fb_lpm128_hash_tab[(u)])
   1139 #define DBG_SOC_LPM_STATE(u)                (dbg_soc_lpm_state[(u)])
   1140 
   1141 int *dbg_soc_lpm128_index_to_pfx_group2[SOC_MAX_NUM_DEVICES];
   1142 soc_lpm128_state_p dbg_soc_lpm128_state2[SOC_MAX_NUM_DEVICES];
   1143 soc_lpm128_state_p dbg_soc_lpm128_unreserved_state2[SOC_MAX_NUM_DEVICES];
   1144 static _soc_fb_lpm_hash_t *_dbg_fb_lpm_hash_tab2[SOC_MAX_NUM_DEVICES];
   1145 static _soc_fb_lpm_hash_t *_dbg_fb_lpm128_hash_tab2[SOC_MAX_NUM_DEVICES];
   1146 soc_lpm_state_p dbg_soc_lpm_state2[SOC_MAX_NUM_DEVICES];
   1147 int *dbg_soc_lpm_hash_tmp[SOC_MAX_NUM_DEVICES];
   1148 
   1149 #define DBG_SOC_LPM128_STATE2(u)             \
   1150         (dbg_soc_lpm128_state2[(u)])
   1151 #define DBG_SOC_LPM128_UNRESERVED_STATE2(u)  \
   1152         (dbg_soc_lpm128_unreserved_state2[(u)])
   1153 #define DBG_SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE2(u) \
   1154         dbg_soc_lpm128_index_to_pfx_group2[(u)]
   1155 #define DBG_SOC_LPM128_INDEX_TO_PFX_GROUP2(u, index)\
   1156         dbg_soc_lpm128_index_to_pfx_group2[(u)][(index)]
   1157 #define DBG_SOC_LPM_STATE_HASH2(u)           (_dbg_fb_lpm_hash_tab2[(u)])
   1158 #define DBG_SOC_LPM128_STATE_HASH2(u)        (_dbg_fb_lpm128_hash_tab2[(u)])
   1159 #define DBG_SOC_LPM_STATE2(u)                (dbg_soc_lpm_state2[(u)])
   1160 
   1161 #define LPM_TBL_SIZE 16384
   1162 #define DBG_SOC_LPM_HASH_TMP(u)          (dbg_soc_lpm_hash_tmp[(u)])
   1163 #define DBG_SOC_LPM_HASH_TMP_A(u)        (&dbg_soc_lpm_hash_tmp[(u)][0])
   1164 #define DBG_SOC_LPM_HASH_TMP_B(u)        (&dbg_soc_lpm_hash_tmp[(u)][LPM_TBL_SIZE])
   1165 
   1166 #define LPM_HASH_INSERT2(u, entry_data, tab_index, rvt_index0, rvt_index1)   \
   1167     soc_fb_lpm_hash_insert2(u, entry_data, tab_index, LPM_NO_MATCH_INDEX, 0, \
   1168                            rvt_index0, rvt_index1)
   1169 
   1170 void soc_fb_lpm_hash_insert2(int u, void *entry_data, uint32 tab_index,
   1171                             uint32 old_index, int pfx,
   1172                             uint32 *rvt_index0, uint32 *rvt_index1)
   1173 {
   1174     _soc_fb_lpm_hash_entry_t    key_hash;
   1175     soc_mem_t mem = L3_DEFIPm;
   1176     int ipv6 = 0;
   1177 
   1178 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1179     if (SOC_MEM_IS_VALID(u, L3_DEFIP_LEVEL1m)) {
   1180         mem = L3_DEFIP_LEVEL1m;
   1181         uint32 _key_data[2] = {0, 0};
   1182         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, KEY0f, _key_data);
   1183         ipv6 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_TYPEf);
   1184     } else
   1185 #endif
   1186     {
   1187         ipv6 = SOC_MEM_OPT_F32_GET(u, mem, entry_data, defip_mode0_field);
   1188     }
   1189 
   1190     if (ipv6) {
   1191         /* IPV6 entry */
   1192         if (SOC_MEM_OPT_F32_VALID1_GET(u, mem, entry_data) &&
   1193             SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data)) {
   1194 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1195             if (SOC_MEM_IS_VALID(u, L3_DEFIP_LEVEL1m)) {
   1196                 SOC_TH3_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, key_hash);
   1197             } else
   1198 #endif
   1199             {
   1200                 SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, key_hash);
   1201             }
   1202             _soc_fb_lpm_hash_insert(
   1203                         DBG_SOC_LPM_STATE_HASH2(u),
   1204                         _soc_fb_lpm_hash_compare_key,
   1205                         key_hash,
   1206                         pfx,
   1207                         old_index,
   1208                         (tab_index << 1) | FB_LPM_HASH_IPV6_MASK,
   1209                         rvt_index0);
   1210         }
   1211     } else {
   1212         /* IPV4 entry */
   1213         if (SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data)) {
   1214             SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, key_hash);
   1215             _soc_fb_lpm_hash_insert(DBG_SOC_LPM_STATE_HASH2(u),
   1216                                     _soc_fb_lpm_hash_compare_key,
   1217                                     key_hash,
   1218                                     pfx,
   1219                                     old_index,
   1220                                     (tab_index << 1),
   1221                                     rvt_index0);
   1222         }
   1223         if (SOC_MEM_OPT_F32_VALID1_GET(u, mem, entry_data)) {
   1224             SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, key_hash);
   1225             _soc_fb_lpm_hash_insert(DBG_SOC_LPM_STATE_HASH2(u),
   1226                                     _soc_fb_lpm_hash_compare_key,
   1227                                     key_hash,
   1228                                     pfx,
   1229                                     old_index,
   1230                                     ((tab_index << 1) + 1),
   1231                                     rvt_index1);
   1232         }
   1233     }
   1234 }
   1235 
   1236 
   1237 /* The symptom is sw still has the index, but the correspoinding entry 
   1238  * in hw is empty. So let's add an instrument that when doing a 
   1239  * mem write, and when the to be written entry is empty, then its index
   1240  * should be deleted from sw. 
   1241  */
   1242 static
   1243 int _soc_fb_lpm_hash_verify(_soc_fb_lpm_hash_t *hash,
   1244                             uint32 new_index, int valid);
   1245 void soc_fb_lpm_hash_verify(int u, void *entry_data, uint32 tab_index)
   1246 {
   1247     int valid = 0;
   1248     _soc_fb_lpm_hash_t *hash = SOC_LPM128_STATE_HASH(u); 
   1249 
   1250     soc_mem_t mem = L3_DEFIPm;
   1251     int ipv6 = 0;
   1252     int mode = 0;
   1253 
   1254 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1255     if (SOC_MEM_IS_VALID(u, L3_DEFIP_LEVEL1m)) {
   1256         mem = L3_DEFIP_LEVEL1m;
   1257         uint32 _key_data[2] = {0, 0};
   1258         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, KEY0f, _key_data);
   1259         ipv6 = mode = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf);
   1260     } else
   1261 #endif
   1262     {
   1263         mode = ipv6 = SOC_MEM_OPT_F32_GET(u, mem, entry_data, defip_mode0_field);
   1264     }
   1265 
   1266     if (tab_index >= SOC_LPM_STATE_START(u, MAX_PFX_INDEX(u))) {
   1267         hash = SOC_LPM_STATE_HASH(u);
   1268     }
   1269 
   1270     if (ipv6)) {
   1271         /* IPV6 entry */
   1272         valid = (SOC_MEM_OPT_F32_VALID1_GET(u, mem, entry_data) &&
   1273                  SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data));
   1274 
   1275         if (mode == 3) &&
   1276             LPM128_IN_ODD_TCAM(u, tab_index)) {
   1277             tab_index -= SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   1278 
   1279             /* Corner case for transient address */
   1280             valid = SOC_MEM_OPT_F32_GET(u, mem, entry_data, VALID1f);
   1281         }
   1282         _soc_fb_lpm_hash_verify( hash,
   1283                     (tab_index << 1) | FB_LPM_HASH_IPV6_MASK, valid);
   1284     } else {
   1285         /* IPV4 entry */
   1286         valid = SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data);
   1287         _soc_fb_lpm_hash_verify(hash, (tab_index << 1), valid);
   1288 
   1289         valid = SOC_MEM_OPT_F32_VALID1_GET(u, mem, entry_data);
   1290         _soc_fb_lpm_hash_verify(hash, ((tab_index << 1) + 1), valid);
   1291     }
   1292 }
   1293 
   1294 
   1295 extern void
   1296 lpm128_state_dump(int u, int before);
   1297 
   1298 extern void
   1299 lpm128_idx_to_pfx_dump(int u, int before);
   1300 STATIC INLINE void
   1301 _soc_fb_lpm_state_dump(int u, soc_lpm_state_p lpm_state_ptr);
   1302 extern void
   1303 lpm_hash_dump(int u, int before, int step, uint32 usec);
   1304 extern void
   1305 lpm128_hash_dump(int u, int before, int step, uint32 usec);
   1306 extern void
   1307 lpm_count_dump(int u, int before);
   1308 extern int
   1309 dbg_soc_fb_lpm_reinit_done(int unit, int ipv6);
   1310 extern int
   1311 dbg_soc_fb_lpm_reinit(int unit, int idx, uint32 *lpm_entry);
   1312 extern int
   1313 dbg_soc_fb_lpm128_reinit_done(int unit, int ipv6);
   1314 extern int
   1315 dbg_soc_fb_lpm128_reinit(int u, int idx, uint32 *lpm_entry,
   1316                      uint32 *lpm_entry_upr);
   1317 extern STATIC INLINE int
   1318 _soc_fb_lpm_state_cmp(int u, soc_lpm_state_p lpm_state_ptr,
   1319                              soc_lpm_state_p lpm_state_ptr2);
   1320 
   1321 extern int sh_process_command(int u,char * c);
   1322 
   1323 #undef WRITE_L3_DEFIPm
   1324 #define WRITE_L3_DEFIPm debug_write_l3_defip
   1325 
   1326 void
   1327 debug_dump_l3_defip(int u, int index)
   1328 {
   1329     soc_mem_entry_dump_if_changed(u, L3_DEFIPm, 
   1330                                   &(DBG_SOC_L3_DEFIP(u)[index]), "LPM");
   1331 }
   1332 
   1333 int 
   1334 debug_write_l3_defip(int u, int copyno, int index, void *entry_data)
   1335 {
   1336     int rv;
   1337     uint32          data0[20] = {0};
   1338     uint32          data1[20] = {0};    
   1339     uint32      read[SOC_MAX_MEM_FIELD_WORDS] = {0};
   1340     int i = 0, j = 0;
   1341     int offset = (soc_mem_index_count(u, mem) >> 1);
   1342     soc_mem_t mem = L3_DEFIPm;
   1343 
   1344     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   1345         mem = L3_DEFIP_LEVEL1m;
   1346     }
   1347 
   1348     rv = soc_mem_read(u, mem, copyno, index, entry_data);
   1349     /* As long as the target entry is empty or half empty, 
   1350      * trigger a sanity check to the sw hash. The idea is 
   1351      * the empty entry should not be resided in the sw hash, because 
   1352      * the sw hash is always updated prior to hw change, whateve the operation
   1353      * is add or delete or replace.
   1354      */
   1355     if(SOC_URPF_STATUS_GET(u)) {
   1356         if (soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   1357             return (SOC_E_NONE);
   1358         } else {
   1359             if (index >= offset) {
   1360                 soc_fb_lpm_hash_verify(u, entry_data, index - offset);
   1361             } else {
   1362                 soc_fb_lpm_hash_verify(u, entry_data, index);
   1363             }
   1364         }
   1365     } else {
   1366         soc_fb_lpm_hash_verify(u, entry_data, index);
   1367     }
   1368     rv = soc_mem_write(u, mem, copyno, index, entry_data);
   1369     if (rv < 0) {
   1370         LOG_CLI(("L3 Defip write error \n"));
   1371     }
   1372     sal_memcpy(&(DBG_SOC_L3_DEFIP(u)[index]), entry_data, sizeof(uint32)*SOC_MAX_MEM_WORDS);
   1373     rv = soc_mem_read(u, mem, copyno, index, read);
   1374     if (rv < 0) {
   1375         LOG_CLI(("L3 Defip read error \n"));
   1376     }
   1377     data0[i++] = SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data);
   1378     data0[i++] = soc_mem_field32_get(u, mem, entry_data, MODE0f);
   1379     data0[i++] = soc_mem_field32_get(u, mem, entry_data, IP_ADDR0f);
   1380     data0[i++] = soc_mem_field32_get(u, mem, entry_data, IP_ADDR_MASK0f);
   1381     data0[i++] = soc_mem_field32_get(u, mem, entry_data, VRF_ID_0f);
   1382     data0[i++] = soc_mem_field32_get(u, mem, entry_data, VALID1f);
   1383     data0[i++] = soc_mem_field32_get(u, mem, entry_data, MODE1f);
   1384     data0[i++] = soc_mem_field32_get(u, mem, entry_data, IP_ADDR1f);
   1385     data0[i++] = soc_mem_field32_get(u, mem, entry_data, IP_ADDR_MASK1f);
   1386     data0[i++] = soc_mem_field32_get(u, mem, entry_data, VRF_ID_1f);
   1387 
   1388 
   1389     data1[j++] = SOC_MEM_OPT_F32_VALID0_GET(u, mem, read);
   1390     data1[j++] = soc_mem_field32_get(u, mem, read, MODE0f);
   1391     data1[j++] = soc_mem_field32_get(u, mem, read, IP_ADDR0f);
   1392     data1[j++] = soc_mem_field32_get(u, mem, read, IP_ADDR_MASK0f);
   1393     data1[j++] = soc_mem_field32_get(u, mem, read, VRF_ID_0f);
   1394     data1[j++] = soc_mem_field32_get(u, mem, read, VALID1f);
   1395     data1[j++] = soc_mem_field32_get(u, mem, read, MODE1f);
   1396     data1[j++] = soc_mem_field32_get(u, mem, read, IP_ADDR1f);
   1397     data1[j++] = soc_mem_field32_get(u, mem, read, IP_ADDR_MASK1f);
   1398     data1[j++] = soc_mem_field32_get(u, mem, read, VRF_ID_1f);
   1399    
   1400     if (sal_memcmp(data0, data1, sizeof(data0))) {
   1401         LOG_CLI(("Low level write error \n"));
   1402     }
   1403     return rv;
   1404 }
   1405 
   1406 #undef READ_L3_DEFIPm
   1407 #define READ_L3_DEFIPm debug_read_l3_defip
   1408 
   1409 static void
   1410 soc_fb_lpm_debug_collect(uint32 u);
   1411 
   1412 int 
   1413 debug_read_l3_defip(int u, int copyno, int index, void *entry_data)
   1414 {
   1415     int rv;
   1416     uint32          data0[20] = {0};
   1417     uint32          data1[20] = {0};    
   1418     int i = 0, j = 0;
   1419     soc_mem_t mem = L3_DEFIPm;
   1420 
   1421     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   1422         mem = L3_DEFIP_LEVEL1m;
   1423     }
   1424 
   1425     rv = soc_mem_read(u, mem, copyno, index, entry_data);
   1426     if (rv < 0) {
   1427         LOG_CLI(("L3 Defip read  error \n"));
   1428     }
   1429     data0[i++] = SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data);
   1430     data0[i++] = soc_mem_field32_get(u, mem, entry_data, MODE0f);
   1431     data0[i++] = soc_mem_field32_get(u, mem, entry_data, IP_ADDR0f);
   1432     data0[i++] = soc_mem_field32_get(u, mem, entry_data, IP_ADDR_MASK0f);
   1433     data0[i++] = soc_mem_field32_get(u, mem, entry_data, VRF_ID_0f);
   1434     data0[i++] = soc_mem_field32_get(u, mem, entry_data, VALID1f);
   1435     data0[i++] = soc_mem_field32_get(u, mem, entry_data, MODE1f);
   1436     data0[i++] = soc_mem_field32_get(u, mem, entry_data, IP_ADDR1f);
   1437     data0[i++] = soc_mem_field32_get(u, mem, entry_data, IP_ADDR_MASK1f);
   1438     data0[i++] = soc_mem_field32_get(u, mem, entry_data, VRF_ID_1f);
   1439 
   1440 
   1441     data1[j++] = SOC_MEM_OPT_F32_VALID0_GET(u, mem, &(DBG_SOC_L3_DEFIP(u)[index]));
   1442     data1[j++] = soc_mem_field32_get(u, mem, &(DBG_SOC_L3_DEFIP(u)[index]), MODE0f);
   1443     data1[j++] = soc_mem_field32_get(u, mem, &(DBG_SOC_L3_DEFIP(u)[index]), IP_ADDR0f);
   1444     data1[j++] = soc_mem_field32_get(u, mem, &(DBG_SOC_L3_DEFIP(u)[index]), IP_ADDR_MASK0f);
   1445     data1[j++] = soc_mem_field32_get(u, mem, &(DBG_SOC_L3_DEFIP(u)[index]), VRF_ID_0f);
   1446     data1[j++] = soc_mem_field32_get(u, mem, &(DBG_SOC_L3_DEFIP(u)[index]), VALID1f);
   1447     data1[j++] = soc_mem_field32_get(u, mem, &(DBG_SOC_L3_DEFIP(u)[index]), MODE1f);
   1448     data1[j++] = soc_mem_field32_get(u, mem, &(DBG_SOC_L3_DEFIP(u)[index]), IP_ADDR1f);
   1449     data1[j++] = soc_mem_field32_get(u, mem, &(DBG_SOC_L3_DEFIP(u)[index]), IP_ADDR_MASK1f);
   1450     data1[j++] = soc_mem_field32_get(u, mem, &(DBG_SOC_L3_DEFIP(u)[index]), VRF_ID_1f);
   1451 
   1452     if (sal_memcmp(data0, data1, sizeof(data0))) {
   1453         soc_mem_entry_dump(u, L3_DEFIPm, entry_data, BSL_LSS_CLI);
   1454         soc_mem_entry_dump(u, L3_DEFIPm, &(DBG_SOC_L3_DEFIP(u)[index]), BSL_LSS_CLI);
   1455         soc_fb_lpm_debug_collect(u);
   1456         LOG_CLI(("Low level read error \n"));
   1457     }
   1458     return rv;
   1459 }
   1460 
   1461 static void
   1462 soc_fb_lpm_hash_sanity(uint32 u, int print, int *err_count)
   1463 {
   1464 
   1465     uint32 min, idx, i, j;
   1466     _soc_fb_lpm_hash_t  *hash[2];
   1467     int *tmp[2];
   1468     tmp[0] = DBG_SOC_LPM_HASH_TMP_A(u);
   1469     tmp[1] = DBG_SOC_LPM_HASH_TMP_B(u);
   1470     int unmatch = 0;
   1471 
   1472     /* Traverse the table, for each head, traverse the link list.
   1473      * Pick the smallest one as the head.
   1474      * Record the head to each member.
   1475      * In the end, the final arrawy will record all the valid index
   1476      * For those indexes with same hash result, they share same head.
   1477      * Generate two arrays 
   1478      */
   1479 
   1480     sal_memset(DBG_SOC_LPM_HASH_TMP(u), -1, 2 * LPM_TBL_SIZE * sizeof(int));
   1481     hash[0] = DBG_SOC_LPM_STATE_HASH2(u);
   1482     hash[1] = SOC_LPM_STATE_HASH(u);
   1483 
   1484     for (i = 0; i < _fb_lpm_hash_tab[u]->index_count; i++) {
   1485         for (j = 0; j < 2; j++) {
   1486             if (hash[j]->table[i] != FB_LPM_HASH_INDEX_NULL) {
   1487                 min = idx = hash[j]->table[i];
   1488                 while (idx != FB_LPM_HASH_INDEX_NULL) {
   1489                     if (idx < min) {
   1490                         min = idx;
   1491                     }
   1492                     idx = hash[j]->link_table[idx & fb_lpm_hash_index_mask[u]];
   1493                 }
   1494                 idx = hash[j]->table[i];
   1495                 while (idx != FB_LPM_HASH_INDEX_NULL) {
   1496                     if (tmp[j][idx & fb_lpm_hash_index_mask[u]] != -1) {
   1497                         if (print) {
   1498                             LOG_CLI(("duplicate idx %d\n", idx));
   1499                         }
   1500                         if (err_count) {
   1501                             (*err_count) ++;
   1502                         }
   1503                     }
   1504                     tmp[j][idx & fb_lpm_hash_index_mask[u]] = min;
   1505                     idx = hash[j]->link_table[idx & fb_lpm_hash_index_mask[u]];
   1506                 }
   1507             }
   1508         }
   1509     }
   1510 
   1511     for (i = 0; i < LPM_TBL_SIZE; i++) {
   1512         if (tmp[0][i] != tmp[1][i]) {
   1513             unmatch = 1;
   1514             if (print) {
   1515                 LOG_CLI(("  LPM hash %d: %d != %d \n", i, tmp[0][i], tmp[1][i]));
   1516             }
   1517         }
   1518     }
   1519     if (unmatch == 0) {
   1520         if (print) {
   1521             LOG_CLI(("  LPM hash table compare pass \n"));
   1522         }
   1523     } else {
   1524         if (print) {
   1525             LOG_CLI(("  LPM hash table compare error \n"));
   1526         }
   1527         if (err_count) {
   1528             (*err_count) ++;
   1529         }
   1530     }
   1531 
   1532     /* LPM 128 starts here */
   1533 
   1534     sal_memset(DBG_SOC_LPM_HASH_TMP(u), -1, 2 * LPM_TBL_SIZE * sizeof(int));
   1535     hash[0] = DBG_SOC_LPM128_STATE_HASH2(u);
   1536     hash[1] = SOC_LPM128_STATE_HASH(u);
   1537 
   1538     for (i = 0; i < _fb_lpm_hash_tab[u]->index_count; i++) {
   1539         for (j = 0; j < 2; j++) {
   1540             if (hash[j]->table[i] != FB_LPM_HASH_INDEX_NULL) {
   1541                 min = idx = hash[j]->table[i];
   1542                 while (idx != FB_LPM_HASH_INDEX_NULL) {
   1543                     if (idx < min) {
   1544                         min = idx;
   1545                     }
   1546                     idx = hash[j]->link_table[idx & FB_LPM_HASH_INDEX_MASK];
   1547                 }
   1548                 idx = hash[j]->table[i];
   1549                 while (idx != FB_LPM_HASH_INDEX_NULL) {
   1550                     if (tmp[j][idx & FB_LPM_HASH_INDEX_MASK] != -1) {
   1551                         if (print) {
   1552                             LOG_CLI(("duplicate idx %d\n", idx));
   1553                         }
   1554                         if (err_count) {
   1555                             (*err_count) ++;
   1556                         }
   1557                     }
   1558                     tmp[j][idx & FB_LPM_HASH_INDEX_MASK] = min;
   1559                     idx = hash[j]->link_table[idx & FB_LPM_HASH_INDEX_MASK];
   1560                 }
   1561             }
   1562         }
   1563     }
   1564 
   1565     unmatch = 0;
   1566     for (i = 0; i < LPM_TBL_SIZE; i++) {
   1567         if (tmp[0][i] != tmp[1][i]) {
   1568             unmatch = 1;
   1569             if (print) {
   1570                 LOG_CLI(("  LPM 128 hash %d: %d != %d \n", i, tmp[0][i], tmp[1][i]));
   1571             }
   1572         }
   1573     }
   1574     if (unmatch == 0) {
   1575         if (print) {
   1576             LOG_CLI(("  LPM 128 hash table compare pass \n"));
   1577         }
   1578     } else {
   1579         if (print) {
   1580             LOG_CLI(("  LPM 128 hash table compare error \n"));
   1581         }
   1582         if (err_count) {
   1583             (*err_count) ++;
   1584         }
   1585     }
   1586 }
   1587 
   1588 
   1589 static void 
   1590 soc_fb_lpm_debug_parse(uint32 u, int print, int *err_count)
   1591 {
   1592     int i, defip_size, paired_size;
   1593     int rv;
   1594     soc_lpm128_state_p lpm_state_ptr = NULL;
   1595     int pfx_state_size = sizeof(soc_lpm128_state_t) * (MAX_PFX128_ENTRIES);
   1596 /*    int pfx_state_size2 = sizeof(soc_lpm_state_t) * (MAX_PFX_ENTRIES(u));*/
   1597     soc_mem_t mem = L3_DEFIPm;
   1598 
   1599     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   1600         mem = L3_DEFIP_LEVEL1m;
   1601     }
   1602 
   1603 
   1604     /* Parse the l3_defip table to table & link_table. And then compare */
   1605     /* Reset all parsed data */
   1606     /* Reset 1 lpmstate */
   1607 
   1608     soc_fb_lpm_table_sizes_get(u, &paired_size, &defip_size);
   1609 
   1610     for(i = 0; i < MAX_PFX_ENTRIES(u); i++) {
   1611         SOC_LPM_STATE_S(DBG_SOC_LPM_STATE2(u), i) = -1;
   1612         SOC_LPM_STATE_E(DBG_SOC_LPM_STATE2(u), i) = -1;
   1613         SOC_LPM_STATE_P(DBG_SOC_LPM_STATE2(u), i) = -1;
   1614         SOC_LPM_STATE_N(DBG_SOC_LPM_STATE2(u), i) = -1;
   1615         SOC_LPM_STATE_V(DBG_SOC_LPM_STATE2(u), i) = 0;
   1616         SOC_LPM_STATE_F(DBG_SOC_LPM_STATE2(u), i) = 0;
   1617     }    
   1618     SOC_LPM_STATE_F(DBG_SOC_LPM_STATE2(u), MAX_PFX_INDEX(u)) = defip_size;
   1619     SOC_LPM_STATE_S(DBG_SOC_LPM_STATE2(u), MAX_PFX_INDEX(u)) = paired_size;
   1620     SOC_LPM_STATE_E(DBG_SOC_LPM_STATE2(u), MAX_PFX_INDEX(u)) = paired_size - 1;
   1621 
   1622 
   1623     /* Reset 2 lpm128 state ( Reserved case TBD) */
   1624     lpm_state_ptr = DBG_SOC_LPM128_STATE2(u);
   1625     for(i = 0; i < MAX_PFX128_ENTRIES; i++) {
   1626         SOC_LPM128_STATE_START1(u, lpm_state_ptr, i) = -1;
   1627         SOC_LPM128_STATE_START2(u, lpm_state_ptr, i) = -1;
   1628         SOC_LPM128_STATE_END1(u, lpm_state_ptr, i) = -1;
   1629         SOC_LPM128_STATE_END2(u, lpm_state_ptr, i) = -1;
   1630         SOC_LPM128_STATE_PREV(u, lpm_state_ptr, i) = -1;
   1631         SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, i) = -1;
   1632         SOC_LPM128_STATE_VENT(u, lpm_state_ptr, i) = 0;
   1633         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, i) = 0;
   1634     }
   1635     if (soc_feature(u, soc_feature_l3_lpm_128b_entries_reserved)) {
   1636         int num_ipv6_128b_entries =  SOC_L3_DEFIP_MAX_128B_ENTRIES(u);
   1637         if (SOC_URPF_STATUS_GET(u) &&
   1638             !soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   1639             num_ipv6_128b_entries >>= 1;
   1640         }
   1641         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, (MAX_PFX128_INDEX)) =
   1642                               2 * num_ipv6_128b_entries;
   1643     } else {
   1644         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, (MAX_PFX128_INDEX)) =
   1645                               paired_size;
   1646     }
   1647 
   1648     /* reset 3 lpm128 hash*/
   1649     for(i = 0; i < DBG_SOC_LPM128_STATE_HASH2(u)->index_count; i++) {
   1650         DBG_SOC_LPM128_STATE_HASH2(u)->table[i] = FB_LPM_HASH_INDEX_NULL;
   1651     }
   1652     for(i = 0; i < DBG_SOC_LPM128_STATE_HASH2(u)->entry_count; i++) {
   1653         DBG_SOC_LPM128_STATE_HASH2(u)->link_table[i] = FB_LPM_HASH_INDEX_NULL;
   1654         DBG_SOC_LPM128_STATE_HASH2(u)->check_table[i] = 0;
   1655     }    
   1656 
   1657     /* reset 4 lpm hash*/
   1658     for(i = 0; i < DBG_SOC_LPM_STATE_HASH2(u)->index_count; i++) {
   1659         DBG_SOC_LPM_STATE_HASH2(u)->table[i] = FB_LPM_HASH_INDEX_NULL;
   1660     }
   1661     for(i = 0; i < DBG_SOC_LPM_STATE_HASH2(u)->entry_count; i++) {
   1662         DBG_SOC_LPM_STATE_HASH2(u)->link_table[i] = FB_LPM_HASH_INDEX_NULL;
   1663         DBG_SOC_LPM_STATE_HASH2(u)->check_table[i] = 0;
   1664     }    
   1665 
   1666     /* reset 5 lpm/lpm128 count*/
   1667     SOC_LPM128_STAT_128BV6_COUNT2(u)          =  0;
   1668     SOC_LPM128_STAT_V4_COUNT2(u)              =  0;
   1669     SOC_LPM128_STAT_64BV6_COUNT2(u)           =  0;
   1670     SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT2(u)   =  0;
   1671     SOC_LPM_V4_COUNT2(u)                      =  0;
   1672     SOC_LPM_64BV6_COUNT2(u)                   =  0;
   1673     SOC_LPM_V4_HALF_ENTRY_COUNT2(u)           =  0;
   1674 
   1675     /* reset 6 idx 2 group */
   1676     sal_memset(DBG_SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE2(u), -1,
   1677                defip_size * sizeof(int));
   1678 
   1679     for (i = 0; i < paired_size; i++) {
   1680 
   1681         /* Make sure entry is valid. */
   1682         if (!SOC_MEM_OPT_F32_VALID0_GET(u, mem, &(DBG_SOC_L3_DEFIP(u)[i])) &&
   1683             !SOC_MEM_OPT_F32_VALID1_GET(u, mem, &(DBG_SOC_L3_DEFIP(u)[i]))) {
   1684             continue;
   1685         }
   1686 
   1687         if (soc_L3_DEFIPm_field32_get(u, &(DBG_SOC_L3_DEFIP(u)[i]), MODE0f) == 3) {
   1688             if (LPM128_IN_ODD_TCAM(u, i)) {
   1689                 continue;
   1690             }
   1691             if (soc_L3_DEFIPm_field32_get(u, &(DBG_SOC_L3_DEFIP(u)[i]), MODE1f) != 3 ||
   1692                 soc_L3_DEFIPm_field32_get(u, &(DBG_SOC_L3_DEFIP(u)[i+1024]), MODE0f) != 3 ||
   1693                 soc_L3_DEFIPm_field32_get(u, &(DBG_SOC_L3_DEFIP(u)[i+1024]), MODE1f) != 3) {
   1694                 assert(0);
   1695             }
   1696             rv = dbg_soc_fb_lpm128_reinit(u, i, &(DBG_SOC_L3_DEFIP(u)[i]), &(DBG_SOC_L3_DEFIP(u)[i+1024]));
   1697             assert(rv == 0);
   1698         } else {
   1699             rv = dbg_soc_fb_lpm128_reinit(u, i, &(DBG_SOC_L3_DEFIP(u)[i]), NULL);
   1700             assert(rv == 0);
   1701         }
   1702     }
   1703 
   1704     for (i = paired_size; i < soc_mem_index_count(u, L3_DEFIPm); i++) {
   1705         /* Make sure entry is valid. */
   1706         if (!SOC_MEM_OPT_F32_VALID0_GET(u, mem, &(DBG_SOC_L3_DEFIP(u)[i])) &&
   1707             !SOC_MEM_OPT_F32_VALID1_GET(u, mem, &(DBG_SOC_L3_DEFIP(u)[i]))) {
   1708             continue;
   1709         }
   1710 
   1711         rv = dbg_soc_fb_lpm_reinit(u, i, &(DBG_SOC_L3_DEFIP(u)[i]));
   1712         assert(rv == 0);
   1713     }
   1714     
   1715     dbg_soc_fb_lpm128_reinit_done(u, 1);
   1716     dbg_soc_fb_lpm_reinit_done(u, 0);
   1717     dbg_soc_fb_lpm_reinit_done(u, 1);
   1718 
   1719     if (SOC_LPM_STATE(u)) {
   1720         if (_soc_fb_lpm_state_cmp(u, SOC_LPM_STATE(u), DBG_SOC_LPM_STATE2(u))) {
   1721             LOG_ERROR(BSL_LS_SOC_LPM,
   1722                       (BSL_META_U(u,
   1723                                   "  LPM state compare error \n")));
   1724             if (err_count) {
   1725                 (*err_count)++;
   1726             }
   1727         }
   1728     }
   1729 
   1730     if (SOC_LPM128_STATE(u)) {
   1731         if (sal_memcmp(SOC_LPM128_STATE(u),
   1732                    DBG_SOC_LPM128_STATE2(u),
   1733                    pfx_state_size)) {
   1734             LOG_ERROR(BSL_LS_SOC_LPM,
   1735                       (BSL_META_U(u,
   1736                                   "  LPM128 state compare error \n")));
   1737             if (err_count) {
   1738                 (*err_count)++;
   1739             }
   1740         }
   1741     }
   1742 
   1743     if (SOC_LPM128_UNRESERVED_STATE(u)) {
   1744         if (sal_memcmp(SOC_LPM128_UNRESERVED_STATE(u),
   1745                    DBG_SOC_LPM128_UNRESERVED_STATE2(u),
   1746                    pfx_state_size)) {
   1747             LOG_ERROR(BSL_LS_SOC_LPM,
   1748                       (BSL_META_U(u,
   1749                                   "  LPM128 unres state compare error \n")));
   1750         }
   1751     } 
   1752 
   1753     if (SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u)) {
   1754         if (sal_memcmp(SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u),
   1755                    DBG_SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE2(u),
   1756                    (paired_size * sizeof(int)))) {
   1757             LOG_ERROR(BSL_LS_SOC_LPM,
   1758                       (BSL_META_U(u,
   1759                                   "  LPM128 idx 2 pfx compare error \n")));
   1760             if (err_count) {
   1761                 (*err_count)++;
   1762             }
   1763         }
   1764     }
   1765 
   1766     if (SOC_LPM128_STAT_128BV6_COUNT2(u) != SOC_LPM128_STAT_128BV6_COUNT(u) ||
   1767         SOC_LPM128_STAT_V4_COUNT2(u) != SOC_LPM128_STAT_V4_COUNT(u) ||
   1768         SOC_LPM128_STAT_64BV6_COUNT2(u) != SOC_LPM128_STAT_64BV6_COUNT(u) ||
   1769         SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT2(u) != SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u) ||
   1770         SOC_LPM_V4_COUNT2(u) != SOC_LPM_V4_COUNT(u) ||
   1771         SOC_LPM_64BV6_COUNT2(u) != SOC_LPM_64BV6_COUNT(u) ||
   1772         SOC_LPM_V4_HALF_ENTRY_COUNT2(u) != SOC_LPM_V4_HALF_ENTRY_COUNT(u)) {
   1773 
   1774         LOG_ERROR(BSL_LS_SOC_LPM,
   1775                   (BSL_META_U(u,
   1776                               "  Count mismatch \n")));
   1777         if (err_count) {
   1778             (*err_count)++;
   1779         }
   1780     }
   1781 
   1782     if (print) {
   1783         lpm128_state_dump(u, 2);
   1784         lpm128_idx_to_pfx_dump(u, 2);
   1785         _soc_fb_lpm_state_dump(u, DBG_SOC_LPM_STATE2(u));
   1786         lpm_hash_dump(u, 2, 100, 0);
   1787         lpm128_hash_dump(u, 2, 100, 0);
   1788         lpm_count_dump(u, 2);
   1789     }
   1790 }
   1791 static void
   1792 soc_fb_lpm_debug_collect(uint32 u)
   1793 {
   1794     int err_count1 = 0, err_count2 = 0;
   1795     LOG_CLI((BSL_META_U(u, "\n==Before==\n")));
   1796     lpm128_state_dump(u, 1);
   1797     lpm128_idx_to_pfx_dump(u, 1);
   1798     _soc_fb_lpm_state_dump(u, DBG_SOC_LPM_STATE(u));
   1799     lpm_hash_dump(u, 1, 100, 0);
   1800     lpm128_hash_dump(u, 1, 100, 0);
   1801     lpm_count_dump(u, 1);
   1802 
   1803 
   1804     LOG_CLI((BSL_META_U(u, "\n==Current==\n")));
   1805     lpm128_state_dump(u, 0);
   1806     lpm128_idx_to_pfx_dump(u, 0);
   1807     _soc_fb_lpm_state_dump(u, 0);
   1808     lpm_hash_dump(u, 0, 100, 0);
   1809     lpm128_hash_dump(u, 0, 100, 0);
   1810     lpm_count_dump(u, 0);
   1811 
   1812     LOG_CLI((BSL_META_U(u, "\n==Parsed==\n")));
   1813     soc_fb_lpm_debug_parse(u, 1, &err_count1);
   1814     soc_fb_lpm_hash_sanity(u, 1, &err_count2);
   1815     LOG_CLI((" Err1 %d Err2 %d\n", err_count1, err_count2));
   1816 
   1817     if (DBG_SOC_L3_DEFIP(u)) {
   1818         int rv;
   1819         uint32          data0[20] = {0};
   1820         uint32          data1[20] = {0};    
   1821         uint32      read[SOC_MAX_MEM_FIELD_WORDS] = {0};
   1822         int i = 0, j = 0, mismatch = 0, index;
   1823 
   1824         for (index = 0; index < soc_mem_index_count(u, L3_DEFIPm); index++) {
   1825             i = j = 0;
   1826             rv = soc_mem_read(u, L3_DEFIPm, MEM_BLOCK_ANY, index, read);
   1827             if (rv < 0) {
   1828                 LOG_CLI(("L3 Defip read error %d \n", index));
   1829                 continue;
   1830             }
   1831             data0[i++] = SOC_MEM_OPT_F32_VALID0_GET(u, L3_DEFIPm, &(DBG_SOC_L3_DEFIP(u)[index]));
   1832             data0[i++] = soc_mem_field32_get(u, L3_DEFIPm, &(DBG_SOC_L3_DEFIP(u)[index]), MODE0f);
   1833             data0[i++] = soc_mem_field32_get(u, L3_DEFIPm, &(DBG_SOC_L3_DEFIP(u)[index]), IP_ADDR0f);
   1834             data0[i++] = soc_mem_field32_get(u, L3_DEFIPm, &(DBG_SOC_L3_DEFIP(u)[index]), IP_ADDR_MASK0f);
   1835             data0[i++] = soc_mem_field32_get(u, L3_DEFIPm, &(DBG_SOC_L3_DEFIP(u)[index]), VRF_ID_0f);
   1836             data0[i++] = SOC_MEM_OPT_F32_VALID1_GET(u, L3_DEFIPm, &(DBG_SOC_L3_DEFIP(u)[index]));
   1837             data0[i++] = soc_mem_field32_get(u, L3_DEFIPm, &(DBG_SOC_L3_DEFIP(u)[index]), MODE1f);
   1838             data0[i++] = soc_mem_field32_get(u, L3_DEFIPm, &(DBG_SOC_L3_DEFIP(u)[index]), IP_ADDR1f);
   1839             data0[i++] = soc_mem_field32_get(u, L3_DEFIPm, &(DBG_SOC_L3_DEFIP(u)[index]), IP_ADDR_MASK1f);
   1840             data0[i++] = soc_mem_field32_get(u, L3_DEFIPm, &(DBG_SOC_L3_DEFIP(u)[index]), VRF_ID_1f);
   1841 
   1842 
   1843             data1[j++] = SOC_MEM_OPT_F32_VALID0_GET(u, L3_DEFIPm, read);
   1844             data1[j++] = soc_mem_field32_get(u, L3_DEFIPm, read, MODE0f);
   1845             data1[j++] = soc_mem_field32_get(u, L3_DEFIPm, read, IP_ADDR0f);
   1846             data1[j++] = soc_mem_field32_get(u, L3_DEFIPm, read, IP_ADDR_MASK0f);
   1847             data1[j++] = soc_mem_field32_get(u, L3_DEFIPm, read, VRF_ID_0f);
   1848             data1[j++] = SOC_MEM_OPT_F32_VALID0_GET(u, L3_DEFIPm, read);
   1849             data1[j++] = soc_mem_field32_get(u, L3_DEFIPm, read, MODE1f);
   1850             data1[j++] = soc_mem_field32_get(u, L3_DEFIPm, read, IP_ADDR1f);
   1851             data1[j++] = soc_mem_field32_get(u, L3_DEFIPm, read, IP_ADDR_MASK1f);
   1852             data1[j++] = soc_mem_field32_get(u, L3_DEFIPm, read, VRF_ID_1f);
   1853            
   1854             if (sal_memcmp(data0, data1, sizeof(data0))) {
   1855                 mismatch = 1;
   1856                 LOG_CLI(("Defip mismatch %d \n", index));
   1857                 soc_mem_entry_dump(u, L3_DEFIPm, &(DBG_SOC_L3_DEFIP(u)[index]), BSL_LSS_CLI);
   1858             }            
   1859         }
   1860         if (!mismatch) {
   1861             LOG_CLI(("Defip all match\n"));
   1862         }
   1863     }
   1864 
   1865     LOG_CLI(("L3 defip table dump\n"));
   1866     sh_process_command(u, "d chg l3_defip");
   1867     sh_process_command(u, "ser log");
   1868     sh_process_command(u, "soc");
   1869 
   1870     /* Please collect back trace */
   1871     assert(0);
   1872 }
   1873 
   1874 static
   1875 int _soc_fb_lpm_hash_verify(_soc_fb_lpm_hash_t *hash,
   1876                             uint32 new_index,
   1877                             int valid)
   1878 {
   1879     int u = hash->unit;
   1880     int match = 0;
   1881     uint32 index = 0;
   1882 
   1883     for (index = 0; index < hash->index_count; index++) {
   1884         if (hash->table[index] != FB_LPM_HASH_INDEX_NULL) {
   1885             if (new_index == hash->table[index]) {
   1886                 match = 1;
   1887                 break;
   1888             }
   1889         }
   1890     }
   1891 
   1892     for (index = 0; (index < hash->entry_count) && !match; index++) {
   1893         if (hash->link_table[index] != FB_LPM_HASH_INDEX_NULL) {
   1894             if (new_index == hash->link_table[index]) {
   1895                 match = 1;
   1896                 break;
   1897             }
   1898         }
   1899     }
   1900 
   1901     if (match == valid) {
   1902         return(SOC_E_NONE);
   1903     }
   1904 
   1905 
   1906     LOG_ERROR(BSL_LS_SOC_LPM,
   1907               (BSL_META_U(u,
   1908                         "Verify index %d valid %d. Index %d. table %d. Link_table %d\n"),
   1909                         new_index, valid, index, hash->table[index], hash->link_table[index]));
   1910     LOG_CLI(("Fatal5\n"));
   1911 
   1912     soc_fb_lpm_debug_collect(u);
   1913     return (SOC_E_INTERNAL);    
   1914 }
   1915 
   1916 /* 0 : equal. 1: not equal */
   1917 STATIC INLINE int
   1918 _soc_fb_lpm_state_cmp(int u, soc_lpm_state_p lpm_state_ptr,
   1919                              soc_lpm_state_p lpm_state_ptr2)
   1920 {
   1921     int curr_pfx = MAX_PFX_INDEX(u);
   1922     int result = 0;
   1923     while (curr_pfx > 0) {
   1924         if (sal_memcmp(&(SOC_LPM_STATE(u)[curr_pfx]),
   1925                        &(DBG_SOC_LPM_STATE2(u)[curr_pfx]),
   1926                        sizeof(soc_lpm_state_t))) {
   1927             if (SOC_LPM_STATE_S(lpm_state_ptr2, curr_pfx) == -1 &&
   1928                 SOC_LPM_STATE_V(lpm_state_ptr, curr_pfx) == 0) {
   1929                 /* good */
   1930             } else {
   1931                 LOG_CLI(("PFX0 = %d P = %d N = %d START = %d "
   1932                          "END = %d VENT = %d FENT = %d\n",
   1933                          curr_pfx,
   1934                          SOC_LPM_STATE_P(lpm_state_ptr, curr_pfx),
   1935                          SOC_LPM_STATE_N(lpm_state_ptr, curr_pfx),
   1936                          SOC_LPM_STATE_S(lpm_state_ptr, curr_pfx),
   1937                          SOC_LPM_STATE_E(lpm_state_ptr, curr_pfx),
   1938                          SOC_LPM_STATE_V(lpm_state_ptr, curr_pfx),
   1939                          SOC_LPM_STATE_F(lpm_state_ptr, curr_pfx)));
   1940                 LOG_CLI(("PFX2 = %d P = %d N = %d START = %d "
   1941                          "END = %d VENT = %d FENT = %d\n",
   1942                          curr_pfx,
   1943                          SOC_LPM_STATE_P(lpm_state_ptr2, curr_pfx),
   1944                          SOC_LPM_STATE_N(lpm_state_ptr2, curr_pfx),
   1945                          SOC_LPM_STATE_S(lpm_state_ptr2, curr_pfx),
   1946                          SOC_LPM_STATE_E(lpm_state_ptr2, curr_pfx),
   1947                          SOC_LPM_STATE_V(lpm_state_ptr2, curr_pfx),
   1948                          SOC_LPM_STATE_F(lpm_state_ptr2, curr_pfx)));
   1949                 
   1950                 result = 1;
   1951             }
   1952               
   1953         }
   1954         curr_pfx--;
   1955     }
   1956     return result;
   1957 }
   1958 
   1959 #else
   1960 #define H_INDEX_MATCH(str, tab_index, match_index)
   1961 STATIC int
   1962 LOCAL_READ_L3_DEFIPm(int u,int blk, int index, void *data) {
   1963                   return ((SOC_MEM_IS_VALID(u, L3_DEFIPm))?
   1964                   READ_L3_DEFIPm(u, blk, index, data):
   1965                   READ_L3_DEFIP_LEVEL1m(u, blk, index, data));
   1966 }
   1967 #undef READ_L3_DEFIPm
   1968 #define READ_L3_DEFIPm LOCAL_READ_L3_DEFIPm
   1969 
   1970 STATIC int
   1971 LOCAL_WRITE_L3_DEFIPm(int u,int blk, int index, void *data) {
   1972                   return ((SOC_MEM_IS_VALID(u, L3_DEFIPm))?
   1973                   WRITE_L3_DEFIPm(u, blk, index, data):
   1974                   WRITE_L3_DEFIP_LEVEL1m(u, blk, index, data));
   1975 }
   1976 #undef WRITE_L3_DEFIPm
   1977 #define WRITE_L3_DEFIPm LOCAL_WRITE_L3_DEFIPm
   1978 #endif
   1979 
   1980 #define LPM_NO_MATCH_INDEX 0x8000
   1981 #define LPM_HASH_INSERT(u, entry_data, tab_index, rvt_index0, rvt_index1)   \
   1982     soc_fb_lpm_hash_insert(u, entry_data, tab_index, LPM_NO_MATCH_INDEX, 0, \
   1983                            rvt_index0, rvt_index1)
   1984 
   1985 #define LPM_HASH_REVERT(u, entry_data, tab_index, rvt_index0, rvt_index1)   \
   1986     soc_fb_lpm_hash_revert(u, entry_data, tab_index, rvt_index0, rvt_index1)
   1987 
   1988 #define LPM_HASH_DELETE(u, key_data, tab_index)         \
   1989     soc_fb_lpm_hash_delete(u, key_data, tab_index)
   1990 
   1991 #define LPM_HASH_LOOKUP(u, key_data, pfx, tab_index)    \
   1992     soc_fb_lpm_hash_lookup(u, key_data, pfx, tab_index)
   1993 
   1994 void soc_fb_lpm_hash_insert(int u, void *entry_data, uint32 tab_index,
   1995                             uint32 old_index, int pfx,
   1996                             uint32 *rvt_index0, uint32 *rvt_index1)
   1997 {
   1998     _soc_fb_lpm_hash_entry_t    key_hash;
   1999     int                         is_ipv6;
   2000     soc_mem_t                   mem = L3_DEFIPm;
   2001 
   2002 #if defined(BCM_TOMAHAWK3_SUPPORT)
   2003     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   2004         uint32 _key_data[2] = {0, 0};
   2005         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, KEY0f,_key_data);
   2006         is_ipv6 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf);
   2007         mem = L3_DEFIP_LEVEL1m;
   2008     } else
   2009 #endif
   2010     {
   2011         is_ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, defip_mode0_field);
   2012     }
   2013 
   2014     if (is_ipv6) {
   2015         /* IPV6 entry */
   2016         if (SOC_MEM_OPT_F32_VALID1_GET(u, mem, entry_data) &&
   2017             SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data)) {
   2018 #if defined(BCM_TOMAHAWK3_SUPPORT)
   2019             if (SOC_MEM_IS_VALID(u, L3_DEFIP_LEVEL1m)) {
   2020                 SOC_TH3_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, key_hash);
   2021             } else
   2022 #endif
   2023             {
   2024                 SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, key_hash);
   2025             }
   2026             _soc_fb_lpm_hash_insert(
   2027                         SOC_LPM_STATE_HASH(u),
   2028                         _soc_fb_lpm_hash_compare_key,
   2029                         key_hash,
   2030                         pfx,
   2031                         old_index,
   2032                         (tab_index << 1) | FB_LPM_HASH_IPV6_MASK,
   2033                         rvt_index0);
   2034         }
   2035     } else {
   2036         /* IPV4 entry */
   2037         if (SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data)) {
   2038             SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, key_hash);
   2039             _soc_fb_lpm_hash_insert(SOC_LPM_STATE_HASH(u),
   2040                                     _soc_fb_lpm_hash_compare_key,
   2041                                     key_hash,
   2042                                     pfx,
   2043                                     old_index,
   2044                                     (tab_index << 1),
   2045                                     rvt_index0);
   2046         }
   2047         if (SOC_MEM_OPT_F32_VALID1_GET(u, mem, entry_data)) {
   2048             SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, key_hash);
   2049             _soc_fb_lpm_hash_insert(SOC_LPM_STATE_HASH(u),
   2050                                     _soc_fb_lpm_hash_compare_key,
   2051                                     key_hash,
   2052                                     pfx,
   2053                                     old_index,
   2054                                     ((tab_index << 1) + 1),
   2055                                     rvt_index1);
   2056         }
   2057     }
   2058 }
   2059 
   2060 
   2061 
   2062 void soc_fb_lpm_hash_revert(int u, void *entry_data, uint32 tab_index,
   2063                             uint32 rvt_index0, uint32 rvt_index1)
   2064 {
   2065     _soc_fb_lpm_hash_entry_t    key_hash;
   2066     soc_mem_t                   mem = L3_DEFIPm;
   2067     int ipv6 = 0;
   2068 #if defined(BCM_TOMAHAWK3_SUPPORT)
   2069     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   2070         uint32 _key_data[2] = {0, 0};
   2071         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, KEY0f,_key_data);
   2072         ipv6 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf);
   2073         mem = L3_DEFIP_LEVEL1m;
   2074     } else
   2075 #endif
   2076     {
   2077         ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, defip_mode0_field);
   2078     }
   2079 
   2080     if (ipv6) {
   2081         /* IPV6 entry */
   2082         if (SOC_MEM_OPT_F32_VALID1_GET(u, mem, entry_data) &&
   2083             SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data)) {
   2084 #if defined(BCM_TOMAHAWK3_SUPPORT)
   2085             if (SOC_MEM_IS_VALID(u, L3_DEFIP_LEVEL1m)) {
   2086                 SOC_TH3_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, key_hash);
   2087             } else
   2088 #endif
   2089             {
   2090                 SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, key_hash);
   2091             }
   2092             _soc_fb_lpm_hash_revert(
   2093                         SOC_LPM_STATE_HASH(u),
   2094                         _soc_fb_lpm_hash_compare_key,
   2095                         key_hash,
   2096                         (tab_index << 1) | FB_LPM_HASH_IPV6_MASK,
   2097                         rvt_index0);
   2098         }
   2099     } else {
   2100         /* IPV4 entry */
   2101         if (SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data)) {
   2102             SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, key_hash);
   2103             _soc_fb_lpm_hash_revert(SOC_LPM_STATE_HASH(u),
   2104                                     _soc_fb_lpm_hash_compare_key,
   2105                                     key_hash,
   2106                                     (tab_index << 1),
   2107                                     rvt_index0);
   2108         }
   2109         if (SOC_MEM_OPT_F32_VALID1_GET(u, mem, entry_data)) {
   2110             SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, key_hash);
   2111             _soc_fb_lpm_hash_revert(SOC_LPM_STATE_HASH(u),
   2112                                     _soc_fb_lpm_hash_compare_key,
   2113                                     key_hash,
   2114                                     ((tab_index << 1) + 1),
   2115                                     rvt_index1);
   2116         }
   2117     }
   2118 }
   2119 
   2120 void soc_fb_lpm_hash_delete(int u, void *key_data, uint32 tab_index)
   2121 {
   2122     _soc_fb_lpm_hash_entry_t    key_hash;
   2123     int                         pfx = -1;
   2124     int                         rv;
   2125     int                         is_ipv6;
   2126     uint32                      index;
   2127 
   2128 #if defined(BCM_TOMAHAWK3_SUPPORT)
   2129     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   2130         uint32 _key_data[2] = {0, 0};
   2131         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, key_data, KEY0f,_key_data);
   2132         is_ipv6 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf);
   2133     } else
   2134 #endif
   2135     {
   2136         is_ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, defip_mode0_field);
   2137     }
   2138 
   2139     if (is_ipv6) {
   2140 #if defined(BCM_TOMAHAWK3_SUPPORT)
   2141             if (SOC_MEM_IS_VALID(u, L3_DEFIP_LEVEL1m)) {
   2142                 SOC_TH3_LPM_HASH_ENTRY_IPV6_GET(u, key_data, key_hash);
   2143             } else
   2144 #endif
   2145             {
   2146                 SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, key_data, key_hash);
   2147             }
   2148         index = (tab_index << 1) | FB_LPM_HASH_IPV6_MASK;
   2149     } else {
   2150         SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, key_data, key_hash);
   2151         index = tab_index;
   2152     }
   2153 
   2154     rv = _soc_fb_lpm_hash_delete(SOC_LPM_STATE_HASH(u),
   2155                                  _soc_fb_lpm_hash_compare_key,
   2156                                  key_hash, pfx, index);
   2157     if (SOC_FAILURE(rv)) {
   2158         LOG_ERROR(BSL_LS_SOC_LPM,
   2159                   (BSL_META_U(u,
   2160                               "\ndel  index: H %d error %d\n"), index, rv));
   2161     }
   2162 }
   2163 
   2164 int soc_fb_lpm_hash_lookup(int u, void *key_data, int pfx, int *key_index)
   2165 {
   2166     _soc_fb_lpm_hash_entry_t    key_hash;
   2167     int                         is_ipv6;
   2168     int                         rv;
   2169     uint32                      index = FB_LPM_HASH_INDEX_NULL;
   2170 
   2171 #if defined(BCM_TOMAHAWK3_SUPPORT)
   2172     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   2173         uint32 _key_data[2] = {0, 0};
   2174         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, key_data, KEY0f,_key_data);
   2175         is_ipv6 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf);
   2176     } else
   2177 #endif
   2178     {
   2179         is_ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, defip_mode0_field);
   2180     }
   2181 
   2182     if (is_ipv6) {
   2183         SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, key_data, key_hash);
   2184     } else {
   2185         SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, key_data, key_hash);
   2186     }
   2187 
   2188     rv = _soc_fb_lpm_hash_lookup(SOC_LPM_STATE_HASH(u),
   2189                                  _soc_fb_lpm_hash_compare_key,
   2190                                  key_hash, pfx, &index);
   2191     if (SOC_FAILURE(rv)) {
   2192         *key_index = 0xFFFFFFFF;
   2193         return(rv);
   2194     }
   2195 
   2196     *key_index = index;
   2197 
   2198     return(SOC_E_NONE);
   2199 }
   2200 
   2201 /* 
   2202  * Function:
   2203  *      _soc_fb_lpm_hash_compute
   2204  * Purpose:
   2205  *      Compute CRC hash for key data.
   2206  * Parameters:
   2207  *      data - Key data
   2208  *      data_nbits - Number of data bits
   2209  * Returns:
   2210  *      Computed 16 bit hash
   2211  */
   2212 static
   2213 unsigned int _soc_fb_lpm_hash_compute(uint8 *data, int data_nbits)
   2214 {
   2215     return (_shr_crc32b(0, data, data_nbits));
   2216 }
   2217 
   2218 /* 
   2219  * Function:
   2220  *      _soc_fb_lpm_hash_create
   2221  * Purpose:
   2222  *      Create an empty hash table
   2223  * Parameters:
   2224  *      unit  - Device unit
   2225  *      entry_count - Limit for number of entries in table
   2226  *      index_count - Hash index max + 1. (index_count <= count)
   2227  *      fb_lpm_hash_ptr - Return pointer (handle) to new Hash Table
   2228  * Returns:
   2229  *      SOC_E_NONE       Success
   2230  *      SOC_E_MEMORY     Out of memory (system allocator)
   2231  */
   2232 
   2233 static
   2234 int _soc_fb_lpm_hash_create(int unit,
   2235                             int entry_count,
   2236                             int index_count,
   2237                             _soc_fb_lpm_hash_t **fb_lpm_hash_ptr)
   2238 {
   2239     _soc_fb_lpm_hash_t  *hash;
   2240     int                 index;
   2241 
   2242     if (index_count > entry_count) {
   2243         return SOC_E_MEMORY;
   2244     }
   2245 
   2246     hash = sal_alloc(sizeof (_soc_fb_lpm_hash_t), "lpm_hash");
   2247     if (hash == NULL) {
   2248         return SOC_E_MEMORY;
   2249     }
   2250 
   2251     sal_memset(hash, 0, sizeof (*hash));
   2252 
   2253     hash->unit = unit;
   2254     hash->entry_count = entry_count;
   2255     hash->index_count = index_count;
   2256 
   2257     /*
   2258      * Pre-allocate the hash table storage.
   2259      */
   2260     hash->table = sal_alloc(hash->index_count * sizeof(*(hash->table)),
   2261                             "hash_table");
   2262 
   2263     if (hash->table == NULL) {
   2264         sal_free(hash);
   2265         return SOC_E_MEMORY;
   2266     }
   2267     /*
   2268      * In case where all the entries should hash into the same bucket
   2269      * this will prevent the hash table overflow
   2270      */
   2271     hash->link_table = sal_alloc(
   2272                             hash->entry_count * sizeof(*(hash->link_table)),
   2273                             "link_table");
   2274     if (hash->link_table == NULL) {
   2275         sal_free(hash->table);
   2276         sal_free(hash);
   2277         return SOC_E_MEMORY;
   2278     }
   2279 
   2280 #ifdef FB_LPM_DEBUG
   2281     hash->check_table = sal_alloc(
   2282                             hash->entry_count * sizeof(*(hash->check_table)),
   2283                             "link_table");
   2284     if (hash->check_table == NULL) {
   2285         sal_free(hash->link_table);
   2286         sal_free(hash->table);
   2287         sal_free(hash);
   2288         return SOC_E_MEMORY;
   2289     }
   2290     for(index = 0; index < hash->entry_count; index++) {
   2291         hash->check_table[index] = 0;
   2292     }
   2293 #endif
   2294 
   2295     /*
   2296      * Set the entries in the hash table to FB_LPM_HASH_INDEX_NULL
   2297      * Link the entries beyond hash->index_max for handling collisions
   2298      */
   2299     for(index = 0; index < hash->index_count; index++) {
   2300         hash->table[index] = FB_LPM_HASH_INDEX_NULL;
   2301     }
   2302     for(index = 0; index < hash->entry_count; index++) {
   2303         hash->link_table[index] = FB_LPM_HASH_INDEX_NULL;
   2304     }
   2305     *fb_lpm_hash_ptr = hash;
   2306     return SOC_E_NONE;
   2307 }
   2308 
   2309 /* 
   2310  * Function:
   2311  *      _soc_fb_lpm_hash_destroy
   2312  * Purpose:
   2313  *      Destroy the hash table
   2314  * Parameters:
   2315  *      fb_lpm_hash - Pointer (handle) to Hash Table
   2316  * Returns:
   2317  *      SOC_E_NONE       Success
   2318  */
   2319 static
   2320 int _soc_fb_lpm_hash_destroy(_soc_fb_lpm_hash_t *fb_lpm_hash)
   2321 {
   2322     if (fb_lpm_hash != NULL) {
   2323         sal_free(fb_lpm_hash->table);
   2324         sal_free(fb_lpm_hash->link_table);
   2325 #ifdef FB_LPM_DEBUG
   2326         sal_free(fb_lpm_hash->check_table);
   2327 #endif
   2328         sal_free(fb_lpm_hash);
   2329     }
   2330 
   2331     return SOC_E_NONE;
   2332 }
   2333 
   2334 /*
   2335  * Function:
   2336  *      _soc_fb_lpm_hash_lookup
   2337  * Purpose:
   2338  *      Look up a key in the hash table
   2339  * Parameters:
   2340  *      hash - Pointer (handle) to Hash Table
   2341  *      key_cmp_fn - Compare function which should compare key
   2342  *      entry   - The key to lookup
   2343  *      pfx     - Prefix length for lookup acceleration.
   2344  *      key_index - (OUT)       Index where the key was found.
   2345  * Returns:
   2346  *      SOC_E_NONE      Key found
   2347  *      SOC_E_NOT_FOUND Key not found
   2348  */
   2349 
   2350 static
   2351 int _soc_fb_lpm_hash_lookup(_soc_fb_lpm_hash_t          *hash,
   2352                             _soc_fb_lpm_hash_compare_fn key_cmp_fn,
   2353                             _soc_fb_lpm_hash_entry_t    entry,
   2354                             int                         pfx,
   2355                             uint32                      *key_index)
   2356 {
   2357     int u = hash->unit, v, i = 0;
   2358 
   2359     uint16 hash_val;
   2360     uint32 index;
   2361 
   2362     hash_val = _soc_fb_lpm_hash_compute((uint8 *)entry,
   2363                                         (32 * 6)) % hash->index_count;
   2364     index = hash->table[hash_val];
   2365     H_INDEX_MATCH("lhash", entry[0], hash_val);
   2366     H_INDEX_MATCH("lkup ", entry[0], index);
   2367     while(index != FB_LPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   2368         uint32  e[SOC_MAX_MEM_FIELD_WORDS];
   2369         _soc_fb_lpm_hash_entry_t  r_entry;
   2370         int     rindex;
   2371         int rv = SOC_E_NONE;
   2372 
   2373         rindex = (index & fb_lpm_hash_index_mask[u]) >> 1;
   2374         /*
   2375          * Check prefix length and skip index if not valid for given length
   2376         if ((SOC_LPM_STATE_START(u, pfx) <= rindex) &&
   2377             (SOC_LPM_STATE_END(u, pfx) >= rindex)) {
   2378          */
   2379         rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, rindex, e);
   2380         SOC_IF_ERROR_RETURN(rv);
   2381         SOC_FB_LPM_HASH_ENTRY_GET(u, e, index, r_entry, &v);
   2382         if (v == 0) {
   2383             LOG_ERROR(BSL_LS_SOC_LPM,
   2384                       (BSL_META_U(u,
   2385                                 "Empty entry[%d] in link_table. hash_val %d ridx %d\n"),
   2386                                 index, hash_val, rindex));
   2387         }
   2388         if ((*key_cmp_fn)(entry, r_entry) == 0) {
   2389             *key_index = (index & fb_lpm_hash_index_mask[u]) >>
   2390                             ((index & FB_LPM_HASH_IPV6_MASK) ? 1 : 0);
   2391             H_INDEX_MATCH("found", entry[0], index);
   2392             return(SOC_E_NONE);
   2393         }
   2394         /*
   2395         }
   2396         */
   2397         index = hash->link_table[index & fb_lpm_hash_index_mask[u]];
   2398         H_INDEX_MATCH("lkup1", entry[0], index);
   2399     }
   2400     if (i > hash->entry_count) {
   2401         LOG_ERROR(BSL_LS_SOC_LPM,
   2402                   (BSL_META_U(u,
   2403                             "Hash loop\n")));
   2404     }
   2405     H_INDEX_MATCH("not_found", entry[0], index);
   2406     return(SOC_E_NOT_FOUND);
   2407 }
   2408 
   2409 /*
   2410  * Function:
   2411  *      _soc_fb_lpm_hash_insert
   2412  * Purpose:
   2413  *      Insert/Update a key index in the hash table
   2414  * Parameters:
   2415  *      hash - Pointer (handle) to Hash Table
   2416  *      key_cmp_fn - Compare function which should compare key
   2417  *      entry   - The key to lookup
   2418  *      pfx     - Prefix length for lookup acceleration.
   2419  *      old_index - Index where the key was moved from.
   2420  *                  FB_LPM_HASH_INDEX_NULL if new entry.
   2421  *      new_index - Index where the key was moved to.
   2422  * Returns:
   2423  *      SOC_E_NONE      Key found
   2424  */
   2425 /*
   2426  *      Should be caled before updating the LPM table so that the
   2427  *      data in the hash table is consistent with the LPM table
   2428  */
   2429 static
   2430 int _soc_fb_lpm_hash_insert(_soc_fb_lpm_hash_t *hash,
   2431                             _soc_fb_lpm_hash_compare_fn key_cmp_fn,
   2432                             _soc_fb_lpm_hash_entry_t entry,
   2433                             int    pfx,
   2434                             uint32 old_index,
   2435                             uint32 new_index,
   2436                             uint32 *rvt_index)
   2437 {
   2438     int u = hash->unit, v, i = 0;
   2439     uint32 hash_val;
   2440     uint32 index;
   2441     uint32 prev_index;
   2442     int rv = SOC_E_NONE;
   2443 
   2444     if (rvt_index) {
   2445         *rvt_index = FB_LPM_HASH_INDEX_NULL;
   2446     }
   2447     hash_val = _soc_fb_lpm_hash_compute((uint8 *)entry,
   2448                                         (32 * 6)) % hash->index_count;
   2449     index = hash->table[hash_val];
   2450     H_INDEX_MATCH("ihash", entry[0], hash_val);
   2451     H_INDEX_MATCH("ins  ", entry[0], new_index);
   2452     H_INDEX_MATCH("ins1 ", index, new_index);
   2453     prev_index = FB_LPM_HASH_INDEX_NULL;
   2454     if (old_index != FB_LPM_HASH_INDEX_NULL) {
   2455         while(index != FB_LPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   2456             uint32  e[SOC_MAX_MEM_FIELD_WORDS];
   2457             _soc_fb_lpm_hash_entry_t  r_entry;
   2458             int     rindex;
   2459             
   2460             rindex = (index & fb_lpm_hash_index_mask[u]) >> 1;
   2461 
   2462             /*
   2463              * Check prefix length and skip index if not valid for given length
   2464             if ((SOC_LPM_STATE_START(u, pfx) <= rindex) &&
   2465                 (SOC_LPM_STATE_END(u, pfx) >= rindex)) {
   2466              */
   2467             rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, rindex, e);
   2468             SOC_IF_ERROR_RETURN(rv);
   2469             SOC_FB_LPM_HASH_ENTRY_GET(u, e, index, r_entry, &v);
   2470             if (v == 0) {
   2471                 if ((index & FB_LPM_HASH_IPV6_MASK) ||
   2472                     !((new_index & 1) && (new_index == (index + 1)))) {
   2473                     LOG_ERROR(BSL_LS_SOC_LPM,
   2474                           (BSL_META_U(u,
   2475                                     "Empty entry[%d] in link_table. hash_val %d ridx %d nidx %d\n"),
   2476                                     index, hash_val, rindex, new_index));
   2477                 }
   2478             }
   2479             if (v && ((*key_cmp_fn)(entry, r_entry) == 0)) {
   2480                 /* assert(old_index == index);*/
   2481                 if (new_index != index) {
   2482                     H_INDEX_MATCH("imove", prev_index, new_index);
   2483                     if (prev_index == FB_LPM_HASH_INDEX_NULL) {
   2484                         INDEX_UPDATE(hash, hash_val, index, new_index);
   2485                     } else {
   2486                         INDEX_UPDATE_LINK(hash, prev_index, index, new_index);
   2487                     }
   2488                 }
   2489                 if (rvt_index) {
   2490                     *rvt_index = index;
   2491                 }
   2492                 H_INDEX_MATCH("imtch", index, new_index);
   2493                 return(SOC_E_NONE);
   2494             }
   2495             /*
   2496             }
   2497             */
   2498             prev_index = index;
   2499             index = hash->link_table[index & fb_lpm_hash_index_mask[u]];
   2500             H_INDEX_MATCH("ins2 ", index, new_index);
   2501         }
   2502     }
   2503     if (i > hash->entry_count) {
   2504         LOG_ERROR(BSL_LS_SOC_LPM,
   2505                   (BSL_META_U(u,
   2506                             "Hash loop\n")));
   2507         return SOC_E_INTERNAL;
   2508     }
   2509     INDEX_ADD(hash, hash_val, new_index);  /* new entry */
   2510     return(SOC_E_NONE);
   2511 }
   2512 
   2513 /*
   2514  * Function:
   2515  *      _soc_fb_lpm_hash_revert
   2516  * Purpose:
   2517  *      Revert a key index in the hash table
   2518  * Parameters:
   2519  *      hash - Pointer (handle) to Hash Table
   2520  *      key_cmp_fn - Compare function which should compare key
   2521  *      entry   - The key to delete
   2522  *      pfx     - Prefix length for lookup acceleration.
   2523  *      delete_index - Index to delete.
   2524  * Returns:
   2525  *      SOC_E_NONE      Success
   2526  *      SOC_E_NOT_FOUND Key index not found.
   2527  */
   2528 static
   2529 int _soc_fb_lpm_hash_revert(_soc_fb_lpm_hash_t *hash,
   2530                             _soc_fb_lpm_hash_compare_fn key_cmp_fn,
   2531                             _soc_fb_lpm_hash_entry_t entry,
   2532                             uint32 new_index,
   2533                             uint32 rvt_index)
   2534 {
   2535     int u = hash->unit, i = 0;
   2536     uint16 hash_val;
   2537     uint32 index;
   2538     uint32 prev_index;
   2539 
   2540     hash_val = _soc_fb_lpm_hash_compute((uint8 *)entry,
   2541                                         (32 * 6)) % hash->index_count;
   2542     index = hash->table[hash_val];
   2543     H_INDEX_MATCH("rhash", entry[0], hash_val);
   2544     H_INDEX_MATCH("rvt  ", entry[0], index);
   2545     prev_index = FB_LPM_HASH_INDEX_NULL;
   2546     while(index != FB_LPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   2547         if (new_index == index) {
   2548             H_INDEX_MATCH("rfoun", entry[0], index);
   2549             if (rvt_index == FB_LPM_HASH_INDEX_NULL) {
   2550                 if (prev_index == FB_LPM_HASH_INDEX_NULL) {
   2551                     INDEX_DELETE(hash, hash_val, new_index);
   2552                 } else {
   2553                     INDEX_DELETE_LINK(hash, prev_index, new_index);
   2554                 }
   2555             } else {
   2556                 if (prev_index == FB_LPM_HASH_INDEX_NULL) {
   2557                     INDEX_UPDATE(hash, hash_val, new_index, rvt_index);
   2558                 } else {
   2559                     INDEX_UPDATE_LINK(hash, prev_index, new_index, rvt_index);
   2560                 }
   2561             }
   2562             return(SOC_E_NONE);
   2563         }
   2564         prev_index = index;
   2565         index = hash->link_table[index & fb_lpm_hash_index_mask[u]];
   2566         H_INDEX_MATCH("rvt1 ", entry[0], index);
   2567     }
   2568     if (i > hash->entry_count) {
   2569         LOG_ERROR(BSL_LS_SOC_LPM,
   2570                   (BSL_META_U(u,
   2571                             "Hash loop\n")));
   2572     }
   2573     return(SOC_E_NOT_FOUND);
   2574 }
   2575 
   2576 /*
   2577  * Function:
   2578  *      _soc_fb_lpm_hash_delete
   2579  * Purpose:
   2580  *      Delete a key index in the hash table
   2581  * Parameters:
   2582  *      hash - Pointer (handle) to Hash Table
   2583  *      key_cmp_fn - Compare function which should compare key
   2584  *      entry   - The key to delete
   2585  *      pfx     - Prefix length for lookup acceleration.
   2586  *      delete_index - Index to delete.
   2587  * Returns:
   2588  *      SOC_E_NONE      Success
   2589  *      SOC_E_NOT_FOUND Key index not found.
   2590  */
   2591 static
   2592 int _soc_fb_lpm_hash_delete(_soc_fb_lpm_hash_t *hash,
   2593                             _soc_fb_lpm_hash_compare_fn key_cmp_fn,
   2594                             _soc_fb_lpm_hash_entry_t entry,
   2595                             int    pfx,
   2596                             uint32 delete_index)
   2597 {
   2598     int u = hash->unit, i = 0;
   2599     uint16 hash_val;
   2600     uint32 index;
   2601     uint32 prev_index;
   2602 
   2603     hash_val = _soc_fb_lpm_hash_compute((uint8 *)entry,
   2604                                         (32 * 6)) % hash->index_count;
   2605     index = hash->table[hash_val];
   2606     H_INDEX_MATCH("dhash", entry[0], hash_val);
   2607     H_INDEX_MATCH("del  ", entry[0], index);
   2608     prev_index = FB_LPM_HASH_INDEX_NULL;
   2609     while(index != FB_LPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   2610         if (delete_index == index) {
   2611             H_INDEX_MATCH("dfoun", entry[0], index);
   2612             if (prev_index == FB_LPM_HASH_INDEX_NULL) {
   2613                 INDEX_DELETE(hash, hash_val, delete_index);
   2614             } else {
   2615                 INDEX_DELETE_LINK(hash, prev_index, delete_index);
   2616             }
   2617             return(SOC_E_NONE);
   2618         }
   2619         prev_index = index;
   2620         index = hash->link_table[index & fb_lpm_hash_index_mask[u]];
   2621         H_INDEX_MATCH("del1 ", entry[0], index);
   2622     }
   2623     if (i > hash->entry_count) {
   2624         LOG_ERROR(BSL_LS_SOC_LPM,
   2625                   (BSL_META_U(u,
   2626                             "Hash loop\n")));
   2627     }
   2628     return(SOC_E_NOT_FOUND);
   2629 }
   2630 #else
   2631 #define LPM_HASH_INSERT(u, entry_data, tab_index, rvt_index0, rvt_index1)
   2632 #define LPM_HASH_REVERT(u, entry_data, tab_index, rvt_index0, rvt_index1)
   2633 #define LPM_HASH_DELETE(u, key_data, tab_index)
   2634 #define LPM_HASH_LOOKUP(u, key_data, pfx, tab_index)
   2635 #endif /* FB_LPM_HASH_SUPPORT */
   2636 
   2637 static
   2638 int
   2639 _ipmask2pfx(uint32 ipv4m, int *mask_len)
   2640 {
   2641     *mask_len = 0;
   2642     while (ipv4m & (1 << 31)) {
   2643         *mask_len += 1;
   2644         ipv4m <<= 1;
   2645     }
   2646 
   2647     return ((ipv4m) ? SOC_E_PARAM : SOC_E_NONE);
   2648 }
   2649 
   2650 /* src and dst can be same */
   2651 int
   2652 soc_fb_lpm_ip4entry0_to_0(int u, void *src, void *dst, int copy_hit)
   2653 {
   2654     uint32      ipv4a;
   2655     soc_mem_t mem = L3_DEFIPm;
   2656 
   2657     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   2658         mem = L3_DEFIP_LEVEL1m;
   2659     }
   2660 #ifdef BCM_TRIDENT3_SUPPORT
   2661     if (soc_feature(u, soc_feature_flex_flow)) {
   2662         uint32      key_type;
   2663 
   2664         if (soc_mem_field_valid(u, L3_DEFIPm, KEY_TYPE0f)) {
   2665             key_type = soc_mem_field32_get(u, L3_DEFIPm, src, KEY_TYPE0f);
   2666         } else {
   2667             key_type = 0;
   2668         }
   2669    
   2670         if (BCMI_LPM_FLEX_VIEW(key_type)) {
   2671             return soc_td3_lpm_flex_ip4entry0_to_0(u, src, dst, key_type, copy_hit);
   2672         }
   2673     }
   2674 #endif
   2675 
   2676 
   2677     ipv4a = SOC_MEM_OPT_F32_VALID0_GET(u, mem, src);
   2678     SOC_MEM_OPT_F32_VALID0_SET(u, mem, dst, ipv4a);
   2679 
   2680     if (copy_hit) {
   2681         ipv4a = SOC_MEM_OPT_F32_HIT0_GET(u, mem, src);
   2682         SOC_MEM_OPT_F32_HIT0_SET(u, mem, dst, ipv4a);
   2683     }
   2684 
   2685 #if defined(BCM_TOMAHAWK3_SUPPORT)
   2686     if (SOC_IS_TOMAHAWK3(u)) {
   2687         uint32      val[2] = {0, 0};
   2688         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, KEY0f, val);
   2689         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, KEY0f, val);
   2690         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, MASK0f, val);
   2691         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, MASK0f, val);
   2692         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, ASSOC_DATA0f, val);
   2693         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, ASSOC_DATA0f, val);
   2694         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, FIXED_DATA0f, val);
   2695         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, FIXED_DATA0f, val);
   2696         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, ALPM1_DATA0f, val);
   2697         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, ALPM1_DATA0f, val);
   2698         return(SOC_E_NONE);
   2699     }
   2700 #endif
   2701     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, defip_mode0_field);
   2702     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, defip_mode0_field, ipv4a);
   2703 #if defined(BCM_TRX_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
   2704     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, defip_mode_mask0_field)) {
   2705         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, defip_mode_mask0_field);
   2706         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, defip_mode_mask0_field, ipv4a);
   2707     }
   2708 #endif /* BCM_TRX_SUPPORT || BCM_RAVEN_SUPPORT */
   2709 
   2710 #if defined(BCM_TRX_SUPPORT)
   2711     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, GLOBAL_ROUTE0f)) {
   2712         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_ROUTE0f);
   2713         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_ROUTE0f, ipv4a);
   2714     }
   2715 #endif /* BCM_TRX_SUPPORT */
   2716 
   2717     if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE0f)) {
   2718         ipv4a = soc_mem_field32_get(u, L3_DEFIPm, src, DATA_TYPE0f);
   2719         soc_mem_field32_set(u, L3_DEFIPm, dst, DATA_TYPE0f, ipv4a);
   2720     }
   2721 
   2722 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2723     if (soc_feature(u, soc_feature_ipmc_defip)) {
   2724         if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE0f)) {
   2725             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MULTICAST_ROUTE0f);
   2726             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MULTICAST_ROUTE0f, ipv4a);
   2727         }
   2728 
   2729         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f);
   2730         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f, ipv4a);
   2731 
   2732         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f);
   2733         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f, ipv4a);
   2734 
   2735         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPA_ID0f);
   2736         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPA_ID0f, ipv4a);
   2737 
   2738         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, EXPECTED_L3_IIF0f);
   2739         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, EXPECTED_L3_IIF0f, ipv4a);
   2740 
   2741         if (soc_mem_field_valid(u, L3_DEFIPm, L3MC_INDEX0f)) {
   2742             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, L3MC_INDEX0f);
   2743             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, L3MC_INDEX0f, ipv4a);
   2744         }
   2745     }
   2746 #endif
   2747     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR0f);
   2748     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR0f, ipv4a);
   2749 
   2750     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR_MASK0f);
   2751     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR_MASK0f, ipv4a);
   2752 
   2753     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP0f)) {
   2754         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP0f);
   2755         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP0f, ipv4a);
   2756     }
   2757 
   2758     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP_COUNT0f)) {
   2759         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_COUNT0f);
   2760         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_COUNT0f, ipv4a);
   2761 
   2762         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_PTR0f);
   2763         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_PTR0f, ipv4a);
   2764     } else {
   2765 #if defined(BCM_TRIDENT3_SUPPORT)
   2766         if (soc_feature(u, soc_feature_generic_dest)) {
   2767             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DESTINATION0f);
   2768             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DESTINATION0f, ipv4a);
   2769 
   2770         } else
   2771 #endif
   2772         {
   2773             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, NEXT_HOP_INDEX0f);
   2774             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, NEXT_HOP_INDEX0f, ipv4a);
   2775         }
   2776     }
   2777 
   2778     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, PRI0f);
   2779     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, PRI0f, ipv4a);
   2780 
   2781     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPE0f);
   2782     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPE0f, ipv4a);
   2783 
   2784     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DEFAULTROUTE0f)) {
   2785         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src,DEFAULTROUTE0f);
   2786         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DEFAULTROUTE0f, ipv4a);
   2787     }
   2788 
   2789     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f)) {
   2790         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_0f);
   2791         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_0f, ipv4a);
   2792         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_MASK0f);
   2793         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_MASK0f, ipv4a);
   2794     }
   2795 
   2796     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ENTRY_TYPE0f)) {
   2797         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ENTRY_TYPE0f);
   2798         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ENTRY_TYPE0f, ipv4a);
   2799         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ENTRY_TYPE_MASK0f);
   2800         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ENTRY_TYPE_MASK0f, ipv4a);
   2801     }
   2802 
   2803     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, D_ID0f)) {
   2804         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, D_ID0f);
   2805         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, D_ID0f, ipv4a);
   2806         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, D_ID_MASK0f);
   2807         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, D_ID_MASK0f, ipv4a);
   2808     }
   2809 
   2810     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD0f)) {
   2811         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DST_DISCARD0f);
   2812         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DST_DISCARD0f, ipv4a);
   2813     }
   2814 #if defined(BCM_TRX_SUPPORT)
   2815     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, CLASS_ID0f)) {
   2816         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, CLASS_ID0f);
   2817         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, CLASS_ID0f, ipv4a);
   2818     }
   2819 #endif /* BCM_TRX_SUPPORT */
   2820 #if defined(BCM_TRIDENT2_SUPPORT)
   2821     if (soc_feature(u, soc_feature_advanced_flex_counter)) {
   2822         if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, FLEX_CTR_OFFSET_MODE0f)) {
   2823             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src,
   2824                                         FLEX_CTR_OFFSET_MODE0f);
   2825             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_OFFSET_MODE0f,
   2826                                 ipv4a);
   2827             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src,
   2828                                         FLEX_CTR_POOL_NUMBER0f);
   2829             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_POOL_NUMBER0f,
   2830                                 ipv4a);
   2831             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src,
   2832                                         FLEX_CTR_BASE_COUNTER_IDX0f);
   2833             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_BASE_COUNTER_IDX0f,
   2834                                 ipv4a);
   2835         }
   2836     }
   2837 #endif
   2838 
   2839     return(SOC_E_NONE);
   2840 }
   2841 
   2842 int
   2843 soc_fb_lpm_ip4entry1_to_1(int u, void *src, void *dst, int copy_hit)
   2844 {
   2845     uint32      ipv4a;
   2846     soc_mem_t mem = L3_DEFIPm;
   2847 
   2848     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   2849         mem = L3_DEFIP_LEVEL1m;
   2850     }
   2851 
   2852 
   2853     ipv4a = SOC_MEM_OPT_F32_VALID1_GET(u, mem, src);
   2854     SOC_MEM_OPT_F32_VALID1_SET(u, mem, dst, ipv4a);
   2855 
   2856     if (copy_hit) {
   2857         ipv4a = SOC_MEM_OPT_F32_HIT1_GET(u, mem, src);
   2858         SOC_MEM_OPT_F32_HIT1_SET(u, mem, dst, ipv4a);
   2859     }
   2860 
   2861 #if defined(BCM_TOMAHAWK3_SUPPORT)
   2862     if (SOC_IS_TOMAHAWK3(u)) {
   2863         uint32 val[2] = {0, 0};
   2864         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, KEY1f, val);
   2865         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, KEY1f, val);
   2866         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, MASK1f, val);
   2867         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, MASK1f, val);
   2868         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, ASSOC_DATA1f, val);
   2869         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, ASSOC_DATA1f, val);
   2870         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, FIXED_DATA1f, val);
   2871         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, FIXED_DATA1f, val);
   2872         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, ALPM1_DATA1f, val);
   2873         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, ALPM1_DATA1f, val);
   2874         return(SOC_E_NONE);
   2875     }
   2876 #endif
   2877     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, defip_mode1_field);
   2878     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, defip_mode1_field, ipv4a);
   2879 #if defined(BCM_TRX_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
   2880     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, defip_mode_mask1_field)) {
   2881         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, defip_mode_mask1_field);
   2882         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, defip_mode_mask1_field, ipv4a);
   2883     }
   2884 #endif /* BCM_TRX_SUPPORT || BCM_RAVEN_SUPPORT */
   2885 
   2886 #if defined(BCM_TRX_SUPPORT)
   2887     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, GLOBAL_ROUTE1f)) {
   2888         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_ROUTE1f);
   2889         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_ROUTE1f, ipv4a);
   2890     }
   2891 #endif /* BCM_TRX_SUPPORT */
   2892 
   2893     if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE1f)) {
   2894         ipv4a = soc_mem_field32_get(u, L3_DEFIPm, src, DATA_TYPE1f);
   2895         soc_mem_field32_set(u, L3_DEFIPm, dst, DATA_TYPE1f, ipv4a);
   2896     }
   2897 
   2898 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2899     if (soc_feature(u, soc_feature_ipmc_defip)) {
   2900         if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE1f)) {
   2901             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MULTICAST_ROUTE1f);
   2902             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MULTICAST_ROUTE1f, ipv4a);
   2903         }
   2904 
   2905         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f);
   2906         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f, ipv4a);
   2907 
   2908         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f);
   2909         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f, ipv4a);
   2910 
   2911         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPA_ID1f);
   2912         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPA_ID1f, ipv4a);
   2913 
   2914         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, EXPECTED_L3_IIF1f);
   2915         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, EXPECTED_L3_IIF1f, ipv4a);
   2916 
   2917         if (soc_mem_field_valid(u, L3_DEFIPm, L3MC_INDEX1f)) {
   2918             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, L3MC_INDEX1f);
   2919             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, L3MC_INDEX1f, ipv4a);
   2920         }
   2921     }
   2922 #endif
   2923 
   2924     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR1f);
   2925     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR1f, ipv4a);
   2926 
   2927     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR_MASK1f);
   2928     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR_MASK1f, ipv4a);
   2929 
   2930     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP1f)) {
   2931         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP1f);
   2932         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP1f, ipv4a);
   2933     }
   2934 
   2935     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP_COUNT1f)) {
   2936         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_COUNT1f);
   2937         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_COUNT1f, ipv4a);
   2938 
   2939         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_PTR1f);
   2940         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_PTR1f, ipv4a);
   2941     } else {
   2942 #if defined(BCM_TRIDENT3_SUPPORT)
   2943         if (soc_feature(u, soc_feature_generic_dest)) {
   2944             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DESTINATION1f);
   2945             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DESTINATION1f, ipv4a);
   2946         } else
   2947 #endif
   2948         {
   2949             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, NEXT_HOP_INDEX1f);
   2950             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, NEXT_HOP_INDEX1f, ipv4a);
   2951         }
   2952     }
   2953 
   2954     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, PRI1f);
   2955     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, PRI1f, ipv4a);
   2956 
   2957     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPE1f);
   2958     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPE1f, ipv4a);
   2959 
   2960     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DEFAULTROUTE1f)) {
   2961         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src,DEFAULTROUTE1f);
   2962         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DEFAULTROUTE1f, ipv4a);
   2963     }
   2964 
   2965     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_1f)) {
   2966         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_1f);
   2967         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_1f, ipv4a);
   2968         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_MASK1f);
   2969         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_MASK1f, ipv4a);
   2970     }
   2971 
   2972     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ENTRY_TYPE1f)) {
   2973         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ENTRY_TYPE1f);
   2974         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ENTRY_TYPE1f, ipv4a);
   2975         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ENTRY_TYPE_MASK1f);
   2976         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ENTRY_TYPE_MASK1f, ipv4a);
   2977     }
   2978 
   2979     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, D_ID1f)) {
   2980         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, D_ID1f);
   2981         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, D_ID1f, ipv4a);
   2982         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, D_ID_MASK1f);
   2983         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, D_ID_MASK1f, ipv4a);
   2984     }
   2985 
   2986     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD1f)) {
   2987         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DST_DISCARD1f);
   2988         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DST_DISCARD1f, ipv4a);
   2989     }
   2990 #if defined(BCM_TRX_SUPPORT)
   2991     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, CLASS_ID1f)) {
   2992         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, CLASS_ID1f);
   2993         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, CLASS_ID1f, ipv4a);
   2994     }
   2995 #endif /* BCM_TRX_SUPPORT */
   2996 
   2997 #if defined(BCM_TRIDENT2_SUPPORT)
   2998     if (soc_feature(u, soc_feature_advanced_flex_counter)) {
   2999         if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, FLEX_CTR_OFFSET_MODE1f)) {
   3000             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src,
   3001                                         FLEX_CTR_OFFSET_MODE1f);
   3002             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_OFFSET_MODE1f,
   3003                                 ipv4a);
   3004             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src,
   3005                                         FLEX_CTR_POOL_NUMBER1f);
   3006             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_POOL_NUMBER1f,
   3007                                 ipv4a);
   3008             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src,
   3009                                         FLEX_CTR_BASE_COUNTER_IDX1f);
   3010             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_BASE_COUNTER_IDX1f,
   3011                                 ipv4a);
   3012         }
   3013     }
   3014 #endif
   3015 
   3016     return(SOC_E_NONE);
   3017 }
   3018 
   3019 /* src and dst can be same */
   3020 int
   3021 soc_fb_lpm_ip4entry0_to_1(int u, void *src, void *dst, int copy_hit)
   3022 {
   3023     uint32      ipv4a;
   3024     soc_mem_t mem = L3_DEFIPm;
   3025 
   3026     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   3027         mem = L3_DEFIP_LEVEL1m;
   3028     }
   3029 
   3030 #ifdef BCM_TRIDENT3_SUPPORT
   3031     if (soc_feature(u, soc_feature_flex_flow)) {
   3032         uint32      key_type;
   3033 
   3034         if (soc_mem_field_valid(u, mem, KEY_TYPE0f)) {
   3035             key_type = soc_mem_field32_get(u, L3_DEFIPm, src, KEY_TYPE0f);
   3036         } else {
   3037             key_type = 0;
   3038         }
   3039     
   3040         if (BCMI_LPM_FLEX_VIEW(key_type)) {
   3041 
   3042             return soc_td3_lpm_flex_ip4entry0_to_1(u, src, dst, key_type, copy_hit);
   3043         }
   3044     }
   3045 #endif
   3046 
   3047     if (copy_hit) {
   3048         ipv4a = SOC_MEM_OPT_F32_HIT0_GET(u, mem, src);
   3049         SOC_MEM_OPT_F32_HIT1_SET(u, mem, dst, ipv4a);
   3050     }
   3051     ipv4a = SOC_MEM_OPT_F32_VALID0_GET(u, mem, src);
   3052     SOC_MEM_OPT_F32_VALID1_SET(u, mem, dst, ipv4a);
   3053 
   3054 
   3055 #if defined(BCM_TOMAHAWK3_SUPPORT)
   3056     if (SOC_IS_TOMAHAWK3(u)) {
   3057         uint32 val[2] = {0, 0};
   3058         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, KEY0f, val);
   3059         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, KEY1f, val);
   3060         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, MASK0f, val);
   3061         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, MASK1f, val);
   3062         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, ASSOC_DATA0f, val);
   3063         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, ASSOC_DATA1f, val);
   3064         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, FIXED_DATA0f, val);
   3065         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, FIXED_DATA1f, val);
   3066         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, ALPM1_DATA0f, val);
   3067         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, ALPM1_DATA1f, val);
   3068         return(SOC_E_NONE);
   3069     }
   3070 #endif
   3071 
   3072     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, defip_mode0_field);
   3073     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, defip_mode1_field, ipv4a);
   3074 #if defined(BCM_TRX_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
   3075     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, defip_mode_mask0_field)) {
   3076         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, defip_mode_mask0_field);
   3077         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, defip_mode_mask1_field, ipv4a);
   3078     }
   3079 #endif /* BCM_TRX_SUPPORT || BCM_RAVEN_SUPPORT */
   3080 #if defined(BCM_TRX_SUPPORT)
   3081     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, GLOBAL_ROUTE0f)) {
   3082         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_ROUTE0f);
   3083         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_ROUTE1f, ipv4a);
   3084     }
   3085 #endif /* BCM_TRX_SUPPORT */
   3086 
   3087     if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE0f)) {
   3088         ipv4a = soc_mem_field32_get(u, L3_DEFIPm, src, DATA_TYPE0f);
   3089         soc_mem_field32_set(u, L3_DEFIPm, dst, DATA_TYPE1f, ipv4a);
   3090     }
   3091 
   3092 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3093     if (soc_feature(u, soc_feature_ipmc_defip)) {
   3094         if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE1f)) {
   3095             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MULTICAST_ROUTE0f);
   3096             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MULTICAST_ROUTE1f, ipv4a);
   3097         }
   3098 
   3099         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPA_ID0f);
   3100         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPA_ID1f, ipv4a);
   3101 
   3102         if (soc_mem_field_valid(u, L3_DEFIPm, L3MC_INDEX1f)) {
   3103             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, L3MC_INDEX0f);
   3104             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, L3MC_INDEX1f, ipv4a);
   3105         }
   3106 
   3107         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, EXPECTED_L3_IIF0f);
   3108         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, EXPECTED_L3_IIF1f, ipv4a);
   3109 
   3110         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f);
   3111         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f, ipv4a);
   3112 
   3113         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f);
   3114         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f, ipv4a);
   3115     }
   3116 #endif /* BCM_TRIDENT2PLUS_SUPPORT */    
   3117 
   3118     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR0f);
   3119     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR1f, ipv4a);
   3120 
   3121     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR_MASK0f);
   3122     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR_MASK1f, ipv4a);
   3123 
   3124     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP0f)) {
   3125         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP0f);
   3126         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP1f, ipv4a);
   3127     }
   3128 
   3129     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP_COUNT0f)) {
   3130         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_COUNT0f);
   3131         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_COUNT1f, ipv4a);
   3132 
   3133         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_PTR0f);
   3134         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_PTR1f, ipv4a);
   3135     } else {
   3136 #if defined(BCM_TRIDENT3_SUPPORT)
   3137         if (soc_feature(u, soc_feature_generic_dest)) {
   3138             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DESTINATION0f);
   3139             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DESTINATION1f, ipv4a);
   3140         } else
   3141 #endif
   3142         {
   3143             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, NEXT_HOP_INDEX0f);
   3144             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, NEXT_HOP_INDEX1f, ipv4a);
   3145         }
   3146     }
   3147 
   3148     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, PRI0f);
   3149     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, PRI1f, ipv4a);
   3150 
   3151     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPE0f);
   3152     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPE1f, ipv4a);
   3153 
   3154     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DEFAULTROUTE0f) &&
   3155         SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DEFAULTROUTE1f)) {
   3156         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src,DEFAULTROUTE0f);
   3157         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DEFAULTROUTE1f, ipv4a);
   3158     }
   3159 
   3160     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f)) {
   3161         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_0f);
   3162         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_1f, ipv4a);
   3163         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_MASK0f);
   3164         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_MASK1f, ipv4a);
   3165     }
   3166 
   3167     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ENTRY_TYPE0f)) {
   3168         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ENTRY_TYPE0f);
   3169         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ENTRY_TYPE1f, ipv4a);
   3170         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ENTRY_TYPE_MASK0f);
   3171         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ENTRY_TYPE_MASK1f, ipv4a);
   3172     }
   3173 
   3174     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, D_ID0f)) {
   3175         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, D_ID0f);
   3176         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, D_ID1f, ipv4a);
   3177         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, D_ID_MASK0f);
   3178         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, D_ID_MASK1f, ipv4a);
   3179     }
   3180 
   3181     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD0f)) {
   3182         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DST_DISCARD0f);
   3183         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DST_DISCARD1f, ipv4a);
   3184     }
   3185 
   3186 #if defined(BCM_TRX_SUPPORT)
   3187     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, CLASS_ID0f)) {
   3188         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, CLASS_ID0f);
   3189         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, CLASS_ID1f, ipv4a);
   3190     }
   3191 #endif /* BCM_TRX_SUPPORT */
   3192 
   3193 #if defined(BCM_TRIDENT2_SUPPORT)
   3194     if (soc_feature(u, soc_feature_advanced_flex_counter)) {
   3195         if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, FLEX_CTR_OFFSET_MODE0f)) {
   3196             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src,
   3197                                         FLEX_CTR_OFFSET_MODE0f);
   3198             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_OFFSET_MODE1f,
   3199                                 ipv4a);
   3200             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src,
   3201                                         FLEX_CTR_POOL_NUMBER0f);
   3202             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_POOL_NUMBER1f,
   3203                                 ipv4a);
   3204             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src,
   3205                                         FLEX_CTR_BASE_COUNTER_IDX0f);
   3206             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_BASE_COUNTER_IDX1f,
   3207                                 ipv4a);
   3208         }
   3209     }
   3210 #endif
   3211 
   3212     return(SOC_E_NONE);
   3213 }
   3214 
   3215 /* src and dst can be same */
   3216 int
   3217 soc_fb_lpm_ip4entry1_to_0(int u, void *src, void *dst, int copy_hit)
   3218 {
   3219     uint32      ipv4a;
   3220     soc_mem_t mem = L3_DEFIPm;
   3221 
   3222     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   3223         mem = L3_DEFIP_LEVEL1m;
   3224     }
   3225 
   3226     ipv4a = SOC_MEM_OPT_F32_VALID1_GET(u, mem, src);
   3227     SOC_MEM_OPT_F32_VALID0_SET(u, mem, dst, ipv4a);
   3228 
   3229     if (copy_hit) {
   3230         ipv4a = SOC_MEM_OPT_F32_HIT1_GET(u, mem, src);
   3231         SOC_MEM_OPT_F32_HIT0_SET(u, mem, dst, ipv4a);
   3232     }
   3233 #if defined(BCM_TOMAHAWK3_SUPPORT)
   3234     if (SOC_IS_TOMAHAWK3(u)) {
   3235         uint32 _key_data[2] = {0, 0};
   3236         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, KEY1f, _key_data);
   3237         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, KEY0f, _key_data);
   3238         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, MASK1f, _key_data);
   3239         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, MASK0f, _key_data);
   3240         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, ASSOC_DATA1f, _key_data);
   3241         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, ASSOC_DATA0f, _key_data);
   3242         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, FIXED_DATA1f, _key_data);
   3243         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, FIXED_DATA0f, _key_data);
   3244         SOC_TH3_MEM_OPT_F64_GET(u, mem, src, ALPM1_DATA1f, _key_data);
   3245         SOC_TH3_MEM_OPT_F64_SET(u, mem, dst, ALPM1_DATA0f, _key_data);
   3246         return(SOC_E_NONE);
   3247     }
   3248 #endif
   3249 
   3250 
   3251     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, defip_mode1_field);
   3252     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, defip_mode0_field, ipv4a);
   3253 #if defined(BCM_TRX_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
   3254     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, defip_mode_mask0_field)) {
   3255         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, defip_mode_mask1_field);
   3256         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, defip_mode_mask0_field, ipv4a);
   3257     }
   3258 #endif /* BCM_TRX_SUPPORT || BCM_RAVEN_SUPPORT */
   3259 #if defined(BCM_TRX_SUPPORT)
   3260     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, GLOBAL_ROUTE1f)) {
   3261         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_ROUTE1f);
   3262         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_ROUTE0f, ipv4a);
   3263     }
   3264 #endif /* BCM_TRX_SUPPORT */
   3265 
   3266     if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE0f)) {
   3267         ipv4a = soc_mem_field32_get(u, L3_DEFIPm, src, DATA_TYPE1f);
   3268         soc_mem_field32_set(u, L3_DEFIPm, dst, DATA_TYPE0f, ipv4a);
   3269     }
   3270 
   3271 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3272     if (soc_feature(u, soc_feature_ipmc_defip)) {
   3273         if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE1f)) {
   3274             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MULTICAST_ROUTE1f);
   3275             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MULTICAST_ROUTE0f, ipv4a);
   3276         }
   3277 
   3278         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f);
   3279         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f, ipv4a);
   3280 
   3281         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f);
   3282         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f, ipv4a);
   3283 
   3284         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPA_ID1f);
   3285         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPA_ID0f, ipv4a);
   3286 
   3287         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, EXPECTED_L3_IIF1f);
   3288         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, EXPECTED_L3_IIF0f, ipv4a);
   3289 
   3290         if (soc_mem_field_valid(u, L3_DEFIPm, L3MC_INDEX1f)) {
   3291             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, L3MC_INDEX1f);
   3292             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, L3MC_INDEX0f, ipv4a);
   3293         }
   3294     }
   3295 #endif
   3296 
   3297     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR1f);
   3298     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR0f, ipv4a);
   3299 
   3300     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR_MASK1f);
   3301     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR_MASK0f, ipv4a);
   3302 
   3303 	if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP0f)) {
   3304         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP1f);
   3305         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP0f, ipv4a);
   3306 	}
   3307 
   3308     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP_COUNT1f)) {
   3309         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_COUNT1f);
   3310         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_COUNT0f, ipv4a);
   3311 
   3312         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_PTR1f);
   3313         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_PTR0f, ipv4a);
   3314     } else {
   3315 #if defined(BCM_TRIDENT3_SUPPORT)
   3316         if (soc_feature(u, soc_feature_generic_dest)) {
   3317             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DESTINATION1f);
   3318             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DESTINATION0f, ipv4a);
   3319         } else
   3320 #endif
   3321         {
   3322             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, NEXT_HOP_INDEX1f);
   3323             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, NEXT_HOP_INDEX0f, ipv4a);
   3324         }
   3325     }
   3326 
   3327     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, PRI1f);
   3328     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, PRI0f, ipv4a);
   3329 
   3330     ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPE1f);
   3331     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPE0f, ipv4a);
   3332 
   3333     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DEFAULTROUTE0f) &&
   3334         SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DEFAULTROUTE1f)) {
   3335         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src,DEFAULTROUTE1f);
   3336         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DEFAULTROUTE0f, ipv4a);
   3337     }
   3338 
   3339     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_1f)) {
   3340         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_1f);
   3341         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_0f, ipv4a);
   3342         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_MASK1f);
   3343         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_MASK0f, ipv4a);
   3344     }
   3345 
   3346     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ENTRY_TYPE1f)) {
   3347         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ENTRY_TYPE1f);
   3348         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ENTRY_TYPE0f, ipv4a);
   3349         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ENTRY_TYPE_MASK1f);
   3350         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ENTRY_TYPE_MASK0f, ipv4a);
   3351     }
   3352 
   3353     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, D_ID1f)) {
   3354         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, D_ID1f);
   3355         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, D_ID0f, ipv4a);
   3356         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, D_ID_MASK1f);
   3357         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, D_ID_MASK0f, ipv4a);
   3358     }
   3359 
   3360     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD1f)) {
   3361         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DST_DISCARD1f);
   3362         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DST_DISCARD0f, ipv4a);
   3363     }
   3364 
   3365 #if defined(BCM_TRX_SUPPORT)
   3366     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, CLASS_ID1f)) {
   3367         ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, CLASS_ID1f);
   3368         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, CLASS_ID0f, ipv4a);
   3369     }
   3370 #endif /* BCM_TRX_SUPPORT */
   3371 
   3372 #if defined(BCM_TRIDENT2_SUPPORT)
   3373     if (soc_feature(u, soc_feature_advanced_flex_counter)) {
   3374         if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, FLEX_CTR_OFFSET_MODE1f)) {
   3375             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src,
   3376                                         FLEX_CTR_OFFSET_MODE1f);
   3377             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_OFFSET_MODE0f,
   3378                                 ipv4a);
   3379             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src,
   3380                                         FLEX_CTR_POOL_NUMBER1f);
   3381             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_POOL_NUMBER0f,
   3382                                 ipv4a);
   3383             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src,
   3384                                         FLEX_CTR_BASE_COUNTER_IDX1f);
   3385             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_BASE_COUNTER_IDX0f,
   3386                                 ipv4a);
   3387         }
   3388     }
   3389 #endif
   3390 
   3391     return(SOC_E_NONE);
   3392 }
   3393 
   3394 
   3395 STATIC INLINE void
   3396 _soc_fb_lpm_state_dump(int u, soc_lpm_state_p lpm_state_ptr)
   3397 {
   3398     int curr_pfx = MAX_PFX_INDEX(u);
   3399     if (lpm_state_ptr == NULL) {
   3400         lpm_state_ptr = SOC_LPM_STATE(u);
   3401     }
   3402     while (lpm_state_ptr && curr_pfx > 0) {
   3403         LOG_CLI(("PFX = %d P = %d N = %d START = %d "
   3404                  "END = %d VENT = %d FENT = %d\n",
   3405                  curr_pfx,
   3406                  SOC_LPM_STATE_P(lpm_state_ptr, curr_pfx),
   3407                  SOC_LPM_STATE_N(lpm_state_ptr, curr_pfx),
   3408                  SOC_LPM_STATE_S(lpm_state_ptr, curr_pfx),
   3409                  SOC_LPM_STATE_E(lpm_state_ptr, curr_pfx),
   3410                  SOC_LPM_STATE_V(lpm_state_ptr, curr_pfx),
   3411                  SOC_LPM_STATE_F(lpm_state_ptr, curr_pfx)));
   3412 
   3413         curr_pfx = SOC_LPM_STATE_N(lpm_state_ptr, curr_pfx);
   3414     }
   3415 }
   3416 
   3417 void
   3418 soc_fb_lpm_state_dump(int u)
   3419 {
   3420 
   3421     if (!bsl_check(bslLayerSoc, bslSourceLpm, bslSeverityVerbose, u)) {
   3422         return;
   3423     }
   3424     _soc_fb_lpm_state_dump(u, 0);
   3425 }
   3426 
   3427 /*
   3428  *      Gets entry index offset in second half of the tcam if URPF check is ON. 
   3429  */
   3430 int soc_lpm_fb_urpf_entry_replicate_index_offset(int unit, int *offset)
   3431 {
   3432     int src_tcam_offset;  /* Defip memory size/2 urpf source lookup offset */
   3433 
   3434     if(!SOC_URPF_STATUS_GET(unit)) {
   3435         return (SOC_E_NONE);
   3436     }
   3437 
   3438     *offset = 0;
   3439 
   3440     if (soc_feature(unit, soc_feature_l3_defip_hole)) {
   3441         src_tcam_offset = (soc_mem_index_count(unit, L3_DEFIPm) >> 1);
   3442     } else if (SOC_IS_APOLLO(unit)) {
   3443         src_tcam_offset = (soc_mem_index_count(unit, L3_DEFIPm) >> 1) + 0x0400;
   3444     } else {
   3445         src_tcam_offset = (soc_mem_index_count(unit, L3_DEFIPm) >> 1);
   3446     }
   3447 
   3448 #if defined(BCM_KATANA_SUPPORT)
   3449     if (SOC_IS_KATANA(unit)) {
   3450         if (soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 0) == 1) {
   3451             /* When tcams are paired ipv4 lpm and ipv6 64b lpm
   3452              * starts at index of tcam 4. We have to add size of the
   3453              * tcam used for DIP lookup to get the urpf index */
   3454             src_tcam_offset = kt_lpm_ipv6_info[unit]->ipv6_64b.depth;
   3455         }
   3456     }
   3457 #endif
   3458 
   3459     /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
   3460      * both DIP and SIP lookup is done using only 1 L3_DEFIP entry.
   3461      * L3_DEFIP table is not divided into 2 to support URPF (For ex: Katana2).
   3462      */
   3463     if (!soc_feature(unit, soc_feature_l3_defip_advanced_lookup)) {
   3464         *offset += src_tcam_offset;
   3465     }
   3466 
   3467     return SOC_E_NONE;
   3468 }
   3469 
   3470 /*
   3471  *      Replicate entry to the second half of the tcam if URPF check is ON. 
   3472  */
   3473 static 
   3474 int _lpm_fb_urpf_entry_replicate(int u, int index, int temp_index, uint32 *e)
   3475 {
   3476     int src_tcam_offset;  /* Defip memory size/2 urpf source lookup offset */
   3477     int ipv6;             /* IPv6 entry.                                   */
   3478     uint32 mask0;         /* Mask 0 field value.                           */
   3479     uint32 mask1;         /* Mask 1 field value.                           */
   3480     int def_gw_flag;      /* Entry is default gateway.                     */ 
   3481     int rv;               /* Return type.                                  */
   3482     uint32 lpm_entry[SOC_MAX_MEM_WORDS]; /* Temporary lpm entry. */
   3483     soc_mem_t mem = L3_DEFIPm;
   3484 #if defined(BCM_TRIDENT3_SUPPORT)
   3485     int data_type0 = 0, data_type1 = 0;
   3486 #endif
   3487 
   3488     if(!SOC_URPF_STATUS_GET(u)) {
   3489         return (SOC_E_NONE);
   3490     }
   3491 
   3492     if (soc_feature(u, soc_feature_l3_defip_hole)) {
   3493          src_tcam_offset = (soc_mem_index_count(u, mem) >> 1);
   3494     } else if (SOC_IS_APOLLO(u)) {
   3495          src_tcam_offset = (soc_mem_index_count(u, mem) >> 1) + 0x0400;
   3496     } 
   3497     else {
   3498          src_tcam_offset = (soc_mem_index_count(u, mem) >> 1);
   3499     }
   3500 
   3501     ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, defip_mode0_field);
   3502 
   3503     #if defined(BCM_KATANA_SUPPORT)
   3504     if (SOC_IS_KATANA(u)) {
   3505         if (soc_property_get(u, spn_IPV6_LPM_128B_ENABLE, 0) == 1) {
   3506             /* When tcams are paired ipv4 lpm and ipv6 64b lpm
   3507              * starts at index of tcam 4. We have to add size of the
   3508              * tcam used for DIP lookup to get the urpf index */
   3509             src_tcam_offset = kt_lpm_ipv6_info[u]->ipv6_64b.depth;
   3510         }
   3511     }
   3512     #endif
   3513 
   3514     /* Reset destination discard bit. */
   3515     if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD0f)) {
   3516         /* For KT2, both dip and sip lookup is done using only 1 l3_defip entry.
   3517          * l3_defip table is not divided into 2 to support urpf. So, dest
   3518          * discard bits should not be reset in KT2. For other devices, if urpf
   3519          * is enabled, destination discard bits has to be reset since only sip
   3520          * lookup happens in the second half of L3_DEFIPm.
   3521          */
   3522         if (!soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   3523             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD0f, 0);
   3524             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD1f, 0);
   3525         }
   3526     }
   3527 
   3528     /* Set/Reset default gateway flag based on ip mask value. */
   3529     mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, IP_ADDR_MASK0f);
   3530     mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, IP_ADDR_MASK1f);
   3531 
   3532 
   3533     if (!ipv6) {
   3534         if (SOC_MEM_OPT_F32_VALID0_GET(u, L3_DEFIPm, e)) {
   3535             /* 
   3536              * For KT2, L3_DEFIP table is not divided in 2 parts to 
   3537              * support URPF unlike previous devices
   3538              * RPExf and DEFAULTROUTExf are not overlaid in KT2 
   3539              * like other devices.
   3540              */
   3541             if (!soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   3542                 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE0f, (!mask0) ? 1 : 0);
   3543             }
   3544             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e,
   3545                 DEFAULTROUTE0f, (!mask0) ? 1 : 0);
   3546 
   3547 #if defined(BCM_TRIDENT3_SUPPORT)
   3548             if (SOC_MEM_FIELD_VALID(u, L3_DEFIPm, DATA_TYPE0f)) {
   3549                 data_type0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, DATA_TYPE0f);
   3550                 /* SIP lookup for flex entries use a different data_type
   3551                  * as defined in CANCUN.Setting this only for fixed flows
   3552                  * where data_type is within the regsfile defined values */
   3553                 if (data_type0 <= 3) {
   3554                     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DATA_TYPE0f, 1);
   3555                 }
   3556             }
   3557 #endif
   3558         }
   3559         if (SOC_MEM_OPT_F32_VALID1_GET(u, L3_DEFIPm, e)) {
   3560             /* 
   3561              * For KT2, L3_DEFIP table is not divided in 2 parts to 
   3562              * support URPF unlike previous devices
   3563              * RPExf and DEFAULTROUTExf are not overlaid in KT2 
   3564              * like other devices.
   3565              */
   3566             if (!soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   3567                 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE1f, (!mask1) ? 1 : 0);
   3568             }
   3569             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e,
   3570                 DEFAULTROUTE1f, (!mask1) ? 1 : 0);
   3571 
   3572 #if defined(BCM_TRIDENT3_SUPPORT)
   3573             if (SOC_MEM_FIELD_VALID(u, L3_DEFIPm, DATA_TYPE1f)) {
   3574                 data_type1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, DATA_TYPE1f);
   3575                 /* SIP lookup for flex entries use a different data_type
   3576                  * as defined in CANCUN.Setting this only for fixed flows
   3577                  * where data_type is within the regsfile defined values */
   3578                 if (data_type1 <= 3) {
   3579                     SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DATA_TYPE1f, 1);
   3580                 }
   3581             }
   3582 #endif
   3583         }
   3584     } else {
   3585         def_gw_flag = ((!mask0) &&  (!mask1)) ? 1 : 0;
   3586 
   3587         /* 
   3588          * For KT2, L3_DEFIP table is not divided in 2 parts to 
   3589          * support URPF unlike previous devices
   3590          * RPExf and DEFAULTROUTExf are not overlaid in KT2 
   3591          * like other devices.
   3592          */
   3593         if (!soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   3594             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE0f, def_gw_flag);
   3595             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE1f, def_gw_flag);
   3596         }
   3597         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DEFAULTROUTE0f, def_gw_flag);
   3598         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DEFAULTROUTE1f, def_gw_flag);
   3599 #if defined(BCM_TRIDENT3_SUPPORT)
   3600         if (SOC_MEM_FIELD_VALID(u, L3_DEFIPm, DATA_TYPE0f)) {
   3601             data_type0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, DATA_TYPE0f);
   3602             /* SIP lookup for flex entries use a different data_type
   3603              * as defined in CANCUN.Setting this only for fixed flows
   3604              * where data_type is within the regsfile defined values */
   3605             if (data_type0 <= 3) {
   3606                 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DATA_TYPE0f, 1);
   3607                 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DATA_TYPE1f, 1);
   3608             }
   3609         }
   3610 #endif
   3611     }
   3612 
   3613     /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
   3614      * both DIP and SIP lookup is done using only 1 L3_DEFIP entry.
   3615      * L3_DEFIP table is not divided into 2 to support URPF (For ex: Katana2).
   3616      */
   3617     if (!soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   3618         index += src_tcam_offset;
   3619         if (temp_index != -1) {
   3620            temp_index += src_tcam_offset;
   3621         }
   3622     }
   3623 
   3624     /*
   3625      * In order to avoid atomicity issue, write the tcam entry to temp_index
   3626      * before writing into the actual index.
   3627      * "temp_index" is VALID only if 'lpm_atomic_write' feature is enabled.
   3628      */  
   3629     if (temp_index != -1) {
   3630         sal_memset(&lpm_entry, 0x0, sizeof(lpm_entry));
   3631         rv =  READ_L3_DEFIPm(u, MEM_BLOCK_ANY, index, &lpm_entry);
   3632         SOC_IF_ERROR_RETURN(rv);
   3633         rv =  WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, temp_index, &lpm_entry);
   3634         SOC_IF_ERROR_RETURN(rv);
   3635     }
   3636     if (SOC_IS_TRIDENT3(u)) {
   3637         soc_mem_field32_set(u, L3_DEFIPm, e, FLEX_CTR_BASE_COUNTER_IDX0f, 0);
   3638         soc_mem_field32_set(u, L3_DEFIPm, e, FLEX_CTR_BASE_COUNTER_IDX1f, 0);
   3639     }
   3640 
   3641     rv =  WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, index, e);
   3642     SOC_IF_ERROR_RETURN(rv);
   3643 
   3644     /*
   3645      * Clear temp_index
   3646      */
   3647     if (temp_index != -1) {
   3648        sal_memset(&lpm_entry, 0x0, sizeof(lpm_entry));
   3649        rv =  WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, temp_index, &lpm_entry);
   3650     } 
   3651 
   3652     return rv;
   3653 }
   3654 
   3655 /*
   3656  *      Create a slot for the new entry rippling the entries if required
   3657  */
   3658 static
   3659 int _lpm_fb_entry_shift(int u, int from_ent, int to_ent)
   3660 {
   3661     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   3662     int         rv;
   3663     uint32      rvt_index0 = 0, rvt_index1 = 0;
   3664 #ifdef FB_LPM_TABLE_CACHED
   3665     soc_mem_t mem = L3_DEFIPm;
   3666 
   3667     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   3668         mem = L3_DEFIP_LEVEL1m;
   3669     }
   3670 
   3671     SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, mem,
   3672                                        MEM_BLOCK_ANY, from_ent));
   3673 #endif /* FB_LPM_TABLE_CACHED */
   3674 
   3675     rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, e);
   3676     SOC_IF_ERROR_RETURN(rv);
   3677     LPM_HASH_INSERT(u, e, to_ent, &rvt_index0, &rvt_index1);
   3678     rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, to_ent, e);
   3679     if ((SOC_MEM_IS_VALID(u, L3_DEFIPm)) && (rv >= 0)) {
   3680         rv = _lpm_fb_urpf_entry_replicate(u, to_ent, -1, e);
   3681     }
   3682     if (rv < 0) {
   3683         LPM_HASH_REVERT(u, e, to_ent, rvt_index0, rvt_index1);
   3684     }
   3685     LPM_AVL_INSERT(u, e, to_ent);
   3686     return (rv);
   3687 }
   3688 
   3689 
   3690 /*
   3691  *      Shift prefix entries 1 entry UP, while preserving  
   3692  *      last half empty IPv4 entry if any.
   3693  */
   3694 static
   3695 int _lpm_fb_shift_pfx_up(int u, int pfx, int ipv6)
   3696 {
   3697     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   3698     int         from_ent;
   3699     int         to_ent;
   3700     uint32      v0, v1;
   3701     uint32      rvt_index0 = 0, rvt_index1 = 0;
   3702     soc_mem_t mem = L3_DEFIPm;
   3703     int rv = SOC_E_NONE;
   3704 
   3705     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   3706         mem = L3_DEFIP_LEVEL1m;
   3707     }
   3708 
   3709 
   3710     to_ent = SOC_LPM_STATE_END(u, pfx) + 1;
   3711 
   3712     /* Don't move empty prefix . */ 
   3713     if (SOC_LPM_STATE_VENT(u, pfx) == 0) {
   3714         SOC_LPM_STATE_START(u, pfx) = to_ent + 1;
   3715         SOC_LPM_STATE_END(u, pfx) = to_ent;
   3716         return (SOC_E_NONE);
   3717     }
   3718 
   3719     ipv6 = SOC_LPM_PFX_IS_V6_64(u, pfx);
   3720 
   3721     if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity) && !ipv6) {
   3722         from_ent = SOC_LPM_STATE_END(u, pfx);
   3723 #ifdef FB_LPM_TABLE_CACHED
   3724         SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, mem,
   3725                                                      MEM_BLOCK_ANY, from_ent));
   3726 #endif /* FB_LPM_TABLE_CACHED */
   3727         rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, e);
   3728         SOC_IF_ERROR_RETURN(rv);
   3729         v0 = SOC_MEM_OPT_F32_VALID0_GET(u, mem, e);
   3730         v1 = SOC_MEM_OPT_F32_VALID1_GET(u, mem, e);
   3731 
   3732         if ((v0 == 0) || (v1 == 0)) {
   3733             /* Last entry is half full -> keep it last. */
   3734             LPM_HASH_INSERT(u, e, to_ent, &rvt_index0, &rvt_index1);
   3735             rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, to_ent, e);
   3736             if ((SOC_MEM_IS_VALID(u, L3_DEFIPm)) && (rv >= 0)) {
   3737                 rv = _lpm_fb_urpf_entry_replicate(u, to_ent, -1, e);
   3738             }
   3739             if (rv < 0) {
   3740                 LPM_HASH_REVERT(u, e, to_ent, rvt_index0, rvt_index1);
   3741                 return rv;
   3742             }
   3743             LPM_AVL_INSERT(u, e, to_ent);
   3744             to_ent--;
   3745         }
   3746     }
   3747 
   3748     from_ent = SOC_LPM_STATE_START(u, pfx);
   3749     if (from_ent != to_ent) {
   3750         SOC_IF_ERROR_RETURN(_lpm_fb_entry_shift(u, from_ent, to_ent));
   3751     } 
   3752     SOC_LPM_STATE_START(u, pfx) += 1;
   3753     SOC_LPM_STATE_END(u, pfx) += 1;
   3754     return (SOC_E_NONE);
   3755 }
   3756 
   3757 /*
   3758  *      Shift prefix entries 1 entry DOWN, while preserving  
   3759  *      last half empty IPv4 entry if any.
   3760  */
   3761 static
   3762 int _lpm_fb_shift_pfx_down(int u, int pfx, int ipv6)
   3763 {
   3764     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   3765     int         from_ent;
   3766     int         to_ent;
   3767     int         prev_ent;
   3768     uint32      v0, v1;
   3769     uint32      rvt_index0 = 0, rvt_index1 = 0;
   3770     int rv = SOC_E_NONE;
   3771     soc_mem_t mem = L3_DEFIPm;
   3772 
   3773     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   3774         mem = L3_DEFIP_LEVEL1m;
   3775     }
   3776 
   3777 
   3778     to_ent = SOC_LPM_STATE_START(u, pfx) - 1;
   3779 
   3780     /* Don't move empty prefix . */ 
   3781     if (SOC_LPM_STATE_VENT(u, pfx) == 0) {
   3782         SOC_LPM_STATE_START(u, pfx) = to_ent;
   3783         SOC_LPM_STATE_END(u, pfx) = to_ent - 1;
   3784         return (SOC_E_NONE);
   3785     }
   3786 
   3787     ipv6 = SOC_LPM_PFX_IS_V6_64(u, pfx);
   3788 
   3789     if ((!ipv6) && (SOC_LPM_STATE_END(u, pfx) != SOC_LPM_STATE_START(u, pfx))) {
   3790 
   3791         from_ent = SOC_LPM_STATE_END(u, pfx);
   3792 
   3793 #ifdef FB_LPM_TABLE_CACHED
   3794         SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, mem,
   3795                                                      MEM_BLOCK_ANY, from_ent));
   3796 #endif /* FB_LPM_TABLE_CACHED */
   3797         rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, e);
   3798         SOC_IF_ERROR_RETURN(rv);
   3799         v0 = SOC_MEM_OPT_F32_VALID0_GET(u, mem, e);
   3800         v1 = SOC_MEM_OPT_F32_VALID1_GET(u, mem, e);
   3801 
   3802         if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity) && 
   3803             ((v0 == 0) || (v1 == 0))) {
   3804             /* Last entry is half full -> keep it last. */
   3805             /* Shift entry before last to start - 1 position. */
   3806             prev_ent = from_ent - 1;
   3807             SOC_IF_ERROR_RETURN(_lpm_fb_entry_shift(u, prev_ent, to_ent));
   3808 
   3809             LPM_HASH_INSERT(u, e, prev_ent, &rvt_index0, &rvt_index1);
   3810             rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, prev_ent , e);
   3811             if ((SOC_MEM_IS_VALID(u, L3_DEFIPm)) && (rv >= 0)) {
   3812                 rv = _lpm_fb_urpf_entry_replicate(u, prev_ent, -1, e);
   3813             }
   3814             if (rv < 0) {
   3815                 LPM_HASH_REVERT(u, e, prev_ent, rvt_index0, rvt_index1);
   3816                 return rv;
   3817             }
   3818             LPM_AVL_INSERT(u, e, prev_ent);
   3819         } else {
   3820             /* Last entry is full -> just shift it to start - 1  position. */
   3821             LPM_HASH_INSERT(u, e, to_ent, &rvt_index0, &rvt_index1);
   3822             rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, to_ent, e);
   3823             if ((SOC_MEM_IS_VALID(u, L3_DEFIPm)) && (rv >= 0)) {
   3824                 rv = _lpm_fb_urpf_entry_replicate(u, to_ent, -1, e);
   3825             }
   3826             if (rv < 0) {
   3827                 LPM_HASH_REVERT(u, e, to_ent, rvt_index0, rvt_index1);
   3828                 return rv;
   3829             }
   3830             LPM_AVL_INSERT(u, e, to_ent);
   3831         }
   3832 
   3833     } else  {
   3834 
   3835         from_ent = SOC_LPM_STATE_END(u, pfx);
   3836         SOC_IF_ERROR_RETURN(_lpm_fb_entry_shift(u, from_ent, to_ent));
   3837 
   3838     }
   3839 
   3840     SOC_LPM_STATE_START(u, pfx) -= 1;
   3841     SOC_LPM_STATE_END(u, pfx) -= 1;
   3842 
   3843     return (SOC_E_NONE);
   3844 }
   3845 
   3846 /*
   3847  * @name  - _lpm_entry_in_paired_tcam
   3848  * @param - unit - unit number
   3849  * @param - index - logical index into L3_DEFIP
   3850  *
   3851  * @purpose - Check if the physical index corresponding to the logical index
   3852  *            is in paired tcam 
   3853  * @returns - TRUE/FALSE
   3854  */
   3855 STATIC int
   3856 _lpm_entry_in_paired_tcam(int unit, int index) 
   3857 {
   3858     int num_tcams = 0;
   3859     int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
   3860     int new_index;
   3861     int num_ipv6_128b_entries = SOC_L3_DEFIP_INDEX_REMAP_GET(unit);
   3862     soc_mem_t mem = L3_DEFIPm;
   3863 
   3864     if (!SOC_MEM_IS_VALID(unit, L3_DEFIPm)) {
   3865         mem = L3_DEFIP_LEVEL1m;
   3866     }
   3867 
   3868 
   3869     if (index >= soc_mem_index_count(unit, mem)) {
   3870         return FALSE; 
   3871     }
   3872 
   3873     /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
   3874      * both DIP and SIP lookup is done using only 1 L3_DEFIP entry.
   3875      * L3_DEFIP table is not divided into 2 to support URPF (For ex: Katana2).
   3876      */
   3877     if (SOC_URPF_STATUS_GET(unit) &&
   3878         !soc_feature(unit, soc_feature_l3_defip_advanced_lookup)) {
   3879         new_index = soc_l3_defip_urpf_index_map(unit, 0, index); 
   3880         num_ipv6_128b_entries /= 2;
   3881     } else {
   3882         new_index = soc_l3_defip_index_map(unit, 0, index); 
   3883     } 
   3884 
   3885     num_tcams = (num_ipv6_128b_entries /  tcam_size) +
   3886                 ((num_ipv6_128b_entries % tcam_size) ? 1 : 0);
   3887 
   3888     if (new_index < num_tcams * tcam_size * 2) {
   3889         return TRUE;
   3890     }
   3891 
   3892     return FALSE;
   3893 }
   3894 
   3895 /*
   3896  * Function:
   3897  *      _lpm_free_slot_remove_empty_pfx
   3898  * Purpose:
   3899  *      Remove freed prefix from the prefix state link
   3900  * Parameters:
   3901  *      u - Device unit
   3902  *      pfx - Translated prefix (Global prefix value)
   3903  * Returns:
   3904  *      None
   3905  */  
   3906 STATIC void 
   3907 _lpm_free_slot_remove_empty_pfx(int u, int pfx)
   3908 {
   3909     int prev_pfx;
   3910     int next_pfx;
   3911 
   3912     if (pfx == MAX_PFX_INDEX(u)) {
   3913         return ;
   3914     }
   3915     
   3916     if ((SOC_LPM_STATE_VENT(u, pfx) == 0) &&
   3917         (SOC_LPM_STATE_FENT(u, pfx) == 0)) {
   3918         /* remove from the list */
   3919         prev_pfx = SOC_LPM_STATE_PREV(u, pfx); /* Always present */
   3920         next_pfx = SOC_LPM_STATE_NEXT(u, pfx);
   3921         SOC_LPM_STATE_NEXT(u, prev_pfx) = next_pfx;
   3922         if (next_pfx != -1) {
   3923             SOC_LPM_STATE_PREV(u, next_pfx) = prev_pfx;
   3924         }
   3925         SOC_LPM_STATE_NEXT(u, pfx) = -1;
   3926         SOC_LPM_STATE_PREV(u, pfx) = -1;
   3927         SOC_LPM_STATE_START(u, pfx) = -1;
   3928         SOC_LPM_STATE_END(u, pfx) = -1;
   3929     }
   3930 
   3931     return;
   3932 }
   3933 
   3934 /*
   3935  *      Create a slot for the new entry rippling the entries if required
   3936  */
   3937 STATIC
   3938 int _lpm_free_slot_create(int u, int pfx, int ipv6, void *e, int *free_slot)
   3939 {
   3940     int         prev_pfx;
   3941     int         next_pfx;
   3942     int         free_pfx;
   3943     int         curr_pfx;
   3944     int         from_ent;
   3945     uint32      v0, v1;
   3946     int         rv;
   3947     int         v6_index_in_paired_tcam = 0;
   3948     int         start_index = 0;
   3949     int         to_ent;
   3950     int         unpaired_start = -1;
   3951     int         occupied_index = -1;
   3952     uint32      entry[SOC_MAX_MEM_FIELD_WORDS];
   3953     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   3954     int num_ipv6_128b_entries = SOC_L3_DEFIP_MAX_128B_ENTRIES(u);
   3955     soc_mem_t mem = L3_DEFIPm;
   3956 
   3957     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   3958         mem = L3_DEFIP_LEVEL1m;
   3959     }
   3960 
   3961 
   3962     if ((SOC_LPM_STATE_VENT(u, pfx) == 0) && 
   3963         (SOC_LPM_STATE_FENT(u, pfx) == 0)) {
   3964         /*
   3965          * Find the  prefix position. Only prefix with valid
   3966          * entries are in the list.
   3967          * next -> high to low prefix. low to high index
   3968          * prev -> low to high prefix. high to low index
   3969          * Unused prefix length MAX_PFX_INDEX is the head of the
   3970          * list and is node corresponding to this is always
   3971          * present.
   3972          */
   3973         curr_pfx = MAX_PFX_INDEX(u);
   3974         while (SOC_LPM_STATE_NEXT(u, curr_pfx) > pfx) {
   3975             curr_pfx = SOC_LPM_STATE_NEXT(u, curr_pfx);
   3976         }
   3977         /* Insert the new prefix */
   3978         next_pfx = SOC_LPM_STATE_NEXT(u, curr_pfx);
   3979         if (next_pfx != -1) {
   3980             SOC_LPM_STATE_PREV(u, next_pfx) = pfx;
   3981         }
   3982         SOC_LPM_STATE_NEXT(u, pfx) = SOC_LPM_STATE_NEXT(u, curr_pfx);
   3983         SOC_LPM_STATE_PREV(u, pfx) = curr_pfx;
   3984         SOC_LPM_STATE_NEXT(u, curr_pfx) = pfx;
   3985 
   3986         SOC_LPM_STATE_START(u, pfx) =  SOC_LPM_STATE_END(u, curr_pfx) +
   3987                                    (SOC_LPM_STATE_FENT(u, curr_pfx) / 2) + 1;
   3988         SOC_LPM_STATE_END(u, pfx) = SOC_LPM_STATE_START(u, pfx) - 1;
   3989         SOC_LPM_STATE_VENT(u, pfx) = 0;
   3990 
   3991         if (soc_feature(u, soc_feature_l3_shared_defip_table) ||
   3992             (soc_feature(u, soc_feature_l3_kt2_shared_defip_table))) {
   3993             /* if v6, dont allow the entry to be added in paired tcam */
   3994             start_index = SOC_LPM_STATE_START(u, pfx);
   3995             if ((ipv6 != 0) && _lpm_entry_in_paired_tcam(u, start_index)) {
   3996                 /* entry location is paired tcam. 
   3997                  * so find a new slot for this prefix. 
   3998                  */
   3999                 v6_index_in_paired_tcam = 1;
   4000                 SOC_LPM_STATE_START(u, pfx) = -1;
   4001                 SOC_LPM_STATE_END(u, pfx) = -1;
   4002                 SOC_LPM_STATE_FENT(u, pfx) = 0;
   4003                 if (SOC_LPM_STATE_FENT(u, curr_pfx)) {
   4004                     /* fent = 0, index in paired tcam for V6, if prev has
   4005                      * fent, then figureout the start of unpaired tcam
   4006                      * and try to get that index
   4007                      */
   4008                     /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
   4009                      * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
   4010                      * L3_DEFIP table is not divided into 2 to support URPF.
   4011                      */
   4012                     if (SOC_URPF_STATUS_GET(u) &&
   4013                         !soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   4014                         num_ipv6_128b_entries >>= 1;
   4015                     }
   4016                     unpaired_start = (tcam_depth -
   4017                                      (num_ipv6_128b_entries % tcam_depth)) << 1;
   4018                     /* Need not check if num_ipv6_128b_entries % tcam_depth == 0
   4019                      * as _lpm_entry_in_paired_tcam will be true only if it is 
   4020                      * not zero. 
   4021                      */
   4022                     if (unpaired_start <= soc_mem_index_max(u, mem)) {
   4023                         occupied_index = SOC_LPM_STATE_END(u, curr_pfx) +
   4024                                          SOC_LPM_STATE_FENT(u, curr_pfx);
   4025                         if ((SOC_LPM_STATE_END(u, curr_pfx) < unpaired_start) &&
   4026                             (occupied_index - unpaired_start >= 0)) {
   4027                             SOC_LPM_STATE_FENT(u, pfx) = occupied_index -
   4028                                                     unpaired_start + 1;
   4029                             SOC_LPM_STATE_FENT(u, curr_pfx) -=
   4030                                 SOC_LPM_STATE_FENT(u, pfx);
   4031                             _lpm_free_slot_remove_empty_pfx(u, curr_pfx);
   4032                             SOC_LPM_STATE_START(u, pfx) = unpaired_start;
   4033                             SOC_LPM_STATE_END(u, pfx) = unpaired_start - 1;
   4034                             v6_index_in_paired_tcam = 0;
   4035                         }
   4036                     }
   4037                 }
   4038             } else {
   4039                 SOC_LPM_STATE_FENT(u, pfx) =  (SOC_LPM_STATE_FENT(u, curr_pfx) + 1) / 2;
   4040                 SOC_LPM_STATE_FENT(u, curr_pfx) -= SOC_LPM_STATE_FENT(u, pfx);
   4041                 _lpm_free_slot_remove_empty_pfx(u, curr_pfx);
   4042             }
   4043         } else {
   4044             SOC_LPM_STATE_FENT(u, pfx) =  (SOC_LPM_STATE_FENT(u, curr_pfx) + 1) / 2;
   4045             SOC_LPM_STATE_FENT(u, curr_pfx) -= SOC_LPM_STATE_FENT(u, pfx);
   4046             _lpm_free_slot_remove_empty_pfx(u, curr_pfx);
   4047         }
   4048     } else if (!ipv6) {
   4049         /* For IPv4 Check if alternate entry is free */
   4050         from_ent = SOC_LPM_STATE_START(u, pfx);
   4051         if (SOC_LPM_STATE_VENT(u, pfx) == 0) {
   4052             /* Just occupied a new entry */
   4053             SOC_LPM_STATE_VENT(u, pfx) += 1;
   4054             SOC_LPM_STATE_FENT(u, pfx) -= 1;
   4055             SOC_LPM_STATE_END(u, pfx) += 1;
   4056 #ifdef BCM_TOMAHAWK2_SUPPORT
   4057             if (soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
   4058                 *free_slot = (from_ent << 1) + 1;
   4059             } else 
   4060 #endif
   4061             {
   4062                 SOC_LPM_STATE_HFENT(u, pfx) = 1;
   4063                 *free_slot = from_ent << 1;
   4064             }
   4065             sal_memcpy(e, soc_mem_entry_null(u, mem),
   4066                        soc_mem_entry_words(u,mem) * 4);
   4067             return (SOC_E_NONE);
   4068         }
   4069         
   4070 #ifdef FB_LPM_TABLE_CACHED
   4071         if ((rv = soc_mem_cache_invalidate(u, mem,
   4072                                            MEM_BLOCK_ANY, from_ent)) < 0) {
   4073             return rv;
   4074         }
   4075 #endif /* FB_LPM_TABLE_CACHED */
   4076 
   4077         if (SOC_LPM_STATE_HFENT(u, pfx)) {
   4078            from_ent = SOC_LPM_STATE_END(u, pfx);
   4079 #ifdef FB_LPM_TABLE_CACHED
   4080            if ((rv = soc_mem_cache_invalidate(u, mem,
   4081                                            MEM_BLOCK_ANY, from_ent)) < 0) {
   4082               return rv;
   4083            }
   4084 #endif /* FB_LPM_TABLE_CACHED */
   4085            if ((rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, e)) < 0) {
   4086               return rv;
   4087            }
   4088            v0 = SOC_MEM_OPT_F32_VALID0_GET(u, mem, e);
   4089            v1 = SOC_MEM_OPT_F32_VALID1_GET(u, mem, e);
   4090 
   4091            if ((v0 == 0) || (v1 == 0)) {
   4092               *free_slot = (from_ent << 1) + ((v0 == 0) ? 0 : 1);
   4093               SOC_LPM_STATE_HFENT(u, pfx) = 0;
   4094               return(SOC_E_NONE);
   4095            }
   4096         }
   4097     }
   4098 
   4099     /* VENT[pfx] == 0 || FENT[pfx] == 0 */
   4100     free_pfx = pfx;
   4101     while (SOC_LPM_STATE_FENT(u, free_pfx) == 0) {
   4102         free_pfx = SOC_LPM_STATE_NEXT(u, free_pfx);
   4103         if (free_pfx == -1) {
   4104             /* No free entries on this side try the other side */
   4105             free_pfx = pfx;
   4106             break;
   4107         }
   4108     }
   4109     while (v6_index_in_paired_tcam == 0 && 
   4110            SOC_LPM_STATE_FENT(u, free_pfx) == 0) {
   4111         free_pfx = SOC_LPM_STATE_PREV(u, free_pfx);
   4112         if (free_pfx == -1) {
   4113             if (SOC_LPM_STATE_VENT(u, pfx) == 0) {
   4114                 /* failed to allocate entries for a newly allocated prefix.*/
   4115                 prev_pfx = SOC_LPM_STATE_PREV(u, pfx);
   4116                 next_pfx = SOC_LPM_STATE_NEXT(u, pfx);
   4117                 if (-1 != prev_pfx) {
   4118                     SOC_LPM_STATE_NEXT(u, prev_pfx) = next_pfx;
   4119                 }
   4120                 if (-1 != next_pfx) {
   4121                     SOC_LPM_STATE_PREV(u, next_pfx) = prev_pfx;
   4122                 }
   4123             }
   4124             return(SOC_E_FULL);
   4125         }
   4126     }
   4127 
   4128     /*
   4129      * Ripple entries to create free space
   4130      */
   4131     while (free_pfx > pfx) {
   4132         next_pfx = SOC_LPM_STATE_NEXT(u, free_pfx); 
   4133         if (soc_feature(u, soc_feature_l3_shared_defip_table) ||
   4134             (soc_feature(u, soc_feature_l3_kt2_shared_defip_table))) {
   4135             /*
   4136              * If the next_pfx is of type 64b V6 and if the free_pfx is in 
   4137              * paired_tcam space, we should not move the entry.
   4138              * We will move the entry from the next prefix. 
   4139              * The assumption here is order of V4 and V6 entries are independent
   4140              */
   4141             if (SOC_LPM_PFX_IS_V6_64(u, next_pfx) == TRUE) {
   4142                 to_ent = SOC_LPM_STATE_START(u, next_pfx) - 1;
   4143                 if (_lpm_entry_in_paired_tcam(u, to_ent)) {
   4144 
   4145                     /* encountered V6 prefix which cannot be moved to 
   4146                      * paired tcam. When we move a pfx, the from entry will
   4147                      * not be removed assuming that the location will be used
   4148                      * by next prefix. In this case we did not write the V6 
   4149                      * entry. so we need to delete the from entry. 
   4150                      * Ideally we should delete hash and set valid bits to 0 
   4151                      * in _lpm_fb_entry_shift for the from_entry. But in most 
   4152                      * of the cases, the from entry will be used by next prefix
   4153                      * so we can reduce one read/write of L3_DEFIP if we dont 
   4154                      * delete the entry in _lpm_fb_entry_shift
   4155                      * free_pfx contains the previous pfx from which entry was 
   4156                      * moved 
   4157                      */
   4158                      
   4159                     from_ent = SOC_LPM_STATE_END(u, free_pfx) + 1;
   4160                     rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY,
   4161                                                        from_ent, entry);
   4162                     SOC_IF_ERROR_RETURN(rv);
   4163                     SOC_MEM_OPT_F32_VALID0_SET(u, mem, entry, 0);
   4164                     SOC_MEM_OPT_F32_VALID0_SET(u, mem, entry, 0);
   4165                     SOC_IF_ERROR_RETURN(WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, 
   4166                                                         from_ent, entry));
   4167                     if (SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   4168                         SOC_IF_ERROR_RETURN(_lpm_fb_urpf_entry_replicate(u,
   4169                                         from_ent, -1, entry));
   4170                     }
   4171                     if (SOC_LPM_STATE_VENT(u, pfx) == 0) {
   4172                         /* failed to allocate entries for a newly allocated prefix.*/
   4173                         prev_pfx = SOC_LPM_STATE_PREV(u, pfx);
   4174                         next_pfx = SOC_LPM_STATE_NEXT(u, pfx);
   4175                         if (-1 != prev_pfx) {
   4176                             SOC_LPM_STATE_NEXT(u, prev_pfx) = next_pfx;
   4177                         }
   4178                         if (-1 != next_pfx) {
   4179                             SOC_LPM_STATE_PREV(u, next_pfx) = prev_pfx;
   4180                         }
   4181                     }
   4182                     return (SOC_E_FULL);
   4183                 }
   4184             }
   4185         }
   4186         SOC_IF_ERROR_RETURN(_lpm_fb_shift_pfx_down(u, next_pfx, ipv6));
   4187         SOC_LPM_STATE_FENT(u, free_pfx) -= 1;
   4188         SOC_LPM_STATE_FENT(u, next_pfx) += 1;
   4189         _lpm_free_slot_remove_empty_pfx(u, free_pfx);
   4190         free_pfx = next_pfx;
   4191     }
   4192 
   4193     while (free_pfx < pfx) {
   4194         SOC_IF_ERROR_RETURN(_lpm_fb_shift_pfx_up(u, free_pfx, ipv6));
   4195         SOC_LPM_STATE_FENT(u, free_pfx) -= 1;
   4196         prev_pfx = SOC_LPM_STATE_PREV(u, free_pfx); 
   4197         SOC_LPM_STATE_FENT(u, prev_pfx) += 1;
   4198         _lpm_free_slot_remove_empty_pfx(u, free_pfx);
   4199         free_pfx = prev_pfx;
   4200     }
   4201 
   4202     if (soc_feature(u, soc_feature_l3_shared_defip_table) ||
   4203         (soc_feature(u, soc_feature_l3_kt2_shared_defip_table))) {
   4204         if (v6_index_in_paired_tcam != 0 && free_pfx == pfx) {
   4205             /* could not find a entry in  unpaired tcam */
   4206             if (SOC_LPM_STATE_VENT(u, pfx) == 0) {
   4207                 prev_pfx = SOC_LPM_STATE_PREV(u, pfx);
   4208                 next_pfx = SOC_LPM_STATE_NEXT(u, pfx);
   4209                 if (SOC_LPM_STATE_FENT(u, pfx)) {
   4210                     SOC_LPM_STATE_START(u, pfx) =
   4211                         SOC_LPM_STATE_START(u, next_pfx) - 1;
   4212                     SOC_LPM_STATE_END(u, pfx) = SOC_LPM_STATE_START(u, pfx) - 1;
   4213                 } else {
   4214                     /* failed to allocate entries for a newly allocated prefix.*/
   4215                     if (-1 != prev_pfx) {
   4216                         SOC_LPM_STATE_NEXT(u, prev_pfx) = next_pfx;
   4217                     }
   4218                     if (-1 != next_pfx) {
   4219                         SOC_LPM_STATE_PREV(u, next_pfx) = prev_pfx;
   4220                     }
   4221                     return SOC_E_FULL;
   4222                 }
   4223             }
   4224         }
   4225     }
   4226 
   4227     SOC_LPM_STATE_VENT(u, pfx) += 1;
   4228     SOC_LPM_STATE_FENT(u, pfx) -= 1;
   4229     SOC_LPM_STATE_END(u, pfx) += 1;
   4230     if (ipv6 == 0) {
   4231        SOC_LPM_STATE_HFENT(u, pfx) = 
   4232            soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity) ? 0 : 1;
   4233     }
   4234     *free_slot = SOC_LPM_STATE_END(u, pfx) <<  ((ipv6) ? 0 : 1);
   4235 #ifdef BCM_TOMAHAWK2_SUPPORT
   4236     if (soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
   4237         *free_slot += (ipv6) ? 0 : 1; 
   4238     }
   4239 #endif
   4240     LOG_DEBUG(BSL_LS_SOC_LPM, (BSL_META_U(u,
   4241       "ADD - pfx[%d]: start:%d end:%d vent:%d fent:%d hfent:%d free_slot:%d\n\r"),
   4242              pfx, soc_lpm_state[u][pfx].start, soc_lpm_state[u][pfx].end,
   4243              soc_lpm_state[u][pfx].vent, soc_lpm_state[u][pfx].fent,
   4244              soc_lpm_state[u][pfx].hfent, *free_slot));
   4245 
   4246     sal_memcpy(e, soc_mem_entry_null(u, mem),
   4247                soc_mem_entry_words(u,mem) * 4);
   4248 
   4249     return(SOC_E_NONE);
   4250 }
   4251 
   4252 /*
   4253  *      Delete a slot and adjust entry pointers if required.
   4254  *      e - has the contents of entry at slot(useful for IPV4 only)
   4255  */
   4256 static
   4257 int _lpm_free_slot_delete(int u, int pfx, int ipv6, void *e, int slot)
   4258 {
   4259     int         from_ent;
   4260     int         to_ent;
   4261     int         temp_index = -1;
   4262     int         temp_hw_index = -1;
   4263     uint32      ef[SOC_MAX_MEM_FIELD_WORDS];
   4264     void        *et;
   4265     int         rv;
   4266     uint32      rvt_index0 = 0, rvt_index1 = 0;
   4267     uint32      e_temp[SOC_MAX_MEM_FIELD_WORDS] = {0};
   4268     int         half_entry_free = 0;
   4269     soc_mem_t mem = L3_DEFIPm;
   4270 
   4271     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   4272         mem = L3_DEFIP_LEVEL1m;
   4273     }
   4274 
   4275 
   4276     from_ent = SOC_LPM_STATE_END(u, pfx);
   4277     to_ent = slot;
   4278     if (!ipv6) { /* IPV4 */
   4279         to_ent >>= 1;
   4280 #ifdef FB_LPM_TABLE_CACHED
   4281         if ((rv = soc_mem_cache_invalidate(u, mem,
   4282                                            MEM_BLOCK_ANY, from_ent)) < 0) {
   4283             return rv;
   4284         }
   4285 #endif /* FB_LPM_TABLE_CACHED */
   4286         if ((rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, ef)) < 0) {
   4287             return rv;
   4288         }
   4289         et = (to_ent == from_ent) ? ef : e;
   4290 
   4291         half_entry_free = SOC_LPM_STATE_HFENT(u, pfx);
   4292         if (soc_feature(u, soc_feature_lpm_atomic_write)) {
   4293            if (((to_ent == from_ent) && (half_entry_free == 0)) ||
   4294                (to_ent != from_ent)) {
   4295               /* Reset half free entry value. */ 
   4296               SOC_LPM_STATE_HFENT(u, pfx) = 0;
   4297               /* Create new slot */
   4298               rv = _lpm_free_slot_create(u, pfx, ipv6, e_temp, &temp_index);
   4299               if (SOC_FAILURE(rv)) {
   4300                  return rv;
   4301               }
   4302 
   4303               /* Increment the Half entry count due to recent temp entry. */
   4304               SOC_LPM_COUNT_INC(SOC_LPM_V4_HALF_ENTRY_COUNT(u));
   4305 
   4306               temp_hw_index = temp_index >> 1;
   4307               /*
   4308                * In case, getting the free slot from higher prefix,
   4309                * entries get moved up and from_ent index gets modified.
   4310                */
   4311               if (temp_hw_index == from_ent) {
   4312                   /*
   4313                    * Check End index has half entry then 'from_ent - 1'
   4314                    * will be moved to start index and 'from_ent' moves by 1.
   4315                    */
   4316                  if (half_entry_free) {
   4317                     if ((from_ent - 1) == to_ent) {
   4318                        to_ent = SOC_LPM_STATE_START(u, pfx);
   4319                     }
   4320                     from_ent = temp_hw_index - 1;
   4321                  } else {
   4322                     if (to_ent == from_ent) {
   4323                        to_ent = SOC_LPM_STATE_START(u, pfx);
   4324                     }
   4325                     from_ent = SOC_LPM_STATE_END(u, pfx) - 1;
   4326                     rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, ef);
   4327                     if (SOC_FAILURE(rv)) {
   4328                        LOG_ERROR(BSL_LS_SOC_LPM, (BSL_META_U(u,
   4329                           "Failed to read entry from index:%d\n\r"), from_ent));
   4330                        return SOC_E_INTERNAL;
   4331                     }
   4332                  }
   4333               }
   4334 
   4335               if (slot & 1) {
   4336                  rv = soc_fb_lpm_ip4entry0_to_0(u, e, e_temp, PRESERVE_HIT);
   4337               } else {
   4338                  rv = soc_fb_lpm_ip4entry1_to_0(u, e, e_temp, PRESERVE_HIT);
   4339               }
   4340               SOC_IF_ERROR_RETURN(rv);
   4341 
   4342               /* Write left over original entry to new slot 'temp_index' */ 
   4343               rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, temp_hw_index, e_temp);
   4344               SOC_IF_ERROR_RETURN(rv);
   4345 
   4346               if (to_ent != from_ent) {
   4347                  /* Copy end slot entry to temp buffer */
   4348                  if (half_entry_free) {
   4349                     rv = soc_fb_lpm_ip4entry0_to_1(u, ef, e_temp, PRESERVE_HIT);
   4350                  } else {
   4351                     rv = soc_fb_lpm_ip4entry1_to_1(u, ef, e_temp, PRESERVE_HIT);
   4352                  }                 
   4353                  SOC_IF_ERROR_RETURN(rv);
   4354               }
   4355            } else {
   4356               /* In case of single entry. */
   4357               SOC_LPM_STATE_VENT(u, pfx) -= 1;
   4358               SOC_LPM_STATE_FENT(u, pfx) += 1;
   4359               SOC_LPM_STATE_END(u, pfx) -= 1;
   4360            }
   4361 
   4362            /*
   4363             *  Write temp buffer (left over original entry + adjusted end slot)
   4364             *  to the original entry.
   4365             */
   4366            LPM_HASH_INSERT(u, e_temp, to_ent, &rvt_index0, &rvt_index1);
   4367            rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, to_ent, e_temp);
   4368            if ((SOC_MEM_IS_VALID(u, L3_DEFIPm)) && (SOC_SUCCESS(rv))) {
   4369               rv = _lpm_fb_urpf_entry_replicate(u, to_ent, temp_hw_index, e_temp);
   4370               if (SOC_FAILURE(rv)) {
   4371                  LPM_HASH_REVERT(u, e_temp, to_ent, rvt_index0, rvt_index1);
   4372                  return rv;
   4373               }
   4374            }
   4375            LPM_AVL_INSERT(u, e_temp, to_ent);
   4376 
   4377            /* Update END slot */ 
   4378            if (to_ent != from_ent) {
   4379               sal_memset(e_temp, 0x0, sizeof(e_temp));
   4380               if (half_entry_free == 0) {
   4381                  rv = soc_fb_lpm_ip4entry0_to_0(u, ef, e_temp, PRESERVE_HIT);
   4382                  SOC_IF_ERROR_RETURN(rv);
   4383 
   4384                  /* Write temp buffer to new temp slot */
   4385                  rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, temp_hw_index, e_temp);
   4386                  SOC_IF_ERROR_RETURN(rv);
   4387               } else {
   4388                  /* Remove End Slot */
   4389                  SOC_LPM_STATE_VENT(u, pfx) -= 1;
   4390                  SOC_LPM_STATE_FENT(u, pfx) += 1;
   4391                  SOC_LPM_STATE_END(u, pfx) -= 1;
   4392               }
   4393               /* Write temp buffer to End slot */ 
   4394               LPM_HASH_INSERT(u, e_temp, from_ent, &rvt_index0, &rvt_index1);
   4395               rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, e_temp);
   4396               if ((SOC_MEM_IS_VALID(u, L3_DEFIPm)) && (SOC_SUCCESS(rv))) {
   4397                  rv = _lpm_fb_urpf_entry_replicate(u, from_ent, temp_hw_index, e_temp);
   4398               }
   4399 
   4400               if (SOC_FAILURE(rv)) {
   4401                  LPM_HASH_REVERT(u, e_temp, from_ent, rvt_index0, rvt_index1);
   4402                  return rv;
   4403               }
   4404               LPM_AVL_INSERT(u, e_temp, from_ent);
   4405            }
   4406           
   4407            if (temp_index != -1) {
   4408               /* Delete temp slot */
   4409               SOC_LPM_STATE_VENT(u, pfx) -= 1;
   4410               SOC_LPM_STATE_FENT(u, pfx) += 1;
   4411               SOC_LPM_STATE_END(u, pfx) -= 1;
   4412               /* Decrement the global Half entry count due to recent temp entry. */
   4413               SOC_LPM_COUNT_DEC(SOC_LPM_V4_HALF_ENTRY_COUNT(u));
   4414 
   4415               sal_memcpy(e_temp, soc_mem_entry_null(u, mem),
   4416                          soc_mem_entry_words(u,mem) * 4);
   4417               /* Write temp buffer to End slot */ 
   4418               rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, temp_hw_index, e_temp);
   4419               SOC_IF_ERROR_RETURN(rv);
   4420            }
   4421       
   4422            if (half_entry_free) {
   4423               /* Remaining half entry got deleted. Decrement half entry count.*/
   4424               SOC_LPM_COUNT_DEC(SOC_LPM_V4_HALF_ENTRY_COUNT(u));
   4425            } else {
   4426               /* Incremented half entry. Created after deleting existing half.*/
   4427               SOC_LPM_COUNT_INC(SOC_LPM_V4_HALF_ENTRY_COUNT(u));
   4428            }
   4429         } else {
   4430            if (SOC_MEM_OPT_F32_VALID1_GET(u, mem, ef)) {
   4431                if (slot & 1) {
   4432                    rv = soc_fb_lpm_ip4entry1_to_1(u, ef, et, PRESERVE_HIT);
   4433                } else {
   4434                    rv = soc_fb_lpm_ip4entry1_to_0(u, ef, et, PRESERVE_HIT);
   4435                }
   4436                SOC_MEM_OPT_F32_VALID1_SET(u, mem, ef, 0);
   4437                /* first half of full entry is deleted, generating half entry.*/
   4438                if (((soc_feature(u, soc_feature_l3_shared_defip_table)) ||
   4439                    (soc_feature(u, soc_feature_shared_defip_stat_support))) && 
   4440                    !(soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity))) {
   4441                    SOC_LPM_COUNT_INC(SOC_LPM_V4_HALF_ENTRY_COUNT(u));
   4442                }
   4443 #ifdef BCM_TOMAHAWK2_SUPPORT               
   4444                if (soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
   4445                    SOC_LPM_STATE_VENT(u, pfx) -= 1;
   4446                    SOC_LPM_STATE_FENT(u, pfx) += 1;
   4447                    SOC_LPM_STATE_END(u, pfx) -= 1;
   4448                }
   4449 #endif               
   4450            } else {
   4451                if (slot & 1) {
   4452                    rv = soc_fb_lpm_ip4entry0_to_1(u, ef, et, PRESERVE_HIT);
   4453                } else {
   4454                    rv = soc_fb_lpm_ip4entry0_to_0(u, ef, et, PRESERVE_HIT);
   4455                }
   4456                SOC_MEM_OPT_F32_VALID0_SET(u, mem, ef, 0);
   4457                /* Remaining half entry got deleted. Decrement half entry count.*/ 
   4458                if ((soc_feature(u, soc_feature_l3_shared_defip_table)) ||
   4459                    (soc_feature(u, soc_feature_shared_defip_stat_support))) {
   4460                    SOC_LPM_COUNT_DEC(SOC_LPM_V4_HALF_ENTRY_COUNT(u));
   4461                } 
   4462                SOC_LPM_STATE_VENT(u, pfx) -= 1;
   4463                SOC_LPM_STATE_FENT(u, pfx) += 1;
   4464                SOC_LPM_STATE_END(u, pfx) -= 1;
   4465            }
   4466 
   4467            if (to_ent != from_ent) {
   4468                LPM_HASH_INSERT(u, et, to_ent, &rvt_index0, &rvt_index1);
   4469                if ((rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, to_ent, et)) < 0) {
   4470                    LPM_HASH_REVERT(u, et, to_ent, rvt_index0, rvt_index1);
   4471                    return rv;
   4472                }
   4473                if (SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   4474                    if ((rv = _lpm_fb_urpf_entry_replicate(u, to_ent, -1, et)) < 0) {
   4475                        LPM_HASH_REVERT(u, et, to_ent, rvt_index0, rvt_index1);
   4476                        return rv;
   4477                    }
   4478                }
   4479                LPM_AVL_INSERT(u, et, to_ent);
   4480            }
   4481            LPM_HASH_INSERT(u, ef, from_ent, &rvt_index0, &rvt_index1);
   4482            if ((rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, ef)) < 0) {
   4483                LPM_HASH_REVERT(u, ef, from_ent, rvt_index0, rvt_index1);
   4484                return rv;
   4485            }
   4486            if (SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   4487                if ((rv = _lpm_fb_urpf_entry_replicate(u, from_ent, -1, ef)) < 0) {
   4488                    LPM_HASH_REVERT(u, ef, from_ent, rvt_index0, rvt_index1);
   4489                    return rv;
   4490                }
   4491            }
   4492            LPM_AVL_INSERT(u, ef, from_ent);
   4493         }
   4494      
   4495         /* Update half entry for the given prefix */        
   4496         if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
   4497             SOC_LPM_STATE_HFENT(u, pfx) = (half_entry_free) ? 0 : 1;
   4498         }
   4499         LOG_DEBUG(BSL_LS_SOC_LPM, (BSL_META_U(u,
   4500           "DEL - pfx[%d]: start:%d end:%d vent:%d fent:%d hfent:%d slot:%d\n\r"),
   4501              pfx, soc_lpm_state[u][pfx].start, soc_lpm_state[u][pfx].end,
   4502              soc_lpm_state[u][pfx].vent, soc_lpm_state[u][pfx].fent,
   4503              soc_lpm_state[u][pfx].hfent, slot));
   4504 
   4505     } else { /* IPV6 */
   4506         SOC_LPM_STATE_VENT(u, pfx) -= 1;
   4507         SOC_LPM_STATE_FENT(u, pfx) += 1;
   4508         SOC_LPM_STATE_END(u, pfx) -= 1;
   4509         if (to_ent != from_ent) {
   4510 #ifdef FB_LPM_TABLE_CACHED
   4511             if ((rv = soc_mem_cache_invalidate(u, mem,
   4512                                                MEM_BLOCK_ANY, from_ent)) < 0) {
   4513                 return rv;
   4514             }
   4515 #endif /* FB_LPM_TABLE_CACHED */
   4516             if ((rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, ef)) < 0) {
   4517                 return rv;
   4518             }
   4519             LPM_HASH_INSERT(u, ef, to_ent, &rvt_index0, &rvt_index1);
   4520             if ((rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, to_ent, ef)) < 0) {
   4521                 LPM_HASH_REVERT(u, ef, to_ent, rvt_index0, rvt_index1);
   4522                 return rv;
   4523             }
   4524             if (SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   4525                 if ((rv = _lpm_fb_urpf_entry_replicate(u, to_ent, -1, ef)) < 0) {
   4526                     LPM_HASH_REVERT(u, ef, to_ent, rvt_index0, rvt_index1);
   4527                     return rv;
   4528                 }
   4529             }
   4530             LPM_AVL_INSERT(u, ef, to_ent);
   4531         }
   4532 
   4533         sal_memcpy(ef, soc_mem_entry_null(u, mem),
   4534                    soc_mem_entry_words(u,mem) * 4);
   4535         LPM_HASH_INSERT(u, ef, from_ent, &rvt_index0, &rvt_index1);
   4536         if ((rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, ef)) < 0) {
   4537             LPM_HASH_REVERT(u, ef, from_ent, rvt_index0, rvt_index1);
   4538             return rv;
   4539         }
   4540         if (SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   4541             if ((rv = _lpm_fb_urpf_entry_replicate(u, from_ent, -1, ef)) < 0) {
   4542                 LPM_HASH_REVERT(u, ef, from_ent, rvt_index0, rvt_index1);
   4543                 return rv;
   4544             }
   4545         }
   4546         LPM_AVL_INSERT(u, ef, from_ent);
   4547     }
   4548 
   4549     if ((SOC_LPM_STATE_VENT(u, pfx) == 0) &&
   4550         (SOC_LPM_STATE_FENT(u, pfx) == 0)) {
   4551         _lpm_free_slot_remove_empty_pfx(u, pfx);
   4552     }
   4553 
   4554     return(rv);
   4555 }
   4556 
   4557 
   4558 /*
   4559  * Function:
   4560  *      _soc_fb_lpm_vrf_get
   4561  * Purpose:
   4562  *      Service routine used to translate hw specific vrf id to API format.
   4563  * Parameters:
   4564  *      unit      - (IN)SOC unit number.
   4565  *      lpm_entry - (IN)Route info buffer from hw.
   4566  *      vrf_id    - (OUT)Virtual router id.
   4567  * Returns:
   4568  *      BCM_E_XXX
   4569  */
   4570 int
   4571 soc_fb_lpm_vrf_get(int unit, void *lpm_entry, int *vrf)
   4572 {
   4573     int vrf_id;
   4574 
   4575 #if defined(BCM_TOMAHAWK3_SUPPORT)
   4576     if (!SOC_MEM_IS_VALID(unit, L3_DEFIPm)) {
   4577         uint32 _key_data[2] = {0, 0};
   4578         int global_low = 0, vrf_id_mask;
   4579         SOC_TH3_MEM_OPT_F64_GET(unit, L3_DEFIP_LEVEL1m, lpm_entry, KEY0f,_key_data);
   4580         vrf_id = soc_format_field32_get(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, VRF_IDf);
   4581         SOC_TH3_MEM_OPT_F64_GET(unit, L3_DEFIP_LEVEL1m, lpm_entry, MASK0f,_key_data);
   4582         vrf_id_mask = soc_format_field32_get(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, VRF_IDf);
   4583         SOC_TH3_MEM_OPT_F64_GET(unit, L3_DEFIP_LEVEL1m, lpm_entry, FIXED_DATA0f,_key_data);
   4584         global_low = soc_format_field32_get(unit, FIXED_DATAfmt, _key_data, SUB_DB_PRIORITYf);
   4585         if (global_low == 2) {
   4586            global_low = 1;
   4587         } else {
   4588            global_low = 0;
   4589         }
   4590         if (vrf_id_mask) {
   4591             *vrf = vrf_id;
   4592         } else if (SOC_VRF_MAX(unit) == vrf_id) {
   4593             *vrf = SOC_L3_VRF_GLOBAL;
   4594         } else {
   4595             *vrf = SOC_L3_VRF_OVERRIDE;
   4596             if (global_low) {
   4597                 *vrf = SOC_L3_VRF_GLOBAL;
   4598             }
   4599         }
   4600         return (SOC_E_NONE);
   4601     }
   4602 #endif
   4603 
   4604     /* Get Virtual Router id if supported. */
   4605     if (SOC_MEM_OPT_FIELD_VALID(unit, L3_DEFIPm, VRF_ID_MASK0f)){
   4606         vrf_id = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VRF_ID_0f);
   4607 
   4608         /* Special vrf's handling. */
   4609         if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f)) {
   4610             *vrf = vrf_id;    
   4611         } else if (SOC_VRF_MAX(unit) == vrf_id) {
   4612             *vrf = SOC_L3_VRF_GLOBAL;
   4613         } else {
   4614             *vrf = SOC_L3_VRF_OVERRIDE;    
   4615             if (SOC_MEM_OPT_FIELD_VALID(unit, L3_DEFIPm, GLOBAL_ROUTE0f)) {
   4616                 if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f)) {
   4617                     *vrf = SOC_L3_VRF_GLOBAL; 
   4618                 }
   4619             }
   4620         }
   4621     } else {
   4622         /* No vrf support on this device. */
   4623         *vrf = SOC_L3_VRF_DEFAULT;
   4624     }
   4625     return (SOC_E_NONE);
   4626 }
   4627 
   4628 STATIC int
   4629 _soc_fb_lpm_prefix_get_by_len(int u, int ipv6, int vrf_type, int len, int *pfx, int mc)
   4630 {
   4631     int         pfx_len = len;
   4632     int         n = 0, d = MAX_LPM_ZONE(u);
   4633 
   4634     if (ipv6) {
   4635         if (!(soc_feature(u, soc_feature_l3_shared_defip_table) ||
   4636             (soc_feature(u, soc_feature_l3_kt2_shared_defip_table)))) {
   4637             /*
   4638              * if using shared defip table, 64B V6 addresses have lower
   4639              * prefix length than V4 address. This is because, V4 entries 
   4640              * can be added to the paired tcam but not 64B V6 addresses.
   4641              * So V4 entries need to occupy the lower addresses to be contigous 
   4642              * in software.
   4643              */     
   4644          
   4645             pfx_len += IPV6_PFX_ZERO; /* First 33 are for IPV4 addresses */
   4646         }
   4647     } else {
   4648         if (soc_feature(u, soc_feature_l3_shared_defip_table) ||
   4649             (soc_feature(u, soc_feature_l3_kt2_shared_defip_table))) {
   4650             /*
   4651              * V4 prefixes should be at lower indices that 64B prefixes
   4652              * as V4 entries can be added to the paired tcam as well.
   4653              * The max V4 prefix length is 295.
   4654              * Max 64B prefix length is 262.
   4655              */
   4656             pfx_len += IPV4_PFX_ZERO(u);
   4657         } 
   4658     }
   4659 
   4660     switch (vrf_type) { 
   4661     case SOC_L3_VRF_GLOBAL:
   4662         n = 0;
   4663         break;
   4664     case SOC_L3_VRF_OVERRIDE:
   4665         n = 2;
   4666         break;
   4667     default:
   4668         n = 1;
   4669         break;
   4670     }
   4671 
   4672     if (soc_feature(u, soc_feature_td3_lpm_ipmc_war) && mc) {
   4673         n += 3;
   4674     }
   4675 
   4676     *pfx = pfx_len + n * (MAX_PFX_ENTRIES(u) / d);
   4677 
   4678     return (SOC_E_NONE);
   4679 }
   4680 
   4681 
   4682 /*
   4683  * _soc_fb_lpm_prefix_length_get (Extract vrf weighted  prefix lenght from the 
   4684  * hw entry based on ip, mask & vrf)
   4685  */
   4686 STATIC int
   4687 _soc_fb_lpm_prefix_length_get(int u, void *entry, int *pfx_len) 
   4688 {
   4689     int         pfx;
   4690     int         rv;
   4691     int         ipv6;
   4692     uint32      ipv4a = 0;
   4693     int         vrf_id;
   4694     int         mc = 0;
   4695 
   4696 #if defined(BCM_TRIDENT3_SUPPORT)
   4697     soc_mem_t   mem = L3_DEFIPm;
   4698 #endif
   4699   
   4700 #if defined(BCM_TOMAHAWK3_SUPPORT)
   4701     uint32 _key_data[2] = {0, 0};
   4702 #endif
   4703 
   4704 #ifdef BCM_TRIDENT3_SUPPORT
   4705     uint32      key_type;
   4706 
   4707     if (soc_mem_field_valid(u, mem, KEY_TYPE0f)) {
   4708         key_type = soc_mem_field32_get(u, mem, entry, KEY_TYPE0f);
   4709     } else {
   4710         key_type = 0;
   4711     }
   4712 
   4713     if (soc_mem_field_valid(u, mem, DATA_TYPE0f)) {
   4714         mc = (soc_mem_field32_get(u, mem, entry, DATA_TYPE0f) == 2);
   4715     }
   4716 
   4717     if (soc_feature(u, soc_feature_flex_flow) &&
   4718         BCMI_LPM_FLEX_VIEW(key_type)) {
   4719 
   4720             SOC_IF_ERROR_RETURN(
   4721                  soc_td3_lpm_flex_prefix_length_get(u, entry,
   4722                                          &ipv6, &vrf_id, &pfx, key_type));
   4723     }
   4724     else
   4725 #endif
   4726     {
   4727 #if defined(BCM_TOMAHAWK3_SUPPORT)
   4728         if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   4729             SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry, KEY0f,_key_data);
   4730             ipv6 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf);
   4731             SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry, MASK0f,_key_data);
   4732             ipv4a = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);
   4733         } else 
   4734 #endif
   4735         {
   4736             ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, defip_mode0_field);
   4737             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f);
   4738         }
   4739 
   4740         if (ipv6) {
   4741             if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
   4742                 return(rv);
   4743             }
   4744             if (SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   4745                 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK1f);
   4746             }
   4747 #if defined(BCM_TOMAHAWK3_SUPPORT)
   4748             else {
   4749                 SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry, MASK1f,_key_data);
   4750                 ipv4a = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);
   4751             }
   4752 #endif
   4753             if (pfx) {
   4754                 if (ipv4a != 0xffffffff)  {
   4755                     return(SOC_E_PARAM);
   4756                 }
   4757                 pfx += 32;
   4758             } else {
   4759                 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
   4760                     return(rv);
   4761                 }
   4762             }
   4763         } else {
   4764 #if defined(BCM_TOMAHAWK3_SUPPORT)
   4765             if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   4766                 SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry, MASK0f,_key_data);
   4767                 ipv4a = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);
   4768             } else
   4769 #endif
   4770             {
   4771                 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f);
   4772             }
   4773             if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) {
   4774                 return(rv);
   4775             }
   4776         }
   4777 
   4778         SOC_IF_ERROR_RETURN(soc_fb_lpm_vrf_get(u, entry, &vrf_id));
   4779     }
   4780 
   4781     return _soc_fb_lpm_prefix_get_by_len(u, ipv6, vrf_id, pfx, pfx_len, mc);
   4782 }
   4783 
   4784 
   4785 /*
   4786  * _soc_fb_lpm_match (Exact match for the key. Will match both IP address
   4787  * and mask)
   4788  */
   4789 static
   4790 int
   4791 _soc_fb_lpm_match(int u,
   4792                void *key_data,
   4793                void *e,         /* return entry data if found */
   4794                int *index_ptr,  /* return key location */
   4795                int *pfx_len,    /* Key prefix length. vrf + 32 + prefix len for IPV6*/
   4796                int *ipv6)       /* Entry is ipv6. */
   4797 {
   4798     int         rv;
   4799     int         v6;
   4800     int         key_index;
   4801     int         pfx = 0;
   4802 
   4803 #if defined(BCM_TOMAHAWK3_SUPPORT)
   4804     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   4805         uint32 _key_data[2] = {0,0};
   4806         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, key_data, KEY0f,_key_data);
   4807         v6 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf);
   4808         if (v6) {
   4809             SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, key_data, KEY1f,_key_data);
   4810             v6 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf);
   4811             if (!v6) {
   4812                 return (SOC_E_PARAM);
   4813             }
   4814         }
   4815     } else
   4816 #endif
   4817     {
   4818 
   4819         v6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, defip_mode0_field);
   4820 
   4821         if (v6) {
   4822             if (!(v6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, defip_mode1_field))) {
   4823                 return (SOC_E_PARAM);
   4824             }
   4825         }
   4826     }
   4827     *ipv6 = v6;
   4828 
   4829     /* Calculate vrf weighted prefix lengh. */
   4830     _soc_fb_lpm_prefix_length_get(u, key_data, &pfx); 
   4831     *pfx_len = pfx; 
   4832 
   4833 #ifdef FB_LPM_HASH_SUPPORT
   4834     if (LPM_HASH_LOOKUP(u, key_data, pfx, &key_index) == SOC_E_NONE) {
   4835         *index_ptr = key_index;
   4836         if ((rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY,
   4837                          (*ipv6) ? *index_ptr : (*index_ptr >> 1), e)) < 0) {
   4838             return rv;
   4839         }
   4840 #ifndef  FB_LPM_CHECKER_ENABLE
   4841         return(SOC_E_NONE);
   4842 #endif
   4843     } else {
   4844 #ifndef  FB_LPM_CHECKER_ENABLE
   4845         return(SOC_E_NOT_FOUND);
   4846 #endif
   4847     }
   4848 #endif /* FB_LPM_HASH_SUPPORT */
   4849 
   4850 #if defined(FB_LPM_AVL_SUPPORT)
   4851     if (LPM_AVL_LOOKUP(u, key_data, pfx, &key_index) == SOC_E_NONE) {
   4852 #ifdef  FB_LPM_CHECKER_ENABLE
   4853         if (*index_ptr != key_index) {
   4854             LOG_ERROR(BSL_LS_SOC_LPM,
   4855                       (BSL_META_U(u,
   4856                                   "\nsoc_fb_lpm_locate: HASH %d AVL %d\n"), *index_ptr, key_index));
   4857         }
   4858         assert(*index_ptr == key_index);
   4859 #endif
   4860         *index_ptr = key_index;
   4861         if ((rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY,
   4862                          (*ipv6) ? *index_ptr : (*index_ptr >> 1), e)) < 0) {
   4863             return rv;
   4864         }
   4865         return(SOC_E_NONE);
   4866     } else {
   4867         return(SOC_E_NOT_FOUND);
   4868     }
   4869 #endif /* FB_LPM_AVL_SUPPORT */
   4870 }
   4871 
   4872 int soc_fb_lpm_tcam_pair_count_get(int u, int *tcam_pair_count)
   4873 {
   4874     int num_ipv6_128b_entries;
   4875     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   4876 
   4877     if (tcam_pair_count == NULL) {
   4878         return SOC_E_PARAM;
   4879     }
   4880 
   4881     num_ipv6_128b_entries =  SOC_L3_DEFIP_MAX_128B_ENTRIES(u);
   4882     if (num_ipv6_128b_entries) {
   4883         *tcam_pair_count = (num_ipv6_128b_entries / tcam_depth) +
   4884                           ((num_ipv6_128b_entries % tcam_depth) ? 1 : 0);
   4885     } else {
   4886         *tcam_pair_count = 0;
   4887     }
   4888     
   4889     return SOC_E_NONE;
   4890 }
   4891 
   4892 STATIC int 
   4893 _soc_lpm_max_v4_route_get(int u, int paired, uint16 *entries)
   4894 {
   4895     int is_reserved = 0;
   4896     int paired_table_size = 0;
   4897     int defip_table_size = 0;
   4898     int max_v6_entries = SOC_L3_DEFIP_MAX_128B_ENTRIES(u);
   4899     soc_mem_t mem = L3_DEFIPm;
   4900 
   4901     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   4902         mem = L3_DEFIP_LEVEL1m;
   4903     }
   4904 
   4905     if (soc_feature(u, soc_feature_l3_lpm_128b_entries_reserved)) {
   4906         is_reserved = 1;
   4907     }
   4908 
   4909     if (!paired && !soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
   4910         /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
   4911          * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
   4912          * L3_DEFIP table is not divided into 2 to support URPF.
   4913          */
   4914         if (SOC_URPF_STATUS_GET(u) &&
   4915             !soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   4916             *entries = (soc_mem_index_count(u, mem));
   4917         } else {
   4918             *entries = (soc_mem_index_count(u, mem) << 1);
   4919         }
   4920         return SOC_E_NONE;
   4921     }
   4922 
   4923     if (paired && !soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
   4924         *entries = 0;
   4925         return SOC_E_NONE;
   4926     }
   4927 
   4928     SOC_IF_ERROR_RETURN(soc_fb_lpm_table_sizes_get(u, &paired_table_size, 
   4929                                                    &defip_table_size));
   4930     /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
   4931      * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
   4932      * L3_DEFIP table is not divided into 2 to support URPF.
   4933      */
   4934     if (SOC_URPF_STATUS_GET(u) &&
   4935         !soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   4936         max_v6_entries >>= 1;
   4937     }
   4938     if (paired) {
   4939         if (is_reserved) {
   4940             *entries = paired_table_size - (max_v6_entries << 1);
   4941         } else {
   4942             *entries = paired_table_size;
   4943         }
   4944     } else {
   4945         *entries = defip_table_size;
   4946     }
   4947     *entries <<= 1;
   4948     return SOC_E_NONE;
   4949 }
   4950 
   4951 STATIC int 
   4952 _soc_lpm_max_64bv6_route_get(int u, int paired, uint16 *entries)
   4953 {
   4954     int is_reserved = 0;
   4955     int paired_table_size = 0;
   4956     int defip_table_size = 0;
   4957     int tcam_pair_count = 0;
   4958     int max_pair_count = 0;
   4959     int max_v6_entries = SOC_L3_DEFIP_MAX_128B_ENTRIES(u);
   4960     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   4961     int max_tcams = SOC_L3_DEFIP_MAX_TCAMS_GET(u);
   4962 
   4963     if (soc_feature(u, soc_feature_l3_lpm_128b_entries_reserved)) {
   4964         is_reserved = 1;
   4965     }
   4966 
   4967     if (!paired) {
   4968         /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
   4969          * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
   4970          * L3_DEFIP table is not divided into 2 to support URPF.
   4971          */
   4972         if (SOC_URPF_STATUS_GET(u) &&
   4973             !soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   4974             max_v6_entries >>= 1;
   4975             tcam_pair_count = (max_v6_entries / tcam_depth) + 
   4976                               (max_v6_entries % tcam_depth ? 1 : 0);
   4977             max_pair_count = max_tcams >> 2;
   4978             *entries = ((max_pair_count - tcam_pair_count) * tcam_depth);
   4979         } else {
   4980             tcam_pair_count = (max_v6_entries / tcam_depth) + 
   4981                               (max_v6_entries % tcam_depth ? 1 : 0);
   4982             max_pair_count = max_tcams >> 1;
   4983             *entries = ((max_pair_count - tcam_pair_count) * tcam_depth);
   4984         }
   4985         *entries <<= 1;
   4986         return SOC_E_NONE;
   4987     }
   4988 
   4989     if (paired && soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
   4990         SOC_IF_ERROR_RETURN(soc_fb_lpm_table_sizes_get(u, &paired_table_size, 
   4991                                                        &defip_table_size));
   4992         /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
   4993          * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
   4994          * L3_DEFIP table is not divided into 2 to support URPF.
   4995          */
   4996         if (SOC_URPF_STATUS_GET(u) &&
   4997             !soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   4998             max_v6_entries >>= 1;
   4999         }
   5000         *entries = (paired_table_size >> 1);
   5001         if (is_reserved) {
   5002             *entries -= (max_v6_entries);
   5003         }
   5004         return SOC_E_NONE;
   5005     }
   5006     *entries = 0;
   5007     return SOC_E_NONE;
   5008 }
   5009 
   5010 STATIC int
   5011 _soc_lpm_max_128bv6_route_get(int u, uint16 *entries)
   5012 {
   5013     int is_reserved = 0;
   5014     int paired_table_size = 0;
   5015     int defip_table_size = 0;
   5016     int max_v6_entries = SOC_L3_DEFIP_MAX_128B_ENTRIES(u);
   5017 
   5018     if (soc_feature(u, soc_feature_l3_lpm_128b_entries_reserved)) {
   5019         is_reserved = 1;
   5020     }
   5021 
   5022     if (!soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
   5023         /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
   5024          * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
   5025          * L3_DEFIP table is not divided into 2 to support URPF.
   5026          */
   5027         if (SOC_URPF_STATUS_GET(u) &&
   5028             !soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   5029             max_v6_entries >>= 1;
   5030         }
   5031         *entries = max_v6_entries;
   5032         return SOC_E_NONE;
   5033     }
   5034 
   5035     SOC_IF_ERROR_RETURN(soc_fb_lpm_table_sizes_get(u, &paired_table_size, 
   5036                                                    &defip_table_size));
   5037     /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
   5038      * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
   5039      * L3_DEFIP table is not divided into 2 to support URPF.
   5040      */
   5041     if (SOC_URPF_STATUS_GET(u) &&
   5042         !soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   5043         max_v6_entries >>= 1;
   5044     }
   5045     if (is_reserved) {
   5046         *entries = max_v6_entries;
   5047     } else {
   5048         *entries = paired_table_size >> 1;
   5049     }
   5050     return SOC_E_NONE;
   5051 }
   5052 
   5053 /*
   5054  * Function:
   5055  *      soc_fb_lpm_state_config
   5056  * Purpose:
   5057  *      Config LPM prefix state table by property
   5058  * Parameters:
   5059  *      u - Device unit
   5060  *      ipv6_64_depth - L3_DEFIP memory table depth
   5061  *      start   - start memory index to configure
   5062  * Returns:
   5063  *      SOC_E_NONE
   5064  */ 
   5065 int
   5066 soc_fb_lpm_state_config(int u, int ipv6_64_depth, int start)
   5067 {
   5068     int i;
   5069     int pfx, curr_pfx, next_pfx, prev_pfx;
   5070     int ipver, vrf_type, plen, entry_number, max_pfx_number;
   5071     int entry_total_count = 0;
   5072     char *cfg_str;
   5073     char sub_str[128];
   5074 
   5075     char *tokstr;
   5076     char *ipver_str, *vrf_str, *len_str, *num_str;
   5077 
   5078 #define MAX_PFX_CONF_NUM    64
   5079 
   5080     if (SOC_WARM_BOOT(u)) {
   5081         return SOC_E_NONE;
   5082     }
   5083     
   5084     if (soc_property_get(u, spn_LPM_LAYOUT_PREFIX_ENABLE, 0) == FALSE) {
   5085         return SOC_E_NONE;
   5086     }
   5087 
   5088     /* LPM prefix layout enable */
   5089     for (i = 0; i <= MAX_PFX_INDEX(u); i++) {
   5090         SOC_LPM_STATE_START(u, i) = -1;
   5091         SOC_LPM_STATE_END(u, i) = -1;
   5092         SOC_LPM_STATE_PREV(u, i) = -1;
   5093         SOC_LPM_STATE_NEXT(u, i) = -1;
   5094         SOC_LPM_STATE_VENT(u, i) = 0;
   5095         SOC_LPM_STATE_FENT(u, i) = 0;
   5096     }
   5097 
   5098     for (i = 1; i <= MAX_PFX_CONF_NUM; i++) {
   5099         cfg_str = soc_property_suffix_num_str_get(u, i, spn_LPM_LAYOUT, "prefix");
   5100         if (cfg_str == NULL) {
   5101             continue;
   5102         }
   5103 
   5104         /* lpm_layout_prefix<idx>=
   5105          *   <IP version>:<VRF type>:<prefix length>:<route number>
   5106          */
   5107         if (sal_strlen(cfg_str) < sizeof(sub_str)) {
   5108             /* coverity [secure_coding : FALSE] */
   5109             sal_strcpy(sub_str, cfg_str);
   5110         } else {
   5111             LOG_ERROR(BSL_LS_SOC_LPM,
   5112                       (BSL_META_U(u,
   5113                                   "Prefix index %d: Invalid string \"%s\"\n"),
   5114                        i, cfg_str));
   5115             continue;              
   5116         }
   5117 
   5118         ipver_str = sal_strtok_r(sub_str, ":", &tokstr);
   5119         vrf_str = sal_strtok_r(NULL, ":", &tokstr);
   5120         len_str = sal_strtok_r(NULL, ":", &tokstr);
   5121         num_str = sal_strtok_r(NULL, ":", &tokstr);
   5122 
   5123         if (ipver_str == NULL || vrf_str == NULL || 
   5124             len_str == NULL || num_str == NULL) {
   5125             LOG_ERROR(BSL_LS_SOC_LPM,
   5126                       (BSL_META_U(u,
   5127                                   "Prefix index %d: Invalid string \"%s\"\n"),
   5128                        i, cfg_str));
   5129             continue;          
   5130         }
   5131 
   5132         /* Parsing physical port number */
   5133         ipver = sal_ctoi(ipver_str, NULL);
   5134         if (ipver != 4 && ipver != 6) {
   5135             LOG_ERROR(BSL_LS_SOC_LPM,
   5136                       (BSL_META_U(u,
   5137                                   "Prefix index %d: Invalid IP version %d\n"),
   5138                        i, ipver));
   5139             continue;
   5140         }
   5141 
   5142         /* Parsing VRF configuration */
   5143         vrf_type = sal_ctoi(vrf_str, NULL);
   5144         if (vrf_type != 0 && vrf_type != 1 && vrf_type != 2) {
   5145             LOG_ERROR(BSL_LS_SOC_LPM,
   5146                       (BSL_META_U(u,
   5147                                   "Prefix index %d: Invalid VRF value %d\n"),
   5148                        i, vrf_type));
   5149             continue;
   5150         } 
   5151         if (vrf_type == 1) {
   5152             vrf_type = SOC_L3_VRF_OVERRIDE;
   5153         } else if (vrf_type == 2) {
   5154             vrf_type = SOC_L3_VRF_GLOBAL;
   5155         }
   5156 
   5157         /* Parsing prefix length */
   5158         plen = sal_ctoi(len_str, NULL);
   5159 
   5160         /* Only prefix length <= 64 allowed */
   5161         if (!((ipver == 4 && plen >= 0 && plen <= 32) || 
   5162               (ipver == 6 && plen >= 0 && plen <= 64))) {
   5163             LOG_ERROR(BSL_LS_SOC_LPM,
   5164                       (BSL_META_U(u,
   5165                                   "Prefix index %d: Invalid prefix length value %d\n"),
   5166                        i, plen));
   5167             continue;
   5168         }
   5169 
   5170         /* Parsing prefix length */
   5171         entry_number = sal_ctoi(num_str, NULL);
   5172         if (entry_number < 0) {
   5173             LOG_ERROR(BSL_LS_SOC_LPM,
   5174                       (BSL_META_U(u,
   5175                                   "Prefix index %d: Invalid entry number value %d\n"),
   5176                        i, entry_number));
   5177             continue;
   5178         }
   5179 
   5180         if (ipver == 4) {
   5181             entry_number = (entry_number + 1) / 2;
   5182         }
   5183         entry_total_count += entry_number;
   5184         if (entry_total_count > ipv6_64_depth) {
   5185             LOG_WARN(BSL_LS_SOC_LPM,
   5186                      (BSL_META_U(u,
   5187                                  "LPM Prefix Layout: Exceeded max capacity %d(cur %d) in "
   5188                                  "L3_DEFIP, ignore rest configuration.\n"), 
   5189                       ipv6_64_depth, entry_total_count));
   5190             entry_number -= entry_total_count - ipv6_64_depth;
   5191             entry_total_count = ipv6_64_depth;
   5192             
   5193             /* Force to break by setting i to SOC_PREFIX_COUNT_NUMBER */
   5194             i = MAX_PFX_CONF_NUM;
   5195         }
   5196 
   5197         /* Layout LPM prefix state in 1st round, we only create link and number
   5198          * here, after all prefix configuration are ready, then we orginaze the 
   5199          * start and end pointer */
   5200         (void)_soc_fb_lpm_prefix_get_by_len(u, ipver == 6, vrf_type, plen, &pfx, 0);
   5201 
   5202         curr_pfx = MAX_PFX_INDEX(u);
   5203         while (SOC_LPM_STATE_NEXT(u, curr_pfx) > pfx) {
   5204             curr_pfx = SOC_LPM_STATE_NEXT(u, curr_pfx);
   5205         }
   5206 
   5207         SOC_LPM_STATE_FENT(u, pfx) = entry_number;
   5208         if (curr_pfx != pfx) {
   5209             next_pfx = SOC_LPM_STATE_NEXT(u, curr_pfx);
   5210             if (next_pfx != -1) {
   5211                 SOC_LPM_STATE_PREV(u, next_pfx) = pfx;
   5212             }
   5213             SOC_LPM_STATE_NEXT(u, pfx) = SOC_LPM_STATE_NEXT(u, curr_pfx);
   5214             SOC_LPM_STATE_PREV(u, pfx) = curr_pfx;
   5215             SOC_LPM_STATE_NEXT(u, curr_pfx) = pfx;
   5216         }
   5217     }
   5218 
   5219     /* ipv6_64_depth equals to soc_mem_index_count(mem)
   5220      * So the rest memory we need to get back to MAX_PFX_INDEX */
   5221     max_pfx_number = ipv6_64_depth - entry_total_count;
   5222 
   5223     /* Layout LPM prefix state in 2nd round */
   5224     curr_pfx = MAX_PFX_INDEX(u);
   5225     while (curr_pfx != -1) {
   5226         if (curr_pfx == MAX_PFX_INDEX(u)) {
   5227             /* We never use prefix MAX_PFX_INDEX, so we can set its start 
   5228              * to 0, it won't break the lpm logic */ 
   5229             SOC_LPM_STATE_START(u, curr_pfx) = start;
   5230             SOC_LPM_STATE_END(u, curr_pfx) = start - 1;
   5231             SOC_LPM_STATE_VENT(u, curr_pfx) = 0;
   5232             SOC_LPM_STATE_FENT(u, curr_pfx) = max_pfx_number;
   5233             
   5234             curr_pfx = SOC_LPM_STATE_NEXT(u, curr_pfx);
   5235             continue;
   5236         }
   5237 
   5238         /* Setup start index of each prefix base on free entry number. */
   5239         prev_pfx = SOC_LPM_STATE_PREV(u, curr_pfx);
   5240         SOC_LPM_STATE_START(u, curr_pfx) = 
   5241             SOC_LPM_STATE_START(u, prev_pfx) + SOC_LPM_STATE_FENT(u, prev_pfx);
   5242         SOC_LPM_STATE_END(u, curr_pfx) = 
   5243             SOC_LPM_STATE_END(u, prev_pfx) + SOC_LPM_STATE_FENT(u, prev_pfx);
   5244         SOC_LPM_STATE_VENT(u, curr_pfx) = 0;
   5245         
   5246         curr_pfx = SOC_LPM_STATE_NEXT(u, curr_pfx);
   5247     }
   5248 
   5249     return SOC_E_NONE;
   5250 }
   5251 
   5252 int
   5253 soc_fb_lpm_stat_init(int u)
   5254 {
   5255     if (!(soc_feature(u, soc_feature_l3_shared_defip_table) ||
   5256           soc_feature(u, soc_feature_shared_defip_stat_support))) {
   5257         return SOC_E_NONE;
   5258     }
   5259 
   5260     if (SOC_LPM_STAT_INIT_CHECK(u)) {
   5261         sal_free(soc_lpm_stat[u]);
   5262         soc_lpm_stat[u] = NULL;
   5263     }
   5264 
   5265     soc_lpm_stat[u] = sal_alloc(sizeof(soc_lpm_stat_t), "LPM STATS");
   5266     if (soc_lpm_stat[u] == NULL) {
   5267         return SOC_E_MEMORY;
   5268     }
   5269 
   5270     SOC_LPM_V4_COUNT(u) = 0;
   5271     SOC_LPM_64BV6_COUNT(u) = 0;
   5272     SOC_LPM_128BV6_COUNT(u) = 0;
   5273     SOC_LPM_V4_HALF_ENTRY_COUNT(u) = 0;
   5274     SOC_IF_ERROR_RETURN(_soc_lpm_max_v4_route_get(u, 0,
   5275                                            &SOC_LPM_MAX_V4_COUNT(u))); 
   5276     SOC_IF_ERROR_RETURN(_soc_lpm_max_64bv6_route_get(u, 0,
   5277                                            &SOC_LPM_MAX_64BV6_COUNT(u))); 
   5278     if (!soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
   5279         SOC_IF_ERROR_RETURN(_soc_lpm_max_128bv6_route_get(u,
   5280                                            &SOC_LPM_MAX_128BV6_COUNT(u)));
   5281     } else {
   5282         SOC_LPM_MAX_128BV6_COUNT(u) = 0;
   5283     }
   5284     return SOC_E_NONE;
   5285 }
   5286 
   5287 int
   5288 soc_fb_lpm128_stat_init(int u)
   5289 {
   5290     if (SOC_LPM128_STATE(u) == NULL) {
   5291         return SOC_E_INTERNAL;
   5292     }
   5293     SOC_LPM128_STAT_V4_COUNT(u) = 0;
   5294     SOC_LPM128_STAT_64BV6_COUNT(u) = 0;
   5295     SOC_LPM128_STAT_128BV6_COUNT(u) = 0;
   5296     SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u) = 0;
   5297     /* Now setup max values */
   5298 
   5299     if (soc_feature(u, soc_feature_defip_2_tcams_with_separate_rpf)) {
   5300         int rpf_scale = 1;
   5301         rpf_scale = (SOC_URPF_STATUS_GET(u) ? 1: 2);
   5302 
   5303         SOC_LPM128_STAT_MAX_V4_COUNT(u) = R2P_V4_MAX * rpf_scale;
   5304         SOC_LPM128_STAT_MAX_64BV6_COUNT(u) = R2P_64V6_MAX * rpf_scale;
   5305         SOC_LPM128_STAT_MAX_128BV6_COUNT(u) =  R2P_128V6_MAX * rpf_scale;
   5306         return SOC_E_NONE;
   5307     }
   5308 
   5309     SOC_IF_ERROR_RETURN(_soc_lpm_max_v4_route_get(u, 1,
   5310                                        &SOC_LPM128_STAT_MAX_V4_COUNT(u)));
   5311     SOC_IF_ERROR_RETURN(_soc_lpm_max_64bv6_route_get(u, 1,
   5312                                       &SOC_LPM128_STAT_MAX_64BV6_COUNT(u)));
   5313     SOC_IF_ERROR_RETURN(_soc_lpm_max_128bv6_route_get(u,
   5314                                      &SOC_LPM128_STAT_MAX_128BV6_COUNT(u)));
   5315 
   5316     return SOC_E_NONE;
   5317 }
   5318 
   5319 /*
   5320  * Initialize the start/end tracking pointers for each prefix length
   5321  */
   5322 int
   5323 soc_fb_lpm_init(int u)
   5324 {
   5325     int max_pfx_len;
   5326     int defip_table_size = 0;
   5327     int pfx_state_size;
   5328     int i;    
   5329 #if defined(BCM_KATANA_SUPPORT)
   5330     uint32 l3_defip_tbl_size;
   5331     int ipv6_lpm_128b_enable;
   5332 #endif
   5333     int tcam_pair_count = 0;
   5334     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   5335     int start_index = 0;
   5336     int hash_table_size = 0;
   5337     soc_field_t defip_mode0_field = MODE0f;
   5338     soc_field_t defip_mode1_field = MODE1f;
   5339     soc_field_t defip_mode_mask0_field = KEY_MODE_MASK0f;
   5340     soc_field_t defip_mode_mask1_field = KEY_MODE_MASK1f;
   5341     soc_mem_t mem = L3_DEFIPm;
   5342 
   5343 #if defined(BCM_TRIDENT3_SUPPORT)
   5344     if (SOC_IS_TRIDENT3X(u)) {
   5345         defip_mode0_field = defip_mode0_bit[u] = KEY_MODE0f;
   5346         defip_mode1_field = defip_mode1_bit[u] = KEY_MODE1f;
   5347         defip_mode_mask0_field = defip_mode_mask0_bit[u] = KEY_MODE_MASK0f;
   5348         defip_mode_mask1_field = defip_mode_mask1_bit[u] = KEY_MODE_MASK1f;
   5349     } else 
   5350 #endif
   5351     {
   5352         defip_mode0_field = defip_mode0_bit[u] = MODE0f;
   5353         defip_mode1_field = defip_mode1_bit[u] = MODE1f;
   5354         defip_mode_mask0_field = defip_mode_mask0_bit[u] = MODE_MASK0f;
   5355         defip_mode_mask1_field = defip_mode_mask1_bit[u] = MODE_MASK1f;
   5356     }
   5357     if (! soc_feature(u, soc_feature_lpm_tcam)) {
   5358         return(SOC_E_UNAVAIL);
   5359     }
   5360 
   5361     if (!SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   5362         mem = L3_DEFIP_LEVEL1m;
   5363     }
   5364 
   5365     max_pfx_len = MAX_PFX_ENTRIES(u);
   5366     pfx_state_size = sizeof(soc_lpm_state_t) * (max_pfx_len);
   5367 
   5368     if (! SOC_LPM_INIT_CHECK(u)) {
   5369         soc_lpm_field_cache_state[u] = 
   5370                 sal_alloc(sizeof(soc_lpm_field_cache_t), "lpm_field_state");
   5371         if (NULL == soc_lpm_field_cache_state[u]) {
   5372             return (SOC_E_MEMORY);
   5373         }
   5374         sal_memset(soc_lpm_field_cache_state[u], 0 , sizeof(soc_lpm_field_cache_t));
   5375         if (SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   5376             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, CLASS_ID0f);
   5377             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, CLASS_ID1f);
   5378             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, DST_DISCARD0f);
   5379             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, DST_DISCARD1f);
   5380             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, ECMP0f);
   5381             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, ECMP1f);
   5382             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, ECMP_COUNT0f);
   5383             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, ECMP_COUNT1f);
   5384             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, ECMP_PTR0f);
   5385             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, ECMP_PTR1f);
   5386             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, GLOBAL_ROUTE0f);
   5387             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, GLOBAL_ROUTE1f);
   5388 
   5389 #if defined(BCM_TRIDENT3_SUPPORT)
   5390         if (SOC_MEM_FIELD_VALID(u, L3_DEFIPm, DESTINATION0f)) {
   5391             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, DESTINATION0f);
   5392             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, DESTINATION1f);
   5393             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, DATA_TYPE0f);
   5394             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, DATA_TYPE1f);
   5395         }
   5396 #endif /* BCM_TRIDENT3_SUPPORT */
   5397 
   5398 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   5399             if (soc_feature(u, soc_feature_ipmc_defip)) {
   5400                 SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u], L3_DEFIPm, MULTICAST_ROUTE0f);
   5401                 SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u], L3_DEFIPm, MULTICAST_ROUTE1f);
   5402                 SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u], L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f);
   5403                 SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u], L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f);
   5404                 SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u], L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f);
   5405                 SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u], L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f);
   5406                 SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u], L3_DEFIPm, EXPECTED_L3_IIF0f);
   5407                 SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u], L3_DEFIPm, EXPECTED_L3_IIF1f);
   5408                 SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u], L3_DEFIPm, RPA_ID0f);
   5409                 SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u], L3_DEFIPm, RPA_ID1f);
   5410                 SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u], L3_DEFIPm, L3MC_INDEX0f);
   5411                 SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u], L3_DEFIPm, L3MC_INDEX1f);
   5412             }
   5413 #endif
   5414             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, HIT0f);
   5415             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, HIT1f);
   5416             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, IP_ADDR0f);
   5417             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, IP_ADDR1f);
   5418             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, IP_ADDR_MASK0f);
   5419             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, IP_ADDR_MASK1f);
   5420             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, defip_mode0_field);
   5421             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, defip_mode1_field);
   5422             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, defip_mode_mask0_field);
   5423             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, defip_mode_mask1_field);
   5424             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, NEXT_HOP_INDEX0f);
   5425             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, NEXT_HOP_INDEX1f);
   5426             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, PRI0f);
   5427             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, PRI1f);
   5428             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, RPE0f);
   5429             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, RPE1f);
   5430             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, VALID0f);
   5431             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, VALID1f);
   5432             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, VRF_ID_0f);
   5433             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, VRF_ID_1f);
   5434             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, VRF_ID_MASK0f);
   5435             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, VRF_ID_MASK1f);
   5436             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, ENTRY_TYPE0f);
   5437             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, ENTRY_TYPE1f);
   5438             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, ENTRY_TYPE_MASK0f);
   5439             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, ENTRY_TYPE_MASK1f);
   5440             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, D_ID0f);
   5441             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, D_ID1f);
   5442             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, D_ID_MASK0f);
   5443             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, D_ID_MASK1f);
   5444             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, DEFAULTROUTE0f);
   5445             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, DEFAULTROUTE1f);
   5446 #if defined(BCM_TRIDENT2_SUPPORT)
   5447             if (soc_feature(u, soc_feature_advanced_flex_counter)) {
   5448                 if (SOC_MEM_FIELD_VALID(u, L3_DEFIPm, FLEX_CTR_OFFSET_MODE0f)) {
   5449                     SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u],
   5450                                                L3_DEFIPm, FLEX_CTR_OFFSET_MODE0f);
   5451                     SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u],
   5452                                                L3_DEFIPm, FLEX_CTR_OFFSET_MODE1f);
   5453                     SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u],
   5454                                                L3_DEFIPm, FLEX_CTR_POOL_NUMBER0f);
   5455                     SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u],
   5456                                                L3_DEFIPm, FLEX_CTR_POOL_NUMBER1f);
   5457                     SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u],
   5458                                                L3_DEFIPm, FLEX_CTR_BASE_COUNTER_IDX0f);
   5459                     SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u],
   5460                                                L3_DEFIPm, FLEX_CTR_BASE_COUNTER_IDX1f);
   5461                 }
   5462             }
   5463 #endif
   5464         }
   5465 #if defined(BCM_TOMAHAWK3_SUPPORT)
   5466         else if (SOC_MEM_IS_VALID(u, L3_DEFIP_LEVEL1m)) {
   5467             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIP_LEVEL1m, HIT0f);
   5468             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIP_LEVEL1m, HIT1f);
   5469             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIP_LEVEL1m, VALID0f);
   5470             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIP_LEVEL1m, VALID1f);
   5471             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIP_LEVEL1m, ASSOC_DATA0f);
   5472             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIP_LEVEL1m, ASSOC_DATA1f);
   5473             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIP_LEVEL1m, FIXED_DATA0f);
   5474             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIP_LEVEL1m, FIXED_DATA1f);
   5475             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIP_LEVEL1m, ALPM1_DATA0f);
   5476             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIP_LEVEL1m, ALPM1_DATA1f);
   5477             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIP_LEVEL1m, KEY0f);
   5478             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIP_LEVEL1m, KEY1f);
   5479             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIP_LEVEL1m, MASK0f);
   5480             SOC_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIP_LEVEL1m, MASK1f);
   5481         }
   5482 #endif
   5483         SOC_LPM_STATE(u) = sal_alloc(pfx_state_size, "LPM prefix info");
   5484         if (NULL == SOC_LPM_STATE(u)) {
   5485             sal_free(soc_lpm_field_cache_state[u]);
   5486             soc_lpm_field_cache_state[u] = NULL;
   5487             return (SOC_E_MEMORY);
   5488         }
   5489 #ifdef FB_LPM_DEBUG
   5490         DBG_SOC_LPM_STATE(u) = sal_alloc(pfx_state_size, "DBG LPM prefix info");
   5491         if (NULL == DBG_SOC_LPM_STATE(u)) {
   5492             soc_fb_lpm_deinit(u);
   5493             return (SOC_E_MEMORY);
   5494         }
   5495         DBG_SOC_LPM_STATE2(u) = sal_alloc(pfx_state_size, "DBG LPM prefix info 2");
   5496         if (NULL == DBG_SOC_LPM_STATE2(u)) {
   5497             soc_fb_lpm_deinit(u);
   5498             return (SOC_E_MEMORY);
   5499         }
   5500         DBG_SOC_LPM_HASH_TMP(u) = sal_alloc(2 * LPM_TBL_SIZE * sizeof(int), "hash");
   5501         if (NULL == DBG_SOC_LPM_HASH_TMP(u)) {
   5502             soc_fb_lpm_deinit(u);
   5503             return (SOC_E_MEMORY);
   5504         }
   5505 #endif
   5506     }
   5507 
   5508 #ifdef FB_LPM_TABLE_CACHED
   5509     SOC_IF_ERROR_RETURN (soc_mem_cache_set(u, mem, MEM_BLOCK_ALL, TRUE));
   5510 #endif /* FB_LPM_TABLE_CACHED */
   5511     SOC_LPM_LOCK(u);
   5512 
   5513     sal_memset(SOC_LPM_STATE(u), 0, pfx_state_size);
   5514     for(i = 0; i < max_pfx_len; i++) {
   5515         SOC_LPM_STATE_START(u, i) = -1;
   5516         SOC_LPM_STATE_END(u, i) = -1;
   5517         SOC_LPM_STATE_PREV(u, i) = -1;
   5518         SOC_LPM_STATE_NEXT(u, i) = -1;
   5519         SOC_LPM_STATE_VENT(u, i) = 0;
   5520         SOC_LPM_STATE_FENT(u, i) = 0;
   5521     }
   5522 #ifdef FB_LPM_DEBUG
   5523     sal_memset(DBG_SOC_LPM_STATE2(u), 0, pfx_state_size);
   5524     for(i = 0; i < max_pfx_len; i++) {
   5525         SOC_LPM_STATE_S(DBG_SOC_LPM_STATE2(u), i) = -1;
   5526         SOC_LPM_STATE_E(DBG_SOC_LPM_STATE2(u), i) = -1;
   5527         SOC_LPM_STATE_P(DBG_SOC_LPM_STATE2(u), i) = -1;
   5528         SOC_LPM_STATE_N(DBG_SOC_LPM_STATE2(u), i) = -1;
   5529         SOC_LPM_STATE_V(DBG_SOC_LPM_STATE2(u), i) = 0;
   5530         SOC_LPM_STATE_F(DBG_SOC_LPM_STATE2(u), i) = 0;
   5531     }
   5532 #endif
   5533 
   5534     defip_table_size = soc_mem_index_count(u, mem);
   5535 #ifdef BCM_KATANA2_SUPPORT
   5536     if (SOC_IS_KATANA2(u)) {
   5537           fb_lpm_hash_index_mask[u] = 0x7FFF;
   5538     } else {
   5539           fb_lpm_hash_index_mask[u] = 0x3FFF;
   5540     }
   5541 #else
   5542     fb_lpm_hash_index_mask[u] = 0x3FFF;
   5543 #endif
   5544 
   5545 #ifdef BCM_TRIDENT3_SUPPORT
   5546     if (SOC_IS_TRIDENT3X(u)) {
   5547           fb_lpm_hash_index_mask[u] = 0x7FFF;
   5548     }
   5549 #endif
   5550 
   5551     if (SOC_IS_HELIX4(u)) {
   5552         fb_lpm_hash_index_mask[u] = 0xFFFF;
   5553     } else if (SOC_IS_TOMAHAWK2(u)) {
   5554         fb_lpm_hash_index_mask[u] = 0x7FFF;
   5555     }
   5556 
   5557     if (SOC_URPF_STATUS_GET(u)) {
   5558         if (soc_feature(u, soc_feature_l3_defip_hole)) {
   5559               defip_table_size = SOC_APOLLO_B0_L3_DEFIP_URPF_SIZE;
   5560         } else if (SOC_IS_APOLLO(u)) {
   5561             defip_table_size = SOC_APOLLO_L3_DEFIP_URPF_SIZE;
   5562         } else {
   5563             /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
   5564              * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
   5565              * L3_DEFIP table is not divided into 2 to support URPF.
   5566              */
   5567             if (!soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   5568                 defip_table_size >>= 1;
   5569             }
   5570         }
   5571     }
   5572 
   5573     if (soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
   5574         SOC_IF_ERROR_RETURN(soc_fb_lpm_tcam_pair_count_get(u, &tcam_pair_count));
   5575         /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
   5576          * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
   5577          * L3_DEFIP table is not divided into 2 to support URPF.
   5578          */
   5579         if (SOC_URPF_STATUS_GET(u) &&
   5580             !soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   5581             switch(tcam_pair_count) {
   5582                 case 1:
   5583                 case 2:
   5584                     defip_table_size -= (2 * tcam_depth);
   5585                     start_index = 2 * tcam_depth;
   5586                     break;
   5587                 case 3: 
   5588                 case 4:
   5589                     defip_table_size -= (4 * tcam_depth);
   5590                     start_index = 4 * tcam_depth;
   5591                     break;
   5592                 case 5: 
   5593                 case 6:
   5594                     defip_table_size -= (6 * tcam_depth);
   5595                     start_index = 6 * tcam_depth;
   5596                     break;
   5597                 case 7: 
   5598                 case 8:
   5599                     defip_table_size -= (8 * tcam_depth);
   5600                     start_index = 8 * tcam_depth;
   5601                     break;
   5602                 default:
   5603                     break;
   5604                 
   5605             }
   5606         } else {
   5607             defip_table_size -= (tcam_pair_count * tcam_depth * 2);
   5608             start_index = (2 * tcam_pair_count * tcam_depth);
   5609         }
   5610     } else {
   5611         start_index = 0;
   5612     }
   5613 
   5614     SOC_LPM_STATE_FENT(u, (MAX_PFX_INDEX(u))) = defip_table_size;
   5615     SOC_LPM_STATE_START(u, MAX_PFX_INDEX(u)) = start_index;
   5616     SOC_LPM_STATE_END(u, (MAX_PFX_INDEX(u))) = start_index - 1;
   5617 #ifdef FB_LPM_DEBUG
   5618     SOC_LPM_STATE_F(DBG_SOC_LPM_STATE2(u), MAX_PFX_INDEX(u)) = defip_table_size;
   5619     SOC_LPM_STATE_S(DBG_SOC_LPM_STATE2(u), MAX_PFX_INDEX(u)) = start_index;
   5620     SOC_LPM_STATE_E(DBG_SOC_LPM_STATE2(u), MAX_PFX_INDEX(u)) = start_index - 1;
   5621 #endif
   5622 #if defined(BCM_KATANA_SUPPORT)
   5623     if (SOC_IS_KATANA(u)) {
   5624         l3_defip_tbl_size = soc_mem_index_count(u, L3_DEFIPm);
   5625         
   5626         ipv6_lpm_128b_enable = soc_property_get(u, spn_IPV6_LPM_128B_ENABLE, 0);
   5627     
   5628         /* IPv6 128b and IPv6 64b entries are stored in mutually exclusive
   5629          * entries in L3_DEFIP table. IPv6 128b are stored in L3_DEFIP_PAIR_128
   5630          * table which is an alias of the L3_DEFIP TCAM pairs. While storing the
   5631          * IPv6 64b entriesin L3_DEFIP table it should be taken care not to
   5632          * overlap with the  entry locations reserved for IPv6 128b for a given
   5633          * 128b pairing mode */
   5634 
   5635         /* De-allocate any existing kt_lpm_ipv6_info structures. */
   5636         if (kt_lpm_ipv6_info[u] != NULL) {
   5637             kt_lpm_ipv6_info[u] = NULL;
   5638             sal_free(kt_lpm_ipv6_info[u]);
   5639         }
   5640 
   5641         /* Allocate kt_lpm_ipv6_info structure. */
   5642         kt_lpm_ipv6_info[u] = sal_alloc(sizeof(soc_kt_lpm_ipv6_info_t),
   5643                                         "kt_lpm_ipv6_info");
   5644         if (kt_lpm_ipv6_info[u] == NULL) {
   5645             return (SOC_E_MEMORY);
   5646         }
   5647 
   5648         /* Reset kt_lpm_ipv6_info structure. */
   5649         sal_memset(kt_lpm_ipv6_info[u], 0, sizeof(soc_kt_lpm_ipv6_info_t));
   5650 
   5651         if (SOC_URPF_STATUS_GET(u)) {
   5652             /* urpf check enabled */
   5653             if (ipv6_lpm_128b_enable == 1) {
   5654                 /*
   5655                  * Saber - 56246 has only 2 L3_DEFIP tcams
   5656                  * Both IPV6 and RPF cannot be supported
   5657                  * on this device.
   5658                  */
   5659                 if (soc_feature(u, soc_feature_l3_max_2_defip_tcams)) {
   5660                     LOG_ERROR(BSL_LS_SOC_LPM,
   5661                               (BSL_META_U(u,
   5662                                "Cannot enable IPV6 and URPF "
   5663                                "only 2 L3_DEFIP tcams present\n")));
   5664                     return SOC_E_CONFIG;
   5665                 } else {
   5666                     /* C6 :
   5667                      * L3_DEFIP_KEY_SEL=101100_011 ( 0x163 )
   5668                      * TCAMs 0-1 paired for DIP IPv6 LPM 128b
   5669                      * TCAMs 2-3 paired for SIP Ipv6 LPM 128b*/
   5670                     WRITE_L3_DEFIP_KEY_SELr(u, 0x163);
   5671                 }
   5672                 kt_lpm_ipv6_info[u]->ipv6_128b.depth = L3_DEFIP_TCAM_SIZE;
   5673                 /* TCAM 4 is used for DIP IPv6 LPM 64b
   5674                  * TCAM 5 is used for SIP IPv6 LPM 64b */
   5675                 kt_lpm_ipv6_info[u]->ipv6_64b.dip_start_offset =
   5676                     L3_DEFIP_TCAM_SIZE * 4;
   5677                 kt_lpm_ipv6_info[u]->ipv6_64b.depth = L3_DEFIP_TCAM_SIZE;
   5678             } else {
   5679                 /*
   5680                  * Saber - 56246 has only 2 L3_DEFIP tcams
   5681                  * on this device.
   5682                  */
   5683                 if (soc_feature(u, soc_feature_l3_max_2_defip_tcams)) {
   5684                     WRITE_L3_DEFIP_KEY_SELr(u, 0x10);
   5685                 } else {
   5686                     /* C5 :
   5687                      * L3_DEFIP_KEY_SEL=111000_000 ( 0x1c0 )
   5688                      * No TCAM pairing - No IPv6 LPM 128b entries */
   5689                     WRITE_L3_DEFIP_KEY_SELr(u, 0x1c0);
   5690                 }
   5691                 /* TCAMs 0-2 are shared for DIP IPv4 LPM and IPv6 LPM 64b
   5692                  * TCAMs 3-5 are shared for SIP IPv4 LPM and IPv6 LPM 64b*/
   5693                 kt_lpm_ipv6_info[u]->ipv6_64b.depth = l3_defip_tbl_size / 2;
   5694             }
   5695             kt_lpm_ipv6_info[u]->ipv6_128b.sip_start_offset =
   5696                 kt_lpm_ipv6_info[u]->ipv6_128b.dip_start_offset +
   5697                 kt_lpm_ipv6_info[u]->ipv6_128b.depth;
   5698             kt_lpm_ipv6_info[u]->ipv6_64b.sip_start_offset =
   5699                 kt_lpm_ipv6_info[u]->ipv6_64b.dip_start_offset +
   5700                 kt_lpm_ipv6_info[u]->ipv6_64b.depth;
   5701         } else {
   5702             /* urpf check disabled */
   5703             if (ipv6_lpm_128b_enable == 1) {
   5704                 /* C3:
   5705                  * L3_DEFIP_KEY_SEL = 000000_011
   5706                  * TCAMs 0-3 paired for DIP IPv6 LPM 128b */
   5707                 WRITE_L3_DEFIP_KEY_SELr(u, 0x3);
   5708                 kt_lpm_ipv6_info[u]->ipv6_128b.depth = L3_DEFIP_TCAM_SIZE * 2;
   5709                 /* TCAMs 4-5 is used for DIP IPv6 LPM 64b */
   5710                 kt_lpm_ipv6_info[u]->ipv6_64b.dip_start_offset =
   5711                     L3_DEFIP_TCAM_SIZE * 4;
   5712                 kt_lpm_ipv6_info[u]->ipv6_64b.depth = L3_DEFIP_TCAM_SIZE * 2;
   5713             } else {
   5714                 /* C1:
   5715                  * L3_DEFIP_KEY_SEL = 000000_000
   5716                  * No TCAM pairing - No Ipv6 LPM 128b entries */
   5717                 WRITE_L3_DEFIP_KEY_SELr(u, 0x0);
   5718                 /* TCAMs 0-6 are used for DIP IPv6 LPM 64b */
   5719                 kt_lpm_ipv6_info[u]->ipv6_64b.depth = l3_defip_tbl_size;
   5720             };
   5721         }
   5722         SOC_LPM_STATE_FENT(u, (MAX_PFX_INDEX(u))) =
   5723                 kt_lpm_ipv6_info[u]->ipv6_64b.depth;
   5724         SOC_LPM_STATE_END(u, (MAX_PFX_INDEX(u))) =
   5725                 kt_lpm_ipv6_info[u]->ipv6_64b.dip_start_offset - 1;
   5726 
   5727         SOC_IF_ERROR_RETURN(soc_fb_lpm_state_config(u,
   5728                             kt_lpm_ipv6_info[u]->ipv6_64b.depth,
   5729                             kt_lpm_ipv6_info[u]->ipv6_64b.dip_start_offset));
   5730     } else 
   5731 #endif /* BCM_KATANA_SUPPORT */
   5732     {
   5733         SOC_IF_ERROR_RETURN(soc_fb_lpm_state_config(u, defip_table_size, 
   5734                                                     start_index));
   5735     }
   5736 
   5737 
   5738 
   5739 #if defined(FB_LPM_AVL_SUPPORT)
   5740     if (SOC_LPM_STATE_AVL(u) != NULL) {
   5741         if (shr_avl_destroy(SOC_LPM_STATE_AVL(u)) < 0) {
   5742             SOC_LPM_UNLOCK(u);
   5743             return SOC_E_INTERNAL;
   5744         }
   5745         SOC_LPM_STATE_AVL(u) = NULL;
   5746     }
   5747     if (shr_avl_create(&SOC_LPM_STATE_AVL(u), INT_TO_PTR(u),
   5748                        sizeof(soc_lpm_avl_state_t), defip_table_size * 2) < 0) {
   5749         SOC_LPM_UNLOCK(u);
   5750         return SOC_E_MEMORY;
   5751     }
   5752 #endif /* FB_LPM_AVL_SUPPORT */
   5753 
   5754 #ifdef FB_LPM_HASH_SUPPORT
   5755     if (SOC_LPM_STATE_HASH(u) != NULL) {
   5756         if (_soc_fb_lpm_hash_destroy(SOC_LPM_STATE_HASH(u)) < 0) {
   5757             SOC_LPM_UNLOCK(u);
   5758             return SOC_E_INTERNAL;
   5759         }
   5760         SOC_LPM_STATE_HASH(u) = NULL;
   5761     }
   5762 
   5763     if (SOC_MEM_IS_VALID(u, L3_DEFIPm)) {
   5764         hash_table_size = soc_mem_index_count(u, L3_DEFIPm);
   5765     } else {
   5766         hash_table_size = soc_mem_index_count(u, L3_DEFIP_LEVEL1m);
   5767     }
   5768 
   5769     if (_soc_fb_lpm_hash_create(u, hash_table_size * 2, hash_table_size,
   5770                                 &SOC_LPM_STATE_HASH(u)) < 0) {
   5771         SOC_LPM_UNLOCK(u);
   5772         return SOC_E_MEMORY;
   5773     }
   5774 #ifdef FB_LPM_DEBUG
   5775     if (_soc_fb_lpm_hash_create(u, hash_table_size * 2, hash_table_size,
   5776                                 &DBG_SOC_LPM_STATE_HASH(u)) < 0) {
   5777         SOC_LPM_UNLOCK(u);
   5778         return SOC_E_MEMORY;
   5779     }
   5780 
   5781     if (_soc_fb_lpm_hash_create(u, hash_table_size * 2, hash_table_size,
   5782                                 &DBG_SOC_LPM_STATE_HASH2(u)) < 0) {
   5783         SOC_LPM_UNLOCK(u);
   5784         return SOC_E_MEMORY;
   5785     }
   5786 #endif
   5787 #endif
   5788     if ((soc_feature(u, soc_feature_l3_shared_defip_table)) ||
   5789         (soc_feature(u, soc_feature_shared_defip_stat_support))) {
   5790         if (soc_fb_lpm_stat_init(u) < 0) {
   5791        /* COVERITY
   5792         * soc_fb_lpm_deinit is called in error condition.
   5793         * so irrespective of its return value we are going to release lpm lock
   5794         * and return E_INTERNAL. Hence we can ignore the return value
   5795         */
   5796         /* coverity[check_return] */
   5797             soc_fb_lpm_deinit(u);
   5798             SOC_LPM_UNLOCK(u);
   5799             return SOC_E_INTERNAL;
   5800         }
   5801     }
   5802     SOC_LPM_UNLOCK(u);
   5803 
   5804     return(SOC_E_NONE);
   5805 }
   5806 /*
   5807  * De-initialize the start/end tracking pointers for each prefix length
   5808  */
   5809 int
   5810 soc_fb_lpm_deinit(int u)
   5811 {
   5812     if (!soc_feature(u, soc_feature_lpm_tcam)) {
   5813         return(SOC_E_UNAVAIL);
   5814     }
   5815 
   5816     SOC_LPM_LOCK(u);
   5817 
   5818 #if defined(FB_LPM_AVL_SUPPORT)
   5819     if (SOC_LPM_STATE_AVL(u) != NULL) {
   5820         shr_avl_destroy(SOC_LPM_STATE_AVL(u));
   5821         SOC_LPM_STATE_AVL(u) = NULL;
   5822     }
   5823 #endif /* FB_LPM_AVL_SUPPORT */
   5824 
   5825 #ifdef FB_LPM_HASH_SUPPORT
   5826     if (SOC_LPM_STATE_HASH(u) != NULL) {
   5827         _soc_fb_lpm_hash_destroy(SOC_LPM_STATE_HASH(u));
   5828         SOC_LPM_STATE_HASH(u) = NULL;
   5829     }
   5830 #ifdef FB_LPM_DEBUG
   5831     if (DBG_SOC_LPM_STATE_HASH(u) != NULL) {
   5832         _soc_fb_lpm_hash_destroy(DBG_SOC_LPM_STATE_HASH(u));
   5833         DBG_SOC_LPM_STATE_HASH(u) = NULL;
   5834     }
   5835     if (DBG_SOC_LPM_STATE_HASH2(u) != NULL) {
   5836         _soc_fb_lpm_hash_destroy(DBG_SOC_LPM_STATE_HASH2(u));
   5837         DBG_SOC_LPM_STATE_HASH2(u) = NULL;
   5838     }
   5839 
   5840     if (DBG_SOC_LPM_STATE(u) != NULL) {
   5841         sal_free(DBG_SOC_LPM_STATE(u));
   5842         DBG_SOC_LPM_STATE(u) = NULL;
   5843     }
   5844     if (DBG_SOC_LPM_STATE2(u) != NULL) {
   5845         sal_free(DBG_SOC_LPM_STATE2(u));
   5846         DBG_SOC_LPM_STATE2(u) = NULL;
   5847     }
   5848     if (DBG_SOC_LPM_HASH_TMP(u) != NULL) {
   5849         sal_free(DBG_SOC_LPM_HASH_TMP(u));
   5850         DBG_SOC_LPM_HASH_TMP(u) = NULL;
   5851     }
   5852 #endif
   5853 #endif
   5854 
   5855 #ifdef BCM_KATANA_SUPPORT
   5856     if (SOC_IS_KATANA(u)) {
   5857         /* De-allocate any existing kt_lpm_ipv6_info structures. */
   5858         if (kt_lpm_ipv6_info[u] != NULL) {
   5859             kt_lpm_ipv6_info[u] = NULL;
   5860             sal_free(kt_lpm_ipv6_info[u]);
   5861         }
   5862     }
   5863 #endif
   5864 
   5865     if (SOC_LPM_INIT_CHECK(u)) {
   5866         sal_free(soc_lpm_field_cache_state[u]);
   5867         soc_lpm_field_cache_state[u] = NULL;
   5868         sal_free(SOC_LPM_STATE(u));
   5869         SOC_LPM_STATE(u) = NULL;
   5870     }
   5871 
   5872     if (SOC_LPM_STAT_INIT_CHECK(u)) {
   5873         sal_free(soc_lpm_stat[u]);
   5874         soc_lpm_stat[u] = NULL;
   5875     }
   5876 
   5877     SOC_LPM_UNLOCK(u);
   5878 
   5879     return(SOC_E_NONE);
   5880 }
   5881 
   5882 #ifdef BCM_WARM_BOOT_SUPPORT
   5883 int
   5884 soc_fb_lpm_reinit_done(int unit, int ipv6)
   5885 {
   5886     int idx;
   5887     int prev_idx = MAX_PFX_INDEX(unit);
   5888     uint32      v0 = 0, v1 = 0;
   5889     int from_ent = -1;
   5890     uint32      e[SOC_MAX_MEM_FIELD_WORDS] = {0};
   5891     int rv = SOC_E_NONE;
   5892     soc_mem_t mem = L3_DEFIPm;
   5893 
   5894     int defip_table_size;
   5895 
   5896     if (SOC_IS_HAWKEYE(unit)) {
   5897         return SOC_E_NONE;
   5898     }
   5899 
   5900 #if defined(BCM_TOMAHAWK3_SUPPORT)
   5901     if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) {
   5902          mem = L3_DEFIP_LEVEL1m;
   5903     }
   5904 #endif
   5905 
   5906     defip_table_size = soc_mem_index_count(unit, mem);
   5907 
   5908     if (SOC_URPF_STATUS_GET(unit)) {
   5909         if (soc_feature(unit, soc_feature_l3_defip_hole)) {
   5910               defip_table_size = SOC_APOLLO_B0_L3_DEFIP_URPF_SIZE;
   5911         } else if (SOC_IS_APOLLO(unit)) {
   5912             defip_table_size = SOC_APOLLO_L3_DEFIP_URPF_SIZE;
   5913         } else {
   5914             /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
   5915              * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
   5916              * L3_DEFIP table is not divided into 2 to support URPF.
   5917              */
   5918             if (!soc_feature(unit, soc_feature_l3_defip_advanced_lookup)) {
   5919                 defip_table_size >>= 1;
   5920             }
   5921         }
   5922     } 
   5923 
   5924     SOC_LPM_STATE_PREV(unit, MAX_PFX_INDEX(unit)) = -1;
   5925 
   5926     for (idx = MAX_PFX_INDEX(unit); idx >= 0; idx--) {
   5927         if ((idx == MAX_PFX_INDEX(unit)) && (SOC_LPM_STATE_START(unit, idx) <= 0)) {
   5928             continue;
   5929         }
   5930             
   5931         if (-1 == SOC_LPM_STATE_START(unit, idx)) {
   5932             continue;
   5933         }
   5934 
   5935         if (prev_idx != idx) {
   5936             SOC_LPM_STATE_PREV(unit, idx) = prev_idx;
   5937             SOC_LPM_STATE_NEXT(unit, prev_idx) = idx;
   5938         }
   5939         SOC_LPM_STATE_FENT(unit, prev_idx) =                    \
   5940                           SOC_LPM_STATE_START(unit, idx) -      \
   5941                           SOC_LPM_STATE_END(unit, prev_idx) - 1;
   5942         prev_idx = idx;
   5943         
   5944         if (idx == MAX_PFX_INDEX(unit) || (ipv6 && SOC_LPM_PFX_IS_V4(unit, idx)) ||
   5945            (!ipv6 && SOC_LPM_PFX_IS_V6_64(unit, idx))) {
   5946             continue;
   5947         }
   5948 
   5949         if (!(soc_feature(unit, soc_feature_l3_shared_defip_table) ||
   5950             (soc_feature(unit, soc_feature_l3_kt2_shared_defip_table)))) {
   5951             continue;
   5952         }
   5953 
   5954         if (SOC_LPM_PFX_IS_V4(unit, idx)) {
   5955             from_ent = SOC_LPM_STATE_END(unit, idx);
   5956 #ifdef FB_LPM_TABLE_CACHED
   5957         SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(unit, L3_DEFIPm,
   5958                                                      MEM_BLOCK_ANY, from_ent));
   5959 #endif /* FB_LPM_TABLE_CACHED */
   5960             rv = READ_L3_DEFIPm(unit, MEM_BLOCK_ANY, from_ent, e);
   5961             SOC_IF_ERROR_RETURN(rv);
   5962             if (!soc_feature(unit, soc_feature_half_of_l3_defip_ipv4_capacity)) {
   5963                 v0 = SOC_MEM_OPT_F32_VALID0_GET(unit, mem, e);
   5964                 v1 = SOC_MEM_OPT_F32_VALID1_GET(unit, mem, e);
   5965                 SOC_LPM_V4_COUNT(unit) += (SOC_LPM_STATE_VENT(unit, idx) << 1);
   5966                 if ((v0 == 0) || (v1 == 0)) {
   5967                     SOC_LPM_V4_COUNT(unit) -= 1;
   5968                 }
   5969                 if ((v0 && (!(v1))) || (!(v0) && v1)) {
   5970                     SOC_LPM_COUNT_INC(SOC_LPM_V4_HALF_ENTRY_COUNT(unit));
   5971                     SOC_LPM_STATE_HFENT(unit, idx) = 1;
   5972                 } 
   5973             } else {
   5974                 SOC_LPM_V4_COUNT(unit) += SOC_LPM_STATE_VENT(unit, idx);
   5975             }
   5976         } else {
   5977             SOC_LPM_64BV6_COUNT(unit) += SOC_LPM_STATE_VENT(unit, idx);
   5978         }
   5979     }
   5980 
   5981     SOC_LPM_STATE_NEXT(unit, prev_idx) = -1;
   5982     SOC_LPM_STATE_FENT(unit, prev_idx) =                       \
   5983                           defip_table_size -                   \
   5984                           SOC_LPM_STATE_END(unit, prev_idx) - 1;
   5985 
   5986 #if defined(BCM_KATANA_SUPPORT)
   5987     if (SOC_IS_KATANA(unit)) {
   5988         SOC_LPM_STATE_FENT(unit, MAX_PFX_INDEX(unit)) =
   5989                 kt_lpm_ipv6_info[unit]->ipv6_64b.depth;
   5990     }
   5991 #endif
   5992 
   5993     return (SOC_E_NONE);
   5994 }
   5995 
   5996 int
   5997 soc_fb_lpm_reinit(int unit, int idx, uint32 *lpm_entry)
   5998 {
   5999     int pfx_len;
   6000 #ifdef BCM_TOMAHAWK2_SUPPORT
   6001     uint32 lpm_entry_tmp[SOC_MAX_MEM_WORDS];
   6002     sal_memset(&lpm_entry_tmp, 0,sizeof(lpm_entry_tmp));
   6003 #endif
   6004     if (SOC_IS_HAWKEYE(unit)) {
   6005         return SOC_E_NONE;
   6006     }
   6007 #ifdef BCM_TOMAHAWK2_SUPPORT
   6008     if (soc_feature(unit, soc_feature_half_of_l3_defip_ipv4_capacity) && 
   6009         SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VALID1f) && 
   6010         !SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, defip_mode1_field)) {
   6011         soc_fb_lpm_ip4entry1_to_0(unit, lpm_entry, &lpm_entry_tmp, TRUE);
   6012         SOC_IF_ERROR_RETURN
   6013             (_soc_fb_lpm_prefix_length_get(unit, &lpm_entry_tmp, &pfx_len));
   6014     } else 
   6015 #endif
   6016     {
   6017         SOC_IF_ERROR_RETURN
   6018             (_soc_fb_lpm_prefix_length_get(unit, lpm_entry, &pfx_len));
   6019     }
   6020     if (SOC_LPM_STATE_VENT(unit, pfx_len) == 0) {
   6021         SOC_LPM_STATE_START(unit, pfx_len) = idx;
   6022         SOC_LPM_STATE_END(unit, pfx_len) = idx;
   6023     } else {
   6024         SOC_LPM_STATE_END(unit, pfx_len) = idx;
   6025     }
   6026 
   6027     SOC_LPM_STATE_VENT(unit, pfx_len)++;
   6028     LPM_HASH_INSERT(unit, lpm_entry, idx, NULL, NULL);
   6029     LPM_AVL_INSERT(unit, lpm_entry, idx);
   6030 
   6031     return (SOC_E_NONE);
   6032 }
   6033 
   6034 
   6035 #endif /* BCM_WARM_BOOT_SUPPORT */
   6036 
   6037 
   6038 /*
   6039  * Function:
   6040  *     soc_fb_lpm_sw_dump
   6041  * Purpose:
   6042  *     Displays FB LPM information maintained by software.
   6043  * Parameters:
   6044  *     unit - Device unit number
   6045  * Returns:
   6046  *     None
   6047  */
   6048 void
   6049 soc_fb_lpm_sw_dump(int unit)
   6050 {
   6051     soc_lpm_state_p  lpm_state;
   6052     int              i;
   6053 
   6054     LOG_CLI((BSL_META_U(unit,
   6055                         "\n    FB LPM State -\n")));
   6056     LOG_CLI((BSL_META_U(unit,
   6057                         "        Prefix entries : %d\n"), MAX_PFX_ENTRIES(unit)));
   6058 
   6059     lpm_state = soc_lpm_state[unit];
   6060     if (lpm_state == NULL) {
   6061         return;
   6062     }
   6063 
   6064     for (i = 0; i < MAX_PFX_INDEX(unit); i++) {
   6065         if (lpm_state[i].vent != 0 || lpm_state[i].fent != 0 || 
   6066             lpm_state[i].prev != -1 || lpm_state[i].next != -1) {
   6067             LOG_CLI((BSL_META_U(unit,
   6068                                 "      Prefix %d\n"), i));
   6069             LOG_CLI((BSL_META_U(unit,
   6070                                 "        Start : %d\n"), lpm_state[i].start));
   6071             LOG_CLI((BSL_META_U(unit,
   6072                                 "        End   : %d\n"), lpm_state[i].end));
   6073             LOG_CLI((BSL_META_U(unit,
   6074                                 "        Prev  : %d\n"), lpm_state[i].prev));
   6075             LOG_CLI((BSL_META_U(unit,
   6076                                 "        Next  : %d\n"), lpm_state[i].next));
   6077             LOG_CLI((BSL_META_U(unit,
   6078                                 "        Valid Entries : %d\n"), lpm_state[i].vent));
   6079             LOG_CLI((BSL_META_U(unit,
   6080                                 "        Free  Entries : %d\n"), lpm_state[i].fent));
   6081             if (soc_feature(unit, soc_feature_l3_shared_defip_table) ||
   6082                 (soc_feature(unit, soc_feature_l3_kt2_shared_defip_table))) {
   6083                 if (SOC_LPM_PFX_IS_V4(unit, i)) {
   6084                     LOG_CLI((BSL_META_U(unit,
   6085                                         "        Type  : IPV4\n")));
   6086                 } else if (SOC_LPM_PFX_IS_V6_64(unit, i)) {
   6087                     LOG_CLI((BSL_META_U(unit,
   6088                                         "        Type  : 64B IPV6\n")));
   6089                 }
   6090             }
   6091         }
   6092     }
   6093     
   6094     LOG_CLI((BSL_META_U(unit,
   6095                         "      Prefix %d\n"), i));
   6096     LOG_CLI((BSL_META_U(unit,
   6097                         "        Start : %d\n"), lpm_state[i].start));
   6098     LOG_CLI((BSL_META_U(unit,
   6099                         "        End   : %d\n"), lpm_state[i].end));
   6100     LOG_CLI((BSL_META_U(unit,
   6101                         "        Prev  : %d\n"), lpm_state[i].prev));
   6102     LOG_CLI((BSL_META_U(unit,
   6103                         "        Next  : %d\n"), lpm_state[i].next));
   6104     LOG_CLI((BSL_META_U(unit,
   6105                         "        Valid Entries : %d\n"), lpm_state[i].vent));
   6106     LOG_CLI((BSL_META_U(unit,
   6107                         "        Free  Entries : %d\n"), lpm_state[i].fent));
   6108     if (soc_feature(unit, soc_feature_l3_shared_defip_table) ||
   6109         (soc_feature(unit, soc_feature_l3_kt2_shared_defip_table))) {
   6110         LOG_CLI((BSL_META_U(unit,
   6111                             "        Type  : MAX\n")));
   6112     }
   6113     return;
   6114 }
   6115 
   6116 /*
   6117  * Implementation using soc_mem_read/write using entry rippling technique
   6118  * Advantage: A completely sorted table is not required. Lookups can be slow
   6119  * as it will perform a linear search on the entries for a given prefix length.
   6120  * No device access necessary for the search if the table is cached. Auxiliary
   6121  * hash table can be maintained to speed up search(Not implemented) instead of
   6122  * performing a linear search.
   6123  * Small number of entries need to be moved around (97 worst case)
   6124  * for performing insert/update/delete. However CPU needs to do all
   6125  * the work to move the entries.
   6126  */
   6127 
   6128 /*
   6129  * soc_fb_lpm_insert
   6130  * For IPV4 assume only both IP_ADDR0 is valid
   6131  * Moving multiple entries around in h/w vs  doing a linear search in s/w
   6132  */
   6133 int
   6134 soc_fb_lpm_insert(int u, void *entry_data)
   6135 {
   6136     int         pfx;
   6137     int         index, copy_index;
   6138     int         ipv6;
   6139     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   6140     int         rv = SOC_E_NONE;
   6141     int         found = 0;
   6142     uint32      rvt_index0 = 0, rvt_index1 = 0;
   6143     soc_mem_t   mem = L3_DEFIPm;
   6144 
   6145     if (SOC_MEM_IS_VALID(u, mem)) {
   6146         mem = L3_DEFIP_LEVEL1m;
   6147     }
   6148 
   6149     sal_memcpy(e, soc_mem_entry_null(u, mem),
   6150                soc_mem_entry_words(u,mem) * 4);
   6151 
   6152     SOC_LPM_LOCK(u);
   6153     rv = _soc_fb_lpm_match(u, entry_data, e, &index, &pfx, &ipv6);
   6154     if (rv == SOC_E_NOT_FOUND) {
   6155         rv = _lpm_free_slot_create(u, pfx, ipv6, e, &index);
   6156         if (rv < 0) {
   6157             SOC_LPM_UNLOCK(u);
   6158             return(rv);
   6159         }
   6160     } else {
   6161         found = 1;
   6162     }
   6163 
   6164     copy_index = index;
   6165     if (rv == SOC_E_NONE) {
   6166         /* Entry already present. Update the entry */
   6167         if (!ipv6) {
   6168             /* IPV4 entry */
   6169             if (index & 1) {
   6170                 rv = soc_fb_lpm_ip4entry0_to_1(u, entry_data, e, PRESERVE_HIT);
   6171             } else {
   6172                 rv = soc_fb_lpm_ip4entry0_to_0(u, entry_data, e, PRESERVE_HIT);
   6173             }
   6174 
   6175             if (rv < 0) {
   6176                 SOC_LPM_UNLOCK(u);
   6177                 return(rv);
   6178             }
   6179 
   6180             entry_data = (void *)e;
   6181             index >>= 1;
   6182         }
   6183         soc_fb_lpm_state_dump(u);
   6184         LOG_INFO(BSL_LS_SOC_LPM,
   6185                  (BSL_META_U(u,
   6186                              "\nsoc_fb_lpm_insert: %d %d\n"),
   6187                              index, pfx));
   6188         if (!found) {
   6189             LPM_HASH_INSERT(u, entry_data, index, &rvt_index0, &rvt_index1);
   6190             if ((soc_feature(u, soc_feature_l3_shared_defip_table)) ||
   6191                 (soc_feature(u, soc_feature_shared_defip_stat_support))) {
   6192                 if (ipv6) {
   6193                     SOC_LPM_COUNT_INC(SOC_LPM_64BV6_COUNT(u));
   6194                 } else {
   6195                     SOC_LPM_COUNT_INC(SOC_LPM_V4_COUNT(u));
   6196                     if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
   6197                         /* half entry counts should change for new entry only */
   6198                         if (copy_index & 1) {
   6199                             SOC_LPM_COUNT_DEC(SOC_LPM_V4_HALF_ENTRY_COUNT(u));
   6200                         } else {
   6201                             SOC_LPM_COUNT_INC(SOC_LPM_V4_HALF_ENTRY_COUNT(u));
   6202                         }
   6203                     }
   6204                 }
   6205             }
   6206         }
   6207         rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, index, entry_data);
   6208         if ((SOC_MEM_IS_VALID(u, L3_DEFIPm)) && (rv >= 0)) {
   6209             rv = _lpm_fb_urpf_entry_replicate(u, index, -1, entry_data);
   6210         }
   6211         if (!found && rv < 0) {
   6212             LPM_HASH_REVERT(u, entry_data, index, rvt_index0, rvt_index1);
   6213         }
   6214         LPM_AVL_INSERT(u, entry_data, index);
   6215     }
   6216 
   6217     SOC_LPM_UNLOCK(u);
   6218     return(rv);
   6219 }
   6220 
   6221 /*
   6222  * soc_fb_lpm_insert_index
   6223  */
   6224 int
   6225 soc_fb_lpm_insert_index(int u, void *entry_data, int index)
   6226 {
   6227     int         pfx;
   6228     int         ipv6;
   6229     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   6230     uint32      e_temp[SOC_MAX_MEM_FIELD_WORDS] = {0};
   6231     int         rv = SOC_E_NONE;
   6232     int         new_add = 0;
   6233     int         copy_index;
   6234     uint32      rvt_index0 = 0, rvt_index1 = 0;
   6235     int         temp_index = -1;
   6236     soc_mem_t   mem = L3_DEFIPm;
   6237     int mode1;
   6238 
   6239 #if defined(BCM_TOMAHAWK3_SUPPORT)
   6240     if (SOC_MEM_IS_VALID(u, L3_DEFIP_LEVEL1m)) {
   6241         uint32 _key_data[2] = {0, 0};
   6242         mem = L3_DEFIP_LEVEL1m;
   6243         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, KEY0f, _key_data);
   6244         ipv6 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf);
   6245         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, KEY1f, _key_data);
   6246         mode1 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf);
   6247     } else
   6248 #endif
   6249     {
   6250         ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, defip_mode0_field);
   6251         mode1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, defip_mode1_field);
   6252     }
   6253 
   6254     if (index == -2) {
   6255         return soc_fb_lpm_insert(u, entry_data);
   6256     }
   6257 
   6258     SOC_LPM_LOCK(u);
   6259     if (ipv6) {
   6260         if (!mode1) {
   6261             SOC_LPM_UNLOCK(u);
   6262             return (SOC_E_PARAM);
   6263         }
   6264     }
   6265     /* Calculate vrf weighted prefix lengh. */
   6266     _soc_fb_lpm_prefix_length_get(u, entry_data, &pfx); 
   6267 
   6268     if (index == -1) {
   6269         /*
   6270          * Validate free entries in V4 space. In case of atomic write,
   6271          * one entry is reserved in V4 space (two v4 routes).
   6272          * Insert should not be allowed more than (max_v4_count - 2).
   6273          */
   6274         if (soc_feature(u, soc_feature_lpm_atomic_write)) {
   6275             int max_entries, used_entries;
   6276 
   6277             used_entries = SOC_LPM_V4_COUNT(u) - SOC_LPM_V4_HALF_ENTRY_COUNT(u);
   6278             used_entries = ((used_entries + 1) >> 1) + SOC_LPM_V4_HALF_ENTRY_COUNT(u);
   6279             used_entries += SOC_LPM_64BV6_COUNT(u);
   6280             used_entries -= SOC_LPM_STATE_HFENT(u, pfx); /* Entry only half used */
   6281 
   6282             max_entries = SOC_LPM_MAX_64BV6_COUNT(u);
   6283             if (used_entries  >= (max_entries - 1)) {
   6284                 SOC_LPM_UNLOCK(u);
   6285                 return SOC_E_FULL;
   6286             }
   6287         } 
   6288 
   6289         sal_memcpy(e, soc_mem_entry_null(u, mem),
   6290                    soc_mem_entry_words(u,mem) * 4);
   6291         rv = _lpm_free_slot_create(u, pfx, ipv6, e, &index);
   6292         if (SOC_FAILURE(rv)) {
   6293             SOC_LPM_UNLOCK(u);
   6294             return rv;
   6295         }
   6296    
   6297         /*
   6298          * In case of IPv4, while inserting second entry (upper part) into the
   6299          * valid TCAM index, for a momentary time, the entry gets disabled,
   6300          * which results in lookup miss for the existing (lower part) valid entry.
   6301          * In order to avoid atomicity issue, Create a new slot and insert the valid
   6302          * entry to the temporary created index.
   6303          */ 
   6304         if (soc_feature(u, soc_feature_lpm_atomic_write) &&
   6305             (ipv6 == 0) && (index & 1)) {
   6306            rv = _lpm_free_slot_create(u, pfx, ipv6, e_temp, &temp_index);
   6307            if (SOC_FAILURE(rv)) {
   6308               LOG_ERROR(BSL_LS_SOC_LPM, (BSL_META_U(u,
   6309                      "Temporary backup entry slot create failure: %d,"
   6310                      "original_index:%d temp_index:%d pfx:%d\n\r"),
   6311                       rv, index, temp_index, pfx));
   6312               goto cleanup; 
   6313            }
   6314            
   6315            /*
   6316             * Increment Half entry created by reserve entry, which gets
   6317             * decremented while deleting the slot in _lpm_free_slot_delete.
   6318            */
   6319            SOC_LPM_COUNT_INC(SOC_LPM_V4_HALF_ENTRY_COUNT(u));
   6320 
   6321            /* If temp_index happens to be same as index, then thew new
   6322             * slot creattion resulted in pfx_move_down and the last half entry
   6323             * (which originally is expected to be at 'index' would have moved up
   6324             * in the table by one physical entry level. The 'index' now needs to
   6325             * be corrected for this movement.
   6326  */
   6327            if ((temp_index >> 1) == (index >> 1)) {
   6328                /*
   6329                 * (index >> 1) gives physical index; and we decr this by 1
   6330                 * and then convert it back to 'slot' range (by multiplying with 2).
   6331                 * Lastly offset with 1 because we are dealing with the upper half.
   6332  */
   6333                index = (((index >> 1) - 1) << 1) + (index & 1);
   6334            }
   6335            /* Copy index to temp_index */
   6336            rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, (index >> 1), e_temp);
   6337            if (SOC_FAILURE(rv)) {
   6338               goto cleanup; 
   6339            }
   6340            rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, (temp_index >> 1), e_temp);
   6341            if (SOC_FAILURE(rv)) {
   6342               goto cleanup; 
   6343            }
   6344         }
   6345         new_add = 1;
   6346     } else {
   6347         rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY,
   6348                          ipv6 ? index : (index >> 1), e);
   6349     }
   6350 
   6351     copy_index = index;
   6352     if (rv == SOC_E_NONE) {
   6353         /* Entry already present. Update the entry */
   6354         if (!ipv6) {
   6355             /* IPV4 entry */
   6356             if (index & 1) {
   6357                 rv = soc_fb_lpm_ip4entry0_to_1(u, entry_data, e, PRESERVE_HIT);
   6358             } else {
   6359                 rv = soc_fb_lpm_ip4entry0_to_0(u, entry_data, e, PRESERVE_HIT);
   6360             }
   6361 
   6362             if (SOC_FAILURE(rv)) {
   6363                 goto cleanup;
   6364             }
   6365             entry_data = (void *)e;
   6366             index >>= 1;
   6367         }
   6368         soc_fb_lpm_state_dump(u);
   6369         LOG_INFO(BSL_LS_SOC_LPM,
   6370                  (BSL_META_U(u,
   6371                              "\nsoc_fb_lpm_insert_index: %d %d\n"),
   6372                              index, pfx));
   6373         if (new_add) {
   6374             LPM_HASH_INSERT(u, entry_data, index, &rvt_index0, &rvt_index1);
   6375             if ((soc_feature(u, soc_feature_l3_shared_defip_table)) ||
   6376                 (soc_feature(u, soc_feature_shared_defip_stat_support))) {
   6377                 if (ipv6) {
   6378                     SOC_LPM_COUNT_INC(SOC_LPM_64BV6_COUNT(u));
   6379                 } else {
   6380                     SOC_LPM_COUNT_INC(SOC_LPM_V4_COUNT(u));
   6381                     if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
   6382                         if (copy_index & 1) {
   6383                             SOC_LPM_COUNT_DEC(SOC_LPM_V4_HALF_ENTRY_COUNT(u));
   6384                         } else {
   6385                             SOC_LPM_COUNT_INC(SOC_LPM_V4_HALF_ENTRY_COUNT(u));
   6386                         } 
   6387                     }
   6388                 }
   6389             }
   6390         }
   6391         rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, index, entry_data);
   6392         if ((!SOC_IS_TOMAHAWK3(u)) && SOC_SUCCESS(rv)) {
   6393             rv = _lpm_fb_urpf_entry_replicate(u, index,
   6394                      ((temp_index == -1) ? (-1):(temp_index >> 1)) , entry_data);
   6395         }
   6396         if (new_add && SOC_FAILURE(rv)) {
   6397             LPM_HASH_REVERT(u, entry_data, index, rvt_index0, rvt_index1);
   6398         }
   6399         LPM_AVL_INSERT(u, entry_data, index);
   6400 
   6401 cleanup:
   6402         /*
   6403          * Delete the temporary slot created to maintain atomicity.
   6404          */
   6405         if (temp_index != -1) {
   6406            rv = _lpm_free_slot_delete(u, pfx, ipv6, e_temp, temp_index);
   6407            if (SOC_FAILURE(rv)) {
   6408               LOG_ERROR(BSL_LS_SOC_LPM, (BSL_META_U(u,
   6409                      "Temporary backup entry slot delete failure: %d,"
   6410                      "original_index:%d temp_index:%d pfx:%d\n\r"),
   6411                       rv, (index << 1), temp_index, pfx));
   6412            }
   6413         } 
   6414     }
   6415 
   6416     SOC_LPM_UNLOCK(u);
   6417     return(rv);
   6418 }
   6419 
   6420 /*
   6421  * soc_fb_lpm_delete
   6422  */
   6423 int
   6424 soc_fb_lpm_delete(int u, void *key_data)
   6425 {
   6426     int         pfx;
   6427     int         index;
   6428     int         ipv6;
   6429     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   6430     int         rv = SOC_E_NONE;
   6431 
   6432     SOC_LPM_LOCK(u);
   6433     rv = _soc_fb_lpm_match(u, key_data, e, &index, &pfx, &ipv6);
   6434     if (rv == SOC_E_NONE) {
   6435         LOG_INFO(BSL_LS_SOC_LPM,
   6436                  (BSL_META_U(u,
   6437                              "\nsoc_fb_lpm_delete: %d %d\n"),
   6438                              index, pfx));
   6439         LPM_HASH_DELETE(u, key_data, index);
   6440         rv = _lpm_free_slot_delete(u, pfx, ipv6, e, index);
   6441         LPM_AVL_DELETE(u, key_data, index);
   6442         if ((soc_feature(u, soc_feature_l3_shared_defip_table)) ||
   6443             (soc_feature(u, soc_feature_shared_defip_stat_support))) {
   6444             if (ipv6) {
   6445                 SOC_LPM_COUNT_DEC(SOC_LPM_64BV6_COUNT(u));
   6446             } else {
   6447                 SOC_LPM_COUNT_DEC(SOC_LPM_V4_COUNT(u));
   6448             }
   6449         }
   6450     }
   6451     soc_fb_lpm_state_dump(u);
   6452     SOC_LPM_UNLOCK(u);
   6453     return(rv);
   6454 }
   6455 
   6456 /*
   6457  * soc_fb_lpm_delete_index
   6458  */
   6459 int
   6460 soc_fb_lpm_delete_index(int u, void *key_data, int index)
   6461 {
   6462     int         pfx;
   6463     int         ipv6;
   6464     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   6465     int         rv = SOC_E_NONE;
   6466 
   6467     if (index == -1) {
   6468         return soc_fb_lpm_delete(u, key_data);
   6469     } 
   6470 
   6471 #if defined(BCM_TOMAHAWK3_SUPPORT)
   6472     if (SOC_IS_TOMAHAWK3(u)) {
   6473         uint32 _key_data[2] = {0, 0};
   6474         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, key_data, KEY0f, _key_data);
   6475         ipv6 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf);
   6476         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, key_data, KEY1f, _key_data);
   6477     } else
   6478 #endif
   6479     {
   6480         ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, defip_mode0_field);
   6481     }
   6482 
   6483     SOC_LPM_LOCK(u);
   6484     /* Calculate vrf weighted prefix lengh. */
   6485     _soc_fb_lpm_prefix_length_get(u, key_data, &pfx); 
   6486     rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY,
   6487                      ipv6 ? index : (index >> 1), e);
   6488 
   6489     if (rv == SOC_E_NONE) {
   6490         LOG_INFO(BSL_LS_SOC_LPM,
   6491                  (BSL_META_U(u,
   6492                              "\nsoc_fb_lpm_delete_index: %d %d\n"),
   6493                              index, pfx));
   6494         LPM_HASH_DELETE(u, key_data, index);
   6495         rv = _lpm_free_slot_delete(u, pfx, ipv6, e, index);
   6496         LPM_AVL_DELETE(u, key_data, index);
   6497         if ((soc_feature(u, soc_feature_l3_shared_defip_table)) ||
   6498             (soc_feature(u, soc_feature_shared_defip_stat_support))) {
   6499             if (ipv6) {
   6500                 SOC_LPM_COUNT_DEC(SOC_LPM_64BV6_COUNT(u));
   6501             } else {
   6502                 SOC_LPM_COUNT_DEC(SOC_LPM_V4_COUNT(u));
   6503             }
   6504         }
   6505     }
   6506     soc_fb_lpm_state_dump(u);
   6507     SOC_LPM_UNLOCK(u);
   6508     return(rv);
   6509 }
   6510 
   6511 /*
   6512  * soc_fb_lpm_match (Exact match for the key. Will match both IP
   6513  *                   address and mask)
   6514  */
   6515 int
   6516 soc_fb_lpm_match(int u,
   6517                void *key_data,
   6518                void *e,         /* return entry data if found */
   6519                int *index_ptr)  /* return key location */
   6520 {
   6521     int        pfx;
   6522     int        rv;
   6523     int        ipv6;
   6524 
   6525     SOC_LPM_LOCK(u);
   6526     rv = _soc_fb_lpm_match(u, key_data, e, index_ptr, &pfx, &ipv6);
   6527     SOC_LPM_UNLOCK(u);
   6528     return(rv);
   6529 }
   6530 
   6531 /*
   6532  * soc_fb_lpm_lookup (LPM search). Masked match.
   6533  */
   6534 int
   6535 soc_fb_lpm_lookup(int u,
   6536                void *key_data,
   6537                void *entry_data,
   6538                int *index_ptr)
   6539 {
   6540     return(SOC_E_UNAVAIL);
   6541 }
   6542 
   6543 /*
   6544  * Function:
   6545  *	soc_fb_lpm_ipv4_delete_index
   6546  * Purpose:
   6547  *	Delete an entry from a LPM table based on index,
   6548  * Parameters:
   6549  *	u - StrataSwitch unit #
   6550  *	Index for IPv4 entry is 0 .. 2 * max_index + 1. 
   6551  *      If entry appears at offset N and entry 0 of the table
   6552  *      then index = 2 * N + 0.
   6553  *      If entry appears at offset N and entry 1 of the table
   6554  *      then index = 2 * N + 1.
   6555  *                            =========================================
   6556  *     Offset N - 1           =  IPV4 Entry 1    =  IPV4 Entry 0      =
   6557  *                            =========================================
   6558  *     Offset N               =  IPV4 Entry 1    =  IPV4 Entry 0      =
   6559  *                            =========================================
   6560  *     Offset N + 1           =  IPV4 Entry 1    =  IPV4 Entry 0      =
   6561  *                            =========================================
   6562  */
   6563 int
   6564 soc_fb_lpm_ipv4_delete_index(int u, int index)
   6565 {
   6566     int         pfx;
   6567     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   6568     int         rv = SOC_E_NONE;
   6569 
   6570     SOC_LPM_LOCK(u);
   6571     rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, index / 2, e); 
   6572     if (rv == SOC_E_NONE) {
   6573         if ((soc_mem_field32_get(u, L3_DEFIPm, e,
   6574                                 (index % 2) ? VALID1f : VALID0f)) &&
   6575             (soc_mem_field32_get(u, L3_DEFIPm, e,
   6576                                 (index % 2) ? defip_mode1_bit[u] : defip_mode0_bit[u]) == 0)) {
   6577             uint32      ipv4a;
   6578             ipv4a = soc_mem_field32_get(u, L3_DEFIPm, e,
   6579                                         (index % 2) ?
   6580                                         IP_ADDR_MASK1f : IP_ADDR_MASK0f);
   6581             rv = _ipmask2pfx(ipv4a, &pfx);
   6582         } else {
   6583             rv = SOC_E_PARAM;
   6584         }
   6585         if (rv == SOC_E_NONE) {
   6586             LOG_INFO(BSL_LS_SOC_LPM,
   6587                      (BSL_META_U(u,
   6588                                  "\nsoc_fb_lpm_ipv4_delete_index: %d %d\n"),
   6589                       index, pfx));
   6590             LPM_HASH_DELETE(u, e, index);
   6591             rv = _lpm_free_slot_delete(u, pfx, FALSE, e, index);
   6592             LPM_AVL_DELETE(u, e, index);
   6593         }
   6594         soc_fb_lpm_state_dump(u);
   6595     }
   6596     SOC_LPM_UNLOCK(u);
   6597     return(rv);
   6598 }
   6599 
   6600 /*
   6601  * Function:
   6602  *	soc_fb_lpm_ipv6_delete_index
   6603  * Purpose:
   6604  *	Delete an entry from a LPM table based on index,
   6605  * Parameters:
   6606  *	u - StrataSwitch unit #
   6607  *	Index for IPv6 entry is 0 .. max_index. 
   6608  *                            =========================================
   6609  *     Offset N - 1           =  IPV6 Entry                           =
   6610  *                            =========================================
   6611  *     Offset N               =  IPV6 Entry                           =
   6612  *                            =========================================
   6613  *     Offset N + 1           =  IPV6 Entry                           =
   6614  *                            =========================================
   6615  */
   6616 int
   6617 soc_fb_lpm_ipv6_delete_index(int u, int index)
   6618 {
   6619     int         pfx;
   6620     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   6621     int         rv = SOC_E_NONE;
   6622 
   6623     SOC_LPM_LOCK(u);
   6624     rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, index , e); 
   6625     if (rv == SOC_E_NONE) {
   6626         if ((SOC_MEM_OPT_F32_VALID0_GET(u, L3_DEFIPm, e)) &&
   6627             (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, defip_mode0_field)) &&
   6628             (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, defip_mode1_field)) &&
   6629             (SOC_MEM_OPT_F32_VALID1_GET(u, L3_DEFIPm, e))) {
   6630             uint32      ipv4a;
   6631  
   6632             ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, IP_ADDR_MASK0f);
   6633             if ((rv = _ipmask2pfx(ipv4a, &pfx)) == SOC_E_NONE) {
   6634                 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, IP_ADDR_MASK1f);
   6635                 if (pfx) {
   6636                     if (ipv4a != 0xffffffff)  {
   6637                         rv =SOC_E_PARAM;
   6638                     }
   6639                     pfx += 32;
   6640                 } else {
   6641                     rv = _ipmask2pfx(ipv4a, &pfx);
   6642                 }
   6643             }
   6644         } else {
   6645             rv = SOC_E_PARAM;
   6646         }
   6647         if (rv == SOC_E_NONE) {
   6648             LOG_INFO(BSL_LS_SOC_LPM,
   6649                      (BSL_META_U(u,
   6650                                  "\nsoc_fb_lpm_ipv4_delete_index: %d %d\n"),
   6651                       index, pfx));
   6652             LPM_HASH_DELETE(u, e, index);
   6653             rv = _lpm_free_slot_delete(u, pfx, TRUE,e, index);
   6654             LPM_AVL_DELETE(u, e, index);
   6655         }
   6656         soc_fb_lpm_state_dump(u);
   6657     }
   6658     SOC_LPM_UNLOCK(u);
   6659     return(rv);
   6660 }
   6661 
   6662 int soc_fb_get_largest_prefix(int u, int ipv6, void *e, 
   6663                               int *index, int *pfx_len, int* count)
   6664 {
   6665     int curr_pfx = MAX_PFX_INDEX(u);
   6666     int next_pfx = SOC_LPM_STATE_NEXT(u, curr_pfx);
   6667     int rv = SOC_E_NOT_FOUND;
   6668     uint32 v0, v1;
   6669     soc_mem_t mem = L3_DEFIPm;
   6670 
   6671     while (next_pfx != -1) {
   6672         if (!ipv6 && SOC_LPM_PFX_IS_V4(u, next_pfx)) {
   6673             break; 
   6674         } else if(ipv6 && SOC_LPM_PFX_IS_V6_64(u, next_pfx)) {
   6675            break;
   6676         } 
   6677         next_pfx = SOC_LPM_STATE_NEXT(u, next_pfx);  
   6678     }
   6679 
   6680     if (next_pfx == -1) {
   6681         return rv;
   6682     }
   6683 
   6684     *index = SOC_LPM_STATE_END(u, next_pfx);
   6685     *pfx_len = next_pfx;
   6686 
   6687 #ifdef FB_LPM_TABLE_CACHED
   6688     if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm,
   6689                                        MEM_BLOCK_ANY, *index)) < 0) {
   6690         return rv;
   6691     }
   6692 #endif /* FB_LPM_TABLE_CACHED */
   6693     if ((rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, *index, e)) < 0) {
   6694         return rv;
   6695     }
   6696 
   6697 #if defined(BCM_TOMAHAWK3_SUPPORT)
   6698     if (SOC_IS_TOMAHAWK3(u)) {
   6699         mem = L3_DEFIP_LEVEL1m;
   6700     }
   6701 #endif
   6702 
   6703     v0 = SOC_MEM_OPT_F32_VALID0_GET(u, mem, e);
   6704     v1 = SOC_MEM_OPT_F32_VALID1_GET(u, mem, e);
   6705 
   6706    
   6707     *count = (v0 == 1) ? 1 : 0;
   6708     if (!ipv6 && v1) {
   6709        *count = 2;    
   6710     }
   6711     return rv;
   6712 }
   6713 
   6714 
   6715                         /* LPM 128 code starts here */
   6716 
   6717 #define LPM128_HASH_INSERT(u, entry_data, entry_data_upr, tab_index, rvt_index0, rvt_index1)  \
   6718     soc_fb_lpm128_hash_insert(u, entry_data, entry_data_upr, tab_index, LPM_NO_MATCH_INDEX, 0,\
   6719                               rvt_index0, rvt_index1)
   6720 
   6721 #define LPM128_HASH_REVERT(u, entry_data, entry_data_upr, tab_index, rvt_index0, rvt_index1)  \
   6722     soc_fb_lpm128_hash_revert(u, entry_data, entry_data_upr, tab_index, rvt_index0, rvt_index1) 
   6723 
   6724 #define LPM128_HASH_DELETE(u, key_data, key_data_upr, tab_index)         \
   6725     soc_fb_lpm128_hash_delete(u, key_data, key_data_upr, tab_index)
   6726 
   6727 #define LPM128_HASH_LOOKUP(u, key_data, key_data_upr, pfx, tab_index)    \
   6728     soc_fb_lpm128_hash_lookup(u, key_data, key_data_upr, pfx, tab_index)
   6729 
   6730 
   6731 
   6732 STATIC
   6733 void _soc_fb_lpm128_hash_entry_get(int u, void *e, void *eupr,
   6734                                    int index, _soc_fb_lpm128_hash_entry_t r_entry,
   6735                                    int *v)
   6736 {
   6737     soc_mem_t mem = L3_DEFIPm;
   6738 #if defined(BCM_TOMAHAWK3_SUPPORT)
   6739     if (SOC_IS_TOMAHAWK3(u)) {
   6740         mem = L3_DEFIP_LEVEL1m;
   6741     }
   6742 #endif
   6743 
   6744     if (index & FB_LPM_HASH_IPV6_MASK) {
   6745         SOC_FB_LPM128_HASH_ENTRY_IPV6_GET(u, e, eupr, r_entry);
   6746         if (v) {
   6747             *v = SOC_MEM_OPT_F32_VALID0_GET(u, mem, e) &&
   6748                  SOC_MEM_OPT_F32_VALID1_GET(u, mem, e) &&
   6749                  SOC_MEM_OPT_F32_VALID0_GET(u, mem, eupr) &&
   6750                  SOC_MEM_OPT_F32_VALID1_GET(u, mem, eupr);
   6751         }
   6752     } else {
   6753         if (index & 0x1) {
   6754             SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, e, r_entry);
   6755             if (v) {
   6756                 *v = SOC_MEM_OPT_F32_VALID0_GET(u, mem, e);
   6757             }
   6758         } else {
   6759             SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, e, r_entry);
   6760             if (v) {
   6761                 *v = SOC_MEM_OPT_F32_VALID0_GET(u, mem, e);
   6762             }
   6763         }
   6764     }
   6765 }
   6766 
   6767 /*
   6768  * Function:
   6769  *      _soc_fb_lpm128_hash_insert
   6770  * Purpose:
   6771  *      Insert/Update a key index in the hash table
   6772  * Parameters:
   6773  *      hash - Pointer (handle) to Hash Table
   6774  *      key_cmp_fn - Compare function which should compare key
   6775  *      entry   - The key to lookup
   6776  *      pfx     - Prefix length for lookup acceleration.
   6777  *      old_index - Index where the key was moved from.
   6778  *                  FB_LPM_HASH_INDEX_NULL if new entry.
   6779  *      new_index - Index where the key was moved to.
   6780  * Returns:
   6781  *      SOC_E_NONE      Key found
   6782  */
   6783 /*
   6784  *      Should be caled before updating the LPM table so that the
   6785  *      data in the hash table is consistent with the LPM table
   6786  */
   6787 static
   6788 int _soc_fb_lpm128_hash_insert(_soc_fb_lpm_hash_t *hash,
   6789                             _soc_fb_lpm128_hash_compare_fn key_cmp_fn,
   6790                             _soc_fb_lpm128_hash_entry_t entry,
   6791                             int    pfx,
   6792                             uint32 old_index,
   6793                             uint32 new_index,
   6794                             uint32 *rvt_index)
   6795 {
   6796     int u = hash->unit, v, i = 0;
   6797     uint16 hash_val;
   6798     uint32 index;
   6799     uint32 prev_index;
   6800     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   6801     int rv = SOC_E_NONE;
   6802 
   6803     if (rvt_index) {
   6804         *rvt_index = FB_LPM_HASH_INDEX_NULL;
   6805     }
   6806     hash_val = _soc_fb_lpm_hash_compute((uint8 *)entry,
   6807                (32 * _SOC_LPM128_HASH_KEY_LEN_IN_WORDS)) % hash->index_count;
   6808     index = hash->table[hash_val];
   6809     H_INDEX_MATCH("ihash", entry[0], hash_val);
   6810     H_INDEX_MATCH("ins  ", entry[0], new_index);
   6811     H_INDEX_MATCH("ins1 ", index, new_index);
   6812     prev_index = FB_LPM_HASH_INDEX_NULL;
   6813     if (old_index != FB_LPM_HASH_INDEX_NULL) {
   6814         while(index != FB_LPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   6815             uint32  e[SOC_MAX_MEM_FIELD_WORDS];
   6816             uint32  eupr[SOC_MAX_MEM_FIELD_WORDS];
   6817             _soc_fb_lpm128_hash_entry_t  r_entry = {0};
   6818             int     rindex;
   6819 
   6820             rindex = (index & FB_LPM_HASH_INDEX_MASK) >> 1;
   6821 
   6822             /*
   6823              * Check prefix length and skip index if not valid for given length
   6824             if ((SOC_LPM_STATE_START(u, pfx) <= rindex) &&
   6825                 (SOC_LPM_STATE_END(u, pfx) >= rindex)) {
   6826              */
   6827             rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, rindex, e);
   6828             SOC_IF_ERROR_RETURN(rv);
   6829             if (index & FB_LPM_HASH_IPV6_MASK) {
   6830                 rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, rindex + tcam_depth, eupr);
   6831                 SOC_IF_ERROR_RETURN(rv);
   6832                 SOC_FB_LPM128_HASH_ENTRY_GET(u, e, eupr, index, r_entry, &v);
   6833             } else {
   6834                 SOC_FB_LPM128_HASH_ENTRY_GET(u, e, NULL, index, r_entry, &v);
   6835             }
   6836             if (v == 0) {
   6837                 if ((index & FB_LPM_HASH_IPV6_MASK) ||
   6838                     !((new_index & 1) && (new_index == (index + 1)))) {
   6839                     LOG_ERROR(BSL_LS_SOC_LPM,
   6840                           (BSL_META_U(u,
   6841                                     "Empty entry[%d] in link_table. hash_val %d ridx %d nidx %d\n"),
   6842                                     index, hash_val, rindex, new_index));
   6843                 }
   6844             }
   6845             if (v && ((*key_cmp_fn)(entry, r_entry) == 0)) {
   6846                 /* assert(old_index == index);*/
   6847                 if (new_index != index) {
   6848                     H_INDEX_MATCH("imove", prev_index, new_index);
   6849                     if (prev_index == FB_LPM_HASH_INDEX_NULL) {
   6850                         INDEX_UPDATE(hash, hash_val, index, new_index);
   6851                     } else {
   6852                         INDEX_UPDATE_LINK(hash, prev_index, index, new_index);
   6853                     }
   6854                 }
   6855                 if (rvt_index) {
   6856                     *rvt_index = index;
   6857                 }
   6858                 H_INDEX_MATCH("imtch", index, new_index);
   6859                 return(SOC_E_NONE);
   6860             }
   6861             /*
   6862             }
   6863             */
   6864             prev_index = index;
   6865             index = hash->link_table[index & FB_LPM_HASH_INDEX_MASK];
   6866             H_INDEX_MATCH("ins2 ", index, new_index);
   6867         }
   6868     }
   6869     if (i > hash->entry_count) {
   6870         LOG_ERROR(BSL_LS_SOC_LPM,
   6871                   (BSL_META_U(u,
   6872                             "Hash loop\n")));
   6873         return SOC_E_INTERNAL;
   6874     }
   6875     INDEX_ADD(hash, hash_val, new_index);  /* new entry */
   6876     return(SOC_E_NONE);
   6877 }
   6878 
   6879 /*
   6880  * Function:
   6881  *      _soc_fb_lpm128_hash_lookup
   6882  * Purpose:
   6883  *      Look up a key in the hash table
   6884  * Parameters:
   6885  *      hash - Pointer (handle) to Hash Table
   6886  *      key_cmp_fn - Compare function which should compare key
   6887  *      entry   - The key to lookup
   6888  *      pfx     - Prefix length for lookup acceleration.
   6889  *      key_index - (OUT)       Index where the key was found.
   6890  * Returns:
   6891  *      SOC_E_NONE      Key found
   6892  *      SOC_E_NOT_FOUND Key not found
   6893  */
   6894 
   6895 static
   6896 int _soc_fb_lpm128_hash_lookup(_soc_fb_lpm_hash_t          *hash,
   6897                             _soc_fb_lpm128_hash_compare_fn key_cmp_fn,
   6898                             _soc_fb_lpm128_hash_entry_t    entry,
   6899                             int                         pfx,
   6900                             uint32                      *key_index)
   6901 {
   6902     int u = hash->unit, v, i = 0;
   6903 
   6904     uint16 hash_val;
   6905     uint32 index;
   6906     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   6907 
   6908     hash_val = _soc_fb_lpm_hash_compute((uint8 *)entry,
   6909                (32 * _SOC_LPM128_HASH_KEY_LEN_IN_WORDS)) % hash->index_count;
   6910     index = hash->table[hash_val];
   6911     H_INDEX_MATCH("lhash", entry[0], hash_val);
   6912     H_INDEX_MATCH("lkup ", entry[0], index);
   6913     while(index != FB_LPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   6914         uint32  e[SOC_MAX_MEM_FIELD_WORDS];
   6915         uint32  eupr[SOC_MAX_MEM_FIELD_WORDS];
   6916         _soc_fb_lpm128_hash_entry_t  r_entry = {0};
   6917         int     rindex;
   6918         int rv = SOC_E_NONE;
   6919 
   6920         rindex = (index & FB_LPM_HASH_INDEX_MASK) >> 1;
   6921         /*
   6922          * Check prefix length and skip index if not valid for given length
   6923         if ((SOC_LPM_STATE_START(u, pfx) <= rindex) &&
   6924             (SOC_LPM_STATE_END(u, pfx) >= rindex)) {
   6925          */
   6926         rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, rindex, e);
   6927         SOC_IF_ERROR_RETURN(rv);
   6928         if (index & FB_LPM_HASH_IPV6_MASK) {
   6929             rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, \
   6930                                                rindex + tcam_depth, eupr);
   6931             SOC_IF_ERROR_RETURN(rv);
   6932             SOC_FB_LPM128_HASH_ENTRY_GET(u, e, eupr, index, r_entry, &v);
   6933         } else {
   6934             SOC_FB_LPM128_HASH_ENTRY_GET(u, e, NULL, index, r_entry, &v);
   6935         }
   6936         if (v == 0) {
   6937             LOG_ERROR(BSL_LS_SOC_LPM,
   6938                       (BSL_META_U(u,
   6939                                 "Empty entry[%d] in link_table. hash_val %d ridx %d\n"),
   6940                                 index, hash_val, rindex));
   6941         }
   6942         if ((*key_cmp_fn)(entry, r_entry) == 0) {
   6943             *key_index = (index & FB_LPM_HASH_INDEX_MASK) >>
   6944                             ((index & FB_LPM_HASH_IPV6_MASK) ? 1 : 0);
   6945             H_INDEX_MATCH("found", entry[0], index);
   6946             return(SOC_E_NONE);
   6947         }
   6948         /*
   6949         }
   6950         */
   6951         index = hash->link_table[index & FB_LPM_HASH_INDEX_MASK];
   6952         H_INDEX_MATCH("lkup1", entry[0], index);
   6953     }
   6954     if (i > hash->entry_count) {
   6955         LOG_ERROR(BSL_LS_SOC_LPM,
   6956                   (BSL_META_U(u,
   6957                             "Hash loop\n")));
   6958     }
   6959     H_INDEX_MATCH("not_found", entry[0], index);
   6960     return(SOC_E_NOT_FOUND);
   6961 }
   6962 
   6963 /*
   6964  * Function:
   6965  *      _soc_fb_lpm128_hash_revert
   6966  * Purpose:
   6967  *      Revert a key index in the hash table
   6968  * Parameters:
   6969  *      hash - Pointer (handle) to Hash Table
   6970  *      key_cmp_fn - Compare function which should compare key
   6971  *      entry   - The key to delete
   6972  *      pfx     - Prefix length for lookup acceleration.
   6973  *      new_index - Index to delete.
   6974  * Returns:
   6975  *      SOC_E_NONE      Success
   6976  *      SOC_E_NOT_FOUND Key index not found.
   6977  */
   6978 static
   6979 int _soc_fb_lpm128_hash_revert(_soc_fb_lpm_hash_t *hash,
   6980                             _soc_fb_lpm128_hash_compare_fn key_cmp_fn,
   6981                             _soc_fb_lpm128_hash_entry_t entry,
   6982                             uint32 new_index,
   6983                             uint32 rvt_index)
   6984 {
   6985     int u = hash->unit, i = 0;
   6986     uint16 hash_val;
   6987     uint32 index;
   6988     uint32 prev_index;
   6989 
   6990     hash_val = _soc_fb_lpm_hash_compute((uint8 *)entry,
   6991                (32 * _SOC_LPM128_HASH_KEY_LEN_IN_WORDS)) % hash->index_count;
   6992     index = hash->table[hash_val];
   6993     H_INDEX_MATCH("rhash", entry[0], hash_val);
   6994     H_INDEX_MATCH("rvt  ", entry[0], index);
   6995     prev_index = FB_LPM_HASH_INDEX_NULL;
   6996     while(index != FB_LPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   6997         if (new_index == index) {
   6998             H_INDEX_MATCH("rfoun", entry[0], index);
   6999             if (rvt_index == FB_LPM_HASH_INDEX_NULL) {
   7000                 if (prev_index == FB_LPM_HASH_INDEX_NULL) {
   7001                     INDEX_DELETE(hash, hash_val, new_index);
   7002                 } else {
   7003                     INDEX_DELETE_LINK(hash, prev_index, new_index);
   7004                 }
   7005             } else {
   7006                 if (prev_index == FB_LPM_HASH_INDEX_NULL) {
   7007                     INDEX_UPDATE(hash, hash_val, new_index, rvt_index);
   7008                 } else {
   7009                     INDEX_UPDATE_LINK(hash, prev_index, new_index, rvt_index);
   7010                 }
   7011             }
   7012             return(SOC_E_NONE);
   7013         }
   7014         prev_index = index;
   7015         index = hash->link_table[index & FB_LPM_HASH_INDEX_MASK];
   7016         H_INDEX_MATCH("rvt1 ", entry[0], index);
   7017     }
   7018     if (i > hash->entry_count) {
   7019         LOG_ERROR(BSL_LS_SOC_LPM,
   7020                   (BSL_META_U(u,
   7021                             "Hash loop\n")));
   7022     }
   7023     return(SOC_E_NOT_FOUND);
   7024 }
   7025 
   7026 /*
   7027  * Function:
   7028  *      _soc_fb_lpm128_hash_delete
   7029  * Purpose:
   7030  *      Delete a key index in the hash table
   7031  * Parameters:
   7032  *      hash - Pointer (handle) to Hash Table
   7033  *      key_cmp_fn - Compare function which should compare key
   7034  *      entry   - The key to delete
   7035  *      pfx     - Prefix length for lookup acceleration.
   7036  *      delete_index - Index to delete.
   7037  * Returns:
   7038  *      SOC_E_NONE      Success
   7039  *      SOC_E_NOT_FOUND Key index not found.
   7040  */
   7041 static
   7042 int _soc_fb_lpm128_hash_delete(_soc_fb_lpm_hash_t *hash,
   7043                             _soc_fb_lpm128_hash_compare_fn key_cmp_fn,
   7044                             _soc_fb_lpm128_hash_entry_t entry,
   7045                             int    pfx,
   7046                             uint32 delete_index)
   7047 {
   7048     int u = hash->unit, i = 0;
   7049     uint16 hash_val;
   7050     uint32 index;
   7051     uint32 prev_index;
   7052 
   7053     hash_val = _soc_fb_lpm_hash_compute((uint8 *)entry,
   7054                (32 * _SOC_LPM128_HASH_KEY_LEN_IN_WORDS)) % hash->index_count;
   7055     index = hash->table[hash_val];
   7056     H_INDEX_MATCH("dhash", entry[0], hash_val);
   7057     H_INDEX_MATCH("del  ", entry[0], index);
   7058     prev_index = FB_LPM_HASH_INDEX_NULL;
   7059     while(index != FB_LPM_HASH_INDEX_NULL && i++ < hash->entry_count) {
   7060         if (delete_index == index) {
   7061             H_INDEX_MATCH("dfoun", entry[0], index);
   7062             if (prev_index == FB_LPM_HASH_INDEX_NULL) {
   7063                 INDEX_DELETE(hash, hash_val, delete_index);
   7064             } else {
   7065                 INDEX_DELETE_LINK(hash, prev_index, delete_index);
   7066             }
   7067             return(SOC_E_NONE);
   7068         }
   7069         prev_index = index;
   7070         index = hash->link_table[index & FB_LPM_HASH_INDEX_MASK];
   7071         H_INDEX_MATCH("del1 ", entry[0], index);
   7072     }
   7073     if (i > hash->entry_count) {
   7074         LOG_ERROR(BSL_LS_SOC_LPM,
   7075                   (BSL_META_U(u,
   7076                             "Hash loop\n")));
   7077     }
   7078     return(SOC_E_NOT_FOUND);
   7079 }
   7080 
   7081 void soc_fb_lpm128_hash_insert(int u, void *entry_data, void *entry_data_upr,
   7082                                uint32 tab_index, uint32 old_index, int pfx,
   7083                                uint32 *rvt_index0, uint32 *rvt_index1)
   7084 {
   7085     _soc_fb_lpm128_hash_entry_t    key_hash = {0};
   7086     soc_mem_t mem = L3_DEFIPm;
   7087     int mode;
   7088 #if defined(BCM_TOMAHAWK3_SUPPORT)
   7089     if (SOC_IS_TOMAHAWK3(u)) {
   7090         uint32 _key_data[2] = {0, 0};
   7091         mem = L3_DEFIP_LEVEL1m;
   7092         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, KEY0f, _key_data);
   7093         mode = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf);
   7094     } else
   7095 #endif
   7096     {
   7097         mode = SOC_MEM_OPT_F32_GET(u, mem, entry_data, defip_mode0_field);
   7098     }
   7099 
   7100     if (mode && mode != 3) {
   7101         LOG_ERROR(BSL_LS_SOC_LPM,
   7102                   (BSL_META_U(u,
   7103                               "Invalid mode while inserting lpm128 hash for pfx - %d\n"), pfx));
   7104         return;
   7105     }
   7106     if (mode) {
   7107         /* IPV6 entry */
   7108         if (entry_data_upr == NULL) {
   7109             LOG_ERROR(BSL_LS_SOC_LPM,
   7110                       (BSL_META_U(u,
   7111                                   "upper data is NULL for pfx - %d\n"), pfx));
   7112             return;
   7113         }
   7114         if (SOC_MEM_OPT_F32_VALID1_GET(u, mem, entry_data) &&
   7115             SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data) &&
   7116             SOC_MEM_OPT_F32_VALID1_GET(u, mem, entry_data_upr) &&
   7117             SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data_upr)) {
   7118             SOC_FB_LPM128_HASH_ENTRY_IPV6_GET(u, entry_data, entry_data_upr,
   7119                                               key_hash);
   7120             (void) _soc_fb_lpm128_hash_insert(
   7121                         SOC_LPM128_STATE_HASH(u),
   7122                         _soc_fb_lpm128_hash_compare_key,
   7123                         key_hash,
   7124                         pfx,
   7125                         old_index,
   7126                         (tab_index << 1) | FB_LPM_HASH_IPV6_MASK,
   7127                         rvt_index0);
   7128         }
   7129     } else {
   7130         /* IPV4 entry */
   7131         if (SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data)) {
   7132             SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, key_hash);
   7133             (void) _soc_fb_lpm128_hash_insert(SOC_LPM128_STATE_HASH(u),
   7134                                     _soc_fb_lpm128_hash_compare_key,
   7135                                     key_hash,
   7136                                     pfx,
   7137                                     old_index,
   7138                                     (tab_index << 1),
   7139                                     rvt_index0);
   7140         }
   7141         if (SOC_MEM_OPT_F32_VALID1_GET(u, mem, entry_data)) {
   7142             SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, key_hash);
   7143             (void)_soc_fb_lpm128_hash_insert(SOC_LPM128_STATE_HASH(u),
   7144                                     _soc_fb_lpm128_hash_compare_key,
   7145                                     key_hash,
   7146                                     pfx,
   7147                                     old_index,
   7148                                     ((tab_index << 1) + 1),
   7149                                     rvt_index1);
   7150         }
   7151     }
   7152 }
   7153 
   7154 
   7155 
   7156 void soc_fb_lpm128_hash_revert(int u, void *entry_data, void *entry_data_upr,
   7157                                uint32 tab_index, uint32 rvt_index0, uint32 rvt_index1)
   7158 {
   7159     _soc_fb_lpm128_hash_entry_t    key_hash = {0};
   7160     soc_mem_t mem = L3_DEFIPm;
   7161     int mode;
   7162 
   7163 #if defined(BCM_TOMAHAWK3_SUPPORT)
   7164     if (SOC_IS_TOMAHAWK3(u)) {
   7165         uint32 _key_data[2] = {0, 0};
   7166         mem = L3_DEFIP_LEVEL1m;
   7167         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_data, KEY0f, _key_data);
   7168         mode = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf);
   7169     } else
   7170 #endif
   7171     {
   7172         mode = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, defip_mode0_field);
   7173     }
   7174 
   7175     if (mode && mode != 3) {
   7176         LOG_ERROR(BSL_LS_SOC_LPM,
   7177                   (BSL_META_U(u,
   7178                               "Invalid mode while inserting lpm128 hash\n")));
   7179         return;
   7180     }
   7181     if (mode) {
   7182         /* IPV6 entry */
   7183         if (entry_data_upr == NULL) {
   7184             LOG_ERROR(BSL_LS_SOC_LPM,
   7185                       (BSL_META_U(u,
   7186                                   "upper data is NULL\n")));
   7187             return;
   7188         }
   7189         if (SOC_MEM_OPT_F32_VALID1_GET(u, mem, entry_data) &&
   7190             SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data) &&
   7191             SOC_MEM_OPT_F32_VALID1_GET(u, mem, entry_data_upr) &&
   7192             SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data_upr)) {
   7193             SOC_FB_LPM128_HASH_ENTRY_IPV6_GET(u, entry_data, entry_data_upr,
   7194                                               key_hash);
   7195             (void) _soc_fb_lpm128_hash_revert(
   7196                         SOC_LPM128_STATE_HASH(u),
   7197                         _soc_fb_lpm128_hash_compare_key,
   7198                         key_hash,
   7199                         (tab_index << 1) | FB_LPM_HASH_IPV6_MASK,
   7200                         rvt_index0);
   7201         }
   7202     } else {
   7203         /* IPV4 entry */
   7204         if (SOC_MEM_OPT_F32_VALID0_GET(u, mem, entry_data)) {
   7205             SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, key_hash);
   7206             (void) _soc_fb_lpm128_hash_revert(SOC_LPM128_STATE_HASH(u),
   7207                                     _soc_fb_lpm128_hash_compare_key,
   7208                                     key_hash,
   7209                                     (tab_index << 1),
   7210                                     rvt_index0);
   7211         }
   7212         if (SOC_MEM_OPT_F32_VALID1_GET(u, mem, entry_data)) {
   7213             SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, key_hash);
   7214             (void)_soc_fb_lpm128_hash_revert(SOC_LPM128_STATE_HASH(u),
   7215                                     _soc_fb_lpm128_hash_compare_key,
   7216                                     key_hash,
   7217                                     ((tab_index << 1) + 1),
   7218                                     rvt_index1);
   7219         }
   7220     }
   7221 }
   7222 
   7223 
   7224 
   7225 void soc_fb_lpm128_hash_delete(int u, void *key_data, void *key_data_upr, 
   7226                                uint32 tab_index)
   7227 {
   7228     _soc_fb_lpm128_hash_entry_t    key_hash = {0};
   7229     int                         pfx = -1;
   7230     int                         rv;
   7231     uint32                      index;
   7232 #if defined(BCM_TOMAHAWK3_SUPPORT)
   7233     uint32 _key_data[2] = {0, 0};
   7234 #endif
   7235     int is_ipv6 = 0;
   7236 
   7237 #if defined(BCM_TOMAHAWK3_SUPPORT)
   7238     if (SOC_IS_TOMAHAWK3(u)) {
   7239         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, key_data, KEY0f, _key_data);
   7240         is_ipv6 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf);
   7241     } else
   7242 #endif
   7243     {
   7244         is_ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, defip_mode0_field);
   7245     }
   7246 
   7247     if (is_ipv6) {
   7248         SOC_FB_LPM128_HASH_ENTRY_IPV6_GET(u, key_data, key_data_upr, key_hash);
   7249         index = (tab_index << 1) | FB_LPM_HASH_IPV6_MASK;
   7250     } else {
   7251         SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, key_data, key_hash);
   7252         index = tab_index;
   7253     }
   7254 
   7255     rv = _soc_fb_lpm128_hash_delete(SOC_LPM128_STATE_HASH(u),
   7256                                  _soc_fb_lpm128_hash_compare_key,
   7257                                  key_hash, pfx, index);
   7258     if (SOC_FAILURE(rv)) {
   7259         LOG_ERROR(BSL_LS_SOC_LPM,
   7260                   (BSL_META_U(u,
   7261                               "\ndel  index: H %d error %d\n"), index, rv));
   7262     }
   7263 }
   7264 
   7265 int soc_fb_lpm128_hash_lookup(int u, void *key_data, void *key_data_upr, 
   7266                               int pfx, int *key_index)
   7267 {
   7268     _soc_fb_lpm128_hash_entry_t    key_hash = {0};
   7269     int                         is_ipv6;
   7270     int                         rv;
   7271     uint32                      index = FB_LPM_HASH_INDEX_NULL;
   7272 #if defined(BCM_TOMAHAWK3_SUPPORT)
   7273     uint32 _key_data[2] = {0, 0};
   7274 #endif
   7275 
   7276 #if defined(BCM_TOMAHAWK3_SUPPORT)
   7277     if (SOC_IS_TOMAHAWK3(u)) {
   7278         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, key_data, KEY0f, _key_data);
   7279         is_ipv6 = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf);
   7280     } else
   7281 #endif
   7282     {
   7283         is_ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, defip_mode0_field);
   7284     }
   7285     if (is_ipv6 == 3) {
   7286         SOC_FB_LPM128_HASH_ENTRY_IPV6_GET(u, key_data, key_data_upr, key_hash);
   7287     } else if(is_ipv6 == 0) {
   7288         SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, key_data, key_hash);
   7289     } else {
   7290         LOG_ERROR(BSL_LS_SOC_LPM,
   7291                   (BSL_META_U(u,
   7292                               "LPM128 hash lookup for pfx - %d failed\n"), pfx));
   7293         return SOC_E_PARAM;
   7294     }
   7295 
   7296     rv = _soc_fb_lpm128_hash_lookup(SOC_LPM128_STATE_HASH(u),
   7297                                  _soc_fb_lpm128_hash_compare_key,
   7298                                  key_hash, pfx, &index);
   7299     if (SOC_FAILURE(rv)) {
   7300         *key_index = 0xFFFFFFFF;
   7301         return(rv);
   7302     }
   7303 
   7304     *key_index = index;
   7305     return(SOC_E_NONE);
   7306 }
   7307 
   7308 
   7309 /*
   7310  * _soc_fb_lpm_prefix_length_get (Extract vrf weighted  prefix lenght from the 
   7311  * hw entry based on ip, mask & vrf)
   7312  */
   7313 static int
   7314 _soc_fb_lpm128_prefix_length_get(int u, void *entry, void* entry_upr, 
   7315                                  int *pfx_len)
   7316 {
   7317     int         pfx_len1 = 0;
   7318     int         pfx_len2 = 0;
   7319     int         pfx_len3 = 0;
   7320     int         pfx_len4 = 0;
   7321     int         rv;
   7322     int         mode;
   7323     uint32      ipv4a;
   7324     int         vrf_id;
   7325     int pfx;
   7326     int offset = 0;
   7327     int value;
   7328     soc_mem_t mem = L3_DEFIPm;
   7329     int n = 0, p = 3;
   7330     int mc = 0;
   7331 
   7332 #if defined(BCM_TOMAHAWK3_SUPPORT)
   7333     uint32 _key_data[2] = {0, 0};
   7334     if (SOC_IS_TOMAHAWK3(u)) {
   7335         mem = L3_DEFIP_LEVEL1m;
   7336     }
   7337 #endif
   7338 
   7339 #if defined(BCM_TOMAHAWK3_SUPPORT)
   7340     if (SOC_IS_TOMAHAWK3(u)) {
   7341         mem = L3_DEFIP_LEVEL1m;
   7342         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry, KEY0f, _key_data);
   7343         mode = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf);
   7344         SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry, MASK0f, _key_data);
   7345         ipv4a = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);
   7346     } else
   7347 #endif
   7348     {
   7349         mode = SOC_MEM_OPT_F32_GET(u, mem, entry, defip_mode0_field);
   7350         ipv4a = SOC_MEM_OPT_F32_GET(u, mem, entry, IP_ADDR_MASK0f);
   7351     }
   7352 
   7353 #if defined(BCM_TRIDENT3_SUPPORT)
   7354     if (SOC_IS_TRIDENT3X(u)) {
   7355         mc = (SOC_MEM_OPT_F32_GET(u, mem, entry, DATA_TYPE0f) == 2);
   7356     }
   7357 #endif
   7358 
   7359     if (mode && (mode != 3)) {
   7360        return SOC_E_PARAM;
   7361     }
   7362 
   7363     if (ipv4a) {
   7364         if ((rv = _ipmask2pfx(ipv4a, &pfx_len1)) < 0) {
   7365             return(rv);
   7366         }
   7367     }
   7368     if (mode) {
   7369 #if defined(BCM_TOMAHAWK3_SUPPORT)
   7370         if (SOC_IS_TOMAHAWK3(u)) {
   7371             _key_data[0] = _key_data[1] = 0;
   7372             SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry, MASK1f, _key_data);
   7373             ipv4a = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);
   7374         } else
   7375 #endif
   7376         {
   7377             ipv4a = SOC_MEM_OPT_F32_GET(u, mem, entry, IP_ADDR_MASK1f);
   7378         }
   7379         if (ipv4a) {
   7380             if ((rv = _ipmask2pfx(ipv4a, &pfx_len2)) < 0) {
   7381                 return(rv);
   7382             }
   7383         }
   7384 
   7385 #if defined(BCM_TOMAHAWK3_SUPPORT)
   7386         if (SOC_IS_TOMAHAWK3(u)) {
   7387             _key_data[0] = _key_data[1] = 0;
   7388             SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_upr, MASK0f, _key_data);
   7389             ipv4a = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);
   7390         } else
   7391 #endif
   7392         {
   7393             ipv4a = SOC_MEM_OPT_F32_GET(u, mem, entry_upr, IP_ADDR_MASK0f);
   7394         }
   7395         if (ipv4a) {
   7396             if ((rv = _ipmask2pfx(ipv4a, &pfx_len3)) < 0) {
   7397                 return(rv);
   7398             }
   7399         }
   7400 
   7401 #if defined(BCM_TOMAHAWK3_SUPPORT)
   7402         if (SOC_IS_TOMAHAWK3(u)) {
   7403             SOC_TH3_MEM_OPT_F64_GET(u, L3_DEFIP_LEVEL1m, entry_upr, MASK1f, _key_data);
   7404             ipv4a = soc_format_field32_get(u, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf);
   7405         } else
   7406 #endif
   7407         {
   7408             ipv4a = SOC_MEM_OPT_F32_GET(u, mem, entry_upr, IP_ADDR_MASK1f);
   7409         }
   7410         if (ipv4a) {
   7411             if ((rv = _ipmask2pfx(ipv4a, &pfx_len4)) < 0) {
   7412                 return(rv);
   7413             }
   7414         }
   7415     }
   7416 
   7417     pfx = pfx_len1 + pfx_len2 + pfx_len3 + pfx_len4;
   7418 
   7419     if (mode == 0) {
   7420         offset = 0;
   7421     } else {
   7422         offset = (pfx > 64) ? (MAX_PFX_64_OFFSET + MAX_PFX_32_OFFSET) :
   7423                  MAX_PFX_32_OFFSET;
   7424     }
   7425 
   7426     pfx += offset;
   7427 
   7428     SOC_IF_ERROR_RETURN(soc_fb_lpm_vrf_get(u, entry, &vrf_id));
   7429 
   7430     switch(mode) {
   7431         case 0:
   7432             value = MAX_PFX_32_OFFSET;
   7433             break; 
   7434         case 3:
   7435             if (offset > MAX_PFX_32_OFFSET) {
   7436                 value = MAX_PFX_128_OFFSET;
   7437             } else {
   7438                 value = MAX_PFX_64_OFFSET;
   7439             }  
   7440             break;
   7441         /* COVERITY
   7442          * Default switch case
   7443          */
   7444         /* coverity[dead_error_begin] */
   7445         default:
   7446             return SOC_E_INTERNAL;
   7447     }
   7448 
   7449     switch (vrf_id) { 
   7450       case SOC_L3_VRF_GLOBAL:
   7451           n = 0;
   7452           break;
   7453       case SOC_L3_VRF_OVERRIDE:
   7454           n = 2;
   7455           break;
   7456       default:
   7457           n = 1;
   7458           break;
   7459     }
   7460 
   7461     if (soc_feature(u, soc_feature_td3_lpm_ipmc_war) && mc) {
   7462         n += 3;
   7463     }
   7464 
   7465 #if defined(BCM_TRIDENT3_SUPPORT)
   7466     p = 6;
   7467 #endif
   7468 
   7469     *pfx_len = pfx + n * (value / p);
   7470 
   7471     return (SOC_E_NONE);
   7472 }
   7473 /*
   7474  * _soc_fb_lpm_match (Exact match for the key. Will match both IP address
   7475  * and mask)
   7476  */
   7477 
   7478 STATIC int
   7479 _soc_fb_lpm128_match(int u,
   7480                void *key_data,
   7481                void *key_data_upr,
   7482                void *e,         /* return entry data if found */
   7483                void *eupr,         /* return entry data if found */
   7484                int *index_ptr,  /* return key location */
   7485                int *pfx_len,    /* Key prefix length. vrf + 32 + prefix len for IPV6*/
   7486                soc_lpm_entry_type_t *type_out)
   7487 {
   7488     int         rv;
   7489     int         key_index;
   7490     int         pfx = 0;
   7491     int         tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   7492     soc_lpm_entry_type_t type;
   7493 
   7494     /* Calculate vrf weighted prefix lengh. */
   7495     SOC_IF_ERROR_RETURN
   7496     (_soc_fb_lpm128_prefix_length_get(u, key_data, key_data_upr, &pfx));
   7497     *pfx_len = pfx;
   7498 
   7499      if (SOC_LPM128_PFX_IS_V6_128(u, pfx)) {
   7500          type = socLpmEntryType128BV6;
   7501      } else if (SOC_LPM128_PFX_IS_V6_64(u, pfx)) {
   7502          type = socLpmEntryType64BV6;
   7503      } else {
   7504          type = socLpmEntryTypeV4;
   7505      }
   7506 
   7507 #ifdef FB_LPM_HASH_SUPPORT
   7508     rv = LPM128_HASH_LOOKUP(u, key_data, key_data_upr, pfx, &key_index);
   7509     if (rv == SOC_E_NONE) {
   7510         *index_ptr = key_index;
   7511         if (type == socLpmEntryTypeV4) {
   7512             key_index = key_index >> 1; 
   7513         }
   7514 
   7515         if (e != NULL) {
   7516            if ((rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, key_index, e)) < 0) {
   7517               return rv;
   7518            }
   7519         }
   7520         if (eupr != NULL) {
   7521            if (type == socLpmEntryType128BV6) {
   7522               if ((rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, 
   7523                                       (key_index + tcam_depth),
   7524                       eupr)) < 0) {
   7525                  return rv;
   7526               }
   7527            }
   7528        }
   7529 
   7530     }
   7531 #endif /* FB_LPM_HASH_SUPPORT */
   7532     if (type_out != NULL) {
   7533        *type_out = type;
   7534     }
   7535     return rv;
   7536 }
   7537 
   7538 /*
   7539  * Initialize the start/end tracking pointers for each prefix length
   7540  */
   7541 
   7542 int
   7543 soc_fb_lpm128_init(int u)
   7544 {
   7545     int max_pfx_len;
   7546     int defip_table_size = 0;
   7547     int pfx_state_size;
   7548     int i;
   7549     int num_ipv6_128b_entries;
   7550     int tcam_pair_count = 0;
   7551     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   7552     int is_reserved = 0;
   7553     int unreserved_start_offset = 0; 
   7554     soc_lpm128_state_p lpm_state_ptr = NULL;
   7555     int hash_table_size = 0;
   7556     soc_mem_t defip_mem = (SOC_MEM_IS_VALID(u, L3_DEFIP_LEVEL1m) ?
   7557                            L3_DEFIP_LEVEL1m : L3_DEFIPm);
   7558 
   7559     if (!soc_feature(u, soc_feature_lpm_tcam)) {
   7560         return(SOC_E_UNAVAIL);
   7561     }
   7562 
   7563     if (!soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
   7564         return SOC_E_UNAVAIL;
   7565     }
   7566 
   7567     if (soc_feature(u, soc_feature_l3_lpm_128b_entries_reserved)) {
   7568         is_reserved = 1;
   7569     }
   7570 
   7571 
   7572     num_ipv6_128b_entries =  SOC_L3_DEFIP_MAX_128B_ENTRIES(u);
   7573 
   7574     SOC_IF_ERROR_RETURN(soc_fb_lpm_tcam_pair_count_get(u, &tcam_pair_count));
   7575 
   7576     /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
   7577      * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
   7578      * L3_DEFIP table is not divided into 2 to support URPF.
   7579      */
   7580     if (tcam_pair_count && SOC_URPF_STATUS_GET(u) &&
   7581         !soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   7582         switch(tcam_pair_count) {
   7583             case 1:
   7584             case 2:
   7585                 defip_table_size = 2 * tcam_depth;
   7586                 break; 
   7587             case 3:
   7588             case 4:
   7589                 defip_table_size = 4 * tcam_depth;
   7590                 break;
   7591             case 5:
   7592             case 6:
   7593                 defip_table_size = 6 * tcam_depth;
   7594                 break; 
   7595             case 7:
   7596             case 8:
   7597                 defip_table_size = 8 * tcam_depth;
   7598                 break;
   7599 
   7600             default:
   7601                 defip_table_size = 0;
   7602                break;
   7603         }
   7604     } else {
   7605         defip_table_size = (tcam_pair_count * tcam_depth * 2);
   7606     }
   7607 
   7608     /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
   7609      * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
   7610      * L3_DEFIP table is not divided into 2 to support URPF.
   7611      */
   7612     if (SOC_URPF_STATUS_GET(u) &&
   7613         !soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   7614         num_ipv6_128b_entries >>= 1;
   7615     }
   7616 
   7617     if(SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u)) {
   7618         /* defip table size might have changed */
   7619         sal_free(SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u));
   7620         SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u) = NULL;
   7621     }
   7622 
   7623     SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u) =
   7624         sal_alloc(defip_table_size * sizeof(int), 
   7625                   "SOC LPM128 GROUP TO PFX");
   7626     if (NULL == SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u)) {
   7627         return SOC_E_MEMORY;
   7628     }
   7629     
   7630     sal_memset(SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u), -1,
   7631                defip_table_size * sizeof(int));
   7632 
   7633     if (!SOC_LPM128_STATE_TABLE_INIT_CHECK(u)) {
   7634         SOC_LPM128_STATE_TABLE(u) = sal_alloc(sizeof(soc_lpm128_table_t),
   7635                                               "soc LPM STATE table");
   7636         if (NULL == SOC_LPM128_STATE_TABLE(u)) {
   7637             soc_fb_lpm128_deinit(u);
   7638             return SOC_E_MEMORY;
   7639         }
   7640     }
   7641     sal_memset(SOC_LPM128_STATE_TABLE(u), 0x0, sizeof(soc_lpm128_table_t));
   7642 
   7643     max_pfx_len = MAX_PFX128_ENTRIES;
   7644     pfx_state_size = sizeof(soc_lpm128_state_t) * (max_pfx_len);
   7645 
   7646     if (!SOC_LPM128_INIT_CHECK(u)) {
   7647         SOC_LPM128_STATE(u) = sal_alloc(pfx_state_size, "LPM prefix info");
   7648         if (NULL == SOC_LPM128_STATE(u)) {
   7649             soc_fb_lpm128_deinit(u);
   7650             return (SOC_E_MEMORY);
   7651         }
   7652     }
   7653 
   7654     if (!SOC_LPM128_UNRESERVED_INIT_CHECK(u)) {
   7655         if (is_reserved && (num_ipv6_128b_entries % tcam_depth) != 0) {
   7656             SOC_LPM128_UNRESERVED_STATE(u) = sal_alloc(pfx_state_size,
   7657                                                        "LPM prefix info");
   7658             if (NULL == SOC_LPM128_UNRESERVED_STATE(u)) {
   7659                 soc_fb_lpm128_deinit(u);
   7660                 return (SOC_E_MEMORY);
   7661             }
   7662 #ifdef FB_LPM_DEBUG
   7663             DBG_SOC_LPM128_UNRESERVED_STATE(u) = sal_alloc(pfx_state_size,
   7664                                                        "Debug LPM prefix info");
   7665             if (NULL == DBG_SOC_LPM128_UNRESERVED_STATE(u)) {
   7666                 return (SOC_E_MEMORY);
   7667             }
   7668 
   7669             DBG_SOC_LPM128_UNRESERVED_STATE2(u) = sal_alloc(pfx_state_size,
   7670                                                        "Debug LPM prefix info");
   7671             if (NULL == DBG_SOC_LPM128_UNRESERVED_STATE2(u)) {
   7672                 return (SOC_E_MEMORY);
   7673             }            
   7674 #endif
   7675         } else {
   7676             SOC_LPM128_UNRESERVED_STATE(u) = NULL;
   7677 #ifdef FB_LPM_DEBUG
   7678             DBG_SOC_LPM128_UNRESERVED_STATE(u) = NULL;
   7679             DBG_SOC_LPM128_UNRESERVED_STATE2(u) = NULL;
   7680 #endif
   7681         }
   7682     } else {
   7683         if (is_reserved && (num_ipv6_128b_entries % tcam_depth) == 0) {
   7684            sal_free(SOC_LPM128_UNRESERVED_STATE(u));
   7685            SOC_LPM128_UNRESERVED_STATE(u) = NULL;
   7686 #ifdef FB_LPM_DEBUG
   7687            sal_free(DBG_SOC_LPM128_UNRESERVED_STATE(u));
   7688            DBG_SOC_LPM128_UNRESERVED_STATE(u) = NULL;
   7689            sal_free(DBG_SOC_LPM128_UNRESERVED_STATE2(u));
   7690            DBG_SOC_LPM128_UNRESERVED_STATE2(u) = NULL;
   7691 #endif
   7692         }
   7693     }
   7694 #ifdef FB_LPM_DEBUG
   7695 
   7696     DBG_SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u) =
   7697         sal_alloc(defip_table_size * sizeof(int),
   7698                   "Debug SOC LPM128 GROUP TO PFX");
   7699     if (NULL == DBG_SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u)) {
   7700         return SOC_E_MEMORY;
   7701     }
   7702     sal_memset(DBG_SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u), -1,
   7703                defip_table_size * sizeof(int));
   7704 
   7705     DBG_SOC_LPM128_STATE(u) = sal_alloc(pfx_state_size, "Debug LPM prefix info");
   7706     if (NULL == DBG_SOC_LPM128_STATE(u)) {
   7707         return (SOC_E_MEMORY);
   7708     }
   7709 
   7710 
   7711     DBG_SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE2(u) =
   7712         sal_alloc(defip_table_size * sizeof(int),
   7713                   "Debug SOC LPM128 GROUP TO PFX");
   7714     if (NULL == DBG_SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE2(u)) {
   7715         return SOC_E_MEMORY;
   7716     }
   7717     sal_memset(DBG_SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE2(u), -1,
   7718                defip_table_size * sizeof(int));
   7719 
   7720     DBG_SOC_LPM128_STATE2(u) = sal_alloc(pfx_state_size, "Debug LPM prefix info");
   7721     if (NULL == DBG_SOC_LPM128_STATE2(u)) {
   7722         return (SOC_E_MEMORY);
   7723     }
   7724 
   7725 
   7726     DBG_SOC_L3_DEFIP(u) = sal_alloc((sizeof(defip_entry_t) *
   7727                                  soc_mem_index_count(u, defip_mem), "Debug L3_DEFIP");
   7728     if (NULL == DBG_SOC_L3_DEFIP(u)) {
   7729         return (SOC_E_MEMORY);
   7730     }
   7731 
   7732 #endif
   7733 
   7734     SOC_LPM_LOCK(u);
   7735 
   7736     SOC_LPM128_STATE_TABLE_TOTAL_COUNT(u) = defip_table_size;
   7737 
   7738     lpm_state_ptr = SOC_LPM128_STATE(u);
   7739     for(i = 0; i < max_pfx_len; i++) {
   7740         SOC_LPM128_STATE_START1(u, lpm_state_ptr, i) = -1;
   7741         SOC_LPM128_STATE_START2(u, lpm_state_ptr, i) = -1;
   7742         SOC_LPM128_STATE_END1(u, lpm_state_ptr, i) = -1;
   7743         SOC_LPM128_STATE_END2(u, lpm_state_ptr, i) = -1;
   7744         SOC_LPM128_STATE_PREV(u, lpm_state_ptr, i) = -1;
   7745         SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, i) = -1;
   7746         SOC_LPM128_STATE_VENT(u, lpm_state_ptr, i) = 0;
   7747         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, i) = 0;
   7748         SOC_LPM128_STATE_HFENT(u, lpm_state_ptr, i) = 0;
   7749     }
   7750 
   7751     if (is_reserved) {
   7752         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, (MAX_PFX128_INDEX)) =
   7753                               2 * num_ipv6_128b_entries;
   7754     } else {
   7755         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, (MAX_PFX128_INDEX)) =
   7756                               defip_table_size;
   7757     }
   7758 #ifdef FB_LPM_DEBUG
   7759     lpm_state_ptr = DBG_SOC_LPM128_STATE2(u);
   7760     for(i = 0; i < max_pfx_len; i++) {
   7761         SOC_LPM128_STATE_START1(u, lpm_state_ptr, i) = -1;
   7762         SOC_LPM128_STATE_START2(u, lpm_state_ptr, i) = -1;
   7763         SOC_LPM128_STATE_END1(u, lpm_state_ptr, i) = -1;
   7764         SOC_LPM128_STATE_END2(u, lpm_state_ptr, i) = -1;
   7765         SOC_LPM128_STATE_PREV(u, lpm_state_ptr, i) = -1;
   7766         SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, i) = -1;
   7767         SOC_LPM128_STATE_VENT(u, lpm_state_ptr, i) = 0;
   7768         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, i) = 0;
   7769     }
   7770     if (is_reserved) {
   7771         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, (MAX_PFX128_INDEX)) =
   7772                               2 * num_ipv6_128b_entries;
   7773     } else {
   7774         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, (MAX_PFX128_INDEX)) =
   7775                               defip_table_size;
   7776     }
   7777 #endif
   7778     
   7779     unreserved_start_offset = 0;
   7780     if (is_reserved && ((num_ipv6_128b_entries % tcam_depth) != 0)) {
   7781         unreserved_start_offset =
   7782             ((num_ipv6_128b_entries / tcam_depth) * tcam_depth * 2) +
   7783             (num_ipv6_128b_entries % tcam_depth);
   7784     }
   7785 
   7786     if (unreserved_start_offset) {
   7787         lpm_state_ptr = SOC_LPM128_UNRESERVED_STATE(u);
   7788         for(i = 0; i < max_pfx_len; i++) {
   7789             SOC_LPM128_STATE_START1(u, lpm_state_ptr, i) = -1;
   7790             SOC_LPM128_STATE_START2(u, lpm_state_ptr, i) = -1;
   7791             SOC_LPM128_STATE_END1(u, lpm_state_ptr, i) = -1;
   7792             SOC_LPM128_STATE_END2(u, lpm_state_ptr, i) = -1;
   7793             SOC_LPM128_STATE_PREV(u, lpm_state_ptr, i) = -1;
   7794             SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, i) = -1;
   7795             SOC_LPM128_STATE_VENT(u, lpm_state_ptr, i) = 0;
   7796             SOC_LPM128_STATE_FENT(u, lpm_state_ptr, i) = 0;
   7797         }
   7798         /* Assign all fent entries to FENT only */
   7799        SOC_LPM128_STATE_FENT(u, lpm_state_ptr, (MAX_PFX128_INDEX)) =
   7800            defip_table_size - (2 * num_ipv6_128b_entries);
   7801 
   7802        SOC_LPM128_STATE_START1(u, lpm_state_ptr, (MAX_PFX128_INDEX)) =
   7803            unreserved_start_offset;
   7804        SOC_LPM128_STATE_END1(u, lpm_state_ptr, (MAX_PFX128_INDEX)) =
   7805            unreserved_start_offset - 1;       
   7806     }
   7807 #ifdef FB_LPM_DEBUG
   7808     if (unreserved_start_offset) {
   7809         lpm_state_ptr = DBG_SOC_LPM128_UNRESERVED_STATE2(u);
   7810         for(i = 0; i < max_pfx_len; i++) {
   7811             SOC_LPM128_STATE_START1(u, lpm_state_ptr, i) = -1;
   7812             SOC_LPM128_STATE_START2(u, lpm_state_ptr, i) = -1;
   7813             SOC_LPM128_STATE_END1(u, lpm_state_ptr, i) = -1;
   7814             SOC_LPM128_STATE_END2(u, lpm_state_ptr, i) = -1;
   7815             SOC_LPM128_STATE_PREV(u, lpm_state_ptr, i) = -1;
   7816             SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, i) = -1;
   7817             SOC_LPM128_STATE_VENT(u, lpm_state_ptr, i) = 0;
   7818             SOC_LPM128_STATE_FENT(u, lpm_state_ptr, i) = 0;
   7819         }
   7820         /* Assign all fent entries to FENT only */
   7821        SOC_LPM128_STATE_FENT(u, lpm_state_ptr, (MAX_PFX128_INDEX)) =
   7822            defip_table_size - (2 * num_ipv6_128b_entries);
   7823 
   7824        SOC_LPM128_STATE_START1(u, lpm_state_ptr, (MAX_PFX128_INDEX)) =
   7825            unreserved_start_offset;
   7826        SOC_LPM128_STATE_END1(u, lpm_state_ptr, (MAX_PFX128_INDEX)) =
   7827            unreserved_start_offset - 1;       
   7828    }
   7829 #endif
   7830 
   7831 #ifdef FB_LPM_HASH_SUPPORT
   7832     if (SOC_LPM128_STATE_HASH(u) != NULL) {
   7833         if (_soc_fb_lpm_hash_destroy(SOC_LPM128_STATE_HASH(u)) < 0) {
   7834             SOC_LPM_UNLOCK(u);
   7835             soc_fb_lpm128_deinit(u);
   7836             return SOC_E_INTERNAL;
   7837         }
   7838         SOC_LPM128_STATE_HASH(u) = NULL;
   7839     }
   7840 
   7841     hash_table_size = soc_mem_index_count(u, defip_mem);
   7842     if (_soc_fb_lpm_hash_create(u, hash_table_size * 2, hash_table_size,
   7843                                 &SOC_LPM128_STATE_HASH(u)) < 0) {
   7844         soc_fb_lpm128_deinit(u);
   7845         SOC_LPM_UNLOCK(u);
   7846         return SOC_E_MEMORY;
   7847     }
   7848 #ifdef FB_LPM_DEBUG
   7849     if (_soc_fb_lpm_hash_create(u, hash_table_size * 2, hash_table_size,
   7850                                 &DBG_SOC_LPM128_STATE_HASH(u)) < 0) {
   7851         soc_fb_lpm128_deinit(u);
   7852         SOC_LPM_UNLOCK(u);
   7853         return SOC_E_MEMORY;
   7854     }
   7855 
   7856     if (_soc_fb_lpm_hash_create(u, hash_table_size * 2, hash_table_size,
   7857                                 &DBG_SOC_LPM128_STATE_HASH2(u)) < 0) {
   7858         soc_fb_lpm128_deinit(u);
   7859         SOC_LPM_UNLOCK(u);
   7860         return SOC_E_MEMORY;
   7861     }
   7862 #endif
   7863 
   7864 #endif
   7865     if (soc_fb_lpm128_stat_init(u) < 0) {
   7866         soc_fb_lpm128_deinit(u);
   7867         SOC_LPM_UNLOCK(u);
   7868         return SOC_E_INTERNAL;
   7869     }
   7870     SOC_LPM_UNLOCK(u);
   7871 
   7872     return(SOC_E_NONE);
   7873 }
   7874 
   7875 /*
   7876  * De-initialize the start/end tracking pointers for each prefix length
   7877  */
   7878 int
   7879 soc_fb_lpm128_deinit(int u)
   7880 {
   7881     if (!soc_feature(u, soc_feature_lpm_tcam)) {
   7882         return(SOC_E_UNAVAIL);
   7883     }
   7884 
   7885     if (!soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
   7886         return SOC_E_UNAVAIL;
   7887     }
   7888 
   7889     SOC_LPM_LOCK(u);
   7890     if (SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u) != NULL) {
   7891         sal_free(SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u));
   7892         SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u) = NULL;
   7893     }
   7894 
   7895     if (SOC_LPM128_STATE_TABLE_INIT_CHECK(u) && SOC_LPM128_INIT_CHECK(u)) {
   7896         sal_free(SOC_LPM128_STATE(u));
   7897         SOC_LPM128_STATE(u) = NULL;
   7898     }
   7899 
   7900     if (soc_feature(u, soc_feature_l3_lpm_128b_entries_reserved) &&
   7901         SOC_LPM128_STATE_TABLE_INIT_CHECK(u) &&
   7902         SOC_LPM128_UNRESERVED_INIT_CHECK(u)) {
   7903         sal_free(SOC_LPM128_UNRESERVED_STATE(u));
   7904         SOC_LPM128_UNRESERVED_STATE(u) = NULL;
   7905     }
   7906 
   7907     if (SOC_LPM128_STATE_TABLE_INIT_CHECK(u)) {
   7908         sal_free(SOC_LPM128_STATE_TABLE(u));
   7909         SOC_LPM128_STATE_TABLE(u) = NULL;
   7910     }
   7911 #ifdef FB_LPM_HASH_SUPPORT
   7912     if (SOC_LPM128_STATE_HASH(u) != NULL) {
   7913         _soc_fb_lpm_hash_destroy(SOC_LPM128_STATE_HASH(u));
   7914         SOC_LPM128_STATE_HASH(u) = NULL;
   7915     }
   7916 #endif
   7917 
   7918 #ifdef FB_LPM_DEBUG
   7919     if (DBG_SOC_LPM128_STATE_HASH(u)) {
   7920         _soc_fb_lpm_hash_destroy(DBG_SOC_LPM128_STATE_HASH(u));
   7921         DBG_SOC_LPM128_STATE_HASH(u) = NULL;
   7922     }
   7923 
   7924     if (DBG_SOC_LPM128_STATE_HASH2(u)) {
   7925         _soc_fb_lpm_hash_destroy(DBG_SOC_LPM128_STATE_HASH2(u));
   7926         DBG_SOC_LPM128_STATE_HASH2(u) = NULL;
   7927     }
   7928 
   7929     if (DBG_SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u) != NULL) {
   7930         sal_free(DBG_SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u));
   7931         DBG_SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u) = NULL;
   7932     }
   7933     if (DBG_SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE2(u) != NULL) {
   7934         sal_free(DBG_SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE2(u));
   7935         DBG_SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE2(u) = NULL;
   7936     }
   7937         
   7938     if (DBG_SOC_LPM128_STATE(u)) {
   7939         sal_free(DBG_SOC_LPM128_STATE(u));
   7940         DBG_SOC_LPM128_STATE(u) = NULL;
   7941     }
   7942 
   7943     if (DBG_SOC_LPM128_STATE2(u)) {
   7944         sal_free(DBG_SOC_LPM128_STATE2(u));
   7945         DBG_SOC_LPM128_STATE2(u) = NULL;
   7946     }
   7947 
   7948     if (DBG_SOC_LPM128_UNRESERVED_STATE(u)) {
   7949         sal_free(DBG_SOC_LPM128_UNRESERVED_STATE(u));
   7950         DBG_SOC_LPM128_UNRESERVED_STATE(u) = NULL;
   7951     }
   7952 
   7953     if (DBG_SOC_LPM128_UNRESERVED_STATE2(u)) {
   7954         sal_free(DBG_SOC_LPM128_UNRESERVED_STATE2(u));
   7955         DBG_SOC_LPM128_UNRESERVED_STATE2(u) = NULL;
   7956     }
   7957 
   7958     if (DBG_SOC_L3_DEFIP(u)) {
   7959         sal_free(DBG_SOC_L3_DEFIP(u));
   7960         DBG_SOC_L3_DEFIP(u) = NULL;
   7961     }
   7962 #endif
   7963 
   7964     SOC_LPM_UNLOCK(u);
   7965 
   7966     return(SOC_E_NONE);
   7967 }
   7968 
   7969 
   7970 /*
   7971  * Expect pfx1 < pfx2,
   7972  */
   7973 STATIC INLINE int
   7974 _lpm128_pfx_conflicting(int pfx1, int pfx2)
   7975 {
   7976     return  (SOC_LPM128_PFX_IS_V4(u, pfx1) && SOC_LPM128_PFX_IS_V6(u, pfx2));
   7977 }
   7978 
   7979 STATIC int
   7980 _lpm128_fb_urpf_entry_replicate(int u, int index, int temp_index, uint32 *e, uint32 *eupr)
   7981 {
   7982     int src_tcam_offset;  /* Defip memory size/2 urpf source lookup offset */
   7983     int new_index = 0;
   7984     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   7985     int max_tcams = SOC_L3_DEFIP_MAX_TCAMS_GET(u);
   7986     int ipv6;             /* IPv6 entry.                                   */
   7987     uint32 mask0;         /* Mask 0 field value.                           */
   7988     uint32 mask1;         /* Mask 1 field value.                           */
   7989     int def_gw_flag;      /* Entry is default gateway.                     */
   7990     uint32 defip_temp_e[SOC_MAX_MEM_WORDS]; /* Temporary lpm entry. */
   7991     int rv = SOC_E_NONE;
   7992 
   7993     if(!SOC_URPF_STATUS_GET(u)) {
   7994         return (SOC_E_NONE);
   7995     }
   7996 
   7997     ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, defip_mode0_field);
   7998 
   7999     /* Set/Reset default gateway flag based on ip mask value. */
   8000     mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, IP_ADDR_MASK0f);
   8001     mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, IP_ADDR_MASK1f);
   8002 
   8003     if (!ipv6) {
   8004         if (SOC_MEM_OPT_F32_VALID0_GET(u, L3_DEFIPm, e)) {
   8005             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e,
   8006             DEFAULTROUTE0f, (!mask0) ? 1 : 0);
   8007         }
   8008         if (SOC_MEM_OPT_F32_VALID1_GET(u, L3_DEFIPm, e)) {
   8009             SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e,
   8010                  DEFAULTROUTE1f, (!mask1) ? 1 : 0);
   8011         }
   8012     } else {
   8013         def_gw_flag = ((!mask0) &&  (!mask1)) ? 1 : 0;
   8014         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DEFAULTROUTE0f, def_gw_flag);
   8015         SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DEFAULTROUTE1f, def_gw_flag);
   8016     }
   8017 
   8018     /* If soc_feature_l3_defip_advanced_lookup is TRUE then
   8019      * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
   8020      * L3_DEFIP table is not divided into 2 to support URPF.
   8021      */
   8022     if (soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   8023         return WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, index, e);
   8024     }
   8025     if (soc_feature(u, soc_feature_defip_2_tcams_with_separate_rpf)) {
   8026         src_tcam_offset = SOC_DEFIP_HOLE_RPF_OFFSET;
   8027     } else {
   8028         src_tcam_offset = (max_tcams * tcam_depth) / 2;
   8029     }
   8030 
   8031     new_index = index + src_tcam_offset;
   8032     
   8033     /*
   8034      * In order to avoid atomicity issue, write the tcam entry to temp_index
   8035      * before writing into the actual index.
   8036      * "temp_index" is VALID only if 'lpm_atomic_write' feature is enabled.
   8037      */  
   8038     if (temp_index != -1) {
   8039        temp_index += src_tcam_offset;
   8040        rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY,
   8041                                           new_index, &defip_temp_e);
   8042        SOC_IF_ERROR_RETURN(rv);
   8043        rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY,
   8044                                           temp_index, &defip_temp_e);
   8045        SOC_IF_ERROR_RETURN(rv);
   8046     }
   8047 
   8048     /* Write entry to the second half of the tcam. */
   8049     if (SOC_IS_TRIDENT3X(u)) {
   8050         soc_mem_t   mem = L3_DEFIPm;
   8051         soc_mem_field32_set(u, mem, e, FLEX_CTR_BASE_COUNTER_IDX0f, 0);
   8052         soc_mem_field32_set(u, mem, e, FLEX_CTR_BASE_COUNTER_IDX1f, 0);
   8053         if (eupr) {
   8054             soc_mem_field32_set(u, mem, eupr, FLEX_CTR_BASE_COUNTER_IDX0f, 0);
   8055             soc_mem_field32_set(u, mem, eupr, FLEX_CTR_BASE_COUNTER_IDX1f, 0);
   8056         }
   8057     } 
   8058 
   8059     SOC_IF_ERROR_RETURN(WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, new_index, e));
   8060     if (eupr) {
   8061         SOC_IF_ERROR_RETURN(WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY,
   8062                                             new_index + tcam_depth, eupr));
   8063     }
   8064 
   8065     if (temp_index != -1) {
   8066        sal_memset(&defip_temp_e, 0x0, sizeof(defip_temp_e));
   8067        SOC_IF_ERROR_RETURN(WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY,
   8068                                           temp_index, &defip_temp_e));
   8069     }
   8070     return SOC_E_NONE;
   8071 }
   8072 
   8073 #ifdef FB_LPM_DEBUG
   8074 #define DBG_LPM128_HASH_INSERT(u, entry_data, entry_data_upr, tab_index, rvt_index0, rvt_index1)  \
   8075     dbg_soc_fb_lpm128_hash_insert(u, entry_data, entry_data_upr, tab_index, LPM_NO_MATCH_INDEX, 0,\
   8076                               rvt_index0, rvt_index1)
   8077 
   8078 void dbg_soc_fb_lpm128_hash_insert(int u, void *entry_data, void *entry_data_upr,
   8079                                uint32 tab_index, uint32 old_index, int pfx,
   8080                                uint32 *rvt_index0, uint32 *rvt_index1)
   8081 {
   8082     _soc_fb_lpm128_hash_entry_t    key_hash = {0};
   8083     int mode = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, defip_mode0_field);
   8084 
   8085     if (mode && mode != 3) {
   8086         LOG_ERROR(BSL_LS_SOC_LPM,
   8087                   (BSL_META_U(u,
   8088                               "Invalid mode while inserting lpm128 hash for pfx - %d\n"), pfx));
   8089         return;
   8090     }
   8091     if (mode) {
   8092         /* IPV6 entry */
   8093         if (SOC_MEM_OPT_F32_VALID1_GET(u, L3_DEFIPm, entry_data) &&
   8094             SOC_MEM_OPT_F32_VALID0_GET(u, L3_DEFIPm, entry_data) &&
   8095             SOC_MEM_OPT_F32_VALID1_GET(u, L3_DEFIPm, entry_data_upr) &&
   8096             SOC_MEM_OPT_F32_VALID0_GET(u, L3_DEFIPm, entry_data_upr)) {
   8097             SOC_FB_LPM128_HASH_ENTRY_IPV6_GET(u, entry_data, entry_data_upr,
   8098                                               key_hash);
   8099             (void) _soc_fb_lpm128_hash_insert(
   8100                         DBG_SOC_LPM128_STATE_HASH2(u),
   8101                         _soc_fb_lpm128_hash_compare_key,
   8102                         key_hash,
   8103                         pfx,
   8104                         old_index,
   8105                         (tab_index << 1) | FB_LPM_HASH_IPV6_MASK,
   8106                         rvt_index0);
   8107         }
   8108     } else {
   8109         /* IPV4 entry */
   8110         if (SOC_MEM_OPT_F32_VALID0_GET(u, L3_DEFIPm, entry_data)) {
   8111             SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, key_hash);
   8112             (void) _soc_fb_lpm128_hash_insert(DBG_SOC_LPM128_STATE_HASH2(u),
   8113                                     _soc_fb_lpm128_hash_compare_key,
   8114                                     key_hash,
   8115                                     pfx,
   8116                                     old_index,
   8117                                     (tab_index << 1),
   8118                                     rvt_index0);
   8119         }
   8120         if (SOC_MEM_OPT_F32_VALID1_GET(u, L3_DEFIPm, entry_data)) {
   8121             SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, key_hash);
   8122             (void)_soc_fb_lpm128_hash_insert(DBG_SOC_LPM128_STATE_HASH2(u),
   8123                                     _soc_fb_lpm128_hash_compare_key,
   8124                                     key_hash,
   8125                                     pfx,
   8126                                     old_index,
   8127                                     ((tab_index << 1) + 1),
   8128                                     rvt_index1);
   8129         }
   8130     }
   8131 }
   8132 
   8133 void
   8134 lpm128_idx_to_pfx_dump(int u, int before)
   8135 {
   8136     int i = 0;
   8137     int defip_table_size;
   8138     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   8139     int pfx1, pfx2;
   8140     int prev_pfx1 = -2;
   8141     int prev_pfx2 = -2;
   8142     int repeat_cnt = 0;
   8143 
   8144     if (soc_fb_lpm_table_sizes_get(u, &defip_table_size, NULL) < 0 ) {
   8145         return ;
   8146     }
   8147 
   8148     LOG_CLI((BSL_META_U(u,
   8149                         "|===============||===============|\n")));
   8150     for (i = 0; i < defip_table_size; i++) {
   8151         if (LPM128_IN_ODD_TCAM(u, i)) {
   8152             i += tcam_depth - 1;
   8153             continue;
   8154         }
   8155         if (before == 2) {
   8156             pfx1 = DBG_SOC_LPM128_INDEX_TO_PFX_GROUP2(u, i);
   8157             pfx2 = DBG_SOC_LPM128_INDEX_TO_PFX_GROUP2(u, i + tcam_depth);
   8158         } else if (before == 1) {
   8159             pfx1 = DBG_SOC_LPM128_INDEX_TO_PFX_GROUP(u, i);
   8160             pfx2 = DBG_SOC_LPM128_INDEX_TO_PFX_GROUP(u, i + tcam_depth);
   8161         } else {
   8162             pfx1 = SOC_LPM128_INDEX_TO_PFX_GROUP(u, i);
   8163             pfx2 = SOC_LPM128_INDEX_TO_PFX_GROUP(u, i + tcam_depth);
   8164         }
   8165 
   8166         if (pfx1 == prev_pfx1 && pfx2 == prev_pfx2) {
   8167             repeat_cnt++;
   8168             continue;
   8169         }
   8170 
   8171         if (repeat_cnt) {
   8172             repeat_cnt++;
   8173             LOG_CLI((BSL_META_U(u,
   8174                             "| repeats %5d || repeats %5d |\n"),
   8175                             repeat_cnt, repeat_cnt));
   8176         }
   8177 
   8178         repeat_cnt = 0;
   8179         LOG_CLI((BSL_META_U(u,
   8180                             "| %5d [%5d] || %5d [%5d] |\n"),
   8181                             pfx1, i, pfx2, i + tcam_depth));
   8182         prev_pfx1 = pfx1;
   8183         prev_pfx2 = pfx2;
   8184     }
   8185     if (repeat_cnt) {
   8186         repeat_cnt++;
   8187         LOG_CLI((BSL_META_U(u,
   8188                         "| repeats %5d || repeats %5d |\n"),
   8189                         repeat_cnt, repeat_cnt));
   8190     }
   8191     LOG_CLI((BSL_META_U(u,
   8192                         "|===============||===============|\n")));
   8193     return ;
   8194 }
   8195 
   8196 void
   8197 lpm_hash_dump(int u, int before, int step, uint32 usec)
   8198 {
   8199     int i, j;
   8200     _soc_fb_lpm_hash_t * hash = before == 2 ? DBG_SOC_LPM_STATE_HASH2(u) :
   8201                                 before == 1 ? DBG_SOC_LPM_STATE_HASH(u) :
   8202                                               SOC_LPM_STATE_HASH(u);
   8203 
   8204     if (step < 5) {
   8205         step = 5;
   8206     }
   8207                                               
   8208     LOG_CLI((" Lpm table\n"));
   8209     for (i = 0, j = 0; i < hash->index_count; i++) {
   8210         if (hash->table[i] != FB_LPM_HASH_INDEX_NULL) {
   8211             LOG_CLI((" t[%d] %d\n", i, hash->table[i]));
   8212             if ((j % step) == 0) {
   8213                 sal_usleep (usec);
   8214             }
   8215             j++;
   8216         }
   8217     }
   8218 
   8219     LOG_CLI((" Lpm link_table \n"));
   8220     for (i = 0, j = 0; i < hash->entry_count; i++) {
   8221         if (hash->link_table[i] != FB_LPM_HASH_INDEX_NULL) {
   8222             LOG_CLI((" l[%d] %d\n", i, hash->link_table[i]));
   8223             if ((j % step) == 0) {
   8224                 sal_usleep(usec);
   8225             }
   8226             j++;
   8227         }
   8228     }
   8229 
   8230     return ;
   8231 }
   8232 
   8233 
   8234 void
   8235 lpm_count_dump(int u, int before)
   8236 {
   8237     if (before == 2) {
   8238         LOG_CLI(("Lpm128 %d %d %d %d Lpm %d %d %d. before=%d\n",
   8239         SOC_LPM128_STAT_128BV6_COUNT2(u),
   8240         SOC_LPM128_STAT_V4_COUNT2(u),
   8241         SOC_LPM128_STAT_64BV6_COUNT2(u),
   8242         SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT2(u),
   8243         SOC_LPM_V4_COUNT2(u),
   8244         SOC_LPM_64BV6_COUNT2(u),
   8245         SOC_LPM_V4_HALF_ENTRY_COUNT2(u),
   8246         before));
   8247     } else if (before == 1) {
   8248         LOG_CLI(("Lpm128 %d %d %d %d Lpm %d %d %d. before=%d\n",
   8249         SOC_LPM128_STAT_128BV6_COUNT1(u),
   8250         SOC_LPM128_STAT_V4_COUNT1(u),
   8251         SOC_LPM128_STAT_64BV6_COUNT1(u),
   8252         SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT1(u),
   8253         SOC_LPM_V4_COUNT1(u),
   8254         SOC_LPM_64BV6_COUNT1(u),
   8255         SOC_LPM_V4_HALF_ENTRY_COUNT1(u),
   8256         before));
   8257     } else {
   8258         LOG_CLI(("Lpm128 %d %d %d %d Lpm %d %d %d. before=%d\n",
   8259         SOC_LPM128_STAT_128BV6_COUNT(u),
   8260         SOC_LPM128_STAT_V4_COUNT(u),
   8261         SOC_LPM128_STAT_64BV6_COUNT(u),
   8262         SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u),
   8263         SOC_LPM_V4_COUNT(u),
   8264         SOC_LPM_64BV6_COUNT(u),
   8265         SOC_LPM_V4_HALF_ENTRY_COUNT(u),
   8266         before));
   8267     }
   8268 }
   8269 
   8270 void
   8271 lpm128_hash_dump(int u, int before, int step, uint32 usec)
   8272 {
   8273     int i, j;
   8274     _soc_fb_lpm_hash_t * hash = before == 2 ? DBG_SOC_LPM128_STATE_HASH2(u) :
   8275                                 before == 1 ? DBG_SOC_LPM128_STATE_HASH(u) :
   8276                                               SOC_LPM128_STATE_HASH(u);
   8277     if (step < 5) {
   8278         step = 5;
   8279     }
   8280                                               
   8281     LOG_CLI((" Lpm 128 table\n"));
   8282     for (i = 0, j = 0; i < hash->index_count; i++) {
   8283         if (hash->table[i] != FB_LPM_HASH_INDEX_NULL) {
   8284             LOG_CLI((" t8[%d] %d\n", i, hash->table[i]));
   8285             if ((j % step) == 0) {
   8286                 sal_usleep (usec);
   8287             }
   8288             j++;
   8289         }
   8290     }
   8291 
   8292     LOG_CLI((" Lpm 128 link_table \n"));
   8293     for (i = 0, j = 0; i < hash->entry_count; i++) {
   8294         if (hash->link_table[i] != FB_LPM_HASH_INDEX_NULL) {
   8295             LOG_CLI((" l8[%d] %d\n", i, hash->link_table[i]));
   8296             if ((j % step) == 0) {
   8297                 sal_usleep(usec);
   8298             }
   8299             j++;
   8300         }
   8301     }
   8302 
   8303     return ;
   8304 }
   8305 
   8306 
   8307 void
   8308 lpm128_state_dump(int u, int before)
   8309 {
   8310     soc_lpm128_state_p lpm_state_ptr;
   8311     int start1;
   8312     int start2;
   8313     int end1;
   8314     int end2;
   8315     int vent;
   8316     int fent;
   8317     int prev;
   8318     int next;
   8319     int total_prefixes = 0;
   8320     int curr_pfx = MAX_PFX128_INDEX;
   8321 
   8322     LOG_CLI((BSL_META_U(u, "before = %d:\n"), before));
   8323 
   8324     if (SOC_LPM128_UNRESERVED_STATE(u)) {
   8325         LOG_CLI((BSL_META_U(u,
   8326                             "Reserved prefixes=====================\n")));
   8327     } else {
   8328         LOG_CLI((BSL_META_U(u,
   8329                             "Prefixes=====================\n")));
   8330     }
   8331 
   8332     lpm_state_ptr = before == 2 ? DBG_SOC_LPM128_STATE2(u) :
   8333                     before == 1 ? DBG_SOC_LPM128_STATE(u) :
   8334                                   SOC_LPM128_STATE(u);
   8335     while (lpm_state_ptr && curr_pfx > 0) {
   8336         start1 = SOC_LPM128_STATE_START1(u, lpm_state_ptr, curr_pfx);
   8337         start2 = SOC_LPM128_STATE_START2(u, lpm_state_ptr, curr_pfx);
   8338         end1   = SOC_LPM128_STATE_END1(u, lpm_state_ptr, curr_pfx);
   8339         end2   = SOC_LPM128_STATE_END2(u, lpm_state_ptr, curr_pfx);
   8340         vent   = SOC_LPM128_STATE_VENT(u, lpm_state_ptr, curr_pfx);
   8341         fent   = SOC_LPM128_STATE_FENT(u, lpm_state_ptr, curr_pfx);
   8342         prev   = SOC_LPM128_STATE_PREV(u, lpm_state_ptr, curr_pfx);
   8343         next   = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, curr_pfx);
   8344         LOG_CLI((BSL_META_U(u,
   8345                             "PFX:%3d S1:%4d E1:%4d S2:%4d E2:%4d "\
   8346                             "V:%4d F:%4d P:%3d N:%3d \n"),
   8347                  curr_pfx, start1, end1, start2, end2,
   8348                  vent, fent, prev, next ));
   8349         curr_pfx = next;
   8350         total_prefixes += vent;
   8351     }
   8352 
   8353     lpm_state_ptr = before == 2 ? DBG_SOC_LPM128_UNRESERVED_STATE2(u) :
   8354                     before == 1 ? DBG_SOC_LPM128_UNRESERVED_STATE(u) :
   8355                                   SOC_LPM128_UNRESERVED_STATE(u);
   8356     curr_pfx = MAX_PFX128_INDEX;
   8357     if (lpm_state_ptr) {
   8358         LOG_CLI((BSL_META_U(u,
   8359                             "Total number of reserved prefixes - %d\n"), total_prefixes));
   8360         total_prefixes = 0;
   8361 
   8362         LOG_CLI((BSL_META_U(u,
   8363                             "Unreserved prefixes=====================\n")));
   8364     }
   8365     while (lpm_state_ptr && curr_pfx > 0) {
   8366         start1 = SOC_LPM128_STATE_START1(u, lpm_state_ptr, curr_pfx);
   8367         start2 = SOC_LPM128_STATE_START2(u, lpm_state_ptr, curr_pfx);
   8368         end1   = SOC_LPM128_STATE_END1(u, lpm_state_ptr, curr_pfx);
   8369         end2   = SOC_LPM128_STATE_END2(u, lpm_state_ptr, curr_pfx);
   8370         vent   = SOC_LPM128_STATE_VENT(u, lpm_state_ptr, curr_pfx);
   8371         fent   = SOC_LPM128_STATE_FENT(u, lpm_state_ptr, curr_pfx);
   8372         prev   = SOC_LPM128_STATE_PREV(u, lpm_state_ptr, curr_pfx);
   8373         next   = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, curr_pfx);
   8374         LOG_CLI((BSL_META_U(u,
   8375                             "PFX:%3d S1:%4d E1:%4d S2:%4d E2:%4d "\
   8376                             "V:%4d F:%4d P:%3d N:%3d \n"),
   8377                  curr_pfx, start1, end1, start2, end2,
   8378                  vent, fent, prev, next ));
   8379         curr_pfx = next;
   8380         total_prefixes += vent;
   8381     }
   8382 
   8383     if (lpm_state_ptr) {
   8384         LOG_CLI((BSL_META_U(u,
   8385                             "Total number of unreserved prefixes - %d\n"), total_prefixes));
   8386     } else {
   8387         LOG_CLI((BSL_META_U(u,
   8388                             "Total number of prefixes - %d\n"), total_prefixes));
   8389     }
   8390     return;
   8391 }
   8392 int
   8393 dbg_soc_fb_lpm_reinit_done(int unit, int ipv6)
   8394 {
   8395     int idx;
   8396     int prev_idx = MAX_PFX_INDEX(unit);
   8397     uint32      v0 = 0, v1 = 0;
   8398     int from_ent = -1;
   8399     soc_lpm_state_p state2 = DBG_SOC_LPM_STATE2(unit);
   8400     int defip_table_size = soc_mem_index_count(unit, L3_DEFIPm);
   8401 
   8402     if (SOC_URPF_STATUS_GET(unit)) {
   8403         if (soc_feature(unit, soc_feature_l3_defip_hole)) {
   8404               defip_table_size = SOC_APOLLO_B0_L3_DEFIP_URPF_SIZE;
   8405         } else if (SOC_IS_APOLLO(unit)) {
   8406             defip_table_size = SOC_APOLLO_L3_DEFIP_URPF_SIZE;
   8407         } else {
   8408             /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
   8409              * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
   8410              * L3_DEFIP table is not divided into 2 to support URPF.
   8411              */
   8412             if (!soc_feature(unit, soc_feature_l3_defip_advanced_lookup)) {
   8413                 defip_table_size >>= 1;
   8414             }
   8415         }
   8416     } 
   8417 
   8418     SOC_LPM_STATE_P(state2, MAX_PFX_INDEX(unit)) = -1;
   8419 
   8420     for (idx = MAX_PFX_INDEX(unit); idx >= 0; idx--) {
   8421         if ((idx == MAX_PFX_INDEX(unit)) && (SOC_LPM_STATE_S(state2, idx) <= 0)) {
   8422             continue;
   8423         }
   8424             
   8425         if (-1 == SOC_LPM_STATE_S(state2, idx)) {
   8426             continue;
   8427         }
   8428 
   8429         if (prev_idx != idx) {
   8430             SOC_LPM_STATE_P(state2, idx) = prev_idx;
   8431             SOC_LPM_STATE_N(state2, prev_idx) = idx;
   8432         }
   8433         SOC_LPM_STATE_F(state2, prev_idx) =                    \
   8434                           SOC_LPM_STATE_S(state2, idx) -      \
   8435                           SOC_LPM_STATE_E(state2, prev_idx) - 1;
   8436         prev_idx = idx;
   8437         
   8438         if (idx == MAX_PFX_INDEX(unit) || (ipv6 && SOC_LPM_PFX_IS_V4(unit, idx)) ||
   8439            (!ipv6 && SOC_LPM_PFX_IS_V6_64(unit, idx))) {
   8440             continue;
   8441         }
   8442 
   8443         if (!(soc_feature(unit, soc_feature_l3_shared_defip_table) ||
   8444             (soc_feature(unit, soc_feature_l3_kt2_shared_defip_table)))) {
   8445             continue;
   8446         }
   8447 
   8448         if (SOC_LPM_PFX_IS_V4(unit, idx)) {
   8449             from_ent = SOC_LPM_STATE_E(state2, idx);
   8450             if (!soc_feature(unit, soc_feature_half_of_l3_defip_ipv4_capacity)) {
   8451                 v0 = SOC_MEM_OPT_F32_VALID0_GET(unit, L3_DEFIPm, &(DBG_SOC_L3_DEFIP(unit)[from_ent]));
   8452                 v1 = SOC_MEM_OPT_F32_VALID1_GET(unit, L3_DEFIPm, &(DBG_SOC_L3_DEFIP(unit)[from_ent]));
   8453                 SOC_LPM_V4_COUNT2(unit) += (SOC_LPM_STATE_V(state2, idx) << 1);
   8454                 if ((v0 == 0) || (v1 == 0)) {
   8455                     SOC_LPM_V4_COUNT2(unit) -= 1;
   8456                 }
   8457                 if ((v0 && (!(v1))) || (!(v0) && v1)) {
   8458                     SOC_LPM_COUNT_INC(SOC_LPM_V4_HALF_ENTRY_COUNT2(unit));
   8459                 } 
   8460             } else {
   8461                 SOC_LPM_V4_COUNT2(unit) += SOC_LPM_STATE_V(state2, idx);
   8462             }
   8463         } else {
   8464             SOC_LPM_64BV6_COUNT2(unit) += SOC_LPM_STATE_V(state2, idx);
   8465         }
   8466     }
   8467 
   8468     SOC_LPM_STATE_N(state2, prev_idx) = -1;
   8469     SOC_LPM_STATE_F(state2, prev_idx) =                       \
   8470                           defip_table_size -                   \
   8471                           SOC_LPM_STATE_E(state2, prev_idx) - 1;
   8472 
   8473     return (SOC_E_NONE);
   8474 }
   8475 
   8476 
   8477 
   8478 int
   8479 dbg_soc_fb_lpm_reinit(int unit, int idx, uint32 *lpm_entry)
   8480 {
   8481     int pfx_len;
   8482 
   8483     if (SOC_IS_HAWKEYE(unit)) {
   8484         return SOC_E_NONE;
   8485     }
   8486 
   8487     SOC_IF_ERROR_RETURN
   8488         (_soc_fb_lpm_prefix_length_get(unit, lpm_entry, &pfx_len));
   8489 
   8490     if (DBG_SOC_LPM_STATE2(unit)[pfx_len].vent == 0) {
   8491         DBG_SOC_LPM_STATE2(unit)[pfx_len].start = idx;
   8492         DBG_SOC_LPM_STATE2(unit)[pfx_len].end = idx;
   8493     } else {
   8494         DBG_SOC_LPM_STATE2(unit)[pfx_len].end = idx;
   8495     }
   8496 
   8497     DBG_SOC_LPM_STATE2(unit)[pfx_len].vent++;
   8498     LPM_HASH_INSERT2(unit, lpm_entry, idx, NULL, NULL);
   8499     LPM_AVL_INSERT(unit, lpm_entry, idx);
   8500 
   8501     return (SOC_E_NONE);
   8502 }
   8503 
   8504 
   8505 STATIC int
   8506 dbg_soc_fb_lpm128_setup_pfx_state(int u, soc_lpm128_state_p lpm_state_ptr)
   8507 {
   8508     int prev_idx = MAX_PFX128_INDEX;
   8509     int idx = 0;
   8510     int from_ent = -1;
   8511     int v0 = 0, v1 = 0;
   8512 
   8513     if (NULL == lpm_state_ptr) {
   8514        return SOC_E_INTERNAL;
   8515     }
   8516 
   8517     SOC_LPM128_STATE_PREV(u, lpm_state_ptr, MAX_PFX128_INDEX) = -1;
   8518 
   8519     for (idx = MAX_PFX128_INDEX; idx > 0; idx--) {
   8520         if (SOC_LPM128_STATE_START1(u, lpm_state_ptr, idx) == -1) {
   8521            continue;
   8522         }
   8523 
   8524         SOC_LPM128_STATE_PREV(u, lpm_state_ptr, idx) = prev_idx;
   8525         SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, prev_idx) = idx;
   8526 
   8527         prev_idx = idx;
   8528         if (SOC_LPM128_PFX_IS_V6_64(u, idx)) {
   8529            SOC_LPM128_STAT_64BV6_COUNT2(u) += SOC_LPM128_STATE_VENT(u,
   8530                                                            lpm_state_ptr, idx);
   8531         }
   8532 
   8533         if (SOC_LPM128_PFX_IS_V6_128(u, idx)) {
   8534            SOC_LPM128_STAT_128BV6_COUNT2(u) += SOC_LPM128_STATE_VENT(u,
   8535                                                             lpm_state_ptr, idx);
   8536         }
   8537 
   8538         if (SOC_LPM128_PFX_IS_V4(u, idx)) {
   8539             if (SOC_LPM128_STATE_START2(u, lpm_state_ptr, idx) != -1) {
   8540                from_ent = SOC_LPM128_STATE_END2(u, lpm_state_ptr, idx);
   8541             } else {
   8542                from_ent = SOC_LPM128_STATE_END1(u, lpm_state_ptr, idx);
   8543             }
   8544             if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
   8545                 v0 = SOC_MEM_OPT_F32_VALID0_GET(u, L3_DEFIPm, &(DBG_SOC_L3_DEFIP(u)[from_ent]));
   8546                 v1 = SOC_MEM_OPT_F32_VALID1_GET(u, L3_DEFIPm, &(DBG_SOC_L3_DEFIP(u)[from_ent]));
   8547                 SOC_LPM128_STAT_V4_COUNT2(u) += (SOC_LPM128_STATE_VENT(u,
   8548                                                           lpm_state_ptr, idx)) << 1;
   8549                 if ((v0 == 0) || (v1 == 0)) {
   8550                     SOC_LPM128_STAT_V4_COUNT2(u) -= 1;
   8551                 }
   8552                 if ((v0 && (!(v1))) || ((!(v0) && v1))) {
   8553                     SOC_LPM_COUNT_INC(SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT2(u));
   8554                 }
   8555             } else {
   8556                 SOC_LPM128_STAT_V4_COUNT2(u) += SOC_LPM128_STATE_VENT(u,
   8557                                                           lpm_state_ptr, idx);
   8558             }
   8559         }
   8560     }
   8561 
   8562     SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, prev_idx) = -1;
   8563 
   8564     return SOC_E_NONE;
   8565 }
   8566 
   8567 
   8568 int
   8569 dbg_soc_fb_lpm128_reinit_done(int unit, int ipv6)
   8570 {
   8571     int paired_table_size = 0;
   8572     int defip_table_size = 0;
   8573     int i = 0;
   8574     int pfx;
   8575     int is_reserved = 0;
   8576     int start_idx = -1;
   8577     int end_idx = -1;
   8578     int fent_incr = 0;
   8579     int found = 0;
   8580     int first_v4_index = -1;
   8581     int split_done = 0;
   8582     int next_pfx = -1;
   8583     soc_lpm128_state_p lpm_state_ptr = DBG_SOC_LPM128_STATE2(unit);
   8584     int max_v6_entries = SOC_L3_DEFIP_MAX_128B_ENTRIES(unit);
   8585     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
   8586 
   8587     if (!soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) {
   8588         return SOC_E_NONE;
   8589     }
   8590 
   8591     if (!ipv6) {
   8592         return SOC_E_NONE;
   8593     }
   8594 
   8595     if (max_v6_entries == 0) {
   8596         return SOC_E_NONE;
   8597     }
   8598 
   8599     if (soc_feature(unit, soc_feature_l3_lpm_128b_entries_reserved)) {
   8600         is_reserved = 1;
   8601     }
   8602 
   8603     SOC_IF_ERROR_RETURN(soc_fb_lpm_table_sizes_get(unit, &paired_table_size,
   8604                                                    &defip_table_size));
   8605     /* If soc_feature_l3_defip_advanced_lookup is TRUE then
   8606      * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
   8607      * L3_DEFIP table is not divided into 2 to support URPF.
   8608      */
   8609     if (SOC_URPF_STATUS_GET(unit) &&
   8610         !soc_feature(unit, soc_feature_l3_defip_advanced_lookup)) {
   8611         max_v6_entries >>= 1;
   8612     }
   8613 
   8614     lpm_state_ptr = DBG_SOC_LPM128_STATE2(unit);
   8615     if (lpm_state_ptr == NULL) {
   8616         return SOC_E_NONE;
   8617     }
   8618     SOC_IF_ERROR_RETURN
   8619         (dbg_soc_fb_lpm128_setup_pfx_state(unit, lpm_state_ptr));
   8620 
   8621     pfx = MAX_PFX128_INDEX;
   8622     next_pfx = SOC_LPM128_STATE_NEXT(unit, lpm_state_ptr, pfx);
   8623     start_idx = 0;
   8624     if (!is_reserved) {
   8625         end_idx = paired_table_size;
   8626         if (next_pfx == -1) {
   8627             SOC_LPM128_STATE_FENT(unit, lpm_state_ptr, pfx) = end_idx;
   8628         }
   8629     } else {
   8630         end_idx = max_v6_entries;
   8631         if (next_pfx == -1) {
   8632             SOC_LPM128_STATE_FENT(unit, lpm_state_ptr, pfx) = end_idx << 1;
   8633         }
   8634     }
   8635 
   8636     for (i = start_idx; (next_pfx != -1) && i < end_idx; i++) {
   8637         if (((i / tcam_depth) & 1) && (i % tcam_depth == 0)) {
   8638             if (is_reserved) {
   8639                 i += max_v6_entries;
   8640             }
   8641             if (first_v4_index != -1 && !split_done) {
   8642                 i = first_v4_index + tcam_depth;
   8643                 split_done = 1;
   8644             }
   8645         }
   8646         if (DBG_SOC_LPM128_INDEX_TO_PFX_GROUP2(unit, i) != -1) {
   8647             pfx = DBG_SOC_LPM128_INDEX_TO_PFX_GROUP2(unit, i);
   8648             if (SOC_LPM128_PFX_IS_V4(u, pfx)) {
   8649                 if (first_v4_index == -1) {
   8650                    first_v4_index = SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx);
   8651                 }
   8652                 fent_incr = 1;
   8653             } else {
   8654                 fent_incr = 2;
   8655             }
   8656             if (pfx != MAX_PFX128_INDEX) {
   8657                 found = 1;
   8658             }
   8659         } else {
   8660             if ((SOC_LPM128_PFX_IS_V6(u, pfx)) && ((i / tcam_depth) & 1)) {
   8661                 continue;
   8662             }
   8663             SOC_LPM128_STATE_FENT(unit, lpm_state_ptr, pfx) += fent_incr;
   8664         }
   8665     }
   8666 
   8667     if (found) {
   8668         SOC_LPM128_STATE_FENT(unit, lpm_state_ptr, MAX_PFX128_INDEX) = 0;
   8669     }
   8670     lpm_state_ptr = DBG_SOC_LPM128_UNRESERVED_STATE2(unit);
   8671     if (lpm_state_ptr == NULL) {
   8672        return SOC_E_NONE;
   8673     }
   8674     SOC_IF_ERROR_RETURN
   8675         (dbg_soc_fb_lpm128_setup_pfx_state(unit, lpm_state_ptr));
   8676     pfx = MAX_PFX128_INDEX;
   8677     found = 0;
   8678     start_idx = ((max_v6_entries / tcam_depth) * tcam_depth * 2) +
   8679                 max_v6_entries % tcam_depth;
   8680     next_pfx = SOC_LPM128_STATE_NEXT(unit, lpm_state_ptr, pfx);
   8681     if (next_pfx == -1) {
   8682         SOC_LPM128_STATE_FENT(unit, lpm_state_ptr, pfx) = (paired_table_size -
   8683                                                          (max_v6_entries << 1));
   8684     }
   8685     for (i = start_idx; (next_pfx != -1) && i < paired_table_size; i++) {
   8686         if (((i / tcam_depth) & 1) && (i % tcam_depth == 0)) {
   8687             i += (max_v6_entries % tcam_depth);
   8688         }
   8689         if (DBG_SOC_LPM128_INDEX_TO_PFX_GROUP2(unit, i) != -1) {
   8690             pfx = DBG_SOC_LPM128_INDEX_TO_PFX_GROUP2(unit, i);
   8691             if (SOC_LPM128_PFX_IS_V4(u, pfx)) {
   8692                 fent_incr = 1;
   8693             } else {
   8694                 fent_incr = 2;
   8695             }
   8696             if (pfx != MAX_PFX128_INDEX) {
   8697                 found = 1;
   8698             }
   8699         } else {
   8700             SOC_LPM128_STATE_FENT(unit, lpm_state_ptr, pfx) += fent_incr;
   8701         }
   8702     }
   8703 
   8704     if (found) {
   8705         SOC_LPM128_STATE_FENT(unit, lpm_state_ptr, MAX_PFX128_INDEX) = 0;
   8706     }
   8707 
   8708     return SOC_E_NONE;
   8709 }
   8710 
   8711 int
   8712 dbg_soc_fb_lpm128_reinit(int u, int idx, uint32 *lpm_entry,
   8713                      uint32 *lpm_entry_upr)
   8714 {
   8715     int pfx = 0;
   8716     int is_reserved = 0;
   8717     soc_lpm128_state_p lpm_state_ptr = DBG_SOC_LPM128_STATE2(u);
   8718     int max_v6_entries = SOC_L3_DEFIP_MAX_128B_ENTRIES(u);
   8719     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   8720 
   8721     if (!soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
   8722         return SOC_E_NONE;
   8723     }
   8724 
   8725     if (max_v6_entries == 0) {
   8726         return SOC_E_NONE;
   8727     }
   8728 
   8729     if (soc_feature(u, soc_feature_l3_lpm_128b_entries_reserved)) {
   8730         is_reserved = 1;
   8731     }
   8732 
   8733     SOC_IF_ERROR_RETURN
   8734         (_soc_fb_lpm128_prefix_length_get(u, lpm_entry, lpm_entry_upr,
   8735                                           &pfx));
   8736 
   8737     if (!is_reserved || (SOC_LPM128_PFX_IS_V6_128(u, pfx))) {
   8738         lpm_state_ptr = DBG_SOC_LPM128_STATE2(u);
   8739     } else {
   8740         lpm_state_ptr = DBG_SOC_LPM128_UNRESERVED_STATE2(u);
   8741     }
   8742 
   8743     if (SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) == 0) {
   8744         SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx) = idx;
   8745         SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) = idx;
   8746     } else {
   8747         if (SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) != -1) {
   8748             SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) = idx;
   8749         } else {
   8750             if (((SOC_LPM128_PFX_IS_V6(u, pfx))) && ((idx / tcam_depth) & 1)) {
   8751                 return SOC_E_NONE;
   8752             }
   8753             if ((SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) + 1) != idx &&
   8754                 (SOC_LPM128_PFX_IS_V4(u, pfx))) {
   8755                 SOC_LPM128_STATE_START2(u, lpm_state_ptr, pfx) = idx;
   8756                 SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) = idx;
   8757             } else {
   8758                 SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) = idx;
   8759             }
   8760         }
   8761     }
   8762 
   8763     SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) += 1;
   8764     DBG_LPM128_HASH_INSERT(u, lpm_entry, lpm_entry_upr, idx, NULL, NULL);
   8765     DBG_SOC_LPM128_INDEX_TO_PFX_GROUP2(u, idx) = pfx;
   8766     if (SOC_LPM128_PFX_IS_V6(u, pfx)) {
   8767         DBG_SOC_LPM128_INDEX_TO_PFX_GROUP2(u, idx + tcam_depth) = pfx;
   8768     }
   8769 
   8770     return (SOC_E_NONE);
   8771 }
   8772 
   8773 
   8774 int lpm_state_verify(int u, int *err)
   8775 {
   8776     int i = 0, idx = 0;
   8777     int paired_size = 0, defip_size = 0;
   8778     int free_count = 0;
   8779     soc_lpm_state_p lpm_state_ptr = SOC_LPM_STATE(u);
   8780     int32 curr_pfx = MAX_PFX_INDEX(unit);
   8781     int32 *pfxmap = NULL;
   8782     int32 *pfxmap2 = NULL;
   8783     int start;
   8784     int end;
   8785     int vent = 0;
   8786     int vent_count = 0;
   8787     int next_pfx = -1;
   8788     int fent = 0;
   8789     int error_count = 0;
   8790 
   8791     SOC_IF_ERROR_RETURN(soc_fb_lpm_table_sizes_get(u, &paired_size, &defip_size));
   8792 
   8793     if (lpm_state_ptr == NULL) {
   8794         LOG_ERROR(BSL_LS_SOC_LPM,
   8795                   (BSL_META_U(u,
   8796                               "lpm state ptr is NULL, just return\n")));
   8797         return SOC_E_MEMORY;
   8798     }
   8799 
   8800     pfxmap = sal_alloc(defip_size * sizeof(int), "debug pfxmap");
   8801     if (pfxmap == NULL) {
   8802         return SOC_E_MEMORY;
   8803     }
   8804 
   8805     sal_memset(pfxmap, -1, sizeof(int) * defip_size);
   8806 
   8807     pfxmap2 = sal_alloc(defip_size * sizeof(int), "debug pfxmap2");
   8808     if (pfxmap2 == NULL) {
   8809         return SOC_E_MEMORY;
   8810     }
   8811     sal_memset(pfxmap2, -1, sizeof(int) * defip_size);
   8812 
   8813     free_count = SOC_LPM_STATE_F(lpm_state_ptr, MAX_PFX_INDEX(unit));
   8814 
   8815     while (curr_pfx != -1) {
   8816         next_pfx = SOC_LPM_STATE_N(lpm_state_ptr, curr_pfx);
   8817         if (curr_pfx == MAX_PFX_INDEX(unit)) {
   8818             if (next_pfx == -1) {
   8819                 goto done;
   8820             }
   8821             curr_pfx = next_pfx;
   8822             continue;
   8823         }
   8824 
   8825         if (next_pfx != -1) {
   8826             if (SOC_LPM_STATE_P(lpm_state_ptr, next_pfx) != curr_pfx ||
   8827                 curr_pfx <= next_pfx) {
   8828                 LOG_ERROR(BSL_LS_SOC_LPM,
   8829                           (BSL_META_U(u,
   8830                                       "Corrupted list0 pfx:%d != next's prev:%d,"\
   8831                                       " next_pfx:%d \n"), curr_pfx,
   8832                                       SOC_LPM_STATE_P(lpm_state_ptr, next_pfx),
   8833                                       next_pfx));
   8834                 error_count++;
   8835             }
   8836         }
   8837 
   8838         start = SOC_LPM_STATE_S(lpm_state_ptr, curr_pfx);
   8839         end   = SOC_LPM_STATE_E(lpm_state_ptr, curr_pfx);
   8840         fent  = SOC_LPM_STATE_F(lpm_state_ptr, curr_pfx);
   8841         vent  = SOC_LPM_STATE_V(lpm_state_ptr, curr_pfx);
   8842         if (start <= -1 || end <= -1 || fent <= -1 || (vent <= 0 && fent <= 0)) {
   8843             LOG_ERROR(BSL_LS_SOC_LPM,
   8844                       (BSL_META_U(u,
   8845                                   "pfx: %d Negative values detected\n"), curr_pfx));
   8846             error_count++;
   8847         }
   8848 
   8849         if (vent != end + 1 - start) {
   8850             LOG_ERROR(BSL_LS_SOC_LPM,
   8851                       (BSL_META_U(u,
   8852                                   "pfx: %d Vent wrong\n"), curr_pfx));
   8853         }
   8854 
   8855         for (i = start; i <= end + fent; i++) {
   8856             if (pfxmap[i-paired_size] != -1) {
   8857                 /* There is a overwrite */
   8858                 LOG_ERROR(BSL_LS_SOC_LPM,
   8859                           (BSL_META_U(u,
   8860                                       "Conflict0 for pfx: %d with pfx: %d\n"),
   8861                                       curr_pfx, pfxmap[i-paired_size]));
   8862                 error_count++;
   8863             } else {
   8864                 pfxmap[i-paired_size] = curr_pfx;
   8865                 if (i <= end) {
   8866                     pfxmap2[i-paired_size] = curr_pfx;
   8867                 }
   8868             }
   8869         }
   8870 
   8871         vent_count += vent;
   8872         free_count += fent;
   8873         curr_pfx = next_pfx;
   8874     }
   8875 
   8876     if ((free_count + vent_count) != defip_size) {
   8877         LOG_ERROR(BSL_LS_SOC_LPM,
   8878                   (BSL_META_U(u,
   8879                               "Count mismatch! free: %d vent: %d defipsize: %d\n"),
   8880                    free_count, vent_count, defip_size));
   8881         error_count++;
   8882     }
   8883 
   8884     for (i = 0; i < defip_size; i++) {
   8885 
   8886         idx = i + paired_size;
   8887         /* The following does sanity check on lpm hash table, with the 
   8888          * help from lpm state (say it's trustable) and a little help
   8889          * from cached l3_defip 
   8890          */
   8891         if (pfxmap2[i] != -1 && SOC_LPM_PFX_IS_V6_64(u, pfxmap2[i])) {
   8892             /* left must exist in hash table, right must not exist. */
   8893             if (SOC_LPM_STATE_HASH(u)->check_table[(idx << 1)] == 0 ||
   8894                 SOC_LPM_STATE_HASH(u)->check_table[(idx << 1) + 1]) {
   8895                 error_count++;
   8896                 LOG_ERROR(BSL_LS_SOC_LPM,
   8897                           (BSL_META_U(u,
   8898                                       "Check table error0: %d "
   8899                                       "  pfx %d, check_table %d %d \n"),
   8900                                       i, pfxmap2[i],
   8901                                       SOC_LPM_STATE_HASH(u)->check_table[(idx << 1)],
   8902                                       SOC_LPM_STATE_HASH(u)->check_table[(idx << 1) + 1]));
   8903             }
   8904         } else if (pfxmap2[i] != -1 && SOC_LPM_PFX_IS_V4(u, pfxmap2[i])) {
   8905             /* Valid v4 */
   8906             /* left half must exist in hash table */
   8907             if (SOC_LPM_STATE_HASH(u)->check_table[(idx << 1)] == 0) {
   8908                 error_count++;
   8909                 LOG_ERROR(BSL_LS_SOC_LPM,
   8910                           (BSL_META_U(u,
   8911                                       "Check table error2: %d "
   8912                                       "  pfx %d, check_table %d \n"),
   8913                                       i, pfxmap2[i],
   8914                                       SOC_LPM_STATE_HASH(u)->check_table[(idx << 1)]));
   8915             }
   8916 
   8917             /* right half must exist in hash table when VALID1 is 1 */
   8918             if (SOC_LPM_STATE_HASH(u)->check_table[(idx << 1) + 1] == 0) {
   8919                 /* further check if it's half entry, report error if not half entry */
   8920                 if (soc_L3_DEFIPm_field32_get(u, &(DBG_SOC_L3_DEFIP(u)[idx]), VALID1f)) {
   8921                     error_count++;
   8922                     LOG_ERROR(BSL_LS_SOC_LPM,
   8923                               (BSL_META_U(u,
   8924                                           "Check table error3: %d "
   8925                                           "  pfx %d, check_table %d \n"),
   8926                                           i, pfxmap2[i],
   8927                                           SOC_LPM_STATE_HASH(u)->check_table[(idx << 1) + 1]));
   8928                 }
   8929             }
   8930         } else {
   8931             /* Not valid entry, must not exist in hash table */
   8932             if (SOC_LPM_STATE_HASH(u)->check_table[(idx << 1)] ||
   8933                 SOC_LPM_STATE_HASH(u)->check_table[(idx << 1) + 1]) {
   8934                 error_count++;
   8935                 LOG_ERROR(BSL_LS_SOC_LPM,
   8936                           (BSL_META_U(u,
   8937                                       "Check table error4: %d "
   8938                                       "  pfx %d, check_table %d %d \n"),
   8939                                       i, pfxmap2[i],
   8940                                       SOC_LPM_STATE_HASH(u)->check_table[(idx << 1)],
   8941                                       SOC_LPM_STATE_HASH(u)->check_table[(idx << 1) + 1]));
   8942             }
   8943         }
   8944 
   8945     }
   8946 
   8947 
   8948 done:
   8949     sal_free(pfxmap);
   8950     sal_free(pfxmap2);
   8951     if (err) {
   8952         *err = (*err) + error_count;
   8953     }
   8954 
   8955     return SOC_E_NONE;
   8956 }
   8957 
   8958 
   8959 int lpm128_state_verify(int u)
   8960 {
   8961     int i = 0;
   8962     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   8963     int paired_size = 0, defip_size = 0;
   8964     int free_count = 0;
   8965     soc_lpm128_state_p lpm_state_ptr = SOC_LPM128_STATE(u);
   8966     int32 curr_pfx = MAX_PFX128_INDEX;
   8967     int32 *pfxmap = NULL;
   8968     int32 *pfxmap2 = NULL;
   8969     int start1, start2;
   8970     int end1, end2;
   8971     int vent = 0;
   8972     int vent_count = 0;
   8973     int split_count = 0;
   8974     int max_v6_entries = SOC_L3_DEFIP_MAX_128B_ENTRIES(u);
   8975     int is_reserved = 0;
   8976     int next_pfx = -1;
   8977     int prev_split_pfx = -1;
   8978     int max_entries = 0;
   8979     int end_idx = 0;
   8980     int fent = 0;
   8981     int first_v4_start = -1;
   8982     int error_count = 0;
   8983     int pfx_state_size = sizeof(soc_lpm128_state_t) * (MAX_PFX128_ENTRIES);
   8984     int pfx_state_size2 = sizeof(soc_lpm_state_t) * (MAX_PFX_ENTRIES(u));
   8985 
   8986     SOC_IF_ERROR_RETURN(soc_fb_lpm_table_sizes_get(u, &paired_size, &defip_size));
   8987 
   8988     /* If soc_feature_l3_defip_advanced_lookup is TRUE then
   8989      * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
   8990      * L3_DEFIP table is not divided into 2 to support URPF.
   8991      */
   8992     if (SOC_URPF_STATUS_GET(u) &&
   8993         !soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   8994         max_v6_entries >>= 1;
   8995     }
   8996 
   8997     if (soc_feature(u, soc_feature_l3_lpm_128b_entries_reserved)) {
   8998         is_reserved = 1;
   8999     }
   9000 
   9001     if (is_reserved) {
   9002         lpm_state_ptr = SOC_LPM128_UNRESERVED_STATE(u);
   9003         if (NULL == lpm_state_ptr) {
   9004             if (max_v6_entries % tcam_depth == 0) {
   9005                 return SOC_E_NONE;
   9006             }
   9007             LOG_ERROR(BSL_LS_SOC_LPM,
   9008                       (BSL_META_U(u,
   9009                                   "reserved and unreserved state ptr is NULL\n")));
   9010             return SOC_E_MEMORY;
   9011         }
   9012     }
   9013 
   9014     if (lpm_state_ptr == NULL) {
   9015         LOG_ERROR(BSL_LS_SOC_LPM,
   9016                   (BSL_META_U(u,
   9017                               "lpm128 state ptr is NULL, just return\n")));
   9018         return SOC_E_MEMORY;
   9019     }
   9020 
   9021     pfxmap = sal_alloc(paired_size * sizeof(int), "debug pfxmap");
   9022     if (pfxmap == NULL) {
   9023         return SOC_E_MEMORY;
   9024     }
   9025     pfxmap2 = sal_alloc(paired_size * sizeof(int), "debug pfxmap2");
   9026     if (pfxmap2 == NULL) {
   9027         return SOC_E_MEMORY;
   9028     }
   9029 
   9030     sal_memset(pfxmap, -1, sizeof(int) * paired_size);
   9031     sal_memset(pfxmap2, -1, sizeof(int) * paired_size);
   9032 
   9033     free_count = SOC_LPM128_STATE_FENT(u, lpm_state_ptr, MAX_PFX128_INDEX);
   9034 
   9035     while (curr_pfx != -1) {
   9036         next_pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, curr_pfx);
   9037         if (curr_pfx == MAX_PFX128_INDEX) {
   9038             if (next_pfx == -1) {
   9039                 goto done;
   9040             }
   9041             curr_pfx = next_pfx;
   9042             continue;
   9043         }
   9044 
   9045         if (next_pfx != -1) {
   9046             if (SOC_LPM128_STATE_PREV(u, lpm_state_ptr, next_pfx) != curr_pfx ||
   9047                 curr_pfx <= next_pfx) {
   9048                 LOG_ERROR(BSL_LS_SOC_LPM,
   9049                           (BSL_META_U(u,
   9050                                       "Corrupted list pfx:%d != next's prev:%d,"\
   9051                                       " next_pfx:%d \n"), curr_pfx,
   9052                                       SOC_LPM128_STATE_PREV(u, lpm_state_ptr, next_pfx),
   9053                                       next_pfx));
   9054                 error_count++;
   9055             }
   9056         }
   9057 
   9058         start1 = SOC_LPM128_STATE_START1(u, lpm_state_ptr, curr_pfx);
   9059         end1 = SOC_LPM128_STATE_END1(u, lpm_state_ptr, curr_pfx);
   9060         fent = SOC_LPM128_STATE_FENT(u, lpm_state_ptr, curr_pfx);
   9061         vent = SOC_LPM128_STATE_VENT(u, lpm_state_ptr, curr_pfx);
   9062         if (start1 <= -1 || end1 <= -1 || fent <= -1 || vent <= 0) {
   9063             LOG_ERROR(BSL_LS_SOC_LPM,
   9064                       (BSL_META_U(u,
   9065                                   "pfx: %d Negative values detected\n"), curr_pfx));
   9066             error_count++;
   9067         }
   9068 
   9069         start2 = SOC_LPM128_STATE_START2(u, lpm_state_ptr, curr_pfx);
   9070         end2 = SOC_LPM128_STATE_END2(u, lpm_state_ptr, curr_pfx);
   9071 
   9072         if (SOC_LPM128_PFX_IS_V6(u, curr_pfx)) {
   9073             if (fent & 1) {
   9074                 LOG_ERROR(BSL_LS_SOC_LPM,
   9075                           (BSL_META_U(u,
   9076                                       "V6 pfx: %d fent odd number \n"), curr_pfx));
   9077                 error_count++;
   9078             }
   9079             end_idx  = end1;
   9080         } else {
   9081             if (start2 != -1) {
   9082                 end_idx  = end2;
   9083             } else {
   9084                 end_idx = end1;
   9085             }
   9086         }
   9087 
   9088         if (start2 != -1) {
   9089             if (split_count > 1) {
   9090                  LOG_ERROR(BSL_LS_SOC_LPM,
   9091                            (BSL_META_U(u,
   9092                                        "More than one split. pfx: %d prev split pfx: %d\n"),
   9093                             curr_pfx, prev_split_pfx));
   9094                 error_count++;
   9095             } else {
   9096                 split_count++;
   9097                 prev_split_pfx = curr_pfx;
   9098             }
   9099             if (end2 == -1) {
   9100                 LOG_ERROR(BSL_LS_SOC_LPM,
   9101                           (BSL_META_U(u,
   9102                                       "pfx: %d end2 is -1\n"), curr_pfx));
   9103                 error_count++;
   9104             }
   9105 
   9106             for (i = start2; i <= end_idx + fent; i++) {
   9107                 if (pfxmap[i] != -1) {
   9108                     /* There is a overwrite */
   9109                     LOG_ERROR(BSL_LS_SOC_LPM,
   9110                               (BSL_META_U(u,
   9111                                           "S2 Conflict for pfx: %d with pfx: %d\n"),
   9112                                           curr_pfx, pfxmap[i]));
   9113                     error_count++;
   9114                 } else {
   9115                     pfxmap[i] = curr_pfx;
   9116                     if (i <= end_idx) {
   9117                         pfxmap2[i] = curr_pfx;
   9118                     }
   9119                 }
   9120             }
   9121         }
   9122 
   9123         if (SOC_LPM128_PFX_IS_V4(u, curr_pfx)) {
   9124             if (first_v4_start == -1){
   9125                 first_v4_start = start1;
   9126             }
   9127         }
   9128 
   9129         if (start2 != -1) {
   9130             end_idx = end1;
   9131         } else {
   9132             if (SOC_LPM128_PFX_IS_V4(u, curr_pfx)) {
   9133 
   9134                 int v6_count_in_last_tcam = first_v4_start % tcam_depth;
   9135 
   9136                 /* even if there's no range2 for valid entries, there still could be
   9137                  * a range2 for free entries, in which case both start1 and end1 should
   9138                  * be in same tcam number as the first v4.
   9139                  * Condition: end1 + fent is in a larger tcam_number than end1,
   9140                  *            both start1 and end1 in same tcam number as first_v4_start
   9141                  *            and there left v6 entries (valid or free).
   9142                  */
   9143                 end_idx = end1 + fent;
   9144                 if (end_idx / tcam_depth > end1 / tcam_depth  &&
   9145                     start1 / tcam_depth == first_v4_start / tcam_depth &&
   9146                     end1 / tcam_depth == first_v4_start / tcam_depth)  {
   9147                     end_idx += v6_count_in_last_tcam;
   9148                 }
   9149 
   9150             } else {
   9151                 /* For ipv6, get the last entry (free or valid) index */
   9152                 int k;
   9153                 if (next_pfx != -1) {
   9154                     int start1_next_pfx;
   9155                     int end_idx_comp;
   9156 
   9157                     start1_next_pfx = SOC_LPM128_STATE_START1(u, lpm_state_ptr, next_pfx);
   9158                     if (end1 / tcam_depth == (start1_next_pfx - 1) / tcam_depth) {
   9159                         end_idx = end1 + (fent / 2);
   9160                     } else {
   9161                         k = ((start1_next_pfx - 1) / tcam_depth - end1 / tcam_depth);
   9162                         end_idx = end1 + (fent / 2) + (k / 2 * tcam_depth);
   9163                     }
   9164 
   9165                     if(((start1_next_pfx - 1) / tcam_depth ) & 1) {
   9166                         end_idx_comp = (start1_next_pfx - 1) - tcam_depth;
   9167                     } else {
   9168                         end_idx_comp = (start1_next_pfx - 1);
   9169                     }
   9170                     if (end_idx != end_idx_comp) {
   9171                         LOG_ERROR(BSL_LS_SOC_LPM,
   9172                                   (BSL_META_U(u,
   9173                                   "End_idx compare wrong: end_idx %d ,"\
   9174                                   "end_idx_comp %d\n"), end_idx,
   9175                                   end_idx_comp
   9176                                   ));
   9177                         error_count++;
   9178                     }
   9179 
   9180                 } else {
   9181                     k = (end1 + fent / 2) / tcam_depth - end1 / tcam_depth;
   9182                     end_idx = end1 + fent / 2 + k * tcam_depth;
   9183 
   9184                     if (end_idx != (paired_size - tcam_depth - 1)) {
   9185                         LOG_ERROR(BSL_LS_SOC_LPM,
   9186                                   (BSL_META_U(u,
   9187                                   "End_idx caculation wrong: end_idx %d ,"\
   9188                                   "should be %d\n"), end_idx,
   9189                                   (paired_size - tcam_depth - 1)
   9190                                   ));
   9191                         error_count++;
   9192                     }
   9193                 }
   9194             }
   9195         }
   9196 
   9197 
   9198         for (i = start1; i <= end_idx; i++) {
   9199             if (SOC_LPM128_PFX_IS_V4(u, curr_pfx) &&
   9200                 ((i / tcam_depth) & 1) && ((i % tcam_depth) == 0) &&
   9201                 ((i / tcam_depth) - 1 == first_v4_start / tcam_depth)) {
   9202 
   9203                 i += first_v4_start % tcam_depth;
   9204             } else if (SOC_LPM128_PFX_IS_V6(u, curr_pfx) &&
   9205                        ((i / tcam_depth) & 1) && ((i % tcam_depth) == 0)) {
   9206 
   9207                 i += tcam_depth;
   9208             }
   9209 
   9210             if (pfxmap[i] != -1) {
   9211                 /* There is a overwrite */
   9212                 LOG_ERROR(BSL_LS_SOC_LPM,
   9213                           (BSL_META_U(u,
   9214                                       "Conflict for pfx: %d with pfx: %d\n"),
   9215                                       curr_pfx, pfxmap[i]));
   9216                 error_count++;
   9217             } else {
   9218                 pfxmap[i] = curr_pfx;
   9219                 if (SOC_LPM128_PFX_IS_V6(u, curr_pfx)) {
   9220                     pfxmap[i + tcam_depth] = curr_pfx;
   9221                 }
   9222 
   9223                 if (i <= end1) {
   9224                     pfxmap2[i] = curr_pfx;
   9225                     if (SOC_LPM128_PFX_IS_V6(u, curr_pfx)) {
   9226                         pfxmap2[i + tcam_depth] = curr_pfx;
   9227                     }
   9228                 }
   9229             }
   9230         }
   9231 
   9232         if (SOC_LPM128_PFX_IS_V4(u, curr_pfx)) {
   9233             vent_count += vent;
   9234         } else {
   9235             vent_count += (vent * 2);
   9236         }
   9237         free_count += SOC_LPM128_STATE_FENT(u, lpm_state_ptr, curr_pfx);
   9238         curr_pfx = next_pfx;
   9239     }
   9240 
   9241     if (is_reserved) {
   9242         max_entries = paired_size - (2 * max_v6_entries);
   9243     } else {
   9244         max_entries = paired_size;
   9245     }
   9246     if ((free_count + vent_count) != max_entries) {
   9247         LOG_ERROR(BSL_LS_SOC_LPM,
   9248                   (BSL_META_U(u,
   9249                               "count mismatch!!! free: %d vent: %d tablesize: %d\n"),
   9250                    free_count, vent_count, paired_size));
   9251         error_count++;
   9252     }
   9253 
   9254     if (is_reserved) {
   9255         int reserved_v6_last;
   9256         if (max_v6_entries == 0) {
   9257             reserved_v6_last = -1;
   9258         }else {
   9259             reserved_v6_last = ((max_v6_entries - 1) / tcam_depth) * tcam_depth * 2 +
   9260                      ((max_v6_entries - 1) % tcam_depth);
   9261         }
   9262         for (i = 0; i < (reserved_v6_last + 1); i++) {
   9263             if (((i / tcam_depth) & 1) && ((i % tcam_depth) == 0)) {
   9264                 i += tcam_depth;
   9265             }
   9266             if (pfxmap[i] != -1 ||
   9267                 pfxmap[i + tcam_depth] != -1) {
   9268                 LOG_ERROR(BSL_LS_SOC_LPM,
   9269                           (BSL_META_U(u,
   9270                                       "overflow into reserved space pfx: %d\n"),
   9271                                       pfxmap[i]));
   9272                 error_count++;
   9273             }
   9274         }
   9275 
   9276         for (; i < paired_size; i++) {
   9277             if (((i / tcam_depth) & 1) && ((i % tcam_depth) == 0) &&
   9278                 (reserved_v6_last != -1) &&
   9279                 ((i / tcam_depth) - 1 == reserved_v6_last / tcam_depth)) {
   9280 
   9281                 i += (reserved_v6_last + 1) % tcam_depth;
   9282             }
   9283 
   9284             if (pfxmap2[i] != SOC_LPM128_INDEX_TO_PFX_GROUP(u, i) ||
   9285                 pfxmap[i]  == -1) {
   9286                 LOG_ERROR(BSL_LS_SOC_LPM,
   9287                           (BSL_META_U(u,
   9288                                       "Reserverd: index missmatch: %d "
   9289                                       "  pfxmap %d, pfxmap2 %d, pfx %d \n"),
   9290                                       i, pfxmap[i], pfxmap2[i],
   9291                                       SOC_LPM128_INDEX_TO_PFX_GROUP(u, i)));
   9292                 error_count++;
   9293             }
   9294         }
   9295     } else {
   9296         for (i = 0; i < paired_size; i++) {
   9297             if (pfxmap2[i] != SOC_LPM128_INDEX_TO_PFX_GROUP(u, i) ||
   9298                 pfxmap[i]  == -1) {
   9299                 LOG_ERROR(BSL_LS_SOC_LPM,
   9300                           (BSL_META_U(u,
   9301                                       "Unreserverd: index missmatch: %d "
   9302                                       "  pfxmap %d, pfxmap2 %d, pfx %d \n"),
   9303                                       i, pfxmap[i], pfxmap2[i],
   9304                                       SOC_LPM128_INDEX_TO_PFX_GROUP(u, i)));
   9305                 error_count++;
   9306             }
   9307 
   9308             /* The following does sanity check on lpm128 hash table, with the 
   9309              * help from lpm128 state (say it's trustable) and a little help
   9310              * from cached l3_defip 
   9311              */
   9312             if (pfxmap2[i] != -1 && SOC_LPM128_PFX_IS_V6(u, pfxmap2[i])) {
   9313                 /* Valid v6 */
   9314                 if (LPM128_IN_EVEN_TCAM(u,i)) {
   9315                     /* left must exist in hash table, right must not exist */
   9316                     if (SOC_LPM128_STATE_HASH(u)->check_table[(i << 1)] == 0 ||
   9317                         SOC_LPM128_STATE_HASH(u)->check_table[(i << 1) + 1]) {
   9318                         error_count++;
   9319                         LOG_ERROR(BSL_LS_SOC_LPM,
   9320                                   (BSL_META_U(u,
   9321                                               "Unreserverd: check table error0: %d "
   9322                                               "  pfx %d, check_table %d %d \n"),
   9323                                               i, pfxmap2[i],
   9324                                               SOC_LPM128_STATE_HASH(u)->check_table[(i << 1)],
   9325                                               SOC_LPM128_STATE_HASH(u)->check_table[(i << 1) + 1]));
   9326                     }
   9327                 } else {
   9328                     /* both must not exist in hash table */
   9329                     if (SOC_LPM128_STATE_HASH(u)->check_table[(i << 1)] ||
   9330                         SOC_LPM128_STATE_HASH(u)->check_table[(i << 1) + 1]) {
   9331                         error_count++;
   9332                         LOG_ERROR(BSL_LS_SOC_LPM,
   9333                                   (BSL_META_U(u,
   9334                                               "Unreserverd: check table error1: %d "
   9335                                               "  pfx %d, check_table %d %d \n"),
   9336                                               i, pfxmap2[i],
   9337                                               SOC_LPM128_STATE_HASH(u)->check_table[(i << 1)],
   9338                                               SOC_LPM128_STATE_HASH(u)->check_table[(i << 1) + 1]));
   9339                     }
   9340                 }
   9341             } else if (pfxmap2[i] != -1 && SOC_LPM128_PFX_IS_V4(u, pfxmap2[i])) {
   9342                 /* Valid v4 */
   9343                 /* left half must exist in hash table */
   9344                 if (SOC_LPM128_STATE_HASH(u)->check_table[(i << 1)] == 0) {
   9345                     error_count++;
   9346                     LOG_ERROR(BSL_LS_SOC_LPM,
   9347                               (BSL_META_U(u,
   9348                                           "Unreserverd: check table error2: %d "
   9349                                           "  pfx %d, check_table %d \n"),
   9350                                           i, pfxmap2[i],
   9351                                           SOC_LPM128_STATE_HASH(u)->check_table[(i << 1)]));
   9352                 }
   9353 
   9354                 /* right half must exist in hash table when VALID1 is 1 */
   9355                 if (SOC_LPM128_STATE_HASH(u)->check_table[(i << 1) + 1] == 0) {
   9356                     /* further check if it's half entry, report error if not half entry */
   9357                     if (soc_L3_DEFIPm_field32_get(u, &(DBG_SOC_L3_DEFIP(u)[i]), VALID1f)) {
   9358                         error_count++;
   9359                         LOG_ERROR(BSL_LS_SOC_LPM,
   9360                                   (BSL_META_U(u,
   9361                                               "Unreserverd: check table error3: %d "
   9362                                               "  pfx %d, check_table %d \n"),
   9363                                               i, pfxmap2[i],
   9364                                               SOC_LPM128_STATE_HASH(u)->check_table[(i << 1) + 1]));
   9365                     }
   9366                 }
   9367             } else {
   9368                 /* Not valid entry, must not exist in hash table */
   9369                 if (SOC_LPM128_STATE_HASH(u)->check_table[(i << 1)] ||
   9370                     SOC_LPM128_STATE_HASH(u)->check_table[(i << 1) + 1]) {
   9371                     error_count++;
   9372                     LOG_ERROR(BSL_LS_SOC_LPM,
   9373                               (BSL_META_U(u,
   9374                                           "Unreserverd: check table error4: %d "
   9375                                           "  pfx %d, check_table %d %d \n"),
   9376                                           i, pfxmap2[i],
   9377                                           SOC_LPM128_STATE_HASH(u)->check_table[(i << 1)],
   9378                                           SOC_LPM128_STATE_HASH(u)->check_table[(i << 1) + 1]));
   9379                 }
   9380             }
   9381         }
   9382     }
   9383 
   9384     (void) lpm_state_verify(u, &error_count);
   9385 /* Parse for every operation is just too time intensive. */
   9386 /*
   9387     soc_fb_lpm_debug_parse(u, 0, &error_count);
   9388     soc_fb_lpm_hash_sanity(u, 0, &error_count); */
   9389 
   9390 done:
   9391     sal_free(pfxmap);
   9392     sal_free(pfxmap2);
   9393 
   9394     if (error_count) {
   9395         LOG_ERROR(BSL_LS_SOC_LPM,
   9396                   (BSL_META_U(u,
   9397                               "Total ERROR: %d \n"),
   9398                               error_count));
   9399         soc_fb_lpm_debug_collect(u);
   9400         return SOC_E_INTERNAL;
   9401     }
   9402     
   9403     if (SOC_LPM_STATE(u)) {
   9404         sal_memcpy(DBG_SOC_LPM_STATE(u),
   9405                    SOC_LPM_STATE(u),
   9406                    pfx_state_size2);
   9407     }
   9408 
   9409     if (SOC_LPM128_STATE(u)) {
   9410         sal_memcpy(DBG_SOC_LPM128_STATE(u),
   9411                    SOC_LPM128_STATE(u),
   9412                    pfx_state_size);
   9413     }
   9414 
   9415     if (SOC_LPM128_UNRESERVED_STATE(u)) {
   9416         sal_memcpy(DBG_SOC_LPM128_UNRESERVED_STATE(u),
   9417                    SOC_LPM128_UNRESERVED_STATE(u),
   9418                    pfx_state_size);
   9419     }
   9420 
   9421     if (SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u)) {
   9422         sal_memcpy(DBG_SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u),
   9423                    SOC_LPM128_INDEX_TO_PFX_GROUP_TABLE(u),
   9424                    (paired_size * sizeof(int)));
   9425     }
   9426 
   9427     if (SOC_LPM_STATE_HASH(u)) {
   9428         sal_memcpy(DBG_SOC_LPM_STATE_HASH(u)->table, 
   9429                    SOC_LPM_STATE_HASH(u)->table, 
   9430                    _fb_lpm_hash_tab[u]->index_count * sizeof(*(_fb_lpm_hash_tab[u]->table)));
   9431         sal_memcpy(DBG_SOC_LPM_STATE_HASH(u)->link_table, 
   9432                    SOC_LPM_STATE_HASH(u)->link_table, 
   9433                    _fb_lpm_hash_tab[u]->entry_count * sizeof(*(_fb_lpm_hash_tab[u]->link_table)));
   9434     }
   9435 
   9436     if (SOC_LPM128_STATE_HASH(u)) {
   9437         sal_memcpy(DBG_SOC_LPM128_STATE_HASH(u)->table, 
   9438                    SOC_LPM128_STATE_HASH(u)->table, 
   9439                    _fb_lpm128_hash_tab[u]->index_count * sizeof(*(_fb_lpm128_hash_tab[u]->table)));
   9440         sal_memcpy(DBG_SOC_LPM128_STATE_HASH(u)->link_table, 
   9441                    SOC_LPM128_STATE_HASH(u)->link_table, 
   9442                    _fb_lpm128_hash_tab[u]->entry_count * sizeof(*(_fb_lpm128_hash_tab[u]->link_table)));
   9443     }
   9444 
   9445     SOC_LPM128_STAT_128BV6_COUNT1(u)          =  SOC_LPM128_STAT_128BV6_COUNT(u);
   9446     SOC_LPM128_STAT_V4_COUNT1(u)              =  SOC_LPM128_STAT_V4_COUNT(u);
   9447     SOC_LPM128_STAT_64BV6_COUNT1(u)           =  SOC_LPM128_STAT_64BV6_COUNT(u);
   9448     SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT1(u)   =  SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u);
   9449     SOC_LPM_V4_COUNT1(u)                      =  SOC_LPM_V4_COUNT(u);
   9450     SOC_LPM_64BV6_COUNT1(u)                   =  SOC_LPM_64BV6_COUNT(u);
   9451     SOC_LPM_V4_HALF_ENTRY_COUNT1(u)           =  SOC_LPM_V4_HALF_ENTRY_COUNT(u);
   9452     
   9453     return SOC_E_NONE;
   9454 }
   9455 #endif
   9456 
   9457 
   9458 STATIC int
   9459 _lpm128_smallest_v6_prefix(int u)
   9460 {
   9461     int pfx;
   9462     int smallest_pfx = -1;
   9463     soc_lpm128_state_p lpm_state_ptr;
   9464 
   9465     pfx = MAX_PFX128_INDEX;
   9466     lpm_state_ptr = SOC_LPM128_STATE(u);
   9467     while(lpm_state_ptr && pfx != -1) {
   9468         pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, pfx);
   9469         if ((pfx == -1) || SOC_LPM128_PFX_IS_V4(u, pfx)) {
   9470             break;
   9471         }
   9472 
   9473         /* This happens when a v6 group is about to freed, its free
   9474          * entries are now available for next v4 to occupy.
   9475          * This also happens when a v6 group is created just now,
   9476          * in that case skip it and continue to find.
   9477          */
   9478         if (SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) == 0) {
   9479             continue;
   9480         }
   9481 
   9482         smallest_pfx = pfx;
   9483     }
   9484 
   9485     pfx = MAX_PFX128_INDEX;
   9486     lpm_state_ptr = SOC_LPM128_UNRESERVED_STATE(u);
   9487     while(lpm_state_ptr && pfx != -1) {
   9488         pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, pfx);
   9489         if ((pfx == -1) || SOC_LPM128_PFX_IS_V4(u, pfx)) {
   9490             break;
   9491         }
   9492 
   9493         /* This happens when a v6 group is about to freed, its free
   9494          * entries are now available for next v4 to occupy.
   9495          * This also happens when a v6 group is created just now,
   9496          * in that case skip it and continue to find.
   9497          */
   9498         if (SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) == 0) {
   9499             continue;
   9500         }
   9501 
   9502         smallest_pfx = pfx;
   9503     }
   9504 
   9505     return smallest_pfx;
   9506 }
   9507 
   9508 
   9509 STATIC int
   9510 _lpm128_v4_domain_odd_start(int u)
   9511 {
   9512     int pfx_id = -1;
   9513     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   9514     int fent = 0;
   9515     int end = 0;
   9516     int tcam_count = 0;
   9517     int rem = 0;
   9518     int fent_in_last_tcam = 0;
   9519     int max_128b_entries = SOC_L3_DEFIP_MAX_128B_ENTRIES(u);
   9520     soc_lpm128_state_p lpm_state_ptr = SOC_LPM128_STATE(u);
   9521     int v4_domain_odd_start;
   9522 
   9523     if (SOC_URPF_STATUS_GET(u) &&
   9524         !soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
   9525         max_128b_entries >>= 1;
   9526     }
   9527 
   9528     v4_domain_odd_start = tcam_depth;
   9529     pfx_id = _lpm128_smallest_v6_prefix(u);
   9530     if (pfx_id == -1) {
   9531         if (soc_feature(u, soc_feature_l3_lpm_128b_entries_reserved)) {
   9532             v4_domain_odd_start = (max_128b_entries / tcam_depth) * tcam_depth * 2 +
   9533                                   (max_128b_entries % tcam_depth);
   9534             v4_domain_odd_start += tcam_depth;
   9535         }
   9536 
   9537     } else {
   9538         if (SOC_LPM128_UNRESERVED_STATE(u)) {
   9539             lpm_state_ptr = SOC_LPM128_UNRESERVED_STATE(u);
   9540             if (SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx_id) == -1) {
   9541                 lpm_state_ptr = SOC_LPM128_STATE(u);
   9542             }
   9543         }
   9544 
   9545         end  = SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx_id);
   9546         fent = SOC_LPM128_STATE_FENT(u, lpm_state_ptr, pfx_id);
   9547         rem = tcam_depth - (end + 1) % tcam_depth;
   9548         if (tcam_depth == rem) {
   9549             rem  = 0;
   9550         }
   9551 
   9552         /*
   9553          * during the middle of conflicting process, free slot move up
   9554          * could result fent into 1, but that entry should still be
   9555          * considered as part of v4 domain.
   9556          */
   9557 
   9558         if (fent == 1) {
   9559             fent = 0;
   9560         }
   9561         if (fent >= 2  * rem) {
   9562             fent -= (2 * rem);
   9563             tcam_count = (end + rem + 1) / tcam_depth;;
   9564             if (tcam_count % 2) {
   9565                 tcam_count++;
   9566             }
   9567 
   9568             fent_in_last_tcam = (fent / 2) % tcam_depth;
   9569             fent -= (2 * fent_in_last_tcam);
   9570             tcam_count += (fent / tcam_depth);
   9571             v4_domain_odd_start = ((tcam_count + 1) * tcam_depth) + fent_in_last_tcam;
   9572         } else {
   9573             v4_domain_odd_start = end + tcam_depth + (fent / 2) + 1;
   9574         }
   9575 
   9576     }
   9577 
   9578     LOG_DEBUG(BSL_LS_SOC_LPM,
   9579               (BSL_META_U(u,
   9580                           "V4 DOMAIN START %d \n"), v4_domain_odd_start));
   9581     return v4_domain_odd_start;
   9582 }
   9583 
   9584 STATIC INLINE int
   9585 _lpm128_next_index(int u, int pfx,  /* pfx that index belongs to */
   9586                    int index)
   9587 {
   9588     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   9589     int next_idx = 0;
   9590     int v4_domain_start;
   9591 
   9592     next_idx = index + 1;
   9593     if (SOC_LPM128_PFX_IS_V4(u, pfx)) {
   9594         if (LPM128_IN_ODD_TCAM_FIRST(u, next_idx)) {
   9595             v4_domain_start = _lpm128_v4_domain_odd_start(u);
   9596             if (LPM128_TCAM_NUM(u, next_idx) ==
   9597                 LPM128_TCAM_NUM(u, v4_domain_start)) {
   9598                 next_idx = v4_domain_start;
   9599             }
   9600         }
   9601     } else if (SOC_LPM128_PFX_IS_V6(u, pfx)) {
   9602         if (LPM128_IN_ODD_TCAM(u, next_idx)) {
   9603             next_idx += tcam_depth;
   9604         }
   9605     }
   9606 
   9607     return next_idx;
   9608 }
   9609 
   9610 
   9611 STATIC INLINE int
   9612 _lpm128_prev_index(int u, int pfx,  /* pfx that index belongs to */
   9613                    soc_lpm128_state_p lpm_state_ptr,
   9614                    int index)
   9615 {
   9616     int prev_pfx;
   9617     int prev_idx;
   9618     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   9619     int v4_domain_start;
   9620     int is_v4 = 0;
   9621 
   9622     if (SOC_LPM128_PFX_IS_V4(u, pfx)) {
   9623         prev_pfx = SOC_LPM128_STATE_PREV(u, lpm_state_ptr, pfx);
   9624         if (prev_pfx == -1  ||
   9625             SOC_LPM128_PFX_IS_V4(u, prev_pfx) ||
   9626             index > SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx)) {
   9627             is_v4 = 1;
   9628         }
   9629 
   9630         /* This happens when a v6 group is about to freed, its free
   9631          * entries are now available for v4 to occupy.
   9632          */
   9633         if (prev_pfx != -1 &&
   9634             SOC_LPM128_STATE_VENT(u, lpm_state_ptr, prev_pfx) == 0) {
   9635             is_v4 = 1;
   9636         }
   9637     }
   9638 
   9639     prev_idx = index - 1;
   9640     if (is_v4) {
   9641         v4_domain_start = _lpm128_v4_domain_odd_start(u);
   9642         if (LPM128_TCAM_NUM(u, v4_domain_start) ==
   9643             LPM128_TCAM_NUM(u, prev_idx) &&
   9644             prev_idx < v4_domain_start) {
   9645             prev_idx = LPM128_TCAM_NUM(u, prev_idx) * tcam_depth - 1;
   9646         }
   9647     } else {
   9648         if (LPM128_IN_ODD_TCAM(u, prev_idx)) {
   9649             prev_idx -= tcam_depth;
   9650         }
   9651     }
   9652 
   9653     return prev_idx;
   9654 }
   9655 
   9656 /*
   9657  *  Copy (or move if erase set) entry from from_ent to to_ent.
   9658  */
   9659 STATIC int
   9660 _lpm128_fb_entry_shift(int u, int pfx,
   9661                        int from_ent, void *fe, void *feupr,
   9662                        int to_ent, int erase)
   9663 {
   9664     uint32 v0 = 0;
   9665     uint32      e[SOC_MAX_MEM_FIELD_WORDS] = {0};
   9666     uint32      eupr[SOC_MAX_MEM_FIELD_WORDS] = {0};
   9667     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
   9668     int         rv = SOC_E_NONE;
   9669     uint32      rvt_index0 = 0, rvt_index1 = 0;
   9670     soc_mem_t mem = L3_DEFIPm;
   9671 
   9672 #if defined(BCM_TOMAHAWK3_SUPPORT)
   9673     if (SOC_IS_TOMAHAWK3(u)) {
   9674         mem = L3_DEFIP_LEVEL1m;
   9675     }
   9676 #endif
   9677 
   9678     if (from_ent == to_ent) {
   9679         return SOC_E_NONE;
   9680     }
   9681 
   9682 #ifdef FB_LPM_TABLE_CACHED
   9683     SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, mem,
   9684                                        MEM_BLOCK_ANY, from_ent));
   9685 #endif /* FB_LPM_TABLE_CACHED */
   9686 
   9687     if (fe) {
   9688         sal_memcpy(e, fe, soc_mem_entry_words(u,mem) * 4);
   9689     } else {
   9690         rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, e);
   9691         SOC_IF_ERROR_RETURN(rv);
   9692     }
   9693     if (SOC_LPM128_PFX_IS_V6(u, pfx)) {
   9694 
   9695         if (feupr) {
   9696             sal_memcpy(eupr, feupr, soc_mem_entry_words(u, mem) * 4);
   9697         } else {
   9698             rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY,
   9699                                            from_ent + tcam_depth, eupr);
   9700             SOC_IF_ERROR_RETURN(rv);
   9701         }
   9702         LPM128_HASH_INSERT(u, e, eupr, to_ent, &rvt_index0, &rvt_index1);
   9703         /* Disable valid bit at to_ent + tcam_depth so that packets dont
   9704          * get forwared to some transient addresses
   9705          */
   9706         v0 = SOC_MEM_OPT_F32_VALID0_GET(u, mem, eupr);
   9707         if (v0) {
   9708             SOC_MEM_OPT_F32_VALID0_SET(u, mem, eupr, 0);
   9709             SOC_IF_ERROR_RETURN(WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY,
   9710                                                 to_ent + tcam_depth, eupr));
   9711         }
   9712         rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, to_ent, e);
   9713         if (v0) {
   9714             SOC_MEM_OPT_F32_VALID0_SET(u, mem, eupr, v0);
   9715         }
   9716         if (rv >= 0) {
   9717             rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, to_ent + tcam_depth, eupr);
   9718         }
   9719 
   9720         if (rv >= 0) {
   9721         /* coverity[copy_paste_error : FALSE] */
   9722             rv = _lpm128_fb_urpf_entry_replicate(u, to_ent, -1, e, eupr);
   9723         }
   9724         if (rv < 0) {
   9725             LPM128_HASH_REVERT(u, e, eupr, to_ent, rvt_index0, rvt_index1);
   9726             return rv;
   9727         }
   9728         SOC_LPM128_INDEX_TO_PFX_GROUP(u, to_ent + tcam_depth) = pfx;
   9729 
   9730     } else {
   9731         LPM128_HASH_INSERT(u, e, NULL, to_ent, &rvt_index0, &rvt_index1);
   9732         rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, to_ent, e);
   9733         if (rv >= 0) {
   9734             rv = _lpm128_fb_urpf_entry_replicate(u, to_ent, -1, e, NULL);
   9735         }
   9736         if (rv < 0) {
   9737             LPM128_HASH_REVERT(u, e, NULL, to_ent, rvt_index0, rvt_index1);
   9738             return rv;
   9739         }
   9740     }
   9741 
   9742     SOC_LPM128_INDEX_TO_PFX_GROUP(u, to_ent) = pfx;
   9743 
   9744     if (erase) {
   9745         sal_memcpy(e, soc_mem_entry_null(u, mem),
   9746                    soc_mem_entry_words(u,mem) * 4);
   9747         SOC_IF_ERROR_RETURN(WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, e));
   9748         SOC_LPM128_INDEX_TO_PFX_GROUP(u, from_ent) = -1;
   9749         if (SOC_LPM128_PFX_IS_V6(u, pfx)) {
   9750             SOC_IF_ERROR_RETURN(WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY,
   9751                                 from_ent + tcam_depth, e));
   9752             SOC_LPM128_INDEX_TO_PFX_GROUP(u, from_ent + tcam_depth) = -1;
   9753             SOC_IF_ERROR_RETURN(_lpm128_fb_urpf_entry_replicate(u, from_ent, -1,
   9754                                                                 e, e));
   9755         } else {
   9756             SOC_IF_ERROR_RETURN(_lpm128_fb_urpf_entry_replicate(u, from_ent, -1,
   9757                                                                 e, NULL));
   9758         }
   9759     }
   9760     return (SOC_E_NONE);
   9761 }
   9762 
   9763 STATIC int
   9764 _lpm128_fb_shift_v4_pfx_up(int u, soc_lpm128_state_p lpm_state_ptr, int pfx)
   9765 {
   9766     uint32      e[SOC_MAX_MEM_FIELD_WORDS] = {0};
   9767     int         end;
   9768     int         end_next;
   9769     int         end_cross = 0;
   9770     int         start1;
   9771     int         start1_next;
   9772     int         start1_cross;
   9773     int         from_end2;
   9774     uint32      v0, v1;
   9775     int         half_entry;
   9776 
   9777     int rv = SOC_E_NONE;
   9778     soc_mem_t mem = L3_DEFIPm;
   9779 
   9780 #if defined(BCM_TOMAHAWK3_SUPPORT)
   9781     if (SOC_IS_TOMAHAWK3(u)) {
   9782         mem = L3_DEFIP_LEVEL1m;
   9783     }
   9784 #endif
   9785 
   9786 
   9787     start1 = SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx);
   9788     if (SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) != -1) {
   9789         end = SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx);
   9790         from_end2 = 1;
   9791     } else {
   9792         end = SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx);
   9793         from_end2 = 0;
   9794     }
   9795     end_next    = _lpm128_next_index(u, pfx, end);
   9796     start1_next = _lpm128_next_index(u, pfx, start1);
   9797     end_cross    = (end_next - end) > 1;
   9798     start1_cross = (start1_next - start1) > 1;
   9799 
   9800 #ifdef FB_LPM_TABLE_CACHED
   9801     SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, mem,
   9802                                                  MEM_BLOCK_ANY, end));
   9803 #endif /* FB_LPM_TABLE_CACHED */
   9804     rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, end, e);
   9805     SOC_IF_ERROR_RETURN(rv);
   9806     v0 = SOC_MEM_OPT_F32_VALID0_GET(u, mem, e);
   9807     v1 = SOC_MEM_OPT_F32_VALID1_GET(u, mem, e);
   9808 
   9809     half_entry = (v0 == 0 || v1 == 0) &&
   9810                  (SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) > 1) && 
   9811                  !soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity);
   9812 
   9813     if (half_entry) {
   9814         /* Last entry is half full -> keep it last. */
   9815         SOC_IF_ERROR_RETURN(_lpm128_fb_entry_shift(u, pfx, end, e, NULL,
   9816                                                    end_next, 0));
   9817         SOC_IF_ERROR_RETURN(_lpm128_fb_entry_shift(u, pfx, start1, NULL, NULL,
   9818                                                    end, 0));
   9819     } else {
   9820         SOC_IF_ERROR_RETURN(_lpm128_fb_entry_shift(u, pfx, start1, NULL, NULL,
   9821                                                    end_next, 0));
   9822     }
   9823 
   9824     /* No need to erase start1 entry, as it will be done by caller. */
   9825 
   9826     if (from_end2) {
   9827         assert (!end_cross);
   9828         if (start1_cross) {
   9829             SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx)  = start1_next;
   9830             SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx)    = end_next;
   9831             SOC_LPM128_STATE_START2(u, lpm_state_ptr, pfx)  = -1;
   9832             SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx)    = -1;
   9833         } else {
   9834             SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx)  = start1_next;
   9835             SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx)    = end_next;
   9836         }
   9837     } else {
   9838         if (end_cross) {
   9839             if (start1_cross) {
   9840                 assert (start1_next == end_next);
   9841                 SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx)  = start1_next;
   9842                 SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx)    = end_next;
   9843             } else {
   9844                 SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx)  = start1_next;
   9845                 SOC_LPM128_STATE_START2(u, lpm_state_ptr, pfx)  = end_next;
   9846                 SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx)    = end_next;
   9847             }
   9848         } else {
   9849             assert (!start1_cross);
   9850             SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx)  = start1_next;
   9851             SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx)    = end_next;
   9852         }
   9853     }
   9854     return SOC_E_NONE;
   9855 }
   9856 
   9857 /*
   9858  *      Shift prefix entries 1 entry UP, while preserving
   9859  *      last half empty IPv4 entry if any.
   9860  */
   9861 STATIC int
   9862 _lpm128_fb_shift_pfx_up(int u, soc_lpm128_state_p lpm_state_ptr, int pfx)
   9863 {
   9864     int         start;
   9865     int         start_next;
   9866     int         end;
   9867     int         end_next;
   9868 
   9869     if (SOC_LPM128_PFX_IS_V4(u, pfx)) {
   9870         return _lpm128_fb_shift_v4_pfx_up(u, lpm_state_ptr, pfx);
   9871     }
   9872 
   9873     start = SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx);
   9874     end   = SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx);
   9875     end_next   = _lpm128_next_index(u, pfx, end);
   9876     start_next = _lpm128_next_index(u, pfx, start);
   9877 
   9878     SOC_IF_ERROR_RETURN(_lpm128_fb_entry_shift(u, pfx, start, NULL, NULL,
   9879                                                end_next, 0));
   9880 
   9881     SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx) = start_next;
   9882     SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) = end_next;
   9883     return (SOC_E_NONE);
   9884 }
   9885 
   9886 
   9887 STATIC int
   9888 _lpm128_fb_shift_v4_pfx_down(int u, soc_lpm128_state_p lpm_state_ptr, int pfx)
   9889 {
   9890     int         end;
   9891     int         end_prev;
   9892     int         end_cross;
   9893     int         from_end2;
   9894     int         v0, v1;
   9895     int         prev_pfx = 0;
   9896     int         start1;
   9897     int         start1_cross = 0;
   9898     int         start1_prev = -1;
   9899     int         half_entry;
   9900     uint32      e[SOC_MAX_MEM_FIELD_WORDS] = {0};
   9901     int         erase;
   9902     int rv = SOC_E_NONE;
   9903     soc_mem_t mem = L3_DEFIPm;
   9904 
   9905 #if defined(BCM_TOMAHAWK3_SUPPORT)
   9906     if (SOC_IS_TOMAHAWK3(u)) {
   9907         mem = L3_DEFIP_LEVEL1m;
   9908     }
   9909 #endif
   9910 
   9911 
   9912     prev_pfx = SOC_LPM128_STATE_PREV(u, lpm_state_ptr, pfx);
   9913     if (prev_pfx == -1) {
   9914         LOG_ERROR(BSL_LS_SOC_LPM,
   9915                   (BSL_META_U(u,
   9916                               "v4 move down: previous pfx is -1 for pfx: %d\n"), pfx));
   9917         return SOC_E_INTERNAL;
   9918     }
   9919 
   9920     start1 = SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx);
   9921     if (SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) != -1) {
   9922         from_end2 = 1;
   9923         end   = SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx);
   9924     } else {
   9925         from_end2 = 0;
   9926         end   = SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx);
   9927     }
   9928 
   9929     end_prev    = _lpm128_prev_index(u, pfx, lpm_state_ptr, end);
   9930     start1_prev = _lpm128_prev_index(u, pfx, lpm_state_ptr, start1);
   9931 
   9932     end_cross    = (end - end_prev) > 1;
   9933     start1_cross = (start1 - start1_prev) > 1;
   9934 
   9935     /* Check if vent is 0. Then no need to move, just update start and end */
   9936     /* This case is hit if the prefix group is created just now */
   9937     if (SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) == 0) {
   9938         SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx) = start1_prev;
   9939         SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx)   = start1_prev - 1;
   9940         SOC_LPM128_INDEX_TO_PFX_GROUP(u, start1_prev) = pfx;
   9941         return SOC_E_NONE;
   9942     }
   9943 
   9944 #ifdef FB_LPM_TABLE_CACHED
   9945     SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, mem,
   9946                                                  MEM_BLOCK_ANY, end));
   9947 #endif /* FB_LPM_TABLE_CACHED */
   9948     rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, end, e);
   9949     SOC_IF_ERROR_RETURN(rv);
   9950     v0 = SOC_MEM_OPT_F32_VALID0_GET(u, mem, e);
   9951     v1 = SOC_MEM_OPT_F32_VALID1_GET(u, mem, e);
   9952 
   9953     half_entry = (v0 == 0 || v1 == 0) &&
   9954                  (SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) > 1) && 
   9955                   !soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity);
   9956 
   9957     /*
   9958      * When this v4_pfx's end crosses tcam boundary, we need to erase 
   9959      * immediately instead of leaving it to a further write. Because a further
   9960      * write can only overwrite one entry, but for a end cross entry, we are 
   9961      * actually moving 2 entries. This could happen on both directions:
   9962      * Giving v6 free entries to v4 or giving v4 free entries to v6.
   9963      * When pfx is V4 and prev_pfx is V6, and V6 needs to give away index, we
   9964      * also need to erase immediately.
   9965      */
   9966     erase = end_cross || (SOC_LPM128_PFX_IS_V6(u, prev_pfx));
   9967     if (half_entry == 0) {
   9968         SOC_IF_ERROR_RETURN(_lpm128_fb_entry_shift(u, pfx,
   9969                                                    end, e, NULL,
   9970                                                    start1_prev, erase));
   9971     } else {
   9972         SOC_IF_ERROR_RETURN(_lpm128_fb_entry_shift(u, pfx,
   9973                                                    end_prev, NULL, NULL,
   9974                                                    start1_prev, 0));
   9975 
   9976         SOC_IF_ERROR_RETURN(_lpm128_fb_entry_shift(u, pfx,
   9977                                                    end, e, NULL,
   9978                                                    end_prev, erase));
   9979     }
   9980 
   9981     if (from_end2) {
   9982         assert (!start1_cross);
   9983         if (end_cross) {
   9984             SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx) = start1_prev;
   9985             SOC_LPM128_STATE_START2(u, lpm_state_ptr, pfx) = -1;
   9986             SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx)   = -1;
   9987         } else {
   9988             SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx) = start1_prev;
   9989             SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx)   = end_prev;
   9990         }
   9991     } else {
   9992         if (start1_cross) {
   9993             if (end_cross) {
   9994                 assert (start1_prev == end_prev);
   9995                 SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx) = start1_prev;
   9996                 SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx)   = end_prev;
   9997             } else {
   9998                 SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx) = start1_prev;
   9999                 SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx)   = start1_prev;
  10000                 SOC_LPM128_STATE_START2(u, lpm_state_ptr, pfx) = start1;
  10001                 SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx)   = end_prev;
  10002             }
  10003         } else {
  10004             assert (!end_cross);
  10005             SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx) = start1_prev;
  10006             SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx)   = end_prev;
  10007         }
  10008     }
  10009     return SOC_E_NONE;
  10010 }
  10011 
  10012 /*
  10013  *      Shift prefix entries 1 entry DOWN, while preserving
  10014  *      last half empty IPv4 entry if any.
  10015  */
  10016 STATIC int
  10017 _lpm128_fb_shift_pfx_down(int u, soc_lpm128_state_p lpm_state_ptr, int pfx)
  10018 {
  10019     int         end;
  10020     int         end_prev;
  10021     int         start;
  10022     int         start_prev;
  10023 
  10024     if (SOC_LPM128_PFX_IS_V4(u, pfx)) {
  10025         return _lpm128_fb_shift_v4_pfx_down(u, lpm_state_ptr, pfx);
  10026     }
  10027 
  10028     start = SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx);
  10029     end   = SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx);
  10030     start_prev = _lpm128_prev_index(u, pfx, lpm_state_ptr, start);
  10031     end_prev   = _lpm128_prev_index(u, pfx, lpm_state_ptr, end);
  10032     /* Don't move empty prefix .
  10033      * This condition is hit if pfx is created for the first time
  10034      */
  10035     if (SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) == 0) {
  10036         SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx) = start_prev;
  10037         SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) = start_prev - 1;
  10038         SOC_LPM128_INDEX_TO_PFX_GROUP(u, start_prev) = pfx;
  10039         return (SOC_E_NONE);
  10040     }
  10041 
  10042     SOC_IF_ERROR_RETURN(_lpm128_fb_entry_shift(u, pfx, end, NULL, NULL,
  10043                                                start_prev, 0));
  10044 
  10045     SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx) = start_prev;
  10046     SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx)   = end_prev;
  10047 
  10048     return (SOC_E_NONE);
  10049 }
  10050 
  10051 STATIC int
  10052 _lpm128_free_slot_move_up(int u, int pfx, int free_pfx,
  10053                           soc_lpm128_state_p lpm_state_ptr);
  10054 STATIC int
  10055 _lpm128_free_slot_move_down(int u, int pfx, int free_pfx,
  10056                             soc_lpm128_state_p lpm_state_ptr);
  10057 
  10058 STATIC int
  10059 _lpm128_move_v4_entry_away_for_v6(int u,
  10060                                   int v6_pfx,     /* last v6 pfx */
  10061                                   int v6_domain_end,
  10062                                   soc_lpm128_state_p lpm_state_ptr)
  10063 {
  10064     int free_pfx    = -1;
  10065     int start_ent   = -1;
  10066     int end_ent     = -1;
  10067     int new_end     = -1;
  10068     int tcam_depth  = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
  10069     int from_end2   = 0;
  10070     int v4_odd_start;      /* index of v4 entry that should be given to v6_pfx */
  10071     int v4_pfx = -1;       /* v4 pfx other index belongs to */
  10072     int it_pfx;
  10073     int entry_count;
  10074     int half_entry = 0;
  10075     uint32  e[SOC_MAX_MEM_FIELD_WORDS] = {0};
  10076     uint32  v0 = 0, v1 = 0;
  10077     int rv = SOC_E_NONE;
  10078     soc_mem_t mem = L3_DEFIPm;
  10079 
  10080 #if defined(BCM_TOMAHAWK3_SUPPORT)
  10081     if (SOC_IS_TOMAHAWK3(u)) {
  10082         mem = L3_DEFIP_LEVEL1m;
  10083     }
  10084 #endif
  10085 
  10086 
  10087     v4_odd_start = v6_domain_end + tcam_depth;
  10088     if (LPM128_IN_EVEN_TCAM(u, v4_odd_start)) {
  10089         LOG_ERROR(BSL_LS_SOC_LPM,
  10090                   (BSL_META_U(u,
  10091                               "creating free slot: other_idx: %d is in even tcam "\
  10092                               " v6_pfx: %d\n"),
  10093                    v4_odd_start, v6_pfx));
  10094         return SOC_E_INTERNAL;
  10095     }
  10096 
  10097     /*
  10098      * v4_odd_start is empty, simply swap the fent
  10099      */
  10100     if (SOC_LPM128_INDEX_TO_PFX_GROUP(u, v4_odd_start) == -1) {
  10101         it_pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, v6_pfx);
  10102         v4_pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, v6_pfx);
  10103 
  10104         while (it_pfx != -1) {
  10105             if (SOC_LPM128_STATE_START1(u, lpm_state_ptr, it_pfx) >
  10106                 v4_odd_start) {
  10107                 break;
  10108             }
  10109             v4_pfx = it_pfx;
  10110             it_pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, it_pfx);
  10111         }
  10112         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, v4_pfx) -= 1;
  10113         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, v6_pfx) += 1;
  10114         return SOC_E_NONE;
  10115     }
  10116 
  10117     v4_pfx = SOC_LPM128_INDEX_TO_PFX_GROUP(u, v4_odd_start);
  10118     assert (SOC_LPM128_PFX_IS_V4(u, v4_pfx));
  10119     free_pfx = v4_pfx;
  10120     while (SOC_LPM128_STATE_FENT(u, lpm_state_ptr, free_pfx) == 0) {
  10121         free_pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, free_pfx);
  10122         if (free_pfx == -1) {
  10123             free_pfx = v4_pfx;
  10124             break;
  10125         }
  10126     }
  10127 
  10128     while (SOC_LPM128_STATE_FENT(u, lpm_state_ptr, free_pfx) == 0) {
  10129        free_pfx = SOC_LPM128_STATE_PREV(u, lpm_state_ptr, free_pfx);
  10130        if (free_pfx == -1) {
  10131            return SOC_E_FULL;
  10132        }
  10133     }
  10134 
  10135     if (free_pfx >= v6_pfx) {
  10136         LOG_ERROR(BSL_LS_SOC_LPM,
  10137                   (BSL_META_U(u,
  10138                               "moving v4 entry to create space for V6: v6_pfx: %d "\
  10139                               "free_pfx: %d v4_pfx: %d\n"), v6_pfx, free_pfx,
  10140                    v4_pfx));
  10141         return SOC_E_FULL;
  10142     }
  10143 
  10144     if (free_pfx < v4_pfx) {
  10145         SOC_IF_ERROR_RETURN(_lpm128_free_slot_move_up(u, v4_pfx, free_pfx,
  10146                                                       lpm_state_ptr));
  10147     }
  10148 
  10149     if (free_pfx > v4_pfx) {
  10150         SOC_IF_ERROR_RETURN(_lpm128_free_slot_move_down(u, v4_pfx, free_pfx,
  10151                                                         lpm_state_ptr));
  10152     }
  10153 
  10154     if (SOC_LPM128_STATE_START2(u, lpm_state_ptr, v4_pfx) != -1) {
  10155         start_ent = SOC_LPM128_STATE_START2(u, lpm_state_ptr, v4_pfx);
  10156         end_ent   = SOC_LPM128_STATE_END2(u, lpm_state_ptr, v4_pfx);
  10157         from_end2 = 1;
  10158     } else {
  10159         start_ent = SOC_LPM128_STATE_START1(u, lpm_state_ptr, v4_pfx);
  10160         end_ent   = SOC_LPM128_STATE_END1(u, lpm_state_ptr, v4_pfx);
  10161         from_end2 = 0;
  10162     }
  10163 
  10164     /* During free_slot_move_down, v4_odd_start could be moved to
  10165      * to create free space. In this case, job done.
  10166      * And no need to erase, since the goal is to create free slot
  10167      * for ipv6 to occupy.
  10168      */
  10169     if (SOC_LPM128_INDEX_TO_PFX_GROUP(u, v4_odd_start) == -1) {
  10170         assert (free_pfx > v4_pfx && end_ent < v4_odd_start);
  10171         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, v4_pfx) -= 1;
  10172         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, v6_pfx) += 1;
  10173 
  10174         return SOC_E_NONE;
  10175     }
  10176 
  10177     new_end = _lpm128_next_index(u, v4_pfx, end_ent);
  10178 
  10179 #ifdef FB_LPM_TABLE_CACHED
  10180     SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, mem,
  10181                                                  MEM_BLOCK_ANY, end_ent));
  10182 #endif /* FB_LPM_TABLE_CACHED */
  10183     rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, end_ent, e);
  10184     SOC_IF_ERROR_RETURN(rv);
  10185     v0 = SOC_MEM_OPT_F32_VALID0_GET(u, mem, e);
  10186     v1 = SOC_MEM_OPT_F32_VALID1_GET(u, mem, e);
  10187     
  10188     entry_count = end_ent - v4_odd_start + 1;
  10189     if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
  10190         half_entry = (v0 == 0 || v1 == 0) && (entry_count > 1);
  10191     }
  10192     if (half_entry == 0)  {
  10193         SOC_IF_ERROR_RETURN(_lpm128_fb_entry_shift(u, v4_pfx,
  10194                                                    v4_odd_start, NULL, NULL,
  10195                                                    new_end, 0));
  10196     } else {
  10197        /* Last entry is half full -> keep it last. */
  10198         SOC_IF_ERROR_RETURN(_lpm128_fb_entry_shift(u, v4_pfx,
  10199                                                    end_ent, e, NULL,
  10200                                                    new_end, 0));
  10201         SOC_IF_ERROR_RETURN(_lpm128_fb_entry_shift(u, v4_pfx,
  10202                                                    v4_odd_start, NULL, NULL,
  10203                                                    end_ent, 0));
  10204     }
  10205 
  10206     if (from_end2 == 0) {
  10207         if (start_ent == v4_odd_start) {
  10208             SOC_LPM128_STATE_START1(u, lpm_state_ptr, v4_pfx) += 1;
  10209             SOC_LPM128_STATE_END1(u, lpm_state_ptr, v4_pfx) += 1;
  10210         } else {
  10211             /* must split */
  10212             assert (start_ent < v4_odd_start && end_ent >= v4_odd_start);
  10213             assert (LPM128_TCAM_NUM(u, start_ent) <
  10214                     LPM128_TCAM_NUM(u, end_ent));
  10215             assert (LPM128_IN_ODD_TCAM_FIRST(u, v4_odd_start));
  10216 
  10217             SOC_LPM128_STATE_END1(u, lpm_state_ptr, v4_pfx) = v4_odd_start - 1;
  10218             SOC_LPM128_STATE_START2(u, lpm_state_ptr, v4_pfx) = v4_odd_start + 1;
  10219             SOC_LPM128_STATE_END2(u, lpm_state_ptr, v4_pfx) = end_ent + 1;
  10220         }
  10221     } else {
  10222         assert (start_ent == v4_odd_start);
  10223         SOC_LPM128_STATE_START2(u, lpm_state_ptr, v4_pfx) += 1;
  10224         SOC_LPM128_STATE_END2(u, lpm_state_ptr, v4_pfx) += 1;
  10225     }
  10226 
  10227     SOC_LPM128_STATE_FENT(u, lpm_state_ptr, v4_pfx) -= 1;
  10228     SOC_LPM128_STATE_FENT(u, lpm_state_ptr, v6_pfx) += 1;
  10229 
  10230     return SOC_E_NONE;
  10231 }
  10232 
  10233 
  10234 STATIC int
  10235 _lpm128_move_v4_entry_down_for_v6(int u, int free_cnt,
  10236                                   int start_index,
  10237                                   int other_pfx,
  10238                                   soc_lpm128_state_p lpm_state_ptr)
  10239 {
  10240     int start;
  10241     int end = -1;
  10242     int entry_count = 0;
  10243     int from, to;
  10244     uint32      e[SOC_MAX_MEM_FIELD_WORDS] = {0};
  10245     uint32      v0 = 0, v1 = 0;
  10246     int half_entry = 0;
  10247     int erase;
  10248     int rv = SOC_E_NONE;
  10249     soc_mem_t mem = L3_DEFIPm;
  10250 
  10251 #if defined(BCM_TOMAHAWK3_SUPPORT)
  10252     if (SOC_IS_TOMAHAWK3(u)) {
  10253         mem = L3_DEFIP_LEVEL1m;
  10254     }
  10255 #endif
  10256 
  10257 
  10258     start = SOC_LPM128_STATE_START2(u, lpm_state_ptr, other_pfx);
  10259     end   = SOC_LPM128_STATE_END2(u, lpm_state_ptr, other_pfx);
  10260     if (end == -1) {
  10261         return SOC_E_INTERNAL;
  10262     }
  10263     entry_count = end - start + 1;
  10264 #ifdef FB_LPM_TABLE_CACHED
  10265     SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, mem,
  10266                                                  MEM_BLOCK_ANY, end));
  10267 #endif /* FB_LPM_TABLE_CACHED */
  10268     rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, end, e);
  10269     SOC_IF_ERROR_RETURN(rv);
  10270     v0 = SOC_MEM_OPT_F32_VALID0_GET(u, mem, e);
  10271     v1 = SOC_MEM_OPT_F32_VALID1_GET(u, mem, e);
  10272     if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
  10273         half_entry = (v0 == 0 || v1 == 0) && (entry_count > 1);
  10274     }
  10275     if (half_entry) {
  10276         from = end - 1;
  10277     } else {
  10278         from = end;
  10279     }
  10280     to = start_index;
  10281 
  10282     /* Normally do erase, unless half_entry can overwrite */
  10283     erase = !half_entry || start != (to + 1);
  10284 
  10285     while (from >= start && to < start) {
  10286         SOC_IF_ERROR_RETURN(_lpm128_fb_entry_shift(u, other_pfx, from, NULL, NULL,
  10287                                                    to, erase));
  10288         from--;
  10289         to++;
  10290     }
  10291 
  10292     if (half_entry) {
  10293         if (to < start) {
  10294             SOC_IF_ERROR_RETURN
  10295             (_lpm128_fb_entry_shift(u, other_pfx, end, e, NULL,
  10296                                     to, 1));
  10297         } else {
  10298             from++;
  10299             SOC_IF_ERROR_RETURN
  10300             (_lpm128_fb_entry_shift(u, other_pfx, end, e, NULL,
  10301                                     from, 1));
  10302         }
  10303     }
  10304 
  10305     SOC_LPM128_STATE_START2(u, lpm_state_ptr, other_pfx) -= free_cnt;
  10306     SOC_LPM128_STATE_END2(u, lpm_state_ptr, other_pfx) -= free_cnt;
  10307 
  10308     if (SOC_LPM128_STATE_START2(u, lpm_state_ptr, other_pfx) ==
  10309         SOC_LPM128_STATE_END1(u, lpm_state_ptr, other_pfx) + 1) {
  10310         SOC_LPM128_STATE_END1(u, lpm_state_ptr, other_pfx) =
  10311             SOC_LPM128_STATE_END2(u, lpm_state_ptr, other_pfx);
  10312         SOC_LPM128_STATE_START2(u, lpm_state_ptr, other_pfx) = -1;
  10313         SOC_LPM128_STATE_END2(u, lpm_state_ptr, other_pfx) = -1;
  10314     }
  10315 
  10316     return SOC_E_NONE;
  10317 }
  10318 
  10319 STATIC int
  10320 _lpm128_move_next_pfx_down_during_delete(int u, int pfx,
  10321                                          soc_lpm128_state_p lpm_state_ptr)
  10322 {
  10323     int end = -1;
  10324     int from_end2 = 0;
  10325     int half_entry = 0;
  10326     uint32 v0, v1;
  10327     int rv;
  10328     int end_prev = 0;
  10329     int end1_index = -1;
  10330     int end2_index = -1;
  10331     int start2_index = -1;
  10332     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
  10333     int fent2 = 0;
  10334     int range2_move = 0;
  10335     int bottom_pfx = 0;
  10336     uint32      e[SOC_MAX_MEM_FIELD_WORDS] = {0};
  10337     int from, to, prev_to, prev_from;
  10338     int other_start;
  10339     int other_pfx = 0;
  10340     int other_start_v4;
  10341     int vent;
  10342     int fent_start = SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx);
  10343     int fent = SOC_LPM128_STATE_FENT(u, lpm_state_ptr, pfx);
  10344     int next_pfx =  SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, pfx);
  10345     int start   = -1;
  10346     int v4_pfx  = -1;
  10347     int erase;
  10348     soc_mem_t mem = L3_DEFIPm;
  10349 
  10350 #if defined(BCM_TOMAHAWK3_SUPPORT)
  10351     if (SOC_IS_TOMAHAWK3(u)) {
  10352         mem = L3_DEFIP_LEVEL1m;
  10353     }
  10354 #endif
  10355 
  10356 
  10357     /* take care of deleting 64BV6 prefix group previous to V4 prefix group */
  10358     if (_lpm128_pfx_conflicting(next_pfx, pfx)) {
  10359         v4_pfx = next_pfx;
  10360 
  10361         other_start_v4 = SOC_LPM128_STATE_START1(u, lpm_state_ptr, v4_pfx) +
  10362                          tcam_depth;
  10363         other_pfx    = v4_pfx;
  10364         bottom_pfx   = v4_pfx;
  10365         while (other_pfx != -1) {
  10366             if (SOC_LPM128_STATE_START1(u, lpm_state_ptr, other_pfx) >=
  10367                 other_start_v4 ||
  10368                 SOC_LPM128_STATE_START2(u, lpm_state_ptr, other_pfx) >=
  10369                 other_start_v4) {
  10370                 break;
  10371             }
  10372             bottom_pfx = other_pfx;
  10373             other_pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, other_pfx);
  10374         }
  10375 
  10376         range2_move = other_pfx != -1 &&
  10377                       SOC_LPM128_STATE_END2(u, lpm_state_ptr, other_pfx) != -1;
  10378 
  10379         if (LPM128_TCAM_NUM(u, fent_start) ==
  10380             LPM128_TCAM_NUM(u, SOC_LPM128_STATE_START1(u, lpm_state_ptr, v4_pfx))) {
  10381             fent2 = fent >> 1;
  10382             other_start = fent_start + tcam_depth;
  10383         } else {
  10384             fent2 = ((fent >> 1) + fent_start) % tcam_depth;
  10385             other_start = SOC_LPM128_STATE_START2(u, lpm_state_ptr, other_pfx) /
  10386                           tcam_depth * tcam_depth;
  10387         }
  10388 
  10389         if (range2_move) {
  10390             /* move other_pfx to make contiguous */
  10391             SOC_IF_ERROR_RETURN(
  10392                 _lpm128_move_v4_entry_down_for_v6(u, fent2,
  10393                     other_start, other_pfx, lpm_state_ptr));
  10394         }
  10395     }
  10396 
  10397     if (SOC_LPM128_STATE_END2(u, lpm_state_ptr, next_pfx) != -1) {
  10398         end = SOC_LPM128_STATE_END2(u, lpm_state_ptr, next_pfx);
  10399         from_end2 = 1;
  10400     } else {
  10401         end = SOC_LPM128_STATE_END1(u, lpm_state_ptr, next_pfx);
  10402         from_end2 = 0;
  10403     }
  10404     vent = SOC_LPM128_STATE_VENT(u, lpm_state_ptr, next_pfx);
  10405     end_prev = _lpm128_prev_index(u, next_pfx, lpm_state_ptr, end);
  10406 
  10407 #ifdef FB_LPM_TABLE_CACHED
  10408     if ((rv = soc_mem_cache_invalidate(u, mem,
  10409                                        MEM_BLOCK_ANY, end)) < 0) {
  10410         return rv;
  10411     }
  10412 #endif /* FB_LPM_TABLE_CACHED */
  10413     if ((rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, end, e)) < 0) {
  10414         return rv;
  10415     }
  10416     v0 = SOC_MEM_OPT_F32_VALID0_GET(u, mem, e);
  10417     v1 = SOC_MEM_OPT_F32_VALID1_GET(u, mem, e);
  10418     if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
  10419         half_entry = (v0 == 0 || v1 == 0) && (vent > 1);
  10420     }
  10421     if (half_entry) {
  10422         from = end_prev;
  10423     } else {
  10424         from = end;
  10425     }
  10426     to   = fent_start;
  10427     prev_to = to;
  10428 
  10429     start = SOC_LPM128_STATE_START1(u, lpm_state_ptr, next_pfx);
  10430 
  10431     /* Normally do erase, unless half_entry can overwrite */
  10432     erase = !half_entry || start != _lpm128_next_index(u, next_pfx, to);
  10433 
  10434     while (from >= start && to < start) {
  10435         SOC_IF_ERROR_RETURN
  10436             (_lpm128_fb_entry_shift(u, next_pfx, from, NULL, NULL, to, erase));
  10437 
  10438         if ((SOC_LPM128_PFX_IS_V4(u, next_pfx) && (to - prev_to > 1) &&
  10439             start2_index == -1)) {
  10440             start2_index = to;
  10441         }
  10442 
  10443         if (start2_index != -1) {
  10444             end2_index = to;
  10445         } else {
  10446             end1_index = to;
  10447         }
  10448 
  10449         prev_to = to;
  10450 
  10451         from = _lpm128_prev_index(u, next_pfx, lpm_state_ptr, from);
  10452         to   = _lpm128_next_index(u, next_pfx, to);
  10453     }
  10454 
  10455     if (half_entry) {
  10456         if (to < start) {
  10457             SOC_IF_ERROR_RETURN
  10458                 (_lpm128_fb_entry_shift(u, next_pfx, end, NULL, NULL, to, 1));
  10459             if ((SOC_LPM128_PFX_IS_V4(u, next_pfx) && (to - prev_to > 1) &&
  10460                 start2_index == -1)) {
  10461                 start2_index = to;
  10462             }
  10463             if (start2_index != -1) {
  10464                 end2_index = to;
  10465             } else {
  10466                 end1_index = to;
  10467             }
  10468         } else {
  10469             prev_from = from;
  10470             from = _lpm128_next_index(u, next_pfx, from);
  10471             SOC_IF_ERROR_RETURN
  10472                 (_lpm128_fb_entry_shift(u, next_pfx, end, NULL, NULL, from, 1));
  10473             if ((SOC_LPM128_PFX_IS_V4(u, next_pfx) && (from - prev_from > 1) &&
  10474                 start2_index == -1)) {
  10475                 start2_index = from;
  10476             }
  10477         }
  10478     }
  10479 
  10480     if (to < SOC_LPM128_STATE_START1(u, lpm_state_ptr, next_pfx)) {
  10481         SOC_LPM128_STATE_END1(u, lpm_state_ptr, next_pfx) = end1_index;
  10482         SOC_LPM128_STATE_START2(u, lpm_state_ptr, next_pfx) = start2_index;
  10483         SOC_LPM128_STATE_END2(u, lpm_state_ptr, next_pfx) = end2_index;
  10484     } else {
  10485         if (from_end2) {
  10486             if (from > SOC_LPM128_STATE_END1(u, lpm_state_ptr, next_pfx)) {
  10487                 SOC_LPM128_STATE_END2(u, lpm_state_ptr, next_pfx) = from;
  10488             } else {
  10489                 SOC_LPM128_STATE_END1(u, lpm_state_ptr, next_pfx) = from;
  10490                 SOC_LPM128_STATE_START2(u, lpm_state_ptr, next_pfx) = -1;
  10491                 SOC_LPM128_STATE_END2(u, lpm_state_ptr, next_pfx) = -1;
  10492             }
  10493         } else {
  10494             if (start2_index != -1) {
  10495                 SOC_LPM128_STATE_END1(u, lpm_state_ptr, next_pfx) = end1_index;
  10496                 SOC_LPM128_STATE_START2(u, lpm_state_ptr, next_pfx) = start2_index;
  10497                 SOC_LPM128_STATE_END2(u, lpm_state_ptr, next_pfx) = from;
  10498             } else {
  10499                 SOC_LPM128_STATE_END1(u, lpm_state_ptr, next_pfx) = from;
  10500             }
  10501         }
  10502     }
  10503     SOC_LPM128_STATE_START1(u, lpm_state_ptr, next_pfx) = fent_start;
  10504     if (_lpm128_pfx_conflicting(next_pfx, pfx)) {
  10505         if (range2_move) {
  10506             SOC_LPM128_STATE_FENT(u, lpm_state_ptr, other_pfx) += fent2;
  10507             SOC_LPM128_STATE_FENT(u, lpm_state_ptr, v4_pfx) += fent - fent2;
  10508         } else {
  10509             SOC_LPM128_STATE_FENT(u, lpm_state_ptr, bottom_pfx) += fent2;
  10510             SOC_LPM128_STATE_FENT(u, lpm_state_ptr, v4_pfx) += fent - fent2;
  10511         }
  10512     } else {
  10513         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, next_pfx) += fent;
  10514     }
  10515 
  10516     SOC_LPM128_STATE_FENT(u, lpm_state_ptr, pfx) = 0;
  10517     return SOC_E_NONE;
  10518 }
  10519 
  10520 
  10521 STATIC int
  10522 _lpm128_assign_free_fent_from_v6_to_v4(int u, int v6_pfx, int new_v4_pfx,
  10523                                        soc_lpm128_state_p lpm_state_ptr)
  10524 {
  10525     int v6_fent = 0;
  10526     int bottom_pfx = -1;
  10527     int other_start = -1;
  10528     int fent2 = 0;
  10529     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
  10530     int v4_pfx;
  10531     int fent_start;
  10532     int other_start_v4;
  10533     int other_pfx;
  10534     int range2_move;
  10535 
  10536     v4_pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, new_v4_pfx);
  10537     assert (_lpm128_pfx_conflicting(new_v4_pfx, v6_pfx));
  10538     assert (v4_pfx != -1);
  10539 
  10540     v6_fent    = SOC_LPM128_STATE_FENT(u, lpm_state_ptr, v6_pfx);
  10541     fent_start = SOC_LPM128_STATE_END1(u, lpm_state_ptr, v6_pfx);
  10542     fent_start = _lpm128_next_index(u, v6_pfx, fent_start);
  10543 
  10544     other_start_v4 = SOC_LPM128_STATE_START1(u, lpm_state_ptr, v4_pfx) +
  10545                      tcam_depth;
  10546     other_pfx    = v4_pfx;
  10547     bottom_pfx   = v4_pfx;
  10548     while (other_pfx != -1) {
  10549         if (SOC_LPM128_STATE_START1(u, lpm_state_ptr, other_pfx) >=
  10550             other_start_v4 ||
  10551             SOC_LPM128_STATE_START2(u, lpm_state_ptr, other_pfx) >=
  10552             other_start_v4) {
  10553             break;
  10554         }
  10555         bottom_pfx = other_pfx;
  10556         other_pfx  = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, other_pfx);
  10557     }
  10558 
  10559     range2_move = other_pfx != -1 &&
  10560                   SOC_LPM128_STATE_END2(u, lpm_state_ptr, other_pfx) != -1;
  10561 
  10562     if (LPM128_TCAM_NUM(u, fent_start) ==
  10563         LPM128_TCAM_NUM(u, SOC_LPM128_STATE_START1(u, lpm_state_ptr, v4_pfx))) {
  10564         fent2 = v6_fent >> 1;
  10565         other_start = fent_start + tcam_depth;
  10566     } else {
  10567         fent2 = ((v6_fent >> 1) + fent_start) % tcam_depth;
  10568         other_start = SOC_LPM128_STATE_START2(u, lpm_state_ptr, other_pfx) /
  10569                       tcam_depth * tcam_depth;
  10570     }
  10571 
  10572     if (range2_move) {
  10573         /* move other_pfx to make contiguous */
  10574         SOC_IF_ERROR_RETURN(
  10575             _lpm128_move_v4_entry_down_for_v6(u, fent2,
  10576                 other_start, other_pfx, lpm_state_ptr));
  10577     }
  10578 
  10579     if (range2_move) {
  10580         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, new_v4_pfx) += v6_fent - fent2;
  10581         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, other_pfx)  += fent2;
  10582     } else {
  10583         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, new_v4_pfx) += v6_fent - fent2;
  10584         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, bottom_pfx) += fent2;
  10585     }
  10586 
  10587     return SOC_E_NONE;
  10588 }
  10589 
  10590 STATIC int
  10591 _lpm128_free_slot_move_down(int u, int pfx, int free_pfx,
  10592                             soc_lpm128_state_p lpm_state_ptr)
  10593 {
  10594     int next_pfx = -1;
  10595     int fent_incr = 0;
  10596     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
  10597     int other_start_v4;
  10598     int other_start;
  10599     int v4_start;
  10600     int other_pfx;
  10601     int bottom_pfx;
  10602     int range2_move;
  10603     int dest_pfx = -1;
  10604 
  10605     while (free_pfx > pfx) {
  10606         /* copy start of prev_pfx to start - 1 */
  10607         next_pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, free_pfx);
  10608         SOC_IF_ERROR_RETURN(_lpm128_fb_shift_pfx_down(u, lpm_state_ptr,
  10609                                                       next_pfx));
  10610         if (SOC_LPM128_PFX_IS_V6(u, next_pfx)) {
  10611             fent_incr = 2; /* V6 to V6 */
  10612         } else {
  10613             fent_incr = 1; /* V4 to V6, V4 to V4 */
  10614         }
  10615 
  10616         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, free_pfx) -= fent_incr;
  10617         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, next_pfx) += fent_incr;
  10618 
  10619         if (SOC_LPM128_STATE_FENT(u, lpm_state_ptr, free_pfx) &&
  10620             _lpm128_pfx_conflicting(next_pfx, free_pfx)) {
  10621             /* V4 to V6 case
  10622              * next_pfx is v4 and got a free index for V6.
  10623              * Since each V6 uses 2 slots, give away the other slot
  10624              *
  10625              * starting from search_index, till start_index search to get the
  10626              * dest_pfx. Following cases are possible
  10627              * 1. if the dest_pfx has start2 then other_index should be equal
  10628              *    to start2 - 1. then simply copy end2 to start2 -1 and
  10629              *    decrement start2 and end2 , increase fent for dest_pfx
  10630              * 2. if start2 for dest_pfx is -1. Then simply increase fent
  10631                   for dest pfx
  10632              *  |  v6       |  v6    |
  10633              *  |  v4 START |  v6    |  Occupy empty v6 to become a v4 entry
  10634              *  |  v4       |  v4    |
  10635              */
  10636             int v4_pfx = next_pfx;
  10637             int v6_pfx = free_pfx;
  10638 
  10639             assert(SOC_LPM128_PFX_IS_V4(u, pfx));
  10640             v4_start = SOC_LPM128_STATE_START1(u, lpm_state_ptr, v4_pfx);
  10641             other_start = v4_start + tcam_depth;
  10642             other_start_v4 = other_start + 1;
  10643             if (LPM128_IN_EVEN_TCAM_FIRST(u, other_start_v4)) {
  10644                 /* This is a corner case where v4_start is the last index in
  10645                  * odd tcam, and other_start_v4 becomes the first in even tcam
  10646                  * (so is the START2 of v4_pfx). In this case, simply do
  10647                  * nothing, and things will work just fine.
  10648                  */
  10649             }
  10650 
  10651             other_pfx  = v4_pfx;
  10652             bottom_pfx = v4_pfx;
  10653             while (other_pfx != -1) {
  10654                 if (SOC_LPM128_STATE_START1(u, lpm_state_ptr, other_pfx) >=
  10655                     other_start_v4 ||
  10656                     SOC_LPM128_STATE_START2(u, lpm_state_ptr, other_pfx) >=
  10657                     other_start_v4) {
  10658                     break;
  10659                 }
  10660                 bottom_pfx = other_pfx;
  10661                 other_pfx  = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, other_pfx);
  10662             }
  10663 
  10664             range2_move = other_pfx != -1 &&
  10665                           SOC_LPM128_STATE_END2(u, lpm_state_ptr, other_pfx) != -1;
  10666 
  10667             if (range2_move) {
  10668                 assert (other_start_v4 == other_start + 1);
  10669                 assert (other_start_v4 ==
  10670                         SOC_LPM128_STATE_START2(u, lpm_state_ptr, other_pfx));
  10671                 SOC_IF_ERROR_RETURN(_lpm128_move_v4_entry_down_for_v6(u, 1,
  10672                     other_start, other_pfx, lpm_state_ptr));
  10673             }
  10674             if (range2_move) {
  10675                 SOC_LPM128_STATE_FENT(u, lpm_state_ptr, other_pfx) += 1;
  10676                 SOC_LPM128_STATE_FENT(u, lpm_state_ptr, v6_pfx) -= 1;
  10677                 dest_pfx = other_pfx;
  10678             } else {
  10679                 SOC_LPM128_STATE_FENT(u, lpm_state_ptr, bottom_pfx) += 1;
  10680                 SOC_LPM128_STATE_FENT(u, lpm_state_ptr, v6_pfx) -= 1;
  10681                 SOC_LPM128_INDEX_TO_PFX_GROUP(u, other_start) = -1;
  10682                 dest_pfx = bottom_pfx;
  10683             }
  10684         }
  10685 
  10686         if (dest_pfx != -1 && dest_pfx >= pfx) {
  10687             free_pfx = dest_pfx;
  10688             dest_pfx = -1;
  10689         } else {
  10690             free_pfx = next_pfx;
  10691         }
  10692     }
  10693     return SOC_E_NONE;
  10694 }
  10695 
  10696 STATIC int
  10697 _lpm128_free_slot_move_up(int u, int pfx, int free_pfx,
  10698                           soc_lpm128_state_p lpm_state_ptr)
  10699 {
  10700     int prev_pfx = -1;
  10701     int prev_last;
  10702     int fent_incr = 0;
  10703 
  10704     while (free_pfx < pfx) {
  10705         SOC_IF_ERROR_RETURN(_lpm128_fb_shift_pfx_up(u, lpm_state_ptr,
  10706                                                     free_pfx));
  10707         prev_pfx = SOC_LPM128_STATE_PREV(u, lpm_state_ptr, free_pfx);
  10708 
  10709         if (SOC_LPM128_PFX_IS_V4(u, free_pfx)) {
  10710             fent_incr = 1; /* V4 to V4, V6 to V4 case*/
  10711         } else {
  10712             fent_incr = 2; /* V6 to V6 case*/
  10713         }
  10714 
  10715         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, free_pfx) -= fent_incr;
  10716         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, prev_pfx) += fent_incr;
  10717 
  10718         if (_lpm128_pfx_conflicting(free_pfx, prev_pfx)) {
  10719             /*
  10720              * prev_pfx is V6 and free_pfx is V4.
  10721              * At this stage there could be 1 entry free in V4. But we need
  10722              * 2 entries to move V6 at index n and n + tcam_depth.
  10723              * n is already free. so now find the prefix of n + tcam_depth and move
  10724              * entries of that prefix to find free space
  10725              *  |  v6 END|  v6    |
  10726              *  |  v6    |  v4    |  move v4 away to become a v6 free entry.
  10727              *  |  v4    |  v4    |
  10728              */
  10729             assert(SOC_LPM128_PFX_IS_V6(u, pfx));
  10730             prev_last = _lpm128_next_index(u, prev_pfx,
  10731                 SOC_LPM128_STATE_END1(u, lpm_state_ptr, prev_pfx));
  10732 
  10733             SOC_IF_ERROR_RETURN(_lpm128_move_v4_entry_away_for_v6(u, prev_pfx,
  10734                                         prev_last, lpm_state_ptr));
  10735         }
  10736         free_pfx = prev_pfx;
  10737     }
  10738     return SOC_E_NONE;
  10739 }
  10740 
  10741 
  10742 STATIC INLINE int
  10743 _lpm128_pfx_group_create(int u, int pfx, soc_lpm128_state_p lpm_state_ptr)
  10744 {
  10745     int start_index = -1;
  10746     int next_pfx = -1;
  10747     int prev_pfx = -1;
  10748 
  10749     /* Find prev and next pfx */
  10750     prev_pfx = MAX_PFX128_INDEX;
  10751     while (SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, prev_pfx) > pfx) {
  10752         prev_pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, prev_pfx);
  10753     }
  10754     next_pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, prev_pfx);
  10755 
  10756     /* Setup the entry in the linked list */
  10757     if (next_pfx != -1) {
  10758         SOC_LPM128_STATE_PREV(u, lpm_state_ptr, next_pfx) = pfx;
  10759     }
  10760     SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, pfx) = next_pfx;
  10761     SOC_LPM128_STATE_PREV(u, lpm_state_ptr, pfx) = prev_pfx;
  10762     SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, prev_pfx) = pfx;
  10763 
  10764     if (next_pfx != -1 && _lpm128_pfx_conflicting(pfx, prev_pfx)) {
  10765         if (SOC_LPM128_STATE_FENT(u, lpm_state_ptr, prev_pfx)) {
  10766             SOC_IF_ERROR_RETURN
  10767             (_lpm128_assign_free_fent_from_v6_to_v4(u, prev_pfx, pfx,
  10768                                                     lpm_state_ptr));
  10769         }
  10770     } else {
  10771         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, pfx) =
  10772             SOC_LPM128_STATE_FENT(u, lpm_state_ptr, prev_pfx);
  10773     }
  10774     SOC_LPM128_STATE_FENT(u, lpm_state_ptr, prev_pfx) = 0;
  10775 
  10776     if (SOC_LPM128_STATE_START2(u, lpm_state_ptr, prev_pfx) != -1) {
  10777         start_index = SOC_LPM128_STATE_END2(u, lpm_state_ptr, prev_pfx);
  10778     } else {
  10779         start_index = SOC_LPM128_STATE_END1(u, lpm_state_ptr, prev_pfx);
  10780     }
  10781 
  10782     start_index = _lpm128_next_index(u, prev_pfx, start_index);
  10783     SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx) = start_index;
  10784     SOC_LPM128_STATE_START2(u, lpm_state_ptr, pfx) = -1;
  10785     SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) = start_index - 1;
  10786     SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) = -1;
  10787     SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) = 0;
  10788 
  10789     return SOC_E_NONE;
  10790 }
  10791 
  10792 
  10793 STATIC int
  10794 _lpm128_pfx_group_destroy(int u, int pfx, soc_lpm128_state_p lpm_state_ptr )
  10795 {
  10796 
  10797     int         prev_pfx;
  10798     int         next_pfx;
  10799 
  10800     if (SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) != 0) {
  10801         return SOC_E_NONE;
  10802     }
  10803 
  10804     /* remove from the list */
  10805     prev_pfx = SOC_LPM128_STATE_PREV(u, lpm_state_ptr, pfx);
  10806     /* prev_pfx Always present */
  10807     assert(prev_pfx != -1);
  10808     next_pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, pfx);
  10809 
  10810     if (next_pfx != -1 && (_lpm128_pfx_conflicting(pfx, prev_pfx) ||
  10811                            prev_pfx == MAX_PFX128_INDEX)) {
  10812         SOC_IF_ERROR_RETURN
  10813             (_lpm128_move_next_pfx_down_during_delete(u, pfx, lpm_state_ptr));
  10814     } else {
  10815         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, prev_pfx) +=
  10816             SOC_LPM128_STATE_FENT(u, lpm_state_ptr, pfx);
  10817     }
  10818 
  10819     if (next_pfx != -1) {
  10820         SOC_LPM128_STATE_PREV(u, lpm_state_ptr, next_pfx) = prev_pfx;
  10821     }
  10822     SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, prev_pfx) = next_pfx;
  10823     SOC_LPM128_STATE_FENT(u, lpm_state_ptr, pfx) = 0;
  10824     SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, pfx) = -1;
  10825     SOC_LPM128_STATE_PREV(u, lpm_state_ptr, pfx) = -1;
  10826     SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx) = -1;
  10827     SOC_LPM128_STATE_START2(u, lpm_state_ptr, pfx) = -1;
  10828     SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) = -1;
  10829     SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) = -1;
  10830 
  10831     return SOC_E_NONE;
  10832 }
  10833 
  10834 
  10835 
  10836 STATIC int
  10837 _lpm128_v4_half_entry_available(int u, soc_lpm128_state_p lpm_state_ptr,
  10838                                 int pfx, void *e, int *free_slot)
  10839 {
  10840     int from_ent;
  10841     uint32 v0, v1;
  10842     int rv;
  10843     soc_mem_t mem = L3_DEFIPm;
  10844 
  10845     if (SOC_LPM128_STATE_HFENT(u, lpm_state_ptr, pfx) == 0) {
  10846        return SOC_E_FULL;
  10847     }
  10848 #if defined(BCM_TOMAHAWK3_SUPPORT)
  10849     if (SOC_IS_TOMAHAWK3(u)) {
  10850         mem = L3_DEFIP_LEVEL1m;
  10851     }
  10852 #endif
  10853 
  10854     if (SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) != -1) {
  10855         from_ent = SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx);
  10856     } else {
  10857         from_ent = SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx);
  10858     }
  10859 
  10860     if (from_ent == -1) {
  10861         return SOC_E_INTERNAL;
  10862     }
  10863 
  10864 #ifdef FB_LPM_TABLE_CACHED
  10865     if ((rv = soc_mem_cache_invalidate(u, mem,
  10866                                        MEM_BLOCK_ANY, from_ent)) < 0) {
  10867         return rv;
  10868     }
  10869 #endif /* FB_LPM_TABLE_CACHED */
  10870     if ((rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, e)) < 0) {
  10871         return rv;
  10872     }
  10873     v0 = SOC_MEM_OPT_F32_VALID0_GET(u, mem, e);
  10874     v1 = SOC_MEM_OPT_F32_VALID1_GET(u, mem, e);
  10875 
  10876     if ((v0 == 0) || (v1 == 0)) {
  10877         *free_slot = (from_ent << 1) + ((v1 == 0) ? 1 : 0);
  10878         return(SOC_E_NONE);
  10879     }
  10880     sal_memcpy(e, soc_mem_entry_null(u, mem),
  10881                soc_mem_entry_words(u, mem) * 4);
  10882     return SOC_E_FULL; /* To indicate that both the entries are in use*/
  10883 }
  10884 
  10885 /*
  10886  *      Create a slot for the new entry rippling the entries if required
  10887  */
  10888 STATIC int
  10889 _lpm128_v4_free_slot_create(int u, int pfx, void *e, int *free_slot)
  10890 {
  10891     int         prev_pfx;
  10892     int         next_pfx;
  10893     int         free_pfx;
  10894     int         rv;
  10895     int         end;
  10896     int         end_next = -1;
  10897     soc_lpm128_state_p lpm_state_ptr = SOC_LPM128_STATE(u);
  10898 
  10899 
  10900     if (SOC_LPM128_UNRESERVED_STATE(u)) {
  10901         lpm_state_ptr = SOC_LPM128_UNRESERVED_STATE(u);
  10902     }
  10903 
  10904     if (SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) == 0) {
  10905         rv = _lpm128_pfx_group_create(u, pfx, lpm_state_ptr);
  10906         if (SOC_FAILURE(rv)) {
  10907             goto cleanup;
  10908         }
  10909     } else {
  10910         /* Check if half of the entry is free. if yes add to it */
  10911         rv = _lpm128_v4_half_entry_available(u, lpm_state_ptr,
  10912                                              pfx, e, free_slot);
  10913         if (SOC_SUCCESS(rv)) {
  10914             SOC_LPM128_STATE_HFENT(u, lpm_state_ptr, pfx) = 0;
  10915             return SOC_E_NONE;
  10916         } else if (rv != SOC_E_FULL) {
  10917             return rv;
  10918         }
  10919     }
  10920 
  10921     free_pfx = pfx;
  10922     while (SOC_LPM128_STATE_FENT(u, lpm_state_ptr, free_pfx) == 0) {
  10923         free_pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, free_pfx);
  10924         if (free_pfx == -1) {
  10925             /* No free entries on right side try the other side */
  10926             free_pfx = pfx;
  10927             break;
  10928         }
  10929     }
  10930 
  10931     while (SOC_LPM128_STATE_FENT(u, lpm_state_ptr, free_pfx) == 0) {
  10932         free_pfx = SOC_LPM128_STATE_PREV(u, lpm_state_ptr, free_pfx);
  10933         if (free_pfx == -1) {
  10934             /* No free entries on left side as well */
  10935             rv = SOC_E_FULL;
  10936             goto cleanup;
  10937         }
  10938     }
  10939 
  10940 
  10941     /*
  10942      * Ripple entries to create free space for v4 pfx.
  10943      */
  10944     if (free_pfx < pfx) {
  10945         rv = _lpm128_free_slot_move_up(u, pfx, free_pfx, lpm_state_ptr);
  10946         if (SOC_FAILURE(rv)) {
  10947             goto cleanup;
  10948         }
  10949     }
  10950 
  10951 
  10952     /*
  10953      * Ripple entries to create free space for v4 pfx.
  10954      */
  10955     if (free_pfx > pfx) {
  10956         rv = _lpm128_free_slot_move_down(u, pfx, free_pfx, lpm_state_ptr);
  10957         if (SOC_FAILURE(rv)) {
  10958             goto cleanup;
  10959         }
  10960     }
  10961 
  10962     if (SOC_LPM128_STATE_START2(u, lpm_state_ptr, pfx) == -1) {
  10963         end = SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx);
  10964         end_next = _lpm128_next_index(u, pfx, end);
  10965         if (end_next - end > 1) {
  10966             SOC_LPM128_STATE_START2(u, lpm_state_ptr, pfx) = end_next;
  10967             SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) = end_next;
  10968         } else {
  10969             SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) = end_next;
  10970         }
  10971     } else {
  10972         SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) += 1;
  10973     }
  10974 
  10975     SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) += 1;
  10976     SOC_LPM128_STATE_FENT(u, lpm_state_ptr, pfx) -= 1;
  10977     SOC_LPM128_STATE_HFENT(u, lpm_state_ptr, pfx) = 
  10978         soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity) ? 0 : 1;
  10979 
  10980     if (SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) != -1) {
  10981         *free_slot = SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) << 1;
  10982     } else {
  10983         *free_slot = SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) << 1;
  10984     }
  10985 #ifdef BCM_TOMAHAWK2_SUPPORT
  10986     if (soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
  10987         *free_slot += 1;
  10988     }
  10989 #endif
  10990     return(SOC_E_NONE);
  10991 
  10992 cleanup:
  10993     if (SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) == 0) {
  10994         /* failed to allocate entries for a newly allocated prefix.*/
  10995         prev_pfx = SOC_LPM128_STATE_PREV(u, lpm_state_ptr, pfx);
  10996         next_pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, pfx);
  10997         if (-1 != prev_pfx) {
  10998             SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, prev_pfx) =
  10999                 next_pfx;
  11000         }
  11001         if (-1 != next_pfx) {
  11002             SOC_LPM128_STATE_PREV(u, lpm_state_ptr, next_pfx) =
  11003             prev_pfx;
  11004         }
  11005     }
  11006     return rv;
  11007 }
  11008 
  11009 
  11010 
  11011 /*
  11012  *      Create a slot for the new entry rippling the entries if required
  11013  */
  11014 STATIC int
  11015 _lpm128_free_slot_create(int u, int pfx, void *e, int *free_slot)
  11016 {
  11017     int         prev_pfx;
  11018     int         next_pfx;
  11019     int         free_pfx, free_pfx2;
  11020     int         old_end;
  11021     int         new_end;
  11022     int         rv;
  11023     soc_lpm128_state_p lpm_state_ptr = SOC_LPM128_STATE(u);
  11024 
  11025     if (SOC_LPM128_PFX_IS_V4(u, pfx)) {
  11026         return _lpm128_v4_free_slot_create(u, pfx, e, free_slot);
  11027     }
  11028 
  11029     if (!SOC_LPM128_PFX_IS_V6_128(u, pfx)  && SOC_LPM128_UNRESERVED_STATE(u)) {
  11030         lpm_state_ptr = SOC_LPM128_UNRESERVED_STATE(u);
  11031     }
  11032 
  11033     if (SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) == 0) {
  11034         rv = _lpm128_pfx_group_create(u, pfx, lpm_state_ptr);
  11035         if (SOC_FAILURE(rv)) {
  11036             goto cleanup;
  11037         }
  11038     }
  11039 
  11040     free_pfx = pfx;
  11041 
  11042     while (SOC_LPM128_STATE_FENT(u, lpm_state_ptr, free_pfx) == 0) {
  11043         free_pfx = SOC_LPM128_STATE_PREV(u, lpm_state_ptr, free_pfx);
  11044         if (free_pfx == -1) {
  11045             /* No free entries on left side */
  11046             free_pfx = pfx;
  11047             break;
  11048         }
  11049     }
  11050 
  11051     while (SOC_LPM128_STATE_FENT(u, lpm_state_ptr, free_pfx) == 0) {
  11052         free_pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, free_pfx);
  11053         if (free_pfx == -1) {
  11054             /* No free entries on right side as well */
  11055             rv = SOC_E_FULL;
  11056             goto cleanup;
  11057         }
  11058     }
  11059 
  11060     /* For ipv6, need 2 free entries */
  11061     if (SOC_LPM128_STATE_FENT(u, lpm_state_ptr, free_pfx) == 1) {
  11062         free_pfx2 = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, free_pfx);
  11063         while (SOC_LPM128_STATE_FENT(u, lpm_state_ptr, free_pfx2) == 0) {
  11064             free_pfx2 = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, free_pfx2);
  11065             if (free_pfx2 == -1) {
  11066                 /* No more free entries */
  11067                 rv = SOC_E_FULL;
  11068                 goto cleanup;
  11069             }
  11070         }
  11071     }
  11072 
  11073     /*
  11074      * Ripple entries to create free space for v6 pfx.
  11075      */
  11076     if (free_pfx > pfx) {
  11077         rv = _lpm128_free_slot_move_down(u, pfx, free_pfx, lpm_state_ptr);
  11078         if (SOC_FAILURE(rv)) {
  11079             goto cleanup;
  11080         }
  11081     }
  11082 
  11083     if (free_pfx < pfx) {
  11084         rv = _lpm128_free_slot_move_up(u, pfx, free_pfx, lpm_state_ptr);
  11085         if (SOC_FAILURE(rv)) {
  11086             goto cleanup;
  11087         }
  11088     }
  11089 
  11090     old_end = SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx);
  11091     new_end = _lpm128_next_index(u, pfx, old_end);
  11092 
  11093     assert ((SOC_LPM128_STATE_FENT(u, lpm_state_ptr, pfx) >= 2) &&
  11094             (SOC_LPM128_STATE_FENT(u, lpm_state_ptr, pfx) & 1) == 0);
  11095 
  11096     SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) = new_end;
  11097     SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) += 1;
  11098     SOC_LPM128_STATE_FENT(u, lpm_state_ptr, pfx) -= 2;
  11099 
  11100     *free_slot = SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx);
  11101     return(SOC_E_NONE);
  11102 
  11103 cleanup:
  11104     if (SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) == 0) {
  11105         /* failed to allocate entries for a newly allocated prefix.*/
  11106         prev_pfx = SOC_LPM128_STATE_PREV(u, lpm_state_ptr, pfx);
  11107         next_pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, pfx);
  11108         if (-1 != prev_pfx) {
  11109             SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, prev_pfx) =
  11110                 next_pfx;
  11111         }
  11112         if (-1 != next_pfx) {
  11113             SOC_LPM128_STATE_PREV(u, lpm_state_ptr, next_pfx) =
  11114             prev_pfx;
  11115         }
  11116     }
  11117     return rv;
  11118 }
  11119 
  11120 
  11121 STATIC int
  11122 _lpm128_v4_free_slot_delete(int u, int pfx, soc_lpm128_state_p lpm_state_ptr,
  11123                             void *key_data, void *e, int slot, int *is_deleted)
  11124 {
  11125     int         end;
  11126     int         end_prev;
  11127     int         end_cross, end_cross_prev = 0;
  11128     int         to_ent;
  11129     uint32      ef[SOC_MAX_MEM_FIELD_WORDS]={0};
  11130     void        *et;
  11131     int         rv;
  11132     int         from_end2;
  11133     uint32      rvt_index0 = 0, rvt_index1 = 0;
  11134     int         temp_index = -1;
  11135     int         temp_hw_index = -1;
  11136     int         half_entry_free = 0;
  11137     soc_mem_t   mem = L3_DEFIPm;
  11138 #if defined(BCM_TOMAHAWK3_SUPPORT)
  11139     if (SOC_IS_TOMAHAWK3(u)) {
  11140         mem = L3_DEFIP_LEVEL1m;
  11141     }
  11142 #endif
  11143 
  11144   
  11145     *is_deleted = 0; 
  11146     to_ent = slot;
  11147     to_ent >>= 1;
  11148 
  11149     if (SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) != -1) {
  11150         end = SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx);
  11151         from_end2 = 1;
  11152     } else {
  11153         end = SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx);
  11154         from_end2 = 0;
  11155     }
  11156 
  11157     half_entry_free = SOC_LPM128_STATE_HFENT(u, lpm_state_ptr, pfx);
  11158 
  11159     /*
  11160      * Allocate Reserved entry.
  11161      */ 
  11162     if (soc_feature(u, soc_feature_lpm_atomic_write)) {
  11163         if (((to_ent == end) && (half_entry_free == 0)) ||
  11164              (to_ent != end)) {
  11165             SOC_LPM128_STATE_HFENT(u, lpm_state_ptr, pfx) = 0;
  11166 
  11167             rv = _lpm128_free_slot_create(u, pfx, ef, &temp_index);
  11168             if (SOC_FAILURE(rv)) {
  11169                return rv;
  11170             }
  11171 
  11172             /* Increment Half entry count, since temp slot creates it. */
  11173             SOC_LPM_COUNT_INC(SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u));
  11174 
  11175             temp_hw_index = temp_index >> 1;
  11176 
  11177             rv = _soc_fb_lpm128_match(u, key_data, NULL, NULL, NULL,
  11178                                       &slot, &pfx, NULL);
  11179             if (SOC_FAILURE(rv)) {
  11180                return rv;
  11181             }
  11182 
  11183             to_ent = slot;
  11184             to_ent >>= 1;
  11185 
  11186             if (SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) != -1) {
  11187                end = SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx);
  11188                from_end2 = 1;
  11189             } else {
  11190                end = SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx);
  11191                from_end2 = 0;
  11192             }
  11193         } 
  11194     }
  11195 
  11196     /* Delete the HASH before updating the HW */
  11197     if (key_data != NULL) {
  11198        LPM128_HASH_DELETE(u, key_data, NULL, slot);
  11199     }
  11200 
  11201     end_prev = _lpm128_prev_index(u, pfx, lpm_state_ptr, end);
  11202     end_cross = (end - end_prev) > 1;
  11203 
  11204     if (temp_index != -1) {
  11205        end = end_prev;
  11206        end_prev = _lpm128_prev_index(u, pfx, lpm_state_ptr, end);
  11207        end_cross_prev = (end - end_prev) > 1;
  11208     }
  11209 
  11210 #ifdef FB_LPM_TABLE_CACHED
  11211     if ((rv = soc_mem_cache_invalidate(u, mem,
  11212                                        MEM_BLOCK_ANY, end)) < 0) {
  11213         return rv;
  11214     }
  11215 #endif /* FB_LPM_TABLE_CACHED */
  11216     if ((rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, end, ef)) < 0) {
  11217         return rv;
  11218     }
  11219     et =  (to_ent == end) ? ef : e;
  11220     if (SOC_MEM_OPT_F32_VALID1_GET(u, mem, ef)) {
  11221         if (slot & 1) {
  11222             (void) soc_fb_lpm_ip4entry1_to_1(u, ef, et, PRESERVE_HIT);
  11223         } else {
  11224             (void) soc_fb_lpm_ip4entry1_to_0(u, ef, et, PRESERVE_HIT);
  11225         }
  11226         SOC_MEM_OPT_F32_VALID1_SET(u, mem, ef, 0);
  11227 #ifdef BCM_TOMAHAWK2_SUPPORT        
  11228         if (soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
  11229             /* Reset the end entry */
  11230             sal_memcpy(ef, soc_mem_entry_null(u, mem),
  11231                        soc_mem_entry_words(u,mem) * 4);
  11232             /* Remaining half entry got deleted. Decrement half entry count.*/
  11233             SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) -= 1;
  11234             SOC_LPM128_STATE_FENT(u, lpm_state_ptr, pfx) += 1;
  11235             SOC_LPM128_INDEX_TO_PFX_GROUP(u, end) = -1;
  11236             *is_deleted = 1;
  11237             if (from_end2) {
  11238                 if (end_cross) {
  11239                     SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx)   = -1;
  11240                     SOC_LPM128_STATE_START2(u, lpm_state_ptr, pfx) = -1;
  11241                     SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) = end_prev;
  11242                 } else {
  11243                     SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) = end_prev;
  11244                 }
  11245             } else {
  11246                 SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) = end_prev;
  11247             }
  11248         } else 
  11249 #endif
  11250         {
  11251             /* first half of full entry is deleted, generating half entry.*/
  11252             SOC_LPM_COUNT_INC(SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u));
  11253         }
  11254     } else {
  11255         if (slot & 1) {
  11256             (void) soc_fb_lpm_ip4entry0_to_1(u, ef, et, PRESERVE_HIT);
  11257         } else {
  11258             (void) soc_fb_lpm_ip4entry0_to_0(u, ef, et, PRESERVE_HIT);
  11259         }
  11260 
  11261         /* Reset the end entry */
  11262         sal_memcpy(ef, soc_mem_entry_null(u, mem),
  11263                    soc_mem_entry_words(u,mem) * 4);
  11264         /* Remaining half entry got deleted. Decrement half entry count.*/
  11265         SOC_LPM_COUNT_DEC(SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u));
  11266         SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) -= 1;
  11267         SOC_LPM128_STATE_FENT(u, lpm_state_ptr, pfx) += 1;
  11268         SOC_LPM128_INDEX_TO_PFX_GROUP(u, end) = -1;
  11269         *is_deleted = 1;
  11270         if (from_end2) {
  11271             if (end_cross) {
  11272                 SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx)   = -1;
  11273                 SOC_LPM128_STATE_START2(u, lpm_state_ptr, pfx) = -1;
  11274                 SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) = end_prev;
  11275             } else {
  11276                 SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) = end_prev;
  11277             }
  11278         } else {
  11279             SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) = end_prev;
  11280         }
  11281     }
  11282             
  11283     if (to_ent != end) {
  11284         if (temp_index != -1) {
  11285            rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, temp_hw_index, et);
  11286            if (SOC_FAILURE(rv)) {
  11287               return rv;
  11288            }
  11289         }
  11290 
  11291         LPM128_HASH_INSERT(u, et, NULL, to_ent, &rvt_index0, &rvt_index1);
  11292         if ((rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, to_ent, et)) < 0) {
  11293             LPM128_HASH_REVERT(u, et, NULL, to_ent, rvt_index0, rvt_index1);
  11294             return rv;
  11295         }
  11296 
  11297         rv = _lpm128_fb_urpf_entry_replicate(u, to_ent, temp_hw_index, et, NULL);
  11298         if (SOC_FAILURE(rv)) {
  11299             LPM128_HASH_REVERT(u, et, NULL, to_ent, rvt_index0, rvt_index1);
  11300             return rv;
  11301         }
  11302     }
  11303 
  11304     if ((temp_index != -1) && (*is_deleted == 0)) {
  11305        rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, temp_hw_index, ef);
  11306        if (SOC_FAILURE(rv)) {
  11307           return rv;
  11308        }
  11309     }
  11310 
  11311     LPM128_HASH_INSERT(u, ef, NULL, end, &rvt_index0, &rvt_index1);
  11312     if ((rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, end, ef)) < 0) {
  11313         LPM128_HASH_REVERT(u, ef, NULL, end, rvt_index0, rvt_index1);
  11314         return rv;
  11315     }
  11316 
  11317     rv = _lpm128_fb_urpf_entry_replicate(u, end, temp_hw_index, ef, NULL);
  11318     if (SOC_FAILURE(rv)) {
  11319         LPM128_HASH_REVERT(u, ef, NULL, end, rvt_index0, rvt_index1);
  11320         return rv;
  11321     }
  11322 
  11323     /* Remove reserved entry */
  11324     if (temp_index != -1) {
  11325        /* Delete temp slot */
  11326        SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) -= 1;
  11327        SOC_LPM128_STATE_FENT(u, lpm_state_ptr, pfx) += 1;
  11328 
  11329        if (*is_deleted == 0) {
  11330           if (from_end2) {
  11331               if (end_cross && (end_cross_prev == 0)) {
  11332                  SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx)   = -1;
  11333                  SOC_LPM128_STATE_START2(u, lpm_state_ptr, pfx) = -1;
  11334                  SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) = end;
  11335               } else {
  11336                  SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) = end;
  11337               }
  11338           } else {
  11339              SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) = end;
  11340           }
  11341        }
  11342             
  11343        /* Decrement Half entry count, since temp slot creates it. */
  11344        if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
  11345            SOC_LPM_COUNT_DEC(SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u));
  11346        }
  11347 
  11348        /* Clear reserved entry */ 
  11349        sal_memcpy(ef, soc_mem_entry_null(u, mem),
  11350                    soc_mem_entry_words(u,mem) * 4);
  11351        rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, temp_hw_index, ef);
  11352        SOC_IF_ERROR_RETURN(rv);
  11353     }
  11354 
  11355     if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
  11356         /* Update half free entry */
  11357         SOC_LPM128_STATE_HFENT(u, lpm_state_ptr, pfx) = (half_entry_free) ? 0 : 1;
  11358     }
  11359     if (SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) == 0) {
  11360         SOC_IF_ERROR_RETURN
  11361         (_lpm128_pfx_group_destroy(u, pfx, lpm_state_ptr));
  11362     }
  11363 
  11364     return(rv);
  11365 }
  11366 
  11367 
  11368 /*
  11369  *      Delete a slot and adjust entry pointers if required.
  11370  *      e - has the contents of entry at slot(useful for IPV4 only)
  11371  */
  11372 STATIC int
  11373 _lpm128_free_slot_delete(int u, int pfx, void *key_data,
  11374                          void *e, int slot, int *is_deleted)
  11375 {
  11376     int         from_ent;
  11377     int         to_ent;
  11378     uint32      ef[SOC_MAX_MEM_FIELD_WORDS];
  11379     uint32      efupr[SOC_MAX_MEM_FIELD_WORDS];
  11380     int         rv = SOC_E_NONE;
  11381     int fent_incr = 1;
  11382     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
  11383     int tcam_number = 0;
  11384     soc_lpm128_state_p lpm_state_ptr = SOC_LPM128_STATE(u);
  11385     uint32      rvt_index0 = 0, rvt_index1 = 0;
  11386     soc_mem_t mem = L3_DEFIPm;
  11387 #if defined(BCM_TOMAHAWK3_SUPPORT)
  11388     if (SOC_IS_TOMAHAWK3(u)) {
  11389         mem = L3_DEFIP_LEVEL1m;
  11390     }
  11391 #endif
  11392 
  11393     if (!SOC_LPM128_PFX_IS_V6_128(u, pfx)  && SOC_LPM128_UNRESERVED_STATE(u)) {
  11394        lpm_state_ptr = SOC_LPM128_UNRESERVED_STATE(u);
  11395     }
  11396 
  11397     if (SOC_LPM128_PFX_IS_V4(u, pfx)) {
  11398         return _lpm128_v4_free_slot_delete(u, pfx, lpm_state_ptr, key_data, e,
  11399                                            slot, is_deleted);
  11400     }
  11401 
  11402     fent_incr = 2;
  11403     from_ent  = SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx);
  11404     to_ent    = slot;
  11405     SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) -= 1;
  11406     SOC_LPM128_STATE_FENT(u, lpm_state_ptr, pfx) += fent_incr;
  11407     SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) -= 1;
  11408     tcam_number = SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) /
  11409                   tcam_depth;
  11410     if (tcam_number & 1) {
  11411         SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) -= tcam_depth;
  11412     }
  11413 
  11414     if (to_ent != from_ent) {
  11415         rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, ef);
  11416         SOC_IF_ERROR_RETURN(rv);
  11417         rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY,
  11418                                            from_ent + tcam_depth, efupr);
  11419         SOC_IF_ERROR_RETURN(rv);
  11420         LPM128_HASH_INSERT(u, ef, efupr, to_ent, &rvt_index0, &rvt_index1);
  11421 
  11422         rv = (WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, to_ent, ef));
  11423         if (rv >= 0) {
  11424             rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, to_ent + tcam_depth, efupr);
  11425         }
  11426         if (rv >= 0) {
  11427             rv = _lpm128_fb_urpf_entry_replicate(u, to_ent, -1, ef, efupr);
  11428         }
  11429         if (rv < 0) {
  11430             LPM128_HASH_REVERT(u, ef, efupr, to_ent, rvt_index0, rvt_index1);
  11431             return rv;
  11432         }
  11433     }
  11434 
  11435     sal_memcpy(ef, soc_mem_entry_null(u, mem),
  11436                soc_mem_entry_words(u,mem) * 4);
  11437     sal_memcpy(efupr, soc_mem_entry_null(u, mem),
  11438                soc_mem_entry_words(u,mem) * 4);
  11439     SOC_IF_ERROR_RETURN(WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, ef));
  11440     SOC_LPM128_INDEX_TO_PFX_GROUP(u, from_ent) = -1;
  11441     SOC_IF_ERROR_RETURN(WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent + tcam_depth,
  11442                                         efupr));
  11443     SOC_LPM128_INDEX_TO_PFX_GROUP(u, from_ent + tcam_depth) = -1;
  11444     SOC_IF_ERROR_RETURN(_lpm128_fb_urpf_entry_replicate(u, from_ent, -1, ef,
  11445                                                         efupr));
  11446     *is_deleted = 1;
  11447     if (SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) == 0) {
  11448         SOC_IF_ERROR_RETURN
  11449         (_lpm128_pfx_group_destroy(u, pfx, lpm_state_ptr));
  11450     }
  11451 
  11452     return(rv);
  11453 }
  11454 
  11455 
  11456 
  11457 /*
  11458  * Function:
  11459  *    _bcm_fb_route_scale_check
  11460  * Purpose:
  11461  *    Check Route scale in DEFIP tables.
  11462  * Parameters:
  11463  *    unit    - (IN) SOC unit number;
  11464  * Return:
  11465  *    TRUE - Scale Reached
  11466  *    False - Scale not reached
  11467  */
  11468 STATIC int
  11469 _bcm_fb_route_scale_check(int unit, int half_entry)
  11470 {
  11471     int rpf_scale = 1;
  11472     int total_routes_added = 0;
  11473     int v4_count = 0;
  11474     rpf_scale = (SOC_URPF_STATUS_GET(unit) ? 1: 2);
  11475     /* In case of Ranger2Plus, we have enabled more tcams
  11476      * but number of routes that should be added in those tcams
  11477      * are less. Moreover traditional LPM state can not
  11478      * scale to exact numbers which are needed for this device.
  11479      */
  11480     if (soc_feature(unit, soc_feature_defip_2_tcams_with_separate_rpf)) {
  11481         /*
  11482          * Check for total scale if that is reached.
  11483          * we are trying the exact scale that is mentioned
  11484          * in device sheet and not how much it takes in hardware.
  11485          */
  11486         v4_count = SOC_LPM128_STAT_V4_COUNT(unit) -
  11487                        SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(unit);
  11488         /*
  11489          * In case this prefix has half entry, then we can add one v4 route.
  11490          */
  11491         v4_count = v4_count - ((half_entry) ? 1 : 0) +
  11492                        (SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(unit) * 2);
  11493 
  11494         total_routes_added = v4_count +
  11495                              (SOC_LPM128_STAT_64BV6_COUNT(unit) * 2) +
  11496                              (SOC_LPM128_STAT_128BV6_COUNT(unit) * 4);
  11497         if (total_routes_added >= (R2P_V4_MAX * rpf_scale)) {
  11498             return TRUE;
  11499         }
  11500     }
  11501     return FALSE;
  11502 }
  11503 
  11504 
  11505 STATIC int
  11506 soc_fb_lpm128_can_insert_entry(int u, soc_lpm_entry_type_t type)
  11507 {
  11508     int free_count = 0;
  11509 
  11510     if (type == socLpmEntryTypeV4) {
  11511         SOC_IF_ERROR_RETURN(soc_lpm_free_v4_route_get(u, &free_count));
  11512 #ifdef BCM_TOMAHAWK2_SUPPORT
  11513         if (soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
  11514             free_count /= 2;
  11515         }
  11516 #endif
  11517     } else if (type == socLpmEntryType64BV6) {
  11518         SOC_IF_ERROR_RETURN(soc_lpm_free_64bv6_route_get(u, &free_count));
  11519     } else if (type == socLpmEntryType128BV6) {
  11520         SOC_IF_ERROR_RETURN(soc_lpm_free_128bv6_route_get(u, &free_count));
  11521     }
  11522     if (free_count == 0) {
  11523         return FALSE;
  11524     }
  11525 
  11526     return TRUE;
  11527 }
  11528 
  11529 /*
  11530  * Implementation using soc_mem_read/write using entry rippling technique
  11531  * Advantage: A completely sorted table is not required. Lookups can be slow
  11532  * as it will perform a linear search on the entries for a given prefix length.
  11533  * No device access necessary for the search if the table is cached. Auxiliary
  11534  * hash table can be maintained to speed up search(Not implemented) instead of
  11535  * performing a linear search.
  11536  * Small number of entries need to be moved around (97 worst case)
  11537  * for performing insert/update/delete. However CPU needs to do all
  11538  * the work to move the entries.
  11539  */
  11540 
  11541 /*
  11542  * soc_fb_lpm128_insert
  11543  * For IPV4 assume only both IP_ADDR0 is valid
  11544  * Moving multiple entries around in h/w vs  doing a linear search in s/w
  11545  */
  11546 int
  11547 soc_fb_lpm128_insert(int u, void *entry_data, void *entry_data1,
  11548                      int *hw_index)
  11549 {
  11550     int         pfx;
  11551     int         index, copy_index;
  11552     uint32      e[SOC_MAX_MEM_FIELD_WORDS] =  {0};
  11553     uint32      e1[SOC_MAX_MEM_FIELD_WORDS] = {0};
  11554     int         rv = SOC_E_NONE;
  11555     int         found = 0;
  11556     soc_lpm_entry_type_t type = socLpmEntryType128BV6;
  11557     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
  11558     uint32      rvt_index0 = 0, rvt_index1 = 0;
  11559     int           temp_index = -1;
  11560     uint32 defip_temp_e[SOC_MAX_MEM_WORDS];
  11561     soc_mem_t mem = L3_DEFIPm;
  11562 
  11563 #if defined(BCM_TOMAHAWK3_SUPPORT)
  11564     if (SOC_IS_TOMAHAWK3(u)) {
  11565         mem  = L3_DEFIP_LEVEL1m;
  11566     }
  11567 #endif
  11568 
  11569     sal_memcpy(e, soc_mem_entry_null(u, mem),
  11570                soc_mem_entry_words(u,mem) * 4);
  11571 
  11572     SOC_LPM_LOCK(u);
  11573     rv = _soc_fb_lpm128_match(u, entry_data, entry_data1, e, e1,
  11574                               &index, &pfx, &type);
  11575 
  11576     if (rv == SOC_E_NOT_FOUND) {
  11577         soc_lpm128_state_p lpm_state_ptr = SOC_LPM128_STATE(u);
  11578 
  11579         if (SOC_LPM128_UNRESERVED_STATE(u)) {
  11580            lpm_state_ptr = SOC_LPM128_UNRESERVED_STATE(u);
  11581         }
  11582 
  11583         /*
  11584          * Validate free entries in V4 space. In case of atomic write,
  11585          * one entry is reserved in V4 space (two v4 routes).
  11586          * Insert should not be allowed more than (max_v4_count - 2).
  11587          */
  11588         if (soc_feature(u, soc_feature_lpm_atomic_write) &&
  11589             soc_fb_lpm128_is_v4_64b_allowed_in_paired_tcam(u) &&
  11590             (SOC_LPM128_STATE_HFENT(u, lpm_state_ptr, pfx) == 0)) {
  11591 
  11592             int max_entries, used_entries, reserved_entries;
  11593 
  11594             /* Used v4 l3_defip entries */
  11595             used_entries = SOC_LPM128_STAT_V4_COUNT(u) - SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u);
  11596             used_entries = ((used_entries + 1) >> 1) + SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u);
  11597             
  11598             /* Used l3_defip entries for (v6_64  + v6_128) */
  11599             used_entries += ((SOC_LPM128_STAT_64BV6_COUNT(u) * 2) +
  11600                              (SOC_LPM128_STAT_128BV6_COUNT(u) * 2));
  11601 
  11602             /* Max number of l3_defip entries */            
  11603             max_entries = SOC_LPM128_STAT_MAX_128BV6_COUNT(u) * 2;
  11604 
  11605             /* Number of reserved entries */
  11606             reserved_entries = (type == socLpmEntryTypeV4) ? 1 : 2;
  11607 
  11608             /* Reserve one paired entry to moves entries during updates */
  11609             if (used_entries >= (max_entries - reserved_entries)) {
  11610                 SOC_LPM_UNLOCK(u);
  11611                 return SOC_E_FULL;
  11612             }
  11613         } 
  11614 
  11615         if (_bcm_fb_route_scale_check(u,
  11616             SOC_LPM128_STATE_HFENT(u, lpm_state_ptr, pfx))) {
  11617             SOC_LPM_UNLOCK(u);
  11618             return SOC_E_FULL;
  11619         }
  11620 
  11621         if (!soc_fb_lpm128_can_insert_entry(u, type)) {
  11622             SOC_LPM_UNLOCK(u);
  11623             return SOC_E_FULL;
  11624         }
  11625 
  11626         /* Will modify e if it's v4 and half entry available */
  11627         rv = _lpm128_free_slot_create(u, pfx, e, &index);
  11628         if (rv < 0) {
  11629             SOC_LPM_UNLOCK(u);
  11630             return(rv);
  11631         }
  11632 
  11633         if (soc_feature(u, soc_feature_lpm_atomic_write) &&
  11634             (type == socLpmEntryTypeV4) && (index & 1)) {
  11635            rv = _lpm128_free_slot_create(u, pfx, &defip_temp_e, &temp_index);
  11636            if (SOC_FAILURE(rv)) {
  11637               LOG_ERROR(BSL_LS_SOC_LPM, (BSL_META_U(u,
  11638                      "Temporary v6 backup entry slot create failure: %d,"
  11639                      "original_index:%d temp_index:%d pfx:%d\n\r"),
  11640                       rv, index, temp_index, pfx));
  11641               SOC_LPM_UNLOCK(u);
  11642               return rv;
  11643            }
  11644            /* Increment Half entry count, since temp slot creates one. */
  11645            SOC_LPM_COUNT_INC(SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u));
  11646 
  11647            /*
  11648             * Search again for the entry, it could have moved around as a part
  11649             * of temp slot create.
  11650             */ 
  11651            rv = _soc_fb_lpm128_match(u, e, NULL, NULL, NULL,
  11652                                       &index, &pfx, NULL);
  11653            if (SOC_FAILURE(rv)) {
  11654               return rv;
  11655            }
  11656            /*
  11657             * Increment the entry to point to the second new half since the
  11658             * search returns base index.
  11659             */
  11660            index += 1;
  11661 
  11662            /* Copy index to temp_index */
  11663            rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, (index >> 1), &defip_temp_e);
  11664            if (SOC_FAILURE(rv)) {
  11665               goto cleanup; 
  11666            }
  11667 
  11668            rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, (temp_index >> 1), &defip_temp_e);
  11669            if (SOC_FAILURE(rv)) {
  11670               goto cleanup; 
  11671            }
  11672         }
  11673     } else {
  11674         found = 1;
  11675     }
  11676 
  11677     copy_index = index;
  11678     if (rv == SOC_E_NONE) {
  11679         /* Entry already present. Update the entry */
  11680         if (type == socLpmEntryTypeV4) {
  11681             /* IPV4 entry */
  11682             if (index & 1) {
  11683                 rv = soc_fb_lpm_ip4entry0_to_1(u, entry_data, e, PRESERVE_HIT);
  11684             } else {
  11685                 rv = soc_fb_lpm_ip4entry0_to_0(u, entry_data, e, PRESERVE_HIT);
  11686             }
  11687 
  11688             if (rv < 0) {
  11689                 SOC_LPM_UNLOCK(u);
  11690                 return(rv);
  11691             }
  11692 
  11693             entry_data = (void *)e;
  11694             index >>= 1;
  11695         }
  11696 
  11697         if (!found) {
  11698             LPM128_HASH_INSERT(u, entry_data, entry_data1, index, &rvt_index0,
  11699                                &rvt_index1);
  11700             if (type == socLpmEntryTypeV4) {
  11701                 SOC_LPM_COUNT_INC(SOC_LPM128_STAT_V4_COUNT(u));
  11702                 if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
  11703                     /* indexes should change for new entry only */
  11704                     if (copy_index & 1) {
  11705                         SOC_LPM_COUNT_DEC(SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u));
  11706                     } else {
  11707                         SOC_LPM_COUNT_INC(SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u));
  11708                     }
  11709                 }
  11710             }
  11711 
  11712             if (type == socLpmEntryType64BV6) {
  11713                 SOC_LPM_COUNT_INC(SOC_LPM128_STAT_64BV6_COUNT(u));
  11714             }
  11715 
  11716             if (type == socLpmEntryType128BV6) {
  11717                 SOC_LPM_COUNT_INC(SOC_LPM128_STAT_128BV6_COUNT(u));
  11718             }
  11719         } else {
  11720             LOG_INFO(BSL_LS_SOC_LPM, (BSL_META_U(u,
  11721                      "\nsoc_fb_lpm128_insert: %d %d ENTRY ALREADY PRESENT\n"),
  11722                       index, pfx));
  11723         }
  11724         rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, index, entry_data);
  11725         if (rv >= 0) {
  11726             if (type != socLpmEntryTypeV4) {
  11727                 rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, index + tcam_depth,
  11728                                      entry_data1);
  11729                 if (rv >= 0) {
  11730                     rv = _lpm128_fb_urpf_entry_replicate(u, index, -1, entry_data,
  11731                                                          entry_data1);
  11732                 }
  11733                 if (rv >= 0) {
  11734                     SOC_LPM128_INDEX_TO_PFX_GROUP(u, index + tcam_depth) = pfx;
  11735                 }
  11736             } else {
  11737                 rv = _lpm128_fb_urpf_entry_replicate(u, index,
  11738                        ((temp_index == -1) ? -1 : (temp_index >> 1)),
  11739                        entry_data, NULL);
  11740             }
  11741             if (rv >= 0) {
  11742                 SOC_LPM128_INDEX_TO_PFX_GROUP(u, index) = pfx;
  11743             }
  11744         }
  11745         if (!found && rv < 0) {
  11746             LPM128_HASH_REVERT(u, entry_data, entry_data1, index,
  11747                                rvt_index0, rvt_index1);
  11748         }
  11749     }
  11750 
  11751 cleanup:
  11752     if (temp_index != -1) {
  11753        int is_deleted;
  11754        rv = _lpm128_free_slot_delete(u, pfx, NULL, &defip_temp_e,
  11755                                      temp_index, &is_deleted);
  11756        if (SOC_FAILURE(rv)) {
  11757           LOG_ERROR(BSL_LS_SOC_LPM, (BSL_META_U(u,
  11758                  "Temporary backup entry slot delete failure: %d,"
  11759                  "original_index:%d temp_index:%d pfx:%d\n\r"),
  11760                   rv, (index << 1), temp_index, pfx));
  11761        }
  11762     }
  11763     SOC_LPM_UNLOCK(u);
  11764     return(rv);
  11765 }
  11766 
  11767 /*
  11768  * soc_fb_lpm_delete
  11769  */
  11770 int
  11771 soc_fb_lpm128_delete(int u, void *key_data, void* key_data_upr)
  11772 {
  11773     int         pfx;
  11774     int         index;
  11775     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
  11776     uint32      eupr[SOC_MAX_MEM_FIELD_WORDS];
  11777     int         rv = SOC_E_NONE;
  11778     soc_lpm_entry_type_t type;
  11779     int is_deleted = 0;
  11780 
  11781     SOC_LPM_LOCK(u);
  11782     rv = _soc_fb_lpm128_match(u, key_data, key_data_upr, e, eupr,
  11783                               &index, &pfx, &type);
  11784     if (rv == SOC_E_NONE) {
  11785         LOG_INFO(BSL_LS_SOC_LPM,
  11786                  (BSL_META_U(u,
  11787                              "\nsoc_fb_lpm128_delete: %d %d\n"),
  11788                              index, pfx));
  11789         if (type != socLpmEntryTypeV4) {
  11790             LPM128_HASH_DELETE(u, key_data, key_data_upr, index);
  11791         }
  11792         rv = _lpm128_free_slot_delete(u, pfx, key_data, e, index, &is_deleted);
  11793         if (rv >= 0) {
  11794             if (type == socLpmEntryTypeV4) {
  11795                 SOC_LPM_COUNT_DEC(SOC_LPM128_STAT_V4_COUNT(u));
  11796             }
  11797 
  11798             if (type == socLpmEntryType64BV6) {
  11799                 SOC_LPM_COUNT_DEC(SOC_LPM128_STAT_64BV6_COUNT(u));
  11800             }
  11801 
  11802             if (type == socLpmEntryType128BV6) {
  11803                 SOC_LPM_COUNT_DEC(SOC_LPM128_STAT_128BV6_COUNT(u));
  11804             }
  11805         }
  11806 
  11807     }
  11808     SOC_LPM_UNLOCK(u);
  11809     return(rv);
  11810 }
  11811 
  11812 /*
  11813  * soc_fb_lpm_match (Exact match for the key. Will match both IP
  11814  *                   address and mask)
  11815  */
  11816 int
  11817 soc_fb_lpm128_match(int u,
  11818                void *key_data,
  11819                void *key_data_upr,
  11820                void *e,         /* return entry data if found */
  11821                void *eupr,         /* return entry data if found */
  11822                int *index_ptr,
  11823                int *pfx,
  11824                soc_lpm_entry_type_t *type)
  11825 {
  11826     int        rv;
  11827 
  11828     SOC_LPM_LOCK(u);
  11829     rv = _soc_fb_lpm128_match(u, key_data, key_data_upr, e, eupr, index_ptr,
  11830                               pfx, type);
  11831     SOC_LPM_UNLOCK(u);
  11832     return(rv);
  11833 }
  11834 
  11835 /*
  11836  * soc_fb_lpm_lookup (LPM search). Masked match.
  11837  */
  11838 int
  11839 soc_fb_lpm128_lookup(int u,
  11840                void *key_data,
  11841                void *entry_data,
  11842                int *index_ptr)
  11843 {
  11844     return(SOC_E_UNAVAIL);
  11845 }
  11846 
  11847 
  11848 int soc_fb_lpm128_get_smallest_movable_prefix(int u, int ipv6, void *e,
  11849                                              void *eupr, int *index,
  11850                                              int *pfx_len, int *count)
  11851 {
  11852     soc_lpm128_state_p lpm_state_ptr = SOC_LPM128_STATE(u);
  11853     int pfx = MAX_PFX128_INDEX;
  11854     int small_pfx = -1;
  11855     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
  11856     int v0, v1;
  11857     int rv = SOC_E_NONE;
  11858     soc_mem_t mem = L3_DEFIPm;
  11859 
  11860 #if defined(BCM_TOMAHAWK3_SUPPORT)
  11861     if (SOC_IS_TOMAHAWK3(u)) {
  11862         mem = L3_DEFIP_LEVEL1m;
  11863     }
  11864 #endif
  11865     if (soc_feature(u, soc_feature_l3_lpm_128b_entries_reserved)) {
  11866         lpm_state_ptr = SOC_LPM128_UNRESERVED_STATE(u);
  11867     }
  11868 
  11869     if (pfx_len == NULL) {
  11870         return SOC_E_PARAM;
  11871     }
  11872 
  11873     if (lpm_state_ptr == NULL) {
  11874         return SOC_E_NOT_FOUND;
  11875     }
  11876 
  11877     while (pfx != -1) {
  11878         if (ipv6 && (SOC_LPM128_PFX_IS_V6_64(u, pfx))) {
  11879             small_pfx = pfx;
  11880         }
  11881         if (!ipv6 && (SOC_LPM128_PFX_IS_V4(u, pfx))) {
  11882            small_pfx = pfx;
  11883         }
  11884         pfx = SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, pfx);
  11885     }
  11886 
  11887     if (small_pfx == -1) {
  11888        return SOC_E_NOT_FOUND;
  11889     }
  11890 
  11891     if (ipv6) {
  11892         if (index != NULL && e != NULL && eupr != NULL && count != NULL) {
  11893             *index = SOC_LPM128_STATE_END1(u, lpm_state_ptr, small_pfx);
  11894             rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, *index, e);
  11895             SOC_IF_ERROR_RETURN(rv);
  11896             rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY,
  11897                                                (*index + tcam_depth), eupr);
  11898             SOC_IF_ERROR_RETURN(rv);
  11899             *count = 1;
  11900         }
  11901     } else {
  11902         if (index != NULL && e != NULL && count != NULL) {
  11903             if (SOC_LPM128_STATE_END2(u, lpm_state_ptr, small_pfx) != -1) {
  11904                 *index = SOC_LPM128_STATE_END2(u, lpm_state_ptr, small_pfx);
  11905             } else {
  11906                 *index = SOC_LPM128_STATE_END1(u, lpm_state_ptr, small_pfx);
  11907             }
  11908 #ifdef BCM_TOMAHAWK2_SUPPORT
  11909             if (soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
  11910                rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, *index, e);
  11911                SOC_IF_ERROR_RETURN(rv);
  11912                *count = 2;
  11913             } else 
  11914 #endif
  11915             {
  11916                 rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, *index, e);
  11917                 SOC_IF_ERROR_RETURN(rv);
  11918                 v0 = SOC_MEM_OPT_F32_VALID0_GET(u, mem, e);
  11919                 v1 = SOC_MEM_OPT_F32_VALID1_GET(u, mem, e);
  11920                 if (v0 == 0 || v1 == 0) {
  11921                     *count = 1;
  11922                 } else {
  11923                     *count = 2;
  11924                 }
  11925             }
  11926         }
  11927     }
  11928 
  11929     *pfx_len = small_pfx;
  11930 
  11931     return SOC_E_NONE;
  11932 }
  11933 
  11934 int soc_fb_lpm128_is_v4_64b_allowed_in_paired_tcam(int unit)
  11935 {
  11936     if (soc_feature(unit, soc_feature_l3_lpm_128b_entries_reserved)) {
  11937         return (SOC_LPM128_UNRESERVED_STATE(unit) != NULL) ? 1 : 0;
  11938     }
  11939 
  11940     return 1;
  11941 }
  11942 
  11943 int
  11944 soc_fb_lpm_table_sizes_get(int unit, int *paired_table_size,
  11945                            int *defip_table_size)
  11946 {
  11947     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
  11948     int max_paired_count = (SOC_L3_DEFIP_MAX_TCAMS_GET(unit)) / 2;
  11949     int tcam_pair_count = 0;
  11950     int paired_size = 0;
  11951     int unpaired_size = 0;
  11952 
  11953     if (!soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) {
  11954         return SOC_E_UNAVAIL;
  11955     }
  11956 
  11957     if (soc_feature(unit, soc_feature_defip_2_tcams_with_separate_rpf)) {
  11958         /* Only 2 tcams are enabled.
  11959          * RPF status does not matter for this size.
  11960          * The RPF route memory is different than these 2 tcams.
  11961          */
  11962         if (paired_table_size != NULL) {
  11963             *paired_table_size = 2048;
  11964         }
  11965         if (defip_table_size != NULL) {
  11966             *defip_table_size  = 0;
  11967         }
  11968         return SOC_E_NONE;
  11969     }
  11970 
  11971     SOC_IF_ERROR_RETURN(soc_fb_lpm_tcam_pair_count_get(unit, &tcam_pair_count));
  11972     /* If soc_feature_l3_defip_advanced_lookup is TRUE then
  11973      * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
  11974      * L3_DEFIP table is not divided into 2 to support URPF.
  11975      */
  11976     if (SOC_URPF_STATUS_GET(unit) &&
  11977         !soc_feature(unit, soc_feature_l3_defip_advanced_lookup)) {
  11978         switch(tcam_pair_count) {
  11979             case 1:
  11980             case 2:
  11981                 unpaired_size = (max_paired_count - 2) * tcam_depth;
  11982                 paired_size = 2 * tcam_depth;
  11983                 break;
  11984             case 3:
  11985             case 4:
  11986                 unpaired_size = (max_paired_count - 4) * tcam_depth;
  11987                 paired_size = 4 * tcam_depth;
  11988                 break;
  11989             case 5:
  11990             case 6:
  11991                 unpaired_size = (max_paired_count - 6) * tcam_depth;
  11992                 paired_size = 6 * tcam_depth;
  11993                 break;
  11994             case 7:
  11995             case 8:
  11996                 unpaired_size = (max_paired_count - 8) * tcam_depth;
  11997                 paired_size = 8 * tcam_depth;
  11998                 break;
  11999             default:
  12000                 unpaired_size = max_paired_count * tcam_depth;
  12001                 paired_size = 0;
  12002                break;
  12003         }
  12004     } else {
  12005         unpaired_size = (max_paired_count - tcam_pair_count) * tcam_depth;
  12006         unpaired_size <<= 1;
  12007         paired_size = tcam_pair_count * tcam_depth;
  12008         paired_size <<= 1;
  12009     }
  12010 
  12011     if (paired_table_size != NULL) {
  12012        *paired_table_size = paired_size;
  12013     }
  12014 
  12015     if (defip_table_size != NULL) {
  12016        *defip_table_size = unpaired_size;
  12017     }
  12018 
  12019     return SOC_E_NONE;
  12020 }
  12021 
  12022 int soc_lpm_max_v4_route_get(int u, int *entries)
  12023 {
  12024     if (!(soc_feature(u, soc_feature_l3_shared_defip_table) ||
  12025           soc_feature(u, soc_feature_shared_defip_stat_support))) {
  12026         return SOC_E_UNAVAIL;
  12027     }
  12028 #if defined (BCM_TRIUMPH3_SUPPORT)
  12029     if (SOC_MEM_IS_ENABLED(u, EXT_IPV4_DEFIPm) &&
  12030         soc_mem_index_count(u, EXT_IPV4_DEFIPm)) {
  12031         *entries = SOC_EXT_LPM_MAX_V4_COUNT(u);
  12032     } else
  12033 #endif
  12034     {
  12035         *entries = SOC_LPM_MAX_V4_COUNT(u);
  12036     }
  12037     if (soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
  12038         *entries += SOC_LPM128_STAT_MAX_V4_COUNT(u);
  12039     }
  12040     return SOC_E_NONE;
  12041 }
  12042 
  12043 int soc_lpm_max_64bv6_route_get(int u, int *entries)
  12044 {
  12045     if (!(soc_feature(u, soc_feature_l3_shared_defip_table) ||
  12046           soc_feature(u, soc_feature_shared_defip_stat_support))) {
  12047         return SOC_E_UNAVAIL;
  12048     }
  12049 #if defined (BCM_TRIUMPH3_SUPPORT)
  12050     if ((SOC_MEM_IS_ENABLED(u, EXT_IPV6_64_DEFIPm) &&
  12051         soc_mem_index_count(u, EXT_IPV6_64_DEFIPm)) ||
  12052         (SOC_MEM_IS_ENABLED(u, EXT_IPV6_128_DEFIPm) &&
  12053         soc_mem_index_count(u, EXT_IPV6_128_DEFIPm))) {
  12054         *entries = SOC_EXT_LPM_MAX_64BV6_COUNT(u);
  12055     } else
  12056 #endif
  12057     {
  12058         *entries = SOC_LPM_MAX_64BV6_COUNT(u);
  12059     }
  12060     if (soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
  12061         *entries += SOC_LPM128_STAT_MAX_64BV6_COUNT(u);
  12062     }
  12063     return SOC_E_NONE;
  12064 }
  12065 
  12066 int soc_lpm_max_128bv6_route_get(int u, int *entries)
  12067 {
  12068     if (!(soc_feature(u, soc_feature_l3_shared_defip_table) ||
  12069           soc_feature(u, soc_feature_shared_defip_stat_support))) {
  12070         return SOC_E_UNAVAIL;
  12071     }
  12072 #if defined (BCM_TRIUMPH3_SUPPORT)
  12073     if (SOC_MEM_IS_ENABLED(u, EXT_IPV6_128_DEFIPm) &&
  12074         soc_mem_index_count(u, EXT_IPV6_128_DEFIPm)) {
  12075         *entries = SOC_EXT_LPM_MAX_128BV6_COUNT(u);
  12076     } else
  12077 #endif
  12078     {
  12079         *entries = SOC_LPM_MAX_128BV6_COUNT(u);
  12080     }
  12081     if (soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
  12082         *entries += SOC_LPM128_STAT_MAX_128BV6_COUNT(u);
  12083     }
  12084     return SOC_E_NONE;
  12085 }
  12086 
  12087 int
  12088 soc_lpm_free_v4_route_get(int u, int *entries)
  12089 {
  12090     int v4_count = 0;
  12091     int b64_count = 0;
  12092     int b128_count = 0;
  12093     int is_reserved = 0;
  12094     int v4_max_count = 0;
  12095 
  12096     if (!(soc_feature(u, soc_feature_l3_shared_defip_table) ||
  12097           soc_feature(u, soc_feature_shared_defip_stat_support))) {
  12098         return SOC_E_UNAVAIL;
  12099     }
  12100     if (soc_feature(u, soc_feature_l3_lpm_128b_entries_reserved)) {
  12101         is_reserved = 1;
  12102     }
  12103 
  12104     SOC_IF_ERROR_RETURN(soc_lpm_max_v4_route_get(u, &v4_max_count));
  12105     SOC_IF_ERROR_RETURN(soc_lpm_used_v4_route_get(u, &v4_count));
  12106 #if defined (BCM_TRIUMPH3_SUPPORT)
  12107     if (SOC_MEM_IS_ENABLED(u, EXT_IPV4_DEFIPm) &&
  12108         soc_mem_index_count(u, EXT_IPV4_DEFIPm)) {
  12109         *entries = v4_max_count - v4_count;
  12110         return SOC_E_NONE;
  12111     }
  12112 #endif
  12113     b64_count = SOC_LPM_64BV6_COUNT(u) << 1;
  12114     if (soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
  12115         b64_count += (SOC_LPM128_STAT_64BV6_COUNT(u) << 2);
  12116         if (!is_reserved) {
  12117             SOC_IF_ERROR_RETURN(soc_lpm_used_128bv6_route_get(u, &b128_count));
  12118             b128_count <<= 2;
  12119         }
  12120     }
  12121 #ifdef BCM_TOMAHAWK2_SUPPORT    
  12122     if (soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
  12123         *entries = v4_max_count - (b64_count + b128_count) - v4_count * 2;
  12124     } else 
  12125 #endif    
  12126     {
  12127         *entries = v4_max_count - (b64_count + b128_count) - v4_count;
  12128     }
  12129     return SOC_E_NONE;
  12130 }
  12131 
  12132 int
  12133 soc_lpm_free_64bv6_route_get(int u, int *entries)
  12134 {
  12135     int v4_count = 0;
  12136     int b64_count = 0;
  12137     int b128_count = 0;
  12138     int is_reserved = 0;
  12139     int v64_max_count = 0;
  12140     int paired_v64_max_count = 0;
  12141     int paired_v4_count = 0;
  12142     int paired_tcam_size = 0;
  12143     int paired_v64_count = 0;
  12144     int paired_count = 0;
  12145     int max_v6_entries = SOC_L3_DEFIP_MAX_128B_ENTRIES(u);
  12146     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
  12147 
  12148     if (!(soc_feature(u, soc_feature_l3_shared_defip_table) ||
  12149           soc_feature(u, soc_feature_shared_defip_stat_support))) {
  12150         return SOC_E_UNAVAIL;
  12151     }
  12152 #if defined (BCM_TRIUMPH3_SUPPORT)
  12153     if ((SOC_MEM_IS_ENABLED(u, EXT_IPV6_64_DEFIPm) &&
  12154         soc_mem_index_count(u, EXT_IPV6_64_DEFIPm)) ||
  12155         (SOC_MEM_IS_ENABLED(u, EXT_IPV6_128_DEFIPm) &&
  12156         soc_mem_index_count(u, EXT_IPV6_128_DEFIPm))) {
  12157         SOC_IF_ERROR_RETURN(soc_lpm_max_64bv6_route_get(u, &v64_max_count));
  12158         SOC_IF_ERROR_RETURN(soc_lpm_used_64bv6_route_get(u, &b64_count));
  12159         *entries = v64_max_count - b64_count;
  12160         return SOC_E_NONE;
  12161     }
  12162 #endif
  12163     if (soc_feature(u, soc_feature_l3_lpm_128b_entries_reserved)) {
  12164         is_reserved = 1;
  12165     }
  12166 
  12167     /* If soc_feature_l3_defip_advanced_lookup is TRUE then
  12168      * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
  12169      * L3_DEFIP table is not divided into 2 to support URPF.
  12170      */
  12171     if (SOC_URPF_STATUS_GET(u) &&
  12172         !soc_feature(u, soc_feature_l3_defip_advanced_lookup)) {
  12173         max_v6_entries >>= 1;
  12174     }
  12175     v64_max_count = SOC_LPM_MAX_64BV6_COUNT(u);
  12176     /*
  12177      * V4 routes may have some half entries. These entries have only
  12178      * one v4 route and other side is empty. For Half entry V4
  12179      * routes, one v4 route occupies one defip index.
  12180      * No need to divide v4 routes in half entries by half.
  12181      */
  12182 #ifdef BCM_TOMAHAWK2_SUPPORT     
  12183     if (soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
  12184         v4_count = SOC_LPM_V4_COUNT(u);
  12185     } else 
  12186 #endif
  12187     {
  12188         v4_count = SOC_LPM_V4_COUNT(u) - SOC_LPM_V4_HALF_ENTRY_COUNT(u);
  12189         v4_count = ((v4_count + 1) >> 1) + SOC_LPM_V4_HALF_ENTRY_COUNT(u);
  12190     }
  12191     b64_count = SOC_LPM_64BV6_COUNT(u);
  12192     if (soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
  12193         SOC_IF_ERROR_RETURN(soc_fb_lpm_table_sizes_get(u, &paired_tcam_size,
  12194                                                                       NULL));
  12195         if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
  12196             paired_v4_count = SOC_LPM128_STAT_V4_COUNT(u) - SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u);
  12197             paired_v4_count = ((paired_v4_count + 1) >> 1) + SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u);
  12198         } else {
  12199             paired_v4_count = SOC_LPM128_STAT_V4_COUNT(u);
  12200         }
  12201         
  12202         paired_v64_count = SOC_LPM128_STAT_64BV6_COUNT(u) << 1;
  12203         paired_v64_max_count = paired_tcam_size;
  12204         if (!is_reserved) {
  12205             SOC_IF_ERROR_RETURN(soc_lpm_used_128bv6_route_get(u, &b128_count));
  12206             b128_count <<= 1;
  12207             paired_count = paired_v64_max_count - paired_v64_count -
  12208                            paired_v4_count - b128_count;
  12209         } else {
  12210             paired_v64_max_count -= (max_v6_entries << 1);
  12211             paired_count = paired_v64_max_count - paired_v4_count -
  12212                            paired_v64_count;
  12213         }
  12214         paired_count >>= 1;
  12215     } else {
  12216         if (max_v6_entries % tcam_depth == 0) {
  12217             paired_v4_count = 0;
  12218         } else {
  12219             paired_v4_count = (tcam_depth - (max_v6_entries % tcam_depth)) << 1;
  12220         }
  12221         if (v4_count > paired_v4_count) {
  12222             v4_count -= paired_v4_count;
  12223         } else {
  12224             v4_count = 0;
  12225         }
  12226     }
  12227     *entries = v64_max_count - b64_count - v4_count + paired_count;
  12228     return SOC_E_NONE;
  12229 }
  12230 
  12231 int
  12232 soc_lpm_free_128bv6_route_get(int u, int *entries)
  12233 {
  12234     int v4_count = 0;
  12235     int b64_count = 0;
  12236     int b128_count = 0;
  12237     int is_reserved = 0;
  12238     int v128_max_count = 0;
  12239 
  12240     if (!(soc_feature(u, soc_feature_l3_shared_defip_table) ||
  12241           soc_feature(u, soc_feature_shared_defip_stat_support))) {
  12242         return SOC_E_UNAVAIL;
  12243     }
  12244 
  12245     if (soc_feature(u, soc_feature_l3_lpm_128b_entries_reserved)) {
  12246         is_reserved = 1;
  12247     }
  12248 
  12249     SOC_IF_ERROR_RETURN(soc_lpm_max_128bv6_route_get(u, &v128_max_count));
  12250     SOC_IF_ERROR_RETURN(soc_lpm_used_128bv6_route_get(u, &b128_count));
  12251 #if defined (BCM_TRIUMPH3_SUPPORT)
  12252     if (SOC_MEM_IS_ENABLED(u, EXT_IPV6_128_DEFIPm) &&
  12253         soc_mem_index_count(u, EXT_IPV6_128_DEFIPm)) {
  12254         *entries = v128_max_count - b128_count;
  12255         return SOC_E_NONE;
  12256     }
  12257 #endif
  12258     if (soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
  12259         if (!is_reserved) {
  12260             /*
  12261              * V4 routes may have some half entries. These entries have only
  12262              * one v4 route and other side is empty. For Half entry V4
  12263              * routes, one v4 route occupies one defip index.
  12264              * No need to divide v4 routes in half entries by half.
  12265              */
  12266 #ifdef BCM_TOMAHAWK2_SUPPORT             
  12267             if (soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
  12268                 v4_count = SOC_LPM128_STAT_V4_COUNT(u);
  12269             } else 
  12270 #endif
  12271             {
  12272                 v4_count = SOC_LPM128_STAT_V4_COUNT(u) - SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u);
  12273                 v4_count = ((v4_count + 1) >> 1) + SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u);
  12274             }
  12275             b64_count = SOC_LPM128_STAT_64BV6_COUNT(u);
  12276         }
  12277     }
  12278     *entries = (v128_max_count << 1) - ((b64_count + b128_count) << 1) -
  12279                v4_count;
  12280     *entries >>= 1;
  12281     return SOC_E_NONE;
  12282 }
  12283 
  12284 int
  12285 soc_lpm_used_v4_route_get(int u, int *entries)
  12286 {
  12287     if (!(soc_feature(u, soc_feature_l3_shared_defip_table) ||
  12288           soc_feature(u, soc_feature_shared_defip_stat_support))) {
  12289         return SOC_E_UNAVAIL;
  12290     }
  12291 #if defined (BCM_TRIUMPH3_SUPPORT)
  12292     if (SOC_MEM_IS_ENABLED(u, EXT_IPV4_DEFIPm) &&
  12293         soc_mem_index_count(u, EXT_IPV4_DEFIPm)) {
  12294         *entries = SOC_EXT_LPM_V4_COUNT(u);
  12295     } else
  12296 #endif
  12297     {
  12298         *entries = SOC_LPM_V4_COUNT(u);
  12299     }
  12300     if (soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
  12301         *entries += SOC_LPM128_STAT_V4_COUNT(u);
  12302     }
  12303     return SOC_E_NONE;
  12304 }
  12305 
  12306 int
  12307 soc_lpm_used_64bv6_route_get(int u, int *entries)
  12308 {
  12309     if (!(soc_feature(u, soc_feature_l3_shared_defip_table) ||
  12310           soc_feature(u, soc_feature_shared_defip_stat_support))) {
  12311         return SOC_E_UNAVAIL;
  12312     }
  12313 #if defined (BCM_TRIUMPH3_SUPPORT)
  12314     if ((SOC_MEM_IS_ENABLED(u, EXT_IPV6_64_DEFIPm) &&
  12315         soc_mem_index_count(u, EXT_IPV6_64_DEFIPm)) ||
  12316         (SOC_MEM_IS_ENABLED(u, EXT_IPV6_128_DEFIPm) &&
  12317         soc_mem_index_count(u, EXT_IPV6_128_DEFIPm))) {
  12318         *entries = SOC_EXT_LPM_64BV6_COUNT(u);
  12319     } else
  12320 #endif
  12321     {
  12322         *entries = SOC_LPM_64BV6_COUNT(u);
  12323     }
  12324     if (soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
  12325         *entries += SOC_LPM128_STAT_64BV6_COUNT(u);
  12326     }
  12327     return SOC_E_NONE;
  12328 }
  12329 
  12330 int
  12331 soc_lpm_used_128bv6_route_get(int u, int *entries)
  12332 {
  12333     if (!(soc_feature(u, soc_feature_l3_shared_defip_table) ||
  12334           soc_feature(u, soc_feature_shared_defip_stat_support))) {
  12335         return SOC_E_UNAVAIL;
  12336     }
  12337 #if defined (BCM_TRIUMPH3_SUPPORT)
  12338     if (SOC_MEM_IS_ENABLED(u, EXT_IPV6_128_DEFIPm) &&
  12339         soc_mem_index_count(u, EXT_IPV6_128_DEFIPm)) {
  12340         *entries = SOC_EXT_LPM_128BV6_COUNT(u);
  12341     } else
  12342 #endif
  12343     {
  12344         *entries = SOC_LPM_128BV6_COUNT(u);
  12345     }
  12346     if (soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
  12347         *entries += SOC_LPM128_STAT_128BV6_COUNT(u);
  12348     }
  12349     return SOC_E_NONE;
  12350 }
  12351 
  12352 void
  12353 soc_lpm_stat_128b_count_update(int u, int incr)
  12354 {
  12355     if (!(soc_feature(u, soc_feature_l3_shared_defip_table) ||
  12356           soc_feature(u, soc_feature_shared_defip_stat_support))) {
  12357         return;
  12358     }
  12359 
  12360     if (incr) {
  12361         SOC_LPM_COUNT_INC(SOC_LPM_128BV6_COUNT(u));
  12362     } else {
  12363         SOC_LPM_COUNT_DEC(SOC_LPM_128BV6_COUNT(u));
  12364     }
  12365 }
  12366 
  12367 /*
  12368  * Returns number of entries reserved to provide atomicity.
  12369  * Supported only if 'lpm_atomic_write' is enabled.
  12370  */
  12371 int
  12372 soc_lpm_reserved_route_get(int u, int *v4_entries,
  12373                            int *v6_64_entries,
  12374                            int *v6_128_entries)
  12375 {
  12376     int v4 = 0, v6_64 = 0, v6_128 = 0;
  12377  
  12378     if (soc_feature(u, soc_feature_lpm_atomic_write)) {
  12379         int max_entries;
  12380         uint16 unpaired_entries;
  12381 
  12382         SOC_IF_ERROR_RETURN(soc_lpm_max_v4_route_get(u, &max_entries));
  12383         SOC_IF_ERROR_RETURN(_soc_lpm_max_v4_route_get(u, 0,
  12384                                               &unpaired_entries));
  12385         if (max_entries - unpaired_entries) {
  12386            v6_64 = 2;
  12387            v4 = 4;
  12388            v6_128 = 1;
  12389         } else {
  12390            v6_64 = 1;
  12391            v4 = 2;
  12392         }
  12393     }
  12394 
  12395     if (v4_entries != NULL) {
  12396        *v4_entries = v4;
  12397     }
  12398 
  12399     if (v6_64_entries != NULL) {
  12400        *v6_64_entries = v6_64;
  12401     }
  12402 
  12403     if (v6_128_entries != NULL) {
  12404        *v6_128_entries = v6_128;
  12405     } 
  12406 
  12407     return SOC_E_NONE;
  12408 }
  12409 
  12410 #ifdef BCM_WARM_BOOT_SUPPORT
  12411 int
  12412 soc_fb_lpm128_reinit(int u, int idx, uint32 *lpm_entry,
  12413                      uint32 *lpm_entry_upr)
  12414 {
  12415     int pfx = 0;
  12416     int is_reserved = 0;
  12417     soc_lpm128_state_p lpm_state_ptr = SOC_LPM128_STATE(u);
  12418     int max_v6_entries = SOC_L3_DEFIP_MAX_128B_ENTRIES(u);
  12419     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(u);
  12420 
  12421     if (!soc_feature(u, soc_feature_l3_lpm_scaling_enable)) {
  12422         return SOC_E_NONE;
  12423     }
  12424 
  12425     if (max_v6_entries == 0) {
  12426         return SOC_E_NONE;
  12427     }
  12428 
  12429     if (soc_feature(u, soc_feature_l3_lpm_128b_entries_reserved)) {
  12430         is_reserved = 1;
  12431     }
  12432 
  12433     SOC_IF_ERROR_RETURN
  12434         (_soc_fb_lpm128_prefix_length_get(u, lpm_entry, lpm_entry_upr,
  12435                                           &pfx));
  12436 
  12437     if (!is_reserved || (SOC_LPM128_PFX_IS_V6_128(u, pfx))) {
  12438         lpm_state_ptr = SOC_LPM128_STATE(u);
  12439     } else {
  12440         lpm_state_ptr = SOC_LPM128_UNRESERVED_STATE(u);
  12441     }
  12442 
  12443     if (SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) == 0) {
  12444         SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx) = idx;
  12445         SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) = idx;
  12446     } else {
  12447         if (SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) != -1) {
  12448             SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) = idx;
  12449         } else {
  12450             if (((SOC_LPM128_PFX_IS_V6(u, pfx))) && ((idx / tcam_depth) & 1)) {
  12451                 return SOC_E_NONE;
  12452             }
  12453             if ((SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) + 1) != idx &&
  12454                 (SOC_LPM128_PFX_IS_V4(u, pfx))) {
  12455                 SOC_LPM128_STATE_START2(u, lpm_state_ptr, pfx) = idx;
  12456                 SOC_LPM128_STATE_END2(u, lpm_state_ptr, pfx) = idx;
  12457             } else {
  12458                 SOC_LPM128_STATE_END1(u, lpm_state_ptr, pfx) = idx;
  12459             }
  12460         }
  12461     }
  12462 
  12463     SOC_LPM128_STATE_VENT(u, lpm_state_ptr, pfx) += 1;
  12464     LPM128_HASH_INSERT(u, lpm_entry, lpm_entry_upr, idx, NULL, NULL);
  12465     SOC_LPM128_INDEX_TO_PFX_GROUP(u, idx) = pfx;
  12466     if (SOC_LPM128_PFX_IS_V6(u, pfx)) {
  12467         SOC_LPM128_INDEX_TO_PFX_GROUP(u, idx + tcam_depth) = pfx;
  12468     }
  12469 
  12470     return (SOC_E_NONE);
  12471 }
  12472 
  12473 STATIC int
  12474 _soc_fb_lpm128_setup_pfx_state(int u, soc_lpm128_state_p lpm_state_ptr)
  12475 {
  12476     int prev_idx = MAX_PFX128_INDEX;
  12477     int idx = 0;
  12478     int from_ent = -1;
  12479     int v0 = 0, v1 = 0;
  12480     uint32      e[SOC_MAX_MEM_FIELD_WORDS] = {0};
  12481     int rv = SOC_E_NONE;
  12482     soc_mem_t mem = L3_DEFIPm;
  12483 
  12484 #if defined(BCM_TOMAHAWK3_SUPPORT)
  12485     if (SOC_IS_TOMAHAWK3(u)) {
  12486         mem = L3_DEFIP_LEVEL1m;
  12487     }
  12488 #endif
  12489 
  12490     if (NULL == lpm_state_ptr) {
  12491        return SOC_E_INTERNAL;
  12492     }
  12493 
  12494     SOC_LPM128_STATE_PREV(u, lpm_state_ptr, MAX_PFX128_INDEX) = -1;
  12495 
  12496     for (idx = MAX_PFX128_INDEX; idx > 0; idx--) {
  12497        if (SOC_LPM128_STATE_START1(u, lpm_state_ptr, idx) == -1) {
  12498            continue;
  12499        }
  12500 
  12501        SOC_LPM128_STATE_PREV(u, lpm_state_ptr, idx) = prev_idx;
  12502        SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, prev_idx) = idx;
  12503 
  12504        prev_idx = idx;
  12505        if (SOC_LPM128_PFX_IS_V6_64(u, idx)) {
  12506            SOC_LPM128_STAT_64BV6_COUNT(u) += SOC_LPM128_STATE_VENT(u,
  12507                                                            lpm_state_ptr, idx);
  12508        }
  12509 
  12510        if (SOC_LPM128_PFX_IS_V6_128(u, idx)) {
  12511            SOC_LPM128_STAT_128BV6_COUNT(u) += SOC_LPM128_STATE_VENT(u,
  12512                                                             lpm_state_ptr, idx);
  12513        }
  12514 
  12515        if (SOC_LPM128_PFX_IS_V4(u, idx)) {
  12516            if (SOC_LPM128_STATE_START2(u, lpm_state_ptr, idx) != -1) {
  12517                from_ent = SOC_LPM128_STATE_END2(u, lpm_state_ptr, idx);
  12518            } else {
  12519                from_ent = SOC_LPM128_STATE_END1(u, lpm_state_ptr, idx);
  12520            }
  12521 #ifdef FB_LPM_TABLE_CACHED
  12522            SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, mem,
  12523                                                      MEM_BLOCK_ANY, from_ent));
  12524 #endif /* FB_LPM_TABLE_CACHED */
  12525             rv = READ_L3_DEFIPm(u, MEM_BLOCK_ANY, from_ent, e);
  12526             SOC_IF_ERROR_RETURN(rv);
  12527             if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) {
  12528                 v0 = SOC_MEM_OPT_F32_VALID0_GET(u, mem, e);
  12529                 v1 = SOC_MEM_OPT_F32_VALID1_GET(u, mem, e);
  12530                 SOC_LPM128_STAT_V4_COUNT(u) += (SOC_LPM128_STATE_VENT(u,
  12531                                                           lpm_state_ptr, idx)) << 1;
  12532                 if ((v0 == 0) || (v1 == 0)) {
  12533                     SOC_LPM128_STAT_V4_COUNT(u) -= 1;
  12534                 }
  12535                 if ((v0 && (!(v1))) || ((!(v0) && v1))) {
  12536                     SOC_LPM_COUNT_INC(SOC_LPM128_STAT_V4_HALF_ENTRY_COUNT(u));
  12537                     SOC_LPM128_STATE_HFENT(u, lpm_state_ptr, idx) = 1;
  12538                 }
  12539             } else {
  12540                 SOC_LPM128_STAT_V4_COUNT(u) += SOC_LPM128_STATE_VENT(u,
  12541                                                           lpm_state_ptr, idx);
  12542             }
  12543         }
  12544     }
  12545 
  12546     SOC_LPM128_STATE_NEXT(u, lpm_state_ptr, prev_idx) = -1;
  12547 
  12548     return SOC_E_NONE;
  12549 }
  12550 
  12551 int
  12552 soc_fb_lpm128_reinit_done(int unit, int ipv6)
  12553 {
  12554     int paired_table_size = 0;
  12555     int defip_table_size = 0;
  12556     int i = 0;
  12557     int pfx;
  12558     int is_reserved = 0;
  12559     int start_idx = -1;
  12560     int end_idx = -1;
  12561     int fent_incr = 0;
  12562     int found = 0;
  12563     int first_v4_index = -1;
  12564     int split_done = 0;
  12565     int next_pfx = -1;
  12566     soc_lpm128_state_p lpm_state_ptr = SOC_LPM128_STATE(unit);
  12567     int max_v6_entries = SOC_L3_DEFIP_MAX_128B_ENTRIES(unit);
  12568     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
  12569 
  12570     if (!soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) {
  12571         return SOC_E_NONE;
  12572     }
  12573 
  12574     if (!ipv6) {
  12575         return SOC_E_NONE;
  12576     }
  12577 
  12578     if (max_v6_entries == 0) {
  12579         return SOC_E_NONE;
  12580     }
  12581 
  12582     if (soc_feature(unit, soc_feature_l3_lpm_128b_entries_reserved)) {
  12583         is_reserved = 1;
  12584     }
  12585 
  12586     SOC_IF_ERROR_RETURN(soc_fb_lpm_table_sizes_get(unit, &paired_table_size,
  12587                                                    &defip_table_size));
  12588     /* If soc_feature_l3_defip_advanced_lookup is TRUE then
  12589      * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
  12590      * L3_DEFIP table is not divided into 2 to support URPF.
  12591      */
  12592     if (SOC_URPF_STATUS_GET(unit) &&
  12593         !soc_feature(unit, soc_feature_l3_defip_advanced_lookup)) {
  12594         max_v6_entries >>= 1;
  12595     }
  12596 
  12597     lpm_state_ptr = SOC_LPM128_STATE(unit);
  12598     if (lpm_state_ptr == NULL) {
  12599         return SOC_E_NONE;
  12600     }
  12601     SOC_IF_ERROR_RETURN
  12602         (_soc_fb_lpm128_setup_pfx_state(unit, lpm_state_ptr));
  12603 
  12604     pfx = MAX_PFX128_INDEX;
  12605     next_pfx = SOC_LPM128_STATE_NEXT(unit, lpm_state_ptr, pfx);
  12606     start_idx = 0;
  12607     if (!is_reserved) {
  12608         end_idx = paired_table_size;
  12609         if (next_pfx == -1) {
  12610             SOC_LPM128_STATE_FENT(unit, lpm_state_ptr, pfx) = end_idx;
  12611         }
  12612     } else {
  12613         end_idx = max_v6_entries;
  12614         if (next_pfx == -1) {
  12615             SOC_LPM128_STATE_FENT(unit, lpm_state_ptr, pfx) = end_idx << 1;
  12616         }
  12617     }
  12618 
  12619     for (i = start_idx; (next_pfx != -1) && i < end_idx; i++) {
  12620         if (((i / tcam_depth) & 1) && (i % tcam_depth == 0)) {
  12621             if (is_reserved) {
  12622                 i += max_v6_entries;
  12623             }
  12624             if (first_v4_index != -1 && !split_done) {
  12625                 i = first_v4_index + tcam_depth;
  12626                 split_done = 1;
  12627             }
  12628         }
  12629         if (SOC_LPM128_INDEX_TO_PFX_GROUP(unit, i) != -1) {
  12630             pfx = SOC_LPM128_INDEX_TO_PFX_GROUP(unit, i);
  12631             if (SOC_LPM128_PFX_IS_V4(u, pfx)) {
  12632                 if (first_v4_index == -1) {
  12633                    first_v4_index = SOC_LPM128_STATE_START1(u, lpm_state_ptr, pfx);
  12634                 }
  12635                 fent_incr = 1;
  12636             } else {
  12637                 fent_incr = 2;
  12638             }
  12639             if (pfx != MAX_PFX128_INDEX) {
  12640                 found = 1;
  12641             }
  12642         } else {
  12643             if ((SOC_LPM128_PFX_IS_V6(u, pfx)) && ((i / tcam_depth) & 1)) {
  12644                 continue;
  12645             }
  12646             SOC_LPM128_STATE_FENT(unit, lpm_state_ptr, pfx) += fent_incr;
  12647         }
  12648     }
  12649 
  12650     if (found) {
  12651         SOC_LPM128_STATE_FENT(unit, lpm_state_ptr, MAX_PFX128_INDEX) = 0;
  12652     }
  12653     lpm_state_ptr = SOC_LPM128_UNRESERVED_STATE(unit);
  12654     if (lpm_state_ptr == NULL) {
  12655        return SOC_E_NONE;
  12656     }
  12657     SOC_IF_ERROR_RETURN
  12658         (_soc_fb_lpm128_setup_pfx_state(unit, lpm_state_ptr));
  12659     pfx = MAX_PFX128_INDEX;
  12660     found = 0;
  12661     start_idx = ((max_v6_entries / tcam_depth) * tcam_depth * 2) +
  12662                 max_v6_entries % tcam_depth;
  12663     next_pfx = SOC_LPM128_STATE_NEXT(unit, lpm_state_ptr, pfx);
  12664     if (next_pfx == -1) {
  12665         SOC_LPM128_STATE_FENT(unit, lpm_state_ptr, pfx) = (paired_table_size -
  12666                                                          (max_v6_entries << 1));
  12667     }
  12668     for (i = start_idx; (next_pfx != -1) && i < paired_table_size; i++) {
  12669         if (((i / tcam_depth) & 1) && (i % tcam_depth == 0)) {
  12670             i += (max_v6_entries % tcam_depth);
  12671         }
  12672         if (SOC_LPM128_INDEX_TO_PFX_GROUP(unit, i) != -1) {
  12673             pfx = SOC_LPM128_INDEX_TO_PFX_GROUP(unit, i);
  12674             if (SOC_LPM128_PFX_IS_V4(u, pfx)) {
  12675                 fent_incr = 1;
  12676             } else {
  12677                 fent_incr = 2;
  12678             }
  12679             if (pfx != MAX_PFX128_INDEX) {
  12680                 found = 1;
  12681             }
  12682         } else {
  12683             SOC_LPM128_STATE_FENT(unit, lpm_state_ptr, pfx) += fent_incr;
  12684         }
  12685     }
  12686 
  12687     if (found) {
  12688         SOC_LPM128_STATE_FENT(unit, lpm_state_ptr, MAX_PFX128_INDEX) = 0;
  12689     }
  12690 
  12691     return SOC_E_NONE;
  12692 }
  12693 #endif /* BCM_WARM_BOOT_SUPPORT */
  12694 #endif
  12695 #endif /* BCM_FIREBOLT_SUPPORT */
  12696 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_L3)
  12697 soc_kt_lpm_ipv6_info_t *
  12698 soc_kt_lpm_ipv6_info_get(int unit)
  12699 {
  12700     return kt_lpm_ipv6_info[unit];
  12701 }
  12702 #endif
  12703 
  12704