lpm.c (59136B)
1 /* 2 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 3 * 4 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 5 * 6 * File: lpm.c 7 * Purpose: Trident3 L3 LPM specific functions 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <bcm/error.h> 13 #include <soc/defs.h> 14 #include <soc/drv.h> 15 16 #if defined(INCLUDE_L3) && defined(BCM_TRIDENT3_SUPPORT) 17 18 #include <bcm/l3.h> 19 #include <soc/lpm.h> 20 #include <soc/format.h> 21 #include <soc/esw/flow_db.h> 22 #include <bcm_int/esw/lpmv6.h> 23 #include <bcm_int/esw/trident3.h> 24 #include <bcm_int/esw/flow.h> 25 26 /* 27 * Function: 28 * _bcm_defip_pair128_flex_ip6_addr_set 29 * Purpose: 30 * Set IP6 address field in memory from ip6 addr type. 31 * Parameters: 32 * unit - (IN) BCM device number. 33 * mem - (IN) view id. 34 * entry - (IN) HW entry buffer. 35 * ip6 - (IN) SW ip6 address buffer. 36 * Returns: void 37 */ 38 STATIC void 39 _bcm_defip_pair128_flex_ip6_addr_set(int unit, soc_mem_t view_id, uint32 *entry, 40 const ip6_addr_t ip6) 41 { 42 uint32 ip6_field[4]; 43 44 if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__DIPf)) { 45 soc_mem_ip6_addr_set(unit, view_id, entry,IPV6__DIPf, ip6, 0); 46 } else if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__SIPf)) { 47 soc_mem_ip6_addr_set(unit, view_id, entry,IPV6__SIPf, ip6, 0); 48 } else { 49 ip6_field[3] = ((ip6[12] << 24)| (ip6[13] << 16) | 50 (ip6[14] << 8) | (ip6[15] << 0)); 51 soc_mem_field32_set(unit, view_id, entry, IP_ADDR0_LWRf, ip6_field[3]); 52 ip6_field[2] = ((ip6[8] << 24) | (ip6[9] << 16) | 53 (ip6[10] << 8) | (ip6[11] << 0)); 54 soc_mem_field32_set(unit, view_id, entry, IP_ADDR1_LWRf, ip6_field[2]); 55 ip6_field[1] = ((ip6[4] << 24) | (ip6[5] << 16) | 56 (ip6[6] << 8) | (ip6[7] << 0)); 57 soc_mem_field32_set(unit, view_id, entry, IP_ADDR0_UPRf, ip6_field[1]); 58 ip6_field[0] = ((ip6[0] << 24) | (ip6[1] << 16) | 59 (ip6[2] << 8) | (ip6[3] << 0)); 60 soc_mem_field32_set(unit, view_id, entry, IP_ADDR1_UPRf, ip6_field[0]); 61 } 62 } 63 64 /* 65 * Function: 66 * _bcm_defip_pair128_flex_ip6_mask_set 67 * Purpose: 68 * Set IP6 mask field in memory from ip6 addr type. 69 * Parameters: 70 * unit - (IN) BCM device number. 71 * mem - (IN) View id. 72 * entry - (IN) HW entry buffer. 73 * ip6 - (IN) SW ip6 address buffer. 74 * Returns: void 75 */ 76 STATIC void 77 _bcm_defip_pair128_flex_ip6_mask_set(int unit, soc_mem_t view_id, uint32 *entry, 78 const ip6_addr_t ip6) 79 { 80 uint32 ip6_field[4]; 81 82 if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__MASKf)) { 83 soc_mem_ip6_addr_set(unit, view_id, entry,IPV6__MASKf, ip6, 0); 84 } else { 85 ip6_field[3] = ((ip6[12] << 24)| (ip6[13] << 16) | 86 (ip6[14] << 8) | (ip6[15] << 0)); 87 soc_mem_field32_set(unit, view_id, entry, IP_ADDR_MASK0_LWRf, ip6_field[3]); 88 ip6_field[2] = ((ip6[8] << 24) | (ip6[9] << 16) | 89 (ip6[10] << 8) | (ip6[11] << 0)); 90 soc_mem_field32_set(unit, view_id, entry, IP_ADDR_MASK1_LWRf, ip6_field[2]); 91 ip6_field[1] = ((ip6[4] << 24) | (ip6[5] << 16) | 92 (ip6[6] << 8) | (ip6[7] << 0)); 93 soc_mem_field32_set(unit, view_id, entry, IP_ADDR_MASK0_UPRf, ip6_field[1]); 94 ip6_field[0] = ((ip6[0] << 24) | (ip6[1] << 16) | 95 (ip6[2] << 8) | (ip6[3] << 0)); 96 soc_mem_field32_set(unit, view_id, entry, IP_ADDR_MASK1_UPRf, ip6_field[0]); 97 } 98 } 99 /* 100 * Function: 101 * _bcm_defip_pair128_flex_entry_clear 102 * Purpose: 103 * Clear/Reset a single flex route entry. 104 * Parameters: 105 * unit - (IN)SOC unit number. 106 * view_id - (IN)View ID number. 107 * hw_index - (IN)Entry index in the tcam. 108 * Returns: 109 * BCM_E_XXX 110 */ 111 STATIC int 112 _bcm_defip_pair128_flex_entry_clear(int unit, soc_mem_t view_id, int hw_index) 113 { 114 uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS]; 115 soc_field_t key_field[4], mask_field[4]; 116 int field_count, i; 117 uint64 val64; 118 key_field[0] = KEY0_UPRf; 119 key_field[1] = KEY1_UPRf; 120 key_field[2] = KEY0_LWRf; 121 key_field[3] = KEY1_LWRf; 122 mask_field[0] = MASK0_UPRf; 123 mask_field[1] = MASK1_UPRf; 124 mask_field[2] = MASK0_LWRf; 125 mask_field[3] = MASK1_LWRf; 126 field_count = 4; 127 sal_memset(hw_entry, 0, WORDS2BYTES(SOC_MAX_MEM_FIELD_WORDS)); 128 COMPILER_64_ZERO(val64); 129 for (i = 0; i < field_count; i++) { 130 if (SOC_MEM_FIELD_VALID(unit, view_id, key_field[i])) { 131 soc_mem_field64_set(unit, view_id, hw_entry, key_field[i], val64); 132 } 133 if (SOC_MEM_FIELD_VALID(unit, view_id, mask_field[i])) { 134 soc_mem_field64_set(unit, view_id, hw_entry, mask_field[i], val64); 135 } 136 } 137 138 /* Reset hw entry. */ 139 BCM_IF_ERROR_RETURN 140 (BCM_XGS3_MEM_WRITE(unit, view_id, hw_index, 141 &soc_mem_entry_null(unit, view_id))); 142 BCM_IF_ERROR_RETURN 143 (BCM_XGS3_MEM_WRITE(unit, view_id, hw_index, hw_entry)); 144 145 /* Reset sw entry. */ 146 BCM_DEFIP_PAIR128_ENTRY_SET(unit, hw_index, 0, 0); 147 148 /* Reset urpf source lookup entry. */ 149 /* If soc_feature_l3_defip_advanced_lookup is TRUE then 150 * both DIP and SIP lookup is done using 1 L3_DEFIP entry. 151 * L3_DEFIP table is not divided into 2 to support URPF (Ex: KT2). 152 */ 153 if (SOC_URPF_STATUS_GET(unit) && 154 !soc_feature(unit, soc_feature_l3_defip_advanced_lookup)) { 155 BCM_IF_ERROR_RETURN 156 (BCM_XGS3_MEM_WRITE(unit, view_id, 157 (hw_index + BCM_DEFIP_PAIR128_URPF_OFFSET(unit)), 158 &soc_mem_entry_null(unit, view_id))); 159 BCM_IF_ERROR_RETURN 160 (BCM_XGS3_MEM_WRITE(unit, view_id, 161 (hw_index+ BCM_DEFIP_PAIR128_URPF_OFFSET(unit)), hw_entry)); 162 } 163 return (BCM_E_NONE); 164 } 165 /* 166 * Function: 167 * _bcm_l3_defip_pair128_flex_add 168 * Purpose: 169 * Add an flex entry to internal L3_DEFIP_PAIR_128 table. 170 * Parameters: 171 * unit - (IN)SOC unit number. 172 * lpm_cfg - (IN)defip information. 173 * view_id - (IN)View ID number. 174 * hw_entry - (IN)Buffer to fill defip information. 175 * nh_ecmp_idx - (IN)Next hop or ecmp group index. 176 * Returns: 177 * BCM_E_XXX 178 */ 179 int 180 _bcm_l3_defip_pair128_flex_add(int unit, _bcm_defip_cfg_t *lpm_cfg, 181 int nh_ecmp_idx, uint32 *hw_entry) 182 { 183 bcm_ip6_t mask; /* Subnet mask. */ 184 int hw_index = 0; /* Entry offset in the TCAM. */ 185 int rv = BCM_E_NONE; /* Operation return status. */ 186 187 soc_mem_t view_id; 188 int i; 189 uint32 field_array[128]; 190 uint32 field_count; 191 uint32 opaque_array[16]; 192 uint32 opaque_count; 193 bcm_flow_logical_field_t* user_fields; 194 195 uint32 action_set = 0; 196 197 uint8 process_destination = 0; 198 uint8 process_class_id = 0; 199 uint8 process_qos = 0; 200 uint8 process_pim_sm = 0; 201 uint8 process_fwd_attributes = 0; 202 uint8 process_fwd_3_attributes = 0; 203 soc_mem_t phy_mem; 204 205 /* Input parameters check. */ 206 if (lpm_cfg == NULL) { 207 return (BCM_E_PARAM); 208 } 209 210 /* Create mask from prefix length. */ 211 bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len); 212 213 /* Apply mask on address. */ 214 bcm_xgs3_l3_mask6_apply(mask, lpm_cfg->defip_ip6_addr); 215 216 /* Allocate a new index for inserted entry. */ 217 if (BCM_XGS3_L3_INVALID_INDEX == lpm_cfg->defip_index) { 218 rv = _bcm_defip_pair128_idx_alloc(unit, lpm_cfg, &hw_index, nh_ecmp_idx); 219 BCM_IF_ERROR_RETURN(rv); 220 } else { 221 hw_index = lpm_cfg->defip_index; 222 } 223 224 BCM_IF_ERROR_RETURN( 225 soc_flow_db_ffo_to_mem_view_id_get(unit, 226 lpm_cfg->defip_flow_handle, 227 lpm_cfg->defip_flow_option_handle, 228 SOC_FLOW_DB_FUNC_L3_ROUTE_ID, 229 (uint32 *)&view_id)); 230 231 /* Initialize control field list for this view id. */ 232 rv = soc_flow_db_mem_view_entry_init(unit, view_id, hw_entry); 233 234 BCM_IF_ERROR_RETURN(rv); 235 236 /* Get logical KEY field list for this view id. */ 237 rv = soc_flow_db_mem_view_field_list_get(unit, 238 view_id, 239 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY, 240 16, 241 opaque_array, 242 &opaque_count); 243 BCM_IF_ERROR_RETURN(rv); 244 245 user_fields = lpm_cfg->defip_logical_fields; 246 247 for (i=0; i<opaque_count; i++) { 248 if (user_fields[i].id == opaque_array[i]) { 249 soc_mem_field32_set(unit, view_id, hw_entry, user_fields[i].id, 250 user_fields[i].value); 251 } 252 } 253 254 /* Get logical PDD field list for this view id. */ 255 rv = soc_flow_db_mem_view_field_list_get(unit, 256 view_id, 257 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 258 16, 259 opaque_array, 260 &opaque_count); 261 262 BCM_IF_ERROR_RETURN(rv); 263 264 user_fields = lpm_cfg->defip_logical_fields; 265 266 for (i=0; i<opaque_count; i++) { 267 if (user_fields[i].id == opaque_array[i]) { 268 soc_mem_field32_set(unit, view_id, hw_entry, user_fields[i].id, 269 user_fields[i].value); 270 } 271 } 272 273 /* Get PDD field list corresponding to the view id. */ 274 rv = soc_flow_db_mem_view_field_list_get(unit, 275 view_id, 276 SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA, 277 128, 278 field_array, 279 &field_count); 280 BCM_IF_ERROR_RETURN(rv); 281 282 for (i=0; i<field_count; i++) { 283 switch (field_array[i]) { 284 case DESTINATION_ACTION_SETf: 285 process_destination = 1; 286 break; 287 case CLASS_ID_ACTION_SETf: 288 process_class_id = 1; 289 break; 290 case QOS_ACTION_SETf: 291 process_qos = 1; 292 break; 293 case FWD_ATTRIBUTES_ACTION_SETf: 294 process_fwd_attributes = 1; 295 break; 296 case FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf: 297 process_fwd_3_attributes = 1; 298 break; 299 case PIM_SM_ACTION_SETf: 300 process_pim_sm = 1; 301 break; 302 default: 303 return BCM_E_INTERNAL; 304 } 305 } 306 307 /* Set hit bit. */ 308 if (lpm_cfg->defip_flags & BCM_L3_HIT) { 309 if (SOC_MEM_FIELD_VALID(unit, view_id, HITf)) { 310 soc_mem_field32_set(unit, view_id, hw_entry, HITf, 1); 311 } 312 if (SOC_MEM_FIELD_VALID(unit, view_id, HIT0f)) { 313 soc_mem_field32_set(unit, view_id, hw_entry, HIT0f, 1); 314 } 315 if (SOC_MEM_FIELD_VALID(unit, view_id, HIT1f)) { 316 soc_mem_field32_set(unit, view_id, hw_entry, HIT1f, 1); 317 } 318 } 319 320 /* Set priority override bit. */ 321 action_set = 0; 322 323 if (lpm_cfg->defip_flags & BCM_L3_RPE) { 324 if (!process_qos) { 325 return BCM_E_UNAVAIL; 326 } 327 soc_format_field32_set(unit, QOS_ACTION_SETfmt, 328 &action_set, RPEf, 1); 329 } 330 if (process_qos) { 331 /* Write priority field. */ 332 soc_format_field32_set(unit, QOS_ACTION_SETfmt, 333 &action_set, PRIf, lpm_cfg->defip_prio); 334 335 soc_mem_field32_set(unit, view_id, hw_entry, 336 QOS_ACTION_SETf, action_set); 337 } 338 339 /* Set classification group id. */ 340 if (process_class_id) { 341 /* CLASS_IDf */ 342 soc_mem_field32_set(unit, view_id, hw_entry, CLASS_ID_ACTION_SETf, 343 lpm_cfg->defip_lookup_class); 344 } 345 346 /* Fill next hop information. */ 347 if (!process_destination) { 348 return BCM_E_INTERNAL; 349 } 350 351 action_set = 0; 352 if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) { 353 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 354 &action_set, DEST_TYPE1f, BCMI_TD3_DEST_TYPE1_ECMP); 355 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 356 &action_set, ECMP_GROUPf, nh_ecmp_idx); 357 } else { 358 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 359 &action_set, DEST_TYPE0f, BCMI_TD3_DEST_TYPE0_NH); 360 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 361 &action_set, NEXT_HOP_INDEXf, nh_ecmp_idx); 362 } 363 soc_mem_field32_set(unit, view_id, hw_entry, 364 DESTINATION_ACTION_SETf, action_set); 365 366 /* Set destination discard flag. */ 367 action_set = 0; 368 if (lpm_cfg->defip_flags & BCM_L3_DST_DISCARD) { 369 if (!process_fwd_attributes) { 370 return BCM_E_UNAVAIL; 371 } 372 soc_format_field32_set(unit, FWD_ATTRIBUTES_ACTION_SETfmt, 373 &action_set, DST_DISCARDf, 1); 374 soc_mem_field32_set(unit, view_id, hw_entry, 375 FWD_ATTRIBUTES_ACTION_SETf, action_set); 376 } 377 378 if (soc_feature(unit, soc_feature_ipmc_defip) && 379 (lpm_cfg->defip_flags & BCM_L3_IPMC)) { 380 381 /* L3MC_INDEXf */ 382 action_set = 0; 383 if (!process_pim_sm) { 384 return BCM_E_UNAVAIL; 385 } 386 387 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 388 &action_set, DEST_TYPE1f, BCMI_TD3_DEST_TYPE1_IPMC); 389 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 390 &action_set, IPMC_GROUPf, lpm_cfg->defip_mc_group); 391 soc_mem_field32_set(unit, view_id, hw_entry, 392 DESTINATION_ACTION_SETf, action_set); 393 394 /* 395 * RP ID has be encoded to 14 bit value, Now it will fit in EXPECTED_L3_IIFf 396 */ 397 action_set = 0; 398 if (lpm_cfg->defip_l3a_rp != BCM_IPMC_RP_ID_INVALID) { 399 soc_format_field32_set(unit, PIM_SM_ACTION_SETfmt, 400 &action_set, EXPECTED_L3_IIFf, 401 _BCM_DEFIP_IPMC_RP_SET(lpm_cfg->defip_l3a_rp)); 402 403 } else if ((lpm_cfg->defip_ipmc_flags & BCM_IPMC_POST_LOOKUP_RPF_CHECK) && 404 (lpm_cfg->defip_expected_intf != 0)) { 405 406 soc_format_field32_set(unit, PIM_SM_ACTION_SETfmt, 407 &action_set, EXPECTED_L3_IIFf, 408 lpm_cfg->defip_expected_intf); 409 410 if (lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_DROP) { 411 soc_format_field32_set(unit, PIM_SM_ACTION_SETfmt, 412 &action_set, IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf, 1); 413 } 414 if (lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_TOCPU) { 415 soc_format_field32_set(unit, PIM_SM_ACTION_SETfmt, 416 &action_set, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf, 1); 417 } 418 } 419 soc_mem_field32_set(unit, view_id, hw_entry, 420 PIM_SM_ACTION_SETf, action_set); 421 } 422 423 if ((!SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK0_LWRf) || 424 !SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK1_LWRf) || 425 !SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK0_UPRf) || 426 !SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK1_UPRf)) && 427 (!SOC_MEM_FIELD_VALID(unit, view_id, IPV6__MASKf))) { 428 return BCM_E_INTERNAL; 429 } 430 431 /* Set destination/source ip address. */ 432 _bcm_defip_pair128_flex_ip6_addr_set(unit, view_id, hw_entry, 433 lpm_cfg->defip_ip6_addr); 434 435 /* Set ip mask. */ 436 _bcm_defip_pair128_flex_ip6_mask_set(unit, view_id, hw_entry, mask); 437 438 /* Set vrf id & vrf mask. */ 439 action_set = 0; 440 if (BCM_L3_VRF_OVERRIDE != lpm_cfg->defip_vrf) { 441 if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_0f) || 442 SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_1f)) { 443 if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_0f)) { 444 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_0f, lpm_cfg->defip_vrf); 445 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK0f, 446 (1 << soc_mem_field_length(unit, view_id, 447 VRF_ID_MASK0f)) - 1); 448 } 449 if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_1f)) { 450 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_1f, lpm_cfg->defip_vrf); 451 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK1f, 452 (1 << soc_mem_field_length(unit, view_id, 453 VRF_ID_MASK1f)) - 1); 454 } 455 } else { 456 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_0_LWRf, lpm_cfg->defip_vrf); 457 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_1_LWRf, lpm_cfg->defip_vrf); 458 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_0_UPRf, lpm_cfg->defip_vrf); 459 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_1_UPRf, lpm_cfg->defip_vrf); 460 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK0_LWRf, 461 (1 << soc_mem_field_length(unit, view_id, 462 VRF_ID_MASK0_LWRf)) - 1); 463 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK1_LWRf, 464 (1 << soc_mem_field_length(unit, view_id, 465 VRF_ID_MASK1_LWRf)) - 1); 466 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK0_UPRf, 467 (1 << soc_mem_field_length(unit, view_id, 468 VRF_ID_MASK0_UPRf)) - 1); 469 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK1_LWRf, 470 (1 << soc_mem_field_length(unit, view_id, 471 VRF_ID_MASK1_UPRf)) - 1); 472 } 473 if (process_fwd_3_attributes) { 474 soc_format_field32_set(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt, 475 &action_set, GLOBAL_ROUTEf, 0); 476 soc_mem_field32_set(unit, view_id, hw_entry, 477 FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf, action_set); 478 } 479 } else { 480 if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_0f) || 481 SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_1f)) { 482 if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_0f)) { 483 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_0f, 0); 484 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK0f, 0); 485 } 486 if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_1f)) { 487 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_1f, 0); 488 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK1f, 0); 489 } 490 } else { 491 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_0_LWRf, 0); 492 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_1_LWRf, 0); 493 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_0_UPRf, 0); 494 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_1_UPRf, 0); 495 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK0_LWRf, 0); 496 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK1_LWRf, 0); 497 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK0_UPRf, 0); 498 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK1_UPRf, 0); 499 } 500 } 501 502 /* Configure entry for SIP lookup if URPF is enabled. This => SIP is default route.*/ 503 /* If soc_feature_l3_defip_advanced_lookup is TRUE then 504 * both DIP and SIP lookup is done using 1 L3_DEFIP entry. 505 * L3_DEFIP table is not divided into 2 to support URPF (Ex: KT2). 506 */ 507 action_set = 0; 508 if (soc_feature(unit, soc_feature_l3_defip_advanced_lookup) && 509 process_fwd_3_attributes) { 510 soc_format_field32_set(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt, 511 &action_set, DEFAULT_ROUTEf, 512 (SOC_URPF_STATUS_GET(unit) ? 1 : 0)); 513 soc_mem_field32_set(unit, view_id, hw_entry, 514 FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf, action_set); 515 } 516 517 SOC_IF_ERROR_RETURN(soc_mem_view_phy_mem_get(unit, view_id, &phy_mem)); 518 519 /* Write buffer to hw. */ 520 rv = BCM_XGS3_MEM_WRITE(unit, phy_mem, hw_index, hw_entry); 521 if (BCM_FAILURE(rv)) { 522 BCM_DEFIP_PAIR128_ENTRY_SET(unit, hw_index, 0, 0); 523 return (rv); 524 } 525 526 /* Write source lookup portion of the entry. */ 527 /* If soc_feature_l3_defip_advanced_lookup is TRUE then 528 * both DIP and SIP lookup is done using 1 L3_DEFIP entry. 529 * L3_DEFIP table is not divided into 2 to support URPF (Ex: KT2). 530 */ 531 action_set = 0; 532 if (SOC_URPF_STATUS_GET(unit) && 533 !soc_feature(unit, soc_feature_l3_defip_advanced_lookup)) { 534 if (!process_fwd_attributes) { 535 return BCM_E_PARAM; 536 } 537 soc_format_field32_set(unit, FWD_ATTRIBUTES_ACTION_SETfmt, 538 &action_set, SRC_DISCARDf, 0); 539 soc_mem_field32_set(unit, view_id, hw_entry, 540 FWD_ATTRIBUTES_ACTION_SETf, action_set); 541 rv = BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, 542 (hw_index + BCM_DEFIP_PAIR128_URPF_OFFSET(unit)), 543 hw_entry); 544 if (BCM_FAILURE(rv)) { 545 _bcm_defip_pair128_flex_entry_clear(unit, view_id, hw_index); 546 return (rv); 547 } 548 } 549 550 /* If new route added increment total number of routes. */ 551 /* Lack of index indicates a new route. */ 552 if (BCM_XGS3_L3_INVALID_INDEX == lpm_cfg->defip_index) { 553 BCM_XGS3_L3_DEFIP_CNT_INC(unit, TRUE); 554 BCM_DEFIP_PAIR128_USED_COUNT(unit)++; 555 soc_lpm_stat_128b_count_update(unit, 1); 556 } 557 558 return rv; 559 560 } 561 /* 562 * Function: 563 * _bcm_td3_flex_ip6_defip_lwr_set 564 * Purpose: 565 * Set an IP6 address field in L3_DEFIPm at index n 566 * Parameters: 567 * unit - (IN) SOC unit number; 568 * lpm_key - (OUT) Buffer to fill. 569 * lpm_cfg - (IN) Route information. 570 * view_id - (IN) Memory view id 571 * Note: 572 * See soc_mem_ip6_addr_set() 573 */ 574 STATIC void 575 _bcm_td3_flex_ip6_defip_lwr_set(int unit, void *lpm_key, _bcm_defip_cfg_t *lpm_cfg, soc_mem_t view_id) 576 { 577 uint8 *ip6; /* Ip6 address. */ 578 uint8 mask[BCM_IP6_ADDRLEN]; /* Subnet mask. */ 579 uint32 ip6_word; /* Temp storage. */ 580 int idx; 581 582 /* Just to keep variable name short. */ 583 ip6 = lpm_cfg->defip_ip6_addr; 584 585 /* Create mask from prefix length. */ 586 bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len); 587 588 /* Apply subnet mask */ 589 idx = lpm_cfg->defip_sub_len / 8; /* Unchanged byte count. */ 590 if (idx < BCM_IP6_ADDRLEN) { 591 ip6[idx] &= mask[idx]; /* Apply mask on next byte. */ 592 } 593 for (idx++; idx < BCM_IP6_ADDRLEN; idx++) { 594 ip6[idx] = 0; /* Reset rest of bytes. */ 595 } 596 597 ip6_word = ((ip6[8] << 24) | (ip6[9] << 16) | (ip6[10] << 8) | (ip6[11])); 598 soc_mem_field32_set(unit, view_id, lpm_key, IP_ADDR1f, ip6_word); 599 600 ip6_word = ((ip6[12] << 24) | (ip6[13] << 16) | (ip6[14] << 8) | (ip6[15])); 601 soc_mem_field32_set(unit, view_id, lpm_key, IP_ADDR0f, ip6_word); 602 603 ip6_word = ((mask[8] << 24) | (mask[9] << 16) | (mask[10] << 8) | 604 (mask[11])); 605 soc_mem_field32_set(unit, view_id, lpm_key, IP_ADDR_MASK1f, ip6_word); 606 607 ip6_word = ((mask[12] << 24) | (mask[13] << 16) | (mask[14] << 8) | 608 (mask[15])); 609 soc_mem_field32_set(unit, view_id, lpm_key, IP_ADDR_MASK0f, ip6_word); 610 } 611 /* 612 * Function: 613 * _bcm_td3_flex_ip6_defip_set 614 * Purpose: 615 * Set an IP6 address field in L3_DEFIPm 616 * Parameters: 617 * unit - (IN) SOC unit number; 618 * lpm_key - (OUT) Buffer to fill. 619 * lpm_cfg - (IN) Route information. 620 * view_id - (IN) Memory view id 621 * Note: 622 * See soc_mem_ip6_addr_set() 623 */ 624 STATIC void 625 _bcm_td3_flex_ip6_defip_set(int unit, void *lpm_key, _bcm_defip_cfg_t *lpm_cfg, soc_mem_t view_id) 626 { 627 uint8 *ip6; /* Ip6 address. */ 628 uint8 mask[BCM_IP6_ADDRLEN]; /* Subnet mask. */ 629 uint32 ip6_word; /* Temp storage. */ 630 int idx; /* Iteration index . */ 631 632 /* Just to keep variable name short. */ 633 ip6 = lpm_cfg->defip_ip6_addr; 634 635 /* Create mask from prefix length. */ 636 bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len); 637 638 /* Apply subnet mask */ 639 idx = lpm_cfg->defip_sub_len / 8; /* Unchanged byte count. */ 640 ip6[idx] &= mask[idx]; /* Apply mask on next byte. */ 641 for (idx++; idx < BCM_IP6_ADDRLEN; idx++) { 642 ip6[idx] = 0; /* Reset rest of bytes. */ 643 } 644 645 646 ip6_word = ((ip6[0] << 24) | (ip6[1] << 16) | (ip6[2] << 8) | (ip6[3])); 647 soc_mem_field32_set(unit, view_id, lpm_key, IP_ADDR1f, ip6_word); 648 649 ip6_word = ((ip6[4] << 24) | (ip6[5] << 16) | (ip6[6] << 8) | (ip6[7])); 650 soc_mem_field32_set(unit, view_id, lpm_key, IP_ADDR0f, ip6_word); 651 652 ip6_word = ((mask[0] << 24) | (mask[1] << 16) | (mask[2] << 8) | (mask[3])); 653 soc_mem_field32_set(unit, view_id, lpm_key, IP_ADDR_MASK1f, ip6_word); 654 655 ip6_word = ((mask[4] << 24) | (mask[5] << 16) | (mask[6] << 8) | (mask[7])); 656 soc_mem_field32_set(unit, view_id, lpm_key, IP_ADDR_MASK0f, ip6_word); 657 } 658 /* 659 * Function: 660 * _bcm_td3_lpm_flex_ent_init 661 * Purpose: 662 * Service routine used to initialize lkup key for flex lpm entry. 663 * Parameters: 664 * unit - (IN)SOC unit number. 665 * lpm_cfg - (IN)Prefix info. 666 * lpm_entry - (OUT)Hw buffer to fill. 667 * Returns: 668 * BCM_E_XXX 669 */ 670 int 671 _bcm_td3_lpm_flex_ent_init(int unit, _bcm_defip_cfg_t *lpm_cfg, 672 uint32 *lpm_entry) 673 { 674 bcm_ip_t ip4_mask; 675 int vrf_id; 676 int vrf_mask; 677 int ipv6 = lpm_cfg->defip_flags & BCM_L3_IP6; 678 int mode = 1; 679 soc_mem_t view_id; 680 uint32 action_set; 681 682 /* Extract entry vrf id & vrf mask. */ 683 BCM_IF_ERROR_RETURN 684 (bcm_xgs3_internal_lpm_vrf_calc(unit, lpm_cfg, &vrf_id, &vrf_mask)); 685 686 BCM_IF_ERROR_RETURN( 687 soc_flow_db_ffo_to_mem_view_id_get(unit, 688 lpm_cfg->defip_flow_handle, 689 lpm_cfg->defip_flow_option_handle, 690 SOC_FLOW_DB_FUNC_L3_ROUTE_ID, 691 (uint32 *)&view_id)); 692 693 if (!(SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK0f) || 694 SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK1f))) { 695 return BCM_E_INTERNAL; 696 } 697 698 BCM_IF_ERROR_RETURN(soc_flow_db_mem_view_entry_init(unit, view_id, lpm_entry)); 699 700 if (SOC_MEM_FIELD_VALID(unit, view_id, KEY_MODE0_UPRf)) { 701 mode = soc_mem_field32_get(unit, view_id, lpm_entry, KEY_MODE0_UPRf); 702 } else if (SOC_MEM_FIELD_VALID(unit, view_id, KEY_MODE0f)) { 703 mode = soc_mem_field32_get(unit, view_id, lpm_entry, KEY_MODE0f); 704 } 705 /* Set prefix ip address & mask. */ 706 if (ipv6) { 707 if (mode == 3) { 708 _bcm_td3_flex_ip6_defip_lwr_set(unit, lpm_entry, lpm_cfg, view_id); 709 } else { 710 _bcm_td3_flex_ip6_defip_set(unit, lpm_entry, lpm_cfg, view_id); 711 } 712 } else { 713 ip4_mask = BCM_IP4_MASKLEN_TO_ADDR(lpm_cfg->defip_sub_len); 714 /* Apply subnet mask. */ 715 lpm_cfg->defip_ip_addr &= ip4_mask; 716 717 /* Set address to the buffer. */ 718 soc_mem_field32_set(unit, view_id, lpm_entry, IP_ADDR0f, 719 lpm_cfg->defip_ip_addr); 720 soc_mem_field32_set(unit, view_id, lpm_entry, IP_ADDR_MASK0f, ip4_mask); 721 } 722 723 /* Set Virtual Router id if supported. */ 724 if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_0f)) { 725 soc_mem_field32_set(unit, view_id, lpm_entry, VRF_ID_0f, vrf_id); 726 soc_mem_field32_set(unit, view_id, lpm_entry, VRF_ID_MASK0f, vrf_mask); 727 } 728 729 if (ipv6) { 730 /* Set Virtual Router id if supported. */ 731 if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_1f)) { 732 soc_mem_field32_set(unit, view_id, lpm_entry, VRF_ID_1f, vrf_id); 733 soc_mem_field32_set(unit, view_id, lpm_entry, VRF_ID_MASK1f, vrf_mask); 734 } 735 } 736 737 action_set = 0; 738 if (SOC_MEM_FIELD_VALID(unit, view_id, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf)) { 739 if (BCM_L3_VRF_GLOBAL == lpm_cfg->defip_vrf) { 740 soc_format_field32_set(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt, 741 &action_set, GLOBAL_ROUTEf, 1); 742 } 743 if (BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) { 744 soc_format_field32_set(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt, 745 &action_set, GLOBAL_ROUTEf, 1); 746 } 747 soc_mem_field32_set(unit, view_id, lpm_entry, 748 FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf, action_set); 749 } 750 return (BCM_E_NONE); 751 } 752 int 753 _bcm_td3_lpm_prepare_flex_defip_entry(int unit, _bcm_defip_cfg_t *lpm_cfg, 754 int nh_ecmp_idx, uint32 *lpm_entry) 755 { 756 int i,j; 757 int rv; 758 soc_mem_t view_id; 759 uint32 field_array[128]; 760 uint32 field_count; 761 uint32 opaque_array[16]; 762 uint32 opaque_count; 763 bcm_flow_logical_field_t* user_fields; 764 765 uint32 action_set = 0; 766 767 uint8 process_destination = 0; 768 uint8 process_class_id = 0; 769 uint8 process_qos = 0; 770 uint8 process_pim_sm = 0; 771 uint8 process_fwd_attributes = 0; 772 uint8 process_fwd_3_attributes = 0; 773 uint8 process_vrf = 0; 774 uint8 process_vrf_mask = 0; 775 776 if (NULL == lpm_cfg || NULL == lpm_entry) { 777 return BCM_E_PARAM; 778 } 779 780 /* This routine handles only IP4 entries in L3_DEFIP */ 781 if (lpm_cfg->defip_flags & BCM_L3_IP6) { 782 return BCM_E_PARAM; 783 } 784 785 /* Set hit bit. */ 786 if (lpm_cfg->defip_flags & BCM_L3_HIT) { 787 soc_L3_DEFIPm_field32_set(unit, lpm_entry, HIT0f, 1); 788 } 789 790 BCM_IF_ERROR_RETURN( 791 soc_flow_db_ffo_to_mem_view_id_get(unit, 792 lpm_cfg->defip_flow_handle, 793 lpm_cfg->defip_flow_option_handle, 794 SOC_FLOW_DB_FUNC_L3_ROUTE_ID, 795 (uint32 *)&view_id)); 796 797 /* Initialize control field list for this view id. */ 798 rv = soc_flow_db_mem_view_entry_init(unit, view_id, (uint32 *) lpm_entry); 799 800 BCM_IF_ERROR_RETURN(rv); 801 802 /* Get logical KEY field list for this view id. */ 803 rv = soc_flow_db_mem_view_field_list_get(unit, 804 view_id, 805 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY, 806 16, 807 opaque_array, 808 &opaque_count); 809 BCM_IF_ERROR_RETURN(rv); 810 811 user_fields = lpm_cfg->defip_logical_fields; 812 813 for (j = 0; j < lpm_cfg->defip_num_of_fields; j++) { 814 for (i=0; i<opaque_count; i++) { 815 if (user_fields[j].id == opaque_array[i]) { 816 soc_mem_field32_set(unit, view_id, lpm_entry, user_fields[j].id, 817 user_fields[j].value); 818 break; 819 } 820 } 821 } 822 823 /* Get logical PDD field list for this view id. */ 824 rv = soc_flow_db_mem_view_field_list_get(unit, 825 view_id, 826 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 827 16, 828 opaque_array, 829 &opaque_count); 830 BCM_IF_ERROR_RETURN(rv); 831 832 user_fields = lpm_cfg->defip_logical_fields; 833 834 for (j = 0; j < lpm_cfg->defip_num_of_fields; j++) { 835 for (i=0; i<opaque_count; i++) { 836 if (user_fields[j].id == opaque_array[i]) { 837 soc_mem_field32_set(unit, view_id, lpm_entry, user_fields[j].id, 838 user_fields[j].value); 839 break; 840 } 841 } 842 } 843 844 /* Get PDD field list corresponding to the view id. */ 845 rv = soc_flow_db_mem_view_field_list_get(unit, 846 view_id, 847 SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA, 848 128, 849 field_array, 850 &field_count); 851 BCM_IF_ERROR_RETURN(rv); 852 853 for (i=0; i<field_count; i++) { 854 switch (field_array[i]) { 855 case DESTINATION_ACTION_SETf: 856 process_destination = 1; 857 break; 858 case CLASS_ID_ACTION_SETf: 859 process_class_id = 1; 860 break; 861 case QOS_ACTION_SETf: 862 process_qos = 1; 863 break; 864 case FWD_ATTRIBUTES_ACTION_SETf: 865 process_fwd_attributes = 1; 866 break; 867 case FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf: 868 process_fwd_3_attributes = 1; 869 break; 870 case PIM_SM_ACTION_SETf: 871 process_pim_sm = 1; 872 break; 873 case VRF_ID_0f: 874 process_vrf = 1; 875 break; 876 case VRF_ID_MASK0f: 877 process_vrf_mask = 1; 878 break; 879 default: 880 break; 881 } 882 } 883 884 action_set = 0; 885 if (process_vrf) { 886 soc_mem_field32_set(unit, view_id, lpm_entry, 887 VRF_ID_0f, lpm_cfg->defip_vrf); 888 } 889 890 if (process_vrf_mask) { 891 soc_mem_field32_set(unit, view_id, lpm_entry, 892 VRF_ID_MASK0f, 0xfff); 893 } 894 895 /* Configure entry for SIP lookup if URPF is enabled. 896 * For devices like KT2 both DIP and SIP lookup is done 897 * using only 1 L3_DEFIP entry, unlike other devices where 898 * L3_DEFIP table is divided in 2 parts to support URPF. 899 * RPExf and DEFAULTROUTExf are not overlayed in KT2 like previous devices. 900 */ 901 action_set = 0; 902 if (soc_feature(unit, soc_feature_l3_defip_advanced_lookup) && 903 process_fwd_3_attributes) { 904 /* DEFAULTROUTE0f */ 905 soc_format_field32_set(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt, 906 &action_set, DEFAULT_ROUTEf, 907 (SOC_URPF_STATUS_GET(unit) ? 1 : 0)); 908 soc_mem_field32_set(unit, view_id, lpm_entry, 909 FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf, action_set); 910 911 } 912 913 /* Set priority override bit. */ 914 action_set = 0; 915 916 if (lpm_cfg->defip_flags & BCM_L3_RPE) { 917 if (!process_qos) { 918 return BCM_E_UNAVAIL; 919 } 920 soc_format_field32_set(unit, QOS_ACTION_SETfmt, 921 &action_set, RPEf, 1); 922 } 923 924 /* Write priority field. */ 925 soc_format_field32_set(unit, QOS_ACTION_SETfmt, 926 &action_set, PRIf, lpm_cfg->defip_prio); 927 928 if (process_qos) { 929 soc_mem_field32_set(unit, view_id, lpm_entry, 930 QOS_ACTION_SETf, action_set); 931 } 932 933 /* Fill next hop information. */ 934 if (!process_destination) { 935 return BCM_E_INTERNAL; 936 } 937 938 action_set = 0; 939 940 if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) { 941 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 942 &action_set, DEST_TYPE1f, BCMI_TD3_DEST_TYPE1_ECMP); 943 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 944 &action_set, ECMP_GROUPf, nh_ecmp_idx); 945 946 } else if (nh_ecmp_idx != BCM_XGS3_L3_INVALID_INDEX) { 947 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 948 &action_set, DEST_TYPE0f, BCMI_TD3_DEST_TYPE0_NH); 949 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 950 &action_set, NEXT_HOP_INDEXf, nh_ecmp_idx); 951 } 952 soc_mem_field32_set(unit, view_id, lpm_entry, 953 DESTINATION_ACTION_SETf, action_set); 954 955 /* Set destination discard flag. */ 956 action_set = 0; 957 if (lpm_cfg->defip_flags & BCM_L3_DST_DISCARD) { 958 if (!process_fwd_attributes) { 959 return BCM_E_UNAVAIL; 960 } 961 soc_format_field32_set(unit, FWD_ATTRIBUTES_ACTION_SETfmt, 962 &action_set, DST_DISCARDf, 1); 963 soc_mem_field32_set(unit, view_id, lpm_entry, 964 FWD_ATTRIBUTES_ACTION_SETf, action_set); 965 } 966 967 /* Set classification group id. */ 968 if (process_class_id) { 969 /* CLASS_ID0f */ 970 soc_mem_field32_set(unit, view_id, lpm_entry, CLASS_ID_ACTION_SETf, 971 lpm_cfg->defip_lookup_class); 972 } 973 974 /* Set Global route flag. */ 975 if (process_fwd_3_attributes) { 976 if (BCM_L3_VRF_GLOBAL == lpm_cfg->defip_vrf) { 977 /* GLOBAL_ROUTE0f */ 978 soc_format_field32_set(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt, 979 &action_set, GLOBAL_ROUTEf, 1); 980 981 } 982 if (BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) { 983 soc_format_field32_set(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt, 984 &action_set, GLOBAL_ROUTEf, 1); 985 } 986 soc_mem_field32_set(unit, view_id, lpm_entry, 987 FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf, action_set); 988 } 989 990 if (soc_feature(unit, soc_feature_ipmc_defip) && 991 (lpm_cfg->defip_flags & BCM_L3_IPMC)) { 992 993 /* L3MC_INDEXf */ 994 action_set = 0; 995 if (!process_pim_sm) { 996 return BCM_E_UNAVAIL; 997 } 998 999 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1000 &action_set, DEST_TYPE1f, BCMI_TD3_DEST_TYPE1_IPMC); 1001 soc_format_field32_set(unit, DESTINATION_FORMATfmt, 1002 &action_set, IPMC_GROUPf, lpm_cfg->defip_mc_group); 1003 soc_mem_field32_set(unit, view_id, lpm_entry, 1004 DESTINATION_ACTION_SETf, action_set); 1005 1006 /* 1007 * RP ID needs uplift by _BCM_L3_DEFIP_RP_ID_BASE value, Now it wil fit in EXPECTED_L3_IIFf 1008 */ 1009 action_set = 0; 1010 if (lpm_cfg->defip_l3a_rp != BCM_IPMC_RP_ID_INVALID) { 1011 soc_format_field32_set(unit, PIM_SM_ACTION_SETfmt, 1012 &action_set, EXPECTED_L3_IIFf, 1013 _BCM_DEFIP_IPMC_RP_SET(lpm_cfg->defip_l3a_rp)); 1014 1015 } else if ((lpm_cfg->defip_ipmc_flags & BCM_IPMC_POST_LOOKUP_RPF_CHECK) && 1016 (lpm_cfg->defip_expected_intf != 0)) { 1017 1018 soc_format_field32_set(unit, PIM_SM_ACTION_SETfmt, 1019 &action_set, EXPECTED_L3_IIFf, 1020 lpm_cfg->defip_expected_intf); 1021 1022 if (lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_DROP) { 1023 soc_format_field32_set(unit, PIM_SM_ACTION_SETfmt, 1024 &action_set, IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf, 1); 1025 } 1026 if (lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_TOCPU) { 1027 soc_format_field32_set(unit, PIM_SM_ACTION_SETfmt, 1028 &action_set, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf, 1); 1029 } 1030 } 1031 soc_mem_field32_set(unit, view_id, lpm_entry, 1032 PIM_SM_ACTION_SETf, action_set); 1033 } 1034 1035 /* 1036 * Note ipv4 entries are expected to reside in part 0 of the entry. 1037 * ipv6 entries both parts should be filled. 1038 * Hence if entry is ipv6 copy part 0 to part 1 1039 */ 1040 if (lpm_cfg->defip_flags & BCM_L3_IP6) { 1041 soc_fb_lpm_ip4entry0_to_1(unit, lpm_entry, lpm_entry, TRUE); 1042 } 1043 1044 /* 1045 * Initialize hw buffer from lpm configuration. 1046 * NOTE: DON'T MOVE _bcm_fb_defip_ent_init CALL UP, 1047 * We want to copy flags & nh info, avoid ipv6 mask & address corruption. 1048 */ 1049 BCM_IF_ERROR_RETURN(_bcm_td3_lpm_flex_ent_init(unit, lpm_cfg, lpm_entry)); 1050 1051 return BCM_E_NONE; 1052 } 1053 /* 1054 * Function: 1055 * _bcm_defip_pair128_ip6_addr_get 1056 * Purpose: 1057 * Read IP6 address field from memory field to ip6_addr_t buffer. 1058 * Parameters: 1059 * unit - (IN) BCM device number. 1060 * mem - (IN) Memory id. 1061 * entry - (IN) HW entry buffer. 1062 * ip6 - (OUT) SW ip6 address buffer. 1063 * Returns: void 1064 */ 1065 STATIC void 1066 _bcm_defip_pair128_flex_ip6_addr_get(int unit, soc_mem_t view_id, const void *entry, ip6_addr_t ip6) 1067 { 1068 uint32 ip6_field[4]; 1069 if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__DIPf)) { 1070 soc_mem_ip6_addr_get(unit, view_id, entry,IPV6__DIPf, ip6, 0); 1071 } else if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__SIPf)) { 1072 soc_mem_ip6_addr_get(unit, view_id, entry,IPV6__SIPf, ip6, 0); 1073 } else { 1074 ip6_field[3] = soc_mem_field32_get(unit, view_id, entry, IP_ADDR0_LWRf); 1075 ip6[12] = (uint8) (ip6_field[3] >> 24); 1076 ip6[13] = (uint8) (ip6_field[3] >> 16 & 0xff); 1077 ip6[14] = (uint8) (ip6_field[3] >> 8 & 0xff); 1078 ip6[15] = (uint8) (ip6_field[3] & 0xff); 1079 ip6_field[2] = soc_mem_field32_get(unit, view_id, entry, IP_ADDR1_LWRf); 1080 ip6[8] = (uint8) (ip6_field[2] >> 24); 1081 ip6[9] = (uint8) (ip6_field[2] >> 16 & 0xff); 1082 ip6[10] = (uint8) (ip6_field[2] >> 8 & 0xff); 1083 ip6[11] = (uint8) (ip6_field[2] & 0xff); 1084 ip6_field[1] = soc_mem_field32_get(unit, view_id, entry, IP_ADDR0_UPRf); 1085 ip6[4] = (uint8) (ip6_field[1] >> 24); 1086 ip6[5] = (uint8) (ip6_field[1] >> 16 & 0xff); 1087 ip6[6] =(uint8) (ip6_field[1] >> 8 & 0xff); 1088 ip6[7] =(uint8) (ip6_field[1] & 0xff); 1089 ip6_field[0] = soc_mem_field32_get(unit, view_id, entry, IP_ADDR1_UPRf); 1090 ip6[0] =(uint8) (ip6_field[0] >> 24); 1091 ip6[1] =(uint8) (ip6_field[0] >> 16 & 0xff); 1092 ip6[2] =(uint8) (ip6_field[0] >> 8 & 0xff); 1093 ip6[3] =(uint8) (ip6_field[0] & 0xff); 1094 } 1095 } 1096 /* 1097 * Function: 1098 * _bcm_defip_pair128_flex_ip6_mask_get 1099 * Purpose: 1100 * Read IP6 mask field from memory field to ip6_addr_t buffer. 1101 * Parameters: 1102 * unit - (IN) BCM device number. 1103 * mem - (IN) Memory id. 1104 * entry - (IN) HW entry buffer. 1105 * ip6 - (OUT) SW ip6 address buffer. 1106 * Returns: void 1107 */ 1108 STATIC void 1109 _bcm_defip_pair128_flex_ip6_mask_get(int unit, soc_mem_t view_id, const void *entry, 1110 ip6_addr_t ip6) 1111 { 1112 uint32 ip6_field[4]; 1113 1114 if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__MASKf)) { 1115 soc_mem_ip6_addr_get(unit, view_id, entry,IPV6__MASKf, ip6, 0); 1116 } else { 1117 ip6_field[3] = soc_mem_field32_get(unit, view_id, entry, IP_ADDR_MASK0_LWRf); 1118 ip6[12] = (uint8) (ip6_field[3] >> 24); 1119 ip6[13] = (uint8) (ip6_field[3] >> 16 & 0xff); 1120 ip6[14] = (uint8) (ip6_field[3] >> 8 & 0xff); 1121 ip6[15] = (uint8) (ip6_field[3] & 0xff); 1122 ip6_field[2] = soc_mem_field32_get(unit, view_id, entry, IP_ADDR_MASK1_LWRf); 1123 ip6[8] = (uint8) (ip6_field[2] >> 24); 1124 ip6[9] = (uint8) (ip6_field[2] >> 16 & 0xff); 1125 ip6[10] = (uint8) (ip6_field[2] >> 8 & 0xff); 1126 ip6[11] = (uint8) (ip6_field[2] & 0xff); 1127 ip6_field[1] = soc_mem_field32_get(unit, view_id, entry, IP_ADDR_MASK0_UPRf); 1128 ip6[4] = (uint8) (ip6_field[1] >> 24); 1129 ip6[5] = (uint8) (ip6_field[1] >> 16 & 0xff); 1130 ip6[6] =(uint8) (ip6_field[1] >> 8 & 0xff); 1131 ip6[7] =(uint8) (ip6_field[1] & 0xff); 1132 ip6_field[0] = soc_mem_field32_get(unit, view_id, entry, IP_ADDR_MASK1_UPRf); 1133 ip6[0] =(uint8) (ip6_field[0] >> 24); 1134 ip6[1] =(uint8) (ip6_field[0] >> 16 & 0xff); 1135 ip6[2] =(uint8) (ip6_field[0] >> 8 & 0xff); 1136 ip6[3] =(uint8) (ip6_field[0] & 0xff); 1137 } 1138 } 1139 /* 1140 * Function: 1141 * _bcm_defip_pair128_get_key 1142 * Purpose: 1143 * Parse route entry key from L3_DEFIP_PAIR_128 table. 1144 * Parameters: 1145 * unit - (IN)SOC unit number. 1146 * entry - (IN)Hw entry buffer. 1147 * lpm_cfg - (IN/OUT)Buffer to fill defip information. 1148 * Returns: 1149 * BCM_E_XXX 1150 */ 1151 int 1152 _bcm_defip_pair128_flex_get_key(int unit, uint32 *hw_entry, 1153 _bcm_defip_cfg_t *lpm_cfg, uint32 key_type) 1154 { 1155 bcm_ip6_t mask; /* Subnet mask. */ 1156 soc_mem_t view_id; 1157 1158 BCM_IF_ERROR_RETURN ( 1159 soc_flow_db_mem_to_view_id_get(unit, 1160 L3_DEFIP_PAIR_128m, 1161 key_type, 1162 SOC_FLOW_DB_DATA_TYPE_INVALID, 1163 0, 1164 NULL, 1165 (uint32 *)&view_id)); 1166 1167 if ((!SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK0_LWRf) || 1168 !SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK1_LWRf) || 1169 !SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK0_UPRf) || 1170 !SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK1_UPRf)) && 1171 (!SOC_MEM_FIELD_VALID(unit, view_id, IPV6__MASKf))) { 1172 return BCM_E_INTERNAL; 1173 } 1174 1175 /* Extract ip6 address. */ 1176 _bcm_defip_pair128_flex_ip6_addr_get(unit, view_id, hw_entry, lpm_cfg->defip_ip6_addr); 1177 1178 /* Extract subnet mask. */ 1179 _bcm_defip_pair128_flex_ip6_mask_get(unit, view_id, hw_entry, mask); 1180 1181 lpm_cfg->defip_sub_len = bcm_ip6_mask_length(mask); 1182 1183 /* Extract vrf id & vrf mask. */ 1184 if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_MASK0_LWRf)) { 1185 if (!soc_mem_field32_get(unit, view_id, hw_entry, VRF_ID_MASK0_LWRf)) { 1186 lpm_cfg->defip_vrf = BCM_L3_VRF_OVERRIDE; 1187 } else { 1188 lpm_cfg->defip_vrf = soc_mem_field32_get(unit, view_id, hw_entry, VRF_ID_0_LWRf); 1189 } 1190 } else if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_MASK0f)) { 1191 if (!soc_mem_field32_get(unit, view_id, hw_entry, VRF_ID_MASK0f)) { 1192 lpm_cfg->defip_vrf = BCM_L3_VRF_OVERRIDE; 1193 } else { 1194 lpm_cfg->defip_vrf = soc_mem_field32_get(unit, view_id, hw_entry, VRF_ID_0f); 1195 } 1196 } 1197 return (BCM_E_NONE); 1198 } 1199 /* 1200 * Function: 1201 * _bcm_td3_lpm_flex_ent_parse 1202 * Purpose: 1203 * Parse flex route entry to sw structure. 1204 * Parameters: 1205 * unit - (IN)SOC unit number. 1206 * hw_entry - (IN)Hw entry buffer. 1207 * lpm_cfg - (IN/OUT)Buffer to fill defip information. 1208 * nh_ecmp_idx - (OUT)Next hop ecmp table index. 1209 * Returns: 1210 * BCM_E_XXX 1211 */ 1212 int 1213 _bcm_td3_lpm_flex_ent_parse(int unit, uint32 *lpm_entry, uint32 key_type, soc_mem_t mem, _bcm_defip_cfg_t *lpm_cfg, int *nh_ecmp_idx) 1214 { 1215 uint32 action_set; 1216 uint32 dest_action_set; 1217 uint32 dest_type1; 1218 soc_mem_t view_id; 1219 uint32 data_ids[BCM_FLOW_MAX_NOF_LOGICAL_FIELDS]; 1220 uint32 key_ids[BCM_FLOW_MAX_NOF_LOGICAL_FIELDS]; 1221 uint32 key_cnt = 0; 1222 uint32 data_cnt = 0; 1223 uint32 i = 0; 1224 1225 BCM_IF_ERROR_RETURN( 1226 soc_flow_db_mem_to_view_id_get(unit, 1227 mem, 1228 key_type, 1229 SOC_FLOW_DB_DATA_TYPE_INVALID, 1230 0, 1231 NULL, 1232 (uint32 *)&view_id)); 1233 1234 if (mem == L3_DEFIP_PAIR_128m || 1235 (SOC_MEM_FIELD_VALID(unit, view_id, IPV6f)) || 1236 (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__SIPf)) || 1237 (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__DIPf))) { 1238 lpm_cfg->defip_flags |= BCM_L3_IP6; 1239 } 1240 1241 dest_action_set = soc_mem_field32_get(unit, view_id, lpm_entry, 1242 DESTINATION_ACTION_SETf); 1243 1244 dest_type1 = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 1245 &dest_action_set, DEST_TYPE1f); 1246 1247 if (soc_feature(unit, soc_feature_ipmc_defip) && 1248 dest_type1 == BCMI_TD3_DEST_TYPE1_IPMC) { 1249 1250 int val; 1251 lpm_cfg->defip_flags |= BCM_L3_IPMC; 1252 1253 action_set = soc_mem_field32_get(unit, view_id, lpm_entry, 1254 PIM_SM_ACTION_SETf); 1255 1256 if (soc_format_field32_get(unit, PIM_SM_ACTION_SETfmt, &action_set, IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf)) { 1257 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RPF_FAIL_DROP; 1258 } 1259 if (soc_format_field32_get(unit, PIM_SM_ACTION_SETfmt, &action_set, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf)) { 1260 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RPF_FAIL_TOCPU; 1261 } 1262 val = soc_format_field32_get(unit, PIM_SM_ACTION_SETfmt, 1263 &action_set, EXPECTED_L3_IIFf); 1264 /* 1265 * RP ID and ExpectedIIF are overlaid. 1266 */ 1267 if (soc_feature(unit, soc_feature_l3defip_rp_l3iif_resolve)) { 1268 int rpa_id_mask; 1269 if (SOC_MEM_FIELD_VALID(unit, mem, RPA_ID0f)) { 1270 rpa_id_mask = (1 << soc_mem_field_length(unit, mem, RPA_ID0f)) - 1; 1271 } else { 1272 rpa_id_mask = (1 << soc_mem_field_length(unit, mem, RPA_IDf)) - 1; 1273 } 1274 /* 1275 * 1) If value is more than RPA_ID field then its l3_iif. 1276 * N/A for TD3/MV2/HX5 to support warmboot. 1277 * 2) When RPF FAIL DROP/TOCPU flags are set then its l3iif valid 1278 */ 1279 if ((lpm_cfg->defip_ipmc_flags & 1280 (BCM_IPMC_RPF_FAIL_DROP | BCM_IPMC_RPF_FAIL_TOCPU)) || 1281 (!(SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit) || 1282 SOC_IS_HELIX5(unit)) && (val > rpa_id_mask))) { 1283 lpm_cfg->defip_expected_intf = val; 1284 if (0 != lpm_cfg->defip_expected_intf) { 1285 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_POST_LOOKUP_RPF_CHECK; 1286 } 1287 lpm_cfg->defip_l3a_rp = BCM_IPMC_RP_ID_INVALID; 1288 } else { 1289 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RP_ID_EXPECTED_INTF_RESOLVE; 1290 lpm_cfg->defip_l3a_rp = val & rpa_id_mask; 1291 lpm_cfg->defip_expected_intf = val; 1292 } 1293 } else if (_BCM_DEFIP_IPMC_RP_IS_SET(val)) { 1294 lpm_cfg->defip_l3a_rp = _BCM_DEFIP_IPMC_RP_GET(val); 1295 } else { 1296 lpm_cfg->defip_expected_intf = val; 1297 1298 if (0 != lpm_cfg->defip_expected_intf) { 1299 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_POST_LOOKUP_RPF_CHECK; 1300 } 1301 lpm_cfg->defip_l3a_rp = BCM_IPMC_RP_ID_INVALID; 1302 } 1303 lpm_cfg->defip_mc_group = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 1304 &dest_action_set, L3MC_INDEXf); 1305 } 1306 1307 if (dest_type1 == BCMI_TD3_DEST_TYPE1_ECMP) { 1308 lpm_cfg->defip_ecmp = TRUE; 1309 lpm_cfg->defip_flags |= BCM_L3_MULTIPATH; 1310 } else { 1311 lpm_cfg->defip_ecmp = 0; 1312 lpm_cfg->defip_ecmp_count = 0; 1313 } 1314 if (nh_ecmp_idx != NULL) { 1315 *nh_ecmp_idx = soc_format_field32_get(unit, DESTINATION_FORMATfmt, 1316 &dest_action_set, NEXT_HOP_INDEXf); 1317 } 1318 1319 if (SOC_MEM_FIELD_VALID(unit, view_id, QOS_ACTION_SETf)) { 1320 action_set = soc_mem_field32_get(unit, view_id, lpm_entry, 1321 QOS_ACTION_SETf); 1322 1323 /* Get entry priority. */ 1324 lpm_cfg->defip_prio = soc_format_field32_get(unit, QOS_ACTION_SETfmt, 1325 &action_set, PRIf); 1326 1327 /* Get priority override bit. */ 1328 if (soc_format_field32_get(unit, QOS_ACTION_SETfmt, &action_set, RPEf)) { 1329 lpm_cfg->defip_flags |= BCM_L3_RPE; 1330 } 1331 } 1332 1333 /* Get classification group id. */ 1334 if (SOC_MEM_FIELD_VALID(unit, view_id, CLASS_ID_ACTION_SETf)) { 1335 lpm_cfg->defip_lookup_class = 1336 soc_mem_field32_get(unit, view_id, lpm_entry, CLASS_ID_ACTION_SETf); 1337 } 1338 1339 /* Get hit bit. */ 1340 if (SOC_MEM_FIELD_VALID(unit, view_id, HITf)) { 1341 if (soc_mem_field32_get(unit, view_id, lpm_entry, HITf)) { 1342 lpm_cfg->defip_flags |= BCM_L3_HIT; 1343 } 1344 } 1345 1346 if (SOC_MEM_FIELD_VALID(unit, view_id, HIT0f)) { 1347 if (soc_mem_field32_get(unit, view_id, lpm_entry, HIT0f)) { 1348 lpm_cfg->defip_flags |= BCM_L3_HIT; 1349 } 1350 } 1351 1352 /* Get destination discard field. */ 1353 if (SOC_MEM_FIELD_VALID(unit, view_id, FWD_ATTRIBUTES_ACTION_SETf)) { 1354 action_set = soc_mem_field32_get(unit, view_id, lpm_entry, 1355 FWD_ATTRIBUTES_ACTION_SETf); 1356 1357 if (soc_format_field32_get(unit, FWD_ATTRIBUTES_ACTION_SETfmt, 1358 &action_set, DST_DISCARDf)) { 1359 lpm_cfg->defip_flags |= BCM_L3_DST_DISCARD; 1360 } 1361 } 1362 1363 /* Get the logical fields */ 1364 lpm_cfg->defip_num_of_fields = 0; 1365 BCM_IF_ERROR_RETURN( 1366 soc_flow_db_mem_view_field_list_get(unit, 1367 view_id, 1368 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY, 1369 BCM_FLOW_MAX_NOF_LOGICAL_FIELDS, 1370 key_ids, 1371 &key_cnt)); 1372 1373 if (key_cnt) { 1374 for (i = 0; 1375 (i < key_cnt) ; i++) { 1376 lpm_cfg->defip_logical_fields[i].id = key_ids[i]; 1377 lpm_cfg->defip_logical_fields[i].value = 1378 soc_mem_field32_get(unit, view_id, lpm_entry, 1379 key_ids[i]); 1380 1381 } 1382 lpm_cfg->defip_num_of_fields = key_cnt; 1383 } 1384 BCM_IF_ERROR_RETURN( 1385 soc_flow_db_mem_view_field_list_get(unit, 1386 view_id, 1387 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 1388 BCM_FLOW_MAX_NOF_LOGICAL_FIELDS, data_ids, &data_cnt)); 1389 if (data_cnt) { 1390 /* Entry traverse */ 1391 for ( ; 1392 ((i < data_cnt) && 1393 ( i < SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA)); 1394 i++) { 1395 lpm_cfg->defip_logical_fields[i].id = data_ids[i]; 1396 lpm_cfg->defip_logical_fields[i].value = 1397 soc_mem_field32_get(unit, view_id, lpm_entry, 1398 data_ids[i]); 1399 } 1400 lpm_cfg->defip_num_of_fields += data_cnt; 1401 } 1402 1403 SOC_IF_ERROR_RETURN(_bcm_flow_mem_view_to_flow_info_get(unit, view_id, 1404 SOC_FLOW_DB_FUNC_L3_ROUTE_ID, 1405 &lpm_cfg->defip_flow_handle, &lpm_cfg->defip_flow_option_handle, 1)); 1406 1407 return (BCM_E_NONE); 1408 } 1409 /* 1410 * Function: 1411 * _bcm_td3_flex_ip6_defip_get 1412 * Purpose: 1413 * Set an IP6 address field in L3_DEFIPm 1414 * Note: 1415 * See soc_mem_ip6_addr_set() 1416 */ 1417 STATIC void 1418 _bcm_td3_flex_ip6_defip_get(int unit, const void *lpm_key, soc_mem_t view_id, 1419 _bcm_defip_cfg_t *lpm_cfg) 1420 { 1421 uint8 *ip6; /* Ip6 address. */ 1422 uint8 mask[BCM_IP6_ADDRLEN]; /* Subnet mask. */ 1423 uint32 ip6_word; /* Temp storage. */ 1424 1425 sal_memset(mask, 0, sizeof (bcm_ip6_t)); 1426 1427 /* Just to keep variable name short. */ 1428 ip6 = lpm_cfg->defip_ip6_addr; 1429 sal_memset(ip6, 0, sizeof (bcm_ip6_t)); 1430 1431 ip6_word = soc_mem_field32_get(unit, view_id, lpm_key, IP_ADDR1f); 1432 ip6[0] = (uint8) ((ip6_word >> 24) & 0xff); 1433 ip6[1] = (uint8) ((ip6_word >> 16) & 0xff); 1434 ip6[2] = (uint8) ((ip6_word >> 8) & 0xff); 1435 ip6[3] = (uint8) (ip6_word & 0xff); 1436 1437 ip6_word = soc_mem_field32_get(unit, view_id, lpm_key, IP_ADDR0f); 1438 ip6[4] = (uint8) ((ip6_word >> 24) & 0xff); 1439 ip6[5] = (uint8) ((ip6_word >> 16) & 0xff); 1440 ip6[6] = (uint8) ((ip6_word >> 8) & 0xff); 1441 ip6[7] = (uint8) (ip6_word & 0xff); 1442 1443 ip6_word = soc_mem_field32_get(unit, view_id, lpm_key, IP_ADDR_MASK1f); 1444 mask[0] = (uint8) ((ip6_word >> 24) & 0xff); 1445 mask[1] = (uint8) ((ip6_word >> 16) & 0xff); 1446 mask[2] = (uint8) ((ip6_word >> 8) & 0xff); 1447 mask[3] = (uint8) (ip6_word & 0xff); 1448 1449 ip6_word = soc_mem_field32_get(unit, view_id, lpm_key, IP_ADDR_MASK0f); 1450 mask[4] = (uint8) ((ip6_word >> 24) & 0xff); 1451 mask[5] = (uint8) ((ip6_word >> 16) & 0xff); 1452 mask[6] = (uint8) ((ip6_word >> 8) & 0xff); 1453 mask[7] = (uint8) (ip6_word & 0xff); 1454 1455 lpm_cfg->defip_sub_len = bcm_ip6_mask_length(mask); 1456 } 1457 /* 1458 * Function: 1459 * _bcm_td3_lpm_flex_vrf_get 1460 * Purpose: 1461 * Service routine used to translate hw specific vrf id to API format. 1462 * Parameters: 1463 * unit - (IN)SOC unit number. 1464 * lpm_entry - (IN)Route info buffer from hw. 1465 * vrf_id - (OUT)Virtual router id. 1466 * Returns: 1467 * BCM_E_XXX 1468 */ 1469 STATIC int 1470 _bcm_td3_lpm_flex_vrf_get(int unit, void *lpm_entry, int *vrf, soc_mem_t view_id) 1471 { 1472 int vrf_id; 1473 1474 /* Get Virtual Router id if supported. */ 1475 if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_MASK0f)){ 1476 vrf_id = soc_mem_field32_get(unit, view_id, lpm_entry, VRF_ID_0f); 1477 1478 /* Special vrf's handling. */ 1479 if (soc_mem_field32_get(unit, view_id, lpm_entry, VRF_ID_MASK0f)) { 1480 *vrf = vrf_id; 1481 } else if (SOC_VRF_MAX(unit) == vrf_id) { 1482 *vrf = BCM_L3_VRF_GLOBAL; 1483 } else { 1484 *vrf = BCM_L3_VRF_OVERRIDE; 1485 if (SOC_MEM_FIELD_VALID(unit, view_id, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf)) { 1486 uint32 action_set = soc_mem_field32_get(unit, view_id, lpm_entry, 1487 FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf); 1488 if (soc_format_field32_get(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt, 1489 &action_set, GLOBAL_ROUTEf)) { 1490 *vrf = BCM_L3_VRF_GLOBAL; 1491 } 1492 } 1493 #if 0 1494 if (SOC_MEM_FIELD_VALID(unit, L3_DEFIPm, GLOBAL_HIGH0f)) { 1495 if (soc_mem_field32_get(unit, view_id, lpm_entry, GLOBAL_HIGH0f)){ 1496 *vrf = BCM_L3_VRF_OVERRIDE; 1497 } 1498 } 1499 #endif 1500 } 1501 } else { 1502 /* No vrf support on this device. */ 1503 *vrf = BCM_L3_VRF_DEFAULT; 1504 } 1505 return (BCM_E_NONE); 1506 } 1507 /* 1508 * Function: 1509 * _bcm_fb_lpm_flex_ent_get_key 1510 * Purpose: 1511 * Get flex entry key from DEFIP table. 1512 * Parameters: 1513 * unit - (IN)SOC unit number. 1514 * lpm_cfg - (OUT)Buffer to fill defip information. 1515 * lpm_entry - (IN) Buffer read from hw. 1516 * Returns: 1517 * void 1518 */ 1519 int 1520 _bcm_td3_lpm_flex_ent_get_key(int unit, _bcm_defip_cfg_t *lpm_cfg, 1521 uint32 *lpm_entry, uint32 key_type) 1522 { 1523 bcm_ip_t v4_mask; 1524 int ipv6 = lpm_cfg->defip_flags & BCM_L3_IP6; 1525 soc_mem_t view_id; 1526 1527 BCM_IF_ERROR_RETURN ( 1528 soc_flow_db_mem_to_view_id_get(unit, 1529 L3_DEFIPm, 1530 key_type, 1531 SOC_FLOW_DB_DATA_TYPE_INVALID, 1532 0, 1533 NULL, 1534 (uint32 *)&view_id)); 1535 1536 /* Set prefix ip address & mask. */ 1537 if (ipv6) { 1538 _bcm_td3_flex_ip6_defip_get(unit, lpm_entry, view_id, lpm_cfg); 1539 } else { 1540 /* Get ipv4 address. */ 1541 lpm_cfg->defip_ip_addr = 1542 soc_mem_field32_get(unit, view_id, lpm_entry, IP_ADDR0f); 1543 1544 /* Get subnet mask. */ 1545 v4_mask = soc_mem_field32_get(unit, view_id, lpm_entry, IP_ADDR_MASK0f); 1546 1547 /* Fill mask length. */ 1548 lpm_cfg->defip_sub_len = bcm_ip_mask_length(v4_mask); 1549 } 1550 1551 /* Get Virtual Router id */ 1552 _bcm_td3_lpm_flex_vrf_get(unit, lpm_entry, &lpm_cfg->defip_vrf, view_id); 1553 1554 return BCM_E_NONE; 1555 } 1556 1557 #endif