l3.c (88555B)
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: l3.c 8 * Purpose: Triumph L3 function implementations 9 */ 10 11 12 #include <soc/defs.h> 13 14 #include <assert.h> 15 16 #include <sal/core/libc.h> 17 #if defined(BCM_TRIUMPH_SUPPORT) && defined(INCLUDE_L3) 18 19 #include <shared/util.h> 20 #include <soc/mem.h> 21 #include <soc/cm.h> 22 #include <soc/drv.h> 23 #include <soc/register.h> 24 #include <soc/memory.h> 25 #include <soc/l3x.h> 26 #include <soc/lpm.h> 27 #include <soc/tnl_term.h> 28 29 #include <bcm/l3.h> 30 #include <bcm/tunnel.h> 31 #include <bcm/debug.h> 32 #include <bcm/error.h> 33 #include <bcm/stack.h> 34 35 #include <bcm_int/esw/mbcm.h> 36 #include <bcm_int/esw/firebolt.h> 37 #include <bcm_int/esw/trx.h> 38 #include <bcm_int/esw/triumph.h> 39 #include <bcm_int/esw/l3.h> 40 #include <bcm_int/esw/xgs3.h> 41 #include <bcm_int/esw_dispatch.h> 42 #if defined(BCM_TRIUMPH2_SUPPORT) 43 #include <bcm_int/esw/triumph2.h> 44 #endif /* BCM_TRIUMPH2_SUPPORT */ 45 #if defined(BCM_KATANA_SUPPORT) 46 #include <bcm_int/esw/katana.h> 47 #endif /* BCM_KATANA_SUPPORT */ 48 #if defined(BCM_TRIDENT2_SUPPORT) 49 #include <bcm_int/esw/trident2.h> 50 #endif /* BCM_TRIDENT2_SUPPORT */ 51 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 52 #include <bcm_int/esw/flex_ctr.h> 53 #endif 54 #ifdef BCM_TRIDENT2_SUPPORT 55 #define _BCM_TD2_IP_OPTIONS_PROFILE_MASK 0x3ff /* 10 bits width */ 56 #define _BCM_TD2_IP_OPTIONS_BITS_WIDTH 8 /* IP options size = 8 */ 57 #endif /* BCM_TRIDENT2_SUPPORT */ 58 /* 59 * Function: 60 * _bcm_tr_defip_init 61 * Purpose: 62 * Initialize L3 DEFIP table for triumph devices. 63 * Parameters: 64 * unit - (IN) SOC unit number. 65 * Returns: 66 * BCM_E_XXX 67 */ 68 int 69 _bcm_tr_defip_init(int unit) 70 { 71 soc_mem_t mem_v4; /* IPv4 Route table memory. */ 72 soc_mem_t mem_v6; /* IPv6 Route table memory. */ 73 soc_mem_t mem_v6_128; /* IPv6 full prefix route table memory. */ 74 int index_min, index_max; 75 #if defined(BCM_KATANA_SUPPORT) 76 int ipv6_lpm_128b_enable; 77 #endif 78 79 /* Get memory for IPv4 entries. */ 80 BCM_IF_ERROR_RETURN(_bcm_tr_l3_defip_mem_get(unit, 0, 0, &mem_v4)); 81 82 /* Initialize IPv4 entries lookup engine. */ 83 if (L3_DEFIPm == mem_v4) { 84 BCM_IF_ERROR_RETURN(soc_fb_lpm_init(unit)); 85 } else { 86 BCM_IF_ERROR_RETURN(_bcm_tr_ext_lpm_init(unit, mem_v4)); 87 } 88 89 /* Get memory for IPv6 entries. */ 90 BCM_IF_ERROR_RETURN 91 (_bcm_tr_l3_defip_mem_get(unit, BCM_L3_IP6, 0, &mem_v6)); 92 93 /* Initialize IPv6 entries lookup engine. */ 94 if (L3_DEFIPm == mem_v6) { 95 if (mem_v4 != mem_v6) { 96 BCM_IF_ERROR_RETURN(soc_fb_lpm_init(unit)); 97 } 98 } else { 99 BCM_IF_ERROR_RETURN(_bcm_tr_ext_lpm_init(unit, mem_v6)); 100 } 101 102 /* Get memory for IPv6 entries with prefix length > 64. */ 103 BCM_IF_ERROR_RETURN 104 (_bcm_tr_l3_defip_mem_get(unit, BCM_L3_IP6, 105 BCM_XGS3_L3_IPV6_PREFIX_LEN, 106 &mem_v6_128)); 107 108 /* Initialize IPv6 entries lookup engine. */ 109 if (mem_v6 != mem_v6_128) { 110 if (SOC_IS_TD2_TT2(unit)) { 111 return BCM_E_NONE; 112 } 113 #if defined(BCM_KATANA_SUPPORT) 114 ipv6_lpm_128b_enable = 115 soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 0); 116 if (SOC_IS_KATANA(unit) && (ipv6_lpm_128b_enable)) { 117 /* Initialize pair memory for IPv6 entries with prefix length > 64. */ 118 BCM_IF_ERROR_RETURN(_bcm_kt_defip_pair128_init(unit)); 119 BCM_IF_ERROR_RETURN(_bcm_trx_defip_128_init(unit)); 120 } else 121 #endif 122 { 123 BCM_IF_ERROR_RETURN(_bcm_trx_defip_128_init(unit)); 124 } 125 } 126 127 /* Update defip size in l3 book keeping if ESM present */ 128 if (soc_feature(unit, soc_feature_esm_support) && (L3_DEFIPm != mem_v4)) { 129 index_min = soc_mem_index_min(unit, mem_v4); 130 index_max = soc_mem_index_max(unit, mem_v4); 131 BCM_XGS3_L3_DEFIP_TBL_SIZE(unit) = index_max - index_min + 1; 132 } 133 return (BCM_E_NONE); 134 } 135 136 137 /* 138 * Function: 139 * _bcm_tr_defip_deinit 140 * Purpose: 141 * De-initialize L3 DEFIP table for triumph devices. 142 * Parameters: 143 * unit - (IN) SOC unit number. 144 * Returns: 145 * BCM_E_XXX 146 */ 147 int 148 _bcm_tr_defip_deinit(int unit) 149 { 150 soc_mem_t mem_v4; /* IPv4 Route table memory. */ 151 soc_mem_t mem_v6; /* IPv6 Route table memory. */ 152 soc_mem_t mem_v6_128; /* IPv6 full prefix route table memory. */ 153 #if defined(BCM_KATANA_SUPPORT) 154 int ipv6_lpm_128b_enable; 155 #endif 156 157 /* Get memory for IPv4 entries. */ 158 BCM_IF_ERROR_RETURN(_bcm_tr_l3_defip_mem_get(unit, 0, 0, &mem_v4)); 159 160 /* Initialize IPv4 entries lookup engine. */ 161 if (L3_DEFIPm == mem_v4) { 162 BCM_IF_ERROR_RETURN(soc_fb_lpm_deinit(unit)); 163 } else { 164 BCM_IF_ERROR_RETURN(_bcm_tr_ext_lpm_deinit(unit, mem_v4)); 165 } 166 167 /* Get memory for IPv6 entries. */ 168 BCM_IF_ERROR_RETURN 169 (_bcm_tr_l3_defip_mem_get(unit, BCM_L3_IP6, 0, &mem_v6)); 170 171 /* Initialize IPv6 entries lookup engine. */ 172 if ((L3_DEFIPm == mem_v6) && (mem_v4 != mem_v6)) { 173 BCM_IF_ERROR_RETURN(soc_fb_lpm_deinit(unit)); 174 } else { 175 BCM_IF_ERROR_RETURN(_bcm_tr_ext_lpm_deinit(unit, mem_v6)); 176 } 177 178 /* Get memory for IPv6 entries with prefix length > 64. */ 179 BCM_IF_ERROR_RETURN 180 (_bcm_tr_l3_defip_mem_get(unit, BCM_L3_IP6, 181 BCM_XGS3_L3_IPV6_PREFIX_LEN, 182 &mem_v6_128)); 183 184 /* Initialize IPv6 entries lookup engine. */ 185 if (mem_v6 != mem_v6_128) { 186 #if defined(BCM_KATANA_SUPPORT) 187 ipv6_lpm_128b_enable = 188 soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 0); 189 if (SOC_IS_KATANA(unit) && (ipv6_lpm_128b_enable)) { 190 BCM_IF_ERROR_RETURN(_bcm_kt_defip_pair128_deinit(unit)); 191 BCM_IF_ERROR_RETURN(_bcm_trx_defip_128_deinit(unit)); 192 } else 193 #endif 194 { 195 BCM_IF_ERROR_RETURN(_bcm_trx_defip_128_deinit(unit)); 196 } 197 } 198 return (BCM_E_NONE); 199 } 200 201 /* 202 * Function: 203 * _bcm_tr_l3_ingress_interface_get 204 * Purpose: 205 * Get ingress interface config. 206 * Parameters: 207 * unit - (IN) BCM unit number. 208 * hw_entry - (IN) Entry data of the specified index. 209 * iif - (IN) Interface configuration. 210 * Returns: 211 * BCM_E_XXX. 212 */ 213 int 214 _bcm_tr_l3_ingress_interface_get(int unit, 215 iif_entry_t *hw_entry, 216 _bcm_l3_ingress_intf_t *iif) 217 { 218 219 #ifdef BCM_TRIDENT2_SUPPORT 220 uint32 index; 221 void *entries[1]; 222 iif_profile_entry_t l3_iif_profile; 223 int hw_idx; 224 #endif 225 iif_entry_t entry; /* HW entry buffer. */ 226 int intf_id; /* Interface id. */ 227 int rv = BCM_E_NONE; /* Operation return status.*/ 228 int hw_map_idx=0; 229 int no_trust_idx=0; 230 int bit_num = 0; 231 int vrf_valid = 1; 232 #ifdef BCM_TOMAHAWK3_SUPPORT 233 uint8 int_flag = 0; 234 #endif 235 236 /* Input parameters sanity check. */ 237 if (NULL == iif) { 238 return (BCM_E_PARAM); 239 } 240 if ((iif->intf_id > soc_mem_index_max(unit, L3_IIFm)) || 241 (iif->intf_id < soc_mem_index_min(unit, L3_IIFm))) { 242 return (BCM_E_PARAM); 243 } 244 245 intf_id = iif->intf_id; 246 sal_memset(iif, 0, sizeof(_bcm_l3_ingress_intf_t)); 247 sal_memcpy(&entry, soc_mem_entry_null(unit, L3_IIFm), 248 sizeof(iif_entry_t)); 249 250 /* if H/W Entry pointer is valid, do not read 251 * This is done to speed up time by avoiding PIO reads for 252 * individual entries */ 253 if (NULL != hw_entry) { 254 sal_memcpy(&entry, hw_entry, sizeof(iif_entry_t)); 255 } else { 256 257 /* Read interface config from hw. */ 258 rv = soc_mem_read(unit, L3_IIFm, MEM_BLOCK_ANY, intf_id, (uint32 *)&entry); 259 BCM_IF_ERROR_RETURN(rv); 260 } 261 262 /* Get class id value. */ 263 if (soc_mem_field_valid(unit, L3_IIFm, CLASS_IDf)) { 264 iif->if_class = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry, CLASS_IDf); 265 } 266 267 /* Get vrf id value. */ 268 if (soc_mem_field_valid(unit, L3_IIFm, VRFf)) { 269 iif->vrf = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry, VRFf); 270 } 271 272 if (soc_mem_field_valid(unit, L3_IIFm, VRF_VALIDf)) { 273 vrf_valid = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry, VRF_VALIDf); 274 } 275 276 if (vrf_valid == 0) { 277 iif->vrf = BCM_L3_VRF_INVALID; 278 } 279 280 /* Get vrf id value. */ 281 if (soc_mem_field_valid(unit, L3_IIFm, ALLOW_GLOBAL_ROUTEf)) { 282 if (1 == soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry, 283 ALLOW_GLOBAL_ROUTEf)) { 284 iif->flags |= BCM_L3_INGRESS_GLOBAL_ROUTE; 285 } 286 } 287 288 #ifdef BCM_TOMAHAWK3_SUPPORT 289 if (soc_feature(unit, soc_feature_inband_network_telemetry)) { 290 int_flag = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry, 291 INT_ENABLEf); 292 if (int_flag) { 293 iif->flags |= BCM_L3_INGRESS_INT; 294 } 295 } 296 #endif 297 298 299 #ifdef BCM_TRIDENT2_SUPPORT 300 if (SOC_IS_TD2_TT2(unit)) { /* Get l3 iif profile entry */ 301 entries[0] = &l3_iif_profile; 302 index = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry, 303 L3_IIF_PROFILE_INDEXf); 304 (void)_bcm_l3_iif_profile_entry_get(unit, index, 1, entries); 305 /* Get vrf id value. */ 306 if (soc_mem_field32_get(unit, L3_IIF_PROFILEm, 307 &l3_iif_profile, ALLOW_GLOBAL_ROUTEf)) { 308 iif->flags |= BCM_L3_INGRESS_GLOBAL_ROUTE; 309 } 310 311 if (soc_mem_field_valid(unit, L3_IIF_PROFILEm, URPF_DEFAULTROUTECHECKf)) { 312 313 if (soc_mem_field32_get(unit, L3_IIF_PROFILEm, 314 &l3_iif_profile, URPF_DEFAULTROUTECHECKf)) { 315 iif->flags |= BCM_L3_INGRESS_URPF_DEFAULT_ROUTE_CHECK; 316 } 317 } 318 319 if (0 == soc_mem_field32_get(unit, L3_IIF_PROFILEm, 320 &l3_iif_profile, IPV4L3_ENABLEf)) { 321 iif->flags |= BCM_L3_INGRESS_ROUTE_DISABLE_IP4_UCAST; 322 } 323 324 if (0 == soc_mem_field32_get(unit, L3_IIF_PROFILEm, 325 &l3_iif_profile, IPMCV4_ENABLEf)) { 326 iif->flags |= BCM_L3_INGRESS_ROUTE_DISABLE_IP4_MCAST; 327 } 328 329 if (0 == soc_mem_field32_get(unit, L3_IIF_PROFILEm, 330 &l3_iif_profile, IPV6L3_ENABLEf)) { 331 iif->flags |= BCM_L3_INGRESS_ROUTE_DISABLE_IP6_UCAST; 332 } 333 334 if (0 == soc_mem_field32_get(unit, L3_IIF_PROFILEm, 335 &l3_iif_profile, IPMCV6_ENABLEf)) { 336 iif->flags |= BCM_L3_INGRESS_ROUTE_DISABLE_IP6_MCAST; 337 } 338 339 if (soc_mem_field32_get(unit, L3_IIF_PROFILEm, 340 &l3_iif_profile, UNKNOWN_IPV4_MC_TOCPUf)) { 341 iif->flags |= BCM_L3_INGRESS_UNKNOWN_IP4_MCAST_TOCPU; 342 } 343 344 if (soc_mem_field32_get(unit, L3_IIF_PROFILEm, 345 &l3_iif_profile, UNKNOWN_IPV6_MC_TOCPUf)) { 346 iif->flags |= BCM_L3_INGRESS_UNKNOWN_IP6_MCAST_TOCPU; 347 } 348 349 #ifdef BCM_TOMAHAWK_SUPPORT 350 if (soc_mem_field_valid(unit, L3_IIF_PROFILEm, IPMC_MISS_AS_L2MCf)) { 351 if (soc_mem_field32_get(unit, L3_IIF_PROFILEm, 352 &l3_iif_profile, IPMC_MISS_AS_L2MCf)) { 353 iif->flags |= BCM_L3_INGRESS_UNKNOWN_IPMC_AS_L2MC; 354 } 355 } 356 #endif 357 358 if (soc_mem_field32_get(unit, L3_IIF_PROFILEm, 359 &l3_iif_profile, ICMP_REDIRECT_TOCPUf)) { 360 iif->flags |= BCM_L3_INGRESS_ICMP_REDIRECT_TOCPU; 361 } 362 363 if (soc_mem_field32_get(unit, L3_IIF_PROFILEm, 364 &l3_iif_profile, L3_OVERRIDE_IPMC_DO_VLANf)) { 365 iif->flags |= BCM_L3_INGRESS_IPMC_DO_VLAN_DISABLE; 366 } 367 368 /* Retrieve IP option Profile Index */ 369 if (soc_feature(unit, soc_feature_l3_ip4_options_profile)) { 370 hw_idx = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry, 371 IP_OPTION_PROFILE_INDEXf); 372 hw_idx <<= _BCM_TD2_IP_OPTIONS_BITS_WIDTH; 373 hw_idx &= _BCM_TD2_IP_OPTIONS_PROFILE_MASK; 374 BCM_IF_ERROR_RETURN( 375 _bcm_td2_l3_ip4_options_profile_idx2id( 376 unit, hw_idx, &(iif->ip4_options_profile_id))); 377 } 378 if (soc_feature(unit, soc_feature_nat) && 379 SOC_MEM_FIELD_VALID(unit, L3_IIFm, SRC_REALM_IDf)) { 380 /* Get the nat source realm id value. */ 381 iif->nat_realm_id = soc_mem_field32_get(unit, L3_IIFm, 382 (uint32 *)&entry, SRC_REALM_IDf); 383 } 384 } 385 #endif 386 387 /* Get Trust QoS Map Id Value. */ 388 if (soc_mem_field_valid(unit, L3_IIFm, TRUST_DSCP_PTRf)) { 389 hw_map_idx = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry, 390 TRUST_DSCP_PTRf); 391 } 392 #ifdef BCM_TRIDENT2_SUPPORT 393 if (SOC_IS_TD2_TT2(unit)) { 394 hw_map_idx = soc_mem_field32_get(unit, L3_IIF_PROFILEm, 395 &l3_iif_profile, TRUST_DSCP_PTRf); 396 } 397 #endif 398 if (BCM_VLAN_INVALID > iif->intf_id) { 399 if (soc_mem_field_valid(unit, L3_IIFm, TRUST_DSCP_PTRf)) { 400 bit_num = soc_mem_field_length(unit, L3_IIFm, TRUST_DSCP_PTRf); 401 switch (bit_num) { 402 case _BCM_TR_L3_TRUST_DSCP_PTR_BIT_SIZE: 403 /* DSCP_TABLE size vary across Chariot and Enduro, but Do not trust value is identical */ 404 no_trust_idx = 63; 405 break; 406 case _BCM_TD_L3_TRUST_DSCP_PTR_BIT_SIZE: 407 /* Trident and Triumph3 */ 408 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_GREYHOUND2(unit)) { 409 no_trust_idx = 127; 410 } else { 411 no_trust_idx = 0; 412 } 413 break; 414 default: 415 break; 416 } 417 } 418 #ifdef BCM_TRIDENT2_SUPPORT 419 if (SOC_IS_TD2_TT2(unit)) { 420 no_trust_idx = 127; 421 } 422 #endif 423 } else { 424 /* for iif->intf_id > 4096 condition */ 425 if (soc_mem_field_valid(unit, L3_IIFm, TRUST_DSCP_PTRf)) { 426 bit_num = soc_mem_field_length(unit, L3_IIFm, TRUST_DSCP_PTRf); 427 switch (bit_num) { 428 case _BCM_TR_L3_TRUST_DSCP_PTR_BIT_SIZE: 429 /* DSCP_TABLE size vary across Chariot and Enduro, but Do not trust value is identical */ 430 no_trust_idx = 63; 431 break; 432 case _BCM_TD_L3_TRUST_DSCP_PTR_BIT_SIZE: 433 /* Trident and Triumph3 */ 434 no_trust_idx = 127; 435 break; 436 default: 437 break; 438 } 439 } 440 #ifdef BCM_TRIDENT2_SUPPORT 441 if (SOC_IS_TD2_TT2(unit)) { 442 no_trust_idx = ((soc_mem_index_count(unit, DSCP_TABLEm) / 64)) - 1; 443 } 444 #endif 445 } 446 447 if (hw_map_idx != no_trust_idx) { 448 if (SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit)) { 449 rv = _bcm_tr_qos_idx2id(unit, hw_map_idx, 0x3, 450 &iif->qos_map_id); 451 } else { 452 #ifdef BCM_TRIUMPH2_SUPPORT 453 rv = _bcm_tr2_qos_idx2id(unit, hw_map_idx, 0x3, 454 &iif->qos_map_id); 455 #endif /*BCM_TRIUMPH2_SUPPORT*/ 456 } 457 if (BCM_SUCCESS(rv) && (iif->qos_map_id != 0)) { 458 iif->flags |= BCM_L3_INGRESS_DSCP_TRUST; 459 } 460 } else { 461 iif->qos_map_id = 0; 462 } 463 464 #ifdef BCM_TRIUMPH2_SUPPORT 465 if (soc_mem_field_valid(unit, L3_IIFm, IPMC_L3_IIFf)) { 466 iif->ipmc_intf_id = 467 soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry, IPMC_L3_IIFf); 468 } 469 #endif /* BCM_TRIUMPH2_SUPPORT */ 470 471 #ifdef BCM_GREYHOUND2_SUPPORT 472 if (soc_mem_field_valid(unit, L3_IIFm, ICMP_REDIRECT_TO_CPUf)) { 473 if (soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry, 474 ICMP_REDIRECT_TO_CPUf)) { 475 iif->flags |= BCM_L3_INGRESS_ICMP_REDIRECT_TOCPU; 476 } 477 } 478 #endif /* BCM_GREYHOUND2_SUPPORT */ 479 480 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 481 if (soc_mem_field_valid(unit, L3_IIFm, URPF_DEFAULTROUTECHECKf)) { 482 if (1 == soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry, 483 URPF_DEFAULTROUTECHECKf)) { 484 iif->flags |= BCM_L3_INGRESS_URPF_DEFAULT_ROUTE_CHECK; 485 } 486 } 487 if (soc_mem_field_valid(unit, L3_IIFm, URPF_MODEf)) { 488 iif->urpf_mode = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry, 489 URPF_MODEf); 490 } 491 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */ 492 493 #ifdef BCM_TRIDENT2_SUPPORT 494 if (SOC_IS_TD2_TT2(unit)) { 495 if (1 == soc_mem_field32_get(unit, L3_IIF_PROFILEm, 496 &l3_iif_profile, 497 ALLOW_GLOBAL_ROUTEf)) { 498 iif->flags |= BCM_L3_INGRESS_GLOBAL_ROUTE; 499 } 500 if (soc_mem_field_valid(unit, L3_IIF_PROFILEm, URPF_DEFAULTROUTECHECKf)) { 501 if (1 == soc_mem_field32_get(unit, L3_IIF_PROFILEm, 502 &l3_iif_profile, 503 URPF_DEFAULTROUTECHECKf)) { 504 iif->flags |= BCM_L3_INGRESS_URPF_DEFAULT_ROUTE_CHECK; 505 } 506 iif->urpf_mode = soc_mem_field32_get(unit, L3_IIF_PROFILEm, 507 &l3_iif_profile, URPF_MODEf); 508 } 509 } 510 #endif 511 #ifdef BCM_TOMAHAWK_SUPPORT 512 if (soc_mem_field_valid(unit, L3_IIFm, ECN_DECAP_MAPPING_PTRf)) { 513 iif->tunnel_term_ecn_map_id = 514 soc_mem_field32_get(unit, L3_IIFm, &entry, 515 ECN_DECAP_MAPPING_PTRf); 516 } 517 #endif 518 /* Set interface id. */ 519 iif->intf_id = intf_id; 520 521 return (BCM_E_NONE); 522 } 523 524 #ifdef BCM_TRIDENT2_SUPPORT 525 /* 526 * Function: 527 * _bcm_l3_iif_profile_recover 528 * Purpose: 529 * Add entry into profile index table. 530 * Parameters: 531 * unit - (IN) BCM unit number. 532 * iif - (IN) Interface configuration. 533 * profile_index - (IN) Index into Profile table 534 * Returns: 535 * BCM_E_XXX. 536 */ 537 538 int 539 _bcm_l3_iif_profile_recover(int unit, iif_profile_entry_t *l3_iif_profile, 540 uint8 profile_index) 541 { 542 uint32 index; 543 void *entries[1]; 544 int rv = BCM_E_NONE; 545 546 /* Input parameters sanity check. */ 547 if (NULL == l3_iif_profile) { 548 return (BCM_E_PARAM); 549 } 550 551 entries[0] = l3_iif_profile; 552 index = profile_index; 553 554 /* Create new profile entry if not existent or updating failed */ 555 rv = _bcm_l3_iif_profile_sw_state_set(unit, entries, 1, index); 556 return rv; 557 } 558 559 /* 560 * Function: 561 * _bcm_l3_iif_profile_add 562 * Purpose: 563 * Add entry into profile index table. 564 * Parameters: 565 * unit - (IN) BCM unit number. 566 * iif - (IN) Interface configuration. 567 * profile_index - (OUT) Index into Profile table 568 * Returns: 569 * BCM_E_XXX. 570 */ 571 572 STATIC int 573 _bcm_l3_iif_profile_add(int unit, _bcm_l3_ingress_intf_t *iif, 574 iif_entry_t *iif_hw_entry, 575 uint8 *profile_index) 576 { 577 uint32 index; 578 uint8 value; /* Enable/disable boolean. */ 579 void *entries[1]; 580 iif_entry_t iif_entry; /* HW iif_entry buffer. */ 581 iif_profile_entry_t l3_iif_profile; 582 int hw_map_idx=0; 583 int no_trust_idx=0; 584 int rv = BCM_E_NONE; 585 586 /* Input parameters sanity check. */ 587 if ((NULL == iif) || (NULL == profile_index)) { 588 return (BCM_E_PARAM); 589 } 590 591 *profile_index = 0; 592 593 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) { 594 if (iif_hw_entry) { 595 sal_memcpy(&iif_entry, iif_hw_entry, sizeof(iif_entry_t)); 596 } else { 597 /* Read interface entry from hw. */ 598 rv = soc_mem_read(unit, L3_IIFm, MEM_BLOCK_ANY, iif->intf_id, 599 (uint32 *)&iif_entry); 600 } 601 602 if (SOC_SUCCESS(rv)) { 603 /* Get profile_index from interface entry*/ 604 index = soc_mem_field32_get(unit, L3_IIFm, 605 (uint32 *)&iif_entry, 606 L3_IIF_PROFILE_INDEXf); 607 608 if (iif->profile_flags & _BCM_L3_IIF_PROFILE_DO_NOT_UPDATE) { 609 *profile_index = (uint8)index; 610 return BCM_E_NONE; 611 } 612 } else { 613 LOG_ERROR(BSL_LS_BCM_L3, 614 (BSL_META_U(unit, 615 "Profile Add: soc_mem_read for L3_IIF failed for index=(%d)\n"), 616 iif->intf_id)); 617 return rv; 618 } 619 620 entries[0] = &l3_iif_profile; 621 sal_memset(&l3_iif_profile, 0, sizeof(iif_profile_entry_t)); 622 623 /* Set Trust QoS Map Id Value. */ 624 if (iif->flags & BCM_L3_INGRESS_DSCP_TRUST) { 625 BCM_IF_ERROR_RETURN 626 (_bcm_tr2_qos_id2idx(unit, iif->qos_map_id, &hw_map_idx)); 627 soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile, 628 TRUST_DSCP_PTRf, hw_map_idx); 629 } else { 630 if (BCM_VLAN_INVALID > iif->intf_id) { 631 uint32 dscp_val = 127; 632 #ifdef BCM_TOMAHAWK3_SUPPORT 633 if (SOC_IS_TOMAHAWK3(unit)) { 634 dscp_val = 63; 635 } 636 #endif 637 soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile, 638 TRUST_DSCP_PTRf, dscp_val); 639 } else { 640 /* Trident2 : 7 bit*/ 641 if (SOC_IS_TRIDENT3X(unit)) { 642 /* TD3TBD NOT SURE HOW TD3 handle this, email sent to ARCHI already */ 643 /* TRUST bit still 7 bits - yet we now have 132 ports - follow 644 * equation below will out bound filed TRUST_DSCP_PTR 645 * Hard coded to 127 according to reg file for now. 646 */ 647 no_trust_idx = ((soc_mem_index_count(unit, PHB_MAPPING_TBL_2m) / 64)) - 1; 648 no_trust_idx = 127; 649 } else { 650 no_trust_idx = ((soc_mem_index_count(unit, DSCP_TABLEm) / 64)) - 1; 651 } 652 soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile, 653 TRUST_DSCP_PTRf, no_trust_idx); 654 } 655 } 656 657 if (soc_mem_field_valid(unit, L3_IIF_PROFILEm, URPF_DEFAULTROUTECHECKf)) { 658 /* Set URPF. */ 659 value = (iif->flags & 660 BCM_L3_INGRESS_URPF_DEFAULT_ROUTE_CHECK) ? 1 : 0; 661 soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile, 662 URPF_DEFAULTROUTECHECKf, value); 663 soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile, 664 URPF_MODEf, iif->urpf_mode); 665 } 666 667 /* Set enable global route value. */ 668 value = (iif->flags & BCM_L3_INGRESS_GLOBAL_ROUTE) ? 1 : 0; 669 soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile, 670 ALLOW_GLOBAL_ROUTEf, value); 671 672 /* enable IPv4 and IPv6 Unicast and MC */ 673 soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile, 674 IPV4L3_ENABLEf, 675 (iif->flags & BCM_L3_INGRESS_ROUTE_DISABLE_IP4_UCAST) 676 ? 0 : 1); 677 soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile, 678 IPMCV4_ENABLEf, 679 (iif->flags & BCM_L3_INGRESS_ROUTE_DISABLE_IP4_MCAST) 680 ? 0 : 1); 681 soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile, 682 IPV6L3_ENABLEf, 683 (iif->flags & BCM_L3_INGRESS_ROUTE_DISABLE_IP6_UCAST) 684 ? 0 : 1); 685 soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile, 686 IPMCV6_ENABLEf, 687 (iif->flags & BCM_L3_INGRESS_ROUTE_DISABLE_IP6_MCAST) 688 ? 0 : 1); 689 690 /* Set ICMP redirect to CPU */ 691 soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile, 692 ICMP_REDIRECT_TOCPUf, 693 (iif->flags & BCM_L3_INGRESS_ICMP_REDIRECT_TOCPU) 694 ? 1 : 0); 695 696 /* Set Unknown IPMC to CPU */ 697 soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile, 698 UNKNOWN_IPV4_MC_TOCPUf, 699 (iif->flags & BCM_L3_INGRESS_UNKNOWN_IP4_MCAST_TOCPU) 700 ? 1 : 0); 701 702 soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile, 703 UNKNOWN_IPV6_MC_TOCPUf, 704 (iif->flags & BCM_L3_INGRESS_UNKNOWN_IP6_MCAST_TOCPU) 705 ? 1 : 0); 706 707 #ifdef BCM_TOMAHAWK_SUPPORT 708 /* Set Unknown IPMC as L2MC */ 709 if (soc_mem_field_valid(unit, L3_IIF_PROFILEm, IPMC_MISS_AS_L2MCf)) { 710 soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile, 711 IPMC_MISS_AS_L2MCf, 712 (iif->flags & BCM_L3_INGRESS_UNKNOWN_IPMC_AS_L2MC) 713 ? 1 : 0); 714 } 715 #endif 716 717 /* set L3_OVERRIDE_IPMC_DO_VLAN */ 718 soc_mem_field32_set(unit, L3_IIF_PROFILEm, &l3_iif_profile, 719 L3_OVERRIDE_IPMC_DO_VLANf, 720 (iif->flags & BCM_L3_INGRESS_IPMC_DO_VLAN_DISABLE) 721 ? 1 : 0); 722 723 if (BCM_SUCCESS(rv)) { 724 /* If profile entry exist and not shared, update it */ 725 rv = _bcm_l3_iif_profile_entry_update(unit, entries, &index); 726 if (BCM_SUCCESS(rv)) { 727 *profile_index = (uint8)index; 728 return BCM_E_NONE; 729 } 730 } 731 732 /* Create new profile entry if not existent or updating failed */ 733 rv = _bcm_l3_iif_profile_entry_add(unit, entries, 1, &index); 734 if (BCM_SUCCESS(rv)) { 735 *profile_index = (uint8)index; 736 } 737 } 738 return rv; 739 740 } 741 #endif /* BCM_TRIDENT2_SUPPORT */ 742 743 744 /* 745 * Function: 746 * _bcm_tr_l3_ingress_interface_set 747 * Purpose: 748 * Set ingress interface config. 749 * Parameters: 750 * unit - (IN) BCM unit number. 751 * iif - (IN) Interface configuration. 752 * iif_hw_entry - (IN) H/W entry for specified iif index 753 * hw_copy - (OUT) Updated H/W entry contents to be written 754 * Returns: 755 * BCM_E_XXX. 756 * Note: 757 * For avoiding PIO Reads by this function at init time, 758 * iif_hw_entry and hw_copy arguments should be non null. 759 * iif_hw_entry should contain the contents of current H/W 760 * entry and hw_copy is updated by function with the new 761 * H/W entry data to be written. 762 * Other than Init time the calls to this function may be using 763 * the last 2 arguments as NULL. 764 */ 765 int 766 _bcm_tr_l3_ingress_interface_set(int unit, _bcm_l3_ingress_intf_t *iif, 767 iif_entry_t *iif_hw_entry, 768 iif_entry_t *hw_copy) 769 { 770 iif_entry_t entry, iif_entry; /* HW entry buffer. */ 771 uint8 value = 0; /* Enable/disable boolean. */ 772 #ifdef BCM_TRIDENT2_SUPPORT 773 uint8 old_profile_index = 0; 774 #endif 775 int hw_map_idx=0; 776 int rv = BCM_E_NONE; 777 #if defined(BCM_KATANA_SUPPORT) || \ 778 defined(BCM_TRIUMPH3_SUPPORT) || \ 779 defined(BCM_TRIDENT2_SUPPORT) 780 int rv2 = BCM_E_NONE; 781 #endif 782 #ifdef BCM_TRIUMPH2_SUPPORT 783 int mode=0; 784 #endif 785 int bit_num=0; 786 787 #ifdef BCM_TRIDENT2_SUPPORT 788 int use_hw_copy = 0; 789 #endif 790 #ifdef BCM_TRIDENT3_SUPPORT 791 _bcm_l3_bookkeeping_t *l3; 792 #endif 793 /* Input parameters sanity check. */ 794 if (NULL == iif) { 795 return (BCM_E_PARAM); 796 } 797 if ((iif->intf_id > soc_mem_index_max(unit, L3_IIFm)) || 798 (iif->intf_id < soc_mem_index_min(unit, L3_IIFm))) { 799 return (BCM_E_PARAM); 800 } 801 802 #ifdef BCM_TRIUMPH2_SUPPORT 803 if (soc_mem_field_valid(unit, L3_IIFm, IPMC_L3_IIFf)) { 804 rv = bcm_xgs3_l3_ingress_mode_get(unit, &mode); 805 if (rv < 0) { 806 return rv; 807 } 808 if (mode) { 809 if (!SOC_MEM_FIELD32_VALUE_FIT(unit, L3_IIFm, 810 IPMC_L3_IIFf, iif->ipmc_intf_id)) { 811 return (BCM_E_PARAM); 812 } 813 } else { 814 if (!SOC_MEM_FIELD32_VALUE_FIT(unit, L3_IIFm, 815 IPMC_L3_IIFf, iif->intf_id)) { 816 return (BCM_E_PARAM); 817 } 818 } 819 } 820 #endif /* BCM_TRIUMPH2_SUPPORT */ 821 /* Make sure both hw_copy and iif_entry parameters are same */ 822 if ((iif_hw_entry && !hw_copy) || 823 (!iif_hw_entry && hw_copy)) { 824 return (BCM_E_PARAM); 825 } 826 827 #ifdef BCM_TRIDENT2_SUPPORT 828 if (iif_hw_entry) { 829 use_hw_copy = TRUE; 830 } 831 #endif 832 833 sal_memcpy(&entry, soc_mem_entry_null(unit, L3_IIFm), 834 sizeof(iif_entry_t)); 835 sal_memcpy(&iif_entry, soc_mem_entry_null(unit, L3_IIFm), 836 sizeof(iif_entry_t)); 837 838 /* Set class id value. */ 839 if (SOC_MEM_FIELD_VALID(unit, L3_IIFm, CLASS_IDf)) { 840 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, CLASS_IDf, 841 iif->if_class); 842 } else { 843 /* for device support L3_IIFm without CLASS_IDf 844 * - Allow init value=0 only. 845 * - Return BCM_E_UNAVAIL for other value. 846 */ 847 if (iif->if_class != 0) { 848 return (BCM_E_UNAVAIL); 849 } 850 } 851 852 /* Set vrf id value. */ 853 if (SOC_MEM_FIELD_VALID(unit, L3_IIFm, VRFf)) { 854 855 #ifdef BCM_TRIDENT3_SUPPORT 856 l3 = &_bcm_l3_bk_info[unit]; 857 858 /*VRF_VALID not set during initialization. Set only when called from API */ 859 if (SOC_MEM_FIELD_VALID(unit, L3_IIFm, VRF_VALIDf)) { 860 if (((!(l3->riot_enable)) || SOC_IS_DONE_INIT(unit)) 861 && (iif->vrf != BCM_L3_VRF_INVALID)) { 862 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, VRF_VALIDf, 1); 863 } else { 864 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, VRF_VALIDf, 0); 865 } 866 } 867 #endif 868 if (BCM_L3_VRF_INVALID != iif->vrf) { 869 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, VRFf, iif->vrf); 870 } else { 871 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, VRFf, 0); 872 } 873 } else { 874 /* for device support L3_IIFm without VRFf 875 * - Allow init value=0 only. 876 * - Return BCM_E_UNAVAIL for other value. 877 */ 878 if (iif->vrf != 0) { 879 return (BCM_E_UNAVAIL); 880 } 881 } 882 883 /* Set Trust QoS Map Id Value. */ 884 if (iif->flags & BCM_L3_INGRESS_DSCP_TRUST) { 885 if (SOC_MEM_FIELD_VALID(unit, L3_IIFm, TRUST_DSCP_PTRf)) { 886 if (SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit) || 887 SOC_IS_HURRICANE3(unit)) { 888 BCM_IF_ERROR_RETURN 889 (_bcm_tr_qos_id2idx(unit, iif->qos_map_id, &hw_map_idx)); 890 } else { 891 #ifdef BCM_TRIUMPH2_SUPPORT 892 BCM_IF_ERROR_RETURN 893 (_bcm_tr2_qos_id2idx(unit, iif->qos_map_id, &hw_map_idx)); 894 #endif /* BCM_TRIUMPH2_SUPPORT */ 895 } 896 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 897 TRUST_DSCP_PTRf, hw_map_idx); 898 } 899 } else { 900 if (BCM_VLAN_INVALID > iif->intf_id) { 901 if (soc_mem_field_valid(unit, L3_IIFm, TRUST_DSCP_PTRf)) { 902 bit_num = soc_mem_field_length(unit, L3_IIFm, TRUST_DSCP_PTRf); 903 switch (bit_num) { 904 case _BCM_TR_L3_TRUST_DSCP_PTR_BIT_SIZE: 905 /* DSCP_TABLE size vary across Chariot and Enduro, but Do not trust value is identical */ 906 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 907 TRUST_DSCP_PTRf, 63); 908 break; 909 case _BCM_TD_L3_TRUST_DSCP_PTR_BIT_SIZE: 910 /* Trident and Triumph3 */ 911 912 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_GREYHOUND2(unit)) { 913 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 914 TRUST_DSCP_PTRf, 127); 915 } else { 916 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 917 TRUST_DSCP_PTRf, 0); 918 } 919 break; 920 921 default: 922 break; 923 } 924 } 925 } else { 926 /* case for iif->intf_id >= 4096 */ 927 if (soc_mem_field_valid(unit, L3_IIFm, TRUST_DSCP_PTRf)) { 928 bit_num = soc_mem_field_length(unit, L3_IIFm, TRUST_DSCP_PTRf); 929 switch (bit_num) { 930 case _BCM_TR_L3_TRUST_DSCP_PTR_BIT_SIZE: 931 /* DSCP_TABLE size vary across Chariot and Enduro, but Do not trust value is identical */ 932 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 933 TRUST_DSCP_PTRf, 63); 934 break; 935 case _BCM_TD_L3_TRUST_DSCP_PTR_BIT_SIZE: 936 /* Trident and Triumph3 */ 937 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 938 TRUST_DSCP_PTRf, 127); 939 break; 940 941 default: 942 break; 943 } 944 } 945 } 946 } 947 /* Set identity mapping for IPMC L3 IIF */ 948 #ifdef BCM_TRIUMPH2_SUPPORT 949 if (soc_mem_field_valid(unit, L3_IIFm, IPMC_L3_IIFf)) { 950 rv = bcm_xgs3_l3_ingress_mode_get(unit, &mode); 951 if (rv < 0) { 952 return rv; 953 } 954 if (mode) { 955 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 956 IPMC_L3_IIFf, iif->ipmc_intf_id); 957 } else { 958 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 959 IPMC_L3_IIFf, iif->intf_id); 960 } 961 } 962 #endif /* BCM_TRIUMPH2_SUPPORT */ 963 964 #ifdef BCM_GREYHOUND2_SUPPORT 965 if (soc_mem_field_valid(unit, L3_IIFm, ICMP_REDIRECT_TO_CPUf)) { 966 value = (iif->flags & BCM_L3_INGRESS_ICMP_REDIRECT_TOCPU) ? 1 : 0; 967 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 968 ICMP_REDIRECT_TO_CPUf, value); 969 } 970 #endif /* BCM_GREYHOUND2_SUPPORT */ 971 972 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 973 if (soc_mem_field_valid(unit, L3_IIFm, URPF_DEFAULTROUTECHECKf)) { 974 value = (iif->flags & BCM_L3_INGRESS_URPF_DEFAULT_ROUTE_CHECK) ? 1 : 0; 975 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 976 URPF_DEFAULTROUTECHECKf, value); 977 } 978 if (soc_mem_field_valid(unit, L3_IIFm, URPF_MODEf)) { 979 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 980 URPF_MODEf, iif->urpf_mode); 981 } 982 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */ 983 984 /* Set enable global route value. */ 985 if (soc_mem_field_valid(unit, L3_IIFm, ALLOW_GLOBAL_ROUTEf)) { 986 value = (iif->flags & BCM_L3_INGRESS_GLOBAL_ROUTE) ? 1 : 0; 987 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 988 ALLOW_GLOBAL_ROUTEf, value); 989 } 990 991 #ifdef BCM_TRIDENT2_SUPPORT 992 if (use_hw_copy) { 993 sal_memcpy(&iif_entry, iif_hw_entry, sizeof(iif_entry_t)); 994 995 } else { 996 /* Read interface entry from hw. */ 997 rv2 = soc_mem_read(unit, L3_IIFm, MEM_BLOCK_ANY, iif->intf_id, 998 (uint32 *)&iif_entry); 999 if (SOC_FAILURE(rv2)) { 1000 LOG_ERROR(BSL_LS_BCM_L3, 1001 (BSL_META_U(unit, 1002 "Mem read for L3_IIF failed for index=(%d)\n"), 1003 iif->intf_id)); 1004 return rv2; 1005 } 1006 } 1007 #elif defined (BCM_KATANA_SUPPORT) || defined (BCM_TRIUMPH3_SUPPORT) 1008 /* Read interface entry from hw. */ 1009 rv2 = soc_mem_read(unit, L3_IIFm, MEM_BLOCK_ANY, iif->intf_id, 1010 (uint32 *)&iif_entry); 1011 if (SOC_FAILURE(rv2)) { 1012 LOG_ERROR(BSL_LS_BCM_L3, 1013 (BSL_META_U(unit, 1014 "Mem read for L3_IIF failed for index=(%d)\n"), 1015 iif->intf_id)); 1016 return rv2; 1017 } 1018 #endif 1019 1020 #ifdef BCM_TRIDENT2_SUPPORT 1021 /* TD2 L3_IIF_PROFILE and IP Option Profile*/ 1022 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) { 1023 if (soc_feature(unit, soc_feature_nat) && 1024 SOC_MEM_FIELD_VALID(unit, L3_IIFm, SRC_REALM_IDf)) { 1025 if ((iif->nat_realm_id < 0) || (iif->nat_realm_id > 3)) { 1026 return BCM_E_PARAM; 1027 } 1028 /* Set the nat source realm id value. */ 1029 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, SRC_REALM_IDf, 1030 iif->nat_realm_id); 1031 if (iif->flags & BCM_L3_INGRESS_SRC_DST_NAT_REALM_ID) { 1032 BCM_IF_ERROR_RETURN( 1033 _bcm_td2_nh_nat_id_update_by_l3_iif(unit, iif->intf_id, 1034 iif->nat_realm_id)); 1035 } 1036 } 1037 1038 if (BCM_SUCCESS(rv2)) { 1039 /* Get profile_index from interface entry*/ 1040 old_profile_index = soc_mem_field32_get(unit, L3_IIFm, 1041 (uint32 *)&iif_entry, 1042 L3_IIF_PROFILE_INDEXf); 1043 } 1044 1045 if (use_hw_copy) { 1046 rv = _bcm_l3_iif_profile_add(unit, iif, iif_hw_entry, &value); 1047 } else { 1048 rv = _bcm_l3_iif_profile_add(unit, iif, NULL, &value); 1049 } 1050 1051 if (BCM_FAILURE(rv)) { 1052 return rv; 1053 } 1054 if ((value < soc_mem_index_min(unit, L3_IIF_PROFILEm)) || 1055 (value > soc_mem_index_max(unit, L3_IIF_PROFILEm))) { 1056 return BCM_E_FAIL; 1057 } 1058 if (soc_mem_field_valid(unit, L3_IIFm, L3_IIF_PROFILE_INDEXf)) { 1059 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 1060 L3_IIF_PROFILE_INDEXf, value); 1061 } 1062 1063 /* Program IP option Profile Index */ 1064 if (soc_feature(unit, soc_feature_l3_ip4_options_profile)) { 1065 int index; 1066 1067 /* Get the hardware index for the profile */ 1068 rv = _bcm_td2_l3_ip4_options_profile_id2idx(unit, 1069 iif->ip4_options_profile_id, 1070 &index); 1071 if (BCM_SUCCESS(rv)) { 1072 /* Program the upper 2 bits */ 1073 index &= _BCM_TD2_IP_OPTIONS_PROFILE_MASK; 1074 /* 1075 * COVERITY 1076 * 1077 * The operands don't affect result. It is kept intentionally 1078 * as a defensive default for future development. 1079 */ 1080 /* coverity[result_independent_of_operands] */ 1081 index = index >> _BCM_TD2_IP_OPTIONS_BITS_WIDTH; 1082 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 1083 IP_OPTION_PROFILE_INDEXf, index); 1084 } 1085 } 1086 } 1087 1088 if (soc_feature(unit, soc_feature_pim_bidir) && 1089 SOC_MEM_FIELD_VALID(unit, L3_IIFm, ACTIVE_L3_IIF_PROFILE_INDEXf) && 1090 BCM_SUCCESS(rv2)) { 1091 int active_profile_index = 0; 1092 active_profile_index = soc_mem_field32_get(unit, L3_IIFm, 1093 (uint32 *)&iif_entry, ACTIVE_L3_IIF_PROFILE_INDEXf); 1094 1095 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 1096 ACTIVE_L3_IIF_PROFILE_INDEXf, 1097 active_profile_index); 1098 } 1099 #endif 1100 1101 #if defined(BCM_TOMAHAWK_SUPPORT) 1102 if (soc_feature(unit, soc_feature_ecn_wred) && 1103 soc_mem_field_valid(unit, L3_IIFm, ECN_DECAP_MAPPING_PTRf)) { 1104 if (iif->flags & BCM_L3_INGRESS_TUNNEL_TERM_ECN_MAP) { 1105 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 1106 ECN_DECAP_MAPPING_PTRf, 1107 iif->tunnel_term_ecn_map_id); 1108 } 1109 } 1110 #endif 1111 1112 #ifdef BCM_TOMAHAWK3_SUPPORT 1113 if (soc_feature(unit, soc_feature_inband_network_telemetry)) { 1114 if (iif->flags & BCM_L3_INGRESS_INT) { 1115 rv = soc_mem_read(unit, L3_IIFm, MEM_BLOCK_ANY, iif->intf_id, (uint32 *)&entry); 1116 if (SOC_MEM_FIELD_VALID(unit, L3_IIFm, INT_ENABLEf)) { 1117 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, INT_ENABLEf, 1); 1118 rv = soc_mem_write(unit, L3_IIFm, MEM_BLOCK_ALL, iif->intf_id, (uint32 *)&entry); 1119 BCM_IF_ERROR_RETURN(rv); 1120 } 1121 } 1122 } 1123 #endif 1124 1125 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 1126 if (soc_feature(unit,soc_feature_advanced_flex_counter) && 1127 BCM_SUCCESS(rv2)) { 1128 uint32 flex_ctr_offset_mode, flex_ctr_pool_number, flex_ctr_base_idx; 1129 /* 1 Store the old flex counter */ 1130 BCM_IF_ERROR_RETURN( 1131 _bcm_esw_get_flex_counter_fields_values(unit, iif->intf_id, 1132 L3_IIFm, 1133 &iif_entry, 1134 0, 1135 &flex_ctr_offset_mode, 1136 &flex_ctr_pool_number, 1137 &flex_ctr_base_idx)); 1138 /* 2 Restore flex counter in new entry */ 1139 BCM_IF_ERROR_RETURN( 1140 _bcm_esw_set_flex_counter_fields_values(unit, iif->intf_id, 1141 L3_IIFm, 1142 &entry, 1143 0, 1144 flex_ctr_offset_mode, 1145 flex_ctr_pool_number, 1146 flex_ctr_base_idx)); 1147 } 1148 #endif 1149 1150 #ifdef BCM_TRIDENT2_SUPPORT 1151 if (use_hw_copy) { 1152 /* Need to skip this step */ 1153 } else 1154 #endif 1155 { 1156 /* Write updated entry back to hw.*/ 1157 rv = soc_mem_write(unit, L3_IIFm, MEM_BLOCK_ALL, iif->intf_id, 1158 (uint32 *)&entry); 1159 } 1160 #ifdef BCM_TRIDENT2_SUPPORT 1161 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) { 1162 if (soc_feature(unit, soc_feature_l3_iif_profile)) { 1163 if (BCM_SUCCESS(rv)) { 1164 /* delete old entry if its valid and different than new entry*/ 1165 if ((value != old_profile_index) && old_profile_index) { 1166 _bcm_l3_iif_profile_entry_delete(unit, old_profile_index); 1167 } 1168 } else { 1169 /* if hw write fails for new entry then old entry is still vaild*/ 1170 /* we may have to remove the new entry which was added above. */ 1171 _bcm_l3_iif_profile_entry_delete(unit, value); 1172 } 1173 } 1174 } 1175 #endif 1176 1177 #ifdef BCM_TRIDENT2_SUPPORT 1178 /* Update the entry copy if hw_entry is used */ 1179 if (use_hw_copy) { 1180 sal_memcpy(hw_copy, &entry, sizeof(iif_entry_t)); 1181 } 1182 #endif 1183 1184 return rv; 1185 } 1186 1187 /* 1188 * Function: 1189 * _bcm_tr_l3_ingress_interface_clr 1190 * Purpose: 1191 * Set ingress interface config. 1192 * Parameters: 1193 * unit - (IN) BCM unit number. 1194 * iif - (IN) Interface configuration. 1195 * Returns: 1196 * BCM_E_XXX. 1197 */ 1198 int 1199 _bcm_tr_l3_ingress_interface_clr(int unit, int intf_id) 1200 { 1201 int bit_num; 1202 iif_entry_t entry; /* HW entry buffer. */ 1203 #ifdef BCM_TRIDENT2_SUPPORT 1204 uint8 index; 1205 int ref_cnt = 0; 1206 #endif /* BCM_TRIDENT2_SUPPORT */ 1207 1208 /* Input parameters sanity check. */ 1209 if ((intf_id > soc_mem_index_max(unit, L3_IIFm)) || 1210 (intf_id < soc_mem_index_min(unit, L3_IIFm))) { 1211 return (BCM_E_PARAM); 1212 } 1213 #ifdef BCM_TRIDENT2_SUPPORT 1214 if (SOC_IS_TD2_TT2(unit)) { 1215 BCM_IF_ERROR_RETURN( 1216 soc_mem_read(unit, L3_IIFm, MEM_BLOCK_ANY, intf_id, (uint32 *)&entry)); 1217 index = soc_mem_field32_get(unit, L3_IIFm, (uint32 *)&entry, 1218 L3_IIF_PROFILE_INDEXf); 1219 /* Since there will be 1:1 mapping for 4k vlans to ingress L3_IIF, 1220 * all these 4k vlans will be mapped to default L3_IIF_PROFILE index 0. 1221 * So, this default entry should be removed only when ref_cnt of profile 1222 * index 0 is greater than 4k. 1223 */ 1224 if (!index) { 1225 (void)_bcm_l3_iif_profile_entry_reference_get(unit, index, 1226 &ref_cnt); 1227 if (ref_cnt > BCM_VLAN_COUNT) { 1228 (void)_bcm_l3_iif_profile_entry_delete(unit, index); 1229 } 1230 } else { 1231 (void)_bcm_l3_iif_profile_entry_delete(unit, index); 1232 } 1233 } 1234 #endif 1235 1236 /* Restore the IIF entry to its defaults */ 1237 sal_memcpy(&entry, soc_mem_entry_null(unit, L3_IIFm), 1238 sizeof(iif_entry_t)); 1239 1240 if (BCM_XGS3_L3_INGRESS_INTF_MAP_MODE_ISSET(unit)) { 1241 /* 1242 * When BCM_XGS3_L3_INGRESS_INTF_MAP_MODE_ISSET, 1243 * the application is expected to have a complete control of 1244 * l3_iif and the mapping between l3_iif and vlan. 1245 */ 1246 1247 if (soc_feature(unit, soc_feature_l3_iif_under_4k) && 1248 soc_mem_field_valid(unit, L3_IIFm, TRUST_DSCP_PTRf)) { 1249 bit_num = soc_mem_field_length(unit, L3_IIFm, TRUST_DSCP_PTRf); 1250 /* max value for TRUST_DSCP_PTRf is special value as inactive */ 1251 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 1252 TRUST_DSCP_PTRf, ((1 << bit_num) - 1)); 1253 } 1254 1255 return soc_mem_write(unit, L3_IIFm, MEM_BLOCK_ALL, intf_id, 1256 (uint32 *)&entry); 1257 } 1258 1259 /* Set enable global route value. */ 1260 if (soc_mem_field_valid(unit, L3_IIFm, ALLOW_GLOBAL_ROUTEf)) { 1261 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 1262 ALLOW_GLOBAL_ROUTEf, 1); 1263 } 1264 1265 /* Set identity mapping for IPMC L3 IIF */ 1266 #ifdef BCM_TRIUMPH2_SUPPORT 1267 if (soc_mem_field_valid(unit, L3_IIFm, IPMC_L3_IIFf)) { 1268 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 1269 IPMC_L3_IIFf, intf_id); 1270 } 1271 #endif /* BCM_TRIUMPH2_SUPPORT */ 1272 1273 #ifdef BCM_GREYHOUND2_SUPPORT 1274 if (soc_mem_field_valid(unit, L3_IIFm, ICMP_REDIRECT_TO_CPUf)) { 1275 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 1276 ICMP_REDIRECT_TO_CPUf, 0); 1277 } 1278 #endif /* BCM_GREYHOUND2_SUPPORT */ 1279 1280 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 1281 if (soc_mem_field_valid(unit, L3_IIFm, URPF_DEFAULTROUTECHECKf)) { 1282 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 1283 URPF_DEFAULTROUTECHECKf, 1); 1284 } 1285 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */ 1286 1287 /* Set appropriate default TRUST_DSCP_PTR mapping */ 1288 if (soc_mem_field_valid(unit, L3_IIFm, TRUST_DSCP_PTRf)) { 1289 bit_num = soc_mem_field_length(unit, L3_IIFm, TRUST_DSCP_PTRf); 1290 1291 switch (bit_num) { 1292 case _BCM_TR_L3_TRUST_DSCP_PTR_BIT_SIZE: 1293 /* DSCP_TABLE size vary across Chariot and Enduro, 1294 * but Do not trust value is identical */ 1295 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 1296 TRUST_DSCP_PTRf, 63); 1297 break; 1298 case _BCM_TD_L3_TRUST_DSCP_PTR_BIT_SIZE: 1299 /* Trident and Triumph3 */ 1300 if ((BCM_VLAN_INVALID < intf_id) || SOC_IS_TRIUMPH3(unit)) { 1301 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 1302 TRUST_DSCP_PTRf, 127); 1303 } else { 1304 /* For Trident, if intf_id < BCM_VLAN_INVALID */ 1305 soc_mem_field32_set(unit, L3_IIFm, (uint32 *)&entry, 1306 TRUST_DSCP_PTRf, 0); 1307 } 1308 break; 1309 default: 1310 break; 1311 } 1312 } 1313 1314 /* Write updated entry back to hw.*/ 1315 return soc_mem_write(unit, L3_IIFm, MEM_BLOCK_ALL, intf_id, 1316 (uint32 *)&entry); 1317 } 1318 1319 /* 1320 * Function: 1321 * _bcm_tr_l3_intf_class_set 1322 * Purpose: 1323 * Set classigication class to the interface. 1324 * Parameters: 1325 * unit - (IN) SOC unit number. 1326 * vid - (IN) vlan id. 1327 * intf_class - (IN) Interface class id. 1328 * Returns: 1329 * BCM_E_XXX. 1330 */ 1331 int 1332 _bcm_tr_l3_intf_class_set(int unit, bcm_vlan_t vid, uint32 intf_class) 1333 { 1334 _bcm_l3_ingress_intf_t iif; /* Ingress interface config.*/ 1335 int ret_val; /* Operation return value. */ 1336 1337 /* Input parameters sanity check. */ 1338 if ((vid > soc_mem_index_max(unit, L3_IIFm)) || 1339 (vid < soc_mem_index_min(unit, L3_IIFm))) { 1340 return (BCM_E_PARAM); 1341 } 1342 1343 if (intf_class> SOC_INTF_CLASS_MAX(unit)) { 1344 return (BCM_E_PARAM); 1345 } 1346 1347 iif.intf_id = vid; 1348 soc_mem_lock(unit, L3_IIFm); 1349 1350 ret_val = _bcm_tr_l3_ingress_interface_get(unit, NULL, &iif); 1351 if (BCM_FAILURE(ret_val)) { 1352 soc_mem_unlock(unit, L3_IIFm); 1353 return (ret_val); 1354 } 1355 1356 iif.if_class = intf_class; 1357 #if defined(BCM_TRIDENT2_SUPPORT) 1358 if (soc_feature(unit, soc_feature_l3_iif_profile)) { 1359 iif.profile_flags |= _BCM_L3_IIF_PROFILE_DO_NOT_UPDATE; 1360 } 1361 #endif /* BCM_TRIDENT2_SUPPORT */ 1362 ret_val = _bcm_tr_l3_ingress_interface_set(unit, &iif, NULL, NULL); 1363 1364 soc_mem_unlock(unit, L3_IIFm); 1365 1366 return (ret_val); 1367 } 1368 1369 /* 1370 * Function: 1371 * _bcm_tr_l3_intf_global_route_enable_get 1372 * Purpose: 1373 * Get the global route enable flag for the specified L3 interface 1374 * Parameters: 1375 * unit - (IN)SOC unit number. 1376 * vid - (IN)Vlan id. 1377 * enable - (OUT)enable. 1378 * Returns: 1379 * BCM_E_XXX. 1380 */ 1381 int 1382 _bcm_tr_l3_intf_global_route_enable_get(int unit, bcm_vlan_t vid, int *enable) 1383 { 1384 _bcm_l3_ingress_intf_t iif; /* Ingress interface config.*/ 1385 1386 /* Input parameters sanity check. */ 1387 if ((vid > soc_mem_index_max(unit, L3_IIFm)) || 1388 (vid < soc_mem_index_min(unit, L3_IIFm))) { 1389 return (BCM_E_PARAM); 1390 } 1391 1392 iif.intf_id = vid; 1393 1394 BCM_IF_ERROR_RETURN(_bcm_tr_l3_ingress_interface_get(unit, NULL, &iif)); 1395 1396 *enable = (iif.flags & BCM_L3_INGRESS_GLOBAL_ROUTE) ? 1 : 0; 1397 return (BCM_E_NONE); 1398 } 1399 1400 /* 1401 * Function: 1402 * _bcm_tr_l3_intf_global_route_enable_set 1403 * Purpose: 1404 * Set global route enable flag for the L3 interface. 1405 * Parameters: 1406 * unit - (IN)SOC unit number. 1407 * vid - (IN)Vlan id. 1408 * enable - (IN)Enable. 1409 * Returns: 1410 * BCM_E_XXX. 1411 */ 1412 int 1413 _bcm_tr_l3_intf_global_route_enable_set(int unit, bcm_vlan_t vid, int enable) 1414 { 1415 _bcm_l3_ingress_intf_t iif; /* Ingress interface config.*/ 1416 int ret_val; /* Operation return value. */ 1417 1418 /* Input parameters sanity check. */ 1419 if ((vid > soc_mem_index_max(unit, L3_IIFm)) || 1420 (vid < soc_mem_index_min(unit, L3_IIFm))) { 1421 return (BCM_E_PARAM); 1422 } 1423 1424 iif.intf_id = vid; 1425 soc_mem_lock(unit, L3_IIFm); 1426 1427 ret_val = _bcm_tr_l3_ingress_interface_get(unit, NULL, &iif); 1428 if (BCM_FAILURE(ret_val)) { 1429 soc_mem_unlock(unit, L3_IIFm); 1430 return (ret_val); 1431 } 1432 1433 if (enable) { 1434 iif.flags |= BCM_L3_INGRESS_GLOBAL_ROUTE; 1435 } else { 1436 iif.flags &= ~BCM_L3_INGRESS_GLOBAL_ROUTE; 1437 } 1438 1439 ret_val = _bcm_tr_l3_ingress_interface_set(unit, &iif, NULL, NULL); 1440 1441 soc_mem_unlock(unit, L3_IIFm); 1442 1443 return (ret_val); 1444 } 1445 1446 #if defined (BCM_TRIDENT2_SUPPORT) 1447 /* 1448 * Function: 1449 * _bcm_tr_l3_intf_nat_realm_id_get 1450 * Purpose: 1451 * Get the src_realm_id for the specified L3 interface 1452 * Parameters: 1453 * unit - (IN)SOC unit number. 1454 * vid - (IN)Vlan id. 1455 * nat_realm_id - (OUT)realm_id. 1456 * Returns: 1457 * BCM_E_XXX. 1458 */ 1459 int 1460 _bcm_tr_l3_intf_nat_realm_id_get(int unit, bcm_vlan_t vid, int *realm_id) 1461 { 1462 _bcm_l3_ingress_intf_t iif; /* Ingress interface config.*/ 1463 1464 if (!soc_feature(unit, soc_feature_nat)) { 1465 return BCM_E_UNAVAIL; 1466 } 1467 1468 /* Input parameters sanity check. */ 1469 if ((vid > soc_mem_index_max(unit, L3_IIFm)) || 1470 (vid < soc_mem_index_min(unit, L3_IIFm))) { 1471 return (BCM_E_PARAM); 1472 } 1473 1474 iif.intf_id = vid; 1475 1476 BCM_IF_ERROR_RETURN(_bcm_tr_l3_ingress_interface_get(unit, NULL, &iif)); 1477 1478 *realm_id = iif.nat_realm_id; 1479 return (BCM_E_NONE); 1480 } 1481 1482 /* 1483 * Function: 1484 * _bcm_tr_l3_intf_nat_realm_id_set 1485 * Purpose: 1486 * Bind interface to the VRF & update if info. 1487 * Parameters: 1488 * unit - (IN)SOC unit number. 1489 * vid - (IN)Vlan id. 1490 * vrf - (OUT)Vrf. 1491 * Returns: 1492 * BCM_E_XXX. 1493 */ 1494 int 1495 _bcm_tr_l3_intf_nat_realm_id_set(int unit, bcm_vlan_t vid, int realm_id) 1496 { 1497 _bcm_l3_ingress_intf_t iif; /* Ingress interface config.*/ 1498 int ret_val; /* Operation return value. */ 1499 1500 if (!soc_feature(unit, soc_feature_nat)) { 1501 return BCM_E_UNAVAIL; 1502 } 1503 1504 /* Input parameters sanity check. */ 1505 if ((vid > soc_mem_index_max(unit, L3_IIFm)) || 1506 (vid < soc_mem_index_min(unit, L3_IIFm))) { 1507 return (BCM_E_PARAM); 1508 } 1509 1510 if ((realm_id < 0) || (realm_id > 3)) { 1511 return (BCM_E_PARAM); 1512 } 1513 1514 iif.intf_id = vid; 1515 soc_mem_lock(unit, L3_IIFm); 1516 1517 ret_val = _bcm_tr_l3_ingress_interface_get(unit, NULL, &iif); 1518 if (BCM_FAILURE(ret_val)) { 1519 soc_mem_unlock(unit, L3_IIFm); 1520 return (ret_val); 1521 } 1522 1523 iif.nat_realm_id = realm_id; 1524 if (soc_feature(unit, soc_feature_l3_iif_profile)) { 1525 iif.profile_flags |= _BCM_L3_IIF_PROFILE_DO_NOT_UPDATE; 1526 } 1527 1528 ret_val = _bcm_tr_l3_ingress_interface_set(unit, &iif, NULL, NULL); 1529 1530 soc_mem_unlock(unit, L3_IIFm); 1531 1532 return (ret_val); 1533 } 1534 #endif /* BCM_TRIDENT2_SUPPORT */ 1535 1536 1537 /* 1538 * Function: 1539 * _bcm_tr_l3_intf_vrf_get 1540 * Purpose: 1541 * Get the VRF,flags info for the specified L3 interface 1542 * Parameters: 1543 * unit - (IN)SOC unit number. 1544 * vid - (IN)Vlan id. 1545 * vrf - (OUT)Vrf. 1546 * Returns: 1547 * BCM_E_XXX. 1548 */ 1549 int 1550 _bcm_tr_l3_intf_vrf_get(int unit, bcm_vlan_t vid, bcm_vrf_t *vrf) 1551 { 1552 _bcm_l3_ingress_intf_t iif; /* Ingress interface config.*/ 1553 1554 /* Input parameters sanity check. */ 1555 if ((vid > soc_mem_index_max(unit, L3_IIFm)) || 1556 (vid < soc_mem_index_min(unit, L3_IIFm))) { 1557 return (BCM_E_PARAM); 1558 } 1559 1560 iif.intf_id = vid; 1561 1562 BCM_IF_ERROR_RETURN(_bcm_tr_l3_ingress_interface_get(unit, NULL, &iif)); 1563 1564 *vrf = iif.vrf; 1565 return (BCM_E_NONE); 1566 } 1567 1568 /* 1569 * Function: 1570 * _bcm_tr_l3_intf_vrf_bind 1571 * Purpose: 1572 * Bind interface to the VRF & update if info. 1573 * Parameters: 1574 * unit - (IN)SOC unit number. 1575 * vid - (IN)Vlan id. 1576 * vrf - (OUT)Vrf. 1577 * Returns: 1578 * BCM_E_XXX. 1579 */ 1580 int 1581 _bcm_tr_l3_intf_vrf_bind(int unit, bcm_vlan_t vid, bcm_vrf_t vrf) 1582 { 1583 _bcm_l3_ingress_intf_t iif; /* Ingress interface config.*/ 1584 int ret_val; /* Operation return value. */ 1585 1586 /* Input parameters sanity check. */ 1587 if ((vid > soc_mem_index_max(unit, L3_IIFm)) || 1588 (vid < soc_mem_index_min(unit, L3_IIFm))) { 1589 return (BCM_E_PARAM); 1590 } 1591 1592 if (vrf > SOC_VRF_MAX(unit)) { 1593 return (BCM_E_PARAM); 1594 } 1595 1596 iif.intf_id = vid; 1597 soc_mem_lock(unit, L3_IIFm); 1598 1599 ret_val = _bcm_tr_l3_ingress_interface_get(unit, NULL, &iif); 1600 if (BCM_FAILURE(ret_val)) { 1601 soc_mem_unlock(unit, L3_IIFm); 1602 return (ret_val); 1603 } 1604 1605 iif.vrf = vrf; 1606 #if defined(BCM_TRIDENT2_SUPPORT) 1607 if (soc_feature(unit, soc_feature_l3_iif_profile)) { 1608 iif.profile_flags |= _BCM_L3_IIF_PROFILE_DO_NOT_UPDATE; 1609 } 1610 #endif /* BCM_TRIDENT2_SUPPORT */ 1611 1612 ret_val = _bcm_tr_l3_ingress_interface_set(unit, &iif, NULL, NULL); 1613 1614 soc_mem_unlock(unit, L3_IIFm); 1615 1616 return (ret_val); 1617 } 1618 1619 /* 1620 * Function: 1621 * _bcm_tr_l3_defip_mem_get 1622 * Purpose: 1623 * Resolve route table memory for a given route entry. 1624 * Parameters: 1625 * unit - (IN)SOC unit number. 1626 * flags - (IN)IPv6/IPv4 route. 1627 * plen - (IN)Prefix length. 1628 * mem - (OUT)Route table memory. 1629 * Returns: 1630 * BCM_E_XXX 1631 */ 1632 int 1633 _bcm_tr_l3_defip_mem_get(int unit, uint32 flags, int plen, soc_mem_t *mem) 1634 { 1635 soc_mem_t defip_mem = L3_DEFIPm, defip_128_mem = L3_DEFIP_128m; 1636 #if defined(BCM_VALKYRIE_SUPPORT) || defined(BCM_ENDURO_SUPPORT) || \ 1637 defined(BCM_APOLLO_SUPPORT) || defined(BCM_VALKYRIE2_SUPPORT) || \ 1638 defined(BCM_TRIDENT_SUPPORT) 1639 if (soc_mem_is_valid(unit, L3_DEFIP_LEVEL1m)) { 1640 defip_mem = L3_DEFIP_LEVEL1m; 1641 defip_128_mem = L3_DEFIP_PAIR_LEVEL1m; 1642 } 1643 if (!soc_feature(unit, soc_feature_esm_support)) { 1644 if (flags & BCM_L3_IP6) { 1645 #ifdef BCM_KATANA2_SUPPORT 1646 if (SOC_IS_KATANA2(unit)) { 1647 *mem = L3_DEFIPm; 1648 } else 1649 #endif /* BCM_KATANA2_SUPPORT */ 1650 if (plen > 64) { 1651 *mem = defip_128_mem; 1652 } else { /* IPv6 prefix length < 64 bit. */ 1653 *mem = defip_mem; 1654 } 1655 } else { /* IPv4 route. */ 1656 *mem = defip_mem; 1657 } 1658 return (BCM_E_NONE); 1659 } 1660 #endif 1661 if (flags & BCM_L3_IP6) { 1662 if (plen > 64) { 1663 *mem = defip_128_mem; 1664 if (soc_feature(unit, soc_feature_esm_support) && 1665 SOC_MEM_IS_ENABLED(unit, EXT_IPV6_128_DEFIPm)) { 1666 if (soc_mem_index_count(unit, EXT_IPV6_128_DEFIPm)) { 1667 *mem = EXT_IPV6_128_DEFIPm; 1668 } 1669 } 1670 } else { /* IPv6 prefix length < 64 bit. */ 1671 if (soc_feature(unit, soc_feature_esm_support) && 1672 (SOC_MEM_IS_ENABLED(unit, EXT_IPV6_128_DEFIPm) || 1673 SOC_MEM_IS_ENABLED(unit, EXT_IPV6_64_DEFIPm))) { 1674 if (soc_mem_index_count(unit, EXT_IPV6_128_DEFIPm)) { 1675 *mem = EXT_IPV6_128_DEFIPm; 1676 } else if (soc_mem_index_count(unit, EXT_IPV6_64_DEFIPm)) { 1677 *mem = EXT_IPV6_64_DEFIPm; 1678 } else { /* Defaults to internal memory even if soc feature esm 1679 is enabled, but device not configured to use ext mem */ 1680 *mem = defip_mem; 1681 } 1682 } else { 1683 *mem = defip_mem; 1684 } 1685 } 1686 } else { /* IPv4 route. */ 1687 *mem = L3_DEFIPm; 1688 if (soc_feature(unit, soc_feature_esm_support) && 1689 SOC_MEM_IS_ENABLED(unit, EXT_IPV4_DEFIPm)) { 1690 if (soc_mem_index_count(unit, EXT_IPV4_DEFIPm)) { 1691 *mem = EXT_IPV4_DEFIPm; 1692 } 1693 } 1694 } 1695 return (BCM_E_NONE); 1696 } 1697 1698 /* 1699 * Function: 1700 * _bcm_tr_l3_enable 1701 * Purpose: 1702 * Resolve route table memory for a given route entry. 1703 * Parameters: 1704 * unit - (IN)BCM device number. 1705 * port - (IN)Port number. 1706 * flags - (IN)IPv6/IPv4 flag. 1707 * enable - (IN)Enable /Disable 1708 * Returns: 1709 * BCM_E_XXX 1710 */ 1711 int 1712 _bcm_tr_l3_enable(int unit, bcm_port_t port, uint32 flags, int enable) 1713 { 1714 int rv; 1715 soc_field_t fields[2]; 1716 uint32 values[2] = {1, 0}; 1717 uint32 rval; 1718 1719 if (!soc_feature(unit, soc_feature_esm_support)) { 1720 /* No esm on this devices. */ 1721 return (BCM_E_NONE); 1722 } 1723 1724 BCM_IF_ERROR_RETURN(READ_ESM_KEYGEN_CTLr(unit, &rval)); 1725 1726 if (flags & BCM_L3_IP6) { 1727 fields[0] = IPV6_FWD_MODEf; 1728 fields[1] = IPV6_128_ENf; 1729 1730 if (enable) { 1731 1732 values[0] = 2; /* L3 forwarding mode */ 1733 /* Enable 128 bit forwarding if 128 bit table is present.*/ 1734 if (soc_mem_index_count(unit, EXT_IPV6_128_DEFIPm)) { 1735 values[1] = 1; 1736 } 1737 } else { 1738 values[0] = 1; /* use L2 to forward IPv6 packet */ 1739 } 1740 rv = soc_reg_fields32_modify(unit, ESM_MODE_PER_PORTr, port, 1741 2, fields, values); 1742 } else { 1743 fields[0] = IPV4_FWD_MODEf; 1744 if (enable) { 1745 1746 values[0] = 2; /* L3 forwarding mode */ 1747 } else { 1748 values[0] = 1; /* use L2 to forward IPv4 packet */ 1749 } 1750 rv = soc_reg_fields32_modify(unit, ESM_MODE_PER_PORTr, port, 1751 1, fields, values); 1752 } 1753 return rv; 1754 } 1755 1756 /* 1757 * Function: 1758 * _bcm_tr_l3_clear_hit 1759 * Purpose: 1760 * Clear hit bit on l3 entry 1761 * Parameters: 1762 * unit - (IN)SOC unit number. 1763 * mem - (IN)L3 table memory. 1764 * l3cfg - (IN)l3 entry info. 1765 * l3x_entry - (IN)l3 entry filled hw buffer. 1766 * Returns: 1767 * BCM_E_XXX 1768 */ 1769 STATIC int 1770 _bcm_tr_l3_clear_hit(int unit, soc_mem_t mem, 1771 _bcm_l3_cfg_t *l3cfg, void *l3x_entry) 1772 { 1773 uint32 *buf_p; /* HW buffer address. */ 1774 int mcast; /* Entry is multicast flag. */ 1775 int ipv6; /* Entry is IPv6 flag. */ 1776 int idx; /* Iterator index. */ 1777 soc_field_t hitf[] = { HIT_0f, HIT_1f, HIT_2f, HIT_3f }; 1778 1779 /* Input parameters check */ 1780 if ((NULL == l3cfg) || (NULL == l3x_entry)) { 1781 return (BCM_E_PARAM); 1782 } 1783 1784 /* Get entry type. */ 1785 ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6); 1786 mcast = (l3cfg->l3c_flags & BCM_L3_IPMC); 1787 1788 /* Init memory pointers. */ 1789 buf_p = (uint32 *)l3x_entry; 1790 1791 /* If entry was not hit there is nothing to clear */ 1792 if (!(l3cfg->l3c_flags & BCM_L3_HIT)) { 1793 return (BCM_E_NONE); 1794 } 1795 1796 /* Reset entry hit bit in hw. */ 1797 if (ipv6 && mcast) { 1798 /* IPV6 multicast entry hit reset. */ 1799 for (idx = 1; idx < 4; idx++) { 1800 soc_mem_field32_set(unit, mem, buf_p, hitf[idx], 0); 1801 } 1802 } else if (ipv6 || mcast) { 1803 /* Reset IPV6 unicast hit bit. */ 1804 for (idx = 1; idx < 2; idx++) { 1805 soc_mem_field32_set(unit, mem, buf_p, hitf[idx], 0); 1806 } 1807 } 1808 1809 /* Reset hit bit. */ 1810 soc_mem_field32_set(unit, mem, buf_p, hitf[0], 0); 1811 1812 /* Write entry back to hw. */ 1813 return BCM_XGS3_MEM_WRITE(unit, mem, l3cfg->l3c_hw_index, buf_p); 1814 } 1815 1816 /* 1817 * Function: 1818 * _bcm_tr_l3_ipmc_ent_init 1819 * Purpose: 1820 * Set GROUP/SOURCE/VID/IMPC flag in the entry. 1821 * Parameters: 1822 * unit - (IN)SOC unit number. 1823 * l3x_entry - (IN/OUT) IPMC entry to fill. 1824 * l3cfg - (IN) Api IPMC data. 1825 * Returns: 1826 * BCM_E_XXX 1827 */ 1828 void 1829 _bcm_tr_l3_ipmc_ent_init(int unit, uint32 *buf_p, 1830 _bcm_l3_cfg_t *l3cfg) 1831 { 1832 soc_mem_t mem; /* IPMC table memory. */ 1833 int ipv6; /* IPv6 entry indicator. */ 1834 int idx; /* Iteration index. */ 1835 soc_field_t typef[] = { KEY_TYPE_0f, KEY_TYPE_1f, 1836 KEY_TYPE_2f, KEY_TYPE_3f }; 1837 soc_field_t validf[] = { VALID_0f, VALID_1f, VALID_2f, VALID_3f }; 1838 1839 /* Get entry type. */ 1840 ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6); 1841 1842 /* Get table memory. */ 1843 mem = (ipv6) ? L3_ENTRY_IPV6_MULTICASTm : L3_ENTRY_IPV4_MULTICASTm; 1844 sal_memset(buf_p, 0, (ipv6) ? BCM_XGS3_L3_ENT_SZ(unit, ipmc_v6) : \ 1845 BCM_XGS3_L3_ENT_SZ(unit, ipmc_v4)); 1846 if (ipv6) { 1847 /* Set group address. */ 1848 soc_mem_ip6_addr_set(unit, mem, buf_p, GROUP_IP_ADDR_LWR_64f, 1849 l3cfg->l3c_ip6, SOC_MEM_IP6_LOWER_ONLY); 1850 l3cfg->l3c_ip6[0] = 0x0; /* Don't write ff entry already mcast. */ 1851 soc_mem_ip6_addr_set(unit, mem, buf_p, GROUP_IP_ADDR_UPR_56f, 1852 l3cfg->l3c_ip6, SOC_MEM_IP6_UPPER_ONLY); 1853 l3cfg->l3c_ip6[0] = 0xff; /* Restore The entry */ 1854 1855 /* Set source address. */ 1856 soc_mem_ip6_addr_set(unit, mem, buf_p, SOURCE_IP_ADDR_LWR_64f, 1857 l3cfg->l3c_sip6, SOC_MEM_IP6_LOWER_ONLY); 1858 soc_mem_ip6_addr_set(unit, mem, buf_p, SOURCE_IP_ADDR_UPR_64f, 1859 l3cfg->l3c_sip6, SOC_MEM_IP6_UPPER_ONLY); 1860 1861 for (idx = 0; idx < 4; idx++) { 1862 /* Set key type */ 1863 soc_mem_field32_set(unit, mem, buf_p, typef[idx], 1864 TR_L3_HASH_KEY_TYPE_V6MC); 1865 1866 /* Set entry valid bit. */ 1867 soc_mem_field32_set(unit, mem, buf_p, validf[idx], 1); 1868 1869 } 1870 } else { 1871 /* Set group id. */ 1872 soc_mem_field32_set(unit, mem, buf_p, GROUP_IP_ADDRf, 1873 l3cfg->l3c_ip_addr); 1874 1875 /* Set source address. */ 1876 soc_mem_field32_set(unit, mem, buf_p, SOURCE_IP_ADDRf, 1877 l3cfg->l3c_src_ip_addr); 1878 1879 for (idx = 0; idx < 2; idx++) { 1880 /* Set key type */ 1881 soc_mem_field32_set(unit, mem, buf_p, typef[idx], 1882 TR_L3_HASH_KEY_TYPE_V4MC); 1883 1884 /* Set entry valid bit. */ 1885 soc_mem_field32_set(unit, mem, buf_p, validf[idx], 1); 1886 } 1887 } 1888 1889 /* Set vlan id or L3_IIF. */ 1890 #ifdef BCM_GREYHOUND2_SUPPORT 1891 /* 1892 * Since Greyhound2 B0 increase field IPMC_L3_IIFf in L3_IIFm, which 1893 * the IPMC "L3_IIF" lookup will compare with the L3_IIF field instead of VLAN. 1894 */ 1895 if (SOC_IS_GREYHOUND2(unit) && SOC_MEM_FIELD_VALID(unit, L3_IIFm, 1896 IPMC_L3_IIFf)) { 1897 if (l3cfg->l3c_ing_intf > 0) { 1898 if (l3cfg->l3c_ing_intf > soc_mem_index_count(unit, L3_IIFm)) { 1899 LOG_ERROR(BSL_LS_BCM_L3, 1900 (BSL_META_U( 1901 unit, 1902 "Mem L3_IIF Entry %d exceed maximum index=(%d)\n"), 1903 l3cfg->l3c_ing_intf, 1904 soc_mem_index_count(unit, L3_IIFm))); 1905 return; 1906 } 1907 soc_mem_field32_set(unit, mem, buf_p, L3_IIFf, l3cfg->l3c_ing_intf); 1908 } else if (l3cfg->l3c_vid < 4096) { 1909 soc_mem_field32_set(unit, mem, buf_p, VLAN_IDf, l3cfg->l3c_vid); 1910 } else if (soc_mem_field_valid(unit, mem, L3_IIFf)) { 1911 soc_mem_field32_set(unit, mem, buf_p, L3_IIFf, l3cfg->l3c_vid); 1912 } 1913 } else 1914 #endif /* BCM_GREYHOUND2_SUPPORT */ 1915 { 1916 if (l3cfg->l3c_vid < 4096) { 1917 soc_mem_field32_set(unit, mem, buf_p, VLAN_IDf, l3cfg->l3c_vid); 1918 } else if (!(SOC_IS_METROLITE(unit)) && soc_mem_field_valid(unit, mem, 1919 L3_IIFf)) { 1920 soc_mem_field32_set(unit, mem, buf_p, L3_IIFf, l3cfg->l3c_vid); 1921 } 1922 } 1923 1924 /* Set virtual router id. */ 1925 if (SOC_MEM_FIELD_VALID(unit, mem, VRF_IDf)) { 1926 soc_mem_field32_set(unit, mem, buf_p, VRF_IDf, l3cfg->l3c_vrf); 1927 } 1928 return; 1929 } 1930 1931 /* 1932 * Function: 1933 * _bcm_tr_l3_ipmc_ent_parse 1934 * Purpose: 1935 * Service routine used to parse hw l3 ipmc entry to api format. 1936 * Parameters: 1937 * unit - (IN)SOC unit number. 1938 * l3cfg - (IN/OUT)l3 entry parsing destination buf. 1939 * l3x_entry - (IN/OUT)hw buffer. 1940 * Returns: 1941 * void 1942 */ 1943 STATIC INLINE void 1944 _bcm_tr_l3_ipmc_ent_parse(int unit, _bcm_l3_cfg_t *l3cfg, 1945 l3_entry_ipv6_multicast_entry_t *l3x_entry) 1946 { 1947 soc_mem_t mem; /* IPMC table memory. */ 1948 uint32 *buf_p; /* HW buffer address. */ 1949 int ipv6; /* IPv6 entry indicator. */ 1950 int idx; /* Iteration index. */ 1951 soc_field_t hitf[] = {HIT_1f, HIT_2f, HIT_3f }; 1952 1953 buf_p = (uint32 *)l3x_entry; 1954 1955 /* Get entry type. */ 1956 ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6); 1957 1958 /* Get table memory. */ 1959 mem = (ipv6) ? L3_ENTRY_IPV6_MULTICASTm : L3_ENTRY_IPV4_MULTICASTm; 1960 1961 /* Mark entry as multicast & clear rest of the flags. */ 1962 l3cfg->l3c_flags = BCM_L3_IPMC; 1963 if (ipv6) { 1964 l3cfg->l3c_flags |= BCM_L3_IP6; 1965 } 1966 1967 /* Read hit value. */ 1968 if(soc_mem_field32_get(unit, mem, buf_p, HIT_0f)) { 1969 l3cfg->l3c_flags |= BCM_L3_HIT; 1970 } else if (ipv6) { 1971 /* Get hit bit. */ 1972 for (idx = 0; idx < 3; idx++) { 1973 if(soc_mem_field32_get(unit, mem, buf_p, hitf[idx])) { 1974 l3cfg->l3c_flags |= BCM_L3_HIT; 1975 break; 1976 } 1977 } 1978 } 1979 1980 /* Set ipv6 group address to multicast. */ 1981 if (ipv6) { 1982 l3cfg->l3c_ip6[0] = 0xff; /* Set entry ip to mcast address. */ 1983 } 1984 1985 /* Read priority override */ 1986 if(soc_mem_field32_get(unit, mem, buf_p, RPEf)) { 1987 l3cfg->l3c_flags |= BCM_L3_RPE; 1988 } 1989 1990 /* Read destination discard bit. */ 1991 if(soc_mem_field32_get(unit, mem, buf_p, DST_DISCARDf)) { 1992 l3cfg->l3c_flags |= BCM_L3_DST_DISCARD; 1993 } 1994 1995 /* Read Virtual Router Id. */ 1996 if(!(SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit))) { 1997 l3cfg->l3c_vrf = soc_mem_field32_get(unit, mem, buf_p, VRF_IDf); 1998 } 1999 2000 /* Pointer to ipmc replication table. */ 2001 l3cfg->l3c_ipmc_ptr = soc_mem_field32_get(unit, mem, buf_p, L3MC_INDEXf); 2002 2003 /* Classification lookup class id. */ 2004 l3cfg->l3c_lookup_class = soc_mem_field32_get(unit, mem, buf_p, CLASS_IDf); 2005 2006 /* Read priority value. */ 2007 l3cfg->l3c_prio = soc_mem_field32_get(unit, mem, buf_p, PRIf); 2008 return; 2009 } 2010 2011 /* 2012 * Function: 2013 * _bcm_tr_l3_ipmc_get 2014 * Purpose: 2015 * Get l3 multicast entry. 2016 * Parameters: 2017 * unit - (IN)SOC unit number. 2018 * l3cfg - (IN/OUT)Group/Source key & Get result buffer. 2019 * Returns: 2020 * BCM_E_XXX 2021 */ 2022 int 2023 _bcm_tr_l3_ipmc_get(int unit, _bcm_l3_cfg_t *l3cfg) 2024 { 2025 l3_entry_ipv6_multicast_entry_t l3x_key; /* Lookup key buffer. */ 2026 l3_entry_ipv6_multicast_entry_t l3x_entry; /* Search result buffer. */ 2027 int clear_hit; /* Clear hit flag. */ 2028 soc_mem_t mem; /* IPMC table memory. */ 2029 int ipv6; /* IPv6 entry indicator. */ 2030 int rv; /* Return value. */ 2031 2032 /* Get entry type. */ 2033 ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6); 2034 2035 /* Get table memory. */ 2036 mem = (ipv6) ? L3_ENTRY_IPV6_MULTICASTm : L3_ENTRY_IPV4_MULTICASTm; 2037 2038 /* Zero buffers. */ 2039 sal_memcpy(&l3x_key, soc_mem_entry_null(unit, mem), 2040 soc_mem_entry_words(unit,mem) * 4); 2041 sal_memcpy(&l3x_entry, soc_mem_entry_null(unit, mem), 2042 soc_mem_entry_words(unit,mem) * 4); 2043 2044 /* Check if clear hit bit is required. */ 2045 clear_hit = l3cfg->l3c_flags & BCM_L3_HIT_CLEAR; 2046 2047 /* Lookup Key preparation. */ 2048 _bcm_tr_l3_ipmc_ent_init(unit, (uint32 *)&l3x_key, l3cfg); 2049 2050 /* Perform hw lookup. */ 2051 MEM_LOCK(unit, mem); 2052 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l3cfg->l3c_hw_index, 2053 &l3x_key, &l3x_entry, 0); 2054 MEM_UNLOCK(unit, mem); 2055 BCM_XGS3_LKUP_IF_ERROR_RETURN(rv, BCM_E_NOT_FOUND); 2056 2057 #ifdef BCM_TRIDENT_SUPPORT 2058 if (SOC_IS_TRIDENT(unit)) { 2059 soc_mem_t mem_y; 2060 l3_entry_ipv6_multicast_entry_t l3x_entry_y; 2061 uint32 hit; 2062 mem_y = ipv6 ? L3_ENTRY_IPV6_MULTICAST_Ym : L3_ENTRY_IPV4_MULTICAST_Ym; 2063 BCM_IF_ERROR_RETURN 2064 (BCM_XGS3_MEM_READ(unit, mem_y, l3cfg->l3c_hw_index, 2065 &l3x_entry_y)); 2066 hit = soc_mem_field32_get(unit, mem, &l3x_entry, HIT_0f); 2067 hit |= soc_mem_field32_get(unit, mem_y, &l3x_entry_y, HIT_0f); 2068 soc_mem_field32_set(unit, mem, &l3x_entry, HIT_0f, hit); 2069 hit = soc_mem_field32_get(unit, mem, &l3x_entry, HIT_1f); 2070 hit |= soc_mem_field32_get(unit, mem_y, &l3x_entry_y, HIT_1f); 2071 soc_mem_field32_set(unit, mem, &l3x_entry, HIT_1f, hit); 2072 if (ipv6) { 2073 hit = soc_mem_field32_get(unit, mem, &l3x_entry, HIT_2f); 2074 hit |= soc_mem_field32_get(unit, mem_y, &l3x_entry_y, HIT_2f); 2075 soc_mem_field32_set(unit, mem, &l3x_entry, HIT_2f, hit); 2076 hit = soc_mem_field32_get(unit, mem, &l3x_entry, HIT_3f); 2077 hit |= soc_mem_field32_get(unit, mem_y, &l3x_entry_y, HIT_3f); 2078 soc_mem_field32_set(unit, mem, &l3x_entry, HIT_3f, hit); 2079 } 2080 } 2081 #endif /* BCM_TRIDENT_SUPPORT */ 2082 2083 /* Extract buffer information. */ 2084 _bcm_tr_l3_ipmc_ent_parse(unit, l3cfg, &l3x_entry); 2085 2086 /* Clear the HIT bit */ 2087 if (clear_hit) { 2088 BCM_IF_ERROR_RETURN(_bcm_tr_l3_clear_hit(unit, mem, l3cfg, &l3x_entry)); 2089 } 2090 return rv; 2091 } 2092 2093 /* 2094 * Function: 2095 * _bcm_tr_l3_ipmc_add 2096 * Purpose: 2097 * Add l3 multicast entry. 2098 * Parameters: 2099 * unit - (IN)SOC unit number. 2100 * l3cfg - (IN/OUT)Group/Source key. 2101 * Returns: 2102 * BCM_E_XXX 2103 */ 2104 int 2105 _bcm_tr_l3_ipmc_add(int unit, _bcm_l3_cfg_t *l3cfg) 2106 { 2107 l3_entry_ipv6_multicast_entry_t l3x_entry; /* Write entry buffer. */ 2108 soc_mem_t mem; /* IPMC table memory. */ 2109 uint32 *buf_p; /* HW buffer address. */ 2110 int ipv6; /* IPv6 entry indicator. */ 2111 int idx; /* Iteration index. */ 2112 int idx_max; /* Iteration index max. */ 2113 int rv; /* Return value. */ 2114 soc_field_t hitf[] = { HIT_0f, HIT_1f, HIT_2f, HIT_3f }; 2115 2116 /* Get entry type. */ 2117 ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6); 2118 2119 /* Get table memory. */ 2120 mem = (ipv6) ? L3_ENTRY_IPV6_MULTICASTm : L3_ENTRY_IPV4_MULTICASTm; 2121 2122 /* Zero buffers. */ 2123 buf_p = (uint32 *)&l3x_entry; 2124 sal_memcpy(buf_p, soc_mem_entry_null(unit, mem), 2125 soc_mem_entry_words(unit,mem) * 4); 2126 2127 /* Prepare entry to write. */ 2128 _bcm_tr_l3_ipmc_ent_init(unit, (uint32 *)&l3x_entry, l3cfg); 2129 2130 /* Set priority override bit. */ 2131 if (l3cfg->l3c_flags & BCM_L3_RPE) { 2132 soc_mem_field32_set(unit, mem, buf_p, RPEf, 1); 2133 } 2134 2135 /* Set destination discard. */ 2136 if (l3cfg->l3c_flags & BCM_L3_DST_DISCARD) { 2137 soc_mem_field32_set(unit, mem, buf_p, DST_DISCARDf, 1); 2138 } 2139 2140 if(!(SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit))) { 2141 /* Virtual router id. */ 2142 soc_mem_field32_set(unit, mem, buf_p, VRF_IDf, l3cfg->l3c_vrf); 2143 } 2144 2145 /* Set priority. */ 2146 soc_mem_field32_set(unit, mem, buf_p, PRIf, l3cfg->l3c_prio); 2147 2148 /* Pointer to ipmc table. */ 2149 soc_mem_field32_set(unit, mem, buf_p, L3MC_INDEXf, l3cfg->l3c_ipmc_ptr); 2150 2151 /* Classification lookup class id. */ 2152 soc_mem_field32_set(unit, mem, buf_p, CLASS_IDf, l3cfg->l3c_lookup_class); 2153 2154 idx_max = (ipv6) ? 4 : 2; 2155 for (idx = 0; idx < idx_max; idx++) { 2156 /* Set hit bit. */ 2157 if (l3cfg->l3c_flags & BCM_L3_HIT) { 2158 soc_mem_field32_set(unit, mem, buf_p, hitf[idx], 1); 2159 } 2160 } 2161 2162 /* Write entry to the hw. */ 2163 MEM_LOCK(unit, mem); 2164 /* Handle replacement. */ 2165 if (BCM_XGS3_L3_INVALID_INDEX != l3cfg->l3c_hw_index) { 2166 rv = BCM_XGS3_MEM_WRITE(unit, mem, l3cfg->l3c_hw_index, buf_p); 2167 } else { 2168 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ANY, (void *)buf_p); 2169 } 2170 2171 /* Increment number of ipmc routes. */ 2172 if (BCM_SUCCESS(rv) && (BCM_XGS3_L3_INVALID_INDEX == l3cfg->l3c_hw_index)) { 2173 (ipv6) ? BCM_XGS3_L3_IP6_IPMC_CNT(unit)++ : \ 2174 BCM_XGS3_L3_IP4_IPMC_CNT(unit)++; 2175 } 2176 /* coverity[overrun-local : FALSE] */ 2177 MEM_UNLOCK(unit, mem); 2178 return rv; 2179 } 2180 2181 /* 2182 * Function: 2183 * _bcm_tr_l3_ipmc_del 2184 * Purpose: 2185 * Delete l3 multicast entry. 2186 * Parameters: 2187 * unit - (IN)SOC unit number. 2188 * l3cfg - (IN)Group/Source deletion key. 2189 * Returns: 2190 * BCM_E_XXX 2191 */ 2192 int 2193 _bcm_tr_l3_ipmc_del(int unit, _bcm_l3_cfg_t *l3cfg) 2194 { 2195 l3_entry_ipv6_multicast_entry_t l3x_entry; /* Delete buffer. */ 2196 soc_mem_t mem; /* IPMC table memory. */ 2197 int ipv6; /* IPv6 entry indicator. */ 2198 int rv; /* Operation return value. */ 2199 2200 /* Get entry type. */ 2201 ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6); 2202 2203 /* Get table memory. */ 2204 mem = (ipv6) ? L3_ENTRY_IPV6_MULTICASTm : L3_ENTRY_IPV4_MULTICASTm; 2205 2206 /* Zero entry buffer. */ 2207 sal_memcpy(&l3x_entry, soc_mem_entry_null(unit, mem), 2208 soc_mem_entry_words(unit,mem) * 4); 2209 2210 2211 /* Key preparation. */ 2212 _bcm_tr_l3_ipmc_ent_init(unit, (uint32 *)&l3x_entry, l3cfg); 2213 2214 /* Delete the entry from hw. */ 2215 MEM_LOCK(unit, mem); 2216 2217 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, (void *)&l3x_entry); 2218 2219 /* Decrement number of ipmc routes. */ 2220 if (BCM_SUCCESS(rv)) { 2221 (ipv6) ? BCM_XGS3_L3_IP6_IPMC_CNT(unit)-- : \ 2222 BCM_XGS3_L3_IP4_IPMC_CNT(unit)--; 2223 } 2224 MEM_UNLOCK(unit, mem); 2225 return rv; 2226 } 2227 2228 /* 2229 * Function: 2230 * _bcm_tr_l3_ipmc_get_by_idx 2231 * Purpose: 2232 * Get l3 multicast entry by entry index. 2233 * Parameters: 2234 * unit - (IN)SOC unit number. 2235 * dma_ptr - (IN)Table pointer in dma. 2236 * idx - (IN)Index to read. 2237 * l3cfg - (IN/OUT)Entry data. 2238 * Returns: 2239 * BCM_E_XXX 2240 */ 2241 int 2242 _bcm_tr_l3_ipmc_get_by_idx(int unit, void *dma_ptr, 2243 int idx, _bcm_l3_cfg_t *l3cfg) 2244 { 2245 l3_entry_ipv6_multicast_entry_t *l3x_entry_p; /* Read buffer address. */ 2246 l3_entry_ipv6_multicast_entry_t l3x_entry; /* Read buffer. */ 2247 soc_mem_t mem; /* IPMC table memory. */ 2248 uint32 ipv6; /* IPv6 entry indicator. */ 2249 int clear_hit; /* Clear hit bit indicator.*/ 2250 int key_type; 2251 2252 /* Get entry type. */ 2253 ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6); 2254 2255 /* Get table memory. */ 2256 mem = (ipv6) ? L3_ENTRY_IPV6_MULTICASTm : L3_ENTRY_IPV4_MULTICASTm; 2257 2258 /* Check if clear hit is required. */ 2259 clear_hit = l3cfg->l3c_flags & BCM_L3_HIT_CLEAR; 2260 2261 if (NULL == dma_ptr) { /* Read from hardware. */ 2262 /* Zero buffers. */ 2263 l3x_entry_p = &l3x_entry; 2264 sal_memcpy(l3x_entry_p, soc_mem_entry_null(unit, mem), 2265 soc_mem_entry_words(unit,mem) * 4); 2266 2267 /* Read entry from hw. */ 2268 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, mem, idx, l3x_entry_p)); 2269 } else { /* Read from dma. */ 2270 l3x_entry_p = 2271 soc_mem_table_idx_to_pointer(unit, mem, 2272 l3_entry_ipv6_multicast_entry_t *, 2273 dma_ptr, idx); 2274 } 2275 #ifdef BCM_TRIDENT_SUPPORT 2276 if (SOC_IS_TRIDENT(unit)) { 2277 soc_mem_t mem_y; 2278 l3_entry_ipv6_multicast_entry_t l3x_entry_y; 2279 uint32 hit; 2280 mem_y = ipv6 ? L3_ENTRY_IPV6_MULTICAST_Ym : L3_ENTRY_IPV4_MULTICAST_Ym; 2281 BCM_IF_ERROR_RETURN 2282 (BCM_XGS3_MEM_READ(unit, mem_y, idx, &l3x_entry_y)); 2283 hit = soc_mem_field32_get(unit, mem, l3x_entry_p, HIT_0f); 2284 hit |= soc_mem_field32_get(unit, mem_y, &l3x_entry_y, HIT_0f); 2285 soc_mem_field32_set(unit, mem, l3x_entry_p, HIT_0f, hit); 2286 hit = soc_mem_field32_get(unit, mem, l3x_entry_p, HIT_1f); 2287 hit |= soc_mem_field32_get(unit, mem_y, &l3x_entry_y, HIT_1f); 2288 soc_mem_field32_set(unit, mem, l3x_entry_p, HIT_1f, hit); 2289 if (ipv6) { 2290 hit = soc_mem_field32_get(unit, mem, l3x_entry_p, HIT_2f); 2291 hit |= soc_mem_field32_get(unit, mem_y, &l3x_entry_y, HIT_2f); 2292 soc_mem_field32_set(unit, mem, l3x_entry_p, HIT_2f, hit); 2293 hit = soc_mem_field32_get(unit, mem, l3x_entry_p, HIT_3f); 2294 hit |= soc_mem_field32_get(unit, mem_y, &l3x_entry_y, HIT_3f); 2295 soc_mem_field32_set(unit, mem, l3x_entry_p, HIT_3f, hit); 2296 } 2297 } 2298 #endif /* BCM_TRIDENT_SUPPORT */ 2299 2300 /* Ignore invalid entries. */ 2301 if (!soc_mem_field32_get(unit, mem, l3x_entry_p, VALID_0f)) { 2302 return (BCM_E_NOT_FOUND); 2303 } 2304 2305 2306 key_type = soc_mem_field32_get(unit, L3_ENTRY_ONLYm, 2307 l3x_entry_p, KEY_TYPEf); 2308 2309 switch (key_type) { 2310 case TR_L3_HASH_KEY_TYPE_V4MC: 2311 l3cfg->l3c_flags = BCM_L3_IPMC; 2312 break; 2313 case TR_L3_HASH_KEY_TYPE_V6UC: 2314 l3cfg->l3c_flags = BCM_L3_IP6; 2315 break; 2316 case TR_L3_HASH_KEY_TYPE_V6MC: 2317 l3cfg->l3c_flags = BCM_L3_IP6 | BCM_L3_IPMC; 2318 break; 2319 default: 2320 /* Catch all other key types, set flags to zero so that the 2321 * following flag check is effective for all key types */ 2322 l3cfg->l3c_flags = 0; 2323 break; 2324 } 2325 2326 /* Ignore protocol mismatch & multicast entries. */ 2327 if ((ipv6 != (l3cfg->l3c_flags & BCM_L3_IP6)) || 2328 (!(l3cfg->l3c_flags & BCM_L3_IPMC))) { 2329 return (BCM_E_NOT_FOUND); 2330 } 2331 2332 /* Set index to l3cfg. */ 2333 l3cfg->l3c_hw_index = idx; 2334 2335 if (ipv6) { 2336 /* Get group address. */ 2337 soc_mem_ip6_addr_get(unit, mem, l3x_entry_p, GROUP_IP_ADDR_LWR_64f, 2338 l3cfg->l3c_ip6, SOC_MEM_IP6_LOWER_ONLY); 2339 2340 soc_mem_ip6_addr_get(unit, mem, l3x_entry_p, GROUP_IP_ADDR_UPR_56f, 2341 l3cfg->l3c_ip6, SOC_MEM_IP6_UPPER_ONLY); 2342 2343 /* Get source address. */ 2344 soc_mem_ip6_addr_get(unit, mem, l3x_entry_p, SOURCE_IP_ADDR_LWR_64f, 2345 l3cfg->l3c_sip6, SOC_MEM_IP6_LOWER_ONLY); 2346 soc_mem_ip6_addr_get(unit, mem, l3x_entry_p, SOURCE_IP_ADDR_UPR_64f, 2347 l3cfg->l3c_sip6, SOC_MEM_IP6_UPPER_ONLY); 2348 2349 l3cfg->l3c_ip6[0] = 0xff; /* Set entry to multicast*/ 2350 } else { 2351 /* Get group id. */ 2352 l3cfg->l3c_ip_addr = 2353 soc_mem_field32_get(unit, mem, l3x_entry_p, GROUP_IP_ADDRf); 2354 2355 /* Get source address. */ 2356 l3cfg->l3c_src_ip_addr = 2357 soc_mem_field32_get(unit, mem, l3x_entry_p, SOURCE_IP_ADDRf); 2358 } 2359 2360 /* Get L3_IIF or vlan id. */ 2361 if (!(SOC_IS_METROLITE(unit)) && soc_mem_field_valid(unit, mem, L3_IIFf)) { 2362 l3cfg->l3c_vid = soc_mem_field32_get(unit, mem, l3x_entry_p, L3_IIFf); 2363 } else { 2364 l3cfg->l3c_vid = soc_mem_field32_get(unit, mem, l3x_entry_p, VLAN_IDf); 2365 } 2366 2367 /* Parse entry data. */ 2368 _bcm_tr_l3_ipmc_ent_parse(unit, l3cfg, l3x_entry_p); 2369 2370 /* Clear the HIT bit */ 2371 if (clear_hit) { 2372 BCM_IF_ERROR_RETURN(_bcm_tr_l3_clear_hit(unit, mem, l3cfg, l3x_entry_p)); 2373 } 2374 return (BCM_E_NONE); 2375 } 2376 2377 /* 2378 * Function: 2379 * _bcm_tr_l3_intf_mtu_set 2380 * Purpose: 2381 * Set L3 interface MTU value. 2382 * Parameters: 2383 * unit - (IN)SOC unit number. 2384 * intf_info - (IN)Interface information. 2385 * Returns: 2386 * BCM_E_XXX 2387 */ 2388 int 2389 _bcm_tr_l3_intf_mtu_set(int unit, _bcm_l3_intf_cfg_t *intf_info) 2390 { 2391 mtu_values_entry_t mtu_value_buf; /* Buffer to write mtu. */ 2392 uint32 *mtu_value_buf_p; /* Write buffer address.*/ 2393 void *null_entry = soc_mem_entry_null(unit, L3_MTU_VALUESm); 2394 int mtu_index; 2395 int interface_map_mode = 0; 2396 2397 /* Input parameters check */ 2398 if (NULL == intf_info) { 2399 return (BCM_E_PARAM); 2400 } 2401 2402 if (soc_feature(unit, soc_feature_l3_ingress_interface)) { 2403 BCM_IF_ERROR_RETURN( 2404 bcm_xgs3_l3_ingress_intf_map_get(unit, &interface_map_mode)); 2405 } 2406 /* coverity[dead_error_begin : FALSE] */ 2407 if(!SOC_MEM_FIELD32_VALUE_FIT(unit, L3_MTU_VALUESm, 2408 MTU_SIZEf, intf_info->l3i_mtu)) { 2409 return (BCM_E_PARAM); 2410 } 2411 if ((!BCM_XGS3_L3_INTF_VLAN_SPLIT_EGRESS_MODE_ISSET(unit)) && 2412 (BCM_VLAN_VALID(intf_info->l3i_vid)) && !interface_map_mode) { 2413 2414 if ((intf_info->l3i_vid < soc_mem_index_min(unit, L3_MTU_VALUESm)) || 2415 (intf_info->l3i_vid > soc_mem_index_max(unit, L3_MTU_VALUESm))) { 2416 return (BCM_E_PARAM); 2417 } 2418 } else { 2419 if ((intf_info->l3i_index < soc_mem_index_min(unit, L3_MTU_VALUESm)) || 2420 (intf_info->l3i_index > soc_mem_index_max(unit, L3_MTU_VALUESm))) { 2421 return (BCM_E_PARAM); 2422 } 2423 } 2424 2425 /* Reset the buffer to default value. */ 2426 mtu_value_buf_p = (uint32 *)&mtu_value_buf; 2427 sal_memcpy(mtu_value_buf_p, null_entry, sizeof(mtu_values_entry_t)); 2428 2429 if (soc_feature(unit, soc_feature_l3_mtu_size_default) && 2430 intf_info->l3i_mtu == 0) { 2431 intf_info->l3i_mtu = 2432 (1 << soc_mem_field_length(unit, L3_MTU_VALUESm, MTU_SIZEf)) - 1; 2433 } 2434 2435 if (intf_info->l3i_mtu) { 2436 /* Set mtu. */ 2437 soc_mem_field32_set(unit, L3_MTU_VALUESm, mtu_value_buf_p, 2438 MTU_SIZEf, intf_info->l3i_mtu); 2439 } 2440 if (!BCM_XGS3_L3_INTF_VLAN_SPLIT_EGRESS_MODE_ISSET(unit)) { 2441 if (!interface_map_mode) { 2442 mtu_index = intf_info->l3i_vid; 2443 } else { 2444 mtu_index = intf_info->l3i_index; 2445 } 2446 return BCM_XGS3_MEM_WRITE(unit, L3_MTU_VALUESm, 2447 mtu_index, mtu_value_buf_p); 2448 } else { 2449 /* MTU index to be based on L3 IIF Index */ 2450 return BCM_XGS3_MEM_WRITE(unit, L3_MTU_VALUESm, 2451 intf_info->l3i_index, mtu_value_buf_p); 2452 } 2453 } 2454 2455 /* 2456 * Function: 2457 * _bcm_tr_l3_intf_mtu_get 2458 * Purpose: 2459 * Get L3 interface MTU value. 2460 * Parameters: 2461 * unit - (IN)SOC unit number. 2462 * intf_info - (IN/OUT)Interface information with updated mtu. 2463 * Returns: 2464 * BCM_E_XXX 2465 */ 2466 int 2467 _bcm_tr_l3_intf_mtu_get(int unit, _bcm_l3_intf_cfg_t *intf_info) 2468 { 2469 mtu_values_entry_t mtu_value_buf; /* Buffer to write mtu. */ 2470 uint32 *mtu_value_buf_p; /* Write buffer address. */ 2471 int mtu_index; 2472 int interface_map_mode = 0; 2473 2474 /* Input parameters check */ 2475 if (NULL == intf_info) { 2476 return (BCM_E_PARAM); 2477 } 2478 2479 if (soc_feature(unit, soc_feature_l3_ingress_interface)) { 2480 BCM_IF_ERROR_RETURN( 2481 bcm_xgs3_l3_ingress_intf_map_get(unit, &interface_map_mode)); 2482 } 2483 2484 if ((!BCM_XGS3_L3_INTF_VLAN_SPLIT_EGRESS_MODE_ISSET(unit)) && 2485 (BCM_VLAN_VALID(intf_info->l3i_vid)) && !interface_map_mode) { 2486 2487 if ((intf_info->l3i_vid < soc_mem_index_min(unit, L3_MTU_VALUESm)) || 2488 (intf_info->l3i_vid > soc_mem_index_max(unit, L3_MTU_VALUESm))) { 2489 return (BCM_E_PARAM); 2490 } 2491 } else { 2492 if ((intf_info->l3i_index < soc_mem_index_min(unit, L3_MTU_VALUESm)) || 2493 (intf_info->l3i_index > soc_mem_index_max(unit, L3_MTU_VALUESm))) { 2494 return (BCM_E_PARAM); 2495 } 2496 } 2497 2498 /* Zero the buffer. */ 2499 mtu_value_buf_p = (uint32 *)&mtu_value_buf; 2500 sal_memset(mtu_value_buf_p, 0, sizeof(mtu_values_entry_t)); 2501 2502 if (!BCM_XGS3_L3_INTF_VLAN_SPLIT_EGRESS_MODE_ISSET(unit)) { 2503 if (!interface_map_mode) { 2504 mtu_index = intf_info->l3i_vid; 2505 } else { 2506 mtu_index = intf_info->l3i_index; 2507 } 2508 /* MTU index to be based on L3 IIF Index */ 2509 /* Read mtu table entry by index. */ 2510 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, L3_MTU_VALUESm, 2511 mtu_index, mtu_value_buf_p)); 2512 } else { 2513 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, L3_MTU_VALUESm, 2514 intf_info->l3i_index, 2515 mtu_value_buf_p)); 2516 } 2517 intf_info->l3i_mtu = 2518 soc_mem_field32_get(unit, L3_MTU_VALUESm, mtu_value_buf_p, MTU_SIZEf); 2519 2520 return (BCM_E_NONE); 2521 } 2522 2523 #else /* BCM_TRIUMPH_SUPPORT && INCLUDE_L3 */ 2524 int bcm_esw_triumph_l3_not_empty; 2525 #endif /* BCM_TRIUMPH_SUPPORT && INCLUDE_L3 */