mpls.c (94882B)
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: mpls.c 8 * Purpose: Katana MPLS enhancements 9 */ 10 #include <soc/defs.h> 11 12 #include <assert.h> 13 #include <shared/bsl.h> 14 #include <sal/core/libc.h> 15 #if defined(BCM_KATANA_SUPPORT) && defined(BCM_MPLS_SUPPORT) && \ 16 defined(INCLUDE_L3) 17 18 #include <shared/util.h> 19 #include <soc/mem.h> 20 #include <soc/cm.h> 21 #include <soc/drv.h> 22 #include <soc/register.h> 23 #include <soc/memory.h> 24 #include <bcm/qos.h> 25 #include <bcm/error.h> 26 #include <bcm_int/esw/triumph2.h> 27 #include <bcm_int/esw/triumph3.h> 28 #include <bcm_int/esw/triumph.h> 29 #include <bcm_int/esw/port.h> 30 #include <bcm_int/esw/firebolt.h> 31 #include <bcm_int/esw/trx.h> 32 #include <bcm_int/esw/virtual.h> 33 #include <bcm_int/esw/xgs3.h> 34 #include <bcm_int/esw_dispatch.h> 35 #include <bcm_int/esw/switch.h> 36 #include <bcm_int/esw/mpls.h> 37 #include <bcm_int/esw/katana.h> 38 #include <bcm_int/esw/flex_ctr.h> 39 #include <bcm_int/esw/multicast.h> 40 #include <bcm_int/common/multicast.h> 41 42 43 /* 44 * Function: 45 * _bcm_kt_mpls_p2mp_loopback_enable 46 * Purpose: 47 * Enable loopback for MPLS P2MP 48 * Parameters: 49 * IN : unit 50 * Returns: 51 * BCM_E_XXX 52 */ 53 54 STATIC int 55 _bcm_kt_mpls_p2mp_loopback_enable(int unit) 56 { 57 int rv = BCM_E_NONE; 58 multipass_loopback_bitmap_entry_t p2mp_loopback; 59 soc_field_t lport_fields[] = { 60 #ifndef BCM_KATANA2_SUPPORT 61 PORT_TYPEf, 62 #endif 63 MPLS_ENABLEf, 64 V4L3_ENABLEf, 65 V6L3_ENABLEf 66 }; 67 uint32 lport_values[] = { 68 #ifndef BCM_KATANA2_SUPPORT 69 0x2, 70 #endif 71 0x1, /* MPLS_ENABLEf */ 72 0x1, /* V4L3_ENABLEf */ 73 0x1 /* V6L3_ENABLEf */ 74 }; 75 76 if (SOC_IS_KATANA(unit)) { 77 sal_memset(&p2mp_loopback, 0, 78 sizeof(multipass_loopback_bitmap_entry_t)); 79 80 /* Enable Loopback */ 81 soc_mem_field32_set(unit, MULTIPASS_LOOPBACK_BITMAPm, 82 &p2mp_loopback, BITMAP_W1f, 0x8); 83 rv = soc_mem_write(unit, MULTIPASS_LOOPBACK_BITMAPm, 84 MEM_BLOCK_ALL, 0, &p2mp_loopback); 85 if (rv < 0) { 86 return rv; 87 } 88 } 89 90 /* Update LPORT Profile Table */ 91 rv = _bcm_lport_profile_fields32_modify(unit, LPORT_PROFILE_LPORT_TAB, 92 COUNTOF(lport_fields), 93 lport_fields, lport_values); 94 95 return rv; 96 } 97 98 /* 99 * Function: 100 * _bcm_kt_mpls_p2mp_loopback_disable 101 * Purpose: 102 * Disable loopback for MPLS P2MP 103 * Parameters: 104 * IN : unit 105 * Returns: 106 * BCM_E_XXX 107 */ 108 109 STATIC int 110 _bcm_kt_mpls_p2mp_loopback_disable(int unit) 111 { 112 int rv = BCM_E_NONE; 113 multipass_loopback_bitmap_entry_t p2mp_loopback; 114 soc_field_t lport_fields[] = { 115 #ifndef BCM_KATANA2_SUPPORT 116 PORT_TYPEf, 117 #endif 118 MPLS_ENABLEf, 119 V4L3_ENABLEf, 120 V6L3_ENABLEf 121 }; 122 uint32 lport_values[] = { 123 #ifndef BCM_KATANA2_SUPPORT 124 0x0, /* PORT_TYPEf */ 125 #endif 126 0x0, /* MPLS_ENABLEf */ 127 0x0, /* V4L3_ENABLEf */ 128 0x0 /* V6L3_ENABLEf */ 129 }; 130 131 if (SOC_IS_KATANA(unit)) { 132 sal_memset(&p2mp_loopback, 0, 133 sizeof(multipass_loopback_bitmap_entry_t)); 134 135 /* Disable Loopback */ 136 soc_mem_field32_set(unit, MULTIPASS_LOOPBACK_BITMAPm, 137 &p2mp_loopback, BITMAP_W1f, 0x0); 138 rv = soc_mem_write(unit, MULTIPASS_LOOPBACK_BITMAPm, 139 MEM_BLOCK_ALL, 0, &p2mp_loopback); 140 if (rv < 0) { 141 return rv; 142 } 143 } 144 145 /* Update LPORT Profile Table */ 146 rv = _bcm_lport_profile_fields32_modify(unit, LPORT_PROFILE_LPORT_TAB, 147 COUNTOF(lport_fields), 148 lport_fields, lport_values); 149 150 return rv; 151 } 152 153 154 /* 155 * Function: 156 * _bcm_kt_mpls_entry_delete 157 * Purpose: 158 * Delete entry from MPLS_ENTRY table 159 * Parameters: 160 * unit - Device Number 161 * ment - MPLS Label entry to delete 162 * Returns: 163 * BCM_E_XXX 164 */ 165 166 STATIC int 167 _bcm_kt_mpls_entry_delete(int unit, mpls_entry_entry_t *ment, 168 bcm_mpls_tunnel_switch_t *info, int index) 169 { 170 ing_pw_term_counters_entry_t pw_cnt_entry; 171 int rv, action, ecmp_index = -1, nh_index = -1, pw_cnt = -1; 172 bcm_if_t egress_if=0; 173 int ref_count=0, forwarding_field_type=-1, ipmc_index=-1; 174 int two_pass=-1, l3_iif=-1, is_set=0; 175 176 if (soc_MPLS_ENTRYm_field32_get(unit, ment, PW_TERM_NUM_VALIDf)) { 177 pw_cnt = soc_MPLS_ENTRYm_field32_get(unit, ment, PW_TERM_NUMf); 178 } 179 180 action = soc_MPLS_ENTRYm_field32_get(unit, ment, 181 MPLS_ACTION_IF_BOSf); 182 forwarding_field_type = soc_MPLS_ENTRYm_field32_get(unit, ment, 183 FORWARDING_FIELD_TYPEf); 184 185 if (forwarding_field_type == _BCM_MPLS_FORWARD_MULTICAST_GROUP) { 186 ipmc_index = soc_MPLS_ENTRYm_field32_get(unit, ment, 187 FORWARDING_FIELDf); 188 two_pass = soc_MPLS_ENTRYm_field32_get(unit, ment, 189 MPLS_SECOND_PASS_ACTION_VALIDf); 190 rv = bcm_xgs3_ipmc_id_is_set(unit, ipmc_index, &is_set); 191 if (BCM_SUCCESS(rv)) { 192 if (is_set) { 193 /* First Delete IPMC_entry, then delete P2MP Label entry */ 194 return BCM_E_BUSY; 195 } 196 } 197 if ((two_pass) && (info->action != -1)) { 198 if (info->action == BCM_MPLS_SWITCH_ACTION_PHP) { 199 l3_iif = soc_MPLS_ENTRYm_field32_get(unit, ment, 200 L3_IIF_2f); 201 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf, 202 0x0); /* INVALID */ 203 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf, 204 0x2); /* L3_IIF */ 205 soc_MPLS_ENTRYm_field32_set(unit, ment, L3_IIFf, 206 l3_iif); 207 } 208 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_VALIDf, 209 0x0); 210 (void) _bcm_kt_mpls_p2mp_loopback_disable(unit); 211 BCM_IF_ERROR_RETURN(rv); 212 213 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_IF_BOSf, 214 0x0); 215 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_IF_NOT_BOSf, 216 0x0); 217 soc_MPLS_ENTRYm_field32_set(unit, ment, L3_IIF_2f, 218 0x0); 219 rv = soc_mem_write(unit, MPLS_ENTRYm, 220 MEM_BLOCK_ALL, index, 221 ment); 222 return rv; 223 } 224 } else if (forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) { 225 /* SWAP_NHI or L3_NHI */ 226 nh_index = soc_MPLS_ENTRYm_field32_get(unit, ment, NEXT_HOP_INDEXf); 227 } else if (forwarding_field_type == _BCM_MPLS_FORWARD_ECMP_GROUP) { 228 /* L3_ECMP */ 229 ecmp_index = soc_MPLS_ENTRYm_field32_get(unit, ment, ECMP_PTRf); 230 } 231 232 /* Delete the entry from HW */ 233 rv = soc_mem_delete(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, ment); 234 if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) { 235 return rv; 236 } 237 238 if (pw_cnt != -1) { 239 sal_memset(&pw_cnt_entry, 0, sizeof(ing_pw_term_counters_entry_t)); 240 (void) WRITE_ING_PW_TERM_COUNTERSm(unit, MEM_BLOCK_ALL, pw_cnt, 241 &pw_cnt_entry); 242 (void) bcm_tr_mpls_pw_used_clear(unit, pw_cnt); 243 } 244 245 if (forwarding_field_type != _BCM_MPLS_FORWARD_MULTICAST_GROUP) { 246 if ((forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) && (action == 0x3)) { 247 /* SWAP_NHI */ 248 /* Check if tunnel_switch.egress_label mode is being used */ 249 rv = bcm_tr_mpls_get_vp_nh (unit, (bcm_if_t) nh_index, &egress_if); 250 if (rv == BCM_E_NONE) { 251 rv = bcm_tr_mpls_l3_nh_info_delete(unit, nh_index); 252 } else { 253 /* Decrement next-hop Reference count */ 254 rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count, nh_index); 255 } 256 } else if ((forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) && (action == 0x4)) { 257 /* L3_NHI */ 258 rv = bcm_xgs3_nh_del(unit, 0, nh_index); 259 } else if (forwarding_field_type == _BCM_MPLS_FORWARD_ECMP_GROUP) { 260 /* L3_ECMP */ 261 rv = bcm_xgs3_ecmp_group_del(unit, ecmp_index, 0); 262 } 263 } 264 return rv; 265 } 266 267 /* 268 * Function: 269 * _bcm_kt_mpls_entry_set_key 270 * Purpose: 271 * Convert key part of application format to HW entry. 272 * Parameters: 273 * unit - Device Number 274 * info - Label (switch) information 275 * ment - MPLS entry 276 * Returns: 277 * BCM_E_XXX 278 */ 279 280 STATIC int 281 _bcm_kt_mpls_entry_set_key(int unit, bcm_mpls_tunnel_switch_t *info, 282 mpls_entry_entry_t *ment) 283 { 284 bcm_module_t mod_out; 285 bcm_port_t port_out; 286 bcm_trunk_t trunk_id; 287 int rv, gport_id; 288 289 sal_memset(ment, 0, sizeof(mpls_entry_entry_t)); 290 291 if (info->port == BCM_GPORT_INVALID) { 292 /* Global label, mod/port not part of lookup key */ 293 soc_MPLS_ENTRYm_field32_set(unit, ment, MODULE_IDf, 0); 294 soc_MPLS_ENTRYm_field32_set(unit, ment, PORT_NUMf, 0); 295 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) { 296 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_LABELf, info->label); 297 } else { 298 return BCM_E_PARAM; 299 } 300 soc_MPLS_ENTRYm_field32_set(unit, ment, VALIDf, 1); 301 return BCM_E_NONE; 302 } 303 304 rv = _bcm_esw_gport_resolve(unit, info->port, &mod_out, 305 &port_out, &trunk_id, &gport_id); 306 BCM_IF_ERROR_RETURN(rv); 307 308 if (BCM_GPORT_IS_TRUNK(info->port)) { 309 soc_MPLS_ENTRYm_field32_set(unit, ment, Tf, 1); 310 soc_MPLS_ENTRYm_field32_set(unit, ment, TGIDf, trunk_id); 311 } else { 312 soc_MPLS_ENTRYm_field32_set(unit, ment, MODULE_IDf, mod_out); 313 soc_MPLS_ENTRYm_field32_set(unit, ment, PORT_NUMf, port_out); 314 } 315 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) { 316 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_LABELf, info->label); 317 } else { 318 return BCM_E_PARAM; 319 } 320 soc_MPLS_ENTRYm_field32_set(unit, ment, VALIDf, 1); 321 soc_MPLS_ENTRYm_field32_set(unit, ment, KEY_TYPEf, 0); 322 323 return BCM_E_NONE; 324 } 325 326 327 /* 328 * Function: 329 * _bcm_kt_mpls_entry_get_key 330 * Purpose: 331 * Convert key part of HW entry to application format. 332 * Parameters: 333 * unit - Device Number 334 * ment - mpls entry 335 * info - Label (switch) information 336 * Returns: 337 * BCM_E_XXX 338 */ 339 340 STATIC int 341 _bcm_kt_mpls_entry_get_key(int unit, mpls_entry_entry_t *ment, 342 bcm_mpls_tunnel_switch_t *info) 343 { 344 bcm_port_t port_in, port_out; 345 bcm_module_t mod_in, mod_out; 346 bcm_trunk_t trunk_id; 347 348 port_in = soc_MPLS_ENTRYm_field32_get(unit, ment, PORT_NUMf); 349 mod_in = soc_MPLS_ENTRYm_field32_get(unit, ment, MODULE_IDf); 350 if (soc_MPLS_ENTRYm_field32_get(unit, ment, Tf)) { 351 trunk_id = soc_MPLS_ENTRYm_field32_get(unit, ment, TGIDf); 352 BCM_GPORT_TRUNK_SET(info->port, trunk_id); 353 } else if ((port_in == 0) && (mod_in == 0)) { 354 /* Global label, mod/port not part of lookup key */ 355 info->port = BCM_GPORT_INVALID; 356 } else { 357 BCM_IF_ERROR_RETURN 358 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 359 mod_in, port_in, &mod_out, &port_out)); 360 BCM_GPORT_MODPORT_SET(info->port, mod_out, port_out); 361 } 362 info->label = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS_LABELf); 363 364 return BCM_E_NONE; 365 } 366 367 /* 368 * Function: 369 * _bcm_kt_mpls_entry_get_data 370 * Purpose: 371 * Convert data part of HW entry to application format. 372 * Parameters: 373 * unit - Device Number 374 * ment - mpls entry 375 * info - Label (switch) information 376 * Returns: 377 * BCM_E_XXX 378 */ 379 380 STATIC int 381 _bcm_kt_mpls_entry_get_data(int unit, mpls_entry_entry_t *ment, 382 bcm_mpls_tunnel_switch_t *info) 383 { 384 int action, nh_index, ecmp_group, vrf, ipmc_index; 385 uint32 forwarding_type=0; 386 bcm_if_t egress_if=0; 387 int rv=BCM_E_NONE; 388 int mode = 0; 389 390 BCM_IF_ERROR_RETURN(bcm_xgs3_l3_ingress_mode_get(unit, &mode)); 391 392 action = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS_ACTION_IF_BOSf); 393 switch(action) { 394 case 0x2: 395 info->action = BCM_MPLS_SWITCH_ACTION_POP; 396 forwarding_type = soc_MPLS_ENTRYm_field32_get(unit, ment, 397 FORWARDING_FIELD_TYPEf); 398 if (forwarding_type == _BCM_MPLS_FORWARD_MULTICAST_GROUP) { 399 info->flags |= BCM_MPLS_SWITCH_P2MP; 400 if (!mode) { 401 vrf = soc_MPLS_ENTRYm_field32_get(unit, ment, L3_IIF_2f); 402 vrf -= _BCM_TR_MPLS_L3_IIF_BASE; 403 _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_L3, vrf); 404 } else { 405 info->ingress_if = soc_MPLS_ENTRYm_field32_get(unit, ment, L3_IIF_2f); 406 } 407 } else { 408 if (!mode) { 409 vrf = soc_MPLS_ENTRYm_field32_get(unit, ment, L3_IIFf); 410 /* 411 * If the ingress mode is not set, then L3_IIF is added 412 * above the intreface of _BCM_TR_MPLS_L3_IIF_BASE. 413 * If this is 0 then 0 vpn index was sent. 414 */ 415 if (vrf != 0) { 416 vrf -= _BCM_TR_MPLS_L3_IIF_BASE; 417 _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_L3, vrf); 418 } 419 } else { 420 info->ingress_if = soc_MPLS_ENTRYm_field32_get(unit, ment, L3_IIFf); 421 } 422 } 423 break; 424 case 0x3: 425 info->action = BCM_MPLS_SWITCH_ACTION_SWAP; 426 forwarding_type = soc_MPLS_ENTRYm_field32_get(unit, ment, 427 FORWARDING_FIELD_TYPEf); 428 if (forwarding_type == _BCM_MPLS_FORWARD_NEXT_HOP) { 429 nh_index = soc_MPLS_ENTRYm_field32_get(unit, ment, 430 NEXT_HOP_INDEXf); 431 rv = bcm_tr_mpls_get_vp_nh (unit, nh_index, &egress_if); 432 if (rv == BCM_E_NONE) { 433 rv = bcm_tr_mpls_l3_nh_info_get(unit, info, nh_index); 434 BCM_IF_ERROR_RETURN(rv); 435 } else { 436 info->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 437 info->egress_label.label = BCM_MPLS_LABEL_INVALID; 438 } 439 } else if (forwarding_type == _BCM_MPLS_FORWARD_ECMP_GROUP) { 440 ecmp_group = soc_MPLS_ENTRYm_field32_get(unit, ment, 441 ECMP_PTRf); 442 info->egress_if = ecmp_group + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 443 info->egress_label.label = BCM_MPLS_LABEL_INVALID; 444 } else if (forwarding_type == _BCM_MPLS_FORWARD_MULTICAST_GROUP) { 445 ipmc_index = soc_MPLS_ENTRYm_field32_get(unit, ment, 446 FORWARDING_FIELDf); 447 info->flags |= BCM_MPLS_SWITCH_P2MP; 448 info->egress_label.label = BCM_MPLS_LABEL_INVALID; 449 _BCM_MULTICAST_GROUP_SET(info->mc_group, 450 _BCM_MULTICAST_TYPE_EGRESS_OBJECT, ipmc_index); 451 } 452 break; 453 case 0x4: 454 info->action = BCM_MPLS_SWITCH_ACTION_PHP; 455 forwarding_type = soc_MPLS_ENTRYm_field32_get(unit, ment, 456 FORWARDING_FIELD_TYPEf); 457 if (forwarding_type == _BCM_MPLS_FORWARD_NEXT_HOP) { 458 nh_index = soc_MPLS_ENTRYm_field32_get(unit, ment, 459 NEXT_HOP_INDEXf); 460 info->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 461 } else if (forwarding_type == _BCM_MPLS_FORWARD_ECMP_GROUP) { 462 ecmp_group = soc_MPLS_ENTRYm_field32_get(unit, ment, 463 ECMP_PTRf); 464 info->egress_if = ecmp_group + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 465 } 466 break; 467 default: 468 return BCM_E_INTERNAL; 469 break; 470 } 471 if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, MPLS__DROP_DATA_ENABLEf)) { 472 if (soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__DROP_DATA_ENABLEf)) { 473 info->flags |= BCM_MPLS_SWITCH_DROP; 474 } 475 } 476 477 if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, MPLS__RX_PROT_GROUPf)) { 478 if (soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__RX_PROT_GROUPf)) { 479 info->failover_id = 480 soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__RX_PROT_GROUPf); 481 } 482 } 483 484 if (soc_MPLS_ENTRYm_field32_get(unit, ment, PW_TERM_NUM_VALIDf)) { 485 info->flags |= BCM_MPLS_SWITCH_COUNTED; 486 } 487 if (!soc_MPLS_ENTRYm_field32_get(unit, ment, DECAP_USE_TTLf)) { 488 info->flags |= BCM_MPLS_SWITCH_INNER_TTL; 489 } 490 if (soc_MPLS_ENTRYm_field32_get(unit, ment, DECAP_USE_EXP_FOR_INNERf)) { 491 info->flags |= BCM_MPLS_SWITCH_INNER_EXP; 492 } 493 if (soc_MPLS_ENTRYm_field32_get(unit, ment, 494 DECAP_USE_EXP_FOR_PRIf) == 0x1) { 495 496 /* Use specified EXP-map to determine internal prio/color */ 497 info->flags |= BCM_MPLS_SWITCH_INT_PRI_MAP; 498 info->exp_map = 499 soc_MPLS_ENTRYm_field32_get(unit, ment, EXP_MAPPING_PTRf); 500 info->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS; 501 } else if (soc_MPLS_ENTRYm_field32_get(unit, ment, 502 DECAP_USE_EXP_FOR_PRIf) == 0x2) { 503 504 /* Use the specified internal priority value */ 505 info->flags |= BCM_MPLS_SWITCH_INT_PRI_SET; 506 info->int_pri = 507 soc_MPLS_ENTRYm_field32_get(unit, ment, NEW_PRIf); 508 509 /* Use specified EXP-map to determine internal color */ 510 info->flags |= BCM_MPLS_SWITCH_COLOR_MAP; 511 info->exp_map = 512 soc_MPLS_ENTRYm_field32_get(unit, ment, EXP_MAPPING_PTRf); 513 info->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS; 514 } 515 return BCM_E_NONE; 516 } 517 /* 518 * Function: 519 * _bcm_kt_mpls_port_stat_get_table_info 520 * Description: 521 * Provides relevant flex table information(table-name,index with 522 * direction) for specific vpn and gport 523 * 524 * Parameters: 525 * unit - (IN) unit number 526 * vpn - (IN) VPN Id 527 * port - (IN) MPLS GPORT ID 528 * num_of_tables - (OUT) Number of flex counter tables 529 * table_info - (OUT) Flex counter tables information 530 * 531 * Return Value: 532 * BCM_E_XXX 533 * Notes: 534 */ 535 STATIC 536 bcm_error_t _bcm_kt_mpls_port_stat_get_table_info( 537 int unit, 538 bcm_vpn_t vpn, 539 bcm_gport_t port, 540 uint32 *num_of_tables, 541 bcm_stat_flex_table_info_t *table_info) 542 { 543 int vp=0, rv = BCM_E_NONE; 544 ing_dvp_table_entry_t dvp={{0}}; 545 int nh_index=0; 546 initial_prot_nhi_table_entry_t prot_entry; 547 int vpless_failover_port = FALSE; 548 549 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(port)) { 550 vpless_failover_port = TRUE; 551 port = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(port); 552 } 553 554 (*num_of_tables)=0; 555 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 556 return BCM_E_UNAVAIL; 557 } 558 if (soc_feature(unit, soc_feature_mpls)) { 559 BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit)); 560 if (!_BCM_MPLS_VPN_IS_VPLS(vpn) && 561 !_BCM_MPLS_VPN_IS_VPWS(vpn)) { 562 bcm_tr_mpls_unlock (unit); 563 return BCM_E_PARAM; 564 } 565 vp = BCM_GPORT_MPLS_PORT_ID_GET(port); 566 if (vp == -1) { 567 bcm_tr_mpls_unlock (unit); 568 return BCM_E_PARAM; 569 } 570 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 571 bcm_tr_mpls_unlock (unit); 572 return BCM_E_NOT_FOUND; 573 } 574 table_info[*num_of_tables].table= SOURCE_VPm; 575 table_info[*num_of_tables].index=vp; 576 table_info[*num_of_tables].direction=bcmStatFlexDirectionIngress; 577 (*num_of_tables)++; 578 if(READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp) == BCM_E_NONE) { 579 nh_index=soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 580 if (vpless_failover_port == TRUE) { 581 rv = READ_INITIAL_PROT_NHI_TABLEm(unit, MEM_BLOCK_ANY, nh_index, 582 &prot_entry); 583 if (BCM_FAILURE(rv)) { 584 bcm_tr_mpls_unlock (unit); 585 return rv; 586 } 587 nh_index = soc_INITIAL_PROT_NHI_TABLEm_field32_get(unit, 588 &prot_entry, PROT_NEXT_HOP_INDEXf); 589 } 590 table_info[*num_of_tables].table= EGR_L3_NEXT_HOPm; 591 table_info[*num_of_tables].index=nh_index; 592 table_info[*num_of_tables].direction=bcmStatFlexDirectionEgress; 593 (*num_of_tables)++; 594 } 595 bcm_tr_mpls_unlock (unit); 596 return BCM_E_NONE; 597 } 598 return BCM_E_UNAVAIL; 599 } 600 /* 601 * Function: 602 * _bcm_kt_mpls_label_stat_get_table_info 603 * Description: 604 * Provides relevant flex table information(table-name,index with 605 * direction) for given mpls label and gport 606 * 607 * Parameters: 608 * unit - (IN) unit number 609 * label - (IN) MPLS Label 610 * port - (IN) MPLS Gport 611 * object - (IN) STAT object 612 * num_of_tables - (OUT) Number of flex counter tables 613 * table_info - (OUT) Flex counter tables information 614 * 615 * Return Value: 616 * BCM_E_XXX 617 * Notes: 618 */ 619 620 STATIC 621 bcm_error_t _bcm_kt_mpls_label_stat_get_table_info( 622 int unit, 623 bcm_mpls_label_t label, 624 bcm_gport_t port, 625 bcm_stat_object_t object, 626 uint32 *num_of_tables, 627 bcm_stat_flex_table_info_t *table_info) 628 { 629 bcm_error_t rv=BCM_E_NOT_FOUND; 630 bcm_mpls_tunnel_switch_t mpls_tunnel_switch={0}; 631 mpls_entry_entry_t ment={{0}}; 632 int index[2] = {0, 0}; 633 soc_mem_t mem[2] = {MPLS_ENTRYm, L3_TUNNELm}; 634 int i, num_found = 0; 635 (*num_of_tables)=0; 636 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 637 return BCM_E_UNAVAIL; 638 } 639 640 if (soc_feature(unit, soc_feature_mpls)) { 641 mpls_tunnel_switch.port = port; 642 if (BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 643 mpls_tunnel_switch.label = label; 644 } else { 645 return BCM_E_PARAM; 646 } 647 648 BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit)); 649 if (object != bcmStatObjectIngMplsFrrLabel) { 650 rv = _bcm_kt_mpls_entry_set_key(unit, &mpls_tunnel_switch, &ment); 651 if (rv == BCM_E_NONE) { 652 if ((rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, 653 &index[num_found], &ment, &ment, 0)) == BCM_E_NONE) { 654 mem[num_found] = MPLS_ENTRYm; 655 num_found++; 656 } 657 } 658 } 659 660 #ifdef BCM_KATANA2_SUPPORT 661 if (soc_feature(unit, soc_feature_mpls_frr_lookup)) { 662 if ((!num_found && (object == bcmStatObjectIngMplsFrrLabel)) || 663 (object == bcmStatObjectMaxValue)) { 664 rv = _bcm_tr3_mpls_tunnel_switch_frr_get(unit, 665 &mpls_tunnel_switch, &index[num_found]); 666 if (rv == BCM_E_NONE) { 667 mem[num_found] = L3_TUNNELm; 668 num_found++; 669 } 670 } 671 } 672 #endif 673 bcm_tr_mpls_unlock(unit); 674 } 675 676 if (num_found && (rv == BCM_E_NOT_FOUND)) { 677 rv = BCM_E_NONE; 678 } 679 680 for (i = 0; i < num_found; i++) { 681 table_info[*num_of_tables].table = mem[i]; 682 table_info[*num_of_tables].index = index[i]; 683 table_info[*num_of_tables].direction = bcmStatFlexDirectionIngress; 684 (*num_of_tables)++; 685 } 686 687 return rv; 688 } 689 690 /* 691 * Function: 692 * _bcm_kt_egress_object_p2mp_set 693 * Purpose: 694 * Set P2MP entry type within Egress Object entry 695 * Parameters: 696 * unit - Device Number 697 * nh_index - Next Hop Index 698 * flag - Indicates SWAP or PHP 699 * value - Value to set 700 * Returns: 701 * BCM_E_XXX 702 */ 703 704 int 705 _bcm_kt_egress_object_p2mp_set(int unit, bcm_multicast_t mc_group, int flag, uint32 value) 706 { 707 int rv=BCM_E_UNAVAIL; 708 egr_l3_next_hop_entry_t egr_nh; 709 int num_encap_id=0, num_sub_encap_id = 0, num_total_encap_id = 0; 710 bcm_if_t *encap_id_array = NULL; 711 bcm_if_t *sub_encap_id_array = NULL; 712 bcm_if_t encap_id; 713 int *q_array = NULL; 714 int i; 715 int nh_index; 716 int if_max = BCM_MULTICAST_PORT_MAX; 717 718 719 /* Get the number of encap IDs of the multicast group */ 720 rv = bcm_esw_multicast_egress_get(unit, mc_group, 0, 721 NULL, NULL, &num_encap_id); 722 if (rv < 0) { 723 goto cleanup; 724 } 725 726 if (num_encap_id != 0) { 727 encap_id_array = sal_alloc(sizeof(bcm_if_t) * num_encap_id, 728 "encap_id_array"); 729 if (NULL == encap_id_array) { 730 rv = BCM_E_MEMORY; 731 goto cleanup; 732 } 733 sal_memset(encap_id_array, 0, sizeof(bcm_if_t) * num_encap_id); 734 735 /* Get all the encap IDs of the multicast group */ 736 rv = bcm_esw_multicast_egress_get(unit, mc_group, num_encap_id, 737 NULL, encap_id_array, &num_encap_id); 738 if (rv < 0) { 739 goto cleanup; 740 } 741 } 742 743 q_array = sal_alloc(if_max * sizeof(bcm_if_t), 744 "mcast q array"); 745 if (q_array == NULL) { 746 rv = BCM_E_MEMORY; 747 goto cleanup; 748 } 749 750 sub_encap_id_array = sal_alloc(if_max * sizeof(bcm_if_t), 751 "mcast encap array"); 752 if (sub_encap_id_array == NULL) { 753 rv = BCM_E_MEMORY; 754 goto cleanup; 755 } 756 757 758 sal_memset(sub_encap_id_array, 0, sizeof(bcm_if_t) * if_max); 759 /* Get the number of subscriber encap IDs of the multicast group */ 760 rv = bcm_esw_multicast_egress_subscriber_get(unit, mc_group, (if_max - 1), 761 NULL, sub_encap_id_array, q_array, &num_sub_encap_id); 762 if (rv < 0) { 763 goto cleanup; 764 } 765 766 num_total_encap_id = num_encap_id + num_sub_encap_id; 767 768 /* Convert encap IDs to next hop indices */ 769 770 for (i = 0; i < num_total_encap_id; i++) { 771 encap_id = (i < num_encap_id) ? encap_id_array[i] : 772 sub_encap_id_array[(i - num_encap_id)]; 773 if (BCM_IF_INVALID != (uint32)encap_id) { 774 nh_index = encap_id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 775 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, 776 MEM_BLOCK_ANY, nh_index, &egr_nh); 777 if (rv < 0) { 778 goto cleanup; 779 } 780 781 switch (flag) { 782 case BCM_MPLS_SWITCH_ACTION_SWAP: 783 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 784 MPLS__LABEL_ACTION_SWAPf, value); 785 break; 786 787 case BCM_MPLS_SWITCH_ACTION_PHP: 788 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 789 MPLS__LABEL_ACTION_PHPf, value); 790 break; 791 792 default: 793 break; 794 } 795 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 796 MEM_BLOCK_ALL, nh_index, &egr_nh); 797 if (rv < 0) { 798 goto cleanup; 799 } 800 } 801 } 802 803 cleanup: 804 if (sub_encap_id_array) { 805 sal_free(sub_encap_id_array); 806 } 807 if (q_array) { 808 sal_free(q_array); 809 } 810 if (encap_id_array) { 811 sal_free(encap_id_array); 812 } 813 814 return rv; 815 } 816 817 /* 818 * Function: 819 * _bcm_kt_mpls_process_swap_label_action 820 * Purpose: 821 * Process tunnel_switch.action = SWAP 822 * Parameters: 823 * unit - Device Number 824 * info - Label (switch) information 825 * Returns: 826 * BCM_E_XXX 827 */ 828 829 int 830 _bcm_kt_mpls_process_swap_label_action(int unit, bcm_mpls_tunnel_switch_t *info, 831 int tunnel_switch_update, 832 int forwarding_field_type, 833 int *nh_index, 834 mpls_entry_entry_t *ment ) 835 { 836 int rv = BCM_E_NONE; 837 uint32 mpath_flag=0; 838 int mc_index = -1; 839 840 if (info->flags & BCM_MPLS_SWITCH_P2MP) { 841 if ((tunnel_switch_update == 1) && 842 (forwarding_field_type == _BCM_MPLS_FORWARD_MULTICAST_GROUP) ) { 843 /* Case of Leaf_LSR + Branch_LSR => BUD_LSR */ 844 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf, 845 0x0); /* INVALID */ 846 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf, 847 0x3); /* SWAP */ 848 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_VALIDf, 849 0x1); 850 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_IF_BOSf, 851 0x2); /*POP_USE_L3_IIF */ 852 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_IF_NOT_BOSf, 853 0x0); /* INVALID */ 854 if (_BCM_MULTICAST_IS_SET(info->mc_group)) { 855 mc_index = _BCM_MULTICAST_ID_GET(info->mc_group); 856 soc_MPLS_ENTRYm_field32_set(unit, ment, FORWARDING_FIELDf, 857 mc_index); 858 } else { 859 return BCM_E_PARAM; 860 } 861 soc_MPLS_ENTRYm_field32_set(unit, ment, FORWARDING_FIELD_TYPEf, 862 _BCM_MPLS_FORWARD_MULTICAST_GROUP); 863 rv = _bcm_kt_mpls_p2mp_loopback_enable(unit); 864 BCM_IF_ERROR_RETURN(rv); 865 } else { 866 /* Case of P2MP BRANCH_LSR */ 867 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf, 868 0x0); /* INVALID */ 869 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf, 870 0x3); /* SWAP NHI */ 871 if (_BCM_MULTICAST_IS_SET(info->mc_group)) { 872 mc_index = _BCM_MULTICAST_ID_GET(info->mc_group); 873 soc_MPLS_ENTRYm_field32_set(unit, ment, FORWARDING_FIELDf, 874 mc_index); 875 } else { 876 return BCM_E_PARAM; 877 } 878 soc_MPLS_ENTRYm_field32_set(unit, ment, FORWARDING_FIELD_TYPEf, 879 _BCM_MPLS_FORWARD_MULTICAST_GROUP); 880 } 881 rv = _bcm_kt_egress_object_p2mp_set(unit, info->mc_group, 882 BCM_MPLS_SWITCH_ACTION_SWAP, 0x1); 883 } else { 884 885 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, info->egress_if)) { 886 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, info->egress_if)) { 887 return BCM_E_PARAM; 888 } 889 } 890 891 /* Case of LSR */ 892 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf, 893 0x3); /* SWAP_NHI */ 894 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf, 895 0x3); /* SWAP NHI */ 896 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->egress_label.label)) { 897 rv = bcm_tr_mpls_l3_nh_info_add(unit, info, nh_index); 898 if (rv < 0) { 899 return rv; 900 } 901 soc_MPLS_ENTRYm_field32_set(unit, ment, NEXT_HOP_INDEXf, *nh_index); 902 soc_MPLS_ENTRYm_field32_set(unit, ment, FORWARDING_FIELD_TYPEf, 903 _BCM_MPLS_FORWARD_NEXT_HOP); 904 } else { 905 rv = bcm_xgs3_get_nh_from_egress_object(unit, info->egress_if, 906 &mpath_flag, 1, nh_index); 907 if (rv < 0) { 908 return rv; 909 } 910 if (mpath_flag == BCM_L3_MULTIPATH) { 911 soc_MPLS_ENTRYm_field32_set(unit, ment, ECMP_PTRf, *nh_index); 912 soc_MPLS_ENTRYm_field32_set(unit, ment, FORWARDING_FIELD_TYPEf, 913 _BCM_MPLS_FORWARD_ECMP_GROUP); 914 } else { 915 soc_MPLS_ENTRYm_field32_set(unit, ment, NEXT_HOP_INDEXf, *nh_index); 916 soc_MPLS_ENTRYm_field32_set(unit, ment, FORWARDING_FIELD_TYPEf, 917 _BCM_MPLS_FORWARD_NEXT_HOP); 918 } 919 } 920 } 921 return rv; 922 } 923 924 925 /* 926 * Function: 927 * _bcm_kt_mpls_process_pop_label_action 928 * Purpose: 929 * Process tunnel_switch.action = SWAP 930 * Parameters: 931 * unit - Device Number 932 * info - Label (switch) information 933 * Returns: 934 * BCM_E_XXX 935 */ 936 937 int 938 _bcm_kt_mpls_process_pop_label_action(int unit, bcm_mpls_tunnel_switch_t *info, 939 int tunnel_switch_update, 940 int forwarding_field_type, 941 int old_action, 942 mpls_entry_entry_t *ment ) 943 { 944 int rv = BCM_E_NONE; 945 int vrf=-1, mode=-1; 946 947 if (_BCM_MPLS_VPN_IS_L3(info->vpn)) { 948 _BCM_MPLS_VPN_GET(vrf, _BCM_MPLS_VPN_TYPE_L3, info->vpn); 949 950 if (!bcm_tr_mpls_vrf_used_get(unit, vrf)) { 951 return BCM_E_PARAM; 952 } 953 954 /* Check L3 Ingress Interface mode. */ 955 mode = 0; 956 rv = bcm_xgs3_l3_ingress_mode_get(unit, &mode); 957 BCM_IF_ERROR_RETURN(rv); 958 } 959 960 if (info->flags & BCM_MPLS_SWITCH_P2MP) { 961 if ((tunnel_switch_update == 1) && 962 (forwarding_field_type == _BCM_MPLS_FORWARD_MULTICAST_GROUP) ) { 963 /* Case of Branch_LSR + Leaf_LSR => BUD_LSR */ 964 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf, 965 0x0); /* INVALID */ 966 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf, 967 old_action); /* SWAP OR PHP */ 968 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_VALIDf, 969 0x1); 970 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_IF_BOSf, 971 0x2); /*POP_USE_L3_IIF */ 972 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_IF_NOT_BOSf, 973 0x0); /* INVALID */ 974 if (!mode) { 975 soc_MPLS_ENTRYm_field32_set(unit, ment, L3_IIF_2f, 976 _BCM_TR_MPLS_L3_IIF_BASE + vrf); 977 } else { 978 soc_MPLS_ENTRYm_field32_set(unit, ment, L3_IIF_2f, info->ingress_if); 979 } 980 rv = _bcm_kt_mpls_p2mp_loopback_enable(unit); 981 } else { 982 /* Case of LEAF_LSR */ 983 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf, 984 0x0); /* INVALID */ 985 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf, 986 0x2); /* L3_IIF */ 987 if (!mode) { 988 soc_MPLS_ENTRYm_field32_set(unit, ment, L3_IIFf, 989 _BCM_TR_MPLS_L3_IIF_BASE + vrf); 990 } else { 991 soc_MPLS_ENTRYm_field32_set(unit, ment, L3_IIFf, info->ingress_if); 992 } 993 } 994 } else { 995 /* Case of LSR */ 996 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf, 997 0x1); /* POP */ 998 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf, 999 0x2); /* L3_IIF */ 1000 if (!mode) { 1001 _bcm_l3_ingress_intf_t iif; 1002 sal_memset(&iif, 0, sizeof(_bcm_l3_ingress_intf_t)); 1003 iif.intf_id = _BCM_TR_MPLS_L3_IIF_BASE + vrf; 1004 rv = _bcm_tr_l3_ingress_interface_get(unit, NULL, &iif); 1005 if (BCM_FAILURE(rv)) { 1006 return rv; 1007 } 1008 iif.vrf = vrf; 1009 rv = _bcm_tr_l3_ingress_interface_set(unit, &iif, NULL, NULL); 1010 if (BCM_FAILURE(rv)) { 1011 return rv; 1012 } 1013 1014 soc_MPLS_ENTRYm_field32_set(unit, ment, L3_IIFf, 1015 _BCM_TR_MPLS_L3_IIF_BASE + vrf); 1016 } else { 1017 soc_MPLS_ENTRYm_field32_set(unit, ment, L3_IIFf, info->ingress_if); 1018 } 1019 } 1020 return rv; 1021 } 1022 1023 1024 /* 1025 * Function: 1026 * _bcm_kt_mpls_process_php_label_action 1027 * Purpose: 1028 * Process tunnel_switch.action = PHP 1029 * Parameters: 1030 * unit - Device Number 1031 * info - Label (switch) information 1032 * Returns: 1033 * BCM_E_XXX 1034 */ 1035 1036 int 1037 _bcm_kt_mpls_process_php_label_action(int unit, bcm_mpls_tunnel_switch_t *info, 1038 int tunnel_switch_update, 1039 int forwarding_field_type, 1040 int *nh_index, 1041 mpls_entry_entry_t *ment ) 1042 { 1043 int rv = BCM_E_NONE; 1044 uint32 mpath_flag=0; 1045 int mc_index=-1; 1046 1047 1048 if (info->flags & BCM_MPLS_SWITCH_P2MP) { 1049 if ((tunnel_switch_update == 1) && 1050 (forwarding_field_type == _BCM_MPLS_FORWARD_MULTICAST_GROUP) ) { 1051 /* Case of Leaf_LSR + Branch_LSR => BUD_LSR */ 1052 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf, 1053 0x0); /* INVALID */ 1054 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf, 1055 0x4); /* PHP */ 1056 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_VALIDf, 1057 0x1); 1058 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_IF_BOSf, 1059 0x2); /*POP_USE_L3_IIF */ 1060 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_IF_NOT_BOSf, 1061 0x0); /* INVALID */ 1062 if (_BCM_MULTICAST_IS_SET(info->mc_group)) { 1063 mc_index = _BCM_MULTICAST_ID_GET(info->mc_group); 1064 soc_MPLS_ENTRYm_field32_set(unit, ment, FORWARDING_FIELDf, 1065 mc_index); 1066 } else { 1067 return BCM_E_PARAM; 1068 } 1069 soc_MPLS_ENTRYm_field32_set(unit, ment, FORWARDING_FIELD_TYPEf, 1070 _BCM_MPLS_FORWARD_MULTICAST_GROUP); 1071 rv = _bcm_kt_mpls_p2mp_loopback_enable(unit); 1072 BCM_IF_ERROR_RETURN(rv); 1073 } else { 1074 /* Case of P2MP BRANCH_LSR */ 1075 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf, 1076 0x0); /* INVALID */ 1077 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf, 1078 0x4); /* PHP NHI */ 1079 if (_BCM_MULTICAST_IS_SET(info->mc_group)) { 1080 mc_index = _BCM_MULTICAST_ID_GET(info->mc_group); 1081 soc_MPLS_ENTRYm_field32_set(unit, ment, FORWARDING_FIELDf, 1082 mc_index); 1083 } else { 1084 return BCM_E_PARAM; 1085 } 1086 soc_MPLS_ENTRYm_field32_set(unit, ment, FORWARDING_FIELD_TYPEf, 1087 _BCM_MPLS_FORWARD_MULTICAST_GROUP); 1088 } 1089 rv = bcm_xgs3_get_nh_from_egress_object(unit, info->egress_if, 1090 &mpath_flag, 1, nh_index); 1091 if (rv < 0) { 1092 return rv; 1093 } 1094 rv = _bcm_kt_egress_object_p2mp_set(unit, info->mc_group, 1095 BCM_MPLS_SWITCH_ACTION_PHP, 0x1); 1096 1097 } else { 1098 1099 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, info->egress_if)) { 1100 if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, info->egress_if)) { 1101 return BCM_E_PARAM; 1102 } 1103 } 1104 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf, 1105 0x2); /* PHP_NHI */ 1106 soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf, 1107 0x4); /* PHP_NHI */ 1108 /* 1109 * Get egress next-hop index from egress object and 1110 * increment egress object reference count. 1111 */ 1112 1113 BCM_IF_ERROR_RETURN(bcm_xgs3_get_nh_from_egress_object(unit, info->egress_if, 1114 &mpath_flag, 1, nh_index)); 1115 1116 /* Fix: Entry_Type = 1, for PHP Packets with more than 1 Label */ 1117 /* Read the egress next_hop entry pointed by Egress-Object */ 1118 rv = bcm_tr_mpls_egress_entry_modify(unit, *nh_index, mpath_flag, 1); 1119 if (rv < 0 ) { 1120 return rv; 1121 } 1122 if (mpath_flag == BCM_L3_MULTIPATH) { 1123 soc_MPLS_ENTRYm_field32_set(unit, ment, ECMP_PTRf, *nh_index); 1124 soc_MPLS_ENTRYm_field32_set(unit, ment, FORWARDING_FIELD_TYPEf, 1125 _BCM_MPLS_FORWARD_ECMP_GROUP); 1126 } else { 1127 soc_MPLS_ENTRYm_field32_set(unit, ment, NEXT_HOP_INDEXf, *nh_index); 1128 soc_MPLS_ENTRYm_field32_set(unit, ment, FORWARDING_FIELD_TYPEf, 1129 _BCM_MPLS_FORWARD_NEXT_HOP); 1130 } 1131 } 1132 return rv; 1133 } 1134 1135 /* 1136 * Function: 1137 * bcm_mpls_tunnel_switch_add 1138 * Purpose: 1139 * Add an MPLS label entry. 1140 * Parameters: 1141 * unit - Device Number 1142 * info - Label (switch) information 1143 * Returns: 1144 * BCM_E_XXX 1145 */ 1146 int 1147 bcm_kt_mpls_tunnel_switch_add(int unit, bcm_mpls_tunnel_switch_t *info) 1148 { 1149 mpls_entry_entry_t ment; 1150 int mode=0, nh_index = -1, rv, num_pw_term, old_pw_cnt = -1, pw_cnt = -1; 1151 int index, forwarding_field_type=-1, old_action = -1; 1152 int old_nh_index = -1, old_ecmp_index = -1, old_ipmc_index=-1; 1153 int tunnel_switch_update=0; 1154 int ref_count=0; 1155 bcm_if_t egress_if=0; 1156 1157 rv = bcm_xgs3_l3_egress_mode_get(unit, &mode); 1158 BCM_IF_ERROR_RETURN(rv); 1159 if (!mode) { 1160 LOG_INFO(BSL_LS_BCM_L3, 1161 (BSL_META_U(unit, 1162 "L3 egress mode must be set first\n"))); 1163 return BCM_E_DISABLED; 1164 } 1165 1166 /* Check for Port_independent Label mapping */ 1167 if (!BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) { 1168 return BCM_E_PARAM; 1169 } 1170 1171 /* BCM_MPLS_SWITCH_KEEP_TTL flag will work only for swap action and 1172 * it is ineffective for other actions. 1173 */ 1174 if ((info->flags & BCM_MPLS_SWITCH_KEEP_TTL) && 1175 (info->action != BCM_MPLS_SWITCH_ACTION_SWAP)) { 1176 return BCM_E_PARAM; 1177 } 1178 1179 rv = bcm_tr_mpls_port_independent_range (unit, info->label, info->port); 1180 if (rv < 0) { 1181 return rv; 1182 } 1183 #ifdef BCM_KATANA2_SUPPORT 1184 if (SOC_IS_KATANA2(unit)) { 1185 if (info->flags & BCM_MPLS_SWITCH_FRR) { 1186 rv = _bcm_tr3_mpls_tunnel_switch_frr_set(unit, info); 1187 return rv; 1188 } 1189 } 1190 #endif /* BCM_KATANA2_SUPPORT */ 1191 BCM_IF_ERROR_RETURN(_bcm_kt_mpls_entry_set_key(unit, info, &ment)); 1192 1193 /* See if entry already exists */ 1194 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 1195 &ment, &ment, 0); 1196 1197 if (rv == SOC_E_NONE) { 1198 /* Entry exists, save old info */ 1199 tunnel_switch_update = 1; 1200 old_action = soc_MPLS_ENTRYm_field32_get(unit, &ment, MPLS_ACTION_IF_BOSf); 1201 forwarding_field_type = soc_MPLS_ENTRYm_field32_get(unit, &ment, FORWARDING_FIELD_TYPEf); 1202 if ((old_action == 0x3) || (old_action == 0x4)) { 1203 if (forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) { 1204 old_nh_index = soc_MPLS_ENTRYm_field32_get(unit, &ment, NEXT_HOP_INDEXf); 1205 } else if (forwarding_field_type == _BCM_MPLS_FORWARD_ECMP_GROUP) { 1206 old_ecmp_index = soc_MPLS_ENTRYm_field32_get(unit, &ment, ECMP_PTRf); 1207 } else if (forwarding_field_type == _BCM_MPLS_FORWARD_MULTICAST_GROUP) { 1208 old_ipmc_index = soc_MPLS_ENTRYm_field32_get(unit, &ment, FORWARDING_FIELDf); 1209 1210 if (old_ipmc_index) { 1211 } 1212 } 1213 } 1214 if (soc_MPLS_ENTRYm_field32_get(unit, &ment, PW_TERM_NUM_VALIDf)) { 1215 old_pw_cnt = soc_MPLS_ENTRYm_field32_get(unit, &ment, PW_TERM_NUMf); 1216 } 1217 } else if (rv != SOC_E_NOT_FOUND) { 1218 return rv; 1219 } 1220 1221 switch(info->action) { 1222 case BCM_MPLS_SWITCH_ACTION_SWAP: 1223 rv = _bcm_kt_mpls_process_swap_label_action(unit, info, 1224 tunnel_switch_update, forwarding_field_type, &nh_index, &ment ); 1225 if (rv < 0) { 1226 goto cleanup; 1227 } 1228 break; 1229 1230 case BCM_MPLS_SWITCH_ACTION_POP: 1231 rv = _bcm_kt_mpls_process_pop_label_action(unit, info, 1232 tunnel_switch_update, forwarding_field_type, old_action, &ment ); 1233 if (rv < 0) { 1234 goto cleanup; 1235 } 1236 break; 1237 1238 case BCM_MPLS_SWITCH_ACTION_PHP: 1239 rv = _bcm_kt_mpls_process_php_label_action(unit, info, 1240 tunnel_switch_update, forwarding_field_type, &nh_index, &ment ); 1241 if (rv < 0) { 1242 goto cleanup; 1243 } 1244 break; 1245 1246 default: 1247 return BCM_E_PARAM; 1248 break; 1249 } 1250 1251 1252 soc_MPLS_ENTRYm_field32_set(unit, &ment, V4_ENABLEf, 1); 1253 soc_MPLS_ENTRYm_field32_set(unit, &ment, V6_ENABLEf, 1); 1254 if (info->flags & BCM_MPLS_SWITCH_INNER_TTL) { 1255 if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) { 1256 rv = BCM_E_PARAM; 1257 goto cleanup; 1258 } 1259 soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_TTLf, 0); 1260 } else { 1261 soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_TTLf, 1); 1262 } 1263 if (info->flags & BCM_MPLS_SWITCH_INNER_EXP) { 1264 if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) { 1265 rv = BCM_E_PARAM; 1266 goto cleanup; 1267 } 1268 soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_EXP_FOR_INNERf, 0); 1269 } else { 1270 /* For SWAP, Do-not PUSH EXP */ 1271 if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) { 1272 soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_EXP_FOR_INNERf, 0); 1273 } else { 1274 soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_EXP_FOR_INNERf, 1); 1275 } 1276 } 1277 1278 (void) bcm_tr_mpls_entry_internal_qos_set(unit, NULL, info, &ment); 1279 1280 if ((info->flags & BCM_MPLS_SWITCH_COUNTED)) { 1281 if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) { 1282 if (old_pw_cnt == -1) { 1283 num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_COUNTERSm); 1284 for (pw_cnt = 0; pw_cnt < num_pw_term; pw_cnt++) { 1285 if (! bcm_tr_mpls_pw_used_get(unit, pw_cnt)) { 1286 break; 1287 } 1288 } 1289 if (pw_cnt == num_pw_term) { 1290 rv = BCM_E_RESOURCE; 1291 goto cleanup; 1292 } 1293 (void) bcm_tr_mpls_pw_used_set(unit, pw_cnt); 1294 soc_MPLS_ENTRYm_field32_set(unit, &ment, PW_TERM_NUMf, pw_cnt); 1295 soc_MPLS_ENTRYm_field32_set(unit, &ment, PW_TERM_NUM_VALIDf, 1); 1296 } 1297 } 1298 } 1299 1300 if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, MPLS__DROP_DATA_ENABLEf)) { 1301 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__DROP_DATA_ENABLEf, 1302 (info->flags & BCM_MPLS_SWITCH_DROP) ? 1 : 0); 1303 } 1304 1305 if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, MPLS__RX_PROT_GROUPf)) { 1306 if ((info->failover_id >= 0) && 1307 (info->failover_id <= soc_mem_index_max(unit, RX_PROT_GROUP_TABLEm))) { 1308 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__RX_PROT_GROUPf, 1309 info->failover_id); 1310 } 1311 } 1312 1313 if (!tunnel_switch_update) { 1314 rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &ment); 1315 } else { 1316 rv = soc_mem_write(unit, MPLS_ENTRYm, 1317 MEM_BLOCK_ALL, index, 1318 &ment); 1319 } 1320 1321 if (rv < 0) { 1322 goto cleanup; 1323 } 1324 1325 if ((tunnel_switch_update) && 1326 (forwarding_field_type != _BCM_MPLS_FORWARD_MULTICAST_GROUP)) { 1327 /* Clean up old next-hop and counter info if entry was replaced */ 1328 if ((old_pw_cnt != -1) && !(info->flags & BCM_MPLS_SWITCH_COUNTED)) { 1329 (void) bcm_tr_mpls_pw_used_clear(unit, old_pw_cnt); 1330 } 1331 if (old_action == 0x3) { /* SWAP_NHI */ 1332 /* Check if tunnel_switch.egress_label mode is being used */ 1333 if (forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) { 1334 rv = bcm_tr_mpls_get_vp_nh (unit, (bcm_if_t) old_nh_index, &egress_if); 1335 if (rv == BCM_E_NONE) { 1336 rv = bcm_tr_mpls_l3_nh_info_delete(unit, old_nh_index); 1337 } else { 1338 /* Decrement next-hop Reference count */ 1339 rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count, old_nh_index); 1340 } 1341 } else { 1342 if (forwarding_field_type == _BCM_MPLS_FORWARD_ECMP_GROUP) { 1343 rv = bcm_xgs3_ecmp_group_del(unit, old_ecmp_index, 0); 1344 } 1345 } 1346 } else if (old_action == 0x4) {/* PHP_NHI */ 1347 /* L3_NHI */ 1348 if (forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) { 1349 rv = bcm_xgs3_nh_del(unit, 0, old_nh_index); 1350 } else if (forwarding_field_type == _BCM_MPLS_FORWARD_ECMP_GROUP) { 1351 rv = bcm_xgs3_ecmp_group_del(unit, old_ecmp_index, 0); 1352 } 1353 } 1354 } 1355 if (rv < 0) { 1356 goto cleanup; 1357 } 1358 1359 #ifdef BCM_WARM_BOOT_SUPPORT 1360 SOC_CONTROL_LOCK(unit); 1361 SOC_CONTROL(unit)->scache_dirty = 1; 1362 SOC_CONTROL_UNLOCK(unit); 1363 #endif 1364 1365 return rv; 1366 1367 cleanup: 1368 if (pw_cnt != -1) { 1369 (void) bcm_tr_mpls_pw_used_clear(unit, pw_cnt); 1370 } 1371 if (nh_index != -1) { 1372 if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) { 1373 if (BCM_XGS3_L3_MPLS_LBL_VALID(info->egress_label.label) || 1374 (info->action == BCM_MPLS_SWITCH_ACTION_PHP)) { 1375 (void) bcm_tr_mpls_l3_nh_info_delete(unit, nh_index); 1376 } 1377 } else if (info->action == BCM_MPLS_SWITCH_ACTION_PHP) { 1378 (void) bcm_xgs3_nh_del(unit, 0, nh_index); 1379 } 1380 } 1381 return rv; 1382 } 1383 1384 /* 1385 * Function: 1386 * bcm_mpls_tunnel_switch_delete 1387 * Purpose: 1388 * Delete an MPLS label entry. 1389 * Parameters: 1390 * unit - Device Number 1391 * info - Label (switch) information 1392 * Returns: 1393 * BCM_E_XXX 1394 */ 1395 int 1396 bcm_kt_mpls_tunnel_switch_delete(int unit, bcm_mpls_tunnel_switch_t *info) 1397 { 1398 int rv, index; 1399 mpls_entry_entry_t ment; 1400 #ifdef BCM_KATANA2_SUPPORT 1401 if ((SOC_IS_KATANA2(unit)) && (info->flags & BCM_MPLS_SWITCH_FRR)) { 1402 rv = _bcm_tr3_mpls_tunnel_switch_frr_delete(unit, info); 1403 } else 1404 #endif /*BCM_KATANA2_SUPPORT*/ 1405 { 1406 rv = _bcm_kt_mpls_entry_set_key(unit, info, &ment); 1407 BCM_IF_ERROR_RETURN(rv); 1408 1409 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 1410 &ment, &ment, 0); 1411 if (rv < 0) { 1412 return rv; 1413 } 1414 rv = _bcm_kt_mpls_entry_delete(unit, &ment, info, index); 1415 } 1416 #ifdef BCM_WARM_BOOT_SUPPORT 1417 SOC_CONTROL_LOCK(unit); 1418 SOC_CONTROL(unit)->scache_dirty = 1; 1419 SOC_CONTROL_UNLOCK(unit); 1420 #endif 1421 1422 return rv; 1423 } 1424 1425 /* 1426 * Function: 1427 * bcm_mpls_tunnel_switch_delete_all 1428 * Purpose: 1429 * Delete all MPLS label entries. 1430 * Parameters: 1431 * unit - Device Number 1432 * Returns: 1433 * BCM_E_XXX 1434 */ 1435 int 1436 bcm_kt_mpls_tunnel_switch_delete_all(int unit) 1437 { 1438 int rv, i, j, num_entries; 1439 mpls_entry_entry_t ment; 1440 bcm_mpls_tunnel_switch_t info; 1441 soc_tunnel_term_t tnl_entry; 1442 int num_del = 0; 1443 1444 1445 1446 num_entries = soc_mem_index_count(unit, MPLS_ENTRYm); 1447 for (i = 0; i < num_entries; i++) { 1448 1449 rv = READ_MPLS_ENTRYm(unit, MEM_BLOCK_ANY, i, &ment); 1450 if (rv < 0) { 1451 return rv; 1452 } 1453 if (!soc_MPLS_ENTRYm_field32_get(unit, &ment, VALIDf)) { 1454 continue; 1455 } 1456 if (soc_MPLS_ENTRYm_field32_get(unit, &ment, 1457 MPLS_ACTION_IF_BOSf) == 0x1) { 1458 /* L2_SVP */ 1459 continue; 1460 } 1461 sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t)); 1462 1463 /* Delete entries by default only once unless 1464 * its a P2MP entry with second pass action valid 1465 */ 1466 num_del = 1; 1467 1468 rv = _bcm_kt_mpls_entry_get_key(unit, &ment, &info); 1469 if (rv < 0) { 1470 return rv; 1471 } 1472 rv = _bcm_kt_mpls_entry_get_data(unit, &ment, &info); 1473 if (rv < 0) { 1474 return rv; 1475 } 1476 1477 /* Check if entry is a P2MP entry with second pass action valid */ 1478 if ((soc_MPLS_ENTRYm_field32_get(unit, &ment, FORWARDING_FIELD_TYPEf)) 1479 == _BCM_MPLS_FORWARD_MULTICAST_GROUP) { 1480 if(soc_MPLS_ENTRYm_field32_get(unit, &ment, 1481 MPLS_SECOND_PASS_ACTION_VALIDf)) { 1482 num_del = 2; 1483 } 1484 } 1485 1486 for (j=0 ; j < num_del; j++) { 1487 rv = _bcm_kt_mpls_entry_delete(unit, &ment, &info, i ); 1488 if (rv < 0) { 1489 return rv; 1490 } 1491 } 1492 } 1493 1494 num_entries = soc_mem_index_count(unit, L3_TUNNELm); 1495 for (i = 0; i < num_entries; i++) { 1496 sal_memset(&tnl_entry, 0, sizeof(tnl_entry)); 1497 rv = READ_L3_TUNNELm(unit, MEM_BLOCK_ANY, i, (uint32 *)&tnl_entry.entry_arr[0]); 1498 if (rv < 0) { 1499 return rv; 1500 } 1501 if (!soc_L3_TUNNELm_field32_get(unit, &tnl_entry, VALIDf)) { 1502 continue; 1503 } 1504 if (0x2 != soc_L3_TUNNELm_field32_get(unit, &tnl_entry, KEY_TYPEf)) { 1505 continue; 1506 } 1507 1508 rv = soc_tunnel_term_delete(unit, &tnl_entry); 1509 if (rv < 0) { 1510 return rv; 1511 } 1512 1513 /*_soc_tunnel_term_slot_free() api moves last entry to 1514 * deleted entry position using _soc_tunnel_term_entry_shift(). 1515 * Therefore adding this index change to support delete all*/ 1516 i--; 1517 } 1518 1519 return BCM_E_NONE; 1520 } 1521 1522 /* 1523 * Function: 1524 * bcm_mpls_tunnel_switch_get 1525 * Purpose: 1526 * Get an MPLS label entry. 1527 * Parameters: 1528 * unit - Device Number 1529 * info - Label (switch) information 1530 * Returns: 1531 * BCM_E_XXX 1532 */ 1533 int 1534 bcm_kt_mpls_tunnel_switch_get(int unit, bcm_mpls_tunnel_switch_t *info) 1535 { 1536 int rv, index; 1537 mpls_entry_entry_t ment; 1538 #ifdef BCM_KATANA2_SUPPORT 1539 if ((SOC_IS_KATANA2(unit)) && (info->flags & BCM_MPLS_SWITCH_FRR)) { 1540 rv = _bcm_tr3_mpls_tunnel_switch_frr_get(unit, info, &index); 1541 } else 1542 #endif /*BCM_KATANA2_SUPPORT*/ 1543 { 1544 rv = _bcm_kt_mpls_entry_set_key(unit, info, &ment); 1545 1546 1547 BCM_IF_ERROR_RETURN(rv); 1548 1549 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 1550 &ment, &ment, 0); 1551 1552 if (rv < 0) { 1553 return rv; 1554 } 1555 rv = _bcm_kt_mpls_entry_get_data(unit, &ment, info); 1556 } 1557 return rv; 1558 } 1559 1560 /* 1561 * Function: 1562 * bcm_mpls_tunnel_switch_traverse 1563 * Purpose: 1564 * Traverse all valid MPLS label entries an call the 1565 * supplied callback routine. 1566 * Parameters: 1567 * unit - Device Number 1568 * cb - User callback function, called once per MPLS entry. 1569 * user_data - cookie 1570 * Returns: 1571 * BCM_E_XXX 1572 */ 1573 int 1574 bcm_kt_mpls_tunnel_switch_traverse(int unit, 1575 bcm_mpls_tunnel_switch_traverse_cb cb, 1576 void *user_data) 1577 { 1578 int rv, i, num_entries; 1579 mpls_entry_entry_t ment; 1580 bcm_mpls_tunnel_switch_t info; 1581 #ifdef BCM_KATANA2_SUPPORT 1582 soc_tunnel_term_t tnl_entry; 1583 uint32 key_type=0; 1584 #endif 1585 1586 1587 num_entries = soc_mem_index_count(unit, MPLS_ENTRYm); 1588 for (i = 0; i < num_entries; i++) { 1589 BCM_IF_ERROR_RETURN (READ_MPLS_ENTRYm(unit, MEM_BLOCK_ANY, i, &ment)); 1590 if (!soc_MPLS_ENTRYm_field32_get(unit, &ment, VALIDf)) { 1591 continue; 1592 } 1593 if (soc_MPLS_ENTRYm_field32_get(unit, &ment, 1594 MPLS_ACTION_IF_BOSf) == 0x1) { 1595 /* L2_SVP */ 1596 continue; 1597 } 1598 sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t)); 1599 rv = _bcm_kt_mpls_entry_get_key(unit, &ment, &info); 1600 if (rv < 0) { 1601 return rv; 1602 } 1603 rv = _bcm_kt_mpls_entry_get_data(unit, &ment, &info); 1604 if (rv < 0) { 1605 return rv; 1606 } 1607 rv = cb(unit, &info, user_data); 1608 #ifdef BCM_CB_ABORT_ON_ERR 1609 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 1610 return rv; 1611 } 1612 #endif 1613 } 1614 #ifdef BCM_KATANA2_SUPPORT 1615 if ((SOC_IS_KATANA2(unit))) { 1616 1617 /* traverse L3_TUNNEL entries */ 1618 num_entries = soc_mem_index_count(unit, L3_TUNNELm); 1619 1620 for (i = 0; i < num_entries; i++) { 1621 1622 sal_memset(&tnl_entry, 0, sizeof(tnl_entry)); 1623 BCM_IF_ERROR_RETURN 1624 (READ_L3_TUNNELm(unit, MEM_BLOCK_ANY, i, (uint32 *)&tnl_entry.entry_arr[0])); 1625 1626 if (!soc_L3_TUNNELm_field32_get (unit, &tnl_entry, VALIDf)) { 1627 continue; 1628 } 1629 1630 /* Check for MPLS entry key */ 1631 key_type = soc_L3_TUNNELm_field32_get(unit, &tnl_entry, KEY_TYPEf); 1632 if (key_type != 0x2) { 1633 continue; 1634 } 1635 1636 sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t)); 1637 rv = _bcm_tr3_mpls_tunnel_switch_frr_entry_key_get (unit, &tnl_entry, &info); 1638 if (rv < 0) { 1639 return rv; 1640 } 1641 1642 (void) _bcm_tr3_mpls_tunnel_switch_frr_parse(unit, &tnl_entry, &info); 1643 1644 rv = cb(unit, &info, user_data); 1645 #ifdef BCM_CB_ABORT_ON_ERR 1646 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 1647 return rv; 1648 } 1649 #endif 1650 } 1651 } 1652 #endif /*BCM_KATANA2_SUPPORT*/ 1653 1654 return BCM_E_NONE; 1655 } 1656 1657 /* 1658 * Function: 1659 * bcm_kt_mpls_port_stat_attach 1660 * Description: 1661 * Attach counters entries to the given mpls gport and vpn 1662 * 1663 * Parameters: 1664 * unit - (IN) unit number 1665 * vpn - (IN) VPN Id 1666 * port - (IN) MPLS GPORT ID 1667 * stat_counter_id - (IN) Stat Counter ID. 1668 * 1669 * Return Value: 1670 * BCM_E_XXX 1671 * Notes: 1672 */ 1673 bcm_error_t bcm_kt_mpls_port_stat_attach( 1674 int unit, 1675 bcm_vpn_t vpn, 1676 bcm_gport_t port, 1677 uint32 stat_counter_id) 1678 { 1679 soc_mem_t table=0; 1680 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 1681 uint32 pool_number=0; 1682 uint32 base_index=0; 1683 bcm_stat_flex_mode_t offset_mode=0; 1684 bcm_stat_object_t object=bcmStatObjectIngPort; 1685 bcm_stat_group_mode_t group_mode= bcmStatGroupModeSingle; 1686 uint32 count=0; 1687 uint32 actual_num_tables=0; 1688 uint32 num_of_tables=0; 1689 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 1690 1691 _bcm_esw_stat_get_counter_id_info( 1692 unit, 1693 stat_counter_id, 1694 &group_mode,&object,&offset_mode,&pool_number,&base_index); 1695 BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_object(unit,object,&direction)); 1696 BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit,group_mode)); 1697 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_table_info( 1698 unit,object,1,&actual_num_tables,&table,&direction)); 1699 1700 BCM_IF_ERROR_RETURN(_bcm_kt_mpls_port_stat_get_table_info( 1701 unit, vpn,port,&num_of_tables,&table_info[0])); 1702 for (count=0; count < num_of_tables ; count++) { 1703 if ((table_info[count].direction == direction) && 1704 (table_info[count].table == table) ) { 1705 if (direction == bcmStatFlexDirectionIngress) { 1706 return _bcm_esw_stat_flex_attach_ingress_table_counters( 1707 unit, 1708 table_info[count].table, 1709 table_info[count].index, 1710 offset_mode, 1711 base_index, 1712 pool_number); 1713 } else { 1714 return _bcm_esw_stat_flex_attach_egress_table_counters( 1715 unit, 1716 table_info[count].table, 1717 table_info[count].index, 1718 0, 1719 offset_mode, 1720 base_index, 1721 pool_number); 1722 } 1723 } 1724 } 1725 return BCM_E_UNAVAIL; 1726 } 1727 /* 1728 * Function: 1729 * bcm_kt_mpls_port_stat_detach 1730 * Description: 1731 * Detach counters entries to the given mpls port and vpn 1732 * 1733 * Parameters: 1734 * unit - (IN) unit number 1735 * vpn - (IN) VPN Id 1736 * port - (IN) MPLS GPORT ID 1737 * 1738 * Return Value: 1739 * BCM_E_XXX 1740 * Notes: 1741 */ 1742 bcm_error_t bcm_kt_mpls_port_stat_detach( 1743 int unit, 1744 bcm_vpn_t vpn, 1745 bcm_gport_t port) 1746 { 1747 uint32 count=0; 1748 uint32 num_of_tables=0; 1749 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 1750 bcm_error_t rv = BCM_E_NONE; 1751 bcm_error_t err_code[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION] = {BCM_E_NONE}; 1752 1753 BCM_IF_ERROR_RETURN(_bcm_kt_mpls_port_stat_get_table_info( 1754 unit, vpn,port,&num_of_tables,&table_info[0])); 1755 1756 for (count=0; count < num_of_tables ; count++) { 1757 if (table_info[count].direction == bcmStatFlexDirectionIngress) { 1758 rv = _bcm_esw_stat_flex_detach_ingress_table_counters( 1759 unit, table_info[count].table, table_info[count].index); 1760 if (BCM_E_NONE != rv && 1761 BCM_E_NONE == err_code[bcmStatFlexDirectionIngress]) { 1762 err_code[bcmStatFlexDirectionIngress] = rv; 1763 } 1764 } else { 1765 rv = _bcm_esw_stat_flex_detach_egress_table_counters( 1766 unit, 0, table_info[count].table, 1767 table_info[count].index); 1768 if (BCM_E_NONE != rv && 1769 BCM_E_NONE == err_code[bcmStatFlexDirectionEgress]) { 1770 err_code[bcmStatFlexDirectionEgress] = rv; 1771 } 1772 } 1773 } 1774 1775 BCM_STAT_FLEX_DETACH_RETURN(err_code) 1776 } 1777 /* 1778 * Function: 1779 * bcm_kt_mpls_port_stat_counter_get 1780 * Description: 1781 * Get counter statistic values for specific vpn and gport 1782 * if sync_mode is set, sync the sw accumulated count 1783 * with hw count value first, else return sw count. 1784 * 1785 * Parameters: 1786 * unit - (IN) unit number 1787 * sync_mode - if sync sw accumulated count with hw count 1788 * vpn - (IN) VPN Id 1789 * port - (IN) MPLS GPORT ID 1790 * stat - (IN) Type of the counter to retrieve 1791 * I.e. ingress/egress byte/packet) 1792 * num_entries - (IN) Number of counter Entries 1793 * counter_indexes - (IN) Pointer to Counter indexes entries 1794 * counter_values - (OUT) Pointer to counter values 1795 * 1796 * Return Value: 1797 * BCM_E_XXX 1798 * Notes: 1799 */ 1800 bcm_error_t bcm_kt_mpls_port_stat_counter_get( 1801 int unit, 1802 int sync_mode, 1803 bcm_vpn_t vpn, 1804 bcm_gport_t port, 1805 bcm_mpls_stat_t stat, 1806 uint32 num_entries, 1807 uint32 *counter_indexes, 1808 bcm_stat_value_t *counter_values) 1809 { 1810 uint32 table_count=0; 1811 uint32 index_count=0; 1812 uint32 num_of_tables=0; 1813 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 1814 uint32 byte_flag=0; 1815 bcm_stat_flex_table_info_t table_info[ 1816 BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 1817 1818 if ((stat == bcmMplsInBytes) || 1819 (stat == bcmMplsInPkts)) { 1820 direction = bcmStatFlexDirectionIngress; 1821 } else { 1822 direction = bcmStatFlexDirectionEgress; 1823 } 1824 if ((stat == bcmMplsInPkts) || 1825 (stat == bcmMplsOutPkts)) { 1826 byte_flag=0; 1827 } else { 1828 byte_flag=1; 1829 } 1830 1831 BCM_IF_ERROR_RETURN(_bcm_kt_mpls_port_stat_get_table_info( 1832 unit, vpn,port,&num_of_tables,&table_info[0])); 1833 1834 for (table_count=0; table_count < num_of_tables ; table_count++) { 1835 if (table_info[table_count].direction == direction) { 1836 for (index_count=0; index_count < num_entries ; index_count++) { 1837 BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_get( 1838 unit, sync_mode, 1839 table_info[table_count].index, 1840 table_info[table_count].table, 1841 0, 1842 byte_flag, 1843 counter_indexes[index_count], 1844 &counter_values[index_count])); 1845 } 1846 } 1847 } 1848 return BCM_E_NONE; 1849 } 1850 /* 1851 * Function: 1852 * bcm_kt_mpls_port_stat_counter_set 1853 * Description: 1854 * Set counter statistic values for specific vpn and gport 1855 * 1856 * Parameters: 1857 * unit - (IN) unit number 1858 * vpn - (IN) VPN Id 1859 * port - (IN) MPLS GPORT ID 1860 * stat - (IN) Type of the counter to retrieve 1861 * I.e. ingress/egress byte/packet) 1862 * num_entries - (IN) Number of counter Entries 1863 * counter_indexes - (IN) Pointer to Counter indexes entries 1864 * counter_values - (OUT) Pointer to counter values 1865 * 1866 * Return Value: 1867 * BCM_E_XXX 1868 * Notes: 1869 */ 1870 bcm_error_t bcm_kt_mpls_port_stat_counter_set( 1871 int unit, 1872 bcm_vpn_t vpn, 1873 bcm_gport_t port, 1874 bcm_mpls_stat_t stat, 1875 uint32 num_entries, 1876 uint32 *counter_indexes, 1877 bcm_stat_value_t *counter_values) 1878 { 1879 uint32 table_count=0; 1880 uint32 index_count=0; 1881 uint32 num_of_tables=0; 1882 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 1883 uint32 byte_flag=0; 1884 bcm_stat_flex_table_info_t table_info[ 1885 BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 1886 1887 if ((stat == bcmMplsInBytes) || 1888 (stat == bcmMplsInPkts)) { 1889 direction = bcmStatFlexDirectionIngress; 1890 } else { 1891 direction = bcmStatFlexDirectionEgress; 1892 } 1893 if ((stat == bcmMplsInPkts) || 1894 (stat == bcmMplsOutPkts)) { 1895 byte_flag=0; 1896 } else { 1897 byte_flag=1; 1898 } 1899 1900 BCM_IF_ERROR_RETURN(_bcm_kt_mpls_port_stat_get_table_info( 1901 unit, vpn,port,&num_of_tables,&table_info[0])); 1902 1903 for (table_count=0; table_count < num_of_tables ; table_count++) { 1904 if (table_info[table_count].direction == direction) { 1905 for (index_count=0; index_count < num_entries ; index_count++) { 1906 BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_set( 1907 unit, 1908 table_info[table_count].index, 1909 table_info[table_count].table, 1910 0, 1911 byte_flag, 1912 counter_indexes[index_count], 1913 &counter_values[index_count])); 1914 } 1915 } 1916 } 1917 return BCM_E_NONE; 1918 } 1919 /* 1920 * Function: 1921 * bcm_kt_mpls_port_stat_id_get 1922 * Description: 1923 * Get stat counter id associated with specific vpn and gport 1924 * 1925 * Parameters: 1926 * unit - (IN) unit number 1927 * vpn - (IN) VPN Id 1928 * port - (IN) MPLS GPORT ID 1929 * stat - (IN) Type of the counter to retrieve 1930 * I.e. ingress/egress byte/packet) 1931 * Stat_counter_id - (OUT) Stat Counter ID 1932 * 1933 * Return Value: 1934 * BCM_E_XXX 1935 * Notes: 1936 */ 1937 bcm_error_t bcm_kt_mpls_port_stat_id_get( 1938 int unit, 1939 bcm_vpn_t vpn, 1940 bcm_gport_t port, 1941 bcm_mpls_stat_t stat, 1942 uint32 *stat_counter_id) 1943 { 1944 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 1945 uint32 num_of_tables=0; 1946 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 1947 uint32 index=0; 1948 uint32 num_stat_counter_ids=0; 1949 1950 if ((stat == bcmMplsInBytes) || 1951 (stat == bcmMplsInPkts)) { 1952 direction = bcmStatFlexDirectionIngress; 1953 } else { 1954 direction = bcmStatFlexDirectionEgress; 1955 } 1956 BCM_IF_ERROR_RETURN(_bcm_kt_mpls_port_stat_get_table_info( 1957 unit,vpn,port,&num_of_tables,&table_info[0])); 1958 for (index=0; index < num_of_tables ; index++) { 1959 if (table_info[index].direction == direction) 1960 return _bcm_esw_stat_flex_get_counter_id( 1961 unit, 1, &table_info[index], 1962 &num_stat_counter_ids,stat_counter_id); 1963 } 1964 return BCM_E_NOT_FOUND; 1965 } 1966 /* 1967 * Function: 1968 * bcm_kt_mpls_label_stat_attach 1969 * Description: 1970 * Attach counters entries to the given mpls label and gport 1971 * 1972 * Parameters: 1973 * unit - (IN) unit number 1974 * label - (IN) MPLS Label 1975 * port - (IN) MPLS Gport 1976 * stat_counter_id - (IN) Stat Counter ID. 1977 * 1978 * Return Value: 1979 * BCM_E_XXX 1980 * Notes: 1981 */ 1982 bcm_error_t bcm_kt_mpls_label_stat_attach( 1983 int unit, 1984 bcm_mpls_label_t label, 1985 bcm_gport_t port, 1986 uint32 stat_counter_id) 1987 { 1988 soc_mem_t table=0; 1989 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 1990 uint32 pool_number=0; 1991 uint32 base_index=0; 1992 bcm_stat_flex_mode_t offset_mode=0; 1993 bcm_stat_object_t object=bcmStatObjectIngPort; 1994 bcm_stat_group_mode_t group_mode= bcmStatGroupModeSingle; 1995 uint32 count=0; 1996 uint32 actual_num_tables=0; 1997 uint32 num_of_tables=0; 1998 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 1999 2000 2001 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 2002 return BCM_E_PARAM; 2003 } 2004 2005 _bcm_esw_stat_get_counter_id_info( 2006 unit, stat_counter_id, 2007 &group_mode,&object,&offset_mode,&pool_number,&base_index); 2008 BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_object(unit,object,&direction)); 2009 BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit,group_mode)); 2010 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_table_info( 2011 unit,object,1,&actual_num_tables,&table,&direction)); 2012 2013 BCM_IF_ERROR_RETURN(_bcm_kt_mpls_label_stat_get_table_info( 2014 unit, label, port, object, &num_of_tables,&table_info[0])); 2015 for (count=0; count < num_of_tables ; count++) { 2016 if ((table_info[count].direction == direction) && 2017 (table_info[count].table == table) ) { 2018 if (direction == bcmStatFlexDirectionIngress) { 2019 return _bcm_esw_stat_flex_attach_ingress_table_counters( 2020 unit, 2021 table_info[count].table, 2022 table_info[count].index, 2023 offset_mode, 2024 base_index, 2025 pool_number); 2026 } else { 2027 return _bcm_esw_stat_flex_attach_egress_table_counters( 2028 unit, 2029 table_info[count].table, 2030 table_info[count].index, 2031 0, 2032 offset_mode, 2033 base_index, 2034 pool_number); 2035 } 2036 } 2037 } 2038 return BCM_E_NOT_FOUND; 2039 } 2040 /* 2041 * Function: 2042 * bcm_kt_mpls_label_stat_detach 2043 * Description: 2044 * Detach counters entries to the given mpls label and gport 2045 * 2046 * Parameters: 2047 * unit - (IN) unit number 2048 * label - (IN) MPLS Label 2049 * port - (IN) MPLS Gport 2050 * 2051 * Return Value: 2052 * BCM_E_XXX 2053 * Notes: 2054 */ 2055 bcm_error_t bcm_kt_mpls_label_stat_detach( 2056 int unit, 2057 bcm_mpls_label_t label, 2058 bcm_gport_t port) 2059 { 2060 uint32 count=0; 2061 uint32 num_of_tables=0; 2062 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 2063 bcm_error_t rv = BCM_E_NONE; 2064 bcm_error_t err_code[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION] = {BCM_E_NONE}; 2065 2066 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 2067 return BCM_E_PARAM; 2068 } 2069 2070 BCM_IF_ERROR_RETURN(_bcm_kt_mpls_label_stat_get_table_info( 2071 unit, label, port, bcmStatObjectMaxValue, 2072 &num_of_tables,&table_info[0])); 2073 2074 for (count=0; count < num_of_tables ; count++) { 2075 if (table_info[count].direction == bcmStatFlexDirectionIngress) { 2076 rv = _bcm_esw_stat_flex_detach_ingress_table_counters( 2077 unit, table_info[count].table, table_info[count].index); 2078 if (BCM_E_NONE != rv && 2079 BCM_E_NONE == err_code[bcmStatFlexDirectionIngress]) { 2080 err_code[bcmStatFlexDirectionIngress] = rv; 2081 } 2082 } else { 2083 rv = _bcm_esw_stat_flex_detach_egress_table_counters( 2084 unit, 0, table_info[count].table, 2085 table_info[count].index); 2086 if (BCM_E_NONE != rv && 2087 BCM_E_NONE == err_code[bcmStatFlexDirectionEgress]) { 2088 err_code[bcmStatFlexDirectionEgress] = rv; 2089 } 2090 } 2091 } 2092 2093 BCM_STAT_FLEX_DETACH_RETURN(err_code) 2094 } 2095 /* 2096 * Function: 2097 * bcm_kt_mpls_label_stat_counter_get 2098 * Description: 2099 * Get counter statistic values for specific MPLS label and gport 2100 * if sync_mode is set, sync the sw accumulated count 2101 * with hw count value first, else return sw count. 2102 * 2103 * 2104 * Parameters: 2105 * unit - (IN) unit number 2106 * sync_mode - if sync sw accumulated count with hw count 2107 * label - (IN) MPLS Label 2108 * port - (IN) MPLS Gport 2109 * stat - (IN) Type of the counter to retrieve 2110 * I.e. ingress/egress byte/packet) 2111 * num_entries - (IN) Number of counter Entries 2112 * counter_indexes - (IN) Pointer to Counter indexes entries 2113 * counter_values - (OUT) Pointer to counter values 2114 * 2115 * Return Value: 2116 * BCM_E_XXX 2117 * Notes: 2118 */ 2119 bcm_error_t bcm_kt_mpls_label_stat_counter_get( 2120 int unit, 2121 int sync_mode, 2122 bcm_mpls_label_t label, 2123 bcm_gport_t port, 2124 bcm_mpls_stat_t stat, 2125 uint32 num_entries, 2126 uint32 *counter_indexes, 2127 bcm_stat_value_t *counter_values) 2128 { 2129 uint32 table_count=0; 2130 uint32 index_count=0; 2131 uint32 num_of_tables=0; 2132 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 2133 uint32 byte_flag=0; 2134 bcm_stat_flex_table_info_t table_info[ 2135 BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 2136 2137 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 2138 return BCM_E_PARAM; 2139 } 2140 2141 if ((stat == bcmMplsInBytes) || 2142 (stat == bcmMplsInPkts)) { 2143 direction = bcmStatFlexDirectionIngress; 2144 } else { 2145 direction = bcmStatFlexDirectionEgress; 2146 } 2147 if ((stat == bcmMplsInPkts) || 2148 (stat == bcmMplsOutPkts)) { 2149 byte_flag=0; 2150 } else { 2151 byte_flag=1; 2152 } 2153 2154 BCM_IF_ERROR_RETURN(_bcm_kt_mpls_label_stat_get_table_info( 2155 unit, label, port, bcmStatObjectMaxValue, 2156 &num_of_tables, &table_info[0])); 2157 2158 for (table_count=0; table_count < num_of_tables ; table_count++) { 2159 if (table_info[table_count].direction == direction) { 2160 for (index_count=0; index_count < num_entries ; index_count++) { 2161 BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_get( 2162 unit, sync_mode, 2163 table_info[table_count].index, 2164 table_info[table_count].table, 2165 0, 2166 byte_flag, 2167 counter_indexes[index_count], 2168 &counter_values[index_count])); 2169 } 2170 } 2171 } 2172 return BCM_E_NONE; 2173 } 2174 /* 2175 * Function: 2176 * bcm_kt_mpls_label_stat_counter_set 2177 * Description: 2178 * Set counter statistic values for specific MPLS label and gport 2179 * 2180 * Parameters: 2181 * unit - (IN) unit number 2182 * label - (IN) MPLS Label 2183 * port - (IN) MPLS Gport 2184 * stat - (IN) Type of the counter to retrieve 2185 * I.e. ingress/egress byte/packet) 2186 * num_entries - (IN) Number of counter Entries 2187 * counter_indexes - (IN) Pointer to Counter indexes entries 2188 * counter_values - (IN) Pointer to counter values 2189 * 2190 * Return Value: 2191 * BCM_E_XXX 2192 * Notes: 2193 */ 2194 bcm_error_t bcm_kt_mpls_label_stat_counter_set( 2195 int unit, 2196 bcm_mpls_label_t label, 2197 bcm_gport_t port, 2198 bcm_mpls_stat_t stat, 2199 uint32 num_entries, 2200 uint32 *counter_indexes, 2201 bcm_stat_value_t *counter_values) 2202 { 2203 uint32 table_count=0; 2204 uint32 index_count=0; 2205 uint32 num_of_tables=0; 2206 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 2207 uint32 byte_flag=0; 2208 bcm_stat_flex_table_info_t table_info[ 2209 BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 2210 bcm_vpn_t vpn = 0; 2211 2212 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 2213 return BCM_E_PARAM; 2214 } 2215 2216 if ((stat == bcmMplsInBytes) || 2217 (stat == bcmMplsInPkts)) { 2218 direction = bcmStatFlexDirectionIngress; 2219 } else { 2220 direction = bcmStatFlexDirectionEgress; 2221 } 2222 if ((stat == bcmMplsInPkts) || 2223 (stat == bcmMplsOutPkts)) { 2224 byte_flag=0; 2225 } else { 2226 byte_flag=1; 2227 } 2228 2229 if (BCM_GPORT_IS_MPLS_PORT(port)) { 2230 /* Just create a valid vpn id to pass the check */ 2231 _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, 1); 2232 BCM_IF_ERROR_RETURN(_bcm_kt_mpls_port_stat_get_table_info( 2233 unit, vpn, port, &num_of_tables, &table_info[0])); 2234 } else { 2235 BCM_IF_ERROR_RETURN(_bcm_kt_mpls_label_stat_get_table_info( 2236 unit, label, port, bcmStatObjectMaxValue, 2237 &num_of_tables, &table_info[0])); 2238 } 2239 for (table_count=0; table_count < num_of_tables ; table_count++) { 2240 if (table_info[table_count].direction == direction) { 2241 for (index_count=0; index_count < num_entries ; index_count++) { 2242 BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_set( 2243 unit, 2244 table_info[table_count].index, 2245 table_info[table_count].table, 2246 0, 2247 byte_flag, 2248 counter_indexes[index_count], 2249 &counter_values[index_count])); 2250 } 2251 } 2252 } 2253 return BCM_E_NONE; 2254 } 2255 /* 2256 * Function: 2257 * bcm_kt_mpls_label_stat_id_get 2258 * Description: 2259 * Get stat counter id associated with given vlan 2260 * 2261 * Parameters: 2262 * unit - (IN) unit number 2263 * label - (IN) MPLS Label 2264 * port - (IN) MPLS Gport 2265 * stat - (IN) Type of the counter to retrieve 2266 * I.e. ingress/egress byte/packet) 2267 * Stat_counter_id - (OUT) Stat Counter ID 2268 * 2269 * Return Value: 2270 * BCM_E_XXX 2271 * Notes: 2272 */ 2273 bcm_error_t bcm_kt_mpls_label_stat_id_get( 2274 int unit, 2275 bcm_mpls_label_t label, 2276 bcm_gport_t port, 2277 bcm_mpls_stat_t stat, 2278 uint32 *stat_counter_id) 2279 { 2280 bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress; 2281 uint32 num_of_tables=0; 2282 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 2283 uint32 index=0; 2284 uint32 num_stat_counter_ids=0; 2285 2286 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 2287 return BCM_E_PARAM; 2288 } 2289 2290 if ((stat == bcmMplsInBytes) || 2291 (stat == bcmMplsInPkts)) { 2292 direction = bcmStatFlexDirectionIngress; 2293 } else { 2294 direction = bcmStatFlexDirectionEgress; 2295 } 2296 BCM_IF_ERROR_RETURN(_bcm_kt_mpls_label_stat_get_table_info( 2297 unit, label, port, bcmStatObjectMaxValue, 2298 &num_of_tables,&table_info[0])); 2299 for (index=0; index < num_of_tables ; index++) { 2300 if (table_info[index].direction == direction) 2301 return _bcm_esw_stat_flex_get_counter_id( 2302 unit, 1, &table_info[index], 2303 &num_stat_counter_ids,stat_counter_id); 2304 } 2305 return BCM_E_NOT_FOUND; 2306 } 2307 /* 2308 * Function: 2309 * bcm_kt_mpls_label_stat_enable_set 2310 * Purpose: 2311 * Enable statistics collection for MPLS label or MPLS gport 2312 * Parameters: 2313 * unit - (IN) Unit number. 2314 * label - (IN) MPLS label 2315 * port - (IN) MPLS gport 2316 * enable - (IN) Non-zero to enable counter collection, zero to disable. 2317 * Returns: 2318 * BCM_E_xxx 2319 * Notes: 2320 */ 2321 int bcm_kt_mpls_label_stat_enable_set( 2322 int unit, 2323 bcm_mpls_label_t label, 2324 bcm_gport_t port, 2325 int enable) 2326 { 2327 uint32 num_of_tables=0; 2328 uint32 num_stat_counter_ids=0; 2329 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 2330 bcm_stat_object_t object=bcmStatObjectIngPort; 2331 uint32 stat_counter_id[ 2332 BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]={0}; 2333 uint32 num_entries=0; 2334 int index=0; 2335 2336 if (BCM_GPORT_IS_MPLS_PORT(port)) { 2337 /* When the gport is an MPLS port, we'll turn on the 2338 * port-based tracking to comply with API definition. 2339 */ 2340 2341 int vpn; 2342 2343 /* just create a valid vpn id to pass the check */ 2344 _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, 1); 2345 BCM_IF_ERROR_RETURN(_bcm_kt_mpls_port_stat_get_table_info( 2346 unit,vpn,port,&num_of_tables,&table_info[0])); 2347 if (enable ) { 2348 for(index=0;index < num_of_tables ;index++) { 2349 if (table_info[index].direction == bcmStatFlexDirectionIngress) { 2350 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_ingress_object( 2351 unit,table_info[index].table, 2352 table_info[index].index,NULL,&object)); 2353 } else { 2354 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_egress_object( 2355 unit,table_info[index].table, 2356 table_info[index].table,NULL,&object)); 2357 } 2358 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_create( 2359 unit,object,bcmStatGroupModeSingle, 2360 &stat_counter_id[table_info[index].direction], 2361 &num_entries)); 2362 BCM_IF_ERROR_RETURN(bcm_kt_mpls_port_stat_attach( 2363 unit,vpn,port, 2364 stat_counter_id[table_info[index].direction])); 2365 } 2366 return BCM_E_NONE; 2367 } else { 2368 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_counter_id( 2369 unit, num_of_tables,&table_info[0], 2370 &num_stat_counter_ids,&stat_counter_id[0])); 2371 if ((stat_counter_id[bcmStatFlexDirectionIngress] == 0) && 2372 (stat_counter_id[bcmStatFlexDirectionEgress] == 0)) { 2373 return BCM_E_PARAM; 2374 } 2375 BCM_IF_ERROR_RETURN(bcm_kt_mpls_port_stat_detach(unit,vpn,port)); 2376 if (stat_counter_id[bcmStatFlexDirectionIngress] != 0) { 2377 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_destroy( 2378 unit, 2379 stat_counter_id[bcmStatFlexDirectionIngress])); 2380 } 2381 if (stat_counter_id[bcmStatFlexDirectionEgress] != 0) { 2382 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_destroy( 2383 unit, 2384 stat_counter_id[bcmStatFlexDirectionEgress])); 2385 } 2386 return BCM_E_NONE; 2387 } 2388 2389 } 2390 2391 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 2392 return BCM_E_PARAM; 2393 } 2394 2395 BCM_IF_ERROR_RETURN(_bcm_kt_mpls_label_stat_get_table_info( 2396 unit, label, port, bcmStatObjectMaxValue, 2397 &num_of_tables, &table_info[0])); 2398 if (enable ) { 2399 for(index=0;index < num_of_tables ;index++) { 2400 if (table_info[index].direction == bcmStatFlexDirectionIngress) { 2401 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_ingress_object( 2402 unit,table_info[index].table, 2403 table_info[index].index,NULL,&object)); 2404 } else { 2405 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_egress_object( 2406 unit,table_info[index].table, 2407 table_info[index].table,NULL,&object)); 2408 } 2409 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_create( 2410 unit,object,bcmStatGroupModeSingle, 2411 &stat_counter_id[table_info[index].direction], 2412 &num_entries)); 2413 BCM_IF_ERROR_RETURN(bcm_esw_mpls_label_stat_attach( 2414 unit,label,port, 2415 stat_counter_id[table_info[index].direction])); 2416 } 2417 return BCM_E_NONE; 2418 } else { 2419 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_counter_id( 2420 unit, num_of_tables,&table_info[0], 2421 &num_stat_counter_ids,&stat_counter_id[0])); 2422 if ((stat_counter_id[bcmStatFlexDirectionIngress] == 0) && 2423 (stat_counter_id[bcmStatFlexDirectionEgress] == 0)) { 2424 return BCM_E_PARAM; 2425 } 2426 BCM_IF_ERROR_RETURN(bcm_esw_mpls_label_stat_detach(unit,label,port)); 2427 if (stat_counter_id[bcmStatFlexDirectionIngress] != 0) { 2428 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_destroy( 2429 unit, 2430 stat_counter_id[bcmStatFlexDirectionIngress])); 2431 } 2432 if (stat_counter_id[bcmStatFlexDirectionEgress] != 0) { 2433 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_destroy( 2434 unit, 2435 stat_counter_id[bcmStatFlexDirectionEgress])); 2436 } 2437 return BCM_E_NONE; 2438 } 2439 2440 } 2441 /* 2442 * Function: 2443 * bcm_kt_mpls_label_stat_get 2444 * Purpose: 2445 * Get L2 MPLS PW Stats 2446 * Parameters: 2447 * unit - (IN) SOC unit # 2448 * label - (IN) MPLS label 2449 * port - (IN) MPLS gport 2450 * stat - (IN) specify the Stat type 2451 * val - (OUT) 64-bit Stats value 2452 * Returns: 2453 * BCM_E_XXX 2454 */ 2455 2456 int bcm_kt_mpls_label_stat_get(int unit, 2457 int sync_mode, 2458 bcm_mpls_label_t label, 2459 bcm_gport_t port, 2460 bcm_mpls_stat_t stat, 2461 uint64 *val) 2462 { 2463 uint32 counter_indexes=0 ; 2464 bcm_stat_value_t counter_values={0}; 2465 2466 if (BCM_GPORT_IS_MPLS_PORT(port)) { 2467 int vpn; 2468 2469 /* just create a valid vpn id to pass the check */ 2470 _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, 1); 2471 2472 BCM_IF_ERROR_RETURN(bcm_kt_mpls_port_stat_counter_get(unit, sync_mode, 2473 vpn, port, 2474 stat, 1, 2475 &counter_indexes, 2476 &counter_values)); 2477 } else { 2478 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 2479 return BCM_E_PARAM; 2480 } 2481 2482 BCM_IF_ERROR_RETURN(bcm_kt_mpls_label_stat_counter_get(unit, sync_mode, 2483 label, port, 2484 stat, 1, 2485 &counter_indexes, 2486 &counter_values)); 2487 } 2488 2489 if ((stat == bcmMplsInPkts) || 2490 (stat == bcmMplsOutPkts)) { 2491 COMPILER_64_SET(*val, 2492 COMPILER_64_HI(counter_values.packets64), 2493 COMPILER_64_LO(counter_values.packets64)); 2494 } else { 2495 COMPILER_64_SET(*val, 2496 COMPILER_64_HI(counter_values.bytes), 2497 COMPILER_64_LO(counter_values.bytes)); 2498 } 2499 return BCM_E_NONE; 2500 } 2501 /* 2502 * Function: 2503 * bcm_kt_mpls_label_stat_get32 2504 * Purpose: 2505 * Get L2 MPLS PW Stats 2506 * if sync_mode is set, sync the sw accumulated count 2507 * with hw count value first, else return sw count. 2508 * Parameters: 2509 * unit - (IN) SOC unit # 2510 * sync_mode - (IN) hwcount is to be synced to sw count 2511 * label - (IN) MPLS label 2512 * port - (IN) MPLS gport 2513 * stat - (IN) specify the Stat type 2514 * val - (OUT) 32-bit Stats value 2515 * Returns: 2516 * BCM_E_XXX 2517 */ 2518 2519 int bcm_kt_mpls_label_stat_get32(int unit, 2520 int sync_mode, 2521 bcm_mpls_label_t label, 2522 bcm_gport_t port, 2523 bcm_mpls_stat_t stat, 2524 uint32 *val) 2525 { 2526 uint32 counter_indexes=0; 2527 bcm_stat_value_t counter_values={0}; 2528 2529 if (BCM_GPORT_IS_MPLS_PORT(port)) { 2530 int vpn; 2531 2532 /* just create a valid vpn id to pass the check */ 2533 _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, 1); 2534 2535 BCM_IF_ERROR_RETURN(bcm_kt_mpls_port_stat_counter_get(unit, sync_mode, 2536 vpn, port, 2537 stat, 1, 2538 &counter_indexes, 2539 &counter_values)); 2540 } else { 2541 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 2542 return BCM_E_PARAM; 2543 } 2544 2545 BCM_IF_ERROR_RETURN(_bcm_esw_mpls_label_stat_counter_get(unit, 2546 sync_mode, 2547 label, port, 2548 stat, 1, 2549 &counter_indexes, 2550 &counter_values)); 2551 } 2552 if ((stat == bcmMplsInPkts) || 2553 (stat == bcmMplsOutPkts)) { 2554 *val = counter_values.packets; 2555 } else { 2556 /* Ignoring Hi bytes value */ 2557 *val = COMPILER_64_LO(counter_values.bytes); 2558 } 2559 return BCM_E_NONE; 2560 } 2561 /* 2562 * Function: 2563 * bcm_kt_mpls_label_stat_clear 2564 * Purpose: 2565 * Clear L2 MPLS PW Stats 2566 * Parameters: 2567 * unit - (IN) SOC unit # 2568 * label - (IN) MPLS label 2569 * port - (IN) MPLS gport 2570 * stat - (IN) specify the Stat type 2571 * Returns: 2572 * BCM_E_XXX 2573 */ 2574 2575 int bcm_kt_mpls_label_stat_clear( 2576 int unit, 2577 bcm_mpls_label_t label, 2578 bcm_gport_t port, 2579 bcm_mpls_stat_t stat) 2580 { 2581 uint32 counter_indexes=0 ; 2582 bcm_stat_value_t counter_values={0}; 2583 2584 if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) { 2585 return BCM_E_PARAM; 2586 } 2587 2588 BCM_IF_ERROR_RETURN(bcm_esw_mpls_label_stat_counter_set( 2589 unit,label,port,stat,1, 2590 &counter_indexes,&counter_values)); 2591 return BCM_E_NONE; 2592 } 2593 2594 2595 2596 2597 #else /* BCM_KATANA_SUPPORT && BCM_MPLS_SUPPORT && INCLUDE_L3 */ 2598 int bcm_esw_katana_mpls_not_empty; 2599 #endif /* BCM_KATANA_SUPPORT && BCM_MPLS_SUPPORT && INCLUDE_L3 */