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