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