alpm_th.c (502564B)
1 /* 2 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 3 * 4 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 5 * 6 * File: alpm.c 7 * Purpose: Tomahawk 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 <soc/tomahawk.h> 22 #include <soc/trident3.h> 23 #include <soc/apache.h> 24 #include <shared/bsl.h> 25 #include <soc/l3x.h> 26 27 #ifdef ALPM_ENABLE 28 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) 29 #include <shared/util.h> 30 #include <shared/l3.h> 31 #include <soc/alpm.h> 32 #include <soc/esw/alpm_int.h> 33 #include <soc/esw/trie.h> 34 #include <soc/esw/alpm_trie_v6.h> 35 36 #define ALPM_REPART_DEBUG 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 /* Add suport for Extended */ 57 #define SOC_ALPM_ENTRY_BUF_128(_v6_, _mem_, _buf_, _v4ent_, _v6ent_) \ 58 _buf_ = ((uint32 *) &(_v6ent_)) 59 60 /* this is a left shift of the prefix by 32/64 - length and convert to 61 brcm order of ip words */ 62 #define ALPM_TRIE_TO_NORMAL_IP(prefix, length, v6) \ 63 do {\ 64 if (!(v6)) {\ 65 prefix[0] = SHR_SHIFT_LEFT(prefix[1], 32 - length);\ 66 prefix[1] = 0;\ 67 } else {\ 68 int macro_pfx_shift = 64 - length;\ 69 int macro_tmp;\ 70 if (macro_pfx_shift < 32) {\ 71 /* get upper half shifted */\ 72 macro_tmp = prefix[3] << macro_pfx_shift;\ 73 /* isolate shifted stuff off lower half */\ 74 macro_tmp |= SHR_SHIFT_RIGHT(prefix[4], 32 - macro_pfx_shift);\ 75 /* swap the order of words */\ 76 prefix[0] = prefix[4] << macro_pfx_shift;\ 77 prefix[1] = macro_tmp;\ 78 prefix[2] = prefix[3] = prefix[4] = 0;\ 79 } else {\ 80 prefix[1] = SHR_SHIFT_LEFT(prefix[4], macro_pfx_shift - 32);\ 81 prefix[0] = prefix[2] = prefix[3] = prefix[4] = 0;\ 82 }\ 83 }\ 84 } while (0) 85 86 #define SOC_ALPM_MOVE_PIVOT_HALF(u, v1, src, dst)\ 87 do {\ 88 int _src = soc_th_alpm_physical_idx((u), L3_DEFIPm, (src), 1)*2; \ 89 int _dst = soc_th_alpm_physical_idx((u), L3_DEFIPm, (dst), 1)*2; \ 90 if ((v1)) {\ 91 _src++;\ 92 }\ 93 ALPM_TCAM_PIVOT((u), _dst) = ALPM_TCAM_PIVOT((u), _src);\ 94 if (ALPM_TCAM_PIVOT((u), _dst)) { \ 95 PIVOT_TCAM_INDEX(ALPM_TCAM_PIVOT((u), _dst)) = _dst;\ 96 SOC_ALPM_BU_PIVOT_IDX_UPDATE(u, _dst); \ 97 } \ 98 ALPM_TCAM_PIVOT((u), _src) = NULL;\ 99 } while (0) 100 101 /* used for moving either 2 v4 entries or 1 v6 entry. */ 102 #define SOC_ALPM_MOVE_PIVOT_FULL(u, src, dst)\ 103 do {\ 104 int _src = soc_th_alpm_physical_idx((u), L3_DEFIPm, (src), 1);\ 105 int _dst = soc_th_alpm_physical_idx((u), L3_DEFIPm, (dst), 1);\ 106 /* Track full-entry move */\ 107 ALPM_TCAM_PIVOT(u, _dst<<1) = ALPM_TCAM_PIVOT(u, _src<<1);\ 108 ALPM_TCAM_PIVOT(u, (_dst<<1) + 1) = \ 109 ALPM_TCAM_PIVOT(u, (_src<<1) + 1);\ 110 if (ALPM_TCAM_PIVOT((u), _dst<<1)) { \ 111 PIVOT_TCAM_INDEX(ALPM_TCAM_PIVOT((u), _dst<<1)) = _dst<<1;\ 112 SOC_ALPM_BU_PIVOT_IDX_UPDATE(u, (_dst<<1)); \ 113 } \ 114 if (ALPM_TCAM_PIVOT((u), (_dst<<1) + 1)) { \ 115 PIVOT_TCAM_INDEX(ALPM_TCAM_PIVOT((u), (_dst<<1) + 1)) = \ 116 (_dst<<1) + 1;\ 117 SOC_ALPM_BU_PIVOT_IDX_UPDATE(u, (_dst<<1) + 1); \ 118 } \ 119 ALPM_TCAM_PIVOT(u, _src<<1) = NULL;\ 120 ALPM_TCAM_PIVOT(u, (_src<<1) + 1) = NULL;\ 121 } while (0) 122 123 #define FB_LPM_HASH_SUPPORT 1 124 125 typedef struct soc_th_alpm_lpm_state_s { 126 int start; /* start index for this prefix length */ 127 int end; /* End index for this prefix length */ 128 int prev; /* Previous (Lo to Hi) prefix length with non zero entry count*/ 129 int next; /* Next (Hi to Lo) prefix length with non zero entry count */ 130 int vent; /* valid entries */ 131 int fent; /* free entries */ 132 } soc_th_alpm_lpm_state_t, *soc_th_alpm_lpm_state_p; 133 134 /* Can move to SOC Control structures */ 135 static soc_th_alpm_lpm_state_p soc_th_alpm_lpm_state[SOC_MAX_NUM_DEVICES]; 136 137 #define ALPM_IPV6_PFX_ZERO 33 138 #define ALPM_MAX_VRF_PFX_ENTRIES (64 + 32 + 2 + 1) 139 #define ALPM_MAX_VRF_PFX_INDEX (ALPM_MAX_VRF_PFX_ENTRIES - 1) 140 #define ALPM_MAX_PFX_ENTRIES (3 * ALPM_MAX_VRF_PFX_ENTRIES) 141 #define ALPM_MAX_PFX_INDEX (ALPM_MAX_PFX_ENTRIES - 1) 142 #define SOC_ALPM_PFX_IS_V4(u, pfx) (((pfx) % ALPM_MAX_VRF_PFX_ENTRIES) < ALPM_IPV6_PFX_ZERO) 143 #define SOC_ALPM_PFX_IS_V6_64(u, pfx) (((pfx) % ALPM_MAX_VRF_PFX_ENTRIES) >= ALPM_IPV6_PFX_ZERO && \ 144 (pfx) != ALPM_MAX_VRF_PFX_INDEX) 145 #define SOC_ALPM_LPM_INIT_CHECK(u) (soc_th_alpm_lpm_state[(u)] != NULL) 146 #define SOC_ALPM_LPM_STATE(u) (soc_th_alpm_lpm_state[(u)]) 147 #define SOC_ALPM_LPM_STATE_START(u, pfx) (soc_th_alpm_lpm_state[(u)][(pfx)].start) 148 #define SOC_ALPM_LPM_STATE_END(u, pfx) (soc_th_alpm_lpm_state[(u)][(pfx)].end) 149 #define SOC_ALPM_LPM_STATE_PREV(u, pfx) (soc_th_alpm_lpm_state[(u)][(pfx)].prev) 150 #define SOC_ALPM_LPM_STATE_NEXT(u, pfx) (soc_th_alpm_lpm_state[(u)][(pfx)].next) 151 #define SOC_ALPM_LPM_STATE_VENT(u, pfx) (soc_th_alpm_lpm_state[(u)][(pfx)].vent) 152 #define SOC_ALPM_LPM_STATE_FENT(u, pfx) (soc_th_alpm_lpm_state[(u)][(pfx)].fent) 153 154 typedef struct soc_th_lpm_field_cache_s { 155 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, CLASS_ID0f); 156 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, CLASS_ID1f); 157 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DST_DISCARD0f); 158 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DST_DISCARD1f); 159 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP0f); 160 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP1f); 161 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_COUNT0f); 162 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_COUNT1f); 163 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_PTR0f); 164 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ECMP_PTR1f); 165 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_ROUTE0f); 166 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_ROUTE1f); 167 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MULTICAST_ROUTE0f); 168 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, MULTICAST_ROUTE1f); 169 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPA_ID0f); 170 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPA_ID1f); 171 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, EXPECTED_L3_IIF0f); 172 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, EXPECTED_L3_IIF1f); 173 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f); 174 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f); 175 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f); 176 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f); 177 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, L3MC_INDEX0f); 178 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, L3MC_INDEX1f); 179 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, HIT0f); 180 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, HIT1f); 181 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR0f); 182 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR1f); 183 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR_MASK0f); 184 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, IP_ADDR_MASK1f); 185 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, NEXT_HOP_INDEX0f); 186 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, NEXT_HOP_INDEX1f); 187 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, PRI0f); 188 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, PRI1f); 189 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPE0f); 190 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, RPE1f); 191 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VALID0f); 192 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VALID1f); 193 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_0f); 194 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_1f); 195 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_MASK0f); 196 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, VRF_ID_MASK1f); 197 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_HIGH0f); 198 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, GLOBAL_HIGH1f); 199 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_HIT_IDX0f); 200 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_HIT_IDX1f); 201 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_BKT_PTR0f); 202 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_BKT_PTR1f); 203 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_SUB_BKT_PTR0f); 204 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ALG_SUB_BKT_PTR1f); 205 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DEFAULT_MISS0f); 206 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DEFAULT_MISS1f); 207 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_BASE_COUNTER_IDX0f); 208 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_BASE_COUNTER_IDX1f); 209 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_POOL_NUMBER0f); 210 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_POOL_NUMBER1f); 211 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_OFFSET_MODE0f); 212 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, FLEX_CTR_OFFSET_MODE1f); 213 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, SRC_DISCARD0f); 214 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, SRC_DISCARD1f); 215 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DESTINATION0f); 216 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, DESTINATION1f); 217 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_VIEW0f); 218 SOC_ALPM_LPM_CACHE_FIELD_CREATE(L3_DEFIPm, ENTRY_VIEW1f); 219 220 } soc_th_lpm_field_cache_t, *soc_lpm_field_cache_p; 221 static soc_lpm_field_cache_p soc_lpm_field_cache_state[SOC_MAX_NUM_DEVICES]; 222 223 #define SOC_MEM_OPT_F32_GET(m_unit, m_mem, m_entry_data, m_field) \ 224 soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), \ 225 (m_entry_data), (soc_lpm_field_cache_state[(m_unit)]->m_mem##m_field)) 226 227 #define SOC_MEM_OPT_F32_SET(m_unit, m_mem, m_entry_data, m_field, m_val) \ 228 soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), \ 229 (m_entry_data), (soc_lpm_field_cache_state[(m_unit)]->m_mem##m_field), (m_val)) 230 231 232 #define SOC_MEM_OPT_FIELD_VALID(m_unit, m_mem, m_field) \ 233 ((soc_lpm_field_cache_state[(m_unit)]->m_mem##m_field) != NULL) 234 235 236 #ifdef FB_LPM_HASH_SUPPORT 237 typedef struct _soc_th_alpm_lpm_hash_s { 238 int unit; 239 int entry_count; /* Number entries in hash table */ 240 int index_count; /* Hash index max value + 1 */ 241 uint16 *table; /* Hash table with 16 bit index */ 242 uint16 *link_table; /* To handle collisions */ 243 } _soc_th_alpm_lpm_hash_t; 244 245 typedef uint32 _soc_th_alpm_lpm_hash_entry_t[5]; 246 typedef int (*_soc_th_alpm_lpm_hash_compare_fn)(_soc_th_alpm_lpm_hash_entry_t key1, 247 _soc_th_alpm_lpm_hash_entry_t key2); 248 static _soc_th_alpm_lpm_hash_t *_fb_lpm_hash_tab[SOC_MAX_NUM_DEVICES]; 249 #define SOC_ALPM_LPM_STATE_HASH(u) (_fb_lpm_hash_tab[(u)]) 250 251 #define TD2_ALPM_HASH_INDEX_NULL (0xFFFF) 252 #define TD2_ALPM_HASH_INDEX_MASK (0x7FFF) 253 #define TD2_ALPM_HASH_IPV6_MASK (0x8000) 254 255 #define SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, odata) \ 256 odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR0f); \ 257 odata[1] = \ 258 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK0f); \ 259 odata[2] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR1f); \ 260 odata[3] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK1f);\ 261 if ( (!(SOC_IS_HURRICANE(u))) && \ 262 (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f))) { \ 263 int m_vrf;\ 264 (void)soc_th_alpm_lpm_vrf_get(u, entry_data, (int *)&odata[4], &m_vrf); \ 265 } else { \ 266 odata[4] = 0; \ 267 } 268 269 #define SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, odata) \ 270 odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR0f); \ 271 odata[1] = \ 272 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK0f); \ 273 odata[2] = 0; \ 274 odata[3] = 0x80000001; \ 275 if ((!(SOC_IS_HURRICANE(u))) && \ 276 (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_0f))) { \ 277 int m_vrf;\ 278 (void)soc_th_alpm_lpm_vrf_get(u, entry_data, (int *)&odata[4], &m_vrf); \ 279 } else { \ 280 odata[4] = 0; \ 281 } 282 283 #define SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, odata) \ 284 odata[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR1f); \ 285 odata[1] = \ 286 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, IP_ADDR_MASK1f); \ 287 odata[2] = 0; \ 288 odata[3] = 0x80000001; \ 289 if ((!(SOC_IS_HURRICANE(u))) && \ 290 (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, VRF_ID_1f))) { \ 291 int m_vrf;\ 292 defip_entry_t m_tmp_ipv4;\ 293 (void)soc_th_alpm_lpm_ip4entry1_to_0(u, entry_data, &m_tmp_ipv4, 0); \ 294 (void)soc_th_alpm_lpm_vrf_get(u, &m_tmp_ipv4, (int *)&odata[4], &m_vrf); \ 295 } else { \ 296 odata[4] = 0; \ 297 } 298 299 #define SOC_FB_LPM_HASH_ENTRY_GET _soc_th_alpm_lpm_hash_entry_get 300 301 /* ALPM Software control block */ 302 soc_alpm_bucket_t soc_th_alpm_bucket[SOC_MAX_NUM_DEVICES]; 303 int l3_alpm_ipv4_double_wide[SOC_MAX_NUM_DEVICES]; 304 extern int l3_alpm_sw_prefix_lookup[SOC_MAX_NUM_DEVICES]; 305 306 /* Bucket sharing global vars */ 307 alpm_bkt_usg_t *bkt_usage[SOC_MAX_NUM_DEVICES]; 308 alpm_bkt_bmp_t *global_bkt_usage[SOC_MAX_NUM_DEVICES][SOC_TH_MAX_ALPM_VIEWS]; 309 310 /* ALPM internel debug counter */ 311 _alpm_int_dbg_cnt_t _alpm_dbg_cntr[SOC_MAX_NUM_DEVICES]; 312 313 /* Functions and externs */ 314 static 315 void _soc_th_alpm_lpm_hash_entry_get(int u, void *e, 316 int index, _soc_th_alpm_lpm_hash_entry_t r_entry, 317 int *v); 318 static 319 uint16 _soc_th_alpm_lpm_hash_compute(uint8 *data, int data_nbits); 320 static 321 int _soc_th_alpm_lpm_hash_create(int unit, 322 int entry_count, 323 int index_count, 324 _soc_th_alpm_lpm_hash_t **fb_lpm_hash_ptr); 325 static 326 int _soc_th_alpm_lpm_hash_destroy(_soc_th_alpm_lpm_hash_t *fb_lpm_hash); 327 static 328 int _soc_th_alpm_lpm_hash_lookup(_soc_th_alpm_lpm_hash_t *hash, 329 _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn, 330 _soc_th_alpm_lpm_hash_entry_t entry, 331 int pfx, 332 uint16 *key_index); 333 static 334 int _soc_th_alpm_lpm_hash_insert(_soc_th_alpm_lpm_hash_t *hash, 335 _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn, 336 _soc_th_alpm_lpm_hash_entry_t entry, 337 int pfx, 338 uint16 old_index, 339 uint16 new_index, 340 uint32 *rvt_index); 341 static 342 int _soc_th_alpm_lpm_hash_revert(_soc_th_alpm_lpm_hash_t *hash, 343 _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn, 344 _soc_th_alpm_lpm_hash_entry_t entry, 345 uint16 new_index, 346 uint32 rvt_index); 347 static 348 int _soc_th_alpm_lpm_hash_delete(_soc_th_alpm_lpm_hash_t *hash, 349 _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn, 350 _soc_th_alpm_lpm_hash_entry_t entry, 351 int pfx, 352 uint16 delete_index); 353 static 354 int _soc_th_alpm_lpm_hash_verify(_soc_th_alpm_lpm_hash_t *hash, 355 _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn, 356 _soc_th_alpm_lpm_hash_entry_t entry, 357 int pfx, 358 uint16 index); 359 static int 360 _soc_th_alpm_lpm_prefix_length_get(int , int , void *, int *, int *, int *); 361 362 static int soc_th_alpm_lpm_init(int u); 363 static int soc_th_alpm_lpm_deinit(int u); 364 static int soc_th_alpm_lpm_insert(int u, void *entry_data, int *index, int bpm_len, 365 int src_default, int src_discard); 366 static int soc_th_alpm_lpm_delete(int u, void *key_data); 367 static int _soc_th_alpm_fill_aux_entry_for_op(int u, 368 void *key_data, 369 int ipv6, /* Entry is ipv6. */ 370 int db_type, /* database type */ 371 int ent_type, 372 int replace_len, /* used for delete propagate */ 373 defip_aux_scratch_entry_t *aux_entry); 374 static int 375 _soc_th_alpm_lpm_match(int u, 376 void *key_data, 377 void *e, /* return entry data if found */ 378 int *index_ptr, /* return key location */ 379 int *pfx_len, /* Key prefix length. vrf + 32 + prefix len for IPV6*/ 380 int *ipv6, /* Entry is ipv6. */ 381 int *vrf_id, /* (OUT) */ 382 int *vrf); /* (OUT) */ 383 static int soc_th_alpm_lpm_match(int u, 384 void *key_data, 385 void *e, /* return entry data if found */ 386 int *index_ptr); /* return key location */ 387 static int soc_th_alpm_shared_mem_init(int u); 388 static int _soc_th_alpm_mem_ent_init(int unit, int ipv6, void *lpm_entry, 389 void *alpm_entry, void *alpm_sip_entry, soc_mem_t mem, 390 uint32 src_flags, uint32 *default_route, int bucket_id); 391 static int _soc_th_alpm_lpm_ent_init(int unit, void *alpm_entry, soc_mem_t mem, 392 int ipv6, int vrf_id, int bucket, int index, 393 void *lpm_entry, int flex); 394 static int _soc_th_alpm_lpm_ent_key_init(int unit, uint32 *key, int len, int vrf, 395 int ipv6, defip_entry_t *lpm_entry, int init); 396 static int soc_th_alpm_vrf_delete(int u, int vrf, int v6); 397 int soc_th_alpm_lpm_delete(int u, void *key_data); 398 399 /* Use MAX_VRF_ID to store VRF_OVERRIDE routes debug info */ 400 extern alpm_vrf_handle_t *alpm_vrf_handle[SOC_MAX_NUM_DEVICES]; 401 extern alpm_pivot_t **tcam_pivot[SOC_MAX_NUM_DEVICES]; 402 403 extern int soc_tomahawk_alpm_mode_get(int unit); 404 extern int _soc_th_alpm_128_prefix_create(int u, void *entry, uint32 *result, 405 uint32 *pfx_len, int *default_route); 406 407 #if 0 408 extern int sh_process_command(int u,char * c); 409 extern void soc_th_alpm_lpm_sw_dump(int unit); 410 void soc_th_debug_collect(int u, int vrf, int v6, soc_mem_t mem, void *entry) 411 { 412 int i; 413 414 sh_process_command(u, "debug ="); 415 416 LOG_CLI(("\n====Collecting info for unit(%d), vrf(%d), v6(%d), mem(%s), entry(%p)\n", 417 u, vrf, v6, SOC_MEM_NAME(u, mem), entry)); 418 419 /* Dump system configuration */ 420 LOG_CLI(("\n====Dumping current config.bcm\n")); 421 sh_process_command(u, "config show"); 422 423 /* Debug counter */ 424 LOG_CLI(("\n====Dumping ALPM debug counters\n")); 425 for (i = 0; i < DEBUG_VAR_NUMBER; i++) { 426 if (debug_var[i] != 0) { 427 LOG_CLI(("debug_var[%2d] = %d\n", i, debug_var[i])); 428 } 429 } 430 431 /* Dump current entry */ 432 if (entry != NULL) { 433 LOG_CLI(("\n====Dumping ALPM current operating entry\n")); 434 soc_mem_entry_dump_if_changed(u, mem, entry, "ALPM-DBG: "); 435 } 436 437 /* Dump ALPM Memories */ 438 LOG_CLI(("\n====Dumping ALPM memories\n")); 439 sh_process_command(u, "d chg L3_DEFIP"); 440 sh_process_command(u, "d chg L3_DEFIP_pair_128"); 441 sh_process_command(u, "d chg L3_DEFIP_aux_table"); 442 sh_process_command(u, "d chg L3_DEFIP_AUX_SCRATCH"); 443 sh_process_command(u, "d chg L3_DEFIP_alpm_ipv4"); 444 sh_process_command(u, "d chg L3_DEFIP_alpm_ipv6_64"); 445 sh_process_command(u, "d chg L3_DEFIP_alpm_ipv6_128"); 446 447 /* Dump Pivot trie */ 448 LOG_CLI(("\n====Dumping ALPM Pivot trie-tree for VRF %d\n", vrf)); 449 trie_dump(v6 ? VRF_PIVOT_TRIE_IPV6_128(u, vrf) : VRF_PIVOT_TRIE_IPV4(u, vrf), 450 NULL, NULL); 451 452 /* Dump VRF trie */ 453 LOG_CLI(("\n====Dumping VRF route trie-tree for VRF %d\n", vrf)); 454 trie_dump(v6 ? VRF_PREFIX_TRIE_IPV6_128(u, vrf) : VRF_PREFIX_TRIE_IPV4(u, vrf), 455 NULL, NULL); 456 457 /* Dump Bucket trie */ 458 LOG_CLI(("\n====Dumping Bucket trie-tree for VRF %d\n", vrf)); 459 for (i = 0; i < TH_MAX_PIVOT_COUNT(u); i++) { 460 if (ALPM_TCAM_PIVOT(u, i) != NULL) { 461 trie_t *trie = PIVOT_BUCKET_TRIE(ALPM_TCAM_PIVOT(u, i)); 462 LOG_CLI(("\t==Dumping Trie-tree for TCAM %d, index %d\n", i, 463 soc_th_alpm_logical_idx(u, L3_DEFIPm, i >> 1, 1))); 464 trie_dump(trie, NULL, NULL); 465 } 466 } 467 468 /* Dump ALPM LPM SW state */ 469 LOG_CLI(("\n====Dumping ALPM LPM SW state\n")); 470 soc_th_alpm_lpm_sw_dump(u); 471 472 /* Running Sanity check */ 473 LOG_CLI(("\n====Running Bucket Sanity check\n")); 474 soc_th_alpm_bucket_sanity_check(u, L3_DEFIPm, -1); 475 476 LOG_CLI(("\n====Running Pivot Sanity check\n")); 477 soc_th_alpm_pivot_sanity_check(u, L3_DEFIPm, -1); 478 479 return ; 480 } 481 #endif 482 483 int 484 _soc_th_alpm_lpm_entry_view_get(int u, int ipv6, int flex) 485 { 486 int entry_view = flex; 487 488 if (SOC_IS_TRIDENT3X(u)) { 489 switch (ipv6) { 490 case L3_DEFIP_MODE_128: 491 entry_view = 0; 492 break; 493 case L3_DEFIP_MODE_64: 494 entry_view = flex ? 1 : 2; 495 break; 496 case L3_DEFIP_MODE_V4: 497 default: 498 entry_view = flex ? 3 : 4; 499 } 500 } 501 502 return entry_view; 503 } 504 505 int 506 _soc_th_alpm_lpm_flex_get(int u, int ipv6, int entry_view) 507 { 508 int flex = entry_view; 509 510 if (SOC_IS_TRIDENT3X(u)) { 511 switch (ipv6) { 512 case L3_DEFIP_MODE_128: 513 flex = 0; 514 break; 515 case L3_DEFIP_MODE_64: 516 flex = (entry_view == 1) ? 1 : 0; 517 break; 518 case L3_DEFIP_MODE_V4: 519 default: 520 flex = (entry_view == 3) ? 1 : 0; 521 } 522 } 523 524 return flex; 525 } 526 527 528 STATIC int 529 _soc_th_alpm_sw_propagate_required(int unit) 530 { 531 int i, mem_cnt; 532 soc_mem_t mem_chk[] = { 533 L3_DEFIPm, 534 L3_DEFIP_PAIR_128m, 535 L3_DEFIP_AUX_TABLEm 536 }; 537 538 mem_cnt = sizeof(mem_chk) / sizeof(mem_chk[0]); 539 for (i = 0; i < mem_cnt; i++) { 540 if (soc_mem_cache_get(unit, mem_chk[i], MEM_BLOCK_ANY)) { 541 return TRUE; 542 } 543 } 544 545 return FALSE; 546 } 547 548 STATIC int 549 _soc_th_alpm_sw_hitbit_upd_required(int unit) 550 { 551 int i, mem_cnt; 552 soc_mem_t mem_chk[] = { 553 L3_DEFIPm, 554 L3_DEFIP_PAIR_128m 555 }; 556 557 mem_cnt = sizeof(mem_chk) / sizeof(mem_chk[0]); 558 for (i = 0; i < mem_cnt; i++) { 559 if (soc_mem_cache_get(unit, mem_chk[i], MEM_BLOCK_ANY)) { 560 return TRUE; 561 } 562 } 563 564 return FALSE; 565 } 566 567 STATIC int 568 _soc_th_alpm_ctrl_init(int u) 569 { 570 int i, mode; 571 sal_memset(&ALPM_CTRL(u), 0, sizeof(_soc_alpm_ctrl_t)); 572 573 ALPM_CTRL(u).trie_propagate = _soc_th_alpm_sw_propagate_required(u); 574 /* Don't set trie_user_ppg = 0, it's for debug purpose only */ 575 ALPM_CTRL(u).trie_user_ppg = soc_property_get(u, "l3_alpm_trie_user_ppg", 1); 576 ALPM_CTRL(u).hit_idx_upd = _soc_th_alpm_sw_hitbit_upd_required(u); 577 ALPM_CTRL(u).force_aux_op = soc_property_get(u, "l3_alpm_force_aux_op", 0); 578 ALPM_CTRL(u).hit_bits_skip = soc_property_get(u, spn_L3_ALPM_HIT_SKIP, 0); 579 ALPM_CTRL(u).alpm_scaling = soc_property_get(u, "l3_alpm_scaling", 1); 580 ALPM_CTRL(u).aux_enable = ALPM_CTRL(u).trie_propagate ? 581 soc_property_get(u, "l3_alpm_aux_enable", 1) : 1; 582 583 /* soc_alpm_cmn_mode_get1(u); */ 584 mode = soc_property_get(u, spn_L3_ALPM_ENABLE, 0); 585 switch (mode) { 586 case 1: /* Parallel mode */ 587 ALPM_CTRL(u).alpm_mode = SOC_ALPM_MODE_PARALLEL; 588 ALPM_CTRL(u).gp_zoned = TRUE; 589 break; 590 case 3: /* TCAM/ALPM mode */ 591 ALPM_CTRL(u).alpm_mode = SOC_ALPM_MODE_TCAM_ALPM; 592 l3_alpm_ipv4_double_wide[u] = 1; 593 ALPM_CTRL(u).gp_zoned = TRUE; 594 break; 595 case 2: /* Combined mode */ 596 ALPM_CTRL(u).alpm_mode = SOC_ALPM_MODE_COMBINED; 597 break; 598 default: /* LPM */ 599 ALPM_CTRL(u).alpm_mode = SOC_ALPM_MODE_INVALID; 600 break; 601 } 602 603 /* Fetch bank number and bits */ 604 ALPM_CTRL(u).num_banks = soc_alpm_cmn_banks_get(u); 605 for (i = 0; i < 32; i++) { 606 if (1 << i == ALPM_CTRL(u).num_banks) { 607 break; 608 } 609 } 610 if (i < 32) { 611 ALPM_CTRL(u).bank_bits = i; 612 } 613 614 if (ALPM_CTRL(u).num_banks == 8) { 615 ALPM_CTRL(u).half_bkt_mode = 0; 616 } else if (ALPM_CTRL(u).num_banks == 4) { 617 if (SOC_IS_TRIDENT3X(u)) { 618 ALPM_CTRL(u).half_bkt_mode = 1; 619 } else { 620 ALPM_CTRL(u).half_bkt_mode = 0; 621 } 622 } else if (ALPM_CTRL(u).num_banks == 2) { 623 ALPM_CTRL(u).half_bkt_mode = 1; 624 } 625 626 /* Fetch bank sharing mode */ 627 if (SOC_MEM_FIELD_VALID(u, L3_DEFIPm, ALG_SUB_BKT_PTR0f)) { 628 ALPM_CTRL(u).bkt_sharing = TRUE; 629 } 630 631 /* Bucket mask SOC_TH_ALPM_BKT_MASK */ 632 if (SOC_IS_TOMAHAWKX(u)) { 633 ALPM_CTRL(u).bkt_mask = SOC_TH_ALPM_BKT_MASK(u); 634 ALPM_CTRL(u).num_bkts = SOC_TH_ALPM_MAX_BKTS(u); 635 } else if (SOC_IS_TRIDENT3X(u)) { 636 ALPM_CTRL(u).bkt_mask = SOC_TD3_ALPM_BKT_MASK(u); 637 ALPM_CTRL(u).num_bkts = SOC_TD3_ALPM_MAX_BKTS(u); 638 } else if (SOC_IS_APACHE(u)) { 639 ALPM_CTRL(u).bkt_mask = SOC_APACHE_ALPM_BKT_MASK; 640 ALPM_CTRL(u).num_bkts = SOC_APACHE_ALPM_MAX_BKTS; 641 } else { 642 ALPM_CTRL(u).bkt_mask = SOC_TD2_ALPM_BKT_MASK; 643 ALPM_CTRL(u).num_bkts = SOC_TD2_ALPM_MAX_BKTS; 644 } 645 646 ALPM_CTRL(u).bkt_bits = _shr_popcount(ALPM_CTRL(u).bkt_mask); 647 648 /* Bank disable bitmap */ 649 soc_th_alpm_bank_dis(u, SOC_VRF_MAX(u) + 1, 650 &ALPM_CTRL(u).bank_disable_bmp[0], 651 &ALPM_CTRL(u).bank_disable_bmp_8b[0]); 652 soc_th_alpm_bank_dis(u, 1, 653 &ALPM_CTRL(u).bank_disable_bmp[1], 654 &ALPM_CTRL(u).bank_disable_bmp_8b[1]); 655 656 /* Double Wide */ 657 /* SOC_TH_ALPM_SCALE_CHECK1(u, ipv6) */ 658 l3_alpm_ipv4_double_wide[u] = 659 soc_property_get(u, "l3_alpm_ipv4_double_wide", 1); 660 if (SOC_IS_TRIDENT3X(u)) { 661 /* Force to IPv4 Double wide mode in TD3 */ 662 l3_alpm_ipv4_double_wide[u] = 1; 663 } 664 for (i = 0; i <= L3_DEFIP_MODE_128; i++) { 665 if (SOC_TH_ALPM_SCALE_CHECK(u, i)) { 666 ALPM_CTRL(u).double_wide[i] = 1; 667 } 668 } 669 670 /* ent_per_bank */ 671 ALPM_CTRL(u).ent_per_bank[L3_DEFIP_MODE_V4] = 6; 672 ALPM_CTRL(u).ent_per_bank[L3_DEFIP_MODE_64] = 4; 673 ALPM_CTRL(u).ent_per_bank[L3_DEFIP_MODE_128] = 2; 674 675 /* cnt_ent_per_bkt */ 676 ALPM_CTRL(u).cnt_ent_per_bkt[L3_DEFIP_MODE_V4] = 677 _soc_th_alpm_bkt_entry_cnt(u, L3_DEFIP_ALPM_IPV4m); 678 ALPM_CTRL(u).cnt_ent_per_bkt[L3_DEFIP_MODE_64] = 679 _soc_th_alpm_bkt_entry_cnt(u, L3_DEFIP_ALPM_IPV6_64m); 680 ALPM_CTRL(u).cnt_ent_per_bkt[L3_DEFIP_MODE_128] = 681 _soc_th_alpm_bkt_entry_cnt(u, L3_DEFIP_ALPM_IPV6_128m); 682 683 /* l3_alpm_sw_prefix_lookup */ 684 if (SOC_IS_TRIDENT3X(u)) { 685 /* Force TD3 to use sw lookup */ 686 ALPM_CTRL(u).sw_prefix_lkup = 1; 687 } else { 688 ALPM_CTRL(u).sw_prefix_lkup = 689 soc_property_get(u, "l3_alpm_sw_prefix_lookup", 1); 690 } 691 692 /* Flex key 693 * ENTRY_TYPE -> KEY_TYPE 694 * MODE -> KEY_MODE 695 */ 696 if (SOC_MEM_FIELD_VALID(u, L3_DEFIPm, KEY_TYPE0f)) { 697 ALPM_CTRL(u).fld.key_mode0 = KEY_MODE0f; 698 ALPM_CTRL(u).fld.key_mode1 = KEY_MODE1f; 699 ALPM_CTRL(u).fld.key_mode_mask0 = KEY_MODE_MASK0f; 700 ALPM_CTRL(u).fld.key_mode_mask1 = KEY_MODE_MASK1f; 701 ALPM_CTRL(u).fld.key_type0 = KEY_TYPE0f; 702 ALPM_CTRL(u).fld.key_type1 = KEY_TYPE1f; 703 ALPM_CTRL(u).fld.key_type_mask0 = KEY_TYPE_MASK0f; 704 ALPM_CTRL(u).fld.key_type_mask1 = KEY_TYPE_MASK1f; 705 ALPM_CTRL(u).fld.key_mode0_upr = KEY_MODE0_UPRf; 706 ALPM_CTRL(u).fld.key_mode0_lwr = KEY_MODE0_LWRf; 707 ALPM_CTRL(u).fld.key_mode1_upr = KEY_MODE1_UPRf; 708 ALPM_CTRL(u).fld.key_mode1_lwr = KEY_MODE1_LWRf; 709 ALPM_CTRL(u).fld.key_mode_mask0_upr = KEY_MODE_MASK0_UPRf; 710 ALPM_CTRL(u).fld.key_mode_mask0_lwr = KEY_MODE_MASK0_LWRf; 711 ALPM_CTRL(u).fld.key_mode_mask1_upr = KEY_MODE_MASK1_UPRf; 712 ALPM_CTRL(u).fld.key_mode_mask1_lwr = KEY_MODE_MASK1_LWRf; 713 ALPM_CTRL(u).fld.key_type0_upr = KEY_TYPE0_UPRf; 714 ALPM_CTRL(u).fld.key_type0_lwr = KEY_TYPE0_LWRf; 715 ALPM_CTRL(u).fld.key_type1_upr = KEY_TYPE1_UPRf; 716 ALPM_CTRL(u).fld.key_type1_lwr = KEY_TYPE1_LWRf; 717 ALPM_CTRL(u).fld.key_type_mask0_upr = KEY_TYPE_MASK0_UPRf; 718 ALPM_CTRL(u).fld.key_type_mask0_lwr = KEY_TYPE_MASK0_LWRf; 719 ALPM_CTRL(u).fld.key_type_mask1_upr = KEY_TYPE_MASK1_UPRf; 720 ALPM_CTRL(u).fld.key_type_mask1_lwr = KEY_TYPE_MASK1_LWRf; 721 ALPM_CTRL(u).fld.key_mode = KEY_MODEf; 722 ALPM_CTRL(u).fld.key_type = KEY_TYPEf; 723 } else { 724 ALPM_CTRL(u).fld.key_mode0 = MODE0f; 725 ALPM_CTRL(u).fld.key_mode1 = MODE1f; 726 ALPM_CTRL(u).fld.key_mode_mask0 = MODE_MASK0f; 727 ALPM_CTRL(u).fld.key_mode_mask1 = MODE_MASK1f; 728 ALPM_CTRL(u).fld.key_type0 = ENTRY_TYPE0f; 729 ALPM_CTRL(u).fld.key_type1 = ENTRY_TYPE1f; 730 ALPM_CTRL(u).fld.key_type_mask0 = ENTRY_TYPE_MASK0f; 731 ALPM_CTRL(u).fld.key_type_mask1 = ENTRY_TYPE_MASK1f; 732 ALPM_CTRL(u).fld.key_mode0_upr = MODE0_UPRf; 733 ALPM_CTRL(u).fld.key_mode0_lwr = MODE0_LWRf; 734 ALPM_CTRL(u).fld.key_mode1_upr = MODE1_UPRf; 735 ALPM_CTRL(u).fld.key_mode1_lwr = MODE1_LWRf; 736 ALPM_CTRL(u).fld.key_mode_mask0_upr = MODE_MASK0_UPRf; 737 ALPM_CTRL(u).fld.key_mode_mask0_lwr = MODE_MASK0_LWRf; 738 ALPM_CTRL(u).fld.key_mode_mask1_upr = MODE_MASK1_UPRf; 739 ALPM_CTRL(u).fld.key_mode_mask1_lwr = MODE_MASK1_LWRf; 740 ALPM_CTRL(u).fld.key_type0_upr = ENTRY_TYPE0_UPRf; 741 ALPM_CTRL(u).fld.key_type0_lwr = ENTRY_TYPE0_LWRf; 742 ALPM_CTRL(u).fld.key_type1_upr = ENTRY_TYPE1_UPRf; 743 ALPM_CTRL(u).fld.key_type1_lwr = ENTRY_TYPE1_LWRf; 744 ALPM_CTRL(u).fld.key_type_mask0_upr = ENTRY_TYPE_MASK0_UPRf; 745 ALPM_CTRL(u).fld.key_type_mask0_lwr = ENTRY_TYPE_MASK0_LWRf; 746 ALPM_CTRL(u).fld.key_type_mask1_upr = ENTRY_TYPE_MASK1_UPRf; 747 ALPM_CTRL(u).fld.key_type_mask1_lwr = ENTRY_TYPE_MASK1_LWRf; 748 ALPM_CTRL(u).fld.key_mode = MODEf; 749 ALPM_CTRL(u).fld.key_type = ENTRY_TYPEf; 750 } 751 ALPM_CTRL(u)._alpm_128b = SOC_ALPM_128B_ENABLE(u); 752 if (ALPM_CTRL(u)._alpm_128b) { 753 ALPM_CTRL(u)._alpm_128b_bkt_rsvd = 754 soc_property_get(u, spn_L3_ALPM_IPV6_128B_BKT_RSVD, 0); 755 if (ALPM_CTRL(u)._alpm_128b_bkt_rsvd) { 756 ALPM_CTRL(u)._alpm_128b_bkt_rsvd_cnt = SOC_L3_DEFIP_MAX_128B_ENTRIES(u); 757 } 758 } 759 760 ALPM_CTRL(u).ctrl_inited = 1; 761 return SOC_E_NONE; 762 } 763 764 STATIC int 765 _soc_th_alpm_sw_propagate(int u, trie_t *pivot, void *prefix, uint32 len, 766 int insert, void *cb, void *user_data) 767 { 768 int rv = SOC_E_NONE; 769 uint32 pivot_len = 0; 770 trie_node_t *lpm_pvt = NULL; 771 trie_bpm_cb_info_t cb_info; 772 773 cb_info.pfx = (void *)prefix; 774 cb_info.len = len; 775 cb_info.user_data = user_data; 776 777 /* Find longest prefix match(pivot) of route */ 778 SOC_IF_ERROR_RETURN(trie_find_lpm(pivot, prefix, len, &lpm_pvt)); 779 pivot_len = (TRIE_ELEMENT_GET(payload_t *, lpm_pvt, node))->len; 780 781 if (ALPM_CTRL(u).trie_user_ppg) { 782 if (pivot->v6_key) { 783 rv = pvt_trie_v6_propagate_prefix(lpm_pvt, pivot_len, 784 (void *)prefix, len, cb, &cb_info); 785 } else { 786 rv = pvt_trie_propagate_prefix(lpm_pvt, pivot_len, 787 (void *)prefix, len, cb, &cb_info); 788 } 789 } else { 790 if (pivot->v6_key) { 791 rv = trie_v6_pivot_propagate_prefix(lpm_pvt, pivot_len, 792 (void *)prefix, len, insert, cb, &cb_info); 793 } else { 794 rv = trie_pivot_propagate_prefix(lpm_pvt, pivot_len, 795 (void *)prefix, len, insert, cb, &cb_info); 796 } 797 } 798 799 return rv; 800 } 801 802 /* Perform an ALPM mem read operation during sw propagation */ 803 STATIC int 804 _soc_th_mem_alpm_read_on_sw_propagate(int unit, soc_mem_t mem, int copyno, 805 int index, void *entry_data) 806 { 807 int rv = SOC_E_NONE; 808 809 if (ALPM_CTRL(unit).aux_enable) { 810 rv = _soc_mem_alpm_read_cache(unit, mem,copyno, index, entry_data); 811 } else { 812 rv = _soc_mem_alpm_read(unit, mem,copyno, index, entry_data); 813 } 814 815 return rv; 816 } 817 818 /* Perform an ALPM mem write operation during sw propagation */ 819 STATIC int 820 _soc_th_mem_alpm_write_on_sw_propagate(int unit, soc_mem_t mem, int copyno, 821 int index, void *entry_data) 822 { 823 int rv = SOC_E_NONE; 824 825 if (ALPM_CTRL(unit).aux_enable) { 826 _soc_mem_alpm_write_cache(unit, mem, copyno, index, entry_data); 827 } else { 828 rv = soc_mem_write(unit, mem, copyno, index, entry_data); 829 } 830 831 return rv; 832 } 833 834 STATIC int 835 _soc_th_alpm_hit_bits_callback(trie_node_t *trie, trie_bpm_cb_info_t *info) 836 { 837 int rv, unit, ipv6; 838 trie_bpm_cb_user_data_t *user_data; 839 alpm_pivot_t *pivot_pyld; 840 int tcam_index, lpm_index, hit_idx; 841 uint32 pvt_bpm_len, pfx_len; 842 843 user_data = info->user_data; 844 unit = user_data->unit; 845 ipv6 = user_data->ipv6; 846 pfx_len = user_data->pfx_len; 847 user_data->count++; 848 849 pivot_pyld = (alpm_pivot_t *)trie; 850 tcam_index = PIVOT_TCAM_INDEX(pivot_pyld); 851 pvt_bpm_len = PIVOT_TCAM_BPMLEN(pivot_pyld); 852 853 if (ALPM_CTRL(unit).trie_user_ppg) { 854 /* Addr & Mask has been screened by propagate function, 855 * no need to do it again */ 856 if (user_data->aux_op == INSERT_PROPAGATE) { 857 if (pvt_bpm_len > pfx_len) { 858 /* Not qualified */ 859 return SOC_E_LIMIT; 860 } 861 } 862 863 if (user_data->aux_op == DELETE_PROPAGATE) { 864 if (pvt_bpm_len != pfx_len) { 865 /* Not qualified */ 866 return (pvt_bpm_len > pfx_len) ? SOC_E_LIMIT : SOC_E_NONE; 867 } 868 } 869 } 870 871 if (ipv6 == L3_DEFIP_MODE_V4 || ipv6 == L3_DEFIP_MODE_64) { 872 soc_mem_t lpm_mem = L3_DEFIPm; 873 defip_entry_t lpm_entry; 874 875 /* Update L3_DEFIPm */ 876 lpm_index = soc_th_alpm_logical_idx(unit, lpm_mem, tcam_index >> 1, 1); 877 878 LOG_INFO(BSL_LS_SOC_ALPM, 879 (BSL_META_U(unit, "ALPM SW hit cb: lpm_mem %s index %d ent %d\n"), 880 SOC_MEM_NAME(unit, lpm_mem), lpm_index, (tcam_index & 1))); 881 882 soc_mem_lock(unit, lpm_mem); 883 884 rv = _soc_th_mem_alpm_read_on_sw_propagate( 885 unit, lpm_mem, MEM_BLOCK_ANY, lpm_index, &lpm_entry); 886 if (SOC_SUCCESS(rv)) { 887 if (ipv6 == L3_DEFIP_MODE_64) { /* IPv6_64 */ 888 hit_idx = soc_mem_field32_get(unit, lpm_mem, 889 (uint32 *)&lpm_entry, ALG_HIT_IDX0f); 890 if (hit_idx == user_data->old_idx) { 891 soc_mem_field32_set(unit, lpm_mem, (uint32 *)&lpm_entry, 892 ALG_HIT_IDX0f, user_data->new_idx); 893 /* Hardware doesn't update ALG_HIT_IDX1f for IPv6-64 894 soc_mem_field32_set(unit, lpm_mem, (uint32 *)&lpm_entry, 895 ALG_HIT_IDX1f, user_data->new_idx); 896 */ 897 } 898 } else { /* IPv4 */ 899 soc_field_t hit_fld = (tcam_index & 1) ? 900 ALG_HIT_IDX1f : 901 ALG_HIT_IDX0f; 902 903 hit_idx = soc_mem_field32_get(unit, lpm_mem, 904 (uint32 *)&lpm_entry, hit_fld); 905 if (hit_idx == user_data->old_idx) { 906 soc_mem_field32_set(unit, lpm_mem, (uint32 *)&lpm_entry, 907 hit_fld, user_data->new_idx); 908 } 909 } 910 (void) _soc_th_mem_alpm_write_on_sw_propagate( 911 unit, lpm_mem, MEM_BLOCK_ALL, lpm_index, &lpm_entry); 912 913 if (SOC_URPF_STATUS_GET(unit)) { 914 lpm_index += (soc_mem_index_count(unit, lpm_mem) >> 1); 915 rv = _soc_th_mem_alpm_read_on_sw_propagate( 916 unit, lpm_mem, MEM_BLOCK_ANY, lpm_index, &lpm_entry); 917 if (SOC_SUCCESS(rv)) { 918 if (ipv6 == L3_DEFIP_MODE_64) { 919 soc_mem_field32_set(unit, lpm_mem, (uint32 *)&lpm_entry, 920 ALG_HIT_IDX0f, 921 _soc_th_alpm_rpf_entry(unit, user_data->new_idx)); 922 /* Hardware doesn't update ALG_HIT_IDX1f for IPv6-64 923 soc_mem_field32_set(unit, lpm_mem, (uint32 *)&lpm_entry, 924 ALG_HIT_IDX1f, 925 _soc_th_alpm_rpf_entry(unit, user_data->new_idx)); 926 */ 927 } else { 928 soc_field_t hit_fld = (tcam_index & 1) ? 929 ALG_HIT_IDX1f : 930 ALG_HIT_IDX0f; 931 soc_mem_field32_set(unit, lpm_mem, (uint32 *)&lpm_entry, 932 hit_fld, 933 _soc_th_alpm_rpf_entry(unit, user_data->new_idx)); 934 } 935 (void) _soc_th_mem_alpm_write_on_sw_propagate( 936 unit, lpm_mem, MEM_BLOCK_ALL, 937 lpm_index, &lpm_entry); 938 } 939 } 940 } 941 soc_mem_unlock(unit, lpm_mem); 942 } else if (ipv6 == L3_DEFIP_MODE_128) { 943 soc_mem_t lpm128_mem = L3_DEFIP_PAIR_128m; 944 defip_pair_128_entry_t lpm128_entry; 945 946 lpm_index = soc_th_alpm_logical_idx(unit, lpm128_mem, 947 SOC_ALPM_128_DEFIP_TO_PAIR(unit, tcam_index >> 1), 1); 948 949 /* Update L3_DEFIP_PAIR_128m */ 950 soc_mem_lock(unit, lpm128_mem); 951 rv = _soc_th_mem_alpm_read_on_sw_propagate( 952 unit, lpm128_mem, MEM_BLOCK_ANY, lpm_index, &lpm128_entry); 953 if (SOC_SUCCESS(rv)) { 954 hit_idx = soc_mem_field32_get(unit, lpm128_mem, 955 (uint32 *)&lpm128_entry, ALG_HIT_IDXf); 956 if (hit_idx == user_data->old_idx) { 957 soc_mem_field32_set(unit, lpm128_mem, (uint32 *)&lpm128_entry, 958 ALG_HIT_IDXf, user_data->new_idx); 959 } 960 (void) _soc_th_mem_alpm_write_on_sw_propagate( 961 unit, lpm128_mem, MEM_BLOCK_ALL, 962 lpm_index, &lpm128_entry); 963 if (SOC_URPF_STATUS_GET(unit)) { 964 lpm_index += (soc_mem_index_count(unit, lpm128_mem) >> 1); 965 rv = _soc_th_mem_alpm_read_on_sw_propagate( 966 unit, lpm128_mem, MEM_BLOCK_ANY, 967 lpm_index, &lpm128_entry); 968 if (SOC_SUCCESS(rv)) { 969 soc_mem_field32_set( 970 unit, lpm128_mem, (uint32 *)&lpm128_entry, ALG_HIT_IDXf, 971 _soc_th_alpm_rpf_entry(unit, user_data->new_idx)); 972 (void) _soc_th_mem_alpm_write_on_sw_propagate( 973 unit, lpm128_mem, MEM_BLOCK_ALL, 974 lpm_index, &lpm128_entry); 975 } 976 } 977 } 978 soc_mem_unlock(unit, lpm128_mem); 979 980 LOG_INFO(BSL_LS_SOC_ALPM, 981 (BSL_META_U(unit, "ALPM SW hit cb: lpm_mem %s index %d\n"), 982 SOC_MEM_NAME(unit, lpm128_mem), lpm_index)); 983 } else { 984 return SOC_E_INTERNAL; 985 } 986 987 return SOC_E_NONE; 988 989 } 990 991 /* Update L3_DEFIP_* memory cache when cache is on */ 992 STATIC int 993 _soc_th_alpm_hit_bits_sw_update(int u, alpm_mem_prefix_array_t *pa, 994 int *new_idx, int *match_num, 995 int ipv6, int vrf) 996 { 997 int rv = SOC_E_NONE; 998 int i, count; 999 payload_t *pfx = NULL; 1000 trie_t *pivot = NULL; 1001 trie_bpm_cb_user_data_t user_data; 1002 1003 count = pa->count; 1004 if (ipv6 == L3_DEFIP_MODE_V4) { 1005 pivot = VRF_PIVOT_TRIE_IPV4(u, vrf); 1006 } else if (ipv6 == L3_DEFIP_MODE_64) { 1007 pivot = VRF_PIVOT_TRIE_IPV6(u, vrf); 1008 } else if (ipv6 == L3_DEFIP_MODE_128) { 1009 pivot = VRF_PIVOT_TRIE_IPV6_128(u, vrf); 1010 } else { 1011 return SOC_E_INTERNAL; 1012 } 1013 1014 sal_memset(&user_data, 0, sizeof(user_data)); 1015 user_data.unit = u; 1016 user_data.aux_op = INSERT_PROPAGATE; 1017 1018 for (i = 0; i < count; i++) { 1019 pfx = pa->prefix[i]; 1020 if (pfx->index <= 0) { 1021 continue; 1022 } 1023 user_data.old_idx = pfx->index; 1024 user_data.new_idx = new_idx[i]; 1025 user_data.ipv6 = ipv6; 1026 user_data.pfx_len = pfx->len; 1027 /* hit bits update are only required for insert case */ 1028 rv = _soc_th_alpm_sw_propagate(u, pivot, pfx->key, pfx->len, 1029 0, _soc_th_alpm_hit_bits_callback, &user_data); 1030 if (rv < 0) { 1031 break; 1032 } 1033 } 1034 1035 _alpm_dbg_cntr[u].ppg_cb_hitbit += user_data.count; 1036 if (match_num != NULL) { 1037 *match_num = user_data.count; 1038 } 1039 1040 return rv; 1041 } 1042 1043 STATIC int 1044 _soc_th_alpm_propagate_callback(trie_node_t *trie, 1045 trie_bpm_cb_info_t *info) 1046 { 1047 int rv = SOC_E_NONE; 1048 int i, unit, mode; 1049 trie_bpm_cb_user_data_t *user_data; 1050 void *aux_entry; 1051 alpm_pivot_t *pivot_pyld; 1052 int tcam_index, lpm_index, aux_index; 1053 int aux_flags; 1054 1055 /* use memory size to declear replace_data field value */ 1056 defip_aux_scratch_entry_t replace_data; 1057 soc_mem_t aux_mem = L3_DEFIP_AUX_SCRATCHm; 1058 1059 /* L3_DEFIP_AUX_TABLE variables */ 1060 defip_aux_table_entry_t shadow_entry; 1061 uint32 pfx_len, rpl_bpm_len, pvt_bpm_len, hit_idx; 1062 1063 #define _URPF_INDEX(urpf, index, mem) \ 1064 (urpf ? (index + (soc_mem_index_count(unit, mem) >> 1)) : index) 1065 1066 user_data = info->user_data; 1067 unit = user_data->unit; 1068 aux_entry = user_data->entry; 1069 aux_flags = user_data->flags; 1070 1071 /* For uRPF case, DB_TYPE is odd, see soc_alpm_db_ent_type_encoding */ 1072 if (soc_mem_field32_get(unit, aux_mem, aux_entry, DB_TYPEf) & 0x1) { 1073 return SOC_E_NONE; 1074 } 1075 1076 pivot_pyld = (alpm_pivot_t *)trie; 1077 pvt_bpm_len = PIVOT_TCAM_BPMLEN(pivot_pyld); 1078 pfx_len = soc_mem_field32_get(unit, aux_mem, aux_entry, IP_LENGTHf); 1079 rpl_bpm_len = soc_mem_field32_get(unit, aux_mem, aux_entry, REPLACE_LENf); 1080 if (user_data->aux_op == INSERT_PROPAGATE) { 1081 rpl_bpm_len = pfx_len; 1082 } 1083 1084 if (ALPM_CTRL(unit).trie_user_ppg) { 1085 /* Addr & Mask has been screened by propagate function, 1086 * no need to do it again */ 1087 if (user_data->aux_op == INSERT_PROPAGATE) { 1088 if (pvt_bpm_len > pfx_len) { 1089 /* Not qualified */ 1090 return SOC_E_LIMIT; 1091 } 1092 } 1093 1094 if (user_data->aux_op == DELETE_PROPAGATE) { 1095 if (pvt_bpm_len != pfx_len) { 1096 /* Not qualified */ 1097 return (pvt_bpm_len > pfx_len) ? SOC_E_LIMIT : SOC_E_NONE; 1098 } 1099 } 1100 } 1101 1102 /* Update bpm length accordingly */ 1103 PIVOT_TCAM_BPMLEN(pivot_pyld) = rpl_bpm_len; 1104 1105 /* update callback count, hw propagate is counting on this */ 1106 user_data->count ++; 1107 1108 sal_memset(&replace_data, 0, sizeof(replace_data)); 1109 soc_mem_field_get(unit, aux_mem, aux_entry, REPLACE_DATAf, 1110 (uint32 *)&replace_data); 1111 hit_idx = soc_mem_field32_get(unit, aux_mem, aux_entry, ALG_HIT_IDXf); 1112 if (hit_idx > 0) { 1113 hit_idx = _soc_th_alpm_rpf_entry(unit, hit_idx); 1114 } 1115 mode = soc_mem_field32_get(unit, aux_mem, aux_entry, MODE_f(unit)); 1116 1117 tcam_index = PIVOT_TCAM_INDEX(pivot_pyld); 1118 if (mode == 0 || mode == 1) { 1119 soc_mem_t lpm_mem = L3_DEFIPm; 1120 defip_entry_t lpm_entry; 1121 1122 /* Update L3_DEFIPm */ 1123 lpm_index = soc_th_alpm_logical_idx(unit, lpm_mem, tcam_index >> 1, 1); 1124 aux_index = tcam_index >> 1; 1125 1126 LOG_INFO(BSL_LS_SOC_ALPM, 1127 (BSL_META_U(unit, "ALPM SW %s ppg cb: lpm_mem %s index %d ent %d," 1128 "AUX_TABLE index %d\n"), 1129 (user_data->aux_op == INSERT_PROPAGATE) ? "Add" : "Del", 1130 SOC_MEM_NAME(unit, lpm_mem), lpm_index, 1131 (tcam_index & 1), aux_index)); 1132 1133 soc_mem_lock(unit, lpm_mem); 1134 rv = _soc_th_mem_alpm_read_on_sw_propagate( 1135 unit, lpm_mem, MEM_BLOCK_ANY, lpm_index, &lpm_entry); 1136 if (SOC_SUCCESS(rv)) { 1137 if (mode == 1) { 1138 /* IPv6_64 */ 1139 soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry, 1140 REPLACE_DATA0f, (uint32 *)&replace_data); 1141 /* Hardware doesn't update entry1 for IPv6-64 1142 soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry, 1143 REPLACE_DATA1f, (uint32 *)&replace_data); 1144 */ 1145 } else { 1146 /* IPv4 */ 1147 soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry, 1148 (tcam_index & 1) ? REPLACE_DATA1f : REPLACE_DATA0f, 1149 (uint32 *)&replace_data); 1150 } 1151 (void) _soc_th_mem_alpm_write_on_sw_propagate( 1152 unit, lpm_mem, MEM_BLOCK_ALL, lpm_index, &lpm_entry); 1153 if (SOC_URPF_STATUS_GET(unit)) { 1154 lpm_index = _URPF_INDEX(TRUE, lpm_index, L3_DEFIPm); 1155 rv = _soc_th_mem_alpm_read_on_sw_propagate( 1156 unit, lpm_mem, MEM_BLOCK_ANY, lpm_index, &lpm_entry); 1157 if (SOC_SUCCESS(rv)) { 1158 if (mode == 1) { 1159 soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry, 1160 REPLACE_DATA0f, (uint32 *)&replace_data); 1161 soc_mem_field32_set(unit, lpm_mem, &lpm_entry, 1162 RPE0f, (aux_flags & SOC_ALPM_AUX_DEF_ROUTE) ? 1 : 0); 1163 soc_mem_field32_set(unit, lpm_mem, &lpm_entry, 1164 ALG_HIT_IDX0f, hit_idx); 1165 soc_mem_field32_set(unit, lpm_mem, 1166 &lpm_entry, SRC_DISCARD0f, 1167 (aux_flags & SOC_ALPM_AUX_SRC_DISCARD) ? 1 : 0); 1168 /* Hardware doesn't update entry1 for IPv6-64 1169 soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry, 1170 REPLACE_DATA1f, (uint32 *)&replace_data); 1171 soc_mem_field32_set(unit, lpm_mem, &lpm_entry, 1172 RPE1f, pfx_len == 0 ? 1 : 0); 1173 soc_mem_field32_set(unit, lpm_mem, &lpm_entry, 1174 ALG_HIT_IDX1f, hit_idx); 1175 */ 1176 } else { 1177 soc_mem_field_set(unit, lpm_mem, (uint32 *)&lpm_entry, 1178 (tcam_index & 1) ? REPLACE_DATA1f : REPLACE_DATA0f, 1179 (uint32 *)&replace_data); 1180 soc_mem_field32_set(unit, lpm_mem, &lpm_entry, 1181 (tcam_index & 1) ? RPE1f : RPE0f, 1182 (aux_flags & SOC_ALPM_AUX_DEF_ROUTE) ? 1 : 0); 1183 soc_mem_field32_set(unit, lpm_mem, &lpm_entry, 1184 (tcam_index & 1) ? ALG_HIT_IDX1f : ALG_HIT_IDX0f, 1185 hit_idx); 1186 soc_mem_field32_set(unit, lpm_mem, &lpm_entry, 1187 (tcam_index & 1) ? SRC_DISCARD1f : SRC_DISCARD0f, 1188 (aux_flags & SOC_ALPM_AUX_SRC_DISCARD) ? 1 : 0); 1189 } 1190 (void) _soc_th_mem_alpm_write_on_sw_propagate( 1191 unit, lpm_mem, MEM_BLOCK_ALL, 1192 lpm_index, &lpm_entry); 1193 } 1194 } 1195 } 1196 soc_mem_unlock(unit, lpm_mem); 1197 1198 /* Do not update L3_DEFIP_AUX_TABLEm if aux table is disabled */ 1199 if (!ALPM_CTRL(unit).aux_enable) { 1200 return SOC_E_NONE; 1201 } 1202 1203 /* Update L3_DEFIP_AUX_TABLEm */ 1204 lpm_mem = L3_DEFIP_AUX_TABLEm; 1205 1206 soc_mem_lock(unit, lpm_mem); 1207 rv = _soc_th_mem_alpm_read_on_sw_propagate( 1208 unit, lpm_mem, MEM_BLOCK_ANY, aux_index, &shadow_entry); 1209 if (SOC_SUCCESS(rv)) { 1210 if (mode == 1) { /* IPv6_64 */ 1211 soc_mem_field32_set(unit, lpm_mem, &shadow_entry, 1212 BPM_LENGTH0f, rpl_bpm_len); 1213 soc_mem_field32_set(unit, lpm_mem, &shadow_entry, 1214 BPM_LENGTH1f, rpl_bpm_len); 1215 } else { /* IPv4 */ 1216 soc_mem_field32_set(unit, lpm_mem, &shadow_entry, 1217 (tcam_index & 1) ? BPM_LENGTH1f : BPM_LENGTH0f, 1218 rpl_bpm_len); 1219 } 1220 (void) _soc_th_mem_alpm_write_on_sw_propagate( 1221 unit, lpm_mem, MEM_BLOCK_ALL, aux_index, &shadow_entry); 1222 if (SOC_URPF_STATUS_GET(unit)) { 1223 aux_index = _URPF_INDEX(TRUE, aux_index, L3_DEFIP_AUX_TABLEm); 1224 rv = _soc_th_mem_alpm_read_on_sw_propagate( 1225 unit, lpm_mem, MEM_BLOCK_ANY, aux_index, &shadow_entry); 1226 if (SOC_SUCCESS(rv)) { 1227 if (mode == 1) { /* IPv6_64 */ 1228 soc_mem_field32_set(unit, lpm_mem, &shadow_entry, 1229 BPM_LENGTH0f, rpl_bpm_len); 1230 soc_mem_field32_set(unit, lpm_mem, &shadow_entry, 1231 BPM_LENGTH1f, rpl_bpm_len); 1232 } else { /* IPv4 */ 1233 soc_mem_field32_set(unit, lpm_mem, &shadow_entry, 1234 (tcam_index & 1) ? BPM_LENGTH1f : BPM_LENGTH0f, 1235 rpl_bpm_len); 1236 } 1237 (void) _soc_th_mem_alpm_write_on_sw_propagate( 1238 unit, lpm_mem, MEM_BLOCK_ALL, 1239 aux_index, &shadow_entry); 1240 } 1241 } 1242 } 1243 soc_mem_unlock(unit, lpm_mem); 1244 1245 } else if (mode == 3) { 1246 soc_mem_t lpm128_mem = L3_DEFIP_PAIR_128m; 1247 defip_pair_128_entry_t lpm128_entry; 1248 1249 lpm_index = soc_th_alpm_logical_idx(unit, L3_DEFIP_PAIR_128m, 1250 SOC_ALPM_128_DEFIP_TO_PAIR(unit, tcam_index >> 1), 1); 1251 aux_index = SOC_ALPM_128_DEFIP_TO_PAIR(unit, tcam_index >> 1); 1252 LOG_INFO(BSL_LS_SOC_ALPM, 1253 (BSL_META_U(unit, "ALPM SW %s ppg cb: lpm_mem %s index %d, " 1254 "AUX_TABLE index0 %d index1 %d\n"), 1255 (user_data->aux_op == INSERT_PROPAGATE) ? "Add" : "Del", 1256 SOC_MEM_NAME(unit, lpm128_mem), lpm_index, 1257 SOC_ALPM_128_ADDR_LWR(unit, aux_index), 1258 SOC_ALPM_128_ADDR_UPR(unit, aux_index))); 1259 1260 /* Update L3_DEFIP_PAIR_128m */ 1261 soc_mem_lock(unit, lpm128_mem); 1262 rv = _soc_th_mem_alpm_read_on_sw_propagate( 1263 unit, lpm128_mem, MEM_BLOCK_ANY, lpm_index, &lpm128_entry); 1264 if (SOC_SUCCESS(rv)) { 1265 soc_mem_field_set(unit, lpm128_mem, (uint32 *)&lpm128_entry, 1266 REPLACE_DATAf, (uint32 *)&replace_data); 1267 (void) _soc_th_mem_alpm_write_on_sw_propagate( 1268 unit, lpm128_mem, MEM_BLOCK_ALL, 1269 lpm_index, &lpm128_entry); 1270 if (SOC_URPF_STATUS_GET(unit)) { 1271 lpm_index = _URPF_INDEX(TRUE, lpm_index, L3_DEFIP_PAIR_128m); 1272 rv = _soc_th_mem_alpm_read_on_sw_propagate( 1273 unit, lpm128_mem, MEM_BLOCK_ANY, 1274 lpm_index, &lpm128_entry); 1275 if (SOC_SUCCESS(rv)) { 1276 soc_mem_field_set(unit, lpm128_mem, (uint32 *)&lpm128_entry, 1277 REPLACE_DATAf, (uint32 *)&replace_data); 1278 soc_mem_field32_set(unit, lpm128_mem, &lpm128_entry, 1279 RPEf, (aux_flags & SOC_ALPM_AUX_DEF_ROUTE) ? 1 : 0); 1280 soc_mem_field32_set(unit, lpm128_mem, &lpm128_entry, 1281 ALG_HIT_IDXf, hit_idx); 1282 soc_mem_field32_set(unit, lpm128_mem, 1283 &lpm128_entry, SRC_DISCARDf, 1284 (aux_flags & SOC_ALPM_AUX_SRC_DISCARD) ? 1 : 0); 1285 (void) _soc_th_mem_alpm_write_on_sw_propagate( 1286 unit, lpm128_mem, MEM_BLOCK_ALL, 1287 lpm_index, &lpm128_entry); 1288 1289 } 1290 } 1291 } 1292 soc_mem_unlock(unit, lpm128_mem); 1293 1294 /* Do not update L3_DEFIP_AUX_TABLEm if aux table is disabled */ 1295 if (!ALPM_CTRL(unit).aux_enable) { 1296 return SOC_E_NONE; 1297 } 1298 1299 /* Update L3_DEFIP_AUX_TABLEm */ 1300 lpm128_mem = L3_DEFIP_AUX_TABLEm; 1301 1302 soc_mem_lock(unit, lpm128_mem); 1303 /* Needs to update 2 AUX_TABLE entries */ 1304 for (i = 0; i < 2; i++) { 1305 int index; 1306 index = ((i == 0) ? 1307 SOC_ALPM_128_ADDR_LWR(unit, aux_index) : 1308 SOC_ALPM_128_ADDR_UPR(unit, aux_index)); 1309 rv = _soc_th_mem_alpm_read_on_sw_propagate( 1310 unit, lpm128_mem, MEM_BLOCK_ANY, index, &shadow_entry); 1311 if (SOC_SUCCESS(rv)) { 1312 soc_mem_field32_set(unit, lpm128_mem, &shadow_entry, 1313 BPM_LENGTH0f, rpl_bpm_len); 1314 soc_mem_field32_set(unit, lpm128_mem, &shadow_entry, 1315 BPM_LENGTH1f, rpl_bpm_len); 1316 (void) _soc_th_mem_alpm_write_on_sw_propagate( 1317 unit, lpm128_mem, MEM_BLOCK_ALL, 1318 index, &shadow_entry); 1319 if (SOC_URPF_STATUS_GET(unit)) { 1320 index = _URPF_INDEX(TRUE, index, lpm128_mem); 1321 rv = _soc_th_mem_alpm_read_on_sw_propagate( 1322 unit, lpm128_mem, MEM_BLOCK_ANY, 1323 index, &shadow_entry); 1324 if (SOC_SUCCESS(rv)) { 1325 soc_mem_field32_set(unit, lpm128_mem, &shadow_entry, 1326 BPM_LENGTH0f, rpl_bpm_len); 1327 soc_mem_field32_set(unit, lpm128_mem, &shadow_entry, 1328 BPM_LENGTH1f, rpl_bpm_len); 1329 (void) _soc_th_mem_alpm_write_on_sw_propagate( 1330 unit, lpm128_mem, MEM_BLOCK_ALL, 1331 index, &shadow_entry); 1332 } 1333 } 1334 } 1335 } 1336 soc_mem_unlock(unit, lpm128_mem); 1337 } else { 1338 return SOC_E_INTERNAL; 1339 } 1340 1341 return SOC_E_NONE; 1342 } 1343 1344 /* 1345 * ipv4: ip6_word[4] = 1346 * {IP_ADDR0f, 0, 0, 0} 1347 * ipv6-64: ip6_word[4] = 1348 * {0, 0, IP_ADDR0f, IP_ADDR1f} 1349 * ipv6-128: ip6_word[4] = 1350 * {IP_ADDR0_LWRf, IP_ADDR1_LWRf, IP_ADDR0_UPRf, IP_ADDR1_UPRf} 1351 */ 1352 STATIC void 1353 _soc_th_alpm_trie_prefix_create(int u, int mode, uint32 *ip6_word, uint32 len, 1354 uint32 *pfx) 1355 { 1356 int i; 1357 uint32 pfx_shift, tmp; 1358 1359 pfx[0] = pfx[1] = pfx[2] = pfx[3] = pfx[4] = 0; 1360 /* Obtain prefix length */ 1361 if (mode == 0) { 1362 pfx[1] = SHR_SHIFT_RIGHT(ip6_word[0], 32 - len); 1363 pfx[0] = 0; 1364 } else if (mode == 1) { 1365 pfx[4] = ip6_word[2]; 1366 pfx[3] = ip6_word[3]; 1367 1368 pfx_shift = 64 - len; 1369 if (pfx_shift < 32) { 1370 /* get lower half shifted */ 1371 pfx[4] >>= pfx_shift; 1372 /* isolate shifted stuff of upper half */ 1373 tmp = SHR_SHIFT_LEFT(pfx[3], 32 - pfx_shift); 1374 pfx[3] >>= pfx_shift; 1375 pfx[4] |= tmp; 1376 } else { 1377 pfx[4] = SHR_SHIFT_RIGHT(pfx[3], pfx_shift - 32); 1378 pfx[3] = 0; 1379 } 1380 } else { 1381 /* PAIR_128 style, for both mode==2 and mode==3 */ 1382 int start; 1383 uint32 tmp_pfx[5] = {0}; 1384 tmp_pfx[0] = ip6_word[0]; 1385 tmp_pfx[1] = ip6_word[1]; 1386 tmp_pfx[2] = ip6_word[2]; 1387 tmp_pfx[3] = ip6_word[3]; 1388 1389 /* shift entire prefix right to remove trailing 0s in prefix */ 1390 /* to simplify, words which are all 0s are ignored to begin with, so 1391 * a right shift of say 46 is a right shift of 46-32 = 14, but starting 1392 * from word 1. Once all shifting is done, shift all words to right by 1 1393 */ 1394 pfx_shift = 128 - len; 1395 start = pfx_shift / 32; 1396 pfx_shift = pfx_shift % 32; 1397 for (i = start; i < 4; i++) { 1398 tmp_pfx[i] >>= pfx_shift; 1399 tmp = tmp_pfx[i+1] & ((1 << pfx_shift) - 1); 1400 tmp = SHR_SHIFT_LEFT(tmp, 32 - pfx_shift); 1401 tmp_pfx[i] |= tmp; 1402 } 1403 /* make shift right justified and also reverse order for trie. 1404 * Also, note trie sees key only in words 1 to 4 1405 */ 1406 for (i = start; i < 4; i++) { 1407 pfx[4 - (i - start)] = tmp_pfx[i]; 1408 } 1409 } 1410 return ; 1411 } 1412 1413 void 1414 _soc_th_alpm_mask_prefix_create(int u, int mode, uint32 mask_len, uint32 *mask) 1415 { 1416 int len; 1417 uint32 ip6_word[4] = {0}; 1418 1419 len = mask_len; 1420 if (mode == 0) { 1421 ip6_word[0] = (len == 32) ? 0x1 : (0xffffffff >> len) + 1; 1422 } else if (mode == 1) { 1423 if (len >= 32) { 1424 ip6_word[3] = 0; 1425 ip6_word[2] = SHR_SHIFT_RIGHT(0xffffffff, len - 32) + 1; 1426 } else { 1427 ip6_word[3] = (0xffffffff >> len) + 1; 1428 ip6_word[2] = 0; 1429 } 1430 } else { 1431 /* Compatible of hardware mode value and L3_DEFIP_MODE_128 */ 1432 int i; 1433 for (i = 0; i < 4; i++) { 1434 if (len <= 32) break; 1435 ip6_word[3-i] = 0; 1436 len -= 32; 1437 } 1438 ip6_word[3-i] = SHR_SHIFT_RIGHT(0xffffffff, len) + 1; 1439 } 1440 1441 return _soc_th_alpm_trie_prefix_create(u, mode, ip6_word, mask_len, mask); 1442 1443 } 1444 1445 /* Create prefix & len in trie format from aux entry */ 1446 STATIC void 1447 _soc_th_alpm_aux_prefix_create(int u, void *aux_entry, uint32 *pfx, uint32 *len) 1448 { 1449 uint32 ip6_word[4]; 1450 int mode; 1451 soc_mem_t aux_mem = L3_DEFIP_AUX_SCRATCHm; 1452 1453 soc_mem_field_get(u, aux_mem, aux_entry, IP_ADDRf, (uint32 *)ip6_word); 1454 *len = soc_mem_field32_get(u, aux_mem, aux_entry, IP_LENGTHf); 1455 mode = soc_mem_field32_get(u, aux_mem, aux_entry, MODE_f(u)); 1456 1457 return _soc_th_alpm_trie_prefix_create(u, mode, ip6_word, *len, pfx); 1458 } 1459 1460 /* Software propagation */ 1461 STATIC int 1462 _soc_th_alpm_aux_sw_op(int u, _soc_aux_op_t aux_op, void *aux_entry, 1463 int *match_cnt, int aux_flags) 1464 { 1465 trie_t *pivot; 1466 int rv = SOC_E_NONE; 1467 int vld, mode, dbt, vrf = 0; 1468 uint32 prefix[5]; 1469 uint32 len; 1470 trie_bpm_cb_user_data_t user_data; 1471 soc_mem_t aux_mem = L3_DEFIP_AUX_SCRATCHm; 1472 int insert = 0; 1473 1474 switch (aux_op) { 1475 case INSERT_PROPAGATE: 1476 insert = 1; 1477 break; 1478 case DELETE_PROPAGATE: 1479 insert = 0; 1480 break; 1481 case HITBIT_REPLACE: 1482 case PREFIX_LOOKUP: 1483 default: 1484 return SOC_E_NONE; 1485 } 1486 1487 vld = soc_mem_field32_get(u, aux_mem, aux_entry, VALIDf); 1488 mode = soc_mem_field32_get(u, aux_mem, aux_entry, MODE_f(u)); 1489 vrf = soc_mem_field32_get(u, aux_mem, aux_entry, VRFf); 1490 dbt = soc_mem_field32_get(u, aux_mem, aux_entry, DB_TYPEf); 1491 1492 /* Need to distinguish vrf=0 and Global low */ 1493 if (vrf == 0 && dbt <= 1) { 1494 vrf = SOC_VRF_MAX(u) + 1; 1495 } 1496 1497 /* Mode indicates entry type: 00:IPv4, 01: 64-Ipv6, 11: IPv6-128 */ 1498 if (mode == 0) { 1499 pivot = VRF_PIVOT_TRIE_IPV4(u, vrf); 1500 } else if (mode == 1) { 1501 pivot = VRF_PIVOT_TRIE_IPV6(u, vrf); 1502 } else if (mode == 3) { 1503 pivot = VRF_PIVOT_TRIE_IPV6_128(u, vrf); 1504 } else { 1505 return SOC_E_INTERNAL; 1506 } 1507 1508 _soc_th_alpm_aux_prefix_create(u, aux_entry, (void *)prefix, &len); 1509 1510 sal_memset(&user_data, 0, sizeof(user_data)); 1511 user_data.unit = u; 1512 user_data.entry = aux_entry; 1513 user_data.aux_op = aux_op; 1514 user_data.flags = aux_flags; 1515 1516 if (vld && pivot) { 1517 rv = _soc_th_alpm_sw_propagate(u, pivot, prefix, len, insert, 1518 _soc_th_alpm_propagate_callback, &user_data); 1519 } 1520 1521 if (insert) { 1522 _alpm_dbg_cntr[u].ppg_cb_insert += user_data.count; 1523 } else { 1524 _alpm_dbg_cntr[u].ppg_cb_delete += user_data.count; 1525 } 1526 1527 if (match_cnt != NULL) { 1528 *match_cnt = user_data.count; 1529 } 1530 1531 return rv; 1532 1533 } 1534 1535 STATIC void 1536 _alpm_128_trie_to_normal_ip(uint32 *result, int length) 1537 { 1538 uint32 pfx_shift, tmp, start, prefix[6]; 1539 int i; 1540 1541 sal_memcpy(prefix, result, sizeof(uint32) * BITS2WORDS(_MAX_KEY_LEN_144_)); 1542 sal_memset(result, 0, sizeof(uint32) * BITS2WORDS(_MAX_KEY_LEN_144_)); 1543 1544 /* shift entire prefix left to add trailing 0s in prefix */ 1545 pfx_shift = 128 - length; 1546 start = (pfx_shift + 31) / 32; 1547 /* fix corner case: */ 1548 if ((pfx_shift % 32) == 0) { 1549 start++; 1550 } 1551 pfx_shift = pfx_shift % 32; 1552 for (i = start; i <= 4; i++) { 1553 prefix[i] <<= pfx_shift; 1554 tmp = prefix[i+1] & ~(0xffffffff >> pfx_shift); 1555 tmp = SHR_SHIFT_RIGHT(tmp, 32 - pfx_shift); 1556 if (i < 4) { 1557 prefix[i] |= tmp; 1558 } 1559 } 1560 /* make shift left justified and reversed, i.e, lsw goes to index 0 */ 1561 for (i = start; i <= 4; i++) { 1562 result[3 - (i - start)] = prefix[i]; 1563 } 1564 } 1565 1566 STATIC int 1567 _soc_alpm_pivot_traverse_check_cb(trie_node_t *trie, void *datum) 1568 { 1569 trie_bpm_cb_user_data_t *cbdata; 1570 trie_t *pivot; 1571 alpm_pivot_t *pivot_pyld; 1572 soc_mem_t mem = L3_DEFIP_AUX_TABLEm; 1573 soc_field_t fld = BPM_LENGTH0f; 1574 defip_aux_table_entry_t ent; 1575 int u, index, lpm_idx, quiet; 1576 int v6, vrf, rv = SOC_E_NONE; 1577 1578 cbdata = datum; 1579 pivot = cbdata->entry; 1580 u = cbdata->unit; 1581 v6 = cbdata->ipv6; 1582 quiet = cbdata->count; 1583 vrf = cbdata->aux_op; 1584 if (trie->type == PAYLOAD) { 1585 uint32 addr[5]; 1586 uint32 hw_bpm_len, bpm_len = -1; 1587 pivot_pyld = (alpm_pivot_t *)trie; 1588 1589 sal_memcpy(addr, pivot_pyld->key, sizeof(addr)); 1590 if (v6 == L3_DEFIP_MODE_128) { 1591 _alpm_128_trie_to_normal_ip(addr, pivot_pyld->len); 1592 } else { 1593 ALPM_TRIE_TO_NORMAL_IP(addr, pivot_pyld->len, v6); 1594 } 1595 1596 index = PIVOT_TCAM_INDEX(pivot_pyld) >> 1; 1597 if (v6 == L3_DEFIP_MODE_128) { 1598 index = SOC_ALPM_128_DEFIP_TO_PAIR(u, index); 1599 lpm_idx = soc_th_alpm_logical_idx(u, L3_DEFIP_PAIR_128m, index, 1); 1600 index = SOC_ALPM_128_ADDR_LWR(u, index); 1601 } else { 1602 lpm_idx = soc_th_alpm_logical_idx(u, L3_DEFIPm, index, 1); 1603 } 1604 1605 if (!v6 && (PIVOT_TCAM_INDEX(pivot_pyld) & 1)) { 1606 fld = BPM_LENGTH1f; 1607 } 1608 1609 if (ALPM_CTRL(u).trie_user_ppg) { 1610 bpm_len = PIVOT_TCAM_BPMLEN(pivot_pyld); 1611 } else { 1612 rv = trie_find_prefix_bpm(pivot, pivot_pyld->key, 1613 pivot_pyld->len, &bpm_len); 1614 if (rv < 0) { 1615 cli_out("Searching bpm[vrf %d] failed, AUX[%d]->LOG[%d]: " 1616 "0x%08x.0x%08x.0x%08x.0x%08x/%d, rv = %d\n", vrf, 1617 index, lpm_idx, 1618 addr[3], addr[2], addr[1], addr[0], pivot_pyld->len, rv); 1619 return SOC_E_NONE; 1620 } 1621 } 1622 1623 SOC_IF_ERROR_RETURN(soc_mem_read(u, mem, MEM_BLOCK_ANY, index, &ent)); 1624 hw_bpm_len = soc_mem_field32_get(u, mem, &ent, fld); 1625 1626 if (!quiet || (hw_bpm_len != bpm_len)) { 1627 cli_out("Touching AUX[%d]->LOG[%d]: vrf %d v6 %d addr:", 1628 index, lpm_idx, vrf, v6); 1629 if (v6 == L3_DEFIP_MODE_128) { 1630 cli_out("0x%08x 0x%08x 0x%08x 0x%08x/%d\n", addr[3], addr[2], 1631 addr[1], addr[0], pivot_pyld->len); 1632 } else if (v6 == L3_DEFIP_MODE_64) { 1633 cli_out("0x%08x 0x%08x/%d\n", addr[1], addr[0], pivot_pyld->len); 1634 } else { 1635 cli_out("0x%08x/%d\n", addr[0], pivot_pyld->len); 1636 } 1637 } 1638 1639 if (hw_bpm_len != bpm_len) { 1640 cli_out("\t==> bpm_len mismatch hw %d trie %d\n", 1641 hw_bpm_len, bpm_len); 1642 } else { 1643 if (!quiet) { 1644 cli_out("\t==> bpm_len %d\n", bpm_len); 1645 } 1646 } 1647 } 1648 return SOC_E_NONE; 1649 } 1650 1651 void 1652 soc_alpm_pivot_traverse_check(int u, int quiet) 1653 { 1654 int rv, vrf, v6; 1655 trie_t *pivot = NULL; 1656 trie_bpm_cb_user_data_t cbdata; 1657 1658 for (vrf = 0; vrf <= SOC_VRF_MAX(u) + 1; vrf++) { 1659 for (v6 = L3_DEFIP_MODE_V4; v6 <= L3_DEFIP_MODE_128; v6++) { 1660 if (v6 == L3_DEFIP_MODE_V4) { 1661 pivot = VRF_PIVOT_TRIE_IPV4(u, vrf); 1662 } else if (v6 == L3_DEFIP_MODE_64) { 1663 pivot = VRF_PIVOT_TRIE_IPV6(u, vrf); 1664 } else if (v6 == L3_DEFIP_MODE_128) { 1665 pivot = VRF_PIVOT_TRIE_IPV6_128(u, vrf); 1666 } 1667 1668 if (pivot == NULL) { 1669 continue; 1670 } 1671 1672 sal_memset(&cbdata, 0, sizeof(cbdata)); 1673 cbdata.unit = u; 1674 cbdata.ipv6 = v6; 1675 cbdata.entry = pivot; 1676 cbdata.count = quiet; 1677 cbdata.aux_op = vrf; 1678 1679 rv = trie_traverse(pivot, _soc_alpm_pivot_traverse_check_cb, 1680 &cbdata, _TRIE_INORDER_TRAVERSE); 1681 if (SOC_FAILURE(rv)) { 1682 cli_out("Traverse Pivot v6 %d vrf %d failed rv=%d\n", v6, vrf, rv); 1683 } 1684 } 1685 } 1686 } 1687 1688 static int 1689 _soc_th_alpm_mask_len_get(int u, int ipv6, void *entry, int *pfx) 1690 { 1691 int rv; 1692 uint32 ipv4a; 1693 1694 if (ipv6) { 1695 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f); 1696 if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) { 1697 return(rv); 1698 } 1699 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK1f); 1700 if (*pfx) { 1701 if (ipv4a != 0xffffffff) { 1702 return(SOC_E_PARAM); 1703 } 1704 *pfx += 32; 1705 } else { 1706 if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) { 1707 return(rv); 1708 } 1709 } 1710 } else { 1711 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f); 1712 if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) { 1713 return(rv); 1714 } 1715 } 1716 1717 return SOC_E_NONE; 1718 } 1719 1720 1721 void 1722 soc_th_alpm_bank_dis(int u, int vrf, uint32 *bnk_dis_4b, uint32 *bnk_dis_8b) 1723 { 1724 uint32 b4 = 0, b8 = 0; 1725 int global = (vrf == SOC_VRF_MAX(u) + 1) ? 1 : 0; 1726 1727 /* TD3 Only has room for 4 bits. 1728 * In full bank mode (UFT_SHARED_BANKS_CONTROL__ALPM_MODE == 0), 1729 * Bit 0 disables banks 0,1. 1730 * Bit 1 disables banks 2,3. 1731 * Bit 2 disables banks 4,5. 1732 * Bit 3 disables banks 6,7. 1733 * In half bank mode, (UFT_SHARED_BANKS_CONTROL__ALPM_MODE == 1) 1734 * Bit 0 disables bank 0. 1735 * Bit 1 disables bank 1. 1736 * Bit 2 disables bank 2. 1737 * Bit 3 disables bank 3. 1738 */ 1739 1740 if (ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_PARALLEL && 1741 SOC_URPF_STATUS_GET(u)) { 1742 if (ALPM_CTRL(u).num_banks <= 2) { 1743 b4 = global ? 0xD : 0xE; /* 1101 : 1110 */ 1744 b8 = b4; 1745 } else if (ALPM_CTRL(u).num_banks <= 4) { 1746 b4 = global ? 0x3 : 0xC; /* 0011 : 1100 */ 1747 if (SOC_IS_TRIDENT3X(u)) { 1748 b8 = global ? 0xF3 : 0xFC; /* 11110011 : 11111100 */ 1749 } else { 1750 b8 = b4; 1751 } 1752 } else { /* 8 Banks mode */ 1753 b4 = global ? 0x3 : 0xC; /* 0011 : 1100 */ 1754 if (SOC_IS_TRIDENT3X(u)) { 1755 b8 = global ? 0xF : 0xF0; /* 00001111 : 11110000 */ 1756 } else { 1757 b8 = b4; 1758 } 1759 } 1760 } else { 1761 if (ALPM_CTRL(u).num_banks <= 2) { 1762 b4 = 0xC; /* 1100 */ 1763 b8 = b4; 1764 } else if (ALPM_CTRL(u).num_banks <= 4) { 1765 b4 = 0; 1766 if (SOC_IS_TRIDENT3X(u)) { 1767 b8 = 0xF0; 1768 } else { 1769 b8 = b4; 1770 } 1771 } else { 1772 b4 = 0; 1773 b8 = b4; 1774 } 1775 } 1776 1777 if (bnk_dis_4b != NULL) { 1778 *bnk_dis_4b = b4; 1779 } 1780 1781 if (bnk_dis_8b != NULL) { 1782 *bnk_dis_8b = b8; 1783 } 1784 1785 return ; 1786 } 1787 1788 int 1789 _soc_th_alpm_rpf_entry(int u, int idx) 1790 { 1791 int bkt; 1792 int bank_bits = ALPM_CTRL(u).bank_bits; 1793 bkt = (idx >> bank_bits) & ALPM_CTRL(u).bkt_mask; 1794 bkt += SOC_TH_ALPM_BUCKET_COUNT(u); 1795 /* form rpf alpm entry index */ 1796 return (idx & ~(ALPM_CTRL(u).bkt_mask << bank_bits)) | (bkt << bank_bits); 1797 } 1798 1799 /* for v4 full = 0, for v6-64 full = 1 */ 1800 int 1801 soc_th_alpm_physical_idx(int u, soc_mem_t mem, int index, int full) 1802 { 1803 int tmp = index & 1; 1804 1805 if (full) { 1806 return soc_alpm_l3_defip_index_map(u, mem, index); 1807 } 1808 index >>= 1; 1809 index = soc_alpm_l3_defip_index_map(u, mem, index); 1810 index <<= 1; 1811 index |= tmp; 1812 return index; 1813 } 1814 1815 int 1816 soc_th_alpm_logical_idx(int u, soc_mem_t mem, int index, int full) 1817 { 1818 int tmp = index & 1; 1819 1820 if (full) { 1821 return soc_alpm_l3_defip_index_remap(u, mem, index); 1822 } 1823 index >>= 1; 1824 index = soc_alpm_l3_defip_index_remap(u, mem, index); 1825 index <<= 1; 1826 index |= tmp; 1827 return index; 1828 } 1829 1830 static void 1831 _soc_th_alpm_pfx_len_to_mask(int u, void *lpm_entry, int len, int ipv6) 1832 { 1833 uint32 mask = 0; 1834 1835 if (ipv6) { 1836 if (len >= 32) { 1837 mask = 0xffffffff; 1838 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, mask); 1839 mask = ~SHR_SHIFT_RIGHT(0xffffffff, len - 32); 1840 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, mask); 1841 } else { 1842 mask = ~(0xffffffff >> len); 1843 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, mask); 1844 /* make sure lower word of mask is 0 */ 1845 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, 0); 1846 } 1847 } else { 1848 assert(len <= 32); 1849 mask = (len == 32) ? 0xffffffff : ~(0xffffffff >> len); 1850 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, mask); 1851 } 1852 } 1853 /* Create Prefix */ 1854 /* Prefix is created based on the trie key packing expectations */ 1855 /* Prefix[0] will have higher order Word, Prefix[1] will have lower order word 1856 * in case of IPV6. For IPV4 prefix[0] will contain the prefix 1857 */ 1858 static int 1859 _soc_th_alpm_prefix_create(int u, int ipv6, void *entry, uint32 *prefix, 1860 uint32 *pfx_len, int *default_route) 1861 { 1862 int ip, ip_mask; 1863 int pfx = 0; 1864 int rv = SOC_E_NONE; 1865 uint32 pfx_shift, tmp; 1866 1867 prefix[0] = prefix[1] = prefix[2] = prefix[3] = prefix[4] = 0; 1868 1869 /* Form Prefix based on the entry */ 1870 ip = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR0f); 1871 ip_mask = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f); 1872 1873 prefix[1] = ip; 1874 1875 ip = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR1f); 1876 ip_mask = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK1f); 1877 1878 prefix[0] = ip; 1879 1880 /* Obtain prefix length */ 1881 if (ipv6) { 1882 prefix[4] = prefix[1]; 1883 prefix[3] = prefix[0]; 1884 prefix[1] = prefix[0] = 0; 1885 ip_mask = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f); 1886 if ((rv = _ipmask2pfx(ip_mask, &pfx)) < 0) { 1887 return(rv); 1888 } 1889 ip_mask = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK1f); 1890 if (pfx) { 1891 if (ip_mask != 0xffffffff) { 1892 return(SOC_E_PARAM); 1893 } 1894 pfx += 32; 1895 } else { 1896 if ((rv = _ipmask2pfx(ip_mask, &pfx)) < 0) { 1897 return(rv); 1898 } 1899 } 1900 pfx_shift = 64 - pfx; 1901 if (pfx_shift < 32) { 1902 /* get lower half shifted */ 1903 prefix[4] >>= pfx_shift; 1904 /* isolate shifted stuff of upper half */ 1905 tmp = SHR_SHIFT_LEFT(prefix[3], 32 - pfx_shift); 1906 prefix[3] >>= pfx_shift; 1907 prefix[4] |= tmp; 1908 } else { 1909 prefix[4] = SHR_SHIFT_RIGHT(prefix[3], pfx_shift - 32); 1910 prefix[3] = 0; 1911 } 1912 } else { 1913 ip_mask = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f); 1914 if ((rv = _ipmask2pfx(ip_mask, &pfx)) < 0) { 1915 return(rv); 1916 } 1917 prefix[1] = SHR_SHIFT_RIGHT(prefix[1], 32 - pfx); 1918 prefix[0] = 0; 1919 } 1920 *pfx_len = pfx; 1921 *default_route = (prefix[0] == 0) && (prefix[1] == 0) && (pfx == 0); 1922 return SOC_E_NONE; 1923 } 1924 1925 int 1926 _soc_th_alpm_find_in_bkt(int u, soc_mem_t mem, int log_bkt, int bank_disable, 1927 uint32 *e, void *alpm_data, int *key_index, int v6) 1928 { 1929 int rv; 1930 rv = soc_mem_alpm_lookup(u, mem, ALPM_PHY_BKT(u, log_bkt), 1931 MEM_BLOCK_ANY, 1932 bank_disable, 1933 e, alpm_data, key_index); 1934 if (SOC_SUCCESS(rv)) { 1935 return rv; 1936 } 1937 if (ALPM_CTRL(u).double_wide[v6]) { 1938 return soc_mem_alpm_lookup(u, mem, ALPM_PHY_BKT(u, log_bkt) + 1, 1939 MEM_BLOCK_ANY, bank_disable, e, alpm_data, 1940 key_index); 1941 } 1942 return rv; 1943 } 1944 1945 static int 1946 _soc_th_alpm_sw_pivot_find(int u, uint32 *prefix, uint32 length, int v6, int vrf, 1947 int *hit, int *tcam_index, int *log_bkt) 1948 { 1949 int rv = SOC_E_NONE; 1950 trie_t *pivot_trie; 1951 trie_node_t *lpmp = NULL; 1952 alpm_pivot_t *pivot_pyld; 1953 1954 if (v6) { 1955 pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf); 1956 } else { 1957 pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf); 1958 } 1959 rv = trie_find_lpm(pivot_trie, prefix, length, &lpmp); 1960 if (SOC_FAILURE(rv)) { 1961 LOG_ERROR(BSL_LS_SOC_ALPM, 1962 (BSL_META_U(u, 1963 "Pivot find failed\n"))); 1964 return rv; 1965 } 1966 pivot_pyld = (alpm_pivot_t *)lpmp; 1967 1968 *hit = 1; 1969 *tcam_index = PIVOT_TCAM_INDEX(pivot_pyld); 1970 *log_bkt = PIVOT_BUCKET_INDEX(pivot_pyld); 1971 1972 return SOC_E_NONE; 1973 } 1974 1975 1976 1977 int 1978 _soc_th_alpm_sw_prefix_check(int u, 1979 soc_mem_t mem, /* Mem type for ALPM */ 1980 int v6, 1981 void *key_data, /* TCAM entry data */ 1982 int vrf_id, 1983 int vrf) 1984 { 1985 int rv = SOC_E_NONE; 1986 uint32 prefix[5], length; 1987 int default_route = 0; 1988 trie_t *pivot_trie, *bkt_trie; 1989 trie_node_t *lpmp = NULL; 1990 alpm_pivot_t *pivot_node; 1991 if (vrf_id == 0) { 1992 if (soc_alpm_cmn_mode_get(u) == SOC_ALPM_MODE_PARALLEL || 1993 soc_alpm_cmn_mode_get(u) == SOC_ALPM_MODE_TCAM_ALPM) { 1994 return SOC_E_PARAM; 1995 } 1996 } 1997 if (!(ALPM_PREFIX_IN_TCAM(u, vrf_id))) { 1998 rv = _soc_th_alpm_prefix_create(u, v6, key_data, prefix, &length, 1999 &default_route); 2000 if (SOC_FAILURE(rv)) { 2001 LOG_ERROR(BSL_LS_SOC_ALPM, 2002 (BSL_META_U(u, 2003 "_soc_th_alpm_sw_prefix_check: prefix create failed\n"))); 2004 return rv; 2005 } 2006 if (v6) { 2007 pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf); 2008 } else { 2009 pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf); 2010 } 2011 rv = trie_find_lpm(pivot_trie, prefix, length, &lpmp); 2012 if (SOC_FAILURE(rv)) { 2013 LOG_ERROR(BSL_LS_SOC_ALPM, 2014 (BSL_META_U(u, 2015 "_soc_th_alpm_sw_prefix_check: Pivot find failed\n"))); 2016 return rv; 2017 } 2018 pivot_node = (alpm_pivot_t *)lpmp; 2019 bkt_trie = pivot_node->bucket->bucket_trie; 2020 if (bkt_trie != NULL) { 2021 rv = trie_search(bkt_trie, prefix, length, 2022 (trie_node_t **)&bkt_trie); 2023 if (SOC_FAILURE(rv)){ 2024 LOG_ERROR(BSL_LS_SOC_ALPM, 2025 (BSL_META_U(u, 2026 "_soc_th_alpm_sw_prefix_check: prefix find failed\n"))); 2027 } 2028 } else { 2029 LOG_ERROR(BSL_LS_SOC_ALPM, 2030 (BSL_META_U(u, 2031 "_soc_th_alpm_sw_prefix_check: bkt trie doesn't exist\n"))); 2032 } 2033 } 2034 return rv; 2035 } 2036 2037 /* 2038 * Find and read the match in the database. 2039 * Returns SOC_E_NONE, if found. 2040 * SOC_E_NOT_FOUND if not found 2041 * SOC_E_FAIL, if lookup failed. 2042 */ 2043 2044 static int 2045 _soc_th_alpm_find(int u, 2046 soc_mem_t mem, /* Mem type for ALPM */ 2047 int v6, 2048 void *key_data, /* TCAM entry data */ 2049 int vrf_id, 2050 int vrf, 2051 void *alpm_data, /* Alpm data if match */ 2052 int *tcam_index, /* TCAM INDEX */ 2053 int *log_bkt, /* return Bucket ID */ 2054 int *index_ptr, /* return key location */ 2055 int sw_find) 2056 { 2057 uint32 *e = NULL; 2058 defip_aux_scratch_entry_t *aux_entry = NULL; 2059 int key_index ; 2060 uint32 db_type, ent_type, bank_disable; 2061 int rv = SOC_E_NONE; 2062 int hit = 0; 2063 2064 e = sal_alloc(sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS, "buf_tmp"); 2065 if (e == NULL) { 2066 rv = SOC_E_MEMORY; 2067 goto clean_up; 2068 } 2069 2070 sal_memset(e, 0, sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS); 2071 2072 if (vrf_id == 0) { 2073 if (ALPM_CTRL(u).gp_zoned) { 2074 /* cannot have 0 as a VRF in parallel mode */ 2075 return SOC_E_PARAM; 2076 } 2077 } 2078 2079 bank_disable = ALPM_CTRL(u).bank_disable_bmp[vrf != (SOC_VRF_MAX(u) + 1)]; 2080 soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type); 2081 2082 /* For VRF_OVERRIDE (Global High) entries, software needs to maintain the 2083 * index */ 2084 /* Prefix resides in TCAM directly */ 2085 if (!(ALPM_PREFIX_IN_TCAM(u, vrf_id))) { 2086 if (sw_find) { 2087 uint32 prefix[5], length; 2088 int default_route = 0; 2089 2090 /* Create Prefix */ 2091 rv = _soc_th_alpm_prefix_create(u, v6, key_data, prefix, &length, 2092 &default_route); 2093 if (SOC_FAILURE(rv)) { 2094 LOG_ERROR(BSL_LS_SOC_ALPM, 2095 (BSL_META_U(u, 2096 "_soc_alpm_insert: prefix create failed\n"))); 2097 goto clean_up; 2098 } 2099 2100 SOC_IF_ERROR_RETURN(_soc_th_alpm_sw_pivot_find(u, prefix, length, v6, 2101 vrf, &hit, tcam_index, 2102 log_bkt)); 2103 } else { 2104 /* Fill in AUX Scratch and perform Lookup Operation */ 2105 aux_entry = sal_alloc(sizeof(defip_aux_scratch_entry_t), "aux_entry"); 2106 if (aux_entry == NULL) { 2107 rv = SOC_E_MEMORY; 2108 goto clean_up; 2109 } 2110 sal_memset(aux_entry, 0, sizeof(defip_aux_scratch_entry_t)); 2111 SOC_IF_ERROR_RETURN( 2112 _soc_th_alpm_fill_aux_entry_for_op(u, key_data, v6, db_type, ent_type, 2113 0, aux_entry)); 2114 SOC_IF_ERROR_RETURN( 2115 _soc_th_alpm_aux_op(u, PREFIX_LOOKUP, aux_entry, TRUE, &hit, 2116 tcam_index, log_bkt, 0)); 2117 } 2118 if (hit) { /* Entry is found in the log_bkt */ 2119 /* Fill entry for lookup */ 2120 _soc_th_alpm_mem_ent_init(u, v6, key_data, e, 0, mem, 0, 0, *log_bkt); 2121 2122 /* Perform lookup */ 2123 rv = _soc_th_alpm_find_in_bkt(u, mem, *log_bkt, bank_disable, 2124 e, alpm_data, &key_index, v6); 2125 if (SOC_SUCCESS(rv)) { 2126 *index_ptr = key_index; 2127 } 2128 } else { 2129 rv = SOC_E_NOT_FOUND; 2130 } 2131 } 2132 clean_up: 2133 if (e) { 2134 sal_free(e); 2135 } 2136 if (aux_entry) { 2137 sal_free(aux_entry); 2138 } 2139 return rv; 2140 } 2141 2142 /* 2143 * Find and update the match in the database. 2144 * Returns SOC_E_NONE, if found and updated. 2145 * SOC_E_NOT_FOUND if not found 2146 * SOC_E_FAIL, if update failed. 2147 */ 2148 static int 2149 _soc_th_alpm_find_and_update(int u, 2150 int v6, 2151 void *key_data, /* TCAM entry data */ 2152 void *alpm_data, /* Alpm data to be updated with */ 2153 void *alpm_sip_data, 2154 soc_mem_t mem, /* Mem view for ALPM data */ 2155 int key_index) /* key location */ 2156 { 2157 defip_aux_scratch_entry_t aux_entry; 2158 int vrf_id, vrf; 2159 int log_bkt; 2160 uint32 db_type, ent_type; 2161 int rv = SOC_E_NONE; 2162 int hit = 0, tmp = 0; 2163 int tcam_index, index; 2164 int aux_flags = 0; 2165 uint32 alpm_ent[SOC_MAX_MEM_FIELD_WORDS]; 2166 2167 SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf)); 2168 soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type); 2169 /* For VRF_OVERRIDE (Global High) entries */ 2170 if (!(ALPM_PREFIX_IN_TCAM(u, vrf_id))) { 2171 /* Fill in AUX Scratch and perform Lookup Operation */ 2172 sal_memset(&aux_entry, 0, sizeof(defip_aux_scratch_entry_t)); 2173 SOC_IF_ERROR_RETURN( 2174 _soc_th_alpm_fill_aux_entry_for_op(u, key_data, v6, db_type, 2175 ent_type, 0, &aux_entry)); 2176 /* Perform lookup */ 2177 SOC_ALPM_LPM_LOCK(u); 2178 /* Find and update the entry */ 2179 rv = _soc_th_alpm_find(u, mem, v6, key_data, vrf_id, vrf, alpm_ent, 2180 &tcam_index, &log_bkt, &index, TRUE); 2181 SOC_ALPM_LPM_UNLOCK(u); 2182 SOC_IF_ERROR_RETURN(rv); 2183 if (ALPM_CTRL(u).bkt_sharing) { 2184 soc_mem_field32_set(u, mem, alpm_data, SUB_BKT_PTRf, 2185 ALPM_SUB_BKT(u, log_bkt)); 2186 } 2187 /* Update the entry */ 2188 SOC_IF_ERROR_RETURN( 2189 soc_mem_write(u, mem, MEM_BLOCK_ANY, ALPM_ENT_INDEX(key_index), 2190 alpm_data)); 2191 if (SOC_URPF_STATUS_GET(u)) { 2192 if (ALPM_CTRL(u).bkt_sharing) { 2193 soc_mem_field32_set(u, mem, alpm_sip_data, SUB_BKT_PTRf, 2194 ALPM_SUB_BKT(u, log_bkt)); 2195 } 2196 /* Update the sip entry */ 2197 SOC_IF_ERROR_RETURN(soc_mem_write(u, mem, MEM_BLOCK_ANY, 2198 _soc_th_alpm_rpf_entry(u, ALPM_ENT_INDEX(key_index)), 2199 alpm_sip_data)); 2200 if (rv != SOC_E_NONE) { 2201 return SOC_E_FAIL; 2202 } 2203 } 2204 /* set REPLACE_LEN field to correct value */ 2205 tmp = soc_mem_field32_get(u, L3_DEFIP_AUX_SCRATCHm, 2206 &aux_entry, IP_LENGTHf); 2207 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, &aux_entry, 2208 REPLACE_LENf, tmp); 2209 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, &aux_entry, ALG_HIT_IDXf, 2210 ALPM_ENT_INDEX(key_index)); 2211 2212 /* We used DELETE_PROPAGATE before because in TD2, INSERT Propagate 2213 * doesn't handle '==' case, so we need DELETE instead. 2214 * but DELETE can't be used against software trie-tree for non-delete 2215 * purpose. 2216 * 2217 * So need to bring INSERT back. 2218 * 2219 * *** For Trident2, don't turn on TCAM cache. *** 2220 */ 2221 if (SOC_URPF_STATUS_GET(u)) { 2222 if (soc_mem_field32_get(u, mem, alpm_sip_data, DEFAULTROUTEf)) { 2223 aux_flags |= SOC_ALPM_AUX_DEF_ROUTE; 2224 } 2225 if (soc_mem_field32_get(u, mem, alpm_sip_data, SRC_DISCARDf)) { 2226 aux_flags |= SOC_ALPM_AUX_SRC_DISCARD; 2227 } 2228 } 2229 2230 SOC_IF_ERROR_RETURN(_soc_th_alpm_aux_op(u, 2231 SOC_IS_TRIDENT2(u) ? DELETE_PROPAGATE : INSERT_PROPAGATE, 2232 &aux_entry, TRUE, &hit, &tcam_index, &log_bkt, aux_flags)); 2233 2234 if (0) { /* uRPF case */ 2235 /* propagate SIP too */ 2236 /* Check default route */ 2237 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, &aux_entry, 2238 DEFAULTROUTEf, tmp == 0 ? 1 : 0); 2239 2240 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, &aux_entry, 2241 DB_TYPEf, db_type + 1); 2242 tmp = soc_mem_field32_get(u, L3_DEFIP_AUX_SCRATCHm, &aux_entry, 2243 ALG_HIT_IDXf); 2244 if (tmp > 0) { 2245 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, &aux_entry, 2246 ALG_HIT_IDXf, _soc_th_alpm_rpf_entry(u, tmp)); 2247 } 2248 SOC_IF_ERROR_RETURN(_soc_th_alpm_aux_op(u, 2249 SOC_IS_TRIDENT2(u) ? DELETE_PROPAGATE : INSERT_PROPAGATE, 2250 &aux_entry, TRUE, &hit, &tcam_index, &log_bkt, 0)); 2251 } 2252 } 2253 return rv; 2254 } 2255 2256 /* Update hit bits in batch */ 2257 STATIC int 2258 _soc_th_alpm_hit_bits_hw_update(int u, alpm_mem_prefix_array_t *pa, 2259 int *new_index, int urpf) 2260 { 2261 int i, index, old_index; 2262 defip_aux_hitbit_update_entry_t entry; 2263 soc_mem_t mem = L3_DEFIP_AUX_HITBIT_UPDATEm; 2264 int batch_count = soc_mem_index_count(u, mem); 2265 2266 for (i = 0, index = 0; i < pa->count; i++) { 2267 old_index = pa->prefix[i]->index; 2268 sal_memset(&entry, 0, sizeof(entry)); 2269 if (old_index > 0) { 2270 soc_mem_field32_set(u, mem, &entry, VALIDf, 1); 2271 if (!urpf) { 2272 soc_mem_field32_set(u, mem, &entry, HITBIT_PTRf, 2273 old_index); 2274 soc_mem_field32_set(u, mem, &entry, REPLACEMENT_PTRf, 2275 new_index[i]); 2276 } else { 2277 soc_mem_field32_set(u, mem, &entry, HITBIT_PTRf, 2278 _soc_th_alpm_rpf_entry(u, old_index)); 2279 soc_mem_field32_set(u, mem, &entry, REPLACEMENT_PTRf, 2280 _soc_th_alpm_rpf_entry(u, new_index[i])); 2281 } 2282 } 2283 SOC_IF_ERROR_RETURN( 2284 soc_mem_write(u, mem, MEM_BLOCK_ANY, index, &entry)); 2285 2286 if (++index == batch_count) { 2287 SOC_IF_ERROR_RETURN(_soc_th_alpm_aux_op(u, HITBIT_REPLACE, NULL, 2288 FALSE, NULL, NULL, NULL, 0)); 2289 index = 0; 2290 } 2291 } 2292 2293 if (index) { 2294 /* Reset trailing entries */ 2295 for (i = index; i < batch_count; i++) { 2296 sal_memset(&entry, 0, sizeof(entry)); 2297 SOC_IF_ERROR_RETURN( 2298 soc_mem_write(u, mem, MEM_BLOCK_ANY, i, &entry)); 2299 } 2300 SOC_IF_ERROR_RETURN(_soc_th_alpm_aux_op(u, HITBIT_REPLACE, NULL, 2301 FALSE, NULL, NULL, NULL, 0)); 2302 } 2303 return SOC_E_NONE; 2304 } 2305 2306 int 2307 soc_th_alpm_hit_bits_update(int u, alpm_mem_prefix_array_t *pa, int *new_idx, 2308 int ipv6, int vrf) 2309 { 2310 int rv = SOC_E_NONE; 2311 int cb_cnt = 1; 2312 2313 /* Skip to update hit bits */ 2314 if (ALPM_CTRL(u).hit_bits_skip) { 2315 return rv; 2316 } 2317 2318 /* Only required when TCAM table cache is on */ 2319 if (ALPM_CTRL(u).hit_idx_upd) { 2320 rv = _soc_th_alpm_hit_bits_sw_update(u, pa, new_idx, &cb_cnt, ipv6, vrf); 2321 } 2322 2323 /* No Hardware propagation if aux table is disabled */ 2324 if (!ALPM_CTRL(u).aux_enable) { 2325 return rv; 2326 } 2327 2328 if ((SOC_SUCCESS(rv) && cb_cnt > 0) || ALPM_CTRL(u).force_aux_op) { 2329 rv = _soc_th_alpm_hit_bits_hw_update(u, pa, new_idx, 0); 2330 if (SOC_URPF_STATUS_GET(u) && SOC_SUCCESS(rv)) { 2331 rv = _soc_th_alpm_hit_bits_hw_update(u, pa, new_idx, 1); 2332 } 2333 } 2334 2335 return rv; 2336 } 2337 2338 /* Callback function for Traverse, to find Leaf nodes */ 2339 int 2340 _soc_th_alpm_mem_prefix_array_cb(trie_node_t *node, void *info) 2341 { 2342 alpm_mem_prefix_array_t *prefix_array = (alpm_mem_prefix_array_t *)info; 2343 if (node->type == PAYLOAD) { 2344 prefix_array->prefix[prefix_array->count] = (payload_t *)node; 2345 prefix_array->count++; 2346 } 2347 return SOC_E_NONE; 2348 } 2349 2350 /* Get entry No. per bucket based on various setting */ 2351 int 2352 _soc_th_alpm_bkt_entry_cnt(int u, soc_mem_t mem) 2353 { 2354 int bkt_ent_max = 0; 2355 int v6 = 0; 2356 2357 /* Base entry number */ 2358 switch (mem) { 2359 case L3_DEFIP_ALPM_IPV4m: 2360 bkt_ent_max = ALPM_IPV4_BKT_COUNT; 2361 v6 = 0; 2362 break; 2363 case L3_DEFIP_ALPM_IPV4_1m: 2364 bkt_ent_max = ALPM_IPV4_BKT_COUNT_FLEX; 2365 v6 = 0; 2366 break; 2367 case L3_DEFIP_ALPM_IPV6_64m: 2368 bkt_ent_max = ALPM_IPV6_64_BKT_COUNT; 2369 v6 = 1; 2370 break; 2371 case L3_DEFIP_ALPM_IPV6_64_1m: 2372 bkt_ent_max = ALPM_IPV6_64_BKT_COUNT_FLEX; 2373 v6 = 1; 2374 break; 2375 case L3_DEFIP_ALPM_IPV6_128m: 2376 bkt_ent_max = ALPM_IPV6_128_BKT_COUNT; 2377 v6 = 1; 2378 break; 2379 default: 2380 bkt_ent_max = ALPM_IPV4_BKT_COUNT; 2381 break; 2382 } 2383 2384 /* TD3 has 8 banks */ 2385 if (SOC_IS_TRIDENT3X(u)) { 2386 bkt_ent_max <<= 1; 2387 } 2388 2389 /* Double-wide mode check */ 2390 if (ALPM_CTRL(u).double_wide[v6]) { 2391 bkt_ent_max <<= 1; 2392 } 2393 2394 /* 2-bank mode check */ 2395 if (ALPM_CTRL(u).half_bkt_mode) { 2396 bkt_ent_max >>= 1; 2397 } 2398 2399 /* Global & vrf sharing & uRPF mode check */ 2400 if (ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_PARALLEL && 2401 SOC_URPF_STATUS_GET(u)) { 2402 bkt_ent_max >>= 1; 2403 } 2404 2405 return bkt_ent_max; 2406 } 2407 2408 2409 /* Connect TCAM entry to a bucket ID */ 2410 STATIC int 2411 _soc_th_alpm_bucket_link(int u, int v6, int pivot_index, int log_bkt) 2412 { 2413 int rv = SOC_E_NONE; 2414 int lpm_index; 2415 soc_mem_t lpm_mem = L3_DEFIPm; 2416 defip_entry_t lpm_entry; 2417 int phy_bkt, sub_bkt; 2418 2419 phy_bkt = ALPM_PHY_BKT(u, log_bkt); 2420 sub_bkt = ALPM_SUB_BKT(u, log_bkt); 2421 2422 /* Connect TCAM entry to new bucket */ 2423 lpm_index = soc_th_alpm_logical_idx(u, lpm_mem, pivot_index >> 1, 1); 2424 2425 rv = _soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY, lpm_index, &lpm_entry); 2426 SOC_IF_ERROR_RETURN(rv); 2427 if ((!v6) && (pivot_index & 1)) { 2428 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, &lpm_entry, ALG_BKT_PTR1f, phy_bkt); 2429 if (ALPM_CTRL(u).bkt_sharing) { 2430 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, &lpm_entry, ALG_SUB_BKT_PTR1f, sub_bkt); 2431 } 2432 } else { 2433 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, &lpm_entry, ALG_BKT_PTR0f, phy_bkt); 2434 if (ALPM_CTRL(u).bkt_sharing) { 2435 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, &lpm_entry, ALG_SUB_BKT_PTR0f, sub_bkt); 2436 } 2437 } 2438 rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, lpm_index, &lpm_entry); 2439 SOC_IF_ERROR_RETURN(rv); 2440 2441 if (SOC_URPF_STATUS_GET(u)) { 2442 int _urpf_index = soc_th_alpm_logical_idx(u, lpm_mem, pivot_index >> 1, 1) 2443 + (soc_mem_index_count(u, lpm_mem) >> 1); 2444 rv = _soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY, 2445 _urpf_index, &lpm_entry); 2446 SOC_IF_ERROR_RETURN(rv); 2447 2448 if ((!v6) && (pivot_index & 1)) { 2449 soc_mem_field32_set(u, lpm_mem, &lpm_entry, ALG_BKT_PTR1f, 2450 phy_bkt + SOC_TH_ALPM_BUCKET_COUNT(u)); 2451 if (ALPM_CTRL(u).bkt_sharing) { 2452 soc_mem_field32_set(u, lpm_mem, &lpm_entry, ALG_SUB_BKT_PTR1f, sub_bkt); 2453 } 2454 } else { 2455 soc_mem_field32_set(u, lpm_mem, &lpm_entry, ALG_BKT_PTR0f, 2456 phy_bkt + SOC_TH_ALPM_BUCKET_COUNT(u)); 2457 if (ALPM_CTRL(u).bkt_sharing) { 2458 soc_mem_field32_set(u, lpm_mem, &lpm_entry, ALG_SUB_BKT_PTR0f, sub_bkt); 2459 } 2460 } 2461 2462 rv = WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, _urpf_index, &lpm_entry); 2463 SOC_IF_ERROR_RETURN(rv); 2464 } 2465 2466 return rv; 2467 } 2468 2469 2470 static void 2471 _soc_th_alpm_bucket_prepare_undo(int u, 2472 alpm_mem_prefix_array_t **alloc_pfx_array, 2473 void **alloc_bufp, 2474 void **alloc_sip_bufp, 2475 int **alloc_new_index) 2476 { 2477 if (*alloc_pfx_array) { 2478 sal_free(*alloc_pfx_array); 2479 *alloc_pfx_array = NULL; 2480 } 2481 if (*alloc_bufp) { 2482 sal_free(*alloc_bufp); 2483 *alloc_bufp = NULL; 2484 } 2485 if (*alloc_sip_bufp) { 2486 sal_free(*alloc_sip_bufp); 2487 *alloc_sip_bufp = NULL; 2488 } 2489 if (*alloc_new_index) { 2490 sal_free(*alloc_new_index); 2491 *alloc_new_index = NULL; 2492 } 2493 } 2494 2495 2496 static int 2497 _soc_th_alpm_bucket_prepare(int u, soc_mem_t mem, 2498 trie_t *bkt_trie, 2499 alpm_mem_prefix_array_t **alloc_pfx_array, 2500 void **alloc_bufp, 2501 void **alloc_sip_bufp, 2502 int **alloc_new_index) 2503 { 2504 int i, rv = SOC_E_NONE; 2505 int entry_size; 2506 int alloc_size; 2507 /* allocation pointers all set to NULL */ 2508 void *bufp = NULL, *sip_bufp = NULL; 2509 int *index_array = NULL; 2510 alpm_mem_prefix_array_t *pfx_array = NULL; 2511 2512 *alloc_bufp = NULL; 2513 *alloc_sip_bufp = NULL; 2514 *alloc_new_index = NULL; 2515 *alloc_pfx_array = NULL; 2516 2517 /* Alloc prefix array */ 2518 alloc_size = sizeof(alpm_mem_prefix_array_t); 2519 pfx_array = sal_alloc(alloc_size, "prefix array"); 2520 if (pfx_array == NULL) { 2521 goto cleanup; 2522 } 2523 2524 /* Fill prefix array */ 2525 sal_memset(pfx_array, 0, alloc_size); 2526 rv = trie_traverse(bkt_trie, _soc_th_alpm_mem_prefix_array_cb, 2527 pfx_array, _TRIE_INORDER_TRAVERSE); 2528 if (SOC_FAILURE(rv)) { 2529 goto cleanup; 2530 } 2531 2532 /* Alloc index array */ 2533 alloc_size = sizeof(int) * pfx_array->count; 2534 index_array = sal_alloc(alloc_size, "index_array"); 2535 if (index_array == NULL) { 2536 goto cleanup; 2537 } 2538 sal_memset(index_array, -1, alloc_size); 2539 2540 /* Alloc bufp & sip_bufp */ 2541 entry_size = (L3_DEFIP_ALPM_IPV6_64m == mem || 2542 L3_DEFIP_ALPM_IPV6_64_1m == mem) ? 2543 sizeof(defip_alpm_ipv6_64_1_entry_t) : 2544 sizeof(defip_alpm_ipv4_1_entry_t); 2545 2546 alloc_size = entry_size * pfx_array->count; 2547 bufp = sal_alloc(alloc_size, "alloc_bufp"); 2548 if (bufp == NULL) { 2549 goto cleanup; 2550 } 2551 if (SOC_URPF_STATUS_GET(u)) { 2552 sip_bufp = sal_alloc(alloc_size, "alloc_sip_bufp"); 2553 if (sip_bufp == NULL) { 2554 goto cleanup; 2555 } 2556 } 2557 2558 /* Fill bufp & sip bufp */ 2559 for (i = 0; i < pfx_array->count; i++) { 2560 payload_t *prefix = pfx_array->prefix[i]; 2561 2562 if (prefix->index > 0) { /* old prefix */ 2563 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, prefix->index, 2564 (uint8 *)bufp + i * entry_size); 2565 2566 if (SOC_FAILURE(rv)) { 2567 break; 2568 } 2569 2570 if (SOC_URPF_STATUS_GET(u)) { 2571 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, 2572 _soc_th_alpm_rpf_entry(u, prefix->index), 2573 (uint8 *)sip_bufp + i * entry_size); 2574 if (SOC_FAILURE(rv)) { 2575 break; 2576 } 2577 } 2578 } 2579 } 2580 if (SOC_FAILURE(rv)) { 2581 goto cleanup; 2582 } 2583 2584 *alloc_bufp = bufp; 2585 *alloc_sip_bufp = sip_bufp; 2586 *alloc_new_index = index_array; 2587 *alloc_pfx_array = pfx_array; 2588 2589 return rv; 2590 2591 cleanup: 2592 if (bufp) { 2593 sal_free(bufp); 2594 } 2595 if (sip_bufp) { 2596 sal_free(sip_bufp); 2597 } 2598 if (index_array) { 2599 sal_free(index_array); 2600 } 2601 if (pfx_array) { 2602 sal_free(pfx_array); 2603 } 2604 return rv; 2605 } 2606 2607 static void 2608 _soc_th_alpm_bucket_inval_undo(int u, soc_mem_t mem, 2609 alpm_mem_prefix_array_t *pfx_array, 2610 void *old_bufp, void *old_sip_bufp) 2611 { 2612 int i; 2613 int entry_size = (L3_DEFIP_ALPM_IPV6_64m == mem || 2614 L3_DEFIP_ALPM_IPV6_64_1m == mem) ? 2615 sizeof(defip_alpm_ipv6_64_1_entry_t) : 2616 sizeof(defip_alpm_ipv4_1_entry_t); 2617 2618 for (i = 0; i < pfx_array->count; i++) { 2619 payload_t *prefix = pfx_array->prefix[i]; 2620 2621 if (prefix->index > 0) { 2622 soc_mem_write(u, mem, MEM_BLOCK_ALL, prefix->index, 2623 (uint8 *)old_bufp + i * entry_size); 2624 2625 if (SOC_URPF_STATUS_GET(u)) { 2626 /* UPRF entry */ 2627 soc_mem_write(u, mem, MEM_BLOCK_ALL, 2628 _soc_th_alpm_rpf_entry(u, prefix->index), 2629 (uint8 *)old_sip_bufp + i * entry_size); 2630 } 2631 } 2632 } 2633 return; 2634 } 2635 2636 2637 static int 2638 _soc_th_alpm_bucket_inval(int u, soc_mem_t mem, 2639 alpm_mem_prefix_array_t *pfx_array, 2640 void *old_bufp, void *old_sip_bufp) 2641 { 2642 int i, rv = SOC_E_NONE; 2643 2644 /* Invalidation process 2645 * 1. Erase old copied entries 2646 * 2. Re-validate those entries if invalidation fails 2647 */ 2648 2649 for (i = 0; i < pfx_array->count; i++) { 2650 payload_t *prefix = pfx_array->prefix[i]; 2651 2652 if (prefix->index >= 0) { 2653 /* zero out old entries now that split is done */ 2654 rv = soc_mem_write(u, mem, MEM_BLOCK_ALL, prefix->index, 2655 soc_mem_entry_null(u, mem)); 2656 if (SOC_FAILURE(rv)) { 2657 break; 2658 } 2659 if (SOC_URPF_STATUS_GET(u)) { 2660 rv = soc_mem_write(u, mem, MEM_BLOCK_ANY, 2661 _soc_th_alpm_rpf_entry(u, prefix->index), 2662 soc_mem_entry_null(u, mem)); 2663 if (SOC_FAILURE(rv)) { 2664 break; 2665 } 2666 } 2667 } 2668 } 2669 2670 /* re-validate old bucket entries */ 2671 if (SOC_FAILURE(rv)) { 2672 _soc_th_alpm_bucket_inval_undo(u, mem, pfx_array, old_bufp, old_sip_bufp); 2673 } 2674 2675 return rv; 2676 } 2677 2678 STATIC int 2679 _soc_th_alpm_split_lpm_init(int u, 2680 soc_mem_t mem, 2681 int pivot_idx_from, 2682 int vrf, 2683 int log_bkt, 2684 void *alpm_data, 2685 void *alpm_sip_data, 2686 uint32 *pivot, 2687 int length, 2688 defip_entry_t *lpm_entry, 2689 uint32 *bpm_len, 2690 uint32 *bpm, 2691 uint32 *src_discard, 2692 uint32 *src_default) 2693 { 2694 int rv = SOC_E_NONE, v6; 2695 trie_node_t *lpm = NULL; 2696 payload_t *bkt_lpm = NULL; 2697 trie_t *pfx_trie; 2698 defip_alpm_ipv4_1_entry_t alpmv4_entry, alpmv4_sip_entry; 2699 defip_alpm_ipv6_64_1_entry_t alpmv6_entry, alpmv6_sip_entry; 2700 uint32 tmp_pivot[5] = {0}; 2701 2702 v6 = SOC_ALPM_MEM_V6(mem); 2703 2704 /* prefix trie */ 2705 if (v6) { 2706 pfx_trie = VRF_PREFIX_TRIE_IPV6(u, vrf); 2707 } else { 2708 pfx_trie = VRF_PREFIX_TRIE_IPV4(u, vrf); 2709 } 2710 2711 /* find longest prefix that covers pivot */ 2712 lpm = NULL; 2713 rv = trie_find_lpm(pfx_trie, pivot, length, &lpm); 2714 if (SOC_FAILURE(rv)) { 2715 LOG_ERROR(BSL_LS_SOC_ALPM, 2716 (BSL_META_U(u, 2717 "unit %d Unable to find lpm for pivot: " 2718 "0x%08x 0x%08x\n 0x%08x 0x%08x 0x%08x length: %d\n"), 2719 u, pivot[0], pivot[1], pivot[2], pivot[3], pivot[4], 2720 length)); 2721 2722 return rv; 2723 } 2724 bkt_lpm = ((payload_t *)lpm)->bkt_ptr; 2725 2726 /* Initialize the lpm entry to insert */ 2727 if (bkt_lpm) { 2728 int index, vrf_id; 2729 void *bufp, *sip_bufp = NULL; 2730 2731 SOC_ALPM_ENTRY_BUF(v6, mem, bufp, alpmv4_entry, alpmv6_entry); 2732 SOC_ALPM_ENTRY_BUF(v6, mem, sip_bufp, alpmv4_sip_entry, alpmv6_sip_entry); 2733 2734 /* this means this bucket default route is an actual route */ 2735 /* initialize new pivot's associated data with data of lpm match */ 2736 index = bkt_lpm->index; 2737 if (index == -1) { 2738 /* this means the new route is the bucket's default */ 2739 if (alpm_data == NULL || alpm_sip_data == NULL) { 2740 return SOC_E_PARAM; 2741 } 2742 sal_memcpy(bufp, alpm_data, v6 ? 2743 sizeof(defip_alpm_ipv6_64_1_entry_t) : 2744 sizeof(defip_alpm_ipv4_1_entry_t)); 2745 if (SOC_URPF_STATUS_GET(u)) { 2746 *src_default = soc_mem_field32_get(u, mem, alpm_sip_data, 2747 DEFAULTROUTEf); 2748 *src_discard = soc_mem_field32_get(u, mem, alpm_sip_data, 2749 SRC_DISCARDf); 2750 } 2751 } else { 2752 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, index, bufp); 2753 if (SOC_FAILURE(rv)) { 2754 return rv; 2755 } 2756 if (SOC_URPF_STATUS_GET(u)) { 2757 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, 2758 _soc_th_alpm_rpf_entry(u, index), 2759 sip_bufp); 2760 *src_default = soc_mem_field32_get(u, mem, sip_bufp, 2761 DEFAULTROUTEf); 2762 *src_discard = soc_mem_field32_get(u, mem, sip_bufp, 2763 SRC_DISCARDf); 2764 } 2765 } 2766 if (SOC_FAILURE(rv)) { 2767 return rv; 2768 } 2769 2770 vrf_id = vrf; 2771 if (vrf == (SOC_VRF_MAX(u) + 1)) { 2772 vrf_id = SOC_L3_VRF_GLOBAL; 2773 } 2774 rv = _soc_th_alpm_lpm_ent_init(u, bufp, mem, v6, vrf_id, log_bkt, 2775 index, lpm_entry, 2776 VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 1)); 2777 if (SOC_FAILURE(rv)) { 2778 return rv; 2779 } 2780 /* remember the bpm_len of this pivot. Need to put in shadow */ 2781 *bpm_len = bkt_lpm->len; 2782 if (ALPM_CTRL(u).trie_propagate) { 2783 (void)trie_bpm_mask_get(pfx_trie, bkt_lpm->key, *bpm_len, bpm); 2784 } 2785 } else { 2786 /* read default data of current pivot */ 2787 /* This case is for those route without default route 0.0.0.0/0, 2788 * e.g. Parallel mode / (Combined mode + global low) 2789 * An internal assiciated data is used. 2790 */ 2791 rv = _soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY, 2792 soc_th_alpm_logical_idx(u, L3_DEFIPm, pivot_idx_from >> 1, 1), 2793 lpm_entry); 2794 if (SOC_FAILURE(rv)) { 2795 return rv; 2796 } 2797 if ((!v6) && (pivot_idx_from & 1)) { 2798 /* move entry to 0 half */ 2799 rv = soc_th_alpm_lpm_ip4entry1_to_0(u, lpm_entry, lpm_entry, 0); 2800 } 2801 /* Need to reset ALG_HIT_IDX0 to 0. */ 2802 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ALG_HIT_IDX0f, 0); 2803 2804 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ALG_BKT_PTR0f, 2805 ALPM_PHY_BKT(u, log_bkt)); 2806 if (ALPM_CTRL(u).bkt_sharing) { 2807 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ALG_SUB_BKT_PTR0f, 2808 ALPM_SUB_BKT(u, log_bkt)); 2809 } 2810 } 2811 2812 /* Convert is a self-modified op, thus use tmp one */ 2813 sal_memcpy(tmp_pivot, pivot, sizeof(tmp_pivot)); 2814 2815 /* Convert from trie format to h/w format */ 2816 ALPM_TRIE_TO_NORMAL_IP(tmp_pivot, length, v6); 2817 _soc_th_alpm_lpm_ent_key_init(u, tmp_pivot, length, vrf, v6, 2818 lpm_entry, 0); 2819 2820 return rv; 2821 } 2822 2823 2824 static int 2825 _soc_th_alpm_split_pivot_create_undo(int u, int v6, int vrf, uint32 *pivot, 2826 uint32 length, alpm_pivot_t *alpm_pivot, 2827 int clear) 2828 { 2829 int rv = SOC_E_NONE, pivot_index; 2830 alpm_bucket_handle_t *bucket_handle; 2831 trie_t *pivot_trie = NULL; 2832 trie_node_t *delp = NULL; 2833 2834 if (v6) { 2835 pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf); 2836 } else { 2837 pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf); 2838 } 2839 2840 if (alpm_pivot == NULL) { 2841 rv = trie_delete(pivot_trie, pivot, length, &delp); 2842 alpm_pivot = (alpm_pivot_t *) delp; 2843 } 2844 if (SOC_SUCCESS(rv)) { 2845 bucket_handle = alpm_pivot->bucket; 2846 pivot_index = PIVOT_TCAM_INDEX(alpm_pivot); 2847 2848 trie_destroy(PIVOT_BUCKET_TRIE(alpm_pivot)); 2849 sal_free(alpm_pivot); 2850 sal_free(bucket_handle); 2851 2852 /* For normal destroy (other than rollback) when the entry is deleted 2853 * from lpm. The pivot_index is already replaced to another index. 2854 */ 2855 if (clear) { 2856 ALPM_TCAM_PIVOT(u, pivot_index) = NULL; 2857 } 2858 } 2859 2860 return rv; 2861 } 2862 2863 2864 2865 static int 2866 _soc_th_alpm_split_pivot_create(int u, int v6, int vrf, int log_bkt_to, 2867 trie_node_t *split_trie_root, 2868 uint32 *pivot, 2869 uint32 length, 2870 uint32 bpm_len, 2871 uint32 *bpm, 2872 alpm_pivot_t **new_pivot) 2873 { 2874 int rv = SOC_E_NONE; 2875 alpm_pivot_t *pivot_pyld_new; 2876 alpm_bucket_handle_t *bucket_handle; 2877 trie_t *pivot_trie = NULL; 2878 if (v6) { 2879 pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf); 2880 } else { 2881 pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf); 2882 } 2883 2884 /* Add New Pivot to the pivot trie */ 2885 bucket_handle = sal_alloc(sizeof(alpm_bucket_handle_t), 2886 "ALPM Bucket Handle"); 2887 if (bucket_handle == 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 return SOC_E_MEMORY; 2893 } 2894 sal_memset(bucket_handle, 0, sizeof(*bucket_handle)); 2895 pivot_pyld_new = sal_alloc(sizeof(alpm_pivot_t), 2896 "Payload for new Pivot"); 2897 if (pivot_pyld_new == NULL) { 2898 LOG_ERROR(BSL_LS_SOC_ALPM, 2899 (BSL_META_U(u, 2900 "Unable to allocate memory " 2901 "for PIVOT trie node \n"))); 2902 sal_free(bucket_handle); 2903 return SOC_E_MEMORY; 2904 } 2905 sal_memset(pivot_pyld_new, 0, sizeof(*pivot_pyld_new)); 2906 PIVOT_BUCKET_HANDLE(pivot_pyld_new) = bucket_handle; 2907 (void) trie_init(v6 ? _MAX_KEY_LEN_144_ :_MAX_KEY_LEN_48_, 2908 &PIVOT_BUCKET_TRIE(pivot_pyld_new)); 2909 PIVOT_BUCKET_TRIE(pivot_pyld_new)->trie = split_trie_root; 2910 PIVOT_BUCKET_INDEX(pivot_pyld_new) = log_bkt_to; 2911 PIVOT_BUCKET_VRF(pivot_pyld_new) = vrf; 2912 PIVOT_BUCKET_IPV6(pivot_pyld_new) = v6; 2913 PIVOT_BUCKET_DEF(pivot_pyld_new) = FALSE; 2914 PIVOT_TCAM_BPMLEN(pivot_pyld_new) = bpm_len; 2915 2916 (pivot_pyld_new)->key[0] = pivot[0]; 2917 (pivot_pyld_new)->key[1] = pivot[1]; 2918 (pivot_pyld_new)->key[2] = pivot[2]; 2919 (pivot_pyld_new)->key[3] = pivot[3]; 2920 (pivot_pyld_new)->key[4] = pivot[4]; 2921 (pivot_pyld_new)->len = length; 2922 2923 rv = trie_insert(pivot_trie, pivot, 2924 ALPM_CTRL(u).trie_propagate ? bpm : NULL, 2925 length, (trie_node_t *)pivot_pyld_new); 2926 2927 if (SOC_SUCCESS(rv)) { 2928 if (new_pivot) { 2929 *new_pivot = pivot_pyld_new; 2930 } 2931 } else { 2932 LOG_ERROR(BSL_LS_SOC_ALPM, 2933 (BSL_META_U(u, "could not initialize pivot"))); 2934 _soc_th_alpm_split_pivot_create_undo(u, v6, vrf, pivot, 2935 length, pivot_pyld_new, 1); 2936 } 2937 2938 return rv; 2939 } 2940 2941 2942 static void 2943 _soc_th_alpm_bucket_copy_undo(int u, soc_mem_t mem, int count, int *new_index) 2944 { 2945 int i; 2946 for (i = 0; i < count; i++) { 2947 if (new_index[i] < 0) { 2948 continue; 2949 } 2950 soc_mem_write(u, mem, MEM_BLOCK_ANY, new_index[i], 2951 soc_mem_entry_null(u, mem)); 2952 if (SOC_URPF_STATUS_GET(u)) { 2953 soc_mem_write(u, mem, MEM_BLOCK_ANY, 2954 _soc_th_alpm_rpf_entry(u, new_index[i]), 2955 soc_mem_entry_null(u, mem)); 2956 } 2957 } 2958 } 2959 2960 2961 /* Populate entries in pfx array to logical bucket */ 2962 static int 2963 _soc_th_alpm_bucket_copy(int u, soc_mem_t mem, int vrf, 2964 alpm_mem_prefix_array_t *pfx_array, 2965 int log_bkt_to, 2966 void *old_bufp, 2967 void *old_sip_bufp, 2968 void *new_bufp, 2969 void *new_sip_bufp, 2970 int *new_index, 2971 int *new_index_pos) 2972 { 2973 int rv = SOC_E_NONE; 2974 defip_alpm_ipv4_1_entry_t alpmv4_entry, alpmv4_sip_entry; 2975 defip_alpm_ipv6_64_1_entry_t alpmv6_entry, alpmv6_sip_entry; 2976 void *bufp, *sip_bufp; 2977 int sub_bkt_to; 2978 int entsz, key_index; 2979 uint32 bank_disable = 0; 2980 int v6, i; 2981 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 2982 2983 sub_bkt_to = ALPM_SUB_BKT(u, log_bkt_to); 2984 2985 bank_disable = 2986 ALPM_CTRL(u).bank_disable_bmp[vrf != (SOC_VRF_MAX(u) + 1)]; 2987 2988 v6 = (L3_DEFIP_ALPM_IPV6_64m == mem || 2989 L3_DEFIP_ALPM_IPV6_64_1m == mem || 2990 L3_DEFIP_ALPM_IPV6_128m == mem); 2991 2992 SOC_ALPM_ENTRY_BUF(v6, mem, bufp, alpmv4_entry, alpmv6_entry); 2993 SOC_ALPM_ENTRY_BUF(v6, mem, sip_bufp, alpmv4_sip_entry, alpmv6_sip_entry); 2994 entsz = v6 ? sizeof(defip_alpm_ipv6_64_1_entry_t) : 2995 sizeof(defip_alpm_ipv4_1_entry_t); 2996 2997 for (i = 0; i < pfx_array->count; i++) { 2998 if (pfx_array->prefix[i]->index > 0) { /* old prefix */ 2999 sal_memcpy(bufp, (uint8 *)old_bufp + i * entsz, entsz); 3000 soc_mem_field32_set(u, mem, bufp, SUB_BKT_PTRf, sub_bkt_to); 3001 /* entry shouldn't exist, insert the entry into the RAM */ 3002 3003 if (SOC_URPF_STATUS_GET(u)) { 3004 sal_memcpy(sip_bufp, (uint8 *)old_sip_bufp + i * entsz, entsz); 3005 } 3006 3007 rv = _soc_th_alpm_insert_in_bkt(u, mem, log_bkt_to, 3008 bank_disable, bufp, sip_bufp, e, 3009 &key_index, v6); 3010 3011 3012 } else { /* for split case only */ 3013 if (!new_bufp || !new_index_pos) { 3014 rv = SOC_E_PARAM; 3015 goto _rollback; 3016 } 3017 *new_index_pos = i; 3018 soc_mem_field32_set(u, mem, new_bufp, SUB_BKT_PTRf, sub_bkt_to); 3019 rv = _soc_th_alpm_insert_in_bkt(u, mem, log_bkt_to, 3020 bank_disable, new_bufp, new_sip_bufp, e, 3021 &key_index, v6); 3022 } 3023 if (SOC_FAILURE(rv)) { 3024 LOG_ERROR(BSL_LS_SOC_ALPM, 3025 (BSL_META_U(u, 3026 "Failed to insert prefix " 3027 "0x%08x 0x%08x 0x%08x 0x%08x to bucket %d\n"), 3028 pfx_array->prefix[i]->key[1], 3029 pfx_array->prefix[i]->key[2], 3030 pfx_array->prefix[i]->key[3], 3031 pfx_array->prefix[i]->key[4], log_bkt_to)); 3032 3033 goto _rollback; 3034 } 3035 new_index[i] = key_index; 3036 } 3037 3038 _rollback: 3039 if (SOC_FAILURE(rv)) { 3040 /* Delete entries in new bucket */ 3041 _soc_th_alpm_bucket_copy_undo(u, mem, pfx_array->count, new_index); 3042 } 3043 3044 return rv; 3045 } 3046 3047 3048 /* Merge entries from one logical bucket to another */ 3049 static int 3050 _soc_th_alpm_bucket_merge(int u, soc_mem_t mem, int log_bkt_from, 3051 int log_bkt_to, soc_alpm_merge_type_t merge_dir, 3052 int *shuffled) 3053 { 3054 int *new_index = NULL; 3055 int rv = SOC_E_NONE; 3056 int pivot_idx_from, pivot_idx_to; 3057 int v6, i; 3058 int vrf = 0; 3059 int phy_bkt_from, sub_bkt_from, phy_bkt_to, sub_bkt_to; 3060 void *bufp = NULL, *sip_bufp = NULL; 3061 alpm_mem_prefix_array_t *pfx_array = NULL; 3062 defip_entry_t lpm_entry; 3063 alpm_pivot_t *from_pivot; 3064 alpm_pivot_t *parent_pivot = NULL, *child_pivot = NULL; 3065 enum { 3066 _MERGE_NONE, 3067 _MERGE_PREPARE, 3068 _MERGE_COPY, 3069 _MERGE_LPM_LINK, 3070 _MERGE_INVALIDATE, 3071 _MERGE_CHILD_TRIE_MERGED, 3072 _MERGE_CHILD_LPM_DELETED, 3073 _MERGE_CHILD_PIVOT_DESTROYED 3074 } doing = _MERGE_NONE, done = _MERGE_NONE; 3075 3076 phy_bkt_from = ALPM_PHY_BKT(u, log_bkt_from); 3077 sub_bkt_from = ALPM_SUB_BKT(u, log_bkt_from); 3078 phy_bkt_to = ALPM_PHY_BKT(u, log_bkt_to); 3079 sub_bkt_to = ALPM_SUB_BKT(u, log_bkt_to); 3080 3081 v6 = (L3_DEFIP_ALPM_IPV6_64m == mem || 3082 L3_DEFIP_ALPM_IPV6_64_1m == mem || 3083 L3_DEFIP_ALPM_IPV6_128m == mem); 3084 3085 pivot_idx_from = SOC_ALPM_BU_PIVOT_IDX(u, phy_bkt_from, sub_bkt_from); 3086 pivot_idx_to = SOC_ALPM_BU_PIVOT_IDX(u, phy_bkt_to, sub_bkt_to); 3087 3088 from_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_from); 3089 3090 vrf = PIVOT_BUCKET_VRF(from_pivot); 3091 3092 /** 3093 * Invalidate need to happen only after all the entries are 3094 * written to the new pivot and the new pivot is valid. Otherwise 3095 * there is a chance of MISS. 3096 * 3097 * hitless move: 3098 * - Copy entries to new bucket. 3099 * - activate new pivot 3100 * - delete entries from old bucket 3101 */ 3102 3103 doing = _MERGE_PREPARE; 3104 rv = _soc_th_alpm_bucket_prepare(u, mem, PIVOT_BUCKET_TRIE(from_pivot), 3105 &pfx_array, &bufp, &sip_bufp, &new_index); 3106 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3107 3108 doing = _MERGE_COPY; 3109 rv = _soc_th_alpm_bucket_copy(u, mem, vrf, pfx_array, 3110 log_bkt_to, bufp, sip_bufp, 3111 NULL, NULL, new_index, NULL); 3112 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3113 3114 /* Connect TCAM entry to new bucket. 3115 * This is a must step even for merge child to parent 3116 */ 3117 doing = _MERGE_LPM_LINK; 3118 rv = _soc_th_alpm_bucket_link(u, v6, pivot_idx_from, log_bkt_to); 3119 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3120 3121 /* Invalide old entries */ 3122 doing = _MERGE_INVALIDATE; 3123 rv = _soc_th_alpm_bucket_inval(u, mem, pfx_array, bufp, sip_bufp); 3124 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3125 3126 if (merge_dir != MERGE_PHY) { 3127 uint32 hw_key[5] = {0}; 3128 int child_vrf; 3129 3130 if (merge_dir == MERGE_LOG_PARENT_TO_CHILD) { 3131 parent_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_from); 3132 child_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_to); 3133 } else if (merge_dir == MERGE_LOG_CHILD_TO_PARENT) { 3134 child_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_from); 3135 parent_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_to); 3136 } 3137 3138 /* SW bucket merge: not expect to fail */ 3139 doing = _MERGE_CHILD_TRIE_MERGED; 3140 rv = trie_merge(PIVOT_BUCKET_TRIE(parent_pivot), 3141 PIVOT_BUCKET_TRIE(child_pivot)->trie, 3142 child_pivot->key, 3143 child_pivot->len); 3144 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3145 3146 sal_memcpy(hw_key, child_pivot->key, sizeof(hw_key)); 3147 ALPM_TRIE_TO_NORMAL_IP(hw_key, child_pivot->len, v6); 3148 3149 child_vrf = PIVOT_BUCKET_VRF(child_pivot); 3150 3151 (void) _soc_th_alpm_lpm_ent_key_init(u, hw_key, child_pivot->len, 3152 child_vrf, v6, &lpm_entry, 1); 3153 3154 /* Delete child lpm entry from TCAM */ 3155 doing = _MERGE_CHILD_LPM_DELETED; 3156 rv = soc_th_alpm_lpm_delete(u, &lpm_entry); 3157 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3158 if (shuffled) { 3159 *shuffled = 1; 3160 } 3161 3162 /* Destroy child pivot from trie */ 3163 doing = _MERGE_CHILD_PIVOT_DESTROYED; 3164 rv = _soc_th_alpm_split_pivot_create_undo 3165 (u, v6, child_vrf, child_pivot->key, child_pivot->len, NULL, 0); 3166 3167 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3168 } 3169 3170 /* Update hit bits */ 3171 rv = soc_th_alpm_hit_bits_update(u, pfx_array, new_index, v6, vrf); 3172 if (SOC_FAILURE(rv)) { 3173 LOG_ERROR(BSL_LS_SOC_ALPM, 3174 (BSL_META_U(u, "update_hit_bits failed, count %d\n"), 3175 pfx_array->count)); 3176 rv = SOC_E_NONE; 3177 } 3178 3179 /* Update TCAM mgmt info: set new logical bucket */ 3180 if (merge_dir != MERGE_LOG_CHILD_TO_PARENT && ALPM_TCAM_PIVOT(u, pivot_idx_from)) { 3181 PIVOT_BUCKET_INDEX(ALPM_TCAM_PIVOT(u, pivot_idx_from)) = log_bkt_to; 3182 } 3183 3184 soc_th_alpm_bucket_usage_decr(u, log_bkt_from, TRUE, vrf, mem, pfx_array->count, log_bkt_to); 3185 soc_th_alpm_bucket_usage_incr(u, log_bkt_to, 3186 (merge_dir == MERGE_LOG_CHILD_TO_PARENT) ? 3187 pivot_idx_to : pivot_idx_from, 3188 vrf, mem, pfx_array->count); 3189 3190 /* Update new index */ 3191 for (i = 0; i < pfx_array->count; i++) { 3192 pfx_array->prefix[i]->index = new_index[i]; 3193 } 3194 3195 _soc_th_alpm_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index); 3196 return rv; 3197 3198 _rollback: 3199 3200 /* fall through on all cases */ 3201 switch (done) { 3202 case _MERGE_CHILD_LPM_DELETED: 3203 if (merge_dir != MERGE_PHY) { 3204 /* not expecting any failure after lpm deleted */ 3205 } 3206 3207 case _MERGE_CHILD_TRIE_MERGED: 3208 if (merge_dir != MERGE_PHY) { 3209 uint32 pivot[5], length; 3210 trie_split2(PIVOT_BUCKET_TRIE(parent_pivot), 3211 child_pivot->key, 3212 child_pivot->len, 3213 pivot, &length, 3214 &(PIVOT_BUCKET_TRIE(child_pivot)->trie), 3215 PIVOT_BUCKET_COUNT(child_pivot), 3216 1); 3217 } 3218 3219 case _MERGE_INVALIDATE: 3220 _soc_th_alpm_bucket_inval_undo(u, mem, pfx_array, bufp, sip_bufp); 3221 3222 case _MERGE_LPM_LINK: 3223 /* Connect TCAM back to original bucket */ 3224 _soc_th_alpm_bucket_link(u, v6, pivot_idx_from, log_bkt_from); 3225 3226 case _MERGE_COPY: 3227 /* Delete entries in new bucket */ 3228 _soc_th_alpm_bucket_copy_undo(u, mem, pfx_array->count, new_index); 3229 3230 case _MERGE_PREPARE: 3231 _soc_th_alpm_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index); 3232 3233 case _MERGE_NONE: 3234 default: 3235 break; 3236 } 3237 3238 /* Error dump */ 3239 switch (doing) { 3240 case _MERGE_LPM_LINK: 3241 LOG_ERROR(BSL_LS_SOC_ALPM, 3242 (BSL_META_U(u, 3243 "_soc_th_alpm_bucket_link failed, pivot %d log_bkt %d\n"), 3244 pivot_idx_from, log_bkt_to)); 3245 break; 3246 3247 case _MERGE_INVALIDATE: 3248 LOG_ERROR(BSL_LS_SOC_ALPM, 3249 (BSL_META_U(u, 3250 "_soc_th_alpm_bucket_inval failed\n"))); 3251 break; 3252 case _MERGE_CHILD_TRIE_MERGED: 3253 break; 3254 3255 case _MERGE_CHILD_PIVOT_DESTROYED: 3256 LOG_ERROR(BSL_LS_SOC_ALPM, 3257 (BSL_META_U(u, 3258 "Pivot destroy fail, something not expected\n"))); 3259 default: 3260 LOG_ERROR(BSL_LS_SOC_ALPM, 3261 (BSL_META_U(u, 3262 "Merge fails at step %d\n"), doing)); 3263 break; 3264 } 3265 3266 return rv; 3267 } 3268 3269 /* Merge physical bucket 1 to bucket 2 */ 3270 STATIC int 3271 _soc_th_alpm_bucket_share(int u, soc_mem_t mem, int phy_bkt_from, int phy_bkt_to) 3272 { 3273 /* if we go to here, the following condition MUST be met: 3274 * 1) Total subbucket num of two buckets <= 4. 3275 * 2) Total entry num of two buckets <= max entry of this bucket view 3276 * 3) Same bucket view for these two buckets. 3277 * 3278 * We don't check condition here. Caller does. 3279 */ 3280 3281 /* Use add-move-invalidate to avoid traffic interrupt */ 3282 int rv = SOC_E_NONE; 3283 int sub_bkt_from, sub_bkt_to; 3284 3285 /* 1) Get used sub bucket from bucket1 */ 3286 for (sub_bkt_from = 0; sub_bkt_from < SOC_TH_MAX_SUB_BUCKETS; sub_bkt_from++) { 3287 /* Skip non-exist sub buckets */ 3288 if (!(SOC_ALPM_BU_SUB_BKT_IS_SET(u, phy_bkt_from, sub_bkt_from))) { 3289 continue; 3290 } 3291 for (sub_bkt_to = 0; sub_bkt_to < SOC_TH_MAX_SUB_BUCKETS; sub_bkt_to++) { 3292 if (SOC_ALPM_BU_SUB_BKT_IS_SET(u, phy_bkt_to, sub_bkt_to)) { 3293 continue; 3294 } 3295 3296 if (mem == L3_DEFIP_ALPM_IPV6_128m) { 3297 rv = _soc_th_alpm_128_bucket_merge(u, mem, ALPM_LOG_BKT(phy_bkt_from, sub_bkt_from), 3298 ALPM_LOG_BKT(phy_bkt_to, sub_bkt_to), MERGE_PHY, 3299 NULL); 3300 } else { 3301 rv = _soc_th_alpm_bucket_merge(u, mem, 3302 ALPM_LOG_BKT(phy_bkt_from, sub_bkt_from), 3303 ALPM_LOG_BKT(phy_bkt_to, sub_bkt_to), 3304 MERGE_PHY, NULL); 3305 } 3306 SOC_IF_ERROR_RETURN(rv); 3307 break; 3308 } 3309 } 3310 3311 _alpm_dbg_cntr[u].bkt_share++; 3312 3313 return SOC_E_NONE; 3314 } 3315 3316 STATIC int 3317 _soc_th_alpm_can_buckets_share(int u, int phy_bkt1, int phy_bkt2) 3318 { 3319 if (phy_bkt1 != phy_bkt2 && 3320 SOC_ALPM_BU_COUNT(u, phy_bkt1) && SOC_ALPM_BU_COUNT(u, phy_bkt2) && 3321 /* both Private or both Global*/ 3322 (SOC_ALPM_BU_GLOBAL(u, phy_bkt1) == SOC_ALPM_BU_GLOBAL(u, phy_bkt2)) && 3323 (_shr_popcount((uint32)SOC_ALPM_BU_SUB_BKTS(u, phy_bkt1)) + 3324 _shr_popcount((uint32)SOC_ALPM_BU_SUB_BKTS(u, phy_bkt2)) <= 3325 SOC_TH_MAX_SUB_BUCKETS)) { 3326 return 1; 3327 } 3328 return 0; 3329 } 3330 3331 /* Find two qualified physical buckets and merge them into one, 3332 * such that one of them become free. 3333 */ 3334 static int 3335 _soc_th_alpm_share(int u, soc_mem_t mem, int *log_bkt) 3336 { 3337 int cnt, cnt2, bkt_cnt; 3338 int phy_bkt, phy_bkt1, phy_bkt2, view; 3339 SHR_BITDCL *bkt_bmp, *bkt_bmp2; 3340 /* be consistent with SOC_ALPM_MEM_VIEW */ 3341 soc_mem_t alpm_mem[] = {L3_DEFIP_ALPM_IPV4m, 3342 L3_DEFIP_ALPM_IPV6_64m, 3343 L3_DEFIP_ALPM_IPV6_128m, 3344 L3_DEFIP_ALPM_IPV4_1m, 3345 L3_DEFIP_ALPM_IPV6_64_1m}; 3346 3347 for (view = 0; view < SOC_TH_MAX_ALPM_VIEWS; view++) { 3348 if (ALPM_CTRL(u)._alpm_128b_bkt_rsvd && 3349 ((!!SOC_ALPM_MEM_V6(mem)) != (!!SOC_ALPM_MEM_V6(alpm_mem[view])))) { 3350 continue; 3351 } 3352 bkt_cnt = _soc_th_alpm_bkt_entry_cnt(u, alpm_mem[view]); 3353 3354 /* Assure total count of two buckets won't exceed max */ 3355 for (cnt = 1; cnt <= (bkt_cnt / 2); cnt++) { 3356 phy_bkt1 = phy_bkt2 = 0; 3357 3358 /* Skip empty entry */ 3359 if (SOC_ALPM_GBU_BKT_COUNT(u, view, cnt) <= 0) { 3360 continue; 3361 } 3362 bkt_bmp = SOC_ALPM_GBU_BKT_BMP(u, view, cnt); 3363 3364 for (phy_bkt = 1; phy_bkt < ALPM_CTRL(u).num_bkts; phy_bkt++) { 3365 if (SHR_BITGET(bkt_bmp, phy_bkt) && 3366 SOC_ALPM_BU_SUB_BKTS(u, phy_bkt) != 0xF) { 3367 3368 if (phy_bkt1 == 0) { 3369 phy_bkt1 = phy_bkt; 3370 } else if (_soc_th_alpm_can_buckets_share(u, phy_bkt1, phy_bkt)) { 3371 phy_bkt2 = phy_bkt; 3372 break; 3373 } 3374 } 3375 } 3376 3377 if (phy_bkt1 == 0) { 3378 continue; 3379 } 3380 3381 /* First physical bucket is found, now find second one */ 3382 for (cnt2 = cnt + 1; 3383 cnt2 <= (bkt_cnt - cnt) && phy_bkt2 == 0; 3384 cnt2++) { 3385 3386 /* Skip empty entry */ 3387 if (SOC_ALPM_GBU_BKT_COUNT(u, view, cnt2) <= 0) { 3388 continue; 3389 } 3390 bkt_bmp2 = SOC_ALPM_GBU_BKT_BMP(u, view, cnt2); 3391 3392 for (phy_bkt = 1; phy_bkt < ALPM_CTRL(u).num_bkts; phy_bkt++) { 3393 if (SHR_BITGET(bkt_bmp2, phy_bkt) && 3394 SOC_ALPM_BU_SUB_BKTS(u, phy_bkt) != 0xF) { 3395 3396 if (_soc_th_alpm_can_buckets_share(u, phy_bkt1, phy_bkt)) { 3397 phy_bkt2 = phy_bkt; 3398 break; 3399 } 3400 } 3401 } 3402 } 3403 3404 if (phy_bkt2) { 3405 /* Move all entries in phy_bkt1 to phy_bkt2, 3406 * and return phy_bkt1 as an empty bucket. 3407 */ 3408 SOC_IF_ERROR_RETURN( 3409 _soc_th_alpm_bucket_share(u, alpm_mem[view], phy_bkt1, phy_bkt2)); 3410 *log_bkt = ALPM_LOG_BKT(phy_bkt1, 0); 3411 return SOC_E_NONE; 3412 } 3413 } /* for cnt */ 3414 } 3415 3416 return SOC_E_FULL; 3417 } 3418 3419 3420 STATIC int 3421 _soc_th_alpm_lpm_free_entries(int u, soc_mem_t mem, int vrf) 3422 { 3423 int curr_pfx, min_pfx; 3424 int total_fent = 0; 3425 3426 if (mem == L3_DEFIP_ALPM_IPV6_128m) { 3427 return _soc_th_alpm_128_lpm_free_entries(u, vrf); 3428 } 3429 3430 curr_pfx = ALPM_MAX_PFX_INDEX; 3431 min_pfx = 0; 3432 if (ALPM_CTRL(u).gp_zoned) { 3433 if (vrf == (SOC_VRF_MAX(u) + 1)) { /* Global VRF */ 3434 min_pfx = ALPM_MAX_VRF_PFX_INDEX + 1; 3435 } else { 3436 curr_pfx = ALPM_MAX_VRF_PFX_INDEX; 3437 } 3438 } 3439 while (curr_pfx >= min_pfx) { 3440 total_fent += SOC_ALPM_LPM_STATE_FENT(u, curr_pfx); 3441 curr_pfx = SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx); 3442 } 3443 3444 return total_fent; 3445 } 3446 3447 3448 /* Move partial entries from one logical bucket to another */ 3449 static int 3450 _soc_th_alpm_bucket_repartition(int u, soc_mem_t mem, int log_bkt_from, 3451 int log_bkt_to, int max_count, 3452 trie_node_t **new_trie, 3453 int *shuffled) 3454 { 3455 trie_node_t *split_trie_root = NULL; 3456 uint32 length, bpm_len = 0; 3457 uint32 pivot[5]; 3458 uint32 bpm[5] = {0}; 3459 defip_entry_t lpm_entry; 3460 alpm_mem_prefix_array_t *pfx_array = NULL; 3461 int *new_index = NULL; 3462 int rv = SOC_E_NONE, i; 3463 int tcam_index, pivot_index; 3464 int pivot_idx_from, pivot_idx_to; 3465 int vrf = 0; 3466 void *bufp = NULL, *sip_bufp = NULL; 3467 uint32 src_discard, src_default; 3468 int phy_bkt_from, sub_bkt_from, phy_bkt_to, sub_bkt_to; 3469 int max_split_count; 3470 alpm_pivot_t *new_pivot, *parent_pivot, *child_pivot; 3471 int v6 = (L3_DEFIP_ALPM_IPV6_64m == mem || 3472 L3_DEFIP_ALPM_IPV6_64_1m == mem || 3473 L3_DEFIP_ALPM_IPV6_128m == mem); 3474 enum { 3475 _REPART_TRIE_NONE, 3476 _REPART_TRIE_SPLIT, 3477 _REPART_LPM_INIT, 3478 _REPART_PIVOT_CREATE, 3479 _REPART_PREPARE, 3480 _REPART_COPY, 3481 _REPART_LPM_INSERT, 3482 _REPART_INVALIDATE, 3483 _REPART_CHILD_TRIE_MERGED, 3484 _REPART_CHILD_LPM_DELETED, 3485 _REPART_CHILD_PIVOT_DESTROYED 3486 } doing = _REPART_TRIE_NONE, done = _REPART_TRIE_NONE; 3487 3488 phy_bkt_from = ALPM_PHY_BKT(u, log_bkt_from); 3489 sub_bkt_from = ALPM_SUB_BKT(u, log_bkt_from); 3490 phy_bkt_to = ALPM_PHY_BKT(u, log_bkt_to); 3491 sub_bkt_to = ALPM_SUB_BKT(u, log_bkt_to); 3492 3493 pivot_idx_from = SOC_ALPM_BU_PIVOT_IDX(u, phy_bkt_from, sub_bkt_from); 3494 pivot_idx_to = SOC_ALPM_BU_PIVOT_IDX(u, phy_bkt_to, sub_bkt_to); 3495 3496 parent_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_from); 3497 child_pivot = ALPM_TCAM_PIVOT(u, pivot_idx_to); 3498 3499 max_split_count = max_count - SOC_ALPM_BU_COUNT(u, phy_bkt_to); 3500 assert(max_split_count >= 0); 3501 if (max_split_count == 0) { 3502 return SOC_E_NONE; 3503 } 3504 3505 doing = _REPART_TRIE_SPLIT; 3506 rv = trie_split2(PIVOT_BUCKET_TRIE(parent_pivot), 3507 child_pivot->key, 3508 child_pivot->len, 3509 pivot, &length, 3510 &split_trie_root, 3511 max_split_count, 0); 3512 if (SOC_FAILURE(rv)) { 3513 /* Non repartable is nothing fatal, just return and keep searching */ 3514 if (rv == SOC_E_NOT_FOUND) { 3515 rv = SOC_E_NONE; 3516 } 3517 /* Must return */ 3518 return rv; 3519 } 3520 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3521 3522 vrf = PIVOT_BUCKET_VRF(ALPM_TCAM_PIVOT(u, pivot_idx_from)); 3523 doing = _REPART_LPM_INIT; 3524 rv = _soc_th_alpm_split_lpm_init(u, mem, pivot_idx_from, 3525 vrf, log_bkt_to, NULL, NULL, 3526 pivot, length, &lpm_entry, &bpm_len, bpm, 3527 &src_discard, &src_default); 3528 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3529 3530 3531 doing = _REPART_PIVOT_CREATE; 3532 rv = _soc_th_alpm_split_pivot_create(u, v6, vrf, log_bkt_to, 3533 split_trie_root, pivot, length, 3534 bpm_len, bpm, &new_pivot); 3535 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3536 3537 doing = _REPART_PREPARE; 3538 rv = _soc_th_alpm_bucket_prepare(u, mem, PIVOT_BUCKET_TRIE(new_pivot), 3539 &pfx_array, &bufp, &sip_bufp, &new_index); 3540 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3541 3542 doing = _REPART_COPY; 3543 rv = _soc_th_alpm_bucket_copy(u, mem, vrf, pfx_array, 3544 log_bkt_to, bufp, sip_bufp, 3545 NULL, NULL, new_index, NULL); 3546 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3547 3548 doing = _REPART_LPM_INSERT; 3549 rv = soc_th_alpm_lpm_insert(u, &lpm_entry, &tcam_index, bpm_len, 3550 src_default, src_discard); 3551 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3552 if (shuffled) { 3553 *shuffled = 1; 3554 } 3555 3556 /* TCAM index from lpm code is logical. Convert to physical idx */ 3557 tcam_index = soc_th_alpm_physical_idx(u, L3_DEFIPm, tcam_index, v6); 3558 pivot_index = tcam_index << (v6 ? 1 : 0); 3559 PIVOT_TCAM_INDEX(new_pivot) = pivot_index; 3560 ALPM_TCAM_PIVOT(u, pivot_index) = new_pivot; 3561 3562 /* Invalide old entries */ 3563 doing = _REPART_INVALIDATE; 3564 rv = _soc_th_alpm_bucket_inval(u, mem, pfx_array, bufp, sip_bufp); 3565 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3566 3567 /* Delete old lpm entry */ 3568 { 3569 uint32 hw_key[5] = {0}; 3570 int child_vrf; 3571 3572 /* SW bucket merge: not expect to fail */ 3573 doing = _REPART_CHILD_TRIE_MERGED; 3574 rv = trie_merge(PIVOT_BUCKET_TRIE(new_pivot), 3575 PIVOT_BUCKET_TRIE(child_pivot)->trie, 3576 child_pivot->key, 3577 child_pivot->len); 3578 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3579 3580 sal_memcpy(hw_key, child_pivot->key, sizeof(hw_key)); 3581 ALPM_TRIE_TO_NORMAL_IP(hw_key, child_pivot->len, v6); 3582 3583 child_vrf = PIVOT_BUCKET_VRF(child_pivot); 3584 3585 (void) _soc_th_alpm_lpm_ent_key_init(u, hw_key, child_pivot->len, 3586 child_vrf, v6, &lpm_entry, 1); 3587 3588 doing = _REPART_CHILD_LPM_DELETED; 3589 rv = soc_th_alpm_lpm_delete(u, &lpm_entry); 3590 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3591 3592 pivot_index = PIVOT_TCAM_INDEX(new_pivot); 3593 3594 /* Destroy child pivot */ 3595 doing = _REPART_CHILD_PIVOT_DESTROYED; 3596 rv = _soc_th_alpm_split_pivot_create_undo 3597 (u, v6, child_vrf, child_pivot->key, child_pivot->len, NULL, 0); 3598 3599 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 3600 } 3601 3602 /* Update hit bits */ 3603 rv = soc_th_alpm_hit_bits_update(u, pfx_array, new_index, v6, vrf); 3604 if (SOC_FAILURE(rv)) { 3605 LOG_ERROR(BSL_LS_SOC_ALPM, 3606 (BSL_META_U(u, "update_hit_bits failed, count %d\n"), 3607 pfx_array->count)); 3608 rv = SOC_E_NONE; 3609 } 3610 soc_th_alpm_bucket_usage_decr(u, log_bkt_from, FALSE, vrf, mem, pfx_array->count, log_bkt_to); 3611 soc_th_alpm_bucket_usage_incr(u, log_bkt_to, pivot_index, vrf, mem, pfx_array->count); 3612 3613 /* Update new index */ 3614 for (i = 0; i < pfx_array->count; i++) { 3615 pfx_array->prefix[i]->index = new_index[i]; 3616 } 3617 3618 _soc_th_alpm_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index); 3619 *new_trie = (trie_node_t *) new_pivot; 3620 3621 return rv; 3622 3623 _rollback: 3624 3625 /* fall through on all cases */ 3626 switch (done) { 3627 case _REPART_CHILD_LPM_DELETED: 3628 /* Not expect any failure after trie_merge */ 3629 3630 case _REPART_CHILD_TRIE_MERGED: { 3631 uint32 pivot2[5], length2; 3632 trie_split2(PIVOT_BUCKET_TRIE(parent_pivot), 3633 child_pivot->key, 3634 child_pivot->len, 3635 pivot2, &length2, 3636 &(PIVOT_BUCKET_TRIE(child_pivot)->trie), 3637 PIVOT_BUCKET_COUNT(child_pivot), 1); 3638 } 3639 3640 case _REPART_INVALIDATE: 3641 _soc_th_alpm_bucket_inval_undo(u, mem, pfx_array, bufp, sip_bufp); 3642 3643 case _REPART_LPM_INSERT: 3644 soc_th_alpm_lpm_delete(u, &lpm_entry); 3645 3646 case _REPART_COPY: 3647 /* Delete entries in new bucket */ 3648 _soc_th_alpm_bucket_copy_undo(u, mem, pfx_array->count, new_index); 3649 3650 case _REPART_PREPARE: 3651 _soc_th_alpm_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index); 3652 3653 case _REPART_PIVOT_CREATE: 3654 _soc_th_alpm_split_pivot_create_undo(u, v6, vrf, pivot, length, NULL, 0); 3655 3656 case _REPART_LPM_INIT: 3657 /* nothing to undo */ 3658 3659 case _REPART_TRIE_SPLIT: 3660 trie_merge(PIVOT_BUCKET_TRIE(parent_pivot), split_trie_root, pivot, length); 3661 default: 3662 break; 3663 } 3664 3665 LOG_ERROR(BSL_LS_SOC_ALPM, 3666 (BSL_META_U(u, 3667 "Repartition fails at step %d\n"), doing)); 3668 3669 return rv; 3670 } 3671 3672 3673 3674 static int 3675 _soc_th_alpm_max_free_log_bkt(int u, soc_mem_t mem, int bkt_cnt, int vrf, 3676 int *log_bkt, int *free_count) 3677 { 3678 int cnt, sub_bkt; 3679 int phy_bkt, view; 3680 SHR_BITDCL *bkt_bmp; 3681 3682 /* 3683 * Try to alloc a sub bucket from least occupied bucket of 3684 * same memory view. 3685 */ 3686 view = SOC_ALPM_MEM_VIEW(mem); 3687 for (cnt = 1; cnt < bkt_cnt - 1; cnt++) { /* at least two free entry */ 3688 if (SOC_ALPM_GBU_BKT_COUNT(u, view, cnt) <= 0) { 3689 continue; 3690 } 3691 3692 bkt_bmp = SOC_ALPM_GBU_BKT_BMP(u, view, cnt); 3693 3694 for (phy_bkt = 1; phy_bkt < ALPM_CTRL(u).num_bkts; phy_bkt++) { 3695 if (SHR_BITGET(bkt_bmp, phy_bkt) && 3696 SOC_ALPM_BU_GLOBAL(u, phy_bkt) == 3697 (vrf == (SOC_VRF_MAX(u) + 1))) { 3698 if (SOC_ALPM_BU_SUB_BKTS(u, phy_bkt) != 0xF) { 3699 break; 3700 } 3701 } 3702 } 3703 3704 if (phy_bkt < ALPM_CTRL(u).num_bkts) { 3705 for (sub_bkt = 0; sub_bkt < SOC_TH_MAX_SUB_BUCKETS; sub_bkt++) { 3706 if (!SOC_ALPM_BU_SUB_BKT_IS_SET(u, phy_bkt, sub_bkt)) { 3707 *log_bkt = ALPM_LOG_BKT(phy_bkt, sub_bkt); 3708 *free_count = bkt_cnt - cnt; 3709 return SOC_E_NONE; 3710 } 3711 } 3712 } 3713 } 3714 return SOC_E_FULL; 3715 } 3716 3717 3718 static int 3719 _soc_th_alpm_repartition_cb(trie_node_t *ptrie, trie_node_t *trie, 3720 trie_traverse_states_e_t *state, void *info, 3721 trie_node_t **new_trie) 3722 { 3723 int rv; 3724 int parent_phy_bkt, child_phy_bkt; 3725 int max_count; 3726 int parent_free_count, child_free_count, free_count = 0; 3727 int log_bkt_from, log_bkt_to, log_bkt_parent, log_bkt_child; 3728 int do_repartition = 0; /* 0: merge. 1: repartition */ 3729 int child_count = 0, parent_count = 0; 3730 soc_alpm_merge_info_t *repart = (soc_alpm_merge_info_t *)info; 3731 alpm_pivot_t *parent_pivot = (alpm_pivot_t *)ptrie; 3732 alpm_pivot_t *child_pivot = (alpm_pivot_t *)trie; 3733 soc_alpm_merge_type_t merge_dir = MERGE_PHY; 3734 int shuffled = 0; 3735 3736 #ifdef ALPM_REPART_DEBUG 3737 { 3738 trie_t *pivot_trie; 3739 trie_node_t *lpm = NULL; 3740 switch (repart->v6) { 3741 case L3_DEFIP_MODE_V4: 3742 pivot_trie = VRF_PIVOT_TRIE_IPV4(repart->u, repart->vrf); 3743 break; 3744 case L3_DEFIP_MODE_64: 3745 pivot_trie = VRF_PIVOT_TRIE_IPV6(repart->u, repart->vrf); 3746 break; 3747 default: 3748 pivot_trie = VRF_PIVOT_TRIE_IPV6_128(repart->u, repart->vrf); 3749 break; 3750 } 3751 trie_find_lpm2(pivot_trie, child_pivot->key, child_pivot->len, &lpm); 3752 ptrie = lpm; 3753 parent_pivot = (alpm_pivot_t *)ptrie; 3754 } 3755 #endif 3756 if (!parent_pivot) { /* no parent, this is a root */ 3757 return SOC_E_NONE; 3758 } 3759 3760 /* Reset state everytime */ 3761 *state = TRIE_TRAVERSE_STATE_NONE; 3762 3763 max_count = repart->max_count; 3764 3765 parent_phy_bkt = ALPM_PHY_BKT(repart->u, PIVOT_BUCKET_INDEX(parent_pivot)); 3766 child_phy_bkt = ALPM_PHY_BKT(repart->u, PIVOT_BUCKET_INDEX(child_pivot)); 3767 3768 if (PIVOT_BUCKET_TRIE(parent_pivot)->trie == NULL) { 3769 merge_dir = MERGE_LOG_PARENT_TO_CHILD; 3770 } 3771 3772 if (PIVOT_BUCKET_TRIE(child_pivot)->trie == NULL) { 3773 merge_dir = MERGE_LOG_CHILD_TO_PARENT; 3774 } 3775 3776 if (merge_dir == MERGE_PHY) { 3777 parent_count = PIVOT_BUCKET_COUNT(parent_pivot); 3778 child_count = PIVOT_BUCKET_COUNT(child_pivot); 3779 parent_free_count = max_count - SOC_ALPM_BU_COUNT(repart->u, parent_phy_bkt); 3780 child_free_count = max_count - SOC_ALPM_BU_COUNT(repart->u, child_phy_bkt); 3781 3782 if (child_count <= parent_free_count) { 3783 merge_dir = MERGE_LOG_CHILD_TO_PARENT; 3784 } else if (parent_count <= child_free_count) { 3785 merge_dir = MERGE_LOG_PARENT_TO_CHILD; 3786 } else { 3787 /* Merge is not qualified, try repartition */ 3788 merge_dir = MERGE_LOG_PARENT_TO_CHILD; 3789 do_repartition = 1; 3790 } 3791 } 3792 log_bkt_parent = PIVOT_BUCKET_INDEX(parent_pivot); 3793 log_bkt_child = PIVOT_BUCKET_INDEX(child_pivot); 3794 3795 if (merge_dir == MERGE_LOG_CHILD_TO_PARENT) { 3796 log_bkt_from = log_bkt_child; 3797 log_bkt_to = log_bkt_parent; 3798 } else { 3799 /* repartition always go here */ 3800 log_bkt_from = log_bkt_parent; 3801 log_bkt_to = log_bkt_child; 3802 } 3803 3804 if (do_repartition == 0) { /* Bucket merge */ 3805 if (repart->mem == L3_DEFIP_ALPM_IPV6_128m) { 3806 rv = _soc_th_alpm_128_bucket_merge(repart->u, repart->mem, 3807 log_bkt_from, log_bkt_to, merge_dir, 3808 &shuffled); 3809 } else { 3810 rv = _soc_th_alpm_bucket_merge(repart->u, repart->mem, 3811 log_bkt_from, log_bkt_to, merge_dir, 3812 &shuffled); 3813 } 3814 if (SOC_FAILURE(rv)) { 3815 LOG_ERROR(BSL_LS_SOC_ALPM, 3816 (BSL_META_U(repart->u, 3817 "Bucket merge fail %d\n"), rv)); 3818 return rv; 3819 } 3820 3821 if (merge_dir == MERGE_LOG_CHILD_TO_PARENT) { 3822 free_count = max_count - SOC_ALPM_BU_COUNT(repart->u, child_phy_bkt); 3823 } else { 3824 free_count = max_count - SOC_ALPM_BU_COUNT(repart->u, parent_phy_bkt); 3825 } 3826 3827 *state = TRIE_TRAVERSE_STATE_DELETED; 3828 repart->free_count = free_count; 3829 repart->log_bkt = log_bkt_from; 3830 if (++repart->merge_count >= REPART_THRESHOLD) { 3831 *state = TRIE_TRAVERSE_STATE_DONE; 3832 } 3833 _alpm_dbg_cntr[repart->u].bkt_merge2++; 3834 } else { /* Repartition */ 3835 /* Repartition is an intermediate stage, not a goal. 3836 * Also note, repartition may result in trie modified 3837 * (old node deleted, new node added). 3838 */ 3839 if (repart->mem == L3_DEFIP_ALPM_IPV6_128m) { 3840 rv = _soc_th_alpm_128_bucket_repartition(repart->u, repart->mem, 3841 log_bkt_from, log_bkt_to, max_count, 3842 new_trie, &shuffled); 3843 } else { 3844 rv = _soc_th_alpm_bucket_repartition(repart->u, repart->mem, 3845 log_bkt_from, log_bkt_to, max_count, 3846 new_trie, &shuffled); 3847 } 3848 if (SOC_FAILURE(rv)) { 3849 LOG_ERROR(BSL_LS_SOC_ALPM, 3850 (BSL_META_U(repart->u, 3851 "Bucket repartition fail %d\n"), rv)); 3852 return rv; 3853 } 3854 /* keep searching if not repartable */ 3855 if (shuffled) { 3856 _alpm_dbg_cntr[repart->u].bkt_repart++; 3857 } 3858 } 3859 3860 if (shuffled) { 3861 repart->shuffled = 1; 3862 } 3863 3864 return SOC_E_NONE; 3865 } 3866 3867 3868 static int 3869 _soc_th_alpm_repartition(int u, soc_mem_t mem, int vrf, int max_count, int *log_bkt, 3870 int *shuffled, int *free_count) 3871 { 3872 int rv = SOC_E_NONE; 3873 soc_alpm_merge_info_t info; 3874 trie_t *pivot_trie = NULL; 3875 3876 sal_memset(&info, 0, sizeof(info)); 3877 info.log_bkt = -1; /* Initialize to non-eligible log_bkt */ 3878 info.u = u; 3879 info.mem = mem; 3880 info.orig_vrf = vrf; 3881 info.v6 = SOC_ALPM_MEM_V6(mem); 3882 info.vrf = vrf; 3883 info.max_count = max_count; 3884 3885 pivot_trie = 3886 (info.v6 == L3_DEFIP_MODE_V4 ? VRF_PIVOT_TRIE_IPV4(u, info.vrf) : 3887 info.v6 == L3_DEFIP_MODE_64 ? VRF_PIVOT_TRIE_IPV6(u, info.vrf) : 3888 VRF_PIVOT_TRIE_IPV6_128(u, info.vrf)); 3889 if (pivot_trie == NULL || pivot_trie->trie == NULL) { 3890 return SOC_E_FULL; 3891 } 3892 /* Choose post-order traverse for repartition. 3893 * All orders are delete safe. 3894 * But only the post-order is modify safe. 3895 */ 3896 rv = trie_repartition(pivot_trie, _soc_th_alpm_repartition_cb, 3897 &info, _TRIE_POSTORDER_TRAVERSE); 3898 if (info.shuffled && shuffled) { 3899 *shuffled = 1; 3900 } 3901 if (SOC_FAILURE(rv)) { 3902 LOG_ERROR(BSL_LS_SOC_ALPM, 3903 (BSL_META_U(u, "Logic bucket repartition fails."\ 3904 "rv %d vrf %d v6 %d\n"), rv, info.vrf, info.v6)); 3905 return rv; 3906 } else if (info.log_bkt != -1) { 3907 /* This indicates at least one merge happened. 3908 * Note repartition don't set log_bkt. 3909 */ 3910 *log_bkt = info.log_bkt; 3911 return _soc_th_alpm_max_free_log_bkt(u, mem, max_count, vrf, 3912 log_bkt, free_count); 3913 } 3914 return SOC_E_FULL; 3915 } 3916 3917 3918 static int 3919 _soc_th_alpm_merge_cb(trie_node_t *ptrie, trie_node_t *trie, 3920 trie_traverse_states_e_t *state, void *info) 3921 { 3922 int rv; 3923 int parent_phy_bkt, child_phy_bkt; 3924 int max_count; 3925 int parent_free_count, child_free_count, free_count = 0; 3926 int log_bkt_from, log_bkt_to, log_bkt_parent, log_bkt_child; 3927 int child_count = 0, parent_count = 0; 3928 soc_alpm_merge_info_t *merge = (soc_alpm_merge_info_t *)info; 3929 alpm_pivot_t *parent_pivot = (alpm_pivot_t *)ptrie; 3930 alpm_pivot_t *child_pivot = (alpm_pivot_t *)trie; 3931 soc_alpm_merge_type_t merge_dir = MERGE_PHY; 3932 int shuffled = 0; 3933 3934 if (!parent_pivot) { 3935 return SOC_E_NONE; 3936 } 3937 3938 /* Reset state everytime */ 3939 *state = TRIE_TRAVERSE_STATE_NONE; 3940 max_count = merge->max_count; 3941 3942 parent_phy_bkt = ALPM_PHY_BKT(merge->u, PIVOT_BUCKET_INDEX(parent_pivot)); 3943 child_phy_bkt = ALPM_PHY_BKT(merge->u, PIVOT_BUCKET_INDEX(child_pivot)); 3944 3945 if (PIVOT_BUCKET_TRIE(parent_pivot)->trie == NULL) { 3946 merge_dir = MERGE_LOG_PARENT_TO_CHILD; 3947 } 3948 3949 if (PIVOT_BUCKET_TRIE(child_pivot)->trie == NULL) { 3950 merge_dir = MERGE_LOG_CHILD_TO_PARENT; 3951 } 3952 3953 if (merge_dir == MERGE_PHY) { 3954 parent_count = PIVOT_BUCKET_COUNT(parent_pivot); 3955 child_count = PIVOT_BUCKET_COUNT(child_pivot); 3956 parent_free_count = max_count - SOC_ALPM_BU_COUNT(merge->u, parent_phy_bkt); 3957 child_free_count = max_count - SOC_ALPM_BU_COUNT(merge->u, child_phy_bkt); 3958 3959 if (child_count <= parent_free_count) { 3960 merge_dir = MERGE_LOG_CHILD_TO_PARENT; 3961 } else if (parent_count <= child_free_count) { 3962 merge_dir = MERGE_LOG_PARENT_TO_CHILD; 3963 } else { 3964 return SOC_E_NONE; 3965 } 3966 } 3967 3968 log_bkt_parent = PIVOT_BUCKET_INDEX(parent_pivot); 3969 log_bkt_child = PIVOT_BUCKET_INDEX(child_pivot); 3970 3971 if (merge_dir == MERGE_LOG_CHILD_TO_PARENT) { 3972 log_bkt_from = log_bkt_child; 3973 log_bkt_to = log_bkt_parent; 3974 } else { 3975 log_bkt_from = log_bkt_parent; 3976 log_bkt_to = log_bkt_child; 3977 } 3978 3979 if (merge->mem == L3_DEFIP_ALPM_IPV6_128m) { 3980 rv = _soc_th_alpm_128_bucket_merge(merge->u, merge->mem, 3981 log_bkt_from, log_bkt_to, merge_dir, 3982 &shuffled); 3983 } else { 3984 rv = _soc_th_alpm_bucket_merge(merge->u, merge->mem, 3985 log_bkt_from, log_bkt_to, merge_dir, 3986 &shuffled); 3987 } 3988 3989 if (SOC_FAILURE(rv)) { /* traverse stops on callback failure */ 3990 LOG_ERROR(BSL_LS_SOC_ALPM, 3991 (BSL_META_U(merge->u, "Merge fails %d (not expecting this )\n"), rv)); 3992 return rv; 3993 } 3994 3995 /* This indicates the trie node is freed */ 3996 *state = TRIE_TRAVERSE_STATE_DELETED; 3997 3998 if (merge_dir == MERGE_LOG_CHILD_TO_PARENT) { 3999 free_count = max_count - SOC_ALPM_BU_COUNT(merge->u, child_phy_bkt); 4000 } else { 4001 free_count = max_count - SOC_ALPM_BU_COUNT(merge->u, parent_phy_bkt); 4002 } 4003 4004 merge->free_count = free_count; 4005 merge->log_bkt = log_bkt_from; 4006 4007 if (++merge->merge_count >= MERGE_THRESHOLD) { 4008 *state = TRIE_TRAVERSE_STATE_DONE; 4009 } 4010 4011 if (shuffled) { 4012 merge->shuffled = 1; 4013 } 4014 4015 _alpm_dbg_cntr[merge->u].bkt_merge++; 4016 return SOC_E_NONE; 4017 } 4018 4019 4020 static int 4021 _soc_th_alpm_merge(int u, soc_mem_t mem, int vrf, int max_count, int *log_bkt, 4022 int *shuffled, int *free_count) 4023 { 4024 int rv = SOC_E_NONE; 4025 soc_alpm_merge_info_t info; 4026 trie_t *pivot_trie = NULL; 4027 4028 sal_memset(&info, 0, sizeof(info)); 4029 info.log_bkt = -1; /* Initialize to non-eligible log_bkt */ 4030 info.u = u; 4031 info.mem = mem; 4032 info.orig_vrf = vrf; 4033 info.v6 = SOC_ALPM_MEM_V6(mem); 4034 info.vrf = vrf; 4035 info.max_count = max_count; 4036 4037 pivot_trie = 4038 (info.v6 == L3_DEFIP_MODE_V4 ? VRF_PIVOT_TRIE_IPV4(u, info.vrf) : 4039 info.v6 == L3_DEFIP_MODE_64 ? VRF_PIVOT_TRIE_IPV6(u, info.vrf) : 4040 VRF_PIVOT_TRIE_IPV6_128(u, info.vrf)); 4041 if (pivot_trie == NULL || pivot_trie->trie == NULL) { 4042 return SOC_E_FULL; 4043 } 4044 rv = trie_traverse2(pivot_trie, _soc_th_alpm_merge_cb, 4045 &info, _TRIE_POSTORDER_TRAVERSE); 4046 if (info.shuffled && shuffled) { 4047 *shuffled = 1; 4048 } 4049 if (SOC_FAILURE(rv)) { 4050 LOG_ERROR(BSL_LS_SOC_ALPM, 4051 (BSL_META_U(u, "Logic bucket merge fails."\ 4052 "rv %d vrf %d v6 %d\n"), rv, info.vrf, info.v6)); 4053 return rv; 4054 } else if (info.log_bkt != -1) { 4055 /* This indicates at least one merge happened. */ 4056 *log_bkt = info.log_bkt; 4057 return _soc_th_alpm_max_free_log_bkt(u, mem, max_count, vrf, 4058 log_bkt, free_count); 4059 } 4060 4061 return SOC_E_FULL; 4062 } 4063 4064 4065 static int 4066 _soc_th_alpm_assign(int u, soc_mem_t mem, int vrf, 4067 int *log_bkt, int *o_shuffled, int *o_free_count) 4068 { 4069 int rv = SOC_E_FULL; 4070 int free_lpm_count = 0; 4071 int free_count = 0; 4072 int shuffled = 0; 4073 int max_count = _soc_th_alpm_bkt_entry_cnt(u, mem); 4074 4075 4076 free_count = max_count; 4077 4078 switch (ALPM_CTRL(u).alpm_scaling) { 4079 case 1: 4080 rv = _soc_th_alpm_merge(u, mem, vrf, max_count, log_bkt, 4081 &shuffled, &free_count); 4082 4083 if (rv == SOC_E_FULL) { 4084 free_lpm_count = _soc_th_alpm_lpm_free_entries(u, mem, vrf); 4085 if (free_lpm_count >= 1 && free_lpm_count <= 5) { 4086 rv = _soc_th_alpm_repartition(u, mem, vrf, max_count, 4087 log_bkt, &shuffled, &free_count); 4088 } 4089 } 4090 4091 if (rv == SOC_E_FULL) { 4092 rv = _soc_th_alpm_share(u, mem, log_bkt); 4093 } 4094 4095 if (rv == SOC_E_FULL) { 4096 rv = _soc_th_alpm_max_free_log_bkt(u, mem, max_count, vrf, 4097 log_bkt, &free_count); 4098 } 4099 break; 4100 default: 4101 rv = _soc_th_alpm_share(u, mem, log_bkt); 4102 4103 if (rv == SOC_E_FULL) { 4104 rv = _soc_th_alpm_max_free_log_bkt(u, mem, max_count, vrf, 4105 log_bkt, &free_count); 4106 } 4107 break; 4108 } 4109 4110 if (o_free_count) { 4111 *o_free_count = free_count; 4112 } 4113 if (o_shuffled) { 4114 *o_shuffled = shuffled; 4115 } 4116 4117 return rv; 4118 4119 } 4120 4121 #ifdef CHECK_CLEAN_BKT 4122 STATIC int 4123 _soc_th_alpm_phy_bkt_trie_count(int u, int phy_bkt) 4124 { 4125 int pivot_idx, sub_bkt; 4126 alpm_pivot_t *pivot; 4127 trie_t *bkt_trie = NULL; 4128 alpm_mem_prefix_array_t prefix_array; 4129 int count = 0; 4130 4131 for (sub_bkt = 0; sub_bkt < SOC_TH_MAX_SUB_BUCKETS; sub_bkt++) { 4132 if (SOC_ALPM_BU_SUB_BKT_IS_SET(u, phy_bkt, sub_bkt)) { 4133 pivot_idx = SOC_ALPM_BU_PIVOT_IDX(u, phy_bkt, sub_bkt); 4134 pivot = ALPM_TCAM_PIVOT(u, (pivot_idx)); 4135 assert(ALPM_LOG_BKT(phy_bkt, sub_bkt) == PIVOT_BUCKET_INDEX(pivot)); 4136 bkt_trie = PIVOT_BUCKET_TRIE(pivot); 4137 4138 sal_memset(&prefix_array, 0, sizeof(prefix_array)); 4139 trie_traverse(bkt_trie, _soc_th_alpm_mem_prefix_array_cb, 4140 &prefix_array, _TRIE_INORDER_TRAVERSE); 4141 count += prefix_array.count; 4142 } 4143 } 4144 return count; 4145 } 4146 #endif 4147 4148 /* Update bucket usage bookeeping info */ 4149 void 4150 soc_th_alpm_bucket_usage_incr(int u, int log_bkt, int pivot_index, int vrf, soc_mem_t mem, int diff) 4151 { 4152 int phy_bkt, sub_bkt; 4153 int count, view; 4154 4155 phy_bkt = ALPM_PHY_BKT(u, log_bkt); 4156 sub_bkt = ALPM_SUB_BKT(u, log_bkt); 4157 view = SOC_ALPM_MEM_VIEW(mem); 4158 4159 count = SOC_ALPM_BU_COUNT(u, phy_bkt); 4160 if (count > 0) { 4161 SOC_ALPM_GBU_BKT_COUNT(u, view, count)--; 4162 SHR_BITCLR(SOC_ALPM_GBU_BKT_BMP(u, view, count), phy_bkt); 4163 } else { /* count == 0 */ 4164 SOC_ALPM_BU_GLOBAL(u, phy_bkt) = (vrf == (SOC_VRF_MAX(u) + 1)); 4165 } 4166 4167 SOC_ALPM_BU_COUNT(u, phy_bkt) += diff; 4168 SOC_ALPM_BU_SUB_BKT_SET(u, phy_bkt, sub_bkt); 4169 SOC_ALPM_BU_PIVOT_IDX(u, phy_bkt, sub_bkt) = pivot_index; 4170 4171 count = SOC_ALPM_BU_COUNT(u, phy_bkt); 4172 if (count > 0) { 4173 SOC_ALPM_GBU_BKT_COUNT(u, view, count)++; 4174 SHR_BITSET(SOC_ALPM_GBU_BKT_BMP(u, view, count), phy_bkt); 4175 } 4176 4177 #ifdef CHECK_CLEAN_BKT 4178 assert(count == _soc_th_alpm_phy_bkt_trie_count(u, phy_bkt)); 4179 #endif 4180 return; 4181 } 4182 4183 /* Update bucket usage bookeeping info */ 4184 void 4185 soc_th_alpm_bucket_usage_decr(int u, int log_bkt, int clear, int vrf, soc_mem_t mem, int diff, int log_bkt_to) 4186 { 4187 int phy_bkt; 4188 int count, view, v6; 4189 4190 phy_bkt = ALPM_PHY_BKT(u, log_bkt); 4191 view = SOC_ALPM_MEM_VIEW(mem); 4192 v6 = SOC_ALPM_MEM_V6(mem); 4193 4194 count = SOC_ALPM_BU_COUNT(u, phy_bkt); 4195 if (count > 0) { 4196 SOC_ALPM_GBU_BKT_COUNT(u, view, count)--; 4197 SHR_BITCLR(SOC_ALPM_GBU_BKT_BMP(u, view, count), phy_bkt); 4198 } 4199 4200 SOC_ALPM_BU_COUNT(u, phy_bkt) -= diff; 4201 if (clear) { 4202 soc_th_alpm_bucket_release(u, log_bkt, vrf, v6); 4203 } 4204 4205 count = SOC_ALPM_BU_COUNT(u, phy_bkt); 4206 if (count > 0) { 4207 SOC_ALPM_GBU_BKT_COUNT(u, view, count)++; 4208 SHR_BITSET(SOC_ALPM_GBU_BKT_BMP(u, view, count), phy_bkt); 4209 } 4210 4211 #ifdef CHECK_CLEAN_BKT 4212 if (phy_bkt != ALPM_PHY_BKT(u, log_bkt_to)) { 4213 /* Some cases, this has to wait for incr done. */ 4214 assert(count == _soc_th_alpm_phy_bkt_trie_count(u, phy_bkt)); 4215 } 4216 #endif 4217 return; 4218 } 4219 4220 /* Dump bucket sharing bookeeping info */ 4221 void 4222 soc_th_alpm_bucket_sw_dump(int u) 4223 { 4224 int i, view, ent, bkt, conflict = 0; 4225 int step_count = 1, used = 0; 4226 alpm_bkt_bmp_t *glb_bu = NULL; 4227 alpm_bkt_usg_t *bu = NULL; 4228 int *pivot; 4229 soc_mem_t lpm_mem; 4230 uint8 ipv; 4231 4232 /* be consistent with SOC_ALPM_MEM_VIEW */ 4233 char *view_str[] = {"IPv4", "IPv6-64", "IPv6-128", "IPv4 Flex", "IPv6-64 Flex"}; 4234 4235 pivot = sal_alloc(sizeof(int) * 16384, "pivot"); 4236 if (pivot == NULL) { 4237 return; 4238 } 4239 sal_memset(pivot, 0, sizeof(int) * 16384); 4240 4241 /* global_bkt_usage info */ 4242 for (view = 0; view < SOC_TH_MAX_ALPM_VIEWS; view++) { 4243 LOG_CLI((BSL_META_U(u, "\n[- %8s -]\n"), view_str[view])); 4244 LOG_CLI((BSL_META_U(u, 4245 "=================================================\n"))); 4246 LOG_CLI((BSL_META_U(u, " %5s | %5s %10s\n"), "entry", "count", "1st-bktbmp")); 4247 LOG_CLI((BSL_META_U(u, 4248 "=================================================\n"))); 4249 bkt = 0; 4250 for (ent = 0; ent < SOC_TH_MAX_BUCKET_ENTRIES(u); ent++) { 4251 glb_bu = &global_bkt_usage[u][view][ent]; 4252 if (glb_bu->bkt_count == 0) { 4253 continue; 4254 } 4255 4256 bkt ++; 4257 LOG_CLI((BSL_META_U(u, " %5d %5d"), ent, glb_bu->bkt_count)); 4258 for (i = 0; i < ALPM_CTRL(u).num_bkts; i++) { 4259 if (SHR_BITGET(glb_bu->bkt_bmp, i)) { 4260 LOG_CLI((BSL_META_U(u, " 0x%08x\n"), glb_bu->bkt_bmp[i / SHR_BITWID])); 4261 break; 4262 } 4263 } 4264 } 4265 4266 if (bkt == 0) { 4267 LOG_CLI((BSL_META_U(u, "- None - \n"))); 4268 } 4269 } 4270 4271 /* bkt_usage info */ 4272 ent = 0; 4273 LOG_CLI((BSL_META_U(u, "%5s | %s\n"), "bkt", "(sub-bkt-idx, tcam-idx)")); 4274 LOG_CLI((BSL_META_U(u, "=================================================\n"))); 4275 for (bkt = 0; bkt < ALPM_CTRL(u).num_bkts; bkt++) { 4276 bu = &bkt_usage[u][bkt]; 4277 if (bu->count == 0) { 4278 continue; 4279 } 4280 4281 ent ++; 4282 conflict = 0; 4283 LOG_CLI((BSL_META_U(u, "%5d | "), bkt)); 4284 for (i = 0; i < 4; i++) { 4285 if (bu->sub_bkts & (1 << i)) { 4286 LOG_CLI((BSL_META_U(u, "(%d, %5d) "), i, bu->pivots[i])); 4287 if (pivot[bu->pivots[i]] != 0) { 4288 conflict = i + 1; 4289 } else { 4290 pivot[bu->pivots[i]] = bkt; 4291 } 4292 } 4293 } 4294 LOG_CLI((BSL_META_U(u, "\n"))); 4295 if (conflict) { 4296 LOG_CLI((BSL_META_U(u, "Error: multi-buckets were linked to pivot %d, prev %d, curr %d\n"), 4297 bu->pivots[conflict - 1], pivot[bu->pivots[conflict - 1]], bkt)); 4298 } 4299 } 4300 4301 if (ent == 0) { 4302 LOG_CLI((BSL_META_U(u, "- None -"))); 4303 } 4304 4305 LOG_CLI((BSL_META_U(u, "\n"))); 4306 4307 LOG_CLI((BSL_META_U(u, 4308 "=================================================\n"))); 4309 LOG_CLI((BSL_META_U(u, 4310 " %s[%s]\n"), "VRF Route bucket idx", "mem_view")); 4311 LOG_CLI((BSL_META_U(u, 4312 "=================================================\n"))); 4313 4314 bkt = 0; 4315 for (ipv = ALPM_IPV4; ipv < ALPM_IPVERS; ipv++) { 4316 if (ipv == ALPM_IPV6 && 4317 SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4) == 4318 SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6)) { 4319 break; 4320 } 4321 for (i = 0; i < SOC_TH_ALPM_BUCKET_COUNT(u); i += step_count) { 4322 SHR_BITTEST_RANGE(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv), i, 4323 step_count, used); 4324 if (used) { 4325 lpm_mem = 4326 soc_alpm_cmn_bkt_view_get(u, 4327 SOC_TH_ALPM_AIDX(u, i, 0, 0, 0)); 4328 LOG_CLI(( 4329 BSL_META_U(u, " 0x%04x[%24s]\n"), 4330 i, lpm_mem == -1 ? "INVALID" : SOC_MEM_NAME(u, lpm_mem))); 4331 bkt++; 4332 } 4333 } 4334 } 4335 4336 if (bkt == 0) { 4337 LOG_CLI((BSL_META_U(u, "- None -\n"))); 4338 } 4339 4340 if (ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_PARALLEL && 4341 SOC_URPF_STATUS_GET(u)) { 4342 4343 LOG_CLI((BSL_META_U(u, 4344 "=================================================\n"))); 4345 LOG_CLI((BSL_META_U(u, 4346 " %s[%s]\n"), "Global Route bucket idx", "mem_view")); 4347 LOG_CLI((BSL_META_U(u, 4348 "=================================================\n"))); 4349 4350 bkt = 0; 4351 for (ipv = ALPM_IPV4; ipv < ALPM_IPVERS; ipv++) { 4352 if (ipv == ALPM_IPV6 && 4353 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4) == 4354 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6)) { 4355 break; 4356 } 4357 for (i = 0; i < SOC_TH_ALPM_BUCKET_COUNT(u); i += step_count) { 4358 SHR_BITTEST_RANGE( 4359 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv), i, step_count, used); 4360 if (used) { 4361 lpm_mem = soc_alpm_cmn_bkt_view_get( 4362 u, SOC_TH_ALPM_AIDX(u, i, 0, 0, 0)); 4363 LOG_CLI(( 4364 BSL_META_U(u, " 0x%04x[%24s]\n"), 4365 i, lpm_mem == -1 ? "INVALID" : SOC_MEM_NAME(u, lpm_mem))); 4366 bkt++; 4367 } 4368 } 4369 4370 } 4371 4372 if (bkt == 0) { 4373 LOG_CLI((BSL_META_U(u, "- None -\n"))); 4374 } 4375 } 4376 4377 sal_free(pivot); 4378 4379 return; 4380 } 4381 4382 /* Update bucket/hit index of tcam entry if urpf is enabled */ 4383 STATIC void 4384 _soc_th_alpm_urpf_tcam_info_update(int u, void *entry) 4385 { 4386 uint32 value = 0; 4387 4388 value = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, ALG_BKT_PTR0f); 4389 if (value) { 4390 value += SOC_TH_ALPM_BUCKET_COUNT(u); 4391 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, entry, ALG_BKT_PTR0f, value); 4392 } 4393 if (ALPM_CTRL(u).bkt_sharing) { 4394 value = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, ALG_SUB_BKT_PTR0f); 4395 if (value) { 4396 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, entry, 4397 ALG_SUB_BKT_PTR0f, value); 4398 } 4399 } 4400 4401 /* modify only valid hit index, both _0 and _1 need to be updated */ 4402 value = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, ALG_HIT_IDX0f); 4403 if (value) { 4404 value = _soc_th_alpm_rpf_entry(u, value); 4405 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, entry, ALG_HIT_IDX0f, value); 4406 } 4407 value = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, ALG_HIT_IDX1f); 4408 if (value) { 4409 value = _soc_th_alpm_rpf_entry(u, value); 4410 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, entry, ALG_HIT_IDX1f, value); 4411 } 4412 if (!soc_mem_field32_get(u, L3_DEFIPm, entry, MODE0_f(u))) { 4413 value = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, ALG_BKT_PTR1f); 4414 if (value) { 4415 value += SOC_TH_ALPM_BUCKET_COUNT(u); 4416 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, entry, 4417 ALG_BKT_PTR1f, value); 4418 } 4419 if (ALPM_CTRL(u).bkt_sharing) { 4420 value = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, 4421 entry, ALG_SUB_BKT_PTR1f); 4422 if (value) { 4423 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, entry, 4424 ALG_SUB_BKT_PTR1f, value); 4425 } 4426 } 4427 } 4428 4429 return; 4430 } 4431 4432 /* create shadow entry copy of primary tcam entry at index */ 4433 static int 4434 _soc_th_alpm_tcam_shadow_ent_init(int u, int r_index, void *entry, void *shadow, 4435 int w_index, int bpm_len, int v4_half) 4436 { 4437 uint32 tmp, ip_mask, v6, db_type, ent_type, urpf = 0; 4438 soc_mem_t s_mem = L3_DEFIP_AUX_TABLEm; 4439 defip_entry_t tmp_ipv4; 4440 int is_ipmc = 0; 4441 int rv = SOC_E_NONE, pfx, pfx2, vrf_id, vrf_id2, vrf, vrf2; 4442 int flex_v6_64 = 0; 4443 4444 SOC_IF_ERROR_RETURN(soc_mem_read(u, s_mem, MEM_BLOCK_ANY, r_index, 4445 shadow)); 4446 tmp = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, VRF_ID_0f); 4447 soc_mem_field32_set(u, s_mem, shadow, VRF0f, tmp); 4448 tmp = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, VRF_ID_1f); 4449 soc_mem_field32_set(u, s_mem, shadow, VRF1f, tmp); 4450 4451 tmp = soc_mem_field32_get(u, L3_DEFIPm, entry, MODE0_f(u)); 4452 soc_mem_field32_set(u, s_mem, shadow, MODE0_f(u), tmp); 4453 tmp = soc_mem_field32_get(u, L3_DEFIPm, entry, MODE1_f(u)); 4454 soc_mem_field32_set(u, s_mem, shadow, MODE1_f(u), tmp); 4455 v6 = tmp; 4456 4457 if (bpm_len == INVALID_BPM_LEN) { 4458 /* Clean dirty data */ 4459 if (soc_mem_field32_get(u, s_mem, shadow, VALID0f) == 0) { 4460 soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH0f, 0); 4461 } 4462 4463 if (soc_mem_field32_get(u, s_mem, shadow, VALID1f) == 0) { 4464 soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH1f, 0); 4465 } 4466 } else { 4467 assert(v6 == (v4_half==0)); 4468 if (v6) { 4469 soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH0f, bpm_len); 4470 soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH1f, bpm_len); 4471 } else { 4472 if (v4_half & 1) { 4473 soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH1f, bpm_len); 4474 } else { 4475 soc_mem_field32_set(u, s_mem, shadow, BPM_LENGTH0f, bpm_len); 4476 } 4477 } 4478 } 4479 /* for now simply copy all fields. Let caller decide which half to use */ 4480 tmp = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, VALID0f); 4481 soc_mem_field32_set(u, s_mem, shadow, VALID0f, tmp); 4482 tmp = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, VALID1f); 4483 soc_mem_field32_set(u, s_mem, shadow, VALID1f, tmp); 4484 4485 4486 /* IP_LENGTH */ 4487 tmp = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f); 4488 if ((rv = _ipmask2pfx(tmp, &pfx)) < 0) { 4489 LOG_ERROR(BSL_LS_SOC_ALPM, 4490 (BSL_META_U(u, 4491 "_ipmask2pfx fails mask0 0x%x pfx %d\n"), 4492 tmp, pfx)); 4493 return rv; 4494 } 4495 ip_mask = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK1f); 4496 if ((rv = _ipmask2pfx(ip_mask, &pfx2)) < 0) { 4497 LOG_ERROR(BSL_LS_SOC_ALPM, 4498 (BSL_META_U(u, 4499 "_ipmask2pfx fails mask1 0x%x pfx2 %d\n"), 4500 ip_mask, pfx2)); 4501 return rv; 4502 } 4503 if (v6) { 4504 soc_mem_field32_set(u, s_mem, shadow, IP_LENGTH0f, pfx + pfx2); 4505 soc_mem_field32_set(u, s_mem, shadow, IP_LENGTH1f, pfx + pfx2); 4506 } else { 4507 soc_mem_field32_set(u, s_mem, shadow, IP_LENGTH0f, pfx); 4508 soc_mem_field32_set(u, s_mem, shadow, IP_LENGTH1f, pfx2); 4509 } 4510 4511 /* IP_ADDR */ 4512 tmp = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR0f); 4513 soc_mem_field32_set(u, s_mem, shadow, IP_ADDR0f, tmp); 4514 tmp = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR1f); 4515 soc_mem_field32_set(u, s_mem, shadow, IP_ADDR1f, tmp); 4516 4517 /* DB_TYPE & ENTRY_TYPE */ 4518 /* for v4 need to be careful */ 4519 if (!v6) { 4520 sal_memcpy(&tmp_ipv4, entry, sizeof(tmp_ipv4)); 4521 /* vrf for ipv4 entry 0 */ 4522 rv = soc_th_alpm_lpm_vrf_get(u, (void *)&tmp_ipv4, &vrf_id, &vrf); 4523 SOC_IF_ERROR_RETURN(rv); 4524 4525 /* vrf for ipv4 entry 1 */ 4526 SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_ip4entry1_to_0(u, &tmp_ipv4, 4527 &tmp_ipv4, PRESERVE_HIT)); 4528 rv = soc_th_alpm_lpm_vrf_get(u, (void *)&tmp_ipv4, &vrf_id2, &vrf2); 4529 SOC_IF_ERROR_RETURN(rv); 4530 } else { 4531 rv = soc_th_alpm_lpm_vrf_get(u, entry, &vrf_id, &vrf); 4532 } 4533 if (SOC_URPF_STATUS_GET(u)) { 4534 if (w_index >= (soc_mem_index_count(u, L3_DEFIPm) >> 1)) { 4535 urpf = 1; 4536 } 4537 } 4538 4539 soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type); 4540 4541 if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && v6) { 4542 uint32 entry_view, flex; 4543 4544 entry_view = soc_mem_field32_get(u, L3_DEFIPm, entry, ENTRY_VIEW0f); 4545 flex = _soc_th_alpm_lpm_flex_get(u, v6, entry_view); 4546 if (flex) { 4547 if (pfx2 == 32 && pfx == 32) { 4548 flex_v6_64 = 1; 4549 } 4550 } 4551 } 4552 4553 if (soc_feature(u, soc_feature_ipmc_defip)) { 4554 is_ipmc = 0; 4555 if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE0f)) { 4556 is_ipmc = soc_mem_field32_get(u, L3_DEFIPm, entry, MULTICAST_ROUTE0f); 4557 } else if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE0f)) { 4558 if (soc_mem_field32_get(u, L3_DEFIPm, entry, DATA_TYPE0f) == 2) { 4559 is_ipmc = 1; 4560 } else { 4561 is_ipmc = 0; 4562 } 4563 } 4564 } 4565 4566 if (ALPM_PREFIX_IN_TCAM(u, vrf_id) || is_ipmc || flex_v6_64) { 4567 soc_mem_field32_set(u, s_mem, shadow, VALID0f, 0); 4568 db_type = 0; /* don't care */ 4569 } else { 4570 if (urpf) { 4571 db_type += 1; 4572 } 4573 } 4574 4575 soc_mem_field32_set(u, s_mem, shadow, DB_TYPE0f, db_type); 4576 tmp = soc_mem_field32_get(u, L3_DEFIPm, entry, ENTRY_TYPE0_f(u)); 4577 soc_mem_field32_set(u, s_mem, shadow, ENTRY_TYPE0_f(u), tmp | ent_type); 4578 if (!v6) { 4579 soc_alpm_db_ent_type_encoding(u, vrf2, &db_type, &ent_type); 4580 if (soc_feature(u, soc_feature_ipmc_defip)) { 4581 is_ipmc = 0; 4582 if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE1f)) { 4583 is_ipmc = soc_mem_field32_get(u, L3_DEFIPm, entry, MULTICAST_ROUTE1f); 4584 } else if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE1f)) { 4585 if (soc_mem_field32_get(u, L3_DEFIPm, entry, DATA_TYPE1f) == 2) { 4586 is_ipmc = 1; 4587 } else { 4588 is_ipmc = 0; 4589 } 4590 } 4591 } 4592 4593 if (ALPM_PREFIX_IN_TCAM(u, vrf_id2) || is_ipmc) { 4594 soc_mem_field32_set(u, s_mem, shadow, VALID1f, 0); 4595 db_type = 0; /* don't care */ 4596 } else { 4597 /* Database to be searched is VRF - DIP */ 4598 if (urpf) { 4599 db_type += 1; 4600 } 4601 } 4602 4603 soc_mem_field32_set(u, s_mem, shadow, DB_TYPE1f, db_type); 4604 tmp = soc_mem_field32_get(u, L3_DEFIPm, entry, ENTRY_TYPE1_f(u)); 4605 soc_mem_field32_set(u, s_mem, shadow, ENTRY_TYPE1_f(u), tmp | ent_type); 4606 } else { 4607 if (soc_feature(u, soc_feature_ipmc_defip)) { 4608 if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE1f)) { 4609 is_ipmc = soc_mem_field32_get(u, L3_DEFIPm, entry, MULTICAST_ROUTE1f); 4610 } else if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE1f)) { 4611 if (soc_mem_field32_get(u, L3_DEFIPm, entry, DATA_TYPE1f) == 2) { 4612 is_ipmc = 1; 4613 } 4614 } 4615 } 4616 4617 if (ALPM_PREFIX_IN_TCAM(u, vrf_id) || is_ipmc || flex_v6_64) { 4618 soc_mem_field32_set(u, s_mem, shadow, VALID1f, 0); 4619 } 4620 soc_mem_field32_set(u, s_mem, shadow, DB_TYPE1f, db_type); 4621 tmp = soc_mem_field32_get(u, L3_DEFIPm, entry, ENTRY_TYPE1_f(u)); 4622 soc_mem_field32_set(u, s_mem, shadow, ENTRY_TYPE1_f(u), tmp | ent_type); 4623 } 4624 4625 /* modify bucket index if urpf is enabled */ 4626 if (urpf) { 4627 _soc_th_alpm_urpf_tcam_info_update(u, entry); 4628 } 4629 4630 /* BPM_LENGTH */ 4631 /* don't modify, preserve existing values */ 4632 return SOC_E_NONE; 4633 } 4634 4635 static INLINE int 4636 _soc_th_alpm_write_pivot_with_bpm_aux(int u, int copyno, int index, int s_index, void *entry, 4637 int bpm_len, int v4_half) 4638 { 4639 defip_aux_table_entry_t shadow; 4640 4641 if (SOC_IS_TRIDENT3(u) && SOC_URPF_STATUS_GET(u) && 4642 (index >= (soc_mem_index_count(u, L3_DEFIPm) >> 1))) { 4643 soc_mem_t mem = L3_DEFIPm; 4644 soc_mem_field32_set(u, mem, entry, FLEX_CTR_BASE_COUNTER_IDX0f, 0); 4645 soc_mem_field32_set(u, mem, entry, FLEX_CTR_BASE_COUNTER_IDX1f, 0); 4646 } 4647 if (!ALPM_CTRL(u).aux_enable) { 4648 /* update defip entry */ 4649 if (SOC_URPF_STATUS_GET(u) && 4650 (index >= (soc_mem_index_count(u, L3_DEFIPm) >> 1))) { 4651 _soc_th_alpm_urpf_tcam_info_update(u, entry); 4652 } 4653 4654 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, index, entry)); 4655 } else { 4656 /* convert from logical to physical indices */ 4657 s_index = soc_th_alpm_physical_idx(u, L3_DEFIPm, s_index, 1); 4658 SOC_IF_ERROR_RETURN(_soc_th_alpm_tcam_shadow_ent_init(u, s_index, entry, 4659 (void *)&shadow, index, bpm_len, v4_half)); 4660 4661 /* write to defip has to be logical */ 4662 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIPm(u, MEM_BLOCK_ANY, index, entry)); 4663 4664 /* write to shadow table has to be physical */ 4665 index = soc_th_alpm_physical_idx(u, L3_DEFIPm, index, 1); 4666 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ANY, 4667 index, &shadow)); 4668 } 4669 4670 return SOC_E_NONE; 4671 4672 } 4673 4674 /* 4675 * Replicate entry to the second half of the tcam if URPF check is ON. 4676 */ 4677 static INLINE int 4678 _lpm_fb_urpf_entry_replicate_with_bpm(int u, int index, uint32 *e, int bpm_len, int v4_half, 4679 int src_default, int src_discard) 4680 { 4681 int src_tcam_offset; /* Defip memory size/2 urpf source lookup offset */ 4682 int ipv6; /* IPv6 entry. */ 4683 uint32 mask0; /* Mask 0 field value. */ 4684 uint32 mask1; /* Mask 1 field value. */ 4685 int def_gw_flag; /* Entry is default gateway. */ 4686 int src_default_0 = 0, src_default_1 = 0; 4687 int src_discard_0 = 0, src_discard_1 = 0; 4688 4689 if(!SOC_URPF_STATUS_GET(u)) { 4690 return (SOC_E_NONE); 4691 } 4692 4693 if (soc_feature(u, soc_feature_l3_defip_hole)) { 4694 src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1); 4695 } else if (SOC_IS_APOLLO(u)) { 4696 src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1) + 0x0400; 4697 } else { 4698 src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1); 4699 } 4700 4701 ipv6 = soc_mem_field32_get(u, L3_DEFIPm, e, MODE0_f(u)); 4702 4703 /* Reset destination discard bit. */ 4704 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD0f)) { 4705 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD0f, 0); 4706 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD1f, 0); 4707 } 4708 4709 /* Set/Reset default gateway flag based on ip mask value. */ 4710 mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, IP_ADDR_MASK0f); 4711 mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, IP_ADDR_MASK1f); 4712 4713 if (!ipv6) { 4714 src_default_0 = src_default & (1 << 0) ? 1 : 0; 4715 src_default_1 = src_default & (1 << 1) ? 1 : 0; 4716 src_discard_0 = src_discard & (1 << 0) ? 1 : 0; 4717 src_discard_1 = src_discard & (1 << 1) ? 1 : 0; 4718 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f)) { 4719 def_gw_flag = (!mask0) ? 1 : 0; 4720 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE0f, src_default_0 | def_gw_flag); 4721 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD0f)) { 4722 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD0f, src_discard_0); 4723 } 4724 if (SOC_IS_TRIDENT3X(u)) { 4725 soc_mem_field32_set(u, L3_DEFIPm, e, DATA_TYPE0f, 1); 4726 } 4727 } 4728 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f)) { 4729 def_gw_flag = (!mask1) ? 1 : 0; 4730 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE1f, src_default_1 | def_gw_flag); 4731 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD1f)) { 4732 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD1f, src_discard_1); 4733 } 4734 if (SOC_IS_TRIDENT3X(u)) { 4735 soc_mem_field32_set(u, L3_DEFIPm, e, DATA_TYPE1f, 1); 4736 } 4737 } 4738 } else { 4739 src_default = src_default ? 1 : 0; 4740 src_discard = src_discard ? 1 : 0; 4741 def_gw_flag = ((!mask0) && (!mask1)) ? 1 : 0; 4742 mask0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f); 4743 mask1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f); 4744 if (mask0 && mask1) { 4745 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE0f, src_default | def_gw_flag); 4746 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, RPE1f, src_default | def_gw_flag); 4747 if (SOC_MEM_OPT_FIELD_VALID(u, L3_DEFIPm, DST_DISCARD0f)) { 4748 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD0f, src_discard); 4749 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, e, DST_DISCARD1f, src_discard); 4750 } 4751 if (SOC_IS_TRIDENT3X(u)) { 4752 soc_mem_field32_set(u, L3_DEFIPm, e, DATA_TYPE0f, 1); 4753 soc_mem_field32_set(u, L3_DEFIPm, e, DATA_TYPE1f, 1); 4754 } 4755 } 4756 } 4757 /* Write entry to the second half of the tcam. */ 4758 return _soc_th_alpm_write_pivot_with_bpm_aux(u, MEM_BLOCK_ANY, index + src_tcam_offset, 4759 index, e, bpm_len, v4_half); 4760 } 4761 4762 /* 4763 * Replicate entry to the second half of the tcam if URPF check is ON. 4764 */ 4765 static 4766 int _lpm_fb_urpf_entry_replicate(int u, int index, uint32 *e, 4767 int sdefault, int sdiscard) 4768 { 4769 return _lpm_fb_urpf_entry_replicate_with_bpm(u, index, e, INVALID_BPM_LEN, 0, 4770 sdefault, sdiscard); 4771 } 4772 4773 static INLINE int 4774 _soc_th_alpm_write_pivot_with_bpm(int u, int copyno, int index, int s_index, void *entry, 4775 int bpm_len, int v4_half, int src_default, 4776 int src_discard) 4777 { 4778 int rv; 4779 rv = _soc_th_alpm_write_pivot_with_bpm_aux 4780 (u, copyno, index, s_index, entry, bpm_len, v4_half); 4781 4782 if (rv >= 0) { 4783 if (bpm_len == INVALID_BPM_LEN) { 4784 rv = _lpm_fb_urpf_entry_replicate(u, index, entry, 4785 src_default, src_discard); 4786 } else { 4787 rv = _lpm_fb_urpf_entry_replicate_with_bpm(u, index, entry, 4788 bpm_len, v4_half, 4789 src_default, src_discard); 4790 } 4791 } 4792 return rv; 4793 } 4794 4795 4796 static int 4797 _soc_th_alpm_write_pivot(int u, int copyno, int index, int s_index, void *entry, 4798 int src_default, int src_discard) 4799 { 4800 return _soc_th_alpm_write_pivot_with_bpm 4801 (u, copyno, index, s_index, entry, INVALID_BPM_LEN, 0, src_default, 4802 src_discard); 4803 } 4804 4805 4806 4807 int 4808 _soc_th_alpm_insert_in_bkt(int u, soc_mem_t mem, int log_bkt, 4809 int bank_disable, void *alpm_data, void *alpm_sip_data, 4810 uint32 *e, int *key_index, int v6) 4811 { 4812 int rv; 4813 4814 rv = soc_mem_alpm_insert(u, mem, ALPM_PHY_BKT(u, log_bkt), 4815 MEM_BLOCK_ANY, bank_disable, alpm_data, e, 4816 key_index); 4817 if (rv == SOC_E_FULL) { 4818 /* in combined search mode non-urpf try inserting into next bkt for v6*/ 4819 if (ALPM_CTRL(u).double_wide[v6]) { 4820 rv = soc_mem_alpm_insert(u, mem, ALPM_PHY_BKT(u, log_bkt) + 1, 4821 MEM_BLOCK_ANY, 4822 bank_disable, 4823 alpm_data, e, key_index); 4824 } 4825 } 4826 4827 if (SOC_SUCCESS(rv)) { 4828 if (SOC_URPF_STATUS_GET(u)) { 4829 soc_mem_field32_set(u, mem, alpm_sip_data, SUB_BKT_PTRf, 4830 ALPM_SUB_BKT(u, log_bkt)); 4831 rv = soc_mem_write(u, mem, MEM_BLOCK_ANY, 4832 _soc_th_alpm_rpf_entry(u, *key_index), 4833 alpm_sip_data); 4834 } 4835 } 4836 return rv; 4837 } 4838 4839 4840 /* ALPM Table Address Translation 4841 * Bank addr[1:0] 4842 * Bucket addr[15:2] 4843 * Entry addr[16] L3_DEFIP_ALPM_IPV6_128m 4844 * addr[16:17] L3_DEFIP_ALPM_IPV6_64m 4845 * addr[16:18] L3_DEFIP_ALPM_IPV4m 4846 */ 4847 int 4848 _soc_th_alpm_mem_index(int u, soc_mem_t mem, int bkt, int offset, 4849 uint32 bank_disable, int *mem_index) 4850 { 4851 int i = 0; 4852 int bank = 0; 4853 int ent = 0; 4854 int bank_enable_count; 4855 4856 int ent_count = 6; 4857 int ent_pos; 4858 int bkt_bts = ALPM_CTRL(u).bkt_bits; 4859 4860 switch (mem) { 4861 case L3_DEFIP_ALPM_IPV4m: 4862 ent_count = 6; 4863 break; 4864 case L3_DEFIP_ALPM_IPV4_1m: 4865 ent_count = 4; 4866 break; 4867 case L3_DEFIP_ALPM_IPV6_64m: 4868 ent_count = 4; 4869 break; 4870 case L3_DEFIP_ALPM_IPV6_64_1m: 4871 ent_count = 3; 4872 break; 4873 case L3_DEFIP_ALPM_IPV6_128m: 4874 ent_count = 2; 4875 break; 4876 default: 4877 break; 4878 } 4879 4880 /* Prepare ent */ 4881 ent = offset % ent_count; 4882 4883 /* Prepare bkt position and ent position */ 4884 ent_pos = bkt_bts + ALPM_CTRL(u).bank_bits; 4885 4886 /* Prepare bank enable count */ 4887 bank_enable_count = MAX_BANK_COUNT(u) - _shr_popcount(bank_disable & 0xFF); 4888 4889 /* Prepare bkt and check range */ 4890 i = offset / (bank_enable_count * ent_count); 4891 if (i == 1) { 4892 offset -= bank_enable_count * ent_count; 4893 bkt++; 4894 } else if (i > 1) { 4895 return SOC_E_PARAM; 4896 } 4897 4898 if (bkt >= (1 << bkt_bts)) { 4899 return SOC_E_PARAM; 4900 } 4901 4902 /* Prepare bank */ 4903 i = offset / ent_count; 4904 for (bank = 0; bank < ALPM_CTRL(u).num_banks; bank++) { 4905 if ((1 << bank) & bank_disable) { 4906 continue; 4907 } 4908 4909 if (0 == i--) { 4910 break; 4911 } 4912 } 4913 4914 *mem_index = (ent << ent_pos) | (bkt << ALPM_CTRL(u).bank_bits) | (bank); 4915 4916 return SOC_E_NONE; 4917 } 4918 4919 4920 4921 static int 4922 _soc_th_alpm_bucket_split(int u, alpm_pfx_info_t *pfx_info, int *index_ptr) 4923 { 4924 trie_node_t *split_trie_root; 4925 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 4926 uint32 length, bpm_len = 0; 4927 uint32 bank_disable = 0; 4928 uint32 pivot[5] = {0}; 4929 uint32 bpm[5] = {0}; 4930 uint32 src_discard, src_default; 4931 int key_index, i; 4932 trie_t *bkt_trie; 4933 defip_entry_t lpm_entry; 4934 alpm_mem_prefix_array_t *pfx_array = NULL; 4935 int *new_index = NULL; 4936 int rv = SOC_E_NONE, new_index_pos = -1; 4937 int tcam_index, pivot_index; 4938 void *bufp = NULL, *sip_bufp = NULL; 4939 int max_split_count; 4940 alpm_pivot_t *new_pivot = NULL; 4941 int max_split_length = 0; 4942 int v6 = (L3_DEFIP_ALPM_IPV6_64m == pfx_info->mem || 4943 L3_DEFIP_ALPM_IPV6_64_1m == pfx_info->mem || 4944 L3_DEFIP_ALPM_IPV6_128m == pfx_info->mem); 4945 enum { 4946 _SPLIT_TRIE_NONE, 4947 _SPLIT_TRIE_SPLIT, 4948 _SPLIT_LPM_INIT, 4949 _SPLIT_PIVOT_CREATE, 4950 _SPLIT_PREPARE, 4951 _SPLIT_COPY, 4952 _SPLIT_LPM_INSERT, 4953 _SPLIT_INVALIDATE 4954 } doing = _SPLIT_TRIE_NONE, done = _SPLIT_TRIE_NONE; 4955 4956 bkt_trie = PIVOT_BUCKET_TRIE(ALPM_TCAM_PIVOT(u, pfx_info->pivot_idx_from)); 4957 4958 /* If free space is less than a single bucket capacity (start 4959 * using sub bucket 1..., ) 4960 * We need to limit the split_trie_root payload count 4961 */ 4962 max_split_count = _soc_th_alpm_bkt_entry_cnt(u, pfx_info->mem) - 4963 SOC_ALPM_BU_COUNT(u, ALPM_PHY_BKT(u, pfx_info->log_bkt_to)); 4964 4965 max_split_length = (v6 ? 64 : 32) - 1; 4966 4967 doing = _SPLIT_TRIE_SPLIT; 4968 rv = trie_split(bkt_trie, max_split_length, FALSE, 4969 pivot, &length, &split_trie_root, NULL, FALSE, max_split_count); 4970 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 4971 4972 if (length > max_split_length) { 4973 rv = SOC_E_FULL; 4974 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 4975 } 4976 4977 doing = _SPLIT_LPM_INIT; 4978 rv = _soc_th_alpm_split_lpm_init(u, 4979 pfx_info->mem, 4980 pfx_info->pivot_idx_from, 4981 pfx_info->vrf, 4982 pfx_info->log_bkt_to, 4983 pfx_info->alpm_data, 4984 pfx_info->alpm_sip_data, 4985 pivot, length, 4986 &lpm_entry, &bpm_len, bpm, 4987 &src_discard, &src_default); 4988 4989 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 4990 4991 doing = _SPLIT_PIVOT_CREATE; 4992 rv = _soc_th_alpm_split_pivot_create(u, v6, pfx_info->vrf, pfx_info->log_bkt_to, 4993 split_trie_root, pivot, length, 4994 bpm_len, bpm, &new_pivot); 4995 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 4996 4997 doing = _SPLIT_PREPARE; 4998 rv = _soc_th_alpm_bucket_prepare(u, pfx_info->mem, PIVOT_BUCKET_TRIE(new_pivot), 4999 &pfx_array, &bufp, &sip_bufp, &new_index); 5000 5001 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5002 5003 doing = _SPLIT_COPY; 5004 rv = _soc_th_alpm_bucket_copy(u, pfx_info->mem, pfx_info->vrf, pfx_array, 5005 pfx_info->log_bkt_to, 5006 bufp, sip_bufp, pfx_info->alpm_data, 5007 pfx_info->alpm_sip_data, new_index, &new_index_pos); 5008 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5009 5010 doing = _SPLIT_LPM_INSERT; 5011 rv = soc_th_alpm_lpm_insert(u, &lpm_entry, &tcam_index, bpm_len, src_default, 5012 src_discard); 5013 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5014 5015 /* TCAM index from lpm code is logical. Convert to global idx */ 5016 tcam_index = soc_th_alpm_physical_idx(u, L3_DEFIPm, tcam_index, v6); 5017 pivot_index = tcam_index << (v6 ? 1 : 0); 5018 PIVOT_TCAM_INDEX(new_pivot) = pivot_index; 5019 ALPM_TCAM_PIVOT(u, pivot_index) = new_pivot; 5020 5021 doing = _SPLIT_INVALIDATE; 5022 rv = _soc_th_alpm_bucket_inval(u, pfx_info->mem, pfx_array, bufp, sip_bufp); 5023 _ALPM_IF_ERROR_GOTO(rv, _rollback, done, doing); 5024 5025 /* Don't try rollback from here on, since split is successful. */ 5026 rv = soc_th_alpm_hit_bits_update(u, pfx_array, new_index, v6, pfx_info->vrf); 5027 if (SOC_FAILURE(rv)) { 5028 LOG_ERROR(BSL_LS_SOC_ALPM, 5029 (BSL_META_U(u, "update_hit_bits failed, count %d\n"), 5030 pfx_array->count)); 5031 rv = SOC_E_NONE; 5032 } 5033 5034 if (new_index_pos != -1) { /* New prefix goes to new split bucket */ 5035 *index_ptr = new_index[new_index_pos]; 5036 } else { /* To old parent bucket, do actual insert */ 5037 /* Add Entry to old bucket RAM */ 5038 soc_mem_field32_set(u, pfx_info->mem, pfx_info->alpm_data, SUB_BKT_PTRf, 5039 ALPM_SUB_BKT(u, pfx_info->log_bkt_from)); 5040 /* entry shouldn't exist, insert the entry into the RAM */ 5041 bank_disable = 5042 ALPM_CTRL(u).bank_disable_bmp[pfx_info->vrf != (SOC_VRF_MAX(u) + 1)]; 5043 rv = _soc_th_alpm_insert_in_bkt(u, pfx_info->mem, pfx_info->log_bkt_from, 5044 bank_disable, pfx_info->alpm_data, 5045 pfx_info->alpm_sip_data, e, &key_index, v6); 5046 5047 assert(rv == 0); 5048 if (SOC_FAILURE(rv)) { 5049 /* recover by matching trie state to h/w state */ 5050 LOG_ERROR(BSL_LS_SOC_ALPM, 5051 (BSL_META_U(u, "Could not insert new " 5052 "prefix into trie after split\n"))); 5053 /* since split was successful, leave split state as-is */ 5054 pfx_info->log_bkt_to = -1; 5055 return rv; 5056 } 5057 5058 *index_ptr = key_index; 5059 } 5060 5061 /* Update old bucket usage */ 5062 soc_th_alpm_bucket_usage_decr(u, pfx_info->log_bkt_from, 5063 FALSE, pfx_info->vrf, 5064 pfx_info->mem, pfx_array->count - 1, 5065 pfx_info->log_bkt_to); 5066 /* Update new bucket usage */ 5067 soc_th_alpm_bucket_usage_incr(u, pfx_info->log_bkt_to, 5068 pivot_index, pfx_info->vrf, 5069 pfx_info->mem, pfx_array->count); 5070 5071 PIVOT_BUCKET_ENT_CNT_UPDATE(new_pivot); 5072 VRF_BUCKET_SPLIT_INC(u, pfx_info->vrf, v6); 5073 5074 /* Update new index */ 5075 for (i = 0; i < pfx_array->count; i++) { 5076 pfx_array->prefix[i]->index = new_index[i]; 5077 } 5078 5079 _soc_th_alpm_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index); 5080 return rv; 5081 5082 _rollback: 5083 /* fall through on all cases */ 5084 switch (done) { 5085 case _SPLIT_LPM_INSERT: 5086 soc_th_alpm_lpm_delete(u, &lpm_entry); 5087 5088 case _SPLIT_COPY: 5089 /* Delete entries in new bucket */ 5090 _soc_th_alpm_bucket_copy_undo(u, pfx_info->mem, pfx_array->count, new_index); 5091 5092 case _SPLIT_PREPARE: 5093 _soc_th_alpm_bucket_prepare_undo(u, &pfx_array, &bufp, &sip_bufp, &new_index); 5094 5095 case _SPLIT_PIVOT_CREATE: 5096 _soc_th_alpm_split_pivot_create_undo(u, v6, pfx_info->vrf, pivot, length, NULL, 0); 5097 5098 case _SPLIT_LPM_INIT: 5099 /* nothing to undo */ 5100 case _SPLIT_TRIE_SPLIT: 5101 trie_merge(bkt_trie, split_trie_root, pivot, length); 5102 5103 case _SPLIT_TRIE_NONE: 5104 default: 5105 /* nothing to rollback for first step */ 5106 break; 5107 } 5108 5109 switch (doing) { 5110 case _SPLIT_TRIE_SPLIT: 5111 LOG_ERROR(BSL_LS_SOC_ALPM, 5112 (BSL_META_U(u, 5113 "Could not split bucket"))); 5114 break; 5115 5116 case _SPLIT_PIVOT_CREATE: 5117 LOG_ERROR(BSL_LS_SOC_ALPM, 5118 (BSL_META_U(u, "failed to insert into pivot bkt_trie\n"))); 5119 break; 5120 5121 case _SPLIT_LPM_INSERT: 5122 LOG_ERROR(BSL_LS_SOC_ALPM, 5123 (BSL_META_U(u, 5124 "Unable to add new pivot to tcam\n"))); 5125 5126 if (rv == SOC_E_FULL) { 5127 VRF_PIVOT_FULL_INC(u, pfx_info->vrf, v6); 5128 } 5129 break; 5130 default: 5131 LOG_ERROR(BSL_LS_SOC_ALPM, 5132 (BSL_META_U(u, 5133 "Split fails at step %d\n"), doing)); 5134 break; 5135 } 5136 5137 return rv; 5138 } 5139 5140 /* 5141 * Insert entry into ALPM database. 5142 * Returns SOC_E_NONE, if found and updated. 5143 * SOC_E_FAIL, if insert failed. 5144 */ 5145 static int 5146 _soc_th_alpm_insert(int u, 5147 int v6, 5148 void *key_data, /* TCAM entry data */ 5149 soc_mem_t mem, /* Mem view for ALPM data */ 5150 void *alpm_data, /* Alpm data to be updated with */ 5151 void *alpm_sip_data, 5152 int *index_ptr, 5153 int log_bkt, 5154 int tcam_index) /* return key location */ 5155 { 5156 alpm_pivot_t *old_pivot; 5157 defip_aux_scratch_entry_t aux_entry; 5158 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 5159 uint32 prefix[5], length; 5160 int vrf, vrf_id; 5161 int key_index; 5162 int rv = SOC_E_NONE; 5163 uint32 db_type, ent_type, bank_disable; 5164 int hit = 0; 5165 int free_count, old_count = 0; 5166 int split = 0; 5167 trie_t *bkt_trie = NULL, *pfx_trie = NULL; 5168 trie_node_t *lpmp = NULL, *lpmp2 = NULL; 5169 payload_t *bkt_payload = NULL, *pfx_payload = NULL, *tmp_pyld; 5170 int default_route = 0; 5171 /* Search Result buffers */ 5172 alpm_pfx_info_t pfx_info; 5173 int new_log_bkt = -1; 5174 int bkt_trie_inserted = 0, pfx_trie_inserted = 0; 5175 int shuffled = 0, aux_flags = 0; 5176 5177 SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf)); 5178 bank_disable = 5179 ALPM_CTRL(u).bank_disable_bmp[vrf != (SOC_VRF_MAX(u) + 1)]; 5180 soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type); 5181 5182 /* Get table memory. */ 5183 SOC_ALPM_TABLE_MEM(u, v6, mem, VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 1)); 5184 5185 /* Insert the prefix into the bucket trie, whether the insert was 5186 * successul or resulted in Split. Spliting the trie after insertion 5187 * yeilds better pivot and better split. 5188 */ 5189 /* Create Prefix */ 5190 rv = _soc_th_alpm_prefix_create(u, v6, key_data, prefix, &length, 5191 &default_route); 5192 if (SOC_FAILURE(rv)) { 5193 LOG_ERROR(BSL_LS_SOC_ALPM, 5194 (BSL_META_U(u, 5195 "_soc_th_alpm_insert: prefix create failed\n"))); 5196 return rv; 5197 } 5198 5199 /* Fill in AUX Scratch and perform PREFIX Operation */ 5200 sal_memset(&aux_entry, 0, sizeof(defip_aux_scratch_entry_t)); 5201 SOC_IF_ERROR_RETURN( 5202 _soc_th_alpm_fill_aux_entry_for_op(u, key_data, v6, db_type, ent_type, 0, 5203 &aux_entry)); 5204 5205 /* we need to do sw pivot find again, or we may miss sub_bkt info */ 5206 if (log_bkt == 0) { 5207 if (ALPM_CTRL(u).sw_prefix_lkup) { 5208 rv = _soc_th_alpm_sw_pivot_find(u, prefix, length, v6, vrf, &hit, 5209 &tcam_index, &log_bkt); 5210 } else { 5211 rv = _soc_th_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry, TRUE, &hit, 5212 &tcam_index, &log_bkt, 0); 5213 } 5214 SOC_IF_ERROR_RETURN(rv); 5215 soc_mem_field32_set(u, mem, alpm_data, SUB_BKT_PTRf, 5216 ALPM_SUB_BKT(u, log_bkt)); 5217 } 5218 5219 /* entry shouldn't exist, insert the entry into the RAM */ 5220 rv = _soc_th_alpm_insert_in_bkt(u, mem, log_bkt, 5221 bank_disable, alpm_data, alpm_sip_data, 5222 e, &key_index, v6); 5223 5224 old_pivot = ALPM_TCAM_PIVOT(u, tcam_index); 5225 5226 if (rv == SOC_E_NONE) { 5227 *index_ptr = key_index; 5228 } else if (rv == SOC_E_FULL) { 5229 5230 rv = soc_th_alpm_assign(u, vrf, mem, &new_log_bkt, 5231 &shuffled, &free_count); 5232 SOC_IF_ERROR_RETURN(rv); 5233 5234 if (shuffled) { 5235 if (ALPM_CTRL(u).sw_prefix_lkup) { 5236 rv = _soc_th_alpm_sw_pivot_find(u, prefix, length, v6, vrf, &hit, 5237 &tcam_index, &log_bkt); 5238 } else { 5239 rv = _soc_th_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry, TRUE, &hit, 5240 &tcam_index, &log_bkt, 0); 5241 } 5242 SOC_IF_ERROR_RETURN(rv); 5243 soc_mem_field32_set(u, mem, alpm_data, SUB_BKT_PTRf, 5244 ALPM_SUB_BKT(u, log_bkt)); 5245 5246 old_pivot = ALPM_TCAM_PIVOT(u, tcam_index); 5247 } 5248 5249 if (PIVOT_BUCKET_TRIE(old_pivot)->trie == NULL || 5250 (((old_count = (PIVOT_BUCKET_COUNT(old_pivot)) + 1)) <= free_count && 5251 _soc_th_alpm_lpm_free_entries(u, mem, vrf) == 0)) { /* find a new home*/ 5252 LOG_DEBUG(BSL_LS_SOC_ALPM, 5253 (BSL_META_U(u, 5254 "Find new home free_count %d old_count + 1 %d\n" 5255 ), free_count, old_count + 1)); 5256 rv = _soc_th_alpm_bucket_merge(u, mem, log_bkt, new_log_bkt, MERGE_PHY, NULL); 5257 if (SOC_FAILURE(rv)) { 5258 soc_th_alpm_bucket_release(u, new_log_bkt, vrf, v6); 5259 return rv; 5260 } 5261 log_bkt = new_log_bkt; 5262 soc_mem_field32_set(u, mem, alpm_data, SUB_BKT_PTRf, 5263 ALPM_SUB_BKT(u, log_bkt)); 5264 /* entry shouldn't exist, insert the entry into the RAM */ 5265 rv = _soc_th_alpm_insert_in_bkt(u, mem, log_bkt, 5266 bank_disable, alpm_data, alpm_sip_data, 5267 e, &key_index, v6); 5268 if (SOC_SUCCESS(rv)) { 5269 *index_ptr = key_index; 5270 } else { 5271 return rv; 5272 } 5273 } else { 5274 split = 1; 5275 /* this indicates a new route, which will be used to decide 5276 * if the new route happens to be new pivot. 5277 */ 5278 key_index = -1; 5279 } 5280 } else { 5281 return rv; 5282 } 5283 5284 /* Allocate Payload */ 5285 bkt_payload = sal_alloc(sizeof(payload_t), "Payload for Key"); 5286 if (bkt_payload == NULL) { 5287 LOG_ERROR(BSL_LS_SOC_ALPM, 5288 (BSL_META_U(u, 5289 "Unable to allocate memory for " 5290 "bkt_payload entry\n"))); 5291 rv = SOC_E_MEMORY; 5292 goto _rollback; 5293 } 5294 5295 pfx_payload = sal_alloc(sizeof(payload_t), "Payload for pfx trie key"); 5296 if (pfx_payload == NULL) { 5297 LOG_ERROR(BSL_LS_SOC_ALPM, 5298 (BSL_META_U(u, 5299 "Unable to allocate memory for " 5300 "pfx trie node\n"))); 5301 rv = SOC_E_MEMORY; 5302 goto _rollback; 5303 } 5304 sal_memset(bkt_payload, 0, sizeof(*bkt_payload)); 5305 sal_memset(pfx_payload, 0, sizeof(*pfx_payload)); 5306 sal_memcpy(bkt_payload->key, prefix, sizeof(prefix)); 5307 bkt_payload->len = length; 5308 /* Needs update for split case, updated below */ 5309 bkt_payload->index = key_index; 5310 /* create duplicate for prefix bkt_trie */ 5311 sal_memcpy(pfx_payload, bkt_payload, sizeof(*bkt_payload)); 5312 pfx_payload->bkt_ptr = bkt_payload; 5313 5314 /* Insert the prefix */ 5315 /* bucket trie insert */ 5316 bkt_trie = PIVOT_BUCKET_TRIE(old_pivot); 5317 rv = trie_insert(bkt_trie, prefix, NULL, length, (trie_node_t *)bkt_payload); 5318 if (SOC_SUCCESS(rv)) { 5319 bkt_trie_inserted = 1; 5320 } else { 5321 goto _rollback; 5322 } 5323 5324 /* prefix trie insert */ 5325 if (v6) { 5326 pfx_trie = VRF_PREFIX_TRIE_IPV6(u, vrf); 5327 } else { 5328 pfx_trie = VRF_PREFIX_TRIE_IPV4(u, vrf); 5329 } 5330 if (!default_route) { 5331 /* default route already in trie */ 5332 uint32 bpm[5]; 5333 _soc_th_alpm_mask_prefix_create(u, v6, length, bpm); 5334 rv = trie_insert(pfx_trie, prefix, 5335 ALPM_CTRL(u).trie_propagate ? bpm : NULL, 5336 length, (trie_node_t *)pfx_payload); 5337 if (SOC_SUCCESS(rv)) { 5338 pfx_trie_inserted = 1; 5339 } 5340 } else { 5341 /* update the default route */ 5342 lpmp = NULL; 5343 rv = trie_find_lpm(pfx_trie, 0, 0, &lpmp); 5344 tmp_pyld = (payload_t *)lpmp; 5345 if (SOC_SUCCESS(rv)) { 5346 tmp_pyld->bkt_ptr = bkt_payload; 5347 } 5348 } 5349 if (SOC_FAILURE(rv)) { 5350 goto _rollback; 5351 } 5352 5353 /* Performs lazy splitting */ 5354 if (split) { 5355 pfx_info.pivot_idx_from = tcam_index; 5356 pfx_info.alpm_data = alpm_data; 5357 pfx_info.alpm_sip_data = alpm_sip_data; 5358 pfx_info.log_bkt_from = log_bkt; 5359 pfx_info.log_bkt_to = new_log_bkt; 5360 pfx_info.vrf = vrf; 5361 pfx_info.mem = mem; 5362 rv = _soc_th_alpm_bucket_split(u, &pfx_info, index_ptr); 5363 if (rv != SOC_E_NONE) { 5364 new_log_bkt = pfx_info.log_bkt_to; 5365 goto _rollback; 5366 } 5367 bkt_payload->index = *index_ptr; 5368 /* New Pivot */ 5369 _alpm_dbg_cntr[u].bkt_split++; 5370 } else { 5371 soc_th_alpm_bucket_usage_incr(u, log_bkt, tcam_index, vrf, mem, 1); 5372 } 5373 5374 /* from here on, we don't expect any failure */ 5375 5376 /* propagate the insertion */ 5377 if (default_route) { 5378 /* also free unused pfx_payload pointer */ 5379 sal_free(pfx_payload); 5380 } 5381 /* do insert propagation to update existing default datas */ 5382 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, &aux_entry, ALG_HIT_IDXf, 5383 *index_ptr); 5384 5385 if (SOC_URPF_STATUS_GET(u)) { 5386 if (soc_mem_field32_get(u, mem, alpm_sip_data, DEFAULTROUTEf)) { 5387 aux_flags |= SOC_ALPM_AUX_DEF_ROUTE; 5388 } 5389 if (soc_mem_field32_get(u, mem, alpm_sip_data, SRC_DISCARDf)) { 5390 aux_flags |= SOC_ALPM_AUX_SRC_DISCARD; 5391 } 5392 } 5393 5394 SOC_IF_ERROR_RETURN(_soc_th_alpm_aux_op(u, INSERT_PROPAGATE, &aux_entry, 5395 TRUE, &hit, &tcam_index, &log_bkt, aux_flags)); 5396 5397 /* For debug, update the old pivot's counter */ 5398 PIVOT_BUCKET_ENT_CNT_UPDATE(old_pivot); 5399 return rv; 5400 5401 _rollback: 5402 if (!default_route && pfx_trie_inserted) { 5403 (void)trie_delete(pfx_trie, prefix, length, &lpmp); 5404 } 5405 5406 if (bkt_trie_inserted) { 5407 (void)trie_delete(bkt_trie, prefix, length, &lpmp2); 5408 } 5409 5410 if (pfx_payload) { 5411 sal_free(pfx_payload); 5412 } 5413 5414 if (bkt_payload) { 5415 sal_free(bkt_payload); 5416 } 5417 5418 if (split && new_log_bkt != -1) { 5419 /* for non-split case, the new logical bucket is taking effect and thus 5420 * should not be released 5421 */ 5422 (void)soc_th_alpm_bucket_release(u, new_log_bkt, vrf, v6); 5423 } 5424 return rv; 5425 } 5426 5427 /* Build an LPM entry, from a key */ 5428 /* Mostly used for the match */ 5429 static int 5430 _soc_th_alpm_lpm_ent_key_init(int u, uint32 *addr, int len, int vrf, int ipv6, 5431 defip_entry_t *lpm_entry, int init) 5432 { 5433 uint32 mask; 5434 soc_mem_t mem = L3_DEFIPm; 5435 5436 /* Zero buffers. */ 5437 if (init) { 5438 sal_memset(lpm_entry, 0, sizeof(defip_entry_t)); 5439 } 5440 5441 /* and with mask to ensure global vrf gets set to 0 */ 5442 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_0f, 5443 vrf & SOC_VRF_MAX(u)); 5444 if (vrf == (SOC_VRF_MAX(u) + 1)) { 5445 /* for global routes */ 5446 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f, 0); 5447 } else { 5448 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f, 5449 SOC_VRF_MAX(u)); 5450 } 5451 5452 if (SOC_MEM_FIELD_VALID(u, mem, DWf)) { 5453 soc_mem_field32_set(u, mem, lpm_entry, DWf, 0); 5454 } 5455 5456 if (ipv6) { 5457 5458 /* Set address to the buffer. */ 5459 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR0f, addr[0]); 5460 5461 /* Set address to the buffer. */ 5462 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR1f, addr[1]); 5463 5464 /* Set mode to ipv6 */ 5465 soc_mem_field32_set(u, mem, lpm_entry, MODE0_f(u), 1); 5466 soc_mem_field32_set(u, mem, lpm_entry, MODE1_f(u), 1); 5467 5468 /* Set Virtual Router id */ 5469 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_1f, vrf & 5470 SOC_VRF_MAX(u)); 5471 if (vrf == (SOC_VRF_MAX(u) + 1)) { 5472 /* for global routes */ 5473 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_MASK1f, 0); 5474 } else { 5475 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_MASK1f, 5476 SOC_VRF_MAX(u)); 5477 } 5478 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VALID1f, 1); 5479 5480 if (len >= 32) { 5481 mask = 0xffffffff; 5482 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, mask); 5483 mask = ~SHR_SHIFT_RIGHT(0xffffffff, len - 32); 5484 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, mask); 5485 } else { 5486 mask = ~(0xffffffff >> len); 5487 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, mask); 5488 /* make sure lower word of mask is 0 */ 5489 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, 0); 5490 } 5491 } else { 5492 /* Set address to the buffer. */ 5493 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR0f, addr[0]); 5494 5495 assert(len <= 32); 5496 mask = (len == 32) ? 0xffffffff : ~(0xffffffff >> len); 5497 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, mask); 5498 } 5499 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VALID0f, 1); 5500 5501 /* Set Mode Masks */ 5502 soc_mem_field32_set(u, mem, lpm_entry, MODE_MASK0_f(u), 5503 (1 << soc_mem_field_length(u, mem, MODE_MASK0_f(u))) - 1); 5504 soc_mem_field32_set(u, mem, lpm_entry, MODE_MASK1_f(u), 5505 (1 << soc_mem_field_length(u, mem, MODE_MASK1_f(u))) - 1); 5506 5507 /* Set Entry Type Masks */ 5508 soc_mem_field32_set(u, mem, lpm_entry, ENTRY_TYPE_MASK0_f(u), 5509 (1 << soc_mem_field_length(u, mem, 5510 ENTRY_TYPE_MASK0_f(u))) - 1); 5511 soc_mem_field32_set(u, mem, lpm_entry, ENTRY_TYPE_MASK1_f(u), 5512 (1 << soc_mem_field_length(u, mem, 5513 ENTRY_TYPE_MASK1_f(u))) - 1); 5514 /* 5515 * Note ipv4 entries are expected to reside in part 0 of the entry. 5516 * ipv6 entries both parts should be filled. 5517 * Hence if entry is ipv6 copy part 0 to part 1 5518 */ 5519 return (SOC_E_NONE); 5520 } 5521 5522 int 5523 _soc_th_alpm_delete_in_bkt(int u, soc_mem_t mem, int phy_bkt, 5524 int bank_disable, void *bufp2, uint32 *e, 5525 int *key_index, int v6) 5526 { 5527 int rv; 5528 5529 rv = soc_mem_alpm_delete(u, mem, phy_bkt, MEM_BLOCK_ALL, 5530 bank_disable, bufp2, e, key_index); 5531 if (SOC_SUCCESS(rv)) { 5532 return rv; 5533 } 5534 if (ALPM_CTRL(u).double_wide[v6]) { 5535 return soc_mem_alpm_delete(u, mem, phy_bkt + 1, 5536 MEM_BLOCK_ALL, bank_disable, bufp2, e, 5537 key_index); 5538 } 5539 return rv; 5540 } 5541 5542 5543 #ifdef CHECK_CLEAN_BKT 5544 static int 5545 _soc_th_alpm_bkt_count(int u, soc_mem_t mem, int is_log_bkt, int bkt, int vrf, void *bufp) 5546 { 5547 int bank_num; 5548 int entry_num; 5549 int bank_count; 5550 int bank_bits; 5551 int alpm_bkt_bits = ALPM_CTRL(u).bkt_bits; 5552 int bkt_count; 5553 int phy_bkt; 5554 int sub_bkt; 5555 int addr; 5556 int rv; 5557 int entry_count; 5558 uint32 bank_disable; 5559 int count = 0; 5560 5561 if (is_log_bkt) { 5562 phy_bkt = ALPM_PHY_BKT(u, bkt); 5563 sub_bkt = ALPM_SUB_BKT(u, bkt); 5564 } else { 5565 phy_bkt = bkt; 5566 sub_bkt = -1; 5567 } 5568 5569 bank_disable = ALPM_CTRL(u).bank_disable_bmp_8b[vrf != (SOC_VRF_MAX(u) + 1)]; 5570 bank_count = ALPM_CTRL(u).num_banks; 5571 bank_bits = ALPM_CTRL(u).bank_bits; 5572 5573 ALPM_FIRST_AVAIL_BANK(bank_num, bank_count, bank_disable); 5574 5575 switch (mem) { 5576 case L3_DEFIP_ALPM_IPV4m: 5577 entry_count = 6; 5578 break; 5579 case L3_DEFIP_ALPM_IPV4_1m: 5580 entry_count = 4; 5581 break; 5582 case L3_DEFIP_ALPM_IPV6_64m: 5583 entry_count = 4; 5584 break; 5585 case L3_DEFIP_ALPM_IPV6_64_1m: 5586 entry_count = 3; 5587 break; 5588 case L3_DEFIP_ALPM_IPV6_128m: 5589 default: 5590 entry_count = 2; 5591 break; 5592 } 5593 bkt_count = _soc_th_alpm_bkt_entry_cnt(u, mem); 5594 entry_num = 0; 5595 while (bkt_count--) { 5596 addr = (entry_num << (bank_bits + alpm_bkt_bits)) | 5597 (phy_bkt << bank_bits) | 5598 (bank_num & ((1U << bank_bits) - 1)); 5599 entry_num++; 5600 if (entry_num == entry_count) { 5601 entry_num = 0; 5602 ALPM_NEXT_AVAIL_BANK(bank_num, bank_count, bank_disable); 5603 if (bank_num == bank_count) { 5604 ALPM_FIRST_AVAIL_BANK(bank_num, bank_count, bank_disable); 5605 phy_bkt ++; 5606 } 5607 } 5608 5609 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, addr, bufp); 5610 SOC_IF_ERROR_RETURN(rv); /* If fail, the rv < 0, and check also fails */ 5611 5612 if (sub_bkt != -1 && sub_bkt != 5613 soc_mem_field32_get(u, mem, bufp, SUB_BKT_PTRf)) { 5614 continue; 5615 } 5616 5617 if (soc_mem_field32_get(u, mem, bufp, VALIDf)) { 5618 LOG_CLI(("mem %s bkt %d vrf %d bank_disable %d bkt_count %d " 5619 "entry_num %d, bank_num %d, addr %d\n", 5620 SOC_MEM_NAME(u, mem), bkt, vrf, bank_disable, bkt_count, 5621 entry_num, bank_num, addr)); 5622 count++; 5623 } 5624 } 5625 5626 return count; 5627 } 5628 #endif /* CHECK_CLEAN_BKT */ 5629 5630 /* 5631 * Delete entry from ALPM database. 5632 * Returns SOC_E_NONE, if found and updated. 5633 * SOC_E_FAIL, if insert failed. 5634 * If default route replace with internal default 5635 */ 5636 static int 5637 _soc_th_alpm_delete(int u, int v6, void *key_data, int log_bkt, 5638 int tcam_index, int key_index) /* TCAM entry data */ 5639 { 5640 alpm_pivot_t *pivot_pyld; 5641 /* Search Result buffer */ 5642 defip_alpm_ipv4_1_entry_t *alpmv4_entry = NULL, *alpmv4_sip_entry = NULL, *alpmv42 = NULL; 5643 defip_alpm_ipv6_64_1_entry_t *alpmv6_entry = NULL, *alpmv6_sip_entry = NULL, *alpmv62 = NULL; 5644 defip_aux_scratch_entry_t *aux_entry = NULL; 5645 uint32 *e = NULL; 5646 soc_mem_t mem; 5647 void *bufp, *bufp2, *sip_bufp = NULL; 5648 int vrf_id; 5649 int rv = SOC_E_NONE, rv2; 5650 uint32 prop_pfx[5], prefix[5], bpm[5]; 5651 int vrf; 5652 uint32 length; 5653 int delete_bucket, delete_phy_bkt; 5654 uint32 db_type, ent_type, bank_disable; 5655 int hit, default_route = 0; 5656 trie_t *trie, *pfx_trie; 5657 uint32 bpm_pfx_len; 5658 defip_entry_t lpm_entry, *lpm_key; 5659 payload_t *payload = NULL, *pfx_pyld = NULL, *tmp_pyld = NULL; 5660 trie_node_t *delp = NULL, *lpmp = NULL; 5661 trie_t *pivot_trie = NULL; 5662 int empty_bucket, aux_flags = 0; 5663 5664 alpmv4_entry = sal_alloc(sizeof(defip_alpm_ipv4_1_entry_t), "alpmv4_entry"); 5665 if (alpmv4_entry == NULL) { 5666 rv = SOC_E_MEMORY; 5667 goto clean_up; 5668 } 5669 5670 alpmv4_sip_entry = sal_alloc(sizeof(defip_alpm_ipv4_1_entry_t), "alpmv4_sip_entry"); 5671 if (alpmv4_sip_entry == NULL) { 5672 rv = SOC_E_MEMORY; 5673 goto clean_up; 5674 } 5675 5676 alpmv42 = sal_alloc(sizeof(defip_alpm_ipv4_1_entry_t), "alpmv42"); 5677 if (alpmv42 == NULL) { 5678 rv = SOC_E_MEMORY; 5679 goto clean_up; 5680 } 5681 5682 alpmv6_entry = sal_alloc(sizeof(defip_alpm_ipv6_64_1_entry_t), "alpmv6_entry"); 5683 if (alpmv6_entry == NULL) { 5684 rv = SOC_E_MEMORY; 5685 goto clean_up; 5686 } 5687 5688 alpmv6_sip_entry = sal_alloc(sizeof(defip_alpm_ipv6_64_1_entry_t), "alpmv6_sip_entry"); 5689 if (alpmv6_sip_entry == NULL) { 5690 rv = SOC_E_MEMORY; 5691 goto clean_up; 5692 } 5693 5694 alpmv62 = sal_alloc(sizeof(defip_alpm_ipv6_64_1_entry_t), "alpmv62"); 5695 if (alpmv62 == NULL) { 5696 rv = SOC_E_MEMORY; 5697 goto clean_up; 5698 } 5699 5700 aux_entry = sal_alloc(sizeof(defip_aux_scratch_entry_t), "aux_entry"); 5701 if (aux_entry == NULL) { 5702 rv = SOC_E_MEMORY; 5703 goto clean_up; 5704 } 5705 5706 e = sal_alloc(sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS, "buf_tmp"); 5707 if (e == NULL) { 5708 rv = SOC_E_MEMORY; 5709 goto clean_up; 5710 } 5711 5712 SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf)); 5713 5714 /* For VRF_OVERRIDE (Global High) entries, software needs to maintain the 5715 * index, Prefix resides in TCAM directly. Handling of these functions are 5716 * taken care by main insert */ 5717 if (!(ALPM_PREFIX_IN_TCAM(u, vrf_id))) { 5718 bank_disable = ALPM_CTRL(u).bank_disable_bmp[vrf != SOC_VRF_MAX(u) + 1]; 5719 soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type); 5720 /* Create Prefix */ 5721 rv = _soc_th_alpm_prefix_create(u, v6, key_data, prefix, &length, 5722 &default_route); 5723 if (SOC_FAILURE(rv)) { 5724 LOG_ERROR(BSL_LS_SOC_ALPM, 5725 (BSL_META_U(u, 5726 "_soc_alpm_delete: prefix create failed\n"))); 5727 goto clean_up; 5728 } 5729 if (ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_COMBINED) { 5730 if (vrf_id != SOC_L3_VRF_GLOBAL) { 5731 /* allow default deletion only at end */ 5732 if (VRF_TRIE_ROUTES_CNT(u, vrf_id, vrf, v6) > 1) { 5733 if (default_route) { 5734 LOG_ERROR(BSL_LS_SOC_ALPM, 5735 (BSL_META_U(u, 5736 "VRF %d: Cannot delete default " 5737 "route if other routes are present in " 5738 "this mode\n"), vrf)); 5739 rv = SOC_E_PARAM; 5740 goto clean_up; 5741 } 5742 } 5743 } 5744 } 5745 5746 /* Get table memory. */ 5747 SOC_ALPM_TABLE_MEM(u, v6, mem, VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 0)); 5748 5749 /* Assign entry buf based on table being used */ 5750 SOC_ALPM_ENTRY_BUF(v6, mem, bufp, *alpmv4_entry, *alpmv6_entry); 5751 SOC_ALPM_ENTRY_BUF(v6, mem, bufp2, *alpmv42, *alpmv62); 5752 5753 SOC_ALPM_LPM_LOCK(u); 5754 5755 if (log_bkt == 0) { 5756 /* Search the entry */ 5757 rv = _soc_th_alpm_find(u, mem, v6, key_data, vrf_id, vrf, bufp, 5758 &tcam_index, &log_bkt, &key_index, TRUE); 5759 } else { 5760 /* key_data has all the info including search result */ 5761 rv = _soc_th_alpm_mem_ent_init(u, v6, key_data, bufp, 0, mem, 5762 0, 0, log_bkt); 5763 } 5764 5765 /* save results as they are lost later */ 5766 sal_memcpy(bufp2, bufp, v6 ? sizeof(defip_alpm_ipv6_64_1_entry_t) : 5767 sizeof(defip_alpm_ipv4_1_entry_t)); 5768 5769 if (SOC_FAILURE(rv)) { 5770 SOC_ALPM_LPM_UNLOCK(u); 5771 LOG_ERROR(BSL_LS_SOC_ALPM, 5772 (BSL_META_U(u, 5773 "_soc_alpm_delete: Unable to find prefix for delete\n"))); 5774 goto clean_up; 5775 } 5776 5777 /* Entry found 5778 * 1> Delete entry from trie 5779 * 2> Find Best Prefix Match 5780 * 3> Update bpm using replacement prefix op 5781 * 4> Invalidate Entry in the ALPM database 5782 */ 5783 /* Delete the prefix from trie*/ 5784 /* Store index to invalidate the prefix */ 5785 delete_bucket = log_bkt; 5786 5787 pivot_pyld = ALPM_TCAM_PIVOT(u, tcam_index); 5788 trie = PIVOT_BUCKET_TRIE(pivot_pyld); 5789 5790 rv = trie_delete(trie, prefix, length, &delp); 5791 payload = (payload_t *) delp; 5792 if (rv != SOC_E_NONE) { 5793 LOG_ERROR(BSL_LS_SOC_ALPM, 5794 (BSL_META_U(u, 5795 "_soc_alpm_delete: Error prefix not present in trie \n"))); 5796 SOC_ALPM_LPM_UNLOCK(u); 5797 goto clean_up; 5798 } 5799 5800 /* prefix trie delete */ 5801 if (v6) { 5802 pfx_trie = VRF_PREFIX_TRIE_IPV6(u, vrf); 5803 } else { 5804 pfx_trie = VRF_PREFIX_TRIE_IPV4(u, vrf); 5805 } 5806 5807 if (v6) { 5808 pivot_trie = VRF_PIVOT_TRIE_IPV6(u, vrf); 5809 } else { 5810 pivot_trie = VRF_PIVOT_TRIE_IPV4(u, vrf); 5811 } 5812 5813 if (!default_route) { 5814 rv = trie_delete(pfx_trie, prefix, length, &delp); 5815 pfx_pyld = (payload_t *) delp; 5816 if (SOC_FAILURE(rv)) { 5817 /* continue anyway to minimize state mismatch */ 5818 LOG_ERROR(BSL_LS_SOC_ALPM, 5819 (BSL_META_U(u, 5820 "_soc_alpm_delete: Prefix not present in pfx" 5821 "trie: 0x%08x 0x%08x\n"), 5822 prefix[0], prefix[1])); 5823 goto recover_bkt_trie; 5824 } 5825 5826 /* Find Best prefix match for the prefix */ 5827 lpmp = NULL; 5828 rv = trie_find_lpm(pfx_trie, prefix, length, &lpmp); 5829 tmp_pyld = (payload_t *) lpmp; 5830 if (SOC_SUCCESS(rv)) { 5831 payload_t *t = (payload_t *)(tmp_pyld->bkt_ptr); 5832 if (t != NULL) { 5833 /* this means a real default route exists */ 5834 bpm_pfx_len = t->len; 5835 } else { 5836 /* only internal default route exists */ 5837 /* this should happen only if the lpm is a default route */ 5838 bpm_pfx_len = 0; 5839 } 5840 } else { 5841 LOG_ERROR(BSL_LS_SOC_ALPM, 5842 (BSL_META_U(u, 5843 "_soc_alpm_delete: Could not find replacement" 5844 "bpm for prefix: 0x%08x 0x%08x\n"), 5845 prefix[0], prefix[1])); 5846 goto recover_pfx_trie; 5847 } 5848 5849 /* Initialize an lpm enty to perform a match */ 5850 /* not expected to fail */ 5851 sal_memcpy(prop_pfx, prefix, sizeof(prefix)); 5852 ALPM_TRIE_TO_NORMAL_IP(prop_pfx, length, v6); 5853 rv = _soc_th_alpm_lpm_ent_key_init(u, prop_pfx, bpm_pfx_len, vrf, v6, 5854 &lpm_entry, 1); 5855 5856 /* Find Associated data for the bpm */ 5857 rv2 = _soc_th_alpm_find(u, mem, v6, &lpm_entry, vrf_id, vrf, bufp, 5858 &tcam_index, &log_bkt, &key_index, TRUE); 5859 if (rv2) { 5860 if (vrf_id != SOC_L3_VRF_GLOBAL && 5861 ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_COMBINED) { 5862 soc_mem_entry_dump_if_changed(u, L3_DEFIPm, &lpm_entry, "ALPM-DBG: "); 5863 LOG_ERROR(BSL_LS_SOC_ALPM, 5864 (BSL_META_U(u, 5865 "Find associated data for next bpm failed." 5866 "prefix: 0x%08x 0x%08x, length %d\n"), 5867 prop_pfx[0], prop_pfx[1], bpm_pfx_len)); 5868 } else { 5869 key_index = 0; 5870 } 5871 } 5872 5873 /* convert associated data to lpm entry format */ 5874 (void) _soc_th_alpm_lpm_ent_init(u, bufp, mem, v6, vrf_id, 5875 log_bkt, 0, &lpm_entry, 0); 5876 5877 /* set key to the prefix being deleted */ 5878 (void) _soc_th_alpm_lpm_ent_key_init(u, prop_pfx, length, vrf, v6, 5879 &lpm_entry, 0); 5880 if (SOC_URPF_STATUS_GET(u)) { 5881 SOC_ALPM_ENTRY_BUF(v6, mem, sip_bufp, *alpmv4_sip_entry, 5882 *alpmv6_sip_entry); 5883 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, 5884 _soc_th_alpm_rpf_entry(u, key_index), sip_bufp); 5885 5886 if (soc_mem_field32_get(u, mem, sip_bufp, DEFAULTROUTEf)) { 5887 aux_flags |= SOC_ALPM_AUX_DEF_ROUTE; 5888 } 5889 if (soc_mem_field32_get(u, mem, sip_bufp, SRC_DISCARDf)) { 5890 aux_flags |= SOC_ALPM_AUX_SRC_DISCARD; 5891 } 5892 } 5893 5894 if ((bpm_pfx_len == 0) && SOC_FAILURE(rv2)) { 5895 /* could not find a default route. Use internal default */ 5896 /* default route's associated data */ 5897 lpm_key = v6 ? VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) : 5898 VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf); 5899 sal_memcpy(&lpm_entry, lpm_key, sizeof(lpm_entry)); 5900 /* copy key info over again */ 5901 rv = _soc_th_alpm_lpm_ent_key_init(u, prop_pfx, length, vrf, v6, 5902 &lpm_entry, 0); 5903 } 5904 5905 if (SOC_FAILURE(rv)) { 5906 LOG_ERROR(BSL_LS_SOC_ALPM, 5907 (BSL_META_U(u, 5908 "_soc_alpm_delete: Could not find replacement" 5909 " prefix for prefix: 0x%08x 0x%08x\n"), 5910 prefix[0], prefix[1])); 5911 goto recover_pfx_trie; 5912 } 5913 5914 lpm_key = &lpm_entry; 5915 } else { /* !default_route */ 5916 /* remove the real default route reference if any */ 5917 5918 lpmp = NULL; 5919 rv = trie_find_lpm(pfx_trie, prefix, length, &lpmp); 5920 tmp_pyld = (payload_t *) lpmp; 5921 if (SOC_FAILURE(rv)) { 5922 LOG_ERROR(BSL_LS_SOC_ALPM, 5923 (BSL_META_U(u, 5924 "_soc_alpm_delete: Could not find default " 5925 "route in the trie for vrf %d\n"), vrf)); 5926 goto recover_bkt_trie; 5927 } 5928 tmp_pyld->bkt_ptr = NULL; 5929 bpm_pfx_len = 0; 5930 lpm_key = v6 ? VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) : 5931 VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf); 5932 key_index = 0; 5933 } 5934 rv = _soc_th_alpm_fill_aux_entry_for_op(u, lpm_key, v6, db_type, 5935 ent_type, bpm_pfx_len, aux_entry); 5936 if (SOC_FAILURE(rv)) { 5937 goto recover_pfx_trie; 5938 } 5939 5940 /* Perform Delete propagate */ 5941 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, ALG_HIT_IDXf, 5942 ALPM_ENT_INDEX(key_index)); 5943 rv = _soc_th_alpm_aux_op(u, DELETE_PROPAGATE, aux_entry, TRUE, &hit, 5944 &tcam_index, &log_bkt, aux_flags); 5945 if (SOC_FAILURE(rv)) { 5946 goto recover_pfx_trie; 5947 } 5948 5949 /* perform SIP delete propagate */ 5950 if (0) { 5951 uint32 tmp; 5952 /* only SRC bits are different from DIP entry. Copy them over if 5953 internal default is not being used */ 5954 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, 5955 DB_TYPEf, db_type + 1); 5956 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, 5957 ALG_HIT_IDXf, _soc_th_alpm_rpf_entry(u, 5958 ALPM_ENT_INDEX(key_index))); 5959 tmp = soc_mem_field32_get(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, 5960 IP_LENGTHf); 5961 soc_mem_field32_set(u, mem, aux_entry, DEFAULTROUTEf, 5962 tmp == 0 ? 1 : 0); 5963 5964 rv = _soc_th_alpm_aux_op(u, DELETE_PROPAGATE, aux_entry, TRUE, 5965 &hit, &tcam_index, &log_bkt, 0); 5966 if (SOC_FAILURE(rv)) { 5967 goto recover_pfx_trie; 5968 } 5969 } 5970 5971 /* From here on don't trie to recover trie state */ 5972 sal_free(payload); 5973 if (!default_route) { 5974 sal_free(pfx_pyld); 5975 } 5976 5977 /* For debug, update the pivot's counter */ 5978 PIVOT_BUCKET_ENT_CNT_UPDATE(pivot_pyld); 5979 5980 empty_bucket = (pivot_pyld->len != 0) && (trie->trie == NULL); 5981 if (empty_bucket) { /* Empty bucket */ 5982 uint32 hw_key[5]; 5983 sal_memcpy(hw_key, pivot_pyld->key, sizeof(hw_key)); 5984 ALPM_TRIE_TO_NORMAL_IP(hw_key, pivot_pyld->len, v6); 5985 5986 /* Initialize an lpm entry to perform a match */ 5987 _soc_th_alpm_lpm_ent_key_init(u, hw_key, pivot_pyld->len, 5988 vrf, v6, &lpm_entry, 1); 5989 5990 /* delete entry from TCAM */ 5991 rv = soc_th_alpm_lpm_delete(u, &lpm_entry); 5992 if (SOC_FAILURE(rv)) { 5993 LOG_ERROR(BSL_LS_SOC_ALPM, 5994 (BSL_META_U(u, 5995 "_soc_alpm_delete: Unable to " 5996 "delete pivot 0x%08x 0x%08x \n"), 5997 pivot_pyld->key[0], pivot_pyld->key[1])); 5998 /* continue to clean up still */ 5999 } 6000 } 6001 6002 /* Invalidate the route */ 6003 delete_phy_bkt = ALPM_PHY_BKT(u, delete_bucket); 6004 rv = _soc_th_alpm_delete_in_bkt(u, mem, delete_phy_bkt, bank_disable, 6005 bufp2, e, &key_index, v6); 6006 if (SOC_FAILURE(rv)) { 6007 LOG_ERROR(BSL_LS_SOC_ALPM, 6008 (BSL_META_U(u, 6009 "_soc_th_alpm_delete_in_bkt: Unable to " 6010 "delete phy bkt 0x%08x \n"), delete_phy_bkt)); 6011 SOC_ALPM_LPM_UNLOCK(u); 6012 goto clean_up; 6013 } 6014 6015 /* delete corresponding RPF entry if it exists */ 6016 if (SOC_URPF_STATUS_GET(u)) { 6017 /* hit is an unused variable */ 6018 delete_phy_bkt = SOC_TH_ALPM_RPF_BKT_IDX(u, delete_phy_bkt); 6019 rv = _soc_th_alpm_delete_in_bkt(u, mem, delete_phy_bkt, bank_disable, 6020 bufp2, e, &hit, v6); 6021 if (SOC_FAILURE(rv)) { 6022 LOG_ERROR(BSL_LS_SOC_ALPM, 6023 (BSL_META_U(u, 6024 "_soc_th_alpm_delete_in_bkt: Unable to " 6025 "delete phy bkt 0x%08x \n"), delete_phy_bkt)); 6026 SOC_ALPM_LPM_UNLOCK(u); 6027 goto clean_up; 6028 } 6029 } 6030 6031 /* Update usage stat */ 6032 soc_th_alpm_bucket_usage_decr(u, PIVOT_BUCKET_INDEX(pivot_pyld), empty_bucket, vrf, mem, 1, 0); 6033 if (empty_bucket) { /* Empty bucket */ 6034 6035 /* remove pivot from pivot trie */ 6036 rv = trie_delete(pivot_trie, pivot_pyld->key, pivot_pyld->len, &delp); 6037 if (SOC_FAILURE(rv)) { 6038 LOG_ERROR(BSL_LS_SOC_ALPM, 6039 (BSL_META_U(u, 6040 "could not delete pivot from pivot trie\n"))); 6041 } 6042 6043 /* Free up Bucket trie */ 6044 trie_destroy(PIVOT_BUCKET_TRIE(pivot_pyld)); 6045 6046 /* Free up Bucket handle */ 6047 sal_free(PIVOT_BUCKET_HANDLE(pivot_pyld)); 6048 6049 /* free Pivot structure */ 6050 sal_free(pivot_pyld); 6051 6052 #ifdef CHECK_CLEAN_BKT 6053 /* make sure bucket is indeed empty */ 6054 assert(_soc_th_alpm_bkt_count(u, mem, 1, delete_bucket, vrf, 6055 bufp) == 0); 6056 #endif /* CHECK_CLEAN_BKT */ 6057 } 6058 } 6059 6060 VRF_TRIE_ROUTES_DEC(u, vrf_id, vrf, v6); 6061 if (VRF_TRIE_ROUTES_CNT(u, vrf_id, vrf, v6) == 0) { 6062 /* vrf is empty. Release resources */ 6063 rv = soc_th_alpm_vrf_delete(u, vrf, v6); 6064 } 6065 SOC_ALPM_LPM_UNLOCK(u); 6066 goto clean_up; 6067 6068 /* Recovery from error: */ 6069 /* add back pivot bucket trie entry */ 6070 /* add back prefix trie entry */ 6071 recover_pfx_trie: 6072 LOG_ERROR(BSL_LS_SOC_ALPM, 6073 (BSL_META_U(u, 6074 "recovering soc_th_alpm_vrf_delete failed\n "))); 6075 6076 _soc_th_alpm_mask_prefix_create(u, v6, length, bpm); 6077 rv2 = trie_insert(pfx_trie, prefix, 6078 ALPM_CTRL(u).trie_propagate ? bpm : NULL, 6079 length, (trie_node_t *)pfx_pyld); 6080 if (SOC_FAILURE(rv2)) { 6081 LOG_ERROR(BSL_LS_SOC_ALPM, 6082 (BSL_META_U(u, 6083 "_soc_alpm_delete: Unable to reinsert" 6084 "prefix 0x%08x 0x%08x into pfx trie\n"), 6085 prefix[0], prefix[1])); 6086 } 6087 recover_bkt_trie: 6088 rv2 = trie_insert(trie, prefix, NULL, length, (trie_node_t *) payload); 6089 if (SOC_FAILURE(rv2)) { 6090 LOG_ERROR(BSL_LS_SOC_ALPM, 6091 (BSL_META_U(u, 6092 "_soc_alpm_delete: Unable to reinsert" 6093 "prefix 0x%08x 0x%08x into bkt trie\n"), 6094 prefix[0], prefix[1])); 6095 } 6096 SOC_ALPM_LPM_UNLOCK(u); 6097 clean_up: 6098 if (alpmv4_entry) { 6099 sal_free(alpmv4_entry); 6100 } 6101 if (alpmv4_sip_entry) { 6102 sal_free(alpmv4_sip_entry); 6103 } 6104 if (alpmv42) { 6105 sal_free(alpmv42); 6106 } 6107 if (alpmv6_entry) { 6108 sal_free(alpmv6_entry); 6109 } 6110 if (alpmv6_sip_entry) { 6111 sal_free(alpmv6_sip_entry); 6112 } 6113 if (alpmv62) { 6114 sal_free(alpmv62); 6115 } 6116 if (aux_entry) { 6117 sal_free(aux_entry); 6118 } 6119 if (e) { 6120 sal_free(e); 6121 } 6122 return rv; 6123 } 6124 6125 void 6126 soc_th_alpm_mem_free(int u) 6127 { 6128 int i, j; 6129 if (alpm_vrf_handle[u] != NULL) { 6130 sal_free(alpm_vrf_handle[u]); 6131 alpm_vrf_handle[u] = NULL; 6132 } 6133 if (tcam_pivot[u] != NULL) { 6134 sal_free(tcam_pivot[u]); 6135 tcam_pivot[u] = NULL; 6136 } 6137 if (bkt_usage[u] != NULL) { 6138 sal_free(bkt_usage[u]); 6139 bkt_usage[u] = NULL; 6140 } 6141 for (i = 0; i < SOC_TH_MAX_ALPM_VIEWS; i++) { 6142 if (global_bkt_usage[u][i] != NULL) { 6143 for (j = 0; j < SOC_TH_MAX_BUCKET_ENTRIES(u); j++) { 6144 if (global_bkt_usage[u][i][j].bkt_bmp != NULL) { 6145 sal_free(global_bkt_usage[u][i][j].bkt_bmp); 6146 global_bkt_usage[u][i][j].bkt_bmp = NULL; 6147 } 6148 } 6149 sal_free(global_bkt_usage[u][i]); 6150 global_bkt_usage[u][i] = NULL; 6151 } 6152 } 6153 } 6154 6155 /* Initialize ALPM Subsytem */ 6156 int 6157 soc_th_alpm_init(int u) 6158 { 6159 int i, j; 6160 int rv = SOC_E_NONE; 6161 uint32 sz, sz2; 6162 6163 if (SOC_ALPM_LPM_INIT_CHECK(u)) { 6164 /* this is a reinit. clean up old state */ 6165 if (soc_th_alpm_deinit(u) < 0) { 6166 return SOC_E_INTERNAL; 6167 } 6168 } 6169 6170 rv = _soc_th_alpm_ctrl_init(u); 6171 SOC_IF_ERROR_RETURN(rv); 6172 6173 /* Initialize TCAM Memory management */ 6174 rv = soc_th_alpm_lpm_init(u); 6175 SOC_IF_ERROR_RETURN(rv); 6176 6177 /* Initialize ALPM memory management */ 6178 rv = soc_th_alpm_shared_mem_init(u); 6179 6180 soc_th_alpm_mem_free(u); 6181 alpm_vrf_handle[u] = sal_alloc((MAX_VRF_ID + 1) * sizeof(alpm_vrf_handle_t), "ALPM VRF Handles"); 6182 if (alpm_vrf_handle[u] == NULL) { 6183 rv = SOC_E_MEMORY; 6184 goto _free_exit; 6185 } 6186 6187 tcam_pivot[u] = sal_alloc(TH_MAX_PIVOT_COUNT(u) * sizeof(alpm_pivot_t *), "ALPM pivots"); 6188 if (tcam_pivot[u] == NULL) { 6189 rv = SOC_E_MEMORY; 6190 goto _free_exit; 6191 } 6192 sal_memset(alpm_vrf_handle[u], 0, (MAX_VRF_ID + 1) * sizeof(alpm_vrf_handle_t)); 6193 sal_memset(tcam_pivot[u], 0, TH_MAX_PIVOT_COUNT(u) * sizeof(alpm_pivot_t *)); 6194 6195 /* Bucket sharing structure */ 6196 sz = ALPM_CTRL(u).num_bkts * sizeof(alpm_bkt_usg_t); 6197 bkt_usage[u] = sal_alloc(sz, "ALPM_BS"); 6198 if (bkt_usage[u] == NULL) { 6199 rv = SOC_E_MEMORY; 6200 goto _free_exit; 6201 } 6202 sal_memset(bkt_usage[u], 0, sz); 6203 6204 sz = SOC_TH_MAX_BUCKET_ENTRIES(u) * sizeof(alpm_bkt_bmp_t); 6205 sz2 = SHR_BITALLOCSIZE(ALPM_CTRL(u).num_bkts); 6206 for (i = 0; i < SOC_TH_MAX_ALPM_VIEWS; i++) { 6207 global_bkt_usage[u][i] = sal_alloc(sz, "ALPM_BS"); 6208 if (global_bkt_usage[u][i] == NULL) { 6209 rv = SOC_E_MEMORY; 6210 goto _free_exit; 6211 } 6212 sal_memset(global_bkt_usage[u][i], 0, sz); 6213 6214 for (j = 0; j < SOC_TH_MAX_BUCKET_ENTRIES(u); j++) { 6215 global_bkt_usage[u][i][j].bkt_bmp = sal_alloc(sz2, "ALPM BS bkt_bmp"); 6216 if (global_bkt_usage[u][i][j].bkt_bmp == NULL) { 6217 rv = SOC_E_MEMORY; 6218 goto _free_exit; 6219 } 6220 sal_memset(global_bkt_usage[u][i][j].bkt_bmp, 0, sz2); 6221 } 6222 } 6223 6224 sal_memset(&_alpm_dbg_cntr[u], 0, sizeof(_alpm_int_dbg_cnt_t)); 6225 6226 /* Initialize PIVOT management */ 6227 for (i = 0; i < TH_MAX_PIVOT_COUNT(u); i++) { 6228 ALPM_TCAM_PIVOT(u, i) = NULL; 6229 } 6230 6231 if (SOC_CONTROL(u)->alpm_bulk_retry == NULL) { 6232 SOC_CONTROL(u)->alpm_bulk_retry = 6233 sal_sem_create("ALPM bulk retry", sal_sem_BINARY, 0); 6234 } 6235 if (SOC_CONTROL(u)->alpm_lookup_retry == NULL) { 6236 SOC_CONTROL(u)->alpm_lookup_retry = 6237 sal_sem_create("ALPM lookup retry", sal_sem_BINARY, 0); 6238 } 6239 if (SOC_CONTROL(u)->alpm_insert_retry == NULL) { 6240 SOC_CONTROL(u)->alpm_insert_retry = 6241 sal_sem_create("ALPM insert retry", sal_sem_BINARY, 0); 6242 } 6243 if (SOC_CONTROL(u)->alpm_delete_retry == NULL) { 6244 SOC_CONTROL(u)->alpm_delete_retry = 6245 sal_sem_create("ALPM delete retry", sal_sem_BINARY, 0); 6246 } 6247 6248 rv = soc_th_alpm_128_lpm_init(u); 6249 if (SOC_FAILURE(rv)) { 6250 goto _free_exit; 6251 } 6252 return rv; 6253 6254 _free_exit: 6255 soc_th_alpm_mem_free(u); 6256 return rv; 6257 } 6258 6259 /* clear alpm related internal state */ 6260 static int soc_th_alpm_state_clear(int u) 6261 { 6262 int i, rv; 6263 alpm_pivot_t *tmp; 6264 uint8 ipv; 6265 6266 /* clear all pivot state */ 6267 for (i = 0; i < TH_MAX_PIVOT_COUNT(u); i++) { 6268 tmp = ALPM_TCAM_PIVOT(u, i); 6269 if (tmp) { 6270 if (PIVOT_BUCKET_HANDLE(tmp)) { 6271 if (PIVOT_BUCKET_TRIE(tmp)) { 6272 /* traverse bucket trie and clear it */ 6273 rv = trie_traverse(PIVOT_BUCKET_TRIE(tmp), 6274 alpm_delete_node_cb, NULL, _TRIE_INORDER_TRAVERSE); 6275 if (SOC_SUCCESS(rv)) { 6276 trie_destroy(PIVOT_BUCKET_TRIE(tmp)); 6277 } else { 6278 LOG_ERROR(BSL_LS_SOC_ALPM, 6279 (BSL_META_U(u, 6280 "Unable to clear trie state for unit %d\n"), 6281 u)); 6282 6283 return rv; 6284 } 6285 } 6286 sal_free(PIVOT_BUCKET_HANDLE(tmp)); 6287 } 6288 sal_free(ALPM_TCAM_PIVOT(u, i)); 6289 ALPM_TCAM_PIVOT(u, i) = NULL; 6290 } 6291 } 6292 6293 /* clear all prefix tries */ 6294 for (i = 0; i <= SOC_VRF_MAX(u) + 1; i++) { 6295 rv = trie_traverse(VRF_PREFIX_TRIE_IPV4(u, i), alpm_delete_node_cb, 6296 NULL, _TRIE_INORDER_TRAVERSE); 6297 if (SOC_SUCCESS(rv)) { 6298 trie_destroy(VRF_PREFIX_TRIE_IPV4(u, i)); 6299 } else { 6300 LOG_ERROR(BSL_LS_SOC_ALPM, 6301 (BSL_META_U(u, 6302 "unit: %d Unable to clear v4 pfx trie for vrf %d\n"), 6303 u, i)); 6304 return rv; 6305 } 6306 rv = trie_traverse(VRF_PREFIX_TRIE_IPV6(u, i), alpm_delete_node_cb, 6307 NULL, _TRIE_INORDER_TRAVERSE); 6308 if (SOC_SUCCESS(rv)) { 6309 trie_destroy(VRF_PREFIX_TRIE_IPV6(u, i)); 6310 } else { 6311 LOG_ERROR(BSL_LS_SOC_ALPM, 6312 (BSL_META_U(u, 6313 "unit: %d Unable to clear v4 pfx trie for vrf %d\n"), 6314 u, i)); 6315 return rv; 6316 } 6317 if (VRF_TRIE_DEFAULT_ROUTE_IPV4(u, i) != NULL) { 6318 sal_free(VRF_TRIE_DEFAULT_ROUTE_IPV4(u, i)); 6319 } 6320 if (VRF_TRIE_DEFAULT_ROUTE_IPV6(u, i) != NULL) { 6321 sal_free(VRF_TRIE_DEFAULT_ROUTE_IPV6(u, i)); 6322 } 6323 sal_memset(&alpm_vrf_handle[u][i], 0, sizeof(alpm_vrf_handle_t)); 6324 } 6325 6326 /* Reset VRF_OVERRIDE debug counter */ 6327 sal_memset(&alpm_vrf_handle[u][MAX_VRF_ID], 0, sizeof(alpm_vrf_handle_t)); 6328 /* Mark Global Hi (VRF_OVERRIDE) for IPv4, IPv6-64, IPv6-128 inited for debug usage */ 6329 VRF_TRIE_INIT_DONE(u, MAX_VRF_ID, 0, 1); 6330 VRF_TRIE_INIT_DONE(u, MAX_VRF_ID, 1, 1); 6331 VRF_TRIE_INIT_DONE(u, MAX_VRF_ID, 2, 1); 6332 6333 for (ipv = ALPM_IPV4; ipv < ALPM_IPVERS; ipv++) { 6334 if (ipv == ALPM_IPV6 && !ALPM_CTRL(u)._alpm_128b_bkt_rsvd) { 6335 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv) = NULL; 6336 SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv) = NULL; 6337 break; 6338 } 6339 if (SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv) != NULL) { 6340 if (SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv) != 6341 SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv)) { 6342 sal_free(SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv)); 6343 } 6344 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv) = NULL; 6345 sal_free(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv)); 6346 SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv) = NULL; 6347 } 6348 } 6349 sal_memset(&soc_th_alpm_bucket[u], 0, sizeof(soc_alpm_bucket_t)); 6350 sal_memset(&_alpm_dbg_cntr[u], 0, sizeof(_alpm_int_dbg_cnt_t)); 6351 6352 /* Free memory allocated for VRF handles and tcam pivots */ 6353 soc_th_alpm_mem_free(u); 6354 6355 return SOC_E_NONE; 6356 } 6357 6358 /* De-Init ALPM Subsytem */ 6359 int 6360 soc_th_alpm_deinit(int u) 6361 { 6362 soc_th_alpm_lpm_deinit(u); 6363 6364 SOC_IF_ERROR_RETURN(soc_th_alpm_128_lpm_deinit(u)); 6365 6366 SOC_IF_ERROR_RETURN(soc_th_alpm_128_state_clear(u)); 6367 6368 SOC_IF_ERROR_RETURN(soc_th_alpm_state_clear(u)); 6369 6370 if (SOC_CONTROL(u)->alpm_bulk_retry) { 6371 sal_sem_destroy(SOC_CONTROL(u)->alpm_bulk_retry); 6372 SOC_CONTROL(u)->alpm_bulk_retry = NULL; 6373 } 6374 if (SOC_CONTROL(u)->alpm_lookup_retry) { 6375 sal_sem_destroy(SOC_CONTROL(u)->alpm_lookup_retry); 6376 SOC_CONTROL(u)->alpm_lookup_retry = NULL; 6377 } 6378 if (SOC_CONTROL(u)->alpm_insert_retry) { 6379 sal_sem_destroy(SOC_CONTROL(u)->alpm_insert_retry); 6380 SOC_CONTROL(u)->alpm_insert_retry = NULL; 6381 } 6382 if (SOC_CONTROL(u)->alpm_delete_retry) { 6383 sal_sem_destroy(SOC_CONTROL(u)->alpm_delete_retry); 6384 SOC_CONTROL(u)->alpm_delete_retry = NULL; 6385 } 6386 return SOC_E_NONE; 6387 } 6388 6389 /* 6390 * soc_th_alpm_vrf_add 6391 * Add a VRF default route when a L3 VRF is added 6392 * Adds a 0.0 entry into VRF 6393 */ 6394 static int 6395 soc_th_alpm_vrf_add(int u, int vrf, int v6) 6396 { 6397 defip_entry_t *lpm_entry = NULL, tmp_lpm; 6398 int log_bkt = 0; 6399 int index; 6400 int rv = SOC_E_NONE; 6401 uint32 key[5] = {0}; 6402 uint32 length; 6403 alpm_bucket_handle_t *bucket_handle = NULL; 6404 alpm_pivot_t *pivot_pyld = NULL; 6405 payload_t *pfx_pyld = NULL; 6406 trie_t *root = NULL; 6407 trie_t *pivot_root = NULL; 6408 trie_t *bucket_root = NULL; 6409 soc_mem_t mem; 6410 6411 if (v6 == 0) { 6412 trie_init(_MAX_KEY_LEN_48_, &VRF_PIVOT_TRIE_IPV4(u, vrf)); 6413 pivot_root = VRF_PIVOT_TRIE_IPV4(u, vrf); 6414 } else { 6415 trie_init(_MAX_KEY_LEN_144_, &VRF_PIVOT_TRIE_IPV6(u, vrf)); 6416 pivot_root = VRF_PIVOT_TRIE_IPV6(u, vrf); 6417 } 6418 6419 /* Initialize VRF PIVOT IPV4 trie */ 6420 if (v6 == 0) { 6421 trie_init(_MAX_KEY_LEN_48_, &VRF_PREFIX_TRIE_IPV4(u, vrf)); 6422 root = VRF_PREFIX_TRIE_IPV4(u, vrf); 6423 } else { 6424 trie_init(_MAX_KEY_LEN_144_, &VRF_PREFIX_TRIE_IPV6(u, vrf)); 6425 root = VRF_PREFIX_TRIE_IPV6(u, vrf); 6426 } 6427 6428 lpm_entry = sal_alloc(sizeof(defip_entry_t), "Default LPM entry"); 6429 if (lpm_entry == NULL) { 6430 LOG_ERROR(BSL_LS_SOC_ALPM, 6431 (BSL_META_U(u, 6432 "soc_alpm_vrf_add: unable to allocate memory for " 6433 "IPv4 LPM entry\n"))); 6434 return SOC_E_MEMORY; 6435 } 6436 6437 /* Initialize an lpm entry to perform a match */ 6438 _soc_th_alpm_lpm_ent_key_init(u, key, 0, vrf, v6, lpm_entry, 1); 6439 6440 if (v6 == 0) { 6441 VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf) = lpm_entry; 6442 } else { 6443 VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) = lpm_entry; 6444 } 6445 6446 /* for global VRF */ 6447 if (vrf == SOC_VRF_MAX(u) + 1) { 6448 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f, 1); 6449 } else { 6450 /* Set default miss to global route only for non global routes */ 6451 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, DEFAULT_MISS0f, 1); 6452 } 6453 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ENTRY_VIEW0f, 6454 _soc_th_alpm_lpm_entry_view_get(u, v6, 6455 VRF_FLEX_IS_SET(u, vrf, vrf, v6, 1))); 6456 6457 SOC_ALPM_TABLE_MEM(u, v6, mem, VRF_FLEX_IS_SET(u, vrf, vrf, v6, 1)); 6458 rv = soc_th_alpm_assign(u, vrf, mem, &log_bkt, NULL, NULL); 6459 if (SOC_FAILURE(rv)) { 6460 goto _err_exit; 6461 } 6462 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ALG_BKT_PTR0f, 6463 ALPM_PHY_BKT(u, log_bkt)); 6464 if (ALPM_CTRL(u).bkt_sharing) { 6465 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ALG_SUB_BKT_PTR0f, 6466 ALPM_SUB_BKT(u, log_bkt)); 6467 } 6468 6469 /* add Entry into tcam as default routes for the VRF */ 6470 /* urpf could modify the lpm entry. So use tmp one */ 6471 sal_memcpy(&tmp_lpm, lpm_entry, sizeof(tmp_lpm)); 6472 rv = soc_th_alpm_lpm_insert(u, &tmp_lpm, &index, INVALID_BPM_LEN, 0, 0); 6473 if (SOC_FAILURE(rv)) { 6474 goto _err_exit; 6475 } 6476 6477 /* Insert Pivot into the pivot tries */ 6478 bucket_handle = sal_alloc(sizeof(alpm_bucket_handle_t), "ALPM Bucket Handle"); 6479 if (bucket_handle == NULL) { 6480 LOG_ERROR(BSL_LS_SOC_ALPM, 6481 (BSL_META_U(u, 6482 "soc_th_alpm_vrf_add: Unable to allocate memory for " 6483 "PIVOT trie node \n"))); 6484 rv = SOC_E_MEMORY; 6485 goto _err_exit; 6486 } 6487 sal_memset(bucket_handle, 0, sizeof(*bucket_handle)); 6488 6489 /* Allocate PIVOT Payload */ 6490 pivot_pyld = sal_alloc(sizeof(alpm_pivot_t), "Payload for Pivot"); 6491 if (pivot_pyld == NULL) { 6492 LOG_ERROR(BSL_LS_SOC_ALPM, 6493 (BSL_META_U(u, 6494 "soc_alpm_vrf_add: Unable to allocate memory for " 6495 "PIVOT trie node \n"))); 6496 rv = SOC_E_MEMORY; 6497 goto _err_exit; 6498 } 6499 6500 pfx_pyld = sal_alloc(sizeof(payload_t), "Payload for pfx trie key"); 6501 if (pfx_pyld == NULL) { 6502 LOG_ERROR(BSL_LS_SOC_ALPM, 6503 (BSL_META_U(u, 6504 "soc_alpm_vrf_add: Unable to allocate memory for " 6505 "pfx trie node \n"))); 6506 rv = SOC_E_MEMORY; 6507 goto _err_exit; 6508 } 6509 sal_memset(pivot_pyld, 0, sizeof(*pivot_pyld)); 6510 sal_memset(pfx_pyld, 0, sizeof(*pfx_pyld)); 6511 6512 /* 0 for default * route */ 6513 length = 0; 6514 PIVOT_BUCKET_HANDLE(pivot_pyld) = bucket_handle; 6515 if (v6) { 6516 trie_init(_MAX_KEY_LEN_144_, &PIVOT_BUCKET_TRIE(pivot_pyld)); 6517 } else { 6518 trie_init(_MAX_KEY_LEN_48_, &PIVOT_BUCKET_TRIE(pivot_pyld)); 6519 } 6520 bucket_root = PIVOT_BUCKET_TRIE(pivot_pyld); 6521 PIVOT_BUCKET_INDEX(pivot_pyld) = log_bkt; 6522 PIVOT_BUCKET_VRF(pivot_pyld) = vrf; 6523 PIVOT_BUCKET_IPV6(pivot_pyld) = v6; 6524 PIVOT_BUCKET_DEF(pivot_pyld) = TRUE; 6525 6526 pivot_pyld->key[0] = pfx_pyld->key[0] = key[0]; 6527 pivot_pyld->key[1] = pfx_pyld->key[1] = key[1]; 6528 pivot_pyld->len = pfx_pyld->len = length; 6529 /* no need to convert key in trie format since it's all 0s */ 6530 rv = trie_insert(root, key, ALPM_CTRL(u).trie_propagate ? key : NULL, 6531 length, &(pfx_pyld->node)); 6532 6533 /* no internal default in bucket trie */ 6534 6535 if (SOC_FAILURE(rv)) { 6536 /* free alloced memory */ 6537 goto _err_exit; 6538 } 6539 6540 /* insert into trie of pivots */ 6541 /* no need to convert key in trie format since it's all 0s */ 6542 rv = trie_insert(pivot_root, key, ALPM_CTRL(u).trie_propagate ? key : NULL, 6543 length, (trie_node_t *)pivot_pyld); 6544 if (SOC_FAILURE(rv)) { 6545 trie_node_t *delp = NULL; 6546 (void) trie_delete(root, key, length, &delp); 6547 /* free alloced memory */ 6548 goto _err_exit; 6549 } 6550 6551 /* get physical index */ 6552 index = soc_th_alpm_physical_idx(u, L3_DEFIPm, index, v6); 6553 if (v6 == 0) { 6554 ALPM_TCAM_PIVOT(u, index) = pivot_pyld; 6555 PIVOT_TCAM_INDEX(pivot_pyld) = index; 6556 } else { 6557 ALPM_TCAM_PIVOT(u, index << 1) = pivot_pyld; 6558 PIVOT_TCAM_INDEX(pivot_pyld) = index << 1; 6559 } 6560 PIVOT_TCAM_BPMLEN(pivot_pyld) = length; 6561 6562 VRF_TRIE_INIT_DONE(u, vrf, v6, 1); 6563 return rv; 6564 6565 _err_exit: 6566 if (pfx_pyld != NULL) { 6567 sal_free(pfx_pyld); 6568 } 6569 if (pivot_pyld != NULL) { 6570 sal_free(pivot_pyld); 6571 } 6572 if (bucket_handle != NULL) { 6573 sal_free(bucket_handle); 6574 } 6575 if (lpm_entry != NULL) { 6576 sal_free(lpm_entry); 6577 } 6578 if (v6 == 0) { 6579 VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf) = NULL; 6580 } else { 6581 VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) = NULL; 6582 } 6583 if (bucket_root != NULL) { 6584 trie_destroy(bucket_root); 6585 PIVOT_BUCKET_TRIE(pivot_pyld) = NULL; 6586 } 6587 if (root != NULL) { 6588 trie_destroy(root); 6589 if (v6 == 0) { 6590 VRF_PREFIX_TRIE_IPV4(u, vrf) = NULL; 6591 } else { 6592 VRF_PREFIX_TRIE_IPV6(u, vrf) = NULL; 6593 } 6594 } 6595 if (pivot_root != NULL) { 6596 trie_destroy(pivot_root); 6597 if (v6 == 0) { 6598 VRF_PIVOT_TRIE_IPV4(u, vrf) = NULL; 6599 } else { 6600 VRF_PIVOT_TRIE_IPV6(u, vrf) = NULL; 6601 } 6602 } 6603 6604 return rv; 6605 } 6606 6607 /* 6608 * soc_th_alpm_vrf_delete 6609 * Delete the VRF default route when a L3 VRF is destroyed 6610 */ 6611 static int 6612 soc_th_alpm_vrf_delete(int u, int vrf, int v6) 6613 { 6614 defip_entry_t *lpm_entry; 6615 int idx, vrf_id, _vrf; 6616 int rv = SOC_E_NONE; 6617 uint32 key[5] = {0}, result[SOC_MAX_MEM_FIELD_WORDS]; 6618 payload_t *payload; 6619 alpm_pivot_t *pivot_pyld1; 6620 trie_node_t *delp; 6621 trie_t *root; 6622 trie_t *pivot_root = NULL; 6623 6624 soc_mem_t mem; 6625 int tcam_index, log_bkt, index; 6626 uint32 alpm_ent[SOC_MAX_MEM_FIELD_WORDS]; 6627 6628 if (v6 == 0) { 6629 lpm_entry = VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf); 6630 } else { 6631 lpm_entry = VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf); 6632 } 6633 6634 SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(u, lpm_entry, &vrf_id, &_vrf)); 6635 SOC_ALPM_TABLE_MEM(u, v6, mem, VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 0)); 6636 rv = _soc_th_alpm_find(u, mem, v6, lpm_entry, vrf_id, _vrf, alpm_ent, 6637 &tcam_index, &log_bkt, &index, TRUE); 6638 6639 /* find bucket pointers and release them */ 6640 rv = soc_th_alpm_bucket_release(u, log_bkt, vrf, v6); 6641 if (SOC_FAILURE(rv)) { 6642 LOG_ERROR(BSL_LS_SOC_ALPM, 6643 (BSL_META_U(u, "soc_th_alpm_bucket_release: unable to free" 6644 " bucket %d vrf %d v6 %d\n"), log_bkt, vrf, v6)); 6645 } 6646 6647 /* add Entry into tcam as default routes for the VRF */ 6648 rv = soc_th_alpm_lpm_match(u, lpm_entry, (void *) result, &idx); 6649 if (SOC_FAILURE(rv)) { 6650 LOG_ERROR(BSL_LS_SOC_ALPM, 6651 (BSL_META_U(u, "soc_alpm_vrf_delete: unable to get internal" 6652 " pivot idx for vrf %d/%d\n"), vrf, v6)); 6653 idx = -1; 6654 } 6655 6656 idx = soc_th_alpm_physical_idx(u, L3_DEFIPm, idx, v6); 6657 if (v6 == 0) { 6658 pivot_pyld1 = ALPM_TCAM_PIVOT(u, idx); 6659 } else { 6660 pivot_pyld1 = ALPM_TCAM_PIVOT(u, idx << 1); 6661 } 6662 6663 rv = soc_th_alpm_lpm_delete(u, lpm_entry); 6664 if (SOC_FAILURE(rv)) { 6665 LOG_ERROR(BSL_LS_SOC_ALPM, 6666 (BSL_META_U(u, 6667 "soc_alpm_vrf_delete: unable to delete lpm entry " 6668 " for internal default for vrf %d/%d\n"), vrf, v6)); 6669 } 6670 6671 sal_free(lpm_entry); 6672 6673 if (v6 == 0) { 6674 VRF_TRIE_DEFAULT_ROUTE_IPV4(u, vrf) = NULL; 6675 root = VRF_PREFIX_TRIE_IPV4(u, vrf); 6676 VRF_PREFIX_TRIE_IPV4(u, vrf) = NULL; 6677 } else { 6678 VRF_TRIE_DEFAULT_ROUTE_IPV6(u, vrf) = NULL; 6679 root = VRF_PREFIX_TRIE_IPV6(u, vrf); 6680 VRF_PREFIX_TRIE_IPV6(u, vrf) = NULL; 6681 } 6682 VRF_TRIE_INIT_DONE(u, vrf, v6, 0); 6683 6684 rv = trie_delete(root, key, 0, &delp); 6685 payload = (payload_t *) delp; 6686 if (SOC_FAILURE(rv)) { 6687 LOG_ERROR(BSL_LS_SOC_ALPM, 6688 (BSL_META_U(u, 6689 "Unable to delete internal default for vrf " 6690 " %d/%d\n"), vrf, v6)); 6691 } 6692 sal_free(payload); 6693 6694 (void) trie_destroy(root); 6695 6696 if (v6 == 0) { 6697 pivot_root = VRF_PIVOT_TRIE_IPV4(u, vrf); 6698 VRF_PIVOT_TRIE_IPV4(u, vrf) = NULL; 6699 } else { 6700 pivot_root = VRF_PIVOT_TRIE_IPV6(u, vrf); 6701 VRF_PIVOT_TRIE_IPV6(u, vrf) = NULL; 6702 } 6703 6704 delp = NULL; 6705 rv = trie_delete(pivot_root, key, 0, &delp); 6706 if (SOC_FAILURE(rv)) { 6707 LOG_ERROR(BSL_LS_SOC_ALPM, 6708 (BSL_META_U(u, 6709 "Unable to delete internal pivot node for vrf" 6710 " %d/%d\n"), vrf, v6)); 6711 } 6712 (void) trie_destroy(pivot_root); 6713 6714 (void) trie_destroy(PIVOT_BUCKET_TRIE(pivot_pyld1)); 6715 sal_free(PIVOT_BUCKET_HANDLE(pivot_pyld1)); 6716 sal_free(pivot_pyld1); 6717 6718 return rv; 6719 } 6720 6721 /* 6722 * soc_th_alpm_insert 6723 * For IPV4 assume only both IP_ADDR0 is valid 6724 * Moving multiple entries around in h/w vs doing a linear search in s/w 6725 */ 6726 int 6727 soc_th_alpm_insert(int u, void *lpm_entry, uint32 flags, int ent_index, 6728 int pivot_info) 6729 { 6730 defip_alpm_ipv4_1_entry_t alpmv4_entry, alpmv4_sip_entry; 6731 defip_alpm_ipv6_64_1_entry_t alpmv6_entry, alpmv6_sip_entry; 6732 soc_mem_t mem; 6733 void *bufp, *bufp2; 6734 int vrf_id, vrf; 6735 int index; 6736 int ipv6; 6737 int rv = SOC_E_NONE; 6738 uint32 default_route; 6739 int log_bkt = 0, phy_bkt = 0; 6740 int ipmc_route = 0; 6741 int flex_v6_64 = 0; 6742 6743 ipv6 = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, MODE0_f(u)); 6744 6745 /* Get table memory. */ 6746 SOC_ALPM_TABLE_MEM(u, ipv6, mem, flags & SOC_ALPM_STAT_FLEX); 6747 6748 /* Assign entry buf based on table being used */ 6749 SOC_ALPM_ENTRY_BUF(ipv6, mem, bufp, alpmv4_entry, alpmv6_entry); 6750 SOC_ALPM_ENTRY_BUF(ipv6, mem, bufp2, alpmv4_sip_entry, alpmv6_sip_entry); 6751 6752 if (ent_index != -1) { 6753 log_bkt = SOC_TH_ALPM_AIDX_TO_LOG_BKT(u, ent_index); 6754 } 6755 SOC_IF_ERROR_RETURN( 6756 _soc_th_alpm_mem_ent_init(u, ipv6, lpm_entry, bufp, bufp2, mem, 6757 flags, &default_route, log_bkt)); 6758 6759 /* If the entry is override, then insert into TCAM directly */ 6760 SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(u, lpm_entry, &vrf_id, &vrf)); 6761 6762 if (VRF_FLEX_COMPLETED(u, vrf_id, vrf, ipv6)) { 6763 if (VRF_FLEX_IS_SET(u, vrf_id, vrf, ipv6, 1) != !!(flags & SOC_ALPM_STAT_FLEX)) { 6764 LOG_ERROR(BSL_LS_SOC_ALPM, 6765 (BSL_META_U(u, 6766 "soc_alpm_insert:Flex flag conflict\n" 6767 ))); 6768 return SOC_E_PARAM; 6769 } 6770 } else { 6771 VRF_FLEX_SET(u, vrf_id, vrf, ipv6, flags & SOC_ALPM_STAT_FLEX); 6772 } 6773 6774 if (soc_feature(u, soc_feature_ipmc_defip)) { 6775 ipmc_route = 0; 6776 if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE0f)) { 6777 ipmc_route = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, MULTICAST_ROUTE0f); 6778 } else if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE0f)) { 6779 if (soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, DATA_TYPE0f) == 2) { 6780 ipmc_route = 1; 6781 } else { 6782 ipmc_route = 0; 6783 } 6784 } 6785 } 6786 6787 if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && ipv6 && 6788 (flags & SOC_ALPM_STAT_FLEX)) { 6789 if (soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f) == 0xFFFFFFFF && 6790 soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f) == 0xFFFFFFFF) { 6791 flex_v6_64 = 1; 6792 } 6793 } 6794 6795 /* For VRF_OVERRIDE (Global High) entries and IPMC route, 6796 software needs to maintain the index */ 6797 /* Global High and Global Low Prefixes reside in TCAM directly, 6798 in TCAM / ALPM mode */ 6799 /* Global High Prefixes reside in TCAM directly, in Parallel mode */ 6800 if (ALPM_PREFIX_IN_TCAM(u, vrf_id) || (ipmc_route) || (flex_v6_64)) { 6801 /* Insert into TCAM directly and return */ 6802 /* search in the hash table */ 6803 rv = soc_th_alpm_lpm_insert(u, lpm_entry, &index, INVALID_BPM_LEN, 0, 6804 flags & SOC_ALPM_RPF_SRC_DISCARD); 6805 if (SOC_SUCCESS(rv) && !(pivot_info & SOC_ALPM_LPM_LOOKUP_HIT)) { 6806 VRF_TRIE_ROUTES_INC(u, vrf_id, vrf, ipv6); 6807 } 6808 if (rv == SOC_E_FULL) { 6809 if (vrf_id == SOC_L3_VRF_OVERRIDE) { 6810 VRF_PIVOT_FULL_INC(u, MAX_VRF_ID, ipv6); 6811 } else { 6812 VRF_PIVOT_FULL_INC(u, vrf, ipv6); 6813 } 6814 } 6815 return(rv); 6816 } else if (vrf == 0) { 6817 if (ALPM_CTRL(u).gp_zoned) { 6818 /* cannot have 0 as a VRF in parallel mode */ 6819 LOG_ERROR(BSL_LS_SOC_ALPM, 6820 (BSL_META_U(u, 6821 "VRF=0 cannot be added in current mode\n"))); 6822 return SOC_E_PARAM; 6823 } 6824 } 6825 6826 /* combined search mode protection */ 6827 if (vrf_id != SOC_L3_VRF_GLOBAL) { 6828 if (ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_COMBINED) { 6829 /* for emtpy DB allow insert only if route is default */ 6830 if (VRF_TRIE_ROUTES_CNT(u, vrf_id, vrf, ipv6) == 0) { 6831 /* check if route is default, else throw error */ 6832 if (!default_route) { 6833 LOG_ERROR(BSL_LS_SOC_ALPM, 6834 (BSL_META_U(u, 6835 "VRF %d: First route in a VRF has to " 6836 " be a default route in this mode\n"), vrf_id)); 6837 return SOC_E_PARAM; 6838 } 6839 } 6840 } 6841 } 6842 6843 /* non override entries, goes into ALPM memory */ 6844 if (!VRF_TRIE_INIT_COMPLETED(u, vrf, ipv6)) { 6845 LOG_VERBOSE(BSL_LS_SOC_ALPM, 6846 (BSL_META_U(u, 6847 "soc_alpm_insert:VRF %d is not " 6848 "initialized\n"), vrf)); 6849 rv = soc_th_alpm_vrf_add(u, vrf, ipv6); 6850 if (SOC_FAILURE(rv)) { 6851 LOG_ERROR(BSL_LS_SOC_ALPM, 6852 (BSL_META_U(u, 6853 "soc_alpm_insert:VRF %d/%d trie init \n" 6854 "failed\n"), vrf, ipv6)); 6855 return rv; 6856 } 6857 LOG_VERBOSE(BSL_LS_SOC_ALPM, 6858 (BSL_META_U(u, 6859 "soc_alpm_insert:VRF %d/%d trie init " 6860 "completed\n"), vrf, ipv6)); 6861 6862 } 6863 6864 /* Find and update the entry */ 6865 if (pivot_info & SOC_ALPM_LOOKUP_HIT) { 6866 rv = _soc_th_alpm_find_and_update(u, ipv6, lpm_entry, bufp, bufp2, mem, 6867 ent_index); 6868 } else { 6869 /* entry is not found in database */ 6870 /* Insert the entry into the database, if FULL, split the bucket */ 6871 /* Insert prefix into trie */ 6872 /* Split trie : Insertion into trie results into Split */ 6873 /* Allocate a TCAM entry for PIVOT and bucket and move entries */ 6874 if (ent_index == -1) { 6875 /* internally 0 is invalid bucket index */ 6876 ent_index = 0; 6877 } 6878 phy_bkt = SOC_TH_ALPM_AIDX_TO_PHY_BKT(u, ent_index); 6879 /* In double wide mode, the ent_index could come from second 6880 * bucket, need to adjust to first bucket */ 6881 if (ALPM_CTRL(u).double_wide[ipv6] && (phy_bkt & 0x1)) { 6882 phy_bkt &= ~0x1; 6883 } 6884 log_bkt = ALPM_LOG_BKT(phy_bkt, 6885 SOC_TH_ALPM_AIDX_TO_SUB_BKT(u, ent_index)); 6886 6887 rv = _soc_th_alpm_insert(u, ipv6, lpm_entry, mem, bufp, bufp2, &index, 6888 log_bkt, pivot_info); 6889 if (SOC_SUCCESS(rv)) { 6890 VRF_TRIE_ROUTES_INC(u, vrf_id, vrf, ipv6); 6891 } 6892 } 6893 6894 if (rv == SOC_E_FULL) { 6895 LOG_VERBOSE(BSL_LS_SOC_ALPM, 6896 (BSL_META_U(u, 6897 "unit %d :soc_alpm_insert: Route Insertion Failed :%s\n"), 6898 u, soc_errmsg(rv))); 6899 } else if (rv != SOC_E_NONE) { 6900 LOG_ERROR(BSL_LS_SOC_ALPM, 6901 (BSL_META_U(u, 6902 "unit %d :soc_alpm_insert: Route Insertion Failed :%s\n"), 6903 u, soc_errmsg(rv))); 6904 } 6905 return(rv); 6906 } 6907 6908 /* 6909 * soc_th_alpm_lookup 6910 * For IPV4 assume only both IP_ADDR0 is valid 6911 * Moving multiple entries around in h/w vs doing a linear search in s/w 6912 */ 6913 int 6914 soc_th_alpm_lookup(int u, 6915 void *key_data, 6916 void *e, /* return entry data if found */ 6917 int *index_ptr, 6918 int *cookie) 6919 { 6920 defip_alpm_ipv4_1_entry_t alpmv4_entry; /* Search Result buffer */ 6921 defip_alpm_ipv6_64_1_entry_t alpmv6_entry; /* Search Result buffer */ 6922 soc_mem_t mem; 6923 int log_bkt = 0; 6924 int tcam_index = -1; 6925 void *bufp; 6926 int vrf_id, vrf; 6927 int ipv6, pfx; 6928 int rv = SOC_E_NONE; 6929 int ipmc_route = 0; 6930 int flex_v6_64 = 0; 6931 int flex; 6932 6933 /* First launch lookup directly into tcam. If hit comes from override 6934 * vrf just return it. Else launch lookup into alpm pivots 6935 */ 6936 /* For VRF_OVERRIDE (Global High) entries, software needs to maintain the 6937 * index */ 6938 /* Prefix resides in TCAM directly */ 6939 6940 /* search in the hash table */ 6941 *index_ptr = 0; 6942 rv = _soc_th_alpm_lpm_match(u, key_data, e, index_ptr, &pfx, &ipv6, 6943 &vrf_id, &vrf); 6944 /* 6945 * If entry is ipv4 copy to the "zero" half of the, 6946 * buffer, "zero" half of lpm_entry if the original entry 6947 * is in the "one" half. 6948 */ 6949 flex = VRF_FLEX_IS_SET(u, vrf_id, vrf, ipv6, 0); 6950 if (SOC_SUCCESS(rv)) { 6951 if (!ipv6 && (*index_ptr & 0x1)) { 6952 rv = soc_th_alpm_lpm_ip4entry1_to_0(u, e, e, PRESERVE_HIT); 6953 } 6954 if (soc_feature(u, soc_feature_ipmc_defip)) { 6955 ipmc_route = 0; 6956 if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE0f)) { 6957 ipmc_route = soc_mem_field32_get(u, L3_DEFIPm, e, MULTICAST_ROUTE0f); 6958 } else if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE0f)) { 6959 if (soc_mem_field32_get(u, L3_DEFIPm, e, DATA_TYPE0f) == 2) { 6960 ipmc_route = 1; 6961 } else { 6962 ipmc_route = 0; 6963 } 6964 } 6965 } 6966 6967 if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && ipv6 && flex) { 6968 if (soc_mem_field32_get(u, L3_DEFIPm, key_data, IP_ADDR_MASK0f) == 0xFFFFFFFF && 6969 soc_mem_field32_get(u, L3_DEFIPm, key_data, IP_ADDR_MASK1f) == 0xFFFFFFFF) { 6970 flex_v6_64 = 1; 6971 } 6972 } 6973 } 6974 if (ALPM_PREFIX_IN_TCAM(u, vrf_id) || (ipmc_route) || (flex_v6_64)) { 6975 *cookie = 0; 6976 if (SOC_SUCCESS(rv)) { 6977 *cookie |= SOC_ALPM_LPM_LOOKUP_HIT; 6978 } 6979 return rv; 6980 } 6981 6982 /* either no hit in OVERRIDE or hit in pivot tcam */ 6983 6984 /* non override entries, go to into ALPM memory */ 6985 if (!VRF_TRIE_INIT_COMPLETED(u, vrf, ipv6)) { 6986 LOG_VERBOSE(BSL_LS_SOC_ALPM, 6987 (BSL_META_U(u, "soc_alpm_lookup:VRF %d is not initialized\n"), 6988 vrf)); 6989 *cookie = 0; 6990 return SOC_E_NOT_FOUND; 6991 } 6992 /* Get table memory. */ 6993 SOC_ALPM_TABLE_MEM(u, ipv6, mem, flex); 6994 6995 /* Assign entry buf based on table being used */ 6996 SOC_ALPM_ENTRY_BUF(ipv6, mem, bufp, alpmv4_entry, alpmv6_entry); 6997 6998 SOC_ALPM_LPM_LOCK(u); 6999 /* Find and update the entry */ 7000 rv = _soc_th_alpm_find(u, mem, ipv6, key_data, vrf_id, vrf, bufp, 7001 &tcam_index, &log_bkt, index_ptr, TRUE); 7002 SOC_ALPM_LPM_UNLOCK(u); 7003 if (SOC_FAILURE(rv)) { 7004 *cookie = tcam_index; 7005 *index_ptr = SOC_TH_ALPM_AIDX(u, ALPM_PHY_BKT(u, log_bkt), 7006 ALPM_SUB_BKT(u, log_bkt), 0, 0); 7007 return rv; 7008 } 7009 /* Copy ALPM memory to LPM entry */ 7010 rv = _soc_th_alpm_lpm_ent_init(u, bufp, mem, ipv6, vrf_id, log_bkt, 7011 *index_ptr, e, flex); 7012 *cookie = SOC_ALPM_LOOKUP_HIT | tcam_index; 7013 if (flex) { 7014 *cookie |= SOC_ALPM_COOKIE_FLEX; 7015 } 7016 *index_ptr = (ALPM_SUB_BKT(u, log_bkt) << ALPM_ENT_INDEX_BITS) | *index_ptr; 7017 7018 return(rv); 7019 } 7020 7021 /* Find a LPM Global low or VRF route in ALPM memory */ 7022 static int 7023 _soc_th_alpm_find_best_match(int u, 7024 void *key_data, 7025 void *e, /* return entry data if found */ 7026 int vrf_id, 7027 int *tcam_index, 7028 int *log_bkt, 7029 int *key_index, 7030 int do_urpf) 7031 { 7032 int rv = SOC_E_NONE; 7033 int i, j, v6, hit = 0; 7034 uint32 db_type, ent_type, bank_disable; 7035 defip_aux_scratch_entry_t aux_entry; 7036 int global, mvrf, vrf; 7037 int index; 7038 soc_mem_t mem, lpm_mem; 7039 int hw_len, sw_len; 7040 int ent_num = ALPM_IPV4_BKT_COUNT; 7041 int flex; 7042 7043 /* Used for keeping Longest Matched entry in Bucket */ 7044 uint32 alpm_bufp[SOC_MAX_MEM_FIELD_WORDS] = {0}; 7045 int alpm_len = -1; 7046 int alpm_index = 0; 7047 7048 soc_field_t ip_addr_fld[2] = { 7049 IP_ADDR0f, 7050 IP_ADDR1f, 7051 }; 7052 7053 lpm_mem = L3_DEFIPm; 7054 v6 = soc_mem_field32_get(u, lpm_mem, key_data, MODE0_f(u)); 7055 global = soc_mem_field32_get(u, lpm_mem, key_data, GLOBAL_ROUTE0f); 7056 mvrf = soc_mem_field32_get(u, lpm_mem, key_data, VRF_ID_0f); 7057 vrf = (vrf_id == SOC_L3_VRF_GLOBAL) ? (SOC_VRF_MAX(u) + 1) : mvrf; 7058 7059 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7060 (BSL_META_U(u, 7061 "Prefare AUX Scratch for searching TCAM in " 7062 "%s region, Key data: v6 %d global %d vrf %d:\n"), 7063 vrf_id == SOC_L3_VRF_GLOBAL ? "Global" : "VRF", 7064 v6, global, mvrf)); 7065 7066 bank_disable = ALPM_CTRL(u).bank_disable_bmp_8b[vrf != SOC_VRF_MAX(u) + 1]; 7067 7068 if (ALPM_CTRL(u).sw_prefix_lkup) { 7069 uint32 prefix[5] = {0}; 7070 uint32 length = 0; 7071 int default_route = 0; 7072 7073 if (!VRF_TRIE_INIT_COMPLETED(u, vrf, v6)) { 7074 LOG_VERBOSE(BSL_LS_SOC_ALPM, (BSL_META_U(u, 7075 "_soc_th_alpm_find_best_match: VRF %d is not initialized\n"), 7076 vrf)); 7077 return SOC_E_NOT_FOUND; 7078 } 7079 7080 /* Create Prefix */ 7081 rv = _soc_th_alpm_prefix_create(u, v6, key_data, prefix, &length, 7082 &default_route); 7083 if (SOC_FAILURE(rv)) { 7084 LOG_ERROR(BSL_LS_SOC_ALPM, (BSL_META_U(u, 7085 "_soc_th_alpm_128_find_best_match: prefix create failed\n"))); 7086 return rv; 7087 } 7088 SOC_IF_ERROR_RETURN(_soc_th_alpm_sw_pivot_find(u, prefix, length, v6, 7089 vrf, &hit, tcam_index, 7090 log_bkt)); 7091 } else { 7092 soc_alpm_db_ent_type_encoding(u, vrf, &db_type, &ent_type); 7093 if (do_urpf) { 7094 db_type += 1; 7095 } 7096 if (vrf_id == SOC_L3_VRF_GLOBAL) { 7097 /* Crack these value to use _fill_aux routine */ 7098 soc_mem_field32_set(u, lpm_mem, key_data, GLOBAL_ROUTE0f, 1); 7099 soc_mem_field32_set(u, lpm_mem, key_data, VRF_ID_0f, 0); 7100 } 7101 7102 sal_memset(&aux_entry, 0, sizeof(defip_aux_scratch_entry_t)); 7103 SOC_IF_ERROR_RETURN( 7104 _soc_th_alpm_fill_aux_entry_for_op(u, key_data, v6, db_type, 7105 ent_type, 0, &aux_entry)); 7106 /* Recover to original value */ 7107 if (vrf_id == SOC_L3_VRF_GLOBAL) { 7108 soc_mem_field32_set(u, lpm_mem, key_data, GLOBAL_ROUTE0f, global); 7109 soc_mem_field32_set(u, lpm_mem, key_data, VRF_ID_0f, mvrf); 7110 } 7111 7112 /* Start shadow table engine to search */ 7113 SOC_IF_ERROR_RETURN( 7114 _soc_th_alpm_aux_op(u, PREFIX_LOOKUP, &aux_entry, TRUE, &hit, 7115 tcam_index, log_bkt, 0)); 7116 } 7117 7118 if (hit == 0) { 7119 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7120 (BSL_META_U(u,"Could not find bucket\n"))); 7121 return SOC_E_NOT_FOUND; 7122 } 7123 7124 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7125 (BSL_META_U(u, "Hit in memory %s, index %d, " 7126 "bucket [%d,%d]\n"), SOC_MEM_NAME(u, lpm_mem), 7127 soc_th_alpm_logical_idx(u, lpm_mem, (*tcam_index) >> 1, 1), 7128 ALPM_PHY_BKT(u, *log_bkt), ALPM_SUB_BKT(u, *log_bkt))); 7129 7130 /* Found, check ALPM bucket */ 7131 flex = VRF_FLEX_IS_SET(u, vrf_id, vrf, v6, 0); 7132 SOC_ALPM_TABLE_MEM(u, v6, mem, flex); 7133 rv = _soc_th_alpm_mask_len_get(u, v6, key_data, &sw_len); 7134 if (SOC_FAILURE(rv)) { 7135 return rv; 7136 } 7137 7138 switch (mem) { 7139 case L3_DEFIP_ALPM_IPV4m: 7140 ent_num = ALPM_IPV4_BKT_COUNT; 7141 break; 7142 case L3_DEFIP_ALPM_IPV4_1m: 7143 ent_num = ALPM_IPV4_BKT_COUNT_FLEX; 7144 break; 7145 case L3_DEFIP_ALPM_IPV6_64m: 7146 ent_num = ALPM_IPV6_64_BKT_COUNT; 7147 break; 7148 case L3_DEFIP_ALPM_IPV6_64_1m: 7149 ent_num = ALPM_IPV6_64_BKT_COUNT_FLEX; 7150 break; 7151 /* coverity[dead_error_begin: FALSE] */ 7152 default: 7153 break; 7154 } 7155 7156 /* TD3 doubles the bank count */ 7157 if (SOC_IS_TRIDENT3X(u)) { 7158 ent_num <<= 1; 7159 } 7160 7161 /* Double-wide mode check */ 7162 if ((ALPM_CTRL(u).double_wide[v6])) { 7163 ent_num <<= 1; 7164 } 7165 7166 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7167 (BSL_META_U(u, "Start searching mem %s bucket [%d,%d](count %d) " 7168 "for Length %d\n"), 7169 SOC_MEM_NAME(u, mem), ALPM_PHY_BKT(u, *log_bkt), 7170 ALPM_SUB_BKT(u, *log_bkt), ent_num, sw_len)); 7171 7172 for (i = 0; i < ent_num; i++) { 7173 uint32 bufp[SOC_MAX_MEM_FIELD_WORDS] = {0}; 7174 uint32 mask[2] = {0}; 7175 uint32 hkey[2] = {0}; 7176 uint32 skey[2] = {0}; 7177 int valid; 7178 7179 rv = _soc_th_alpm_mem_index(u, mem, ALPM_PHY_BKT(u, *log_bkt), 7180 i, bank_disable, &index); 7181 if (rv == SOC_E_FULL) { 7182 continue; 7183 } 7184 7185 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, 7186 index, (void *)bufp)); 7187 valid = soc_mem_field32_get(u, mem, bufp, VALIDf); 7188 hw_len = soc_mem_field32_get(u, mem, bufp, LENGTHf); 7189 7190 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7191 (BSL_META_U(u, "Bucket [%d,%d] index %6d: Valid %d, Length %d\n"), 7192 ALPM_PHY_BKT(u, *log_bkt), ALPM_SUB_BKT(u, *log_bkt), 7193 index, valid, hw_len)); 7194 7195 if (!valid || (hw_len > sw_len)) { 7196 continue; 7197 } 7198 7199 /* Length in ALPM <= given length */ 7200 SHR_BITSET_RANGE(mask, (v6 ? 64 : 32) - hw_len, hw_len); 7201 (void)soc_mem_field_get(u, mem, (uint32 *)bufp, KEYf, (uint32 *)hkey); 7202 skey[1] = soc_mem_field32_get(u, lpm_mem, key_data, ip_addr_fld[1]); 7203 skey[0] = soc_mem_field32_get(u, lpm_mem, key_data, ip_addr_fld[0]); 7204 7205 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7206 (BSL_META_U(u, "\tmask %08x %08x\n\t key %08x %08x\n" 7207 "\thost %08x %08x\n"), 7208 mask[1], mask[0], hkey[1], hkey[0], skey[1], skey[0])); 7209 7210 for (j = v6 ? 1 : 0; j >= 0; j--) { 7211 if ((skey[j] & mask[j]) != (hkey[j] & mask[j])) { 7212 break; 7213 } 7214 } 7215 7216 /* Hardware key doesn't match to software key */ 7217 if (j >= 0) { 7218 continue; 7219 } 7220 7221 /* Matched, store and keep searching, 7222 * could be Longer prefix in following entries */ 7223 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7224 (BSL_META_U(u, "Found a match in mem %s bucket [%d,%d], " 7225 "index %d\n"), SOC_MEM_NAME(u, mem), 7226 ALPM_PHY_BKT(u, *log_bkt), ALPM_SUB_BKT(u, *log_bkt), 7227 index)); 7228 7229 /* Keep longest matched route */ 7230 if (alpm_len == -1 || alpm_len < hw_len) { 7231 alpm_len = hw_len; 7232 alpm_index = index; 7233 sal_memcpy(alpm_bufp, bufp, sizeof(bufp)); 7234 } 7235 } 7236 7237 /* Found */ 7238 if (alpm_len != -1) { 7239 rv = _soc_th_alpm_lpm_ent_init(u, alpm_bufp, mem, v6, vrf_id, *log_bkt, 7240 alpm_index, e, flex); 7241 if (SOC_SUCCESS(rv)) { 7242 *key_index = alpm_index; 7243 if (bsl_check(bslLayerSoc, bslSourceAlpm, bslSeverityVerbose, u)) { 7244 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7245 (BSL_META_U(u, "Hit mem %s bucket [%d,%d], index %d\n"), 7246 SOC_MEM_NAME(u, mem), ALPM_PHY_BKT(u, *log_bkt), 7247 ALPM_SUB_BKT(u, *log_bkt), alpm_index)); 7248 } 7249 } 7250 return rv; 7251 } 7252 7253 /* Missed */ 7254 *key_index = soc_th_alpm_logical_idx(u, lpm_mem, (*tcam_index) >> 1, 1); 7255 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7256 (BSL_META_U(u,"Miss in mem %s bucket [%d,%d], use associate data " 7257 "in mem %s LOG index %d\n"), SOC_MEM_NAME(u, mem), 7258 ALPM_PHY_BKT(u, *log_bkt), ALPM_SUB_BKT(u, *log_bkt), 7259 SOC_MEM_NAME(u, lpm_mem), *key_index)); 7260 7261 /* Miss in bucket, use associate data */ 7262 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY, *key_index, 7263 (void *)e)); 7264 if ((!v6) && ((*tcam_index) & 1)) { 7265 /* move entry to 0 half */ 7266 rv = soc_th_alpm_lpm_ip4entry1_to_0(u, e, e, PRESERVE_HIT); 7267 } 7268 7269 return SOC_E_NONE; 7270 } 7271 7272 /* 7273 * soc_th_alpm_find_best_match 7274 * 7275 * It's an indenpendent routine, to simalute HW process for incoming packets. 7276 * Considering possible mismatch between SW and HW, we need to go through 7277 * hardware for lookup regardless of software state. 7278 */ 7279 int 7280 soc_th_alpm_find_best_match(int u, 7281 void *key_data, 7282 void *e, /* return entry data if found */ 7283 int *index_ptr, 7284 int do_urpf) 7285 { 7286 int rv = SOC_E_NONE; 7287 int i, index_min, index_cnt; 7288 defip_entry_t lpm_ent; 7289 uint32 mem_mask[2]; 7290 uint32 mem_addr[2]; 7291 uint32 mask[2]; 7292 uint32 addr[2]; 7293 uint32 glb_hi, glb_rt; 7294 7295 int vrf_id, vrf = 0; 7296 int vld[2] = {0}; 7297 int tcam_index, log_bkt; 7298 soc_mem_t lpm_mem = L3_DEFIPm; 7299 int ent, v6, hw_v6, match = 0; 7300 int flex_v6_64; 7301 7302 soc_field_t glb_hi_fld[] = { 7303 GLOBAL_HIGH0f, 7304 GLOBAL_HIGH1f 7305 }; 7306 soc_field_t glb_rt_fld[] = { 7307 GLOBAL_ROUTE0f, 7308 GLOBAL_ROUTE1f 7309 }; 7310 7311 v6 = soc_mem_field32_get(u, lpm_mem, key_data, MODE0_f(u)); 7312 if (!SOC_URPF_STATUS_GET(u) && do_urpf) { 7313 return SOC_E_PARAM; 7314 } 7315 7316 /* Since L3_DEFIP_* tables are not support for DMA, 7317 * we do PIO search instead */ 7318 index_min = soc_mem_index_min(u, lpm_mem); 7319 index_cnt = soc_mem_index_count(u, lpm_mem); 7320 if (SOC_URPF_STATUS_GET(u)) { 7321 index_cnt >>= 1; 7322 } 7323 /* in Parallel mode search from second half */ 7324 if (ALPM_CTRL(u).gp_zoned) { 7325 index_cnt >>= 1; 7326 index_min += index_cnt; 7327 } 7328 7329 if (do_urpf) { 7330 index_min += soc_mem_index_count(u, lpm_mem) / 2; 7331 } 7332 7333 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7334 (BSL_META_U(u, "Launch LPM searching from index %d count %d\n"), 7335 index_min, index_cnt)); 7336 7337 mask[0] = soc_mem_field32_get(u, lpm_mem, key_data, IP_ADDR_MASK0f); 7338 mask[1] = soc_mem_field32_get(u, lpm_mem, key_data, IP_ADDR_MASK1f); 7339 addr[0] = soc_mem_field32_get(u, lpm_mem, key_data, IP_ADDR0f); 7340 addr[1] = soc_mem_field32_get(u, lpm_mem, key_data, IP_ADDR1f); 7341 7342 /* Scanning for Global High routes */ 7343 for (i = index_min; i < index_min + index_cnt; i++) { 7344 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY, 7345 i, (void *)&lpm_ent)); 7346 vld[0] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, VALID0f); 7347 vld[1] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, VALID1f); 7348 if (vld[0] == 0 && vld[1] == 0) { 7349 continue; 7350 } 7351 7352 hw_v6 = soc_mem_field32_get(u, lpm_mem, &lpm_ent, MODE0_f(u)); 7353 if (hw_v6 != v6) { 7354 continue; 7355 } 7356 7357 for (ent = 0; ent < (v6 ? 1 : 2); ent++) { 7358 if (vld[ent] == 0) { 7359 continue; 7360 } 7361 glb_hi = soc_mem_field32_get(u, lpm_mem, &lpm_ent, glb_hi_fld[ent]); 7362 glb_rt = soc_mem_field32_get(u, lpm_mem, &lpm_ent, glb_rt_fld[ent]); 7363 7364 flex_v6_64 = 0; 7365 if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && v6) { 7366 uint32 entry_view, flex; 7367 entry_view = soc_mem_field32_get(u, lpm_mem, &lpm_ent, ENTRY_VIEW0f); 7368 flex = _soc_th_alpm_lpm_flex_get(u, v6, entry_view); 7369 if (flex) { 7370 if (soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR_MASK0f) == 0xFFFFFFFF && 7371 soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR_MASK1f) == 0xFFFFFFFF) { 7372 flex_v6_64 = 1; 7373 } 7374 } 7375 } 7376 7377 /* No need to compare key if not Global High route,*/ 7378 if (!(ALPM_CTRL(u).alpm_mode != SOC_ALPM_MODE_TCAM_ALPM && 7379 glb_hi && glb_rt) && 7380 !(ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_TCAM_ALPM && 7381 glb_rt) && 7382 !flex_v6_64) { 7383 continue; 7384 } 7385 7386 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7387 (BSL_META_U(u, "Match a Global High route: ent %d\n"), 7388 ent)); 7389 7390 mem_mask[0] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR_MASK0f); 7391 mem_mask[1] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR_MASK1f); 7392 mem_addr[0] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR0f); 7393 mem_addr[1] = soc_mem_field32_get(u, lpm_mem, &lpm_ent, IP_ADDR1f); 7394 7395 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7396 (BSL_META_U(u, "\thmsk %08x %08x\n\thkey %08x %08x\n" 7397 "\tsmsk %08x %08x\n\tskey %08x %08x\n"), 7398 mem_mask[1], mem_mask[0], mem_addr[1], mem_addr[0], 7399 mask[1], mask[0], addr[1], addr[0])); 7400 7401 /* match condition: mem mask equal to or shorten than match mask 7402 * mem masked addrs are equal. 7403 */ 7404 if (v6) { 7405 match = (mem_mask[1] <= mask[1] && mem_mask[0] <= mask[0] && 7406 ((addr[0] & mem_mask[0]) == (mem_addr[0] & mem_mask[0])) && 7407 ((addr[1] & mem_mask[1]) == (mem_addr[1] & mem_mask[1]))); 7408 } else { 7409 match = (mem_mask[ent] <= mask[0] && 7410 ((addr[0] & mem_mask[ent]) == (mem_addr[ent] & mem_mask[ent]))); 7411 } 7412 if (match) { 7413 /* Found, all Key matched */ 7414 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7415 (BSL_META_U(u,"Hit Global High route in index = %d(%d)\n"), 7416 i, ent)); 7417 sal_memcpy(e, &lpm_ent, sizeof(lpm_ent)); 7418 if (!v6 && ent == 1) { 7419 /* ent == 1 indicate it's sencond half of the entry */ 7420 rv = soc_th_alpm_lpm_ip4entry1_to_0(u, e, e, PRESERVE_HIT); 7421 } 7422 *index_ptr = i; 7423 return rv; 7424 } 7425 } 7426 } 7427 7428 /* Global High lookup miss, use AUX to search Global Low and VRF route */ 7429 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7430 (BSL_META_U(u,"Global high lookup miss, use AUX engine to " 7431 "search for VRF and Global Low routes\n"))); 7432 7433 /* Fill in AUX Scratch and perform PREFIX Operation */ 7434 SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf)); 7435 rv = _soc_th_alpm_find_best_match(u, key_data, e, vrf_id, &tcam_index, 7436 &log_bkt, index_ptr, do_urpf); 7437 if (rv == SOC_E_NOT_FOUND) { 7438 vrf = SOC_L3_VRF_GLOBAL; 7439 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7440 (BSL_META_U(u,"Not found in VRF region, trying Global " 7441 "region\n"))); 7442 rv = _soc_th_alpm_find_best_match(u, key_data, e, vrf_id, &tcam_index, 7443 &log_bkt, index_ptr, do_urpf); 7444 } 7445 7446 if (SOC_SUCCESS(rv)) { 7447 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7448 (BSL_META_U(u,"Hit in %s region in TCAM index %d, " 7449 "bucket [%d,%d]\n"), 7450 vrf == SOC_L3_VRF_GLOBAL ? "Global Low" : "VRF", 7451 tcam_index, ALPM_PHY_BKT(u, log_bkt), 7452 ALPM_SUB_BKT(u, log_bkt))); 7453 } else { 7454 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7455 (BSL_META_U(u,"Search miss for given address\n"))); 7456 } 7457 7458 return(rv); 7459 } 7460 7461 7462 /* 7463 * soc_th_alpm_delete 7464 */ 7465 int 7466 soc_th_alpm_delete(int u, void *key_data, int key_idx, int pivot_info) 7467 { 7468 int log_bkt, phy_bkt; 7469 int vrf_id, vrf; 7470 int ipv6; 7471 int rv = SOC_E_NONE; 7472 int ipmc_route = 0; 7473 int flex_v6_64 = 0; 7474 7475 ipv6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0_f(u)); 7476 7477 if (soc_feature(u, soc_feature_ipmc_defip)) { 7478 ipmc_route = 0; 7479 if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE0f)) { 7480 ipmc_route = soc_mem_field32_get(u, L3_DEFIPm, key_data, MULTICAST_ROUTE0f); 7481 } else if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE0f)) { 7482 if (soc_mem_field32_get(u, L3_DEFIPm, key_data, DATA_TYPE0f) == 2) { 7483 ipmc_route = 1; 7484 } else { 7485 ipmc_route = 0; 7486 } 7487 } 7488 } 7489 7490 /* If the entry is override, then insert into TCAM directly */ 7491 SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(u, key_data, &vrf_id, &vrf)); 7492 if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && ipv6 && 7493 VRF_FLEX_IS_SET(u, vrf_id, vrf, ipv6, 0)) { 7494 if (soc_mem_field32_get(u, L3_DEFIPm, key_data, IP_ADDR_MASK0f) == 0xFFFFFFFF && 7495 soc_mem_field32_get(u, L3_DEFIPm, key_data, IP_ADDR_MASK1f) == 0xFFFFFFFF) { 7496 flex_v6_64 = 1; 7497 } 7498 } 7499 7500 /* For VRF_OVERRIDE (Global High) entries, software needs to maintain the 7501 * index */ 7502 /* Prefix resides in TCAM directly */ 7503 if (ALPM_PREFIX_IN_TCAM(u, vrf_id) || (ipmc_route) || (flex_v6_64)) { 7504 /* search in the hash table */ 7505 rv = soc_th_alpm_lpm_delete(u, key_data); 7506 if (SOC_SUCCESS(rv)) { 7507 VRF_TRIE_ROUTES_DEC(u, vrf_id, vrf, ipv6); 7508 } 7509 return(rv); 7510 } else { /* non override entries, go to into ALPM memory */ 7511 int tcam_index; 7512 if (!VRF_TRIE_INIT_COMPLETED(u, vrf, ipv6)) { 7513 LOG_VERBOSE(BSL_LS_SOC_ALPM, 7514 (BSL_META_U(u, 7515 "soc_alpm_delete:VRF %d/%d is not initialized\n"), 7516 vrf, ipv6)); 7517 return SOC_E_NONE; 7518 } 7519 if (key_idx == -1) { 7520 /* internally 0 is invalid bucket index */ 7521 key_idx = 0; 7522 } 7523 phy_bkt = SOC_TH_ALPM_AIDX_TO_PHY_BKT(u, key_idx); 7524 /* In double wide mode, the key_idx could come from second 7525 * bucket, need to adjust to first bucket */ 7526 if (ALPM_CTRL(u).double_wide[ipv6] && (phy_bkt & 0x1)) { 7527 phy_bkt &= ~0x1; 7528 } 7529 7530 log_bkt = ALPM_LOG_BKT(phy_bkt, SOC_TH_ALPM_AIDX_TO_SUB_BKT(u, key_idx)); 7531 tcam_index = pivot_info & SOC_ALPM_TCAM_INDEX_MASK; 7532 rv = _soc_th_alpm_delete(u, ipv6, key_data, log_bkt, tcam_index, key_idx); 7533 } 7534 return(rv); 7535 } 7536 7537 7538 /* Initialize shared bucket management */ 7539 static int 7540 soc_th_alpm_shared_mem_init(int u) 7541 { 7542 int defip_table_size; 7543 int v4_bkt_cnt, v6_bkt_cnt; 7544 int rv; 7545 7546 /* Get Table Size */ 7547 defip_table_size = soc_mem_index_count(u, L3_DEFIPm) 7548 + soc_mem_index_count(u, L3_DEFIP_PAIR_128m) * 2; 7549 SOC_TH_ALPM_BUCKET_COUNT(u) = ALPM_CTRL(u).num_bkts; 7550 SOC_TH_ALPM_V6_RESV_BUCKET_COUNT(u) = ALPM_CTRL(u)._alpm_128b_bkt_rsvd_cnt; 7551 7552 if (SOC_URPF_STATUS_GET(u)) { 7553 /* remaining half buckets are the src buckets */ 7554 defip_table_size >>= 1; 7555 SOC_TH_ALPM_BUCKET_COUNT(u) >>= 1; 7556 SOC_TH_ALPM_V6_RESV_BUCKET_COUNT(u) >>= 1; 7557 } 7558 7559 /* number bytes to manage the max buckets */ 7560 SOC_TH_ALPM_BUCKET_BMAP_SIZE(u) = SHR_BITALLOCSIZE(SOC_TH_ALPM_BUCKET_COUNT(u)); 7561 7562 SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4) = 7563 sal_alloc(SOC_TH_ALPM_BUCKET_BMAP_SIZE(u), 7564 "alpm_vrf_shared_bucket_bitmap"); 7565 if (SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4) == NULL) { 7566 return SOC_E_MEMORY; 7567 } 7568 7569 /* Mark all buckets as free */ 7570 sal_memset(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4), 0, 7571 SOC_TH_ALPM_BUCKET_BMAP_SIZE(u)); 7572 7573 if (ALPM_CTRL(u).double_wide[ALPM_IPV6]) { 7574 defip_table_size = 2; 7575 } else { 7576 defip_table_size = 1; 7577 } 7578 /* Bucket 0 is reserved. Just assign it */ 7579 SHR_BITSET_RANGE(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4), 7580 0, defip_table_size); 7581 v6_bkt_cnt = SOC_TH_ALPM_V6_RESV_BUCKET_COUNT(u); 7582 v4_bkt_cnt = SOC_TH_ALPM_BUCKET_COUNT(u) - v6_bkt_cnt; 7583 if (ALPM_CTRL(u)._alpm_128b_bkt_rsvd) { 7584 SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6) = 7585 sal_alloc(SOC_TH_ALPM_BUCKET_BMAP_SIZE(u), 7586 "alpm_vrf_shared_bucket_bitmap"); 7587 if (SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6) == NULL) { 7588 rv = SOC_E_MEMORY; 7589 goto error; 7590 } 7591 /* Mark all buckets as free */ 7592 sal_memset(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6), 0, 7593 SOC_TH_ALPM_BUCKET_BMAP_SIZE(u)); 7594 7595 SHR_BITSET_RANGE(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4), 7596 v4_bkt_cnt, v6_bkt_cnt); 7597 7598 SHR_BITSET_RANGE(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6), 7599 0, v4_bkt_cnt); 7600 } else { 7601 SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6) = 7602 SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4); 7603 } 7604 7605 /* If Parallel uRPF mode, we share bucket between Global low and VRF */ 7606 if (soc_property_get(u, "l3_alpm_vrf_share_bucket", 0) && 7607 ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_PARALLEL && 7608 SOC_URPF_STATUS_GET(u)) { 7609 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4) = 7610 sal_alloc(SOC_TH_ALPM_BUCKET_BMAP_SIZE(u), "alpm_glb_shr_bkt_bmap"); 7611 if (SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4) == NULL) { 7612 rv = SOC_E_MEMORY; 7613 goto error; 7614 } 7615 /* Mark all buckets as free */ 7616 sal_memset(SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4), 0, 7617 SOC_TH_ALPM_BUCKET_BMAP_SIZE(u)); 7618 /* Bucket 0 is reserved. Just assign it */ 7619 SHR_BITSET_RANGE(SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4), 7620 0, defip_table_size); 7621 if (ALPM_CTRL(u)._alpm_128b_bkt_rsvd) { 7622 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6) = 7623 sal_alloc(SOC_TH_ALPM_BUCKET_BMAP_SIZE(u), 7624 "alpm_vrf_shared_bucket_bitmap"); 7625 if (SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6) == NULL) { 7626 rv = SOC_E_MEMORY; 7627 goto error; 7628 } 7629 /* Mark all buckets as free */ 7630 sal_memset(SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6), 0, 7631 SOC_TH_ALPM_BUCKET_BMAP_SIZE(u)); 7632 7633 SHR_BITSET_RANGE(SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4), 7634 v4_bkt_cnt, v6_bkt_cnt); 7635 7636 SHR_BITSET_RANGE(SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6), 7637 0, v4_bkt_cnt); 7638 } else { 7639 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6) = 7640 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4); 7641 } 7642 } else { 7643 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4) = 7644 SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4); 7645 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6) = 7646 SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6); 7647 } 7648 7649 return SOC_E_NONE; 7650 error: 7651 if (SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4)) { 7652 if (ALPM_CTRL(u)._alpm_128b_bkt_rsvd && 7653 SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6) != 7654 SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4)) { 7655 sal_free(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6)); 7656 } 7657 SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV6) = NULL; 7658 7659 sal_free(SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4)); 7660 SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ALPM_IPV4) = NULL; 7661 } 7662 7663 if (SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4)) { 7664 if (ALPM_CTRL(u)._alpm_128b_bkt_rsvd && 7665 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6) != 7666 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4)) { 7667 sal_free(SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6)); 7668 } 7669 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV6) = NULL; 7670 sal_free(SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4)); 7671 SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ALPM_IPV4) = NULL; 7672 } 7673 7674 return rv; 7675 } 7676 7677 7678 /* Get the free bucket to allocate to the PIVOT */ 7679 int 7680 soc_th_alpm_bucket_assign(int u, int vrf, int v6, int *log_bkt) 7681 { 7682 int i, step_count = 1, used = 0; 7683 uint8 ipv = !!v6; 7684 SHR_BITDCL *bkt_bmap = SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv); 7685 if (vrf == SOC_VRF_MAX(u) + 1) { 7686 bkt_bmap = SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv); 7687 } 7688 7689 /* 7690 * in combined search mode, with urpf disabled, need to allocate even and 7691 * odd bucket pointers 7692 */ 7693 if (ALPM_CTRL(u).double_wide[v6]) { 7694 step_count = 2; 7695 } 7696 7697 for (i = 0; i < SOC_TH_ALPM_BUCKET_COUNT(u); i += step_count) { 7698 SHR_BITTEST_RANGE(bkt_bmap, i, step_count, used); 7699 if (0 == used) { 7700 break; 7701 } 7702 } 7703 if (i == SOC_TH_ALPM_BUCKET_COUNT(u)) { 7704 return SOC_E_FULL; 7705 } 7706 7707 SHR_BITSET_RANGE(bkt_bmap, i, step_count); 7708 *log_bkt = ALPM_LOG_BKT(i, 0); 7709 SOC_TH_ALPM_BUCKET_NEXT_FREE(u) = i; 7710 return SOC_E_NONE; 7711 } 7712 7713 7714 /* Get the free bucket to allocate to the PIVOT */ 7715 int 7716 soc_th_alpm_assign(int u, int vrf, soc_mem_t mem, 7717 int *log_bkt, int *shuffled, int *free_count) 7718 { 7719 int rv; 7720 int phy_bkt, step_count = 1; 7721 int v6 = SOC_ALPM_MEM_V6(mem); 7722 uint8 ipv = !!v6; 7723 7724 rv = soc_th_alpm_bucket_assign(u, vrf, v6, log_bkt); 7725 7726 if (SOC_SUCCESS(rv)) { 7727 int max_count = _soc_th_alpm_bkt_entry_cnt(u, mem); 7728 if (_soc_th_alpm_lpm_free_entries(u, mem, vrf) == 0) { 7729 rv = _soc_th_alpm_merge(u, mem, vrf, max_count, &phy_bkt, shuffled, &step_count); 7730 if (rv == SOC_E_FULL && !v6) { 7731 rv = SOC_E_NONE; 7732 } else if (SOC_FAILURE(rv)){ 7733 (void) soc_th_alpm_bucket_release(u, *log_bkt, vrf, v6); 7734 } 7735 } 7736 if (free_count) { 7737 *free_count = max_count; 7738 } 7739 } else if (rv == SOC_E_FULL) { 7740 rv = _soc_th_alpm_assign(u, mem, vrf, log_bkt, shuffled, free_count); 7741 /* Reclaim the physical bucket in case it has been freed */ 7742 if (SOC_SUCCESS(rv)) { 7743 SHR_BITDCL *bkt_bmap = SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv); 7744 if (vrf == SOC_VRF_MAX(u) + 1) { 7745 bkt_bmap = SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv); 7746 } 7747 if (ALPM_CTRL(u).double_wide[v6]) { 7748 step_count = 2; 7749 } 7750 phy_bkt = ALPM_PHY_BKT(u, *log_bkt); 7751 SHR_BITSET_RANGE(bkt_bmap, phy_bkt, step_count); 7752 SOC_TH_ALPM_BUCKET_NEXT_FREE(u) = phy_bkt; 7753 } 7754 } 7755 7756 return rv; 7757 } 7758 7759 7760 /* Free a logical bucket (bucket ID), if bucket becomes empty, then 7761 * free the physical bucket */ 7762 int 7763 soc_th_alpm_bucket_release(int u, int log_bkt, int vrf, int v6) 7764 { 7765 int step_count = 1, used = 0; 7766 int key_index; 7767 int phy_bkt, sub_bkt; 7768 uint8 ipv = !!v6; 7769 SHR_BITDCL *bkt_bmap = SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv); 7770 7771 phy_bkt = ALPM_PHY_BKT(u, log_bkt); 7772 sub_bkt = ALPM_SUB_BKT(u, log_bkt); 7773 7774 SOC_ALPM_BU_SUB_BKT_CLR(u, phy_bkt, sub_bkt); 7775 SOC_ALPM_BU_PIVOT_IDX(u, phy_bkt, sub_bkt) = 0; 7776 7777 if (SOC_ALPM_BU_COUNT(u, phy_bkt)) { 7778 return SOC_E_NONE; 7779 } 7780 7781 /* Check if the bucket pointer is valid */ 7782 if ((phy_bkt < 1) || 7783 (phy_bkt > SOC_TH_ALPM_BUCKET_MAX_INDEX(u))) { 7784 return SOC_E_PARAM; 7785 } 7786 7787 if (vrf == SOC_VRF_MAX(u) + 1) { 7788 bkt_bmap = SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv); 7789 } 7790 7791 /* in combined search mode, with urpf disabled, need to free even and odd 7792 * bucket pointers 7793 */ 7794 if (ALPM_CTRL(u).double_wide[v6]) { 7795 step_count = 2; 7796 } 7797 SHR_BITTEST_RANGE(bkt_bmap, phy_bkt, step_count, used); 7798 if (!used) { 7799 return SOC_E_PARAM; 7800 } 7801 SHR_BITCLR_RANGE(bkt_bmap, phy_bkt, step_count); 7802 7803 key_index = SOC_TH_ALPM_AIDX(u, phy_bkt, 0, 0, 0); 7804 soc_alpm_cmn_bkt_view_set(u, key_index, INVALIDm); 7805 if (SOC_URPF_STATUS_GET(u)) { 7806 soc_alpm_cmn_bkt_view_set(u, _soc_th_alpm_rpf_entry(u, key_index), 7807 INVALIDm); 7808 } 7809 if (step_count == 2) { 7810 key_index = SOC_TH_ALPM_AIDX(u, phy_bkt + 1, 0, 0, 0); 7811 soc_alpm_cmn_bkt_view_set(u, key_index, INVALIDm); 7812 if (SOC_URPF_STATUS_GET(u)) { 7813 soc_alpm_cmn_bkt_view_set(u, _soc_th_alpm_rpf_entry(u, key_index), 7814 INVALIDm); 7815 } 7816 } 7817 7818 return SOC_E_NONE; 7819 } 7820 7821 int 7822 soc_th_alpm_bucket_is_assigned(int u, int log_bkt, int vrf, int v6, int *used) 7823 { 7824 int step_count = 1; 7825 uint8 ipv = !!v6; 7826 SHR_BITDCL *bkt_bmap = SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv); 7827 int phy_bkt, sub_bkt; 7828 7829 phy_bkt = ALPM_PHY_BKT(u, log_bkt); 7830 sub_bkt = ALPM_SUB_BKT(u, log_bkt); 7831 7832 if (vrf == SOC_VRF_MAX(u) + 1) { 7833 bkt_bmap = SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv); 7834 } 7835 7836 /* Check if the bucket pointer is valid */ 7837 if ((phy_bkt < 1) || (phy_bkt > SOC_TH_ALPM_BUCKET_MAX_INDEX(u))) { 7838 return SOC_E_PARAM; 7839 } 7840 7841 /* in combined search mode, with urpf disabled, need to allocate even and 7842 * odd bucket pointers */ 7843 if (ALPM_CTRL(u).double_wide[v6]) { 7844 step_count = 2; 7845 } 7846 7847 SHR_BITTEST_RANGE(bkt_bmap, phy_bkt, step_count, *used); 7848 *used = *used && SOC_ALPM_BU_SUB_BKT_IS_SET(u, phy_bkt, sub_bkt); 7849 7850 return SOC_E_NONE; 7851 } 7852 7853 /********************************************** 7854 * TCAM Management functions * 7855 */ 7856 7857 /* 7858 * TCAM based PIVOT implementation. Each table entry can hold two IPV4 PIVOTs or 7859 * one IPV6 PIVOT entry. VRF independent routes placed at the beginning or 7860 * at the end of table based on application provided entry vrf id 7861 * (SOC_L3_VRF_OVERRIDE/SOC_L3_VRF_GLOBAL). 7862 * 7863 * ALPM_MAX_PFX_INDEX 7864 * lpm_prefix_index[98].begin ---> =============================== 7865 * == == 7866 * == 0 == 7867 * lpm_prefix_index[98].end ---> =============================== 7868 * 7869 * lpm_prefix_index[97].begin ---> =============================== 7870 * == == 7871 * == IPV6 Prefix Len = 64 == 7872 * lpm_prefix_index[97].end ---> =============================== 7873 * 7874 * 7875 * 7876 * lpm_prefix_index[x].begin ---> =============================== 7877 * == == 7878 * == == 7879 * lpm_prefix_index[x].end ---> =============================== 7880 * 7881 * 7882 * ALPM_IPV6_PFX_ZERO 7883 * lpm_prefix_index[33].begin ---> =============================== 7884 * == == 7885 * == IPV6 Prefix Len = 0 == 7886 * lpm_prefix_index[33].end ---> =============================== 7887 * 7888 * 7889 * lpm_prefix_index[32].begin ---> =============================== 7890 * == == 7891 * == IPV4 Prefix Len = 32 == 7892 * lpm_prefix_index[32].end ---> =============================== 7893 * 7894 * 7895 * 7896 * lpm_prefix_index[0].begin ---> =============================== 7897 * == == 7898 * == IPV4 Prefix Len = 0 == 7899 * lpm_prefix_index[0].end ---> =============================== 7900 */ 7901 7902 7903 /* 7904 * Extract key data from an entry at the given index. 7905 */ 7906 static 7907 void _soc_th_alpm_lpm_hash_entry_get(int u, void *e, 7908 int index, _soc_th_alpm_lpm_hash_entry_t r_entry, 7909 int *v) 7910 { 7911 if (index & TD2_ALPM_HASH_IPV6_MASK) { 7912 SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, e, r_entry); 7913 if (v) { 7914 *v = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f) && 7915 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f); 7916 } 7917 } else { 7918 if (index & 0x1) { 7919 SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, e, r_entry); 7920 if (v) { 7921 *v = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f); 7922 } 7923 } else { 7924 SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, e, r_entry); 7925 if (v) { 7926 *v = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f); 7927 } 7928 } 7929 } 7930 } 7931 7932 /* 7933 * Function: 7934 * _soc_th_alpm_lpm_hash_compare_key 7935 * Purpose: 7936 * Comparison function for AVL shadow table operations. 7937 */ 7938 static 7939 int _soc_th_alpm_lpm_hash_compare_key(_soc_th_alpm_lpm_hash_entry_t key1, 7940 _soc_th_alpm_lpm_hash_entry_t key2) 7941 { 7942 int idx; 7943 7944 for (idx = 0; idx < 5; idx++) { 7945 if (key1[idx] < key2[idx]) { 7946 return -1; 7947 } 7948 if (key1[idx] > key2[idx]) { 7949 return 1; 7950 } 7951 } 7952 return (0); 7953 } 7954 7955 #ifdef FB_LPM_DEBUG 7956 #define H_INDEX_MATCH(str, tab_index, match_index) \ 7957 LOG_ERROR(BSL_LS_SOC_ALPM, \ 7958 (BSL_META("%s index: H %d A %d\n"), \ 7959 str, (int)tab_index, match_index)) 7960 #else 7961 #define H_INDEX_MATCH(str, tab_index, match_index) 7962 #endif 7963 7964 #define LPM_NO_MATCH_INDEX 0x4000 7965 #define LPM_HASH_INSERT(u, entry_data, tab_index, rvt_index0, rvt_index1) \ 7966 soc_th_alpm_lpm_hash_insert(u, entry_data, tab_index, LPM_NO_MATCH_INDEX, 0,\ 7967 rvt_index0, rvt_index1) 7968 7969 #define LPM_HASH_REVERT(u, entry_data, tab_index, rvt_index0, rvt_index1) \ 7970 soc_th_alpm_lpm_hash_revert(u, entry_data, tab_index, \ 7971 rvt_index0, rvt_index1) 7972 7973 #define LPM_HASH_DELETE(u, key_data, tab_index) \ 7974 soc_th_alpm_lpm_hash_delete(u, key_data, tab_index) 7975 7976 #define LPM_HASH_LOOKUP(u, key_data, pfx, tab_index) \ 7977 soc_th_alpm_lpm_hash_lookup(u, key_data, pfx, tab_index) 7978 7979 #define LPM_HASH_VERIFY(u, key_data, tab_index) \ 7980 soc_th_alpm_lpm_hash_verify(u, key_data, tab_index) 7981 7982 #define INDEX_DELETE(hash, hash_idx, del_idx) \ 7983 hash->table[hash_idx] = \ 7984 hash->link_table[del_idx & TD2_ALPM_HASH_INDEX_MASK]; \ 7985 hash->link_table[del_idx & TD2_ALPM_HASH_INDEX_MASK] = \ 7986 TD2_ALPM_HASH_INDEX_NULL 7987 7988 #define INDEX_DELETE_LINK(hash, prev_idx, del_idx) \ 7989 hash->link_table[prev_idx & TD2_ALPM_HASH_INDEX_MASK] = \ 7990 hash->link_table[del_idx & TD2_ALPM_HASH_INDEX_MASK]; \ 7991 hash->link_table[del_idx & TD2_ALPM_HASH_INDEX_MASK] = \ 7992 TD2_ALPM_HASH_INDEX_NULL 7993 7994 7995 static void soc_th_alpm_lpm_hash_insert(int u, void *entry_data, uint32 tab_index, 7996 uint32 old_index, int pfx, 7997 uint32 *rvt_index0, uint32 *rvt_index1) 7998 { 7999 _soc_th_alpm_lpm_hash_entry_t key_hash; 8000 8001 if (soc_mem_field32_get(u, L3_DEFIPm, entry_data, MODE0_f(u))) { 8002 /* IPV6 entry */ 8003 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID1f) && 8004 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID0f)) { 8005 SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, key_hash); 8006 _soc_th_alpm_lpm_hash_insert( 8007 SOC_ALPM_LPM_STATE_HASH(u), 8008 _soc_th_alpm_lpm_hash_compare_key, 8009 key_hash, 8010 pfx, 8011 old_index, 8012 ((uint16)tab_index << 1) | TD2_ALPM_HASH_IPV6_MASK, 8013 rvt_index0); 8014 } 8015 } else { 8016 /* IPV4 entry */ 8017 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID0f)) { 8018 SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, key_hash); 8019 _soc_th_alpm_lpm_hash_insert(SOC_ALPM_LPM_STATE_HASH(u), 8020 _soc_th_alpm_lpm_hash_compare_key, 8021 key_hash, 8022 pfx, 8023 old_index, 8024 ((uint16)tab_index << 1), 8025 rvt_index0); 8026 } 8027 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID1f)) { 8028 SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, key_hash); 8029 _soc_th_alpm_lpm_hash_insert(SOC_ALPM_LPM_STATE_HASH(u), 8030 _soc_th_alpm_lpm_hash_compare_key, 8031 key_hash, 8032 pfx, 8033 old_index, 8034 (((uint16)tab_index << 1) + 1), 8035 rvt_index1); 8036 } 8037 } 8038 } 8039 8040 8041 static void soc_th_alpm_lpm_hash_revert(int u, void *entry_data, uint32 tab_index, 8042 uint32 rvt_index0, uint32 rvt_index1) 8043 { 8044 _soc_th_alpm_lpm_hash_entry_t key_hash; 8045 8046 if (soc_mem_field32_get(u, L3_DEFIPm, entry_data, MODE0_f(u))) { 8047 /* IPV6 entry */ 8048 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID1f) && 8049 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID0f)) { 8050 SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, entry_data, key_hash); 8051 _soc_th_alpm_lpm_hash_revert( 8052 SOC_ALPM_LPM_STATE_HASH(u), 8053 _soc_th_alpm_lpm_hash_compare_key, 8054 key_hash, 8055 ((uint16)tab_index << 1) | TD2_ALPM_HASH_IPV6_MASK, 8056 rvt_index0); 8057 } 8058 } else { 8059 /* IPV4 entry */ 8060 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID0f)) { 8061 SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, entry_data, key_hash); 8062 _soc_th_alpm_lpm_hash_revert(SOC_ALPM_LPM_STATE_HASH(u), 8063 _soc_th_alpm_lpm_hash_compare_key, 8064 key_hash, 8065 ((uint16)tab_index << 1), 8066 rvt_index0); 8067 } 8068 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry_data, VALID1f)) { 8069 SOC_FB_LPM_HASH_ENTRY_IPV4_1_GET(u, entry_data, key_hash); 8070 _soc_th_alpm_lpm_hash_revert(SOC_ALPM_LPM_STATE_HASH(u), 8071 _soc_th_alpm_lpm_hash_compare_key, 8072 key_hash, 8073 (((uint16)tab_index << 1) + 1), 8074 rvt_index1); 8075 } 8076 } 8077 } 8078 8079 8080 static void soc_th_alpm_lpm_hash_delete(int u, void *key_data, uint32 tab_index) 8081 { 8082 _soc_th_alpm_lpm_hash_entry_t key_hash; 8083 int pfx = -1; 8084 int rv; 8085 uint16 index; 8086 8087 if (soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0_f(u))) { 8088 SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, key_data, key_hash); 8089 index = (tab_index << 1) | TD2_ALPM_HASH_IPV6_MASK; 8090 } else { 8091 SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, key_data, key_hash); 8092 index = tab_index; 8093 } 8094 8095 rv = _soc_th_alpm_lpm_hash_delete(SOC_ALPM_LPM_STATE_HASH(u), 8096 _soc_th_alpm_lpm_hash_compare_key, 8097 key_hash, pfx, index); 8098 if (SOC_FAILURE(rv)) { 8099 LOG_ERROR(BSL_LS_SOC_ALPM, 8100 (BSL_META_U(u, 8101 "\ndel index: H %d error %d\n"), index, rv)); 8102 } 8103 } 8104 8105 static int soc_th_alpm_lpm_hash_lookup(int u, void *key_data, int pfx, int *key_index) 8106 { 8107 _soc_th_alpm_lpm_hash_entry_t key_hash; 8108 int is_ipv6; 8109 int rv; 8110 uint16 index = TD2_ALPM_HASH_INDEX_NULL; 8111 8112 is_ipv6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0_f(u)); 8113 if (is_ipv6) { 8114 SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, key_data, key_hash); 8115 } else { 8116 SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, key_data, key_hash); 8117 } 8118 8119 rv = _soc_th_alpm_lpm_hash_lookup(SOC_ALPM_LPM_STATE_HASH(u), 8120 _soc_th_alpm_lpm_hash_compare_key, 8121 key_hash, pfx, &index); 8122 if (SOC_FAILURE(rv)) { 8123 *key_index = 0xFFFFFFFF; 8124 return(rv); 8125 } 8126 8127 *key_index = index; 8128 8129 return(SOC_E_NONE); 8130 } 8131 8132 static int soc_th_alpm_lpm_hash_verify(int u, void *key_data, uint32 tab_index) 8133 { 8134 _soc_th_alpm_lpm_hash_entry_t key_hash; 8135 int pfx = -1; 8136 int rv; 8137 uint16 index; 8138 8139 if (soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0_f(u))) { 8140 SOC_FB_LPM_HASH_ENTRY_IPV6_GET(u, key_data, key_hash); 8141 index = (tab_index << 1) | TD2_ALPM_HASH_IPV6_MASK; 8142 } else { 8143 SOC_FB_LPM_HASH_ENTRY_IPV4_0_GET(u, key_data, key_hash); 8144 index = tab_index; 8145 } 8146 8147 rv = _soc_th_alpm_lpm_hash_verify(SOC_ALPM_LPM_STATE_HASH(u), 8148 _soc_th_alpm_lpm_hash_compare_key, 8149 key_hash, pfx, index); 8150 if (SOC_FAILURE(rv)) { 8151 LOG_ERROR(BSL_LS_SOC_ALPM, 8152 (BSL_META_U(u, 8153 "\nveri index: H %d error %d\n"), index, rv)); 8154 } 8155 return rv; 8156 } 8157 /* 8158 * Function: 8159 * _soc_th_alpm_lpm_hash_compute 8160 * Purpose: 8161 * Compute CRC hash for key data. 8162 * Parameters: 8163 * data - Key data 8164 * data_nbits - Number of data bits 8165 * Returns: 8166 * Computed 16 bit hash 8167 */ 8168 static 8169 uint16 _soc_th_alpm_lpm_hash_compute(uint8 *data, int data_nbits) 8170 { 8171 return (_shr_crc16b(0, data, data_nbits)); 8172 } 8173 8174 /* 8175 * Function: 8176 * _soc_th_alpm_lpm_hash_create 8177 * Purpose: 8178 * Create an empty hash table 8179 * Parameters: 8180 * unit - Device unit 8181 * entry_count - Limit for number of entries in table 8182 * index_count - Hash index max + 1. (index_count <= count) 8183 * fb_lpm_hash_ptr - Return pointer (handle) to new Hash Table 8184 * Returns: 8185 * SOC_E_NONE Success 8186 * SOC_E_MEMORY Out of memory (system allocator) 8187 */ 8188 8189 static 8190 int _soc_th_alpm_lpm_hash_create(int unit, 8191 int entry_count, 8192 int index_count, 8193 _soc_th_alpm_lpm_hash_t **fb_lpm_hash_ptr) 8194 { 8195 _soc_th_alpm_lpm_hash_t *hash; 8196 int index; 8197 8198 if (index_count > entry_count) { 8199 return SOC_E_MEMORY; 8200 } 8201 hash = sal_alloc(sizeof (_soc_th_alpm_lpm_hash_t), "lpm_hash"); 8202 if (hash == NULL) { 8203 return SOC_E_MEMORY; 8204 } 8205 8206 sal_memset(hash, 0, sizeof (*hash)); 8207 8208 hash->unit = unit; 8209 hash->entry_count = entry_count; 8210 hash->index_count = index_count; 8211 8212 /* 8213 * Pre-allocate the hash table storage. 8214 */ 8215 hash->table = sal_alloc(hash->index_count * sizeof(*(hash->table)), 8216 "hash_table"); 8217 8218 if (hash->table == NULL) { 8219 sal_free(hash); 8220 return SOC_E_MEMORY; 8221 } 8222 /* 8223 * In case where all the entries should hash into the same bucket 8224 * this will prevent the hash table overflow 8225 */ 8226 hash->link_table = sal_alloc( 8227 hash->entry_count * sizeof(*(hash->link_table)), 8228 "link_table"); 8229 if (hash->link_table == NULL) { 8230 sal_free(hash->table); 8231 sal_free(hash); 8232 return SOC_E_MEMORY; 8233 } 8234 8235 /* 8236 * Set the entries in the hash table to TD2_ALPM_HASH_INDEX_NULL 8237 * Link the entries beyond hash->index_max for handling collisions 8238 */ 8239 for(index = 0; index < hash->index_count; index++) { 8240 hash->table[index] = TD2_ALPM_HASH_INDEX_NULL; 8241 } 8242 for(index = 0; index < hash->entry_count; index++) { 8243 hash->link_table[index] = TD2_ALPM_HASH_INDEX_NULL; 8244 } 8245 *fb_lpm_hash_ptr = hash; 8246 return SOC_E_NONE; 8247 } 8248 8249 /* 8250 * Function: 8251 * _soc_th_alpm_lpm_hash_destroy 8252 * Purpose: 8253 * Destroy the hash table 8254 * Parameters: 8255 * fb_lpm_hash - Pointer (handle) to Hash Table 8256 * Returns: 8257 * SOC_E_NONE Success 8258 */ 8259 static 8260 int _soc_th_alpm_lpm_hash_destroy(_soc_th_alpm_lpm_hash_t *fb_lpm_hash) 8261 { 8262 if (fb_lpm_hash != NULL) { 8263 sal_free(fb_lpm_hash->table); 8264 sal_free(fb_lpm_hash->link_table); 8265 sal_free(fb_lpm_hash); 8266 } 8267 8268 return SOC_E_NONE; 8269 } 8270 8271 /* 8272 * Function: 8273 * _soc_th_alpm_lpm_hash_lookup 8274 * Purpose: 8275 * Look up a key in the hash table 8276 * Parameters: 8277 * hash - Pointer (handle) to Hash Table 8278 * key_cmp_fn - Compare function which should compare key 8279 * entry - The key to lookup 8280 * pfx - Prefix length for lookup acceleration. 8281 * key_index - (OUT) Index where the key was found. 8282 * Returns: 8283 * SOC_E_NONE Key found 8284 * SOC_E_NOT_FOUND Key not found 8285 */ 8286 8287 static 8288 int _soc_th_alpm_lpm_hash_lookup(_soc_th_alpm_lpm_hash_t *hash, 8289 _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn, 8290 _soc_th_alpm_lpm_hash_entry_t entry, 8291 int pfx, 8292 uint16 *key_index) 8293 { 8294 int u = hash->unit, v, i = 0; 8295 8296 uint16 hash_val; 8297 uint16 index; 8298 8299 hash_val = _soc_th_alpm_lpm_hash_compute((uint8 *)entry, 8300 (32 * 5)) % hash->index_count; 8301 index = hash->table[hash_val]; 8302 H_INDEX_MATCH("lhash", entry[0], hash_val); 8303 H_INDEX_MATCH("lkup ", entry[0], index); 8304 while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) { 8305 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 8306 _soc_th_alpm_lpm_hash_entry_t r_entry; 8307 int rindex; 8308 8309 rindex = (index & TD2_ALPM_HASH_INDEX_MASK) >> 1; 8310 /* 8311 * Check prefix length and skip index if not valid for given length 8312 if ((SOC_ALPM_LPM_STATE_START(u, pfx) <= rindex) && 8313 (SOC_ALPM_LPM_STATE_END(u, pfx) >= rindex)) { 8314 */ 8315 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm, 8316 MEM_BLOCK_ANY, rindex, e)); 8317 SOC_FB_LPM_HASH_ENTRY_GET(u, e, index, r_entry, &v); 8318 if (v == 0) { 8319 LOG_ERROR(BSL_LS_SOC_ALPM, 8320 (BSL_META_U(u, 8321 "Empty entry[%d] in link_table. hash_val %d ridx %d \n"), 8322 index, hash_val, rindex)); 8323 } 8324 if ((*key_cmp_fn)(entry, r_entry) == 0) { 8325 *key_index = (index & TD2_ALPM_HASH_INDEX_MASK) >> 8326 ((index & TD2_ALPM_HASH_IPV6_MASK) ? 1 : 0); 8327 H_INDEX_MATCH("found", entry[0], index); 8328 return(SOC_E_NONE); 8329 } 8330 /* 8331 } 8332 */ 8333 index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK]; 8334 H_INDEX_MATCH("lkup1", entry[0], index); 8335 } 8336 if (i > hash->entry_count) { 8337 LOG_ERROR(BSL_LS_SOC_ALPM, 8338 (BSL_META_U(u, 8339 "Hash loop\n"))); 8340 } 8341 H_INDEX_MATCH("not_found", entry[0], index); 8342 return(SOC_E_NOT_FOUND); 8343 } 8344 8345 /* 8346 * Function: 8347 * _soc_th_alpm_lpm_hash_insert 8348 * Purpose: 8349 * Insert/Update a key index in the hash table 8350 * Parameters: 8351 * hash - Pointer (handle) to Hash Table 8352 * key_cmp_fn - Compare function which should compare key 8353 * entry - The key to lookup 8354 * pfx - Prefix length for lookup acceleration. 8355 * old_index - Index where the key was moved from. 8356 * TD2_ALPM_HASH_INDEX_NULL if new entry. 8357 * new_index - Index where the key was moved to. 8358 * Returns: 8359 * SOC_E_NONE Key found 8360 */ 8361 /* 8362 * Should be caled before updating the LPM table so that the 8363 * data in the hash table is consistent with the LPM table 8364 */ 8365 static 8366 int _soc_th_alpm_lpm_hash_insert(_soc_th_alpm_lpm_hash_t *hash, 8367 _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn, 8368 _soc_th_alpm_lpm_hash_entry_t entry, 8369 int pfx, 8370 uint16 old_index, 8371 uint16 new_index, 8372 uint32 *rvt_index) 8373 { 8374 8375 #define INDEX_ADD(hash, hash_idx, new_idx) \ 8376 hash->link_table[new_idx & TD2_ALPM_HASH_INDEX_MASK] = \ 8377 hash->table[hash_idx]; \ 8378 hash->table[hash_idx] = new_idx 8379 8380 #define INDEX_ADD_LINK(hash, t_index, new_idx) \ 8381 hash->link_table[new_idx & TD2_ALPM_HASH_INDEX_MASK] = \ 8382 hash->link_table[t_index & TD2_ALPM_HASH_INDEX_MASK]; \ 8383 hash->link_table[t_index & TD2_ALPM_HASH_INDEX_MASK] = new_idx 8384 8385 #define INDEX_UPDATE(hash, hash_idx, old_idx, new_idx) \ 8386 hash->table[hash_idx] = new_idx; \ 8387 hash->link_table[new_idx & TD2_ALPM_HASH_INDEX_MASK] = \ 8388 hash->link_table[old_idx & TD2_ALPM_HASH_INDEX_MASK]; \ 8389 hash->link_table[old_idx & TD2_ALPM_HASH_INDEX_MASK] = TD2_ALPM_HASH_INDEX_NULL 8390 8391 #define INDEX_UPDATE_LINK(hash, prev_idx, old_idx, new_idx) \ 8392 hash->link_table[prev_idx & TD2_ALPM_HASH_INDEX_MASK] = new_idx; \ 8393 hash->link_table[new_idx & TD2_ALPM_HASH_INDEX_MASK] = \ 8394 hash->link_table[old_idx & TD2_ALPM_HASH_INDEX_MASK]; \ 8395 hash->link_table[old_idx & TD2_ALPM_HASH_INDEX_MASK] = TD2_ALPM_HASH_INDEX_NULL 8396 8397 8398 int u = hash->unit, v, i = 0; 8399 8400 uint16 hash_val; 8401 uint16 index; 8402 uint16 prev_index; 8403 8404 if (rvt_index) { 8405 *rvt_index = TD2_ALPM_HASH_INDEX_NULL; 8406 } 8407 hash_val = _soc_th_alpm_lpm_hash_compute((uint8 *)entry, 8408 (32 * 5)) % hash->index_count; 8409 index = hash->table[hash_val]; 8410 H_INDEX_MATCH("ihash", entry[0], hash_val); 8411 H_INDEX_MATCH("ins ", entry[0], new_index); 8412 H_INDEX_MATCH("ins1 ", index, new_index); 8413 prev_index = TD2_ALPM_HASH_INDEX_NULL; 8414 if (old_index != TD2_ALPM_HASH_INDEX_NULL) { 8415 while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) { 8416 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 8417 _soc_th_alpm_lpm_hash_entry_t r_entry; 8418 int rindex; 8419 8420 rindex = (index & TD2_ALPM_HASH_INDEX_MASK) >> 1; 8421 8422 /* 8423 * Check prefix length and skip index if not valid for given length 8424 if ((SOC_ALPM_LPM_STATE_START(u, pfx) <= rindex) && 8425 (SOC_ALPM_LPM_STATE_END(u, pfx) >= rindex)) { 8426 */ 8427 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY, 8428 rindex, e)); 8429 SOC_FB_LPM_HASH_ENTRY_GET(u, e, index, r_entry, &v); 8430 if (v == 0) { 8431 if ((index & TD2_ALPM_HASH_IPV6_MASK) || 8432 !((new_index & 1) && (new_index == (index + 1)))) { 8433 LOG_ERROR(BSL_LS_SOC_ALPM, 8434 (BSL_META_U(u, 8435 "Empty entry[%d] in link_table. hash_val %d ridx %d nidx %d\n"), 8436 index, hash_val, rindex, new_index)); 8437 } 8438 } 8439 if (v && ((*key_cmp_fn)(entry, r_entry) == 0)) { 8440 /* assert(old_index == index);*/ 8441 if (new_index != index) { 8442 H_INDEX_MATCH("imove", prev_index, new_index); 8443 if (prev_index == TD2_ALPM_HASH_INDEX_NULL) { 8444 INDEX_UPDATE(hash, hash_val, index, new_index); 8445 } else { 8446 INDEX_UPDATE_LINK(hash, prev_index, index, new_index); 8447 } 8448 } 8449 if (rvt_index) { 8450 *rvt_index = index; 8451 } 8452 H_INDEX_MATCH("imtch", index, new_index); 8453 return(SOC_E_NONE); 8454 } 8455 /* 8456 } 8457 */ 8458 prev_index = index; 8459 index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK]; 8460 H_INDEX_MATCH("ins2 ", index, new_index); 8461 } 8462 } 8463 if (i > hash->entry_count) { 8464 LOG_ERROR(BSL_LS_SOC_ALPM, 8465 (BSL_META_U(u, 8466 "Hash loop\n"))); 8467 return SOC_E_INTERNAL; 8468 } 8469 INDEX_ADD(hash, hash_val, new_index); /* new entry */ 8470 return(SOC_E_NONE); 8471 } 8472 8473 /* 8474 * Function: 8475 * _soc_th_alpm_lpm_hash_delete 8476 * Purpose: 8477 * Delete a key index in the hash table 8478 * Parameters: 8479 * hash - Pointer (handle) to Hash Table 8480 * key_cmp_fn - Compare function which should compare key 8481 * entry - The key to delete 8482 * pfx - Prefix length for lookup acceleration. 8483 * delete_index - Index to delete. 8484 * Returns: 8485 * SOC_E_NONE Success 8486 * SOC_E_NOT_FOUND Key index not found. 8487 */ 8488 static 8489 int _soc_th_alpm_lpm_hash_delete(_soc_th_alpm_lpm_hash_t *hash, 8490 _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn, 8491 _soc_th_alpm_lpm_hash_entry_t entry, 8492 int pfx, 8493 uint16 delete_index) 8494 { 8495 int u = hash->unit, i = 0; 8496 uint16 hash_val; 8497 uint16 index; 8498 uint16 prev_index; 8499 8500 hash_val = _soc_th_alpm_lpm_hash_compute((uint8 *)entry, 8501 (32 * 5)) % hash->index_count; 8502 index = hash->table[hash_val]; 8503 H_INDEX_MATCH("dhash", entry[0], hash_val); 8504 H_INDEX_MATCH("del ", entry[0], index); 8505 prev_index = TD2_ALPM_HASH_INDEX_NULL; 8506 while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) { 8507 if (delete_index == index) { 8508 H_INDEX_MATCH("dfoun", entry[0], index); 8509 if (prev_index == TD2_ALPM_HASH_INDEX_NULL) { 8510 INDEX_DELETE(hash, hash_val, delete_index); 8511 } else { 8512 INDEX_DELETE_LINK(hash, prev_index, delete_index); 8513 } 8514 return(SOC_E_NONE); 8515 } 8516 prev_index = index; 8517 index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK]; 8518 H_INDEX_MATCH("del1 ", entry[0], index); 8519 } 8520 if (i > hash->entry_count) { 8521 LOG_ERROR(BSL_LS_SOC_ALPM, 8522 (BSL_META_U(u, 8523 "Hash loop\n"))); 8524 } 8525 return(SOC_E_NOT_FOUND); 8526 } 8527 8528 static 8529 int _soc_th_alpm_lpm_hash_revert(_soc_th_alpm_lpm_hash_t *hash, 8530 _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn, 8531 _soc_th_alpm_lpm_hash_entry_t entry, 8532 uint16 new_index, 8533 uint32 rvt_index) 8534 { 8535 int u = hash->unit, i = 0; 8536 uint16 hash_val; 8537 uint16 index; 8538 uint16 prev_index; 8539 8540 hash_val = _soc_th_alpm_lpm_hash_compute((uint8 *)entry, 8541 (32 * 5)) % hash->index_count; 8542 index = hash->table[hash_val]; 8543 H_INDEX_MATCH("rhash", entry[0], hash_val); 8544 H_INDEX_MATCH("rvt ", entry[0], index); 8545 prev_index = TD2_ALPM_HASH_INDEX_NULL; 8546 while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) { 8547 if (new_index == index) { 8548 H_INDEX_MATCH("dfoun", entry[0], index); 8549 if (rvt_index == TD2_ALPM_HASH_INDEX_NULL) { 8550 if (prev_index == TD2_ALPM_HASH_INDEX_NULL) { 8551 INDEX_DELETE(hash, hash_val, new_index); 8552 } else { 8553 INDEX_DELETE_LINK(hash, prev_index, new_index); 8554 } 8555 } else { 8556 if (prev_index == TD2_ALPM_HASH_INDEX_NULL) { 8557 INDEX_UPDATE(hash, hash_val, new_index, rvt_index); 8558 } else { 8559 INDEX_UPDATE_LINK(hash, prev_index, new_index, rvt_index); 8560 } 8561 } 8562 return(SOC_E_NONE); 8563 } 8564 prev_index = index; 8565 index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK]; 8566 H_INDEX_MATCH("rvt1 ", entry[0], index); 8567 } 8568 if (i > hash->entry_count) { 8569 LOG_ERROR(BSL_LS_SOC_ALPM, 8570 (BSL_META_U(u, 8571 "Hash loop\n"))); 8572 } 8573 return(SOC_E_NOT_FOUND); 8574 } 8575 8576 8577 /* 8578 * Function: 8579 * _soc_th_alpm_lpm_hash_verify 8580 * Purpose: 8581 * Verify a key index in the hash table 8582 * Parameters: 8583 * hash - Pointer (handle) to Hash Table 8584 * key_cmp_fn - Compare function which should compare key 8585 * entry - The key to delete 8586 * pfx - Prefix length for lookup acceleration. 8587 * verify_index - Index to verify. 8588 * Returns: 8589 * SOC_E_NONE Success 8590 * SOC_E_NOT_FOUND Key index not found. 8591 */ 8592 static 8593 int _soc_th_alpm_lpm_hash_verify(_soc_th_alpm_lpm_hash_t *hash, 8594 _soc_th_alpm_lpm_hash_compare_fn key_cmp_fn, 8595 _soc_th_alpm_lpm_hash_entry_t entry, 8596 int pfx, 8597 uint16 verify_index) 8598 { 8599 int u = hash->unit, i = 0; 8600 uint16 hash_val; 8601 uint16 index; 8602 8603 hash_val = _soc_th_alpm_lpm_hash_compute((uint8 *)entry, 8604 (32 * 5)) % hash->index_count; 8605 index = hash->table[hash_val]; 8606 H_INDEX_MATCH("vhash", entry[0], hash_val); 8607 H_INDEX_MATCH("veri ", entry[0], index); 8608 while(index != TD2_ALPM_HASH_INDEX_NULL && i++ < hash->entry_count) { 8609 if (verify_index == index) { 8610 H_INDEX_MATCH("vfoun", entry[0], index); 8611 return(SOC_E_NONE); 8612 } 8613 index = hash->link_table[index & TD2_ALPM_HASH_INDEX_MASK]; 8614 H_INDEX_MATCH("veri1", entry[0], index); 8615 } 8616 if (i > hash->entry_count) { 8617 LOG_ERROR(BSL_LS_SOC_ALPM, 8618 (BSL_META_U(u, 8619 "Hash loop\n"))); 8620 } 8621 return(SOC_E_NOT_FOUND); 8622 } 8623 #else 8624 #define LPM_HASH_INSERT(u, entry_data, tab_index, rvt_index0, rvt_index1) 8625 #define LPM_HASH_REVERT(u, entry_data, tab_index, rvt_index0, rvt_index1) 8626 #define LPM_HASH_DELETE(u, key_data, tab_index) 8627 #define LPM_HASH_LOOKUP(u, key_data, pfx, tab_index) 8628 #define LPM_HASH_VERIFY(u, key_data, tab_index) 8629 #endif /* FB_LPM_HASH_SUPPORT */ 8630 8631 /* src and dst can be same */ 8632 #define _COPY_FIELD32(src_fld, dst_fld) \ 8633 do { \ 8634 uint32 val; \ 8635 val = soc_mem_field32_get(u, mem, src, src_fld); \ 8636 soc_mem_field32_set(u, mem, dst, dst_fld, val); \ 8637 } while (0) 8638 8639 #define _COPY_FIELD(src_fld, dst_fld) \ 8640 do { \ 8641 uint32 vals[5]; \ 8642 sal_memset(vals, 0, sizeof(vals)); \ 8643 soc_mem_field_get(u, mem, src, src_fld, vals); \ 8644 soc_mem_field_set(u, mem, dst, dst_fld, vals); \ 8645 } while (0) 8646 8647 int 8648 soc_th_alpm_lpm_ip4entry0_to_0(int u, void *src, void *dst, int copy_hit) 8649 { 8650 soc_mem_t mem = L3_DEFIPm; 8651 8652 _COPY_FIELD32(VALID0f, VALID0f); 8653 _COPY_FIELD32(ALG_BKT_PTR0f, ALG_BKT_PTR0f); 8654 _COPY_FIELD32(GLOBAL_HIGH0f, GLOBAL_HIGH0f); 8655 _COPY_FIELD32(ALG_HIT_IDX0f, ALG_HIT_IDX0f); 8656 _COPY_FIELD32(ENTRY_VIEW0f, ENTRY_VIEW0f); 8657 if (ALPM_CTRL(u).bkt_sharing) { 8658 _COPY_FIELD32(ALG_SUB_BKT_PTR0f, ALG_SUB_BKT_PTR0f); 8659 } 8660 if (soc_feature(u, soc_feature_ipmc_defip)) { 8661 if (soc_mem_field_valid(u, mem, MULTICAST_ROUTE0f)) { 8662 _COPY_FIELD32(MULTICAST_ROUTE0f, MULTICAST_ROUTE0f); 8663 } 8664 } 8665 if (copy_hit) { 8666 _COPY_FIELD32(HIT0f, HIT0f); 8667 } 8668 8669 _COPY_FIELD(KEY0f, KEY0f); 8670 _COPY_FIELD(MASK0f, MASK0f); 8671 _COPY_FIELD(REPLACE_DATA0f, REPLACE_DATA0f); 8672 8673 if (soc_mem_field_valid(u, mem, DATA_TYPE0f)) { 8674 _COPY_FIELD(DATA_TYPE0f, DATA_TYPE0f); 8675 } 8676 8677 return(SOC_E_NONE); 8678 } 8679 8680 int 8681 soc_th_alpm_lpm_ip4entry1_to_1(int u, void *src, void *dst, int copy_hit) 8682 { 8683 soc_mem_t mem = L3_DEFIPm; 8684 8685 _COPY_FIELD32(VALID1f, VALID1f); 8686 _COPY_FIELD32(ALG_BKT_PTR1f, ALG_BKT_PTR1f); 8687 _COPY_FIELD32(GLOBAL_HIGH1f, GLOBAL_HIGH1f); 8688 _COPY_FIELD32(ALG_HIT_IDX1f, ALG_HIT_IDX1f); 8689 _COPY_FIELD32(ENTRY_VIEW1f, ENTRY_VIEW1f); 8690 if (ALPM_CTRL(u).bkt_sharing) { 8691 _COPY_FIELD32(ALG_SUB_BKT_PTR1f, ALG_SUB_BKT_PTR1f); 8692 } 8693 if (soc_feature(u, soc_feature_ipmc_defip)) { 8694 if (soc_mem_field_valid(u, mem, MULTICAST_ROUTE1f)) { 8695 _COPY_FIELD32(MULTICAST_ROUTE1f, MULTICAST_ROUTE1f); 8696 } 8697 } 8698 if (copy_hit) { 8699 _COPY_FIELD32(HIT1f, HIT1f); 8700 } 8701 8702 _COPY_FIELD(KEY1f, KEY1f); 8703 _COPY_FIELD(MASK1f, MASK1f); 8704 _COPY_FIELD(REPLACE_DATA1f, REPLACE_DATA1f); 8705 8706 if (soc_mem_field_valid(u, mem, DATA_TYPE1f)) { 8707 _COPY_FIELD(DATA_TYPE1f, DATA_TYPE1f); 8708 } 8709 8710 return(SOC_E_NONE); 8711 } 8712 8713 /* src and dst can be same */ 8714 int 8715 soc_th_alpm_lpm_ip4entry0_to_1(int u, void *src, void *dst, int copy_hit) 8716 { 8717 soc_mem_t mem = L3_DEFIPm; 8718 8719 _COPY_FIELD32(VALID0f, VALID1f); 8720 _COPY_FIELD32(ALG_BKT_PTR0f, ALG_BKT_PTR1f); 8721 _COPY_FIELD32(GLOBAL_HIGH0f, GLOBAL_HIGH1f); 8722 _COPY_FIELD32(ALG_HIT_IDX0f, ALG_HIT_IDX1f); 8723 _COPY_FIELD32(ENTRY_VIEW0f, ENTRY_VIEW1f); 8724 if (ALPM_CTRL(u).bkt_sharing) { 8725 _COPY_FIELD32(ALG_SUB_BKT_PTR0f, ALG_SUB_BKT_PTR1f); 8726 } 8727 if (soc_feature(u, soc_feature_ipmc_defip)) { 8728 if (soc_mem_field_valid(u, mem, MULTICAST_ROUTE1f)) { 8729 _COPY_FIELD32(MULTICAST_ROUTE0f, MULTICAST_ROUTE1f); 8730 } 8731 } 8732 if (copy_hit) { 8733 _COPY_FIELD32(HIT0f, HIT1f); 8734 } 8735 8736 _COPY_FIELD(KEY0f, KEY1f); 8737 _COPY_FIELD(MASK0f, MASK1f); 8738 _COPY_FIELD(REPLACE_DATA0f, REPLACE_DATA1f); 8739 8740 if (soc_mem_field_valid(u, mem, DATA_TYPE0f)) { 8741 _COPY_FIELD(DATA_TYPE0f, DATA_TYPE1f); 8742 } 8743 8744 return(SOC_E_NONE); 8745 } 8746 8747 /* src and dst can be same */ 8748 int 8749 soc_th_alpm_lpm_ip4entry1_to_0(int u, void *src, void *dst, int copy_hit) 8750 { 8751 soc_mem_t mem = L3_DEFIPm; 8752 8753 _COPY_FIELD32(VALID1f, VALID0f); 8754 _COPY_FIELD32(ALG_BKT_PTR1f, ALG_BKT_PTR0f); 8755 _COPY_FIELD32(GLOBAL_HIGH1f, GLOBAL_HIGH0f); 8756 _COPY_FIELD32(ALG_HIT_IDX1f, ALG_HIT_IDX0f); 8757 _COPY_FIELD32(ENTRY_VIEW1f, ENTRY_VIEW0f); 8758 if (ALPM_CTRL(u).bkt_sharing) { 8759 _COPY_FIELD32(ALG_SUB_BKT_PTR1f, ALG_SUB_BKT_PTR0f); 8760 } 8761 if (soc_feature(u, soc_feature_ipmc_defip)) { 8762 if (soc_mem_field_valid(u, mem, MULTICAST_ROUTE1f)) { 8763 _COPY_FIELD32(MULTICAST_ROUTE1f, MULTICAST_ROUTE0f); 8764 } 8765 } 8766 if (copy_hit) { 8767 _COPY_FIELD32(HIT1f, HIT0f); 8768 } 8769 8770 _COPY_FIELD(KEY1f, KEY0f); 8771 _COPY_FIELD(MASK1f, MASK0f); 8772 _COPY_FIELD(REPLACE_DATA1f, REPLACE_DATA0f); 8773 8774 if (soc_mem_field_valid(u, mem, DATA_TYPE0f)) { 8775 _COPY_FIELD(DATA_TYPE1f, DATA_TYPE0f); 8776 } 8777 8778 return(SOC_E_NONE); 8779 } 8780 8781 void 8782 soc_th_alpm_lpm_state_dump(int u) 8783 { 8784 int i; 8785 int max_pfx_len; 8786 max_pfx_len = ALPM_MAX_PFX_INDEX; 8787 8788 #ifndef BCM_WARM_BOOT_SUPPORT_SW_DUMP 8789 if (!bsl_check(bslLayerSoc, bslSourceAlpm, bslSeverityVerbose, u)) { 8790 return; 8791 } 8792 #endif 8793 8794 for(i = max_pfx_len; i >= 0 ; i--) { 8795 if ((i != ALPM_MAX_PFX_INDEX) && (SOC_ALPM_LPM_STATE_START(u, i) == -1)) { 8796 continue; 8797 } 8798 8799 #ifdef ALPM_WARM_BOOT_DEBUG 8800 LOG_ERROR(BSL_LS_SOC_ALPM, 8801 (BSL_META_U(u, 8802 "PFX = %d P = %d N = %d START = %d END = %d VENT = %d FENT = %d\n"), 8803 i, 8804 SOC_ALPM_LPM_STATE_PREV(u, i), 8805 SOC_ALPM_LPM_STATE_NEXT(u, i), 8806 SOC_ALPM_LPM_STATE_START(u, i), 8807 SOC_ALPM_LPM_STATE_END(u, i), 8808 SOC_ALPM_LPM_STATE_VENT(u, i), 8809 SOC_ALPM_LPM_STATE_FENT(u, i))); 8810 #else 8811 LOG_VERBOSE(BSL_LS_SOC_ALPM, 8812 (BSL_META_U(u, 8813 "PFX = %d P = %d N = %d START = %d END = %d VENT = %d FENT = %d\n"), 8814 i, 8815 SOC_ALPM_LPM_STATE_PREV(u, i), 8816 SOC_ALPM_LPM_STATE_NEXT(u, i), 8817 SOC_ALPM_LPM_STATE_START(u, i), 8818 SOC_ALPM_LPM_STATE_END(u, i), 8819 SOC_ALPM_LPM_STATE_VENT(u, i), 8820 SOC_ALPM_LPM_STATE_FENT(u, i))); 8821 #endif 8822 } 8823 } 8824 8825 /* 8826 * Create a slot for the new entry rippling the entries if required 8827 */ 8828 static 8829 int _lpm_fb_entry_shift(int u, int from_ent, int to_ent) 8830 { 8831 uint32 e[SOC_MAX_MEM_FIELD_WORDS], e_urpf[SOC_MAX_MEM_FIELD_WORDS]; 8832 uint32 rvt_index0 = 0, rvt_index1 = 0; 8833 int src_default = 0, src_discard = 0; 8834 int src_tcam_offset = 0; 8835 int rv; 8836 #ifdef FB_LPM_TABLE_CACHED 8837 SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, L3_DEFIPm, 8838 MEM_BLOCK_ANY, from_ent)); 8839 #endif /* FB_LPM_TABLE_CACHED */ 8840 8841 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm, 8842 MEM_BLOCK_ANY, from_ent, e)); 8843 if (SOC_URPF_STATUS_GET(u)) { 8844 if (soc_feature(u, soc_feature_l3_defip_hole)) { 8845 src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1); 8846 } else if (SOC_IS_APOLLO(u)) { 8847 src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1) + 0x0400; 8848 } else { 8849 src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1); 8850 } 8851 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm, 8852 MEM_BLOCK_ANY, 8853 from_ent + src_tcam_offset, 8854 e_urpf)); 8855 src_default = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, RPE0f) | 8856 (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, RPE1f) << 1); 8857 src_discard = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, SRC_DISCARD0f) | 8858 (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, SRC_DISCARD1f) << 1); 8859 } 8860 8861 LPM_HASH_INSERT(u, e, to_ent, &rvt_index0, &rvt_index1); 8862 rv = _soc_th_alpm_write_pivot(u, MEM_BLOCK_ANY, to_ent, from_ent, e, src_default, src_discard); 8863 if (rv < 0) { 8864 LPM_HASH_REVERT(u, e, to_ent, rvt_index0, rvt_index1); 8865 return rv; 8866 } 8867 8868 SOC_ALPM_MOVE_PIVOT_FULL(u, from_ent, to_ent); 8869 8870 return (SOC_E_NONE); 8871 } 8872 8873 8874 /* 8875 * Shift prefix entries 1 entry UP, while preserving 8876 * last half empty IPv4 entry if any. 8877 */ 8878 static 8879 int _lpm_fb_shift_pfx_up(int u, int pfx, int ipv6) 8880 { 8881 uint32 e[SOC_MAX_MEM_FIELD_WORDS], e_urpf[SOC_MAX_MEM_FIELD_WORDS]; 8882 int from_ent; 8883 int to_ent; 8884 uint32 v0, v1; 8885 uint32 rvt_index0 = 0, rvt_index1 = 0; 8886 int rv; 8887 int src_default = 0, src_discard = 0; 8888 int src_tcam_offset = 0; 8889 8890 if (SOC_URPF_STATUS_GET(u)) { 8891 if (soc_feature(u, soc_feature_l3_defip_hole)) { 8892 src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1); 8893 } else if (SOC_IS_APOLLO(u)) { 8894 src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1) + 0x0400; 8895 } else { 8896 src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1); 8897 } 8898 } 8899 8900 to_ent = SOC_ALPM_LPM_STATE_END(u, pfx) + 1; 8901 8902 ipv6 = SOC_ALPM_PFX_IS_V6_64(u, pfx); 8903 if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity) && !ipv6) { 8904 from_ent = SOC_ALPM_LPM_STATE_END(u, pfx); 8905 #ifdef FB_LPM_TABLE_CACHED 8906 SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, L3_DEFIPm, 8907 MEM_BLOCK_ANY, from_ent)); 8908 #endif /* FB_LPM_TABLE_CACHED */ 8909 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm, 8910 MEM_BLOCK_ANY, from_ent, e)); 8911 if (SOC_URPF_STATUS_GET(u)) { 8912 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm, 8913 MEM_BLOCK_ANY, 8914 from_ent + src_tcam_offset, 8915 e_urpf)); 8916 src_default = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, RPE0f) | 8917 (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, RPE1f) << 1); 8918 src_discard = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, SRC_DISCARD0f) | 8919 (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, SRC_DISCARD1f) << 1); 8920 } 8921 8922 v0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f); 8923 v1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f); 8924 8925 if ((v0 == 0) || (v1 == 0)) { 8926 /* Last entry is half full -> keep it last. */ 8927 LPM_HASH_INSERT(u, e, to_ent, &rvt_index0, &rvt_index1); 8928 rv = _soc_th_alpm_write_pivot(u, MEM_BLOCK_ANY, to_ent, from_ent, e, 8929 src_default, src_discard); 8930 if (rv < 0) { 8931 LPM_HASH_REVERT(u, e, to_ent, rvt_index0, rvt_index1); 8932 return rv; 8933 } 8934 8935 /* track pivot state movement */ 8936 SOC_ALPM_MOVE_PIVOT_HALF(u, v1, from_ent, to_ent); 8937 to_ent--; 8938 } 8939 } 8940 8941 from_ent = SOC_ALPM_LPM_STATE_START(u, pfx); 8942 if (from_ent != to_ent) { 8943 SOC_IF_ERROR_RETURN(_lpm_fb_entry_shift(u, from_ent, to_ent)); 8944 VRF_PIVOT_SHIFT_INC(u, MAX_VRF_ID, ipv6); 8945 } 8946 SOC_ALPM_LPM_STATE_START(u, pfx) += 1; 8947 SOC_ALPM_LPM_STATE_END(u, pfx) += 1; 8948 return (SOC_E_NONE); 8949 } 8950 8951 /* 8952 * Shift prefix entries 1 entry DOWN, while preserving 8953 * last half empty IPv4 entry if any. 8954 */ 8955 static 8956 int _lpm_fb_shift_pfx_down(int u, int pfx, int ipv6) 8957 { 8958 uint32 e[SOC_MAX_MEM_FIELD_WORDS], e_urpf[SOC_MAX_MEM_FIELD_WORDS]; 8959 int from_ent; 8960 int to_ent; 8961 int prev_ent; 8962 uint32 v0, v1; 8963 uint32 rvt_index0 = 0, rvt_index1 = 0; 8964 int rv; 8965 int src_default = 0, src_discard = 0; 8966 int src_tcam_offset = 0; 8967 8968 if (SOC_URPF_STATUS_GET(u)) { 8969 if (soc_feature(u, soc_feature_l3_defip_hole)) { 8970 src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1); 8971 } else if (SOC_IS_APOLLO(u)) { 8972 src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1) + 0x0400; 8973 } else { 8974 src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1); 8975 } 8976 } 8977 8978 to_ent = SOC_ALPM_LPM_STATE_START(u, pfx) - 1; 8979 8980 /* Don't move empty prefix . */ 8981 if (SOC_ALPM_LPM_STATE_VENT(u, pfx) == 0) { 8982 SOC_ALPM_LPM_STATE_START(u, pfx) = to_ent; 8983 SOC_ALPM_LPM_STATE_END(u, pfx) = to_ent - 1; 8984 return (SOC_E_NONE); 8985 } 8986 ipv6 = SOC_ALPM_PFX_IS_V6_64(u, pfx); 8987 8988 if ((!ipv6) && (SOC_ALPM_LPM_STATE_END(u, pfx) != SOC_ALPM_LPM_STATE_START(u, pfx))) { 8989 8990 from_ent = SOC_ALPM_LPM_STATE_END(u, pfx); 8991 8992 #ifdef FB_LPM_TABLE_CACHED 8993 SOC_IF_ERROR_RETURN(soc_mem_cache_invalidate(u, L3_DEFIPm, 8994 MEM_BLOCK_ANY, from_ent)); 8995 #endif /* FB_LPM_TABLE_CACHED */ 8996 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm, 8997 MEM_BLOCK_ANY, from_ent, e)); 8998 if (SOC_URPF_STATUS_GET(u)) { 8999 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm, 9000 MEM_BLOCK_ANY, 9001 from_ent + src_tcam_offset, 9002 e_urpf)); 9003 src_default = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, RPE0f) | 9004 (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, RPE1f) << 1); 9005 src_discard = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, SRC_DISCARD0f) | 9006 (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e_urpf, SRC_DISCARD1f) << 1); 9007 } 9008 9009 v0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f); 9010 v1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f); 9011 9012 if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity) && 9013 ((v0 == 0) || (v1 == 0))) { 9014 /* Last entry is half full -> keep it last. */ 9015 /* Shift entry before last to start - 1 position. */ 9016 prev_ent = from_ent - 1; 9017 SOC_IF_ERROR_RETURN(_lpm_fb_entry_shift(u, prev_ent, to_ent)); 9018 VRF_PIVOT_SHIFT_INC(u, MAX_VRF_ID, ipv6); 9019 9020 LPM_HASH_INSERT(u, e, prev_ent, &rvt_index0, &rvt_index1); 9021 rv = _soc_th_alpm_write_pivot(u, MEM_BLOCK_ANY, prev_ent, from_ent, e, 9022 src_default, src_discard); 9023 if (rv < 0) { 9024 LPM_HASH_REVERT(u, e, prev_ent, rvt_index0, rvt_index1); 9025 return rv; 9026 } 9027 SOC_ALPM_MOVE_PIVOT_HALF(u, v1, from_ent, prev_ent); 9028 } else { 9029 /* Last entry is full -> just shift it to start - 1 position. */ 9030 LPM_HASH_INSERT(u, e, to_ent, &rvt_index0, &rvt_index1); 9031 rv = _soc_th_alpm_write_pivot(u, MEM_BLOCK_ANY, to_ent, from_ent, e, 9032 src_default, src_discard); 9033 if (rv < 0) { 9034 LPM_HASH_REVERT(u, e, to_ent, rvt_index0, rvt_index1); 9035 return rv; 9036 } 9037 9038 /* Track full-entry move */ 9039 SOC_ALPM_MOVE_PIVOT_FULL(u, from_ent, to_ent); 9040 } 9041 9042 } else { 9043 9044 from_ent = SOC_ALPM_LPM_STATE_END(u, pfx); 9045 SOC_IF_ERROR_RETURN(_lpm_fb_entry_shift(u, from_ent, to_ent)); 9046 VRF_PIVOT_SHIFT_INC(u, MAX_VRF_ID, ipv6); 9047 9048 } 9049 SOC_ALPM_LPM_STATE_START(u, pfx) -= 1; 9050 SOC_ALPM_LPM_STATE_END(u, pfx) -= 1; 9051 9052 return (SOC_E_NONE); 9053 } 9054 9055 /* 9056 * Create a slot for the new entry rippling the entries if required 9057 */ 9058 static 9059 int _lpm_free_slot_create(int u, int pfx, int ipv6, void *e, int *free_slot) 9060 { 9061 int prev_pfx; 9062 int next_pfx; 9063 int free_pfx; 9064 int curr_pfx; 9065 int from_ent; 9066 uint32 v0, v1; 9067 int rv; 9068 9069 9070 if (SOC_ALPM_LPM_STATE_VENT(u, pfx) == 0) { 9071 /* 9072 * Find the prefix position. Only prefix with valid 9073 * entries are in the list. 9074 * next -> high to low prefix. low to high index 9075 * prev -> low to high prefix. high to low index 9076 * Unused prefix length ALPM_MAX_PFX_INDEX is the head of the 9077 * list and is node corresponding to this is always 9078 * present. 9079 */ 9080 curr_pfx = ALPM_MAX_PFX_INDEX; 9081 if (ALPM_CTRL(u).gp_zoned) { 9082 if (pfx <= ALPM_MAX_VRF_PFX_INDEX) { 9083 curr_pfx = ALPM_MAX_VRF_PFX_INDEX; 9084 } 9085 } 9086 while (SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx) > pfx) { 9087 curr_pfx = SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx); 9088 } 9089 /* Insert the new prefix */ 9090 next_pfx = SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx); 9091 if (next_pfx != -1) { 9092 SOC_ALPM_LPM_STATE_PREV(u, next_pfx) = pfx; 9093 } 9094 SOC_ALPM_LPM_STATE_NEXT(u, pfx) = SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx); 9095 SOC_ALPM_LPM_STATE_PREV(u, pfx) = curr_pfx; 9096 SOC_ALPM_LPM_STATE_NEXT(u, curr_pfx) = pfx; 9097 9098 SOC_ALPM_LPM_STATE_FENT(u, pfx) = (SOC_ALPM_LPM_STATE_FENT(u, curr_pfx) + 1) / 2; 9099 SOC_ALPM_LPM_STATE_FENT(u, curr_pfx) -= SOC_ALPM_LPM_STATE_FENT(u, pfx); 9100 SOC_ALPM_LPM_STATE_START(u, pfx) = SOC_ALPM_LPM_STATE_END(u, curr_pfx) + 9101 SOC_ALPM_LPM_STATE_FENT(u, curr_pfx) + 1; 9102 SOC_ALPM_LPM_STATE_END(u, pfx) = SOC_ALPM_LPM_STATE_START(u, pfx) - 1; 9103 SOC_ALPM_LPM_STATE_VENT(u, pfx) = 0; 9104 } else if (!soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity) && 9105 !ipv6) { 9106 /* For IPv4 Check if alternate entry is free */ 9107 from_ent = SOC_ALPM_LPM_STATE_START(u, pfx); 9108 #ifdef FB_LPM_TABLE_CACHED 9109 if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm, 9110 MEM_BLOCK_ANY, from_ent)) < 0) { 9111 return rv; 9112 } 9113 #endif /* FB_LPM_TABLE_CACHED */ 9114 if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm, 9115 MEM_BLOCK_ANY, from_ent, e)) < 0) { 9116 return rv; 9117 } 9118 v0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f); 9119 v1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f); 9120 9121 if ((v0 == 0) || (v1 == 0)) { 9122 *free_slot = (from_ent << 1) + ((v1 == 0) ? 1 : 0); 9123 return(SOC_E_NONE); 9124 } 9125 9126 from_ent = SOC_ALPM_LPM_STATE_END(u, pfx); 9127 #ifdef FB_LPM_TABLE_CACHED 9128 if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm, 9129 MEM_BLOCK_ANY, from_ent)) < 0) { 9130 return rv; 9131 } 9132 #endif /* FB_LPM_TABLE_CACHED */ 9133 if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm, 9134 MEM_BLOCK_ANY, from_ent, e)) < 0) { 9135 return rv; 9136 } 9137 v0 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID0f); 9138 v1 = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, e, VALID1f); 9139 9140 if ((v0 == 0) || (v1 == 0)) { 9141 *free_slot = (from_ent << 1) + ((v1 == 0) ? 1 : 0); 9142 return(SOC_E_NONE); 9143 } 9144 } 9145 9146 free_pfx = pfx; 9147 while(SOC_ALPM_LPM_STATE_FENT(u, free_pfx) == 0) { 9148 free_pfx = SOC_ALPM_LPM_STATE_NEXT(u, free_pfx); 9149 if (free_pfx == -1) { 9150 /* No free entries on this side try the other side */ 9151 free_pfx = pfx; 9152 break; 9153 } 9154 } 9155 9156 while(SOC_ALPM_LPM_STATE_FENT(u, free_pfx) == 0) { 9157 free_pfx = SOC_ALPM_LPM_STATE_PREV(u, free_pfx); 9158 if (free_pfx == -1) { 9159 if (SOC_ALPM_LPM_STATE_VENT(u, pfx) == 0) { 9160 /* We failed to allocate entries for a newly allocated prefix.*/ 9161 prev_pfx = SOC_ALPM_LPM_STATE_PREV(u, pfx); 9162 next_pfx = SOC_ALPM_LPM_STATE_NEXT(u, pfx); 9163 if (-1 != prev_pfx) { 9164 SOC_ALPM_LPM_STATE_NEXT(u, prev_pfx) = next_pfx; 9165 } 9166 if (-1 != next_pfx) { 9167 SOC_ALPM_LPM_STATE_PREV(u, next_pfx) = prev_pfx; 9168 } 9169 } 9170 return(SOC_E_FULL); 9171 } 9172 } 9173 9174 /* 9175 * Ripple entries to create free space 9176 */ 9177 while (free_pfx > pfx) { 9178 next_pfx = SOC_ALPM_LPM_STATE_NEXT(u, free_pfx); 9179 SOC_IF_ERROR_RETURN(_lpm_fb_shift_pfx_down(u, next_pfx, ipv6)); 9180 SOC_ALPM_LPM_STATE_FENT(u, free_pfx) -= 1; 9181 SOC_ALPM_LPM_STATE_FENT(u, next_pfx) += 1; 9182 free_pfx = next_pfx; 9183 } 9184 9185 while (free_pfx < pfx) { 9186 SOC_IF_ERROR_RETURN(_lpm_fb_shift_pfx_up(u, free_pfx, ipv6)); 9187 SOC_ALPM_LPM_STATE_FENT(u, free_pfx) -= 1; 9188 prev_pfx = SOC_ALPM_LPM_STATE_PREV(u, free_pfx); 9189 SOC_ALPM_LPM_STATE_FENT(u, prev_pfx) += 1; 9190 free_pfx = prev_pfx; 9191 } 9192 9193 SOC_ALPM_LPM_STATE_VENT(u, pfx) += 1; 9194 SOC_ALPM_LPM_STATE_FENT(u, pfx) -= 1; 9195 SOC_ALPM_LPM_STATE_END(u, pfx) += 1; 9196 *free_slot = SOC_ALPM_LPM_STATE_END(u, pfx) << ((ipv6) ? 0 : 1); 9197 #ifdef BCM_TOMAHAWK2_SUPPORT 9198 if (soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) { 9199 *free_slot += (ipv6) ? 0 : 1; 9200 } 9201 #endif 9202 sal_memcpy(e, soc_mem_entry_null(u, L3_DEFIPm), 9203 soc_mem_entry_words(u,L3_DEFIPm) * 4); 9204 9205 return(SOC_E_NONE); 9206 } 9207 9208 /* 9209 * Delete a slot and adjust entry pointers if required. 9210 * e - has the contents of entry at slot(useful for IPV4 only) 9211 */ 9212 static 9213 int _lpm_free_slot_delete(int u, int pfx, int ipv6, void *e, int slot) 9214 { 9215 int prev_pfx; 9216 int next_pfx; 9217 int from_ent; 9218 int to_ent; 9219 uint32 *ef = NULL; 9220 uint32 *ef_urpf = NULL; 9221 uint32 *sf = NULL; 9222 uint32 *st = NULL; 9223 void *et; 9224 int rv; 9225 int src_pivot, bpm_len; 9226 uint32 rvt_index0 = 0, rvt_index1 = 0; 9227 int upper_half = 0; 9228 int src_default = 0, src_discard = 0; 9229 int src_tcam_offset = 0; 9230 9231 ef = sal_alloc(sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS, "buf_tmp"); 9232 if (ef == NULL) { 9233 rv = SOC_E_MEMORY; 9234 goto clean_up; 9235 } 9236 9237 ef_urpf = sal_alloc(sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS, "buf_tmp_urpf"); 9238 if (ef_urpf == NULL) { 9239 rv = SOC_E_MEMORY; 9240 goto clean_up; 9241 } 9242 9243 sf = sal_alloc(sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS, "buf_tmp_from"); 9244 if (sf == NULL) { 9245 rv = SOC_E_MEMORY; 9246 goto clean_up; 9247 } 9248 9249 st = sal_alloc(sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS, "buf_tmp_to"); 9250 if (st == NULL) { 9251 rv = SOC_E_MEMORY; 9252 goto clean_up; 9253 } 9254 9255 if (SOC_URPF_STATUS_GET(u)) { 9256 if (soc_feature(u, soc_feature_l3_defip_hole)) { 9257 src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1); 9258 } else if (SOC_IS_APOLLO(u)) { 9259 src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1) + 0x0400; 9260 } else { 9261 src_tcam_offset = (soc_mem_index_count(u, L3_DEFIPm) >> 1); 9262 } 9263 } 9264 9265 from_ent = SOC_ALPM_LPM_STATE_END(u, pfx); 9266 to_ent = slot; 9267 if (!ipv6) { /* IPV4 */ 9268 to_ent >>= 1; 9269 #ifdef FB_LPM_TABLE_CACHED 9270 if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm, 9271 MEM_BLOCK_ANY, from_ent)) < 0) { 9272 goto clean_up; 9273 } 9274 #endif /* FB_LPM_TABLE_CACHED */ 9275 if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm, 9276 MEM_BLOCK_ANY, from_ent, ef)) < 0) { 9277 goto clean_up; 9278 } 9279 if (SOC_URPF_STATUS_GET(u)) { 9280 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm, 9281 MEM_BLOCK_ANY, 9282 from_ent + src_tcam_offset, 9283 ef_urpf)); 9284 src_default = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef_urpf, RPE0f) | 9285 (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef_urpf, RPE1f) << 1); 9286 src_discard = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef_urpf, SRC_DISCARD0f) | 9287 (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef_urpf, SRC_DISCARD1f) << 1); 9288 } 9289 et = (to_ent == from_ent) ? ef : e; 9290 upper_half = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef, VALID1f); 9291 if (upper_half) { 9292 if (slot & 1) { 9293 rv = soc_th_alpm_lpm_ip4entry1_to_1(u, ef, et, PRESERVE_HIT); 9294 } else { 9295 rv = soc_th_alpm_lpm_ip4entry1_to_0(u, ef, et, PRESERVE_HIT); 9296 } 9297 #ifdef BCM_TOMAHAWK2_SUPPORT 9298 if (soc_feature(u, soc_feature_half_of_l3_defip_ipv4_capacity)) { 9299 SOC_ALPM_LPM_STATE_VENT(u, pfx) -= 1; 9300 SOC_ALPM_LPM_STATE_FENT(u, pfx) += 1; 9301 SOC_ALPM_LPM_STATE_END(u, pfx) -= 1; 9302 } 9303 #endif 9304 src_pivot = (from_ent << 1) + 1; 9305 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, ef, VALID1f, 0); 9306 } else { 9307 if (slot & 1) { 9308 rv = soc_th_alpm_lpm_ip4entry0_to_1(u, ef, et, PRESERVE_HIT); 9309 } else { 9310 rv = soc_th_alpm_lpm_ip4entry0_to_0(u, ef, et, PRESERVE_HIT); 9311 } 9312 src_pivot = from_ent << 1; 9313 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, ef, VALID0f, 0); 9314 SOC_ALPM_LPM_STATE_VENT(u, pfx) -= 1; 9315 SOC_ALPM_LPM_STATE_FENT(u, pfx) += 1; 9316 SOC_ALPM_LPM_STATE_END(u, pfx) -= 1; 9317 } 9318 9319 src_pivot = soc_th_alpm_physical_idx(u, L3_DEFIPm, src_pivot, 0); 9320 slot = soc_th_alpm_physical_idx(u, L3_DEFIPm, slot, 0); 9321 9322 /* assert(ALPM_TCAM_PIVOT(u, slot) != 0); not true for OVERRIDE routes */ 9323 ALPM_TCAM_PIVOT(u, slot) = ALPM_TCAM_PIVOT(u, src_pivot); 9324 if (ALPM_TCAM_PIVOT(u, slot)) { 9325 PIVOT_TCAM_INDEX(ALPM_TCAM_PIVOT(u, slot)) = slot; 9326 SOC_ALPM_BU_PIVOT_IDX_UPDATE(u, slot); 9327 } 9328 ALPM_TCAM_PIVOT(u, src_pivot) = NULL; 9329 9330 if (ALPM_CTRL(u).aux_enable) { 9331 /* get bpm_len of entry that is about to move */ 9332 SOC_IF_ERROR_RETURN(READ_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ANY, 9333 soc_th_alpm_physical_idx(u, L3_DEFIPm, from_ent, 1), sf)); 9334 SOC_IF_ERROR_RETURN(READ_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ANY, 9335 soc_th_alpm_physical_idx(u, L3_DEFIPm, to_ent, 1), st)); 9336 9337 if (upper_half) { 9338 bpm_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm, 9339 sf, BPM_LENGTH1f); 9340 if (slot & 1) { 9341 soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, st, 9342 BPM_LENGTH1f, bpm_len); 9343 } else { 9344 soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, st, 9345 BPM_LENGTH0f, bpm_len); 9346 } 9347 } else { 9348 bpm_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm, 9349 sf, BPM_LENGTH0f); 9350 if (slot & 1) { 9351 soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, st, 9352 BPM_LENGTH1f, bpm_len); 9353 } else { 9354 soc_mem_field32_set(u, L3_DEFIP_AUX_TABLEm, st, 9355 BPM_LENGTH0f, bpm_len); 9356 } 9357 } 9358 9359 /* update bpm_len at target */ 9360 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_AUX_TABLEm(u, MEM_BLOCK_ALL, 9361 soc_th_alpm_physical_idx(u, L3_DEFIPm, to_ent, 1), st)); 9362 } 9363 9364 if (to_ent != from_ent) { 9365 LPM_HASH_INSERT(u, et, to_ent, &rvt_index0, &rvt_index1); 9366 rv = _soc_th_alpm_write_pivot(u, MEM_BLOCK_ANY, to_ent, to_ent, 9367 et, src_default, src_discard); 9368 if (rv < 0) 9369 { 9370 LPM_HASH_REVERT(u, et, to_ent, rvt_index0, rvt_index1); 9371 goto clean_up; 9372 } 9373 } 9374 LPM_HASH_INSERT(u, ef, from_ent, &rvt_index0, &rvt_index1); 9375 if ((rv = _soc_th_alpm_write_pivot(u, MEM_BLOCK_ANY, from_ent, from_ent, ef, 0, 0)) < 0) { 9376 LPM_HASH_REVERT(u, ef, from_ent, rvt_index0, rvt_index1); 9377 goto clean_up; 9378 } 9379 } else { /* IPV6 */ 9380 SOC_ALPM_LPM_STATE_VENT(u, pfx) -= 1; 9381 SOC_ALPM_LPM_STATE_FENT(u, pfx) += 1; 9382 SOC_ALPM_LPM_STATE_END(u, pfx) -= 1; 9383 if (to_ent != from_ent) { 9384 #ifdef FB_LPM_TABLE_CACHED 9385 if ((rv = soc_mem_cache_invalidate(u, L3_DEFIPm, 9386 MEM_BLOCK_ANY, from_ent)) < 0) { 9387 goto clean_up; 9388 } 9389 #endif /* FB_LPM_TABLE_CACHED */ 9390 if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm, 9391 MEM_BLOCK_ANY, from_ent, ef)) < 0) { 9392 goto clean_up; 9393 } 9394 if (SOC_URPF_STATUS_GET(u)) { 9395 SOC_IF_ERROR_RETURN(_soc_mem_alpm_read(u, L3_DEFIPm, 9396 MEM_BLOCK_ANY, 9397 from_ent + src_tcam_offset, 9398 ef_urpf)); 9399 src_default = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef_urpf, RPE0f) | 9400 (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef_urpf, RPE1f) << 1); 9401 src_discard = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef_urpf, SRC_DISCARD0f) | 9402 (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, ef_urpf, SRC_DISCARD1f) << 1); 9403 } 9404 LPM_HASH_INSERT(u, ef, to_ent, &rvt_index0, &rvt_index1); 9405 rv = _soc_th_alpm_write_pivot(u, MEM_BLOCK_ANY, to_ent, from_ent, 9406 ef, src_default, src_discard); 9407 if (rv < 0) 9408 { 9409 LPM_HASH_REVERT(u, ef, to_ent, rvt_index0, rvt_index1); 9410 goto clean_up; 9411 } 9412 } 9413 /* v6-64 indices are still raw in pivot tcam */ 9414 /* tmp variables: */ 9415 slot = soc_th_alpm_physical_idx(u, L3_DEFIPm, to_ent, 1); 9416 src_pivot = soc_th_alpm_physical_idx(u, L3_DEFIPm, from_ent, 1); 9417 ALPM_TCAM_PIVOT(u, slot << 1) = ALPM_TCAM_PIVOT(u, src_pivot << 1); 9418 ALPM_TCAM_PIVOT(u, src_pivot << 1) = NULL; 9419 if (ALPM_TCAM_PIVOT(u, slot << 1)) { 9420 PIVOT_TCAM_INDEX(ALPM_TCAM_PIVOT(u, slot << 1)) = slot << 1; 9421 SOC_ALPM_BU_PIVOT_IDX_UPDATE(u, slot << 1); 9422 } 9423 9424 sal_memcpy(ef, soc_mem_entry_null(u, L3_DEFIPm), 9425 soc_mem_entry_words(u,L3_DEFIPm) * 4); 9426 LPM_HASH_INSERT(u, ef, from_ent, &rvt_index0, &rvt_index1); 9427 if ((rv = _soc_th_alpm_write_pivot(u, MEM_BLOCK_ANY, from_ent, from_ent, ef, 0, 0)) < 0) { 9428 LPM_HASH_REVERT(u, ef, from_ent, rvt_index0, rvt_index1); 9429 goto clean_up; 9430 } 9431 } 9432 9433 if (SOC_ALPM_LPM_STATE_VENT(u, pfx) == 0) { 9434 /* remove from the list */ 9435 prev_pfx = SOC_ALPM_LPM_STATE_PREV(u, pfx); /* Always present */ 9436 assert(prev_pfx != -1); 9437 next_pfx = SOC_ALPM_LPM_STATE_NEXT(u, pfx); 9438 SOC_ALPM_LPM_STATE_NEXT(u, prev_pfx) = next_pfx; 9439 SOC_ALPM_LPM_STATE_FENT(u, prev_pfx) += SOC_ALPM_LPM_STATE_FENT(u, pfx); 9440 SOC_ALPM_LPM_STATE_FENT(u, pfx) = 0; 9441 if (next_pfx != -1) { 9442 SOC_ALPM_LPM_STATE_PREV(u, next_pfx) = prev_pfx; 9443 } 9444 SOC_ALPM_LPM_STATE_NEXT(u, pfx) = -1; 9445 SOC_ALPM_LPM_STATE_PREV(u, pfx) = -1; 9446 SOC_ALPM_LPM_STATE_START(u, pfx) = -1; 9447 SOC_ALPM_LPM_STATE_END(u, pfx) = -1; 9448 } 9449 clean_up: 9450 if (ef) { 9451 sal_free(ef); 9452 } 9453 if (ef_urpf) { 9454 sal_free(ef_urpf); 9455 } 9456 if (sf) { 9457 sal_free(sf); 9458 } 9459 if (st) { 9460 sal_free(st); 9461 } 9462 return(rv); 9463 } 9464 9465 9466 9467 9468 /* 9469 * Function: 9470 * soc_th_alpm_lpm_vrf_get 9471 * Purpose: 9472 * Service routine used to translate hw specific vrf id to API format. 9473 * Parameters: 9474 * unit - (IN)SOC unit number. 9475 * lpm_entry - (IN)Route info buffer from hw. 9476 * vrf_id - (OUT)Virtual router id. 9477 * Returns: 9478 * BCM_E_XXX 9479 */ 9480 int 9481 soc_th_alpm_lpm_vrf_get(int unit, void *lpm_entry, int *vrf_id, int *vrf) 9482 { 9483 int mem_vrf; 9484 9485 /* Get Virtual Router id if supported. */ 9486 if (SOC_MEM_OPT_FIELD_VALID(unit, L3_DEFIPm, VRF_ID_MASK0f)){ 9487 mem_vrf = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VRF_ID_0f); 9488 9489 /* Special vrf's handling. */ 9490 if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f)) { 9491 *vrf_id = mem_vrf; 9492 } else if (!SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, 9493 GLOBAL_HIGH0f)) { 9494 *vrf_id = SOC_L3_VRF_GLOBAL; 9495 } else { 9496 *vrf_id = SOC_L3_VRF_OVERRIDE; 9497 } 9498 if (vrf) { 9499 if (*vrf_id == SOC_L3_VRF_GLOBAL) { 9500 *vrf = SOC_VRF_MAX(unit) + 1; 9501 } else { 9502 *vrf = mem_vrf; 9503 } 9504 } 9505 } else { 9506 /* No vrf support on this device. */ 9507 *vrf_id = SOC_L3_VRF_DEFAULT; 9508 } 9509 return (SOC_E_NONE); 9510 } 9511 9512 /* 9513 * _soc_th_alpm_lpm_prefix_length_get (Extract vrf weighted 9514 * prefix lenght from the hw entry based on ip, mask & vrf) 9515 */ 9516 static int 9517 _soc_th_alpm_lpm_prefix_length_get(int u, int ipv6, void *entry, int *pfx_len, 9518 int *vrf_id, int *vrf) 9519 { 9520 int pfx; 9521 int rv; 9522 uint32 ipv4a; 9523 int vrfid; 9524 int mode; 9525 9526 if (ipv6) { 9527 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f); 9528 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 9529 return(rv); 9530 } 9531 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK1f); 9532 if (pfx) { 9533 if (ipv4a != 0xffffffff) { 9534 return(SOC_E_PARAM); 9535 } 9536 pfx += 32; 9537 } else { 9538 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 9539 return(rv); 9540 } 9541 } 9542 pfx += ALPM_IPV6_PFX_ZERO; /* First 33 are for IPV4 addresses */ 9543 } else { 9544 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, entry, IP_ADDR_MASK0f); 9545 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 9546 return(rv); 9547 } 9548 } 9549 9550 SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(u, entry, &vrfid, &rv)); 9551 if (vrf_id != NULL) { 9552 *vrf_id = vrfid; 9553 } 9554 if (vrf != NULL) { 9555 *vrf = rv; 9556 } 9557 9558 /* In ALPM the arragnement of VRF is at he begining followed by VRF 9559 * override and global */ 9560 mode = ALPM_CTRL(u).alpm_mode; 9561 switch (vrfid) { 9562 case SOC_L3_VRF_GLOBAL: 9563 if ((mode == SOC_ALPM_MODE_PARALLEL) || (mode == SOC_ALPM_MODE_TCAM_ALPM)) { 9564 *pfx_len = pfx + (ALPM_MAX_PFX_ENTRIES / 3); 9565 } else { 9566 *pfx_len = pfx; 9567 } 9568 break; 9569 case SOC_L3_VRF_OVERRIDE: 9570 *pfx_len = pfx + 2 * (ALPM_MAX_PFX_ENTRIES / 3); 9571 break; 9572 default: 9573 if ((mode == SOC_ALPM_MODE_PARALLEL) || (mode == SOC_ALPM_MODE_TCAM_ALPM)) { 9574 *pfx_len = pfx; 9575 } else { 9576 *pfx_len = pfx + (ALPM_MAX_PFX_ENTRIES / 3); 9577 } 9578 break; 9579 } 9580 return (SOC_E_NONE); 9581 } 9582 9583 /* 9584 * _soc_th_alpm_lpm_match (Exact match for the key. Will match both IP address 9585 * and mask) 9586 */ 9587 static int 9588 _soc_th_alpm_lpm_match(int u, 9589 void *key_data, 9590 void *e, /* return entry data if found */ 9591 int *index_ptr, /* return key location */ 9592 int *pfx_len, /* Key prefix length. vrf + 32 + prefix len for IPV6*/ 9593 int *ipv6, /* Entry is ipv6. */ 9594 int *vrf_id, /* (OUT) */ 9595 int *vrf) /* (OUT) */ 9596 { 9597 int rv; 9598 int v6; 9599 int key_index; 9600 int pfx = 0; 9601 9602 v6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0_f(u)); 9603 if (v6) { 9604 if (!(v6 = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE1_f(u)))) { 9605 return (SOC_E_PARAM); 9606 } 9607 } 9608 *ipv6 = v6; 9609 9610 /* Calculate vrf weighted prefix lengh. */ 9611 _soc_th_alpm_lpm_prefix_length_get(u, v6, key_data, &pfx, vrf_id, vrf); 9612 *pfx_len = pfx; 9613 9614 #ifdef FB_LPM_HASH_SUPPORT 9615 if (LPM_HASH_LOOKUP(u, key_data, pfx, &key_index) == SOC_E_NONE) { 9616 *index_ptr = key_index; 9617 if ((rv = _soc_mem_alpm_read(u, L3_DEFIPm, MEM_BLOCK_ANY, 9618 (*ipv6) ? *index_ptr : (*index_ptr >> 1), e)) < 0) { 9619 return rv; 9620 } 9621 #ifndef FB_LPM_CHECKER_ENABLE 9622 return(SOC_E_NONE); 9623 #endif 9624 } else { 9625 #ifndef FB_LPM_CHECKER_ENABLE 9626 return(SOC_E_NOT_FOUND); 9627 #endif 9628 } 9629 #endif /* FB_LPM_HASH_SUPPORT */ 9630 } 9631 9632 STATIC int 9633 soc_alpm_key_sel_reg_init(int u) 9634 { 9635 int i, urpf_enb, lpm_128b; 9636 soc_reg_t kselr = L3_DEFIP_KEY_SELr; 9637 uint32 rval = 0; 9638 soc_field_t pcamf[4] = { 9639 INVALIDf, 9640 INVALIDf, 9641 INVALIDf, 9642 INVALIDf 9643 }; 9644 9645 /* URPF[bit1], 128B[bit0] */ 9646 int key_sel[4] = { 9647 2, /* 0x00b non-URPF + lpm-64b */ 9648 0, /* 0x01b non-URPF + lpm-128b */ 9649 3, /* 0x10b uRPF + lpm-64b */ 9650 1 /* 0x11b uRPF + lpm-128b */ 9651 }; 9652 9653 urpf_enb = !!SOC_URPF_STATUS_GET(u); 9654 lpm_128b = !!SOC_ALPM_128B_ENABLE(u); 9655 9656 if (soc_reg_field_valid(u, kselr, KEY_SEL_CAM0_1f)) { 9657 i = lpm_128b; 9658 soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM0_1f, key_sel[i]); 9659 soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM2_3f, key_sel[i]); 9660 soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM4_5f, key_sel[i]); 9661 soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM6_7f, key_sel[i]); 9662 if (urpf_enb) { 9663 i = (urpf_enb << 1) | lpm_128b; 9664 soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM4_5f, key_sel[i]); 9665 soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM6_7f, key_sel[i]); 9666 } 9667 } else { 9668 if (urpf_enb) { 9669 soc_reg_field_set(u, kselr, &rval, URPF_LOOKUP_CAM4f, 0x1); 9670 soc_reg_field_set(u, kselr, &rval, URPF_LOOKUP_CAM5f, 0x1); 9671 soc_reg_field_set(u, kselr, &rval, URPF_LOOKUP_CAM6f, 0x1); 9672 soc_reg_field_set(u, kselr, &rval, URPF_LOOKUP_CAM7f, 0x1); 9673 } 9674 } 9675 if (lpm_128b) { 9676 if (soc_reg_field_valid(u, kselr, V6_KEY_SEL_CAM0_1f)) { 9677 pcamf[0] = V6_KEY_SEL_CAM0_1f; 9678 pcamf[1] = V6_KEY_SEL_CAM2_3f; 9679 pcamf[2] = V6_KEY_SEL_CAM4_5f; 9680 pcamf[3] = V6_KEY_SEL_CAM6_7f; 9681 } 9682 /* Supports mixed IPv4, IPv6 128 bit prefix IPv6 routes. 9683 * upto 16K IPv4 pivots only or 9684 * upto 2K 128 bit IPv6 and upto 8k v4 pivots, or */ 9685 /* all tcams in paired mode */ 9686 for (i = 0; i < 4; i++) { 9687 if (pcamf[i] != INVALIDf) { 9688 soc_reg_field_set(u, kselr, &rval, pcamf[i], 0x1); 9689 } 9690 } 9691 } 9692 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_KEY_SELr(u, rval)); 9693 return SOC_E_NONE; 9694 } 9695 9696 STATIC int 9697 soc_alpm_cfg_reg_init(int u) 9698 { 9699 soc_reg_t creg = L3_DEFIP_ALPM_CFGr; 9700 uint32 rval = 0; 9701 if (ALPM_CTRL(u).gp_zoned) { 9702 if (SOC_URPF_STATUS_GET(u)) { 9703 /* 4 DIPs, 4 SIPs */ 9704 if (soc_reg_field_valid(u, creg, CAM0_1_SELf)) { 9705 /* *DIP */ 9706 soc_reg_field_set(u, creg, &rval, CAM2_3_SELf, 1); 9707 /* VRF SIP */ 9708 soc_reg_field_set(u, creg, &rval, CAM4_5_SELf, 2); 9709 /* *SIP */ 9710 soc_reg_field_set(u, creg, &rval, CAM6_7_SELf, 3); 9711 } else { 9712 /* *DIP */ 9713 soc_reg_field_set(u, creg, &rval, TCAM2_SELf, 1); 9714 soc_reg_field_set(u, creg, &rval, TCAM3_SELf, 1); 9715 /* VRF SIP */ 9716 soc_reg_field_set(u, creg, &rval, TCAM4_SELf, 2); 9717 soc_reg_field_set(u, creg, &rval, TCAM5_SELf, 2); 9718 /* *SIP */ 9719 soc_reg_field_set(u, creg, &rval, TCAM6_SELf, 3); 9720 soc_reg_field_set(u, creg, &rval, TCAM7_SELf, 3); 9721 } 9722 } else { 9723 if (soc_reg_field_valid(u, creg, CAM0_1_SELf)) { 9724 soc_reg_field_set(u, creg, &rval, CAM4_5_SELf, 1); 9725 soc_reg_field_set(u, creg, &rval, CAM6_7_SELf, 1); 9726 } else { 9727 soc_reg_field_set(u, creg, &rval, TCAM4_SELf, 1); 9728 soc_reg_field_set(u, creg, &rval, TCAM5_SELf, 1); 9729 soc_reg_field_set(u, creg, &rval, TCAM6_SELf, 1); 9730 soc_reg_field_set(u, creg, &rval, TCAM7_SELf, 1); 9731 } 9732 } 9733 } else { 9734 if (SOC_URPF_STATUS_GET(u)) { 9735 /* 4 DIPs, 4 SIPs */ 9736 if (soc_reg_field_valid(u, creg, CAM0_1_SELf)) { 9737 soc_reg_field_set(u, creg, &rval, CAM4_5_SELf, 2); 9738 soc_reg_field_set(u, creg, &rval, CAM6_7_SELf, 2); 9739 } else { 9740 /* DIP */ 9741 /* VRF SIP */ 9742 soc_reg_field_set(u, creg, &rval, TCAM4_SELf, 2); 9743 soc_reg_field_set(u, creg, &rval, TCAM5_SELf, 2); 9744 soc_reg_field_set(u, creg, &rval, TCAM6_SELf, 2); 9745 soc_reg_field_set(u, creg, &rval, TCAM7_SELf, 2); 9746 } 9747 } 9748 } 9749 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_ALPM_CFGr(u, rval)); 9750 9751 return SOC_E_NONE; 9752 } 9753 9754 /* 9755 * Initialize the start/end tracking pointers for each prefix length 9756 */ 9757 static int 9758 soc_th_alpm_lpm_init(int u) 9759 { 9760 int max_pfx_len; 9761 int i; 9762 int defip_table_size; 9763 int pfx_state_size; 9764 uint32 rval, mode; 9765 #define _ALPM_MODE_PARALLEL 1 9766 #define _ALPM_MODE_COMBINED 2 9767 #define _ALPM_MODE_TCAM_ALPM 3 9768 9769 if (! soc_feature(u, soc_feature_lpm_tcam)) { 9770 return(SOC_E_UNAVAIL); 9771 } 9772 9773 mode = ALPM_CTRL(u).alpm_mode; 9774 if (mode != SOC_ALPM_MODE_INVALID) { 9775 /* Set DEFIP mode to ALPM */ 9776 SOC_IF_ERROR_RETURN(READ_L3_DEFIP_RPF_CONTROLr(u, &rval)); 9777 soc_reg_field_set(u, L3_DEFIP_RPF_CONTROLr, &rval, LPM_MODEf, 1); 9778 if (mode == SOC_ALPM_MODE_PARALLEL) { 9779 /* Parallel mode */ 9780 soc_reg_field_set(u, L3_DEFIP_RPF_CONTROLr, &rval, LOOKUP_MODEf, 1); 9781 } else if (mode == SOC_ALPM_MODE_COMBINED) { 9782 /* Combined search mode */ 9783 soc_reg_field_set(u, L3_DEFIP_RPF_CONTROLr, &rval, LOOKUP_MODEf, 0); 9784 l3_alpm_ipv4_double_wide[u] = soc_property_get(u, "l3_alpm_ipv4_double_wide", 1); 9785 if (l3_alpm_ipv4_double_wide[u]) { 9786 if (SOC_REG_FIELD_VALID(u, L3_DEFIP_RPF_CONTROLr, 9787 ENABLE_DOUBLE_WIDE_BUCKETS_FOR_IPV4f)) { 9788 soc_reg_field_set(u, L3_DEFIP_RPF_CONTROLr, &rval, 9789 ENABLE_DOUBLE_WIDE_BUCKETS_FOR_IPV4f, 1); 9790 } 9791 } 9792 } else if (mode == SOC_ALPM_MODE_TCAM_ALPM) { 9793 /* TCAM_ALPM search mode */ 9794 l3_alpm_ipv4_double_wide[u] = 1; 9795 soc_reg_field_set(u, L3_DEFIP_RPF_CONTROLr, &rval, LOOKUP_MODEf, 2); 9796 } 9797 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_RPF_CONTROLr(u, rval)); 9798 9799 SOC_IF_ERROR_RETURN(soc_alpm_key_sel_reg_init(u)); 9800 SOC_IF_ERROR_RETURN(soc_alpm_cfg_reg_init(u)); 9801 } 9802 9803 max_pfx_len = ALPM_MAX_PFX_ENTRIES; 9804 9805 SOC_ALPM_LPM_LOCK(u); 9806 pfx_state_size = sizeof(soc_th_alpm_lpm_state_t) * (max_pfx_len); 9807 9808 soc_lpm_field_cache_state[u] = 9809 sal_alloc(sizeof(soc_th_lpm_field_cache_t), "lpm_field_state"); 9810 if (NULL == soc_lpm_field_cache_state[u]) { 9811 SOC_ALPM_LPM_UNLOCK(u); 9812 return (SOC_E_MEMORY); 9813 } 9814 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9815 CLASS_ID0f); 9816 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9817 CLASS_ID1f); 9818 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9819 DST_DISCARD0f); 9820 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9821 DST_DISCARD1f); 9822 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9823 ECMP0f); 9824 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9825 ECMP1f); 9826 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9827 ECMP_COUNT0f); 9828 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9829 ECMP_COUNT1f); 9830 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9831 ECMP_PTR0f); 9832 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9833 ECMP_PTR1f); 9834 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9835 GLOBAL_ROUTE0f); 9836 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9837 GLOBAL_ROUTE1f); 9838 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9839 MULTICAST_ROUTE0f); 9840 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9841 MULTICAST_ROUTE1f); 9842 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9843 RPA_ID0f); 9844 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9845 RPA_ID1f); 9846 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9847 EXPECTED_L3_IIF0f); 9848 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9849 EXPECTED_L3_IIF1f); 9850 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9851 IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f); 9852 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9853 IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f); 9854 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9855 IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f); 9856 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9857 IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f); 9858 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9859 L3MC_INDEX0f); 9860 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9861 L3MC_INDEX1f); 9862 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9863 HIT0f); 9864 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9865 HIT1f); 9866 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9867 IP_ADDR0f); 9868 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9869 IP_ADDR1f); 9870 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9871 IP_ADDR_MASK0f); 9872 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9873 IP_ADDR_MASK1f); 9874 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9875 NEXT_HOP_INDEX0f); 9876 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9877 NEXT_HOP_INDEX1f); 9878 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9879 PRI0f); 9880 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9881 PRI1f); 9882 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9883 RPE0f); 9884 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9885 RPE1f); 9886 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9887 VALID0f); 9888 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9889 VALID1f); 9890 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9891 VRF_ID_0f); 9892 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9893 VRF_ID_1f); 9894 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9895 VRF_ID_MASK0f); 9896 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9897 VRF_ID_MASK1f); 9898 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9899 GLOBAL_HIGH0f); 9900 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9901 GLOBAL_HIGH1f); 9902 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9903 ALG_HIT_IDX0f); 9904 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9905 ALG_HIT_IDX1f); 9906 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9907 ALG_BKT_PTR0f); 9908 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9909 ALG_BKT_PTR1f); 9910 if (ALPM_CTRL(u).bkt_sharing) { 9911 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9912 ALG_SUB_BKT_PTR0f); 9913 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9914 ALG_SUB_BKT_PTR1f); 9915 } 9916 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9917 DEFAULT_MISS0f); 9918 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9919 DEFAULT_MISS1f); 9920 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9921 FLEX_CTR_BASE_COUNTER_IDX0f); 9922 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9923 FLEX_CTR_BASE_COUNTER_IDX1f); 9924 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9925 FLEX_CTR_POOL_NUMBER0f); 9926 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9927 FLEX_CTR_POOL_NUMBER1f); 9928 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9929 FLEX_CTR_OFFSET_MODE0f); 9930 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9931 FLEX_CTR_OFFSET_MODE1f); 9932 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9933 SRC_DISCARD0f); 9934 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9935 SRC_DISCARD1f); 9936 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9937 ENTRY_VIEW0f); 9938 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u] ,L3_DEFIPm, 9939 ENTRY_VIEW1f); 9940 9941 if (soc_feature(u, soc_feature_generic_dest)) { 9942 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u], 9943 L3_DEFIPm, DESTINATION0f); 9944 SOC_ALPM_LPM_CACHE_FIELD_ASSIGN(u, soc_lpm_field_cache_state[u], 9945 L3_DEFIPm, DESTINATION1f); 9946 } 9947 9948 SOC_ALPM_LPM_STATE(u) = sal_alloc(pfx_state_size, "LPM prefix info"); 9949 if (NULL == SOC_ALPM_LPM_STATE(u)) { 9950 sal_free(soc_lpm_field_cache_state[u]); 9951 soc_lpm_field_cache_state[u] = NULL; 9952 SOC_ALPM_LPM_UNLOCK(u); 9953 return (SOC_E_MEMORY); 9954 } 9955 9956 #ifdef FB_LPM_TABLE_CACHED 9957 rv = soc_mem_cache_set(u, L3_DEFIPm, MEM_BLOCK_ALL, TRUE); 9958 if (SOC_FAILURE(rv)) { 9959 SOC_ALPM_LPM_UNLOCK(u); 9960 return rv; 9961 } 9962 #endif /* FB_LPM_TABLE_CACHED */ 9963 9964 sal_memset(SOC_ALPM_LPM_STATE(u), 0, pfx_state_size); 9965 for(i = 0; i < max_pfx_len; i++) { 9966 SOC_ALPM_LPM_STATE_START(u, i) = -1; 9967 SOC_ALPM_LPM_STATE_END(u, i) = -1; 9968 SOC_ALPM_LPM_STATE_PREV(u, i) = -1; 9969 SOC_ALPM_LPM_STATE_NEXT(u, i) = -1; 9970 SOC_ALPM_LPM_STATE_VENT(u, i) = 0; 9971 SOC_ALPM_LPM_STATE_FENT(u, i) = 0; 9972 } 9973 9974 defip_table_size = soc_mem_index_count(u, L3_DEFIPm); 9975 9976 /* RPF supported, then the table is partitioned for DIP and SIP */ 9977 if (SOC_URPF_STATUS_GET(u)) { 9978 defip_table_size >>= 1; 9979 } 9980 9981 if (ALPM_CTRL(u).gp_zoned) { 9982 /* For Parallel search, the TCAM is hard paritioned. 9983 * First half are for VRF specific, the bottom half for override and 9984 * global. Start of Global entries start at the bottom half of TCAM 9985 */ 9986 SOC_ALPM_LPM_STATE_END(u, ALPM_MAX_PFX_INDEX) = (defip_table_size>>1) - 1; 9987 9988 /* Free entries for VRF */ 9989 SOC_ALPM_LPM_STATE_FENT(u, (ALPM_MAX_VRF_PFX_INDEX)) = defip_table_size >> 1; 9990 9991 /* Remaining entries are assigned to Global entries */ 9992 SOC_ALPM_LPM_STATE_FENT(u, (ALPM_MAX_PFX_INDEX)) = 9993 (defip_table_size - SOC_ALPM_LPM_STATE_FENT(u, (ALPM_MAX_VRF_PFX_INDEX))); 9994 } else { 9995 /* Remaining entries are assigned to Global entries */ 9996 SOC_ALPM_LPM_STATE_FENT(u, (ALPM_MAX_PFX_INDEX)) = defip_table_size; 9997 } 9998 9999 if (SOC_ALPM_LPM_STATE_HASH(u) != NULL) { 10000 if (_soc_th_alpm_lpm_hash_destroy(SOC_ALPM_LPM_STATE_HASH(u)) < 0) { 10001 SOC_ALPM_LPM_UNLOCK(u); 10002 return SOC_E_INTERNAL; 10003 } 10004 SOC_ALPM_LPM_STATE_HASH(u) = NULL; 10005 } 10006 10007 if (_soc_th_alpm_lpm_hash_create(u, defip_table_size * 2, defip_table_size, 10008 &SOC_ALPM_LPM_STATE_HASH(u)) < 0) { 10009 SOC_ALPM_LPM_UNLOCK(u); 10010 return SOC_E_MEMORY; 10011 } 10012 10013 SOC_ALPM_LPM_UNLOCK(u); 10014 10015 return(SOC_E_NONE); 10016 } 10017 10018 /* 10019 * De-initialize the start/end tracking pointers for each prefix length 10020 */ 10021 static int 10022 soc_th_alpm_lpm_deinit(int u) 10023 { 10024 if (!soc_feature(u, soc_feature_lpm_tcam)) { 10025 return(SOC_E_UNAVAIL); 10026 } 10027 10028 SOC_ALPM_LPM_LOCK(u); 10029 10030 if (SOC_ALPM_LPM_STATE_HASH(u) != NULL) { 10031 _soc_th_alpm_lpm_hash_destroy(SOC_ALPM_LPM_STATE_HASH(u)); 10032 SOC_ALPM_LPM_STATE_HASH(u) = NULL; 10033 } 10034 10035 if (SOC_ALPM_LPM_INIT_CHECK(u)) { 10036 sal_free(soc_lpm_field_cache_state[u]); 10037 soc_lpm_field_cache_state[u] = NULL; 10038 sal_free(SOC_ALPM_LPM_STATE(u)); 10039 SOC_ALPM_LPM_STATE(u) = NULL; 10040 } 10041 10042 SOC_ALPM_LPM_UNLOCK(u); 10043 10044 return(SOC_E_NONE); 10045 } 10046 10047 /* 10048 * Implementation using soc_mem_read/write using entry rippling technique 10049 * Advantage: A completely sorted table is not required. Lookups can be slow 10050 * as it will perform a linear search on the entries for a given prefix length. 10051 * No device access necessary for the search if the table is cached. Auxiliary 10052 * hash table can be maintained to speed up search(Not implemented) instead of 10053 * performing a linear search. 10054 * Small number of entries need to be moved around (97 worst case) 10055 * for performing insert/update/delete. However CPU needs to do all 10056 * the work to move the entries. 10057 */ 10058 10059 /* 10060 * soc_th_alpm_lpm_insert 10061 * For IPV4 assume only both IP_ADDR0 is valid 10062 * Moving multiple entries around in h/w vs doing a linear search in s/w 10063 */ 10064 static int 10065 soc_th_alpm_lpm_insert(int u, void *entry_data, int *lpm_index, int bpm_len, 10066 int src_default, int src_discard) 10067 { 10068 int pfx; 10069 int index, v4_half = 0; 10070 int ipv6; 10071 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 10072 int rv = SOC_E_NONE; 10073 int found = 0; 10074 uint32 rvt_index0 = 0, rvt_index1 = 0; 10075 int vrf, vrf_id; 10076 10077 sal_memcpy(e, soc_mem_entry_null(u, L3_DEFIPm), 10078 soc_mem_entry_words(u,L3_DEFIPm) * 4); 10079 10080 SOC_ALPM_LPM_LOCK(u); 10081 rv = _soc_th_alpm_lpm_match(u, entry_data, e, &index, &pfx, &ipv6, &vrf_id, &vrf); 10082 if (rv == SOC_E_NOT_FOUND) { 10083 rv = _lpm_free_slot_create(u, pfx, ipv6, e, &index); 10084 if (rv < 0) { 10085 SOC_ALPM_LPM_UNLOCK(u); 10086 return(rv); 10087 } 10088 } else { 10089 found = 1; 10090 } 10091 10092 *lpm_index = index; 10093 10094 if (rv == SOC_E_NONE) { 10095 /* Entry already present. Update the entry */ 10096 if (!ipv6) { 10097 /* IPV4 entry */ 10098 if (index & 1) { 10099 rv = soc_th_alpm_lpm_ip4entry0_to_1(u, entry_data, e, 10100 PRESERVE_HIT); 10101 v4_half = 3; 10102 } else { 10103 rv = soc_th_alpm_lpm_ip4entry0_to_0(u, entry_data, e, 10104 PRESERVE_HIT); 10105 v4_half = 2; 10106 } 10107 10108 if (rv < 0) { 10109 SOC_ALPM_LPM_UNLOCK(u); 10110 return(rv); 10111 } 10112 entry_data = (void *)e; 10113 index >>= 1; 10114 } 10115 soc_th_alpm_lpm_state_dump(u); 10116 LOG_VERBOSE(BSL_LS_SOC_ALPM, 10117 (BSL_META_U(u, 10118 "soc_alpm_lpm_insert: %d %d\n"), 10119 index, pfx)); 10120 10121 if (!found) { 10122 LPM_HASH_INSERT(u, entry_data, index, &rvt_index0, &rvt_index1); 10123 } 10124 rv = _soc_th_alpm_write_pivot_with_bpm(u, MEM_BLOCK_ANY, index, index, 10125 entry_data, bpm_len, v4_half, 10126 src_default, src_discard); 10127 if (!found) { 10128 if (SOC_SUCCESS(rv)) { 10129 VRF_PIVOT_REF_INC(u, vrf_id, vrf, ipv6); 10130 } else { 10131 LPM_HASH_REVERT(u, entry_data, index, rvt_index0, rvt_index1); 10132 } 10133 } 10134 } 10135 10136 SOC_ALPM_LPM_UNLOCK(u); 10137 10138 return(rv); 10139 } 10140 10141 /* 10142 * soc_th_alpm_lpm_delete 10143 */ 10144 static int 10145 soc_th_alpm_lpm_delete(int u, void *key_data) 10146 { 10147 int pfx; 10148 int index; 10149 int ipv6; 10150 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 10151 int rv = SOC_E_NONE; 10152 int vrf, vrf_id; 10153 10154 SOC_ALPM_LPM_LOCK(u); 10155 rv = _soc_th_alpm_lpm_match(u, key_data, e, &index, &pfx, &ipv6, &vrf_id, &vrf); 10156 if (rv == SOC_E_NONE) { 10157 LOG_VERBOSE(BSL_LS_SOC_ALPM, 10158 (BSL_META_U(u, 10159 "soc_alpm_lpm_delete: %d %d\n"), 10160 index, pfx)); 10161 LPM_HASH_DELETE(u, key_data, index); 10162 rv = _lpm_free_slot_delete(u, pfx, ipv6, e, index); 10163 } 10164 if (SOC_SUCCESS(rv)) { 10165 VRF_PIVOT_REF_DEC(u, vrf_id, vrf, ipv6); 10166 } 10167 soc_th_alpm_lpm_state_dump(u); 10168 SOC_ALPM_LPM_UNLOCK(u); 10169 10170 return(rv); 10171 } 10172 10173 /* 10174 * soc_th_alpm_lpm_match (Exact match for the key. Will match both IP 10175 * address and mask) 10176 */ 10177 static int 10178 soc_th_alpm_lpm_match(int u, 10179 void *key_data, 10180 void *e, /* return entry data if found */ 10181 int *index_ptr) /* return key location */ 10182 { 10183 int pfx; 10184 int rv; 10185 int ipv6; 10186 10187 SOC_ALPM_LPM_LOCK(u); 10188 rv = _soc_th_alpm_lpm_match(u, key_data, e, index_ptr, &pfx, &ipv6, 0, 0); 10189 SOC_ALPM_LPM_UNLOCK(u); 10190 return(rv); 10191 } 10192 10193 10194 /* Fill Aux entry for operation */ 10195 static int 10196 _soc_th_alpm_fill_aux_entry_for_op(int u, 10197 void *key_data, 10198 int ipv6, /* Entry is ipv6. */ 10199 int db_type, /* database type */ 10200 int ent_type, 10201 int replace_len, /* used for DElete propagate */ 10202 defip_aux_scratch_entry_t *aux_entry) 10203 { 10204 uint32 ipv4a; 10205 uint32 ip6_word[4] = {0, 0, 0, 0}; 10206 int pfx = 0; 10207 int rv = SOC_E_NONE; 10208 10209 sal_memset(aux_entry, 0, sizeof(defip_aux_scratch_entry_t)); 10210 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, VALID0f); 10211 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, VALIDf, ipv4a); 10212 10213 ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, MODE0_f(u)); 10214 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, MODE_f(u), ipv4a); 10215 10216 ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, ENTRY_TYPE0_f(u)); 10217 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, ENTRY_TYPE_f(u), ent_type); 10218 10219 if (SOC_IS_TRIDENT3X(u)) { 10220 ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, DATA_TYPE0f); 10221 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, DATA_TYPEf, ipv4a); 10222 } 10223 10224 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, GLOBAL_ROUTE0f); 10225 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, GLOBAL_ROUTEf, ipv4a); 10226 10227 if (soc_feature(u, soc_feature_ipmc_defip)) { 10228 ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, RPA_ID0f); 10229 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, RPA_IDf, ipv4a); 10230 10231 ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, EXPECTED_L3_IIF0f); 10232 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, EXPECTED_L3_IIFf, ipv4a); 10233 10234 ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f); 10235 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf, ipv4a); 10236 10237 ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f); 10238 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf, ipv4a); 10239 10240 if (soc_mem_field_valid(u, L3_DEFIPm, L3MC_INDEX0f)) { 10241 ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, L3MC_INDEX0f); 10242 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, L3MC_INDEXf, ipv4a); 10243 } 10244 } 10245 10246 if (soc_feature(u, soc_feature_generic_dest)) { 10247 ipv4a = soc_mem_field32_get(u, L3_DEFIPm, key_data, DESTINATION0f); 10248 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, 10249 DESTINATIONf, ipv4a); 10250 } else { 10251 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, ECMP0f); 10252 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, ECMPf, ipv4a); 10253 10254 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, ECMP_PTR0f); 10255 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, ECMP_PTRf, ipv4a); 10256 10257 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, NEXT_HOP_INDEX0f); 10258 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, NEXT_HOP_INDEXf, ipv4a); 10259 } 10260 10261 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, PRI0f); 10262 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, PRIf, ipv4a); 10263 10264 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, RPE0f); 10265 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, RPEf, ipv4a); 10266 10267 ipv4a =SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, VRF_ID_0f); 10268 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, VRFf, ipv4a); 10269 10270 /* Set Database type */ 10271 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, DB_TYPEf, db_type); 10272 10273 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, DST_DISCARD0f); 10274 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, DST_DISCARDf, ipv4a); 10275 10276 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, CLASS_ID0f); 10277 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, CLASS_IDf, ipv4a); 10278 10279 10280 /* Set IP Address and IP length */ 10281 if (ipv6) { 10282 ip6_word[2] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, IP_ADDR0f); 10283 ip6_word[3] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, IP_ADDR1f); 10284 } else { 10285 ip6_word[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, IP_ADDR0f); 10286 } 10287 soc_mem_field_set(u, L3_DEFIP_AUX_SCRATCHm, (uint32*)aux_entry, 10288 IP_ADDRf, (uint32*)ip6_word); 10289 10290 if (ipv6) { 10291 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, IP_ADDR_MASK0f); 10292 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 10293 return(rv); 10294 } 10295 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, IP_ADDR_MASK1f); 10296 if (pfx) { 10297 if (ipv4a != 0xffffffff) { 10298 return(SOC_E_PARAM); 10299 } 10300 pfx += 32; 10301 } else { 10302 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 10303 return(rv); 10304 } 10305 } 10306 } else { 10307 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, IP_ADDR_MASK0f); 10308 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 10309 return(rv); 10310 } 10311 } 10312 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, IP_LENGTHf, pfx); 10313 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, REPLACE_LENf, 10314 replace_len); 10315 10316 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, FLEX_CTR_BASE_COUNTER_IDX0f); 10317 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, FLEX_CTR_BASE_COUNTER_IDXf, ipv4a); 10318 10319 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, FLEX_CTR_OFFSET_MODE0f); 10320 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, FLEX_CTR_OFFSET_MODEf, ipv4a); 10321 10322 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, key_data, FLEX_CTR_POOL_NUMBER0f); 10323 soc_mem_field32_set(u, L3_DEFIP_AUX_SCRATCHm, aux_entry, FLEX_CTR_POOL_NUMBERf, ipv4a); 10324 10325 return (SOC_E_NONE); 10326 } 10327 10328 #define _SOC_ALPM_AUX_OP_RETRY_TO 1000000 10329 #define _SOC_ALPM_AUX_OP_RETRY_COUNT 100 10330 10331 /* Using binary search with DMA read to retrieve corrupted index */ 10332 int 10333 _soc_th_alpm_aux_error_index(int u, int pipe, int *index, soc_mem_t *mem) 10334 { 10335 char *dmabuf = NULL; 10336 soc_mem_t mem_to_search[2] = {L3_DEFIP_AUX_TABLEm, L3_DEFIP_DATA_ONLYm}; 10337 int min, max; 10338 uint32 ser_flags; 10339 int i = 0; 10340 int found_index = FALSE; 10341 int mem_wsz = 0; 10342 10343 switch (pipe) { 10344 case 0: 10345 ser_flags = _SOC_MEM_ADDR_ACC_TYPE_PIPE_0; 10346 break; 10347 case 1: 10348 ser_flags = _SOC_MEM_ADDR_ACC_TYPE_PIPE_1; 10349 break; 10350 case 2: 10351 ser_flags = _SOC_MEM_ADDR_ACC_TYPE_PIPE_2; 10352 break; 10353 case 3: 10354 ser_flags = _SOC_MEM_ADDR_ACC_TYPE_PIPE_3; 10355 break; 10356 default: 10357 ser_flags = _SOC_MEM_ADDR_ACC_TYPE_PIPE_0; 10358 break; 10359 } 10360 10361 ser_flags |= _SOC_SER_FLAG_DMA_ERR_RETURN; 10362 ser_flags |= _SOC_SER_FLAG_DISCARD_READ; 10363 ser_flags |= _SOC_SER_FLAG_MULTI_PIPE; 10364 10365 for (i = 0; i < 2; i++) { 10366 min = soc_mem_index_min(u, mem_to_search[i]); 10367 if (mem_to_search[i] == L3_DEFIP_DATA_ONLYm) { 10368 max = soc_mem_index_max(u, L3_DEFIP_DATA_ONLYm) + 10369 soc_mem_index_max(u, L3_DEFIP_PAIR_128_DATA_ONLYm) * 2; 10370 } else { 10371 max = soc_mem_index_max(u, mem_to_search[i]); 10372 } 10373 10374 mem_wsz = sizeof(uint32) * soc_mem_entry_words(u, mem_to_search[i]); 10375 dmabuf = soc_cm_salloc(u, max * mem_wsz, "auxtbl_dmabuf"); 10376 if (dmabuf == NULL) { 10377 return SOC_E_MEMORY; 10378 } 10379 10380 while (min <= max) { 10381 int mid = min + (max - min) / 2; 10382 if (soc_mem_ser_read_range(u, mem_to_search[i], MEM_BLOCK_ALL, min, mid, 10383 ser_flags, dmabuf) < 0) { 10384 if (max == min) { 10385 *index = min; 10386 found_index = TRUE; 10387 break; 10388 } 10389 max = mid; 10390 } else { 10391 min = mid + 1; 10392 } 10393 } 10394 soc_cm_sfree(u, dmabuf); 10395 10396 if (found_index) { 10397 *mem = mem_to_search[i]; 10398 break; 10399 } 10400 } 10401 10402 if (min > max) { 10403 /* Not found */ 10404 LOG_WARN(BSL_LS_SOC_ALPM, 10405 (BSL_META_U(u, "No corrupted index in L3_DEFIP_AUX_TABLE or " 10406 "L3_DEFIP_DATA_ONLY Pipe %d\n"), pipe)); 10407 return SOC_E_NOT_FOUND; 10408 } else { 10409 LOG_WARN(BSL_LS_SOC_ALPM, 10410 (BSL_META_U(u, "Found corrupted Index %d in %s Table Pipe %d\n"), 10411 *index, SOC_MEM_NAME(u, *mem),pipe)); 10412 return SOC_E_NONE; 10413 } 10414 } 10415 10416 /* Perform an ALPM hardware operation */ 10417 int 10418 _soc_th_alpm_aux_hw_op(int u, _soc_aux_op_t aux_op, 10419 defip_aux_scratch_entry_t *aux_entry, int update_scratch, 10420 int *hit, int *tcam_index, int *log_bkt) 10421 { 10422 soc_timeout_t to; 10423 int pipe, rv = SOC_E_NONE; 10424 int _soc_alpm_aux_op_retry = 0; 10425 10426 uint32 rval[_TH_PIPES_PER_DEV]; 10427 int value[_TH_PIPES_PER_DEV]; 10428 int err[_TH_PIPES_PER_DEV]; 10429 10430 uint32 baddr; 10431 int block; 10432 uint8 acc_type; 10433 int num_pipe; 10434 soc_mem_t mem = INVALIDm; 10435 10436 /* Write to Aux Scratch before performing the operation */ 10437 if (update_scratch) { 10438 SOC_IF_ERROR_RETURN( 10439 WRITE_L3_DEFIP_AUX_SCRATCHm(u, MEM_BLOCK_ANY, 0, aux_entry)); 10440 } 10441 10442 num_pipe = SOC_INFO(u).num_pipe; 10443 10444 _retry: 10445 switch (aux_op) { 10446 case INSERT_PROPAGATE: 10447 value[0] = 0; 10448 break; 10449 case DELETE_PROPAGATE: 10450 value[0] = 1; 10451 break; 10452 case PREFIX_LOOKUP: 10453 value[0] = 2; 10454 break; 10455 case HITBIT_REPLACE: 10456 value[0] = 3; 10457 break; 10458 default: 10459 return SOC_E_PARAM; 10460 } 10461 10462 rval[0] = 0; 10463 10464 /* set opcode */ 10465 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[0], OPCODEf, value[0]); 10466 10467 /* Start opertation */ 10468 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[0], STARTf, 1); 10469 10470 /* Write to Aux ctrl reg */ 10471 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_AUX_CTRLr(u, rval[0])); 10472 soc_timeout_init(&to, 50000, 5); 10473 10474 /* Check for Operation complete */ 10475 sal_memset(value, 0, sizeof(value)); 10476 sal_memset(err, 0, sizeof(err)); 10477 baddr = soc_reg_addr_get(u, L3_DEFIP_AUX_CTRLr, REG_PORT_ANY, 0, 10478 SOC_REG_ADDR_OPTION_NONE, 10479 &block, &acc_type); 10480 10481 do { 10482 for (pipe = 0; pipe < num_pipe; pipe++) { 10483 if (SAL_BOOT_SIMULATION) { 10484 value[pipe] = 1; 10485 err[pipe] = 0; 10486 } else { 10487 SOC_IF_ERROR_RETURN 10488 (_soc_reg32_get(u, block, pipe, baddr, &rval[pipe])); 10489 value[pipe] = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr, 10490 rval[pipe], DONEf); 10491 err[pipe] = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr, 10492 rval[pipe], ERRORf); 10493 } 10494 if (value[pipe] != 1) { 10495 break; 10496 } 10497 } 10498 10499 /* All DONE */ 10500 if (pipe >= num_pipe) { 10501 rv = SOC_E_NONE; 10502 break; 10503 } 10504 10505 if (soc_timeout_check(&to)) { 10506 sal_memset(value, 0, sizeof(value)); 10507 sal_memset(err, 0, sizeof(err)); 10508 for (pipe = 0; pipe < num_pipe; pipe++) { 10509 SOC_IF_ERROR_RETURN 10510 (_soc_reg32_get(u, block, pipe, baddr, &rval[pipe])); 10511 value[pipe] = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr, 10512 rval[pipe], DONEf); 10513 err[pipe] = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr, 10514 rval[pipe], ERRORf); 10515 if (value[pipe] != 1) { 10516 break; 10517 } 10518 } 10519 10520 if (pipe >= num_pipe) { 10521 rv = SOC_E_NONE; 10522 } else { 10523 LOG_WARN(BSL_LS_SOC_ALPM, 10524 (BSL_META_U(u, "unit %d : DEFIP AUX Operation timeout, " 10525 "Pipe %d\n"), u, pipe)); 10526 rv = SOC_E_TIMEOUT; 10527 } 10528 break; 10529 } 10530 } while (1); 10531 10532 if (SOC_SUCCESS(rv)) { 10533 for (pipe = 0; pipe < num_pipe; pipe++) { 10534 if (err[pipe]) { 10535 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[pipe], STARTf, 0); 10536 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[pipe], ERRORf, 0); 10537 soc_reg_field_set(u, L3_DEFIP_AUX_CTRLr, &rval[pipe], DONEf, 0); 10538 SOC_IF_ERROR_RETURN 10539 (_soc_reg32_set(u, block, pipe, baddr, rval[pipe])); 10540 LOG_WARN(BSL_LS_SOC_ALPM, 10541 (BSL_META_U(u, "DEFIP AUX Operation encountered " 10542 "parity error in Pipe %d!!\n"), pipe)); 10543 _soc_alpm_aux_op_retry++; 10544 if (SOC_CONTROL(u)->alpm_bulk_retry) { 10545 sal_sem_take(SOC_CONTROL(u)->alpm_bulk_retry, _SOC_ALPM_AUX_OP_RETRY_TO); 10546 } 10547 if (_soc_alpm_aux_op_retry < _SOC_ALPM_AUX_OP_RETRY_COUNT) { 10548 int err_index; 10549 if (_soc_th_alpm_aux_error_index(u, pipe, &err_index, &mem) >= 0) { 10550 /* Call inline correction with err_index and pipe */ 10551 rv = soc_mem_alpm_aux_table_correction(u, pipe, err_index, mem); 10552 if (rv < 0) { 10553 LOG_ERROR(BSL_LS_SOC_ALPM, 10554 (BSL_META_U(u, "_soc_th_alpm_aux_error_index " 10555 "pipe %d index %d failed\n"), pipe, err_index)); 10556 } 10557 } 10558 LOG_WARN(BSL_LS_SOC_ALPM, 10559 (BSL_META_U(u, "Retry DEFIP AUX Operation in Pipe %d.\n"), 10560 pipe)); 10561 goto _retry; 10562 } else { 10563 LOG_ERROR(BSL_LS_SOC_ALPM, 10564 (BSL_META_U(u, "unit %d: Aborting DEFIP AUX Operation " 10565 "due to un-correctable error !!\n"), u)); 10566 return SOC_E_INTERNAL; 10567 } 10568 } 10569 } 10570 10571 if (aux_op == PREFIX_LOOKUP) { 10572 if (hit && tcam_index) { 10573 int sub_bkt_ptr = 0; 10574 /* Get the hit bit and Bucket index for lookup operations */ 10575 *hit = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr, rval[0], HITf); 10576 *tcam_index = soc_reg_field_get(u, L3_DEFIP_AUX_CTRLr, 10577 rval[0], BKT_INDEXf); 10578 SOC_IF_ERROR_RETURN(READ_L3_DEFIP_AUX_CTRL_1r(u, &rval[1])); 10579 if (ALPM_CTRL(u).bkt_sharing) { 10580 sub_bkt_ptr = soc_reg_field_get(u, L3_DEFIP_AUX_CTRL_1r, 10581 rval[1], SUB_BKT_PTRf); 10582 } 10583 *log_bkt = ALPM_LOG_BKT( 10584 soc_reg_field_get(u, L3_DEFIP_AUX_CTRL_1r, 10585 rval[1], BKT_PTRf), sub_bkt_ptr); 10586 } 10587 } 10588 } 10589 10590 return rv; 10591 } 10592 10593 int 10594 _soc_th_alpm_aux_op(int u, _soc_aux_op_t aux_op, 10595 defip_aux_scratch_entry_t *aux_entry, int update_scratch, 10596 int *hit, int *tcam_index, int *log_bkt, int aux_flags) 10597 { 10598 int rv = SOC_E_NONE; 10599 int cb_cnt = 1; 10600 10601 /* SW propagation: 10602 * 10603 * Callback only being proceeded when cache of LPM TCAM tables is 10604 * turn on. 10605 */ 10606 if (ALPM_CTRL(u).trie_propagate) { 10607 rv = _soc_th_alpm_aux_sw_op(u, aux_op, aux_entry, &cb_cnt, aux_flags); 10608 } 10609 10610 /* No Hardware propagation if aux table is disabled */ 10611 if (!ALPM_CTRL(u).aux_enable) { 10612 return rv; 10613 } 10614 10615 /* Hareware assists only needed when matched pivot is hit. */ 10616 if ((SOC_SUCCESS(rv) && cb_cnt > 0) || ALPM_CTRL(u).force_aux_op) { 10617 uint32 val; 10618 rv = _soc_th_alpm_aux_hw_op(u, aux_op, aux_entry, update_scratch, hit, 10619 tcam_index, log_bkt); 10620 if ((aux_op == INSERT_PROPAGATE || aux_op == DELETE_PROPAGATE) && 10621 SOC_SUCCESS(rv) && SOC_URPF_STATUS_GET(u)) { 10622 soc_mem_t mem = L3_DEFIP_AUX_SCRATCHm; 10623 val = soc_mem_field32_get(u, mem, aux_entry, DB_TYPEf); 10624 soc_mem_field32_set(u, mem, aux_entry, DB_TYPEf, val + 1); 10625 val = (aux_flags & SOC_ALPM_AUX_DEF_ROUTE) ? 1 : 0; 10626 soc_mem_field32_set(u, mem, aux_entry, DEFAULTROUTEf, val); 10627 val = (aux_flags & SOC_ALPM_AUX_SRC_DISCARD) ? 1 : 0; 10628 soc_mem_field32_set(u, mem, aux_entry, SRC_DISCARDf, val); 10629 val = soc_mem_field32_get(u, mem, aux_entry, ALG_HIT_IDXf); 10630 if (val > 0) { 10631 val = _soc_th_alpm_rpf_entry(u, val); 10632 soc_mem_field32_set(u, mem, aux_entry, ALG_HIT_IDXf, val); 10633 } 10634 rv = _soc_th_alpm_aux_hw_op(u, aux_op, aux_entry, TRUE, NULL, 10635 NULL, NULL); 10636 } 10637 } 10638 10639 return rv; 10640 } 10641 10642 /* Initialize the ALPM memory from a TCAM entry */ 10643 static int 10644 _soc_th_alpm_mem_ent_init(int u, int ipv6, void *lpm_entry, 10645 void *alpm_entry, void *alpm_sip_entry, soc_mem_t mem, 10646 uint32 src_flags, uint32 *is_default, int bucket_id) 10647 { 10648 uint32 ipv4a; 10649 uint32 ip6_word[4] = {0, 0}; 10650 int pfx = 0; 10651 int rv = SOC_E_NONE; 10652 uint32 default_route = 0; 10653 10654 /* Zero Buffer */ 10655 sal_memset(alpm_entry, 0, soc_mem_entry_words(u, mem) * 4); 10656 10657 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, HIT0f); 10658 soc_mem_field32_set(u, mem, alpm_entry, HITf, ipv4a); 10659 10660 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, VALID0f); 10661 soc_mem_field32_set(u, mem, alpm_entry, VALIDf, ipv4a); 10662 10663 if (soc_feature(u, soc_feature_generic_dest)) { 10664 ipv4a = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, 10665 DESTINATION0f); 10666 soc_mem_field32_set(u, mem, alpm_entry, DESTINATIONf, ipv4a); 10667 } else { 10668 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ECMP0f); 10669 soc_mem_field32_set(u, mem, alpm_entry, ECMPf, ipv4a); 10670 10671 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ECMP_PTR0f); 10672 soc_mem_field32_set(u, mem, alpm_entry, ECMP_PTRf, ipv4a); 10673 10674 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, NEXT_HOP_INDEX0f); 10675 soc_mem_field32_set(u, mem, alpm_entry, NEXT_HOP_INDEXf, ipv4a); 10676 } 10677 10678 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, PRI0f); 10679 soc_mem_field32_set(u, mem, alpm_entry, PRIf, ipv4a); 10680 10681 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, RPE0f); 10682 soc_mem_field32_set(u, mem, alpm_entry, RPEf, ipv4a); 10683 10684 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, DST_DISCARD0f); 10685 soc_mem_field32_set(u, mem, alpm_entry, DST_DISCARDf, ipv4a); 10686 10687 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, SRC_DISCARD0f); 10688 soc_mem_field32_set(u, mem, alpm_entry, SRC_DISCARDf, ipv4a); 10689 10690 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, CLASS_ID0f); 10691 soc_mem_field32_set(u, mem, alpm_entry, CLASS_IDf, ipv4a); 10692 10693 soc_mem_field32_set(u, mem, alpm_entry, SUB_BKT_PTRf, 10694 ALPM_SUB_BKT(u, bucket_id)); 10695 10696 /* Set IP Address and IP length */ 10697 ip6_word[0] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, IP_ADDR0f); 10698 if (ipv6) { 10699 ip6_word[1] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, IP_ADDR1f); 10700 } 10701 soc_mem_field_set(u, mem, (uint32*)alpm_entry, KEYf, (uint32*)ip6_word); 10702 10703 if (ipv6) { 10704 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f); 10705 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 10706 return(rv); 10707 } 10708 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f); 10709 if (pfx) { 10710 if (ipv4a != 0xffffffff) { 10711 return(SOC_E_PARAM); 10712 } 10713 pfx += 32; 10714 } else { 10715 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 10716 return(rv); 10717 } 10718 } 10719 } else { 10720 ipv4a = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f); 10721 if ((rv = _ipmask2pfx(ipv4a, &pfx)) < 0) { 10722 return(rv); 10723 } 10724 } 10725 if ((pfx == 0) && (ip6_word[0] == 0) && (ip6_word[1] == 0)) { 10726 default_route = 1; 10727 } 10728 if (is_default != NULL) { 10729 *is_default = default_route; 10730 } 10731 soc_mem_field32_set(u, mem, alpm_entry, LENGTHf, pfx); 10732 10733 if (mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64_1m) { 10734 ipv4a = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, FLEX_CTR_BASE_COUNTER_IDX0f); 10735 soc_mem_field32_set(u, mem, alpm_entry, FLEX_CTR_BASE_COUNTER_IDXf, ipv4a); 10736 10737 ipv4a = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, FLEX_CTR_OFFSET_MODE0f); 10738 soc_mem_field32_set(u, mem, alpm_entry, FLEX_CTR_OFFSET_MODEf, ipv4a); 10739 10740 ipv4a = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, FLEX_CTR_POOL_NUMBER0f); 10741 soc_mem_field32_set(u, mem, alpm_entry, FLEX_CTR_POOL_NUMBERf, ipv4a); 10742 } 10743 10744 if (alpm_sip_entry == NULL) { 10745 return (SOC_E_NONE); 10746 } 10747 if (SOC_URPF_STATUS_GET(u)) { 10748 sal_memset(alpm_sip_entry, 0, soc_mem_entry_words(u, mem) * 4); 10749 sal_memcpy(alpm_sip_entry, alpm_entry, soc_mem_entry_words(u, mem) * 4); 10750 soc_mem_field32_set(u, mem, alpm_sip_entry, DST_DISCARDf, 0); 10751 soc_mem_field32_set(u, mem, alpm_sip_entry, RPEf, 0); 10752 10753 soc_mem_field32_set(u, mem, alpm_sip_entry, SRC_DISCARDf, 10754 src_flags & SOC_ALPM_RPF_SRC_DISCARD); 10755 soc_mem_field32_set(u, mem, alpm_sip_entry, DEFAULTROUTEf, 10756 default_route); 10757 #if defined(BCM_TRIDENT3_SUPPORT) 10758 if (SOC_IS_TRIDENT3X(u)) { 10759 if (SOC_MEM_FIELD_VALID(u, mem, FLEX_CTR_BASE_COUNTER_IDXf)) { 10760 soc_mem_field32_set(u, mem, alpm_sip_entry, 10761 FLEX_CTR_BASE_COUNTER_IDXf, 0); 10762 } 10763 if (SOC_MEM_FIELD_VALID(u, mem, FLEX_CTR_BASE_COUNTER_IDX0f)) { 10764 soc_mem_field32_set(u, mem, alpm_sip_entry, 10765 FLEX_CTR_BASE_COUNTER_IDX0f, 0); 10766 } 10767 if (SOC_MEM_FIELD_VALID(u, mem, FLEX_CTR_BASE_COUNTER_IDX1f)) { 10768 soc_mem_field32_set(u, mem, alpm_sip_entry, 10769 FLEX_CTR_BASE_COUNTER_IDX1f, 0); 10770 } 10771 } 10772 #endif 10773 } 10774 return (SOC_E_NONE); 10775 } 10776 10777 /* Initialize the TCAM entry from ALPM memory */ 10778 static int 10779 _soc_th_alpm_lpm_ent_init(int u, void *alpm_entry, soc_mem_t mem, int ipv6, 10780 int vrf_id, int log_bkt, int index, void *lpm_entry, 10781 int flex) 10782 { 10783 uint32 ipv4a; 10784 uint32 ip6_word[4] = {0, 0}; 10785 uint32 pfx = 0; 10786 10787 /* Zero Buffer */ 10788 sal_memset(lpm_entry, 0, soc_mem_entry_words(u, L3_DEFIPm) * 4); 10789 10790 ipv4a = soc_mem_field32_get(u, mem, alpm_entry, HITf); 10791 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, HIT0f, ipv4a); 10792 if (ipv6) { 10793 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, HIT1f, ipv4a); 10794 } 10795 10796 ipv4a = soc_mem_field32_get(u, mem, alpm_entry, VALIDf); 10797 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VALID0f, ipv4a); 10798 if (ipv6) { 10799 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VALID1f, ipv4a); 10800 } 10801 10802 if (soc_feature(u, soc_feature_generic_dest)) { 10803 ipv4a = soc_mem_field32_get(u, mem, alpm_entry, DESTINATIONf); 10804 soc_mem_field32_set(u, L3_DEFIPm, lpm_entry, DESTINATION0f, ipv4a); 10805 } else { 10806 ipv4a = soc_mem_field32_get(u, mem, alpm_entry, ECMPf); 10807 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ECMP0f, ipv4a); 10808 10809 ipv4a = soc_mem_field32_get(u, mem, alpm_entry, ECMP_PTRf); 10810 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ECMP_PTR0f, ipv4a); 10811 10812 ipv4a = soc_mem_field32_get(u, mem, alpm_entry, NEXT_HOP_INDEXf); 10813 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, NEXT_HOP_INDEX0f, ipv4a); 10814 } 10815 10816 ipv4a = soc_mem_field32_get(u, mem, alpm_entry, PRIf); 10817 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, PRI0f, ipv4a); 10818 10819 ipv4a = soc_mem_field32_get(u, mem, alpm_entry, RPEf); 10820 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, RPE0f, ipv4a); 10821 10822 ipv4a = soc_mem_field32_get(u, mem, alpm_entry, DST_DISCARDf); 10823 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, DST_DISCARD0f, ipv4a); 10824 10825 ipv4a = soc_mem_field32_get(u, mem, alpm_entry, SRC_DISCARDf); 10826 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, SRC_DISCARD0f, ipv4a); 10827 10828 ipv4a = soc_mem_field32_get(u, mem, alpm_entry, CLASS_IDf); 10829 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, CLASS_ID0f, ipv4a); 10830 10831 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ALG_BKT_PTR0f, 10832 ALPM_PHY_BKT(u, log_bkt)); 10833 if (ALPM_CTRL(u).bkt_sharing) { 10834 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ALG_SUB_BKT_PTR0f, 10835 ALPM_SUB_BKT(u, log_bkt)); 10836 } 10837 if (index > 0) { 10838 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ALG_HIT_IDX0f, index); 10839 } 10840 soc_mem_field32_set(u, L3_DEFIPm, lpm_entry, MODE_MASK0_f(u), 3); 10841 soc_mem_field32_set(u, L3_DEFIPm, lpm_entry, ENTRY_TYPE_MASK0_f(u), 1); 10842 if (ipv6) { 10843 soc_mem_field32_set(u, L3_DEFIPm, lpm_entry, MODE0_f(u), 1); 10844 soc_mem_field32_set(u, L3_DEFIPm, lpm_entry, MODE1_f(u), 1); 10845 } 10846 10847 /* Set IP Address and IP length */ 10848 soc_mem_field_get(u, mem, alpm_entry, KEYf, ip6_word); 10849 if (ipv6) { 10850 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR1f, 10851 ip6_word[1]); 10852 } 10853 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR0f, ip6_word[0]); 10854 10855 ipv4a = soc_mem_field32_get(u, mem, alpm_entry, LENGTHf); 10856 if (ipv6) { 10857 if (ipv4a >= 32) { 10858 pfx = 0xffffffff; 10859 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, pfx); 10860 pfx = ~SHR_SHIFT_RIGHT(0xffffffff, ipv4a - 32); 10861 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, pfx); 10862 } else { 10863 pfx = ~(0xffffffff >> ipv4a); 10864 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f, pfx); 10865 } 10866 } else { 10867 assert(ipv4a <= 32); 10868 pfx = ~SHR_SHIFT_RIGHT(0xffffffff, ipv4a); 10869 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f, pfx); 10870 } 10871 10872 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, ENTRY_VIEW0f, 10873 _soc_th_alpm_lpm_entry_view_get(u, ipv6, flex)); 10874 10875 if (vrf_id == SOC_L3_VRF_OVERRIDE) { 10876 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, GLOBAL_HIGH0f, 1); 10877 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f, 1); 10878 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_0f, 0); 10879 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f, 0); 10880 } else if (vrf_id == SOC_L3_VRF_GLOBAL) { 10881 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f, 1); 10882 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_0f, 0); 10883 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f, 0); 10884 } else { 10885 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_0f, vrf_id); 10886 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, VRF_ID_MASK0f, 10887 SOC_VRF_MAX(u)); 10888 } 10889 10890 if (mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64_1m) { 10891 ipv4a = soc_mem_field32_get(u, mem, alpm_entry, FLEX_CTR_BASE_COUNTER_IDXf); 10892 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, FLEX_CTR_BASE_COUNTER_IDX0f, ipv4a); 10893 10894 ipv4a = soc_mem_field32_get(u, mem, alpm_entry, FLEX_CTR_OFFSET_MODEf); 10895 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, FLEX_CTR_OFFSET_MODE0f, ipv4a); 10896 10897 ipv4a = soc_mem_field32_get(u, mem, alpm_entry, FLEX_CTR_POOL_NUMBERf); 10898 SOC_MEM_OPT_F32_SET(u, L3_DEFIPm, lpm_entry, FLEX_CTR_POOL_NUMBER0f, ipv4a); 10899 } 10900 return (SOC_E_NONE); 10901 } 10902 10903 STATIC int 10904 _soc_th_alpm_pivot_bmp_len_get(int unit, int ipv6, 10905 void *lpm_entry, uint32 *bpm_len) 10906 { 10907 int rv = SOC_E_NONE; 10908 int vrf_id = 0, vrf = 0; 10909 uint32 length; 10910 uint32 prefix[5] = {0}; 10911 int default_route = 0; 10912 trie_t *pfx_root = NULL; 10913 trie_node_t *lpmp = NULL; 10914 payload_t *tmp_pyld = NULL; 10915 10916 *bpm_len = 0; 10917 10918 SOC_IF_ERROR_RETURN( 10919 soc_th_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf)); 10920 10921 if ((ALPM_PREFIX_IN_TCAM(unit, vrf_id))) { 10922 return rv; 10923 } 10924 10925 SOC_IF_ERROR_RETURN( 10926 _soc_th_alpm_prefix_create(unit, ipv6, lpm_entry, 10927 prefix, &length, &default_route)); 10928 if (ipv6) { 10929 pfx_root = VRF_PREFIX_TRIE_IPV6(unit, vrf); 10930 } else { 10931 pfx_root = VRF_PREFIX_TRIE_IPV4(unit, vrf); 10932 } 10933 10934 /* find longest prefix that covers pivot */ 10935 rv = trie_find_lpm(pfx_root, prefix, length, &lpmp); 10936 if (SOC_FAILURE(rv)) { 10937 return rv; 10938 } 10939 10940 tmp_pyld = (payload_t *)lpmp; 10941 10942 if (tmp_pyld->bkt_ptr) { 10943 *bpm_len = ((payload_t *)(tmp_pyld->bkt_ptr))->len; 10944 } 10945 10946 return rv; 10947 } 10948 10949 int 10950 soc_th_alpm_warmboot_pivot_bmp_len_update(int unit, int ipv6, 10951 void *lpm_entry, int tcam_idx) 10952 { 10953 int rv = SOC_E_NONE; 10954 alpm_pivot_t *pivot = NULL; 10955 uint32 bpm_len = 0; 10956 10957 SOC_IF_ERROR_RETURN( 10958 _soc_th_alpm_pivot_bmp_len_get(unit, ipv6, lpm_entry, &bpm_len)); 10959 10960 tcam_idx = soc_th_alpm_physical_idx(unit, L3_DEFIPm, tcam_idx, ipv6); 10961 10962 pivot = ALPM_TCAM_PIVOT(unit, tcam_idx); 10963 10964 /* update bpm_len */ 10965 PIVOT_TCAM_BPMLEN(pivot) = bpm_len; 10966 10967 return rv; 10968 } 10969 10970 int 10971 soc_th_alpm_warmboot_pivot_add(int unit, 10972 int ipv6, 10973 void *lpm_entry, 10974 int tcam_idx, 10975 int log_bkt) 10976 { 10977 int rv = SOC_E_NONE; 10978 uint32 key[2] = {0}; 10979 alpm_pivot_t *pivot = NULL; 10980 alpm_bucket_handle_t *bucket_handle = NULL; 10981 int vrf_id = 0, vrf = 0; 10982 10983 uint32 length2; 10984 trie_t *pivot_root = NULL; 10985 uint32 prefix[5] = {0}; 10986 uint32 bpm[5] = {0}; 10987 int default_route = 0; 10988 10989 SOC_IF_ERROR_RETURN(_soc_th_alpm_prefix_create(unit, ipv6, lpm_entry, 10990 prefix, &length2, &default_route)); 10991 10992 SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf)); 10993 tcam_idx = soc_th_alpm_physical_idx(unit, L3_DEFIPm, tcam_idx, ipv6); 10994 10995 /* Allocate bucket handle */ 10996 bucket_handle = sal_alloc(sizeof(alpm_bucket_handle_t), "ALPM Bucket Handle"); 10997 if (bucket_handle == NULL) { 10998 LOG_ERROR(BSL_LS_SOC_ALPM, 10999 (BSL_META_U(unit, 11000 "Unable to allocate memory for " 11001 "PIVOT trie node \n"))); 11002 return SOC_E_NONE; 11003 } 11004 sal_memset(bucket_handle, 0, sizeof(*bucket_handle)); 11005 11006 /* Allocate pivot Payload */ 11007 pivot = sal_alloc(sizeof(alpm_pivot_t), "Payload for Pivot"); 11008 if (pivot == NULL) { 11009 LOG_ERROR(BSL_LS_SOC_ALPM, 11010 (BSL_META_U(unit, 11011 "Unable to allocate memory for " 11012 "PIVOT trie node \n"))); 11013 sal_free(bucket_handle); 11014 return SOC_E_MEMORY; 11015 } 11016 sal_memset(pivot, 0, sizeof(*pivot)); 11017 11018 /* Save bucket_handle in pivot->bucket_trie */ 11019 PIVOT_BUCKET_HANDLE(pivot) = bucket_handle; 11020 11021 if (ipv6) { 11022 trie_init(_MAX_KEY_LEN_144_, &PIVOT_BUCKET_TRIE(pivot)); 11023 11024 /* Set address to the buffer. */ 11025 key[0] = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, IP_ADDR0f); 11026 11027 /* Set address to the buffer. */ 11028 key[1] = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, IP_ADDR1f); 11029 } else { 11030 trie_init(_MAX_KEY_LEN_48_, &PIVOT_BUCKET_TRIE(pivot)); 11031 11032 /* Set address to the buffer. */ 11033 key[0] = SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, IP_ADDR0f); 11034 } 11035 11036 /* Save bucket index into pivot->bucket->bucket_index */ 11037 PIVOT_BUCKET_INDEX(pivot) = log_bkt; 11038 11039 /* Save tcam index into pivot->tcam_index */ 11040 PIVOT_TCAM_INDEX(pivot) = tcam_idx; 11041 11042 if (!(ALPM_PREFIX_IN_TCAM(unit, vrf_id))) { 11043 if (ipv6 == 0) { 11044 pivot_root = VRF_PIVOT_TRIE_IPV4(unit, vrf); 11045 if (pivot_root == NULL) { 11046 trie_init(_MAX_KEY_LEN_48_, &VRF_PIVOT_TRIE_IPV4(unit, vrf)); 11047 pivot_root = VRF_PIVOT_TRIE_IPV4(unit, vrf); 11048 } 11049 } else { 11050 pivot_root = VRF_PIVOT_TRIE_IPV6(unit, vrf); 11051 if (pivot_root == NULL) { 11052 trie_init(_MAX_KEY_LEN_144_, &VRF_PIVOT_TRIE_IPV6(unit, vrf)); 11053 pivot_root = VRF_PIVOT_TRIE_IPV6(unit, vrf); 11054 } 11055 } 11056 11057 sal_memcpy(pivot->key, prefix, sizeof(prefix)); 11058 pivot->len = length2; 11059 11060 /* insert into pivot trie */ 11061 rv = trie_insert(pivot_root, pivot->key, 11062 ALPM_CTRL(unit).trie_propagate ? bpm : NULL, 11063 pivot->len, (trie_node_t *)pivot); 11064 if (SOC_FAILURE(rv)) { 11065 sal_free(bucket_handle); 11066 sal_free(pivot); 11067 return rv; 11068 } 11069 } 11070 11071 /* Insert pivot into global pivot array indexed by tcam_idx */ 11072 ALPM_TCAM_PIVOT(unit, tcam_idx) = pivot; 11073 PIVOT_BUCKET_VRF(pivot) = vrf; 11074 PIVOT_BUCKET_IPV6(pivot) = ipv6; 11075 11076 PIVOT_BUCKET_ENT_CNT_UPDATE(pivot); 11077 if (key[0] == 0 && key[1] == 0) { 11078 PIVOT_BUCKET_DEF(pivot) = TRUE; 11079 } 11080 11081 return rv; 11082 } 11083 11084 11085 static int 11086 _soc_th_alpm_warmboot_insert(int unit, 11087 int ipv6, 11088 int flex, 11089 void *lpm_entry, 11090 void *alpm_entry, /* ALPM (SRAM) entry data */ 11091 int tcam_idx, /* TCAM index */ 11092 int log_bkt, /* Bucket index */ 11093 int alpm_idx ) /* ALPM entry index */ 11094 { 11095 int vrf_id; /* Internal API representation of VRF id */ 11096 int vrf; /* VRF in 0 to (MAX_VRF + 1) range; */ 11097 /* VRF = (MAX_VRF + 1), software rep of GLOBAL VRF */ 11098 int rv = SOC_E_NONE; 11099 int default_route = 0; 11100 uint32 prefix[5] = {0, 0, 0, 0, 0}; 11101 uint32 length; 11102 defip_entry_t temp_lpm_entry; 11103 trie_t *bkt_trie = NULL; 11104 trie_t *pfx_trie = NULL; 11105 trie_node_t *delp = NULL; 11106 payload_t *bkt_payload = NULL; 11107 payload_t *pfx_payload = NULL; 11108 alpm_pivot_t *pivot_pyld = NULL; 11109 soc_mem_t mem; 11110 11111 /* Check function params */ 11112 if ((NULL == lpm_entry) || (NULL == alpm_entry)) { 11113 return SOC_E_PARAM; 11114 } 11115 11116 /* Check IPv6 */ 11117 if (ipv6) { 11118 if (!(ipv6 = soc_mem_field32_get(unit, L3_DEFIPm, lpm_entry, MODE1_f(unit)))) { 11119 return (SOC_E_PARAM); 11120 } 11121 } 11122 11123 /* Get VRF */ 11124 SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf)); 11125 11126 /* Get ALPM table memory. */ 11127 SOC_ALPM_TABLE_MEM(unit, ipv6, mem, flex); 11128 11129 /* Convert alpm_entry into lpm_entry to extract prefix */ 11130 SOC_IF_ERROR_RETURN(_soc_th_alpm_lpm_ent_init(unit, alpm_entry, mem, ipv6, 11131 vrf_id, log_bkt, tcam_idx, 11132 &temp_lpm_entry, 0)); 11133 11134 /* Create Prefix */ 11135 rv = _soc_th_alpm_prefix_create(unit, ipv6, &temp_lpm_entry, prefix, 11136 &length, &default_route); 11137 if (SOC_FAILURE(rv)) { 11138 LOG_ERROR(BSL_LS_SOC_ALPM, 11139 (BSL_META_U(unit, 11140 "prefix create failed\n"))); 11141 return rv; 11142 } 11143 11144 /* Get TCAM pivot */ 11145 pivot_pyld = ALPM_TCAM_PIVOT(unit, tcam_idx); 11146 11147 /* Get bucket trie from pivot */ 11148 bkt_trie = PIVOT_BUCKET_TRIE(pivot_pyld); 11149 11150 /* Allocate bucket payload */ 11151 bkt_payload = sal_alloc(sizeof(payload_t), "Payload for Key"); 11152 if (NULL == bkt_payload) { 11153 LOG_ERROR(BSL_LS_SOC_ALPM, 11154 (BSL_META_U(unit, 11155 "Unable to allocate memory for trie node.\n"))); 11156 return SOC_E_MEMORY; 11157 } 11158 11159 /* Allocate prefix trie payload */ 11160 pfx_payload = sal_alloc(sizeof(payload_t), "Payload for pfx trie key"); 11161 if (NULL == pfx_payload) { 11162 LOG_ERROR(BSL_LS_SOC_ALPM, 11163 (BSL_META_U(unit, 11164 "Unable to allocate memory for pfx trie node\n"))); 11165 sal_free(bkt_payload); 11166 return SOC_E_MEMORY; 11167 } 11168 11169 /* Clear allocated payloads */ 11170 sal_memset(bkt_payload, 0, sizeof(*bkt_payload)); 11171 sal_memset(pfx_payload, 0, sizeof(*pfx_payload)); 11172 11173 bkt_payload->key[0] = prefix[0]; 11174 bkt_payload->key[1] = prefix[1]; 11175 bkt_payload->key[2] = prefix[2]; 11176 bkt_payload->key[3] = prefix[3]; 11177 bkt_payload->key[4] = prefix[4]; 11178 bkt_payload->len = length; 11179 bkt_payload->index = alpm_idx; 11180 11181 #ifdef ALPM_WARM_BOOT_DEBUG_EXTENSIVE 11182 LOG_ERROR(BSL_LS_SOC_ALPM, 11183 (BSL_META_U(unit, 11184 "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, length = 0x%x alpm_idx = 0x%x\n"), 11185 bkt_payload->key[0], bkt_payload->key[1], bkt_payload->key[2], 11186 bkt_payload->key[3], bkt_payload->key[4], 11187 length, alpm_idx)); 11188 #endif 11189 11190 /* Create duplicate for prefix trie */ 11191 sal_memcpy(pfx_payload, bkt_payload, sizeof(*bkt_payload)); 11192 pfx_payload->bkt_ptr = bkt_payload; 11193 11194 /* Insert prefix into bucket-trie */ 11195 rv = trie_insert(bkt_trie, prefix, NULL, length, 11196 (trie_node_t *)bkt_payload); 11197 if (SOC_FAILURE(rv)) { 11198 goto free_memory; 11199 } 11200 11201 /* Insert prefix into prefix-trie */ 11202 if (ipv6) { 11203 pfx_trie = VRF_PREFIX_TRIE_IPV6(unit, vrf); 11204 } else { 11205 pfx_trie = VRF_PREFIX_TRIE_IPV4(unit, vrf); 11206 } 11207 11208 if (!default_route) { 11209 uint32 bpm[5]; 11210 11211 _soc_th_alpm_mask_prefix_create(unit, ipv6, length, bpm); 11212 /* Default route already in prefix trie */ 11213 rv = trie_insert(pfx_trie, prefix, 11214 ALPM_CTRL(unit).trie_propagate ? bpm : NULL, 11215 length, (trie_node_t *)pfx_payload); 11216 if (SOC_FAILURE(rv)) { 11217 goto delete_bkt_trie; 11218 } 11219 } 11220 11221 /* Return success */ 11222 return rv; 11223 11224 delete_bkt_trie: 11225 (void) trie_delete(bkt_trie, prefix, length, &delp); 11226 bkt_payload = (payload_t *) delp; 11227 11228 free_memory: 11229 sal_free(bkt_payload); 11230 sal_free(pfx_payload); 11231 return rv; 11232 } 11233 11234 /* 11235 * soc_th_alpm_warmboot_vrf_add 11236 */ 11237 static int 11238 soc_th_alpm_warmboot_vrf_add(int unit, 11239 int v6, 11240 int vrf, 11241 int idx, 11242 int log_bkt) 11243 { 11244 11245 int rv = SOC_E_NONE; 11246 uint32 length; 11247 uint32 key[5] = {0}; 11248 trie_t *pfx_root = NULL; 11249 payload_t *pfx_pyld = NULL; 11250 defip_entry_t *lpm_entry = NULL; 11251 11252 /* Initialize VRF PIVOT IPV4 trie */ 11253 lpm_entry = sal_alloc(sizeof(defip_entry_t), "Default LPM entry"); 11254 if (lpm_entry == NULL) { 11255 LOG_ERROR(BSL_LS_SOC_ALPM, 11256 (BSL_META_U(unit, 11257 "unable to allocate memory for LPM entry\n"))); 11258 return SOC_E_MEMORY; 11259 } 11260 11261 /* Initialize an lpm entry to perform a match */ 11262 _soc_th_alpm_lpm_ent_key_init(unit, key, 0, vrf, v6, lpm_entry, 1); 11263 11264 /* for global VRF */ 11265 if (vrf == SOC_VRF_MAX(unit) + 1) { 11266 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f, 1); 11267 } else { 11268 /* Set default miss to global route only for non global routes */ 11269 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, DEFAULT_MISS0f, 1); 11270 } 11271 11272 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, ALG_BKT_PTR0f, 11273 ALPM_PHY_BKT(unit, log_bkt)); 11274 if (ALPM_CTRL(unit).bkt_sharing) { 11275 SOC_MEM_OPT_F32_SET(unit, L3_DEFIPm, lpm_entry, ALG_SUB_BKT_PTR0f, 11276 ALPM_SUB_BKT(unit, log_bkt)); 11277 } 11278 11279 if (v6 == 0) { 11280 VRF_TRIE_DEFAULT_ROUTE_IPV4(unit, vrf) = lpm_entry; 11281 trie_init(_MAX_KEY_LEN_48_, &VRF_PREFIX_TRIE_IPV4(unit, vrf)); 11282 pfx_root = VRF_PREFIX_TRIE_IPV4(unit, vrf); 11283 } else { 11284 VRF_TRIE_DEFAULT_ROUTE_IPV6(unit, vrf) = lpm_entry; 11285 trie_init(_MAX_KEY_LEN_144_, &VRF_PREFIX_TRIE_IPV6(unit, vrf)); 11286 pfx_root = VRF_PREFIX_TRIE_IPV6(unit, vrf); 11287 } 11288 11289 pfx_pyld = sal_alloc(sizeof(payload_t), "Payload for pfx trie key"); 11290 if (pfx_pyld == NULL) { 11291 LOG_ERROR(BSL_LS_SOC_ALPM, 11292 (BSL_META_U(unit, 11293 "Unable to allocate memory for pfx trie node \n"))); 11294 return SOC_E_MEMORY; 11295 } 11296 11297 sal_memset(pfx_pyld, 0, sizeof(*pfx_pyld)); 11298 11299 length = 0; 11300 pfx_pyld->key[0] = key[0]; 11301 pfx_pyld->key[1] = key[1]; 11302 pfx_pyld->len = length; 11303 11304 rv = trie_insert(pfx_root, key, ALPM_CTRL(unit).trie_propagate ? key : NULL, 11305 length, &(pfx_pyld->node)); 11306 if (SOC_FAILURE(rv)) { 11307 sal_free(pfx_pyld); 11308 return rv; 11309 } 11310 11311 VRF_TRIE_INIT_DONE(unit, vrf, v6, 1); 11312 11313 return rv; 11314 } 11315 /* 11316 * soc_th_alpm_warmboot_prefix_insert 11317 */ 11318 int 11319 soc_th_alpm_warmboot_prefix_insert(int unit, 11320 int ipv6, 11321 int flex, 11322 void *lpm_entry, 11323 void *alpm_entry, 11324 int tcam_idx, 11325 int log_bkt, 11326 int alpm_idx) 11327 { 11328 int vrf_id; /* Internal API representation of VRF id */ 11329 int vrf; /* VRF in (0 - (MAX_VRF + 1)) range */ 11330 int rv = SOC_E_NONE; 11331 soc_mem_t mem; 11332 11333 tcam_idx = soc_th_alpm_physical_idx(unit, L3_DEFIPm, tcam_idx, ipv6); 11334 11335 /* Get ALPM table memory. */ 11336 SOC_ALPM_TABLE_MEM(unit, ipv6, mem, flex); 11337 11338 /* Get VRF */ 11339 SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf)); 11340 11341 /* For VRF_OVERRIDE (Global High) entries, Prefix resides in TCAM directly */ 11342 if (ALPM_PREFIX_IN_TCAM(unit, vrf_id)) { 11343 return(rv); 11344 } 11345 /* Non override entries, goes into ALPM memory */ 11346 if (!VRF_TRIE_INIT_COMPLETED(unit, vrf, ipv6)) { 11347 LOG_VERBOSE(BSL_LS_SOC_ALPM, 11348 (BSL_META_U(unit, 11349 "VRF %d is not initialized\n"), 11350 vrf)); 11351 rv = soc_th_alpm_warmboot_vrf_add(unit, ipv6, vrf, tcam_idx, log_bkt); 11352 if (SOC_FAILURE(rv)) { 11353 LOG_ERROR(BSL_LS_SOC_ALPM, 11354 (BSL_META_U(unit, 11355 "VRF %d/%d trie init \n" 11356 "failed\n"), vrf, ipv6)); 11357 return rv; 11358 } 11359 11360 LOG_VERBOSE(BSL_LS_SOC_ALPM, 11361 (BSL_META_U(unit, 11362 "VRF %d/%d trie init completed\n"), 11363 vrf, ipv6)); 11364 } 11365 11366 rv = _soc_th_alpm_warmboot_insert(unit, ipv6, flex, lpm_entry, alpm_entry, 11367 tcam_idx, log_bkt, alpm_idx); 11368 if (rv != SOC_E_NONE) { 11369 LOG_WARN(BSL_LS_SOC_ALPM, 11370 (BSL_META_U(unit, 11371 "unit %d : Route Insertion Failed :%s\n"), 11372 unit, soc_errmsg(rv))); 11373 11374 return(rv); 11375 } 11376 11377 soc_th_alpm_bucket_usage_incr(unit, log_bkt, tcam_idx, vrf, mem, 1); 11378 11379 VRF_TRIE_ROUTES_INC(unit, vrf_id, vrf, ipv6); 11380 return(rv); 11381 } 11382 11383 /* 11384 * alpm_warmboot_bucket_bitmap_set 11385 * This function will set bit position in bucket bitmap 11386 */ 11387 int 11388 soc_th_alpm_warmboot_bucket_bitmap_set(int u, /* Unit */ 11389 int vrf, /* VRF */ 11390 int v6, /* Flag v4/v6 */ 11391 int phy_bkt) /* Bucket index */ 11392 { 11393 int step_count = 1; 11394 uint8 ipv = !!v6; 11395 SHR_BITDCL *bkt_bmap = SOC_TH_ALPM_VRF_BUCKET_BMAP(u, ipv); 11396 11397 if (vrf == SOC_VRF_MAX(u) + 1) { 11398 bkt_bmap = SOC_TH_ALPM_GLB_BUCKET_BMAP(u, ipv); 11399 } 11400 11401 /* 11402 * In combined search mode, with urpf disabled, need to allocate even and 11403 * odd bucket pointers 11404 */ 11405 if (ALPM_CTRL(u).double_wide[v6]) { 11406 step_count = 2; 11407 } 11408 11409 /* Set bit position */ 11410 SHR_BITSET_RANGE(bkt_bmap, phy_bkt, step_count); 11411 11412 return SOC_E_NONE; 11413 } 11414 11415 int 11416 soc_th_alpm_warmboot_lpm_reinit_done(int unit) 11417 { 11418 int idx; 11419 int prev_idx = ALPM_MAX_PFX_INDEX; 11420 int alpm_mode; 11421 int defip_table_size = soc_mem_index_count(unit, L3_DEFIPm); 11422 11423 if (SOC_URPF_STATUS_GET(unit)) { 11424 defip_table_size >>= 1; 11425 } 11426 11427 /* returns 0 for combined search mode and 1 for parallel search mode */ 11428 alpm_mode = ALPM_CTRL(unit).alpm_mode; 11429 if (alpm_mode == SOC_ALPM_MODE_COMBINED) { 11430 /* Combined search mode */ 11431 SOC_ALPM_LPM_STATE_PREV(unit, ALPM_MAX_PFX_INDEX) = -1; 11432 11433 for (idx = ALPM_MAX_PFX_INDEX; idx > -1; idx--) { 11434 if (-1 == SOC_ALPM_LPM_STATE_START(unit, idx)) { 11435 continue; 11436 } 11437 11438 SOC_ALPM_LPM_STATE_PREV(unit, idx) = prev_idx; 11439 SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = idx; 11440 11441 SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) = \ 11442 SOC_ALPM_LPM_STATE_START(unit, idx) - \ 11443 SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1; 11444 prev_idx = idx; 11445 11446 } 11447 11448 SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = -1; 11449 SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) = \ 11450 defip_table_size - \ 11451 SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1; 11452 } else if ((alpm_mode == SOC_ALPM_MODE_PARALLEL) || 11453 (alpm_mode == SOC_ALPM_MODE_TCAM_ALPM)) { 11454 /* Parallel search mode or TCAM/ALPM mode 11455 * 11456 * Configured VRF Range 11457 * {0 - (ALPM_MAX_PFX_INDEX/3)} 11458 * Global VRF Range 11459 * {((ALPM_MAX_PFX_INDEX/1) + 1) - (ALPM_MAX_PFX_INDEX/2) } 11460 * Override VRF Range 11461 * {((ALPM_MAX_PFX_INDEX/2) + 1) - (ALPM_MAX_PFX_INDEX) } 11462 */ 11463 11464 /* 11465 * Global and Overide VRF range are treated as single block and 11466 * both blocks will be linked 11467 */ 11468 SOC_ALPM_LPM_STATE_PREV(unit, ALPM_MAX_PFX_INDEX) = -1; 11469 for (idx = ALPM_MAX_PFX_INDEX; idx > (ALPM_MAX_PFX_INDEX/3) ; idx--) { 11470 if (-1 == SOC_ALPM_LPM_STATE_START(unit, idx)) { 11471 continue; 11472 } 11473 11474 SOC_ALPM_LPM_STATE_PREV(unit, idx) = prev_idx; 11475 SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = idx; 11476 11477 SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) = \ 11478 SOC_ALPM_LPM_STATE_START(unit, idx) - \ 11479 SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1; 11480 11481 prev_idx = idx; 11482 } 11483 SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = -1; 11484 SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) = \ 11485 defip_table_size - \ 11486 SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1; 11487 11488 /* Configured VRF range */ 11489 prev_idx = (ALPM_MAX_PFX_INDEX/3); 11490 SOC_ALPM_LPM_STATE_PREV(unit, (ALPM_MAX_PFX_INDEX/3)) = -1; 11491 for (idx = ((ALPM_MAX_PFX_INDEX/3)-1); idx > -1; idx--) { 11492 if (-1 == SOC_ALPM_LPM_STATE_START(unit, idx)) { 11493 continue; 11494 } 11495 11496 SOC_ALPM_LPM_STATE_PREV(unit, idx) = prev_idx; 11497 SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = idx; 11498 11499 SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) = \ 11500 SOC_ALPM_LPM_STATE_START(unit, idx) - \ 11501 SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1; 11502 prev_idx = idx; 11503 } 11504 SOC_ALPM_LPM_STATE_NEXT(unit, prev_idx) = -1; 11505 SOC_ALPM_LPM_STATE_FENT(unit, prev_idx) = \ 11506 (defip_table_size >> 1) - \ 11507 SOC_ALPM_LPM_STATE_END(unit, prev_idx) - 1; 11508 } 11509 11510 return (SOC_E_NONE); 11511 } 11512 11513 int 11514 soc_th_alpm_warmboot_lpm_reinit(int unit, 11515 int ipv6, 11516 int idx, 11517 void *lpm_entry) 11518 { 11519 int pfx_len; 11520 int flex; 11521 defip_entry_t lpm_entry_hi; 11522 int vrf_id, vrf; 11523 11524 if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VALID0f) || 11525 SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VALID1f)) { 11526 LPM_HASH_INSERT(unit, lpm_entry, idx, NULL, NULL); 11527 } 11528 11529 if (ipv6) { 11530 if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VALID0f)) { 11531 SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf)); 11532 if (!VRF_FLEX_COMPLETED(unit, vrf_id, vrf, ipv6)) { 11533 flex = _soc_th_alpm_lpm_flex_get(unit, ipv6, 11534 SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, 11535 lpm_entry, ENTRY_VIEW0f)); 11536 VRF_FLEX_SET(unit, vrf_id, vrf, ipv6, flex); 11537 } 11538 VRF_PIVOT_REF_INC(unit, vrf_id, vrf, ipv6); 11539 } 11540 } else { 11541 if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VALID0f)) { 11542 SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(unit, lpm_entry, &vrf_id, &vrf)); 11543 if (!VRF_FLEX_COMPLETED(unit, vrf_id, vrf, ipv6)) { 11544 flex = _soc_th_alpm_lpm_flex_get(unit, ipv6, 11545 SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, 11546 lpm_entry, ENTRY_VIEW0f)); 11547 VRF_FLEX_SET(unit, vrf_id, vrf, ipv6, flex); 11548 } 11549 VRF_PIVOT_REF_INC(unit, vrf_id, vrf, ipv6); 11550 } 11551 if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VALID1f)) { 11552 soc_th_alpm_lpm_ip4entry1_to_0(unit, lpm_entry, &lpm_entry_hi, TRUE); 11553 SOC_IF_ERROR_RETURN(soc_th_alpm_lpm_vrf_get(unit, &lpm_entry_hi, &vrf_id, &vrf)); 11554 if (!VRF_FLEX_COMPLETED(unit, vrf_id, vrf, ipv6)) { 11555 flex = _soc_th_alpm_lpm_flex_get(unit, ipv6, 11556 SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, 11557 lpm_entry, ENTRY_VIEW1f)); 11558 VRF_FLEX_SET(unit, vrf_id, vrf, ipv6, flex); 11559 } 11560 VRF_PIVOT_REF_INC(unit, vrf_id, vrf, ipv6); 11561 } 11562 } 11563 11564 if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VALID0f)) { 11565 SOC_IF_ERROR_RETURN 11566 (_soc_th_alpm_lpm_prefix_length_get(unit, ipv6, lpm_entry, 11567 &pfx_len, 0, 0)); 11568 11569 if (SOC_ALPM_LPM_STATE_VENT(unit, pfx_len) == 0) { 11570 SOC_ALPM_LPM_STATE_START(unit, pfx_len) = idx; 11571 SOC_ALPM_LPM_STATE_END(unit, pfx_len) = idx; 11572 } else { 11573 SOC_ALPM_LPM_STATE_END(unit, pfx_len) = idx; 11574 } 11575 11576 SOC_ALPM_LPM_STATE_VENT(unit, pfx_len)++; 11577 11578 if (ipv6) { 11579 /* IPv6 entry */ 11580 return (SOC_E_NONE); 11581 } 11582 } else { 11583 /* Check upper half of lpm_entry */ 11584 if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, VALID1f)) { 11585 if (ipv6) { 11586 return SOC_E_NONE; 11587 } 11588 11589 /* Get prefix length */ 11590 SOC_IF_ERROR_RETURN 11591 (_soc_th_alpm_lpm_prefix_length_get(unit, ipv6, &lpm_entry_hi, 11592 &pfx_len, 0, 0)); 11593 11594 if (SOC_ALPM_LPM_STATE_VENT(unit, pfx_len) == 0) { 11595 SOC_ALPM_LPM_STATE_START(unit, pfx_len) = idx; 11596 SOC_ALPM_LPM_STATE_END(unit, pfx_len) = idx; 11597 } else { 11598 SOC_ALPM_LPM_STATE_END(unit, pfx_len) = idx; 11599 } 11600 11601 SOC_ALPM_LPM_STATE_VENT(unit, pfx_len)++; 11602 } 11603 } 11604 return (SOC_E_NONE); 11605 } 11606 11607 /* Walk through all ALPM table to check if uRPF entries is installing well */ 11608 void 11609 soc_th_alpm_dbg_urpf(int u) 11610 { 11611 int rv = SOC_E_NONE; 11612 soc_mem_t mem; 11613 int i, phy_bkt; 11614 int index; 11615 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 11616 uint32 eu[SOC_MAX_MEM_FIELD_WORDS]; 11617 11618 int good = 0, bad = 0; 11619 11620 if (!SOC_URPF_STATUS_GET(u)) { 11621 LOG_CLI((BSL_META_U(u, "Only supported in uRPF mode\n"))); 11622 return ; 11623 } 11624 11625 for (phy_bkt = 0; phy_bkt <= ALPM_CTRL(u).num_bkts / 2; phy_bkt++) { 11626 index = SOC_TH_ALPM_AIDX(u, phy_bkt, 0, 0, 0); 11627 mem = soc_alpm_cmn_bkt_view_get(u, index); 11628 11629 /* Iter entry based on memory type */ 11630 for (i = 0; i < SOC_TH_MAX_BUCKET_ENTRIES(u) - 1; i++) { 11631 rv = _soc_th_alpm_mem_index(u, mem, phy_bkt, i, 0, &index); 11632 if (SOC_FAILURE(rv)) { 11633 continue; 11634 } 11635 11636 sal_memset(e, 0, sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS); 11637 sal_memset(eu, 0, sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS); 11638 11639 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, index, e); 11640 if (SOC_FAILURE(rv)) { 11641 continue; 11642 } 11643 if (soc_mem_field32_get(u, mem, e, VALIDf) == 0) { 11644 continue; 11645 } 11646 11647 soc_mem_field32_set(u, mem, e, HITf, 0); 11648 11649 rv = _soc_mem_alpm_read(u, mem, MEM_BLOCK_ANY, _soc_th_alpm_rpf_entry(u, index), eu); 11650 if (SOC_FAILURE(rv)) { 11651 continue; 11652 } 11653 soc_mem_field32_set(u, mem, eu, HITf, 0); 11654 soc_mem_field32_set(u, mem, eu, RPEf, 0); 11655 11656 if (sal_memcmp(e, eu, sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS) != 0) { 11657 LOG_CLI((BSL_META_U(u, 11658 "uRPF sanity check failed: bucket %4d mem %s index %d uRPF index %d\n"), 11659 phy_bkt, SOC_MEM_NAME(u, mem), index, _soc_th_alpm_rpf_entry(u, index))); 11660 bad ++; 11661 } else { 11662 good ++; 11663 } 11664 } 11665 } 11666 11667 LOG_CLI((BSL_META_U(u, "uRPF Sanity check finished, good %d bad %d\n"), good, bad)); 11668 11669 return ; 11670 } 11671 11672 /* Helper structure for Debug Counter */ 11673 typedef struct _alpm_dbg_cnt_s { 11674 int v4; /* Counter for IPv4 */ 11675 int v6_64; 11676 int v6_128; 11677 int v4t; /* Totaled counter for IPv4 per VRF */ 11678 int v6_64t; 11679 int v6_128t; 11680 int used; 11681 } _alpm_dbg_cnt_t; 11682 11683 typedef enum _alpm_pvt_cnt_type_e { 11684 SOC_ALPM_DEBUG_CNT_ADD = 0, 11685 SOC_ALPM_DEBUG_CNT_DEL, 11686 SOC_ALPM_DEBUG_CNT_SPLIT, 11687 SOC_ALPM_DEBUG_CNT_USED, 11688 SOC_ALPM_DEBUG_CNT_LPM_SHIFT, 11689 SOC_ALPM_DEBUG_CNT_LPM_FULL 11690 } _alpm_pvt_cnt_type_t; 11691 11692 11693 #define _ALPM_DBG_CNT_ADD(dst_dc, src_dc) \ 11694 do { \ 11695 (dst_dc)->v4 += (src_dc)->v4; \ 11696 (dst_dc)->v4t += (src_dc)->v4t; \ 11697 (dst_dc)->v6_64 += (src_dc)->v6_64; \ 11698 (dst_dc)->v6_64t += (src_dc)->v6_64t; \ 11699 (dst_dc)->v6_128 += (src_dc)->v6_128; \ 11700 (dst_dc)->v6_128t += (src_dc)->v6_128t; \ 11701 } while (0) 11702 11703 /* Common debug counter print */ 11704 #define PRINT_SPLIT_LINE(u) \ 11705 LOG_CLI((BSL_META_U(u, "-----------------------------------------------\n"))) 11706 #define PRINT_VRF_HEADER(u) \ 11707 LOG_CLI((BSL_META_U(u, "\n VRF v4 v6-64 v6-128 | AVG\n"))) 11708 #define PRINT_VRF_NOT_FOUND(u) \ 11709 LOG_CLI((BSL_META_U(u, "%9s\n"), "Specific VRF not found")) 11710 11711 /* Print Bucket Occupancy */ 11712 #define BKT_PERCENT(used, tot) \ 11713 (tot) ? (used) * 100 / (tot) : 0, (tot) ? (used) * 1000 / (tot) % 10 : 0 11714 #define PRINT_BKT_OCCU_ITEM(u, vrf, tmp_dc) \ 11715 do { \ 11716 LOG_CLI((BSL_META_U(u, \ 11717 "%9d %02d.%d%% %02d.%d%% %02d.%d%% | %02d.%d%% %5s\n"), \ 11718 (vrf), BKT_PERCENT(tmp_dc->v4, tmp_dc->v4t), \ 11719 BKT_PERCENT(tmp_dc->v6_64, tmp_dc->v6_64t), \ 11720 BKT_PERCENT(tmp_dc->v6_128, tmp_dc->v6_128t), \ 11721 BKT_PERCENT((tmp_dc->v4+tmp_dc->v6_64+tmp_dc->v6_128),\ 11722 (tmp_dc->v4t+tmp_dc->v6_64t+tmp_dc->v6_128t)), \ 11723 (vrf) == SOC_VRF_MAX(u)+1 ? "GLo" : "")); \ 11724 } while (0) 11725 #define PRINT_BKT_OCCU_ITEM_TOT(u, all_dc) \ 11726 do { \ 11727 LOG_CLI((BSL_META_U(u, \ 11728 "%9s %02d.%d%% %02d.%d%% %02d.%d%% | %02d.%d%% \n"), \ 11729 "AVG", BKT_PERCENT((all_dc)->v4, (all_dc)->v4t), \ 11730 BKT_PERCENT((all_dc)->v6_64, (all_dc)->v6_64t), \ 11731 BKT_PERCENT((all_dc)->v6_128, (all_dc)->v6_128t), \ 11732 BKT_PERCENT(((all_dc)->v4+(all_dc)->v6_64+(all_dc)->v6_128),\ 11733 ((all_dc)->v4t+(all_dc)->v6_64t+(all_dc)->v6_128t)))); \ 11734 } while (0) 11735 11736 11737 /* Print VRF based debug counter */ 11738 #define PRINT_VRF_ITEM(u, vrf, v4, v6_64, v6_128, total) \ 11739 do { \ 11740 LOG_CLI((BSL_META_U(u, \ 11741 "%9d %-7d %-7d %-7d | %-7d %s\n"), \ 11742 (vrf == MAX_VRF_ID ? -1 : vrf), (v4), (v6_64),\ 11743 (v6_128), (total), (vrf) == MAX_VRF_ID ? "GHi" : \ 11744 (vrf) == SOC_VRF_MAX(u)+1 ? "GLo" : "")); \ 11745 } while (0) 11746 #define PRINT_VRF_ITEM_TOT(u, v4, v6_64, v6_128, total) \ 11747 do { \ 11748 LOG_CLI((BSL_META_U(u, \ 11749 "%9s %-7d %-7d %-7d | %-7d \n"), "Total", (v4), (v6_64),\ 11750 (v6_128), (total))); \ 11751 } while (0) 11752 11753 #define PRINT_BUCKET_HEADER(u) \ 11754 do { \ 11755 LOG_CLI((BSL_META_U(u, \ 11756 "\nPivot/VRF Min Max Cur | Comment\n"))); \ 11757 } while (0) 11758 #define PRINT_BUCKET_ITEM(u, bkt, vrf, min, max, cur, def) \ 11759 do { \ 11760 LOG_CLI((BSL_META_U(u, \ 11761 "%5d/%-4d %-7d %-7d %-7d | %-7s\n"), bkt, vrf, \ 11762 min, max, cur, def ? "Def" : \ 11763 (vrf) == SOC_VRF_MAX(u)+1 ? "GLo" : "")); \ 11764 } while (0) 11765 11766 /* Get max available IPv4, IPv6-64, IPv6-128 entry numbers */ 11767 static void 11768 _soc_th_alpm_pivot_max_get(int u, alpm_vrf_counter_t *pvt_max) 11769 { 11770 pvt_max->v4 = soc_mem_index_count(u, L3_DEFIPm) * 2; 11771 pvt_max->v6_128 = soc_mem_index_count(u, L3_DEFIP_PAIR_128m); 11772 11773 if (SOC_ALPM_128B_ENABLE(u)) { 11774 pvt_max->v6_64 = pvt_max->v6_128; 11775 } else { 11776 pvt_max->v6_64 = pvt_max->v4 >> 1; 11777 } 11778 11779 if (SOC_URPF_STATUS_GET(u)) { 11780 pvt_max->v4 >>= 1; 11781 pvt_max->v6_128 >>= 1; 11782 pvt_max->v6_64 >>= 1; 11783 } 11784 } 11785 11786 static void 11787 _soc_th_alpm_pivot_debug_dump(int u, int vrf_id, alpm_vrf_handle_t *vh, 11788 _alpm_pvt_cnt_type_t pct) 11789 { 11790 alpm_vrf_counter_t *vc; 11791 int i, tv4c, tv6_64c, tv6_128c; 11792 int found = 0; 11793 11794 alpm_vrf_counter_t pvt_max; 11795 11796 /* Print Pivot debug info header */ 11797 switch (pct) { 11798 case SOC_ALPM_DEBUG_CNT_ADD: 11799 LOG_CLI((BSL_META_U(u, 11800 "\nAdd Counter:\n"))); 11801 break; 11802 case SOC_ALPM_DEBUG_CNT_DEL: 11803 LOG_CLI((BSL_META_U(u, 11804 "\nDelete Counter:\n"))); 11805 break; 11806 case SOC_ALPM_DEBUG_CNT_SPLIT: 11807 LOG_CLI((BSL_META_U(u, 11808 "\nInternal Debug Counter - Split:\n"))); 11809 break; 11810 case SOC_ALPM_DEBUG_CNT_USED: 11811 _soc_th_alpm_pivot_max_get(u, &pvt_max); 11812 LOG_CLI((BSL_META_U(u, 11813 "\nPivot Occupancy: Max v4/v6-64/v6-128 = %d/%d/%d\n"), 11814 pvt_max.v4, pvt_max.v6_64, pvt_max.v6_128)); 11815 break; 11816 case SOC_ALPM_DEBUG_CNT_LPM_SHIFT: 11817 LOG_CLI((BSL_META_U(u, 11818 "\nInternal Debug Counter - LPM Shift:\n"))); 11819 break; 11820 case SOC_ALPM_DEBUG_CNT_LPM_FULL: 11821 LOG_CLI((BSL_META_U(u, 11822 "\nInternal Debug Counter - LPM Full:\n"))); 11823 break; 11824 default: 11825 break; 11826 } 11827 PRINT_VRF_HEADER(u); 11828 PRINT_SPLIT_LINE(u); 11829 11830 tv4c = tv6_64c = tv6_128c = 0; 11831 for (i = 0; i < MAX_VRF_ID + 1; i++) { 11832 int v4c, v6_64c, v6_128c; 11833 if (vh[i].init_done == 0 && i != MAX_VRF_ID) { 11834 continue; 11835 } 11836 if (vrf_id != -1 && vrf_id != i) { 11837 continue; 11838 } 11839 11840 found = 1; 11841 11842 switch (pct) { 11843 case SOC_ALPM_DEBUG_CNT_ADD: 11844 vc = &vh[i].add; 11845 break; 11846 case SOC_ALPM_DEBUG_CNT_DEL: 11847 vc = &vh[i].del; 11848 break; 11849 case SOC_ALPM_DEBUG_CNT_SPLIT: 11850 vc = &vh[i].bkt_split; 11851 break; 11852 case SOC_ALPM_DEBUG_CNT_LPM_SHIFT: 11853 vc = &vh[i].lpm_shift; 11854 break; 11855 case SOC_ALPM_DEBUG_CNT_LPM_FULL: 11856 vc = &vh[i].lpm_full; 11857 break; 11858 case SOC_ALPM_DEBUG_CNT_USED: 11859 vc = &vh[i].pivot_used; 11860 break; 11861 default: 11862 vc = &vh[i].pivot_used; 11863 break; 11864 } 11865 11866 v4c = vc->v4; 11867 v6_64c = vc->v6_64; 11868 v6_128c = vc->v6_128; 11869 11870 tv4c += v4c; 11871 tv6_64c += v6_64c; 11872 tv6_128c += v6_128c; 11873 11874 PRINT_VRF_ITEM(u, i, v4c, v6_64c, v6_128c, (v4c+v6_64c+v6_128c)); 11875 } 11876 if (found == 0) { 11877 PRINT_VRF_NOT_FOUND(u); 11878 } else { 11879 PRINT_SPLIT_LINE(u); 11880 PRINT_VRF_ITEM_TOT(u, tv4c, tv6_64c, tv6_128c, (tv4c+tv6_64c+tv6_128c)); 11881 } 11882 11883 return ; 11884 } 11885 11886 /* vrf_id -1 indicates all vrf */ 11887 int 11888 soc_th_alpm_debug_show(int u, int vrf_id, uint32 flags) 11889 { 11890 int i, alloc_sz, found = 0; 11891 _alpm_dbg_cnt_t *alpm_dc_arr; 11892 _alpm_dbg_cnt_t bkt_ent_max; 11893 _alpm_dbg_cnt_t all_dc; 11894 11895 if (vrf_id > (SOC_VRF_MAX(u) + 1)) { 11896 return SOC_E_PARAM; 11897 } 11898 11899 alloc_sz = MAX_VRF_ID * sizeof(_alpm_dbg_cnt_t); 11900 alpm_dc_arr = sal_alloc(alloc_sz, "_alpm_dbg_cnt"); 11901 if (alpm_dc_arr == NULL) { 11902 return SOC_E_MEMORY; 11903 } 11904 sal_memset(alpm_dc_arr, 0, alloc_sz); 11905 11906 /* Collect data */ 11907 bkt_ent_max.v4 = ALPM_IPV4_BKT_COUNT; 11908 bkt_ent_max.v6_64 = ALPM_IPV6_64_BKT_COUNT; 11909 bkt_ent_max.v6_128 = ALPM_IPV6_128_BKT_COUNT; 11910 11911 if (SOC_IS_TRIDENT3X(u)) { 11912 bkt_ent_max.v4 <<= 1; 11913 bkt_ent_max.v6_64 <<= 1; 11914 bkt_ent_max.v6_128 <<= 1; 11915 } 11916 11917 if (ALPM_CTRL(u).double_wide[L3_DEFIP_MODE_V4]) { 11918 bkt_ent_max.v4 <<= 1; 11919 } 11920 if (ALPM_CTRL(u).double_wide[L3_DEFIP_MODE_64]) { 11921 bkt_ent_max.v6_64 <<= 1; 11922 } 11923 if (ALPM_CTRL(u).double_wide[L3_DEFIP_MODE_128]) { 11924 bkt_ent_max.v6_128 <<= 1; 11925 } 11926 11927 /* 1. Bucket Occupancy */ 11928 if (flags & (SOC_ALPM_DEBUG_SHOW_FLAG_BKT)) { 11929 LOG_CLI((BSL_META_U(u, 11930 "\nBucket Occupancy:\n"))); 11931 PRINT_BUCKET_HEADER(u); 11932 PRINT_SPLIT_LINE(u); 11933 } 11934 for (i = 0; i < TH_MAX_PIVOT_COUNT(u); i++) { 11935 alpm_pivot_t *p = ALPM_TCAM_PIVOT(u, i); 11936 if (p != NULL) { 11937 _alpm_dbg_cnt_t *tmp_dc; 11938 int vrf = PIVOT_BUCKET_VRF(p); 11939 11940 if (vrf < 0 || vrf > (SOC_VRF_MAX(u) + 1)) { 11941 continue; 11942 } 11943 11944 if (vrf_id != -1 && vrf_id != vrf) { 11945 continue; 11946 } 11947 11948 if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_BKT) { 11949 found = 1; 11950 PRINT_BUCKET_ITEM(u, i, vrf, 11951 PIVOT_BUCKET_MIN(p), 11952 PIVOT_BUCKET_MAX(p), 11953 PIVOT_BUCKET_COUNT(p), 11954 PIVOT_BUCKET_DEF(p)); 11955 } 11956 11957 tmp_dc = &alpm_dc_arr[vrf]; 11958 if (PIVOT_BUCKET_IPV6(p) == L3_DEFIP_MODE_128) { 11959 tmp_dc->v6_128 += PIVOT_BUCKET_COUNT(p); 11960 tmp_dc->v6_128t += bkt_ent_max.v6_128; 11961 } else if (PIVOT_BUCKET_IPV6(p) == L3_DEFIP_MODE_64) { 11962 tmp_dc->v6_64 += PIVOT_BUCKET_COUNT(p); 11963 tmp_dc->v6_64t += bkt_ent_max.v6_64; 11964 } else { 11965 tmp_dc->v4 += PIVOT_BUCKET_COUNT(p); 11966 tmp_dc->v4t += bkt_ent_max.v4; 11967 } 11968 tmp_dc->used = TRUE; 11969 } 11970 } 11971 11972 if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_BKT) { 11973 if (found == 0) { 11974 PRINT_VRF_NOT_FOUND(u); 11975 } 11976 } 11977 11978 sal_memset(&all_dc, 0, sizeof(all_dc)); 11979 found = 0; 11980 11981 if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_BKTUSG) { 11982 LOG_CLI((BSL_META_U(u, 11983 "\nBucket Usage:\n"))); 11984 PRINT_VRF_HEADER(u); 11985 PRINT_SPLIT_LINE(u); 11986 for (i = 0; i < MAX_VRF_ID; i++) { 11987 _alpm_dbg_cnt_t *tmp_dc; 11988 if (alpm_dc_arr[i].used != TRUE) { 11989 continue; 11990 } 11991 if (vrf_id != -1 && vrf_id != i) { 11992 continue; 11993 } 11994 11995 found = 1; 11996 tmp_dc = &alpm_dc_arr[i]; 11997 _ALPM_DBG_CNT_ADD(&all_dc, tmp_dc); 11998 PRINT_BKT_OCCU_ITEM(u, i, tmp_dc); 11999 } 12000 if (found == 0) { 12001 PRINT_VRF_NOT_FOUND(u); 12002 } else { 12003 PRINT_SPLIT_LINE(u); 12004 PRINT_BKT_OCCU_ITEM_TOT(u, &all_dc); 12005 } 12006 } 12007 12008 /* 2. Pivot Occupancy */ 12009 if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_PVT) { 12010 _soc_th_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 12011 SOC_ALPM_DEBUG_CNT_USED); 12012 } 12013 12014 /* 3. Add/Delete counters per VRF/ip type */ 12015 if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_CNT) { 12016 _soc_th_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 12017 SOC_ALPM_DEBUG_CNT_ADD); 12018 12019 _soc_th_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 12020 SOC_ALPM_DEBUG_CNT_DEL); 12021 } 12022 12023 /* 4. Total No. of bucket splits per VRF/ip type */ 12024 if (flags & SOC_ALPM_DEBUG_SHOW_FLAG_INTDBG) { 12025 _soc_th_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 12026 SOC_ALPM_DEBUG_CNT_SPLIT); 12027 _soc_th_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 12028 SOC_ALPM_DEBUG_CNT_LPM_FULL); 12029 _soc_th_alpm_pivot_debug_dump(u, vrf_id, alpm_vrf_handle[u], 12030 SOC_ALPM_DEBUG_CNT_LPM_SHIFT); 12031 } 12032 12033 sal_free(alpm_dc_arr); 12034 12035 return SOC_E_NONE; 12036 } 12037 12038 void 12039 soc_th_alpm_debug_cntr_show(int u) 12040 { 12041 LOG_CLI(("====ALPM=Internal=Debug=Counter====\n")); 12042 LOG_CLI(("%-24s%d\n", "Bucket Split:", _alpm_dbg_cntr[u].bkt_split)); 12043 LOG_CLI(("%-24s%d\n", "Bucket Share:", _alpm_dbg_cntr[u].bkt_share)); 12044 LOG_CLI(("%-24s%d\n", "Bucket Merge:", _alpm_dbg_cntr[u].bkt_merge)); 12045 LOG_CLI(("%-24s%d\n", "Bucket MergeDuringRp:", _alpm_dbg_cntr[u].bkt_merge2)); 12046 LOG_CLI(("%-24s%d\n", "Bucket Repartition:", _alpm_dbg_cntr[u].bkt_repart)); 12047 LOG_CLI(("%-24s%d\n", "Propagation Insert CB:", 12048 _alpm_dbg_cntr[u].ppg_cb_insert)); 12049 LOG_CLI(("%-24s%d\n", "Propagation Delete CB:", 12050 _alpm_dbg_cntr[u].ppg_cb_delete)); 12051 LOG_CLI(("%-24s%d\n", "Propagation Hitbit CB:", 12052 _alpm_dbg_cntr[u].ppg_cb_hitbit)); 12053 } 12054 12055 int 12056 soc_th_alpm_debug_index_mapping(int u) 12057 { 12058 int idx, m, err = 0; 12059 int log_idx, phy_idx; 12060 soc_mem_t mem[2] = {L3_DEFIPm, L3_DEFIP_PAIR_128m}; 12061 int max_index = SOC_L3_DEFIP_TCAM_DEPTH_GET(u) * 12062 SOC_L3_DEFIP_MAX_TCAMS_GET(u); 12063 12064 for (m = 0; m < 2; m++) { 12065 for (idx = 0; idx < soc_mem_index_count(u, mem[m]); idx++) { 12066 phy_idx = soc_th_alpm_physical_idx(u, mem[m], idx, 1); 12067 log_idx = soc_th_alpm_logical_idx(u, mem[m], phy_idx, 1); 12068 if (phy_idx < 0 || phy_idx >= max_index || idx != log_idx) { 12069 LOG_CLI(("ALPM index mapping testing failed %17s " 12070 "loc(%d)->phy(%d)->loc(%d)\n", 12071 SOC_MEM_NAME(u, mem[m]), idx, phy_idx, log_idx)); 12072 err++; 12073 break; 12074 } 12075 } 12076 } 12077 12078 if (!err) { 12079 LOG_CLI(("ALPM index mapping testing passed\n")); 12080 } 12081 12082 if (err) { 12083 return SOC_E_FAIL; 12084 } else { 12085 return SOC_E_NONE; 12086 } 12087 } 12088 12089 int 12090 soc_th_alpm_debug_brief_show(int u, int phy_bkt, int index) 12091 { 12092 int i, j, rv = SOC_E_NONE; 12093 uint32 rval, alpm = 0, mode = 0, urpf, bit128, fv, bnkbits; 12094 int v4used = 0, v4max; 12095 int v6_64used = 0, v6_64max; 12096 int v6_128used = 0, v6_128max; 12097 int bucket_used = 0, bucket_max; 12098 char *lpm_tbl_ptr = NULL; 12099 defip_entry_t *lpm_entry; /* Hw entry buffer. */ 12100 defip_pair_128_entry_t *lpm_entry_p128; /* Hw entry buffer. */ 12101 int ipv6, bkt_ptr, gh, gr, use_alpm; 12102 int *bktref = NULL; 12103 int glb_hi_cnt = 0, glb_lo_cnt = 0; 12104 soc_mem_t lpm_mem; 12105 int bs11 = 0, bs21 = 0, bs31 = 0, bs41 = 0, alloc_size; 12106 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 12107 soc_field_t fldv, fldb, fldg, fldr; 12108 int alpm_bkt_bits = ALPM_CTRL(u).bkt_bits; 12109 12110 char *mode_str[] = { 12111 "LPM", 12112 "ALPM-Combined", 12113 "ALPM-Parallel", 12114 "ALPM-TCAM_ALPM", 12115 "ALPM-Invalid" 12116 }; 12117 char *ipver_str[] = { 12118 "IPv4", 12119 "IPv6-64", 12120 "IPv6-128" 12121 }; 12122 12123 char *rtype_str[] = { 12124 "Global", 12125 "Private" 12126 }; 12127 12128 char *dw_str = "Double Wide"; 12129 char *sw_str = "Single Wide"; 12130 12131 LOG_CLI(("\n")); 12132 LOG_CLI(("SW Status:\n")); 12133 LOG_CLI(("%-24s", "Mode:")); 12134 12135 if (ALPM_CTRL(u).ctrl_inited) { 12136 switch (ALPM_CTRL(u).alpm_mode) { 12137 case -1: 12138 LOG_CLI(("%s\n", mode_str[0])); 12139 break; 12140 case SOC_ALPM_MODE_COMBINED: 12141 LOG_CLI(("%s\n", mode_str[1])); 12142 break; 12143 case SOC_ALPM_MODE_PARALLEL: 12144 LOG_CLI(("%s\n", mode_str[2])); 12145 break; 12146 case SOC_ALPM_MODE_TCAM_ALPM: 12147 LOG_CLI(("%s\n", mode_str[3])); 12148 break; 12149 default: 12150 break; 12151 } 12152 } else { 12153 LOG_CLI(("%s\n", mode_str[0])); 12154 } 12155 urpf = SOC_URPF_STATUS_GET(u); 12156 LOG_CLI(("%-24s%s\n", "uRPF:", urpf ? "Enable" : "Disable")); 12157 bit128 = !!soc_mem_index_count(u, L3_DEFIP_PAIR_128m); 12158 LOG_CLI(("%-24s%d\n", "IPv6 Bits:", bit128 ? 128 : 64)); 12159 for (i = 0; i <= L3_DEFIP_MODE_128; i++) { 12160 LOG_CLI(("%-24s%s | %2d EPBkt | %2d EPBnk\n", 12161 ipver_str[i], 12162 ALPM_CTRL(u).double_wide[i] ? dw_str : sw_str, 12163 ALPM_CTRL(u).cnt_ent_per_bkt[i], 12164 ALPM_CTRL(u).ent_per_bank[i])); 12165 } 12166 LOG_CLI(("%-24s%d\n", "Num Banks:", ALPM_CTRL(u).num_banks)); 12167 LOG_CLI(("%-24s%d\n", "Bank bits:", ALPM_CTRL(u).bank_bits)); 12168 LOG_CLI(("%-24s%d\n", "Num Buckets:", ALPM_CTRL(u).num_bkts)); 12169 LOG_CLI(("%-24s%d\n", "Bucket bits:", ALPM_CTRL(u).bkt_bits)); 12170 LOG_CLI(("%-24s0x%x\n", "Bucket Mask:", ALPM_CTRL(u).bkt_mask)); 12171 LOG_CLI(("%-24s%s\n", "Bucket sharing:", 12172 ALPM_CTRL(u).bkt_sharing ? "Enable" : "Disable")); 12173 LOG_CLI(("Disabled bank bitmap:\n")); 12174 for (i = 0; i < 2; i++) { 12175 LOG_CLI(("\t%-16s0x%2x\n", rtype_str[i], 12176 ALPM_CTRL(u).bank_disable_bmp[i])); 12177 } 12178 LOG_CLI(("Disabled bank bitmap(8b):\n")); 12179 for (i = 0; i < 2; i++) { 12180 LOG_CLI(("\t%-16s0x%2x\n", rtype_str[i], 12181 ALPM_CTRL(u).bank_disable_bmp_8b[i])); 12182 } 12183 LOG_CLI(("%-24s%s\n", "Global/Private Zoned:", 12184 ALPM_CTRL(u).gp_zoned ? "Yes" : "No")); 12185 LOG_CLI(("%-24s%s\n", "SW Prefix Lookup:", 12186 ALPM_CTRL(u).sw_prefix_lkup ? "Yes" : "No")); 12187 12188 soc_th_alpm_debug_index_mapping(u); 12189 12190 LOG_CLI(("\n")); 12191 LOG_CLI(("HW Status:\n")); 12192 12193 SOC_IF_ERROR_RETURN(READ_L3_DEFIP_RPF_CONTROLr(u, &rval)); 12194 alpm = soc_reg_field_get(u, L3_DEFIP_RPF_CONTROLr, rval, LPM_MODEf); 12195 if (alpm != 0) { 12196 mode = soc_reg_field_get(u, L3_DEFIP_RPF_CONTROLr, rval, LOOKUP_MODEf); 12197 } 12198 urpf = soc_reg_field_get(u, L3_DEFIP_RPF_CONTROLr, rval, DEFIP_RPF_ENABLEf); 12199 12200 LOG_CLI(("\n")); 12201 LOG_CLI(("%-24s%s\n", "Mode:", mode_str[alpm + mode])); 12202 LOG_CLI(("%-24s%s\n", "uRPF:", urpf ? "Enable" : "Disable")); 12203 bit128 = !!soc_mem_index_count(u, L3_DEFIP_PAIR_128m); 12204 LOG_CLI(("%-24s%d\n", "IPv6 Bits:", bit128 ? 128 : 64)); 12205 if (alpm == 0) { 12206 return SOC_E_NONE; 12207 } 12208 12209 if (mode == 0 && !urpf) { /* Combined mode && uRPF */ 12210 if (SOC_IS_TRIDENT3X(u)) { 12211 fv = 1; 12212 } else { 12213 fv = soc_reg_field_get(u, L3_DEFIP_RPF_CONTROLr, rval, 12214 ENABLE_DOUBLE_WIDE_BUCKETS_FOR_IPV4f); 12215 } 12216 } else if (mode == 2) { /* TCAM/ALPM mode */ 12217 fv = 1; 12218 } else { /* Parallel mode */ 12219 fv = 0; 12220 } 12221 LOG_CLI(("%-24s%s\n", "IPv4:", fv ? dw_str : sw_str)); 12222 12223 if (mode == 0 && !urpf) { /* Combined mode && uRPF */ 12224 fv = 1; 12225 } else if (mode == 2) { /* TCAM/ALPM mode */ 12226 fv = 1; 12227 } else { /* Parallel mode */ 12228 fv = 0; 12229 } 12230 LOG_CLI(("%-24s%s\n", "IPv6-64:", fv ? dw_str : sw_str)); 12231 LOG_CLI(("%-24s%s\n", "IPv6-128:", fv ? dw_str : sw_str)); 12232 12233 if (SOC_REG_IS_VALID(u, ISS_LOG_TO_PHY_BANK_MAP_2r)) { 12234 SOC_IF_ERROR_RETURN(READ_ISS_LOG_TO_PHY_BANK_MAP_2r(u, &rval)); 12235 bnkbits = soc_reg_field_get(u, ISS_LOG_TO_PHY_BANK_MAP_2r, rval, 12236 ALPM_BANK_MODEf); 12237 } else { 12238 SOC_IF_ERROR_RETURN(READ_ISS_LOG_TO_PHY_BANK_MAPr(u, &rval)); 12239 bnkbits = soc_reg_field_get(u, ISS_LOG_TO_PHY_BANK_MAPr, rval, 12240 ALPM_BANK_MODEf); 12241 } 12242 if (SOC_IS_TRIDENT3X(u)) { 12243 LOG_CLI(("%-24s%d\n", "Num Banks:", bnkbits == 0 ? 8 : 4)); 12244 } else { 12245 LOG_CLI(("%-24s%d\n", "Num Banks:", bnkbits == 0 ? 4 : 2)); 12246 } 12247 if (bnkbits == 0) { 12248 bnkbits = SOC_IS_TRIDENT3X(u) ? 0xff : 0xf; 12249 } else { 12250 bnkbits = SOC_IS_TRIDENT3X(u) ? 0xf : 0x3; 12251 } 12252 LOG_CLI(("---------------------------------------\n")); 12253 /* Calculate utilization */ 12254 v4max = 2 * soc_mem_index_count(u, L3_DEFIPm); 12255 v6_64max = bit128 ? soc_mem_index_count(u, L3_DEFIP_PAIR_128m) : 12256 soc_mem_index_count(u, L3_DEFIPm); 12257 v6_128max = soc_mem_index_count(u, L3_DEFIP_PAIR_128m); 12258 bucket_max = ALPM_CTRL(u).num_bkts; 12259 if (urpf) { 12260 v4max >>= 1; 12261 v6_64max >>= 1; 12262 v6_128max >>= 1; 12263 bucket_max >>= 1; 12264 } 12265 12266 bktref = sal_alloc(bucket_max * sizeof(int), "bktref"); 12267 if (bktref == NULL) { 12268 return SOC_E_MEMORY; 12269 } 12270 sal_memset(bktref, 0, bucket_max * sizeof(int)); 12271 12272 /* DMA LPM table to software copy */ 12273 lpm_mem = L3_DEFIPm; 12274 alloc_size = WORDS2BYTES(soc_mem_entry_words(u, lpm_mem)) * 12275 soc_mem_index_count(u, lpm_mem); 12276 lpm_tbl_ptr = soc_cm_salloc(u, alloc_size, "lpm_tbl"); 12277 if (lpm_tbl_ptr == NULL) { 12278 rv = SOC_E_MEMORY; 12279 goto _free_mem; 12280 } 12281 /* Reset allocated buffer. */ 12282 sal_memset(lpm_tbl_ptr, 0, alloc_size); 12283 12284 /* Read table to the buffer. */ 12285 if (v4max && soc_mem_read_range(u, lpm_mem, MEM_BLOCK_ANY, 12286 soc_mem_index_min(u, lpm_mem), 12287 soc_mem_index_max(u, lpm_mem), lpm_tbl_ptr) < 0) { 12288 rv = (SOC_E_INTERNAL); 12289 goto _free_mem; 12290 } 12291 12292 for (i = 0; i < (v4max / 2); i++) { 12293 /* Calculate entry offset */ 12294 lpm_entry = 12295 soc_mem_table_idx_to_pointer(u, lpm_mem, 12296 defip_entry_t *, lpm_tbl_ptr, i); 12297 ipv6 = soc_mem_field32_get(u, lpm_mem, lpm_entry, MODE0_f(u)); 12298 12299 for (j = 0; j < (ipv6 ? 1 : 2); j++) { 12300 if (j == 1) { 12301 fldv = VALID1f; 12302 } else { 12303 fldv = VALID0f; 12304 } 12305 /* Make sure entry is valid. */ 12306 if (!soc_mem_field32_get(u, lpm_mem, lpm_entry, fldv)) { 12307 continue; 12308 } 12309 12310 if (ipv6) { 12311 v6_64used ++; 12312 } else { 12313 v4used ++; 12314 } 12315 12316 if (j == 0) { 12317 fldg = GLOBAL_HIGH0f; 12318 fldb = ALG_BKT_PTR0f; 12319 fldr = GLOBAL_ROUTE0f; 12320 } else { 12321 fldg = GLOBAL_HIGH1f; 12322 fldb = ALG_BKT_PTR1f; 12323 fldr = GLOBAL_ROUTE1f; 12324 } 12325 12326 gh = soc_mem_field32_get(u, lpm_mem, lpm_entry, fldg); 12327 gr = soc_mem_field32_get(u, lpm_mem, lpm_entry, fldr); 12328 if (gr) { 12329 if (gh) { 12330 glb_hi_cnt ++; 12331 use_alpm = 0; 12332 } else { 12333 glb_lo_cnt ++; 12334 use_alpm = (mode == 2) ? 0 : 1; 12335 } 12336 } else { 12337 use_alpm = 1; 12338 } 12339 12340 if (use_alpm) { 12341 bkt_ptr = soc_mem_field32_get(u, lpm_mem, lpm_entry, fldb); 12342 if (bkt_ptr > bucket_max) { 12343 LOG_CLI(("Invalid phy_bkt pointer in %s index %d\n", 12344 SOC_MEM_NAME(u, lpm_mem), i)); 12345 } else { 12346 bktref[bkt_ptr] ++; 12347 } 12348 } 12349 } 12350 } 12351 12352 soc_cm_sfree(u, lpm_tbl_ptr); 12353 12354 /* l3_defip_pair_128 */ 12355 lpm_tbl_ptr = NULL; 12356 lpm_mem = L3_DEFIP_PAIR_128m; 12357 alloc_size = WORDS2BYTES(soc_mem_entry_words(u, lpm_mem)) * 12358 soc_mem_index_count(u, lpm_mem); 12359 lpm_tbl_ptr = soc_cm_salloc(u, alloc_size, "lpm_tbl_p128"); 12360 if (lpm_tbl_ptr == NULL) { 12361 rv = SOC_E_MEMORY; 12362 goto _free_mem; 12363 } 12364 /* Reset allocated buffer. */ 12365 sal_memset(lpm_tbl_ptr, 0, alloc_size); 12366 12367 /* Read table to the buffer. */ 12368 if (v6_128max && soc_mem_read_range(u, lpm_mem, MEM_BLOCK_ANY, 12369 soc_mem_index_min(u, lpm_mem), 12370 soc_mem_index_max(u, lpm_mem), lpm_tbl_ptr) < 0) { 12371 rv = (SOC_E_INTERNAL); 12372 goto _free_mem; 12373 } 12374 12375 for (i = 0; i < v6_128max; i++) { 12376 /* Calculate entry offset */ 12377 lpm_entry_p128 = 12378 soc_mem_table_idx_to_pointer(u, lpm_mem, 12379 defip_pair_128_entry_t *, lpm_tbl_ptr, i); 12380 /* Verify if read LPM entry is IPv6-128 entry */ 12381 if (0x03 != soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, MODE1_UPR_f(u))) { 12382 continue; 12383 }; 12384 12385 /* Verify if LPM entry is valid */ 12386 if (!soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, 12387 VALID1_LWRf) || 12388 !soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, 12389 VALID0_LWRf) || 12390 !soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, 12391 VALID1_UPRf) || 12392 !soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, 12393 VALID0_UPRf)) { 12394 continue; 12395 }; 12396 12397 v6_128used ++; 12398 12399 gh = soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, GLOBAL_HIGHf); 12400 gr = soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, GLOBAL_ROUTEf); 12401 if (gr) { 12402 if (gh) { 12403 glb_hi_cnt ++; 12404 use_alpm = 0; 12405 } else { 12406 glb_lo_cnt ++; 12407 use_alpm = (mode == 2) ? 0 : 1; 12408 } 12409 } else { 12410 use_alpm = 1; 12411 } 12412 12413 if (use_alpm) { 12414 bkt_ptr = soc_mem_field32_get(u, lpm_mem, lpm_entry_p128, ALG_BKT_PTRf); 12415 if (bkt_ptr > bucket_max) { 12416 LOG_CLI(("Invalid phy_bkt pointer in %s index %d\n", 12417 SOC_MEM_NAME(u, lpm_mem), i)); 12418 } else { 12419 bktref[bkt_ptr] ++; 12420 } 12421 } 12422 } 12423 12424 for (i = 0; i < bucket_max; i++) { 12425 if (bktref[i] != 0) { 12426 bucket_used ++; 12427 } 12428 if (bktref[i] == 4) { 12429 bs41 ++; 12430 } 12431 if (bktref[i] == 3) { 12432 bs31 ++; 12433 } 12434 if (bktref[i] == 2) { 12435 bs21 ++; 12436 } 12437 if (bktref[i] == 1) { 12438 bs11 ++; 12439 } 12440 } 12441 12442 if (ALPM_CTRL(u).double_wide[0]) { 12443 bucket_max >>= 1; 12444 } 12445 12446 LOG_CLI(("\n")); 12447 LOG_CLI(("%-24s%d/%-4d\n", "IPv4 Pivots:", v4used, v4max)); 12448 LOG_CLI(("%-24s%d/%-4d\n", "IPv6-64 Pivots:", v6_64used, v6_64max)); 12449 LOG_CLI(("%-24s%d/%-4d\n", "IPv6-128 Pivots:", v6_128used, v6_128max)); 12450 LOG_CLI(("%-24s%d/%-4d\n", "Buckets:", bucket_used, bucket_max)); 12451 LOG_CLI(("%-24s%d\n", "Global High:", glb_hi_cnt)); 12452 LOG_CLI(("%-24s%d\n", "Global Low:", glb_lo_cnt)); 12453 LOG_CLI(("\n")); 12454 LOG_CLI(("%s\n", "Bucket Sharing:")); 12455 LOG_CLI(("%-24s%d\n", "1->1:", bs11)); 12456 LOG_CLI(("%-24s%d\n", "2->1:", bs21)); 12457 LOG_CLI(("%-24s%d\n", "3->1:", bs31)); 12458 LOG_CLI(("%-24s%d\n", "4->1:", bs41)); 12459 LOG_CLI(("\n")); 12460 soc_th_alpm_debug_cntr_show(u); 12461 LOG_CLI(("\n\n")); 12462 12463 _free_mem: 12464 if (bktref) { 12465 sal_free(bktref); 12466 bktref = NULL; 12467 } 12468 12469 if (lpm_tbl_ptr) { 12470 soc_cm_sfree(u, lpm_tbl_ptr); 12471 lpm_tbl_ptr = NULL; 12472 } 12473 12474 if (phy_bkt != -1) { 12475 int bank, entmax, tmp; 12476 12477 lpm_mem = soc_alpm_cmn_bkt_view_get(u, 12478 SOC_TH_ALPM_AIDX(u, phy_bkt, 0, 0, 0)); 12479 LOG_CLI(("Bucket = %4d (View %s)\n", phy_bkt, lpm_mem == -1 ? "INVALID" : 12480 SOC_MEM_NAME(u, lpm_mem))); 12481 LOG_CLI(("------------------------------------------------------------\n")); 12482 LOG_CLI(("Index distribution (* indicates occupied)\n")); 12483 12484 switch (lpm_mem) { 12485 case L3_DEFIP_ALPM_IPV4m: 12486 entmax = 6; 12487 break; 12488 case L3_DEFIP_ALPM_IPV4_1m: 12489 entmax = 4; 12490 break; 12491 case L3_DEFIP_ALPM_IPV6_64m: 12492 entmax = 4; 12493 break; 12494 case L3_DEFIP_ALPM_IPV6_64_1m: 12495 entmax = 3; 12496 break; 12497 case L3_DEFIP_ALPM_IPV6_128m: 12498 entmax = 2; 12499 break; 12500 default: 12501 lpm_mem = L3_DEFIP_ALPM_IPV4m; 12502 entmax = 6; 12503 break; 12504 } 12505 12506 for (bank = 0; bank < MAX_BANK_COUNT(u); bank++) { 12507 if (!(bnkbits & (1 << bank))) { 12508 continue; 12509 } 12510 12511 LOG_CLI(("Bank%d: ", bank)); 12512 for (i = 0; i < entmax; i++) { 12513 int rv1; 12514 j = SOC_TH_ALPM_AIDX(u, phy_bkt, 0, bank, i); 12515 rv1 = _soc_mem_alpm_read(u, lpm_mem, MEM_BLOCK_ANY, j, e); 12516 if (rv1 == 0 && 12517 soc_mem_field32_get(u, lpm_mem, e, VALIDf)) { 12518 tmp = 1; 12519 } else { 12520 tmp = 0; 12521 } 12522 if (tmp) { 12523 LOG_CLI(("%d(*) ", j)); 12524 } else { 12525 LOG_CLI(("%d( ) ", j)); 12526 } 12527 } 12528 LOG_CLI(("\n")); 12529 } 12530 } 12531 12532 LOG_CLI(("\n")); 12533 if (index != -1) { 12534 int log_bkt; 12535 LOG_CLI(("Index = %8d\n", index)); 12536 LOG_CLI(("------------------------------------------------------------\n")); 12537 lpm_mem = soc_alpm_cmn_bkt_view_get(u, index); 12538 LOG_CLI(("%-24s%s\n", "Type", lpm_mem == -1 ? "INVALID" : 12539 SOC_MEM_NAME(u, lpm_mem))); 12540 LOG_CLI(("%-24s%d\n", "Bucket:", SOC_TH_ALPM_AIDX_TO_PHY_BKT(u, index))); 12541 LOG_CLI(("%-24s%d\n", "Sub-Bucket:", SOC_TH_ALPM_AIDX_TO_SUB_BKT(u, index))); 12542 LOG_CLI(("%-24s%d\n", "Bank:", index & ALPM_CTRL(u).bank_bits)); 12543 log_bkt = (_shr_popcount(bnkbits) + 1) / 2 + alpm_bkt_bits; 12544 LOG_CLI(("%-24s%d\n", "Entry:", index >> log_bkt)); 12545 LOG_CLI(("\n")); 12546 } 12547 12548 return rv; 12549 } 12550 12551 /* 12552 * Function: 12553 * soc_th_alpm_lpm_sw_dump 12554 * Purpose: 12555 * Displays FB LPM information maintained by software. 12556 * Parameters: 12557 * unit - Device unit number 12558 * Returns: 12559 * None 12560 */ 12561 void 12562 soc_th_alpm_lpm_sw_dump(int unit) 12563 { 12564 soc_th_alpm_lpm_state_p lpm_state; 12565 int i, j; 12566 alpm_pivot_t *pivot_pyld = NULL; 12567 _soc_th_alpm_lpm_hash_t *hash; 12568 int idx; 12569 12570 /* Dump v4/v6 lpm state */ 12571 LOG_CLI((BSL_META_U(unit, "V4 LPM STATE DUMP.\n"))); 12572 lpm_state = soc_th_alpm_lpm_state[unit]; 12573 12574 if (lpm_state != NULL) { 12575 for (i = 0; i < ALPM_MAX_PFX_ENTRIES; i++) { 12576 if (lpm_state[i].vent != 0) { 12577 LOG_CLI((BSL_META_U(unit, "Prefix %d\n"), i)); 12578 LOG_CLI((BSL_META_U(unit, " Start : %d\n"), lpm_state[i].start)); 12579 LOG_CLI((BSL_META_U(unit, " End : %d\n"), lpm_state[i].end)); 12580 LOG_CLI((BSL_META_U(unit, " Prev : %d\n"), lpm_state[i].prev)); 12581 LOG_CLI((BSL_META_U(unit, " Next : %d\n"), lpm_state[i].next)); 12582 LOG_CLI((BSL_META_U(unit, " Valid : %d\n"), lpm_state[i].vent)); 12583 LOG_CLI((BSL_META_U(unit, " Free : %d\n"), lpm_state[i].fent)); 12584 } 12585 } 12586 } 12587 LOG_CLI((BSL_META_U(unit, "V4 LPM STATE DUMP DONE.\n\n"))); 12588 12589 /* Dump LPM HASH table */ 12590 LOG_CLI((BSL_META_U(unit, "LPM HASH TABLE DUMP.\n"))); 12591 hash = SOC_ALPM_LPM_STATE_HASH(unit); 12592 for(idx = 0; idx < hash->index_count; idx++) { 12593 j = 0; 12594 if (hash->table[idx] != TD2_ALPM_HASH_INDEX_NULL) { 12595 LOG_CLI(( 12596 BSL_META_U(unit, "\nhash_idx = 0x%04x Data = 0x%04x"), 12597 idx, hash->table[idx])); 12598 } 12599 i = hash->table[idx]; 12600 while ((i != TD2_ALPM_HASH_INDEX_NULL) && (j++ < hash->entry_count)) { 12601 if ((j - 1) % 8 == 0) { 12602 LOG_CLI((BSL_META_U(unit, "\nlink_idx ="))); 12603 } 12604 LOG_CLI((BSL_META_U(unit, " 0x%04x"), i)); 12605 i = hash->link_table[i & TD2_ALPM_HASH_INDEX_MASK]; 12606 } 12607 } 12608 LOG_CLI((BSL_META_U(unit, "\nLPM HASH TABLE DUMP DONE.\n\n"))); 12609 12610 /* Dump TCAM pivot table */ 12611 LOG_CLI((BSL_META_U(unit, "TCAM PIVOT DUMP.\n"))); 12612 for(idx = 0; idx < TH_MAX_PIVOT_COUNT(unit); idx++) { 12613 /* Get TCAM pivot */ 12614 pivot_pyld = ALPM_TCAM_PIVOT(unit, idx); 12615 if (NULL == pivot_pyld) { 12616 continue; 12617 } 12618 if (PIVOT_BUCKET_HANDLE(pivot_pyld) == NULL) { 12619 continue; 12620 } 12621 12622 /* Get bucket trie from pivot */ 12623 LOG_CLI(( 12624 BSL_META_U(unit, "tcam_idex = 0x%04x\n"), pivot_pyld->tcam_index)); 12625 LOG_CLI((BSL_META_U(unit, " len = 0x%02x\t"), pivot_pyld->len)); 12626 LOG_CLI((BSL_META_U(unit, "bpm_len = 0x%02x\t"), pivot_pyld->bpm_len)); 12627 LOG_CLI(( 12628 BSL_META_U(unit, "bkt_idx = 0x%04x\n"), 12629 PIVOT_BUCKET_INDEX(pivot_pyld))); 12630 LOG_CLI(( 12631 BSL_META_U(unit, " vrf = 0x%04x\t"), PIVOT_BUCKET_VRF(pivot_pyld))); 12632 LOG_CLI(( 12633 BSL_META_U(unit, "v6 = 0x%0x\t"), PIVOT_BUCKET_IPV6(pivot_pyld))); 12634 LOG_CLI((BSL_META_U(unit, "Key : {"))); 12635 if (pivot_pyld->len < 32) { 12636 LOG_CLI(( 12637 BSL_META_U(unit, "0x%x/%d"), 12638 pivot_pyld->key[0], pivot_pyld->len)); 12639 } else { 12640 for (i=0; i < (((pivot_pyld->len)/32) + 1); i++) 12641 LOG_CLI((BSL_META_U(unit, " 0x%x"), pivot_pyld->key[i])); 12642 LOG_CLI((BSL_META_U(unit, "/%d"), pivot_pyld->len)); 12643 } 12644 LOG_CLI((BSL_META_U(unit, "}\n"))); 12645 } 12646 LOG_CLI((BSL_META_U(unit, "TCAM PIVOT DUMP DONE.\n\n"))); 12647 12648 /* Print VRF count/default route infomation */ 12649 LOG_CLI((BSL_META_U(unit, "VRF ROUTE DUMP.\n"))); 12650 for (idx = 0; idx < (SOC_VRF_MAX(unit) + 2); idx++) { 12651 if (alpm_vrf_handle[unit][idx].count_v4 != 0) { 12652 LOG_CLI(( 12653 BSL_META_U(unit, "V4-32 VRF = %d, Routes = %d Default Route:\n"), 12654 idx, alpm_vrf_handle[unit][idx].count_v4)); 12655 if (VRF_TRIE_DEFAULT_ROUTE_IPV4(unit, idx)) { 12656 soc_mem_entry_dump(unit, L3_DEFIPm, 12657 VRF_TRIE_DEFAULT_ROUTE_IPV4(unit, idx), 12658 BSL_LSS_CLI); 12659 } 12660 } 12661 12662 if (alpm_vrf_handle[unit][idx].count_v6_64 !=0) { 12663 LOG_CLI(( 12664 BSL_META_U(unit, "V6-64 VRF = %d, Routes = %d Default Route:\n"), 12665 idx, alpm_vrf_handle[unit][idx].count_v6_64)); 12666 if (VRF_TRIE_DEFAULT_ROUTE_IPV6(unit, idx)) { 12667 soc_mem_entry_dump(unit, L3_DEFIPm, 12668 VRF_TRIE_DEFAULT_ROUTE_IPV6(unit, idx), 12669 BSL_LSS_CLI); 12670 } 12671 } 12672 12673 if (alpm_vrf_handle[unit][idx].count_v6_128 != 0) { 12674 LOG_CLI(( 12675 BSL_META_U(unit, "V6-128 VRF = %d, Routes = %d Default Route:\n"), 12676 idx, alpm_vrf_handle[unit][idx].count_v6_128)); 12677 if (VRF_TRIE_DEFAULT_ROUTE_IPV6_128(unit, idx)) { 12678 soc_mem_entry_dump(unit, L3_DEFIP_PAIR_128m, 12679 VRF_TRIE_DEFAULT_ROUTE_IPV6_128(unit, idx), 12680 BSL_LSS_CLI); 12681 } 12682 } 12683 } 12684 LOG_CLI((BSL_META_U(unit, "VRF ROUTE DUMP DONE.\n"))); 12685 12686 return; 12687 } 12688 12689 #ifndef BCM_SW_STATE_DUMP_DISABLE 12690 /* 12691 * Function: 12692 * soc_th_alpm_sw_dump 12693 * Purpose: 12694 * Displays ALPM state maintained by software. 12695 * Parameters: 12696 * unit - Device unit number 12697 * Returns: 12698 * None 12699 */ 12700 void 12701 soc_th_alpm_sw_dump(int unit) 12702 { 12703 LOG_CLI((BSL_META_U(unit, "\n ALPM Info -\n"))); 12704 12705 soc_th_alpm_lpm_sw_dump(unit); 12706 12707 soc_th_alpm_bucket_sw_dump(unit); 12708 12709 return; 12710 } 12711 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 12712 12713 /* 12714 * Function: 12715 * _soc_th_alpm_sanity_check 12716 * Purpose: 12717 * Sanity check for ALPM with L3_DEFIP 12718 * Parameters: 12719 * u - Device unit 12720 * min - Min index of L3_DEFIP 12721 * max - Max index of L3_DEFIP 12722 * check_sw - Check software 12723 * bkt_ptr_arr - bucket ptr array 12724 * Returns: 12725 * SOC_E_XXX defined in error.h 12726 */ 12727 STATIC int 12728 _soc_th_alpm_sanity_check(int u, int min, int max, int check_sw, 12729 int *bkt_ptr_arr, alpm_bkt_usg_t *bkt_usg) 12730 { 12731 int rv = SOC_E_NONE; 12732 int lpm_idx, lpm_idx2, fd_lpm_idx2, alpm_idx, prev_idx = 0; 12733 int i, j, ipv6, prev_v6 = 0, prev_i = 0; 12734 int vrf_id, vrf; 12735 int fd_lpm_idx, fd_bkt_ptr, fd_alpm_idx; 12736 int ent, ent_num, bkt_ptr, sub_bkt_ptr; 12737 int error1 = 0, error2 = 0, error = 0, success = 0; 12738 int used; 12739 int bpm_len, ip_len; 12740 int trie_bpm_len, default_route; 12741 int alloc_size; 12742 uint32 bank_disable = 0; 12743 uint32 *e = NULL; 12744 uint32 *shadow = NULL; 12745 uint32 prefix[5], length; 12746 trie_t *pfx_trie = NULL; 12747 trie_node_t *lpmp = NULL; 12748 payload_t *tmp_pyld = NULL; 12749 uint32 data0[10] = {0}; 12750 uint32 data1[10] = {0}; 12751 char *buffer = NULL; 12752 defip_entry_t *lpm_entry, lpm_entry2, lpm_bmp; 12753 soc_mem_t bkt_mem_type; 12754 soc_mem_t alpm_mem; 12755 int flex; 12756 int bpm_check = 0; 12757 int flex_v6_64; 12758 int ipmc_route = 0; 12759 12760 e = sal_alloc(sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS, "buf_tmp"); 12761 if (e == NULL) { 12762 return (SOC_E_MEMORY); 12763 } 12764 12765 shadow = sal_alloc(sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS, "shadow_buf_tmp"); 12766 if (shadow == NULL) { 12767 sal_free(e); 12768 return (SOC_E_MEMORY); 12769 } 12770 /* Calculate table size. */ 12771 alloc_size = sizeof(defip_entry_t) * (max - min + 1); 12772 12773 /* Allocate memory buffer. */ 12774 buffer = soc_cm_salloc(u, alloc_size, "lpm_tbl"); 12775 if (buffer == NULL) { 12776 sal_free(e); 12777 sal_free(shadow); 12778 return (SOC_E_MEMORY); 12779 } 12780 12781 /* Reset allocated buffer. */ 12782 sal_memset(buffer, 0, alloc_size); 12783 12784 SOC_ALPM_LPM_LOCK(u); 12785 12786 /* Read table to the buffer. */ 12787 if (soc_mem_read_range(u, L3_DEFIPm, MEM_BLOCK_ANY, 12788 min, max, buffer) < 0) { 12789 sal_free(e); 12790 sal_free(shadow); 12791 soc_cm_sfree(u, buffer); 12792 SOC_ALPM_LPM_UNLOCK(u); 12793 return (SOC_E_INTERNAL); 12794 } 12795 12796 for (lpm_idx = min; lpm_idx <= max; lpm_idx++) { 12797 lpm_entry = soc_mem_table_idx_to_pointer(u, L3_DEFIPm, 12798 defip_entry_t *, buffer, 12799 lpm_idx - min); 12800 12801 ipv6 = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, MODE0_f(u)); 12802 12803 12804 for (i = 0; i <= (ipv6 ? 0 : 1); i++) { 12805 if (error1) { 12806 LOG_ERROR(BSL_LS_SOC_ALPM, 12807 (BSL_META_U(u, 12808 "\tL3_DEFIP index:[%d,%d] check failed. ipv6 %d error count %d\n"), 12809 prev_idx, prev_i, prev_v6, error1)); 12810 error = 1; 12811 } else if (success) { 12812 LOG_INFO(BSL_LS_SOC_ALPM,(BSL_META_U(u, 12813 "\tL3_DEFIP index:[%d,%d] check passed. ipv6 %d success count %d\n"), 12814 prev_idx, prev_i, prev_v6, success)); 12815 } 12816 error1 = error2 = success = 0; 12817 prev_v6 = ipv6; 12818 prev_idx = lpm_idx; 12819 prev_i = i; 12820 12821 /* cache coherency check */ 12822 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, VALID0f) || 12823 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, VALID1f)) { 12824 defip_entry_t hw_ent, sw_ent; 12825 soc_mem_t cmem = L3_DEFIPm; 12826 sal_memset(&hw_ent, 0, sizeof(hw_ent)); 12827 sal_memset(&sw_ent, 0, sizeof(sw_ent)); 12828 rv = _soc_mem_alpm_read_cache(u, cmem, SOC_BLOCK_ANY, 12829 lpm_idx, &sw_ent); 12830 if (SOC_SUCCESS(rv)) { 12831 rv = soc_mem_read_no_cache(u, 0, cmem, 0, SOC_BLOCK_ANY, 12832 lpm_idx, &hw_ent); 12833 if (SOC_SUCCESS(rv)) { 12834 soc_mem_parity_field_clear( 12835 u, cmem, (void *)&hw_ent, (void *)&sw_ent); 12836 if (sal_memcmp(&sw_ent, &hw_ent, 12837 soc_mem_entry_bytes(u, cmem)) != 0) { 12838 LOG_ERROR(BSL_LS_SOC_ALPM, 12839 (BSL_META_U(u, "\t%s index:[%d], ipv6(%d)" 12840 " cache mismatch\n"), SOC_MEM_NAME(u, cmem), 12841 lpm_idx, ipv6)); 12842 error1 ++; 12843 } 12844 } 12845 } 12846 12847 /* We can just use defip_entry_t because it's always longer 12848 * than aux_entry_t */ 12849 cmem = L3_DEFIP_AUX_TABLEm; 12850 sal_memset(&hw_ent, 0, sizeof(hw_ent)); 12851 sal_memset(&sw_ent, 0, sizeof(sw_ent)); 12852 lpm_idx2 = soc_th_alpm_physical_idx(u, L3_DEFIPm, lpm_idx, 1); 12853 rv = _soc_mem_alpm_read_cache(u, cmem, SOC_BLOCK_ANY, 12854 lpm_idx2, &sw_ent); 12855 if (SOC_SUCCESS(rv)) { 12856 rv = soc_mem_read_no_cache(u, 0, cmem, 0, SOC_BLOCK_ANY, 12857 lpm_idx2, &hw_ent); 12858 if (SOC_SUCCESS(rv)) { 12859 soc_mem_parity_field_clear( 12860 u, cmem, (void *)&hw_ent, (void *)&sw_ent); 12861 if (sal_memcmp(&sw_ent, &hw_ent, 12862 soc_mem_entry_bytes(u, cmem)) != 0) { 12863 LOG_ERROR(BSL_LS_SOC_ALPM, 12864 (BSL_META_U(u, "\t%s index:[%d], ipv6(%d)" 12865 " cache mismatch\n"), SOC_MEM_NAME(u, cmem), 12866 lpm_idx2, ipv6)); 12867 error1 ++; 12868 } 12869 } 12870 } 12871 } 12872 12873 if (i == 1) { 12874 soc_th_alpm_lpm_ip4entry1_to_0(u, lpm_entry, lpm_entry, PRESERVE_HIT); 12875 } 12876 bkt_ptr = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ALG_BKT_PTR0f); 12877 if (!SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, VALID0f)) { 12878 continue; 12879 } 12880 12881 flex = _soc_th_alpm_lpm_flex_get(u, ipv6, 12882 soc_mem_field32_get(u, L3_DEFIPm, 12883 lpm_entry, ENTRY_VIEW0f)); 12884 flex_v6_64 = 0; 12885 if (soc_feature(u, soc_feature_alpm_flex_stat_v6_64) && ipv6 && flex) { 12886 if (soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK0f) == 0xFFFFFFFF && 12887 soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, IP_ADDR_MASK1f) == 0xFFFFFFFF) { 12888 flex_v6_64 = 1; 12889 } 12890 } 12891 12892 if (soc_feature(u, soc_feature_ipmc_defip)) { 12893 ipmc_route = 0; 12894 if (soc_mem_field_valid(u, L3_DEFIPm, MULTICAST_ROUTE0f)) { 12895 ipmc_route = soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, MULTICAST_ROUTE0f); 12896 } else if (soc_mem_field_valid(u, L3_DEFIPm, DATA_TYPE0f)) { 12897 if (soc_mem_field32_get(u, L3_DEFIPm, lpm_entry, DATA_TYPE0f) == 2) { 12898 ipmc_route = 1; 12899 } else { 12900 ipmc_route = 0; 12901 } 12902 } 12903 } 12904 12905 if (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, GLOBAL_HIGH0f) || 12906 ipmc_route || 12907 (SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, GLOBAL_ROUTE0f) && 12908 ALPM_CTRL(u).alpm_mode == SOC_ALPM_MODE_TCAM_ALPM) || 12909 flex_v6_64) { 12910 if (bkt_ptr != 0) { 12911 LOG_ERROR(BSL_LS_SOC_ALPM, 12912 (BSL_META_U(u, "\tWrong bkt_ptr %d\n"), 12913 bkt_ptr)); 12914 error1 ++; 12915 } 12916 continue; 12917 } 12918 if (bkt_ptr == 0) { 12919 LOG_ERROR(BSL_LS_SOC_ALPM, 12920 (BSL_META_U(u, "\tWrong bkt_ptr2 %d\n"), 12921 bkt_ptr)); 12922 error1 ++; 12923 } 12924 12925 j = 0; 12926 if (soc_feature(u, soc_feature_generic_dest)) { 12927 uint32 val, dest_type = SOC_MEM_FIF_DEST_NEXTHOP; 12928 val = soc_mem_field32_dest_get(u, L3_DEFIPm, lpm_entry, 12929 DESTINATION0f, &dest_type); 12930 if (dest_type == SOC_MEM_FIF_DEST_ECMP) { 12931 data0[j++] = 1; 12932 } else { 12933 data0[j++] = 0; 12934 } 12935 data0[j++] = val; 12936 data0[j++] = val; 12937 } else { 12938 data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ECMP0f); 12939 data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ECMP_PTR0f); 12940 data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, NEXT_HOP_INDEX0f); 12941 } 12942 data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, PRI0f); 12943 data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, RPE0f); 12944 data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, DST_DISCARD0f); 12945 data0[j++] = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, CLASS_ID0f); 12946 12947 /* Check if bucket pointer duplicated */ 12948 if (ALPM_CTRL(u).bkt_sharing) { 12949 sub_bkt_ptr = SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, ALG_SUB_BKT_PTR0f); 12950 } else { 12951 sub_bkt_ptr = 0; 12952 } 12953 if (bkt_ptr_arr) { 12954 if (bkt_ptr_arr[bkt_ptr * SOC_TH_MAX_SUB_BUCKETS + sub_bkt_ptr] == -1) { 12955 bkt_ptr_arr[bkt_ptr * SOC_TH_MAX_SUB_BUCKETS + sub_bkt_ptr] = lpm_idx; 12956 if (ALPM_CTRL(u).double_wide[ipv6]) { 12957 bkt_ptr_arr[(bkt_ptr + 1) * SOC_TH_MAX_SUB_BUCKETS + sub_bkt_ptr] = lpm_idx; 12958 } 12959 success ++; 12960 } else { 12961 LOG_ERROR(BSL_LS_SOC_ALPM, 12962 (BSL_META_U(u, "\tConflict bucket pointer [%d,%d]: " 12963 "was %d now %d\n"), bkt_ptr, sub_bkt_ptr, 12964 bkt_ptr_arr[bkt_ptr * SOC_TH_MAX_SUB_BUCKETS + sub_bkt_ptr], 12965 lpm_idx)); 12966 error1 ++; 12967 } 12968 } 12969 if (ipv6) { 12970 if (flex) { 12971 alpm_mem = L3_DEFIP_ALPM_IPV6_64_1m; 12972 } else { 12973 alpm_mem = L3_DEFIP_ALPM_IPV6_64m; 12974 } 12975 } else { 12976 if (flex) { 12977 alpm_mem = L3_DEFIP_ALPM_IPV4_1m; 12978 } else { 12979 alpm_mem = L3_DEFIP_ALPM_IPV4m; 12980 } 12981 } 12982 12983 (void) soc_th_alpm_lpm_vrf_get(u, lpm_entry, &vrf_id, &vrf); 12984 12985 /* read shadow table for bpm length */ 12986 lpm_idx2 = soc_th_alpm_physical_idx(u, L3_DEFIPm, lpm_idx, 1); 12987 12988 if (bkt_usg) { 12989 if (bkt_usg[bkt_ptr].sub_bkts == 0) { 12990 bkt_usg[bkt_ptr].global = (vrf == SOC_VRF_MAX(u) + 1); 12991 } 12992 bkt_usg[bkt_ptr].sub_bkts |= 1U << sub_bkt_ptr; 12993 bkt_usg[bkt_ptr].pivots[sub_bkt_ptr] = (lpm_idx2 << 1) + i; 12994 } 12995 12996 bpm_len = -1; 12997 bpm_check = 0; 12998 if (!ALPM_CTRL(u).aux_enable) { 12999 rv = _soc_th_alpm_pivot_bmp_len_get( 13000 u, ipv6, lpm_entry, (uint32 *)&bpm_len); 13001 if (SOC_SUCCESS(rv)) { 13002 bpm_check = 1; 13003 } 13004 } else { 13005 rv = soc_mem_read(u, L3_DEFIP_AUX_TABLEm, MEM_BLOCK_ANY, 13006 lpm_idx2, shadow); 13007 if (SOC_SUCCESS(rv)) { 13008 if (i == 0) { 13009 bpm_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm, 13010 shadow, BPM_LENGTH0f); 13011 ip_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm, 13012 shadow, IP_LENGTH0f); 13013 } else { 13014 bpm_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm, 13015 shadow, BPM_LENGTH1f); 13016 ip_len = soc_mem_field32_get(u, L3_DEFIP_AUX_TABLEm, 13017 shadow, IP_LENGTH1f); 13018 } 13019 if (bpm_len > ip_len) { 13020 LOG_ERROR(BSL_LS_SOC_ALPM, 13021 (BSL_META_U(u, "\tAUX Table corrupted\n"))); 13022 error1 ++; 13023 } else { 13024 success ++; 13025 } 13026 bpm_check = 1; 13027 } 13028 } 13029 13030 if ((bpm_check == 1) && (bpm_len == 0) && 13031 SOC_MEM_OPT_F32_GET(u, L3_DEFIPm, lpm_entry, DEFAULT_MISS0f)) { 13032 bpm_check = 0; 13033 } 13034 13035 if (bpm_check) { 13036 sal_memcpy(&lpm_bmp, lpm_entry, sizeof(defip_entry_t)); 13037 _soc_th_alpm_pfx_len_to_mask(u, &lpm_bmp, bpm_len, ipv6); 13038 13039 fd_lpm_idx = fd_bkt_ptr = fd_alpm_idx = -1; 13040 rv = _soc_th_alpm_find( 13041 u, alpm_mem, ipv6, &lpm_bmp, vrf_id, vrf, 13042 e, &fd_lpm_idx, &fd_bkt_ptr, &fd_alpm_idx, 13043 (SOC_IS_TRIDENT3X(u) ? TRUE : 13044 (ALPM_CTRL(u).aux_enable ? FALSE : TRUE))); 13045 if (fd_lpm_idx > 0) { 13046 fd_lpm_idx = soc_th_alpm_logical_idx(u, L3_DEFIPm, 13047 fd_lpm_idx >> 1, 1); 13048 } 13049 if (SOC_SUCCESS(rv)) { 13050 j = 0; 13051 if (soc_feature(u, soc_feature_generic_dest)) { 13052 uint32 val, dest_type = SOC_MEM_FIF_DEST_NEXTHOP; 13053 val = soc_mem_field32_dest_get(u, alpm_mem, e, 13054 DESTINATIONf, &dest_type); 13055 if (dest_type == SOC_MEM_FIF_DEST_ECMP) { 13056 data1[j++] = 1; 13057 } else { 13058 data1[j++] = 0; 13059 } 13060 data1[j++] = val; 13061 data1[j++] = val; 13062 } else { 13063 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, ECMPf); 13064 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, ECMP_PTRf); 13065 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, NEXT_HOP_INDEXf); 13066 } 13067 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, PRIf); 13068 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, RPEf); 13069 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, DST_DISCARDf); 13070 data1[j++] = soc_mem_field32_get(u, alpm_mem, e, CLASS_IDf); 13071 13072 if (sal_memcmp(data0, data1, sizeof(data0)) != 0) { 13073 LOG_ERROR(BSL_LS_SOC_ALPM, 13074 (BSL_META_U(u, 13075 "\tData mismatch: " 13076 "lpm_idx %d find_lpm_idx %d " 13077 "find_alpm_idx %d find_bkt_ptr %d\n"), 13078 lpm_idx, fd_lpm_idx, 13079 fd_alpm_idx, fd_bkt_ptr)); 13080 error1 ++; 13081 } else { 13082 success ++; 13083 } 13084 } else { 13085 if (rv == SOC_E_NOT_FOUND && 13086 (vrf_id == SOC_L3_VRF_GLOBAL || ALPM_CTRL(u).gp_zoned)) { 13087 LOG_VERBOSE(BSL_LS_SOC_ALPM, 13088 (BSL_META_U(u, 13089 "\t_soc_th_alpm_find rv=%d: " 13090 "lpm_idx %d find_lpm_idx %d " 13091 "find_alpm_idx %d find_bkt_ptr %d," 13092 "(Possible: global route or !combined " 13093 "without default)\n"), 13094 rv, lpm_idx, fd_lpm_idx, 13095 fd_alpm_idx, fd_bkt_ptr)); 13096 } else { 13097 LOG_ERROR(BSL_LS_SOC_ALPM, 13098 (BSL_META_U(u, 13099 "\t_soc_th_alpm_find rv=%d: " 13100 "lpm_idx %d find_lpm_idx %d " 13101 "find_alpm_idx %d find_bkt_ptr %d\n"), 13102 rv, lpm_idx, fd_lpm_idx, 13103 fd_alpm_idx, fd_bkt_ptr)); 13104 error1 ++; 13105 } 13106 } 13107 } 13108 13109 bank_disable = 13110 ALPM_CTRL(u).bank_disable_bmp_8b[vrf != SOC_VRF_MAX(u) + 1]; 13111 ent_num = _soc_th_alpm_bkt_entry_cnt(u, alpm_mem); 13112 13113 /* Traverse bucket */ 13114 for (ent = 0; ent < ent_num; ent++) { 13115 rv = _soc_th_alpm_mem_index(u, alpm_mem, bkt_ptr, ent, 13116 bank_disable, &alpm_idx); 13117 13118 if (SOC_FAILURE(rv)) { 13119 LOG_ERROR(BSL_LS_SOC_ALPM, 13120 (BSL_META_U(u, "\tALPM mem index get failure: rv %d " 13121 "bkt_ptr %d, ent %d, bank_dis %d\n"), 13122 rv, bkt_ptr, ent, bank_disable)); 13123 error1 ++; 13124 error2 ++; 13125 } 13126 13127 rv = _soc_mem_alpm_read(u, alpm_mem, MEM_BLOCK_ANY, alpm_idx, e); 13128 if (SOC_FAILURE(rv)) { 13129 continue; 13130 } 13131 13132 if (!soc_mem_field32_get(u, alpm_mem, e, VALIDf)) { 13133 continue; 13134 } 13135 13136 if (sub_bkt_ptr != 13137 soc_mem_field32_get(u, alpm_mem, e, SUB_BKT_PTRf)) { 13138 continue; 13139 } 13140 13141 if (bkt_usg) { 13142 bkt_usg[bkt_ptr].count++; 13143 } 13144 13145 (void) _soc_th_alpm_lpm_ent_init(u, e, alpm_mem, ipv6, vrf_id, 13146 ALPM_LOG_BKT(bkt_ptr, sub_bkt_ptr), 13147 0, &lpm_entry2, 0); 13148 13149 if (check_sw) { 13150 rv = _soc_th_alpm_sw_prefix_check(u, alpm_mem, ipv6, &lpm_entry2, vrf_id, vrf); 13151 if (SOC_FAILURE(rv)) { 13152 error1 ++; 13153 error2 ++; 13154 LOG_ERROR(BSL_LS_SOC_ALPM, 13155 (BSL_META_U(u, 13156 "_soc_th_alpm_sw_prefix_check rv=%d: v6 = %d, vrf_id = %d, vrf = %d\n"), 13157 rv, ipv6, vrf_id, vrf)); 13158 } 13159 } 13160 13161 fd_lpm_idx2 = fd_lpm_idx = fd_bkt_ptr = fd_alpm_idx = -1; 13162 rv = _soc_th_alpm_find( 13163 u, alpm_mem, ipv6, &lpm_entry2, vrf_id, vrf, 13164 e, &fd_lpm_idx, &fd_bkt_ptr, &fd_alpm_idx, 13165 (SOC_IS_TRIDENT3X(u) ? TRUE : 13166 (ALPM_CTRL(u).aux_enable ? FALSE : TRUE))); 13167 if (SOC_SUCCESS(rv)) { 13168 fd_lpm_idx2 = soc_th_alpm_logical_idx(u, 13169 L3_DEFIPm, fd_lpm_idx >> 1, 1); 13170 } 13171 13172 if (SOC_FAILURE(rv) || 13173 fd_bkt_ptr != ALPM_LOG_BKT(bkt_ptr, sub_bkt_ptr) || 13174 fd_lpm_idx2 != lpm_idx || 13175 fd_lpm_idx >> 1 != lpm_idx2 || /* for map remap */ 13176 fd_alpm_idx != alpm_idx) { 13177 13178 error1 ++; 13179 error2 ++; 13180 LOG_ERROR(BSL_LS_SOC_ALPM, 13181 (BSL_META_U(u, 13182 "\t_soc_th_alpm_find2 rv=%d: " 13183 "fl [%d,%d] fa %d fb [%d,%d] " 13184 "l [%d,%d] a %d b [%d,%d]\n"), 13185 rv, 13186 fd_lpm_idx >> 1, fd_lpm_idx2, fd_alpm_idx, 13187 ALPM_PHY_BKT(u, fd_bkt_ptr), ALPM_SUB_BKT(u, fd_bkt_ptr), 13188 lpm_idx2, lpm_idx, alpm_idx, bkt_ptr, sub_bkt_ptr)); 13189 } 13190 } 13191 if (error2 == 0) { 13192 success ++; 13193 } 13194 13195 if (!check_sw) { 13196 continue; 13197 } 13198 13199 /* 13200 * Check hardware table above. 13201 * Check software table below. 13202 */ 13203 13204 /* lpm hash */ 13205 13206 rv = LPM_HASH_VERIFY(u, lpm_entry, 13207 ipv6 ? lpm_idx : ((lpm_idx << 1) + i)); 13208 if (SOC_FAILURE(rv)) { 13209 LOG_ERROR(BSL_LS_SOC_ALPM, 13210 (BSL_META_U(u, "\tLPM Hash check failed: rv %d " 13211 "lpm_idx %d\n"), 13212 rv, lpm_idx)); 13213 error1 ++; 13214 } else { 13215 success ++; 13216 } 13217 13218 /* bucket bitmap */ 13219 rv = soc_th_alpm_bucket_is_assigned(u, ALPM_LOG_BKT(bkt_ptr, sub_bkt_ptr), 13220 vrf, ipv6, &used); 13221 if (SOC_FAILURE(rv) || sub_bkt_ptr >= SOC_TH_MAX_SUB_BUCKETS) { 13222 LOG_ERROR(BSL_LS_SOC_ALPM, 13223 (BSL_META_U(u, "\tInvalid bucket pointer [%d,%d] " 13224 "detected, in memory %s index %d\n"), 13225 bkt_ptr, sub_bkt_ptr, 13226 SOC_MEM_NAME(u, L3_DEFIPm), lpm_idx)); 13227 error1 ++; 13228 } else if (used == 0) { 13229 /* If bucket was already freed */ 13230 LOG_ERROR(BSL_LS_SOC_ALPM, 13231 (BSL_META_U(u, "\tFreed bucket pointer %d " 13232 "detected, in memory %s index %d\n"), bkt_ptr, 13233 SOC_MEM_NAME(u, L3_DEFIPm), lpm_idx)); 13234 error1 ++; 13235 } else { 13236 success ++; 13237 } 13238 13239 /* bucket view map */ 13240 bkt_mem_type = soc_alpm_cmn_bkt_view_get(u, 13241 SOC_TH_ALPM_AIDX(u, bkt_ptr, 0, 0, 0)); 13242 if (alpm_mem != bkt_mem_type) { 13243 LOG_ERROR(BSL_LS_SOC_ALPM, 13244 (BSL_META_U(u, "\tMismatched alpm view " 13245 "in bucket %d, expected %s, was %s\n"), bkt_ptr, 13246 SOC_MEM_NAME(u, alpm_mem), 13247 SOC_MEM_NAME(u, bkt_mem_type))); 13248 error1 ++; 13249 } else { 13250 success ++; 13251 } 13252 13253 /* Check bpm len information */ 13254 rv = _soc_th_alpm_prefix_create(u, ipv6, lpm_entry, prefix, 13255 &length, &default_route); 13256 if (SOC_SUCCESS(rv)) { 13257 if (ipv6) { 13258 pfx_trie = VRF_PREFIX_TRIE_IPV6(u, vrf); 13259 } else { 13260 pfx_trie = VRF_PREFIX_TRIE_IPV4(u, vrf); 13261 } 13262 lpmp = NULL; 13263 if (pfx_trie) { 13264 rv = trie_find_lpm(pfx_trie, prefix, length, &lpmp); 13265 } 13266 if (SOC_SUCCESS(rv) && lpmp){ 13267 tmp_pyld = (payload_t *) lpmp; 13268 if (tmp_pyld->bkt_ptr != NULL) { 13269 trie_bpm_len = ((payload_t *)(tmp_pyld->bkt_ptr))->len; 13270 if (trie_bpm_len != bpm_len) { 13271 LOG_ERROR(BSL_LS_SOC_ALPM, 13272 (BSL_META_U(u, "\tBPM len mismatch: lpm_idx %d" 13273 " alpm_idx %d bpm_len %d trie_bpm_len %d\n"), 13274 lpm_idx, alpm_idx, bpm_len, trie_bpm_len)); 13275 error1 ++; 13276 } else { 13277 success ++; 13278 } 13279 } else { 13280 success ++; 13281 } 13282 } else { 13283 LOG_ERROR(BSL_LS_SOC_ALPM, 13284 (BSL_META_U(u, "\ttrie_find_lpm failed: " 13285 "lpm_idx %d alpm_idx %d lpmp %p\n"), 13286 lpm_idx, alpm_idx, lpmp)); 13287 error1 ++; 13288 } 13289 } else { 13290 LOG_ERROR(BSL_LS_SOC_ALPM, 13291 (BSL_META_U(u, "\tPrefix creating failed: " 13292 "lpm_idx %d alpm_idx %d\n" ), lpm_idx, alpm_idx)); 13293 error1 ++; 13294 } 13295 } 13296 } 13297 13298 if (error1) { 13299 LOG_ERROR(BSL_LS_SOC_ALPM, 13300 (BSL_META_U(u, 13301 "\tL3_DEFIP index:[%d,%d] check failed. ipv6 %d error count %d\n"), 13302 prev_idx, prev_i, prev_v6, error1)); 13303 error = 1; 13304 } else if (success) { 13305 LOG_INFO(BSL_LS_SOC_ALPM,(BSL_META_U(u, 13306 "\tL3_DEFIP index:[%d,%d] check passed. ipv6 %d success count %d\n"), 13307 prev_idx, prev_i, prev_v6, success)); 13308 } 13309 13310 SOC_ALPM_LPM_UNLOCK(u); 13311 sal_free(e); 13312 sal_free(shadow); 13313 soc_cm_sfree(u, buffer); 13314 13315 return (error ? SOC_E_FAIL: SOC_E_NONE); 13316 } 13317 13318 extern int _soc_th_alpm_128_sanity_check(int u, int min, int max, 13319 int check_sw, int *bkt_ptr_arr, 13320 alpm_bkt_usg_t *bkt_usg); 13321 13322 /* 13323 * Function: 13324 * soc_th_alpm_sanity_check 13325 * Purpose: 13326 * Sanity check for ALPM 13327 * Parameters: 13328 * u - Device unit 13329 * mem - L3_DEFIP/L3_DEFIP_PAIR_128 memory 13330 * index - -2 indicates full check to both table, 13331 * -1 indicates full check to given table 13332 * other indicates single entry check to given table 13333 * check_sw - Check SW tables as well. 13334 */ 13335 int 13336 soc_th_alpm_sanity_check(int u, soc_mem_t mem, int index, int check_sw) 13337 { 13338 int alloc_size; 13339 int rv = SOC_E_NONE; 13340 int rv2 = SOC_E_NONE; 13341 int index_min = -1, index_max = -1; 13342 int index_min2 = -1, index_max2 = -1; 13343 int *bkt_ptr_arr = NULL; 13344 #ifdef ALPM_SANITY_SENSITIVE 13345 int i, j; 13346 soc_mem_t bkt_view; 13347 #endif 13348 alpm_bkt_usg_t *bkt_usg = NULL; 13349 int error, bkt_ptr; 13350 13351 if ((mem == L3_DEFIPm || index == -2) && 13352 soc_mem_index_max(u, L3_DEFIPm) != -1) { 13353 index_min = soc_mem_index_min(u, L3_DEFIPm); 13354 index_max = soc_mem_index_max(u, L3_DEFIPm); 13355 /* Don't check urpf */ 13356 if (SOC_URPF_STATUS_GET(u)) { 13357 index_max >>= 1; 13358 } 13359 if (index < -2 || index > index_max) { 13360 return SOC_E_PARAM; 13361 } 13362 if (index >= index_min && index <= index_max) { 13363 index_min = index; 13364 index_max = index; 13365 } 13366 } 13367 13368 if ((mem == L3_DEFIP_PAIR_128m || index == -2) && 13369 soc_mem_index_max(u, L3_DEFIP_PAIR_128m) != -1) { 13370 index_min2 = soc_mem_index_min(u, L3_DEFIP_PAIR_128m); 13371 index_max2 = soc_mem_index_max(u, L3_DEFIP_PAIR_128m); 13372 /* Don't check urpf */ 13373 if (SOC_URPF_STATUS_GET(u)) { 13374 index_max2 >>= 1; 13375 } 13376 if (index < -2 || index > index_max2) { 13377 return SOC_E_PARAM; 13378 } 13379 if (index >= index_min2 && index <= index_max2) { 13380 index_min2 = index; 13381 index_max2 = index; 13382 } 13383 } 13384 13385 if (index_max == -1 && index_max2 == -1) { 13386 return SOC_E_PARAM; 13387 } 13388 13389 L3_LOCK(u); 13390 alloc_size = sizeof(int) * ALPM_CTRL(u).num_bkts * SOC_TH_MAX_SUB_BUCKETS; 13391 bkt_ptr_arr = sal_alloc(alloc_size, "Bucket ptr array"); 13392 if (bkt_ptr_arr == NULL) { 13393 return SOC_E_MEMORY; 13394 } 13395 sal_memset(bkt_ptr_arr, 0xff, alloc_size); 13396 13397 alloc_size = ALPM_CTRL(u).num_bkts * sizeof(alpm_bkt_usg_t); 13398 bkt_usg = sal_alloc(alloc_size, "ALPM bucket usage"); 13399 if (bkt_usg == NULL) { 13400 sal_free(bkt_ptr_arr); 13401 return SOC_E_MEMORY; 13402 } 13403 sal_memset(bkt_usg, 0, alloc_size); 13404 13405 if (index_max != -1) { 13406 LOG_CLI(("Processing ALPM sanity check L3_DEFIP " 13407 "from index:%d to index:%d\n", 13408 index_min, index_max)); 13409 rv = _soc_th_alpm_sanity_check(u, index_min, index_max, check_sw, bkt_ptr_arr, bkt_usg); 13410 LOG_CLI(("ALPM sanity check L3_DEFIP %s. \n\n", 13411 SOC_SUCCESS(rv) ? "passed" : "failed")); 13412 } 13413 13414 if (index_max2 != -1) { 13415 LOG_CLI(("Processing ALPM sanity check L3_DEFIP_PAIR_128 " 13416 "from index:%d to index:%d\n", 13417 index_min2, index_max2)); 13418 rv2 = _soc_th_alpm_128_sanity_check(u, index_min2, index_max2, check_sw, bkt_ptr_arr, bkt_usg); 13419 LOG_CLI(("ALPM sanity check L3_DEFIP_PAIR_128 %s. \n", 13420 SOC_SUCCESS(rv2) ? "passed" : "failed")); 13421 } 13422 13423 #ifdef ALPM_SANITY_SENSITIVE 13424 /* This check is very sensitive, turn it off for now. */ 13425 /* In case full check to both table, the bkt ptr is fully collected */ 13426 if (index == -2 && SOC_SUCCESS(rv) && SOC_SUCCESS(rv2)) { 13427 for (i = 0; i < ALPM_CTRL(u).num_bkts; i++) { 13428 for (j = 0; j < SOC_TH_MAX_SUB_BUCKETS; j++) { 13429 if (bkt_ptr_arr[i * SOC_TH_MAX_SUB_BUCKETS + j] != -1) { 13430 break; 13431 } 13432 } 13433 if (j < SOC_TH_MAX_SUB_BUCKETS) { 13434 continue; 13435 } 13436 13437 bkt_view = soc_alpm_cmn_bkt_view_get(u, 13438 SOC_TH_ALPM_AIDX(u, i, 0, 0, 0)); 13439 if (bkt_view != INVALIDm){ 13440 LOG_ERROR(BSL_LS_SOC_ALPM, 13441 (BSL_META_U(u, 13442 "\tBucket view corrupted: bkt_ptr %d, view %s.\n"), 13443 i, SOC_MEM_NAME(u, bkt_view))); 13444 } 13445 } 13446 } 13447 #endif 13448 13449 /* In case full check to both table and software check is enabled, 13450 * the bucket usage data is fully collected 13451 */ 13452 error = 0; 13453 if (index == -2 && SOC_SUCCESS(rv) && SOC_SUCCESS(rv2) && check_sw) { 13454 for (bkt_ptr = 0; bkt_ptr < ALPM_CTRL(u).num_bkts; bkt_ptr++) { 13455 if (bkt_usg[bkt_ptr].count != SOC_ALPM_BU_COUNT(u, bkt_ptr)) { 13456 LOG_ERROR(BSL_LS_SOC_ALPM, 13457 (BSL_META_U(u, "\tBucket count conflict: "\ 13458 "phy_bkt %d hw-sw %d-%d\n"), 13459 bkt_ptr, bkt_usg[bkt_ptr].count, 13460 SOC_ALPM_BU_COUNT(u, bkt_ptr))); 13461 error ++; 13462 } 13463 13464 if (bkt_usg[bkt_ptr].sub_bkts != SOC_ALPM_BU_SUB_BKTS(u, bkt_ptr)) { 13465 LOG_ERROR(BSL_LS_SOC_ALPM, 13466 (BSL_META_U(u, "\tBucket sub_bkts conflict: "\ 13467 "phy_bkt %d hw-sw 0x%x-0x%x\n"), 13468 bkt_ptr, bkt_usg[bkt_ptr].sub_bkts, 13469 SOC_ALPM_BU_SUB_BKTS(u, bkt_ptr))); 13470 error ++; 13471 } 13472 13473 if (bkt_usg[bkt_ptr].pivots[0] != SOC_ALPM_BU_PIVOT_IDX(u, bkt_ptr, 0) || 13474 bkt_usg[bkt_ptr].pivots[1] != SOC_ALPM_BU_PIVOT_IDX(u, bkt_ptr, 1) || 13475 bkt_usg[bkt_ptr].pivots[2] != SOC_ALPM_BU_PIVOT_IDX(u, bkt_ptr, 2) || 13476 bkt_usg[bkt_ptr].pivots[3] != SOC_ALPM_BU_PIVOT_IDX(u, bkt_ptr, 3)) { 13477 LOG_ERROR(BSL_LS_SOC_ALPM, 13478 (BSL_META_U(u, "\tBucket pivots conflict: "\ 13479 "phy_bkt %d hw-sw %d-%d %d-%d %d-%d %d-%d\n"), 13480 bkt_ptr, 13481 bkt_usg[bkt_ptr].pivots[0], 13482 SOC_ALPM_BU_PIVOT_IDX(u, bkt_ptr, 0), 13483 bkt_usg[bkt_ptr].pivots[1], 13484 SOC_ALPM_BU_PIVOT_IDX(u, bkt_ptr, 1), 13485 bkt_usg[bkt_ptr].pivots[2], 13486 SOC_ALPM_BU_PIVOT_IDX(u, bkt_ptr, 2), 13487 bkt_usg[bkt_ptr].pivots[3], 13488 SOC_ALPM_BU_PIVOT_IDX(u, bkt_ptr, 3))); 13489 error ++; 13490 } 13491 } 13492 LOG_CLI(("ALPM sanity check bucket usage %s. \n", 13493 error == 0 ? "passed" : "failed")); 13494 } 13495 13496 sal_free(bkt_ptr_arr); 13497 sal_free(bkt_usg); 13498 L3_UNLOCK(u); 13499 return SOC_FAILURE(rv) ? rv : 13500 SOC_FAILURE(rv2) ? rv2 : 13501 error ? SOC_E_FAIL : SOC_E_NONE; 13502 } 13503 13504 13505 STATIC int 13506 _soc_th_alpm_route_resource_get(int unit, soc_mem_t mem, 13507 int *num_pivots, int *num_bkts) 13508 { 13509 int tcam_ent = 0, tot_bkt = 0; 13510 int tcam_alpm = 0, parallel = 0; 13511 int urpf = SOC_URPF_STATUS_GET(unit); 13512 int v6; 13513 13514 switch (ALPM_CTRL(unit).alpm_mode) { 13515 case SOC_ALPM_MODE_PARALLEL: 13516 parallel = 1; 13517 break; 13518 case SOC_ALPM_MODE_TCAM_ALPM: 13519 tcam_alpm = 1; 13520 case SOC_ALPM_MODE_COMBINED: 13521 break; 13522 default: 13523 return SOC_E_INTERNAL; 13524 } 13525 13526 tot_bkt = ALPM_CTRL(unit).num_bkts; 13527 13528 switch (mem) { 13529 case L3_DEFIP_ALPM_IPV4m: 13530 case L3_DEFIP_ALPM_IPV4_1m: 13531 tcam_ent = soc_mem_index_count(unit, L3_DEFIPm) * 2; 13532 #ifdef BCM_TOMAHAWK2_SUPPORT 13533 if (soc_feature(unit, soc_feature_half_of_l3_defip_ipv4_capacity)) { 13534 tcam_ent >>= 1; 13535 } 13536 #endif 13537 if (ALPM_CTRL(unit)._alpm_128b_bkt_rsvd) { 13538 tot_bkt -= ALPM_CTRL(unit)._alpm_128b_bkt_rsvd_cnt; 13539 } 13540 break; 13541 13542 case L3_DEFIP_ALPM_IPV6_64m: 13543 case L3_DEFIP_ALPM_IPV6_64_1m: 13544 tcam_ent = soc_mem_index_count(unit, L3_DEFIP_PAIR_128m); 13545 if (ALPM_CTRL(unit)._alpm_128b_bkt_rsvd) { 13546 tot_bkt = ALPM_CTRL(unit)._alpm_128b_bkt_rsvd_cnt; 13547 } 13548 13549 if (tcam_ent == 0) { 13550 tcam_ent = soc_mem_index_count(unit, L3_DEFIPm); 13551 tot_bkt = ALPM_CTRL(unit).num_bkts; 13552 } 13553 v6 = 1; 13554 break; 13555 13556 case L3_DEFIP_ALPM_IPV6_128m: 13557 tcam_ent = soc_mem_index_count(unit, L3_DEFIP_PAIR_128m); 13558 if (ALPM_CTRL(unit)._alpm_128b_bkt_rsvd) { 13559 tot_bkt = ALPM_CTRL(unit)._alpm_128b_bkt_rsvd_cnt; 13560 } 13561 13562 v6 = 1; 13563 break; 13564 13565 default: 13566 break; 13567 } 13568 13569 if (tcam_alpm) { 13570 tcam_ent >>= 1; 13571 } 13572 13573 if (urpf) { 13574 tcam_ent >>= 1; 13575 } 13576 13577 if (urpf) { 13578 if (!parallel) { 13579 tot_bkt >>= 1; 13580 } 13581 } else { 13582 if (SOC_TH_ALPM_SCALE_CHECK(unit, v6)) { 13583 tot_bkt >>= 1; 13584 } 13585 } 13586 13587 if (num_pivots) { 13588 *num_pivots = tcam_ent; 13589 } 13590 13591 if (num_bkts) { 13592 *num_bkts = tot_bkt; 13593 } 13594 13595 return SOC_E_NONE; 13596 } 13597 13598 13599 STATIC int 13600 _soc_th_alpm_route_capacity_max(int unit, soc_mem_t mem) 13601 { 13602 int max_ent = 0, ent_num = 0; 13603 int num_pivots = 0, num_bkts = 0; 13604 int rv; 13605 13606 rv = _soc_th_alpm_route_resource_get(unit, mem, &num_pivots, &num_bkts); 13607 if (SOC_FAILURE(rv)) { 13608 max_ent = -1; 13609 return max_ent; 13610 } 13611 13612 ent_num = _soc_th_alpm_bkt_entry_cnt(unit, mem); 13613 13614 if (num_pivots) { 13615 /* if number of pivots is larger than half of that of buckets, 13616 * then the MAX buckets allowed is limited by the number of 13617 * physical buckets 13618 */ 13619 if (num_pivots <= num_bkts) { 13620 max_ent = ent_num * num_pivots; 13621 } else { 13622 max_ent = ent_num * num_bkts; 13623 } 13624 13625 if (ALPM_CTRL(unit).alpm_mode == SOC_ALPM_MODE_TCAM_ALPM) { 13626 max_ent += num_pivots; 13627 } 13628 } else { 13629 max_ent = 0; 13630 } 13631 13632 return max_ent; 13633 } 13634 13635 13636 STATIC int 13637 _soc_th_alpm_route_capacity_min(int unit, soc_mem_t mem) 13638 { 13639 #define UTIL_50(x) ((x) / 2) 13640 #define UTIL_75(x) ((x) * 3 / 4) 13641 #define UTIL_87(x) ((x) * 87 / 100) 13642 #define UTIL_93(x) ((x) * 93 / 100) 13643 13644 int min_ent = 0, ent_num = 0; 13645 int num_pivots = 0, num_bkts = 0; 13646 int rv; 13647 13648 rv = _soc_th_alpm_route_resource_get(unit, mem, &num_pivots, &num_bkts); 13649 if (SOC_FAILURE(rv)) { 13650 min_ent = -1; 13651 return min_ent; 13652 } 13653 13654 ent_num = _soc_th_alpm_bkt_entry_cnt(unit, mem); 13655 13656 if (num_pivots) { 13657 if (num_pivots <= num_bkts) { 13658 /* less than 1:1 */ 13659 min_ent = UTIL_50(ent_num * num_pivots); 13660 } else { 13661 if (num_pivots < num_bkts * 2) { 13662 /* less than 2:1 */ 13663 min_ent = UTIL_50(ent_num * num_bkts); 13664 } else if (num_pivots < num_bkts * 3) { 13665 /* less than 3:1 */ 13666 min_ent = UTIL_75(ent_num * num_bkts); 13667 } else if (num_pivots < num_bkts * 4) { 13668 /* less than 4:1 */ 13669 min_ent = UTIL_87(ent_num * num_bkts); 13670 } else { 13671 min_ent = UTIL_93(ent_num * num_bkts); 13672 } 13673 } 13674 13675 if (ALPM_CTRL(unit).alpm_mode == SOC_ALPM_MODE_TCAM_ALPM) { 13676 min_ent += num_pivots; 13677 } 13678 } else { 13679 min_ent = 0; 13680 } 13681 13682 return min_ent; 13683 } 13684 /* 13685 * Function: 13686 * soc_th_alpm_route_capacity_get 13687 * Purpose: 13688 * Get the capacity for ALPM from tables: 13689 * L3_DEFIP_ALPM_IPV4, L3_DEFIP_ALPM_IPV6_64, L3_DEFIP_ALPM_IPV6_128 13690 * L3_DEFIP, L3_DEFIP_PAIR_128 13691 * Parameters: 13692 * unit - Device unit 13693 * route_type - 0: v4, 1: v6-64, 2: v6-128 13694 * cap_type - 0: max capacity, 1: min guaranteed capacity 13695 * max_entries - Maximum result returned. 13696 * min_entries - Minimum result returned. 13697 */ 13698 int 13699 soc_th_alpm_route_capacity_get(int unit, soc_mem_t mem, 13700 int *max_entries, int *min_entries) 13701 { 13702 13703 if (max_entries == NULL && min_entries == NULL) { 13704 return SOC_E_PARAM; 13705 } 13706 switch (mem) { 13707 case L3_DEFIP_ALPM_IPV4m: 13708 case L3_DEFIP_ALPM_IPV4_1m: 13709 case L3_DEFIP_ALPM_IPV6_64m: 13710 case L3_DEFIP_ALPM_IPV6_64_1m: 13711 case L3_DEFIP_ALPM_IPV6_128m: 13712 break; 13713 default: 13714 return SOC_E_UNAVAIL; 13715 } 13716 if (min_entries) { 13717 *min_entries = _soc_th_alpm_route_capacity_min(unit, mem); 13718 if (*min_entries < 0) { 13719 return SOC_E_INTERNAL; 13720 } 13721 } 13722 13723 if (max_entries != NULL) { 13724 *max_entries = _soc_th_alpm_route_capacity_max(unit, mem); 13725 if (*max_entries < 0) { 13726 return SOC_E_INTERNAL; 13727 } 13728 } 13729 13730 return SOC_E_NONE; 13731 } 13732 13733 #endif /* TOMAHAWK APACHE */ 13734 #endif /* ALPM_ENABLE */