alpm.c (439182B)
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.c 7 * Purpose: Primitives for LPM management in ALPM - Mode. 8 * Requires: 9 */ 10 11 /* Implementation notes: 12 */ 13 #include <shared/bsl.h> 14 15 #include <soc/mem.h> 16 #include <soc/drv.h> 17 #include <soc/debug.h> 18 #include <soc/error.h> 19 #include <soc/lpm.h> 20 #include <soc/trident2.h> 21 #include <shared/bsl.h> 22 #include <soc/l3x.h> 23 #ifdef ALPM_ENABLE 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 #include <soc/esw/alpm_trie_v6.h> 30 31 32 33 #define ALPM_REPART_DEBUG 34 #define ALPM_USE_RAW_VIEW 35 /* indicate whether HIT flag is supported */ 36 37 #define SHR_SHIFT_LEFT(val, count) \ 38 (((count) == 32) ? 0 : (val) << (count)) 39 40 #define SHR_SHIFT_RIGHT(val, count) \ 41 (((count) == 32) ? 0 : (val) >> (count)) 42 43 #define SOC_ALPM_LPM_CACHE_FIELD_CREATE(m, f) soc_field_info_t * m##f 44 #define SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(m_u, s, m, f) \ 45 (s)->m##f = soc_mem_fieldinfo_get(m_u, m, f) 46 47 /* Add support for Extended based on Flex Counter support type */ 48 #define SOC_ALPM_TABLE_MEM(_u_, _v6_, _mem_, _flex_) \ 49 _mem_ = (_v6_) ? ((_flex_) ? L3_DEFIP_ALPM_IPV6_64_1m : L3_DEFIP_ALPM_IPV6_64m) \ 50 : ((_flex_) ? L3_DEFIP_ALPM_IPV4_1m : L3_DEFIP_ALPM_IPV4m) 51 52 /* Add suport for Extended */ 53 #define SOC_ALPM_ENTRY_BUF(_v6_, _mem_, _buf_, _v4ent_, _v6ent_) \ 54 _buf_ = ((_v6_) ? ((uint32 *)&(_v6ent_)) : ((uint32 *)&(_v4ent_))) 55 56 57 /* this is a left shift of the prefix by 32/64 - length and convert to 58 brcm order of ip words */ 59 #define ALPM_TRIE_TO_NORMAL_IP(prefix, length, v6) \ 60 do {\ 61 if (!(v6)) {\ 62 prefix[0] = SHR_SHIFT_LEFT(prefix[1], 32 - length);\ 63 prefix[1] = 0;\ 64 } else {\ 65 int macro_pfx_shift = 64 - length;\ 66 int macro_tmp;\ 67 if (macro_pfx_shift < 32) {\ 68 /* get upper half shifted */\ 69 macro_tmp = prefix[3] << macro_pfx_shift;\ 70 /* isolate shifted stuff off lower half */\ 71 macro_tmp |= SHR_SHIFT_RIGHT(prefix[4], 32 - macro_pfx_shift);\ 72 /* swap the order of words */\ 73 prefix[0] = prefix[4] << macro_pfx_shift;\ 74 prefix[1] = macro_tmp;\ 75 prefix[2] = prefix[3] = prefix[4] = 0;\ 76 } else {\ 77 prefix[1] = SHR_SHIFT_LEFT(prefix[4], macro_pfx_shift - 32);\ 78 prefix[0] = prefix[2] = prefix[3] = prefix[4] = 0;\ 79 }\ 80 }\ 81 } while (0) 82 83 84 soc_alpm_bucket_t soc_alpm_bucket[SOC_MAX_NUM_DEVICES]; 85 int l3_alpm_sw_prefix_lookup[SOC_MAX_NUM_DEVICES]; 86 _soc_alpm_ctrl_t soc_alpm_control[SOC_MAX_NUM_DEVICES] = {{0}}; 87 _alpm_int_dbg_cnt_t soc_alpm_dbg_cnt[SOC_MAX_NUM_DEVICES]; 88 89 void soc_alpm_lpm_state_dump(int u); 90 static int soc_alpm_lpm_init(int u); 91 static int soc_alpm_lpm_deinit(int u); 92 static int soc_alpm_lpm_insert(int u, void *entry_data, int *index, 93 int src_default, int src_discard, int bpm_len); 94 static int soc_alpm_lpm_delete(int u, void *key_data); 95 static int _soc_alpm_fill_aux_entry_for_op(int u, 96 void *key_data, 97 int ipv6, /* Entry is ipv6. */ 98 int db_type, /* database type */ 99 int ent_type, 100 int replace_len, /* used for DElete propagate */ 101 defip_aux_scratch_entry_t *aux_entry); 102 103 static int _soc_alpm_lpm_match(int u, 104 void *key_data, 105 void *e, /* return entry data if found */ 106 int *index_ptr, /* return key location */ 107 int *pfx_len, /* Key prefix length. vrf + 32 + prefix len for IPV6*/ 108 int *ipv6); /* Entry is ipv6. */ 109 static int soc_alpm_lpm_match(int u, 110 void *key_data, 111 void *e, /* return entry data if found */ 112 int *index_ptr); /* return key location */ 113 static int soc_alpm_shared_mem_init(int u); 114 static int _soc_alpm_mem_ent_init(int unit, void *lpm_entry, 115 void *alpm_entry, void *alpm_sip_entry, soc_mem_t mem, 116 uint32 src_flags, uint32 *default_route); 117 static int 118 _soc_alpm_lpm_ent_init(int unit, void *alpm_entry, soc_mem_t mem, int ipv6, int vrf_id, 119 int bucket, int index, void *lpm_entry, int flex); 120 static int 121 _soc_alpm_lpm_ent_key_init(int unit, uint32 *key, int len, int vrf, int ipv6, 122 defip_entry_t *lpm_entry, int init); 123 124 static int soc_alpm_vrf_delete(int u, int vrf, int v6); 125 static int _soc_alpm_lpm_prefix_length_get(int u, void *entry, int *pfx_len); 126 127 128 #define FB_LPM_HASH_SUPPORT 1 129 130 typedef struct soc_alpm_lpm_state_s { 131 int start; /* start index for this prefix length */ 132 int end; /* End index for this prefix length */ 133 int prev; /* Previous (Lo to Hi) prefix length with non zero entry count*/ 134 int next; /* Next (Hi to Lo) prefix length with non zero entry count */ 135 int vent; /* valid entries */ 136 int fent; /* free entries */ 137 } soc_alpm_lpm_state_t, *soc_alpm_lpm_state_p; 138 139 #define SOC_MEM_COMPARE_RETURN(a, b) { \ 140 if ((a) < (b)) { return -1; } \ 141 if ((a) > (b)) { return 1; } \ 142 } 143 144 /* Can move to SOC Control structures */ 145 static soc_alpm_lpm_state_p soc_alpm_lpm_state[SOC_MAX_NUM_DEVICES]; 146 147 #define ALPM_INVALID_INDEX -1 148 #define CONVERT_NONE -1 149 #define WRITE_PIVOT_WITH_SRC_INDEX 0 150 #define WRITE_PIVOT_WITH_SRC_INDEX_CONVERT 1 151 #define WRITE_PIVOT_WITH_URPF_PARAMS 2 152 #define WRITE_PIVOT_WITHOUT_INSERT_HASH 0x80000000 153 154 155 #define ALPM_IPV6_PFX_ZERO 33 156 #define ALPM_MAX_VRF_PFX_ENTRIES (64 + 32 + 2 + 1) 157 #define ALPM_MAX_VRF_PFX_INDEX (ALPM_MAX_VRF_PFX_ENTRIES - 1) 158 #define ALPM_MAX_PFX_ENTRIES (3 * ALPM_MAX_VRF_PFX_ENTRIES) 159 #define ALPM_MAX_PFX_INDEX (ALPM_MAX_PFX_ENTRIES - 1) 160 #define SOC_ALPM_PFX_IS_V4(u, pfx) (((pfx) % ALPM_MAX_VRF_PFX_ENTRIES) < ALPM_IPV6_PFX_ZERO) 161 #define SOC_ALPM_PFX_IS_V6_64(u, pfx) (((pfx) % ALPM_MAX_VRF_PFX_ENTRIES) >= ALPM_IPV6_PFX_ZERO && \ 162 (pfx) != ALPM_MAX_VRF_PFX_INDEX) 163 164 #define SOC_ALPM_LPM_INIT_CHECK(u) (soc_alpm_lpm_state[(u)] != NULL) 165 #define SOC_ALPM_LPM_STATE(u) (soc_alpm_lpm_state[(u)]) 166 #define SOC_ALPM_LPM_STATE_START(u, pfx) (soc_alpm_lpm_state[(u)][(pfx)].start) 167 #define SOC_ALPM_LPM_STATE_END(u, pfx) (soc_alpm_lpm_state[(u)][(pfx)].end) 168 #define SOC_ALPM_LPM_STATE_PREV(u, pfx) (soc_alpm_lpm_state[(u)][(pfx)].prev) 169 #define SOC_ALPM_LPM_STATE_NEXT(u, pfx) (soc_alpm_lpm_state[(u)][(pfx)].next) 170 #define SOC_ALPM_LPM_STATE_VENT(u, pfx) (soc_alpm_lpm_state[(u)][(pfx)].vent) 171 #define SOC_ALPM_LPM_STATE_FENT(u, pfx) (soc_alpm_lpm_state[(u)][(pfx)].fent) 172 173 typedef struct soc_lpm_field_cache_s { 174 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, CLASS_ID0f); 175 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, CLASS_ID1f); 176 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DST_DISCARD0f); 177 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DST_DISCARD1f); 178 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP0f); 179 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP1f); 180 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_COUNT0f); 181 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_COUNT1f); 182 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_PTR0f); 183 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_PTR1f); 184 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_ROUTE0f); 185 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_ROUTE1f); 186 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MULTICAST_ROUTE0f); 187 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MULTICAST_ROUTE1f); 188 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPA_ID0f); 189 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPA_ID1f); 190 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, EXPECTED_L3_IIF0f); 191 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, EXPECTED_L3_IIF1f); 192 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f); 193 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f); 194 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f); 195 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f); 196 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, L3MC_INDEX0f); 197 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, L3MC_INDEX1f); 198 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, HIT0f); 199 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, HIT1f); 200 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR0f); 201 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR1f); 202 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR_MASK0f); 203 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR_MASK1f); 204 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MODE0f); 205 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MODE1f); 206 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MODE_MASK0f); 207 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MODE_MASK1f); 208 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, NEXT_HOP_INDEX0f); 209 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, NEXT_HOP_INDEX1f); 210 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, PRI0f); 211 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, PRI1f); 212 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPE0f); 213 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPE1f); 214 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VALID0f); 215 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VALID1f); 216 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_0f); 217 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_1f); 218 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_MASK0f); 219 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_MASK1f); 220 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_HIGH0f); 221 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_HIGH1f); 222 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_HIT_IDX0f); 223 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_HIT_IDX1f); 224 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_BKT_PTR0f); 225 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_BKT_PTR1f); 226 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DEFAULT_MISS0f); 227 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DEFAULT_MISS1f); 228 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_BASE_COUNTER_IDX0f); 229 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_BASE_COUNTER_IDX1f); 230 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_POOL_NUMBER0f); 231 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_POOL_NUMBER1f); 232 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_OFFSET_MODE0f); 233 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_OFFSET_MODE1f); 234 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_TYPE_MASK0f); 235 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_TYPE_MASK1f); 236 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_TYPE0f); 237 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_TYPE1f); 238 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_VIEW0f); 239 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_VIEW1f); 240 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, SRC_DISCARD0f); 241 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, SRC_DISCARD1f); 242 243 } soc_lpm_field_cache_t, *soc_lpm_field_cache_p; 244 static soc_lpm_field_cache_p soc_lpm_field_cache_state[SOC_MAX_NUM_DEVICES]; 245 246 #define SOC_MEM_OPT_F32_GET(m_unit, m_mem, m_entry_data, m_field) \ 247 soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), (soc_lpm_field_cache_state[(m_unit)]->m_mem##m_field)) 248 249 #define SOC_MEM_OPT_F32_SET(m_unit, m_mem, m_entry_data, m_field, m_val) \ 250 soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), (soc_lpm_field_cache_state[(m_unit)]->m_mem##m_field), (m_val)) 251 252 253 #define SOC_MEM_OPT_FIELD_VALID(m_unit, m_mem, m_field) \ 254 ((soc_lpm_field_cache_state[(m_unit)]->m_mem##m_field) != NULL) 255 256 257 #ifdef FB_LPM_HASH_SUPPORT 258 typedef struct _soc_alpm_lpm_hash_s { 259 int unit; 260 int entry_count; /* Number entries in hash table */ 261 int index_count; /* Hash index max value + 1 */ 262 uint16 *table; /* Hash table with 16 bit index */ 263 uint16 *link_table; /* To handle collisions */ 264 } _soc_alpm_lpm_hash_t; 265 266 typedef uint32 _soc_alpm_lpm_hash_entry_t[5]; 267 typedef int (*_soc_alpm_lpm_hash_compare_fn)(_soc_alpm_lpm_hash_entry_t key1, 268 _soc_alpm_lpm_hash_entry_t key2); 269 static _soc_alpm_lpm_hash_t *_fb_lpm_hash_tab[SOC_MAX_NUM_DEVICES]; 270 #define SOC_ALPM_LPM_STATE_HASH(u) (_fb_lpm_hash_tab[(u)]) 271 272 #define TD2_ALPM_HASH_INDEX_NULL (0xFFFF) 273 #define TD2_ALPM_HASH_INDEX_MASK (0x7FFF) 274 #define TD2_ALPM_HASH_IPV6_MASK (0x8000) 275 276 #define SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, odata) \ 277 odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR0f); \ 278 odata[1] = \ 279 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK0f); \ 280 odata[2] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR1f); \ 281 odata[3] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK1f);\ 282 if ( (!(SOC_IS_HURRICANE(u))) && \ 283 (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f))) { \ 284 int m_vrf;\ 285 (void) soc_alpm_lpm_vrf_get(u, entry_data, (int *)&odata[4], &m_vrf); \ 286 } else { \ 287 odata[4] = 0; \ 288 } 289 290 291 #define SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, odata) \ 292 odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR0f); \ 293 odata[1] = \ 294 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK0f); \ 295 odata[2] = 0; \ 296 odata[3] = 0x80000001; \ 297 if ((!(SOC_IS_HURRICANE(u))) && \ 298 (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f))) { \ 299 int m_vrf;\ 300 (void) soc_alpm_lpm_vrf_get(u, entry_data, (int *)&odata[4], &m_vrf); \ 301 } else { \ 302 odata[4] = 0; \ 303 } 304 305 #define SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, odata) \ 306 odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR1f); \ 307 odata[1] = \ 308 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK1f); \ 309 odata[2] = 0; \ 310 odata[3] = 0x80000001; \ 311 if ((!(SOC_IS_HURRICANE(u))) && \ 312 (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_1f))) { \ 313 int m_vrf;\ 314 defip_entry_t m_tmp_ipv4;\ 315 (void )soc_alpm_lpm_ip4entry1_to_0(u, entry_data, &m_tmp_ipv4, 0); \ 316 (void) soc_alpm_lpm_vrf_get(u, &m_tmp_ipv4, (int *)&odata[4], &m_vrf); \ 317 } else { \ 318 odata[4] = 0; \ 319 } 320 321 #define SOC_FB_LPM_HASH_ENTRY_GET _soc_alpm_lpm_hash_entry_get 322 323 static 324 void _soc_alpm_lpm_hash_entry_get(int u, void *e, 325 int index, _soc_alpm_lpm_hash_entry_t r_entry, 326 int *v); 327 static 328 uint16 _soc_alpm_lpm_hash_compute(uint8 *data, int data_nbits); 329 static 330 int _soc_alpm_lpm_hash_create(int unit, 331 int entry_count, 332 int index_count, 333 _soc_alpm_lpm_hash_t **fb_lpm_hash_ptr); 334 static 335 int _soc_alpm_lpm_hash_destroy(_soc_alpm_lpm_hash_t *fb_lpm_hash); 336 static 337 int _soc_alpm_lpm_hash_lookup(_soc_alpm_lpm_hash_t *hash, 338 _soc_alpm_lpm_hash_compare_fn key_cmp_fn, 339 _soc_alpm_lpm_hash_entry_t entry, 340 int pfx, 341 uint16 *key_index); 342 static 343 int _soc_alpm_lpm_hash_insert(_soc_alpm_lpm_hash_t *hash, 344 _soc_alpm_lpm_hash_compare_fn key_cmp_fn, 345 _soc_alpm_lpm_hash_entry_t entry, 346 int pfx, 347 uint16 old_index, 348 uint16 new_index, 349 uint32 *rvt_index); 350 static 351 int _soc_alpm_lpm_hash_revert(_soc_alpm_lpm_hash_t *hash, 352 _soc_alpm_lpm_hash_compare_fn key_cmp_fn, 353 _soc_alpm_lpm_hash_entry_t entry, 354 uint16 new_index, 355 uint32 rvt_index); 356 static 357 int _soc_alpm_lpm_hash_delete(_soc_alpm_lpm_hash_t *hash, 358 _soc_alpm_lpm_hash_compare_fn key_cmp_fn, 359 _soc_alpm_lpm_hash_entry_t entry, 360 int pfx, 361 uint16 delete_index); 362 363 static 364 int _soc_alpm_lpm_hash_verify(_soc_alpm_lpm_hash_t *hash, 365 _soc_alpm_lpm_hash_compare_fn key_cmp_fn, 366 _soc_alpm_lpm_hash_entry_t entry, 367 int pfx, 368 uint16 index); 369 370 /* Use MAX_VRF_ID to store VRF_OVERRIDE routes debug info */ 371 alpm_vrf_handle_t *alpm_vrf_handle[SOC_MAX_NUM_DEVICES]; 372 373 alpm_pivot_t **tcam_pivot[SOC_MAX_NUM_DEVICES]; 374 375 STATIC int 376 _soc_alpm_sw_propagate_required(int unit) 377 { 378 int i, mem_cnt; 379 soc_mem_t mem_chk[] = { 380 L3_DEFIPm, 381 L3_DEFIP_PAIR_128m, 382 L3_DEFIP_AUX_TABLEm 383 }; 384 385 mem_cnt = sizeof(mem_chk) / sizeof(mem_chk[0]); 386 for (i = 0; i < mem_cnt; i++) { 387 if (soc_mem_cache_get(unit, mem_chk[i], MEM_BLOCK_ANY)) { 388 return TRUE; 389 } 390 } 391 return FALSE; 392 } 393 394 STATIC int 395 _soc_alpm_ctrl_init(int u) 396 { 397 sal_memset(&ALPM_CTRL(u), 0, sizeof(_soc_alpm_ctrl_t)); 398 399 ALPM_CTRL(u).trie_propagate = _soc_alpm_sw_propagate_required(u); 400 ALPM_CTRL(u).hit_bits_skip = soc_property_get(u, spn_L3_ALPM_HIT_SKIP, 0); 401 402 ALPM_CTRL(u).fld.key_mode0 = MODE0f; 403 ALPM_CTRL(u).fld.key_mode1 = MODE1f; 404 ALPM_CTRL(u).fld.key_mode_mask0 = MODE_MASK0f; 405 ALPM_CTRL(u).fld.key_mode_mask1 = MODE_MASK1f; 406 ALPM_CTRL(u).fld.key_type0 = ENTRY_TYPE0f; 407 ALPM_CTRL(u).fld.key_type1 = ENTRY_TYPE1f; 408 ALPM_CTRL(u).fld.key_type_mask0 = ENTRY_TYPE_MASK0f; 409 ALPM_CTRL(u).fld.key_type_mask1 = ENTRY_TYPE_MASK1f; 410 ALPM_CTRL(u).fld.key_mode0_upr = MODE0_UPRf; 411 ALPM_CTRL(u).fld.key_mode0_lwr = MODE0_LWRf; 412 ALPM_CTRL(u).fld.key_mode1_upr = MODE1_UPRf; 413 ALPM_CTRL(u).fld.key_mode1_lwr = MODE1_LWRf; 414 ALPM_CTRL(u).fld.key_mode_mask0_upr = MODE_MASK0_UPRf; 415 ALPM_CTRL(u).fld.key_mode_mask0_lwr = MODE_MASK0_LWRf; 416 ALPM_CTRL(u).fld.key_mode_mask1_upr = MODE_MASK1_UPRf; 417 ALPM_CTRL(u).fld.key_mode_mask1_lwr = MODE_MASK1_LWRf; 418 ALPM_CTRL(u).fld.key_type0_upr = ENTRY_TYPE0_UPRf; 419 ALPM_CTRL(u).fld.key_type0_lwr = ENTRY_TYPE0_LWRf; 420 ALPM_CTRL(u).fld.key_type1_upr = ENTRY_TYPE1_UPRf; 421 ALPM_CTRL(u).fld.key_type1_lwr = ENTRY_TYPE1_LWRf; 422 ALPM_CTRL(u).fld.key_type_mask0_upr = ENTRY_TYPE_MASK0_UPRf; 423 ALPM_CTRL(u).fld.key_type_mask0_lwr = ENTRY_TYPE_MASK0_LWRf; 424 ALPM_CTRL(u).fld.key_type_mask1_upr = ENTRY_TYPE_MASK1_UPRf; 425 ALPM_CTRL(u).fld.key_type_mask1_lwr = ENTRY_TYPE_MASK1_LWRf; 426 ALPM_CTRL(u).fld.key_mode = MODEf; 427 ALPM_CTRL(u).fld.key_type = ENTRY_TYPEf; 428 429 ALPM_CTRL(u).ctrl_inited = 1; 430 return SOC_E_NONE; 431 } 432 433 STATIC int 434 _soc_alpm_sw_propagate(int u, trie_t *pivot, void *prefix, uint32 len, 435 int insert, void *cb, void *user_data) 436 { 437 int rv = SOC_E_NONE; 438 uint32 pivot_len = 0; 439 trie_node_t *lpm_pvt = NULL; 440 trie_bpm_cb_info_t cb_info; 441 442 cb_info.pfx = (void *)prefix; 443 cb_info.len = len; 444 cb_info.user_data = user_data; 445 446 /* Find longest prefix match(pivot) of route */ 447 SOC_IF_ERROR_RETURN(trie_find_lpm(pivot, prefix, len, &lpm_pvt)); 448 pivot_len = (TRIE_ELEMENT_GET(payload_t *, lpm_pvt, node))->len; 449 450 if (pivot->v6_key) { 451 rv = pvt_trie_v6_propagate_prefix(lpm_pvt, pivot_len, 452 (void *)prefix, len, cb, &cb_info); 453 } else { 454 rv = pvt_trie_propagate_prefix(lpm_pvt, pivot_len, 455 (void *)prefix, len, cb, &cb_info); 456 } 457 458 return rv; 459 } 460 461 STATIC int 462 _soc_alpm_propagate_callback(trie_node_t *trie, 463 trie_bpm_cb_info_t *info) 464 { 465 int rv = SOC_E_NONE; 466 int i, unit, mode; 467 trie_bpm_cb_user_data_t *user_data; 468 void *aux_entry; 469 alpm_pivot_t *pivot_pyld; 470 int tcam_index, lpm_index, aux_index; 471 int aux_flags; 472 473 /* use memory size to declear replace_data field value */ 474 defip_aux_scratch_entry_t replace_data; 475 soc_mem_t aux_mem = L3_DEFIP_AUX_SCRATCHm; 476 477 /* L3_DEFIP_AUX_TABLE variables */ 478 defip_aux_table_entry_t shadow_entry; 479 uint32 pfx_len, rpl_bpm_len, pvt_bpm_len; 480 481 #define _URPF_INDEX(urpf, index, mem) \ 482 (urpf ? (index + (soc_mem_index_count(unit, mem) >> 1)) : index) 483 484 user_data = info->user_data; 485 unit = user_data->unit; 486 aux_entry = user_data->entry; 487 aux_flags = user_data->flags; 488 489 /* For uRPF case, DB_TYPE is odd, see soc_alpm_db_ent_type_encoding */ 490 if (soc_mem_field32_get(unit, aux_mem, aux_entry, DB_TYPEf) & 0x1) { 491 return SOC_E_NONE; 492 } 493 494 pivot_pyld = (alpm_pivot_t *)trie; 495 pvt_bpm_len = PIVOT_TCAM_BPMLEN(pivot_pyld); 496 pfx_len = soc_mem_field32_get(unit, aux_mem, aux_entry, IP_LENGTHf); 497 498 /* Addr & Mask has been screened by propagate function, 499 * no need to do it again */ 500 if (user_data->aux_op == INSERT_PROPAGATE) { 501 if (pvt_bpm_len > pfx_len) { 502 /* Not qualified */ 503 return SOC_E_NONE; 504 } 505 } 506 507 if (user_data->aux_op == DELETE_PROPAGATE) { 508 if (pvt_bpm_len != pfx_len) { 509 /* Not qualified */ 510 return SOC_E_NONE; 511 } 512 } 513 514 rpl_bpm_len = soc_mem_field32_get(unit, aux_mem, aux_entry, REPLACE_LENf); 515 if (user_data->aux_op == INSERT_PROPAGATE) { 516 rpl_bpm_len = pfx_len; 517 } 518 519 /* Update bpm length accordingly */ 520 PIVOT_TCAM_BPMLEN(pivot_pyld) = rpl_bpm_len; 521 522 /* update callback count, hw propagate is counting on this */ 523 user_data->count ++; 524 525 sal_memset(&replace_data, 0, sizeof(replace_data)); 526 soc_mem_field_get(unit, aux_mem, aux_entry, REPLACE_DATAf, 527 (uint32 *)&replace_data); 528 mode = soc_mem_field32_get(unit, aux_mem, aux_entry, MODEf); 529 530 tcam_index = PIVOT_TCAM_INDEX(pivot_pyld); 531 if (mode == 0 || mode == 1) { 532 soc_mem_t lpm_mem = L3_DEFIPm; 533 defip_entry_t lpm_entry; 534 535 /* Update L3_DEFIPm */ 536 lpm_index = soc_alpm_logical_idx(unit, lpm_mem, tcam_index >> 1, 1); 537 aux_index = tcam_index >> 1; 538 539 LOG_INFO(BSL_LS_SOC_ALPM, 540 (BSL_META_U(unit, "ALPM SW %s ppg cb: lpm_mem %s index %d ent %d," 541 "AUX_TABLE index %d\n"), 542 (user_data->aux_op == INSERT_PROPAGATE) ? "Add" : "Del", 543 SOC_MEM_NAME(unit, lpm_mem), lpm_index, 544 (tcam_index & 1), aux_index)); 545 546 soc_mem_lock(unit, lpm_mem); 547 rv = _soc_mem_alpm_read_cache(unit, lpm_mem, MEM_BLOCK_ANY, 548 lpm_index, &lpm_entry); 549 if (SOC_SUCCESS(rv)) { 550 if (mode == 1) { 551 /* IPv6_64 */ 552 soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry, 553 REPLACE_DATA0f, (uint32 *)&replace_data); 554 } else { 555 /* IPv4 */ 556 soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry, 557 (tcam_index & 1) ? REPLACE_DATA1f : REPLACE_DATA0f, 558 (uint32 *)&replace_data); 559 } 560 _soc_mem_alpm_write_cache(unit, lpm_mem, MEM_BLOCK_ALL, 561 lpm_index, &lpm_entry); 562 if (SOC_URPF_STATUS_GET(unit)) { 563 lpm_index = _URPF_INDEX(TRUE, lpm_index, L3_DEFIPm); 564 (void)_soc_mem_alpm_read_cache(unit, lpm_mem, MEM_BLOCK_ANY, 565 lpm_index, &lpm_entry); 566 if (mode == 1) { 567 soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry, 568 REPLACE_DATA0f, (uint32 *)&replace_data); 569 soc_mem_field32_set(unit, lpm_mem, &lpm_entry, 570 RPE0f, (aux_flags & SOC_ALPM_AUX_DEF_ROUTE) ? 1 : 0); 571 soc_mem_field32_set(unit, lpm_mem, 572 &lpm_entry, SRC_DISCARD0f, 573 (aux_flags & SOC_ALPM_AUX_SRC_DISCARD) ? 1 : 0); 574 } else { 575 soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry, 576 (tcam_index & 1) ? REPLACE_DATA1f : REPLACE_DATA0f, 577 (uint32 *)&replace_data); 578 soc_mem_field32_set(unit, lpm_mem, &lpm_entry, 579 (tcam_index & 1) ? RPE1f : RPE0f, 580 (aux_flags & SOC_ALPM_AUX_DEF_ROUTE) ? 1 : 0); 581 soc_mem_field32_set(unit, lpm_mem, &lpm_entry, 582 (tcam_index & 1) ? SRC_DISCARD1f : SRC_DISCARD0f, 583 (aux_flags & SOC_ALPM_AUX_SRC_DISCARD) ? 1 : 0); 584 } 585 _soc_mem_alpm_write_cache(unit, lpm_mem, MEM_BLOCK_ALL, 586 lpm_index, &lpm_entry); 587 } 588 } 589 soc_mem_unlock(unit, lpm_mem); 590 591 /* Update L3_DEFIP_AUX_TABLEm */ 592 lpm_mem = L3_DEFIP_AUX_TABLEm; 593 594 soc_mem_lock(unit, lpm_mem); 595 rv = _soc_mem_alpm_read_cache(unit, lpm_mem, MEM_BLOCK_ANY, 596 aux_index, &shadow_entry); 597 if (SOC_SUCCESS(rv)) { 598 if (mode == 1) { /* IPv6_64 */ 599 soc_mem_field32_set(unit, lpm_mem, &shadow_entry, 600 BPM_LENGTH0f, rpl_bpm_len); 601 soc_mem_field32_set(unit, lpm_mem, &shadow_entry, 602 BPM_LENGTH1f, rpl_bpm_len); 603 } else { /* IPv4 */ 604 soc_mem_field32_set(unit, lpm_mem, &shadow_entry, 605 (tcam_index & 1) ? BPM_LENGTH1f : BPM_LENGTH0f, 606 rpl_bpm_len); 607 } 608 _soc_mem_alpm_write_cache(unit, lpm_mem, MEM_BLOCK_ALL, 609 aux_index, &shadow_entry); 610 if (SOC_URPF_STATUS_GET(unit)) { 611 aux_index = _URPF_INDEX(TRUE, aux_index, L3_DEFIP_AUX_TABLEm); 612 (void)_soc_mem_alpm_read_cache(unit, lpm_mem, MEM_BLOCK_ANY, 613 aux_index, &shadow_entry); 614 if (mode == 1) { /* IPv6_64 */ 615 soc_mem_field32_set(unit, lpm_mem, &shadow_entry, 616 BPM_LENGTH0f, rpl_bpm_len); 617 soc_mem_field32_set(unit, lpm_mem, &shadow_entry, 618 BPM_LENGTH1f, rpl_bpm_len); 619 } else { /* IPv4 */ 620 soc_mem_field32_set(unit, lpm_mem, &shadow_entry, 621 (tcam_index & 1) ? BPM_LENGTH1f : BPM_LENGTH0f, 622 rpl_bpm_len); 623 } 624 _soc_mem_alpm_write_cache(unit, lpm_mem, MEM_BLOCK_ALL, 625 aux_index, &shadow_entry); 626 } 627 } 628 soc_mem_unlock(unit, lpm_mem); 629 630 } else if (mode == 3) { 631 soc_mem_t lpm128_mem = L3_DEFIP_PAIR_128m; 632 defip_pair_128_entry_t lpm128_entry; 633 634 lpm_index = soc_alpm_logical_idx(unit, L3_DEFIP_PAIR_128m, 635 SOC_ALPM_128_DEFIP_TO_PAIR(unit, tcam_index >> 1), 1); 636 aux_index = SOC_ALPM_128_DEFIP_TO_PAIR(unit, tcam_index >> 1); 637 LOG_INFO(BSL_LS_SOC_ALPM, 638 (BSL_META_U(unit, "ALPM SW %s ppg cb: lpm_mem %s index %d, " 639 "AUX_TABLE index0 %d index1 %d\n"), 640 (user_data->aux_op == INSERT_PROPAGATE) ? "Add" : "Del", 641 SOC_MEM_NAME(unit, lpm128_mem), lpm_index, 642 SOC_ALPM_128_ADDR_LWR(unit, aux_index), 643 SOC_ALPM_128_ADDR_UPR(unit, aux_index))); 644 645 /* Update L3_DEFIP_PAIR_128m */ 646 soc_mem_lock(unit, lpm128_mem); 647 rv = _soc_mem_alpm_read_cache(unit, lpm128_mem, MEM_BLOCK_ANY, 648 lpm_index, &lpm128_entry); 649 if (SOC_SUCCESS(rv)) { 650 soc_mem_field_set(unit, lpm128_mem, (uint32 *)&lpm128_entry, 651 REPLACE_DATAf, (uint32 *)&replace_data); 652 _soc_mem_alpm_write_cache(unit, lpm128_mem, MEM_BLOCK_ALL, 653 lpm_index, &lpm128_entry); 654 if (SOC_URPF_STATUS_GET(unit)) { 655 lpm_index = _URPF_INDEX(TRUE, lpm_index, L3_DEFIP_PAIR_128m); 656 (void)_soc_mem_alpm_read_cache(unit, lpm128_mem, MEM_BLOCK_ANY, 657 lpm_index, &lpm128_entry); 658 soc_mem_field_set(unit, lpm128_mem, (uint32 *)&lpm128_entry, 659 REPLACE_DATAf, (uint32 *)&replace_data); 660 soc_mem_field32_set(unit, lpm128_mem, &lpm128_entry, 661 RPEf, (aux_flags & SOC_ALPM_AUX_DEF_ROUTE) ? 1 : 0); 662 soc_mem_field32_set(unit, lpm128_mem, 663 &lpm128_entry, SRC_DISCARDf, 664 (aux_flags & SOC_ALPM_AUX_SRC_DISCARD) ? 1 : 0); 665 _soc_mem_alpm_write_cache(unit, lpm128_mem, MEM_BLOCK_ALL, 666 lpm_index, &lpm128_entry); 667 } 668 } 669 soc_mem_unlock(unit, lpm128_mem); 670 671 /* Update L3_DEFIP_AUX_TABLEm */ 672 lpm128_mem = L3_DEFIP_AUX_TABLEm; 673 674 soc_mem_lock(unit, lpm128_mem); 675 /* Needs to update 2 AUX_TABLE entries */ 676 for (i = 0; i < 2; i++) { 677 int index; 678 index = ((i == 0) ? 679 SOC_ALPM_128_ADDR_LWR(unit, aux_index) : 680 SOC_ALPM_128_ADDR_UPR(unit, aux_index)); 681 rv = _soc_mem_alpm_read_cache(unit, lpm128_mem, MEM_BLOCK_ANY, 682 index, &shadow_entry); 683 if (SOC_SUCCESS(rv)) { 684 soc_mem_field32_set(unit, lpm128_mem, &shadow_entry, 685 BPM_LENGTH0f, rpl_bpm_len); 686 soc_mem_field32_set(unit, lpm128_mem, &shadow_entry, 687 BPM_LENGTH1f, rpl_bpm_len); 688 _soc_mem_alpm_write_cache(unit, lpm128_mem, MEM_BLOCK_ALL, 689 index, &shadow_entry); 690 if (SOC_URPF_STATUS_GET(unit)) { 691 index = _URPF_INDEX(TRUE, index, lpm128_mem); 692 (void)_soc_mem_alpm_read_cache(unit, lpm128_mem, 693 MEM_BLOCK_ANY, index, &shadow_entry); 694 soc_mem_field32_set(unit, lpm128_mem, &shadow_entry, 695 BPM_LENGTH0f, rpl_bpm_len); 696 soc_mem_field32_set(unit, lpm128_mem, &shadow_entry, 697 BPM_LENGTH1f, rpl_bpm_len); 698 _soc_mem_alpm_write_cache(unit, lpm128_mem, MEM_BLOCK_ALL, 699 index, &shadow_entry); 700 } 701 } 702 } 703 soc_mem_unlock(unit, lpm128_mem); 704 } else { 705 return SOC_E_INTERNAL; 706 } 707 708 return SOC_E_NONE; 709 } 710 711 /* 712 * ipv4: ip6_word[4] = 713 * {IP_ADDR0f, 0, 0, 0} 714 * ipv6-64: ip6_word[4] = 715 * {0, 0, IP_ADDR0f, IP_ADDR1f} 716 * ipv6-128: ip6_word[4] = 717 * {IP_ADDR0_LWRf, IP_ADDR1_LWRf, IP_ADDR0_UPRf, IP_ADDR1_UPRf} 718 */ 719 STATIC void 720 _soc_alpm_trie_prefix_create(int u, int mode, uint32 *ip6_word, uint32 len, 721 uint32 *pfx) 722 { 723 int i; 724 uint32 pfx_shift, tmp; 725 726 pfx[0] = pfx[1] = pfx[2] = pfx[3] = pfx[4] = 0; 727 /* Obtain prefix length */ 728 if (mode == 0) { 729 pfx[1] = SHR_SHIFT_RIGHT(ip6_word[0], 32 - len); 730 pfx[0] = 0; 731 } else if (mode == 1) { 732 pfx[4] = ip6_word[2]; 733 pfx[3] = ip6_word[3]; 734 735 pfx_shift = 64 - len; 736 if (pfx_shift < 32) { 737 /* get lower half shifted */ 738 pfx[4] >>= pfx_shift; 739 /* isolate shifted stuff of upper half */ 740 tmp = SHR_SHIFT_LEFT(pfx[3], 32 - pfx_shift); 741 pfx[3] >>= pfx_shift; 742 pfx[4] |= tmp; 743 } else { 744 pfx[4] = SHR_SHIFT_RIGHT(pfx[3], pfx_shift - 32); 745 pfx[3] = 0; 746 } 747 } else { 748 /* PAIR_128 style, for both mode==2 and mode==3 */ 749 int start; 750 uint32 tmp_pfx[5] = {0}; 751 tmp_pfx[0] = ip6_word[0]; 752 tmp_pfx[1] = ip6_word[1]; 753 tmp_pfx[2] = ip6_word[2]; 754 tmp_pfx[3] = ip6_word[3]; 755 756 /* shift entire prefix right to remove trailing 0s in prefix */ 757 /* to simplify, words which are all 0s are ignored to begin with, so 758 * a right shift of say 46 is a right shift of 46-32 = 14, but starting 759 * from word 1. Once all shifting is done, shift all words to right by 1 760 */ 761 pfx_shift = 128 - len; 762 start = pfx_shift / 32; 763 pfx_shift = pfx_shift % 32; 764 for (i = start; i < 4; i++) { 765 tmp_pfx[i] >>= pfx_shift; 766 tmp = tmp_pfx[i+1] & ((1 << pfx_shift) - 1); 767 tmp = SHR_SHIFT_LEFT(tmp, 32 - pfx_shift); 768 tmp_pfx[i] |= tmp; 769 } 770 /* make shift right justified and also reverse order for trie. 771 * Also, note trie sees key only in words 1 to 4 772 */ 773 for (i = start; i < 4; i++) { 774 pfx[4 - (i - start)] = tmp_pfx[i]; 775 } 776 } 777 return ; 778 } 779 780 /* Create prefix & len in trie format from aux entry */ 781 STATIC void 782 _soc_alpm_aux_prefix_create(int u, void *aux_entry, uint32 *pfx, uint32 *len) 783 { 784 uint32 ip6_word[4]; 785 int mode; 786 soc_mem_t aux_mem = L3_DEFIP_AUX_SCRATCHm; 787 788 soc_mem_field_get(u, aux_mem, aux_entry, IP_ADDRf, (uint32 *)ip6_word); 789 *len = soc_mem_field32_get(u, aux_mem, aux_entry, IP_LENGTHf); 790 mode = soc_mem_field32_get(u, aux_mem, aux_entry, MODEf); 791 792 return _soc_alpm_trie_prefix_create(u, mode, ip6_word, *len, pfx); 793 } 794 795 /* Software propagation */ 796 STATIC int 797 _soc_alpm_aux_sw_op(int u, _soc_aux_op_t aux_op, void *aux_entry, 798 int *match_cnt, int aux_flags) 799 { 800 trie_t *pivot; 801 int rv = SOC_E_NONE; 802 int vld, mode, dbt, vrf = 0; 803 uint32 prefix[5]; 804 uint32 len; 805 trie_bpm_cb_user_data_t user_data; 806 soc_mem_t aux_mem = L3_DEFIP_AUX_SCRATCHm; 807 int insert = 0; 808 809 switch (aux_op) { 810 case INSERT_PROPAGATE: 811 insert = 1; 812 break; 813 case DELETE_PROPAGATE: 814 insert = 0; 815 break; 816 case HITBIT_REPLACE: 817 case PREFIX_LOOKUP: 818 default: 819 return SOC_E_NONE; 820 } 821 822 vld = soc_mem_field32_get(u, aux_mem, aux_entry, VALIDf); 823 mode = soc_mem_field32_get(u, aux_mem, aux_entry, MODEf); 824 vrf = soc_mem_field32_get(u, aux_mem, aux_entry, VRFf); 825 dbt = soc_mem_field32_get(u, aux_mem, aux_entry, DB_TYPEf); 826 827 /* Need to distinguish vrf=0 and Global low */ 828 if ((vrf == 0) && (dbt <= 1)) { 829 vrf = SOC_VRF_MAX(u) + 1; 830 } 831 832 /* Mode indicates entry type: 00:IPv4, 01: 64-Ipv6, 11: IPv6-128 */ 833 if (mode == 0) { 834 pivot = VRF_PIVOT_TRIE_IPV4(u, vrf); 835 } else if (mode == 1) { 836 pivot = VRF_PIVOT_TRIE_IPV6(u, vrf); 837 } else if (mode == 3) { 838 pivot = VRF_PIVOT_TRIE_IPV6_128(u, vrf); 839 } else { 840 return SOC_E_INTERNAL; 841 } 842 843 _soc_alpm_aux_prefix_create(u, aux_entry, (void *)prefix, &len); 844 845 sal_memset(&user_data, 0, sizeof(user_data)); 846 user_data.unit = u; 847 user_data.entry = aux_entry; 848 user_data.aux_op = aux_op; 849 user_data.flags = aux_flags; 850 851 if (vld && pivot) { 852 rv = _soc_alpm_sw_propagate(u, pivot, prefix, len, insert, 853 _soc_alpm_propagate_callback, &user_data); 854 } 855 856 if (insert) { 857 soc_alpm_dbg_cnt[u].ppg_cb_insert += user_data.count; 858 } else { 859 soc_alpm_dbg_cnt[u].ppg_cb_delete += user_data.count; 860 } 861 862 if (match_cnt != NULL) { 863 *match_cnt = user_data.count; 864 } 865 866 return rv; 867 868 } 869 870 871 /* returns 0 for Combined Search mode and 1 for Parallel Search mode */ 872 int 873 soc_alpm_mode_get(int u) 874 { 875 if (soc_trident2_alpm_mode_get(u) == 1) { 876 return 1; 877 } else { 878 return 0; 879 } 880 } 881 882 883 int 884 _soc_alpm_mask_len_get(int u, int ipv6, void *entry, int *pfx) 885 { 886 int rv; 887 uint32 ipv4a; 888 889 if (ipv6) { 890 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f); 891 if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) { 892 return(rv); 893 } 894 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK1f); 895 if (*pfx) { 896 if (ipv4a != 0xffffffff) { 897 return(SOC_E_PARAM); 898 } 899 *pfx += 32; 900 } else { 901 if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) { 902 return(rv); 903 } 904 } 905 } else { 906 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f); 907 if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) { 908 return(rv); 909 } 910 } 911 912 return SOC_E_NONE; 913 } 914 915 /** 916 * Tomahawk & Trident2+ ALPM VRF[10], VRF[11] bit WAR, Trident2 no change. 917 * Need to handle Warmboot as well. 918 * 919 * TH's Pivot Scan Engine is not comparing bit 10 of the VRF[10:0]. 920 * TD2+ also has this issue, it's Pivot Scan Engine is not comparing 921 * bits 11:10 of VRF[11:0] 922 * 923 * Proposed WAR: 924 * New DB_TYPE encodings. In TD2+ we sacrifice FCOE(ENTRY_TYPE=1) entry support 925 * to get 4K VRF support. 926 * 927 * Tips for future FCoE implementation: 928 * Mark VALID0/1 bits to 0 for FCoE entries, so we don't actually care 929 * ENTRY_TYPE bits in L3_DEFIP_AUX_TABLE, like Global High routes. 930 * 931 * ---------------------------------------------------------- 932 * | | No uRPF | uRPF | 933 * ---------------------------------------------------------- 934 * | DB_TYPE(Global) | 0 | 1 | 935 * ---------------------------------------------------------- 936 * | DB_TYPE(VRF0-1023) | 2 | 3 | TD2 937 * ------------------------------------------------------------------- 938 * | DB_TYPE(VRF1024-2047) | 4 | 5 | TH 939 * ------------------------------------------------------------------- 940 * | DB_TYPE(VRF2048-3071) | 6 | 7 | 941 * ---------------------------------------------------------- 942 * | DB_TYPE(VRF3072-4095) | 4+EntType=1 | 5+EntType=1 | TD2+ 943 * ------------------------------------------------------------------- 944 */ 945 void 946 soc_alpm_db_ent_type_encoding(int u, int vrf, uint32 *db_type, uint32 *ent_type) 947 { 948 int dbt, ent, vrf_msb; 949 uint32 db_type_conf[4] = {2, 4, 6, 4}; 950 uint32 en_type_conf[4] = {0, 0, 0, 1}; 951 952 /* Global Low routes always use db_type 0 */ 953 if (vrf == (SOC_VRF_MAX(u) + 1)) { 954 dbt = 0; 955 ent = 0; 956 } else if (SOC_IS_TRIDENT2PLUS(u) || SOC_IS_TOMAHAWKX(u)) { 957 /* TD2+ and TH */ 958 vrf_msb = (vrf >> 10) & 0x3; 959 dbt = db_type_conf[vrf_msb]; 960 ent = en_type_conf[vrf_msb]; 961 } else { 962 /* other chips including TD2 (TD2,TH+,TH2,AP...) */ 963 dbt = 2; 964 ent = 0; 965 } 966 967 if (db_type != NULL) { 968 *db_type = dbt; 969 } 970 971 if (ent_type != NULL) { 972 *ent_type = ent; 973 } 974 975 return ; 976 } 977 978 int 979 _soc_alpm_rpf_entry(int u, int idx) 980 { 981 int bkt; 982 bkt = (idx >> 2) & 0x3fff; 983 bkt += SOC_ALPM_BUCKET_COUNT(u); 984 /* form rpf alpm entry index */ 985 return (idx & ~(0x3fff << 2)) | (bkt << 2); 986 } 987 988 /* for v4 full = 0, for v6-64 full = 1 */ 989 int 990 soc_alpm_physical_idx(int u, soc_mem_t mem, int index, int full) 991 { 992 int tmp = index & 1; 993 994 if (full) { 995 return soc_trident2_l3_defip_index_map(u, mem, index); 996 } 997 index >>= 1; 998 index = soc_trident2_l3_defip_index_map(u, mem, index); 999 index <<= 1; 1000 index |= tmp; 1001 return index; 1002 } 1003 1004 int 1005 soc_alpm_logical_idx(int u, soc_mem_t mem, int index, int full) 1006 { 1007 int tmp = index & 1; 1008 1009 if (full) { 1010 return soc_trident2_l3_defip_index_remap(u, mem, index); 1011 } 1012 index >>= 1; 1013 index = soc_trident2_l3_defip_index_remap(u, mem, index); 1014 index <<= 1; 1015 index |= tmp; 1016 return index; 1017 } 1018 1019 static void 1020 _soc_alpm_pfx_len_to_mask(int u, void *lpm_entry, int len, int ipv6) 1021 { 1022 uint32 mask = 0; 1023 1024 if (ipv6) { 1025 if (len >= 32) { 1026 mask = 0xffffffff; 1027 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, mask); 1028 mask = ~SHR_SHIFT_RIGHT(0xffffffff, len - 32); 1029 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, mask); 1030 } else { 1031 mask = ~(0xffffffff >> len); 1032 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, mask); 1033 /* make sure lower word of mask is 0 */ 1034 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, 0); 1035 } 1036 } else { 1037 assert(len <= 32); 1038 mask = (len == 32) ? 0xffffffff : ~(0xffffffff >> len); 1039 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, mask); 1040 } 1041 } 1042 /* Create Prefix */ 1043 /* Prefix is created based on the trie key packing expectations */ 1044 /* Prefix[0] will have higher order Word, Prefix[1] will have lower order word 1045 * in case of IPV6. For IPV4 prefix[0] will contain the prefix 1046 */ 1047 static int 1048 _alpm_prefix_create(int u, void *entry, uint32 *prefix, uint32 *pfx_len, 1049 int *default_route) 1050 { 1051 int ip, ip_mask, ipv6; 1052 int pfx = 0; 1053 int rv = SOC_E_NONE; 1054 uint32 pfx_shift, tmp; 1055 1056 prefix[0] = prefix[1] = prefix[2] = prefix[3] = prefix[4] = 0; 1057 1058 ipv6 = soc_mem_field32_get(u, L3_DEFIPm, entry, MODE0f); 1059 1060 /* Form Prefix based on the entry */ 1061 ip = soc_mem_field32_get(u, L3_DEFIPm, entry, IP_ADDR0f); 1062 ip_mask = soc_mem_field32_get(u, L3_DEFIPm, entry, IP_ADDR_MASK0f); 1063 1064 prefix[1] = ip; 1065 1066 ip = soc_mem_field32_get(u, L3_DEFIPm, entry, IP_ADDR1f); 1067 ip_mask = soc_mem_field32_get(u, L3_DEFIPm, entry, IP_ADDR_MASK1f); 1068 1069 prefix[0] = ip; 1070 1071 /* Obtain prefix length */ 1072 if (ipv6) { 1073 prefix[4] = prefix[1]; 1074 prefix[3] = prefix[0]; 1075 prefix[1] = prefix[0] = 0; 1076 ip_mask = soc_mem_field32_get(u, L3_DEFIPm, entry, IP_ADDR_MASK0f); 1077 if ((rv = _ipmask2pfx(ip_mask, &pfx)) < 0) { 1078 return(rv); 1079 } 1080 ip_mask = soc_mem_field32_get(u, L3_DEFIPm, entry, IP_ADDR_MASK1f); 1081 if (pfx) { 1082 if (ip_mask != 0xffffffff) { 1083 return(SOC_E_PARAM); 1084 } 1085 pfx += 32; 1086 } else { 1087 if ((rv = _ipmask2pfx(ip_mask, &pfx)) < 0) { 1088 return(rv); 1089 } 1090 } 1091 pfx_shift = 64 - pfx; 1092 if (pfx_shift < 32) { 1093 /* get lower half shifted */ 1094 prefix[4] >>= pfx_shift; 1095 /* isolate shifted stuff of upper half */ 1096 tmp = SHR_SHIFT_LEFT(prefix[3], 32 - pfx_shift); 1097 prefix[3] >>= pfx_shift; 1098 prefix[4] |= tmp; 1099 } else { 1100 prefix[4] = SHR_SHIFT_RIGHT(prefix[3], pfx_shift - 32); 1101 prefix[3] = 0; 1102 } 1103 } else { 1104 ip_mask = soc_mem_field32_get(u, L3_DEFIPm, entry, IP_ADDR_MASK0f); 1105 if ((rv = _ipmask2pfx(ip_mask, &pfx)) < 0) { 1106 return(rv); 1107 } 1108 prefix[1] = SHR_SHIFT_RIGHT(prefix[1], 32 - pfx); 1109 prefix[0] = 0; 1110 } 1111 *pfx_len = pfx; 1112 *default_route = (prefix[0] == 0) && (prefix[1] == 0) && (pfx == 0); 1113 return SOC_E_NONE; 1114 } 1115 1116 #if 0 1117 extern int sh_process_command(int u,char * c); 1118 extern void soc_alpm_lpm_sw_dump(int unit); 1119 void soc_debug_collect(int u, int vrf, int v6, soc_mem_t mem, void *entry) 1120 { 1121 int i; 1122 1123 sh_process_command(u, "debug ="); 1124 1125 LOG_CLI(("\n====Collecting info for unit(%d), vrf(%d), v6(%d), mem(%s), entry(%p)\n", 1126 u, vrf, v6, SOC_MEM_NAME(u, mem), entry)); 1127 1128 /* Dump system configuration */ 1129 LOG_CLI(("\n====Dumping current config.bcm\n")); 1130 sh_process_command(u, "config show"); 1131 1132 /* Debug counter */ 1133 LOG_CLI(("\n====Dumping ALPM debug counters\n")); 1134 for (i = 0; i < DEBUG_VAR_NUMBER; i++) { 1135 if (debug_var2[i] != 0) { 1136 LOG_CLI(("debug_var2[%2d] = %d\n", i, debug_var2[i])); 1137 } 1138 } 1139 1140 /* Dump current entry */ 1141 if (entry != NULL) { 1142 LOG_CLI(("\n====Dumping ALPM current operating entry\n")); 1143 soc_mem_entry_dump_if_changed(u, mem, entry, "ALPM-DBG: "); 1144 } 1145 1146 /* Dump ALPM Memories */ 1147 LOG_CLI(("\n====Dumping ALPM memories\n")); 1148 sh_process_command(u, "d chg L3_DEFIP"); 1149 sh_process_command(u, "d chg L3_DEFIP_pair_128"); 1150 sh_process_command(u, "d chg L3_DEFIP_aux_table"); 1151 sh_process_command(u, "d chg L3_DEFIP_AUX_SCRATCH"); 1152 sh_process_command(u, "d chg L3_DEFIP_alpm_ipv4"); 1153 sh_process_command(u, "d chg L3_DEFIP_alpm_ipv6_64"); 1154 sh_process_command(u, "d chg L3_DEFIP_alpm_ipv6_128"); 1155 1156 /* Dump Pivot trie */ 1157 LOG_CLI(("\n====Dumping ALPM Pivot trie-tree for VRF %d\n", vrf)); 1158 trie_dump(v6 ? VRF_PIVOT_TRIE_IPV6_128(u, vrf) : VRF_PIVOT_TRIE_IPV4(u, vrf), 1159 NULL, NULL); 1160 1161 /* Dump VRF trie */ 1162 LOG_CLI(("\n====Dumping VRF route trie-tree for VRF %d\n", vrf)); 1163 trie_dump(v6 ? VRF_PREFIX_TRIE_IPV6_128(u, vrf) : VRF_PREFIX_TRIE_IPV4(u, vrf), 1164 NULL, NULL); 1165 1166 /* Dump Bucket trie */ 1167 LOG_CLI(("\n====Dumping Bucket trie-tree for VRF %d\n", vrf)); 1168 for (i = 0; i < MAX_PIVOT_COUNT; i++) { 1169 if (ALPM_TCAM_PIVOT(u, i) != NULL) { 1170 trie_t *trie = PIVOT_BUCKET_TRIE(ALPM_TCAM_PIVOT(u, i)); 1171 LOG_CLI(("\t==Dumping Trie-tree for TCAM %d, index %d\n", i, 1172 soc_alpm_logical_idx(u, L3_DEFIPm, i >> 1, 1))); 1173 trie_dump(trie, NULL, NULL); 1174 } 1175 } 1176 1177 /* Dump ALPM LPM SW state */ 1178 LOG_CLI(("\n====Dumping ALPM LPM SW state\n")); 1179 soc_alpm_lpm_sw_dump(u); 1180 1181 /* Running Sanity check */ 1182 LOG_CLI(("\n====Running Bucket Sanity check\n")); 1183 soc_alpm_sanity_check(u, L3_DEFIPm, -1); 1184 1185 return ; 1186 } 1187 #endif 1188 1189 int 1190 _soc_alpm_find_in_bkt(int u, soc_mem_t mem, int bucket_index, int bank_disable, 1191 uint32 *e, void *alpm_data, int *key_index, int v6) 1192 { 1193 int rv; 1194 rv = soc_mem_alpm_lookup(u, mem, bucket_index, 1195 MEM_BLOCK_ANY, 1196 bank_disable, 1197 e, alpm_data, key_index); 1198 if (SOC_SUCCESS(rv)) { 1199 return rv; 1200 } 1201 if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) { 1202 return soc_mem_alpm_lookup(u, mem, bucket_index + 1, MEM_BLOCK_ANY, 1203 bank_disable, e, alpm_data, key_index); 1204 } 1205 return rv; 1206 } 1207 1208 1209 static int 1210 _soc_alpm_sw_pivot_find(int u, uint32 *prefix, uint32 length, int v6, int vrf, 1211 int *hit, int *tcam_index, int *bucket_index) 1212 { 1213 int rv = SOC_E_NONE; 1214 trie_t *pivot_trie; 1215 trie_node_t *lpmp = NULL; 1216 alpm_pivot_t *pivot_pyld; 1217 1218 if (v6) { 1219 pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf); 1220 } else { 1221 pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf); 1222 } 1223 rv = trie_find_lpm(pivot_trie, prefix, length, &lpmp); 1224 if (SOC_FAILURE(rv)) { 1225 LOG_ERROR(BSL_LS_SOC_ALPM, 1226 (BSL_META_U(u, 1227 "Pivot find failed\n"))); 1228 return rv; 1229 } 1230 pivot_pyld = (alpm_pivot_t *)lpmp; 1231 1232 *hit = 1; 1233 *tcam_index = PIVOT_TCAM_INDEX(pivot_pyld); 1234 *bucket_index = PIVOT_BUCKET_INDEX(pivot_pyld); 1235 1236 return SOC_E_NONE; 1237 } 1238 1239 uint32 1240 soc_alpm_bank_dis(int u, int vrf) 1241 { 1242 uint32 bank_disable; 1243 int global = (vrf == SOC_VRF_MAX(u) + 1) ? 1 : 0; 1244 if (soc_alpm_mode_get(u) == SOC_ALPM_MODE_PARALLEL && 1245 SOC_URPF_STATUS_GET(u)) { 1246 bank_disable = global ? 0x3 : 0xC; 1247 } else { 1248 bank_disable = 0; 1249 } 1250 return bank_disable; 1251 } 1252 1253 int 1254 _soc_alpm_sw_prefix_check(int u, 1255 soc_mem_t mem, /* Mem type for ALPM */ 1256 int v6, 1257 void *key_data, /* TCAM entry data */ 1258 int vrf_id, 1259 int vrf) 1260 { 1261 int rv = SOC_E_NONE; 1262 uint32 prefix[5], length; 1263 int default_route = 0; 1264 trie_t *pivot_trie, *bkt_trie; 1265 trie_node_t *lpmp = NULL; 1266 alpm_pivot_t *pivot_node; 1267 1268 if (vrf_id == 0) { 1269 if (soc_alpm_mode_get(u)) { 1270 /* cannot have 0 as a VRF in parallel mode */ 1271 return SOC_E_PARAM; 1272 } 1273 } 1274 1275 if (vrf_id != SOC_L3_VRF_OVERRIDE) { 1276 /* Create Prefix */ 1277 rv = _alpm_prefix_create(u, key_data, prefix, &length, 1278 &default_route); 1279 if (SOC_FAILURE(rv)) { 1280 LOG_ERROR(BSL_LS_SOC_ALPM, 1281 (BSL_META_U(u, 1282 "_soc_alpm_sw_prefix_check: prefix create failed\n"))); 1283 return rv; 1284 } 1285 1286 if (v6) { 1287 pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf); 1288 } else { 1289 pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf); 1290 } 1291 1292 rv = trie_find_lpm(pivot_trie, prefix, length, &lpmp); 1293 if (SOC_FAILURE(rv)) { 1294 LOG_ERROR(BSL_LS_SOC_ALPM, 1295 (BSL_META_U(u, 1296 "_soc_alpm_sw_prefix_check: Pivot find failed\n"))); 1297 return rv; 1298 } 1299 pivot_node = (alpm_pivot_t *)lpmp; 1300 bkt_trie = pivot_node->bucket->bucket_trie; 1301 if (bkt_trie != NULL) { 1302 rv = trie_search(bkt_trie, prefix, length, 1303 (trie_node_t **)&bkt_trie); 1304 if (SOC_FAILURE(rv)){ 1305 LOG_ERROR(BSL_LS_SOC_ALPM, 1306 (BSL_META_U(u, 1307 "_soc_alpm_sw_prefix_check: prefix find failed\n"))); 1308 } 1309 } else { 1310 LOG_ERROR(BSL_LS_SOC_ALPM, 1311 (BSL_META_U(u, 1312 "_soc_alpm_sw_prefix_check: bkt trie doesn't exist\n"))); 1313 } 1314 } 1315 return rv; 1316 } 1317 1318 /* 1319 * Find and read the match in the database. 1320 * Returns SOC_E_NONE, if found. 1321 * SOC_E_NOT_FOUND if not found 1322 * SOC_E_FAIL, if lookup failed. 1323 */ 1324 static int 1325 _soc_alpm_find(int u, 1326 void *key_data, /* TCAM entry data */ 1327 soc_mem_t mem, /* Mem type for ALPM */ 1328 void *alpm_data, /* Alpm data if match */ 1329 int *tcam_index, /* TCAM INDEX */ 1330 int *bucket_index, /* return Bucket Index*/ 1331 int *index_ptr, /* return key location */ 1332 int sw_find /* 1: search from trie, 0: search from aux */ 1333 ) 1334 { 1335 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 1336 int vrf_id, vrf, v6; 1337 int key_index ; 1338 uint32 db_type, ent_type, bank_disable; 1339 int rv = SOC_E_NONE; 1340 int hit = 0; 1341 1342 v6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0f); 1343 if (v6) { 1344 if (!(v6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE1f))) { 1345 return (SOC_E_PARAM); 1346 } 1347 } 1348 1349 SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf)); 1350 if (vrf_id == 0) { 1351 if (soc_alpm_mode_get(u)) { 1352 /* cannot have 0 as a VRF in parallel mode */ 1353 return SOC_E_PARAM; 1354 } 1355 } 1356 1357 soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type); 1358 bank_disable = soc_alpm_bank_dis(u, vrf); 1359 1360 /* For VRF_OVERRIDE (Global High) entries, software needs to maintain the 1361 * index */ 1362 /* Prefix resides in TCAM directly */ 1363 if (vrf_id != SOC_L3_VRF_OVERRIDE) { 1364 if (sw_find) { 1365 uint32 prefix[5], length; 1366 int default_route = 0; 1367 1368 /* Create Prefix */ 1369 rv = _alpm_prefix_create(u, key_data, prefix, &length, &default_route); 1370 if (SOC_FAILURE(rv)) { 1371 LOG_ERROR(BSL_LS_SOC_ALPM, 1372 (BSL_META_U(u, 1373 "_soc_alpm_insert: prefix create failed\n"))); 1374 1375 return rv; 1376 } 1377 1378 rv = _soc_alpm_sw_pivot_find(u, prefix, length, v6, vrf, &hit, 1379 tcam_index, bucket_index); 1380 SOC_IF_ERROR_RETURN(rv); 1381 } else { 1382 defip_aux_scratch_entry_t aux_entry; 1383 /* Fill in AUX Scratch and perform Lookup Operation */ 1384 SOC_IF_ERROR_RETURN( 1385 _soc_alpm_fill_aux_entry_for_op(u, key_data, v6, db_type, 1386 ent_type, 0, &aux_entry)); 1387 SOC_IF_ERROR_RETURN( 1388 _soc_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry, TRUE, &hit, 1389 tcam_index, bucket_index, 0)); 1390 } 1391 1392 if (hit) { /* Entry is found in the bucket_index */ 1393 /* Fill entry for lookup */ 1394 _soc_alpm_mem_ent_init(u, key_data, e, 0, mem, 0, 0); 1395 1396 /* Perform lookup */ 1397 rv = _soc_alpm_find_in_bkt(u, mem, *bucket_index, bank_disable, 1398 e, alpm_data, &key_index, v6); 1399 if (SOC_SUCCESS(rv)) { 1400 *index_ptr = key_index; 1401 } 1402 } else { 1403 rv = SOC_E_NOT_FOUND; 1404 } 1405 } 1406 return rv; 1407 } 1408 1409 1410 /* 1411 * Find and update the match in the database. 1412 * Returns SOC_E_NONE, if found and updated. 1413 * SOC_E_NOT_FOUND if not found 1414 * SOC_E_FAIL, if update failed. 1415 */ 1416 static int 1417 _soc_alpm_find_and_update(int u, 1418 void *key_data, /* TCAM entry data */ 1419 void *alpm_data, /* Alpm data to be updated with */ 1420 void *alpm_sip_data, 1421 soc_mem_t mem, /* Mem view for ALPM data */ 1422 int key_index) /* key location */ 1423 { 1424 defip_aux_scratch_entry_t aux_entry; 1425 int vrf_id, v6, vrf; 1426 int bucket_index; 1427 uint32 db_type, ent_type; 1428 int rv = SOC_E_NONE; 1429 int hit = 0, tmp = 0; 1430 int tcam_index; 1431 int aux_flags = 0; 1432 1433 v6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0f); 1434 if (v6) { 1435 if (!(v6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE1f))) { 1436 return (SOC_E_PARAM); 1437 } 1438 } 1439 1440 SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf)); 1441 soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type); 1442 1443 /* For VRF_OVERRIDE (Global High) entries */ 1444 if (vrf_id != SOC_L3_VRF_OVERRIDE) { 1445 /* Fill in AUX Scratch and perform Lookup Operation */ 1446 SOC_IF_ERROR_RETURN( 1447 _soc_alpm_fill_aux_entry_for_op(u, key_data, v6, db_type, ent_type, 1448 0, &aux_entry)); 1449 /* Perform lookup */ 1450 /* Update the entry */ 1451 SOC_IF_ERROR_RETURN( 1452 soc_mem_write(u, mem, MEM_BLOCK_ANY, key_index, 1453 alpm_data)); 1454 if (SOC_URPF_STATUS_GET(u)) { 1455 /* Update the sip entry */ 1456 SOC_IF_ERROR_RETURN(soc_mem_write(u, mem, MEM_BLOCK_ANY, 1457 _soc_alpm_rpf_entry(u, key_index), 1458 alpm_sip_data)); 1459 } 1460 /* set REPLACE_LEN field to correct value */ 1461 tmp = soc_mem_field32_get(u, L3_DEFIP_AUX_SCRATCHm, 1462 &aux_entry, IP_LENGTHf); 1463 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, &aux_entry, 1464 REPLACE_LENf, tmp); 1465 1466 if (SOC_URPF_STATUS_GET(u)) { 1467 if (soc_mem_field32_get(u, mem, alpm_sip_data, DEFAULTROUTEf)) { 1468 aux_flags |= SOC_ALPM_AUX_DEF_ROUTE; 1469 } 1470 if (soc_mem_field32_get(u, mem, alpm_sip_data, SRC_DISCARDf)) { 1471 aux_flags |= SOC_ALPM_AUX_SRC_DISCARD; 1472 } 1473 } 1474 1475 SOC_IF_ERROR_RETURN( 1476 _soc_alpm_aux_op(u, DELETE_PROPAGATE, &aux_entry, TRUE, 1477 &hit, &tcam_index, &bucket_index, aux_flags)); 1478 } 1479 return rv; 1480 } 1481 1482 1483 /* Callback function for Traverse, to find Leaf nodes */ 1484 int 1485 alpm_mem_prefix_array_cb(trie_node_t *node, void *info) 1486 { 1487 alpm_mem_prefix_array_t *prefix_array = (alpm_mem_prefix_array_t *)info; 1488 if (node->type == PAYLOAD) { 1489 prefix_array->prefix[prefix_array->count] = (payload_t *)node; 1490 prefix_array->count++; 1491 } 1492 return SOC_E_NONE; 1493 } 1494 1495 int 1496 alpm_delete_node_cb(trie_node_t *node, void *info) 1497 { 1498 if (node != NULL) { 1499 sal_free(node); 1500 } 1501 return SOC_E_NONE; 1502 } 1503 1504 1505 /* src and dst can be same */ 1506 static int 1507 _soc_alpm_aux_entry_convert(int u, void *src, void *dst, int convert) 1508 { 1509 soc_field_t f0[] = { 1510 VRF0f, 1511 MODE0f, 1512 VALID0f, 1513 IP_LENGTH0f, 1514 BPM_LENGTH0f, 1515 IP_ADDR0f, 1516 DB_TYPE0f, 1517 ENTRY_TYPE0f}; 1518 soc_field_t f1[] = { 1519 VRF1f, 1520 MODE1f, 1521 VALID1f, 1522 IP_LENGTH1f, 1523 BPM_LENGTH1f, 1524 IP_ADDR1f, 1525 DB_TYPE1f, 1526 ENTRY_TYPE1f}; 1527 soc_field_t *sf, *df; 1528 int i = 0; 1529 uint32 v; 1530 1531 switch (convert) { 1532 case 0: 1533 sf = f0; 1534 df = f0; 1535 break; 1536 case 1: 1537 sf = f0; 1538 df = f1; 1539 break; 1540 case 2: 1541 sf = f1; 1542 df = f0; 1543 break; 1544 case 3: 1545 sf = f1; 1546 df = f1; 1547 break; 1548 default: 1549 return SOC_E_INTERNAL; 1550 } 1551 1552 for (i = 0; i < COUNTOF(f0); i++) { 1553 v = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm, src, sf[i]); 1554 soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, dst, df[i], v); 1555 } 1556 1557 return SOC_E_NONE; 1558 } 1559 1560 1561 /* create shadow entry copy of primary tcam entry at index */ 1562 static int 1563 _soc_alpm_tcam_shadow_ent_init(int u, int s_index, int index, void *entry, 1564 int convert, void *shadow, int bpm_len, int v4_half) 1565 { 1566 uint32 tmp, ip_mask, v6, db_type, ent_type, urpf = 0; 1567 soc_mem_t mem = L3_DEFIPm; 1568 soc_mem_t s_mem = L3_DEFIP_AUX_TABLEm; 1569 defip_entry_t tmp_ipv4; 1570 int rv = SOC_E_NONE, pfx, pfx2, vrf_id, vrf_id2, vrf, vrf2; 1571 defip_aux_table_entry_t src_shadow; 1572 void *shadow_ptr = shadow; 1573 int flex_v6_64 = 0; 1574 1575 /* convert from logical to physical indices */ 1576 s_index = soc_alpm_physical_idx(u, L3_DEFIPm, s_index, 1); 1577 1578 if (convert == CONVERT_NONE) { 1579 SOC_IF_ERROR_RETURN(soc_mem_read(u, s_mem, MEM_BLOCK_ANY, s_index, 1580 shadow)); 1581 } else { 1582 tmp = soc_alpm_physical_idx(u, L3_DEFIPm, index, 1); 1583 SOC_IF_ERROR_RETURN(soc_mem_read(u, s_mem, MEM_BLOCK_ANY, tmp, 1584 shadow)); 1585 if (s_index != tmp) { 1586 SOC_IF_ERROR_RETURN(soc_mem_read(u, s_mem, MEM_BLOCK_ANY, s_index, 1587 &src_shadow)); 1588 shadow_ptr = (void*) &src_shadow; 1589 } 1590 1591 SOC_IF_ERROR_RETURN(_soc_alpm_aux_entry_convert(u, shadow_ptr, shadow, 1592 convert)); 1593 } 1594 1595 tmp = soc_mem_field32_get(u, mem, entry, VRF_ID_0f); 1596 soc_mem_field32_set(u, s_mem, shadow, VRF0f, tmp); 1597 tmp = soc_mem_field32_get(u, mem, entry, VRF_ID_1f); 1598 soc_mem_field32_set(u, s_mem, shadow, VRF1f, tmp); 1599 1600 tmp = soc_mem_field32_get(u, mem, entry, MODE0f); 1601 soc_mem_field32_set(u, s_mem, shadow, MODE0f, tmp); 1602 tmp = soc_mem_field32_get(u, mem, entry, MODE1f); 1603 soc_mem_field32_set(u, s_mem, shadow, MODE1f, tmp); 1604 v6 = tmp; 1605 1606 if (bpm_len == INVALID_BPM_LEN) { 1607 /* Clean dirty data */ 1608 if (soc_mem_field32_get(u, s_mem, shadow, VALID0f) == 0) { 1609 soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH0f, 0); 1610 } 1611 1612 if (soc_mem_field32_get(u, s_mem, shadow, VALID1f) == 0) { 1613 soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH1f, 0); 1614 } 1615 } else { 1616 assert(v6 == (v4_half==0)); 1617 if (v6) { 1618 soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH0f, bpm_len); 1619 soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH1f, bpm_len); 1620 } else { 1621 if (v4_half & 1) { 1622 soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH1f, bpm_len); 1623 } else { 1624 soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH0f, bpm_len); 1625 } 1626 } 1627 } 1628 /* for now simply copy all fields. Let caller decide which half to use */ 1629 tmp = soc_mem_field32_get(u, mem, entry, VALID0f); 1630 soc_mem_field32_set(u, s_mem, shadow, VALID0f, tmp); 1631 tmp = soc_mem_field32_get(u, mem, entry, VALID1f); 1632 soc_mem_field32_set(u, s_mem, shadow, VALID1f, tmp); 1633 1634 1635 /* IP_LENGTH */ 1636 tmp = soc_mem_field32_get(u, mem, entry, IP_ADDR_MASK0f); 1637 if ((rv = _ipmask2pfx(tmp, &pfx)) < 0) { 1638 LOG_ERROR(BSL_LS_SOC_ALPM, 1639 (BSL_META_U(u, 1640 "_ipmask2pfx fails mask0 0x%x pfx %d\n"), 1641 tmp, pfx)); 1642 return rv; 1643 } 1644 ip_mask = soc_mem_field32_get(u, mem, entry, IP_ADDR_MASK1f); 1645 if ((rv = _ipmask2pfx(ip_mask, &pfx2)) < 0) { 1646 LOG_ERROR(BSL_LS_SOC_ALPM, 1647 (BSL_META_U(u, 1648 "_ipmask2pfx fails mask1 0x%x pfx2 %d\n"), 1649 ip_mask, pfx2)); 1650 return rv; 1651 } 1652 if (v6) { 1653 soc_mem_field32_set(u, s_mem, shadow, IP_LENGTH0f, pfx + pfx2); 1654 soc_mem_field32_set(u, s_mem, shadow, IP_LENGTH1f, pfx + pfx2); 1655 } else { 1656 soc_mem_field32_set(u, s_mem, shadow, IP_LENGTH0f, pfx); 1657 soc_mem_field32_set(u, s_mem, shadow, IP_LENGTH1f, pfx2); 1658 } 1659 1660 /* IP_ADDR */ 1661 tmp = soc_mem_field32_get(u, mem, entry, IP_ADDR0f); 1662 soc_mem_field32_set(u, s_mem, shadow, IP_ADDR0f, tmp); 1663 tmp = soc_mem_field32_get(u, mem, entry, IP_ADDR1f); 1664 soc_mem_field32_set(u, s_mem, shadow, IP_ADDR1f, tmp); 1665 1666 /* DB_TYPE & ENTRY_TYPE */ 1667 /* for v4 need to be careful */ 1668 if (!v6) { 1669 sal_memcpy(&tmp_ipv4, entry, sizeof(tmp_ipv4)); 1670 /* vrf_id for ipv4 entry 0 */ 1671 rv = soc_alpm_lpm_vrf_get(u, (void *)&tmp_ipv4, &vrf_id, &vrf); 1672 SOC_IF_ERROR_RETURN(rv); 1673 1674 /* vrf_id for ipv4 entry 1 */ 1675 SOC_IF_ERROR_RETURN(soc_alpm_lpm_ip4entry1_to_0(u, &tmp_ipv4, 1676 &tmp_ipv4, PRESERVE_HIT)); 1677 rv = soc_alpm_lpm_vrf_get(u, (void *)&tmp_ipv4, &vrf_id2, &vrf2); 1678 SOC_IF_ERROR_RETURN(rv); 1679 } else { 1680 rv = soc_alpm_lpm_vrf_get(u, entry, &vrf_id, &vrf); 1681 } 1682 if (SOC_URPF_STATUS_GET(u)) { 1683 if (index >= (soc_mem_index_count(u, L3_DEFIPm) >> 1)) { 1684 urpf = 1; 1685 } 1686 } 1687 1688 soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type); 1689 1690 if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && v6 && 1691 soc_mem_field32_get(u, L3_DEFIPm, entry, ENTRY_VIEW0f)) { 1692 if (pfx2 == 32 && pfx == 32) { 1693 flex_v6_64 = 1; 1694 } 1695 } 1696 1697 if (vrf_id == SOC_L3_VRF_OVERRIDE || 1698 (soc_feature(u, soc_feature_ipmc_defip) && 1699 soc_mem_field32_get(u, mem, entry, MULTICAST_ROUTE0f)) || 1700 flex_v6_64) { 1701 soc_mem_field32_set(u, s_mem, shadow, VALID0f, 0); 1702 db_type = 0; 1703 } else { 1704 if (urpf) { 1705 db_type += 1; 1706 } 1707 } 1708 1709 soc_mem_field32_set(u, s_mem, shadow, DB_TYPE0f, db_type); 1710 tmp = soc_mem_field32_get(u, mem, entry, ENTRY_TYPE0f); 1711 soc_mem_field32_set(u, s_mem, shadow, ENTRY_TYPE0f, tmp | ent_type); 1712 if (!v6) { 1713 soc_alpm_db_ent_type_encoding(u, vrf2, &db_type, &ent_type); 1714 1715 if (vrf_id2 == SOC_L3_VRF_OVERRIDE || 1716 (soc_feature(u, soc_feature_ipmc_defip) && 1717 soc_mem_field32_get(u, mem, entry, MULTICAST_ROUTE1f))) { 1718 soc_mem_field32_set(u, s_mem, shadow, VALID1f, 0); 1719 db_type = 0; /* don't care */ 1720 } else { 1721 /* Database to be searched is VRF - DIP */ 1722 if (urpf) { 1723 db_type += 1; 1724 } 1725 } 1726 soc_mem_field32_set(u, s_mem, shadow, DB_TYPE1f, db_type); 1727 tmp = soc_mem_field32_get(u, mem, entry, ENTRY_TYPE1f); 1728 soc_mem_field32_set(u, s_mem, shadow, ENTRY_TYPE1f, tmp | ent_type); 1729 } else { 1730 if (vrf_id == SOC_L3_VRF_OVERRIDE || 1731 (soc_feature(u, soc_feature_ipmc_defip) && 1732 soc_mem_field32_get(u, mem, entry, MULTICAST_ROUTE1f)) || 1733 flex_v6_64) { 1734 soc_mem_field32_set(u, s_mem, shadow, VALID1f, 0); 1735 } 1736 soc_mem_field32_set(u, s_mem, shadow, DB_TYPE1f, db_type); 1737 tmp = soc_mem_field32_get(u, mem, entry, ENTRY_TYPE1f); 1738 soc_mem_field32_set(u, s_mem, shadow, ENTRY_TYPE1f, tmp | ent_type); 1739 } 1740 1741 /* modify bucket index if urpf is enabled */ 1742 if (urpf) { 1743 tmp = soc_mem_field32_get(u, mem, entry, ALG_BKT_PTR0f); 1744 if (tmp && tmp < SOC_ALPM_BUCKET_COUNT(u)) { 1745 tmp += SOC_ALPM_BUCKET_COUNT(u); 1746 soc_mem_field32_set(u, mem, entry, ALG_BKT_PTR0f, tmp); 1747 } 1748 if (!v6) { 1749 tmp = soc_mem_field32_get(u, mem, entry, ALG_BKT_PTR1f); 1750 if (tmp && tmp < SOC_ALPM_BUCKET_COUNT(u)) { 1751 tmp += SOC_ALPM_BUCKET_COUNT(u); 1752 soc_mem_field32_set(u, mem, entry, ALG_BKT_PTR1f, tmp); 1753 } 1754 } 1755 } 1756 1757 /* BPM_LENGTH */ 1758 /* don't modify, preserve existing values */ 1759 return SOC_E_NONE; 1760 } 1761 1762 static int 1763 _soc_alpm_write_pivot_aux(int u, int s_index, int index, void *entry, 1764 int convert, int bpm_len, int v4_half) 1765 { 1766 defip_aux_table_entry_t shadow; 1767 1768 SOC_IF_ERROR_RETURN(_soc_alpm_tcam_shadow_ent_init(u, 1769 s_index, index, entry, convert, (void *)&shadow, bpm_len, v4_half)); 1770 1771 /* write to defip has to be logical */ 1772 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, 1773 index, entry)); 1774 1775 /* write to shadow table has to be physical */ 1776 index = soc_alpm_physical_idx(u, L3_DEFIPm, index, 1); 1777 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ANY, 1778 index, &shadow)); 1779 return SOC_E_NONE; 1780 } 1781 1782 int 1783 _soc_alpm_insert_in_bkt(int u, soc_mem_t mem, int bucket_index, 1784 int bank_disable, void *alpm_data, void *alpm_sip_data, 1785 uint32 *e, int *key_index, int v6) 1786 { 1787 int rv; 1788 1789 rv = soc_mem_alpm_insert(u, mem, bucket_index, 1790 MEM_BLOCK_ANY, 1791 bank_disable, 1792 alpm_data, e, key_index); 1793 if (rv == SOC_E_FULL) { 1794 /* in combined search mode non-urpf try inserting into next bkt for v6*/ 1795 if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) { 1796 rv = soc_mem_alpm_insert(u, mem, bucket_index+1, 1797 MEM_BLOCK_ANY, 1798 bank_disable, 1799 alpm_data, e, key_index); 1800 } 1801 } 1802 1803 if (SOC_SUCCESS(rv)) { 1804 if (SOC_URPF_STATUS_GET(u)) { 1805 rv = soc_mem_write(u, mem, MEM_BLOCK_ANY, 1806 _soc_alpm_rpf_entry(u, *key_index), 1807 alpm_sip_data); 1808 } 1809 } 1810 return rv; 1811 } 1812 1813 #define _TD2_ALPM_BANK_NUM (4) 1814 #define _TD2_ALPM_BANK_MASK ((1 << _TD2_ALPM_BANK_NUM) - 1) 1815 1816 /* ALPM Table Address Translation 1817 * Bank addr[1:0] 1818 * Bucket addr[15:2] 1819 * Entry addr[16] L3_DEFIP_ALPM_IPV6_128m 1820 * addr[16:17] L3_DEFIP_ALPM_IPV6_64m 1821 * addr[16:18] L3_DEFIP_ALPM_IPV4m 1822 */ 1823 int 1824 _soc_alpm_mem_index(int u, soc_mem_t mem, int bucket_index, int offset, 1825 uint32 bank_disable, int *mem_index) 1826 { 1827 int i, bidx = 0; 1828 int baddr_arr[4] = {0}; 1829 int bnk_index = 0; 1830 int ent_index = 0; 1831 int avail_bank_num; 1832 1833 int v6 = 0; 1834 int ent_cnt = 6; 1835 1836 switch (mem) { 1837 case L3_DEFIP_ALPM_IPV4m: 1838 ent_cnt = 6; 1839 v6 = 0; 1840 break; 1841 case L3_DEFIP_ALPM_IPV4_1m: 1842 ent_cnt = 4; 1843 v6 = 0; 1844 break; 1845 case L3_DEFIP_ALPM_IPV6_64m: 1846 ent_cnt = 4; 1847 v6 = 1; 1848 break; 1849 case L3_DEFIP_ALPM_IPV6_64_1m: 1850 ent_cnt = 3; 1851 v6 = 1; 1852 break; 1853 case L3_DEFIP_ALPM_IPV6_128m: 1854 ent_cnt = 2; 1855 v6 = 1; 1856 break; 1857 default: 1858 break; 1859 } 1860 1861 if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) { 1862 if (offset >= ALPM_RAW_BKT_COUNT * ent_cnt) { 1863 bucket_index ++; 1864 offset -= ALPM_RAW_BKT_COUNT * ent_cnt; 1865 } 1866 } 1867 1868 avail_bank_num = _TD2_ALPM_BANK_NUM - 1869 _shr_popcount(bank_disable & _TD2_ALPM_BANK_MASK); 1870 1871 if (bucket_index >= (1 << 16) || offset >= avail_bank_num * ent_cnt) { 1872 return SOC_E_FULL; 1873 } 1874 ent_index = offset % ent_cnt; 1875 1876 /* Prepare bank address array for offset */ 1877 for (i = 0; i < _TD2_ALPM_BANK_NUM; i++) { 1878 if ((1 << i) & bank_disable) { 1879 continue; 1880 } 1881 1882 baddr_arr[bidx++] = i; 1883 } 1884 bnk_index = baddr_arr[offset / ent_cnt]; 1885 1886 *mem_index = (ent_index << 16) | 1887 (bucket_index << 2) | 1888 (bnk_index); 1889 return SOC_E_NONE; 1890 } 1891 1892 #ifdef ALPM_USE_RAW_VIEW 1893 1894 void 1895 _soc_alpm_raw_mem_read(int unit, soc_mem_t mem, void *raw_entry, 1896 int ent_id, void *entry) 1897 { 1898 1899 soc_mem_info_t meminfo; 1900 soc_field_info_t fieldinfo; 1901 /* Exclude HIT bit */ 1902 int entry_bits = soc_mem_entry_bits(unit, mem) - 1; 1903 1904 /* Construct presdo memory & field info, to take advantage of 1905 * socmem.c function get original view */ 1906 meminfo.flags = 0; 1907 meminfo.bytes = sizeof(defip_alpm_raw_entry_t); 1908 fieldinfo.flags = SOCF_LE; 1909 fieldinfo.bp = entry_bits * ent_id; 1910 fieldinfo.len = entry_bits; 1911 1912 (void)soc_meminfo_fieldinfo_field_get(raw_entry, &meminfo, 1913 &fieldinfo, entry); 1914 1915 } 1916 1917 void 1918 _soc_alpm_raw_mem_write(int unit, soc_mem_t mem, void *raw_entry, 1919 int index, int ent_id, void *entry) 1920 { 1921 soc_mem_info_t meminfo; 1922 soc_field_info_t fieldinfo; 1923 /* Exclude HIT bit */ 1924 int entry_bits = soc_mem_entry_bits(unit, mem) - 1; 1925 1926 (void) soc_mem_cache_invalidate(unit, mem, MEM_BLOCK_ANY, index); 1927 1928 meminfo.flags = 0; 1929 meminfo.bytes = sizeof(defip_alpm_raw_entry_t); 1930 fieldinfo.bp = entry_bits * ent_id; 1931 fieldinfo.len = entry_bits; 1932 fieldinfo.flags = SOCF_LE; 1933 1934 (void)soc_meminfo_fieldinfo_field_set(raw_entry, &meminfo, 1935 &fieldinfo, entry); 1936 1937 } 1938 1939 int 1940 _soc_alpm_raw_bucket_read(int u, soc_mem_t mem, int bucket_index, 1941 void *raw_entry, void *raw_sip_entry) 1942 { 1943 int i, v6 = 1; 1944 int raw_index, raw_sip_index; 1945 defip_alpm_raw_entry_t *ent = raw_entry; 1946 defip_alpm_raw_entry_t *entsip = raw_sip_entry; 1947 1948 if (mem == L3_DEFIP_ALPM_IPV4m || 1949 mem == L3_DEFIP_ALPM_IPV4_1m) { 1950 v6 = 0; 1951 } 1952 1953 /* Read all bucket entries by using ALPM_RAW view */ 1954 raw_index = SOC_ALPM_BKT_IDX_TO_ENTRY(bucket_index); 1955 1956 for (i = 0; i < SOC_ALPM_RAW_BUCKET_SIZE(u, v6); i++) { 1957 SOC_IF_ERROR_RETURN( 1958 _soc_mem_alpm_read(u, L3_DEFIP_ALPM_RAWm, MEM_BLOCK_ANY, 1959 raw_index + i, &ent[i])); 1960 if (SOC_URPF_STATUS_GET(u)) { 1961 raw_sip_index = _soc_alpm_rpf_entry(u, raw_index + i); 1962 SOC_IF_ERROR_RETURN( 1963 _soc_mem_alpm_read(u, L3_DEFIP_ALPM_RAWm, MEM_BLOCK_ANY, 1964 raw_sip_index, &entsip[i])); 1965 } 1966 } 1967 1968 return SOC_E_NONE; 1969 } 1970 1971 int 1972 _soc_alpm_raw_bucket_write(int u, soc_mem_t mem, int bucket_index, 1973 uint32 bank_disable, 1974 void *raw_entry, void *raw_sip_entry, int entry_cnt) 1975 { 1976 int i = 0, bank, v6 = 1; 1977 int raw_index, raw_sip_index, raw_ent_cnt; 1978 defip_alpm_raw_entry_t *ent = raw_entry; 1979 defip_alpm_raw_entry_t *entsip = raw_sip_entry; 1980 int ent_per_bank = 6; 1981 1982 switch (mem) { 1983 case L3_DEFIP_ALPM_IPV4m: 1984 ent_per_bank = 6; 1985 v6 = 0; 1986 break; 1987 case L3_DEFIP_ALPM_IPV4_1m: 1988 ent_per_bank = 4; 1989 v6 = 0; 1990 break; 1991 case L3_DEFIP_ALPM_IPV6_64m: 1992 ent_per_bank = 4; 1993 v6 = 1; 1994 break; 1995 case L3_DEFIP_ALPM_IPV6_64_1m: 1996 ent_per_bank = 3; 1997 v6 = 1; 1998 break; 1999 case L3_DEFIP_ALPM_IPV6_128m: 2000 ent_per_bank = 2; 2001 v6 = 1; 2002 break; 2003 default: 2004 break; 2005 } 2006 2007 /* Write all bucket entries by using ALPM_RAW view */ 2008 raw_index = SOC_ALPM_BKT_IDX_TO_ENTRY(bucket_index); 2009 if (entry_cnt == MAX_RAW_COUNT) { 2010 raw_ent_cnt = SOC_ALPM_RAW_BUCKET_SIZE(u, v6); 2011 } else { 2012 raw_ent_cnt = (entry_cnt / ent_per_bank) + 1; 2013 } 2014 2015 for (bank = 0; bank < SOC_ALPM_RAW_BUCKET_SIZE(u, v6); bank++) { 2016 if ((1 << (bank % _TD2_ALPM_BANK_NUM)) & bank_disable) { 2017 continue; 2018 } 2019 SOC_IF_ERROR_RETURN(soc_mem_write(u, L3_DEFIP_ALPM_RAWm, MEM_BLOCK_ANY, 2020 raw_index + bank, &ent[bank])); 2021 _soc_trident2_alpm_bkt_view_set(u, raw_index + bank, mem); 2022 if (SOC_URPF_STATUS_GET(u)) { 2023 raw_sip_index = _soc_alpm_rpf_entry(u, raw_index + bank); 2024 _soc_trident2_alpm_bkt_view_set(u, raw_sip_index, mem); 2025 SOC_IF_ERROR_RETURN(soc_mem_write(u, L3_DEFIP_ALPM_RAWm, MEM_BLOCK_ANY, 2026 raw_sip_index, &entsip[bank])); 2027 } 2028 if (++i == raw_ent_cnt) { 2029 break; 2030 } 2031 } 2032 2033 return SOC_E_NONE; 2034 } 2035 2036 void _soc_alpm_raw_parity_set(int u, soc_mem_t mem, void *alpm_data) 2037 { 2038 int i, entry_words, bit1count = 0; 2039 uint32 *entry = alpm_data; 2040 2041 entry_words = soc_mem_entry_words(u, mem); 2042 2043 /* Count bit1 number */ 2044 for (i = 0; i < entry_words; i++) { 2045 bit1count += _shr_popcount(entry[i]); 2046 } 2047 2048 /* If the number is odd, we should set PARITY bit */ 2049 if (bit1count & 0x1) { 2050 if (SOC_MEM_FIELD_VALID(u, mem, EVEN_PARITYf)) { 2051 soc_mem_field32_set(u, mem, alpm_data, EVEN_PARITYf, 1); 2052 } 2053 } 2054 } 2055 2056 static void 2057 _soc_alpm_raw_bucket_prepare_undo(int u, 2058 alpm_mem_prefix_array_t **alloc_pfx_array, 2059 void **alloc_raw_bkt, 2060 int **alloc_new_index) 2061 { 2062 if (*alloc_raw_bkt) { 2063 sal_free(*alloc_raw_bkt); 2064 } 2065 if (*alloc_pfx_array) { 2066 sal_free(*alloc_pfx_array); 2067 *alloc_pfx_array = NULL; 2068 } 2069 if (*alloc_new_index) { 2070 sal_free(*alloc_new_index); 2071 *alloc_new_index = NULL; 2072 } 2073 } 2074 2075 static int 2076 _soc_alpm_raw_bucket_prepare(int u, soc_mem_t mem, 2077 trie_t *bkt_trie, 2078 int bucket_index_from, 2079 int bucket_index_to, 2080 uint32 bank_disable, 2081 void *alpm_data, 2082 void *alpm_sip_data, 2083 alpm_mem_prefix_array_t **alloc_pfx_array, 2084 void **alloc_raw_bkt, 2085 int **alloc_new_index, 2086 int *new_index_pos, 2087 int to_exist) 2088 { 2089 int i, j = 0, rv = SOC_E_NONE; 2090 int raw_size, raw_bkt_size, alloc_size; 2091 void *raw_ent; 2092 void *raw_bkt[RAW_BKT_NUM] = {NULL}; 2093 int raw_id = 0; 2094 int ent_id = 0; 2095 int key_index; 2096 /* allocation pointers all set to NULL */ 2097 alpm_mem_prefix_array_t *pfx_array = NULL; 2098 int *index_array = NULL; 2099 int v6 = SOC_ALPM_MEM_V6(mem); 2100 /* Search Result buffers */ 2101 defip_alpm_ipv4_1_entry_t alpmv4_entry, alpmv4_sip_entry; 2102 defip_alpm_ipv6_64_1_entry_t alpmv6_entry, alpmv6_sip_entry; 2103 void *bufp = NULL, *sip_bufp = NULL; 2104 defip_alpm_ipv4_1_entry_t alpmv4_entry2; 2105 defip_alpm_ipv6_64_1_entry_t alpmv6_entry2; 2106 void *bufp2 = NULL; 2107 int max_count = 0; 2108 2109 /* Assign entry buf based on table being used */ 2110 SOC_ALPM_ENTRY_BUF(v6, mem, bufp, alpmv4_entry, alpmv6_entry); 2111 SOC_ALPM_ENTRY_BUF(v6, mem, sip_bufp, alpmv4_sip_entry, alpmv6_sip_entry); 2112 SOC_ALPM_ENTRY_BUF(v6, mem, bufp2, alpmv4_entry2, alpmv6_entry2); 2113 2114 *alloc_raw_bkt = NULL; 2115 *alloc_new_index = NULL; 2116 *alloc_pfx_array = NULL; 2117 2118 /* Alloc prefix array */ 2119 alloc_size = sizeof(alpm_mem_prefix_array_t); 2120 pfx_array = sal_alloc(alloc_size, "prefix array"); 2121 if (pfx_array == NULL) { 2122 goto cleanup; 2123 } 2124 2125 /* Fill prefix array */ 2126 sal_memset(pfx_array, 0, alloc_size); 2127 rv = trie_traverse(bkt_trie, alpm_mem_prefix_array_cb, 2128 pfx_array, _TRIE_INORDER_TRAVERSE); 2129 if (SOC_FAILURE(rv)) { 2130 goto cleanup; 2131 } 2132 2133 /* Alloc index array */ 2134 alloc_size = sizeof(int) * pfx_array->count; 2135 index_array = sal_alloc(alloc_size, "index_array"); 2136 if (index_array == NULL) { 2137 goto cleanup; 2138 } 2139 sal_memset(index_array, -1, alloc_size); 2140 2141 raw_size = sizeof(defip_alpm_raw_entry_t); 2142 raw_bkt_size = raw_size * ALPM_RAW_BKT_COUNT_DW; 2143 raw_bkt[0] = sal_alloc(RAW_BKT_NUM * raw_bkt_size, "Raw memory buffer"); 2144 if (raw_bkt[0] == NULL) { 2145 rv = SOC_E_MEMORY; 2146 goto cleanup; 2147 } 2148 sal_memset(raw_bkt[0], 0, RAW_BKT_NUM * raw_bkt_size); 2149 for (i = 1; i < RAW_BKT_NUM; i++) { 2150 raw_bkt[i] = (uint8 *)raw_bkt[0] + raw_bkt_size * i; 2151 } 2152 2153 rv = _soc_alpm_raw_bucket_read(u, mem, bucket_index_from, 2154 raw_bkt[RAW_OLD_BKT_DIP], 2155 raw_bkt[RAW_OLD_BKT_SIP]); 2156 if (SOC_FAILURE(rv)) { 2157 goto cleanup; 2158 } 2159 sal_memcpy(raw_bkt[RAW_RB_BKT_DIP], raw_bkt[RAW_OLD_BKT_DIP], raw_bkt_size); 2160 sal_memcpy(raw_bkt[RAW_RB_BKT_SIP], raw_bkt[RAW_OLD_BKT_SIP], raw_bkt_size); 2161 2162 if (to_exist) { 2163 rv = _soc_alpm_raw_bucket_read(u, mem, bucket_index_to, 2164 raw_bkt[RAW_NEW_BKT_DIP], 2165 raw_bkt[RAW_NEW_BKT_SIP]); 2166 if (SOC_FAILURE(rv)) { 2167 goto cleanup; 2168 } 2169 max_count = _soc_alpm_bkt_entry_cnt(u, mem); 2170 } 2171 2172 for (i = 0; i < pfx_array->count; i++) { 2173 payload_t *pfx = pfx_array->prefix[i]; 2174 if (pfx->index > 0) { 2175 /* if this is the new prefix it does not exist in the 2176 * bucket, no point reading */ 2177 SOC_ALPM_RAW_INDEX_DECODE(u, v6, pfx->index, raw_id, ent_id); 2178 raw_ent = (uint8 *)raw_bkt[RAW_OLD_BKT_DIP] + raw_id * raw_size; 2179 _soc_alpm_raw_mem_read(u, mem, raw_ent, ent_id, bufp); 2180 _soc_alpm_raw_mem_write(u, mem, raw_ent, pfx->index, 2181 ent_id, soc_mem_entry_null(u, mem)); 2182 2183 if (SOC_URPF_STATUS_GET(u)) { 2184 raw_ent = (uint8 *)raw_bkt[RAW_OLD_BKT_SIP] + raw_id * raw_size; 2185 _soc_alpm_raw_mem_read(u, mem, raw_ent, ent_id, sip_bufp); 2186 _soc_alpm_raw_mem_write(u, mem, raw_ent, 2187 _soc_alpm_rpf_entry(u, pfx->index), 2188 ent_id, soc_mem_entry_null(u, mem)); 2189 } 2190 2191 if (to_exist) { 2192 for (;j < max_count; j++) { 2193 rv = _soc_alpm_mem_index(u, mem, bucket_index_to, j, 2194 bank_disable, &key_index); 2195 if (SOC_FAILURE(rv)) { 2196 goto cleanup; 2197 } 2198 SOC_ALPM_RAW_INDEX_DECODE(u, v6, key_index, raw_id, ent_id); 2199 raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_DIP] + raw_id * raw_size; 2200 _soc_alpm_raw_mem_read(u, mem, raw_ent, ent_id, bufp2); 2201 if (soc_mem_field32_get(u, mem, bufp2, VALIDf) == 0) { 2202 break; 2203 } 2204 } 2205 if (j == max_count) { 2206 rv = SOC_E_INTERNAL; 2207 goto cleanup; 2208 } 2209 _soc_alpm_raw_mem_write(u, mem, raw_ent, 2210 key_index, ent_id, bufp); 2211 if (SOC_URPF_STATUS_GET(u)) { 2212 raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_SIP] + raw_id * raw_size; 2213 _soc_alpm_raw_mem_write(u, mem, raw_ent, 2214 _soc_alpm_rpf_entry(u, key_index), 2215 ent_id, sip_bufp); 2216 } 2217 } else { 2218 rv = _soc_alpm_mem_index(u, mem, bucket_index_to, i, 2219 bank_disable, &key_index); 2220 if (SOC_FAILURE(rv)) { 2221 goto cleanup; 2222 } 2223 SOC_ALPM_RAW_INDEX_DECODE(u, v6, key_index, raw_id, ent_id); 2224 raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_DIP] + raw_id * raw_size; 2225 _soc_alpm_raw_mem_write(u, mem, raw_ent, 2226 key_index, ent_id, bufp); 2227 if (SOC_URPF_STATUS_GET(u)) { 2228 raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_SIP] + raw_id * raw_size; 2229 _soc_alpm_raw_mem_write(u, mem, raw_ent, 2230 _soc_alpm_rpf_entry(u, key_index), 2231 ent_id, sip_bufp); 2232 } 2233 } 2234 } else { 2235 rv = _soc_alpm_mem_index(u, mem, bucket_index_to, i, 2236 bank_disable, &key_index); 2237 if (SOC_FAILURE(rv)) { 2238 goto cleanup; 2239 } 2240 2241 if (!new_index_pos) { 2242 rv = SOC_E_PARAM; 2243 goto cleanup; 2244 } 2245 *new_index_pos = i; 2246 2247 /* New entry, need to take care of Parity for raw view */ 2248 _soc_alpm_raw_parity_set(u, mem, alpm_data); 2249 SOC_ALPM_RAW_INDEX_DECODE(u, v6, key_index, raw_id, ent_id); 2250 raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_DIP] + raw_id * raw_size; 2251 _soc_alpm_raw_mem_write(u, mem, raw_ent, 2252 key_index, ent_id, alpm_data); 2253 if (SOC_URPF_STATUS_GET(u)) { 2254 _soc_alpm_raw_parity_set(u, mem, alpm_sip_data); 2255 raw_ent = (uint8 *)raw_bkt[RAW_NEW_BKT_SIP] + raw_id * raw_size; 2256 _soc_alpm_raw_mem_write(u, mem, raw_ent, 2257 _soc_alpm_rpf_entry(u, key_index), 2258 ent_id, alpm_sip_data); 2259 } 2260 } 2261 index_array[i] = key_index; 2262 } 2263 2264 for (i = 0; i < RAW_BKT_NUM; i++) { 2265 alloc_raw_bkt[i] = raw_bkt[i]; 2266 } 2267 *alloc_new_index = index_array; 2268 *alloc_pfx_array = pfx_array; 2269 2270 return rv; 2271 2272 cleanup: 2273 if (raw_bkt[0]) { 2274 sal_free(raw_bkt[0]); 2275 } 2276 if (index_array) { 2277 sal_free(index_array); 2278 } 2279 if (pfx_array) { 2280 sal_free(pfx_array); 2281 } 2282 return rv; 2283 } 2284 2285 2286 static void 2287 _soc_alpm_raw_bucket_copy_undo(int u, soc_mem_t mem, 2288 int bucket_index, 2289 uint32 bank_disable, 2290 void *new_raw_bufp, void *new_raw_sip_bufp, 2291 int *new_index, int index_count) 2292 { 2293 int i; 2294 int raw_size = sizeof(defip_alpm_raw_entry_t); 2295 int raw_id = 0; 2296 int ent_id = 0; 2297 void *raw_ent; 2298 int v6 = SOC_ALPM_MEM_V6(mem); 2299 2300 /* Restore the new bucket to null */ 2301 for (i = 0; i < index_count; i++) { 2302 if (new_index[i] < 0) { 2303 continue; 2304 } 2305 2306 SOC_ALPM_RAW_INDEX_DECODE(u, v6, new_index[i], raw_id, ent_id); 2307 raw_ent = (uint8 *)new_raw_bufp + raw_id * raw_size; 2308 _soc_alpm_raw_mem_write(u, mem, raw_ent, 2309 new_index[i], ent_id, soc_mem_entry_null(u, mem)); 2310 if (SOC_URPF_STATUS_GET(u)) { 2311 raw_ent = (uint8 *)new_raw_sip_bufp + raw_id * raw_size; 2312 _soc_alpm_raw_mem_write(u, mem, raw_ent, 2313 _soc_alpm_rpf_entry(u, new_index[i]), 2314 ent_id, soc_mem_entry_null(u, mem)); 2315 } 2316 } 2317 2318 (void)_soc_alpm_raw_bucket_write(u, mem, bucket_index, bank_disable, 2319 new_raw_bufp, new_raw_sip_bufp, MAX_RAW_COUNT); 2320 } 2321 2322 /* Populate entries in pfx array to logical bucket */ 2323 static int 2324 _soc_alpm_raw_bucket_copy(int u, soc_mem_t mem, 2325 int bucket_index, 2326 uint32 bank_disable, 2327 void *new_raw_bufp, 2328 void *new_raw_sip_bufp, 2329 int *new_index, 2330 int index_count) 2331 { 2332 int rv; 2333 rv = _soc_alpm_raw_bucket_write(u, mem, bucket_index, bank_disable, 2334 new_raw_bufp, new_raw_sip_bufp, MAX_RAW_COUNT); 2335 2336 if (SOC_FAILURE(rv)) { 2337 /* Delete entries in new bucket */ 2338 _soc_alpm_raw_bucket_copy_undo(u, mem, bucket_index, bank_disable, 2339 new_raw_bufp, new_raw_sip_bufp, 2340 new_index, index_count); 2341 } 2342 return rv; 2343 } 2344 2345 2346 2347 static INLINE void 2348 _soc_alpm_raw_bucket_inval_undo(int u, soc_mem_t mem, int bucket_index, 2349 uint32 bank_disable, 2350 void *old_raw_bufp, void *old_raw_sip_bufp) 2351 { 2352 2353 (void)_soc_alpm_raw_bucket_write(u, mem, bucket_index, 2354 bank_disable, (void *)old_raw_bufp, 2355 (void *)old_raw_sip_bufp, MAX_RAW_COUNT); 2356 return; 2357 } 2358 static int 2359 _soc_alpm_raw_bucket_inval(int u, soc_mem_t mem, int bucket_index, 2360 uint32 bank_disable, 2361 void *old_bufp, 2362 void *old_sip_bufp, 2363 void *rb_bufp, 2364 void *rb_sip_bufp) 2365 { 2366 int rv = SOC_E_NONE; 2367 2368 /* Invalidation process 2369 * 1. Erase old copied entries 2370 * 2. Re-validate those entries if invalidation fails 2371 */ 2372 2373 /* Update old bucket with split entries invalidated */ 2374 rv = _soc_alpm_raw_bucket_write(u, mem, bucket_index, 2375 bank_disable, old_bufp, 2376 old_sip_bufp, MAX_RAW_COUNT); 2377 /* re-validate old bucket entries */ 2378 if (SOC_FAILURE(rv)) { 2379 _soc_alpm_raw_bucket_inval_undo(u, mem, bucket_index, 2380 bank_disable, rb_bufp, 2381 rb_sip_bufp); 2382 } 2383 2384 return rv; 2385 } 2386 2387 #else 2388 2389 static void 2390 _soc_alpm_bucket_prepare_undo(int u, 2391 alpm_mem_prefix_array_t **alloc_pfx_array, 2392 void **alloc_bufp, 2393 void **alloc_sip_bufp, 2394 int **alloc_new_index) 2395 { 2396 if (*alloc_pfx_array) { 2397 sal_free(*alloc_pfx_array); 2398 *alloc_pfx_array = NULL; 2399 } 2400 if (*alloc_bufp) { 2401 sal_free(*alloc_bufp); 2402 *alloc_bufp = NULL; 2403 } 2404 if (*alloc_sip_bufp) { 2405 sal_free(*alloc_sip_bufp); 2406 *alloc_sip_bufp = NULL; 2407 } 2408 if (*alloc_new_index) { 2409 sal_free(*alloc_new_index); 2410 *alloc_new_index = NULL; 2411 } 2412 } 2413 2414 static int 2415 _soc_alpm_bucket_prepare(int u, soc_mem_t mem, 2416 trie_t *bkt_trie, 2417 alpm_mem_prefix_array_t **alloc_pfx_array, 2418 void **alloc_bufp, 2419 void **alloc_sip_bufp, 2420 int **alloc_new_index) 2421 { 2422 int i, rv = SOC_E_NONE; 2423 int entry_size; 2424 int alloc_size; 2425 /* allocation pointers all set to NULL */ 2426 void *bufp = NULL, *sip_bufp = NULL; 2427 int *index_array = NULL; 2428 alpm_mem_prefix_array_t *pfx_array = NULL; 2429 2430 *alloc_bufp = NULL; 2431 *alloc_sip_bufp = NULL; 2432 *alloc_new_index = NULL; 2433 *alloc_pfx_array = NULL; 2434 2435 /* Alloc prefix array */ 2436 alloc_size = sizeof(alpm_mem_prefix_array_t); 2437 pfx_array = sal_alloc(alloc_size, "prefix array"); 2438 if (pfx_array == NULL) { 2439 goto cleanup; 2440 } 2441 2442 /* Fill prefix array */ 2443 sal_memset(pfx_array, 0, alloc_size); 2444 rv = trie_traverse(bkt_trie, alpm_mem_prefix_array_cb, 2445 pfx_array, _TRIE_INORDER_TRAVERSE); 2446 if (SOC_FAILURE(rv)) { 2447 goto cleanup; 2448 } 2449 2450 /* Alloc index array */ 2451 alloc_size = sizeof(int) * pfx_array->count; 2452 index_array = sal_alloc(alloc_size, "index_array"); 2453 if (index_array == NULL) { 2454 goto cleanup; 2455 } 2456 sal_memset(index_array, -1, alloc_size); 2457 2458 /* Alloc bufp & sip_bufp */ 2459 entry_size = (L3_DEFIP_ALPM_IPV6_64m == mem || 2460 L3_DEFIP_ALPM_IPV6_64_1m == mem) ? 2461 sizeof(defip_alpm_ipv6_64_1_entry_t) : 2462 sizeof(defip_alpm_ipv4_1_entry_t); 2463 2464 alloc_size = entry_size * pfx_array->count; 2465 bufp = sal_alloc(alloc_size, "alloc_bufp"); 2466 if (bufp == NULL) { 2467 goto cleanup; 2468 } 2469 if (SOC_URPF_STATUS_GET(u)) { 2470 sip_bufp = sal_alloc(alloc_size, "alloc_sip_bufp"); 2471 if (sip_bufp == NULL) { 2472 goto cleanup; 2473 } 2474 } 2475 2476 /* Fill bufp & sip bufp */ 2477 for (i = 0; i < pfx_array->count; i++) { 2478 payload_t *pfx = pfx_array->prefix[i]; 2479 2480 if (pfx->index > 0) { /* old pfx */ 2481 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, pfx->index, 2482 (uint8 *)bufp + i * entry_size); 2483 2484 if (SOC_FAILURE(rv)) { 2485 break; 2486 } 2487 2488 if (SOC_URPF_STATUS_GET(u)) { 2489 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, 2490 _soc_alpm_rpf_entry(u, pfx->index), 2491 (uint8 *)sip_bufp + i * entry_size); 2492 if (SOC_FAILURE(rv)) { 2493 break; 2494 } 2495 } 2496 } 2497 } 2498 if (SOC_FAILURE(rv)) { 2499 goto cleanup; 2500 } 2501 2502 *alloc_bufp = bufp; 2503 *alloc_sip_bufp = sip_bufp; 2504 *alloc_new_index = index_array; 2505 *alloc_pfx_array = pfx_array; 2506 2507 return rv; 2508 2509 cleanup: 2510 if (bufp) { 2511 sal_free(bufp); 2512 } 2513 if (sip_bufp) { 2514 sal_free(sip_bufp); 2515 } 2516 if (index_array) { 2517 sal_free(index_array); 2518 } 2519 if (pfx_array) { 2520 sal_free(pfx_array); 2521 } 2522 return rv; 2523 } 2524 2525 2526 static void 2527 _soc_alpm_bucket_copy_undo(int u, soc_mem_t mem, int count, int *new_index) 2528 { 2529 int i; 2530 2531 for (i = 0; i < count; i++) { 2532 if (new_index[i] < 0) { 2533 continue; 2534 } 2535 soc_mem_write(u, mem, MEM_BLOCK_ANY, new_index[i], 2536 soc_mem_entry_null(u, mem)); 2537 if (SOC_URPF_STATUS_GET(u)) { 2538 soc_mem_write(u, mem, MEM_BLOCK_ANY, 2539 _soc_alpm_rpf_entry(u, new_index[i]), 2540 soc_mem_entry_null(u, mem)); 2541 } 2542 } 2543 } 2544 2545 /* Populate entries in pfx array to logical bucket */ 2546 static int 2547 _soc_alpm_bucket_copy(int u, soc_mem_t mem, int vrf, 2548 alpm_mem_prefix_array_t *pfx_array, 2549 int bucket_index, 2550 void *old_bufp, 2551 void *old_sip_bufp, 2552 void *new_bufp, 2553 void *new_sip_bufp, 2554 int *new_index, 2555 int *new_index_pos) 2556 { 2557 int rv; 2558 void *bufp, *sip_bufp; 2559 int entsz, key_index; 2560 uint32 bank_disable = 0; 2561 int v6, i; 2562 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 2563 bank_disable = soc_alpm_bank_dis(u, vrf); 2564 2565 v6 = SOC_ALPM_MEM_V6(mem); 2566 2567 entsz = v6 ? sizeof(defip_alpm_ipv6_64_1_entry_t) : 2568 sizeof(defip_alpm_ipv4_1_entry_t); 2569 2570 for (i = 0; i < pfx_array->count; i++) { 2571 if (pfx_array->prefix[i]->index > 0) { /* old prefix */ 2572 2573 bufp = (uint8 *)old_bufp + i * entsz; 2574 if (SOC_URPF_STATUS_GET(u)) { 2575 sip_bufp = (uint8 *)old_sip_bufp + i * entsz; 2576 } 2577 2578 /* entry shouldn't exist, insert the entry into the RAM */ 2579 rv = _soc_alpm_insert_in_bkt(u, mem, bucket_index, 2580 bank_disable, bufp, sip_bufp, e, 2581 &key_index, v6); 2582 } else { /* for split case only */ 2583 if (!new_bufp || !new_index_pos) { 2584 rv = SOC_E_PARAM; 2585 goto _rollback; 2586 } 2587 *new_index_pos = i; 2588 rv = _soc_alpm_insert_in_bkt(u, mem, bucket_index, 2589 bank_disable, new_bufp, new_sip_bufp, e, 2590 &key_index, v6); 2591 } 2592 if (SOC_FAILURE(rv)) { 2593 LOG_ERROR(BSL_LS_SOC_ALPM, 2594 (BSL_META_U(u, 2595 "Failed to insert prefix " 2596 "0x%08x 0x%08x 0x%08x 0x%08x to bucket %d\n"), 2597 pfx_array->prefix[i]->key[1], 2598 pfx_array->prefix[i]->key[2], 2599 pfx_array->prefix[i]->key[3], 2600 pfx_array->prefix[i]->key[4], bucket_index)); 2601 2602 goto _rollback; 2603 } 2604 new_index[i] = key_index; 2605 } 2606 2607 _rollback: 2608 if (SOC_FAILURE(rv)) { 2609 /* Delete entries in new bucket */ 2610 _soc_alpm_bucket_copy_undo(u, mem, pfx_array->count, new_index); 2611 } 2612 2613 return rv; 2614 } 2615 2616 2617 2618 2619 2620 static void 2621 _soc_alpm_bucket_inval_undo(int u, soc_mem_t mem, 2622 alpm_mem_prefix_array_t *pfx_array, 2623 void *old_bufp, void *old_sip_bufp) 2624 { 2625 int i; 2626 int entry_size = (L3_DEFIP_ALPM_IPV6_64m == mem || 2627 L3_DEFIP_ALPM_IPV6_64_1m == mem) ? 2628 sizeof(defip_alpm_ipv6_64_1_entry_t) : 2629 sizeof(defip_alpm_ipv4_1_entry_t); 2630 2631 for (i = 0; i < pfx_array->count; i++) { 2632 payload_t *prefix = pfx_array->prefix[i]; 2633 2634 if (prefix->index > 0) { 2635 soc_mem_write(u, mem, MEM_BLOCK_ALL, prefix->index, 2636 (uint8 *)old_bufp + i * entry_size); 2637 2638 if (SOC_URPF_STATUS_GET(u)) { 2639 /* UPRF entry */ 2640 soc_mem_write(u, mem, MEM_BLOCK_ALL, 2641 _soc_alpm_rpf_entry(u, prefix->index), 2642 (uint8 *)old_sip_bufp + i * entry_size); 2643 } 2644 } 2645 } 2646 return; 2647 } 2648 static int 2649 _soc_alpm_bucket_inval(int u, soc_mem_t mem, 2650 alpm_mem_prefix_array_t *pfx_array, 2651 void *old_bufp, void *old_sip_bufp) 2652 { 2653 int i, rv = SOC_E_NONE; 2654 2655 /* Invalidation process 2656 * 1. Erase old copied entries 2657 * 2. Re-validate those entries if invalidation fails 2658 */ 2659 2660 for (i = 0; i < pfx_array->count; i ++) { 2661 payload_t *prefix = pfx_array->prefix[i]; 2662 2663 if (prefix->index >= 0) { 2664 /* zero out old entries now that split is done */ 2665 rv = soc_mem_write(u, mem, MEM_BLOCK_ALL, prefix->index, 2666 soc_mem_entry_null(u, mem)); 2667 if (SOC_FAILURE(rv)) { 2668 break; 2669 } 2670 if (SOC_URPF_STATUS_GET(u)) { 2671 rv = soc_mem_write(u, mem, MEM_BLOCK_ANY, 2672 _soc_alpm_rpf_entry(u, prefix->index), 2673 soc_mem_entry_null(u, mem)); 2674 if (SOC_FAILURE(rv)) { 2675 break; 2676 } 2677 } 2678 } 2679 } 2680 /* re-validate old bucket entries */ 2681 if (SOC_FAILURE(rv)) { 2682 _soc_alpm_bucket_inval_undo(u, mem, pfx_array, old_bufp, old_sip_bufp); 2683 } 2684 2685 return rv; 2686 } 2687 2688 2689 #endif /* ALPM_USE_RAW_VIEW */ 2690 2691 2692 2693 STATIC int 2694 _soc_alpm_split_lpm_init(int u, 2695 soc_mem_t mem, 2696 int vrf, 2697 int bucket_index, 2698 void *alpm_data, 2699 void *alpm_sip_data, 2700 uint32 *pivot, 2701 int length, 2702 defip_entry_t *lpm_entry, 2703 uint32 *bpm_len, 2704 uint32 *src_discard, 2705 uint32 *src_default) 2706 { 2707 int rv = SOC_E_NONE, v6; 2708 trie_node_t *lpm = NULL; 2709 payload_t *bkt_lpm = NULL; 2710 trie_t *pfx_trie; 2711 uint32 tmp_pivot[5] = {0}; 2712 2713 v6 = SOC_ALPM_MEM_V6(mem); 2714 2715 /* prefix trie */ 2716 if (v6) { 2717 pfx_trie = VRF_PREFIX_TRIE_IPV6(u, vrf); 2718 } else { 2719 pfx_trie = VRF_PREFIX_TRIE_IPV4(u, vrf); 2720 } 2721 2722 2723 /* find longest prefix that covers pivot */ 2724 lpm = NULL; 2725 rv = trie_find_lpm(pfx_trie, pivot, length, &lpm); 2726 if (SOC_FAILURE(rv)) { 2727 LOG_ERROR(BSL_LS_SOC_ALPM, 2728 (BSL_META_U(u, 2729 "unit %d Unable to find lpm for pivot: " 2730 "0x%08x 0x%08x\n 0x%08x 0x%08x 0x%08x length: %d\n"), 2731 u, pivot[0], pivot[1], pivot[2], pivot[3], pivot[4], 2732 length)); 2733 2734 return rv; 2735 } 2736 bkt_lpm = ((payload_t *)lpm)->bkt_ptr; 2737 2738 /* Initialize the lpm entry to insert */ 2739 if (bkt_lpm) { 2740 defip_alpm_ipv4_1_entry_t alpmv4_entry, alpmv4_sip_entry; 2741 defip_alpm_ipv6_64_1_entry_t alpmv6_entry, alpmv6_sip_entry; 2742 int index, vrf_id; 2743 void *bufp = NULL, *sip_bufp = NULL; 2744 2745 SOC_ALPM_ENTRY_BUF(v6, mem, bufp, alpmv4_entry, alpmv6_entry); 2746 SOC_ALPM_ENTRY_BUF(v6, mem, sip_bufp, alpmv4_sip_entry, alpmv6_sip_entry); 2747 2748 /* this means this bucket default route is an actual route */ 2749 /* initialize new pivot's associated data with data of lpm match */ 2750 index = bkt_lpm->index; 2751 if (index == -1) { 2752 /* this means the new route is the bucket's default */ 2753 if (alpm_data == NULL || alpm_sip_data == NULL) { 2754 return SOC_E_PARAM; 2755 } 2756 sal_memcpy(bufp, alpm_data, v6 ? 2757 sizeof(defip_alpm_ipv6_64_1_entry_t) : 2758 sizeof(defip_alpm_ipv4_1_entry_t)); 2759 if (SOC_URPF_STATUS_GET(u)) { 2760 *src_default = soc_mem_field32_get(u, mem, alpm_sip_data, 2761 DEFAULTROUTEf); 2762 *src_discard = soc_mem_field32_get(u, mem, alpm_sip_data, 2763 SRC_DISCARDf); 2764 } 2765 } else { 2766 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, index, bufp); 2767 if (SOC_FAILURE(rv)) { 2768 return rv; 2769 } 2770 if (SOC_URPF_STATUS_GET(u)) { 2771 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, 2772 _soc_alpm_rpf_entry(u, index), 2773 sip_bufp); 2774 *src_default = soc_mem_field32_get(u, mem, sip_bufp, 2775 DEFAULTROUTEf); 2776 *src_discard = soc_mem_field32_get(u, mem, sip_bufp, 2777 SRC_DISCARDf); 2778 } 2779 } 2780 if (SOC_FAILURE(rv)) { 2781 return rv; 2782 } 2783 2784 vrf_id = vrf; 2785 if (vrf == (SOC_VRF_MAX(u) + 1)) { 2786 vrf_id = SOC_L3_VRF_GLOBAL; 2787 } 2788 rv = _soc_alpm_lpm_ent_init(u, bufp, mem, v6, vrf_id, bucket_index, 2789 0, lpm_entry, 2790 VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 1)); 2791 if (SOC_FAILURE(rv)) { 2792 return rv; 2793 } 2794 /* remember the bpm_len of this pivot. Need to put in shadow */ 2795 *bpm_len = bkt_lpm->len; 2796 } else { 2797 defip_entry_t *lpm_key; 2798 2799 lpm_key = v6 ? VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) : 2800 VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf); 2801 sal_memcpy(lpm_entry, lpm_key, sizeof(defip_entry_t)); 2802 2803 /* the sip ad does not matter here */ 2804 soc_L3_DEFIPm_field32_set(u, lpm_entry, ALG_BKT_PTR0f, bucket_index); 2805 } 2806 2807 /* Convert is a self-modified op, thus use tmp one */ 2808 sal_memcpy(tmp_pivot, pivot, sizeof(tmp_pivot)); 2809 2810 /* Convert from trie format to h/w format */ 2811 ALPM_TRIE_TO_NORMAL_IP(tmp_pivot, length, v6); 2812 (void) _soc_alpm_lpm_ent_key_init(u, tmp_pivot, length, vrf, v6, 2813 lpm_entry, 0); 2814 2815 return rv; 2816 } 2817 2818 static int 2819 _soc_alpm_split_pivot_create_undo(int u, int v6, int vrf, uint32 *pivot, 2820 uint32 length, alpm_pivot_t *alpm_pivot, 2821 int clear) 2822 { 2823 int rv = SOC_E_NONE, pivot_index; 2824 alpm_bucket_handle_t *bucket_handle; 2825 trie_t *pivot_trie = NULL; 2826 trie_node_t *delp = NULL; 2827 2828 if (v6) { 2829 pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf); 2830 } else { 2831 pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf); 2832 } 2833 2834 if (alpm_pivot == NULL) { 2835 rv = trie_delete(pivot_trie, pivot, length, &delp); 2836 alpm_pivot = (alpm_pivot_t *) delp; 2837 } 2838 if (SOC_SUCCESS(rv)) { 2839 bucket_handle = alpm_pivot->bucket; 2840 pivot_index = PIVOT_TCAM_INDEX(alpm_pivot); 2841 2842 trie_destroy(PIVOT_BUCKET_TRIE(alpm_pivot)); 2843 sal_free(alpm_pivot); 2844 sal_free(bucket_handle); 2845 2846 /* For normal destroy (other than rollback) when the entry is deleted 2847 * from lpm. The pivot_index is already replaced to another index. 2848 */ 2849 if (clear) { 2850 ALPM_TCAM_PIVOT(u, pivot_index) = NULL; 2851 } 2852 } 2853 2854 return rv; 2855 } 2856 static int 2857 _soc_alpm_split_pivot_create(int u, int v6, int vrf, int bucket_index, 2858 trie_node_t *split_trie_root, 2859 uint32 *pivot, 2860 uint32 length, 2861 uint32 bpm_len, 2862 alpm_pivot_t **new_pivot) 2863 { 2864 int rv = SOC_E_NONE; 2865 alpm_pivot_t *pivot_pyld; 2866 alpm_bucket_handle_t *bucket_handle; 2867 trie_t *pivot_trie = NULL; 2868 if (v6) { 2869 pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf); 2870 } else { 2871 pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf); 2872 } 2873 2874 /* Add New Pivot to the pivot trie */ 2875 bucket_handle = sal_alloc(sizeof(alpm_bucket_handle_t), 2876 "ALPM Bucket Handle"); 2877 if (bucket_handle == NULL) { 2878 LOG_ERROR(BSL_LS_SOC_ALPM, 2879 (BSL_META_U(u, 2880 "Unable to allocate memory " 2881 "for PIVOT trie node \n"))); 2882 return SOC_E_MEMORY; 2883 } 2884 sal_memset(bucket_handle, 0, sizeof(*bucket_handle)); 2885 pivot_pyld = sal_alloc(sizeof(alpm_pivot_t), 2886 "Payload for new Pivot"); 2887 if (pivot_pyld == NULL) { 2888 LOG_ERROR(BSL_LS_SOC_ALPM, 2889 (BSL_META_U(u, 2890 "Unable to allocate memory " 2891 "for PIVOT trie node \n"))); 2892 sal_free(bucket_handle); 2893 return SOC_E_MEMORY; 2894 } 2895 sal_memset(pivot_pyld, 0, sizeof(*pivot_pyld)); 2896 PIVOT_BUCKET_HANDLE(pivot_pyld) = bucket_handle; 2897 (void) trie_init(v6 ? _MAX_KEY_LEN_144_ :_MAX_KEY_LEN_48_, 2898 &PIVOT_BUCKET_TRIE(pivot_pyld)); 2899 PIVOT_BUCKET_TRIE(pivot_pyld)->trie = split_trie_root; 2900 PIVOT_BUCKET_INDEX(pivot_pyld) = bucket_index; 2901 PIVOT_BUCKET_VRF(pivot_pyld) = vrf; 2902 PIVOT_BUCKET_IPV6(pivot_pyld) = v6; 2903 PIVOT_BUCKET_DEF(pivot_pyld) = FALSE; 2904 PIVOT_TCAM_BPMLEN(pivot_pyld)= bpm_len; 2905 2906 (pivot_pyld)->key[0] = pivot[0]; 2907 (pivot_pyld)->key[1] = pivot[1]; 2908 (pivot_pyld)->key[2] = pivot[2]; 2909 (pivot_pyld)->key[3] = pivot[3]; 2910 (pivot_pyld)->key[4] = pivot[4]; 2911 (pivot_pyld)->len = length; 2912 2913 /* insert into pivot trie */ 2914 rv = trie_insert(pivot_trie, pivot, NULL, length, 2915 (trie_node_t *)pivot_pyld); 2916 if (SOC_SUCCESS(rv)) { 2917 if (new_pivot) { 2918 *new_pivot = pivot_pyld; 2919 } 2920 } else { 2921 LOG_ERROR(BSL_LS_SOC_ALPM, 2922 (BSL_META_U(u, 2923 "failed to insert into pivot trie\n"))); 2924 _soc_alpm_split_pivot_create_undo(u, v6, vrf, pivot, 2925 length, pivot_pyld, 1); 2926 } 2927 2928 return rv; 2929 } 2930 2931 static int 2932 _soc_alpm_bucket_split(int u, alpm_pfx_info_t *pfx_info, int *index_ptr) 2933 { 2934 trie_node_t *split_trie_root; 2935 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 2936 uint32 length, bpm_len = 0; 2937 uint32 bank_disable = 0; 2938 uint32 pivot[5] = {0}; 2939 uint32 src_discard, src_default; 2940 int key_index, i; 2941 trie_t *bkt_trie; 2942 defip_entry_t lpm_entry; 2943 alpm_mem_prefix_array_t *pfx_array = NULL; 2944 int *new_index = NULL; 2945 int rv = SOC_E_NONE, new_index_pos = -1; 2946 int tcam_index, pivot_index; 2947 alpm_pivot_t *new_pivot = NULL; 2948 int v6 = (L3_DEFIP_ALPM_IPV6_64m == pfx_info->mem || 2949 L3_DEFIP_ALPM_IPV6_64_1m == pfx_info->mem || 2950 L3_DEFIP_ALPM_IPV6_128m == pfx_info->mem); 2951 #ifdef ALPM_USE_RAW_VIEW 2952 void *raw_bkt[RAW_BKT_NUM] = {0}; 2953 #else 2954 void *bufp = NULL, *sip_bufp = NULL; 2955 #endif 2956 enum { 2957 _SPLIT_TRIE_NONE, 2958 _SPLIT_TRIE_SPLIT, 2959 _SPLIT_LPM_INIT, 2960 _SPLIT_PIVOT_CREATE, 2961 _SPLIT_PREPARE, 2962 _SPLIT_COPY, 2963 _SPLIT_LPM_INSERT, 2964 _SPLIT_INVALIDATE 2965 } doing = _SPLIT_TRIE_NONE, done = _SPLIT_TRIE_NONE; 2966 2967 doing = _SPLIT_TRIE_SPLIT; 2968 bkt_trie = PIVOT_BUCKET_TRIE(ALPM_TCAM_PIVOT(u, pfx_info->pivot_idx_from)); 2969 rv = trie_split(bkt_trie, v6 ? _MAX_KEY_LEN_144_ : _MAX_KEY_LEN_48_, FALSE, 2970 pivot, &length, &split_trie_root, NULL, FALSE, 1024); 2971 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 2972 2973 doing = _SPLIT_LPM_INIT; 2974 rv = _soc_alpm_split_lpm_init(u, 2975 pfx_info->mem, 2976 pfx_info->vrf, 2977 pfx_info->log_bkt_to, 2978 pfx_info->alpm_data, 2979 pfx_info->alpm_sip_data, 2980 pivot, length, 2981 &lpm_entry, &bpm_len, 2982 &src_discard, &src_default); 2983 2984 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 2985 2986 doing = _SPLIT_PIVOT_CREATE; 2987 rv = _soc_alpm_split_pivot_create(u, v6, pfx_info->vrf, pfx_info->log_bkt_to, 2988 split_trie_root, pivot, length, bpm_len, 2989 &new_pivot); 2990 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 2991 2992 /* Optimized Memory invalidate, 2993 * Invalidate need to happen only after all the entries are 2994 * written to the new pivot and the new pivot is valid. Otherwise 2995 * there is a chance of MISS. 2996 * 2997 * hitless move: 2998 * - Move entries to new bucket. 2999 * - activate new pivot 3000 * - delete entries from old bucket 3001 */ 3002 bank_disable = soc_alpm_bank_dis(u, pfx_info->vrf); 3003 3004 doing = _SPLIT_PREPARE; 3005 #ifdef ALPM_USE_RAW_VIEW 3006 rv = _soc_alpm_raw_bucket_prepare(u, pfx_info->mem, PIVOT_BUCKET_TRIE(new_pivot), 3007 pfx_info->log_bkt_from, pfx_info->log_bkt_to, 3008 bank_disable, 3009 pfx_info->alpm_data, pfx_info->alpm_sip_data, 3010 &pfx_array, raw_bkt, &new_index, 3011 &new_index_pos, 0); 3012 #else 3013 rv = _soc_alpm_bucket_prepare(u, pfx_info->mem, PIVOT_BUCKET_TRIE(new_pivot), 3014 &pfx_array, &bufp, &sip_bufp, &new_index); 3015 #endif 3016 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3017 3018 doing = _SPLIT_COPY; 3019 3020 #ifdef ALPM_USE_RAW_VIEW 3021 rv = _soc_alpm_raw_bucket_copy(u, pfx_info->mem, pfx_info->log_bkt_to, 3022 bank_disable, raw_bkt[RAW_NEW_BKT_DIP], 3023 raw_bkt[RAW_NEW_BKT_SIP], 3024 new_index, pfx_array->count); 3025 #else 3026 rv = _soc_alpm_bucket_copy(u, pfx_info->mem, pfx_info->vrf, pfx_array, 3027 pfx_info->log_bkt_to, 3028 bufp, sip_bufp, pfx_info->alpm_data, 3029 pfx_info->alpm_sip_data, new_index, &new_index_pos); 3030 #endif 3031 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3032 3033 doing = _SPLIT_LPM_INSERT; 3034 rv = soc_alpm_lpm_insert(u, &lpm_entry, &tcam_index, src_default, src_discard, bpm_len); 3035 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3036 3037 /* TCAM index from lpm code is logical. Convert to physical idx */ 3038 tcam_index = soc_alpm_physical_idx(u, L3_DEFIPm, tcam_index, v6); 3039 pivot_index = tcam_index << (v6 ? 1 : 0); 3040 PIVOT_TCAM_INDEX(new_pivot) = pivot_index; 3041 ALPM_TCAM_PIVOT(u, pivot_index) = new_pivot; 3042 3043 doing = _SPLIT_INVALIDATE; 3044 #ifdef ALPM_USE_RAW_VIEW 3045 rv = _soc_alpm_raw_bucket_inval(u, pfx_info->mem, pfx_info->log_bkt_from, 3046 bank_disable, 3047 raw_bkt[RAW_OLD_BKT_DIP], 3048 raw_bkt[RAW_OLD_BKT_SIP], 3049 raw_bkt[RAW_RB_BKT_DIP], 3050 raw_bkt[RAW_RB_BKT_SIP]); 3051 #else 3052 rv = _soc_alpm_bucket_inval(u, pfx_info->mem, pfx_array, bufp, sip_bufp); 3053 #endif 3054 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3055 3056 if (new_index_pos != -1) { /* New prefix goes to new split bucket */ 3057 *index_ptr = new_index[new_index_pos]; 3058 } else { /* To old parent bucket, do actual insert */ 3059 /* Add Entry to old bucket RAM */ 3060 rv = _soc_alpm_insert_in_bkt(u, pfx_info->mem, pfx_info->log_bkt_from, /* this should be from old pivot*/ 3061 bank_disable, pfx_info->alpm_data, pfx_info->alpm_sip_data, 3062 e, &key_index, v6); 3063 3064 if (SOC_FAILURE(rv)) { 3065 /* recover by matching trie state to h/w state */ 3066 LOG_ERROR(BSL_LS_SOC_ALPM, 3067 (BSL_META_U(u, "Could not insert new " 3068 "prefix into trie after split\n"))); 3069 /* since split was successful, leave split state as-is */ 3070 pfx_info->log_bkt_to = -1; 3071 return rv; 3072 } 3073 3074 *index_ptr = key_index; 3075 } 3076 3077 PIVOT_BUCKET_ENT_CNT_UPDATE(new_pivot); 3078 VRF_BUCKET_SPLIT_INC(u, pfx_info->vrf, v6); 3079 3080 /* Update new index */ 3081 for (i = 0; i < pfx_array->count; i++) { 3082 pfx_array->prefix[i]->index = new_index[i]; 3083 } 3084 #ifdef ALPM_USE_RAW_VIEW 3085 _soc_alpm_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index); 3086 #else 3087 _soc_alpm_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index); 3088 #endif 3089 3090 return rv; 3091 3092 _rollback: 3093 /* fall through on all cases */ 3094 switch (done) { 3095 case _SPLIT_LPM_INSERT: 3096 soc_alpm_lpm_delete(u, &lpm_entry); 3097 3098 case _SPLIT_COPY: 3099 /* Delete entries in new bucket */ 3100 #ifdef ALPM_USE_RAW_VIEW 3101 _soc_alpm_raw_bucket_copy_undo(u, pfx_info->mem, pfx_info->log_bkt_to, bank_disable, 3102 raw_bkt[RAW_NEW_BKT_DIP], 3103 raw_bkt[RAW_NEW_BKT_SIP], new_index, pfx_array->count); 3104 #else 3105 _soc_alpm_bucket_copy_undo(u, pfx_info->mem, pfx_array->count, new_index); 3106 #endif 3107 3108 case _SPLIT_PREPARE: 3109 #ifdef ALPM_USE_RAW_VIEW 3110 _soc_alpm_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index); 3111 #else 3112 _soc_alpm_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index); 3113 #endif 3114 3115 case _SPLIT_PIVOT_CREATE: 3116 _soc_alpm_split_pivot_create_undo(u, v6, pfx_info->vrf, pivot, length, NULL, 0); 3117 3118 case _SPLIT_LPM_INIT: 3119 /* nothing to undo */ 3120 3121 case _SPLIT_TRIE_SPLIT: 3122 trie_merge(bkt_trie, split_trie_root, pivot, length); 3123 3124 case _SPLIT_TRIE_NONE: 3125 default: 3126 /* nothing to rollback for first step */ 3127 break; 3128 } 3129 3130 switch (doing) { 3131 case _SPLIT_TRIE_SPLIT: 3132 LOG_ERROR(BSL_LS_SOC_ALPM, 3133 (BSL_META_U(u, 3134 "Could not split bucket"))); 3135 break; 3136 3137 case _SPLIT_PIVOT_CREATE: 3138 LOG_ERROR(BSL_LS_SOC_ALPM, 3139 (BSL_META_U(u, "failed to insert into pivot bkt_trie\n"))); 3140 break; 3141 3142 case _SPLIT_LPM_INSERT: 3143 LOG_ERROR(BSL_LS_SOC_ALPM, 3144 (BSL_META_U(u, 3145 "Unable to add new pivot to tcam\n"))); 3146 3147 if (rv == SOC_E_FULL) { 3148 VRF_PIVOT_FULL_INC(u, pfx_info->vrf, v6); 3149 } 3150 break; 3151 default: 3152 LOG_ERROR(BSL_LS_SOC_ALPM, 3153 (BSL_META_U(u, 3154 "Split fails at step %d\n"), doing)); 3155 break; 3156 } 3157 3158 return rv; 3159 } 3160 3161 3162 /* 3163 * Insert entry into ALPM database. 3164 * Returns SOC_E_NONE, if found and updated. 3165 * SOC_E_FAIL, if insert failed. 3166 */ 3167 static int 3168 _soc_alpm_insert(int u, 3169 int v6, 3170 void *key_data, /* TCAM entry data */ 3171 soc_mem_t mem, /* Mem view for ALPM data */ 3172 void *alpm_data, /* Alpm data to be updated with */ 3173 void *alpm_sip_data, 3174 int *index_ptr, 3175 int bucket_index, 3176 int tcam_index) 3177 { 3178 alpm_pivot_t *old_pivot; 3179 defip_aux_scratch_entry_t aux_entry; 3180 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 3181 uint32 prefix[5], length; 3182 int vrf, vrf_id; 3183 int key_index; 3184 int rv = SOC_E_NONE; 3185 uint32 db_type, ent_type, bank_disable; 3186 int hit =0; 3187 int split = 0; 3188 trie_t *bkt_trie = NULL , *pfx_trie = NULL; 3189 trie_node_t *lpmp = NULL, *lpmp2 = NULL; 3190 payload_t *bkt_payload = NULL, *pfx_payload = NULL, *tmp_pyld; 3191 int default_route = 0; 3192 /* Search Result buffers */ 3193 alpm_pfx_info_t pfx_info; 3194 int new_bucket_index = -1; 3195 int bkt_trie_inserted = 0, pfx_trie_inserted = 0; 3196 int shuffled = 0; 3197 int aux_flags = 0; 3198 3199 SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf)); 3200 bank_disable = soc_alpm_bank_dis(u, vrf); 3201 soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type); 3202 3203 /* Get table memory. */ 3204 SOC_ALPM_TABLE_MEM(u, v6, mem, VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 1)); 3205 3206 /* Insert the prefix into the bucket trie, whether the insert was 3207 * successul or resulted in Split. Spliting the trie after insertion 3208 * yeilds better pivot and better split. 3209 */ 3210 /* Create Prefix */ 3211 rv = _alpm_prefix_create(u, key_data, prefix, &length, &default_route); 3212 if (SOC_FAILURE(rv)) { 3213 LOG_ERROR(BSL_LS_SOC_ALPM, 3214 (BSL_META_U(u, 3215 "_soc_alpm_insert: prefix create failed\n"))); 3216 return rv; 3217 } 3218 3219 /* Fill in AUX Scratch and perform PREFIX Operation */ 3220 sal_memset(&aux_entry, 0, sizeof(defip_aux_scratch_entry_t)); 3221 SOC_IF_ERROR_RETURN( 3222 _soc_alpm_fill_aux_entry_for_op(u, key_data, v6, db_type, ent_type, 0, 3223 &aux_entry)); 3224 3225 if (bucket_index == 0) { 3226 if (SOC_ALPM_SW_LOOKUP(u)) { 3227 rv = _soc_alpm_sw_pivot_find(u, prefix, length, v6, vrf, &hit, 3228 &tcam_index, &bucket_index); 3229 SOC_IF_ERROR_RETURN(rv); 3230 } else { 3231 /* no cookie provided */ 3232 SOC_IF_ERROR_RETURN(_soc_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry, 3233 TRUE, &hit, &tcam_index, &bucket_index, 0)); 3234 } 3235 3236 if (hit == 0) { 3237 LOG_ERROR(BSL_LS_SOC_ALPM, 3238 (BSL_META_U(u, 3239 "_soc_alpm_insert: " 3240 "Could not find bucket to insert prefix\n"))); 3241 return SOC_E_NOT_FOUND; 3242 } 3243 } 3244 bucket_index &= ~SOC_ALPM_V6_SCALE_CHECK(u, v6); 3245 3246 /* entry shouldn't exist, insert the entry into the RAM */ 3247 rv = _soc_alpm_insert_in_bkt(u, mem, bucket_index, 3248 bank_disable, alpm_data, alpm_sip_data, 3249 e, &key_index, v6); 3250 3251 if (rv == SOC_E_NONE) { 3252 *index_ptr = key_index; 3253 } else if (rv == SOC_E_FULL) { 3254 /* The wish count is a matter of choice, but it must be bigger than 3255 * old_count to yeild a better result: find a new home as much 3256 * as possible to avoid split. 3257 * The sense behind this is splitting will result in repartition, 3258 * which is more costly. 3259 */ 3260 rv = soc_alpm_assign(u, vrf, mem, &new_bucket_index, &shuffled); 3261 SOC_IF_ERROR_RETURN(rv); 3262 if (shuffled) { 3263 if (SOC_ALPM_SW_LOOKUP(u)) { 3264 rv = _soc_alpm_sw_pivot_find(u, prefix, length, v6, vrf, &hit, 3265 &tcam_index, &bucket_index); 3266 } else { 3267 rv = _soc_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry, TRUE, &hit, 3268 &tcam_index, &bucket_index, 0); 3269 } 3270 SOC_IF_ERROR_RETURN(rv); 3271 } 3272 3273 split = 1; 3274 /* this indicates a new route, which will be used to decide 3275 * if the new route happens to be new pivot. 3276 */ 3277 key_index = -1; 3278 } else { 3279 return rv; 3280 } 3281 3282 old_pivot = ALPM_TCAM_PIVOT(u, tcam_index); 3283 if (old_pivot == NULL) { 3284 LOG_ERROR(BSL_LS_SOC_ALPM, 3285 (BSL_META_U(u, "ins: pivot index %d bkt %d is not valid \n"), 3286 tcam_index, bucket_index)); 3287 return SOC_E_PARAM; 3288 } 3289 3290 /* Allocate Payload */ 3291 bkt_payload = sal_alloc(sizeof(payload_t), "Payload for Key"); 3292 if (bkt_payload == NULL) { 3293 LOG_ERROR(BSL_LS_SOC_ALPM, 3294 (BSL_META_U(u, 3295 "Unable to allocate memory for " 3296 "bkt_payload entry\n"))); 3297 rv = SOC_E_MEMORY; 3298 goto _rollback; 3299 } 3300 3301 pfx_payload = sal_alloc(sizeof(payload_t), "Payload for pfx trie key"); 3302 if (pfx_payload == NULL) { 3303 LOG_ERROR(BSL_LS_SOC_ALPM, 3304 (BSL_META_U(u, 3305 "Unable to allocate memory for " 3306 "pfx trie node\n"))); 3307 rv = SOC_E_MEMORY; 3308 goto _rollback; 3309 } 3310 sal_memset(bkt_payload, 0, sizeof(*bkt_payload)); 3311 sal_memset(pfx_payload, 0, sizeof(*pfx_payload)); 3312 sal_memcpy(bkt_payload->key, prefix, sizeof(prefix)); 3313 bkt_payload->len = length; 3314 /* Needs update for split case, updated below */ 3315 bkt_payload->index = key_index; 3316 /* create duplicate for prefix bkt_trie */ 3317 sal_memcpy(pfx_payload, bkt_payload, sizeof(*bkt_payload)); 3318 pfx_payload->bkt_ptr = bkt_payload; 3319 3320 /* Insert the prefix */ 3321 /* bucket trie insert */ 3322 bkt_trie = PIVOT_BUCKET_TRIE(old_pivot); 3323 rv = trie_insert(bkt_trie, prefix, NULL, length, (trie_node_t *)bkt_payload); 3324 if (SOC_SUCCESS(rv)) { 3325 bkt_trie_inserted = 1; 3326 } else { 3327 goto _rollback; 3328 } 3329 3330 /* prefix trie insert */ 3331 if (v6) { 3332 pfx_trie = VRF_PREFIX_TRIE_IPV6(u, vrf); 3333 } else { 3334 pfx_trie = VRF_PREFIX_TRIE_IPV4(u, vrf); 3335 } 3336 if (!default_route) { 3337 /* default route already in trie */ 3338 rv = trie_insert(pfx_trie, prefix, NULL, length, 3339 (trie_node_t *)pfx_payload); 3340 if (SOC_SUCCESS(rv)) { 3341 pfx_trie_inserted = 1; 3342 } 3343 } else { 3344 /* update the default route */ 3345 lpmp = NULL; 3346 rv = trie_find_lpm(pfx_trie, 0, 0, &lpmp); 3347 tmp_pyld = (payload_t *) lpmp; 3348 if (SOC_SUCCESS(rv)) { 3349 tmp_pyld->bkt_ptr = bkt_payload; 3350 } 3351 } 3352 if (SOC_FAILURE(rv)) { 3353 goto _rollback; 3354 } 3355 3356 /* Performs lazy splitting */ 3357 if (split) { /* Split */ 3358 sal_memset(&pfx_info, 0, sizeof(pfx_info)); 3359 pfx_info.pivot_idx_from = tcam_index; 3360 pfx_info.alpm_data = alpm_data; 3361 pfx_info.alpm_sip_data = alpm_sip_data; 3362 pfx_info.log_bkt_from = bucket_index; 3363 pfx_info.log_bkt_to = new_bucket_index; 3364 pfx_info.vrf = vrf; 3365 pfx_info.mem = mem; 3366 rv = _soc_alpm_bucket_split(u, &pfx_info, index_ptr); 3367 if (rv != SOC_E_NONE) { 3368 new_bucket_index = pfx_info.log_bkt_to; 3369 goto _rollback; 3370 } 3371 bkt_payload->index = *index_ptr; 3372 /* New Pivot */ 3373 soc_alpm_dbg_cnt[u].bkt_split++; 3374 } 3375 3376 /* from here on, we don't expect any failure */ 3377 3378 /* propagate the insertion */ 3379 if (default_route) { 3380 /* also free unused pfx_payload pointer */ 3381 sal_free(pfx_payload); 3382 } 3383 3384 if (SOC_URPF_STATUS_GET(u)) { 3385 if (soc_mem_field32_get(u, mem, alpm_sip_data, DEFAULTROUTEf)) { 3386 aux_flags |= SOC_ALPM_AUX_DEF_ROUTE; 3387 } 3388 if (soc_mem_field32_get(u, mem, alpm_sip_data, SRC_DISCARDf)) { 3389 aux_flags |= SOC_ALPM_AUX_SRC_DISCARD; 3390 } 3391 } 3392 3393 SOC_IF_ERROR_RETURN(_soc_alpm_aux_op(u, INSERT_PROPAGATE, &aux_entry, 3394 TRUE, &hit, &tcam_index, &bucket_index, aux_flags)); 3395 3396 /* For debug, update the old pivot's counter */ 3397 PIVOT_BUCKET_ENT_CNT_UPDATE(old_pivot); 3398 return rv; 3399 3400 _rollback: 3401 if (!default_route && pfx_trie_inserted) { 3402 (void)trie_delete(pfx_trie, prefix, length, &lpmp); 3403 } 3404 3405 if (bkt_trie_inserted) { 3406 (void)trie_delete(bkt_trie, prefix, length, &lpmp2); 3407 } 3408 3409 if (pfx_payload) { 3410 sal_free(pfx_payload); 3411 } 3412 3413 if (bkt_payload) { 3414 sal_free(bkt_payload); 3415 } 3416 3417 if (split && new_bucket_index != -1) { 3418 /* for non-split case, the new logical bucket is taking effect and thus 3419 * should not be released 3420 */ 3421 (void)alpm_bucket_release(u, new_bucket_index, v6); 3422 } 3423 return rv; 3424 } 3425 3426 3427 3428 /* Build an LPM entry, from a key */ 3429 /* Mostly used for the match */ 3430 static int 3431 _soc_alpm_lpm_ent_key_init(int unit, uint32 *key, int len, int vrf, int ipv6, 3432 defip_entry_t *lpm_entry, int init) 3433 { 3434 uint32 mask; 3435 3436 /* Zero buffers. */ 3437 if (init) { 3438 sal_memset(lpm_entry, 0, sizeof(defip_entry_t)); 3439 } 3440 3441 /* and with mask to ensure global vrf gets set to 0 */ 3442 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, VRF_ID_0f, 3443 vrf & SOC_VRF_MAX(unit)); 3444 if (vrf == (SOC_VRF_MAX(unit) + 1)) { 3445 /* for global routes */ 3446 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f, 0); 3447 } else { 3448 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f, 3449 SOC_VRF_MAX(unit)); 3450 } 3451 3452 if (ipv6) { 3453 /* Set address to the buffer. */ 3454 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, IP_ADDR0f, key[0]); 3455 3456 /* Set address to the buffer. */ 3457 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, IP_ADDR1f, key[1]); 3458 /* Set mode to ipv6 */ 3459 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, MODE0f, 1); 3460 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, MODE1f, 1); 3461 3462 /* Set Virtual Router id */ 3463 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, VRF_ID_1f, vrf & 3464 SOC_VRF_MAX(unit)); 3465 if (vrf == (SOC_VRF_MAX(unit) + 1)) { 3466 /* for global routes */ 3467 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK1f, 0); 3468 } else { 3469 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK1f, 3470 SOC_VRF_MAX(unit)); 3471 } 3472 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, VALID1f, 1); 3473 3474 if (len >= 32) { 3475 mask = 0xffffffff; 3476 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, mask); 3477 mask = ~SHR_SHIFT_RIGHT(0xffffffff, len - 32); 3478 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, mask); 3479 } else { 3480 mask = ~(0xffffffff >> len); 3481 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, mask); 3482 /* make sure lower word of mask is 0 */ 3483 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, 0); 3484 } 3485 } else { 3486 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, IP_ADDR0f, key[0]); 3487 3488 /* Set address to the buffer. */ 3489 assert(len <= 32); 3490 mask = (len == 32) ? 0xffffffff : ~(0xffffffff >> len); 3491 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, mask); 3492 } 3493 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, VALID0f, 1); 3494 3495 /* Set Mode Masks */ 3496 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, MODE_MASK0f, 3497 (1 << soc_mem_field_length(unit, L3_DEFIPm, MODE_MASK0f)) - 1); 3498 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, MODE_MASK1f, 3499 (1 << soc_mem_field_length(unit, L3_DEFIPm, MODE_MASK1f)) - 1); 3500 3501 /* Set Entry Type Masks */ 3502 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, ENTRY_TYPE_MASK0f, 3503 (1 << soc_mem_field_length(unit, L3_DEFIPm, 3504 ENTRY_TYPE_MASK0f)) - 1); 3505 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, ENTRY_TYPE_MASK1f, 3506 (1 << soc_mem_field_length(unit, L3_DEFIPm, 3507 ENTRY_TYPE_MASK1f)) - 1); 3508 /* 3509 * Note ipv4 entries are expected to reside in part 0 of the entry. 3510 * ipv6 entries both parts should be filled. 3511 * Hence if entry is ipv6 copy part 0 to part 1 3512 */ 3513 return (SOC_E_NONE); 3514 } 3515 3516 3517 int 3518 _soc_alpm_delete_in_bkt(int u, soc_mem_t mem, int delete_bucket, 3519 int bank_disable, void *bufp2, uint32 *e, 3520 int *key_index, int v6) 3521 { 3522 int rv; 3523 3524 rv = soc_mem_alpm_delete(u, mem, delete_bucket, MEM_BLOCK_ALL, 3525 bank_disable, bufp2, e, key_index); 3526 if (SOC_SUCCESS(rv)) { 3527 return rv; 3528 } 3529 if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) { 3530 return soc_mem_alpm_delete(u, mem, delete_bucket + 1, MEM_BLOCK_ALL, 3531 bank_disable, bufp2, e, key_index); 3532 } 3533 return rv; 3534 } 3535 3536 3537 #ifdef CHECK_CLEAN_BKT 3538 static int 3539 _soc_alpm_bkt_count(int u, soc_mem_t mem, int bkt_idx, int v6, void *bufp) 3540 { 3541 int bank, entry; 3542 int addr, rv; 3543 int count = 0; 3544 3545 for (bank = 0; bank < 4; bank++) { 3546 for (entry = 0; entry < (v6 ? 4 : 6); entry++) { 3547 addr = (entry << 16) | (bkt_idx << 2) | (bank & 3); 3548 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, addr, bufp); 3549 SOC_IF_ERROR_RETURN(rv); 3550 if (soc_mem_field32_get(u, mem, bufp, VALIDf)) { 3551 count++; 3552 } 3553 } 3554 } 3555 return count; 3556 } 3557 #endif /* CHECK_CLEAN_BKT */ 3558 3559 /* 3560 * Delete entry from ALPM database. 3561 * Returns SOC_E_NONE, if found and updated. 3562 * SOC_E_FAIL, if insert failed. 3563 * If default route replace with internal default 3564 */ 3565 static int 3566 _soc_alpm_delete(int u, void *key_data, int bucket_index, 3567 int tcam_index, int key_index, int propagate) /* TCAM entry data */ 3568 { 3569 alpm_pivot_t *pivot_pyld; 3570 /* Search Result buffer */ 3571 defip_alpm_ipv4_1_entry_t alpmv4_entry, alpmv4_sip_entry, alpmv42; 3572 defip_alpm_ipv6_64_1_entry_t alpmv6_entry, alpmv6_sip_entry, alpmv62; 3573 defip_aux_scratch_entry_t aux_entry; 3574 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 3575 soc_mem_t mem; 3576 void *bufp, *bufp2, *sip_bufp = NULL; 3577 int vrf_id; 3578 int ipv6; 3579 int rv = SOC_E_NONE, rv2; 3580 uint32 prop_pfx[5], prefix[5]; 3581 int v6, vrf; 3582 uint32 length; 3583 int delete_bucket; 3584 uint32 db_type, ent_type, bank_disable; 3585 int hit, default_route = 0; 3586 trie_t *trie, *pfx_trie; 3587 uint32 bpm_pfx_len; 3588 defip_entry_t lpm_entry, *lpm_key; 3589 payload_t *payload = NULL, *pfx_pyld = NULL, *tmp_pyld = NULL; 3590 trie_node_t *delp = NULL, *lpmp = NULL; 3591 trie_t *pivot_trie = NULL; 3592 int aux_flags = 0; 3593 3594 ipv6 = v6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0f); 3595 if (v6) { 3596 if (!(v6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE1f))) { 3597 return (SOC_E_PARAM); 3598 } 3599 } 3600 3601 SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf)); 3602 3603 /* For VRF_OVERRIDE (Global High) entries, software needs to maintain the 3604 * index, Prefix resides in TCAM directly. Handling of these functions are 3605 * taken care by main insert */ 3606 soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type); 3607 if (vrf_id != SOC_L3_VRF_OVERRIDE) { 3608 bank_disable = soc_alpm_bank_dis(u, vrf); 3609 3610 /* Create Prefix */ 3611 rv = _alpm_prefix_create(u, key_data, prefix, &length, &default_route); 3612 3613 if (SOC_FAILURE(rv)) { 3614 LOG_ERROR(BSL_LS_SOC_ALPM, 3615 (BSL_META_U(u, 3616 "_soc_alpm_delete: prefix create failed\n"))); 3617 return rv; 3618 } 3619 if (!soc_alpm_mode_get(u)) { 3620 if (vrf_id != SOC_L3_VRF_GLOBAL) { 3621 /* allow default deletion only at end */ 3622 if (VRF_TRIE_ROUTES_CNT(u, vrf_id, vrf, v6) > 1) { 3623 if (default_route) { 3624 LOG_ERROR(BSL_LS_SOC_ALPM, 3625 (BSL_META_U(u, 3626 "VRF %d: Cannot delete default " 3627 "route if other routes are present in " 3628 "this mode"), vrf)); 3629 return SOC_E_PARAM; 3630 } 3631 } 3632 } 3633 } 3634 3635 /* Get table memory. */ 3636 SOC_ALPM_TABLE_MEM(u, v6, mem, VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 0)); 3637 3638 /* Assign entry buf based on table being used */ 3639 SOC_ALPM_ENTRY_BUF(v6, mem, bufp, alpmv4_entry, alpmv6_entry); 3640 SOC_ALPM_ENTRY_BUF(v6, mem, bufp2, alpmv42, alpmv62); 3641 3642 SOC_ALPM_LPM_LOCK(u); 3643 3644 if (bucket_index == 0) { 3645 /* Search the entry */ 3646 rv = _soc_alpm_find(u, key_data, mem, bufp, &tcam_index, 3647 &bucket_index, &key_index, 3648 SOC_ALPM_SW_LOOKUP(u)); 3649 } else { 3650 /* key_data has all the info including search result */ 3651 rv = _soc_alpm_mem_ent_init(u, key_data, bufp, 0, mem, 0, 0); 3652 } 3653 3654 /* save results as they are lost later */ 3655 sal_memcpy(bufp2, bufp, v6 ? sizeof(alpmv6_entry) : 3656 sizeof(alpmv4_entry)); 3657 3658 if (SOC_FAILURE(rv)) { 3659 SOC_ALPM_LPM_UNLOCK(u); 3660 LOG_ERROR(BSL_LS_SOC_ALPM, 3661 (BSL_META_U(u, 3662 "_soc_alpm_delete: Unable to find prefix for delete\n"))); 3663 return rv; 3664 } 3665 3666 /* Entry found 3667 * 1> Delete entry from trie 3668 * 2> Find Best Prefix Match 3669 * 3> Update bpm using replacement prefix op 3670 * 4> Invalidate Entry in the ALPM database 3671 */ 3672 /* Delete the prefix from trie*/ 3673 /* Store index to invalidate the prefix */ 3674 delete_bucket = bucket_index & ~SOC_ALPM_V6_SCALE_CHECK(u, ipv6); 3675 3676 pivot_pyld = ALPM_TCAM_PIVOT(u, tcam_index); 3677 if (pivot_pyld == NULL) { 3678 LOG_ERROR(BSL_LS_SOC_ALPM, 3679 (BSL_META_U(u, "del: pivot index %d bkt %d is not valid \n"), 3680 tcam_index, bucket_index)); 3681 SOC_ALPM_LPM_UNLOCK(u); 3682 return SOC_E_PARAM; 3683 } 3684 3685 trie = PIVOT_BUCKET_TRIE(pivot_pyld); 3686 3687 rv = trie_delete(trie, prefix, length, &delp); 3688 payload = (payload_t *) delp; 3689 if (rv != SOC_E_NONE) { 3690 LOG_ERROR(BSL_LS_SOC_ALPM, 3691 (BSL_META_U(u, 3692 "_soc_alpm_delete: Error prefix not present in trie \n"))); 3693 SOC_ALPM_LPM_UNLOCK(u); 3694 return rv; 3695 } 3696 3697 /* prefix trie delete */ 3698 if (v6) { 3699 pfx_trie = VRF_PREFIX_TRIE_IPV6(u, vrf); 3700 } else { 3701 pfx_trie = VRF_PREFIX_TRIE_IPV4(u, vrf); 3702 } 3703 3704 if (v6) { 3705 pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf); 3706 } else { 3707 pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf); 3708 } 3709 3710 if (!default_route) { 3711 rv = trie_delete(pfx_trie, prefix, length, &delp); 3712 pfx_pyld = (payload_t *) delp; 3713 3714 if (SOC_FAILURE(rv)) { 3715 /* continue anyway to minimize state mismatch */ 3716 LOG_ERROR(BSL_LS_SOC_ALPM, 3717 (BSL_META_U(u, 3718 "_soc_alpm_delete: Prefix not present in pfx" 3719 "trie: 0x%08x 0x%08x\n"), 3720 prefix[0], prefix[1])); 3721 goto recover_bkt_trie; 3722 } 3723 3724 if (propagate) { 3725 /* Find Best prefix match for the prefix */ 3726 lpmp = NULL; 3727 rv = trie_find_lpm(pfx_trie, prefix, length, &lpmp); 3728 tmp_pyld = (payload_t *) lpmp; 3729 if (SOC_SUCCESS(rv)) { 3730 payload_t *t = (payload_t *)(tmp_pyld->bkt_ptr); 3731 if (t != NULL) { 3732 /* this means a real default route exists */ 3733 bpm_pfx_len = t->len; 3734 } else { 3735 /* only internal default route exists */ 3736 /* this should happen only if the lpm is a default route */ 3737 bpm_pfx_len = 0; 3738 } 3739 } else { 3740 LOG_ERROR(BSL_LS_SOC_ALPM, 3741 (BSL_META_U(u, 3742 "_soc_alpm_delete: Could not find replacement" 3743 "bpm for prefix: 0x%08x 0x%08x\n"), 3744 prefix[0], prefix[1])); 3745 goto recover_pfx_trie; 3746 } 3747 3748 /* Initialize an lpm enty to perform a match */ 3749 /* not expected to fail */ 3750 3751 3752 sal_memcpy(prop_pfx, prefix, sizeof(prefix)); 3753 ALPM_TRIE_TO_NORMAL_IP(prop_pfx, length, v6); 3754 (void) _soc_alpm_lpm_ent_key_init(u, prop_pfx, bpm_pfx_len, vrf, ipv6, 3755 &lpm_entry, 1); 3756 3757 /* Find Associated data for the bpm */ 3758 rv = _soc_alpm_find(u, &lpm_entry, mem, bufp, &tcam_index, 3759 &bucket_index, &key_index, 3760 SOC_ALPM_SW_LOOKUP(u)); 3761 if (SOC_SUCCESS(rv)) { 3762 /* convert associated data to lpm entry format */ 3763 (void) _soc_alpm_lpm_ent_init(u, bufp, mem, ipv6, vrf_id, 3764 bucket_index, 0, &lpm_entry, 0); 3765 3766 /* set key to the prefix being deleted */ 3767 (void) _soc_alpm_lpm_ent_key_init(u, prop_pfx, length, vrf, ipv6, 3768 &lpm_entry, 0); 3769 3770 if (SOC_URPF_STATUS_GET(u)) { 3771 SOC_ALPM_ENTRY_BUF(v6, mem, sip_bufp, alpmv4_sip_entry, 3772 alpmv6_sip_entry); 3773 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, 3774 _soc_alpm_rpf_entry(u, key_index), sip_bufp); 3775 3776 if (soc_mem_field32_get(u, mem, sip_bufp, DEFAULTROUTEf)) { 3777 aux_flags |= SOC_ALPM_AUX_DEF_ROUTE; 3778 } 3779 if (soc_mem_field32_get(u, mem, sip_bufp, SRC_DISCARDf)) { 3780 aux_flags |= SOC_ALPM_AUX_SRC_DISCARD; 3781 } 3782 } 3783 3784 } else if (bpm_pfx_len == 0) { 3785 /* could not find a default route. Use internal default */ 3786 /* default route's associated data */ 3787 3788 lpm_key = v6 ? VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) : 3789 VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf); 3790 sal_memcpy(&lpm_entry, lpm_key, sizeof(lpm_entry)); 3791 /* set key to the prefix being deleted */ 3792 (void) _soc_alpm_lpm_ent_key_init(u, prop_pfx, length, vrf, ipv6, 3793 &lpm_entry, 0); 3794 /* the sip ad does not matter here */ 3795 rv = SOC_E_NONE; 3796 } 3797 3798 if (SOC_FAILURE(rv)) { 3799 LOG_ERROR(BSL_LS_SOC_ALPM, 3800 (BSL_META_U(u, 3801 "_soc_alpm_delete: Could not find replacement" 3802 " prefix for prefix: 0x%08x 0x%08x, prop_pfx:" 3803 " 0x%08x 0x%08x, bpm_len %d \n"), 3804 prefix[0], prefix[1], 3805 prop_pfx[0], prop_pfx[1], bpm_pfx_len)); 3806 goto recover_pfx_trie; 3807 } 3808 3809 lpm_key = &lpm_entry; 3810 } 3811 3812 } else { /* !default_route */ 3813 /* remove the real default route reference if any */ 3814 lpmp = NULL; 3815 rv = trie_find_lpm(pfx_trie, prefix, length, &lpmp); 3816 tmp_pyld = (payload_t *) lpmp; 3817 if (SOC_FAILURE(rv)) { 3818 LOG_ERROR(BSL_LS_SOC_ALPM, 3819 (BSL_META_U(u, 3820 "_soc_alpm_delete: Could not find default " 3821 "route in the trie for vrf %d\n"), vrf)); 3822 goto recover_bkt_trie; 3823 } 3824 tmp_pyld->bkt_ptr = NULL; 3825 bpm_pfx_len = 0; 3826 lpm_key = v6 ? VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) : 3827 VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf); 3828 } 3829 3830 if (propagate) { 3831 rv = _soc_alpm_fill_aux_entry_for_op(u, lpm_key, v6, db_type, ent_type, 3832 bpm_pfx_len, &aux_entry); 3833 if (SOC_FAILURE(rv)) { 3834 goto recover_pfx_trie; 3835 } 3836 3837 /* Perform Delete propagate */ 3838 rv = _soc_alpm_aux_op(u, DELETE_PROPAGATE, &aux_entry, TRUE, &hit, 3839 &tcam_index, &bucket_index, aux_flags); 3840 3841 if (SOC_FAILURE(rv)) { 3842 goto recover_pfx_trie; 3843 } 3844 } 3845 3846 /* From here on don't try to recover trie state */ 3847 sal_free(payload); 3848 if (!default_route) { 3849 sal_free(pfx_pyld); 3850 } 3851 3852 /* For debug, update the pivot's counter */ 3853 PIVOT_BUCKET_ENT_CNT_UPDATE(pivot_pyld); 3854 3855 if ((pivot_pyld->len != 0) && (trie->trie == NULL)) { /* Empty bucket */ 3856 uint32 hw_key[5]; 3857 sal_memcpy(hw_key, pivot_pyld->key, sizeof(hw_key)); 3858 ALPM_TRIE_TO_NORMAL_IP(hw_key, pivot_pyld->len, ipv6); 3859 3860 /* Initialize an lpm entry to perform a match */ 3861 (void) _soc_alpm_lpm_ent_key_init(u, hw_key, pivot_pyld->len, 3862 vrf, ipv6, &lpm_entry, 1); 3863 3864 /* delete entry from TCAM */ 3865 rv = soc_alpm_lpm_delete(u, &lpm_entry); 3866 if (SOC_FAILURE(rv)) { 3867 LOG_ERROR(BSL_LS_SOC_ALPM, 3868 (BSL_META_U(u, 3869 "_soc_alpm_delete: Unable to " 3870 "delete pivot 0x%08x 0x%08x \n"), 3871 pivot_pyld->key[0], pivot_pyld->key[1])); 3872 /* continue to clean up still */ 3873 } 3874 } 3875 3876 /* Invalidate the route */ 3877 rv = _soc_alpm_delete_in_bkt(u, mem, delete_bucket, bank_disable, 3878 bufp2, e, &key_index, v6); 3879 if (!SOC_SUCCESS(rv)) { 3880 LOG_ERROR(BSL_LS_SOC_ALPM, 3881 (BSL_META_U(u, 3882 "_soc_th_alpm_delete_in_bkt: Unable to " 3883 "delete phy bkt 0x%08x \n"), delete_bucket)); 3884 SOC_ALPM_LPM_UNLOCK(u); 3885 rv = SOC_E_FAIL; 3886 return rv; 3887 } 3888 3889 /* delete corresponding RPF entry if it exists */ 3890 if (SOC_URPF_STATUS_GET(u)) { 3891 /* hit is an unused variable */ 3892 rv = _soc_alpm_delete_in_bkt(u, mem, 3893 SOC_ALPM_RPF_BKT_IDX(u, delete_bucket), 3894 bank_disable, 3895 bufp2, e, &hit, v6); 3896 if (!SOC_SUCCESS(rv)) { 3897 LOG_ERROR(BSL_LS_SOC_ALPM, 3898 (BSL_META_U(u, 3899 "_soc_th_alpm_delete_in_bkt: Unable to " 3900 "delete phy bkt 0x%08x \n"), 3901 SOC_ALPM_RPF_BKT_IDX(u, delete_bucket))); 3902 SOC_ALPM_LPM_UNLOCK(u); 3903 rv = SOC_E_FAIL; 3904 return rv; 3905 } 3906 } 3907 3908 if ((pivot_pyld->len != 0) && (trie->trie == NULL)) { /* Empty bucket */ 3909 /* Release Bucket */ 3910 rv = alpm_bucket_release(u, PIVOT_BUCKET_INDEX(pivot_pyld), v6); 3911 if (SOC_FAILURE(rv)) { 3912 LOG_ERROR(BSL_LS_SOC_ALPM, 3913 (BSL_META_U(u, 3914 "_soc_alpm_delete: Unable to release" 3915 "empty bucket: %d\n"), 3916 PIVOT_BUCKET_INDEX(pivot_pyld))); 3917 /* we lose this bucket */ 3918 } 3919 3920 /* remove pivot from pivot trie */ 3921 rv = trie_delete(pivot_trie, pivot_pyld->key, pivot_pyld->len, &delp); 3922 if (SOC_FAILURE(rv)) { 3923 LOG_ERROR(BSL_LS_SOC_ALPM, 3924 (BSL_META_U(u, 3925 "could not delete pivot from pivot trie\n"))); 3926 } 3927 3928 /* Free up Bucket trie */ 3929 trie_destroy(PIVOT_BUCKET_TRIE(pivot_pyld)); 3930 3931 /* Free up Bucket handle */ 3932 sal_free(PIVOT_BUCKET_HANDLE(pivot_pyld)); 3933 3934 /* free Pivot structure */ 3935 sal_free(pivot_pyld); 3936 3937 #ifdef CHECK_CLEAN_BKT 3938 /* make sure bucket is indeed empty */ 3939 assert(_soc_alpm_bkt_count(u, mem, delete_bucket, v6, 3940 bufp) == 0); 3941 #endif /* CHECK_CLEAN_BKT */ 3942 } 3943 } 3944 VRF_TRIE_ROUTES_DEC(u, vrf_id, vrf, v6); 3945 if (VRF_TRIE_ROUTES_CNT(u, vrf_id, vrf, v6) == 0) { 3946 /* vrf is empty. Release resources */ 3947 rv = soc_alpm_vrf_delete(u, vrf, v6); 3948 } 3949 SOC_ALPM_LPM_UNLOCK(u); 3950 return rv; 3951 3952 /* Recovery from error: */ 3953 /* add back pivot bucket trie entry */ 3954 /* add back prefix trie entry */ 3955 recover_pfx_trie: 3956 rv2 = trie_insert(pfx_trie, prefix, NULL, length, (trie_node_t *) 3957 pfx_pyld); 3958 if (SOC_FAILURE(rv2)) { 3959 LOG_ERROR(BSL_LS_SOC_ALPM, 3960 (BSL_META_U(u, 3961 "_soc_alpm_delete: Unable to reinsert" 3962 "prefix 0x%08x 0x%08x into pfx trie\n"), 3963 prefix[0], prefix[1])); 3964 } 3965 recover_bkt_trie: 3966 rv2 = trie_insert(trie, prefix, NULL, length, (trie_node_t *) payload); 3967 if (SOC_FAILURE(rv2)) { 3968 LOG_ERROR(BSL_LS_SOC_ALPM, 3969 (BSL_META_U(u, 3970 "_soc_alpm_delete: Unable to reinsert" 3971 "prefix 0x%08x 0x%08x into bkt trie\n"), 3972 prefix[0], prefix[1])); 3973 } 3974 3975 SOC_ALPM_LPM_UNLOCK(u); 3976 return rv; 3977 } 3978 3979 /** 3980 * IPMC_MISS signal is never asserted after an unsuccessful L3_DEFIP table 3981 * lookup for IPMC packets when IPMC (PIM-SM, PIM-BIDIR) forwarding is enabled 3982 * in TD2+. Due to this, the forwarding logic miss forwards IPMC 3983 * packets to an incorrect (or invalid) IPMC group. 3984 * 3985 * WAR: Add two default rules as last entries in L3_DEFIP (TCAM) table such that 3986 * all IPV4 and IPV6 multicast packets will, by default, hit these entries, if 3987 * any specific IPMC were not added in the L3_DEFIP table. Thus L3_DEFIP lookup 3988 * for IPMC packets will never result in a miss. 3989 * 3990 * Packets copied to CPU due to IPMC_MISS will have OPCODE set as 4 3991 * (IP Multicast) as opposed to 3 (L2 Multicast). This may cause some mismatches 3992 * in case of CPU bound packets compared to legacy XGS devices. 3993 */ 3994 int 3995 soc_alpm_ipmc_war(int unit, int install) 3996 { 3997 int i, ipv6 = 0; 3998 int index = -1; 3999 defip_entry_t lpm_entry; 4000 soc_mem_t mem = L3_DEFIPm; 4001 int count = 1; 4002 int num_rp = 63; 4003 4004 if (!(soc_feature(unit, soc_feature_alpm) && 4005 soc_feature(unit, soc_feature_td2p_a0_sw_war) && 4006 soc_property_get(unit, spn_L3_ALPM_ENABLE, 0))) { 4007 return SOC_E_NONE; 4008 } 4009 4010 if (!SOC_ALPM_LPM_INIT_CHECK(unit)) { 4011 return SOC_E_NONE; 4012 } 4013 4014 if (!SOC_IS_TRIDENT2PLUS(unit)) { 4015 return SOC_E_NONE; 4016 } 4017 4018 if (SOC_WARM_BOOT(unit)) { 4019 return SOC_E_NONE; 4020 } 4021 4022 if (soc_mem_index_count(unit, L3_DEFIPm) <= 0) { 4023 return SOC_E_NONE; 4024 } 4025 4026 if (soc_mem_index_count(unit, L3_DEFIP_PAIR_128m) <= 0) { 4027 count = 2; 4028 } 4029 4030 num_rp = soc_mem_field_length(unit, 4031 ING_ACTIVE_L3_IIF_PROFILEm, RPA_ID_PROFILEf); 4032 4033 /* First loop for ipv4, second loop for ipv6 */ 4034 for (i = 0; i < count; i++) { 4035 /* Zero Buffer */ 4036 sal_memset(&lpm_entry, 0, soc_mem_entry_words(unit, mem) * 4); 4037 ipv6 = i; 4038 4039 soc_mem_field32_set(unit, mem, &lpm_entry, VALID0f, 1); 4040 soc_mem_field32_set(unit, mem, &lpm_entry, MODE_MASK0f, 3); 4041 soc_mem_field32_set(unit, mem, &lpm_entry, ENTRY_TYPE_MASK0f, 1); 4042 soc_mem_field32_set(unit, mem, &lpm_entry, MULTICAST_ROUTE0f, 1); 4043 soc_mem_field32_set(unit, mem, &lpm_entry, GLOBAL_ROUTE0f, 1); 4044 soc_mem_field32_set(unit, mem, &lpm_entry, RPA_ID0f, num_rp - 1); 4045 soc_mem_field32_set(unit, mem, &lpm_entry, EXPECTED_L3_IIF0f, 16383); 4046 4047 if (ipv6) { 4048 soc_mem_field32_set(unit, mem, &lpm_entry, VALID1f, 1); 4049 soc_mem_field32_set(unit, mem, &lpm_entry, MODE0f, 1); 4050 soc_mem_field32_set(unit, mem, &lpm_entry, MODE1f, 1); 4051 soc_mem_field32_set(unit, mem, &lpm_entry, MODE_MASK1f, 3); 4052 soc_mem_field32_set(unit, mem, &lpm_entry, ENTRY_TYPE_MASK1f, 1); 4053 soc_mem_field32_set(unit, mem, &lpm_entry, MULTICAST_ROUTE1f, 1); 4054 soc_mem_field32_set(unit, mem, &lpm_entry, GLOBAL_ROUTE1f, 1); 4055 soc_mem_field32_set(unit, mem, &lpm_entry, RPA_ID1f, num_rp - 1); 4056 /* 16383 indicate a max field value which is used as an invalid value */ 4057 soc_mem_field32_set(unit, mem, &lpm_entry, EXPECTED_L3_IIF1f, 16383); 4058 4059 soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR0f, 0); 4060 soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR_MASK0f, 0); 4061 /* IPv6 multicast route address starts from ff00 for default match */ 4062 soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR1f, 0xff000000); 4063 soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR_MASK1f, 0xff000000); 4064 } else { 4065 /* IPv4 multicast route address starts from 224 for default match */ 4066 soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR0f, 0xe0000000); 4067 soc_mem_field32_set(unit, mem, &lpm_entry, IP_ADDR_MASK0f, 0xe0000000); 4068 } 4069 4070 if (install) { 4071 if (soc_feature(unit, soc_feature_alpm_flex_stat)) { 4072 soc_mem_field32_set(unit, mem, &lpm_entry, ENTRY_VIEW0f, 0x1); 4073 VRF_FLEX_SET(unit, SOC_L3_VRF_GLOBAL, SOC_VRF_MAX(unit) + 1, ipv6, 1); 4074 } 4075 SOC_IF_ERROR_RETURN(soc_alpm_lpm_insert(unit, &lpm_entry, &index, 4076 0, 0, INVALID_BPM_LEN)); 4077 } else { 4078 SOC_IF_ERROR_RETURN(soc_alpm_lpm_delete(unit, &lpm_entry)); 4079 } 4080 } 4081 4082 return SOC_E_NONE; 4083 } 4084 4085 /* Initialize ALPM Subsytem */ 4086 int 4087 soc_alpm_init(int u) 4088 { 4089 int i; 4090 int rv = SOC_E_NONE; 4091 4092 if (SOC_ALPM_LPM_INIT_CHECK(u)) { 4093 /* this is a reinit. clean up old state */ 4094 if (soc_alpm_deinit(u) < 0) { 4095 return SOC_E_INTERNAL; 4096 } 4097 } 4098 4099 /* Initialize ALPM control */ 4100 rv = _soc_alpm_ctrl_init(u); 4101 SOC_IF_ERROR_RETURN(rv); 4102 4103 /* Initialize TCAM Memory management */ 4104 rv = soc_alpm_lpm_init(u); 4105 SOC_IF_ERROR_RETURN(rv); 4106 4107 /* Initialize ALPM memory management */ 4108 rv = soc_alpm_shared_mem_init(u); 4109 4110 alpm_vrf_handle[u] = sal_alloc((MAX_VRF_ID + 1) * sizeof(alpm_vrf_handle_t), "ALPM VRF Handles"); 4111 if (alpm_vrf_handle[u] == NULL) { 4112 return SOC_E_MEMORY; 4113 } 4114 4115 tcam_pivot[u] = sal_alloc(MAX_PIVOT_COUNT * sizeof(alpm_pivot_t *), "ALPM pivots"); 4116 if (tcam_pivot[u] == NULL) { 4117 return SOC_E_MEMORY; 4118 } 4119 sal_memset(alpm_vrf_handle[u], 0, (MAX_VRF_ID + 1) * sizeof(alpm_vrf_handle_t)); 4120 sal_memset(tcam_pivot[u], 0, MAX_PIVOT_COUNT * sizeof(alpm_pivot_t *)); 4121 sal_memset(&soc_alpm_dbg_cnt[u], 0, sizeof(_alpm_int_dbg_cnt_t)); 4122 4123 /* Initialize PIVOT management */ 4124 for (i = 0; i < MAX_PIVOT_COUNT; i++) { 4125 ALPM_TCAM_PIVOT(u, i) = NULL; 4126 } 4127 4128 if (SOC_CONTROL(u)->alpm_bulk_retry == NULL) { 4129 SOC_CONTROL(u)->alpm_bulk_retry = 4130 sal_sem_create("ALPM bulk retry", sal_sem_BINARY, 0); 4131 } 4132 if (SOC_CONTROL(u)->alpm_lookup_retry == NULL) { 4133 SOC_CONTROL(u)->alpm_lookup_retry = 4134 sal_sem_create("ALPM lookup retry", sal_sem_BINARY, 0); 4135 } 4136 if (SOC_CONTROL(u)->alpm_insert_retry == NULL) { 4137 SOC_CONTROL(u)->alpm_insert_retry = 4138 sal_sem_create("ALPM insert retry", sal_sem_BINARY, 0); 4139 } 4140 if (SOC_CONTROL(u)->alpm_delete_retry == NULL) { 4141 SOC_CONTROL(u)->alpm_delete_retry = 4142 sal_sem_create("ALPM delete retry", sal_sem_BINARY, 0); 4143 } 4144 4145 rv = soc_alpm_128_lpm_init(u); 4146 SOC_IF_ERROR_RETURN(rv); 4147 4148 (void)soc_alpm_ipmc_war(u, TRUE); 4149 4150 return rv; 4151 } 4152 4153 4154 /* clear alpm related internal state */ 4155 static int soc_alpm_state_clear(int u) 4156 { 4157 int i, rv; 4158 alpm_pivot_t *tmp; 4159 4160 /* clear all pivot state */ 4161 for (i = 0; i < MAX_PIVOT_COUNT; i++) { 4162 tmp = ALPM_TCAM_PIVOT(u, i); 4163 if (tmp) { 4164 if (PIVOT_BUCKET_HANDLE(tmp)) { 4165 if (PIVOT_BUCKET_TRIE(tmp)) { 4166 /* traverse bucket trie and clear it */ 4167 rv = trie_traverse(PIVOT_BUCKET_TRIE(tmp), 4168 alpm_delete_node_cb, NULL, _TRIE_INORDER_TRAVERSE); 4169 if (SOC_SUCCESS(rv)) { 4170 trie_destroy(PIVOT_BUCKET_TRIE(tmp)); 4171 } else { 4172 LOG_ERROR(BSL_LS_SOC_ALPM, 4173 (BSL_META_U(u, 4174 "Unable to clear trie state for unit %d\n"), 4175 u)); 4176 return rv; 4177 } 4178 } 4179 sal_free(PIVOT_BUCKET_HANDLE(tmp)); 4180 } 4181 sal_free(ALPM_TCAM_PIVOT(u, i)); 4182 ALPM_TCAM_PIVOT(u, i) = NULL; 4183 } 4184 } 4185 4186 /* clear all prefix tries */ 4187 for (i = 0; i <= SOC_VRF_MAX(u) + 1; i++) { 4188 rv = trie_traverse(VRF_PREFIX_TRIE_IPV4(u, i), alpm_delete_node_cb, 4189 NULL, _TRIE_INORDER_TRAVERSE); 4190 if (SOC_SUCCESS(rv)) { 4191 trie_destroy(VRF_PREFIX_TRIE_IPV4(u, i)); 4192 } else { 4193 LOG_ERROR(BSL_LS_SOC_ALPM, 4194 (BSL_META_U(u, 4195 "unit: %d Unable to clear v4 pfx trie for vrf %d\n"), 4196 u, i)); 4197 return rv; 4198 } 4199 rv = trie_traverse(VRF_PREFIX_TRIE_IPV6(u, i), alpm_delete_node_cb, 4200 NULL, _TRIE_INORDER_TRAVERSE); 4201 if (SOC_SUCCESS(rv)) { 4202 trie_destroy(VRF_PREFIX_TRIE_IPV6(u, i)); 4203 } else { 4204 LOG_ERROR(BSL_LS_SOC_ALPM, 4205 (BSL_META_U(u, 4206 "unit: %d Unable to clear v6 pfx trie for vrf %d\n"), 4207 u, i)); 4208 return rv; 4209 } 4210 if (VRF_TRIE_DEFAULT_ROUTE_IPV4(u, i) != NULL) { 4211 sal_free(VRF_TRIE_DEFAULT_ROUTE_IPV4(u, i)); 4212 } 4213 if (VRF_TRIE_DEFAULT_ROUTE_IPV6(u, i) != NULL) { 4214 sal_free(VRF_TRIE_DEFAULT_ROUTE_IPV6(u, i)); 4215 } 4216 sal_memset(&alpm_vrf_handle[u][i], 0, sizeof(alpm_vrf_handle_t)); 4217 } 4218 4219 /* Reset VRF_OVERRIDE debug counter */ 4220 sal_memset(&alpm_vrf_handle[u][MAX_VRF_ID], 0, sizeof(alpm_vrf_handle_t)); 4221 /* Mark Global Hi (VRF_OVERRIDE) for IPv4, IPv6-64, IPv6-128 inited for debug usage */ 4222 VRF_TRIE_INIT_DONE(u, MAX_VRF_ID, 0, 1); 4223 VRF_TRIE_INIT_DONE(u, MAX_VRF_ID, 1, 1); 4224 VRF_TRIE_INIT_DONE(u, MAX_VRF_ID, 2, 1); 4225 4226 if (SOC_ALPM_BUCKET_BMAP(u) != NULL) { 4227 sal_free(SOC_ALPM_BUCKET_BMAP(u)); 4228 } 4229 sal_memset(&soc_alpm_bucket[u], 0, sizeof(soc_alpm_bucket_t)); 4230 sal_memset(&soc_alpm_dbg_cnt[u], 0, sizeof(_alpm_int_dbg_cnt_t)); 4231 4232 /* Free memory allocated for VRF handles and tcam pivots */ 4233 if (alpm_vrf_handle[u]) 4234 sal_free(alpm_vrf_handle[u]); 4235 if (tcam_pivot[u]) 4236 sal_free(tcam_pivot[u]); 4237 alpm_vrf_handle[u] = NULL; 4238 tcam_pivot[u] = NULL; 4239 return SOC_E_NONE; 4240 } 4241 4242 /* De-Init ALPM Subsytem */ 4243 int 4244 soc_alpm_deinit(int u) 4245 { 4246 soc_alpm_lpm_deinit(u); 4247 4248 SOC_IF_ERROR_RETURN(soc_alpm_128_lpm_deinit(u)); 4249 4250 SOC_IF_ERROR_RETURN(soc_alpm_128_state_clear(u)); 4251 4252 SOC_IF_ERROR_RETURN(soc_alpm_state_clear(u)); 4253 4254 if (SOC_CONTROL(u)->alpm_bulk_retry) { 4255 sal_sem_destroy(SOC_CONTROL(u)->alpm_bulk_retry); 4256 SOC_CONTROL(u)->alpm_bulk_retry = NULL; 4257 } 4258 if (SOC_CONTROL(u)->alpm_lookup_retry) { 4259 sal_sem_destroy(SOC_CONTROL(u)->alpm_lookup_retry); 4260 SOC_CONTROL(u)->alpm_lookup_retry = NULL; 4261 } 4262 if (SOC_CONTROL(u)->alpm_insert_retry) { 4263 sal_sem_destroy(SOC_CONTROL(u)->alpm_insert_retry); 4264 SOC_CONTROL(u)->alpm_insert_retry = NULL; 4265 } 4266 if (SOC_CONTROL(u)->alpm_delete_retry) { 4267 sal_sem_destroy(SOC_CONTROL(u)->alpm_delete_retry); 4268 SOC_CONTROL(u)->alpm_delete_retry = NULL; 4269 } 4270 4271 return SOC_E_NONE; 4272 } 4273 4274 4275 /* 4276 * soc_alpm_vrf_add 4277 * Add a VRF default route when a L3 VRF is added 4278 * Adds a 0.0 entry into VRF 4279 */ 4280 static int 4281 soc_alpm_vrf_add(int u, int vrf, int v6) 4282 { 4283 defip_entry_t *lpm_entry = NULL, tmp_lpm; 4284 int bucket_pointer; 4285 int index; 4286 int rv = SOC_E_NONE; 4287 uint32 key[5] = {0}; 4288 uint32 length; 4289 alpm_bucket_handle_t *bucket_handle = NULL; 4290 alpm_pivot_t *pivot_pyld = NULL; 4291 payload_t *pfx_pyld = NULL; 4292 trie_t *prefix_root = NULL, *bucket_root = NULL; 4293 int prefix_root_inserted = 0; 4294 trie_t *pivot_root = NULL; 4295 int pivot_root_inserted = 0; 4296 soc_mem_t mem; 4297 4298 SOC_ALPM_TABLE_MEM(u, v6, mem, VRF_FLEX_IS_SET(u, vrf, vrf, v6, 1)); 4299 rv = soc_alpm_assign(u, vrf, mem, &bucket_pointer, NULL); 4300 if (SOC_FAILURE(rv)) { 4301 return rv; 4302 } 4303 4304 /* Allocate bucket handle */ 4305 bucket_handle = sal_alloc(sizeof(alpm_bucket_handle_t), "ALPM Bucket Handle"); 4306 if (bucket_handle == NULL) { 4307 LOG_ERROR(BSL_LS_SOC_ALPM, 4308 (BSL_META_U(u, 4309 "soc_alpm_vrf_add: Unable to allocate memory for " 4310 "PIVOT trie node \n"))); 4311 rv = SOC_E_MEMORY; 4312 goto cleanup; 4313 } 4314 sal_memset(bucket_handle, 0, sizeof(*bucket_handle)); 4315 4316 /* Allocate PIVOT Payload */ 4317 pivot_pyld = sal_alloc(sizeof(alpm_pivot_t), "Payload for Pivot"); 4318 if (pivot_pyld == NULL) { 4319 LOG_ERROR(BSL_LS_SOC_ALPM, 4320 (BSL_META_U(u, 4321 "soc_alpm_vrf_add: Unable to allocate memory for " 4322 "PIVOT trie node \n"))); 4323 rv = SOC_E_MEMORY; 4324 goto cleanup; 4325 } 4326 sal_memset(pivot_pyld, 0, sizeof(*pivot_pyld)); 4327 PIVOT_BUCKET_HANDLE(pivot_pyld) = bucket_handle; 4328 4329 /* Allocate Prefix Payload */ 4330 pfx_pyld = sal_alloc(sizeof(payload_t), "Payload for pfx trie key"); 4331 if (pfx_pyld == NULL) { 4332 LOG_ERROR(BSL_LS_SOC_ALPM, 4333 (BSL_META_U(u, 4334 "soc_alpm_vrf_add: Unable to allocate memory for " 4335 "pfx trie node \n"))); 4336 rv = SOC_E_MEMORY; 4337 goto cleanup; 4338 } 4339 sal_memset(pfx_pyld, 0, sizeof(*pfx_pyld)); 4340 4341 /* Initialize VRF pivot trie */ 4342 if (v6 == 0) { 4343 rv = trie_init(_MAX_KEY_LEN_48_, &VRF_PIVOT_TRIE_IPV4(u, vrf)); 4344 pivot_root = VRF_PIVOT_TRIE_IPV4(u, vrf); 4345 } else { 4346 rv = trie_init(_MAX_KEY_LEN_144_, &VRF_PIVOT_TRIE_IPV6(u, vrf)); 4347 pivot_root = VRF_PIVOT_TRIE_IPV6(u, vrf); 4348 } 4349 if (SOC_FAILURE(rv)) { 4350 goto cleanup; 4351 } 4352 4353 /* Initialize VRF prefix trie */ 4354 if (v6 == 0) { 4355 rv = trie_init(_MAX_KEY_LEN_48_, &VRF_PREFIX_TRIE_IPV4(u, vrf)); 4356 prefix_root = VRF_PREFIX_TRIE_IPV4(u, vrf); 4357 } else { 4358 rv = trie_init(_MAX_KEY_LEN_144_, &VRF_PREFIX_TRIE_IPV6(u, vrf)); 4359 prefix_root = VRF_PREFIX_TRIE_IPV6(u, vrf); 4360 } 4361 if (SOC_FAILURE(rv)) { 4362 goto cleanup; 4363 } 4364 4365 /* Initialize bucket trie */ 4366 if (v6) { 4367 rv = trie_init(_MAX_KEY_LEN_144_, &PIVOT_BUCKET_TRIE(pivot_pyld)); 4368 } else { 4369 rv = trie_init(_MAX_KEY_LEN_48_, &PIVOT_BUCKET_TRIE(pivot_pyld)); 4370 } 4371 bucket_root = PIVOT_BUCKET_TRIE(pivot_pyld); 4372 if (SOC_FAILURE(rv)) { 4373 goto cleanup; 4374 } 4375 PIVOT_BUCKET_INDEX(pivot_pyld) = bucket_pointer; 4376 PIVOT_BUCKET_VRF(pivot_pyld) = vrf; 4377 PIVOT_BUCKET_IPV6(pivot_pyld) = v6; 4378 PIVOT_BUCKET_DEF(pivot_pyld) = TRUE; 4379 4380 /* 0 for default * route */ 4381 length = 0; 4382 pivot_pyld->key[0] = pfx_pyld->key[0] = key[0]; 4383 pivot_pyld->key[1] = pfx_pyld->key[1] = key[1]; 4384 pivot_pyld->len = pfx_pyld->len = length; 4385 rv = trie_insert(prefix_root, key, NULL, length, &(pfx_pyld->node)); 4386 /* no internal default in bucket trie */ 4387 if (SOC_FAILURE(rv)) { 4388 goto cleanup; 4389 } 4390 prefix_root_inserted = 1; 4391 4392 /* insert into trie of pivots */ 4393 rv = trie_insert(pivot_root, key, NULL, length, (trie_node_t *)pivot_pyld); 4394 if (SOC_FAILURE(rv)) { 4395 goto cleanup; 4396 } 4397 pivot_root_inserted = 1; 4398 4399 /* Initialize an lpm entry to perform a match */ 4400 (void) _soc_alpm_lpm_ent_key_init(u, key, 0, vrf, v6, &tmp_lpm, 1); 4401 4402 /* for global VRF */ 4403 if (vrf == SOC_VRF_MAX(u) + 1) { 4404 soc_L3_DEFIPm_field32_set(u, &tmp_lpm, GLOBAL_ROUTE0f, 1); 4405 } else { 4406 /* Set default miss to global route only for non global routes */ 4407 soc_L3_DEFIPm_field32_set(u, &tmp_lpm, DEFAULT_MISS0f, 1); 4408 } 4409 soc_L3_DEFIPm_field32_set(u, &tmp_lpm, ENTRY_VIEW0f, 4410 VRF_FLEX_IS_SET(u, vrf, vrf, v6, 1)); 4411 4412 soc_L3_DEFIPm_field32_set(u, &tmp_lpm, ALG_BKT_PTR0f, bucket_pointer); 4413 4414 /* Allocate default lpm entry */ 4415 lpm_entry = sal_alloc(sizeof(defip_entry_t), "Default LPM entry"); 4416 if (lpm_entry == NULL) { 4417 LOG_ERROR(BSL_LS_SOC_ALPM, 4418 (BSL_META_U(u, 4419 "soc_alpm_vrf_add: unable to allocate memory for " 4420 "IPv4 LPM entry\n"))); 4421 rv = SOC_E_MEMORY; 4422 goto cleanup; 4423 } 4424 sal_memcpy(lpm_entry, &tmp_lpm, sizeof(tmp_lpm)); 4425 4426 /* add Entry into tcam as default routes for the VRF */ 4427 /* urpf could modify the lpm entry. So use tmp one */ 4428 rv = soc_alpm_lpm_insert(u, &tmp_lpm, &index, 0, 0, INVALID_BPM_LEN); 4429 if (SOC_FAILURE(rv)) { 4430 goto cleanup; 4431 } 4432 4433 if (v6 == 0) { 4434 VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf) = lpm_entry; 4435 } else { 4436 VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) = lpm_entry; 4437 } 4438 4439 /* get physical index */ 4440 index = soc_alpm_physical_idx(u, L3_DEFIPm, index, v6); 4441 if (v6 == 0) { 4442 ALPM_TCAM_PIVOT(u, index) = pivot_pyld; 4443 PIVOT_TCAM_INDEX(pivot_pyld) = index; 4444 } else { 4445 ALPM_TCAM_PIVOT(u, index << 1) = pivot_pyld; 4446 PIVOT_TCAM_INDEX(pivot_pyld) = index << 1; 4447 } 4448 4449 PIVOT_TCAM_BPMLEN(pivot_pyld) = length; 4450 VRF_TRIE_INIT_DONE(u, vrf, v6, 1); 4451 4452 return SOC_E_NONE; 4453 4454 cleanup: 4455 if (lpm_entry) { 4456 sal_free(lpm_entry); 4457 } 4458 4459 if (pivot_root_inserted) { 4460 trie_node_t *delp = NULL; 4461 (void) trie_delete(pivot_root, key, length, &delp); 4462 } 4463 4464 if (prefix_root_inserted) { 4465 trie_node_t *delp = NULL; 4466 (void) trie_delete(prefix_root, key, length, &delp); 4467 } 4468 4469 /* destroy inited tries */ 4470 if (bucket_root) { 4471 (void) trie_destroy(bucket_root); 4472 PIVOT_BUCKET_TRIE(pivot_pyld) = NULL; 4473 } 4474 if (prefix_root) { 4475 (void) trie_destroy(prefix_root); 4476 if (v6 == 0) { 4477 VRF_PREFIX_TRIE_IPV4(u, vrf) = NULL; 4478 } else { 4479 VRF_PREFIX_TRIE_IPV6(u, vrf) = NULL; 4480 } 4481 } 4482 if (pivot_root) { 4483 (void) trie_destroy(pivot_root); 4484 if (v6 == 0) { 4485 VRF_PIVOT_TRIE_IPV4(u, vrf) = NULL; 4486 } else { 4487 VRF_PIVOT_TRIE_IPV6(u, vrf) = NULL; 4488 } 4489 } 4490 4491 if (pfx_pyld) { 4492 sal_free(pfx_pyld); 4493 } 4494 if (pivot_pyld) { 4495 sal_free(pivot_pyld); 4496 } 4497 if (bucket_handle) { 4498 sal_free(bucket_handle); 4499 } 4500 4501 (void) alpm_bucket_release(u, bucket_pointer, v6); 4502 return rv; 4503 } 4504 4505 4506 /* 4507 * soc_alpm_vrf_delete 4508 * Delete the VRF default route when a L3 VRF is destroyed 4509 */ 4510 static int 4511 soc_alpm_vrf_delete(int u, int vrf, int v6) 4512 { 4513 defip_entry_t *lpm_entry; 4514 int bucket_pointer; 4515 int idx; 4516 int rv = SOC_E_NONE; 4517 uint32 key[5] = {0}, result[SOC_MAX_MEM_FIELD_WORDS]; 4518 payload_t *payload; 4519 alpm_pivot_t *pivot_pyld1; 4520 trie_node_t *delp; 4521 trie_t *root; 4522 trie_t *pivot_root = NULL; 4523 4524 if (v6 == 0) { 4525 lpm_entry = VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf); 4526 } else { 4527 lpm_entry = VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf); 4528 } 4529 4530 /* find bucket pointers and release them */ 4531 bucket_pointer = soc_L3_DEFIPm_field32_get(u, lpm_entry, ALG_BKT_PTR0f); 4532 rv = alpm_bucket_release(u, bucket_pointer, v6); 4533 4534 /* add Entry into tcam as default routes for the VRF */ 4535 rv = soc_alpm_lpm_match(u, lpm_entry, (void *) result, &idx); 4536 if (SOC_FAILURE(rv)) { 4537 LOG_ERROR(BSL_LS_SOC_ALPM, 4538 (BSL_META_U(u, 4539 "soc_alpm_vrf_delete: unable to get internal" 4540 " pivot idx for vrf %d/%d\n"), vrf, v6)); 4541 idx = -1; 4542 } 4543 4544 idx = soc_alpm_physical_idx(u, L3_DEFIPm, idx, v6); 4545 if (v6 == 0) { 4546 pivot_pyld1 = ALPM_TCAM_PIVOT(u, idx); 4547 } else { 4548 pivot_pyld1 = ALPM_TCAM_PIVOT(u, idx << 1); 4549 } 4550 4551 rv = soc_alpm_lpm_delete(u, lpm_entry); 4552 if (SOC_FAILURE(rv)) { 4553 LOG_ERROR(BSL_LS_SOC_ALPM, 4554 (BSL_META_U(u, 4555 "soc_alpm_vrf_delete: unable to delete lpm entry " 4556 " for internal default for vrf %d/%d\n"), vrf, v6)); 4557 } 4558 4559 sal_free(lpm_entry); 4560 4561 if (v6 == 0) { 4562 VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf) = NULL; 4563 root = VRF_PREFIX_TRIE_IPV4(u, vrf); 4564 VRF_PREFIX_TRIE_IPV4(u, vrf) = NULL; 4565 } else { 4566 VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) = NULL; 4567 root = VRF_PREFIX_TRIE_IPV6(u, vrf); 4568 VRF_PREFIX_TRIE_IPV6(u, vrf) = NULL; 4569 } 4570 VRF_TRIE_INIT_DONE(u, vrf, v6, 0); 4571 4572 rv = trie_delete(root, key, 0, &delp); 4573 payload = (payload_t *) delp; 4574 if (SOC_FAILURE(rv)) { 4575 LOG_ERROR(BSL_LS_SOC_ALPM, 4576 (BSL_META_U(u, 4577 "Unable to delete internal default for vrf " 4578 " %d/%d\n"), vrf, v6)); 4579 } 4580 sal_free(payload); 4581 4582 (void) trie_destroy(root); 4583 4584 if (v6 == 0) { 4585 pivot_root = VRF_PIVOT_TRIE_IPV4(u, vrf); 4586 VRF_PIVOT_TRIE_IPV4(u, vrf) = NULL; 4587 } else { 4588 pivot_root = VRF_PIVOT_TRIE_IPV6(u, vrf); 4589 VRF_PIVOT_TRIE_IPV6(u, vrf) = NULL; 4590 } 4591 4592 delp = NULL; 4593 rv = trie_delete(pivot_root, key, 0, &delp); 4594 if (SOC_FAILURE(rv)) { 4595 LOG_ERROR(BSL_LS_SOC_ALPM, 4596 (BSL_META_U(u, 4597 "Unable to delete internal pivot node for vrf" 4598 " %d/%d\n"), vrf, v6)); 4599 } 4600 (void) trie_destroy(pivot_root); 4601 4602 (void) trie_destroy(PIVOT_BUCKET_TRIE(pivot_pyld1)); 4603 sal_free(PIVOT_BUCKET_HANDLE(pivot_pyld1)); 4604 sal_free(pivot_pyld1); 4605 4606 return rv; 4607 } 4608 4609 /* 4610 * soc_alpm_insert 4611 * For IPV4 assume only both IP_ADDR0 is valid 4612 * Moving multiple entries around in h/w vs doing a linear search in s/w 4613 */ 4614 int 4615 soc_alpm_insert(int u, void *lpm_entry, uint32 flags, int bkt_idx, 4616 int pivot_info) 4617 { 4618 defip_alpm_ipv4_1_entry_t alpmv4_entry, alpmv4_sip_entry; 4619 defip_alpm_ipv6_64_1_entry_t alpmv6_entry, alpmv6_sip_entry; 4620 soc_mem_t mem; 4621 void *bufp, *bufp2; 4622 int vrf_id, vrf; 4623 int index; 4624 int ipv6; 4625 int rv = SOC_E_NONE; 4626 uint32 default_route; 4627 int ipmc_route = 0; 4628 int flex_v6_64 = 0; 4629 4630 ipv6 = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, MODE0f); 4631 4632 /* Get table memory. */ 4633 SOC_ALPM_TABLE_MEM(u, ipv6, mem, flags & SOC_ALPM_STAT_FLEX); 4634 4635 /* Assign entry buf based on table being used */ 4636 SOC_ALPM_ENTRY_BUF(ipv6, mem, bufp, alpmv4_entry, alpmv6_entry); 4637 SOC_ALPM_ENTRY_BUF(ipv6, mem, bufp2, alpmv4_sip_entry, alpmv6_sip_entry); 4638 4639 SOC_IF_ERROR_RETURN( 4640 _soc_alpm_mem_ent_init(u, lpm_entry, bufp, bufp2, mem, flags, 4641 &default_route)); 4642 4643 /* If the entry is override, then insert into TCAM directly */ 4644 SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, lpm_entry, &vrf_id, &vrf)); 4645 4646 if (VRF_FLEX_COMPLETED(u, vrf_id, vrf, ipv6)) { 4647 if (VRF_FLEX_IS_SET(u, vrf_id, vrf, ipv6, 1) != !!(flags & SOC_ALPM_STAT_FLEX)) { 4648 LOG_ERROR(BSL_LS_SOC_ALPM, 4649 (BSL_META_U(u, 4650 "soc_alpm_insert:Flex flag conflict\n" 4651 ))); 4652 return SOC_E_PARAM; 4653 } 4654 } else { 4655 VRF_FLEX_SET(u, vrf_id, vrf, ipv6, flags & SOC_ALPM_STAT_FLEX); 4656 } 4657 4658 if (soc_feature(u, soc_feature_ipmc_defip)) { 4659 ipmc_route = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, MULTICAST_ROUTE0f); 4660 } 4661 4662 if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && ipv6 && 4663 (flags & SOC_ALPM_STAT_FLEX)) { 4664 if (soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f) == 0xFFFFFFFF && 4665 soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f) == 0xFFFFFFFF) { 4666 flex_v6_64 = 1; 4667 } 4668 } 4669 4670 if ((vrf_id != SOC_L3_VRF_OVERRIDE) && 4671 (vrf == 0) && soc_alpm_mode_get(u)) { 4672 /* cannot have 0 as a VRF in parallel mode */ 4673 LOG_ERROR(BSL_LS_SOC_ALPM, 4674 (BSL_META_U(u, 4675 "VRF=0 cannot be added in Parallel mode\n"))); 4676 return SOC_E_PARAM; 4677 } 4678 4679 /* For VRF_OVERRIDE (Global High) entries, and IPMC route 4680 * software needs to maintain the index 4681 */ 4682 /* Prefix resides in TCAM directly */ 4683 if ((vrf_id == SOC_L3_VRF_OVERRIDE) || (ipmc_route) || (flex_v6_64)) { 4684 4685 /* Insert into TCAM directly and return */ 4686 /* search in the hash table */ 4687 rv = soc_alpm_lpm_insert(u, lpm_entry, &index, 0, 4688 flags & SOC_ALPM_RPF_SRC_DISCARD, INVALID_BPM_LEN); 4689 if (SOC_SUCCESS(rv) && !(pivot_info & SOC_ALPM_LPM_LOOKUP_HIT)) { 4690 VRF_TRIE_ROUTES_INC(u, vrf_id, vrf, ipv6); 4691 } 4692 4693 if (rv == SOC_E_FULL) { 4694 VRF_PIVOT_FULL_INC(u, MAX_VRF_ID, ipv6); 4695 } 4696 return(rv); 4697 } 4698 4699 /* combined search mode protection */ 4700 if (vrf_id != SOC_L3_VRF_GLOBAL) { 4701 if (!soc_alpm_mode_get(u)) { 4702 /* for emtpy DB allow insert only if route is default */ 4703 if (VRF_TRIE_ROUTES_CNT(u, vrf_id, vrf, ipv6) == 0) { 4704 /* check if route is default, else throw error */ 4705 if (!default_route) { 4706 LOG_ERROR(BSL_LS_SOC_ALPM, 4707 (BSL_META_U(u, 4708 "VRF %d: First route in a VRF has to " 4709 " be a default route in this mode\n"), vrf_id)); 4710 return SOC_E_PARAM; 4711 } 4712 } 4713 } 4714 } 4715 4716 /* non override entries, goes into ALPM memory */ 4717 if (!VRF_TRIE_INIT_COMPLETED(u, vrf, ipv6)) { 4718 LOG_VERBOSE(BSL_LS_SOC_ALPM, 4719 (BSL_META_U(u, 4720 "soc_alpm_insert:VRF %d is not " 4721 "initialized\n"), vrf)); 4722 rv = soc_alpm_vrf_add(u, vrf, ipv6); 4723 if (SOC_FAILURE(rv)) { 4724 LOG_ERROR(BSL_LS_SOC_ALPM, 4725 (BSL_META_U(u, 4726 "soc_alpm_insert:VRF %d/%d trie init \n" 4727 "failed\n"), vrf, ipv6)); 4728 return rv; 4729 } 4730 LOG_VERBOSE(BSL_LS_SOC_ALPM, 4731 (BSL_META_U(u, 4732 "soc_alpm_insert:VRF %d/%d trie init " 4733 "completed\n"), vrf, ipv6)); 4734 } 4735 4736 /* Find and update the entry */ 4737 if (pivot_info & SOC_ALPM_LOOKUP_HIT) { 4738 rv = _soc_alpm_find_and_update(u, lpm_entry, bufp, bufp2, mem, 4739 bkt_idx); 4740 } else { 4741 /* entry is not found in database */ 4742 /* Insert the entry into the database, if FULL, split the bucket */ 4743 /* Insert prefix into trie */ 4744 /* Split trie : Insertion into trie results into Split */ 4745 /* Allocate a TCAM entry for PIVOT and bucket and move entries */ 4746 if (bkt_idx == -1) { 4747 /* internally 0 is invalid bucket index */ 4748 bkt_idx = 0; 4749 } 4750 rv = _soc_alpm_insert(u, ipv6, lpm_entry, mem, bufp, bufp2, &index, 4751 SOC_ALPM_BKT_ENTRY_TO_IDX(bkt_idx), pivot_info); 4752 if (SOC_SUCCESS(rv)) { 4753 VRF_TRIE_ROUTES_INC(u, vrf_id, vrf, ipv6); 4754 } 4755 } 4756 4757 if (rv != SOC_E_NONE) { 4758 LOG_WARN(BSL_LS_SOC_ALPM, 4759 (BSL_META_U(u, 4760 "unit %d :soc_alpm_insert: Route Insertion Failed :%s\n"), 4761 u, soc_errmsg(rv))); 4762 } 4763 return(rv); 4764 } 4765 4766 4767 /* 4768 * soc_alpm_lookup 4769 * For IPV4 assume only both IP_ADDR0 is valid 4770 * Moving multiple entries around in h/w vs doing a linear search in s/w 4771 */ 4772 int 4773 soc_alpm_lookup(int u, 4774 void *key_data, 4775 void *e, /* return entry data if found */ 4776 int *index_ptr, 4777 int *cookie) 4778 { 4779 defip_alpm_ipv4_1_entry_t alpmv4_entry; /* Search Result buffer */ 4780 defip_alpm_ipv6_64_1_entry_t alpmv6_entry; /* Search Result buffer */ 4781 soc_mem_t mem; 4782 int bucket_index; 4783 int tcam_index = -1; 4784 void *bufp; 4785 int vrf_id, vrf; 4786 int ipv6, pfx; 4787 int rv = SOC_E_NONE; 4788 int ipmc_route = 0; 4789 int flex_v6_64 = 0; 4790 int flex = 0; 4791 4792 ipv6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0f); 4793 4794 /* If the entry is override, then insert into TCAM directly */ 4795 SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf)); 4796 4797 /* First launch lookup directly into tcam. If hit comes from override 4798 * vrf just return it. Else launch lookup into alpm pivots 4799 */ 4800 /* For VRF_OVERRIDE (Global High) entries, software needs to maintain the 4801 * index */ 4802 /* Prefix resides in TCAM directly */ 4803 4804 /* search in the hash table */ 4805 *index_ptr = 0; 4806 rv = _soc_alpm_lpm_match(u, key_data, e, index_ptr, &pfx, &ipv6); 4807 /* 4808 * If entry is ipv4 copy to the "zero" half of the, 4809 * buffer, "zero" half of e if the original entry 4810 * is in the "one" half. 4811 */ 4812 flex = VRF_FLEX_IS_SET(u, vrf_id, vrf, ipv6, 0); 4813 if (SOC_SUCCESS(rv)) { 4814 if (!ipv6 && (*index_ptr & 0x1)) { 4815 rv = soc_alpm_lpm_ip4entry1_to_0(u, e, e, PRESERVE_HIT); 4816 } 4817 if (soc_feature(u, soc_feature_ipmc_defip)) { 4818 ipmc_route = soc_mem_field32_get(u, L3_DEFIPm, e, MULTICAST_ROUTE0f); 4819 } 4820 4821 if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && ipv6 && flex) { 4822 if (soc_mem_field32_get(u, L3_DEFIPm, key_data, IP_ADDR_MASK0f) == 0xFFFFFFFF && 4823 soc_mem_field32_get(u, L3_DEFIPm, key_data, IP_ADDR_MASK1f) == 0xFFFFFFFF) { 4824 flex_v6_64 = 1; 4825 } 4826 } 4827 } 4828 if ((vrf_id == SOC_L3_VRF_OVERRIDE) || (ipmc_route) || (flex_v6_64)) { 4829 *cookie = 0; 4830 if (SOC_SUCCESS(rv)) { 4831 *cookie |= SOC_ALPM_LPM_LOOKUP_HIT; 4832 } 4833 return rv; 4834 } 4835 4836 /* either no hit in OVERRIDE or hit in pivot tcam */ 4837 /* non override entries, go to into ALPM memory */ 4838 if (!VRF_TRIE_INIT_COMPLETED(u, vrf, ipv6)) { 4839 LOG_VERBOSE(BSL_LS_SOC_ALPM, 4840 (BSL_META_U(u, 4841 "soc_alpm_lookup:VRF %d is not initialized\n"), 4842 vrf)); 4843 *cookie = 0; 4844 return SOC_E_NOT_FOUND; 4845 } 4846 /* Get table memory. */ 4847 SOC_ALPM_TABLE_MEM(u, ipv6, mem, flex); 4848 4849 /* Assign entry buf based on table being used */ 4850 SOC_ALPM_ENTRY_BUF(ipv6, mem, bufp, alpmv4_entry, alpmv6_entry); 4851 4852 SOC_ALPM_LPM_LOCK(u); 4853 /* Find and update the entry */ 4854 rv = _soc_alpm_find(u, key_data, mem, bufp, &tcam_index, &bucket_index, 4855 index_ptr, SOC_ALPM_SW_LOOKUP(u)); 4856 SOC_ALPM_LPM_UNLOCK(u); 4857 4858 if (SOC_FAILURE(rv)) { 4859 *cookie = tcam_index; 4860 *index_ptr = bucket_index << 2; 4861 return rv; 4862 } 4863 /* Copy ALPM memory to LPM entry */ 4864 rv = _soc_alpm_lpm_ent_init(u, bufp, mem, ipv6, vrf_id, 4865 bucket_index, *index_ptr, e, flex); 4866 *cookie = SOC_ALPM_LOOKUP_HIT | tcam_index; 4867 if (flex) { 4868 *cookie |= SOC_ALPM_COOKIE_FLEX; 4869 } 4870 return(rv); 4871 } 4872 4873 /* Find a LPM Global low or VRF route in ALPM memory */ 4874 static int 4875 _soc_alpm_find_best_match(int u, 4876 void *key_data, 4877 void *e, /* return entry data if found */ 4878 int vrf_id, 4879 int *tcam_index, 4880 int *bucket_index, 4881 int *key_index, 4882 int do_urpf) 4883 { 4884 int rv = SOC_E_NONE; 4885 int i, j, v6, hit = 0; 4886 uint32 db_type, ent_type, bank_disable; 4887 defip_aux_scratch_entry_t aux_entry; 4888 int global, mvrf, vrf; 4889 int index; 4890 soc_mem_t mem, lpm_mem; 4891 int hw_len, sw_len; 4892 int ent_num; 4893 4894 /* Used for keeping Longest Matched entry in Bucket */ 4895 uint32 alpm_bufp[SOC_MAX_MEM_FIELD_WORDS] = {0}; 4896 int alpm_len = -1; 4897 int alpm_index = 0; 4898 int flex; 4899 4900 soc_field_t ip_addr_fld[2] = { 4901 IP_ADDR0f, 4902 IP_ADDR1f, 4903 }; 4904 4905 lpm_mem = L3_DEFIPm; 4906 v6 = soc_mem_field32_get(u, lpm_mem, key_data, MODE0f); 4907 global = soc_mem_field32_get(u, lpm_mem, key_data, GLOBAL_ROUTE0f); 4908 mvrf = soc_mem_field32_get(u, lpm_mem, key_data, VRF_ID_0f); 4909 vrf = (vrf_id == SOC_L3_VRF_GLOBAL) ? (SOC_VRF_MAX(u) + 1) : mvrf; 4910 4911 LOG_VERBOSE(BSL_LS_SOC_ALPM, 4912 (BSL_META_U(u, 4913 "Prefare AUX Scratch for searching TCAM in " 4914 "%s region, Key data: v6 %d global %d vrf %d:\n"), 4915 vrf_id == SOC_L3_VRF_GLOBAL ? "Global" : "VRF", 4916 v6, global, mvrf)); 4917 soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type); 4918 if (do_urpf) { 4919 db_type ++; 4920 } 4921 if (vrf_id == SOC_L3_VRF_GLOBAL) { 4922 /* Crack these value to use _fill_aux routine */ 4923 soc_mem_field32_set(u, lpm_mem, key_data, GLOBAL_ROUTE0f, 1); 4924 soc_mem_field32_set(u, lpm_mem, key_data, VRF_ID_0f, 0); 4925 } 4926 4927 bank_disable = soc_alpm_bank_dis(u, vrf); 4928 4929 SOC_IF_ERROR_RETURN( 4930 _soc_alpm_fill_aux_entry_for_op(u, key_data, v6, db_type, ent_type, 4931 0, &aux_entry)); 4932 /* Recover to original value */ 4933 if (vrf_id == SOC_L3_VRF_GLOBAL) { 4934 soc_mem_field32_set(u, lpm_mem, key_data, GLOBAL_ROUTE0f, global); 4935 soc_mem_field32_set(u, lpm_mem, key_data, VRF_ID_0f, mvrf); 4936 } 4937 4938 /* Start shadow table engine to search */ 4939 SOC_IF_ERROR_RETURN( 4940 _soc_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry, TRUE, &hit, tcam_index, 4941 bucket_index, 0)); 4942 4943 if (hit == 0) { 4944 LOG_VERBOSE(BSL_LS_SOC_ALPM, 4945 (BSL_META_U(u,"Could not find bucket\n"))); 4946 return SOC_E_NOT_FOUND; 4947 } 4948 4949 LOG_VERBOSE(BSL_LS_SOC_ALPM, 4950 (BSL_META_U(u, "Hit in memory %s, index %d, " 4951 "bucket_index %d\n"), SOC_MEM_NAME(u, lpm_mem), 4952 soc_alpm_logical_idx(u, lpm_mem, (*tcam_index) >> 1, 1), 4953 *bucket_index)); 4954 4955 /* Found, check ALPM bucket */ 4956 flex = VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 0); 4957 SOC_ALPM_TABLE_MEM(u, v6, mem, flex); 4958 rv = _soc_alpm_mask_len_get(u, v6, key_data, &sw_len); 4959 if (SOC_FAILURE(rv)) { 4960 return rv; 4961 } 4962 4963 if (v6) { 4964 if (flex) { 4965 ent_num = ALPM_IPV6_64_BKT_COUNT_FLEX; 4966 } else { 4967 ent_num = ALPM_IPV6_64_BKT_COUNT; 4968 } 4969 } else { 4970 if (flex) { 4971 ent_num = ALPM_IPV4_BKT_COUNT_FLEX; 4972 } else { 4973 ent_num = ALPM_IPV4_BKT_COUNT; 4974 } 4975 } 4976 if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) { 4977 ent_num <<= 1; 4978 } 4979 4980 LOG_VERBOSE(BSL_LS_SOC_ALPM, 4981 (BSL_META_U(u, "Start searching mem %s bucket %d(count %d) " 4982 "for Length %d\n"), 4983 SOC_MEM_NAME(u, mem), *bucket_index, ent_num, sw_len)); 4984 4985 for (i = 0; i < ent_num; i++) { 4986 uint32 bufp[SOC_MAX_MEM_FIELD_WORDS] = {0}; 4987 uint32 mask[2] = {0}; 4988 uint32 hkey[2] = {0}; 4989 uint32 skey[2] = {0}; 4990 int valid; 4991 4992 rv = _soc_alpm_mem_index(u, mem, *bucket_index, i, bank_disable, &index); 4993 if (rv == SOC_E_FULL) { 4994 continue; 4995 } 4996 4997 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, 4998 index, (void *)bufp)); 4999 valid = soc_mem_field32_get(u, mem, bufp, VALIDf); 5000 hw_len = soc_mem_field32_get(u, mem, bufp, LENGTHf); 5001 5002 LOG_VERBOSE(BSL_LS_SOC_ALPM, 5003 (BSL_META_U(u, "Bucket %5d Index %6d: Valid %d, Length %d\n"), 5004 *bucket_index, index, valid, hw_len)); 5005 5006 if (!valid || (hw_len > sw_len)) { 5007 continue; 5008 } 5009 5010 /* Length in ALPM <= given length */ 5011 SHR_BITSET_RANGE(mask, (v6 ? 64 : 32) - hw_len, hw_len); 5012 (void)soc_mem_field_get(u, mem, (uint32 *)bufp, KEYf, (uint32 *)hkey); 5013 skey[1] = soc_mem_field32_get(u, lpm_mem, key_data, ip_addr_fld[1]); 5014 skey[0] = soc_mem_field32_get(u, lpm_mem, key_data, ip_addr_fld[0]); 5015 5016 LOG_VERBOSE(BSL_LS_SOC_ALPM, 5017 (BSL_META_U(u, "\tmask %08x %08x\n\t key %08x %08x\n" 5018 "\thost %08x %08x\n"), 5019 mask[1], mask[0], hkey[1], hkey[0], skey[1], skey[0])); 5020 5021 for (j = v6 ? 1 : 0; j >= 0; j--) { 5022 if ((skey[j] & mask[j]) != (hkey[j] & mask[j])) { 5023 break; 5024 } 5025 } 5026 5027 /* Hardware key doesn't match to software key */ 5028 if (j >= 0) { 5029 continue; 5030 } 5031 5032 /* Matched, store and keep searching, 5033 * could be Longer prefix in following entries */ 5034 LOG_VERBOSE(BSL_LS_SOC_ALPM, 5035 (BSL_META_U(u, "Found a match in mem %s bucket %d, " 5036 "index %d\n"), SOC_MEM_NAME(u, mem), *bucket_index, index)); 5037 5038 /* Keep longest matched route */ 5039 if (alpm_len == -1 || alpm_len < hw_len) { 5040 alpm_len = hw_len; 5041 alpm_index = index; 5042 sal_memcpy(alpm_bufp, bufp, sizeof(bufp)); 5043 } 5044 } 5045 5046 /* Found */ 5047 if (alpm_len != -1) { 5048 rv = _soc_alpm_lpm_ent_init(u, alpm_bufp, mem, v6, vrf_id, *bucket_index, 5049 alpm_index, e, flex); 5050 if (SOC_SUCCESS(rv)) { 5051 *key_index = alpm_index; 5052 if (bsl_check(bslLayerSoc, bslSourceAlpm, bslSeverityVerbose, u)) { 5053 LOG_VERBOSE(BSL_LS_SOC_ALPM, 5054 (BSL_META_U(u, "Hit mem %s bucket %d, index %d\n"), 5055 SOC_MEM_NAME(u, mem), *bucket_index, alpm_index)); 5056 } 5057 } 5058 return rv; 5059 } 5060 5061 /* Missed */ 5062 *key_index = soc_alpm_logical_idx(u, lpm_mem, (*tcam_index) >> 1, 1); 5063 LOG_VERBOSE(BSL_LS_SOC_ALPM, 5064 (BSL_META_U(u,"Miss in mem %s bucket %d, use associate data " 5065 "in mem %s LOG index %d\n"), SOC_MEM_NAME(u, mem), *bucket_index, 5066 SOC_MEM_NAME(u, lpm_mem), *key_index)); 5067 5068 /* Miss in bucket, use associate data */ 5069 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY, 5070 *key_index, (void *)e)); 5071 if ((!v6) && ((*tcam_index) & 1)) { 5072 /* move entry to 0 half */ 5073 rv = soc_alpm_lpm_ip4entry1_to_0(u, e, e, PRESERVE_HIT); 5074 } 5075 5076 return SOC_E_NONE; 5077 } 5078 5079 /* 5080 * soc_alpm_find_best_match 5081 * 5082 * It's an indenpendent routine, to simalute HW process for incoming packets. 5083 * Considering possible mismatch between SW and HW, we need to go through 5084 * hardware for lookup regardless of software state. 5085 */ 5086 int 5087 soc_alpm_find_best_match(int u, 5088 void *key_data, 5089 void *e, /* return entry data if found */ 5090 int *index_ptr, 5091 int do_urpf) 5092 { 5093 int rv = SOC_E_NONE; 5094 int i, index_min, index_cnt; 5095 defip_entry_t lpm_ent; 5096 uint32 mem_mask[2]; 5097 uint32 mem_addr[2]; 5098 uint32 mask[2]; 5099 uint32 addr[2]; 5100 uint32 glb_hi, glb_rt; 5101 5102 int vrf_id, vrf = 0; 5103 int vld[2] = {0}; 5104 int tcam_index, bucket_index; 5105 soc_mem_t lpm_mem = L3_DEFIPm; 5106 int ent, v6, hw_v6, match = 0; 5107 int flex_v6_64; 5108 5109 soc_field_t glb_hi_fld[] = { 5110 GLOBAL_HIGH0f, 5111 GLOBAL_HIGH1f 5112 }; 5113 soc_field_t glb_rt_fld[] = { 5114 GLOBAL_ROUTE0f, 5115 GLOBAL_ROUTE1f 5116 }; 5117 5118 v6 = soc_mem_field32_get(u, lpm_mem, key_data, MODE0f); 5119 if (!SOC_URPF_STATUS_GET(u) && do_urpf) { 5120 return SOC_E_PARAM; 5121 } 5122 5123 /* Since L3_DEFIP_* tables are not support for DMA, 5124 * we do PIO search instead */ 5125 index_min = soc_mem_index_min(u, lpm_mem); 5126 index_cnt = soc_mem_index_count(u, lpm_mem); 5127 if (SOC_URPF_STATUS_GET(u)) { 5128 index_cnt >>= 1; 5129 } 5130 /* in Parallel mode search from second half */ 5131 if (soc_alpm_mode_get(u)) { 5132 index_cnt >>= 1; 5133 index_min += index_cnt; 5134 } 5135 5136 if (do_urpf) { 5137 index_min += soc_mem_index_count(u, lpm_mem) / 2; 5138 } 5139 5140 LOG_VERBOSE(BSL_LS_SOC_ALPM, 5141 (BSL_META_U(u, "Launch LPM searching from index %d count %d\n"), 5142 index_min, index_cnt)); 5143 5144 mask[0] = soc_mem_field32_get(u, lpm_mem, key_data, IP_ADDR_MASK0f); 5145 mask[1] = soc_mem_field32_get(u, lpm_mem, key_data, IP_ADDR_MASK1f); 5146 addr[0] = soc_mem_field32_get(u, lpm_mem, key_data, IP_ADDR0f); 5147 addr[1] = soc_mem_field32_get(u, lpm_mem, key_data, IP_ADDR1f); 5148 5149 /* Scanning for Global High routes */ 5150 for (i = index_min; i < index_min + index_cnt; i++) { 5151 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY, 5152 i, (void *)&lpm_ent)); 5153 vld[0] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, VALID0f); 5154 vld[1] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, VALID1f); 5155 if (vld[0] == 0 && vld[1] == 0) { 5156 continue; 5157 } 5158 5159 hw_v6 = soc_mem_field32_get(u, lpm_mem, &lpm_ent, MODE0f); 5160 if (hw_v6 != v6) { 5161 continue; 5162 } 5163 5164 for (ent = 0; ent < (v6 ? 1 : 2); ent++) { 5165 if (vld[ent] == 0) { 5166 continue; 5167 } 5168 glb_hi = soc_mem_field32_get(u, lpm_mem, &lpm_ent, glb_hi_fld[ent]); 5169 glb_rt = soc_mem_field32_get(u, lpm_mem, &lpm_ent, glb_rt_fld[ent]); 5170 flex_v6_64 = 0; 5171 if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && v6 && 5172 soc_mem_field32_get(u, lpm_mem, &lpm_ent, ENTRY_VIEW0f)) { 5173 if (soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR_MASK0f) == 0xFFFFFFFF && 5174 soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR_MASK1f) == 0xFFFFFFFF) { 5175 flex_v6_64 = 1; 5176 } 5177 } 5178 5179 /* No need to compare key if not Global High route */ 5180 if (!(glb_hi && glb_rt) && !flex_v6_64) { 5181 continue; 5182 } 5183 5184 LOG_VERBOSE(BSL_LS_SOC_ALPM, 5185 (BSL_META_U(u, "Match a Global High route: ent %d\n"), 5186 ent)); 5187 5188 mem_mask[0] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR_MASK0f); 5189 mem_mask[1] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR_MASK1f); 5190 mem_addr[0] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR0f); 5191 mem_addr[1] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR1f); 5192 5193 LOG_VERBOSE(BSL_LS_SOC_ALPM, 5194 (BSL_META_U(u, "\thmsk %08x %08x\n\thkey %08x %08x\n" 5195 "\tsmsk %08x %08x\n\tskey %08x %08x\n"), 5196 mem_mask[1], mem_mask[0], mem_addr[1], mem_addr[0], 5197 mask[1], mask[0], addr[1], addr[0])); 5198 5199 /* match condition: mem mask equal to or shorten than match mask 5200 * mem masked addrs are equal. 5201 */ 5202 if (v6) { 5203 match = (mem_mask[1] <= mask[1] && mem_mask[0] <= mask[0] && 5204 ((addr[0] & mem_mask[0]) == (mem_addr[0] & mem_mask[0])) && 5205 ((addr[1] & mem_mask[1]) == (mem_addr[1] & mem_mask[1]))); 5206 } else { 5207 match = (mem_mask[ent] <= mask[0] && 5208 ((addr[0] & mem_mask[ent]) == (mem_addr[ent] & mem_mask[ent]))); 5209 } 5210 if (match) { 5211 /* Found, all Key matched */ 5212 LOG_VERBOSE(BSL_LS_SOC_ALPM, 5213 (BSL_META_U(u,"Hit Global High route in index = %d(%d)\n"), 5214 i, ent)); 5215 sal_memcpy(e, &lpm_ent, sizeof(lpm_ent)); 5216 if (!v6 && ent == 1) { 5217 /* ent == 1 indicate it's sencond half of the entry */ 5218 rv = soc_alpm_lpm_ip4entry1_to_0(u, e, e, PRESERVE_HIT); 5219 } 5220 *index_ptr = i; 5221 return rv; 5222 } 5223 } 5224 } 5225 5226 /* Global High lookup miss, use AUX to search Global Low and VRF route */ 5227 LOG_VERBOSE(BSL_LS_SOC_ALPM, 5228 (BSL_META_U(u,"Global high lookup miss, use AUX engine to " 5229 "search for VRF and Global Low routes\n"))); 5230 5231 /* Fill in AUX Scratch and perform PREFIX Operation */ 5232 SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf)); 5233 rv = _soc_alpm_find_best_match(u, key_data, e, vrf_id, &tcam_index, 5234 &bucket_index, index_ptr, do_urpf); 5235 if (rv == SOC_E_NOT_FOUND) { 5236 vrf = SOC_L3_VRF_GLOBAL; 5237 LOG_VERBOSE(BSL_LS_SOC_ALPM, 5238 (BSL_META_U(u,"Not found in VRF region, trying Global " 5239 "region\n"))); 5240 rv = _soc_alpm_find_best_match(u, key_data, e, vrf_id, &tcam_index, 5241 &bucket_index, index_ptr, do_urpf); 5242 } 5243 5244 if (SOC_SUCCESS(rv)) { 5245 LOG_VERBOSE(BSL_LS_SOC_ALPM, 5246 (BSL_META_U(u,"Hit in %s region in TCAM index %d, " 5247 "buckekt_index %d\n"), 5248 vrf == SOC_L3_VRF_GLOBAL ? "Global Low" : "VRF", 5249 tcam_index, bucket_index)); 5250 } else { 5251 LOG_VERBOSE(BSL_LS_SOC_ALPM, 5252 (BSL_META_U(u,"Search miss for given address\n"))); 5253 } 5254 5255 return(rv); 5256 } 5257 5258 5259 /* 5260 * soc_alpm_delete 5261 */ 5262 int 5263 soc_alpm_delete(int u, void *key_data, int bkt_idx, int pivot_info) 5264 { 5265 int vrf_id, vrf; 5266 int ipv6; 5267 int rv = SOC_E_NONE; 5268 int propagate = 0; 5269 int ipmc_route = 0; 5270 int flex_v6_64 = 0; 5271 5272 ipv6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0f); 5273 5274 if (soc_feature(u, soc_feature_ipmc_defip)) { 5275 ipmc_route = soc_mem_field32_get(u, L3_DEFIPm, key_data, MULTICAST_ROUTE0f); 5276 } 5277 /* If the entry is override, then Lookup into TCAM directly */ 5278 SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf)); 5279 5280 if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && ipv6 && 5281 VRF_FLEX_IS_SET(u, vrf_id, vrf, ipv6, 0)) { 5282 if (soc_mem_field32_get(u, L3_DEFIPm, key_data, IP_ADDR_MASK0f) == 0xFFFFFFFF && 5283 soc_mem_field32_get(u, L3_DEFIPm, key_data, IP_ADDR_MASK1f) == 0xFFFFFFFF) { 5284 flex_v6_64 = 1; 5285 } 5286 } 5287 5288 /* For VRF_OVERRIDE (Global High) entries, and IPMC route 5289 * software needs to maintain the index 5290 */ 5291 /* Prefix resides in TCAM directly */ 5292 if ((vrf_id == SOC_L3_VRF_OVERRIDE) || (ipmc_route) || (flex_v6_64)) { 5293 /* TCAM Direct lookup */ 5294 /* search in the hash table */ 5295 rv = soc_alpm_lpm_delete(u, key_data); 5296 if (SOC_SUCCESS(rv)) { 5297 VRF_TRIE_ROUTES_DEC(u, vrf_id, vrf, ipv6); 5298 } 5299 return(rv); 5300 } else { /* non override entries, go to into ALPM memory */ 5301 int tcam_index; 5302 if (!VRF_TRIE_INIT_COMPLETED(u, vrf, ipv6)) { 5303 LOG_VERBOSE(BSL_LS_SOC_ALPM, 5304 (BSL_META_U(u, 5305 "soc_alpm_delete:VRF %d/%d is not initialized\n"), 5306 vrf, ipv6)); 5307 return SOC_E_NONE; 5308 } 5309 if (bkt_idx == -1) { 5310 /* internally 0 is invalid bucket index */ 5311 bkt_idx = 0; 5312 } 5313 /* deleting all skip propagation to reduce overall time */ 5314 propagate = !(pivot_info & SOC_ALPM_DELETE_ALL); 5315 tcam_index = pivot_info & SOC_ALPM_TCAM_INDEX_MASK; 5316 rv = _soc_alpm_delete(u, key_data, SOC_ALPM_BKT_ENTRY_TO_IDX(bkt_idx), 5317 tcam_index, bkt_idx, 5318 propagate); 5319 } 5320 return(rv); 5321 } 5322 5323 5324 /* Initialize shared bucket management */ 5325 static int 5326 soc_alpm_shared_mem_init(int u) 5327 { 5328 int defip_table_size; 5329 5330 /* Maximm number of IPv4 pivots */ 5331 SOC_ALPM_BUCKET_COUNT(u) = SOC_TD2_ALPM_MAX_BKTS; 5332 5333 if (SOC_URPF_STATUS_GET(u)) { 5334 /* remaining half buckets are the src buckets */ 5335 SOC_ALPM_BUCKET_COUNT(u) >>= 1; 5336 } 5337 5338 /* number bytes to manage the max buckets */ 5339 SOC_ALPM_BUCKET_BMAP_SIZE(u) = SHR_BITALLOCSIZE(SOC_ALPM_BUCKET_COUNT(u)); 5340 5341 SOC_ALPM_BUCKET_BMAP(u) = 5342 sal_alloc(SOC_ALPM_BUCKET_BMAP_SIZE(u), 5343 "alpm_shared_bucket_bitmap"); 5344 if (SOC_ALPM_BUCKET_BMAP(u) == NULL) { 5345 LOG_WARN(BSL_LS_SOC_ALPM, 5346 (BSL_META_U(u, 5347 "soc_alpm_shared_mem_init: Memory allocation for " 5348 "bucket bitmap management failed\n"))); 5349 return SOC_E_MEMORY; 5350 } 5351 5352 /* Mark all buckets as free */ 5353 sal_memset(SOC_ALPM_BUCKET_BMAP(u), 0, SOC_ALPM_BUCKET_BMAP_SIZE(u)); 5354 5355 /* Bucket 0 is reserved. Just assign it */ 5356 alpm_bucket_assign(u, 1, &defip_table_size); 5357 return SOC_E_NONE; 5358 } 5359 5360 STATIC int 5361 _soc_alpm_lpm_free_entries(int u, soc_mem_t mem, int vrf) 5362 { 5363 int curr_pfx, min_pfx; 5364 int total_fent = 0; 5365 5366 if (mem == L3_DEFIP_ALPM_IPV6_128m) { 5367 return _soc_alpm_128_lpm_free_entries(u, vrf); 5368 } 5369 5370 curr_pfx = ALPM_MAX_PFX_INDEX; 5371 min_pfx = 0; 5372 if (soc_alpm_mode_get(u) == SOC_ALPM_MODE_PARALLEL) { 5373 if (vrf == (SOC_VRF_MAX(u) + 1)) { /* Global VRF */ 5374 min_pfx = ALPM_MAX_VRF_PFX_INDEX + 1; 5375 } else { 5376 curr_pfx = ALPM_MAX_VRF_PFX_INDEX; 5377 } 5378 } 5379 while (curr_pfx >= min_pfx) { 5380 total_fent += SOC_ALPM_LPM_STATE_FENT(u, curr_pfx); 5381 curr_pfx = SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx); 5382 } 5383 return total_fent; 5384 } 5385 5386 5387 /* Connect TCAM entry to a bucket ID */ 5388 STATIC int 5389 _soc_alpm_bucket_link(int u, int v6, int pivot_index, int bucket_index) 5390 { 5391 int rv = SOC_E_NONE; 5392 int lpm_index; 5393 soc_mem_t lpm_mem = L3_DEFIPm; 5394 defip_entry_t lpm_entry; 5395 5396 /* Connect TCAM entry to new bucket */ 5397 lpm_index = soc_alpm_logical_idx(u, lpm_mem, pivot_index >> 1, 1); 5398 5399 rv = _soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY, lpm_index, &lpm_entry); 5400 SOC_IF_ERROR_RETURN(rv); 5401 if ((!v6) && (pivot_index & 1)) { 5402 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, &lpm_entry, ALG_BKT_PTR1f, bucket_index); 5403 } else { 5404 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, &lpm_entry, ALG_BKT_PTR0f, bucket_index); 5405 } 5406 rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, lpm_index, &lpm_entry); 5407 SOC_IF_ERROR_RETURN(rv); 5408 5409 if (SOC_URPF_STATUS_GET(u)) { 5410 int _urpf_index = lpm_index + (soc_mem_index_count(u, lpm_mem) >> 1); 5411 rv = _soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY, 5412 _urpf_index, &lpm_entry); 5413 SOC_IF_ERROR_RETURN(rv); 5414 5415 if ((!v6) && (pivot_index & 1)) { 5416 soc_mem_field32_set(u, lpm_mem, &lpm_entry, ALG_BKT_PTR1f, 5417 bucket_index + SOC_ALPM_BUCKET_COUNT(u)); 5418 } else { 5419 soc_mem_field32_set(u, lpm_mem, &lpm_entry, ALG_BKT_PTR0f, 5420 bucket_index + SOC_ALPM_BUCKET_COUNT(u)); 5421 } 5422 5423 rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, _urpf_index, &lpm_entry); 5424 SOC_IF_ERROR_RETURN(rv); 5425 } 5426 5427 return rv; 5428 } 5429 5430 5431 /* Merge entries from one logical bucket to another */ 5432 static int 5433 _soc_alpm_bucket_merge(int u, soc_mem_t mem, int pivot_idx_from, int pivot_idx_to, 5434 soc_alpm_merge_type_t merge_dir, int *shuffled) 5435 { 5436 int *new_index = NULL; 5437 int rv = SOC_E_NONE; 5438 int bucket_index_from, bucket_index_to; 5439 int v6, i; 5440 int vrf = 0; 5441 alpm_mem_prefix_array_t *pfx_array = NULL; 5442 defip_entry_t lpm_entry; 5443 alpm_pivot_t *from_pivot, *to_pivot; 5444 alpm_pivot_t *parent_pivot = NULL, *child_pivot = NULL; 5445 uint32 bank_disable; 5446 enum { 5447 _MERGE_NONE, 5448 _MERGE_PREPARE, 5449 _MERGE_COPY, 5450 _MERGE_LPM_LINK, 5451 _MERGE_INVALIDATE, 5452 _MERGE_CHILD_TRIE_MERGED, 5453 _MERGE_CHILD_LPM_DELETED, 5454 _MERGE_CHILD_PIVOT_DESTROYED 5455 } doing = _MERGE_NONE, done = _MERGE_NONE; 5456 void *raw_bkt[RAW_BKT_NUM] = {0}; 5457 v6 = (L3_DEFIP_ALPM_IPV6_64m == mem || 5458 L3_DEFIP_ALPM_IPV6_64_1m == mem || 5459 L3_DEFIP_ALPM_IPV6_128m == mem); 5460 5461 from_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_from); 5462 to_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_to); 5463 5464 bucket_index_from = PIVOT_BUCKET_INDEX(from_pivot); 5465 bucket_index_to = PIVOT_BUCKET_INDEX(to_pivot); 5466 5467 vrf = PIVOT_BUCKET_VRF(from_pivot); 5468 bank_disable = soc_alpm_bank_dis(u, vrf); 5469 5470 /** 5471 * Invalidate need to happen only after all the entries are 5472 * written to the new pivot and the new pivot is valid. Otherwise 5473 * there is a chance of MISS. 5474 * 5475 * hitless move: 5476 * - Copy entries to new bucket. 5477 * - activate new pivot 5478 * - delete entries from old bucket 5479 */ 5480 5481 doing = _MERGE_PREPARE; 5482 rv = _soc_alpm_raw_bucket_prepare(u, mem, PIVOT_BUCKET_TRIE(from_pivot), 5483 bucket_index_from, bucket_index_to, 5484 bank_disable, NULL, NULL, 5485 &pfx_array, raw_bkt, &new_index, NULL, 1); 5486 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5487 5488 doing = _MERGE_COPY; 5489 rv = _soc_alpm_raw_bucket_copy(u, mem, bucket_index_to, 5490 bank_disable, raw_bkt[RAW_NEW_BKT_DIP], 5491 raw_bkt[RAW_NEW_BKT_SIP], 5492 new_index, pfx_array->count); 5493 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5494 5495 /* Connect TCAM entry to new bucket. 5496 * This is a must step even for merge child to parent 5497 */ 5498 doing = _MERGE_LPM_LINK; 5499 rv = _soc_alpm_bucket_link(u, v6, pivot_idx_from, bucket_index_to); 5500 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5501 5502 /* Invalide old entries */ 5503 doing = _MERGE_INVALIDATE; 5504 rv = _soc_alpm_raw_bucket_inval(u, mem, bucket_index_from, 5505 bank_disable, 5506 raw_bkt[RAW_OLD_BKT_DIP], 5507 raw_bkt[RAW_OLD_BKT_SIP], 5508 raw_bkt[RAW_RB_BKT_DIP], 5509 raw_bkt[RAW_RB_BKT_SIP]); 5510 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5511 5512 if (merge_dir != MERGE_PHY) { 5513 uint32 hw_key[5] = {0}; 5514 int child_vrf; 5515 5516 if (merge_dir == MERGE_LOG_PARENT_TO_CHILD) { 5517 parent_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_from); 5518 child_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_to); 5519 } else if (merge_dir == MERGE_LOG_CHILD_TO_PARENT) { 5520 child_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_from); 5521 parent_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_to); 5522 } 5523 5524 /* SW bucket merge: not expect to fail */ 5525 doing = _MERGE_CHILD_TRIE_MERGED; 5526 rv = trie_merge(PIVOT_BUCKET_TRIE(parent_pivot), 5527 PIVOT_BUCKET_TRIE(child_pivot)->trie, 5528 child_pivot->key, 5529 child_pivot->len); 5530 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5531 5532 sal_memcpy(hw_key, child_pivot->key, sizeof(hw_key)); 5533 ALPM_TRIE_TO_NORMAL_IP(hw_key, child_pivot->len, v6); 5534 5535 child_vrf = PIVOT_BUCKET_VRF(child_pivot); 5536 5537 (void) _soc_alpm_lpm_ent_key_init(u, hw_key, child_pivot->len, 5538 child_vrf, v6, &lpm_entry, 1); 5539 5540 /* Delete child lpm entry from TCAM */ 5541 doing = _MERGE_CHILD_LPM_DELETED; 5542 rv = soc_alpm_lpm_delete(u, &lpm_entry); 5543 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5544 if (shuffled) { 5545 *shuffled = 1; 5546 } 5547 5548 /* Destroy child pivot from trie */ 5549 doing = _MERGE_CHILD_PIVOT_DESTROYED; 5550 rv = _soc_alpm_split_pivot_create_undo 5551 (u, v6, child_vrf, child_pivot->key, child_pivot->len, NULL, 0); 5552 5553 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5554 } 5555 5556 /* Update TCAM mgmt info: set new logical bucket */ 5557 if (merge_dir != MERGE_LOG_CHILD_TO_PARENT && ALPM_TCAM_PIVOT(u, pivot_idx_from)) { 5558 PIVOT_BUCKET_INDEX(ALPM_TCAM_PIVOT(u, pivot_idx_from)) = bucket_index_to; 5559 } 5560 5561 alpm_bucket_release(u, bucket_index_from, v6); 5562 5563 /* Update new index */ 5564 for (i = 0; i < pfx_array->count; i++) { 5565 pfx_array->prefix[i]->index = new_index[i]; 5566 } 5567 5568 _soc_alpm_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index); 5569 return rv; 5570 5571 _rollback: 5572 5573 /* fall through on all cases */ 5574 switch (done) { 5575 case _MERGE_CHILD_LPM_DELETED: 5576 if (merge_dir != MERGE_PHY) { 5577 /* not expecting any failure after lpm deleted */ 5578 } 5579 5580 case _MERGE_CHILD_TRIE_MERGED: 5581 if (merge_dir != MERGE_PHY) { 5582 uint32 pivot[5], length; 5583 trie_split2(PIVOT_BUCKET_TRIE(parent_pivot), 5584 child_pivot->key, 5585 child_pivot->len, 5586 pivot, &length, 5587 &(PIVOT_BUCKET_TRIE(child_pivot)->trie), 5588 PIVOT_BUCKET_COUNT(child_pivot), 5589 1); 5590 } 5591 5592 case _MERGE_INVALIDATE: 5593 _soc_alpm_raw_bucket_inval_undo(u, mem, bucket_index_from, 5594 bank_disable, 5595 raw_bkt[RAW_RB_BKT_DIP], 5596 raw_bkt[RAW_RB_BKT_SIP]); 5597 5598 case _MERGE_LPM_LINK: 5599 /* Connect TCAM back to original bucket */ 5600 _soc_alpm_bucket_link(u, v6, pivot_idx_from, bucket_index_from); 5601 5602 case _MERGE_COPY: 5603 /* Delete entries in new bucket */ 5604 _soc_alpm_raw_bucket_copy_undo(u, mem, bucket_index_to, bank_disable, 5605 raw_bkt[RAW_NEW_BKT_DIP], 5606 raw_bkt[RAW_NEW_BKT_SIP], new_index, 5607 pfx_array->count); 5608 5609 case _MERGE_PREPARE: 5610 _soc_alpm_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index); 5611 5612 case _MERGE_NONE: 5613 default: 5614 break; 5615 } 5616 5617 /* Error dump */ 5618 switch (doing) { 5619 case _MERGE_LPM_LINK: 5620 LOG_ERROR(BSL_LS_SOC_ALPM, 5621 (BSL_META_U(u, 5622 "_soc_alpm_bucket_link failed, pivot %d log_bkt %d\n"), 5623 pivot_idx_from, bucket_index_to)); 5624 break; 5625 5626 case _MERGE_INVALIDATE: 5627 LOG_ERROR(BSL_LS_SOC_ALPM, 5628 (BSL_META_U(u, 5629 "_soc_alpm_bucket_inval failed\n"))); 5630 break; 5631 case _MERGE_CHILD_TRIE_MERGED: 5632 break; 5633 5634 case _MERGE_CHILD_PIVOT_DESTROYED: 5635 LOG_ERROR(BSL_LS_SOC_ALPM, 5636 (BSL_META_U(u, 5637 "Pivot destroy fail, something not expected\n"))); 5638 default: 5639 LOG_ERROR(BSL_LS_SOC_ALPM, 5640 (BSL_META_U(u, 5641 "Merge fails at step %d\n"), doing)); 5642 break; 5643 } 5644 5645 return rv; 5646 } 5647 5648 5649 /* Move partial entries from one logical bucket to another */ 5650 static int 5651 _soc_alpm_bucket_repartition(int u, soc_mem_t mem, int pivot_idx_from, 5652 int pivot_idx_to, trie_node_t **new_trie, 5653 int *shuffled) 5654 { 5655 trie_node_t *split_trie_root = NULL; 5656 uint32 length, bpm_len = 0; 5657 uint32 pivot[5]; 5658 defip_entry_t lpm_entry; 5659 alpm_mem_prefix_array_t *pfx_array = NULL; 5660 int *new_index = NULL; 5661 int rv = SOC_E_NONE, i; 5662 int tcam_index, pivot_index; 5663 int bucket_index_from, bucket_index_to; 5664 int vrf = 0; 5665 uint32 src_discard, src_default; 5666 void *raw_bkt[RAW_BKT_NUM] = {0}; 5667 alpm_pivot_t *new_pivot, *parent_pivot, *child_pivot; 5668 uint32 bank_disable = 0; 5669 int v6 = (L3_DEFIP_ALPM_IPV6_64m == mem || 5670 L3_DEFIP_ALPM_IPV6_64_1m == mem || 5671 L3_DEFIP_ALPM_IPV6_128m == mem); 5672 enum { 5673 _REPART_TRIE_NONE, 5674 _REPART_TRIE_SPLIT, 5675 _REPART_LPM_INIT, 5676 _REPART_PIVOT_CREATE, 5677 _REPART_PREPARE, 5678 _REPART_COPY, 5679 _REPART_LPM_INSERT, 5680 _REPART_INVALIDATE, 5681 _REPART_CHILD_TRIE_MERGED, 5682 _REPART_CHILD_LPM_DELETED, 5683 _REPART_CHILD_PIVOT_DESTROYED 5684 } doing = _REPART_TRIE_NONE, done = _REPART_TRIE_NONE; 5685 5686 parent_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_from); 5687 child_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_to); 5688 bucket_index_from = PIVOT_BUCKET_INDEX(parent_pivot); 5689 bucket_index_to = PIVOT_BUCKET_INDEX(child_pivot); 5690 5691 doing = _REPART_TRIE_SPLIT; 5692 rv = trie_split2(PIVOT_BUCKET_TRIE(parent_pivot), 5693 child_pivot->key, 5694 child_pivot->len, 5695 pivot, &length, 5696 &split_trie_root, 5697 1024, 0); 5698 if (SOC_FAILURE(rv)) { 5699 /* Non repartable is nothing fatal, just return and keep searching */ 5700 if (rv == SOC_E_NOT_FOUND) { 5701 rv = SOC_E_NONE; 5702 } 5703 /* Must return */ 5704 return rv; 5705 } 5706 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5707 5708 vrf = PIVOT_BUCKET_VRF(parent_pivot); 5709 doing = _REPART_LPM_INIT; 5710 5711 rv = _soc_alpm_split_lpm_init(u, mem, vrf, bucket_index_to, NULL, NULL, 5712 pivot, length, &lpm_entry, &bpm_len, 5713 &src_discard, &src_default); 5714 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5715 5716 5717 doing = _REPART_PIVOT_CREATE; 5718 rv = _soc_alpm_split_pivot_create(u, v6, vrf, bucket_index_to, 5719 split_trie_root, pivot, length, 5720 bpm_len, &new_pivot); 5721 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5722 5723 bank_disable = soc_alpm_bank_dis(u, vrf); 5724 5725 doing = _REPART_PREPARE; 5726 rv = _soc_alpm_raw_bucket_prepare(u, mem, PIVOT_BUCKET_TRIE(new_pivot), 5727 bucket_index_from, bucket_index_to, 5728 bank_disable, NULL, NULL, 5729 &pfx_array, raw_bkt, &new_index, NULL, 1); 5730 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5731 5732 doing = _REPART_COPY; 5733 rv = _soc_alpm_raw_bucket_copy(u, mem, bucket_index_to, 5734 bank_disable, raw_bkt[RAW_NEW_BKT_DIP], 5735 raw_bkt[RAW_NEW_BKT_SIP], 5736 new_index, pfx_array->count); 5737 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5738 5739 doing = _REPART_LPM_INSERT; 5740 rv = soc_alpm_lpm_insert(u, &lpm_entry, &tcam_index, 5741 src_default, src_discard, bpm_len); 5742 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5743 if (shuffled) { 5744 *shuffled = 1; 5745 } 5746 5747 /* TCAM index from lpm code is logical. Convert to global idx */ 5748 tcam_index = soc_alpm_physical_idx(u, L3_DEFIPm, tcam_index, v6); 5749 pivot_index = tcam_index << (v6 ? 1 : 0); 5750 PIVOT_TCAM_INDEX(new_pivot) = pivot_index; 5751 ALPM_TCAM_PIVOT(u, pivot_index) = new_pivot; 5752 5753 /* Invalide old entries */ 5754 doing = _REPART_INVALIDATE; 5755 rv = _soc_alpm_raw_bucket_inval(u, mem, bucket_index_from, 5756 bank_disable, 5757 raw_bkt[RAW_OLD_BKT_DIP], 5758 raw_bkt[RAW_OLD_BKT_SIP], 5759 raw_bkt[RAW_RB_BKT_DIP], 5760 raw_bkt[RAW_RB_BKT_SIP]); 5761 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5762 5763 /* Delete old lpm entry */ 5764 { 5765 uint32 hw_key[5] = {0}; 5766 int child_vrf; 5767 5768 /* SW bucket merge: not expect to fail */ 5769 doing = _REPART_CHILD_TRIE_MERGED; 5770 rv = trie_merge(PIVOT_BUCKET_TRIE(new_pivot), 5771 PIVOT_BUCKET_TRIE(child_pivot)->trie, 5772 child_pivot->key, 5773 child_pivot->len); 5774 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5775 5776 sal_memcpy(hw_key, child_pivot->key, sizeof(hw_key)); 5777 ALPM_TRIE_TO_NORMAL_IP(hw_key, child_pivot->len, v6); 5778 5779 child_vrf = PIVOT_BUCKET_VRF(child_pivot); 5780 5781 (void) _soc_alpm_lpm_ent_key_init(u, hw_key, child_pivot->len, 5782 child_vrf, v6, &lpm_entry, 1); 5783 5784 doing = _REPART_CHILD_LPM_DELETED; 5785 rv = soc_alpm_lpm_delete(u, &lpm_entry); 5786 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5787 5788 pivot_index = PIVOT_TCAM_INDEX(new_pivot); 5789 5790 /* Destroy child pivot */ 5791 doing = _REPART_CHILD_PIVOT_DESTROYED; 5792 rv = _soc_alpm_split_pivot_create_undo 5793 (u, v6, child_vrf, child_pivot->key, child_pivot->len, NULL, 0); 5794 5795 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5796 } 5797 5798 5799 /* Update new index */ 5800 for (i = 0; i < pfx_array->count; i++) { 5801 pfx_array->prefix[i]->index = new_index[i]; 5802 } 5803 5804 _soc_alpm_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index); 5805 *new_trie = (trie_node_t *) new_pivot; 5806 5807 /* LOG_CLI((" Do repartition for two buckets OK\n"));*/ 5808 5809 return rv; 5810 5811 _rollback: 5812 5813 /* fall through on all cases */ 5814 switch (done) { 5815 case _REPART_CHILD_LPM_DELETED: 5816 /* Not expect any failure after trie_merge */ 5817 5818 case _REPART_CHILD_TRIE_MERGED: { 5819 uint32 pivot2[5], length2; 5820 trie_split2(PIVOT_BUCKET_TRIE(parent_pivot), 5821 child_pivot->key, 5822 child_pivot->len, 5823 pivot2, &length2, 5824 &(PIVOT_BUCKET_TRIE(child_pivot)->trie), 5825 PIVOT_BUCKET_COUNT(child_pivot), 1); 5826 } 5827 5828 case _REPART_INVALIDATE: 5829 _soc_alpm_raw_bucket_inval_undo(u, mem, bucket_index_from, 5830 bank_disable, 5831 raw_bkt[RAW_RB_BKT_DIP], 5832 raw_bkt[RAW_RB_BKT_SIP]); 5833 5834 case _REPART_LPM_INSERT: 5835 soc_alpm_lpm_delete(u, &lpm_entry); 5836 5837 case _REPART_COPY: 5838 /* Delete entries in new bucket */ 5839 _soc_alpm_raw_bucket_copy_undo(u, mem, bucket_index_to, bank_disable, 5840 raw_bkt[RAW_NEW_BKT_DIP], 5841 raw_bkt[RAW_NEW_BKT_SIP], new_index, 5842 pfx_array->count); 5843 5844 case _REPART_PREPARE: 5845 _soc_alpm_raw_bucket_prepare_undo(u, &pfx_array, raw_bkt, &new_index); 5846 5847 case _REPART_PIVOT_CREATE: 5848 _soc_alpm_split_pivot_create_undo(u, v6, vrf, pivot, length, NULL, 0); 5849 5850 case _REPART_LPM_INIT: 5851 /* nothing to undo */ 5852 5853 case _REPART_TRIE_SPLIT: 5854 trie_merge(PIVOT_BUCKET_TRIE(parent_pivot), split_trie_root, pivot, length); 5855 default: 5856 break; 5857 } 5858 5859 LOG_ERROR(BSL_LS_SOC_ALPM, 5860 (BSL_META_U(u, 5861 "Repartition fails at step %d\n"), doing)); 5862 5863 return rv; 5864 } 5865 5866 5867 static int 5868 _soc_alpm_repartition_cb(trie_node_t *ptrie, trie_node_t *trie, 5869 trie_traverse_states_e_t *state, void *info, 5870 trie_node_t **new_trie) 5871 { 5872 int rv; 5873 int max_count; 5874 int pivot_idx_from, pivot_idx_to, pivot_idx_parent, pivot_idx_child; 5875 int bucket_index_from; 5876 int do_repartition = 0; /* 0: merge. 1: repartition */ 5877 int child_count = 0, parent_count = 0; 5878 soc_alpm_merge_info_t *repart = (soc_alpm_merge_info_t *)info; 5879 alpm_pivot_t *parent_pivot = (alpm_pivot_t *)ptrie; 5880 alpm_pivot_t *child_pivot = (alpm_pivot_t *)trie; 5881 soc_alpm_merge_type_t merge_dir = MERGE_PHY; 5882 5883 #ifdef ALPM_REPART_DEBUG 5884 { 5885 trie_t *pivot_trie; 5886 trie_node_t *lpm = NULL; 5887 switch (repart->v6) { 5888 case L3_DEFIP_MODE_V4: 5889 pivot_trie = VRF_PIVOT_TRIE_IPV4(repart->u, repart->vrf); 5890 break; 5891 case L3_DEFIP_MODE_64: 5892 pivot_trie = VRF_PIVOT_TRIE_IPV6(repart->u, repart->vrf); 5893 break; 5894 default: 5895 pivot_trie = VRF_PIVOT_TRIE_IPV6_128(repart->u, repart->vrf); 5896 break; 5897 } 5898 trie_find_lpm2(pivot_trie, child_pivot->key, child_pivot->len, &lpm); 5899 ptrie = lpm; 5900 parent_pivot = (alpm_pivot_t *)ptrie; 5901 } 5902 #endif 5903 5904 if (!parent_pivot) { /* no parent, this is a root */ 5905 return SOC_E_NONE; 5906 } 5907 5908 /* Reset state everytime */ 5909 *state = TRIE_TRAVERSE_STATE_NONE; 5910 5911 max_count = repart->max_count; 5912 5913 if (PIVOT_BUCKET_TRIE(parent_pivot)->trie == NULL) { 5914 merge_dir = MERGE_LOG_PARENT_TO_CHILD; 5915 } 5916 5917 if (PIVOT_BUCKET_TRIE(child_pivot)->trie == NULL) { 5918 merge_dir = MERGE_LOG_CHILD_TO_PARENT; 5919 } 5920 5921 if (merge_dir == MERGE_PHY) { 5922 parent_count = PIVOT_BUCKET_COUNT(parent_pivot); 5923 child_count = PIVOT_BUCKET_COUNT(child_pivot); 5924 if (parent_count + child_count < max_count) { 5925 if (parent_count > child_count) { 5926 merge_dir = MERGE_LOG_CHILD_TO_PARENT; 5927 } else { 5928 merge_dir = MERGE_LOG_PARENT_TO_CHILD; 5929 } 5930 } else { 5931 /* Merge is not qualified, try repartition */ 5932 merge_dir = MERGE_LOG_PARENT_TO_CHILD; 5933 do_repartition = 1; 5934 } 5935 } 5936 5937 pivot_idx_parent = PIVOT_TCAM_INDEX(parent_pivot); 5938 pivot_idx_child = PIVOT_TCAM_INDEX(child_pivot); 5939 5940 if (merge_dir == MERGE_LOG_CHILD_TO_PARENT) { 5941 pivot_idx_from = pivot_idx_child; 5942 pivot_idx_to = pivot_idx_parent; 5943 bucket_index_from = PIVOT_BUCKET_INDEX(child_pivot); 5944 } else { 5945 /* repartition always go here */ 5946 pivot_idx_from = pivot_idx_parent; 5947 pivot_idx_to = pivot_idx_child; 5948 bucket_index_from = PIVOT_BUCKET_INDEX(parent_pivot); 5949 } 5950 5951 if (do_repartition == 0) { /* Bucket merge */ 5952 if (repart->mem == L3_DEFIP_ALPM_IPV6_128m) { 5953 rv = _soc_alpm_128_bucket_merge(repart->u, repart->mem, 5954 pivot_idx_from, pivot_idx_to, merge_dir, 5955 &repart->shuffled); 5956 } else { 5957 rv = _soc_alpm_bucket_merge(repart->u, repart->mem, 5958 pivot_idx_from, pivot_idx_to, merge_dir, 5959 &repart->shuffled); 5960 } 5961 if (SOC_FAILURE(rv)) { 5962 LOG_ERROR(BSL_LS_SOC_ALPM, 5963 (BSL_META_U(repart->u, 5964 "Bucket merge fail %d\n"), rv)); 5965 return rv; 5966 } 5967 5968 repart->log_bkt = bucket_index_from; 5969 *state = TRIE_TRAVERSE_STATE_DELETED; 5970 if (++repart->merge_count >= REPART_THRESHOLD) { 5971 *state = TRIE_TRAVERSE_STATE_DONE; 5972 } 5973 soc_alpm_dbg_cnt[repart->u].bkt_merge2++; 5974 } else { /* Repartition */ 5975 /* Repartition is an intermediate stage, not a goal. 5976 * Also note, repartition may result in trie modified 5977 * (old node deleted, new node added). 5978 */ 5979 if (repart->mem == L3_DEFIP_ALPM_IPV6_128m) { 5980 rv = _soc_alpm_128_bucket_repartition(repart->u, repart->mem, 5981 pivot_idx_from, pivot_idx_to, 5982 new_trie, &repart->shuffled); 5983 } else { 5984 rv = _soc_alpm_bucket_repartition(repart->u, repart->mem, 5985 pivot_idx_from, pivot_idx_to, 5986 new_trie, &repart->shuffled); 5987 } 5988 if (SOC_FAILURE(rv)) { 5989 LOG_ERROR(BSL_LS_SOC_ALPM, 5990 (BSL_META_U(repart->u, 5991 "Bucket repartition fail %d\n"), rv)); 5992 } 5993 /* keep searching if not repartable */ 5994 if (repart->shuffled) { 5995 soc_alpm_dbg_cnt[repart->u].bkt_repart++; 5996 } 5997 } 5998 5999 return rv; 6000 } 6001 6002 6003 static int 6004 _soc_alpm_repartition(int u, soc_mem_t mem, int vrf, int *bucket_index, int *shuffled) 6005 { 6006 int rv = SOC_E_NONE; 6007 soc_alpm_merge_info_t info; 6008 trie_t *pivot_trie = NULL; 6009 6010 sal_memset(&info, 0, sizeof(info)); 6011 info.log_bkt = -1; /* Initialize to non-eligible bucket_index */ 6012 info.u = u; 6013 info.mem = mem; 6014 info.orig_vrf = vrf; 6015 info.v6 = SOC_ALPM_MEM_V6(mem); 6016 info.vrf = vrf; 6017 info.max_count = _soc_alpm_bkt_entry_cnt(u, mem); 6018 6019 pivot_trie = 6020 (info.v6 == L3_DEFIP_MODE_V4 ? VRF_PIVOT_TRIE_IPV4(u, info.vrf) : 6021 info.v6 == L3_DEFIP_MODE_64 ? VRF_PIVOT_TRIE_IPV6(u, info.vrf) : 6022 VRF_PIVOT_TRIE_IPV6_128(u, info.vrf)); 6023 if (pivot_trie == NULL || pivot_trie->trie == NULL) { 6024 return SOC_E_FULL; 6025 } 6026 /* Choose post-order traverse for repartition. 6027 * All orders are delete safe. 6028 * But only the post-order is modify safe. 6029 */ 6030 rv = trie_repartition(pivot_trie, _soc_alpm_repartition_cb, 6031 &info, _TRIE_POSTORDER_TRAVERSE); 6032 if (info.shuffled && shuffled) { 6033 *shuffled = 1; 6034 } 6035 if (SOC_FAILURE(rv)) { 6036 LOG_ERROR(BSL_LS_SOC_ALPM, 6037 (BSL_META_U(u, "Logic bucket repartition fails."\ 6038 "rv %d vrf %d v6 %d\n"), rv, info.vrf, info.v6)); 6039 return rv; 6040 } else if (info.log_bkt != -1) { 6041 /* This indicates one and only one merge happened. 6042 * Note repartition don't set bucket_index. 6043 */ 6044 *bucket_index = info.log_bkt; 6045 return SOC_E_NONE; 6046 } 6047 return SOC_E_FULL; 6048 } 6049 6050 static int 6051 _soc_alpm_merge_cb(trie_node_t *ptrie, trie_node_t *trie, 6052 trie_traverse_states_e_t *state, void *info) 6053 { 6054 int rv; 6055 int max_count; 6056 int pivot_idx_from, pivot_idx_to, pivot_idx_parent, pivot_idx_child; 6057 int bucket_index_from; 6058 int child_count = 0, parent_count = 0; 6059 soc_alpm_merge_info_t *merge = (soc_alpm_merge_info_t *)info; 6060 alpm_pivot_t *parent_pivot = (alpm_pivot_t *)ptrie; 6061 alpm_pivot_t *child_pivot = (alpm_pivot_t *)trie; 6062 soc_alpm_merge_type_t merge_dir = MERGE_PHY; 6063 6064 if (!parent_pivot) { 6065 return SOC_E_NONE; 6066 } 6067 6068 /* Reset state everytime */ 6069 *state = TRIE_TRAVERSE_STATE_NONE; 6070 6071 max_count = merge->max_count; 6072 6073 if (PIVOT_BUCKET_TRIE(parent_pivot)->trie == NULL) { 6074 merge_dir = MERGE_LOG_PARENT_TO_CHILD; 6075 } 6076 6077 if (PIVOT_BUCKET_TRIE(child_pivot)->trie == NULL) { 6078 merge_dir = MERGE_LOG_CHILD_TO_PARENT; 6079 } 6080 6081 if (merge_dir == MERGE_PHY) { 6082 parent_count = PIVOT_BUCKET_COUNT(parent_pivot); 6083 child_count = PIVOT_BUCKET_COUNT(child_pivot); 6084 if (parent_count + child_count < max_count) { 6085 if (parent_count > child_count) { 6086 merge_dir = MERGE_LOG_CHILD_TO_PARENT; 6087 } else { 6088 merge_dir = MERGE_LOG_PARENT_TO_CHILD; 6089 } 6090 } else { 6091 return SOC_E_NONE; 6092 } 6093 } 6094 6095 pivot_idx_parent = PIVOT_TCAM_INDEX(parent_pivot); 6096 pivot_idx_child = PIVOT_TCAM_INDEX(child_pivot); 6097 6098 if (merge_dir == MERGE_LOG_CHILD_TO_PARENT) { 6099 pivot_idx_from = pivot_idx_child; 6100 pivot_idx_to = pivot_idx_parent; 6101 bucket_index_from = PIVOT_BUCKET_INDEX(child_pivot); 6102 } else { 6103 pivot_idx_from = pivot_idx_parent; 6104 pivot_idx_to = pivot_idx_child; 6105 bucket_index_from = PIVOT_BUCKET_INDEX(parent_pivot); 6106 } 6107 6108 /* Do logical bucket merge */ 6109 if (merge->mem == L3_DEFIP_ALPM_IPV6_128m) { 6110 rv = _soc_alpm_128_bucket_merge(merge->u, merge->mem, 6111 pivot_idx_from, pivot_idx_to, merge_dir, 6112 &merge->shuffled); 6113 } else { 6114 rv = _soc_alpm_bucket_merge(merge->u, merge->mem, 6115 pivot_idx_from, pivot_idx_to, merge_dir, 6116 &merge->shuffled); 6117 } 6118 6119 if (SOC_FAILURE(rv)) { /* traverse stops on callback failure */ 6120 LOG_CLI(("Merge fails %d (not expecting this )\n", rv)); 6121 return rv; 6122 } 6123 6124 merge->log_bkt = bucket_index_from; 6125 *state = TRIE_TRAVERSE_STATE_DELETED; 6126 if (++merge->merge_count >= MERGE_THRESHOLD) { 6127 *state = TRIE_TRAVERSE_STATE_DONE; 6128 } 6129 soc_alpm_dbg_cnt[merge->u].bkt_merge++; 6130 6131 return SOC_E_NONE; 6132 } 6133 6134 6135 static int 6136 _soc_alpm_merge(int u, soc_mem_t mem, int vrf, int *bucket_index, int *shuffled) 6137 { 6138 int rv = SOC_E_NONE; 6139 soc_alpm_merge_info_t info; 6140 trie_t *pivot_trie = NULL; 6141 6142 sal_memset(&info, 0, sizeof(info)); 6143 info.log_bkt = -1; /* Initialize to non-eligible bucket_index */ 6144 info.u = u; 6145 info.mem = mem; 6146 info.orig_vrf = vrf; 6147 info.v6 = SOC_ALPM_MEM_V6(mem); 6148 info.vrf = vrf; 6149 info.max_count = _soc_alpm_bkt_entry_cnt(u, mem); 6150 6151 pivot_trie = 6152 (info.v6 == L3_DEFIP_MODE_V4 ? VRF_PIVOT_TRIE_IPV4(u, info.vrf) : 6153 info.v6 == L3_DEFIP_MODE_64 ? VRF_PIVOT_TRIE_IPV6(u, info.vrf) : 6154 VRF_PIVOT_TRIE_IPV6_128(u, info.vrf)); 6155 if (pivot_trie == NULL || pivot_trie->trie == NULL) { 6156 return SOC_E_FULL; 6157 } 6158 rv = trie_traverse2(pivot_trie, _soc_alpm_merge_cb, 6159 &info, _TRIE_POSTORDER_TRAVERSE); 6160 if (info.shuffled && shuffled) { 6161 *shuffled = 1; 6162 } 6163 if (SOC_FAILURE(rv)) { 6164 LOG_ERROR(BSL_LS_SOC_ALPM, 6165 (BSL_META_U(u, "Logic bucket merge fails."\ 6166 "rv %d vrf %d v6 %d\n"), rv, info.vrf, info.v6)); 6167 return rv; 6168 } else if (info.log_bkt != -1) { 6169 /* This indicates one and only one merge happened. */ 6170 *bucket_index = info.log_bkt; 6171 return SOC_E_NONE; 6172 } 6173 return SOC_E_FULL; 6174 } 6175 6176 6177 6178 static int 6179 _soc_alpm_assign(int u, soc_mem_t mem, int vrf, int *bucket_index, int *o_shuffled) 6180 { 6181 int rv = SOC_E_FULL; 6182 int shuffled = 0; 6183 int lpm_free_count = 0; 6184 6185 /* Logical bucket merge on condition. */ 6186 rv = _soc_alpm_merge(u, mem, vrf, bucket_index, &shuffled); 6187 6188 if (rv == SOC_E_FULL) { 6189 /* Logical bucket repartition on condition. */ 6190 lpm_free_count = _soc_alpm_lpm_free_entries(u, mem, vrf); 6191 if (lpm_free_count >= 1 && lpm_free_count <= 5) { 6192 rv = _soc_alpm_repartition(u, mem, vrf, bucket_index, &shuffled); 6193 } 6194 } 6195 6196 if (o_shuffled) { 6197 *o_shuffled = shuffled; 6198 } 6199 return rv; 6200 } 6201 6202 /* Get the free bucket to allocate to the PIVOT */ 6203 int 6204 alpm_bucket_assign(int u, int v6, int *bucket_pointer) 6205 { 6206 int i, step_count = 1, used = 0; 6207 6208 /* 6209 * in combined search mode, with urpf disabled, need to allocate even and 6210 * odd bucket pointers 6211 */ 6212 6213 if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) { 6214 step_count = 2; 6215 } 6216 for (i = 0; i < SOC_ALPM_BUCKET_COUNT(u); i += step_count) { 6217 SHR_BITTEST_RANGE(SOC_ALPM_BUCKET_BMAP(u), i, step_count, used); 6218 if (0 == used) { 6219 break; 6220 } 6221 } 6222 if (i == SOC_ALPM_BUCKET_COUNT(u)) { 6223 return SOC_E_FULL; 6224 } 6225 SHR_BITSET_RANGE(SOC_ALPM_BUCKET_BMAP(u), i, step_count); 6226 *bucket_pointer = i; 6227 SOC_ALPM_BUCKET_NEXT_FREE(u) = i; 6228 return SOC_E_NONE; 6229 } 6230 6231 int 6232 soc_alpm_assign(int u, int vrf, soc_mem_t mem, int *bucket_pointer, int *shuffled) 6233 { 6234 int rv; 6235 int step_count = 1; 6236 int v6 = SOC_ALPM_MEM_V6(mem); 6237 6238 rv = alpm_bucket_assign(u, v6, bucket_pointer); 6239 6240 if (SOC_SUCCESS(rv)) { 6241 if (_soc_alpm_lpm_free_entries(u, mem, vrf) == 0) { 6242 rv = _soc_alpm_merge(u, mem, vrf, &step_count, shuffled); 6243 if (rv == SOC_E_FULL && !v6) { 6244 rv = SOC_E_NONE; 6245 } else if (SOC_FAILURE(rv)) { 6246 (void) alpm_bucket_release(u, *bucket_pointer, v6); 6247 } 6248 } 6249 } else if (rv == SOC_E_FULL) { 6250 rv = _soc_alpm_assign(u, mem, vrf, bucket_pointer, shuffled); 6251 /* Reclaim the physical bucket in case it has been freed */ 6252 if (SOC_SUCCESS(rv)) { 6253 if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) { 6254 step_count = 2; 6255 } 6256 SHR_BITSET_RANGE(SOC_ALPM_BUCKET_BMAP(u), *bucket_pointer, step_count); 6257 SOC_ALPM_BUCKET_NEXT_FREE(u) = *bucket_pointer; 6258 } 6259 } 6260 return rv; 6261 } 6262 6263 6264 /* Release the bucket to the pool*/ 6265 int 6266 alpm_bucket_release(int u, int bucket_pointer, int v6) 6267 { 6268 int step_count = 1, used = 0; 6269 6270 /* Check if the bucket pointer is valid */ 6271 if ((bucket_pointer < 1) || 6272 (bucket_pointer > SOC_ALPM_BUCKET_MAX_INDEX(u))) { 6273 LOG_ERROR(BSL_LS_SOC_ALPM, 6274 (BSL_META_U(u, 6275 "Unit %d\n, freeing invalid bucket index %d\n"), 6276 u, bucket_pointer)); 6277 return SOC_E_PARAM; 6278 } 6279 /* in combined search mode, with urpf disabled, need to free even and odd 6280 * bucket pointers 6281 */ 6282 if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) { 6283 step_count = 2; 6284 } 6285 SHR_BITTEST_RANGE(SOC_ALPM_BUCKET_BMAP(u), bucket_pointer, step_count, 6286 used); 6287 if (!used) { 6288 return SOC_E_PARAM; 6289 } 6290 SHR_BITCLR_RANGE(SOC_ALPM_BUCKET_BMAP(u), bucket_pointer, step_count); 6291 _soc_trident2_alpm_bkt_view_set(u, bucket_pointer << 2, INVALIDm); 6292 if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) { 6293 _soc_trident2_alpm_bkt_view_set(u, (bucket_pointer + 1) << 2, 6294 INVALIDm); 6295 } 6296 6297 if (SOC_URPF_STATUS_GET(u)) { 6298 _soc_trident2_alpm_bkt_view_set(u, 6299 _soc_alpm_rpf_entry(u, bucket_pointer << 2), INVALIDm); 6300 if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) { 6301 _soc_trident2_alpm_bkt_view_set(u, 6302 _soc_alpm_rpf_entry(u, (bucket_pointer + 1) << 2), INVALIDm); 6303 } 6304 } 6305 return SOC_E_NONE; 6306 } 6307 6308 int 6309 alpm_bucket_is_assigned(int u, int bucket_ptr, int ipv6, int *used) 6310 { 6311 int step_count = 1; 6312 6313 /* Check if the bucket pointer is valid */ 6314 if ((bucket_ptr < 1) || (bucket_ptr > SOC_ALPM_BUCKET_MAX_INDEX(u))) { 6315 return SOC_E_PARAM; 6316 } 6317 6318 /* in combined search mode, with urpf disabled, need to allocate even and 6319 * odd bucket pointers */ 6320 if (ipv6) { 6321 if (!soc_alpm_mode_get(u) && !SOC_URPF_STATUS_GET(u)) { 6322 step_count = 2; 6323 } 6324 } 6325 6326 SHR_BITTEST_RANGE(SOC_ALPM_BUCKET_BMAP(u), bucket_ptr, step_count, *used); 6327 return SOC_E_NONE; 6328 } 6329 6330 /********************************************** 6331 * TCAM Management functions * 6332 */ 6333 6334 /* 6335 * TCAM based PIVOT implementation. Each table entry can hold two IPV4 PIVOTs or 6336 * one IPV6 PIVOT entry. VRF independent routes placed at the beginning or 6337 * at the end of table based on application provided entry vrf id 6338 * (SOC_L3_VRF_OVERRIDE/SOC_L3_VRF_GLOBAL). 6339 * 6340 * ALPM_MAX_PFX_INDEX 6341 * lpm_prefix_index[98].begin ---> =============================== 6342 * == == 6343 * == 0 == 6344 * lpm_prefix_index[98].end ---> =============================== 6345 * 6346 * lpm_prefix_index[97].begin ---> =============================== 6347 * == == 6348 * == IPV6 Prefix Len = 64 == 6349 * lpm_prefix_index[97].end ---> =============================== 6350 * 6351 * 6352 * 6353 * lpm_prefix_index[x].begin ---> =============================== 6354 * == == 6355 * == == 6356 * lpm_prefix_index[x].end ---> =============================== 6357 * 6358 * 6359 * ALPM_IPV6_PFX_ZERO 6360 * lpm_prefix_index[33].begin ---> =============================== 6361 * == == 6362 * == IPV6 Prefix Len = 0 == 6363 * lpm_prefix_index[33].end ---> =============================== 6364 * 6365 * 6366 * lpm_prefix_index[32].begin ---> =============================== 6367 * == == 6368 * == IPV4 Prefix Len = 32 == 6369 * lpm_prefix_index[32].end ---> =============================== 6370 * 6371 * 6372 * 6373 * lpm_prefix_index[0].begin ---> =============================== 6374 * == == 6375 * == IPV4 Prefix Len = 0 == 6376 * lpm_prefix_index[0].end ---> =============================== 6377 */ 6378 6379 6380 /* 6381 * Extract key data from an entry at the given index. 6382 */ 6383 static 6384 void _soc_alpm_lpm_hash_entry_get(int u, void *e, 6385 int index, _soc_alpm_lpm_hash_entry_t r_entry, 6386 int *v) 6387 { 6388 if (index & TD2_ALPM_HASH_IPV6_MASK) { 6389 SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, e, r_entry); 6390 if (v) { 6391 *v = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f) && 6392 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f); 6393 } 6394 } else { 6395 if (index & 0x1) { 6396 SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, e, r_entry); 6397 if (v) { 6398 *v = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f); 6399 } 6400 } else { 6401 SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, e, r_entry); 6402 if (v) { 6403 *v = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f); 6404 } 6405 } 6406 } 6407 } 6408 6409 /* 6410 * Function: 6411 * _soc_alpm_lpm_hash_compare_key 6412 * Purpose: 6413 * Comparison function for AVL shadow table operations. 6414 */ 6415 static 6416 int _soc_alpm_lpm_hash_compare_key(_soc_alpm_lpm_hash_entry_t key1, 6417 _soc_alpm_lpm_hash_entry_t key2) 6418 { 6419 int idx; 6420 6421 for (idx = 0; idx < 5; idx++) { 6422 SOC_MEM_COMPARE_RETURN(key1[idx], key2[idx]); 6423 } 6424 return (0); 6425 } 6426 6427 #ifdef FB_LPM_DEBUG 6428 #define H_INDEX_MATCH(str, tab_index, match_index) \ 6429 LOG_ERROR(BSL_LS_SOC_ALPM, \ 6430 (BSL_META("%s index: H %d A %d\n"), \ 6431 str, (int)tab_index, match_index)) 6432 #else 6433 #define H_INDEX_MATCH(str, tab_index, match_index) 6434 #endif 6435 6436 #define LPM_NO_MATCH_INDEX 0x4000 6437 #define LPM_HASH_INSERT(u, entry_data, tab_index, rvt_index0, rvt_index1) \ 6438 soc_alpm_lpm_hash_insert(u, entry_data, tab_index, LPM_NO_MATCH_INDEX, 0, \ 6439 rvt_index0, rvt_index1) 6440 6441 #define LPM_HASH_REVERT(u, entry_data, tab_index, rvt_index0, rvt_index1) \ 6442 soc_alpm_lpm_hash_revert(u, entry_data, tab_index, \ 6443 rvt_index0, rvt_index1) 6444 6445 #define LPM_HASH_DELETE(u, key_data, tab_index) \ 6446 soc_alpm_lpm_hash_delete(u, key_data, tab_index) 6447 6448 #define LPM_HASH_LOOKUP(u, key_data, pfx, tab_index) \ 6449 soc_alpm_lpm_hash_lookup(u, key_data, pfx, tab_index) 6450 6451 #define LPM_HASH_VERIFY(u, key_data, tab_index) \ 6452 soc_alpm_lpm_hash_verify(u, key_data, tab_index) 6453 6454 #define INDEX_DELETE(hash, hash_idx, del_idx) \ 6455 hash->table[hash_idx] = \ 6456 hash->link_table[del_idx & TD2_ALPM_HASH_INDEX_MASK]; \ 6457 hash->link_table[del_idx & TD2_ALPM_HASH_INDEX_MASK] = \ 6458 TD2_ALPM_HASH_INDEX_NULL 6459 6460 #define INDEX_DELETE_LINK(hash, prev_idx, del_idx) \ 6461 hash->link_table[prev_idx & TD2_ALPM_HASH_INDEX_MASK] = \ 6462 hash->link_table[del_idx & TD2_ALPM_HASH_INDEX_MASK]; \ 6463 hash->link_table[del_idx & TD2_ALPM_HASH_INDEX_MASK] = \ 6464 TD2_ALPM_HASH_INDEX_NULL 6465 6466 6467 static void soc_alpm_lpm_hash_insert(int u, void *entry_data, uint32 tab_index, 6468 uint32 old_index, int pfx, 6469 uint32 *rvt_index0, uint32 *rvt_index1) 6470 { 6471 _soc_alpm_lpm_hash_entry_t key_hash; 6472 6473 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, MODE0f)) { 6474 /* IPV6 entry */ 6475 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID1f) && 6476 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID0f)) { 6477 SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, key_hash); 6478 _soc_alpm_lpm_hash_insert( 6479 SOC_ALPM_LPM_STATE_HASH(u), 6480 _soc_alpm_lpm_hash_compare_key, 6481 key_hash, 6482 pfx, 6483 old_index, 6484 ((uint16)tab_index << 1) | TD2_ALPM_HASH_IPV6_MASK, 6485 rvt_index0); 6486 } 6487 } else { 6488 /* IPV4 entry */ 6489 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID0f)) { 6490 SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, key_hash); 6491 _soc_alpm_lpm_hash_insert(SOC_ALPM_LPM_STATE_HASH(u), 6492 _soc_alpm_lpm_hash_compare_key, 6493 key_hash, 6494 pfx, 6495 old_index, 6496 ((uint16)tab_index << 1), 6497 rvt_index0); 6498 } 6499 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID1f)) { 6500 SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, key_hash); 6501 _soc_alpm_lpm_hash_insert(SOC_ALPM_LPM_STATE_HASH(u), 6502 _soc_alpm_lpm_hash_compare_key, 6503 key_hash, 6504 pfx, 6505 old_index, 6506 (((uint16)tab_index << 1) + 1), 6507 rvt_index1); 6508 } 6509 } 6510 } 6511 6512 6513 6514 6515 static void soc_alpm_lpm_hash_revert(int u, void *entry_data, uint32 tab_index, 6516 uint32 rvt_index0, uint32 rvt_index1) 6517 { 6518 _soc_alpm_lpm_hash_entry_t key_hash; 6519 6520 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, MODE0f)) { 6521 /* IPV6 entry */ 6522 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID1f) && 6523 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID0f)) { 6524 SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, key_hash); 6525 _soc_alpm_lpm_hash_revert( 6526 SOC_ALPM_LPM_STATE_HASH(u), 6527 _soc_alpm_lpm_hash_compare_key, 6528 key_hash, 6529 ((uint16)tab_index << 1) | TD2_ALPM_HASH_IPV6_MASK, 6530 rvt_index0); 6531 } 6532 } else { 6533 /* IPV4 entry */ 6534 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID0f)) { 6535 SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, key_hash); 6536 _soc_alpm_lpm_hash_revert(SOC_ALPM_LPM_STATE_HASH(u), 6537 _soc_alpm_lpm_hash_compare_key, 6538 key_hash, 6539 ((uint16)tab_index << 1), 6540 rvt_index0); 6541 } 6542 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID1f)) { 6543 SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, key_hash); 6544 _soc_alpm_lpm_hash_revert(SOC_ALPM_LPM_STATE_HASH(u), 6545 _soc_alpm_lpm_hash_compare_key, 6546 key_hash, 6547 (((uint16)tab_index << 1) + 1), 6548 rvt_index1); 6549 } 6550 } 6551 } 6552 6553 6554 static void soc_alpm_lpm_hash_delete(int u, void *key_data, uint32 tab_index) 6555 { 6556 _soc_alpm_lpm_hash_entry_t key_hash; 6557 int pfx = -1; 6558 int rv; 6559 uint16 index; 6560 6561 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, MODE0f)) { 6562 SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, key_data, key_hash); 6563 index = (tab_index << 1) | TD2_ALPM_HASH_IPV6_MASK; 6564 } else { 6565 SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, key_data, key_hash); 6566 index = tab_index; 6567 } 6568 6569 rv = _soc_alpm_lpm_hash_delete(SOC_ALPM_LPM_STATE_HASH(u), 6570 _soc_alpm_lpm_hash_compare_key, 6571 key_hash, pfx, index); 6572 if (SOC_FAILURE(rv)) { 6573 LOG_ERROR(BSL_LS_SOC_ALPM, 6574 (BSL_META_U(u, 6575 "\ndel index: H %d error %d\n"), index, rv)); 6576 } 6577 } 6578 6579 static int soc_alpm_lpm_hash_lookup(int u, void *key_data, int pfx, int *key_index) 6580 { 6581 _soc_alpm_lpm_hash_entry_t key_hash; 6582 int is_ipv6; 6583 int rv; 6584 uint16 index = TD2_ALPM_HASH_INDEX_NULL; 6585 6586 is_ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, MODE0f); 6587 if (is_ipv6) { 6588 SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, key_data, key_hash); 6589 } else { 6590 SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, key_data, key_hash); 6591 } 6592 6593 rv = _soc_alpm_lpm_hash_lookup(SOC_ALPM_LPM_STATE_HASH(u), 6594 _soc_alpm_lpm_hash_compare_key, 6595 key_hash, pfx, &index); 6596 if (SOC_FAILURE(rv)) { 6597 *key_index = 0xFFFFFFFF; 6598 return(rv); 6599 } 6600 6601 *key_index = index; 6602 6603 return(SOC_E_NONE); 6604 } 6605 6606 static int soc_alpm_lpm_hash_verify(int u, void *key_data, uint32 tab_index) 6607 { 6608 _soc_alpm_lpm_hash_entry_t key_hash; 6609 int pfx = -1; 6610 int rv; 6611 uint16 index; 6612 6613 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, MODE0f)) { 6614 SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, key_data, key_hash); 6615 index = (tab_index << 1) | TD2_ALPM_HASH_IPV6_MASK; 6616 } else { 6617 SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, key_data, key_hash); 6618 index = tab_index; 6619 } 6620 6621 rv = _soc_alpm_lpm_hash_verify(SOC_ALPM_LPM_STATE_HASH(u), 6622 _soc_alpm_lpm_hash_compare_key, 6623 key_hash, pfx, index); 6624 if (SOC_FAILURE(rv)) { 6625 LOG_ERROR(BSL_LS_SOC_ALPM, 6626 (BSL_META_U(u, 6627 "\nveri index: H %d error %d\n"), index, rv)); 6628 } 6629 return rv; 6630 } 6631 6632 /* 6633 * Function: 6634 * _soc_alpm_lpm_hash_compute 6635 * Purpose: 6636 * Compute CRC hash for key data. 6637 * Parameters: 6638 * data - Key data 6639 * data_nbits - Number of data bits 6640 * Returns: 6641 * Computed 16 bit hash 6642 */ 6643 static 6644 uint16 _soc_alpm_lpm_hash_compute(uint8 *data, int data_nbits) 6645 { 6646 return (_shr_crc16b(0, data, data_nbits)); 6647 } 6648 6649 /* 6650 * Function: 6651 * _soc_alpm_lpm_hash_create 6652 * Purpose: 6653 * Create an empty hash table 6654 * Parameters: 6655 * unit - Device unit 6656 * entry_count - Limit for number of entries in table 6657 * index_count - Hash index max + 1. (index_count <= count) 6658 * fb_lpm_hash_ptr - Return pointer (handle) to new Hash Table 6659 * Returns: 6660 * SOC_E_NONE Success 6661 * SOC_E_MEMORY Out of memory (system allocator) 6662 */ 6663 6664 static 6665 int _soc_alpm_lpm_hash_create(int unit, 6666 int entry_count, 6667 int index_count, 6668 _soc_alpm_lpm_hash_t **fb_lpm_hash_ptr) 6669 { 6670 _soc_alpm_lpm_hash_t *hash; 6671 int index; 6672 6673 if (index_count > entry_count) { 6674 return SOC_E_MEMORY; 6675 } 6676 hash = sal_alloc(sizeof (_soc_alpm_lpm_hash_t), "lpm_hash"); 6677 if (hash == NULL) { 6678 return SOC_E_MEMORY; 6679 } 6680 6681 sal_memset(hash, 0, sizeof (*hash)); 6682 6683 hash->unit = unit; 6684 hash->entry_count = entry_count; 6685 hash->index_count = index_count; 6686 6687 /* 6688 * Pre-allocate the hash table storage. 6689 */ 6690 hash->table = sal_alloc(hash->index_count * sizeof(*(hash->table)), 6691 "hash_table"); 6692 6693 if (hash->table == NULL) { 6694 sal_free(hash); 6695 return SOC_E_MEMORY; 6696 } 6697 /* 6698 * In case where all the entries should hash into the same bucket 6699 * this will prevent the hash table overflow 6700 */ 6701 hash->link_table = sal_alloc( 6702 hash->entry_count * sizeof(*(hash->link_table)), 6703 "link_table"); 6704 if (hash->link_table == NULL) { 6705 sal_free(hash->table); 6706 sal_free(hash); 6707 return SOC_E_MEMORY; 6708 } 6709 6710 /* 6711 * Set the entries in the hash table to TD2_ALPM_HASH_INDEX_NULL 6712 * Link the entries beyond hash->index_max for handling collisions 6713 */ 6714 for(index = 0; index < hash->index_count; index++) { 6715 hash->table[index] = TD2_ALPM_HASH_INDEX_NULL; 6716 } 6717 for(index = 0; index < hash->entry_count; index++) { 6718 hash->link_table[index] = TD2_ALPM_HASH_INDEX_NULL; 6719 } 6720 *fb_lpm_hash_ptr = hash; 6721 return SOC_E_NONE; 6722 } 6723 6724 /* 6725 * Function: 6726 * _soc_alpm_lpm_hash_destroy 6727 * Purpose: 6728 * Destroy the hash table 6729 * Parameters: 6730 * fb_lpm_hash - Pointer (handle) to Hash Table 6731 * Returns: 6732 * SOC_E_NONE Success 6733 */ 6734 static 6735 int _soc_alpm_lpm_hash_destroy(_soc_alpm_lpm_hash_t *fb_lpm_hash) 6736 { 6737 if (fb_lpm_hash != NULL) { 6738 sal_free(fb_lpm_hash->table); 6739 sal_free(fb_lpm_hash->link_table); 6740 sal_free(fb_lpm_hash); 6741 } 6742 6743 return SOC_E_NONE; 6744 } 6745 6746 /* 6747 * Function: 6748 * _soc_alpm_lpm_hash_lookup 6749 * Purpose: 6750 * Look up a key in the hash table 6751 * Parameters: 6752 * hash - Pointer (handle) to Hash Table 6753 * key_cmp_fn - Compare function which should compare key 6754 * entry - The key to lookup 6755 * pfx - Prefix length for lookup acceleration. 6756 * key_index - (OUT) Index where the key was found. 6757 * Returns: 6758 * SOC_E_NONE Key found 6759 * SOC_E_NOT_FOUND Key not found 6760 */ 6761 6762 static 6763 int _soc_alpm_lpm_hash_lookup(_soc_alpm_lpm_hash_t *hash, 6764 _soc_alpm_lpm_hash_compare_fn key_cmp_fn, 6765 _soc_alpm_lpm_hash_entry_t entry, 6766 int pfx, 6767 uint16 *key_index) 6768 { 6769 int u = hash->unit, v, i = 0; 6770 6771 uint16 hash_val; 6772 uint16 index; 6773 6774 hash_val = _soc_alpm_lpm_hash_compute((uint8 *)entry, 6775 (32 * 5)) % hash->index_count; 6776 index = hash->table[hash_val]; 6777 H_INDEX_MATCH("lhash", entry[0], hash_val); 6778 H_INDEX_MATCH("lkup ", entry[0], index); 6779 while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) { 6780 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 6781 _soc_alpm_lpm_hash_entry_t r_entry; 6782 int rindex; 6783 6784 rindex = (index & TD2_ALPM_HASH_INDEX_MASK) >> 1; 6785 /* 6786 * Check prefix length and skip index if not valid for given length 6787 if ((SOC_ALPM_LPM_STATE_START(u, pfx) <= rindex) && 6788 (SOC_ALPM_LPM_STATE_END(u, pfx) >= rindex)) { 6789 */ 6790 SOC_IF_ERROR_RETURN( 6791 _soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY, rindex, e)); 6792 SOC_FB_LPM_HASH_ENTRY_GET(u, e, index, r_entry, &v); 6793 if (v == 0) { 6794 LOG_ERROR(BSL_LS_SOC_ALPM, 6795 (BSL_META_U(u, 6796 "Empty entry[%d] in link_table. hash_val %d ridx %d \n"), 6797 index, hash_val, rindex)); 6798 } 6799 if ((*key_cmp_fn)(entry, r_entry) == 0) { 6800 *key_index = (index & TD2_ALPM_HASH_INDEX_MASK) >> 6801 ((index & TD2_ALPM_HASH_IPV6_MASK) ? 1 : 0); 6802 H_INDEX_MATCH("found", entry[0], index); 6803 return(SOC_E_NONE); 6804 } 6805 /* 6806 } 6807 */ 6808 index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK]; 6809 H_INDEX_MATCH("lkup1", entry[0], index); 6810 } 6811 if (i > hash->entry_count) { 6812 LOG_ERROR(BSL_LS_SOC_ALPM, 6813 (BSL_META_U(u, 6814 "Hash loop\n"))); 6815 } 6816 H_INDEX_MATCH("not_found", entry[0], index); 6817 return(SOC_E_NOT_FOUND); 6818 } 6819 6820 /* 6821 * Function: 6822 * _soc_alpm_lpm_hash_insert 6823 * Purpose: 6824 * Insert/Update a key index in the hash table 6825 * Parameters: 6826 * hash - Pointer (handle) to Hash Table 6827 * key_cmp_fn - Compare function which should compare key 6828 * entry - The key to lookup 6829 * pfx - Prefix length for lookup acceleration. 6830 * old_index - Index where the key was moved from. 6831 * TD2_ALPM_HASH_INDEX_NULL if new entry. 6832 * new_index - Index where the key was moved to. 6833 * Returns: 6834 * SOC_E_NONE Key found 6835 */ 6836 /* 6837 * Should be caled before updating the LPM table so that the 6838 * data in the hash table is consistent with the LPM table 6839 */ 6840 static 6841 int _soc_alpm_lpm_hash_insert(_soc_alpm_lpm_hash_t *hash, 6842 _soc_alpm_lpm_hash_compare_fn key_cmp_fn, 6843 _soc_alpm_lpm_hash_entry_t entry, 6844 int pfx, 6845 uint16 old_index, 6846 uint16 new_index, 6847 uint32 *rvt_index) 6848 { 6849 6850 #define INDEX_ADD(hash, hash_idx, new_idx) \ 6851 hash->link_table[new_idx & TD2_ALPM_HASH_INDEX_MASK] = \ 6852 hash->table[hash_idx]; \ 6853 hash->table[hash_idx] = new_idx 6854 6855 #define INDEX_ADD_LINK(hash, t_index, new_idx) \ 6856 hash->link_table[new_idx & TD2_ALPM_HASH_INDEX_MASK] = \ 6857 hash->link_table[t_index & TD2_ALPM_HASH_INDEX_MASK]; \ 6858 hash->link_table[t_index & TD2_ALPM_HASH_INDEX_MASK] = new_idx 6859 6860 #define INDEX_UPDATE(hash, hash_idx, old_idx, new_idx) \ 6861 hash->table[hash_idx] = new_idx; \ 6862 hash->link_table[new_idx & TD2_ALPM_HASH_INDEX_MASK] = \ 6863 hash->link_table[old_idx & TD2_ALPM_HASH_INDEX_MASK]; \ 6864 hash->link_table[old_idx & TD2_ALPM_HASH_INDEX_MASK] = TD2_ALPM_HASH_INDEX_NULL 6865 6866 #define INDEX_UPDATE_LINK(hash, prev_idx, old_idx, new_idx) \ 6867 hash->link_table[prev_idx & TD2_ALPM_HASH_INDEX_MASK] = new_idx; \ 6868 hash->link_table[new_idx & TD2_ALPM_HASH_INDEX_MASK] = \ 6869 hash->link_table[old_idx & TD2_ALPM_HASH_INDEX_MASK]; \ 6870 hash->link_table[old_idx & TD2_ALPM_HASH_INDEX_MASK] = TD2_ALPM_HASH_INDEX_NULL 6871 6872 6873 int u = hash->unit, v, i = 0; 6874 6875 uint16 hash_val; 6876 uint16 index; 6877 uint16 prev_index; 6878 6879 if (rvt_index) { 6880 *rvt_index = TD2_ALPM_HASH_INDEX_NULL; 6881 } 6882 hash_val = _soc_alpm_lpm_hash_compute((uint8 *)entry, 6883 (32 * 5)) % hash->index_count; 6884 index = hash->table[hash_val]; 6885 H_INDEX_MATCH("ihash", entry[0], hash_val); 6886 H_INDEX_MATCH("ins ", entry[0], new_index); 6887 H_INDEX_MATCH("ins1 ", index, new_index); 6888 prev_index = TD2_ALPM_HASH_INDEX_NULL; 6889 if (old_index != TD2_ALPM_HASH_INDEX_NULL) { 6890 while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) { 6891 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 6892 _soc_alpm_lpm_hash_entry_t r_entry; 6893 int rindex; 6894 6895 rindex = (index & TD2_ALPM_HASH_INDEX_MASK) >> 1; 6896 6897 /* 6898 * Check prefix length and skip index if not valid for given length 6899 if ((SOC_ALPM_LPM_STATE_START(u, pfx) <= rindex) && 6900 (SOC_ALPM_LPM_STATE_END(u, pfx) >= rindex)) { 6901 */ 6902 SOC_IF_ERROR_RETURN( 6903 _soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY, rindex, e)); 6904 SOC_FB_LPM_HASH_ENTRY_GET(u, e, index, r_entry, &v); 6905 if (v == 0) { 6906 if ((index & TD2_ALPM_HASH_IPV6_MASK) || 6907 !((new_index & 1) && (new_index == (index + 1)))) { 6908 LOG_ERROR(BSL_LS_SOC_ALPM, 6909 (BSL_META_U(u, 6910 "Empty entry[%d] in link_table. hash_val %d ridx %d nidx %d\n"), 6911 index, hash_val, rindex, new_index)); 6912 } 6913 } 6914 if (v && ((*key_cmp_fn)(entry, r_entry) == 0)) { 6915 /* assert(old_index == index);*/ 6916 if (new_index != index) { 6917 H_INDEX_MATCH("imove", prev_index, new_index); 6918 if (prev_index == TD2_ALPM_HASH_INDEX_NULL) { 6919 INDEX_UPDATE(hash, hash_val, index, new_index); 6920 } else { 6921 INDEX_UPDATE_LINK(hash, prev_index, index, new_index); 6922 } 6923 } 6924 if (rvt_index) { 6925 *rvt_index = index; 6926 } 6927 H_INDEX_MATCH("imtch", index, new_index); 6928 return(SOC_E_NONE); 6929 } 6930 /* 6931 } 6932 */ 6933 prev_index = index; 6934 index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK]; 6935 H_INDEX_MATCH("ins2 ", index, new_index); 6936 } 6937 } 6938 if (i > hash->entry_count) { 6939 LOG_ERROR(BSL_LS_SOC_ALPM, 6940 (BSL_META_U(u, 6941 "Hash loop\n"))); 6942 return SOC_E_INTERNAL; 6943 } 6944 INDEX_ADD(hash, hash_val, new_index); /* new entry */ 6945 return(SOC_E_NONE); 6946 } 6947 6948 /* 6949 * Function: 6950 * _soc_alpm_lpm_hash_revert 6951 * Purpose: 6952 * Revert a key index in the hash table 6953 * Parameters: 6954 * hash - Pointer (handle) to Hash Table 6955 * key_cmp_fn - Compare function which should compare key 6956 * entry - The key to delete 6957 * pfx - Prefix length for lookup acceleration. 6958 * delete_index - Index to delete. 6959 * Returns: 6960 * SOC_E_NONE Success 6961 * SOC_E_NOT_FOUND Key index not found. 6962 */ 6963 static 6964 int _soc_alpm_lpm_hash_revert(_soc_alpm_lpm_hash_t *hash, 6965 _soc_alpm_lpm_hash_compare_fn key_cmp_fn, 6966 _soc_alpm_lpm_hash_entry_t entry, 6967 uint16 new_index, 6968 uint32 rvt_index) 6969 { 6970 int u = hash->unit, i = 0; 6971 uint16 hash_val; 6972 uint16 index; 6973 uint16 prev_index; 6974 6975 hash_val = _soc_alpm_lpm_hash_compute((uint8 *)entry, 6976 (32 * 5)) % hash->index_count; 6977 index = hash->table[hash_val]; 6978 H_INDEX_MATCH("rhash", entry[0], hash_val); 6979 H_INDEX_MATCH("rvt ", entry[0], index); 6980 prev_index = TD2_ALPM_HASH_INDEX_NULL; 6981 while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) { 6982 if (new_index == index) { 6983 H_INDEX_MATCH("dfoun", entry[0], index); 6984 if (rvt_index == TD2_ALPM_HASH_INDEX_NULL) { 6985 if (prev_index == TD2_ALPM_HASH_INDEX_NULL) { 6986 INDEX_DELETE(hash, hash_val, new_index); 6987 } else { 6988 INDEX_DELETE_LINK(hash, prev_index, new_index); 6989 } 6990 } else { 6991 if (prev_index == TD2_ALPM_HASH_INDEX_NULL) { 6992 INDEX_UPDATE(hash, hash_val, new_index, rvt_index); 6993 } else { 6994 INDEX_UPDATE_LINK(hash, prev_index, new_index, rvt_index); 6995 } 6996 } 6997 return(SOC_E_NONE); 6998 } 6999 prev_index = index; 7000 index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK]; 7001 H_INDEX_MATCH("rvt1 ", entry[0], index); 7002 } 7003 if (i > hash->entry_count) { 7004 LOG_ERROR(BSL_LS_SOC_ALPM, 7005 (BSL_META_U(u, 7006 "Hash loop\n"))); 7007 } 7008 return(SOC_E_NOT_FOUND); 7009 } 7010 7011 7012 7013 /* 7014 * Function: 7015 * _soc_alpm_lpm_hash_delete 7016 * Purpose: 7017 * Delete a key index in the hash table 7018 * Parameters: 7019 * hash - Pointer (handle) to Hash Table 7020 * key_cmp_fn - Compare function which should compare key 7021 * entry - The key to delete 7022 * pfx - Prefix length for lookup acceleration. 7023 * delete_index - Index to delete. 7024 * Returns: 7025 * SOC_E_NONE Success 7026 * SOC_E_NOT_FOUND Key index not found. 7027 */ 7028 static 7029 int _soc_alpm_lpm_hash_delete(_soc_alpm_lpm_hash_t *hash, 7030 _soc_alpm_lpm_hash_compare_fn key_cmp_fn, 7031 _soc_alpm_lpm_hash_entry_t entry, 7032 int pfx, 7033 uint16 delete_index) 7034 { 7035 int u = hash->unit, i = 0; 7036 uint16 hash_val; 7037 uint16 index; 7038 uint16 prev_index; 7039 7040 hash_val = _soc_alpm_lpm_hash_compute((uint8 *)entry, 7041 (32 * 5)) % hash->index_count; 7042 index = hash->table[hash_val]; 7043 H_INDEX_MATCH("dhash", entry[0], hash_val); 7044 H_INDEX_MATCH("del ", entry[0], index); 7045 prev_index = TD2_ALPM_HASH_INDEX_NULL; 7046 while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) { 7047 if (delete_index == index) { 7048 H_INDEX_MATCH("dfoun", entry[0], index); 7049 if (prev_index == TD2_ALPM_HASH_INDEX_NULL) { 7050 INDEX_DELETE(hash, hash_val, delete_index); 7051 } else { 7052 INDEX_DELETE_LINK(hash, prev_index, delete_index); 7053 } 7054 return(SOC_E_NONE); 7055 } 7056 prev_index = index; 7057 index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK]; 7058 H_INDEX_MATCH("del1 ", entry[0], index); 7059 } 7060 if (i > hash->entry_count) { 7061 LOG_ERROR(BSL_LS_SOC_ALPM, 7062 (BSL_META_U(u, 7063 "Hash loop\n"))); 7064 } 7065 return(SOC_E_NOT_FOUND); 7066 } 7067 7068 7069 /* 7070 * Function: 7071 * _soc_alpm_lpm_hash_verify 7072 * Purpose: 7073 * Verify a key index in the hash table 7074 * Parameters: 7075 * hash - Pointer (handle) to Hash Table 7076 * key_cmp_fn - Compare function which should compare key 7077 * entry - The key to delete 7078 * pfx - Prefix length for lookup acceleration. 7079 * verify_index - Index to verify. 7080 * Returns: 7081 * SOC_E_NONE Success 7082 * SOC_E_NOT_FOUND Key index not found. 7083 */ 7084 static 7085 int _soc_alpm_lpm_hash_verify(_soc_alpm_lpm_hash_t *hash, 7086 _soc_alpm_lpm_hash_compare_fn key_cmp_fn, 7087 _soc_alpm_lpm_hash_entry_t entry, 7088 int pfx, 7089 uint16 verify_index) 7090 { 7091 int u = hash->unit, i = 0; 7092 uint16 hash_val; 7093 uint16 index; 7094 7095 hash_val = _soc_alpm_lpm_hash_compute((uint8 *)entry, 7096 (32 * 5)) % hash->index_count; 7097 index = hash->table[hash_val]; 7098 H_INDEX_MATCH("vhash", entry[0], hash_val); 7099 H_INDEX_MATCH("veri ", entry[0], index); 7100 while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) { 7101 if (verify_index == index) { 7102 H_INDEX_MATCH("vfoun", entry[0], index); 7103 return(SOC_E_NONE); 7104 } 7105 index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK]; 7106 H_INDEX_MATCH("veri1", entry[0], index); 7107 } 7108 if (i > hash->entry_count) { 7109 LOG_ERROR(BSL_LS_SOC_ALPM, 7110 (BSL_META_U(u, 7111 "Hash loop\n"))); 7112 } 7113 return(SOC_E_NOT_FOUND); 7114 } 7115 #else 7116 #define LPM_HASH_INSERT(u, entry_data, tab_index, rvt_index0, rvt_index1) 7117 #define LPM_HASH_REVERT(u, entry_data, tab_index, rvt_index0, rvt_index1) 7118 #define LPM_HASH_DELETE(u, key_data, tab_index) 7119 #define LPM_HASH_LOOKUP(u, key_data, pfx, tab_index) 7120 #define LPM_HASH_VERIFY(u, key_data, tab_index) 7121 #endif /* FB_LPM_HASH_SUPPORT */ 7122 7123 int 7124 _ipmask2pfx(uint32 ipv4m, int *mask_len) 7125 { 7126 *mask_len = 0; 7127 while (ipv4m & (1 << 31)) { 7128 *mask_len += 1; 7129 ipv4m <<= 1; 7130 } 7131 7132 return ((ipv4m) ? SOC_E_PARAM : SOC_E_NONE); 7133 } 7134 7135 /* src and dst can be same */ 7136 int 7137 soc_alpm_lpm_ip4entry0_to_0(int u, void *src, void *dst, int copy_hit) 7138 { 7139 uint32 ipv4a; 7140 7141 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VALID0f); 7142 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VALID0f, ipv4a); 7143 7144 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MODE0f); 7145 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MODE0f, ipv4a); 7146 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, MODE_MASK0f)) { 7147 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MODE_MASK0f); 7148 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MODE_MASK0f, ipv4a); 7149 } 7150 7151 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, GLOBAL_ROUTE0f)) { 7152 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_ROUTE0f); 7153 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_ROUTE0f, ipv4a); 7154 } 7155 7156 if (soc_feature(u, soc_feature_ipmc_defip)) { 7157 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MULTICAST_ROUTE0f); 7158 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MULTICAST_ROUTE0f, ipv4a); 7159 7160 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPA_ID0f); 7161 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPA_ID0f, ipv4a); 7162 7163 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, EXPECTED_L3_IIF0f); 7164 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, EXPECTED_L3_IIF0f, ipv4a); 7165 7166 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f); 7167 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f, ipv4a); 7168 7169 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f); 7170 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f, ipv4a); 7171 7172 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, L3MC_INDEX0f); 7173 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, L3MC_INDEX0f, ipv4a); 7174 } 7175 7176 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR0f); 7177 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR0f, ipv4a); 7178 7179 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR_MASK0f); 7180 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR_MASK0f, ipv4a); 7181 7182 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP0f)) { 7183 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP0f); 7184 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP0f, ipv4a); 7185 } 7186 7187 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP_COUNT0f)) { 7188 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_COUNT0f); 7189 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_COUNT0f, ipv4a); 7190 7191 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_PTR0f); 7192 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_PTR0f, ipv4a); 7193 } else { 7194 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, NEXT_HOP_INDEX0f); 7195 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, NEXT_HOP_INDEX0f, ipv4a); 7196 } 7197 7198 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, PRI0f); 7199 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, PRI0f, ipv4a); 7200 7201 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPE0f); 7202 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPE0f, ipv4a); 7203 7204 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f)) { 7205 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_0f); 7206 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_0f, ipv4a); 7207 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_MASK0f); 7208 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_MASK0f, ipv4a); 7209 } 7210 7211 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD0f)) { 7212 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DST_DISCARD0f); 7213 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DST_DISCARD0f, ipv4a); 7214 } 7215 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, CLASS_ID0f)) { 7216 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, CLASS_ID0f); 7217 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, CLASS_ID0f, ipv4a); 7218 } 7219 if (copy_hit) { 7220 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, HIT0f); 7221 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, HIT0f, ipv4a); 7222 } 7223 7224 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_HIGH0f); 7225 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_HIGH0f, ipv4a); 7226 7227 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ALG_HIT_IDX0f); 7228 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ALG_HIT_IDX0f, ipv4a); 7229 7230 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ALG_BKT_PTR0f); 7231 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ALG_BKT_PTR0f, ipv4a); 7232 7233 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DEFAULT_MISS0f); 7234 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DEFAULT_MISS0f, ipv4a); 7235 7236 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_BASE_COUNTER_IDX0f); 7237 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_BASE_COUNTER_IDX0f, ipv4a); 7238 7239 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_POOL_NUMBER0f); 7240 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_POOL_NUMBER0f, ipv4a); 7241 7242 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_OFFSET_MODE0f); 7243 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_OFFSET_MODE0f, ipv4a); 7244 7245 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ENTRY_VIEW0f); 7246 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ENTRY_VIEW0f, ipv4a); 7247 7248 return(SOC_E_NONE); 7249 } 7250 7251 int 7252 soc_alpm_lpm_ip4entry1_to_1(int u, void *src, void *dst, int copy_hit) 7253 { 7254 uint32 ipv4a; 7255 7256 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VALID1f); 7257 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VALID1f, ipv4a); 7258 7259 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MODE1f); 7260 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MODE1f, ipv4a); 7261 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, MODE_MASK1f)) { 7262 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MODE_MASK1f); 7263 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MODE_MASK1f, ipv4a); 7264 } 7265 7266 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, GLOBAL_ROUTE1f)) { 7267 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_ROUTE1f); 7268 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_ROUTE1f, ipv4a); 7269 } 7270 7271 if (soc_feature(u, soc_feature_ipmc_defip)) { 7272 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MULTICAST_ROUTE1f); 7273 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MULTICAST_ROUTE1f, ipv4a); 7274 7275 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPA_ID1f); 7276 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPA_ID1f, ipv4a); 7277 7278 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, EXPECTED_L3_IIF1f); 7279 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, EXPECTED_L3_IIF1f, ipv4a); 7280 7281 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f); 7282 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f, ipv4a); 7283 7284 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f); 7285 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f, ipv4a); 7286 7287 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, L3MC_INDEX1f); 7288 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, L3MC_INDEX1f, ipv4a); 7289 } 7290 7291 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR1f); 7292 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR1f, ipv4a); 7293 7294 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR_MASK1f); 7295 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR_MASK1f, ipv4a); 7296 7297 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP1f)) { 7298 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP1f); 7299 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP1f, ipv4a); 7300 } 7301 7302 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP_COUNT1f)) { 7303 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_COUNT1f); 7304 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_COUNT1f, ipv4a); 7305 7306 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_PTR1f); 7307 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_PTR1f, ipv4a); 7308 } else { 7309 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, NEXT_HOP_INDEX1f); 7310 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, NEXT_HOP_INDEX1f, ipv4a); 7311 } 7312 7313 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, PRI1f); 7314 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, PRI1f, ipv4a); 7315 7316 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPE1f); 7317 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPE1f, ipv4a); 7318 7319 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_1f)) { 7320 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_1f); 7321 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_1f, ipv4a); 7322 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_MASK1f); 7323 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_MASK1f, ipv4a); 7324 } 7325 7326 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD1f)) { 7327 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DST_DISCARD1f); 7328 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DST_DISCARD1f, ipv4a); 7329 } 7330 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, CLASS_ID1f)) { 7331 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, CLASS_ID1f); 7332 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, CLASS_ID1f, ipv4a); 7333 } 7334 if (copy_hit) { 7335 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, HIT1f); 7336 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, HIT1f, ipv4a); 7337 } 7338 7339 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_HIGH1f); 7340 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_HIGH1f, ipv4a); 7341 7342 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ALG_HIT_IDX1f); 7343 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ALG_HIT_IDX1f, ipv4a); 7344 7345 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ALG_BKT_PTR1f); 7346 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ALG_BKT_PTR1f, ipv4a); 7347 7348 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DEFAULT_MISS1f); 7349 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DEFAULT_MISS1f, ipv4a); 7350 7351 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_BASE_COUNTER_IDX1f); 7352 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_BASE_COUNTER_IDX1f, ipv4a); 7353 7354 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_POOL_NUMBER1f); 7355 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_POOL_NUMBER1f, ipv4a); 7356 7357 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_OFFSET_MODE1f); 7358 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_OFFSET_MODE1f, ipv4a); 7359 7360 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ENTRY_VIEW1f); 7361 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ENTRY_VIEW1f, ipv4a); 7362 7363 return(SOC_E_NONE); 7364 } 7365 7366 /* src and dst can be same */ 7367 int 7368 soc_alpm_lpm_ip4entry0_to_1(int u, void *src, void *dst, int copy_hit) 7369 { 7370 uint32 ipv4a; 7371 7372 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VALID0f); 7373 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VALID1f, ipv4a); 7374 7375 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MODE0f); 7376 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MODE1f, ipv4a); 7377 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, MODE_MASK0f)) { 7378 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MODE_MASK0f); 7379 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MODE_MASK1f, ipv4a); 7380 } 7381 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, GLOBAL_ROUTE0f)) { 7382 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_ROUTE0f); 7383 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_ROUTE1f, ipv4a); 7384 } 7385 7386 if (soc_feature(u, soc_feature_ipmc_defip)) { 7387 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MULTICAST_ROUTE0f); 7388 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MULTICAST_ROUTE1f, ipv4a); 7389 7390 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPA_ID0f); 7391 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPA_ID1f, ipv4a); 7392 7393 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, EXPECTED_L3_IIF0f); 7394 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, EXPECTED_L3_IIF1f, ipv4a); 7395 7396 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f); 7397 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f, ipv4a); 7398 7399 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f); 7400 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f, ipv4a); 7401 7402 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, L3MC_INDEX0f); 7403 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, L3MC_INDEX1f, ipv4a); 7404 } 7405 7406 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR0f); 7407 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR1f, ipv4a); 7408 7409 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR_MASK0f); 7410 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR_MASK1f, ipv4a); 7411 7412 if (!SOC_IS_HURRICANE(u)) { 7413 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP0f); 7414 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP1f, ipv4a); 7415 } 7416 7417 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP_COUNT0f)) { 7418 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_COUNT0f); 7419 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_COUNT1f, ipv4a); 7420 7421 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_PTR0f); 7422 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_PTR1f, ipv4a); 7423 } else { 7424 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, NEXT_HOP_INDEX0f); 7425 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, NEXT_HOP_INDEX1f, ipv4a); 7426 } 7427 7428 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, PRI0f); 7429 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, PRI1f, ipv4a); 7430 7431 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPE0f); 7432 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPE1f, ipv4a); 7433 7434 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f)) { 7435 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_0f); 7436 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_1f, ipv4a); 7437 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_MASK0f); 7438 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_MASK1f, ipv4a); 7439 } 7440 7441 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD0f)) { 7442 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DST_DISCARD0f); 7443 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DST_DISCARD1f, ipv4a); 7444 } 7445 7446 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, CLASS_ID0f)) { 7447 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, CLASS_ID0f); 7448 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, CLASS_ID1f, ipv4a); 7449 } 7450 if (copy_hit) { 7451 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, HIT0f); 7452 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, HIT1f, ipv4a); 7453 } 7454 7455 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_HIGH0f); 7456 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_HIGH1f, ipv4a); 7457 7458 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ALG_HIT_IDX0f); 7459 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ALG_HIT_IDX1f, ipv4a); 7460 7461 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ALG_BKT_PTR0f); 7462 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ALG_BKT_PTR1f, ipv4a); 7463 7464 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DEFAULT_MISS0f); 7465 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DEFAULT_MISS1f, ipv4a); 7466 7467 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_BASE_COUNTER_IDX0f); 7468 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_BASE_COUNTER_IDX1f, ipv4a); 7469 7470 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_POOL_NUMBER0f); 7471 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_POOL_NUMBER1f, ipv4a); 7472 7473 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_OFFSET_MODE0f); 7474 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_OFFSET_MODE1f, ipv4a); 7475 7476 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ENTRY_VIEW0f); 7477 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ENTRY_VIEW1f, ipv4a); 7478 7479 return(SOC_E_NONE); 7480 } 7481 7482 /* src and dst can be same */ 7483 int 7484 soc_alpm_lpm_ip4entry1_to_0(int u, void *src, void *dst, int copy_hit) 7485 { 7486 uint32 ipv4a; 7487 7488 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VALID1f); 7489 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VALID0f, ipv4a); 7490 7491 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MODE1f); 7492 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MODE0f, ipv4a); 7493 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, MODE_MASK0f)) { 7494 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MODE_MASK1f); 7495 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MODE_MASK0f, ipv4a); 7496 } 7497 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, GLOBAL_ROUTE1f)) { 7498 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_ROUTE1f); 7499 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_ROUTE0f, ipv4a); 7500 } 7501 7502 if (soc_feature(u, soc_feature_ipmc_defip)) { 7503 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, MULTICAST_ROUTE1f); 7504 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, MULTICAST_ROUTE0f, ipv4a); 7505 7506 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPA_ID1f); 7507 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPA_ID0f, ipv4a); 7508 7509 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, EXPECTED_L3_IIF1f); 7510 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, EXPECTED_L3_IIF0f, ipv4a); 7511 7512 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f); 7513 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f, ipv4a); 7514 7515 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f); 7516 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f, ipv4a); 7517 7518 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, L3MC_INDEX1f); 7519 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, L3MC_INDEX0f, ipv4a); 7520 } 7521 7522 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR1f); 7523 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR0f, ipv4a); 7524 7525 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, IP_ADDR_MASK1f); 7526 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, IP_ADDR_MASK0f, ipv4a); 7527 7528 if (!SOC_IS_HURRICANE(u)) { 7529 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP1f); 7530 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP0f, ipv4a); 7531 } 7532 7533 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, ECMP_COUNT1f)) { 7534 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_COUNT1f); 7535 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_COUNT0f, ipv4a); 7536 7537 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ECMP_PTR1f); 7538 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ECMP_PTR0f, ipv4a); 7539 } else { 7540 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, NEXT_HOP_INDEX1f); 7541 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, NEXT_HOP_INDEX0f, ipv4a); 7542 } 7543 7544 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, PRI1f); 7545 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, PRI0f, ipv4a); 7546 7547 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, RPE1f); 7548 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, RPE0f, ipv4a); 7549 7550 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_1f)) { 7551 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_1f); 7552 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_0f, ipv4a); 7553 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, VRF_ID_MASK1f); 7554 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, VRF_ID_MASK0f, ipv4a); 7555 } 7556 7557 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD1f)) { 7558 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DST_DISCARD1f); 7559 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DST_DISCARD0f, ipv4a); 7560 } 7561 7562 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, CLASS_ID1f)) { 7563 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, CLASS_ID1f); 7564 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, CLASS_ID0f, ipv4a); 7565 } 7566 if (copy_hit) { 7567 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, HIT1f); 7568 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, HIT0f, ipv4a); 7569 } 7570 7571 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, GLOBAL_HIGH1f); 7572 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, GLOBAL_HIGH0f, ipv4a); 7573 7574 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ALG_HIT_IDX1f); 7575 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ALG_HIT_IDX0f, ipv4a); 7576 7577 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ALG_BKT_PTR1f); 7578 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ALG_BKT_PTR0f, ipv4a); 7579 7580 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, DEFAULT_MISS1f); 7581 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, DEFAULT_MISS0f, ipv4a); 7582 7583 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_BASE_COUNTER_IDX1f); 7584 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_BASE_COUNTER_IDX0f, ipv4a); 7585 7586 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_POOL_NUMBER1f); 7587 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_POOL_NUMBER0f, ipv4a); 7588 7589 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, FLEX_CTR_OFFSET_MODE1f); 7590 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, FLEX_CTR_OFFSET_MODE0f, ipv4a); 7591 7592 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, src, ENTRY_VIEW1f); 7593 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, dst, ENTRY_VIEW0f, ipv4a); 7594 7595 return(SOC_E_NONE); 7596 } 7597 7598 void 7599 soc_alpm_lpm_state_dump(int u) 7600 { 7601 int i; 7602 int max_pfx_len; 7603 max_pfx_len = ALPM_MAX_PFX_INDEX; 7604 7605 #ifndef BCM_WARM_BOOT_SUPPORT_SW_DUMP 7606 if (!bsl_check(bslLayerSoc, bslSourceAlpm, bslSeverityVerbose, u)) { 7607 return; 7608 } 7609 #endif 7610 7611 for(i = max_pfx_len; i >= 0 ; i--) { 7612 if ((i != ALPM_MAX_PFX_INDEX) && (SOC_ALPM_LPM_STATE_START(u, i) == -1)) { 7613 continue; 7614 } 7615 7616 #ifdef ALPM_WARM_BOOT_DEBUG 7617 LOG_ERROR(BSL_LS_SOC_ALPM, 7618 (BSL_META_U(u, 7619 "PFX = %d P = %d N = %d START = %d END = %d VENT = %d FENT = %d\n"), 7620 i, 7621 SOC_ALPM_LPM_STATE_PREV(u, i), 7622 SOC_ALPM_LPM_STATE_NEXT(u, i), 7623 SOC_ALPM_LPM_STATE_START(u, i), 7624 SOC_ALPM_LPM_STATE_END(u, i), 7625 SOC_ALPM_LPM_STATE_VENT(u, i), 7626 SOC_ALPM_LPM_STATE_FENT(u, i))); 7627 #else 7628 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7629 (BSL_META_U(u, 7630 "PFX = %d P = %d N = %d START = %d END = %d VENT = %d FENT = %d\n"), 7631 i, 7632 SOC_ALPM_LPM_STATE_PREV(u, i), 7633 SOC_ALPM_LPM_STATE_NEXT(u, i), 7634 SOC_ALPM_LPM_STATE_START(u, i), 7635 SOC_ALPM_LPM_STATE_END(u, i), 7636 SOC_ALPM_LPM_STATE_VENT(u, i), 7637 SOC_ALPM_LPM_STATE_FENT(u, i))); 7638 #endif 7639 } 7640 } 7641 7642 7643 /* 7644 * Function: 7645 * _lpm_fb_urpf_entry_replicate 7646 * Purpose: 7647 * Replicate entry to the second half of the tcam if URPF check is ON. 7648 * Parameters: 7649 * u - (IN) SOC unit number. 7650 * index: - (IN) corresponding dip target index 7651 * e - (IN|OUT) input dip entry, could be modified for sip 7652 * src_index - (IN) if ALPM_INVALID_INDEX use input e, 7653 * otherwise copy from src_index. 7654 * convert - (IN) Used if src_index != ALPM_INVALID_INDEX. 7655 * src_default - (IN) Used if src_index = ALPM_INVALID_INDEX. 7656 * 0 - caculate using entry_data's mask (legacy way) 7657 * 1 - force set (split case) 7658 * src_discard - (IN) Used if src_index = ALPM_INVALID_INDEX. 7659 * Returns: 7660 * BCM_E_XXX 7661 */ 7662 static 7663 int _lpm_fb_urpf_entry_replicate(int u, int src_index, int index, uint32 *e, 7664 int convert, int src_default, int src_discard, 7665 int bpm_len, int v4_half) 7666 { 7667 int src_tcam_offset; /* Defip memory size/2 urpf source lookup offset */ 7668 int ipv6; /* IPv6 entry. */ 7669 uint32 mask0; /* Mask 0 field value. */ 7670 uint32 mask1; /* Mask 1 field value. */ 7671 int def_gw_flag; /* Entry is default gateway. */ 7672 defip_entry_t urpf; 7673 7674 if(!SOC_URPF_STATUS_GET(u)) { 7675 return (SOC_E_NONE); 7676 } 7677 7678 src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1); 7679 7680 ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, MODE0f); 7681 7682 if (src_index != ALPM_INVALID_INDEX) { 7683 #ifdef FB_LPM_TABLE_CACHED 7684 SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, L3_DEFIPm, 7685 MEM_BLOCK_ANY, 7686 src_index + src_tcam_offset)); 7687 #endif /* FB_LPM_TABLE_CACHED */ 7688 7689 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY, 7690 src_index + src_tcam_offset, 7691 &urpf)); 7692 switch (convert) { 7693 case CONVERT_NONE: 7694 sal_memcpy(e, &urpf, sizeof(defip_entry_t)); 7695 break; 7696 case 0: 7697 mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, &urpf, RPE0f); 7698 mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, &urpf, DST_DISCARD0f); 7699 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE0f, mask0); 7700 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD0f, mask1); 7701 break; 7702 case 1: 7703 mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, &urpf, RPE0f); 7704 mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, &urpf, DST_DISCARD0f); 7705 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE1f, mask0); 7706 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD1f, mask1); 7707 break; 7708 case 2: 7709 mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, &urpf, RPE1f); 7710 mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, &urpf, DST_DISCARD1f); 7711 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE0f, mask0); 7712 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD0f, mask1); 7713 break; 7714 case 3: 7715 mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, &urpf, RPE1f); 7716 mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, &urpf, DST_DISCARD1f); 7717 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE1f, mask0); 7718 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD1f, mask1); 7719 break; 7720 default: 7721 return SOC_E_INTERNAL; 7722 } 7723 7724 /* Write entry to the second half of the tcam. */ 7725 /* Better use index instead of (index + src_tcam_offset) for src_index, 7726 * because the entry at index is just written, and we can simply form 7727 * aux based on it, it's simple. 7728 * But if we use (index + src_tcam_offset), we have to do convert again. 7729 */ 7730 return _soc_alpm_write_pivot_aux(u, index, index + src_tcam_offset, e, 7731 CONVERT_NONE, bpm_len, v4_half); 7732 } 7733 7734 src_default = src_default ? 1 : 0; 7735 src_discard = src_discard ? 1 : 0; 7736 7737 /* Set/Reset default gateway flag based on ip mask value. */ 7738 mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, IP_ADDR_MASK0f); 7739 mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, IP_ADDR_MASK1f); 7740 7741 if (!ipv6) { 7742 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f)) { 7743 def_gw_flag = (!mask0) ? 1 : 0; 7744 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE0f, src_default | def_gw_flag); 7745 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD0f)) { 7746 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD0f, src_discard); 7747 } 7748 } 7749 7750 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f)) { 7751 def_gw_flag = (!mask1) ? 1 : 0; 7752 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE1f, src_default | def_gw_flag); 7753 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD1f)) { 7754 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD1f, src_discard); 7755 } 7756 } 7757 } else { 7758 def_gw_flag = ((!mask0) && (!mask1)) ? 1 : 0; 7759 mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f); 7760 mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f); 7761 if (mask0 && mask1) { 7762 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE0f, src_default | def_gw_flag); 7763 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE1f, src_default | def_gw_flag); 7764 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD0f)) { 7765 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD0f, src_discard); 7766 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD1f, src_discard); 7767 } 7768 } 7769 } 7770 /* Write entry to the second half of the tcam. */ 7771 return _soc_alpm_write_pivot_aux(u, index, index + src_tcam_offset, e, 7772 CONVERT_NONE, bpm_len, v4_half); 7773 } 7774 7775 static int 7776 _soc_alpm_write_pivot_with_bpm(int u, int src_index, int index, void *entry, 7777 uint32 op, int src_default_or_convert, 7778 int src_discard, int bpm_len, int v4_half) 7779 { 7780 7781 int convert = CONVERT_NONE; 7782 int src_index_uprf = ALPM_INVALID_INDEX; 7783 int sdefault = 0, sdiscard = 0; 7784 uint32 rvt_index0 = 0, rvt_index1 = 0; 7785 int rv; 7786 7787 switch (op & (~WRITE_PIVOT_WITHOUT_INSERT_HASH)) { 7788 case WRITE_PIVOT_WITH_SRC_INDEX: 7789 src_index_uprf = src_index; 7790 break; 7791 case WRITE_PIVOT_WITH_SRC_INDEX_CONVERT: 7792 src_index_uprf = src_index; 7793 convert = src_default_or_convert; 7794 break; 7795 case WRITE_PIVOT_WITH_URPF_PARAMS: 7796 sdefault = src_default_or_convert; 7797 sdiscard = src_discard; 7798 break; 7799 default: 7800 return SOC_E_INTERNAL; 7801 } 7802 7803 if (!(op & WRITE_PIVOT_WITHOUT_INSERT_HASH)) { 7804 LPM_HASH_INSERT(u, entry, index, &rvt_index0, &rvt_index1); 7805 } 7806 7807 /* Do not use src_index_urpf because it can be invalid. 7808 * For aux entry, reading src from HW is required for BPM_LENGTH. 7809 */ 7810 rv = (_soc_alpm_write_pivot_aux(u, src_index, index, entry, convert, bpm_len, v4_half)); 7811 7812 if (rv >= 0) { 7813 rv = (_lpm_fb_urpf_entry_replicate(u, src_index_uprf, index, entry, 7814 convert, sdefault, sdiscard, bpm_len, v4_half)); 7815 } 7816 if (!(op & WRITE_PIVOT_WITHOUT_INSERT_HASH) && rv < 0) { 7817 LPM_HASH_REVERT(u, entry, index, rvt_index0, rvt_index1); 7818 } 7819 7820 return rv; 7821 } 7822 static int 7823 _soc_alpm_write_pivot(int u, int src_index, int index, void *entry, 7824 uint32 op, int src_default_or_convert, int src_discard) 7825 { 7826 return _soc_alpm_write_pivot_with_bpm(u, src_index, index, entry, op, 7827 src_default_or_convert, src_discard, INVALID_BPM_LEN, 0); 7828 } 7829 static void 7830 _soc_alpm_move_pivot(int u, int src, int dst, int src_half, int dst_half) 7831 { 7832 alpm_pivot_t *src_pivot; 7833 7834 src = soc_alpm_physical_idx((u), L3_DEFIPm, (src), 1) << 1; 7835 dst = soc_alpm_physical_idx((u), L3_DEFIPm, (dst), 1) << 1; 7836 src += src_half ? 1 : 0; 7837 dst += dst_half ? 1 : 0; 7838 7839 src_pivot = ALPM_TCAM_PIVOT(u, src); 7840 if (src_pivot) { 7841 PIVOT_TCAM_INDEX(src_pivot) = dst; 7842 } 7843 7844 ALPM_TCAM_PIVOT(u, dst) = src_pivot; 7845 ALPM_TCAM_PIVOT(u, src) = NULL; 7846 7847 return; 7848 } 7849 7850 /* 7851 * Create a slot for the new entry rippling the entries if required 7852 */ 7853 static 7854 int _lpm_fb_entry_shift(int u, int from_ent, int to_ent) 7855 { 7856 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 7857 7858 if (from_ent == to_ent) { 7859 return SOC_E_NONE; 7860 } 7861 7862 #ifdef FB_LPM_TABLE_CACHED 7863 SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, L3_DEFIPm, 7864 MEM_BLOCK_ANY, from_ent)); 7865 #endif /* FB_LPM_TABLE_CACHED */ 7866 7867 SOC_IF_ERROR_RETURN( 7868 _soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY, from_ent, e)); 7869 7870 SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, to_ent, e, 7871 WRITE_PIVOT_WITH_SRC_INDEX, 0, 0)); 7872 7873 /* from_ent != to_ent */ 7874 _soc_alpm_move_pivot(u, from_ent, to_ent, 0, 0); 7875 _soc_alpm_move_pivot(u, from_ent, to_ent, 1, 1); 7876 return (SOC_E_NONE); 7877 } 7878 7879 7880 /* 7881 * Shift prefix entries 1 entry UP, while preserving 7882 * last half empty IPv4 entry if any. 7883 */ 7884 static 7885 int _lpm_fb_shift_pfx_up(int u, int pfx, int ipv6) 7886 { 7887 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 7888 int from_ent; 7889 int to_ent; 7890 uint32 v0, v1; 7891 7892 to_ent = SOC_ALPM_LPM_STATE_END(u, pfx) + 1; 7893 7894 ipv6 = SOC_ALPM_PFX_IS_V6_64(u, pfx); 7895 if (!ipv6) { 7896 from_ent = SOC_ALPM_LPM_STATE_END(u, pfx); 7897 #ifdef FB_LPM_TABLE_CACHED 7898 SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, L3_DEFIPm, 7899 MEM_BLOCK_ANY, from_ent)); 7900 #endif /* FB_LPM_TABLE_CACHED */ 7901 SOC_IF_ERROR_RETURN( 7902 _soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY, from_ent, e)); 7903 v0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f); 7904 v1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f); 7905 7906 if ((v0 == 0) || (v1 == 0)) { 7907 /* Last entry is half full -> keep it last. */ 7908 SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, to_ent, e, 7909 WRITE_PIVOT_WITH_SRC_INDEX, 0, 0)); 7910 7911 /* track pivot state movement */ 7912 /* from_ent != to_ent */ 7913 _soc_alpm_move_pivot(u, from_ent, to_ent, v1, 0); 7914 to_ent--; 7915 } 7916 } 7917 7918 from_ent = SOC_ALPM_LPM_STATE_START(u, pfx); 7919 if (from_ent != to_ent) { 7920 SOC_IF_ERROR_RETURN(_lpm_fb_entry_shift(u, from_ent, to_ent)); 7921 VRF_PIVOT_SHIFT_INC(u, MAX_VRF_ID, ipv6); 7922 } 7923 SOC_ALPM_LPM_STATE_START(u, pfx) += 1; 7924 SOC_ALPM_LPM_STATE_END(u, pfx) += 1; 7925 return (SOC_E_NONE); 7926 } 7927 7928 /* 7929 * Shift prefix entries 1 entry DOWN, while preserving 7930 * last half empty IPv4 entry if any. 7931 */ 7932 static 7933 int _lpm_fb_shift_pfx_down(int u, int pfx, int ipv6) 7934 { 7935 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 7936 int from_ent; 7937 int to_ent; 7938 int prev_ent; 7939 uint32 v0, v1; 7940 7941 to_ent = SOC_ALPM_LPM_STATE_START(u, pfx) - 1; 7942 7943 /* Don't move empty prefix . */ 7944 if (SOC_ALPM_LPM_STATE_VENT(u, pfx) == 0) { 7945 SOC_ALPM_LPM_STATE_START(u, pfx) = to_ent; 7946 SOC_ALPM_LPM_STATE_END(u, pfx) = to_ent - 1; 7947 return (SOC_E_NONE); 7948 } 7949 7950 ipv6 = SOC_ALPM_PFX_IS_V6_64(u, pfx); 7951 if ((!ipv6) && (SOC_ALPM_LPM_STATE_END(u, pfx) != SOC_ALPM_LPM_STATE_START(u, pfx))) { 7952 7953 from_ent = SOC_ALPM_LPM_STATE_END(u, pfx); 7954 7955 #ifdef FB_LPM_TABLE_CACHED 7956 SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, L3_DEFIPm, 7957 MEM_BLOCK_ANY, from_ent)); 7958 #endif /* FB_LPM_TABLE_CACHED */ 7959 SOC_IF_ERROR_RETURN( 7960 _soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY, from_ent, e)); 7961 v0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f); 7962 v1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f); 7963 7964 if ((v0 == 0) || (v1 == 0)) { 7965 /* Last entry is half full -> keep it last. */ 7966 /* Shift entry before last to start - 1 position. */ 7967 prev_ent = from_ent - 1; 7968 SOC_IF_ERROR_RETURN(_lpm_fb_entry_shift(u, prev_ent, to_ent)); 7969 VRF_PIVOT_SHIFT_INC(u, MAX_VRF_ID, ipv6); 7970 7971 7972 SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, prev_ent, e, 7973 WRITE_PIVOT_WITH_SRC_INDEX, 0, 0)); 7974 7975 /* from_ent != prev_ent */ 7976 _soc_alpm_move_pivot(u, from_ent, prev_ent, v1, 0); 7977 } else { 7978 /* Last entry is full -> just shift it to start - 1 position. */ 7979 7980 SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, to_ent, e, 7981 WRITE_PIVOT_WITH_SRC_INDEX, 0, 0)); 7982 7983 /* Track full-entry move */ 7984 /* from_ent != to_ent */ 7985 _soc_alpm_move_pivot(u, from_ent, to_ent, 0, 0); 7986 _soc_alpm_move_pivot(u, from_ent, to_ent, 1, 1); 7987 } 7988 7989 } else { 7990 7991 from_ent = SOC_ALPM_LPM_STATE_END(u, pfx); 7992 SOC_IF_ERROR_RETURN(_lpm_fb_entry_shift(u, from_ent, to_ent)); 7993 VRF_PIVOT_SHIFT_INC(u, MAX_VRF_ID, ipv6); 7994 7995 } 7996 SOC_ALPM_LPM_STATE_START(u, pfx) -= 1; 7997 SOC_ALPM_LPM_STATE_END(u, pfx) -= 1; 7998 7999 return (SOC_E_NONE); 8000 } 8001 8002 /* 8003 * Create a slot for the new entry rippling the entries if required 8004 */ 8005 static 8006 int _lpm_free_slot_create(int u, int pfx, int ipv6, void *e, int *free_slot) 8007 { 8008 int prev_pfx; 8009 int next_pfx; 8010 int free_pfx; 8011 int curr_pfx; 8012 int from_ent; 8013 uint32 v0, v1; 8014 int rv; 8015 8016 8017 if (SOC_ALPM_LPM_STATE_VENT(u, pfx) == 0) { 8018 /* 8019 * Find the prefix position. Only prefix with valid 8020 * entries are in the list. 8021 * next -> high to low prefix. low to high index 8022 * prev -> low to high prefix. high to low index 8023 * Unused prefix length ALPM_MAX_PFX_INDEX is the head of the 8024 * list and is node corresponding to this is always 8025 * present. 8026 */ 8027 curr_pfx = ALPM_MAX_PFX_INDEX; 8028 if (soc_alpm_mode_get(u) == SOC_ALPM_MODE_PARALLEL) { 8029 if (pfx <= ALPM_MAX_VRF_PFX_INDEX) { 8030 curr_pfx = ALPM_MAX_VRF_PFX_INDEX; 8031 } 8032 } 8033 while (SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx) > pfx) { 8034 curr_pfx = SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx); 8035 } 8036 /* Insert the new prefix */ 8037 next_pfx = SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx); 8038 if (next_pfx != -1) { 8039 SOC_ALPM_LPM_STATE_PREV(u, next_pfx) = pfx; 8040 } 8041 SOC_ALPM_LPM_STATE_NEXT(u, pfx) = SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx); 8042 SOC_ALPM_LPM_STATE_PREV(u, pfx) = curr_pfx; 8043 SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx) = pfx; 8044 8045 SOC_ALPM_LPM_STATE_FENT(u, pfx) = (SOC_ALPM_LPM_STATE_FENT(u, curr_pfx) + 1) / 2; 8046 SOC_ALPM_LPM_STATE_FENT(u, curr_pfx) -= SOC_ALPM_LPM_STATE_FENT(u, pfx); 8047 SOC_ALPM_LPM_STATE_START(u, pfx) = SOC_ALPM_LPM_STATE_END(u, curr_pfx) + 8048 SOC_ALPM_LPM_STATE_FENT(u, curr_pfx) + 1; 8049 SOC_ALPM_LPM_STATE_END(u, pfx) = SOC_ALPM_LPM_STATE_START(u, pfx) - 1; 8050 SOC_ALPM_LPM_STATE_VENT(u, pfx) = 0; 8051 } else if (!ipv6) { 8052 /* For IPv4 Check if alternate entry is free */ 8053 from_ent = SOC_ALPM_LPM_STATE_START(u, pfx); 8054 #ifdef FB_LPM_TABLE_CACHED 8055 if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm, 8056 MEM_BLOCK_ANY, from_ent)) < 0) { 8057 return rv; 8058 } 8059 #endif /* FB_LPM_TABLE_CACHED */ 8060 if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm, 8061 MEM_BLOCK_ANY, from_ent, e)) < 0) { 8062 return rv; 8063 } 8064 v0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f); 8065 v1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f); 8066 8067 if ((v0 == 0) || (v1 == 0)) { 8068 *free_slot = (from_ent << 1) + ((v1 == 0) ? 1 : 0); 8069 return(SOC_E_NONE); 8070 } 8071 8072 from_ent = SOC_ALPM_LPM_STATE_END(u, pfx); 8073 #ifdef FB_LPM_TABLE_CACHED 8074 if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm, 8075 MEM_BLOCK_ANY, from_ent)) < 0) { 8076 return rv; 8077 } 8078 #endif /* FB_LPM_TABLE_CACHED */ 8079 if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm, 8080 MEM_BLOCK_ANY, from_ent, e)) < 0) { 8081 return rv; 8082 } 8083 v0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f); 8084 v1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f); 8085 8086 if ((v0 == 0) || (v1 == 0)) { 8087 *free_slot = (from_ent << 1) + ((v1 == 0) ? 1 : 0); 8088 return(SOC_E_NONE); 8089 } 8090 } 8091 8092 free_pfx = pfx; 8093 while(SOC_ALPM_LPM_STATE_FENT(u, free_pfx) == 0) { 8094 free_pfx = SOC_ALPM_LPM_STATE_NEXT(u, free_pfx); 8095 if (free_pfx == -1) { 8096 /* No free entries on this side try the other side */ 8097 free_pfx = pfx; 8098 break; 8099 } 8100 } 8101 8102 while(SOC_ALPM_LPM_STATE_FENT(u, free_pfx) == 0) { 8103 free_pfx = SOC_ALPM_LPM_STATE_PREV(u, free_pfx); 8104 if (free_pfx == -1) { 8105 if (SOC_ALPM_LPM_STATE_VENT(u, pfx) == 0) { 8106 /* We failed to allocate entries for a newly allocated prefix.*/ 8107 prev_pfx = SOC_ALPM_LPM_STATE_PREV(u, pfx); 8108 next_pfx = SOC_ALPM_LPM_STATE_NEXT(u, pfx); 8109 if (-1 != prev_pfx) { 8110 SOC_ALPM_LPM_STATE_NEXT(u, prev_pfx) = next_pfx; 8111 } 8112 if (-1 != next_pfx) { 8113 SOC_ALPM_LPM_STATE_PREV(u, next_pfx) = prev_pfx; 8114 } 8115 } 8116 return(SOC_E_FULL); 8117 } 8118 } 8119 8120 /* 8121 * Ripple entries to create free space 8122 */ 8123 while (free_pfx > pfx) { 8124 next_pfx = SOC_ALPM_LPM_STATE_NEXT(u, free_pfx); 8125 SOC_IF_ERROR_RETURN(_lpm_fb_shift_pfx_down(u, next_pfx, ipv6)); 8126 SOC_ALPM_LPM_STATE_FENT(u, free_pfx) -= 1; 8127 SOC_ALPM_LPM_STATE_FENT(u, next_pfx) += 1; 8128 free_pfx = next_pfx; 8129 } 8130 8131 while (free_pfx < pfx) { 8132 SOC_IF_ERROR_RETURN(_lpm_fb_shift_pfx_up(u, free_pfx, ipv6)); 8133 SOC_ALPM_LPM_STATE_FENT(u, free_pfx) -= 1; 8134 prev_pfx = SOC_ALPM_LPM_STATE_PREV(u, free_pfx); 8135 SOC_ALPM_LPM_STATE_FENT(u, prev_pfx) += 1; 8136 free_pfx = prev_pfx; 8137 } 8138 8139 SOC_ALPM_LPM_STATE_VENT(u, pfx) += 1; 8140 SOC_ALPM_LPM_STATE_FENT(u, pfx) -= 1; 8141 SOC_ALPM_LPM_STATE_END(u, pfx) += 1; 8142 *free_slot = SOC_ALPM_LPM_STATE_END(u, pfx) << ((ipv6) ? 0 : 1); 8143 sal_memcpy(e, soc_mem_entry_null(u, L3_DEFIPm), 8144 soc_mem_entry_words(u,L3_DEFIPm) * 4); 8145 8146 return(SOC_E_NONE); 8147 } 8148 8149 /* 8150 * Delete a slot and adjust entry pointers if required. 8151 * e - has the contents of entry at slot(useful for IPV4 only) 8152 */ 8153 static 8154 int _lpm_free_slot_delete(int u, int pfx, int ipv6, void *e, int slot) 8155 { 8156 int prev_pfx; 8157 int next_pfx; 8158 int from_ent; 8159 int to_ent; 8160 uint32 ef[SOC_MAX_MEM_FIELD_WORDS]; 8161 uint32 sf[SOC_MAX_MEM_FIELD_WORDS]; 8162 uint32 st[SOC_MAX_MEM_FIELD_WORDS]; 8163 void *et; 8164 int rv = SOC_E_NONE; 8165 int bpm_len; 8166 int src_half = 0, dst_half = 0; 8167 8168 from_ent = SOC_ALPM_LPM_STATE_END(u, pfx); 8169 to_ent = slot; 8170 if (!ipv6) { /* IPV4 */ 8171 to_ent >>= 1; 8172 #ifdef FB_LPM_TABLE_CACHED 8173 if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm, 8174 MEM_BLOCK_ANY, from_ent)) < 0) { 8175 return rv; 8176 } 8177 #endif /* FB_LPM_TABLE_CACHED */ 8178 if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm, 8179 MEM_BLOCK_ANY, from_ent, ef)) < 0) { 8180 return rv; 8181 } 8182 /* get bpm_len of entry that is about to move */ 8183 if ((rv = READ_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ANY, 8184 soc_alpm_physical_idx(u, L3_DEFIPm, from_ent, 1), sf)) < 0) { 8185 return rv; 8186 } 8187 if ((rv = READ_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ANY, 8188 soc_alpm_physical_idx(u, L3_DEFIPm, to_ent, 1), st)) < 0) { 8189 return rv; 8190 } 8191 et = (to_ent == from_ent) ? ef : e; 8192 src_half = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef, VALID1f); 8193 dst_half = (slot & 1); 8194 if (src_half) { 8195 bpm_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm, 8196 sf, BPM_LENGTH1f); 8197 if (dst_half) { 8198 rv = soc_alpm_lpm_ip4entry1_to_1(u, ef, et, PRESERVE_HIT); 8199 soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, st, BPM_LENGTH1f, 8200 bpm_len); 8201 } else { 8202 rv = soc_alpm_lpm_ip4entry1_to_0(u, ef, et, PRESERVE_HIT); 8203 soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, st, BPM_LENGTH0f, 8204 bpm_len); 8205 } 8206 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, ef, VALID1f, 0); 8207 } else { 8208 bpm_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm, 8209 sf, BPM_LENGTH0f); 8210 if (dst_half) { 8211 rv = soc_alpm_lpm_ip4entry0_to_1(u, ef, et, PRESERVE_HIT); 8212 soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, st, BPM_LENGTH1f, 8213 bpm_len); 8214 } else { 8215 rv = soc_alpm_lpm_ip4entry0_to_0(u, ef, et, PRESERVE_HIT); 8216 soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, st, BPM_LENGTH0f, 8217 bpm_len); 8218 } 8219 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, ef, VALID0f, 0); 8220 SOC_ALPM_LPM_STATE_VENT(u, pfx) -= 1; 8221 SOC_ALPM_LPM_STATE_FENT(u, pfx) += 1; 8222 SOC_ALPM_LPM_STATE_END(u, pfx) -= 1; 8223 } 8224 8225 /* update bpm_len at target */ 8226 if ((rv = WRITE_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ALL, 8227 soc_alpm_physical_idx(u, L3_DEFIPm, to_ent, 1), st)) < 0) { 8228 return rv; 8229 } 8230 8231 if (to_ent == from_ent) { 8232 SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, from_ent, ef, 8233 WRITE_PIVOT_WITH_SRC_INDEX_CONVERT, 8234 ((src_half << 1) | dst_half), 0)); 8235 } else { 8236 SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, to_ent, et, 8237 WRITE_PIVOT_WITH_SRC_INDEX_CONVERT, 8238 ((src_half << 1) | dst_half), 0)); 8239 8240 /* Use WRITE_PIVOT_WITH_URPF_PARAMS because it's faster */ 8241 SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, from_ent, ef, 8242 WRITE_PIVOT_WITH_URPF_PARAMS, 0, 0)); 8243 } 8244 8245 _soc_alpm_move_pivot(u, from_ent, to_ent, src_half, dst_half); 8246 8247 } else { /* IPV6 */ 8248 SOC_ALPM_LPM_STATE_VENT(u, pfx) -= 1; 8249 SOC_ALPM_LPM_STATE_FENT(u, pfx) += 1; 8250 SOC_ALPM_LPM_STATE_END(u, pfx) -= 1; 8251 if (to_ent != from_ent) { 8252 #ifdef FB_LPM_TABLE_CACHED 8253 if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm, 8254 MEM_BLOCK_ANY, from_ent)) < 0) { 8255 return rv; 8256 } 8257 #endif /* FB_LPM_TABLE_CACHED */ 8258 if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm, 8259 MEM_BLOCK_ANY, from_ent, ef)) < 0) { 8260 return rv; 8261 } 8262 8263 SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, to_ent, ef, 8264 WRITE_PIVOT_WITH_SRC_INDEX, 0, 0)); 8265 } 8266 8267 /* set from_ent invalid */ 8268 sal_memcpy(ef, soc_mem_entry_null(u, L3_DEFIPm), 8269 soc_mem_entry_words(u,L3_DEFIPm) * 4); 8270 8271 SOC_IF_ERROR_RETURN(_soc_alpm_write_pivot(u, from_ent, from_ent, ef, 8272 WRITE_PIVOT_WITH_URPF_PARAMS, 0, 0)); 8273 8274 _soc_alpm_move_pivot(u, from_ent, to_ent, 0, 0); 8275 _soc_alpm_move_pivot(u, from_ent, to_ent, 1, 1); 8276 } 8277 8278 if (SOC_ALPM_LPM_STATE_VENT(u, pfx) == 0) { 8279 /* remove from the list */ 8280 prev_pfx = SOC_ALPM_LPM_STATE_PREV(u, pfx); /* Always present */ 8281 assert(prev_pfx != -1); 8282 next_pfx = SOC_ALPM_LPM_STATE_NEXT(u, pfx); 8283 SOC_ALPM_LPM_STATE_NEXT(u, prev_pfx) = next_pfx; 8284 SOC_ALPM_LPM_STATE_FENT(u, prev_pfx) += SOC_ALPM_LPM_STATE_FENT(u, pfx); 8285 SOC_ALPM_LPM_STATE_FENT(u, pfx) = 0; 8286 if (next_pfx != -1) { 8287 SOC_ALPM_LPM_STATE_PREV(u, next_pfx) = prev_pfx; 8288 } 8289 SOC_ALPM_LPM_STATE_NEXT(u, pfx) = -1; 8290 SOC_ALPM_LPM_STATE_PREV(u, pfx) = -1; 8291 SOC_ALPM_LPM_STATE_START(u, pfx) = -1; 8292 SOC_ALPM_LPM_STATE_END(u, pfx) = -1; 8293 } 8294 8295 return(rv); 8296 } 8297 8298 8299 /* 8300 * Function: 8301 * soc_alpm_lpm_vrf_get 8302 * Purpose: 8303 * Service routine used to translate hw specific vrf id to API format. 8304 * Parameters: 8305 * unit - (IN)SOC unit number. 8306 * lpm_entry - (IN)Route info buffer from hw. 8307 * vrf_id - (OUT)Virtual router id. 8308 * Returns: 8309 * BCM_E_XXX 8310 */ 8311 int 8312 soc_alpm_lpm_vrf_get(int unit, void *lpm_entry, int *vrf_id, int *vrf) 8313 { 8314 int mem_vrf; 8315 8316 /* Get Virtual Router id if supported. */ 8317 if (SOC_MEM_OPT_FIELD_VALID(unit, L3_DEFIPm, VRF_ID_MASK0f)){ 8318 mem_vrf = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VRF_ID_0f); 8319 8320 /* Special vrf's handling. */ 8321 if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f)) { 8322 *vrf_id = mem_vrf; 8323 } else if (!SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, 8324 GLOBAL_HIGH0f)) { 8325 *vrf_id = SOC_L3_VRF_GLOBAL; 8326 } else { 8327 *vrf_id = SOC_L3_VRF_OVERRIDE; 8328 } 8329 if (vrf) { 8330 if (*vrf_id == SOC_L3_VRF_GLOBAL) { 8331 *vrf = SOC_VRF_MAX(unit) + 1; 8332 } else { 8333 *vrf = mem_vrf; 8334 } 8335 } 8336 } else { 8337 /* No vrf support on this device. */ 8338 *vrf_id = SOC_L3_VRF_DEFAULT; 8339 } 8340 return (SOC_E_NONE); 8341 } 8342 8343 /* 8344 * _soc_alpm_lpm_prefix_length_get (Extract vrf weighted prefix lenght from the 8345 * hw entry based on ip, mask & vrf) 8346 */ 8347 static int 8348 _soc_alpm_lpm_prefix_length_get(int u, void *entry, int *pfx_len) 8349 { 8350 int pfx; 8351 int rv; 8352 int ipv6; 8353 uint32 ipv4a; 8354 int vrf_id; 8355 int mode; 8356 8357 ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, MODE0f); 8358 8359 if (ipv6) { 8360 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f); 8361 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 8362 return(rv); 8363 } 8364 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK1f); 8365 if (pfx) { 8366 if (ipv4a != 0xffffffff) { 8367 return(SOC_E_PARAM); 8368 } 8369 pfx += 32; 8370 } else { 8371 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 8372 return(rv); 8373 } 8374 } 8375 pfx += ALPM_IPV6_PFX_ZERO; /* First 33 are for IPV4 addresses */ 8376 } else { 8377 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f); 8378 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 8379 return(rv); 8380 } 8381 } 8382 8383 SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, entry, &vrf_id, NULL)); 8384 8385 /* In ALPM the arragnement of VRF is at he begining followed by VRF 8386 * override and global */ 8387 mode = soc_alpm_mode_get(u); 8388 switch (vrf_id) { 8389 case SOC_L3_VRF_GLOBAL: 8390 if (mode == SOC_ALPM_MODE_PARALLEL) { 8391 *pfx_len = pfx + (ALPM_MAX_PFX_ENTRIES / 3); 8392 } else { 8393 *pfx_len = pfx; 8394 } 8395 break; 8396 case SOC_L3_VRF_OVERRIDE: 8397 *pfx_len = pfx + 2 * (ALPM_MAX_PFX_ENTRIES / 3); 8398 break; 8399 default: 8400 if (mode == SOC_ALPM_MODE_PARALLEL) { 8401 *pfx_len = pfx; 8402 } else { 8403 *pfx_len = pfx + (ALPM_MAX_PFX_ENTRIES / 3); 8404 } 8405 break; 8406 } 8407 return (SOC_E_NONE); 8408 } 8409 8410 8411 /* 8412 * _soc_alpm_lpm_match (Exact match for the key. Will match both IP address 8413 * and mask) 8414 */ 8415 static int 8416 _soc_alpm_lpm_match(int u, 8417 void *key_data, 8418 void *e, /* return entry data if found */ 8419 int *index_ptr, /* return key location */ 8420 int *pfx_len, /* Key prefix length. vrf + 32 + prefix len for IPV6*/ 8421 int *ipv6) /* Entry is ipv6. */ 8422 { 8423 int rv; 8424 int v6; 8425 int key_index; 8426 int pfx = 0; 8427 8428 v6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, MODE0f); 8429 8430 if (v6) { 8431 if (!(v6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, MODE1f))) { 8432 return (SOC_E_PARAM); 8433 } 8434 } 8435 *ipv6 = v6; 8436 8437 /* Calculate vrf weighted prefix lengh. */ 8438 _soc_alpm_lpm_prefix_length_get(u, key_data, &pfx); 8439 *pfx_len = pfx; 8440 8441 #ifdef FB_LPM_HASH_SUPPORT 8442 if (LPM_HASH_LOOKUP(u, key_data, pfx, &key_index) == SOC_E_NONE) { 8443 *index_ptr = key_index; 8444 if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY, 8445 (*ipv6) ? *index_ptr : (*index_ptr >> 1), e)) < 0) { 8446 return rv; 8447 } 8448 #ifndef FB_LPM_CHECKER_ENABLE 8449 return(SOC_E_NONE); 8450 #endif 8451 } else { 8452 #ifndef FB_LPM_CHECKER_ENABLE 8453 return(SOC_E_NOT_FOUND); 8454 #endif 8455 } 8456 #endif /* FB_LPM_HASH_SUPPORT */ 8457 } 8458 8459 /* 8460 * Initialize the start/end tracking pointers for each prefix length 8461 */ 8462 static int 8463 soc_alpm_lpm_init(int u) 8464 { 8465 int max_pfx_len; 8466 int i; 8467 int defip_table_size; 8468 int pfx_state_size; 8469 uint32 rval = 0; 8470 uint32 mode; 8471 8472 if (! soc_feature(u, soc_feature_lpm_tcam)) { 8473 return(SOC_E_UNAVAIL); 8474 } 8475 8476 if ((mode = soc_property_get(u, spn_L3_ALPM_ENABLE, 0))) { 8477 /* Set DEFIP mode to ALPM */ 8478 SOC_IF_ERROR_RETURN(READ_L3_DEFIP_RPF_CONTROLr(u, &rval)); 8479 soc_reg_field_set(u, L3_DEFIP_RPF_CONTROLr, &rval, LPM_MODEf, 1); 8480 /* Parallel mode */ 8481 if (mode == SOC_ALPM_MODE_PARALLEL) { 8482 soc_reg_field_set(u, L3_DEFIP_RPF_CONTROLr, &rval, LOOKUP_MODEf, 1); 8483 } else { 8484 /* combined search mode */ 8485 soc_reg_field_set(u, L3_DEFIP_RPF_CONTROLr, &rval, LOOKUP_MODEf, 0); 8486 } 8487 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_RPF_CONTROLr(u, rval)); 8488 SOC_ALPM_SW_LOOKUP(u) = soc_property_get(u, "l3_alpm_sw_prefix_lookup", 1); 8489 8490 rval = 0; 8491 if (SOC_URPF_STATUS_GET(u)) { 8492 soc_reg_field_set(u, L3_DEFIP_KEY_SELr, &rval, 8493 URPF_LOOKUP_CAM4f, 0x1); 8494 soc_reg_field_set(u, L3_DEFIP_KEY_SELr, &rval, 8495 URPF_LOOKUP_CAM5f, 0x1); 8496 soc_reg_field_set(u, L3_DEFIP_KEY_SELr, &rval, 8497 URPF_LOOKUP_CAM6f, 0x1); 8498 soc_reg_field_set(u, L3_DEFIP_KEY_SELr, &rval, 8499 URPF_LOOKUP_CAM7f, 0x1); 8500 } 8501 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_KEY_SELr(u, rval)); 8502 8503 rval = 0; 8504 if (mode == SOC_ALPM_MODE_PARALLEL) { 8505 if (SOC_URPF_STATUS_GET(u)) { 8506 /* 4 DIPs, 4 SIPs */ 8507 /* *DIP */ 8508 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM2_SELf, 1); 8509 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM3_SELf, 1); 8510 /* VRF SIP */ 8511 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM4_SELf, 2); 8512 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM5_SELf, 2); 8513 /* *SIP */ 8514 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM6_SELf, 3); 8515 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM7_SELf, 3); 8516 } else { 8517 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM4_SELf, 1); 8518 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM5_SELf, 1); 8519 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM6_SELf, 1); 8520 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM7_SELf, 1); 8521 } 8522 } else { 8523 if (SOC_URPF_STATUS_GET(u)) { 8524 /* 4 DIPs, 4 SIPs */ 8525 /* DIP */ 8526 /* VRF SIP */ 8527 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM4_SELf, 2); 8528 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM5_SELf, 2); 8529 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM6_SELf, 2); 8530 soc_reg_field_set(u, L3_DEFIP_ALPM_CFGr, &rval, TCAM7_SELf, 2); 8531 } 8532 } 8533 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_ALPM_CFGr(u, rval)); 8534 if (SOC_ALPM_128B_ENABLE(u)) { 8535 uint32 defip_key_sel_val = 0; 8536 8537 SOC_IF_ERROR_RETURN(READ_L3_DEFIP_KEY_SELr(u, &defip_key_sel_val)); 8538 /* Supports mixed IPv4, IPv6 128 bit prefix IPv6 routes. 8539 * upto 16K IPv4 pivots only or 8540 * upto 2K 128 bit IPv6 and upto 8k v4 pivots, or */ 8541 /* all tcams in paired mode */ 8542 soc_reg_field_set(u, L3_DEFIP_KEY_SELr, &defip_key_sel_val, 8543 V6_KEY_SEL_CAM0_1f, 0x1); 8544 soc_reg_field_set(u, L3_DEFIP_KEY_SELr, &defip_key_sel_val, 8545 V6_KEY_SEL_CAM2_3f, 0x1); 8546 soc_reg_field_set(u, L3_DEFIP_KEY_SELr, &defip_key_sel_val, 8547 V6_KEY_SEL_CAM4_5f, 0x1); 8548 soc_reg_field_set(u, L3_DEFIP_KEY_SELr, &defip_key_sel_val, 8549 V6_KEY_SEL_CAM6_7f, 0x1); 8550 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_KEY_SELr(u, defip_key_sel_val)); 8551 } 8552 } 8553 8554 max_pfx_len = ALPM_MAX_PFX_ENTRIES; 8555 8556 SOC_ALPM_LPM_LOCK(u); 8557 pfx_state_size = sizeof(soc_alpm_lpm_state_t) * (max_pfx_len); 8558 8559 soc_lpm_field_cache_state[u] = 8560 sal_alloc(sizeof(soc_lpm_field_cache_t), "lpm_field_state"); 8561 if (NULL == soc_lpm_field_cache_state[u]) { 8562 SOC_ALPM_LPM_UNLOCK(u); 8563 return (SOC_E_MEMORY); 8564 } 8565 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8566 CLASS_ID0f); 8567 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8568 CLASS_ID1f); 8569 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8570 DST_DISCARD0f); 8571 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8572 DST_DISCARD1f); 8573 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8574 ECMP0f); 8575 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8576 ECMP1f); 8577 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8578 ECMP_COUNT0f); 8579 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8580 ECMP_COUNT1f); 8581 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8582 ECMP_PTR0f); 8583 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8584 ECMP_PTR1f); 8585 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8586 GLOBAL_ROUTE0f); 8587 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8588 GLOBAL_ROUTE1f); 8589 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8590 MULTICAST_ROUTE0f); 8591 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8592 MULTICAST_ROUTE1f); 8593 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8594 RPA_ID0f); 8595 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8596 RPA_ID1f); 8597 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8598 EXPECTED_L3_IIF0f); 8599 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8600 EXPECTED_L3_IIF1f); 8601 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8602 IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f); 8603 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8604 IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f); 8605 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8606 IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f); 8607 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8608 IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f); 8609 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8610 L3MC_INDEX0f); 8611 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8612 L3MC_INDEX1f); 8613 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8614 HIT0f); 8615 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8616 HIT1f); 8617 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8618 IP_ADDR0f); 8619 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8620 IP_ADDR1f); 8621 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8622 IP_ADDR_MASK0f); 8623 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8624 IP_ADDR_MASK1f); 8625 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8626 MODE0f); 8627 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8628 MODE1f); 8629 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8630 MODE_MASK0f); 8631 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8632 MODE_MASK1f); 8633 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8634 NEXT_HOP_INDEX0f); 8635 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8636 NEXT_HOP_INDEX1f); 8637 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8638 PRI0f); 8639 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8640 PRI1f); 8641 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8642 RPE0f); 8643 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8644 RPE1f); 8645 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8646 VALID0f); 8647 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8648 VALID1f); 8649 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8650 VRF_ID_0f); 8651 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8652 VRF_ID_1f); 8653 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8654 VRF_ID_MASK0f); 8655 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8656 VRF_ID_MASK1f); 8657 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8658 GLOBAL_HIGH0f); 8659 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8660 GLOBAL_HIGH1f); 8661 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8662 ALG_HIT_IDX0f); 8663 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8664 ALG_HIT_IDX1f); 8665 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8666 ALG_BKT_PTR0f); 8667 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8668 ALG_BKT_PTR1f); 8669 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8670 DEFAULT_MISS0f); 8671 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8672 DEFAULT_MISS1f); 8673 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8674 FLEX_CTR_BASE_COUNTER_IDX0f); 8675 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8676 FLEX_CTR_BASE_COUNTER_IDX1f); 8677 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8678 FLEX_CTR_POOL_NUMBER0f); 8679 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8680 FLEX_CTR_POOL_NUMBER1f); 8681 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8682 FLEX_CTR_OFFSET_MODE0f); 8683 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8684 FLEX_CTR_OFFSET_MODE1f); 8685 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8686 SRC_DISCARD0f); 8687 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8688 SRC_DISCARD1f); 8689 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8690 ENTRY_TYPE_MASK0f); 8691 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8692 ENTRY_TYPE_MASK1f); 8693 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8694 ENTRY_TYPE0f); 8695 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8696 ENTRY_TYPE1f); 8697 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8698 ENTRY_VIEW0f); 8699 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 8700 ENTRY_VIEW1f); 8701 8702 SOC_ALPM_LPM_STATE(u) = sal_alloc(pfx_state_size, "LPM prefix info"); 8703 if (NULL == SOC_ALPM_LPM_STATE(u)) { 8704 sal_free(soc_lpm_field_cache_state[u]); 8705 soc_lpm_field_cache_state[u] = NULL; 8706 SOC_ALPM_LPM_UNLOCK(u); 8707 return (SOC_E_MEMORY); 8708 } 8709 8710 #ifdef FB_LPM_TABLE_CACHED 8711 rv = soc_mem_cache_set(u, L3_DEFIPm, MEM_BLOCK_ALL, TRUE); 8712 if (SOC_FAILURE(rv)) { 8713 SOC_ALPM_LPM_UNLOCK(u); 8714 return rv; 8715 } 8716 #endif /* FB_LPM_TABLE_CACHED */ 8717 8718 sal_memset(SOC_ALPM_LPM_STATE(u), 0, pfx_state_size); 8719 for(i = 0; i < max_pfx_len; i++) { 8720 SOC_ALPM_LPM_STATE_START(u, i) = -1; 8721 SOC_ALPM_LPM_STATE_END(u, i) = -1; 8722 SOC_ALPM_LPM_STATE_PREV(u, i) = -1; 8723 SOC_ALPM_LPM_STATE_NEXT(u, i) = -1; 8724 SOC_ALPM_LPM_STATE_VENT(u, i) = 0; 8725 SOC_ALPM_LPM_STATE_FENT(u, i) = 0; 8726 } 8727 8728 defip_table_size = soc_mem_index_count(u, L3_DEFIPm); 8729 8730 /* RPF supported, then the table is partitioned for DIP and SIP */ 8731 if (SOC_URPF_STATUS_GET(u)) { 8732 defip_table_size >>= 1; 8733 } 8734 8735 if (mode == SOC_ALPM_MODE_PARALLEL) { 8736 /* For Parallel search, the TCAM is hard paritioned. 8737 * First half are for VRF specific, the bottom half for override and 8738 * global. Start of Global entries start at the bottom half of TCAM 8739 */ 8740 SOC_ALPM_LPM_STATE_END(u, ALPM_MAX_PFX_INDEX) = (defip_table_size>>1) - 1; 8741 8742 /* Free entries for VRF */ 8743 SOC_ALPM_LPM_STATE_FENT(u, (ALPM_MAX_VRF_PFX_INDEX)) = defip_table_size >> 1; 8744 8745 /* Remaining entries are assigned to Global entries */ 8746 SOC_ALPM_LPM_STATE_FENT(u, (ALPM_MAX_PFX_INDEX)) = 8747 (defip_table_size - SOC_ALPM_LPM_STATE_FENT(u, (ALPM_MAX_VRF_PFX_INDEX))); 8748 } else { 8749 /* Remaining entries are assigned to Global entries */ 8750 SOC_ALPM_LPM_STATE_FENT(u, (ALPM_MAX_PFX_INDEX)) = defip_table_size; 8751 } 8752 8753 #ifdef FB_LPM_HASH_SUPPORT 8754 if (SOC_ALPM_LPM_STATE_HASH(u) != NULL) { 8755 if (_soc_alpm_lpm_hash_destroy(SOC_ALPM_LPM_STATE_HASH(u)) < 0) { 8756 SOC_ALPM_LPM_UNLOCK(u); 8757 return SOC_E_INTERNAL; 8758 } 8759 SOC_ALPM_LPM_STATE_HASH(u) = NULL; 8760 } 8761 8762 if (_soc_alpm_lpm_hash_create(u, defip_table_size * 2, defip_table_size, 8763 &SOC_ALPM_LPM_STATE_HASH(u)) < 0) { 8764 SOC_ALPM_LPM_UNLOCK(u); 8765 return SOC_E_MEMORY; 8766 } 8767 #endif 8768 8769 8770 SOC_ALPM_LPM_UNLOCK(u); 8771 return(SOC_E_NONE); 8772 } 8773 8774 /* 8775 * De-initialize the start/end tracking pointers for each prefix length 8776 */ 8777 static int 8778 soc_alpm_lpm_deinit(int u) 8779 { 8780 if (!soc_feature(u, soc_feature_lpm_tcam)) { 8781 return(SOC_E_UNAVAIL); 8782 } 8783 8784 SOC_ALPM_LPM_LOCK(u); 8785 8786 #ifdef FB_LPM_HASH_SUPPORT 8787 if (SOC_ALPM_LPM_STATE_HASH(u) != NULL) { 8788 _soc_alpm_lpm_hash_destroy(SOC_ALPM_LPM_STATE_HASH(u)); 8789 SOC_ALPM_LPM_STATE_HASH(u) = NULL; 8790 } 8791 #endif 8792 8793 if (SOC_ALPM_LPM_INIT_CHECK(u)) { 8794 sal_free(soc_lpm_field_cache_state[u]); 8795 soc_lpm_field_cache_state[u] = NULL; 8796 sal_free(SOC_ALPM_LPM_STATE(u)); 8797 SOC_ALPM_LPM_STATE(u) = NULL; 8798 } 8799 8800 SOC_ALPM_LPM_UNLOCK(u); 8801 8802 return(SOC_E_NONE); 8803 } 8804 8805 /* 8806 * Implementation using soc_mem_read/write using entry rippling technique 8807 * Advantage: A completely sorted table is not required. Lookups can be slow 8808 * as it will perform a linear search on the entries for a given prefix length. 8809 * No device access necessary for the search if the table is cached. Auxiliary 8810 * hash table can be maintained to speed up search(Not implemented) instead of 8811 * performing a linear search. 8812 * Small number of entries need to be moved around (97 worst case) 8813 * for performing insert/update/delete. However CPU needs to do all 8814 * the work to move the entries. 8815 */ 8816 8817 /* 8818 * soc_alpm_lpm_insert 8819 * For IPV4 assume only both IP_ADDR0 is valid 8820 * Moving multiple entries around in h/w vs doing a linear search in s/w 8821 * src_default: for sip entry if any 8822 * 0 - caculate using entry_data's mask (legacy way) 8823 * 1 - force set (split case) 8824 * src_discard: for sip entry if any 8825 */ 8826 static int 8827 soc_alpm_lpm_insert(int u, void *entry_data, int *lpm_index, 8828 int src_default, int src_discard, int bpm_len) 8829 { 8830 int pfx; 8831 int index; 8832 int ipv6, v4_half = 0; 8833 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 8834 int rv = SOC_E_NONE; 8835 int found = 0; 8836 int vrf, vrf_id; 8837 8838 sal_memcpy(e, soc_mem_entry_null(u, L3_DEFIPm), 8839 soc_mem_entry_words(u, L3_DEFIPm) * 4); 8840 8841 SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, entry_data, &vrf_id, &vrf)); 8842 8843 SOC_ALPM_LPM_LOCK(u); 8844 rv = _soc_alpm_lpm_match(u, entry_data, e, &index, &pfx, &ipv6); 8845 if (rv == SOC_E_NOT_FOUND) { 8846 rv = _lpm_free_slot_create(u, pfx, ipv6, e, &index); 8847 if (rv < 0) { 8848 SOC_ALPM_LPM_UNLOCK(u); 8849 return(rv); 8850 } 8851 } else { 8852 found = 1; 8853 } 8854 8855 *lpm_index = index; 8856 8857 if (rv == SOC_E_NONE) { 8858 if (!ipv6) { 8859 /* IPV4 entry */ 8860 if (index & 1) { 8861 rv = soc_alpm_lpm_ip4entry0_to_1(u, entry_data, e, 8862 PRESERVE_HIT); 8863 v4_half = 3; 8864 } else { 8865 rv = soc_alpm_lpm_ip4entry0_to_0(u, entry_data, e, 8866 PRESERVE_HIT); 8867 v4_half = 2; 8868 } 8869 8870 if (rv < 0) { 8871 SOC_ALPM_LPM_UNLOCK(u); 8872 return(rv); 8873 } 8874 entry_data = (void *)e; 8875 index >>= 1; 8876 } 8877 soc_alpm_lpm_state_dump(u); 8878 LOG_INFO(BSL_LS_SOC_ALPM, 8879 (BSL_META_U(u, 8880 "\nsoc_alpm_lpm_insert: %d %d\n"), 8881 index, pfx)); 8882 rv = _soc_alpm_write_pivot_with_bpm(u, index, index, entry_data, 8883 WRITE_PIVOT_WITH_URPF_PARAMS | 8884 (found ? WRITE_PIVOT_WITHOUT_INSERT_HASH : 0), 8885 src_default, src_discard, bpm_len, v4_half); 8886 if (!found && SOC_SUCCESS(rv)) { 8887 VRF_PIVOT_REF_INC(u, vrf_id, vrf, ipv6); 8888 } 8889 } 8890 8891 SOC_ALPM_LPM_UNLOCK(u); 8892 8893 return(rv); 8894 } 8895 8896 /* 8897 * soc_alpm_lpm_delete 8898 */ 8899 static int 8900 soc_alpm_lpm_delete(int u, void *key_data) 8901 { 8902 int pfx; 8903 int index; 8904 int ipv6; 8905 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 8906 int rv = SOC_E_NONE; 8907 int vrf, vrf_id; 8908 8909 SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf)); 8910 SOC_ALPM_LPM_LOCK(u); 8911 rv = _soc_alpm_lpm_match(u, key_data, e, &index, &pfx, &ipv6); 8912 if (rv == SOC_E_NONE) { 8913 LOG_INFO(BSL_LS_SOC_ALPM, 8914 (BSL_META_U(u, 8915 "\nsoc_alpm_lpm_delete: %d %d\n"), 8916 index, pfx)); 8917 LPM_HASH_DELETE(u, key_data, index); 8918 rv = _lpm_free_slot_delete(u, pfx, ipv6, e, index); 8919 } 8920 if (SOC_SUCCESS(rv)) { 8921 VRF_PIVOT_REF_DEC(u, vrf_id, vrf, ipv6); 8922 } 8923 soc_alpm_lpm_state_dump(u); 8924 SOC_ALPM_LPM_UNLOCK(u); 8925 return(rv); 8926 } 8927 8928 /* 8929 * soc_alpm_lpm_match (Exact match for the key. Will match both IP 8930 * address and mask) 8931 */ 8932 static int 8933 soc_alpm_lpm_match(int u, 8934 void *key_data, 8935 void *e, /* return entry data if found */ 8936 int *index_ptr) /* return key location */ 8937 { 8938 int pfx; 8939 int rv; 8940 int ipv6; 8941 8942 SOC_ALPM_LPM_LOCK(u); 8943 rv = _soc_alpm_lpm_match(u, key_data, e, index_ptr, &pfx, &ipv6); 8944 SOC_ALPM_LPM_UNLOCK(u); 8945 return(rv); 8946 } 8947 8948 8949 /* Fill Aux entry for operation */ 8950 static int 8951 _soc_alpm_fill_aux_entry_for_op(int unit, 8952 void *key_data, 8953 int ipv6, /* Entry is ipv6. */ 8954 int db_type, /* database type */ 8955 int ent_type, 8956 int replace_len, /* used for Delete propagate */ 8957 defip_aux_scratch_entry_t *aux_entry) 8958 { 8959 uint32 ipv4a; 8960 uint32 ip6_word[4] = {0, 0, 0, 0}; 8961 int pfx = 0; 8962 int rv = SOC_E_NONE; 8963 8964 sal_memset(aux_entry, 0, sizeof(defip_aux_scratch_entry_t)); 8965 8966 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, VALID0f); 8967 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, VALIDf, ipv4a); 8968 8969 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, MODE0f); 8970 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, MODEf, ipv4a); 8971 8972 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, ENTRY_TYPE0f); 8973 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, ENTRY_TYPEf, ent_type); 8974 8975 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, GLOBAL_ROUTE0f); 8976 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, GLOBAL_ROUTEf, ipv4a); 8977 8978 if (soc_feature(unit, soc_feature_ipmc_defip)) { 8979 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, RPA_ID0f); 8980 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, RPA_IDf, ipv4a); 8981 8982 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, EXPECTED_L3_IIF0f); 8983 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, EXPECTED_L3_IIFf, ipv4a); 8984 8985 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f); 8986 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf, ipv4a); 8987 8988 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f); 8989 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf, ipv4a); 8990 8991 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, L3MC_INDEX0f); 8992 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, L3MC_INDEXf, ipv4a); 8993 } 8994 8995 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, ECMP0f); 8996 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, ECMPf, ipv4a); 8997 8998 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, ECMP_PTR0f); 8999 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, ECMP_PTRf, ipv4a); 9000 9001 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, NEXT_HOP_INDEX0f); 9002 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, NEXT_HOP_INDEXf, ipv4a); 9003 9004 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, PRI0f); 9005 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, PRIf, ipv4a); 9006 9007 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, RPE0f); 9008 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, RPEf, ipv4a); 9009 9010 ipv4a =soc_mem_field32_get(unit, L3_DEFIPm, key_data, VRF_ID_0f); 9011 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, VRFf, ipv4a); 9012 9013 /* Set Database type */ 9014 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, DB_TYPEf, db_type); 9015 9016 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, DST_DISCARD0f); 9017 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, DST_DISCARDf, ipv4a); 9018 9019 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, DEFAULT_MISS0f); 9020 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, DEFAULT_MISSf, ipv4a); 9021 9022 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, CLASS_ID0f); 9023 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, CLASS_IDf, ipv4a); 9024 9025 9026 /* Set IP Address and IP length */ 9027 if (ipv6) { 9028 ip6_word[2] = soc_mem_field32_get(unit, L3_DEFIPm, key_data, IP_ADDR0f); 9029 ip6_word[3] = soc_mem_field32_get(unit, L3_DEFIPm, key_data, IP_ADDR1f); 9030 } else { 9031 ip6_word[0] = soc_mem_field32_get(unit, L3_DEFIPm, key_data, IP_ADDR0f); 9032 } 9033 soc_mem_field_set(unit, L3_DEFIP_AUX_SCRATCHm, (uint32*)aux_entry, 9034 IP_ADDRf, (uint32*)ip6_word); 9035 9036 if (ipv6) { 9037 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, IP_ADDR_MASK0f); 9038 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 9039 return(rv); 9040 } 9041 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, IP_ADDR_MASK1f); 9042 if (pfx) { 9043 if (ipv4a != 0xffffffff) { 9044 return(SOC_E_PARAM); 9045 } 9046 pfx += 32; 9047 } else { 9048 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 9049 return(rv); 9050 } 9051 } 9052 } else { 9053 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, key_data, IP_ADDR_MASK0f); 9054 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 9055 return(rv); 9056 } 9057 } 9058 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, IP_LENGTHf, pfx); 9059 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, REPLACE_LENf, 9060 replace_len); 9061 9062 ipv4a = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, key_data, FLEX_CTR_BASE_COUNTER_IDX0f); 9063 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, FLEX_CTR_BASE_COUNTER_IDXf, ipv4a); 9064 9065 ipv4a = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, key_data, FLEX_CTR_OFFSET_MODE0f); 9066 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, FLEX_CTR_OFFSET_MODEf, ipv4a); 9067 9068 ipv4a = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, key_data, FLEX_CTR_POOL_NUMBER0f); 9069 soc_mem_field32_set(unit, L3_DEFIP_AUX_SCRATCHm, aux_entry, FLEX_CTR_POOL_NUMBERf, ipv4a); 9070 9071 return (SOC_E_NONE); 9072 } 9073 9074 #define _SOC_ALPM_AUX_OP_RETRY_TO 1000000 9075 #define _SOC_ALPM_AUX_OP_RETRY_COUNT 100 9076 #define _TD2_PIPES_PER_DEV 2 9077 9078 /* Using binary search with DMA read to retrieve corrupted index */ 9079 int 9080 _soc_alpm_aux_error_index(int u, int pipe, int *index, soc_mem_t *mem) 9081 { 9082 char *dmabuf = NULL; 9083 soc_mem_t mem_to_search[2] = {L3_DEFIP_AUX_TABLEm, L3_DEFIP_DATA_ONLYm}; 9084 int min, max; 9085 uint32 ser_flags; 9086 int i = 0; 9087 int found_index = FALSE; 9088 int mem_wsz = 0; 9089 9090 switch (pipe) { 9091 case 0: 9092 ser_flags = _SOC_MEM_ADDR_ACC_TYPE_PIPE_X; 9093 break; 9094 case 1: 9095 ser_flags = _SOC_MEM_ADDR_ACC_TYPE_PIPE_Y; 9096 break; 9097 default: 9098 ser_flags = _SOC_MEM_ADDR_ACC_TYPE_PIPE_X; 9099 break; 9100 } 9101 9102 ser_flags |= _SOC_SER_FLAG_DMA_ERR_RETURN; 9103 ser_flags |= _SOC_SER_FLAG_DISCARD_READ; 9104 ser_flags |= _SOC_SER_FLAG_MULTI_PIPE; 9105 9106 for (i = 0; i < 2; i++) { 9107 min = soc_mem_index_min(u, mem_to_search[i]); 9108 if (mem_to_search[i] == L3_DEFIP_DATA_ONLYm) { 9109 max = soc_mem_index_max(u, L3_DEFIP_DATA_ONLYm) + 9110 soc_mem_index_max(u,L3_DEFIP_PAIR_128_DATA_ONLYm) * 2; 9111 } else { 9112 max = soc_mem_index_max(u, mem_to_search[i]); 9113 } 9114 9115 mem_wsz = sizeof(uint32) * soc_mem_entry_words(u, mem_to_search[i]); 9116 dmabuf = soc_cm_salloc(u, max * mem_wsz, "auxtbl_dmabuf"); 9117 if (dmabuf == NULL) { 9118 return SOC_E_MEMORY; 9119 } 9120 9121 while (min <= max) { 9122 int mid = min + (max - min) / 2; 9123 if (soc_mem_ser_read_range(u, mem_to_search[i], MEM_BLOCK_ALL, min, mid, ser_flags, 9124 dmabuf) < 0) { 9125 if (max == min) { 9126 *index = min; 9127 found_index = TRUE; 9128 break; 9129 } 9130 max = mid; 9131 } else { 9132 min = mid + 1; 9133 } 9134 } 9135 9136 soc_cm_sfree(u, dmabuf); 9137 9138 if (found_index) { 9139 *mem = mem_to_search[i]; 9140 break; 9141 } 9142 } 9143 9144 if (min > max) { 9145 /* Not found */ 9146 LOG_WARN(BSL_LS_SOC_ALPM, 9147 (BSL_META_U(u, "No corrupted index in L3_DEFIP_AUX_TABLE or" 9148 "L3_DEFIP_DATA_ONLY Pipe %d\n"), pipe)); 9149 return SOC_E_NOT_FOUND; 9150 } else { 9151 LOG_WARN(BSL_LS_SOC_ALPM, 9152 (BSL_META_U(u, "Found corrupted Index %d in %s Table Pipe %d\n"), 9153 *index, SOC_MEM_NAME(u, *mem), pipe)); 9154 return SOC_E_NONE; 9155 } 9156 } 9157 9158 /* Perform an ALPM hardware operation */ 9159 int 9160 _soc_alpm_aux_hw_op(int u, _soc_aux_op_t aux_op, 9161 defip_aux_scratch_entry_t *aux_entry, int update_scratch, 9162 int *hit, int *tcam_index, int *bucket_index) 9163 { 9164 soc_timeout_t to; 9165 int pipe, rv = SOC_E_NONE; 9166 int _soc_alpm_aux_op_retry = 0; 9167 9168 uint32 rval[_TD2_PIPES_PER_DEV]; 9169 int value[_TD2_PIPES_PER_DEV]; 9170 int err[_TD2_PIPES_PER_DEV]; 9171 9172 uint32 baddr; 9173 int block; 9174 uint8 acc_type; 9175 soc_mem_t mem = INVALIDm; 9176 9177 /* Write to Aux Scratch before performing the operation */ 9178 if (update_scratch) { 9179 SOC_IF_ERROR_RETURN( 9180 WRITE_L3_DEFIP_AUX_SCRATCHm(u, MEM_BLOCK_ANY, 0, aux_entry)); 9181 } 9182 9183 #ifdef AUX_OPTIMIZATIONS_OFF 9184 SOC_IF_ERROR_RETURN(READ_L3_DEFIP_AUX_CTRLr(u, &rval[0])); 9185 if (soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr, rval[0], STARTf)) { 9186 /* Aux op in porgress */ 9187 return SOC_E_BUSY; 9188 } 9189 #endif /* OPTIMIZATIONS_OFF */ 9190 9191 _retry: 9192 switch (aux_op) { 9193 case INSERT_PROPAGATE: 9194 value[0] = 0; 9195 break; 9196 case DELETE_PROPAGATE: 9197 value[0] = 1; 9198 break; 9199 case PREFIX_LOOKUP: 9200 value[0] = 2; 9201 break; 9202 case HITBIT_REPLACE: 9203 value[0] = 3; 9204 break; 9205 default: 9206 return SOC_E_PARAM; 9207 } 9208 9209 rval[0] = 0; 9210 9211 /* set opcode */ 9212 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[0], OPCODEf, value[0]); 9213 9214 /* Start opertation */ 9215 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[0], STARTf, 1); 9216 9217 /* Write to Aux ctrl reg */ 9218 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_AUX_CTRLr(u, rval[0])); 9219 soc_timeout_init(&to, 50000, 5); 9220 9221 /* Check for Operation complete */ 9222 sal_memset(value, 0, sizeof(value)); 9223 sal_memset(err, 0, sizeof(err)); 9224 baddr = soc_reg_addr_get(u, L3_DEFIP_AUX_CTRLr, REG_PORT_ANY, 0, 9225 SOC_REG_ADDR_OPTION_NONE, 9226 &block, &acc_type); 9227 do { 9228 for (pipe = 0; pipe < _TD2_PIPES_PER_DEV; pipe++) { 9229 SOC_IF_ERROR_RETURN 9230 (_soc_reg32_get(u, block, pipe + 1, baddr, &rval[pipe])); 9231 value[pipe] = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr, 9232 rval[pipe], DONEf); 9233 err[pipe] = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr, 9234 rval[pipe], ERRORf); 9235 if (value[pipe] != 1) { 9236 break; 9237 } 9238 } 9239 9240 /* All DONE */ 9241 if (pipe >= _TD2_PIPES_PER_DEV) { 9242 rv = SOC_E_NONE; 9243 break; 9244 } 9245 9246 if (soc_timeout_check(&to)) { 9247 sal_memset(value, 0, sizeof(value)); 9248 sal_memset(err, 0, sizeof(err)); 9249 for (pipe = 0; pipe < _TD2_PIPES_PER_DEV; pipe++) { 9250 SOC_IF_ERROR_RETURN 9251 (_soc_reg32_get(u, block, pipe + 1, baddr, &rval[pipe])); 9252 value[pipe] = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr, 9253 rval[pipe], DONEf); 9254 err[pipe] = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr, 9255 rval[pipe], ERRORf); 9256 if (value[pipe] != 1) { 9257 break; 9258 } 9259 } 9260 9261 if (pipe >= _TD2_PIPES_PER_DEV) { 9262 rv = SOC_E_NONE; 9263 } else { 9264 LOG_WARN(BSL_LS_SOC_ALPM, 9265 (BSL_META_U(u, "unit %d : DEFIP AUX Operation " 9266 "timeout, Pipe %d\n"), u, pipe)); 9267 rv = SOC_E_TIMEOUT; 9268 } 9269 break; 9270 } 9271 } while (1); 9272 9273 if (SOC_SUCCESS(rv)) { 9274 for (pipe = 0; pipe < _TD2_PIPES_PER_DEV; pipe++) { 9275 if (err[pipe]) { 9276 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[pipe], STARTf, 0); 9277 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[pipe], ERRORf, 0); 9278 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[pipe], DONEf, 0); 9279 9280 SOC_IF_ERROR_RETURN 9281 (_soc_reg32_set(u, block, pipe + 1, baddr, rval[pipe])); 9282 LOG_WARN(BSL_LS_SOC_ALPM, 9283 (BSL_META_U(u, "DEFIP AUX Operation encountered " 9284 "parity error in Pipe %d!!\n"), pipe)); 9285 _soc_alpm_aux_op_retry++; 9286 if (SOC_CONTROL(u)->alpm_bulk_retry) { 9287 sal_sem_take(SOC_CONTROL(u)->alpm_bulk_retry, _SOC_ALPM_AUX_OP_RETRY_TO); 9288 } 9289 if (_soc_alpm_aux_op_retry < _SOC_ALPM_AUX_OP_RETRY_COUNT) { 9290 int err_index; 9291 if (_soc_alpm_aux_error_index(u, pipe, &err_index, &mem) >= 0) { 9292 /* Call inline correction with err_index and pipe */ 9293 rv = soc_mem_alpm_aux_table_correction(u, pipe, err_index, mem); 9294 if (rv < 0) { 9295 LOG_ERROR(BSL_LS_SOC_ALPM, 9296 (BSL_META_U(u, "_soc_th_alpm_aux_error_index " 9297 "pipe %d index %d failed\n"), pipe, err_index)); 9298 } 9299 } 9300 LOG_WARN(BSL_LS_SOC_ALPM, 9301 (BSL_META_U(u, "Retry DEFIP AUX Operation in " 9302 "Pipe %d.\n"), pipe)); 9303 goto _retry; 9304 } else { 9305 LOG_ERROR(BSL_LS_SOC_ALPM, 9306 (BSL_META_U(u, "unit %d: Aborting DEFIP AUX Operation " 9307 "due to un-correctable error !!\n"), u)); 9308 return SOC_E_INTERNAL; 9309 } 9310 } 9311 } 9312 9313 if (aux_op == PREFIX_LOOKUP) { 9314 if (hit && tcam_index) { 9315 /* Get the hit bit and Bucket index for lookup operations */ 9316 *hit = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr, rval[0], HITf); 9317 *tcam_index = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr, 9318 rval[0], BKT_INDEXf); 9319 SOC_IF_ERROR_RETURN(READ_L3_DEFIP_AUX_CTRL_1r(u, &rval[1])); 9320 *bucket_index = soc_reg_field_get(u, L3_DEFIP_AUX_CTRL_1r, 9321 rval[1], BKT_PTRf); 9322 } 9323 } 9324 } 9325 #ifdef AUX_OPTIMIZATIONS_OFF 9326 /* clear AUX ctrl register */ 9327 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[0], STARTf, 0); 9328 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[0], DONEf, 0); 9329 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_AUX_CTRLr(u, rval[0])); 9330 #endif /* OPTIMIZATIONS_OFF */ 9331 return rv; 9332 } 9333 9334 int 9335 _soc_alpm_aux_op(int u, _soc_aux_op_t aux_op, 9336 defip_aux_scratch_entry_t *aux_entry, int update_scratch, 9337 int *hit, int *tcam_index, int *log_bkt, int aux_flags) 9338 { 9339 int rv = SOC_E_NONE; 9340 int cb_cnt = 1; 9341 9342 /* 9343 * SW propagation: 9344 * Callback only being proceeded when cache of LPM TCAM tables is 9345 * turn on. 9346 */ 9347 if (ALPM_CTRL(u).trie_propagate) { 9348 rv = _soc_alpm_aux_sw_op(u, aux_op, aux_entry, 9349 &cb_cnt, aux_flags); 9350 } 9351 9352 /* Hareware assists only needed when matched pivot is hit. */ 9353 if (SOC_SUCCESS(rv) && cb_cnt > 0) { 9354 uint32 val; 9355 9356 if (SOC_IS_TRIDENT2(u) && (aux_op == INSERT_PROPAGATE)) { 9357 /* 9358 * Do DELETE propagation to update existing default datas 9359 * Since INSERT Propagate doesn't handle '==' case 9360 */ 9361 rv = _soc_alpm_aux_hw_op(u, DELETE_PROPAGATE, aux_entry, 9362 update_scratch, hit, tcam_index, log_bkt); 9363 if (SOC_SUCCESS(rv)) { 9364 rv = _soc_alpm_aux_hw_op(u, aux_op, aux_entry, FALSE, 9365 hit, tcam_index, log_bkt); 9366 } 9367 } else { 9368 rv = _soc_alpm_aux_hw_op(u, aux_op, aux_entry, update_scratch, 9369 hit, tcam_index, log_bkt); 9370 } 9371 9372 if ((aux_op == INSERT_PROPAGATE || aux_op == DELETE_PROPAGATE) && 9373 SOC_SUCCESS(rv) && SOC_URPF_STATUS_GET(u)) { 9374 soc_mem_t mem = L3_DEFIP_AUX_SCRATCHm; 9375 val = soc_mem_field32_get(u, mem, aux_entry, DB_TYPEf); 9376 soc_mem_field32_set(u, mem, aux_entry, DB_TYPEf, val + 1); 9377 9378 val = (aux_flags & SOC_ALPM_AUX_DEF_ROUTE) ? 1 : 0; 9379 soc_mem_field32_set(u, mem, aux_entry, DEFAULTROUTEf, val); 9380 9381 val = (aux_flags & SOC_ALPM_AUX_SRC_DISCARD) ? 1 : 0; 9382 soc_mem_field32_set(u, mem, aux_entry, SRC_DISCARDf, val); 9383 9384 if (SOC_IS_TRIDENT2(u) && (aux_op == INSERT_PROPAGATE)) { 9385 /* 9386 * Do DELETE propagation to update existing default datas 9387 * Since INSERT Propagate doesn't handle '==' case. 9388 */ 9389 rv = _soc_alpm_aux_hw_op(u, DELETE_PROPAGATE, aux_entry, 9390 TRUE, NULL, NULL, NULL); 9391 if (SOC_SUCCESS(rv)) { 9392 rv = _soc_alpm_aux_hw_op(u, aux_op, aux_entry, FALSE, 9393 NULL, NULL, NULL); 9394 } 9395 } else { 9396 rv = _soc_alpm_aux_hw_op(u, aux_op, aux_entry, TRUE, 9397 NULL, NULL, NULL); 9398 } 9399 } 9400 } 9401 9402 return rv; 9403 } 9404 9405 /* Perform an ALPM mem read operation */ 9406 int 9407 _soc_mem_alpm_read(int unit, soc_mem_t mem, int copyno, 9408 int index, void *entry_data) 9409 { 9410 int rv = SOC_E_NONE; 9411 int read_no_cache = FALSE; 9412 9413 switch (mem) { 9414 case L3_DEFIPm: 9415 case L3_DEFIP_PAIR_128m: 9416 case L3_DEFIP_ALPM_RAWm: 9417 case L3_DEFIP_ALPM_IPV4m: 9418 case L3_DEFIP_ALPM_IPV4_1m: 9419 case L3_DEFIP_ALPM_IPV6_64m: 9420 case L3_DEFIP_ALPM_IPV6_64_1m: 9421 case L3_DEFIP_ALPM_IPV6_128m: 9422 if (!ALPM_CTRL(unit).hit_bits_skip) { 9423 /* Be sure to get hit information */ 9424 read_no_cache = TRUE; 9425 } 9426 break; 9427 default: 9428 break; 9429 } 9430 9431 if (read_no_cache) { 9432 rv = soc_mem_read_no_cache(unit, 0, mem, 0, copyno, index, entry_data); 9433 } else { 9434 rv = soc_mem_read(unit, mem, copyno, index, entry_data); 9435 } 9436 9437 return rv; 9438 } 9439 9440 /* Initialize the ALPM memory from a TCAM entry */ 9441 static int 9442 _soc_alpm_mem_ent_init(int unit, void *lpm_entry, 9443 void *alpm_entry, void *alpm_sip_entry, soc_mem_t mem, 9444 uint32 flags, uint32 *is_default) 9445 { 9446 uint32 ipv4a; 9447 uint32 ip6_word[4] = {0, 0}; 9448 int pfx = 0; 9449 int rv = SOC_E_NONE; 9450 int ipv6; 9451 uint32 default_route = 0; 9452 9453 ipv6 = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, MODE0f); 9454 9455 /* Zero Buffer */ 9456 sal_memset(alpm_entry, 0, soc_mem_entry_words(unit, mem) * 4); 9457 9458 if (!soc_feature(unit, soc_feature_alpm_hit_bits_not_support)) { 9459 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, HIT0f); 9460 soc_mem_field32_set(unit, mem, alpm_entry, HITf, ipv4a); 9461 } 9462 9463 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, VALID0f); 9464 soc_mem_field32_set(unit, mem, alpm_entry, VALIDf, ipv4a); 9465 9466 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, ECMP0f); 9467 soc_mem_field32_set(unit, mem, alpm_entry, ECMPf, ipv4a); 9468 9469 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, ECMP_PTR0f); 9470 soc_mem_field32_set(unit, mem, alpm_entry, ECMP_PTRf, ipv4a); 9471 9472 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, NEXT_HOP_INDEX0f); 9473 soc_mem_field32_set(unit, mem, alpm_entry, NEXT_HOP_INDEXf, ipv4a); 9474 9475 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, PRI0f); 9476 soc_mem_field32_set(unit, mem, alpm_entry, PRIf, ipv4a); 9477 9478 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, RPE0f); 9479 soc_mem_field32_set(unit, mem, alpm_entry, RPEf, ipv4a); 9480 9481 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, DST_DISCARD0f); 9482 soc_mem_field32_set(unit, mem, alpm_entry, DST_DISCARDf, ipv4a); 9483 9484 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, SRC_DISCARD0f); 9485 soc_mem_field32_set(unit, mem, alpm_entry, SRC_DISCARDf, ipv4a); 9486 9487 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, CLASS_ID0f); 9488 soc_mem_field32_set(unit, mem, alpm_entry, CLASS_IDf, ipv4a); 9489 9490 /* Set IP Address and IP length */ 9491 ip6_word[0] = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, IP_ADDR0f); 9492 if (ipv6) { 9493 ip6_word[1] = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, IP_ADDR1f); 9494 } 9495 soc_mem_field_set(unit, mem, (uint32*)alpm_entry, KEYf, (uint32*)ip6_word); 9496 9497 if (ipv6) { 9498 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f); 9499 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 9500 return(rv); 9501 } 9502 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f); 9503 if (pfx) { 9504 if (ipv4a != 0xffffffff) { 9505 return(SOC_E_PARAM); 9506 } 9507 pfx += 32; 9508 } else { 9509 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 9510 return(rv); 9511 } 9512 } 9513 } else { 9514 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f); 9515 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 9516 return(rv); 9517 } 9518 } 9519 if ((pfx == 0) && (ip6_word[0] == 0) && (ip6_word[1] == 0)) { 9520 default_route = 1; 9521 } 9522 if (is_default != NULL) { 9523 *is_default = default_route; 9524 } 9525 soc_mem_field32_set(unit, mem, alpm_entry, LENGTHf, pfx); 9526 9527 if (mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64_1m) { 9528 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, FLEX_CTR_BASE_COUNTER_IDX0f); 9529 soc_mem_field32_set(unit, mem, alpm_entry, FLEX_CTR_BASE_COUNTER_IDXf, ipv4a); 9530 9531 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, FLEX_CTR_OFFSET_MODE0f); 9532 soc_mem_field32_set(unit, mem, alpm_entry, FLEX_CTR_OFFSET_MODEf, ipv4a); 9533 9534 ipv4a = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, FLEX_CTR_POOL_NUMBER0f); 9535 soc_mem_field32_set(unit, mem, alpm_entry, FLEX_CTR_POOL_NUMBERf, ipv4a); 9536 } 9537 9538 if (alpm_sip_entry == NULL) { 9539 return (SOC_E_NONE); 9540 } 9541 if (SOC_URPF_STATUS_GET(unit)) { 9542 sal_memset(alpm_sip_entry, 0, soc_mem_entry_words(unit, mem) * 4); 9543 sal_memcpy(alpm_sip_entry, alpm_entry, soc_mem_entry_words(unit, mem) * 4); 9544 soc_mem_field32_set(unit, mem, alpm_sip_entry, DST_DISCARDf, 0); 9545 soc_mem_field32_set(unit, mem, alpm_sip_entry, RPEf, 0); 9546 9547 soc_mem_field32_set(unit, mem, alpm_sip_entry, SRC_DISCARDf, 9548 flags & SOC_ALPM_RPF_SRC_DISCARD); 9549 soc_mem_field32_set(unit, mem, alpm_sip_entry, DEFAULTROUTEf, 9550 default_route); 9551 } 9552 9553 return (SOC_E_NONE); 9554 } 9555 9556 /* Initialize the TCAM entry from ALPM memory */ 9557 static int 9558 _soc_alpm_lpm_ent_init(int unit, void *alpm_entry, soc_mem_t mem, int ipv6, 9559 int vrf_id, int bucket, int index, void *lpm_entry, 9560 int flex) 9561 { 9562 uint32 ipv4a; 9563 uint32 ip6_word[4] = {0, 0}; 9564 uint32 pfx = 0; 9565 9566 /* Zero Buffer */ 9567 sal_memset(lpm_entry, 0, soc_mem_entry_words(unit, L3_DEFIPm) * 4); 9568 9569 if (!soc_feature(unit, soc_feature_alpm_hit_bits_not_support)) { 9570 ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, HITf); 9571 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, HIT0f, ipv4a); 9572 if (ipv6) { 9573 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, HIT1f, ipv4a); 9574 } 9575 } 9576 9577 ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, VALIDf); 9578 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, VALID0f, ipv4a); 9579 if (ipv6) { 9580 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, VALID1f, ipv4a); 9581 } 9582 9583 ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, ECMPf); 9584 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, ECMP0f, ipv4a); 9585 9586 ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, ECMP_PTRf); 9587 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, ECMP_PTR0f, ipv4a); 9588 9589 ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, NEXT_HOP_INDEXf); 9590 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, NEXT_HOP_INDEX0f, ipv4a); 9591 9592 ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, PRIf); 9593 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, PRI0f, ipv4a); 9594 9595 ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, RPEf); 9596 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, RPE0f, ipv4a); 9597 9598 ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, DST_DISCARDf); 9599 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, DST_DISCARD0f, ipv4a); 9600 9601 ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, SRC_DISCARDf); 9602 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, SRC_DISCARD0f, ipv4a); 9603 9604 ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, CLASS_IDf); 9605 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, CLASS_ID0f, ipv4a); 9606 9607 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, ALG_BKT_PTR0f, bucket); 9608 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, ALG_HIT_IDX0f, index); 9609 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, MODE_MASK0f, 3); 9610 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, ENTRY_TYPE_MASK0f, 1); 9611 9612 if (ipv6) { 9613 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, MODE0f, 1); 9614 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, MODE1f, 1); 9615 } 9616 9617 /* Set IP Address and IP length */ 9618 soc_mem_field_get(unit, mem, alpm_entry, KEYf, ip6_word); 9619 if (ipv6) { 9620 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, IP_ADDR1f, 9621 ip6_word[1]); 9622 } 9623 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, IP_ADDR0f, ip6_word[0]); 9624 9625 ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, LENGTHf); 9626 if (ipv6) { 9627 if (ipv4a >= 32) { 9628 pfx = 0xffffffff; 9629 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, pfx); 9630 pfx = ~SHR_SHIFT_RIGHT(0xffffffff, ipv4a - 32); 9631 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, pfx); 9632 } else { 9633 pfx = ~(0xffffffff >> ipv4a); 9634 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, pfx); 9635 } 9636 } else { 9637 assert(ipv4a <= 32); 9638 pfx = ~SHR_SHIFT_RIGHT(0xffffffff, ipv4a); 9639 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, pfx); 9640 } 9641 9642 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, ENTRY_VIEW0f, flex); 9643 9644 if (vrf_id == SOC_L3_VRF_OVERRIDE) { 9645 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, GLOBAL_HIGH0f, 1); 9646 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f, 1); 9647 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, VRF_ID_0f, 0); 9648 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f, 0); 9649 } else if (vrf_id == SOC_L3_VRF_GLOBAL) { 9650 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f, 1); 9651 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, VRF_ID_0f, 0); 9652 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f, 0); 9653 } else { 9654 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, VRF_ID_0f, vrf_id); 9655 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f, 9656 SOC_VRF_MAX(unit)); 9657 } 9658 9659 if (mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64_1m) { 9660 ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, FLEX_CTR_BASE_COUNTER_IDXf); 9661 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, FLEX_CTR_BASE_COUNTER_IDX0f, ipv4a); 9662 9663 ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, FLEX_CTR_OFFSET_MODEf); 9664 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, FLEX_CTR_OFFSET_MODE0f, ipv4a); 9665 9666 ipv4a = soc_mem_field32_get(unit, mem, alpm_entry, FLEX_CTR_POOL_NUMBERf); 9667 soc_mem_field32_set(unit, L3_DEFIPm, lpm_entry, FLEX_CTR_POOL_NUMBER0f, ipv4a); 9668 } 9669 9670 return (SOC_E_NONE); 9671 } 9672 9673 int 9674 soc_alpm_warmboot_pivot_add(int unit, 9675 int ipv6, 9676 void *lpm_entry, 9677 int tcam_idx, 9678 int bckt_idx) 9679 { 9680 int rv = SOC_E_NONE; 9681 uint32 key[2] = {0, 0}; 9682 alpm_pivot_t *pivot = NULL; 9683 alpm_bucket_handle_t *bucket_handle = NULL; 9684 int vrf_id = 0, vrf = 0; 9685 uint32 length2; 9686 trie_t *pivot_root = NULL; 9687 uint32 prefix[5] = {0}; 9688 uint32 bpm_len = 0; 9689 int default_route = 0; 9690 defip_aux_table_entry_t aux_ent; 9691 9692 rv = _alpm_prefix_create(unit, lpm_entry, prefix, &length2, &default_route); 9693 SOC_IF_ERROR_RETURN(rv); 9694 9695 SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf)); 9696 tcam_idx = soc_alpm_physical_idx(unit, L3_DEFIPm, tcam_idx, ipv6); 9697 9698 /* Allocate bucket handle */ 9699 bucket_handle = sal_alloc(sizeof(alpm_bucket_handle_t), "ALPM Bucket Handle"); 9700 if (bucket_handle == NULL) { 9701 LOG_ERROR(BSL_LS_SOC_ALPM, 9702 (BSL_META_U(unit, 9703 "Unable to allocate memory for " 9704 "PIVOT trie node \n"))); 9705 return SOC_E_NONE; 9706 } 9707 sal_memset(bucket_handle, 0, sizeof(*bucket_handle)); 9708 9709 /* Allocate pivot Payload */ 9710 pivot = sal_alloc(sizeof(alpm_pivot_t), "Payload for Pivot"); 9711 if (pivot == NULL) { 9712 LOG_ERROR(BSL_LS_SOC_ALPM, 9713 (BSL_META_U(unit, 9714 "Unable to allocate memory for " 9715 "PIVOT trie node \n"))); 9716 sal_free(bucket_handle); 9717 return SOC_E_MEMORY; 9718 } 9719 sal_memset(pivot, 0, sizeof(*pivot)); 9720 9721 /* Save bucket_handle in pivot->bucket_trie */ 9722 PIVOT_BUCKET_HANDLE(pivot) = bucket_handle; 9723 9724 if (ipv6) { 9725 trie_init(_MAX_KEY_LEN_144_, &PIVOT_BUCKET_TRIE(pivot)); 9726 9727 /* Set address to the buffer. */ 9728 key[0] = soc_L3_DEFIPm_field32_get(unit, lpm_entry, IP_ADDR0f); 9729 9730 /* Set address to the buffer. */ 9731 key[1] = soc_L3_DEFIPm_field32_get(unit, lpm_entry, IP_ADDR1f); 9732 } else { 9733 trie_init(_MAX_KEY_LEN_48_, &PIVOT_BUCKET_TRIE(pivot)); 9734 9735 /* Set address to the buffer. */ 9736 key[0] = soc_L3_DEFIPm_field32_get(unit, lpm_entry, IP_ADDR0f); 9737 } 9738 9739 /* Save bucket index into pivot->bucket->bucket_index */ 9740 PIVOT_BUCKET_INDEX(pivot) = bckt_idx; 9741 9742 /* Save tcam index into pivot->tcam_index */ 9743 PIVOT_TCAM_INDEX(pivot) = tcam_idx; 9744 9745 if (vrf_id != SOC_L3_VRF_OVERRIDE) { 9746 if (ipv6 == 0) { 9747 pivot_root = VRF_PIVOT_TRIE_IPV4(unit, vrf); 9748 if (pivot_root == NULL) { 9749 trie_init(_MAX_KEY_LEN_48_, &VRF_PIVOT_TRIE_IPV4(unit, vrf)); 9750 pivot_root = VRF_PIVOT_TRIE_IPV4(unit, vrf); 9751 } 9752 } else { 9753 pivot_root = VRF_PIVOT_TRIE_IPV6(unit, vrf); 9754 if (pivot_root == NULL) { 9755 trie_init(_MAX_KEY_LEN_144_, &VRF_PIVOT_TRIE_IPV6(unit, vrf)); 9756 pivot_root = VRF_PIVOT_TRIE_IPV6(unit, vrf); 9757 } 9758 } 9759 9760 sal_memcpy(pivot->key, prefix, sizeof(prefix)); 9761 pivot->len = length2; 9762 9763 /* insert into pivot trie */ 9764 rv = soc_mem_read(unit, L3_DEFIP_AUX_TABLEm, SOC_BLOCK_ANY, 9765 tcam_idx >> 1, &aux_ent); 9766 if (SOC_SUCCESS(rv)) { 9767 bpm_len = soc_mem_field32_get(unit, L3_DEFIP_AUX_TABLEm, &aux_ent, 9768 ipv6 ? BPM_LENGTH0f : 9769 (tcam_idx & 1) ? BPM_LENGTH1f : BPM_LENGTH0f); 9770 } 9771 9772 rv = trie_insert(pivot_root, pivot->key, NULL, pivot->len, 9773 (trie_node_t *)pivot); 9774 if (SOC_FAILURE(rv)) { 9775 sal_free(bucket_handle); 9776 sal_free(pivot); 9777 return rv; 9778 } 9779 } 9780 9781 PIVOT_TCAM_BPMLEN(pivot) = bpm_len; 9782 /* Insert pivot into global pivot array indexed by tcam_idx */ 9783 ALPM_TCAM_PIVOT(unit, tcam_idx) = pivot; 9784 PIVOT_BUCKET_VRF(pivot) = vrf; 9785 PIVOT_BUCKET_IPV6(pivot) = ipv6; 9786 9787 PIVOT_BUCKET_ENT_CNT_UPDATE(pivot); 9788 if (key[0] == 0 && key[1] == 0) { 9789 PIVOT_BUCKET_DEF(pivot) = TRUE; 9790 } 9791 9792 return rv; 9793 } 9794 9795 9796 static int 9797 _soc_alpm_warmboot_insert(int unit, 9798 int ipv6, 9799 int flex, 9800 void *lpm_entry, 9801 void *alpm_entry, /* ALPM (SRAM) entry data */ 9802 int tcam_idx, /* TCAM index */ 9803 int bckt_idx, /* Bucket index */ 9804 int alpm_idx ) /* ALPM entry index */ 9805 { 9806 int vrf_id; /* Internal API representation of VRF id */ 9807 int vrf; /* VRF in 0 to (MAX_VRF + 1) range; */ 9808 /* VRF = (MAX_VRF + 1), software rep of GLOBAL VRF */ 9809 int rv = SOC_E_NONE; 9810 int default_route = 0; 9811 uint32 prefix[5] = {0, 0, 0, 0, 0}; 9812 uint32 length; 9813 defip_entry_t temp_lpm_entry; 9814 trie_t *bkt_trie = NULL; 9815 trie_t *pfx_trie = NULL; 9816 trie_node_t *delp = NULL; 9817 payload_t *bkt_payload = NULL; 9818 payload_t *pfx_payload = NULL; 9819 alpm_pivot_t *pivot_pyld = NULL; 9820 soc_mem_t mem; 9821 defip_entry_t *def_entry = NULL; 9822 9823 /* Check function params */ 9824 if ((NULL == lpm_entry) || (NULL == alpm_entry)) { 9825 return SOC_E_PARAM; 9826 } 9827 9828 /* Check IPv6 */ 9829 if (ipv6) { 9830 if (!(ipv6 = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, MODE1f))) { 9831 return (SOC_E_PARAM); 9832 } 9833 } 9834 9835 /* Get VRF */ 9836 SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf)); 9837 9838 /* Get ALPM table memory. */ 9839 SOC_ALPM_TABLE_MEM(unit, ipv6, mem, flex); 9840 9841 /* Convert alpm_entry into lpm_entry to extract prefix */ 9842 SOC_IF_ERROR_RETURN(_soc_alpm_lpm_ent_init(unit, alpm_entry, mem, ipv6, 9843 vrf_id, bckt_idx, tcam_idx, 9844 &temp_lpm_entry, 0)); 9845 9846 /* Create Prefix */ 9847 rv = _alpm_prefix_create(unit, &temp_lpm_entry, prefix, &length, &default_route); 9848 if (SOC_FAILURE(rv)) { 9849 LOG_ERROR(BSL_LS_SOC_ALPM, 9850 (BSL_META_U(unit, 9851 "prefix create failed\n"))); 9852 return rv; 9853 } 9854 9855 /* Get TCAM pivot */ 9856 pivot_pyld = ALPM_TCAM_PIVOT(unit, tcam_idx); 9857 9858 /* Get bucket trie from pivot */ 9859 bkt_trie = PIVOT_BUCKET_TRIE(pivot_pyld); 9860 9861 /* Allocate bucket payload */ 9862 bkt_payload = sal_alloc(sizeof(payload_t), "Payload for Key"); 9863 if (NULL == bkt_payload) { 9864 LOG_ERROR(BSL_LS_SOC_ALPM, 9865 (BSL_META_U(unit, 9866 "Unable to allocate memory for trie node.\n"))); 9867 return SOC_E_MEMORY; 9868 } 9869 9870 /* Allocate prefix trie payload */ 9871 pfx_payload = sal_alloc(sizeof(payload_t), "Payload for pfx trie key"); 9872 if (NULL == pfx_payload) { 9873 LOG_ERROR(BSL_LS_SOC_ALPM, 9874 (BSL_META_U(unit, 9875 "Unable to allocate memory for pfx trie node\n"))); 9876 sal_free(bkt_payload); 9877 return SOC_E_MEMORY; 9878 } 9879 9880 /* Clear allocated payloads */ 9881 sal_memset(bkt_payload, 0, sizeof(*bkt_payload)); 9882 sal_memset(pfx_payload, 0, sizeof(*pfx_payload)); 9883 9884 bkt_payload->key[0] = prefix[0]; 9885 bkt_payload->key[1] = prefix[1]; 9886 bkt_payload->key[2] = prefix[2]; 9887 bkt_payload->key[3] = prefix[3]; 9888 bkt_payload->key[4] = prefix[4]; 9889 bkt_payload->len = length; 9890 bkt_payload->index = alpm_idx; 9891 9892 #ifdef ALPM_WARM_BOOT_DEBUG_EXTENSIVE 9893 LOG_ERROR(BSL_LS_SOC_ALPM, 9894 (BSL_META_U(unit, 9895 "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, length = 0x%x alpm_idx = 0x%x\n"), 9896 bkt_payload->key[0], bkt_payload->key[1], bkt_payload->key[2], 9897 bkt_payload->key[3], bkt_payload->key[4], 9898 length, alpm_idx)); 9899 #endif 9900 9901 /* Create duplicate for prefix trie */ 9902 sal_memcpy(pfx_payload, bkt_payload, sizeof(*bkt_payload)); 9903 pfx_payload->bkt_ptr = bkt_payload; 9904 9905 /* Insert prefix into bucket-trie */ 9906 rv = trie_insert(bkt_trie, prefix, NULL, length, 9907 (trie_node_t *)bkt_payload); 9908 if (SOC_FAILURE(rv)) { 9909 goto free_memory; 9910 } 9911 9912 /* Insert prefix into prefix-trie */ 9913 if (ipv6) { 9914 pfx_trie = VRF_PREFIX_TRIE_IPV6(unit, vrf); 9915 } else { 9916 pfx_trie = VRF_PREFIX_TRIE_IPV4(unit, vrf); 9917 } 9918 9919 if (!default_route) { 9920 /* Default route already in prefix trie */ 9921 rv = trie_insert(pfx_trie, prefix, NULL, length, 9922 (trie_node_t *)pfx_payload); 9923 if (SOC_FAILURE(rv)) { 9924 goto delete_bkt_trie; 9925 } 9926 } 9927 9928 /* Update bucket index for VRF default route entry */ 9929 if (VRF_TRIE_INIT_COMPLETED(unit, vrf, ipv6)) { 9930 if (ipv6 == 0) { 9931 def_entry = VRF_TRIE_DEFAULT_ROUTE_IPV4(unit, vrf); 9932 } else { 9933 def_entry = VRF_TRIE_DEFAULT_ROUTE_IPV6(unit, vrf); 9934 } 9935 9936 if (0 == soc_L3_DEFIPm_field32_get(unit, def_entry, ALG_BKT_PTR0f)) { 9937 default_route = 0; 9938 rv = _alpm_prefix_create(unit, lpm_entry, prefix, 9939 &length, &default_route); 9940 if (SOC_SUCCESS(rv) && default_route) { 9941 soc_L3_DEFIPm_field32_set(unit, def_entry, 9942 ALG_BKT_PTR0f, bckt_idx); 9943 } 9944 } 9945 } 9946 9947 /* Return success */ 9948 return rv; 9949 9950 delete_bkt_trie: 9951 (void) trie_delete(bkt_trie, prefix, length, &delp); 9952 bkt_payload = (payload_t *) delp; 9953 9954 free_memory: 9955 sal_free(bkt_payload); 9956 sal_free(pfx_payload); 9957 return rv; 9958 } 9959 9960 /* 9961 * soc_alpm_warmboot_vrf_add 9962 */ 9963 static int 9964 soc_alpm_warmboot_vrf_add(int unit, 9965 int v6, 9966 int vrf, 9967 int idx, 9968 int bkt_ptr) 9969 { 9970 9971 int rv = SOC_E_NONE; 9972 uint32 length; 9973 uint32 key[5] = {0}; 9974 trie_t *pfx_root = NULL; 9975 payload_t *pfx_pyld = NULL; 9976 defip_entry_t *lpm_entry = NULL; 9977 9978 /* Initialize VRF PIVOT IPV4 trie */ 9979 lpm_entry = sal_alloc(sizeof(defip_entry_t), "Default LPM entry"); 9980 if (lpm_entry == NULL) { 9981 LOG_ERROR(BSL_LS_SOC_ALPM, 9982 (BSL_META_U(unit, 9983 "unable to allocate memory for LPM entry\n"))); 9984 return SOC_E_MEMORY; 9985 } 9986 9987 /* Initialize an lpm entry to perform a match */ 9988 (void) _soc_alpm_lpm_ent_key_init(unit, key, 0, vrf, v6, lpm_entry, 1); 9989 9990 /* for global VRF */ 9991 if (vrf == SOC_VRF_MAX(unit) + 1) { 9992 soc_L3_DEFIPm_field32_set(unit, lpm_entry, GLOBAL_ROUTE0f, 1); 9993 } else { 9994 /* Set default miss to global route only for non global routes */ 9995 soc_L3_DEFIPm_field32_set(unit, lpm_entry, DEFAULT_MISS0f, 1); 9996 } 9997 9998 if (v6 == 0) { 9999 VRF_TRIE_DEFAULT_ROUTE_IPV4(unit, vrf) = lpm_entry; 10000 trie_init(_MAX_KEY_LEN_48_, &VRF_PREFIX_TRIE_IPV4(unit, vrf)); 10001 pfx_root = VRF_PREFIX_TRIE_IPV4(unit, vrf); 10002 } else { 10003 VRF_TRIE_DEFAULT_ROUTE_IPV6(unit, vrf) = lpm_entry; 10004 trie_init(_MAX_KEY_LEN_144_, &VRF_PREFIX_TRIE_IPV6(unit, vrf)); 10005 pfx_root = VRF_PREFIX_TRIE_IPV6(unit, vrf); 10006 } 10007 10008 pfx_pyld = sal_alloc(sizeof(payload_t), "Payload for pfx trie key"); 10009 if (pfx_pyld == NULL) { 10010 LOG_ERROR(BSL_LS_SOC_ALPM, 10011 (BSL_META_U(unit, 10012 "Unable to allocate memory for pfx trie node \n"))); 10013 return SOC_E_MEMORY; 10014 } 10015 10016 sal_memset(pfx_pyld, 0, sizeof(*pfx_pyld)); 10017 10018 length = 0; 10019 pfx_pyld->key[0] = key[0]; 10020 pfx_pyld->key[1] = key[1]; 10021 pfx_pyld->len = length; 10022 10023 rv = trie_insert(pfx_root, key, NULL, length, &(pfx_pyld->node)); 10024 if (SOC_FAILURE(rv)) { 10025 sal_free(pfx_pyld); 10026 return rv; 10027 } 10028 10029 VRF_TRIE_INIT_DONE(unit, vrf, v6, 1); 10030 10031 return rv; 10032 } 10033 /* 10034 * soc_alpm_warmboot_prefix_insert 10035 */ 10036 int 10037 soc_alpm_warmboot_prefix_insert(int unit, 10038 int ipv6, 10039 int flex, 10040 void *lpm_entry, 10041 void *alpm_entry, 10042 int tcam_idx, 10043 int bckt_idx, 10044 int alpm_idx) 10045 { 10046 int vrf_id; /* Internal API representation of VRF id */ 10047 int vrf; /* VRF in (0 - (MAX_VRF + 1)) range */ 10048 int rv = SOC_E_NONE; 10049 10050 tcam_idx = soc_alpm_physical_idx(unit, L3_DEFIPm, tcam_idx, ipv6); 10051 10052 /* Get VRF */ 10053 SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf)); 10054 10055 /* For VRF_OVERRIDE (Global High) entries, Prefix resides in TCAM directly */ 10056 if (vrf_id == SOC_L3_VRF_OVERRIDE) { 10057 return(rv); 10058 } 10059 /* Non override entries, goes into ALPM memory */ 10060 if (!VRF_TRIE_INIT_COMPLETED(unit, vrf, ipv6)) { 10061 LOG_VERBOSE(BSL_LS_SOC_ALPM, 10062 (BSL_META_U(unit, 10063 "VRF %d is not initialized\n"), 10064 vrf)); 10065 rv = soc_alpm_warmboot_vrf_add(unit, ipv6, vrf, tcam_idx, bckt_idx); 10066 if (SOC_FAILURE(rv)) { 10067 LOG_ERROR(BSL_LS_SOC_ALPM, 10068 (BSL_META_U(unit, 10069 "VRF %d/%d trie init \n" 10070 "failed\n"), vrf, ipv6)); 10071 return rv; 10072 } 10073 10074 LOG_VERBOSE(BSL_LS_SOC_ALPM, 10075 (BSL_META_U(unit, 10076 "VRF %d/%d trie init completed\n"), 10077 vrf, ipv6)); 10078 } 10079 10080 rv = _soc_alpm_warmboot_insert(unit, ipv6, flex, lpm_entry, alpm_entry, 10081 tcam_idx, bckt_idx, alpm_idx); 10082 if (rv != SOC_E_NONE) { 10083 LOG_WARN(BSL_LS_SOC_ALPM, 10084 (BSL_META_U(unit, 10085 "unit %d : Route Insertion Failed :%s\n"), 10086 unit, soc_errmsg(rv))); 10087 10088 return(rv); 10089 } 10090 VRF_TRIE_ROUTES_INC(unit, vrf_id, vrf, ipv6); 10091 return(rv); 10092 } 10093 10094 /* 10095 * alpm_warmboot_bucket_bitmap_set 10096 * This function will set bit position in bucket bitmap 10097 */ 10098 int 10099 soc_alpm_warmboot_bucket_bitmap_set(int u, /* Unit */ 10100 int v6, /* Flag v4/v6 */ 10101 int bkt_idx) /* Bucket index */ 10102 { 10103 int step_count = 1; 10104 10105 /* 10106 * In combined search mode, with urpf disabled, need to allocate even and 10107 * odd bucket pointers 10108 */ 10109 if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) { 10110 step_count = 2; 10111 } 10112 10113 if (SOC_ALPM_BUCKET_BMAP(u) == NULL) { 10114 return SOC_E_INTERNAL; 10115 } 10116 10117 /* Set bit position */ 10118 SHR_BITSET_RANGE(SOC_ALPM_BUCKET_BMAP(u), bkt_idx, step_count); 10119 10120 return SOC_E_NONE; 10121 } 10122 10123 int 10124 soc_alpm_warmboot_lpm_reinit_done(int unit) 10125 { 10126 int idx; 10127 int prev_idx = ALPM_MAX_PFX_INDEX; 10128 10129 int defip_table_size = soc_mem_index_count(unit, L3_DEFIPm); 10130 10131 if (SOC_URPF_STATUS_GET(unit)) { 10132 defip_table_size >>= 1; 10133 } 10134 10135 /* returns 0 for combined search mode and 1 for parallel search mode */ 10136 if (!soc_alpm_mode_get(unit)) { 10137 /* Combined search mode */ 10138 SOC_ALPM_LPM_STATE_PREV(unit, ALPM_MAX_PFX_INDEX) = -1; 10139 10140 for (idx = ALPM_MAX_PFX_INDEX; idx > -1; idx--) { 10141 if (-1 == SOC_ALPM_LPM_STATE_START(unit, idx)) { 10142 continue; 10143 } 10144 10145 SOC_ALPM_LPM_STATE_PREV(unit, idx) = prev_idx; 10146 SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = idx; 10147 10148 SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) = \ 10149 SOC_ALPM_LPM_STATE_START(unit, idx) - \ 10150 SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1; 10151 prev_idx = idx; 10152 10153 } 10154 10155 SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = -1; 10156 SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) = \ 10157 defip_table_size - \ 10158 SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1; 10159 } else { 10160 /* Parallel search mode 10161 * 10162 * Configured VRF Range 10163 * {0 - (ALPM_MAX_PFX_INDEX/3)} 10164 * Global VRF Range 10165 * {((ALPM_MAX_PFX_INDEX/1) + 1) - (ALPM_MAX_PFX_INDEX/2) } 10166 * Override VRF Range 10167 * {((ALPM_MAX_PFX_INDEX/2) + 1) - (ALPM_MAX_PFX_INDEX) } 10168 */ 10169 10170 /* 10171 * Global and Overide VRF range are treated as single block and 10172 * both blocks will be linked 10173 */ 10174 SOC_ALPM_LPM_STATE_PREV(unit, ALPM_MAX_PFX_INDEX) = -1; 10175 for (idx = ALPM_MAX_PFX_INDEX; idx > (ALPM_MAX_PFX_INDEX/3) ; idx--) { 10176 if (-1 == SOC_ALPM_LPM_STATE_START(unit, idx)) { 10177 continue; 10178 } 10179 10180 SOC_ALPM_LPM_STATE_PREV(unit, idx) = prev_idx; 10181 SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = idx; 10182 10183 SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) = \ 10184 SOC_ALPM_LPM_STATE_START(unit, idx) - \ 10185 SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1; 10186 10187 prev_idx = idx; 10188 } 10189 SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = -1; 10190 SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) = \ 10191 defip_table_size - \ 10192 SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1; 10193 10194 /* Configured VRF range */ 10195 prev_idx = (ALPM_MAX_PFX_INDEX/3); 10196 SOC_ALPM_LPM_STATE_PREV(unit, (ALPM_MAX_PFX_INDEX/3)) = -1; 10197 for (idx = ((ALPM_MAX_PFX_INDEX/3)-1); idx > -1; idx--) { 10198 if (-1 == SOC_ALPM_LPM_STATE_START(unit, idx)) { 10199 continue; 10200 } 10201 10202 SOC_ALPM_LPM_STATE_PREV(unit, idx) = prev_idx; 10203 SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = idx; 10204 10205 SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) = \ 10206 SOC_ALPM_LPM_STATE_START(unit, idx) - \ 10207 SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1; 10208 prev_idx = idx; 10209 } 10210 SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = -1; 10211 SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) = \ 10212 (defip_table_size >> 1) - \ 10213 SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1; 10214 } 10215 10216 return (SOC_E_NONE); 10217 } 10218 10219 int 10220 soc_alpm_warmboot_lpm_reinit(int unit, 10221 int ipv6, 10222 int idx, 10223 void *lpm_entry) 10224 { 10225 int pfx_len; 10226 int flex; 10227 defip_entry_t lpm_entry_hi; 10228 int vrf_id, vrf; 10229 10230 if (soc_L3_DEFIPm_field32_get(unit, lpm_entry, VALID0f) || 10231 soc_L3_DEFIPm_field32_get(unit, lpm_entry, VALID1f)) { 10232 10233 LPM_HASH_INSERT(unit, lpm_entry, idx, NULL, NULL); 10234 } 10235 10236 if (ipv6) { 10237 if (soc_L3_DEFIPm_field32_get(unit, lpm_entry, VALID0f)) { 10238 SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf)); 10239 if (!VRF_FLEX_COMPLETED(unit, vrf_id, vrf, ipv6)) { 10240 flex = soc_L3_DEFIPm_field32_get(unit, lpm_entry, ENTRY_VIEW0f); 10241 VRF_FLEX_SET(unit, vrf_id, vrf, ipv6, flex); 10242 } 10243 VRF_PIVOT_REF_INC(unit, vrf_id, vrf, ipv6); 10244 } 10245 } else { 10246 if (soc_L3_DEFIPm_field32_get(unit, lpm_entry, VALID0f)) { 10247 SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf)); 10248 if (!VRF_FLEX_COMPLETED(unit, vrf_id, vrf, ipv6)) { 10249 flex = soc_L3_DEFIPm_field32_get(unit, lpm_entry, ENTRY_VIEW0f); 10250 VRF_FLEX_SET(unit, vrf_id, vrf, ipv6, flex); 10251 } 10252 VRF_PIVOT_REF_INC(unit, vrf_id, vrf, ipv6); 10253 } 10254 if (soc_L3_DEFIPm_field32_get(unit, lpm_entry, VALID1f)) { 10255 soc_alpm_lpm_ip4entry1_to_0(unit, lpm_entry, &lpm_entry_hi, TRUE); 10256 SOC_IF_ERROR_RETURN(soc_alpm_lpm_vrf_get(unit, &lpm_entry_hi, &vrf_id, &vrf)); 10257 if (!VRF_FLEX_COMPLETED(unit, vrf_id, vrf, ipv6)) { 10258 flex = soc_L3_DEFIPm_field32_get(unit, lpm_entry, ENTRY_VIEW1f); 10259 VRF_FLEX_SET(unit, vrf_id, vrf, ipv6, flex); 10260 } 10261 VRF_PIVOT_REF_INC(unit, vrf_id, vrf, ipv6); 10262 } 10263 } 10264 10265 if (soc_L3_DEFIPm_field32_get(unit, lpm_entry, VALID0f)) { 10266 10267 SOC_IF_ERROR_RETURN 10268 (_soc_alpm_lpm_prefix_length_get(unit, lpm_entry, &pfx_len)); 10269 10270 if (SOC_ALPM_LPM_STATE_VENT(unit, pfx_len) == 0) { 10271 SOC_ALPM_LPM_STATE_START(unit, pfx_len) = idx; 10272 SOC_ALPM_LPM_STATE_END(unit, pfx_len) = idx; 10273 } else { 10274 SOC_ALPM_LPM_STATE_END(unit, pfx_len) = idx; 10275 } 10276 10277 SOC_ALPM_LPM_STATE_VENT(unit, pfx_len)++; 10278 10279 if (ipv6) { 10280 /* IPv6 entry */ 10281 return (SOC_E_NONE); 10282 } 10283 } else { 10284 /* Check upper half of lpm_entry */ 10285 if (soc_L3_DEFIPm_field32_get(unit, lpm_entry, VALID1f)) { 10286 if (ipv6) { 10287 return SOC_E_NONE; 10288 } 10289 10290 /* Get prefix length */ 10291 SOC_IF_ERROR_RETURN 10292 (_soc_alpm_lpm_prefix_length_get(unit, &lpm_entry_hi, &pfx_len)); 10293 10294 if (SOC_ALPM_LPM_STATE_VENT(unit, pfx_len) == 0) { 10295 SOC_ALPM_LPM_STATE_START(unit, pfx_len) = idx; 10296 SOC_ALPM_LPM_STATE_END(unit, pfx_len) = idx; 10297 } else { 10298 SOC_ALPM_LPM_STATE_END(unit, pfx_len) = idx; 10299 } 10300 10301 SOC_ALPM_LPM_STATE_VENT(unit, pfx_len)++; 10302 } 10303 } 10304 return (SOC_E_NONE); 10305 } 10306 10307 /* Helper structure for Debug Counter */ 10308 typedef struct _alpm_dbg_cnt_s { 10309 int v4; /* Counter for IPv4 */ 10310 int v6_64; 10311 int v6_128; 10312 int v4t; /* Totaled counter for IPv4 per VRF */ 10313 int v6_64t; 10314 int v6_128t; 10315 int used; 10316 } _alpm_dbg_cnt_t; 10317 10318 typedef enum _alpm_pvt_cnt_type_e { 10319 SOC_ALPM_DEBUG_CNT_ADD = 0, 10320 SOC_ALPM_DEBUG_CNT_DEL, 10321 SOC_ALPM_DEBUG_CNT_SPLIT, 10322 SOC_ALPM_DEBUG_CNT_USED, 10323 SOC_ALPM_DEBUG_CNT_LPM_SHIFT, 10324 SOC_ALPM_DEBUG_CNT_LPM_FULL 10325 } _alpm_pvt_cnt_type_t; 10326 10327 10328 #define _ALPM_DBG_CNT_ADD(dst_dc, src_dc) \ 10329 do { \ 10330 (dst_dc)->v4 += (src_dc)->v4; \ 10331 (dst_dc)->v4t += (src_dc)->v4t; \ 10332 (dst_dc)->v6_64 += (src_dc)->v6_64; \ 10333 (dst_dc)->v6_64t += (src_dc)->v6_64t; \ 10334 (dst_dc)->v6_128 += (src_dc)->v6_128; \ 10335 (dst_dc)->v6_128t += (src_dc)->v6_128t; \ 10336 } while (0) 10337 10338 /* Common debug counter print */ 10339 #define PRINT_SPLIT_LINE(u) \ 10340 LOG_CLI((BSL_META_U(u, "-----------------------------------------------\n"))) 10341 #define PRINT_VRF_HEADER(u) \ 10342 LOG_CLI((BSL_META_U(u, "\n VRF v4 v6-64 v6-128 | AVG\n"))) 10343 #define PRINT_VRF_NOT_FOUND(u) \ 10344 LOG_CLI((BSL_META_U(u, "%9s\n"), "Specific VRF not found")) 10345 10346 /* Print Bucket Occupancy */ 10347 #define BKT_PERCENT(used, tot) \ 10348 (tot) ? (used) * 100 / (tot) : 0, (tot) ? (used) * 1000 / (tot) % 10 : 0 10349 #define PRINT_BKT_OCCU_ITEM(u, vrf, tmp_dc) \ 10350 do { \ 10351 LOG_CLI((BSL_META_U(u, \ 10352 "%9d %02d.%d%% %02d.%d%% %02d.%d%% | %02d.%d%% %5s\n"), \ 10353 (vrf), BKT_PERCENT(tmp_dc->v4, tmp_dc->v4t), \ 10354 BKT_PERCENT(tmp_dc->v6_64, tmp_dc->v6_64t), \ 10355 BKT_PERCENT(tmp_dc->v6_128, tmp_dc->v6_128t), \ 10356 BKT_PERCENT((tmp_dc->v4+tmp_dc->v6_64+tmp_dc->v6_128),\ 10357 (tmp_dc->v4t+tmp_dc->v6_64t+tmp_dc->v6_128t)), \ 10358 (vrf) == SOC_VRF_MAX(u)+1 ? "GLo" : "")); \ 10359 } while (0) 10360 #define PRINT_BKT_OCCU_ITEM_TOT(u, all_dc) \ 10361 do { \ 10362 LOG_CLI((BSL_META_U(u, \ 10363 "%9s %02d.%d%% %02d.%d%% %02d.%d%% | %02d.%d%% \n"), \ 10364 "AVG", BKT_PERCENT((all_dc)->v4, (all_dc)->v4t), \ 10365 BKT_PERCENT((all_dc)->v6_64, (all_dc)->v6_64t), \ 10366 BKT_PERCENT((all_dc)->v6_128, (all_dc)->v6_128t), \ 10367 BKT_PERCENT(((all_dc)->v4+(all_dc)->v6_64+(all_dc)->v6_128),\ 10368 ((all_dc)->v4t+(all_dc)->v6_64t+(all_dc)->v6_128t)))); \ 10369 } while (0) 10370 10371 /* Print VRF based debug counter */ 10372 #define PRINT_VRF_ITEM(u, vrf, v4, v6_64, v6_128, total) \ 10373 do { \ 10374 LOG_CLI((BSL_META_U(u, \ 10375 "%9d %-7d %-7d %-7d | %-7d %s\n"), \ 10376 (vrf == MAX_VRF_ID ? -1 : vrf), (v4), (v6_64),\ 10377 (v6_128), (total), (vrf) == MAX_VRF_ID ? "GHi" : \ 10378 (vrf) == SOC_VRF_MAX(u)+1 ? "GLo" : "")); \ 10379 } while (0) 10380 #define PRINT_VRF_ITEM_TOT(u, v4, v6_64, v6_128, total) \ 10381 do { \ 10382 LOG_CLI((BSL_META_U(u, \ 10383 "%9s %-7d %-7d %-7d | %-7d \n"), "Total", (v4), (v6_64),\ 10384 (v6_128), (total))); \ 10385 } while (0) 10386 10387 #define PRINT_BUCKET_HEADER(u) \ 10388 do { \ 10389 LOG_CLI((BSL_META_U(u, \ 10390 "\n BKT/VRF Min Max Cur | Comment\n"))); \ 10391 } while (0) 10392 #define PRINT_BUCKET_ITEM(u, bkt, vrf, min, max, cur, def) \ 10393 do { \ 10394 LOG_CLI((BSL_META_U(u, \ 10395 "%5d/%-4d %-7d %-7d %-7d | %-7s\n"), bkt, vrf, \ 10396 min, max, cur, def ? "Def" : \ 10397 (vrf) == SOC_VRF_MAX(u)+1 ? "GLo" : "")); \ 10398 } while (0) 10399 10400 /* Get max available IPv4, IPv6-64, IPv6-128 entry numbers */ 10401 static void 10402 _soc_alpm_pivot_max_get(int u, alpm_vrf_counter_t *pvt_max) 10403 { 10404 pvt_max->v4 = soc_mem_index_count(u, L3_DEFIPm) * 2; 10405 pvt_max->v6_128 = soc_mem_index_count(u, L3_DEFIP_PAIR_128m); 10406 10407 if (SOC_ALPM_128B_ENABLE(u)) { 10408 pvt_max->v6_64 = pvt_max->v6_128; 10409 } else { 10410 pvt_max->v6_64 = pvt_max->v4 >> 1; 10411 } 10412 10413 if (SOC_URPF_STATUS_GET(u)) { 10414 pvt_max->v4 >>= 1; 10415 pvt_max->v6_128 >>= 1; 10416 pvt_max->v6_64 >>= 1; 10417 } 10418 } 10419 10420 static void 10421 _soc_alpm_pivot_debug_dump(int u, int vrf_id, alpm_vrf_handle_t *vh, 10422 _alpm_pvt_cnt_type_t pct) 10423 { 10424 alpm_vrf_counter_t *vc; 10425 int i, tv4c, tv6_64c, tv6_128c; 10426 int found = 0; 10427 10428 alpm_vrf_counter_t pvt_max; 10429 10430 /* Print Pivot debug info header */ 10431 switch (pct) { 10432 case SOC_ALPM_DEBUG_CNT_ADD: 10433 LOG_CLI((BSL_META_U(u, 10434 "\nAdd Counter:\n"))); 10435 break; 10436 case SOC_ALPM_DEBUG_CNT_DEL: 10437 LOG_CLI((BSL_META_U(u, 10438 "\nDelete Counter:\n"))); 10439 break; 10440 case SOC_ALPM_DEBUG_CNT_SPLIT: 10441 LOG_CLI((BSL_META_U(u, 10442 "\nInternal Debug Counter - Split:\n"))); 10443 break; 10444 case SOC_ALPM_DEBUG_CNT_USED: 10445 _soc_alpm_pivot_max_get(u, &pvt_max); 10446 LOG_CLI((BSL_META_U(u, 10447 "\nPivot Occupancy: Max v4/v6-64/v6-128 = %d/%d/%d\n"), 10448 pvt_max.v4, pvt_max.v6_64, pvt_max.v6_128)); 10449 break; 10450 case SOC_ALPM_DEBUG_CNT_LPM_SHIFT: 10451 LOG_CLI((BSL_META_U(u, 10452 "\nInternal Debug Counter - LPM Shift:\n"))); 10453 break; 10454 case SOC_ALPM_DEBUG_CNT_LPM_FULL: 10455 LOG_CLI((BSL_META_U(u, 10456 "\nInternal Debug Counter - LPM Full:\n"))); 10457 break; 10458 default: 10459 break; 10460 } 10461 PRINT_VRF_HEADER(u); 10462 PRINT_SPLIT_LINE(u); 10463 10464 tv4c = tv6_64c = tv6_128c = 0; 10465 for (i = 0; i < MAX_VRF_ID + 1; i++) { 10466 int v4c, v6_64c, v6_128c; 10467 if (vh[i].init_done == 0 && i != MAX_VRF_ID) { 10468 continue; 10469 } 10470 if (vrf_id != -1 && vrf_id != i) { 10471 continue; 10472 } 10473 10474 found = 1; 10475 10476 switch (pct) { 10477 case SOC_ALPM_DEBUG_CNT_ADD: 10478 vc = &vh[i].add; 10479 break; 10480 case SOC_ALPM_DEBUG_CNT_DEL: 10481 vc = &vh[i].del; 10482 break; 10483 case SOC_ALPM_DEBUG_CNT_SPLIT: 10484 vc = &vh[i].bkt_split; 10485 break; 10486 case SOC_ALPM_DEBUG_CNT_LPM_SHIFT: 10487 vc = &vh[i].lpm_shift; 10488 break; 10489 case SOC_ALPM_DEBUG_CNT_LPM_FULL: 10490 vc = &vh[i].lpm_full; 10491 break; 10492 case SOC_ALPM_DEBUG_CNT_USED: 10493 vc = &vh[i].pivot_used; 10494 break; 10495 default: 10496 vc = &vh[i].pivot_used; 10497 break; 10498 } 10499 10500 v4c = vc->v4; 10501 v6_64c = vc->v6_64; 10502 v6_128c = vc->v6_128; 10503 10504 tv4c += v4c; 10505 tv6_64c += v6_64c; 10506 tv6_128c += v6_128c; 10507 10508 PRINT_VRF_ITEM(u, i, v4c, v6_64c, v6_128c, (v4c+v6_64c+v6_128c)); 10509 } 10510 if (found == 0) { 10511 PRINT_VRF_NOT_FOUND(u); 10512 } else { 10513 PRINT_SPLIT_LINE(u); 10514 PRINT_VRF_ITEM_TOT(u, tv4c, tv6_64c, tv6_128c, (tv4c+tv6_64c+tv6_128c)); 10515 } 10516 10517 return ; 10518 } 10519 10520 int 10521 soc_alpm_debug_show(int u, int vrf_id, uint32 flags) 10522 { 10523 int i, alloc_sz, found = 0; 10524 _alpm_dbg_cnt_t *alpm_dc_arr; 10525 _alpm_dbg_cnt_t bkt_ent_max; 10526 _alpm_dbg_cnt_t all_dc; 10527 10528 if (vrf_id > (SOC_VRF_MAX(u) + 1)) { 10529 return SOC_E_PARAM; 10530 } 10531 10532 alloc_sz = MAX_VRF_ID * sizeof(_alpm_dbg_cnt_t); 10533 alpm_dc_arr = sal_alloc(alloc_sz, "_alpm_dbg_cnt"); 10534 if (alpm_dc_arr == NULL) { 10535 return SOC_E_MEMORY; 10536 } 10537 sal_memset(alpm_dc_arr, 0, alloc_sz); 10538 10539 /* Collect data */ 10540 bkt_ent_max.v4 = ALPM_IPV4_BKT_COUNT; 10541 bkt_ent_max.v6_64 = ALPM_IPV6_64_BKT_COUNT; 10542 bkt_ent_max.v6_128 = ALPM_IPV6_128_BKT_COUNT; 10543 10544 if (!soc_alpm_mode_get(u) && !SOC_URPF_STATUS_GET(u)) { 10545 bkt_ent_max.v6_64 <<= 1; 10546 bkt_ent_max.v6_128 <<= 1; 10547 } 10548 10549 /* 1. Bucket Occupancy */ 10550 if (flags & (SOC_ALPM_DEBUG_SHOW_FLAG_BKT)) { 10551 LOG_CLI((BSL_META_U(u, 10552 "\nBucket Occupancy:\n"))); 10553 PRINT_BUCKET_HEADER(u); 10554 PRINT_SPLIT_LINE(u); 10555 } 10556 for (i = 0; i < MAX_PIVOT_COUNT; i++) { 10557 alpm_pivot_t *p = ALPM_TCAM_PIVOT(u, i); 10558 if (p != NULL) { 10559 _alpm_dbg_cnt_t *tmp_dc; 10560 int vrf = PIVOT_BUCKET_VRF(p); 10561 10562 if (vrf < 0 || vrf > (SOC_VRF_MAX(u) + 1)) { 10563 continue; 10564 } 10565 10566 if (vrf_id != -1 && vrf_id != vrf) { 10567 continue; 10568 } 10569 10570 if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_BKT) { 10571 found = 1; 10572 PRINT_BUCKET_ITEM(u, i, vrf, 10573 PIVOT_BUCKET_MIN(p), 10574 PIVOT_BUCKET_MAX(p), 10575 PIVOT_BUCKET_COUNT(p), 10576 PIVOT_BUCKET_DEF(p)); 10577 } 10578 10579 tmp_dc = &alpm_dc_arr[vrf]; 10580 if (PIVOT_BUCKET_IPV6(p) == L3_DEFIP_MODE_128) { 10581 tmp_dc->v6_128 += PIVOT_BUCKET_COUNT(p); 10582 tmp_dc->v6_128t += bkt_ent_max.v6_128; 10583 } else if (PIVOT_BUCKET_IPV6(p) == L3_DEFIP_MODE_64) { 10584 tmp_dc->v6_64 += PIVOT_BUCKET_COUNT(p); 10585 tmp_dc->v6_64t += bkt_ent_max.v6_64; 10586 } else { 10587 tmp_dc->v4 += PIVOT_BUCKET_COUNT(p); 10588 tmp_dc->v4t += bkt_ent_max.v4; 10589 } 10590 tmp_dc->used = TRUE; 10591 } 10592 } 10593 10594 if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_BKT) { 10595 if (found == 0) { 10596 PRINT_VRF_NOT_FOUND(u); 10597 } 10598 } 10599 10600 sal_memset(&all_dc, 0, sizeof(all_dc)); 10601 found = 0; 10602 10603 if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_BKTUSG) { 10604 LOG_CLI((BSL_META_U(u, 10605 "\nBucket Usage:\n"))); 10606 PRINT_VRF_HEADER(u); 10607 PRINT_SPLIT_LINE(u); 10608 for (i = 0; i < MAX_VRF_ID; i++) { 10609 _alpm_dbg_cnt_t *tmp_dc; 10610 if (alpm_dc_arr[i].used != TRUE) { 10611 continue; 10612 } 10613 if (vrf_id != -1 && vrf_id != i) { 10614 continue; 10615 } 10616 10617 found = 1; 10618 tmp_dc = &alpm_dc_arr[i]; 10619 _ALPM_DBG_CNT_ADD(&all_dc, tmp_dc); 10620 PRINT_BKT_OCCU_ITEM(u, i, tmp_dc); 10621 } 10622 if (found == 0) { 10623 PRINT_VRF_NOT_FOUND(u); 10624 } else { 10625 PRINT_SPLIT_LINE(u); 10626 PRINT_BKT_OCCU_ITEM_TOT(u, &all_dc); 10627 } 10628 } 10629 10630 /* 2. Pivot Occupancy */ 10631 if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_PVT) { 10632 _soc_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 10633 SOC_ALPM_DEBUG_CNT_USED); 10634 } 10635 10636 /* 3. Add/Delete counters per VRF/ip type */ 10637 if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_CNT) { 10638 _soc_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 10639 SOC_ALPM_DEBUG_CNT_ADD); 10640 10641 _soc_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 10642 SOC_ALPM_DEBUG_CNT_DEL); 10643 } 10644 10645 /* 4. Total No. of bucket splits per VRF/ip type */ 10646 if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_INTDBG) { 10647 _soc_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 10648 SOC_ALPM_DEBUG_CNT_SPLIT); 10649 _soc_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 10650 SOC_ALPM_DEBUG_CNT_LPM_FULL); 10651 _soc_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 10652 SOC_ALPM_DEBUG_CNT_LPM_SHIFT); 10653 } 10654 10655 sal_free(alpm_dc_arr); 10656 10657 return SOC_E_NONE; 10658 } 10659 10660 void 10661 soc_alpm_debug_cntr_show(int u) 10662 { 10663 LOG_CLI(("====ALPM=Internal=Debug=Counter====\n")); 10664 LOG_CLI(("%-24s%d\n", "Bucket Split:", soc_alpm_dbg_cnt[u].bkt_split)); 10665 LOG_CLI(("%-24s%d\n", "Bucket Merge:", soc_alpm_dbg_cnt[u].bkt_merge)); 10666 LOG_CLI(("%-24s%d\n", "Bucket MergeDuringRp:", soc_alpm_dbg_cnt[u].bkt_merge2)); 10667 LOG_CLI(("%-24s%d\n", "Bucket Repartition:", soc_alpm_dbg_cnt[u].bkt_repart)); 10668 LOG_CLI(("%-24s%d\n", "Propagation Insert CB:", 10669 soc_alpm_dbg_cnt[u].ppg_cb_insert)); 10670 LOG_CLI(("%-24s%d\n", "Propagation Delete CB:", 10671 soc_alpm_dbg_cnt[u].ppg_cb_delete)); 10672 } 10673 10674 int 10675 soc_alpm_debug_brief_show(int u, int phy_bkt, int index) 10676 { 10677 int i = 0, j = 0, rv = SOC_E_NONE; 10678 uint32 rval = 0, alpm = 0, mode = 0; 10679 uint32 urpf = 0, bit128 = 0, fv = 0, bnkbits = 0xf; 10680 int v4used = 0, v4max = 0; 10681 int v6_64used = 0, v6_64max = 0; 10682 int v6_128used = 0, v6_128max = 0; 10683 int bucket_used = 0, bucket_max = 0; 10684 char *lpm_tbl_ptr = NULL; 10685 defip_entry_t *lpm_entry = NULL; 10686 defip_pair_128_entry_t *lpm_entry_p128 = NULL; 10687 int ipv6, bkt_ptr, gh, gr, use_alpm; 10688 int *bktref = NULL; 10689 int glb_hi_cnt = 0, glb_lo_cnt = 0; 10690 soc_mem_t lpm_mem; 10691 int alloc_size = 0; 10692 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 10693 soc_field_t fldv, fldb, fldg, fldr; 10694 int alpm_bkt_bits = SOC_ALPM_BUCKET_BITS(u); 10695 10696 char *mode_str[] = { 10697 "LPM", 10698 "ALPM-Combined", 10699 "ALPM-Parallel", 10700 "ALPM-Invalid", 10701 "ALPM-Invalid" 10702 }; 10703 10704 SOC_IF_ERROR_RETURN(READ_L3_DEFIP_RPF_CONTROLr(u, &rval)); 10705 alpm = soc_reg_field_get(u, L3_DEFIP_RPF_CONTROLr, rval, LPM_MODEf); 10706 if (alpm != 0) { 10707 mode = soc_reg_field_get(u, L3_DEFIP_RPF_CONTROLr, rval, LOOKUP_MODEf); 10708 } 10709 urpf = soc_reg_field_get(u, L3_DEFIP_RPF_CONTROLr, rval, DEFIP_RPF_ENABLEf); 10710 10711 LOG_CLI(("\n")); 10712 LOG_CLI(("%-24s%s\n", "Mode:", mode_str[alpm + mode])); 10713 LOG_CLI(("%-24s%s\n", "uRPF:", urpf ? "Enable" : "Disable")); 10714 bit128 = !!soc_mem_index_count(u, L3_DEFIP_PAIR_128m); 10715 LOG_CLI(("%-24s%d\n", "IPv6 Bits:", bit128 ? 128 : 64)); 10716 10717 if (alpm == 0) { 10718 return SOC_E_NONE; 10719 } 10720 LOG_CLI(("%-24s%s\n", "IPv4 Wide:", "Single")); 10721 10722 if (mode == 0 && !urpf) { 10723 fv = 1; 10724 } else { 10725 fv = 0; 10726 } 10727 LOG_CLI(("%-24s%s\n", "IPv6 Wide:", fv ? "Double" : "Single")); 10728 10729 LOG_CLI(("%-24s%d\n", "Banks:", 4)); 10730 10731 /* Calculate utilization */ 10732 v4max = 2 * soc_mem_index_count(u, L3_DEFIPm); 10733 v6_64max = bit128 ? soc_mem_index_count(u, L3_DEFIP_PAIR_128m) : 10734 soc_mem_index_count(u, L3_DEFIPm); 10735 v6_128max = soc_mem_index_count(u, L3_DEFIP_PAIR_128m); 10736 bucket_max = SOC_TD2_ALPM_MAX_BKTS; 10737 if (urpf) { 10738 v4max >>= 1; 10739 v6_64max >>= 1; 10740 v6_128max >>= 1; 10741 bucket_max >>= 1; 10742 } 10743 10744 bktref = sal_alloc(bucket_max * sizeof(int), "bktref"); 10745 if (bktref == NULL) { 10746 return SOC_E_MEMORY; 10747 } 10748 sal_memset(bktref, 0, bucket_max * sizeof(int)); 10749 10750 /* DMA LPM table to software copy */ 10751 lpm_mem = L3_DEFIPm; 10752 alloc_size = WORDS2BYTES(soc_mem_entry_words(u, lpm_mem)) * 10753 soc_mem_index_count(u, lpm_mem); 10754 lpm_tbl_ptr = soc_cm_salloc(u, alloc_size, "lpm_tbl"); 10755 if (lpm_tbl_ptr == NULL) { 10756 rv = SOC_E_MEMORY; 10757 goto _free_mem; 10758 } 10759 /* Reset allocated buffer. */ 10760 sal_memset(lpm_tbl_ptr, 0, alloc_size); 10761 10762 /* Read table to the buffer. */ 10763 if (v4max && soc_mem_read_range(u, lpm_mem, MEM_BLOCK_ANY, 10764 soc_mem_index_min(u, lpm_mem), 10765 soc_mem_index_max(u, lpm_mem), lpm_tbl_ptr) < 0) { 10766 rv = (SOC_E_INTERNAL); 10767 goto _free_mem; 10768 } 10769 10770 for (i = 0; i < (v4max / 2); i++) { 10771 /* Calculate entry offset */ 10772 lpm_entry = 10773 soc_mem_table_idx_to_pointer(u, lpm_mem, 10774 defip_entry_t *, lpm_tbl_ptr, i); 10775 ipv6 = soc_mem_field32_get(u, lpm_mem, lpm_entry, MODE0f); 10776 10777 for (j = 0; j < (ipv6 ? 1 : 2); j++) { 10778 if (j == 1) { 10779 fldv = VALID1f; 10780 } else { 10781 fldv = VALID0f; 10782 } 10783 /* Make sure entry is valid. */ 10784 if (!soc_mem_field32_get(u, lpm_mem, lpm_entry, fldv)) { 10785 continue; 10786 } 10787 10788 if (ipv6) { 10789 v6_64used++; 10790 } else { 10791 v4used++; 10792 } 10793 10794 if (j == 0) { 10795 fldg = GLOBAL_HIGH0f; 10796 fldb = ALG_BKT_PTR0f; 10797 fldr = GLOBAL_ROUTE0f; 10798 } else { 10799 fldg = GLOBAL_HIGH1f; 10800 fldb = ALG_BKT_PTR1f; 10801 fldr = GLOBAL_ROUTE1f; 10802 } 10803 10804 gh = soc_mem_field32_get(u, lpm_mem, lpm_entry, fldg); 10805 gr = soc_mem_field32_get(u, lpm_mem, lpm_entry, fldr); 10806 if (gr) { 10807 if (gh) { 10808 glb_hi_cnt++; 10809 use_alpm = 0; 10810 } else { 10811 glb_lo_cnt++; 10812 use_alpm = 1; 10813 } 10814 } else { 10815 use_alpm = 1; 10816 } 10817 10818 if (use_alpm) { 10819 bkt_ptr = soc_mem_field32_get(u, lpm_mem, lpm_entry, fldb); 10820 if (bkt_ptr > bucket_max) { 10821 LOG_CLI(("Invalid phy_bkt pointer in %s index %d\n", 10822 SOC_MEM_NAME(u, lpm_mem), i)); 10823 } else { 10824 if (bktref[bkt_ptr]) { 10825 LOG_CLI(("Invalid bucket sharing in %s index %d\n", 10826 SOC_MEM_NAME(u, lpm_mem), i)); 10827 } else { 10828 bktref[bkt_ptr]++; 10829 bucket_used++; 10830 } 10831 } 10832 } 10833 } 10834 } 10835 10836 soc_cm_sfree(u, lpm_tbl_ptr); 10837 10838 /* l3_defip_pair_128 */ 10839 lpm_tbl_ptr = NULL; 10840 lpm_mem = L3_DEFIP_PAIR_128m; 10841 alloc_size = WORDS2BYTES(soc_mem_entry_words(u, lpm_mem)) * 10842 soc_mem_index_count(u, lpm_mem); 10843 lpm_tbl_ptr = soc_cm_salloc(u, alloc_size, "lpm_tbl_p128"); 10844 if (lpm_tbl_ptr == NULL) { 10845 rv = SOC_E_MEMORY; 10846 goto _free_mem; 10847 } 10848 /* Reset allocated buffer. */ 10849 sal_memset(lpm_tbl_ptr, 0, alloc_size); 10850 10851 /* Read table to the buffer. */ 10852 if (v6_128max && soc_mem_read_range(u, lpm_mem, MEM_BLOCK_ANY, 10853 soc_mem_index_min(u, lpm_mem), 10854 soc_mem_index_max(u, lpm_mem), lpm_tbl_ptr) < 0) { 10855 rv = (SOC_E_INTERNAL); 10856 goto _free_mem; 10857 } 10858 10859 for (i = 0; i < v6_128max; i++) { 10860 /* Calculate entry offset */ 10861 lpm_entry_p128 = 10862 soc_mem_table_idx_to_pointer(u, lpm_mem, 10863 defip_pair_128_entry_t *, lpm_tbl_ptr, i); 10864 /* Verify if read LPM entry is IPv6-128 entry */ 10865 if (0x03 != soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, MODE1_UPRf)) { 10866 continue; 10867 }; 10868 10869 /* Verify if LPM entry is valid */ 10870 if (!soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, 10871 VALID1_LWRf) || 10872 !soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, 10873 VALID0_LWRf) || 10874 !soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, 10875 VALID1_UPRf) || 10876 !soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, 10877 VALID0_UPRf)) { 10878 continue; 10879 }; 10880 10881 v6_128used++; 10882 10883 gh = soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, GLOBAL_HIGHf); 10884 gr = soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, GLOBAL_ROUTEf); 10885 if (gr) { 10886 if (gh) { 10887 glb_hi_cnt++; 10888 use_alpm = 0; 10889 } else { 10890 glb_lo_cnt++; 10891 use_alpm = 1; 10892 } 10893 } else { 10894 use_alpm = 1; 10895 } 10896 10897 if (use_alpm) { 10898 bkt_ptr = soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, ALG_BKT_PTRf); 10899 if (bkt_ptr > bucket_max) { 10900 LOG_CLI(("Invalid phy_bkt pointer in %s index %d\n", 10901 SOC_MEM_NAME(u, lpm_mem), i)); 10902 } else { 10903 if (bktref[bkt_ptr]) { 10904 LOG_CLI(("Invalid bucket sharing in %s index %d\n", 10905 SOC_MEM_NAME(u, lpm_mem), i)); 10906 } else { 10907 bktref[bkt_ptr]++; 10908 bucket_used++; 10909 } 10910 } 10911 } 10912 } 10913 10914 LOG_CLI(("\n")); 10915 LOG_CLI(("%-24s%d/%-4d\n", "IPv4 Pivots:", v4used, v4max)); 10916 LOG_CLI(("%-24s%d/%-4d\n", "IPv6-64 Pivots:", v6_64used, v6_64max)); 10917 LOG_CLI(("%-24s%d/%-4d\n", "IPv6-128 Pivots:", v6_128used, v6_128max)); 10918 LOG_CLI(("%-24s%d/%-4d\n", "Buckets:", bucket_used, bucket_max)); 10919 LOG_CLI(("%-24s%d\n", "Global High:", glb_hi_cnt)); 10920 LOG_CLI(("%-24s%d\n", "Global Low:", glb_lo_cnt)); 10921 LOG_CLI(("\n")); 10922 soc_alpm_debug_cntr_show(u); 10923 LOG_CLI(("\n\n")); 10924 10925 _free_mem: 10926 if (bktref) { 10927 sal_free(bktref); 10928 bktref = NULL; 10929 } 10930 10931 if (lpm_tbl_ptr) { 10932 soc_cm_sfree(u, lpm_tbl_ptr); 10933 lpm_tbl_ptr = NULL; 10934 } 10935 10936 if (phy_bkt != -1) { 10937 int bank, entmax, tmp; 10938 10939 lpm_mem = _soc_trident2_alpm_bkt_view_get(u, phy_bkt << 2); 10940 LOG_CLI(("Bucket = %4d (View %s)\n", phy_bkt, lpm_mem == -1 ? "INVALID" : 10941 SOC_MEM_NAME(u, lpm_mem))); 10942 LOG_CLI(("------------------------------------------------------------\n")); 10943 LOG_CLI(("Index distribution (* indicates occupied)\n")); 10944 10945 switch (lpm_mem) { 10946 case L3_DEFIP_ALPM_IPV4m: 10947 entmax = 6; 10948 break; 10949 case L3_DEFIP_ALPM_IPV4_1m: 10950 entmax = 4; 10951 break; 10952 case L3_DEFIP_ALPM_IPV6_64m: 10953 entmax = 4; 10954 break; 10955 case L3_DEFIP_ALPM_IPV6_64_1m: 10956 entmax = 3; 10957 break; 10958 case L3_DEFIP_ALPM_IPV6_128m: 10959 entmax = 2; 10960 break; 10961 default: 10962 lpm_mem = L3_DEFIP_ALPM_IPV4m; 10963 entmax = 6; 10964 break; 10965 } 10966 10967 for (bank = 0; bank < 4; bank++) { 10968 if (!(bnkbits & (1 << bank))) { 10969 continue; 10970 } 10971 10972 LOG_CLI(("Bank%d: ", bank)); 10973 for (i = 0; i < entmax; i++) { 10974 int rv1; 10975 tmp = (_shr_popcount(bnkbits) + 1) / 2; 10976 j = (i << (tmp + alpm_bkt_bits)) | 10977 (phy_bkt << tmp) | bank; 10978 rv1 = _soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY, j, e); 10979 if (rv1 == 0 && 10980 soc_mem_field32_get(u, lpm_mem, e, VALIDf)) { 10981 tmp = 1; 10982 } else { 10983 tmp = 0; 10984 } 10985 if (tmp) { 10986 LOG_CLI(("%d(*) ", j)); 10987 } else { 10988 LOG_CLI(("%d( ) ", j)); 10989 } 10990 } 10991 LOG_CLI(("\n")); 10992 } 10993 } 10994 10995 LOG_CLI(("\n")); 10996 if (index != -1) { 10997 int log_bkt; 10998 LOG_CLI(("Index = %8d\n", index)); 10999 LOG_CLI(("------------------------------------------------------------\n")); 11000 lpm_mem = _soc_trident2_alpm_bkt_view_get(u, index); 11001 LOG_CLI(("%-24s%s\n", "Type", lpm_mem == -1 ? "INVALID" : 11002 SOC_MEM_NAME(u, lpm_mem))); 11003 LOG_CLI(("%-24s%d\n", "Bucket:", (index >> 2) & 0x3fff)); 11004 LOG_CLI(("%-24s%d\n", "Bank:", index & (_shr_popcount(bnkbits) - 1))); 11005 log_bkt = (_shr_popcount(bnkbits) + 1) / 2 + alpm_bkt_bits; 11006 LOG_CLI(("%-24s%d\n", "Entry:", index >> log_bkt)); 11007 LOG_CLI(("\n")); 11008 } 11009 11010 return rv; 11011 } 11012 11013 /* 11014 * Function: 11015 * soc_alpm_lpm_sw_dump 11016 * Purpose: 11017 * Displays FB LPM information maintained by software. 11018 * Parameters: 11019 * unit - Device unit number 11020 * Returns: 11021 * None 11022 */ 11023 void 11024 soc_alpm_lpm_sw_dump(int unit) 11025 { 11026 soc_alpm_lpm_state_p lpm_state; 11027 int i, j; 11028 alpm_pivot_t *pivot_pyld = NULL; 11029 _soc_alpm_lpm_hash_t *hash; 11030 int idx; 11031 11032 /* Dump v4/v6 lpm state */ 11033 LOG_CLI((BSL_META_U(unit, "V4 LPM STATE DUMP.\n"))); 11034 lpm_state = soc_alpm_lpm_state[unit]; 11035 11036 if (lpm_state != NULL) { 11037 for (i = 0; i < ALPM_MAX_PFX_ENTRIES; i++) { 11038 if (lpm_state[i].vent != 0) { 11039 LOG_CLI((BSL_META_U(unit, "Prefix %d\n"), i)); 11040 LOG_CLI((BSL_META_U(unit, " Start : %d\n"), lpm_state[i].start)); 11041 LOG_CLI((BSL_META_U(unit, " End : %d\n"), lpm_state[i].end)); 11042 LOG_CLI((BSL_META_U(unit, " Prev : %d\n"), lpm_state[i].prev)); 11043 LOG_CLI((BSL_META_U(unit, " Next : %d\n"), lpm_state[i].next)); 11044 LOG_CLI((BSL_META_U(unit, " Valid : %d\n"), lpm_state[i].vent)); 11045 LOG_CLI((BSL_META_U(unit, " Free : %d\n"), lpm_state[i].fent)); 11046 } 11047 } 11048 } 11049 LOG_CLI((BSL_META_U(unit, "V4 LPM STATE DUMP DONE.\n\n"))); 11050 11051 /* Dump LPM HASH table */ 11052 LOG_CLI((BSL_META_U(unit, "LPM HASH TABLE DUMP.\n"))); 11053 hash = SOC_ALPM_LPM_STATE_HASH(unit); 11054 for(idx = 0; idx < hash->index_count; idx++) { 11055 j = 0; 11056 if (hash->table[idx] != TD2_ALPM_HASH_INDEX_NULL) { 11057 LOG_CLI(( 11058 BSL_META_U(unit, "\nhash_idx = 0x%04x Data = 0x%04x"), 11059 idx, hash->table[idx])); 11060 } 11061 i = hash->table[idx]; 11062 while ((i != TD2_ALPM_HASH_INDEX_NULL) && (j++ < hash->entry_count)) { 11063 if ((j - 1) % 8 == 0) { 11064 LOG_CLI((BSL_META_U(unit, "\nlink_idx ="))); 11065 } 11066 LOG_CLI((BSL_META_U(unit, " 0x%04x"), i)); 11067 i = hash->link_table[i & TD2_ALPM_HASH_INDEX_MASK]; 11068 } 11069 } 11070 LOG_CLI((BSL_META_U(unit, "\nLPM HASH TABLE DUMP DONE.\n\n"))); 11071 11072 /* Dump TCAM pivot table */ 11073 LOG_CLI((BSL_META_U(unit, "TCAM PIVOT DUMP.\n"))); 11074 for(idx = 0; idx < MAX_PIVOT_COUNT; idx++) { 11075 /* Get TCAM pivot */ 11076 pivot_pyld = ALPM_TCAM_PIVOT(unit, idx); 11077 if (NULL == pivot_pyld) { 11078 continue; 11079 } 11080 if (PIVOT_BUCKET_HANDLE(pivot_pyld) == NULL) { 11081 continue; 11082 } 11083 11084 /* Get bucket trie from pivot */ 11085 LOG_CLI(( 11086 BSL_META_U(unit, "tcam_idex = 0x%04x\n"), pivot_pyld->tcam_index)); 11087 LOG_CLI((BSL_META_U(unit, " len = 0x%02x\t"), pivot_pyld->len)); 11088 LOG_CLI((BSL_META_U(unit, "bpm_len = 0x%02x\t"), pivot_pyld->bpm_len)); 11089 LOG_CLI(( 11090 BSL_META_U(unit, "bkt_idx = 0x%04x\n"), 11091 PIVOT_BUCKET_INDEX(pivot_pyld))); 11092 LOG_CLI(( 11093 BSL_META_U(unit, " vrf = 0x%04x\t"), PIVOT_BUCKET_VRF(pivot_pyld))); 11094 LOG_CLI(( 11095 BSL_META_U(unit, "v6 = 0x%x\t"), PIVOT_BUCKET_IPV6(pivot_pyld))); 11096 LOG_CLI((BSL_META_U(unit, "Key : {"))); 11097 if (pivot_pyld->len < 32) { 11098 LOG_CLI(( 11099 BSL_META_U(unit, "0x%x/%d"), 11100 pivot_pyld->key[0], pivot_pyld->len)); 11101 } else { 11102 for (i=0; i < (((pivot_pyld->len)/32) + 1); i++) 11103 LOG_CLI((BSL_META_U(unit, " 0x%x"), pivot_pyld->key[i])); 11104 LOG_CLI((BSL_META_U(unit, "/%d"), pivot_pyld->len)); 11105 } 11106 LOG_CLI((BSL_META_U(unit, "}\n"))); 11107 } 11108 LOG_CLI((BSL_META_U(unit, "TCAM PIVOT DUMP DONE.\n\n"))); 11109 11110 /* Print VRF count/default route infomation */ 11111 LOG_CLI((BSL_META_U(unit, "VRF ROUTE DUMP.\n"))); 11112 for (idx = 0; idx < (SOC_VRF_MAX(unit) + 2); idx++) { 11113 if (alpm_vrf_handle[unit][idx].count_v4 != 0) { 11114 LOG_CLI(( 11115 BSL_META_U(unit, "V4-32 VRF = %d, Routes = %d Default Route:\n"), 11116 idx, alpm_vrf_handle[unit][idx].count_v4)); 11117 if (VRF_TRIE_DEFAULT_ROUTE_IPV4(unit, idx)) { 11118 soc_mem_entry_dump(unit, L3_DEFIPm, 11119 VRF_TRIE_DEFAULT_ROUTE_IPV4(unit, idx), 11120 BSL_LSS_CLI); 11121 } 11122 } 11123 11124 if (alpm_vrf_handle[unit][idx].count_v6_64 !=0) { 11125 LOG_CLI(( 11126 BSL_META_U(unit, "V6-64 VRF = %d, Routes = %d Default Route:\n"), 11127 idx, alpm_vrf_handle[unit][idx].count_v6_64)); 11128 if (VRF_TRIE_DEFAULT_ROUTE_IPV6(unit, idx)) { 11129 soc_mem_entry_dump(unit, L3_DEFIPm, 11130 VRF_TRIE_DEFAULT_ROUTE_IPV6(unit, idx), 11131 BSL_LSS_CLI); 11132 } 11133 } 11134 11135 if (alpm_vrf_handle[unit][idx].count_v6_128 != 0) { 11136 LOG_CLI(( 11137 BSL_META_U(unit, "V6-128 VRF = %d, Routes = %d Default Route:\n"), 11138 idx, alpm_vrf_handle[unit][idx].count_v6_128)); 11139 if (VRF_TRIE_DEFAULT_ROUTE_IPV6_128(unit, idx)) { 11140 soc_mem_entry_dump(unit, L3_DEFIP_PAIR_128m, 11141 VRF_TRIE_DEFAULT_ROUTE_IPV6_128(unit, idx), 11142 BSL_LSS_CLI); 11143 } 11144 } 11145 } 11146 LOG_CLI((BSL_META_U(unit, "VRF ROUTE DUMP DONE.\n"))); 11147 11148 return; 11149 } 11150 11151 /* 11152 * Function: 11153 * soc_alpm_bucket_sw_dump 11154 * Purpose: 11155 * Displays ALPM bucket information maintained by software. 11156 * Parameters: 11157 * unit - Device unit number 11158 * Returns: 11159 * None 11160 */ 11161 void 11162 soc_alpm_bucket_sw_dump(int unit) 11163 { 11164 int i = 0, bkt= 0, used = 0; 11165 soc_mem_t lpm_mem; 11166 11167 LOG_CLI((BSL_META_U(unit, "\n"))); 11168 11169 LOG_CLI((BSL_META_U(unit, 11170 "=================================================\n"))); 11171 LOG_CLI((BSL_META_U(unit, 11172 " %s[%s]\n"), "VRF Route bucket idx", "mem_view")); 11173 LOG_CLI((BSL_META_U(unit, 11174 "=================================================\n"))); 11175 11176 for (i = 0; i < SOC_ALPM_BUCKET_COUNT(unit); i++) { 11177 SHR_BITTEST_RANGE(SOC_ALPM_BUCKET_BMAP(unit), i, 1, used); 11178 if (0 != used) { 11179 lpm_mem = _soc_trident2_alpm_bkt_view_get(unit, i << 2); 11180 11181 LOG_CLI(( 11182 BSL_META_U(unit, " 0x%04x[%24s]\n"), 11183 i, lpm_mem == -1 ? "INVALID" : SOC_MEM_NAME(unit, lpm_mem))); 11184 bkt++; 11185 } 11186 } 11187 11188 if (bkt == 0) { 11189 LOG_CLI((BSL_META_U(unit, "- None -\n"))); 11190 } 11191 11192 return; 11193 } 11194 11195 11196 #ifndef BCM_SW_STATE_DUMP_DISABLE 11197 /* 11198 * Function: 11199 * soc_alpm_sw_dump 11200 * Purpose: 11201 * Displays ALPM state maintained by software. 11202 * Parameters: 11203 * unit - Device unit number 11204 * Returns: 11205 * None 11206 */ 11207 void 11208 soc_alpm_sw_dump(int unit) 11209 { 11210 LOG_CLI((BSL_META_U(unit, "\n ALPM Info -\n"))); 11211 11212 soc_alpm_lpm_sw_dump(unit); 11213 11214 soc_alpm_bucket_sw_dump(unit); 11215 11216 return; 11217 } 11218 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 11219 11220 /* 11221 * Function: 11222 * _soc_alpm_sanity_check 11223 * Purpose: 11224 * Sanity check for ALPM with L3_DEFIP 11225 * Parameters: 11226 * u - Device unit 11227 * min - Min index of L3_DEFIP 11228 * max - Max index of L3_DEFIP 11229 * check_sw - Check software 11230 * bkt_ptr_arr - bucket ptr array 11231 * Returns: 11232 * SOC_E_XXX defined in error.h 11233 */ 11234 STATIC int 11235 _soc_alpm_sanity_check(int u, int min, int max, int check_sw, int *bkt_ptr_arr) 11236 { 11237 int rv = SOC_E_NONE; 11238 int lpm_idx, lpm_idx2, fd_lpm_idx2, alpm_idx, prev_idx = 0; 11239 int i, j, ipv6, prev_v6 = 0, prev_i = 0; 11240 int vrf_id, vrf; 11241 int fd_lpm_idx, fd_bkt_ptr, fd_alpm_idx; 11242 int ent, ent_num, bkt_ptr; 11243 int error1 = 0, error2 = 0, error = 0, success = 0; 11244 int used; 11245 int bpm_len, ip_len; 11246 int trie_bpm_len, default_route; 11247 int alloc_size; 11248 uint32 bank_disable = 0; 11249 uint32 e[SOC_MAX_MEM_FIELD_WORDS] = {0}; 11250 uint32 shadow[SOC_MAX_MEM_FIELD_WORDS] = {0}; 11251 uint32 prefix[5], length; 11252 trie_t *pfx_trie = NULL; 11253 trie_node_t *lpmp = NULL; 11254 payload_t *tmp_pyld = NULL; 11255 uint32 data0[10] = {0}; 11256 uint32 data1[10] = {0}; 11257 char *buffer = NULL; 11258 defip_entry_t *lpm_entry, lpm_entry2, lpm_bmp; 11259 soc_mem_t bkt_mem_type; 11260 soc_mem_t alpm_mem; 11261 int flex; 11262 int bpm_check = 0; 11263 int flex_v6_64; 11264 11265 /* Calculate table size. */ 11266 alloc_size = sizeof(defip_entry_t) * (max - min + 1); 11267 11268 /* Allocate memory buffer. */ 11269 buffer = soc_cm_salloc(u, alloc_size, "lpm_tbl"); 11270 if (buffer == NULL) { 11271 return (SOC_E_MEMORY); 11272 } 11273 11274 /* Reset allocated buffer. */ 11275 sal_memset(buffer, 0, alloc_size); 11276 11277 SOC_ALPM_LPM_LOCK(u); 11278 11279 /* Read table to the buffer. */ 11280 if (soc_mem_read_range(u, L3_DEFIPm, MEM_BLOCK_ANY, 11281 min, max, buffer) < 0) { 11282 soc_cm_sfree(u, buffer); 11283 SOC_ALPM_LPM_UNLOCK(u); 11284 return (SOC_E_INTERNAL); 11285 } 11286 11287 for (lpm_idx = min; lpm_idx <= max; lpm_idx++) { 11288 lpm_entry = soc_mem_table_idx_to_pointer(u, L3_DEFIPm, 11289 defip_entry_t *, buffer, 11290 lpm_idx - min); 11291 11292 ipv6 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, MODE0f); 11293 11294 for (i = 0; i <= (ipv6 ? 0 : 1); i++) { 11295 if (error1) { 11296 LOG_ERROR(BSL_LS_SOC_ALPM, 11297 (BSL_META_U(u, 11298 "\tL3_DEFIP index:[%d,%d] check failed. ipv6 %d error count %d\n"), 11299 prev_idx, prev_i, prev_v6, error1)); 11300 error = 1; 11301 } else if (success) { 11302 LOG_INFO(BSL_LS_SOC_ALPM,(BSL_META_U(u, 11303 "\tL3_DEFIP index:[%d,%d] check passed. ipv6 %d success count %d\n"), 11304 prev_idx, prev_i, prev_v6, success)); 11305 } 11306 error1 = error2 = success = 0; 11307 prev_v6 = ipv6; 11308 prev_idx = lpm_idx; 11309 prev_i = i; 11310 11311 /* cache coherency check */ 11312 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, VALID0f) || 11313 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, VALID1f)) { 11314 defip_entry_t hw_ent, sw_ent; 11315 soc_mem_t cmem = L3_DEFIPm; 11316 sal_memset(&hw_ent, 0, sizeof(hw_ent)); 11317 sal_memset(&sw_ent, 0, sizeof(sw_ent)); 11318 rv = _soc_mem_alpm_read_cache(u, cmem, SOC_BLOCK_ANY, 11319 lpm_idx, &sw_ent); 11320 if (SOC_SUCCESS(rv)) { 11321 rv = soc_mem_read_no_cache(u, 0, cmem, 0, SOC_BLOCK_ANY, 11322 lpm_idx, &hw_ent); 11323 if (SOC_SUCCESS(rv)) { 11324 if (soc_mem_field_valid(u, cmem, EVEN_PARITYf)) { 11325 soc_mem_field32_set(u, cmem, &hw_ent, 11326 EVEN_PARITYf, 0); 11327 soc_mem_field32_set(u, cmem, &sw_ent, 11328 EVEN_PARITYf, 0); 11329 } else if (soc_mem_field_valid(u, cmem, PARITY0f)) { 11330 soc_mem_field32_set(u, cmem, &hw_ent, PARITY0f, 0); 11331 soc_mem_field32_set(u, cmem, &sw_ent, PARITY0f, 0); 11332 soc_mem_field32_set(u, cmem, &hw_ent, PARITY1f, 0); 11333 soc_mem_field32_set(u, cmem, &sw_ent, PARITY1f, 0); 11334 } 11335 soc_mem_field32_set(u, cmem, &hw_ent, HIT0f, 0); 11336 soc_mem_field32_set(u, cmem, &sw_ent, HIT0f, 0); 11337 soc_mem_field32_set(u, cmem, &hw_ent, HIT1f, 0); 11338 soc_mem_field32_set(u, cmem, &sw_ent, HIT1f, 0); 11339 if (sal_memcmp(&sw_ent, &hw_ent, 11340 soc_mem_entry_bytes(u, cmem)) != 0) { 11341 LOG_ERROR(BSL_LS_SOC_ALPM, 11342 (BSL_META_U(u, "\t%s index:[%d], ipv6(%d)" 11343 " cache mismatch\n"), SOC_MEM_NAME(u, cmem), 11344 lpm_idx, ipv6)); 11345 error1 ++; 11346 } 11347 } 11348 } 11349 11350 /* We can just use defip_entry_t because it's always longer 11351 * than aux_entry_t */ 11352 cmem = L3_DEFIP_AUX_TABLEm; 11353 sal_memset(&hw_ent, 0, sizeof(hw_ent)); 11354 sal_memset(&sw_ent, 0, sizeof(sw_ent)); 11355 lpm_idx2 = soc_alpm_physical_idx(u, L3_DEFIPm, lpm_idx, 1); 11356 rv = _soc_mem_alpm_read_cache(u, cmem, SOC_BLOCK_ANY, 11357 lpm_idx2, &sw_ent); 11358 if (SOC_SUCCESS(rv)) { 11359 rv = soc_mem_read_no_cache(u, 0, cmem, 0, SOC_BLOCK_ANY, 11360 lpm_idx2, &hw_ent); 11361 if (SOC_SUCCESS(rv)) { 11362 if (soc_mem_field_valid(u, cmem, EVEN_PARITYf)) { 11363 soc_mem_field32_set(u, cmem, &hw_ent, 11364 EVEN_PARITYf, 0); 11365 soc_mem_field32_set(u, cmem, &sw_ent, 11366 EVEN_PARITYf, 0); 11367 } else if (soc_mem_field_valid(u, cmem, PARITYf)) { 11368 soc_mem_field32_set(u, cmem, &hw_ent, PARITYf, 0); 11369 soc_mem_field32_set(u, cmem, &sw_ent, PARITYf, 0); 11370 } 11371 if (sal_memcmp(&sw_ent, &hw_ent, 11372 soc_mem_entry_bytes(u, cmem)) != 0) { 11373 LOG_ERROR(BSL_LS_SOC_ALPM, 11374 (BSL_META_U(u, "\t%s index:[%d], ipv6(%d)" 11375 " cache mismatch\n"), SOC_MEM_NAME(u, cmem), 11376 lpm_idx2, ipv6)); 11377 error1 ++; 11378 } 11379 } 11380 } 11381 } 11382 11383 if (i == 1) { 11384 soc_alpm_lpm_ip4entry1_to_0(u, lpm_entry, lpm_entry, PRESERVE_HIT); 11385 } 11386 bkt_ptr = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ALG_BKT_PTR0f); 11387 if (!SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, VALID0f)) { 11388 continue; 11389 } 11390 flex = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, ENTRY_VIEW0f); 11391 flex_v6_64 = 0; 11392 if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && ipv6 && flex) { 11393 if (soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f) == 0xFFFFFFFF && 11394 soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f) == 0xFFFFFFFF) { 11395 flex_v6_64 = 1; 11396 } 11397 } 11398 11399 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, GLOBAL_HIGH0f) || 11400 (soc_feature(u, soc_feature_ipmc_defip) && 11401 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, MULTICAST_ROUTE0f)) || 11402 flex_v6_64) { 11403 if (bkt_ptr != 0) { 11404 LOG_ERROR(BSL_LS_SOC_ALPM, 11405 (BSL_META_U(u, "\tWrong bkt_ptr %d\n"), 11406 bkt_ptr)); 11407 error1 ++; 11408 } 11409 continue; 11410 } 11411 if (bkt_ptr == 0) { 11412 LOG_ERROR(BSL_LS_SOC_ALPM, 11413 (BSL_META_U(u, "\tWrong bkt_ptr2 %d\n"), 11414 bkt_ptr)); 11415 error1 ++; 11416 } 11417 11418 j = 0; 11419 data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ECMP0f); 11420 data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ECMP_PTR0f); 11421 data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, NEXT_HOP_INDEX0f); 11422 data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, PRI0f); 11423 data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, RPE0f); 11424 data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, DST_DISCARD0f); 11425 data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, CLASS_ID0f); 11426 11427 /* Check if bucket pointer duplicated */ 11428 if (bkt_ptr_arr) { 11429 if (bkt_ptr_arr[bkt_ptr] == -1) { 11430 bkt_ptr_arr[bkt_ptr] = lpm_idx; 11431 if (SOC_ALPM_V6_SCALE_CHECK(u, ipv6)) { 11432 bkt_ptr_arr[bkt_ptr + 1] = lpm_idx; 11433 } 11434 success ++; 11435 } else { 11436 LOG_ERROR(BSL_LS_SOC_ALPM, 11437 (BSL_META_U(u, "\tConflict bucket pointer %d: " 11438 "was %d now %d\n"), bkt_ptr, 11439 bkt_ptr_arr[bkt_ptr], lpm_idx)); 11440 error1 ++; 11441 } 11442 } 11443 11444 if (ipv6) { 11445 if (flex) { 11446 alpm_mem = L3_DEFIP_ALPM_IPV6_64_1m; 11447 ent_num = ALPM_IPV6_64_BKT_COUNT_FLEX; 11448 } else { 11449 alpm_mem = L3_DEFIP_ALPM_IPV6_64m; 11450 ent_num = ALPM_IPV6_64_BKT_COUNT; 11451 } 11452 } else { 11453 if (flex) { 11454 alpm_mem = L3_DEFIP_ALPM_IPV4_1m; 11455 ent_num = ALPM_IPV4_BKT_COUNT_FLEX; 11456 } else { 11457 alpm_mem = L3_DEFIP_ALPM_IPV4m; 11458 ent_num = ALPM_IPV4_BKT_COUNT; 11459 } 11460 } 11461 if (SOC_ALPM_V6_SCALE_CHECK(u, ipv6)) { 11462 ent_num <<= 1; 11463 } 11464 11465 (void) soc_alpm_lpm_vrf_get(u, lpm_entry, &vrf_id, &vrf); 11466 11467 /* read shadow table for bpm length */ 11468 lpm_idx2 = soc_alpm_physical_idx(u, L3_DEFIPm, lpm_idx, 1); 11469 rv = soc_mem_read(u, L3_DEFIP_AUX_TABLEm, MEM_BLOCK_ANY, 11470 lpm_idx2, shadow); 11471 bpm_len = -1; 11472 bpm_check = 0; 11473 if (SOC_SUCCESS(rv)) { 11474 if (i == 0) { 11475 bpm_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm, 11476 shadow, BPM_LENGTH0f); 11477 ip_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm, 11478 shadow, IP_LENGTH0f); 11479 } else { 11480 bpm_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm, 11481 shadow, BPM_LENGTH1f); 11482 ip_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm, 11483 shadow, IP_LENGTH1f); 11484 } 11485 if (bpm_len > ip_len) { 11486 LOG_ERROR(BSL_LS_SOC_ALPM, 11487 (BSL_META_U(u, "\tAUX Table corrupted\n"))); 11488 error1 ++; 11489 } else { 11490 success ++; 11491 } 11492 11493 bpm_check = 1; 11494 if (bpm_len == 0 && 11495 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, DEFAULT_MISS0f)) { 11496 bpm_check = 0; 11497 } 11498 } 11499 11500 if (bpm_check) { 11501 sal_memcpy(&lpm_bmp, lpm_entry, sizeof(defip_entry_t)); 11502 _soc_alpm_pfx_len_to_mask(u, &lpm_bmp, bpm_len, ipv6); 11503 11504 fd_lpm_idx = fd_bkt_ptr = fd_alpm_idx = -1; 11505 rv = _soc_alpm_find(u, &lpm_bmp, alpm_mem, e, &fd_lpm_idx, 11506 &fd_bkt_ptr, &fd_alpm_idx, FALSE); 11507 11508 if (fd_lpm_idx > 0) { 11509 fd_lpm_idx = soc_alpm_logical_idx(u, L3_DEFIPm, 11510 fd_lpm_idx >> 1, 1); 11511 } 11512 11513 if (SOC_SUCCESS(rv)) { 11514 j = 0; 11515 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, ECMPf); 11516 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, ECMP_PTRf); 11517 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, NEXT_HOP_INDEXf); 11518 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, PRIf); 11519 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, RPEf); 11520 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, DST_DISCARDf); 11521 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, CLASS_IDf); 11522 11523 if (sal_memcmp(data0, data1, sizeof(data0)) != 0) { 11524 LOG_ERROR(BSL_LS_SOC_ALPM, 11525 (BSL_META_U(u, 11526 "\tData mismatch: " 11527 "lpm_idx %d find_lpm_idx %d " 11528 "find_alpm_idx %d find_bkt_ptr %d\n"), 11529 lpm_idx, fd_lpm_idx, 11530 fd_alpm_idx, fd_bkt_ptr)); 11531 error1 ++; 11532 } else { 11533 success ++; 11534 } 11535 } else { 11536 if (rv == SOC_E_NOT_FOUND && 11537 (vrf_id == SOC_L3_VRF_GLOBAL || soc_alpm_mode_get(u))) { 11538 LOG_VERBOSE(BSL_LS_SOC_ALPM, 11539 (BSL_META_U(u, 11540 "\t_soc_alpm_find rv=%d: " 11541 "lpm_idx %d find_lpm_idx %d " 11542 "find_alpm_idx %d find_bkt_ptr %d," 11543 "(Possible: global route or !combined " 11544 "without default)\n"), 11545 rv, lpm_idx, fd_lpm_idx, 11546 fd_alpm_idx, fd_bkt_ptr)); 11547 } else { 11548 LOG_ERROR(BSL_LS_SOC_ALPM, 11549 (BSL_META_U(u, 11550 "\t_soc_alpm_find rv=%d: " 11551 "lpm_idx %d find_lpm_idx %d " 11552 "find_alpm_idx %d find_bkt_ptr %d\n"), 11553 rv, lpm_idx, fd_lpm_idx, 11554 fd_alpm_idx, fd_bkt_ptr)); 11555 error1 ++; 11556 } 11557 } 11558 } 11559 11560 bank_disable = soc_alpm_bank_dis(u, vrf); 11561 /* Traverse bucket */ 11562 for (ent = 0; ent < ent_num; ent++) { 11563 (void) _soc_alpm_mem_index(u, alpm_mem, bkt_ptr, ent, bank_disable, &alpm_idx); 11564 11565 rv = _soc_mem_alpm_read(u, alpm_mem, 11566 MEM_BLOCK_ANY, alpm_idx, e); 11567 if (SOC_FAILURE(rv)) { 11568 continue; 11569 } 11570 11571 if (!soc_mem_field32_get(u, alpm_mem, e, VALIDf)) { 11572 continue; 11573 } 11574 11575 (void) _soc_alpm_lpm_ent_init(u, e, alpm_mem, ipv6, vrf_id, 11576 bkt_ptr, 0, &lpm_entry2, 0); 11577 11578 if (check_sw) { 11579 rv = _soc_alpm_sw_prefix_check(u, alpm_mem, ipv6, &lpm_entry2, vrf_id, vrf); 11580 if (SOC_FAILURE(rv)) { 11581 error1 ++; 11582 error2 ++; 11583 LOG_ERROR(BSL_LS_SOC_ALPM, 11584 (BSL_META_U(u, 11585 "_soc_alpm_sw_prefix_check rv=%d: v6 = %d, vrf_id = %d, vrf = %d\n"), 11586 rv, ipv6, vrf_id, vrf)); 11587 } 11588 } 11589 11590 fd_lpm_idx2 = fd_lpm_idx = fd_bkt_ptr = fd_alpm_idx = -1; 11591 rv = _soc_alpm_find(u, &lpm_entry2, alpm_mem, e, 11592 &fd_lpm_idx, &fd_bkt_ptr, 11593 &fd_alpm_idx, FALSE); 11594 11595 if (SOC_SUCCESS(rv)) { 11596 fd_lpm_idx2 = soc_alpm_logical_idx(u, 11597 L3_DEFIPm, fd_lpm_idx >> 1, 1); 11598 } 11599 11600 if (SOC_FAILURE(rv) || 11601 fd_bkt_ptr != bkt_ptr || 11602 fd_lpm_idx2 != lpm_idx || 11603 fd_lpm_idx >> 1 != lpm_idx2 || /* for map remap */ 11604 fd_alpm_idx != alpm_idx) { 11605 11606 error1 ++; 11607 error2 ++; 11608 LOG_ERROR(BSL_LS_SOC_ALPM, 11609 (BSL_META_U(u, 11610 "\t_soc_alpm_find2 rv=%d: " 11611 "fl [%d,%d] fa %d fb %d " 11612 "l [%d,%d] a %d b %d\n"), 11613 rv, 11614 fd_lpm_idx >> 1, fd_lpm_idx2, fd_alpm_idx, fd_bkt_ptr, 11615 lpm_idx2, lpm_idx, alpm_idx, bkt_ptr)); 11616 } 11617 } 11618 if (error2 == 0) { 11619 success ++; 11620 } 11621 11622 if (!check_sw) { 11623 continue; 11624 } 11625 11626 /* 11627 * Check hardware table above. 11628 * Check software table below. 11629 */ 11630 11631 /* lpm hash */ 11632 11633 #ifdef FB_LPM_HASH_SUPPORT 11634 rv = LPM_HASH_VERIFY(u, lpm_entry, 11635 ipv6 ? lpm_idx : ((lpm_idx << 1) + i)); 11636 if (SOC_FAILURE(rv)) { 11637 LOG_ERROR(BSL_LS_SOC_ALPM, 11638 (BSL_META_U(u, "\tLPM Hash check failed: rv %d " 11639 "lpm_idx %d\n"), 11640 rv, lpm_idx)); 11641 error1 ++; 11642 } else { 11643 success ++; 11644 } 11645 #endif 11646 11647 /* bucket bitmap */ 11648 rv = alpm_bucket_is_assigned(u, bkt_ptr, ipv6, &used); 11649 if (SOC_FAILURE(rv)) { 11650 LOG_ERROR(BSL_LS_SOC_ALPM, 11651 (BSL_META_U(u, "\tInvalid bucket pointer %d " 11652 "detected, in memory %s index %d\n"), bkt_ptr, 11653 SOC_MEM_NAME(u, L3_DEFIPm), lpm_idx)); 11654 error1 ++; 11655 } else if (used == 0) { 11656 /* If bucket was already freed */ 11657 LOG_ERROR(BSL_LS_SOC_ALPM, 11658 (BSL_META_U(u, "\tFreed bucket pointer %d " 11659 "detected, in memory %s index %d\n"), bkt_ptr, 11660 SOC_MEM_NAME(u, L3_DEFIPm), lpm_idx)); 11661 error1 ++; 11662 } else { 11663 success ++; 11664 } 11665 11666 /* bucket view map */ 11667 bkt_mem_type = _soc_trident2_alpm_bkt_view_get(u, bkt_ptr << 2); 11668 if (alpm_mem != bkt_mem_type) { 11669 LOG_ERROR(BSL_LS_SOC_ALPM, 11670 (BSL_META_U(u, "\tMismatched alpm view " 11671 "in bucket %d, expected %s, was %s\n"), bkt_ptr, 11672 SOC_MEM_NAME(u, alpm_mem), 11673 SOC_MEM_NAME(u, bkt_mem_type))); 11674 error1 ++; 11675 } else { 11676 success ++; 11677 } 11678 11679 /* Check bpm len information */ 11680 rv = _alpm_prefix_create(u, lpm_entry, prefix, 11681 &length, &default_route); 11682 if (SOC_SUCCESS(rv)) { 11683 if (ipv6) { 11684 pfx_trie = VRF_PREFIX_TRIE_IPV6(u, vrf); 11685 } else { 11686 pfx_trie = VRF_PREFIX_TRIE_IPV4(u, vrf); 11687 } 11688 lpmp = NULL; 11689 if (pfx_trie) { 11690 rv = trie_find_lpm(pfx_trie, prefix, length, &lpmp); 11691 } 11692 if (SOC_SUCCESS(rv) && lpmp){ 11693 tmp_pyld = (payload_t *) lpmp; 11694 if (tmp_pyld->bkt_ptr != NULL) { 11695 trie_bpm_len = ((payload_t *)(tmp_pyld->bkt_ptr))->len; 11696 if (trie_bpm_len != bpm_len) { 11697 LOG_ERROR(BSL_LS_SOC_ALPM, 11698 (BSL_META_U(u, "\tBPM len mismatch: lpm_idx %d" 11699 " alpm_idx %d bpm_len %d trie_bpm_len %d\n"), 11700 lpm_idx, alpm_idx, bpm_len, trie_bpm_len)); 11701 error1 ++; 11702 } else { 11703 success ++; 11704 } 11705 } else { 11706 success ++; 11707 } 11708 } else { 11709 LOG_ERROR(BSL_LS_SOC_ALPM, 11710 (BSL_META_U(u, "\ttrie_find_lpm failed: " 11711 "lpm_idx %d alpm_idx %d lpmp %p\n"), 11712 lpm_idx, alpm_idx, lpmp)); 11713 error1 ++; 11714 } 11715 } else { 11716 LOG_ERROR(BSL_LS_SOC_ALPM, 11717 (BSL_META_U(u, "\tPrefix creating failed: " 11718 "lpm_idx %d alpm_idx %d\n" ), lpm_idx, alpm_idx)); 11719 error1 ++; 11720 } 11721 } 11722 } 11723 11724 if (error1) { 11725 LOG_ERROR(BSL_LS_SOC_ALPM, 11726 (BSL_META_U(u, 11727 "\tL3_DEFIP index:[%d,%d] check failed. ipv6 %d error count %d\n"), 11728 prev_idx, prev_i, prev_v6, error1)); 11729 error = 1; 11730 } else if (success) { 11731 LOG_INFO(BSL_LS_SOC_ALPM,(BSL_META_U(u, 11732 "\tL3_DEFIP index:[%d,%d] check passed. ipv6 %d success count %d\n"), 11733 prev_idx, prev_i, prev_v6, success)); 11734 } 11735 11736 SOC_ALPM_LPM_UNLOCK(u); 11737 soc_cm_sfree(u, buffer); 11738 11739 return (error ? SOC_E_FAIL: SOC_E_NONE); 11740 } 11741 11742 extern int _soc_alpm_128_sanity_check(int u, int min, int max, 11743 int check_sw, int *bkt_ptr_arr); 11744 11745 /* 11746 * Function: 11747 * soc_alpm_sanity_check 11748 * Purpose: 11749 * Sanity check for ALPM 11750 * Parameters: 11751 * u - Device unit 11752 * mem - L3_DEFIP/L3_DEFIP_PAIR_128 memory 11753 * index - -2 indicates full check to both table, 11754 * -1 indicates full check to given table 11755 * other indicates single entry check to given table 11756 * check_sw - Check SW tables as well. 11757 */ 11758 int 11759 soc_alpm_sanity_check(int u, soc_mem_t mem, int index, int check_sw) 11760 { 11761 int rv = SOC_E_NONE; 11762 int rv2 = SOC_E_NONE; 11763 int index_min = -1, index_max = -1; 11764 int index_min2 = -1, index_max2 = -1; 11765 int *bkt_ptr_arr = NULL; 11766 #ifdef ALPM_SANITY_SENSITIVE 11767 int i; 11768 soc_mem_t bkt_view; 11769 #endif 11770 11771 if ((mem == L3_DEFIPm || index == -2) && 11772 soc_mem_index_max(u, L3_DEFIPm) != -1) { 11773 index_min = soc_mem_index_min(u, L3_DEFIPm); 11774 index_max = soc_mem_index_max(u, L3_DEFIPm); 11775 /* Don't check urpf */ 11776 if (SOC_URPF_STATUS_GET(u)) { 11777 index_max >>= 1; 11778 } 11779 if (index < -2 || index > index_max) { 11780 return SOC_E_PARAM; 11781 } 11782 if (index >= index_min && index <= index_max) { 11783 index_min = index; 11784 index_max = index; 11785 } 11786 } 11787 11788 if ((mem == L3_DEFIP_PAIR_128m || index == -2) && 11789 soc_mem_index_max(u, L3_DEFIP_PAIR_128m) != -1) { 11790 index_min2 = soc_mem_index_min(u, L3_DEFIP_PAIR_128m); 11791 index_max2 = soc_mem_index_max(u, L3_DEFIP_PAIR_128m); 11792 /* Don't check urpf */ 11793 if (SOC_URPF_STATUS_GET(u)) { 11794 index_max2 >>= 1; 11795 } 11796 if (index < -2 || index > index_max2) { 11797 return SOC_E_PARAM; 11798 } 11799 if (index >= index_min2 && index <= index_max2) { 11800 index_min2 = index; 11801 index_max2 = index; 11802 } 11803 } 11804 11805 if (index_max == -1 && index_max2 == -1) { 11806 return SOC_E_PARAM; 11807 } 11808 11809 L3_LOCK(u); 11810 bkt_ptr_arr = sal_alloc(sizeof(int) * MAX_PIVOT_COUNT, "Bucket ptr array"); 11811 if (bkt_ptr_arr == NULL) { 11812 return SOC_E_MEMORY; 11813 } 11814 sal_memset(bkt_ptr_arr, 0xff, sizeof(int) * MAX_PIVOT_COUNT); 11815 11816 if (index_max != -1) { 11817 LOG_CLI(("Processing ALPM sanity check L3_DEFIP " 11818 "from index:%d to index:%d\n", 11819 index_min, index_max)); 11820 rv = _soc_alpm_sanity_check(u, index_min, index_max, check_sw, bkt_ptr_arr); 11821 LOG_CLI(("ALPM sanity check L3_DEFIP %s. \n\n", 11822 SOC_SUCCESS(rv) ? "passed" : "failed")); 11823 } 11824 11825 if (index_max2 != -1) { 11826 LOG_CLI(("Processing ALPM sanity check L3_DEFIP_PAIR_128 " 11827 "from index:%d to index:%d\n", 11828 index_min2, index_max2)); 11829 rv2 = _soc_alpm_128_sanity_check(u, index_min2, index_max2, check_sw, bkt_ptr_arr); 11830 LOG_CLI(("ALPM sanity check L3_DEFIP_PAIR_128 %s. \n", 11831 SOC_SUCCESS(rv2) ? "passed" : "failed")); 11832 } 11833 11834 #ifdef ALPM_SANITY_SENSITIVE 11835 /* This check is very sensitive, turn it off for now. */ 11836 /* In case full check to both table, the bkt ptr is fully collected */ 11837 if (index == -2 && SOC_SUCCESS(rv) && SOC_SUCCESS(rv2)) { 11838 for (i = 0; i < MAX_PIVOT_COUNT; i++) { 11839 if (bkt_ptr_arr[i] != -1) { 11840 continue; 11841 } 11842 bkt_view = _soc_trident2_alpm_bkt_view_get(u, i << 2); 11843 if (bkt_view != INVALIDm){ 11844 LOG_ERROR(BSL_LS_SOC_ALPM, 11845 (BSL_META_U(u, 11846 "\tBucket view corrupted: bkt_ptr %d, view %s.\n"), 11847 i, SOC_MEM_NAME(u, bkt_view))); 11848 } 11849 } 11850 } 11851 #endif 11852 11853 sal_free(bkt_ptr_arr); 11854 L3_UNLOCK(u); 11855 return SOC_SUCCESS(rv) ? rv2: rv; 11856 } 11857 11858 11859 /* Get entry No. per bucket based on various setting */ 11860 int 11861 _soc_alpm_bkt_entry_cnt(int u, soc_mem_t mem) 11862 { 11863 int bkt_cnt = 0; 11864 int v6; 11865 11866 switch (mem) { 11867 case L3_DEFIP_ALPM_IPV4m: 11868 bkt_cnt = ALPM_IPV4_BKT_COUNT; 11869 v6 = 0; 11870 break; 11871 case L3_DEFIP_ALPM_IPV4_1m: 11872 bkt_cnt = ALPM_IPV4_BKT_COUNT_FLEX; 11873 v6 = 0; 11874 break; 11875 case L3_DEFIP_ALPM_IPV6_64m: 11876 bkt_cnt = ALPM_IPV6_64_BKT_COUNT; 11877 v6 = 1; 11878 break; 11879 case L3_DEFIP_ALPM_IPV6_64_1m: 11880 bkt_cnt = ALPM_IPV6_64_BKT_COUNT_FLEX; 11881 v6 = 1; 11882 break; 11883 case L3_DEFIP_ALPM_IPV6_128m: 11884 bkt_cnt = ALPM_IPV6_128_BKT_COUNT; 11885 v6 = 1; 11886 break; 11887 default: 11888 return SOC_E_INTERNAL; 11889 } 11890 11891 if (SOC_ALPM_V6_SCALE_CHECK(u, v6)) { 11892 bkt_cnt <<= 1; 11893 } 11894 11895 if (soc_alpm_mode_get(u) == SOC_ALPM_MODE_PARALLEL && 11896 SOC_URPF_STATUS_GET(u)) { 11897 bkt_cnt >>= 1; 11898 } 11899 11900 return bkt_cnt; 11901 } 11902 11903 /* 11904 * Function: 11905 * soc_alpm_route_capacity_get 11906 * Purpose: 11907 * Get the capacity for ALPM from tables: 11908 * L3_DEFIP_ALPM_IPV4, L3_DEFIP_ALPM_IPV6_64, L3_DEFIP_ALPM_IPV6_128 11909 * L3_DEFIP, L3_DEFIP_PAIR_128 11910 * Parameters: 11911 * unit - Device unit 11912 * route_type - 0: v4, 1: v6-64, 2: v6-128 11913 * cap_type - 0: max capacity, 1: min guaranteed capacity 11914 * max_entries - Maximum result returned. 11915 * min_entries - Minimum result returned. 11916 */ 11917 int 11918 soc_alpm_route_capacity_get(int unit, soc_mem_t mem, 11919 int *max_entries, int *min_entries) 11920 { 11921 int rv = SOC_E_NONE; 11922 int num_ent, num_pivot, num_bkt_max, num_bkt_min; 11923 11924 if (max_entries == NULL && min_entries == NULL) { 11925 return SOC_E_PARAM; 11926 } 11927 11928 switch (mem) { 11929 case L3_DEFIP_ALPM_IPV4m: 11930 case L3_DEFIP_ALPM_IPV4_1m: 11931 num_ent = soc_mem_index_count(unit, L3_DEFIPm) * 2; 11932 break; 11933 case L3_DEFIP_ALPM_IPV6_64m: 11934 case L3_DEFIP_ALPM_IPV6_64_1m: 11935 num_ent = soc_mem_index_count(unit, L3_DEFIP_PAIR_128m); 11936 if (num_ent == 0) { 11937 num_ent = soc_mem_index_count(unit, L3_DEFIPm); 11938 } 11939 break; 11940 case L3_DEFIP_ALPM_IPV6_128m: 11941 num_ent = soc_mem_index_count(unit, L3_DEFIP_PAIR_128m); 11942 break; 11943 default: 11944 return SOC_E_UNAVAIL; 11945 } 11946 11947 num_pivot = num_ent >> SOC_URPF_STATUS_GET(unit); 11948 num_bkt_max = _soc_alpm_bkt_entry_cnt(unit, mem); 11949 num_bkt_min = num_bkt_max / 2; 11950 11951 if (max_entries != NULL) { 11952 *max_entries = num_pivot * num_bkt_max; 11953 } 11954 if (min_entries != NULL) { 11955 *min_entries = num_pivot * num_bkt_min; 11956 } 11957 11958 return rv; 11959 } 11960 11961 #endif /* ALPM_ENABLE */