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