lpmv6.c (153229B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: lpv6.c 8 * Purpose: L3 LPM V6 function implementations 9 */ 10 11 #include <soc/defs.h> 12 #include <shared/bsl.h> 13 #ifdef INCLUDE_L3 14 15 #include <soc/drv.h> 16 #include <bcm/vlan.h> 17 #include <bcm/error.h> 18 19 #include <bcm/l3.h> 20 #include <soc/l3x.h> 21 #include <soc/lpm.h> 22 #include <soc/format.h> 23 #ifdef ALPM_ENABLE 24 #include <soc/alpm.h> 25 #endif 26 #include <bcm/tunnel.h> 27 #include <bcm/debug.h> 28 #include <bcm/error.h> 29 #include <bcm/stack.h> 30 #include <soc/trident2.h> 31 32 #include <bcm_int/esw/trident2.h> 33 #include <bcm_int/esw/lpmv6.h> 34 #include <bcm_int/esw/firebolt.h> 35 #include <bcm_int/esw/triumph.h> 36 #include <bcm_int/esw/triumph2.h> 37 #include <bcm_int/esw/stack.h> 38 #include <bcm_int/esw/flex_ctr.h> 39 #include <bcm_int/esw_dispatch.h> 40 #include <bcm_int/esw/flex_ctr.h> 41 #include <bcm_int/esw/virtual.h> 42 #include <bcm_int/esw/l3.h> 43 #include <bcm_int/esw/alpm.h> 44 #include <bcm_int/esw/alpm_util.h> 45 46 #ifdef BCM_KATANA2_SUPPORT 47 #include <bcm_int/esw/katana2.h> 48 #endif /* BCM_KATANA2_SUPPORT */ 49 50 #ifdef BCM_TRIDENT3_SUPPORT 51 #include <bcm_int/esw/trident3.h> 52 #include <bcm_int/esw/flow.h> 53 #include <soc/esw/flow_db.h> 54 #endif /* TRIDENT3_SUPPORT */ 55 56 #if defined(BCM_TRX_SUPPORT) 57 #include <bcm_int/esw/trx.h> 58 #endif /* BCM_TRX_SUPPORT */ 59 60 #define _BCM_L3_MEM_BANKS_ALL (-1) 61 #define _BCM_HOST_ENTRY_NOT_FOUND (-1) 62 63 /* L3 LPM state */ 64 _bcm_defip_pair128_table_t *l3_defip_pair128[BCM_MAX_NUM_UNITS]; 65 66 #define SOC_LPM_128_LPM_CACHE_FIELD_CREATE(m, f) soc_field_info_t * m##f 67 #define SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(m_u, s, m, f) \ 68 (s)->m##f = soc_mem_fieldinfo_get(m_u, m, f) 69 typedef struct soc_lpm_128_field_cache_s { 70 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, CLASS_IDf); 71 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, DST_DISCARDf); 72 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ECMPf); 73 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ECMP_COUNTf); 74 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ECMP_PTRf); 75 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, GLOBAL_ROUTEf); 76 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, HITf); 77 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IP_ADDR0_UPRf); 78 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IP_ADDR1_UPRf); 79 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IP_ADDR0_LWRf); 80 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IP_ADDR1_LWRf); 81 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IP_ADDR_MASK0_UPRf); 82 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IP_ADDR_MASK1_UPRf); 83 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IP_ADDR_MASK0_LWRf); 84 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IP_ADDR_MASK1_LWRf); 85 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MODE0_UPRf); 86 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MODE1_UPRf); 87 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MODE0_LWRf); 88 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MODE1_LWRf); 89 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MODE_MASK0_UPRf); 90 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MODE_MASK1_UPRf); 91 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MODE_MASK0_LWRf); 92 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MODE_MASK1_LWRf); 93 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, NEXT_HOP_INDEXf); 94 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, PRIf); 95 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, RPEf); 96 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VALID0_UPRf); 97 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VALID1_UPRf); 98 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VALID0_LWRf); 99 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VALID1_LWRf); 100 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VRF_ID_0_UPRf); 101 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VRF_ID_1_UPRf); 102 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VRF_ID_0_LWRf); 103 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VRF_ID_1_LWRf); 104 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VRF_ID_MASK0_UPRf); 105 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VRF_ID_MASK1_UPRf); 106 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VRF_ID_MASK0_LWRf); 107 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, VRF_ID_MASK1_LWRf); 108 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, GLOBAL_HIGHf); 109 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ALG_HIT_IDXf); 110 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, ALG_BKT_PTRf); 111 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, DEFAULT_MISSf); 112 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, FLEX_CTR_BASE_COUNTER_IDXf); 113 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, FLEX_CTR_POOL_NUMBERf); 114 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, SRC_DISCARDf); 115 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, DEFAULTROUTEf); 116 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, HIT0f); 117 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, HIT1f); 118 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 119 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, MULTICAST_ROUTEf); 120 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf); 121 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf); 122 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, EXPECTED_L3_IIFf); 123 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, RPA_IDf); 124 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_128m, L3MC_INDEXf); 125 #endif 126 #if defined(BCM_TOMAHAWK3_SUPPORT) 127 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, LWR_HIT0f); 128 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, LWR_HIT1f); 129 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, LWR_VALID0f); 130 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, LWR_VALID1f); 131 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, UPR_VALID0f); 132 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, UPR_VALID1f); 133 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, LWR_KEY0f); 134 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, LWR_KEY1f); 135 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, UPR_KEY0f); 136 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, UPR_KEY1f); 137 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, LWR_MASK0f); 138 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, LWR_MASK1f); 139 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, UPR_MASK0f); 140 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, UPR_MASK1f); 141 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, LWR_ASSOC_DATA0f); 142 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, LWR_ASSOC_DATA1f); 143 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, LWR_FIXED_DATA0f); 144 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, LWR_FIXED_DATA1f); 145 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, LWR_ALPM1_DATA0f); 146 SOC_LPM_128_LPM_CACHE_FIELD_CREATE(L3_DEFIP_PAIR_LEVEL1m, LWR_ALPM1_DATA1f); 147 #endif 148 } soc_lpm_128_field_cache_t, *soc_lpm_128_field_cache_p; 149 150 static soc_lpm_128_field_cache_p 151 soc_lpm_128_field_cache_state[SOC_MAX_NUM_DEVICES]; 152 153 #define SOC_TH3_MEM_OPT_FLD_SET(m_unit, m_entry_data, m_field, m_pval) \ 154 soc_meminfo_fieldinfo_field_set((m_entry_data), \ 155 (&SOC_MEM_INFO(m_unit, L3_DEFIP_PAIR_LEVEL1m)), \ 156 (soc_lpm_128_field_cache_state[(m_unit)]->L3_DEFIP_PAIR_LEVEL1m##m_field), (m_pval)) 157 158 #define SOC_TH3_MEM_OPT_FLD_VALID(m_unit, m_mem, m_field) \ 159 ((soc_lpm_128_field_cache_state[(m_unit)]->L3_DEFIP_PAIR_LEVEL1m##m_field) != NULL) 160 161 #define SOC_TH3_MEM_OPT_FLD_LENGTH(m_unit, m_mem, m_field) \ 162 ((soc_lpm_128_field_cache_state[(m_unit)]->L3_DEFIP_PAIR_LEVEL1m##m_field)->len) 163 164 #define SOC_TH3_MEM_OPT_FLD32_GET(m_unit, m_mem, m_entry_data, m_field) \ 165 soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), \ 166 (m_entry_data), (soc_lpm_128_field_cache_state[(m_unit)]->L3_DEFIP_PAIR_LEVEL1m##m_field)) 167 168 #define SOC_TH3_MEM_OPT_FLD32_SET(m_unit, m_mem, m_entry_data, m_field, m_val) \ 169 soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), \ 170 (m_entry_data), (soc_lpm_128_field_cache_state[(m_unit)]->L3_DEFIP_PAIR_LEVEL1m##m_field), (m_val)) 171 172 #define SOC_TH3_MEM_OPT_FLD_GET(m_unit, m_mem, m_entry_data, m_field, m_pval) \ 173 soc_meminfo_fieldinfo_field_get((m_entry_data), \ 174 (&SOC_MEM_INFO(m_unit, m_mem)), \ 175 (soc_lpm_128_field_cache_state[(m_unit)]->L3_DEFIP_PAIR_LEVEL1m##m_field), (m_pval)) 176 177 178 #define SOC_MEM_OPT_FLD32_GET(m_unit, m_mem, m_entry_data, m_field) \ 179 soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), \ 180 (m_entry_data), (soc_lpm_128_field_cache_state[(m_unit)]->m_mem##m_field)) 181 182 #define SOC_MEM_OPT_FLD32_SET(m_unit, m_mem, m_entry_data, m_field, m_val) \ 183 soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), \ 184 (m_entry_data), (soc_lpm_128_field_cache_state[(m_unit)]->m_mem##m_field), (m_val)) 185 186 #define SOC_MEM_OPT_FLD_GET(m_unit, m_mem, m_entry_data, m_field, m_pval) \ 187 soc_meminfo_fieldinfo_field_get((m_entry_data), \ 188 (&SOC_MEM_INFO(m_unit, m_mem)), \ 189 (soc_lpm_128_field_cache_state[(m_unit)]->m_mem##m_field), (m_pval)) 190 191 #define SOC_MEM_OPT_FLD_SET(m_unit, m_mem, m_entry_data, m_field, m_pval) \ 192 soc_meminfo_fieldinfo_field_set((m_entry_data), \ 193 (&SOC_MEM_INFO(m_unit, m_mem)), \ 194 (soc_lpm_128_field_cache_state[(m_unit)]->m_mem##m_field), (m_pval)) 195 196 #define SOC_MEM_OPT_FLD_VALID(m_unit, m_mem, m_field) \ 197 ((soc_lpm_128_field_cache_state[(m_unit)]->m_mem##m_field) != NULL) 198 199 #define SOC_MEM_OPT_FLD_LENGTH(m_unit, m_mem, m_field) \ 200 ((soc_lpm_128_field_cache_state[(m_unit)]->m_mem##m_field)->len) 201 202 203 /* 204 * Function: 205 * _bcm_l3_defip_mem_get 206 * Purpose: 207 * Resolve route table memory for a given route entry. 208 * Parameters: 209 * unit - (IN)SOC unit number. 210 * flags - (IN)IPv6/IPv4 route. 211 * plen - (IN)Prefix length. 212 * mem - (OUT)Route table memory. 213 * Returns: 214 * BCM_E_XXX 215 */ 216 STATIC int 217 _bcm_l3_defip_mem_get(int unit, uint32 flags, int plen, soc_mem_t *mem) 218 { 219 /* Default value */ 220 *mem = L3_DEFIPm; 221 if(!SOC_MEM_IS_VALID(unit, L3_DEFIPm) && 222 (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m))) { 223 *mem = L3_DEFIP_LEVEL1m; 224 } 225 226 if ((flags & BCM_L3_IP6) && (plen > 64)) { 227 *mem = L3_DEFIP_PAIR_128m; 228 if(!SOC_MEM_IS_VALID(unit, L3_DEFIP_PAIR_128m)) { 229 *mem = L3_DEFIP_PAIR_LEVEL1m; 230 } 231 } 232 return BCM_E_NONE; 233 } 234 235 /* 236 * Function: 237 * _bcm_defip_pair128_hash 238 * Purpose: 239 * Calculate an entry 16 bit hash. 240 * Parameters: 241 * unit - (IN)SOC unit number. 242 * lpm_cfg - (IN)Buffer to fill defip information. 243 * entry_hash - (OUT)Entry hash 244 * Returns: 245 * BCM_E_XXX 246 */ 247 STATIC int 248 _bcm_defip_pair128_hash(int unit, _bcm_defip_cfg_t *lpm_cfg, uint16 *hash) 249 { 250 uint32 key[BCM_DEFIP_PAIR128_HASH_SZ]; 251 252 if (hash == NULL) { 253 return (BCM_E_PARAM); 254 } 255 256 if (lpm_cfg->defip_flags & BCM_L3_IP6) { 257 SAL_IP6_ADDR_TO_UINT32(lpm_cfg->defip_ip6_addr, key); 258 key[4] = lpm_cfg->defip_sub_len; 259 key[5] = lpm_cfg->defip_vrf; 260 261 *hash = _shr_crc16b(0, (void *)key, 262 WORDS2BITS((BCM_DEFIP_PAIR128_HASH_SZ))); 263 } else { 264 /* Call V4 hash function */ 265 } 266 return (BCM_E_NONE); 267 } 268 269 int 270 _bcm_defip_lkup_plen_get(int unit, _bcm_defip_cfg_t *lpm_cfg) 271 { 272 int f, mc; 273 274 f = ((BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) ? 2 : 1); 275 mc = (lpm_cfg->defip_flags & BCM_L3_IPMC); 276 277 if (soc_feature(unit, soc_feature_td3_lpm_ipmc_war) && mc) { 278 f += 3; 279 } 280 281 return lpm_cfg->defip_sub_len * f; 282 } 283 284 #ifdef BCM_WARM_BOOT_SUPPORT 285 /* 286 * Function: 287 * _bcm_defip_pair128_reinit 288 * Purpose: 289 * Re-Initialize sw image for L3_DEFIP_PAIR_128 internal tcam. 290 * during warm boot. 291 * Parameters: 292 * unit - (IN)SOC unit number. 293 * idx - (IN)Entry index 294 * lpm_cfg - (IN)Inserted entry. 295 * Returns: 296 * BCM_E_XXX 297 */ 298 STATIC int 299 _bcm_defip_pair128_reinit(int unit, int idx, _bcm_defip_cfg_t *lpm_cfg) 300 { 301 int lkup_plen; /* Vrf weighted lookup prefix. */ 302 uint16 hash = 0; /* Entry hash value. */ 303 304 /* Calculate vrf weighted prefix length. */ 305 lkup_plen = _bcm_defip_lkup_plen_get(unit, lpm_cfg); 306 307 /* Calculate entry lookup hash. */ 308 BCM_IF_ERROR_RETURN(_bcm_defip_pair128_hash(unit, lpm_cfg, &hash)); 309 310 /* Set software structure info. */ 311 BCM_DEFIP_PAIR128_ENTRY_SET(unit, idx, lkup_plen, hash); 312 313 /* Update software usage counter. */ 314 BCM_DEFIP_PAIR128_USED_COUNT(unit)++; 315 soc_lpm_stat_128b_count_update(unit, 1); 316 317 return (BCM_E_NONE); 318 } 319 #endif /* BCM_WARM_BOOT_SUPPORT */ 320 321 /* 322 * Function: 323 * _bcm_defip_pair128_deinit 324 * Purpose: 325 * De-initialize sw image for L3_DEFIP_PAIR_128 internal tcam. 326 * Parameters: 327 * unit - (IN)SOC unit number. 328 * Returns: 329 * BCM_E_XXX 330 */ 331 int 332 _bcm_defip_pair128_deinit(int unit) 333 { 334 335 if (BCM_DEFIP_PAIR128(unit) == NULL) { 336 return (BCM_E_NONE); 337 } 338 339 /* De-allocate any existing structures. */ 340 if (soc_lpm_128_field_cache_state[unit] != NULL) { 341 sal_free(soc_lpm_128_field_cache_state[unit]); 342 soc_lpm_128_field_cache_state[unit] = NULL; 343 } 344 345 if (BCM_DEFIP_PAIR128_ARR(unit) != NULL) { 346 sal_free(BCM_DEFIP_PAIR128_ARR(unit)); 347 BCM_DEFIP_PAIR128_ARR(unit) = NULL; 348 } 349 sal_free(BCM_DEFIP_PAIR128(unit)); 350 BCM_DEFIP_PAIR128(unit) = NULL; 351 352 return (BCM_E_NONE); 353 } 354 355 int 356 _bcm_defip_pair128_field_cache_init(int unit) 357 { 358 /* De-allocate existing structures. */ 359 if (soc_lpm_128_field_cache_state[unit] != NULL) { 360 sal_free(soc_lpm_128_field_cache_state[unit]); 361 } 362 363 soc_lpm_128_field_cache_state[unit] = 364 sal_alloc(sizeof(soc_lpm_128_field_cache_t), "lpm_128_field_state"); 365 if (NULL == soc_lpm_128_field_cache_state[unit]) { 366 return (BCM_E_MEMORY); 367 } 368 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 369 L3_DEFIP_PAIR_128m, CLASS_IDf); 370 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 371 L3_DEFIP_PAIR_128m, DST_DISCARDf); 372 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 373 L3_DEFIP_PAIR_128m, ECMPf); 374 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 375 L3_DEFIP_PAIR_128m, ECMP_COUNTf); 376 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 377 L3_DEFIP_PAIR_128m, ECMP_PTRf); 378 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 379 L3_DEFIP_PAIR_128m, GLOBAL_ROUTEf); 380 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 381 L3_DEFIP_PAIR_128m, HITf); 382 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 383 L3_DEFIP_PAIR_128m, IP_ADDR0_LWRf); 384 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 385 L3_DEFIP_PAIR_128m, IP_ADDR0_UPRf); 386 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 387 L3_DEFIP_PAIR_128m, IP_ADDR1_LWRf); 388 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 389 L3_DEFIP_PAIR_128m, IP_ADDR1_UPRf); 390 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 391 L3_DEFIP_PAIR_128m, IP_ADDR_MASK0_LWRf); 392 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 393 L3_DEFIP_PAIR_128m, IP_ADDR_MASK0_UPRf); 394 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 395 L3_DEFIP_PAIR_128m, IP_ADDR_MASK1_LWRf); 396 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 397 L3_DEFIP_PAIR_128m, IP_ADDR_MASK1_UPRf); 398 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 399 L3_DEFIP_PAIR_128m, MODE0_LWRf); 400 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 401 L3_DEFIP_PAIR_128m, MODE0_UPRf); 402 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 403 L3_DEFIP_PAIR_128m, MODE1_LWRf); 404 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 405 L3_DEFIP_PAIR_128m, MODE1_UPRf); 406 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 407 L3_DEFIP_PAIR_128m, MODE_MASK0_LWRf); 408 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 409 L3_DEFIP_PAIR_128m, MODE_MASK0_UPRf); 410 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 411 L3_DEFIP_PAIR_128m, MODE_MASK1_LWRf); 412 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 413 L3_DEFIP_PAIR_128m, MODE_MASK1_UPRf); 414 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 415 L3_DEFIP_PAIR_128m, NEXT_HOP_INDEXf); 416 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 417 L3_DEFIP_PAIR_128m, PRIf); 418 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 419 L3_DEFIP_PAIR_128m, RPEf); 420 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 421 L3_DEFIP_PAIR_128m, VALID0_LWRf); 422 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 423 L3_DEFIP_PAIR_128m, VALID0_UPRf); 424 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 425 L3_DEFIP_PAIR_128m, VALID1_LWRf); 426 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 427 L3_DEFIP_PAIR_128m, VALID1_UPRf); 428 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 429 L3_DEFIP_PAIR_128m, VRF_ID_0_LWRf); 430 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 431 L3_DEFIP_PAIR_128m, VRF_ID_0_UPRf); 432 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 433 L3_DEFIP_PAIR_128m, VRF_ID_1_LWRf); 434 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 435 L3_DEFIP_PAIR_128m, VRF_ID_1_UPRf); 436 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 437 L3_DEFIP_PAIR_128m, VRF_ID_MASK0_LWRf); 438 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 439 L3_DEFIP_PAIR_128m, VRF_ID_MASK0_UPRf); 440 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 441 L3_DEFIP_PAIR_128m, VRF_ID_MASK1_LWRf); 442 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 443 L3_DEFIP_PAIR_128m, VRF_ID_MASK1_UPRf); 444 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 445 L3_DEFIP_PAIR_128m, GLOBAL_HIGHf); 446 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 447 L3_DEFIP_PAIR_128m, ALG_HIT_IDXf); 448 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 449 L3_DEFIP_PAIR_128m, ALG_BKT_PTRf); 450 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 451 L3_DEFIP_PAIR_128m, DEFAULT_MISSf); 452 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 453 L3_DEFIP_PAIR_128m, 454 FLEX_CTR_BASE_COUNTER_IDXf); 455 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 456 L3_DEFIP_PAIR_128m, 457 FLEX_CTR_POOL_NUMBERf); 458 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 459 L3_DEFIP_PAIR_128m, 460 SRC_DISCARDf); 461 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 462 L3_DEFIP_PAIR_128m, DEFAULTROUTEf); 463 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 464 L3_DEFIP_PAIR_128m, HIT0f); 465 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 466 L3_DEFIP_PAIR_128m, HIT1f); 467 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 468 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 469 L3_DEFIP_PAIR_128m, MULTICAST_ROUTEf); 470 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 471 L3_DEFIP_PAIR_128m, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf); 472 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 473 L3_DEFIP_PAIR_128m, IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf); 474 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 475 L3_DEFIP_PAIR_128m, EXPECTED_L3_IIFf); 476 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 477 L3_DEFIP_PAIR_128m, RPA_IDf); 478 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 479 L3_DEFIP_PAIR_128m, L3MC_INDEXf); 480 #endif 481 #if defined(BCM_TOMAHAWK3_SUPPORT) 482 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 483 L3_DEFIP_PAIR_LEVEL1m, LWR_HIT0f); 484 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 485 L3_DEFIP_PAIR_LEVEL1m, LWR_HIT1f); 486 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 487 L3_DEFIP_PAIR_LEVEL1m, LWR_VALID0f); 488 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 489 L3_DEFIP_PAIR_LEVEL1m, LWR_VALID1f); 490 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 491 L3_DEFIP_PAIR_LEVEL1m, UPR_VALID0f); 492 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 493 L3_DEFIP_PAIR_LEVEL1m, UPR_VALID1f); 494 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 495 L3_DEFIP_PAIR_LEVEL1m, LWR_KEY0f); 496 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 497 L3_DEFIP_PAIR_LEVEL1m, LWR_KEY1f); 498 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 499 L3_DEFIP_PAIR_LEVEL1m, UPR_KEY0f); 500 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 501 L3_DEFIP_PAIR_LEVEL1m, UPR_KEY1f); 502 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 503 L3_DEFIP_PAIR_LEVEL1m, LWR_MASK0f); 504 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 505 L3_DEFIP_PAIR_LEVEL1m, LWR_MASK1f); 506 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 507 L3_DEFIP_PAIR_LEVEL1m, UPR_MASK0f); 508 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 509 L3_DEFIP_PAIR_LEVEL1m, UPR_MASK1f); 510 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 511 L3_DEFIP_PAIR_LEVEL1m, LWR_ASSOC_DATA0f); 512 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 513 L3_DEFIP_PAIR_LEVEL1m, LWR_ASSOC_DATA1f); 514 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 515 L3_DEFIP_PAIR_LEVEL1m, LWR_FIXED_DATA0f); 516 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 517 L3_DEFIP_PAIR_LEVEL1m, LWR_FIXED_DATA1f); 518 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 519 L3_DEFIP_PAIR_LEVEL1m, LWR_ALPM1_DATA0f); 520 SOC_LPM_128_LPM_CACHE_FIELD_ASSIGN(unit, soc_lpm_128_field_cache_state[unit], 521 L3_DEFIP_PAIR_LEVEL1m, LWR_ALPM1_DATA1f); 522 #endif 523 return BCM_E_NONE; 524 } 525 526 /* 527 * Function: 528 * _bcm_defip_pair128_init 529 * Purpose: 530 * Initialize sw image for L3_DEFIP_PAIR_128 internal tcam. 531 * Parameters: 532 * unit - (IN)SOC unit number. 533 * Returns: 534 * BCM_E_XXX 535 */ 536 STATIC int 537 _bcm_defip_pair128_init(int unit) 538 { 539 int rv; 540 int mem_sz; 541 int ipv6_128_depth; 542 543 /* De-allocate any existing structures. */ 544 if (BCM_DEFIP_PAIR128(unit) != NULL) { 545 rv = _bcm_defip_pair128_deinit(unit); 546 BCM_IF_ERROR_RETURN(rv); 547 } 548 549 /* Allocate cam control structure. */ 550 mem_sz = sizeof(_bcm_defip_pair128_table_t); 551 BCM_DEFIP_PAIR128(unit) = sal_alloc(mem_sz, "td2_l3_defip_pair128"); 552 if (BCM_DEFIP_PAIR128(unit) == NULL) { 553 return (BCM_E_MEMORY); 554 } 555 556 /* Reset cam control structure. */ 557 sal_memset(BCM_DEFIP_PAIR128(unit), 0, mem_sz); 558 559 ipv6_128_depth = SOC_L3_DEFIP_MAX_128B_ENTRIES(unit); 560 BCM_DEFIP_PAIR128_TOTAL(unit) = ipv6_128_depth; 561 BCM_DEFIP_PAIR128_URPF_OFFSET(unit) = 0; 562 BCM_DEFIP_PAIR128_IDX_MAX(unit) = ipv6_128_depth - 1; 563 if (ipv6_128_depth) { 564 mem_sz = ipv6_128_depth * sizeof(_bcm_defip_pair128_entry_t); 565 BCM_DEFIP_PAIR128_ARR(unit) = 566 sal_alloc(mem_sz, 567 "td2_l3_defip_pair128_entry_array"); 568 if (BCM_DEFIP_PAIR128_ARR(unit) == NULL) { 569 BCM_IF_ERROR_RETURN(_bcm_defip_pair128_deinit(unit)); 570 return (BCM_E_MEMORY); 571 } 572 sal_memset(BCM_DEFIP_PAIR128_ARR(unit), 0, mem_sz); 573 } 574 575 rv = _bcm_defip_pair128_field_cache_init(unit); 576 if (BCM_FAILURE(rv)) { 577 BCM_IF_ERROR_RETURN(_bcm_defip_pair128_deinit(unit)); 578 return rv; 579 } 580 581 return (BCM_E_NONE); 582 } 583 584 /* 585 * Function: 586 * _bcm_defip_pair128_ip6_mask_set 587 * Purpose: 588 * Set IP6 mask field in memory from ip6 addr type. 589 * Parameters: 590 * unit - (IN) BCM device number. 591 * mem - (IN) Memory id. 592 * entry - (IN) HW entry buffer. 593 * ip6 - (IN) SW ip6 address buffer. 594 * Returns: void 595 */ 596 STATIC void 597 _bcm_defip_pair128_ip6_mask_set(int unit, soc_mem_t mem, uint32 *entry, 598 const ip6_addr_t ip6) 599 { 600 uint32 ip6_field[4]; 601 602 #if defined(BCM_TOMAHAWK3_SUPPORT) 603 assert((mem == L3_DEFIP_PAIR_128m) || (mem == L3_DEFIP_PAIR_LEVEL1m)); 604 #else 605 assert(mem == L3_DEFIP_PAIR_128m); 606 #endif 607 ip6_field[3] = ((ip6[12] << 24)| (ip6[13] << 16) | 608 (ip6[14] << 8) | (ip6[15] << 0)); 609 610 #if defined(BCM_TOMAHAWK3_SUPPORT) 611 if (!SOC_MEM_IS_VALID(unit, L3_DEFIP_PAIR_128m)) { 612 int vrf_mask = 0; 613 uint32 _key_data[2] = {0,0}; 614 vrf_mask = (1 << soc_format_field_length(unit, L3_DEFIP_TCAM_KEYfmt, VRF_IDf)) - 1; 615 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf, ip6_field[3]); 616 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, VRF_IDf, vrf_mask); 617 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf, 0x3); 618 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_TYPEf, 0x1); 619 SOC_TH3_MEM_OPT_FLD_SET(unit, (uint32 *)entry, LWR_MASK0f, _key_data); 620 621 ip6_field[2] = ((ip6[8] << 24) | (ip6[9] << 16) | 622 (ip6[10] << 8) | (ip6[11] << 0)); 623 _key_data[0] = _key_data[1] = 0; 624 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf, ip6_field[2]); 625 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, VRF_IDf, vrf_mask); 626 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf, 0x3); 627 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_TYPEf, 0x1); 628 SOC_TH3_MEM_OPT_FLD_SET(unit, (uint32 *)entry, LWR_MASK1f, _key_data); 629 630 ip6_field[1] = ((ip6[4] << 24) | (ip6[5] << 16) | 631 (ip6[6] << 8) | (ip6[7] << 0)); 632 _key_data[0] = _key_data[1] = 0; 633 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf, ip6_field[1]); 634 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, VRF_IDf, vrf_mask); 635 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf, 0x3); 636 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_TYPEf, 0x1); 637 SOC_TH3_MEM_OPT_FLD_SET(unit, (uint32 *)entry, UPR_MASK0f, _key_data); 638 639 ip6_field[0] = ((ip6[0] << 24) | (ip6[1] << 16) | 640 (ip6[2] << 8) | (ip6[3] << 0)); 641 _key_data[0] = _key_data[1] = 0; 642 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf, ip6_field[0]); 643 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, VRF_IDf, vrf_mask); 644 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf, 0x3); 645 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_TYPEf, 0x1); 646 SOC_TH3_MEM_OPT_FLD_SET(unit, (uint32 *)entry, UPR_MASK1f, _key_data); 647 } else 648 #endif 649 { 650 SOC_MEM_OPT_FLD_SET(unit, L3_DEFIP_PAIR_128m, entry, IP_ADDR_MASK0_LWRf, &ip6_field[3]); 651 ip6_field[2] = ((ip6[8] << 24) | (ip6[9] << 16) | 652 (ip6[10] << 8) | (ip6[11] << 0)); 653 SOC_MEM_OPT_FLD_SET(unit, L3_DEFIP_PAIR_128m, entry, IP_ADDR_MASK1_LWRf, &ip6_field[2]); 654 ip6_field[1] = ((ip6[4] << 24) | (ip6[5] << 16) | 655 (ip6[6] << 8) | (ip6[7] << 0)); 656 SOC_MEM_OPT_FLD_SET(unit, L3_DEFIP_PAIR_128m, entry, IP_ADDR_MASK0_UPRf, &ip6_field[1]); 657 ip6_field[0] = ((ip6[0] << 24) | (ip6[1] << 16) | 658 (ip6[2] << 8) | (ip6[3] << 0)); 659 SOC_MEM_OPT_FLD_SET(unit, L3_DEFIP_PAIR_128m, entry, IP_ADDR_MASK1_UPRf, ip6_field); 660 } 661 } 662 663 /* 664 * Function: 665 * _bcm_defip_pair128_ip6_mask_get 666 * Purpose: 667 * Read IP6 mask field from memory field to ip6_addr_t buffer. 668 * Parameters: 669 * unit - (IN) BCM device number. 670 * mem - (IN) Memory id. 671 * entry - (IN) HW entry buffer. 672 * ip6 - (OUT) SW ip6 address buffer. 673 * Returns: void 674 */ 675 STATIC void 676 _bcm_defip_pair128_ip6_mask_get(int unit, soc_mem_t mem, const void *entry, 677 ip6_addr_t ip6) 678 { 679 uint32 ip6_field[4]; 680 681 assert((mem == L3_DEFIP_PAIR_128m) || (mem == L3_DEFIP_PAIR_LEVEL1m)); 682 683 #if defined(BCM_TOMAHAWK3_SUPPORT) 684 if (!SOC_MEM_IS_VALID(unit, L3_DEFIP_PAIR_128m)) { 685 uint32 _key_data[2] = {0, 0}; 686 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_LEVEL1m, (void *)entry, LWR_MASK0f, _key_data); 687 ip6_field[3] = soc_format_field32_get(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf); 688 ip6[12] = (uint8) (ip6_field[3] >> 24); 689 ip6[13] = (uint8) (ip6_field[3] >> 16 & 0xff); 690 ip6[14] = (uint8) (ip6_field[3] >> 8 & 0xff); 691 ip6[15] = (uint8) (ip6_field[3] & 0xff); 692 _key_data[0] = _key_data[1] = 0; 693 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_LEVEL1m, (void *)entry, LWR_MASK1f, _key_data); 694 ip6_field[2] = soc_format_field32_get(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf); 695 ip6[8] = (uint8) (ip6_field[2] >> 24); 696 ip6[9] = (uint8) (ip6_field[2] >> 16 & 0xff); 697 ip6[10] = (uint8) (ip6_field[2] >> 8 & 0xff); 698 ip6[11] = (uint8) (ip6_field[2] & 0xff); 699 _key_data[0] = _key_data[1] = 0; 700 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_LEVEL1m, (void *)entry, UPR_MASK0f, _key_data); 701 ip6_field[1] = soc_format_field32_get(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf); 702 ip6[4] = (uint8) (ip6_field[1] >> 24); 703 ip6[5] = (uint8) (ip6_field[1] >> 16 & 0xff); 704 ip6[6] = (uint8) (ip6_field[1] >> 8 & 0xff); 705 ip6[7] = (uint8) (ip6_field[1] & 0xff); 706 _key_data[0] = _key_data[1] = 0; 707 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_LEVEL1m, (void *)entry, UPR_MASK1f, _key_data); 708 ip6_field[0] = soc_format_field32_get(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf); 709 ip6[0] = (uint8) (ip6_field[0] >> 24); 710 ip6[1] = (uint8) (ip6_field[0] >> 16 & 0xff); 711 ip6[2] = (uint8) (ip6_field[0] >> 8 & 0xff); 712 ip6[3] = (uint8) (ip6_field[0] & 0xff); 713 } else 714 #endif 715 { 716 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_128m, entry, IP_ADDR_MASK0_LWRf, (uint32 *)&ip6_field[3]); 717 ip6[12] = (uint8) (ip6_field[3] >> 24); 718 ip6[13] = (uint8) (ip6_field[3] >> 16 & 0xff); 719 ip6[14] = (uint8) (ip6_field[3] >> 8 & 0xff); 720 ip6[15] = (uint8) (ip6_field[3] & 0xff); 721 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_128m, entry, IP_ADDR_MASK1_LWRf, (uint32 *)&ip6_field[2]); 722 ip6[8] = (uint8) (ip6_field[2] >> 24); 723 ip6[9] = (uint8) (ip6_field[2] >> 16 & 0xff); 724 ip6[10] = (uint8) (ip6_field[2] >> 8 & 0xff); 725 ip6[11] = (uint8) (ip6_field[2] & 0xff); 726 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_128m, entry, IP_ADDR_MASK0_UPRf, (uint32 *)&ip6_field[1]); 727 ip6[4] = (uint8) (ip6_field[1] >> 24); 728 ip6[5] = (uint8) (ip6_field[1] >> 16 & 0xff); 729 ip6[6] = (uint8) (ip6_field[1] >> 8 & 0xff); 730 ip6[7] = (uint8) (ip6_field[1] & 0xff); 731 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_128m, entry, IP_ADDR_MASK1_UPRf, ip6_field); 732 ip6[0] = (uint8) (ip6_field[0] >> 24); 733 ip6[1] = (uint8) (ip6_field[0] >> 16 & 0xff); 734 ip6[2] = (uint8) (ip6_field[0] >> 8 & 0xff); 735 ip6[3] = (uint8) (ip6_field[0] & 0xff); 736 } 737 } 738 739 /* 740 * Function: 741 * _bcm_defip_pair128_ip6_addr_set 742 * Purpose: 743 * Set IP6 address field in memory from ip6 addr type. 744 * Parameters: 745 * unit - (IN) BCM device number. 746 * mem - (IN) Memory id. 747 * entry - (IN) HW entry buffer. 748 * ip6 - (IN) SW ip6 address buffer. 749 * Returns: void 750 */ 751 STATIC void 752 _bcm_defip_pair128_ip6_addr_set(int unit, soc_mem_t mem, uint32 *entry, 753 const ip6_addr_t ip6) 754 { 755 uint32 ip6_field[4]; 756 757 assert(mem == L3_DEFIP_PAIR_128m); 758 759 ip6_field[3] = ((ip6[12] << 24)| (ip6[13] << 16) | 760 (ip6[14] << 8) | (ip6[15] << 0)); 761 SOC_MEM_OPT_FLD_SET(unit, L3_DEFIP_PAIR_128m, entry, IP_ADDR0_LWRf, &ip6_field[3]); 762 ip6_field[2] = ((ip6[8] << 24) | (ip6[9] << 16) | 763 (ip6[10] << 8) | (ip6[11] << 0)); 764 SOC_MEM_OPT_FLD_SET(unit, L3_DEFIP_PAIR_128m, entry, IP_ADDR1_LWRf, &ip6_field[2]); 765 ip6_field[1] = ((ip6[4] << 24) | (ip6[5] << 16) | 766 (ip6[6] << 8) | (ip6[7] << 0)); 767 SOC_MEM_OPT_FLD_SET(unit, L3_DEFIP_PAIR_128m, entry, IP_ADDR0_UPRf, &ip6_field[1]); 768 ip6_field[0] = ((ip6[0] << 24) | (ip6[1] << 16) | 769 (ip6[2] << 8) | (ip6[3] << 0)); 770 SOC_MEM_OPT_FLD_SET(unit, L3_DEFIP_PAIR_128m, entry, IP_ADDR1_UPRf, ip6_field); 771 772 } 773 774 /* 775 * Function: 776 * _bcm_defip_pair128_ip6_addr_get 777 * Purpose: 778 * Read IP6 address field from memory field to ip6_addr_t buffer. 779 * Parameters: 780 * unit - (IN) BCM device number. 781 * mem - (IN) Memory id. 782 * entry - (IN) HW entry buffer. 783 * ip6 - (OUT) SW ip6 address buffer. 784 * Returns: void 785 */ 786 STATIC void 787 _bcm_defip_pair128_ip6_addr_get(int unit, soc_mem_t mem, const void *entry, 788 ip6_addr_t ip6) 789 { 790 uint32 ip6_field[4]; 791 792 assert((mem == L3_DEFIP_PAIR_128m) || (mem == L3_DEFIP_PAIR_LEVEL1m)); 793 794 if (mem == L3_DEFIP_PAIR_128m) { 795 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_128m, entry, IP_ADDR0_LWRf, (uint32 *)&ip6_field[3]); 796 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_128m, entry, IP_ADDR1_LWRf, (uint32 *)&ip6_field[2]); 797 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_128m, entry, IP_ADDR0_UPRf, (uint32 *)&ip6_field[1]); 798 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_128m, entry, IP_ADDR1_UPRf, ip6_field); 799 } else { 800 #ifdef BCM_TOMAHAWK3_SUPPORT 801 uint32 _key_data[2] = {0, 0}; 802 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_LEVEL1m, (void *)entry, LWR_KEY0f, _key_data); 803 ip6_field[3] = soc_format_field32_get(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf); 804 _key_data[0] = _key_data[1] = 0; 805 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_LEVEL1m, (void *)entry, LWR_KEY1f, _key_data); 806 ip6_field[2] = soc_format_field32_get(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf); 807 _key_data[0] = _key_data[1] = 0; 808 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_LEVEL1m, (void *)entry, UPR_KEY0f, _key_data); 809 ip6_field[1] = soc_format_field32_get(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf); 810 _key_data[0] = _key_data[1] = 0; 811 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_LEVEL1m, (void *)entry, UPR_KEY1f, _key_data); 812 ip6_field[0] = soc_format_field32_get(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf); 813 #endif 814 } 815 ip6[12] = (uint8) (ip6_field[3] >> 24); 816 ip6[13] = (uint8) (ip6_field[3] >> 16 & 0xff); 817 ip6[14] = (uint8) (ip6_field[3] >> 8 & 0xff); 818 ip6[15] = (uint8) (ip6_field[3] & 0xff); 819 ip6[8] = (uint8) (ip6_field[2] >> 24); 820 ip6[9] = (uint8) (ip6_field[2] >> 16 & 0xff); 821 ip6[10] = (uint8) (ip6_field[2] >> 8 & 0xff); 822 ip6[11] = (uint8) (ip6_field[2] & 0xff); 823 ip6[4] = (uint8) (ip6_field[1] >> 24); 824 ip6[5] = (uint8) (ip6_field[1] >> 16 & 0xff); 825 ip6[6] =(uint8) (ip6_field[1] >> 8 & 0xff); 826 ip6[7] =(uint8) (ip6_field[1] & 0xff); 827 ip6[0] =(uint8) (ip6_field[0] >> 24); 828 ip6[1] =(uint8) (ip6_field[0] >> 16 & 0xff); 829 ip6[2] =(uint8) (ip6_field[0] >> 8 & 0xff); 830 ip6[3] =(uint8) (ip6_field[0] & 0xff); 831 832 } 833 834 /* 835 * Function: 836 * _bcm_defip_pair128_get_key 837 * Purpose: 838 * Parse route entry key from L3_DEFIP_PAIR_128 table. 839 * Parameters: 840 * unit - (IN)SOC unit number. 841 * entry - (IN)Hw entry buffer. 842 * lpm_cfg - (IN/OUT)Buffer to fill defip information. 843 * Returns: 844 * BCM_E_XXX 845 */ 846 STATIC int 847 _bcm_defip_pair128_get_key(int unit, uint32 *hw_entry, _bcm_defip_cfg_t *lpm_cfg) 848 { 849 bcm_ip6_t mask; /* Subnet mask. */ 850 soc_mem_t mem = L3_DEFIP_PAIR_128m; 851 852 /* Input parameters check. */ 853 if ((lpm_cfg == NULL) || (hw_entry == NULL)) { 854 return (BCM_E_PARAM); 855 } 856 857 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_PAIR_LEVEL1m)) { 858 #ifdef BCM_TOMAHAWK3_SUPPORT 859 uint32 _key_data[2] = {0, 0}; 860 uint8 priority = 0; 861 mem = L3_DEFIP_PAIR_LEVEL1m; 862 863 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_LEVEL1m, (void *)hw_entry, LWR_KEY0f, _key_data); 864 lpm_cfg->defip_vrf = soc_format_field32_get(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, VRF_IDf); 865 _key_data[0] = _key_data[1] = 0; 866 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_LEVEL1m, (void *)hw_entry, LWR_FIXED_DATA0f, _key_data); 867 priority = soc_format_field32_get(unit, FIXED_DATAfmt, _key_data, SUB_DB_PRIORITYf); 868 if (priority == 0) { 869 lpm_cfg->defip_vrf = BCM_L3_VRF_OVERRIDE; 870 } else if (priority == 2) { 871 lpm_cfg->defip_vrf = BCM_L3_VRF_GLOBAL; 872 } 873 #endif 874 } 875 876 #ifdef BCM_TRIDENT3_SUPPORT 877 if (soc_feature(unit, soc_feature_flex_flow)) { 878 uint32 key_type; 879 880 key_type = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, 881 hw_entry, KEY_TYPE0_LWRf); 882 883 if (BCMI_LPM_FLEX_VIEW(key_type)) { 884 BCM_IF_ERROR_RETURN( 885 _bcm_defip_pair128_flex_get_key(unit, hw_entry, lpm_cfg, key_type)); 886 return BCM_E_NONE; 887 } 888 } 889 #endif 890 891 /* Extract ip6 address. */ 892 _bcm_defip_pair128_ip6_addr_get(unit, mem, hw_entry, lpm_cfg->defip_ip6_addr); 893 894 /* Extract subnet mask. */ 895 _bcm_defip_pair128_ip6_mask_get(unit, mem, hw_entry, mask); 896 lpm_cfg->defip_sub_len = bcm_ip6_mask_length(mask); 897 898 /* Extract vrf id & vrf mask. */ 899 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_PAIR_128m)) { 900 if (!SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_MASK0_LWRf)) { 901 lpm_cfg->defip_vrf = BCM_L3_VRF_OVERRIDE; 902 } else { 903 lpm_cfg->defip_vrf = SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_0_LWRf); 904 } 905 } 906 return (BCM_E_NONE); 907 } 908 909 /* 910 * Function: 911 * _bcm_defip_pair128_match 912 * Purpose: 913 * Lookup route entry from L3_DEFIP_PAIR_128 table. 914 * Parameters: 915 * unit - (IN)SOC unit number. 916 * lpm_cfg - (IN)Buffer to fill defip information. 917 * hw_entry - (OUT)Matching hw entry. 918 * hw_index - (OUT)HW table index. 919 * Returns: 920 * BCM_E_XXX 921 */ 922 STATIC int 923 _bcm_defip_pair128_match(int unit, _bcm_defip_cfg_t *lpm_cfg, 924 uint32 *hw_entry, int *hw_index) 925 { 926 _bcm_defip_cfg_t candidate; /* Match condidate. */ 927 int lkup_plen; /* Vrf weighted lookup prefix. */ 928 int index; /* Table iteration index. */ 929 uint16 hash = 0; /* Entry hash value. */ 930 int rv = BCM_E_NONE; /* Internal operation status. */ 931 soc_mem_t mem = L3_DEFIP_PAIR_128m; 932 933 /* Initialization */ 934 sal_memset(&candidate, 0, sizeof(_bcm_defip_cfg_t)); 935 936 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_PAIR_LEVEL1m)) { 937 mem = L3_DEFIP_PAIR_LEVEL1m; 938 } 939 940 /* Calculate vrf weighted prefix length. */ 941 lkup_plen = _bcm_defip_lkup_plen_get(unit, lpm_cfg); 942 943 /* Calculate entry lookup hash. */ 944 BCM_IF_ERROR_RETURN(_bcm_defip_pair128_hash(unit, lpm_cfg, &hash)); 945 946 /* coverity[assignment : FALSE] */ 947 for (index = 0; index <= BCM_DEFIP_PAIR128_IDX_MAX(unit); index++) { 948 949 /* Route prefix length comparison. */ 950 if (lkup_plen != BCM_DEFIP_PAIR128_ARR(unit)[index].prefix_len) { 951 continue; 952 } 953 954 /* Route lookup key hash comparison. */ 955 if (hash != BCM_DEFIP_PAIR128_ARR(unit)[index].entry_hash) { 956 continue; 957 } 958 959 /* Hash & prefix length match -> read and compare hw entry itself. */ 960 rv = BCM_XGS3_MEM_READ(unit, mem, index, hw_entry); 961 if (BCM_FAILURE(rv)) { 962 break; 963 } 964 965 /* Make sure entry is valid. */ 966 #ifdef BCM_TOMAHAWK3_SUPPORT 967 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_PAIR_LEVEL1m)) { 968 if ((!SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_LEVEL1m, hw_entry, LWR_VALID0f)) || 969 (!SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_LEVEL1m, hw_entry, LWR_VALID1f)) || 970 (!SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_LEVEL1m, hw_entry, UPR_VALID0f)) || 971 (!SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_LEVEL1m, hw_entry, UPR_VALID1f)) 972 ) { 973 /* Too bad sw image doesn't match hardware. */ 974 continue; 975 } 976 } else 977 #endif 978 if ((!SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, hw_entry, VALID0_LWRf)) || 979 (!SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, hw_entry, VALID1_LWRf)) || 980 (!SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, hw_entry, VALID0_UPRf)) || 981 (!SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, hw_entry, VALID1_UPRf)) 982 ) { 983 /* Too bad sw image doesn't match hardware. */ 984 continue; 985 } 986 987 /* Extract entry address vrf */ 988 rv = _bcm_defip_pair128_get_key(unit, hw_entry, &candidate); 989 if (BCM_FAILURE(rv)) { 990 break; 991 } 992 993 994 /* Address & Vrf comparison. */ 995 if (lpm_cfg->defip_vrf != candidate.defip_vrf) { 996 continue; 997 } 998 999 /* Subnet mask comparison. */ 1000 if (lpm_cfg->defip_sub_len != candidate.defip_sub_len) { 1001 continue; 1002 } 1003 1004 1005 if (sal_memcmp(lpm_cfg->defip_ip6_addr, candidate.defip_ip6_addr, 1006 sizeof(bcm_ip6_t))) { 1007 continue; 1008 } 1009 1010 /* Matching entry found. */ 1011 break; 1012 1013 } 1014 1015 BCM_IF_ERROR_RETURN(rv); 1016 1017 if (index > BCM_DEFIP_PAIR128_IDX_MAX(unit)) { 1018 return (BCM_E_NOT_FOUND); 1019 } 1020 1021 *hw_index = index; 1022 return (BCM_E_NONE); 1023 } 1024 1025 /* 1026 * Function: 1027 * _bcm_defip_pair128_entry_clear 1028 * Purpose: 1029 * Clear/Reset a single route entry. 1030 * Parameters: 1031 * unit - (IN)SOC unit number. 1032 * hw_index - (IN)Entry index in the tcam. 1033 * Returns: 1034 * BCM_E_XXX 1035 */ 1036 STATIC int 1037 _bcm_defip_pair128_entry_clear(int unit, int hw_index) 1038 { 1039 soc_mem_t mem = L3_DEFIP_PAIR_128m; 1040 uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS]; 1041 soc_field_t key_field[4], mask_field[4]; 1042 int field_count, i; 1043 uint64 val64; 1044 key_field[0] = KEY0_UPRf; 1045 key_field[1] = KEY1_UPRf; 1046 key_field[2] = KEY0_LWRf; 1047 key_field[3] = KEY1_LWRf; 1048 mask_field[0] = MASK0_UPRf; 1049 mask_field[1] = MASK1_UPRf; 1050 mask_field[2] = MASK0_LWRf; 1051 mask_field[3] = MASK1_LWRf; 1052 field_count = 4; 1053 1054 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_PAIR_LEVEL1m)) { 1055 key_field[0] = UPR_KEY0f; 1056 key_field[1] = UPR_KEY1f; 1057 key_field[2] = LWR_KEY0f; 1058 key_field[3] = LWR_KEY1f; 1059 mask_field[0] = UPR_MASK0f; 1060 mask_field[1] = UPR_MASK1f; 1061 mask_field[2] = LWR_MASK0f; 1062 mask_field[3] = LWR_MASK1f; 1063 mem = L3_DEFIP_PAIR_LEVEL1m; 1064 } 1065 sal_memset(hw_entry, 0, WORDS2BYTES(SOC_MAX_MEM_FIELD_WORDS)); 1066 COMPILER_64_ZERO(val64); 1067 for (i = 0; i < field_count; i++) { 1068 soc_mem_field64_set(unit, mem, hw_entry, key_field[i], val64); 1069 soc_mem_field64_set(unit, mem, hw_entry, mask_field[i], val64); 1070 } 1071 1072 /* Reset hw entry. */ 1073 BCM_IF_ERROR_RETURN 1074 (BCM_XGS3_MEM_WRITE(unit, mem, hw_index, 1075 &soc_mem_entry_null(unit, mem))); 1076 BCM_IF_ERROR_RETURN 1077 (BCM_XGS3_MEM_WRITE(unit, mem, hw_index, hw_entry)); 1078 1079 /* Reset sw entry. */ 1080 BCM_DEFIP_PAIR128_ENTRY_SET(unit, hw_index, 0, 0); 1081 1082 /* Reset urpf source lookup entry. */ 1083 /* If soc_feature_l3_defip_advanced_lookup is TRUE then 1084 * both DIP and SIP lookup is done using 1 L3_DEFIP entry. 1085 * L3_DEFIP table is not divided into 2 to support URPF (Ex: KT2). 1086 */ 1087 if (SOC_URPF_STATUS_GET(unit) && 1088 !soc_feature(unit, soc_feature_l3_defip_advanced_lookup)) { 1089 BCM_IF_ERROR_RETURN 1090 (BCM_XGS3_MEM_WRITE(unit, mem, 1091 (hw_index + BCM_DEFIP_PAIR128_URPF_OFFSET(unit)), 1092 &soc_mem_entry_null(unit, mem))); 1093 BCM_IF_ERROR_RETURN 1094 (BCM_XGS3_MEM_WRITE(unit, mem, 1095 (hw_index+ BCM_DEFIP_PAIR128_URPF_OFFSET(unit)), hw_entry)); 1096 } 1097 return (BCM_E_NONE); 1098 } 1099 1100 /* 1101 * Function: 1102 * _bcm_defip_pair128_parse 1103 * Purpose: 1104 * Parse route entry from L3_DEFIP_PAIR_128 table to sw structure. 1105 * Parameters: 1106 * unit - (IN)SOC unit number. 1107 * hw_entry - (IN)Hw entry buffer. 1108 * lpm_cfg - (IN/OUT)Buffer to fill defip information. 1109 * nh_ecmp_idx - (OUT)Next hop ecmp table index. 1110 * Returns: 1111 * BCM_E_XXX 1112 */ 1113 static INLINE int 1114 _bcm_defip_pair128_parse(int unit, uint32 *hw_entry, 1115 _bcm_defip_cfg_t *lpm_cfg, int *nh_ecmp_idx) 1116 { 1117 /* Input parameters check. */ 1118 if ((lpm_cfg == NULL) || (hw_entry == NULL)) { 1119 return (BCM_E_PARAM); 1120 } 1121 1122 /* Reset entry flags first. */ 1123 lpm_cfg->defip_flags = 0; 1124 1125 #ifdef BCM_TRIDENT3_SUPPORT 1126 if (soc_feature(unit, soc_feature_flex_flow)) { 1127 uint32 key_type; 1128 1129 key_type = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, 1130 hw_entry, KEY_TYPE0_LWRf); 1131 1132 if (BCMI_LPM_FLEX_VIEW(key_type)) { 1133 return _bcm_td3_lpm_flex_ent_parse(unit, hw_entry, key_type, 1134 L3_DEFIP_PAIR_128m, lpm_cfg, 1135 nh_ecmp_idx); 1136 } 1137 } 1138 #endif 1139 1140 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1141 if (soc_feature(unit, soc_feature_ipmc_defip)) { 1142 int ipmc_route = 0; 1143 if (soc_mem_field_valid(unit, L3_DEFIP_PAIR_128m, MULTICAST_ROUTEf)) { 1144 ipmc_route = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, 1145 hw_entry, MULTICAST_ROUTEf); 1146 } else if (soc_mem_field_valid(unit, L3_DEFIP_PAIR_128m, DATA_TYPEf)) { 1147 if (soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, 1148 hw_entry, DATA_TYPEf) == 2) { 1149 ipmc_route = 1; 1150 } else { 1151 ipmc_route = 0; 1152 } 1153 } 1154 1155 if (ipmc_route) { 1156 int val; 1157 lpm_cfg->defip_flags |= BCM_L3_IPMC; 1158 1159 if (SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, hw_entry, IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf)) { 1160 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RPF_FAIL_DROP; 1161 } 1162 if (SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, hw_entry, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf)) { 1163 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RPF_FAIL_TOCPU; 1164 } 1165 val = SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, hw_entry, EXPECTED_L3_IIFf); 1166 /* 1167 * RP ID and ExpectedIIF are overlaid. 1168 */ 1169 if (soc_feature(unit, soc_feature_l3defip_rp_l3iif_resolve)) { 1170 int rpa_id_mask = 1171 (1 << soc_mem_field_length(unit, L3_DEFIP_PAIR_128m, RPA_IDf)) - 1; 1172 /* 1173 * 1) If value is more than RPA_ID field then its l3_iif. 1174 * N/A for TD3/MV2/HX5 to support warmboot. 1175 * 2) When RPF FAIL DROP/TOCPU flags are set then its l3iif valid 1176 */ 1177 if ((lpm_cfg->defip_ipmc_flags & 1178 (BCM_IPMC_RPF_FAIL_DROP | BCM_IPMC_RPF_FAIL_TOCPU)) || 1179 (!(SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit) || 1180 SOC_IS_HELIX5(unit)) && (val > rpa_id_mask))) { 1181 lpm_cfg->defip_expected_intf = val; 1182 if (0 != lpm_cfg->defip_expected_intf) { 1183 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_POST_LOOKUP_RPF_CHECK; 1184 } 1185 lpm_cfg->defip_l3a_rp = BCM_IPMC_RP_ID_INVALID; 1186 } else { 1187 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RP_ID_EXPECTED_INTF_RESOLVE; 1188 lpm_cfg->defip_l3a_rp = val & rpa_id_mask; 1189 lpm_cfg->defip_expected_intf = val; 1190 } 1191 } else if (_BCM_DEFIP_IPMC_RP_IS_SET(val)) { 1192 lpm_cfg->defip_l3a_rp = _BCM_DEFIP_IPMC_RP_GET(val); 1193 } else { 1194 lpm_cfg->defip_expected_intf = val; 1195 1196 if (0 != lpm_cfg->defip_expected_intf) { 1197 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_POST_LOOKUP_RPF_CHECK; 1198 } 1199 lpm_cfg->defip_l3a_rp = BCM_IPMC_RP_ID_INVALID; 1200 } 1201 1202 if (soc_feature(unit, soc_feature_generic_dest)) { 1203 uint32 dest_type = SOC_MEM_FIF_DEST_INVALID; 1204 uint32 dest_value = 0; 1205 dest_value = soc_mem_field32_dest_get(unit, 1206 L3_DEFIP_PAIR_128m, hw_entry, 1207 DESTINATIONf, &dest_type); 1208 if (dest_type == SOC_MEM_FIF_DEST_IPMC) { 1209 lpm_cfg->defip_mc_group = dest_value; 1210 } else { 1211 lpm_cfg->defip_mc_group = 0; 1212 } 1213 } else { 1214 lpm_cfg->defip_mc_group = soc_mem_field32_get(unit, L3_DEFIP_PAIR_128m, 1215 hw_entry, L3MC_INDEXf); 1216 } 1217 } 1218 } 1219 #endif 1220 1221 #if defined(BCM_TOMAHAWK3_SUPPORT) 1222 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_PAIR_LEVEL1m)) { 1223 uint32 _key_data[2] = {0, 0}; 1224 uint8 ecmp = 0; 1225 SOC_MEM_OPT_FLD_GET(unit, L3_DEFIP_PAIR_LEVEL1m, (void *)hw_entry, LWR_ASSOC_DATA0f, _key_data); 1226 ecmp = soc_format_field32_get(unit, ASSOC_DATA_FULLfmt, _key_data, DEST_TYPEf); 1227 if (ecmp) { 1228 lpm_cfg->defip_ecmp = TRUE; 1229 lpm_cfg->defip_flags |= BCM_L3_MULTIPATH; 1230 } else { 1231 lpm_cfg->defip_ecmp = 0; 1232 lpm_cfg->defip_ecmp_count = 0; 1233 } 1234 if (nh_ecmp_idx != NULL) { 1235 *nh_ecmp_idx = soc_format_field32_get(unit, ASSOC_DATA_FULLfmt, _key_data, DESTINATIONf); 1236 } 1237 /* Mark entry as IPv6 */ 1238 lpm_cfg->defip_flags |= BCM_L3_IP6; 1239 1240 /* Get entry priority. */ 1241 lpm_cfg->defip_prio = soc_format_field32_get(unit, ASSOC_DATA_FULLfmt, _key_data, PRIf); 1242 1243 /* Get classification group id. */ 1244 lpm_cfg->defip_lookup_class = 1245 soc_format_field32_get(unit, ASSOC_DATA_FULLfmt, _key_data, CLASS_IDf); 1246 1247 /* Get priority override bit. */ 1248 if (soc_format_field32_get(unit, ASSOC_DATA_FULLfmt, _key_data, RPEf)) { 1249 lpm_cfg->defip_flags |= BCM_L3_RPE; 1250 } 1251 1252 /* Get destination discard field. */ 1253 if (soc_format_field32_get(unit, ASSOC_DATA_FULLfmt, _key_data, DST_DISCARDf)) { 1254 lpm_cfg->defip_flags |= BCM_L3_DST_DISCARD; 1255 } 1256 1257 /* Get hit bit. */ 1258 if (SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_LEVEL1m, hw_entry, LWR_HIT0f)) { 1259 lpm_cfg->defip_flags |= BCM_L3_HIT; 1260 } 1261 1262 if (SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_LEVEL1m, hw_entry, LWR_HIT1f)) { 1263 lpm_cfg->defip_flags |= BCM_L3_HIT; 1264 } 1265 1266 return (BCM_E_NONE); 1267 } 1268 #endif 1269 if (soc_feature(unit, soc_feature_generic_dest)) { 1270 uint32 dstt = 0, dstv; 1271 dstv = soc_mem_field32_dest_get(unit, L3_DEFIP_PAIR_128m, hw_entry, 1272 DESTINATIONf, &dstt); 1273 if (dstt == SOC_MEM_FIF_DEST_ECMP) { 1274 lpm_cfg->defip_ecmp = TRUE; 1275 lpm_cfg->defip_flags |= BCM_L3_MULTIPATH; 1276 } else { 1277 lpm_cfg->defip_ecmp = 0; 1278 lpm_cfg->defip_ecmp_count = 0; 1279 } 1280 if (nh_ecmp_idx != NULL) { 1281 *nh_ecmp_idx = dstv; 1282 } 1283 } else { 1284 /* Check if entry points to ecmp group. */ 1285 if (SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, hw_entry, ECMPf)) { 1286 /* Mark entry as ecmp */ 1287 lpm_cfg->defip_ecmp = TRUE; 1288 lpm_cfg->defip_flags |= BCM_L3_MULTIPATH; 1289 1290 /* Get ecmp group id. */ 1291 if (nh_ecmp_idx != NULL) { 1292 *nh_ecmp_idx = SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, 1293 hw_entry, ECMP_PTRf); 1294 } 1295 } else { 1296 /* Mark entry as non-ecmp. */ 1297 lpm_cfg->defip_ecmp = 0; 1298 1299 /* Reset ecmp group next hop count. */ 1300 lpm_cfg->defip_ecmp_count = 0; 1301 1302 /* Get next hop index. */ 1303 if (nh_ecmp_idx != NULL) { 1304 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1305 if (soc_feature(unit, soc_feature_ipmc_defip) && 1306 (lpm_cfg->defip_flags & BCM_L3_IPMC)) { 1307 *nh_ecmp_idx = BCM_XGS3_L3_INVALID_INDEX; 1308 } else 1309 #endif 1310 { 1311 *nh_ecmp_idx = SOC_MEM_OPT_FLD32_GET(unit, 1312 L3_DEFIP_PAIR_128m, hw_entry, NEXT_HOP_INDEXf); 1313 } 1314 } 1315 } 1316 } 1317 1318 /* Mark entry as IPv6 */ 1319 lpm_cfg->defip_flags |= BCM_L3_IP6; 1320 1321 /* Get entry priority. */ 1322 lpm_cfg->defip_prio = SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, hw_entry, PRIf); 1323 1324 /* Get classification group id. */ 1325 lpm_cfg->defip_lookup_class = 1326 SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, hw_entry, CLASS_IDf); 1327 1328 /* Get hit bit. */ 1329 if (SOC_MEM_OPT_FLD_VALID(unit, L3_DEFIP_PAIR_128m, HITf)) { 1330 if (SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, hw_entry, HITf)) { 1331 lpm_cfg->defip_flags |= BCM_L3_HIT; 1332 } 1333 } 1334 1335 if (SOC_MEM_OPT_FLD_VALID(unit, L3_DEFIP_PAIR_128m, HIT0f)) { 1336 if (SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, hw_entry, HIT0f)) { 1337 lpm_cfg->defip_flags |= BCM_L3_HIT; 1338 } 1339 } 1340 1341 /* Get priority override bit. */ 1342 if (SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, hw_entry, RPEf)) { 1343 lpm_cfg->defip_flags |= BCM_L3_RPE; 1344 } 1345 1346 /* Get destination discard field. */ 1347 if (SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, hw_entry, DST_DISCARDf)) { 1348 lpm_cfg->defip_flags |= BCM_L3_DST_DISCARD; 1349 } 1350 return (BCM_E_NONE); 1351 } 1352 1353 /* 1354 * Function: 1355 * _bcm_defip_pair128_shift 1356 * Purpose: 1357 * Shift entries in the tcam. 1358 * Parameters: 1359 * unit - (IN)SOC unit number. 1360 * idx_src - (IN)Entry source. 1361 * idx_dest - (IN)Entry destination. 1362 * Returns: 1363 * BCM_E_XXX 1364 */ 1365 STATIC int 1366 _bcm_defip_pair128_shift(int unit, int idx_src, int idx_dest) 1367 { 1368 uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer. */ 1369 soc_mem_t mem = L3_DEFIP_PAIR_128m; 1370 1371 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_PAIR_LEVEL1m)) { 1372 mem = L3_DEFIP_PAIR_LEVEL1m; 1373 } 1374 1375 /* Don't copy uninstalled entries. */ 1376 if (0 != BCM_DEFIP_PAIR128_ARR(unit)[idx_src].prefix_len) { 1377 /* Read entry from source index. */ 1378 BCM_IF_ERROR_RETURN 1379 (BCM_XGS3_MEM_READ(unit, mem, idx_src, hw_entry)); 1380 1381 /* Write entry to the destination index. */ 1382 BCM_IF_ERROR_RETURN 1383 (BCM_XGS3_MEM_WRITE(unit, mem, idx_dest, hw_entry)); 1384 1385 /* Shift corresponding URPF/source lookup entries. */ 1386 /* If soc_feature_l3_defip_advanced_lookup is TRUE then 1387 * both DIP and SIP lookup is done using 1 L3_DEFIP entry. 1388 * L3_DEFIP table is not divided into 2 to support URPF (Ex: KT2). 1389 */ 1390 if (SOC_URPF_STATUS_GET(unit) && 1391 !soc_feature(unit, soc_feature_l3_defip_advanced_lookup)) { 1392 /* Read entry from source index + half tcam. */ 1393 BCM_IF_ERROR_RETURN 1394 (BCM_XGS3_MEM_READ(unit, mem, 1395 idx_src + BCM_DEFIP_PAIR128_URPF_OFFSET(unit), 1396 hw_entry)); 1397 1398 /* Write entry to the destination index + half tcam. */ 1399 BCM_IF_ERROR_RETURN 1400 (BCM_XGS3_MEM_WRITE(unit, mem, 1401 idx_dest + BCM_DEFIP_PAIR128_URPF_OFFSET(unit), 1402 hw_entry)); 1403 } 1404 } 1405 1406 /* Copy software portion of the entry. */ 1407 sal_memcpy (&BCM_DEFIP_PAIR128_ARR(unit)[idx_dest], 1408 &BCM_DEFIP_PAIR128_ARR(unit)[idx_src], 1409 sizeof(_bcm_defip_pair128_entry_t)); 1410 1411 return (BCM_E_NONE); 1412 } 1413 1414 /* 1415 * Function: 1416 * _bcm_defip_pair128_shift_range 1417 * Purpose: 1418 * Shift entries in the tcam. 1419 * Parameters: 1420 * unit - (IN)SOC unit number. 1421 * idx_start - (IN)Start index 1422 * idx_end - (IN)End index 1423 * Returns: 1424 * BCM_E_XXX 1425 */ 1426 STATIC int 1427 _bcm_defip_pair128_shift_range(int unit, int idx_start, int idx_end) 1428 { 1429 int idx; /* Iteration index. */ 1430 int rv = BCM_E_NONE; /* Operaton status. */ 1431 1432 /* Shift entries down (1 index up) */ 1433 if (idx_end > idx_start) { 1434 for (idx = idx_end - 1; idx >= idx_start; idx--) { 1435 rv = _bcm_defip_pair128_shift(unit, idx, idx + 1); 1436 if (BCM_FAILURE(rv)) { 1437 break; 1438 } 1439 } 1440 /* Delete last entry from hardware & software. */ 1441 rv = _bcm_defip_pair128_entry_clear(unit, idx_start); 1442 } 1443 1444 /* Shift entries up (1 index down) */ 1445 if (idx_end < idx_start) { 1446 for (idx = idx_end + 1; idx <= idx_start; idx++) { 1447 rv = _bcm_defip_pair128_shift(unit, idx, idx - 1); 1448 if (BCM_FAILURE(rv)) { 1449 break; 1450 } 1451 } 1452 /* Delete last entry from hardware & software. */ 1453 rv = _bcm_defip_pair128_entry_clear(unit, idx_start); 1454 } 1455 1456 return (rv); 1457 } 1458 1459 /* 1460 * Function: 1461 * _bcm_defip_pair128_idx_alloc 1462 * Purpose: 1463 * Shuffle the tcam in order to insert a new entry 1464 * based on vrf weighted prefix length. 1465 * Parameters: 1466 * unit - (IN)SOC unit number. 1467 * lpm_cfg - (IN)Route info 1468 * hw_index - (OUT)Allocated hw index. 1469 * Returns: 1470 * BCM_E_XXX 1471 */ 1472 int 1473 _bcm_defip_pair128_idx_alloc(int unit, _bcm_defip_cfg_t *lpm_cfg, int *hw_index, 1474 int nh_ecmp_idx) 1475 { 1476 int lkup_plen; /* Vrf weighted lookup prefix. */ 1477 uint16 hash = 0; /* Entry hash value. */ 1478 int idx; /* Table iteration index. */ 1479 int rv; /* Operation return status. */ 1480 int shift_min = 0; /* Minimum entry shift required. */ 1481 int range_start = 0; /* First valid location for pfx. */ 1482 int range_end = BCM_DEFIP_PAIR128_IDX_MAX(unit); 1483 /* Last valid location for pfx. */ 1484 int free_idx_before = -1; /* Free index before range_start. */ 1485 int free_idx_after = -1; /* Free index after range_end. */ 1486 1487 /* Input parameters check. */ 1488 if ((lpm_cfg == NULL) || (hw_index == NULL)) { 1489 return (BCM_E_PARAM); 1490 } 1491 1492 /* Calculate vrf weighted prefix length. */ 1493 lkup_plen = _bcm_defip_lkup_plen_get(unit, lpm_cfg); 1494 1495 /* Calculate entry hash. */ 1496 BCM_IF_ERROR_RETURN(_bcm_defip_pair128_hash(unit, lpm_cfg, &hash)); 1497 1498 /* Make sure at least one slot is available. */ 1499 if (BCM_DEFIP_PAIR128_USED_COUNT(unit) == 1500 BCM_DEFIP_PAIR128_TOTAL(unit)) { 1501 return (BCM_E_FULL); 1502 } 1503 1504 /* 1505 * Find first valid index for the prefix; 1506 */ 1507 for (idx = 0; idx <= BCM_DEFIP_PAIR128_IDX_MAX(unit); idx++) { 1508 /* Remember free entry before installation location. */ 1509 if (0 == BCM_DEFIP_PAIR128_ARR(unit)[idx].prefix_len) { 1510 free_idx_before = idx; 1511 continue; 1512 } 1513 /* Route prefix length comparison. */ 1514 if (lkup_plen < BCM_DEFIP_PAIR128_ARR(unit)[idx].prefix_len) { 1515 range_start = idx; 1516 continue; 1517 } 1518 break; 1519 } 1520 1521 /* 1522 * Find last valid index for the prefix; 1523 */ 1524 for (idx = BCM_DEFIP_PAIR128_IDX_MAX(unit); idx >= 0; idx--) { 1525 1526 /* Remeber free entry after installation location. */ 1527 if (0 == BCM_DEFIP_PAIR128_ARR(unit)[idx].prefix_len) { 1528 free_idx_after = idx; 1529 continue; 1530 } 1531 /* Route prefix length comparison. */ 1532 if (lkup_plen > BCM_DEFIP_PAIR128_ARR(unit)[idx].prefix_len) { 1533 range_end = idx; 1534 continue; 1535 } 1536 break; 1537 } 1538 1539 /* Check if entry should be inserted at the end. */ 1540 if (range_start == BCM_DEFIP_PAIR128_IDX_MAX(unit)) { 1541 /* Shift all entries from free_idx_before till the end 1 up. */ 1542 rv = _bcm_defip_pair128_shift_range(unit, BCM_DEFIP_PAIR128_IDX_MAX(unit), free_idx_before); 1543 1544 if (BCM_SUCCESS(rv)) { 1545 /* Allocated index is last TCAM entry. */ 1546 *hw_index = BCM_DEFIP_PAIR128_IDX_MAX(unit); 1547 BCM_DEFIP_PAIR128_ENTRY_SET(unit, *hw_index, lkup_plen, hash); 1548 } 1549 return (rv); 1550 } 1551 1552 /* Check if entry should be inserted at the beginning. */ 1553 if (range_end < 0) { 1554 /* Shift all entries from 0 till free_idx_after 1 down. */ 1555 rv = _bcm_defip_pair128_shift_range(unit, 0, free_idx_after); 1556 1557 if (BCM_SUCCESS(rv)) { 1558 /* Allocated index is first TCAM entry. */ 1559 *hw_index = 0; 1560 BCM_DEFIP_PAIR128_ENTRY_SET(unit, 0, lkup_plen, hash); 1561 } 1562 return (rv); 1563 } 1564 1565 /* Find if there is any free index in range. */ 1566 for (idx = range_start; idx <= range_end; idx++) { 1567 if (0 == BCM_DEFIP_PAIR128_ARR(unit)[idx].prefix_len) { 1568 *hw_index = idx; 1569 BCM_DEFIP_PAIR128_ENTRY_SET(unit, idx, lkup_plen, hash); 1570 return (BCM_E_NONE); 1571 } 1572 } 1573 1574 /* Check if entry should be inserted at the end of range. */ 1575 if ((free_idx_after > range_end) && (free_idx_after != -1)) { 1576 shift_min = free_idx_after - range_end; 1577 } 1578 1579 /* Check if entry should be inserted in the beginning. */ 1580 if ((free_idx_before < range_start) && (free_idx_before != -1)) { 1581 if((shift_min > (range_start - free_idx_before)) || (free_idx_after == -1)) { 1582 shift_min = -1; 1583 } 1584 } 1585 1586 if (shift_min <= 0) { 1587 rv = _bcm_defip_pair128_shift_range(unit, range_start, free_idx_before); 1588 if (BCM_SUCCESS(rv)) { 1589 *hw_index= range_start; 1590 BCM_DEFIP_PAIR128_ENTRY_SET(unit, range_start, lkup_plen, hash); 1591 } 1592 } else { 1593 rv = _bcm_defip_pair128_shift_range(unit, range_end, free_idx_after); 1594 if (BCM_SUCCESS(rv)) { 1595 *hw_index = range_end; 1596 BCM_DEFIP_PAIR128_ENTRY_SET(unit, range_end, lkup_plen, hash); 1597 } 1598 } 1599 return (rv); 1600 } 1601 1602 /* 1603 * Function: 1604 * _bcm_l3_defip_pair128_get 1605 * Purpose: 1606 * Get an entry from L3_DEFIP_PAIR_128 table. 1607 * Parameters: 1608 * unit - (IN)SOC unit number. 1609 * lpm_cfg - (IN)Buffer to fill defip information. 1610 * nh_ecmp_idx - (IN)Next hop or ecmp group index 1611 * Returns: 1612 * BCM_E_XXX 1613 */ 1614 int 1615 _bcm_l3_defip_pair128_get(int unit, _bcm_defip_cfg_t *lpm_cfg, 1616 int *nh_ecmp_idx) 1617 { 1618 uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS];/* Hw entry buffer. */ 1619 bcm_ip6_t mask; /* Subnet mask. */ 1620 int clear_hit; /* Clear entry hit bit flag. */ 1621 int hw_index; /* Entry offset in the TCAM. */ 1622 int rv; /* Internal operation status.*/ 1623 soc_mem_t mem = L3_DEFIP_PAIR_128m; 1624 1625 /* Input parameters check. */ 1626 if (lpm_cfg == NULL) { 1627 return (BCM_E_PARAM); 1628 } 1629 1630 /* Check if clear hit bit required. */ 1631 clear_hit = lpm_cfg->defip_flags & BCM_L3_HIT_CLEAR; 1632 1633 /* Create mask from prefix length. */ 1634 bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len); 1635 1636 /* Apply mask on address. */ 1637 bcm_xgs3_l3_mask6_apply(mask, lpm_cfg->defip_ip6_addr); 1638 1639 /* Search for matching entry in the cam. */ 1640 rv = _bcm_defip_pair128_match(unit, lpm_cfg, hw_entry, &hw_index); 1641 BCM_IF_ERROR_RETURN(rv); 1642 1643 lpm_cfg->defip_index = hw_index; 1644 1645 /* Parse matched entry. */ 1646 rv = _bcm_defip_pair128_parse(unit, hw_entry, lpm_cfg, nh_ecmp_idx); 1647 BCM_IF_ERROR_RETURN(rv); 1648 1649 /* Clear the HIT bit */ 1650 if (clear_hit) { 1651 1652 #if defined(BCM_TOMAHAWK3_SUPPORT) 1653 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_PAIR_LEVEL1m)) { 1654 mem = L3_DEFIP_PAIR_LEVEL1m; 1655 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_LEVEL1m, hw_entry, LWR_HIT0f, 0); 1656 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_LEVEL1m, hw_entry, LWR_HIT1f, 0); 1657 } else 1658 #endif 1659 { 1660 if (SOC_MEM_OPT_FLD_VALID(unit, L3_DEFIP_PAIR_128m, HITf)) { 1661 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, HITf, 0); 1662 } 1663 1664 if (SOC_MEM_OPT_FLD_VALID(unit, L3_DEFIP_PAIR_128m, HIT0f)) { 1665 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, HIT0f, 0); 1666 } 1667 1668 if (SOC_MEM_OPT_FLD_VALID(unit, L3_DEFIP_PAIR_128m, HIT1f)) { 1669 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, HIT1f, 0); 1670 } 1671 } 1672 rv = BCM_XGS3_MEM_WRITE(unit, mem, hw_index, hw_entry); 1673 } 1674 1675 return (rv); 1676 } 1677 1678 /* 1679 * Function: 1680 * _bcm_l3_defip_pair128_add 1681 * Purpose: 1682 * Add an entry to internal L3_DEFIP_PAIR_128 table. 1683 * Parameters: 1684 * unit - (IN)SOC unit number. 1685 * lpm_cfg - (IN)Buffer to fill defip information. 1686 * nh_ecmp_idx - (IN)Next hop or ecmp group index. 1687 * Returns: 1688 * BCM_E_XXX 1689 */ 1690 int 1691 _bcm_l3_defip_pair128_add(int unit, _bcm_defip_cfg_t *lpm_cfg, 1692 int nh_ecmp_idx) 1693 { 1694 uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS]; /* New entry hw buffer. */ 1695 bcm_ip6_t mask; /* Subnet mask. */ 1696 int hw_index = 0; /* Entry offset in the TCAM. */ 1697 int rv = BCM_E_NONE; /* Operation return status. */ 1698 soc_mem_t mem = L3_DEFIP_PAIR_128m; 1699 1700 uint32 max_v6_entries = BCM_XGS3_L3_IP6_MAX_128B_ENTRIES(unit); 1701 uint32 used_cnt = BCM_DEFIP_PAIR128_USED_COUNT(unit); 1702 /* Input parameters check. */ 1703 if (lpm_cfg == NULL) { 1704 return (BCM_E_PARAM); 1705 } 1706 1707 if ((used_cnt >= max_v6_entries) && 1708 !(lpm_cfg->defip_flags & BCM_L3_REPLACE)) { 1709 return BCM_E_FULL; 1710 } 1711 1712 /* No support for routes matchin AFTER vrf specific. */ 1713 if (BCM_L3_VRF_GLOBAL == lpm_cfg->defip_vrf) { 1714 return (BCM_E_UNAVAIL); 1715 } 1716 1717 /* Zero buffers. */ 1718 sal_memset(hw_entry, 0, WORDS2BYTES(SOC_MAX_MEM_FIELD_WORDS)); 1719 1720 #ifdef BCM_TRIDENT3_SUPPORT 1721 if (soc_feature(unit, soc_feature_flex_flow) && 1722 lpm_cfg->defip_flow_handle != 0) { 1723 1724 BCM_IF_ERROR_RETURN( 1725 _bcm_l3_defip_pair128_flex_add(unit, lpm_cfg, nh_ecmp_idx, hw_entry)); 1726 return BCM_E_NONE; 1727 } 1728 #endif 1729 1730 /* Create mask from prefix length. */ 1731 bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len); 1732 1733 /* Apply mask on address. */ 1734 bcm_xgs3_l3_mask6_apply(mask, lpm_cfg->defip_ip6_addr); 1735 1736 /* Allocate a new index for inserted entry. */ 1737 if (BCM_XGS3_L3_INVALID_INDEX == lpm_cfg->defip_index) { 1738 rv = _bcm_defip_pair128_idx_alloc(unit, lpm_cfg, &hw_index, nh_ecmp_idx); 1739 BCM_IF_ERROR_RETURN(rv); 1740 } else { 1741 hw_index = lpm_cfg->defip_index; 1742 } 1743 1744 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_PAIR_128m)) { 1745 /* Set hit bit. */ 1746 if (lpm_cfg->defip_flags & BCM_L3_HIT) { 1747 if (SOC_MEM_OPT_FLD_VALID(unit, L3_DEFIP_PAIR_128m, HITf)) { 1748 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, HITf, 1); 1749 } 1750 if (SOC_MEM_OPT_FLD_VALID(unit, L3_DEFIP_PAIR_128m, HIT0f)) { 1751 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, HIT0f, 1); 1752 } 1753 if (SOC_MEM_OPT_FLD_VALID(unit, L3_DEFIP_PAIR_128m, HIT1f)) { 1754 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, HIT1f, 1); 1755 } 1756 } 1757 } 1758 1759 /* Set ip mask. */ 1760 _bcm_defip_pair128_ip6_mask_set(unit, mem, hw_entry, mask); 1761 1762 #if defined(BCM_TOMAHAWK3_SUPPORT) 1763 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_PAIR_LEVEL1m)) { 1764 uint32 ip6_field; 1765 uint32 _key_data[2] = {0,0}; 1766 uint32 fmte[4] = {0,0,0,0}; 1767 1768 mem = L3_DEFIP_PAIR_LEVEL1m; 1769 1770 if (lpm_cfg->defip_flags & BCM_L3_HIT) { 1771 if (SOC_TH3_MEM_OPT_FLD_VALID(unit, L3_DEFIP_PAIR_LEVEL1m, LWR_HIT0f)) { 1772 SOC_TH3_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_LEVEL1m, hw_entry, LWR_HIT0f, 1); 1773 } 1774 if (SOC_TH3_MEM_OPT_FLD_VALID(unit, L3_DEFIP_PAIR_LEVEL1m, LWR_HIT1f)) { 1775 SOC_TH3_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_LEVEL1m, hw_entry, LWR_HIT1f, 1); 1776 } 1777 } 1778 1779 /* Set valid bits. */ 1780 SOC_TH3_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_LEVEL1m, hw_entry, UPR_VALID1f, 1); 1781 SOC_TH3_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_LEVEL1m, hw_entry, UPR_VALID0f, 1); 1782 SOC_TH3_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_LEVEL1m, hw_entry, LWR_VALID1f, 1); 1783 SOC_TH3_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_LEVEL1m, hw_entry, LWR_VALID0f, 1); 1784 1785 ip6_field = ((lpm_cfg->defip_ip6_addr[12] << 24)| (lpm_cfg->defip_ip6_addr[13] << 16) | 1786 (lpm_cfg->defip_ip6_addr[14] << 8) | (lpm_cfg->defip_ip6_addr[15] << 0)); 1787 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf, ip6_field); 1788 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf, 0x3); 1789 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_TYPEf, 0x1); 1790 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, VRF_IDf, 1791 (BCM_L3_VRF_OVERRIDE != lpm_cfg->defip_vrf) ? lpm_cfg->defip_vrf:0); 1792 SOC_TH3_MEM_OPT_FLD_SET(unit, (uint32 *)hw_entry, LWR_KEY0f, _key_data); 1793 1794 _key_data[0] = _key_data[1] = 0; 1795 ip6_field = ((lpm_cfg->defip_ip6_addr[8] << 24)| (lpm_cfg->defip_ip6_addr[9] << 16) | 1796 (lpm_cfg->defip_ip6_addr[10] << 8) | (lpm_cfg->defip_ip6_addr[11] << 0)); 1797 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf, ip6_field); 1798 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf, 0x3); 1799 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_TYPEf, 0x1); 1800 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, VRF_IDf, 1801 (BCM_L3_VRF_OVERRIDE != lpm_cfg->defip_vrf) ? lpm_cfg->defip_vrf:0); 1802 SOC_TH3_MEM_OPT_FLD_SET(unit, (uint32 *)hw_entry, LWR_KEY1f, _key_data); 1803 1804 _key_data[0] = _key_data[1] = 0; 1805 ip6_field = ((lpm_cfg->defip_ip6_addr[4] << 24)| (lpm_cfg->defip_ip6_addr[5] << 16) | 1806 (lpm_cfg->defip_ip6_addr[6] << 8) | (lpm_cfg->defip_ip6_addr[7] << 0)); 1807 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf, ip6_field); 1808 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf, 0x3); 1809 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_TYPEf, 0x1); 1810 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, VRF_IDf, 1811 (BCM_L3_VRF_OVERRIDE != lpm_cfg->defip_vrf) ? lpm_cfg->defip_vrf:0); 1812 SOC_TH3_MEM_OPT_FLD_SET(unit, (uint32 *)hw_entry, UPR_KEY0f, _key_data); 1813 1814 _key_data[0] = _key_data[1] = 0; 1815 ip6_field = ((lpm_cfg->defip_ip6_addr[0] << 24)| (lpm_cfg->defip_ip6_addr[1] << 16) | 1816 (lpm_cfg->defip_ip6_addr[2] << 8) | (lpm_cfg->defip_ip6_addr[3] << 0)); 1817 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, IP_ADDRf, ip6_field); 1818 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_MODEf, 0x3); 1819 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, KEY_TYPEf, 0x1); 1820 soc_format_field32_set(unit, L3_DEFIP_TCAM_KEYfmt, _key_data, VRF_IDf, 1821 (BCM_L3_VRF_OVERRIDE != lpm_cfg->defip_vrf) ? lpm_cfg->defip_vrf:0); 1822 SOC_TH3_MEM_OPT_FLD_SET(unit, (uint32 *)hw_entry, UPR_KEY1f, _key_data); 1823 1824 sal_memset(fmte, 0, sizeof(fmte)); 1825 if (BCM_L3_VRF_GLOBAL == lpm_cfg->defip_vrf) { 1826 soc_format_field32_set(unit, FIXED_DATAfmt, fmte, 1827 SUB_DB_PRIORITYf, 2); 1828 } else if (BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) { 1829 soc_format_field32_set(unit, FIXED_DATAfmt, fmte, 1830 SUB_DB_PRIORITYf, 0); 1831 } else { 1832 soc_format_field32_set(unit, FIXED_DATAfmt, fmte, 1833 SUB_DB_PRIORITYf, 1); 1834 } 1835 soc_mem_field_set(unit, L3_DEFIP_PAIR_LEVEL1m, hw_entry, 1836 LWR_FIXED_DATA0f, fmte); 1837 1838 fmte[0] = fmte[1] = fmte[2] = fmte[3] = 0; 1839 if (lpm_cfg->defip_flags & BCM_L3_RPE) { 1840 soc_format_field32_set(unit, ASSOC_DATA_FULLfmt, fmte, RPEf, 1); 1841 } 1842 soc_format_field32_set(unit, ASSOC_DATA_FULLfmt, fmte, PRIf, lpm_cfg->defip_prio); 1843 soc_format_field32_set(unit, ASSOC_DATA_FULLfmt, fmte, CLASS_IDf, 1844 lpm_cfg->defip_lookup_class); 1845 if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) { 1846 soc_format_field32_set(unit, ASSOC_DATA_FULLfmt, fmte, DEST_TYPEf, 1); 1847 } else if (nh_ecmp_idx != BCM_XGS3_L3_INVALID_INDEX) { 1848 soc_format_field32_set(unit, ASSOC_DATA_FULLfmt, fmte, DEST_TYPEf, 0); 1849 } 1850 soc_format_field32_set(unit, ASSOC_DATA_FULLfmt, fmte, DESTINATIONf, nh_ecmp_idx); 1851 if (lpm_cfg->defip_flags & BCM_L3_RPE) { 1852 soc_format_field32_set(unit, ASSOC_DATA_FULLfmt, fmte, RPEf, 1); 1853 } 1854 if (lpm_cfg->defip_flags & BCM_L3_DST_DISCARD) { 1855 soc_format_field32_set(unit, ASSOC_DATA_FULLfmt, fmte, DST_DISCARDf, 1); 1856 } 1857 soc_format_field32_set(unit, ASSOC_DATA_FULLfmt, fmte, CLASS_IDf, lpm_cfg->defip_lookup_class); 1858 soc_format_field32_set(unit, ASSOC_DATA_FULLfmt, fmte, PRIf, lpm_cfg->defip_prio); 1859 SOC_TH3_MEM_OPT_FLD_SET(unit, (uint32 *)hw_entry, LWR_ASSOC_DATA0f, fmte); 1860 SOC_TH3_MEM_OPT_FLD_SET(unit, (uint32 *)hw_entry, LWR_ASSOC_DATA1f, fmte); 1861 fmte[0] = fmte[1] = fmte[2] = fmte[3] = 0; 1862 soc_format_field32_set(unit, ALPM1_DATAfmt, fmte, DIRECT_ROUTEf, 1); 1863 SOC_TH3_MEM_OPT_FLD_SET(unit, (uint32 *)hw_entry, LWR_ALPM1_DATA0f, fmte); 1864 } else 1865 #endif 1866 { 1867 /* Set priority override bit. */ 1868 if (lpm_cfg->defip_flags & BCM_L3_RPE) { 1869 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, RPEf, 1); 1870 } 1871 1872 /* Set classification group id. */ 1873 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, CLASS_IDf, 1874 lpm_cfg->defip_lookup_class); 1875 1876 /* Write priority field. */ 1877 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, PRIf, lpm_cfg->defip_prio); 1878 1879 1880 /* Fill next hop information. */ 1881 if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) { 1882 if (soc_feature(unit, soc_feature_generic_dest)) { 1883 soc_mem_field32_dest_set(unit, L3_DEFIP_PAIR_128m, hw_entry, 1884 DESTINATIONf, SOC_MEM_FIF_DEST_ECMP, nh_ecmp_idx); 1885 } else { 1886 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, 1887 ECMP_PTRf, nh_ecmp_idx); 1888 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, ECMPf, 1); 1889 } 1890 } else if (!(lpm_cfg->defip_flags & BCM_L3_IPMC)) { 1891 if (soc_feature(unit, soc_feature_generic_dest)) { 1892 soc_mem_field32_dest_set(unit, L3_DEFIP_PAIR_128m, hw_entry, 1893 DESTINATIONf, SOC_MEM_FIF_DEST_NEXTHOP, nh_ecmp_idx); 1894 } else { 1895 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, 1896 NEXT_HOP_INDEXf, nh_ecmp_idx); 1897 } 1898 } 1899 1900 /* Set destination discard flag. */ 1901 if (lpm_cfg->defip_flags & BCM_L3_DST_DISCARD) { 1902 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, DST_DISCARDf, 1); 1903 } 1904 1905 /* Set mode bits to indicate IP v6 128b pair mode */ 1906 if (soc_mem_field_valid(unit, L3_DEFIP_PAIR_128m, KEY_MODE0_UPRf)) { 1907 soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, hw_entry, KEY_MODE1_UPRf, 0x3); 1908 soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, hw_entry, KEY_MODE0_UPRf, 0x3); 1909 soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, hw_entry, KEY_MODE1_LWRf, 0x3); 1910 soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, hw_entry, KEY_MODE0_LWRf, 0x3); 1911 1912 soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, hw_entry, KEY_MODE_MASK1_UPRf, 0x3); 1913 soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, hw_entry, KEY_MODE_MASK0_UPRf, 0x3); 1914 soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, hw_entry, KEY_MODE_MASK1_LWRf, 0x3); 1915 soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, hw_entry, KEY_MODE_MASK0_LWRf, 0x3); 1916 } else { 1917 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, MODE1_UPRf, 0x3); 1918 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, MODE0_UPRf, 0x3); 1919 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, MODE1_LWRf, 0x3); 1920 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, MODE0_LWRf, 0x3); 1921 1922 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, MODE_MASK1_UPRf, 0x3); 1923 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, MODE_MASK0_UPRf, 0x3); 1924 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, MODE_MASK1_LWRf, 0x3); 1925 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, MODE_MASK0_LWRf, 0x3); 1926 } 1927 1928 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1929 if (soc_feature(unit, soc_feature_ipmc_defip) && 1930 (lpm_cfg->defip_flags & BCM_L3_IPMC)) { 1931 1932 if (soc_mem_field_valid(unit, L3_DEFIP_PAIR_128m, MULTICAST_ROUTEf)) { 1933 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, MULTICAST_ROUTEf, 1); 1934 } else if (soc_mem_field_valid(unit, L3_DEFIP_PAIR_128m, DATA_TYPEf)) { 1935 soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, hw_entry, DATA_TYPEf, 2); 1936 } 1937 1938 if (soc_feature(unit, soc_feature_generic_dest)) { 1939 if (lpm_cfg->defip_mc_group > 0) { 1940 soc_mem_field32_dest_set(unit, L3_DEFIP_PAIR_128m, hw_entry, 1941 DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, 1942 lpm_cfg->defip_mc_group); 1943 } 1944 } else { 1945 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, L3MC_INDEXf, lpm_cfg->defip_mc_group); 1946 } 1947 1948 /* 1949 * RP ID has be encoded to 14 bit value, Now it will fit in EXPECTED_L3_IIFf 1950 */ 1951 if (lpm_cfg->defip_l3a_rp != BCM_IPMC_RP_ID_INVALID) { 1952 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, EXPECTED_L3_IIFf, 1953 _BCM_DEFIP_IPMC_RP_SET(lpm_cfg->defip_l3a_rp)); 1954 1955 } else if ((lpm_cfg->defip_ipmc_flags & BCM_IPMC_POST_LOOKUP_RPF_CHECK) && 1956 (lpm_cfg->defip_expected_intf != 0)) { 1957 1958 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, EXPECTED_L3_IIFf, lpm_cfg->defip_expected_intf); 1959 1960 if (lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_DROP) { 1961 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf, 1); 1962 } 1963 if (lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_TOCPU) { 1964 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf, 1); 1965 } 1966 } 1967 } 1968 #endif 1969 1970 /* Set valid bits. */ 1971 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VALID1_UPRf, 1); 1972 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VALID0_UPRf, 1); 1973 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VALID1_LWRf, 1); 1974 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VALID0_LWRf, 1); 1975 1976 /* Set destination/source ip address. */ 1977 _bcm_defip_pair128_ip6_addr_set(unit, L3_DEFIP_PAIR_128m, hw_entry, lpm_cfg->defip_ip6_addr); 1978 1979 /* Set vrf id & vrf mask. */ 1980 if (BCM_L3_VRF_OVERRIDE != lpm_cfg->defip_vrf) { 1981 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_0_LWRf, lpm_cfg->defip_vrf); 1982 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_1_LWRf, lpm_cfg->defip_vrf); 1983 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_0_UPRf, lpm_cfg->defip_vrf); 1984 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_1_UPRf, lpm_cfg->defip_vrf); 1985 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_MASK0_LWRf, 1986 (1 << SOC_MEM_OPT_FLD_LENGTH(unit, L3_DEFIP_PAIR_128m, 1987 VRF_ID_MASK0_LWRf)) - 1); 1988 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_MASK1_LWRf, 1989 (1 << SOC_MEM_OPT_FLD_LENGTH(unit, L3_DEFIP_PAIR_128m, 1990 VRF_ID_MASK1_LWRf)) - 1); 1991 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_MASK0_UPRf, 1992 (1 << SOC_MEM_OPT_FLD_LENGTH(unit, L3_DEFIP_PAIR_128m, 1993 VRF_ID_MASK0_UPRf)) - 1); 1994 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_MASK1_LWRf, 1995 (1 << SOC_MEM_OPT_FLD_LENGTH(unit, L3_DEFIP_PAIR_128m, 1996 VRF_ID_MASK1_UPRf)) - 1); 1997 if (SOC_MEM_OPT_FLD_VALID(unit, L3_DEFIP_PAIR_128m, GLOBAL_ROUTEf)) { 1998 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, GLOBAL_ROUTEf, 0); 1999 } 2000 } else { 2001 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_0_LWRf, 0); 2002 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_1_LWRf, 0); 2003 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_0_UPRf, 0); 2004 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_1_UPRf, 0); 2005 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_MASK0_LWRf, 0); 2006 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_MASK1_LWRf, 0); 2007 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_MASK0_UPRf, 0); 2008 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, VRF_ID_MASK1_UPRf, 0); 2009 } 2010 2011 /* Configure entry for SIP lookup if URPF is enabled. This => SIP is default route.*/ 2012 /* If soc_feature_l3_defip_advanced_lookup is TRUE then 2013 * both DIP and SIP lookup is done using 1 L3_DEFIP entry. 2014 * L3_DEFIP table is not divided into 2 to support URPF (Ex: KT2). 2015 */ 2016 if (soc_feature(unit, soc_feature_l3_defip_advanced_lookup)) { 2017 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, DEFAULTROUTEf, 2018 (SOC_URPF_STATUS_GET(unit) ? 1 : 0)); 2019 2020 } 2021 } 2022 2023 /* Write buffer to hw. */ 2024 rv = BCM_XGS3_MEM_WRITE(unit, mem, hw_index, hw_entry); 2025 if (BCM_FAILURE(rv)) { 2026 BCM_DEFIP_PAIR128_ENTRY_SET(unit, hw_index, 0, 0); 2027 return (rv); 2028 } 2029 2030 /* Write source lookup portion of the entry. */ 2031 /* If soc_feature_l3_defip_advanced_lookup is TRUE then 2032 * both DIP and SIP lookup is done using 1 L3_DEFIP entry. 2033 * L3_DEFIP table is not divided into 2 to support URPF (Ex: KT2). 2034 */ 2035 if (SOC_URPF_STATUS_GET(unit) && 2036 !soc_feature(unit, soc_feature_l3_defip_advanced_lookup) && 2037 SOC_MEM_IS_VALID(unit, L3_DEFIP_PAIR_128m)) { 2038 SOC_MEM_OPT_FLD32_SET(unit, L3_DEFIP_PAIR_128m, hw_entry, SRC_DISCARDf, 0); 2039 if (SOC_IS_TRIDENT3(unit)) { 2040 soc_mem_field32_set(unit, L3_DEFIP_PAIR_128m, hw_entry, 2041 FLEX_CTR_BASE_COUNTER_IDXf, 0); 2042 } 2043 2044 rv = BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, 2045 (hw_index + BCM_DEFIP_PAIR128_URPF_OFFSET(unit)), hw_entry); 2046 if (BCM_FAILURE(rv)) { 2047 _bcm_defip_pair128_entry_clear(unit, hw_index); 2048 return (rv); 2049 } 2050 } 2051 2052 /* If new route added increment total number of routes. */ 2053 /* Lack of index indicates a new route. */ 2054 if (BCM_XGS3_L3_INVALID_INDEX == lpm_cfg->defip_index) { 2055 BCM_XGS3_L3_DEFIP_CNT_INC(unit, TRUE); 2056 BCM_DEFIP_PAIR128_USED_COUNT(unit)++; 2057 soc_lpm_stat_128b_count_update(unit, 1); 2058 } 2059 2060 return rv; 2061 2062 } 2063 2064 /* 2065 * Function: 2066 * _bcm_l3_defip_pair128_del 2067 * Purpose: 2068 * Delete an entry from L3_DEFIP_PAIR_128 table. 2069 * Parameters: 2070 * unit - (IN)SOC unit number. 2071 * lpm_cfg - (IN)Buffer to fill defip information. 2072 * Returns: 2073 * BCM_E_XXX 2074 */ 2075 int 2076 _bcm_l3_defip_pair128_del(int unit, _bcm_defip_cfg_t *lpm_cfg) 2077 { 2078 uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS];/* Hw entry buffer. */ 2079 uint32 temp_hw_entry[SOC_MAX_MEM_FIELD_WORDS];/* Hw entry buffer. */ 2080 bcm_ip6_t mask; /* Subnet mask. */ 2081 int hw_index; /* Entry offset in the TCAM. */ 2082 int rv; 2083 _bcm_defip_cfg_t temp_lpm; 2084 int temp_nh_ecmp_idx, idx; 2085 2086 /* Input parameters check. */ 2087 if (lpm_cfg == NULL) { 2088 return (BCM_E_PARAM); 2089 } 2090 2091 /* Create mask from prefix length. */ 2092 bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len); 2093 2094 /* Apply mask on address. */ 2095 bcm_xgs3_l3_mask6_apply(mask, lpm_cfg->defip_ip6_addr); 2096 /* Search for matching entry in theL3_DEFIP_PAIR_128 cam. */ 2097 rv = _bcm_defip_pair128_match(unit, lpm_cfg, hw_entry, &hw_index); 2098 if (BCM_FAILURE(rv)) { 2099 return (rv); 2100 } 2101 2102 /* Delete entry from hardware & software (L3_DEFIP_PAIR_128m). */ 2103 rv = _bcm_defip_pair128_entry_clear(unit, hw_index); 2104 if (BCM_SUCCESS(rv)) { 2105 BCM_XGS3_L3_DEFIP_CNT_DEC(unit, TRUE); 2106 BCM_DEFIP_PAIR128_USED_COUNT(unit)--; 2107 soc_lpm_stat_128b_count_update(unit, 0); 2108 /* Delete valid entry at highest index (or lowest LPM) in 2109 * L3_DEFIP_128m table if available 2110 * and add it to L3_DEFIP_PAIR_128m */ 2111 hw_index = BCM_DEFIP_PAIR128_IDX_MAX(unit); 2112 for (idx = BCM_DEFIP_PAIR128_IDX_MAX(unit); idx >=0; idx--) { 2113 if (0 == BCM_DEFIP_PAIR128_ARR(unit)[idx].prefix_len) { 2114 hw_index = idx - 1; 2115 continue; 2116 } 2117 break; 2118 } 2119 2120 rv = BCM_XGS3_MEM_READ(unit, L3_DEFIP_128m, hw_index, &temp_hw_entry); 2121 if (rv != BCM_E_NONE && rv != BCM_E_UNAVAIL) { 2122 return rv; 2123 } 2124 if (rv != BCM_E_UNAVAIL) { 2125 sal_memset(&temp_lpm, 0, sizeof(_bcm_defip_cfg_t)); 2126 /* Parse entry. */ 2127 rv = _bcm_defip_pair128_parse(unit, temp_hw_entry, 2128 &temp_lpm, &temp_nh_ecmp_idx); 2129 BCM_IF_ERROR_RETURN(rv); 2130 2131 /* Extract entry address vrf */ 2132 rv = _bcm_defip_pair128_get_key(unit, temp_hw_entry, &temp_lpm); 2133 BCM_IF_ERROR_RETURN(rv); 2134 2135 /* Add the copied entry to L3_DEFIP_PAIR_128 table */ 2136 temp_lpm.defip_index = BCM_XGS3_L3_INVALID_INDEX; 2137 rv = _bcm_l3_defip_pair128_add(unit, &temp_lpm, temp_nh_ecmp_idx); 2138 BCM_IF_ERROR_RETURN(rv); 2139 2140 2141 /* Delete entry from L3_DEFIP_128 table. */ 2142 temp_lpm.defip_index = hw_index; 2143 rv = BCM_E_UNAVAIL; 2144 rv = _bcm_l3_defip_pair128_del(unit, &temp_lpm); 2145 return rv; 2146 } 2147 return BCM_E_NONE; 2148 } 2149 return (rv); 2150 } 2151 2152 /* 2153 * Function: 2154 * _bcm_l3_defip_pair128_update_match 2155 * Purpose: 2156 * Update/Delete all entries in defip table matching a certain rule. 2157 * Parameters: 2158 * unit - (IN)SOC unit number. 2159 * trv_data - (IN)Delete pattern + compare,act,notify routines. 2160 * Returns: 2161 * BCM_E_XXX 2162 */ 2163 int 2164 _bcm_l3_defip_pair128_update_match(int unit, _bcm_l3_trvrs_data_t *trv_data) 2165 { 2166 int idx; /* Iteration index. */ 2167 int rv; /* Operation return status. */ 2168 int cmp_result; /* Test routine result. */ 2169 int nh_ecmp_idx; /* Next hop/Ecmp group index. */ 2170 uint32 *hw_entry; /* Hw entry buffer. */ 2171 char *lpm_tbl_ptr; /* Dma table pointer. */ 2172 int defip_pair128_tbl_size; /* Defip table size. */ 2173 _bcm_defip_cfg_t lpm_cfg; /* Buffer to fill route info. */ 2174 _bcm_trvs_range_t *range_info; 2175 int max_index,start_index = 0; /* START/MAX index to traverse on Entries. */ 2176 soc_mem_t mem = L3_DEFIP_PAIR_128m; 2177 int validf = 0; 2178 2179 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_PAIR_LEVEL1m)) { 2180 mem = L3_DEFIP_PAIR_LEVEL1m; 2181 } 2182 /* Table DMA the LPM table to software copy */ 2183 BCM_IF_ERROR_RETURN 2184 (bcm_xgs3_l3_tbl_dma(unit, mem, BCM_L3_MEM_ENT_SIZE(unit, mem), 2185 "lpm_tbl", &lpm_tbl_ptr, &defip_pair128_tbl_size)); 2186 2187 /* If soc_feature_l3_defip_advanced_lookup is TRUE then 2188 * both DIP and SIP lookup is done using 1 L3_DEFIP entry. 2189 * L3_DEFIP table is not divided into 2 to support URPF (Ex: KT2). 2190 */ 2191 if (SOC_URPF_STATUS_GET(unit) && 2192 !soc_feature(unit, soc_feature_l3_defip_advanced_lookup)) { 2193 defip_pair128_tbl_size >>= 1; 2194 BCM_DEFIP_PAIR128_URPF_OFFSET(unit) = defip_pair128_tbl_size; 2195 } 2196 2197 max_index = defip_pair128_tbl_size - 1; 2198 if (!(trv_data->flags & BCM_XGS3_L3_OP_DEL)) { 2199 range_info = trv_data->pattern; 2200 if ((range_info != NULL) && (defip_pair128_tbl_size > range_info->end)) { 2201 max_index = range_info->end; 2202 start_index = range_info->start; 2203 range_info->current_count = start_index; 2204 } 2205 } 2206 2207 for (idx = start_index ; idx <= max_index; idx++) { 2208 /* Calculate entry ofset. */ 2209 hw_entry = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 2210 lpm_tbl_ptr, idx); 2211 2212 #if defined(BCM_TOMAHAWK3_SUPPORT) 2213 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_PAIR_LEVEL1m)) { 2214 validf = SOC_TH3_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_LEVEL1m, hw_entry, LWR_VALID0f); 2215 } else 2216 #endif 2217 { 2218 validf = SOC_MEM_OPT_FLD32_GET(unit, L3_DEFIP_PAIR_128m, hw_entry, VALID0_LWRf); 2219 } 2220 2221 /* Make sure entry is valid. */ 2222 if (!validf) { 2223 continue; 2224 } 2225 2226 /* Zero destination buffer first. */ 2227 sal_memset(&lpm_cfg, 0, sizeof(_bcm_defip_cfg_t)); 2228 2229 /* Parse the entry. */ 2230 _bcm_defip_pair128_parse(unit, hw_entry, &lpm_cfg, &nh_ecmp_idx); 2231 lpm_cfg.defip_index = idx; 2232 2233 /* Fill entry ip address & subnet mask. */ 2234 _bcm_defip_pair128_get_key(unit, hw_entry, &lpm_cfg); 2235 2236 /* Execute operation routine if any. */ 2237 if (trv_data->op_cb) { 2238 rv = (*trv_data->op_cb) (unit, (void *)trv_data, 2239 (void *)&lpm_cfg, 2240 (void *)&nh_ecmp_idx, &cmp_result); 2241 if (BCM_FAILURE(rv)) { 2242 soc_cm_sfree(unit, lpm_tbl_ptr); 2243 return rv; 2244 } 2245 } 2246 #ifdef BCM_WARM_BOOT_SUPPORT 2247 if (SOC_WARM_BOOT(unit)) { 2248 rv = _bcm_defip_pair128_reinit(unit, idx, &lpm_cfg); 2249 if (BCM_FAILURE(rv)) { 2250 soc_cm_sfree(unit, lpm_tbl_ptr); 2251 return rv; 2252 } 2253 } 2254 #endif /* BCM_WARM_BOOT_SUPPORT */ 2255 } 2256 2257 #ifdef BCM_WARM_BOOT_SUPPORT 2258 if (SOC_WARM_BOOT(unit)) { 2259 SOC_IF_ERROR_RETURN(soc_fb_lpm_reinit_done(unit, 1)); 2260 } 2261 #endif /* BCM_WARM_BOOT_SUPPORT */ 2262 soc_cm_sfree(unit, lpm_tbl_ptr); 2263 return (BCM_E_NONE); 2264 } 2265 2266 /* Configure L3_DEFIP_KEY_SELr register */ 2267 int 2268 _bcm_l3_defip_key_sel_set(int unit, int urpf, int tcam_pair_count) 2269 { 2270 int i; 2271 soc_reg_t key_selr = L3_DEFIP_KEY_SELr; 2272 uint32 defip_key_sel_val = 0; 2273 soc_field_t key_sel_f[4] = { 2274 V6_KEY_SEL_CAM0_1f, 2275 V6_KEY_SEL_CAM2_3f, 2276 V6_KEY_SEL_CAM4_5f, 2277 V6_KEY_SEL_CAM6_7f 2278 }; 2279 /* Trident3 Style */ 2280 soc_field_t key_sel_f2[4] = { 2281 KEY_SEL_CAM0_1f, 2282 KEY_SEL_CAM2_3f, 2283 KEY_SEL_CAM4_5f, 2284 KEY_SEL_CAM6_7f 2285 }; 2286 2287 /* Key sel value 2288 * 2, 0x00b non-URPF + lpm-64b 2289 * 0, 0x01b non-URPF + lpm-128b 2290 * 3, 0x10b uRPF + lpm-64b 2291 * 1 0x11b uRPF + lpm-128b 2292 */ 2293 if (tcam_pair_count < 0 || tcam_pair_count > 4) { 2294 return BCM_E_NONE; 2295 } 2296 2297 if (soc_reg_field_valid(unit, key_selr, KEY_SEL_CAM0_1f)) { 2298 /* Trident3 Style */ 2299 if (urpf) { 2300 switch (tcam_pair_count) { 2301 case 0: 2302 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2303 key_sel_f2[0], 2); 2304 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2305 key_sel_f2[1], 2); 2306 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2307 key_sel_f2[2], 3); 2308 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2309 key_sel_f2[3], 3); 2310 break; 2311 case 1: 2312 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2313 key_sel_f2[0], 0); 2314 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2315 key_sel_f2[1], 2); 2316 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2317 key_sel_f2[2], 1); 2318 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2319 key_sel_f2[3], 3); 2320 break; 2321 case 2: 2322 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2323 key_sel_f2[0], 0); 2324 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2325 key_sel_f2[1], 2); 2326 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2327 key_sel_f2[2], 1); 2328 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2329 key_sel_f2[3], 3); 2330 break; 2331 case 3: 2332 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2333 key_sel_f2[0], 0); 2334 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2335 key_sel_f2[1], 0); 2336 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2337 key_sel_f2[2], 1); 2338 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2339 key_sel_f2[3], 1); 2340 break; 2341 case 4: 2342 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2343 key_sel_f2[0], 0); 2344 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2345 key_sel_f2[1], 0); 2346 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2347 key_sel_f2[2], 1); 2348 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2349 key_sel_f2[3], 1); 2350 break; 2351 /* coverity[dead_error_begin : FALSE] */ 2352 default: 2353 break; 2354 } 2355 } else { 2356 for (i = 0; i < (4 - tcam_pair_count); i++) { 2357 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2358 key_sel_f2[3 - i], 2); 2359 } 2360 } 2361 } else { 2362 for (i = 0; i < tcam_pair_count; i++) { 2363 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2364 key_sel_f[i], 0x1); 2365 } 2366 2367 if (urpf) { 2368 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2369 URPF_LOOKUP_CAM4f, 0x1); 2370 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2371 URPF_LOOKUP_CAM5f, 0x1); 2372 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2373 URPF_LOOKUP_CAM6f, 0x1); 2374 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2375 URPF_LOOKUP_CAM7f, 0x1); 2376 2377 if (tcam_pair_count == 1) { 2378 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2379 key_sel_f[2], 0x1); 2380 } else if (tcam_pair_count == 2) { 2381 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2382 key_sel_f[1], 0); 2383 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2384 key_sel_f[2], 0x1); 2385 } else if (tcam_pair_count == 3) { 2386 soc_reg_field_set(unit, key_selr, &defip_key_sel_val, 2387 key_sel_f[3], 0x1); 2388 } 2389 } 2390 } 2391 2392 BCM_IF_ERROR_RETURN(WRITE_L3_DEFIP_KEY_SELr(unit, defip_key_sel_val)); 2393 return BCM_E_NONE; 2394 } 2395 2396 /* 2397 * Function: 2398 * _bcm_l3_defip_init 2399 * Purpose: 2400 * Configure TD2 internal route table as per soc properties. 2401 * (tcam pairing for IPv4, 64/128 bit IPV6 prefixes) 2402 * Parameters: 2403 * unit - (IN)SOC unit number. 2404 * Returns: 2405 * BCM_E_XXX 2406 */ 2407 int 2408 _bcm_l3_defip_init(int unit) 2409 { 2410 int num_ipv6_128b_entries; 2411 int mem_v4, mem_v6, mem_v6_128; /* Route table memories */ 2412 int ipv6_64_depth = 0; 2413 int start_index = 0; 2414 int tcam_pair_count = 0; 2415 int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 2416 2417 num_ipv6_128b_entries = SOC_L3_DEFIP_MAX_128B_ENTRIES(unit); 2418 BCM_XGS3_L3_IP6_MAX_128B_ENTRIES(unit) = num_ipv6_128b_entries; 2419 #ifdef ALPM_ENABLE 2420 /* ALPM Mode */ 2421 if (soc_property_get(unit, spn_L3_ALPM_ENABLE, 0)) { 2422 int rv = BCM_E_NONE; 2423 if (soc_feature(unit, soc_feature_alpm)) { 2424 if (SOC_IS_TRIDENT2(unit) || SOC_IS_TRIDENT2PLUS(unit)) { 2425 rv = soc_alpm_init(unit); 2426 } 2427 #if defined(BCM_TOMAHAWK_SUPPORT) 2428 else if (soc_feature(unit, soc_feature_alpm2)) { 2429 rv = bcm_esw_alpm_init(unit); 2430 } 2431 #endif 2432 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 2433 else { 2434 rv = soc_th_alpm_init(unit); 2435 } 2436 #endif 2437 if (BCM_SUCCESS(rv)) { 2438 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2439 (BSL_META_U(unit, 2440 "ALPM mode initialized\n"))); 2441 } else { 2442 LOG_ERROR(BSL_LS_BCM_ALPM, 2443 (BSL_META_U(unit, 2444 "ALPM mode initialization failed, " 2445 "retVal = %d\n"), rv)); 2446 } 2447 return rv; 2448 } else { 2449 LOG_WARN(BSL_LS_BCM_ALPM, 2450 (BSL_META_U(unit, 2451 "ALPM feature is not available in this device.\n"))); 2452 } 2453 } 2454 #else /* ALPM_ENABLE */ 2455 if (soc_feature(unit, soc_feature_alpm) && 2456 soc_property_get(unit, spn_L3_ALPM_ENABLE, 0)) { 2457 LOG_WARN(BSL_LS_BCM_ALPM, 2458 (BSL_META_U(unit, 2459 "ALPM mode support is not compiled. Please, " 2460 "recompile the SDK with ALPM_ENABLE proprocessor variable " 2461 "defined\n"))); 2462 } 2463 #endif /* ALPM_ENABLE */ 2464 2465 SOC_IF_ERROR_RETURN(soc_fb_lpm_tcam_pair_count_get(unit, &tcam_pair_count)); 2466 2467 if (!SOC_IS_TOMAHAWK3(unit)) { 2468 BCM_IF_ERROR_RETURN(_bcm_l3_defip_key_sel_set(unit, 2469 SOC_URPF_STATUS_GET(unit), tcam_pair_count)); 2470 } 2471 if(!SOC_MEM_IS_VALID(unit, L3_DEFIPm)) { 2472 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) { 2473 ipv6_64_depth = soc_mem_index_count(unit, L3_DEFIP_LEVEL1m); 2474 } 2475 } else { 2476 ipv6_64_depth = soc_mem_index_count(unit, L3_DEFIPm); 2477 } 2478 2479 /* Get memory for IPv4 entries. */ 2480 BCM_IF_ERROR_RETURN(_bcm_l3_defip_mem_get(unit, 0, 0, &mem_v4)); 2481 2482 /* Initialize IPv4 entries lookup engine. */ 2483 BCM_IF_ERROR_RETURN(soc_fb_lpm_init(unit)); 2484 2485 /* Overriding defaults set during lpm init */ 2486 2487 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 2488 BCM_IF_ERROR_RETURN(soc_fb_lpm128_init(unit)); 2489 ipv6_64_depth -= (tcam_pair_count * tcam_depth * 2); 2490 start_index = (tcam_pair_count * tcam_depth * 2); 2491 } else { 2492 start_index = 0; 2493 } 2494 2495 SOC_LPM_STATE_START(unit, (MAX_PFX_INDEX(unit))) = start_index; 2496 SOC_LPM_STATE_END(unit, (MAX_PFX_INDEX(unit))) = start_index - 1; 2497 2498 SOC_LPM_STATE_FENT(unit, (MAX_PFX_INDEX(unit))) = ipv6_64_depth; 2499 BCM_IF_ERROR_RETURN(soc_fb_lpm_state_config(unit, ipv6_64_depth, 2500 start_index)); 2501 2502 /* Get memory for IPv6 entries. */ 2503 BCM_IF_ERROR_RETURN 2504 (_bcm_l3_defip_mem_get(unit, BCM_L3_IP6, 0, &mem_v6)); 2505 2506 /* Get memory for IPv6 entries with prefix length > 64. */ 2507 BCM_IF_ERROR_RETURN 2508 (_bcm_l3_defip_mem_get(unit, BCM_L3_IP6, 2509 BCM_XGS3_L3_IPV6_PREFIX_LEN, 2510 &mem_v6_128)); 2511 2512 /* Initialize IPv6 entries lookup engine. */ 2513 if (mem_v6 != mem_v6_128) { 2514 if (!soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 2515 BCM_IF_ERROR_RETURN(_bcm_defip_pair128_init(unit)); 2516 } 2517 } 2518 2519 return BCM_E_NONE; 2520 } 2521 2522 /* 2523 * Function: 2524 * _bcm_l3_defip_deinit 2525 * Purpose: 2526 * De-initialize route table for trident2 devices. 2527 * Parameters: 2528 * unit - (IN) SOC unit number. 2529 * Returns: 2530 * BCM_E_XXX 2531 */ 2532 int 2533 _bcm_l3_defip_deinit(int unit) 2534 { 2535 soc_mem_t mem_v4; /* IPv4 Route table memory. */ 2536 soc_mem_t mem_v6; /* IPv6 Route table memory. */ 2537 soc_mem_t mem_v6_128; /* IPv6 full prefix route table memory. */ 2538 2539 /* Get memory for IPv4 entries. */ 2540 BCM_IF_ERROR_RETURN(_bcm_l3_defip_mem_get(unit, 0, 0, &mem_v4)); 2541 2542 /* Initialize IPv4 entries lookup engine. */ 2543 BCM_IF_ERROR_RETURN(soc_fb_lpm_deinit(unit)); 2544 2545 /* Get memory for IPv6 entries. */ 2546 BCM_IF_ERROR_RETURN 2547 (_bcm_l3_defip_mem_get(unit, BCM_L3_IP6, 0, &mem_v6)); 2548 2549 /* Initialize IPv6 entries lookup engine. */ 2550 if (mem_v4 != mem_v6) { 2551 BCM_IF_ERROR_RETURN(soc_fb_lpm_deinit(unit)); 2552 } 2553 2554 /* Get memory for IPv6 entries with prefix length > 64. */ 2555 BCM_IF_ERROR_RETURN 2556 (_bcm_l3_defip_mem_get(unit, BCM_L3_IP6, 2557 BCM_XGS3_L3_IPV6_PREFIX_LEN, 2558 &mem_v6_128)); 2559 2560 /* Initialize IPv6 entries lookup engine. */ 2561 if (mem_v6 != mem_v6_128) { 2562 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 2563 BCM_IF_ERROR_RETURN(soc_fb_lpm128_deinit(unit)); 2564 } else { 2565 BCM_IF_ERROR_RETURN(_bcm_defip_pair128_deinit(unit)); 2566 } 2567 } 2568 2569 #ifdef ALPM_ENABLE 2570 /* Delete WAR entries before uRPF status change, or we may not 2571 * be able to delete the old WAR entries after status change, 2572 * because alpm_lpm_deinit is currently inside alpm_lpm_init which 2573 * will try to delete WAR uRPF entry which is not exist before uPRF 2574 * status change. 2575 */ 2576 (void) soc_alpm_ipmc_war(unit, FALSE); 2577 (void) soc_alpm_128_ipmc_war(unit, FALSE); 2578 #endif 2579 2580 return (BCM_E_NONE); 2581 } 2582 2583 STATIC int 2584 _bcm_l3_lpm_table_sizes_get(int unit, int *paired_table_size, 2585 int *defip_table_size) 2586 { 2587 return soc_fb_lpm_table_sizes_get(unit, paired_table_size, 2588 defip_table_size); 2589 } 2590 2591 int 2592 _bcm_l3_is_v4_64b_allowed_in_paired_tcam(int unit) 2593 { 2594 return soc_fb_lpm128_is_v4_64b_allowed_in_paired_tcam(unit); 2595 } 2596 2597 int 2598 _bcm_l3_scaled_lpm_get(int unit, _bcm_defip_cfg_t *lpm_cfg, int *nh_ecmp_idx) 2599 { 2600 int rv = BCM_E_NOT_FOUND; 2601 int defip_table_size = 0; 2602 int paired_table_size = 0; 2603 2604 if (!soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 2605 return BCM_E_UNAVAIL; 2606 } 2607 2608 BCM_IF_ERROR_RETURN(_bcm_l3_lpm_table_sizes_get(unit, &paired_table_size, 2609 &defip_table_size)); 2610 2611 if (paired_table_size == 0 && lpm_cfg->defip_sub_len > 64) { 2612 return BCM_E_NOT_FOUND; 2613 } 2614 2615 if ((paired_table_size != 0) && 2616 (lpm_cfg->defip_sub_len > 64 || defip_table_size == 0)) { 2617 return _bcm_fb_lpm128_get(unit, lpm_cfg, nh_ecmp_idx); 2618 } 2619 2620 rv = _bcm_fb_lpm_get(unit, lpm_cfg, nh_ecmp_idx); 2621 if ((rv == BCM_E_NOT_FOUND) && 2622 _bcm_l3_is_v4_64b_allowed_in_paired_tcam(unit)) { 2623 rv = _bcm_fb_lpm128_get(unit, lpm_cfg, nh_ecmp_idx); 2624 if (BCM_FAILURE(rv)) { 2625 lpm_cfg->defip_flags_high &= ~BCM_XGS3_L3_ENTRY_IN_DEFIP_PAIR; 2626 } 2627 } 2628 2629 return rv; 2630 } 2631 2632 /* 2633 * Function: 2634 * _bcm_l3_lpm_get 2635 * Purpose: 2636 * Get an entry from the route table. 2637 * Parameters: 2638 * unit - (IN)SOC unit number. 2639 * lpm_cfg - (IN)Buffer to fill defip information. 2640 * nh_ecmp_idx - (IN)Next hop or ecmp group index 2641 * Returns: 2642 * BCM_E_XXX 2643 */ 2644 int 2645 _bcm_l3_lpm_get(int unit, _bcm_defip_cfg_t *lpm_cfg, int *nh_ecmp_idx) 2646 { 2647 soc_mem_t mem = L3_DEFIPm; 2648 uint32 max_v6_entries = BCM_XGS3_L3_IP6_MAX_128B_ENTRIES(unit); 2649 2650 /* Input parameters check */ 2651 if (NULL == lpm_cfg) { 2652 return (BCM_E_PARAM); 2653 } 2654 #if defined(BCM_TRIDENT3_SUPPORT) 2655 if (SOC_IS_TRIDENT3X(unit) && soc_feature(unit, soc_feature_flex_flow) 2656 && (lpm_cfg->defip_flow_handle != 0)) { 2657 soc_mem_t view_id; 2658 soc_flow_db_mem_view_info_t vinfo; 2659 2660 BCM_IF_ERROR_RETURN( soc_flow_db_ffo_to_mem_view_id_get(unit, 2661 lpm_cfg->defip_flow_handle, 2662 lpm_cfg->defip_flow_option_handle, 2663 SOC_FLOW_DB_FUNC_L3_ROUTE_ID, 2664 (uint32 *)&view_id)); 2665 BCM_IF_ERROR_RETURN(soc_flow_db_mem_view_info_get(unit, view_id, &vinfo)); 2666 mem = vinfo.mem; 2667 } else 2668 #endif 2669 { 2670 BCM_IF_ERROR_RETURN(_bcm_l3_defip_mem_get(unit, lpm_cfg->defip_flags, 2671 lpm_cfg->defip_sub_len, &mem)); 2672 } 2673 2674 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 2675 return _bcm_l3_scaled_lpm_get(unit, lpm_cfg, nh_ecmp_idx); 2676 } 2677 2678 switch (mem) { 2679 case L3_DEFIP_PAIR_128m: 2680 case L3_DEFIP_PAIR_LEVEL1m: 2681 if (max_v6_entries > 0) { 2682 return _bcm_l3_defip_pair128_get(unit, lpm_cfg, nh_ecmp_idx); 2683 } 2684 break; 2685 default: 2686 if (soc_mem_index_count(unit, mem) > 0) { 2687 return _bcm_fb_lpm_get(unit, lpm_cfg, nh_ecmp_idx); 2688 } 2689 break; 2690 } 2691 2692 return (BCM_E_NOT_FOUND); 2693 } 2694 2695 void 2696 _bcm_defip_cfg_t_dump(_bcm_defip_cfg_t *lpm_cfg) 2697 { 2698 int i = 0; 2699 2700 if (lpm_cfg) { 2701 LOG_CLI((BSL_META("flags: 0x%x vrf: %d\n"), lpm_cfg->defip_flags, lpm_cfg->defip_vrf)); 2702 if (lpm_cfg->defip_flags & BCM_L3_IP6) { 2703 LOG_CLI((BSL_META("defip_ip6_addr - "))); 2704 for (i = 0; i < sizeof(bcm_ip6_t); i++) { 2705 LOG_CLI((BSL_META("0x%x:"), lpm_cfg->defip_ip6_addr[i])); 2706 } 2707 LOG_CLI((BSL_META("\n"))); 2708 } else { 2709 LOG_CLI((BSL_META("defip_ip_addr: 0x%x\n"), lpm_cfg->defip_ip_addr)); 2710 } 2711 LOG_CLI((BSL_META("defip_sub_len: %d defip_index: %d\n"), 2712 lpm_cfg->defip_sub_len, lpm_cfg->defip_index)); 2713 for(i = 0; i < sizeof(bcm_mac_t); i++) { 2714 LOG_CLI((BSL_META("defip_mac_addr - "))); 2715 LOG_CLI((BSL_META("0x%x:"), lpm_cfg->defip_mac_addr[i])); 2716 } 2717 2718 if (lpm_cfg->defip_flags & BCM_L3_IP6) { 2719 LOG_CLI((BSL_META("\ndefip_nexthop_ip6 - "))); 2720 for (i = 0; i < sizeof(bcm_ip6_t); i++) { 2721 LOG_CLI((BSL_META("0x%x:"), lpm_cfg->defip_nexthop_ip6[i])); 2722 } 2723 LOG_CLI((BSL_META("\n"))); 2724 } else { 2725 LOG_CLI((BSL_META("defip_nexthop_ip: 0x%x\n"), lpm_cfg->defip_nexthop_ip)); 2726 } 2727 2728 LOG_CLI((BSL_META("defip_tunnel: %d defip_prio: %d\n"), 2729 lpm_cfg->defip_tunnel, lpm_cfg->defip_prio)); 2730 2731 LOG_CLI((BSL_META("defip_intf: %d defip_port_tgid: %d\n"), 2732 lpm_cfg->defip_intf, lpm_cfg->defip_port_tgid)); 2733 2734 LOG_CLI((BSL_META("defip_stack_port: %d defip_modid: %d\n"), 2735 lpm_cfg->defip_stack_port, lpm_cfg->defip_modid)); 2736 2737 LOG_CLI((BSL_META("defip_vid: %d defip_ecmp: %d\n"), 2738 lpm_cfg->defip_vid, lpm_cfg->defip_ecmp)); 2739 2740 LOG_CLI((BSL_META("defip_ecmp_count: %d defip_ecmp_index: %d\n"), 2741 lpm_cfg->defip_ecmp_count, lpm_cfg->defip_ecmp_index)); 2742 2743 LOG_CLI((BSL_META("defip_l3hw_index: %d defip_tunnel_option: %d\n"), 2744 lpm_cfg->defip_l3hw_index, lpm_cfg->defip_tunnel_option)); 2745 2746 LOG_CLI((BSL_META("defip_mpls_label: %d defip_lookup_class: %d\n"), 2747 lpm_cfg->defip_mpls_label, lpm_cfg->defip_lookup_class)); 2748 } 2749 } 2750 2751 /* When a entry is delete in unpaired TCAM, then check if you can move 2752 * 64B V6 or V4 entries back to unpaired TCAM. This is required to keep 2753 * the entries in order 2754 */ 2755 int _bcm_l3_lpm128_ripple_entries(int unit) 2756 { 2757 _bcm_defip_cfg_t lpm_cfg_array[2]; 2758 int nh_ecmp_idx[2]; 2759 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 2760 uint32 eupr[SOC_MAX_MEM_FIELD_WORDS]; 2761 int index = 0; 2762 int pfx_len = 0; 2763 int count = 0; 2764 int ipv6 = 0; 2765 int rv = BCM_E_NONE; 2766 int idx = 0; 2767 soc_mem_t mem = L3_DEFIPm; 2768 2769 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) { 2770 mem = L3_DEFIP_LEVEL1m; 2771 } 2772 /* Do the following 2773 * 1. Find the smallest 64BV6 prefix 2774 * 2. if 64BV6 entry not found, find the smallest V4 prefix 2775 * 3. Try to add it to the unpaired tcam 2776 * 4. If adding to the unpaired tcam is successful, 2777 * then delete the entry from paired TCAM 2778 */ 2779 sal_memcpy(e, soc_mem_entry_null(unit, mem), 2780 soc_mem_entry_words(unit,mem) * 4); 2781 sal_memcpy(eupr, soc_mem_entry_null(unit, mem), 2782 soc_mem_entry_words(unit,mem) * 4); 2783 ipv6 = 1; 2784 rv = _bcm_fb_lpm128_get_smallest_movable_prefix(unit, ipv6, e, eupr, &index, 2785 &pfx_len, &count); 2786 if (BCM_FAILURE(rv)) { 2787 if (rv == BCM_E_NOT_FOUND) { 2788 ipv6 = 0; 2789 rv = _bcm_fb_lpm128_get_smallest_movable_prefix(unit, ipv6, e,eupr, 2790 &index, &pfx_len, 2791 &count); 2792 if (BCM_FAILURE(rv)) { 2793 return BCM_E_NONE; 2794 } 2795 } else { 2796 return rv; 2797 } 2798 } 2799 2800 if (ipv6) { 2801 BCM_IF_ERROR_RETURN(_bcm_fb_lpm128_defip_cfg_get(unit, e, eupr, 2802 lpm_cfg_array, 2803 nh_ecmp_idx)); 2804 } else { 2805 BCM_IF_ERROR_RETURN(_bcm_fb_lpm_defip_cfg_get(unit, ipv6, e, 2806 lpm_cfg_array, 2807 nh_ecmp_idx)); 2808 } 2809 for (idx = 0; idx < count; idx++) { 2810 #ifdef BCM_TOMAHAWK2_SUPPORT 2811 if (soc_feature(unit, soc_feature_half_of_l3_defip_ipv4_capacity) && 2812 !(idx & 1)) { 2813 continue; 2814 } 2815 #endif 2816 lpm_cfg_array[idx].defip_index = BCM_XGS3_L3_INVALID_INDEX; 2817 lpm_cfg_array[idx].defip_flags_high = 0; 2818 rv = _bcm_fb_lpm_add(unit, &lpm_cfg_array[idx], 2819 nh_ecmp_idx[idx]); 2820 if (BCM_FAILURE(rv)) { 2821 return BCM_E_NONE; 2822 } 2823 BCM_IF_ERROR_RETURN(_bcm_fb_lpm128_del(unit, &lpm_cfg_array[idx])); 2824 } 2825 2826 return BCM_E_NONE; 2827 } 2828 2829 int 2830 _bcm_l3_lpm_ripple_entries(int unit, _bcm_defip_cfg_t *lpm_cfg, 2831 int new_nh_ecmp_idx) 2832 { 2833 2834 _bcm_defip_cfg_t lpm_cfg_array[2]; 2835 int nh_ecmp_idx[2]; 2836 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 2837 int index = 0; 2838 int pfx_len = 0; 2839 int count = 0; 2840 int ipv6 = 0; 2841 int do_ripple = 0; 2842 int rv = BCM_E_NONE; 2843 int new_is_ipv6 = 0, move_is_ipv6 = 0; 2844 int new_is_ipmc = 0, move_is_ipmc = 0; 2845 int idx = 0; 2846 soc_mem_t mem = L3_DEFIPm; 2847 2848 #ifdef BCM_TOMAHAWK3_SUPPORT 2849 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) { 2850 mem = L3_DEFIP_LEVEL1m; 2851 } 2852 #endif 2853 2854 /* Do the following 2855 * 1. Find the largest V4 prefix 2856 * 2. if V4 entry not found, find the largest 64B V6 prefix 2857 * 3. Try to add it to the paired tcam 2858 * 4. If adding to the paired tcam is successful, 2859 * then delete the entry 2860 * 5. Add this entry again 2861 */ 2862 sal_memcpy(e, soc_mem_entry_null(unit, mem), 2863 soc_mem_entry_words(unit, mem) * 4); 2864 sal_memset(&lpm_cfg_array[0], 0x0, sizeof(_bcm_defip_cfg_t)); 2865 sal_memset(&lpm_cfg_array[1], 0x0, sizeof(_bcm_defip_cfg_t)); 2866 2867 ipv6 = 0; 2868 rv = _bcm_fb_get_largest_prefix(unit, ipv6, e, &index, 2869 &pfx_len, &count); 2870 if (BCM_FAILURE(rv)) { 2871 if (rv == BCM_E_NOT_FOUND) { 2872 ipv6 = 1; 2873 rv = _bcm_fb_get_largest_prefix(unit, ipv6, e, 2874 &index, 2875 &pfx_len, &count); 2876 if (BCM_FAILURE(rv)) { 2877 /* Failure here indicates something fatal */ 2878 return BCM_E_INTERNAL; 2879 } 2880 } else { 2881 return BCM_E_FULL; 2882 } 2883 } 2884 2885 /* 2886 * If atomic write is enabled, one free entry is reserved to move 2887 * the entries during entry update. 2888 * count == 0 means HW doesn't hold any entry however SW v4 or v6 2889 * prefix entries still holds a free entry after deleting all 2890 * the entries in unpaired tcam. 2891 */ 2892 if (soc_feature(unit, soc_feature_lpm_atomic_write) && (count == 0)) { 2893 return _bcm_fb_lpm128_add(unit, lpm_cfg, new_nh_ecmp_idx); 2894 } 2895 2896 BCM_IF_ERROR_RETURN(_bcm_fb_lpm_defip_cfg_get(unit, ipv6, e, lpm_cfg_array, 2897 nh_ecmp_idx)); 2898 new_is_ipv6 = !!(lpm_cfg->defip_flags & BCM_L3_IP6); 2899 move_is_ipv6 = !!(lpm_cfg_array[0].defip_flags & BCM_L3_IP6); 2900 /* 2901 * move | new 2902 *------------ 2903 * v6 | v6 length(move) > length(new) ripple 2904 * v4 | v4 length(move) > length(new) ripple 2905 * v4 | v6 ripple 2906 * v6 | v4 add to pair128 2907 */ 2908 if (soc_feature(unit, soc_feature_td3_lpm_ipmc_war)) { 2909 new_is_ipmc = !!(lpm_cfg->defip_flags & BCM_L3_IPMC); 2910 move_is_ipmc = !!(lpm_cfg_array[0].defip_flags & BCM_L3_IPMC); 2911 } 2912 2913 if (!new_is_ipv6 && move_is_ipv6) { 2914 do_ripple = 0; 2915 } else if ((new_is_ipv6 && !move_is_ipv6) || 2916 ((move_is_ipmc << 8 | lpm_cfg_array[0].defip_sub_len) > 2917 (new_is_ipmc << 8 | lpm_cfg->defip_sub_len))) { 2918 /* Ripple move to pair128 */ 2919 do_ripple = 1; 2920 } 2921 2922 if (do_ripple) { 2923 for (idx = 0; idx < count; idx++) { 2924 lpm_cfg_array[idx].defip_index = BCM_XGS3_L3_INVALID_INDEX; 2925 #ifdef BCM_TOMAHAWK2_SUPPORT 2926 if (soc_feature(unit, soc_feature_half_of_l3_defip_ipv4_capacity) && 2927 !(idx & 1)) { 2928 continue; 2929 } 2930 #endif 2931 rv = _bcm_fb_lpm128_add(unit, &lpm_cfg_array[idx], 2932 nh_ecmp_idx[idx]); 2933 lpm_cfg_array[idx].defip_flags_high = 0x0; 2934 if (BCM_FAILURE(rv)) { 2935 return rv; 2936 } 2937 BCM_IF_ERROR_RETURN(_bcm_fb_lpm_del(unit, &lpm_cfg_array[idx])); 2938 } 2939 return _bcm_fb_lpm_add(unit, lpm_cfg, new_nh_ecmp_idx); 2940 } else { 2941 /* Add new to pair128 */ 2942 return _bcm_fb_lpm128_add(unit, lpm_cfg, new_nh_ecmp_idx); 2943 } 2944 2945 return BCM_E_NONE; 2946 } 2947 2948 /* 2949 * Update the LPM entry for L3_DEFIP_DATA_ONLY view during Entry Modify. 2950 */ 2951 STATIC int 2952 _bcm_l3_scaled_lpm_data_modify(int unit, _bcm_defip_cfg_t *lpm_cfg, int nh_ecmp_idx) 2953 { 2954 uint32 lpm_hit[SOC_MAX_MEM_WORDS]; 2955 uint32 lpm_hit_copy[SOC_MAX_MEM_WORDS]; 2956 uint32 lpm_data[SOC_MAX_MEM_WORDS]; 2957 uint32 lpm_data_copy[SOC_MAX_MEM_WORDS]; 2958 uint32 defip_entry_lwr[SOC_MAX_MEM_WORDS]; 2959 uint32 defip_entry_upr[SOC_MAX_MEM_WORDS]; 2960 uint32 defip_entry[SOC_MAX_MEM_WORDS]; 2961 int defip_change = FALSE; 2962 int defip_index = lpm_cfg->defip_index; 2963 int defip_pair_index = -1; 2964 int ipv6 = (lpm_cfg->defip_flags & BCM_L3_IP6); 2965 int pfx_len = lpm_cfg->defip_sub_len; 2966 int rv = BCM_E_NONE; 2967 int mode; 2968 2969 2970 /* Set mode */ 2971 if (ipv6 == 0) { 2972 mode = 0; 2973 defip_index >>= 1; 2974 } else if (pfx_len > 64 || 2975 lpm_cfg->defip_flags_high & BCM_XGS3_L3_ENTRY_IN_DEFIP_PAIR) { 2976 mode = 3; 2977 } else { 2978 mode = 1; 2979 } 2980 2981 rv = READ_L3_DEFIP_DATA_ONLYm(unit, MEM_BLOCK_ANY, 2982 defip_index, (uint32 *)lpm_data_copy); 2983 if (BCM_FAILURE(rv)) { 2984 return rv; 2985 } 2986 rv = READ_L3_DEFIP_HIT_ONLYm(unit, MEM_BLOCK_ANY, 2987 defip_index, lpm_hit_copy); 2988 if (BCM_FAILURE(rv)) { 2989 return rv; 2990 } 2991 2992 sal_memcpy(lpm_data, lpm_data_copy, sizeof(lpm_data)); 2993 sal_memcpy(lpm_hit, lpm_hit_copy, sizeof(lpm_hit)); 2994 2995 if ((ipv6) || (lpm_cfg->defip_index & 1)) { 2996 rv = _bcm_fb_lpm_prepare_defip_data(unit, lpm_cfg, 2997 nh_ecmp_idx, 2998 (uint32 *)lpm_data, lpm_hit, 1); 2999 if (BCM_FAILURE(rv)) { 3000 return rv; 3001 } 3002 } 3003 3004 if ((ipv6) || !(lpm_cfg->defip_index & 1)) { 3005 rv = _bcm_fb_lpm_prepare_defip_data(unit, lpm_cfg, 3006 nh_ecmp_idx, 3007 (uint32 *)lpm_data, lpm_hit, 0); 3008 } 3009 3010 if (BCM_FAILURE(rv)) { 3011 return rv; 3012 } 3013 3014 3015 if (sal_memcmp(lpm_data_copy, lpm_data, sizeof(lpm_data))) { 3016 rv = WRITE_L3_DEFIP_DATA_ONLYm(unit, MEM_BLOCK_ANY, 3017 defip_index, lpm_data); 3018 if (BCM_FAILURE(rv)) { 3019 return rv; 3020 } 3021 /* In case of 128 bit entries */ 3022 if (mode == 3) { 3023 defip_pair_index = defip_index + SOC_CONTROL(unit)->l3_defip_tcam_size; 3024 rv = WRITE_L3_DEFIP_DATA_ONLYm(unit, MEM_BLOCK_ANY, 3025 defip_pair_index, lpm_data); 3026 if (BCM_FAILURE(rv)) { 3027 return rv; 3028 } 3029 } 3030 defip_change = TRUE; 3031 } 3032 3033 if (sal_memcmp(&lpm_hit_copy, lpm_hit, sizeof(lpm_hit))) { 3034 rv = WRITE_L3_DEFIP_HIT_ONLYm(unit, MEM_BLOCK_ANY, 3035 defip_index, &lpm_hit); 3036 if (BCM_FAILURE(rv)) { 3037 return rv; 3038 } 3039 /* In case of 128 bit entries */ 3040 if (mode == 3) { 3041 defip_pair_index = defip_index + SOC_CONTROL(unit)->l3_defip_tcam_size; 3042 rv = WRITE_L3_DEFIP_HIT_ONLYm(unit, MEM_BLOCK_ANY, 3043 defip_pair_index, &lpm_hit); 3044 if (BCM_FAILURE(rv)) { 3045 return rv; 3046 } 3047 } 3048 defip_change = TRUE; 3049 } 3050 3051 /* The cache of L3_DEFIP table should be updated if necessary */ 3052 if (defip_change && soc_mem_cache_get(unit, L3_DEFIPm, MEM_BLOCK_ALL)) { 3053 sal_memset(&defip_entry, 0x0, BCM_XGS3_L3_ENT_SZ(unit, defip)); 3054 rv = _soc_mem_alpm_read_cache(unit, L3_DEFIPm, MEM_BLOCK_ANY, 3055 defip_index, &defip_entry); 3056 if (SOC_SUCCESS(rv)) { 3057 sal_memset(&defip_entry_lwr, 0x0, BCM_XGS3_L3_ENT_SZ(unit, defip)); 3058 if (3 == mode) { 3059 sal_memset(&defip_entry_upr, 0x0, 3060 BCM_XGS3_L3_ENT_SZ(unit, defip)); 3061 (void) _bcm_fb_lpm_prepare_defip_entry( 3062 unit, lpm_cfg, nh_ecmp_idx, 3063 defip_entry_lwr, defip_entry_upr); 3064 3065 _soc_mem_alpm_write_cache(unit, L3_DEFIPm, MEM_BLOCK_ALL, 3066 defip_index, defip_entry_lwr); 3067 _soc_mem_alpm_write_cache(unit, L3_DEFIPm, MEM_BLOCK_ALL, 3068 defip_index + SOC_L3_DEFIP_TCAM_DEPTH_GET(unit), 3069 defip_entry_upr); 3070 } else { 3071 (void) _bcm_fb_lpm_prepare_defip_entry( 3072 unit, lpm_cfg, nh_ecmp_idx, 3073 defip_entry_lwr, NULL); 3074 if (!ipv6) { 3075 if (lpm_cfg->defip_index & 0x1) { 3076 (void) soc_fb_lpm_ip4entry0_to_1( 3077 unit, &defip_entry_lwr, 3078 defip_entry, PRESERVE_HIT); 3079 } else { 3080 (void) soc_fb_lpm_ip4entry0_to_0( 3081 unit, defip_entry_lwr, 3082 defip_entry, PRESERVE_HIT); 3083 } 3084 } 3085 _soc_mem_alpm_write_cache( 3086 unit, L3_DEFIPm, MEM_BLOCK_ALL, defip_index, 3087 ipv6 ? defip_entry_lwr : defip_entry); 3088 } 3089 } 3090 } 3091 3092 return BCM_E_NONE; 3093 } 3094 3095 /* 3096 * Update the LPM entry for L3_DEFIP_DATA_ONLY view during Entry Modify. 3097 */ 3098 STATIC int 3099 _bcm_l3_scaled_lpm_data_modify_urpf_entry_replicate(int unit, _bcm_defip_cfg_t *lpm_cfg, int nh_ecmp_idx) 3100 { 3101 int rv; /* Return type. */ 3102 int offset = 0; 3103 int defip_index = lpm_cfg->defip_index; 3104 3105 if(!SOC_URPF_STATUS_GET(unit)) { 3106 return (SOC_E_NONE); 3107 } 3108 3109 BCM_IF_ERROR_RETURN(soc_lpm_fb_urpf_entry_replicate_index_offset(unit, &offset)); 3110 3111 /* For non-ipv6 multiple by 2, since will be >> by 1 in 3112 * _bcm_l3_scaled_lpm_data_modify function */ 3113 if (!(lpm_cfg->defip_flags & BCM_L3_IP6)) { 3114 offset = offset << 1; 3115 } 3116 3117 /* Update with urpf entry defip index */ 3118 lpm_cfg->defip_index += offset; 3119 3120 /* Update urpf entry with new data */ 3121 rv = _bcm_l3_scaled_lpm_data_modify(unit, lpm_cfg, nh_ecmp_idx); 3122 3123 /* Restore original defip index */ 3124 lpm_cfg->defip_index = defip_index; 3125 3126 return rv; 3127 } 3128 3129 int 3130 _bcm_l3_scaled_lpm_add(int unit, _bcm_defip_cfg_t *lpm_cfg, int nh_ecmp_idx) 3131 { 3132 int rv = BCM_E_NONE; 3133 int defip_table_size = 0; 3134 int paired_table_size = 0; 3135 3136 if (!soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3137 return BCM_E_UNAVAIL; 3138 } 3139 3140 /* Input parameters check */ 3141 if (lpm_cfg == NULL) { 3142 return BCM_E_INTERNAL; 3143 } 3144 3145 /* Check if Entry is for modification */ 3146 /* Modify only the Data part for the given LPM entry index */ 3147 if ((lpm_cfg->defip_index >= 0) && !SOC_IS_TOMAHAWK3(unit)) { 3148 BCM_IF_ERROR_RETURN(_bcm_l3_scaled_lpm_data_modify(unit, lpm_cfg, nh_ecmp_idx)); 3149 /* Update Urpf entry when URPF is ON */ 3150 return _bcm_l3_scaled_lpm_data_modify_urpf_entry_replicate(unit, lpm_cfg, nh_ecmp_idx); 3151 } 3152 3153 BCM_IF_ERROR_RETURN(_bcm_l3_lpm_table_sizes_get(unit, &paired_table_size, 3154 &defip_table_size)); 3155 3156 if (paired_table_size == 0 && lpm_cfg->defip_sub_len > 64) { 3157 return BCM_E_FULL; 3158 } 3159 3160 if ((paired_table_size != 0 && lpm_cfg->defip_sub_len > 64) || 3161 (defip_table_size == 0)) { 3162 return _bcm_fb_lpm128_add(unit, lpm_cfg, nh_ecmp_idx); 3163 } 3164 3165 rv = _bcm_fb_lpm_add(unit, lpm_cfg, nh_ecmp_idx); 3166 if ((rv == BCM_E_FULL) && _bcm_l3_is_v4_64b_allowed_in_paired_tcam(unit)) { 3167 return _bcm_l3_lpm_ripple_entries(unit, lpm_cfg, 3168 nh_ecmp_idx); 3169 } 3170 return rv; 3171 } 3172 3173 /* 3174 * Function: 3175 * _bcm_l3_lpm_add 3176 * Purpose: 3177 * Add an entry to TD2 route table table. 3178 * Parameters: 3179 * unit - (IN)SOC unit number. 3180 * lpm_cfg - (IN)Buffer to fill defip information. 3181 frtu[]* nh_ecmp_idx - (IN)Next hop or ecmp group index. 3182 * Returns: 3183 * BCM_E_XXX 3184 */ 3185 int 3186 _bcm_l3_lpm_add(int unit, _bcm_defip_cfg_t *lpm_cfg, int nh_ecmp_idx) 3187 { 3188 int rv; 3189 soc_mem_t mem = L3_DEFIPm; 3190 3191 /* Input parameters check */ 3192 if (NULL == lpm_cfg) { 3193 return (BCM_E_PARAM); 3194 } 3195 #if defined(BCM_TRIDENT3_SUPPORT) 3196 if (SOC_IS_TRIDENT3X(unit) && soc_feature(unit, soc_feature_flex_flow) 3197 && (lpm_cfg->defip_flow_handle != 0)) { 3198 soc_mem_t view_id; 3199 soc_flow_db_mem_view_info_t vinfo; 3200 3201 BCM_IF_ERROR_RETURN( soc_flow_db_ffo_to_mem_view_id_get(unit, 3202 lpm_cfg->defip_flow_handle, 3203 lpm_cfg->defip_flow_option_handle, 3204 SOC_FLOW_DB_FUNC_L3_ROUTE_ID, 3205 (uint32 *)&view_id)); 3206 BCM_IF_ERROR_RETURN(soc_flow_db_mem_view_info_get(unit, view_id, &vinfo)); 3207 mem = vinfo.mem; 3208 } else 3209 #endif 3210 { 3211 BCM_IF_ERROR_RETURN(_bcm_l3_defip_mem_get(unit, lpm_cfg->defip_flags, 3212 lpm_cfg->defip_sub_len, &mem)); 3213 } 3214 3215 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3216 rv = _bcm_l3_scaled_lpm_add(unit, lpm_cfg, nh_ecmp_idx); 3217 #ifdef FB_LPM_DEBUG 3218 BCM_IF_ERROR_RETURN(lpm128_state_verify(unit)); 3219 #endif 3220 return rv; 3221 } 3222 3223 switch (mem) { 3224 case L3_DEFIP_PAIR_128m: 3225 case L3_DEFIP_PAIR_LEVEL1m: 3226 if (soc_mem_index_count(unit, mem) > 0) { 3227 return _bcm_l3_defip_pair128_add(unit, lpm_cfg, nh_ecmp_idx); 3228 } 3229 break; 3230 default: 3231 if (soc_mem_index_count(unit, mem) > 0) { 3232 return _bcm_fb_lpm_add(unit, lpm_cfg, nh_ecmp_idx); 3233 } 3234 break; 3235 } 3236 return (BCM_E_FULL); 3237 } 3238 3239 int 3240 _bcm_l3_scaled_lpm_del(int unit, _bcm_defip_cfg_t *lpm_cfg) 3241 { 3242 int rv = BCM_E_NONE; 3243 int defip_table_size = 0; 3244 int paired_table_size = 0; 3245 3246 if (!soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3247 return BCM_E_UNAVAIL; 3248 } 3249 3250 BCM_IF_ERROR_RETURN(_bcm_l3_lpm_table_sizes_get(unit, &paired_table_size, 3251 &defip_table_size)); 3252 3253 if ((paired_table_size != 0) && (lpm_cfg->defip_sub_len > 64 || 3254 (defip_table_size == 0) || 3255 lpm_cfg->defip_flags_high & BCM_XGS3_L3_ENTRY_IN_DEFIP_PAIR)) { 3256 return _bcm_fb_lpm128_del(unit, lpm_cfg); 3257 } 3258 3259 if (paired_table_size == 0 && lpm_cfg->defip_sub_len > 64) { 3260 return BCM_E_NOT_FOUND; 3261 } 3262 3263 lpm_cfg->defip_flags_high = 0; 3264 3265 rv = _bcm_fb_lpm_del(unit, lpm_cfg); 3266 if (BCM_SUCCESS(rv) && _bcm_l3_is_v4_64b_allowed_in_paired_tcam(unit)) { 3267 return _bcm_l3_lpm128_ripple_entries(unit); 3268 } 3269 return rv; 3270 } 3271 3272 /* 3273 * Function: 3274 * _bcm_l3_lpm_del 3275 * Purpose: 3276 * Delete an entry from the route table. 3277 * Parameters: 3278 * unit - (IN)SOC unit number. 3279 * lpm_cfg - (IN)Buffer to fill defip information. 3280 * Returns: 3281 * BCM_E_XXX 3282 */ 3283 int 3284 _bcm_l3_lpm_del(int unit, _bcm_defip_cfg_t *lpm_cfg) 3285 { 3286 soc_mem_t mem = L3_DEFIPm; 3287 uint32 max_v6_entries = BCM_XGS3_L3_IP6_MAX_128B_ENTRIES(unit); 3288 int rv = BCM_E_NONE; 3289 3290 /* Input parameters check */ 3291 if (NULL == lpm_cfg) { 3292 return (BCM_E_PARAM); 3293 } 3294 if (!SOC_MEM_IS_VALID(unit, L3_DEFIPm)) { 3295 mem = L3_DEFIP_LEVEL1m; 3296 } 3297 #if defined(BCM_TRIDENT3_SUPPORT) 3298 if (SOC_IS_TRIDENT3X(unit) && soc_feature(unit, soc_feature_flex_flow) 3299 && (lpm_cfg->defip_flow_handle != 0)) { 3300 soc_mem_t view_id; 3301 soc_flow_db_mem_view_info_t vinfo; 3302 3303 BCM_IF_ERROR_RETURN( soc_flow_db_ffo_to_mem_view_id_get(unit, 3304 lpm_cfg->defip_flow_handle, 3305 lpm_cfg->defip_flow_option_handle, 3306 SOC_FLOW_DB_FUNC_L3_ROUTE_ID, 3307 (uint32 *)&view_id)); 3308 BCM_IF_ERROR_RETURN(soc_flow_db_mem_view_info_get(unit, view_id, &vinfo)); 3309 mem = vinfo.mem; 3310 } else 3311 #endif 3312 { 3313 BCM_IF_ERROR_RETURN(_bcm_l3_defip_mem_get(unit, lpm_cfg->defip_flags, 3314 lpm_cfg->defip_sub_len, &mem)); 3315 } 3316 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3317 rv = _bcm_l3_scaled_lpm_del(unit, lpm_cfg); 3318 #ifdef FB_LPM_DEBUG 3319 BCM_IF_ERROR_RETURN(lpm128_state_verify(unit)); 3320 #endif 3321 return rv; 3322 } 3323 3324 switch (mem) { 3325 case L3_DEFIP_PAIR_128m: 3326 #ifdef BCM_TOMAHAWK3_SUPPORT 3327 case L3_DEFIP_PAIR_LEVEL1m: 3328 #endif 3329 if (max_v6_entries > 0) { 3330 return _bcm_l3_defip_pair128_del(unit, lpm_cfg); 3331 } 3332 break; 3333 default: 3334 if (soc_mem_index_count(unit, mem) > 0) { 3335 return _bcm_fb_lpm_del(unit, lpm_cfg); 3336 } 3337 break; 3338 } 3339 3340 return (rv); 3341 } 3342 3343 int _bcm_l3_scaled_lpm_update_match(int unit, _bcm_l3_trvrs_data_t *trv_data) 3344 { 3345 int rv1 = BCM_E_NONE; 3346 int rv2 = BCM_E_NONE; 3347 int defip_table_size = 0; 3348 int paired_table_size = 0; 3349 3350 if (!soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3351 return BCM_E_UNAVAIL; 3352 } 3353 3354 BCM_IF_ERROR_RETURN(_bcm_l3_lpm_table_sizes_get(unit, &paired_table_size, 3355 &defip_table_size)); 3356 3357 if (paired_table_size != 0) { 3358 rv1 = _bcm_fb_lpm128_update_match(unit, trv_data); 3359 } 3360 3361 if (defip_table_size != 0) { 3362 rv2 = _bcm_fb_lpm_update_match(unit, trv_data); 3363 } 3364 3365 BCM_IF_ERROR_RETURN(rv1); 3366 BCM_IF_ERROR_RETURN(rv2); 3367 3368 return (BCM_E_NONE); 3369 } 3370 3371 /* 3372 * Function: 3373 * _bcm_l3_lpm_update_match 3374 * Purpose: 3375 * Update/Delete all entries in defip table matching a certain rule. 3376 * Parameters: 3377 * unit - (IN)SOC unit number. 3378 * trv_data - (IN)Delete pattern + compare,act,notify routines. 3379 * Returns: 3380 * BCM_E_XXX 3381 */ 3382 int 3383 _bcm_l3_lpm_update_match(int unit, _bcm_l3_trvrs_data_t *trv_data) 3384 { 3385 int rv1 = BCM_E_NONE; 3386 int rv2 = BCM_E_NONE; 3387 uint32 max_v6_entries = BCM_XGS3_L3_IP6_MAX_128B_ENTRIES(unit); 3388 soc_mem_t mem = L3_DEFIPm; 3389 3390 if (!SOC_MEM_IS_VALID(unit, L3_DEFIPm)) { 3391 mem = L3_DEFIP_LEVEL1m; 3392 } 3393 3394 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3395 return _bcm_l3_scaled_lpm_update_match(unit, trv_data); 3396 } 3397 3398 if ((trv_data->flags & BCM_L3_IP6) && (max_v6_entries > 0)) { 3399 rv2 = _bcm_l3_defip_pair128_update_match(unit, trv_data); 3400 } 3401 3402 if (soc_mem_index_count(unit, mem) > 0) { 3403 rv1 = _bcm_fb_lpm_update_match(unit, trv_data); 3404 } 3405 BCM_IF_ERROR_RETURN(rv1); 3406 BCM_IF_ERROR_RETURN(rv2); 3407 3408 return (BCM_E_NONE); 3409 } 3410 3411 /* 3412 * Function: 3413 * _bcm_l3_defip_urpf_enable 3414 * Purpose: 3415 * Configure TD2 internal route table for URPF mode 3416 * Parameters: 3417 * unit - (IN)SOC unit number. 3418 * Returns: 3419 * BCM_E_XXX 3420 */ 3421 int 3422 _bcm_l3_defip_urpf_enable(int unit, int enable) 3423 { 3424 int ipv6_64_depth = 0; 3425 int ipv6_128_dip_offset = 0, ipv6_128_depth = 0; 3426 int num_ipv6_128b_entries; 3427 int tcam_pair_count = 0; 3428 int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 3429 int start_index = 0; 3430 #ifdef ALPM_ENABLE 3431 if (soc_feature(unit, soc_feature_alpm) && 3432 soc_property_get(unit, spn_L3_ALPM_ENABLE, 0)) { 3433 return SOC_E_NONE; 3434 } 3435 #endif 3436 num_ipv6_128b_entries = SOC_L3_DEFIP_MAX_128B_ENTRIES(unit); 3437 SOC_IF_ERROR_RETURN(soc_fb_lpm_tcam_pair_count_get(unit, &tcam_pair_count)); 3438 3439 if (enable) { 3440 /* All CAMs in URPF mode */ 3441 switch (tcam_pair_count) { 3442 case 0: 3443 /* No pairing of tcams */ 3444 ipv6_64_depth = 4 * tcam_depth; 3445 break; 3446 case 1: 3447 case 2: 3448 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3449 ipv6_64_depth = 2 * tcam_depth; 3450 } 3451 break; 3452 default: 3453 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3454 ipv6_64_depth = 0; 3455 } 3456 break; 3457 } 3458 3459 if (!soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3460 ipv6_128_dip_offset = num_ipv6_128b_entries / 2; 3461 ipv6_128_depth = num_ipv6_128b_entries / 2; 3462 ipv6_64_depth = soc_mem_index_count(unit, L3_DEFIPm) / 2; 3463 } 3464 } else { /* Disable case */ 3465 ipv6_64_depth = soc_mem_index_count(unit, L3_DEFIPm); 3466 ipv6_128_dip_offset = 0; 3467 ipv6_128_depth = num_ipv6_128b_entries; 3468 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3469 ipv6_64_depth -= (tcam_pair_count * tcam_depth * 2); 3470 } 3471 } 3472 3473 SOC_LPM_STATE_FENT(unit, (MAX_PFX_INDEX(unit))) = ipv6_64_depth; 3474 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3475 if (!enable) { 3476 start_index = (tcam_pair_count * tcam_depth * 2); 3477 } else { 3478 switch (tcam_pair_count) { 3479 case 1: 3480 case 2: 3481 start_index = 2 * tcam_depth; 3482 break; 3483 case 3: 3484 case 4: 3485 start_index = 4 * tcam_depth; 3486 break; 3487 default: 3488 start_index = 0; 3489 break; 3490 } 3491 } 3492 /* reinit the lpm128 logic to get the correct size for table */ 3493 SOC_IF_ERROR_RETURN(soc_fb_lpm_stat_init(unit)); 3494 SOC_IF_ERROR_RETURN(soc_fb_lpm128_deinit(unit)); 3495 SOC_IF_ERROR_RETURN(soc_fb_lpm128_init(unit)); 3496 } else { 3497 BCM_DEFIP_PAIR128_URPF_OFFSET(unit) = ipv6_128_dip_offset; 3498 BCM_DEFIP_PAIR128_IDX_MAX(unit) = ipv6_128_depth - 1; 3499 BCM_DEFIP_PAIR128_TOTAL(unit) = ipv6_128_depth; 3500 SOC_IF_ERROR_RETURN(soc_fb_lpm_stat_init(unit)); 3501 } 3502 SOC_LPM_STATE_START(unit, (MAX_PFX_INDEX(unit))) = start_index; 3503 SOC_LPM_STATE_END(unit, (MAX_PFX_INDEX(unit))) = start_index - 1; 3504 3505 BCM_IF_ERROR_RETURN(soc_fb_lpm_state_config(unit, ipv6_64_depth, 3506 start_index)); 3507 3508 BCM_IF_ERROR_RETURN( 3509 _bcm_l3_defip_key_sel_set(unit, enable, tcam_pair_count)); 3510 return BCM_E_NONE; 3511 } 3512 3513 #if defined(BCM_KATANA2_SUPPORT) 3514 3515 #define URPF_OFFSET 0 3516 /* 3517 * Function: 3518 * _bcm_kt2_l3_defip_mem_get 3519 * Purpose: 3520 * Resolve route table memory for a given route entry. 3521 * Parameters: 3522 * unit - (IN)SOC unit number. 3523 * flags - (IN)IPv6/IPv4 route. 3524 * plen - (IN)Prefix length. 3525 * mem - (OUT)Route table memory. 3526 * Returns: 3527 * BCM_E_XXX 3528 */ 3529 STATIC int 3530 _bcm_kt2_l3_defip_mem_get(int unit, uint32 flags, int plen, soc_mem_t *mem) 3531 { 3532 *mem = ((flags & BCM_L3_IP6) && (plen > 64)) ? 3533 L3_DEFIP_PAIR_128m : L3_DEFIPm ; 3534 3535 return BCM_E_NONE; 3536 } 3537 3538 /* 3539 * Function: 3540 * _bcm_kt2_defip_pair128_init 3541 * Purpose: 3542 * Initialize sw image for L3_DEFIP_PAIR_128 internal tcam. 3543 * Parameters: 3544 * unit - (IN)SOC unit number. 3545 * Returns: 3546 * BCM_E_XXX 3547 */ 3548 STATIC int 3549 _bcm_kt2_defip_pair128_init(int unit) 3550 { 3551 int rv; 3552 int mem_sz; 3553 int defip_config; 3554 int ipv6_128_depth; 3555 int ipv6_default_depth = 1024; 3556 3557 #ifdef BCM_METROLITE_SUPPORT 3558 if (SOC_IS_METROLITE(unit)) { 3559 ipv6_default_depth = 256; 3560 } 3561 #endif 3562 3563 /* De-allocate any existing structures. */ 3564 if (BCM_DEFIP_PAIR128(unit) != NULL) { 3565 BCM_IF_ERROR_RETURN(_bcm_defip_pair128_deinit(unit)); 3566 } 3567 3568 /* Allocate CAM control structure. */ 3569 mem_sz = sizeof(_bcm_defip_pair128_table_t); 3570 BCM_DEFIP_PAIR128(unit) = sal_alloc(mem_sz, "kt2_l3_defip_pair128"); 3571 if (BCM_DEFIP_PAIR128(unit) == NULL) { 3572 return (BCM_E_MEMORY); 3573 } 3574 3575 /* Reset CAM control structure. */ 3576 sal_memset(BCM_DEFIP_PAIR128(unit), 0, mem_sz); 3577 3578 defip_config = soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE,1); 3579 ipv6_128_depth = soc_property_get(unit, spn_NUM_IPV6_LPM_128B_ENTRIES, 3580 (defip_config ? ipv6_default_depth : 0)); 3581 3582 BCM_DEFIP_PAIR128_TOTAL(unit) = ipv6_128_depth; 3583 BCM_DEFIP_PAIR128_URPF_OFFSET(unit) = URPF_OFFSET; 3584 BCM_DEFIP_PAIR128_IDX_MAX(unit) = ipv6_128_depth - 1; 3585 BCM_XGS3_L3_IP6_MAX_128B_ENTRIES(unit) = ipv6_128_depth; 3586 if (ipv6_128_depth) { 3587 mem_sz = ipv6_128_depth * sizeof(_bcm_defip_pair128_entry_t); 3588 BCM_DEFIP_PAIR128_ARR(unit) = 3589 sal_alloc(mem_sz, "kt2_l3_defip_pair128_entry_array"); 3590 if (BCM_DEFIP_PAIR128_ARR(unit) == NULL) { 3591 BCM_IF_ERROR_RETURN(_bcm_defip_pair128_deinit(unit)); 3592 return (BCM_E_MEMORY); 3593 } 3594 sal_memset(BCM_DEFIP_PAIR128_ARR(unit), 0, mem_sz); 3595 } 3596 rv = _bcm_defip_pair128_field_cache_init(unit); 3597 if (BCM_FAILURE(rv)) { 3598 BCM_IF_ERROR_RETURN(_bcm_defip_pair128_deinit(unit)); 3599 return rv; 3600 } 3601 return (BCM_E_NONE); 3602 } 3603 3604 /* 3605 * Function: 3606 * _bcm_kt2_l3_defip_init 3607 * Purpose: 3608 * Configure KT2 internal route table as per soc properties. 3609 * (TCAM pairing for IPv4, 64/128 bit IPV6 prefixes) 3610 * Parameters: 3611 * unit - (IN)SOC unit number. 3612 * Returns: 3613 * BCM_E_XXX 3614 */ 3615 int 3616 _bcm_kt2_l3_defip_init(int unit) 3617 { 3618 int defip_config; 3619 uint32 defip_key_sel_val = 0; 3620 int mem_v4, mem_v6, mem_v6_128; /* Route table memories */ 3621 int ipv6_64_depth = 0; 3622 int num_ipv6_128b_entries; 3623 int start_index = 0; 3624 int tcam_pair_count = 0; 3625 int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 3626 3627 defip_config = soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 1); 3628 num_ipv6_128b_entries = 3629 soc_property_get(unit, spn_NUM_IPV6_LPM_128B_ENTRIES, 3630 (defip_config ?(SOC_IS_METROLITE(unit) ? 256:1024) : 0)); 3631 3632 if (num_ipv6_128b_entries) { 3633 tcam_pair_count = (num_ipv6_128b_entries / tcam_depth) + 3634 ((num_ipv6_128b_entries % tcam_depth) ? 1 : 0); 3635 } 3636 3637 BCM_XGS3_L3_IP6_MAX_128B_ENTRIES(unit) = 3638 SOC_L3_DEFIP_MAX_128B_ENTRIES(unit); 3639 3640 switch (tcam_pair_count) { 3641 case 8: 3642 soc_reg_field_set(unit, L3_DEFIP_KEY_SELr, &defip_key_sel_val, 3643 V6_KEY_SEL_CAM14_15f, 0x1); 3644 case 7: 3645 soc_reg_field_set(unit, L3_DEFIP_KEY_SELr, &defip_key_sel_val, 3646 V6_KEY_SEL_CAM12_13f, 0x1); 3647 case 6: 3648 soc_reg_field_set(unit, L3_DEFIP_KEY_SELr, &defip_key_sel_val, 3649 V6_KEY_SEL_CAM10_11f, 0x1); 3650 case 5: 3651 soc_reg_field_set(unit, L3_DEFIP_KEY_SELr, &defip_key_sel_val, 3652 V6_KEY_SEL_CAM8_9f, 0x1); 3653 case 4: 3654 soc_reg_field_set(unit, L3_DEFIP_KEY_SELr, &defip_key_sel_val, 3655 V6_KEY_SEL_CAM6_7f, 0x1); 3656 case 3: 3657 soc_reg_field_set(unit, L3_DEFIP_KEY_SELr, &defip_key_sel_val, 3658 V6_KEY_SEL_CAM4_5f, 0x1); 3659 case 2: 3660 soc_reg_field_set(unit, L3_DEFIP_KEY_SELr, &defip_key_sel_val, 3661 V6_KEY_SEL_CAM2_3f, 0x1); 3662 case 1: 3663 soc_reg_field_set(unit, L3_DEFIP_KEY_SELr, &defip_key_sel_val, 3664 V6_KEY_SEL_CAM0_1f, 0x1); 3665 break; 3666 default: 3667 break; 3668 } 3669 ipv6_64_depth = soc_mem_index_count(unit, L3_DEFIPm); 3670 3671 BCM_IF_ERROR_RETURN(WRITE_L3_DEFIP_KEY_SELr(unit, defip_key_sel_val)); 3672 3673 /* Get memory for IPv4 entries. */ 3674 BCM_IF_ERROR_RETURN(_bcm_kt2_l3_defip_mem_get(unit, 0, 0, &mem_v4)); 3675 3676 /* Initialize IPv4 entries lookup engine. */ 3677 BCM_IF_ERROR_RETURN(soc_fb_lpm_init(unit)); 3678 3679 /* Get memory for IPv6 entries. */ 3680 BCM_IF_ERROR_RETURN 3681 (_bcm_kt2_l3_defip_mem_get(unit, BCM_L3_IP6, 0, &mem_v6)); 3682 3683 /* Initialize IPv6 entries lookup engine. */ 3684 if (mem_v4 != mem_v6) { 3685 BCM_IF_ERROR_RETURN(soc_fb_lpm_init(unit)); 3686 } 3687 /* Overriding defaults set during lpm init */ 3688 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3689 BCM_IF_ERROR_RETURN(soc_fb_lpm128_init(unit)); 3690 ipv6_64_depth -= (tcam_pair_count * tcam_depth * 2); 3691 start_index = (tcam_pair_count * tcam_depth * 2); 3692 } else { 3693 start_index = 0; 3694 } 3695 3696 SOC_LPM_STATE_START(unit, (MAX_PFX_INDEX(unit))) = start_index; 3697 SOC_LPM_STATE_END(unit, (MAX_PFX_INDEX(unit))) = start_index - 1; 3698 SOC_LPM_STATE_FENT(unit, (MAX_PFX_INDEX(unit))) = ipv6_64_depth; 3699 BCM_IF_ERROR_RETURN(soc_fb_lpm_state_config(unit, ipv6_64_depth, 3700 start_index)); 3701 3702 /* Get memory for IPv6 entries with prefix length > 64. */ 3703 BCM_IF_ERROR_RETURN 3704 (_bcm_kt2_l3_defip_mem_get(unit, BCM_L3_IP6, 3705 BCM_XGS3_L3_IPV6_PREFIX_LEN, 3706 &mem_v6_128)); 3707 3708 /* Initialize IPv6 entries lookup engine. */ 3709 if (mem_v6 != mem_v6_128) { 3710 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3711 return soc_fb_lpm128_init(unit); 3712 } else { 3713 BCM_IF_ERROR_RETURN(_bcm_kt2_defip_pair128_init(unit)); 3714 } 3715 } 3716 3717 return BCM_E_NONE; 3718 } 3719 3720 /* 3721 * Function: 3722 * _bcm_kt2_l3_defip_deinit 3723 * Purpose: 3724 * De-initialize route table for katana2 devices. 3725 * Parameters: 3726 * unit - (IN) SOC unit number. 3727 * Returns: 3728 * BCM_E_XXX 3729 */ 3730 int 3731 _bcm_kt2_l3_defip_deinit(int unit) 3732 { 3733 soc_mem_t mem_v4; /* IPv4 Route table memory. */ 3734 soc_mem_t mem_v6; /* IPv6 Route table memory. */ 3735 soc_mem_t mem_v6_128; /* IPv6 full prefix route table memory. */ 3736 3737 /* Get memory for IPv4 entries. */ 3738 BCM_IF_ERROR_RETURN(_bcm_kt2_l3_defip_mem_get(unit, 0, 0, &mem_v4)); 3739 3740 /* Deinitialize IPv4 entries lookup engine. */ 3741 BCM_IF_ERROR_RETURN(soc_fb_lpm_deinit(unit)); 3742 3743 /* Get memory for IPv6 entries. */ 3744 BCM_IF_ERROR_RETURN 3745 (_bcm_kt2_l3_defip_mem_get(unit, BCM_L3_IP6, 0, &mem_v6)); 3746 3747 /* Deinitialize IPv6 entries lookup engine. */ 3748 if (mem_v4 != mem_v6) { 3749 BCM_IF_ERROR_RETURN(soc_fb_lpm_deinit(unit)); 3750 } 3751 3752 /* Get memory for IPv6 entries with prefix length > 64. */ 3753 BCM_IF_ERROR_RETURN 3754 (_bcm_kt2_l3_defip_mem_get(unit, BCM_L3_IP6, 3755 BCM_XGS3_L3_IPV6_PREFIX_LEN, 3756 &mem_v6_128)); 3757 3758 /* Deinitialize IPv6 entries lookup engine. */ 3759 if (mem_v6 != mem_v6_128) { 3760 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3761 BCM_IF_ERROR_RETURN(soc_fb_lpm128_deinit(unit)); 3762 } else { 3763 BCM_IF_ERROR_RETURN(_bcm_defip_pair128_deinit(unit)); 3764 } 3765 } 3766 return (BCM_E_NONE); 3767 3768 } 3769 3770 /* 3771 * Function: 3772 * _bcm_kt2_l3_lpm_get 3773 * Purpose: 3774 * Get an entry from the route table. 3775 * Parameters: 3776 * unit - (IN)SOC unit number. 3777 * lpm_cfg - (IN)Buffer to fill defip information. 3778 * nh_ecmp_idx - (IN)Next hop or ecmp group index 3779 * Returns: 3780 * BCM_E_XXX 3781 */ 3782 int 3783 _bcm_kt2_l3_lpm_get(int unit, _bcm_defip_cfg_t *lpm_cfg, int *nh_ecmp_idx) 3784 { 3785 soc_mem_t mem = L3_DEFIPm; 3786 uint32 max_v6_entries = BCM_XGS3_L3_IP6_MAX_128B_ENTRIES(unit); 3787 3788 /* Input parameters check */ 3789 if (NULL == lpm_cfg) { 3790 return (BCM_E_PARAM); 3791 } 3792 3793 BCM_IF_ERROR_RETURN(_bcm_kt2_l3_defip_mem_get(unit, lpm_cfg->defip_flags, 3794 lpm_cfg->defip_sub_len, &mem)); 3795 3796 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3797 if (mem == L3_DEFIPm || mem == L3_DEFIP_PAIR_128m) { 3798 return _bcm_l3_scaled_lpm_get(unit, lpm_cfg, nh_ecmp_idx); 3799 } 3800 } 3801 3802 switch (mem) { 3803 case L3_DEFIP_PAIR_128m: 3804 if (max_v6_entries > 0) { 3805 return _bcm_l3_defip_pair128_get(unit, lpm_cfg, nh_ecmp_idx); 3806 } 3807 break; 3808 default: 3809 if (soc_mem_index_count(unit, L3_DEFIPm) > 0) { 3810 return _bcm_fb_lpm_get(unit, lpm_cfg, nh_ecmp_idx); 3811 } 3812 break; 3813 } 3814 3815 return (BCM_E_NOT_FOUND); 3816 } 3817 3818 /* 3819 * Function: 3820 * _bcm_kt2_l3_lpm_add 3821 * Purpose: 3822 * Add an entry to KT2 route table table. 3823 * Parameters: 3824 * unit - (IN)SOC unit number. 3825 * lpm_cfg - (IN)Buffer to fill defip information. 3826 * nh_ecmp_idx - (IN)Next hop or ecmp group index. 3827 * Returns: 3828 * BCM_E_XXX 3829 */ 3830 int 3831 _bcm_kt2_l3_lpm_add(int unit, _bcm_defip_cfg_t *lpm_cfg, int nh_ecmp_idx) 3832 { 3833 soc_mem_t mem = L3_DEFIPm; 3834 3835 /* Input parameters check */ 3836 if (NULL == lpm_cfg) { 3837 return (BCM_E_PARAM); 3838 } 3839 3840 BCM_IF_ERROR_RETURN(_bcm_kt2_l3_defip_mem_get(unit, lpm_cfg->defip_flags, 3841 lpm_cfg->defip_sub_len, &mem)); 3842 3843 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3844 if (mem == L3_DEFIPm || mem == L3_DEFIP_PAIR_128m) { 3845 return _bcm_l3_scaled_lpm_add(unit, lpm_cfg, nh_ecmp_idx); 3846 } 3847 } 3848 3849 switch (mem) { 3850 case L3_DEFIP_PAIR_128m: 3851 if (soc_mem_index_count(unit, L3_DEFIP_PAIR_128m) > 0) { 3852 return _bcm_l3_defip_pair128_add(unit, lpm_cfg, nh_ecmp_idx); 3853 } 3854 break; 3855 default: 3856 if (soc_mem_index_count(unit, L3_DEFIPm) > 0) { 3857 return _bcm_fb_lpm_add(unit, lpm_cfg, nh_ecmp_idx); 3858 } 3859 break; 3860 } 3861 3862 return (BCM_E_FULL); 3863 } 3864 3865 /* 3866 * Function: 3867 * _bcm_kt2_l3_lpm_del 3868 * Purpose: 3869 * Delete an entry from the route table. 3870 * Parameters: 3871 * unit - (IN)SOC unit number. 3872 * lpm_cfg - (IN)Buffer to fill defip information. 3873 * Returns: 3874 * BCM_E_XXX 3875 */ 3876 int 3877 _bcm_kt2_l3_lpm_del(int unit, _bcm_defip_cfg_t *lpm_cfg) 3878 { 3879 soc_mem_t mem = L3_DEFIPm; 3880 uint32 max_v6_entries = BCM_XGS3_L3_IP6_MAX_128B_ENTRIES(unit); 3881 3882 /* Input parameters check */ 3883 if (NULL == lpm_cfg) { 3884 return (BCM_E_PARAM); 3885 } 3886 3887 BCM_IF_ERROR_RETURN(_bcm_kt2_l3_defip_mem_get(unit, lpm_cfg->defip_flags, 3888 lpm_cfg->defip_sub_len, &mem)); 3889 3890 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3891 if (mem == L3_DEFIPm || mem == L3_DEFIP_PAIR_128m) { 3892 return _bcm_l3_scaled_lpm_del(unit, lpm_cfg); 3893 } 3894 } 3895 3896 switch (mem) { 3897 case L3_DEFIP_PAIR_128m: 3898 if (max_v6_entries > 0) { 3899 return _bcm_l3_defip_pair128_del(unit, lpm_cfg); 3900 } 3901 break; 3902 default: 3903 if (soc_mem_index_count(unit, L3_DEFIPm) > 0) { 3904 return _bcm_fb_lpm_del(unit, lpm_cfg); 3905 } 3906 break; 3907 } 3908 3909 return (BCM_E_NOT_FOUND); 3910 } 3911 3912 /* 3913 * Function: 3914 * _bcm_kt2_l3_lpm_update_match 3915 * Purpose: 3916 * Update/Delete all entries in defip table matching a certain rule. 3917 * Parameters: 3918 * unit - (IN)SOC unit number. 3919 * trv_data - (IN)Delete pattern + compare,act,notify routines. 3920 * Returns: 3921 * BCM_E_XXX 3922 */ 3923 int 3924 _bcm_kt2_l3_lpm_update_match(int unit, _bcm_l3_trvrs_data_t *trv_data) 3925 { 3926 int rv1 = BCM_E_NONE; 3927 int rv2 = BCM_E_NONE; 3928 uint32 max_v6_entries = BCM_XGS3_L3_IP6_MAX_128B_ENTRIES(unit); 3929 3930 if (NULL == trv_data) { 3931 return (BCM_E_PARAM); 3932 } 3933 3934 if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) { 3935 return _bcm_l3_scaled_lpm_update_match(unit, trv_data); 3936 } 3937 3938 if ((trv_data->flags & BCM_L3_IP6) && (max_v6_entries > 0)) { 3939 rv2 = _bcm_l3_defip_pair128_update_match(unit, trv_data); 3940 } 3941 3942 if (soc_mem_index_count(unit, L3_DEFIPm) > 0) { 3943 rv1 = _bcm_fb_lpm_update_match(unit, trv_data); 3944 } 3945 BCM_IF_ERROR_RETURN(rv1); 3946 BCM_IF_ERROR_RETURN(rv2); 3947 3948 return (BCM_E_NONE); 3949 } 3950 #endif /* BCM_KATANA2_SUPPORT */ 3951 #endif /* INCLUDE_L3 */