l3.c (452673B)
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: Manages L3 interface table, forwarding table, routing table 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <soc/defs.h> 14 #include <bcm/error.h> 15 #ifdef INCLUDE_L3 16 #include <sal/core/libc.h> 17 #include <soc/drv.h> 18 #include <soc/scache.h> 19 #include <soc/util.h> 20 #include <soc/l3x.h> 21 #include <soc/hash.h> 22 #include <soc/mem.h> 23 24 #if defined BCM_METROLITE_SUPPORT 25 #include <soc/katana2.h> 26 #endif 27 28 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT 29 #include <soc/esw/ecmp.h> 30 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */ 31 #ifdef CANCUN_SUPPORT 32 #include <soc/esw/cancun.h> 33 #endif /* CANCUN_SUPPORT */ 34 35 #include <bcm/l3.h> 36 #include <bcm/debug.h> 37 38 #include <bcm_int/esw/mbcm.h> 39 #include <bcm_int/esw/l3.h> 40 #include <bcm_int/esw/vlan.h> 41 #include <bcm_int/esw/virtual.h> 42 43 #ifdef BCM_XGS_SWITCH_SUPPORT 44 #include <bcm_int/esw/firebolt.h> 45 #if defined(BCM_TRIUMPH_SUPPORT) 46 #include <bcm_int/esw/triumph.h> 47 #endif /* BCM_TRIUMPH_SUPPORT */ 48 #if defined(BCM_TRIUMPH2_SUPPORT) 49 #include <bcm_int/esw/triumph2.h> 50 #endif /* BCM_TRIUMPH2_SUPPORT */ 51 #if defined(BCM_TRIUMPH3_SUPPORT) 52 #include <bcm_int/esw/triumph3.h> 53 #endif /* BCM_TRIUMPH3_SUPPORT */ 54 #endif /* BCM_XGS_SWITCH_SUPPORT */ 55 #ifdef BCM_WARM_BOOT_SUPPORT 56 #include <bcm_int/esw/switch.h> 57 #endif /* BCM_WARM_BOOT_SUPPORT */ 58 #if defined(BCM_TRIDENT2_SUPPORT) 59 #include <bcm_int/esw/trident2.h> 60 #endif /* BCM_TRIDENT2_SUPPORT */ 61 #if defined(BCM_TRIDENT3_SUPPORT) 62 #include <bcm_int/esw/trident3.h> 63 #include <soc/trident3.h> 64 #endif /* BCM_TRIDENT3_SUPPORT */ 65 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 66 #include <bcm_int/esw/trident2plus.h> 67 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 68 #if defined(BCM_KATANA2_SUPPORT) 69 #include <bcm_int/esw/katana2.h> 70 #endif /* BCM_KATANA2_SUPPORT */ 71 #if defined(BCM_TOMAHAWK_SUPPORT) 72 #include <bcm_int/esw/tomahawk.h> 73 #endif /* BCM_TOMAHAWK_SUPPORT */ 74 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 75 #include <bcm_int/esw/tomahawk2.h> 76 #endif /* BCM_TOMAHAWK2_SUPPORT */ 77 #if defined(BCM_HGPROXY_COE_SUPPORT) 78 #include <bcm_int/esw/xgs5.h> 79 #endif /* BCM_HGPROXY_COE_SUPPORT */ 80 #if defined(BCM_TOMAHAWK3_SUPPORT) 81 #include <bcm_int/esw/alpm.h> 82 #include <bcm_int/esw/tomahawk3.h> 83 #endif /* BCM_TOMAHAWK3_SUPPORT */ 84 85 #include <bcm_int/esw_dispatch.h> 86 #include <bcm_int/esw/flex_ctr.h> 87 #include <bcm_int/esw/switch.h> 88 #include <bcm_int/common/multicast.h> 89 #include <bcm_int/esw/multicast.h> 90 91 /* 92 * Special IP addresses 93 */ 94 #define INADDR_ANY (uint32)0x00000000 95 #define INADDR_LOOPBACK (uint32)0x7F000001 96 #define INADDR_NONE (uint32)0xffffffff 97 98 #ifdef BCM_KATANA_SUPPORT 99 #define _BCM_QOS_MAP_TYPE_MASK 0x3ff 100 #define _BCM_QOS_MAP_SHIFT 10 101 #define _BCM_QOS_MAP_TYPE_ING_QUEUE_OFFSET_MAP_TABLE 5 102 #define _BCM_QOS_MAP_ING_QUEUE_OFFSET_MAX 7 103 #endif 104 /* 105 * L3 book keeping global info 106 */ 107 108 _bcm_l3_bookkeeping_t _bcm_l3_bk_info[BCM_MAX_NUM_UNITS]; 109 static int l3_internal_initialized = 0; 110 111 #if defined(BCM_TOMAHAWK_SUPPORT) 112 int ecmp_mode_hierarchical = TH_ECMP_MODE_HIERARCHICAL; 113 int ecmp_mode_single = TH_ECMP_MODE_SINGLE; 114 #endif 115 116 #ifdef BCM_TOMAHAWK3_SUPPORT 117 extern int ecmp_mode_hierarchical; 118 #endif 119 #define L3_INIT(unit) \ 120 if (!soc_feature(unit, soc_feature_l3)) { \ 121 return BCM_E_UNAVAIL; \ 122 } else if (!l3_internal_initialized) { \ 123 return BCM_E_DISABLED; \ 124 } else { \ 125 if (!_bcm_l3_bk_info[unit].l3_initialized) { return BCM_E_INIT; } \ 126 } 127 128 #if defined(BCM_TRIDENT3_SUPPORT) 129 int bcmi_l3_init_check(int unit) 130 { 131 if (!soc_feature(unit, soc_feature_l3)) { 132 return BCM_E_UNAVAIL; 133 } else if (!soc_property_get(unit, spn_L3_ENABLE, 1)) { 134 return BCM_E_DISABLED; 135 } else { 136 if (!_bcm_l3_bk_info[unit].l3_initialized) { return BCM_E_INIT; } 137 } 138 139 return BCM_E_NONE; 140 } 141 #endif /*BCM_TRIDENT3_SUPPORT */ 142 143 int _bcm_l3_reinit(int unit) 144 { 145 _bcm_l3_bookkeeping_t *l3; 146 147 l3 = &_bcm_l3_bk_info[unit]; 148 149 if (soc_property_get(unit, spn_L3_DISABLE_ADD_TO_ARL, 0)) { 150 BCM_L3_BK_FLAG_SET(unit, BCM_L3_BK_DISABLE_ADD_TO_ARL); 151 } 152 153 if (soc_property_get(unit, spn_EMBEDDED_NH_VP_SUPPORT, 0)) { 154 #ifdef BCM_TOMAHAWK_SUPPORT 155 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) { 156 BCM_L3_BK_FLAG_SET(unit, BCM_L3_BK_ENABLE_MACDA_OUI_PROFILE); 157 } 158 #endif /* BCM_TOMAHAWK_SUPPORT */ 159 } 160 161 #ifdef BCM_XGS3_SWITCH_SUPPORT 162 if ((SOC_IS_FB_FX_HX(unit) && !SOC_IS_RAPTOR(unit)) || 163 SOC_IS_TR_VL(unit) || SOC_IS_HB_GW(unit) || 164 SOC_IS_SC_CQ(unit)) { 165 BCM_IF_ERROR_RETURN(_bcm_xgs3_l3_reinit(unit)); 166 } 167 #endif 168 169 l3->l3_initialized = 1; 170 return BCM_E_NONE; 171 } 172 173 174 /* 175 * Function: 176 * _bcm_esw_l3_gport_construct 177 * Purpose: 178 * Constructs a gport out of given parameter for L3 Module. 179 * Parameters: 180 * unit - SOC device unit number 181 * port_tgid - Physical port 182 * modid - Module ID 183 * tgid - Trunk group ID 184 * flags - L3 Flags 185 * gport - (Out) gport constructed from given arguments 186 * Returns: 187 * BCM_E_XXX 188 */ 189 190 int 191 _bcm_esw_l3_gport_construct(int unit, bcm_port_t port, bcm_module_t modid, 192 bcm_trunk_t tgid, uint32 flags, bcm_port_t *gport) 193 { 194 int isGport, rv; 195 _bcm_gport_dest_t dest; 196 bcm_module_t mymodid; 197 #if defined(BCM_KATANA2_SUPPORT) 198 bcm_port_t pp_port; 199 int min_subport = SOC_INFO(unit).pp_port_index_min; 200 int max_subport = SOC_INFO(unit).pp_port_index_max; 201 #endif 202 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 203 int is_local_subport = 0; 204 #endif 205 206 if (NULL == gport) { 207 return BCM_E_PARAM; 208 } 209 210 if (flags & BCM_L3_TGID) { 211 if (BCM_FAILURE(_bcm_trunk_id_validate(unit, tgid))) { 212 return BCM_E_PARAM; 213 } 214 } else if ((port < 0) && (modid < 0)){ 215 return BCM_E_PARAM; 216 } 217 218 BCM_IF_ERROR_RETURN( 219 bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport)); 220 221 /* if output should not be gport then do nothing*/ 222 if (!isGport) { 223 return BCM_E_NONE; 224 } 225 226 if (BCM_GPORT_IS_WLAN_PORT(port)) { 227 return BCM_E_NONE; 228 } 229 230 #if defined(BCM_HGPROXY_COE_SUPPORT) 231 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 232 233 if(_bcm_xgs5_subport_coe_mod_port_local(unit, modid, port)) { 234 is_local_subport = 1; 235 236 /* Encode our outgoing parameter as GPORT_SUBPORT type and 237 fill in the associated (mod,port) */ 238 _BCM_SUBPORT_COE_PORT_ID_SET(*gport, modid, port); 239 240 /* Set the bit on the outgoing param indicating this is subtag type */ 241 _BCM_SUBPORT_COE_PORT_TYPE_SET(*gport, _BCM_SUBPORT_COE_TYPE_SUBTAG); 242 } 243 } 244 #endif 245 #if defined(BCM_KATANA2_SUPPORT) 246 if (soc_feature(unit, soc_feature_linkphy_coe) || 247 soc_feature(unit, soc_feature_subtag_coe)) { 248 /* For LinkPHY/SubportPktTag pp_ports, check if the mod is a valid one */ 249 if ((_bcm_kt2_mod_is_coe_mod_check(unit, modid) == BCM_E_NONE) 250 && !(flags & BCM_L3_TGID)) { 251 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(unit, 252 modid, port, &pp_port)); 253 /*For KT2, pp_port >=42 are used for LinkPHY/SubportPktTag subport. 254 * Get the subport info associated with the pp_port and form the 255 * subport_gport */ 256 #if defined BCM_METROLITE_SUPPORT 257 if (soc_feature(unit, soc_feature_discontinuous_pp_port)) { 258 if (_SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, pp_port)) { 259 is_local_subport = 1; 260 /* construct LinkPHY/SubportPkttag subport gport */ 261 _BCM_KT2_SUBPORT_PORT_ID_SET(*gport, pp_port); 262 if (BCM_PBMP_MEMBER( 263 SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) { 264 _BCM_KT2_SUBPORT_PORT_TYPE_SET(*gport, 265 _BCM_KT2_SUBPORT_TYPE_LINKPHY); 266 } else if (BCM_PBMP_MEMBER( 267 SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) { 268 _BCM_KT2_SUBPORT_PORT_TYPE_SET(*gport, 269 _BCM_KT2_SUBPORT_TYPE_SUBTAG); 270 } else { 271 return BCM_E_PORT; 272 } 273 } 274 } else 275 #endif 276 { 277 if ((pp_port >= min_subport) && 278 (pp_port <= max_subport)) { 279 is_local_subport = 1; 280 /* construct LinkPHY/SubportPkttag subport gport */ 281 _BCM_KT2_SUBPORT_PORT_ID_SET(*gport, pp_port); 282 if (BCM_PBMP_MEMBER( 283 SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) { 284 _BCM_KT2_SUBPORT_PORT_TYPE_SET(*gport, 285 _BCM_KT2_SUBPORT_TYPE_LINKPHY); 286 } else if (BCM_PBMP_MEMBER( 287 SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) { 288 _BCM_KT2_SUBPORT_PORT_TYPE_SET(*gport, 289 _BCM_KT2_SUBPORT_TYPE_SUBTAG); 290 } else { 291 return BCM_E_PORT; 292 } 293 } 294 } 295 } 296 } 297 #endif 298 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 299 if (is_local_subport) { 300 /* gport assigned above */ 301 } else 302 #endif 303 { 304 _bcm_gport_dest_t_init(&dest); 305 306 if (flags & BCM_L3_TGID) { 307 dest.tgid = tgid; 308 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 309 } else { 310 /* Stacking ports should be encoded as devport */ 311 if (IS_ST_PORT(unit, port)) { 312 rv = bcm_esw_stk_my_modid_get(unit, &mymodid); 313 if (BCM_E_UNAVAIL == rv) { 314 dest.gport_type = _SHR_GPORT_TYPE_DEVPORT; 315 } else { 316 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 317 dest.modid = modid; 318 } 319 } else { 320 dest.modid = modid; 321 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 322 } 323 dest.port = port; 324 } 325 BCM_IF_ERROR_RETURN( 326 _bcm_esw_gport_construct(unit, &dest, gport)); 327 } 328 329 return BCM_E_NONE; 330 } 331 332 333 /* 334 * Function: 335 * _bcm_esw_l3_gport_resolve 336 * Purpose: 337 * Resolves a gport for L3 Module. 338 * Parameters: 339 * unit - SOC device unit number 340 * gport - gport provided 341 * port - (Out) Physical port decoded from gport 342 * modid - (Out) Module ID decodec from gport 343 * tgid - (Out) Trunk group ID decoded from gport 344 * gport - (Out) gport constructed from given arguments 345 * Returns: 346 * BCM_E_XXX 347 */ 348 int 349 _bcm_esw_l3_gport_resolve(int unit, bcm_gport_t gport, bcm_port_t *port, 350 bcm_module_t *modid, bcm_trunk_t *tgid, uint32 *flags) 351 { 352 int id; 353 bcm_trunk_t local_tgid; 354 bcm_module_t local_modid; 355 bcm_port_t local_port; 356 357 if ((NULL == port) || (NULL == modid) || (NULL == tgid) || 358 (NULL == flags)) { 359 return BCM_E_PARAM; 360 } 361 362 /* 363 * if incoming port is an acceptable virtual port 364 * for RIOT then use the port as it is. 365 */ 366 if ((BCM_GPORT_IS_BLACK_HOLE(gport)) 367 #ifdef BCM_RIOT_SUPPORT 368 || ((BCMI_RIOT_IS_ENABLED(unit)) 369 && (_bcm_vp_is_vfi_type(unit, gport))) 370 #endif 371 ) { 372 373 *port = gport; 374 return BCM_E_NONE; 375 } else { 376 BCM_IF_ERROR_RETURN( 377 _bcm_esw_gport_resolve(unit, gport, 378 &local_modid, &local_port, &local_tgid, &id)); 379 } 380 381 #if defined(BCM_HGPROXY_COE_SUPPORT) 382 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 383 BCM_GPORT_IS_SET(gport) && 384 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)) { 385 } else 386 #endif 387 #if defined(BCM_KATANA2_SUPPORT) 388 if (BCM_GPORT_IS_SET(gport) && 389 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT (unit, gport)) { 390 } else 391 #endif 392 if (-1 != id) { 393 return BCM_E_PARAM; 394 } 395 #ifdef BCM_KATANA_SUPPORT 396 if (SOC_IS_KATANAX(unit) && 397 ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) || 398 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) || 399 (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)))) { 400 *modid = local_modid; 401 *port = local_port; 402 *tgid = local_tgid; /* overlaying extended queue id in tgid */ 403 } else 404 #endif 405 if (BCM_TRUNK_INVALID != local_tgid) { 406 *flags |= BCM_L3_TGID; 407 *tgid = local_tgid; 408 } else { 409 *modid = local_modid; 410 *port = local_port; 411 } 412 413 return BCM_E_NONE; 414 } 415 416 #if defined(BCM_XGS3_SWITCH_SUPPORT) 417 #ifdef BCM_WARM_BOOT_SUPPORT 418 419 #define BCM_WB_PART_DEFAULT 0 /* L3 default warmboot state partition. */ 420 #define BCM_WB_PART_SOC_ECMP_STATE 1 /* SOC ECMP warmboot state partition. */ 421 422 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 423 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 424 #define BCM_WB_VERSION_1_3 SOC_SCACHE_VERSION(1,3) 425 #define BCM_WB_VERSION_1_4 SOC_SCACHE_VERSION(1,4) 426 #define BCM_WB_VERSION_1_5 SOC_SCACHE_VERSION(1,5) 427 #define BCM_WB_VERSION_1_6 SOC_SCACHE_VERSION(1,6) 428 #define BCM_WB_VERSION_1_7 SOC_SCACHE_VERSION(1,7) 429 #define BCM_WB_VERSION_1_8 SOC_SCACHE_VERSION(1,8) 430 #define BCM_WB_VERSION_1_9 SOC_SCACHE_VERSION(1,9) 431 #define BCM_WB_VERSION_1_10 SOC_SCACHE_VERSION(1,10) 432 #define BCM_WB_VERSION_1_11 SOC_SCACHE_VERSION(1,11) 433 #define BCM_WB_VERSION_1_12 SOC_SCACHE_VERSION(1,12) 434 #define BCM_WB_VERSION_1_13 SOC_SCACHE_VERSION(1,13) 435 #define BCM_WB_VERSION_1_14 SOC_SCACHE_VERSION(1,14) 436 #define BCM_WB_VERSION_1_15 SOC_SCACHE_VERSION(1,15) 437 #define BCM_WB_VERSION_1_16 SOC_SCACHE_VERSION(1,16) 438 #define BCM_WB_VERSION_1_17 SOC_SCACHE_VERSION(1,17) 439 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_17 440 441 442 /* 443 * Function: 444 * _bcm_esw_l3_sync 445 * Purpose: 446 * Record L3 module persisitent info for Level 2 Warm Boot 447 * Parameters: 448 * unit - StrataSwitch unit number. 449 * Returns: 450 * BCM_E_XXX 451 */ 452 453 int 454 _bcm_esw_l3_sync(int unit) 455 { 456 soc_scache_handle_t scache_handle; 457 uint8 *l3_scache_ptr; 458 int alloc_sz = 2 * sizeof(int32); /* Egress, HostAdd mode */ 459 int32 l3EgressMode = 0; 460 int32 l3HostAddMode = 0; 461 int alloc_size = 0; 462 SHR_BITDCL *ecmp_flags = NULL; 463 #ifdef BCM_TRIUMPH_SUPPORT 464 int32 l3IntfMapMode = 0; 465 int32 l3IngressMode = 0; 466 #endif /* BCM_TRIUMPH_SUPPORT */ 467 #ifdef BCM_TRIUMPH2_SUPPORT 468 int idx; 469 #endif 470 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 471 int l3_flags_synced = 0; 472 int l3_flags_alloced = 0; 473 int i; 474 uint8 flag = 0; 475 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 476 #ifdef BCM_TRIDENT2_SUPPORT 477 _bcm_l3_tbl_t *ecmp_tbl_ptr = BCM_XGS3_L3_TBL_PTR(unit, ecmp_grp); 478 #endif 479 #ifdef BCM_TOMAHAWK_SUPPORT 480 int j; 481 SHR_BITDCL *ecmp_l1_flags = NULL; 482 SHR_BITDCL *ecmp_l2_flags = NULL; 483 #endif /* BCM_TOMAHAWK_SUPPORT */ 484 #ifdef BCM_TRIUMPH_SUPPORT 485 if (soc_feature(unit, soc_feature_l3_ingress_interface)) { 486 alloc_sz += sizeof(int32); /* Ingress mode */ 487 alloc_sz += sizeof(int32); /* Interface Map mode */ 488 } 489 #endif /* BCM_TRIUMPH_SUPPORT */ 490 491 #ifdef BCM_TRIUMPH2_SUPPORT 492 /* For extended scache warmboot mode (level-2) only */ 493 if (soc_feature(unit, soc_feature_l3_dynamic_ecmp_group) && 494 BCM_XGS3_L3_MAX_ECMP_MODE(unit) && 495 !SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 496 alloc_sz += sizeof(uint16) * 497 BCM_XGS3_L3_ECMP_MAX_GROUPS(unit); 498 } 499 #endif 500 501 #ifdef BCM_TRIUMPH3_SUPPORT 502 if (soc_feature(unit, soc_feature_ecmp_dlb)) { 503 int ecmp_dlb_alloc_sz = 0; 504 505 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined (BCM_TRIDENT3_SUPPORT) 506 if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) { 507 BCM_IF_ERROR_RETURN 508 (bcm_th2_ecmp_dlb_wb_alloc_size_get(unit, &ecmp_dlb_alloc_sz)); 509 } else 510 #endif /* BCM_TOMAHAWK2_SUPPORT */ 511 { 512 BCM_IF_ERROR_RETURN 513 (bcm_tr3_ecmp_dlb_wb_alloc_size_get(unit, &ecmp_dlb_alloc_sz)); 514 } 515 alloc_sz += ecmp_dlb_alloc_sz; 516 } 517 #endif /* BCM_TRIUMPH3_SUPPORT */ 518 519 #ifdef BCM_TRIUMPH2_SUPPORT 520 if (soc_mem_field_valid(unit, L3_ECMP_COUNTm, BASE_PTRf) || 521 soc_mem_field_valid(unit, L3_ECMP_COUNTm, BASE_PTR_0f)) { 522 int wb_alloc_sz; 523 524 BCM_IF_ERROR_RETURN 525 (bcm_tr2_l3_ecmp_defragment_buffer_wb_alloc_size_get(unit, 526 &wb_alloc_sz)); 527 alloc_sz += wb_alloc_sz; 528 } 529 #endif /* BCM_TRIUMPH2_SUPPORT */ 530 531 #ifdef BCM_TRIDENT2_SUPPORT 532 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_6) { 533 if (soc_feature(unit, soc_feature_l3_ip4_options_profile)) { 534 int wb_alloc_sz; 535 BCM_IF_ERROR_RETURN 536 (_bcm_td2_l3_ip4_options_profile_scache_len_get(unit, &wb_alloc_sz)); 537 alloc_sz += wb_alloc_sz; 538 } 539 } 540 541 #endif /* BCM_TRIDENT2_SUPPORT */ 542 543 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_METROLITE_SUPPORT) ||\ 544 defined(BCM_HURRICANE3_SUPPORT) 545 if (soc_feature(unit, soc_feature_l3_ingress_interface) && 546 !soc_feature(unit, soc_feature_l3_ingress_intf_kt2_recover)) { 547 alloc_sz += SHR_BITALLOCSIZE(BCM_XGS3_L3_ING_IF_TBL_SIZE(unit)); 548 } 549 #endif /* defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_METROLITE_SUPPORT) || 550 * defined(BCM_HURRICANE3_SUPPORT) 551 */ 552 /* ECMP max paths info */ 553 alloc_sz += sizeof(int); 554 555 /* Determine ECMP_GROUP entry number in 32-bits words */ 556 if (soc_feature(unit, soc_feature_l3)) { 557 alloc_sz += SHR_BITALLOCSIZE(BCM_XGS3_L3_ECMP_MAX_GROUPS_2(unit)); 558 } 559 560 #ifdef BCM_TOMAHAWK_SUPPORT 561 /* Determine Hierarchical ECMP Level flags */ 562 if (soc_feature(unit, soc_feature_l3) && 563 soc_feature(unit, soc_feature_hierarchical_ecmp)) { 564 /* ECMP Level 1 flags */ 565 alloc_sz += SHR_BITALLOCSIZE(BCM_XGS3_L3_ECMP_MAX_GROUPS(unit)); 566 /* ECMP Level 2 flags */ 567 alloc_sz += SHR_BITALLOCSIZE(BCM_XGS3_L3_ECMP_MAX_GROUPS(unit)); 568 } 569 #endif /* BCM_TOMAHAWK_SUPPORT */ 570 571 #ifdef BCM_TRIDENT2_SUPPORT 572 /* Determine ECMP_GROUP resorting flags*/ 573 if (soc_feature(unit, soc_feature_l3)) { 574 alloc_sz += SHR_BITALLOCSIZE(BCM_XGS3_L3_ECMP_MAX_GROUPS_2(unit)); 575 } 576 #endif 577 #ifdef BCM_TRIUMPH3_SUPPORT 578 if (soc_feature(unit, soc_feature_l2gre)) { 579 alloc_sz += BCM_XGS3_L3_NH_TBL_SIZE(unit) * sizeof(uint8); 580 l3_flags_alloced = 1; 581 } 582 #endif /* BCM_TRIUMPH3_SUPPORT */ 583 #ifdef BCM_TRIDENT_SUPPORT 584 if (soc_feature(unit, soc_feature_trill)) { 585 if (!l3_flags_alloced) { 586 alloc_sz += BCM_XGS3_L3_NH_TBL_SIZE(unit) * sizeof(uint8); 587 l3_flags_alloced = 1; 588 } 589 } 590 #endif /* BCM_TRIDENT_SUPPORT */ 591 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 592 if (soc_feature(unit, soc_feature_vxlan) || 593 soc_feature(unit, soc_feature_vxlan_lite)) { 594 if (!l3_flags_alloced) { 595 alloc_sz += BCM_XGS3_L3_NH_TBL_SIZE(unit) * sizeof(uint8); 596 l3_flags_alloced = 1; 597 } 598 } 599 #endif /* BCM_TRIDENT2_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 600 #ifdef BCM_TOMAHAWK_SUPPORT 601 /* Determine ECMP_GROUP RH members */ 602 if (soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized)) { 603 /* ECMP RH max paths */ 604 alloc_sz += sizeof(int); 605 /* ECMP max paths info per RH group */ 606 alloc_sz += sizeof(uint16) * 607 BCM_XGS3_L3_ECMP_MAX_GROUPS(unit); 608 /* Group, member tuples */ 609 alloc_sz += (RH_ECMP_MEMBER_TBL_MAX(unit) * 610 (sizeof(int16) + sizeof(bcm_if_t))); 611 } 612 if (SOC_IS_TOMAHAWKX(unit)) { 613 /* This space is reserved for TH L3 extended view */ 614 bcm_th_l3_extended_required_scache_size_get(unit, &alloc_sz); 615 } 616 617 #endif /* BCM_TOMAHAWK_SUPPORT */ 618 619 /* memory needed for multi level prot s/w state */ 620 if (soc_feature(unit, soc_feature_l3) && 621 (soc_feature(unit, soc_feature_hierarchical_protection))) { 622 623 alloc_sz += (BCM_XGS3_L3_NH_TBL_SIZE(unit) * sizeof(int)); 624 } 625 626 #ifdef BCM_TRIDENT_SUPPORT 627 if (soc_feature(unit, soc_feature_nh_for_ifp_actions)) { 628 if (!l3_flags_alloced) { 629 alloc_sz += BCM_XGS3_L3_NH_TBL_SIZE(unit) * sizeof(uint8); 630 } 631 } 632 #endif /* BCM_TRIDENT_SUPPORT */ 633 634 #if defined(BCM_RIOT_SUPPORT) 635 if (soc_feature(unit, soc_feature_riot)) { 636 /* This space is reserved for TD2P L3 extended view */ 637 bcm_td2p_l3_extended_required_scache_size_get(unit, &alloc_sz); 638 } 639 #endif /* BCM_RIOT_SUPPORT */ 640 641 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 642 if (soc_feature(unit, soc_feature_dgm)) { 643 alloc_sz += sizeof(uint16) * 644 BCM_XGS3_L3_ECMP_MAX_GROUPS(unit); 645 } 646 #endif /* BCM_TOMAHAWK2_SUPPORT */ 647 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_15) { 648 /* Space reserved to store Maximum VRF IDs on the device */ 649 alloc_sz += sizeof(uint16); 650 } 651 if (!(BCM_L3_BK_FLAG_GET(unit, BCM_L3_BK_DISABLE_ADD_TO_ARL)) 652 && (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_16)) { 653 /* arl interface bitamp */ 654 alloc_sz += SHR_BITALLOCSIZE(soc_mem_index_count(unit, EGR_L3_INTFm)); 655 } 656 657 #if defined(BCM_TRX_SUPPORT) 658 if (soc_feature(unit, soc_feature_l3_ingress_interface) && 659 soc_feature(unit, soc_feature_l3_ingress_intf_kt2_recover)) { 660 alloc_sz += SHR_BITALLOCSIZE(BCM_XGS3_L3_ING_IF_TBL_SIZE(unit)); 661 } 662 #endif /* BCM_TRX_SUPPORT */ 663 664 L3_INIT(unit); 665 666 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_L3, 0); 667 BCM_IF_ERROR_RETURN 668 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 669 alloc_sz, &l3_scache_ptr, 670 BCM_WB_DEFAULT_VERSION, NULL)); 671 672 BCM_IF_ERROR_RETURN(bcm_xgs3_l3_egress_mode_get(unit, &l3EgressMode)); 673 sal_memcpy(l3_scache_ptr, &l3EgressMode, sizeof(l3EgressMode)); 674 l3_scache_ptr += sizeof(l3EgressMode); 675 676 #ifdef BCM_TRIUMPH_SUPPORT 677 if (soc_feature(unit, soc_feature_l3_ingress_interface)) { 678 BCM_IF_ERROR_RETURN(bcm_xgs3_l3_ingress_mode_get(unit, &l3IngressMode)); 679 sal_memcpy(l3_scache_ptr, &l3IngressMode, sizeof(l3IngressMode)); 680 l3_scache_ptr += sizeof(l3IngressMode); 681 } 682 #endif /* BCM_TRIUMPH_SUPPORT */ 683 684 BCM_IF_ERROR_RETURN(bcm_xgs3_l3_host_as_route_return_get(unit, &l3HostAddMode)); 685 sal_memcpy(l3_scache_ptr, &l3HostAddMode, sizeof(l3HostAddMode)); 686 l3_scache_ptr += sizeof(l3HostAddMode); 687 688 #ifdef BCM_TRIUMPH_SUPPORT 689 if (soc_feature(unit, soc_feature_l3_ingress_interface)) { 690 BCM_IF_ERROR_RETURN(bcm_xgs3_l3_ingress_intf_map_get(unit, &l3IntfMapMode)); 691 sal_memcpy(l3_scache_ptr, &l3IntfMapMode, sizeof(l3IntfMapMode)); 692 l3_scache_ptr += sizeof(l3IntfMapMode); 693 } 694 #endif /* BCM_TRIUMPH_SUPPORT */ 695 696 #ifdef BCM_TRIUMPH2_SUPPORT 697 /* For extended scache warmboot mode (level-2) only */ 698 if (soc_feature(unit, soc_feature_l3_dynamic_ecmp_group) && 699 BCM_XGS3_L3_MAX_ECMP_MODE(unit) && 700 !SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 701 for(idx=0; idx<BCM_XGS3_L3_ECMP_MAX_GROUPS(unit); idx++) { 702 sal_memcpy(l3_scache_ptr, 703 &(BCM_XGS3_L3_MAX_PATHS_PERGROUP_PTR(unit)[idx]), 704 sizeof(uint16)); 705 l3_scache_ptr += sizeof(uint16); 706 } 707 } 708 #endif 709 710 #ifdef BCM_TRIUMPH3_SUPPORT 711 if (soc_feature(unit, soc_feature_ecmp_dlb)) { 712 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined (BCM_TRIDENT3_SUPPORT) 713 if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) { 714 BCM_IF_ERROR_RETURN 715 (bcm_th2_ecmp_dlb_sync(unit, &l3_scache_ptr)); 716 } else 717 #endif /* BCM_TOMAHAWK2_SUPPORT */ 718 { 719 BCM_IF_ERROR_RETURN(bcm_tr3_ecmp_dlb_sync(unit, &l3_scache_ptr)); 720 } 721 } 722 #endif /* BCM_TRIUMPH3_SUPPORT */ 723 724 #ifdef BCM_TRIUMPH2_SUPPORT 725 if (soc_mem_field_valid(unit, L3_ECMP_COUNTm, BASE_PTRf) || 726 soc_mem_field_valid(unit, L3_ECMP_COUNTm, BASE_PTR_0f)) { 727 if (!soc_feature(unit, soc_feature_l3_no_ecmp)) { 728 BCM_IF_ERROR_RETURN 729 (bcm_tr2_l3_ecmp_defragment_buffer_sync(unit, &l3_scache_ptr)); 730 } 731 } 732 #endif /* BCM_TRIUMPH2_SUPPORT */ 733 734 #ifdef BCM_TRIDENT2_SUPPORT 735 if (soc_feature(unit, soc_feature_l3_ip4_options_profile)) { 736 BCM_IF_ERROR_RETURN(_bcm_td2_l3_ip4_options_sync(unit, &l3_scache_ptr)); 737 } 738 739 #endif /* BCM_TRIDENT2_SUPPORT */ 740 741 sal_memcpy(l3_scache_ptr, &BCM_XGS3_L3_ECMP_MAX_PATHS(unit), sizeof(int)); 742 l3_scache_ptr += sizeof(int); 743 744 /* Store ECMP_GRP valid/invalid bit to Scache */ 745 if (soc_feature(unit, soc_feature_l3) && !soc_feature(unit, soc_feature_l3_no_ecmp)) { 746 int i; 747 _bcm_l3_tbl_t *ecmp_tbl_ptr = BCM_XGS3_L3_TBL_PTR(unit, ecmp_grp); 748 alloc_size = SHR_BITALLOCSIZE(BCM_XGS3_L3_ECMP_MAX_GROUPS_2(unit)); 749 ecmp_flags = sal_alloc(alloc_size, "ECMP flags"); 750 if (ecmp_flags == NULL) { 751 return SOC_E_MEMORY; 752 } 753 sal_memset(ecmp_flags, 0, alloc_size); 754 755 for (i = 0; i <= ecmp_tbl_ptr->idx_max; i++) { 756 #ifdef BCM_TOMAHAWK3_SUPPORT 757 if (soc_feature(unit, soc_feature_l3_ecmp_hier_tbl) && 758 (BCM_XGS3_L3_TBL(unit, ecmp_info).ecmp_mode == 759 ecmp_mode_hierarchical) && 760 (i < (BCM_XGS3_L3_ECMP_MAX_GROUPS(unit) / 2))) { 761 _bcm_l3_tbl_t *hecmp_tbl_ptr = BCM_XGS3_L3_TBL_PTR(unit, hecmp_grp); 762 if (BCM_XGS3_L3_ENT_REF_CNT(hecmp_tbl_ptr, i) > 0) { 763 SHR_BITSET(ecmp_flags, i); 764 } 765 continue; 766 } 767 #endif 768 769 if (BCM_XGS3_L3_ENT_REF_CNT(ecmp_tbl_ptr, i) > 0) { 770 SHR_BITSET(ecmp_flags, i); 771 } 772 } 773 sal_memcpy(l3_scache_ptr, ecmp_flags, alloc_size); 774 l3_scache_ptr += SHR_BITALLOCSIZE(BCM_XGS3_L3_ECMP_MAX_GROUPS_2(unit)); 775 sal_free(ecmp_flags); 776 } 777 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_METROLITE_SUPPORT) ||\ 778 defined(BCM_HURRICANE3_SUPPORT) 779 if (soc_feature(unit, soc_feature_l3_ingress_interface) && 780 !soc_feature(unit, soc_feature_l3_ingress_intf_kt2_recover)) { 781 sal_memcpy(l3_scache_ptr, BCM_XGS3_L3_ING_IF_INUSE(unit), 782 SHR_BITALLOCSIZE(BCM_XGS3_L3_ING_IF_TBL_SIZE(unit))); 783 l3_scache_ptr += SHR_BITALLOCSIZE(BCM_XGS3_L3_ING_IF_TBL_SIZE(unit)); 784 } 785 #endif /* defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_METROLITE_SUPPORT) || 786 * defined(BCM_HURRICANE3_SUPPORT) 787 */ 788 789 #ifdef BCM_TRIDENT2_SUPPORT 790 if (soc_feature(unit, soc_feature_l3) && !soc_feature(unit, soc_feature_l3_no_ecmp)) { 791 alloc_size = SHR_BITALLOCSIZE(BCM_XGS3_L3_ECMP_MAX_GROUPS_2(unit)); 792 ecmp_flags = sal_alloc(alloc_size, "ECMP flags"); 793 if (ecmp_flags == NULL) { 794 return SOC_E_MEMORY; 795 } 796 sal_memset(ecmp_flags, 0, alloc_size); 797 798 for (i = 0; i <= ecmp_tbl_ptr->idx_max; i++) { 799 if (BCM_XGS3_L3_ENT_REF_CNT(ecmp_tbl_ptr, i) > 0 && 800 (BCM_XGS3_L3_ECMP_GROUP_FLAGS_ISSET(unit, i, 801 BCM_L3_ECMP_PATH_NO_SORTING))) { 802 SHR_BITSET(ecmp_flags, i); 803 } 804 } 805 sal_memcpy(l3_scache_ptr, ecmp_flags, alloc_size); 806 l3_scache_ptr += alloc_size; 807 sal_free(ecmp_flags); 808 } 809 #endif 810 #ifdef BCM_TRIUMPH3_SUPPORT 811 if (soc_feature(unit, soc_feature_l2gre)) { 812 for (i = 0; i < BCM_XGS3_L3_NH_TBL_SIZE(unit); i++) { 813 flag = BCM_XGS3_L3_ENT_FLAG(BCM_XGS3_L3_TBL_PTR(unit, next_hop), i); 814 sal_memcpy(l3_scache_ptr, &flag, sizeof(uint8)); 815 l3_scache_ptr += sizeof(uint8); 816 } 817 l3_flags_synced = 1; 818 } 819 #endif /* BCM_TRIUMPH3_SUPPORT */ 820 #ifdef BCM_TRIDENT_SUPPORT 821 if (soc_feature(unit, soc_feature_trill)) { 822 if (!l3_flags_synced) { 823 for (i = 0; i < BCM_XGS3_L3_NH_TBL_SIZE(unit); i++) { 824 flag = BCM_XGS3_L3_ENT_FLAG(BCM_XGS3_L3_TBL_PTR(unit, next_hop), i); 825 sal_memcpy(l3_scache_ptr, &flag, sizeof(uint8)); 826 l3_scache_ptr += sizeof(uint8); 827 } 828 l3_flags_synced = 1; 829 } 830 } 831 #endif /* BCM_TRIDENT_SUPPORT */ 832 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 833 if (soc_feature(unit, soc_feature_vxlan) || 834 soc_feature(unit, soc_feature_vxlan_lite)) { 835 if (!l3_flags_synced) { 836 for (i = 0; i < BCM_XGS3_L3_NH_TBL_SIZE(unit); i++) { 837 flag = BCM_XGS3_L3_ENT_FLAG( 838 BCM_XGS3_L3_TBL_PTR(unit, next_hop), i); 839 sal_memcpy(l3_scache_ptr, &flag, sizeof(uint8)); 840 l3_scache_ptr += sizeof(uint8); 841 } 842 l3_flags_synced = 1; 843 } 844 } 845 #endif /* BCM_TRIDENT2_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 846 #ifdef BCM_TOMAHAWK_SUPPORT 847 if (soc_feature(unit, soc_feature_l3) && 848 soc_feature(unit, soc_feature_hierarchical_ecmp)) { 849 alloc_size = SHR_BITALLOCSIZE(BCM_XGS3_L3_ECMP_MAX_GROUPS(unit)); 850 ecmp_l1_flags = sal_alloc(alloc_size, "ECMP level1 flags"); 851 if (ecmp_l1_flags == NULL) { 852 return SOC_E_MEMORY; 853 } 854 ecmp_l2_flags = sal_alloc(alloc_size, "ECMP level2 flags"); 855 if (ecmp_l2_flags == NULL) { 856 sal_free(ecmp_l1_flags); 857 return SOC_E_MEMORY; 858 } 859 sal_memset(ecmp_l1_flags, 0, alloc_size); 860 sal_memset(ecmp_l2_flags, 0, alloc_size); 861 for (j = 0; j <= ecmp_tbl_ptr->idx_max; j++) { 862 if (BCM_XGS3_L3_ENT_REF_CNT(ecmp_tbl_ptr, j) > 0 && 863 (BCM_XGS3_L3_ECMP_GROUP_FLAGS_ISSET(unit, j, 864 BCM_L3_ECMP_OVERLAY))) { 865 SHR_BITSET(ecmp_l1_flags, j); 866 } 867 if (BCM_XGS3_L3_ENT_REF_CNT(ecmp_tbl_ptr, j) > 0 && 868 (BCM_XGS3_L3_ECMP_GROUP_FLAGS_ISSET(unit, j, 869 BCM_L3_ECMP_UNDERLAY))) { 870 SHR_BITSET(ecmp_l2_flags, j); 871 } 872 } 873 sal_memcpy(l3_scache_ptr, ecmp_l1_flags, alloc_size); 874 l3_scache_ptr += alloc_size; 875 sal_memcpy(l3_scache_ptr, ecmp_l2_flags, alloc_size); 876 l3_scache_ptr += alloc_size; 877 sal_free(ecmp_l1_flags); 878 sal_free(ecmp_l2_flags); 879 } 880 if (soc_feature(unit, soc_feature_l3) && 881 soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized)) { 882 /* save interface count for each ecmp group */ 883 BCM_IF_ERROR_RETURN 884 (bcm_opt_l3_ecmp_rh_member_sync(unit, &l3_scache_ptr)); 885 } 886 if (SOC_IS_TOMAHAWKX(unit)) { 887 BCM_IF_ERROR_RETURN 888 (bcm_th_l3_extended_view_sync(unit, &l3_scache_ptr)); 889 } 890 #endif /* BCM_TOMAHAWK_SUPPORT */ 891 892 if (soc_feature(unit, soc_feature_l3) && 893 (soc_feature(unit, soc_feature_hierarchical_protection))) { 894 895 sal_memcpy(l3_scache_ptr, BCM_XGS3_L3_NH_MULTI_COUNT(unit), 896 BCM_XGS3_L3_NH_TBL_SIZE(unit) * sizeof(int)); 897 l3_scache_ptr += (BCM_XGS3_L3_NH_TBL_SIZE(unit) * sizeof(int)); 898 } 899 900 #ifdef BCM_TRIDENT_SUPPORT 901 if (soc_feature(unit, soc_feature_nh_for_ifp_actions)) { 902 if (!l3_flags_synced) { 903 for (i = 0; i < BCM_XGS3_L3_NH_TBL_SIZE(unit); i++) { 904 flag = BCM_XGS3_L3_ENT_FLAG(BCM_XGS3_L3_TBL_PTR(unit, next_hop), i); 905 sal_memcpy(l3_scache_ptr, &flag, sizeof(uint8)); 906 l3_scache_ptr += sizeof(uint8); 907 } 908 } 909 } 910 #endif /* BCM_TRIDENT_SUPPORT */ 911 #if defined(BCM_RIOT_SUPPORT) 912 if (soc_feature(unit, soc_feature_riot)) { 913 BCM_IF_ERROR_RETURN 914 (bcm_td2p_l3_extended_view_sync(unit, &l3_scache_ptr)); 915 } 916 #endif /* BCM_RIOT_SUPPORT */ 917 918 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 919 if (soc_feature(unit, soc_feature_dgm)) { 920 for (idx = 0; idx < BCM_XGS3_L3_ECMP_MAX_GROUPS(unit); idx++) { 921 sal_memcpy(l3_scache_ptr, 922 &(BCM_XGS3_L3_ALTERNATE_CNT_PTR(unit)[idx]), 923 sizeof(uint16)); 924 l3_scache_ptr += sizeof(uint16); 925 } 926 } 927 #endif 928 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_15) { 929 /* Maximum VRF Ids on the device */ 930 sal_memcpy(l3_scache_ptr, &(SOC_VRF_MAX(unit)), sizeof(uint16)); 931 l3_scache_ptr += sizeof(uint16); 932 } 933 if (!(BCM_L3_BK_FLAG_GET(unit, BCM_L3_BK_DISABLE_ADD_TO_ARL)) 934 && (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_16)) { 935 /* arl interface bit map */ 936 sal_memcpy(l3_scache_ptr, BCM_XGS3_L3_IF_ADD2ARL(unit), 937 SHR_BITALLOCSIZE(soc_mem_index_count(unit, EGR_L3_INTFm))); 938 l3_scache_ptr += SHR_BITALLOCSIZE(soc_mem_index_count(unit, EGR_L3_INTFm)); 939 } 940 941 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 942 if (soc_feature(unit, soc_feature_ecmp_dlb) && 943 soc_feature(unit, soc_feature_ecmp_dlb_optimized) && 944 !soc_feature(unit, soc_feature_th3_style_dlb)) { 945 BCM_IF_ERROR_RETURN( 946 bcm_th2_ecmp_dlb_member_sync(unit, &l3_scache_ptr)); 947 } 948 #endif /* BCM_TOMAHAWK2_SUPPORT */ 949 950 #if defined(BCM_TRX_SUPPORT) 951 if (soc_feature(unit, soc_feature_l3_ingress_interface) && 952 soc_feature(unit, soc_feature_l3_ingress_intf_kt2_recover)) { 953 sal_memcpy(l3_scache_ptr, BCM_XGS3_L3_ING_IF_INUSE(unit), 954 SHR_BITALLOCSIZE(BCM_XGS3_L3_ING_IF_TBL_SIZE(unit))); 955 l3_scache_ptr += SHR_BITALLOCSIZE(BCM_XGS3_L3_ING_IF_TBL_SIZE(unit)); 956 } 957 #endif 958 959 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT 960 if (soc_feature(unit, soc_feature_l3_ecmp_protected_access)) { 961 /* Sync ecmp protected warmboot state (separate partition). */ 962 BCM_IF_ERROR_RETURN(soc_esw_ecmp_protected_state_warmboot_sync(unit)); 963 } 964 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */ 965 966 return BCM_E_NONE; 967 } 968 969 /* 970 * Function: 971 * _bcm_esw_l3_warm_boot_alloc 972 * Purpose: 973 * Allocate persistent info memory for L3 module - Level 2 Warm Boot 974 * Parameters: 975 * unit - StrataSwitch unit number. 976 * Returns: 977 * BCM_E_XXX 978 */ 979 STATIC int 980 _bcm_esw_l3_warm_boot_alloc(int unit) 981 { 982 int rv; 983 int alloc_sz = 2 * sizeof(int32); /* Egress, Host modes */ 984 uint8 *l3_scache_ptr; 985 soc_scache_handle_t scache_handle; 986 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 987 int l3_flags_alloced = 0; 988 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 989 990 #ifdef BCM_TRIUMPH2_SUPPORT 991 BCM_XGS3_L3_MAX_ECMP_MODE(unit) = (SOC_IS_TRIUMPH3(unit)) ? TRUE : 992 soc_property_get(unit, spn_L3_MAX_ECMP_MODE, 0); 993 #endif 994 995 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1) { 996 #ifdef BCM_TRIUMPH_SUPPORT 997 if (soc_feature(unit, soc_feature_l3_ingress_interface)) { 998 alloc_sz += sizeof(int32); /* Ingress mode */ 999 } 1000 #endif /* BCM_TRIUMPH_SUPPORT */ 1001 } 1002 1003 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_2) { 1004 #ifdef BCM_TRIUMPH_SUPPORT 1005 if (soc_feature(unit, soc_feature_l3_ingress_interface)) { 1006 alloc_sz += sizeof(int32); /* intfMap mode */ 1007 } 1008 #endif /* BCM_TRIUMPH_SUPPORT */ 1009 } 1010 1011 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_3) { 1012 #ifdef BCM_TRIUMPH2_SUPPORT 1013 /* For extended scache warmboot mode (level-2) only */ 1014 if (soc_feature(unit, soc_feature_l3_dynamic_ecmp_group) && 1015 BCM_XGS3_L3_MAX_ECMP_MODE(unit) && 1016 !SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 1017 alloc_sz += sizeof(uint16) * 1018 BCM_XGS3_L3_ECMP_MAX_GROUPS(unit); 1019 } 1020 #endif 1021 1022 #ifdef BCM_TRIUMPH3_SUPPORT 1023 if (soc_feature(unit, soc_feature_ecmp_dlb)) { 1024 int ecmp_dlb_alloc_sz = 0; 1025 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 1026 if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) { 1027 BCM_IF_ERROR_RETURN 1028 (bcm_th2_ecmp_dlb_wb_alloc_size_get(unit, &ecmp_dlb_alloc_sz)); 1029 } else 1030 #endif /* BCM_TOMAHAWK2_SUPPORT */ 1031 { 1032 BCM_IF_ERROR_RETURN 1033 (bcm_tr3_ecmp_dlb_wb_alloc_size_get(unit, &ecmp_dlb_alloc_sz)); 1034 } 1035 alloc_sz += ecmp_dlb_alloc_sz; 1036 } 1037 #endif /* BCM_TRIUMPH3_SUPPORT */ 1038 1039 #ifdef BCM_TRIUMPH2_SUPPORT 1040 if (soc_mem_field_valid(unit, L3_ECMP_COUNTm, BASE_PTRf) || 1041 soc_mem_field_valid(unit, L3_ECMP_COUNTm, BASE_PTR_0f)) { 1042 int wb_alloc_sz; 1043 1044 BCM_IF_ERROR_RETURN 1045 (bcm_tr2_l3_ecmp_defragment_buffer_wb_alloc_size_get(unit, 1046 &wb_alloc_sz)); 1047 alloc_sz += wb_alloc_sz; 1048 } 1049 #endif /* BCM_TRIUMPH2_SUPPORT */ 1050 } 1051 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_6) { 1052 #ifdef BCM_TRIDENT2_SUPPORT 1053 if (soc_feature(unit, soc_feature_l3_ip4_options_profile)) { 1054 int wb_alloc_sz; 1055 BCM_IF_ERROR_RETURN 1056 (_bcm_td2_l3_ip4_options_profile_scache_len_get(unit, &wb_alloc_sz)); 1057 alloc_sz += wb_alloc_sz; 1058 } 1059 #endif /* BCM_TRIUMPH_SUPPORT */ 1060 } 1061 1062 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_METROLITE_SUPPORT) ||\ 1063 defined(BCM_HURRICANE3_SUPPORT) 1064 if (soc_feature(unit, soc_feature_l3_ingress_interface)){ 1065 alloc_sz += 1066 SHR_BITALLOCSIZE(soc_mem_index_count(unit, L3_IIFm)); 1067 } 1068 #endif /* defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_METROLITE_SUPPORT) || 1069 * defined(BCM_HURRICANE3_SUPPORT) 1070 */ 1071 /* to save max ecmp paths info */ 1072 alloc_sz += sizeof(int); 1073 1074 /* each bit save per L3_ECMP_GROUP entry valid/invalid */ 1075 if (soc_feature(unit, soc_feature_l3)) { 1076 alloc_sz += SHR_BITALLOCSIZE(BCM_XGS3_L3_ECMP_MAX_GROUPS_2(unit)); 1077 } 1078 1079 #ifdef BCM_TOMAHAWK_SUPPORT 1080 /* Determine Hierarchical ECMP Level flags */ 1081 if (soc_feature(unit, soc_feature_l3) && 1082 soc_feature(unit, soc_feature_hierarchical_ecmp)) { 1083 /* ECMP Level 1 flags */ 1084 alloc_sz += SHR_BITALLOCSIZE(BCM_XGS3_L3_ECMP_MAX_GROUPS(unit)); 1085 /* ECMP Level 2 flags */ 1086 alloc_sz += SHR_BITALLOCSIZE(BCM_XGS3_L3_ECMP_MAX_GROUPS(unit)); 1087 } 1088 #endif /* BCM_TOMAHAWK_SUPPORT */ 1089 1090 #ifdef BCM_TRIDENT2_SUPPORT 1091 /* ECMP group resorting flag */ 1092 if (soc_feature(unit, soc_feature_l3)) { 1093 alloc_sz += SHR_BITALLOCSIZE(BCM_XGS3_L3_ECMP_MAX_GROUPS_2(unit)); 1094 } 1095 #endif 1096 #ifdef BCM_TRIUMPH3_SUPPORT 1097 if (soc_feature(unit, soc_feature_l2gre)) { 1098 alloc_sz += soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 1099 l3_flags_alloced = 1; 1100 } 1101 #endif /* BCM_TRIUMPH3_SUPPORT */ 1102 #ifdef BCM_TRIDENT_SUPPORT 1103 if (soc_feature(unit, soc_feature_trill)) { 1104 if (!l3_flags_alloced) { 1105 alloc_sz += soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 1106 l3_flags_alloced = 1; 1107 } 1108 } 1109 #endif /* BCM_TRIDENT_SUPPORT */ 1110 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 1111 if (soc_feature(unit, soc_feature_vxlan) || 1112 soc_feature(unit, soc_feature_vxlan_lite)) { 1113 if (!l3_flags_alloced) { 1114 alloc_sz += soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 1115 l3_flags_alloced = 1; 1116 } 1117 } 1118 #endif /* BCM_TRIDENT2_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 1119 #ifdef BCM_TOMAHAWK_SUPPORT 1120 if (soc_feature(unit, soc_feature_l3) && 1121 soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized)) { 1122 /* Save RH max paths */ 1123 alloc_sz += sizeof(int); 1124 /* ECMP max paths info per RH group */ 1125 alloc_sz += sizeof(uint16) * 1126 BCM_XGS3_L3_ECMP_MAX_GROUPS(unit); 1127 /* save interface count for each ecmp group */ 1128 alloc_sz += (RH_ECMP_MEMBER_TBL_MAX(unit) * 1129 (sizeof(int16) + sizeof(bcm_if_t))); 1130 } 1131 if (SOC_IS_TOMAHAWKX(unit)) { 1132 int th_wb_l3_extended_size = 0; 1133 /* Get the required scache size */ 1134 bcm_th_l3_extended_required_scache_size_get(unit, &th_wb_l3_extended_size); 1135 alloc_sz += th_wb_l3_extended_size; 1136 } 1137 #endif /* BCM_TOMAHAWK_SUPPORT */ 1138 1139 /* memory needed for multi level prot s/w state */ 1140 if (soc_feature(unit, soc_feature_l3) && 1141 (soc_feature(unit, soc_feature_hierarchical_protection))) { 1142 1143 alloc_sz += (BCM_XGS3_L3_NH_TBL_SIZE(unit) * sizeof(int)); 1144 } 1145 1146 #ifdef BCM_TRIDENT_SUPPORT 1147 if (soc_feature(unit, soc_feature_nh_for_ifp_actions)) { 1148 if (!l3_flags_alloced) { 1149 alloc_sz += soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 1150 } 1151 } 1152 #endif /* BCM_TRIDENT_SUPPORT */ 1153 #if defined(BCM_RIOT_SUPPORT) 1154 if (soc_feature(unit, soc_feature_riot)) { 1155 int td2p_wb_l3_extended_size = 0; 1156 bcm_td2p_l3_extended_required_scache_size_get(unit, &td2p_wb_l3_extended_size); 1157 alloc_sz += td2p_wb_l3_extended_size; 1158 } 1159 #endif /* BCM_RIOT_SUPPORT */ 1160 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 1161 if (soc_feature(unit, soc_feature_dgm)) { 1162 alloc_sz += sizeof(uint16) * 1163 BCM_XGS3_L3_ECMP_MAX_GROUPS(unit); 1164 } 1165 #endif /* BCM_TOMAHAWK2_SUPPORT */ 1166 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_15) { 1167 /* Maximum VRF IDs on the device */ 1168 alloc_sz += sizeof(uint16); 1169 } 1170 1171 if (!(BCM_L3_BK_FLAG_GET(unit, BCM_L3_BK_DISABLE_ADD_TO_ARL)) && 1172 (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_16)) { 1173 /* arl interface bitamp */ 1174 alloc_sz += SHR_BITALLOCSIZE(soc_mem_index_count(unit, EGR_L3_INTFm)); 1175 } 1176 1177 1178 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_L3, 0); 1179 1180 /* This function is only used for Cold Boot */ 1181 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 1182 alloc_sz, &l3_scache_ptr, 1183 BCM_WB_DEFAULT_VERSION, NULL); 1184 1185 if (BCM_E_NOT_FOUND == rv) { 1186 /* Proceed with Level 1 Warm Boot */ 1187 rv = BCM_E_NONE; 1188 } 1189 1190 return rv; 1191 } 1192 #endif /* BCM_WARM_BOOT_SUPPORT */ 1193 #endif /* defined(BCM_XGS3_SWITCH_SUPPORT) */ 1194 1195 /* 1196 * Function: 1197 * bcm_l3_init 1198 * Purpose: 1199 * Initialize the L3 table, default IP table and the L3 interface table. 1200 * Parameters: 1201 * unit - SOC device unit number 1202 * Returns: 1203 * BCM_E_NONE Success 1204 * BCM_E_UNIT Illegal unit number 1205 * BCM_E_MEMORY Cannot allocate memory 1206 * BCM_E_INTERNAL Chip access failure 1207 * Notes: 1208 * This function has to be called before any other L3 functions. 1209 */ 1210 1211 int 1212 bcm_esw_l3_init(int unit) 1213 { 1214 _bcm_l3_bookkeeping_t *l3; 1215 1216 if (!soc_feature(unit, soc_feature_l3)) { 1217 if (!soc_feature(unit, soc_feature_miml_no_l3)) { 1218 return BCM_E_UNAVAIL; 1219 } 1220 } 1221 1222 if (!soc_property_get(unit, spn_L3_ENABLE, 1)) { 1223 l3_internal_initialized = 0; 1224 return BCM_E_DISABLED; 1225 } 1226 1227 1228 if (!l3_internal_initialized) { 1229 sal_memset(_bcm_l3_bk_info, 0, 1230 BCM_MAX_NUM_UNITS * sizeof(_bcm_l3_bookkeeping_t)); 1231 l3_internal_initialized = 1; 1232 } 1233 1234 l3 = &_bcm_l3_bk_info[unit]; 1235 l3->flags = 0; 1236 1237 if (soc_property_get(unit, spn_L3_DISABLE_ADD_TO_ARL, 0)) { 1238 BCM_L3_BK_FLAG_SET(unit, BCM_L3_BK_DISABLE_ADD_TO_ARL); 1239 } 1240 1241 #if defined(BCM_RIOT_SUPPORT) || defined(BCM_MULTI_LEVEL_ECMP_SUPPORT) 1242 if (soc_feature(unit, soc_feature_riot) || 1243 soc_feature(unit, soc_feature_multi_level_ecmp)) { 1244 l3->l3_ecmp_levels = 1245 soc_property_get(unit, spn_L3_ECMP_LEVELS, 1); 1246 } 1247 else { 1248 l3->l3_ecmp_levels = 1; 1249 } 1250 1251 l3->l3_ecmp_rh_overlay_entries = 1252 soc_property_get(unit, spn_RIOT_OVERLAY_ECMP_RESILIENT_HASH_SIZE, 0); 1253 1254 #ifdef BCM_TRIDENT3_SUPPORT 1255 if ((l3->l3_ecmp_levels > 1) && (l3->l3_ecmp_rh_overlay_entries == 0) && (SOC_IS_TRIDENT3X(unit))) { 1256 l3->l3_ecmp_rh_overlay_entries = 1257 soc_mem_view_index_count(unit, RH_ECMP_FLOWSETm) / 2; 1258 } 1259 1260 if (soc_feature(unit, soc_feature_td3_style_riot)) { 1261 l3->l3_ecmp_group_first_lkup_mem_size = 1262 soc_property_get(unit, spn_L3_ECMP_GROUP_FIRST_LKUP_MEM_SIZE, 0); 1263 l3->l3_ecmp_member_first_lkup_mem_size = 1264 soc_property_get(unit, spn_L3_ECMP_MEMBER_FIRST_LKUP_MEM_SIZE, 0); 1265 } 1266 #endif 1267 #endif 1268 1269 #ifdef BCM_RIOT_SUPPORT 1270 if (soc_property_get(unit, spn_RIOT_ENABLE, 0) && 1271 (soc_feature(unit, soc_feature_riot))) { 1272 1273 LOG_INFO(BSL_LS_BCM_L3, (BSL_META_U(unit, 1274 "Routing into and out of Tunnels is Enabled.\n"))); 1275 l3->riot_enable = TRUE; 1276 /* Hierarchical ECMP support required to support RIOT in TD3 1277 l3_ecmp_levels configuration should handle this */ 1278 } 1279 1280 l3->l3_intf_overlay_entries = 1281 soc_property_get(unit, spn_RIOT_OVERLAY_L3_INTF_MEM_SIZE, 0); 1282 l3->l3_nh_overlay_entries = 1283 soc_property_get(unit, spn_RIOT_OVERLAY_L3_EGRESS_MEM_SIZE, 0); 1284 1285 /* "alloc mode" is 0 by default for backward compatible */ 1286 l3->l3_intf_overlay_alloc_mode = 1287 soc_property_get(unit, spn_RIOT_OVERLAY_L3_INTF_MEM_ALLOC_MODE, 0); 1288 l3->l3_nh_overlay_alloc_mode = 1289 soc_property_get(unit, spn_RIOT_OVERLAY_L3_EGRESS_MEM_ALLOC_MODE, 0); 1290 1291 #endif 1292 1293 if (soc_property_get(unit, spn_EMBEDDED_NH_VP_SUPPORT, 0)) { 1294 #ifdef BCM_TOMAHAWK_SUPPORT 1295 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) { 1296 BCM_L3_BK_FLAG_SET(unit, BCM_L3_BK_ENABLE_MACDA_OUI_PROFILE); 1297 } 1298 #endif /* BCM_TOMAHAWK_SUPPORT */ 1299 } 1300 1301 l3->l3_nh_reserve_for_ecmp = soc_property_get( 1302 unit, spn_RESERVE_NH_FOR_ECMP, 0); 1303 1304 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT 1305 if (soc_feature(unit, soc_feature_l3_ecmp_protected_access)) { 1306 int tbl_size; 1307 soc_esw_ecmp_init_info_t init_info; 1308 soc_esw_ecmp_init_info_t_init(&init_info); 1309 1310 tbl_size = soc_mem_index_count(unit, L3_ECMPm); 1311 1312 init_info.num_banks = BCMI_L3_ECMP_MAX_BANKS(unit); 1313 init_info.bank_size = BCMI_L3_ECMP_PER_BANK(unit); 1314 init_info.num_levels = l3->l3_ecmp_levels; 1315 if (BCMI_L3_ECMP_IS_MULTI_LEVEL(unit)) { 1316 /* HECMP enabled. Table needs to be split into lkup1 & lkup2. */ 1317 init_info.lkup1_size = l3->l3_ecmp_member_first_lkup_mem_size; 1318 if (init_info.lkup1_size == 0) { 1319 /* HX5: If LKUP1 size is not specified, expectation is to 1320 * devide the table into two equal partitions. 1321 * 1322 * Since one bank needs to be reserved for protected accesses 1323 * to the table, we will end up reserving 2 banks here. 1324 */ 1325 tbl_size /= 2; 1326 init_info.lkup1_size = (tbl_size / 2); 1327 } else { 1328 /* One bank reserved. */ 1329 tbl_size -= init_info.bank_size; 1330 } 1331 init_info.lkup2_size = (tbl_size - init_info.lkup1_size); 1332 if (init_info.lkup2_size <= 0) { 1333 LOG_ERROR( 1334 BSL_LS_BCM_L3, 1335 (BSL_META_U(unit, "The config property " 1336 "l3_ecmp_member_first_lkup_mem_size cannot be " 1337 "greater than 2048 for this device.\n"))); 1338 return BCM_E_CONFIG; 1339 } 1340 } 1341 init_info.ecmp_if_offset = BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 1342 #ifdef BCM_WARM_BOOT_SUPPORT 1343 SOC_SCACHE_HANDLE_SET(init_info.scache_handle, unit, 1344 BCM_MODULE_L3, BCM_WB_PART_SOC_ECMP_STATE); 1345 #endif /* BCM_WARM_BOOT_SUPPORT */ 1346 1347 SOC_IF_ERROR_RETURN(soc_esw_ecmp_protected_init(unit, &init_info)); 1348 } 1349 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */ 1350 1351 #ifdef BCM_TRIDENT3_SUPPORT 1352 if (soc_feature(unit, soc_feature_cancun)) { 1353 /* These two features are supported on TD3 from 6.0.0 and above */ 1354 uint32 cancun_ver; 1355 SOC_IF_ERROR_RETURN(soc_cancun_version_get(unit, &cancun_ver)); 1356 1357 if (SOC_IS_TRIDENT3(unit) && (cancun_ver >= SOC_CANCUN_VERSION_DEF_6_0_0)) { 1358 SOC_FEATURE_SET(unit, soc_feature_large_scale_nat); 1359 SOC_FEATURE_SET(unit, soc_feature_vfi_switched_l2_change_fields); 1360 } 1361 } 1362 #endif /* BCM_TRIDENT3_SUPPORT */ 1363 1364 #ifdef BCM_WARM_BOOT_SUPPORT 1365 if (SOC_WARM_BOOT(unit)) { 1366 return (_bcm_l3_reinit(unit)); 1367 } 1368 #if defined(BCM_XGS3_SWITCH_SUPPORT) 1369 else { 1370 BCM_IF_ERROR_RETURN(_bcm_esw_l3_warm_boot_alloc(unit)); 1371 } 1372 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 1373 #endif /* BCM_WARM_BOOT_SUPPORT */ 1374 1375 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) 1376 if (soc_feature(unit, soc_feature_urpf) && 1377 SOC_REG_FIELD_VALID(unit, L3_DEFIP_RPF_CONTROLr, DEFIP_RPF_ENABLEf)) { 1378 BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, 1379 L3_DEFIP_RPF_CONTROLr, REG_PORT_ANY, DEFIP_RPF_ENABLEf, 0x0)); 1380 } 1381 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 1382 1383 BCM_IF_ERROR_RETURN(mbcm_driver[unit]->mbcm_l3_tables_init(unit)); 1384 1385 if (!BCM_XGS3_L3_NH_CNT(unit)) { 1386 BCM_XGS3_L3_NH_CNT(unit) = 1; 1387 } 1388 1389 l3->l3_initialized = 1; 1390 1391 if (soc_property_get(unit, spn_L3_INTF_VLAN_SPLIT_EGRESS, 0)) { 1392 BCM_XGS3_L3_FLAGS(unit) |= _BCM_L3_SHR_L3_INTF_VLAN_SPLIT_EGRESS; 1393 } else { 1394 BCM_XGS3_L3_FLAGS(unit) &= ~_BCM_L3_SHR_L3_INTF_VLAN_SPLIT_EGRESS; 1395 } 1396 1397 return BCM_E_NONE; 1398 } 1399 1400 /* 1401 * Function: 1402 * _bcm_esw_l3_intf_create 1403 * Purpose: 1404 * Create an L3 interface 1405 * Parameters: 1406 * unit - StrataXGS unit number 1407 * intf - interface info: l3a_mac_addr - MAC address; 1408 * l3a_vid - VLAN ID; 1409 * flag BCM_L3_ADD_TO_ARL: add mac address to arl table 1410 * with static bit and L3 bit set. 1411 * flag BCM_L3_WITH_ID: use specified interface ID l3a_intf. 1412 * flag BCM_L3_REPLACE: overwrite if interface already exists. 1413 * Returns: 1414 * BCM_E_XXX 1415 * Notes: 1416 * The VLAN table should be set up properly before this call. 1417 * The L3 interface ID is automatically assigned unless a specific 1418 * ID is requested with the BCM_L3_WITH_ID flag. 1419 */ 1420 1421 int 1422 _bcm_esw_l3_intf_create(int unit, bcm_l3_intf_t *intf) 1423 { 1424 _bcm_l3_intf_cfg_t l3i; 1425 bcm_l3_intf_t find_if; 1426 int rv; 1427 #ifdef BCM_RIOT_SUPPORT 1428 int32 l3IntfMapMode = 0; 1429 int32 l3IngressMode = 0; 1430 #endif 1431 1432 /* Input parameters check. */ 1433 if (NULL == intf) { 1434 return (BCM_E_PARAM); 1435 } 1436 1437 if (((intf->l3a_vrf > SOC_VRF_MAX(unit)) || 1438 (intf->l3a_vrf < BCM_L3_VRF_DEFAULT)) 1439 && !soc_feature(unit, soc_feature_fp_based_routing)) { 1440 1441 if ((!soc_mem_field_valid(unit, L3_IIFm, VRF_VALIDf)) || 1442 ((soc_mem_field_valid(unit, L3_IIFm, VRF_VALIDf) && 1443 (intf->l3a_vrf != BCM_L3_VRF_INVALID)))) { 1444 return (BCM_E_PARAM); 1445 } 1446 } 1447 1448 if (BCM_MAC_IS_ZERO(intf->l3a_mac_addr)) { 1449 return (BCM_E_PARAM); 1450 } 1451 1452 #ifdef BCM_RIOT_SUPPORT 1453 /* 1454 * If user sends vpn in place of vlan 1455 * then RIOT must be enabled 1456 */ 1457 if (_BCM_VPN_VFI_IS_SET((intf->l3a_vid))) { 1458 if (!(BCMI_RIOT_IS_ENABLED(unit))) { 1459 return BCM_E_UNAVAIL; 1460 } 1461 } 1462 /* 1463 * SDK will not allow creating RIOT flow without 1464 * l3 ingress mode and l3 interface map mode set. 1465 * It has been discussed with API team. 1466 */ 1467 if (BCMI_RIOT_VPN_VFI_IS_SET(unit, intf->l3a_vid)) { 1468 if (soc_feature(unit, soc_feature_l3_ingress_interface)) { 1469 BCM_IF_ERROR_RETURN( 1470 bcm_xgs3_l3_ingress_intf_map_get(unit, &l3IntfMapMode)); 1471 if (!l3IntfMapMode) { 1472 LOG_ERROR(BSL_LS_BCM_L3, (BSL_META_U(unit, 1473 "Enable bcmSwitchL3IngressInterfaceMapSet for overlay intf\n"))); 1474 1475 return BCM_E_PARAM; 1476 } 1477 BCM_IF_ERROR_RETURN( 1478 bcm_xgs3_l3_ingress_mode_get(unit, &l3IngressMode)); 1479 if (!l3IngressMode) { 1480 LOG_ERROR(BSL_LS_BCM_L3, (BSL_META_U(unit, 1481 "Enable bcmSwitchLl3IngressMode to create overlay intf\n"))); 1482 1483 return BCM_E_PARAM; 1484 } 1485 } else { 1486 LOG_ERROR(BSL_LS_BCM_L3, (BSL_META_U(unit, 1487 "Enable soc_feature_l3_ingress_interface for overlay intf\n"))); 1488 return BCM_E_PARAM; 1489 } 1490 } 1491 #endif 1492 1493 /* L3 interfaces can also accept VFI as part of vid. 1494 These interfaces are used in overlay domain 1495 */ 1496 if ((!BCM_VLAN_VALID(intf->l3a_vid)) 1497 #ifdef BCM_RIOT_SUPPORT 1498 && (BCMI_RIOT_VPN_VFI_IS_NOT_SET(unit, intf->l3a_vid)) 1499 #endif 1500 ) { 1501 return (BCM_E_PARAM); 1502 } 1503 if (!BCM_TTL_VALID(intf->l3a_ttl)) { 1504 return (BCM_E_PARAM); 1505 } 1506 1507 if (intf->l3a_group) { 1508 return (BCM_E_PARAM); 1509 } 1510 1511 if ((intf->l3a_group > SOC_INTF_CLASS_MAX(unit)) || 1512 (intf->l3a_group < 0)) { 1513 return (BCM_E_PARAM); 1514 } 1515 1516 if ((0 == SOC_IS_TRX(unit)) && (intf->l3a_inner_vlan)) { 1517 return (BCM_E_PARAM); 1518 } 1519 1520 sal_memset(&l3i, 0, sizeof(_bcm_l3_intf_cfg_t)); 1521 sal_memcpy(l3i.l3i_mac_addr, intf->l3a_mac_addr, sizeof(bcm_mac_t)); 1522 l3i.l3i_vid = intf->l3a_vid; 1523 l3i.l3i_inner_vlan = intf->l3a_inner_vlan; 1524 l3i.l3i_flags = intf->l3a_flags; 1525 #if defined(BCM_XGS3_SWITCH_SUPPORT) 1526 l3i.l3i_vrf = intf->l3a_vrf; 1527 l3i.l3i_group = intf->l3a_group; 1528 l3i.l3i_ttl = intf->l3a_ttl; 1529 l3i.l3i_mtu = intf->l3a_mtu; 1530 l3i.l3i_tunnel_idx = intf->l3a_tunnel_idx; 1531 sal_memcpy(&l3i.vlan_qos, &intf->vlan_qos, sizeof(bcm_l3_intf_qos_t)); 1532 sal_memcpy(&l3i.inner_vlan_qos, &intf->inner_vlan_qos, sizeof(bcm_l3_intf_qos_t)); 1533 sal_memcpy(&l3i.dscp_qos, &intf->dscp_qos, sizeof(bcm_l3_intf_qos_t)); 1534 #if defined(BCM_TRIUMPH3_SUPPORT) 1535 if ((intf->l3a_intf_class > SOC_INTF_CLASS_MAX(unit)) || 1536 (intf->l3a_intf_class < 0)) { 1537 return (BCM_E_PARAM); 1538 } 1539 l3i.l3i_class = intf->l3a_intf_class; 1540 #endif /* BCM_TRIUMPH3_SUPPORT */ 1541 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 1542 1543 #ifdef BCM_TRIDENT2_SUPPORT 1544 l3i.l3i_ip4_options_profile_id = intf->l3a_ip4_options_profile_id; 1545 l3i.l3i_nat_realm_id = intf->l3a_nat_realm_id; 1546 l3i.l3i_intf_flags = intf->l3a_intf_flags; 1547 #endif /* BCM_TRIDENT2_SUPPORT */ 1548 #ifdef BCM_RIOT_SUPPORT 1549 l3i.l3i_source_vp = intf->l3a_source_vp; 1550 #endif /* BCM_RIOT_SUPPORT */ 1551 #ifdef BCM_TRIDENT3_SUPPORT 1552 if (soc_feature(unit, soc_feature_flex_flow)) { 1553 l3i.flow_handle = intf->flow_handle; 1554 l3i.flow_option_handle = intf->flow_option_handle; 1555 l3i.num_of_fields = intf->num_of_fields; 1556 sal_memcpy(l3i.logical_fields, intf->logical_fields, 1557 intf->num_of_fields*sizeof(bcm_flow_logical_field_t)); 1558 } 1559 #endif /* BCM_TRIDENT3_SUPPORT */ 1560 1561 /* L3 interface ID given */ 1562 if (intf->l3a_flags & BCM_L3_WITH_ID) { 1563 /* Initilize interface lookup key. */ 1564 bcm_l3_intf_t_init(&find_if); 1565 1566 /* Set interface index. */ 1567 find_if.l3a_intf_id = intf->l3a_intf_id; 1568 1569 /* Read interface info by index. */ 1570 rv = bcm_esw_l3_intf_get(unit, &find_if); 1571 1572 if (rv == BCM_E_NONE) { 1573 /* BCM_L3_REPLACE flag must be set for interface update. */ 1574 if (!(intf->l3a_flags & BCM_L3_REPLACE)) { 1575 return BCM_E_EXISTS; 1576 } 1577 1578 /* Remove old interface layer 2 address if required. */ 1579 if (BCM_L3_INTF_ARL_GET(unit, intf->l3a_intf_id)) { 1580 BCM_IF_ERROR_RETURN 1581 (bcm_esw_l2_addr_delete(unit, find_if.l3a_mac_addr, 1582 find_if.l3a_vid)); 1583 BCM_L3_INTF_ARL_CLR(unit, find_if.l3a_intf_id); 1584 } 1585 } else if (rv != BCM_E_NOT_FOUND) { /* Other error */ 1586 return rv; 1587 } 1588 /* Set interface index. */ 1589 l3i.l3i_index = intf->l3a_intf_id; 1590 rv = mbcm_driver[unit]->mbcm_l3_intf_id_create(unit, &l3i); 1591 } else { 1592 rv = mbcm_driver[unit]->mbcm_l3_intf_create(unit, &l3i); 1593 } 1594 1595 if (rv < 0) { 1596 return (rv); 1597 } 1598 1599 if (!(intf->l3a_flags & BCM_L3_WITH_ID)) { 1600 intf->l3a_intf_id = l3i.l3i_index; 1601 } 1602 1603 return BCM_E_NONE; 1604 } 1605 1606 /* 1607 * Function: 1608 * bcm_esw_l3_intf_create 1609 * Purpose: 1610 * Create an L3 interface 1611 * Parameters: 1612 * unit - StrataXGS unit number 1613 * intf - interface info: l3a_mac_addr - MAC address; 1614 * l3a_vid - VLAN ID; 1615 * flag BCM_L3_ADD_TO_ARL: add mac address to arl table 1616 * with static bit and L3 bit set. 1617 * flag BCM_L3_WITH_ID: use specified interface ID l3a_intf. 1618 * flag BCM_L3_REPLACE: overwrite if interface already exists. 1619 * Returns: 1620 * BCM_E_XXX 1621 * Notes: 1622 * The VLAN table should be set up properly before this call. 1623 * The L3 interface ID is automatically assigned unless a specific 1624 * ID is requested with the BCM_L3_WITH_ID flag. 1625 */ 1626 int 1627 bcm_esw_l3_intf_create(int unit, bcm_l3_intf_t *intf) 1628 { 1629 int rv; 1630 1631 L3_INIT(unit); 1632 L3_LOCK(unit); 1633 1634 rv = _bcm_esw_l3_intf_create(unit, intf); 1635 1636 L3_UNLOCK(unit); 1637 return (rv); 1638 } 1639 1640 /* 1641 * Function: 1642 * bcm_esw_l3_intf_delete 1643 * Purpose: 1644 * Delete L3 interface based on L3 interface ID 1645 * Parameters: 1646 * unit - StrataXGS unit number 1647 * intf - interface structure with L3 interface ID as input 1648 * Returns: 1649 * BCM_E_XXX 1650 */ 1651 int 1652 bcm_esw_l3_intf_delete(int unit, bcm_l3_intf_t *intf) 1653 { 1654 _bcm_l3_intf_cfg_t l3i; 1655 int rv; 1656 1657 L3_INIT(unit); 1658 1659 if (NULL == intf) { 1660 return (BCM_E_PARAM); 1661 } 1662 1663 sal_memset(&l3i, 0, sizeof(_bcm_l3_intf_cfg_t)); 1664 l3i.l3i_index = intf->l3a_intf_id; 1665 l3i.l3i_flags = intf->l3a_flags; 1666 1667 L3_LOCK(unit); 1668 rv = mbcm_driver[unit]->mbcm_l3_intf_delete(unit, &l3i); 1669 L3_UNLOCK(unit); 1670 return (rv); 1671 } 1672 1673 /* 1674 * Function: 1675 * bcm_esw_l3_intf_find 1676 * Purpose: 1677 * Find the L3 intf number based on (MAC, VLAN) 1678 * Parameters: 1679 * unit - StrataXGS unit number 1680 * intf - (IN) interface (MAC, VLAN), (OUT)intf number 1681 * Returns: 1682 * BCM_E_XXX 1683 */ 1684 int 1685 bcm_esw_l3_intf_find(int unit, bcm_l3_intf_t *intf) 1686 { 1687 _bcm_l3_intf_cfg_t l3i; 1688 int rv; 1689 1690 L3_INIT(unit); 1691 1692 if (NULL == intf) { 1693 return (BCM_E_PARAM); 1694 } 1695 1696 if ((BCM_MAC_IS_MCAST(intf->l3a_mac_addr)) || 1697 (BCM_MAC_IS_ZERO(intf->l3a_mac_addr))) { 1698 return (BCM_E_PARAM); 1699 } 1700 1701 if ((!BCM_VLAN_VALID(intf->l3a_vid)) 1702 #ifdef BCM_RIOT_SUPPORT 1703 && (BCMI_RIOT_VPN_VFI_IS_NOT_SET(unit, intf->l3a_vid)) 1704 #endif 1705 ) { 1706 return (BCM_E_PARAM); 1707 } 1708 1709 sal_memset(&l3i, 0, sizeof(_bcm_l3_intf_cfg_t)); 1710 sal_memcpy(l3i.l3i_mac_addr, intf->l3a_mac_addr, sizeof(bcm_mac_t)); 1711 l3i.l3i_vid = intf->l3a_vid; 1712 1713 L3_LOCK(unit); 1714 1715 rv = mbcm_driver[unit]->mbcm_l3_intf_lookup(unit, &l3i); 1716 1717 L3_UNLOCK(unit); 1718 1719 intf->l3a_intf_id = l3i.l3i_index; 1720 1721 return rv; 1722 } 1723 1724 /* 1725 * Function: 1726 * bcm_esw_l3_intf_get 1727 * Purpose: 1728 * Given the L3 interface number, return the MAC and VLAN 1729 * Parameters: 1730 * unit - StrataXGS unit number 1731 * intf - (IN) L3 interface; (OUT)VLAN ID, 802.3 MAC for this L3 intf 1732 * Returns: 1733 * BCM_E_XXX 1734 */ 1735 int 1736 bcm_esw_l3_intf_get(int unit, bcm_l3_intf_t *intf) 1737 { 1738 _bcm_l3_intf_cfg_t l3i; 1739 int rv; 1740 1741 L3_INIT(unit); 1742 1743 if (NULL == intf) { 1744 return (BCM_E_PARAM); 1745 } 1746 1747 sal_memset(&l3i, 0, sizeof(_bcm_l3_intf_cfg_t)); 1748 l3i.l3i_index = intf->l3a_intf_id; 1749 1750 L3_LOCK(unit); 1751 1752 rv = mbcm_driver[unit]->mbcm_l3_intf_get(unit, &l3i); 1753 1754 L3_UNLOCK(unit); 1755 if (rv < 0) { 1756 return (rv); 1757 } 1758 1759 sal_memcpy(intf->l3a_mac_addr, l3i.l3i_mac_addr, sizeof(bcm_mac_t)); 1760 intf->l3a_vid = l3i.l3i_vid; 1761 intf->l3a_inner_vlan = l3i.l3i_inner_vlan; 1762 intf->l3a_tunnel_idx = l3i.l3i_tunnel_idx; 1763 intf->l3a_flags = l3i.l3i_flags; 1764 intf->l3a_vrf = l3i.l3i_vrf; 1765 intf->l3a_ttl = l3i.l3i_ttl; 1766 intf->l3a_mtu = l3i.l3i_mtu; 1767 intf->l3a_group = l3i.l3i_group; 1768 sal_memcpy(&intf->vlan_qos, &l3i.vlan_qos, sizeof(bcm_l3_intf_qos_t)); 1769 sal_memcpy(&intf->inner_vlan_qos, &l3i.inner_vlan_qos, sizeof(bcm_l3_intf_qos_t)); 1770 sal_memcpy(&intf->dscp_qos, &l3i.dscp_qos, sizeof(bcm_l3_intf_qos_t)); 1771 #ifdef BCM_TRIUMPH3_SUPPORT 1772 intf->l3a_intf_class = l3i.l3i_class; 1773 #endif /* BCM_TRIUMPH3_SUPPORT */ 1774 #ifdef BCM_TRIDENT2_SUPPORT 1775 intf->l3a_ip4_options_profile_id = l3i.l3i_ip4_options_profile_id; 1776 intf->l3a_nat_realm_id = l3i.l3i_nat_realm_id; 1777 intf->l3a_intf_flags = l3i.l3i_intf_flags; 1778 #endif /* BCM_TRIDENT2_SUPPORT */ 1779 #ifdef BCM_RIOT_SUPPORT 1780 intf->l3a_source_vp = l3i.l3i_source_vp; 1781 #endif 1782 #ifdef BCM_TRIDENT3_SUPPORT 1783 if (soc_feature(unit, soc_feature_flex_flow)) { 1784 intf->flow_handle = l3i.flow_handle; 1785 intf->flow_option_handle = l3i.flow_option_handle; 1786 intf->num_of_fields = l3i.num_of_fields; 1787 sal_memcpy(intf->logical_fields, l3i.logical_fields, 1788 l3i.num_of_fields*sizeof(bcm_flow_logical_field_t)); 1789 } 1790 #endif 1791 1792 return BCM_E_NONE; 1793 } 1794 1795 /* 1796 * Function: 1797 * bcm_esw_l3_intf_find_vlan 1798 * Purpose: 1799 * Find the L3 interface by VLAN 1800 * Parameters: 1801 * unit - StrataXGS unit number 1802 * intf - (IN) VID, (OUT)L3 intf info 1803 * Returns: 1804 * BCM_E_XXX 1805 */ 1806 int 1807 bcm_esw_l3_intf_find_vlan(int unit, bcm_l3_intf_t *intf) 1808 { 1809 int rv; 1810 _bcm_l3_intf_cfg_t l3i; 1811 1812 L3_INIT(unit); 1813 1814 if (NULL == intf) { 1815 return (BCM_E_PARAM); 1816 } 1817 1818 if (!BCM_VLAN_VALID(intf->l3a_vid) 1819 #ifdef BCM_RIOT_SUPPORT 1820 && !BCMI_RIOT_VPN_VFI_IS_SET(unit, intf->l3a_vid) 1821 #endif 1822 ) { 1823 return (BCM_E_PARAM); 1824 } 1825 1826 sal_memset(&l3i, 0, sizeof(_bcm_l3_intf_cfg_t)); 1827 l3i.l3i_vid = intf->l3a_vid; 1828 1829 L3_LOCK(unit); 1830 rv = mbcm_driver[unit]->mbcm_l3_intf_get_by_vid(unit, &l3i); 1831 1832 L3_UNLOCK(unit); 1833 if (rv < 0) { 1834 return (rv); 1835 } 1836 1837 intf->l3a_intf_id = l3i.l3i_index; 1838 sal_memcpy(intf->l3a_mac_addr, l3i.l3i_mac_addr, sizeof(bcm_mac_t)); 1839 intf->l3a_tunnel_idx = l3i.l3i_tunnel_idx; 1840 intf->l3a_flags = l3i.l3i_flags; 1841 intf->l3a_vrf = l3i.l3i_vrf; 1842 intf->l3a_ttl = l3i.l3i_ttl; 1843 intf->l3a_mtu = l3i.l3i_mtu; 1844 intf->l3a_group = l3i.l3i_group; 1845 #ifdef BCM_TRIDENT2_SUPPORT 1846 intf->l3a_intf_flags = l3i.l3i_intf_flags; 1847 #endif /* BCM_TRIDENT2_SUPPORT */ 1848 1849 return (BCM_E_NONE); 1850 } 1851 1852 /* 1853 * Function: 1854 * bcm_esw_l3_intf_delete_all 1855 * Purpose: 1856 * Delete all L3 interfaces 1857 * Parameters: 1858 * unit - SOC device unit number 1859 * Returns: 1860 * BCM_E_XXXX 1861 */ 1862 int 1863 bcm_esw_l3_intf_delete_all(int unit) 1864 { 1865 int rv; 1866 L3_INIT(unit); 1867 L3_LOCK(unit); 1868 1869 rv = mbcm_driver[unit]->mbcm_l3_intf_delete_all(unit); 1870 1871 L3_UNLOCK(unit); 1872 1873 return (rv); 1874 } 1875 1876 /* 1877 * Function: 1878 * bcm_esw_l3_host_find 1879 * Purpose: 1880 * Find an entry from the L3 host table given IP address. 1881 * Parameters: 1882 * unit - SOC device unit number 1883 * info - (Out) Pointer to memory for bcm_l3_host_t. 1884 * Returns: 1885 * BCM_E_XXX 1886 * Notes: 1887 * 1) The hit returned may be either L3SH or L3DH or Both 1888 * 2) Flag set to BCM_L3_IP6 for IPv6, default is IPv4 1889 */ 1890 1891 int 1892 bcm_esw_l3_host_find(int unit, bcm_l3_host_t *info) 1893 { 1894 _bcm_l3_cfg_t l3cfg; 1895 int rt; 1896 1897 L3_INIT(unit); 1898 1899 if (NULL == info) { 1900 return (BCM_E_PARAM); 1901 } 1902 1903 /* Vrf is in device supported range check. */ 1904 if ((info->l3a_vrf > SOC_VRF_MAX(unit)) || 1905 (info->l3a_vrf < BCM_L3_VRF_DEFAULT)) { 1906 return (BCM_E_PARAM); 1907 } 1908 1909 /* Check that device supports ipv6. */ 1910 if (BCM_L3_NO_IP6_SUPPORT(unit, info->l3a_flags)) { 1911 return (BCM_E_UNAVAIL); 1912 } 1913 1914 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 1915 l3cfg.l3c_flags = info->l3a_flags; 1916 l3cfg.l3c_vrf = info->l3a_vrf; 1917 #ifdef BCM_TRIDENT3_SUPPORT 1918 if (soc_feature(unit, soc_feature_flex_flow)) { 1919 l3cfg.l3c_flow_handle = info->flow_handle; 1920 l3cfg.l3c_flow_option_handle = info->flow_option_handle; 1921 l3cfg.l3c_num_of_fields = info->num_of_fields; 1922 sal_memcpy(l3cfg.l3c_logical_fields, info->logical_fields, 1923 info->num_of_fields*sizeof(bcm_flow_logical_field_t)); 1924 } 1925 #endif /* BCM_TRIDENT3_SUPPORT */ 1926 1927 L3_LOCK(unit); 1928 if (info->l3a_flags & BCM_L3_IP6) { 1929 sal_memcpy(l3cfg.l3c_ip6, info->l3a_ip6_addr, BCM_IP6_ADDRLEN); 1930 rt = mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg); 1931 } else { 1932 l3cfg.l3c_ip_addr = info->l3a_ip_addr; 1933 rt = mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg); 1934 } 1935 L3_UNLOCK(unit); 1936 1937 if (rt < 0) { 1938 return (rt); 1939 } 1940 1941 info->l3a_flags = l3cfg.l3c_flags; 1942 info->l3a_flags2 = l3cfg.l3c_flags2; 1943 if (l3cfg.l3c_flags & BCM_L3_IPMC) { 1944 info->l3a_ipmc_ptr = l3cfg.l3c_ipmc_ptr; 1945 info->l3a_ipmc_ptr_l2 = l3cfg.l3c_ipmc_ptr_l2; 1946 } 1947 sal_memcpy(info->l3a_nexthop_mac, l3cfg.l3c_mac_addr, sizeof(bcm_mac_t)); 1948 info->l3a_intf = l3cfg.l3c_intf; 1949 info->l3a_port_tgid = l3cfg.l3c_port_tgid; 1950 info->l3a_modid = l3cfg.l3c_modid; 1951 1952 /* For devices that support the overlaid_address_range, if the RPE 1953 field is '0', the 4 bits of PRI are the upper 4 bits 1954 (of total 10 bits) of the classId, the lower 6 come from classId 1955 as usual, for rest of the cases, the classID and PRI are copied 1956 over directly. 1957 */ 1958 if (soc_feature(unit, soc_feature_overlaid_address_class) && 1959 !BCM_L3_RPE_SET(l3cfg.l3c_flags)) { 1960 info->l3a_lookup_class = ((l3cfg.l3c_prio & 0xF) << 6); 1961 info->l3a_lookup_class |= (l3cfg.l3c_lookup_class & 0x3F); 1962 } else { 1963 info->l3a_lookup_class = l3cfg.l3c_lookup_class; 1964 info->l3a_pri = l3cfg.l3c_prio; 1965 } 1966 1967 #ifdef BCM_TRIUMPH2_SUPPORT 1968 if (soc_feature(unit, soc_feature_wlan) && 1969 BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, l3cfg.l3c_intf)) { 1970 /* Get DVP using the egress object ID and construct a gport */ 1971 egr_l3_next_hop_entry_t next_hop; 1972 _bcm_gport_dest_t dest; 1973 int nh_idx = l3cfg.l3c_intf - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 1974 BCM_IF_ERROR_RETURN 1975 (READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_idx, &next_hop)); 1976 dest.wlan_id = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &next_hop, DVPf); 1977 dest.gport_type = _SHR_GPORT_TYPE_WLAN_PORT; 1978 BCM_IF_ERROR_RETURN( 1979 _bcm_esw_gport_construct(unit, &dest, &(info->l3a_port_tgid))); 1980 } else 1981 #endif 1982 #ifdef BCM_TOMAHAWK_SUPPORT 1983 if (soc_feature(unit, soc_feature_virtual_port_routing) && 1984 BCM_L3_BK_FLAG_GET(unit, BCM_L3_BK_ENABLE_MACDA_OUI_PROFILE)) { 1985 if (BCM_GPORT_IS_NIV_PORT(info->l3a_port_tgid) || 1986 BCM_GPORT_IS_EXTENDER_PORT(info->l3a_port_tgid)) { 1987 /* For NIV and PE, info->l3a_port_tgid already represents a gport 1988 * Hence simply return from this routine. 1989 */ 1990 return BCM_E_NONE; 1991 } else { 1992 BCM_IF_ERROR_RETURN 1993 (_bcm_esw_l3_gport_construct(unit, info->l3a_port_tgid, 1994 info->l3a_modid, info->l3a_port_tgid, 1995 info->l3a_flags, 1996 &(info->l3a_port_tgid))); 1997 } 1998 } else 1999 #endif /* BCM_TOMAHAWK_SUPPORT */ 2000 { 2001 BCM_IF_ERROR_RETURN 2002 (_bcm_esw_l3_gport_construct(unit, info->l3a_port_tgid, 2003 info->l3a_modid, info->l3a_port_tgid, 2004 info->l3a_flags, 2005 &(info->l3a_port_tgid))); 2006 } 2007 return BCM_E_NONE; 2008 } 2009 2010 /* 2011 * Function: 2012 * bcm_esw_l3_host_add 2013 * Purpose: 2014 * Add an entry to the L3 table. 2015 * Parameters: 2016 * unit - SOC unit number 2017 * info - Pointer to bcm_l3_host_t containing fields related to IP table. 2018 * Returns: 2019 * BCM_E_XXX 2020 * Notes: 2021 * 1. Flag set to BCM_L3_IP6 for IPv6, default is IPv4 2022 * 2023 * 2. If BCM_L3_REPLACE flag is set, replace exisiting L3 entry 2024 * with new information, otherwise, add only if key does not 2025 * exist. 2026 * On XGS, the DEFIP table points to the L3 entry, so this 2027 * function will affect both L3 switching entry and routes. 2028 * The affected route is one whose next hop IP address 2029 * is the key (2nd parameter of this function). 2030 */ 2031 2032 int 2033 bcm_esw_l3_host_add(int unit, bcm_l3_host_t *info) 2034 { 2035 int rv; 2036 _bcm_l3_cfg_t l3cfg; 2037 bcm_l3_host_t info_orig, info_local; 2038 bcm_l3_route_t info_route; 2039 2040 L3_INIT(unit); 2041 2042 if (NULL == info) { 2043 return (BCM_E_PARAM); 2044 } 2045 2046 /* Copy provided structure to local so it can be modified. */ 2047 sal_memcpy(&info_local, info, sizeof(bcm_l3_host_t)); 2048 2049 /* Vrf is in device supported range check. */ 2050 if ((info_local.l3a_vrf > SOC_VRF_MAX(unit)) || 2051 (info_local.l3a_vrf < BCM_L3_VRF_DEFAULT)) { 2052 return (BCM_E_PARAM); 2053 } 2054 2055 /* Check that device supports ipv6. */ 2056 if (BCM_L3_NO_IP6_SUPPORT(unit, info_local.l3a_flags)) { 2057 return (BCM_E_UNAVAIL); 2058 } 2059 2060 if (info_local.l3a_intf < 0) { 2061 return (BCM_E_PARAM); 2062 } 2063 2064 /* FP lookup class range check. */ 2065 /* These are the 3 classID validity checks: 2066 2067 1. If the device is a TR3, the 10 bit classID is natively supported. 2068 and hence we check against the same. 2069 2070 2. For devices that support the overlaid_address_range, if the RPE 2071 field is '0', the 4 bits of PRI are the upper 4 bits 2072 (of total 10 bits) of the classId, the lower 6 come from classId 2073 as usual, we hence need to check the value range accordingly. 2074 2075 3. For rest of the cases classID is restricted to 6 bits and we 2076 need to check accordingly. 2077 */ 2078 2079 if (soc_feature(unit, soc_feature_extended_address_class)) { 2080 if ((info_local.l3a_lookup_class > SOC_EXT_ADDR_CLASS_MAX(unit)) || 2081 (info_local.l3a_lookup_class < 0)) { 2082 return (BCM_E_PARAM); 2083 } 2084 } else if (soc_feature(unit, soc_feature_overlaid_address_class) && 2085 !BCM_L3_RPE_SET(info_local.l3a_flags)) { 2086 if ((info_local.l3a_lookup_class > 2087 SOC_OVERLAID_ADDR_CLASS_MAX(unit)) || 2088 (info_local.l3a_lookup_class < 0)) { 2089 return (BCM_E_PARAM); 2090 } 2091 } else if ((info_local.l3a_lookup_class > SOC_ADDR_CLASS_MAX(unit)) || 2092 (info_local.l3a_lookup_class < 0)) { 2093 return (BCM_E_PARAM); 2094 } 2095 2096 /* 2097 * When RPE is not set and soc_feature_overlaid_address_class is 2098 * not enabled, priority values range from 0-7. 2099 * When RPE is set, priority values range from 0-15. 2100 * When RPE is not set but soc_feature_overlaid_address_class 2101 * is enabled, priority value ranges from 0-15. 2102 */ 2103 if(!BCM_L3_RPE_SET(info_local.l3a_flags) && 2104 !soc_feature(unit, soc_feature_overlaid_address_class)) { 2105 if (!BCM_PRIORITY_VALID(info_local.l3a_pri)) { 2106 return (BCM_E_PARAM); 2107 } 2108 } else { 2109 if (!BCM_RPE_PRIORITY_VALID(info_local.l3a_pri)) { 2110 return (BCM_E_PARAM); 2111 } 2112 } 2113 if (BCM_GPORT_IS_SET(info_local.l3a_port_tgid)) { 2114 bcm_trunk_t trunk_id; 2115 int vp_routing = FALSE; 2116 2117 if (BCM_GPORT_IS_NIV_PORT(info_local.l3a_port_tgid) || 2118 BCM_GPORT_IS_EXTENDER_PORT(info_local.l3a_port_tgid)) { 2119 if (soc_feature(unit, soc_feature_virtual_port_routing) && 2120 BCM_L3_BK_FLAG_GET(unit, BCM_L3_BK_ENABLE_MACDA_OUI_PROFILE)) { 2121 vp_routing = TRUE; 2122 } else { 2123 /* host add only accepts niv/port extender gport when config 2124 * property EMBEDDED_NH_VP_SUPPORT is enabled for the device. 2125 */ 2126 return BCM_E_PARAM; 2127 } 2128 } 2129 2130 if (vp_routing) { 2131 /* l3a_port_tgid can contain either port or trunk */ 2132 rv = _bcm_esw_gport_resolve(unit, info_local.l3a_port_tgid, 2133 &(info_local.l3a_modid), 2134 &(info_local.l3a_port_tgid), 2135 &trunk_id, 2136 &(info_local.encap_id)); 2137 if (-1 != trunk_id) { 2138 info_local.l3a_flags |= BCM_L3_TGID; 2139 info_local.l3a_port_tgid = trunk_id; 2140 } 2141 } else { 2142 BCM_IF_ERROR_RETURN( 2143 _bcm_esw_l3_gport_resolve(unit, info_local.l3a_port_tgid, 2144 &(info_local.l3a_port_tgid), 2145 &(info_local.l3a_modid), 2146 &(info_local.l3a_port_tgid), 2147 &(info_local.l3a_flags))); 2148 } 2149 } else if (!(info_local.l3a_flags & BCM_L3_TGID)) { 2150 PORT_DUALMODID_VALID(unit, info_local.l3a_port_tgid); 2151 } 2152 /* Check if host entry already exists. */ 2153 L3_LOCK(unit); 2154 info_orig = info_local; 2155 rv = bcm_esw_l3_host_find(unit, &info_orig); 2156 if ((BCM_SUCCESS(rv)) && (0 == (info_local.l3a_flags & BCM_L3_REPLACE))) { 2157 /* If so BCM_L3_REPLACE flag must be set. */ 2158 L3_UNLOCK(unit); 2159 return (BCM_E_EXISTS); 2160 } else if ((BCM_FAILURE(rv)) && (BCM_E_NOT_FOUND != rv)) { 2161 L3_UNLOCK(unit); 2162 return (rv); 2163 } 2164 2165 /* Initialize mbcm structure. */ 2166 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 2167 sal_memcpy(l3cfg.l3c_mac_addr, info_local.l3a_nexthop_mac, sizeof(bcm_mac_t)); 2168 l3cfg.l3c_intf = info_local.l3a_intf; 2169 l3cfg.l3c_modid = info_local.l3a_modid; 2170 l3cfg.l3c_port_tgid = info_local.l3a_port_tgid; 2171 l3cfg.l3c_flags = info_local.l3a_flags; 2172 l3cfg.l3c_flags2 = info_local.l3a_flags2; 2173 l3cfg.l3c_vrf = info_local.l3a_vrf; 2174 l3cfg.l3c_encap_id = info_local.encap_id; 2175 if (info_local.l3a_flags & BCM_L3_IPMC) { 2176 l3cfg.l3c_ipmc_ptr = _BCM_MULTICAST_ID_GET(info_local.l3a_ipmc_ptr); 2177 l3cfg.l3c_ipmc_ptr_l2 = _BCM_MULTICAST_ID_GET(info_local.l3a_ipmc_ptr_l2); 2178 } 2179 2180 #ifdef BCM_TRIDENT3_SUPPORT 2181 if (soc_feature(unit, soc_feature_flex_flow)) { 2182 l3cfg.l3c_flow_handle = info_local.flow_handle; 2183 l3cfg.l3c_flow_option_handle = info_local.flow_option_handle; 2184 l3cfg.l3c_num_of_fields = info_local.num_of_fields; 2185 sal_memcpy(l3cfg.l3c_logical_fields, info_local.logical_fields, 2186 info_local.num_of_fields*sizeof(bcm_flow_logical_field_t)); 2187 } 2188 #endif /* BCM_TRIDENT3_SUPPORT */ 2189 2190 /* If the chip uses the 'soc_feature_overlaid_address_class' feature and 2191 if the RPE is '0' the upper 4 bits of the classId need to be copied 2192 from the PRI field, the lower bits get copied to the classId field as, 2193 for all other cases, the classID and PRI are assigned directly */ 2194 if (soc_feature(unit, soc_feature_overlaid_address_class) && 2195 (!BCM_L3_RPE_SET(info_local.l3a_flags))) { 2196 l3cfg.l3c_prio = ((info_local.l3a_lookup_class & 0x3C0) >> 6); 2197 l3cfg.l3c_lookup_class = (info_local.l3a_lookup_class & 0x3F); 2198 } else { 2199 l3cfg.l3c_prio = info_local.l3a_pri; 2200 l3cfg.l3c_lookup_class = info_local.l3a_lookup_class; 2201 } 2202 2203 if (info_local.l3a_flags & BCM_L3_IP6) { 2204 sal_memcpy(l3cfg.l3c_ip6, info_local.l3a_ip6_addr, BCM_IP6_ADDRLEN); 2205 /* Add host entry - no prior entry found */ 2206 if (BCM_FAILURE(rv)) { 2207 rv = mbcm_driver[unit]->mbcm_l3_ip6_add(unit, &l3cfg); 2208 } else { 2209 /* Remove Route entry and add to Host table */ 2210 if ((info_orig.l3a_flags & BCM_L3_HOST_AS_ROUTE) && 2211 !(info_local.l3a_flags2 & BCM_L3_FLAGS2_ROUTE_NO_MOVE) && 2212 !soc_property_get(unit, spn_HOST_AS_ROUTE_DISABLE, 0)) { 2213 2214 /* Entry exists within ROUTE table */ 2215 l3cfg.l3c_flags &= ~BCM_L3_HOST_AS_ROUTE; 2216 2217 /* Add entry to HOST Table */ 2218 rv = mbcm_driver[unit]->mbcm_l3_ip6_add(unit, &l3cfg); 2219 2220 if (BCM_SUCCESS(rv)) { 2221 2222 /* Init ROUTE entry */ 2223 sal_memset(&info_route, 0, sizeof(bcm_l3_route_t)); 2224 sal_memcpy(info_route.l3a_nexthop_mac, l3cfg.l3c_mac_addr, sizeof(bcm_mac_t)); 2225 info_route.l3a_vrf = l3cfg.l3c_vrf; 2226 info_route.l3a_flags = BCM_L3_IP6; 2227 sal_memcpy(info_route.l3a_ip6_net, l3cfg.l3c_ip6, 2228 sizeof(bcm_ip6_t)); 2229 bcm_ip6_mask_create(info_route.l3a_ip6_mask, 128); 2230 info_route.l3a_intf = l3cfg.l3c_intf; 2231 info_route.l3a_modid = l3cfg.l3c_modid; 2232 info_route.l3a_port_tgid = l3cfg.l3c_port_tgid; 2233 info_route.l3a_pri = l3cfg.l3c_prio; 2234 info_route.l3a_lookup_class = l3cfg.l3c_lookup_class; 2235 2236 /* Delete ROUTE entry */ 2237 rv = bcm_esw_l3_route_delete(unit, &info_route); 2238 if (BCM_SUCCESS(rv)) { 2239 /* Special return value - as entry existed within ROUTE table */ 2240 #if defined(BCM_FIREBOLT_SUPPORT) 2241 (void) bcm_xgs3_l3_host_as_route_return_get(unit, &rv); 2242 #endif /* BCM_FIREBOLT_SUPPORT */ 2243 } 2244 } else { 2245 /* Update ROUTE entry */ 2246 l3cfg.l3c_flags |= BCM_L3_HOST_AS_ROUTE; 2247 rv = mbcm_driver[unit]->mbcm_l3_ip6_replace(unit, &l3cfg); 2248 } 2249 } else { 2250 /* Replace prior entry found */ 2251 if ((info_orig.l3a_flags & BCM_L3_HOST_AS_ROUTE) && 2252 !soc_property_get(unit, spn_HOST_AS_ROUTE_DISABLE, 0)) { 2253 l3cfg.l3c_flags |= BCM_L3_HOST_AS_ROUTE; 2254 } 2255 rv = mbcm_driver[unit]->mbcm_l3_ip6_replace(unit, &l3cfg); 2256 } 2257 } 2258 } else { 2259 l3cfg.l3c_ip_addr = info_local.l3a_ip_addr; 2260 /* Add host entry - no prior entry found */ 2261 if (BCM_FAILURE(rv)) { 2262 rv = mbcm_driver[unit]->mbcm_l3_ip4_add(unit, &l3cfg); 2263 } else { 2264 /* Remove Route entry and add to Host table */ 2265 if ((info_orig.l3a_flags & BCM_L3_HOST_AS_ROUTE) && 2266 !(info_local.l3a_flags2 & BCM_L3_FLAGS2_ROUTE_NO_MOVE) && 2267 !soc_property_get(unit, spn_HOST_AS_ROUTE_DISABLE, 0)) { 2268 /* Entry exists within ROUTE table */ 2269 l3cfg.l3c_flags &= ~BCM_L3_HOST_AS_ROUTE; 2270 2271 /* Add entry to HOST Table */ 2272 rv = mbcm_driver[unit]->mbcm_l3_ip4_add(unit, &l3cfg); 2273 2274 if (BCM_SUCCESS(rv)) { 2275 2276 /* Init ROUTE entry */ 2277 sal_memset(&info_route, 0, sizeof(bcm_l3_route_t)); 2278 sal_memcpy(info_route.l3a_nexthop_mac, l3cfg.l3c_mac_addr, sizeof(bcm_mac_t)); 2279 info_route.l3a_vrf = l3cfg.l3c_vrf; 2280 info_route.l3a_subnet = l3cfg.l3c_ip_addr; 2281 info_route.l3a_ip_mask = bcm_ip_mask_create(32); 2282 info_route.l3a_intf = l3cfg.l3c_intf; 2283 info_route.l3a_modid = l3cfg.l3c_modid; 2284 info_route.l3a_port_tgid = l3cfg.l3c_port_tgid; 2285 info_route.l3a_pri = l3cfg.l3c_prio; 2286 info_route.l3a_lookup_class = l3cfg.l3c_lookup_class; 2287 2288 /* Delete ROUTE entry */ 2289 rv = bcm_esw_l3_route_delete(unit, &info_route); 2290 if (BCM_SUCCESS(rv)) { 2291 /* Special return value - as entry existed within ROUTE table */ 2292 #if defined(BCM_FIREBOLT_SUPPORT) 2293 (void) bcm_xgs3_l3_host_as_route_return_get(unit, &rv); 2294 #endif /* BCM_FIREBOLT_SUPPORT */ 2295 } 2296 } else { 2297 /* Update ROUTE entry */ 2298 l3cfg.l3c_flags |= BCM_L3_HOST_AS_ROUTE; 2299 rv = mbcm_driver[unit]->mbcm_l3_ip4_replace(unit, &l3cfg); 2300 } 2301 } else { 2302 /* Replace prior entry found */ 2303 if ((info_orig.l3a_flags & BCM_L3_HOST_AS_ROUTE) && 2304 !soc_property_get(unit, spn_HOST_AS_ROUTE_DISABLE, 0)) { 2305 l3cfg.l3c_flags |= BCM_L3_HOST_AS_ROUTE; 2306 } 2307 rv = mbcm_driver[unit]->mbcm_l3_ip4_replace(unit, &l3cfg); 2308 } 2309 } 2310 } 2311 L3_UNLOCK(unit); 2312 return (rv); 2313 } 2314 2315 /* 2316 * Function: 2317 * bcm_esw_l3_host_delete 2318 * Purpose: 2319 * Delete an entry from the L3 table. 2320 * Parameters: 2321 * unit - SOC device unit number 2322 * ip_addr - Pointer to host structure containing 2323 * destination IP address. 2324 * Returns: 2325 * BCM_E_NONE Success 2326 * BCM_E_UNIT Illegal unit number 2327 * BCM_E_INTERNAL Chip access failure 2328 * BCM_E_INIT Unit Not initialized yet 2329 * BCM_E_NOT_FOUND Cannot find a match 2330 * Notes: 2331 * Flag set to BCM_L3_IP6 for IPv6, default is IPv4 2332 */ 2333 2334 int 2335 bcm_esw_l3_host_delete(int unit, bcm_l3_host_t *ip_addr) 2336 { 2337 _bcm_l3_cfg_t l3cfg; 2338 bcm_l3_host_t info; 2339 int rt; 2340 2341 L3_INIT(unit); 2342 2343 if (NULL == ip_addr) { 2344 return (BCM_E_PARAM); 2345 } 2346 2347 /* Vrf is in device supported range check. */ 2348 if ((ip_addr->l3a_vrf > SOC_VRF_MAX(unit)) || 2349 (ip_addr->l3a_vrf < BCM_L3_VRF_DEFAULT)) { 2350 return (BCM_E_PARAM); 2351 } 2352 2353 /* Check that device supports ipv6. */ 2354 if (BCM_L3_NO_IP6_SUPPORT(unit, ip_addr->l3a_flags)) { 2355 return (BCM_E_UNAVAIL); 2356 } 2357 2358 bcm_l3_host_t_init(&info); 2359 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 2360 info.l3a_vrf = ip_addr->l3a_vrf; 2361 2362 #ifdef BCM_TRIDENT3_SUPPORT 2363 if (soc_feature(unit, soc_feature_flex_flow)) { 2364 info.flow_handle = ip_addr->flow_handle; 2365 info.flow_option_handle = ip_addr->flow_option_handle; 2366 info.num_of_fields = ip_addr->num_of_fields; 2367 sal_memcpy(info.logical_fields, ip_addr->logical_fields, 2368 ip_addr->num_of_fields*sizeof(bcm_flow_logical_field_t)); 2369 2370 l3cfg.l3c_flow_handle = ip_addr->flow_handle; 2371 l3cfg.l3c_flow_option_handle = ip_addr->flow_option_handle; 2372 l3cfg.l3c_num_of_fields = ip_addr->num_of_fields; 2373 sal_memcpy(l3cfg.l3c_logical_fields, ip_addr->logical_fields, 2374 ip_addr->num_of_fields*sizeof(bcm_flow_logical_field_t)); 2375 } 2376 #endif /* BCM_TRIDENT3_SUPPORT */ 2377 2378 L3_LOCK(unit); 2379 if (ip_addr->l3a_flags & BCM_L3_IP6) { 2380 info.l3a_flags = BCM_L3_IP6; 2381 sal_memcpy(info.l3a_ip6_addr, ip_addr->l3a_ip6_addr, BCM_IP6_ADDRLEN); 2382 rt = bcm_esw_l3_host_find(unit, &info); 2383 if (rt != BCM_E_NONE) { 2384 L3_UNLOCK(unit); 2385 return rt; 2386 } 2387 2388 sal_memcpy(l3cfg.l3c_ip6, 2389 ip_addr->l3a_ip6_addr, BCM_IP6_ADDRLEN); 2390 l3cfg.l3c_flags = info.l3a_flags; 2391 l3cfg.l3c_flags2 = info.l3a_flags2; 2392 l3cfg.l3c_vrf = ip_addr->l3a_vrf; 2393 rt = mbcm_driver[unit]->mbcm_l3_ip6_delete(unit, &l3cfg); 2394 } else { 2395 info.l3a_ip_addr = ip_addr->l3a_ip_addr; 2396 rt = bcm_esw_l3_host_find(unit, &info); 2397 if (rt != BCM_E_NONE) { 2398 L3_UNLOCK(unit); 2399 return rt; 2400 } 2401 2402 l3cfg.l3c_ip_addr = ip_addr->l3a_ip_addr; 2403 l3cfg.l3c_flags = info.l3a_flags; /* BCM_L3_L2TOCPU might be set */ 2404 l3cfg.l3c_flags2 = info.l3a_flags2; 2405 l3cfg.l3c_vrf = ip_addr->l3a_vrf; 2406 rt = mbcm_driver[unit]->mbcm_l3_ip4_delete(unit, &l3cfg); 2407 } 2408 L3_UNLOCK(unit); 2409 return rt; 2410 } 2411 2412 /* 2413 * Function: 2414 * bcm_esw_l3_host_delete_by_network 2415 * Purpose: 2416 * Delete all L3 entries that match the IP address mask 2417 * Parameters: 2418 * unit - SOC device unit number 2419 * net_addr - Pointer to route structure containing the network 2420 * address to be matched against 2421 * Returns: 2422 * BCM_E_NONE Success 2423 * BCM_E_UNIT Illegal unit number 2424 * BCM_E_INTERNAL Chip access failure 2425 * BCM_E_INIT Unit Not initialized yet 2426 * Notes: 2427 * Flag set to BCM_L3_IP6 for IPv6, default is IPv4 2428 */ 2429 2430 int 2431 bcm_esw_l3_host_delete_by_network(int unit, bcm_l3_route_t *net_addr) 2432 { 2433 _bcm_l3_cfg_t l3cfg; 2434 int rv; 2435 2436 L3_INIT(unit); 2437 2438 if (NULL == net_addr) { 2439 return (BCM_E_PARAM); 2440 } 2441 2442 /* Vrf is in device supported range check. */ 2443 if ((net_addr->l3a_vrf > SOC_VRF_MAX(unit)) || 2444 (net_addr->l3a_vrf < BCM_L3_VRF_DEFAULT)) { 2445 return (BCM_E_PARAM); 2446 } 2447 2448 /* Check that device supports ipv6. */ 2449 if (BCM_L3_NO_IP6_SUPPORT(unit, net_addr->l3a_flags)) { 2450 return (BCM_E_UNAVAIL); 2451 } 2452 2453 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 2454 l3cfg.l3c_vrf = net_addr->l3a_vrf; 2455 2456 L3_LOCK(unit); 2457 if (net_addr->l3a_flags & BCM_L3_IP6) { 2458 sal_memcpy(l3cfg.l3c_ip6, 2459 net_addr->l3a_ip6_net, BCM_IP6_ADDRLEN); 2460 sal_memcpy(l3cfg.l3c_ip6_mask, 2461 net_addr->l3a_ip6_mask, BCM_IP6_ADDRLEN); 2462 l3cfg.l3c_flags = BCM_L3_IP6; 2463 rv = mbcm_driver[unit]->mbcm_l3_ip6_delete_prefix(unit, &l3cfg); 2464 } else { 2465 l3cfg.l3c_ip_addr = net_addr->l3a_subnet; 2466 l3cfg.l3c_ip_mask = net_addr->l3a_ip_mask; 2467 rv = mbcm_driver[unit]->mbcm_l3_ip4_delete_prefix(unit, &l3cfg); 2468 } 2469 L3_UNLOCK(unit); 2470 return (rv); 2471 } 2472 2473 /* 2474 * Function: 2475 * bcm_esw_l3_host_delete_by_interface 2476 * Purpose: 2477 * Delete all L3 entries that match the L3 interface 2478 * Parameters: 2479 * unit - SOC device unit number 2480 * info - The host structure containing the to be matched interface ID 2481 * (IN)l3a_intf_id member 2482 * Returns: 2483 * BCM_E_NONE Success 2484 * BCM_E_UNIT Illegal unit number 2485 * BCM_E_INIT Unit Not initialized yet 2486 * Notes: 2487 * - Flag set to BCM_L3_NEGATE to delete all host entries 2488 * that do NOT match the L3 interface. 2489 */ 2490 int 2491 bcm_esw_l3_host_delete_by_interface(int unit, bcm_l3_host_t *info) 2492 { 2493 int rv; 2494 _bcm_l3_cfg_t l3cfg; 2495 int negate; 2496 2497 L3_INIT(unit); 2498 2499 if (NULL == info) { 2500 return (BCM_E_PARAM); 2501 } 2502 2503 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 2504 2505 l3cfg.l3c_intf = info->l3a_intf; 2506 negate = info->l3a_flags & BCM_L3_NEGATE ? 1 : 0; 2507 2508 L3_LOCK(unit); 2509 2510 rv = mbcm_driver[unit]->mbcm_l3_delete_intf(unit, &l3cfg, negate); 2511 2512 L3_UNLOCK(unit); 2513 return (rv); 2514 } 2515 2516 /* 2517 * Function: 2518 * bcm_esw_l3_host_delete_all 2519 * Purpose: 2520 * Delete all entries from the L3 table. 2521 * Parameters: 2522 * unit - SOC device unit number 2523 * info - Pointer to host structure containing the flag 2524 * indicating IPv4 or IPv6 2525 * Returns: 2526 * BCM_E_NONE Success 2527 * BCM_E_UNIT Illegal unit number 2528 * BCM_E_INTERNAL Chip access failure 2529 * BCM_E_INIT Unit Not initialized yet 2530 */ 2531 int 2532 bcm_esw_l3_host_delete_all(int unit, bcm_l3_host_t *info) 2533 { 2534 int rv; 2535 L3_INIT(unit); 2536 2537 L3_LOCK(unit); 2538 2539 rv = mbcm_driver[unit]->mbcm_l3_delete_all(unit); 2540 2541 L3_UNLOCK(unit); 2542 return (rv); 2543 } 2544 2545 /* 2546 * Function: 2547 * bcm_esw_l3_host_conflict_get 2548 * Purpose: 2549 * Given a IP address, return conflicts in the L3 table. 2550 * Parameters: 2551 * unit - SOC unit number. 2552 * ipkey - IP address to test conflict condition 2553 * cf_array - (OUT) arrary of conflicting addresses(at most 8) 2554 * cf_max - max number of conflicts wanted 2555 * cf_count - (OUT) actual # of conflicting addresses 2556 * Returns: 2557 * BCM_E_XXX 2558 */ 2559 int 2560 bcm_esw_l3_host_conflict_get(int unit, bcm_l3_key_t *ipkey, bcm_l3_key_t *cf_array, 2561 int cf_max, int *cf_count) 2562 { 2563 int rv; 2564 L3_INIT(unit); 2565 2566 if (NULL == ipkey) { 2567 return (BCM_E_PARAM); 2568 } 2569 2570 /* Vrf is in device supported range check. */ 2571 if ((ipkey->l3k_vrf > SOC_VRF_MAX(unit)) || 2572 (ipkey->l3k_vrf < BCM_L3_VRF_DEFAULT)) { 2573 return (BCM_E_PARAM); 2574 } 2575 2576 /* Check that device supports ipv6. */ 2577 if (BCM_L3_NO_IP6_SUPPORT(unit, ipkey->l3k_flags)) { 2578 return (BCM_E_UNAVAIL); 2579 } 2580 2581 L3_LOCK(unit); 2582 2583 rv = mbcm_driver[unit]->mbcm_l3_conflict_get(unit, ipkey, cf_array, 2584 cf_max, cf_count); 2585 L3_UNLOCK(unit); 2586 return (rv); 2587 } 2588 2589 /* 2590 * Function: 2591 * bcm_esw_l3_host_age 2592 * Purpose: 2593 * Age out the L3 entry by clearing the HIT bit when appropriate, 2594 * the L3 host entry itself is removed if HIT bit is not set. 2595 * Parameters: 2596 * unit - SOC device unit number 2597 * flags - The criteria used to age out L3 table. 2598 * age_cb - Call back routine. 2599 * user_data - (IN) User provided cookie for callback. 2600 * Returns: 2601 * BCM_E_UNIT Illegal unit number 2602 * BCM_E_INIT Unit Not initialized yet 2603 */ 2604 2605 int 2606 bcm_esw_l3_host_age(int unit, uint32 flags, bcm_l3_host_traverse_cb age_cb, 2607 void *user_data) 2608 { 2609 int rv; 2610 L3_INIT(unit); 2611 2612 /* Check that device supports ipv6. */ 2613 if (BCM_L3_NO_IP6_SUPPORT(unit, flags)) { 2614 return (BCM_E_UNAVAIL); 2615 } 2616 2617 L3_LOCK(unit); 2618 2619 rv = mbcm_driver[unit]->mbcm_l3_age(unit, flags, age_cb, user_data); 2620 2621 L3_UNLOCK(unit); 2622 return (rv); 2623 } 2624 2625 /* 2626 * Function: 2627 * bcm_esw_l3_host_traverse 2628 * Purpose: 2629 * Go through all valid L3 entries, and call the callback function 2630 * at each entry 2631 * Parameters: 2632 * unit - SOC device unit number 2633 * flags - BCM_L3_IP6 2634 * start - Callback called after this many L3 entries 2635 * end - Callback called before this many L3 entries 2636 * cb - User supplied callback function 2637 * user_data - User supplied cookie used in parameter in callback function 2638 * Returns: 2639 * BCM_E_UNIT Illegal unit number 2640 * BCM_E_INIT Unit Not initialized yet 2641 */ 2642 2643 int 2644 bcm_esw_l3_host_traverse(int unit, uint32 flags, 2645 uint32 start, uint32 end, 2646 bcm_l3_host_traverse_cb cb, void *user_data) 2647 { 2648 int rv; 2649 2650 L3_INIT(unit); 2651 2652 if (NULL == cb) { 2653 return (BCM_E_PARAM); 2654 } 2655 2656 /* Check that device supports ipv6. */ 2657 if (BCM_L3_NO_IP6_SUPPORT(unit, flags)) { 2658 return (BCM_E_UNAVAIL); 2659 } 2660 2661 L3_LOCK(unit); 2662 2663 if (flags & BCM_L3_IP6) { 2664 rv = mbcm_driver[unit]->mbcm_l3_ip6_traverse(unit, flags, 2665 start, end, cb, user_data); 2666 } else { 2667 rv = mbcm_driver[unit]->mbcm_l3_ip4_traverse(unit, flags, 2668 start, end, cb, user_data); 2669 } 2670 2671 L3_UNLOCK(unit); 2672 return (rv); 2673 } 2674 2675 /* 2676 * Function: 2677 * bcm_esw_l3_host_invalidate_entry 2678 * Purpose: 2679 * Given a IP address, invalidate the L3 entry without 2680 * clearing the entry information, so that the entry can be 2681 * turned back to valid without resetting all the information. 2682 * Parameters: 2683 * unit - SOC unit number. 2684 * ipaddr - IP address to test conflict condition 2685 * Returns: 2686 * BCM_E_XXX 2687 */ 2688 int 2689 bcm_esw_l3_host_invalidate_entry(int unit, bcm_ip_t ipaddr) 2690 { 2691 #ifdef BCM_XGS12_SWITCH_SUPPORT 2692 int rv; 2693 #endif /* BCM_XGS_SWITCH_SUPPORT */ 2694 L3_INIT(unit); 2695 2696 #ifdef BCM_XGS12_SWITCH_SUPPORT 2697 if (SOC_IS_XGS12_SWITCH(unit)) { 2698 L3_LOCK(unit); 2699 rv = bcm_xgs_l3_invalidate_entry(unit, ipaddr); 2700 L3_UNLOCK(unit); 2701 return (rv); 2702 } 2703 #endif /* BCM_XGS_SWITCH_SUPPORT */ 2704 2705 return BCM_E_UNAVAIL; 2706 } 2707 2708 /* 2709 * Function: 2710 * bcm_esw_l3_host_validate_entry 2711 * Purpose: 2712 * Given a IP address, validate the L3 entry without 2713 * resetting the entry information. 2714 * Parameters: 2715 * unit - SOC unit number. 2716 * ipaddr - IP address to test conflict condition 2717 * Returns: 2718 * BCM_E_XXX 2719 */ 2720 int 2721 bcm_esw_l3_host_validate_entry(int unit, bcm_ip_t ipaddr) 2722 { 2723 #ifdef BCM_XGS12_SWITCH_SUPPORT 2724 int rv; 2725 #endif /* BCM_XGS_SWITCH_SUPPORT */ 2726 L3_INIT(unit); 2727 2728 #ifdef BCM_XGS12_SWITCH_SUPPORT 2729 if (SOC_IS_XGS12_SWITCH(unit)) { 2730 L3_LOCK(unit); 2731 rv = bcm_xgs_l3_validate_entry(unit, ipaddr); 2732 L3_UNLOCK(unit); 2733 return (rv); 2734 } 2735 #endif /* BCM_XGS_SWITCH_SUPPORT */ 2736 2737 return BCM_E_UNAVAIL; 2738 } 2739 2740 /* 2741 * Function: 2742 * bcm_esw_l3_route_add 2743 * Purpose: 2744 * Add an IP route to the DEFIP table. 2745 * Parameters: 2746 * unit - SOC device unit number 2747 * info - Pointer to bcm_l3_route_t containing all valid fields. 2748 * Returns: 2749 * BCM_E_XXX 2750 * Note: 2751 * 1. In addition to the route info (i.e. the network number, 2752 * nexthop MAC addr, L3 intf, port, modid, or trunk ID), 2753 * on XGS chips, one must specify the nexthop IP addr. 2754 * This is used as key to find entry in the L3 table. 2755 * 2756 * 2. XGS ECMP route must have BCM_L3_MULTIPATH flag set. 2757 * ECMP is supported on all XGS devices. 2758 * 2759 * 3. BCM_L3_DEFIP_LOCAL flag is used, then packets that matches 2760 * LPM table will be sent to CPU unchanged (XGS only). 2761 * BCM_L3_DEFIP_LOCAL flag is used for last hop direct-connected 2762 * subnet (e.g where workstations are attached to router). 2763 * BCM_L3_DEFIP_LOCAL and BCM_L3_MULTIPATH can not be both set. 2764 * When BCM_L3_DEFIP_LOCAL flag is used, nexthop IP addr 2765 * is not needed. 2766 */ 2767 2768 int 2769 bcm_esw_l3_route_add(int unit, bcm_l3_route_t *info) 2770 { 2771 int max_prefix_length; 2772 _bcm_defip_cfg_t defip; 2773 uint8 ip6_zero[BCM_IP6_ADDRLEN] = {0}; 2774 int rv; 2775 bcm_l3_route_t info_local; 2776 bcm_module_t source_modid = 0; 2777 bcm_port_t source_port_tgid = 0; 2778 uint32 source_trunk_flag = 0; 2779 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 2780 int l3iif_max; 2781 #endif 2782 2783 L3_INIT(unit); 2784 2785 if (NULL == info) { 2786 return (BCM_E_PARAM); 2787 } 2788 2789 /* Copy provided structure to local so it can be modified. */ 2790 sal_memcpy(&info_local, info, sizeof(bcm_l3_route_t)); 2791 2792 if ((info_local.l3a_vrf > SOC_VRF_MAX(unit)) || 2793 (info_local.l3a_vrf < BCM_L3_VRF_GLOBAL)) { 2794 return (BCM_E_PARAM); 2795 } 2796 2797 /* Check that device supports ipv6. */ 2798 if (BCM_L3_NO_IP6_SUPPORT(unit, info_local.l3a_flags)) { 2799 return (BCM_E_UNAVAIL); 2800 } 2801 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 2802 if (soc_feature(unit, soc_feature_ipmc_defip)) { 2803 2804 if ((info_local.l3a_flags & BCM_L3_IPMC) && 2805 !(_BCM_MULTICAST_IS_L3(info_local.l3a_mc_group)) && 2806 !(_BCM_MULTICAST_IS_VXLAN(info_local.l3a_mc_group))) { 2807 return BCM_E_PARAM; 2808 } 2809 /* Expected L3IIF and RP ID cannot go together */ 2810 if((info_local.l3a_ipmc_flags & BCM_IPMC_POST_LOOKUP_RPF_CHECK) && 2811 (info_local.l3a_rp != BCM_IPMC_RP_ID_INVALID)) { 2812 return (BCM_E_PARAM); 2813 } 2814 /* Resolve is not applicable */ 2815 if(info_local.l3a_ipmc_flags & BCM_IPMC_RP_ID_EXPECTED_INTF_RESOLVE) { 2816 return (BCM_E_PARAM); 2817 } 2818 l3iif_max = _BCM_DEFIP_IPMC_EXPECTED_L3IIF_MAX; 2819 if (soc_feature(unit, soc_feature_l3defip_rp_l3iif_resolve) && 2820 SOC_MEM_FIELD_VALID(unit, L3_DEFIPm, EXPECTED_L3_IIF0f)) { 2821 l3iif_max = 2822 (1 << soc_mem_field_length(unit, L3_DEFIPm, EXPECTED_L3_IIF0f)) - 1; 2823 } 2824 /* 2825 * 1) Expected L3IIF cannot be more than _BCM_DEFIP_IPMC_EXPECTED_L3IIF_MAX 2826 * 2) MULTIPATH and MULTICAST cannot be true together 2827 */ 2828 if((info_local.l3a_expected_intf > l3iif_max) || 2829 ((info_local.l3a_flags & BCM_L3_MULTIPATH) && 2830 (info_local.l3a_flags & BCM_L3_IPMC))) { 2831 return (BCM_E_PARAM); 2832 } 2833 } 2834 #endif 2835 2836 if (soc_feature(unit, soc_feature_extended_address_class)) { 2837 if ((info_local.l3a_lookup_class > SOC_EXT_ADDR_CLASS_MAX(unit)) || 2838 (info_local.l3a_lookup_class < 0)) { 2839 return (BCM_E_PARAM); 2840 } 2841 } else if (soc_feature(unit, soc_feature_overlaid_address_class) && 2842 !BCM_L3_RPE_SET(info_local.l3a_flags)) { 2843 if ((info_local.l3a_lookup_class > 2844 SOC_OVERLAID_ADDR_CLASS_MAX(unit)) || 2845 (info_local.l3a_lookup_class < 0)) { 2846 return (BCM_E_PARAM); 2847 } 2848 } else if ((info_local.l3a_lookup_class > SOC_ADDR_CLASS_MAX(unit)) || 2849 (info_local.l3a_lookup_class < 0)) { 2850 return (BCM_E_PARAM); 2851 } 2852 2853 /* 2854 * When RPE is not set and soc_feature_overlaid_address_class is 2855 * not enabled, priority values range from 0-7. 2856 * When RPE is set, priority values range from 0-15. 2857 * When RPE is not set but soc_feature_overlaid_address_class 2858 * is enabled, priority value ranges from 0-15. 2859 */ 2860 if(!BCM_L3_RPE_SET(info_local.l3a_flags) && 2861 !soc_feature(unit, soc_feature_overlaid_address_class)) { 2862 if (!BCM_PRIORITY_VALID(info_local.l3a_pri)) { 2863 return (BCM_E_PARAM); 2864 } 2865 } else { 2866 if (!BCM_RPE_PRIORITY_VALID(info_local.l3a_pri)) { 2867 return (BCM_E_PARAM); 2868 } 2869 } 2870 2871 if (BCM_GPORT_IS_SET(info_local.l3a_port_tgid)) { 2872 2873 /* l3a_port_tgid can contain either port or trunk */ 2874 BCM_IF_ERROR_RETURN( 2875 _bcm_esw_l3_gport_resolve(unit, info_local.l3a_port_tgid, 2876 &(info_local.l3a_port_tgid), 2877 &(info_local.l3a_modid), 2878 &(info_local.l3a_port_tgid), 2879 &(info_local.l3a_flags))); 2880 } else { 2881 PORT_DUALMODID_VALID(unit, info_local.l3a_port_tgid); 2882 } 2883 2884 if (soc_feature(unit, soc_feature_ipmc_defip) && 2885 (info_local.l3a_flags & BCM_L3_IPMC) && 2886 !(info_local.l3a_ipmc_flags & BCM_IPMC_SOURCE_PORT_NOCHECK)) { 2887 if (BCM_GPORT_IS_SET(info_local.l3a_expected_src_gport)) { 2888 2889 /* l3a_port_tgid can contain either port or trunk */ 2890 BCM_IF_ERROR_RETURN( 2891 _bcm_esw_l3_gport_resolve(unit, 2892 info_local.l3a_expected_src_gport, 2893 &source_port_tgid, 2894 &source_modid, 2895 &source_port_tgid, 2896 &source_trunk_flag)); 2897 } else { 2898 PORT_DUALMODID_VALID(unit, info_local.l3a_expected_src_gport); 2899 } 2900 } 2901 2902 sal_memset(&defip, 0, sizeof(_bcm_defip_cfg_t)); 2903 2904 sal_memcpy(defip.defip_mac_addr, info_local.l3a_nexthop_mac, 2905 sizeof(bcm_mac_t)); 2906 defip.defip_intf = info_local.l3a_intf; 2907 defip.defip_modid = info_local.l3a_modid; 2908 defip.defip_port_tgid = info_local.l3a_port_tgid; 2909 defip.defip_vid = info_local.l3a_vid; 2910 defip.defip_flags = info_local.l3a_flags; 2911 defip.defip_flags2 = info_local.l3a_flags2; 2912 defip.defip_ipmc_flags = info_local.l3a_ipmc_flags; 2913 defip.defip_vrf = info_local.l3a_vrf; 2914 defip.defip_tunnel_option = (info_local.l3a_tunnel_option & 0xffff); 2915 defip.defip_mpls_label = info_local.l3a_mpls_label; 2916 defip.defip_expected_intf = info_local.l3a_expected_intf; 2917 defip.defip_l3a_rp = info_local.l3a_rp; 2918 defip.defip_mc_group = info_local.l3a_mc_group; 2919 if (soc_feature(unit, soc_feature_ipmc_defip) && 2920 (defip.defip_flags & BCM_L3_IPMC)) { 2921 defip.defip_source_modid = source_modid; 2922 defip.defip_source_port_tgid = source_port_tgid; 2923 defip.defip_source_ts = (source_trunk_flag & BCM_L3_TGID) ? 1 : 0; 2924 if(_BCM_MULTICAST_IS_L3(defip.defip_mc_group) || 2925 _BCM_MULTICAST_IS_VXLAN(defip.defip_mc_group)) { 2926 defip.defip_mc_group = _BCM_MULTICAST_ID_GET(defip.defip_mc_group); 2927 } else { 2928 return BCM_E_PARAM; 2929 } 2930 } 2931 if (soc_feature(unit, soc_feature_overlaid_address_class) && 2932 (!BCM_L3_RPE_SET(info_local.l3a_flags))) { 2933 defip.defip_prio = ((info_local.l3a_lookup_class & 0x3C0) >> 6); 2934 defip.defip_lookup_class = (info_local.l3a_lookup_class & 0x3F); 2935 } else { 2936 defip.defip_prio = info_local.l3a_pri; 2937 defip.defip_lookup_class = info_local.l3a_lookup_class; 2938 } 2939 2940 #ifdef BCM_TRIDENT3_SUPPORT 2941 if (soc_feature(unit, soc_feature_flex_flow)) { 2942 defip.defip_flow_handle = info_local.flow_handle; 2943 defip.defip_flow_option_handle = info_local.flow_option_handle; 2944 defip.defip_num_of_fields = info_local.num_of_fields; 2945 sal_memcpy(defip.defip_logical_fields, info_local.logical_fields, 2946 info_local.num_of_fields*sizeof(bcm_flow_logical_field_t)); 2947 } 2948 #endif /* BCM_TRIDENT3_SUPPORT */ 2949 L3_LOCK(unit); 2950 if (info_local.l3a_flags & BCM_L3_IP6) { 2951 max_prefix_length = 2952 soc_feature(unit, soc_feature_lpm_prefix_length_max_128) ? 128 : 64; 2953 if (bcm_ip6_mask_length(info_local.l3a_ip6_mask) == 0 && 2954 sal_memcmp(info_local.l3a_ip6_net, ip6_zero, BCM_IP6_ADDRLEN) != 0) { 2955 L3_UNLOCK(unit); 2956 return (BCM_E_PARAM); 2957 } 2958 sal_memcpy(defip.defip_ip6_addr, info_local.l3a_ip6_net, BCM_IP6_ADDRLEN); 2959 defip.defip_sub_len = bcm_ip6_mask_length(info_local.l3a_ip6_mask); 2960 if (defip.defip_sub_len > max_prefix_length) { 2961 L3_UNLOCK(unit); 2962 return (BCM_E_PARAM); 2963 } 2964 rv = mbcm_driver[unit]->mbcm_ip6_defip_add(unit, &defip); 2965 } else { 2966 if (info_local.l3a_ip_mask == 0 && info_local.l3a_subnet != 0) { 2967 L3_UNLOCK(unit); 2968 return (BCM_E_PARAM); 2969 } 2970 defip.defip_ip_addr = info_local.l3a_subnet & info_local.l3a_ip_mask; 2971 defip.defip_sub_len = bcm_ip_mask_length(info_local.l3a_ip_mask); 2972 defip.defip_nexthop_ip = info_local.l3a_nexthop_ip; 2973 rv = mbcm_driver[unit]->mbcm_ip4_defip_add(unit, &defip); 2974 } 2975 L3_UNLOCK(unit); 2976 2977 return (rv); 2978 } 2979 2980 /* 2981 * Function: 2982 * bcm_esw_l3_route_delete 2983 * Purpose: 2984 * Delete an entry from the Default IP Router table. 2985 * Parameters: 2986 * unit - SOC device unit number 2987 * info - Pointer to bcm_l3_route_t structure with valid IP subnet & mask. 2988 * Returns: 2989 * BCM_E_XXX. 2990 * Note: 2991 * 1. For non-ECMP routes, it suffices to specify the network number 2992 * in order to delete the route, since there is only one path. 2993 * 2994 * 2. For ECMP routes, in addition to specifying the network number, 2995 * one must specify which ECMP path is to be deleted. 2996 * This is done by specifying the following parameters: 2997 * nexthop MAC addr, L3 intf, port, modid, next hop IP addr. 2998 * 2999 * This is how these parameters are used to identify the ECMP path: 3000 * next hop IP addr | nexthop MAC addr | 3001 * (L3 intf, port, modid) 3002 * Unspecified nexthop IP or MAC addr must be set to 0. 3003 * 3004 * XGS ECMP route must have BCM_L3_MULTIPATH flag set. 3005 * ECMP is supported on all XGS devices. 3006 */ 3007 3008 int 3009 bcm_esw_l3_route_delete(int unit, bcm_l3_route_t *info) 3010 { 3011 int max_prefix_length; 3012 _bcm_defip_cfg_t defip; 3013 int rv; 3014 bcm_l3_route_t info_local; 3015 3016 L3_INIT(unit); 3017 3018 if (NULL == info) { 3019 return (BCM_E_PARAM); 3020 } 3021 3022 /* Copy provided structure to local so it can be modified. */ 3023 sal_memcpy(&info_local, info, sizeof(bcm_l3_route_t)); 3024 3025 if ((info_local.l3a_vrf > SOC_VRF_MAX(unit)) || 3026 (info_local.l3a_vrf < BCM_L3_VRF_GLOBAL)) { 3027 return (BCM_E_PARAM); 3028 } 3029 3030 /* Check that device supports ipv6. */ 3031 if (BCM_L3_NO_IP6_SUPPORT(unit, info_local.l3a_flags)) { 3032 return (BCM_E_UNAVAIL); 3033 } 3034 3035 sal_memset(&defip, 0, sizeof(_bcm_defip_cfg_t)); 3036 3037 defip.defip_vid = info_local.l3a_vid; 3038 defip.defip_flags = info_local.l3a_flags; 3039 defip.defip_vrf = info_local.l3a_vrf; 3040 3041 if (info_local.l3a_flags & BCM_L3_MULTIPATH) { 3042 if (BCM_GPORT_IS_SET(info_local.l3a_port_tgid)) { 3043 /* l3a_port_tgid can contain either port or trunk */ 3044 BCM_IF_ERROR_RETURN( 3045 _bcm_esw_l3_gport_resolve(unit, info_local.l3a_port_tgid, 3046 &(info_local.l3a_port_tgid), 3047 &(info_local.l3a_modid), 3048 &(info_local.l3a_port_tgid), 3049 &(info_local.l3a_flags))); 3050 } 3051 3052 sal_memcpy(defip.defip_mac_addr, info_local.l3a_nexthop_mac, 3053 sizeof(bcm_mac_t)); 3054 defip.defip_intf = info_local.l3a_intf; 3055 defip.defip_port_tgid = info_local.l3a_port_tgid; 3056 defip.defip_modid = info_local.l3a_modid; 3057 defip.defip_flags = info_local.l3a_flags; 3058 } 3059 #ifdef BCM_TRIDENT3_SUPPORT 3060 if (soc_feature(unit, soc_feature_flex_flow)) { 3061 defip.defip_flow_handle = info_local.flow_handle; 3062 defip.defip_flow_option_handle = info_local.flow_option_handle; 3063 defip.defip_num_of_fields = info_local.num_of_fields; 3064 sal_memcpy(defip.defip_logical_fields, info_local.logical_fields, 3065 info_local.num_of_fields*sizeof(bcm_flow_logical_field_t)); 3066 } 3067 #endif /* BCM_TRIDENT3_SUPPORT */ 3068 3069 L3_LOCK(unit); 3070 if (info_local.l3a_flags & BCM_L3_IP6) { 3071 max_prefix_length = 3072 soc_feature(unit, soc_feature_lpm_prefix_length_max_128) ? 128 : 64; 3073 sal_memcpy(defip.defip_ip6_addr, info_local.l3a_ip6_net, BCM_IP6_ADDRLEN); 3074 defip.defip_sub_len = bcm_ip6_mask_length(info_local.l3a_ip6_mask); 3075 if (defip.defip_sub_len > max_prefix_length) { 3076 L3_UNLOCK(unit); 3077 return (BCM_E_PARAM); 3078 } 3079 rv = mbcm_driver[unit]->mbcm_ip6_defip_delete(unit, &defip); 3080 } else { 3081 defip.defip_ip_addr = info_local.l3a_subnet & info_local.l3a_ip_mask; 3082 defip.defip_sub_len = bcm_ip_mask_length(info_local.l3a_ip_mask); 3083 defip.defip_nexthop_ip = info_local.l3a_nexthop_ip; 3084 3085 rv = mbcm_driver[unit]->mbcm_ip4_defip_delete(unit, &defip); 3086 } 3087 3088 L3_UNLOCK(unit); 3089 return (rv); 3090 } 3091 3092 /* 3093 * Function: 3094 * bcm_esw_l3_route_get 3095 * Purpose: 3096 * Get an entry from the DEF IP table. 3097 * Parameters: 3098 * unit - SOC device unit number 3099 * info - (OUT)Pointer to bcm_l3_route_t for return information. 3100 * Returns: 3101 * BCM_E_XXX 3102 * Notes: 3103 * - Application has to pass IP address, IP mask for the network 3104 * - If the route is local, then the BCM_L3_DEFIP_LOCAL flag is 3105 * set, and next hop MAC, port/tgid, interface, MODID fields 3106 * are all cleared. 3107 */ 3108 3109 int 3110 bcm_esw_l3_route_get(int unit, bcm_l3_route_t *info) 3111 { 3112 int max_prefix_length; 3113 _bcm_defip_cfg_t defip; 3114 int rv; 3115 #if defined(BCM_TRX_SUPPORT) 3116 uint32 ipmc_id; 3117 #endif 3118 3119 L3_INIT(unit); 3120 3121 if (NULL == info) { 3122 return BCM_E_PARAM; 3123 } 3124 3125 if ((info->l3a_vrf > SOC_VRF_MAX(unit)) || 3126 (info->l3a_vrf < BCM_L3_VRF_GLOBAL)) { 3127 return (BCM_E_PARAM); 3128 } 3129 3130 /* Check that device supports ipv6. */ 3131 if (BCM_L3_NO_IP6_SUPPORT(unit, info->l3a_flags)) { 3132 return (BCM_E_UNAVAIL); 3133 } 3134 3135 sal_memset(&defip, 0, sizeof(_bcm_defip_cfg_t)); 3136 defip.defip_l3a_rp = BCM_IPMC_RP_ID_INVALID; 3137 defip.defip_flags = info->l3a_flags; 3138 defip.defip_vrf = info->l3a_vrf; 3139 3140 #ifdef BCM_TRIDENT3_SUPPORT 3141 if (soc_feature(unit, soc_feature_flex_flow)) { 3142 defip.defip_flow_handle = info->flow_handle; 3143 defip.defip_flow_option_handle = info->flow_option_handle; 3144 defip.defip_num_of_fields = info->num_of_fields; 3145 sal_memcpy(defip.defip_logical_fields, info->logical_fields, 3146 info->num_of_fields*sizeof(bcm_flow_logical_field_t)); 3147 } 3148 #endif /* BCM_TRIDENT3_SUPPORT */ 3149 3150 L3_LOCK(unit); 3151 if (info->l3a_flags & BCM_L3_IP6) { 3152 max_prefix_length = 3153 soc_feature(unit, soc_feature_lpm_prefix_length_max_128) ? 128 : 64; 3154 sal_memcpy(defip.defip_ip6_addr, info->l3a_ip6_net, BCM_IP6_ADDRLEN); 3155 defip.defip_sub_len = bcm_ip6_mask_length(info->l3a_ip6_mask); 3156 if (defip.defip_sub_len > max_prefix_length) { 3157 L3_UNLOCK(unit); 3158 return (BCM_E_PARAM); 3159 } 3160 rv = mbcm_driver[unit]->mbcm_ip6_defip_cfg_get(unit, &defip); 3161 } else { 3162 defip.defip_ip_addr = info->l3a_subnet & info->l3a_ip_mask; 3163 defip.defip_sub_len = bcm_ip_mask_length(info->l3a_ip_mask); 3164 rv = mbcm_driver[unit]->mbcm_ip4_defip_cfg_get(unit, &defip); 3165 } 3166 3167 L3_UNLOCK(unit); 3168 if (rv < 0) { 3169 return rv; 3170 } 3171 3172 sal_memcpy(info->l3a_nexthop_mac, defip.defip_mac_addr, 3173 sizeof(bcm_mac_t)); 3174 info->l3a_nexthop_ip = defip.defip_nexthop_ip; 3175 info->l3a_intf = defip.defip_intf; 3176 info->l3a_port_tgid = defip.defip_port_tgid; 3177 info->l3a_modid = defip.defip_modid; 3178 info->l3a_lookup_class = defip.defip_lookup_class; 3179 info->l3a_flags = defip.defip_flags; 3180 info->l3a_flags2 = defip.defip_flags2; 3181 info->l3a_mpls_label = defip.defip_mpls_label; 3182 info->l3a_tunnel_option = defip.defip_tunnel_option; 3183 info->l3a_expected_intf = defip.defip_expected_intf; 3184 info->l3a_rp = defip.defip_l3a_rp; 3185 info->l3a_mc_group = defip.defip_mc_group; 3186 info->l3a_ipmc_flags = defip.defip_ipmc_flags; 3187 if (defip.defip_flags & BCM_L3_IPMC ) { 3188 #if defined(BCM_TRX_SUPPORT) 3189 if (SOC_IS_TRX(unit)) { 3190 ipmc_id = info->l3a_mc_group; 3191 rv = _bcm_tr_multicast_ipmc_group_type_get( 3192 unit, ipmc_id, &(info->l3a_mc_group)); 3193 if (BCM_FAILURE(rv)) { 3194 /* default to _BCM_MULTICAST_TYPE_L3 */ 3195 _BCM_MULTICAST_GROUP_SET(info->l3a_mc_group, 3196 _BCM_MULTICAST_TYPE_L3, ipmc_id); 3197 } 3198 } else 3199 #endif 3200 { 3201 _BCM_MULTICAST_GROUP_SET(info->l3a_mc_group, 3202 _BCM_MULTICAST_TYPE_L3, info->l3a_mc_group); 3203 } 3204 } 3205 3206 /* For devices that support the overlaid_address_range, if the RPE 3207 field is '0', the 4 bits of PRI are the upper 4 bits 3208 (of total 10 bits) of the classId, the lower 6 come from classId 3209 as usual, for rest of the cases, the classID and PRI are copied 3210 over directly. 3211 */ 3212 if (soc_feature(unit, soc_feature_overlaid_address_class) && 3213 !BCM_L3_RPE_SET(defip.defip_flags)) { 3214 info->l3a_lookup_class = ((defip.defip_prio & 0xF) << 6); 3215 info->l3a_lookup_class |= (defip.defip_lookup_class & 0x3F); 3216 } else { 3217 info->l3a_pri = defip.defip_prio; 3218 } 3219 3220 #ifdef BCM_TRIDENT3_SUPPORT 3221 if (soc_feature(unit, soc_feature_flex_flow)) { 3222 sal_memcpy(info->logical_fields, 3223 defip.defip_logical_fields, 3224 defip.defip_num_of_fields * sizeof(bcm_flow_logical_field_t)); 3225 } 3226 #endif /* BCM_TRIDENT3_SUPPORT */ 3227 3228 BCM_IF_ERROR_RETURN( 3229 _bcm_esw_l3_gport_construct(unit, info->l3a_port_tgid, info->l3a_modid, 3230 info->l3a_port_tgid, info->l3a_flags, 3231 &(info->l3a_port_tgid))); 3232 3233 if (!(info->l3a_ipmc_flags & BCM_IPMC_SOURCE_PORT_NOCHECK)) { 3234 BCM_IF_ERROR_RETURN( 3235 _bcm_esw_l3_gport_construct(unit, defip.defip_source_port_tgid, 3236 defip.defip_source_modid, 3237 defip.defip_source_port_tgid, 3238 defip.defip_source_ts ? BCM_L3_TGID : 0, 3239 &(info->l3a_expected_src_gport))); 3240 } 3241 return BCM_E_NONE; 3242 } 3243 3244 /* 3245 * Function: 3246 * bcm_l3_route_find 3247 * Purpose: 3248 * Get a Longest Prefix Matched entry from the DEF IP table for 3249 * a host address. 3250 * Parameters: 3251 * unit - SOC device unit number 3252 * dest - (IN) Given host address. 3253 * route - (OUT)Pointer to bcm_l3_route_t for return information. 3254 * Returns: 3255 * BCM_E_XXX 3256 * Notes: 3257 * - Application has to pass IP address and flag for IP version. 3258 */ 3259 int 3260 bcm_esw_l3_route_find(int unit, bcm_l3_host_t *host, bcm_l3_route_t *route) 3261 { 3262 int max_prefix_length; 3263 _bcm_defip_cfg_t defip; 3264 int rv; 3265 3266 L3_INIT(unit); 3267 3268 if (NULL == host || NULL == route) { 3269 return BCM_E_PARAM; 3270 } 3271 3272 if ((host->l3a_vrf > SOC_VRF_MAX(unit)) || 3273 (host->l3a_vrf < BCM_L3_VRF_GLOBAL)) { 3274 return (BCM_E_PARAM); 3275 } 3276 3277 /* Check that device supports ipv6. */ 3278 if (BCM_L3_NO_IP6_SUPPORT(unit, host->l3a_flags)) { 3279 return (BCM_E_UNAVAIL); 3280 } 3281 3282 sal_memset(&defip, 0, sizeof(_bcm_defip_cfg_t)); 3283 defip.defip_l3a_rp = BCM_IPMC_RP_ID_INVALID; 3284 defip.defip_flags = host->l3a_flags; 3285 defip.defip_vrf = host->l3a_vrf; 3286 3287 L3_LOCK(unit); 3288 if (host->l3a_flags & BCM_L3_IP6) { 3289 max_prefix_length = 128; 3290 sal_memcpy(defip.defip_ip6_addr, host->l3a_ip6_addr, BCM_IP6_ADDRLEN); 3291 defip.defip_sub_len = max_prefix_length; 3292 rv = bcm_xgs3_defip_find(unit, &defip); 3293 } else { 3294 defip.defip_ip_addr = host->l3a_ip_addr; 3295 defip.defip_sub_len = 32; 3296 rv = bcm_xgs3_defip_find(unit, &defip); 3297 } 3298 3299 L3_UNLOCK(unit); 3300 if (rv < 0) { 3301 return rv; 3302 } 3303 3304 sal_memcpy(route->l3a_nexthop_mac, defip.defip_mac_addr, 3305 sizeof(bcm_mac_t)); 3306 route->l3a_nexthop_ip = defip.defip_nexthop_ip; 3307 route->l3a_intf = defip.defip_intf; 3308 route->l3a_port_tgid = defip.defip_port_tgid; 3309 route->l3a_modid = defip.defip_modid; 3310 route->l3a_flags = defip.defip_flags; 3311 route->l3a_flags2 = defip.defip_flags2; 3312 route->l3a_mpls_label = defip.defip_mpls_label; 3313 route->l3a_tunnel_option = (uint32)defip.defip_index; 3314 route->l3a_vrf = defip.defip_vrf; 3315 route->l3a_expected_intf = defip.defip_expected_intf; 3316 route->l3a_rp = defip.defip_l3a_rp; 3317 route->l3a_mc_group = defip.defip_mc_group; 3318 route->l3a_ipmc_flags = defip.defip_ipmc_flags; 3319 if (defip.defip_flags & BCM_L3_IPMC ) { 3320 _BCM_MULTICAST_GROUP_SET(route->l3a_mc_group, _BCM_MULTICAST_TYPE_L3, 3321 route->l3a_mc_group); 3322 } 3323 3324 if (soc_feature(unit, soc_feature_overlaid_address_class) && 3325 !BCM_L3_RPE_SET(defip.defip_flags)) { 3326 route->l3a_lookup_class = ((defip.defip_prio & 0xF) << 6); 3327 route->l3a_lookup_class |= (defip.defip_lookup_class & 0x3F); 3328 } else { 3329 route->l3a_lookup_class = defip.defip_lookup_class; 3330 } 3331 if (defip.defip_flags & BCM_L3_IP6) { 3332 sal_memcpy(route->l3a_ip6_net, defip.defip_ip6_addr, BCM_IP6_ADDRLEN); 3333 bcm_ip6_mask_create(route->l3a_ip6_mask, defip.defip_sub_len); 3334 } else { 3335 route->l3a_subnet = defip.defip_ip_addr; 3336 route->l3a_ip_mask = bcm_ip_mask_create(defip.defip_sub_len); 3337 } 3338 3339 BCM_IF_ERROR_RETURN( 3340 _bcm_esw_l3_gport_construct(unit, route->l3a_port_tgid, route->l3a_modid, 3341 route->l3a_port_tgid, route->l3a_flags, 3342 &(route->l3a_port_tgid))); 3343 3344 if (!(route->l3a_ipmc_flags & BCM_IPMC_SOURCE_PORT_NOCHECK)) { 3345 BCM_IF_ERROR_RETURN( 3346 _bcm_esw_l3_gport_construct(unit, defip.defip_source_port_tgid, 3347 defip.defip_source_modid, 3348 defip.defip_source_port_tgid, 3349 defip.defip_source_ts ? BCM_L3_TGID : 0, 3350 &(route->l3a_expected_src_gport))); 3351 } 3352 3353 return BCM_E_NONE; 3354 } 3355 3356 /* 3357 * Function: 3358 * bcm_l3_subnet_route_find 3359 * Purpose: 3360 * Get a Longest Prefix Matched entry from the DEF IP table for a subnet. 3361 * Parameters: 3362 * unit - SOC device unit number 3363 * input - (IN) Given subnet. 3364 * route - (OUT)Pointer to bcm_l3_route_t for return information. 3365 * Returns: 3366 * BCM_E_XXX 3367 * Notes: 3368 * - Application has to pass IP address, IP mask for the network, and 3369 * - flag for IP version. 3370 */ 3371 int 3372 bcm_esw_l3_subnet_route_find(int unit, bcm_l3_route_t *input, 3373 bcm_l3_route_t *route) 3374 { 3375 int max_prefix_length; 3376 _bcm_defip_cfg_t defip; 3377 int rv; 3378 3379 L3_INIT(unit); 3380 3381 if (NULL == input || NULL == route) { 3382 return BCM_E_PARAM; 3383 } 3384 3385 if ((input->l3a_vrf > SOC_VRF_MAX(unit)) || 3386 (input->l3a_vrf < BCM_L3_VRF_GLOBAL)) { 3387 return (BCM_E_PARAM); 3388 } 3389 3390 /* Check that device supports ipv6. */ 3391 if (BCM_L3_NO_IP6_SUPPORT(unit, input->l3a_flags)) { 3392 return (BCM_E_UNAVAIL); 3393 } 3394 3395 sal_memset(&defip, 0, sizeof(_bcm_defip_cfg_t)); 3396 defip.defip_l3a_rp = BCM_IPMC_RP_ID_INVALID; 3397 defip.defip_flags = input->l3a_flags; 3398 defip.defip_vrf = input->l3a_vrf; 3399 3400 L3_LOCK(unit); 3401 if (input->l3a_flags & BCM_L3_IP6) { 3402 bcm_ip6_t mask; 3403 max_prefix_length = 128; 3404 sal_memcpy(defip.defip_ip6_addr, input->l3a_ip6_net, BCM_IP6_ADDRLEN); 3405 sal_memcpy(mask, input->l3a_ip6_mask, BCM_IP6_ADDRLEN); 3406 defip.defip_sub_len = bcm_ip6_mask_length(mask); 3407 if (defip.defip_sub_len > max_prefix_length) { 3408 L3_UNLOCK(unit); 3409 return (BCM_E_PARAM); 3410 } 3411 rv = bcm_xgs3_defip_find(unit, &defip); 3412 } else { 3413 defip.defip_ip_addr = input->l3a_subnet & input->l3a_ip_mask; 3414 defip.defip_sub_len = bcm_ip_mask_length(input->l3a_ip_mask); 3415 rv = bcm_xgs3_defip_find(unit, &defip); 3416 } 3417 3418 L3_UNLOCK(unit); 3419 if (rv < 0) { 3420 return rv; 3421 } 3422 3423 sal_memcpy(route->l3a_nexthop_mac, defip.defip_mac_addr, 3424 sizeof(bcm_mac_t)); 3425 route->l3a_nexthop_ip = defip.defip_nexthop_ip; 3426 route->l3a_intf = defip.defip_intf; 3427 route->l3a_port_tgid = defip.defip_port_tgid; 3428 route->l3a_modid = defip.defip_modid; 3429 route->l3a_lookup_class = defip.defip_lookup_class; 3430 route->l3a_flags = defip.defip_flags; 3431 route->l3a_flags2 = defip.defip_flags2; 3432 route->l3a_mpls_label = defip.defip_mpls_label; 3433 route->l3a_tunnel_option = (uint32)defip.defip_index; 3434 route->l3a_vrf = defip.defip_vrf; 3435 route->l3a_expected_intf = defip.defip_expected_intf; 3436 route->l3a_rp = defip.defip_l3a_rp; 3437 route->l3a_mc_group = defip.defip_mc_group; 3438 route->l3a_ipmc_flags = defip.defip_ipmc_flags; 3439 if (defip.defip_flags & BCM_L3_IPMC ) { 3440 _BCM_MULTICAST_GROUP_SET(route->l3a_mc_group, _BCM_MULTICAST_TYPE_L3, 3441 route->l3a_mc_group); 3442 } 3443 if (defip.defip_flags & BCM_L3_IP6) { 3444 sal_memcpy(route->l3a_ip6_net, defip.defip_ip6_addr, BCM_IP6_ADDRLEN); 3445 bcm_ip6_mask_create(route->l3a_ip6_mask, defip.defip_sub_len); 3446 } else { 3447 route->l3a_subnet = defip.defip_ip_addr; 3448 route->l3a_ip_mask = bcm_ip_mask_create(defip.defip_sub_len); 3449 } 3450 3451 BCM_IF_ERROR_RETURN( 3452 _bcm_esw_l3_gport_construct(unit, route->l3a_port_tgid, route->l3a_modid, 3453 route->l3a_port_tgid, route->l3a_flags, 3454 &(route->l3a_port_tgid))); 3455 return BCM_E_NONE; 3456 } 3457 3458 /* 3459 * Function: 3460 * bcm_esw_l3_route_multipath_get 3461 * Purpose: 3462 * Get all paths for a route, useful for ECMP route, 3463 * For non-ECMP route, there is only one path returned. 3464 * Parameters: 3465 * unit - (IN) SOC device unit number 3466 * the_route - (IN) route's net/mask 3467 * path_array - (OUT) Array of all ECMP paths 3468 * path_count - (OUT) Actual number of ECMP paths 3469 * Returns: 3470 * BCM_E_XXX 3471 */ 3472 3473 int 3474 bcm_esw_l3_route_multipath_get(int unit, bcm_l3_route_t *the_route, 3475 bcm_l3_route_t *path_array, int max_path, int *path_count) 3476 { 3477 int max_prefix_length; 3478 _bcm_defip_cfg_t defip; 3479 int rv; 3480 3481 L3_INIT(unit); 3482 3483 if ((NULL == the_route) || (max_path < 1)) { 3484 return BCM_E_PARAM; 3485 } 3486 3487 if ((the_route->l3a_vrf > SOC_VRF_MAX(unit)) || 3488 (the_route->l3a_vrf < BCM_L3_VRF_GLOBAL)) { 3489 return (BCM_E_PARAM); 3490 } 3491 3492 sal_memset(&defip, 0, sizeof(_bcm_defip_cfg_t)); 3493 defip.defip_l3a_rp = BCM_IPMC_RP_ID_INVALID; 3494 defip.defip_flags = the_route->l3a_flags; 3495 defip.defip_vrf = the_route->l3a_vrf; 3496 3497 L3_LOCK(unit); 3498 if (the_route->l3a_flags & BCM_L3_IP6) { 3499 max_prefix_length = 3500 soc_feature(unit, soc_feature_lpm_prefix_length_max_128) ? 128 : 64; 3501 sal_memcpy(defip.defip_ip6_addr, the_route->l3a_ip6_net, BCM_IP6_ADDRLEN); 3502 defip.defip_sub_len = bcm_ip6_mask_length(the_route->l3a_ip6_mask); 3503 if (defip.defip_sub_len > max_prefix_length) { 3504 L3_UNLOCK(unit); 3505 return (BCM_E_PARAM); 3506 } 3507 rv = mbcm_driver[unit]->mbcm_ip6_defip_ecmp_get_all(unit, &defip, 3508 path_array, max_path, path_count); 3509 } else { 3510 defip.defip_ip_addr = the_route->l3a_subnet & the_route->l3a_ip_mask; 3511 defip.defip_sub_len = bcm_ip_mask_length(the_route->l3a_ip_mask); 3512 rv = mbcm_driver[unit]->mbcm_ip4_defip_ecmp_get_all(unit, &defip, 3513 path_array, max_path, path_count); 3514 } 3515 L3_UNLOCK(unit); 3516 return (rv); 3517 } 3518 3519 /* 3520 * Function: 3521 * bcm_esw_l3_route_delete_by_interface 3522 * Purpose: 3523 * Delete all entries from the DEF IP table which have 3524 * L3 interface number intf. 3525 * Parameters: 3526 * unit - SOC device unit number 3527 * intf - The L3 interface number 3528 * Returns: 3529 * BCM_E_NONE Success 3530 * BCM_E_UNIT Illegal unit number 3531 * BCM_E_INIT Unit Not initialized yet 3532 * Notes: 3533 * - Flag set to BCM_L3_IP6 for IPv6, default is IPv4 3534 * - Flag set to BCM_L3_NEGATE to delete all host entries 3535 * that do NOT match the L3 interface. 3536 */ 3537 3538 int 3539 bcm_esw_l3_route_delete_by_interface(int unit, bcm_l3_route_t *info) 3540 { 3541 int rv; 3542 _bcm_defip_cfg_t defip; 3543 3544 L3_INIT(unit); 3545 3546 if (NULL == info) { 3547 return (BCM_E_PARAM); 3548 } 3549 3550 sal_memset(&defip, 0, sizeof(_bcm_defip_cfg_t)); 3551 defip.defip_intf = info->l3a_intf; 3552 defip.defip_flags = info->l3a_flags; 3553 3554 L3_LOCK(unit); 3555 3556 if (info->l3a_flags & BCM_L3_NEGATE) { 3557 rv = mbcm_driver[unit]->mbcm_defip_delete_intf(unit, &defip, 1); 3558 } else { 3559 rv = mbcm_driver[unit]->mbcm_defip_delete_intf(unit, &defip, 0); 3560 } 3561 3562 L3_UNLOCK(unit); 3563 3564 return (rv); 3565 } 3566 3567 /* 3568 * Function: 3569 * bcm_esw_l3_route_delete_all 3570 * Purpose: 3571 * Remove all defip entries for a specified unit. 3572 * Parameters: 3573 * unit - StrataSwitch Unit #. 3574 * Returns: 3575 * BCM_E_NONE - delete successful. 3576 * BCM_E_XXX - delete failed. 3577 */ 3578 3579 int 3580 bcm_esw_l3_route_delete_all(int unit, bcm_l3_route_t *info) 3581 { 3582 int rv; 3583 L3_INIT(unit); 3584 3585 L3_LOCK(unit); 3586 3587 rv = mbcm_driver[unit]->mbcm_defip_delete_all(unit); 3588 3589 L3_UNLOCK(unit); 3590 3591 return (rv); 3592 } 3593 3594 /* 3595 * Function: 3596 * bcm_esw_l3_route_traverse 3597 * Purpose: 3598 * Find entries from the DEF IP table. 3599 * Parameters: 3600 * unit - SOC device unit number 3601 * flags - BCM_L3_IP6 3602 * start - Starting point of interest. 3603 * end - Ending point of interest. 3604 * trav_fn - User callback function, called once per defip entry. 3605 * user_data - User supplied cookie used in parameter in callback function 3606 * Returns: 3607 * BCM_E_XXX 3608 * Notes: 3609 * The hit returned may be either L3SH or L3DH or Both 3610 */ 3611 int 3612 bcm_esw_l3_route_traverse(int unit, uint32 flags, 3613 uint32 start, uint32 end, 3614 bcm_l3_route_traverse_cb trav_fn, void *user_data) 3615 { 3616 int rv; 3617 3618 L3_INIT(unit); 3619 L3_LOCK(unit); 3620 3621 /* Check that device supports ipv6. */ 3622 if (BCM_L3_NO_IP6_SUPPORT(unit, flags)) { 3623 L3_UNLOCK(unit); 3624 return (BCM_E_UNAVAIL); 3625 } 3626 3627 if (flags & BCM_L3_IP6) { 3628 rv = mbcm_driver[unit]->mbcm_ip6_defip_traverse(unit, 3629 start, end, trav_fn, user_data); 3630 } else { 3631 rv = mbcm_driver[unit]->mbcm_ip4_defip_traverse(unit, 3632 start, end, trav_fn, user_data); 3633 } 3634 3635 L3_UNLOCK(unit); 3636 return (rv); 3637 } 3638 3639 /* to be deprecated */ 3640 int 3641 bcm_esw_l3_defip_traverse(int unit, bcm_l3_route_traverse_cb trav_fn, 3642 uint32 start, uint32 end) 3643 { 3644 int rv; 3645 L3_INIT(unit); 3646 3647 if (start > end) { 3648 return (BCM_E_PARAM); 3649 } 3650 3651 L3_LOCK(unit); 3652 3653 rv = mbcm_driver[unit]->mbcm_ip4_defip_traverse(unit, 3654 start, end, trav_fn, NULL); 3655 L3_UNLOCK(unit); 3656 return (rv); 3657 } 3658 3659 /* 3660 * Function: 3661 * bcm_esw_l3_route_age 3662 * Purpose: 3663 * Age on DEFIP routing table, clear HIT bit of entry if set 3664 * Parameters: 3665 * unit - (IN) BCM device unit number. 3666 * age_out - (IN) Call back routine. 3667 * user_data - (IN) User provided cookie for callback. 3668 * Returns: 3669 * BCM_E_XXX 3670 */ 3671 int 3672 bcm_esw_l3_route_age(int unit, uint32 flags, bcm_l3_route_traverse_cb age_out, 3673 void *user_data) 3674 { 3675 int rv; 3676 L3_INIT(unit); 3677 3678 L3_LOCK(unit); 3679 3680 rv = mbcm_driver[unit]->mbcm_defip_age(unit, age_out, user_data); 3681 3682 L3_UNLOCK(unit); 3683 return (rv); 3684 } 3685 3686 /* 3687 * Function: 3688 * bcm_esw_l3_route_max_ecmp_set 3689 * Purpose: 3690 * Set the maximum ECMP paths allowed for a route 3691 * for chips that supports ECMP 3692 * Parameters: 3693 * unit - SOC device unit number 3694 * max - MAX number of paths for ECMP (number must be power of 2) 3695 * Returns: 3696 * BCM_E_XXX 3697 * Note: 3698 * There is a hardware limit on the number of ECMP paths, 3699 * for bcm_ip_mask_length it is 32, BCM5665/50/73/74 is 8. 3700 * The above parameter must be within the hardware limit. 3701 * This function can be called before ECMP routes are added, 3702 * normally at the beginning. Once ECMP routes exist, cannot be reset. 3703 */ 3704 int 3705 bcm_esw_l3_route_max_ecmp_set(int unit, int max) 3706 { 3707 int rv = BCM_E_UNAVAIL; 3708 L3_INIT(unit); 3709 L3_LOCK(unit); 3710 3711 #if defined(BCM_XGS3_SWITCH_SUPPORT) 3712 if (SOC_IS_XGS3_SWITCH(unit)) { 3713 rv = bcm_xgs3_max_ecmp_set(unit, max); 3714 } 3715 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 3716 3717 L3_UNLOCK(unit); 3718 return (rv); 3719 } 3720 3721 /* 3722 * Function: 3723 * bcm_esw_l3_route_max_ecmp_get 3724 * Purpose: 3725 * Get the maximum ECMP paths allowed for a route 3726 * for chips that supports ECMP 3727 * Parameters: 3728 * unit - SOC device unit number 3729 * max - (OUT)MAX number of paths for ECMP (number must be power of 2) 3730 * Returns: 3731 * BCM_E_XXX 3732 */ 3733 int 3734 bcm_esw_l3_route_max_ecmp_get(int unit, int *max) 3735 { 3736 int rv = BCM_E_UNAVAIL; 3737 L3_INIT(unit); 3738 3739 if (NULL == max) { 3740 return (BCM_E_PARAM); 3741 } 3742 3743 *max = 0; 3744 3745 L3_LOCK(unit); 3746 #if defined(BCM_XGS3_SWITCH_SUPPORT) 3747 if (SOC_IS_XGS3_SWITCH(unit)) { 3748 rv = bcm_xgs3_max_ecmp_get(unit, max); 3749 } 3750 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 3751 L3_UNLOCK(unit); 3752 return (rv); 3753 } 3754 3755 /* 3756 * Function: 3757 * bcm_l3_cleanup 3758 * Purpose: 3759 * Detach L3 function for a unit, clean up all tables and data structures 3760 * Parameters: 3761 * unit - StrataSwitch Unit #. 3762 * Returns: 3763 * BCM_E_NONE - detach successful. 3764 * BCM_E_XXX - detach failed. 3765 */ 3766 3767 int 3768 bcm_esw_l3_cleanup(int unit) 3769 { 3770 int rv = BCM_E_NONE; 3771 3772 if ((0 == l3_internal_initialized) || 3773 (0 == _bcm_l3_bk_info[unit].l3_initialized)) { 3774 if (NULL != mbcm_driver[unit]) { 3775 rv = mbcm_driver[unit]->mbcm_l3_tables_cleanup(unit); 3776 } 3777 return rv; 3778 } 3779 3780 L3_LOCK(unit); 3781 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT 3782 if (soc_feature(unit, soc_feature_l3_ecmp_protected_access)) { 3783 rv = soc_esw_ecmp_protected_detach(unit); 3784 if (BCM_FAILURE(rv)) { 3785 L3_UNLOCK(unit); 3786 return (rv); 3787 } 3788 } 3789 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */ 3790 3791 rv = bcm_esw_ipmc_detach(unit); 3792 if (BCM_FAILURE(rv)) { 3793 L3_UNLOCK(unit); 3794 return (rv); 3795 } 3796 3797 /*no subport feature in Hurricane*/ 3798 if(!(SOC_IS_HURRICANEX(unit)||SOC_IS_GREYHOUND(unit) || 3799 SOC_IS_GREYHOUND2(unit))) { 3800 rv = bcm_esw_subport_cleanup(unit); 3801 if (BCM_FAILURE(rv)) { 3802 L3_UNLOCK(unit); 3803 return (rv); 3804 } 3805 }/*SOC_IS_HURRICANE*/ 3806 3807 rv = bcm_esw_mpls_cleanup(unit); 3808 if (BCM_FAILURE(rv)) { 3809 L3_UNLOCK(unit); 3810 return (rv); 3811 } 3812 3813 if(!(SOC_IS_HURRICANEX(unit)||SOC_IS_GREYHOUND(unit) || 3814 SOC_IS_GREYHOUND2(unit))) { 3815 rv = bcm_esw_wlan_detach(unit); 3816 if (BCM_FAILURE(rv)) { 3817 L3_UNLOCK(unit); 3818 return (rv); 3819 } 3820 }/*SOC_IS_HURRICANE*/ 3821 3822 if(!(SOC_IS_HURRICANEX(unit)||SOC_IS_GREYHOUND(unit) || 3823 SOC_IS_GREYHOUND2(unit))) { 3824 rv = bcm_esw_mim_detach(unit); 3825 if (BCM_FAILURE(rv)) { 3826 L3_UNLOCK(unit); 3827 return (rv); 3828 } 3829 } 3830 3831 if (0 == SOC_HW_ACCESS_DISABLE(unit)) { 3832 rv = bcm_esw_l3_route_delete_all(unit, NULL); 3833 if (BCM_FAILURE(rv)) { 3834 L3_UNLOCK(unit); 3835 return (rv); 3836 } 3837 rv = bcm_esw_l3_host_delete_all(unit, NULL); 3838 if (BCM_FAILURE(rv)) { 3839 L3_UNLOCK(unit); 3840 return (rv); 3841 } 3842 rv = bcm_esw_l3_intf_delete_all(unit); 3843 if (BCM_FAILURE(rv)) { 3844 L3_UNLOCK(unit); 3845 return (rv); 3846 } 3847 } 3848 3849 rv = mbcm_driver[unit]->mbcm_l3_tables_cleanup(unit); 3850 _bcm_l3_bk_info[unit].l3_initialized = 0; 3851 3852 /* Clear the state which is needed in L3 subsystem */ 3853 bcmi_esw_l3_dependent_cleanup(unit); 3854 3855 L3_UNLOCK(unit); 3856 3857 return(rv); 3858 } 3859 3860 /* 3861 * Function: 3862 * bcm_esw_l3_enable_set 3863 * Purpose: 3864 * Enable/disable L3 function for a unit without clearing any L3 tables 3865 * Parameters: 3866 * unit - StrataSwitch Unit #. 3867 * enable - 1 for enable, 0 for disable 3868 * Returns: 3869 * BCM_E_XXX 3870 */ 3871 3872 int 3873 bcm_esw_l3_enable_set(int unit, int enable) 3874 { 3875 L3_INIT(unit); 3876 L3_LOCK(unit); 3877 3878 mbcm_driver[unit]->mbcm_l3_enable(unit, enable); 3879 3880 L3_UNLOCK(unit); 3881 3882 return (BCM_E_NONE); 3883 } 3884 3885 /* 3886 * Function: 3887 * bcm_esw_l3_info 3888 * Purpose: 3889 * Get the status of hardware. 3890 * Parameters: 3891 * unit - SOC device unit number 3892 * l3_info - (OUT) Available hardware's L3 information. 3893 * Returns: 3894 * BCM_E_XXX. 3895 */ 3896 3897 int 3898 bcm_esw_l3_info(int unit, bcm_l3_info_t *l3info) 3899 { 3900 int rv; 3901 L3_INIT(unit); 3902 3903 if (l3info == NULL) { 3904 return (BCM_E_PARAM); 3905 } 3906 L3_LOCK(unit); 3907 3908 rv = mbcm_driver[unit]->mbcm_l3_info_get(unit, l3info); 3909 3910 L3_UNLOCK(unit); 3911 return (rv); 3912 } 3913 3914 /* 3915 * Function: 3916 * bcm_esw_l3_ingress_create 3917 * Purpose: 3918 * Create an Ingress Interface object. 3919 * Parameters: 3920 * unit - (IN) bcm device. 3921 * flags - (IN) BCM_L3_INGRESS_REPLACE: replace existing. 3922 * BCM_L3_INGRESS_WITH_ID: intf argument is given. 3923 * BCM_L3_INGRESS_GLOBAL_ROUTE : 3924 * BCM_L3_INGRESS_DSCP_TRUST : 3925 * ing_intf - (IN) Ingress Interface information. 3926 * intf_id - (OUT) L3 Ingress interface id pointing to Ingress object. 3927 * This is an IN argument if either BCM_L3_INGRESS_REPLACE 3928 * or BCM_L3_INGRESS_WITH_ID are given in flags. 3929 * Returns: 3930 * BCM_E_XXX 3931 */ 3932 3933 int 3934 bcm_esw_l3_ingress_create(int unit, bcm_l3_ingress_t *ing_intf, bcm_if_t *intf_id) 3935 { 3936 int rv = BCM_E_UNAVAIL; 3937 #if defined (BCM_TRIUMPH_SUPPORT) 3938 if (soc_feature(unit,soc_feature_l3_ingress_interface)) { 3939 L3_LOCK(unit); 3940 rv = bcm_xgs3_l3_ingress_create(unit, ing_intf, intf_id); 3941 L3_UNLOCK(unit); 3942 } 3943 #endif 3944 return rv; 3945 } 3946 3947 /* 3948 * Function: 3949 * bcm_esw_l3_ingress_destroy 3950 * Purpose: 3951 * Destroy an Ingress Interface object. 3952 * Parameters: 3953 * unit - (IN) bcm device. 3954 * intf_id - (IN) L3 Ingress interface id pointing to Ingress object. 3955 * Returns: 3956 * BCM_E_XXX 3957 */ 3958 3959 int 3960 bcm_esw_l3_ingress_destroy(int unit, bcm_if_t intf_id) 3961 { 3962 int rv = BCM_E_UNAVAIL; 3963 #if defined (BCM_TRIUMPH_SUPPORT) 3964 if (soc_feature(unit,soc_feature_l3_ingress_interface)) { 3965 L3_LOCK(unit); 3966 rv = bcm_xgs3_l3_ingress_destroy(unit, intf_id); 3967 L3_UNLOCK(unit); 3968 } 3969 #endif 3970 return rv; 3971 } 3972 3973 /* 3974 * Function: 3975 * bcm_esw_l3_ingress_find 3976 * Purpose: 3977 * Find an Ingress Interface object. 3978 * Parameters: 3979 * unit - (IN) bcm device. 3980 * ing_intf - (IN) Ingress Interface information. 3981 * intf_id - (OUT) L3 Ingress interface id pointing to Ingress object. 3982 * Returns: 3983 * BCM_E_XXX 3984 */ 3985 3986 int 3987 bcm_esw_l3_ingress_find(int unit, bcm_l3_ingress_t *ing_intf, bcm_if_t *intf_id) 3988 { 3989 int rv = BCM_E_UNAVAIL; 3990 #if defined (BCM_TRIUMPH_SUPPORT) 3991 if (soc_feature(unit,soc_feature_l3_ingress_interface)) { 3992 L3_LOCK(unit); 3993 rv = bcm_xgs3_l3_ingress_find(unit, ing_intf, intf_id); 3994 L3_UNLOCK(unit); 3995 } 3996 #endif 3997 return rv; 3998 } 3999 4000 /* 4001 * Function: 4002 * bcm_esw_l3_ingress_get 4003 * Purpose: 4004 * Get an Ingress Interface object. 4005 * Parameters: 4006 * unit - (IN) bcm device. 4007 * intf_id - (IN) L3 Ingress interface id pointing to Ingress object. 4008 * ing_intf - (OUT) Ingress Interface information. 4009 * Returns: 4010 * BCM_E_XXX 4011 */ 4012 4013 int 4014 bcm_esw_l3_ingress_get(int unit, bcm_if_t intf_id, bcm_l3_ingress_t *ing_intf) 4015 { 4016 int rv = BCM_E_UNAVAIL; 4017 #if defined (BCM_TRIUMPH_SUPPORT) 4018 if (soc_feature(unit,soc_feature_l3_ingress_interface)) { 4019 L3_LOCK(unit); 4020 rv = bcm_xgs3_l3_ingress_get(unit, intf_id, ing_intf); 4021 L3_UNLOCK(unit); 4022 } 4023 #endif 4024 return rv; 4025 } 4026 4027 /* 4028 * Function: 4029 * bcm_esw_l3_ingress_traverse 4030 * Purpose: 4031 * Goes through ijgress interface objects table and runs the user callback 4032 * function at each valid ingress objects entry passing back the 4033 * information for that object. 4034 * Parameters: 4035 * unit - (IN) bcm device. 4036 * trav_fn - (IN) Callback function. 4037 * user_data - (IN) User data to be passed to callback function. 4038 * Returns: 4039 * BCM_E_XXX 4040 */ 4041 int 4042 bcm_esw_l3_ingress_traverse(int unit, 4043 bcm_l3_ingress_traverse_cb trav_fn, void *user_data) 4044 { 4045 int rv = BCM_E_UNAVAIL; 4046 #if defined (BCM_TRIUMPH_SUPPORT) 4047 if (soc_feature(unit,soc_feature_l3_ingress_interface)) { 4048 L3_LOCK(unit); 4049 rv = bcm_xgs3_l3_ingress_traverse(unit, trav_fn, user_data); 4050 L3_UNLOCK(unit); 4051 } 4052 #endif 4053 return rv; 4054 } 4055 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 4056 /* 4057 * Function: 4058 * _bcm_esw_l3_egress_stat_get_table_info 4059 * Description: 4060 * Provides relevant flex table information(table-name,index with 4061 * direction) for given egress interface. 4062 * 4063 * Parameters: 4064 * unit - (IN) unit number 4065 * intf_id - (IN) Interface id of a egress L3 object. 4066 * num_of_tables - (OUT) Number of flex counter tables 4067 * table_info - (OUT) Flex counter tables information 4068 * 4069 * Return Value: 4070 * BCM_E_XXX 4071 * Notes: 4072 */ 4073 static 4074 bcm_error_t _bcm_esw_l3_egress_stat_get_table_info( 4075 int unit, 4076 bcm_if_t intf_id, 4077 uint32 *num_of_tables, 4078 bcm_stat_flex_table_info_t *table_info) 4079 { 4080 bcm_l3_egress_t egr_intf={0}; 4081 int index=0; 4082 4083 (*num_of_tables) = 0; 4084 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 4085 return BCM_E_UNAVAIL; 4086 } 4087 BCM_IF_ERROR_RETURN(bcm_esw_l3_egress_get(unit, intf_id, &egr_intf)); 4088 #ifdef BCM_TRIUMPH2_SUPPORT 4089 if (soc_feature(unit, soc_feature_wlan) && egr_intf.encap_id > 0) { 4090 index = intf_id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) ; 4091 } else 4092 #endif 4093 { 4094 if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, intf_id)) { 4095 index = intf_id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 4096 } else { 4097 index = intf_id - BCM_XGS3_EGRESS_IDX_MIN(unit); 4098 } 4099 } 4100 table_info[*num_of_tables].table=EGR_L3_NEXT_HOPm; 4101 table_info[*num_of_tables].index=index; 4102 table_info[*num_of_tables].direction=bcmStatFlexDirectionEgress; 4103 (*num_of_tables)++; 4104 return BCM_E_NONE; 4105 } 4106 /* 4107 * Function: 4108 * _bcm_esw_l3_ingress_stat_get_table_info 4109 * Description: 4110 * Provides relevant flex table information(table-name,index with 4111 * direction) for given ingress interface. 4112 * 4113 * Parameters: 4114 * unit - (IN) unit number 4115 * intf_id - (IN) Interface id of a ingress L3 object. 4116 * num_of_tables - (OUT) Number of flex counter tables 4117 * table_info - (OUT) Flex counter tables information 4118 * 4119 * Return Value: 4120 * BCM_E_XXX 4121 * Notes: 4122 */ 4123 static 4124 bcm_error_t _bcm_esw_l3_ingress_stat_get_table_info( 4125 int unit, 4126 bcm_if_t intf_id, 4127 uint32 *num_of_tables, 4128 bcm_stat_flex_table_info_t *table_info) 4129 { 4130 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 4131 return BCM_E_UNAVAIL; 4132 } 4133 4134 /* Input parameters check. */ 4135 if ( (intf_id < 0) || (intf_id >= BCM_XGS3_L3_ING_IF_TBL_SIZE(unit))) { 4136 return (BCM_E_PARAM); 4137 } 4138 4139 if (!SHR_BITGET(BCM_XGS3_L3_ING_IF_INUSE(unit), intf_id)) { 4140 return (BCM_E_NOT_FOUND); 4141 } 4142 4143 table_info[*num_of_tables].table=L3_IIFm; 4144 table_info[*num_of_tables].index=intf_id; 4145 table_info[*num_of_tables].direction=bcmStatFlexDirectionIngress; 4146 (*num_of_tables)++; 4147 return BCM_E_NONE; 4148 } 4149 #endif 4150 4151 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 4152 STATIC _bcm_flex_stat_t 4153 _bcm_esw_l3_stat_to_flex_stat(bcm_l3_stat_t stat) 4154 { 4155 _bcm_flex_stat_t flex_stat; 4156 4157 switch (stat) { 4158 case bcmL3StatInPackets: 4159 flex_stat = _bcmFlexStatIngressPackets; 4160 break; 4161 case bcmL3StatInBytes: 4162 flex_stat = _bcmFlexStatIngressBytes; 4163 break; 4164 case bcmL3StatOutPackets: 4165 flex_stat = _bcmFlexStatEgressPackets; 4166 break; 4167 case bcmL3StatOutBytes: 4168 flex_stat = _bcmFlexStatEgressBytes; 4169 break; 4170 default: 4171 flex_stat = _bcmFlexStatNum; 4172 } 4173 4174 return flex_stat; 4175 } 4176 #endif 4177 4178 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 4179 /* 4180 * Function: 4181 * _bcm_esw_l3_egress_stat_attach 4182 * Description: 4183 * Attach counters entries to the given L3 Egress interface 4184 * 4185 * Parameters: 4186 * unit - (IN) unit number 4187 * intf_id - (IN) Interface id of a egress L3 object. 4188 * stat_counter_id - (IN) Stat Counter ID. 4189 * 4190 * Return Value: 4191 * BCM_E_XXX 4192 * Notes: 4193 */ 4194 STATIC bcm_error_t _bcm_esw_l3_egress_stat_attach( 4195 int unit, 4196 bcm_if_t intf_id, 4197 uint32 stat_counter_id) 4198 { 4199 soc_mem_t table=0; 4200 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 4201 uint32 pool_number=0; 4202 uint32 base_index=0; 4203 bcm_stat_flex_mode_t offset_mode=0; 4204 bcm_stat_object_t object=bcmStatObjectIngPort; 4205 bcm_stat_group_mode_t group_mode= bcmStatGroupModeSingle; 4206 uint32 count=0; 4207 uint32 actual_num_tables=0; 4208 uint32 num_of_tables=0; 4209 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4210 4211 _bcm_esw_stat_get_counter_id_info( 4212 unit, 4213 stat_counter_id, 4214 &group_mode,&object,&offset_mode,&pool_number,&base_index); 4215 BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_object(unit,object,&direction)); 4216 BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit,group_mode)); 4217 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_table_info( 4218 unit,object,1,&actual_num_tables,&table,&direction)); 4219 4220 BCM_IF_ERROR_RETURN(_bcm_esw_l3_egress_stat_get_table_info( 4221 unit, intf_id,&num_of_tables,&table_info[0])); 4222 for (count=0; count < num_of_tables ; count++) { 4223 if ((table_info[count].direction == direction) && 4224 (table_info[count].table == table) ) { 4225 if (direction == bcmStatFlexDirectionIngress) { 4226 return _bcm_esw_stat_flex_attach_ingress_table_counters( 4227 unit, 4228 table_info[count].table, 4229 table_info[count].index, 4230 offset_mode, 4231 base_index, 4232 pool_number); 4233 } else { 4234 return _bcm_esw_stat_flex_attach_egress_table_counters( 4235 unit, 4236 table_info[count].table, 4237 table_info[count].index, 4238 0, 4239 offset_mode, 4240 base_index, 4241 pool_number); 4242 } 4243 } 4244 } 4245 return BCM_E_NOT_FOUND; 4246 } 4247 #endif 4248 4249 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 4250 STATIC int 4251 _bcm_esw_l3_egr_flex_stat_hw_index_set(int unit, _bcm_flex_stat_handle_t fsh, 4252 int fs_idx, void *cookie) 4253 { 4254 bcm_if_t intf_id; 4255 int index; 4256 egr_l3_next_hop_entry_t egr_nh; 4257 int rv; 4258 uint32 handle = _BCM_FLEX_STAT_HANDLE_WORD_GET(fsh, 0); 4259 bcm_l3_egress_t egr_intf={0}; 4260 int entry_type; 4261 soc_mem_info_t *memp; 4262 soc_field_t ctr_field; 4263 soc_field_t use_ctr_field; 4264 4265 intf_id = (bcm_if_t)handle; 4266 rv = BCM_E_NONE; 4267 4268 BCM_IF_ERROR_RETURN(bcm_esw_l3_egress_get(unit, intf_id, &egr_intf)); 4269 4270 if (soc_feature(unit, soc_feature_wlan) && egr_intf.encap_id > 0) { 4271 index = intf_id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 4272 } else { 4273 index = intf_id - BCM_XGS3_EGRESS_IDX_MIN(unit); 4274 } 4275 4276 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,index,&egr_nh); 4277 4278 if (BCM_SUCCESS(rv)) { 4279 entry_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4280 ENTRY_TYPEf); 4281 memp = &SOC_MEM_INFO(unit, EGR_L3_NEXT_HOPm); 4282 if (memp->views != NULL) { 4283 if (sal_strcmp(memp->views[entry_type],"L3") == 0) { 4284 ctr_field = L3__VINTF_CTR_IDXf; 4285 use_ctr_field = L3__USE_VINTF_CTR_IDXf; 4286 } else if (sal_strcmp(memp->views[entry_type],"PROXY") == 0) { 4287 ctr_field = PROXY__VINTF_CTR_IDXf; 4288 use_ctr_field = PROXY__USE_VINTF_CTR_IDXf; 4289 } else if (sal_strcmp(memp->views[entry_type],"MPLS") == 0) { 4290 ctr_field = MPLS__VINTF_CTR_IDXf; 4291 use_ctr_field = MPLS__USE_VINTF_CTR_IDXf; 4292 } else if (sal_strcmp(memp->views[entry_type],"SD_TAG") == 0) { 4293 ctr_field = SD_TAG__VINTF_CTR_IDXf; 4294 use_ctr_field = SD_TAG__USE_VINTF_CTR_IDXf; 4295 } else if (sal_strcmp(memp->views[entry_type],"MIM") == 0) { 4296 ctr_field = MIM__VINTF_CTR_IDXf; 4297 use_ctr_field = MIM__USE_VINTF_CTR_IDXf; 4298 } else { 4299 return BCM_E_UNAVAIL; 4300 } 4301 } else { 4302 ctr_field = L3__VINTF_CTR_IDXf; 4303 use_ctr_field = L3__USE_VINTF_CTR_IDXf; 4304 } 4305 4306 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, use_ctr_field)) { 4307 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4308 use_ctr_field, fs_idx > 0 ? 1 : 0); 4309 } 4310 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, ctr_field)) { 4311 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4312 ctr_field, fs_idx); 4313 } 4314 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, index, 4315 &egr_nh); 4316 } 4317 return rv; 4318 } 4319 4320 STATIC int 4321 _bcm_esw_l3_ingr_flex_stat_hw_index_set(int unit, _bcm_flex_stat_handle_t fsh, 4322 int fs_idx, void *cookie) 4323 { 4324 int index; 4325 int rv; 4326 uint32 handle = _BCM_FLEX_STAT_HANDLE_WORD_GET(fsh, 0); 4327 iif_entry_t l3iif_entry; 4328 4329 index = (int)handle; /* interface_id */ 4330 rv = BCM_E_NONE; 4331 4332 rv = soc_mem_read(unit, L3_IIFm, MEM_BLOCK_ANY,index,&l3iif_entry); 4333 4334 if (BCM_SUCCESS(rv)) { 4335 if (soc_mem_field_valid(unit, L3_IIFm, 4336 USE_VINTF_CTR_IDXf)) { 4337 soc_mem_field32_set(unit, L3_IIFm, &l3iif_entry, 4338 USE_VINTF_CTR_IDXf, 4339 fs_idx > 0 ? 1 : 0); 4340 } 4341 soc_mem_field32_set(unit, L3_IIFm, &l3iif_entry, 4342 VINTF_CTR_IDXf, fs_idx); 4343 rv = soc_mem_write(unit, L3_IIFm, MEM_BLOCK_ALL, index, 4344 &l3iif_entry); 4345 } 4346 return rv; 4347 } 4348 4349 #endif 4350 4351 /* 4352 * Function: 4353 * bcm_esw_l3_egress_stat_attach 4354 * Description: 4355 * Attach counters entries to the given L3 Egress interface 4356 * 4357 * Parameters: 4358 * unit - (IN) unit number 4359 * intf_id - (IN) Interface id of a egress L3 object. 4360 * stat_counter_id - (IN) Stat Counter ID. 4361 * 4362 * Return Value: 4363 * BCM_E_XXX 4364 * Notes: 4365 */ 4366 int bcm_esw_l3_egress_stat_attach( 4367 int unit, 4368 bcm_if_t intf_id, 4369 uint32 stat_counter_id) 4370 { 4371 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 4372 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 4373 return _bcm_esw_l3_egress_stat_attach(unit,intf_id,stat_counter_id); 4374 } else 4375 #endif 4376 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 4377 if (soc_feature(unit,soc_feature_gport_service_counters)) { 4378 _bcm_flex_stat_type_t fs_type; 4379 uint32 fs_inx; 4380 uint32 flag; 4381 int rv; 4382 4383 fs_type = _BCM_FLEX_STAT_TYPE(stat_counter_id); 4384 fs_inx = _BCM_FLEX_STAT_COUNT_INX(stat_counter_id); 4385 4386 if (!((fs_type == _bcmFlexStatTypeEgressGport) && fs_inx)) { 4387 return BCM_E_PARAM; 4388 } 4389 4390 flag = _BCM_FLEX_STAT_HW_EGRESS; 4391 4392 rv = _bcm_esw_flex_stat_enable_set(unit, fs_type, 4393 _bcm_esw_l3_egr_flex_stat_hw_index_set, 4394 INT_TO_PTR(flag), 4395 intf_id, TRUE,fs_inx); 4396 return rv; 4397 } else 4398 #endif 4399 { 4400 return BCM_E_UNAVAIL; 4401 } 4402 } 4403 4404 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 4405 /* 4406 * Function: 4407 * _bcm_esw_l3_egress_stat_detach 4408 * Description: 4409 * Detach counters entries to the given L3 Egress interface. 4410 * 4411 * Parameters: 4412 * unit - (IN) unit number 4413 * intf_id - (IN) Interface id of a egress L3 object. 4414 * stat_counter_id - (IN) Stat Counter ID. 4415 * 4416 * Return Value: 4417 * BCM_E_XXX 4418 * Notes: 4419 */ 4420 STATIC 4421 bcm_error_t _bcm_esw_l3_egress_stat_detach( 4422 int unit, 4423 bcm_if_t intf_id) 4424 { 4425 uint32 count=0; 4426 uint32 num_of_tables=0; 4427 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4428 bcm_error_t rv = BCM_E_NONE; 4429 bcm_error_t err_code[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION] = {BCM_E_NOT_FOUND}; 4430 uint32 flag[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION] = {0}; 4431 4432 BCM_IF_ERROR_RETURN(_bcm_esw_l3_egress_stat_get_table_info( 4433 unit, intf_id,&num_of_tables,&table_info[0])); 4434 4435 for (count=0; count < num_of_tables ; count++) { 4436 if (table_info[count].direction == bcmStatFlexDirectionIngress) { 4437 if (0 == flag[bcmStatFlexDirectionIngress]) { 4438 err_code[bcmStatFlexDirectionIngress] = BCM_E_NONE; 4439 flag[bcmStatFlexDirectionIngress] = 1; 4440 } 4441 rv = _bcm_esw_stat_flex_detach_ingress_table_counters( 4442 unit, table_info[count].table,table_info[count].index); 4443 if (BCM_E_NONE != rv && 4444 BCM_E_NONE == err_code[bcmStatFlexDirectionIngress]) { 4445 err_code[bcmStatFlexDirectionIngress] = rv; 4446 } 4447 } else { 4448 if (0 == flag[bcmStatFlexDirectionEgress]) { 4449 err_code[bcmStatFlexDirectionEgress] = BCM_E_NONE; 4450 flag[bcmStatFlexDirectionEgress] = 1; 4451 } 4452 rv = _bcm_esw_stat_flex_detach_egress_table_counters( 4453 unit, 0, table_info[count].table, 4454 table_info[count].index); 4455 if (BCM_E_NONE != rv && 4456 BCM_E_NONE == err_code[bcmStatFlexDirectionEgress]) { 4457 err_code[bcmStatFlexDirectionEgress] = rv; 4458 } 4459 } 4460 } 4461 4462 BCM_STAT_FLEX_DETACH_RETURN(err_code) 4463 } 4464 #endif 4465 4466 /* 4467 * Function: 4468 * bcm_esw_l3_egress_stat_detach 4469 * Description: 4470 * Detach counters entries to the given L3 Egress interface. 4471 * 4472 * Parameters: 4473 * unit - (IN) unit number 4474 * intf_id - (IN) Interface id of a egress L3 object. 4475 * stat_counter_id - (IN) Stat Counter ID. 4476 * 4477 * Return Value: 4478 * BCM_E_XXX 4479 * Notes: 4480 */ 4481 int bcm_esw_l3_egress_stat_detach( 4482 int unit, 4483 bcm_if_t intf_id) 4484 { 4485 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 4486 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 4487 return _bcm_esw_l3_egress_stat_detach(unit,intf_id); 4488 } else 4489 #endif 4490 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 4491 if (soc_feature(unit,soc_feature_gport_service_counters)) { 4492 uint32 flag; 4493 int rv; 4494 4495 flag = _BCM_FLEX_STAT_HW_EGRESS; 4496 4497 rv = _bcm_esw_flex_stat_enable_set(unit, _bcmFlexStatTypeEgressGport, 4498 _bcm_esw_l3_egr_flex_stat_hw_index_set, 4499 INT_TO_PTR(flag), 4500 intf_id, FALSE,1); 4501 return rv; 4502 } else 4503 #endif 4504 { 4505 return BCM_E_UNAVAIL; 4506 } 4507 } 4508 4509 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 4510 /* 4511 * Function: 4512 * _bcm_esw_l3_egress_stat_counter_get 4513 * Description: 4514 * Get the specified counter statistic for a L3 egress interface 4515 * if sync_mode is set, sync the sw accumulated count 4516 * with hw count value first, else return sw count. 4517 * 4518 * Parameters: 4519 * unit - (IN) unit number 4520 * sync_mode - (IN) hwcount is to be synced to sw count 4521 * intf_id - (IN) Interface id of a egress L3 object. 4522 * stat - (IN) Type of the counter to retrieve 4523 * I.e. ingress/egress byte/packet) 4524 * num_entries - (IN) Number of counter Entries 4525 * counter_indexes - (IN) Pointer to Counter indexes entries 4526 * counter_values - (OUT) Pointer to counter values 4527 * 4528 * Return Value: 4529 * BCM_E_XXX 4530 * Notes: 4531 */ 4532 STATIC 4533 bcm_error_t _bcm_esw_l3_egress_stat_counter_get(int unit, 4534 int sync_mode, 4535 bcm_if_t intf_id, 4536 bcm_l3_stat_t stat, 4537 uint32 num_entries, 4538 uint32 *counter_indexes, 4539 bcm_stat_value_t *counter_values) 4540 { 4541 uint32 table_count=0; 4542 uint32 index_count=0; 4543 uint32 num_of_tables=0; 4544 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 4545 uint32 byte_flag=0; 4546 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4547 4548 if ((stat == bcmL3StatOutPackets) || 4549 (stat == bcmL3StatOutBytes)) { 4550 direction = bcmStatFlexDirectionEgress; 4551 } else { 4552 /* direction = bcmStatFlexDirectionIngress; */ 4553 return BCM_E_PARAM; 4554 } 4555 if (stat == bcmL3StatOutPackets) { 4556 byte_flag=0; 4557 } else { 4558 byte_flag=1; 4559 } 4560 4561 BCM_IF_ERROR_RETURN(_bcm_esw_l3_egress_stat_get_table_info( 4562 unit, intf_id,&num_of_tables,&table_info[0])); 4563 4564 for (table_count=0; table_count < num_of_tables ; table_count++) { 4565 if (table_info[table_count].direction == direction) { 4566 for (index_count=0; index_count < num_entries ; index_count++) { 4567 BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_get( 4568 unit, sync_mode, 4569 table_info[table_count].index, 4570 table_info[table_count].table, 4571 0, byte_flag, 4572 counter_indexes[index_count], 4573 &counter_values[index_count])); 4574 } 4575 } 4576 } 4577 return BCM_E_NONE; 4578 } 4579 #endif 4580 4581 /* 4582 * Function: 4583 * _bcm_esw_l3_egress_counter_get 4584 * Description: 4585 * Get the specified counter statistic for a L3 egress interface 4586 * if sync_mode is set, sync the sw accumulated count 4587 * with hw count value first, else return sw count. 4588 * 4589 * Parameters: 4590 * unit - (IN) unit number 4591 * sync_mode - (IN) hwcount is to be synced to sw count 4592 * intf_id - (IN) Interface id of a egress L3 object. 4593 * stat - (IN) Type of the counter to retrieve 4594 * I.e. ingress/egress byte/packet) 4595 * num_entries - (IN) Number of counter Entries 4596 * counter_indexes - (IN) Pointer to Counter indexes entries 4597 * counter_values - (OUT) Pointer to counter values 4598 * 4599 * Return Value: 4600 * BCM_E_XXX 4601 * Notes: 4602 */ 4603 int _bcm_esw_l3_egress_counter_get(int unit, 4604 int sync_mode, 4605 bcm_if_t intf_id, 4606 bcm_l3_stat_t stat, 4607 uint32 num_entries, 4608 uint32 *counter_indexes, 4609 bcm_stat_value_t *counter_values) 4610 { 4611 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 4612 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 4613 return _bcm_esw_l3_egress_stat_counter_get(unit, sync_mode, 4614 intf_id, 4615 stat, num_entries, 4616 counter_indexes, 4617 counter_values); 4618 } else 4619 #endif 4620 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 4621 if (soc_feature(unit,soc_feature_gport_service_counters)) { 4622 uint64 val; 4623 int rv = BCM_E_NONE; 4624 4625 if (!(stat == bcmL3StatOutPackets || 4626 stat == bcmL3StatOutBytes)) { 4627 return BCM_E_PARAM; 4628 } 4629 rv = _bcm_esw_flex_stat_get(unit, 4630 sync_mode, 4631 _bcmFlexStatTypeEgressGport, 4632 intf_id, 4633 _bcm_esw_l3_stat_to_flex_stat(stat), 4634 &val); 4635 4636 if (stat == bcmL3StatOutPackets) { 4637 counter_values->packets = COMPILER_64_LO(val); 4638 } else { 4639 COMPILER_64_SET(counter_values->bytes, 4640 COMPILER_64_HI(val), 4641 COMPILER_64_LO(val)); 4642 } 4643 return rv; 4644 4645 } else 4646 #endif 4647 { 4648 return BCM_E_UNAVAIL; 4649 } 4650 } 4651 4652 /* 4653 * Function: 4654 * bcm_esw_l3_egress_stat_counter_get 4655 * Description: 4656 * Get the specified counter statistic for a L3 egress interface 4657 * 4658 * Parameters: 4659 * unit - (IN) unit number 4660 * intf_id - (IN) Interface id of a egress L3 object. 4661 * stat - (IN) Type of the counter to retrieve 4662 * I.e. ingress/egress byte/packet) 4663 * num_entries - (IN) Number of counter Entries 4664 * counter_indexes - (IN) Pointer to Counter indexes entries 4665 * counter_values - (OUT) Pointer to counter values 4666 * 4667 * Return Value: 4668 * BCM_E_XXX 4669 * Notes: 4670 */ 4671 int bcm_esw_l3_egress_stat_counter_get( 4672 int unit, 4673 bcm_if_t intf_id, 4674 bcm_l3_stat_t stat, 4675 uint32 num_entries, 4676 uint32 *counter_indexes, 4677 bcm_stat_value_t *counter_values) 4678 { 4679 return _bcm_esw_l3_egress_counter_get(unit, 0, intf_id, stat, 4680 num_entries, 4681 counter_indexes, 4682 counter_values); 4683 } 4684 4685 /* 4686 * Function: 4687 * bcm_esw_l3_egress_stat_counter_sync_get 4688 * Description: 4689 * retrieve set of counter statistics for a L3 egress interface 4690 * sw accumulated counters synced with hw count. 4691 * 4692 * Parameters: 4693 * unit - (IN) unit number 4694 * intf_id - (IN) Interface id of a egress L3 object. 4695 * stat - (IN) Type of the counter to retrieve 4696 * I.e. ingress/egress byte/packet) 4697 * num_entries - (IN) Number of counter Entries 4698 * counter_indexes - (IN) Pointer to Counter indexes entries 4699 * counter_values - (OUT) Pointer to counter values 4700 * 4701 * Return Value: 4702 * BCM_E_XXX 4703 * Notes: 4704 */ 4705 int bcm_esw_l3_egress_stat_counter_sync_get(int unit, 4706 bcm_if_t intf_id, 4707 bcm_l3_stat_t stat, 4708 uint32 num_entries, 4709 uint32 *counter_indexes, 4710 bcm_stat_value_t *counter_values) 4711 { 4712 return _bcm_esw_l3_egress_counter_get(unit, 1, intf_id, stat, 4713 num_entries, counter_indexes, 4714 counter_values); 4715 } 4716 4717 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 4718 /* 4719 * Function: 4720 * _bcm_esw_l3_egress_stat_counter_set 4721 * Description: 4722 * Set the specified counter statistic for a L3 egress interface 4723 * 4724 * Parameters: 4725 * unit - (IN) unit number 4726 * intf_id - (IN) Interface id of a egress L3 object. 4727 * stat - (IN) Type of the counter to retrieve 4728 * I.e. ingress/egress byte/packet) 4729 * num_entries - (IN) Number of counter Entries 4730 * counter_indexes - (IN) Pointer to Counter indexes entries 4731 * counter_values - (IN) Pointer to counter values 4732 * 4733 * Return Value: 4734 * BCM_E_XXX 4735 * Notes: 4736 */ 4737 STATIC 4738 bcm_error_t _bcm_esw_l3_egress_stat_counter_set( 4739 int unit, 4740 bcm_if_t intf_id, 4741 bcm_l3_stat_t stat, 4742 uint32 num_entries, 4743 uint32 *counter_indexes, 4744 bcm_stat_value_t *counter_values) 4745 { 4746 uint32 table_count=0; 4747 uint32 index_count=0; 4748 uint32 num_of_tables=0; 4749 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 4750 uint32 byte_flag=0; 4751 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4752 4753 if ((stat == bcmL3StatOutPackets) || 4754 (stat == bcmL3StatOutBytes)) { 4755 direction = bcmStatFlexDirectionEgress; 4756 } else { 4757 /* direction = bcmStatFlexDirectionIngress; */ 4758 return BCM_E_PARAM; 4759 } 4760 if (stat == bcmL3StatOutPackets) { 4761 byte_flag=0; 4762 } else { 4763 byte_flag=1; 4764 } 4765 4766 BCM_IF_ERROR_RETURN(_bcm_esw_l3_egress_stat_get_table_info( 4767 unit, intf_id,&num_of_tables,&table_info[0])); 4768 4769 for (table_count=0; table_count < num_of_tables ; table_count++) { 4770 if (table_info[table_count].direction == direction) { 4771 for (index_count=0; index_count < num_entries ; index_count++) { 4772 BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_set( 4773 unit, 4774 table_info[table_count].index, 4775 table_info[table_count].table, 4776 0, byte_flag, 4777 counter_indexes[index_count], 4778 &counter_values[index_count])); 4779 } 4780 } 4781 } 4782 return BCM_E_NONE; 4783 } 4784 #endif 4785 4786 /* 4787 * Function: 4788 * bcm_esw_l3_egress_stat_counter_set 4789 * Description: 4790 * Set the specified counter statistic for a L3 egress interface 4791 * 4792 * Parameters: 4793 * unit - (IN) unit number 4794 * intf_id - (IN) Interface id of a egress L3 object. 4795 * stat - (IN) Type of the counter to retrieve 4796 * I.e. ingress/egress byte/packet) 4797 * num_entries - (IN) Number of counter Entries 4798 * counter_indexes - (IN) Pointer to Counter indexes entries 4799 * counter_values - (IN) Pointer to counter values 4800 * 4801 * Return Value: 4802 * BCM_E_XXX 4803 * Notes: 4804 */ 4805 int bcm_esw_l3_egress_stat_counter_set( 4806 int unit, 4807 bcm_if_t intf_id, 4808 bcm_l3_stat_t stat, 4809 uint32 num_entries, 4810 uint32 *counter_indexes, 4811 bcm_stat_value_t *counter_values) 4812 { 4813 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 4814 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 4815 return _bcm_esw_l3_egress_stat_counter_set(unit,intf_id,stat, 4816 num_entries,counter_indexes,counter_values); 4817 } else 4818 #endif 4819 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 4820 if (soc_feature(unit,soc_feature_gport_service_counters)) { 4821 uint64 val; 4822 int rv = BCM_E_NONE; 4823 4824 if (!(stat == bcmL3StatOutPackets || 4825 stat == bcmL3StatOutBytes)) { 4826 return BCM_E_PARAM; 4827 } 4828 4829 if (stat == bcmL3StatOutPackets) { 4830 COMPILER_64_SET(val,0,counter_values->packets); 4831 } else { 4832 COMPILER_64_SET(val, 4833 COMPILER_64_HI(counter_values->bytes), 4834 COMPILER_64_LO(counter_values->bytes)); 4835 } 4836 rv = _bcm_esw_flex_stat_set(unit, 4837 _bcmFlexStatTypeEgressGport, 4838 intf_id, 4839 _bcm_esw_l3_stat_to_flex_stat(stat), val); 4840 4841 return rv; 4842 4843 } else 4844 #endif 4845 { 4846 return BCM_E_UNAVAIL; 4847 } 4848 } 4849 4850 /* 4851 * Function: 4852 * bcm_esw_l3_egress_stat_id_get 4853 * Description: 4854 * Get stat counter id associated with given egress interface id 4855 * 4856 * Parameters: 4857 * unit - (IN) unit number 4858 * intf_id - (IN) Interface id of a egress L3 object. 4859 * stat - (IN) Type of the counter to retrieve 4860 * I.e. ingress/egress byte/packet) 4861 * Stat_counter_id - (OUT) Stat Counter ID 4862 * 4863 * Return Value: 4864 * BCM_E_XXX 4865 * Notes: 4866 */ 4867 int bcm_esw_l3_egress_stat_id_get( 4868 int unit, 4869 bcm_if_t intf_id, 4870 bcm_l3_stat_t stat, 4871 uint32 *stat_counter_id) 4872 { 4873 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 4874 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 4875 uint32 num_of_tables=0; 4876 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4877 uint32 index=0; 4878 uint32 num_stat_counter_ids=0; 4879 4880 if ((stat == bcmL3StatInPackets) || 4881 (stat == bcmL3StatInBytes)) { 4882 direction = bcmStatFlexDirectionIngress; 4883 } else { 4884 direction = bcmStatFlexDirectionEgress; 4885 } 4886 BCM_IF_ERROR_RETURN(_bcm_esw_l3_egress_stat_get_table_info( 4887 unit,intf_id,&num_of_tables,&table_info[0])); 4888 for (index=0; index < num_of_tables ; index++) { 4889 if (table_info[index].direction == direction) 4890 return _bcm_esw_stat_flex_get_counter_id( 4891 unit, 1, &table_info[index], 4892 &num_stat_counter_ids,stat_counter_id); 4893 } 4894 return BCM_E_NOT_FOUND; 4895 #else 4896 return BCM_E_UNAVAIL; 4897 #endif 4898 } 4899 4900 4901 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 4902 /* 4903 * Function: 4904 * _bcm_esw_l3_ingress_stat_attach 4905 * Description: 4906 * Attach counters entries to the given L3 Ingress interface 4907 * 4908 * Parameters: 4909 * unit - (IN) unit number 4910 * intf_id - (IN) Interface id of a Ingress L3 object. 4911 * stat_counter_id - (IN) Stat Counter ID. 4912 * 4913 * Return Value: 4914 * BCM_E_XXX 4915 * Notes: 4916 */ 4917 STATIC 4918 bcm_error_t _bcm_esw_l3_ingress_stat_attach( 4919 int unit, 4920 bcm_if_t intf_id, 4921 uint32 stat_counter_id) 4922 { 4923 soc_mem_t table=0; 4924 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 4925 uint32 pool_number=0; 4926 uint32 base_index=0; 4927 bcm_stat_flex_mode_t offset_mode=0; 4928 bcm_stat_object_t object=bcmStatObjectIngPort; 4929 bcm_stat_group_mode_t group_mode= bcmStatGroupModeSingle; 4930 uint32 count=0; 4931 uint32 actual_num_tables=0; 4932 uint32 num_of_tables=0; 4933 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4934 4935 _bcm_esw_stat_get_counter_id_info( 4936 unit, stat_counter_id, 4937 &group_mode,&object,&offset_mode,&pool_number,&base_index); 4938 BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_object(unit,object,&direction)); 4939 BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit,group_mode)); 4940 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_table_info( 4941 unit,object,1,&actual_num_tables,&table,&direction)); 4942 4943 BCM_IF_ERROR_RETURN(_bcm_esw_l3_ingress_stat_get_table_info( 4944 unit, intf_id,&num_of_tables,&table_info[0])); 4945 for (count=0; count < num_of_tables ; count++) { 4946 if ((table_info[count].direction == direction) && 4947 (table_info[count].table == table) ) { 4948 if (direction == bcmStatFlexDirectionIngress) { 4949 return _bcm_esw_stat_flex_attach_ingress_table_counters( 4950 unit, 4951 table_info[count].table, 4952 table_info[count].index, 4953 offset_mode, 4954 base_index, 4955 pool_number); 4956 } else { 4957 return _bcm_esw_stat_flex_attach_egress_table_counters( 4958 unit, 4959 table_info[count].table, 4960 table_info[count].index, 4961 0, 4962 offset_mode, 4963 base_index, 4964 pool_number); 4965 } 4966 } 4967 } 4968 return BCM_E_NOT_FOUND; 4969 } 4970 #endif 4971 4972 /* 4973 * Function: 4974 * bcm_esw_l3_ingress_stat_attach 4975 * Description: 4976 * Attach counters entries to the given L3 Ingress interface 4977 * 4978 * Parameters: 4979 * unit - (IN) unit number 4980 * intf_id - (IN) Interface id of a Ingress L3 object. 4981 * stat_counter_id - (IN) Stat Counter ID. * 4982 * Return Value: 4983 * BCM_E_XXX 4984 * Notes: 4985 */ 4986 int bcm_esw_l3_ingress_stat_attach( 4987 int unit, 4988 bcm_if_t intf_id, 4989 uint32 stat_counter_id) 4990 { 4991 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 4992 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 4993 return _bcm_esw_l3_ingress_stat_attach(unit,intf_id,stat_counter_id); 4994 } else 4995 #endif 4996 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 4997 if (soc_feature(unit,soc_feature_gport_service_counters)) { 4998 _bcm_flex_stat_type_t fs_type; 4999 uint32 fs_inx; 5000 uint32 flag; 5001 int rv; 5002 5003 /* Input parameters check. */ 5004 if ( (intf_id < 0) || (intf_id >= BCM_XGS3_L3_ING_IF_TBL_SIZE(unit))) { 5005 return (BCM_E_PARAM); 5006 } 5007 5008 if (!SHR_BITGET(BCM_XGS3_L3_ING_IF_INUSE(unit), intf_id)) { 5009 return (BCM_E_NOT_FOUND); 5010 } 5011 5012 fs_type = _BCM_FLEX_STAT_TYPE(stat_counter_id); 5013 fs_inx = _BCM_FLEX_STAT_COUNT_INX(stat_counter_id); 5014 5015 if (!((fs_type == _bcmFlexStatTypeGport) && fs_inx)) { 5016 return BCM_E_PARAM; 5017 } 5018 5019 flag = _BCM_FLEX_STAT_HW_INGRESS; 5020 5021 rv = _bcm_esw_flex_stat_enable_set(unit, fs_type, 5022 _bcm_esw_l3_ingr_flex_stat_hw_index_set, 5023 INT_TO_PTR(flag), 5024 intf_id, TRUE,fs_inx); 5025 return rv; 5026 } else 5027 #endif 5028 { 5029 return BCM_E_UNAVAIL; 5030 } 5031 5032 } 5033 5034 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 5035 /* 5036 * Function: 5037 * _bcm_esw_l3_ingress_stat_detach 5038 * Description: 5039 * Detach counters entries to the given L3 Ingress interface. 5040 * 5041 * Parameters: 5042 * unit - (IN) unit number 5043 * intf_id - (IN) Interface id of a egress L3 object. 5044 * stat_counter_id - (IN) Stat Counter ID. 5045 * 5046 * Return Value: 5047 * BCM_E_XXX 5048 * Notes: 5049 */ 5050 STATIC 5051 bcm_error_t _bcm_esw_l3_ingress_stat_detach( 5052 int unit, 5053 bcm_if_t intf_id) 5054 { 5055 uint32 count=0; 5056 uint32 num_of_tables=0; 5057 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 5058 bcm_error_t rv = BCM_E_NONE; 5059 bcm_error_t err_code[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION] = {BCM_E_NONE}; 5060 5061 BCM_IF_ERROR_RETURN(_bcm_esw_l3_ingress_stat_get_table_info( 5062 unit, intf_id,&num_of_tables,&table_info[0])); 5063 5064 for (count=0; count < num_of_tables ; count++) { 5065 if (table_info[count].direction == bcmStatFlexDirectionIngress) { 5066 rv = _bcm_esw_stat_flex_detach_ingress_table_counters( 5067 unit, table_info[count].table, table_info[count].index); 5068 if (BCM_E_NONE != rv && 5069 BCM_E_NONE == err_code[bcmStatFlexDirectionIngress]) { 5070 err_code[bcmStatFlexDirectionIngress] = rv; 5071 } 5072 } else { 5073 rv = _bcm_esw_stat_flex_detach_egress_table_counters( 5074 unit, 0, table_info[count].table, 5075 table_info[count].index); 5076 if (BCM_E_NONE != rv && 5077 BCM_E_NONE == err_code[bcmStatFlexDirectionEgress]) { 5078 err_code[bcmStatFlexDirectionEgress] = rv; 5079 } 5080 } 5081 } 5082 5083 BCM_STAT_FLEX_DETACH_RETURN(err_code) 5084 } 5085 #endif 5086 5087 /* 5088 * Function: 5089 * bcm_esw_l3_ingress_stat_detach 5090 * Description: 5091 * Detach counters entries to the given L3 Ingress interface. 5092 * 5093 * Parameters: 5094 * unit - (IN) unit number 5095 * intf_id - (IN) Interface id of a egress L3 object. 5096 * stat_counter_id - (IN) Stat Counter ID. 5097 * 5098 * Return Value: 5099 * BCM_E_XXX 5100 * Notes: 5101 */ 5102 5103 int bcm_esw_l3_ingress_stat_detach( 5104 int unit, 5105 bcm_if_t intf_id) 5106 { 5107 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 5108 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 5109 return _bcm_esw_l3_ingress_stat_detach(unit,intf_id); 5110 } else 5111 #endif 5112 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 5113 if (soc_feature(unit,soc_feature_gport_service_counters)) { 5114 uint32 flag; 5115 int rv; 5116 5117 flag = _BCM_FLEX_STAT_HW_INGRESS; 5118 5119 rv = _bcm_esw_flex_stat_enable_set(unit, _bcmFlexStatTypeGport, 5120 _bcm_esw_l3_ingr_flex_stat_hw_index_set, 5121 INT_TO_PTR(flag), 5122 intf_id, FALSE,1); 5123 return rv; 5124 } else 5125 #endif 5126 { 5127 return BCM_E_UNAVAIL; 5128 } 5129 } 5130 5131 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 5132 /* 5133 * Function: 5134 * _bcm_esw_l3_ingress_stat_counter_get 5135 * Description: 5136 * Get the specified counter statistic for a L3 ingress interface 5137 * if sync_mode is set, sync the sw accumulated count 5138 * with hw count value first, else return sw count. 5139 * 5140 * Parameters: 5141 * unit - (IN) unit number 5142 * sync_mode - (IN) hwcount is to be synced to sw count 5143 * intf_id - (IN) Interface id of a ingress L3 object. 5144 * stat - (IN) Type of the counter to retrieve 5145 * I.e. ingress/egress byte/packet) 5146 * num_entries - (IN) Number of counter Entries 5147 * counter_indexes - (IN) Pointer to Counter indexes entries 5148 * counter_values - (OUT) Pointer to counter values 5149 * 5150 * Return Value: 5151 * BCM_E_XXX 5152 * Notes: 5153 */ 5154 STATIC 5155 bcm_error_t _bcm_esw_l3_ingress_stat_counter_get( 5156 int unit, 5157 int sync_mode, 5158 bcm_if_t intf_id, 5159 bcm_l3_stat_t stat, 5160 uint32 num_entries, 5161 uint32 *counter_indexes, 5162 bcm_stat_value_t *counter_values) 5163 { 5164 uint32 table_count=0; 5165 uint32 index_count=0; 5166 uint32 num_of_tables=0; 5167 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 5168 uint32 byte_flag=0; 5169 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 5170 5171 if ((stat == bcmL3StatInPackets) || 5172 (stat == bcmL3StatInBytes)) { 5173 direction = bcmStatFlexDirectionIngress; 5174 } else { 5175 /* direction = bcmStatFlexDirectionEgress; */ 5176 return BCM_E_PARAM; 5177 } 5178 if (stat == bcmL3StatInPackets) { 5179 byte_flag=0; 5180 } else { 5181 byte_flag=1; 5182 } 5183 5184 BCM_IF_ERROR_RETURN(_bcm_esw_l3_ingress_stat_get_table_info( 5185 unit, intf_id,&num_of_tables,&table_info[0])); 5186 5187 for (table_count=0; table_count < num_of_tables ; table_count++) { 5188 if (table_info[table_count].direction == direction) { 5189 for (index_count=0; index_count < num_entries ; index_count++) { 5190 BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_get( 5191 unit, sync_mode, 5192 table_info[table_count].index, 5193 table_info[table_count].table, 5194 0, byte_flag, 5195 counter_indexes[index_count], 5196 &counter_values[index_count])); 5197 } 5198 } 5199 } 5200 return BCM_E_NONE; 5201 } 5202 #endif 5203 5204 /* 5205 * Function: 5206 * _bcm_esw_l3_ingress_flex_stat_counter_get 5207 * Description: 5208 * Get the specified counter statistic for a L3 ingress interface 5209 * if sync_mode is set, sync the sw accumulated count 5210 * with hw count value first, else return sw count. 5211 * 5212 * Parameters: 5213 * unit - (IN) unit number 5214 * sync_mode - (IN) hwcount is to be synced to sw count 5215 * intf_id - (IN) Interface id of a ingress L3 object. 5216 * stat - (IN) Type of the counter to retrieve 5217 * I.e. ingress/egress byte/packet) 5218 * num_entries - (IN) Number of counter Entries 5219 * counter_indexes - (IN) Pointer to Counter indexes entries 5220 * counter_values - (OUT) Pointer to counter values 5221 * 5222 * Return Value: 5223 * BCM_E_XXX 5224 * Notes: 5225 */ 5226 int _bcm_esw_l3_ingress_flex_stat_counter_get( 5227 int unit, 5228 int sync_mode, 5229 bcm_if_t intf_id, 5230 bcm_l3_stat_t stat, 5231 uint32 num_entries, 5232 uint32 *counter_indexes, 5233 bcm_stat_value_t *counter_values) 5234 { 5235 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 5236 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 5237 return _bcm_esw_l3_ingress_stat_counter_get(unit, sync_mode, 5238 intf_id, stat, 5239 num_entries, 5240 counter_indexes, 5241 counter_values); 5242 } else 5243 #endif 5244 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 5245 if (soc_feature(unit,soc_feature_gport_service_counters)) { 5246 uint64 val; 5247 int rv = BCM_E_NONE; 5248 5249 if (!(stat == bcmL3StatInPackets || 5250 stat == bcmL3StatInBytes)) { 5251 return BCM_E_PARAM; 5252 } 5253 rv = _bcm_esw_flex_stat_get(unit, sync_mode, 5254 _bcmFlexStatTypeGport, 5255 intf_id, 5256 _bcm_esw_l3_stat_to_flex_stat(stat), 5257 &val); 5258 5259 if (stat == bcmL3StatInPackets) { 5260 counter_values->packets = COMPILER_64_LO(val); 5261 } else { 5262 COMPILER_64_SET(counter_values->bytes, 5263 COMPILER_64_HI(val), 5264 COMPILER_64_LO(val)); 5265 } 5266 return rv; 5267 5268 } else 5269 #endif 5270 { 5271 return BCM_E_UNAVAIL; 5272 } 5273 } 5274 5275 5276 /* 5277 * Function: 5278 * bcm_esw_l3_ingress_stat_counter_get 5279 * Description: 5280 * Get the specified counter statistic for a L3 ingress interface 5281 * 5282 * Parameters: 5283 * unit - (IN) unit number 5284 * intf_id - (IN) Interface id of a ingress L3 object. 5285 * stat - (IN) Type of the counter to retrieve 5286 * I.e. ingress/egress byte/packet) 5287 * num_entries - (IN) Number of counter Entries 5288 * counter_indexes - (IN) Pointer to Counter indexes entries 5289 * counter_values - (OUT) Pointer to counter values 5290 * 5291 * Return Value: 5292 * BCM_E_XXX 5293 * Notes: 5294 */ 5295 int bcm_esw_l3_ingress_stat_counter_get( 5296 int unit, 5297 bcm_if_t intf_id, 5298 bcm_l3_stat_t stat, 5299 uint32 num_entries, 5300 uint32 *counter_indexes, 5301 bcm_stat_value_t *counter_values) 5302 { 5303 int rv = BCM_E_UNAVAIL; 5304 5305 rv = _bcm_esw_l3_ingress_flex_stat_counter_get(unit, 0, intf_id, stat, 5306 num_entries, 5307 counter_indexes, 5308 counter_values); 5309 5310 return rv; 5311 } 5312 5313 5314 5315 /* 5316 * Function: 5317 * bcm_esw_l3_ingress_stat_counter_sync_get 5318 * Description: 5319 * Get the specified counter statisitic for a L3 ingress interface 5320 * sw accumulated counters synced with hw count. 5321 * 5322 * Parameters: 5323 * unit - (IN) unit number 5324 * intf_id - (IN) Interface id of a ingress L3 object. 5325 * stat - (IN) Type of the counter to retrieve 5326 * I.e. ingress/egress byte/packet) 5327 * num_entries - (IN) Number of counter Entries 5328 * counter_indexes - (IN) Pointer to Counter indexes entries 5329 * counter_values - (OUT) Pointer to counter values 5330 * 5331 * Return Value: 5332 * BCM_E_XXX 5333 * Notes: 5334 */ 5335 int bcm_esw_l3_ingress_stat_counter_sync_get( 5336 int unit, 5337 bcm_if_t intf_id, 5338 bcm_l3_stat_t stat, 5339 uint32 num_entries, 5340 uint32 *counter_indexes, 5341 bcm_stat_value_t *counter_values) 5342 { 5343 int rv = BCM_E_UNAVAIL; 5344 5345 rv = _bcm_esw_l3_ingress_flex_stat_counter_get(unit, 1, intf_id, stat, 5346 num_entries, 5347 counter_indexes, 5348 counter_values); 5349 5350 return rv; 5351 } 5352 5353 5354 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 5355 /* 5356 * Function: 5357 * _bcm_esw_l3_ingress_stat_counter_set 5358 * Description: 5359 * Set the specified counter statistic for a L3 ingress interface 5360 * 5361 * Parameters: 5362 * unit - (IN) unit number 5363 * intf_id - (IN) Interface id of a egress L3 object. 5364 * stat - (IN) Type of the counter to retrieve 5365 * I.e. ingress/egress byte/packet) 5366 * num_entries - (IN) Number of counter Entries 5367 * counter_indexes - (IN) Pointer to Counter indexes entries 5368 * counter_values - (IN) Pointer to counter values 5369 * 5370 * Return Value: 5371 * BCM_E_XXX 5372 * Notes: 5373 */ 5374 5375 STATIC 5376 bcm_error_t _bcm_esw_l3_ingress_stat_counter_set( 5377 int unit, 5378 bcm_if_t intf_id, 5379 bcm_l3_stat_t stat, 5380 uint32 num_entries, 5381 uint32 *counter_indexes, 5382 bcm_stat_value_t *counter_values) 5383 { 5384 uint32 table_count=0; 5385 uint32 index_count=0; 5386 uint32 num_of_tables=0; 5387 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 5388 uint32 byte_flag=0; 5389 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 5390 5391 if ((stat == bcmL3StatInPackets) || 5392 (stat == bcmL3StatInBytes)) { 5393 direction = bcmStatFlexDirectionIngress; 5394 } else { 5395 /* direction = bcmStatFlexDirectionEgress; */ 5396 return BCM_E_PARAM; 5397 } 5398 if (stat == bcmL3StatInPackets) { 5399 byte_flag=0; 5400 } else { 5401 byte_flag=1; 5402 } 5403 5404 BCM_IF_ERROR_RETURN(_bcm_esw_l3_ingress_stat_get_table_info( 5405 unit, intf_id,&num_of_tables,&table_info[0])); 5406 5407 for (table_count=0; table_count < num_of_tables ; table_count++) { 5408 if (table_info[table_count].direction == direction) { 5409 for (index_count=0; index_count < num_entries ; index_count++) { 5410 BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_set( 5411 unit, 5412 table_info[table_count].index, 5413 table_info[table_count].table, 5414 0, byte_flag, 5415 counter_indexes[index_count], 5416 &counter_values[index_count])); 5417 } 5418 } 5419 } 5420 return BCM_E_NONE; 5421 } 5422 #endif 5423 5424 #ifdef BCM_KATANA_SUPPORT 5425 /* 5426 * Function: 5427 * _bcm_kt_extended_queue_config 5428 * Description: 5429 * Set the cosq id and the profile index for subscriber port in 5430 * ING_L3_NEXT_HOP/ING_QUEUE_MAP 5431 * Parameters: 5432 * unit - (IN) unit number 5433 * options - (IN) options to create the API(REPLACE/WITH_ID..etc..). 5434 * flags - (IN) Flag to indicate EH_TAG_TYPE 5435 * queue_id - (IN) CosQ id derived from gport 5436 * profile_index - (IN) value ING_QUEUE_OFFSET_MAPPING_TABLE profile 5437 * intf - (IN) L3 interface id pointing to Egress object. 5438 * 5439 * Return Value: 5440 * BCM_E_XXX 5441 * Notes: 5442 */ 5443 5444 int _bcm_kt_extended_queue_config(int unit, uint32 options, uint32 flags, 5445 int queue_id, int profile_index, bcm_if_t *intf) 5446 { 5447 int idx = 0; 5448 ing_queue_map_entry_t ing_queue_entry; 5449 ing_l3_next_hop_entry_t in_entry; 5450 int old_queue_id = 0; 5451 int eh_tag_type = 1; /*EH_QUEUE_TAG contains actual COSQ value */ 5452 int mem = ING_L3_NEXT_HOPm; 5453 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, *intf)) { 5454 idx = *intf - BCM_XGS3_EGRESS_IDX_MIN(unit); 5455 } else { 5456 idx = *intf - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 5457 } 5458 sal_memset(&in_entry, 0, BCM_XGS3_L3_ENT_SZ(unit, nh)); 5459 /* Read ingress next hop entry. */ 5460 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, mem, idx, &in_entry)); 5461 if (flags & BCM_L3_QUEUE_MAP) { 5462 /* ING_QUEUE_MAP needs to be configured */ 5463 sal_memset(&ing_queue_entry, 0, sizeof(ing_queue_map_entry_t)); 5464 soc_mem_field32_set(unit, ING_QUEUE_MAPm, 5465 &ing_queue_entry, QUEUE_SET_BASEf, queue_id); 5466 soc_mem_field32_set(unit, ING_QUEUE_MAPm, &ing_queue_entry, 5467 QUEUE_OFFSET_PROFILE_INDEXf, profile_index); 5468 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_WRITE(unit, ING_QUEUE_MAPm, 5469 queue_id, &ing_queue_entry)); 5470 eh_tag_type = 2; /* Get BASE QUEUE from ING_QUEUE_MAP */ 5471 } 5472 if (options & BCM_L3_REPLACE) { 5473 if (SOC_MEM_FIELD_VALID(unit, mem, EH_QUEUE_TAGf)) { 5474 old_queue_id = soc_mem_field32_get(unit, mem, &in_entry, 5475 EH_QUEUE_TAGf); 5476 if ((old_queue_id > 0) && (old_queue_id != queue_id)) { 5477 /* ING_QUEUE_MAP needs to be reset for old entry */ 5478 sal_memset(&ing_queue_entry, 0, sizeof(ing_queue_map_entry_t)); 5479 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_WRITE(unit, ING_QUEUE_MAPm, 5480 old_queue_id, &ing_queue_entry)); 5481 } 5482 } 5483 if (queue_id == 0) { 5484 eh_tag_type = 0; /* No HQOS */ 5485 } 5486 } 5487 if (SOC_MEM_FIELD_VALID(unit, mem, EH_TAG_TYPEf)) { 5488 soc_mem_field32_set(unit, mem, &in_entry, EH_TAG_TYPEf, 5489 eh_tag_type & 0x3); 5490 } 5491 if (SOC_MEM_FIELD_VALID(unit, mem, EH_QUEUE_TAGf)) { 5492 soc_mem_field32_set(unit, mem, &in_entry, EH_QUEUE_TAGf, queue_id); 5493 } 5494 /* Write ingress next hop entry. */ 5495 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_WRITE(unit, mem, idx, &in_entry)); 5496 return BCM_E_NONE; 5497 } 5498 /* 5499 * Function: 5500 * _bcm_kt_extended_queue_qos_profile_get 5501 * Description: 5502 * Get qos profile index for subscriber port. 5503 * Parameters: 5504 * unit - (IN) unit number 5505 * intf - (IN) L3 interface id pointing to Egress object. 5506 * profile_index - (OUT) QoS profile index for a given subscriber port. 5507 * Return Value: 5508 * BCM_E_XXX 5509 * Notes: 5510 */ 5511 5512 int _bcm_kt_extended_queue_qos_profile_get(int unit, 5513 bcm_if_t intf, 5514 int *profile_index) 5515 { 5516 int idx = 0, pid = -1, queue_id = 0; 5517 ing_queue_map_entry_t ing_queue_entry; 5518 ing_l3_next_hop_entry_t in_entry; 5519 int eh_tag_type = 0; 5520 int mem = ING_L3_NEXT_HOPm; 5521 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, intf)) { 5522 idx = intf - BCM_XGS3_EGRESS_IDX_MIN(unit); 5523 } else { 5524 idx = intf - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 5525 } 5526 sal_memset(&in_entry, 0, BCM_XGS3_L3_ENT_SZ(unit, nh)); 5527 /* Read ingress next hop entry. */ 5528 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, mem, idx, &in_entry)); 5529 if (SOC_MEM_FIELD_VALID(unit, mem, EH_TAG_TYPEf)) { 5530 eh_tag_type = soc_mem_field32_get(unit, mem, &in_entry, EH_TAG_TYPEf); 5531 } 5532 if ((eh_tag_type == 2) && SOC_MEM_FIELD_VALID(unit, mem, EH_QUEUE_TAGf)) { 5533 queue_id = soc_mem_field32_get(unit, mem, &in_entry, EH_QUEUE_TAGf); 5534 } 5535 5536 if (queue_id) { 5537 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, ING_QUEUE_MAPm, 5538 queue_id, &ing_queue_entry)); 5539 pid = soc_mem_field32_get(unit, ING_QUEUE_MAPm, &ing_queue_entry, 5540 QUEUE_OFFSET_PROFILE_INDEXf); 5541 } 5542 *profile_index = pid; 5543 return BCM_E_NONE; 5544 } 5545 #endif /* BCM_KATANA_SUPPORT */ 5546 5547 /* 5548 * Function: 5549 * bcm_esw_l3_ingress_stat_counter_set 5550 * Description: 5551 * Set the specified counter statistic for a L3 ingress interface 5552 * 5553 * Parameters: 5554 * unit - (IN) unit number 5555 * intf_id - (IN) Interface id of a egress L3 object. 5556 * stat - (IN) Type of the counter to retrieve 5557 * I.e. ingress/egress byte/packet) 5558 * num_entries - (IN) Number of counter Entries 5559 * counter_indexes - (IN) Pointer to Counter indexes entries 5560 * counter_values - (IN) Pointer to counter values 5561 * 5562 * Return Value: 5563 * BCM_E_XXX 5564 * Notes: 5565 */ 5566 5567 int bcm_esw_l3_ingress_stat_counter_set( 5568 int unit, 5569 bcm_if_t intf_id, 5570 bcm_l3_stat_t stat, 5571 uint32 num_entries, 5572 uint32 *counter_indexes, 5573 bcm_stat_value_t *counter_values) 5574 { 5575 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 5576 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 5577 return _bcm_esw_l3_ingress_stat_counter_set(unit,intf_id,stat, 5578 num_entries,counter_indexes,counter_values); 5579 } else 5580 #endif 5581 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 5582 if (soc_feature(unit,soc_feature_gport_service_counters)) { 5583 uint64 val; 5584 int rv = BCM_E_NONE; 5585 5586 if (!(stat == bcmL3StatInPackets || 5587 stat == bcmL3StatInBytes)) { 5588 return BCM_E_PARAM; 5589 } 5590 5591 if (stat == bcmL3StatInPackets) { 5592 COMPILER_64_SET(val,0,counter_values->packets); 5593 } else { 5594 COMPILER_64_SET(val, 5595 COMPILER_64_HI(counter_values->bytes), 5596 COMPILER_64_LO(counter_values->bytes)); 5597 } 5598 rv = _bcm_esw_flex_stat_set(unit, 5599 _bcmFlexStatTypeGport, 5600 intf_id, 5601 _bcm_esw_l3_stat_to_flex_stat(stat), val); 5602 return rv; 5603 } else 5604 #endif 5605 { 5606 return BCM_E_UNAVAIL; 5607 } 5608 } 5609 5610 /* 5611 * Function: 5612 * bcm_esw_l3_egress_stat_id_get 5613 * Description: 5614 * Get stat counter id associated with given ingress interface id 5615 * 5616 * Parameters: 5617 * unit - (IN) unit number 5618 * intf_id - (IN) Interface id of a ingress L3 object. 5619 * stat - (IN) Type of the counter to retrieve 5620 * I.e. ingress/egress byte/packet) 5621 * Stat_counter_id - (OUT) Stat Counter ID 5622 * 5623 * Return Value: 5624 * BCM_E_XXX 5625 * Notes: 5626 */ 5627 int bcm_esw_l3_ingress_stat_id_get( 5628 int unit, 5629 bcm_if_t intf_id, 5630 bcm_l3_stat_t stat, 5631 uint32 *stat_counter_id) 5632 { 5633 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 5634 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 5635 uint32 num_of_tables=0; 5636 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 5637 uint32 index=0; 5638 uint32 num_stat_counter_ids=0; 5639 5640 if ((stat == bcmL3StatInPackets) || 5641 (stat == bcmL3StatInBytes)) { 5642 direction = bcmStatFlexDirectionIngress; 5643 } else { 5644 direction = bcmStatFlexDirectionEgress; 5645 } 5646 BCM_IF_ERROR_RETURN(_bcm_esw_l3_ingress_stat_get_table_info( 5647 unit,intf_id,&num_of_tables,&table_info[0])); 5648 for (index=0; index < num_of_tables ; index++) { 5649 if (table_info[index].direction == direction) 5650 return _bcm_esw_stat_flex_get_counter_id( 5651 unit, 1, &table_info[index], 5652 &num_stat_counter_ids,stat_counter_id); 5653 } 5654 return BCM_E_NOT_FOUND; 5655 #else 5656 return BCM_E_UNAVAIL; 5657 #endif 5658 } 5659 5660 5661 5662 5663 /* 5664 * Function: 5665 * bcm_esw_l3_egress_create 5666 * Purpose: 5667 * Create an Egress forwarding object. 5668 * Parameters: 5669 * unit - (IN) bcm device. 5670 * flags - (IN) BCM_L3_REPLACE: replace existing. 5671 * BCM_L3_WITH_ID: intf argument is given. 5672 * egr - (IN) Egress forwarding destination. 5673 * intf - (OUT) L3 interface id pointing to Egress object. 5674 * This is an IN argument if either BCM_L3_REPLACE 5675 * or BCM_L3_WITH_ID are given in flags. 5676 * Returns: 5677 * BCM_E_XXX 5678 */ 5679 int 5680 bcm_esw_l3_egress_create(int unit, uint32 flags, bcm_l3_egress_t *egr, 5681 bcm_if_t *intf) 5682 { 5683 int rv = BCM_E_UNAVAIL; 5684 #ifdef BCM_KATANA_SUPPORT 5685 int extended_queue_id = 0; 5686 #endif 5687 #if defined(BCM_XGS3_SWITCH_SUPPORT) 5688 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 5689 bcm_l3_egress_t egr_local; 5690 int vp_routing = FALSE; 5691 5692 /* Input parameters check. */ 5693 if ((NULL == egr) || (NULL == intf)) { 5694 return (BCM_E_PARAM); 5695 } 5696 5697 /* Copy provided structure to local so it can be modified. */ 5698 sal_memcpy(&egr_local, egr, sizeof(bcm_l3_egress_t)); 5699 5700 if (egr_local.vlan >= BCM_VLAN_INVALID) { 5701 return (BCM_E_PARAM); 5702 } 5703 5704 /* The MEPID field is of 13 bits. So max value is 5705 * 8191. 5706 */ 5707 if (egr_local.oam_global_context_id >= 8192) { 5708 return (BCM_E_PARAM); 5709 } 5710 5711 #ifdef BCM_KATANA_SUPPORT 5712 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(egr_local.port)) || 5713 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(egr_local.port)) || 5714 (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(egr_local.port))) { 5715 if ((((egr_local.qos_map_id >> _BCM_QOS_MAP_SHIFT) != 5716 _BCM_QOS_MAP_TYPE_ING_QUEUE_OFFSET_MAP_TABLE)) || 5717 ((egr_local.qos_map_id & _BCM_QOS_MAP_TYPE_MASK) > 5718 _BCM_QOS_MAP_ING_QUEUE_OFFSET_MAX)) { 5719 return (BCM_E_PARAM); 5720 } 5721 } 5722 #endif 5723 if (BCM_GPORT_IS_BLACK_HOLE(egr_local.port)) { 5724 return BCM_E_PARAM; 5725 } else if (BCM_GPORT_IS_SET(egr_local.port)) { 5726 if (BCM_GPORT_IS_NIV_PORT(egr_local.port) || 5727 BCM_GPORT_IS_EXTENDER_PORT(egr_local.port) || 5728 BCM_GPORT_IS_VLAN_PORT(egr_local.port) || 5729 (!soc_feature(unit, soc_feature_riot) && 5730 BCM_GPORT_IS_MPLS_PORT(egr_local.port)) 5731 ) { 5732 #ifdef BCM_TRIDENT2_SUPPORT 5733 if (soc_feature(unit, soc_feature_virtual_port_routing)) { 5734 vp_routing = TRUE; 5735 } else 5736 #endif /* BCM_TRIDENT2_SUPPORT */ 5737 { 5738 return BCM_E_UNAVAIL; 5739 } 5740 } 5741 if (BCM_GPORT_IS_WLAN_PORT(egr_local.port) || (vp_routing)) { 5742 /* Resolve the gport and store the VP in egr->encap_id */ 5743 BCM_IF_ERROR_RETURN( 5744 _bcm_esw_gport_resolve(unit, egr_local.port, 5745 &(egr_local.module), 5746 &(egr_local.port), 5747 &(egr_local.trunk), 5748 &(egr_local.encap_id))); 5749 if (-1 != egr_local.trunk) { 5750 egr_local.flags |= BCM_L3_TGID; 5751 } 5752 } else { 5753 /* vxlan port is used to associate with underlay NH */ 5754 if (!(egr_local.flags2 & BCM_L3_FLAGS2_UNDERLAY)) { 5755 BCM_IF_ERROR_RETURN( 5756 _bcm_esw_l3_gport_resolve(unit, egr_local.port, 5757 &(egr_local.port), 5758 &(egr_local.module), 5759 &(egr_local.trunk), 5760 &(egr_local.flags))); 5761 } 5762 5763 } 5764 } else { 5765 PORT_DUALMODID_VALID(unit, egr_local.port); 5766 } 5767 5768 if((egr_local.flags & BCM_L3_IPMC) && 5769 !BCM_MAC_IS_ZERO(egr_local.mac_addr)) { 5770 if (!soc_feature(unit, soc_feature_ipmc_use_configured_dest_mac)) { 5771 return BCM_E_CONFIG; 5772 } 5773 } 5774 5775 L3_LOCK(unit); 5776 if (soc_feature(unit, soc_feature_mpls)) { 5777 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT) 5778 rv = bcm_tr_mpls_lock(unit); 5779 if ((rv != BCM_E_INIT) && BCM_FAILURE(rv)) { 5780 L3_UNLOCK(unit); 5781 return rv; 5782 } 5783 #endif /* BCM_TRIUMPH_SUPPORT && BCM_MPLS_SUPPORT */ 5784 } 5785 #ifdef BCM_KATANA_SUPPORT 5786 if (soc_feature(unit, soc_feature_extended_queueing)) { 5787 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(egr->port)) || 5788 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(egr->port)) || 5789 (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(egr->port))) { 5790 extended_queue_id = egr_local.trunk; 5791 egr_local.trunk = 0; 5792 } 5793 } 5794 #endif 5795 rv = bcm_xgs3_l3_egress_create(unit, flags, &egr_local, intf); 5796 if (soc_feature(unit, soc_feature_mpls)) { 5797 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT) 5798 bcm_tr_mpls_unlock(unit); 5799 #endif /* BCM_TRIUMPH_SUPPORT && BCM_MPLS_SUPPORT */ 5800 } 5801 #ifdef BCM_KATANA_SUPPORT 5802 if (BCM_SUCCESS(rv)) { 5803 if (soc_feature(unit, soc_feature_extended_queueing)) { 5804 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(egr->port)) || 5805 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(egr->port)) || 5806 (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(egr->port))) { 5807 rv = _bcm_kt_extended_queue_config(unit, flags, egr_local.flags, 5808 extended_queue_id, 5809 (egr_local.qos_map_id & _BCM_QOS_MAP_TYPE_MASK), intf); 5810 } else { 5811 /* Reset extended queue configuration, if any */ 5812 if (flags & BCM_L3_REPLACE) { 5813 rv = _bcm_kt_extended_queue_config(unit, flags, egr_local.flags, 5814 0, 0, intf); 5815 } 5816 } 5817 } 5818 } 5819 #endif 5820 L3_UNLOCK(unit); 5821 } 5822 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 5823 return (rv); 5824 } 5825 5826 /* 5827 * Function: 5828 * bcm_esw_l3_egress_destroy 5829 * Purpose: 5830 * Destroy an Egress forwarding object. 5831 * Parameters: 5832 * unit - (IN) bcm device. 5833 * intf - (IN) L3 interface id pointing to Egress object. 5834 * Returns: 5835 * BCM_E_XXX 5836 */ 5837 int 5838 bcm_esw_l3_egress_destroy(int unit, bcm_if_t intf) 5839 { 5840 int rv = BCM_E_UNAVAIL; 5841 #if defined(BCM_XGS3_SWITCH_SUPPORT) 5842 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 5843 L3_LOCK(unit); 5844 if (soc_feature(unit, soc_feature_mpls)) { 5845 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT) 5846 rv = bcm_tr_mpls_lock(unit); 5847 if ((rv != BCM_E_INIT) && BCM_FAILURE(rv)) { 5848 L3_UNLOCK(unit); 5849 return rv; 5850 } 5851 #endif /* BCM_TRIUMPH_SUPPORT && BCM_MPLS_SUPPORT */ 5852 } 5853 rv = bcm_xgs3_l3_egress_destroy(unit, intf); 5854 if (soc_feature(unit, soc_feature_mpls)) { 5855 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT) 5856 bcm_tr_mpls_unlock(unit); 5857 #endif /* BCM_TRIUMPH_SUPPORT && BCM_MPLS_SUPPORT */ 5858 } 5859 L3_UNLOCK(unit); 5860 } 5861 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 5862 return rv; 5863 } 5864 5865 /* 5866 * Function: 5867 * bcm_esw_l3_egress_get 5868 * Purpose: 5869 * Get an Egress forwarding object. 5870 * Parameters: 5871 * unit - (IN) bcm device. 5872 * intf - (IN) L3 interface id pointing to Egress object. 5873 * egr - (OUT) Egress forwarding destination. 5874 * Returns: 5875 * BCM_E_XXX 5876 */ 5877 int 5878 bcm_esw_l3_egress_get (int unit, bcm_if_t intf, bcm_l3_egress_t *egr) 5879 { 5880 int rv = BCM_E_UNAVAIL; 5881 #if defined(BCM_XGS3_SWITCH_SUPPORT) 5882 5883 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 5884 L3_LOCK(unit); 5885 rv = bcm_xgs3_l3_egress_get (unit, intf, egr); 5886 L3_UNLOCK(unit); 5887 if (BCM_FAILURE(rv)) { 5888 return rv; 5889 } 5890 5891 #ifdef BCM_TRX_SUPPORT 5892 if (egr->encap_id > 0 && egr->encap_id < BCM_XGS3_EGRESS_IDX_MIN(unit)) { 5893 /* encap_id contains a virtual port value */ 5894 int vp; 5895 vp = egr->encap_id; 5896 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) { 5897 BCM_GPORT_NIV_PORT_ID_SET(egr->port, vp); 5898 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 5899 BCM_GPORT_EXTENDER_PORT_ID_SET(egr->port, vp); 5900 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 5901 BCM_GPORT_VLAN_PORT_ID_SET(egr->port, vp); 5902 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeWlan)) { 5903 BCM_GPORT_WLAN_PORT_ID_SET(egr->port, vp); 5904 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)){ 5905 BCM_GPORT_MPLS_PORT_ID_SET(egr->port, vp); 5906 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) { 5907 BCM_GPORT_VXLAN_PORT_ID_SET(egr->encap_id, vp); 5908 if (egr->flags2 & BCM_L3_FLAGS2_UNDERLAY) { 5909 egr->port = egr->encap_id; 5910 } 5911 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) { 5912 BCM_GPORT_FLOW_PORT_ID_SET(egr->encap_id, vp); 5913 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 5914 BCM_GPORT_L2GRE_PORT_ID_SET(egr->encap_id, vp); 5915 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) { 5916 BCM_GPORT_TRILL_PORT_ID_SET(egr->encap_id, vp); 5917 } else { 5918 return BCM_E_INTERNAL; 5919 } 5920 if (egr->encap_id == vp) { 5921 egr->module = 0; 5922 egr->trunk = 0; 5923 egr->flags &= ~BCM_L3_TGID; 5924 egr->encap_id = 0; 5925 } 5926 } else if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, egr->encap_id)) { 5927 /* encap_id contains a L2 egress object ID */ 5928 egr->port = 0; 5929 egr->module = 0; 5930 egr->trunk = 0; 5931 egr->flags &= ~BCM_L3_TGID; 5932 } else 5933 #endif /* BCM_TRX_SUPPORT */ 5934 #ifdef BCM_RIOT_SUPPORT 5935 if ((BCMI_RIOT_IS_ENABLED(unit)) && 5936 _bcm_vp_is_vfi_type(unit, egr->port) ) { 5937 /* we should not do anything here. return the virtual port.*/ 5938 return BCM_E_NONE; 5939 5940 } else 5941 #endif 5942 { 5943 rv = _bcm_esw_l3_gport_construct(unit, egr->port, egr->module, 5944 egr->trunk, egr->flags, &(egr->port)); 5945 if ((intf - BCM_XGS3_EGRESS_IDX_MIN(unit)) == BCM_XGS3_L3_BLACK_HOLE_NH_IDX(unit)) { 5946 egr->port = BCM_GPORT_BLACK_HOLE; 5947 } 5948 } 5949 } 5950 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 5951 return rv; 5952 } 5953 5954 /* 5955 * Function: 5956 * bcm_esw_l3_egress_find 5957 * Purpose: 5958 * Find an egress forwarding object. 5959 * Parameters: 5960 * unit - (IN) bcm device. 5961 * egr - (IN) Egress object properties to match. 5962 * intf - (OUT) L3 interface id pointing to egress object 5963 * if found. 5964 * Returns: 5965 * BCM_E_XXX 5966 */ 5967 int 5968 bcm_esw_l3_egress_find(int unit, bcm_l3_egress_t *egr, 5969 bcm_if_t *intf) 5970 { 5971 int rv = BCM_E_UNAVAIL; 5972 #if defined(BCM_XGS3_SWITCH_SUPPORT) 5973 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 5974 bcm_l3_egress_t egr_local; 5975 int vp_routing = FALSE; 5976 5977 /* Input parameters check. */ 5978 if ((NULL == egr) || (NULL == intf)) { 5979 return (BCM_E_PARAM); 5980 } 5981 5982 /* Copy provided structure to local so it can be modified. */ 5983 sal_memcpy(&egr_local, egr, sizeof(bcm_l3_egress_t)); 5984 5985 if (BCM_GPORT_IS_SET(egr_local.port)) { 5986 #ifdef BCM_TRIDENT2_SUPPORT 5987 if (soc_feature(unit, soc_feature_virtual_port_routing) && 5988 (BCM_GPORT_IS_NIV_PORT(egr_local.port) || 5989 BCM_GPORT_IS_EXTENDER_PORT(egr_local.port) || 5990 BCM_GPORT_IS_VLAN_PORT(egr_local.port) 5991 #ifndef BCM_RIOT_SUPPORT 5992 ||(!soc_feature(unit, soc_feature_riot) && 5993 BCM_GPORT_IS_MPLS_PORT(egr_local.port)) 5994 #endif 5995 )) { 5996 vp_routing = TRUE; 5997 } 5998 #endif 5999 if (BCM_GPORT_IS_WLAN_PORT(egr_local.port) || (vp_routing)) { 6000 /* Resolve the WLAN gport and store the VP in egr->encap_id */ 6001 rv = _bcm_esw_gport_resolve(unit, egr_local.port, 6002 &(egr_local.module), 6003 &(egr_local.port), 6004 &(egr_local.trunk), 6005 &(egr_local.encap_id)); 6006 if (-1 != egr_local.trunk) { 6007 egr_local.flags |= BCM_L3_TGID; 6008 } 6009 } else { 6010 rv = _bcm_esw_l3_gport_resolve(unit, egr_local.port, 6011 &(egr_local.port), 6012 &(egr_local.module), 6013 &(egr_local.trunk), 6014 &(egr_local.flags)); 6015 } 6016 BCM_IF_ERROR_RETURN(rv); 6017 } else { 6018 PORT_DUALMODID_VALID(unit, egr_local.port); 6019 } 6020 L3_LOCK(unit); 6021 rv = bcm_xgs3_l3_egress_find(unit, &egr_local, intf); 6022 L3_UNLOCK(unit); 6023 } 6024 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6025 return (rv); 6026 } 6027 6028 /* 6029 * Function: 6030 * bcm_esw_l3_egress_traverse 6031 * Purpose: 6032 * Goes through egress objects table and runs the user callback 6033 * function at each valid egress objects entry passing back the 6034 * information for that object. 6035 * Parameters: 6036 * unit - (IN) bcm device. 6037 * trav_fn - (IN) Callback function. 6038 * user_data - (IN) User data to be passed to callback function. 6039 * Returns: 6040 * BCM_E_XXX 6041 */ 6042 int 6043 bcm_esw_l3_egress_traverse(int unit, 6044 bcm_l3_egress_traverse_cb trav_fn, void *user_data) 6045 { 6046 int rv = BCM_E_UNAVAIL; 6047 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6048 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 6049 L3_LOCK(unit); 6050 rv = bcm_xgs3_l3_egress_traverse(unit, trav_fn, user_data); 6051 L3_UNLOCK(unit); 6052 } 6053 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6054 return rv; 6055 } 6056 6057 /* 6058 * Function: 6059 * bcm_esw_l3_egress_multipath_max_create 6060 * Purpose: 6061 * Create an Egress Multipath forwarding object with specified path-width 6062 * Parameters: 6063 * unit - (IN) bcm device. 6064 * flags - (IN) BCM_L3_REPLACE: replace existing. 6065 * BCM_L3_WITH_ID: intf argument is given. 6066 * max_paths - (IN) configurable path-width 6067 * intf_count - (IN) Number of elements in intf_array. 6068 * intf_array - (IN) Array of Egress forwarding objects. 6069 * mpintf - (OUT) L3 interface id pointing to Egress multipath object. 6070 * This is an IN argument if either BCM_L3_REPLACE 6071 * or BCM_L3_WITH_ID are given in flags. 6072 * Returns: 6073 * BCM_E_XXX 6074 */ 6075 int 6076 bcm_esw_l3_egress_multipath_max_create(int unit, uint32 flags, int max_paths, 6077 int intf_count, bcm_if_t *intf_array, bcm_if_t *mpintf) 6078 { 6079 int rv = BCM_E_UNAVAIL; 6080 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6081 if (SOC_IS_TRX(unit) && soc_feature(unit, soc_feature_l3)) { 6082 L3_LOCK(unit); 6083 rv = bcm_xgs3_l3_egress_multipath_max_create(unit, flags, 0, max_paths, intf_count, 6084 intf_array, mpintf, intf_count, NULL); 6085 L3_UNLOCK(unit); 6086 } 6087 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6088 return rv; 6089 } 6090 6091 /* 6092 * Function: 6093 * bcm_esw_l3_egress_multipath_create 6094 * Purpose: 6095 * Create an Egress Multipath forwarding object. 6096 * Parameters: 6097 * unit - (IN) bcm device. 6098 * flags - (IN) BCM_L3_REPLACE: replace existing. 6099 * BCM_L3_WITH_ID: intf argument is given. 6100 * intf_count - (IN) Number of elements in intf_array. 6101 * intf_array - (IN) Array of Egress forwarding objects. 6102 * mpintf - (OUT) L3 interface id pointing to Egress multipath object. 6103 * This is an IN argument if either BCM_L3_REPLACE 6104 * or BCM_L3_WITH_ID are given in flags. 6105 * Returns: 6106 * BCM_E_XXX 6107 */ 6108 int 6109 bcm_esw_l3_egress_multipath_create(int unit, uint32 flags, int intf_count, 6110 bcm_if_t *intf_array, bcm_if_t *mpintf) 6111 { 6112 int rv = BCM_E_UNAVAIL; 6113 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6114 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 6115 L3_LOCK(unit); 6116 rv = bcm_xgs3_l3_egress_multipath_create(unit, flags, 0, intf_count, 6117 intf_array, mpintf, intf_count, 6118 NULL); 6119 L3_UNLOCK(unit); 6120 } 6121 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6122 return rv; 6123 } 6124 6125 /* 6126 * Function: 6127 * bcm_esw_l3_egress_multipath_destroy 6128 * Purpose: 6129 * Destroy an Egress Multipath forwarding object. 6130 * Parameters: 6131 * unit - (IN) bcm device. 6132 * mpintf - (IN) L3 interface id pointing to Egress multipath object. 6133 * Returns: 6134 * BCM_E_XXX 6135 */ 6136 int 6137 bcm_esw_l3_egress_multipath_destroy(int unit, bcm_if_t mpintf) 6138 { 6139 int rv = BCM_E_UNAVAIL; 6140 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6141 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 6142 L3_LOCK(unit); 6143 6144 rv = bcm_xgs3_l3_egress_multipath_destroy(unit, mpintf); 6145 6146 L3_UNLOCK(unit); 6147 } 6148 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6149 return rv; 6150 } 6151 6152 /* 6153 * Function: 6154 * bcm_esw_l3_egress_multipath_get 6155 * Purpose: 6156 * Get an Egress Multipath forwarding object. 6157 * Parameters: 6158 * unit - (IN) bcm device. 6159 * mpintf - (IN) L3 interface id pointing to Egress multipath object. 6160 * intf_size - (IN) Size of allocated entries in intf_array. 6161 * intf_array - (OUT) Array of Egress forwarding objects. 6162 * intf_count - (OUT) Number of entries of intf_count actually filled in. 6163 * This will be a value less than or equal to the value. 6164 * passed in as intf_size unless intf_size is 0. If 6165 * intf_size is 0 then intf_array is ignored and 6166 * intf_count is filled in with the number of entries 6167 * that would have been filled into intf_array if 6168 * intf_size was arbitrarily large. 6169 * Returns: 6170 * BCM_E_XXX 6171 */ 6172 int 6173 bcm_esw_l3_egress_multipath_get(int unit, bcm_if_t mpintf, int intf_size, 6174 bcm_if_t *intf_array, int *intf_count) 6175 { 6176 int rv = BCM_E_UNAVAIL; 6177 6178 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6179 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 6180 6181 L3_LOCK(unit); 6182 6183 #ifdef BCM_TOMAHAWK_SUPPORT 6184 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, mpintf)) { 6185 L3_UNLOCK(unit); 6186 return (BCM_E_PARAM); 6187 } else if (soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized) && 6188 bcm_opt_ecmp_group_is_rh(unit, mpintf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit))) { 6189 rv = bcm_opt_ecmp_rh_multipath_get(unit, mpintf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit), 6190 intf_size, 6191 intf_array, 6192 intf_count, 6193 NULL); 6194 } else 6195 #endif 6196 { 6197 rv = bcm_xgs3_l3_egress_multipath_get(unit, mpintf, intf_size, 6198 intf_array, intf_count); 6199 } 6200 6201 L3_UNLOCK(unit); 6202 6203 } 6204 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6205 return rv; 6206 } 6207 6208 /* 6209 * Function: 6210 * bcm_esw_l3_egress_multipath_add 6211 * Purpose: 6212 * Add an Egress forwarding object to an Egress Multipath 6213 * forwarding object. 6214 * Parameters: 6215 * unit - (IN) bcm device. 6216 * mpintf - (IN) L3 interface id pointing to Egress multipath object. 6217 * intf - (IN) L3 interface id pointing to Egress forwarding object. 6218 * Returns: 6219 * BCM_E_XXX 6220 */ 6221 int 6222 bcm_esw_l3_egress_multipath_add(int unit, bcm_if_t mpintf, bcm_if_t intf) 6223 { 6224 int rv = BCM_E_UNAVAIL; 6225 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6226 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 6227 L3_LOCK(unit); 6228 rv = bcm_xgs3_l3_egress_multipath_add(unit, mpintf, intf); 6229 L3_UNLOCK(unit); 6230 } 6231 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6232 return (rv); 6233 } 6234 6235 /* 6236 * Function: 6237 * bcm_esw_l3_egress_multipath_delete 6238 * Purpose: 6239 * Delete an Egress forwarding object to an Egress Multipath 6240 * forwarding object. 6241 * Parameters: 6242 * unit - (IN) bcm device. 6243 * mpintf - (IN) L3 interface id pointing to Egress multipath object 6244 * intf - (IN) L3 interface id pointing to Egress forwarding object 6245 * Returns: 6246 * BCM_E_XXX 6247 */ 6248 int 6249 bcm_esw_l3_egress_multipath_delete(int unit, bcm_if_t mpintf, bcm_if_t intf) 6250 { 6251 int rv = BCM_E_UNAVAIL; 6252 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6253 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 6254 L3_LOCK(unit); 6255 rv = bcm_xgs3_l3_egress_multipath_delete(unit, mpintf, intf); 6256 L3_UNLOCK(unit); 6257 } 6258 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6259 return rv; 6260 } 6261 6262 /* 6263 * Function: 6264 * bcm_esw_l3_egress_multipath_find 6265 * Purpose: 6266 * Find an egress multipath forwarding object. 6267 * Parameters: 6268 * unit - (IN) bcm device. 6269 * intf_count - (IN) Number of elements in intf_array. 6270 * intf_array - (IN) Array of egress forwarding objects. 6271 * intf - (OUT) L3 interface id pointing to egress multipath object 6272 * if found. 6273 * Returns: 6274 * BCM_E_XXX 6275 */ 6276 int 6277 bcm_esw_l3_egress_multipath_find(int unit, int intf_count, bcm_if_t 6278 *intf_array, bcm_if_t *mpintf) 6279 { 6280 int rv = BCM_E_UNAVAIL; 6281 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6282 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 6283 L3_LOCK(unit); 6284 rv = bcm_xgs3_l3_egress_multipath_find(unit, intf_count, 6285 intf_array, mpintf); 6286 L3_UNLOCK(unit); 6287 } 6288 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6289 return rv; 6290 } 6291 6292 /* 6293 * Function: 6294 * bcm_esw_l3_egress_multipath_traverse 6295 * Purpose: 6296 * Goes through multipath egress objects table and runs the user callback 6297 * function at each multipath egress objects entry passing back the 6298 * information for that multipath object. 6299 * Parameters: 6300 * unit - (IN) bcm device. 6301 * trav_fn - (IN) Callback function. 6302 * user_data - (IN) User data to be passed to callback function. 6303 * Returns: 6304 * BCM_E_XXX 6305 */ 6306 int 6307 bcm_esw_l3_egress_multipath_traverse(int unit, 6308 bcm_l3_egress_multipath_traverse_cb trav_fn, 6309 void *user_data) 6310 { 6311 int rv = BCM_E_UNAVAIL; 6312 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6313 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 6314 L3_LOCK(unit); 6315 rv = bcm_xgs3_l3_egress_multipath_traverse(unit, trav_fn, user_data); 6316 L3_UNLOCK(unit); 6317 } 6318 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6319 return rv; 6320 } 6321 6322 /* 6323 * Function: 6324 * _bcm_esw_l3_egress_ecmp_get 6325 * Purpose: 6326 * Get an Egress ECMP forwarding object with members from the ECMP table 6327 * Parameters: 6328 * unit - (IN) bcm device. 6329 * ecmp - (INOUT) ECMP group info. 6330 * intf_size - (IN) Size of allocated entries in intf_array. 6331 * intf_array - (OUT) Array of Egress forwarding objects. 6332 * intf_count - (OUT) Number of entries of intf_count actually filled in. 6333 * This will be a value less than or equal to the value. 6334 * passed in as intf_size unless intf_size is 0. If 6335 * intf_size is 0 then intf_array is ignored and 6336 * intf_count is filled in with the number of entries 6337 * that would have been filled into intf_array if 6338 * intf_size was arbitrarily large. 6339 * Returns: 6340 * BCM_E_XXX 6341 */ 6342 int 6343 _bcm_esw_l3_egress_ecmp_get(int unit, bcm_l3_egress_ecmp_t *ecmp, int intf_size, 6344 bcm_if_t *intf_array, int *intf_count, int rh_retrieve) 6345 { 6346 int rv = BCM_E_UNAVAIL; 6347 int grp_idx = 0; 6348 #ifdef BCM_TOMAHAWK_SUPPORT 6349 int lb_mode = 0; 6350 #endif 6351 6352 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 6353 L3_LOCK(unit); 6354 rv = bcm_xgs3_l3_egress_multipath_get(unit, ecmp->ecmp_intf, intf_size, 6355 intf_array, intf_count); 6356 if (BCM_FAILURE(rv)) { 6357 L3_UNLOCK(unit); 6358 return rv; 6359 } 6360 6361 ecmp->flags = 0; 6362 rv = bcm_xgs3_l3_egress_ecmp_max_paths_get(unit, ecmp->ecmp_intf, 6363 &ecmp->max_paths, NULL); 6364 if (BCM_FAILURE(rv)) { 6365 L3_UNLOCK(unit); 6366 return rv; 6367 } 6368 6369 /* Get ecmp group index. */ 6370 grp_idx = ecmp->ecmp_intf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 6371 if (BCM_XGS3_L3_ECMP_GROUP_FLAGS_ISSET(unit, grp_idx, 6372 BCM_L3_ECMP_PATH_NO_SORTING)) { 6373 ecmp->ecmp_group_flags = BCM_L3_ECMP_PATH_NO_SORTING; 6374 } else { 6375 ecmp->ecmp_group_flags = 0; 6376 } 6377 ecmp->dynamic_mode = 0; 6378 ecmp->dynamic_size = 0; 6379 ecmp->dynamic_age = 0; 6380 ecmp->dynamic_load_exponent = 0; 6381 ecmp->dynamic_expected_load_exponent = 0; 6382 ecmp->dgm.threshold = 0; 6383 ecmp->dgm.cost = 0; 6384 ecmp->dgm.bias = 0; 6385 6386 #if defined(BCM_RIOT_SUPPORT) || defined(BCM_MULTI_LEVEL_ECMP_SUPPORT) 6387 /* 6388 * we can look into the ecmp_grp index to know if this 6389 * is overlay entry or underlay entry. 6390 */ 6391 if (BCMI_L3_ECMP_IS_MULTI_LEVEL(unit)) { 6392 6393 if (grp_idx < BCMI_L3_ECMP_OVERLAY_ENTRIES(unit)) { 6394 6395 ecmp->ecmp_group_flags |= BCM_L3_ECMP_OVERLAY; 6396 } 6397 } 6398 #endif 6399 6400 #ifdef BCM_TRIUMPH3_SUPPORT 6401 if (soc_feature(unit, soc_feature_ecmp_dlb)) { 6402 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 6403 if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) { 6404 rv = bcm_th2_l3_egress_ecmp_dlb_get(unit, ecmp); 6405 } else 6406 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT*/ 6407 { 6408 rv = bcm_tr3_l3_egress_ecmp_dlb_get(unit, ecmp); 6409 } 6410 if (BCM_FAILURE(rv)) { 6411 L3_UNLOCK(unit); 6412 return rv; 6413 } 6414 } 6415 #endif /* BCM_TRIUMPH3_SUPPORT */ 6416 6417 #ifdef BCM_TRIDENT2_SUPPORT 6418 if (soc_feature(unit, soc_feature_ecmp_resilient_hash)) { 6419 6420 #ifdef BCM_TRIDENT3_SUPPORT 6421 int ecmp_group; 6422 ecmp_count_entry_t ecmp_count_entry; 6423 if (SOC_IS_TRIDENT3X(unit)) { 6424 if (BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp->ecmp_intf)) { 6425 ecmp_group = ecmp->ecmp_intf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 6426 6427 BCM_IF_ERROR_RETURN(READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, 6428 ecmp_group, &ecmp_count_entry)); 6429 lb_mode = soc_L3_ECMP_COUNTm_field32_get(unit, 6430 &ecmp_count_entry, LB_MODEf); 6431 } 6432 } 6433 #endif 6434 if ((!(SOC_IS_TRIDENT3X(unit))) 6435 #ifdef BCM_TRIDENT3_SUPPORT 6436 || ((SOC_IS_TRIDENT3X(unit)) && (lb_mode == BCM_ECMP_LB_MODE_ENHANCED_HASH) 6437 && (ecmp->dynamic_mode == 0)) 6438 /* ecmp->dynamic_mode == 0 to make sure this is not DLB. 6439 For DLB, the previous call would have filled this up */ 6440 /* In TD3 ENHANCED_HASHING Is 4*/ 6441 #endif 6442 #ifdef BCM_TOMAHAWK_SUPPORT 6443 || (lb_mode == BCM_TH_L3_ECMP_LB_MODE_RH) 6444 #endif 6445 ) { 6446 rv = bcm_td2_l3_egress_ecmp_rh_get(unit, ecmp); 6447 } 6448 6449 if (BCM_FAILURE(rv)) { 6450 L3_UNLOCK(unit); 6451 return rv; 6452 } 6453 } 6454 #endif /* BCM_TRIUMPH3_SUPPORT */ 6455 6456 #ifdef BCM_TOMAHAWK_SUPPORT 6457 if (soc_feature(unit, soc_feature_hierarchical_ecmp)) { 6458 /* Set ECMP Level flags */ 6459 if (BCM_XGS3_L3_ECMP_GROUP_FLAGS_ISSET(unit, 6460 (ecmp->ecmp_intf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit)), 6461 BCM_L3_ECMP_OVERLAY)) { 6462 ecmp->ecmp_group_flags |= BCM_L3_ECMP_OVERLAY; 6463 } 6464 if (BCM_XGS3_L3_ECMP_GROUP_FLAGS_ISSET(unit, 6465 (ecmp->ecmp_intf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit)), 6466 BCM_L3_ECMP_UNDERLAY)) { 6467 ecmp->ecmp_group_flags |= BCM_L3_ECMP_UNDERLAY; 6468 } 6469 } 6470 6471 if ( 6472 #ifdef BCM_TRIDENT3_SUPPORT 6473 ((SOC_IS_TRIDENT3X(unit)) && (lb_mode != BCM_ECMP_LB_MODE_ENHANCED_HASH)) || 6474 #endif 6475 soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized)) { 6476 rv = bcm_opt_l3_egress_ecmp_lb_get(unit, ecmp); 6477 if (BCM_FAILURE(rv)) { 6478 L3_UNLOCK(unit); 6479 return rv; 6480 } 6481 } 6482 6483 /* 6484 * On Tomahawk, member table contains the RH set 6485 * which is returned above. 6486 * Member array is in the info structure. Hence, need to look 6487 * into rh info to retrieve member array if it is a RH group 6488 */ 6489 if (soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized) && 6490 rh_retrieve) { 6491 if (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_RESILIENT) { 6492 rv = bcm_opt_ecmp_rh_multipath_get(unit, 6493 (ecmp->ecmp_intf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit)), 6494 intf_size, intf_array, intf_count, &ecmp->max_paths); 6495 } 6496 } 6497 #endif /* BCM_TOMAHAWK_SUPPORT */ 6498 6499 #if defined(BCM_TOMAHAWK3_SUPPORT) 6500 if (ecmp->ecmp_group_flags & BCM_L3_ECMP_WEIGHTED) { 6501 /* Weighted groups are never sorted */ 6502 ecmp->ecmp_group_flags &= ~BCM_L3_ECMP_PATH_NO_SORTING; 6503 } 6504 #endif 6505 6506 L3_UNLOCK(unit); 6507 } 6508 6509 return rv; 6510 } 6511 6512 /* 6513 * Function: 6514 * _bcm_esw_l3_ecmp_create 6515 * Purpose: 6516 * Create or modify an Egress ECMP forwarding object. 6517 * Parameters: 6518 * unit - (IN) bcm device. 6519 * ecmp - (INOUT) ECMP group info. 6520 * intf_count - (IN) Number of elements in intf_array. 6521 * intf_array - (IN) Array of Egress forwarding objects. 6522 * op - (IN) Member operation: SET, ADD, DELETE, or REPLACE. 6523 * count - (IN) Number of elements in intf. 6524 * intf - (IN) Egress forwarding objects to add, delete, or replace. 6525 * primary_count - (IN) Primary count for DGM, if not DGM set intf_count. 6526 * ecmp_member_bitmap - (IN) ECMP DLB members. 6527 * Returns: 6528 * BCM_E_XXX 6529 */ 6530 int 6531 _bcm_esw_l3_ecmp_create(int unit, bcm_l3_egress_ecmp_t *ecmp, 6532 int intf_count, bcm_if_t *intf_array, int op, 6533 int count, bcm_if_t *intf, int primary_count, 6534 SHR_BITDCL *dlb_member_bitmap) 6535 { 6536 int rv = BCM_E_UNAVAIL; 6537 6538 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6539 6540 int rv2 = BCM_E_NONE; 6541 uint32 ecmp_group_flags = 0; 6542 int tmp_max_paths, tmp_intf_count; 6543 bcm_if_t *tmp_intf_array; 6544 #ifdef BCM_TOMAHAWK_SUPPORT 6545 bcm_if_t *new_intf_array = NULL; 6546 int cnt; 6547 int alloc_size; 6548 int pow = 0; 6549 int grp_idx; 6550 #endif /* BCM_TOMAHAWK_SUPPORT */ 6551 #if defined(BCM_TRIDENT3_SUPPORT) 6552 int rh_status; 6553 #endif 6554 6555 6556 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 6557 ecmp_group_flags = ecmp->ecmp_group_flags; 6558 6559 #if defined(BCM_TOMAHAWK3_SUPPORT) 6560 if ((BCM_XGS3_L3_TBL(unit, ecmp_info).ecmp_mode == 6561 ecmp_mode_hierarchical) && 6562 (soc_feature(unit, soc_feature_l3_ecmp_hier_tbl)) && 6563 !(ecmp->ecmp_group_flags & BCM_L3_ECMP_OVERLAY) && 6564 !(ecmp->ecmp_group_flags & BCM_L3_ECMP_UNDERLAY)) { 6565 if (ecmp->flags & BCM_L3_REPLACE) { 6566 if (BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, 6567 ecmp->ecmp_intf)) { 6568 ecmp_group_flags |= BCM_L3_ECMP_OVERLAY; 6569 } else { 6570 ecmp_group_flags |= BCM_L3_ECMP_UNDERLAY; 6571 } 6572 } else if (soc_feature(unit, soc_feature_l3_ecmp_hier_tbl) && 6573 (BCM_TH2_ECMP_IS_DLB_OR_DGM(unit, ecmp->dynamic_mode))) { 6574 ecmp_group_flags |= BCM_L3_ECMP_UNDERLAY; 6575 } else { 6576 return BCM_E_PARAM; 6577 } 6578 } 6579 #endif 6580 if (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_NORMAL || 6581 ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_ASSIGNED || 6582 ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_OPTIMAL) { 6583 if (!soc_feature(unit, soc_feature_ecmp_dlb)) { 6584 return BCM_E_UNAVAIL; 6585 } 6586 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined (BCM_TRIDENT3_SUPPORT) \ 6587 || defined(BCM_TOMAHAWK3_SUPPORT) 6588 /* A DLB group can only be programmed at ECMP Level 2 */ 6589 if (soc_feature(unit, soc_feature_hierarchical_ecmp) && 6590 ecmp->ecmp_group_flags & BCM_L3_ECMP_OVERLAY) { 6591 return BCM_E_PARAM; 6592 } 6593 if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) { 6594 ecmp_group_flags |= BCM_L3_ECMP_DLB_OPT; 6595 /* Do not sort for DLB resiliency since member offset can't be changed */ 6596 ecmp_group_flags |= BCM_L3_ECMP_PATH_NO_SORTING; 6597 } 6598 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT*/ 6599 } else if (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_RESILIENT) { 6600 if (!(soc_feature(unit, soc_feature_ecmp_resilient_hash) || 6601 soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized))) { 6602 return BCM_E_UNAVAIL; 6603 } 6604 if (soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized)) { 6605 /* Do not sort if load balancing mode is RH on Tomahawk. */ 6606 ecmp_group_flags |= BCM_L3_ECMP_PATH_NO_SORTING; 6607 ecmp_group_flags |= BCM_L3_ECMP_RH_OPT; 6608 } 6609 } else if (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_ROUND_ROBIN) { 6610 if (!soc_feature(unit, soc_feature_ecmp_round_robin)) { 6611 return BCM_E_UNAVAIL; 6612 } 6613 } else if (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_RANDOM) { 6614 if (!soc_feature(unit, soc_feature_ecmp_random)) { 6615 return BCM_E_UNAVAIL; 6616 } 6617 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 6618 } else if (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_DGM) { 6619 if (!soc_feature(unit, soc_feature_dgm)) { 6620 return BCM_E_UNAVAIL; 6621 } 6622 ecmp_group_flags |= BCM_L3_ECMP_DGM_OPT; 6623 /* Do not sort for DGM resiliency since member offset can't be changed */ 6624 ecmp_group_flags |= BCM_L3_ECMP_PATH_NO_SORTING; 6625 #endif /* BCM_TOMAHAWK2_SUPPORT */ 6626 } else if (ecmp->dynamic_mode != BCM_L3_ECMP_DYNAMIC_MODE_DISABLED) { 6627 return BCM_E_PARAM; 6628 } 6629 #if defined(BCM_RIOT_SUPPORT) || defined(BCM_MULTI_LEVEL_ECMP_SUPPORT) 6630 if (soc_feature(unit, soc_feature_riot) || 6631 soc_feature(unit, soc_feature_multi_level_ecmp)) { 6632 if (!BCMI_L3_ECMP_IS_MULTI_LEVEL(unit) && 6633 ((ecmp->ecmp_group_flags & BCM_L3_ECMP_OVERLAY))) { 6634 return (BCM_E_UNAVAIL); 6635 } 6636 } else 6637 #endif 6638 { 6639 if ((ecmp->ecmp_group_flags & BCM_L3_ECMP_OVERLAY) || 6640 (ecmp->ecmp_group_flags & BCM_L3_ECMP_UNDERLAY)) { 6641 if (!(soc_feature(unit, soc_feature_hierarchical_ecmp))) { 6642 return (BCM_E_UNAVAIL); 6643 } 6644 } 6645 } 6646 6647 if ((ecmp->max_paths > 0) && (intf_count > ecmp->max_paths)) { 6648 return BCM_E_RESOURCE; 6649 } 6650 6651 if ((intf_count > BCM_XGS3_L3_ECMP_MAX_PATHS(unit)) && 6652 !(ecmp_group_flags & BCM_L3_ECMP_RH_OPT)) { 6653 return BCM_E_RESOURCE; 6654 } 6655 6656 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 6657 if (soc_feature(unit, soc_feature_dgm)) { 6658 if (primary_count > BCM_XGS3_L3_ECMP_MAX_PATHS(unit) && 6659 (ecmp_group_flags & BCM_L3_ECMP_DGM_OPT)) { 6660 return BCM_E_RESOURCE; 6661 } 6662 } 6663 #endif /* BCM_TOMAHAWK2_SUPPORT */ 6664 6665 if (soc_feature(unit, soc_feature_ecmp_resilient_hash) && 6666 (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_RESILIENT)) { 6667 if (intf_count > ecmp->dynamic_size) { 6668 return BCM_E_PARAM; 6669 } 6670 } 6671 6672 6673 if ((ecmp->max_paths > BCM_XGS3_L3_ECMP_MAX_PATHS(unit)) && 6674 !(ecmp_group_flags & BCM_L3_ECMP_RH_OPT)) { 6675 return (BCM_E_PARAM); 6676 } 6677 6678 L3_LOCK(unit); 6679 6680 #ifdef BCM_TOMAHAWK_SUPPORT 6681 if (soc_feature(unit, soc_feature_hierarchical_ecmp)) { 6682 if ((BCM_XGS3_L3_TBL(unit, ecmp_info).ecmp_mode != 6683 ecmp_mode_hierarchical) && 6684 ((ecmp->ecmp_group_flags & BCM_L3_ECMP_OVERLAY) || 6685 (ecmp->ecmp_group_flags & BCM_L3_ECMP_UNDERLAY))) { 6686 L3_UNLOCK(unit); 6687 return (BCM_E_UNAVAIL); 6688 } 6689 /* Only one ECMP Level can be specified for a group */ 6690 if ((ecmp->ecmp_group_flags & BCM_L3_ECMP_OVERLAY) && 6691 (ecmp->ecmp_group_flags & BCM_L3_ECMP_UNDERLAY)) { 6692 L3_UNLOCK(unit); 6693 return (BCM_E_PARAM); 6694 } 6695 /* An RH group can only be programmed at ECMP Level 1 */ 6696 if (!(soc_feature(unit, soc_feature_l3_ecmp_hier_tbl)) && 6697 (ecmp->ecmp_group_flags & BCM_L3_ECMP_UNDERLAY) && 6698 (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_RESILIENT)) { 6699 L3_UNLOCK(unit); 6700 return (BCM_E_PARAM); 6701 } 6702 } 6703 6704 #ifdef BCM_TOMAHAWK3_SUPPORT 6705 if ((soc_feature(unit, soc_feature_l3_ecmp_weighted)) && 6706 (ecmp_group_flags & BCM_L3_ECMP_WEIGHTED)) { 6707 if ((intf_count != ecmp->max_paths) || 6708 (ecmp->dynamic_mode != BCM_L3_ECMP_DYNAMIC_MODE_DISABLED)) { 6709 return BCM_E_PARAM; 6710 } 6711 } 6712 6713 if (soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized) && 6714 (soc_feature(unit, soc_feature_ecmp_rh_1k_unique_members)) && 6715 (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_RESILIENT)) { 6716 if (intf_count > 1024) { 6717 return BCM_E_CONFIG; 6718 } 6719 } 6720 6721 #endif 6722 6723 /* Here the RH set constructed should be written in the member table */ 6724 if (soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized) && 6725 (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_RESILIENT)) { 6726 6727 if (ecmp->max_paths > BCM_XGS3_L3_ECMP_RH_MAX_PATHS(unit)) { 6728 L3_UNLOCK(unit); 6729 return BCM_E_PARAM; 6730 } 6731 /* Check if RH size is a power of 2 */ 6732 if (op == BCM_L3_ECMP_MEMBER_OP_SET) { 6733 pow = (ecmp->dynamic_size && 6734 !(ecmp->dynamic_size & (ecmp->dynamic_size - 1))); 6735 if (!pow) { 6736 L3_UNLOCK(unit); 6737 return BCM_E_PARAM; 6738 } 6739 if (intf_count > ecmp->dynamic_size) { 6740 L3_UNLOCK(unit); 6741 return BCM_E_PARAM; 6742 } 6743 if (ecmp->dynamic_size < RH_OPT_MIN_PATHS(unit) || 6744 ecmp->dynamic_size > RH_OPT_MAX_PATHS(unit)) { 6745 L3_UNLOCK(unit); 6746 return BCM_E_PARAM; 6747 } 6748 } 6749 /* Allocate new intf array which will be the RH set */ 6750 alloc_size = sizeof(bcm_if_t) * BCM_XGS3_L3_ECMP_MAX(unit); 6751 new_intf_array = sal_alloc(alloc_size, "RH intf array"); 6752 if (NULL == new_intf_array) { 6753 L3_UNLOCK(unit); 6754 return(BCM_E_MEMORY); 6755 } 6756 sal_memset(new_intf_array, 0, sizeof(bcm_if_t) * BCM_XGS3_L3_ECMP_MAX(unit)); 6757 /* Get existing RH entry set if the group is already exists */ 6758 if (op != BCM_L3_ECMP_MEMBER_OP_SET) { 6759 bcm_l3_egress_ecmp_t ecmp_copy; 6760 sal_memcpy(&ecmp_copy, ecmp, sizeof(ecmp_copy)); 6761 rv = _bcm_esw_l3_egress_ecmp_get(unit, &ecmp_copy, BCM_XGS3_L3_ECMP_MAX(unit), 6762 new_intf_array, &cnt, FALSE); 6763 if (BCM_FAILURE(rv)) { 6764 sal_free(new_intf_array); 6765 L3_UNLOCK(unit); 6766 return rv; 6767 } 6768 } 6769 6770 /* Create/modify the RH entry set */ 6771 rv = bcm_opt_l3_egress_ecmp_rh_create(unit, ecmp, intf_count, 6772 intf_array, op, count, intf, new_intf_array); 6773 if (BCM_FAILURE(rv)) { 6774 sal_free(new_intf_array); 6775 L3_UNLOCK(unit); 6776 return rv; 6777 } 6778 } 6779 #endif /* BCM_TOMAHAWK_SUPPORT */ 6780 6781 #ifdef BCM_TOMAHAWK3_SUPPORT 6782 if ((soc_feature(unit, soc_feature_post_ifp_single_stage_ecmp)) && 6783 (ecmp->dynamic_mode != BCM_L3_ECMP_DYNAMIC_MODE_RESILIENT) && 6784 (ecmp->dynamic_mode != BCM_L3_ECMP_DYNAMIC_MODE_DISABLED) && 6785 (ecmp->flags & BCM_L3_REPLACE) && (ecmp->ecmp_intf >= BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit)) && 6786 (bcm_opt_ecmp_group_is_rh(unit, ecmp->ecmp_intf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit)))) { 6787 bcm_opt_l3_egress_ecmp_rh_destroy(unit, ecmp->ecmp_intf); 6788 } else if ((soc_feature(unit, soc_feature_post_ifp_single_stage_ecmp)) 6789 && (soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized)) 6790 && (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_DISABLED) && 6791 (ecmp->flags & BCM_L3_REPLACE) && 6792 (!(ecmp->ecmp_group_flags & BCM_L3_ECMP_RH_OPT)) && 6793 (bcm_opt_ecmp_group_is_rh(unit, 6794 ecmp->ecmp_intf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit)))) { 6795 6796 /* Restore intf count and intf array */ 6797 if (ecmp->max_paths == 0) { 6798 tmp_max_paths = BCM_XGS3_L3_ECMP_RH_MAX_PATHS(unit); 6799 } else { 6800 tmp_max_paths = ecmp->max_paths; 6801 } 6802 6803 rv = bcm_opt_ecmp_rh_set_intf_arr(unit, intf_count, intf_array, 6804 ecmp->ecmp_intf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit), 6805 ecmp->dynamic_size, tmp_max_paths); 6806 6807 if (BCM_FAILURE(rv)) { 6808 sal_free(new_intf_array); 6809 L3_UNLOCK(unit); 6810 return rv; 6811 } 6812 6813 } 6814 #endif 6815 6816 tmp_max_paths = ecmp->max_paths; 6817 tmp_intf_count = intf_count; 6818 tmp_intf_array = intf_array; 6819 #ifdef BCM_TOMAHAWK_SUPPORT 6820 /* Save the members of the original intf_array */ 6821 if (soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized) && 6822 (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_RESILIENT)) { 6823 tmp_max_paths = ecmp->dynamic_size; 6824 tmp_intf_count = intf_count ? ecmp->dynamic_size : 0; 6825 primary_count = tmp_intf_count; 6826 tmp_intf_array = new_intf_array; 6827 } 6828 #endif /* BCM_TOMAHAWK_SUPPORT */ 6829 if (tmp_max_paths > 0) { 6830 rv = bcm_xgs3_l3_egress_multipath_max_create(unit, ecmp->flags, 6831 ecmp_group_flags, 6832 tmp_max_paths, 6833 tmp_intf_count, 6834 tmp_intf_array, 6835 &ecmp->ecmp_intf, 6836 primary_count, 6837 dlb_member_bitmap); 6838 } else { 6839 rv = bcm_xgs3_l3_egress_multipath_create(unit, ecmp->flags, 6840 ecmp_group_flags, 6841 intf_count, 6842 intf_array, 6843 &ecmp->ecmp_intf, 6844 primary_count, 6845 dlb_member_bitmap); 6846 } 6847 6848 #ifdef BCM_TOMAHAWK_SUPPORT 6849 if (new_intf_array) { 6850 sal_free(new_intf_array); 6851 new_intf_array = NULL; 6852 } 6853 #endif 6854 if (BCM_FAILURE(rv)) { 6855 L3_UNLOCK(unit); 6856 return rv; 6857 } 6858 6859 #ifdef BCM_TOMAHAWK_SUPPORT 6860 grp_idx = ecmp->ecmp_intf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 6861 /* Save the members of the original intf_array */ 6862 if (soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized) && 6863 (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_RESILIENT)) { 6864 BCM_XGS3_L3_ECMP_GROUP_FLAGS_RESET(unit, grp_idx, 6865 BCM_L3_ECMP_PATH_NO_SORTING); 6866 6867 /* Restore intf count and intf array */ 6868 if (ecmp->max_paths == 0) { 6869 tmp_max_paths = BCM_XGS3_L3_ECMP_RH_MAX_PATHS(unit); 6870 } else { 6871 tmp_max_paths = ecmp->max_paths; 6872 } 6873 6874 rv = bcm_opt_ecmp_rh_set_intf_arr(unit, intf_count, intf_array, 6875 grp_idx, ecmp->dynamic_size, tmp_max_paths); 6876 rv = bcm_opt_ecmp_lb_mode_set(unit, grp_idx, 6877 BCM_TH_L3_ECMP_LB_MODE_RH); 6878 } else if (soc_feature(unit, soc_feature_ecmp_random) && 6879 (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_RANDOM)) { 6880 rv = bcm_opt_ecmp_lb_mode_set(unit, grp_idx, 6881 BCM_TH_L3_ECMP_LB_MODE_RANDOM); 6882 } else if (soc_feature(unit, soc_feature_ecmp_round_robin) && 6883 (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_ROUND_ROBIN)) { 6884 rv = bcm_opt_ecmp_lb_mode_set(unit, grp_idx, 6885 BCM_TH_L3_ECMP_LB_MODE_RR); 6886 } else { 6887 if ((SOC_IS_TRIDENT3X(unit) && (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_DISABLED)) 6888 || (soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized))) { 6889 if (!(ecmp_group_flags & BCM_L3_ECMP_WEIGHTED)) { 6890 rv = bcm_opt_ecmp_lb_mode_set(unit, grp_idx, 6891 BCM_L3_ECMP_DYNAMIC_MODE_DISABLED); 6892 } 6893 } 6894 6895 } 6896 #endif /* BCM_TOMAHAWK_SUPPORT */ 6897 6898 #ifdef BCM_TRIUMPH3_SUPPORT 6899 if (soc_feature(unit, soc_feature_ecmp_dlb)) { 6900 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 6901 if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) { 6902 #ifdef BCM_TRIDENT3_SUPPORT 6903 if (BCM_TH2_ECMP_IS_DLB_OR_DGM(unit, ecmp->dynamic_mode) && SOC_IS_TRIDENT3X(unit)) { 6904 BCM_IF_ERROR_RETURN(bcmi_ecmp_rh_status_get(unit, &rh_status)); 6905 if (rh_status) { 6906 /* ECMP DLB and resilient hashing cannot be enabled 6907 * at the same time. 6908 */ 6909 return BCM_E_PARAM; 6910 } 6911 } 6912 #endif 6913 rv = bcm_th2_l3_egress_ecmp_dlb_create(unit, ecmp, intf_count, 6914 intf_array, primary_count, 6915 dlb_member_bitmap); 6916 } else 6917 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT*/ 6918 { 6919 rv = bcm_tr3_l3_egress_ecmp_dlb_create(unit, ecmp, intf_count, 6920 intf_array); 6921 } 6922 } 6923 #endif /* BCM_TRIUMPH3_SUPPORT */ 6924 6925 #ifdef BCM_TRIDENT3_SUPPORT 6926 rh_status = TRUE; /*Default for non-TD3 */ 6927 if (SOC_IS_TRIDENT3X(unit)) { 6928 BCM_IF_ERROR_RETURN(bcmi_ecmp_rh_status_get(unit, &rh_status)); 6929 } 6930 #endif 6931 #ifdef BCM_TRIDENT2_SUPPORT 6932 if ( 6933 #ifdef BCM_TRIDENT3_SUPPORT 6934 ((rh_status && (ecmp->flags & BCM_L3_REPLACE)) || 6935 (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_RESILIENT)) && 6936 #endif 6937 soc_feature(unit, soc_feature_ecmp_resilient_hash)) { 6938 #ifdef BCM_TRIDENT3_SUPPORT 6939 if (SOC_IS_TRIDENT3X(unit)) { 6940 int dlb_status; 6941 BCM_IF_ERROR_RETURN(bcmi_ecmp_dlb_status_get(unit, &dlb_status)); 6942 if (dlb_status) { 6943 /* ECMP DLB and resilient hashing cannot be enabled 6944 * at the same time. 6945 */ 6946 return BCM_E_PARAM; 6947 } 6948 } 6949 #endif 6950 rv = bcm_td2_l3_egress_ecmp_rh_create(unit, ecmp, intf_count, 6951 intf_array, op, count, intf); 6952 } 6953 #endif /* BCM_TRIUMPH3_SUPPORT */ 6954 6955 /* 6956 * One of above two hashing features should be active at a time. 6957 * 6958 * Free/Destroy the software state created for ecmp object if 6959 * there is error in feature specific multipath state creation. 6960 * Return the main error coming from feature specific 6961 * routines. Error coming from multipath destroy is very rare 6962 * as the object that was just created is being destroyed. 6963 * But even if there is some error, display a message. 6964 */ 6965 if (BCM_FAILURE(rv) 6966 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 6967 && !(soc_feature(unit, soc_feature_ecmp_dlb) && 6968 soc_feature(unit, soc_feature_ecmp_dlb_optimized) && 6969 BCM_TH2_ECMP_IS_DLB_OR_DGM(unit, ecmp->dynamic_mode) && 6970 (ecmp->flags & BCM_L3_REPLACE)) 6971 /* When replace fails, the original ECMP group should not be deleted.*/ 6972 #endif 6973 ) { 6974 rv2 = bcm_xgs3_l3_egress_multipath_destroy(unit, ecmp->ecmp_intf); 6975 } 6976 6977 if (BCM_FAILURE(rv2)) { 6978 LOG_ERROR(BSL_LS_BCM_COMMON, 6979 (BSL_META_U(unit, 6980 "multipath destroy failed : %d \n"), rv2)); 6981 } 6982 L3_UNLOCK(unit); 6983 } 6984 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6985 6986 return rv; 6987 } 6988 6989 /* 6990 * Function: 6991 * bcm_esw_l3_ecmp_create 6992 * Purpose: 6993 * Create or modify an Egress ECMP forwarding object. 6994 * Parameters: 6995 * unit - (IN) bcm device. 6996 * options - (IN) BCM_L3_ECMP_O_xxx flags 6997 * ecmp_info - (INOUT) ECMP group info. 6998 * ecmp_member_count - (IN) Number of elements in 6999 * ecmp_member_array. 7000 * ecmp_member_array - (IN) Member array of Egress 7001 * forwarding objects. 7002 * Returns: 7003 * BCM_E_XXX 7004 */ 7005 int 7006 bcm_esw_l3_ecmp_create( 7007 int unit, 7008 uint32 options, 7009 bcm_l3_egress_ecmp_t *ecmp_info, 7010 int ecmp_member_count, 7011 bcm_l3_ecmp_member_t *ecmp_member_array) 7012 { 7013 int rv, rv2; 7014 int i, alloc_size, intf_count, old_intf_count; 7015 bcm_if_t *intf_array = NULL; 7016 bcm_if_t *old_intf_array = NULL; 7017 7018 if (ecmp_info == NULL || ecmp_member_array == NULL) { 7019 return (BCM_E_PARAM); 7020 } 7021 7022 ecmp_info->flags &= ~(BCM_L3_WITH_ID | BCM_L3_REPLACE); 7023 7024 if (options & BCM_L3_ECMP_O_CREATE_WITH_ID) { 7025 ecmp_info->flags |= BCM_L3_WITH_ID; 7026 } 7027 if (options & BCM_L3_ECMP_O_REPLACE) { 7028 ecmp_info->flags |= BCM_L3_REPLACE; 7029 } 7030 7031 L3_LOCK(unit); 7032 7033 intf_count = ecmp_member_count; 7034 if (intf_count > BCM_XGS3_L3_ECMP_MAX(unit)) { 7035 rv = BCM_E_RESOURCE; 7036 goto clean_up; 7037 } 7038 7039 /* Convert the ecmp_member_array to intf_array */ 7040 alloc_size = BCM_XGS3_L3_ECMP_MAX(unit) * sizeof(bcm_if_t); 7041 intf_array = sal_alloc(alloc_size, "L3 ECMP intf_array"); 7042 if (intf_array == NULL) { 7043 rv = BCM_E_MEMORY; 7044 goto clean_up; 7045 } 7046 7047 sal_memset(intf_array, 0, alloc_size); 7048 7049 /* Configure the intf_array to HW */ 7050 if ((soc_feature(unit, soc_feature_ecmp_resilient_hash) || 7051 soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized)) && 7052 (ecmp_info->flags & BCM_L3_ECMP_RH_REPLACE)) { 7053 7054 for (i = 0; i < intf_count; i++) { 7055 intf_array[i] = ecmp_member_array[i].egress_if; 7056 } 7057 7058 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_info->ecmp_intf)) { 7059 rv = BCM_E_PARAM; 7060 goto clean_up; 7061 } 7062 7063 for (i = 0; i < intf_count; i++) { 7064 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, intf_array[i])) { 7065 rv = BCM_E_PARAM; 7066 goto clean_up; 7067 } 7068 } 7069 7070 /* Allocate interface array */ 7071 alloc_size = sizeof(bcm_if_t) * BCM_XGS3_L3_ECMP_MAX(unit); 7072 old_intf_array = sal_alloc(alloc_size, "old intf array"); 7073 if (NULL == old_intf_array) { 7074 rv = BCM_E_MEMORY; 7075 goto clean_up; 7076 } 7077 sal_memset(old_intf_array, 0, alloc_size); 7078 7079 7080 /* Get ECMP group's existing interface array */ 7081 rv = bcm_esw_l3_egress_multipath_get(unit, ecmp_info->ecmp_intf, 7082 BCM_XGS3_L3_ECMP_MAX(unit), 7083 old_intf_array, 7084 &old_intf_count); 7085 if (BCM_FAILURE(rv)) { 7086 goto clean_up; 7087 } 7088 7089 /* Check if there is room in ECMP group */ 7090 if ((old_intf_count == ecmp_info->max_paths) && 7091 (intf_count > old_intf_count)) { 7092 rv = BCM_E_FULL; 7093 goto clean_up; 7094 } 7095 7096 #if defined(BCM_TOMAHAWK3_SUPPORT) 7097 if (ecmp_info->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_RESILIENT) { 7098 if (intf_count > ecmp_info->dynamic_size) { 7099 rv = BCM_E_RESOURCE; 7100 goto clean_up; 7101 } 7102 } else 7103 #endif 7104 { 7105 if (intf_count > ecmp_info->max_paths) { 7106 rv = BCM_E_RESOURCE; 7107 goto clean_up; 7108 } 7109 } 7110 7111 /* Update ECMP group */ 7112 ecmp_info->flags |= BCM_L3_REPLACE | BCM_L3_WITH_ID; 7113 7114 rv = _bcm_esw_l3_ecmp_create(unit, ecmp_info, intf_count, intf_array, 7115 BCM_L3_ECMP_MEMBER_OP_REPLACE, old_intf_count, old_intf_array, 7116 intf_count, NULL); 7117 } else { 7118 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 7119 if (BCM_TH2_ECMP_IS_DLB_OR_DGM(unit, ecmp_info->dynamic_mode)) { 7120 rv = bcm_th2_l3_ecmp_dlb_dgm_member_create(unit, ecmp_info, 7121 ecmp_member_array, 7122 ecmp_member_count); 7123 /* No DLB ECMP failover */ 7124 goto clean_up; 7125 } else 7126 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT */ 7127 { 7128 for (i = 0; i < intf_count; i++) { 7129 intf_array[i] = ecmp_member_array[i].egress_if; 7130 } 7131 rv = _bcm_esw_l3_ecmp_create(unit, ecmp_info, intf_count, 7132 intf_array, BCM_L3_ECMP_MEMBER_OP_SET, 7133 0, NULL, intf_count, NULL); 7134 } 7135 } 7136 7137 if (BCM_FAILURE(rv)) { 7138 goto clean_up; 7139 } 7140 7141 /* Configure the member's attributions */ 7142 rv = _bcm_xgs3_l3_ecmp_member_set(unit, ecmp_info, 7143 intf_count, ecmp_member_array); 7144 if (BCM_FAILURE(rv)) { 7145 if (!(ecmp_info->flags & BCM_L3_REPLACE)) { 7146 rv2 = bcm_xgs3_l3_egress_multipath_destroy(unit, ecmp_info->ecmp_intf); 7147 if (BCM_FAILURE(rv2)) { 7148 LOG_ERROR(BSL_LS_BCM_COMMON, 7149 (BSL_META_U(unit, 7150 "multipath destroy failed : %d \n"), rv2)); 7151 } 7152 } 7153 goto clean_up; 7154 } 7155 7156 clean_up: 7157 if (intf_array) { 7158 sal_free(intf_array); 7159 intf_array = NULL; 7160 } 7161 if (old_intf_array) { 7162 sal_free(old_intf_array); 7163 old_intf_array = NULL; 7164 } 7165 L3_UNLOCK(unit); 7166 7167 return rv; 7168 } 7169 7170 /* 7171 * Function: 7172 * bcm_esw_l3_ecmp_destroy 7173 * Purpose: 7174 * Destroy an Egress ECMP forwarding object. 7175 * Parameters: 7176 * unit - (IN) bcm device. 7177 * ecmp_group_id - (IN) L3 interface ID pointing to Egress 7178 * ECMP forwarding object 7179 * Returns: 7180 * BCM_E_XXX 7181 */ 7182 int 7183 bcm_esw_l3_ecmp_destroy( 7184 int unit, 7185 bcm_if_t ecmp_group_id) 7186 { 7187 int rv = BCM_E_UNAVAIL; 7188 7189 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7190 if (SOC_IS_XGS3_SWITCH(unit) && 7191 soc_feature(unit, soc_feature_l3)) { 7192 L3_LOCK(unit); 7193 rv = bcm_xgs3_l3_ecmp_destroy(unit, ecmp_group_id); 7194 L3_UNLOCK(unit); 7195 } 7196 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 7197 7198 return rv; 7199 } 7200 7201 /* 7202 * Function: 7203 * bcm_esw_l3_ecmp_get 7204 * Purpose: 7205 * Get an Egress ECMP forwarding object. 7206 * Parameters: 7207 * unit - (IN) bcm device. 7208 * ecmp_info - (INOUT) ECMP group info. 7209 * ecmp_member_size - (IN) Size of allocated entries in 7210 * ecmp_member_array. 7211 * ecmp_member_array - (OUT) Member array of Egress forwarding objects. 7212 * ecmp_member_count - (OUT) Number of members of ecmp_member_count actually 7213 * filled in. This will be a value less than or 7214 * equal to the value passed in as ecmp_member_size 7215 * unless ecmp_member_size is 0. If ecmp_member_size 7216 * is 0, then ecmp_member_array is ignored and 7217 * ecmp_member_count is filled in with the number of 7218 * members that would have been filled into 7219 * ecmp_member_array if ecmp_member_size was 7220 * arbitrarily large. 7221 * Returns: 7222 * BCM_E_XXX 7223 */ 7224 int 7225 bcm_esw_l3_ecmp_get( 7226 int unit, 7227 bcm_l3_egress_ecmp_t *ecmp_info, 7228 int ecmp_member_size, 7229 bcm_l3_ecmp_member_t *ecmp_member_array, 7230 int *ecmp_member_count) 7231 { 7232 int rv = BCM_E_UNAVAIL; 7233 7234 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7235 if (SOC_IS_XGS3_SWITCH(unit) && 7236 soc_feature(unit, soc_feature_l3)) { 7237 L3_LOCK(unit); 7238 7239 /* Get the ECMP group's information */ 7240 rv = _bcm_xgs3_l3_ecmp_info_get(unit, ecmp_info); 7241 if (BCM_FAILURE(rv)) { 7242 L3_UNLOCK(unit); 7243 return rv; 7244 } 7245 7246 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 7247 if (BCM_TH2_ECMP_IS_DLB_OR_DGM(unit, ecmp_info->dynamic_mode)) { 7248 rv = bcm_th2_l3_ecmp_dlb_dgm_member_get( 7249 unit, ecmp_info, ecmp_member_size, 7250 ecmp_member_array, ecmp_member_count); 7251 } else 7252 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT */ 7253 { 7254 /* Get the ECMP member's information */ 7255 rv = _bcm_xgs3_l3_ecmp_member_get( 7256 unit, ecmp_info, ecmp_member_size, 7257 ecmp_member_array, ecmp_member_count); 7258 } 7259 L3_UNLOCK(unit); 7260 } 7261 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 7262 7263 return rv; 7264 } 7265 7266 /* 7267 * Function: 7268 * bcm_esw_l3_ecmp_member_add 7269 * Purpose: 7270 * Add a member to an Egress ECMP forwarding object. 7271 * Parameters: 7272 * unit - (IN) bcm device. 7273 * ecmp_group_id - (IN) L3 interface ID pointing to Egress 7274 * ECMP forwarding object 7275 * ecmp_member - (IN) Pointer to Egress forwarding 7276 * object member structure. 7277 * Returns: 7278 * BCM_E_XXX 7279 */ 7280 int 7281 bcm_esw_l3_ecmp_member_add( 7282 int unit, 7283 bcm_if_t ecmp_group_id, 7284 bcm_l3_ecmp_member_t *ecmp_member) 7285 { 7286 int rv = BCM_E_UNAVAIL; 7287 7288 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7289 if (SOC_IS_XGS3_SWITCH(unit) && 7290 soc_feature(unit, soc_feature_l3)) { 7291 int i, alloc_size; 7292 bcm_if_t *intf_array = NULL; 7293 bcm_l3_egress_ecmp_t ecmp_info; 7294 int ecmp_member_count; 7295 bcm_l3_ecmp_member_t *ecmp_member_array = NULL; 7296 int primary_count; 7297 7298 /* Input check */ 7299 if (ecmp_member == NULL) { 7300 return BCM_E_PARAM; 7301 } 7302 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_group_id)) { 7303 return BCM_E_PARAM; 7304 } 7305 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, ecmp_member->egress_if)) { 7306 #ifdef BCM_RIOT_SUPPORT 7307 if ((BCMI_L3_ECMP_IS_MULTI_LEVEL(unit)) && 7308 (BCMI_RIOT_IS_ENABLED(unit))) { 7309 7310 if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, 7311 ecmp_member->egress_if)) { 7312 7313 return (BCM_E_PARAM); 7314 } 7315 } else 7316 #endif 7317 { 7318 return (BCM_E_PARAM); 7319 } 7320 } 7321 7322 /* Allocate interface array */ 7323 alloc_size = sizeof(bcm_if_t) * BCM_XGS3_L3_ECMP_MAX(unit); 7324 intf_array = sal_alloc(alloc_size, "intf array"); 7325 if (NULL == intf_array) { 7326 return BCM_E_MEMORY; 7327 } 7328 sal_memset(intf_array, 0, alloc_size); 7329 7330 alloc_size = sizeof(bcm_l3_ecmp_member_t) * BCM_XGS3_L3_ECMP_MAX(unit); 7331 ecmp_member_array = sal_alloc(alloc_size, "ecmp member array"); 7332 if (NULL == ecmp_member_array) { 7333 sal_free(intf_array); 7334 return BCM_E_MEMORY; 7335 } 7336 sal_memset(ecmp_member_array, 0, alloc_size); 7337 7338 L3_LOCK(unit); 7339 7340 ecmp_info.ecmp_intf = ecmp_group_id; 7341 rv = bcm_xgs3_l3_ecmp_get(unit, &ecmp_info, BCM_XGS3_L3_ECMP_MAX(unit), 7342 ecmp_member_array, &ecmp_member_count); 7343 if (BCM_FAILURE(rv)) { 7344 goto clean_up; 7345 } 7346 7347 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 7348 if (BCM_TH2_ECMP_IS_DLB_OR_DGM(unit, ecmp_info.dynamic_mode)) { 7349 rv = bcm_th2_l3_ecmp_dlb_dgm_member_add( 7350 unit, &ecmp_info, ecmp_member, 7351 ecmp_member_array, &ecmp_member_count); 7352 } else 7353 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT */ 7354 { 7355 /* Check if there is room in ECMP group */ 7356 if (ecmp_member_count == ecmp_info.max_paths) { 7357 rv = BCM_E_FULL; 7358 goto clean_up; 7359 } 7360 7361 7362 sal_memcpy(&ecmp_member_array[ecmp_member_count], ecmp_member, 7363 sizeof(ecmp_member_array[ecmp_member_count])); 7364 primary_count = ecmp_member_count + 1; 7365 7366 for (i = 0; i <= ecmp_member_count; i++) { 7367 intf_array[i] = ecmp_member_array[i].egress_if; 7368 } 7369 7370 /* Update ECMP group */ 7371 ecmp_info.flags |= BCM_L3_REPLACE | BCM_L3_WITH_ID; 7372 7373 rv = _bcm_esw_l3_ecmp_create( 7374 unit, &ecmp_info, ecmp_member_count + 1, 7375 intf_array, BCM_L3_ECMP_MEMBER_OP_ADD, 7376 1, &ecmp_member->egress_if, primary_count, NULL); 7377 if (BCM_FAILURE(rv)) { 7378 goto clean_up; 7379 } 7380 7381 rv = _bcm_xgs3_l3_ecmp_member_set(unit, &ecmp_info, 7382 ecmp_member_count + 1, ecmp_member_array); 7383 if (BCM_FAILURE(rv)) { 7384 goto clean_up; 7385 } 7386 } 7387 7388 clean_up: 7389 if (intf_array) { 7390 sal_free(intf_array); 7391 intf_array = NULL; 7392 } 7393 if (ecmp_member_array) { 7394 sal_free(ecmp_member_array); 7395 ecmp_member_array = NULL; 7396 } 7397 7398 L3_UNLOCK(unit); 7399 } 7400 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 7401 7402 return rv; 7403 } 7404 7405 /* 7406 * Function: 7407 * bcm_esw_l3_ecmp_member_delete 7408 * Purpose: 7409 * Delete a member from an Egress ECMP forwarding object. 7410 * Parameters: 7411 * unit - (IN) bcm device. 7412 * ecmp_group_id - (IN) L3 interface ID pointing to Egress 7413 * ECMP forwarding object. 7414 * ecmp_member - (IN) L3 interface id pointing to Egress 7415 * forwarding object 7416 * Returns: 7417 * BCM_E_XXX 7418 */ 7419 7420 int 7421 bcm_esw_l3_ecmp_member_delete( 7422 int unit, 7423 bcm_if_t ecmp_group_id, 7424 bcm_l3_ecmp_member_t *ecmp_member) 7425 { 7426 int rv = BCM_E_UNAVAIL; 7427 7428 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7429 if (SOC_IS_XGS3_SWITCH(unit) && 7430 soc_feature(unit, soc_feature_l3)) { 7431 int alloc_size; 7432 bcm_if_t *intf_array = NULL; 7433 int i, j; 7434 bcm_l3_egress_ecmp_t ecmp_info; 7435 int ecmp_member_count; 7436 bcm_l3_ecmp_member_t *ecmp_member_array = NULL; 7437 int primary_count; 7438 7439 /* Input check */ 7440 if (ecmp_member == NULL) { 7441 return BCM_E_PARAM; 7442 } 7443 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_group_id)) { 7444 return (BCM_E_PARAM); 7445 } 7446 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, ecmp_member->egress_if)) { 7447 #if defined(BCM_TOMAHAWK3_SUPPORT) 7448 if (soc_feature(unit, soc_feature_hierarchical_ecmp) && 7449 (BCM_XGS3_L3_TBL(unit, ecmp_info).ecmp_mode == 7450 ecmp_mode_hierarchical)) { 7451 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_member->egress_if)) { 7452 return (BCM_E_PARAM); 7453 } 7454 } else 7455 #endif 7456 #ifdef BCM_RIOT_SUPPORT 7457 if ((BCMI_L3_ECMP_IS_MULTI_LEVEL(unit)) && 7458 (BCMI_RIOT_IS_ENABLED(unit))) { 7459 7460 if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, 7461 ecmp_member->egress_if)) { 7462 7463 return (BCM_E_PARAM); 7464 } 7465 } else 7466 #endif 7467 { 7468 return (BCM_E_PARAM); 7469 } 7470 } 7471 7472 /* Allocate interface array */ 7473 alloc_size = sizeof(bcm_if_t) * BCM_XGS3_L3_ECMP_MAX(unit); 7474 intf_array = sal_alloc(alloc_size, "intf array"); 7475 if (NULL == intf_array) { 7476 return BCM_E_MEMORY; 7477 } 7478 sal_memset(intf_array, 0, alloc_size); 7479 7480 alloc_size = sizeof(bcm_l3_ecmp_member_t) * BCM_XGS3_L3_ECMP_MAX(unit); 7481 ecmp_member_array = sal_alloc(alloc_size, "ecmp member array"); 7482 if (NULL == ecmp_member_array) { 7483 sal_free(intf_array); 7484 return BCM_E_MEMORY; 7485 } 7486 sal_memset(ecmp_member_array, 0, alloc_size); 7487 7488 L3_LOCK(unit); 7489 7490 /* Get ECMP group's existing member array */ 7491 ecmp_info.ecmp_intf = ecmp_group_id; 7492 rv = bcm_xgs3_l3_ecmp_get(unit, &ecmp_info, BCM_XGS3_L3_ECMP_MAX(unit), 7493 ecmp_member_array, &ecmp_member_count); 7494 if (BCM_FAILURE(rv)) { 7495 goto clean_up; 7496 } 7497 7498 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 7499 if (BCM_TH2_ECMP_IS_DLB_OR_DGM(unit, ecmp_info.dynamic_mode)) { 7500 7501 rv = bcm_th2_l3_ecmp_dlb_dgm_member_delete( 7502 unit, &ecmp_info, ecmp_member, 7503 ecmp_member_array, &ecmp_member_count); 7504 } else 7505 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT */ 7506 { 7507 for (i = 0; i < ecmp_member_count; i++) { 7508 intf_array[i] = ecmp_member_array[i].egress_if; 7509 } 7510 7511 /* Search for given intf */ 7512 for (i = 0; i < ecmp_member_count; i++) { 7513 if (intf_array[i] == ecmp_member->egress_if) { 7514 break; 7515 } 7516 } 7517 if (i == ecmp_member_count) { 7518 /* Not found */ 7519 rv = BCM_E_NOT_FOUND; 7520 goto clean_up; 7521 } 7522 7523 primary_count = ecmp_member_count - 1; 7524 7525 /* Shift remaining elements of intf_array */ 7526 for (j = i; j < ecmp_member_count - 1; j++) { 7527 intf_array[j] = intf_array[j + 1]; 7528 sal_memcpy(&ecmp_member_array[j], &ecmp_member_array[j + 1], 7529 sizeof(ecmp_member_array[j])); 7530 } 7531 7532 /* Update ECMP group */ 7533 ecmp_info.flags |= BCM_L3_REPLACE | BCM_L3_WITH_ID; 7534 rv = _bcm_esw_l3_ecmp_create(unit, &ecmp_info, ecmp_member_count - 1, 7535 intf_array, BCM_L3_ECMP_MEMBER_OP_DELETE, 7536 1, &ecmp_member->egress_if, 7537 primary_count, NULL); 7538 if (BCM_FAILURE(rv)) { 7539 goto clean_up; 7540 } 7541 7542 rv = _bcm_xgs3_l3_ecmp_member_set(unit, &ecmp_info, 7543 ecmp_member_count - 1, ecmp_member_array); 7544 if (BCM_FAILURE(rv)) { 7545 goto clean_up; 7546 } 7547 } 7548 7549 clean_up: 7550 if (intf_array) { 7551 sal_free(intf_array); 7552 intf_array = NULL; 7553 } 7554 if (ecmp_member_array) { 7555 sal_free(ecmp_member_array); 7556 ecmp_member_array = NULL; 7557 } 7558 7559 L3_UNLOCK(unit); 7560 } 7561 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 7562 7563 return rv; 7564 } 7565 7566 /* 7567 * Function: 7568 * bcm_esw_l3_ecmp_member_delete_all 7569 * Purpose: 7570 * Delete all members from an Egress ECMP forwarding object. 7571 * Parameters: 7572 * unit - (IN) bcm device. 7573 * ecmp_group_id - (IN) L3 interface ID pointing to Egress 7574 * ECMP forwarding object. 7575 * Returns: 7576 * BCM_E_XXX 7577 */ 7578 7579 int 7580 bcm_esw_l3_ecmp_member_delete_all( 7581 int unit, 7582 bcm_if_t ecmp_group_id) 7583 { 7584 int rv = BCM_E_UNAVAIL; 7585 7586 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7587 if (SOC_IS_XGS3_SWITCH(unit) && 7588 soc_feature(unit, soc_feature_l3)) { 7589 int i, alloc_size; 7590 bcm_l3_egress_ecmp_t ecmp_info; 7591 int ecmp_member_count; 7592 bcm_l3_ecmp_member_t *ecmp_member_array = NULL; 7593 7594 L3_LOCK(unit); 7595 7596 bcm_l3_egress_ecmp_t_init(&ecmp_info); 7597 7598 ecmp_info.ecmp_intf = ecmp_group_id; 7599 7600 rv = bcm_esw_l3_ecmp_get(unit, &ecmp_info, 0, 7601 NULL, &ecmp_member_count); 7602 if (BCM_FAILURE(rv)) { 7603 goto clean_up; 7604 } 7605 if (ecmp_member_count > 0) { 7606 alloc_size = ecmp_member_count * sizeof(bcm_l3_ecmp_member_t); 7607 ecmp_member_array = sal_alloc(alloc_size, "ecmp_member_array"); 7608 if (ecmp_member_array == NULL) { 7609 rv = BCM_E_MEMORY; 7610 goto clean_up; 7611 } 7612 sal_memset(ecmp_member_array, 0, alloc_size); 7613 7614 rv = bcm_esw_l3_ecmp_get(unit, &ecmp_info, ecmp_member_count, 7615 ecmp_member_array, &ecmp_member_count); 7616 if (BCM_FAILURE(rv)) { 7617 goto clean_up; 7618 } 7619 #if defined(BCM_TOMAHAWK3_SUPPORT) 7620 /* Update ECMP group */ 7621 if (soc_feature(unit, soc_feature_l3_ecmp_hier_tbl) && 7622 (ecmp_mode_hierarchical == 7623 BCM_XGS3_L3_TBL(unit, ecmp_info).ecmp_mode) && 7624 ((BCM_XGS3_L3_ECMP_MAX_GROUPS(unit) / 2) > 7625 (ecmp_group_id - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit)))) { 7626 ecmp_info.flags |= BCM_L3_REPLACE | BCM_L3_WITH_ID; 7627 rv = _bcm_esw_l3_ecmp_create(unit, &ecmp_info, 0, 7628 NULL, BCM_L3_ECMP_MEMBER_OP_REPLACE, 7629 0, NULL, 7630 0, NULL); 7631 if (BCM_FAILURE(rv)) { 7632 goto clean_up; 7633 } 7634 7635 rv = _bcm_xgs3_l3_ecmp_member_set(unit, &ecmp_info, 7636 ecmp_member_count - 1, ecmp_member_array); 7637 if (BCM_FAILURE(rv)) { 7638 goto clean_up; 7639 } 7640 } else 7641 #endif 7642 { 7643 7644 for (i = 0; i < ecmp_member_count; i++) { 7645 rv = bcm_esw_l3_ecmp_member_delete(unit, ecmp_info.ecmp_intf, 7646 &ecmp_member_array[i]); 7647 if (BCM_FAILURE(rv)) { 7648 goto clean_up; 7649 } 7650 } 7651 } 7652 } 7653 clean_up: 7654 if (ecmp_member_array) { 7655 sal_free(ecmp_member_array); 7656 ecmp_member_array = NULL; 7657 } 7658 7659 L3_UNLOCK(unit); 7660 } 7661 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 7662 7663 return rv; 7664 } 7665 7666 /* 7667 * Function: 7668 * bcm_esw_l3_ecmp_find 7669 * Purpose: 7670 * Find an Egress ECMP forwarding object. 7671 * Parameters: 7672 * unit - (IN) bcm device. 7673 * ecmp_member_count - (IN) Number of elements in ecmp_member_array. 7674 * ecmp_member_array - (IN) Member array of Egress forwarding objects. 7675 * ecmp_info - (OUT) ECMP group info. 7676 * Returns: 7677 * BCM_E_XXX 7678 */ 7679 7680 int 7681 bcm_esw_l3_ecmp_find( 7682 int unit, 7683 int ecmp_member_count, 7684 bcm_l3_ecmp_member_t *ecmp_member_array, 7685 bcm_l3_egress_ecmp_t *ecmp_info) 7686 { 7687 int rv = BCM_E_UNAVAIL; 7688 7689 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7690 if (SOC_IS_XGS3_SWITCH(unit) && 7691 soc_feature(unit, soc_feature_l3)) { 7692 L3_LOCK(unit); 7693 rv = bcm_xgs3_l3_ecmp_find(unit, ecmp_member_count, ecmp_member_array, 7694 ecmp_info); 7695 L3_UNLOCK(unit); 7696 } 7697 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 7698 7699 return rv; 7700 } 7701 7702 /* 7703 * Function: 7704 * bcm_esw_l3_ecmp_traverse 7705 * Purpose: 7706 * Goes through Egress ECMP forwarding objects table and runs the 7707 * user callback function at each Egress ECMP forwarding objects 7708 * entry passing back the information for that ECMP object. 7709 * Parameters: 7710 * unit - (IN) bcm device. 7711 * trav_fn - (IN) Callback function. 7712 * user_data - (IN) User data to be passed to callback function. 7713 * Returns: 7714 * BCM_E_XXX 7715 */ 7716 7717 int 7718 bcm_esw_l3_ecmp_traverse( 7719 int unit, 7720 bcm_l3_ecmp_traverse_cb trav_fn, 7721 void *user_data) 7722 { 7723 int rv = BCM_E_UNAVAIL; 7724 7725 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7726 if (SOC_IS_XGS3_SWITCH(unit) && 7727 soc_feature(unit, soc_feature_l3)) { 7728 L3_LOCK(unit); 7729 rv = bcm_xgs3_l3_ecmp_traverse(unit, trav_fn, user_data); 7730 L3_UNLOCK(unit); 7731 } 7732 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 7733 7734 return rv; 7735 } 7736 7737 #ifdef BCM_TOMAHAWK_SUPPORT 7738 7739 STATIC int 7740 _bcm_th_l3_ecmp_agm_update(int unit, 7741 bcm_if_t l3_ecmp_id, bcm_switch_agm_type_t agm_type, 7742 int agm_pool_id, int agm_index) 7743 { 7744 int rv, ecmp_index; 7745 uint32 mpath_flag; 7746 int ecmp_group_id; 7747 ecmp_count_entry_t ecmpc_entry; 7748 soc_mem_t mem = L3_ECMP_COUNTm; 7749 7750 if (BCM_XGS3_L3_EGRESS_MODE_ISSET(unit) == 0) { 7751 return BCM_E_UNAVAIL; 7752 } 7753 7754 /* Check l3_ecmp_id */ 7755 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, l3_ecmp_id)) { 7756 return BCM_E_PARAM; 7757 } 7758 7759 rv = bcm_xgs3_get_nh_from_egress_object(unit, l3_ecmp_id, &mpath_flag, 7760 0, &ecmp_group_id); 7761 if (BCM_FAILURE(rv)) { 7762 return BCM_E_PARAM; 7763 } 7764 if (0 == soc_feature(unit, soc_feature_l3_dynamic_ecmp_group)) { 7765 ecmp_index = ecmp_group_id * BCM_XGS3_L3_ECMP_MAX_PATHS(unit); 7766 } else { 7767 ecmp_index = ecmp_group_id; 7768 } 7769 7770 #ifdef BCM_TOMAHAWK3_SUPPORT 7771 /* Check if the given ecmp itf is hierarchial */ 7772 if (soc_feature(unit, soc_feature_l3_ecmp_hier_tbl) && 7773 (ecmp_mode_hierarchical == 7774 BCM_XGS3_L3_TBL(unit, ecmp_info).ecmp_mode) && 7775 ((BCM_XGS3_L3_ECMP_MAX_GROUPS(unit) / 2) > 7776 (l3_ecmp_id - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit)))) { 7777 7778 /* Check that AGMTYPE is overlay if the ecmp intf is hierarchial */ 7779 if (bcmSwitchAgmTypeL3EcmpOverlay != agm_type) { 7780 return (BCM_E_PARAM); 7781 } 7782 7783 /* Choose the correct memory based on the AGM type */ 7784 if (soc_mem_is_valid(unit, ECMP_GROUP_HIERARCHICALm)) { 7785 mem = ECMP_GROUP_HIERARCHICALm; 7786 } 7787 } 7788 #endif 7789 7790 /* l3_ecmp group entry */ 7791 SOC_IF_ERROR_RETURN 7792 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, ecmp_index, &ecmpc_entry)); 7793 soc_mem_field32_set( 7794 unit, mem, &ecmpc_entry, AGM_MONITOR_POOL_IDf, agm_pool_id); 7795 soc_mem_field32_set(unit, mem, &ecmpc_entry, AGM_MONITOR_IDf, agm_index); 7796 7797 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 7798 if (soc_feature(unit, soc_feature_dgm) && 7799 soc_feature(unit, soc_feature_agm_support_for_dgm)) { 7800 int count; 7801 bcm_l3_egress_ecmp_t ecmp_info; 7802 bcm_l3_egress_ecmp_t_init(&ecmp_info); 7803 ecmp_info.ecmp_intf = ecmp_group_id + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 7804 rv = bcm_xgs3_l3_ecmp_get(unit, &ecmp_info, 0, NULL, &count); 7805 7806 if (SOC_SUCCESS(rv) && 7807 ecmp_info.dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_DGM) { 7808 if (0 == agm_index) { /* detach */ 7809 count -= BCM_XGS3_L3_ALTERNATE_CNT_PTR(unit)[ecmp_index]; 7810 } 7811 soc_mem_field32_set(unit, mem, &ecmpc_entry, COUNTf, count - 1); 7812 } 7813 } 7814 #endif 7815 SOC_IF_ERROR_RETURN 7816 (soc_mem_write(unit, mem, MEM_BLOCK_ANY, ecmp_index, &ecmpc_entry)); 7817 7818 return rv; 7819 } 7820 7821 /* 7822 * Function: 7823 * bcm_th_l3_ecmp_agm_attach 7824 * Purpose: 7825 * Attach already created monitor entry to a l3 ecmp group 7826 * Internally, Map the monitor_entry_id to an aggregation 7827 * group (l3 ecmp group). 7828 */ 7829 int 7830 bcm_th_l3_ecmp_agm_attach(int unit, bcm_if_t l3_ecmp_id, 7831 bcm_switch_agm_id_t agm_id) 7832 { 7833 int rv = BCM_E_NONE; 7834 agm_monitor_t agm_mnt; 7835 bcm_switch_agm_id_t agm_id_old; 7836 int agm_pool_id; 7837 uint32 agm_index; 7838 int mbm_cnt = 0, mbm_max; 7839 bcm_if_t *mbm_arr; 7840 7841 /* Validate parameters */ 7842 if (!SOC_UNIT_VALID(unit)) { 7843 return BCM_E_UNIT; 7844 } 7845 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, l3_ecmp_id)) { 7846 return BCM_E_PARAM; 7847 } 7848 7849 BCM_IF_ERROR_RETURN(bcm_th_switch_agm_info(unit, agm_id, &agm_mnt)); 7850 if ((agm_mnt.attr.agm_type != bcmSwitchAgmTypeL3Ecmp) && 7851 (agm_mnt.attr.agm_type != bcmSwitchAgmTypeL3EcmpOverlay)) { 7852 return BCM_E_PARAM; 7853 } 7854 7855 if (agm_mnt.group_id == (int)l3_ecmp_id) { 7856 return BCM_E_EXISTS; 7857 } 7858 7859 mbm_max = agm_mnt.attr.num_members; 7860 mbm_arr = sal_alloc(mbm_max * sizeof(*mbm_arr), "mbm_arr"); 7861 if (mbm_arr == NULL) { 7862 return BCM_E_MEMORY; 7863 } 7864 7865 rv = bcm_esw_l3_egress_multipath_get(unit, l3_ecmp_id, mbm_max, 7866 mbm_arr, &mbm_cnt); 7867 sal_free(mbm_arr); 7868 if (BCM_FAILURE(rv)) { 7869 return rv; 7870 } 7871 if (mbm_cnt != agm_mnt.attr.num_members) { 7872 LOG_VERBOSE(BSL_LS_BCM_L3, (BSL_META_U(unit, 7873 "AGM %d member cnt %d doesn't match ECMP %d member cnt %d\n"), 7874 agm_id, agm_mnt.attr.num_members, l3_ecmp_id, mbm_cnt)); 7875 return BCM_E_PARAM; 7876 } 7877 7878 #if defined(BCM_TOMAHAWK3_SUPPORT) 7879 if (SOC_IS_TOMAHAWK3(unit)) { 7880 BCM_IF_ERROR_RETURN( 7881 bcm_th3_switch_agm_l3_ecmp_stat_destroy(unit, agm_id)); 7882 BCM_IF_ERROR_RETURN( 7883 bcm_th3_switch_agm_l3_ecmp_stat_create(unit, agm_id, l3_ecmp_id)); 7884 } 7885 #endif /* BCM_TOMAHAWK3_SUPPORT */ 7886 7887 agm_pool_id = agm_mnt.agm_pool_id; 7888 agm_index = agm_mnt.attr.agm_id; 7889 7890 rv = _bcm_th_l3_ecmp_agm_update(unit, l3_ecmp_id, 7891 agm_mnt.attr.agm_type, agm_pool_id, agm_index); 7892 if (BCM_FAILURE(rv)) { 7893 #if defined(BCM_TOMAHAWK3_SUPPORT) 7894 if (SOC_IS_TOMAHAWK3(unit)) { 7895 bcm_th3_switch_agm_l3_ecmp_stat_destroy(unit, agm_id); 7896 } 7897 #endif /* BCM_TOMAHAWK3_SUPPORT */ 7898 return rv; 7899 } 7900 7901 /* in case of changing AGM, detach the old AGM first */ 7902 if (BCM_SUCCESS(bcm_th_switch_agm_id_get_by_group(unit, l3_ecmp_id, 7903 &agm_id_old))) { 7904 BCM_IF_ERROR_RETURN(bcm_th_switch_agm_fwd_grp_update(unit, agm_id_old, 7905 _AGM_GROUP_ID_INVALID)); 7906 } 7907 7908 BCM_IF_ERROR_RETURN(bcm_th_switch_agm_fwd_grp_update(unit, agm_id, 7909 l3_ecmp_id)); 7910 return rv; 7911 } 7912 7913 /* 7914 * Function: 7915 * bcm_th_l3_ecmp_agm_detach 7916 * Purpose: 7917 * Detach a monitor entry from a l3 ecmp group 7918 * Internally, un-map the monitor_entry_id from an aggregation 7919 * group (l3 ecmp group). 7920 */ 7921 int 7922 bcm_th_l3_ecmp_agm_detach(int unit, bcm_if_t l3_ecmp_id, 7923 bcm_switch_agm_id_t agm_id) 7924 { 7925 int rv = BCM_E_NONE; 7926 agm_monitor_t agm_mnt; 7927 7928 /* Validate parameters */ 7929 if (!SOC_UNIT_VALID(unit)) { 7930 return BCM_E_UNIT; 7931 } 7932 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, l3_ecmp_id)) { 7933 return BCM_E_PARAM; 7934 } 7935 7936 BCM_IF_ERROR_RETURN(bcm_th_switch_agm_info(unit, agm_id, &agm_mnt)); 7937 if ((agm_mnt.attr.agm_type != bcmSwitchAgmTypeL3Ecmp) && 7938 (agm_mnt.attr.agm_type != bcmSwitchAgmTypeL3EcmpOverlay)) { 7939 return BCM_E_PARAM; 7940 } 7941 7942 if (agm_mnt.group_id != (int)l3_ecmp_id) { 7943 return BCM_E_NOT_FOUND; 7944 } 7945 7946 BCM_IF_ERROR_RETURN(_bcm_th_l3_ecmp_agm_update(unit, l3_ecmp_id, 7947 agm_mnt.attr.agm_type, 0, 0)); 7948 BCM_IF_ERROR_RETURN(bcm_th_switch_agm_fwd_grp_update(unit, agm_id, -1)); 7949 #if defined(BCM_TOMAHAWK3_SUPPORT) 7950 if (SOC_IS_TOMAHAWK3(unit)) { 7951 BCM_IF_ERROR_RETURN(bcm_th3_switch_agm_l3_ecmp_stat_destroy(unit, agm_id)); 7952 } 7953 #endif /* BCM_TOMAHAWK3_SUPPORT */ 7954 7955 return rv; 7956 } 7957 7958 /* 7959 * Function: 7960 * bcm_th_l3_ecmp_agm_attach_get 7961 * Purpose: 7962 * Retrieve a monitor id attached to a l3 ecmp group. 7963 */ 7964 int 7965 bcm_th_l3_ecmp_agm_attach_get(int unit, bcm_if_t l3_ecmp_id, 7966 bcm_switch_agm_id_t *agm_id) 7967 { 7968 /* Validate parameters */ 7969 if (!SOC_UNIT_VALID(unit)) { 7970 return BCM_E_UNIT; 7971 } 7972 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, l3_ecmp_id)) { 7973 return BCM_E_PARAM; 7974 } 7975 7976 return bcm_th_switch_agm_id_get_by_group(unit, l3_ecmp_id, agm_id); 7977 } 7978 7979 #endif /* BCM_TOMAHAWK_SUPPORT */ 7980 7981 /* 7982 * Function: 7983 * bcm_esw_l3_ecmp_agm_attach 7984 * Purpose: 7985 * Attach already created monitor entry to a l3 ecmp group 7986 * Internally, Map the monitor_entry_id to an aggregation 7987 * group (l3 ecmp group). 7988 * Parameters: 7989 * unit - (IN) bcm device. 7990 * l3_ecmp_id - (IN) ecmp group id. 7991 * agm_id - (IN) id of aggregation group monitoring entry created 7992 * via the bcm_switch_agm_create api. 7993 * Returns: 7994 * BCM_E_NONE: if the attachment is succeed 7995 * BCM_E_PARAM: if the monitor_id is not valid or the monitor 7996 * entry is not created. If the ecmp id is not valid 7997 * BCM_E_FULL: if a monitor entry is already attached to 7998 * BCM_E_PARAM: if number of l3 ecmp member is different from the 7999 * number on the monitor entry 8000 */ 8001 int 8002 bcm_esw_l3_ecmp_agm_attach(int unit, bcm_if_t l3_ecmp_id, 8003 bcm_switch_agm_id_t agm_id) 8004 { 8005 int rv = BCM_E_UNAVAIL; 8006 #if defined(BCM_TOMAHAWK_SUPPORT) 8007 if (soc_feature(unit, soc_feature_agm) && 8008 soc_feature(unit, soc_feature_l3)) { 8009 L3_LOCK(unit); 8010 rv = bcm_th_l3_ecmp_agm_attach(unit, l3_ecmp_id, agm_id); 8011 L3_UNLOCK(unit); 8012 } 8013 #endif /* BCM_TOMAHAWK_SUPPORT */ 8014 return rv; 8015 } 8016 8017 /* 8018 * Function: 8019 * bcm_esw_l3_ecmp_agm_detach 8020 * Purpose: 8021 * Detach a monitor entry from a l3 ecmp group 8022 * Internally, un-map the monitor_entry_id from an aggregation 8023 * group (l3 ecmp group). 8024 * Parameters: 8025 * unit - (IN) bcm device. 8026 * l3_ecmp_id - (IN) ecmp group id. 8027 * agm_id - (IN) id of aggregation group monitoring entry created 8028 * via the bcm_switch_agm_create api. 8029 * Returns: 8030 * BCM_E_NONE: if the enable or disable is succeed 8031 * BCM_E_PARAM: If the ecmp id is not valid 8032 * BCM_E_NOT_FOUND: if no monitor entry is attached to the 8033 * aggregation group. 8034 */ 8035 int 8036 bcm_esw_l3_ecmp_agm_detach(int unit, bcm_if_t l3_ecmp_id, 8037 bcm_switch_agm_id_t agm_id) 8038 { 8039 int rv = BCM_E_UNAVAIL; 8040 #if defined(BCM_TOMAHAWK_SUPPORT) 8041 if (soc_feature(unit, soc_feature_agm) && 8042 soc_feature(unit, soc_feature_l3)) { 8043 L3_LOCK(unit); 8044 rv = bcm_th_l3_ecmp_agm_detach(unit, l3_ecmp_id, agm_id); 8045 L3_UNLOCK(unit); 8046 } 8047 #endif /* BCM_TOMAHAWK_SUPPORT */ 8048 return rv; 8049 } 8050 8051 /* 8052 * Function: 8053 * bcm_esw_l3_ecmp_agm_attach_get 8054 * Purpose: 8055 * Retrieve a monitor id attached to a l3 ecmp group. 8056 * Parameters: 8057 * unit - (IN) bcm device. 8058 * l3_ecmp_id - (IN) ecmp group id. 8059 * agm_id - (IN/OUT) aggregation group monitoring entry. 8060 * Returns: 8061 * BCM_E_NONE: if monitor entry id found 8062 * BCM_E_NOT_FOUND: if no monitor entry is attached to the 8063 * aggregation group. 8064 */ 8065 int 8066 bcm_esw_l3_ecmp_agm_attach_get(int unit, bcm_if_t l3_ecmp_id, 8067 bcm_switch_agm_id_t *agm_id) 8068 { 8069 int rv = BCM_E_UNAVAIL; 8070 #if defined(BCM_TOMAHAWK_SUPPORT) 8071 if (soc_feature(unit, soc_feature_agm) && 8072 soc_feature(unit, soc_feature_l3)) { 8073 L3_LOCK(unit); 8074 rv = bcm_th_l3_ecmp_agm_attach_get(unit, l3_ecmp_id, agm_id); 8075 L3_UNLOCK(unit); 8076 } 8077 #endif /* BCM_TOMAHAWK_SUPPORT */ 8078 return rv; 8079 } 8080 8081 /* 8082 * Function: 8083 * bcm_esw_l3_egress_ecmp_create 8084 * Purpose: 8085 * Create or modify an Egress ECMP forwarding object. 8086 * Parameters: 8087 * unit - (IN) bcm device. 8088 * ecmp - (INOUT) ECMP group info. 8089 * intf_count - (IN) Number of elements in intf_array. 8090 * intf_array - (IN) Array of Egress forwarding objects. 8091 * Returns: 8092 * BCM_E_XXX 8093 */ 8094 int 8095 bcm_esw_l3_egress_ecmp_create(int unit, bcm_l3_egress_ecmp_t *ecmp, 8096 int intf_count, bcm_if_t *intf_array) 8097 { 8098 int rv; 8099 8100 if (ecmp == NULL) { 8101 return (BCM_E_PARAM); 8102 } 8103 if ((soc_feature(unit, soc_feature_ecmp_resilient_hash) || 8104 soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized)) && 8105 (ecmp->flags & BCM_L3_ECMP_RH_REPLACE)) { 8106 int alloc_size, old_intf_count; 8107 bcm_if_t *old_intf_array = NULL; 8108 int i; 8109 8110 /* Input check */ 8111 if (intf_count > 0 && intf_array == NULL) { 8112 return (BCM_E_PARAM); 8113 } 8114 8115 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp->ecmp_intf)) { 8116 return (BCM_E_PARAM); 8117 } 8118 8119 for (i = 0; i < intf_count; i++) { 8120 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, intf_array[i])) { 8121 #if defined(BCM_TOMAHAWK3_SUPPORT) 8122 if (soc_feature(unit, soc_feature_l3_ecmp_hier_tbl)) { 8123 if (!(BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, intf_array[i])) 8124 || !(BCM_XGS3_L3_TBL(unit, ecmp_info).ecmp_mode == 8125 ecmp_mode_hierarchical)) { 8126 return (BCM_E_PARAM); 8127 } 8128 } else 8129 #endif 8130 { 8131 return (BCM_E_PARAM); 8132 } 8133 } 8134 } 8135 8136 /* Allocate interface array */ 8137 alloc_size = sizeof(bcm_if_t) * BCM_XGS3_L3_ECMP_MAX(unit); 8138 old_intf_array = sal_alloc(alloc_size, "old intf array"); 8139 if (NULL == old_intf_array) { 8140 return BCM_E_MEMORY; 8141 } 8142 sal_memset(old_intf_array, 0, alloc_size); 8143 8144 L3_LOCK(unit); 8145 8146 /* Get ECMP group's existing interface array */ 8147 rv = _bcm_esw_l3_egress_ecmp_get(unit, ecmp, BCM_XGS3_L3_ECMP_MAX(unit), 8148 old_intf_array, &old_intf_count, TRUE); 8149 if (BCM_FAILURE(rv)) { 8150 sal_free(old_intf_array); 8151 L3_UNLOCK(unit); 8152 return rv; 8153 } 8154 8155 /* Check if there is room in ECMP group */ 8156 if ((old_intf_count == ecmp->max_paths) && 8157 (intf_count > old_intf_count)) { 8158 sal_free(old_intf_array); 8159 L3_UNLOCK(unit); 8160 return BCM_E_FULL; 8161 } 8162 8163 if (intf_count > ecmp->max_paths) { 8164 sal_free(old_intf_array); 8165 L3_UNLOCK(unit); 8166 return BCM_E_RESOURCE; 8167 } 8168 8169 /* Update ECMP group */ 8170 ecmp->flags |= BCM_L3_REPLACE | BCM_L3_WITH_ID; 8171 rv = _bcm_esw_l3_ecmp_create(unit, ecmp, intf_count, intf_array, 8172 BCM_L3_ECMP_MEMBER_OP_REPLACE, old_intf_count, old_intf_array, 8173 intf_count, NULL); 8174 sal_free(old_intf_array); 8175 L3_UNLOCK(unit); 8176 } else { 8177 8178 8179 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 8180 if (BCM_TH2_ECMP_IS_DLB(unit, ecmp->dynamic_mode)) { 8181 L3_LOCK(unit); 8182 rv = bcm_th2_l3_ecmp_dlb_member_create(unit, ecmp, 8183 intf_array, intf_count); 8184 L3_UNLOCK(unit); 8185 } else 8186 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT */ 8187 { 8188 rv = _bcm_esw_l3_ecmp_create(unit, ecmp, intf_count, 8189 intf_array, BCM_L3_ECMP_MEMBER_OP_SET, 8190 0, NULL, intf_count, NULL); 8191 } 8192 } 8193 8194 return rv; 8195 } 8196 8197 /* 8198 * Function: 8199 * bcm_esw_l3_egress_ecmp_destroy 8200 * Purpose: 8201 * Destroy an Egress ECMP forwarding object. 8202 * Parameters: 8203 * unit - (IN) bcm device. 8204 * ecmp - (IN) ECMP group info. 8205 * Returns: 8206 * BCM_E_XXX 8207 */ 8208 int 8209 bcm_esw_l3_egress_ecmp_destroy(int unit, bcm_l3_egress_ecmp_t *ecmp) 8210 { 8211 int rv = BCM_E_UNAVAIL; 8212 8213 #if defined(BCM_XGS3_SWITCH_SUPPORT) 8214 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 8215 L3_LOCK(unit); 8216 rv = bcm_xgs3_l3_egress_multipath_destroy(unit, ecmp->ecmp_intf); 8217 8218 #ifdef BCM_TRIUMPH3_SUPPORT 8219 if (BCM_SUCCESS(rv)) { 8220 if (soc_feature(unit, soc_feature_ecmp_dlb)) { 8221 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 8222 if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) { 8223 rv = bcm_th2_l3_egress_ecmp_dlb_destroy(unit, ecmp->ecmp_intf); 8224 } else 8225 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT*/ 8226 { 8227 rv = bcm_tr3_l3_egress_ecmp_dlb_destroy(unit, ecmp->ecmp_intf); 8228 } 8229 } 8230 } 8231 #endif /* BCM_TRIUMPH3_SUPPORT */ 8232 8233 #ifdef BCM_TRIDENT2_SUPPORT 8234 if (BCM_SUCCESS(rv)) { 8235 if (soc_feature(unit, soc_feature_ecmp_resilient_hash)) { 8236 #ifdef BCM_TRIDENT3_SUPPORT 8237 int lb_mode = 0; 8238 int ecmp_group; 8239 ecmp_count_entry_t ecmp_count_entry; 8240 8241 if (SOC_IS_TRIDENT3X(unit)) { 8242 if (BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp->ecmp_intf)) { 8243 ecmp_group = ecmp->ecmp_intf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 8244 8245 BCM_IF_ERROR_RETURN(READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, 8246 ecmp_group, &ecmp_count_entry)); 8247 lb_mode = soc_L3_ECMP_COUNTm_field32_get(unit, 8248 &ecmp_count_entry, LB_MODEf); 8249 } 8250 } 8251 #endif 8252 if ( (!(SOC_IS_TRIDENT3X(unit))) 8253 #ifdef BCM_TRIDENT3_SUPPORT 8254 || (lb_mode == BCM_ECMP_LB_MODE_ENHANCED_HASH) 8255 #endif 8256 ) { 8257 rv = bcm_td2_l3_egress_ecmp_rh_destroy(unit, ecmp->ecmp_intf); 8258 } 8259 } 8260 } 8261 #endif /* BCM_TRIDENT2_SUPPORT */ 8262 8263 #ifdef BCM_TOMAHAWK_SUPPORT 8264 if (BCM_SUCCESS(rv) && 8265 soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized)) { 8266 rv = bcm_opt_l3_egress_ecmp_rh_destroy(unit, ecmp->ecmp_intf); 8267 } 8268 if (BCM_SUCCESS(rv) && 8269 (SOC_IS_TRIDENT3X(unit) || soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized))) { 8270 rv = bcm_opt_ecmp_lb_mode_reset(unit, ecmp->ecmp_intf); 8271 } 8272 if (BCM_SUCCESS(rv) && soc_feature(unit, soc_feature_hierarchical_ecmp)) { 8273 BCM_XGS3_L3_ECMP_GROUP_FLAGS_RESET(unit, ecmp->ecmp_intf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit), 8274 BCM_L3_ECMP_UNDERLAY); 8275 BCM_XGS3_L3_ECMP_GROUP_FLAGS_RESET(unit, ecmp->ecmp_intf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit), 8276 BCM_L3_ECMP_OVERLAY); 8277 } 8278 #endif /* BCM_TOMAHAWK_SUPPORT */ 8279 8280 L3_UNLOCK(unit); 8281 8282 } 8283 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 8284 8285 return rv; 8286 } 8287 8288 /* 8289 * Function: 8290 * bcm_esw_l3_egress_ecmp_get 8291 * Purpose: 8292 * Get an Egress ECMP forwarding object. 8293 * Parameters: 8294 * unit - (IN) bcm device. 8295 * ecmp - (INOUT) ECMP group info. 8296 * intf_size - (IN) Size of allocated entries in intf_array. 8297 * intf_array - (OUT) Array of Egress forwarding objects. 8298 * intf_count - (OUT) Number of entries of intf_count actually filled in. 8299 * This will be a value less than or equal to the value. 8300 * passed in as intf_size unless intf_size is 0. If 8301 * intf_size is 0 then intf_array is ignored and 8302 * intf_count is filled in with the number of entries 8303 * that would have been filled into intf_array if 8304 * intf_size was arbitrarily large. 8305 * Returns: 8306 * BCM_E_XXX 8307 */ 8308 int 8309 bcm_esw_l3_egress_ecmp_get(int unit, bcm_l3_egress_ecmp_t *ecmp, int intf_size, 8310 bcm_if_t *intf_array, int *intf_count) 8311 { 8312 int rv = BCM_E_UNAVAIL; 8313 8314 #if defined(BCM_XGS3_SWITCH_SUPPORT) 8315 8316 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 8317 8318 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 8319 if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)){ 8320 SHR_BITDCL *group_bitmap_ptr = NULL; 8321 int ecmp_group_idx = 0; 8322 8323 if ((NULL == ecmp) || 8324 !BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp->ecmp_intf)) { 8325 return (BCM_E_PARAM); 8326 } 8327 8328 ecmp_group_idx = ecmp->ecmp_intf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 8329 8330 group_bitmap_ptr = 8331 BCM_XGS3_L3_ECMP_DLB_MEMBER_GROUP_PTR(unit, ecmp_group_idx); 8332 8333 L3_LOCK(unit); 8334 if (!SHR_BITNULL_RANGE(group_bitmap_ptr, 0, 8335 BCM_XGS3_L3_ECMP_DLB_MAX_PATHS(unit))) { 8336 rv = bcm_th2_l3_ecmp_dlb_member_get(unit, ecmp, intf_size, 8337 intf_array, intf_count); 8338 } else { 8339 rv = _bcm_esw_l3_egress_ecmp_get(unit, ecmp, intf_size, 8340 intf_array, intf_count, TRUE); 8341 } 8342 L3_UNLOCK(unit); 8343 } else 8344 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT*/ 8345 { 8346 rv = _bcm_esw_l3_egress_ecmp_get(unit, ecmp, intf_size, 8347 intf_array, intf_count, TRUE); 8348 } 8349 } 8350 8351 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 8352 8353 return rv; 8354 } 8355 8356 /* 8357 * Function: 8358 * bcm_esw_l3_egress_ecmp_add 8359 * Purpose: 8360 * Add an Egress forwarding object to an Egress ECMP 8361 * forwarding object. 8362 * Parameters: 8363 * unit - (IN) bcm device. 8364 * ecmp - (IN) ECMP group info. 8365 * intf - (IN) L3 interface id pointing to Egress forwarding object. 8366 * Returns: 8367 * BCM_E_XXX 8368 */ 8369 int 8370 bcm_esw_l3_egress_ecmp_add(int unit, bcm_l3_egress_ecmp_t *ecmp, bcm_if_t intf) 8371 { 8372 int rv = BCM_E_UNAVAIL; 8373 8374 #if defined(BCM_XGS3_SWITCH_SUPPORT) 8375 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 8376 int alloc_size; 8377 bcm_if_t *intf_array; 8378 int intf_count; 8379 8380 /* Input check */ 8381 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp->ecmp_intf)) { 8382 return (BCM_E_PARAM); 8383 } 8384 8385 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, intf)) { 8386 #if defined(BCM_RIOT_SUPPORT) || defined(BCM_MULTI_LEVEL_ECMP_SUPPORT) 8387 if (BCMI_L3_ECMP_IS_MULTI_LEVEL(unit)) { 8388 8389 #if defined(BCM_RIOT_SUPPORT) 8390 if (BCMI_RIOT_IS_ENABLED(unit)) { 8391 if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, intf)) { 8392 if (!soc_feature(unit, soc_feature_multi_level_ecmp)) { 8393 return (BCM_E_PARAM); 8394 } 8395 else if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, intf)) { 8396 return (BCM_E_PARAM); 8397 } 8398 } 8399 } else 8400 #endif 8401 { 8402 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, intf)) { 8403 return (BCM_E_PARAM); 8404 } 8405 } 8406 } else 8407 #endif 8408 if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, intf)) { 8409 if (!soc_feature(unit,soc_feature_virtual_port_routing)) { 8410 return (BCM_E_PARAM); 8411 } 8412 } else { 8413 if (!soc_feature(unit, soc_feature_hierarchical_ecmp)) { 8414 return (BCM_E_PARAM); 8415 } else { 8416 /* In Hierarchical/Multi-level ecmp mode, member can 8417 * be another ECMP group 8418 */ 8419 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, intf)) { 8420 return (BCM_E_PARAM); 8421 } 8422 } 8423 } 8424 } 8425 8426 /* Allocate interface array */ 8427 alloc_size = sizeof(bcm_if_t) * BCM_XGS3_L3_ECMP_MAX(unit); 8428 intf_array = sal_alloc(alloc_size, "intf array"); 8429 if (NULL == intf_array) { 8430 return BCM_E_MEMORY; 8431 } 8432 sal_memset(intf_array, 0, alloc_size); 8433 8434 L3_LOCK(unit); 8435 /* Get ECMP group's existing interface array */ 8436 rv = _bcm_esw_l3_egress_ecmp_get(unit, ecmp, BCM_XGS3_L3_ECMP_MAX(unit), 8437 intf_array, &intf_count, TRUE); 8438 if (BCM_FAILURE(rv)) { 8439 sal_free(intf_array); 8440 L3_UNLOCK(unit); 8441 return rv; 8442 } 8443 8444 /* Check if there is room in ECMP group */ 8445 #ifdef BCM_TOMAHAWK_SUPPORT 8446 if (soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized) && 8447 (ecmp->dynamic_mode == BCM_L3_ECMP_DYNAMIC_MODE_RESILIENT)) { 8448 if (intf_count == BCM_XGS3_L3_ECMP_RH_MAX_PATHS(unit)) { 8449 sal_free(intf_array); 8450 L3_UNLOCK(unit); 8451 return BCM_E_RESOURCE; 8452 } 8453 } 8454 #ifdef BCM_TOMAHAWK_SUPPORT 8455 else if ((soc_feature(unit, soc_feature_l3_ecmp_hier_tbl)) && 8456 (ecmp->ecmp_group_flags & BCM_L3_ECMP_OVERLAY) && 8457 (intf_count > 1)) { 8458 sal_free(intf_array); 8459 L3_UNLOCK(unit); 8460 return BCM_E_PARAM; 8461 } 8462 #endif 8463 #endif 8464 8465 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 8466 if (BCM_TH2_ECMP_IS_DLB(unit, ecmp->dynamic_mode)) { 8467 rv = bcm_th2_l3_ecmp_dlb_member_add(unit, ecmp, intf, 8468 intf_array, &intf_count); 8469 } else 8470 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT */ 8471 { 8472 /* Check if there is room in ECMP group */ 8473 if (intf_count == ecmp->max_paths) { 8474 sal_free(intf_array); 8475 L3_UNLOCK(unit); 8476 return BCM_E_FULL; 8477 } 8478 intf_array[intf_count] = intf; 8479 8480 /* Update ECMP group */ 8481 ecmp->flags |= BCM_L3_REPLACE | BCM_L3_WITH_ID; 8482 rv = _bcm_esw_l3_ecmp_create(unit, ecmp, intf_count + 1, 8483 intf_array, BCM_L3_ECMP_MEMBER_OP_ADD, 1, &intf, 8484 intf_count + 1, NULL); 8485 } 8486 sal_free(intf_array); 8487 8488 L3_UNLOCK(unit); 8489 } 8490 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 8491 8492 return rv; 8493 } 8494 8495 /* 8496 * Function: 8497 * bcm_esw_l3_egress_ecmp_delete 8498 * Purpose: 8499 * Delete an Egress forwarding object to an Egress ECMP 8500 * forwarding object. 8501 * Parameters: 8502 * unit - (IN) bcm device. 8503 * ecmp - (IN) ECMP group info. 8504 * intf - (IN) L3 interface id pointing to Egress forwarding object 8505 * Returns: 8506 * BCM_E_XXX 8507 */ 8508 int 8509 bcm_esw_l3_egress_ecmp_delete(int unit, bcm_l3_egress_ecmp_t *ecmp, 8510 bcm_if_t intf) 8511 { 8512 int rv = BCM_E_UNAVAIL; 8513 8514 #if defined(BCM_XGS3_SWITCH_SUPPORT) 8515 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 8516 int alloc_size; 8517 bcm_if_t *intf_array; 8518 int intf_count; 8519 int i, j; 8520 8521 /* Input check */ 8522 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp->ecmp_intf)) { 8523 return (BCM_E_PARAM); 8524 } 8525 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, intf)) { 8526 #if defined(BCM_RIOT_SUPPORT) || defined(BCM_MULTI_LEVEL_ECMP_SUPPORT) 8527 if (BCMI_L3_ECMP_IS_MULTI_LEVEL(unit)) { 8528 8529 #if defined(BCM_RIOT_SUPPORT) 8530 if (BCMI_RIOT_IS_ENABLED(unit)) { 8531 if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, intf)) { 8532 if (!soc_feature(unit, soc_feature_multi_level_ecmp)) { 8533 return (BCM_E_PARAM); 8534 } 8535 else if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, intf)) { 8536 return (BCM_E_PARAM); 8537 } 8538 } 8539 } else 8540 #endif 8541 { 8542 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, intf)) { 8543 return (BCM_E_PARAM); 8544 } 8545 } 8546 } else 8547 #endif 8548 if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, intf)) { 8549 if (!soc_feature(unit,soc_feature_virtual_port_routing)) { 8550 return (BCM_E_PARAM); 8551 } 8552 } else { 8553 if (!soc_feature(unit, soc_feature_hierarchical_ecmp)) { 8554 return (BCM_E_PARAM); 8555 } else { 8556 /* In Hierarchical/Multi-level ecmp mode, member can 8557 * be another ECMP group 8558 */ 8559 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, intf)) { 8560 return (BCM_E_PARAM); 8561 } 8562 } 8563 } 8564 } 8565 8566 /* Allocate interface array */ 8567 alloc_size = sizeof(bcm_if_t) * BCM_XGS3_L3_ECMP_MAX(unit); 8568 intf_array = sal_alloc(alloc_size, "intf array"); 8569 if (NULL == intf_array) { 8570 return BCM_E_MEMORY; 8571 } 8572 sal_memset(intf_array, 0, alloc_size); 8573 L3_LOCK(unit); 8574 8575 /* Get ECMP group's existing interface array */ 8576 rv = _bcm_esw_l3_egress_ecmp_get(unit, ecmp, BCM_XGS3_L3_ECMP_MAX(unit), 8577 intf_array, &intf_count, TRUE); 8578 if (BCM_FAILURE(rv)) { 8579 sal_free(intf_array); 8580 L3_UNLOCK(unit); 8581 return rv; 8582 8583 } 8584 8585 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 8586 if (BCM_TH2_ECMP_IS_DLB(unit, ecmp->dynamic_mode)) { 8587 rv = bcm_th2_l3_ecmp_dlb_member_delete(unit, ecmp, intf, 8588 intf_array, &intf_count); 8589 } else 8590 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT */ 8591 { 8592 /* Search for given intf */ 8593 for (i = 0; i < intf_count; i++) { 8594 if (intf_array[i] == intf) { 8595 break; 8596 } 8597 } 8598 if (i == intf_count) { 8599 /* Not found */ 8600 sal_free(intf_array); 8601 L3_UNLOCK(unit); 8602 return BCM_E_NOT_FOUND; 8603 } 8604 8605 /* Shift remaining elements of intf_array */ 8606 for (j = i; j < intf_count - 1; j++) { 8607 intf_array[j] = intf_array[j+1]; 8608 } 8609 8610 /* Update ECMP group */ 8611 ecmp->flags |= BCM_L3_REPLACE | BCM_L3_WITH_ID; 8612 rv = _bcm_esw_l3_ecmp_create(unit, ecmp, intf_count - 1, 8613 intf_array, BCM_L3_ECMP_MEMBER_OP_DELETE, 1, &intf, 8614 intf_count - 1, NULL); 8615 8616 8617 } 8618 8619 sal_free(intf_array); 8620 8621 L3_UNLOCK(unit); 8622 } 8623 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 8624 8625 return rv; 8626 } 8627 8628 /* 8629 * Function: 8630 * bcm_esw_l3_egress_ecmp_find 8631 * Purpose: 8632 * Find an egress ECMP forwarding object. 8633 * Parameters: 8634 * unit - (IN) bcm device. 8635 * intf_count - (IN) Number of elements in intf_array. 8636 * intf_array - (IN) Array of egress forwarding objects. 8637 * ecmp - (OUT) ECMP group info. 8638 * Returns: 8639 * BCM_E_XXX 8640 */ 8641 int 8642 bcm_esw_l3_egress_ecmp_find(int unit, int intf_count, 8643 bcm_if_t *intf_array, bcm_l3_egress_ecmp_t *ecmp) 8644 { 8645 int rv = BCM_E_UNAVAIL; 8646 #if defined(BCM_RIOT_SUPPORT) || defined(BCM_MULTI_LEVEL_ECMP_SUPPORT) 8647 int grp_idx = 0; 8648 #endif 8649 8650 #if defined(BCM_XGS3_SWITCH_SUPPORT) 8651 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 8652 8653 L3_LOCK(unit); 8654 8655 rv = bcm_xgs3_l3_egress_multipath_find(unit, intf_count, 8656 intf_array, &ecmp->ecmp_intf); 8657 8658 if (BCM_FAILURE(rv)) { 8659 L3_UNLOCK(unit); 8660 return rv; 8661 } 8662 8663 ecmp->flags = 0; 8664 rv = bcm_xgs3_l3_egress_ecmp_max_paths_get(unit, ecmp->ecmp_intf, 8665 &ecmp->max_paths, NULL); 8666 if (BCM_FAILURE(rv)) { 8667 L3_UNLOCK(unit); 8668 return rv; 8669 } 8670 8671 ecmp->ecmp_group_flags = 0; 8672 ecmp->dynamic_mode = 0; 8673 ecmp->dynamic_size = 0; 8674 ecmp->dynamic_age = 0; 8675 ecmp->dynamic_load_exponent = 0; 8676 ecmp->dynamic_expected_load_exponent = 0; 8677 ecmp->dgm.threshold = 0; 8678 ecmp->dgm.cost = 0; 8679 ecmp->dgm.bias = 0; 8680 8681 #if defined(BCM_RIOT_SUPPORT) || defined(BCM_MULTI_LEVEL_ECMP_SUPPORT) 8682 /* Get ecmp group index. */ 8683 grp_idx = ecmp->ecmp_intf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 8684 8685 /* 8686 * we can look into the ecmp_grp index to know if this 8687 * is overlay entry or underlay entry. 8688 */ 8689 if (BCMI_L3_ECMP_IS_MULTI_LEVEL(unit)) { 8690 8691 if (grp_idx < BCMI_L3_ECMP_OVERLAY_ENTRIES(unit)) { 8692 8693 ecmp->ecmp_group_flags |= BCM_L3_ECMP_OVERLAY; 8694 } 8695 } 8696 #endif 8697 8698 #ifdef BCM_TRIUMPH3_SUPPORT 8699 if (soc_feature(unit, soc_feature_ecmp_dlb)) { 8700 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 8701 if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) { 8702 rv = bcm_th2_l3_egress_ecmp_dlb_get(unit, ecmp); 8703 } else 8704 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT*/ 8705 { 8706 rv = bcm_tr3_l3_egress_ecmp_dlb_get(unit, ecmp); 8707 } 8708 if (BCM_FAILURE(rv)) { 8709 L3_UNLOCK(unit); 8710 return rv; 8711 } 8712 } 8713 #endif /* BCM_TRIUMPH3_SUPPORT */ 8714 8715 #ifdef BCM_TRIDENT2_SUPPORT 8716 if (soc_feature(unit, soc_feature_ecmp_resilient_hash)) { 8717 rv = bcm_td2_l3_egress_ecmp_rh_get(unit, ecmp); 8718 if (BCM_FAILURE(rv)) { 8719 L3_UNLOCK(unit); 8720 return rv; 8721 } 8722 } 8723 #endif /* BCM_TRIUMPH3_SUPPORT */ 8724 8725 #ifdef BCM_TOMAHAWK_SUPPORT 8726 /* Get ECMP Level flags */ 8727 if (soc_feature(unit, soc_feature_hierarchical_ecmp)) { 8728 if (BCM_XGS3_L3_ECMP_GROUP_FLAGS_ISSET(unit, 8729 (ecmp->ecmp_intf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit)), 8730 BCM_L3_ECMP_OVERLAY)) { 8731 ecmp->ecmp_group_flags |= BCM_L3_ECMP_OVERLAY; 8732 } 8733 if (BCM_XGS3_L3_ECMP_GROUP_FLAGS_ISSET(unit, 8734 (ecmp->ecmp_intf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit)), 8735 BCM_L3_ECMP_UNDERLAY)) { 8736 ecmp->ecmp_group_flags |= BCM_L3_ECMP_UNDERLAY; 8737 } 8738 } 8739 8740 if (soc_feature(unit, soc_feature_ecmp_resilient_hash_optimized)) { 8741 rv = bcm_opt_l3_egress_ecmp_lb_get(unit, ecmp); 8742 if (BCM_FAILURE(rv)) { 8743 L3_UNLOCK(unit); 8744 return rv; 8745 } 8746 } 8747 #endif /* BCM_TOMAHAWK_SUPPORT */ 8748 8749 L3_UNLOCK(unit); 8750 } 8751 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 8752 8753 return rv; 8754 } 8755 8756 /* 8757 * Function: 8758 * bcm_esw_l3_egress_ecmp_traverse 8759 * Purpose: 8760 * Goes through ECMP egress objects table and runs the user callback 8761 * function at each ECMP egress objects entry passing back the 8762 * information for that ECMP object. 8763 * Parameters: 8764 * unit - (IN) bcm device. 8765 * trav_fn - (IN) Callback function. 8766 * user_data - (IN) User data to be passed to callback function. 8767 * Returns: 8768 * BCM_E_XXX 8769 */ 8770 int 8771 bcm_esw_l3_egress_ecmp_traverse(int unit, 8772 bcm_l3_egress_ecmp_traverse_cb trav_fn, 8773 void *user_data) 8774 { 8775 int rv = BCM_E_UNAVAIL; 8776 8777 #if defined(BCM_XGS3_SWITCH_SUPPORT) 8778 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 8779 L3_LOCK(unit); 8780 rv = bcm_xgs3_l3_egress_ecmp_traverse(unit, trav_fn, user_data); 8781 L3_UNLOCK(unit); 8782 } 8783 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 8784 8785 return rv; 8786 } 8787 8788 /* 8789 * Function: 8790 * bcm_esw_l3_egress_ecmp_member_status_set 8791 * Purpose: 8792 * Set ECMP dynamic load balancing member status. 8793 * Parameters: 8794 * unit - (IN) Unit number. 8795 * intf - (IN) L3 Interface ID pointing to an Egress forwarding object. 8796 * status - (IN) ECMP member status. 8797 * Returns: 8798 * BCM_E_XXX 8799 */ 8800 int 8801 bcm_esw_l3_egress_ecmp_member_status_set( 8802 int unit, 8803 bcm_if_t intf, 8804 int status) 8805 { 8806 int rv = BCM_E_UNAVAIL; 8807 8808 #ifdef BCM_TRIUMPH3_SUPPORT 8809 if (soc_feature(unit, soc_feature_ecmp_dlb)) { 8810 L3_LOCK(unit); 8811 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 8812 if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) { 8813 rv = bcm_th2_l3_egress_ecmp_member_status_set(unit, intf, status); 8814 } else 8815 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT*/ 8816 { 8817 rv = bcm_tr3_l3_egress_ecmp_member_status_set(unit, intf, status); 8818 } 8819 L3_UNLOCK(unit); 8820 } 8821 #endif /* BCM_TRIUMPH3_SUPPORT */ 8822 8823 return rv; 8824 } 8825 8826 /* 8827 * Function: 8828 * bcm_esw_l3_egress_ecmp_member_status_get 8829 * Purpose: 8830 * Get ECMP member status. 8831 * Parameters: 8832 * unit - (IN) Unit number. 8833 * intf - (IN) L3 Interface ID pointing to an Egress forwarding object. 8834 * status - (OUT) ECMP member status. 8835 * Returns: 8836 * BCM_E_XXX 8837 */ 8838 int 8839 bcm_esw_l3_egress_ecmp_member_status_get( 8840 int unit, 8841 bcm_if_t intf, 8842 int *status) 8843 { 8844 int rv = BCM_E_UNAVAIL; 8845 8846 #ifdef BCM_TRIUMPH3_SUPPORT 8847 if (soc_feature(unit, soc_feature_ecmp_dlb)) { 8848 L3_LOCK(unit); 8849 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 8850 if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) { 8851 rv = bcm_th2_l3_egress_ecmp_member_status_get(unit, intf, status); 8852 } else 8853 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT*/ 8854 { 8855 rv = bcm_tr3_l3_egress_ecmp_member_status_get(unit, intf, status); 8856 } 8857 L3_UNLOCK(unit); 8858 } 8859 #endif /* BCM_TRIUMPH3_SUPPORT */ 8860 8861 return rv; 8862 } 8863 8864 /* 8865 * Function: 8866 * bcm_esw_l3_egress_ecmp_ethertype_set 8867 * Purpose: 8868 * Set the Ethertypes that are eligible or ineligible for 8869 * ECMP dynamic load balancing or resilient hashing. 8870 * Parameters: 8871 * unit - (IN) Unit number. 8872 * flags - (IN) BCM_L3_ECMP_DYNAMIC_ETHERTYPE_xxx flags. 8873 * ethertype_count - (IN) Number of elements in ethertype_array. 8874 * ethertype_array - (IN) Array of Ethertypes. 8875 * Returns: 8876 * BCM_E_XXX 8877 */ 8878 int 8879 bcm_esw_l3_egress_ecmp_ethertype_set( 8880 int unit, 8881 uint32 flags, 8882 int ethertype_count, 8883 int *ethertype_array) 8884 { 8885 int rv; 8886 int i; 8887 8888 if ((ethertype_count > 0) && (NULL == ethertype_array)) { 8889 return BCM_E_PARAM; 8890 } 8891 for (i = 0; i < ethertype_count; i++) { 8892 if (ethertype_array[i] < 0 || ethertype_array[i] > 0xffff) { 8893 return BCM_E_PARAM; 8894 } 8895 } 8896 8897 L3_LOCK(unit); 8898 8899 rv = BCM_E_UNAVAIL; 8900 8901 if (flags & BCM_L3_ECMP_DYNAMIC_ETHERTYPE_RESILIENT) { 8902 #ifdef BCM_TRIDENT2_SUPPORT 8903 if (soc_feature(unit, soc_feature_ecmp_resilient_hash)) { 8904 rv = bcm_td2_l3_egress_ecmp_rh_ethertype_set(unit, flags, 8905 ethertype_count, ethertype_array); 8906 if (BCM_FAILURE(rv)) { 8907 L3_UNLOCK(unit); 8908 return rv; 8909 } 8910 } 8911 #endif /* BCM_TRIDENT2_SUPPORT */ 8912 } else { 8913 #ifdef BCM_TRIUMPH3_SUPPORT 8914 if (soc_feature(unit, soc_feature_ecmp_dlb)) { 8915 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 8916 if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) { 8917 rv = bcm_th2_l3_egress_ecmp_dlb_ethertype_set(unit, flags, 8918 ethertype_count, ethertype_array); 8919 } else 8920 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT */ 8921 { 8922 rv = bcm_tr3_l3_egress_ecmp_dlb_ethertype_set(unit, flags, 8923 ethertype_count, ethertype_array); 8924 } 8925 if (BCM_FAILURE(rv)) { 8926 L3_UNLOCK(unit); 8927 return rv; 8928 } 8929 } 8930 #endif /* BCM_TRIUMPH3_SUPPORT */ 8931 } 8932 8933 L3_UNLOCK(unit); 8934 8935 return rv; 8936 } 8937 8938 /* 8939 * Function: 8940 * bcm_esw_l3_egress_ecmp_ethertype_get 8941 * Purpose: 8942 * Get the Ethertypes that are eligible or ineligible for 8943 * ECMP dynamic load balancing. 8944 * Parameters: 8945 * unit - (IN) Unit number. 8946 * flags - (INOUT) BCM_L3_ECMP_DYNAMIC_ETHERTYPE_xxx flags. 8947 * ethertype_max - (IN) Number of elements in ethertype_array. 8948 * ethertype_array - (OUT) Array of Ethertypes. 8949 * ethertype_count - (OUT) Number of elements returned in ethertype_array. 8950 * Returns: 8951 * BCM_E_XXX 8952 */ 8953 int 8954 bcm_esw_l3_egress_ecmp_ethertype_get( 8955 int unit, 8956 uint32 *flags, 8957 int ethertype_max, 8958 int *ethertype_array, 8959 int *ethertype_count) 8960 { 8961 int rv; 8962 8963 L3_LOCK(unit); 8964 8965 rv = BCM_E_UNAVAIL; 8966 8967 if (*flags & BCM_L3_ECMP_DYNAMIC_ETHERTYPE_RESILIENT) { 8968 #ifdef BCM_TRIDENT2_SUPPORT 8969 if (soc_feature(unit, soc_feature_ecmp_resilient_hash)) { 8970 rv = bcm_td2_l3_egress_ecmp_rh_ethertype_get(unit, flags, 8971 ethertype_max, ethertype_array, ethertype_count); 8972 if (BCM_FAILURE(rv)) { 8973 L3_UNLOCK(unit); 8974 return rv; 8975 } 8976 } 8977 #endif /* BCM_TRIDENT2_SUPPORT */ 8978 } else { 8979 #ifdef BCM_TRIUMPH3_SUPPORT 8980 if (soc_feature(unit, soc_feature_ecmp_dlb)) { 8981 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 8982 if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) { 8983 rv = bcm_th2_l3_egress_ecmp_dlb_ethertype_get(unit, flags, 8984 ethertype_max, ethertype_array, ethertype_count); 8985 } else 8986 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT*/ 8987 { 8988 rv = bcm_tr3_l3_egress_ecmp_dlb_ethertype_get(unit, flags, 8989 ethertype_max, ethertype_array, ethertype_count); 8990 } 8991 if (BCM_FAILURE(rv)) { 8992 L3_UNLOCK(unit); 8993 return rv; 8994 } 8995 } 8996 #endif /* BCM_TRIUMPH3_SUPPORT */ 8997 } 8998 8999 L3_UNLOCK(unit); 9000 return rv; 9001 } 9002 9003 /* 9004 * Function: 9005 * bcm_esw_l3_ip6_prefix_map_get 9006 * Purpose: 9007 * Get a list of IPv6 96 bit prefixes which are mapped to ipv4 lookup 9008 * space. 9009 * Parameters: 9010 * unit - (IN) bcm device. 9011 * map_size - (IN) Size of allocated entries in ip6_array. 9012 * ip6_array - (OUT) Array of mapped prefixes. 9013 * ip6_count - (OUT) Number of entries of ip6_array actually filled in. 9014 * This will be a value less than or equal to the value. 9015 * passed in as map_size unless map_size is 0. If 9016 * map_size is 0 then ip6_array is ignored and 9017 * ip6_count is filled in with the number of entries 9018 * that would have been filled into ip6_array if 9019 * map_size was arbitrarily large. 9020 * Returns: 9021 * BCM_E_XXX 9022 */ 9023 int 9024 bcm_esw_l3_ip6_prefix_map_get(int unit, int map_size, 9025 bcm_ip6_t *ip6_array, int *ip6_count) 9026 { 9027 int rv = BCM_E_UNAVAIL; 9028 9029 /* Check that device supports ipv6. */ 9030 if (BCM_L3_NO_IP6_SUPPORT(unit, BCM_L3_IP6)) { 9031 return (BCM_E_UNAVAIL); 9032 } 9033 #if defined(BCM_XGS3_SWITCH_SUPPORT) 9034 L3_LOCK(unit); 9035 rv = bcm_xgs3_l3_ip6_prefix_map_get(unit, map_size, 9036 ip6_array, ip6_count); 9037 L3_UNLOCK(unit); 9038 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 9039 return rv; 9040 } 9041 /* 9042 * Function: 9043 * bcm_esw_l3_ip6_prefix_map_add 9044 * Purpose: 9045 * Create an IPv6 prefix map into IPv4 entry. In case Ipv6 traffic 9046 * destination or source IP address matches upper 96 bits of 9047 * translation entry. traffic will be routed/switched based on 9048 * lower 32 bits of destination/source IP address treated as IPv4 address. 9049 * Parameters: 9050 * unit - (IN) bcm device. 9051 * ip6_addr - (IN) New IPv6 translation address. 9052 * Returns: 9053 * BCM_E_XXX 9054 */ 9055 int 9056 bcm_esw_l3_ip6_prefix_map_add(int unit, bcm_ip6_t ip6_addr) 9057 { 9058 int rv = BCM_E_UNAVAIL; 9059 9060 /* Check that device supports ipv6. */ 9061 if (BCM_L3_NO_IP6_SUPPORT(unit, BCM_L3_IP6)) { 9062 return (BCM_E_UNAVAIL); 9063 } 9064 #if defined(BCM_XGS3_SWITCH_SUPPORT) 9065 L3_LOCK(unit); 9066 rv = bcm_xgs3_l3_ip6_prefix_map_add(unit, ip6_addr); 9067 L3_UNLOCK(unit); 9068 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 9069 return (rv); 9070 } 9071 9072 /* 9073 * Function: 9074 * bcm_esw_l3_ip6_prefix_map_delete 9075 * Purpose: 9076 * Destroy an IPv6 prefix map entry. 9077 * Parameters: 9078 * unit - (IN) bcm device. 9079 * ip6_addr - (IN) IPv6 translation address. 9080 * Returns: 9081 * BCM_E_XXX 9082 */ 9083 int 9084 bcm_esw_l3_ip6_prefix_map_delete(int unit, bcm_ip6_t ip6_addr) 9085 { 9086 int rv = BCM_E_UNAVAIL; 9087 9088 /* Check that device supports ipv6. */ 9089 if (BCM_L3_NO_IP6_SUPPORT(unit, BCM_L3_IP6)) { 9090 return (BCM_E_UNAVAIL); 9091 } 9092 #if defined(BCM_XGS3_SWITCH_SUPPORT) 9093 L3_LOCK(unit); 9094 rv = bcm_xgs3_l3_ip6_prefix_map_delete(unit, ip6_addr); 9095 L3_UNLOCK(unit); 9096 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 9097 return (rv); 9098 } 9099 9100 /* 9101 * Function: 9102 * bcm_esw_l3_ip6_prefix_map_delete_all 9103 * Purpose: 9104 * Flush all IPv6 prefix maps. 9105 * Parameters: 9106 * unit - (IN) bcm device. 9107 * Returns: 9108 * BCM_E_XXX 9109 */ 9110 int 9111 bcm_esw_l3_ip6_prefix_map_delete_all(int unit) 9112 { 9113 int rv = BCM_E_UNAVAIL; 9114 9115 /* Check that device supports ipv6. */ 9116 if (BCM_L3_NO_IP6_SUPPORT(unit, BCM_L3_IP6)) { 9117 return (BCM_E_UNAVAIL); 9118 } 9119 9120 #if defined(BCM_XGS3_SWITCH_SUPPORT) 9121 L3_LOCK(unit); 9122 rv = bcm_xgs3_l3_ip6_prefix_map_delete_all(unit); 9123 L3_UNLOCK(unit); 9124 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 9125 return (rv); 9126 } 9127 9128 /* 9129 * Function: 9130 * bcm_esw_l3_vrrp_add 9131 * Purpose: 9132 * Add VRID for the given VSI. Adding a VRID using this API means 9133 * the physical node has become the master for the virtual router 9134 * Parameters: 9135 * unit - (IN) Unit number. 9136 * vlan - (IN) VLAN/VSI 9137 * vrid - (IN) VRID - Virtual router ID to be added 9138 * Returns: 9139 * BCM_E_xxx 9140 * Notes: 9141 */ 9142 int 9143 bcm_esw_l3_vrrp_add(int unit, bcm_vlan_t vlan, uint32 vrid) 9144 { 9145 bcm_l2_addr_t l2addr; /* Layer 2 address for interface. */ 9146 int rv; /* Operation return status. */ 9147 bcm_mac_t mac = {0x00, 0x00, 0x5e, 0x00, 0x01, 0x00};/* Mac address.*/ 9148 9149 if (!BCM_VLAN_VALID(vlan)) { 9150 return (BCM_E_PARAM); 9151 } 9152 9153 if (vrid > 0xff) { 9154 return (BCM_E_PARAM); 9155 } 9156 mac[5] = vrid; 9157 9158 /* Set l2 address info. */ 9159 bcm_l2_addr_t_init(&l2addr, mac, vlan); 9160 9161 #if defined(BCM_MIRAGE_SUPPORT) 9162 if (soc_feature(unit, soc_feature_fp_routing_mirage)) { 9163 /* Set l2 entry flags. */ 9164 l2addr.flags = BCM_L2_STATIC | BCM_L2_REPLACE_DYNAMIC; 9165 9166 /* Set l2 entry port to CPU port. */ 9167 l2addr.port = BCM_MIRAGE_L3_PORT; 9168 } else 9169 #endif /* BCM_MIRAGE_SUPPORT */ 9170 { 9171 /* Set l2 entry flags. */ 9172 l2addr.flags = BCM_L2_L3LOOKUP | BCM_L2_STATIC | BCM_L2_REPLACE_DYNAMIC; 9173 9174 /* Set l2 entry port to CPU port. */ 9175 l2addr.port = CMIC_PORT(unit); 9176 } 9177 9178 /* Set l2 entry module id to local module. */ 9179 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &l2addr.modid)); 9180 9181 /* Overwrite existing entry if any. */ 9182 bcm_esw_l2_addr_delete(unit, mac, vlan); 9183 9184 /* Add entry to l2 table. */ 9185 rv = bcm_esw_l2_addr_add(unit, &l2addr); 9186 9187 return rv; 9188 } 9189 9190 /* 9191 * Function: 9192 * bcm_esw_l3_vrrp_delete 9193 * Purpose: 9194 * Delete VRID for a particulat VLAN/VSI 9195 * Parameters: 9196 * unit - (IN) Unit number. 9197 * vlan - (IN) VLAN/VSI 9198 * vrid - (IN) VRID - Virtual router ID to be deleted 9199 * Returns: 9200 * BCM_E_xxx 9201 * Notes: 9202 */ 9203 int 9204 bcm_esw_l3_vrrp_delete(int unit, bcm_vlan_t vlan, uint32 vrid) 9205 { 9206 bcm_l2_addr_t l2addr; /* Layer 2 address for interface. */ 9207 int rv; /* Operation return status. */ 9208 bcm_mac_t mac = {0x00, 0x00, 0x5e, 0x00, 0x01, 0x00};/* Mac address.*/ 9209 9210 if (!BCM_VLAN_VALID(vlan)) { 9211 return (BCM_E_PARAM); 9212 } 9213 9214 if (vrid > 0xff) { 9215 return (BCM_E_PARAM); 9216 } 9217 mac[5] = vrid; 9218 9219 /* Set l2 address info. */ 9220 bcm_l2_addr_t_init(&l2addr, mac, vlan); 9221 9222 /* Overwrite existing entry if any. */ 9223 rv = bcm_esw_l2_addr_delete(unit, mac, vlan); 9224 return rv; 9225 } 9226 9227 /* 9228 * Function: 9229 * bcm_esw_l3_vrrp_delete_all 9230 * Purpose: 9231 * Delete all the VRIDs for a particular VLAN/VSI 9232 * Parameters: 9233 * unit - (IN) Unit number. 9234 * vlan - (IN) VLAN/VSI 9235 * Returns: 9236 * BCM_E_xxx 9237 * Notes: 9238 */ 9239 int 9240 bcm_esw_l3_vrrp_delete_all(int unit, bcm_vlan_t vlan) 9241 { 9242 int idx; /* vr id iteration index. */ 9243 int rv; /* Operation return status. */ 9244 9245 if (!BCM_VLAN_VALID(vlan)) { 9246 return (BCM_E_PARAM); 9247 } 9248 9249 for (idx = 0; idx < 0x100; idx++) { 9250 rv = bcm_esw_l3_vrrp_delete(unit, vlan, idx); 9251 if (BCM_FAILURE(rv) && (BCM_E_NOT_FOUND != rv)) { 9252 return (rv); 9253 } 9254 } 9255 return (BCM_E_NONE); 9256 } 9257 9258 9259 /* 9260 * Function: 9261 * bcm_esw_l3_vrrp_get 9262 * Purpose: 9263 * Get all the VRIDs for which the physical node is master for 9264 * the virtual routers on the given VLAN/VSI 9265 * Parameters: 9266 * unit - (IN) Unit number. 9267 * vlan - (IN) VLAN/VSI 9268 * alloc_size - (IN) Size of vrid_array 9269 * vrid_array - (OUT) Pointer to the array to which the VRIDs will be copied 9270 * count - (OUT) Number of VRIDs copied 9271 * Returns: 9272 * BCM_E_xxx 9273 * Notes: 9274 */ 9275 int 9276 bcm_esw_l3_vrrp_get(int unit, bcm_vlan_t vlan, int alloc_size, 9277 int *vrid_array, int *count) 9278 { 9279 bcm_l2_addr_t l2addr; /* Layer 2 address for interface. */ 9280 int idx; /* vr id iteration index. */ 9281 int tmp_cnt; /* Valie entry count. */ 9282 int rv; /* Operation return status. */ 9283 bcm_mac_t mac = {0x00, 0x00, 0x5e, 0x00, 0x01, 0x00};/* Mac address.*/ 9284 9285 if (!BCM_VLAN_VALID(vlan)) { 9286 return (BCM_E_PARAM); 9287 } 9288 9289 if (NULL == count) { 9290 return (BCM_E_PARAM); 9291 } 9292 9293 tmp_cnt = 0; 9294 for (idx = 0; idx < 0x100; idx++) { 9295 if ( alloc_size > tmp_cnt) { 9296 mac[5] = idx; 9297 9298 /* Set l2 address info. */ 9299 bcm_l2_addr_t_init(&l2addr, mac, vlan); 9300 9301 /* Overwrite existing entry if any. */ 9302 rv = bcm_esw_l2_addr_get(unit, mac, vlan, &l2addr); 9303 if (BCM_SUCCESS(rv)) { 9304 if (NULL != vrid_array) { 9305 vrid_array[tmp_cnt] = idx; 9306 } 9307 tmp_cnt++; 9308 } 9309 } 9310 } 9311 *count = tmp_cnt; 9312 return (BCM_E_NONE); 9313 } 9314 9315 9316 #if defined(BCM_TRIUMPH2_SUPPORT) 9317 #define BCM_VRF_STAT_VALID(unit, vrf) \ 9318 if (!soc_feature(unit, soc_feature_gport_service_counters)) { \ 9319 return BCM_E_UNAVAIL; \ 9320 } else if (((vrf) > SOC_VRF_MAX(unit)) || \ 9321 ((vrf) < BCM_L3_VRF_DEFAULT)) { return (BCM_E_PARAM); } 9322 9323 STATIC int 9324 _bcm_vrf_flex_stat_hw_index_set(int unit, _bcm_flex_stat_handle_t fsh, 9325 int fs_idx, void *cookie) 9326 { 9327 uint32 handle = _BCM_FLEX_STAT_HANDLE_WORD_GET(fsh, 0); 9328 COMPILER_REFERENCE(cookie); 9329 if (SOC_MEM_FIELD_VALID(unit, VRFm, USE_SERVICE_CTR_IDXf)) { 9330 BCM_IF_ERROR_RETURN( 9331 soc_mem_field32_modify(unit, VRFm, handle, 9332 USE_SERVICE_CTR_IDXf, (fs_idx!=0) ? 1:0)); 9333 } 9334 return soc_mem_field32_modify(unit, VRFm, handle, 9335 SERVICE_CTR_IDXf, fs_idx); 9336 } 9337 9338 STATIC _bcm_flex_stat_t 9339 _bcm_esw_l3_vrf_stat_to_flex_stat(bcm_l3_vrf_stat_t stat) 9340 { 9341 _bcm_flex_stat_t flex_stat; 9342 9343 switch (stat) { 9344 case bcmL3VrfStatIngressPackets: 9345 flex_stat = _bcmFlexStatIngressPackets; 9346 break; 9347 case bcmL3VrfStatIngressBytes: 9348 flex_stat = _bcmFlexStatIngressBytes; 9349 break; 9350 default: 9351 flex_stat = _bcmFlexStatNum; 9352 } 9353 9354 return flex_stat; 9355 } 9356 9357 /* Requires "idx" variable */ 9358 #define BCM_VRF_STAT_ARRAY_VALID(unit, nstat, value_arr) \ 9359 for (idx = 0; idx < nstat; idx++) { \ 9360 if (NULL == value_arr + idx) { \ 9361 return (BCM_E_PARAM); \ 9362 } \ 9363 } 9364 9365 STATIC int 9366 _bcm_l3_vrf_stat_array_convert(int unit, int nstat, 9367 bcm_l3_vrf_stat_t *stat_arr, 9368 _bcm_flex_stat_t *fs_arr) 9369 { 9370 int idx; 9371 9372 if ((nstat <= 0) || (nstat > _bcmFlexStatEgressPackets)) { 9373 /* VRF only has ingress support, so the number of ingress types 9374 * is the first egress type. */ 9375 return BCM_E_PARAM; 9376 } 9377 9378 if (NULL == stat_arr) { 9379 return (BCM_E_PARAM); 9380 } 9381 9382 for (idx = 0; idx < nstat; idx++) { 9383 fs_arr[idx] = _bcm_esw_l3_vrf_stat_to_flex_stat(stat_arr[idx]); 9384 } 9385 return BCM_E_NONE; 9386 } 9387 #endif /* BCM_TRIUMPH2_SUPPORT */ 9388 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 9389 /* 9390 * Function: 9391 * _bcm_esw_l3_vrf_stat_get_table_info 9392 * Description: 9393 * Provides relevant flex table information(table-name,index with 9394 * direction) for given VRF(Virtual Router Interface) id. 9395 * 9396 * Parameters: 9397 * unit - (IN) unit number 9398 * vrf - (IN) VRF(Virtual Router Interface) id 9399 * num_of_tables - (OUT) Number of flex counter tables 9400 * table_info - (OUT) Flex counter tables information 9401 * 9402 * Return Value: 9403 * BCM_E_XXX 9404 * Notes: 9405 */ 9406 static 9407 bcm_error_t _bcm_esw_l3_vrf_stat_get_table_info( 9408 int unit, 9409 bcm_vrf_t vrf, 9410 uint32 *num_of_tables, 9411 bcm_stat_flex_table_info_t *table_info) 9412 { 9413 (*num_of_tables)=0; 9414 9415 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 9416 return BCM_E_UNAVAIL; 9417 } 9418 9419 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 9420 if (soc_feature(unit, soc_feature_l3_256_defip_table) || 9421 soc_feature(unit, soc_feature_no_vrf_stats)) { 9422 return BCM_E_UNAVAIL; /* VRF stats not valid for Ranger & Ranger + */ 9423 } 9424 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_GREYHOUND2_SUPPORT*/ 9425 9426 #if defined(BCM_TRIUMPH2_SUPPORT) 9427 L3_INIT(unit); 9428 if ((vrf > SOC_VRF_MAX(unit)) || (vrf < BCM_L3_VRF_DEFAULT)) { 9429 return (BCM_E_PARAM); 9430 } 9431 #if defined (BCM_TRIDENT3_SUPPORT) 9432 if (SOC_IS_TRIDENT3X(unit)){ 9433 table_info[*num_of_tables].table = VRF_ATTRS_2m; 9434 } else 9435 #endif 9436 { 9437 table_info[*num_of_tables].table=VRFm; 9438 } 9439 table_info[*num_of_tables].index=vrf; 9440 table_info[*num_of_tables].direction=bcmStatFlexDirectionIngress; 9441 (*num_of_tables)++; 9442 return BCM_E_NONE; 9443 #else 9444 return BCM_E_UNAVAIL; 9445 #endif /* BCM_TRIUMPH2_SUPPORT */ 9446 } 9447 #endif 9448 9449 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 9450 /* 9451 * Function: 9452 * _bcm_esw_l3_vrf_stat_attach 9453 * Description: 9454 * Attach counters entries to the given VRF 9455 * 9456 * Parameters: 9457 * unit - (IN) unit number 9458 * vrf - (IN) Virtual router instance 9459 * stat_counter_id - (IN) Stat Counter ID. 9460 * 9461 * Return Value: 9462 * BCM_E_XXX 9463 * Notes: 9464 */ 9465 9466 STATIC bcm_error_t _bcm_esw_l3_vrf_stat_attach( 9467 int unit, 9468 bcm_vrf_t vrf, 9469 uint32 stat_counter_id) 9470 { 9471 soc_mem_t table=0; 9472 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 9473 uint32 pool_number=0; 9474 uint32 base_index=0; 9475 bcm_stat_flex_mode_t offset_mode=0; 9476 bcm_stat_object_t object=bcmStatObjectIngPort; 9477 bcm_stat_group_mode_t group_mode= bcmStatGroupModeSingle; 9478 uint32 count=0; 9479 uint32 actual_num_tables=0; 9480 uint32 num_of_tables=0; 9481 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 9482 9483 _bcm_esw_stat_get_counter_id_info( 9484 unit, stat_counter_id, 9485 &group_mode,&object,&offset_mode,&pool_number,&base_index); 9486 BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_object(unit,object,&direction)); 9487 BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit,group_mode)); 9488 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_table_info( 9489 unit,object,1,&actual_num_tables,&table,&direction)); 9490 9491 BCM_IF_ERROR_RETURN(_bcm_esw_l3_vrf_stat_get_table_info( 9492 unit, vrf,&num_of_tables,&table_info[0])); 9493 for (count=0; count < num_of_tables ; count++) { 9494 if ((table_info[count].direction == direction) && 9495 (table_info[count].table == table) ) { 9496 if (direction == bcmStatFlexDirectionIngress) { 9497 return _bcm_esw_stat_flex_attach_ingress_table_counters( 9498 unit, 9499 table_info[count].table, 9500 table_info[count].index, 9501 offset_mode, 9502 base_index, 9503 pool_number); 9504 } else { 9505 return _bcm_esw_stat_flex_attach_egress_table_counters( 9506 unit, 9507 table_info[count].table, 9508 table_info[count].index, 9509 0, 9510 offset_mode, 9511 base_index, 9512 pool_number); 9513 } 9514 } 9515 } 9516 return BCM_E_NOT_FOUND; 9517 } 9518 #endif 9519 9520 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 9521 /* 9522 * Function: 9523 * _tr2_l3_vrf_stat_attach 9524 * Description: 9525 * Attach counters entries to the given VRF for TR2/Trident device 9526 * 9527 * Parameters: 9528 * unit - (IN) unit number 9529 * vrf - (IN) Virtual router instance 9530 * stat_counter_id - (IN) Stat Counter ID. 9531 * 9532 * Return Value: 9533 * BCM_E_XXX 9534 * Notes: 9535 */ 9536 9537 STATIC bcm_error_t _tr2_l3_vrf_stat_attach( 9538 int unit, 9539 bcm_vrf_t vrf, 9540 uint32 stat_counter_id, 9541 int enable) 9542 { 9543 9544 _bcm_flex_stat_type_t fs_type; 9545 uint32 fs_inx; 9546 int rv; 9547 9548 fs_type = _BCM_FLEX_STAT_TYPE(stat_counter_id); 9549 fs_inx = _BCM_FLEX_STAT_COUNT_INX(stat_counter_id); 9550 9551 if (!((fs_type == _bcmFlexStatTypeVrf) && fs_inx)) { 9552 return BCM_E_PARAM; 9553 } 9554 BCM_VRF_STAT_VALID(unit, vrf); 9555 9556 L3_LOCK(unit); 9557 rv = _bcm_esw_flex_stat_enable_set(unit, fs_type, 9558 _bcm_vrf_flex_stat_hw_index_set, 9559 INT_TO_PTR(_BCM_FLEX_STAT_HW_INGRESS), 9560 vrf, enable,fs_inx); 9561 L3_UNLOCK(unit); 9562 return rv; 9563 } 9564 #endif 9565 9566 /* 9567 * Function: 9568 * bcm_esw_l3_vrf_stat_attach 9569 * Description: 9570 * Attach counters entries to the given VRF 9571 * 9572 * Parameters: 9573 * unit - (IN) unit number 9574 * vrf - (IN) Virtual router instance 9575 * stat_counter_id - (IN) Stat Counter ID. 9576 * 9577 * Return Value: 9578 * BCM_E_XXX 9579 * Notes: 9580 */ 9581 9582 int bcm_esw_l3_vrf_stat_attach( 9583 int unit, 9584 bcm_vrf_t vrf, 9585 uint32 stat_counter_id) 9586 { 9587 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 9588 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 9589 return _bcm_esw_l3_vrf_stat_attach(unit,vrf,stat_counter_id); 9590 } else 9591 #endif 9592 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 9593 if (soc_feature(unit,soc_feature_gport_service_counters)) { 9594 return _tr2_l3_vrf_stat_attach(unit,vrf,stat_counter_id,TRUE); 9595 } else 9596 #endif 9597 { 9598 return BCM_E_UNAVAIL; 9599 } 9600 } 9601 9602 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 9603 /* 9604 * Function: 9605 * _bcm_esw_l3_vrf_stat_detach 9606 * Description: 9607 * Detach counters entries to the given VRF 9608 * 9609 * Parameters: 9610 * unit - (IN) unit number 9611 * vrf - (IN) Virtual router instance 9612 * stat_counter_id - (IN) Stat Counter ID. 9613 * 9614 * Return Value: 9615 * BCM_E_XXX 9616 * Notes: 9617 */ 9618 STATIC bcm_error_t _bcm_esw_l3_vrf_stat_detach( 9619 int unit, 9620 bcm_vrf_t vrf) 9621 { 9622 uint32 count=0; 9623 uint32 num_of_tables=0; 9624 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 9625 bcm_error_t rv = BCM_E_NONE; 9626 bcm_error_t err_code[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION] = {BCM_E_NONE}; 9627 9628 BCM_IF_ERROR_RETURN(_bcm_esw_l3_vrf_stat_get_table_info( 9629 unit, vrf,&num_of_tables,&table_info[0])); 9630 9631 for (count=0; count < num_of_tables ; count++) { 9632 if (table_info[count].direction == bcmStatFlexDirectionIngress) { 9633 rv = _bcm_esw_stat_flex_detach_ingress_table_counters( 9634 unit, table_info[count].table, table_info[count].index); 9635 if (BCM_E_NONE != rv && 9636 BCM_E_NONE == err_code[bcmStatFlexDirectionIngress]) { 9637 err_code[bcmStatFlexDirectionIngress] = rv; 9638 } 9639 } else { 9640 rv = _bcm_esw_stat_flex_detach_egress_table_counters( 9641 unit, 0, table_info[count].table, 9642 table_info[count].index); 9643 if (BCM_E_NONE != rv && 9644 BCM_E_NONE == err_code[bcmStatFlexDirectionEgress]) { 9645 err_code[bcmStatFlexDirectionEgress] = rv; 9646 } 9647 } 9648 } 9649 9650 BCM_STAT_FLEX_DETACH_RETURN(err_code) 9651 } 9652 #endif 9653 9654 /* 9655 * Function: 9656 * bcm_esw_l3_vrf_stat_detach 9657 * Description: 9658 * Detach counters entries to the given VRF 9659 * 9660 * Parameters: 9661 * unit - (IN) unit number 9662 * vrf - (IN) Virtual router instance 9663 * stat_counter_id - (IN) Stat Counter ID. 9664 * 9665 * Return Value: 9666 * BCM_E_XXX 9667 * Notes: 9668 */ 9669 int bcm_esw_l3_vrf_stat_detach( 9670 int unit, 9671 bcm_vrf_t vrf) 9672 { 9673 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 9674 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 9675 return _bcm_esw_l3_vrf_stat_detach(unit,vrf); 9676 } else 9677 #endif 9678 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 9679 if (soc_feature(unit,soc_feature_gport_service_counters)) { 9680 return _tr2_l3_vrf_stat_attach(unit,vrf, 9681 _BCM_FLEX_STAT_COUNT_ID(_bcmFlexStatTypeVrf,1), 9682 FALSE); 9683 } else 9684 #endif 9685 { 9686 return BCM_E_UNAVAIL; 9687 } 9688 } 9689 9690 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 9691 /* 9692 * Function: 9693 * _bcm_esw_l3_vrf_stat_counter_get 9694 * Description: 9695 * Get L3 VRF counter value for specified VRF statistic type 9696 * if sync_mode is set, sync the sw accumulated count 9697 * with hw count value first, else return sw count. 9698 * 9699 * Parameters: 9700 * unit - (IN) unit number 9701 * sync_mode - (IN) hwcount is to be synced to sw count 9702 * vrf - (IN) Virtual router instance 9703 * stat - (IN) Type of the counter to retrieve 9704 * I.e. ingress/egress byte/packet) 9705 * num_entries - (IN) Number of counter Entries 9706 * counter_indexes - (IN) Pointer to Counter indexes entries 9707 * counter_values - (OUT) Pointer to counter values 9708 * 9709 * Return Value: 9710 * BCM_E_XXX 9711 * Notes: 9712 */ 9713 STATIC bcm_error_t _bcm_esw_l3_vrf_stat_counter_get( 9714 int unit, 9715 int sync_mode, 9716 bcm_vrf_t vrf, 9717 bcm_l3_vrf_stat_t stat, 9718 uint32 num_entries, 9719 uint32 *counter_indexes, 9720 bcm_stat_value_t *counter_values) 9721 { 9722 uint32 table_count=0; 9723 uint32 index_count=0; 9724 uint32 num_of_tables=0; 9725 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 9726 uint32 byte_flag=0; 9727 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 9728 9729 if ((stat == bcmL3VrfStatIngressPackets) || 9730 (stat == bcmL3VrfStatIngressBytes)) { 9731 direction = bcmStatFlexDirectionIngress; 9732 } else { 9733 /* direction = bcmStatFlexDirectionEgress; */ 9734 return BCM_E_PARAM; 9735 } 9736 9737 if ((num_entries > 0) && 9738 ((NULL == counter_indexes) || (NULL == counter_values))) { 9739 return BCM_E_PARAM; 9740 } 9741 9742 if (stat == bcmL3VrfStatIngressPackets) { 9743 byte_flag=0; 9744 } else { 9745 byte_flag=1; 9746 } 9747 9748 BCM_IF_ERROR_RETURN(_bcm_esw_l3_vrf_stat_get_table_info( 9749 unit, vrf,&num_of_tables,&table_info[0])); 9750 9751 for (table_count=0; table_count < num_of_tables ; table_count++) { 9752 if (table_info[table_count].direction == direction) { 9753 for (index_count=0; index_count < num_entries ; index_count++) { 9754 BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_get( 9755 unit, sync_mode, 9756 table_info[table_count].index, 9757 table_info[table_count].table, 9758 0, byte_flag, 9759 counter_indexes[index_count], 9760 &counter_values[index_count])); 9761 } 9762 } 9763 } 9764 return BCM_E_NONE; 9765 } 9766 9767 9768 #endif 9769 /* 9770 * Function: 9771 * _bcm_esw_l3_vrf_flex_stat_counter_get 9772 * Description: 9773 * Get L3 VRF counter value for specified VRF statistic type 9774 *if sync_mode is set, sync the sw accumulated count 9775 *with hw count value first, else return sw count. 9776 * 9777 * Parameters: 9778 * unit - (IN) unit number 9779 * sync_mode - (IN) hwcount is to be synced to sw count 9780 * vrf - (IN) Virtual router instance 9781 * stat - (IN) Type of the counter to retrieve 9782 * I.e. ingress/egress byte/packet) 9783 * num_entries - (IN) Number of counter Entries 9784 * counter_indexes - (IN) Pointer to Counter indexes entries 9785 * counter_values - (OUT) Pointer to counter values 9786 * 9787 * Return Value: 9788 * BCM_E_XXX 9789 * Notes: 9790 */ 9791 int _bcm_esw_l3_vrf_flex_stat_counter_get( 9792 int unit, 9793 int sync_mode, 9794 bcm_vrf_t vrf, 9795 bcm_l3_vrf_stat_t stat, 9796 uint32 num_entries, 9797 uint32 *counter_indexes, 9798 bcm_stat_value_t *counter_values) 9799 { 9800 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 9801 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 9802 return _bcm_esw_l3_vrf_stat_counter_get(unit, sync_mode, vrf, stat, 9803 num_entries, counter_indexes, counter_values); 9804 } else 9805 #endif 9806 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 9807 if (soc_feature(unit,soc_feature_gport_service_counters)) { 9808 uint64 val; 9809 int rv = BCM_E_NONE; 9810 9811 if (NULL == counter_values) { 9812 return BCM_E_PARAM; 9813 } 9814 9815 rv = _bcm_esw_l3_vrf_stat_get(unit, sync_mode, vrf, stat, &val); 9816 9817 if (stat == bcmL3VrfStatIngressPackets) { 9818 counter_values->packets = COMPILER_64_LO(val); 9819 } else { 9820 COMPILER_64_SET(counter_values->bytes, 9821 COMPILER_64_HI(val), 9822 COMPILER_64_LO(val)); 9823 } 9824 return rv; 9825 9826 } else 9827 #endif 9828 { 9829 return BCM_E_UNAVAIL; 9830 } 9831 } 9832 9833 9834 9835 /* 9836 * Function: 9837 * bcm_esw_l3_vrf_stat_counter_get 9838 * Description: 9839 * Get L3 VRF counter value for specified VRF statistic type 9840 * 9841 * Parameters: 9842 * unit - (IN) unit number 9843 * vrf - (IN) Virtual router instance 9844 * stat - (IN) Type of the counter to retrieve 9845 * I.e. ingress/egress byte/packet) 9846 * num_entries - (IN) Number of counter Entries 9847 * counter_indexes - (IN) Pointer to Counter indexes entries 9848 * counter_values - (OUT) Pointer to counter values 9849 * 9850 * Return Value: 9851 * BCM_E_XXX 9852 * Notes: 9853 */ 9854 int bcm_esw_l3_vrf_stat_counter_get( 9855 int unit, 9856 bcm_vrf_t vrf, 9857 bcm_l3_vrf_stat_t stat, 9858 uint32 num_entries, 9859 uint32 *counter_indexes, 9860 bcm_stat_value_t *counter_values) 9861 { 9862 int rv = BCM_E_UNAVAIL; 9863 9864 rv = _bcm_esw_l3_vrf_flex_stat_counter_get(unit, 0, vrf, stat, num_entries, 9865 counter_indexes, counter_values); 9866 return rv; 9867 } 9868 9869 9870 /* 9871 * Function: 9872 * bcm_esw_l3_vrf_stat_counter_sync_get 9873 * Description: 9874 * Get L3 VRF counter value for specified VRF statistic type 9875 * sw accumulated counters synced with hw count. 9876 * Parameters: 9877 * unit - (IN) unit number 9878 * vrf - (IN) Virtual router instance 9879 * stat - (IN) Type of the counter to retrieve 9880 * I.e. ingress/egress byte/packet) 9881 * num_entries - (IN) Number of counter Entries 9882 * counter_indexes - (IN) Pointer to Counter indexes entries 9883 * counter_values - (OUT) Pointer to counter values 9884 * 9885 * Return Value: 9886 * BCM_E_XXX 9887 * Notes: 9888 */ 9889 int bcm_esw_l3_vrf_stat_counter_sync_get( 9890 int unit, 9891 bcm_vrf_t vrf, 9892 bcm_l3_vrf_stat_t stat, 9893 uint32 num_entries, 9894 uint32 *counter_indexes, 9895 bcm_stat_value_t *counter_values) 9896 { 9897 int rv = BCM_E_UNAVAIL; 9898 9899 rv = _bcm_esw_l3_vrf_flex_stat_counter_get(unit, 1, vrf, stat, num_entries, 9900 counter_indexes, counter_values); 9901 return rv; 9902 } 9903 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 9904 /* 9905 * Function: 9906 * _bcm_esw_l3_vrf_stat_counter_set 9907 * Description: 9908 * Set L3 VRF counter value for specified VRF statistic type 9909 * 9910 * Parameters: 9911 * unit - (IN) unit number 9912 * vrf - (IN) Virtual router instance 9913 * stat - (IN) Type of the counter to retrieve 9914 * I.e. ingress/egress byte/packet) 9915 * num_entries - (IN) Number of counter Entries 9916 * counter_indexes - (IN) Pointer to Counter indexes entries 9917 * counter_values - (OUT) Pointer to counter values 9918 * 9919 * Return Value: 9920 * BCM_E_XXX 9921 * Notes: 9922 */ 9923 STATIC bcm_error_t _bcm_esw_l3_vrf_stat_counter_set( 9924 int unit, 9925 bcm_vrf_t vrf, 9926 bcm_l3_vrf_stat_t stat, 9927 uint32 num_entries, 9928 uint32 *counter_indexes, 9929 bcm_stat_value_t *counter_values) 9930 { 9931 uint32 table_count=0; 9932 uint32 index_count=0; 9933 uint32 num_of_tables=0; 9934 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 9935 uint32 byte_flag=0; 9936 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 9937 9938 if ((stat == bcmL3VrfStatIngressPackets) || 9939 (stat == bcmL3VrfStatIngressBytes)) { 9940 direction = bcmStatFlexDirectionIngress; 9941 } else { 9942 /* direction = bcmStatFlexDirectionEgress; */ 9943 return BCM_E_PARAM; 9944 } 9945 9946 if ((num_entries > 0) && 9947 ((NULL == counter_indexes) || (NULL == counter_values))) { 9948 return BCM_E_PARAM; 9949 } 9950 9951 if (stat == bcmL3VrfStatIngressPackets) { 9952 byte_flag=0; 9953 } else { 9954 byte_flag=1; 9955 } 9956 9957 BCM_IF_ERROR_RETURN(_bcm_esw_l3_vrf_stat_get_table_info( 9958 unit, vrf,&num_of_tables,&table_info[0])); 9959 9960 for (table_count=0; table_count < num_of_tables ; table_count++) { 9961 if (table_info[table_count].direction == direction) { 9962 for (index_count=0; index_count < num_entries ; index_count++) { 9963 BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_set( 9964 unit, 9965 table_info[table_count].index, 9966 table_info[table_count].table, 9967 0, byte_flag, 9968 counter_indexes[index_count], 9969 &counter_values[index_count])); 9970 } 9971 } 9972 } 9973 return BCM_E_NONE; 9974 } 9975 #endif 9976 9977 /* 9978 * Function: 9979 * bcm_esw_l3_vrf_stat_counter_set 9980 * Description: 9981 * Set L3 VRF counter value for specified VRF statistic type 9982 * 9983 * Parameters: 9984 * unit - (IN) unit number 9985 * vrf - (IN) Virtual router instance 9986 * stat - (IN) Type of the counter to retrieve 9987 * I.e. ingress/egress byte/packet) 9988 * num_entries - (IN) Number of counter Entries 9989 * counter_indexes - (IN) Pointer to Counter indexes entries 9990 * counter_values - (OUT) Pointer to counter values 9991 * 9992 * Return Value: 9993 * BCM_E_XXX 9994 * Notes: 9995 */ 9996 int bcm_esw_l3_vrf_stat_counter_set( 9997 int unit, 9998 bcm_vrf_t vrf, 9999 bcm_l3_vrf_stat_t stat, 10000 uint32 num_entries, 10001 uint32 *counter_indexes, 10002 bcm_stat_value_t *counter_values) 10003 { 10004 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10005 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 10006 return _bcm_esw_l3_vrf_stat_counter_set(unit,vrf,stat, 10007 num_entries,counter_indexes,counter_values); 10008 } else 10009 #endif 10010 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 10011 if (soc_feature(unit,soc_feature_gport_service_counters)) { 10012 uint64 val; 10013 int rv = BCM_E_NONE; 10014 10015 if (NULL == counter_values) { 10016 return BCM_E_PARAM; 10017 } 10018 10019 if (stat == bcmL3VrfStatIngressPackets) { 10020 COMPILER_64_SET(val,0,counter_values->packets); 10021 } else { 10022 COMPILER_64_SET(val, 10023 COMPILER_64_HI(counter_values->bytes), 10024 COMPILER_64_LO(counter_values->bytes)); 10025 } 10026 rv = bcm_esw_l3_vrf_stat_set(unit,vrf,stat,val); 10027 10028 return rv; 10029 10030 } else 10031 #endif 10032 { 10033 return BCM_E_UNAVAIL; 10034 } 10035 10036 } 10037 10038 /* 10039 * Function: 10040 * bcm_esw_l3_vrf_stat_id_get 10041 * Description: 10042 * Get stat counter id associated with given VRF 10043 * 10044 * Parameters: 10045 * unit - (IN) unit number 10046 * vrf - (IN) Virtual router instance 10047 * stat - (IN) Type of the counter to retrieve 10048 * I.e. ingress/egress byte/packet) 10049 * Stat_counter_id - (OUT) Stat Counter ID 10050 * 10051 * Return Value: 10052 * BCM_E_XXX 10053 * Notes: 10054 */ 10055 int bcm_esw_l3_vrf_stat_id_get( 10056 int unit, 10057 bcm_vrf_t vrf, 10058 bcm_l3_vrf_stat_t stat, 10059 uint32 *stat_counter_id) 10060 { 10061 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10062 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 10063 uint32 num_of_tables=0; 10064 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 10065 uint32 index=0; 10066 uint32 num_stat_counter_ids=0; 10067 10068 if ((stat == bcmL3VrfStatIngressPackets) || 10069 (stat == bcmL3VrfStatIngressBytes)) { 10070 direction = bcmStatFlexDirectionIngress; 10071 } else { 10072 direction = bcmStatFlexDirectionEgress; 10073 } 10074 BCM_IF_ERROR_RETURN(_bcm_esw_l3_vrf_stat_get_table_info( 10075 unit,vrf,&num_of_tables,&table_info[0])); 10076 for (index=0; index < num_of_tables ; index++) { 10077 if (table_info[index].direction == direction) 10078 return _bcm_esw_stat_flex_get_counter_id( 10079 unit, 1, &table_info[index], 10080 &num_stat_counter_ids,stat_counter_id); 10081 } 10082 return BCM_E_NOT_FOUND; 10083 #else 10084 return BCM_E_UNAVAIL; 10085 #endif 10086 } 10087 10088 10089 10090 10091 10092 /* 10093 * Function: 10094 * bcm_esw_l3_vrf_stat_enable_set 10095 * Purpose: 10096 * Enable/disable packet and byte counters for the selected VRF. 10097 * Parameters: 10098 * unit - (IN) Unit number. 10099 * vrf - (IN) Virtual router instance. 10100 * enable - (IN) Non-zero to enable counter collection, zero to disable. 10101 * Returns: 10102 * BCM_E_XXX 10103 * Notes: 10104 */ 10105 int 10106 bcm_esw_l3_vrf_stat_enable_set(int unit, bcm_vrf_t vrf, int enable) 10107 { 10108 #if defined(BCM_TRIUMPH2_SUPPORT) 10109 int rv = BCM_E_UNAVAIL; 10110 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10111 uint32 num_of_tables=0; 10112 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 10113 bcm_stat_object_t object=bcmStatObjectIngPort; 10114 uint32 num_entries=0; 10115 uint32 num_stat_counter_ids=0; 10116 uint32 stat_counter_id[ 10117 BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]={0}; 10118 #endif /* BCM_KATANA_SUPPORT */ 10119 L3_INIT(unit); 10120 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 10121 BCM_VRF_STAT_VALID(unit, vrf); 10122 10123 L3_LOCK(unit); 10124 rv = _bcm_esw_flex_stat_enable_set(unit, _bcmFlexStatTypeVrf, 10125 _bcm_vrf_flex_stat_hw_index_set, 10126 NULL, vrf, enable,0); 10127 L3_UNLOCK(unit); 10128 return rv; 10129 } 10130 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10131 if (enable) { 10132 BCM_IF_ERROR_RETURN(_bcm_esw_l3_vrf_stat_get_table_info( 10133 unit,vrf,&num_of_tables,&table_info[0])); 10134 if (num_of_tables != 1) { 10135 return BCM_E_INTERNAL; 10136 } 10137 if (table_info[0].direction != bcmStatFlexDirectionIngress) { 10138 return BCM_E_INTERNAL; 10139 } 10140 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_ingress_object( 10141 unit,table_info[0].table, 10142 table_info[0].index,NULL,&object)); 10143 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_create( 10144 unit,object,bcmStatGroupModeSingle, 10145 &stat_counter_id[table_info[0].direction], 10146 &num_entries)); 10147 BCM_IF_ERROR_RETURN(bcm_esw_l3_vrf_stat_attach( 10148 unit,vrf,stat_counter_id[table_info[0].direction])); 10149 } else { 10150 BCM_IF_ERROR_RETURN(_bcm_esw_l3_vrf_stat_get_table_info( 10151 unit,vrf,&num_of_tables,&table_info[0])); 10152 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_counter_id( 10153 unit, num_of_tables,&table_info[0], 10154 &num_stat_counter_ids,&stat_counter_id[0])); 10155 if (num_stat_counter_ids != 1) { 10156 return BCM_E_INTERNAL; 10157 } 10158 BCM_IF_ERROR_RETURN(bcm_esw_l3_vrf_stat_detach(unit,vrf)); 10159 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_destroy( 10160 unit, 10161 stat_counter_id[bcmStatFlexDirectionIngress])); 10162 } 10163 return BCM_E_NONE; 10164 #else 10165 return BCM_E_UNAVAIL; 10166 #endif /* BCM_KATANA_SUPPORT */ 10167 #else 10168 return BCM_E_UNAVAIL; 10169 #endif /* BCM_TRIUMPH2_SUPPORT */ 10170 } 10171 10172 /* 10173 * Function: 10174 * _bcm_esw_l3_vrf_stat_get 10175 * Purpose: 10176 * Get 64-bit counter value for specified VRF statistic type. 10177 * if sync_mode is set, sync the sw accumulated count 10178 * with hw count value first, else return sw count. 10179 * Parameters: 10180 * unit - (IN) Unit number. 10181 * sync_mode - (IN) hwcount is to be synced to sw count 10182 * vrf - (IN) Virtual router instance. 10183 * stat - (IN) Type of the counter to retrieve. 10184 * val - (OUT) Pointer to a counter value. 10185 * Returns: 10186 * BCM_E_XXX 10187 * Notes: 10188 */ 10189 int 10190 _bcm_esw_l3_vrf_stat_get(int unit, int sync_mode, 10191 bcm_vrf_t vrf, bcm_l3_vrf_stat_t stat, uint64 *val) 10192 { 10193 #if defined(BCM_TRIUMPH2_SUPPORT) 10194 int rv=BCM_E_UNAVAIL; 10195 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10196 uint32 counter_indexes=0; 10197 bcm_stat_value_t counter_values={0}; 10198 #endif 10199 L3_INIT(unit); 10200 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 10201 BCM_VRF_STAT_VALID(unit, vrf); 10202 L3_LOCK(unit); 10203 10204 rv = _bcm_esw_flex_stat_get(unit, sync_mode, _bcmFlexStatTypeVrf, vrf, 10205 _bcm_esw_l3_vrf_stat_to_flex_stat(stat), val); 10206 L3_UNLOCK(unit); 10207 return rv; 10208 } 10209 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10210 BCM_IF_ERROR_RETURN(_bcm_esw_l3_vrf_stat_counter_get(unit, sync_mode, vrf, 10211 stat, 1, 10212 &counter_indexes, 10213 &counter_values)); 10214 if (stat == bcmL3VrfStatIngressPackets) { 10215 COMPILER_64_SET(*val, 10216 COMPILER_64_HI(counter_values.packets64), 10217 COMPILER_64_LO(counter_values.packets64)); 10218 } else { 10219 COMPILER_64_SET(*val, 10220 COMPILER_64_HI(counter_values.bytes), 10221 COMPILER_64_LO(counter_values.bytes)); 10222 } 10223 return BCM_E_NONE; 10224 #else 10225 return BCM_E_UNAVAIL; 10226 #endif 10227 #else 10228 return BCM_E_UNAVAIL; 10229 #endif /* BCM_TRIUMPH2_SUPPORT */ 10230 } 10231 10232 10233 /* 10234 * Function: 10235 * bcm_esw_l3_vrf_stat_get 10236 * Purpose: 10237 * Get 64-bit counter value for specified VRF statistic type. 10238 * Parameters: 10239 * unit - (IN) Unit number. 10240 * vrf - (IN) Virtual router instance. 10241 * stat - (IN) Type of the counter to retrieve. 10242 * val - (OUT) Pointer to a counter value. 10243 * Returns: 10244 * BCM_E_XXX 10245 * Notes: 10246 */ 10247 int 10248 bcm_esw_l3_vrf_stat_get(int unit, bcm_vrf_t vrf, bcm_l3_vrf_stat_t stat, 10249 uint64 *val) 10250 { 10251 int rv = BCM_E_UNAVAIL; 10252 10253 rv = _bcm_esw_l3_vrf_stat_get(unit, 0, vrf, stat, val); 10254 10255 return rv; 10256 } 10257 10258 10259 /* 10260 * Function: 10261 * bcm_esw_l3_vrf_stat_sync_get 10262 * Purpose: 10263 * Get 64-bit counter value for specified VRF statistic type. 10264 * sw accumulated counters synced with hw count. 10265 * Parameters: 10266 * unit - (IN) Unit number. 10267 * vrf - (IN) Virtual router instance. 10268 * stat - (IN) Type of the counter to retrieve. 10269 * val - (OUT) Pointer to a counter value. 10270 * Returns: 10271 * BCM_E_XXX 10272 * Notes: 10273 */ 10274 int 10275 bcm_esw_l3_vrf_stat_sync_get(int unit, bcm_vrf_t vrf, bcm_l3_vrf_stat_t stat, 10276 uint64 *val) 10277 { 10278 int rv = BCM_E_UNAVAIL; 10279 10280 rv = _bcm_esw_l3_vrf_stat_get(unit, 1, vrf, stat, val); 10281 10282 return rv; 10283 } 10284 10285 10286 10287 /* 10288 * Function: 10289 * _bcm_esw_l3_vrf_stat_get32 10290 * Purpose: 10291 * Get lower 32-bit counter value for specified VRF statistic 10292 * type. 10293 * if sync_mode is set, sync the sw accumulated count 10294 * with hw count value first, else return sw count. 10295 * Parameters: 10296 * unit - (IN) Unit number. 10297 * sync_mode - (IN) hwcount is to be synced to sw count 10298 * vrf - (IN) Virtual router instance. 10299 * stat - (IN) Type of the counter to retrieve. 10300 * val - (OUT) Pointer to a counter value. 10301 * Returns: 10302 * BCM_E_XXX 10303 * Notes: 10304 */ 10305 int 10306 _bcm_esw_l3_vrf_stat_get32(int unit, int sync_mode, bcm_vrf_t vrf, 10307 bcm_l3_vrf_stat_t stat, uint32 *val) 10308 { 10309 #if defined(BCM_TRIUMPH2_SUPPORT) 10310 int rv = BCM_E_UNAVAIL; 10311 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10312 uint32 counter_indexes=0; 10313 bcm_stat_value_t counter_values={0}; 10314 #endif 10315 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 10316 L3_INIT(unit); 10317 BCM_VRF_STAT_VALID(unit, vrf); 10318 L3_LOCK(unit); 10319 10320 rv = _bcm_esw_flex_stat_get32(unit, sync_mode, _bcmFlexStatTypeVrf, vrf, 10321 _bcm_esw_l3_vrf_stat_to_flex_stat(stat), val); 10322 L3_UNLOCK(unit); 10323 return rv; 10324 } 10325 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10326 BCM_IF_ERROR_RETURN(_bcm_esw_l3_vrf_stat_counter_get(unit, sync_mode, vrf, 10327 stat, 1, 10328 &counter_indexes, 10329 &counter_values)); 10330 if (stat == bcmL3VrfStatIngressPackets) { 10331 *val = counter_values.packets; 10332 } else { 10333 /* Ignoring Hi bytes value */ 10334 *val = COMPILER_64_LO(counter_values.bytes); 10335 } 10336 return BCM_E_NONE; 10337 #else 10338 return BCM_E_UNAVAIL; 10339 #endif 10340 #else 10341 return BCM_E_UNAVAIL; 10342 #endif /* BCM_TRIUMPH2_SUPPORT */ 10343 } 10344 10345 /* 10346 * Function: 10347 * bcm_esw_l3_vrf_stat_get32 10348 * Purpose: 10349 * Get lower 32-bit counter value for specified VRF statistic 10350 * type. 10351 * Parameters: 10352 * unit - (IN) Unit number. 10353 * sync_mode - (IN) hwcount is to be synced to sw count 10354 * vrf - (IN) Virtual router instance. 10355 * stat - (IN) Type of the counter to retrieve. 10356 * val - (OUT) Pointer to a counter value. 10357 * Returns: 10358 * BCM_E_XXX 10359 * Notes: 10360 */ 10361 int 10362 bcm_esw_l3_vrf_stat_get32(int unit,bcm_vrf_t vrf, 10363 bcm_l3_vrf_stat_t stat, uint32 *val) 10364 { 10365 int rv = BCM_E_UNAVAIL; 10366 10367 rv = _bcm_esw_l3_vrf_stat_get32(unit, 0, vrf, stat, val); 10368 10369 return rv; 10370 } 10371 10372 10373 /* 10374 * Function: 10375 * bcm_esw_l3_vrf_stat_sync_get32 10376 * Purpose: 10377 * Get lower 32-bit counter value for specified VRF statistic 10378 * type. 10379 * sw accumulated counters synced with hw count. 10380 * Parameters: 10381 * unit - (IN) Unit number. 10382 * vrf - (IN) Virtual router instance. 10383 * stat - (IN) Type of the counter to retrieve. 10384 * val - (OUT) Pointer to a counter value. 10385 * Returns: 10386 * BCM_E_XXX 10387 * Notes: 10388 */ 10389 int 10390 bcm_esw_l3_vrf_stat_sync_get32(int unit,bcm_vrf_t vrf, 10391 bcm_l3_vrf_stat_t stat, uint32 *val) 10392 { 10393 int rv = BCM_E_UNAVAIL; 10394 10395 rv = _bcm_esw_l3_vrf_stat_get32(unit, 1, vrf, stat, val); 10396 10397 return rv; 10398 } 10399 10400 /* 10401 * Function: 10402 * bcm_esw_l3_vrf_stat_set 10403 * Purpose: 10404 * Set 64-bit counter value for specified VRF statistic type. 10405 * Parameters: 10406 * unit - (IN) Unit number. 10407 * vrf - (IN) Virtual router instance. 10408 * stat - (IN) Type of the counter to retrieve. 10409 * val - (IN) New counter value. 10410 * Returns: 10411 * BCM_E_XXX 10412 * Notes: 10413 */ 10414 int 10415 bcm_esw_l3_vrf_stat_set(int unit, bcm_vrf_t vrf, bcm_l3_vrf_stat_t stat, 10416 uint64 val) 10417 { 10418 #if defined(BCM_TRIUMPH2_SUPPORT) 10419 int rv = BCM_E_UNAVAIL; 10420 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10421 uint32 counter_indexes=0; 10422 bcm_stat_value_t counter_values={0}; 10423 #endif 10424 L3_INIT(unit); 10425 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 10426 BCM_VRF_STAT_VALID(unit, vrf); 10427 L3_LOCK(unit); 10428 10429 rv = _bcm_esw_flex_stat_set(unit, _bcmFlexStatTypeVrf, vrf, 10430 _bcm_esw_l3_vrf_stat_to_flex_stat(stat), val); 10431 L3_UNLOCK(unit); 10432 return rv; 10433 } 10434 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10435 if (stat == bcmL3VrfStatIngressPackets) { 10436 counter_values.packets = COMPILER_64_LO(val); 10437 } else { 10438 COMPILER_64_SET(counter_values.bytes, 10439 COMPILER_64_HI(val), 10440 COMPILER_64_LO(val)); 10441 } 10442 BCM_IF_ERROR_RETURN(bcm_esw_l3_vrf_stat_counter_set( 10443 unit,vrf,stat,1, &counter_indexes, &counter_values)); 10444 return BCM_E_NONE; 10445 #else 10446 return BCM_E_UNAVAIL; 10447 #endif 10448 #else 10449 return BCM_E_UNAVAIL; 10450 #endif /* BCM_TRIUMPH2_SUPPORT */ 10451 } 10452 10453 /* 10454 * Function: 10455 * bcm_esw_l3_vrf_stat_set32 10456 * Purpose: 10457 * Set lower 32-bit counter value for specified VRF statistic 10458 * type. 10459 * Parameters: 10460 * unit - (IN) Unit number. 10461 * vrf - (IN) Virtual router instance. 10462 * stat - (IN) Type of the counter to retrieve. 10463 * val - (IN) New counter value. 10464 * Returns: 10465 * BCM_E_XXX 10466 * Notes: 10467 */ 10468 int 10469 bcm_esw_l3_vrf_stat_set32(int unit, bcm_vrf_t vrf, 10470 bcm_l3_vrf_stat_t stat, uint32 val) 10471 { 10472 #if defined(BCM_TRIUMPH2_SUPPORT) 10473 int rv = BCM_E_UNAVAIL; 10474 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10475 uint32 counter_indexes=0; 10476 bcm_stat_value_t counter_values={0}; 10477 #endif 10478 L3_INIT(unit); 10479 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 10480 BCM_VRF_STAT_VALID(unit, vrf); 10481 L3_LOCK(unit); 10482 10483 rv = _bcm_esw_flex_stat_set32(unit, _bcmFlexStatTypeVrf, vrf, 10484 _bcm_esw_l3_vrf_stat_to_flex_stat(stat), val); 10485 L3_UNLOCK(unit); 10486 return rv; 10487 } 10488 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10489 if (stat == bcmL3VrfStatIngressPackets) { 10490 counter_values.packets = val; 10491 } else { 10492 /* Ignoring high value */ 10493 COMPILER_64_SET(counter_values.bytes,0,val); 10494 } 10495 BCM_IF_ERROR_RETURN(bcm_esw_l3_vrf_stat_counter_set( 10496 unit,vrf, stat, 1, &counter_indexes, &counter_values)); 10497 return BCM_E_NONE; 10498 #else 10499 return BCM_E_UNAVAIL; 10500 #endif 10501 #else 10502 return BCM_E_UNAVAIL; 10503 #endif /* BCM_TRIUMPH2_SUPPORT */ 10504 } 10505 10506 /* 10507 * Function: 10508 * bcm_esw_l3_vrf_stat_multi_get 10509 * Purpose: 10510 * Get 64-bit counter value for multiple VRF statistic types. 10511 * Parameters: 10512 * unit - (IN) Unit number. 10513 * vrf - (IN) Virtual router instance. 10514 * nstat - (IN) Number of elements in stat array 10515 * stat_arr - (IN) Collected statistics descriptors array 10516 * value_arr - (OUT) Collected counters values 10517 * Returns: 10518 * BCM_E_XXX 10519 * Notes: 10520 */ 10521 int 10522 bcm_esw_l3_vrf_stat_multi_get(int unit, bcm_vrf_t vrf, int nstat, 10523 bcm_l3_vrf_stat_t *stat_arr, 10524 uint64 *value_arr) 10525 { 10526 #if defined(BCM_TRIUMPH2_SUPPORT) 10527 int rv = BCM_E_UNAVAIL; 10528 _bcm_flex_stat_t fs_arr[_bcmFlexStatNum]; /* Normalize stats */ 10529 int idx; /* Statistics iteration index. */ 10530 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10531 uint32 counter_indexes=0; 10532 bcm_stat_value_t counter_values={0}; 10533 #endif 10534 10535 L3_INIT(unit); 10536 10537 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 10538 BCM_VRF_STAT_VALID(unit, vrf); 10539 BCM_IF_ERROR_RETURN 10540 (_bcm_l3_vrf_stat_array_convert(unit, nstat, stat_arr, fs_arr)); 10541 BCM_VRF_STAT_ARRAY_VALID(unit, nstat, value_arr); 10542 L3_LOCK(unit); 10543 10544 rv = _bcm_esw_flex_stat_multi_get(unit, _bcmFlexStatTypeVrf, vrf, 10545 nstat, fs_arr, value_arr); 10546 L3_UNLOCK(unit); 10547 return rv; 10548 } 10549 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10550 if ( (NULL == stat_arr) || (NULL == value_arr) ) { 10551 return BCM_E_PARAM; 10552 } 10553 for (idx=0;idx < nstat ; idx ++) { 10554 BCM_IF_ERROR_RETURN(bcm_esw_l3_vrf_stat_counter_get( 10555 unit, vrf, stat_arr[idx], 10556 1, &counter_indexes, &counter_values)); 10557 if (stat_arr[idx] == bcmL3VrfStatIngressPackets) { 10558 COMPILER_64_SET(value_arr[idx], 10559 COMPILER_64_HI(counter_values.packets64), 10560 COMPILER_64_LO(counter_values.packets64)); 10561 } else { 10562 COMPILER_64_SET(value_arr[idx], 10563 COMPILER_64_HI(counter_values.bytes), 10564 COMPILER_64_LO(counter_values.bytes)); 10565 } 10566 } 10567 return BCM_E_NONE; 10568 #else 10569 return BCM_E_UNAVAIL; 10570 #endif 10571 #else 10572 return BCM_E_UNAVAIL; 10573 #endif /* BCM_TRIUMPH2_SUPPORT */ 10574 } 10575 10576 /* 10577 * Function: 10578 * bcm_esw_l3_vrf_stat_multi_get32 10579 * Purpose: 10580 * Get lower 32-bit counter value for multiple VRF statistic 10581 * types. 10582 * Parameters: 10583 * unit - (IN) Unit number. 10584 * vrf - (IN) Virtual router instance. 10585 * nstat - (IN) Number of elements in stat array 10586 * stat_arr - (IN) Collected statistics descriptors array 10587 * value_arr - (OUT) Collected counters values 10588 * Returns: 10589 * BCM_E_XXX 10590 * Notes: 10591 */ 10592 int 10593 bcm_esw_l3_vrf_stat_multi_get32(int unit, bcm_vrf_t vrf, int nstat, 10594 bcm_l3_vrf_stat_t *stat_arr, 10595 uint32 *value_arr) 10596 { 10597 #if defined(BCM_TRIUMPH2_SUPPORT) 10598 int rv = BCM_E_UNAVAIL; 10599 _bcm_flex_stat_t fs_arr[_bcmFlexStatNum]; /* Normalize stats */ 10600 int idx; /* Statistics iteration index. */ 10601 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10602 uint32 counter_indexes=0; 10603 bcm_stat_value_t counter_values={0}; 10604 #endif 10605 10606 L3_INIT(unit); 10607 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 10608 BCM_VRF_STAT_VALID(unit, vrf); 10609 BCM_IF_ERROR_RETURN 10610 (_bcm_l3_vrf_stat_array_convert(unit, nstat, stat_arr, fs_arr)); 10611 BCM_VRF_STAT_ARRAY_VALID(unit, nstat, value_arr); 10612 L3_LOCK(unit); 10613 10614 rv = _bcm_esw_flex_stat_multi_get32(unit, _bcmFlexStatTypeVrf, vrf, 10615 nstat, fs_arr, value_arr); 10616 L3_UNLOCK(unit); 10617 return rv; 10618 } 10619 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10620 if ( (NULL == stat_arr) || (NULL == value_arr) ) { 10621 return BCM_E_PARAM; 10622 } 10623 for (idx=0;idx < nstat ; idx ++) { 10624 BCM_IF_ERROR_RETURN(bcm_esw_l3_vrf_stat_counter_get( 10625 unit, vrf, stat_arr[idx], 10626 1, &counter_indexes, &counter_values)); 10627 if (stat_arr[idx] == bcmL3VrfStatIngressPackets) { 10628 value_arr[idx] = counter_values.packets; 10629 } else { 10630 value_arr[idx] = COMPILER_64_LO(counter_values.bytes); 10631 } 10632 } 10633 return BCM_E_NONE; 10634 #else 10635 return BCM_E_UNAVAIL; 10636 #endif 10637 #else 10638 return BCM_E_UNAVAIL; 10639 #endif /* BCM_TRIUMPH2_SUPPORT */ 10640 } 10641 10642 /* 10643 * Function: 10644 * bcm_esw_l3_vrf_stat_multi_set 10645 * Purpose: 10646 * Set 64-bit counter value for multiple VRF statistic types. 10647 * Parameters: 10648 * unit - (IN) Unit number. 10649 * vrf - (IN) Virtual router instance. 10650 * nstat - (IN) Number of elements in stat array 10651 * stat_arr - (IN) New statistics descriptors array 10652 * value_arr - (IN) New counters values 10653 * Returns: 10654 * BCM_E_XXX 10655 * Notes: 10656 */ 10657 int 10658 bcm_esw_l3_vrf_stat_multi_set(int unit, bcm_vrf_t vrf, int nstat, 10659 bcm_l3_vrf_stat_t *stat_arr, 10660 uint64 *value_arr) 10661 { 10662 #if defined(BCM_TRIUMPH2_SUPPORT) 10663 int rv = BCM_E_UNAVAIL; 10664 _bcm_flex_stat_t fs_arr[_bcmFlexStatNum]; /* Normalize stats */ 10665 int idx; /* Statistics iteration index. */ 10666 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10667 uint32 counter_indexes=0; 10668 bcm_stat_value_t counter_values={0}; 10669 #endif 10670 10671 L3_INIT(unit); 10672 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 10673 BCM_VRF_STAT_VALID(unit, vrf); 10674 BCM_IF_ERROR_RETURN 10675 (_bcm_l3_vrf_stat_array_convert(unit, nstat, stat_arr, fs_arr)); 10676 BCM_VRF_STAT_ARRAY_VALID(unit, nstat, value_arr); 10677 L3_LOCK(unit); 10678 10679 rv = _bcm_esw_flex_stat_multi_set(unit, _bcmFlexStatTypeVrf, vrf, 10680 nstat, fs_arr, value_arr); 10681 L3_UNLOCK(unit); 10682 return rv; 10683 } 10684 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10685 if ( (NULL == stat_arr) || (NULL == value_arr) ) { 10686 return BCM_E_PARAM; 10687 } 10688 for (idx=0;idx < nstat ; idx ++) { 10689 if (stat_arr[idx] == bcmL3VrfStatIngressPackets) { 10690 counter_values.packets = COMPILER_64_LO(value_arr[idx]); 10691 } else { 10692 COMPILER_64_SET(counter_values.bytes, 10693 COMPILER_64_HI(value_arr[idx]), 10694 COMPILER_64_LO(value_arr[idx])); 10695 } 10696 BCM_IF_ERROR_RETURN(bcm_esw_l3_vrf_stat_counter_set( 10697 unit, vrf, stat_arr[idx], 1, 10698 &counter_indexes, &counter_values)); 10699 } 10700 return BCM_E_NONE; 10701 #else 10702 return BCM_E_UNAVAIL; 10703 #endif 10704 #else 10705 return BCM_E_UNAVAIL; 10706 #endif /* BCM_TRIUMPH2_SUPPORT */ 10707 } 10708 10709 /* 10710 * Function: 10711 * bcm_esw_l3_vrf_stat_multi_set32 10712 * Purpose: 10713 * Set lower 32-bit counter value for multiple VRF statistic 10714 * types. 10715 * Parameters: 10716 * unit - (IN) Unit number. 10717 * vrf - (IN) Virtual router instance. 10718 * nstat - (IN) Number of elements in stat array 10719 * stat_arr - (IN) New statistics descriptors array 10720 * value_arr - (IN) New counters values 10721 * Returns: 10722 * BCM_E_XXX 10723 * Notes: 10724 */ 10725 int 10726 bcm_esw_l3_vrf_stat_multi_set32(int unit, bcm_vrf_t vrf, int nstat, 10727 bcm_l3_vrf_stat_t *stat_arr, 10728 uint32 *value_arr) 10729 { 10730 #if defined(BCM_TRIUMPH2_SUPPORT) 10731 int rv = BCM_E_UNAVAIL; 10732 _bcm_flex_stat_t fs_arr[_bcmFlexStatNum]; /* Normalize stats */ 10733 int idx; /* Statistics iteration index. */ 10734 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10735 uint32 counter_indexes=0; 10736 bcm_stat_value_t counter_values={0}; 10737 #endif 10738 10739 L3_INIT(unit); 10740 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 10741 BCM_VRF_STAT_VALID(unit, vrf); 10742 BCM_IF_ERROR_RETURN 10743 (_bcm_l3_vrf_stat_array_convert(unit, nstat, stat_arr, fs_arr)); 10744 BCM_VRF_STAT_ARRAY_VALID(unit, nstat, value_arr); 10745 L3_LOCK(unit); 10746 10747 rv = _bcm_esw_flex_stat_multi_set32(unit, _bcmFlexStatTypeVrf, vrf, 10748 nstat, fs_arr, value_arr); 10749 L3_UNLOCK(unit); 10750 return rv; 10751 } 10752 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10753 if ( (NULL == stat_arr) || (NULL == value_arr) ) { 10754 return BCM_E_PARAM; 10755 } 10756 for (idx=0;idx < nstat ; idx ++) { 10757 if (stat_arr[idx] == bcmL3VrfStatIngressPackets) { 10758 counter_values.packets = value_arr[idx]; 10759 } else { 10760 COMPILER_64_SET(counter_values.bytes,0,value_arr[idx]); 10761 } 10762 BCM_IF_ERROR_RETURN(bcm_esw_l3_vrf_stat_counter_set( 10763 unit, vrf, stat_arr[idx], 1, 10764 &counter_indexes, &counter_values)); 10765 } 10766 return BCM_E_NONE; 10767 #else 10768 return BCM_E_UNAVAIL; 10769 #endif 10770 #else 10771 return BCM_E_UNAVAIL; 10772 #endif /* BCM_TRIUMPH2_SUPPORT */ 10773 } 10774 10775 /* 10776 * Function: 10777 * bcm_esw_l3_vrf_route_data_mode_get 10778 * Purpose: 10779 * This function returns the current ALPM route associated data mode 10780 * in the VRF and IP type, including the default mode by configuration 10781 * if no vrf specific setting available. 10782 * Parameters: 10783 * unit - (IN) BCM device number 10784 * vrf - (IN) Virtual router instance. 10785 * flgas - (IN) IP type flag (BCM_L3_IP6) 10786 * mode - (OUT) Current ALPM data mode. 10787 * Returns: 10788 * BCM_E_XXX: 10789 * - BCM_E_NONE: on success 10790 * - BCM_E_PARAM: if NULL or invalid parameters are passed 10791 * - BCM_E_UNAVAIL: if this feature is not supported (eg. ALPM disabled). 10792 * Notes: 10793 * Currently this feature is only supported in TOMAHAWK3 ALPM2. 10794 */ 10795 int 10796 bcm_esw_l3_vrf_route_data_mode_get(int unit, bcm_vrf_t vrf, uint32 flags, 10797 bcm_l3_vrf_route_data_mode_t *mode) 10798 { 10799 #ifdef ALPM_ENABLE 10800 #ifdef BCM_TOMAHAWK3_SUPPORT 10801 int rv; 10802 10803 /* Currently this API is supported on Tomahawk3 only */ 10804 if (!SOC_IS_TOMAHAWK3(unit)) { 10805 return BCM_E_UNAVAIL; 10806 } 10807 10808 if (mode == NULL) { 10809 return BCM_E_PARAM; 10810 } 10811 10812 if ((vrf > SOC_VRF_MAX(unit)) || 10813 (vrf < BCM_L3_VRF_GLOBAL)) { 10814 return (BCM_E_PARAM); 10815 } 10816 10817 rv = bcm_esw_alpm_vrf_data_mode_get(unit, vrf, flags, mode); 10818 10819 return rv; 10820 10821 #else /* BCM_TOMAHAWK3_SUPPORT */ 10822 return BCM_E_UNAVAIL; 10823 #endif 10824 #else /* ALPM_ENABLE */ 10825 return BCM_E_UNAVAIL; 10826 #endif 10827 } 10828 10829 /* 10830 * Function: 10831 * bcm_esw_l3_vrf_route_data_mode_set 10832 * Purpose: 10833 * This function sets ALPM route associated data mode in the VRF 10834 * and IP type. 10835 * Parameters: 10836 * unit - (IN) BCM device number 10837 * vrf - (IN) Virtual router instance. 10838 * flgas - (IN) IP type flag (BCM_L3_IP6) 10839 * mode - (IN) ALPM data mode to set. 10840 * Returns: 10841 * BCM_E_XXX: 10842 * - BCM_E_NONE: on success 10843 * - BCM_E_PARAM: if invalid parameters are passed 10844 * - BCM_E_UNAVAIL: if this feature is not supported (eg. ALPM disabled). 10845 * - BCM_E_FAIL: if change of ALPM data mode is not allowed 10846 * in the VRF and IP type. 10847 * Notes: 10848 * Currently this feature is only supported in TOMAHAWK3 ALPM2. 10849 * 10850 * Initial Implementation: user can call this API if want to change the 10851 * default mode in this VRF and IP type (IPv4 or IPv6), before add the 10852 * first ALPM route in the VRF and IP type. Mode change is not allowed 10853 * once ALPM VRF initialized (ALPM route added in the VRF and IP type). 10854 * 10855 * Future Enhancement (TBD): user can call this API anytime and SDK will 10856 * change the assoc data mode for all ALPM routes in the VRF and IP type. 10857 */ 10858 int 10859 bcm_esw_l3_vrf_route_data_mode_set(int unit, bcm_vrf_t vrf, uint32 flags, 10860 bcm_l3_vrf_route_data_mode_t mode) 10861 { 10862 #ifdef ALPM_ENABLE 10863 #ifdef BCM_TOMAHAWK3_SUPPORT 10864 int rv; 10865 10866 /* Currently this API is supported on Tomahawk3 only */ 10867 if (!SOC_IS_TOMAHAWK3(unit)) { 10868 return BCM_E_UNAVAIL; 10869 } 10870 10871 if ((vrf > SOC_VRF_MAX(unit)) || 10872 (vrf < BCM_L3_VRF_GLOBAL)) { 10873 return (BCM_E_PARAM); 10874 } 10875 10876 rv = bcm_esw_alpm_vrf_data_mode_set(unit, vrf, flags, mode); 10877 10878 return rv; 10879 10880 #else /* BCM_TOMAHAWK3_SUPPORT */ 10881 return BCM_E_UNAVAIL; 10882 #endif 10883 #else /* ALPM_ENABLE */ 10884 return BCM_E_UNAVAIL; 10885 #endif 10886 } 10887 10888 /* 10889 * Function: 10890 * bcm_esw_l3_source_bind_enable_set 10891 * Purpose: 10892 * Enable or disable l3 source binding checks on an ingress port. 10893 * Parameters: 10894 * unit - (IN) Unit number. 10895 * port - (IN) Packet ingress port. 10896 * enable - (IN) Non-zero to enable l3 source binding checks, 10897 * zero to disable. 10898 * Returns: 10899 * BCM_E_XXX 10900 * Notes: 10901 */ 10902 int 10903 bcm_esw_l3_source_bind_enable_set(int unit, bcm_port_t port, int enable) 10904 { 10905 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 10906 int key_type_value; 10907 int key_type; 10908 _bcm_port_config_t key_config, port_config; 10909 10910 if (!soc_feature(unit, soc_feature_ip_source_bind)) { 10911 return BCM_E_UNAVAIL; 10912 } 10913 10914 if (enable) { 10915 BCM_IF_ERROR_RETURN 10916 (_bcm_esw_port_config_get(unit, port, 10917 _bcmPortVTKeyTypeSecond, &key_type_value)); 10918 BCM_IF_ERROR_RETURN 10919 (_bcm_esw_pt_vtkey_type_get(unit,key_type_value,&key_type)); 10920 10921 if (key_type == VLXLT_HASH_KEY_TYPE_OVID) { 10922 /* Overwrite OVID if it's in second slot */ 10923 key_config = _bcmPortVTKeyTypeSecond; 10924 port_config = _bcmPortVTKeyPortSecond; 10925 } else { /* Otherwise just use first slot */ 10926 key_config = _bcmPortVTKeyTypeFirst; 10927 port_config = _bcmPortVTKeyPortFirst; 10928 } 10929 10930 BCM_IF_ERROR_RETURN 10931 (_bcm_esw_pt_vtkey_type_value_get(unit, 10932 VLXLT_HASH_KEY_TYPE_HPAE,&key_type_value)); 10933 BCM_IF_ERROR_RETURN 10934 (_bcm_esw_port_config_set(unit, port, key_config, 10935 key_type_value)); 10936 BCM_IF_ERROR_RETURN 10937 (_bcm_esw_pt_vtkey_type_value_get(unit, 10938 VLXLT_HASH_KEY_TYPE_OTAG,&key_type_value)); 10939 BCM_IF_ERROR_RETURN 10940 (_bcm_esw_port_config_set(unit, port, port_config, 10941 key_type_value)); 10942 } else { 10943 BCM_IF_ERROR_RETURN 10944 (_bcm_esw_port_config_get(unit, port, 10945 _bcmPortVTKeyTypeSecond, &key_type_value)); 10946 BCM_IF_ERROR_RETURN 10947 (_bcm_esw_pt_vtkey_type_get(unit,key_type_value,&key_type)); 10948 if (key_type == VLXLT_HASH_KEY_TYPE_HPAE) { 10949 key_config = _bcmPortVTKeyTypeSecond; 10950 port_config = _bcmPortVTKeyPortSecond; 10951 } else { 10952 BCM_IF_ERROR_RETURN 10953 (_bcm_esw_port_config_get(unit, port, 10954 _bcmPortVTKeyTypeFirst, 10955 &key_type_value)); 10956 BCM_IF_ERROR_RETURN 10957 (_bcm_esw_pt_vtkey_type_get(unit, 10958 key_type_value,&key_type)); 10959 if (key_type == VLXLT_HASH_KEY_TYPE_HPAE) { 10960 key_config = _bcmPortVTKeyTypeFirst; 10961 port_config = _bcmPortVTKeyPortFirst; 10962 } else { 10963 /* Already not enabled */ 10964 return BCM_E_NONE; 10965 } 10966 } 10967 /* Return to OVID usage */ 10968 BCM_IF_ERROR_RETURN 10969 (_bcm_esw_pt_vtkey_type_value_get(unit, 10970 VLXLT_HASH_KEY_TYPE_OVID,&key_type_value)); 10971 BCM_IF_ERROR_RETURN 10972 (_bcm_esw_port_config_set(unit, port, key_config, 10973 key_type_value)); 10974 BCM_IF_ERROR_RETURN 10975 (_bcm_esw_pt_vtkey_type_value_get(unit, 10976 VLXLT_HASH_KEY_TYPE_OTAG,&key_type_value)); 10977 BCM_IF_ERROR_RETURN 10978 (_bcm_esw_port_config_set(unit, port, port_config, 10979 key_type_value)); 10980 } 10981 return BCM_E_NONE; 10982 #else 10983 return BCM_E_UNAVAIL; 10984 #endif 10985 } 10986 10987 /* 10988 * Function: 10989 * bcm_eswl3_source_bind_enable_get 10990 * Purpose: 10991 * Retrieve whether l3 source binding checks are performed on an 10992 * ingress port. 10993 * Parameters: 10994 * unit - (IN) Unit number. 10995 * port - (IN) Packet ingress port. 10996 * enable - (OUT) Non-zero if l3 source binding checks are enabled, 10997 * zero if disabled. 10998 * Returns: 10999 * BCM_E_XXX 11000 * Notes: 11001 */ 11002 int 11003 bcm_esw_l3_source_bind_enable_get(int unit, bcm_port_t port, int *enable) 11004 { 11005 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 11006 int key_type; 11007 int key_type_value; 11008 if (!soc_feature(unit, soc_feature_ip_source_bind)) { 11009 return BCM_E_UNAVAIL; 11010 } 11011 11012 BCM_IF_ERROR_RETURN 11013 (_bcm_esw_port_config_get(unit, port, 11014 _bcmPortVTKeyTypeSecond, &key_type_value)); 11015 BCM_IF_ERROR_RETURN 11016 (_bcm_esw_pt_vtkey_type_get(unit,key_type_value,&key_type)); 11017 11018 if (key_type == VLXLT_HASH_KEY_TYPE_HPAE) { 11019 *enable = TRUE; 11020 } else { 11021 BCM_IF_ERROR_RETURN 11022 (_bcm_esw_port_config_get(unit, port, 11023 _bcmPortVTKeyTypeFirst, &key_type_value)); 11024 BCM_IF_ERROR_RETURN 11025 (_bcm_esw_pt_vtkey_type_get(unit,key_type_value,&key_type)); 11026 if (key_type == VLXLT_HASH_KEY_TYPE_HPAE) { 11027 *enable = TRUE; 11028 } else { 11029 *enable = FALSE; 11030 } 11031 } 11032 11033 return BCM_E_NONE; 11034 #else 11035 return BCM_E_UNAVAIL; 11036 #endif 11037 } 11038 11039 #if defined(BCM_TRIUMPH3_SUPPORT) 11040 STATIC int 11041 _tr3_l3_source_bind_add(int unit, bcm_l3_source_bind_t *info) 11042 { 11043 int tmp_id, rv, idx = 0; 11044 bcm_module_t modid_out; 11045 bcm_port_t port_out; 11046 bcm_trunk_t trunk_out; 11047 vlan_xlate_extd_entry_t vxent, res_vxent; 11048 11049 if (!soc_feature(unit, soc_feature_ip_source_bind)) { 11050 return BCM_E_UNAVAIL; 11051 } 11052 11053 if (info->flags & BCM_L3_SOURCE_BIND_IP6) { 11054 /* Not supported yet */ 11055 return BCM_E_UNAVAIL; 11056 } 11057 11058 if (info->flags & BCM_L3_SOURCE_BIND_USE_MASK) { 11059 /* Not supported */ 11060 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 11061 "%s: failed with error : %s \n"), FUNCTION_NAME(), 11062 bcm_errmsg(BCM_E_PARAM))); 11063 return BCM_E_PARAM; 11064 } 11065 11066 sal_memset(&vxent, 0, sizeof(vlan_xlate_extd_entry_t)); 11067 sal_memset(&res_vxent, 0, sizeof(vlan_xlate_extd_entry_t)); 11068 11069 /* MAC_IP_BIND lookup key type */ 11070 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, VALID_0f, 1); 11071 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, VALID_1f, 1); 11072 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, KEY_TYPE_0f, 11073 TR3_VLXLT_HASH_KEY_TYPE_HPAE); 11074 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, KEY_TYPE_1f, 11075 TR3_VLXLT_HASH_KEY_TYPE_HPAE); 11076 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, 11077 MAC_IP_BIND__SIPf, info->ip); 11078 11079 rv = soc_mem_search(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ALL, &idx, 11080 &vxent, &res_vxent, 0); 11081 11082 if (BCM_SUCCESS(rv)) { 11083 if (soc_VLAN_XLATE_EXTDm_field32_get(unit, &res_vxent, VALID_0f)) { 11084 /* Valid entry found */ 11085 if ((info->flags & BCM_L3_SOURCE_BIND_REPLACE) == 0) { 11086 /* Entry exists! */ 11087 return BCM_E_EXISTS; 11088 } 11089 } 11090 } else if (rv != SOC_E_NOT_FOUND) { 11091 return rv; 11092 } 11093 11094 if (info->port == BCM_GPORT_INVALID) { 11095 /* wild card */ 11096 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, 11097 MAC_IP_BIND__MODULE_IDf, 0x7f); 11098 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, 11099 MAC_IP_BIND__Tf, 1); 11100 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, 11101 MAC_IP_BIND__PORT_NUMf, 0x3f); 11102 } else if (BCM_GPORT_IS_SET(info->port)) { 11103 BCM_IF_ERROR_RETURN 11104 (_bcm_esw_gport_resolve(unit, info->port, &modid_out, 11105 &port_out, &trunk_out, &tmp_id)); 11106 if (-1 != tmp_id) { 11107 return BCM_E_PARAM; 11108 } 11109 if (BCM_TRUNK_INVALID != trunk_out) { 11110 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, 11111 MAC_IP_BIND__Tf, 1); 11112 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, 11113 MAC_IP_BIND__MODULE_IDf, (trunk_out >> 6) & 0x1); 11114 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, 11115 MAC_IP_BIND__PORT_NUMf, trunk_out & 0x3f); 11116 } else { 11117 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, 11118 MAC_IP_BIND__MODULE_IDf, modid_out); 11119 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, 11120 MAC_IP_BIND__PORT_NUMf, port_out); 11121 } 11122 } else { 11123 return BCM_E_PORT; 11124 } 11125 11126 soc_VLAN_XLATE_EXTDm_mac_addr_set(unit, &vxent, 11127 MAC_IP_BIND__MAC_ADDRf, info->mac); 11128 11129 if (soc_feature(unit, soc_feature_ipfix_rate) && info->rate_id != 0) { 11130 soc_VLAN_XLATE_EXTDm_field32_set 11131 (unit, &vxent, MAC_IP_BIND__IPFIX_FLOW_METER_IDf, info->rate_id); 11132 } 11133 11134 rv = soc_mem_insert(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ALL, &vxent); 11135 11136 if ((rv == SOC_E_EXISTS) && 11137 (info->flags & BCM_L3_SOURCE_BIND_REPLACE)) { 11138 rv = BCM_E_NONE; 11139 } 11140 11141 return rv; 11142 } 11143 #endif /* BCM_TRIUMPH3_SUPPORT */ 11144 11145 #if defined(BCM_TRIDENT3_SUPPORT) 11146 STATIC int 11147 _td3_l3_source_bind_add(int unit, bcm_l3_source_bind_t *info) 11148 { 11149 int tmp_id, rv, idx = 0; 11150 bcm_module_t modid_out; 11151 bcm_port_t port_out; 11152 bcm_trunk_t trunk_out; 11153 vlan_xlate_1_double_entry_t vxent, res_vxent; 11154 11155 if (!soc_feature(unit, soc_feature_ip_source_bind)) { 11156 return BCM_E_UNAVAIL; 11157 } 11158 11159 if (info->flags & BCM_L3_SOURCE_BIND_IP6) { 11160 /* Not supported yet */ 11161 return BCM_E_UNAVAIL; 11162 } 11163 11164 if (info->flags & BCM_L3_SOURCE_BIND_USE_MASK) { 11165 /* Not supported */ 11166 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 11167 "failed with error : %s \n"), 11168 bcm_errmsg(BCM_E_PARAM))); 11169 return BCM_E_PARAM; 11170 } 11171 11172 sal_memset(&vxent, 0, sizeof(vlan_xlate_1_double_entry_t)); 11173 sal_memset(&res_vxent, 0, sizeof(vlan_xlate_1_double_entry_t)); 11174 11175 /* MAC_IP_BIND lookup key type */ 11176 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, BASE_VALID_0f, 3); 11177 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, BASE_VALID_1f, 7); 11178 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, DATA_TYPEf, 11179 7); 11180 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, KEY_TYPEf, 7); 11181 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, 11182 MAC_IP_BIND__SIPf, info->ip); 11183 11184 rv = soc_mem_search(unit, VLAN_XLATE_1_DOUBLEm, MEM_BLOCK_ALL, &idx, 11185 &vxent, &res_vxent, 0); 11186 11187 if (BCM_SUCCESS(rv)) { 11188 if (soc_VLAN_XLATE_1_DOUBLEm_field32_get(unit, &res_vxent, BASE_VALID_0f)) { 11189 /* Valid entry found */ 11190 if ((info->flags & BCM_L3_SOURCE_BIND_REPLACE) == 0) { 11191 /* Entry exists! */ 11192 return BCM_E_EXISTS; 11193 } 11194 } 11195 } else if (rv != SOC_E_NOT_FOUND) { 11196 return rv; 11197 } 11198 11199 if (info->port == BCM_GPORT_INVALID) { 11200 /* wild card */ 11201 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, 11202 MAC_IP_BIND__SRC_MODIDf, 0x7f); 11203 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, 11204 MAC_IP_BIND__SRC_Tf, 1); 11205 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, 11206 MAC_IP_BIND__SRC_PORTf, 0x3f); 11207 } else if (BCM_GPORT_IS_SET(info->port)) { 11208 BCM_IF_ERROR_RETURN 11209 (_bcm_esw_gport_resolve(unit, info->port, &modid_out, 11210 &port_out, &trunk_out, &tmp_id)); 11211 if (-1 != tmp_id) { 11212 return BCM_E_PARAM; 11213 } 11214 if (BCM_TRUNK_INVALID != trunk_out) { 11215 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, 11216 MAC_IP_BIND__SRC_Tf, 1); 11217 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, 11218 MAC_IP_BIND__SRC_MODIDf, (trunk_out >> 6) & 0x1); 11219 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, 11220 MAC_IP_BIND__SRC_PORTf, trunk_out & 0x3f); 11221 } else { 11222 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, 11223 MAC_IP_BIND__SRC_MODIDf, modid_out); 11224 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, 11225 MAC_IP_BIND__SRC_PORTf, port_out); 11226 } 11227 } else { 11228 return BCM_E_PORT; 11229 } 11230 11231 soc_VLAN_XLATE_1_DOUBLEm_mac_addr_set(unit, &vxent, 11232 MAC_IP_BIND__HPAE_MAC_ADDRf, info->mac); 11233 11234 rv = soc_mem_insert(unit, VLAN_XLATE_1_DOUBLEm, MEM_BLOCK_ALL, &vxent); 11235 11236 if ((rv == SOC_E_EXISTS) && 11237 (info->flags & BCM_L3_SOURCE_BIND_REPLACE)) { 11238 rv = BCM_E_NONE; 11239 } 11240 11241 return rv; 11242 } 11243 STATIC int 11244 _td3_l3_source_bind_delete(int unit, bcm_l3_source_bind_t *info) 11245 { 11246 vlan_xlate_1_double_entry_t vxent; 11247 int rv; 11248 11249 if (!soc_feature(unit, soc_feature_ip_source_bind)) { 11250 return BCM_E_UNAVAIL; 11251 } 11252 11253 if (info->flags & BCM_L3_SOURCE_BIND_IP6) { 11254 /* Not supported yet */ 11255 return BCM_E_UNAVAIL; 11256 } 11257 11258 if (info->flags & BCM_L3_SOURCE_BIND_USE_MASK) { 11259 /* Not supported */ 11260 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 11261 "%s: failed with error : %s \n"), FUNCTION_NAME(), 11262 bcm_errmsg(BCM_E_PARAM))); 11263 return BCM_E_PARAM; 11264 } 11265 11266 sal_memset(&vxent, 0, sizeof(vxent)); 11267 11268 /* MAC_IP_BIND key type */ 11269 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, BASE_VALID_0f, 3); 11270 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, BASE_VALID_1f, 7); 11271 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, DATA_TYPEf, 11272 7); 11273 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, KEY_TYPEf, 7); 11274 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, 11275 MAC_IP_BIND__SIPf, info->ip); 11276 11277 rv = soc_mem_delete(unit, VLAN_XLATE_1_DOUBLEm, MEM_BLOCK_ALL, &vxent); 11278 11279 return rv; 11280 } 11281 11282 STATIC int 11283 _td3_l3_source_bind_delete_all(int unit) 11284 { 11285 vlan_xlate_1_double_entry_t *vxent, *vxentp; 11286 int idx, imin, imax, nent, vmbytes, rv; 11287 11288 if (!soc_feature(unit, soc_feature_ip_source_bind)) { 11289 return BCM_E_UNAVAIL; 11290 } 11291 11292 imin = soc_mem_index_min(unit, VLAN_XLATE_1_DOUBLEm); 11293 imax = soc_mem_index_max(unit, VLAN_XLATE_1_DOUBLEm); 11294 nent = soc_mem_index_count(unit, VLAN_XLATE_1_DOUBLEm); 11295 vmbytes = soc_mem_entry_words(unit, VLAN_XLATE_1_DOUBLEm); 11296 vmbytes = WORDS2BYTES(vmbytes); 11297 vxent = soc_cm_salloc(unit, nent * sizeof(*vxent), "vlan_xlate_1_double"); 11298 11299 if (vxent == NULL) { 11300 return BCM_E_MEMORY; 11301 } 11302 11303 soc_mem_lock(unit, VLAN_XLATE_1_DOUBLEm); 11304 rv = soc_mem_read_range(unit, VLAN_XLATE_1_DOUBLEm, MEM_BLOCK_ANY, 11305 imin, imax, vxent); 11306 if (BCM_FAILURE(rv)) { 11307 soc_mem_unlock(unit, VLAN_XLATE_1_DOUBLEm); 11308 soc_cm_sfree(unit, vxent); 11309 return rv; 11310 } 11311 11312 for(idx = 0; idx < nent; idx++) { 11313 vxentp = soc_mem_table_idx_to_pointer(unit, VLAN_XLATE_1_DOUBLEm, 11314 vlan_xlate_1_double_entry_t *, vxent, idx); 11315 11316 if ((0 == soc_VLAN_XLATE_1_DOUBLEm_field32_get(unit, vxentp, 11317 BASE_VALID_0f)) || (TD3_VLXLT_HASH_KEY_TYPE_HPAE != 11318 soc_VLAN_XLATE_1_DOUBLEm_field32_get(unit, vxentp, KEY_TYPEf))) { 11319 continue; 11320 } 11321 11322 rv = soc_mem_delete(unit, VLAN_XLATE_1_DOUBLEm, MEM_BLOCK_ALL, vxentp); 11323 if (BCM_FAILURE(rv)) { 11324 soc_mem_unlock(unit, VLAN_XLATE_1_DOUBLEm); 11325 soc_cm_sfree(unit, vxent); 11326 return rv; 11327 } 11328 } 11329 11330 soc_mem_unlock(unit, VLAN_XLATE_1_DOUBLEm); 11331 soc_cm_sfree(unit, vxent); 11332 return rv; 11333 } 11334 #endif /* BCM_TRIDENT3_SUPPORT */ 11335 11336 #if defined(BCM_TRIUMPH2_SUPPORT) 11337 STATIC int 11338 _tr2_l3_source_bind_add(int unit, bcm_l3_source_bind_t *info) 11339 { 11340 int tmp_id, rv, idx = 0; 11341 bcm_module_t modid_out; 11342 bcm_port_t port_out; 11343 bcm_trunk_t trunk_out; 11344 vlan_mac_entry_t vment, res_vment; 11345 11346 if (!soc_feature(unit, soc_feature_ip_source_bind)) { 11347 return BCM_E_UNAVAIL; 11348 } 11349 11350 if (info->flags & BCM_L3_SOURCE_BIND_IP6) { 11351 /* Not supported yet */ 11352 return BCM_E_UNAVAIL; 11353 } 11354 11355 if (info->flags & BCM_L3_SOURCE_BIND_USE_MASK) { 11356 /* Not supported */ 11357 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 11358 "%s: failed with error : %s \n"), FUNCTION_NAME(), 11359 bcm_errmsg(BCM_E_PARAM))); 11360 return BCM_E_PARAM; 11361 } 11362 11363 sal_memset(&vment, 0, sizeof(vlan_mac_entry_t)); 11364 sal_memset(&res_vment, 0, sizeof(vlan_mac_entry_t)); 11365 11366 /* MAC_IP_BIND lookup key type */ 11367 soc_VLAN_MACm_field32_set(unit, &vment, VALIDf, 1); 11368 soc_VLAN_MACm_field32_set(unit, &vment, KEY_TYPEf, 11369 TR_VLXLT_HASH_KEY_TYPE_HPAE); 11370 soc_VLAN_MACm_field32_set(unit, &vment, 11371 MAC_IP_BIND__SIPf, info->ip); 11372 11373 rv = soc_mem_search(unit, VLAN_MACm, MEM_BLOCK_ALL, &idx, 11374 &vment, &res_vment, 0); 11375 11376 if (BCM_SUCCESS(rv)) { 11377 if (soc_VLAN_MACm_field32_get(unit, &res_vment, VALIDf)) { 11378 /* Valid entry found */ 11379 if ((info->flags & BCM_L3_SOURCE_BIND_REPLACE) == 0) { 11380 /* Entry exists! */ 11381 return BCM_E_EXISTS; 11382 } 11383 } 11384 } else if (rv != SOC_E_NOT_FOUND) { 11385 return rv; 11386 } 11387 11388 if (info->port == BCM_GPORT_INVALID) { 11389 /* wild card */ 11390 soc_VLAN_MACm_field32_set(unit, &vment, 11391 MAC_IP_BIND__SRC_MODIDf, 0x7f); 11392 soc_VLAN_MACm_field32_set(unit, &vment, 11393 MAC_IP_BIND__SRC_Tf, 1); 11394 soc_VLAN_MACm_field32_set(unit, &vment, 11395 MAC_IP_BIND__SRC_PORTf, 0x3f); 11396 } else if (BCM_GPORT_IS_SET(info->port)) { 11397 BCM_IF_ERROR_RETURN 11398 (_bcm_esw_gport_resolve(unit, info->port, &modid_out, 11399 &port_out, &trunk_out, &tmp_id)); 11400 if (-1 != tmp_id) { 11401 return BCM_E_PARAM; 11402 } 11403 if (BCM_TRUNK_INVALID != trunk_out) { 11404 soc_VLAN_MACm_field32_set(unit, &vment, 11405 MAC_IP_BIND__SRC_Tf, 1); 11406 soc_VLAN_MACm_field32_set(unit, &vment, MAC_IP_BIND__SRC_MODIDf, 11407 (trunk_out >> 6) & 0x1); 11408 soc_VLAN_MACm_field32_set(unit, &vment, MAC_IP_BIND__SRC_PORTf, 11409 trunk_out & 0x3f); 11410 } else { 11411 soc_VLAN_MACm_field32_set(unit, &vment, MAC_IP_BIND__SRC_MODIDf, 11412 modid_out); 11413 soc_VLAN_MACm_field32_set(unit, &vment, MAC_IP_BIND__SRC_PORTf, 11414 port_out); 11415 } 11416 } else { 11417 return BCM_E_PORT; 11418 } 11419 11420 soc_VLAN_MACm_mac_addr_set(unit, &vment, 11421 MAC_IP_BIND__HPAE_MAC_ADDRf, info->mac); 11422 11423 if (soc_feature(unit, soc_feature_ipfix_rate) && info->rate_id != 0) { 11424 soc_VLAN_MACm_field32_set 11425 (unit, &vment, MAC_IP_BIND__IPFIX_FLOW_METER_IDf, info->rate_id); 11426 } 11427 11428 rv = soc_mem_insert(unit, VLAN_MACm, MEM_BLOCK_ALL, &vment); 11429 11430 if ((rv == SOC_E_EXISTS) && 11431 (info->flags & BCM_L3_SOURCE_BIND_REPLACE)) { 11432 rv = BCM_E_NONE; 11433 } 11434 11435 return rv; 11436 } 11437 #endif /* BCM_TRIUMPH2_SUPPORT */ 11438 11439 /* 11440 * Function: 11441 * bcm_esw_l3_source_bind_add 11442 * Purpose: 11443 * Add or replace an L3 source binding. 11444 * Parameters: 11445 * unit - (IN) Unit number. 11446 * info - (IN) L3 source binding information 11447 * Returns: 11448 * BCM_E_XXX 11449 * Notes: 11450 */ 11451 int 11452 bcm_esw_l3_source_bind_add(int unit, bcm_l3_source_bind_t *info) 11453 { 11454 #if defined(BCM_TRIUMPH3_SUPPORT) 11455 if (SOC_IS_TRIUMPH3(unit)) { 11456 BCM_IF_ERROR_RETURN 11457 (_tr3_l3_source_bind_add(unit,info)); 11458 return BCM_E_NONE; 11459 } 11460 #endif 11461 #if defined(BCM_TRIDENT3_SUPPORT) 11462 if ((SOC_IS_TRIDENT3X(unit))) { 11463 BCM_IF_ERROR_RETURN 11464 (_td3_l3_source_bind_add(unit,info)); 11465 return BCM_E_NONE; 11466 } 11467 #endif 11468 #if defined(BCM_TRIUMPH2_SUPPORT) 11469 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_HURRICANE2(unit)) { 11470 BCM_IF_ERROR_RETURN 11471 (_tr2_l3_source_bind_add(unit,info)); 11472 return BCM_E_NONE; 11473 } 11474 #endif 11475 return BCM_E_UNAVAIL; 11476 } 11477 11478 #if defined(BCM_TRIUMPH3_SUPPORT) 11479 STATIC int 11480 _tr3_l3_source_bind_delete(int unit, bcm_l3_source_bind_t *info) 11481 { 11482 vlan_xlate_extd_entry_t vxent; 11483 int rv; 11484 11485 if (!soc_feature(unit, soc_feature_ip_source_bind)) { 11486 return BCM_E_UNAVAIL; 11487 } 11488 11489 if (info->flags & BCM_L3_SOURCE_BIND_IP6) { 11490 /* Not supported yet */ 11491 return BCM_E_UNAVAIL; 11492 } 11493 11494 if (info->flags & BCM_L3_SOURCE_BIND_USE_MASK) { 11495 /* Not supported */ 11496 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 11497 "%s: failed with error : %s \n"), FUNCTION_NAME(), 11498 bcm_errmsg(BCM_E_PARAM))); 11499 return BCM_E_PARAM; 11500 } 11501 11502 sal_memset(&vxent, 0, sizeof(vxent)); 11503 11504 /* MAC_IP_BIND key type */ 11505 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, VALID_0f, 1); 11506 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, VALID_1f, 1); 11507 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, KEY_TYPE_0f, 11508 TR3_VLXLT_HASH_KEY_TYPE_HPAE); 11509 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, KEY_TYPE_1f, 11510 TR3_VLXLT_HASH_KEY_TYPE_HPAE); 11511 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, 11512 MAC_IP_BIND__SIPf, info->ip); 11513 11514 rv = soc_mem_delete(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ALL, &vxent); 11515 11516 return rv; 11517 } 11518 #endif /* BCM_TRIUMPH3_SUPPORT */ 11519 11520 #if defined(BCM_TRIUMPH2_SUPPORT) 11521 STATIC int 11522 _tr2_l3_source_bind_delete(int unit, bcm_l3_source_bind_t *info) 11523 { 11524 vlan_mac_entry_t vment; 11525 int rv; 11526 11527 if (!soc_feature(unit, soc_feature_ip_source_bind)) { 11528 return BCM_E_UNAVAIL; 11529 } 11530 11531 if (info->flags & BCM_L3_SOURCE_BIND_IP6) { 11532 /* Not supported yet */ 11533 return BCM_E_UNAVAIL; 11534 } 11535 11536 if (info->flags & BCM_L3_SOURCE_BIND_USE_MASK) { 11537 /* Not supported */ 11538 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 11539 "%s: failed with error : %s \n"), FUNCTION_NAME(), 11540 bcm_errmsg(BCM_E_PARAM))); 11541 return BCM_E_PARAM; 11542 } 11543 11544 sal_memset(&vment, 0, sizeof(vment)); 11545 11546 /* MAC_IP_BIND key type */ 11547 soc_VLAN_MACm_field32_set(unit, &vment, VALIDf, 1); 11548 soc_VLAN_MACm_field32_set(unit, &vment, KEY_TYPEf, 11549 TR_VLXLT_HASH_KEY_TYPE_HPAE); 11550 soc_VLAN_MACm_field32_set(unit, &vment, 11551 MAC_IP_BIND__SIPf, info->ip); 11552 11553 rv = soc_mem_delete(unit, VLAN_MACm, MEM_BLOCK_ALL, &vment); 11554 11555 return rv; 11556 } 11557 #endif /* BCM_TRIUMPH2_SUPPORT */ 11558 11559 /* 11560 * Function: 11561 * bcm_esw_l3_source_bind_delete 11562 * Purpose: 11563 * Remove an existing L3 source binding. 11564 * Parameters: 11565 * unit - (IN) Unit number. 11566 * info - (IN) L3 source binding information 11567 * Returns: 11568 * BCM_E_XXX 11569 * Notes: 11570 */ 11571 int 11572 bcm_esw_l3_source_bind_delete(int unit, bcm_l3_source_bind_t *info) 11573 { 11574 #if defined(BCM_TRIDENT3_SUPPORT) 11575 if (SOC_IS_TRIDENT3X(unit)) { 11576 BCM_IF_ERROR_RETURN 11577 (_td3_l3_source_bind_delete(unit,info)); 11578 return BCM_E_NONE; 11579 } 11580 #endif 11581 #if defined(BCM_TRIUMPH3_SUPPORT) 11582 if (SOC_IS_TRIUMPH3(unit)) { 11583 BCM_IF_ERROR_RETURN 11584 (_tr3_l3_source_bind_delete(unit,info)); 11585 return BCM_E_NONE; 11586 } 11587 #endif 11588 #if defined(BCM_TRIUMPH2_SUPPORT) 11589 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_HURRICANE2(unit)) { 11590 BCM_IF_ERROR_RETURN 11591 (_tr2_l3_source_bind_delete(unit,info)); 11592 return BCM_E_NONE; 11593 } 11594 #endif 11595 return BCM_E_UNAVAIL; 11596 11597 } 11598 11599 #if defined(BCM_TRIUMPH3_SUPPORT) 11600 STATIC int 11601 _tr3_l3_source_bind_delete_all(int unit) 11602 { 11603 int idx, imin, imax, nent, vmbytes, rv; 11604 vlan_xlate_extd_entry_t * vxtab, *vxtabp; 11605 11606 if (!soc_feature(unit, soc_feature_ip_source_bind)) { 11607 return BCM_E_UNAVAIL; 11608 } 11609 11610 imin = soc_mem_index_min(unit, VLAN_XLATE_EXTDm); 11611 imax = soc_mem_index_max(unit, VLAN_XLATE_EXTDm); 11612 nent = soc_mem_index_count(unit, VLAN_XLATE_EXTDm); 11613 vmbytes = soc_mem_entry_words(unit, VLAN_XLATE_EXTDm); 11614 vmbytes = WORDS2BYTES(vmbytes); 11615 vxtab = soc_cm_salloc(unit, nent * sizeof(*vxtab), "vlan_xlate_extd"); 11616 11617 if (vxtab == NULL) { 11618 return BCM_E_MEMORY; 11619 } 11620 11621 soc_mem_lock(unit, VLAN_XLATE_EXTDm); 11622 rv = soc_mem_read_range(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ANY, 11623 imin, imax, vxtab); 11624 if (BCM_FAILURE(rv)) { 11625 soc_mem_unlock(unit, VLAN_XLATE_EXTDm); 11626 soc_cm_sfree(unit, vxtab); 11627 return rv; 11628 } 11629 11630 for(idx = 0; idx < nent; idx++) { 11631 vxtabp = soc_mem_table_idx_to_pointer(unit, VLAN_XLATE_EXTDm, 11632 vlan_xlate_extd_entry_t *, 11633 vxtab, idx); 11634 11635 if ((0 == soc_VLAN_XLATE_EXTDm_field32_get(unit, vxtabp, VALID_0f)) || 11636 (TR3_VLXLT_HASH_KEY_TYPE_HPAE != 11637 soc_VLAN_XLATE_EXTDm_field32_get(unit, vxtabp, KEY_TYPE_0f))) { 11638 continue; 11639 } 11640 11641 rv = soc_mem_delete(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ALL, vxtabp); 11642 if (BCM_FAILURE(rv)) { 11643 soc_mem_unlock(unit, VLAN_XLATE_EXTDm); 11644 soc_cm_sfree(unit, vxtab); 11645 return rv; 11646 } 11647 } 11648 11649 soc_mem_unlock(unit, VLAN_XLATE_EXTDm); 11650 soc_cm_sfree(unit, vxtab); 11651 return rv; 11652 } 11653 #endif /* BCM_TRIUMPH3_SUPPORT */ 11654 11655 #if defined(BCM_TRIUMPH2_SUPPORT) 11656 STATIC int 11657 _tr2_l3_source_bind_delete_all(int unit) 11658 { 11659 int idx, imin, imax, nent, vmbytes, rv; 11660 vlan_mac_entry_t * vmtab, *vmtabp; 11661 11662 if (!soc_feature(unit, soc_feature_ip_source_bind)) { 11663 return BCM_E_UNAVAIL; 11664 } 11665 11666 imin = soc_mem_index_min(unit, VLAN_MACm); 11667 imax = soc_mem_index_max(unit, VLAN_MACm); 11668 nent = soc_mem_index_count(unit, VLAN_MACm); 11669 vmbytes = soc_mem_entry_words(unit, VLAN_MACm); 11670 vmbytes = WORDS2BYTES(vmbytes); 11671 vmtab = soc_cm_salloc(unit, nent * sizeof(*vmtab), "vlan_mac"); 11672 11673 if (vmtab == NULL) { 11674 return BCM_E_MEMORY; 11675 } 11676 11677 soc_mem_lock(unit, VLAN_MACm); 11678 rv = soc_mem_read_range(unit, VLAN_MACm, MEM_BLOCK_ANY, 11679 imin, imax, vmtab); 11680 if (BCM_FAILURE(rv)) { 11681 soc_mem_unlock(unit, VLAN_MACm); 11682 soc_cm_sfree(unit, vmtab); 11683 return rv; 11684 } 11685 11686 for(idx = 0; idx < nent; idx++) { 11687 vmtabp = soc_mem_table_idx_to_pointer(unit, VLAN_MACm, 11688 vlan_mac_entry_t *, 11689 vmtab, idx); 11690 11691 if ((0 == soc_VLAN_MACm_field32_get(unit, vmtabp, VALIDf)) || 11692 (TR_VLXLT_HASH_KEY_TYPE_HPAE != 11693 soc_VLAN_MACm_field32_get(unit, vmtabp, KEY_TYPEf))) { 11694 continue; 11695 } 11696 11697 rv = soc_mem_delete(unit, VLAN_MACm, MEM_BLOCK_ALL, vmtabp); 11698 if (BCM_FAILURE(rv)) { 11699 soc_mem_unlock(unit, VLAN_MACm); 11700 soc_cm_sfree(unit, vmtab); 11701 return rv; 11702 } 11703 } 11704 11705 soc_mem_unlock(unit, VLAN_MACm); 11706 soc_cm_sfree(unit, vmtab); 11707 return rv; 11708 } 11709 #endif /* BCM_TRIUMPH2_SUPPORT */ 11710 11711 /* 11712 * Function: 11713 * bcm_esw_l3_source_bind_delete_all 11714 * Purpose: 11715 * Remove all existing L3 source bindings. 11716 * Parameters: 11717 * unit - (IN) Unit number. 11718 * Returns: 11719 * BCM_E_XXX 11720 * Notes: 11721 */ 11722 int 11723 bcm_esw_l3_source_bind_delete_all(int unit) 11724 { 11725 #if defined(BCM_TRIUMPH3_SUPPORT) 11726 if (SOC_IS_TRIUMPH3(unit)) { 11727 BCM_IF_ERROR_RETURN 11728 (_tr3_l3_source_bind_delete_all(unit)); 11729 return BCM_E_NONE; 11730 } 11731 #endif 11732 #if defined(BCM_TRIUMPH2_SUPPORT) 11733 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_HURRICANE2(unit)) { 11734 BCM_IF_ERROR_RETURN 11735 (_tr2_l3_source_bind_delete_all(unit)); 11736 return BCM_E_NONE; 11737 } 11738 #endif 11739 #if defined(BCM_TRIDENT3_SUPPORT) 11740 if (SOC_IS_TRIDENT3X(unit)) { 11741 BCM_IF_ERROR_RETURN 11742 (_td3_l3_source_bind_delete_all(unit)); 11743 return BCM_E_NONE; 11744 } 11745 #endif 11746 return BCM_E_UNAVAIL; 11747 } 11748 11749 #if defined(BCM_TRIDENT3_SUPPORT) 11750 STATIC int 11751 _td3_l3_source_bind_hw_entry_to_sw_info(int unit, 11752 vlan_xlate_1_double_entry_t *vxent, 11753 bcm_l3_source_bind_t *info) 11754 { 11755 int t_bit; 11756 bcm_module_t modid; 11757 bcm_port_t port; 11758 11759 bcm_l3_source_bind_t_init(info); 11760 info->ip = soc_VLAN_XLATE_1_DOUBLEm_field32_get(unit, vxent, 11761 MAC_IP_BIND__SIPf); 11762 soc_VLAN_XLATE_1_DOUBLEm_mac_addr_get(unit, &vxent, 11763 MAC_IP_BIND__HPAE_MAC_ADDRf, info->mac); 11764 11765 /* Port analysis */ 11766 11767 port = soc_VLAN_XLATE_1_DOUBLEm_field32_get(unit, &vxent, 11768 MAC_IP_BIND__SRC_PORTf); 11769 modid = soc_VLAN_XLATE_1_DOUBLEm_field32_get(unit, &vxent, 11770 MAC_IP_BIND__SRC_MODIDf); 11771 t_bit = soc_VLAN_XLATE_1_DOUBLEm_field32_get(unit, &vxent, 11772 MAC_IP_BIND__SRC_Tf); 11773 if (t_bit == 1) { 11774 if ((modid == 0x7f) && (port == 0x3f)) { 11775 info->port = BCM_GPORT_TYPE_BLACK_HOLE; /* Wild card */ 11776 } else { 11777 BCM_IF_ERROR_RETURN 11778 (_bcm_esw_l3_gport_construct(unit, 0, 0, 11779 (port & 0x3f) | ((modid & 0x1) << 6), 11780 BCM_L3_TGID, &(info->port))); 11781 } 11782 } else { 11783 BCM_IF_ERROR_RETURN 11784 (_bcm_esw_l3_gport_construct(unit, port, modid, 11785 0, 0, &(info->port))); 11786 } 11787 11788 return BCM_E_NONE; 11789 } 11790 #endif /* BCM_TRIDENT3_SUPPORT */ 11791 11792 #if defined(BCM_TRIUMPH3_SUPPORT) 11793 STATIC int 11794 _tr3_l3_source_bind_hw_entry_to_sw_info(int unit, 11795 vlan_xlate_extd_entry_t *vxent, 11796 bcm_l3_source_bind_t *info) 11797 { 11798 int t_bit; 11799 bcm_module_t modid; 11800 bcm_port_t port; 11801 11802 bcm_l3_source_bind_t_init(info); 11803 info->ip = soc_VLAN_XLATE_EXTDm_field32_get(unit, vxent, 11804 MAC_IP_BIND__SIPf); 11805 if (soc_feature(unit, soc_feature_ipfix_rate)) { 11806 info->rate_id = soc_VLAN_XLATE_EXTDm_field32_get 11807 (unit, vxent, MAC_IP_BIND__IPFIX_FLOW_METER_IDf); 11808 } 11809 soc_VLAN_XLATE_EXTDm_mac_addr_get(unit, vxent, 11810 MAC_IP_BIND__MAC_ADDRf, info->mac); 11811 11812 /* Port analysis */ 11813 11814 port = soc_VLAN_XLATE_EXTDm_field32_get(unit, vxent, 11815 MAC_IP_BIND__PORT_NUMf); 11816 modid = soc_VLAN_XLATE_EXTDm_field32_get(unit, vxent, 11817 MAC_IP_BIND__MODULE_IDf); 11818 t_bit = soc_VLAN_XLATE_EXTDm_field32_get(unit, vxent, 11819 MAC_IP_BIND__Tf); 11820 11821 if (t_bit == 1) { 11822 if ((modid == 0x7f) && (port == 0x3f)) { 11823 info->port = BCM_GPORT_TYPE_BLACK_HOLE; /* Wild card */ 11824 } else { 11825 BCM_IF_ERROR_RETURN 11826 (_bcm_esw_l3_gport_construct(unit, 0, 0, 11827 (port & 0x3f) | ((modid & 0x1) << 6), 11828 BCM_L3_TGID, &(info->port))); 11829 } 11830 } else { 11831 BCM_IF_ERROR_RETURN 11832 (_bcm_esw_l3_gport_construct(unit, port, modid, 11833 0, 0, &(info->port))); 11834 } 11835 11836 return BCM_E_NONE; 11837 } 11838 #endif /* BCM_TRIUMPH3_SUPPORT */ 11839 11840 #if defined(BCM_TRIUMPH2_SUPPORT) 11841 STATIC int 11842 _tr2_l3_source_bind_hw_entry_to_sw_info(int unit, 11843 vlan_mac_entry_t *vment, 11844 bcm_l3_source_bind_t *info) 11845 { 11846 int t_bit; 11847 bcm_module_t modid; 11848 bcm_port_t port; 11849 11850 bcm_l3_source_bind_t_init(info); 11851 info->ip = soc_VLAN_MACm_field32_get(unit, vment, MAC_IP_BIND__SIPf); 11852 if (soc_feature(unit, soc_feature_ipfix_rate)) { 11853 info->rate_id = soc_VLAN_MACm_field32_get 11854 (unit, vment, MAC_IP_BIND__IPFIX_FLOW_METER_IDf); 11855 } 11856 soc_VLAN_MACm_mac_addr_get(unit, vment, 11857 MAC_IP_BIND__HPAE_MAC_ADDRf, info->mac); 11858 11859 /* Port analysis */ 11860 11861 port = soc_VLAN_MACm_field32_get(unit, vment, 11862 MAC_IP_BIND__SRC_PORTf); 11863 modid = soc_VLAN_MACm_field32_get(unit, vment, 11864 MAC_IP_BIND__SRC_MODIDf); 11865 t_bit = soc_VLAN_MACm_field32_get(unit, vment, 11866 MAC_IP_BIND__SRC_Tf); 11867 11868 if (t_bit == 1) { 11869 if ((modid == 0x7f) && (port == 0x3f)) { 11870 info->port = BCM_GPORT_TYPE_BLACK_HOLE; /* Wild card */ 11871 } else { 11872 BCM_IF_ERROR_RETURN 11873 (_bcm_esw_l3_gport_construct(unit, 0, 0, 11874 (port & 0x3f) | ((modid & 0x1) << 6), 11875 BCM_L3_TGID, &(info->port))); 11876 } 11877 } else { 11878 BCM_IF_ERROR_RETURN 11879 (_bcm_esw_l3_gport_construct(unit, port, modid, 11880 0, 0, &(info->port))); 11881 #if defined(BCM_HURRICANE2_SUPPORT) 11882 if (SOC_IS_HURRICANE2(unit)) { 11883 BCM_GPORT_MODPORT_SET(info->port, modid, port); 11884 } 11885 #endif /* BCM_HURRICANE2_SUPPORT */ 11886 } 11887 11888 return BCM_E_NONE; 11889 } 11890 #endif /* BCM_TRIUMPH2_SUPPORT */ 11891 11892 #if defined(BCM_TRIUMPH3_SUPPORT) 11893 STATIC int 11894 _tr3_l3_source_bind_get(int unit, bcm_l3_source_bind_t *info) 11895 { 11896 int rv, idx = 0; 11897 vlan_xlate_extd_entry_t vxent, res_vxent; 11898 11899 if (!soc_feature(unit, soc_feature_ip_source_bind)) { 11900 return BCM_E_UNAVAIL; 11901 } 11902 11903 if (info->flags & BCM_L3_SOURCE_BIND_IP6) { 11904 /* Not supported yet */ 11905 return BCM_E_UNAVAIL; 11906 } 11907 11908 if (info->flags & BCM_L3_SOURCE_BIND_USE_MASK) { 11909 /* Not supported */ 11910 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 11911 "%s: failed with error : %s \n"), FUNCTION_NAME(), 11912 bcm_errmsg(BCM_E_PARAM))); 11913 return BCM_E_PARAM; 11914 } 11915 11916 sal_memset(&vxent, 0, sizeof(vlan_xlate_extd_entry_t)); 11917 sal_memset(&res_vxent, 0, sizeof(vlan_xlate_extd_entry_t)); 11918 11919 /* MAC_IP_BIND lookup key type */ 11920 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, VALID_0f, 1); 11921 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, VALID_1f, 1); 11922 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, KEY_TYPE_0f, 11923 TR3_VLXLT_HASH_KEY_TYPE_HPAE); 11924 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, KEY_TYPE_1f, 11925 TR3_VLXLT_HASH_KEY_TYPE_HPAE); 11926 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, 11927 MAC_IP_BIND__SIPf, info->ip); 11928 11929 soc_mem_lock(unit, VLAN_XLATE_EXTDm); 11930 rv = soc_mem_search(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ALL, &idx, 11931 &vxent, &res_vxent, 0); 11932 soc_mem_unlock(unit, VLAN_XLATE_EXTDm); 11933 BCM_IF_ERROR_RETURN(rv); 11934 11935 return _tr3_l3_source_bind_hw_entry_to_sw_info(unit, &res_vxent, 11936 info); 11937 } 11938 #endif /* BCM_TRIUMPH3_SUPPORT */ 11939 11940 #if defined(BCM_TRIUMPH2_SUPPORT) 11941 STATIC int 11942 _tr2_l3_source_bind_get(int unit, bcm_l3_source_bind_t *info) 11943 { 11944 int rv, idx = 0; 11945 vlan_mac_entry_t vment, res_vment; 11946 11947 if (!soc_feature(unit, soc_feature_ip_source_bind)) { 11948 return BCM_E_UNAVAIL; 11949 } 11950 11951 if (info->flags & BCM_L3_SOURCE_BIND_IP6) { 11952 /* Not supported yet */ 11953 return BCM_E_UNAVAIL; 11954 } 11955 11956 if (info->flags & BCM_L3_SOURCE_BIND_USE_MASK) { 11957 /* Not supported */ 11958 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 11959 "%s: failed with error : %s \n"), FUNCTION_NAME(), 11960 bcm_errmsg(BCM_E_PARAM))); 11961 return BCM_E_PARAM; 11962 } 11963 11964 sal_memset(&vment, 0, sizeof(vlan_mac_entry_t)); 11965 sal_memset(&res_vment, 0, sizeof(vlan_mac_entry_t)); 11966 11967 /* MAC_IP_BIND lookup key type */ 11968 soc_VLAN_MACm_field32_set(unit, &vment, VALIDf, 1); 11969 soc_VLAN_MACm_field32_set(unit, &vment, KEY_TYPEf, 11970 TR_VLXLT_HASH_KEY_TYPE_HPAE); 11971 soc_VLAN_MACm_field32_set(unit, &vment, 11972 MAC_IP_BIND__SIPf, info->ip); 11973 11974 soc_mem_lock(unit, VLAN_MACm); 11975 rv = soc_mem_search(unit, VLAN_MACm, MEM_BLOCK_ALL, &idx, 11976 &vment, &res_vment, 0); 11977 soc_mem_unlock(unit, VLAN_MACm); 11978 BCM_IF_ERROR_RETURN(rv); 11979 11980 return _tr2_l3_source_bind_hw_entry_to_sw_info(unit, &res_vment, 11981 info); 11982 } 11983 #endif /* BCM_TRIUMPH2_SUPPORT */ 11984 11985 #if defined(BCM_TRIDENT3_SUPPORT) 11986 STATIC int 11987 _td3_l3_source_bind_get(int unit, bcm_l3_source_bind_t *info) 11988 { 11989 int rv, idx = 0; 11990 vlan_xlate_1_double_entry_t vxent, res_vxent; 11991 11992 if (!soc_feature(unit, soc_feature_ip_source_bind)) { 11993 return BCM_E_UNAVAIL; 11994 } 11995 11996 if (info->flags & BCM_L3_SOURCE_BIND_IP6) { 11997 /* Not supported yet */ 11998 return BCM_E_UNAVAIL; 11999 } 12000 12001 if (info->flags & BCM_L3_SOURCE_BIND_USE_MASK) { 12002 /* Not supported */ 12003 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 12004 "%s: failed with error : %s \n"), FUNCTION_NAME(), 12005 bcm_errmsg(BCM_E_PARAM))); 12006 return BCM_E_PARAM; 12007 } 12008 12009 sal_memset(&vxent, 0, sizeof(vlan_xlate_1_double_entry_t)); 12010 sal_memset(&res_vxent, 0, sizeof(vlan_xlate_1_double_entry_t)); 12011 12012 /* MAC_IP_BIND lookup key type */ 12013 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, BASE_VALID_0f, 3); 12014 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, BASE_VALID_1f, 7); 12015 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, DATA_TYPEf, 12016 7); 12017 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, KEY_TYPEf, 7); 12018 soc_VLAN_XLATE_1_DOUBLEm_field32_set(unit, &vxent, 12019 MAC_IP_BIND__SIPf, info->ip); 12020 12021 rv = soc_mem_search(unit, VLAN_XLATE_1_DOUBLEm, MEM_BLOCK_ALL, &idx, 12022 &vxent, &res_vxent, 0); 12023 BCM_IF_ERROR_RETURN(rv); 12024 12025 return _td3_l3_source_bind_hw_entry_to_sw_info(unit, &res_vxent, 12026 info); 12027 } 12028 #endif /* BCM_TRIDENT3_SUPPORT */ 12029 12030 /* 12031 * Function: 12032 * bcm_esw_l3_source_bind_get 12033 * Purpose: 12034 * Retrieve the details of an existing L3 source binding. 12035 * Parameters: 12036 * unit - (IN) Unit number. 12037 * info - (IN/OUT) L3 source binding information 12038 * Returns: 12039 * BCM_E_XXX 12040 * Notes: 12041 */ 12042 int 12043 bcm_esw_l3_source_bind_get(int unit, bcm_l3_source_bind_t *info) 12044 { 12045 #if defined(BCM_TRIUMPH3_SUPPORT) 12046 if (SOC_IS_TRIUMPH3(unit)) { 12047 BCM_IF_ERROR_RETURN 12048 (_tr3_l3_source_bind_get(unit,info)); 12049 return BCM_E_NONE; 12050 } 12051 #endif 12052 #if defined(BCM_TRIUMPH2_SUPPORT) 12053 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_HURRICANE2(unit)) { 12054 BCM_IF_ERROR_RETURN 12055 (_tr2_l3_source_bind_get(unit,info)); 12056 return BCM_E_NONE; 12057 } 12058 #endif 12059 #if defined(BCM_TRIDENT3_SUPPORT) 12060 if ((SOC_IS_TRIDENT3X(unit))) { 12061 BCM_IF_ERROR_RETURN 12062 (_td3_l3_source_bind_get(unit,info)); 12063 return BCM_E_NONE; 12064 } 12065 #endif 12066 12067 return BCM_E_UNAVAIL; 12068 } 12069 12070 #if defined(BCM_TRIUMPH3_SUPPORT) 12071 STATIC int 12072 _tr3_l3_source_bind_traverse(int unit, bcm_l3_source_bind_traverse_cb cb, 12073 void *user_data) 12074 { 12075 int idx, imin, imax, nent, vmbytes, rv; 12076 vlan_xlate_extd_entry_t * vxtab, *vxtabp; 12077 bcm_l3_source_bind_t info; 12078 12079 if (!soc_feature(unit, soc_feature_ip_source_bind)) { 12080 return BCM_E_UNAVAIL; 12081 } 12082 12083 /* Input parameters check. */ 12084 if (NULL == cb) { 12085 return (BCM_E_PARAM); 12086 } 12087 12088 imin = soc_mem_index_min(unit, VLAN_XLATE_EXTDm); 12089 imax = soc_mem_index_max(unit, VLAN_XLATE_EXTDm); 12090 nent = soc_mem_index_count(unit, VLAN_XLATE_EXTDm); 12091 vmbytes = soc_mem_entry_words(unit, VLAN_XLATE_EXTDm); 12092 vmbytes = WORDS2BYTES(vmbytes); 12093 vxtab = soc_cm_salloc(unit, nent * sizeof(*vxtab), "vlan_xlate_extd"); 12094 12095 if (vxtab == NULL) { 12096 return BCM_E_MEMORY; 12097 } 12098 12099 soc_mem_lock(unit, VLAN_XLATE_EXTDm); 12100 rv = soc_mem_read_range(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ANY, 12101 imin, imax, vxtab); 12102 if (BCM_FAILURE(rv)) { 12103 soc_mem_unlock(unit, VLAN_XLATE_EXTDm); 12104 soc_cm_sfree(unit, vxtab); 12105 return rv; 12106 } 12107 12108 for(idx = 0; idx < nent; idx++) { 12109 vxtabp = soc_mem_table_idx_to_pointer(unit, VLAN_XLATE_EXTDm, 12110 vlan_xlate_extd_entry_t *, 12111 vxtab, idx); 12112 12113 if ((0 == soc_VLAN_XLATE_EXTDm_field32_get(unit, vxtabp, VALID_0f)) || 12114 (TR3_VLXLT_HASH_KEY_TYPE_HPAE != 12115 soc_VLAN_XLATE_EXTDm_field32_get(unit, vxtabp, KEY_TYPE_0f))) { 12116 continue; 12117 } 12118 12119 rv = _tr3_l3_source_bind_hw_entry_to_sw_info(unit, vxtabp, 12120 &info); 12121 12122 if (BCM_SUCCESS(rv)) { 12123 /* Call traverse callback with the data. */ 12124 rv = cb(unit, &info, user_data); 12125 } 12126 12127 if (BCM_FAILURE(rv)) { 12128 soc_mem_unlock(unit, VLAN_XLATE_EXTDm); 12129 soc_cm_sfree(unit, vxtab); 12130 return rv; 12131 } 12132 } 12133 12134 soc_mem_unlock(unit, VLAN_XLATE_EXTDm); 12135 soc_cm_sfree(unit, vxtab); 12136 return rv; 12137 } 12138 #endif /* BCM_TRIUMPH3_SUPPORT */ 12139 12140 #if defined(BCM_TRIUMPH2_SUPPORT) 12141 STATIC int 12142 _tr2_l3_source_bind_traverse(int unit, bcm_l3_source_bind_traverse_cb cb, 12143 void *user_data) 12144 { 12145 int idx, imin, imax, nent, vmbytes, rv; 12146 vlan_mac_entry_t * vmtab, *vmtabp; 12147 bcm_l3_source_bind_t info; 12148 12149 if (!soc_feature(unit, soc_feature_ip_source_bind)) { 12150 return BCM_E_UNAVAIL; 12151 } 12152 12153 /* Input parameters check. */ 12154 if (NULL == cb) { 12155 return (BCM_E_PARAM); 12156 } 12157 12158 imin = soc_mem_index_min(unit, VLAN_MACm); 12159 imax = soc_mem_index_max(unit, VLAN_MACm); 12160 nent = soc_mem_index_count(unit, VLAN_MACm); 12161 vmbytes = soc_mem_entry_words(unit, VLAN_MACm); 12162 vmbytes = WORDS2BYTES(vmbytes); 12163 vmtab = soc_cm_salloc(unit, nent * sizeof(*vmtab), "vlan_mac"); 12164 12165 if (vmtab == NULL) { 12166 return BCM_E_MEMORY; 12167 } 12168 12169 soc_mem_lock(unit, VLAN_MACm); 12170 rv = soc_mem_read_range(unit, VLAN_MACm, MEM_BLOCK_ANY, 12171 imin, imax, vmtab); 12172 if (BCM_FAILURE(rv)) { 12173 soc_mem_unlock(unit, VLAN_MACm); 12174 soc_cm_sfree(unit, vmtab); 12175 return rv; 12176 } 12177 12178 for(idx = 0; idx < nent; idx++) { 12179 vmtabp = soc_mem_table_idx_to_pointer(unit, VLAN_MACm, 12180 vlan_mac_entry_t *, 12181 vmtab, idx); 12182 12183 if ((0 == soc_VLAN_MACm_field32_get(unit, vmtabp, VALIDf)) || 12184 (TR_VLXLT_HASH_KEY_TYPE_HPAE != 12185 soc_VLAN_MACm_field32_get(unit, vmtabp, KEY_TYPEf))) { 12186 continue; 12187 } 12188 12189 rv = _tr2_l3_source_bind_hw_entry_to_sw_info(unit, vmtabp, 12190 &info); 12191 12192 if (BCM_SUCCESS(rv)) { 12193 /* Call traverse callback with the data. */ 12194 rv = cb(unit, &info, user_data); 12195 } 12196 12197 if (BCM_FAILURE(rv)) { 12198 soc_mem_unlock(unit, VLAN_MACm); 12199 soc_cm_sfree(unit, vmtab); 12200 return rv; 12201 } 12202 } 12203 12204 soc_mem_unlock(unit, VLAN_MACm); 12205 soc_cm_sfree(unit, vmtab); 12206 return rv; 12207 } 12208 #endif /* BCM_TRIUMPH2_SUPPORT */ 12209 12210 /* 12211 * Function: 12212 * bcm_esw_l3_source_bind_traverse 12213 * Purpose: 12214 * Traverse through the L3 source bindings and run callback at 12215 * each defined binding. 12216 * Parameters: 12217 * unit - (IN) Unit number. 12218 * cb - (IN) Call back routine. 12219 * user_data - (IN) User provided cookie for callback. 12220 * Returns: 12221 * BCM_E_XXX 12222 * Notes: 12223 */ 12224 int 12225 bcm_esw_l3_source_bind_traverse(int unit, bcm_l3_source_bind_traverse_cb cb, 12226 void *user_data) 12227 { 12228 #if defined(BCM_TRIUMPH3_SUPPORT) 12229 if (SOC_IS_TRIUMPH3(unit)) { 12230 BCM_IF_ERROR_RETURN 12231 (_tr3_l3_source_bind_traverse(unit,cb,user_data)); 12232 return BCM_E_NONE; 12233 } 12234 #endif 12235 #if defined(BCM_TRIUMPH2_SUPPORT) 12236 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_HURRICANE2(unit)) { 12237 BCM_IF_ERROR_RETURN 12238 (_tr2_l3_source_bind_traverse(unit,cb,user_data)); 12239 return BCM_E_NONE; 12240 } 12241 #endif 12242 return BCM_E_UNAVAIL; 12243 } 12244 12245 #ifdef BCM_WARM_BOOT_SUPPORT 12246 int 12247 _bcm_l3_cleanup(int unit) 12248 { 12249 12250 return(mbcm_driver[unit]->mbcm_l3_tables_cleanup(unit)); 12251 } 12252 #endif /* BCM_WARM_BOOT_SUPPORT */ 12253 12254 /* 12255 * Function: 12256 * bcm_esw_l3_host_stat_attach 12257 * Description: 12258 * Attach counters entries to the given L3 host entry 12259 * 12260 * Parameters: 12261 * unit - (IN) unit number 12262 * info - (IN) L3 host description 12263 * stat_counter_id - (IN) Stat Counter ID. 12264 * 12265 * Return Value: 12266 * BCM_E_XXX 12267 */ 12268 int bcm_esw_l3_host_stat_attach( 12269 int unit, 12270 bcm_l3_host_t *info, 12271 uint32 stat_counter_id) 12272 { 12273 #if defined(BCM_TRIDENT2_SUPPORT) 12274 if (SOC_IS_TD2_TT2(unit)) { 12275 return _bcm_td2_l3_host_stat_attach(unit, info, stat_counter_id); 12276 } else 12277 #endif 12278 #if defined(BCM_TRIUMPH3_SUPPORT) 12279 if (SOC_IS_TRIUMPH3(unit)) { 12280 return _bcm_tr3_l3_host_stat_attach(unit, info, stat_counter_id); 12281 } else 12282 #endif 12283 { 12284 return BCM_E_UNAVAIL; 12285 } 12286 } 12287 12288 /* 12289 * Function: 12290 * bcm_esw_l3_host_stat_detach 12291 * Description: 12292 * Detach counters entries to the given L3 host entry 12293 * 12294 * Parameters: 12295 * unit - (IN) unit number 12296 * info - (IN) L3 host description 12297 * 12298 * Return Value: 12299 * BCM_E_XXX 12300 * Notes: 12301 */ 12302 int bcm_esw_l3_host_stat_detach( 12303 int unit, 12304 bcm_l3_host_t *info) 12305 { 12306 #if defined(BCM_TRIDENT2_SUPPORT) 12307 if (SOC_IS_TD2_TT2(unit)) { 12308 return _bcm_td2_l3_host_stat_detach(unit, info); 12309 } else 12310 #endif 12311 #if defined(BCM_TRIUMPH3_SUPPORT) 12312 if (SOC_IS_TRIUMPH3(unit)) { 12313 return _bcm_tr3_l3_host_stat_detach(unit, info); 12314 } else 12315 #endif 12316 { 12317 return BCM_E_UNAVAIL; 12318 } 12319 } 12320 12321 /* 12322 * Function: 12323 * _bcm_esw_l3_host_stat_counter_get 12324 * Description: 12325 * Get counter statistic values for specific L3 host entry 12326 * if sync_mode is set, sync the sw accumulated count 12327 * with hw count value first, else return sw count. 12328 * Parameters: 12329 * unit - (IN) unit number 12330 * sync_mode - (IN) hwcount is to be synced to sw count 12331 * info - (IN) L3 host description 12332 * stat - (IN) Type of the counter to retrieve 12333 * I.e. ingress/egress byte/packet) 12334 * num_entries - (IN) Number of counter Entries 12335 * counter_indexes - (IN) Pointer to Counter indexes entries 12336 * counter_values - (OUT) Pointer to counter values 12337 * 12338 * Return Value: 12339 * BCM_E_XXX 12340 * Notes: 12341 */ 12342 int _bcm_esw_l3_host_stat_counter_get( 12343 int unit, 12344 int sync_mode, 12345 bcm_l3_host_t *info, 12346 bcm_l3_stat_t stat, 12347 uint32 num_entries, 12348 uint32 *counter_indexes, 12349 bcm_stat_value_t *counter_values) 12350 { 12351 12352 #if defined(BCM_TRIDENT2_SUPPORT) 12353 if (SOC_IS_TD2_TT2(unit)) { 12354 return _bcm_td2_l3_host_stat_counter_get(unit, sync_mode, info, 12355 stat, num_entries, counter_indexes, counter_values); 12356 } else 12357 #endif 12358 #if defined(BCM_TRIUMPH3_SUPPORT) 12359 if (SOC_IS_TRIUMPH3(unit)) { 12360 return _bcm_tr3_l3_host_stat_counter_get(unit, sync_mode, info, 12361 stat, num_entries, counter_indexes, counter_values); 12362 } else 12363 #endif 12364 { 12365 return BCM_E_UNAVAIL; 12366 } 12367 } 12368 12369 12370 /* 12371 * Function: 12372 * bcm_esw_l3_host_stat_counter_get 12373 * Description: 12374 * Get counter statistic values for specific L3 host entry 12375 * 12376 * Parameters: 12377 * unit - (IN) unit number 12378 * info - (IN) L3 host description 12379 * stat - (IN) Type of the counter to retrieve 12380 * I.e. ingress/egress byte/packet) 12381 * num_entries - (IN) Number of counter Entries 12382 * counter_indexes - (IN) Pointer to Counter indexes entries 12383 * counter_values - (OUT) Pointer to counter values 12384 * 12385 * Return Value: 12386 * BCM_E_XXX 12387 * Notes: 12388 */ 12389 int bcm_esw_l3_host_stat_counter_get( 12390 int unit, 12391 bcm_l3_host_t *info, 12392 bcm_l3_stat_t stat, 12393 uint32 num_entries, 12394 uint32 *counter_indexes, 12395 bcm_stat_value_t *counter_values) 12396 { 12397 int rv = BCM_E_UNAVAIL; 12398 12399 rv = _bcm_esw_l3_host_stat_counter_get(unit, 0, info, stat, 12400 num_entries, counter_indexes, 12401 counter_values); 12402 12403 return rv; 12404 } 12405 12406 12407 /* 12408 * Function: 12409 * bcm_esw_l3_host_stat_counter_sync_get 12410 * Description: 12411 * Get counter statistic values for specific L3 host entry 12412 * sw accumulated counters synced with hw count. 12413 * Parameters: 12414 * unit - (IN) unit number 12415 * info - (IN) L3 host description 12416 * stat - (IN) Type of the counter to retrieve 12417 * I.e. ingress/egress byte/packet) 12418 * num_entries - (IN) Number of counter Entries 12419 * counter_indexes - (IN) Pointer to Counter indexes entries 12420 * counter_values - (OUT) Pointer to counter values 12421 * 12422 * Return Value: 12423 * BCM_E_XXX 12424 * Notes: 12425 */ 12426 int bcm_esw_l3_host_stat_counter_sync_get( 12427 int unit, 12428 bcm_l3_host_t *info, 12429 bcm_l3_stat_t stat, 12430 uint32 num_entries, 12431 uint32 *counter_indexes, 12432 bcm_stat_value_t *counter_values) 12433 { 12434 int rv = BCM_E_UNAVAIL; 12435 12436 rv = _bcm_esw_l3_host_stat_counter_get(unit, 1, info, stat, 12437 num_entries, counter_indexes, 12438 counter_values); 12439 12440 return rv; 12441 } 12442 12443 /* 12444 * Function: 12445 * bcm_esw_l3_host_stat_counter_set 12446 * Description: 12447 * Set counter statistic values for specific L3 host entry 12448 * 12449 * Parameters: 12450 * unit - (IN) unit number 12451 * info - (IN) L3 host description 12452 * stat - (IN) Type of the counter to retrieve 12453 * I.e. ingress/egress byte/packet) 12454 * num_entries - (IN) Number of counter Entries 12455 * counter_indexes - (IN) Pointer to Counter indexes entries 12456 * counter_values - (IN) Pointer to counter values 12457 * 12458 * Return Value: 12459 * BCM_E_XXX 12460 * Notes: 12461 */ 12462 int bcm_esw_l3_host_stat_counter_set( 12463 int unit, 12464 bcm_l3_host_t *info, 12465 bcm_l3_stat_t stat, 12466 uint32 num_entries, 12467 uint32 *counter_indexes, 12468 bcm_stat_value_t *counter_values) 12469 { 12470 #if defined(BCM_TRIDENT2_SUPPORT) 12471 if (SOC_IS_TD2_TT2(unit)) { 12472 return _bcm_td2_l3_host_stat_counter_set(unit, info, stat, 12473 num_entries, counter_indexes, counter_values); 12474 } else 12475 #endif 12476 #if defined(BCM_TRIUMPH3_SUPPORT) 12477 if (SOC_IS_TRIUMPH3(unit)) { 12478 return _bcm_tr3_l3_host_stat_counter_set(unit, info, stat, 12479 num_entries, counter_indexes, counter_values); 12480 } else 12481 #endif 12482 { 12483 return BCM_E_UNAVAIL; 12484 } 12485 } 12486 12487 /* 12488 * Function: 12489 * bcm_esw_l3_host_stat_id_get 12490 * Description: 12491 * Get stat counter id associated with given L3 host entry 12492 * 12493 * Parameters: 12494 * unit - (IN) unit number 12495 * info - (IN) L3 host description 12496 * stat - (IN) Type of the counter to retrieve 12497 * I.e. ingress/egress byte/packet) 12498 * Stat_counter_id - (OUT) Stat Counter ID 12499 * Return Value: 12500 * BCM_E_XXX 12501 * Notes: 12502 */ 12503 int bcm_esw_l3_host_stat_id_get( 12504 int unit, 12505 bcm_l3_host_t *info, 12506 bcm_l3_stat_t stat, 12507 uint32 *stat_counter_id) 12508 { 12509 #if defined(BCM_TRIDENT2_SUPPORT) 12510 if (SOC_IS_TD2_TT2(unit)) { 12511 return _bcm_td2_l3_host_stat_id_get(unit, info, stat, stat_counter_id); 12512 } else 12513 #endif 12514 #if defined(BCM_TRIUMPH3_SUPPORT) 12515 if (SOC_IS_TRIUMPH3(unit)) { 12516 return _bcm_tr3_l3_host_stat_id_get(unit, info, stat, stat_counter_id); 12517 } else 12518 #endif 12519 { 12520 return BCM_E_UNAVAIL; 12521 } 12522 } 12523 12524 /* 12525 * Function: 12526 * bcm_esw_l3_route_stat_attach 12527 * Description: 12528 * Attach counters entries to the given l3 route defip index . Allocate 12529 * flex counter and assign counter index and offset for the index pointed 12530 * by l3 defip index 12531 * 12532 * Parameters: 12533 * unit - (IN) unit number 12534 * info - (IN) L3 Route Info 12535 * stat_counter_id - (IN) Stat Counter ID. 12536 * 12537 * Return Value: 12538 * BCM_E_XXX 12539 * Notes: 12540 */ 12541 12542 int bcm_esw_l3_route_stat_attach ( 12543 int unit, 12544 bcm_l3_route_t *info, 12545 uint32 stat_counter_id) 12546 { 12547 int rv = BCM_E_UNAVAIL; 12548 12549 #if defined(BCM_TRIDENT2_SUPPORT) 12550 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 12551 L3_LOCK(unit); 12552 rv = _bcm_td2_l3_route_stat_attach ( 12553 unit, info, stat_counter_id); 12554 12555 L3_UNLOCK(unit); 12556 } 12557 #endif 12558 return rv; 12559 } 12560 12561 12562 /* 12563 * Function: 12564 * bcm_esw_l3_route_stat_detach 12565 * Description: 12566 * Detach counter entries to the given l3 route index. 12567 * 12568 * Parameters: 12569 * unit - (IN) unit number 12570 * info - (IN) L3 Route Info 12571 * 12572 * Return Value: 12573 * BCM_E_XXX 12574 * Notes: 12575 */ 12576 int bcm_esw_l3_route_stat_detach ( 12577 int unit, 12578 bcm_l3_route_t *info) 12579 { 12580 int rv = BCM_E_UNAVAIL; 12581 12582 #if defined(BCM_TRIDENT2_SUPPORT) 12583 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 12584 L3_LOCK(unit); 12585 rv = _bcm_td2_l3_route_stat_detach (unit, info); 12586 L3_UNLOCK(unit); 12587 } 12588 #endif 12589 return rv; 12590 } 12591 12592 /* 12593 * Function: 12594 * _bcm_esw_l3_route_stat_counter_get 12595 * 12596 * Description: 12597 * Get l3 route counter value for specified l3 route index 12598 * if sync_mode is set, sync the sw accumulated count 12599 * with hw count value first, else return sw count. 12600 * 12601 * Parameters: 12602 * unit - (IN) unit number 12603 * sync_mode - (IN) hwcount is to be synced to sw count 12604 * info - (IN) L3 Route Info 12605 * stat - (IN) l3 route counter stat types 12606 * num_entries - (IN) Number of counter Entries 12607 * counter_indexes - (IN) Pointer to Counter indexes entries 12608 * counter_values - (OUT) Pointer to counter values 12609 * 12610 * Return Value: 12611 * BCM_E_XXX 12612 * Notes: 12613 */ 12614 int _bcm_esw_l3_route_stat_counter_get( 12615 int unit, 12616 int sync_mode, 12617 bcm_l3_route_t *info, 12618 bcm_l3_route_stat_t stat, 12619 uint32 num_entries, 12620 uint32 *counter_indexes, 12621 bcm_stat_value_t *counter_values) 12622 { 12623 int rv = BCM_E_UNAVAIL; 12624 12625 #if defined(BCM_TRIDENT2_SUPPORT) 12626 12627 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 12628 L3_LOCK(unit); 12629 rv = _bcm_td2_l3_route_stat_counter_get ( 12630 unit, sync_mode, info, stat, num_entries, 12631 counter_indexes, counter_values); 12632 L3_UNLOCK(unit); 12633 } 12634 #endif 12635 return rv; 12636 } 12637 12638 12639 /* 12640 * Function: 12641 * bcm_esw_l3_route_stat_counter_get 12642 * 12643 * Description: 12644 * Get l3 route counter value for specified l3 route index 12645 * 12646 * Parameters: 12647 * unit - (IN) unit number 12648 * info - (IN) L3 Route Info 12649 * stat - (IN) l3 route counter stat types 12650 * num_entries - (IN) Number of counter Entries 12651 * counter_indexes - (IN) Pointer to Counter indexes entries 12652 * counter_values - (OUT) Pointer to counter values 12653 * 12654 * Return Value: 12655 * BCM_E_XXX 12656 * Notes: 12657 */ 12658 int bcm_esw_l3_route_stat_counter_get( 12659 int unit, 12660 bcm_l3_route_t *info, 12661 bcm_l3_route_stat_t stat, 12662 uint32 num_entries, 12663 uint32 *counter_indexes, 12664 bcm_stat_value_t *counter_values) 12665 { 12666 int rv = BCM_E_UNAVAIL; 12667 12668 rv = _bcm_esw_l3_route_stat_counter_get(unit, 0, info, stat, 12669 num_entries, counter_indexes, 12670 counter_values); 12671 return rv; 12672 } 12673 12674 12675 12676 /* 12677 * Function: 12678 * bcm_esw_l3_route_stat_counter_sync_get 12679 * 12680 * Description: 12681 * Get l3 route counter value for specified l3 route index 12682 * sw accumulated counters synced with hw count. 12683 * Parameters: 12684 * unit - (IN) unit number 12685 * info - (IN) L3 Route Info 12686 * stat - (IN) l3 route counter stat types 12687 * num_entries - (IN) Number of counter Entries 12688 * counter_indexes - (IN) Pointer to Counter indexes entries 12689 * counter_values - (OUT) Pointer to counter values 12690 * 12691 * Return Value: 12692 * BCM_E_XXX 12693 * Notes: 12694 */ 12695 int bcm_esw_l3_route_stat_counter_sync_get( 12696 int unit, 12697 bcm_l3_route_t *info, 12698 bcm_l3_route_stat_t stat, 12699 uint32 num_entries, 12700 uint32 *counter_indexes, 12701 bcm_stat_value_t *counter_values) 12702 { 12703 int rv = BCM_E_UNAVAIL; 12704 12705 rv = _bcm_esw_l3_route_stat_counter_get(unit, 1, info, stat, 12706 num_entries, counter_indexes, 12707 counter_values); 12708 return rv; 12709 } 12710 /* 12711 * Function: 12712 * bcm_esw_l3_route_stat_counter_set 12713 * 12714 * Description: 12715 * Set l3 route counter value for specified l3 route index 12716 * 12717 * Parameters: 12718 * unit - (IN) unit number 12719 * info - (IN) L3 Route Info 12720 * stat - (IN) l3 route counter stat types 12721 * num_entries - (IN) Number of counter Entries 12722 * counter_indexes - (IN) Pointer to Counter indexes entries 12723 * counter_values - (OUT) Pointer to counter values 12724 * 12725 * Return Value: 12726 * BCM_E_XXX 12727 * Notes: 12728 */ 12729 int bcm_esw_l3_route_stat_counter_set( 12730 int unit, 12731 bcm_l3_route_t *info, 12732 bcm_l3_route_stat_t stat, 12733 uint32 num_entries, 12734 uint32 *counter_indexes, 12735 bcm_stat_value_t *counter_values) 12736 { 12737 int rv = BCM_E_UNAVAIL; 12738 12739 if (counter_indexes == NULL || counter_values == NULL) { 12740 return BCM_E_PARAM; 12741 } 12742 12743 #if defined(BCM_TRIDENT2_SUPPORT) 12744 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 12745 L3_LOCK(unit); 12746 rv = _bcm_td2_l3_route_stat_counter_set ( 12747 unit, info, stat, num_entries, 12748 counter_indexes, counter_values); 12749 L3_UNLOCK(unit); 12750 } 12751 #endif 12752 return rv; 12753 } 12754 12755 /* 12756 * Function: 12757 * bcm_esw_l3_route_stat_multi_get 12758 * 12759 * Description: 12760 * Get Multiple l3 route counter value for specified l3 route index for multiple stat 12761 * types 12762 * 12763 * Parameters: 12764 * unit - (IN) unit number 12765 * info - (IN) L3 Route Info 12766 * nstat - (IN) Number of elements in stat array 12767 * stat_arr - (IN) Collected statistics descriptors array 12768 * value_arr - (OUT) Collected counters values 12769 * 12770 * Return Value: 12771 * BCM_E_XXX 12772 * Notes: 12773 */ 12774 12775 12776 int bcm_esw_l3_route_stat_multi_get( 12777 int unit, 12778 bcm_l3_route_t *info, 12779 int nstat, 12780 bcm_l3_route_stat_t *stat_arr, 12781 uint64 *value_arr) 12782 { 12783 int rv = BCM_E_UNAVAIL; 12784 12785 #if defined(BCM_TRIDENT2_SUPPORT) 12786 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 12787 L3_LOCK(unit); 12788 rv = _bcm_td2_l3_route_stat_multi_get ( 12789 unit, info, nstat, stat_arr, value_arr); 12790 L3_UNLOCK(unit); 12791 } 12792 #endif 12793 return rv; 12794 } 12795 12796 /* 12797 * Function: 12798 * bcm_esw_l3_route_stat_multi_get32 12799 * 12800 * Description: 12801 * Get 32bit l3 route counter value for specified l3 route index for multiple stat 12802 * types 12803 * 12804 * Parameters: 12805 * unit - (IN) unit number 12806 * info - (IN) L3 Route Info 12807 * nstat - (IN) Number of elements in stat array 12808 * stat_arr - (IN) Collected statistics descriptors array 12809 * value_arr - (OUT) Collected counters values 12810 * 12811 * Return Value: 12812 * BCM_E_XXX 12813 * Notes: 12814 */ 12815 int bcm_esw_l3_route_stat_multi_get32( 12816 int unit, 12817 bcm_l3_route_t *info, 12818 int nstat, 12819 bcm_l3_route_stat_t *stat_arr, 12820 uint32 *value_arr) 12821 { 12822 int rv = BCM_E_UNAVAIL; 12823 12824 #if defined(BCM_TRIDENT2_SUPPORT) 12825 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 12826 L3_LOCK(unit); 12827 rv = _bcm_td2_l3_route_stat_multi_get32 ( 12828 unit, info, nstat, stat_arr, value_arr); 12829 L3_UNLOCK(unit); 12830 } 12831 #endif 12832 return rv; 12833 } 12834 12835 /* 12836 * Function: 12837 * bcm_esw_l3_route_stat_multi_set 12838 * 12839 * Description: 12840 * Set l3 route counter value for specified l3 route index for multiple stat 12841 * types 12842 * 12843 * Parameters: 12844 * unit - (IN) unit number 12845 * info - (IN) L3 Route Info 12846 * stat - (IN) l3 route counter stat types 12847 * num_entries - (IN) Number of counter Entries 12848 * counter_indexes - (IN) Pointer to Counter indexes entries 12849 * counter_values - (OUT) Pointer to counter values 12850 * 12851 * Return Value: 12852 * BCM_E_XXX 12853 * Notes: 12854 */ 12855 int bcm_esw_l3_route_stat_multi_set( 12856 int unit, 12857 bcm_l3_route_t *info, 12858 int nstat, 12859 bcm_l3_route_stat_t *stat_arr, 12860 uint64 *value_arr) 12861 { 12862 int rv = BCM_E_UNAVAIL; 12863 12864 #if defined(BCM_TRIDENT2_SUPPORT) 12865 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 12866 L3_LOCK(unit); 12867 rv = _bcm_td2_l3_route_stat_multi_set ( 12868 unit, info, nstat, stat_arr, value_arr); 12869 L3_UNLOCK(unit); 12870 } 12871 #endif 12872 return rv; 12873 12874 } 12875 12876 /* 12877 * Function: 12878 * bcm_esw_l3_route_stat_multi_set32 12879 * 12880 * Description: 12881 * Set 32bit l3 route counter value for specified l3 route index for multiple stat 12882 * types 12883 * 12884 * Parameters: 12885 * unit - (IN) unit number 12886 * info - (IN) L3 Route Info 12887 * stat - (IN) l3 route counter stat types 12888 * num_entries - (IN) Number of counter Entries 12889 * counter_indexes - (IN) Pointer to Counter indexes entries 12890 * counter_values - (OUT) Pointer to counter values 12891 * 12892 * Return Value: 12893 * BCM_E_XXX 12894 * Notes: 12895 */ 12896 12897 int bcm_esw_l3_route_stat_multi_set32( 12898 int unit, 12899 bcm_l3_route_t *info, 12900 int nstat, 12901 bcm_l3_route_stat_t *stat_arr, 12902 uint32 *value_arr) 12903 { 12904 int rv = BCM_E_UNAVAIL; 12905 12906 #if defined(BCM_TRIDENT2_SUPPORT) 12907 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 12908 L3_LOCK(unit); 12909 rv = _bcm_td2_l3_route_stat_multi_set32 ( 12910 unit, info, nstat, stat_arr, value_arr); 12911 L3_UNLOCK(unit); 12912 } 12913 #endif 12914 return rv; 12915 } 12916 12917 /* 12918 * Function: 12919 * bcm_esw_l3_route_stat_id_get 12920 * 12921 * Description: 12922 * Get Stat Counter if associated with given l3 route index 12923 * 12924 * Parameters: 12925 * unit - (IN) bcm device 12926 * info - (IN) L3 Route Info 12927 * stat - (IN) l3 route counter stat types 12928 * stat_counter_id - (IN) Stat Counter ID. 12929 * 12930 * Returns: 12931 * BCM_E_NONE - Success 12932 * BCM_E_XXX 12933 * Notes: 12934 */ 12935 12936 int bcm_esw_l3_route_stat_id_get( 12937 int unit, 12938 bcm_l3_route_t *info, 12939 bcm_l3_route_stat_t stat, 12940 uint32 *stat_counter_id) 12941 { 12942 int rv = BCM_E_UNAVAIL; 12943 12944 #if defined(BCM_TRIDENT2_SUPPORT) 12945 if (soc_feature(unit,soc_feature_advanced_flex_counter)) { 12946 rv = _bcm_td2_l3_route_stat_id_get ( 12947 unit, info, stat, stat_counter_id); 12948 } 12949 #endif 12950 return rv; 12951 } 12952 12953 /* 12954 * Function: 12955 * bcm_esw_l3_route_stat_enable_set 12956 * Purpose: 12957 * Enable/disable packet and byte counters for the selected route 12958 * Parameters: 12959 * unit - (IN) Unit number. 12960 * info - (IN) Route info 12961 * enable - (IN) Non-zero to enable counter collection, zero to disable. 12962 * Returns: 12963 * BCM_E_XXX 12964 * Notes: 12965 */ 12966 int 12967 bcm_esw_l3_route_stat_enable_set(int unit, bcm_l3_route_t *info, int enable) 12968 { 12969 int rv = BCM_E_UNAVAIL; 12970 12971 /* Old Flex API interfaces are not supported for L3 Route */ 12972 12973 return rv; 12974 } 12975 12976 /* 12977 * Function: 12978 * bcm_esw_l3_route_stat_get 12979 * Purpose: 12980 * Get 64-bit counter value for specified L3 Route Types. 12981 * Parameters: 12982 * unit - (IN) Unit number. 12983 * info - (IN) Route info 12984 * stat - (IN) Type of the counter to retrieve. 12985 * val - (OUT) Pointer to a counter value. 12986 * Returns: 12987 * BCM_E_XXX 12988 * Notes: 12989 */ 12990 int 12991 bcm_esw_l3_route_stat_get(int unit, bcm_l3_route_t *info, bcm_l3_stat_t stat, 12992 uint64 *val) 12993 { 12994 int rv = BCM_E_UNAVAIL; 12995 12996 /* Old Flex API interfaces are not supported for L3 route */ 12997 12998 return rv; 12999 } 13000 13001 /* 13002 * Function: 13003 * bcm_esw_l3_route_stat_get32 13004 * Purpose: 13005 * Get 32-bit counter value for specified L3 Route Types. 13006 * Parameters: 13007 * unit - (IN) Unit number. 13008 * info - (IN) Route info 13009 * stat - (IN) Type of the counter to retrieve. 13010 * val - (OUT) Pointer to a counter value. 13011 * Returns: 13012 * BCM_E_XXX 13013 * Notes: 13014 */ 13015 int 13016 bcm_esw_l3_route_stat_get32(int unit, bcm_l3_route_t *info, bcm_l3_stat_t stat, 13017 uint32 *val) 13018 { 13019 int rv = BCM_E_UNAVAIL; 13020 13021 /* Old Flex API interfaces are not supported for L3 route */ 13022 13023 return rv; 13024 } 13025 13026 /* 13027 * Function: 13028 * bcm_esw_l3_route_stat_set 13029 * Purpose: 13030 * Get 64-bit counter value for specified L3 Route Types. 13031 * Parameters: 13032 * unit - (IN) Unit number. 13033 * info - (IN) Route info 13034 * stat - (IN) Type of the counter to retrieve. 13035 * val - (OUT) Pointer to a counter value. 13036 * Returns: 13037 * BCM_E_XXX 13038 * Notes: 13039 */ 13040 int 13041 bcm_esw_l3_route_stat_set(int unit, bcm_l3_route_t *info, bcm_l3_stat_t stat, 13042 uint64 val) 13043 { 13044 int rv = BCM_E_UNAVAIL; 13045 13046 /* Old Flex API interfaces are not supported for L3 route */ 13047 13048 return rv; 13049 } 13050 13051 /* 13052 * Function: 13053 * bcm_esw_l3_route_stat_set32 13054 * Purpose: 13055 * Get 32-bit counter value for specified L3 Route Types. 13056 * Parameters: 13057 * unit - (IN) Unit number. 13058 * info - (IN) Route info 13059 * stat - (IN) Type of the counter to retrieve. 13060 * val - (OUT) Pointer to a counter value. 13061 * Returns: 13062 * BCM_E_XXX 13063 * Notes: 13064 */ 13065 int 13066 bcm_esw_l3_route_stat_set32(int unit, bcm_l3_route_t *info, bcm_l3_stat_t stat, 13067 uint32 val) 13068 { 13069 int rv = BCM_E_UNAVAIL; 13070 13071 /* Old Flex API interfaces are not supported for L3 route */ 13072 13073 return rv; 13074 } 13075 13076 13077 /* 13078 * Function: 13079 * bcm_esw_l3_ip4_options_profile_create 13080 * Purpose: 13081 * Create an IP option handling profile. 13082 * Parameters: 13083 * unit - (IN) bcm device. 13084 * flags - (IN) BCM_L3_WITH_ID: ip4_options_profile_id argument given. 13085 * default_action - (IN) Default action for options in the profile 13086 * ip4_options_profile_id - (OUT) L3 IP options profile ID 13087 * This is an IN argument if BCM_L3_WITH_ID is given in 13088 * flag. 13089 * Returns: 13090 * BCM_E_XXX 13091 */ 13092 int 13093 bcm_esw_l3_ip4_options_profile_create(int unit, uint32 flags, 13094 bcm_l3_ip4_options_action_t default_action, 13095 int *ip4_options_profile_id) 13096 { 13097 int rv = BCM_E_UNAVAIL; 13098 if (ip4_options_profile_id == NULL) { 13099 return BCM_E_PARAM; 13100 } 13101 #ifdef BCM_TRIDENT2_SUPPORT 13102 if (soc_feature(unit, soc_feature_l3_ip4_options_profile)) { 13103 rv = _bcm_td2_l3_ip4_options_profile_create(unit, flags, 13104 default_action, ip4_options_profile_id); 13105 } 13106 #endif /* BCM_TRIDENT2_SUPPORT */ 13107 return (rv); 13108 } 13109 13110 /* 13111 * Function: 13112 * bcm_esw_l3_ip4_options_profile_destroy 13113 * Purpose: 13114 * Delete a IP option handling profile. 13115 * Parameters: 13116 * unit - (IN) bcm device. 13117 * ip4_options_profile_id - (IN) L3 IP options profile ID 13118 * Returns: 13119 * BCM_E_XXX 13120 */ 13121 int 13122 bcm_esw_l3_ip4_options_profile_destroy(int unit, int ip4_options_profile_id) 13123 { 13124 int rv = BCM_E_UNAVAIL; 13125 #ifdef BCM_TRIDENT2_SUPPORT 13126 if (soc_feature(unit, soc_feature_l3_ip4_options_profile)) { 13127 rv = _bcm_td2_l3_ip4_options_profile_destroy(unit, ip4_options_profile_id); 13128 } 13129 #endif /* BCM_TRIDENT2_SUPPORT */ 13130 return (rv); 13131 } 13132 13133 13134 /* 13135 * Function: 13136 * bcm_esw_l3_ip4_options_action_set 13137 * Purpose: 13138 * Update action for given IP action and Profile ID 13139 * Parameters: 13140 * unit - (IN) bcm device. 13141 * ip4_options_profile_id - (IN) IP options profile ID 13142 * ip4_option - (IN) New Action for IP Options 13143 * Returns: 13144 * BCM_E_XXX 13145 */ 13146 int 13147 bcm_esw_l3_ip4_options_action_set(int unit, 13148 int ip4_options_profile_id, 13149 int ip4_option, 13150 bcm_l3_ip4_options_action_t action) 13151 { 13152 int rv = BCM_E_UNAVAIL; 13153 #ifdef BCM_TRIDENT2_SUPPORT 13154 if (soc_feature(unit, soc_feature_l3_ip4_options_profile)) { 13155 rv = _bcm_td2_l3_ip4_options_profile_action_set(unit, ip4_options_profile_id, 13156 ip4_option, action); 13157 } 13158 #endif /* BCM_TRIDENT2_SUPPORT */ 13159 return (rv); 13160 } 13161 13162 /* 13163 * Function: 13164 * bcm_esw_l3_ip4_options_action_get 13165 * Purpose: 13166 * Retrive action for given IP action and Profile ID 13167 * Parameters: 13168 * unit - (IN) bcm device. 13169 * ip4_options_profile_id - (IN) IP options profile ID 13170 * ip4_option - (OUT) Action for IP Options 13171 * Returns: 13172 * BCM_E_XXX 13173 */ 13174 int 13175 bcm_esw_l3_ip4_options_action_get(int unit, 13176 int ip4_options_profile_id, 13177 int ip4_option, 13178 bcm_l3_ip4_options_action_t *action) 13179 { 13180 int rv = BCM_E_UNAVAIL; 13181 if (action == NULL) { 13182 return BCM_E_PARAM; 13183 } 13184 #ifdef BCM_TRIDENT2_SUPPORT 13185 if (soc_feature(unit, soc_feature_l3_ip4_options_profile)) { 13186 rv = _bcm_td2_l3_ip4_options_profile_action_get(unit, ip4_options_profile_id, 13187 ip4_option, action); 13188 } 13189 #endif /* BCM_TRIDENT2_SUPPORT */ 13190 return (rv); 13191 } 13192 13193 /* 13194 * Function: 13195 * _bcm_esw_l3_egress_reference_get 13196 * Purpose: 13197 * Get the reference count of the following object 13198 * 13199 * Egress object ECMP = 0 13200 * Multipath object ECMP = 1 13201 * 13202 * Parameters: 13203 * unit - (IN) bcm device. 13204 * mpintf - (IN) L3 interface id pointing to Egress nh/multipath object 13205 * ecmp - (IN) Flag to indicate the object is multicast or not 13206 * ref_count - (OUT) The number of references to the L3 Table 13207 * Returns: 13208 * BCM_E_XXX 13209 */ 13210 int 13211 _bcm_esw_l3_egress_reference_get(int unit, bcm_if_t mpintf, int ecmp, 13212 uint32 * ref_count) 13213 { 13214 #if defined(BCM_XGS3_SWITCH_SUPPORT) 13215 int offset = 0; 13216 uint32 object_id; 13217 13218 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 13219 L3_LOCK(unit); 13220 13221 if (ecmp != 0) { 13222 /* Multipath object */ 13223 offset = BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 13224 } else { 13225 /* None-Multipaht object */ 13226 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, mpintf)) { 13227 /* Egress object */ 13228 offset = BCM_XGS3_EGRESS_IDX_MIN(unit); 13229 } else if ( BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, mpintf)) { 13230 /* DVP Egress object */ 13231 offset = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 13232 } 13233 } 13234 13235 object_id = mpintf - offset; 13236 13237 _bcm_xgs3_nh_ref_cnt_get(unit, object_id, ecmp, ref_count); 13238 13239 L3_UNLOCK(unit); 13240 } 13241 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 13242 return (BCM_E_NONE); 13243 } 13244 13245 /* 13246 * Function: 13247 * _bcm_esw_l3_egress_ref_dlb_update 13248 * Purpose: 13249 * Update the reference count based on DLB 13250 * 13251 * Parameters: 13252 * unit - (IN) bcm device. 13253 * index - (IN) egress object index 13254 * ref_count - (OUT) pointer of the number of references to the L3 Table 13255 * Returns: 13256 * BCM_E_XXX 13257 */ 13258 int 13259 _bcm_esw_l3_egress_ref_dlb_update(int unit, int index,uint32 * ref_count) 13260 { 13261 int rv = BCM_E_NONE; 13262 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined (BCM_TRIDENT3_SUPPORT) 13263 int i, j; 13264 bcm_l3_egress_ecmp_t tmp_ecmp; 13265 SHR_BITDCL *group_bitmap_ptr = NULL; 13266 int dlb_intf_count = 0; 13267 bcm_if_t *dlb_intf_array = NULL; 13268 int group_enable; 13269 ecmp_dlb_control_entry_t *ecmp_group_entry; 13270 int offset = 0; 13271 int index_min, index_max, buf_size; 13272 uint8 *ecmp_dlb_buf = NULL; 13273 soc_mem_t mem = ECMP_DLB_CONTROLm; 13274 13275 if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) { 13276 int dlb_start = 0, dlb_end = 0; 13277 dlb_intf_array = sal_alloc(sizeof(bcm_if_t) * 13278 BCM_XGS3_L3_ECMP_MAX(unit), 13279 "ecmp intf array"); 13280 if (NULL == dlb_intf_array) { 13281 return BCM_E_MEMORY; 13282 } 13283 #if defined(BCM_TOMAHAWK3_SUPPORT) 13284 if (soc_feature(unit, soc_feature_th3_style_dlb)) { 13285 dlb_start = BCM_TH3_L3_ECMP_DLB_START(unit); 13286 dlb_end = BCM_TH3_L3_ECMP_DLB_END(unit) + 1; 13287 } else 13288 #endif 13289 { 13290 index_min = soc_mem_index_min(unit, mem); 13291 index_max = soc_mem_index_max(unit, mem); 13292 dlb_end = soc_mem_index_count(unit, ECMP_DLB_CONTROLm); 13293 buf_size = SOC_MEM_TABLE_BYTES(unit, mem); 13294 ecmp_dlb_buf = soc_cm_salloc(unit, buf_size, "ECMP_DLB_CONTROL buffer for group"); 13295 if (NULL == ecmp_dlb_buf) { 13296 rv = BCM_E_MEMORY; 13297 goto cleanup; 13298 } 13299 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index_min, index_max, ecmp_dlb_buf); 13300 if (SOC_FAILURE(rv)) { 13301 goto cleanup; 13302 } 13303 } 13304 #if defined(BCM_TOMAHAWK3_SUPPORT) 13305 if (soc_feature(unit, soc_feature_th3_style_dlb)) { 13306 offset = (BCM_XGS3_L3_MAX_ECMP_MODE(unit)) ? 1 : 2; 13307 } else 13308 #endif 13309 { 13310 offset = 1; 13311 } 13312 for (i = dlb_start; i < dlb_end; i += offset) { 13313 #if defined(BCM_TOMAHAWK3_SUPPORT) 13314 if (soc_feature(unit, soc_feature_th3_style_dlb)) { 13315 uint64 dlb_en_bitmap; 13316 uint32 dlb_id, len; 13317 dlb_id = i - BCM_TH3_L3_ECMP_DLB_START(unit); 13318 len = soc_reg_field_length(unit, 13319 DLB_ID_0_TO_63_ENABLEr, BITMAPf); 13320 if (len == 0) { 13321 rv = BCM_E_INTERNAL; 13322 goto cleanup; 13323 } 13324 if (dlb_id < len) { 13325 SOC_IF_ERROR_RETURN 13326 (READ_DLB_ID_0_TO_63_ENABLEr(unit, &dlb_en_bitmap)); 13327 group_enable = ((COMPILER_64_BITTEST(dlb_en_bitmap, 13328 dlb_id))); 13329 } else { 13330 SOC_IF_ERROR_RETURN 13331 (READ_DLB_ID_64_TO_127_ENABLEr(unit, &dlb_en_bitmap)); 13332 group_enable = ((COMPILER_64_BITTEST(dlb_en_bitmap, 13333 dlb_id - len))); 13334 } 13335 } else 13336 #endif 13337 { 13338 ecmp_group_entry = (ecmp_dlb_control_entry_t *) 13339 soc_mem_table_idx_to_pointer 13340 (unit, mem, void *, ecmp_dlb_buf, i); 13341 group_enable = soc_ECMP_DLB_CONTROLm_field32_get(unit, 13342 ecmp_group_entry, 13343 GROUP_ENABLEf); 13344 } 13345 if (0 == group_enable) { 13346 /* DLB not enabled */ 13347 continue; 13348 } 13349 13350 bcm_l3_egress_ecmp_t_init(&tmp_ecmp); 13351 tmp_ecmp.ecmp_intf = i + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 13352 rv = _bcm_esw_l3_egress_ecmp_get(unit, &tmp_ecmp, 13353 BCM_XGS3_L3_ECMP_MAX(unit), 13354 dlb_intf_array, &dlb_intf_count, 13355 TRUE); 13356 if (BCM_FAILURE(rv)) { 13357 rv = BCM_E_INTERNAL; 13358 goto cleanup; 13359 } 13360 group_bitmap_ptr = 13361 BCM_XGS3_L3_ECMP_DLB_MEMBER_GROUP_PTR(unit, i); 13362 for (j = 0; j < dlb_intf_count; j++) { 13363 if (!SHR_BITGET(group_bitmap_ptr, j) && 13364 (index == dlb_intf_array[j])) { 13365 ref_count--; 13366 } 13367 } 13368 } 13369 cleanup: 13370 if (ecmp_dlb_buf) { 13371 soc_cm_sfree(unit, ecmp_dlb_buf); 13372 } 13373 sal_free(dlb_intf_array); 13374 } 13375 #endif 13376 13377 return rv; 13378 } 13379 13380 /* 13381 * Function: 13382 * bcmi_esw_l3_egress_ref_count_update 13383 * Purpose: 13384 * Update the reference count of the following object 13385 * 13386 * Egress object ECMP = 0 13387 * Multipath object ECMP = 1 13388 * 13389 * Parameters: 13390 * unit - (IN) bcm device. 13391 * intf - (IN) L3 interface id pointing to Egress nh/multipath object 13392 * flags - (IN) Flag to indicate the object is multicast or not 13393 * nh_ecmp_id - (IN) Next Hop ECMP Id 13394 * incr - (IN) Increment/Decrement 13395 * Returns: 13396 * BCM_E_XXX 13397 */ 13398 int 13399 bcmi_esw_l3_egress_ref_count_update(int unit, 13400 bcm_if_t intf, 13401 uint32 flags, 13402 int nh_ecmp_id, 13403 int incr) 13404 { 13405 int rv = BCM_E_UNAVAIL; 13406 13407 #if defined(BCM_XGS3_SWITCH_SUPPORT) 13408 if (SOC_IS_XGS3_SWITCH(unit) && soc_feature(unit, soc_feature_l3)) { 13409 L3_LOCK(unit); 13410 rv = bcmi_xgs3_l3_egress_ref_count_update (unit, 13411 intf, flags, nh_ecmp_id, incr); 13412 L3_UNLOCK(unit); 13413 } 13414 #endif 13415 return rv; 13416 } 13417 13418 /* 13419 * Function: 13420 * bcm_esw_l3_egress_multi_alloc 13421 * Purpose: 13422 * Allocates multiple egress objects. 13423 * 13424 * Parameters: 13425 * unit - (IN) bcm device. 13426 * egress_multi_info - (IN) information needed to create multiple 13427 * egress objects 13428 * base_egress_id - (IN/OUT) base Next Hop Id 13429 * Returns: 13430 * BCM_E_XXX 13431 */ 13432 int 13433 bcm_esw_l3_egress_multi_alloc(int unit, 13434 bcm_l3_egress_multi_info_t egress_multi_info, 13435 bcm_if_t *base_egress_id) 13436 { 13437 int rv = BCM_E_NONE; 13438 13439 if (base_egress_id == NULL) { 13440 return BCM_E_PARAM; 13441 } 13442 13443 L3_LOCK(unit); 13444 rv = bcmi_l3_egress_multi_alloc(unit, egress_multi_info, base_egress_id); 13445 L3_UNLOCK(unit); 13446 13447 return rv; 13448 } 13449 13450 /* 13451 * Function: 13452 * bcm_esw_l3_egress_multi_free 13453 * Purpose: 13454 * Frees multiple egress objects. 13455 * 13456 * Parameters: 13457 * unit - (IN) bcm device. 13458 * base_egress_id - (IN) base Next Hop Id 13459 * Returns: 13460 * BCM_E_XXX 13461 */ 13462 int 13463 bcm_esw_l3_egress_multi_free(int unit, bcm_if_t base_egress_id) 13464 { 13465 13466 int rv = BCM_E_NONE; 13467 13468 L3_LOCK(unit); 13469 rv = bcmi_l3_egress_multi_free(unit, base_egress_id); 13470 L3_UNLOCK(unit); 13471 13472 return rv; 13473 } 13474 13475 /* 13476 * Function: 13477 * bcm_esw_l3_intf_vpn_set 13478 * Purpose: 13479 * Set the VPN on a given L3 Egress interface. 13480 * 13481 * Parameters: 13482 * unit - (IN) Unit number. 13483 * l3_intf_id - (IN) Interface ID of an egress L3 object 13484 * bcm_vpn_t - (IN) VPN_ID that needs to be set on this interface 13485 * flags - (IN) Flags for future use 13486 * Returns: 13487 * BCM_E_XXX 13488 */ 13489 int 13490 bcm_esw_l3_intf_vpn_set(int unit, 13491 bcm_if_t l3_intf_id, uint32 flags, 13492 bcm_vpn_t vpn) 13493 { 13494 int rv = BCM_E_UNAVAIL; 13495 #ifdef BCM_TRIDENT3_SUPPORT 13496 if (soc_feature(unit, soc_feature_egr_intf_vlan_vfi_deoverlay)) { 13497 L3_LOCK(unit); 13498 rv = bcmi_l3_intf_vpn_set(unit, l3_intf_id, vpn, flags); 13499 L3_UNLOCK(unit); 13500 } 13501 #endif 13502 return rv; 13503 } 13504 13505 /* 13506 * Function: 13507 * bcm_esw_l3_intf_vpn_get 13508 * Purpose: 13509 * Get the VPN on a given L3 Egress interface. 13510 * 13511 * Parameters: 13512 * unit - (IN) Unit number. 13513 * l3_intf_id - (IN) Interface ID of an egress L3 object 13514 * bcm_vpn_t - (OUT) VPN_ID that was set on this interface 13515 * flags - (OUT) Flags for future use 13516 * Returns: 13517 * BCM_E_XXX 13518 */ 13519 int 13520 bcm_esw_l3_intf_vpn_get(int unit, 13521 bcm_if_t l3_intf_id, uint32 *flags, 13522 bcm_vpn_t *vpn) 13523 { 13524 int rv = BCM_E_UNAVAIL; 13525 #ifdef BCM_TRIDENT3_SUPPORT 13526 if (soc_feature(unit, soc_feature_egr_intf_vlan_vfi_deoverlay)) { 13527 L3_LOCK(unit); 13528 rv = bcmi_l3_intf_vpn_get(unit, l3_intf_id, vpn, flags); 13529 L3_UNLOCK(unit); 13530 } 13531 #endif 13532 return rv; 13533 } 13534 13535 /* 13536 * Function: 13537 * bcmi_esw_l3_dependent_cleanup 13538 * Purpose: 13539 * frees l3 dependednt resources from other modules. 13540 * Parameters: 13541 * unit - (IN)bcm device id 13542 * Returns: 13543 * NONE 13544 */ 13545 void 13546 bcmi_esw_l3_dependent_cleanup(int unit) 13547 { 13548 bcmi_l3_dependent_free_resources(unit); 13549 } 13550 13551 /* 13552 * Function: 13553 * bcm_esw_l3_ecmp_dlb_mon_config_set 13554 * Purpose: 13555 * This API configures DLB flow monitoring parameters for a DLB id 13556 * derived from ECMP group id (the second argument). The monitored packets 13557 * can be copied to cpu and/or mirrored (using newly defined PSAMP header 13558 * formats). The sample rate is used to program sampling threshold to 13559 * determine when a packet should be sampled. 13560 * Parameters: 13561 * unit : (IN) Device's unit number 13562 * ecmp_intf : (IN) ECMP interface id obtained from bcm_l3_ecmp_create or 13563 * bcm_l3_egress_ecmp_create 13564 * dlb_mon_cfg : (IN) DLB flow monitoring configuration 13565 * Returns: 13566 * BCM_E_XXX 13567 * Notes: 13568 * Property spn_DLB_FLOW_MONITOR_EN must be enabled to use this API 13569 */ 13570 int 13571 bcm_esw_l3_ecmp_dlb_mon_config_set(int unit, 13572 bcm_if_t ecmp_intf, 13573 bcm_l3_ecmp_dlb_mon_cfg_t *dlb_mon_cfg) 13574 { 13575 #ifdef BCM_TOMAHAWK3_SUPPORT 13576 int rv = BCM_E_UNAVAIL; 13577 13578 /* Currently this API is supported on Tomahawk3 only */ 13579 if (!SOC_IS_TOMAHAWK3(unit)) { 13580 return BCM_E_UNAVAIL; 13581 } 13582 13583 rv = bcm_th3_l3_ecmp_dlb_mon_config_set(unit, ecmp_intf, dlb_mon_cfg); 13584 13585 return rv; 13586 #else /* BCM_TOMAHAWK3_SUPPORT */ 13587 return BCM_E_UNAVAIL; 13588 #endif 13589 } 13590 13591 /* 13592 * Function: 13593 * bcm_esw_l3_ecmp_dlb_mon_config_get 13594 * Purpose: 13595 * This API will fetch DLB monitoring parameters from hardware, for a DLB id 13596 * derived from ECMP group id (the second argument). If the get API is called 13597 * before any configuration, just after init, it will return default hardware 13598 * values. In other cases, it will contain the last configured set of values 13599 * associated with the DLB id. 13600 * Parameters: 13601 * unit : (IN) Device's unit number 13602 * ecmp_intf : (IN) ECMP interface id obtained from bcm_l3_ecmp_create or, 13603 * bcm_l3_egress_ecmp_create 13604 * dlb_mon_cfg : (OUT) DLB flow monitoring configuration read from h/w for 13605 * specified DLB 13606 * Returns: 13607 * BCM_E_XXX 13608 * Notes: 13609 * 1. Property spn_DLB_FLOW_MONITOR_EN must be enabled to use this API 13610 * 2. Sample rates are calculated only if MONITOR_EN is set for a DLB id. 13611 * Otherwise, sample rate of 0 is returned. 13612 */ 13613 int bcm_esw_l3_ecmp_dlb_mon_config_get(int unit, 13614 bcm_if_t ecmp_intf, 13615 bcm_l3_ecmp_dlb_mon_cfg_t *dlb_mon_cfg) 13616 { 13617 #ifdef BCM_TOMAHAWK3_SUPPORT 13618 int rv = BCM_E_UNAVAIL; 13619 13620 /* Currently this API is supported on Tomahawk3 only */ 13621 if (!SOC_IS_TOMAHAWK3(unit)) { 13622 return BCM_E_UNAVAIL; 13623 } 13624 13625 rv = bcm_th3_l3_ecmp_dlb_mon_config_get(unit, ecmp_intf, dlb_mon_cfg); 13626 13627 return rv; 13628 #else /* BCM_TOMAHAWK3_SUPPORT */ 13629 return BCM_E_UNAVAIL; 13630 #endif 13631 } 13632 13633 #endif /* INCLUDE_L3 */ 13634