oam.c (589850B)
1 /* 2 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 3 * 4 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 5 * 6 * File: 7 * oam.c 8 * 9 * Purpose: 10 * OAM implementation for trident2p family of devices. 11 */ 12 13 #include <shared/bsl.h> 14 15 #include <sal/core/libc.h> 16 #include <soc/defs.h> 17 #include <soc/drv.h> 18 #include <soc/scache.h> 19 #include <soc/profile_mem.h> 20 #include <soc/hash.h> 21 22 #include <bcm/oam.h> 23 #include <bcm/field.h> 24 25 #include <bcm_int/esw/oam.h> 26 #include <bcm_int/esw/port.h> 27 #include <bcm_int/esw/switch.h> 28 #include <bcm_int/esw/virtual.h> 29 #include <bcm_int/esw_dispatch.h> 30 31 #include <soc/shared/olp_pkt.h> 32 #include <soc/shared/olp_pack.h> 33 #include <soc/shared/oam_pm_shared.h> 34 35 #if defined(INCLUDE_CCM) || defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 36 #include <bcm_int/esw/fp_oam.h> 37 #endif 38 39 #if defined(INCLUDE_BHH) 40 #include <bcm_int/esw/bhh_sdk_pack.h> 41 #endif 42 43 #if defined(INCLUDE_MPLS_LM_DM) 44 #include <bcm_int/esw/mpls_lm_dm.h> 45 #include <bcm_int/esw/mpls_lm_dm_feature.h> 46 #include <bcm_int/esw/mpls_lm_dm_sdk_msg.h> 47 #include <bcm_int/esw/mpls_lm_dm_sdk_pack.h> 48 #endif /* INCLUDE_MPLS_LM_DM */ 49 50 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 51 #include <bcm_int/esw/flex_ctr.h> 52 #include <bcm_int/esw/firebolt.h> 53 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */ 54 55 56 /* WB sequence for the different modules in OAM */ 57 #if defined(BCM_WARM_BOOT_SUPPORT) 58 typedef enum bcm_fp_oam_wb_sequence_e { 59 bcmFpOamWbSequenceBhh = 0, 60 bcmFpOamWbSequenceMplsLmDm = 1, 61 bcmFpOamWbSequenceCount = 2 62 } bcm_fp_oam_wb_sequence_t; 63 #endif 64 65 66 /*******************************************************************************/ 67 /* OAM Hardware configuration for TD2+ & Apache Start */ 68 /*******************************************************************************/ 69 /* Magic port used for remote OLP over HG communication */ 70 #define _BCM_OAM_TD2P_OLP_MAGIC_PORT 0x7F 71 72 #define _BCM_TD2P_OLP_HDR_TYPE_RX 1 73 #define _BCM_TD2P_OLP_HDR_TYPE_MACSEC_ENCRYPT 2 74 #define _BCM_TD2P_OLP_HDR_TYPE_MACSEC_DECRYPT 3 75 76 /* OLP_HDR_SUBTYPE filled with one of the following values */ 77 /* Down mep subtypes */ 78 #define _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_CCM 0x01 79 #define _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_LM 0x02 80 #define _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_DM 0x03 81 #define _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_OTHER_OC 0x04 82 #define _BCM_TD2P_OLP_HDR_SUBTYPE_BHH_CCM 0x05 83 #define _BCM_TD2P_OLP_HDR_SUBTYPE_BHH_LM 0x06 84 #define _BCM_TD2P_OLP_HDR_SUBTYPE_BHH_DM 0x07 85 #define _BCM_TD2P_OLP_HDR_SUBTYPE_BHH_OTHER_OC 0x08 86 #define _BCM_TD2P_OLP_HDR_SUBTYPE_BFD 0x09 87 #define _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_DLM 0x0A 88 #define _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_DM 0x0B 89 #define _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_DLM_DM 0x0C 90 #define _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_ILM 0x0D 91 #define _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_ILM_DM 0x0E 92 #define _BCM_TD2P_OLP_HDR_SUBTYPE_SAT 0x0F 93 #define _BCM_TD2P_OLP_HDR_SUBTYPE_OTH_ACH 0x10 94 95 /* Up mep subtypes */ 96 #define _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_CCM_UP 0x11 97 #define _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_LM_UP 0x12 98 #define _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_DM_UP 0x13 99 #define _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_OTHER_OC_UP 0x14 100 #define _BCM_TD2P_OLP_HDR_SUBTYPE_SAT_UP 0x15 101 102 #define _BCM_TD2P_OLP_HDR_SUBTYPE_MACSEC_ENCRYPT 0x00 103 #define _BCM_TD2P_OLP_HDR_SUBTYPE_MACSEC_DECRYPT 0x01 104 105 typedef struct _bcm_td2p_olp_hdr_type_mapping_s { 106 bcm_field_olp_header_type_t field_olp_hdr_type; 107 uint8 subtype; 108 } _bcm_td2p_olp_hdr_type_mapping_t; 109 110 STATIC _bcm_td2p_olp_hdr_type_mapping_t td2p_olp_hdr_type_mapping[] = { 111 112 /* Field OLP header type to Subtype mapping table 113 * Note: Do not change the order, as EGR_OLP_HEADER_TYPE_MAPPING table is 114 * programmed in the same order. 115 */ 116 117 /* BFD */ 118 {bcmFieldOlpHeaderTypeBfdOam, _BCM_TD2P_OLP_HDR_SUBTYPE_BFD}, 119 120 /* ETH OAM Down MEP*/ 121 {bcmFieldOlpHeaderTypeEthOamCcm, _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_CCM}, 122 {bcmFieldOlpHeaderTypeEthOamLm, _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_LM}, 123 {bcmFieldOlpHeaderTypeEthOamDm, _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_DM}, 124 {bcmFieldOlpHeaderTypeEthOthers, _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_OTHER_OC}, 125 126 /* BHH */ 127 {bcmFieldOlpHeaderTypeBhhOamCcm, _BCM_TD2P_OLP_HDR_SUBTYPE_BHH_CCM}, 128 {bcmFieldOlpHeaderTypeBhhOamLm, _BCM_TD2P_OLP_HDR_SUBTYPE_BHH_LM}, 129 {bcmFieldOlpHeaderTypeBhhOamDm, _BCM_TD2P_OLP_HDR_SUBTYPE_BHH_DM}, 130 {bcmFieldOlpHeaderTypeBhhOamOthers, _BCM_TD2P_OLP_HDR_SUBTYPE_BHH_OTHER_OC}, 131 132 /* MPLS LM/DM */ 133 {bcmFieldOlpHeaderTypeRfc6374Dlm, _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_DLM}, 134 {bcmFieldOlpHeaderTypeRfc6374Dm, _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_DM}, 135 {bcmFieldOlpHeaderTypeRfc6374DlmPlusDm, _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_DLM_DM}, 136 {bcmFieldOlpHeaderTypeRfc6374Ilm, _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_ILM}, 137 {bcmFieldOlpHeaderTypeRfc6374IlmPlusDm, _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_ILM_DM}, 138 139 /* Down SAT */ 140 {bcmFieldOlpHeaderTypeSat, _BCM_TD2P_OLP_HDR_SUBTYPE_SAT}, 141 142 /* Other ACH */ 143 {bcmFieldOlpHeaderTypeOtherAch, _BCM_TD2P_OLP_HDR_SUBTYPE_OTH_ACH}, 144 145 /* ETH-OAM Up MEP */ 146 {bcmFieldOlpHeaderTypeEthOamUpMepCcm, _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_CCM_UP}, 147 {bcmFieldOlpHeaderTypeEthOamUpMepLm, _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_LM_UP}, 148 {bcmFieldOlpHeaderTypeEthOamUpMepDm, _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_DM_UP}, 149 {bcmFieldOlpHeaderTypeEthOamUpMepOthers, _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_OTHER_OC_UP}, 150 151 /* Up SAT*/ 152 {bcmFieldOlpHeaderTypeUpSat, _BCM_TD2P_OLP_HDR_SUBTYPE_SAT_UP}, 153 154 /* Macsec */ 155 {bcmFieldOlpHeaderTypeMacSecEncrypt, _BCM_TD2P_OLP_HDR_SUBTYPE_MACSEC_ENCRYPT}, 156 {bcmFieldOlpHeaderTypeMacSecDecrypt, _BCM_TD2P_OLP_HDR_SUBTYPE_MACSEC_DECRYPT}, 157 158 }; 159 160 static uint8 td2p_olp_hdr_type_count = sizeof(td2p_olp_hdr_type_mapping) / 161 sizeof(td2p_olp_hdr_type_mapping[0]); 162 int _bcm_fp_oam_trunk_ports_update_trunk_id(int unit, bcm_trunk_t trunk_id); 163 164 #if defined(INCLUDE_BHH) 165 static int fp_oam_mpls_tp_ach_channel_type = SHR_BHH_ACH_CHANNEL_TYPE; 166 #endif /* INCLUDE_BHH */ 167 168 /* 169 * Function: 170 * _bcm_td2p_oam_olp_header_type_mapping_set 171 * Purpose: 172 * Miscellaneous OAM configurations: 173 * 1. Enable IFP lookup on the CPU port. 174 * Parameters: 175 * unit - (IN) BCM unit number. 176 * Retruns: 177 * BCM_E_XXX 178 */ 179 STATIC int 180 _bcm_td2p_oam_olp_header_type_mapping_set(int unit) 181 { 182 int index = 0; 183 int mem_index_count = 0; 184 egr_olp_header_type_mapping_entry_t entry; 185 186 mem_index_count = soc_mem_index_count(unit, EGR_OLP_HEADER_TYPE_MAPPINGm); 187 188 if (td2p_olp_hdr_type_count > mem_index_count) { 189 return BCM_E_RESOURCE; 190 } 191 192 for (index = 0; index < td2p_olp_hdr_type_count; index++) { 193 soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set(unit, 194 &entry, 195 HDR_TYPEf, 196 _BCM_TD2P_OLP_HDR_TYPE_RX); 197 198 #if defined(BCM_MONTEREY_SUPPORT) 199 if (soc_feature(unit, soc_feature_xflow_macsec)) { 200 if (td2p_olp_hdr_type_mapping[index].field_olp_hdr_type 201 == bcmFieldOlpHeaderTypeMacSecEncrypt) { 202 soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set(unit, 203 &entry, 204 HDR_TYPEf, 205 _BCM_TD2P_OLP_HDR_TYPE_MACSEC_ENCRYPT); 206 } else if (td2p_olp_hdr_type_mapping[index].field_olp_hdr_type 207 == bcmFieldOlpHeaderTypeMacSecDecrypt) { 208 soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set(unit, 209 &entry, 210 HDR_TYPEf, 211 _BCM_TD2P_OLP_HDR_TYPE_MACSEC_DECRYPT); 212 } 213 } 214 #endif 215 soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set( 216 unit, 217 &entry, 218 HDR_SUBTYPEf, 219 td2p_olp_hdr_type_mapping[index].subtype); 220 221 SOC_IF_ERROR_RETURN( 222 WRITE_EGR_OLP_HEADER_TYPE_MAPPINGm(unit, MEM_BLOCK_ALL, 223 index, &entry)); 224 #if defined (BCM_APACHE_SUPPORT) || defined(BCM_MONTEREY_SUPPORT) 225 if (soc_feature(unit, soc_feature_ep_redirect_v2) || 226 soc_feature(unit, soc_feature_xflow_macsec)) { 227 SOC_IF_ERROR_RETURN( 228 WRITE_EGR_OLP_HEADER_TYPE_MAPPING_1m(unit, MEM_BLOCK_ALL, 229 index, &entry)); 230 } 231 #endif 232 } 233 return BCM_E_NONE; 234 } 235 236 /* 237 * Function: 238 * _bcm_td2p_oam_hg_olp_enable 239 * Purpose: 240 * Enable OLP on HG ports by default 241 * Parameters: 242 * unit - (IN) BCM device number 243 * Retruns: 244 * BCM_E_XXX 245 */ 246 STATIC int 247 _bcm_td2p_oam_hg_olp_enable(int unit) 248 { 249 bcm_pbmp_t ports; 250 bcm_port_t port; 251 iarb_ing_port_table_entry_t entry; 252 253 BCM_PBMP_ASSIGN(ports, PBMP_PORT_ALL(unit)); 254 255 PBMP_ITER(ports, port) { 256 if (IS_HG_PORT(unit, port)) { 257 SOC_IF_ERROR_RETURN(soc_mem_read(unit, IARB_ING_PORT_TABLEm, 258 MEM_BLOCK_ANY, port, &entry)); 259 260 soc_IARB_ING_PORT_TABLEm_field32_set(unit, &entry, OLP_ENABLEf, 1); 261 262 SOC_IF_ERROR_RETURN(soc_mem_write(unit, IARB_ING_PORT_TABLEm, 263 MEM_BLOCK_ALL, port, &entry)); 264 } 265 } 266 return (BCM_E_NONE); 267 } 268 269 /* 270 * Function: 271 * _bcm_td2p_oam_olp_magic_port_set 272 * Purpose: 273 * Set Magic port used for remote OLP over HG communication 274 * Parameters: 275 * unit - (IN) BCM device number 276 * Returns: 277 * BCM_E_XXX 278 */ 279 int 280 _bcm_td2p_oam_olp_magic_port_set(int unit) 281 { 282 int modid; 283 284 /* Configure modid and the magic port */ 285 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 286 287 SOC_IF_ERROR_RETURN( 288 soc_reg_field32_modify(unit, IARB_OLP_CONFIG_1r, 289 REG_PORT_ANY, MY_MODIDf, modid)); 290 291 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, 292 IARB_OLP_CONFIG_1r, 293 REG_PORT_ANY, 294 MY_PORT_NUMf, 295 _BCM_OAM_TD2P_OLP_MAGIC_PORT)); 296 297 return (BCM_E_NONE); 298 } 299 300 #if defined (BCM_APACHE_SUPPORT) 301 /* 302 * Function: 303 * _bcm_apache_oam_drop_control_fp_encode 304 * Purpose: 305 * Convert a Drop Control mep_type to FP 306 * data and mask 307 * Parameters: 308 * mep_type - (IN) Mep type 309 * data - (OUT) Data for FP qualifier 310 * mask - (OUT) Mask for FP qualifier 311 * Returns: 312 * BCM_E_XXX 313 * Notes: 314 */ 315 int 316 _bcm_apache_oam_drop_control_fp_encode(bcm_field_oam_drop_mep_type_t mep_type, 317 uint8 *data, 318 uint8 *mask) 319 { 320 321 int data_pkt = FALSE; 322 int drop_vector_mask_index; 323 324 switch (mep_type) { 325 case bcmFieldOamDropPortDownMepData: 326 case bcmFieldOamDropPortDownMepControl: 327 drop_vector_mask_index = 0; 328 break; 329 330 case bcmFieldOamDropInnerVlanDownMepData: 331 case bcmFieldOamDropInnerVlanDownMepControl: 332 drop_vector_mask_index = 1; 333 break; 334 335 case bcmFieldOamDropOuterVlanDownMepData: 336 case bcmFieldOamDropOuterVlanDownMepControl: 337 case bcmFieldOamDropInnerPlusOuterVlanDownMepData: 338 case bcmFieldOamDropInnerPlusOuterVlanDownMepControl: 339 drop_vector_mask_index = 2; 340 break; 341 342 case bcmFieldOamDropInnerVlanUpMepData: 343 drop_vector_mask_index = 3; 344 break; 345 346 case bcmFieldOamDropOuterVlanUpMepData: 347 case bcmFieldOamDropInnerPlusOuterVlanUpMepData: 348 drop_vector_mask_index = 4; 349 break; 350 351 case bcmFieldOamDropSectionPortMepData: 352 case bcmFieldOamDropSectionInnerVlanMepData: 353 case bcmFieldOamDropSectionOuterVlanMepData: 354 case bcmFieldOamDropSectionInnerPlusOuterVlanMepData: 355 drop_vector_mask_index = 5; 356 break; 357 358 case bcmFieldOamDropLSPMepData: 359 case bcmFieldOamDropPwMepData: 360 drop_vector_mask_index = 6; 361 break; 362 363 case bcmFieldOamDropSectionPortMepControl: 364 case bcmFieldOamDropSectionInnerVlanMepControl: 365 case bcmFieldOamDropSectionOuterVlanMepControl: 366 case bcmFieldOamDropSectionInnerPlusOuterVlanMepControl: 367 case bcmFieldOamDropLSPMepControl: 368 case bcmFieldOamDropPwMepControl: 369 drop_vector_mask_index = 7; 370 break; 371 372 default: 373 return BCM_E_PARAM; 374 } 375 376 switch (mep_type) { 377 case bcmFieldOamDropPortDownMepData: 378 case bcmFieldOamDropInnerVlanDownMepData: 379 case bcmFieldOamDropOuterVlanDownMepData: 380 case bcmFieldOamDropInnerPlusOuterVlanDownMepData: 381 case bcmFieldOamDropInnerVlanUpMepData: 382 case bcmFieldOamDropOuterVlanUpMepData: 383 case bcmFieldOamDropInnerPlusOuterVlanUpMepData: 384 case bcmFieldOamDropSectionPortMepData: 385 case bcmFieldOamDropSectionInnerVlanMepData: 386 case bcmFieldOamDropSectionOuterVlanMepData: 387 case bcmFieldOamDropSectionInnerPlusOuterVlanMepData: 388 case bcmFieldOamDropLSPMepData: 389 case bcmFieldOamDropPwMepData: 390 data_pkt = TRUE; 391 break; 392 393 default: 394 data_pkt = FALSE; 395 break; 396 } 397 398 if (TRUE == data_pkt) { 399 *data = 1 << drop_vector_mask_index; 400 } else { 401 *data = 0; 402 } 403 404 *mask = 1 << drop_vector_mask_index; 405 406 return BCM_E_NONE; 407 } 408 409 /* 410 * Function: 411 * _bcm_apache_drop_vector_mask_default_set 412 * Purpose: 413 * Program the DROP_VECTOR_MASKS_x with the drop reasons 414 * per MEP. 415 * Parameters: 416 * unit - (IN) BCM unit number. 417 * Returns: 418 * BCM_E_XXX 419 */ 420 STATIC int 421 _bcm_apache_drop_vector_mask_default_set (int unit) 422 { 423 int index; 424 drop_vector_mask_entry_t drop_vector_mask_entry; 425 int entry_count; 426 uint32 entry[][3] = { 427 {0x00003200, 0x00000000, 0x00B013F0}, 428 {0x0000B200, 0x00000800, 0x00B013F0}, 429 {0x0000B200, 0x00008800, 0x00F013F0}, 430 {0x0000B201, 0x00000800, 0x0CB013F0}, 431 {0x0000B201, 0x0000E800, 0x0CF013F0}, 432 {0x0000F201, 0x0000E800, 0x00F017F2}, 433 {0x0000F201, 0x0030E800, 0x03F017F2}, 434 {0x0000F201, 0x0000E800, 0x00F017F2}, 435 }; 436 437 entry_count = soc_mem_index_count(unit, DROP_VECTOR_MASKm); 438 439 for (index = 0; index < entry_count; index++) { 440 soc_DROP_VECTOR_MASKm_field_set(unit, 441 &drop_vector_mask_entry, 442 MASKf, 443 entry[index]); 444 SOC_IF_ERROR_RETURN( 445 WRITE_DROP_VECTOR_MASKm(unit, 446 MEM_BLOCK_ALL, 447 index, 448 &drop_vector_mask_entry)); 449 } 450 return BCM_E_NONE; 451 } 452 453 STATIC int 454 _bcm_apache_oam_default_hw_config_set(int unit) 455 { 456 egr_multicast_mac_addr_entry_t egr_multicast_mac_cfg; 457 bcm_mac_t mac_addr; 458 uint64 mac_addr_64; 459 460 /* Program EGR_MULTICAST_MAC_ADDR with OAM mulicast addresses */ 461 sal_memset(&egr_multicast_mac_cfg, 0, sizeof(egr_multicast_mac_cfg)); 462 463 /* Set ADDR1 to class1 address: 01:80:C2:00:00:30 */ 464 mac_addr[0] = 0x01; 465 mac_addr[1] = 0x80; 466 mac_addr[2] = 0xC2; 467 mac_addr[3] = 0x00; 468 mac_addr[4] = 0x00; 469 mac_addr[5] = 0x30; 470 soc_EGR_MULTICAST_MAC_ADDRm_mac_addr_set(unit, 471 &egr_multicast_mac_cfg, 472 ADDR1f, 473 mac_addr); 474 475 /* Set ADDR_2 & ADDR3 to class2 address: 01:80:C2:00:00:38 */ 476 mac_addr[0] = 0x01; 477 mac_addr[1] = 0x80; 478 mac_addr[2] = 0xC2; 479 mac_addr[3] = 0x00; 480 mac_addr[4] = 0x00; 481 mac_addr[5] = 0x38; 482 soc_EGR_MULTICAST_MAC_ADDRm_mac_addr_set(unit, 483 &egr_multicast_mac_cfg, 484 ADDR2f, 485 mac_addr); 486 soc_EGR_MULTICAST_MAC_ADDRm_mac_addr_set(unit, 487 &egr_multicast_mac_cfg, 488 ADDR3f, 489 mac_addr); 490 491 SOC_IF_ERROR_RETURN( 492 WRITE_EGR_MULTICAST_MAC_ADDRm(unit, 493 MEM_BLOCK_ALL, 494 0, 495 &egr_multicast_mac_cfg)); 496 497 /* Set EGR_MULTICAST_MAC_ADDR_MASK to FF:FF:FF:FF:FF:F8 */ 498 COMPILER_64_SET(mac_addr_64, 0xFFFF, 0xFFFFFFF8); 499 SOC_IF_ERROR_RETURN( 500 WRITE_EGR_MULTICAST_MAC_ADDR_MASKr(unit, mac_addr_64)); 501 502 503 /* Set EGR_LBR_OPCODE to 0x2 */ 504 SOC_IF_ERROR_RETURN(WRITE_EGR_LBR_OPCODEr(unit, 0x2)); 505 506 /* Set default for DROP_VECTOR_MASK[1..8] */ 507 BCM_IF_ERROR_RETURN(_bcm_apache_drop_vector_mask_default_set(unit)); 508 509 return BCM_E_NONE; 510 } 511 #endif /* BCM_APACHE_SUPPORT */ 512 513 514 /* 515 * Function: _bcm_td2p_oam_olp_fp_hw_index_get 516 * 517 * Purpose: 518 * Get OLP_HDR_TYPE_COMPRESSED corresponding to subtype 519 * Parameters: 520 * unit - (IN) BCM device number 521 * Returns: 522 * BCM_E_XXX 523 */ 524 int 525 _bcm_td2p_oam_olp_fp_hw_index_get(int unit, 526 bcm_field_olp_header_type_t olp_hdr_type, 527 int *hwindex) 528 { 529 int index; 530 531 for (index = 0; index < td2p_olp_hdr_type_count; index++) { 532 if (td2p_olp_hdr_type_mapping[index].field_olp_hdr_type == olp_hdr_type) { 533 *hwindex = index; 534 return BCM_E_NONE; 535 } 536 } 537 538 return BCM_E_NOT_FOUND; 539 } 540 541 /* 542 * Function: _bcm_td2p_oam_olp_hw_index_olp_type_get 543 * 544 * Purpose: 545 * Get subtype corresponding to OLP_HDR_TYPE_COMPRESSED 546 * Parameters: 547 * unit - (IN) BCM device number 548 * Returns: 549 * BCM_E_XXX 550 */ 551 int 552 _bcm_td2p_oam_olp_hw_index_olp_type_get(int unit, 553 int hwindex, 554 bcm_field_olp_header_type_t *olp_hdr_type) 555 { 556 if (hwindex >= td2p_olp_hdr_type_count) { 557 return BCM_E_PARAM; 558 } 559 560 *olp_hdr_type = td2p_olp_hdr_type_mapping[hwindex].field_olp_hdr_type; 561 562 return BCM_E_NONE; 563 } 564 /*******************************************************************************/ 565 /* OAM Hardware configuration for TD2+ & Apache end */ 566 /*******************************************************************************/ 567 /*******************************************************************************/ 568 /* PM MACROs for BHH & MPLS LM/DM App start */ 569 /*******************************************************************************/ 570 #if defined (INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 571 typedef struct _bcm_fp_oam_pm_profile_int_info_s { 572 int id_status; 573 bcm_oam_pm_profile_info_t pm_profile; 574 }_bcm_fp_oam_pm_profile_int_info_t; 575 typedef struct _bcm_fp_oam_pm_profile_control_s { 576 _bcm_fp_oam_pm_profile_int_info_t profile_info[_BCM_OAM_MAX_PM_PROFILES]; 577 }_bcm_fp_oam_pm_profile_control_t; 578 579 _bcm_fp_oam_pm_profile_control_t *pm_profile_control[SOC_MAX_NUM_DEVICES]; 580 581 #define _BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, id) \ 582 (pmc->profile_info[id].id_status == 1) 583 #define _BCM_FP_OAM_PM_CTRL_PROFILE_PTR(pmc, id) \ 584 (&(pmc->profile_info[id].pm_profile)) 585 #define _BCM_FP_OAM_SET_PM_CTRL_PROFILE_IN_USE(pmc, id) \ 586 (pmc->profile_info[id].id_status = 1) 587 #define _BCM_FP_OAM_SET_PM_CTRL_PROFILE_NOT_IN_USE(pmc, id) \ 588 (pmc->profile_info[id].id_status = 0) 589 590 #define _BCM_FP_OAM_PM_PROFILE_REPLACE_FLAG_SET(profile) (profile->flags & \ 591 BCM_OAM_PM_PROFILE_REPLACE) 592 593 #define _BCM_FP_OAM_PM_PROFILE_WITH_ID_FLAG_SET(profile) (profile->flags & \ 594 BCM_OAM_PM_PROFILE_WITH_ID) 595 596 #define _BCM_FP_OAM_PM_PROFILE_ID_VALID(profile_id) \ 597 ((profile_id >= 0) && (profile_id < _BCM_OAM_MAX_PM_PROFILES)) 598 599 /* PM raw data events handling macros */ 600 #define _BCM_FP_OAM_EVENT_TYPE_PM_EVENT(event_types) \ 601 ((SHR_BITGET(event_types.w, bcmOAMEventBHHRawData)) || \ 602 (SHR_BITGET(event_types.w, bcmOAMEventMplsLmDmRawData))) 603 604 #if defined (INCLUDE_BHH) 605 #define _BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc) \ 606 (oc->pm_bhh_lmdm_data_collection_mode != \ 607 _BCM_OAM_PM_COLLECTION_MODE_NONE) 608 #define _BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc) \ 609 (oc->pm_bhh_lmdm_data_collection_mode == \ 610 _BCM_OAM_PM_COLLECTION_MODE_RAW_DATA) 611 #define _BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc) \ 612 (oc->pm_bhh_lmdm_data_collection_mode == \ 613 _BCM_OAM_PM_COLLECTION_MODE_PROCESSED_STATS) 614 #else 615 #define _BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc) 0 616 #define _BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc) 0 617 #define _BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc) 0 618 #endif /* INCLUDE_BHH */ 619 620 #if defined (INCLUDE_MPLS_LM_DM) 621 #define _BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc) \ 622 (oc->pm_mpls_lm_dm_data_collection_mode != \ 623 _BCM_OAM_PM_COLLECTION_MODE_NONE) 624 #define _BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)\ 625 (oc->pm_mpls_lm_dm_data_collection_mode ==\ 626 _BCM_OAM_PM_COLLECTION_MODE_RAW_DATA) 627 #define _BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc) \ 628 (oc->pm_mpls_lm_dm_data_collection_mode ==\ 629 _BCM_OAM_PM_COLLECTION_MODE_PROCESSED_STATS) 630 #else 631 #define _BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc) 0 632 #define _BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc) 0 633 #define _BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc) 0 634 #endif /* INCLUDE_MPLS_LM_DM */ 635 636 #define _BCM_FP_OAM_PM_BHH_EVENT_IDX 0 637 #define _BCM_FP_OAM_PM_MPLS_LM_DM_EVENT_IDX 1 638 639 #define _BCM_FP_OAM_BHH_OAM_PM_EVENT_TYPE(event_type) \ 640 (event_type == bcmOAMEventBHHRawData) 641 642 #define PM_READ_DONE_INDEX(event_idx) \ 643 (oc->pm_read_done_index[event_idx]) 644 #define PM_WRITE_DONE_INDEX(event_idx) \ 645 (oc->pm_write_done_index[event_idx]) 646 #define INCREMENT_PM_WRITE_DONE_INDEX(event_idx) \ 647 (((oc->pm_write_done_index[event_idx])+1)%BCM_OAM_MAX_PM_BUFFERS) 648 #define NUM_FREE_BUFFERS(event_idx)\ 649 (oc->pm_num_free_raw_data_buffers[event_idx]) 650 #define SET_NUM_FREE_BUFFERS(event_idx, value)\ 651 (oc->pm_num_free_raw_data_buffers[event_idx] = value) 652 #define DECR_NUM_FREE_BUFFERS(event_idx) \ 653 SET_NUM_FREE_BUFFERS(event_idx, (NUM_FREE_BUFFERS(event_idx) - 1)) 654 #define INCR_NUM_FREE_BUFFERS(event_idx) \ 655 SET_NUM_FREE_BUFFERS(event_idx, (NUM_FREE_BUFFERS(event_idx) + 1)) 656 657 658 659 #define VALID_PM_RAW_DATA_BUFFER_READ_WRITE_INDEX(index) \ 660 (index < BCM_OAM_MAX_PM_BUFFERS) 661 662 int bcm_fp_oam_pm_profile_detach(int unit, bcm_oam_endpoint_t endpoint_id, 663 bcm_oam_pm_profile_t profile_id); 664 665 #ifdef BCM_WARM_BOOT_SUPPORT 666 /* Macro for PM profile information size */ 667 #define _BCM_FP_OAM_PM_PROFILE_SCACHE_SIZE \ 668 (sizeof(_bcm_fp_oam_pm_profile_int_info_t) * (_BCM_OAM_MAX_PM_PROFILES)) 669 #endif /* BCM_WARM_BOOT_SUPPORT */ 670 671 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */ 672 /*******************************************************************************/ 673 /* PM MACROs for BHH & MPLS LM/DM App end */ 674 /*******************************************************************************/ 675 676 #if defined(INCLUDE_BHH) 677 /* 678 * Macro: 679 * BCM_WB_XXX 680 * Purpose: 681 * OAM module scache version information. 682 * Parameters: 683 * (major number, minor number) 684 */ 685 #ifdef BCM_WARM_BOOT_SUPPORT 686 #define BCM_BHH_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 687 #define BCM_BHH_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 688 #define BCM_BHH_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 689 #define BCM_BHH_WB_VERSION_1_3 SOC_SCACHE_VERSION(1,3) 690 #define BCM_WB_BHH_DEFAULT_VERSION BCM_BHH_WB_VERSION_1_3 691 692 #endif 693 694 #define BHH_COSQ_INVALID 0xFFFF 695 696 #define _BCM_FP_OAM_INVALID_NUM_SESSION_ENTRIES 0 697 #define _BCM_OAM_EP_LEVEL_COUNT (1 << (_BCM_OAM_EP_LEVEL_BIT_COUNT)) 698 #define _BCM_OAM_EP_LEVEL_MAX (_BCM_OAM_EP_LEVEL_COUNT - 1) 699 700 /* 701 * * Macro: 702 * _BCM_OAM_BHH_IS_VALID (internal) 703 * Purpose: 704 * Check that the BHH feature is available on this unit 705 * Parameters: 706 * unit - BCM device number 707 * Notes: 708 * Results in return(BCM_E_UNAVAIL), 709 */ 710 #define _BCM_OAM_BHH_IS_VALID(unit) \ 711 do { \ 712 if (!soc_feature(unit, soc_feature_bhh)) { \ 713 return (BCM_E_UNAVAIL); \ 714 } \ 715 } while (0) 716 717 #define BCM_OAM_BHH_GET_UKERNEL_GROUP(group) \ 718 (group - oc->bhh_base_group_id) 719 #define BCM_OAM_BHH_GET_SDK_GROUP(group) \ 720 (group + oc->bhh_base_group_id) 721 722 #define BCM_OAM_BHH_GET_SDK_EP(ep) \ 723 (ep + oc->bhh_base_endpoint_id) 724 #define BCM_OAM_BHH_GET_UKERNEL_EP(ep) \ 725 (ep - oc->bhh_base_endpoint_id) 726 727 #define BCM_OAM_BHH_VALIDATE_EP(_ep_) \ 728 do { \ 729 if (((_ep_) < oc->bhh_base_endpoint_id) || \ 730 ((_ep_) >= (oc->bhh_base_endpoint_id \ 731 + oc->bhh_endpoint_count))) { \ 732 LOG_ERROR(BSL_LS_BCM_OAM, \ 733 (BSL_META_U(unit, \ 734 "OAM(unit %d) Error: Invalid Endpoint ID" \ 735 " = %d.\n"), unit, _ep_)); \ 736 _BCM_OAM_UNLOCK(oc); \ 737 return (BCM_E_PARAM); \ 738 } \ 739 } while (0); 740 741 #define BHH_TYPE(type) ( (type == bcmOAMEndpointTypeBHHMPLS) || \ 742 (type == bcmOAMEndpointTypeBHHMPLSVccv)||\ 743 (type == bcmOAMEndpointTypeBhhSection)||\ 744 (type == bcmOAMEndpointTypeBhhSectionInnervlan)||\ 745 (type == bcmOAMEndpointTypeBhhSectionOuterVlan)||\ 746 (type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)\ 747 ) 748 749 #define BHH_EP_TYPE(ep) (BHH_TYPE(ep->type)) 750 751 #define BHH_EP_MPLS_SECTION_TYPE(ep) (\ 752 (ep->type == bcmOAMEndpointTypeBhhSection)||\ 753 (ep->type == bcmOAMEndpointTypeBhhSectionInnervlan)||\ 754 (ep->type == bcmOAMEndpointTypeBhhSectionOuterVlan)||\ 755 (ep->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)\ 756 ) 757 758 #define BHH_EP_LSP_TYPE(ep) (ep->type == bcmOAMEndpointTypeBHHMPLS) 759 760 /* 761 * Macro: 762 * _BCM_FP_OAM_BHH_GROUP_INDEX_VALIDATE 763 * Purpose: 764 * Validate BHH Group ID value. 765 * Parameters: 766 * _group_ - Group ID value. 767 */ 768 #define _BCM_FP_OAM_BHH_GROUP_INDEX_VALIDATE(_group_) \ 769 do { \ 770 if (((_group_) < oc->bhh_base_group_id) || \ 771 ((_group_) >= (oc->bhh_base_group_id + \ 772 oc->bhh_endpoint_count))) { \ 773 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META("OAM Error: " \ 774 "Invalid Group ID = %d.\n"), _group_)); \ 775 return (BCM_E_PARAM); \ 776 } \ 777 } while (0); 778 779 780 781 /* 782 * Macro: 783 * _BHH_FP_OAM_HASH_DATA_CLEAR 784 * Purpose: 785 * Clear hash data memory occupied by one endpoint. 786 * Parameters: 787 * _ptr_ - Pointer to endpoint hash data memory. 788 */ 789 #define _BHH_FP_OAM_HASH_DATA_CLEAR(_ptr_) \ 790 sal_memset(_ptr_, 0, sizeof(_bhh_fp_oam_ep_data_t)); 791 792 STATIC void 793 _bcm_fp_oam_bhh_callback_thread(void *param); 794 STATIC int 795 _bcm_fp_oam_bhh_event_mask_set(int unit); 796 STATIC int 797 _bcm_fp_oam_bhh_endpoint_create(int unit, 798 bcm_oam_endpoint_info_t *endpoint_info); 799 800 #endif /* INCLUDE_BHH */ 801 802 /*******************************************************************************/ 803 /* MPLS LM/DM specific MACROs */ 804 /*******************************************************************************/ 805 #if defined(INCLUDE_MPLS_LM_DM) 806 #define MPLS_LM_DM_MAX_RAW_DATA_SESSIONS 128 /* Max sessions when PM is operating 807 * in Raw data mode 808 */ 809 #define MPLS_LM_DM_MAX_SESSIONS 256 810 #define _MPLS_LM_DM_INVALID_SESS_ID 0xFFFFFFFF 811 #define _MPLS_LM_DM_INVALID_EP_ID 0xFFFFFFFF 812 813 #define _MPLS_LM_DM_MPLS_MAX_LABELS 9 /* Max MPLS labels in Apache */ 814 815 #define MPLS_LM_DM_RX_CHANNEL_UC_VIEW 1 816 817 818 #define _MPLS_LM_DM_ENDPOINT_TYPE(_type_) \ 819 (((_type_) == bcmOAMEndpointTypeMplsLmDmSectionPort) || \ 820 ((_type_) == bcmOAMEndpointTypeMplsLmDmSectionInnervlan) || \ 821 ((_type_) == bcmOAMEndpointTypeMplsLmDmSectionOuterVlan) || \ 822 ((_type_) == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan)|| \ 823 ((_type_) == bcmOAMEndpointTypeMplsLmDmPw) || \ 824 ((_type_) == bcmOAMEndpointTypeMplsLmDmLsp)) 825 826 #define _MPLS_LM_DM_SECTION_ENDPOINT_TYPE(_type_) \ 827 (((_type_) == bcmOAMEndpointTypeMplsLmDmSectionPort) || \ 828 ((_type_) == bcmOAMEndpointTypeMplsLmDmSectionInnervlan) || \ 829 ((_type_) == bcmOAMEndpointTypeMplsLmDmSectionOuterVlan) || \ 830 ((_type_) == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan)) 831 832 833 #define _MPLS_LM_DM_EP_ID_RANGE(_id_) \ 834 (((_id_) >= oc->mpls_lm_dm_base_endpoint_id) && \ 835 ((_id_) < (oc->mpls_lm_dm_base_endpoint_id + oc->mpls_lm_dm_max_ep_count))) 836 837 #define _MPLS_LM_DM_SESS_ID_RANGE(_id_) \ 838 ( ( (_id_) >= 0 ) && ( (_id_) < oc->mpls_lm_dm_max_ep_count) ) 839 840 #define _MPLS_LM_DM_EP_ID_TO_SESS_ID(_id_) \ 841 _MPLS_LM_DM_EP_ID_RANGE(_id_) ? ((_id_) - oc->mpls_lm_dm_base_endpoint_id) \ 842 : _MPLS_LM_DM_INVALID_SESS_ID 843 844 #define _MPLS_LM_DM_SESS_ID_TO_EP_ID(_id_) \ 845 _MPLS_LM_DM_SESS_ID_RANGE(_id_) ? ((_id_) + oc->mpls_lm_dm_base_endpoint_id) \ 846 : _MPLS_LM_DM_INVALID_EP_ID 847 848 #define _MPLS_LM_DM_HW_SESS_ID_GET(_pool_, _index_) \ 849 ((((_pool_) << 12) & 0x7000) | ((_index_) & 0xfff)) 850 851 #define _MPLS_LM_DM_EP_ITER(_ep_, _idx_) \ 852 for((_idx_) = 0, (_ep_) = &(oc->mpls_lm_dm_ep_data[0]); \ 853 (_idx_) < oc->mpls_lm_dm_max_ep_count; \ 854 (_idx_)++, (_ep_)++) 855 856 #define _MPLS_LM_DM_OLP_REPL_OFFSET_DLM 24 857 #define _MPLS_LM_DM_OLP_REPL_OFFSET_DM 12 858 859 #if defined (BCM_WARM_BOOT_SUPPORT) 860 typedef struct _bcm_fp_oam_mpls_lm_dm_scache_v0_global_data_s { 861 uint8 uc_num; 862 uint8 ukernel_ready; 863 uint8 rx_channel; 864 uint16 max_ep_count; 865 bcm_oam_endpoint_t base_endpoint_id; 866 } _bcm_fp_oam_mpls_lm_dm_scache_v0_global_data_t; 867 868 typedef struct _bcm_fp_oam_mpls_lm_dm_scache_v0_ep_data_s { 869 uint8 in_use; 870 uint8 type; 871 uint8 vccv_type; 872 uint8 trunk_index; 873 uint8 session_num_entries; 874 uint8 lm_ctr_offset[BCM_OAM_LM_COUNTER_MAX]; 875 uint8 lm_ctr_action[BCM_OAM_LM_COUNTER_MAX]; 876 uint8 lm_ctr_size; 877 uint8 dm_ctr_offset[BCM_OAM_LM_COUNTER_MAX]; 878 uint8 dm_ctr_size; 879 uint8 lm_exp; 880 uint8 dm_exp; 881 uint8 outer_pri; 882 uint8 inner_pri; 883 uint8 lm_int_pri; 884 uint8 dm_int_pri; 885 uint8 dst_mac[6]; 886 uint8 src_mac[6]; 887 uint8 pm_profile; 888 uint16 inner_vlan; 889 uint16 outer_vlan; 890 uint16 vpn; 891 uint16 outer_tpid; 892 uint16 inner_tpid; 893 uint32 flags; 894 uint32 lm_ctr_base_id[BCM_OAM_LM_COUNTER_MAX]; 895 uint32 dm_ctr_base_id[BCM_OAM_LM_COUNTER_MAX]; 896 uint32 session_id; 897 uint32 egress_label; 898 bcm_gport_t gport; 899 bcm_if_t intf_id; 900 } _bcm_fp_oam_mpls_lm_dm_scache_v0_ep_data_t; 901 902 #define _MPLS_LM_DM_SCACHE_V0_SIZE \ 903 ((sizeof(_bcm_fp_oam_mpls_lm_dm_scache_v0_global_data_t) + \ 904 (sizeof(_bcm_fp_oam_mpls_lm_dm_scache_v0_ep_data_t) * \ 905 oc->mpls_lm_dm_max_ep_count)) + \ 906 _BCM_FP_OAM_PM_PROFILE_SCACHE_SIZE) 907 908 909 #define BCM_WB_MPLS_LM_DM_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 910 #define BCM_WB_MPLS_LM_DM_DEFAULT_VERSION BCM_WB_MPLS_LM_DM_VERSION_1_0 911 912 #endif /* BCM_WARM_BOOT_SUPPORT */ 913 914 STATIC int _bcm_fp_oam_mpls_lm_dm_loss_delete(int unit, bcm_oam_endpoint_t id); 915 STATIC int _bcm_fp_oam_mpls_lm_dm_delay_delete(int unit, bcm_oam_endpoint_t id); 916 STATIC int _bcm_fp_mpls_lm_dm_event_mask_set(int unit); 917 918 #endif /* INCLUDE_MPLS_LM_DM */ 919 920 #if defined(INCLUDE_CCM) || defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 921 /*******************************************************************************/ 922 /* Common supporting functions used by CCM and BHH Embedded Apps Start */ 923 /*******************************************************************************/ 924 925 /* External functions definition */ 926 extern void _bcm_esw_stat_get_counter_id_info( 927 int unit, 928 uint32 stat_counter_id, 929 bcm_stat_group_mode_t *group, 930 bcm_stat_object_t *object, 931 uint32 *mode, 932 uint32 *pool_number, 933 uint32 *base_idx); 934 935 extern int 936 _bcm_olp_l2_hdr_get(int unit, int glp, uint8 nbo, soc_olp_l2_hdr_t *l2hdr); 937 extern int soc_uc_in_reset(int unit, int uC); 938 extern int soc_uc_status(int unit, int uC, int *status); 939 940 #define BCM_OAM_ABS(x) (((x) < 0) ? (-(x)) : (x)) 941 /* 942 *Macro: 943 * _BCM_OAM_LOCK 944 * Purpose: 945 * Lock take the OAM control mutex 946 * Parameters: 947 * control - Pointer to OAM control structure. 948 */ 949 #define _BCM_OAM_LOCK(control) \ 950 sal_mutex_take((control)->oc_lock, sal_mutex_FOREVER) 951 952 953 /* 954 * Macro: 955 * _BCM_OAM_UNLOCK 956 * Purpose: 957 * Lock take the OAM control mutex 958 * Parameters: 959 * control - Pointer to OAM control structure. 960 */ 961 #define _BCM_OAM_UNLOCK(control) \ 962 sal_mutex_give((control)->oc_lock); 963 964 965 /* 966 *Macro: 967 * _BCM_OAM_IS_INIT 968 * Purpose: 969 * Check if module is initialized 970 * Parameters: 971 * unit - soc unit number. 972 */ 973 #define _BCM_OAM_IS_INIT(unit) \ 974 do { \ 975 if (_fp_oam_control[unit] == NULL) { \ 976 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: Module " \ 977 "not initialized\n"))); \ 978 return (BCM_E_INIT); \ 979 } \ 980 } while (0) 981 982 /* 983 * Macro: 984 * _BCM_OAM_ALLOC 985 * Purpose: 986 * Generic memory allocation routine. 987 * Parameters: 988 * _ptr_ - Pointer to allocated memory. 989 * _ptype_ - Pointer type. 990 * _size_ - Size of heap memory to be allocated. 991 * _descr_ - Information about this memory allocation. 992 */ 993 #define _BCM_OAM_ALLOC(_ptr_,_ptype_,_size_,_descr_) \ 994 do { \ 995 if (NULL == (_ptr_)) { \ 996 (_ptr_) = (_ptype_ *) sal_alloc((_size_), (_descr_)); \ 997 } \ 998 if((_ptr_) != NULL) { \ 999 sal_memset((_ptr_), 0, (_size_)); \ 1000 } else { \ 1001 LOG_ERROR(BSL_LS_BCM_OAM, \ 1002 (BSL_META("OAM Error: Allocation failure %s\n"), \ 1003 (_descr_))); \ 1004 } \ 1005 } while (0) 1006 1007 /* 1008 * Macro: 1009 * _BCM_OAM_KEY_PACK 1010 * Purpose: 1011 * Pack the hash table look up key fields. 1012 * Parameters: 1013 * _dest_ - Hash key buffer. 1014 * _src_ - Hash key field to be packed. 1015 * _size_ - Hash key field size in bytes. 1016 */ 1017 #define _BCM_OAM_KEY_PACK(_dest_,_src_,_size_) \ 1018 do { \ 1019 sal_memcpy((_dest_), (_src_), (_size_)); \ 1020 (_dest_) += (_size_); \ 1021 } while (0) 1022 1023 /* Device OAM control structure */ 1024 _bcm_fp_oam_control_t *_fp_oam_control[SOC_MAX_NUM_DEVICES]; 1025 1026 1027 /* 1028 * Function: 1029 * _bcm_fp_oam_control_get 1030 * Purpose: 1031 * Lookup a OAM control config from a bcm device id. 1032 * Parameters: 1033 * unit - (IN)BCM unit number. 1034 * oc - (OUT) OAM control structure. 1035 * Retruns: 1036 * BCM_E_XXX 1037 */ 1038 STATIC int 1039 _bcm_fp_oam_control_get(int unit, _bcm_fp_oam_control_t **oc) 1040 { 1041 if (NULL == oc) { 1042 return (BCM_E_PARAM); 1043 } 1044 1045 /* Ensure oam module is initialized. */ 1046 _BCM_OAM_IS_INIT(unit); 1047 1048 *oc = _fp_oam_control[unit]; 1049 1050 return (BCM_E_NONE); 1051 } 1052 1053 /* 1054 * Function: 1055 * _bcm_fp_oam_msg_send_receive 1056 * Purpose: 1057 * Sends given control message to the uController. 1058 * Receives and verifies expected reply. 1059 * Performs DMA operation if required. 1060 * Parameters: 1061 * unit - (IN) Unit number. 1062 * msg_class - (IN) Message Class 1063 * s_subclass - (IN) Message subclass. 1064 * s_len - (IN) Value for 'len' field in message struct. 1065 * Length of buffer to flush if DMA send is required. 1066 * s_data - (IN) Value for 'data' field in message struct. 1067 * Ignored if message requires a DMA send/receive 1068 * operation. 1069 * r_subclass - (IN) Expected reply message subclass. 1070 * r_len - (OUT) Returns value in 'len' reply message field. 1071 * Returns: 1072 * BCM_E_XXX 1073 * Notes: 1074 * - The uc_msg 'len' and 'data' fields of mos_msg_data_t 1075 * can take any arbitrary data. 1076 */ 1077 STATIC int 1078 _bcm_fp_oam_msg_send_receive(int unit, uint8 msg_class, uint8 s_subclass, 1079 uint16 s_len, uint32 s_data, 1080 uint8 r_subclass, uint16 *r_len) 1081 { 1082 int rv; 1083 _bcm_fp_oam_control_t *oc; 1084 mos_msg_data_t send, reply; 1085 uint8 *dma_buffer = NULL; 1086 int dma_buffer_len = 0, uc_num = 0; 1087 uint32 uc_rv; 1088 1089 /* Lock already taken by the calling routine. */ 1090 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 1091 1092 sal_memset(&send, 0, sizeof(send)); 1093 sal_memset(&reply, 0, sizeof(reply)); 1094 send.s.mclass = msg_class; 1095 send.s.subclass = s_subclass; 1096 send.s.len = bcm_htons(s_len); 1097 1098 /* Set 'data' to DMA buffer address if a DMA operation is 1099 * required for send or receive. */ 1100 #if defined(INCLUDE_CCM) 1101 if (msg_class == MOS_MSG_CLASS_CCM) { 1102 dma_buffer = oc->dma_buffer; 1103 dma_buffer_len = oc->dma_buffer_len; 1104 uc_num = oc->ccm_uc_num; 1105 } else 1106 #endif /* INCLUDE_CCM */ 1107 #if defined(INCLUDE_BHH) 1108 if (msg_class == MOS_MSG_CLASS_BHH) { 1109 dma_buffer = oc->bhh_dma_buffer; 1110 dma_buffer_len = oc->bhh_dma_buffer_len; 1111 uc_num = oc->bhh_uc_num; 1112 } else 1113 #endif /* INCLUDE_BHH */ 1114 #if defined(INCLUDE_MPLS_LM_DM) 1115 if (msg_class == MOS_MSG_CLASS_MPLS_LM_DM) { 1116 dma_buffer = oc->mpls_lm_dm_dma_buffer; 1117 dma_buffer_len = oc->mpls_lm_dm_dma_buffer_len; 1118 uc_num = oc->mpls_lm_dm_uc_num; 1119 } 1120 #endif /* INCLUDE_MPLS_LM_DM */ 1121 1122 if(dma_buffer == NULL){ 1123 return (BCM_E_INTERNAL); 1124 } 1125 1126 if (MOS_MSG_DMA_MSG(s_subclass) || 1127 MOS_MSG_DMA_MSG(r_subclass)) { 1128 send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer)); 1129 } else { 1130 send.s.data = bcm_htonl(s_data); 1131 } 1132 1133 /* Flush DMA memory */ 1134 if (MOS_MSG_DMA_MSG(s_subclass)) { 1135 soc_cm_sflush(unit, dma_buffer, s_len); 1136 } 1137 1138 /* Invalidate DMA memory to read */ 1139 if (MOS_MSG_DMA_MSG(r_subclass)) { 1140 soc_cm_sinval(unit, dma_buffer, dma_buffer_len); 1141 } 1142 1143 rv = soc_cmic_uc_msg_send_receive(unit, uc_num, &send, &reply, 1144 _UC_MSG_TIMEOUT_USECS); 1145 1146 /* Check reply class, subclass */ 1147 if (rv == SOC_E_TIMEOUT) { 1148 return (BCM_E_TIMEOUT); 1149 } else if (rv == SOC_E_INIT) { 1150 return (BCM_E_INIT); 1151 } else if (rv != SOC_E_NONE) { 1152 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 1153 "UC Message Send/Rcv Failed %s\n"), bcm_errmsg(rv))); 1154 return (BCM_E_INTERNAL); 1155 } 1156 1157 /* Convert uController error code to BCM */ 1158 uc_rv = bcm_ntohl(reply.s.data); 1159 switch(uc_rv) { 1160 case SHR_UC_E_NONE: 1161 rv = BCM_E_NONE; 1162 break; 1163 case SHR_UC_E_INTERNAL: 1164 rv = BCM_E_INTERNAL; 1165 break; 1166 case SHR_UC_E_MEMORY: 1167 rv = BCM_E_MEMORY; 1168 break; 1169 case SHR_UC_E_PARAM: 1170 rv = BCM_E_PARAM; 1171 break; 1172 case SHR_UC_E_RESOURCE: 1173 rv = BCM_E_RESOURCE; 1174 break; 1175 case SHR_UC_E_EXISTS: 1176 rv = BCM_E_EXISTS; 1177 break; 1178 case SHR_UC_E_NOT_FOUND: 1179 rv = BCM_E_NOT_FOUND; 1180 break; 1181 case SHR_UC_E_INIT: 1182 rv = BCM_E_INIT; 1183 break; 1184 case SHR_UC_E_UNAVAIL: 1185 rv = BCM_E_UNAVAIL; 1186 break; 1187 default: 1188 rv = BCM_E_INTERNAL; 1189 break; 1190 } 1191 1192 *r_len = bcm_ntohs(reply.s.len); 1193 1194 /*Check reply class and subclass*/ 1195 if((rv == SOC_E_NONE) && ((reply.s.mclass != msg_class) || 1196 (reply.s.subclass != r_subclass))) 1197 { 1198 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 1199 "UC Err or Rcv Sclass not same as Expected %s\n"), bcm_errmsg(rv))); 1200 return BCM_E_INTERNAL; 1201 } 1202 1203 return (rv); 1204 } 1205 1206 /* 1207 * Function: 1208 * _bcm_fp_oam_endpoint_gport_resolve 1209 * Purpose: 1210 * Resolve an endpoint GPORT value to SGLP and DGLP value. 1211 * Parameters: 1212 * unit - (IN) BCM device number 1213 * ep_info_p - (IN/OUT) Pointer to endpoint information. 1214 * src_glp - (IN/OUT) Pointer to source generic logical port value. 1215 * dst_glp - (IN/OUT) Pointer to destination generic logical port value. 1216 * tx_gport - (OUT) Physical gport on which OAM pkts should go out 1217 * trunk_id - (IN/OUT) Pointer to trunk id 1218 * trunk_member - (OUT) trunk member on which EP present 1219 * 1220 * Retruns: 1221 * BCM_E_XXX 1222 */ 1223 STATIC int 1224 _bcm_fp_oam_endpoint_gport_resolve(int unit, 1225 bcm_oam_endpoint_info_t *ep_info_p, 1226 int *src_glp, 1227 int *dst_glp, 1228 bcm_gport_t *tx_gport, 1229 bcm_trunk_t *trunk_id, 1230 bcm_trunk_member_t *trunk_member) 1231 { 1232 bcm_module_t module_id; /* Module ID */ 1233 bcm_port_t port_id; /* Port ID */ 1234 int local_id; /* Hardware ID */ 1235 bcm_trunk_info_t trunk_info; /* Trunk information. */ 1236 bcm_trunk_member_t *member_array = NULL; /* Trunk member array */ 1237 int member_count = 0; /* Trunk Member count */ 1238 bcm_trunk_t tid = BCM_TRUNK_INVALID; 1239 int tx_enabled = 1; /* CCM Tx enabled */ 1240 int rv = 0; /* Return Value */ 1241 int is_local = 0; 1242 1243 /* Get Trunk ID or (Modid + Port) value from Gport */ 1244 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, ep_info_p->gport, 1245 &module_id, &port_id, trunk_id, 1246 &local_id)); 1247 1248 /* Set CCM endpoint Tx status only for local endpoints. */ 1249 if(ep_info_p->type == bcmOAMEndpointTypeEthernet) { 1250 if (!(ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE)) { 1251 tx_enabled = 1252 (ep_info_p->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) ? 1 : 0; 1253 } 1254 } 1255 1256 if (SOC_GPORT_IS_MPLS_PORT(ep_info_p->gport)) { 1257 if(BCM_TRUNK_INVALID == (*trunk_id)){ 1258 rv = _bcm_esw_modid_is_local(unit, module_id, &is_local); 1259 if(BCM_SUCCESS(rv) && (is_local)) { 1260 _bcm_esw_glp_construct(unit, *trunk_id, module_id, port_id, 1261 dst_glp); 1262 *src_glp = *dst_glp; 1263 } 1264 } 1265 } 1266 1267 /* 1268 * If Gport is Trunk type, _bcm_esw_gport_resolve() 1269 * sets trunk_id. Using Trunk ID, get Dst Modid and Port value. 1270 */ 1271 if (BCM_GPORT_IS_TRUNK(ep_info_p->gport)) { 1272 if (BCM_TRUNK_INVALID == *trunk_id) { 1273 /* Has to be a valid Trunk. */ 1274 return (BCM_E_PARAM); 1275 } 1276 } 1277 1278 1279 if (BCM_TRUNK_INVALID == *trunk_id) { /* Phy gport */ 1280 BCM_GPORT_MODPORT_SET(*tx_gport, module_id, port_id); 1281 } else { 1282 1283 /* Construct Hw SGLP value. */ 1284 BCM_IF_ERROR_RETURN(_bcm_esw_glp_construct(unit, *trunk_id, 1285 module_id, port_id, 1286 src_glp)); 1287 1288 /* 1289 * CCM Tx is enabled on a trunk member port. 1290 * trunk_index value is required to derive the Modid and Port info. 1291 */ 1292 if (1 == tx_enabled) { 1293 1294 if (_BCM_OAM_INVALID_INDEX == ep_info_p->trunk_index) { 1295 /* Invalid Trunk member index passed. */ 1296 return (BCM_E_PORT); 1297 } 1298 1299 /* Get count of ports in this trunk. */ 1300 BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, *trunk_id, NULL, 1301 0, NULL, &member_count)); 1302 if (0 == member_count) { 1303 /* No members have been added to the trunk group yet */ 1304 return BCM_E_PARAM; 1305 } 1306 1307 _BCM_OAM_ALLOC(member_array, bcm_trunk_member_t, 1308 sizeof(bcm_trunk_member_t) * member_count, 1309 "Trunk info"); 1310 if (NULL == member_array) { 1311 return (BCM_E_MEMORY); 1312 } 1313 1314 /* Get Trunk Info for the Trunk ID. */ 1315 rv = bcm_esw_trunk_get(unit, *trunk_id, &trunk_info, 1316 member_count, member_array, &member_count); 1317 if (BCM_FAILURE(rv)) { 1318 sal_free(member_array); 1319 return (rv); 1320 } 1321 1322 /* Check if the input trunk_index is valid. */ 1323 if (ep_info_p->trunk_index >= member_count) { 1324 sal_free(member_array); 1325 return BCM_E_PARAM; 1326 } 1327 1328 /* Get the Modid and Port value using Trunk Index value. */ 1329 rv = _bcm_esw_gport_resolve(unit, 1330 member_array[ep_info_p->trunk_index].gport, 1331 &module_id, &port_id, &tid, &local_id); 1332 if (BCM_FAILURE(rv)) { 1333 sal_free(member_array); 1334 return (rv); 1335 } 1336 1337 sal_free(member_array); 1338 1339 /* Construct Hw DGLP value. */ 1340 BCM_IF_ERROR_RETURN(_bcm_esw_glp_construct(unit, BCM_TRUNK_INVALID, 1341 module_id, port_id, 1342 dst_glp)); 1343 *trunk_member = member_array[ep_info_p->trunk_index]; 1344 1345 *tx_gport = member_array[ep_info_p->trunk_index].gport; 1346 } else { 1347 *dst_glp = *src_glp; 1348 } 1349 } 1350 1351 /* 1352 * Application can resolve the trunk and pass the desginated 1353 * port as Gport value. Check if the Gport belongs to a trunk. 1354 */ 1355 if ((BCM_TRUNK_INVALID == (*trunk_id)) && 1356 (BCM_GPORT_IS_MODPORT(ep_info_p->gport) || 1357 BCM_GPORT_IS_LOCAL(ep_info_p->gport))) { 1358 1359 /* When Gport is ModPort or Port type, _bcm_esw_gport_resolve() 1360 * returns Modid and Port value. Use these values to make the DGLP 1361 * value. 1362 */ 1363 _bcm_esw_glp_construct(unit, BCM_TRUNK_INVALID, 1364 module_id, port_id, dst_glp); 1365 1366 /* Use the Modid, Port value and determine if the port 1367 * belongs to a Trunk. 1368 */ 1369 rv = bcm_esw_trunk_find(unit, module_id, port_id, trunk_id); 1370 if (BCM_SUCCESS(rv)) { 1371 /* 1372 * Port is member of a valid trunk. 1373 * Now create the SGLP value from Trunk ID. 1374 */ 1375 _bcm_esw_glp_construct(unit, *trunk_id, module_id, port_id, src_glp); 1376 } else { 1377 /* Port not a member of trunk. DGLP and SGLP are the same. */ 1378 *src_glp = *dst_glp; 1379 } 1380 } 1381 1382 return BCM_E_NONE; 1383 } 1384 1385 1386 /* 1387 * Function: 1388 * _bcm_fp_oam_olp_l2_header_pack 1389 * Purpose: 1390 * Pack OLP L2 Header into buffer. 1391 * Parameters: 1392 * buffer - (IN/OUT) Buffer to Pack OLP Header 1393 * l2 - (IN) Pointer to OLP L2 Header fields structure. 1394 * Retruns: 1395 * Pointer to end of packet buffer 1396 */ 1397 STATIC uint8 * 1398 _bcm_fp_oam_olp_l2_header_pack(uint8 *buffer, soc_olp_l2_hdr_t *l2) 1399 { 1400 1401 int i; 1402 1403 for (i = 0; i < 6; i++) { 1404 _SHR_PACK_U8(buffer, l2->dst_mac[i]); 1405 } 1406 1407 for (i = 0; i < 6; i++) { 1408 _SHR_PACK_U8(buffer, l2->src_mac[i]); 1409 } 1410 1411 /* Vlan tpid */ 1412 _SHR_PACK_U16(buffer, l2->tpid); 1413 1414 /* Vlan Id */ 1415 _SHR_PACK_U16(buffer, l2->vlan); 1416 1417 /* Ethertype */ 1418 _SHR_PACK_U16(buffer, l2->etherType); 1419 1420 return (buffer); 1421 } 1422 1423 /* 1424 * Function: 1425 * _bcm_fp_oam_olp_l2_header_unpack 1426 * Purpose: 1427 * Unpack OLP L2 Header into buffer. 1428 * Parameters: 1429 * buffer - (IN/OUT) Buffer to Pack OLP Header 1430 * l2 - (IN) Pointer to OLP L2 Header fields structure. 1431 * Retruns: 1432 * Pointer to end of packet buffer 1433 */ 1434 STATIC uint8 * 1435 _bcm_fp_oam_olp_l2_header_unpack(uint8 *buffer, soc_olp_l2_hdr_t *l2) 1436 { 1437 1438 int i; 1439 1440 for (i = 0; i < 6; i++) { 1441 _SHR_UNPACK_U8(buffer, l2->dst_mac[i]); 1442 } 1443 1444 for (i = 0; i < 6; i++) { 1445 _SHR_UNPACK_U8(buffer, l2->src_mac[i]); 1446 } 1447 1448 /* Vlan tpid */ 1449 _SHR_UNPACK_U16(buffer, l2->tpid); 1450 1451 /* Vlan Id */ 1452 _SHR_UNPACK_U16(buffer, l2->vlan); 1453 1454 /* Ethertype */ 1455 _SHR_UNPACK_U16(buffer, l2->etherType); 1456 1457 return (buffer); 1458 } 1459 1460 int 1461 bcm_fp_oam_convert_ep_to_time_spec(bcm_time_spec_t* bts, int sec, int ns) 1462 { 1463 int rv = BCM_E_NONE; 1464 1465 if (bts != NULL) { 1466 /* if both seconds and nanoseconds are negative or both positive, 1467 * then the ucode's subtraction is ok. 1468 * if seconds and nanoseconds have different signs, then "borrow" 1469 * 1000000000 nanoseconds from seconds. 1470 */ 1471 if ((sec < 0) && (ns > 0)) { 1472 ns -= 1000000000; 1473 sec += 1; 1474 } else if ((sec > 0) && (ns < 0)) { 1475 ns += 1000000000; 1476 sec -= 1; 1477 } 1478 1479 if (ns < 0) { 1480 /* if still negative, then something else is wrong. 1481 * the nanoseconds field is the difference between two 1482 * (non-negative) time-stamps. 1483 */ 1484 rv = BCM_E_INTERNAL; 1485 } 1486 1487 /* if seconds is negative then set the bts is-negative flag, 1488 * and use the absolute value of seconds & nanoseconds. 1489 */ 1490 bts->isnegative = (sec < 0 ? 1 : 0); 1491 bts->seconds = BCM_OAM_ABS(sec); 1492 bts->nanoseconds = BCM_OAM_ABS(ns); 1493 } else { 1494 rv = BCM_E_INTERNAL; 1495 } 1496 1497 return rv; 1498 } 1499 #endif /* INCLUDE_CCM || INCLUDE_BHH || INCLUDE_MPLS_LM_DM */ 1500 1501 1502 /*******************************************************************************/ 1503 /* PM routines for BHH & MPLS LM/DM app start */ 1504 /*******************************************************************************/ 1505 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 1506 /* 1507 * Function: 1508 * _bcm_fp_oam_data_collection_modes_init 1509 * Purpose: 1510 * Get the data collection mode for all apps 1511 * Parameters: 1512 * unit - (IN) BCM device number 1513 * Returns: 1514 * None 1515 */ 1516 void _bcm_fp_oam_data_collection_modes_init(int unit) 1517 { 1518 _bcm_fp_oam_control_t *oc = NULL; /* Pointer to control structure. */ 1519 int rv = BCM_E_NONE; 1520 1521 rv = _bcm_fp_oam_control_get(unit, &oc); 1522 1523 if (BCM_FAILURE(rv)) { 1524 LOG_ERROR(BSL_LS_BCM_OAM, 1525 (BSL_META_U(unit, 1526 "OAM(unit %d) Error: Oam control get failed " 1527 "- %s.\n"), unit, bcm_errmsg(rv))); 1528 return; 1529 } 1530 #if defined (INCLUDE_BHH) 1531 oc->pm_bhh_lmdm_data_collection_mode = soc_property_get(unit, 1532 spn_BHH_DATA_COLLECTION_MODE, _BCM_OAM_PM_COLLECTION_MODE_NONE); 1533 #endif /* INCLUDE_BHH */ 1534 #if defined (INCLUDE_MPLS_LM_DM) 1535 oc->pm_mpls_lm_dm_data_collection_mode = soc_property_get(unit, 1536 spn_MPLS_LMDM_DATA_COLLECTION_MODE, _BCM_OAM_PM_COLLECTION_MODE_NONE); 1537 #endif /* INCLUDE_MPLS_LM_DM */ 1538 } 1539 1540 /* 1541 * Function: 1542 * _bcm_fp_oam_pm_init 1543 * Purpose: 1544 * Initialize PM module for all apps 1545 * Parameters: 1546 * unit - (IN) BCM device number 1547 * Returns: 1548 * BCM_E_XXX 1549 */ 1550 int _bcm_fp_oam_pm_init(int unit) 1551 { 1552 /* Profile data structure initialization */ 1553 _bcm_fp_oam_pm_profile_control_t *pmc = NULL; 1554 _bcm_fp_oam_control_t *oc = NULL; 1555 1556 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 1557 _BCM_OAM_LOCK(oc); 1558 1559 _bcm_fp_oam_data_collection_modes_init(unit); 1560 1561 1562 /* Allocate profiles only if one of them has processed stats 1563 * collection enabled 1564 */ 1565 if ((_BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) || 1566 (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc))) { 1567 1568 _BCM_OAM_ALLOC(pmc, _bcm_fp_oam_pm_profile_control_t, 1569 sizeof (_bcm_fp_oam_pm_profile_control_t), 1570 "OAM PM profile control"); 1571 if (!pmc) { 1572 _BCM_OAM_UNLOCK(oc); 1573 return BCM_E_MEMORY; 1574 } 1575 1576 pm_profile_control[unit] = pmc; 1577 } 1578 _BCM_OAM_UNLOCK(oc); 1579 return BCM_E_NONE; 1580 } 1581 1582 #if defined (INCLUDE_BHH) 1583 /* 1584 * Function: 1585 * _bcm_fp_oam_bhh_pm_init 1586 * Purpose: 1587 * Initialize PM module for BHH app 1588 * Parameters: 1589 * unit - (IN) BCM device number 1590 * Returns: 1591 * BCM_E_XXX 1592 */ 1593 int _bcm_fp_oam_bhh_pm_init(int unit) 1594 { 1595 1596 _bcm_fp_oam_control_t *oc = NULL; 1597 1598 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 1599 _BCM_OAM_LOCK(oc); 1600 1601 1602 /* 1603 * Allocate DMA buffers and raw data buffers. 1604 * 1605 * 1) DMA buffer will be used to send and receive 'long' messages 1606 * between SDK Host and uController (BTE). 1607 * 1608 * 1609 * 2) Allocate RAW data buffers which is provided 1610 * to Application during PM event callback 1611 */ 1612 /* DMA buffer */ 1613 if (!oc->ukernel_not_ready) { 1614 if (_BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc)) { 1615 oc->pm_bhh_dma_buffer_len = sizeof(shr_oam_pm_msg_ctrl_t); 1616 oc->pm_bhh_dma_buffer = soc_cm_salloc(unit, 1617 oc->pm_bhh_dma_buffer_len, 1618 "PM DMA buffer"); 1619 if (!oc->pm_bhh_dma_buffer) { 1620 _BCM_OAM_UNLOCK(oc); 1621 return (BCM_E_MEMORY); 1622 } 1623 sal_memset(oc->pm_bhh_dma_buffer, 0, oc->pm_bhh_dma_buffer_len); 1624 if (_BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) { 1625 /* Raw data buffers */ 1626 oc->pm_bhh_raw_data_num_buffers = 1627 soc_property_get(unit, 1628 spn_BHH_PM_RAW_DATA_BUFFERS, 4); 1629 } 1630 /* For first time, when we write this will be 1631 incremented to zero index */ 1632 PM_WRITE_DONE_INDEX(_BCM_FP_OAM_PM_BHH_EVENT_IDX) = -1; 1633 /* Initially all the buffers are free */ 1634 NUM_FREE_BUFFERS(_BCM_FP_OAM_PM_BHH_EVENT_IDX) = BCM_OAM_MAX_PM_BUFFERS; 1635 } 1636 } 1637 _BCM_OAM_UNLOCK(oc); 1638 return BCM_E_NONE; 1639 } 1640 #endif /* INCLUDE_BHH */ 1641 1642 #if defined (INCLUDE_MPLS_LM_DM) 1643 /* 1644 * Function: 1645 * _bcm_fp_oam_mpls_lm_dm_pm_init 1646 * Purpose: 1647 * Initialize PM module for BHH app 1648 * Parameters: 1649 * unit - (IN) BCM device number 1650 * Returns: 1651 * BCM_E_XXX 1652 */ 1653 int _bcm_fp_oam_mpls_lm_dm_pm_init(int unit) 1654 { 1655 1656 _bcm_fp_oam_control_t *oc = NULL; 1657 1658 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 1659 _BCM_OAM_LOCK(oc); 1660 1661 /* DMA buffer */ 1662 if (oc->mpls_lm_dm_ukernel_ready) { 1663 if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc)) { 1664 1665 if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) { 1666 /* Raw data buffers */ 1667 oc->pm_mpls_lm_dm_raw_data_num_buffers = 1668 soc_property_get(unit, 1669 spn_MPLS_LMDM_PM_RAW_DATA_BUFFERS, 4); 1670 /* For first time, when we write this will be incremented to 1671 * zero index 1672 */ 1673 PM_READ_DONE_INDEX(_BCM_FP_OAM_PM_MPLS_LM_DM_EVENT_IDX) = -1; 1674 PM_WRITE_DONE_INDEX(_BCM_FP_OAM_PM_MPLS_LM_DM_EVENT_IDX) = -1; 1675 1676 /* Initially all the buffers are free */ 1677 NUM_FREE_BUFFERS(_BCM_FP_OAM_PM_MPLS_LM_DM_EVENT_IDX) = 1678 BCM_OAM_MAX_PM_BUFFERS; 1679 1680 } 1681 } 1682 } 1683 _BCM_OAM_UNLOCK(oc); 1684 return BCM_E_NONE; 1685 } 1686 #endif /* INCLUDE_MPLS_LM_DM */ 1687 1688 /* 1689 * Function: 1690 * _bcm_fp_oam_pm_dma_buffer_from_endpoint_type_get 1691 * Purpose: 1692 * Get DMA buffer from endpoint type 1693 * Parameters: 1694 * unit - (IN) BCM device number 1695 * type - (OUT) Endpoint type 1696 * Returns: 1697 * Pointer to dma buffer 1698 */ 1699 uint8* 1700 _bcm_fp_oam_pm_dma_buffer_from_endpoint_type_get(int unit, 1701 bcm_oam_endpoint_type_t type) 1702 { 1703 _bcm_fp_oam_control_t *oc = NULL; 1704 int rv = BCM_E_NONE; 1705 1706 rv = _bcm_fp_oam_control_get(unit, &oc); 1707 if (BCM_FAILURE(rv)) { 1708 return NULL; 1709 } 1710 1711 #if defined (INCLUDE_BHH) 1712 if (BHH_TYPE(type)) { 1713 return oc->pm_bhh_dma_buffer; 1714 1715 } else 1716 #endif /* INCLUDE_BHH */ 1717 1718 #if defined(INCLUDE_MPLS_LM_DM) 1719 if (_MPLS_LM_DM_ENDPOINT_TYPE(type)) { 1720 return oc->mpls_lm_dm_dma_buffer; 1721 } 1722 #endif /* INCLUDE_MPLS_LM_DM */ 1723 return NULL; 1724 } 1725 1726 int 1727 _bcm_fp_oam_pm_dma_buffer_and_len_from_class_get(int unit, uint8 class, 1728 uint8 **buffer, int *buffer_len) 1729 { 1730 _bcm_fp_oam_control_t *oc = NULL; 1731 int rv = BCM_E_NONE; 1732 1733 rv = _bcm_fp_oam_control_get(unit, &oc); 1734 if (BCM_FAILURE(rv)) { 1735 return rv; 1736 } 1737 1738 switch(class) { 1739 #if defined(INCLUDE_BHH) 1740 case MOS_MSG_CLASS_BHH: 1741 *buffer = oc->pm_bhh_dma_buffer; 1742 *buffer_len = oc->pm_bhh_dma_buffer_len; 1743 break; 1744 #endif /* INCLUDE_BHH */ 1745 #if defined(INCLUDE_MPLS_LM_DM) 1746 case MOS_MSG_CLASS_MPLS_LM_DM: 1747 *buffer = oc->mpls_lm_dm_dma_buffer; 1748 *buffer_len = oc->mpls_lm_dm_dma_buffer_len; 1749 break; 1750 #endif /* INCLUDE_MPLS_LM_DM */ 1751 default: 1752 return BCM_E_PARAM; 1753 break; 1754 } 1755 return BCM_E_NONE; 1756 } 1757 1758 uint8* _bcm_fp_oam_pm_dma_buffer_get(int unit, bcm_oam_event_type_t event_type) 1759 { 1760 _bcm_fp_oam_control_t *oc = NULL; 1761 int rv = BCM_E_NONE; 1762 uint8 *buffer = NULL; 1763 1764 rv = _bcm_fp_oam_control_get(unit, &oc); 1765 if (BCM_FAILURE(rv)) { 1766 return buffer; 1767 } 1768 switch(event_type) { 1769 #if defined(INCLUDE_BHH) 1770 case bcmOAMEventBHHRawData: 1771 buffer = oc->pm_bhh_dma_buffer; 1772 break; 1773 #endif /* INCLUDE_BHH */ 1774 #if defined(INCLUDE_MPLS_LM_DM) 1775 case bcmOAMEventMplsLmDmRawData: 1776 buffer = oc->mpls_lm_dm_dma_buffer; 1777 break; 1778 #endif /* INCLUDE_MPLS_LM_DM */ 1779 default: 1780 buffer = NULL; 1781 break; 1782 } 1783 return buffer; 1784 } 1785 1786 /* 1787 * Function: 1788 * _bcm_fp_oam_pm_msg_send_receive 1789 * Purpose: 1790 * Sends given PM control message to the uController. 1791 * Receives and verifies expected reply. 1792 * Performs DMA operation if required. 1793 * Parameters: 1794 * unit - (IN) Unit number. 1795 * s_class - (IN) PM message class. 1796 * s_len - (IN) Value for 'len' field in message struct. 1797 * Length of buffer to flush if DMA send is required. 1798 * s_data - (IN) Value for 'data' field in message struct. 1799 * Ignored if message requires a DMA send/receive 1800 * operation. 1801 * r_subclass - (IN) Expected reply message subclass. 1802 * r_len - (OUT) Returns value in 'len' reply message field. 1803 * Returns: 1804 * BCM_E_XXX 1805 * Notes: 1806 * - The uc_msg 'len' and 'data' fields of mos_msg_data_t 1807 * can take any arbitrary data. 1808 * 1809 * PM Long Control message: 1810 * - PM control messages that require send/receive of information 1811 * that cannot fit in the uc_msg 'len' and 'data' fields need to 1812 * use DMA operations to exchange information (long control message). 1813 * 1814 * - PM convention for long control messages for 1815 * 'mos_msg_data_t' fields: 1816 * 'len' size of the DMA buffer to send to uController 1817 * 'data' physical DMA memory address to send or receive 1818 * 1819 * DMA Operations: 1820 * - DMA read/write operation is performed when a long BHH control 1821 * message is involved. 1822 * 1823 * - Messages that require DMA operation (long control message) 1824 * is indicated by MOS_MSG_DMA_MSG(). 1825 * 1826 * - Callers must 'pack' and 'unpack' corresponding information 1827 * into/from DMA buffer indicated by dma_buffer. 1828 */ 1829 STATIC int 1830 _bcm_fp_oam_pm_msg_send_receive(int unit, uint8 s_class, uint8 s_subclass, 1831 uint16 s_len, uint32 s_data, 1832 uint8 r_subclass, uint16 *r_len) 1833 { 1834 int rv = BCM_E_NONE; 1835 _bcm_fp_oam_control_t *oc; 1836 mos_msg_data_t send, reply; 1837 uint8 *dma_buffer = NULL; 1838 int dma_buffer_len = 0; 1839 uint32 uc_rv; 1840 int uc_num = -1; 1841 1842 /* Lock already taken by the calling routine. */ 1843 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 1844 1845 sal_memset(&send, 0, sizeof(send)); 1846 sal_memset(&reply, 0, sizeof(reply)); 1847 send.s.mclass = s_class; 1848 send.s.subclass = s_subclass; 1849 send.s.len = bcm_htons(s_len); 1850 1851 /* 1852 * Set 'data' to DMA buffer address if a DMA operation is 1853 * required for send or receive. 1854 */ 1855 1856 BCM_IF_ERROR_RETURN( 1857 _bcm_fp_oam_pm_dma_buffer_and_len_from_class_get(unit, s_class, 1858 &dma_buffer, 1859 &dma_buffer_len)); 1860 1861 if (MOS_MSG_DMA_MSG(s_subclass) || 1862 MOS_MSG_DMA_MSG(r_subclass)) { 1863 send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer)); 1864 } else { 1865 send.s.data = bcm_htonl(s_data); 1866 } 1867 1868 /* Flush DMA memory */ 1869 if (MOS_MSG_DMA_MSG(s_subclass)) { 1870 soc_cm_sflush(unit, dma_buffer, s_len); 1871 } 1872 1873 /* Invalidate DMA memory to read */ 1874 if (MOS_MSG_DMA_MSG(r_subclass)) { 1875 soc_cm_sinval(unit, dma_buffer, dma_buffer_len); 1876 } 1877 1878 switch (s_class) { 1879 #if defined(INCLUDE_BHH) 1880 case MOS_MSG_CLASS_BHH: 1881 uc_num = oc->bhh_uc_num; 1882 break; 1883 #endif /* INCLUDE_BHH */ 1884 #if defined(INCLUDE_MPLS_LM_DM) 1885 case MOS_MSG_CLASS_MPLS_LM_DM: 1886 uc_num = oc->mpls_lm_dm_uc_num; 1887 break; 1888 #endif /* INCLUDE_MPLS_LM_DM */ 1889 default: 1890 uc_num = -1; 1891 break; 1892 } 1893 1894 if (uc_num == -1) { 1895 return BCM_E_PARAM; 1896 } 1897 /* coverity[unreachable] */ 1898 rv = soc_cmic_uc_msg_send_receive(unit, uc_num, 1899 &send, &reply, 1900 _PM_UC_MSG_TIMEOUT_USECS); 1901 1902 /* Check reply class, subclass */ 1903 /* We can expect the same class that was sent */ 1904 if ((rv != SOC_E_NONE) || 1905 (reply.s.mclass != s_class) || 1906 (reply.s.subclass != r_subclass)) { 1907 return (BCM_E_INTERNAL); 1908 } 1909 1910 /* Convert OAM PM uController error code to BCM */ 1911 uc_rv = bcm_ntohl(reply.s.data); 1912 switch(uc_rv) { 1913 case SHR_OAM_PM_UC_E_NONE: 1914 rv = BCM_E_NONE; 1915 break; 1916 case SHR_OAM_PM_UC_E_INTERNAL: 1917 rv = BCM_E_INTERNAL; 1918 break; 1919 case SHR_OAM_PM_UC_E_MEMORY: 1920 rv = BCM_E_MEMORY; 1921 break; 1922 case SHR_OAM_PM_UC_E_PARAM: 1923 rv = BCM_E_PARAM; 1924 break; 1925 case SHR_OAM_PM_UC_E_RESOURCE: 1926 rv = BCM_E_RESOURCE; 1927 break; 1928 case SHR_OAM_PM_UC_E_EXISTS: 1929 rv = BCM_E_EXISTS; 1930 break; 1931 case SHR_OAM_PM_UC_E_NOT_FOUND: 1932 rv = BCM_E_NOT_FOUND; 1933 break; 1934 case SHR_OAM_PM_UC_E_UNAVAIL: 1935 rv = BCM_E_UNAVAIL; 1936 break; 1937 case SHR_OAM_PM_UC_E_VERSION: 1938 rv = BCM_E_CONFIG; 1939 break; 1940 case SHR_OAM_PM_UC_E_INIT: 1941 rv = BCM_E_INIT; 1942 break; 1943 default: 1944 rv = BCM_E_INTERNAL; 1945 break; 1946 } 1947 1948 *r_len = bcm_ntohs(reply.s.len); 1949 1950 return (rv); 1951 } 1952 1953 int _bcm_fp_oam_pm_profile_compare(bcm_oam_pm_profile_info_t *profile_info1, 1954 bcm_oam_pm_profile_info_t *profile_info2) 1955 { 1956 if (!(sal_memcmp(profile_info1->bin_edges, profile_info2->bin_edges, 1957 BCM_OAM_MAX_PM_PROFILE_BIN_EDGES * sizeof(uint32)))) { 1958 /* Match */ 1959 return 1; 1960 } 1961 return 0; 1962 } 1963 1964 int 1965 _bcm_fp_oam_pm_profile_exists(int unit, bcm_oam_pm_profile_info_t *profile_info) 1966 { 1967 int id = 0; 1968 _bcm_fp_oam_pm_profile_control_t *pmc = NULL; 1969 1970 pmc = pm_profile_control[unit]; 1971 if (!pmc) { 1972 return 0; 1973 } 1974 1975 for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) { 1976 /* If a profile is in use */ 1977 if (_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, id)) { 1978 if (_bcm_fp_oam_pm_profile_compare( 1979 _BCM_FP_OAM_PM_CTRL_PROFILE_PTR(pmc, id), 1980 profile_info)) { 1981 return 1; 1982 } 1983 } 1984 } 1985 return 0; 1986 } 1987 1988 int 1989 _bcm_fp_oam_find_free_pm_profile_id(int unit, int *pm_profile_id) 1990 { 1991 int id = 0; 1992 _bcm_fp_oam_pm_profile_control_t *pmc = NULL; 1993 1994 pmc = pm_profile_control[unit]; 1995 if (!pmc) { 1996 return BCM_E_INIT; 1997 } 1998 1999 /* return the lowest unused id */ 2000 for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) { 2001 if (!(_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, id))) { 2002 /* If a profile is not in use */ 2003 /* Assign it and return */ 2004 *pm_profile_id = id; 2005 return BCM_E_NONE; 2006 } 2007 } 2008 return BCM_E_RESOURCE; 2009 } 2010 2011 int 2012 _bcm_fp_oam_pm_profile_delete(int unit, bcm_oam_pm_profile_t profile_id, int all) 2013 { 2014 _bcm_fp_oam_pm_profile_control_t *pmc; 2015 #if defined(INCLUDE_MPLS_LM_DM) 2016 _bcm_fp_oam_control_t *oc; 2017 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep; 2018 bcm_oam_endpoint_t endpoint_id; 2019 int idx; 2020 #endif /* INCLUDE_MPLS_LM_DM */ 2021 2022 pmc = pm_profile_control[unit]; 2023 if (!pmc) { 2024 return BCM_E_INIT; 2025 } 2026 2027 /* Check it only if it is a delete for a particular profile */ 2028 if (!(_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, profile_id)) && !all) { 2029 /* It is not in use. Return error */ 2030 return BCM_E_NOT_FOUND; 2031 } 2032 2033 /* Detach all EPs having this profile */ 2034 #if defined(INCLUDE_MPLS_LM_DM) 2035 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 2036 2037 _MPLS_LM_DM_EP_ITER(ep, idx) { 2038 2039 if (!ep->in_use) { 2040 continue; 2041 } 2042 2043 if (ep->pm_profile == profile_id) { 2044 endpoint_id = _MPLS_LM_DM_SESS_ID_TO_EP_ID(idx); 2045 BCM_IF_ERROR_RETURN(bcm_fp_oam_pm_profile_detach(unit, endpoint_id, 2046 profile_id)); 2047 } 2048 } 2049 #endif /* INCLUDE_MPLS_LM_DM */ 2050 2051 /* Zero out that profile */ 2052 sal_memset(_BCM_FP_OAM_PM_CTRL_PROFILE_PTR(pmc, profile_id), 0, 2053 sizeof(bcm_oam_pm_profile_info_t)); 2054 /* Mark it un used */ 2055 _BCM_FP_OAM_SET_PM_CTRL_PROFILE_NOT_IN_USE(pmc, profile_id); 2056 2057 return BCM_E_NONE; 2058 } 2059 2060 int 2061 bcm_fp_oam_pm_profile_delete(int unit, bcm_oam_pm_profile_t profile_id) 2062 { 2063 if (!(_BCM_FP_OAM_PM_PROFILE_ID_VALID(profile_id))) { 2064 return BCM_E_PARAM; 2065 } 2066 return _bcm_fp_oam_pm_profile_delete(unit, profile_id, 0); 2067 } 2068 2069 int 2070 bcm_fp_oam_pm_profile_delete_all(int unit) 2071 { 2072 int id; 2073 for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) { 2074 BCM_IF_ERROR_RETURN(_bcm_fp_oam_pm_profile_delete(unit, id, 1)); 2075 } 2076 return BCM_E_NONE; 2077 } 2078 2079 int 2080 bcm_fp_oam_pm_profile_create(int unit, bcm_oam_pm_profile_info_t *profile_info) 2081 { 2082 _bcm_fp_oam_pm_profile_control_t *pmc = NULL; 2083 bcm_oam_pm_profile_info_t *profile_ptr = NULL; 2084 int pm_profile_id = 0; 2085 2086 pmc = pm_profile_control[unit]; 2087 if (!pmc) { 2088 return BCM_E_INIT; 2089 } 2090 2091 if (_BCM_FP_OAM_PM_PROFILE_WITH_ID_FLAG_SET(profile_info)) { 2092 if (!(_BCM_FP_OAM_PM_PROFILE_ID_VALID(profile_info->id))) { 2093 return BCM_E_PARAM; 2094 } 2095 } 2096 2097 if (_BCM_FP_OAM_PM_PROFILE_REPLACE_FLAG_SET(profile_info)) { 2098 if (!(_BCM_FP_OAM_PM_PROFILE_WITH_ID_FLAG_SET(profile_info))) { 2099 /* replace needs the id to be present */ 2100 return BCM_E_PARAM; 2101 } 2102 2103 if (!(_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, profile_info->id))) { 2104 /* Trying to replace a non-existent PM profile */ 2105 return BCM_E_NOT_FOUND; 2106 } 2107 2108 /* Delete the previous profile. */ 2109 BCM_IF_ERROR_RETURN(bcm_fp_oam_pm_profile_delete(unit, 2110 profile_info->id)); 2111 } 2112 2113 if (_BCM_FP_OAM_PM_PROFILE_WITH_ID_FLAG_SET(profile_info)) { 2114 2115 if (_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, profile_info->id)) { 2116 /* That profile id is in use. */ 2117 return BCM_E_EXISTS; 2118 } 2119 2120 /* Else use that as the id */ 2121 pm_profile_id = profile_info->id; 2122 } else { 2123 BCM_IF_ERROR_RETURN(_bcm_fp_oam_find_free_pm_profile_id(unit, 2124 &pm_profile_id)); 2125 } 2126 2127 /* Check if such a profile already exists. */ 2128 if (_bcm_fp_oam_pm_profile_exists(unit, profile_info)) { 2129 return BCM_E_EXISTS; 2130 } 2131 2132 /* Copy it to local profile information */ 2133 profile_ptr = _BCM_FP_OAM_PM_CTRL_PROFILE_PTR(pmc, pm_profile_id); 2134 sal_memcpy(profile_ptr, profile_info, 2135 sizeof(bcm_oam_pm_profile_info_t)); 2136 2137 /* Update the id in the profile */ 2138 profile_ptr->id = profile_info->id = pm_profile_id; 2139 2140 2141 /* Current flags have only transient meaning, so clear them */ 2142 profile_ptr->flags = 0; 2143 2144 /* Mark that profile used */ 2145 _BCM_FP_OAM_SET_PM_CTRL_PROFILE_IN_USE(pmc, pm_profile_id); 2146 2147 2148 return BCM_E_NONE; 2149 } 2150 2151 int 2152 bcm_fp_oam_pm_profile_get(int unit, bcm_oam_pm_profile_info_t *profile_info) 2153 { 2154 _bcm_fp_oam_pm_profile_control_t *pmc; 2155 int profile_id = profile_info->id; 2156 2157 pmc = pm_profile_control[unit]; 2158 if (!pmc) { 2159 return BCM_E_INIT; 2160 } 2161 2162 if (profile_info->id >= _BCM_OAM_MAX_PM_PROFILES) { 2163 return BCM_E_PARAM; 2164 } 2165 2166 if (!(_BCM_FP_OAM_PM_PROFILE_ID_VALID(profile_id))) { 2167 return BCM_E_PARAM; 2168 } 2169 2170 if (!(_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) { 2171 /* It is not in use. Return error */ 2172 return BCM_E_NOT_FOUND; 2173 } 2174 2175 /* Copy the profile to the profile structure passed */ 2176 sal_memcpy(profile_info, _BCM_FP_OAM_PM_CTRL_PROFILE_PTR(pmc, profile_id), 2177 sizeof(bcm_oam_pm_profile_info_t)); 2178 2179 return BCM_E_NONE; 2180 } 2181 2182 int bcm_fp_oam_pm_profile_attach(int unit, bcm_oam_endpoint_t endpoint_id, 2183 bcm_oam_pm_profile_t profile_id) 2184 { 2185 _bcm_fp_oam_pm_profile_control_t *pmc = NULL; 2186 bcm_oam_pm_profile_info_t *profile_info = NULL; 2187 bcm_oam_pm_profile_t *profile = NULL; 2188 _bcm_fp_oam_control_t *oc = NULL; 2189 shr_oam_pm_msg_ctrl_profile_attach_t msg; 2190 uint8 msg_class = 0; 2191 uint16 reply_len = 0; 2192 uint8 msg_subclass = 0; 2193 uint8 msg_reply_subclass = 0; 2194 uint8 *buffer = NULL, *buffer_ptr = NULL; 2195 uint16 buffer_len; 2196 #if defined(INCLUDE_BHH) 2197 _bhh_fp_oam_ep_data_t *h_data_p = NULL; 2198 int bhh_pool_ep_idx = 0; 2199 #endif /* INCLUDE_BHH */ 2200 #if defined(INCLUDE_MPLS_LM_DM) 2201 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep; 2202 uint16 idx; 2203 #endif /* INCLUDE_MPLS_LM_DM */ 2204 int ep_found = 0; 2205 int rv = BCM_E_NONE; 2206 2207 pmc = pm_profile_control[unit]; 2208 if (!pmc) { 2209 return BCM_E_INIT; 2210 } 2211 2212 if (!(_BCM_FP_OAM_PM_PROFILE_ID_VALID(profile_id))) { 2213 return BCM_E_PARAM; 2214 } 2215 2216 /* Check profile id exists or not */ 2217 if (!(_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) { 2218 /* It is not in use. Return error */ 2219 return BCM_E_NOT_FOUND; 2220 } 2221 2222 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 2223 _BCM_OAM_LOCK(oc); 2224 2225 #if defined(INCLUDE_BHH) 2226 if ((endpoint_id >= oc->bhh_base_endpoint_id) && 2227 (endpoint_id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count))) { 2228 2229 ep_found = 1; 2230 2231 bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id); 2232 h_data_p = &oc->bhh_ep_data[bhh_pool_ep_idx]; 2233 2234 if (0 == h_data_p->in_use) { 2235 LOG_ERROR(BSL_LS_BCM_OAM, 2236 (BSL_META_U(unit, 2237 "OAM(unit %d) Error: h_data_p not in use EP=%d\n"), 2238 unit, endpoint_id)); 2239 _BCM_OAM_UNLOCK(oc); 2240 return (BCM_E_NOT_FOUND); 2241 } 2242 2243 /* Check if a profile id is already attached to this endpoint */ 2244 if (h_data_p->pm_profile_attached != _BCM_OAM_INVALID_INDEX) { 2245 _BCM_OAM_UNLOCK(oc); 2246 return BCM_E_EXISTS; 2247 } 2248 2249 /* Attach it to the endpoint */ 2250 h_data_p->pm_profile_attached = profile_id; 2251 profile = &(h_data_p->pm_profile_attached); 2252 2253 /* Send info to u-Kernel about the profile attached with the endpoint */ 2254 sal_memset(&msg, 0, sizeof(msg)); 2255 msg_class = MOS_MSG_CLASS_BHH; 2256 msg_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_ATTACH; 2257 msg_reply_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_ATTACH_REPLY; 2258 msg.sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id); 2259 buffer = oc->pm_bhh_dma_buffer; 2260 } 2261 #endif /* INCLUDE_BHH */ 2262 #if defined(INCLUDE_MPLS_LM_DM) 2263 if(_MPLS_LM_DM_EP_ID_RANGE(endpoint_id)) { 2264 2265 ep_found = 1; 2266 2267 if (!oc->mpls_lm_dm_ukernel_ready) { 2268 _BCM_OAM_UNLOCK(oc); 2269 return BCM_E_INIT; 2270 } 2271 idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(endpoint_id); 2272 ep = &(oc->mpls_lm_dm_ep_data[idx]); 2273 2274 if (!ep->in_use) { 2275 _BCM_OAM_UNLOCK(oc); 2276 return BCM_E_NOT_FOUND; 2277 } 2278 2279 if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) { 2280 _BCM_OAM_UNLOCK(oc); 2281 return BCM_E_PARAM; 2282 } 2283 2284 2285 /* Check if a profile id is already attached to this endpoint */ 2286 if (ep->pm_profile != _BCM_OAM_INVALID_INDEX) { 2287 _BCM_OAM_UNLOCK(oc); 2288 return BCM_E_EXISTS; 2289 } 2290 2291 /* Attach it to the endpoint */ 2292 ep->pm_profile = profile_id; 2293 profile = &(ep->pm_profile); 2294 2295 /* Send info to u-Kernel about the profile attached with the endpoint */ 2296 sal_memset(&msg, 0, sizeof(msg)); 2297 msg_class = MOS_MSG_CLASS_MPLS_LM_DM; 2298 msg_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_PROFILE_ATTACH; 2299 msg_reply_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_PROFILE_ATTACH_REPLY; 2300 msg.sess_id = idx; 2301 buffer = oc->mpls_lm_dm_dma_buffer; 2302 } 2303 #endif /* INCLUDE_MPLS_LM_DM */ 2304 2305 if (!ep_found) { 2306 _BCM_OAM_UNLOCK(oc); 2307 return BCM_E_PARAM; 2308 } 2309 2310 profile_info = _BCM_FP_OAM_PM_CTRL_PROFILE_PTR(pmc, profile_id); 2311 2312 msg.profile_id = profile_id; 2313 msg.profile_flags = profile_info->flags; 2314 sal_memcpy(&(msg.profile_edges), &(profile_info->bin_edges), 2315 (sizeof(uint32) * SHR_OAM_PM_MAX_PM_BIN_EDGES)); 2316 2317 buffer_ptr = shr_oam_pm_msg_ctrl_profile_attach_pack(buffer, &msg); 2318 buffer_len = buffer_ptr - buffer; 2319 2320 2321 rv = _bcm_fp_oam_pm_msg_send_receive(unit, msg_class, msg_subclass, 2322 buffer_len, 0, msg_reply_subclass, 2323 &reply_len); 2324 2325 if(BCM_FAILURE(rv)) { 2326 *profile = _BCM_OAM_INVALID_INDEX; 2327 _BCM_OAM_UNLOCK(oc); 2328 return BCM_E_INTERNAL; 2329 } 2330 2331 _BCM_OAM_UNLOCK(oc); 2332 return BCM_E_NONE; 2333 } 2334 2335 int bcm_fp_oam_pm_profile_detach(int unit, bcm_oam_endpoint_t endpoint_id, 2336 bcm_oam_pm_profile_t profile_id) 2337 { 2338 int rv = BCM_E_NONE; 2339 _bcm_fp_oam_pm_profile_control_t *pmc = NULL; 2340 _bcm_fp_oam_control_t *oc = NULL; 2341 uint8 msg_class = 0; 2342 uint16 reply_len = 0; 2343 uint8 msg_subclass = 0; 2344 uint8 msg_reply_subclass = 0; 2345 uint16 sess_id = 0; 2346 int ep_found = 0; 2347 bcm_oam_pm_profile_t *profile = NULL; 2348 #if defined(INCLUDE_BHH) 2349 _bhh_fp_oam_ep_data_t *h_data_p = NULL; 2350 int bhh_pool_ep_idx = 0; 2351 #endif /* INCLUDE_BHH */ 2352 #if defined(INCLUDE_MPLS_LM_DM) 2353 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep; 2354 uint16 idx; 2355 #endif /* INCLUDE_MPLS_LM_DM */ 2356 2357 pmc = pm_profile_control[unit]; 2358 if (!pmc) { 2359 return BCM_E_INIT; 2360 } 2361 2362 if (!(_BCM_FP_OAM_PM_PROFILE_ID_VALID(profile_id))) { 2363 return BCM_E_PARAM; 2364 } 2365 2366 /* Check profile id exists or not */ 2367 if (!(_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) { 2368 /* It is not in use. Return error */ 2369 return BCM_E_NOT_FOUND; 2370 } 2371 2372 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 2373 _BCM_OAM_LOCK(oc); 2374 2375 #if defined(INCLUDE_BHH) 2376 if ((endpoint_id >= oc->bhh_base_endpoint_id) && 2377 (endpoint_id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count))) { 2378 2379 ep_found = 1; 2380 2381 /* Validate endpoint index value. */ 2382 BCM_OAM_BHH_VALIDATE_EP(endpoint_id); 2383 2384 bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id); 2385 h_data_p = &oc->bhh_ep_data[bhh_pool_ep_idx]; 2386 profile = &(h_data_p->pm_profile_attached); 2387 2388 if (0 == h_data_p->in_use) { 2389 LOG_ERROR(BSL_LS_BCM_OAM, 2390 (BSL_META_U(unit, 2391 "OAM(unit %d) Error: h_data_p not in use EP=%d\n"), 2392 unit, endpoint_id)); 2393 _BCM_OAM_UNLOCK(oc); 2394 return (BCM_E_NOT_FOUND); 2395 } 2396 2397 /* Check if the passed profile id is the one that is attached */ 2398 if (profile_id != h_data_p->pm_profile_attached) { 2399 _BCM_OAM_UNLOCK(oc); 2400 return BCM_E_PARAM; 2401 } 2402 2403 msg_class = MOS_MSG_CLASS_BHH; 2404 msg_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_DETACH; 2405 msg_reply_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_DETACH_REPLY; 2406 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id); 2407 } 2408 #endif /* INCLUDE_BHH */ 2409 #if defined(INCLUDE_MPLS_LM_DM) 2410 if(_MPLS_LM_DM_EP_ID_RANGE(endpoint_id)) { 2411 2412 ep_found = 1; 2413 2414 if (!oc->mpls_lm_dm_ukernel_ready) { 2415 _BCM_OAM_UNLOCK(oc); 2416 return BCM_E_INIT; 2417 } 2418 idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(endpoint_id); 2419 ep = &(oc->mpls_lm_dm_ep_data[idx]); 2420 2421 if (!ep->in_use) { 2422 _BCM_OAM_UNLOCK(oc); 2423 return BCM_E_NOT_FOUND; 2424 } 2425 2426 2427 /* Attach it to the endpoint */ 2428 profile = &(ep->pm_profile); 2429 2430 /* Check if the passed profile id is the one that is attached */ 2431 if (profile_id != ep->pm_profile) { 2432 _BCM_OAM_UNLOCK(oc); 2433 return BCM_E_PARAM; 2434 } 2435 2436 2437 /* Send info to u-Kernel about the profile attached with the endpoint */ 2438 msg_class = MOS_MSG_CLASS_MPLS_LM_DM; 2439 msg_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_PROFILE_DETACH; 2440 msg_reply_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_PROFILE_DETACH_REPLY; 2441 sess_id = idx; 2442 } 2443 #endif /* INCLUDE_MPLS_LM_DM */ 2444 2445 if (!ep_found) { 2446 _BCM_OAM_UNLOCK(oc); 2447 return BCM_E_PARAM; 2448 } 2449 2450 rv = _bcm_fp_oam_pm_msg_send_receive(unit, msg_class, msg_subclass, 2451 sess_id, profile_id, msg_reply_subclass, 2452 &reply_len); 2453 if(BCM_FAILURE(rv)) { 2454 _BCM_OAM_UNLOCK(oc); 2455 return BCM_E_INTERNAL; 2456 } 2457 /* Detach the profile from endpoint */ 2458 *profile = _BCM_OAM_INVALID_INDEX; 2459 2460 _BCM_OAM_UNLOCK(oc); 2461 return BCM_E_NONE; 2462 } 2463 2464 int bcm_fp_oam_pm_profile_traverse(int unit, 2465 bcm_oam_pm_profile_traverse_cb cb, 2466 void *user_data) 2467 { 2468 int rv = BCM_E_NONE; 2469 bcm_oam_pm_profile_info_t *profile_info = NULL; 2470 _bcm_fp_oam_pm_profile_control_t *pmc = NULL; 2471 int profile_id; 2472 2473 /* Validate input parameter. */ 2474 if (NULL == cb) { 2475 return (BCM_E_PARAM); 2476 } 2477 pmc = pm_profile_control[unit]; 2478 if (!pmc) { 2479 return BCM_E_INIT; 2480 } 2481 2482 for (profile_id = 0; profile_id < _BCM_OAM_MAX_PM_PROFILES; profile_id++) { 2483 /* Check profile id is in use or not */ 2484 if (!(_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) { 2485 /* Skip that profile id */ 2486 continue; 2487 } 2488 profile_info = _BCM_FP_OAM_PM_CTRL_PROFILE_PTR(pmc, profile_id); 2489 rv = cb(unit, profile_info, user_data); 2490 if (BCM_FAILURE(rv)) { 2491 LOG_ERROR(BSL_LS_BCM_OAM, 2492 (BSL_META_U(unit, 2493 "OAM(unit %d) Error: EP=%d callback " 2494 "failed - %s.\n"), 2495 unit, profile_id, bcm_errmsg(rv))); 2496 return (rv); 2497 } 2498 } 2499 return (rv); 2500 } 2501 2502 void 2503 _bcm_fp_oam_copy_stats_msg_to_stats_ptr( 2504 shr_oam_pm_msg_ctrl_pm_stats_get_t *stats_msg, 2505 bcm_oam_pm_stats_t *stats_ptr, 2506 uint8 pm_stat_extra_elem_feature) 2507 { 2508 stats_ptr->far_loss_min = stats_msg->far_loss_min; 2509 stats_ptr->far_tx_min = stats_msg->far_tx_min; 2510 stats_ptr->far_loss_max = stats_msg->far_loss_max; 2511 stats_ptr->far_tx_max = stats_msg->far_tx_max; 2512 stats_ptr->far_loss = stats_msg->far_loss; 2513 stats_ptr->near_loss_min = stats_msg->near_loss_min; 2514 stats_ptr->near_tx_min = stats_msg->near_tx_min; 2515 stats_ptr->near_loss_max = stats_msg->near_loss_max; 2516 stats_ptr->near_tx_max = stats_msg->near_tx_max; 2517 stats_ptr->near_loss = stats_msg->near_loss; 2518 stats_ptr->lm_tx_count = stats_msg->lm_tx_count; 2519 stats_ptr->DM_min = stats_msg->DM_min; 2520 stats_ptr->DM_max = stats_msg->DM_max; 2521 if(stats_msg->dm_rx_count) { 2522 stats_ptr->DM_avg = stats_msg->DM_avg/stats_msg->dm_rx_count; 2523 } 2524 stats_ptr->dm_tx_count = stats_msg->dm_tx_count; 2525 stats_ptr->profile_id = stats_msg->profile_id; 2526 sal_memcpy(&(stats_ptr->bin_counters), &(stats_msg->bin_counters), 2527 sizeof(uint32) * (SHR_OAM_PM_MAX_PM_BIN_EDGES + 1)); 2528 if(pm_stat_extra_elem_feature) { 2529 stats_ptr->lm_rx_count = stats_msg->lm_rx_count; 2530 stats_ptr->dm_rx_count = stats_msg->dm_rx_count; 2531 stats_ptr->far_total_tx_pkt_count = stats_msg->far_total_tx_pkt_count; 2532 stats_ptr->near_total_tx_pkt_count = stats_msg->near_total_tx_pkt_count; 2533 } 2534 2535 if (stats_msg->flags & SHR_OAM_PM_STATS_FLAG_COUNTER_ROLLOVER) { 2536 stats_ptr->flags |= BCM_OAM_PM_STATS_PROCESSED_COUNTER_ROLLOVER; 2537 } 2538 } 2539 2540 int bcm_fp_oam_pm_stats_get(int unit, 2541 bcm_oam_endpoint_t endpoint_id, 2542 bcm_oam_pm_stats_t *stats_ptr) 2543 { 2544 _bcm_fp_oam_pm_profile_control_t *pmc = NULL; 2545 _bcm_fp_oam_control_t *oc = NULL; 2546 shr_oam_pm_msg_ctrl_pm_stats_get_t stats_msg; 2547 int rv = BCM_E_NONE; 2548 uint16 sess_id = 0; 2549 uint8 msg_class = 0; 2550 uint16 reply_len = 0; 2551 uint8 msg_subclass = 0; 2552 uint8 msg_reply_subclass = 0; 2553 uint8 *dma_buffer = NULL; 2554 uint8 pm_stat_extra_elem_feature = 0; 2555 int ep_found = 0; 2556 #if defined(INCLUDE_BHH) 2557 _bhh_fp_oam_ep_data_t *h_data_p = NULL; 2558 int bhh_pool_ep_idx = 0; 2559 #endif /* INCLUDE_BHH */ 2560 #if defined(INCLUDE_MPLS_LM_DM) 2561 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep; 2562 uint16 idx; 2563 #endif /* INCLUDE_MPLS_LM_DM */ 2564 2565 pmc = pm_profile_control[unit]; 2566 if (!pmc) { 2567 return BCM_E_INIT; 2568 } 2569 2570 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 2571 _BCM_OAM_LOCK(oc); 2572 2573 #if defined(INCLUDE_BHH) 2574 if ((endpoint_id >= oc->bhh_base_endpoint_id) && 2575 (endpoint_id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count))) { 2576 2577 ep_found = 1; 2578 /* Validate endpoint index value. */ 2579 BCM_OAM_BHH_VALIDATE_EP(endpoint_id); 2580 2581 bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id); 2582 /* Check endpoint status. */ 2583 rv = shr_idxres_list_elem_state(oc->bhh_pool, bhh_pool_ep_idx); 2584 if ((BCM_E_EXISTS != rv)) { 2585 /* Endpoint not in use. */ 2586 LOG_ERROR(BSL_LS_BCM_OAM, 2587 (BSL_META_U(unit, 2588 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 2589 unit, endpoint_id, bcm_errmsg(rv))); 2590 _BCM_OAM_UNLOCK(oc); 2591 return (rv); 2592 } 2593 2594 h_data_p = &oc->bhh_ep_data[bhh_pool_ep_idx]; 2595 2596 if (0 == h_data_p->in_use) { 2597 LOG_ERROR(BSL_LS_BCM_OAM, 2598 (BSL_META_U(unit, 2599 "OAM(unit %d) Error: h_data_p not in use EP=%d\n"), 2600 unit, endpoint_id)); 2601 _BCM_OAM_UNLOCK(oc); 2602 return (BCM_E_INTERNAL); 2603 } 2604 2605 msg_class = MOS_MSG_CLASS_BHH; 2606 msg_subclass = MOS_MSG_SUBCLASS_BHH_PM_STATS_GET; 2607 msg_reply_subclass = MOS_MSG_SUBCLASS_BHH_PM_STATS_GET_REPLY; 2608 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id); 2609 pm_stat_extra_elem_feature = BHH_UC_FEATURE_CHECK( 2610 BHH_PM_STAT_EXTRA_ELEM); 2611 dma_buffer = _bcm_fp_oam_pm_dma_buffer_from_endpoint_type_get(unit, 2612 h_data_p->type); 2613 } 2614 #endif /* INCLUDE_BHH */ 2615 #if defined(INCLUDE_MPLS_LM_DM) 2616 if(_MPLS_LM_DM_EP_ID_RANGE(endpoint_id)) { 2617 ep_found = 1; 2618 2619 if (!oc->mpls_lm_dm_ukernel_ready) { 2620 _BCM_OAM_UNLOCK(oc); 2621 return BCM_E_INIT; 2622 } 2623 idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(endpoint_id); 2624 ep = &(oc->mpls_lm_dm_ep_data[idx]); 2625 2626 if (!ep->in_use) { 2627 _BCM_OAM_UNLOCK(oc); 2628 return BCM_E_NOT_FOUND; 2629 } 2630 2631 if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED) && 2632 !(ep->flags & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) { 2633 _BCM_OAM_UNLOCK(oc); 2634 return BCM_E_NOT_FOUND; 2635 } 2636 2637 if (!_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) { 2638 _BCM_OAM_UNLOCK(oc); 2639 return BCM_E_NOT_FOUND; 2640 } 2641 2642 msg_class = MOS_MSG_CLASS_MPLS_LM_DM; 2643 msg_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_STATS_GET; 2644 msg_reply_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_STATS_GET_REPLY; 2645 sess_id = idx; 2646 pm_stat_extra_elem_feature = MPLS_LM_DM_UC_FEATURE_CHECK( 2647 MPLS_LM_DM_PM_STAT_EXTRA_ELEM); 2648 dma_buffer = oc->mpls_lm_dm_dma_buffer; 2649 } 2650 #endif /* INCLUDE_MPLS_LM_DM */ 2651 2652 if (!ep_found) { 2653 _BCM_OAM_UNLOCK(oc); 2654 return BCM_E_PARAM; 2655 } 2656 2657 /* Pass the buffer pointer in data and sess id in length fields.*/ 2658 rv = _bcm_fp_oam_pm_msg_send_receive(unit, msg_class, 2659 msg_subclass, 2660 sess_id, soc_cm_l2p(unit, dma_buffer), 2661 msg_reply_subclass, 2662 &reply_len); 2663 if(BCM_FAILURE(rv) || reply_len == 0) { 2664 _BCM_OAM_UNLOCK(oc); 2665 return BCM_E_INTERNAL; 2666 } 2667 2668 shr_oam_pm_msg_ctrl_pm_stats_get_unpack(dma_buffer, &stats_msg, 2669 pm_stat_extra_elem_feature); 2670 2671 _bcm_fp_oam_copy_stats_msg_to_stats_ptr(&stats_msg, stats_ptr, 2672 pm_stat_extra_elem_feature); 2673 2674 _BCM_OAM_UNLOCK(oc); 2675 return BCM_E_NONE; 2676 } 2677 2678 2679 int 2680 bcm_fp_oam_pm_profile_attach_get(int unit, 2681 bcm_oam_endpoint_t endpoint_id, 2682 bcm_oam_pm_profile_t *profile_id) 2683 { 2684 _bcm_fp_oam_pm_profile_control_t *pmc = NULL; 2685 _bcm_fp_oam_control_t *oc = NULL; 2686 int ep_found = 0; 2687 #if defined(INCLUDE_BHH) 2688 _bhh_fp_oam_ep_data_t *h_data_p = NULL; 2689 int bhh_pool_ep_idx = 0; 2690 int rv = BCM_E_NONE; 2691 #endif /* INCLUDE_BHH */ 2692 #if defined(INCLUDE_MPLS_LM_DM) 2693 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep; 2694 uint16 idx; 2695 #endif /* INCLUDE_MPLS_LM_DM */ 2696 2697 pmc = pm_profile_control[unit]; 2698 if (!pmc) { 2699 return BCM_E_INIT; 2700 } 2701 2702 /* Check profile id exists or not */ 2703 if (!(_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, *profile_id))) { 2704 /* It is not in use. Return error */ 2705 return BCM_E_PARAM; 2706 } 2707 2708 2709 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 2710 _BCM_OAM_LOCK(oc); 2711 2712 #if defined(INCLUDE_BHH) 2713 if ((endpoint_id >= oc->bhh_base_endpoint_id) && 2714 (endpoint_id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count))) { 2715 2716 ep_found = 1; 2717 /* Validate endpoint index value. */ 2718 BCM_OAM_BHH_VALIDATE_EP(endpoint_id); 2719 2720 bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id); 2721 /* Check endpoint status. */ 2722 rv = shr_idxres_list_elem_state(oc->bhh_pool, bhh_pool_ep_idx); 2723 if ((BCM_E_EXISTS != rv)) { 2724 /* Endpoint not in use. */ 2725 LOG_ERROR(BSL_LS_BCM_OAM, 2726 (BSL_META_U(unit, 2727 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 2728 unit, endpoint_id, bcm_errmsg(rv))); 2729 _BCM_OAM_UNLOCK(oc); 2730 return (rv); 2731 } 2732 h_data_p = &oc->bhh_ep_data[bhh_pool_ep_idx]; 2733 2734 if (0 == h_data_p->in_use) { 2735 LOG_ERROR(BSL_LS_BCM_OAM, 2736 (BSL_META_U(unit, 2737 "OAM(unit %d) Error: h_data_p not in use EP=%d\n"), 2738 unit, endpoint_id)); 2739 _BCM_OAM_UNLOCK(oc); 2740 return (BCM_E_INTERNAL); 2741 } 2742 /* Get the attached profile */ 2743 *profile_id = h_data_p->pm_profile_attached; 2744 } 2745 #endif /* INCLUDE_BHH */ 2746 #if defined(INCLUDE_MPLS_LM_DM) 2747 if(_MPLS_LM_DM_EP_ID_RANGE(endpoint_id)) { 2748 2749 ep_found = 1; 2750 2751 if (!oc->mpls_lm_dm_ukernel_ready) { 2752 _BCM_OAM_UNLOCK(oc); 2753 return BCM_E_INIT; 2754 } 2755 idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(endpoint_id); 2756 ep = &(oc->mpls_lm_dm_ep_data[idx]); 2757 2758 if (!ep->in_use) { 2759 _BCM_OAM_UNLOCK(oc); 2760 return BCM_E_NOT_FOUND; 2761 } 2762 2763 /* Check if a profile id is already attached to this endpoint */ 2764 if (ep->pm_profile == _BCM_OAM_INVALID_INDEX) { 2765 _BCM_OAM_UNLOCK(oc); 2766 return BCM_E_EXISTS; 2767 } 2768 /* Get the attached profile */ 2769 *profile_id = ep->pm_profile; 2770 } 2771 #endif /* INCLUDE_MPLS_LM_DM */ 2772 2773 if (!ep_found) { 2774 _BCM_OAM_UNLOCK(oc); 2775 return BCM_E_PARAM; 2776 } 2777 if (*profile_id == _BCM_OAM_INVALID_INDEX) { 2778 _BCM_OAM_UNLOCK(oc); 2779 return BCM_E_NOT_FOUND; 2780 } 2781 2782 _BCM_OAM_UNLOCK(oc); 2783 return BCM_E_NONE; 2784 } 2785 2786 void 2787 _bcm_fp_oam_write_dma_buffer_to_raw_buffer(int unit, uint8 *dma_buffer, 2788 bcm_oam_pm_raw_data_t *raw_data, int write_index) 2789 { 2790 shr_oam_pm_msg_ctrl_raw_buffer_unpack(dma_buffer, 2791 (shr_oam_pm_msg_ctrl_raw_buffer_t *)(&(raw_data->raw_buffer[write_index]))); 2792 } 2793 2794 int _bcm_fp_oam_pm_raw_data_event_index_from_event_get(bcm_oam_event_type_t event_type) 2795 { 2796 switch (event_type) { 2797 #if defined(INCLUDE_BHH) 2798 case bcmOAMEventBHHRawData: 2799 return _BCM_FP_OAM_PM_BHH_EVENT_IDX; 2800 break; 2801 #endif /* INCLUDE_BHH */ 2802 #if defined(INCLUDE_MPLS_LM_DM) 2803 case bcmOAMEventMplsLmDmRawData: 2804 return _BCM_FP_OAM_PM_MPLS_LM_DM_EVENT_IDX; 2805 break; 2806 #endif /* INCLUDE_MPLS_LM_DM */ 2807 default: 2808 return -1; 2809 break; 2810 } 2811 return -1; 2812 } 2813 2814 void _bcm_fp_oam_update_num_free_buffers(_bcm_fp_oam_control_t *oc, 2815 int event_idx, int read_idx, 2816 int write_idx, int last_op) 2817 { 2818 /* Normal case */ 2819 if (read_idx < write_idx) { 2820 SET_NUM_FREE_BUFFERS(event_idx, 2821 (BCM_OAM_MAX_PM_BUFFERS - (write_idx - read_idx))); 2822 } else if (read_idx > write_idx) { 2823 /* rollover case */ 2824 SET_NUM_FREE_BUFFERS(event_idx, 2825 (read_idx - write_idx)); 2826 } else { /* read index = write index case */ 2827 if (last_op == 1) { 2828 /* Last operation was write, means write idx has caught 2829 up with read_idx. 2830 Just decrement the number of buffers by 1. 2831 Ideally this would mean the num of free buffers would 2832 become zero */ 2833 DECR_NUM_FREE_BUFFERS(event_idx); 2834 } else if (last_op == 0) { 2835 /* Last operation was read, means read idx has caught 2836 up with write idx. 2837 Just increment the number of buffers by 1. 2838 Ideally this would mean the num of free buffers would 2839 have become max. */ 2840 INCR_NUM_FREE_BUFFERS(event_idx); 2841 } 2842 } 2843 } 2844 2845 /* Returns 0 - Not updated or 1 - Updated */ 2846 int 2847 _bcm_fp_oam_update_dma_buffer_into_raw_buffer(int unit, 2848 bcm_oam_event_type_t event_type, 2849 uint8 *dma_buffer, 2850 bcm_oam_pm_raw_data_t *raw_data) 2851 { 2852 int rv = BCM_E_NONE; 2853 int event_idx = -1; 2854 _bcm_fp_oam_control_t *oc; 2855 int read_idx = -1; 2856 int write_idx = -1; 2857 2858 /* Get OAM Control Structure. */ 2859 rv = _bcm_fp_oam_control_get(unit, &oc); 2860 if (BCM_FAILURE(rv)) { 2861 return FALSE; 2862 } 2863 2864 event_idx = _bcm_fp_oam_pm_raw_data_event_index_from_event_get(event_type); 2865 if (event_idx == -1) { 2866 return FALSE; 2867 } 2868 2869 if (NUM_FREE_BUFFERS(event_idx) > 0) { 2870 PM_WRITE_DONE_INDEX(event_idx) = INCREMENT_PM_WRITE_DONE_INDEX 2871 (event_idx); 2872 /* Writing at the incremented index */ 2873 _bcm_fp_oam_write_dma_buffer_to_raw_buffer(unit, dma_buffer, raw_data, 2874 PM_WRITE_DONE_INDEX(event_idx)); 2875 } else { 2876 /* There are no free buffers. Do not update */ 2877 return FALSE; 2878 } 2879 read_idx = PM_READ_DONE_INDEX(event_idx); 2880 write_idx = PM_WRITE_DONE_INDEX(event_idx); 2881 2882 /* 1 passed indicates last operation was write */ 2883 _bcm_fp_oam_update_num_free_buffers(oc, event_idx, read_idx, write_idx, 1); 2884 2885 raw_data->read_index = PM_READ_DONE_INDEX(event_idx); 2886 raw_data->write_index = PM_WRITE_DONE_INDEX(event_idx); 2887 2888 return TRUE; 2889 } 2890 2891 int 2892 bcm_fp_oam_pm_raw_data_read_done(int unit, 2893 bcm_oam_event_types_t event_types, 2894 uint32 read_index) 2895 { 2896 bcm_oam_event_type_t event_type; 2897 _bcm_fp_oam_control_t *oc; 2898 int event_idx = -1; 2899 2900 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 2901 /* Do sanity validation of event_types and read_index */ 2902 if (!(_BCM_FP_OAM_EVENT_TYPE_PM_EVENT(event_types))) { 2903 return BCM_E_PARAM; 2904 } 2905 2906 if (!(VALID_PM_RAW_DATA_BUFFER_READ_WRITE_INDEX(read_index))) { 2907 return BCM_E_PARAM; 2908 } 2909 2910 for (event_type = bcmOAMEventBHHRawData; 2911 event_type <= bcmOAMEventMplsLmDmRawData; event_type++) { 2912 if (BCM_OAM_EVENT_TYPE_GET(event_types, event_type)) { 2913 event_idx = _bcm_fp_oam_pm_raw_data_event_index_from_event_get 2914 (event_type); 2915 if (event_idx == -1) { 2916 return BCM_E_PARAM; 2917 } 2918 PM_READ_DONE_INDEX(event_idx) = read_index; 2919 /* 0 passed indicates last operation was read */ 2920 _bcm_fp_oam_update_num_free_buffers(oc, event_idx, read_index, 2921 PM_WRITE_DONE_INDEX(event_idx), 0); 2922 } 2923 } 2924 return BCM_E_NONE; 2925 } 2926 2927 bcm_oam_pm_raw_data_t* 2928 _bcm_fp_oam_pm_raw_data_info_get(int unit, 2929 bcm_oam_event_type_t event_type) 2930 { 2931 int rv = BCM_E_NONE; 2932 _bcm_fp_oam_control_t *oc; 2933 bcm_oam_pm_raw_data_t *buffer = NULL; 2934 2935 rv = _bcm_fp_oam_control_get(unit, &oc); 2936 if (BCM_FAILURE(rv)) { 2937 return NULL; 2938 } 2939 switch (event_type) { 2940 #if defined(INCLUDE_BHH) 2941 case bcmOAMEventBHHRawData: 2942 buffer = &(oc->pm_bhh_raw_data_info); 2943 break; 2944 #endif /* INCLUDE_BHH */ 2945 #if defined(INCLUDE_MPLS_LM_DM) 2946 case bcmOAMEventMplsLmDmRawData: 2947 buffer = &(oc->pm_mpls_lm_dm_raw_data_info); 2948 break; 2949 #endif /* INCLUDE_MPLS_LM_DM */ 2950 default: 2951 buffer = NULL; 2952 break; 2953 } 2954 return buffer; 2955 } 2956 2957 STATIC void _bcm_fp_oam_pm_event_msg_handle(_bcm_fp_oam_control_t *oc, 2958 mos_msg_data_t *event_msg) 2959 { 2960 bcm_oam_event_type_t event_type = 0; 2961 _bcm_oam_pm_event_handler_t *pm_event_handler_p; 2962 bcm_oam_pm_raw_data_t *raw_data = NULL; 2963 uint8 *dma_buffer = NULL; 2964 int is_updated = 0; 2965 #if defined (INCLUDE_MPLS_LM_DM) 2966 uint32 event_mask; 2967 int sess_id; 2968 uint16 ep_id = 0; 2969 bcm_oam_event_types_t events; 2970 _bcm_oam_event_handler_t *event_handler_p; 2971 #endif 2972 2973 2974 switch (event_msg->s.mclass) { 2975 #if defined(INCLUDE_BHH) 2976 case MOS_MSG_CLASS_BHH_EVENT: 2977 event_type = bcmOAMEventBHHRawData; 2978 break; 2979 #endif /* INCLUDE_BHH */ 2980 #if defined(INCLUDE_MPLS_LM_DM) 2981 case MOS_MSG_CLASS_MPLS_LM_DM_EVENT: 2982 event_mask = bcm_ntohl(event_msg->s.data); 2983 if (event_mask & MPLS_LM_DM_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER) { 2984 event_type = bcmOAMEventMplsLmDmPmCounterRollover; 2985 /* Get data from event message */ 2986 sess_id = (int)bcm_ntohs(event_msg->s.len); 2987 ep_id = _MPLS_LM_DM_SESS_ID_TO_EP_ID(sess_id); 2988 /* Set events */ 2989 sal_memset(&events, 0, sizeof(events)); 2990 LOG_DEBUG(BSL_LS_BCM_OAM, 2991 (BSL_META_U(oc->unit, 2992 "****** OAM PM MPLS_LM_DM Counter Rollover ******\n"))); 2993 if (oc->event_handler_cnt[bcmOAMEventMplsLmDmPmCounterRollover] > 0) { 2994 SHR_BITSET(events.w, bcmOAMEventMplsLmDmPmCounterRollover); 2995 } 2996 } else { 2997 event_type = bcmOAMEventMplsLmDmRawData; 2998 } 2999 break; 3000 #endif /* INCLUDE_MPLS_LM_DM */ 3001 default: 3002 LOG_ERROR(BSL_LS_BCM_OAM, 3003 (BSL_META( 3004 "OAM(unit %d) Error: %s called" 3005 "for unknown protocol" 3006 "- %d.\n"), 3007 oc->unit, FUNCTION_NAME(), event_msg->s.mclass)); 3008 return; 3009 } 3010 3011 if (oc->event_handler_cnt[event_type] <= 0) { 3012 LOG_ERROR(BSL_LS_BCM_OAM, 3013 (BSL_META( 3014 "OAM(unit %d) Error: Received notif for" 3015 "event without callback - %d.\n"), 3016 oc->unit, event_type)); 3017 return; 3018 } 3019 3020 /* Loop over registered callbacks 3021 */ 3022 if (event_type == bcmOAMEventMplsLmDmPmCounterRollover) { 3023 #if defined (INCLUDE_MPLS_LM_DM) 3024 for (event_handler_p = oc->event_handler_list_p; event_handler_p != NULL; 3025 event_handler_p = event_handler_p->next_p) { 3026 if (SHR_BITGET(events.w, event_type)) { 3027 if (SHR_BITGET(event_handler_p->event_types.w, event_type)) { 3028 event_handler_p->cb(oc->unit, 3029 0, event_type, 3030 0, 3031 ep_id, 3032 event_handler_p->user_data); 3033 } 3034 } 3035 } 3036 #endif 3037 } else { 3038 for (pm_event_handler_p = oc->pm_event_handler_list_p; 3039 pm_event_handler_p != NULL; 3040 pm_event_handler_p = pm_event_handler_p->next_p) { 3041 if (SHR_BITGET(pm_event_handler_p->event_types.w, 3042 event_type)) { 3043 raw_data = _bcm_fp_oam_pm_raw_data_info_get(oc->unit, event_type); 3044 dma_buffer = _bcm_fp_oam_pm_dma_buffer_get(oc->unit, event_type); 3045 if (!raw_data) { 3046 /* Should not happen. This would mean you have received 3047 * a PM event for which you have not allocated buffers 3048 * itself. 3049 */ 3050 LOG_ERROR(BSL_LS_BCM_OAM, 3051 (BSL_META_U(oc->unit, 3052 "OAM(unit %d) Error: Oam raw data get failed" 3053 " event - %d.\n"), oc->unit, event_type)); 3054 return; 3055 } 3056 is_updated = _bcm_fp_oam_update_dma_buffer_into_raw_buffer(oc->unit, 3057 event_type, 3058 dma_buffer, 3059 raw_data); 3060 if (is_updated) { 3061 pm_event_handler_p->cb(oc->unit, 3062 event_type, 3063 raw_data, /* The raw data */ 3064 pm_event_handler_p->user_data); 3065 } else { 3066 /* Oops ! The event is lost ! */ 3067 LOG_WARN(BSL_LS_BCM_OAM, 3068 (BSL_META_U(oc->unit, 3069 "OAM(unit %d) Error: PM event missed " 3070 "event - %d.\n"), oc->unit, event_type)); 3071 } 3072 } 3073 } 3074 } 3075 } 3076 3077 /* 3078 * Function: 3079 * bcm_fp_oam_pm_event_register 3080 * Purpose: 3081 * Register a callback for handling OAM PM events 3082 * Parameters: 3083 * unit - (IN) BCM device number 3084 * event_types - (IN) The set of OAM PM events for which the specified 3085 * callback should be called. 3086 * cb - (IN) A pointer to the callback function to call for 3087 * the specified OAM PM events 3088 * user_data - (IN) Pointer to user data to supply in the callback 3089 * Returns: 3090 * BCM_E_XXX 3091 */ 3092 int 3093 bcm_fp_oam_pm_event_register(int unit, bcm_oam_event_types_t event_types, 3094 bcm_oam_pm_event_cb cb, void *user_data) 3095 { 3096 _bcm_fp_oam_control_t *oc; 3097 _bcm_oam_pm_event_handler_t *event_h_p; 3098 _bcm_oam_pm_event_handler_t *prev_p = NULL; 3099 int rv; /* Operation return status. */ 3100 uint16 reply_len = 0; 3101 uint8 msg_class = 0; 3102 uint8 msg_subclass = 0; 3103 uint8 msg_reply_subclass = 0; 3104 uint8 *dma_buffer = NULL; 3105 3106 /* Validate event callback input parameter. */ 3107 if (NULL == cb) { 3108 return (BCM_E_PARAM); 3109 } 3110 3111 /* Validate the event type to be of PM event type */ 3112 if (!(_BCM_FP_OAM_EVENT_TYPE_PM_EVENT(event_types))) { 3113 return (BCM_E_PARAM); 3114 } 3115 3116 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 3117 _BCM_OAM_LOCK(oc); 3118 3119 for (event_h_p = oc->pm_event_handler_list_p; event_h_p != NULL; 3120 event_h_p = event_h_p->next_p) { 3121 if (event_h_p->cb == cb) { 3122 break; 3123 } 3124 prev_p = event_h_p; 3125 } 3126 3127 if (NULL == event_h_p) { 3128 3129 _BCM_OAM_ALLOC(event_h_p, _bcm_oam_pm_event_handler_t, 3130 sizeof(_bcm_oam_pm_event_handler_t), "OAM event handler"); 3131 3132 if (NULL == event_h_p) { 3133 LOG_ERROR(BSL_LS_BCM_OAM, 3134 (BSL_META_U(unit, 3135 "OAM(unit %d) Error: Event handler alloc failed -" 3136 " %s.\n"), unit, bcm_errmsg(BCM_E_MEMORY))); 3137 _BCM_OAM_UNLOCK(oc); 3138 return (BCM_E_MEMORY); 3139 } 3140 3141 event_h_p->next_p = NULL; 3142 event_h_p->cb = cb; 3143 3144 SHR_BITCLR_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount); 3145 if (prev_p != NULL) { 3146 prev_p->next_p = event_h_p; 3147 } else { 3148 oc->pm_event_handler_list_p = event_h_p; 3149 } 3150 } 3151 3152 #if defined(INCLUDE_BHH) 3153 if (SHR_BITGET(event_types.w, bcmOAMEventBHHRawData)) { 3154 if (!SHR_BITGET(event_h_p->event_types.w, bcmOAMEventBHHRawData)) { 3155 /* Add this event to the registered events list. */ 3156 SHR_BITSET(event_h_p->event_types.w, bcmOAMEventBHHRawData); 3157 msg_class = MOS_MSG_CLASS_BHH; 3158 msg_subclass = MOS_MSG_SUBCLASS_BHH_PM_RAW_DATA_EVENT_SET; 3159 msg_reply_subclass = 3160 MOS_MSG_SUBCLASS_BHH_PM_RAW_DATA_EVENT_SET_REPLY; 3161 dma_buffer = oc->pm_bhh_dma_buffer; 3162 rv = _bcm_fp_oam_pm_msg_send_receive(unit, msg_class, 3163 msg_subclass, 3164 0, soc_cm_l2p(unit, dma_buffer), 3165 msg_reply_subclass, 3166 &reply_len); 3167 if(BCM_FAILURE(rv)) { 3168 _BCM_OAM_UNLOCK(oc); 3169 return BCM_E_INTERNAL; 3170 } 3171 } 3172 oc->event_handler_cnt[bcmOAMEventBHHRawData]++; 3173 } 3174 #endif /* INCLUDE_BHH */ 3175 3176 #if defined(INCLUDE_MPLS_LM_DM) 3177 if (oc->mpls_lm_dm_ukernel_ready) { 3178 if (SHR_BITGET(event_types.w, bcmOAMEventMplsLmDmRawData)) { 3179 if (!SHR_BITGET(event_h_p->event_types.w, bcmOAMEventMplsLmDmRawData)) { 3180 /* Add this event to the registered events list. */ 3181 SHR_BITSET(event_h_p->event_types.w, bcmOAMEventMplsLmDmRawData); 3182 msg_class = MOS_MSG_CLASS_MPLS_LM_DM; 3183 msg_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_RAW_DATA_EVENT_SET; 3184 msg_reply_subclass = 3185 MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_RAW_DATA_EVENT_SET_REPLY; 3186 dma_buffer = oc->mpls_lm_dm_dma_buffer; 3187 3188 rv = _bcm_fp_oam_pm_msg_send_receive(unit, msg_class, 3189 msg_subclass, 3190 0, soc_cm_l2p(unit, 3191 dma_buffer), 3192 msg_reply_subclass, 3193 &reply_len); 3194 if(BCM_FAILURE(rv)) { 3195 _BCM_OAM_UNLOCK(oc); 3196 return BCM_E_INTERNAL; 3197 } 3198 } 3199 oc->event_handler_cnt[bcmOAMEventMplsLmDmRawData]++; 3200 } 3201 } 3202 #endif /* INCLUDE_MPLS_LM_DM */ 3203 3204 3205 3206 event_h_p->user_data = user_data; 3207 3208 _BCM_OAM_UNLOCK(oc); 3209 return (BCM_E_NONE); 3210 } 3211 3212 /* 3213 * Function: 3214 * bcm_fp_oam_pm_event_unregister 3215 * Purpose: 3216 * Remove a registered event from the event handler list. 3217 * Parameters: 3218 * unit - (IN) BCM device number 3219 * event_types - (IN) The set of OAM PM events for which the specified 3220 * callback should not be called 3221 * cb - (IN) A pointer to the callback function to unregister 3222 * from the specified OAM PM events 3223 * Returns: 3224 * BCM_E_XXX 3225 */ 3226 int 3227 bcm_fp_oam_pm_event_unregister(int unit, bcm_oam_event_types_t event_types, 3228 bcm_oam_pm_event_cb cb) 3229 { 3230 _bcm_fp_oam_control_t *oc; 3231 _bcm_oam_pm_event_handler_t *event_h_p; 3232 _bcm_oam_pm_event_handler_t *prev_p = NULL; 3233 bcm_oam_event_type_t e_type; 3234 int rv; /* Operation return status. */ 3235 uint8 msg_class = 0; 3236 uint16 reply_len = 0; 3237 uint8 msg_subclass = 0; 3238 uint8 msg_reply_subclass = 0; 3239 3240 /* Validate event callback input parameter. */ 3241 if (NULL == cb) { 3242 return (BCM_E_PARAM); 3243 } 3244 3245 /* Validate the event type to be of PM event type */ 3246 if (!_BCM_FP_OAM_EVENT_TYPE_PM_EVENT(event_types)) { 3247 return (BCM_E_PARAM); 3248 } 3249 3250 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 3251 _BCM_OAM_LOCK(oc); 3252 3253 for (event_h_p = oc->pm_event_handler_list_p; event_h_p != NULL; 3254 event_h_p = event_h_p->next_p) { 3255 if (event_h_p->cb == cb) { 3256 break; 3257 } 3258 prev_p = event_h_p; 3259 } 3260 if (NULL == event_h_p) { 3261 _BCM_OAM_UNLOCK(oc); 3262 return (BCM_E_NOT_FOUND); 3263 } 3264 3265 #if defined(INCLUDE_BHH) 3266 e_type = bcmOAMEventBHHRawData; 3267 if (SHR_BITGET(event_types.w, e_type)) { 3268 if ((oc->event_handler_cnt[e_type] > 0) 3269 && SHR_BITGET(event_h_p->event_types.w, e_type)) { 3270 3271 /* Remove this event from the registered events list. */ 3272 SHR_BITCLR(event_h_p->event_types.w, e_type); 3273 3274 oc->event_handler_cnt[e_type] -= 1; 3275 3276 if (oc->event_handler_cnt[e_type] == 0) { 3277 /* There are no event handlers for this event type 3278 * Send msg to uKernel to stop notifying this event. 3279 */ 3280 if (e_type == bcmOAMEventBHHRawData) { 3281 msg_class = MOS_MSG_CLASS_BHH; 3282 msg_subclass = 3283 MOS_MSG_SUBCLASS_BHH_PM_RAW_DATA_EVENT_UNSET; 3284 msg_reply_subclass = 3285 MOS_MSG_SUBCLASS_BHH_PM_RAW_DATA_EVENT_UNSET_REPLY; 3286 } 3287 rv = _bcm_fp_oam_pm_msg_send_receive 3288 (unit, msg_class, 3289 msg_subclass, 3290 0, 0, 3291 msg_reply_subclass, 3292 &reply_len); 3293 if(BCM_FAILURE(rv)) { 3294 _BCM_OAM_UNLOCK(oc); 3295 return BCM_E_INTERNAL; 3296 } 3297 } 3298 } 3299 } 3300 #endif /* INCLUDE_BHH */ 3301 3302 #if defined(INCLUDE_MPLS_LM_DM) 3303 e_type = bcmOAMEventMplsLmDmRawData; 3304 if (SHR_BITGET(event_types.w, e_type)) { 3305 if ((oc->event_handler_cnt[e_type] > 0) 3306 && SHR_BITGET(event_h_p->event_types.w, e_type)) { 3307 3308 /* Remove this event from the registered events list. */ 3309 SHR_BITCLR(event_h_p->event_types.w, e_type); 3310 3311 oc->event_handler_cnt[e_type] -= 1; 3312 3313 if (oc->event_handler_cnt[e_type] == 0) { 3314 /* There are no event handlers for this event type 3315 * Send msg to uKernel to stop notifying this event. 3316 */ 3317 msg_class = MOS_MSG_CLASS_MPLS_LM_DM; 3318 msg_subclass = 3319 MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_RAW_DATA_EVENT_UNSET; 3320 msg_reply_subclass = 3321 MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_RAW_DATA_EVENT_UNSET_REPLY; 3322 3323 rv = _bcm_fp_oam_pm_msg_send_receive(unit, msg_class, 3324 msg_subclass, 3325 0, 0, 3326 msg_reply_subclass, 3327 &reply_len); 3328 if(BCM_FAILURE(rv)) { 3329 _BCM_OAM_UNLOCK(oc); 3330 return BCM_E_INTERNAL; 3331 } 3332 } 3333 } 3334 } 3335 #endif /* INCLUDE_MPLS_LM_DM */ 3336 3337 if (!_BCM_FP_OAM_EVENT_TYPE_PM_EVENT(event_h_p->event_types)) { 3338 /* No more PM events for this callback registered 3339 Delete the node. */ 3340 if (NULL != prev_p) { 3341 prev_p->next_p = event_h_p->next_p; 3342 3343 } else { 3344 oc->pm_event_handler_list_p = event_h_p->next_p; 3345 } 3346 sal_free(event_h_p); 3347 } 3348 3349 _BCM_OAM_UNLOCK(oc); 3350 return (BCM_E_NONE); 3351 } 3352 3353 #if defined(INCLUDE_MPLS_LM_DM) 3354 /* 3355 * Function: 3356 * _bcm_fp_oam_mpls_lm_dm_pm_callback_thread_func 3357 * Purpose: 3358 * Thread to listen for event messages MPLS LM/DM uC for PM events. 3359 * Parameters: 3360 * oc - Pointer to oam control structures. 3361 * events - the set of events that we are listening. 3362 * Returns: 3363 * None 3364 */ 3365 STATIC void 3366 _bcm_fp_oam_mpls_lm_dm_pm_callback_thread_func(_bcm_fp_oam_control_t *oc, 3367 bcm_oam_event_types_t event_types) 3368 { 3369 int rv; 3370 mos_msg_data_t event_msg; 3371 3372 if (!(BCM_OAM_EVENT_TYPE_GET(event_types, bcmOAMEventMplsLmDmRawData) || 3373 BCM_OAM_EVENT_TYPE_GET(event_types, bcmOAMEventMplsLmDmPmCounterRollover))) { 3374 /* No other event is currently handled here. return. */ 3375 LOG_ERROR(BSL_LS_BCM_OAM, 3376 (BSL_META_U(oc->unit, 3377 "OAM(unit %d) Error: %s called for unknown " 3378 "event.\n"), oc->unit, FUNCTION_NAME())); 3379 return; 3380 } 3381 3382 while (1) { 3383 /* Wait on notifications from uController */ 3384 rv = soc_cmic_uc_msg_receive(oc->unit, oc->mpls_lm_dm_uc_num, 3385 MOS_MSG_CLASS_MPLS_LM_DM_EVENT, 3386 &event_msg, 3387 sal_sem_FOREVER); 3388 3389 if (BCM_FAILURE(rv)) { 3390 break; /* Thread exit */ 3391 } else { 3392 if (event_msg.s.subclass == _MPLS_LM_DM_EVENT_OAM_PM_EVENT) { 3393 _bcm_fp_oam_pm_event_msg_handle(oc, &event_msg); 3394 } else { 3395 LOG_ERROR(BSL_LS_BCM_OAM, 3396 (BSL_META( 3397 "OAM(unit %d) Error: Unknown PM event" 3398 "- %d.\n"), 3399 oc->unit, event_msg.s.subclass)); 3400 } 3401 } 3402 } 3403 3404 oc->mpls_lm_dm_pm_event_thread_id = NULL; 3405 sal_thread_exit(0); 3406 } 3407 3408 STATIC void 3409 _bcm_fp_oam_mpls_lm_dm_pm_thread(void *param) 3410 { 3411 bcm_oam_event_types_t event_types = {{0}}; 3412 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventMplsLmDmRawData); 3413 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventMplsLmDmPmCounterRollover); 3414 3415 _bcm_fp_oam_mpls_lm_dm_pm_callback_thread_func((_bcm_fp_oam_control_t *)param, 3416 event_types); 3417 } 3418 #endif /* INCLUDE_MPLS_LM_DM */ 3419 3420 3421 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */ 3422 /*******************************************************************************/ 3423 /* PM routines for BHH & MPLS LM/DM app start */ 3424 /*******************************************************************************/ 3425 3426 3427 /*******************************************************************************/ 3428 /* BHH Embedded App supporting functions Start */ 3429 /*******************************************************************************/ 3430 #if defined (INCLUDE_BHH) 3431 /* 3432 * Function: 3433 * _bcm_fp_oam_bhh_callback_thread 3434 * Purpose: 3435 * Thread to listen for event messages from uController. 3436 * Parameters: 3437 * param - Pointer to OAM info structure. 3438 * Returns: 3439 * None 3440 */ 3441 STATIC void 3442 _bcm_fp_oam_bhh_callback_thread(void *param) 3443 { 3444 int rv; 3445 _bcm_fp_oam_control_t *oc = (_bcm_fp_oam_control_t *)param; 3446 bcm_oam_event_types_t events; 3447 bcm_oam_event_type_t event_type; 3448 bhh_msg_event_t event_msg; 3449 int sess_id; 3450 uint32 event_mask; 3451 _bcm_oam_event_handler_t *event_handler_p; 3452 _bhh_fp_oam_ep_data_t *h_data_p; 3453 int ep_id = 0; 3454 char thread_name[SAL_THREAD_NAME_MAX_LEN]; 3455 uint8 msg_subclass = 0; 3456 3457 thread_name[0] = 0; 3458 sal_thread_name(oc->event_thread_id, thread_name, sizeof (thread_name)); 3459 3460 while (1) { 3461 /* Wait on notifications from uController */ 3462 rv = soc_cmic_uc_msg_receive(oc->unit, oc->bhh_uc_num, 3463 MOS_MSG_CLASS_BHH_EVENT, &event_msg, 3464 sal_sem_FOREVER); 3465 if (BCM_FAILURE(rv)) { 3466 break; /* Thread exit */ 3467 } 3468 3469 /* Get data from event message */ 3470 sess_id = (int)bcm_ntohs(event_msg.s.len); 3471 ep_id = BCM_OAM_BHH_GET_SDK_EP(sess_id); 3472 3473 msg_subclass = event_msg.s.subclass; 3474 if (msg_subclass == _BHH_EVENT_OAM_PM_EVENT) { 3475 /* Call PM message handling function and continue */ 3476 _bcm_fp_oam_pm_event_msg_handle(oc, &event_msg); 3477 continue; 3478 } 3479 if (sess_id < 0 || 3480 sess_id >= oc->bhh_endpoint_count) { 3481 LOG_CLI((BSL_META_U(oc->unit, 3482 "%s: Invalid sess_id:%d \n"), FUNCTION_NAME(), sess_id)); 3483 continue; 3484 } 3485 3486 /* Check endpoint status. */ 3487 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 3488 if ((BCM_E_EXISTS != rv)) { 3489 /* Endpoint not in use. */ 3490 LOG_ERROR(BSL_LS_BCM_OAM, 3491 (BSL_META("OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 3492 oc->unit, ep_id, bcm_errmsg(rv))); 3493 continue; 3494 } 3495 h_data_p = &oc->bhh_ep_data[sess_id]; 3496 event_mask = bcm_ntohl(event_msg.s.data); 3497 3498 /* Set events */ 3499 sal_memset(&events, 0, sizeof(events)); 3500 3501 if (event_mask & BHH_BTE_EVENT_LB_TIMEOUT) { 3502 LOG_DEBUG(BSL_LS_BCM_OAM, 3503 (BSL_META_U(oc->unit, 3504 "****** OAM BHH LB Timeout ******\n"))); 3505 3506 if (oc->event_handler_cnt[bcmOAMEventBHHLBTimeout] > 0) { 3507 SHR_BITSET(events.w, bcmOAMEventBHHLBTimeout); 3508 } 3509 } 3510 if (event_mask & BHH_BTE_EVENT_LB_DISCOVERY_UPDATE) { 3511 LOG_DEBUG(BSL_LS_BCM_OAM, 3512 (BSL_META_U(oc->unit, 3513 "****** OAM BHH LB Discovery Update ******\n"))); 3514 if (oc->event_handler_cnt[bcmOAMEventBHHLBDiscoveryUpdate] > 0) { 3515 SHR_BITSET(events.w, bcmOAMEventBHHLBDiscoveryUpdate); 3516 } 3517 } 3518 if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT) { 3519 LOG_DEBUG(BSL_LS_BCM_OAM, 3520 (BSL_META_U(oc->unit, 3521 "****** OAM BHH CCM Timeout ******\n"))); 3522 if (oc->event_handler_cnt[bcmOAMEventBHHCCMTimeout] > 0) { 3523 SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeout); 3524 } 3525 } 3526 if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR) { 3527 LOG_DEBUG(BSL_LS_BCM_OAM, 3528 (BSL_META_U(oc->unit, 3529 "****** OAM BHH CCM Timeout Clear ******\n"))); 3530 if (oc->event_handler_cnt[bcmOAMEventBHHCCMTimeoutClear] > 0) { 3531 SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeoutClear); 3532 } 3533 } 3534 if (event_mask & BHH_BTE_EVENT_STATE) { 3535 LOG_DEBUG(BSL_LS_BCM_OAM, 3536 (BSL_META_U(oc->unit, 3537 "****** OAM BHH State ******\n"))); 3538 if (oc->event_handler_cnt[bcmOAMEventBHHCCMState] > 0) { 3539 SHR_BITSET(events.w, bcmOAMEventBHHCCMState); 3540 } 3541 } 3542 if (event_mask & BHH_BTE_EVENT_CCM_RDI) { 3543 LOG_DEBUG(BSL_LS_BCM_OAM, 3544 (BSL_META_U(oc->unit, 3545 "****** OAM BHH CCM RDI ******\n"))); 3546 if (oc->event_handler_cnt[bcmOAMEventBHHCCMRdi] > 0) { 3547 SHR_BITSET(events.w, bcmOAMEventBHHCCMRdi); 3548 } 3549 } 3550 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL) { 3551 LOG_DEBUG(BSL_LS_BCM_OAM, 3552 (BSL_META_U(oc->unit, 3553 "****** OAM BHH CCM Unknown MEG LEVEL ******\n"))); 3554 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegLevel] > 0) { 3555 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevel); 3556 } 3557 } 3558 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID) { 3559 LOG_DEBUG(BSL_LS_BCM_OAM, 3560 (BSL_META_U(oc->unit, 3561 "****** OAM BHH CCM Unknown MEG ID ******\n"))); 3562 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegId] > 0) { 3563 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegId); 3564 } 3565 } 3566 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID) { 3567 LOG_DEBUG(BSL_LS_BCM_OAM, 3568 (BSL_META_U(oc->unit, 3569 "****** OAM BHH CCM Unknown MEP ID ******\n"))); 3570 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMepId] > 0) { 3571 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepId); 3572 } 3573 } 3574 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD) { 3575 LOG_DEBUG(BSL_LS_BCM_OAM, 3576 (BSL_META_U(oc->unit, 3577 "****** OAM BHH CCM Unknown Period ******\n"))); 3578 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPeriod] > 0) { 3579 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriod); 3580 } 3581 } 3582 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY) { 3583 LOG_DEBUG(BSL_LS_BCM_OAM, 3584 (BSL_META_U(oc->unit, 3585 "****** OAM BHH CCM Unknown Priority ******\n"))); 3586 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPriority] > 0) { 3587 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriority); 3588 } 3589 } 3590 if (event_mask & BHH_BTE_EVENT_CCM_RDI_CLEAR) { 3591 LOG_DEBUG(BSL_LS_BCM_OAM, 3592 (BSL_META_U(oc->unit, 3593 "****** OAM BHH CCM RDI Clear ******\n"))); 3594 if (oc->event_handler_cnt[bcmOAMEventBHHCCMRdiClear] > 0) { 3595 SHR_BITSET(events.w, bcmOAMEventBHHCCMRdiClear); 3596 } 3597 } 3598 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR) { 3599 LOG_DEBUG(BSL_LS_BCM_OAM, 3600 (BSL_META_U(oc->unit, 3601 "****** OAM BHH CCM Unknown MEG Level Clear ******\n"))); 3602 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegLevelClear] > 0) { 3603 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevelClear); 3604 } 3605 } 3606 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR) { 3607 LOG_DEBUG(BSL_LS_BCM_OAM, 3608 (BSL_META_U(oc->unit, 3609 "****** OAM BHH CCM Unknown MEG ID Clear ******\n"))); 3610 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegIdClear] > 0) { 3611 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegIdClear); 3612 } 3613 } 3614 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR) { 3615 LOG_DEBUG(BSL_LS_BCM_OAM, 3616 (BSL_META_U(oc->unit, 3617 "****** OAM BHH CCM Unknown MEP ID Clear ******\n"))); 3618 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMepIdClear] > 0) { 3619 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepIdClear); 3620 } 3621 } 3622 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR) { 3623 LOG_DEBUG(BSL_LS_BCM_OAM, 3624 (BSL_META_U(oc->unit, 3625 "****** OAM BHH CCM Unknown Period Clear ******\n"))); 3626 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPeriodClear] > 0) { 3627 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriodClear); 3628 } 3629 } 3630 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR) { 3631 LOG_DEBUG(BSL_LS_BCM_OAM, 3632 (BSL_META_U(oc->unit, 3633 "****** OAM BHH CCM Unknown Priority Clear ******\n"))); 3634 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPriorityClear] > 0) { 3635 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriorityClear); 3636 } 3637 } 3638 if (event_mask & BHH_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER) { 3639 LOG_DEBUG(BSL_LS_BCM_OAM, 3640 (BSL_META_U(oc->unit, 3641 "****** OAM PM BHH Counter Rollover ******\n"))); 3642 3643 if (oc->event_handler_cnt[bcmOAMEventBhhPmCounterRollover] > 0) { 3644 SHR_BITSET(events.w, bcmOAMEventBhhPmCounterRollover); 3645 } 3646 } 3647 if (event_mask & BHH_BTE_EVENT_CSF_LOS) { 3648 LOG_DEBUG(BSL_LS_BCM_OAM, 3649 (BSL_META_U(oc->unit, 3650 "****** OAM BHH CSF LOS ******\n"))); 3651 3652 if (oc->event_handler_cnt[bcmOAMEventCsfLos] > 0) { 3653 SHR_BITSET(events.w, bcmOAMEventCsfLos); 3654 } 3655 } 3656 if (event_mask & BHH_BTE_EVENT_CSF_FDI) { 3657 LOG_DEBUG(BSL_LS_BCM_OAM, 3658 (BSL_META_U(oc->unit, 3659 "****** OAM BHH CSF FDI ******\n"))); 3660 3661 if (oc->event_handler_cnt[bcmOAMEventCsfFdi] > 0) { 3662 SHR_BITSET(events.w, bcmOAMEventCsfFdi); 3663 } 3664 } 3665 if (event_mask & BHH_BTE_EVENT_CSF_RDI) { 3666 LOG_DEBUG(BSL_LS_BCM_OAM, 3667 (BSL_META_U(oc->unit, 3668 "****** OAM BHH CSF RDI ******\n"))); 3669 3670 if (oc->event_handler_cnt[bcmOAMEventCsfRdi] > 0) { 3671 SHR_BITSET(events.w, bcmOAMEventCsfRdi); 3672 } 3673 } 3674 if (event_mask & BHH_BTE_EVENT_CSF_DCI) { 3675 LOG_DEBUG(BSL_LS_BCM_OAM, 3676 (BSL_META_U(oc->unit, 3677 "****** OAM BHH CSF DCI ******\n"))); 3678 3679 if (oc->event_handler_cnt[bcmOAMEventCsfDci] > 0) { 3680 SHR_BITSET(events.w, bcmOAMEventCsfDci); 3681 } 3682 } 3683 /* Loop over registered callbacks, 3684 * If any match the events field, then invoke 3685 */ 3686 for (event_handler_p = oc->event_handler_list_p; 3687 event_handler_p != NULL; 3688 event_handler_p = event_handler_p->next_p) { 3689 for (event_type = bcmOAMEventBHHLBTimeout; event_type < bcmOAMEventCount; ++event_type) { 3690 if (SHR_BITGET(events.w, event_type)) { 3691 if (SHR_BITGET(event_handler_p->event_types.w, 3692 event_type)) { 3693 event_handler_p->cb(oc->unit, 3694 0, 3695 event_type, 3696 h_data_p->group_index, /* Group index */ 3697 ep_id, /* Endpoint index */ 3698 event_handler_p->user_data); 3699 } 3700 } 3701 } 3702 } 3703 } 3704 3705 oc->bhh_event_thread_id = NULL; 3706 LOG_VERBOSE(BSL_LS_BCM_OAM, 3707 (BSL_META_U(oc->unit, 3708 "Thread Exit:%s\n"), thread_name)); 3709 sal_thread_exit(0); 3710 } 3711 3712 STATIC uint8 * 3713 _bcm_fp_oam_ach_header_pack(uint8 *buffer, _ach_header_t *ach) 3714 { 3715 uint32 tmp; 3716 3717 tmp = ((ach->f_nibble & 0xf) << 28) | ((ach->version & 0xf) << 24) | 3718 (ach->reserved << 16) | ach->channel_type; 3719 3720 _BHH_ENCAP_PACK_U32(buffer, tmp); 3721 3722 return (buffer); 3723 } 3724 3725 STATIC uint8 * 3726 _bcm_fp_oam_mpls_label_pack(uint8 *buffer, _mpls_label_t *mpls) 3727 { 3728 uint32 tmp; 3729 3730 tmp = ((mpls->label & 0xfffff) << 12) | ((mpls->exp & 0x7) << 9) | 3731 ((mpls->s & 0x1) << 8) | mpls->ttl; 3732 _BHH_ENCAP_PACK_U32(buffer, tmp); 3733 3734 return (buffer); 3735 } 3736 3737 STATIC uint8 * 3738 _bcm_fp_oam_mpls_label_unpack(uint8 *buffer, _mpls_label_t *mpls) 3739 { 3740 uint32 tmp; 3741 3742 _SHR_UNPACK_U32(buffer, tmp); 3743 mpls->label = (tmp >> 12) & 0xfffff; 3744 mpls->exp = (tmp >> 9) & 0x7; 3745 mpls->s = (tmp >> 8) & 0x1; 3746 mpls->ttl = tmp & 0xffff; 3747 3748 return (buffer); 3749 } 3750 3751 STATIC uint8 * 3752 _bcm_fp_oam_l2_header_pack(bcm_oam_endpoint_type_t type, 3753 uint8 *buffer, _l2_header_t *l2) 3754 { 3755 uint32 tmp; 3756 int i; 3757 3758 for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) { 3759 _BHH_ENCAP_PACK_U8(buffer, l2->dst_mac[i]); 3760 } 3761 3762 for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) { 3763 _BHH_ENCAP_PACK_U8(buffer, l2->src_mac[i]); 3764 } 3765 3766 /* Vlan Tag tpid = 0 indicates untagged */ 3767 if (0 != l2->vlan_tag.tpid) { 3768 tmp = (l2->vlan_tag.tpid << 16) | 3769 ((l2->vlan_tag.tci.prio & 0x7) << 13) | 3770 ((l2->vlan_tag.tci.cfi & 0x1) << 12) | 3771 (l2->vlan_tag.tci.vid & 0xfff); 3772 _BHH_ENCAP_PACK_U32(buffer, tmp); 3773 } 3774 /*Inner Vlan Tag inner_tpid = 0 indicates single tag */ 3775 if (0 != l2->vlan_tag_inner.tpid) { 3776 tmp = (l2->vlan_tag_inner.tpid << 16) | 3777 ((l2->vlan_tag_inner.tci.prio & 0x7) << 13) | 3778 ((l2->vlan_tag_inner.tci.cfi & 0x1) << 12) | 3779 (l2->vlan_tag_inner.tci.vid & 0xfff); 3780 _BHH_ENCAP_PACK_U32(buffer, tmp); 3781 } 3782 _BHH_ENCAP_PACK_U16(buffer, l2->etype); 3783 3784 return (buffer); 3785 } 3786 3787 /* 3788 * Function: 3789 * bcm_fp_oam_mpls_tp_channel_type_tx_get 3790 * Purpose: 3791 * Get MPLS TP(BHH) ACH Channel type 3792 * Parameters: 3793 * unit (IN) BCM device number 3794 * channel_type (IN) Channel type is ignored in XGS devices 3795 * Value (OUT) User define MPLS TP(BHH) ACH channel type 3796 * 3797 * Returns: 3798 * BCM_E_NONE No error 3799 * BCM_E_XXXX Error 3800 */ 3801 int 3802 bcm_fp_oam_mpls_tp_channel_type_tx_get(int unit, 3803 bcm_oam_mpls_tp_channel_type_t channel_type, 3804 int *value) 3805 { 3806 *value = fp_oam_mpls_tp_ach_channel_type; 3807 return BCM_E_NONE; 3808 } 3809 3810 /* 3811 * Function: 3812 * bcm_fp_oam_mpls_tp_channel_type_tx_set 3813 * Purpose: 3814 * Update MPLS TP(BHH) ACH Channel type with user defined value 3815 * Parameters: 3816 * unit (IN) BCM device number 3817 * channel_type (IN) Channel type is ignored in XGS devices 3818 * Value (IN) User define MPLS TP(BHH) ACH channel type 3819 * 3820 * Returns: 3821 * BCM_E_NONE No error 3822 * BCM_E_XXXX Error 3823 */ 3824 int 3825 bcm_fp_oam_mpls_tp_channel_type_tx_set(int unit, 3826 bcm_oam_mpls_tp_channel_type_t channel_type, 3827 int value) 3828 { 3829 uint8 *buffer, *buffer_ptr; 3830 uint16 buffer_len, reply_len; 3831 int rv = BCM_E_NONE; 3832 uint32 *msg; 3833 _bcm_fp_oam_control_t *oc = NULL; /* OAM control structure */ 3834 3835 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 3836 _BCM_OAM_LOCK(oc); 3837 3838 if (oc->ukernel_not_ready) { 3839 _BCM_OAM_UNLOCK(oc); 3840 return BCM_E_INIT; 3841 } 3842 3843 if ((value != SHR_BHH_ACH_CHANNEL_TYPE) && 3844 (value != SHR_BHH_ACH_CHANNEL_TYPE_1)) { 3845 _BCM_OAM_UNLOCK(oc); 3846 return BCM_E_CONFIG; 3847 } 3848 3849 fp_oam_mpls_tp_ach_channel_type = value; 3850 msg = (uint32 *)&fp_oam_mpls_tp_ach_channel_type; 3851 3852 /* Pack control message data into DMA buffer */ 3853 buffer = oc->dma_buffer; 3854 buffer_ptr = bhh_sdk_msg_ctrl_ach_channel_type_msg_pack(buffer, msg); 3855 buffer_len = buffer_ptr - buffer; 3856 3857 rv = _bcm_fp_oam_msg_send_receive( 3858 unit, 3859 MOS_MSG_CLASS_BHH, 3860 MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE, 3861 buffer_len, 0, 3862 MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE_REPLY, 3863 &reply_len); 3864 3865 if (BCM_FAILURE(rv)) { 3866 _BCM_OAM_UNLOCK(oc); 3867 return (rv); 3868 } 3869 3870 _BCM_OAM_UNLOCK(oc); 3871 return BCM_E_NONE; 3872 } 3873 3874 3875 STATIC int 3876 _bcm_fp_oam_ach_header_get(uint32 packet_flags, _ach_header_t *ach) 3877 { 3878 sal_memset(ach, 0, sizeof(*ach)); 3879 3880 ach->f_nibble = SHR_BHH_ACH_FIRST_NIBBLE; 3881 ach->version = SHR_BHH_ACH_VERSION; 3882 ach->reserved = 0; 3883 ach->channel_type = fp_oam_mpls_tp_ach_channel_type; 3884 3885 return (BCM_E_NONE); 3886 } 3887 3888 STATIC int 3889 _bcm_fp_oam_mpls_label_get(uint32 label, uint8 exp, uint8 s, uint8 ttl, 3890 _mpls_label_t *mpls) 3891 { 3892 sal_memset(mpls, 0, sizeof(*mpls)); 3893 3894 mpls->label = label; 3895 mpls->exp = exp & 0x07; 3896 mpls->s = s; 3897 if(ttl){ 3898 mpls->ttl = ttl; 3899 } else { 3900 mpls->ttl = _BHH_MPLS_DFLT_TTL; 3901 } 3902 3903 return (BCM_E_NONE); 3904 } 3905 3906 STATIC int 3907 _bcm_fp_oam_mpls_gal_label_get(_mpls_label_t *mpls, uint8 oam_exp) 3908 { 3909 return _bcm_fp_oam_mpls_label_get(SHR_BHH_MPLS_GAL_LABEL, 3910 oam_exp, 1, 1, mpls); 3911 } 3912 3913 STATIC int 3914 _bcm_fp_oam_mpls_labels_get(int unit, _bhh_fp_oam_ep_data_t *h_data_p, 3915 uint32 packet_flags, 3916 int max_count, 3917 _mpls_label_t *pw_label, 3918 _mpls_label_t *mpls, 3919 int *mpls_count, bcm_if_t *l3_intf_id, uint8 oam_exp, 3920 uint8 oam_ttl) 3921 { 3922 int count = 0; 3923 bcm_l3_egress_t l3_egress; 3924 bcm_mpls_port_t mpls_port; 3925 bcm_mpls_egress_label_t label_array[_BHH_FP_OAM_MPLS_MAX_LABELS]; 3926 bcm_mpls_egress_label_t tmp_label; 3927 int label_count; 3928 int i = 0; 3929 3930 /* Get L3 objects */ 3931 bcm_l3_egress_t_init(&l3_egress); 3932 if (BCM_FAILURE(bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) { 3933 return (BCM_E_PARAM); 3934 } 3935 3936 /* Look for a tunnel associated with this interface */ 3937 if (BCM_SUCCESS 3938 (bcm_esw_mpls_tunnel_initiator_get(unit, l3_egress.intf, 3939 _BHH_FP_OAM_MPLS_MAX_LABELS, 3940 label_array, &label_count))) { 3941 /* We need to sawp the labels configured in tunnel initiator as 3942 it returns labels in reverse order than how it should be in pkt */ 3943 for (i=0; i<(label_count/2); i++) { 3944 sal_memcpy(&tmp_label, &label_array[i], sizeof(tmp_label)); 3945 sal_memcpy(&label_array[i], &label_array[label_count - 1 - i], 3946 sizeof(tmp_label)); 3947 sal_memcpy(&label_array[label_count - 1 - i], &tmp_label, 3948 sizeof(tmp_label)); 3949 } 3950 3951 /* Add VRL Label */ 3952 if (BHH_EP_LSP_TYPE(h_data_p)) { 3953 if ( (l3_egress.mpls_label != BCM_MPLS_LABEL_INVALID) && 3954 (label_count < _BHH_FP_OAM_MPLS_MAX_LABELS) ) { 3955 label_array[label_count].label = l3_egress.mpls_label; 3956 label_array[label_count].exp = l3_egress.mpls_exp; 3957 label_array[label_count].ttl = l3_egress.mpls_ttl; 3958 label_count++; 3959 } 3960 } 3961 /* Traverse through Label stack and match on control label, this 3962 label should be the one just above GAL in the label stack, any 3963 following labels should not be added */ 3964 for (i=0; i < label_count; i++) { 3965 if (label_array[i].label == h_data_p->egr_label) { 3966 /* Set the intended msg type EXP for control Label */ 3967 label_array[i].exp = oam_exp; 3968 if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) && 3969 oam_ttl) { 3970 label_array[i].ttl = oam_ttl; 3971 } 3972 label_count = i; 3973 _bcm_fp_oam_mpls_label_get(label_array[i].label, 3974 label_array[i].exp, 3975 0, 3976 label_array[i].ttl, 3977 &mpls[count++]); 3978 break; 3979 } 3980 _bcm_fp_oam_mpls_label_get(label_array[i].label, 3981 label_array[i].exp, 3982 0, 3983 label_array[i].ttl, 3984 &mpls[count++]); 3985 } 3986 } 3987 3988 /* MPLS Router Alert */ 3989 if (packet_flags & _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT) { 3990 /* Ignore overrun error as RAL is only added for PW MEPs and so overrun 3991 * condition will not exist. 3992 */ 3993 /* coverity[overrun-local] */ 3994 mpls[count].label = SHR_BHH_MPLS_ROUTER_ALERT_LABEL; 3995 mpls[count].exp = 0; 3996 mpls[count].s = 0; 3997 mpls[count].ttl = _BHH_MPLS_DFLT_TTL; 3998 count++; 3999 } 4000 4001 /* Use GPORT to resolve interface */ 4002 if (BCM_GPORT_IS_MPLS_PORT(h_data_p->gport)) { 4003 /* Get mpls port and label info */ 4004 bcm_mpls_port_t_init(&mpls_port); 4005 mpls_port.mpls_port_id = h_data_p->gport; 4006 if (BCM_FAILURE(bcm_esw_mpls_port_get(unit, h_data_p->vpn, 4007 &mpls_port))) { 4008 return (BCM_E_PARAM); 4009 } 4010 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv && 4011 h_data_p->vccv_type == bcmOamBhhVccvTtl) { 4012 mpls_port.egress_label.ttl = 0x1; 4013 } 4014 if (h_data_p->egr_label == mpls_port.egress_label.label) { 4015 mpls_port.egress_label.exp = oam_exp; 4016 if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) && 4017 oam_ttl) { 4018 mpls_port.egress_label.ttl = oam_ttl; 4019 } 4020 } 4021 4022 _bcm_fp_oam_mpls_label_get(mpls_port.egress_label.label, 4023 mpls_port.egress_label.exp, 4024 0, 4025 mpls_port.egress_label.ttl, 4026 &mpls[count++]); 4027 } 4028 4029 4030 /* Set Bottom of Stack if there is no GAL label */ 4031 if (!(packet_flags & _BHH_ENCAP_PKT_GAL)) { 4032 mpls[count-1].s = 1; 4033 } 4034 4035 *mpls_count = count; 4036 4037 return (BCM_E_NONE); 4038 4039 } 4040 4041 STATIC int 4042 _bcm_fp_oam_l2_header_get(int unit, _bhh_fp_oam_ep_data_t *h_data_p, 4043 bcm_port_t port, uint16 etype, 4044 _l2_header_t *l2, uint8 *lm_pdu_counter_offset) 4045 { 4046 uint16 tpid; 4047 bcm_l3_egress_t l3_egress; 4048 bcm_l3_intf_t l3_intf; 4049 bcm_vlan_control_vlan_t vc; 4050 int tpid_select; 4051 bcm_pbmp_t pbmp, ubmp; 4052 4053 sal_memset(l2, 0, sizeof(*l2)); 4054 4055 if (!BHH_EP_MPLS_SECTION_TYPE(h_data_p)) { 4056 /* Get L3 interfaces */ 4057 bcm_l3_egress_t_init(&l3_egress); 4058 bcm_l3_intf_t_init(&l3_intf); 4059 4060 if (BCM_FAILURE 4061 (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) { 4062 return (BCM_E_PARAM); 4063 } 4064 4065 l3_intf.l3a_intf_id = l3_egress.intf; 4066 if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) { 4067 return (BCM_E_PARAM); 4068 } 4069 4070 /* Get TPID */ 4071 BCM_IF_ERROR_RETURN( 4072 bcm_esw_vlan_control_port_get(unit, 4073 port, 4074 bcmVlanPortOuterTpidSelect, 4075 &tpid_select)); 4076 if (tpid_select == BCM_PORT_OUTER_TPID) { 4077 BCM_IF_ERROR_RETURN(bcm_esw_port_tpid_get(unit, port, &tpid)); 4078 } else { 4079 BCM_IF_ERROR_RETURN( 4080 bcm_esw_vlan_control_vlan_get(unit, l3_intf.l3a_vid, &vc)); 4081 tpid = vc.outer_tpid; 4082 } 4083 4084 sal_memcpy(l2->dst_mac, l3_egress.mac_addr, _BHH_MAC_ADDR_LENGTH); 4085 sal_memcpy(l2->src_mac, l3_intf.l3a_mac_addr, _BHH_MAC_ADDR_LENGTH); 4086 *lm_pdu_counter_offset += 2*_BHH_MAC_ADDR_LENGTH; 4087 l2->vlan_tag.tpid = tpid; 4088 l2->vlan_tag.tci.prio = h_data_p->vlan_pri; 4089 l2->vlan_tag.tci.cfi = 0; 4090 l2->vlan_tag.tci.vid = l3_intf.l3a_vid; 4091 *lm_pdu_counter_offset += 4; 4092 4093 BCM_IF_ERROR_RETURN(bcm_esw_vlan_port_get(unit, 4094 l2->vlan_tag.tci.vid, 4095 &pbmp, 4096 &ubmp)); 4097 if (BCM_PBMP_MEMBER(ubmp, port)) { 4098 l2->vlan_tag.tpid = 0; /* Set to 0 to indicate untagged */ 4099 } 4100 4101 if (l3_intf.l3a_inner_vlan != 0) { 4102 BCM_IF_ERROR_RETURN(bcm_esw_port_inner_tpid_get(unit, port, &tpid)); 4103 l2->vlan_tag_inner.tpid = tpid; 4104 l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri; 4105 l2->vlan_tag_inner.tci.cfi = 0; 4106 l2->vlan_tag_inner.tci.vid = l3_intf.l3a_inner_vlan; 4107 *lm_pdu_counter_offset += 4; 4108 } 4109 }else { 4110 sal_memcpy(l2->dst_mac, h_data_p->dst_mac_address, _BHH_MAC_ADDR_LENGTH); 4111 sal_memcpy(l2->src_mac, h_data_p->src_mac_address, _BHH_MAC_ADDR_LENGTH); 4112 *lm_pdu_counter_offset += 2*_BHH_MAC_ADDR_LENGTH; 4113 if((h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterVlan) || 4114 (h_data_p->type == bcmOAMEndpointTypeBhhSectionInnervlan) || 4115 (h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)){ 4116 if (h_data_p->vlan != 0) { 4117 l2->vlan_tag.tpid = h_data_p->outer_tpid; 4118 l2->vlan_tag.tci.prio = h_data_p->vlan_pri; 4119 l2->vlan_tag.tci.cfi = 0; 4120 l2->vlan_tag.tci.vid = h_data_p->vlan; 4121 *lm_pdu_counter_offset += 4; 4122 } 4123 } 4124 if((h_data_p->type == bcmOAMEndpointTypeBhhSectionInnervlan) || 4125 (h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)){ 4126 l2->vlan_tag_inner.tpid = h_data_p->inner_tpid; 4127 l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri; 4128 l2->vlan_tag_inner.tci.cfi = 0; 4129 l2->vlan_tag_inner.tci.vid = h_data_p->inner_vlan; 4130 *lm_pdu_counter_offset += 4; 4131 } 4132 etype = SHR_BHH_L2_ETYPE_MPLS_UCAST; 4133 } 4134 l2->etype = etype; 4135 *lm_pdu_counter_offset += 2; 4136 4137 return (BCM_E_NONE); 4138 } 4139 4140 /* 4141 * Function: 4142 * _bcm_fp_oam_encap_data_dump 4143 * Purpose: 4144 * Dumps buffer contents. 4145 * Parameters: 4146 * buffer - (IN) Buffer to dump data. 4147 * length - (IN) Length of buffer. 4148 * Returns: 4149 * None 4150 */ 4151 void 4152 _bcm_fp_oam_encap_data_dump(uint8 *buffer, int length) 4153 { 4154 int i; 4155 4156 LOG_CLI((BSL_META("\nBHH encapsulation (length=%d):\n"), length)); 4157 4158 for (i = 0; i < length; i++) { 4159 if ((i % 16) == 0) { 4160 LOG_CLI((BSL_META("\n"))); 4161 } 4162 LOG_CLI((BSL_META(" %02x"), buffer[i])); 4163 } 4164 4165 LOG_CLI((BSL_META("\n"))); 4166 return; 4167 } 4168 4169 /* 4170 * Function: 4171 * _bcm_fp_oam_olp_tx_header_create 4172 * Purpose: 4173 * Adds OLP Tx header packet to encapsulation. 4174 * Parameters: 4175 * unit - (IN) Unit number. 4176 * mod - (IN) module Id. 4177 * port_id - (IN) port Id. 4178 * ts_mode - (IN) Timestamp type for DM PDU. 4179 * lm_pdu_counter_offset - (IN) Counter offset in LM PDU. 4180 * encap_data - (OUT) Buffer returning MPLS OAM encapsulation. 4181 * encap_length - (OUT) Buffer length which contains 4182 * MPLS OAM encapsulation length. 4183 * int_pri - (IN) INT_PRI of OAM message. 4184 * Returns: 4185 * BCM_E_XXX 4186 * Notes: 4187 * The returning MPLS OAM encapsulation buffer includes 4188 * OLP TX header. 4189 */ 4190 4191 STATIC int 4192 _bcm_fp_oam_olp_tx_header_create(int unit, 4193 bcm_module_t mod, bcm_port_t port_id, 4194 uint8 counter_size, 4195 uint32 *counter_base_id, 4196 uint32 *counter_offset, 4197 int *counter_action, 4198 uint32 *counter_byte_offset, 4199 uint8 ts_mode, 4200 uint8 lm_pdu_counter_offset, 4201 uint8 *encap_data, 4202 uint16 *encap_length, 4203 bcm_cos_t int_pri) 4204 { 4205 int rv = 0, i; 4206 soc_olp_l2_hdr_t olp_l2_header; 4207 soc_olp_tx_hdr_t olp_oam_header; 4208 uint8 *buffer_p = encap_data; 4209 bcm_stat_group_mode_t stat_group; 4210 bcm_stat_object_t stat_object; 4211 uint32 stat_mode; 4212 uint32 stat_pool_number; 4213 uint32 base_index; 4214 bcm_module_t my_modid = 0; 4215 bcm_gport_t cpu_dglp; 4216 4217 4218 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 4219 BCM_IF_ERROR_RETURN(_bcm_esw_glp_construct(unit, BCM_TRUNK_INVALID, my_modid, 4220 CMIC_PORT(unit), &cpu_dglp)); 4221 /* Get OLP L2 Header for CPU port */ 4222 sal_memset(&olp_l2_header, 0, sizeof(olp_l2_header)); 4223 rv = _bcm_olp_l2_hdr_get(unit, cpu_dglp, 0, &olp_l2_header); 4224 if (BCM_FAILURE(rv)) { 4225 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 4226 "OLP Header get failed.\n"))); 4227 return (rv); 4228 } 4229 buffer_p = _bcm_fp_oam_olp_l2_header_pack(buffer_p, &olp_l2_header); 4230 4231 sal_memset(&olp_oam_header, 0, sizeof(olp_oam_header)); 4232 /* Set Port number */ 4233 SOC_OLP_TX_PORT(&olp_oam_header) = port_id; 4234 SOC_OLP_TX_MODID(&olp_oam_header) = mod; 4235 SOC_OLP_TX_PRI(&olp_oam_header) = int_pri; 4236 4237 for (i=0; i< counter_size; i++) { 4238 4239 _bcm_esw_stat_get_counter_id_info(unit, counter_base_id[i], 4240 &stat_group, &stat_object, 4241 &stat_mode, &stat_pool_number, 4242 &base_index); 4243 if (i == 0) { 4244 SOC_OLP_TX_CTR1_ID(&olp_oam_header) = 4245 SOC_OLP_TX_CTR(stat_pool_number, 4246 (base_index + counter_offset[i])); 4247 SOC_OLP_TX_CTR1_ACTION(&olp_oam_header) = 4248 counter_action[i]; 4249 /* Counter location is Egress */ 4250 SOC_OLP_TX_CTR1_LOCATION(&olp_oam_header) = 1; 4251 } 4252 if (i == 1) { 4253 SOC_OLP_TX_CTR2_ID_SET(&olp_oam_header, 4254 SOC_OLP_TX_CTR(stat_pool_number, 4255 (base_index + counter_offset[i]))); 4256 SOC_OLP_TX_CTR2_ACTION(&olp_oam_header) = 4257 counter_action[i]; 4258 SOC_OLP_TX_CTR2_LOCATION(&olp_oam_header) = 1; 4259 } 4260 if (i == 2) { 4261 SOC_OLP_TX_CTR3_ID_SET(&olp_oam_header, 4262 SOC_OLP_TX_CTR(stat_pool_number, 4263 (base_index + counter_offset[i]))); 4264 SOC_OLP_TX_CTR3_ACTION(&olp_oam_header) = 4265 counter_action[i]; 4266 SOC_OLP_TX_CTR3_LOCATION(&olp_oam_header) = 1; 4267 } 4268 } 4269 if(lm_pdu_counter_offset){ 4270 /* COUNTER OFFSET in OLP Header = 4271 * (L2 Encap + Counter field offset in MPLS OAM Header - 14)/2 4272 */ 4273 SOC_OLP_TX_OAM_OFFSET(&olp_oam_header) = 4274 (lm_pdu_counter_offset - 14) >> 1; 4275 } 4276 4277 SOC_OLP_TX_TIMESTAMP_ACTION(&olp_oam_header) = ts_mode; 4278 4279 /* Pack OLP OAM Encap */ 4280 buffer_p = shr_olp_tx_header_pack(buffer_p, &olp_oam_header); 4281 *encap_length += (buffer_p - encap_data); 4282 4283 #ifdef _BHH_DEBUG_DUMP 4284 _bcm_fp_oam_encap_data_dump(encap_data, *encap_length); 4285 #endif 4286 return rv; 4287 } 4288 4289 /* 4290 * Function: 4291 * _bcm_fp_oam_encap_build_pack 4292 * Purpose: 4293 * Builds and packs the MPLS OAM packet encapsulation for a given 4294 * tunnel type. 4295 * Parameters: 4296 * unit - (IN) Unit number. 4297 * mod - (IN) Module. 4298 * port - (IN) Port. 4299 * endpoint_config - (IN/OUT) Pointer to endpoint structure. 4300 * packet_flags - (IN) Flags for building packet. 4301 * buffer - (OUT) Buffer returning encapsulation. 4302 * counter_info - (IN/OUT) Pointer to LM counter info. 4303 * int_pri - (IN) INT_PRI of OAM message. 4304 * Returns: 4305 * BCM_E_XXX 4306 * Notes: 4307 * The returning BHH encapsulation includes only all the 4308 * encapsulation headers/labels and does not include 4309 * the BHH control packet. 4310 */ 4311 STATIC int 4312 _bcm_fp_oam_encap_build_pack(int unit, bcm_module_t mod, bcm_port_t port, 4313 _bhh_fp_oam_ep_data_t *h_data_p, 4314 uint32 packet_flags, 4315 uint8 *buffer, 4316 uint16 *encap_length, 4317 _bhh_oam_lm_dm_info_t *counter_info, 4318 bcm_cos_t int_pri, uint8 oam_exp, 4319 uint8 oam_ttl) 4320 { 4321 uint8 *cur_ptr = buffer; 4322 uint16 etype = 0; 4323 bcm_if_t l3_intf_id = -1; 4324 _ach_header_t ach; 4325 _mpls_label_t mpls_gal; 4326 _mpls_label_t mpls_labels[_BHH_MPLS_MAX_LABELS]; 4327 _mpls_label_t pw_label; 4328 int mpls_count = 0; 4329 _l2_header_t l2; 4330 int i; 4331 4332 /* 4333 * Get necessary headers/labels information. 4334 * 4335 * Following order is important since some headers/labels 4336 * may depend on previous header/label information. 4337 */ 4338 if (packet_flags & _BHH_ENCAP_PKT_G_ACH) { 4339 BCM_IF_ERROR_RETURN 4340 (_bcm_fp_oam_ach_header_get(packet_flags, &ach)); 4341 counter_info->oam_replacement_offset += 4; 4342 } 4343 4344 if (packet_flags & _BHH_ENCAP_PKT_GAL) { 4345 if (h_data_p->egr_label == SHR_BHH_MPLS_GAL_LABEL) { 4346 BCM_IF_ERROR_RETURN 4347 (_bcm_fp_oam_mpls_gal_label_get(&mpls_gal, 4348 h_data_p->egr_label_exp)); 4349 } else { 4350 BCM_IF_ERROR_RETURN 4351 (_bcm_fp_oam_mpls_gal_label_get(&mpls_gal, 0)); 4352 } 4353 counter_info->oam_replacement_offset += 4; 4354 } 4355 4356 if (packet_flags & _BHH_ENCAP_PKT_MPLS) { 4357 etype = SHR_BHH_L2_ETYPE_MPLS_UCAST; 4358 BCM_IF_ERROR_RETURN 4359 (_bcm_fp_oam_mpls_labels_get(unit, h_data_p, 4360 packet_flags, 4361 _BHH_FP_OAM_MPLS_MAX_LABELS, 4362 &pw_label, 4363 mpls_labels, 4364 &mpls_count, 4365 &l3_intf_id, 4366 oam_exp, oam_ttl)); 4367 counter_info->oam_replacement_offset += (mpls_count *4); 4368 } 4369 4370 /* Always build L2 Header */ 4371 BCM_IF_ERROR_RETURN 4372 (_bcm_fp_oam_l2_header_get(unit, 4373 h_data_p, 4374 port, 4375 etype, 4376 &l2, 4377 &counter_info->oam_replacement_offset)); 4378 _bcm_fp_oam_olp_tx_header_create(unit, mod, port, 4379 counter_info->counter_size, 4380 counter_info->counter_base_id, 4381 counter_info->counter_offset, 4382 counter_info->counter_action, 4383 counter_info->byte_count_offset, 4384 counter_info->ts_mode, 4385 counter_info->oam_replacement_offset, 4386 buffer, 4387 encap_length, int_pri); 4388 /* 4389 * Pack header/labels into given buffer (network packet format). 4390 * 4391 * Following packing order must be followed to correctly 4392 * build the packet encapsulation. 4393 */ 4394 cur_ptr = buffer + *encap_length; 4395 4396 /* L2 Header is always present */ 4397 cur_ptr = _bcm_fp_oam_l2_header_pack(h_data_p->type, cur_ptr, &l2); 4398 4399 if (packet_flags & _BHH_ENCAP_PKT_MPLS) { 4400 for (i = 0;i < mpls_count;i++) { 4401 cur_ptr = _bcm_fp_oam_mpls_label_pack(cur_ptr, &mpls_labels[i]); 4402 } 4403 } 4404 4405 if (packet_flags & _BHH_ENCAP_PKT_GAL) { 4406 cur_ptr = _bcm_fp_oam_mpls_label_pack(cur_ptr, &mpls_gal); 4407 } 4408 4409 if (packet_flags & _BHH_ENCAP_PKT_G_ACH) { 4410 cur_ptr = _bcm_fp_oam_ach_header_pack(cur_ptr, &ach); 4411 } 4412 4413 #ifdef _BHH_DEBUG_DUMP 4414 _bcm_fp_oam_encap_data_dump(buffer, *encap_length); 4415 #endif 4416 4417 /* Set BHH encapsulation length */ 4418 *encap_length = cur_ptr - buffer; 4419 4420 return (BCM_E_NONE); 4421 } 4422 4423 void 4424 _bcm_fp_oam_bhh_hash_data_dump(int unit, _bhh_fp_oam_ep_data_t *h_data_p) 4425 { 4426 int i = 0; 4427 LOG_CLI((BSL_META_U(unit,"Type = %d\r\n"),h_data_p->type)); 4428 LOG_CLI((BSL_META_U(unit,"EP ID = %d\r\n"),h_data_p->ep_id)); 4429 LOG_CLI((BSL_META_U(unit,"Remote = %d\r\n"),h_data_p->is_remote)); 4430 LOG_CLI((BSL_META_U(unit,"Name = %d\r\n"),h_data_p->name)); 4431 LOG_CLI((BSL_META_U(unit,"Level = %d\r\n"),h_data_p->level)); 4432 LOG_CLI((BSL_META_U(unit,"Outer Vlan = %d\r\n"),h_data_p->vlan)); 4433 LOG_CLI((BSL_META_U(unit,"Inner Vlan = %d\r\n"),h_data_p->inner_vlan)); 4434 LOG_CLI((BSL_META_U(unit,"Gport = %d\r\n"),h_data_p->gport)); 4435 LOG_CLI((BSL_META_U(unit,"SGLP = %d\r\n"),h_data_p->sglp)); 4436 LOG_CLI((BSL_META_U(unit,"DGLP = %d\r\n"),h_data_p->dglp)); 4437 LOG_CLI((BSL_META_U(unit,"Grp idx = %d\r\n"),h_data_p->group_index)); 4438 LOG_CLI((BSL_META_U(unit,"VP = %d\r\n"),h_data_p->vp)); 4439 LOG_CLI((BSL_META_U(unit,"Flags = 0x%x\r\n"),h_data_p->flags)); 4440 LOG_CLI((BSL_META_U(unit,"Flags2 = 0x%x\r\n"),h_data_p->flags2)); 4441 LOG_CLI((BSL_META_U(unit,"Period = %d\r\n"),h_data_p->period)); 4442 LOG_CLI((BSL_META_U(unit,"Label = 0x%x\r\n"),h_data_p->label)); 4443 LOG_CLI((BSL_META_U(unit,"Vlan Pri = %d\r\n"),h_data_p->vlan_pri)); 4444 LOG_CLI((BSL_META_U(unit,"Egress if = 0x%x\r\n"),h_data_p->egress_if)); 4445 LOG_CLI((BSL_META_U(unit,"Outer TPID = 0x%04X\r\n"),h_data_p->outer_tpid)); 4446 LOG_CLI((BSL_META_U(unit,"Inner TPID = 0x%04X\r\n"),h_data_p->inner_tpid)); 4447 LOG_CLI((BSL_META_U(unit,"Trunk ID = %d\r\n"),h_data_p->trunk_id)); 4448 LOG_CLI((BSL_META_U(unit,"Trunk Index = %d\r\n"),h_data_p->trunk_index)); 4449 LOG_CLI((BSL_META_U(unit,"Src Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"), 4450 h_data_p->src_mac_address[0], h_data_p->src_mac_address[1], 4451 h_data_p->src_mac_address[2], h_data_p->src_mac_address[3], 4452 h_data_p->src_mac_address[4], h_data_p->src_mac_address[5])); 4453 LOG_CLI((BSL_META_U(unit,"Dst Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"), 4454 h_data_p->dst_mac_address[0], h_data_p->dst_mac_address[1], 4455 h_data_p->dst_mac_address[2], h_data_p->dst_mac_address[3], 4456 h_data_p->dst_mac_address[4], h_data_p->dst_mac_address[5])); 4457 LOG_CLI((BSL_META_U(unit,"Inner vlan pri = %d\r\n"), 4458 h_data_p->inner_vlan_pri)); 4459 LOG_CLI((BSL_META_U(unit,"Vccv Type = %d\r\n"),h_data_p->vccv_type)); 4460 LOG_CLI((BSL_META_U(unit,"VPN = %d\r\n"),h_data_p->vpn)); 4461 LOG_CLI((BSL_META_U(unit,"PM profile attached = %d\r\n"), 4462 h_data_p->pm_profile_attached)); 4463 LOG_CLI((BSL_META_U(unit,"BHH Session Id = %u\r\n"), 4464 h_data_p->uc_session_id)); 4465 LOG_CLI((BSL_META_U(unit,"BHH CCM counter info :\n"))); 4466 LOG_CLI((BSL_META_U(unit,"BHH CCM counter size = %u\r\n"), 4467 h_data_p->ccm_tx_counter_size)); 4468 for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) 4469 { 4470 LOG_CLI((BSL_META_U(unit,"BHH counter %d base Id = %u\r\n"), 4471 i, h_data_p->ccm_tx_update_lm_counter_base_id[i])); 4472 LOG_CLI((BSL_META_U(unit,"BHH counter %d offset = %u\r\n"), 4473 i, h_data_p->ccm_tx_update_lm_counter_offset[i])); 4474 } 4475 LOG_CLI((BSL_META_U(unit,"BHH LM counter info :\n"))); 4476 LOG_CLI((BSL_META_U(unit,"BHH LM counter size = %u\r\n"), 4477 h_data_p->lm_counter_size)); 4478 for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) 4479 { 4480 LOG_CLI((BSL_META_U(unit,"BHH counter %d base Id = %u\r\n"), 4481 i, h_data_p->lm_counter_base_id[i])); 4482 LOG_CLI((BSL_META_U(unit,"BHH counter %d offset = %u\r\n"), 4483 i, h_data_p->lm_counter_offset[i])); 4484 LOG_CLI((BSL_META_U(unit,"BHH counter %d action = %u\r\n"), 4485 i, h_data_p->lm_counter_action[i])); 4486 } 4487 LOG_CLI((BSL_META_U(unit,"BHH DM counter info :\n"))); 4488 LOG_CLI((BSL_META_U(unit,"BHH DM counter size = %u\r\n"), 4489 h_data_p->dm_tx_counter_size)); 4490 for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) 4491 { 4492 LOG_CLI((BSL_META_U(unit,"BHH counter %d base Id = %u\r\n"), 4493 i, h_data_p->dm_tx_update_lm_counter_base_id[i])); 4494 LOG_CLI((BSL_META_U(unit,"BHH counter %d offset = %u\r\n"), 4495 i, h_data_p->dm_tx_update_lm_counter_offset[i])); 4496 } 4497 LOG_CLI((BSL_META_U(unit,"BHH LB counter info :\n"))); 4498 LOG_CLI((BSL_META_U(unit,"BHH LB counter size = %u\r\n"), 4499 h_data_p->lb_tx_counter_size)); 4500 for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) 4501 { 4502 LOG_CLI((BSL_META_U(unit,"BHH counter %d base Id = %u\r\n"), 4503 i, h_data_p->lb_tx_update_lm_counter_base_id[i])); 4504 LOG_CLI((BSL_META_U(unit,"BHH counter %d offset = %u\r\n"), 4505 i, h_data_p->lb_tx_update_lm_counter_offset[i])); 4506 } 4507 LOG_CLI((BSL_META_U(unit,"HW session ID = %d\r\n"), 4508 h_data_p->hw_session_id)); 4509 LOG_CLI((BSL_META_U(unit,"HW no of session entries = %d\r\n"), 4510 h_data_p->hw_session_num_entries)); 4511 LOG_CLI((BSL_META_U(unit,"Resolved trunk gport based on trunk " 4512 "index 0x%x\r\n"), 4513 h_data_p->resolved_trunk_gport)); 4514 } 4515 4516 /* 4517 * Function: 4518 * _bcm_fp_oam_bhh_encap_create 4519 * Purpose: 4520 * Creates a BHH packet encapsulation. 4521 * Parameters: 4522 * unit - (IN) Unit number. 4523 * mod - (IN) Module. 4524 * port_id - (IN) Port. 4525 * endpoint_config - (IN/OUT) Pointer to endpoint structure. 4526 * encap_data - (OUT) Buffer returning encapsulation. 4527 * counter_info - (IN/OUT) Pointer to LM counter info. 4528 * int_pri - (IN) INT_PRI of OAM message. 4529 * Returns: 4530 * BCM_E_XXX 4531 * Notes: 4532 * The returning BHH encapsulation buffer includes all the 4533 * corresponding headers/labels EXCEPT for the BHH control packet. 4534 */ 4535 STATIC int 4536 _bcm_fp_oam_bhh_encap_create(int unit, bcm_module_t mod, 4537 bcm_port_t port_id, 4538 _bhh_fp_oam_ep_data_t *h_data_p, 4539 uint8 *encap_data, 4540 uint8 *encap_type, 4541 uint16 *encap_length, 4542 _bhh_oam_lm_dm_info_t *counter_info, 4543 bcm_cos_t int_pri, uint8 oam_exp, 4544 uint8 oam_ttl) 4545 { 4546 uint32 packet_flags; 4547 _bcm_fp_oam_control_t *oc; 4548 4549 packet_flags = 0; 4550 4551 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 4552 4553 /* 4554 * Get BHH encapsulation packet format flags 4555 4556 * Also, perform the following for each BHH tunnel type: 4557 * - Check for valid parameter values 4558 * - Set specific values required by the BHH tunnel definition 4559 * (e.g. such as ttl=1,...) 4560 */ 4561 switch (h_data_p->type) { 4562 case bcmOAMEndpointTypeBHHMPLS: 4563 packet_flags |= 4564 (_BHH_ENCAP_PKT_MPLS | 4565 _BHH_ENCAP_PKT_GAL | 4566 _BHH_ENCAP_PKT_G_ACH); 4567 break; 4568 4569 case bcmOAMEndpointTypeBHHMPLSVccv: 4570 switch(h_data_p->vccv_type) { 4571 4572 case bcmOamBhhVccvChannelAch: 4573 packet_flags |= 4574 (_BHH_ENCAP_PKT_MPLS | 4575 _BHH_ENCAP_PKT_PW | 4576 _BHH_ENCAP_PKT_G_ACH); 4577 break; 4578 4579 case bcmOamBhhVccvRouterAlert: 4580 packet_flags |= 4581 (_BHH_ENCAP_PKT_MPLS | 4582 _BHH_ENCAP_PKT_PW | 4583 _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT | 4584 _BHH_ENCAP_PKT_G_ACH); 4585 break; 4586 4587 case bcmOamBhhVccvTtl: 4588 packet_flags |= 4589 (_BHH_ENCAP_PKT_MPLS | 4590 _BHH_ENCAP_PKT_PW | 4591 _BHH_ENCAP_PKT_G_ACH); 4592 break; 4593 4594 case bcmOamBhhVccvGal13: 4595 packet_flags |= 4596 (_BHH_ENCAP_PKT_MPLS | 4597 _BHH_ENCAP_PKT_PW | 4598 _BHH_ENCAP_PKT_GAL | 4599 _BHH_ENCAP_PKT_G_ACH); 4600 break; 4601 4602 default: 4603 return (BCM_E_PARAM); 4604 break; 4605 } 4606 break; 4607 4608 case bcmOAMEndpointTypeBhhSection: 4609 case bcmOAMEndpointTypeBhhSectionInnervlan: 4610 case bcmOAMEndpointTypeBhhSectionOuterVlan: 4611 case bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan: 4612 packet_flags |= 4613 (_BHH_ENCAP_PKT_GAL | 4614 _BHH_ENCAP_PKT_G_ACH); 4615 break; 4616 default: 4617 return (BCM_E_PARAM); 4618 } 4619 4620 /* Build header/labels and pack in buffer */ 4621 BCM_IF_ERROR_RETURN 4622 (_bcm_fp_oam_encap_build_pack(unit, mod, port_id, 4623 h_data_p, 4624 packet_flags, 4625 encap_data, 4626 encap_length, counter_info, int_pri, 4627 oam_exp, oam_ttl)); 4628 4629 /* Set encap type (indicates uC side that checksum is required) */ 4630 *encap_type = SHR_BHH_ENCAP_TYPE_RAW; 4631 4632 #ifdef _BHH_DEBUG_DUMP 4633 _bcm_fp_oam_encap_data_dump(encap_data, *encap_length); 4634 #endif 4635 4636 if (*encap_length > oc->bhh_max_encap_length) { 4637 LOG_ERROR(BSL_LS_BCM_OAM, 4638 (BSL_META_U(unit, 4639 "OAM(unit %d) Error: Encap length greater than max," 4640 "encap_length=%u max=%u\n"), 4641 unit, *encap_length, oc->bhh_max_encap_length)); 4642 return BCM_E_CONFIG; 4643 } 4644 4645 return (BCM_E_NONE); 4646 } 4647 4648 /* 4649 * Function: 4650 * _bhh_fp_oam_ep_hash_key_construct 4651 * Purpose: 4652 * Construct hash table key for a given endpoint information. 4653 * Parameters: 4654 * unit - (IN) BCM device number 4655 * oc - (IN) Pointer to OAM control structure. 4656 * ep_info - (IN) Pointer to endpoint information structure. 4657 * key - (IN/OUT) Pointer to hash key buffer. 4658 * Retruns: 4659 * None 4660 */ 4661 STATIC void 4662 _bhh_fp_oam_ep_hash_key_construct(int unit, 4663 _bcm_fp_oam_control_t *oc, 4664 bcm_oam_endpoint_info_t *ep_info, 4665 _bhh_fp_oam_hash_key_t *key) 4666 { 4667 uint8 *loc = *key; 4668 4669 sal_memset(key, 0, sizeof(_bhh_fp_oam_hash_key_t)); 4670 4671 if (NULL != ep_info) { 4672 _BCM_OAM_KEY_PACK(loc, &ep_info->group, sizeof(ep_info->group)); 4673 4674 _BCM_OAM_KEY_PACK(loc, &ep_info->name, sizeof(ep_info->name)); 4675 4676 _BCM_OAM_KEY_PACK(loc, &ep_info->gport, sizeof(ep_info->gport)); 4677 4678 _BCM_OAM_KEY_PACK(loc, &ep_info->level, sizeof(ep_info->level)); 4679 4680 _BCM_OAM_KEY_PACK(loc, &ep_info->vlan, sizeof(ep_info->vlan)); 4681 4682 _BCM_OAM_KEY_PACK(loc, &ep_info->inner_vlan, 4683 sizeof(ep_info->inner_vlan)); 4684 _BCM_OAM_KEY_PACK(loc, &ep_info->mpls_label, 4685 sizeof(ep_info->mpls_label)); 4686 } 4687 4688 /* End address should not exceed size of _bcm_oam_hash_key_t. */ 4689 assert ((int) (loc - *key) <= sizeof(_bhh_fp_oam_hash_key_t)); 4690 } 4691 4692 #if defined(BCM_WARM_BOOT_SUPPORT) 4693 /* 4694 * Function: 4695 * _bcm_fp_oam_bhh_scache_alloc 4696 * Purpose: 4697 * Allocate scache memory for BHH module 4698 * Parameters: 4699 * unit - (IN) BCM device number 4700 * Returns: 4701 * BCM_E_UNIT - Invalid BCM unit number. 4702 * BCM_E_UNAVAIL - OAM not support on this device. 4703 * BCM_E_MEMORY - Allocation failure 4704 * BCM_E_NONE - Success 4705 */ 4706 STATIC int 4707 _bcm_fp_oam_bhh_scache_alloc(int unit) { 4708 _bcm_fp_oam_control_t *oc; 4709 soc_scache_handle_t scache_handle; 4710 uint8 *oam_scache; 4711 int alloc_sz = 0; 4712 4713 4714 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 4715 4716 /* Number of BHH groups */ 4717 alloc_sz += sizeof(int); 4718 4719 alloc_sz += (sizeof(int) + sizeof(int) + sizeof(uint32) + 4720 BCM_OAM_GROUP_NAME_LENGTH) * 4721 oc->bhh_endpoint_count; 4722 4723 /* Number of BHH endpoints */ 4724 alloc_sz += sizeof(int); 4725 4726 alloc_sz += (sizeof(bcm_oam_endpoint_t) + 4727 sizeof(bcm_oam_endpoint_type_t) + sizeof(bcm_oam_group_t) + 4728 sizeof(bcm_gport_t) + sizeof(bcm_mpls_label_t) + 4729 sizeof(uint8) + 4730 sizeof(bcm_vpn_t) + 4731 sizeof(bcm_if_t) + 4732 sizeof(bcm_oam_pm_profile_t) + 4733 sizeof(uint8) + 4734 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) + 4735 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) + 4736 sizeof(uint8) + 4737 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) + 4738 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) + 4739 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) + 4740 sizeof(uint8) + 4741 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) + 4742 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) + 4743 sizeof(uint8) + 4744 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) + 4745 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX)) * 4746 oc->bhh_endpoint_count + 4747 sizeof(uint32) + 4748 sizeof(uint8) + 4749 sizeof(int) + 4750 /* CSF counters */ 4751 (sizeof(uint8) + 4752 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) + 4753 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) * 4754 oc->bhh_endpoint_count); 4755 4756 /* Allocate memory to store oam_mpls_tp_ach_channel_type */ 4757 alloc_sz += sizeof(fp_oam_mpls_tp_ach_channel_type); 4758 4759 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 4760 bcmFpOamWbSequenceBhh); 4761 BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 1, 4762 alloc_sz, &oam_scache, BCM_WB_BHH_DEFAULT_VERSION, NULL)); 4763 return BCM_E_NONE; 4764 } 4765 4766 /* 4767 * Function: 4768 * _bcm_fp_oam_bhh_sync 4769 * Purpose: 4770 * Store BHH configuration to level two storage cache memory. 4771 * Parameters: 4772 * unit - (IN) Device unit number 4773 * Returns: 4774 * BCM_E_XXX 4775 */ 4776 int 4777 _bcm_fp_oam_bhh_sync(int unit) 4778 { 4779 int rv; /* Operation return status. */ 4780 _bcm_fp_oam_control_t *oc; 4781 int alloc_size = 0, csf_cntr_size; 4782 int stable_size; 4783 soc_scache_handle_t scache_handle; 4784 uint8 *oam_scache; 4785 int grp_idx; 4786 _bhh_fp_oam_group_data_t *group_p; /* Pointer to group list. */ 4787 int group_count = 0, ep_count = 0; 4788 int idx = 0; 4789 _bhh_fp_oam_ep_data_t *ep_data; 4790 uint8 i = 0; 4791 4792 /* Get OAM module storage size. */ 4793 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 4794 4795 /* If level 2 store is not configured return from here. */ 4796 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) { 4797 return BCM_E_NONE; 4798 } 4799 4800 /* Get handle to control structure. */ 4801 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 4802 4803 _BCM_OAM_LOCK(oc); 4804 4805 if (oc->ukernel_not_ready == 0) { 4806 /* Initialize to group array pointer. */ 4807 group_p = oc->bhh_group_data; 4808 4809 for (grp_idx = 0; grp_idx < oc->bhh_endpoint_count; grp_idx++) { 4810 4811 /* Check if the group is in use. */ 4812 if (BCM_E_EXISTS 4813 == shr_idxres_list_elem_state(oc->bhh_group_pool, grp_idx)) { 4814 /*Store Group ID of this group*/ 4815 alloc_size += sizeof(int); 4816 /*Store LMEP ID associated with this group*/ 4817 alloc_size += sizeof(int); 4818 /*Store flags associated with this group*/ 4819 alloc_size += sizeof(uint32); 4820 /*Store name associated with this group*/ 4821 alloc_size += BCM_OAM_GROUP_NAME_LENGTH; 4822 group_count++; 4823 } 4824 } 4825 /* To store OAM group count. */ 4826 alloc_size += sizeof(int); 4827 4828 ep_data = oc->bhh_ep_data; 4829 for (idx = 0; idx < oc->bhh_endpoint_count; idx++) { 4830 4831 /* Check if the EP is in use. */ 4832 if (BCM_E_EXISTS 4833 == shr_idxres_list_elem_state(oc->bhh_pool, idx)) { 4834 /*Store ID of this EP*/ 4835 alloc_size += sizeof(bcm_oam_endpoint_t); 4836 /*Store type of this EP*/ 4837 alloc_size += sizeof(bcm_oam_endpoint_type_t); 4838 /*Store group ID associated with this EP*/ 4839 alloc_size += sizeof(bcm_oam_group_t); 4840 /*Store gport associated with this EP*/ 4841 alloc_size += sizeof(bcm_gport_t); 4842 /*Store egr label associated with this EP*/ 4843 alloc_size += sizeof(bcm_mpls_label_t); 4844 /*Store egr label exp associated with this EP*/ 4845 alloc_size += sizeof(uint8); 4846 /*Store vpn associated with this EP*/ 4847 alloc_size += sizeof(bcm_vpn_t); 4848 /*Store intf associated with this EP*/ 4849 alloc_size += sizeof(bcm_if_t); 4850 /*Store PM profile associated with this EP*/ 4851 alloc_size += sizeof(bcm_oam_pm_profile_t); 4852 /*Store CCM TX counter info associated with this EP*/ 4853 /*Store CCM TX counter size*/ 4854 alloc_size += sizeof(uint8); 4855 /*Store CCM TX counters base_ids*/ 4856 alloc_size += sizeof(uint32) * ep_data[idx].ccm_tx_counter_size; 4857 /*Store CCM TX counters offsets*/ 4858 alloc_size += sizeof(uint32) * ep_data[idx].ccm_tx_counter_size; 4859 /*Store LM TX counter info associated with this EP*/ 4860 /*Store LM TX counter size*/ 4861 alloc_size += sizeof(uint8); 4862 /*Store LM TX counters base_ids*/ 4863 alloc_size += sizeof(uint32) * ep_data[idx].lm_counter_size; 4864 /*Store LM TX counters offsets*/ 4865 alloc_size += sizeof(uint32) * ep_data[idx].lm_counter_size; 4866 /*Store LM TX counters actions*/ 4867 alloc_size += sizeof(uint32) * ep_data[idx].lm_counter_size; 4868 /*Store LB TX counter info associated with this EP*/ 4869 /*Store LB TX counter size*/ 4870 alloc_size += sizeof(uint8); 4871 /*Store LB TX counters base_ids*/ 4872 alloc_size += sizeof(uint32) * ep_data[idx].lb_tx_counter_size; 4873 /*Store LB TX counters offsets*/ 4874 alloc_size += sizeof(uint32) * ep_data[idx].lb_tx_counter_size; 4875 /*Store DM TX counter info associated with this EP*/ 4876 /*Store DM TX counter size*/ 4877 alloc_size += sizeof(uint8); 4878 /*Store DM TX counters base_ids*/ 4879 alloc_size += sizeof(uint32) * ep_data[idx].dm_tx_counter_size; 4880 /*Store DM TX counters offsets*/ 4881 alloc_size += sizeof(uint32) * ep_data[idx].dm_tx_counter_size; 4882 /*Store HW provided session ID*/ 4883 alloc_size += sizeof(uint32); 4884 /*Store HW provided number of session IDs*/ 4885 alloc_size += sizeof(uint8); 4886 /*Store Trunk index */ 4887 alloc_size += sizeof(int); 4888 ep_count++; 4889 } 4890 } 4891 /* To store BHH EP count. */ 4892 alloc_size += (sizeof(bcm_oam_endpoint_t) * ep_count); 4893 if (_BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) { 4894 alloc_size += _BCM_FP_OAM_PM_PROFILE_SCACHE_SIZE; 4895 } 4896 4897 /* Scache Version 1 */ 4898 4899 /* Calculate size taken to accomadate CSF counters */ 4900 csf_cntr_size = 0; 4901 /* Store CSF TX counter size */ 4902 csf_cntr_size += sizeof(uint8); 4903 /* Store CSF TX counters base_ids */ 4904 csf_cntr_size += sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX; 4905 /* Store CSF TX counters offsets */ 4906 csf_cntr_size += sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX; 4907 /* Counters are per-endpoint */ 4908 csf_cntr_size *= oc->bhh_endpoint_count; 4909 4910 alloc_size += csf_cntr_size; 4911 4912 /* Allocate memory to store oam_mpls_tp_ach_channel_type */ 4913 alloc_size += sizeof(fp_oam_mpls_tp_ach_channel_type); 4914 4915 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 4916 bcmFpOamWbSequenceBhh); 4917 4918 /* Check if memory has already been allocated */ 4919 rv = _bcm_esw_scache_ptr_get(unit, 4920 scache_handle, 4921 0, 4922 0, 4923 &oam_scache, 4924 BCM_WB_BHH_DEFAULT_VERSION, 4925 NULL 4926 ); 4927 if (!SOC_WARM_BOOT(unit) && (BCM_E_NOT_FOUND == rv)) { 4928 rv = _bcm_esw_scache_ptr_get(unit, 4929 scache_handle, 4930 1, 4931 alloc_size, 4932 &oam_scache, 4933 BCM_WB_BHH_DEFAULT_VERSION, 4934 NULL 4935 ); 4936 if (BCM_FAILURE(rv) 4937 || (NULL == oam_scache)) { 4938 goto cleanup; 4939 } 4940 } else if (BCM_FAILURE(rv)) { 4941 goto cleanup; 4942 } 4943 /* To store OAM group count. */ 4944 sal_memcpy(oam_scache, &group_count, sizeof(int)); 4945 oam_scache += sizeof(int); 4946 4947 for (grp_idx = 0; grp_idx < oc->bhh_endpoint_count; grp_idx++) 4948 { 4949 /* Check if the group is in use. */ 4950 if (BCM_E_EXISTS 4951 == shr_idxres_list_elem_state(oc->bhh_group_pool, 4952 grp_idx)) { 4953 4954 sal_memcpy(oam_scache, &group_p[grp_idx].group_id, 4955 sizeof(int)); 4956 oam_scache += sizeof(int); 4957 sal_memcpy(oam_scache, &group_p[grp_idx].lmep_id, 4958 sizeof(int)); 4959 oam_scache += sizeof(int); 4960 sal_memcpy(oam_scache, &group_p[grp_idx].flags, 4961 sizeof(uint32)); 4962 oam_scache += sizeof(uint32); 4963 sal_memcpy(oam_scache, group_p[grp_idx].name, 4964 BCM_OAM_GROUP_NAME_LENGTH); 4965 oam_scache += BCM_OAM_GROUP_NAME_LENGTH; 4966 } 4967 } 4968 /* To store BHH EP count. */ 4969 sal_memcpy(oam_scache, &ep_count, sizeof(int)); 4970 oam_scache += sizeof(int); 4971 for (idx = 0; idx < oc->bhh_endpoint_count; idx++) { 4972 4973 /* Check if the EP is in use. */ 4974 if (BCM_E_EXISTS 4975 == shr_idxres_list_elem_state(oc->bhh_pool, idx)) { 4976 sal_memcpy(oam_scache, &ep_data[idx].ep_id, 4977 sizeof(bcm_oam_endpoint_t)); 4978 oam_scache += sizeof(bcm_oam_endpoint_t); 4979 sal_memcpy(oam_scache, &ep_data[idx].type, 4980 sizeof(bcm_oam_endpoint_type_t)); 4981 oam_scache += sizeof(bcm_oam_endpoint_type_t); 4982 sal_memcpy(oam_scache, &ep_data[idx].group_index, 4983 sizeof(bcm_oam_group_t)); 4984 oam_scache += sizeof(bcm_oam_group_t); 4985 sal_memcpy(oam_scache, &ep_data[idx].gport, 4986 sizeof(bcm_gport_t)); 4987 oam_scache += sizeof(bcm_gport_t); 4988 sal_memcpy(oam_scache, &ep_data[idx].egr_label, 4989 sizeof(bcm_mpls_label_t)); 4990 oam_scache += sizeof(bcm_mpls_label_t); 4991 sal_memcpy(oam_scache, &ep_data[idx].egr_label_exp, 4992 sizeof(uint8)); 4993 oam_scache += sizeof(uint8); 4994 sal_memcpy(oam_scache, &ep_data[idx].vpn, 4995 sizeof(bcm_vpn_t)); 4996 oam_scache += sizeof(bcm_vpn_t); 4997 sal_memcpy(oam_scache, &ep_data[idx].egress_if, 4998 sizeof(bcm_if_t)); 4999 oam_scache += sizeof(bcm_if_t); 5000 sal_memcpy(oam_scache, &ep_data[idx].pm_profile_attached, 5001 sizeof(bcm_oam_pm_profile_t)); 5002 oam_scache += sizeof(bcm_oam_pm_profile_t); 5003 /*Store CCM TX counter info associated with this EP*/ 5004 /*Store CCM TX counter size*/ 5005 sal_memcpy(oam_scache, &ep_data[idx].ccm_tx_counter_size, 5006 sizeof(uint8)); 5007 oam_scache += sizeof(uint8); 5008 /*Store CCM TX counters base_ids*/ 5009 for (i = 0; i < ep_data[idx].ccm_tx_counter_size; i++) { 5010 sal_memcpy(oam_scache, 5011 &ep_data[idx].ccm_tx_update_lm_counter_base_id[i], 5012 sizeof(uint32)); 5013 oam_scache += sizeof(uint32); 5014 } 5015 /*Store CCM TX counters offsets*/ 5016 for (i = 0; i < ep_data[idx].ccm_tx_counter_size; i++) { 5017 sal_memcpy(oam_scache, 5018 &ep_data[idx].ccm_tx_update_lm_counter_offset[i], 5019 sizeof(uint32)); 5020 oam_scache += sizeof(uint32); 5021 } 5022 /*Store LM TX counter info associated with this EP*/ 5023 /*Store LM TX counter size*/ 5024 sal_memcpy(oam_scache, &ep_data[idx].lm_counter_size, 5025 sizeof(uint8)); 5026 oam_scache += sizeof(uint8); 5027 /*Store LM TX counters base_ids*/ 5028 for (i = 0; i < ep_data[idx].lm_counter_size; i++) { 5029 sal_memcpy(oam_scache, 5030 &ep_data[idx].lm_counter_base_id[i], 5031 sizeof(uint32)); 5032 oam_scache += sizeof(uint32); 5033 } 5034 /*Store LM TX counters offsets*/ 5035 for (i = 0; i < ep_data[idx].lm_counter_size; i++) { 5036 sal_memcpy(oam_scache, 5037 &ep_data[idx].lm_counter_offset[i], 5038 sizeof(uint32)); 5039 oam_scache += sizeof(uint32); 5040 } 5041 /*Store LM TX counters actions*/ 5042 for (i = 0; i < ep_data[idx].lm_counter_size; i++) { 5043 sal_memcpy(oam_scache, 5044 &ep_data[idx].lm_counter_action[i], 5045 sizeof(uint32)); 5046 oam_scache += sizeof(uint32); 5047 } 5048 /*Store LB TX counter info associated with this EP*/ 5049 /*Store LB TX counter size*/ 5050 sal_memcpy(oam_scache, &ep_data[idx].lb_tx_counter_size, 5051 sizeof(uint8)); 5052 oam_scache += sizeof(uint8); 5053 /*Store LB TX counters base_ids*/ 5054 for (i = 0; i < ep_data[idx].lb_tx_counter_size; i++) { 5055 sal_memcpy(oam_scache, 5056 &ep_data[idx].lb_tx_update_lm_counter_base_id[i], 5057 sizeof(uint32)); 5058 oam_scache += sizeof(uint32); 5059 } 5060 /*Store LB TX counters offsets*/ 5061 for (i = 0; i < ep_data[idx].lb_tx_counter_size; i++) { 5062 sal_memcpy(oam_scache, 5063 &ep_data[idx].lb_tx_update_lm_counter_offset[i], 5064 sizeof(uint32)); 5065 oam_scache += sizeof(uint32); 5066 } 5067 /*Store DM TX counter info associated with this EP*/ 5068 /*Store DM TX counter size*/ 5069 sal_memcpy(oam_scache, &ep_data[idx].dm_tx_counter_size, 5070 sizeof(uint8)); 5071 oam_scache += sizeof(uint8); 5072 /*Store DM TX counters base_ids*/ 5073 for (i = 0; i < ep_data[idx].dm_tx_counter_size; i++) { 5074 sal_memcpy(oam_scache, 5075 &ep_data[idx].dm_tx_update_lm_counter_base_id[i], 5076 sizeof(uint32)); 5077 oam_scache += sizeof(uint32); 5078 } 5079 /*Store DM TX counters offsets*/ 5080 for (i = 0; i < ep_data[idx].dm_tx_counter_size; i++) { 5081 sal_memcpy(oam_scache, 5082 &ep_data[idx].dm_tx_update_lm_counter_offset[i], 5083 sizeof(uint32)); 5084 oam_scache += sizeof(uint32); 5085 } 5086 /*Store HW session ID*/ 5087 sal_memcpy(oam_scache, &ep_data[idx].hw_session_id, 5088 sizeof(uint32)); 5089 oam_scache += sizeof(uint32); 5090 /*Store HW number of session IDs*/ 5091 sal_memcpy(oam_scache, &ep_data[idx].hw_session_num_entries, 5092 sizeof(uint8)); 5093 oam_scache += sizeof(uint8); 5094 sal_memcpy(oam_scache, &ep_data[idx].trunk_index, 5095 sizeof(int)); 5096 oam_scache += sizeof(int); 5097 } 5098 } 5099 if (_BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) { 5100 /* Store pm profile */ 5101 int itr; 5102 _bcm_fp_oam_pm_profile_control_t *pmc = NULL; 5103 5104 pmc = pm_profile_control[unit]; 5105 if (!pmc) { 5106 goto cleanup; 5107 } 5108 for(itr = 0; itr < _BCM_OAM_MAX_PM_PROFILES; itr++) { 5109 sal_memcpy(oam_scache, 5110 &(pmc->profile_info[itr]), sizeof(_bcm_fp_oam_pm_profile_int_info_t)); 5111 oam_scache += sizeof(_bcm_fp_oam_pm_profile_int_info_t); 5112 } 5113 } 5114 5115 for (idx = 0; idx < oc->bhh_endpoint_count; idx++) { 5116 /* Check if the EP is in use. */ 5117 if (BCM_E_EXISTS != shr_idxres_list_elem_state(oc->bhh_pool, idx)) { 5118 continue; 5119 } 5120 /* Store CSF TX counter info associated with this EP */ 5121 /* Store CSF TX counter size */ 5122 sal_memcpy(oam_scache, &ep_data[idx].csf_tx_counter_size, 5123 sizeof(uint8)); 5124 oam_scache += sizeof(uint8); 5125 5126 /* Store CSF TX counters base_ids */ 5127 for (i = 0; i < BCM_OAM_LM_COUNTER_MAX; i++) { 5128 sal_memcpy(oam_scache, 5129 &ep_data[idx].csf_tx_update_lm_counter_base_id[i], 5130 sizeof(uint32)); 5131 oam_scache += sizeof(uint32); 5132 } 5133 5134 /* Store CSF TX counters offsets */ 5135 for (i = 0; i < BCM_OAM_LM_COUNTER_MAX; i++) { 5136 sal_memcpy(oam_scache, 5137 &ep_data[idx].csf_tx_update_lm_counter_offset[i], 5138 sizeof(uint32)); 5139 oam_scache += sizeof(uint32); 5140 } 5141 } 5142 for (idx = 0; idx < oc->bhh_endpoint_count; idx++) { 5143 /* Check if the EP is in use. */ 5144 if (BCM_E_EXISTS != shr_idxres_list_elem_state(oc->bhh_pool, idx)) { 5145 continue; 5146 } 5147 sal_memcpy(oam_scache, &ep_data[idx].egr_label_ttl, 5148 sizeof(uint8)); 5149 oam_scache += sizeof(uint8); 5150 } 5151 sal_memcpy(oam_scache, &fp_oam_mpls_tp_ach_channel_type, 5152 sizeof(fp_oam_mpls_tp_ach_channel_type)); 5153 oam_scache += sizeof(fp_oam_mpls_tp_ach_channel_type); 5154 } 5155 5156 cleanup: 5157 _BCM_OAM_UNLOCK(oc); 5158 return (BCM_E_NONE); 5159 } 5160 5161 /* 5162 * Function: 5163 * _bcm_fp_oam_wb_group_recover 5164 * Purpose: 5165 * Recover OAM group configuration. 5166 * Parameters: 5167 * unit - (IN) BCM device number 5168 * stable_size - (IN) OAM module Level2 storage size. 5169 * oam_scache - (IN) Pointer to scache address pointer. 5170 * Returns: 5171 * BCM_E_XXX 5172 */ 5173 STATIC int 5174 _bcm_fp_oam_wb_group_recover(int unit, int stable_size, uint8 **oam_scache) 5175 { 5176 int index; /* Hw table index. */ 5177 _bhh_fp_oam_group_data_t *group_p; /* Group info pointer. */ 5178 _bcm_fp_oam_control_t *oc; /* Pointer to Control */ 5179 /* structure. */ 5180 int rv; /* Operation return */ 5181 /* status. */ 5182 uint32 group_count; /* Stored OAM group count*/ 5183 int bhh_group_idx = 0, group_id = 0; 5184 5185 /* Control lock taken by calling routine. */ 5186 /* Get OAM control structure. */ 5187 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 5188 5189 /* Recover the OAM groups */ 5190 sal_memcpy(&group_count, *oam_scache, sizeof(int)); 5191 *oam_scache = (*oam_scache + sizeof(int)); 5192 5193 for (index = 0; index < group_count; index++) { 5194 5195 /* Get the group id from stored info. */ 5196 sal_memcpy(&group_id, *oam_scache, 5197 sizeof(int)); 5198 *oam_scache = (*oam_scache + sizeof(int)); 5199 5200 bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(group_id); 5201 /* Reserve the group index. */ 5202 rv = shr_idxres_list_reserve(oc->bhh_group_pool, bhh_group_idx, 5203 bhh_group_idx); 5204 if (BCM_FAILURE(rv)) { 5205 LOG_ERROR(BSL_LS_BCM_OAM, 5206 (BSL_META_U(unit, 5207 "OAM(unit %d) Error: (GID=%d) Index reserve " 5208 " failed - %s.\n"), unit, index, 5209 bcm_errmsg(rv))); 5210 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 5211 goto cleanup; 5212 } 5213 /* Get the group memory pointer. */ 5214 group_p = &oc->bhh_group_data[bhh_group_idx]; 5215 if (1 == group_p->in_use) { 5216 rv = BCM_E_INTERNAL; 5217 goto cleanup; 5218 } 5219 5220 group_p->group_id = group_id; 5221 sal_memcpy(&group_p->lmep_id, *oam_scache, 5222 sizeof(int)); 5223 *oam_scache = (*oam_scache + sizeof(int)); 5224 sal_memcpy(&group_p->flags, *oam_scache, 5225 sizeof(uint32)); 5226 *oam_scache = (*oam_scache + sizeof(uint32)); 5227 5228 sal_memcpy(group_p->name, *oam_scache, 5229 BCM_OAM_GROUP_NAME_LENGTH); 5230 *oam_scache = (*oam_scache + BCM_OAM_GROUP_NAME_LENGTH); 5231 group_p->in_use = 1; 5232 } 5233 5234 return (BCM_E_NONE); 5235 5236 cleanup: 5237 5238 if (BCM_E_EXISTS 5239 == shr_idxres_list_elem_state(oc->group_pool, bhh_group_idx)) { 5240 shr_idxres_list_free(oc->group_pool, bhh_group_idx); 5241 } 5242 5243 return (rv); 5244 5245 } 5246 5247 5248 /* 5249 * Function: 5250 * _bcm_fp_oam_endpoint_alloc 5251 * Purpose: 5252 * Allocate an endpoint memory element. 5253 * Parameters: 5254 * ep_pp - (IN/OUT) Pointer to endpoint address pointer. 5255 * Returns: 5256 * BCM_E_XXX 5257 */ 5258 STATIC int 5259 _bcm_fp_oam_endpoint_alloc(bcm_oam_endpoint_info_t **ep_pp) 5260 { 5261 bcm_oam_endpoint_info_t *ep_p = NULL; 5262 5263 _BCM_OAM_ALLOC(ep_p, bcm_oam_endpoint_info_t, 5264 sizeof(bcm_oam_endpoint_info_t), "Endpoint info"); 5265 if (NULL == ep_p) { 5266 return (BCM_E_MEMORY); 5267 } 5268 5269 *ep_pp = ep_p; 5270 5271 return (BCM_E_NONE); 5272 5273 } 5274 5275 /* 5276 * Function: 5277 * _bcm_fp_oam_mpls_entry_label_lookup 5278 * Purpose: 5279 * Finds a MPLS_ENTRY corresponding to a MPLS label. 5280 * Parameters: 5281 * unit - (IN) BCM device number 5282 * label - (IN) label to which MPLS_ENTRY object to found 5283 * label - (IN) index in MPLS_ENTRY object to found 5284 * found_entry - (OUT) Pointer to MPLS_ENTRY object. 5285 * Returns: 5286 * BCM_E_XXX 5287 */ 5288 STATIC int 5289 _bcm_fp_oam_mpls_entry_label_lookup(int unit, bcm_mpls_label_t label, 5290 int *mpls_index, 5291 mpls_entry_entry_t *found_entry) 5292 { 5293 #if defined(INCLUDE_L3) 5294 mpls_entry_entry_t mpls_key_entry; 5295 int rv = BCM_E_NONE; 5296 5297 sal_memset(&mpls_key_entry, 0, sizeof(mpls_key_entry)); 5298 5299 soc_MPLS_ENTRYm_field32_set(unit, &mpls_key_entry, MPLS_LABELf, label); 5300 soc_MPLS_ENTRYm_field32_set(unit, &mpls_key_entry, VALIDf, 1); 5301 5302 BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit)); 5303 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, mpls_index, 5304 &mpls_key_entry, found_entry, 0); 5305 bcm_tr_mpls_unlock(unit); 5306 5307 return rv; 5308 #endif /* INCLUDE_L3 */ 5309 return BCM_E_UNAVAIL; 5310 } 5311 5312 /* 5313 * Function: 5314 * _bcm_fp_oam_wb_endpoints_recover 5315 * Purpose: 5316 * Recover OAM endpoint configuration for DownMEPS. 5317 * Parameters: 5318 * unit - (IN) BCM device number 5319 * stable_size - OAM module Level2 memory size. 5320 * oam_scache - Pointer to secondary storage buffer pointer. 5321 * Returns: 5322 * BCM_E_XXX 5323 */ 5324 STATIC int 5325 _bcm_fp_oam_wb_endpoints_recover(int unit, 5326 int stable_size, 5327 uint8 **oam_scache) 5328 { 5329 _bhh_fp_oam_ep_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 5330 _bcm_fp_oam_control_t *oc; /* Pointer to control structure. */ 5331 int rv; /* Operation return status. */ 5332 int ep_id, ep_count;/* Endpoint ID. */ 5333 _bhh_fp_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 5334 bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information. */ 5335 _bhh_fp_oam_group_data_t *group_p; /* Group info pointer. */ 5336 int idx = 0, i = 0; 5337 bcm_oam_endpoint_t bhh_endpoint_index = 0; 5338 bhh_sdk_msg_ctrl_sess_get_t msg; 5339 mpls_entry_entry_t mpls_entry; 5340 uint16 buffer_len, reply_len; 5341 uint8 *buffer, *buffer_ptr; 5342 int mpls_index = -1; 5343 bcm_l3_egress_t l3_egress; 5344 bcm_l3_intf_t l3_intf; 5345 uint8* encap_data = NULL; 5346 soc_olp_l2_hdr_t olp_l2_header; 5347 soc_olp_tx_hdr_t olp_oam_tx_header; 5348 int bhh_group_idx = 0; 5349 int sglp = 0; /* Source global logical port. */ 5350 int dglp = 0; /* Dest global logical port. */ 5351 bcm_gport_t dgpp = 0; 5352 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 5353 bcm_trunk_member_t trunk_member; 5354 5355 LOG_DEBUG(BSL_LS_BCM_OAM, 5356 (BSL_META_U(unit, 5357 "OAM(unit %d) Info: " 5358 "_bcm_fp_oam_wb_endpoints_recover.\n"), unit)); 5359 /* 5360 * Get OAM control structure. 5361 * Note: Lock taken by calling routine. 5362 */ 5363 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 5364 5365 /* Recover the OAM endpoint count */ 5366 sal_memcpy(&ep_count, *oam_scache, sizeof(int)); 5367 *oam_scache = (*oam_scache + sizeof(int)); 5368 5369 for (idx = 0; idx < ep_count; idx++) { 5370 5371 sal_memcpy(&ep_id, *oam_scache, sizeof(bcm_oam_endpoint_t)); 5372 *oam_scache = (*oam_scache + sizeof(bcm_oam_endpoint_t)); 5373 5374 bhh_endpoint_index = BCM_OAM_BHH_GET_UKERNEL_EP(ep_id); 5375 5376 h_data_p = &oc->bhh_ep_data[bhh_endpoint_index]; 5377 if (1 == h_data_p->in_use) { 5378 return (BCM_E_INTERNAL); 5379 } 5380 rv = shr_idxres_list_reserve(oc->bhh_pool, bhh_endpoint_index, 5381 bhh_endpoint_index); 5382 if (BCM_FAILURE(rv)) { 5383 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 5384 LOG_ERROR(BSL_LS_BCM_OAM, 5385 (BSL_META_U(unit, 5386 "BHH(unit %d) Error: Endpoint reserve (EP=%d) - %s.\n"), 5387 unit, bhh_endpoint_index, bcm_errmsg(rv))); 5388 goto cleanup; 5389 } 5390 5391 _BHH_FP_OAM_HASH_DATA_CLEAR(h_data_p); 5392 h_data_p->remote_index = _BCM_OAM_INVALID_INDEX; 5393 h_data_p->trunk_id = BCM_TRUNK_INVALID; 5394 5395 h_data_p->ep_id = ep_id; 5396 h_data_p->uc_session_id = bhh_endpoint_index; 5397 5398 sal_memcpy(&h_data_p->type, *oam_scache, 5399 sizeof(bcm_oam_endpoint_type_t)); 5400 *oam_scache = (*oam_scache + sizeof(bcm_oam_endpoint_type_t)); 5401 sal_memcpy(&h_data_p->group_index, *oam_scache, 5402 sizeof(bcm_oam_group_t)); 5403 *oam_scache = (*oam_scache + sizeof(bcm_oam_group_t)); 5404 sal_memcpy(&h_data_p->gport, *oam_scache, 5405 sizeof(bcm_gport_t)); 5406 *oam_scache = (*oam_scache + sizeof(bcm_gport_t)); 5407 sal_memcpy(&h_data_p->egr_label, *oam_scache, 5408 sizeof(bcm_mpls_label_t)); 5409 *oam_scache = (*oam_scache + sizeof(bcm_mpls_label_t)); 5410 sal_memcpy(&h_data_p->egr_label_exp, *oam_scache, 5411 sizeof(uint8)); 5412 *oam_scache = (*oam_scache + sizeof(uint8)); 5413 sal_memcpy(&h_data_p->vpn, *oam_scache, 5414 sizeof(bcm_vpn_t)); 5415 *oam_scache = (*oam_scache + sizeof(bcm_vpn_t)); 5416 5417 sal_memcpy(&h_data_p->egress_if, *oam_scache, 5418 sizeof(bcm_if_t)); 5419 *oam_scache = (*oam_scache + sizeof(bcm_if_t)); 5420 sal_memcpy(&h_data_p->pm_profile_attached, *oam_scache, 5421 sizeof(bcm_oam_pm_profile_t)); 5422 *oam_scache = (*oam_scache + sizeof(bcm_oam_pm_profile_t)); 5423 sal_memcpy(&h_data_p->ccm_tx_counter_size, *oam_scache, 5424 sizeof(uint8)); 5425 *oam_scache = (*oam_scache + sizeof(uint8)); 5426 for (i = 0; i < h_data_p->ccm_tx_counter_size; i++) { 5427 sal_memcpy(&h_data_p->ccm_tx_update_lm_counter_base_id[i], 5428 *oam_scache, 5429 sizeof(uint32)); 5430 *oam_scache = (*oam_scache + sizeof(uint32)); 5431 } 5432 for (i = 0; i < h_data_p->ccm_tx_counter_size; i++) { 5433 sal_memcpy(&h_data_p->ccm_tx_update_lm_counter_offset[i], 5434 *oam_scache, 5435 sizeof(uint32)); 5436 *oam_scache = (*oam_scache + sizeof(uint32)); 5437 } 5438 sal_memcpy(&h_data_p->lm_counter_size, *oam_scache, 5439 sizeof(uint8)); 5440 *oam_scache = (*oam_scache + sizeof(uint8)); 5441 for (i = 0; i < h_data_p->lm_counter_size; i++) { 5442 sal_memcpy(&h_data_p->lm_counter_base_id[i], 5443 *oam_scache, 5444 sizeof(uint32)); 5445 *oam_scache = (*oam_scache + sizeof(uint32)); 5446 } 5447 for (i = 0; i < h_data_p->lm_counter_size; i++) { 5448 sal_memcpy(&h_data_p->lm_counter_offset[i], 5449 *oam_scache, 5450 sizeof(uint32)); 5451 *oam_scache = (*oam_scache + sizeof(uint32)); 5452 } 5453 for (i = 0; i < h_data_p->lm_counter_size; i++) { 5454 sal_memcpy(&h_data_p->lm_counter_action[i], 5455 *oam_scache, 5456 sizeof(uint32)); 5457 *oam_scache = (*oam_scache + sizeof(uint32)); 5458 } 5459 sal_memcpy(&h_data_p->lb_tx_counter_size, *oam_scache, 5460 sizeof(uint8)); 5461 *oam_scache = (*oam_scache + sizeof(uint8)); 5462 for (i = 0; i < h_data_p->lb_tx_counter_size; i++) { 5463 sal_memcpy(&h_data_p->lb_tx_update_lm_counter_base_id[i], 5464 *oam_scache, 5465 sizeof(uint32)); 5466 *oam_scache = (*oam_scache + sizeof(uint32)); 5467 } 5468 for (i = 0; i < h_data_p->lb_tx_counter_size; i++) { 5469 sal_memcpy(&h_data_p->lb_tx_update_lm_counter_offset[i], 5470 *oam_scache, 5471 sizeof(uint32)); 5472 *oam_scache = (*oam_scache + sizeof(uint32)); 5473 } 5474 sal_memcpy(&h_data_p->dm_tx_counter_size, *oam_scache, 5475 sizeof(uint8)); 5476 *oam_scache = (*oam_scache + sizeof(uint8)); 5477 for (i = 0; i < h_data_p->dm_tx_counter_size; i++) { 5478 sal_memcpy(&h_data_p->dm_tx_update_lm_counter_base_id[i], 5479 *oam_scache, 5480 sizeof(uint32)); 5481 *oam_scache = (*oam_scache + sizeof(uint32)); 5482 } 5483 for (i = 0; i < h_data_p->dm_tx_counter_size; i++) { 5484 sal_memcpy(&h_data_p->dm_tx_update_lm_counter_offset[i], 5485 *oam_scache, 5486 sizeof(uint32)); 5487 *oam_scache = (*oam_scache + sizeof(uint32)); 5488 } 5489 sal_memcpy(&h_data_p->hw_session_id, *oam_scache, 5490 sizeof(uint32)); 5491 *oam_scache = (*oam_scache + sizeof(uint32)); 5492 sal_memcpy(&h_data_p->hw_session_num_entries, *oam_scache, 5493 sizeof(uint8)); 5494 *oam_scache = (*oam_scache + sizeof(uint8)); 5495 sal_memcpy(&h_data_p->trunk_index, *oam_scache, 5496 sizeof(int)); 5497 *oam_scache = (*oam_scache + sizeof(int)); 5498 5499 h_data_p->level = _BCM_OAM_EP_LEVEL_MAX; 5500 /* Get the endpoint parameters from firmware */ 5501 rv = _bcm_fp_oam_msg_send_receive(unit, 5502 MOS_MSG_CLASS_BHH, 5503 MOS_MSG_SUBCLASS_BHH_SESS_GET, 5504 bhh_endpoint_index, 0, 5505 MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY, 5506 &reply_len); 5507 if (BCM_FAILURE(rv)) { 5508 LOG_ERROR(BSL_LS_BCM_OAM, 5509 (BSL_META_U(unit, 5510 "BHH(unit %d) Error: ukernel msg " 5511 "failed for" 5512 " EP=%d %s.\n"), unit, 5513 bhh_endpoint_index, 5514 bcm_errmsg(rv))); 5515 goto cleanup; 5516 } 5517 5518 buffer = oc->bhh_dma_buffer; 5519 buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg); 5520 buffer_len = buffer_ptr - buffer; 5521 5522 if (reply_len != buffer_len) { 5523 rv = BCM_E_INTERNAL; 5524 LOG_ERROR(BSL_LS_BCM_OAM, 5525 (BSL_META_U(unit, 5526 "BHH(unit %d) Error: ukernel msg " 5527 "failed for" 5528 " EP=%d %s.\n"), unit, 5529 bhh_endpoint_index, 5530 bcm_errmsg(rv))); 5531 goto cleanup; 5532 } 5533 5534 h_data_p->name = msg.mep_id; 5535 h_data_p->period = msg.local_period; 5536 h_data_p->label = msg.mpls_label; 5537 /* Set the flags */ 5538 if (msg.flags & SHR_BHH_SESS_SET_F_MIP) 5539 h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE; 5540 5541 if (!BHH_EP_MPLS_SECTION_TYPE(h_data_p)) { 5542 /* port value from l3_egress_if*/ 5543 bcm_l3_egress_t_init(&l3_egress); 5544 if (BCM_FAILURE (bcm_esw_l3_egress_get(unit, 5545 h_data_p->egress_if, &l3_egress))) { 5546 LOG_ERROR(BSL_LS_BCM_OAM, 5547 (BSL_META_U(unit, 5548 "BHH(unit %d) Error: Failed to get L3 " 5549 "egress object EP=%d egress_if=%d %s.\n"), 5550 unit, bhh_endpoint_index, 5551 h_data_p->egress_if, bcm_errmsg(rv))); 5552 goto cleanup; 5553 } 5554 5555 l3_intf.l3a_intf_id = l3_egress.intf; 5556 if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) { 5557 LOG_ERROR(BSL_LS_BCM_OAM, 5558 (BSL_META_U(unit, 5559 "BHH(unit %d) Error: Failed to get L3 " 5560 " interface EP=%d l3a_intf_id=%d %s.\n"), 5561 unit, bhh_endpoint_index, 5562 l3_intf.l3a_intf_id, bcm_errmsg(rv))); 5563 goto cleanup; 5564 } 5565 sal_memcpy(h_data_p->dst_mac_address, l3_egress.mac_addr, 5566 _BHH_MAC_ADDR_LENGTH); 5567 sal_memcpy(h_data_p->src_mac_address, l3_intf.l3a_mac_addr, 5568 _BHH_MAC_ADDR_LENGTH); 5569 5570 h_data_p->sglp = l3_egress.port; 5571 h_data_p->dglp = l3_egress.port; 5572 h_data_p->vlan = l3_intf.l3a_vid; 5573 } else { 5574 encap_data = msg.encap_data; 5575 encap_data = _bcm_fp_oam_olp_l2_header_unpack(encap_data, 5576 &olp_l2_header); 5577 encap_data = shr_olp_tx_header_unpack(encap_data, 5578 &olp_oam_tx_header); 5579 h_data_p->int_pri = SOC_OLP_TX_PRI_GET(&olp_oam_tx_header); 5580 sal_memcpy(h_data_p->dst_mac_address, encap_data, 5581 _BHH_MAC_ADDR_LENGTH); 5582 encap_data += _BHH_MAC_ADDR_LENGTH; 5583 5584 sal_memcpy(h_data_p->src_mac_address, encap_data, 5585 _BHH_MAC_ADDR_LENGTH); 5586 encap_data += _BHH_MAC_ADDR_LENGTH; 5587 if((h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterVlan) || 5588 (h_data_p->type == bcmOAMEndpointTypeBhhSectionInnervlan) || 5589 (h_data_p->type == 5590 bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)){ 5591 encap_data += SHR_BHH_L2_ETYPE_LENGTH; 5592 sal_memcpy(&h_data_p->vlan, encap_data, 5593 SHR_BHH_L2_VLAN_HEADER_LENGTH); 5594 h_data_p->vlan = (h_data_p->vlan & _BHH_VLAN_MASK); 5595 encap_data += SHR_BHH_L2_VLAN_HEADER_LENGTH; 5596 } 5597 if(h_data_p->type == 5598 bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan){ 5599 sal_memcpy(&h_data_p->inner_vlan, encap_data, 5600 SHR_BHH_L2_VLAN_HEADER_LENGTH); 5601 h_data_p->inner_vlan = (h_data_p->vlan & _BHH_VLAN_MASK); 5602 encap_data += SHR_BHH_L2_VLAN_HEADER_LENGTH; 5603 } 5604 } 5605 bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(h_data_p->group_index); 5606 /* Get the group memory pointer. */ 5607 group_p = &oc->bhh_group_data[bhh_group_idx]; 5608 if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){ 5609 group_p->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT; 5610 } 5611 if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){ 5612 group_p->faults |= BCM_OAM_BHH_FAULT_CCM_RDI; 5613 } 5614 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){ 5615 group_p->faults |= 5616 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL; 5617 } 5618 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){ 5619 group_p->faults |= 5620 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID; 5621 } 5622 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){ 5623 group_p->faults |= 5624 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID; 5625 } 5626 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){ 5627 group_p->faults |= 5628 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD; 5629 } 5630 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){ 5631 group_p->faults |= 5632 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY; 5633 } 5634 5635 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 5636 /* get vccv_type from MPLS_ENTRY */ 5637 rv = _bcm_fp_oam_mpls_entry_label_lookup(unit, h_data_p->label, 5638 &mpls_index, 5639 &mpls_entry); 5640 if(rv != BCM_E_NONE) { 5641 /* Not found or some other error */ 5642 LOG_ERROR(BSL_LS_BCM_OAM, 5643 (BSL_META_U(unit, 5644 "BHH(unit %d) Error: (Label=%u) - %s.\n"), 5645 unit, h_data_p->label, bcm_errmsg(rv))); 5646 goto cleanup; 5647 } 5648 h_data_p->vccv_type = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, 5649 PW_CC_TYPEf); 5650 h_data_p->vccv_type--; 5651 } 5652 rv = _bcm_fp_oam_endpoint_alloc(&ep_info); 5653 if (BCM_FAILURE(rv)) { 5654 goto cleanup; 5655 } 5656 5657 bcm_oam_endpoint_info_t_init(ep_info); 5658 5659 /* Set up endpoint information for key construction. */ 5660 ep_info->group = h_data_p->group_index; 5661 ep_info->name = h_data_p->name; 5662 ep_info->gport = h_data_p->gport; 5663 ep_info->level = h_data_p->level; 5664 ep_info->vlan = h_data_p->vlan; 5665 ep_info->inner_vlan = h_data_p->inner_vlan; 5666 ep_info->mpls_label = h_data_p->label; 5667 ep_info->type = h_data_p->type; 5668 ep_info->trunk_index = h_data_p->trunk_index; 5669 ep_info->ccm_period = h_data_p->period; 5670 5671 /* Resolve given endpoint gport value to SGLP and DGLP values. */ 5672 rv = _bcm_fp_oam_endpoint_gport_resolve(unit, ep_info, 5673 &sglp, &dglp, &dgpp, 5674 &trunk_id, &trunk_member); 5675 if (BCM_FAILURE(rv)) { 5676 LOG_ERROR(BSL_LS_BCM_OAM, 5677 (BSL_META_U(unit, 5678 "OAM(unit %d) Error: Gport resolve (EP=%d) - %s.\n"), 5679 unit, h_data_p->ep_id, bcm_errmsg(rv))); 5680 _BCM_OAM_UNLOCK(oc); 5681 return (rv); 5682 } 5683 if (BCM_TRUNK_INVALID != trunk_id) { 5684 h_data_p->trunk_id = trunk_id; 5685 h_data_p->resolved_trunk_gport = trunk_member.gport; 5686 } 5687 /* 5688 * Calculate hash key for hash table insert 5689 * operation. 5690 */ 5691 _bhh_fp_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key); 5692 5693 sal_free(ep_info); 5694 5695 rv = shr_htb_insert(oc->bhh_mep_htbl, hash_key, h_data_p); 5696 if (BCM_FAILURE(rv)) { 5697 LOG_ERROR(BSL_LS_BCM_OAM, 5698 (BSL_META_U(unit, 5699 "BHH(unit %d) Error: Hash table insert" 5700 "(EP=%d) failed - %s.\n"), unit, 5701 h_data_p->ep_id, bcm_errmsg(rv))); 5702 goto cleanup; 5703 } else { 5704 LOG_DEBUG(BSL_LS_BCM_OAM, 5705 (BSL_META_U(unit, 5706 "BHH(unit %d) Info: Hash Tbl (EP=%d)" 5707 " inserted - %s.\n"), unit, h_data_p->ep_id, 5708 bcm_errmsg(rv))); 5709 } 5710 h_data_p->in_use = 1; 5711 } /* end of for loop */ 5712 5713 LOG_DEBUG(BSL_LS_BCM_OAM, 5714 (BSL_META_U(unit, 5715 "OAM(unit %d) Info: _bcm_fp_oam_wb_endpoints_recover" 5716 " - done.\n"), unit)); 5717 return (BCM_E_NONE); 5718 5719 cleanup: 5720 5721 if (NULL != ep_info) { 5722 sal_free(ep_info); 5723 } 5724 5725 if (BCM_E_EXISTS 5726 == shr_idxres_list_elem_state(oc->bhh_pool,bhh_endpoint_index)) { 5727 shr_idxres_list_free(oc->bhh_pool,bhh_endpoint_index); 5728 } 5729 5730 _BHH_FP_OAM_HASH_DATA_CLEAR(h_data_p); 5731 5732 LOG_DEBUG(BSL_LS_BCM_OAM, 5733 (BSL_META_U(unit, 5734 "OAM(unit %d) Info: _bcm_fp_oam_wb_endpoints_recover" 5735 " - error_done.\n"), unit)); 5736 return (rv); 5737 5738 } 5739 5740 /* 5741 * Function: 5742 * _bcm_fp_oam_wb_csf_recover 5743 * Purpose: 5744 * Recover BHH OAM CSF configuration 5745 * Parameters: 5746 * unit - (IN) BCM device number 5747 * stable_size - OAM module Level2 memory size. 5748 * oam_scache - Pointer to secondary storage buffer pointer. 5749 * Returns: 5750 * BCM_E_XXX 5751 */ 5752 STATIC int 5753 _bcm_fp_oam_bhh_wb_csf_recover(int unit, int stable_size, uint8 **oam_scache) 5754 { 5755 _bhh_fp_oam_ep_data_t *h_data_p = NULL; 5756 _bcm_fp_oam_control_t *oc; 5757 int idx, i; 5758 5759 5760 LOG_DEBUG(BSL_LS_BCM_OAM, 5761 (BSL_META_U(unit, 5762 "OAM(unit %d) Info: " 5763 "_bcm_fp_oam_bhh_wb_csf_recover.\n"), unit)); 5764 /* 5765 * Get OAM control structure. 5766 * Note: Lock taken by calling routine. 5767 */ 5768 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 5769 5770 for (idx = 0; idx < oc->bhh_endpoint_count; idx++) { 5771 5772 h_data_p = &oc->bhh_ep_data[idx]; 5773 if (!h_data_p->in_use) { 5774 continue; 5775 } 5776 5777 sal_memcpy(&h_data_p->csf_tx_counter_size, *oam_scache, sizeof(uint8)); 5778 *oam_scache += sizeof(uint8); 5779 5780 for (i = 0; i < BCM_OAM_LM_COUNTER_MAX; i++) { 5781 sal_memcpy(&h_data_p->csf_tx_update_lm_counter_base_id[i], 5782 *oam_scache, sizeof(uint32)); 5783 *oam_scache += sizeof(uint32); 5784 } 5785 for (i = 0; i < BCM_OAM_LM_COUNTER_MAX; i++) { 5786 sal_memcpy(&h_data_p->csf_tx_update_lm_counter_offset[i], 5787 *oam_scache, sizeof(uint32)); 5788 *oam_scache += sizeof(uint32); 5789 } 5790 } 5791 return BCM_E_NONE; 5792 } 5793 5794 /* 5795 * Function: 5796 * _bcm_fp_oam_bhh_reinit 5797 * Purpose: 5798 * Reconstruct BHH software state. 5799 * Parameters: 5800 * unit - (IN) BCM device number 5801 * Retruns: 5802 * BCM_E_XXX 5803 */ 5804 STATIC int 5805 _bcm_fp_oam_bhh_reinit(int unit) 5806 { 5807 int stable_size; /* Secondary storage size. */ 5808 uint8 *oam_scache = NULL;/* Pointer to scache memory. */ 5809 soc_scache_handle_t scache_handle; /* Scache memory handler. */ 5810 _bcm_fp_oam_control_t *oc; /* Pointer to OAM control structure*/ 5811 int rv = BCM_E_NONE; /* Operation return status. */ 5812 uint16 recovered_ver = 0; 5813 uint16 csf_cntr_size = 0; 5814 uint32 realloc_size = 0; 5815 uint16 ttl_cntr_size = 0; 5816 5817 LOG_DEBUG(BSL_LS_BCM_OAM, 5818 (BSL_META_U(unit, 5819 "OAM(unit %d) Info: OAM warm boot recovery.....\n"), 5820 unit)); 5821 5822 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 5823 5824 /* Get OAM control structure. */ 5825 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 5826 5827 _BCM_OAM_LOCK(oc); 5828 5829 if (oc->ukernel_not_ready) { 5830 _BCM_OAM_UNLOCK(oc); 5831 return BCM_E_NONE; 5832 } 5833 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) { 5834 5835 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 5836 bcmFpOamWbSequenceBhh); 5837 5838 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0, 5839 &oam_scache, BCM_WB_BHH_DEFAULT_VERSION, 5840 &recovered_ver); 5841 if (BCM_E_NOT_FOUND == rv) { 5842 /* Upgrading from SDK release that does not have warmboot state */ 5843 _bcm_fp_oam_bhh_scache_alloc(unit); 5844 rv = BCM_E_NONE; 5845 goto cleanup; 5846 } else if (BCM_FAILURE(rv)) { 5847 goto cleanup; 5848 } 5849 } else { 5850 rv = BCM_E_NONE; 5851 goto cleanup; 5852 } 5853 5854 rv = _bcm_fp_oam_wb_group_recover(unit, stable_size, &oam_scache); 5855 if (BCM_FAILURE(rv)) { 5856 LOG_ERROR(BSL_LS_BCM_OAM, 5857 (BSL_META_U(unit, 5858 "OAM(unit %d) Error: Group recovery failed - " 5859 "%s.\n"), 5860 unit, bcm_errmsg(rv))); 5861 goto cleanup; 5862 } 5863 5864 rv = _bcm_fp_oam_wb_endpoints_recover(unit, stable_size, &oam_scache); 5865 if (BCM_FAILURE(rv)) { 5866 LOG_ERROR(BSL_LS_BCM_OAM, 5867 (BSL_META_U(unit, 5868 "OAM(unit %d) Error: Endpoint recovery failed " 5869 "- %s.\n"), 5870 unit, bcm_errmsg(rv))); 5871 goto cleanup; 5872 } 5873 if (_BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) { 5874 int itr; 5875 _bcm_fp_oam_pm_profile_control_t *pmc = NULL; 5876 5877 pmc = pm_profile_control[unit]; 5878 if (!pmc) { 5879 rv = BCM_E_INIT; 5880 goto cleanup; 5881 } 5882 for(itr = 0; itr < _BCM_OAM_MAX_PM_PROFILES; itr++) { 5883 sal_memcpy(&(pmc->profile_info[itr]), oam_scache, 5884 sizeof(_bcm_fp_oam_pm_profile_int_info_t)); 5885 oam_scache += sizeof(_bcm_fp_oam_pm_profile_int_info_t); 5886 } 5887 } 5888 5889 if (recovered_ver >= BCM_BHH_WB_VERSION_1_2) { 5890 int idx = 0; 5891 _bhh_fp_oam_ep_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 5892 for (idx = 0; idx < oc->bhh_endpoint_count; idx++) { 5893 h_data_p = &oc->bhh_ep_data[idx]; 5894 if (!h_data_p->in_use) { 5895 continue; 5896 } 5897 5898 sal_memcpy(&h_data_p->egr_label_ttl, oam_scache, 5899 sizeof(uint8)); 5900 oam_scache = (oam_scache + sizeof(uint8)); 5901 ttl_cntr_size += sizeof(uint8); 5902 } 5903 } 5904 5905 if (recovered_ver >= BCM_BHH_WB_VERSION_1_1) { 5906 rv = _bcm_fp_oam_bhh_wb_csf_recover(unit, stable_size, &oam_scache); 5907 if (BCM_FAILURE(rv)) { 5908 LOG_ERROR(BSL_LS_BCM_OAM, 5909 (BSL_META_U(unit, 5910 "OAM(unit %d) Error: CSF recovery failed " 5911 "- %s.\n"), 5912 unit, bcm_errmsg(rv))); 5913 goto cleanup; 5914 } 5915 } 5916 5917 if (recovered_ver >= BCM_BHH_WB_VERSION_1_3) { 5918 sal_memcpy(&fp_oam_mpls_tp_ach_channel_type, oam_scache, 5919 sizeof(fp_oam_mpls_tp_ach_channel_type)); 5920 oam_scache += sizeof(fp_oam_mpls_tp_ach_channel_type); 5921 } 5922 5923 /* Increase scache size, in case of upgrading from older version */ 5924 if (recovered_ver < BCM_BHH_WB_VERSION_1_1) { 5925 /* v1.1 add csf counters to scache */ 5926 5927 /* Calculate size taken to accomadate CSF counters */ 5928 csf_cntr_size = 0; 5929 /* Store CSF TX counter size */ 5930 csf_cntr_size += sizeof(uint8); 5931 /* Store CSF TX counters base_ids */ 5932 csf_cntr_size += sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX; 5933 /* Store CSF TX counters offsets */ 5934 csf_cntr_size += sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX; 5935 /* Counters are per-endpoint */ 5936 csf_cntr_size *= oc->bhh_endpoint_count; 5937 5938 realloc_size += csf_cntr_size; 5939 } 5940 5941 /* Increase scache size, in case of upgrading from older version */ 5942 if (recovered_ver < BCM_BHH_WB_VERSION_1_2) { 5943 /* v1.2 add csf counters to scache */ 5944 realloc_size += ttl_cntr_size; 5945 } 5946 5947 if (recovered_ver < BCM_BHH_WB_VERSION_1_3) { 5948 /* Store the BHH ACH Channel Type */ 5949 realloc_size += sizeof(fp_oam_mpls_tp_ach_channel_type); 5950 } 5951 5952 if (realloc_size > 0) { 5953 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 5954 bcmFpOamWbSequenceBhh); 5955 rv = soc_scache_realloc(unit, scache_handle, realloc_size); 5956 if (SOC_FAILURE(rv)) { 5957 LOG_ERROR(BSL_LS_BCM_OAM, 5958 (BSL_META_U(unit,"OAM Error: scache alloc failed - %s.\n"), 5959 bcm_errmsg(rv))); 5960 goto cleanup; 5961 } 5962 } 5963 5964 cleanup: 5965 _BCM_OAM_UNLOCK(oc); 5966 return (rv); 5967 } 5968 5969 #endif 5970 5971 STATIC uint8 5972 bcm_fp_oam_bhh_get_oam_exp_from_encap(_bhh_fp_oam_ep_data_t *h_data_p, 5973 uint8 *encap_data, uint16 encap_length) 5974 { 5975 uint16 oam_label_offset = 0; 5976 _mpls_label_t label; 5977 5978 if (BHH_EP_MPLS_SECTION_TYPE(h_data_p)) { 5979 /* Go back ACH and GAL */ 5980 oam_label_offset = encap_length - 5981 (SHR_BHH_ACH_LENGTH + SHR_BHH_MPLS_LABEL_LENGTH); 5982 } else if (BHH_EP_LSP_TYPE(h_data_p)) { 5983 /* Go back ACH + GAL + OAM label */ 5984 oam_label_offset = encap_length - 5985 (SHR_BHH_ACH_LENGTH + (SHR_BHH_MPLS_LABEL_LENGTH * 2)); 5986 } else { /* PW */ 5987 if (h_data_p->vccv_type == bcmOamBhhVccvGal13) { 5988 /* Go back ACH + GAL + PW label */ 5989 oam_label_offset = encap_length - 5990 (SHR_BHH_ACH_LENGTH + (SHR_BHH_MPLS_LABEL_LENGTH * 2)); 5991 } else { 5992 /* Go back ACH and PW label */ 5993 oam_label_offset = encap_length - 5994 (SHR_BHH_ACH_LENGTH + SHR_BHH_MPLS_LABEL_LENGTH); 5995 } 5996 } 5997 5998 _bcm_fp_oam_mpls_label_unpack(&(encap_data[oam_label_offset]), &label); 5999 return label.exp; 6000 } 6001 /* 6002 * Function: 6003 * _bcm_fp_oam_bhh_group_create 6004 * Purpose: 6005 * Create or replace a BHH group object 6006 * Parameters: 6007 * unit - (IN) BCM device number 6008 * group_info - (IN/OUT) Pointer to an OAM group information. 6009 * Returns: 6010 * BCM_E_XXX 6011 */ 6012 int 6013 _bcm_fp_oam_bhh_group_create(int unit, bcm_oam_group_info_t *group_info) 6014 { 6015 _bcm_fp_oam_control_t *oc = NULL; /* OAM control structure */ 6016 _bhh_fp_oam_group_data_t *oam_group = NULL; /* OAM Group being created */ 6017 int rv = 0; /* return value */ 6018 int bhh_group_idx = 0; 6019 uint32 session_flags = 0; 6020 bhh_sdk_msg_ctrl_sess_set_t msg_sess; 6021 uint16 buffer_len, reply_len; 6022 uint8 *buffer = NULL; 6023 uint8 *buffer_ptr = NULL; 6024 6025 /* Validate input parameter. */ 6026 if (NULL == group_info) { 6027 return (BCM_E_PARAM); 6028 } 6029 6030 /* Get OAM control structure handle. */ 6031 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 6032 if (oc->ukernel_not_ready == 1){ 6033 LOG_ERROR(BSL_LS_BCM_OAM, 6034 (BSL_META_U(unit, 6035 "OAM(unit %d) Error: BTE(ukernel) " 6036 "not ready.\n"), unit)); 6037 return (BCM_E_INIT); 6038 } 6039 /* Validate group id. */ 6040 if (group_info->flags & BCM_OAM_GROUP_WITH_ID) { 6041 _BCM_FP_OAM_BHH_GROUP_INDEX_VALIDATE(group_info->id); 6042 } 6043 6044 _BCM_OAM_LOCK(oc); 6045 6046 /* 6047 * If MA group create is called with replace flag bit set. 6048 * - Check and return error if a group does not exist with the ID. 6049 */ 6050 if (group_info->flags & BCM_OAM_GROUP_REPLACE) { 6051 if (group_info->flags & BCM_OAM_GROUP_WITH_ID) { 6052 bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(group_info->id); 6053 /* Search the list with the MA Group ID value. */ 6054 rv = shr_idxres_list_elem_state(oc->bhh_group_pool, bhh_group_idx); 6055 if (BCM_E_EXISTS != rv) { 6056 _BCM_OAM_UNLOCK(oc); 6057 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 6058 "OAM Error: Group does not exist.\n"))); 6059 return (BCM_E_PARAM); 6060 } 6061 } else { 6062 _BCM_OAM_UNLOCK(oc); 6063 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 6064 "OAM Error: Replace command needs a valid Group ID.\n"))); 6065 return (BCM_E_PARAM); 6066 } 6067 } else if (group_info->flags & BCM_OAM_GROUP_WITH_ID) { 6068 bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(group_info->id); 6069 /* 6070 * If MA group create is called with ID flag bit set. 6071 * - Check and return error if the ID is already in use. 6072 */ 6073 rv = shr_idxres_list_reserve(oc->bhh_group_pool, bhh_group_idx, 6074 bhh_group_idx); 6075 if (BCM_FAILURE(rv)) { 6076 _BCM_OAM_UNLOCK(oc); 6077 return ((rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv); 6078 } 6079 } else { 6080 /* Reserve the next available group index. */ 6081 rv = shr_idxres_list_alloc(oc->bhh_group_pool, 6082 (shr_idxres_element_t *) &bhh_group_idx); 6083 if (BCM_FAILURE(rv)) { 6084 _BCM_OAM_UNLOCK(oc); 6085 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 6086 "OAM Error: Group allocation (GID=%d) %s\n"), 6087 group_info->id, bcm_errmsg(rv))); 6088 return (rv); 6089 } 6090 group_info->id = BCM_OAM_BHH_GET_SDK_GROUP(bhh_group_idx); 6091 } 6092 6093 /* Get this group memory to store group information. */ 6094 oam_group = &(oc->bhh_group_data[bhh_group_idx]); 6095 6096 /* Store the group name. */ 6097 sal_memcpy(oam_group->name, group_info->name, 6098 BCM_OAM_GROUP_NAME_LENGTH); 6099 6100 /* Store the group flags. */ 6101 oam_group->flags = group_info->flags; 6102 6103 /* Set LMEP as not configured */ 6104 oam_group->lmep_id = _BHH_FP_OAM_INVALID_LMEP_ID; 6105 6106 oam_group->group_id = group_info->id; 6107 6108 oam_group->in_use = 1; 6109 6110 if (group_info->flags & BCM_OAM_GROUP_REPLACE) { 6111 /* Send message to uC to set the Soft RDI */ 6112 if (group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) { 6113 6114 /* Set the RDI flag in session bits */ 6115 session_flags |= SHR_BHH_SESS_SET_F_RDI; 6116 6117 /* Get the session is from endpoint */ 6118 msg_sess.sess_id = 6119 BCM_OAM_BHH_GET_UKERNEL_EP(oam_group->lmep_id); 6120 6121 /* Pack control message data into DMA buffer */ 6122 msg_sess.flags = session_flags; 6123 6124 buffer = oc->bhh_dma_buffer; 6125 buffer_ptr = 6126 bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess); 6127 buffer_len = buffer_ptr - buffer; 6128 6129 /* Send BHH Session Update message to uC */ 6130 rv = _bcm_fp_oam_msg_send_receive(unit, 6131 MOS_MSG_CLASS_BHH, 6132 MOS_MSG_SUBCLASS_BHH_SESS_SET, 6133 buffer_len, 0, 6134 MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY, 6135 &reply_len); 6136 if (BCM_FAILURE(rv)) { 6137 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 6138 "OAM(unit %d) Error: ukernel msg failed for" 6139 "%s.\n"), unit, bcm_errmsg(rv))); 6140 _BCM_OAM_UNLOCK(oc); 6141 return (BCM_E_INTERNAL); 6142 } 6143 } 6144 } 6145 6146 _BCM_OAM_UNLOCK(oc); 6147 return rv; 6148 } 6149 6150 /* 6151 * Function: 6152 * _bcm_fp_oam_bhh_group_get 6153 * Purpose: 6154 * Get a BHH group object. 6155 * Parameters: 6156 * unit - (IN) BCM device number 6157 * group_info - (IN/OUT) Pointer to an OAM group Id. 6158 * Returns: 6159 * BCM_E_XXX 6160 */ 6161 int 6162 _bcm_fp_oam_bhh_group_get(int unit, bcm_oam_group_info_t *group_info) { 6163 6164 _bcm_fp_oam_control_t *oc = NULL; /* OAM control structure */ 6165 _bhh_fp_oam_group_data_t *group_p; /* Handle to S/w Group Data */ 6166 int rv = 0; /* Return Value */ 6167 uint16 buffer_len, reply_len; 6168 uint8 *buffer = NULL; 6169 uint8 *buffer_ptr = NULL; 6170 bhh_sdk_msg_ctrl_sess_get_t msg; 6171 int bhh_group_idx = 0; 6172 int sess_id = 0; 6173 6174 /* Get OAM control structure handle. */ 6175 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 6176 6177 6178 bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(group_info->id); 6179 /* Get Handle to Local DB */ 6180 group_p = &(oc->bhh_group_data[bhh_group_idx]); 6181 if (!(group_p->in_use)) { 6182 return BCM_E_NOT_FOUND; 6183 } 6184 6185 if (group_p->lmep_id != _BHH_FP_OAM_INVALID_LMEP_ID) { 6186 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(group_p->lmep_id); 6187 rv = _bcm_fp_oam_msg_send_receive(unit, 6188 MOS_MSG_CLASS_BHH, 6189 MOS_MSG_SUBCLASS_BHH_SESS_GET, 6190 sess_id, 0, 6191 MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY, 6192 &reply_len); 6193 if (BCM_FAILURE(rv)) { 6194 LOG_ERROR(BSL_LS_BCM_OAM, 6195 (BSL_META_U(unit, 6196 "OAM(unit %d) Error: ukernel msg failed for" 6197 " EP=%d %s.\n"), unit, group_p->lmep_id, 6198 bcm_errmsg(rv))); 6199 return (rv); 6200 } 6201 6202 /* Pack control message data into DMA buffer */ 6203 buffer = oc->bhh_dma_buffer; 6204 buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg); 6205 buffer_len = buffer_ptr - buffer; 6206 6207 if (reply_len != buffer_len) { 6208 rv = BCM_E_INTERNAL; 6209 LOG_ERROR(BSL_LS_BCM_OAM, 6210 (BSL_META_U(unit, 6211 "OAM(unit %d) Error: ukernel msg failed for" 6212 " EP=%d %s.\n"), unit, group_p->lmep_id, 6213 bcm_errmsg(rv))); 6214 return (rv); 6215 } else { 6216 6217 if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){ 6218 group_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT; 6219 } 6220 if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){ 6221 group_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI; 6222 } 6223 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){ 6224 group_info->faults |= 6225 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL; 6226 } 6227 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){ 6228 group_info->faults |= 6229 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID; 6230 } 6231 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){ 6232 group_info->faults |= 6233 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID; 6234 } 6235 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){ 6236 group_info->faults |= 6237 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD; 6238 } 6239 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){ 6240 group_info->faults |= 6241 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY; 6242 } 6243 if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) { 6244 group_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS; 6245 } 6246 if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) { 6247 group_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI; 6248 } 6249 if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) { 6250 group_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI; 6251 } 6252 } 6253 } 6254 sal_memcpy(group_info->name, group_p->name, BCM_OAM_GROUP_NAME_LENGTH); 6255 group_info->flags = group_p->flags; 6256 6257 return rv; 6258 } 6259 6260 #define _BCM_FP_OAM_MAX_CCM_INTERVALS 8 6261 /* 6262 * FP OAM CCM intervals array initialization.. 6263 */ 6264 STATIC uint32 _fp_oam_ccm_intervals[] = 6265 { 6266 BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED, 6267 BCM_OAM_ENDPOINT_CCM_PERIOD_3MS, 6268 BCM_OAM_ENDPOINT_CCM_PERIOD_10MS, 6269 BCM_OAM_ENDPOINT_CCM_PERIOD_100MS, 6270 BCM_OAM_ENDPOINT_CCM_PERIOD_1S, 6271 BCM_OAM_ENDPOINT_CCM_PERIOD_10S, 6272 BCM_OAM_ENDPOINT_CCM_PERIOD_1M, 6273 BCM_OAM_ENDPOINT_CCM_PERIOD_10M, 6274 _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED 6275 }; 6276 6277 6278 /* 6279 * Function: 6280 * _bcm_fp_oam_period_validate 6281 * Purpose: 6282 * Validates whether OAM period is in allowed range or not . 6283 * Parameters: 6284 * period - (IN) OAM PDU interval in milli seconds. 6285 * Returns: 6286 * BCM_E_XXX 6287 */ 6288 STATIC int 6289 _bcm_fp_oam_period_validate(int period) 6290 { 6291 int q_period = 0; /* OAM period value. */ 6292 6293 /* Find whether requested period is matching with supported period or not */ 6294 for (q_period = 0; q_period < 6295 _BCM_FP_OAM_MAX_CCM_INTERVALS; q_period++) { 6296 if (period == _fp_oam_ccm_intervals[q_period]) { 6297 return BCM_E_NONE; 6298 } 6299 } 6300 6301 return BCM_E_PARAM; 6302 } 6303 6304 /* 6305 * Function: 6306 * _bcm_fp_oam_bhh_appl_callback 6307 * Purpose: 6308 * Update FW BHH appl state 6309 * Parameters: 6310 * unit - (IN) Unit number. 6311 * uC - (IN) core number. 6312 * stage - (IN) core reset stage. 6313 * user_data - (IN) data pointer. 6314 * Returns: 6315 * BCM_E_XXX 6316 * Notes: 6317 */ 6318 6319 int _bcm_fp_oam_bhh_appl_callback(int unit, 6320 int uC, 6321 soc_cmic_uc_shutdown_stage_t stage, 6322 void *user_data) { 6323 _bcm_fp_oam_control_t *oc; 6324 6325 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 6326 _BCM_OAM_LOCK(oc); 6327 oc->ukernel_not_ready = 1; 6328 6329 _BCM_OAM_UNLOCK(oc); 6330 6331 return BCM_E_NONE; 6332 } 6333 6334 /* 6335 * * Function: 6336 * _bcm_fp_oam_bhh_endpoint_create 6337 * Purpose: 6338 * Create or replace a BHH FP OAM endpoint object 6339 * Parameters: 6340 * unit - (IN) Unit number. 6341 * endpoint_info - (IN/OUT) Pointer to endpoint information buffer. 6342 * Returns: 6343 * BCM_E_XXX 6344 * Notes: 6345 */ 6346 int 6347 _bcm_fp_oam_bhh_endpoint_create(int unit, 6348 bcm_oam_endpoint_info_t *endpoint_info) 6349 { 6350 _bcm_fp_oam_control_t *oc; 6351 _bhh_fp_oam_ep_data_t *hash_data = NULL;/* Endpoint hash data pointer. */ 6352 _bhh_fp_oam_ep_data_t h_stored_data; /* dummy Endpoint hash data */ 6353 _bhh_fp_oam_group_data_t *group_p; /* Pointer to group data. */ 6354 _bhh_fp_oam_hash_key_t hash_key; /* Hash Key buffer. */ 6355 int rv = BCM_E_NONE; /* Operation return status. */ 6356 int is_remote = 0; /* Remote endpoint status. */ 6357 int is_replace; 6358 int is_local = 0; 6359 int sglp = 0; /* Source global logical port. */ 6360 int dglp = 0; /* Dest global logical port. */ 6361 bcm_gport_t dgpp = 0; 6362 bcm_module_t module_id; /* Module ID */ 6363 bcm_port_t port_id; 6364 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 6365 int local_id; 6366 bhh_sdk_msg_ctrl_rmep_create_t msg_rmep_create; 6367 uint8 *buffer, *buffer_ptr; 6368 uint16 buffer_len, reply_len; 6369 uint32 session_flags; 6370 int bhh_pool_ep_idx = 0; 6371 int bhh_group_idx = 0; 6372 int i = 0; 6373 bcm_trunk_member_t trunk_member; 6374 _bhh_oam_lm_dm_info_t counter_info; 6375 uint8 lm_pdu_counter_offset = 0; 6376 _l2_header_t l2_hdr; 6377 bcm_stat_group_mode_t stat_group; 6378 bcm_stat_object_t stat_object; 6379 uint32 stat_mode; 6380 uint32 stat_pool_number; 6381 uint32 base_index; 6382 6383 LOG_DEBUG(BSL_LS_BCM_OAM, 6384 (BSL_META_U(unit, 6385 "BHH(unit %d) Info: _bcm_fp_oam_bhh_endpoint_create" 6386 "Endpoint ID=%d.\n"), unit, endpoint_info->id)); 6387 6388 _BCM_OAM_BHH_IS_VALID(unit); 6389 6390 /* Validate input parameter. */ 6391 if (NULL == endpoint_info) { 6392 return (BCM_E_PARAM); 6393 } 6394 6395 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 6396 _BCM_FP_OAM_BHH_GROUP_INDEX_VALIDATE(endpoint_info->group); 6397 _BCM_OAM_LOCK(oc); 6398 6399 if (oc->ukernel_not_ready == 1){ 6400 LOG_ERROR(BSL_LS_BCM_OAM, 6401 (BSL_META_U(unit, 6402 "OAM(unit %d) Error: BTE(ukernel) " 6403 "not ready.\n"), unit)); 6404 _BCM_OAM_UNLOCK(oc); 6405 return (BCM_E_INIT); 6406 } 6407 6408 /* Perform BHH specific validation checks */ 6409 /* BHH EP can only be at the MAX Level */ 6410 if (endpoint_info->level != _BCM_OAM_EP_LEVEL_MAX ) { 6411 LOG_ERROR(BSL_LS_BCM_OAM, 6412 (BSL_META_U(unit, 6413 "OAM(unit %d) Error: EP Level should be equal to %d\n"), 6414 unit, _BCM_OAM_EP_LEVEL_MAX)); 6415 _BCM_OAM_UNLOCK(oc); 6416 return (BCM_E_PARAM); 6417 } 6418 6419 6420 /* For replace operation, endpoint ID is required. */ 6421 if ((endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) 6422 && !(endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID)) { 6423 _BCM_OAM_UNLOCK(oc); 6424 return (BCM_E_PARAM); 6425 } 6426 6427 bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(endpoint_info->group); 6428 rv = shr_idxres_list_elem_state(oc->bhh_group_pool, bhh_group_idx); 6429 if (BCM_E_EXISTS != rv) { 6430 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 6431 "Group (GID:%d) does not exist.\n"), endpoint_info->group)); 6432 _BCM_OAM_UNLOCK(oc); 6433 return (BCM_E_PARAM); 6434 } 6435 6436 /*Validate CCM period */ 6437 rv = _bcm_fp_oam_period_validate(endpoint_info->ccm_period); 6438 if (BCM_FAILURE(rv)) { 6439 LOG_ERROR(BSL_LS_BCM_OAM, 6440 (BSL_META_U(unit, "OAM Error: Invalid CCM period : %d \n"), 6441 endpoint_info->ccm_period)); 6442 _BCM_OAM_UNLOCK(oc); 6443 return rv; 6444 } 6445 6446 group_p = &(oc->bhh_group_data[bhh_group_idx]); 6447 if (!(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE)) { 6448 6449 /* Only One LMEP should be configured per group */ 6450 if (group_p->lmep_id != _FP_OAM_INVALID_LMEP_ID) { 6451 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 6452 "LMEP already existst for the group\n"))); 6453 _BCM_OAM_UNLOCK(oc); 6454 return (BCM_E_EXISTS); 6455 } 6456 /*Atleast one valid session entry should be present for endpoint*/ 6457 if (endpoint_info->session_num_entries == 6458 _BCM_FP_OAM_INVALID_NUM_SESSION_ENTRIES) { 6459 LOG_ERROR(BSL_LS_BCM_OAM, 6460 (BSL_META_U(unit, 6461 "OAM(unit %d) Error: number of session entries " 6462 "cannot be zero for EP\n"), unit)); 6463 _BCM_OAM_UNLOCK(oc); 6464 return (BCM_E_PARAM); 6465 } 6466 } 6467 6468 /* Calculate the hash key for given enpoint input parameters. */ 6469 _bhh_fp_oam_ep_hash_key_construct(unit, oc, endpoint_info, &hash_key); 6470 rv = shr_htb_find(oc->bhh_mep_htbl, hash_key, 6471 (shr_htb_data_t *)&h_stored_data, 0); 6472 if (BCM_SUCCESS(rv) 6473 && !(endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE)) { 6474 6475 LOG_ERROR(BSL_LS_BCM_OAM, 6476 (BSL_META_U(unit, 6477 "OAM(unit %d) Error: Endpoint ID=%d %s.\n"), 6478 unit, endpoint_info->id, bcm_errmsg(BCM_E_EXISTS))); 6479 6480 /* Endpoint must not be in use expect for Replace operation. */ 6481 _BCM_OAM_UNLOCK(oc); 6482 return (BCM_E_EXISTS); 6483 6484 } else { 6485 6486 LOG_DEBUG(BSL_LS_BCM_OAM, 6487 (BSL_META_U(unit, 6488 "OAM(unit %d) Info: Endpoint ID=%d " 6489 "Available. %s.\n"), 6490 unit, endpoint_info->id, bcm_errmsg(rv))); 6491 6492 } 6493 6494 6495 /* Get MEP remote endpoint status. */ 6496 is_remote = (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0; 6497 6498 is_replace = ((endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) != 0); 6499 6500 /* Validate EP Id if BCM_OAM_ENDPOINT_WITH_ID flag is set */ 6501 if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) { 6502 if((endpoint_info->id < oc->bhh_base_endpoint_id) || 6503 (endpoint_info->id >= (oc->bhh_base_endpoint_id 6504 + oc->bhh_endpoint_count))) { 6505 _BCM_OAM_UNLOCK(oc); 6506 return (BCM_E_PARAM); 6507 } 6508 } 6509 6510 /* Validate remote EP Id if BCM_OAM_ENDPOINT_REMOTE flag is set */ 6511 if (is_remote) { 6512 if((endpoint_info->local_id < oc->bhh_base_endpoint_id) || 6513 (endpoint_info->local_id >= (oc->bhh_base_endpoint_id 6514 + oc->bhh_endpoint_count))) { 6515 _BCM_OAM_UNLOCK(oc); 6516 return (BCM_E_PARAM); 6517 } 6518 } 6519 6520 /* Validate if the gport is an MPLS port for PW MEP */ 6521 if (endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv) { 6522 if (-1 == BCM_GPORT_MPLS_PORT_ID_GET(endpoint_info->gport)) { 6523 _BCM_OAM_UNLOCK(oc); 6524 return BCM_E_PARAM; 6525 } 6526 } 6527 6528 if (is_replace) { 6529 if (is_remote) { 6530 LOG_ERROR(BSL_LS_BCM_OAM, 6531 (BSL_META_U(unit, 6532 "OAM(unit %d) Error: Replace is " 6533 " not allowed on remote endpoint\n"), 6534 unit)); 6535 _BCM_OAM_UNLOCK(oc); 6536 return (BCM_E_PARAM); 6537 } 6538 bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_info->id); 6539 hash_data = &oc->bhh_ep_data[bhh_pool_ep_idx]; 6540 if (!hash_data->in_use) { 6541 _BCM_OAM_UNLOCK(oc); 6542 return (BCM_E_NOT_FOUND); 6543 } 6544 if(!BHH_EP_MPLS_SECTION_TYPE(hash_data)){ 6545 if ((hash_data->egress_if != endpoint_info->intf_id) || 6546 (hash_data->label != endpoint_info->mpls_label) || 6547 (hash_data->egr_label != endpoint_info->egress_label.label) || 6548 (hash_data->gport != endpoint_info->gport) || 6549 (hash_data->period != endpoint_info->ccm_period) || 6550 (hash_data->vccv_type != endpoint_info->vccv_type) || 6551 (hash_data->vpn != endpoint_info->vpn) || 6552 (hash_data->name != endpoint_info->name) || 6553 (hash_data->level != endpoint_info->level) || 6554 (hash_data->type != endpoint_info->type) || 6555 (hash_data->ep_id != endpoint_info->id) || 6556 (hash_data->group_index != endpoint_info->group)) { 6557 LOG_ERROR(BSL_LS_BCM_OAM, 6558 (BSL_META_U(unit, 6559 "OAM(unit %d) Error: Parameters passed are " 6560 " not valid to replace\n"), 6561 unit)); 6562 _BCM_OAM_UNLOCK(oc); 6563 return (BCM_E_PARAM); 6564 } 6565 } else { 6566 if ((hash_data->gport != endpoint_info->gport) || 6567 (hash_data->period != endpoint_info->ccm_period) || 6568 (hash_data->name != endpoint_info->name) || 6569 (hash_data->level != endpoint_info->level) || 6570 (hash_data->type != endpoint_info->type) || 6571 (hash_data->ep_id != endpoint_info->id) || 6572 (hash_data->group_index != endpoint_info->group) || 6573 (hash_data->vlan != endpoint_info->vlan) || 6574 (hash_data->inner_vlan != endpoint_info->inner_vlan) || 6575 (hash_data->outer_tpid != endpoint_info->outer_tpid) || 6576 (hash_data->inner_tpid != endpoint_info->inner_tpid) || 6577 (hash_data->vlan_pri != endpoint_info->pkt_pri) || 6578 (hash_data->inner_vlan_pri != endpoint_info->inner_pkt_pri)) { 6579 LOG_ERROR(BSL_LS_BCM_OAM, 6580 (BSL_META_U(unit, 6581 "OAM(unit %d) Error: Parameters passed are" 6582 " not valid to replace\n"), 6583 unit)); 6584 _BCM_OAM_UNLOCK(oc); 6585 return (BCM_E_PARAM); 6586 } 6587 } 6588 } 6589 6590 /* Interface validation check */ 6591 if(!BHH_EP_MPLS_SECTION_TYPE(endpoint_info)){ 6592 if ((!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, endpoint_info->intf_id)) && 6593 (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, endpoint_info->intf_id))) { 6594 LOG_ERROR(BSL_LS_BCM_OAM, 6595 (BSL_META_U(unit, 6596 "OAM(unit %d) Error: intf type" 6597 " not valid. It should be DVP_EGRESS or " 6598 "L3_EGRESS type.\n"), 6599 unit)); 6600 _BCM_OAM_UNLOCK(oc); 6601 return (BCM_E_PARAM); 6602 } 6603 } 6604 /* Now that we passed the validation checks 6605 * Create a new endpoint with the requested ID. */ 6606 if ( !is_remote && (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) ) { 6607 6608 bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_info->id); 6609 6610 hash_data = &oc->bhh_ep_data[bhh_pool_ep_idx]; 6611 6612 if (!is_replace && hash_data->in_use) { 6613 _BCM_OAM_UNLOCK(oc); 6614 return (BCM_E_EXISTS); 6615 } 6616 6617 if(!is_replace) { 6618 rv = shr_idxres_list_reserve(oc->bhh_pool, bhh_pool_ep_idx, 6619 bhh_pool_ep_idx); 6620 if (BCM_FAILURE(rv)) { 6621 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 6622 LOG_ERROR(BSL_LS_BCM_OAM, 6623 (BSL_META_U(unit, 6624 "BHH(unit %d) Error: Endpoint reserve (EP=%d) - %s.\n"), 6625 unit, endpoint_info->id, bcm_errmsg(rv))); 6626 _BCM_OAM_UNLOCK(oc); 6627 return (rv); 6628 } 6629 } 6630 } else { 6631 6632 /* BHH uses local and remote same index */ 6633 if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) { 6634 bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP 6635 (endpoint_info->local_id); 6636 } 6637 else { 6638 /* Allocate the next available endpoint index. */ 6639 rv = shr_idxres_list_alloc(oc->bhh_pool, 6640 (shr_idxres_element_t *)&bhh_pool_ep_idx); 6641 if (BCM_FAILURE(rv)) { 6642 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_FULL) : rv; 6643 LOG_ERROR(BSL_LS_BCM_OAM, 6644 (BSL_META_U(unit, 6645 "BHH(unit %d) Error: Endpoint alloc failed - %s.\n"), 6646 unit, bcm_errmsg(rv))); 6647 _BCM_OAM_UNLOCK(oc); 6648 return (rv); 6649 } 6650 } 6651 endpoint_info->id = BCM_OAM_BHH_GET_SDK_EP(bhh_pool_ep_idx); 6652 } 6653 6654 /* Get the hash data pointer where the data is to be stored. */ 6655 hash_data = &oc->bhh_ep_data[bhh_pool_ep_idx]; 6656 6657 if (is_remote) { 6658 6659 if (!hash_data->in_use) { 6660 _BCM_OAM_UNLOCK(oc); 6661 return (BCM_E_NOT_FOUND); 6662 } else if (hash_data->flags & BCM_OAM_ENDPOINT_REMOTE) { 6663 _BCM_OAM_UNLOCK(oc); 6664 return (BCM_E_EXISTS); 6665 } 6666 msg_rmep_create.sess_id = bhh_pool_ep_idx; 6667 msg_rmep_create.flags = 0; 6668 msg_rmep_create.enable = 1; 6669 msg_rmep_create.remote_mep_id = endpoint_info->name; 6670 msg_rmep_create.period = endpoint_info->ccm_period; 6671 6672 /* Pack control message data into DMA buffer */ 6673 buffer = oc->bhh_dma_buffer; 6674 buffer_ptr = bhh_sdk_msg_ctrl_rmep_create_pack(buffer, 6675 &msg_rmep_create); 6676 buffer_len = buffer_ptr - buffer; 6677 6678 /* Send BHH Session Update message to uC */ 6679 rv = _bcm_fp_oam_msg_send_receive(unit, 6680 MOS_MSG_CLASS_BHH, 6681 MOS_MSG_SUBCLASS_BHH_RMEP_CREATE, 6682 buffer_len, 0, 6683 MOS_MSG_SUBCLASS_BHH_RMEP_CREATE_REPLY, 6684 &reply_len); 6685 if (BCM_FAILURE(rv) || (reply_len != 0)) { 6686 LOG_ERROR(BSL_LS_BCM_OAM, 6687 (BSL_META_U(unit, 6688 "BHH(unit %d) Error: Endpoint create " 6689 "(EP=%d) - %s.\n"), 6690 unit, endpoint_info->id, bcm_errmsg(rv))); 6691 _BCM_OAM_UNLOCK(oc); 6692 return (BCM_E_INTERNAL); 6693 } 6694 } else { 6695 /* Resolve given endpoint gport value to SGLP and DGLP values. */ 6696 rv = _bcm_fp_oam_endpoint_gport_resolve(unit, endpoint_info, 6697 &sglp, &dglp, &dgpp, 6698 &trunk_id, &trunk_member); 6699 if (BCM_FAILURE(rv)) { 6700 LOG_ERROR(BSL_LS_BCM_OAM, 6701 (BSL_META_U(unit, 6702 "OAM(unit %d) Error: Gport resolve (EP=%d) - %s.\n"), 6703 unit, endpoint_info->id, bcm_errmsg(rv))); 6704 _BCM_OAM_UNLOCK(oc); 6705 /* Return ID back to free MEP ID pool.*/ 6706 rv = shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx); 6707 return (rv); 6708 } 6709 6710 /* Clear the hash data element contents before storing the values. */ 6711 _BHH_FP_OAM_HASH_DATA_CLEAR(hash_data); 6712 hash_data->type = endpoint_info->type; 6713 hash_data->ep_id = endpoint_info->id; 6714 hash_data->group_index = endpoint_info->group; 6715 hash_data->level = endpoint_info->level; 6716 hash_data->vlan = endpoint_info->vlan; 6717 hash_data->inner_vlan = endpoint_info->inner_vlan; 6718 hash_data->outer_tpid = endpoint_info->outer_tpid; 6719 hash_data->inner_tpid = endpoint_info->inner_tpid; 6720 hash_data->vlan_pri = endpoint_info->pkt_pri; 6721 hash_data->inner_vlan_pri = endpoint_info->inner_pkt_pri; 6722 hash_data->gport = endpoint_info->gport; 6723 hash_data->sglp = sglp; 6724 hash_data->dglp = dglp; 6725 hash_data->flags = endpoint_info->flags; 6726 hash_data->flags2 = endpoint_info->flags2; 6727 hash_data->int_pri = endpoint_info->int_pri; 6728 hash_data->period = endpoint_info->ccm_period; 6729 hash_data->vccv_type = endpoint_info->vccv_type; 6730 hash_data->vpn = endpoint_info->vpn; 6731 hash_data->name = endpoint_info->name; 6732 hash_data->egress_if = endpoint_info->intf_id; 6733 hash_data->label = endpoint_info->mpls_label; 6734 hash_data->egr_label = endpoint_info->egress_label.label; 6735 hash_data->egr_label_exp = endpoint_info->egress_label.exp; 6736 hash_data->egr_label_ttl = endpoint_info->egress_label.ttl; 6737 hash_data->trunk_index = endpoint_info->trunk_index; 6738 hash_data->hw_session_id = endpoint_info->session_id; 6739 hash_data->hw_session_num_entries = endpoint_info->session_num_entries; 6740 6741 sal_memcpy(hash_data->dst_mac_address, endpoint_info->dst_mac_address, 6742 _BHH_MAC_ADDR_LENGTH); 6743 sal_memcpy(hash_data->src_mac_address, endpoint_info->src_mac_address, 6744 _BHH_MAC_ADDR_LENGTH); 6745 hash_data->trunk_id = trunk_id; 6746 6747 hash_data->pm_profile_attached = _BCM_OAM_INVALID_INDEX; 6748 hash_data->in_use = 1; 6749 group_p->lmep_id = endpoint_info->id; 6750 6751 if (BCM_TRUNK_INVALID != trunk_id) { 6752 endpoint_info->gport = trunk_member.gport; 6753 hash_data->resolved_trunk_gport = trunk_member.gport; 6754 } 6755 /* Get the Trunk, Port and Modid info for this Gport */ 6756 rv = _bcm_esw_gport_resolve(unit, 6757 endpoint_info->gport, &module_id, &port_id, 6758 &trunk_id, &local_id); 6759 6760 if (BCM_FAILURE(rv)) { 6761 LOG_ERROR(BSL_LS_BCM_OAM, 6762 (BSL_META_U(unit, 6763 "BHH(unit %d) Error: Gport resolve (EP=%d) -" 6764 " %s.\n"), 6765 unit, endpoint_info->id, bcm_errmsg(rv))); 6766 /* Return ID back to free MEP ID pool.*/ 6767 rv = shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx); 6768 _BCM_OAM_UNLOCK(oc); 6769 return (rv); 6770 } 6771 6772 /* Get local port used for TX BHH packet */ 6773 rv = _bcm_esw_modid_is_local(unit, module_id, &is_local); 6774 if(BCM_FAILURE(rv)) { 6775 LOG_ERROR(BSL_LS_BCM_OAM, 6776 (BSL_META_U(unit, 6777 "BHH(unit %d) Error: local port for " 6778 "BHH TX failed(ep=%d) - %s.\n"), 6779 unit, endpoint_info->id, bcm_errmsg(rv))); 6780 /* Return ID back to free MEP ID pool.*/ 6781 rv = shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx); 6782 _BCM_OAM_UNLOCK(oc); 6783 return (rv); 6784 } 6785 6786 if (!is_local) { /* HG port */ 6787 rv = bcm_esw_stk_modport_get(unit, module_id, &port_id); 6788 if(BCM_FAILURE(rv)) { 6789 LOG_ERROR(BSL_LS_BCM_OAM, 6790 (BSL_META_U(unit, 6791 "BHH(unit %d) Error: HG port get failed " 6792 "(EP=%d) - %s.\n"), 6793 unit, endpoint_info->id, bcm_errmsg(rv))); 6794 /* Return ID back to free MEP ID pool.*/ 6795 rv = shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx); 6796 _BCM_OAM_UNLOCK(oc); 6797 return (rv); 6798 } 6799 } 6800 /* Set Endpoint config entry */ 6801 hash_data->uc_session_id = bhh_pool_ep_idx; 6802 6803 sal_memset(&counter_info, 0, sizeof(counter_info)); 6804 counter_info.counter_size = 6805 endpoint_info->ccm_tx_update_lm_counter_size; 6806 hash_data->ccm_tx_counter_size = 6807 endpoint_info->ccm_tx_update_lm_counter_size; 6808 for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) 6809 { 6810 counter_info.counter_base_id[i] = 6811 endpoint_info->ccm_tx_update_lm_counter_base_id[i]; 6812 hash_data->ccm_tx_update_lm_counter_base_id[i] = 6813 endpoint_info->ccm_tx_update_lm_counter_base_id[i]; 6814 counter_info.counter_offset[i] = 6815 endpoint_info->ccm_tx_update_lm_counter_offset[i]; 6816 hash_data->ccm_tx_update_lm_counter_offset[i] = 6817 endpoint_info->ccm_tx_update_lm_counter_offset[i]; 6818 counter_info.counter_action[i] = bcmOamCounterActionIncrement; 6819 counter_info.byte_count_offset[i] = 0; 6820 } 6821 counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE; 6822 counter_info.oam_replacement_offset = SHR_BHH_LM_OFFSET_INSIDE_CCM_PDU; 6823 6824 session_flags = (is_replace) ? 0 : SHR_BHH_SESS_SET_F_CREATE; 6825 if(!is_replace) { 6826 6827 bhh_sdk_msg_ctrl_sess_set_t msg_sess; 6828 uint16 encap_length = 0; 6829 6830 sal_memset(&msg_sess, 0, sizeof(msg_sess)); 6831 /* 6832 * Set the BHH encapsulation data 6833 * 6834 * The function _bcm_fp_oam_bhh_encap_create() is called first 6835 * since this sets some fields in 'hash_data' which are 6836 * used in the message. 6837 */ 6838 rv = _bcm_fp_oam_bhh_encap_create(unit, 6839 module_id, 6840 port_id, 6841 hash_data, 6842 msg_sess.encap_data, 6843 &msg_sess.encap_type, 6844 &encap_length, 6845 &counter_info, hash_data->int_pri, 6846 hash_data->egr_label_exp, 6847 hash_data->egr_label_ttl); 6848 6849 if(BCM_FAILURE(rv)) 6850 { 6851 LOG_ERROR(BSL_LS_BCM_OAM, 6852 (BSL_META_U(unit, 6853 "BHH(unit %d) Error: Encap create failed " 6854 "(EP=%d) - %s.\n"), 6855 unit, endpoint_info->id, bcm_errmsg(rv))); 6856 /* Return ID back to free MEP ID pool.*/ 6857 rv = shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx); 6858 _BCM_OAM_UNLOCK(oc); 6859 return (rv); 6860 } 6861 6862 rv = _bcm_fp_oam_l2_header_get(unit, hash_data, 6863 port_id, SHR_BHH_L2_ETYPE_MPLS_UCAST, 6864 &l2_hdr, &lm_pdu_counter_offset); 6865 if (BCM_FAILURE(rv)) { 6866 _BCM_OAM_UNLOCK(oc); 6867 return rv; 6868 } 6869 session_flags |= SHR_BHH_SESS_SET_F_CCM; 6870 6871 if (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) 6872 session_flags |= SHR_BHH_SESS_SET_F_MIP; 6873 6874 if (group_p->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) { 6875 session_flags |= SHR_BHH_SESS_SET_F_RDI; 6876 } 6877 6878 msg_sess.encap_length = encap_length; 6879 msg_sess.sess_id = bhh_pool_ep_idx; 6880 msg_sess.flags = session_flags; 6881 6882 msg_sess.mel = hash_data->level; 6883 msg_sess.mep_id = hash_data->name; 6884 sal_memcpy(msg_sess.meg_id, group_p->name, 6885 BCM_OAM_GROUP_NAME_LENGTH); 6886 msg_sess.period = endpoint_info->ccm_period; 6887 msg_sess.if_num = endpoint_info->intf_id; 6888 msg_sess.tx_port = port_id; 6889 msg_sess.num_session_entries = endpoint_info->session_num_entries; 6890 _bcm_esw_stat_get_counter_id_info(unit, endpoint_info->session_id, 6891 &stat_group, &stat_object, 6892 &stat_mode, &stat_pool_number, 6893 &base_index); 6894 msg_sess.lm_counter_index = SOC_OLP_TX_CTR(stat_pool_number, 6895 base_index); 6896 6897 if (!BHH_EP_MPLS_SECTION_TYPE(endpoint_info)) { 6898 msg_sess.mpls_label = endpoint_info->mpls_label; 6899 } else { 6900 msg_sess.mpls_label = SHR_BHH_MPLS_GAL_LABEL; 6901 } 6902 6903 if (0 != l2_hdr.vlan_tag_inner.tpid) { 6904 msg_sess.inner_vlan = l2_hdr.vlan_tag_inner.tci.vid; 6905 } 6906 6907 if (0 != l2_hdr.vlan_tag.tpid) { 6908 msg_sess.outer_vlan = l2_hdr.vlan_tag.tci.vid; 6909 } 6910 6911 switch (endpoint_info->type) { 6912 case bcmOAMEndpointTypeBHHMPLS: 6913 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_LSP; 6914 msg_sess.priority = endpoint_info->mpls_exp; 6915 break; 6916 6917 case bcmOAMEndpointTypeBHHMPLSVccv: 6918 switch(endpoint_info->vccv_type) { 6919 6920 case bcmOamBhhVccvChannelAch: 6921 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_1; 6922 msg_sess.priority = endpoint_info->mpls_exp; 6923 break; 6924 6925 case bcmOamBhhVccvRouterAlert: 6926 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_2; 6927 msg_sess.priority = endpoint_info->mpls_exp; 6928 break; 6929 6930 case bcmOamBhhVccvTtl: 6931 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_3; 6932 msg_sess.priority = endpoint_info->mpls_exp; 6933 break; 6934 6935 case bcmOamBhhVccvGal13: 6936 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_4; 6937 msg_sess.priority = endpoint_info->mpls_exp; 6938 break; 6939 6940 default: 6941 return BCM_E_PARAM; 6942 break; 6943 } 6944 break; 6945 6946 case bcmOAMEndpointTypeBhhSection: 6947 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION; 6948 msg_sess.priority = 0; 6949 break; 6950 case bcmOAMEndpointTypeBhhSectionInnervlan: 6951 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_INNERVLAN; 6952 msg_sess.priority = endpoint_info->inner_pkt_pri; 6953 break; 6954 case bcmOAMEndpointTypeBhhSectionOuterVlan: 6955 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTERVLAN; 6956 msg_sess.priority = endpoint_info->pkt_pri; 6957 break; 6958 case bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan: 6959 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTER_PLUS_INNERVLAN; 6960 msg_sess.priority = endpoint_info->pkt_pri; 6961 break; 6962 6963 default: 6964 return BCM_E_PARAM; 6965 } 6966 6967 /* Pack control message data into DMA buffer */ 6968 buffer = oc->bhh_dma_buffer; 6969 buffer_ptr = bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess); 6970 buffer_len = buffer_ptr - buffer; 6971 6972 /* Send BHH Session Update message to uC */ 6973 rv = _bcm_fp_oam_msg_send_receive(unit, 6974 MOS_MSG_CLASS_BHH, 6975 MOS_MSG_SUBCLASS_BHH_SESS_SET, 6976 buffer_len, 0, 6977 MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY, 6978 &reply_len); 6979 if (BCM_FAILURE(rv) || (reply_len != 0)) { 6980 LOG_ERROR(BSL_LS_BCM_OAM, 6981 (BSL_META_U(unit, 6982 "BHH(unit %d) Error: Session SET failed " 6983 "(EP=%d) - %s.\n"), 6984 unit, endpoint_info->id, bcm_errmsg(rv))); 6985 /* Return ID back to free MEP ID pool.*/ 6986 rv = shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx); 6987 _BCM_OAM_UNLOCK(oc); 6988 return (rv); 6989 } 6990 6991 /* hash collision */ 6992 rv = shr_htb_insert(oc->bhh_mep_htbl, hash_key, hash_data); 6993 if (BCM_FAILURE(rv)) { 6994 LOG_ERROR(BSL_LS_BCM_OAM, 6995 (BSL_META_U(unit, 6996 "OAM(unit %d) Error: Hash table insert " 6997 "failed EP=%d %s.\n"), 6998 unit, endpoint_info->id, bcm_errmsg(rv))); 6999 /* Return ID back to free MEP ID pool.*/ 7000 rv = shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx); 7001 _BCM_OAM_UNLOCK(oc); 7002 return (rv); 7003 } 7004 7005 hash_data->in_use = 1; 7006 } else { 7007 bhh_sdk_msg_session_update_t msg_sess; 7008 uint8 encap_type;/* dummy*/ 7009 7010 sal_memset(&msg_sess, 0, sizeof(msg_sess)); 7011 msg_sess.sess_id = bhh_pool_ep_idx; 7012 msg_sess.rdi = (group_p->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX); 7013 msg_sess.msg_type = BHH_CCM_MSG; 7014 7015 rv = _bcm_fp_oam_bhh_encap_create(unit, 7016 module_id, 7017 port_id, 7018 hash_data, 7019 msg_sess.encap_data, 7020 &encap_type, 7021 &msg_sess.encap_length, 7022 &counter_info, hash_data->int_pri, 7023 hash_data->egr_label_exp, 7024 hash_data->egr_label_ttl); 7025 7026 if(BCM_FAILURE(rv)) 7027 { 7028 LOG_ERROR(BSL_LS_BCM_OAM, 7029 (BSL_META_U(unit, 7030 "BHH(unit %d) Error: Encap create failed " 7031 "(EP=%d) - %s.\n"), 7032 unit, endpoint_info->id, bcm_errmsg(rv))); 7033 _BCM_OAM_UNLOCK(oc); 7034 return (rv); 7035 } 7036 /* Pack control message data into DMA buffer */ 7037 buffer = oc->bhh_dma_buffer; 7038 buffer_ptr = bhh_sdk_msg_ctrl_session_update_pack(buffer, &msg_sess); 7039 buffer_len = buffer_ptr - buffer; 7040 7041 7042 /* Send BHH Session Update message to uC */ 7043 rv = _bcm_fp_oam_msg_send_receive(unit, 7044 MOS_MSG_CLASS_BHH, 7045 MOS_MSG_SUBCLASS_BHH_SESS_UPDATE, 7046 buffer_len, 0, 7047 MOS_MSG_SUBCLASS_BHH_SESS_UPDATE_REPLY, 7048 &reply_len); 7049 if (BCM_FAILURE(rv) || (reply_len != 0)) { 7050 LOG_ERROR(BSL_LS_BCM_OAM, 7051 (BSL_META_U(unit, 7052 "BHH(unit %d) Error: Session Update failed " 7053 "(EP=%d) - %s.\n"), 7054 unit, endpoint_info->id, bcm_errmsg(rv))); 7055 _BCM_OAM_UNLOCK(oc); 7056 return (rv); 7057 } 7058 } 7059 } 7060 _BCM_OAM_UNLOCK(oc); 7061 return (rv); 7062 } 7063 7064 /* 7065 * Function: 7066 * _bcm_fp_oam_bhh_endpoint_get 7067 * Purpose: 7068 * Get an OAM endpoint object 7069 * Parameters: 7070 * unit - (IN) BCM device number 7071 * endpoint_info - (OUT) Pointer to OAM endpoint information buffer. 7072 * Returns: 7073 * BCM_E_XXX 7074 */ 7075 int 7076 _bcm_fp_oam_bhh_endpoint_get(int unit, bcm_oam_endpoint_info_t *endpoint_info) 7077 { 7078 _bhh_fp_oam_ep_data_t *h_data_p; /* Pointer to endpoint hash data. */ 7079 int rv = BCM_E_NONE;/* Operation return status. */ 7080 _bcm_fp_oam_control_t *oc; /* Pointer to OAM control structure. */ 7081 bhh_sdk_msg_ctrl_sess_get_t msg; 7082 uint8 *buffer, *buffer_ptr; 7083 uint16 buffer_len, reply_len; 7084 int sess_id = 0, i = 0; 7085 bcm_l3_egress_t l3_egress; 7086 bcm_l3_intf_t l3_intf; 7087 7088 7089 if (NULL == endpoint_info) { 7090 return (BCM_E_PARAM); 7091 } 7092 7093 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 7094 7095 7096 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_info->id); 7097 h_data_p = &oc->bhh_ep_data[sess_id]; 7098 7099 if (0 == h_data_p->in_use) { 7100 LOG_ERROR(BSL_LS_BCM_OAM, 7101 (BSL_META_U(unit, 7102 "OAM(unit %d) Error: h_data_p not in use EP=%d\n"), 7103 unit, endpoint_info->id)); 7104 return (BCM_E_NOT_FOUND); 7105 } 7106 7107 rv = _bcm_fp_oam_msg_send_receive(unit, 7108 MOS_MSG_CLASS_BHH, 7109 MOS_MSG_SUBCLASS_BHH_SESS_GET, 7110 sess_id, 0, 7111 MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY, 7112 &reply_len); 7113 if (BCM_FAILURE(rv)) { 7114 LOG_ERROR(BSL_LS_BCM_OAM, 7115 (BSL_META_U(unit, 7116 "OAM(unit %d) Error: ukernel msg failed for" 7117 " EP=%d %s.\n"), unit, endpoint_info->id, 7118 bcm_errmsg(rv))); 7119 return (rv); 7120 } 7121 7122 /* Pack control message data into DMA buffer */ 7123 buffer = oc->bhh_dma_buffer; 7124 buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg); 7125 buffer_len = buffer_ptr - buffer; 7126 7127 if (reply_len != buffer_len) { 7128 rv = BCM_E_INTERNAL; 7129 LOG_ERROR(BSL_LS_BCM_OAM, 7130 (BSL_META_U(unit, 7131 "OAM(unit %d) Error: ukernel msg failed for" 7132 " EP=%d %s.\n"), unit, endpoint_info->id, 7133 bcm_errmsg(rv))); 7134 return (rv); 7135 } else { 7136 endpoint_info->int_pri = msg.tx_cos; 7137 endpoint_info->pkt_pri = msg.tx_pri; 7138 endpoint_info->mpls_exp = msg.priority; 7139 7140 if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE){ 7141 endpoint_info->name = msg.remote_mep_id; 7142 endpoint_info->ccm_period = msg.remote_period; 7143 } else { 7144 endpoint_info->name = msg.mep_id; 7145 endpoint_info->ccm_period = msg.local_period; 7146 } 7147 7148 if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){ 7149 endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT; 7150 } 7151 if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){ 7152 endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI; 7153 } 7154 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){ 7155 endpoint_info->faults |= 7156 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL; 7157 } 7158 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){ 7159 endpoint_info->faults |= 7160 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID; 7161 } 7162 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){ 7163 endpoint_info->faults |= 7164 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID; 7165 } 7166 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){ 7167 endpoint_info->faults |= 7168 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD; 7169 } 7170 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){ 7171 endpoint_info->faults |= 7172 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY; 7173 } 7174 if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) { 7175 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS; 7176 } 7177 if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) { 7178 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI; 7179 } 7180 if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) { 7181 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI; 7182 } 7183 } 7184 7185 endpoint_info->intf_id = h_data_p->egress_if; 7186 endpoint_info->mpls_label = h_data_p->label; 7187 endpoint_info->gport = h_data_p->gport; 7188 endpoint_info->vpn = h_data_p->vpn; 7189 endpoint_info->trunk_index = h_data_p->trunk_index; 7190 if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE){ 7191 endpoint_info->name = msg.remote_mep_id; 7192 endpoint_info->local_id = endpoint_info->id; 7193 } 7194 if(!BHH_EP_MPLS_SECTION_TYPE(h_data_p)){ 7195 /* 7196 * Get MAC address 7197 */ 7198 bcm_l3_egress_t_init(&l3_egress); 7199 bcm_l3_intf_t_init(&l3_intf); 7200 7201 if (BCM_FAILURE 7202 (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) { 7203 return (BCM_E_INTERNAL); 7204 } 7205 7206 l3_intf.l3a_intf_id = l3_egress.intf; 7207 if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) { 7208 return (BCM_E_INTERNAL); 7209 } 7210 7211 sal_memcpy(endpoint_info->src_mac_address, l3_intf.l3a_mac_addr, 7212 _BHH_MAC_ADDR_LENGTH); 7213 }else { 7214 sal_memcpy(endpoint_info->src_mac_address, h_data_p->src_mac_address, 7215 _BHH_MAC_ADDR_LENGTH); 7216 } 7217 7218 7219 7220 endpoint_info->group = h_data_p->group_index; 7221 7222 endpoint_info->vlan = h_data_p->vlan; 7223 endpoint_info->inner_vlan = h_data_p->inner_vlan; 7224 endpoint_info->level = h_data_p->level; 7225 endpoint_info->gport = h_data_p->gport; 7226 endpoint_info->flags |= h_data_p->flags; 7227 endpoint_info->flags &= ~(BCM_OAM_ENDPOINT_WITH_ID); 7228 endpoint_info->flags2 = h_data_p->flags2; 7229 endpoint_info->type = h_data_p->type; 7230 endpoint_info->vccv_type = h_data_p->vccv_type; 7231 endpoint_info->outer_tpid = h_data_p->outer_tpid; 7232 endpoint_info->inner_tpid = h_data_p->inner_tpid; 7233 endpoint_info->egress_label.label = h_data_p->egr_label; 7234 endpoint_info->egress_label.exp = h_data_p->egr_label_exp; 7235 endpoint_info->egress_label.ttl = h_data_p->egr_label_ttl; 7236 for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) 7237 { 7238 endpoint_info->ccm_tx_update_lm_counter_base_id[i] = 7239 h_data_p->ccm_tx_update_lm_counter_base_id[i]; 7240 endpoint_info->ccm_tx_update_lm_counter_offset[i] = 7241 h_data_p->ccm_tx_update_lm_counter_offset[i]; 7242 endpoint_info->ccm_tx_update_lm_counter_action[i] = 7243 bcmOamCounterActionIncrement; 7244 } 7245 7246 endpoint_info->session_id = h_data_p->hw_session_id; 7247 7248 endpoint_info->session_num_entries = h_data_p->hw_session_num_entries; 7249 7250 endpoint_info->ccm_tx_update_lm_counter_size = 7251 h_data_p->ccm_tx_counter_size; 7252 return (BCM_E_NONE); 7253 } 7254 7255 7256 /* 7257 * Function: 7258 * _bcm_fp_oam_bhh_endpoint_destroy 7259 * Purpose: 7260 * Delete an endpoint and free all its allocated resources. 7261 * Parameters: 7262 * unit - (IN) BCM device number 7263 * ep_id - (IN) Endpoint ID value. 7264 * Retruns: 7265 * BCM_E_XXX 7266 */ 7267 STATIC int 7268 _bcm_fp_oam_bhh_endpoint_destroy(int unit, 7269 bcm_oam_endpoint_t ep_id) 7270 { 7271 _bcm_fp_oam_control_t *oc; /* Pointer to OAM control structure. */ 7272 _bhh_fp_oam_ep_data_t *h_data_p; /* Pointer to endpoint data. */ 7273 _bhh_fp_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 7274 bcm_oam_endpoint_info_t ep_info; /* Endpoint information. */ 7275 _bhh_fp_oam_ep_data_t h_data; /* Pointer to endpoint data. */ 7276 _bhh_fp_oam_group_data_t *group_p; /* Pointer to group data. */ 7277 uint16 reply_len; 7278 bcm_oam_endpoint_t bhh_pool_ep_id; 7279 int rv = BCM_E_NONE;/* Operation return status. */ 7280 int bhh_group_idx = 0; 7281 7282 /* Lock already taken by the calling routine. */ 7283 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 7284 7285 bhh_pool_ep_id = BCM_OAM_BHH_GET_UKERNEL_EP(ep_id); 7286 /* Get the hash data pointer. */ 7287 h_data_p = &oc->bhh_ep_data[bhh_pool_ep_id]; 7288 if(0 == h_data_p->in_use){ 7289 return BCM_E_NOT_FOUND; 7290 } 7291 bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(h_data_p->group_index); 7292 group_p = &(oc->bhh_group_data[bhh_group_idx]); 7293 if (h_data_p->is_remote) { 7294 /* 7295 * BHH uses same index for local and remote. 7296 * So, delete always goes through 7297 * local endpoint destory 7298 */ 7299 return (BCM_E_NONE); 7300 } else { 7301 7302 if (!SOC_WARM_BOOT(unit)) { 7303 /*Send BHH Session Delete message to uC.Error response is not an 7304 during switch re-init as uKernel is reloaded and its state is 7305 cleared before oam init. As such endpoint wont exist during 7306 oam init*/ 7307 rv = _bcm_fp_oam_msg_send_receive(unit, 7308 MOS_MSG_CLASS_BHH, 7309 MOS_MSG_SUBCLASS_BHH_SESS_DELETE, 7310 (int)bhh_pool_ep_id, 0, 7311 MOS_MSG_SUBCLASS_BHH_SESS_DELETE_REPLY, 7312 &reply_len); 7313 if (BCM_FAILURE(rv)) { 7314 LOG_ERROR(BSL_LS_BCM_OAM, 7315 (BSL_META_U(unit, 7316 "OAM(unit %d) Error: ukernel msg " 7317 "failed forEP=%d %s.\n"), unit, ep_id, 7318 bcm_errmsg(rv))); 7319 return (rv); 7320 } 7321 7322 } 7323 7324 h_data_p->in_use = 0; 7325 7326 /* Return ID back to free MEP ID pool.*/ 7327 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, 7328 bhh_pool_ep_id)); 7329 7330 /* Set up endpoint information for key construction. */ 7331 ep_info.group = h_data_p->group_index; 7332 ep_info.name = h_data_p->name; 7333 ep_info.gport = h_data_p->gport; 7334 ep_info.level = h_data_p->level; 7335 ep_info.vlan = h_data_p->vlan; 7336 ep_info.inner_vlan = h_data_p->inner_vlan; 7337 ep_info.flags = h_data_p->flags; 7338 ep_info.mpls_label = h_data_p->label; 7339 ep_info.type = h_data_p->type; 7340 7341 /* Construct hash key for lookup + delete operation. */ 7342 _bhh_fp_oam_ep_hash_key_construct(unit, oc, &ep_info, &hash_key); 7343 7344 /* Remove entry from hash table. */ 7345 BCM_IF_ERROR_RETURN(shr_htb_find(oc->bhh_mep_htbl, hash_key, 7346 (shr_htb_data_t *)&h_data, 7347 1)); 7348 7349 /* Clear the hash data memory previously occupied by this endpoint*/ 7350 _BHH_FP_OAM_HASH_DATA_CLEAR(h_data_p); 7351 7352 group_p->lmep_id = _BHH_FP_OAM_INVALID_LMEP_ID; 7353 7354 } 7355 7356 return (BCM_E_NONE); 7357 } 7358 7359 /* 7360 * Function: 7361 * _bcm_fp_oam_bhh_group_destroy 7362 * Purpose: 7363 * Delete a BHH group object. All OAM endpoints associated with the 7364 * group will also be destroyed. 7365 * Parameters: 7366 * unit - (IN) BCM device number 7367 * group_id - (IN/OUT) Pointer to an OAM group Id. 7368 * Returns: 7369 * BCM_E_XXX 7370 */ 7371 int 7372 _bcm_fp_oam_bhh_group_destroy(int unit, bcm_oam_group_t group_id) 7373 { 7374 _bcm_fp_oam_control_t *oc = NULL; /* OAM control structure */ 7375 _bhh_fp_oam_group_data_t *group_p; /* Handle to S/w Group Data */ 7376 int rv = 0; /* Return Value */ 7377 int bhh_group_idx = 0; 7378 7379 /* Get OAM control structure handle. */ 7380 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 7381 7382 bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(group_id); 7383 /* Get Handle to Local DB */ 7384 group_p = &(oc->bhh_group_data[bhh_group_idx]); 7385 if (!(group_p->in_use)) { 7386 return BCM_E_NOT_FOUND; 7387 } 7388 7389 if (group_p->lmep_id != _BHH_FP_OAM_INVALID_LMEP_ID) { 7390 rv = _bcm_fp_oam_bhh_endpoint_destroy(unit, group_p->lmep_id); 7391 if (BCM_FAILURE(rv)) { 7392 LOG_ERROR(BSL_LS_BCM_OAM, 7393 (BSL_META_U(unit, 7394 "OAM(unit %d) Error: EP destroy failed for " 7395 "(EP=%d) - %s.\n"), unit, 7396 group_p->lmep_id, bcm_errmsg(rv))); 7397 return (rv); 7398 } 7399 } 7400 sal_memset(group_p, 0, sizeof(_bhh_fp_oam_group_data_t)); 7401 group_p->lmep_id = _BHH_FP_OAM_INVALID_LMEP_ID; 7402 /* Return Group ID back to free group pool. */ 7403 rv = shr_idxres_list_free(oc->bhh_group_pool, bhh_group_idx); 7404 if (BCM_FAILURE(rv)) { 7405 LOG_ERROR(BSL_LS_BCM_OAM, 7406 (BSL_META_U(unit, 7407 "OAM(unit %d) Error: Free of group " 7408 "index failed for group=%d %s.\n"), unit, 7409 group_id, 7410 bcm_errmsg(rv))); 7411 7412 return (rv); 7413 } 7414 return rv; 7415 } 7416 7417 /* 7418 * Function: 7419 * _bcm_fp_oam_bhh_endpoint_destroy_all 7420 * Purpose: 7421 * Delete all endpointans associated with group and free all its allocated 7422 * resources. 7423 * Parameters: 7424 * unit - (IN) BCM device number 7425 * ep_id - (IN) Endpoint ID value. 7426 * Retruns: 7427 * BCM_E_XXX 7428 */ 7429 7430 int 7431 _bcm_fp_oam_bhh_endpoint_destroy_all(int unit, bcm_oam_group_t group_id) 7432 { 7433 _bcm_fp_oam_control_t *oc = NULL; /* OAM control structure */ 7434 _bhh_fp_oam_group_data_t *group_p; /* Handle to S/w Group Data */ 7435 int rv = 0; /* Return Value */ 7436 int bhh_group_idx = 0; 7437 7438 /* Get OAM control structure handle. */ 7439 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 7440 7441 bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(group_id); 7442 /* Get Handle to Local DB */ 7443 group_p = &(oc->bhh_group_data[bhh_group_idx]); 7444 if (!(group_p->in_use)) { 7445 return BCM_E_NOT_FOUND; 7446 } 7447 7448 if (group_p->lmep_id != _BHH_FP_OAM_INVALID_LMEP_ID) { 7449 rv = _bcm_fp_oam_bhh_endpoint_destroy(unit, group_p->lmep_id); 7450 if (BCM_FAILURE(rv)) { 7451 LOG_ERROR(BSL_LS_BCM_OAM, 7452 (BSL_META_U(unit, 7453 "OAM(unit %d) Error: EP destroy failed for " 7454 "(EP=%d) - %s.\n"), unit, 7455 group_p->lmep_id, bcm_errmsg(rv))); 7456 return rv; 7457 } 7458 } 7459 group_p->lmep_id = _BHH_FP_OAM_INVALID_LMEP_ID; 7460 7461 return rv; 7462 } 7463 7464 /* 7465 * Function: 7466 * _bcm_fp_oam_bhh_endpoint_traverse 7467 * Purpose: 7468 * Traverse the entire set of BHH endpoints associated with group, 7469 * calling a specified callback for each one 7470 * Parameters: 7471 * unit - (IN) BCM device number 7472 * group - (IN) Group ID of endpoints associated. 7473 * cb - (IN) Pointer to call back function. 7474 * user_data - (IN) Pointer to user supplied data. 7475 * Returns: 7476 * BCM_E_XXX 7477 */ 7478 int 7479 _bcm_fp_oam_bhh_endpoint_traverse(int unit, bcm_oam_group_t group, 7480 bcm_oam_endpoint_traverse_cb cb, 7481 void *user_data) 7482 { 7483 _bcm_fp_oam_control_t *oc; /* OAM control structure pointer. */ 7484 bcm_oam_endpoint_info_t endpoint_info; /* Group information to be set. */ 7485 _bhh_fp_oam_group_data_t *group_p; /* Handle to S/w Group Data */ 7486 int rv = 0; /* Return Value */ 7487 int bhh_group_idx = 0; 7488 7489 if (NULL == cb) { 7490 return (BCM_E_PARAM); 7491 } 7492 7493 /* Get device OAM control structure handle. */ 7494 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 7495 7496 bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(group); 7497 /* Get Handle to Local DB */ 7498 group_p = &(oc->bhh_group_data[bhh_group_idx]); 7499 if (!(group_p->in_use)) { 7500 return BCM_E_NOT_FOUND; 7501 } 7502 if (group_p->lmep_id != _BHH_FP_OAM_INVALID_LMEP_ID) { 7503 sal_memset(&endpoint_info, 0, sizeof(endpoint_info)); 7504 endpoint_info.id = group_p->lmep_id; 7505 rv = _bcm_fp_oam_bhh_endpoint_get(unit, &endpoint_info); 7506 7507 /* Call the user call back routine with group information. */ 7508 rv = cb(unit, &endpoint_info, user_data); 7509 if (BCM_FAILURE(rv)) { 7510 LOG_ERROR(BSL_LS_BCM_OAM, 7511 (BSL_META_U(unit, 7512 "OAM(unit %d) Error: User call back " 7513 "routine (EP=%d) - %s.\n"), unit, 7514 endpoint_info.id, bcm_errmsg(rv))); 7515 return (rv); 7516 } 7517 } 7518 7519 return BCM_E_NONE; 7520 } 7521 7522 /* BHH Event Handler */ 7523 typedef struct _event_handler_s { 7524 struct _event_handler_s *next; 7525 bcm_oam_event_types_t event_types; 7526 bcm_oam_event_cb cb; 7527 void *user_data; 7528 } _event_handler_t; 7529 7530 /* 7531 * Function: 7532 * _bcm_fp_oam_bhh_event_mask_set 7533 * Purpose: 7534 * Set the BHH Events mask. 7535 * Events are set per BHH module. 7536 * Parameters: 7537 * unit - (IN) Unit number. 7538 * Returns: 7539 * BCM_E_NONE Operation completed successfully 7540 * BCM_E_XXX Operation failed 7541 * Notes: 7542 */ 7543 STATIC int 7544 _bcm_fp_oam_bhh_event_mask_set(int unit) 7545 { 7546 _bcm_fp_oam_control_t *oc; 7547 _bcm_oam_event_handler_t *event_handler_p; 7548 uint32 event_mask = 0; 7549 uint16 reply_len; 7550 int rv = BCM_E_NONE; 7551 7552 /* Lock already taken by the calling routine. */ 7553 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 7554 7555 /* Get event mask from all callbacks */ 7556 for (event_handler_p = oc->event_handler_list_p; 7557 event_handler_p != NULL; 7558 event_handler_p = event_handler_p->next_p) { 7559 7560 if (SHR_BITGET(event_handler_p->event_types.w, 7561 bcmOAMEventBHHLBTimeout)) { 7562 event_mask |= BHH_BTE_EVENT_LB_TIMEOUT; 7563 } 7564 if (SHR_BITGET(event_handler_p->event_types.w, 7565 bcmOAMEventBHHLBDiscoveryUpdate)) { 7566 event_mask |= BHH_BTE_EVENT_LB_DISCOVERY_UPDATE; 7567 } 7568 if (SHR_BITGET(event_handler_p->event_types.w, 7569 bcmOAMEventBHHCCMTimeout)) { 7570 event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT; 7571 } 7572 if (SHR_BITGET(event_handler_p->event_types.w, 7573 bcmOAMEventBHHCCMTimeoutClear)) { 7574 event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR; 7575 } 7576 if (SHR_BITGET(event_handler_p->event_types.w, 7577 bcmOAMEventBHHCCMState)) { 7578 event_mask |= BHH_BTE_EVENT_STATE; 7579 } 7580 if (SHR_BITGET(event_handler_p->event_types.w, 7581 bcmOAMEventBHHCCMRdi)) { 7582 event_mask |= BHH_BTE_EVENT_CCM_RDI; 7583 } 7584 if (SHR_BITGET(event_handler_p->event_types.w, 7585 bcmOAMEventBHHCCMUnknownMegLevel)) { 7586 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL; 7587 } 7588 if (SHR_BITGET(event_handler_p->event_types.w, 7589 bcmOAMEventBHHCCMUnknownMegId)) { 7590 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID; 7591 } 7592 if (SHR_BITGET(event_handler_p->event_types.w, 7593 bcmOAMEventBHHCCMUnknownMepId)) { 7594 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID; 7595 } 7596 if (SHR_BITGET(event_handler_p->event_types.w, 7597 bcmOAMEventBHHCCMUnknownPeriod)) { 7598 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD; 7599 } 7600 if (SHR_BITGET(event_handler_p->event_types.w, 7601 bcmOAMEventBHHCCMUnknownPriority)) { 7602 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY; 7603 } 7604 if (SHR_BITGET(event_handler_p->event_types.w, 7605 bcmOAMEventBHHCCMRdiClear)) { 7606 event_mask |= BHH_BTE_EVENT_CCM_RDI_CLEAR; 7607 } 7608 if (SHR_BITGET(event_handler_p->event_types.w, 7609 bcmOAMEventBHHCCMUnknownMegLevelClear)) { 7610 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR; 7611 } 7612 if (SHR_BITGET(event_handler_p->event_types.w, 7613 bcmOAMEventBHHCCMUnknownMegIdClear)) { 7614 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR; 7615 } 7616 if (SHR_BITGET(event_handler_p->event_types.w, 7617 bcmOAMEventBHHCCMUnknownMepIdClear)) { 7618 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR; 7619 } 7620 if (SHR_BITGET(event_handler_p->event_types.w, 7621 bcmOAMEventBHHCCMUnknownPeriodClear)) { 7622 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR; 7623 } 7624 if (SHR_BITGET(event_handler_p->event_types.w, 7625 bcmOAMEventBHHCCMUnknownPriorityClear)) { 7626 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR; 7627 } 7628 if (SHR_BITGET(event_handler_p->event_types.w, 7629 bcmOAMEventBhhPmCounterRollover)) { 7630 event_mask |= BHH_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER; 7631 } 7632 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfLos)) { 7633 event_mask |= BHH_BTE_EVENT_CSF_LOS; 7634 } 7635 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfFdi)) { 7636 event_mask |= BHH_BTE_EVENT_CSF_FDI; 7637 } 7638 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfRdi)) { 7639 event_mask |= BHH_BTE_EVENT_CSF_RDI; 7640 } 7641 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfDci)) { 7642 event_mask |= BHH_BTE_EVENT_CSF_DCI; 7643 } 7644 } 7645 7646 /* Update BHH event mask in uKernel */ 7647 if (event_mask != oc->bhh_event_mask) { 7648 /* Send BHH Event Mask message to uC */ 7649 rv = _bcm_fp_oam_msg_send_receive 7650 (unit, 7651 MOS_MSG_CLASS_BHH, 7652 MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET, 7653 0, event_mask, 7654 MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET_REPLY, 7655 &reply_len); 7656 7657 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 7658 rv = BCM_E_INTERNAL; 7659 } 7660 } 7661 7662 oc->bhh_event_mask = event_mask; 7663 7664 return (rv); 7665 } 7666 7667 /* 7668 * Function: 7669 * bcm_fp_oam_loopback_add 7670 * Purpose: 7671 * 7672 * Parameters: 7673 * unit - Device unit number 7674 * Returns: 7675 * None 7676 */ 7677 int 7678 bcm_fp_oam_loopback_add(int unit, bcm_oam_loopback_t *loopback_p) 7679 { 7680 _bcm_fp_oam_control_t *oc; 7681 _bhh_fp_oam_ep_data_t *h_data_p; 7682 int rv = BCM_E_NONE; 7683 bhh_sdk_msg_ctrl_loopback_add_t msg; 7684 uint8 *buffer, *buffer_ptr, encap_type; 7685 uint16 buffer_len, reply_len; 7686 uint32 flags = 0; 7687 int sess_id = 0, i = 0; 7688 _bhh_oam_lm_dm_info_t counter_info; 7689 bcm_module_t module_id; 7690 bcm_port_t port_id; 7691 bcm_trunk_t trunk_id; 7692 int local_id; 7693 7694 /* Get OAM Control Structure. */ 7695 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 7696 7697 _BCM_OAM_LOCK(oc); 7698 7699 BCM_OAM_BHH_VALIDATE_EP(loopback_p->id); 7700 7701 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id); 7702 7703 /* Check endpoint status. */ 7704 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 7705 if ((BCM_E_EXISTS != rv)) { 7706 /* Endpoint not in use. */ 7707 LOG_ERROR(BSL_LS_BCM_OAM, 7708 (BSL_META_U(unit, 7709 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 7710 unit, loopback_p->id, bcm_errmsg(rv))); 7711 _BCM_OAM_UNLOCK(oc); 7712 return (rv); 7713 } 7714 7715 /*Validate LB period */ 7716 rv = _bcm_fp_oam_period_validate(loopback_p->period); 7717 if (BCM_FAILURE(rv)) { 7718 LOG_ERROR(BSL_LS_BCM_OAM, 7719 (BSL_META_U(unit, 7720 "OAM(unit %d) Error: Invalid period : %d\n"), 7721 unit, loopback_p->period)); 7722 _BCM_OAM_UNLOCK(oc); 7723 return (rv); 7724 } 7725 7726 h_data_p = &oc->bhh_ep_data[sess_id]; 7727 7728 h_data_p->lb_tx_counter_size = loopback_p->lb_tx_update_lm_counter_size; 7729 sal_memset(&counter_info, 0, sizeof(counter_info)); 7730 counter_info.counter_size = loopback_p->lb_tx_update_lm_counter_size; 7731 for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) 7732 { 7733 h_data_p->lb_tx_update_lm_counter_base_id[i] = 7734 loopback_p->lb_tx_update_lm_counter_base_id[i]; 7735 h_data_p->lb_tx_update_lm_counter_offset[i] = 7736 loopback_p->lb_tx_update_lm_counter_offset[i]; 7737 counter_info.counter_base_id[i] = 7738 loopback_p->lb_tx_update_lm_counter_base_id[i]; 7739 counter_info.counter_offset[i] = 7740 loopback_p->lb_tx_update_lm_counter_offset[i]; 7741 counter_info.counter_action[i] = bcmOamCounterActionIncrement; 7742 counter_info.byte_count_offset[i] = 0; 7743 } 7744 counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE; 7745 7746 /* 7747 * Convert host space flags to uKernel space flags 7748 */ 7749 7750 if (loopback_p->flags & BCM_OAM_LOOPBACK_TX_ENABLE) { 7751 flags |= BCM_BHH_TX_ENABLE; 7752 } 7753 7754 if (loopback_p->flags & BCM_OAM_BHH_INC_REQUESTING_MEP_TLV) { 7755 flags |= BCM_BHH_INC_REQUESTING_MEP_TLV; 7756 } 7757 7758 if (loopback_p->flags & BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) { 7759 flags |= BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV; 7760 } else if (loopback_p->flags & 7761 BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) { 7762 flags |= BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV; 7763 } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MEP_TLV) { 7764 flags |= BCM_BHH_LBM_ICC_MEP_TLV; 7765 } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MIP_TLV) { 7766 flags |= BCM_BHH_LBM_ICC_MIP_TLV; 7767 } else { 7768 flags |= BCM_BHH_LBM_ICC_MEP_TLV; /* Default */ 7769 } 7770 7771 if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MEP_TLV) { 7772 flags |= BCM_BHH_LBR_ICC_MEP_TLV; 7773 } else if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MIP_TLV) { 7774 flags |= BCM_BHH_LBR_ICC_MIP_TLV; 7775 } 7776 7777 sal_memset(&msg, 0, sizeof(msg)); 7778 msg.flags = flags; 7779 msg.sess_id = sess_id; 7780 msg.int_pri = loopback_p->int_pri; 7781 msg.pkt_pri = loopback_p->pkt_pri; 7782 7783 /* 7784 * Set period 7785 */ 7786 msg.period = loopback_p->period; 7787 7788 /* 7789 * Check TTL 7790 */ 7791 if (loopback_p->ttl == 0 || loopback_p->ttl > 255) { 7792 _BCM_OAM_UNLOCK(oc); 7793 return BCM_E_PARAM; 7794 } 7795 /* Check for default usage of int_pri */ 7796 if (loopback_p->int_pri == -1) { 7797 loopback_p->int_pri = 7; /*Use default */ 7798 } 7799 /* Check for default usage of pkt_pri */ 7800 if (loopback_p->pkt_pri == 0xff) { 7801 loopback_p->pkt_pri = 7; /*Use default */ 7802 } 7803 if (BHH_EP_MPLS_SECTION_TYPE(h_data_p) || 7804 (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv && 7805 h_data_p->vccv_type == bcmOamBhhVccvTtl)) { 7806 7807 msg.ttl = 1; /* Only TTL 1 is valid */ 7808 } else { 7809 msg.ttl = loopback_p->ttl; 7810 } 7811 if (h_data_p->trunk_id == BCM_TRUNK_INVALID) { 7812 rv = _bcm_esw_gport_resolve(unit, 7813 h_data_p->gport, &module_id, &port_id, &trunk_id, &local_id); 7814 } else { 7815 rv = _bcm_esw_gport_resolve(unit, 7816 h_data_p->resolved_trunk_gport, &module_id, &port_id, 7817 &trunk_id, &local_id); 7818 7819 } 7820 7821 if (BCM_FAILURE(rv)) { 7822 LOG_ERROR(BSL_LS_BCM_OAM, 7823 (BSL_META_U(unit, 7824 "BHH(unit %d) Error: Gport resolve - %s.\n"), 7825 unit, bcm_errmsg(rv))); 7826 _BCM_OAM_UNLOCK(oc); 7827 return (rv); 7828 } 7829 7830 7831 /* 7832 * Set the BHH encapsulation data 7833 * 7834 * The function _bcm_fp_oam_bhh_encap_create() is called first 7835 * since this sets some fields in 'hash_data' which are 7836 * used in the message. 7837 */ 7838 rv = _bcm_fp_oam_bhh_encap_create(unit, 7839 module_id, 7840 port_id, 7841 h_data_p, 7842 msg.encap_data, 7843 &encap_type, 7844 &msg.encap_length, 7845 &counter_info, loopback_p->int_pri, loopback_p->pkt_pri, 7846 loopback_p->ttl); 7847 if(BCM_FAILURE(rv)) 7848 { 7849 LOG_ERROR(BSL_LS_BCM_OAM, 7850 (BSL_META_U(unit, 7851 "BHH(unit %d) Error: Encap create failed " 7852 " - %s.\n"), 7853 unit, bcm_errmsg(rv))); 7854 _BCM_OAM_UNLOCK(oc); 7855 return (rv); 7856 } 7857 /* Pack control message data into DMA buffer */ 7858 buffer = oc->bhh_dma_buffer; 7859 buffer_ptr = bhh_sdk_msg_ctrl_loopback_add_pack(buffer, &msg); 7860 buffer_len = buffer_ptr - buffer; 7861 7862 /* Send BHH Session Update message to uC */ 7863 rv = _bcm_fp_oam_msg_send_receive(unit, 7864 MOS_MSG_CLASS_BHH, 7865 MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD, 7866 buffer_len, 0, 7867 MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD_REPLY, 7868 &reply_len); 7869 7870 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 7871 rv = BCM_E_INTERNAL; 7872 } 7873 7874 7875 _BCM_OAM_UNLOCK(oc); 7876 return (rv); 7877 } 7878 7879 /* 7880 * Function: 7881 * bcm_fp_oam_loopback_get 7882 * Purpose: 7883 * 7884 * Parameters: 7885 * unit - Device unit number 7886 * Returns: 7887 * None 7888 */ 7889 int 7890 bcm_fp_oam_loopback_get(int unit, bcm_oam_loopback_t *loopback_p) 7891 { 7892 _bcm_fp_oam_control_t *oc; 7893 int rv = BCM_E_NONE; 7894 bhh_sdk_msg_ctrl_loopback_get_t msg; 7895 _bhh_fp_oam_ep_data_t *h_data_p; 7896 uint8 *buffer, *buffer_ptr; 7897 uint16 buffer_len, reply_len; 7898 int sess_id = 0, i = 0; 7899 uint8* encap_data = NULL; 7900 soc_olp_l2_hdr_t olp_l2_header; 7901 soc_olp_tx_hdr_t olp_oam_tx_header; 7902 7903 /* Get OAM Control Structure. */ 7904 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 7905 7906 _BCM_OAM_LOCK(oc); 7907 7908 BCM_OAM_BHH_VALIDATE_EP(loopback_p->id); 7909 7910 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id); 7911 7912 /* Check endpoint status. */ 7913 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 7914 if ((BCM_E_EXISTS != rv)) { 7915 /* Endpoint not in use. */ 7916 LOG_ERROR(BSL_LS_BCM_OAM, 7917 (BSL_META_U(unit, 7918 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 7919 unit, loopback_p->id, bcm_errmsg(rv))); 7920 _BCM_OAM_UNLOCK(oc); 7921 return (rv); 7922 } 7923 7924 h_data_p = &oc->bhh_ep_data[sess_id]; 7925 7926 7927 sal_memset(&msg, 0, sizeof(msg)); 7928 /* Send BHH Session Update message to uC */ 7929 rv = _bcm_fp_oam_msg_send_receive(unit, 7930 MOS_MSG_CLASS_BHH, 7931 MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET, 7932 sess_id, 0, 7933 MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET_REPLY, 7934 &reply_len); 7935 if(BCM_FAILURE(rv)) { 7936 LOG_ERROR(BSL_LS_BCM_OAM, 7937 (BSL_META_U(unit, 7938 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 7939 unit, loopback_p->id, bcm_errmsg(rv))); 7940 _BCM_OAM_UNLOCK(oc); 7941 return (rv); 7942 } 7943 7944 /* Pack control message data into DMA buffer */ 7945 buffer = oc->bhh_dma_buffer; 7946 buffer_ptr = bhh_sdk_msg_ctrl_loopback_get_unpack(buffer, &msg); 7947 buffer_len = buffer_ptr - buffer; 7948 7949 7950 if (reply_len != buffer_len) { 7951 rv = BCM_E_INTERNAL; 7952 } else { 7953 /* 7954 * Convert kernel space flags to host space flags 7955 */ 7956 if (msg.flags & BCM_BHH_INC_REQUESTING_MEP_TLV) { 7957 loopback_p->flags |= BCM_OAM_BHH_INC_REQUESTING_MEP_TLV; 7958 } 7959 7960 if (msg.flags & BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) { 7961 loopback_p->flags |= BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV; 7962 } else if (msg.flags & BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) { 7963 loopback_p->flags |= BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV; 7964 } else if (msg.flags & BCM_BHH_LBM_ICC_MEP_TLV) { 7965 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MEP_TLV; 7966 } else if (msg.flags & BCM_BHH_LBM_ICC_MIP_TLV) { 7967 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MIP_TLV; 7968 } 7969 7970 if (msg.flags & BCM_BHH_LBR_ICC_MEP_TLV) { 7971 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MEP_TLV; 7972 } else if (msg.flags & BCM_BHH_LBR_ICC_MIP_TLV) { 7973 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MIP_TLV; 7974 } 7975 7976 if (msg.flags & BCM_BHH_TX_ENABLE) { 7977 loopback_p->flags |= BCM_OAM_LOOPBACK_TX_ENABLE; 7978 } 7979 7980 loopback_p->period = msg.period; 7981 loopback_p->ttl = msg.ttl; 7982 loopback_p->discovered_me.flags = msg.discovery_flags; 7983 loopback_p->discovered_me.name = msg.discovery_id; 7984 loopback_p->discovered_me.ttl = msg.discovery_ttl; 7985 loopback_p->rx_count = msg.rx_count; 7986 loopback_p->tx_count = msg.tx_count; 7987 loopback_p->drop_count = msg.drop_count; 7988 loopback_p->unexpected_response = msg.unexpected_response; 7989 loopback_p->out_of_sequence = msg.out_of_sequence; 7990 loopback_p->local_mipid_missmatch = msg.local_mipid_missmatch; 7991 loopback_p->remote_mipid_missmatch = msg.remote_mipid_missmatch; 7992 loopback_p->invalid_target_mep_tlv = msg.invalid_target_mep_tlv; 7993 loopback_p->invalid_mep_tlv_subtype = msg.invalid_mep_tlv_subtype; 7994 loopback_p->invalid_tlv_offset = msg.invalid_tlv_offset; 7995 for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) 7996 { 7997 loopback_p->lb_tx_update_lm_counter_base_id[i] = 7998 h_data_p->lb_tx_update_lm_counter_base_id[i]; 7999 loopback_p->lb_tx_update_lm_counter_offset[i] = 8000 h_data_p->lb_tx_update_lm_counter_offset[i]; 8001 } 8002 loopback_p->lb_tx_update_lm_counter_size = h_data_p->lb_tx_counter_size; 8003 8004 encap_data = msg.encap_data; 8005 encap_data = _bcm_fp_oam_olp_l2_header_unpack(encap_data, 8006 &olp_l2_header); 8007 encap_data = shr_olp_tx_header_unpack(encap_data, 8008 &olp_oam_tx_header); 8009 8010 loopback_p->int_pri = SOC_OLP_TX_PRI_GET(&olp_oam_tx_header); 8011 8012 loopback_p->pkt_pri = 8013 bcm_fp_oam_bhh_get_oam_exp_from_encap(h_data_p, 8014 msg.encap_data, 8015 msg.encap_length); 8016 rv = BCM_E_NONE; 8017 } 8018 8019 8020 _BCM_OAM_UNLOCK(oc); 8021 8022 return (rv); 8023 } 8024 8025 /* 8026 * Function: 8027 * bcm_fp_oam_loopback_delete 8028 * Purpose: 8029 * 8030 * Parameters: 8031 * unit - Device unit number 8032 * Returns: 8033 * None 8034 */ 8035 int 8036 bcm_fp_oam_loopback_delete(int unit, bcm_oam_loopback_t *loopback_p) 8037 { 8038 _bcm_fp_oam_control_t *oc; 8039 int rv = BCM_E_NONE; 8040 shr_bhh_msg_ctrl_loopback_delete_t msg; 8041 uint8 *buffer, *buffer_ptr; 8042 uint16 buffer_len, reply_len; 8043 int sess_id = 0; 8044 _bhh_fp_oam_ep_data_t *h_data_p; 8045 8046 /* Get OAM Control Structure. */ 8047 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 8048 8049 _BCM_OAM_LOCK(oc); 8050 8051 BCM_OAM_BHH_VALIDATE_EP(loopback_p->id); 8052 8053 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id); 8054 8055 /* Check endpoint status. */ 8056 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 8057 if ((BCM_E_EXISTS != rv)) { 8058 /* Endpoint not in use. */ 8059 LOG_ERROR(BSL_LS_BCM_OAM, 8060 (BSL_META_U(unit, 8061 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 8062 unit, loopback_p->id, bcm_errmsg(rv))); 8063 _BCM_OAM_UNLOCK(oc); 8064 return (rv); 8065 } 8066 8067 h_data_p = &oc->bhh_ep_data[sess_id]; 8068 8069 8070 msg.sess_id = h_data_p->uc_session_id; 8071 8072 /* Pack control message data into DMA buffer */ 8073 buffer = oc->bhh_dma_buffer; 8074 buffer_ptr = shr_bhh_msg_ctrl_loopback_delete_pack(buffer, &msg); 8075 buffer_len = buffer_ptr - buffer; 8076 8077 /* Send BHH Session Update message to uC */ 8078 rv = _bcm_fp_oam_msg_send_receive(unit, 8079 MOS_MSG_CLASS_BHH, 8080 MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE, 8081 buffer_len, 0, 8082 MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE_REPLY, 8083 &reply_len); 8084 8085 if(BCM_SUCCESS(rv) && (reply_len != 0)) 8086 rv = BCM_E_INTERNAL; 8087 8088 8089 _BCM_OAM_UNLOCK(oc); 8090 8091 return (rv); 8092 } 8093 8094 /* 8095 * Function: 8096 * _bcm_fp_oam_bhh_loss_add 8097 * Purpose: 8098 * Loss Measurement add for BHH endpoints. 8099 * Parameters: 8100 * unit - Device unit number 8101 * Returns: 8102 * None 8103 */ 8104 int 8105 _bcm_fp_oam_bhh_loss_add(int unit, bcm_oam_loss_t *loss_p) 8106 { 8107 _bcm_fp_oam_control_t *oc; 8108 _bhh_fp_oam_ep_data_t *h_data_p; 8109 int rv = BCM_E_NONE; 8110 uint8 *buffer, *buffer_ptr, encap_type; 8111 uint16 buffer_len, reply_len; 8112 uint32 flags = 0; 8113 int sess_id = 0, i = 0; 8114 _bhh_oam_lm_dm_info_t counter_info; 8115 bcm_module_t module_id; 8116 bcm_port_t port_id; 8117 bcm_trunk_t trunk_id; 8118 int local_id; 8119 8120 /* Get OAM Control Structure. */ 8121 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 8122 8123 _BCM_OAM_LOCK(oc); 8124 8125 /* Validate the index passed by user is within range */ 8126 BCM_OAM_BHH_VALIDATE_EP(loss_p->id); 8127 8128 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id); 8129 h_data_p = &oc->bhh_ep_data[sess_id]; 8130 8131 if (!(h_data_p->in_use)) { 8132 /* Endpoint not in use. */ 8133 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: " 8134 "Endpoint EP=%d not configured.\n"), unit, loss_p->id)); 8135 _BCM_OAM_UNLOCK(oc); 8136 return BCM_E_NOT_FOUND; 8137 } 8138 /*Validate LM period */ 8139 rv = _bcm_fp_oam_period_validate(loss_p->period); 8140 if (BCM_FAILURE(rv)) { 8141 LOG_ERROR(BSL_LS_BCM_OAM, 8142 (BSL_META_U(unit, 8143 "OAM(unit %d) Error: Invalid period : %d\n"), 8144 unit, loss_p->period)); 8145 _BCM_OAM_UNLOCK(oc); 8146 return rv; 8147 } 8148 8149 h_data_p->lm_counter_size = loss_p->lm_counter_size; 8150 sal_memset(&counter_info, 0, sizeof(counter_info)); 8151 counter_info.counter_size = loss_p->lm_counter_size; 8152 for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) 8153 { 8154 h_data_p->lm_counter_base_id[i] = loss_p->lm_counter_base_id[i]; 8155 h_data_p->lm_counter_offset[i] = loss_p->lm_counter_offset[i]; 8156 h_data_p->lm_counter_action[i] = loss_p->lm_counter_action[i]; 8157 counter_info.counter_base_id[i] = loss_p->lm_counter_base_id[i]; 8158 counter_info.counter_offset[i] = loss_p->lm_counter_offset[i]; 8159 counter_info.counter_action[i] = loss_p->lm_counter_action[i]; 8160 counter_info.byte_count_offset[i] = 0; 8161 } 8162 counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE; 8163 counter_info.oam_replacement_offset = SHR_BHH_HEADER_LENGTH; 8164 8165 bhh_sdk_msg_ctrl_loss_add_t msg; 8166 8167 sal_memset(&msg, 0, sizeof(msg)); 8168 8169 /* Check endpoint status. */ 8170 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 8171 if ((BCM_E_EXISTS != rv)) { 8172 /* Endpoint not in use. */ 8173 LOG_ERROR(BSL_LS_BCM_OAM, 8174 (BSL_META_U(unit, 8175 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 8176 unit, loss_p->id, bcm_errmsg(rv))); 8177 _BCM_OAM_UNLOCK(oc); 8178 return (rv); 8179 } 8180 8181 8182 /* 8183 * Convert host space flags to uKernel space flags 8184 */ 8185 if (loss_p->flags & BCM_OAM_LOSS_SINGLE_ENDED) { 8186 flags |= BCM_BHH_LM_SINGLE_ENDED; 8187 } 8188 8189 if (loss_p->flags & BCM_OAM_LOSS_TX_ENABLE) { 8190 flags |= BCM_BHH_LM_TX_ENABLE; 8191 } 8192 8193 if (loss_p->flags & BCM_OAM_LOSS_SLM) { 8194 flags |= BCM_BHH_LM_SLM; 8195 } 8196 8197 sal_memset(&msg, 0, sizeof(msg)); 8198 msg.flags = flags; 8199 msg.sess_id = sess_id; 8200 8201 /* 8202 * Set period 8203 */ 8204 msg.period = loss_p->period; 8205 msg.int_pri = loss_p->int_pri; 8206 msg.pkt_pri = loss_p->pkt_pri; 8207 if (h_data_p->trunk_id == BCM_TRUNK_INVALID) { 8208 rv = _bcm_esw_gport_resolve(unit, 8209 h_data_p->gport, &module_id, &port_id, &trunk_id, &local_id); 8210 } else { 8211 rv = _bcm_esw_gport_resolve(unit, 8212 h_data_p->resolved_trunk_gport, &module_id, &port_id, 8213 &trunk_id, &local_id); 8214 8215 } 8216 if (BCM_FAILURE(rv)) { 8217 LOG_ERROR(BSL_LS_BCM_OAM, 8218 (BSL_META_U(unit, 8219 "BHH(unit %d) Error: Gport resolve - %s.\n"), 8220 unit, bcm_errmsg(rv))); 8221 _BCM_OAM_UNLOCK(oc); 8222 return (rv); 8223 } 8224 8225 8226 /* 8227 * Set the BHH encapsulation data 8228 * 8229 * The function _bcm_fp_oam_bhh_encap_create() is called first 8230 * since this sets some fields in 'hash_data' which are 8231 * used in the message. 8232 */ 8233 rv = _bcm_fp_oam_bhh_encap_create(unit, 8234 module_id, 8235 port_id, 8236 h_data_p, 8237 msg.encap_data, 8238 &encap_type, 8239 &msg.encap_length, 8240 &counter_info, loss_p->int_pri, loss_p->pkt_pri, 8241 h_data_p->egr_label_ttl); 8242 if(BCM_FAILURE(rv)) 8243 { 8244 LOG_ERROR(BSL_LS_BCM_OAM, 8245 (BSL_META_U(unit, 8246 "BHH(unit %d) Error: Encap create failed " 8247 " - %s.\n"), 8248 unit, bcm_errmsg(rv))); 8249 _BCM_OAM_UNLOCK(oc); 8250 return (rv); 8251 } 8252 /* Pack control message data into DMA buffer */ 8253 buffer = oc->bhh_dma_buffer; 8254 buffer_ptr = bhh_sdk_msg_ctrl_loss_add_pack(buffer, &msg); 8255 buffer_len = buffer_ptr - buffer; 8256 8257 /* Send BHH Session Update message to uC */ 8258 rv = _bcm_fp_oam_msg_send_receive(unit, 8259 MOS_MSG_CLASS_BHH, 8260 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_ADD, 8261 buffer_len, 0, 8262 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_ADD_REPLY, 8263 &reply_len); 8264 8265 loss_p->pm_id = sess_id; 8266 8267 if(BCM_SUCCESS(rv) && (reply_len != 0)) 8268 rv = BCM_E_INTERNAL; 8269 8270 8271 _BCM_OAM_UNLOCK(oc); 8272 return (rv); 8273 } 8274 8275 /* 8276 * Function: 8277 * _bcm_fp_oam_bhh_loss_get 8278 * Purpose: 8279 * Loss Measurement get for BHH endpoints 8280 * Parameters: 8281 * unit - Device unit number 8282 * Returns: 8283 * None 8284 */ 8285 int 8286 _bcm_fp_oam_bhh_loss_get(int unit, bcm_oam_loss_t *loss_p) 8287 { 8288 _bcm_fp_oam_control_t *oc; 8289 int rv = BCM_E_NONE; 8290 _bhh_fp_oam_ep_data_t *h_data_p; 8291 uint8 *buffer, *buffer_ptr; 8292 uint16 buffer_len, reply_len; 8293 int sess_id = 0, i = 0; 8294 bhh_sdk_msg_ctrl_loss_get_t msg; 8295 uint8* encap_data = NULL; 8296 soc_olp_l2_hdr_t olp_l2_header; 8297 soc_olp_tx_hdr_t olp_oam_tx_header; 8298 8299 8300 /* Get OAM Control Structure. */ 8301 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 8302 8303 _BCM_OAM_LOCK(oc); 8304 8305 BCM_OAM_BHH_VALIDATE_EP(loss_p->id); 8306 8307 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id); 8308 h_data_p = &oc->bhh_ep_data[sess_id]; 8309 if (!(h_data_p->in_use)) { 8310 /* Endpoint not in use. */ 8311 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: " 8312 "Endpoint EP=%d %s.\n"), unit, loss_p->id, bcm_errmsg(rv))); 8313 _BCM_OAM_UNLOCK(oc); 8314 return BCM_E_NOT_FOUND; 8315 } 8316 8317 8318 /* Check endpoint status. */ 8319 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 8320 if ((BCM_E_EXISTS != rv)) { 8321 /* Endpoint not in use. */ 8322 LOG_ERROR(BSL_LS_BCM_OAM, 8323 (BSL_META_U(unit, 8324 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 8325 unit, loss_p->id, bcm_errmsg(rv))); 8326 _BCM_OAM_UNLOCK(oc); 8327 return (rv); 8328 } 8329 8330 sal_memset(&msg, 0, sizeof(msg)); 8331 /* Send BHH Session Update message to uC */ 8332 rv = _bcm_fp_oam_msg_send_receive(unit, 8333 MOS_MSG_CLASS_BHH, 8334 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_GET, 8335 sess_id, 0, 8336 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_GET_REPLY, 8337 &reply_len); 8338 if(BCM_FAILURE(rv)) { 8339 LOG_ERROR(BSL_LS_BCM_OAM, 8340 (BSL_META_U(unit, 8341 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 8342 unit, loss_p->id, bcm_errmsg(rv))); 8343 _BCM_OAM_UNLOCK(oc); 8344 return (rv); 8345 } 8346 8347 /* Pack control message data into DMA buffer */ 8348 buffer = oc->bhh_dma_buffer; 8349 buffer_ptr = bhh_sdk_msg_ctrl_loss_get_unpack(buffer, &msg); 8350 buffer_len = buffer_ptr - buffer; 8351 8352 if (reply_len != buffer_len) { 8353 rv = BCM_E_INTERNAL; 8354 } else { 8355 /* 8356 * Convert kernel space flags to host space flags 8357 */ 8358 if (msg.flags & BCM_BHH_LM_SINGLE_ENDED) { 8359 loss_p->flags |= BCM_OAM_LOSS_SINGLE_ENDED; 8360 } 8361 8362 if (msg.flags & BCM_BHH_LM_TX_ENABLE) { 8363 loss_p->flags |= BCM_OAM_LOSS_TX_ENABLE; 8364 } 8365 8366 if (msg.flags & BCM_BHH_LM_SLM) { 8367 loss_p->flags |= BCM_OAM_LOSS_SLM; 8368 } 8369 8370 loss_p->period = msg.period; 8371 loss_p->loss_threshold = msg.loss_threshold; 8372 loss_p->loss_nearend = msg.loss_nearend; 8373 loss_p->loss_farend = msg.loss_farend; 8374 loss_p->tx_nearend = msg.tx_nearend; 8375 loss_p->rx_nearend = msg.rx_nearend; 8376 loss_p->tx_farend = msg.tx_farend; 8377 loss_p->rx_farend = msg.rx_farend; 8378 loss_p->rx_oam_packets = msg.rx_oam_packets; 8379 loss_p->tx_oam_packets = msg.tx_oam_packets; 8380 loss_p->int_pri = msg.int_pri; 8381 loss_p->pkt_pri = msg.pkt_pri; 8382 loss_p->pm_id = sess_id; 8383 for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) 8384 { 8385 loss_p->lm_counter_base_id[i] = 8386 h_data_p->lm_counter_base_id[i]; 8387 loss_p->lm_counter_offset[i] = 8388 h_data_p->lm_counter_offset[i]; 8389 loss_p->lm_counter_action[i] = 8390 h_data_p->lm_counter_action[i]; 8391 } 8392 loss_p->lm_counter_size = h_data_p->lm_counter_size; 8393 encap_data = msg.encap_data; 8394 encap_data = _bcm_fp_oam_olp_l2_header_unpack(encap_data, 8395 &olp_l2_header); 8396 encap_data = shr_olp_tx_header_unpack(encap_data, 8397 &olp_oam_tx_header); 8398 loss_p->int_pri = SOC_OLP_TX_PRI_GET(&olp_oam_tx_header); 8399 8400 loss_p->pkt_pri = 8401 bcm_fp_oam_bhh_get_oam_exp_from_encap(h_data_p, 8402 msg.encap_data, 8403 msg.encap_length); 8404 rv = BCM_E_NONE; 8405 } 8406 8407 _BCM_OAM_UNLOCK(oc); 8408 8409 return (rv); 8410 } 8411 8412 /* 8413 * Function: 8414 * _bcm_fp_oam_bhh_loss_delete 8415 * Purpose: 8416 * Loss Measurement Delete for BHH endpoints 8417 * Parameters: 8418 * unit - Device unit number 8419 * Returns: 8420 * None 8421 */ 8422 int 8423 _bcm_fp_oam_bhh_loss_delete(int unit, bcm_oam_loss_t *loss_p) 8424 { 8425 _bcm_fp_oam_control_t *oc; 8426 int rv = BCM_E_NONE; 8427 _bhh_fp_oam_ep_data_t *h_data_p; 8428 uint8 *buffer, *buffer_ptr; 8429 uint16 buffer_len, reply_len; 8430 int sess_id = 0; 8431 8432 /* Get OAM Control Structure. */ 8433 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 8434 8435 _BCM_OAM_LOCK(oc); 8436 BCM_OAM_BHH_VALIDATE_EP(loss_p->id); 8437 8438 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id); 8439 h_data_p = &oc->bhh_ep_data[sess_id]; 8440 if (!(h_data_p->in_use)) { 8441 /* Endpoint not in use. */ 8442 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: " 8443 "Endpoint EP=%d %s.\n"), unit, loss_p->id, bcm_errmsg(rv))); 8444 _BCM_OAM_UNLOCK(oc); 8445 return BCM_E_NOT_FOUND; 8446 } 8447 8448 8449 shr_bhh_msg_ctrl_loss_delete_t msg; 8450 8451 /* Check endpoint status. */ 8452 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 8453 if ((BCM_E_EXISTS != rv)) { 8454 /* Endpoint not in use. */ 8455 LOG_ERROR(BSL_LS_BCM_OAM, 8456 (BSL_META_U(unit, 8457 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 8458 unit, loss_p->id, bcm_errmsg(rv))); 8459 _BCM_OAM_UNLOCK(oc); 8460 return (rv); 8461 } 8462 8463 h_data_p = &oc->bhh_ep_data[loss_p->id]; 8464 8465 msg.sess_id = sess_id; 8466 8467 /* Pack control message data into DMA buffer */ 8468 buffer = oc->bhh_dma_buffer; 8469 buffer_ptr = shr_bhh_msg_ctrl_loss_delete_pack(buffer, &msg); 8470 buffer_len = buffer_ptr - buffer; 8471 8472 /* Send BHH Session Update message to uC */ 8473 rv = _bcm_fp_oam_msg_send_receive(unit, 8474 MOS_MSG_CLASS_BHH, 8475 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_DELETE, 8476 buffer_len, 0, 8477 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_DELETE_REPLY, 8478 &reply_len); 8479 8480 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 8481 rv = BCM_E_INTERNAL; 8482 } 8483 8484 8485 _BCM_OAM_UNLOCK(oc); 8486 8487 return (rv); 8488 } 8489 8490 /* 8491 * Function: 8492 * _bcm_fp_oam_bhh_delay_add 8493 * Purpose: 8494 * Delay Measurement add for BHH endpoints. 8495 * Parameters: 8496 * unit - Device unit number 8497 * Returns: 8498 * None 8499 */ 8500 int 8501 _bcm_fp_oam_bhh_delay_add(int unit, bcm_oam_delay_t *delay_p) 8502 { 8503 _bcm_fp_oam_control_t *oc; 8504 _bhh_fp_oam_ep_data_t *h_data_p; 8505 int rv = BCM_E_NONE; 8506 uint8 *buffer, *buffer_ptr, encap_type; 8507 uint16 buffer_len, reply_len; 8508 uint32 flags = 0; 8509 int sess_id = 0, i = 0; 8510 _bhh_oam_lm_dm_info_t counter_info; 8511 bcm_module_t module_id; 8512 bcm_port_t port_id; 8513 bcm_trunk_t trunk_id; 8514 int local_id; 8515 8516 /* Get OAM Control Structure. */ 8517 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 8518 8519 _BCM_OAM_LOCK(oc); 8520 BCM_OAM_BHH_VALIDATE_EP(delay_p->id); 8521 8522 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id); 8523 8524 h_data_p = &oc->bhh_ep_data[sess_id]; 8525 if (!(h_data_p->in_use)) { 8526 /* Endpoint not in use. */ 8527 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: " 8528 "Endpoint EP=%d %s.\n"), unit, delay_p->id, bcm_errmsg(rv))); 8529 _BCM_OAM_UNLOCK(oc); 8530 return BCM_E_NOT_FOUND; 8531 } 8532 /*Validate LM period */ 8533 rv = _bcm_fp_oam_period_validate(delay_p->period); 8534 if (BCM_FAILURE(rv)) { 8535 LOG_ERROR(BSL_LS_BCM_OAM, 8536 (BSL_META_U(unit, 8537 "OAM(unit %d) Error: Invalid period : %d\n"), 8538 unit, delay_p->period)); 8539 _BCM_OAM_UNLOCK(oc); 8540 return (rv); 8541 } 8542 8543 h_data_p->dm_tx_counter_size = delay_p->dm_tx_update_lm_counter_size; 8544 sal_memset(&counter_info, 0, sizeof(counter_info)); 8545 counter_info.counter_size = delay_p->dm_tx_update_lm_counter_size; 8546 for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) 8547 { 8548 h_data_p->dm_tx_update_lm_counter_base_id[i] = 8549 delay_p->dm_tx_update_lm_counter_base_id[i]; 8550 h_data_p->dm_tx_update_lm_counter_offset[i] = 8551 delay_p->dm_tx_update_lm_counter_offset[i]; 8552 counter_info.counter_base_id[i] = 8553 delay_p->dm_tx_update_lm_counter_base_id[i]; 8554 counter_info.counter_offset[i] = 8555 delay_p->dm_tx_update_lm_counter_offset[i]; 8556 counter_info.counter_action[i] = bcmOamCounterActionIncrement; 8557 counter_info.byte_count_offset[i] = 0; 8558 } 8559 counter_info.oam_replacement_offset = SHR_BHH_HEADER_LENGTH; 8560 8561 8562 bhh_sdk_msg_ctrl_delay_add_t msg; 8563 sal_memset(&msg, 0, sizeof(msg)); 8564 8565 /* Check endpoint status. */ 8566 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 8567 if ((BCM_E_EXISTS != rv)) { 8568 /* Endpoint not in use. */ 8569 LOG_ERROR(BSL_LS_BCM_OAM, 8570 (BSL_META_U(unit, 8571 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 8572 unit, delay_p->id, bcm_errmsg(rv))); 8573 _BCM_OAM_UNLOCK(oc); 8574 return (rv); 8575 } 8576 /* 8577 * Convert host space flags to uKernel space flags 8578 */ 8579 if (delay_p->flags & BCM_OAM_DELAY_ONE_WAY) { 8580 flags |= BCM_BHH_DM_ONE_WAY; 8581 } 8582 8583 if (delay_p->flags & BCM_OAM_DELAY_TX_ENABLE) { 8584 flags |= BCM_BHH_DM_TX_ENABLE; 8585 } 8586 8587 sal_memset(&msg, 0, sizeof(msg)); 8588 msg.flags = flags; 8589 msg.sess_id = sess_id; 8590 8591 if(delay_p->timestamp_format == bcmOAMTimestampFormatIEEE1588v1) { 8592 msg.dm_format = BCM_BHH_DM_TYPE_PTP; 8593 counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_PTP; 8594 } else { 8595 msg.dm_format = BCM_BHH_DM_TYPE_NTP; 8596 counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NTP; 8597 } 8598 /* 8599 * Set period 8600 */ 8601 msg.period = delay_p->period; 8602 8603 if (h_data_p->trunk_id == BCM_TRUNK_INVALID) { 8604 rv = _bcm_esw_gport_resolve(unit, 8605 h_data_p->gport, &module_id, &port_id, &trunk_id, &local_id); 8606 } else { 8607 rv = _bcm_esw_gport_resolve(unit, 8608 h_data_p->resolved_trunk_gport, &module_id, &port_id, 8609 &trunk_id, &local_id); 8610 8611 } 8612 8613 if (BCM_FAILURE(rv)) { 8614 LOG_ERROR(BSL_LS_BCM_OAM, 8615 (BSL_META_U(unit, 8616 "BHH(unit %d) Error: Gport resolve - %s.\n"), 8617 unit, bcm_errmsg(rv))); 8618 _BCM_OAM_UNLOCK(oc); 8619 return (rv); 8620 } 8621 8622 8623 /* 8624 * Set the BHH encapsulation data 8625 * 8626 * The function _bcm_fp_oam_bhh_encap_create() is called first 8627 * since this sets some fields in 'hash_data' which are 8628 * used in the message. 8629 */ 8630 rv = _bcm_fp_oam_bhh_encap_create(unit, 8631 module_id, 8632 port_id, 8633 h_data_p, 8634 msg.encap_data, 8635 &encap_type, 8636 &msg.encap_length, 8637 &counter_info, delay_p->int_pri, delay_p->pkt_pri, 8638 h_data_p->egr_label_ttl); 8639 if(BCM_FAILURE(rv)) 8640 { 8641 LOG_ERROR(BSL_LS_BCM_OAM, 8642 (BSL_META_U(unit, 8643 "BHH(unit %d) Error: Encap create failed " 8644 " - %s.\n"), 8645 unit, bcm_errmsg(rv))); 8646 _BCM_OAM_UNLOCK(oc); 8647 return (rv); 8648 } 8649 /* Pack control message data into DMA buffer */ 8650 buffer = oc->bhh_dma_buffer; 8651 buffer_ptr = bhh_sdk_msg_ctrl_delay_add_pack(buffer, &msg); 8652 buffer_len = buffer_ptr - buffer; 8653 8654 /* Send BHH Session Update message to uC */ 8655 rv = _bcm_fp_oam_msg_send_receive(unit, 8656 MOS_MSG_CLASS_BHH, 8657 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_ADD, 8658 buffer_len, 0, 8659 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_ADD_REPLY, 8660 &reply_len); 8661 8662 delay_p->pm_id = sess_id; 8663 8664 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 8665 rv = BCM_E_INTERNAL; 8666 } 8667 8668 8669 _BCM_OAM_UNLOCK(oc); 8670 return (rv); 8671 } 8672 8673 /* 8674 * Function: 8675 * _bcm_fp_oam_bhh_delay_get 8676 * Purpose: 8677 * Delay Measurements get for BHH endpoints. 8678 * Parameters: 8679 * unit - Device unit number 8680 * Returns: 8681 * None 8682 */ 8683 int 8684 _bcm_fp_oam_bhh_delay_get(int unit, bcm_oam_delay_t *delay_p) 8685 { 8686 _bcm_fp_oam_control_t *oc; 8687 int rv = BCM_E_NONE; 8688 _bhh_fp_oam_ep_data_t *h_data_p; 8689 uint8 *buffer, *buffer_ptr; 8690 uint16 buffer_len, reply_len; 8691 int sess_id = 0, i = 0; 8692 bhh_sdk_msg_ctrl_delay_get_t msg; 8693 uint8* encap_data = NULL; 8694 soc_olp_l2_hdr_t olp_l2_header; 8695 soc_olp_tx_hdr_t olp_oam_tx_header; 8696 8697 /* Get OAM Control Structure. */ 8698 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 8699 8700 _BCM_OAM_LOCK(oc); 8701 BCM_OAM_BHH_VALIDATE_EP(delay_p->id); 8702 8703 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id); 8704 8705 h_data_p = &oc->bhh_ep_data[sess_id]; 8706 if (!(h_data_p->in_use)) { 8707 /* Endpoint not in use. */ 8708 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: " 8709 "Endpoint EP=%d %s.\n"), unit, delay_p->id, bcm_errmsg(rv))); 8710 _BCM_OAM_UNLOCK(oc); 8711 return BCM_E_NOT_FOUND; 8712 } 8713 8714 /* Check endpoint status. */ 8715 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 8716 if ((BCM_E_EXISTS != rv)) { 8717 /* Endpoint not in use. */ 8718 LOG_ERROR(BSL_LS_BCM_OAM, 8719 (BSL_META_U(unit, 8720 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 8721 unit, delay_p->id, bcm_errmsg(rv))); 8722 _BCM_OAM_UNLOCK(oc); 8723 return (rv); 8724 } 8725 8726 sal_memset(&msg, 0, sizeof(msg)); 8727 /* Send BHH Session Update message to uC */ 8728 rv = _bcm_fp_oam_msg_send_receive(unit, 8729 MOS_MSG_CLASS_BHH, 8730 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_GET, 8731 sess_id, 0, 8732 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_GET_REPLY, 8733 &reply_len); 8734 if(BCM_FAILURE(rv)) { 8735 LOG_ERROR(BSL_LS_BCM_OAM, 8736 (BSL_META_U(unit, 8737 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 8738 unit, delay_p->id, bcm_errmsg(rv))); 8739 _BCM_OAM_UNLOCK(oc); 8740 return (rv); 8741 } 8742 8743 /* Pack control message data into DMA buffer */ 8744 buffer = oc->bhh_dma_buffer; 8745 buffer_ptr = bhh_sdk_msg_ctrl_delay_get_unpack(buffer, &msg); 8746 buffer_len = buffer_ptr - buffer; 8747 8748 8749 if (reply_len != buffer_len) { 8750 rv = BCM_E_INTERNAL; 8751 } else { 8752 /* 8753 * Convert kernel space flags to host space flags 8754 */ 8755 if (msg.flags & BCM_BHH_DM_ONE_WAY) { 8756 delay_p->flags |= BCM_OAM_DELAY_ONE_WAY; 8757 } 8758 8759 if (msg.flags & BCM_BHH_DM_TX_ENABLE) { 8760 delay_p->flags |= BCM_OAM_DELAY_TX_ENABLE; 8761 } 8762 8763 delay_p->period = msg.period; 8764 8765 if(msg.dm_format == BCM_BHH_DM_TYPE_PTP) 8766 delay_p->timestamp_format = bcmOAMTimestampFormatIEEE1588v1; 8767 else 8768 delay_p->timestamp_format = bcmOAMTimestampFormatNTP; 8769 8770 rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->delay), 8771 msg.delay_seconds, msg.delay_nanoseconds); 8772 if(BCM_SUCCESS(rv)) { 8773 rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->txf), 8774 msg.txf_seconds, msg.txf_nanoseconds); 8775 } 8776 if(BCM_SUCCESS(rv)) { 8777 rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->rxf), 8778 msg.rxf_seconds, msg.rxf_nanoseconds); 8779 } 8780 if(BCM_SUCCESS(rv)) { 8781 rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->txb), 8782 msg.txb_seconds, msg.txb_nanoseconds); 8783 } 8784 if(BCM_SUCCESS(rv)) { 8785 rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->rxb), 8786 msg.rxb_seconds, msg.rxb_nanoseconds); 8787 } 8788 delay_p->rx_oam_packets = msg.rx_oam_packets; 8789 delay_p->tx_oam_packets = msg.tx_oam_packets; 8790 delay_p->int_pri = msg.int_pri; 8791 delay_p->pkt_pri = msg.pkt_pri; 8792 delay_p->pm_id = sess_id; 8793 for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) 8794 { 8795 delay_p->dm_tx_update_lm_counter_base_id[i] = 8796 h_data_p->dm_tx_update_lm_counter_base_id[i]; 8797 delay_p->dm_tx_update_lm_counter_offset[i] = 8798 h_data_p->dm_tx_update_lm_counter_offset[i]; 8799 } 8800 delay_p->dm_tx_update_lm_counter_size = h_data_p->dm_tx_counter_size; 8801 encap_data = msg.encap_data; 8802 encap_data = _bcm_fp_oam_olp_l2_header_unpack(encap_data, 8803 &olp_l2_header); 8804 encap_data = shr_olp_tx_header_unpack(encap_data, 8805 &olp_oam_tx_header); 8806 delay_p->int_pri = SOC_OLP_TX_PRI_GET (&olp_oam_tx_header); 8807 delay_p->pkt_pri = 8808 bcm_fp_oam_bhh_get_oam_exp_from_encap(h_data_p, 8809 msg.encap_data, 8810 msg.encap_length); 8811 } 8812 8813 8814 _BCM_OAM_UNLOCK(oc); 8815 8816 return (rv); 8817 } 8818 8819 /* 8820 * Function: 8821 * _bcm_fp_oam_bhh_delay_delete 8822 * Purpose: 8823 * Delay Measurement Delete 8824 * Parameters: 8825 * unit - Device unit number 8826 * Returns: 8827 * None 8828 */ 8829 int 8830 _bcm_fp_oam_bhh_delay_delete(int unit, bcm_oam_delay_t *delay_p) 8831 { 8832 _bcm_fp_oam_control_t *oc; 8833 int rv = BCM_E_NONE; 8834 _bhh_fp_oam_ep_data_t *h_data_p; 8835 uint8 *buffer, *buffer_ptr; 8836 uint16 buffer_len, reply_len; 8837 int sess_id = 0; 8838 8839 /* Get OAM Control Structure. */ 8840 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 8841 8842 _BCM_OAM_LOCK(oc); 8843 8844 BCM_OAM_BHH_VALIDATE_EP(delay_p->id); 8845 8846 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id); 8847 h_data_p = &oc->bhh_ep_data[sess_id]; 8848 8849 if (!(h_data_p->in_use)) { 8850 /* Endpoint not in use. */ 8851 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: " 8852 "Endpoint EP=%d %s.\n"), unit, delay_p->id, bcm_errmsg(rv))); 8853 _BCM_OAM_UNLOCK(oc); 8854 return BCM_E_NOT_FOUND; 8855 } 8856 8857 8858 shr_bhh_msg_ctrl_delay_delete_t msg; 8859 8860 /* Check endpoint status. */ 8861 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 8862 if ((BCM_E_EXISTS != rv)) { 8863 /* Endpoint not in use. */ 8864 LOG_ERROR(BSL_LS_BCM_OAM, 8865 (BSL_META_U(unit, 8866 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 8867 unit, delay_p->id, bcm_errmsg(rv))); 8868 _BCM_OAM_UNLOCK(oc); 8869 return (rv); 8870 } 8871 8872 msg.sess_id = sess_id; 8873 8874 /* Pack control message data into DMA buffer */ 8875 buffer = oc->bhh_dma_buffer; 8876 buffer_ptr = shr_bhh_msg_ctrl_delay_delete_pack(buffer, &msg); 8877 buffer_len = buffer_ptr - buffer; 8878 8879 /* Send BHH Session Update message to uC */ 8880 rv = _bcm_fp_oam_msg_send_receive(unit, 8881 MOS_MSG_CLASS_BHH, 8882 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_DELETE, 8883 buffer_len, 0, 8884 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_DELETE_REPLY, 8885 &reply_len); 8886 8887 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 8888 rv = BCM_E_INTERNAL; 8889 } 8890 8891 8892 _BCM_OAM_UNLOCK(oc); 8893 8894 return (rv); 8895 } 8896 8897 /* 8898 * Function: 8899 * _bcm_fp_oam_csf_add 8900 * Purpose: 8901 * Start CSF PDU transmission 8902 * Parameters: 8903 * unit - (IN) Unit number. 8904 * csf_ptr - (INOUT) CSF object 8905 * Returns: 8906 * BCM_E_XXX 8907 * Notes: 8908 */ 8909 int _bcm_fp_oam_csf_add(int unit, bcm_oam_csf_t *csf_p) 8910 { 8911 _bcm_fp_oam_control_t *oc; 8912 _bhh_fp_oam_ep_data_t *h_data_p; 8913 bhh_sdk_msg_ctrl_csf_add_t msg; 8914 uint8 *buffer, *buffer_ptr; 8915 uint16 buffer_len, reply_len; 8916 _bhh_oam_lm_dm_info_t counter_info; 8917 bcm_module_t module_id; 8918 bcm_port_t port_id; 8919 bcm_trunk_t trunk_id; 8920 int local_id; 8921 uint8 encap_type; 8922 int sess_id = 0; 8923 int i; 8924 int rv = BCM_E_NONE; 8925 8926 /* Get OAM Control Structure. */ 8927 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 8928 _BCM_OAM_LOCK(oc); 8929 8930 if (oc->ukernel_not_ready) { 8931 _BCM_OAM_UNLOCK(oc); 8932 return BCM_E_INIT; 8933 } 8934 8935 BCM_OAM_BHH_VALIDATE_EP(csf_p->id); 8936 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id); 8937 8938 /* Check endpoint status. */ 8939 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 8940 if ((BCM_E_EXISTS != rv)) { 8941 /* Endpoint not in use. */ 8942 LOG_ERROR(BSL_LS_BCM_OAM, 8943 (BSL_META_U(unit, 8944 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 8945 unit, csf_p->id, bcm_errmsg(rv))); 8946 _BCM_OAM_UNLOCK(oc); 8947 return (rv); 8948 } 8949 8950 if ((csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1S) && 8951 (csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1M)) { 8952 /* Only 1S and 1M are supported */ 8953 _BCM_OAM_UNLOCK(oc); 8954 return BCM_E_PARAM; 8955 } 8956 8957 h_data_p = &oc->bhh_ep_data[sess_id]; 8958 /* 8959 * Only BHH is supported 8960 */ 8961 if (!BHH_EP_TYPE(h_data_p)) { 8962 _BCM_OAM_UNLOCK(oc); 8963 return BCM_E_UNAVAIL; 8964 } 8965 8966 sal_memset(&counter_info, 0, sizeof(counter_info)); 8967 counter_info.counter_size = csf_p->csf_tx_update_lm_counter_size; 8968 h_data_p->csf_tx_counter_size = csf_p->csf_tx_update_lm_counter_size; 8969 for (i = 0; i < BCM_OAM_LM_COUNTER_MAX; i++) { 8970 h_data_p->csf_tx_update_lm_counter_base_id[i] = 8971 csf_p->csf_tx_update_lm_counter_base_id[i]; 8972 h_data_p->csf_tx_update_lm_counter_offset[i] = 8973 csf_p->csf_tx_update_lm_counter_offset[i]; 8974 8975 counter_info.counter_base_id[i] = 8976 csf_p->csf_tx_update_lm_counter_base_id[i]; 8977 counter_info.counter_offset[i] = 8978 csf_p->csf_tx_update_lm_counter_offset[i]; 8979 counter_info.counter_action[i] = bcmOamCounterActionIncrement; 8980 } 8981 counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE; 8982 8983 sal_memset(&msg, 0, sizeof(msg)); 8984 msg.sess_id = sess_id; 8985 msg.int_pri = csf_p->int_pri; 8986 msg.pkt_pri = csf_p->pkt_pri; 8987 8988 switch(csf_p->type) { 8989 case BCM_OAM_CSF_LOS: 8990 msg.type = SHR_CSF_TYPE_LOS; 8991 break; 8992 8993 case BCM_OAM_CSF_FDI: 8994 msg.type = SHR_CSF_TYPE_FDI; 8995 break; 8996 8997 case BCM_OAM_CSF_RDI: 8998 msg.type = SHR_CSF_TYPE_RDI; 8999 break; 9000 9001 case BCM_OAM_CSF_DCI: 9002 msg.type = SHR_CSF_TYPE_DCI; 9003 break; 9004 9005 default: 9006 _BCM_OAM_UNLOCK(oc); 9007 return BCM_E_PARAM; 9008 } 9009 9010 /* 9011 * Set period 9012 */ 9013 msg.period = csf_p->period; 9014 9015 if (h_data_p->trunk_id == BCM_TRUNK_INVALID) { 9016 rv = _bcm_esw_gport_resolve(unit, h_data_p->gport, 9017 &module_id, &port_id, 9018 &trunk_id, &local_id); 9019 } else { 9020 rv = _bcm_esw_gport_resolve(unit, 9021 h_data_p->resolved_trunk_gport, 9022 &module_id, &port_id, 9023 &trunk_id, &local_id); 9024 } 9025 if (rv != BCM_E_NONE) { 9026 _BCM_OAM_UNLOCK(oc); 9027 return rv; 9028 } 9029 9030 /* 9031 * Set the BHH encapsulation data 9032 */ 9033 rv = _bcm_fp_oam_bhh_encap_create(unit, module_id, port_id, h_data_p, 9034 msg.encap_data, &encap_type, 9035 &msg.encap_length, &counter_info, 9036 csf_p->int_pri, csf_p->pkt_pri, 9037 h_data_p->egr_label_ttl); 9038 if(BCM_FAILURE(rv)) { 9039 LOG_ERROR(BSL_LS_BCM_OAM, 9040 (BSL_META_U(unit, 9041 "BHH(unit %d) Error: Encap create failed " 9042 " - %s.\n"), 9043 unit, bcm_errmsg(rv))); 9044 _BCM_OAM_UNLOCK(oc); 9045 return rv; 9046 } 9047 9048 /* Pack control message data into DMA buffer */ 9049 buffer = oc->bhh_dma_buffer; 9050 buffer_ptr = bhh_sdk_msg_ctrl_csf_add_pack(buffer, &msg); 9051 buffer_len = buffer_ptr - buffer; 9052 9053 /* Send BHH Session Update message to uC */ 9054 rv = _bcm_fp_oam_msg_send_receive(unit, 9055 MOS_MSG_CLASS_BHH, 9056 MOS_MSG_SUBCLASS_BHH_CSF_ADD, 9057 buffer_len, 0, 9058 MOS_MSG_SUBCLASS_BHH_CSF_ADD_REPLY, 9059 &reply_len); 9060 9061 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 9062 rv = BCM_E_INTERNAL; 9063 } 9064 9065 _BCM_OAM_UNLOCK(oc); 9066 return rv; 9067 } 9068 9069 /* 9070 * Function: 9071 * _bcm_fp_oam_csf_get 9072 * Purpose: 9073 * Get CSF info 9074 * Parameters: 9075 * unit - (IN) Unit number. 9076 * csf_ptr - (OUT) CSF object 9077 * Returns: 9078 * BCM_E_XXX 9079 * Notes: 9080 */ 9081 int _bcm_fp_oam_csf_get(int unit, bcm_oam_csf_t *csf_p) 9082 { 9083 _bcm_fp_oam_control_t *oc; 9084 bhh_sdk_msg_ctrl_csf_get_t msg; 9085 _bhh_fp_oam_ep_data_t *h_data_p; 9086 uint8 *buffer, *buffer_ptr; 9087 uint16 buffer_len, reply_len; 9088 uint8* encap_data = NULL; 9089 soc_olp_l2_hdr_t olp_l2_header; 9090 soc_olp_tx_hdr_t olp_oam_tx_header; 9091 int sess_id = 0; 9092 int i; 9093 int rv = BCM_E_NONE; 9094 9095 9096 /* Get OAM Control Structure. */ 9097 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 9098 _BCM_OAM_LOCK(oc); 9099 9100 if (oc->ukernel_not_ready) { 9101 _BCM_OAM_UNLOCK(oc); 9102 return BCM_E_INIT; 9103 } 9104 9105 BCM_OAM_BHH_VALIDATE_EP(csf_p->id); 9106 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id); 9107 9108 /* Check endpoint status. */ 9109 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 9110 if ((BCM_E_EXISTS != rv)) { 9111 /* Endpoint not in use. */ 9112 LOG_ERROR(BSL_LS_BCM_OAM, 9113 (BSL_META_U(unit, 9114 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 9115 unit, csf_p->id, bcm_errmsg(rv))); 9116 _BCM_OAM_UNLOCK(oc); 9117 return (rv); 9118 } 9119 9120 h_data_p = &oc->bhh_ep_data[sess_id]; 9121 9122 if (!BHH_EP_TYPE(h_data_p)) { 9123 _BCM_OAM_UNLOCK(oc); 9124 return BCM_E_UNAVAIL; 9125 } 9126 9127 9128 sal_memset(&msg, 0, sizeof(msg)); 9129 9130 /* Send BHH Session Update message to uC */ 9131 rv = _bcm_fp_oam_msg_send_receive(unit, 9132 MOS_MSG_CLASS_BHH, 9133 MOS_MSG_SUBCLASS_BHH_CSF_GET, 9134 sess_id, 0, 9135 MOS_MSG_SUBCLASS_BHH_CSF_GET_REPLY, 9136 &reply_len); 9137 if(BCM_FAILURE(rv)) { 9138 LOG_ERROR(BSL_LS_BCM_OAM, 9139 (BSL_META_U(unit, 9140 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 9141 unit, csf_p->id, bcm_errmsg(rv))); 9142 _BCM_OAM_UNLOCK(oc); 9143 return (rv); 9144 } 9145 9146 /* Pack control message data into DMA buffer */ 9147 buffer = oc->bhh_dma_buffer; 9148 buffer_ptr = bhh_sdk_msg_ctrl_csf_get_unpack(buffer, &msg); 9149 buffer_len = buffer_ptr - buffer; 9150 9151 9152 if (reply_len != buffer_len) { 9153 _BCM_OAM_UNLOCK(oc); 9154 return BCM_E_INTERNAL; 9155 } 9156 9157 switch(msg.type) { 9158 case SHR_CSF_TYPE_LOS: 9159 csf_p->type = BCM_OAM_CSF_LOS; 9160 break; 9161 9162 case SHR_CSF_TYPE_FDI: 9163 csf_p->type = BCM_OAM_CSF_FDI; 9164 break; 9165 9166 case SHR_CSF_TYPE_RDI: 9167 csf_p->type = BCM_OAM_CSF_RDI; 9168 break; 9169 9170 case SHR_CSF_TYPE_DCI: 9171 csf_p->type = BCM_OAM_CSF_DCI; 9172 break; 9173 9174 default: 9175 _BCM_OAM_UNLOCK(oc); 9176 return BCM_E_INTERNAL; 9177 } 9178 9179 csf_p->period = msg.period; 9180 csf_p->flags = msg.flags; 9181 9182 for (i = 0; i< BCM_OAM_LM_COUNTER_MAX; i++) { 9183 csf_p->csf_tx_update_lm_counter_base_id[i] = 9184 h_data_p->csf_tx_update_lm_counter_base_id[i]; 9185 csf_p->csf_tx_update_lm_counter_offset[i] = 9186 h_data_p->csf_tx_update_lm_counter_offset[i]; 9187 } 9188 csf_p->csf_tx_update_lm_counter_size = h_data_p->csf_tx_counter_size; 9189 9190 encap_data = msg.encap_data; 9191 encap_data = _bcm_fp_oam_olp_l2_header_unpack(encap_data, 9192 &olp_l2_header); 9193 encap_data = shr_olp_tx_header_unpack(encap_data, 9194 &olp_oam_tx_header); 9195 csf_p->int_pri = SOC_OLP_TX_PRI_GET (&olp_oam_tx_header); 9196 csf_p->pkt_pri = bcm_fp_oam_bhh_get_oam_exp_from_encap(h_data_p, 9197 msg.encap_data, 9198 msg.encap_length); 9199 _BCM_OAM_UNLOCK(oc); 9200 return BCM_E_NONE; 9201 9202 } 9203 9204 /* 9205 * Function: 9206 * _bcm_fp_oam_csf_delete 9207 * Purpose: 9208 * Stop CSF PDU transmission 9209 * Parameters: 9210 * unit - (IN Unit number. 9211 * csf_ptr - (IN) CSF object 9212 * Returns: 9213 * BCM_E_XXX 9214 * Notes: 9215 */ 9216 int _bcm_fp_oam_csf_delete(int unit, bcm_oam_csf_t *csf_p) 9217 { 9218 _bcm_fp_oam_control_t *oc; 9219 _bhh_fp_oam_ep_data_t *h_data_p; 9220 uint16 reply_len; 9221 int sess_id; 9222 int rv = BCM_E_NONE; 9223 9224 /* Get OAM Control Structure. */ 9225 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 9226 _BCM_OAM_LOCK(oc); 9227 9228 if (oc->ukernel_not_ready) { 9229 _BCM_OAM_UNLOCK(oc); 9230 return BCM_E_INIT; 9231 } 9232 9233 BCM_OAM_BHH_VALIDATE_EP(csf_p->id); 9234 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id); 9235 9236 /* Check endpoint status. */ 9237 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 9238 if ((BCM_E_EXISTS != rv)) { 9239 /* Endpoint not in use. */ 9240 LOG_ERROR(BSL_LS_BCM_OAM, 9241 (BSL_META_U(unit, 9242 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 9243 unit, csf_p->id, bcm_errmsg(rv))); 9244 _BCM_OAM_UNLOCK(oc); 9245 return (rv); 9246 } 9247 9248 h_data_p = &oc->bhh_ep_data[sess_id]; 9249 9250 if (!BHH_EP_TYPE(h_data_p)) { 9251 _BCM_OAM_UNLOCK(oc); 9252 return BCM_E_UNAVAIL; 9253 } 9254 9255 /* Send BHH Session Update message to uC */ 9256 rv = _bcm_fp_oam_msg_send_receive(unit, 9257 MOS_MSG_CLASS_BHH, 9258 MOS_MSG_SUBCLASS_BHH_CSF_DELETE, 9259 sess_id, 0, 9260 MOS_MSG_SUBCLASS_BHH_CSF_DELETE_REPLY, 9261 &reply_len); 9262 9263 _BCM_OAM_UNLOCK(oc); 9264 return (rv); 9265 } 9266 9267 /* 9268 * Function: 9269 * _bcm_fp_oam_bhh_group_traverse 9270 * Purpose: 9271 * Traverse the entire set of BHH groups, calling a specified 9272 * callback for each one 9273 * Parameters: 9274 * unit - (IN) BCM device number 9275 * cb - (IN) Pointer to call back function. 9276 * user_data - (IN) Pointer to user supplied data. 9277 * Returns: 9278 * BCM_E_XXX 9279 */ 9280 int 9281 _bcm_fp_oam_bhh_group_traverse(int unit, bcm_oam_group_traverse_cb cb, 9282 void *user_data) 9283 { 9284 _bcm_fp_oam_control_t *oc; /* OAM control structure pointer. */ 9285 bcm_oam_group_info_t group_info; /* Group information to be set. */ 9286 bcm_oam_group_t grp_idx; /* MA Group index. */ 9287 int rv; /* Operation return status. */ 9288 9289 if (NULL == cb) { 9290 return (BCM_E_PARAM); 9291 } 9292 9293 /* Get device OAM control structure handle. */ 9294 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 9295 9296 if (soc_feature(unit, soc_feature_bhh)) { 9297 for (grp_idx = 0; grp_idx < oc->bhh_endpoint_count; grp_idx++) { 9298 9299 /* Check if the group is in use. */ 9300 if (BCM_E_EXISTS 9301 == shr_idxres_list_elem_state(oc->bhh_group_pool, grp_idx)) { 9302 9303 /* Initialize the group information structure. */ 9304 bcm_oam_group_info_t_init(&group_info); 9305 9306 group_info.id = BCM_OAM_BHH_GET_SDK_GROUP(grp_idx); 9307 /* Retrieve group information and set in group_info structure.*/ 9308 rv = _bcm_fp_oam_bhh_group_get(unit, &group_info); 9309 if (BCM_FAILURE(rv)) { 9310 LOG_ERROR(BSL_LS_BCM_OAM, 9311 (BSL_META_U(unit, 9312 "OAM(unit %d) Error: " 9313 "_bcm_fp_oam_bhh_group_get " 9314 "(GID=%d) - %s.\n"), unit, grp_idx, 9315 bcm_errmsg(rv))); 9316 return (rv); 9317 } 9318 /* Call the user call back routine with group information. */ 9319 rv = cb(unit, &group_info, user_data); 9320 if (BCM_FAILURE(rv)) { 9321 LOG_ERROR(BSL_LS_BCM_OAM, 9322 (BSL_META_U(unit, 9323 "OAM(unit %d) Error: User call back " 9324 "routine (GID=%d) - %s.\n"), unit, 9325 grp_idx, bcm_errmsg(rv))); 9326 return (rv); 9327 } 9328 } 9329 } 9330 } 9331 9332 return BCM_E_NONE; 9333 } 9334 9335 /* 9336 * Function: 9337 * _bcm_fp_oam_bhh_group_destroy_all 9338 * Purpose: 9339 * Traverse the entire set of BHH groups and deletes all of them 9340 * Parameters: 9341 * unit - (IN) BCM device number 9342 * Returns: 9343 * BCM_E_XXX 9344 */ 9345 int 9346 _bcm_fp_oam_bhh_group_destroy_all(int unit) 9347 { 9348 _bcm_fp_oam_control_t *oc; /* OAM control structure pointer. */ 9349 bcm_oam_group_t grp_idx, group = 0;/* MA Group index. */ 9350 int rv; /* Operation return status. */ 9351 9352 /* Get device OAM control structure handle. */ 9353 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 9354 9355 for (grp_idx = 0; grp_idx < oc->bhh_endpoint_count; grp_idx++) { 9356 9357 /* Check if the group is in use. */ 9358 if (BCM_E_EXISTS 9359 == shr_idxres_list_elem_state(oc->bhh_group_pool, grp_idx)) { 9360 9361 group = BCM_OAM_BHH_GET_SDK_GROUP(grp_idx); 9362 9363 rv = _bcm_fp_oam_bhh_group_destroy(unit, group); 9364 if (BCM_FAILURE(rv)) { 9365 LOG_ERROR(BSL_LS_BCM_OAM, 9366 (BSL_META_U(unit, 9367 "OAM(unit %d) Error: " 9368 "_bcm_fp_oam_bhh_group_destroy " 9369 "(GID=%d) - %s.\n"), unit, group, 9370 bcm_errmsg(rv))); 9371 return (rv); 9372 } 9373 } 9374 } 9375 9376 return BCM_E_NONE; 9377 } 9378 #endif /*(INCLUDE_BHH) */ 9379 9380 /*******************************************************************************/ 9381 /* CCM Embedded App supporting functions Start */ 9382 /*******************************************************************************/ 9383 #if defined (INCLUDE_CCM) 9384 9385 #define _BCM_OAM_GLP_MODULE_ID_GET(_glp_) (0xFF & ((_glp_) >> 7)) 9386 #define _BCM_OAM_GLP_PORT_GET(_glp_) (0x7F & (_glp_)) 9387 9388 /* 9389 * Macro: 9390 * _BCM_OAM_EP_INDEX_VALIDATE 9391 * Purpose: 9392 * Validate OAM Endpoint ID value. 9393 * Parameters: 9394 * _ep_ - Endpoint ID value. 9395 */ 9396 #define _BCM_OAM_EP_INDEX_VALIDATE(_ep_) \ 9397 do { \ 9398 if ((_ep_) < 0 || (_ep_) >= oc->mep_count) { \ 9399 LOG_ERROR(BSL_LS_BCM_OAM, \ 9400 (BSL_META("OAM(unit %d) Error: Invalid Endpoint ID" \ 9401 " = %d.\n"), unit, _ep_)); \ 9402 return (BCM_E_PARAM); \ 9403 } \ 9404 } while (0); 9405 9406 /* 9407 * Macro: 9408 * _BCM_FP_OAM_GROUP_INDEX_VALIDATE 9409 * Purpose: 9410 * Validate OAM Group ID value. 9411 * Parameters: 9412 * _group_ - Group ID value. 9413 */ 9414 #define _BCM_FP_OAM_GROUP_INDEX_VALIDATE(_group_) \ 9415 do { \ 9416 if ((_group_) < 0 || (_group_) >= oc->group_count) { \ 9417 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META("OAM Error: " \ 9418 "Invalid Group ID = %d.\n"), _group_)); \ 9419 return (BCM_E_PARAM); \ 9420 } \ 9421 } while (0); 9422 9423 9424 /* 9425 * Function: 9426 * _bcm_fp_oam_group_set_msg_send 9427 * Purpose: 9428 * Send Group Create/Update Message to UKERNEL 9429 * Parameters: 9430 * unit - (IN) BCM device number 9431 * ep_data - (IN) Pointer to endpoint information. 9432 * msg_flags - (IN) Msg control flags 9433 * Returns: 9434 * BCM_E_XXX 9435 */ 9436 static int 9437 _bcm_fp_oam_group_set_msg_send(int unit, _bcm_fp_oam_group_data_t *grp_p, 9438 uint32 msg_flags, uint16 *r_msg_len) 9439 { 9440 shr_ccm_msg_ctrl_group_data_t group_msg; 9441 _bcm_fp_oam_control_t *oc = NULL; 9442 uint8 *dma_buffer1 = NULL; /* DMA buffer */ 9443 uint8 *dma_buffer2 = NULL; /* DMA buffer ptr after pack */ 9444 uint16 s_msg_len = 0; /* Send Message length */ 9445 int rv = 0; 9446 9447 /* Get OAM Control Structure. */ 9448 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 9449 9450 dma_buffer1 = oc->dma_buffer; 9451 9452 /* Validate input parameter. */ 9453 if (NULL == grp_p) { 9454 return (BCM_E_INTERNAL); 9455 } 9456 9457 /* Clear meo_msg structure */ 9458 sal_memset(&group_msg, 0, sizeof(group_msg)); 9459 group_msg.flags = msg_flags; 9460 9461 /* Fill Mep data and Send MEP Create message to UKENREL */ 9462 sal_memcpy(&(group_msg.group_data), &(grp_p->group_data), 9463 sizeof(ccm_group_data_t)); 9464 9465 /* Pack Mep data to buffer */ 9466 dma_buffer1 = oc->dma_buffer; 9467 dma_buffer2 = shr_ccm_msg_ctrl_group_set_pack(dma_buffer1, &group_msg); 9468 s_msg_len = dma_buffer2 - dma_buffer1; 9469 rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM, 9470 MOS_MSG_SUBCLASS_CCM_GROUP_SET, s_msg_len, 0, 9471 MOS_MSG_SUBCLASS_CCM_GROUP_SET_REPLY, r_msg_len); 9472 if (BCM_FAILURE(rv)) { 9473 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 9474 "Group Set Msg returned error %s.\n"), bcm_errmsg(rv))); 9475 } 9476 return rv; 9477 } 9478 9479 9480 /* 9481 * Function: 9482 * bcm_fp_oam_ccm_group_create 9483 * Purpose: 9484 * Create or replace an OAM group object 9485 * Parameters: 9486 * unit - (IN) BCM device number 9487 * group_info - (IN/OUT) Pointer to an OAM group information. 9488 * Returns: 9489 * BCM_E_XXX 9490 */ 9491 int 9492 bcm_fp_oam_ccm_group_create(int unit, bcm_oam_group_info_t *group_info) 9493 { 9494 _bcm_fp_oam_control_t *oc = NULL; /* OAM control structure */ 9495 _bcm_fp_oam_group_data_t *oam_group = NULL; /* OAM Group being created */ 9496 uint32 msg_flags = 0; /* Group Msg flags */ 9497 uint16 r_len = 0; /* Received Msg length */ 9498 int rv = 0; /* return value */ 9499 9500 /* Validate input parameter. */ 9501 if (NULL == group_info) { 9502 return (BCM_E_PARAM); 9503 } 9504 9505 /* Get OAM control structure handle. */ 9506 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 9507 9508 /* Validate group id. */ 9509 if (group_info->flags & BCM_OAM_GROUP_WITH_ID) { 9510 _BCM_FP_OAM_GROUP_INDEX_VALIDATE(group_info->id); 9511 } 9512 9513 /* 9514 * If MA group create is called with replace flag bit set. 9515 * - Check and return error if a group does not exist with the ID. 9516 */ 9517 if (group_info->flags & BCM_OAM_GROUP_REPLACE) { 9518 if (group_info->flags & BCM_OAM_GROUP_WITH_ID) { 9519 9520 /* Search the list with the MA Group ID value. */ 9521 rv = shr_idxres_list_elem_state(oc->group_pool, group_info->id); 9522 if (BCM_E_EXISTS != rv) { 9523 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 9524 "OAM Error: Group does not exist.\n"))); 9525 return (BCM_E_PARAM); 9526 } 9527 } else { 9528 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 9529 "OAM Error: Replace command needs a valid Group ID.\n"))); 9530 return (BCM_E_PARAM); 9531 } 9532 } else if (group_info->flags & BCM_OAM_GROUP_WITH_ID) { 9533 /* 9534 * If MA group create is called with ID flag bit set. 9535 * - Check and return error if the ID is already in use. 9536 */ 9537 rv = shr_idxres_list_reserve(oc->group_pool, group_info->id, 9538 group_info->id); 9539 if (BCM_FAILURE(rv)) { 9540 return ((rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv); 9541 } 9542 } else { 9543 /* Reserve the next available group index. */ 9544 rv = shr_idxres_list_alloc(oc->group_pool, 9545 (shr_idxres_element_t *) &group_info->id); 9546 if (BCM_FAILURE(rv)) { 9547 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 9548 "OAM Error: Group allocation (GID=%d) %s\n"), 9549 group_info->id, bcm_errmsg(rv))); 9550 return (rv); 9551 } 9552 } 9553 9554 /* Get this group memory to store group information. */ 9555 oam_group = &(oc->group_data[group_info->id]); 9556 9557 if (!(group_info->flags & BCM_OAM_GROUP_REPLACE)) { 9558 9559 /* Store the group name. */ 9560 sal_memcpy(oam_group->group_data.name, group_info->name, 9561 BCM_OAM_GROUP_NAME_LENGTH); 9562 9563 /* Store Lowest Alarm Priority */ 9564 oam_group->group_data.lowest_alarm_priority = group_info->lowest_alarm_priority; 9565 9566 /* Initialize RMEP head to NULL.*/ 9567 sal_memset(oam_group->group_data.rmep_bitmap, 0, 9568 sizeof(oam_group->group_data.rmep_bitmap)); 9569 9570 /* Check if software RDI flag bit needs to be set in hardware. */ 9571 oam_group->group_data.flags |= 9572 ((group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) ? 9573 _FP_OAM_GROUP_SW_RDI_FLAG : 0); 9574 9575 /* Set LMEP as not configured */ 9576 oam_group->group_data.lmep_id = _FP_OAM_INVALID_LMEP_ID; 9577 9578 oam_group->group_data.group_id = group_info->id; 9579 9580 /* Send Group Create message to uKernel */ 9581 rv = _bcm_fp_oam_group_set_msg_send(unit, oam_group, msg_flags, &r_len); 9582 if (BCM_FAILURE(rv)) { 9583 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 9584 "Group create Msg failed, id:%d - %s"), group_info->id, 9585 bcm_errmsg(rv))); 9586 } else { 9587 oam_group->in_use = 1; 9588 } 9589 9590 } else { 9591 /* Only lowest alarm prio and S/w RDI bit can be replaced */ 9592 if ((oam_group->group_data.flags & _FP_OAM_GROUP_SW_RDI_FLAG) != 9593 (group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX)) { 9594 9595 if (group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) { 9596 oam_group->group_data.flags |= _FP_OAM_GROUP_SW_RDI_FLAG; 9597 } else { 9598 oam_group->group_data.flags &= ~(_FP_OAM_GROUP_SW_RDI_FLAG); 9599 } 9600 msg_flags |= _GRP_REPLACE; 9601 msg_flags |= _GRP_REPLACE_SW_RDI; 9602 } 9603 9604 if (oam_group->group_data.lowest_alarm_priority != 9605 group_info->lowest_alarm_priority) { 9606 9607 oam_group->group_data.lowest_alarm_priority = 9608 group_info->lowest_alarm_priority; 9609 msg_flags |= _GRP_REPLACE; 9610 msg_flags |= _GRP_REPLACE_LOWEST_ALARM_PRIO; 9611 } 9612 9613 /* Send Group Create message to uKernel */ 9614 rv = _bcm_fp_oam_group_set_msg_send(unit, oam_group, msg_flags, &r_len); 9615 if (BCM_FAILURE(rv)) { 9616 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 9617 "Group create Msg failed, id:%d - %s"), group_info->id, 9618 bcm_errmsg(rv))); 9619 } 9620 } 9621 9622 return rv; 9623 } 9624 9625 /* 9626 * Function: 9627 * bcm_fp_oam_ccm_group_get 9628 * Purpose: 9629 * Delete an OAM group object. All OAM endpoints associated with the 9630 * group will also be destroyed. 9631 * Parameters: 9632 * unit - (IN) BCM device number 9633 * group_info - (IN/OUT) Pointer to an OAM group Id. 9634 * Returns: 9635 * BCM_E_XXX 9636 */ 9637 int 9638 bcm_fp_oam_ccm_group_get(int unit, bcm_oam_group_info_t *group_info) { 9639 9640 _bcm_fp_oam_control_t *oc = NULL; /* OAM control structure */ 9641 _bcm_fp_oam_group_data_t *group_p; /* Handle to S/w Group Data */ 9642 int rv = 0; /* Return Value */ 9643 uint16 reply_len; 9644 uint8 *dma_buffer1 = NULL; 9645 uint8 *dma_buffer2 = NULL; 9646 shr_ccm_msg_ctrl_group_data_t group_msg; 9647 9648 /* Get OAM control structure handle. */ 9649 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 9650 9651 /* Validate Group Index */ 9652 _BCM_FP_OAM_GROUP_INDEX_VALIDATE(group_info->id); 9653 9654 /* Get Handle to Local DB */ 9655 group_p = &(oc->group_data[group_info->id]); 9656 if (!(group_p->in_use)) { 9657 return BCM_E_NOT_FOUND; 9658 } 9659 9660 rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM, 9661 MOS_MSG_SUBCLASS_CCM_GROUP_GET_FAULTS_ONLY, group_info->id, 0, 9662 MOS_MSG_SUBCLASS_CCM_GROUP_GET_REPLY, &reply_len); 9663 9664 /* UnPack control message data into DMA buffer */ 9665 dma_buffer1 = oc->dma_buffer; 9666 dma_buffer2 = shr_ccm_msg_ctrl_group_get_unpack(dma_buffer1, &group_msg); 9667 9668 if (reply_len != dma_buffer2 - dma_buffer1) { 9669 rv = BCM_E_INTERNAL; 9670 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 9671 "Group get Msg lenght check failed, id:%d.\n"), group_info->id)); 9672 return (rv); 9673 } 9674 group_info->faults = group_msg.group_data.faults; 9675 group_info->persistent_faults = group_msg.group_data.persistent_faults; 9676 9677 sal_memcpy(group_info->name, group_p->group_data.name, _FP_OAM_MAID_LEN); 9678 group_info->lowest_alarm_priority = 9679 group_p->group_data.lowest_alarm_priority; 9680 9681 if (group_p->group_data.flags & _FP_OAM_GROUP_SW_RDI_FLAG) { 9682 group_info->flags |= BCM_OAM_GROUP_REMOTE_DEFECT_TX; 9683 } 9684 9685 return rv; 9686 } 9687 9688 int 9689 _bcm_fp_oam_ccm_group_traverse(int unit, bcm_oam_group_traverse_cb cb, 9690 void *user_data) 9691 { 9692 _bcm_fp_oam_control_t *oc = NULL; /* OAM control structure pointer. */ 9693 bcm_oam_group_info_t group_info; 9694 bcm_oam_group_t grp_idx; /* MA Group index. */ 9695 int rv; /* Operation return status. */ 9696 _bcm_fp_oam_group_data_t *group_p; 9697 9698 if (NULL == cb) { 9699 return (BCM_E_PARAM); 9700 } 9701 9702 /* Get device OAM control structure handle. */ 9703 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 9704 9705 for (grp_idx = 0; grp_idx < oc->group_count; grp_idx++) { 9706 group_p = &(oc->group_data[grp_idx]); 9707 if (group_p->in_use) { 9708 group_info.id = grp_idx; 9709 rv = bcm_fp_oam_ccm_group_get(unit, &group_info); 9710 if (BCM_FAILURE(rv)) { 9711 LOG_ERROR(BSL_LS_BCM_OAM, 9712 (BSL_META_U(unit, 9713 "OAM(unit %d) Error: " 9714 "_bcm_fp_oam_ccm_group_get " 9715 "(GID=%d) - %s.\n"), unit, grp_idx, 9716 bcm_errmsg(rv))); 9717 return (rv); 9718 } 9719 /* Call the user call back routine with group information. */ 9720 rv = cb(unit, &group_info, user_data); 9721 if (BCM_FAILURE(rv)) { 9722 LOG_ERROR(BSL_LS_BCM_OAM, 9723 (BSL_META_U(unit, 9724 "OAM(unit %d) Error: User call back " 9725 "routine (GID=%d) - %s.\n"), unit, 9726 grp_idx, bcm_errmsg(rv))); 9727 return (rv); 9728 } 9729 } 9730 } 9731 return BCM_E_NONE; 9732 } 9733 9734 /* 9735 * Function: 9736 * bcm_fp_oam_ccm_group_destroy 9737 * Purpose: 9738 * Delete an OAM group object. All OAM endpoints associated with the 9739 * group will also be destroyed. 9740 * Parameters: 9741 * unit - (IN) BCM device number 9742 * group_info - (IN/OUT) Pointer to an OAM group Id. 9743 * Returns: 9744 * BCM_E_XXX 9745 */ 9746 int 9747 bcm_fp_oam_ccm_group_destroy(int unit, bcm_oam_group_t group_id) 9748 { 9749 _bcm_fp_oam_control_t *oc = NULL; /* OAM control structure */ 9750 _bcm_fp_oam_group_data_t *group_p; /* Handle to S/w Group Data */ 9751 int rv = 0; /* Return Value */ 9752 uint16 r_len; /* Msg reply lenght */ 9753 int i = 0; 9754 9755 /* Get OAM control structure handle. */ 9756 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 9757 9758 /* Validate Group Index */ 9759 _BCM_FP_OAM_GROUP_INDEX_VALIDATE(group_id); 9760 9761 /* Get Handle to Local DB */ 9762 group_p = &(oc->group_data[group_id]); 9763 if (!(group_p->in_use)) { 9764 return BCM_E_NOT_FOUND; 9765 } 9766 9767 rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM, 9768 MOS_MSG_SUBCLASS_CCM_GROUP_DELETE, group_id, 0, 9769 MOS_MSG_SUBCLASS_CCM_GROUP_DELETE_REPLY, &r_len); 9770 9771 if (BCM_FAILURE(rv)) { 9772 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 9773 "Group Del Msg returned error %s.\n"), bcm_errmsg(rv))); 9774 rv = BCM_E_INTERNAL; 9775 return rv; 9776 } 9777 9778 /* Clean up Local db, including LMEPs and RMEPs */ 9779 if (group_p->group_data.lmep_id != _FP_OAM_INVALID_LMEP_ID) { 9780 sal_memset(&(oc->mep_data[group_p->group_data.lmep_id]), 0, 9781 sizeof(_bcm_fp_oam_mep_data_t)); 9782 9783 /* Free the LMEP index */ 9784 rv = shr_idxres_list_free(oc->mep_pool, group_p->group_data.lmep_id); 9785 if (BCM_FAILURE(rv)) { 9786 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 9787 "LMEP index Free failed EP:%d %s.\n"), 9788 group_p->group_data.lmep_id, bcm_errmsg(rv))); 9789 return (rv); 9790 } 9791 } 9792 9793 for (i=0; i<_CCM_MEP_COUNT; i++) { 9794 if (_GET_BIT_FLD(group_p->group_data.rmep_bitmap, i) ) { 9795 sal_memset(&(oc->mep_data[i]), 0, sizeof(_bcm_fp_oam_mep_data_t)); 9796 9797 /* Free the RMEP index */ 9798 rv = shr_idxres_list_free(oc->mep_pool, i); 9799 if (BCM_FAILURE(rv)) { 9800 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 9801 "RMEP index Free failed EP:%d %s.\n"), i, 9802 bcm_errmsg(rv))); 9803 return (rv); 9804 } 9805 } 9806 } 9807 9808 /* Free the Group index */ 9809 rv = shr_idxres_list_free(oc->group_pool, group_id); 9810 9811 if (BCM_FAILURE(rv)) { 9812 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 9813 "Group index Free failed EP:%d %s.\n"), group_id, 9814 bcm_errmsg(rv))); 9815 return (rv); 9816 } 9817 9818 sal_memset(group_p, 0, sizeof(_bcm_fp_oam_group_data_t)); 9819 group_p->group_data.lmep_id = _FP_OAM_INVALID_LMEP_ID; 9820 9821 return rv; 9822 } 9823 9824 9825 /* 9826 * Function: 9827 * _bcm_fp_oam_ep_hash_key_construct 9828 * Purpose: 9829 * Construct hash table key for a given endpoint information. 9830 * Parameters: 9831 * unit - (IN) BCM device number 9832 * oc - (IN) Pointer to OAM control structure. 9833 * ep_info - (IN) Pointer to endpoint information structure. 9834 * key - (IN/OUT) Pointer to hash key buffer. 9835 * Retruns: 9836 * None 9837 */ 9838 STATIC void 9839 _bcm_fp_oam_ep_hash_key_construct(int unit, _bcm_fp_oam_control_t *oc, 9840 bcm_oam_endpoint_info_t *ep_info, _bcm_fp_oam_hash_key_t *key) 9841 { 9842 uint8 *loc = *key; 9843 uint8 direction = 0; 9844 uint8 isLocal = 1; 9845 9846 sal_memset(key, 0, sizeof(_bcm_fp_oam_hash_key_t)); 9847 9848 if (NULL != ep_info) { 9849 9850 if (ep_info->flags & BCM_OAM_ENDPOINT_UP_FACING) { 9851 direction = 1; 9852 } 9853 if (ep_info->flags & BCM_OAM_ENDPOINT_REMOTE) { 9854 isLocal = 0; 9855 } 9856 _BCM_OAM_KEY_PACK(loc, &direction, sizeof(direction)); 9857 _BCM_OAM_KEY_PACK(loc, &isLocal, sizeof(isLocal)); 9858 _BCM_OAM_KEY_PACK(loc, &ep_info->group, sizeof(ep_info->group)); 9859 _BCM_OAM_KEY_PACK(loc, &ep_info->name, sizeof(ep_info->name)); 9860 _BCM_OAM_KEY_PACK(loc, &ep_info->gport, sizeof(ep_info->gport)); 9861 _BCM_OAM_KEY_PACK(loc, &ep_info->level, sizeof(ep_info->level)); 9862 _BCM_OAM_KEY_PACK(loc, &ep_info->vlan, sizeof(ep_info->vlan)); 9863 _BCM_OAM_KEY_PACK(loc, &ep_info->inner_vlan, 9864 sizeof(ep_info->inner_vlan)); 9865 } 9866 9867 /* End address should not exceed size of _bcm_oam_hash_key_t. */ 9868 assert ((int) (loc - *key) <= sizeof(_bcm_oam_hash_key_t)); 9869 } 9870 9871 9872 /* 9873 * Function: 9874 * _bcm_fp_oam_endpoint_params_validate 9875 * Purpose: 9876 * Validate an endpoint parameters. 9877 * Parameters: 9878 * unit - (IN) BCM device number 9879 * oc - (IN) Pointer to OAM control structure. 9880 * hash_key - (IN) Pointer to endpoint hash key value. 9881 * ep_info_p - (IN) Pointer to endpoint information. 9882 * Retruns: 9883 * BCM_E_XXX 9884 */ 9885 STATIC int 9886 _bcm_fp_oam_endpoint_params_validate(int unit, _bcm_fp_oam_control_t *oc, 9887 _bcm_fp_oam_hash_key_t *hash_key, bcm_oam_endpoint_info_t *ep_info_p) 9888 { 9889 int rv = 0; 9890 _bcm_fp_oam_group_data_t *group_p = NULL; 9891 9892 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Info: " 9893 "_bcm_fp_oam_endpoint_params_validate.\n"))); 9894 9895 /* Endpoint must be 802.1ag/Ethernet OAM type. */ 9896 if ((bcmOAMEndpointTypeEthernet != ep_info_p->type)) 9897 { 9898 /* Other OAM types are not supported, return error. */ 9899 return BCM_E_UNAVAIL; 9900 } 9901 9902 /* Supported MDL level is 0 - 7. */ 9903 if ((ep_info_p->level < 0) || (ep_info_p->level > _FP_OAM_MAX_MDL)) { 9904 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 9905 "EP Level should be in the range(0-%d).\n"), _FP_OAM_MAX_MDL )); 9906 return (BCM_E_PARAM); 9907 } 9908 9909 /* Supported MEPID Name range is 1 - 8191, Skipping range check for MIP and MPLS LM/DM */ 9910 if (((ep_info_p->name < _FP_OAM_EP_NAME_MIN) 9911 || (ep_info_p->name > _FP_OAM_EP_NAME_MAX)) && 9912 !(ep_info_p->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) 9913 #if defined(INCLUDE_MPLS_LM_DM) 9914 && (!_MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p->type))) { 9915 #else 9916 ) { 9917 #endif 9918 LOG_ERROR(BSL_LS_BCM_OAM, 9919 (BSL_META_U(unit, 9920 "OAM Error: MEP Name should be in the range(%d-%d).\n"), 9921 _FP_OAM_EP_NAME_MIN, _FP_OAM_EP_NAME_MAX)); 9922 return (BCM_E_PARAM); 9923 } 9924 9925 /* For replace operation, endpoint ID is required. */ 9926 if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE) 9927 && !(ep_info_p->flags & BCM_OAM_ENDPOINT_WITH_ID)) { 9928 9929 return (BCM_E_PARAM); 9930 } 9931 9932 /* If it is a Port + CVlan based MEP or Section Port + CVlan 9933 * based MEP and the CVlan (inner_vlan) is 0, return E_PARAM 9934 */ 9935 if ((0 == ep_info_p->inner_vlan) && 9936 (ep_info_p->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN)) { 9937 return (BCM_E_PARAM); 9938 } 9939 9940 /* If it is a Port + S + CVlan based MEP or Section Port + S + CVlan 9941 * based MEP and one of SVlan(vlan) or CVlan (inner_vlan) is 0, 9942 * return E_PARAM 9943 */ 9944 if (((0 == ep_info_p->inner_vlan) || (0 == ep_info_p->vlan)) && 9945 ((ep_info_p->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN))) { 9946 return (BCM_E_PARAM); 9947 } 9948 9949 /* Validate endpoint index value. */ 9950 if (ep_info_p->flags & BCM_OAM_ENDPOINT_WITH_ID) { 9951 _BCM_OAM_EP_INDEX_VALIDATE(ep_info_p->id); 9952 } 9953 9954 /* MIP's are not created with non-zero ccm period */ 9955 if ((ep_info_p->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) && 9956 (ep_info_p->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED)) { 9957 return (BCM_E_PARAM); 9958 } 9959 9960 /* Validate endpoint group id. */ 9961 _BCM_FP_OAM_GROUP_INDEX_VALIDATE(ep_info_p->group); 9962 9963 rv = shr_idxres_list_elem_state(oc->group_pool, ep_info_p->group); 9964 if (BCM_E_EXISTS != rv) { 9965 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 9966 "Group (GID:%d) does not exist.\n"), ep_info_p->group)); 9967 return (BCM_E_PARAM); 9968 } 9969 9970 /* Only One LMEP should be configured per group */ 9971 group_p = &(oc->group_data[ep_info_p->group]); 9972 if (!(ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE)) { 9973 9974 if ((group_p->group_data.lmep_id != _FP_OAM_INVALID_LMEP_ID) && 9975 !(ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE)) { 9976 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 9977 "LMEP already existst for the group\n"))); 9978 return (rv); 9979 } 9980 } 9981 9982 #if 0 9983 9984 rv = shr_htb_find(oc->ma_mep_htbl, *hash_key, 9985 (shr_htb_data_t *)&h_stored_data, 0); 9986 9987 if (BCM_SUCCESS(rv) && !(ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE)) { 9988 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: %s\n"), 9989 bcm_errmsg(BCM_E_EXISTS))); 9990 9991 /* Endpoint must not be in use except for Replace operation. */ 9992 return (BCM_E_EXISTS); 9993 } else { 9994 /* Cannot replace any Key params for an endpoint */ 9995 if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE) && !(BCM_SUCCESS(rv))) { 9996 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: Endpoint " 9997 "ID=%d, invalid params for replace operation or Endpoint " 9998 "doesn't exists\n"), ep_info_p->id)); 9999 } 10000 } 10001 #endif 10002 return (BCM_E_NONE); 10003 } 10004 10005 10006 /* 10007 * Function: 10008 * _bcm_fp_oam_get_ctr_info_from_stat_id 10009 * Purpose: 10010 * Get OLP Formatted Counter Id from Stat Id 10011 * Parameters: 10012 * unit - (IN) BCM device number 10013 * stat_id - (IN) Stat group Id. 10014 * offset - (IN) Offset from Base 10015 * counter_id - (OUT) OLP Formatted counter value 10016 * Returns: 10017 * void 10018 */ 10019 STATIC void 10020 _bcm_fp_oam_get_ctr_info_from_stat_id(int unit, uint32 stat_id, uint8 offset, 10021 uint32 *counter_id) 10022 { 10023 bcm_stat_group_mode_t stat_group; 10024 bcm_stat_object_t stat_object; 10025 uint32 stat_mode; 10026 uint32 stat_pool_number; 10027 uint32 stat_base_idx; 10028 10029 _bcm_esw_stat_get_counter_id_info(unit, stat_id, 10030 &stat_group, &stat_object, &stat_mode, &stat_pool_number, &stat_base_idx); 10031 10032 *counter_id = ( ((stat_base_idx & _FP_OAM_OLP_CTR_WIDTH) + offset) | 10033 ((stat_pool_number & _FP_OAM_OLP_CTR_POOL_WIDTH) << 10034 _FP_OAM_OLP_CTR_WIDTH) ); 10035 10036 } 10037 10038 10039 /* 10040 * Function: 10041 * _bcm_fp_oam_olp_header_pack 10042 * Purpose: 10043 * Pack OLP Header into buffer. 10044 * Parameters: 10045 * buffer - (IN/OUT) Buffer to Pack OLP Header 10046 * mep_data - (IN) Pointer to MEP data. 10047 * Retruns: 10048 * BCM_E_XX 10049 */ 10050 STATIC int 10051 _bcm_fp_oam_olp_header_pack(int unit, uint8 *buffer, ccm_mep_data_t *mep_data) 10052 { 10053 10054 soc_olp_l2_hdr_t olp_l2_hdr; 10055 soc_olp_tx_hdr_t olp_oam_header; 10056 int rv = BCM_E_NONE; 10057 uint32 counter_id; 10058 bcm_module_t my_modid = 0; 10059 bcm_gport_t cpu_dglp; 10060 10061 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 10062 BCM_IF_ERROR_RETURN(_bcm_esw_glp_construct(unit, BCM_TRUNK_INVALID, my_modid, 10063 CMIC_PORT(unit), &cpu_dglp)); 10064 /* Get OLP L2 Header for CPU port */ 10065 sal_memset(&olp_l2_hdr, 0, sizeof(olp_l2_hdr)); 10066 rv = _bcm_olp_l2_hdr_get(unit, cpu_dglp, 0, &olp_l2_hdr); 10067 if (BCM_FAILURE(rv)) { 10068 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 10069 "OLP Header get failed.\n"))); 10070 return (rv); 10071 } 10072 10073 /* OLP OAM Header */ 10074 sal_memset(&olp_oam_header, 0, sizeof(olp_oam_header)); 10075 /* Set Port number */ 10076 SOC_OLP_TX_PORT(&olp_oam_header) = 10077 _BCM_OAM_GLP_PORT_GET(mep_data->dglp); 10078 SOC_OLP_TX_MODID(&olp_oam_header) = 10079 _BCM_OAM_GLP_MODULE_ID_GET(mep_data->dglp); 10080 10081 if (mep_data->flags & _FP_OAM_DIRECTION_UP) { 10082 SOC_OLP_TX_HDR_STYPE_GET(&olp_oam_header) = 1; 10083 } 10084 10085 if (0 < mep_data->num_ctrs) { 10086 _bcm_fp_oam_get_ctr_info_from_stat_id(unit, mep_data->flex_stat_id[0], 10087 mep_data->counter_offset[0], &counter_id); 10088 SOC_OLP_TX_CTR1_ID(&olp_oam_header) = counter_id; 10089 SOC_OLP_TX_CTR1_LOCATION(&olp_oam_header) = _FP_OAM_OLP_CTR_LOC_EP; 10090 SOC_OLP_TX_CTR1_ACTION(&olp_oam_header) = _FP_OAM_OLP_CTR_ACTN_INC; 10091 } 10092 if (1 < mep_data->num_ctrs) { 10093 _bcm_fp_oam_get_ctr_info_from_stat_id(unit, mep_data->flex_stat_id[1], 10094 mep_data->counter_offset[1], &counter_id); 10095 SOC_OLP_TX_CTR2_ID_SET(&olp_oam_header, counter_id); 10096 SOC_OLP_TX_CTR2_LOCATION(&olp_oam_header) = _FP_OAM_OLP_CTR_LOC_EP; 10097 SOC_OLP_TX_CTR2_ACTION(&olp_oam_header) = _FP_OAM_OLP_CTR_ACTN_INC; 10098 } 10099 10100 /* Now that we have both L2 and OAM OLP Headers, pack them */ 10101 buffer = _bcm_fp_oam_olp_l2_header_pack(buffer, &olp_l2_hdr); 10102 buffer = shr_olp_tx_header_pack(buffer, &olp_oam_header); 10103 10104 return (rv); 10105 } 10106 10107 10108 /* 10109 * Function: 10110 * _bcm_fp_oam_l2_encap_pack 10111 * Purpose: 10112 * Pack OLP Header into buffer. 10113 * Parameters: 10114 * buffer - (IN/OUT) Buffer to Pack L2 Encap 10115 * mep_data - (IN) Pointer to MEP data. 10116 * Retruns: 10117 * BCM_E_XX 10118 */ 10119 STATIC uint8* 10120 _bcm_fp_oam_l2_encap_pack(int unit, uint8 *buffer, ccm_mep_data_t *mep_data) 10121 { 10122 uint32 vlan_tag = 0; 10123 uint16 cfm_ether_type = _CCM_ETHER_TYPE; 10124 int i; 10125 /* Pack DA */ 10126 for (i=0; i<6; i++) { 10127 _SHR_PACK_U8(buffer, mep_data->da[i]); 10128 } 10129 /* Pack SA */ 10130 for (i=0; i<6; i++) { 10131 _SHR_PACK_U8(buffer, mep_data->sa[i]); 10132 } 10133 /* Pack Outer vlan */ 10134 if (mep_data->vlan) { 10135 vlan_tag = 0; 10136 vlan_tag = (mep_data->tpid << 16) | 10137 ((mep_data->pkt_pri & 0x7) << 13) | 10138 (mep_data->vlan & 0x0FFF); 10139 _SHR_PACK_U32(buffer, vlan_tag); 10140 } 10141 /* Pack Inner vlan */ 10142 if (mep_data->inner_vlan) { 10143 vlan_tag = 0; 10144 vlan_tag = (mep_data->inner_tpid << 16) | 10145 ((mep_data->inner_vlan_pri & 0x7) << 13) | 10146 (mep_data->inner_vlan & 0x0FFF); 10147 _SHR_PACK_U32(buffer, vlan_tag); 10148 } 10149 /* Pack EtherType */ 10150 _SHR_PACK_U16(buffer, cfm_ether_type); 10151 return buffer; 10152 } 10153 10154 10155 /* 10156 * Function: 10157 * _bcm_fp_oam_mep_set_msg_send 10158 * Purpose: 10159 * Send Mep Create/Update Message to UKERNEL 10160 * Parameters: 10161 * unit - (IN) BCM device number 10162 * ep_data - (IN) Pointer to endpoint information. 10163 * uint32 - (IN) Msg Control flags 10164 * Returns: 10165 * BCM_E_XXX 10166 */ 10167 static int 10168 _bcm_fp_oam_mep_set_msg_send(int unit, _bcm_fp_oam_mep_data_t *ep_data, 10169 uint32 msg_flags, uint16 *r_msg_len) 10170 { 10171 shr_ccm_msg_ctrl_mep_data_t mep_msg; 10172 _bcm_fp_oam_control_t *oc = NULL; 10173 uint8 *dma_buffer1 = NULL; /* DMA buffer */ 10174 uint8 *dma_buffer2 = NULL; /* DMA buffer ptr after pack */ 10175 uint16 s_msg_len = 0; /* Send Message length */ 10176 int rv = 0; 10177 10178 /* Get OAM Control Structure. */ 10179 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 10180 10181 dma_buffer1 = oc->dma_buffer; 10182 10183 /* Validate input parameter. */ 10184 if (NULL == ep_data) { 10185 return (BCM_E_INTERNAL); 10186 } 10187 10188 /* Clear mep_msg structure */ 10189 sal_memset(&mep_msg, 0, sizeof(mep_msg)); 10190 mep_msg.flags = msg_flags; 10191 10192 if (msg_flags & _MEP_L2_ENCAP_RECREATE) { 10193 dma_buffer1 = _bcm_fp_oam_l2_encap_pack(unit, mep_msg.L2_encap, 10194 &(ep_data->mep_data)); 10195 mep_msg.l2_encap_len = dma_buffer1 - mep_msg.L2_encap; 10196 } 10197 10198 if (msg_flags & _MEP_OLP_RECREATE) { 10199 rv = _bcm_fp_oam_olp_header_pack(unit, mep_msg.OLP_Tx_Hdr, 10200 &(ep_data->mep_data)); 10201 if (BCM_FAILURE(rv)) { 10202 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 10203 "OLP Header Pack failed.\n"))); 10204 return (rv); 10205 } 10206 } 10207 10208 /* Fill Mep data and Send MEP Create message to UKENREL */ 10209 sal_memcpy(&(mep_msg.mep_data), &(ep_data->mep_data), 10210 sizeof(ccm_mep_data_t)); 10211 10212 /* Pack Mep data to buffer */ 10213 dma_buffer1 = oc->dma_buffer; 10214 dma_buffer2 = shr_ccm_msg_ctrl_mep_set_pack(dma_buffer1, &mep_msg); 10215 s_msg_len = dma_buffer2 - dma_buffer1; 10216 rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM, 10217 MOS_MSG_SUBCLASS_CCM_MEP_SET, s_msg_len, 0, 10218 MOS_MSG_SUBCLASS_CCM_MEP_SET_REPLY, r_msg_len); 10219 10220 if (BCM_FAILURE(rv)) { 10221 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 10222 "MEP Create Msg returned error %s.\n"), bcm_errmsg(rv))); 10223 rv = BCM_E_INTERNAL; 10224 } 10225 return (rv); 10226 } 10227 10228 10229 /* 10230 * Function: 10231 * bcm_fp_oam_ccm_endpoint_create 10232 * Purpose: 10233 * Create or replace a CCM OAM endpoint object 10234 * Parameters: 10235 * unit - (IN) BCM device number 10236 * endpoint_info - (IN/OUT) Pointer to endpoint information buffer. 10237 * Returns: 10238 * BCM_E_XXX 10239 */ 10240 int 10241 bcm_fp_oam_ccm_endpoint_create(int unit, bcm_oam_endpoint_info_t *endpoint_info) 10242 { 10243 _bcm_fp_oam_control_t *oc = NULL; 10244 _bcm_fp_oam_hash_key_t hash_key; 10245 _bcm_fp_oam_mep_data_t *ep_data; 10246 uint32 mep_index; 10247 int src_glp; 10248 int dst_glp; 10249 bcm_gport_t dgpp; 10250 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 10251 ccm_group_data_t *grp_data_ptr = NULL; 10252 uint32 msg_flags = 0; 10253 uint16 r_len = 0; /* Msg response lenght */ 10254 int rv = 0; 10255 bcm_trunk_member_t trunk_member; 10256 int i; 10257 10258 /* Validate input parameter. */ 10259 if (NULL == endpoint_info) { 10260 return (BCM_E_PARAM); 10261 } 10262 /* Get OAM Control Structure. */ 10263 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 10264 10265 /* Calculate the hash key for given enpoint input parameters. */ 10266 _bcm_fp_oam_ep_hash_key_construct(unit, oc, endpoint_info, &hash_key); 10267 10268 /* Validate endpoint input parameters. */ 10269 rv = _bcm_fp_oam_endpoint_params_validate(unit, oc, &hash_key, 10270 endpoint_info); 10271 if (BCM_FAILURE(rv)) { 10272 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: Parameter " 10273 "Validation failed %s.\n"), bcm_errmsg(rv))); 10274 return (rv); 10275 } 10276 10277 rv = _bcm_fp_oam_endpoint_gport_resolve(unit, endpoint_info, 10278 &src_glp, &dst_glp, &dgpp, 10279 &trunk_id, &trunk_member); 10280 if (BCM_FAILURE(rv)) { 10281 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: Gport Resolve " 10282 "Failed %s.\n"), bcm_errmsg(rv))); 10283 return (rv); 10284 } 10285 10286 /* Now that EP passed all the validation checks, create the endpoint */ 10287 if (!(endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE)) { 10288 10289 if (trunk_id != BCM_TRUNK_INVALID) { 10290 rv = _bcm_fp_oam_trunk_ports_update_trunk_id(unit, trunk_id); 10291 if (BCM_FAILURE(rv)) { 10292 /* Dont return just for this error */ 10293 LOG_WARN(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 10294 "Trunk map update failed EP:%d %s.\n"), endpoint_info->id, 10295 bcm_errmsg(rv))); 10296 } 10297 } 10298 10299 if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) { 10300 /* Reserve the Id passed by the user */ 10301 mep_index = endpoint_info->id; 10302 rv = shr_idxres_list_reserve(oc->mep_pool, mep_index, mep_index); 10303 10304 } else { 10305 /* Allocate the next Id from the pool */ 10306 rv = shr_idxres_list_alloc(oc->mep_pool, 10307 (shr_idxres_element_t *)&mep_index); 10308 endpoint_info->id = mep_index; 10309 } 10310 10311 if (BCM_FAILURE(rv)) { 10312 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 10313 "MEP index alloc failed EP:%d %s.\n"), endpoint_info->id, 10314 bcm_errmsg(rv))); 10315 return (rv); 10316 } 10317 10318 /* Shift to specific data element in the array */ 10319 ep_data = &(oc->mep_data[mep_index]); 10320 10321 /* If it is a Port + S + CVlan based MEP */ 10322 if (endpoint_info->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) { 10323 ep_data->mep_data.type = _FP_OAM_MEP_TYPE_S_C_VLAN; 10324 10325 } else { 10326 10327 /* If it is a Port + CVlan based MEP */ 10328 if (endpoint_info->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) { 10329 ep_data->mep_data.type = _FP_OAM_MEP_TYPE_CVLAN; 10330 10331 } else { 10332 10333 /* If it is a Port + SVlan based MEP */ 10334 if (endpoint_info->vlan) { 10335 ep_data->mep_data.type = _FP_OAM_MEP_TYPE_SVLAN; 10336 10337 } else { 10338 /* If it is a Port based MEP */ 10339 ep_data->mep_data.type = _FP_OAM_MEP_TYPE_PORT; 10340 } 10341 } 10342 } 10343 10344 ep_data->mep_data.ep_id = mep_index; 10345 ep_data->mep_data.level = endpoint_info->level; 10346 ep_data->mep_data.period = endpoint_info->ccm_period; 10347 ep_data->mep_data.name = endpoint_info->name; 10348 10349 ep_data->mep_data.gport = endpoint_info->gport; 10350 ep_data->mep_data.dglp = dst_glp; 10351 ep_data->mep_data.sglp = src_glp; 10352 ep_data->mep_data.trunk_index = endpoint_info->trunk_index; 10353 10354 ep_data->mep_data.group_id = endpoint_info->group; 10355 10356 ep_data->mep_data.vlan = endpoint_info->vlan; 10357 ep_data->mep_data.pkt_pri = endpoint_info->pkt_pri; 10358 ep_data->mep_data.tpid = endpoint_info->outer_tpid; 10359 10360 ep_data->mep_data.inner_vlan = endpoint_info->inner_vlan; 10361 ep_data->mep_data.inner_vlan_pri = endpoint_info->inner_pkt_pri; 10362 ep_data->mep_data.inner_tpid = endpoint_info->inner_tpid; 10363 10364 sal_memcpy(ep_data->mep_data.da, endpoint_info->dst_mac_address, 10365 sizeof(bcm_mac_t)); 10366 sal_memcpy(ep_data->mep_data.sa, endpoint_info->src_mac_address, 10367 sizeof(bcm_mac_t)); 10368 10369 grp_data_ptr = &(oc->group_data[endpoint_info->group].group_data); 10370 if (!(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE)) { 10371 if (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_TX) { 10372 ep_data->mep_data.flags |= _FP_OAM_INTERFACE_STATUS_TX; 10373 ep_data->mep_data.intf_state = endpoint_info->interface_state; 10374 } 10375 10376 if (endpoint_info->flags & BCM_OAM_ENDPOINT_PORT_STATE_TX) { 10377 ep_data->mep_data.flags |= _FP_OAM_PORT_STATUS_TX; 10378 ep_data->mep_data.port_state = endpoint_info->port_state; 10379 } 10380 10381 10382 10383 if (endpoint_info->ccm_tx_update_lm_counter_size != 0) { 10384 ep_data->mep_data.num_ctrs = 10385 endpoint_info->ccm_tx_update_lm_counter_size; 10386 for (i=0; i<ep_data->mep_data.num_ctrs; i++) { 10387 ep_data->mep_data.flex_stat_id[i] = 10388 endpoint_info->ccm_tx_update_lm_counter_base_id[i]; 10389 ep_data->mep_data.counter_offset[i] = 10390 endpoint_info->ccm_tx_update_lm_counter_offset[i]; 10391 } 10392 } 10393 10394 /* Set LMEP ID in group */ 10395 grp_data_ptr->lmep_id = mep_index; 10396 msg_flags |= _MEP_OLP_RECREATE; 10397 msg_flags |= (_MEP_L2_ENCAP_RECREATE); 10398 } else { 10399 ep_data->mep_data.flags |= _FP_OAM_REMOTE_MEP; 10400 /* RMEP ID in the group */ 10401 _SET_BIT_FLD(grp_data_ptr->rmep_bitmap, mep_index); 10402 } 10403 10404 if (endpoint_info->flags & BCM_OAM_ENDPOINT_UP_FACING) { 10405 ep_data->mep_data.flags |= _FP_OAM_DIRECTION_UP; 10406 } 10407 10408 10409 /* Send MEP Create Message to UKERNEL */ 10410 rv = _bcm_fp_oam_mep_set_msg_send(unit, ep_data, msg_flags, &r_len); 10411 10412 if (BCM_FAILURE(rv)) { 10413 10414 /* Free the allocated MEP index */ 10415 shr_idxres_list_free(oc->mep_pool, mep_index); 10416 10417 /* Clear LMEP ID in Group */ 10418 if (!(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE)) { 10419 grp_data_ptr->lmep_id = _FP_OAM_INVALID_LMEP_ID; 10420 } 10421 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 10422 "MEP Creation failed EP:%d %s.\n"), endpoint_info->id, 10423 bcm_errmsg(rv))); 10424 return (rv); 10425 10426 } else { 10427 ep_data->in_use = 1; 10428 } 10429 10430 } else { 10431 /* Update case */ 10432 ep_data = &(oc->mep_data[endpoint_info->id]); 10433 10434 /* For Remote MEP, can't replace anything */ 10435 if (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) { 10436 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 10437 "Cannot replace any parameter in RMEP.\n"))); 10438 return BCM_E_PARAM; 10439 } 10440 10441 /* For local MEP, can replace only Intf status, Port status, trunk index 10442 counter indices */ 10443 if (((ep_data->mep_data.flags & _FP_OAM_INTERFACE_STATUS_TX) != 10444 (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_TX)) || 10445 (ep_data->mep_data.intf_state != endpoint_info->interface_state)) { 10446 10447 if (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_TX) { 10448 10449 ep_data->mep_data.flags |= _FP_OAM_INTERFACE_STATUS_TX; 10450 ep_data->mep_data.intf_state = endpoint_info->interface_state; 10451 } else { 10452 ep_data->mep_data.flags &= ~(_FP_OAM_INTERFACE_STATUS_TX); 10453 ep_data->mep_data.intf_state = 0; 10454 } 10455 /* Something valid was found to be replaced */ 10456 msg_flags |= _MEP_REPLACE; 10457 msg_flags |= _REPLACE_INTF_STATUS; 10458 10459 } 10460 10461 if (((ep_data->mep_data.flags & _FP_OAM_PORT_STATUS_TX) != 10462 (endpoint_info->flags & BCM_OAM_ENDPOINT_PORT_STATE_TX)) || 10463 (ep_data->mep_data.port_state != endpoint_info->port_state)) { 10464 10465 if (endpoint_info->flags & BCM_OAM_ENDPOINT_PORT_STATE_TX) { 10466 ep_data->mep_data.flags |= _FP_OAM_PORT_STATUS_TX; 10467 ep_data->mep_data.port_state = endpoint_info->port_state; 10468 } else { 10469 ep_data->mep_data.flags &= ~(_FP_OAM_PORT_STATUS_TX); 10470 ep_data->mep_data.port_state = 0; 10471 } 10472 /* Something valid was found to be replaced */ 10473 msg_flags |= _MEP_REPLACE; 10474 msg_flags |= _REPLACE_PORT_STATUS; 10475 } 10476 10477 if (ep_data->mep_data.trunk_index != endpoint_info->trunk_index) { 10478 ep_data->mep_data.trunk_index = endpoint_info->trunk_index; 10479 ep_data->mep_data.dglp = dst_glp; 10480 10481 msg_flags |= (_MEP_REPLACE | _MEP_OLP_RECREATE); 10482 msg_flags |= _REPLACE_TRUNK_INDEX; 10483 } 10484 10485 if (endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_UPDATE_COUNTER_ACTION) { 10486 if (endpoint_info->ccm_tx_update_lm_counter_size != 0) { 10487 ep_data->mep_data.num_ctrs = 10488 endpoint_info->ccm_tx_update_lm_counter_size; 10489 for (i=0; i<ep_data->mep_data.num_ctrs; i++) { 10490 ep_data->mep_data.flex_stat_id[i] = 10491 endpoint_info->ccm_tx_update_lm_counter_base_id[i]; 10492 ep_data->mep_data.counter_offset[i] = 10493 endpoint_info->ccm_tx_update_lm_counter_offset[i]; 10494 } 10495 } 10496 msg_flags |= (_MEP_REPLACE | _MEP_OLP_RECREATE); 10497 msg_flags |= _REPLACE_CTRS; 10498 } 10499 10500 if (!(msg_flags & _MEP_REPLACE)) { 10501 /* Nothing valid was found to be updated */ 10502 rv = BCM_E_PARAM; 10503 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 10504 "Nothing valid to update:%d %s.\n"), endpoint_info->id, 10505 bcm_errmsg(rv))); 10506 return (rv); 10507 } 10508 10509 /* Send MEP Update message to UKERNEL */ 10510 rv = _bcm_fp_oam_mep_set_msg_send(unit, ep_data, msg_flags, &r_len); 10511 10512 if (BCM_FAILURE(rv)) { 10513 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 10514 "MEP Update failed EP:%d %s.\n"), endpoint_info->id, 10515 bcm_errmsg(rv))); 10516 return (rv); 10517 } 10518 } 10519 10520 return rv; 10521 10522 } 10523 10524 10525 /*, 10526 * Function: 10527 * bcm_fp_oam_ccm_endpoint_get 10528 * Purpose: 10529 * Create or replace an OAM endpoint object 10530 * Parameters: 10531 * unit - (IN) BCM device number 10532 * endpoint_info - (IN/OUT) Pointer to endpoint information buffer. 10533 * Returns: 10534 * BCM_E_XXX 10535 */ 10536 int 10537 bcm_fp_oam_ccm_endpoint_get(int unit, bcm_oam_endpoint_info_t *ep_info_p) { 10538 10539 _bcm_fp_oam_control_t *oc = NULL; 10540 _bcm_fp_oam_mep_data_t *ep_data; 10541 uint16 r_len = 0; /* Msg response lenght */ 10542 uint8 *dma_buffer1 = NULL; 10543 uint8 *dma_buffer2 = NULL; 10544 shr_ccm_msg_ctrl_mep_data_t mep_msg; 10545 int rv = 0; 10546 10547 /* Validate input parameter. */ 10548 if (NULL == ep_info_p) { 10549 return (BCM_E_PARAM); 10550 } 10551 /* Get OAM Control Structure. */ 10552 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 10553 10554 /* Validate EP Index */ 10555 _BCM_OAM_EP_INDEX_VALIDATE(ep_info_p->id); 10556 10557 /* Get pointer to S/w MEP data */ 10558 ep_data = &(oc->mep_data[ep_info_p->id]); 10559 10560 if (!(ep_data->in_use)) { 10561 return BCM_E_NOT_FOUND; 10562 } 10563 10564 rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM, 10565 MOS_MSG_SUBCLASS_CCM_MEP_GET_FAULTS_ONLY, ep_info_p->id, 0, 10566 MOS_MSG_SUBCLASS_CCM_MEP_GET_REPLY, &r_len); 10567 10568 if (BCM_FAILURE(rv)) { 10569 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 10570 "MEP Update failed EP:%d %s.\n"), ep_info_p->id, 10571 bcm_errmsg(rv))); 10572 return (rv); 10573 } 10574 sal_memset(&mep_msg, 0, sizeof(shr_ccm_msg_ctrl_mep_data_t)); 10575 dma_buffer1 = oc->dma_buffer; 10576 dma_buffer2 = shr_ccm_msg_ctrl_mep_get_unpack(dma_buffer1, &mep_msg); 10577 10578 if (r_len != dma_buffer2 - dma_buffer1) { 10579 rv = BCM_E_INTERNAL; 10580 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 10581 "Mep get Msg lenght check failed, id:%d.\n"), ep_info_p->id)); 10582 return (rv); 10583 } 10584 ep_info_p->faults = mep_msg.mep_data.faults; 10585 ep_info_p->persistent_faults = mep_msg.mep_data.persistent_faults; 10586 10587 /* Fill rest of data from local db */ 10588 ep_info_p->type = bcmOAMEndpointTypeEthernet; 10589 ep_info_p->group = ep_data->mep_data.group_id; 10590 ep_info_p->ccm_period = ep_data->mep_data.period; 10591 ep_info_p->gport = ep_data->mep_data.gport; 10592 ep_info_p->trunk_index = ep_data->mep_data.trunk_index; 10593 ep_info_p->name = ep_data->mep_data.name; 10594 ep_info_p->level = ep_data->mep_data.level; 10595 10596 ep_info_p->vlan = ep_data->mep_data.vlan; 10597 ep_info_p->pkt_pri = ep_data->mep_data.pkt_pri; 10598 ep_info_p->outer_tpid = ep_data->mep_data.tpid; 10599 10600 ep_info_p->inner_vlan = ep_data->mep_data.inner_vlan; 10601 ep_info_p->inner_pkt_pri = ep_data->mep_data.inner_vlan_pri; 10602 ep_info_p->inner_tpid = ep_data->mep_data.inner_tpid; 10603 10604 if (!(ep_data->mep_data.flags & _FP_OAM_REMOTE_MEP)) { 10605 10606 if (ep_data->mep_data.flags & _FP_OAM_INTERFACE_STATUS_TX) { 10607 ep_info_p->flags |= BCM_OAM_ENDPOINT_INTERFACE_STATE_TX; 10608 ep_info_p->interface_state = ep_data->mep_data.intf_state; 10609 } 10610 10611 if (ep_data->mep_data.flags & _FP_OAM_PORT_STATUS_TX) { 10612 ep_info_p->flags |= BCM_OAM_ENDPOINT_PORT_STATE_TX; 10613 ep_info_p->port_state = ep_data->mep_data.port_state; 10614 } 10615 10616 ep_info_p->lm_counter_base_id = ep_data->mep_data.flex_stat_id[0]; 10617 sal_memcpy(ep_info_p->src_mac_address, ep_data->mep_data.sa, 10618 sizeof(bcm_mac_t)); 10619 sal_memcpy(ep_info_p->dst_mac_address, ep_data->mep_data.da, 10620 sizeof(bcm_mac_t)); 10621 } else { 10622 /* Set remote flag */ 10623 ep_info_p->flags |= BCM_OAM_ENDPOINT_REMOTE; 10624 ep_info_p->interface_state = mep_msg.mep_data.intf_state; 10625 ep_info_p->port_state = mep_msg.mep_data.port_state; 10626 sal_memcpy(ep_info_p->src_mac_address, mep_msg.mep_data.sa, 10627 sizeof(bcm_mac_t)); 10628 sal_memcpy(ep_info_p->dst_mac_address, mep_msg.mep_data.da, 10629 sizeof(bcm_mac_t)); 10630 } 10631 10632 return (rv); 10633 } 10634 10635 10636 int 10637 _bcm_fp_oam_ccm_endpoint_traverse(int unit, bcm_oam_group_t group, 10638 bcm_oam_endpoint_traverse_cb cb, void *user_data) 10639 { 10640 _bcm_fp_oam_control_t *oc; /* OAM control structure pointer. */ 10641 _bcm_fp_oam_group_data_t *group_p; 10642 int rv = 0; /* Return Value */ 10643 ccm_group_data_t *grp_data_ptr = NULL; 10644 bcm_oam_endpoint_info_t endpoint_info = {0}; 10645 bcm_oam_endpoint_t epid; 10646 10647 if (NULL == cb) { 10648 return (BCM_E_PARAM); 10649 } 10650 10651 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 10652 10653 group_p = &(oc->group_data[group]); 10654 if (group_p->in_use) { 10655 grp_data_ptr = &(oc->group_data[group].group_data); 10656 epid = grp_data_ptr->lmep_id; 10657 if(epid >=0 && epid <oc->mep_count) { 10658 endpoint_info.id = epid; 10659 rv = bcm_fp_oam_ccm_endpoint_get(unit, &endpoint_info); 10660 10661 rv = cb(unit, &endpoint_info, user_data); 10662 if (BCM_FAILURE(rv)) { 10663 LOG_ERROR(BSL_LS_BCM_OAM, 10664 (BSL_META_U(unit, 10665 "OAM(unit %d) Error: User call back " 10666 "routine (EP=%d) - %s.\n"), unit, 10667 epid, bcm_errmsg(rv))); 10668 return (rv); 10669 } 10670 10671 } 10672 } 10673 return BCM_E_NONE; 10674 } 10675 10676 /* 10677 * Function: 10678 * bcm_fp_oam_ccm_group_destroy 10679 * Purpose: 10680 * Delete an OAM group object. All OAM endpoints associated with the 10681 * group will also be destroyed. 10682 * Parameters: 10683 * unit - (IN) BCM device number 10684 * group_info - (IN/OUT) Pointer to an OAM group Id. 10685 * Returns: 10686 * BCM_E_XXX 10687 */ 10688 int 10689 bcm_fp_oam_ccm_endpoint_destroy(int unit, bcm_oam_endpoint_t endpoint) 10690 { 10691 _bcm_fp_oam_control_t *oc = NULL; /* OAM control structure */ 10692 _bcm_fp_oam_mep_data_t *ep_p; /* Handle to S/w Group Data */ 10693 int rv = 0; /* Return Value */ 10694 uint16 r_len; /* Msg reply lenght */ 10695 _bcm_fp_oam_group_data_t *grp_p; /* Handle to S/w Group Data */ 10696 10697 /* Get OAM control structure handle. */ 10698 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 10699 10700 /* Validate EP Index */ 10701 _BCM_OAM_EP_INDEX_VALIDATE(endpoint); 10702 10703 /* Get Handle to Local DB */ 10704 ep_p = &(oc->mep_data[endpoint]); 10705 if (!(ep_p->in_use)) { 10706 return BCM_E_NOT_FOUND; 10707 } 10708 10709 rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM, 10710 MOS_MSG_SUBCLASS_CCM_MEP_DELETE, endpoint, 0, 10711 MOS_MSG_SUBCLASS_CCM_MEP_DELETE_REPLY, &r_len); 10712 10713 if (BCM_FAILURE(rv)) { 10714 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 10715 "Mep Del Msg returned error %s.\n"), bcm_errmsg(rv))); 10716 rv = BCM_E_INTERNAL; 10717 return rv; 10718 } 10719 10720 /* Clean up Group's LMEP/RMEP reference */ 10721 grp_p = &(oc->group_data[ep_p->mep_data.group_id]); 10722 if (ep_p->mep_data.flags & _FP_OAM_REMOTE_MEP) { 10723 _CLR_BIT_FLD(grp_p->group_data.rmep_bitmap, endpoint); 10724 } else { 10725 grp_p->group_data.lmep_id = _FP_OAM_INVALID_LMEP_ID; 10726 } 10727 10728 /* Free the EP index */ 10729 rv = shr_idxres_list_free(oc->mep_pool, endpoint); 10730 if (BCM_FAILURE(rv)) { 10731 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 10732 "MEP index Free failed EP:%d %s.\n"), endpoint, 10733 bcm_errmsg(rv))); 10734 return (rv); 10735 } 10736 10737 sal_memset(ep_p, 0, sizeof(_bcm_fp_oam_mep_data_t)); 10738 10739 return rv; 10740 } 10741 10742 10743 /* 10744 * Function: 10745 * _bcm_fp_oam_ccm_event_mask_set 10746 * Purpose: 10747 * Set the CCM Events mask. 10748 * Parameters: 10749 * unit - (IN) Unit number. 10750 * Returns: 10751 * BCM_E_NONE Operation completed successfully 10752 * BCM_E_XXX Operation failed 10753 * Notes: 10754 */ 10755 STATIC int 10756 _bcm_fp_oam_ccm_event_mask_set(int unit) 10757 { 10758 _bcm_fp_oam_control_t *oc; 10759 _bcm_oam_event_handler_t *event_handler_p; 10760 uint32 event_mask = 0; 10761 uint16 reply_len; 10762 int rv = BCM_E_NONE; 10763 10764 /* Lock already taken by the calling routine. */ 10765 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 10766 10767 /* Get event mask from all callbacks */ 10768 for (event_handler_p = oc->event_handler_list_p; 10769 event_handler_p != NULL; 10770 event_handler_p = event_handler_p->next_p) { 10771 10772 if (SHR_BITGET(event_handler_p->event_types.w, 10773 bcmOAMEventGroupCCMxcon)) { 10774 event_mask |= G_XCON; 10775 } 10776 if (SHR_BITGET(event_handler_p->event_types.w, 10777 bcmOAMEventGroupCCMError)) { 10778 event_mask |= G_CCM_ERROR; 10779 } 10780 if (SHR_BITGET(event_handler_p->event_types.w, 10781 bcmOAMEventGroupRemote)) { 10782 event_mask |= G_RDI; 10783 } 10784 if (SHR_BITGET(event_handler_p->event_types.w, 10785 bcmOAMEventGroupCCMTimeout)) { 10786 event_mask |= G_CCM_TIMEOUT; 10787 } 10788 if (SHR_BITGET(event_handler_p->event_types.w, 10789 bcmOAMEventGroupMACStatus)) { 10790 event_mask |= G_CCM_MAC; 10791 } 10792 if (SHR_BITGET(event_handler_p->event_types.w, 10793 bcmOAMEventGroupCCMxconClear)) { 10794 event_mask |= G_XCON_CLR; 10795 } 10796 if (SHR_BITGET(event_handler_p->event_types.w, 10797 bcmOAMEventGroupCCMErrorClear)) { 10798 event_mask |= G_CCM_ERROR_CLR; 10799 } 10800 if (SHR_BITGET(event_handler_p->event_types.w, 10801 bcmOAMEventGroupRemoteClear)) { 10802 event_mask |= G_RDI_CLR; 10803 } 10804 if (SHR_BITGET(event_handler_p->event_types.w, 10805 bcmOAMEventGroupCCMTimeoutClear)) { 10806 event_mask |= G_CCM_TIME_IN; 10807 } 10808 if (SHR_BITGET(event_handler_p->event_types.w, 10809 bcmOAMEventGroupMACStatusClear)) { 10810 event_mask |= G_CCM_MAC_CLR; 10811 } 10812 10813 if (SHR_BITGET(event_handler_p->event_types.w, 10814 bcmOAMEventEndpointPortDown)) { 10815 event_mask |= E_PORT_DOWN; 10816 } 10817 if (SHR_BITGET(event_handler_p->event_types.w, 10818 bcmOAMEventEndpointPortUp)) { 10819 event_mask |= E_PORT_UP; 10820 } 10821 if (SHR_BITGET(event_handler_p->event_types.w, 10822 bcmOAMEventEndpointInterfaceDown)) { 10823 event_mask |= E_INTF_DOWN; 10824 } 10825 if (SHR_BITGET(event_handler_p->event_types.w, 10826 bcmOAMEventEndpointInterfaceUp)) { 10827 event_mask |= E_INTF_UP; 10828 } 10829 if (SHR_BITGET(event_handler_p->event_types.w, 10830 bcmOAMEventEndpointInterfaceTesting)) { 10831 event_mask |= E_INTF_TEST; 10832 } 10833 if (SHR_BITGET(event_handler_p->event_types.w, 10834 bcmOAMEventEndpointInterfaceUnkonwn)) { 10835 event_mask |= E_INTF_UK; 10836 } 10837 if (SHR_BITGET(event_handler_p->event_types.w, 10838 bcmOAMEventEndpointInterfaceDormant)) { 10839 event_mask |= E_INTF_DOR; 10840 } 10841 if (SHR_BITGET(event_handler_p->event_types.w, 10842 bcmOAMEventEndpointInterfaceDormantToUp)) { 10843 event_mask |= E_INTF_DOR; 10844 } 10845 if (SHR_BITGET(event_handler_p->event_types.w, 10846 bcmOAMEventEndpointInterfaceNotPresent)) { 10847 event_mask |= E_INTF_NP; 10848 } 10849 if (SHR_BITGET(event_handler_p->event_types.w, 10850 bcmOAMEventEndpointInterfaceLLDown)) { 10851 event_mask |= E_INTF_LL; 10852 } 10853 if (SHR_BITGET(event_handler_p->event_types.w, 10854 bcmOAMEventEndpointCCMTimeout)) { 10855 event_mask |= E_CCM_TIMEOUT; 10856 } 10857 if (SHR_BITGET(event_handler_p->event_types.w, 10858 bcmOAMEventEndpointCCMTimein)) { 10859 event_mask |= E_CCM_TIME_IN; 10860 } 10861 if (SHR_BITGET(event_handler_p->event_types.w, 10862 bcmOAMEventEndpointRemote)) { 10863 event_mask |= E_CCM_RDI; 10864 } 10865 if (SHR_BITGET(event_handler_p->event_types.w, 10866 bcmOAMEventEndpointRemoteUp)) { 10867 event_mask |= E_CCM_RDI_CLR; 10868 } 10869 } 10870 10871 /* Update CCM event mask in uKernel */ 10872 if (event_mask != oc->event_mask) { 10873 /* Send CCM Event Mask message to uC */ 10874 rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM, 10875 MOS_MSG_SUBCLASS_CCM_EVENT_MASK_SET, 0, event_mask, 10876 MOS_MSG_SUBCLASS_CCM_EVENT_MASK_SET_REPLY, 10877 &reply_len); 10878 10879 if (BCM_FAILURE(rv)) { 10880 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 10881 "Event Mask set Msg returned error %s.\n"), bcm_errmsg(rv))); 10882 rv = BCM_E_INTERNAL; 10883 } 10884 } 10885 10886 oc->event_mask = event_mask; 10887 10888 return (rv); 10889 } 10890 10891 10892 /* 10893 * Function: 10894 * _bcm_fp_oam_ccm_callback_thread 10895 * Purpose: 10896 * Thread to listen for event messages from uController. 10897 * Parameters: 10898 * param - Pointer to CCM info structure. 10899 * Returns: 10900 * None 10901 */ 10902 STATIC void 10903 _bcm_fp_oam_ccm_callback_thread(void *param) 10904 { 10905 int rv; 10906 _bcm_fp_oam_control_t *oc = (_bcm_fp_oam_control_t *)param; 10907 bcm_oam_event_types_t events; 10908 bcm_oam_event_type_t event_type; 10909 mos_msg_data_t event_msg; 10910 int data_index = 0; 10911 uint32 event_mask; 10912 _bcm_oam_event_handler_t *event_handler_p; 10913 int ep_id = BCM_OAM_ENDPOINT_INVALID; 10914 int group_id = BCM_OAM_GROUP_INVALID; 10915 char thread_name[SAL_THREAD_NAME_MAX_LEN]; 10916 10917 thread_name[0] = 0; 10918 sal_thread_name(oc->event_thread_id, thread_name, sizeof (thread_name)); 10919 10920 while (1) { 10921 /* Wait on notifications from uController */ 10922 rv = soc_cmic_uc_msg_receive(oc->unit, oc->ccm_uc_num, 10923 MOS_MSG_CLASS_CCM_EVENT, &event_msg, 10924 sal_sem_FOREVER); 10925 if (BCM_FAILURE(rv)) { 10926 break; /* Thread exit */ 10927 } 10928 10929 /* Get data from event message */ 10930 data_index = (int)bcm_ntohs(event_msg.s.len); 10931 event_mask = bcm_ntohl(event_msg.s.data); 10932 10933 /* One event Msg can either carry one or more Events related 10934 Group or Endpoint, Check whether Group event or EP event */ 10935 10936 /* Validate EP Index */ 10937 if ( (data_index < 0) || (data_index >= oc->mep_count) || 10938 !(oc->mep_data[data_index].in_use) ) { 10939 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META("OAM Error: " 10940 "CCM Event with Invalid EP ID = %d.\n"), data_index)); 10941 continue; 10942 } 10943 ep_id = data_index; 10944 group_id = oc->mep_data[data_index].mep_data.group_id; 10945 10946 /* Set events */ 10947 sal_memset(&events, 0, sizeof(events)); 10948 if (event_mask & G_EVENT_MASK) { 10949 10950 /* Group Events */ 10951 if (event_mask & G_XCON) { 10952 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 10953 "bcmOAMEventGroupCCMxcon - %d\n"), data_index)); 10954 10955 if (oc->event_handler_cnt[bcmOAMEventGroupCCMxcon] > 0) { 10956 SHR_BITSET(events.w, bcmOAMEventGroupCCMxcon); 10957 } 10958 } 10959 if (event_mask & G_CCM_ERROR) { 10960 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 10961 "bcmOAMEventGroupCCMError - %d\n"), data_index)); 10962 10963 if (oc->event_handler_cnt[bcmOAMEventGroupCCMError] > 0) { 10964 SHR_BITSET(events.w, bcmOAMEventGroupCCMError); 10965 } 10966 } 10967 10968 if (event_mask & G_RDI) { 10969 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 10970 "bcmOAMEventGroupRemote - %d\n"), data_index)); 10971 10972 if (oc->event_handler_cnt[bcmOAMEventGroupRemote] > 0) { 10973 SHR_BITSET(events.w, bcmOAMEventGroupRemote); 10974 } 10975 } 10976 10977 if (event_mask & G_CCM_TIMEOUT) { 10978 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 10979 "bcmOAMEventGroupCCMTimeout - %d\n"), data_index)); 10980 10981 if (oc->event_handler_cnt[bcmOAMEventGroupCCMTimeout] > 0) { 10982 SHR_BITSET(events.w, bcmOAMEventGroupCCMTimeout); 10983 } 10984 } 10985 10986 if (event_mask & G_CCM_MAC) { 10987 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 10988 "bcmOAMEventGroupMACStatus - %d\n"), data_index)); 10989 10990 if (oc->event_handler_cnt[bcmOAMEventGroupMACStatus] > 0) { 10991 SHR_BITSET(events.w, bcmOAMEventGroupMACStatus); 10992 } 10993 } 10994 10995 /* Group Clear Events */ 10996 if (event_mask & G_XCON_CLR) { 10997 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 10998 "bcmOAMEventGroupRemote - %d\n"), data_index)); 10999 11000 if (oc->event_handler_cnt[bcmOAMEventGroupCCMxconClear] > 0) { 11001 SHR_BITSET(events.w, bcmOAMEventGroupCCMxconClear); 11002 } 11003 } 11004 11005 if (event_mask & G_CCM_ERROR_CLR) { 11006 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 11007 "bcmOAMEventGroupCCMTimeout - %d\n"), data_index)); 11008 11009 if (oc->event_handler_cnt[bcmOAMEventGroupCCMErrorClear] > 0) { 11010 SHR_BITSET(events.w, bcmOAMEventGroupCCMErrorClear); 11011 } 11012 } 11013 11014 if (event_mask & G_RDI_CLR) { 11015 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 11016 "bcmOAMEventGroupRemote - %d\n"), data_index)); 11017 11018 if (oc->event_handler_cnt[bcmOAMEventGroupRemoteClear] > 0) { 11019 SHR_BITSET(events.w, bcmOAMEventGroupRemoteClear); 11020 } 11021 } 11022 11023 if (event_mask & G_CCM_TIME_IN) { 11024 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 11025 "bcmOAMEventGroupCCMTimeoutClear - %d\n"), data_index)); 11026 11027 if (oc->event_handler_cnt[bcmOAMEventGroupCCMTimeoutClear] > 0) { 11028 SHR_BITSET(events.w, bcmOAMEventGroupCCMTimeoutClear); 11029 } 11030 } 11031 11032 if (event_mask & G_CCM_MAC_CLR) { 11033 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 11034 "bcmOAMEventGroupMACStatusClear - %d\n"), data_index)); 11035 11036 if (oc->event_handler_cnt[bcmOAMEventGroupMACStatusClear] > 0) { 11037 SHR_BITSET(events.w, bcmOAMEventGroupMACStatusClear); 11038 } 11039 } 11040 } 11041 if ( event_mask & E_EVENT_MASK) { 11042 11043 /* Endpoint Events */ 11044 if (event_mask & E_PORT_DOWN) { 11045 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 11046 "bcmOAMEventEndpointPortDown - %d\n"), data_index)); 11047 11048 if (oc->event_handler_cnt[bcmOAMEventEndpointPortDown] > 0) { 11049 SHR_BITSET(events.w, bcmOAMEventEndpointPortDown); 11050 } 11051 } 11052 11053 if (event_mask & E_PORT_UP) { 11054 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 11055 "bcmOAMEventEndpointPortUp - %d\n"), data_index)); 11056 11057 if (oc->event_handler_cnt[bcmOAMEventEndpointPortUp] > 0) { 11058 SHR_BITSET(events.w, bcmOAMEventEndpointPortUp); 11059 } 11060 } 11061 11062 if (event_mask & E_INTF_DOWN) { 11063 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 11064 "bcmOAMEventEndpointInterfaceDown - %d\n"), data_index)); 11065 11066 if (oc->event_handler_cnt[bcmOAMEventEndpointInterfaceDown] > 0) { 11067 SHR_BITSET(events.w, bcmOAMEventEndpointInterfaceDown); 11068 } 11069 } 11070 11071 if (event_mask & E_INTF_UP) { 11072 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 11073 "bcmOAMEventEndpointInterfaceUp - %d\n"), data_index)); 11074 11075 if (oc->event_handler_cnt[bcmOAMEventEndpointInterfaceUp] > 0) { 11076 SHR_BITSET(events.w, bcmOAMEventEndpointInterfaceUp); 11077 } 11078 } 11079 11080 if (event_mask & E_INTF_TEST) { 11081 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 11082 "bcmOAMEventEndpointInterfaceTesting - %d\n"), data_index)); 11083 11084 if (oc->event_handler_cnt[bcmOAMEventEndpointInterfaceTesting] > 0) { 11085 SHR_BITSET(events.w, bcmOAMEventEndpointInterfaceTesting); 11086 } 11087 } 11088 11089 if (event_mask & E_INTF_UK) { 11090 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 11091 "bcmOAMEventEndpointInterfaceUnkonwn - %d\n"), data_index)); 11092 11093 if (oc->event_handler_cnt[bcmOAMEventEndpointInterfaceUnkonwn] > 0) { 11094 SHR_BITSET(events.w, bcmOAMEventEndpointInterfaceUnkonwn); 11095 } 11096 } 11097 11098 if (event_mask & E_INTF_DOR) { 11099 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 11100 "bcmOAMEventEndpointInterfaceDormant - %d\n"), data_index)); 11101 11102 if (oc->event_handler_cnt[bcmOAMEventEndpointInterfaceDormant] > 0) { 11103 SHR_BITSET(events.w, bcmOAMEventEndpointInterfaceDormant); 11104 } 11105 } 11106 11107 if (event_mask & E_INTF_NP) { 11108 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 11109 "bcmOAMEventEndpointInterfaceNotPresent - %d\n"), data_index)); 11110 11111 if (oc->event_handler_cnt[bcmOAMEventEndpointInterfaceNotPresent] > 0) { 11112 SHR_BITSET(events.w, bcmOAMEventEndpointInterfaceNotPresent); 11113 } 11114 } 11115 11116 if (event_mask & E_INTF_LL) { 11117 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 11118 "bcmOAMEventEndpointInterfaceLLDown - %d\n"), data_index)); 11119 11120 if (oc->event_handler_cnt[bcmOAMEventEndpointInterfaceLLDown] > 0) { 11121 SHR_BITSET(events.w, bcmOAMEventEndpointInterfaceLLDown); 11122 } 11123 } 11124 11125 if (event_mask & E_CCM_TIMEOUT) { 11126 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 11127 "bcmOAMEventEndpointCCMTimeout - %d\n"), data_index)); 11128 11129 if (oc->event_handler_cnt[bcmOAMEventEndpointCCMTimeout] > 0) { 11130 SHR_BITSET(events.w, bcmOAMEventEndpointCCMTimeout); 11131 } 11132 } 11133 11134 if (event_mask & E_CCM_TIME_IN) { 11135 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 11136 "bcmOAMEventEndpointCCMTimein - %d\n"), data_index)); 11137 11138 if (oc->event_handler_cnt[bcmOAMEventEndpointCCMTimein] > 0) { 11139 SHR_BITSET(events.w, bcmOAMEventEndpointCCMTimein); 11140 } 11141 } 11142 11143 if (event_mask & E_CCM_RDI) { 11144 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 11145 "bcmOAMEventEndpointRemote - %d\n"), data_index)); 11146 11147 if (oc->event_handler_cnt[bcmOAMEventEndpointRemote] > 0) { 11148 SHR_BITSET(events.w, bcmOAMEventEndpointRemote); 11149 } 11150 } 11151 11152 if (event_mask & E_CCM_RDI_CLR) { 11153 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, 11154 "bcmOAMEventEndpointRemoteUp - %d\n"), data_index)); 11155 11156 if (oc->event_handler_cnt[bcmOAMEventEndpointRemoteUp] > 0) { 11157 SHR_BITSET(events.w, bcmOAMEventEndpointRemoteUp); 11158 } 11159 } 11160 } 11161 11162 /* Loop over registered callbacks, 11163 * If any match the events field, then invoke 11164 */ 11165 for (event_handler_p = oc->event_handler_list_p; event_handler_p != NULL; 11166 event_handler_p = event_handler_p->next_p) { 11167 11168 for (event_type = bcmOAMEventEndpointPortDown; 11169 event_type < bcmOAMEventCount; ++event_type) { 11170 11171 if (SHR_BITGET(events.w, event_type)) { 11172 if (SHR_BITGET(event_handler_p->event_types.w, event_type)) { 11173 event_handler_p->cb(oc->unit, 11174 0, 11175 event_type, 11176 group_id, /* Group index */ 11177 ep_id, /* Endpoint index */ 11178 event_handler_p->user_data); 11179 } 11180 } 11181 } 11182 } 11183 } 11184 11185 oc->event_thread_id = NULL; 11186 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, "Thread Exit:%s\n"), 11187 thread_name)); 11188 sal_thread_exit(0); 11189 } 11190 11191 11192 /* 11193 * Function: 11194 * _bcm_fp_oam_cmm_group_regen 11195 * Purpose: 11196 * Reconstruct CCM Group S/w State from UKENREL on WB 11197 * Assumes Lock 11198 * Parameters: 11199 * unit - (IN) BCM device number 11200 * Retruns: 11201 * BCM_E_XXX 11202 */ 11203 STATIC int 11204 _bcm_fp_oam_cmm_group_regen(int unit, int grp_id) { 11205 11206 int rv; 11207 _bcm_fp_oam_control_t *oc; /* Pointer to OAM control structure */ 11208 uint16 r_len; 11209 shr_ccm_msg_ctrl_group_data_t grp_msg; 11210 uint8 *dma_buffer1 = NULL; 11211 uint8 *dma_buffer2 = NULL; 11212 11213 /* Get OAM control structure. */ 11214 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 11215 11216 rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM, 11217 MOS_MSG_SUBCLASS_CCM_GROUP_GET, grp_id, 0, 11218 MOS_MSG_SUBCLASS_CCM_GROUP_GET_REPLY, &r_len); 11219 11220 if (BCM_FAILURE(rv)) { 11221 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 11222 "Group Get failed Id:%d %s.\n"), grp_id, bcm_errmsg(rv))); 11223 return (rv); 11224 } 11225 11226 sal_memset(&grp_msg, 0, sizeof(shr_ccm_msg_ctrl_group_data_t)); 11227 dma_buffer1 = oc->dma_buffer; 11228 dma_buffer2 = shr_ccm_msg_ctrl_group_get_unpack(dma_buffer1, &grp_msg); 11229 11230 if (r_len != dma_buffer2 - dma_buffer1) { 11231 rv = BCM_E_INTERNAL; 11232 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 11233 "Group get Msg lenght check failed, Id:%d.\n"), grp_id)); 11234 return (rv); 11235 } 11236 11237 sal_memcpy(&(oc->group_data[grp_id].group_data) , &(grp_msg.group_data), 11238 sizeof(ccm_group_data_t)); 11239 11240 rv = shr_idxres_list_reserve(oc->group_pool, grp_id, grp_id); 11241 if (BCM_FAILURE(rv)) { 11242 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 11243 "Group index reservation failed, id:%d.\n"), grp_id)); 11244 return ((rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv); 11245 } 11246 oc->group_data[grp_id].in_use = 1; 11247 11248 return BCM_E_NONE; 11249 } 11250 11251 11252 /* 11253 * Function: 11254 * _bcm_fp_oam_cmm_mep_regen 11255 * Purpose: 11256 * Reconstruct CCM MEP S/w State from UKENREL on WB 11257 * Assumes Lock 11258 * Parameters: 11259 * unit - (IN) BCM device number 11260 * Retruns: 11261 * BCM_E_XXX 11262 */ 11263 STATIC int 11264 _bcm_fp_oam_cmm_mep_regen(int unit, int mep_id) { 11265 11266 int rv; 11267 _bcm_fp_oam_control_t *oc; /* Pointer to OAM control structure */ 11268 uint16 r_len; 11269 shr_ccm_msg_ctrl_mep_data_t mep_msg; 11270 uint8 *dma_buffer1 = NULL; 11271 uint8 *dma_buffer2 = NULL; 11272 11273 /* Get OAM control structure. */ 11274 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 11275 11276 rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM, 11277 MOS_MSG_SUBCLASS_CCM_MEP_GET, mep_id, 0, 11278 MOS_MSG_SUBCLASS_CCM_MEP_GET_REPLY, &r_len); 11279 11280 if (BCM_FAILURE(rv)) { 11281 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 11282 "MEP Get failed EP:%d %s.\n"), mep_id, bcm_errmsg(rv))); 11283 return (rv); 11284 } 11285 11286 sal_memset(&mep_msg, 0, sizeof(shr_ccm_msg_ctrl_mep_data_t)); 11287 dma_buffer1 = oc->dma_buffer; 11288 dma_buffer2 = shr_ccm_msg_ctrl_mep_get_unpack(dma_buffer1, &mep_msg); 11289 11290 if (r_len != dma_buffer2 - dma_buffer1) { 11291 rv = BCM_E_INTERNAL; 11292 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 11293 "Mep get Msg lenght check failed, id:%d.\n"), mep_id)); 11294 return (rv); 11295 } 11296 11297 sal_memcpy(&(oc->mep_data[mep_id].mep_data) , &(mep_msg.mep_data), 11298 sizeof(ccm_mep_data_t)); 11299 11300 rv = shr_idxres_list_reserve(oc->mep_pool, mep_id, mep_id); 11301 if (BCM_FAILURE(rv)) { 11302 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 11303 "Mep index reservation failed, id:%d.\n"), mep_id)); 11304 return ((rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv); 11305 } 11306 oc->mep_data[mep_id].in_use = 1; 11307 11308 return BCM_E_NONE; 11309 } 11310 11311 11312 /* 11313 * Function: 11314 * _bcm_fp_oam_ccm_reinit 11315 * Purpose: 11316 * Reconstruct CCM S/w State from UKENREL on WB 11317 * Parameters: 11318 * unit - (IN) BCM device number 11319 * Retruns: 11320 * BCM_E_XXX 11321 */ 11322 STATIC int 11323 _bcm_fp_oam_ccm_reinit(int unit) { 11324 _bcm_fp_oam_control_t *oc; /* Pointer to OAM control structure */ 11325 int rv = BCM_E_NONE; /* Operation return status */ 11326 uint16 r_len = 0; 11327 shr_ccm_msg_ctrl_app_data_t app_data_msg; 11328 uint8 *dma_buffer1 = NULL; 11329 uint8 *dma_buffer2 = NULL; 11330 int i, j; 11331 ccm_group_data_t *group_ptr = NULL; 11332 11333 /* Get OAM control structure. */ 11334 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 11335 _BCM_OAM_LOCK(oc); 11336 11337 /* Recover group Bitmap from UKENREL */ 11338 rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM, 11339 MOS_MSG_SUBCLASS_CCM_GET_APP_DATA, 0, 0, 11340 MOS_MSG_SUBCLASS_CCM_GET_APP_DATA_REPLY, &r_len); 11341 if (BCM_FAILURE(rv)) { 11342 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 11343 "App data get failed %s\n"), bcm_errmsg(rv))); 11344 _BCM_OAM_UNLOCK(oc); 11345 return (rv); 11346 } 11347 11348 sal_memset(&app_data_msg, 0, sizeof(shr_ccm_msg_ctrl_app_data_t)); 11349 dma_buffer1 = oc->dma_buffer; 11350 dma_buffer2 = shr_ccm_msg_ctrl_app_data_unpack(dma_buffer1, &app_data_msg); 11351 if (r_len != dma_buffer2 - dma_buffer1) { 11352 rv = BCM_E_INTERNAL; 11353 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 11354 "App Data get Length mismatch\n"))); 11355 _BCM_OAM_UNLOCK(oc); 11356 return (rv); 11357 } 11358 11359 /* Recover Group Data from UKENREL */ 11360 for (i=0; i<oc->group_count; i++) { 11361 if (_GET_BIT_FLD(app_data_msg.group_bitmap, i)) { 11362 rv = _bcm_fp_oam_cmm_group_regen(unit, i); 11363 if (BCM_FAILURE(rv)) { 11364 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 11365 "Group Regen failed, Id:%d, %s\n"), i, bcm_errmsg(rv))); 11366 _BCM_OAM_UNLOCK(oc); 11367 return (rv); 11368 } 11369 11370 /* Now that we have reconstrcuted the group, Reconstrcut its 11371 LMEP & RMEPs */ 11372 group_ptr = &(oc->group_data[i].group_data); 11373 if (group_ptr->lmep_id != _FP_OAM_INVALID_LMEP_ID) { 11374 11375 /* Get LMEP */ 11376 rv = _bcm_fp_oam_cmm_mep_regen(unit, group_ptr->lmep_id); 11377 if (BCM_FAILURE(rv)) { 11378 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 11379 "LMEP Regen failed, Id:%d, %s\n"), group_ptr->lmep_id, 11380 bcm_errmsg(rv))); 11381 _BCM_OAM_UNLOCK(oc); 11382 return (rv); 11383 } 11384 11385 /* Get RMEPs */ 11386 for (j=0; j<oc->mep_count; j++) { 11387 if (_GET_BIT_FLD(group_ptr->rmep_bitmap, j)) { 11388 rv = _bcm_fp_oam_cmm_mep_regen(unit, j); 11389 if (BCM_FAILURE(rv)) { 11390 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 11391 "OAM Error: RMEP Regen failed Id:%d %s\n"), j, 11392 bcm_errmsg(rv))); 11393 _BCM_OAM_UNLOCK(oc); 11394 return (rv); 11395 } 11396 } 11397 } 11398 } 11399 } 11400 } 11401 11402 _BCM_OAM_UNLOCK(oc); 11403 return BCM_E_NONE; 11404 } 11405 11406 #endif /* INCLUDE_CCM */ 11407 /*******************************************************************************/ 11408 /* CCM Embedded App supporting functions End */ 11409 /*******************************************************************************/ 11410 11411 /*******************************************************************************/ 11412 /* MPLS LM/DM App specific routines start */ 11413 /*******************************************************************************/ 11414 #if defined(INCLUDE_MPLS_LM_DM) 11415 #if defined(BCM_WARM_BOOT_SUPPORT) 11416 /* 11417 * Function: 11418 * _bcm_fp_oam_mpls_lm_dm_scache_v0sync 11419 * Purpose: 11420 * Sync MPLS LM/DM scache v0 11421 * Parameters: 11422 * unit - (IN) Device unit number 11423 * scache - (IN) Pointer to current scache location 11424 * Returns: 11425 * BCM_E_XXX 11426 */ 11427 STATIC int 11428 _bcm_fp_oam_mpls_lm_dm_scache_v0_sync(int unit, uint8 *scache) 11429 { 11430 int i; 11431 uint16 idx; 11432 _bcm_fp_oam_control_t *oc; 11433 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep; 11434 _bcm_fp_oam_pm_profile_control_t *pmc = NULL; 11435 _bcm_fp_oam_mpls_lm_dm_scache_v0_global_data_t gdata; 11436 _bcm_fp_oam_mpls_lm_dm_scache_v0_ep_data_t ep_sync; 11437 11438 /* Get handle to control structure. */ 11439 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 11440 11441 11442 /* Sync global data to scache */ 11443 gdata.uc_num = oc->mpls_lm_dm_uc_num; 11444 gdata.ukernel_ready = oc->mpls_lm_dm_ukernel_ready; 11445 gdata.rx_channel = oc->mpls_lm_dm_rx_channel; 11446 gdata.max_ep_count = oc->mpls_lm_dm_max_ep_count; 11447 gdata.base_endpoint_id = oc->mpls_lm_dm_base_endpoint_id; 11448 11449 sal_memcpy(scache, &gdata, sizeof(gdata)); 11450 scache += sizeof(gdata); 11451 11452 /* Sync EP data to scache */ 11453 _MPLS_LM_DM_EP_ITER(ep, idx) { 11454 ep_sync.in_use = ep->in_use; 11455 ep_sync.flags = ep->flags; 11456 ep_sync.type = ep->type; 11457 ep_sync.vccv_type = ep->vccv_type; 11458 ep_sync.gport = ep->gport; 11459 ep_sync.trunk_index = ep->trunk_index; 11460 ep_sync.outer_vlan = ep->outer_vlan; 11461 ep_sync.outer_tpid = ep->outer_tpid; 11462 ep_sync.outer_pri = ep->outer_pri; 11463 ep_sync.inner_vlan = ep->inner_vlan; 11464 ep_sync.inner_tpid = ep->inner_tpid; 11465 ep_sync.inner_pri = ep->inner_pri; 11466 ep_sync.egress_label = ep->egress_label; 11467 ep_sync.intf_id = ep->intf_id; 11468 ep_sync.vpn = ep->vpn; 11469 ep_sync.lm_exp = ep->lm_exp; 11470 ep_sync.lm_int_pri = ep->lm_int_pri; 11471 ep_sync.dm_exp = ep->dm_exp; 11472 ep_sync.dm_int_pri = ep->dm_int_pri; 11473 11474 sal_memcpy(&(ep_sync.dst_mac), &(ep->dst_mac), sizeof(bcm_mac_t)); 11475 sal_memcpy(&(ep_sync.src_mac), &(ep->src_mac), sizeof(bcm_mac_t)); 11476 11477 for (i = 0; i < BCM_OAM_LM_COUNTER_MAX; i++) { 11478 ep_sync.lm_ctr_base_id[i] = ep->lm_ctr_base_id[i]; 11479 ep_sync.lm_ctr_offset[i] = ep->lm_ctr_offset[i]; 11480 ep_sync.lm_ctr_action[i] = ep->lm_ctr_action[i]; 11481 11482 ep_sync.dm_ctr_base_id[i] = ep->dm_ctr_base_id[i]; 11483 ep_sync.dm_ctr_offset[i] = ep->dm_ctr_offset[i]; 11484 } 11485 ep_sync.lm_ctr_size = ep->lm_ctr_size; 11486 ep_sync.dm_ctr_size = ep->dm_ctr_size; 11487 ep_sync.session_id = ep->session_id; 11488 ep_sync.session_num_entries = ep->session_num_entries; 11489 ep_sync.pm_profile = ep->pm_profile; 11490 11491 sal_memcpy(scache, &ep_sync, sizeof(ep_sync)); 11492 scache += sizeof(ep_sync); 11493 } 11494 11495 /* Store pm profile */ 11496 if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) { 11497 11498 pmc = pm_profile_control[unit]; 11499 if (!pmc) { 11500 return BCM_E_NOT_FOUND; 11501 } 11502 11503 for(i = 0; i < _BCM_OAM_MAX_PM_PROFILES; i++) { 11504 sal_memcpy(scache, &(pmc->profile_info[i]), 11505 sizeof(_bcm_fp_oam_pm_profile_int_info_t)); 11506 11507 scache += sizeof(_bcm_fp_oam_pm_profile_int_info_t); 11508 } 11509 } else { 11510 scache += _BCM_FP_OAM_PM_PROFILE_SCACHE_SIZE; 11511 } 11512 return BCM_E_NONE; 11513 } 11514 11515 /* 11516 * Function: 11517 * _bcm_fp_oam_mpls_lm_dm_scache_v0_recover 11518 * Purpose: 11519 * Recover MPLS LM/DM software state from scache v0 11520 * Parameters: 11521 * unit - (IN) Device unit number 11522 * scache - (IN) Pointer to current scache location 11523 * Returns: 11524 * BCM_E_XXX 11525 */ 11526 STATIC int 11527 _bcm_fp_oam_mpls_lm_dm_scache_v0_recover(int unit, uint8 *scache) 11528 { 11529 int i; 11530 int idx; 11531 _bcm_fp_oam_control_t *oc; 11532 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep; 11533 _bcm_fp_oam_mpls_lm_dm_scache_v0_ep_data_t ep_scache; 11534 _bcm_fp_oam_pm_profile_control_t *pmc = NULL; 11535 bcm_oam_endpoint_info_t ep_info; 11536 int sglp, dglp; 11537 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 11538 bcm_trunk_member_t trunk_member; 11539 bcm_stat_object_t object; 11540 uint32 pool; 11541 uint32 offset_mode; 11542 uint32 base_index; 11543 bcm_stat_group_mode_t group_mode; 11544 11545 11546 11547 /* Get handle to control structure. */ 11548 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 11549 11550 /* Step over the global data, as these are either hardcoded or recovered 11551 * from other sources for now (BTE, config file) 11552 */ 11553 scache += sizeof(_bcm_fp_oam_mpls_lm_dm_scache_v0_global_data_t); 11554 11555 /* Recover EP data from scache */ 11556 _MPLS_LM_DM_EP_ITER(ep, idx) { 11557 sal_memcpy(&ep_scache, scache, sizeof(ep_scache)); 11558 scache += sizeof(ep_scache); 11559 11560 ep->in_use = ep_scache.in_use; 11561 if (!ep->in_use) { 11562 continue; 11563 } 11564 11565 ep->flags = ep_scache.flags; 11566 ep->type = ep_scache.type; 11567 ep->vccv_type = ep_scache.vccv_type; 11568 ep->gport = ep_scache.gport; 11569 ep->trunk_index = ep_scache.trunk_index; 11570 ep->outer_vlan = ep_scache.outer_vlan; 11571 ep->outer_tpid = ep_scache.outer_tpid; 11572 ep->outer_pri = ep_scache.outer_pri; 11573 ep->inner_vlan = ep_scache.inner_vlan; 11574 ep->inner_tpid = ep_scache.inner_tpid; 11575 ep->inner_pri = ep_scache.inner_pri; 11576 ep->egress_label = ep_scache.egress_label; 11577 ep->intf_id = ep_scache.intf_id; 11578 ep->vpn = ep_scache.vpn; 11579 ep->lm_exp = ep_scache.lm_exp; 11580 ep->lm_int_pri = ep_scache.lm_int_pri; 11581 ep->dm_exp = ep_scache.dm_exp; 11582 ep->dm_int_pri = ep_scache.dm_int_pri; 11583 11584 sal_memcpy(&(ep->dst_mac), &(ep_scache.dst_mac), sizeof(bcm_mac_t)); 11585 sal_memcpy(&(ep->src_mac), &(ep_scache.src_mac), sizeof(bcm_mac_t)); 11586 11587 for (i = 0; i < BCM_OAM_LM_COUNTER_MAX; i++) { 11588 ep->lm_ctr_base_id[i] = ep_scache.lm_ctr_base_id[i]; 11589 ep->lm_ctr_offset[i] = ep_scache.lm_ctr_offset[i]; 11590 ep->lm_ctr_action[i] = ep_scache.lm_ctr_action[i]; 11591 11592 ep->dm_ctr_base_id[i] = ep_scache.dm_ctr_base_id[i]; 11593 ep->dm_ctr_offset[i] = ep_scache.dm_ctr_offset[i]; 11594 } 11595 ep->lm_ctr_size = ep_scache.lm_ctr_size; 11596 ep->dm_ctr_size = ep_scache.dm_ctr_size; 11597 ep->session_id = ep_scache.session_id; 11598 ep->session_num_entries = ep_scache.session_num_entries; 11599 11600 /* Reconstruct rest of the EP data using the recovered values */ 11601 ep->id = _MPLS_LM_DM_SESS_ID_TO_EP_ID(idx); 11602 11603 _bcm_esw_stat_get_counter_id_info(unit, ep->session_id, 11604 &group_mode, &object, &offset_mode, 11605 &pool, &base_index); 11606 ep->hw_base_session_id = _MPLS_LM_DM_HW_SESS_ID_GET(pool, base_index); 11607 11608 bcm_oam_endpoint_info_t_init(&ep_info); 11609 ep_info.type = ep->type; 11610 ep_info.gport = ep->gport; 11611 ep_info.trunk_index = ep->trunk_index; 11612 BCM_IF_ERROR_RETURN( 11613 _bcm_fp_oam_endpoint_gport_resolve(unit, &ep_info, 11614 &sglp, &dglp, &(ep->tx_gport), 11615 &trunk_id, &trunk_member)); 11616 11617 BCM_IF_ERROR_RETURN(shr_idxres_list_reserve(oc->mpls_lm_dm_pool, 11618 ep->id, ep->id)); 11619 } 11620 11621 11622 if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) { 11623 11624 pmc = pm_profile_control[unit]; 11625 if (!pmc) { 11626 return BCM_E_INIT; 11627 } 11628 11629 for(i = 0; i < _BCM_OAM_MAX_PM_PROFILES; i++) { 11630 sal_memcpy(&(pmc->profile_info[i]), scache, 11631 sizeof(_bcm_fp_oam_pm_profile_int_info_t)); 11632 11633 scache += sizeof(_bcm_fp_oam_pm_profile_int_info_t); 11634 } 11635 } else { 11636 scache += _BCM_FP_OAM_PM_PROFILE_SCACHE_SIZE; 11637 } 11638 11639 return BCM_E_NONE; 11640 } 11641 11642 /* 11643 * Function: 11644 * _bcm_fp_oam_mpls_lm_dm_scache_alloc 11645 * Purpose: 11646 * Allocate scache memory for MPLS LM/DM module 11647 * Parameters: 11648 * unit - (IN) BCM device number 11649 * Returns: 11650 * BCM_E_XXX 11651 */ 11652 STATIC int 11653 _bcm_fp_oam_mpls_lm_dm_scache_alloc(int unit) 11654 { 11655 _bcm_fp_oam_control_t *oc; 11656 soc_scache_handle_t scache_handle; 11657 uint8 *scache; 11658 int alloc_size = 0; 11659 int rv = BCM_E_NONE; 11660 11661 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 11662 _BCM_OAM_LOCK(oc); 11663 11664 /* MPLS LM/DM Scache V0 size */ 11665 alloc_size += _MPLS_LM_DM_SCACHE_V0_SIZE; 11666 11667 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 11668 bcmFpOamWbSequenceMplsLmDm); 11669 11670 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 1, alloc_size, 11671 &scache, 11672 BCM_WB_MPLS_LM_DM_DEFAULT_VERSION, NULL); 11673 11674 _BCM_OAM_UNLOCK(oc); 11675 return rv; 11676 } 11677 11678 /* 11679 * Function: 11680 * _bcm_fp_oam_mpls_lm_dm_sync 11681 * Purpose: 11682 * Store MPLS LM/DM configuration to level two storage cache memory. 11683 * Parameters: 11684 * unit - (IN) Device unit number 11685 * Returns: 11686 * BCM_E_XXX 11687 */ 11688 STATIC int 11689 _bcm_fp_oam_mpls_lm_dm_sync(int unit) 11690 { 11691 int rv = BCM_E_NONE; 11692 _bcm_fp_oam_control_t *oc; 11693 int stable_size; 11694 soc_scache_handle_t scache_handle; 11695 uint8 *scache = NULL; 11696 11697 /* Get OAM module storage size. */ 11698 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 11699 11700 /* If level 2 store is not configured return from here. */ 11701 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) { 11702 return BCM_E_NONE; 11703 } 11704 11705 /* Get handle to control structure. */ 11706 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 11707 _BCM_OAM_LOCK(oc); 11708 11709 if (!(oc->mpls_lm_dm_ukernel_ready)) { 11710 goto cleanup; 11711 } 11712 11713 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 11714 bcmFpOamWbSequenceMplsLmDm); 11715 11716 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0, &scache, 11717 BCM_WB_MPLS_LM_DM_DEFAULT_VERSION, NULL); 11718 11719 if (BCM_FAILURE(rv)) { 11720 goto cleanup; 11721 } 11722 if (NULL == scache) { 11723 rv = BCM_E_INTERNAL; 11724 goto cleanup; 11725 } 11726 11727 /* Sync MPLS LM/DM scache v0 */ 11728 rv = _bcm_fp_oam_mpls_lm_dm_scache_v0_sync(unit, scache); 11729 if (BCM_FAILURE(rv)) { 11730 goto cleanup; 11731 } 11732 11733 cleanup: 11734 _BCM_OAM_UNLOCK(oc); 11735 return rv; 11736 } 11737 11738 /* 11739 * Function: 11740 * _bcm_fp_oam_mpls_lm_dm_wb_recover 11741 * Purpose: 11742 * Recover MPLS LM/DM information from scache 11743 * Parameters: 11744 * unit - (IN) Device unit number 11745 * Returns: 11746 * BCM_E_XXX 11747 */ 11748 STATIC int 11749 _bcm_fp_oam_mpls_lm_dm_wb_recover(int unit) 11750 { 11751 int stable_size; /* Secondary storage size. */ 11752 uint8 *scache = NULL; 11753 soc_scache_handle_t scache_handle; 11754 _bcm_fp_oam_control_t *oc; 11755 int rv = BCM_E_NONE; 11756 uint16 recovered_ver = 0; 11757 11758 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 11759 11760 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 11761 _BCM_OAM_LOCK(oc); 11762 11763 if (!oc->mpls_lm_dm_ukernel_ready) { 11764 goto cleanup; 11765 } 11766 11767 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) { 11768 11769 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 11770 bcmFpOamWbSequenceMplsLmDm); 11771 11772 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0, 11773 &scache, BCM_WB_MPLS_LM_DM_DEFAULT_VERSION, 11774 &recovered_ver); 11775 if (BCM_E_NOT_FOUND == rv) { 11776 /* Upgrading from SDK release that does not have warmboot state */ 11777 _bcm_fp_oam_mpls_lm_dm_scache_alloc(unit); 11778 rv = BCM_E_NONE; 11779 goto cleanup; 11780 } else if (BCM_FAILURE(rv)) { 11781 goto cleanup; 11782 } 11783 11784 if (NULL == scache) { 11785 rv = BCM_E_NOT_FOUND; 11786 goto cleanup; 11787 } 11788 } else { 11789 rv = BCM_E_NONE; 11790 goto cleanup; 11791 } 11792 11793 rv = _bcm_fp_oam_mpls_lm_dm_scache_v0_recover(unit, scache); 11794 if (BCM_FAILURE(rv)) { 11795 goto cleanup; 11796 } 11797 11798 cleanup: 11799 _BCM_OAM_UNLOCK(oc); 11800 return rv; 11801 } 11802 #endif /* BCM_WARM_BOOT_SUPPORT */ 11803 11804 /* 11805 * Function: 11806 * _bcm_fp_oam_mpls_lm_dm_init 11807 * Purpose: 11808 * Initialize MPLS LM/DM app 11809 * Parameters: 11810 * unit - (IN) BCM device number 11811 * oc - (IN) OAM control block 11812 * Returns: 11813 * BCM_E_XXX 11814 */ 11815 STATIC int 11816 _bcm_fp_oam_mpls_lm_dm_init(uint8 unit, _bcm_fp_oam_control_t *oc) 11817 { 11818 int rv = BCM_E_NONE; 11819 int uc = 0; 11820 uint8 *buffer, *buffer_ptr; 11821 uint16 buffer_len, reply_len; 11822 uint16 size; 11823 mpls_lm_dm_sdk_msg_ctrl_init_t mpls_lm_dm_msg_init; 11824 int uc_status; 11825 11826 /* 11827 * Start MPLS LM/DM application in BTE (Broadcom Task Engine) uController, 11828 * Determine which uController is running MPLS LM/DM by choosing the first 11829 * uC that returns successfully. 11830 */ 11831 oc->mpls_lm_dm_ukernel_ready = 0; 11832 for (uc = 0; uc < SOC_INFO(unit).num_ucs; uc++) { 11833 rv = soc_uc_status(unit, uc, &uc_status); 11834 if ((rv == SOC_E_NONE) && (uc_status != 0)) { 11835 rv = soc_cmic_uc_appl_init(unit, uc, MOS_MSG_CLASS_MPLS_LM_DM, 11836 _MPLS_LM_DM_UC_MSG_TIMEOUT_USECS, 11837 MPLS_LM_DM_SDK_VERSION, 11838 MPLS_LM_DM_UC_MIN_VERSION, 11839 _bcm_oam_mpls_lm_dm_appl_callback, NULL); 11840 if (SOC_E_NONE == rv) { 11841 /* MPLS_LM_DM started successfully */ 11842 oc->mpls_lm_dm_uc_num = uc; 11843 break; 11844 } 11845 } 11846 } 11847 11848 if (uc >= SOC_INFO(unit).num_ucs) { 11849 /* App not loaded return OK and skip rest of initialization */ 11850 return BCM_E_NONE; 11851 } 11852 11853 /* 11854 * Assign RX DMA channel to CPU COS Queue 11855 * (This is the RX channel to listen on for MPLS LM/DM packets). 11856 * 11857 * DMA channels (12) are assigned 4 per processor: 11858 * (see /src/bcm/common/rx.c) 11859 * channels 0..3 --> PCI host 11860 * channels 4..7 --> uController 0 11861 * chnanels 8..11 --> uController 1 11862 * 11863 * The uControllers designate the 4 local DMA channels as follows: 11864 * local channel 0 --> TX 11865 * local channel 1..3 --> RX 11866 * 11867 * Each uController application needs to use a different 11868 * RX DMA channel to listen on. 11869 */ 11870 oc->mpls_lm_dm_rx_channel = (BCM_RX_CHANNELS * 11871 (SOC_ARM_CMC(unit, oc->mpls_lm_dm_uc_num))) + 11872 MPLS_LM_DM_RX_CHANNEL_UC_VIEW; 11873 11874 if (soc_feature(unit, soc_feature_oam_pm)) { 11875 oc->pm_mpls_lm_dm_data_collection_mode = 11876 soc_property_get(unit, 11877 spn_MPLS_LMDM_DATA_COLLECTION_MODE, 11878 _BCM_OAM_PM_COLLECTION_MODE_NONE); 11879 } 11880 11881 /* 11882 * Allocate DMA buffers 11883 * DMA buffer will be used to send and receive 'long' messages 11884 * between SDK Host and uController (BTE). 11885 */ 11886 oc->mpls_lm_dm_dma_buffer_len = sizeof(mpls_lm_dm_sdk_msg_ctrl_t); 11887 if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc)) { 11888 /* If PM is enabled, increase the size of the buffer if required */ 11889 if (sizeof(shr_oam_pm_msg_ctrl_t) > oc->mpls_lm_dm_dma_buffer_len) { 11890 oc->mpls_lm_dm_dma_buffer_len = sizeof(shr_oam_pm_msg_ctrl_t); 11891 } 11892 } 11893 oc->mpls_lm_dm_dma_buffer = soc_cm_salloc(unit, 11894 oc->mpls_lm_dm_dma_buffer_len, 11895 "MPLS_LM_DM DMA buffer"); 11896 if (!oc->mpls_lm_dm_dma_buffer) { 11897 return (BCM_E_MEMORY); 11898 } 11899 sal_memset(oc->mpls_lm_dm_dma_buffer, 0, oc->mpls_lm_dm_dma_buffer_len); 11900 11901 if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) { 11902 oc->mpls_lm_dm_max_ep_count = MPLS_LM_DM_MAX_RAW_DATA_SESSIONS; 11903 } else { 11904 oc->mpls_lm_dm_max_ep_count = MPLS_LM_DM_MAX_SESSIONS; 11905 } 11906 11907 #if defined(BCM_WARM_BOOT_SUPPORT) 11908 if (!SOC_WARM_BOOT(unit)) { 11909 #endif /* BCM_WARM_BOOT_SUPPORT */ 11910 11911 /* Send Initialize MPLS LM/DM App on UKERNEL */ 11912 /* Set control message data */ 11913 sal_memset(&mpls_lm_dm_msg_init, 0, sizeof(mpls_lm_dm_msg_init)); 11914 mpls_lm_dm_msg_init.num_sessions = oc->mpls_lm_dm_max_ep_count; 11915 mpls_lm_dm_msg_init.rx_channel = MPLS_LM_DM_RX_CHANNEL_UC_VIEW; 11916 11917 if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc)) { 11918 if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) { 11919 mpls_lm_dm_msg_init.flags |= SHR_MPLS_LM_DM_PM_MODE_RAW; 11920 } else { 11921 mpls_lm_dm_msg_init.flags |= SHR_MPLS_LM_DM_PM_MODE_STATS; 11922 } 11923 } 11924 11925 11926 /* Pack control message data into DMA buffer */ 11927 buffer = oc->mpls_lm_dm_dma_buffer; 11928 buffer_ptr = mpls_lm_dm_sdk_msg_ctrl_init_pack(buffer, 11929 &mpls_lm_dm_msg_init); 11930 buffer_len = buffer_ptr - buffer; 11931 11932 /* Send MPLS_LM_DM Init message to uC */ 11933 rv = _bcm_fp_oam_msg_send_receive(unit, 11934 MOS_MSG_CLASS_MPLS_LM_DM, 11935 MOS_MSG_SUBCLASS_MPLS_LM_DM_INIT, 11936 buffer_len, 0, 11937 MOS_MSG_SUBCLASS_MPLS_LM_DM_INIT_REPLY, 11938 &reply_len); 11939 11940 if (BCM_FAILURE(rv) || (reply_len != 0)) { 11941 /* Could not start MPLS_LM_DM appl */ 11942 LOG_ERROR(BSL_LS_BCM_OAM, 11943 (BSL_META_U(unit, 11944 "OAM(unit %d) Error: " 11945 "MPLS LM DM Session alloc msg failed\n"), unit)); 11946 return rv; 11947 } 11948 #if defined(BCM_WARM_BOOT_SUPPORT) 11949 } 11950 #endif /* BCM_WARM_BOOT_SUPPORT */ 11951 11952 oc->mpls_lm_dm_ukernel_ready = 1; 11953 11954 oc->mpls_lm_dm_base_endpoint_id = 11955 soc_property_get(unit, 11956 spn_MPLS_LM_DM_BASE_ENDPOINT_ID, 11957 768); 11958 11959 /* Check if the endpoint id space tramples over other apps */ 11960 #if defined(INCLUDE_CCM) 11961 if (soc_feature(unit, soc_feature_uc_ccm)) { 11962 if (oc->ccm_ukernel_ready) { 11963 /* Base endpoint Id for CCM is 0 */ 11964 if (oc->mep_count >= oc->mpls_lm_dm_base_endpoint_id) { 11965 return BCM_E_CONFIG; 11966 } 11967 } 11968 } 11969 #endif /* INCLUDE_CCM */ 11970 11971 #if defined(INCLUDE_BHH) 11972 if (soc_feature(unit, soc_feature_bhh)) { 11973 if (!oc->ukernel_not_ready) { 11974 if (oc->mpls_lm_dm_base_endpoint_id <= oc->bhh_base_endpoint_id) { 11975 if ((oc->mpls_lm_dm_base_endpoint_id + 11976 oc->mpls_lm_dm_max_ep_count) 11977 >= oc->bhh_base_endpoint_id) { 11978 return BCM_E_CONFIG; 11979 } 11980 } else { 11981 if (oc->mpls_lm_dm_base_endpoint_id <= 11982 (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)) { 11983 return BCM_E_CONFIG; 11984 } 11985 } 11986 } 11987 } 11988 #endif /* INCLUDE_BHH */ 11989 11990 /* Create Session Pool */ 11991 rv = shr_idxres_list_create(&oc->mpls_lm_dm_pool, 11992 oc->mpls_lm_dm_base_endpoint_id, 11993 oc->mpls_lm_dm_base_endpoint_id + 11994 oc->mpls_lm_dm_max_ep_count, 11995 oc->mpls_lm_dm_base_endpoint_id, 11996 oc->mpls_lm_dm_base_endpoint_id + 11997 oc->mpls_lm_dm_max_ep_count, 11998 "MPLS LM/DM pool"); 11999 if (BCM_FAILURE(rv)) { 12000 return (rv); 12001 } 12002 12003 /* Allocate MPLS LM/DM EP data memory */ 12004 size = sizeof(_bcm_fp_oam_mpls_lm_dm_ep_data_t) * oc->mpls_lm_dm_max_ep_count; 12005 _BCM_OAM_ALLOC(oc->mpls_lm_dm_ep_data, 12006 _bcm_fp_oam_mpls_lm_dm_ep_data_t, 12007 size, "MPLS LM/DM EP data"); 12008 12009 if (soc_feature(unit, soc_feature_oam_pm)) { 12010 rv = _bcm_fp_oam_mpls_lm_dm_pm_init(unit); 12011 if (BCM_FAILURE(rv)) { 12012 return rv; 12013 } 12014 } 12015 12016 12017 #if defined(BCM_WARM_BOOT_SUPPORT) 12018 if (SOC_WARM_BOOT(unit)) { 12019 rv = _bcm_fp_oam_mpls_lm_dm_wb_recover(unit); 12020 } else { 12021 rv = _bcm_fp_oam_mpls_lm_dm_scache_alloc(unit); 12022 } 12023 12024 if (rv == BCM_E_NOT_FOUND) { 12025 /* Continue with initialization if scache not found */ 12026 rv = BCM_E_NONE; 12027 } 12028 if (BCM_FAILURE(rv)) { 12029 return (rv); 12030 } 12031 #endif /* BCM_WARM_BOOT_SUPPORT */ 12032 12033 /* 12034 * Start event message callback thread 12035 */ 12036 if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) { 12037 if (oc->mpls_lm_dm_pm_event_thread_id == NULL) { 12038 if ((oc->mpls_lm_dm_pm_event_thread_id = 12039 sal_thread_create("bcmMPLSLMDM", SAL_THREAD_STKSZ, 12040 MPLS_LMDM_EVENT_THREAD_PRIORITY, 12041 _bcm_fp_oam_mpls_lm_dm_pm_thread, 12042 (void *)oc)) == SAL_THREAD_ERROR) { 12043 oc->mpls_lm_dm_pm_event_thread_id = NULL; 12044 return (BCM_E_MEMORY); 12045 } 12046 } 12047 } 12048 12049 return rv; 12050 } 12051 12052 /* 12053 * Function: 12054 * _bcm_fp_oam_mpls_lm_dm_detach 12055 * Purpose: 12056 * Uninitialize MPLS LM/DM app 12057 * Parameters: 12058 * unit - (IN) BCM device number 12059 * Returns: 12060 * BCM_E_XXX 12061 */ 12062 STATIC int 12063 _bcm_fp_oam_mpls_lm_dm_detach(uint8 unit) 12064 { 12065 int rv = BCM_E_NONE; 12066 _bcm_fp_oam_control_t *oc = NULL; 12067 sal_usecs_t timeout = sal_time_usecs() + 5000000; 12068 uint16 reply_len; 12069 int uc_status; 12070 12071 /* Get OAM Control Structure. */ 12072 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 12073 _BCM_OAM_LOCK(oc); 12074 12075 if (!oc->mpls_lm_dm_ukernel_ready) { 12076 _BCM_OAM_UNLOCK(oc); 12077 return BCM_E_NONE; 12078 } 12079 12080 12081 while (NULL != oc->mpls_lm_dm_pm_event_thread_id) { 12082 soc_cmic_uc_msg_receive_cancel(unit, oc->mpls_lm_dm_uc_num, 12083 MOS_MSG_CLASS_MPLS_LM_DM_EVENT); 12084 12085 if (sal_time_usecs() < timeout) { 12086 /*give some time to already running mpls_lm_dm callback thread 12087 * to schedule and exit */ 12088 sal_usleep(10000); 12089 } else { 12090 /*timeout*/ 12091 LOG_ERROR(BSL_LS_BCM_OAM, 12092 (BSL_META_U(unit, 12093 "MPLS_LM_DM event thread did not exit.\n"))); 12094 _BCM_OAM_UNLOCK(oc); 12095 return BCM_E_INTERNAL; 12096 } 12097 } 12098 12099 if (!SOC_WARM_BOOT(unit)) { 12100 /* Send MPLS_LM_DM Uninit message to uC. Ignore error as uC could have 12101 * died earlier. 12102 */ 12103 SOC_IF_ERROR_RETURN(soc_uc_status(unit, oc->mpls_lm_dm_uc_num, &uc_status)); 12104 if (uc_status) { 12105 rv = _bcm_fp_oam_msg_send_receive(unit, 12106 MOS_MSG_CLASS_MPLS_LM_DM, 12107 MOS_MSG_SUBCLASS_MPLS_LM_DM_UNINIT, 12108 0, 0, 12109 MOS_MSG_SUBCLASS_MPLS_LM_DM_UNINIT_REPLY, 12110 &reply_len); 12111 if (BCM_SUCCESS(rv) && (reply_len != 0)) { 12112 LOG_ERROR(BSL_LS_BCM_OAM, 12113 (BSL_META_U(unit, 12114 "MPLS LM/DM UNINIT failed - reply_len %u\n"), 12115 reply_len)); 12116 _BCM_OAM_UNLOCK(oc); 12117 return BCM_E_INTERNAL; 12118 } 12119 /* Ignore timeout/init error since that may indicate 12120 * uKernel was reloaded/msging is not up.*/ 12121 if ((rv == BCM_E_TIMEOUT) || (rv == BCM_E_INIT)) { 12122 LOG_DEBUG(BSL_LS_BCM_OAM, 12123 (BSL_META_U(unit, 12124 "MPLS LM/DM UNINIT failed - %s\n"), 12125 bcm_errmsg(rv))); 12126 rv = BCM_E_NONE; 12127 } 12128 } 12129 } 12130 12131 _BCM_OAM_UNLOCK(oc); 12132 return rv; 12133 } 12134 12135 /* 12136 * Function: 12137 * _bcm_fp_oam_mpls_lm_dm_endpoint_params_validate 12138 * Purpose: 12139 * Validate MPLS LM/DM endpoint parameters 12140 * Parameters: 12141 * unit - (IN) BCM device number 12142 * endpoint_info - (IN) Endpoint parameters 12143 * Returns: 12144 * BCM_E_XXX 12145 */ 12146 STATIC int 12147 _bcm_fp_oam_mpls_lm_dm_endpoint_params_validate(uint8 unit, 12148 bcm_oam_endpoint_info_t *ep_info) 12149 { 12150 int rv = BCM_E_NONE; 12151 _bcm_fp_oam_control_t *oc; 12152 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep; 12153 uint32 pool; 12154 uint32 offset_mode; 12155 uint32 base_index; 12156 bcm_stat_object_t object; 12157 bcm_stat_group_mode_t group_mode; 12158 bcm_stat_flex_direction_t flex_direction; 12159 uint16 hw_base_session_id; 12160 int16 idx; 12161 12162 12163 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 12164 _BCM_OAM_LOCK(oc); 12165 12166 if (!oc->mpls_lm_dm_ukernel_ready) { 12167 LOG_ERROR(BSL_LS_BCM_OAM, 12168 (BSL_META_U(unit, 12169 "OAM(unit %d) Error: BTE not ready \n"), unit)); 12170 rv = BCM_E_INIT; 12171 goto cleanup; 12172 } 12173 12174 if (ep_info->flags & BCM_OAM_ENDPOINT_WITH_ID) { 12175 12176 /* Check if it is within the range for MPLS LM/DM */ 12177 if (!_MPLS_LM_DM_EP_ID_RANGE(ep_info->id)) { 12178 LOG_ERROR(BSL_LS_BCM_OAM, 12179 (BSL_META_U(unit, 12180 "OAM(unit %d) Error: Invalid id \n"), unit)); 12181 rv = BCM_E_PARAM; 12182 goto cleanup; 12183 } 12184 12185 idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(ep_info->id); 12186 ep = &(oc->mpls_lm_dm_ep_data[idx]); 12187 12188 /* Check if id is already in use, unless it is a replace operation */ 12189 if (!(ep_info->flags & BCM_OAM_ENDPOINT_REPLACE)) { 12190 if (ep->in_use) { 12191 LOG_ERROR(BSL_LS_BCM_OAM, 12192 (BSL_META_U(unit, 12193 "OAM(unit %d) Error: EP in use\n"), unit)); 12194 rv = BCM_E_PARAM; 12195 goto cleanup; 12196 } 12197 } 12198 } 12199 12200 if (ep_info->flags & BCM_OAM_ENDPOINT_REPLACE) { 12201 12202 /* Check if it is within the range for MPLS LM/DM */ 12203 if (!_MPLS_LM_DM_EP_ID_RANGE(ep_info->id)) { 12204 LOG_ERROR(BSL_LS_BCM_OAM, 12205 (BSL_META_U(unit, 12206 "OAM(unit %d) Error: Invalid id \n"), unit)); 12207 rv = BCM_E_PARAM; 12208 goto cleanup; 12209 } 12210 12211 ep = &(oc->mpls_lm_dm_ep_data[ep_info->id]); 12212 12213 /* If it is a replace EP must already exist */ 12214 if (!ep->in_use) { 12215 LOG_ERROR(BSL_LS_BCM_OAM, 12216 (BSL_META_U(unit, 12217 "OAM(unit %d) Error: EP not in use\n"), unit)); 12218 rv = BCM_E_PARAM; 12219 goto cleanup; 12220 } 12221 } 12222 12223 /* Validate if the gport is an MPLS port for PW MEP */ 12224 if (ep_info->type == bcmOAMEndpointTypeMplsLmDmPw) { 12225 if (-1 == BCM_GPORT_MPLS_PORT_ID_GET(ep_info->gport)) { 12226 LOG_ERROR(BSL_LS_BCM_OAM, 12227 (BSL_META_U(unit, 12228 "OAM(unit %d) Error: Invalid gport\n"), unit)); 12229 rv = BCM_E_PARAM; 12230 goto cleanup; 12231 } 12232 } 12233 12234 /* Interface validation check */ 12235 if(ep_info->type == bcmOAMEndpointTypeMplsLmDmLsp) { 12236 if ((!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, ep_info->intf_id)) && 12237 (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, ep_info->intf_id))) { 12238 LOG_ERROR(BSL_LS_BCM_OAM, 12239 (BSL_META_U(unit, 12240 "OAM(unit %d) Error: intf type not valid \n"), 12241 unit)); 12242 rv = BCM_E_PARAM; 12243 goto cleanup; 12244 } 12245 } 12246 12247 /* At least one session entry needs to be present per endpouint */ 12248 if (ep_info->session_num_entries == 0) { 12249 LOG_ERROR(BSL_LS_BCM_OAM, 12250 (BSL_META_U(unit, 12251 "OAM(unit %d) Error: Invalid session entries \n"), 12252 unit)); 12253 rv = BCM_E_PARAM; 12254 goto cleanup; 12255 } 12256 12257 12258 _bcm_esw_stat_get_counter_id_info(unit, ep_info->session_id, 12259 &group_mode, &object, &offset_mode, 12260 &pool, &base_index); 12261 12262 rv = _bcm_esw_stat_validate_object(unit, object, &flex_direction); 12263 if (rv != BCM_E_NONE) { 12264 rv = BCM_E_PARAM; 12265 LOG_ERROR(BSL_LS_BCM_OAM, 12266 (BSL_META_U(unit, 12267 "OAM(unit %d) Error: Invalid session id\n"),unit)); 12268 goto cleanup; 12269 } 12270 12271 rv = _bcm_esw_stat_validate_group(unit, group_mode); 12272 if (rv != BCM_E_NONE) { 12273 rv = BCM_E_PARAM; 12274 LOG_ERROR(BSL_LS_BCM_OAM, 12275 (BSL_META_U(unit, 12276 "OAM(unit %d) Error: Invalid session id\n"),unit)); 12277 goto cleanup; 12278 } 12279 12280 if (flex_direction != bcmStatFlexDirectionIngress) { 12281 rv = BCM_E_PARAM; 12282 LOG_ERROR(BSL_LS_BCM_OAM, 12283 (BSL_META_U(unit, 12284 "OAM(unit %d) Error: Invalid session id\n"),unit)); 12285 goto cleanup; 12286 } 12287 12288 /* Check if the session id space for this endpoint is trampling on a 12289 * different endpoint. 12290 */ 12291 hw_base_session_id = _MPLS_LM_DM_HW_SESS_ID_GET(pool, base_index); 12292 _MPLS_LM_DM_EP_ITER(ep, idx) { 12293 12294 if (!ep->in_use) { 12295 continue; 12296 } 12297 12298 if (ep_info->flags & BCM_OAM_ENDPOINT_REPLACE) { 12299 if (idx == ep_info->id) { 12300 continue; 12301 } 12302 } 12303 12304 if ((ep->hw_base_session_id <= hw_base_session_id) && 12305 ((ep->hw_base_session_id + 12306 ep->session_num_entries - 1) >= hw_base_session_id)) { 12307 rv = BCM_E_PARAM; 12308 LOG_ERROR(BSL_LS_BCM_OAM, 12309 (BSL_META_U(unit, 12310 "OAM(unit %d) Error: Invalid session id\n"),unit)); 12311 goto cleanup; 12312 } 12313 12314 if ((ep->hw_base_session_id <= 12315 (hw_base_session_id + ep_info->session_num_entries - 1)) && 12316 ((ep->hw_base_session_id + ep->session_num_entries - 1) >= 12317 (hw_base_session_id + ep_info->session_num_entries - 1))) { 12318 rv = BCM_E_PARAM; 12319 LOG_ERROR(BSL_LS_BCM_OAM, 12320 (BSL_META_U(unit, 12321 "OAM(unit %d) Error: Invalid session id\n"),unit)); 12322 goto cleanup; 12323 } 12324 } 12325 12326 /* Only pkt counter is supported */ 12327 if (ep_info->lm_ctr_type != bcmOamLmCounterTypePkt) { 12328 rv = BCM_E_UNAVAIL; 12329 goto cleanup; 12330 } 12331 12332 /* Only 32bit counter is supported */ 12333 if (ep_info->lm_ctr_sample_size != bcmOamLmCounterSize32Bit) { 12334 rv = BCM_E_UNAVAIL; 12335 goto cleanup; 12336 } 12337 12338 cleanup: 12339 _BCM_OAM_UNLOCK(oc); 12340 return rv; 12341 } 12342 12343 /* 12344 * Function: 12345 * _bcm_fp_oam_mpls_lm_dm_endpoint_create 12346 * Purpose: 12347 * Create MPLS LM/DM endpoint 12348 * Parameters: 12349 * unit - (IN) BCM device number 12350 * endpoint_info - (IN) Endpoint parameters 12351 * Returns: 12352 * BCM_E_XXX 12353 */ 12354 STATIC int 12355 _bcm_fp_oam_mpls_lm_dm_endpoint_create(uint8 unit, 12356 bcm_oam_endpoint_info_t *ep_info) 12357 { 12358 _bcm_fp_oam_control_t *oc; 12359 int rv = BCM_E_NONE; 12360 _bcm_fp_oam_mpls_lm_dm_ep_data_t ep; 12361 bcm_stat_object_t object; 12362 uint32 pool; 12363 uint32 offset_mode; 12364 uint32 base_index; 12365 bcm_stat_group_mode_t group_mode; 12366 bcm_port_t port; 12367 uint16 tpid; 12368 bcm_oam_endpoint_t id; 12369 bcm_vlan_control_vlan_t vc; 12370 int sglp, dglp; 12371 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 12372 bcm_trunk_member_t trunk_member; 12373 bcm_mpls_port_t mpls_port; 12374 bcm_l3_egress_t l3_egress; 12375 bcm_l3_intf_t l3_intf; 12376 bcm_pbmp_t pbmp, ubmp; 12377 int tpid_select; 12378 uint16 idx; 12379 12380 rv = _bcm_fp_oam_mpls_lm_dm_endpoint_params_validate(unit, ep_info); 12381 if (rv != BCM_E_NONE) { 12382 return rv; 12383 } 12384 12385 sal_memset(&ep, 0, sizeof(ep)); 12386 12387 /* Copy parameters from user */ 12388 ep.in_use = 1; 12389 ep.type = ep_info->type; 12390 ep.vccv_type = ep_info->vccv_type; 12391 12392 ep.gport = ep_info->gport; 12393 ep.trunk_index = ep_info->trunk_index; 12394 12395 ep.intf_id = ep_info->intf_id; 12396 ep.vpn = ep_info->vpn; 12397 ep.egress_label = ep_info->egress_label.label; 12398 12399 ep.session_id = ep_info->session_id; 12400 ep.session_num_entries = ep_info->session_num_entries; 12401 _bcm_esw_stat_get_counter_id_info(unit, ep_info->session_id, 12402 &group_mode, &object, &offset_mode, 12403 &pool, &base_index); 12404 ep.hw_base_session_id = _MPLS_LM_DM_HW_SESS_ID_GET(pool, base_index); 12405 12406 12407 BCM_IF_ERROR_RETURN( 12408 _bcm_fp_oam_endpoint_gport_resolve(unit, ep_info, 12409 &sglp, &dglp, &(ep.tx_gport), 12410 &trunk_id, &trunk_member)); 12411 port = BCM_GPORT_MODPORT_PORT_GET(ep.tx_gport); 12412 if (port == -1) { 12413 return BCM_E_PORT; 12414 } 12415 12416 ep.outer_pri = ep_info->pkt_pri; 12417 ep.inner_pri = ep_info->inner_pkt_pri; 12418 12419 if (_MPLS_LM_DM_SECTION_ENDPOINT_TYPE(ep_info->type)) { 12420 ep.outer_vlan = ep_info->vlan; 12421 ep.outer_tpid = ep_info->outer_tpid; 12422 ep.inner_vlan = ep_info->inner_vlan; 12423 ep.inner_tpid = ep_info->inner_tpid; 12424 12425 sal_memcpy(&(ep.dst_mac), &(ep_info->dst_mac_address), sizeof(bcm_mac_t)); 12426 sal_memcpy(&(ep.src_mac), &(ep_info->src_mac_address), sizeof(bcm_mac_t)); 12427 12428 } else { 12429 /* Get L3 interfaces */ 12430 bcm_l3_egress_t_init(&l3_egress); 12431 bcm_l3_intf_t_init(&l3_intf); 12432 12433 if (ep_info->type == bcmOAMEndpointTypeMplsLmDmPw) { 12434 /* For PW endpoints derive intf_id from DVP */ 12435 bcm_mpls_port_t_init(&mpls_port); 12436 mpls_port.mpls_port_id = ep_info->gport; 12437 BCM_IF_ERROR_RETURN(bcm_esw_mpls_port_get(unit, ep_info->vpn, 12438 &mpls_port)); 12439 ep.intf_id = mpls_port.egress_tunnel_if; 12440 } 12441 BCM_IF_ERROR_RETURN(bcm_esw_l3_egress_get(unit, 12442 ep.intf_id, 12443 &l3_egress)); 12444 l3_intf.l3a_intf_id = l3_egress.intf; 12445 BCM_IF_ERROR_RETURN(bcm_esw_l3_intf_get(unit, &l3_intf)); 12446 12447 /* Get TPID */ 12448 BCM_IF_ERROR_RETURN( 12449 bcm_esw_vlan_control_port_get(unit, 12450 port, 12451 bcmVlanPortOuterTpidSelect, 12452 &tpid_select)); 12453 if (tpid_select == BCM_PORT_OUTER_TPID) { 12454 BCM_IF_ERROR_RETURN(bcm_esw_port_tpid_get(unit, port, &tpid)); 12455 } else { 12456 BCM_IF_ERROR_RETURN(bcm_esw_vlan_control_vlan_get(unit, 12457 l3_intf.l3a_vid, 12458 &vc)); 12459 tpid = vc.outer_tpid; 12460 } 12461 12462 sal_memcpy(ep.dst_mac, l3_egress.mac_addr, sizeof(bcm_mac_t)); 12463 sal_memcpy(ep.src_mac, l3_intf.l3a_mac_addr, sizeof(bcm_mac_t)); 12464 12465 ep.outer_tpid = tpid; 12466 ep.outer_vlan = l3_intf.l3a_vid; 12467 12468 BCM_IF_ERROR_RETURN(bcm_esw_vlan_port_get(unit, 12469 ep.outer_vlan, 12470 &pbmp, 12471 &ubmp)); 12472 if (BCM_PBMP_MEMBER(ubmp, port)) { 12473 ep.outer_tpid = 0; /* Set to 0 to indicate untagged */ 12474 } 12475 12476 if (l3_intf.l3a_inner_vlan != 0) { 12477 BCM_IF_ERROR_RETURN(bcm_esw_port_inner_tpid_get(unit, port, &tpid)); 12478 ep.inner_tpid = tpid; 12479 ep.inner_vlan = l3_intf.l3a_inner_vlan; 12480 } 12481 } 12482 12483 /* All validations completed, add the EP */ 12484 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 12485 _BCM_OAM_LOCK(oc); 12486 12487 if (ep_info->flags & BCM_OAM_ENDPOINT_WITH_ID) { 12488 12489 if (!(ep_info->flags & BCM_OAM_ENDPOINT_REPLACE)) { 12490 rv = shr_idxres_list_reserve(oc->mpls_lm_dm_pool, 12491 ep_info->id, ep_info->id); 12492 } 12493 id = ep_info->id; 12494 } else { 12495 rv = shr_idxres_list_alloc(oc->mpls_lm_dm_pool, 12496 (shr_idxres_element_t *)&id); 12497 } 12498 12499 if (BCM_FAILURE(rv)) { 12500 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_FULL) : rv; 12501 LOG_ERROR(BSL_LS_BCM_OAM, 12502 (BSL_META_U(unit, 12503 "MPLS_LM_DM(unit %d) Error: Endpoint alloc failed - %s.\n"), 12504 unit, bcm_errmsg(rv))); 12505 _BCM_OAM_UNLOCK(oc); 12506 return rv; 12507 } 12508 12509 idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(id); 12510 sal_memcpy(&(oc->mpls_lm_dm_ep_data[idx]), &ep, sizeof(ep)); 12511 12512 /* Set PM profile default value */ 12513 oc->mpls_lm_dm_ep_data[idx].pm_profile = _BCM_OAM_INVALID_INDEX; 12514 oc->mpls_lm_dm_ep_data[idx].in_use = 1; 12515 12516 _BCM_OAM_UNLOCK(oc); 12517 return rv; 12518 } 12519 12520 /* 12521 * Function: 12522 * _bcm_fp_oam_mpls_lm_dm_endpoint_get 12523 * Purpose: 12524 * Create MPLS LM/DM endpoint 12525 * Parameters: 12526 * unit - (IN) BCM device number 12527 * endpoint - (IN) Endpoint id 12528 * endpoint_info - (OUT) Endpoint parameters 12529 * Returns: 12530 * BCM_E_XXX 12531 */ 12532 STATIC int 12533 _bcm_fp_oam_mpls_lm_dm_endpoint_get(int unit, bcm_oam_endpoint_t id, 12534 bcm_oam_endpoint_info_t *ep_info) 12535 { 12536 _bcm_fp_oam_control_t *oc; 12537 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep; 12538 uint16 idx; 12539 12540 12541 if (NULL == ep_info) { 12542 return BCM_E_PARAM; 12543 } 12544 12545 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 12546 12547 if (!oc->mpls_lm_dm_ukernel_ready) { 12548 LOG_ERROR(BSL_LS_BCM_OAM, 12549 (BSL_META_U(unit, 12550 "OAM(unit %d) Error: BTE not ready \n"), unit)); 12551 return BCM_E_INIT; 12552 } 12553 12554 idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(id); 12555 ep = &(oc->mpls_lm_dm_ep_data[idx]); 12556 12557 if (!ep->in_use) { 12558 return BCM_E_NOT_FOUND; 12559 } 12560 12561 /* Copy params from EP data */ 12562 bcm_oam_endpoint_info_t_init(ep_info); 12563 ep_info->id = id; 12564 ep_info->type = ep->type; 12565 ep_info->vccv_type = ep->vccv_type; 12566 12567 ep_info->gport = ep->gport; 12568 ep_info->trunk_index = ep->trunk_index; 12569 12570 ep_info->intf_id = ep->intf_id; 12571 ep_info->vpn = ep->vpn; 12572 ep_info->egress_label.label = ep->egress_label; 12573 12574 ep_info->session_id = ep->session_id; 12575 ep_info->session_num_entries = ep->session_num_entries; 12576 12577 ep_info->vlan = ep->outer_vlan; 12578 ep_info->outer_tpid = ep->outer_tpid; 12579 ep_info->pkt_pri = ep->outer_pri; 12580 12581 ep_info->inner_vlan = ep->inner_vlan; 12582 ep_info->inner_tpid = ep->inner_tpid; 12583 ep_info->inner_pkt_pri = ep->inner_pri; 12584 12585 sal_memcpy(&(ep_info->dst_mac_address), &(ep->dst_mac), sizeof(bcm_mac_t)); 12586 sal_memcpy(&(ep_info->src_mac_address), &(ep->src_mac), sizeof(bcm_mac_t)); 12587 12588 return BCM_E_NONE; 12589 } 12590 12591 /* 12592 * Function: 12593 * _bcm_fp_oam_mpls_lm_dm_endpoint_destroy 12594 * Purpose: 12595 * DEstroy MPLS LM/DM endpoint 12596 * Parameters: 12597 * unit - (IN) BCM device number 12598 * endpoint - (IN) Endpoint id 12599 * Returns: 12600 * BCM_E_XXX 12601 */ 12602 STATIC int 12603 _bcm_fp_oam_mpls_lm_dm_endpoint_destroy(int unit, bcm_oam_endpoint_t id) 12604 { 12605 _bcm_fp_oam_control_t *oc; 12606 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep; 12607 uint16 idx; 12608 int rv = BCM_E_NONE; 12609 12610 12611 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 12612 _BCM_OAM_LOCK(oc); 12613 12614 if (!oc->mpls_lm_dm_ukernel_ready) { 12615 LOG_ERROR(BSL_LS_BCM_OAM, 12616 (BSL_META_U(unit, 12617 "OAM(unit %d) Error: BTE not ready \n"), unit)); 12618 _BCM_OAM_UNLOCK(oc); 12619 return BCM_E_INIT; 12620 } 12621 12622 idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(id); 12623 ep = &(oc->mpls_lm_dm_ep_data[idx]); 12624 12625 if (!(ep->in_use)) { 12626 _BCM_OAM_UNLOCK(oc); 12627 return BCM_E_PARAM; 12628 } 12629 12630 if (ep->flags & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED) { 12631 rv = _bcm_fp_oam_mpls_lm_dm_delay_delete(unit, id); 12632 if (BCM_FAILURE(rv)) { 12633 _BCM_OAM_UNLOCK(oc); 12634 return rv; 12635 } 12636 } 12637 12638 if (ep->flags & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED) { 12639 rv = _bcm_fp_oam_mpls_lm_dm_loss_delete(unit, id); 12640 if (BCM_FAILURE(rv)) { 12641 _BCM_OAM_UNLOCK(oc); 12642 return rv; 12643 } 12644 } 12645 12646 /* Free the EP index */ 12647 rv = shr_idxres_list_free(oc->mpls_lm_dm_pool, id); 12648 if (BCM_FAILURE(rv)) { 12649 _BCM_OAM_UNLOCK(oc); 12650 return rv; 12651 } 12652 12653 sal_memset(ep, 0, sizeof(*ep)); 12654 12655 _BCM_OAM_UNLOCK(oc); 12656 return BCM_E_NONE; 12657 } 12658 12659 /* 12660 * Function: 12661 * _bcm_fp_oam_mpls_lm_dm_period_validate 12662 * Purpose: 12663 * Validate if the period passed by user is valid 12664 * Parameters: 12665 * period - (IN) period from user 12666 * 12667 * Returns: 12668 * BCM_E_NONE - If the period is valid 12669 * BCM_E_PARAM - If the period is invalid 12670 */ 12671 STATIC int 12672 _bcm_fp_oam_mpls_lm_dm_period_validate(int period) 12673 { 12674 switch(period) { 12675 case BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED: 12676 case BCM_OAM_ENDPOINT_CCM_PERIOD_100MS: 12677 case BCM_OAM_ENDPOINT_CCM_PERIOD_1S: 12678 case BCM_OAM_ENDPOINT_CCM_PERIOD_10S: 12679 case BCM_OAM_ENDPOINT_CCM_PERIOD_1M: 12680 case BCM_OAM_ENDPOINT_CCM_PERIOD_10M: 12681 return BCM_E_NONE; 12682 default: 12683 return BCM_E_PARAM; 12684 } 12685 } 12686 12687 /* 12688 * Function: 12689 * _bcm_fp_oam_mpls_lm_dm_encap_data_dump 12690 * Purpose: 12691 * Dumps MPLS LM/DM encap 12692 * Parameters: 12693 * encap_data - (IN) Buffer containing MPLS_LM_DM encapsulation. 12694 * encap_length - (IN) Length of the encap constructed 12695 */ 12696 #if defined(MPLS_LM_DM_DEBUG) 12697 STATIC void 12698 _bcm_fp_oam_mpls_lm_dm_encap_data_dump(uint8 *encap_data, uint16 encap_length) 12699 { 12700 int i = 0; 12701 12702 LOG_CLI((BSL_META("\nEncapsulation (length=%u):\n"), encap_length)); 12703 for (i = 0; i < encap_length; i++) { 12704 if (i % 16 == 0) { 12705 LOG_CLI((BSL_META("\n"))); 12706 } 12707 LOG_CLI((BSL_META("%02x "), encap_data[i])); 12708 } 12709 LOG_CLI((BSL_META("\n"))); 12710 } 12711 #endif /* MPLS_LM_DM_DEBUG */ 12712 12713 STATIC int 12714 _bcm_fp_oam_mpls_lm_dm_label_get(uint32 label, uint8 exp, uint8 s, 12715 uint8 ttl, _mpls_label_t *mpls_hdr) 12716 { 12717 sal_memset(mpls_hdr, 0, sizeof(*mpls_hdr)); 12718 12719 mpls_hdr->label = label; 12720 mpls_hdr->exp = exp; 12721 mpls_hdr->s = s; 12722 if (ttl) { 12723 mpls_hdr->ttl = ttl; 12724 } else { 12725 mpls_hdr->ttl = _MPLS_LM_DM_MPLS_DFLT_TTL; 12726 } 12727 12728 return (BCM_E_NONE); 12729 } 12730 12731 /* 12732 * Function: 12733 * _bcm_fp_oam_mpls_lm_dm_lsp_labels_get 12734 * Purpose: 12735 * Get the LSP label stack 12736 * Parameters: 12737 * unit - (IN) Unit number. 12738 * ep - (IN) Endpoint params 12739 * max_labels - (IN) Max number of supported labels 12740 * label_stack - (OUT) LSP label stack 12741 * label_count - (OUT) Number of LSP labels 12742 * Returns: 12743 * BCM_E_XXX 12744 */ 12745 STATIC int 12746 _bcm_fp_oam_mpls_lm_dm_lsp_labels_get(int unit, 12747 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep, 12748 int max_labels, _mpls_label_t *label_stack, 12749 int *label_count) 12750 { 12751 12752 bcm_l3_egress_t l3_egress; 12753 bcm_l3_intf_t l3_intf; 12754 bcm_mpls_egress_label_t label_array[_MPLS_LM_DM_MPLS_MAX_LABELS]; 12755 int count = 0; 12756 int i, j; 12757 int egr_label_idx = 0; 12758 12759 bcm_l3_egress_t_init(&l3_egress); 12760 bcm_l3_intf_t_init(&l3_intf); 12761 12762 BCM_IF_ERROR_RETURN(bcm_esw_l3_egress_get(unit, 12763 ep->intf_id, 12764 &l3_egress)); 12765 12766 BCM_IF_ERROR_RETURN( 12767 bcm_esw_mpls_tunnel_initiator_get(unit, l3_egress.intf, 12768 _MPLS_LM_DM_MPLS_MAX_LABELS, 12769 label_array, 12770 &count)); 12771 /* LSP endpoint specific */ 12772 if (ep->type == bcmOAMEndpointTypeMplsLmDmLsp) { 12773 /* Add VRL if applicable */ 12774 if ((l3_egress.mpls_label != BCM_MPLS_LABEL_INVALID) && 12775 (count < _MPLS_LM_DM_MPLS_MAX_LABELS)) { 12776 label_array[count - 1].label = l3_egress.mpls_label; 12777 label_array[count - 1].exp = l3_egress.mpls_exp; 12778 label_array[count - 1].ttl = l3_egress.mpls_ttl; 12779 count++; 12780 } 12781 12782 /* Find label on which OAM is running */ 12783 for (i = 0; i < count; i++) { 12784 if (label_array[i].label == ep->egress_label) { 12785 *label_count = count - i; 12786 egr_label_idx = i; 12787 break; 12788 } 12789 } 12790 if (i >= count) { 12791 /* Could not find a matching label */ 12792 return BCM_E_PARAM; 12793 } 12794 /* Remove all labels from BoS to egress_label */ 12795 for (i = egr_label_idx, j = 0; i < count; i++, j++) { 12796 /* Copy labels */ 12797 label_array[j].label = label_array[i].label; 12798 label_array[j].exp = label_array[i].exp; 12799 label_array[j].ttl = label_array[i].ttl; 12800 } 12801 } else { /* PW endpoint */ 12802 *label_count = count; 12803 } 12804 12805 if ((*label_count) > max_labels) { 12806 /* Too many labels */ 12807 return BCM_E_PARAM; 12808 } 12809 12810 12811 for (i = 0; i < (*label_count); i++) { 12812 _bcm_fp_oam_mpls_lm_dm_label_get(label_array[i].label, 12813 label_array[i].exp, 0, 12814 label_array[i].ttl, 12815 &(label_stack[i])); 12816 12817 } 12818 return BCM_E_NONE; 12819 } 12820 12821 /* 12822 * Function: 12823 * _bcm_fp_oam_mpls_lm_dm_l2_hdr_pack 12824 * Purpose: 12825 * Packs the L2 header 12826 * Parameters: 12827 * unit - (IN) Unit number. 12828 * ep - (IN) Endpoint params 12829 * encap_data - (OUT) Buffer returning MPLS_LM_DM encapsulation. 12830 * encap_length - (OUT) Length of the encap constructed 12831 * Returns: 12832 * BCM_E_XXX 12833 */ 12834 STATIC void 12835 _bcm_fp_oam_mpls_lm_dm_l2_hdr_pack(int unit, 12836 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep, 12837 uint8 *encap_data, uint16 *encap_length) 12838 { 12839 uint32 tmp; 12840 int i; 12841 uint8 *cur_ptr = encap_data; 12842 12843 for (i = 0; i < 6; i++) { 12844 _SHR_PACK_U8(cur_ptr, ep->dst_mac[i]); 12845 } 12846 12847 for (i = 0; i < 6; i++) { 12848 _SHR_PACK_U8(cur_ptr, ep->src_mac[i]); 12849 } 12850 12851 /* outer_tpid = 0 indicates no outer tag */ 12852 tmp = 0; 12853 if (0 != ep->outer_tpid) { 12854 tmp = (ep->outer_tpid << 16) | 12855 ((ep->outer_pri & 0x7) << 13) | 12856 (ep->outer_vlan & 0xfff); 12857 _SHR_PACK_U32(cur_ptr, tmp); 12858 } 12859 12860 /* inner_tpid = 0 indicates no inner tag*/ 12861 tmp = 0; 12862 if (0 != ep->inner_tpid) { 12863 tmp = (ep->inner_tpid << 16) | 12864 ((ep->inner_pri & 0x7) << 13) | 12865 (ep->inner_vlan & 0xfff); 12866 _SHR_PACK_U32(cur_ptr, tmp); 12867 } 12868 12869 _SHR_PACK_U16(cur_ptr, SHR_MPLS_LM_DM_L2_ETYPE_MPLS_UCAST); 12870 12871 *encap_length = cur_ptr - encap_data; 12872 12873 } 12874 12875 /* 12876 * Function: 12877 * _bcm_fp_oam_mpls_lm_dm_ach_header_pack 12878 * Purpose: 12879 * Packs the ACH header. 12880 * Parameters: 12881 * ach_header - (IN) ACH header 12882 * buffer - (OUT) Buffer containing packed ACH 12883 * Returns: 12884 * Incremented buffer pointer 12885 */ 12886 STATIC uint8 * 12887 _bcm_fp_oam_mpls_lm_dm_ach_header_pack(_ach_header_t *ach, uint8 *buffer) 12888 { 12889 uint32 tmp; 12890 12891 tmp = ((ach->f_nibble & 0xf) << 28) | 12892 ((ach->version & 0xf) << 24) | 12893 (ach->reserved << 16) | 12894 ach->channel_type; 12895 12896 _SHR_PACK_U32(buffer, tmp); 12897 12898 return (buffer); 12899 } 12900 12901 /* 12902 * Function: 12903 * _bcm_fp_oam_mpls_lm_dm_label_pack 12904 * Purpose: 12905 * Packs the MPLS label header. 12906 * Parameters: 12907 * label - (IN) Label header 12908 * buffer - (OUT) Buffer containing packed Label 12909 * Returns: 12910 * Incremented buffer pointer 12911 */ 12912 STATIC uint8 * 12913 _bcm_fp_oam_mpls_lm_dm_mpls_label_pack(_mpls_label_t *label, uint8 *buffer) 12914 { 12915 uint32 tmp; 12916 12917 tmp = ((label->label & 0xfffff) << 12) | 12918 ((label->exp & 0x7) << 9) | 12919 ((label->s & 0x1) << 8) | 12920 label->ttl; 12921 _SHR_PACK_U32(buffer, tmp); 12922 12923 return (buffer); 12924 } 12925 12926 /* 12927 * Function: 12928 * _bcm_fp_oam_mpls_lm_dm_mpls_hdr_build_pack 12929 * Purpose: 12930 * Builds and packs the MPLS header 12931 * Parameters: 12932 * unit - (IN) Unit number. 12933 * ep - (IN) Endpoint params 12934 * channel_type - (IN) ACH channel type used in the packet 12935 * oam_exp - (IN) EXP of the label running OAM 12936 * oam_ttl - (IN) TTL of the label running OAM 12937 * encap_data - (OUT) Buffer returning MPLS_LM_DM encapsulation. 12938 * encap_length - (OUT) Length of the encap constructed 12939 * Returns: 12940 * BCM_E_XXX 12941 * Notes: 12942 * The returning MPLS_LM_DM encapsulation includes only all the 12943 * encapsulation headers/labels and does not include 12944 * the MPLS_LM_DM control packet. 12945 */ 12946 STATIC int 12947 _bcm_fp_oam_mpls_lm_dm_mpls_hdr_build_pack(int unit, 12948 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep, 12949 uint32 channel_type, 12950 uint8 oam_exp, 12951 uint8 *encap_data, 12952 uint16 *encap_length) 12953 { 12954 _mpls_label_t label_stack[_MPLS_LM_DM_MPLS_MAX_LABELS]; 12955 _ach_header_t ach; 12956 uint32 packet_flags = 0; 12957 int label_count = 0; 12958 int lsp_label_count = 0; 12959 int oam_label_idx = -1; 12960 uint8 *cur_ptr; 12961 int i; 12962 bcm_mpls_port_t mpls_port; 12963 12964 12965 /* 12966 * Get MPLS_LM_DM encapsulation packet format flags 12967 * 12968 * Also, perform the following for each MPLS_LM_DM tunnel type: 12969 * - Check for valid parameter values 12970 * - Set specific values required by the MPLS_LM_DM tunnel definition 12971 * (e.g. such as ttl=1,...) 12972 */ 12973 switch (ep->type) { 12974 case bcmOAMEndpointTypeMplsLmDmLsp: 12975 packet_flags |= (_MPLS_LM_DM_ENCAP_PKT_GAL | 12976 _MPLS_LM_DM_ENCAP_PKT_MPLS_LSP); 12977 break; 12978 12979 case bcmOAMEndpointTypeMplsLmDmPw: 12980 packet_flags |= (_MPLS_LM_DM_ENCAP_PKT_PW | 12981 _MPLS_LM_DM_ENCAP_PKT_MPLS_LSP); 12982 switch(ep->vccv_type) { 12983 12984 case bcmOamBhhVccvChannelAch: 12985 case bcmOamBhhVccvTtl: 12986 break; 12987 12988 case bcmOamBhhVccvRouterAlert: 12989 packet_flags |= _MPLS_LM_DM_ENCAP_PKT_MPLS_ROUTER_ALERT; 12990 break; 12991 12992 case bcmOamBhhVccvGal13: 12993 packet_flags |= _MPLS_LM_DM_ENCAP_PKT_GAL; 12994 break; 12995 12996 default: 12997 return (BCM_E_PARAM); 12998 break; 12999 } 13000 break; 13001 13002 case bcmOAMEndpointTypeMplsLmDmSectionPort: 13003 case bcmOAMEndpointTypeMplsLmDmSectionInnervlan: 13004 case bcmOAMEndpointTypeMplsLmDmSectionOuterVlan: 13005 case bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan: 13006 packet_flags |= _MPLS_LM_DM_ENCAP_PKT_GAL; 13007 break; 13008 default: 13009 return (BCM_E_PARAM); 13010 } 13011 13012 13013 /* 13014 * Get necessary headers/labels information. 13015 * 13016 * The order is important, as the encap is built in this order. 13017 */ 13018 /* Construct ACH */ 13019 sal_memset(&ach, 0, sizeof(ach)); 13020 ach.f_nibble = SHR_MPLS_LM_DM_ACH_FIRST_NIBBLE; 13021 ach.version = SHR_MPLS_LM_DM_ACH_VERSION; 13022 ach.reserved = 0; 13023 ach.channel_type = channel_type; 13024 13025 /* Construct GAL */ 13026 if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_GAL) { 13027 _bcm_fp_oam_mpls_lm_dm_label_get(SHR_MPLS_LM_DM_MPLS_GAL_LABEL, 13028 0, 1, 1, &(label_stack[label_count])); 13029 label_count++; 13030 } 13031 13032 /* Add PW label */ 13033 if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_PW) { 13034 bcm_mpls_port_t_init(&mpls_port); 13035 mpls_port.mpls_port_id = ep->gport; 13036 BCM_IF_ERROR_RETURN(bcm_esw_mpls_port_get(unit, ep->vpn, &mpls_port)); 13037 13038 if (ep->vccv_type == bcmOamBhhVccvTtl) { 13039 mpls_port.egress_label.ttl = 0x1; 13040 } 13041 13042 _bcm_fp_oam_mpls_lm_dm_label_get(mpls_port.egress_label.label, 13043 mpls_port.egress_label.exp, 0, 13044 mpls_port.egress_label.ttl, 13045 &(label_stack[label_count])); 13046 oam_label_idx = label_count; /* OAM label is the PW label */ 13047 label_count++; 13048 } 13049 13050 13051 /* Construct RAL */ 13052 if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_MPLS_ROUTER_ALERT) { 13053 _bcm_fp_oam_mpls_lm_dm_label_get(SHR_MPLS_LM_DM_MPLS_ROUTER_ALERT_LABEL, 13054 0, 0, 0, &(label_stack[label_count])); 13055 label_count++; 13056 } 13057 13058 /* Add LSP labels */ 13059 if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_MPLS_LSP) { 13060 BCM_IF_ERROR_RETURN( 13061 _bcm_fp_oam_mpls_lm_dm_lsp_labels_get( 13062 unit, ep, 13063 _MPLS_LM_DM_MPLS_MAX_LABELS - label_count, 13064 &(label_stack[label_count]), 13065 &lsp_label_count)); 13066 13067 /* Find the OAM label */ 13068 if (ep->type == bcmOAMEndpointTypeMplsLmDmLsp) { 13069 oam_label_idx = label_count; 13070 } 13071 label_count += lsp_label_count; 13072 } 13073 13074 /* Set the EXP of OAM label to user specified value */ 13075 if ((ep->type == bcmOAMEndpointTypeMplsLmDmLsp) || 13076 (ep->type == bcmOAMEndpointTypeMplsLmDmPw)) { 13077 label_stack[oam_label_idx].exp = oam_exp; 13078 } 13079 13080 label_stack[0].s = 1; /* Set BoS*/ 13081 13082 /* Pack the MPLS header in Network Byte Order */ 13083 cur_ptr = encap_data; 13084 for (i = (label_count -1); i >= 0; i--) { 13085 cur_ptr = _bcm_fp_oam_mpls_lm_dm_mpls_label_pack(&(label_stack[i]), 13086 cur_ptr); 13087 } 13088 cur_ptr = _bcm_fp_oam_mpls_lm_dm_ach_header_pack(&ach, cur_ptr); 13089 *encap_length = cur_ptr - encap_data; 13090 13091 return BCM_E_NONE; 13092 } 13093 13094 /* 13095 * Function: 13096 * _bcm_fp_oam_mpls_lm_dm_encap_create 13097 * Purpose: 13098 * Creates a MPLS_LM_DM packet encapsulation. 13099 * Parameters: 13100 * unit - (IN) Unit number. 13101 * ep - (IN) Endpoint params 13102 * encap_data - (OUT) Buffer returning MPLS_LM_DM encapsulation. 13103 * encap_length - (OUT) Length of the encap constructed 13104 * ach - (IN) ACH of the packet 13105 * Returns: 13106 * BCM_E_XXX 13107 * Notes: 13108 * The returning MPLS_LM_DM encapsulation buffer includes all the 13109 * corresponding headers/labels EXCEPT for the MPLS_LM_DM control packet. 13110 */ 13111 STATIC int 13112 _bcm_fp_oam_mpls_lm_dm_encap_create(int unit, 13113 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep, 13114 uint8 *encap_data, uint16 *encap_length, 13115 uint32 ach, uint8 oam_exp) 13116 { 13117 uint16 l2_encap_length, mpls_encap_length; 13118 13119 /* Build and pack l2 header */ 13120 _bcm_fp_oam_mpls_lm_dm_l2_hdr_pack(unit, ep, encap_data, &l2_encap_length); 13121 13122 /* Build and pack MPLS header */ 13123 BCM_IF_ERROR_RETURN( 13124 _bcm_fp_oam_mpls_lm_dm_mpls_hdr_build_pack(unit, ep, ach, oam_exp, 13125 encap_data + l2_encap_length, 13126 &mpls_encap_length)); 13127 13128 *encap_length = l2_encap_length + mpls_encap_length; 13129 13130 #if defined(MPLS_LM_DM_DEBUG) 13131 _bcm_fp_oam_mpls_lm_dm_encap_data_dump(encap_data, *encap_length); 13132 #endif /* MPLS_LM_DM_DEBUG */ 13133 return (BCM_E_NONE); 13134 } 13135 13136 /* 13137 * Function: 13138 * _bcm_fp_oam_mpls_lm_dm_loss_add 13139 * Purpose: 13140 * Create MPLS LM/DM Loss session 13141 * Parameters: 13142 * unit - (IN) BCM device number 13143 * loss_p - (IN) Loss params 13144 * Returns: 13145 * BCM_E_XXX 13146 */ 13147 int 13148 _bcm_fp_oam_mpls_lm_dm_loss_add(uint8 unit, bcm_oam_loss_t *loss_p) 13149 { 13150 _bcm_fp_oam_control_t *oc = NULL; 13151 uint8 num_sample_action = 0; 13152 mpls_lm_dm_sdk_msg_ctrl_loss_add_t msg; 13153 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep; 13154 uint32 ach = 0; 13155 uint32 lm_int_flags = 0; 13156 bcm_module_t my_modid = 0; 13157 bcm_gport_t cpu_dglp; 13158 soc_olp_l2_hdr_t olp_l2_hdr; 13159 soc_olp_tx_hdr_t olp_oam_hdr; 13160 uint8 *buffer, *cur_ptr; 13161 uint16 buffer_len, reply_len; 13162 uint32 ctr_pool; 13163 uint32 ctr_mode; 13164 uint32 base_index; 13165 bcm_stat_group_mode_t ctr_group; 13166 bcm_stat_object_t ctr_object; 13167 uint16 idx; 13168 int rv = BCM_E_NONE; 13169 int i; 13170 13171 13172 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 13173 13174 /* Validation checks */ 13175 if (!oc->mpls_lm_dm_ukernel_ready) { 13176 return BCM_E_INIT; 13177 } 13178 13179 idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(loss_p->id); 13180 ep = &(oc->mpls_lm_dm_ep_data[idx]); 13181 13182 if (!ep->in_use) { 13183 return BCM_E_PARAM; 13184 } 13185 13186 if (loss_p->lm_counter_size > BCM_OAM_LM_COUNTER_MAX) { 13187 return BCM_E_PARAM; 13188 } 13189 13190 if ((loss_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) && 13191 !(loss_p->flags & BCM_OAM_LOSS_SLM)) { 13192 /* DLM + DM not supported */ 13193 return BCM_E_PARAM; 13194 } 13195 13196 /* ILM, only possible action is Increment */ 13197 if ((loss_p->flags & BCM_OAM_LOSS_SLM)) { 13198 for(i = 0; i < loss_p->lm_counter_size; i++) { 13199 if (loss_p->lm_counter_action[i] != bcmOamCounterActionIncrement) { 13200 return BCM_E_PARAM; 13201 } 13202 } 13203 } else { /* DLM, exactly one sample action must be present */ 13204 for(i = 0; i < loss_p->lm_counter_size; i++) { 13205 if (loss_p->lm_counter_action[i] == bcmOamCounterActionSample) { 13206 num_sample_action++; 13207 } 13208 } 13209 if (num_sample_action != 1) { 13210 return BCM_E_PARAM; 13211 } 13212 } 13213 13214 if (ep->flags & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED) { 13215 if (loss_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) { 13216 if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED)) { 13217 /* Delay created without COMBINED flag, reject loss add with 13218 * COMBINED flag 13219 */ 13220 return BCM_E_PARAM; 13221 } 13222 } else { 13223 if (ep->flags & SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED) { 13224 /* Delay created with COMBINED flag, reject loss add without 13225 * COMBINED flag 13226 */ 13227 return BCM_E_PARAM; 13228 } 13229 } 13230 } 13231 13232 /* Validate period */ 13233 BCM_IF_ERROR_RETURN(_bcm_fp_oam_mpls_lm_dm_period_validate(loss_p->period)); 13234 13235 /* Set internal flags */ 13236 if (loss_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) { 13237 lm_int_flags |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED; 13238 lm_int_flags |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM_DM; 13239 ach = SHR_MPLS_LM_DM_ACH_TYPE_ILM_DM; 13240 } else if (loss_p->flags & BCM_OAM_LOSS_SLM) { 13241 lm_int_flags |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM; 13242 ach = SHR_MPLS_LM_DM_ACH_TYPE_ILM; 13243 } else { 13244 lm_int_flags |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DLM; 13245 ach = SHR_MPLS_LM_DM_ACH_TYPE_DLM; 13246 } 13247 13248 /* Active or passive mode */ 13249 if (!(loss_p->flags & BCM_OAM_LOSS_TX_ENABLE)) { 13250 lm_int_flags |= SHR_MPLS_LM_DM_PASSIVE_FLAG; 13251 } 13252 13253 /* Single or dual ended mode */ 13254 if (loss_p->flags & BCM_OAM_LOSS_SINGLE_ENDED) { 13255 lm_int_flags |= SHR_MPLS_LM_DM_SINGLE_ENDED_FLAG; 13256 } 13257 13258 /* Copy user given values */ 13259 ep->lm_exp = loss_p->pkt_pri; 13260 ep->lm_int_pri = loss_p->int_pri; 13261 13262 13263 for(i = 0; i < loss_p->lm_counter_size; i++) { 13264 ep->lm_ctr_base_id[i] = loss_p->lm_counter_base_id[i]; 13265 ep->lm_ctr_offset[i] = loss_p->lm_counter_offset[i]; 13266 ep->lm_ctr_action[i] = loss_p->lm_counter_action[i]; 13267 } 13268 ep->lm_ctr_size = loss_p->lm_counter_size; 13269 13270 /* Construct the message */ 13271 sal_memset(&msg, 0, sizeof(msg)); 13272 msg.sess_id = _MPLS_LM_DM_EP_ID_TO_SESS_ID(loss_p->id); 13273 msg.flags = lm_int_flags; 13274 msg.period = loss_p->period; 13275 msg.session_id = ep->hw_base_session_id; 13276 msg.session_num_entries = ep->session_num_entries; 13277 13278 /* Create packet encap */ 13279 BCM_IF_ERROR_RETURN( 13280 _bcm_fp_oam_mpls_lm_dm_encap_create(unit, ep, 13281 msg.l2_encap_data, 13282 &(msg.l2_encap_length), 13283 ach, ep->lm_exp)); 13284 13285 /* Create OLP encap */ 13286 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 13287 BCM_IF_ERROR_RETURN(_bcm_esw_glp_construct(unit, BCM_TRUNK_INVALID, my_modid, 13288 CMIC_PORT(unit), &cpu_dglp)); 13289 BCM_IF_ERROR_RETURN(_bcm_olp_l2_hdr_get(unit, cpu_dglp, 0, &olp_l2_hdr)); 13290 13291 cur_ptr = _bcm_fp_oam_olp_l2_header_pack(msg.olp_encap_data, &olp_l2_hdr); 13292 13293 /* Construct OLP OAM header */ 13294 sal_memset(&olp_oam_hdr, 0, sizeof(olp_oam_hdr)); 13295 SOC_OLP_TX_PORT(&olp_oam_hdr) = BCM_GPORT_MODPORT_PORT_GET(ep->tx_gport); 13296 SOC_OLP_TX_MODID(&olp_oam_hdr) = BCM_GPORT_MODPORT_MODID_GET(ep->tx_gport); 13297 13298 /* Pack counter information in OLP header */ 13299 for (i=0; i< ep->lm_ctr_size; i++) { 13300 _bcm_esw_stat_get_counter_id_info(unit, ep->lm_ctr_base_id[i], 13301 &ctr_group, &ctr_object, 13302 &ctr_mode, &ctr_pool, 13303 &base_index); 13304 if (i == 0) { 13305 SOC_OLP_TX_CTR1_ID(&olp_oam_hdr) = 13306 SOC_OLP_TX_CTR(ctr_pool, base_index + ep->lm_ctr_offset[i]); 13307 SOC_OLP_TX_CTR1_ACTION(&olp_oam_hdr) = ep->lm_ctr_action[i]; 13308 SOC_OLP_TX_CTR1_LOCATION(&olp_oam_hdr) = 1; /* Egress */ 13309 13310 } else if (i == 1) { 13311 SOC_OLP_TX_CTR2_ID_SET(&olp_oam_hdr, 13312 SOC_OLP_TX_CTR(ctr_pool, 13313 base_index + 13314 ep->lm_ctr_offset[i])); 13315 SOC_OLP_TX_CTR2_ACTION(&olp_oam_hdr) = ep->lm_ctr_action[i]; 13316 SOC_OLP_TX_CTR2_LOCATION(&olp_oam_hdr) = 1; /* Egress */ 13317 } else if (i == 2) { 13318 SOC_OLP_TX_CTR3_ID_SET(&olp_oam_hdr, 13319 SOC_OLP_TX_CTR(ctr_pool, 13320 base_index + 13321 ep->lm_ctr_offset[i])); 13322 SOC_OLP_TX_CTR3_ACTION(&olp_oam_hdr) = ep->lm_ctr_action[i]; 13323 SOC_OLP_TX_CTR3_LOCATION(&olp_oam_hdr) = 1; /* Egress */ 13324 } 13325 } 13326 SOC_OLP_TX_PRI(&olp_oam_hdr) = ep->lm_int_pri; 13327 13328 /* Set generic repl. offset, BTE will adjust offset if it is LM+DM */ 13329 SOC_OLP_TX_OAM_OFFSET(&olp_oam_hdr) = 13330 ((msg.l2_encap_length + _MPLS_LM_DM_OLP_REPL_OFFSET_DLM - 14) / 2); 13331 13332 /* Pack OLP OAM Encap */ 13333 shr_olp_tx_header_pack(cur_ptr, &olp_oam_hdr); 13334 13335 #if defined(MPLS_LM_DM_DEBUG) 13336 _bcm_fp_oam_mpls_lm_dm_encap_data_dump(msg.olp_encap_data, 13337 MPLS_LM_DM_OLP_HDR_LEN); 13338 #endif /* MPLS_LM_DM_DEBUG */ 13339 /* Send Loss Add message */ 13340 buffer = oc->mpls_lm_dm_dma_buffer; 13341 buffer_len = mpls_lm_dm_sdk_msg_ctrl_loss_add_pack(buffer, &msg) - buffer; 13342 13343 rv = _bcm_fp_oam_msg_send_receive(unit, 13344 MOS_MSG_CLASS_MPLS_LM_DM, 13345 MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_ADD, 13346 buffer_len, 0, 13347 MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_ADD_REPLY, 13348 &reply_len); 13349 13350 if ((BCM_SUCCESS(rv)) && (reply_len != 0)) { 13351 rv = BCM_E_INTERNAL; 13352 } 13353 if (BCM_FAILURE(rv)) { 13354 return rv; 13355 } 13356 13357 ep->flags |= lm_int_flags; 13358 ep->flags |= SHR_MPLS_LM_DM_FLAG_LOSS_ADDED; 13359 13360 return rv; 13361 } 13362 13363 /* 13364 * Function: 13365 * _bcm_fp_oam_mpls_lm_dm_loss_get 13366 * Purpose: 13367 * Get MPLS LM/DM Loss session 13368 * Parameters: 13369 * unit - (IN) BCM device number 13370 * loss_p - (IN) Loss params 13371 * Returns: 13372 * BCM_E_XXX 13373 */ 13374 int 13375 _bcm_fp_oam_mpls_lm_dm_loss_get(uint8 unit, bcm_oam_loss_t *loss_p) 13376 { 13377 _bcm_fp_oam_control_t *oc = NULL; 13378 shr_mpls_lm_dm_msg_ctrl_loss_get_t msg_req; 13379 shr_mpls_lm_dm_msg_ctrl_loss_data_t msg_rsp; 13380 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep; 13381 uint8 *buffer = NULL; 13382 uint16 req_len, rsp_len, reply_len; 13383 uint16 idx; 13384 int rv = 0; 13385 int i = 0; 13386 13387 /* Get OAM control pointer */ 13388 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 13389 13390 /* Validation checks */ 13391 if (!oc->mpls_lm_dm_ukernel_ready) { 13392 return BCM_E_INIT; 13393 } 13394 13395 idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(loss_p->id); 13396 ep = &(oc->mpls_lm_dm_ep_data[idx]); 13397 if (!ep->in_use) { 13398 return BCM_E_PARAM; 13399 } 13400 13401 /* Check if the LM is enabled for this EP */ 13402 if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED)) { 13403 return BCM_E_NOT_FOUND; 13404 } 13405 13406 sal_memset(&msg_req, 0, sizeof(msg_req)); 13407 msg_req.sess_id = _MPLS_LM_DM_EP_ID_TO_SESS_ID(loss_p->id); 13408 13409 buffer = oc->mpls_lm_dm_dma_buffer; 13410 req_len = shr_mpls_lm_dm_msg_ctrl_loss_get_pack(buffer, &msg_req) - buffer; 13411 13412 /* Send Loss GET request */ 13413 rv = _bcm_fp_oam_msg_send_receive(unit, 13414 MOS_MSG_CLASS_MPLS_LM_DM, 13415 MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_GET, 13416 req_len, 0, 13417 MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_GET_REPLY, 13418 &reply_len); 13419 13420 if (BCM_FAILURE(rv)) { 13421 LOG_ERROR(BSL_LS_BCM_OAM, 13422 (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:" 13423 " Loss get Msg failed EP:%d %s.\n"), 13424 unit, loss_p->id, bcm_errmsg(rv))); 13425 return rv; 13426 } 13427 13428 /* Initialize the receive Message structure */ 13429 sal_memset(&msg_rsp, 0, sizeof(msg_rsp)); 13430 13431 /* Unpack loss get data */ 13432 buffer = oc->mpls_lm_dm_dma_buffer; 13433 rsp_len = shr_mpls_lm_dm_msg_ctrl_loss_data_unpack(buffer, &msg_rsp) - buffer; 13434 13435 if (reply_len != rsp_len) { 13436 rv = BCM_E_INTERNAL; 13437 } 13438 13439 /* Copy data from msg_rsp */ 13440 if (msg_rsp.flags & (SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM_DM | 13441 SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM )) { 13442 loss_p->flags |= BCM_OAM_LOSS_SLM; 13443 } 13444 13445 if (!(msg_rsp.flags & SHR_MPLS_LM_DM_PASSIVE_FLAG)) { 13446 loss_p->flags |= BCM_OAM_LOSS_TX_ENABLE; 13447 } 13448 13449 if (msg_rsp.flags & SHR_MPLS_LM_DM_SINGLE_ENDED_FLAG) { 13450 loss_p->flags |= BCM_OAM_LOSS_SINGLE_ENDED; 13451 } 13452 13453 if (msg_rsp.flags & SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED) { 13454 loss_p->flags |= BCM_OAM_COMBINED_LOSS_DELAY; 13455 } 13456 13457 loss_p->period = msg_rsp.period; 13458 loss_p->rx_oam_packets = msg_rsp.rx_oam_packets; 13459 loss_p->tx_oam_packets = msg_rsp.tx_oam_packets; 13460 loss_p->loss_nearend = msg_rsp.loss_nearend; 13461 loss_p->loss_farend = msg_rsp.loss_farend; 13462 loss_p->tx_nearend = msg_rsp.tx_nearend; 13463 loss_p->rx_nearend = msg_rsp.rx_nearend; 13464 loss_p->tx_farend = msg_rsp.tx_farend; 13465 loss_p->rx_farend = msg_rsp.rx_farend; 13466 13467 13468 /* Copy data from local SW copy */ 13469 loss_p->int_pri = ep->lm_int_pri; 13470 loss_p->pkt_pri = ep->lm_exp; 13471 13472 loss_p->lm_counter_size = ep->lm_ctr_size; 13473 for (i=0; i < ep->lm_ctr_size; i++) { 13474 loss_p->lm_counter_base_id[i] = ep->lm_ctr_base_id[i]; 13475 loss_p->lm_counter_offset[i] = ep->lm_ctr_offset[i]; 13476 loss_p->lm_counter_action[i] = ep->lm_ctr_action[i]; 13477 } 13478 13479 loss_p->pm_id = _MPLS_LM_DM_EP_ID_TO_SESS_ID(loss_p->id);; 13480 13481 return rv; 13482 } 13483 13484 /* 13485 * Function: 13486 * _bcm_fp_oam_mpls_lm_dm_loss_delete 13487 * Purpose: 13488 * Deletes MPLS LM/DM Loss session 13489 * Parameters: 13490 * unit - (IN) BCM device number 13491 * loss_p - (IN) Loss params 13492 * Returns: 13493 * BCM_E_XXX 13494 */ 13495 STATIC int 13496 _bcm_fp_oam_mpls_lm_dm_loss_delete(int unit, bcm_oam_endpoint_t id) 13497 { 13498 _bcm_fp_oam_control_t *oc = NULL; 13499 shr_mpls_lm_dm_msg_ctrl_loss_delete_t msg; 13500 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep; 13501 uint8 *buffer = NULL; 13502 uint16 buffer_len, reply_len; 13503 uint16 idx; 13504 int rv = BCM_E_NONE; 13505 int i = 0; 13506 13507 /* Get OAM control pointer */ 13508 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 13509 13510 /* Validation checks */ 13511 if (!oc->mpls_lm_dm_ukernel_ready) { 13512 return BCM_E_INIT; 13513 } 13514 13515 idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(id); 13516 ep = &(oc->mpls_lm_dm_ep_data[idx]); 13517 if (!ep->in_use) { 13518 return BCM_E_PARAM; 13519 } 13520 13521 /* Check if the LM is enabled for this EP */ 13522 if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED)) { 13523 return BCM_E_NOT_FOUND; 13524 } 13525 13526 /* Initialize the Message structure */ 13527 sal_memset(&msg, 0, sizeof(msg)); 13528 msg.sess_id = _MPLS_LM_DM_EP_ID_TO_SESS_ID(id); 13529 13530 /* Send loss delete message */ 13531 buffer = oc->mpls_lm_dm_dma_buffer; 13532 buffer_len = shr_mpls_lm_dm_msg_ctrl_loss_delete_pack(buffer, &msg) - buffer; 13533 13534 rv = _bcm_fp_oam_msg_send_receive(unit, 13535 MOS_MSG_CLASS_MPLS_LM_DM, 13536 MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_DELETE, 13537 buffer_len, 0, 13538 MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_DELETE_REPLY, 13539 &reply_len); 13540 13541 if ((BCM_SUCCESS(rv)) && (reply_len != 0)) { 13542 rv = BCM_E_INTERNAL; 13543 } 13544 if (BCM_FAILURE(rv)) { 13545 return rv; 13546 } 13547 13548 /* Clear the loss data from EP data */ 13549 ep->flags &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DLM); 13550 ep->flags &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM); 13551 ep->flags &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM_DM); 13552 ep->flags &= ~(SHR_MPLS_LM_DM_FLAG_LOSS_ADDED); 13553 13554 if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) { 13555 ep->flags &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED); 13556 } 13557 13558 ep->lm_exp = 0; 13559 ep->lm_int_pri = 0; 13560 for (i = 0; i < ep->lm_ctr_size; i++) { 13561 ep->lm_ctr_base_id[i] = 0; 13562 ep->lm_ctr_offset[i] = 0; 13563 ep->lm_ctr_action[i] = bcmOamCounterActionNone; 13564 } 13565 ep->lm_ctr_size = 0; 13566 13567 return rv; 13568 } 13569 13570 /* 13571 * Function: 13572 * _bcm_fp_oam_mpls_lm_dm_delay_add 13573 * Purpose: 13574 * Create MPLS LM/DM Delay session 13575 * Parameters: 13576 * unit - (IN) BCM device number 13577 * delay_p - (IN) Delay params 13578 * Returns: 13579 * BCM_E_XXX 13580 */ 13581 int 13582 _bcm_fp_oam_mpls_lm_dm_delay_add(uint8 unit, bcm_oam_delay_t *delay_p) 13583 { 13584 _bcm_fp_oam_control_t *oc = NULL; 13585 mpls_lm_dm_sdk_msg_ctrl_delay_add_t msg; 13586 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep; 13587 uint32 ach = 0; 13588 uint32 dm_int_flags = 0; 13589 bcm_module_t my_modid = 0; 13590 bcm_gport_t cpu_dglp; 13591 soc_olp_l2_hdr_t olp_l2_hdr; 13592 soc_olp_tx_hdr_t olp_oam_hdr; 13593 uint8 *buffer, *cur_ptr; 13594 uint16 buffer_len, reply_len; 13595 uint32 ctr_pool; 13596 uint32 ctr_mode; 13597 uint32 base_index; 13598 bcm_stat_group_mode_t ctr_group; 13599 bcm_stat_object_t ctr_object; 13600 uint16 idx; 13601 int rv = BCM_E_NONE; 13602 int i; 13603 13604 13605 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 13606 13607 /* Validation checks */ 13608 if (!oc->mpls_lm_dm_ukernel_ready) { 13609 return BCM_E_INIT; 13610 } 13611 13612 idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(delay_p->id); 13613 ep = &(oc->mpls_lm_dm_ep_data[idx]); 13614 13615 if (!ep->in_use) { 13616 return BCM_E_PARAM; 13617 } 13618 13619 if (delay_p->dm_tx_update_lm_counter_size > BCM_OAM_LM_COUNTER_MAX) { 13620 return BCM_E_PARAM; 13621 } 13622 13623 if (ep->flags & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED) { 13624 if (delay_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) { 13625 if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED)) { 13626 /* Loss created without COMBINED flag, reject delay add with 13627 * COMBINED flag 13628 */ 13629 return BCM_E_PARAM; 13630 } 13631 } else { 13632 if (ep->flags & SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED) { 13633 /* Loss created with COMBINED flag, reject delay add without 13634 * COMBINED flag 13635 */ 13636 return BCM_E_PARAM; 13637 } 13638 } 13639 } 13640 13641 /* Validate period, for combined Loss/Delay period is taken from loss_add */ 13642 if (delay_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) { 13643 BCM_IF_ERROR_RETURN( 13644 _bcm_fp_oam_mpls_lm_dm_period_validate(delay_p->period)); 13645 } 13646 13647 /* Set internal flags */ 13648 if (delay_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) { 13649 /* For combined loss, delay the common flags are derived from loss_add */ 13650 dm_int_flags |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED; 13651 } else { 13652 ach = SHR_MPLS_LM_DM_ACH_TYPE_DM; 13653 13654 dm_int_flags |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DM; 13655 13656 /* Active or passive mode */ 13657 if (!(delay_p->flags & BCM_OAM_DELAY_TX_ENABLE)) { 13658 dm_int_flags |= SHR_MPLS_LM_DM_PASSIVE_FLAG; 13659 } 13660 13661 /* Single or dual ended mode */ 13662 if (!(delay_p->flags & BCM_OAM_DELAY_ONE_WAY)) { 13663 dm_int_flags |= SHR_MPLS_LM_DM_SINGLE_ENDED_FLAG; 13664 } 13665 } 13666 13667 13668 /* Copy user given values */ 13669 ep->dm_exp = delay_p->pkt_pri; 13670 ep->dm_int_pri = delay_p->int_pri; 13671 13672 for(i = 0; i < delay_p->dm_tx_update_lm_counter_size; i++) { 13673 ep->dm_ctr_base_id[i] = delay_p->dm_tx_update_lm_counter_base_id[i]; 13674 ep->dm_ctr_offset[i] = delay_p->dm_tx_update_lm_counter_offset[i]; 13675 } 13676 ep->dm_ctr_size = delay_p->dm_tx_update_lm_counter_size; 13677 13678 /* Construct the message */ 13679 sal_memset(&msg, 0, sizeof(msg)); 13680 msg.flags = dm_int_flags; 13681 msg.sess_id = _MPLS_LM_DM_EP_ID_TO_SESS_ID(delay_p->id); 13682 msg.dm_format = delay_p->timestamp_format; 13683 13684 /* In case of combined loss,delay the rest of the parameters are taken from 13685 * loss_add 13686 */ 13687 if (!(delay_p->flags & BCM_OAM_COMBINED_LOSS_DELAY)) { 13688 msg.period = delay_p->period; 13689 msg.session_id = ep->hw_base_session_id; 13690 msg.session_num_entries = ep->session_num_entries; 13691 13692 /* Create packet encap */ 13693 BCM_IF_ERROR_RETURN( 13694 _bcm_fp_oam_mpls_lm_dm_encap_create(unit, ep, 13695 msg.l2_encap_data, 13696 &(msg.l2_encap_length), 13697 ach, ep->dm_exp)); 13698 /* Create OLP encap */ 13699 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 13700 BCM_IF_ERROR_RETURN(_bcm_esw_glp_construct(unit, BCM_TRUNK_INVALID, 13701 my_modid, CMIC_PORT(unit), 13702 &cpu_dglp)); 13703 BCM_IF_ERROR_RETURN(_bcm_olp_l2_hdr_get(unit, cpu_dglp, 0, &olp_l2_hdr)); 13704 13705 cur_ptr = _bcm_fp_oam_olp_l2_header_pack(msg.olp_encap_data, &olp_l2_hdr); 13706 13707 /* Construct OLP OAM header */ 13708 sal_memset(&olp_oam_hdr, 0, sizeof(olp_oam_hdr)); 13709 SOC_OLP_TX_PORT(&olp_oam_hdr) = BCM_GPORT_MODPORT_PORT_GET(ep->tx_gport); 13710 SOC_OLP_TX_MODID(&olp_oam_hdr)= BCM_GPORT_MODPORT_MODID_GET(ep->tx_gport); 13711 13712 /* Pack counter information in OLP header */ 13713 13714 for (i=0; i< ep->dm_ctr_size; i++) { 13715 _bcm_esw_stat_get_counter_id_info(unit, ep->dm_ctr_base_id[i], 13716 &ctr_group, &ctr_object, 13717 &ctr_mode, &ctr_pool, 13718 &base_index); 13719 if (i == 0) { 13720 SOC_OLP_TX_CTR1_ID(&olp_oam_hdr) = 13721 SOC_OLP_TX_CTR(ctr_pool, base_index + ep->dm_ctr_offset[i]); 13722 SOC_OLP_TX_CTR1_ACTION(&olp_oam_hdr) = 1; /* Increment */ 13723 SOC_OLP_TX_CTR1_LOCATION(&olp_oam_hdr) = 1; /* Egress */ 13724 13725 } 13726 if (i == 1) { 13727 SOC_OLP_TX_CTR2_ID_SET(&olp_oam_hdr, 13728 SOC_OLP_TX_CTR(ctr_pool, 13729 base_index + 13730 ep->dm_ctr_offset[i])); 13731 SOC_OLP_TX_CTR2_ACTION(&olp_oam_hdr) = 1; /* Increment */ 13732 SOC_OLP_TX_CTR2_LOCATION(&olp_oam_hdr) = 1; /* Egress */ 13733 } 13734 if (i == 2) { 13735 SOC_OLP_TX_CTR3_ID_SET(&olp_oam_hdr, 13736 SOC_OLP_TX_CTR(ctr_pool, 13737 base_index + 13738 ep->dm_ctr_offset[i])); 13739 SOC_OLP_TX_CTR3_ACTION(&olp_oam_hdr) = 1; /* Increment */ 13740 SOC_OLP_TX_CTR3_LOCATION(&olp_oam_hdr) = 1; /* Egress */ 13741 } 13742 } 13743 SOC_OLP_TX_PRI(&olp_oam_hdr) = ep->dm_int_pri; 13744 13745 /* Set Sample timestamp action */ 13746 SOC_OLP_TX_TIMESTAMP_ACTION(&olp_oam_hdr) = 13747 ((delay_p->timestamp_format == bcmOAMTimestampFormatNTP) 13748 ? 2:1); 13749 13750 /* Timestamp replacement offset */ 13751 SOC_OLP_TX_OAM_OFFSET(&olp_oam_hdr) = 13752 ((msg.l2_encap_length + _MPLS_LM_DM_OLP_REPL_OFFSET_DM - 14) / 2); 13753 13754 /* Pack OLP OAM Encap */ 13755 shr_olp_tx_header_pack(cur_ptr, &olp_oam_hdr); 13756 } 13757 13758 /* Send Delay Add message */ 13759 buffer = oc->mpls_lm_dm_dma_buffer; 13760 buffer_len = mpls_lm_dm_sdk_msg_ctrl_delay_add_pack(buffer, &msg) - buffer; 13761 13762 rv = _bcm_fp_oam_msg_send_receive(unit, 13763 MOS_MSG_CLASS_MPLS_LM_DM, 13764 MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_ADD, 13765 buffer_len, 0, 13766 MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_ADD_REPLY, 13767 &reply_len); 13768 13769 if ((BCM_SUCCESS(rv)) && (reply_len != 0)) { 13770 rv = BCM_E_INTERNAL; 13771 } 13772 if (BCM_FAILURE(rv)) { 13773 return rv; 13774 } 13775 13776 ep->flags |= dm_int_flags; 13777 ep->flags |= SHR_MPLS_LM_DM_FLAG_DELAY_ADDED; 13778 13779 return rv; 13780 } 13781 13782 /* 13783 * Function: 13784 * _bcm_fp_oam_mpls_lm_dm_delay_get 13785 * Purpose: 13786 * Get MPLS LM/DM Delay session 13787 * Parameters: 13788 * unit - (IN) BCM device number 13789 * delay_p - (IN) Delay params 13790 * Returns: 13791 * BCM_E_XXX 13792 */ 13793 int 13794 _bcm_fp_oam_mpls_lm_dm_delay_get(uint8 unit, bcm_oam_delay_t *delay_p) 13795 { 13796 _bcm_fp_oam_control_t *oc; 13797 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep; 13798 uint8 *buffer; 13799 uint16 reply_len, req_len, rsp_len; 13800 shr_mpls_lm_dm_msg_ctrl_delay_get_t msg_req; 13801 mpls_lm_dm_sdk_msg_ctrl_delay_data_t msg_rsp; 13802 uint16 idx; 13803 int rv = BCM_E_NONE; 13804 int i; 13805 13806 /* Get OAM control pointer */ 13807 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 13808 13809 /* Validation checks */ 13810 if (!oc->mpls_lm_dm_ukernel_ready) { 13811 return BCM_E_INIT; 13812 } 13813 13814 idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(delay_p->id); 13815 ep = &(oc->mpls_lm_dm_ep_data[idx]); 13816 if (!ep->in_use) { 13817 return BCM_E_PARAM; 13818 } 13819 13820 /* Check if DM is enabled for this EP */ 13821 if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) { 13822 return BCM_E_NOT_FOUND; 13823 } 13824 13825 sal_memset(&msg_req, 0, sizeof(msg_req)); 13826 msg_req.sess_id = _MPLS_LM_DM_EP_ID_TO_SESS_ID(delay_p->id); 13827 13828 buffer = oc->mpls_lm_dm_dma_buffer; 13829 req_len = shr_mpls_lm_dm_msg_ctrl_delay_get_pack(buffer, &msg_req) - buffer; 13830 13831 /* Send Delay get request */ 13832 rv = _bcm_fp_oam_msg_send_receive(unit, 13833 MOS_MSG_CLASS_MPLS_LM_DM, 13834 MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_GET, 13835 req_len, 0, 13836 MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_GET_REPLY, 13837 &reply_len); 13838 13839 if (BCM_FAILURE(rv)) { 13840 LOG_ERROR(BSL_LS_BCM_OAM, 13841 (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:" 13842 " Delay get Msg failed EP:%d %s.\n"), 13843 unit, delay_p->id, bcm_errmsg(rv))); 13844 return rv; 13845 } 13846 13847 /* Initialize the receive Message structure */ 13848 sal_memset(&msg_rsp, 0, sizeof(msg_rsp)); 13849 13850 /* Unpack loss get data */ 13851 buffer = oc->mpls_lm_dm_dma_buffer; 13852 rsp_len = mpls_lm_dm_sdk_msg_ctrl_delay_data_unpack(buffer, &msg_rsp) - buffer; 13853 13854 if (reply_len != rsp_len) { 13855 return BCM_E_INTERNAL; 13856 } 13857 13858 if (msg_rsp.flags & SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED) { 13859 delay_p->flags |= BCM_OAM_COMBINED_LOSS_DELAY; 13860 } else { 13861 if (!(msg_rsp.flags & SHR_MPLS_LM_DM_PASSIVE_FLAG)) { 13862 delay_p->flags |= BCM_OAM_DELAY_TX_ENABLE; 13863 } 13864 if (!(msg_rsp.flags & SHR_MPLS_LM_DM_SINGLE_ENDED_FLAG)) { 13865 delay_p->flags |= BCM_OAM_DELAY_ONE_WAY; 13866 } 13867 } 13868 13869 delay_p->period = msg_rsp.period; 13870 delay_p->timestamp_format = msg_rsp.dm_format; 13871 rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->delay), 13872 msg_rsp.delay_seconds, 13873 msg_rsp.delay_nanoseconds); 13874 if (BCM_SUCCESS(rv)) { 13875 rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->txf), 13876 msg_rsp.txf_seconds, 13877 msg_rsp.txf_nanoseconds); 13878 } 13879 if (BCM_SUCCESS(rv)) { 13880 rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->rxf), 13881 msg_rsp.rxf_seconds, 13882 msg_rsp.rxf_nanoseconds); 13883 } 13884 if (BCM_SUCCESS(rv)) { 13885 rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->txb), 13886 msg_rsp.txb_seconds, 13887 msg_rsp.txb_nanoseconds); 13888 } 13889 if (BCM_SUCCESS(rv)) { 13890 rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->rxb), 13891 msg_rsp.rxb_seconds, 13892 msg_rsp.rxb_nanoseconds); 13893 } 13894 if (BCM_FAILURE(rv)) { 13895 return rv; 13896 } 13897 13898 delay_p->rx_oam_packets = msg_rsp.rx_oam_packets; 13899 delay_p->tx_oam_packets = msg_rsp.tx_oam_packets; 13900 13901 /* Copy data from local SW copy */ 13902 delay_p->int_pri = ep->dm_int_pri; 13903 delay_p->pkt_pri = ep->dm_exp; 13904 13905 delay_p->dm_tx_update_lm_counter_size = ep->dm_ctr_size; 13906 for (i=0; i < ep->dm_ctr_size; i++) { 13907 delay_p->dm_tx_update_lm_counter_base_id[i] = ep->dm_ctr_base_id[i]; 13908 delay_p->dm_tx_update_lm_counter_offset[i] = ep->dm_ctr_offset[i]; 13909 } 13910 13911 delay_p->pm_id = _MPLS_LM_DM_EP_ID_TO_SESS_ID(delay_p->id); 13912 13913 return rv; 13914 } 13915 13916 /* 13917 * Function: 13918 * _bcm_fp_oam_mpls_lm_dm_delay_delete 13919 * Purpose: 13920 * Delete MPLS LM/DM Delay session 13921 * Parameters: 13922 * unit - (IN) BCM device number 13923 * delay_p - (IN) Delay params 13924 * Returns: 13925 * BCM_E_XXX 13926 */ 13927 STATIC int 13928 _bcm_fp_oam_mpls_lm_dm_delay_delete(int unit, bcm_oam_endpoint_t id) 13929 { 13930 _bcm_fp_oam_control_t *oc = NULL; 13931 shr_mpls_lm_dm_msg_ctrl_delay_delete_t msg; 13932 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep; 13933 uint8 *buffer = NULL; 13934 uint16 buffer_len, reply_len; 13935 uint16 idx; 13936 int rv = BCM_E_NONE; 13937 int i = 0; 13938 13939 /* Get OAM control pointer */ 13940 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 13941 13942 /* Validation checks */ 13943 if (!oc->mpls_lm_dm_ukernel_ready) { 13944 return BCM_E_INIT; 13945 } 13946 13947 idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(id); 13948 ep = &(oc->mpls_lm_dm_ep_data[idx]); 13949 if (!ep->in_use) { 13950 return BCM_E_PARAM; 13951 } 13952 13953 /* Check if DM is enabled for this EP */ 13954 if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) { 13955 return BCM_E_NOT_FOUND; 13956 } 13957 13958 /* Initialize the Message structure */ 13959 sal_memset(&msg, 0, sizeof(msg)); 13960 msg.sess_id = _MPLS_LM_DM_EP_ID_TO_SESS_ID(id); 13961 13962 /* Send delay delete message */ 13963 buffer = oc->mpls_lm_dm_dma_buffer; 13964 buffer_len = shr_mpls_lm_dm_msg_ctrl_delay_delete_pack(buffer, &msg) - buffer; 13965 13966 rv = _bcm_fp_oam_msg_send_receive(unit, 13967 MOS_MSG_CLASS_MPLS_LM_DM, 13968 MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_DELETE, 13969 buffer_len, 0, 13970 MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_DELETE_REPLY, 13971 &reply_len); 13972 13973 if ((BCM_SUCCESS(rv)) && (reply_len != 0)) { 13974 rv = BCM_E_INTERNAL; 13975 } 13976 if (BCM_FAILURE(rv)) { 13977 return rv; 13978 } 13979 13980 /* Clear the delay data from EP data */ 13981 ep->flags &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DM); 13982 ep->flags &= ~(SHR_MPLS_LM_DM_FLAG_DELAY_ADDED); 13983 13984 if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED)) { 13985 ep->flags &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED); 13986 } 13987 13988 ep->dm_int_pri = 0; 13989 for (i = 0; i < ep->dm_ctr_size; i++) { 13990 ep->dm_ctr_base_id[i] = 0; 13991 ep->dm_ctr_offset[i] = 0; 13992 } 13993 ep->dm_ctr_size = 0; 13994 13995 return rv; 13996 } 13997 13998 /* 13999 * Function: 14000 * _bcm_fp_oam_mpls_lm_dm_appl_callback 14001 * Purpose: 14002 * Update FW BHH appl state 14003 * Parameters: 14004 * unit - (IN) Unit number. 14005 * uC - (IN) core number. 14006 * stage - (IN) core reset stage. 14007 * user_data - (IN) data pointer. 14008 * Returns: 14009 * BCM_E_XXX 14010 * Notes: 14011 */ 14012 14013 int _bcm_fp_oam_mpls_lm_dm_appl_callback(int unit, 14014 int uC, 14015 soc_cmic_uc_shutdown_stage_t stage, 14016 void *user_data) { 14017 _bcm_fp_oam_control_t *oc; 14018 14019 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 14020 _BCM_OAM_LOCK(oc); 14021 oc->mpls_lm_dm_ukernel_ready = 0; 14022 14023 _BCM_OAM_UNLOCK(oc); 14024 14025 return BCM_E_NONE; 14026 } 14027 14028 /* 14029 * Function: 14030 * _bcm_fp_mpls_lm_dm_event_mask_set 14031 * Purpose: 14032 * Set the MPLS_LM_DM Events mask. 14033 * Events are set per BHH module. 14034 * Parameters: 14035 * unit - (IN) Unit number. 14036 * Returns: 14037 * BCM_E_NONE Operation completed successfully 14038 * BCM_E_XXX Operation failed 14039 * Notes: 14040 */ 14041 STATIC int 14042 _bcm_fp_mpls_lm_dm_event_mask_set(int unit) 14043 { 14044 _bcm_fp_oam_control_t *oc; 14045 _bcm_oam_event_handler_t *event_handler_p; 14046 uint16 reply_len; 14047 int rv = BCM_E_NONE; 14048 14049 /* Lock already taken by the calling routine. */ 14050 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 14051 _BCM_OAM_LOCK(oc); 14052 14053 /* Get event mask from all callbacks */ 14054 for (event_handler_p = oc->event_handler_list_p; 14055 event_handler_p != NULL; 14056 event_handler_p = event_handler_p->next_p) { 14057 14058 /* Update MPLS_LM_DM event mask in uKernel */ 14059 if (SHR_BITGET(event_handler_p->event_types.w, 14060 bcmOAMEventMplsLmDmPmCounterRollover)) { 14061 /* Send MPLS_LM_DM Event Mask message to uC */ 14062 rv = _bcm_fp_oam_pm_msg_send_receive(unit, 14063 MOS_MSG_CLASS_MPLS_LM_DM, 14064 MOS_MSG_SUBCLASS_MPLS_LM_DM_EVENT_MASK_SET, 14065 0, MPLS_LM_DM_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER, 14066 MOS_MSG_SUBCLASS_MPLS_LM_DM_EVENT_MASK_SET_REPLY, 14067 &reply_len); 14068 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 14069 rv = BCM_E_INTERNAL; 14070 } 14071 _BCM_OAM_UNLOCK(oc); 14072 return (rv); 14073 } 14074 } 14075 _BCM_OAM_UNLOCK(oc); 14076 return (rv); 14077 } 14078 14079 #endif /* INCLUDE_MPLS_LM_DM */ 14080 /*******************************************************************************/ 14081 /* MPLS LM/DM App specific routines end */ 14082 /*******************************************************************************/ 14083 14084 /*******************************************************************************/ 14085 /* Common routines for BHH & MPLS LM/DM App end */ 14086 /*******************************************************************************/ 14087 14088 /*******************************************************************************/ 14089 /* Common routines for CCM, BHH & MPLS LM/DM App start */ 14090 /*******************************************************************************/ 14091 #if defined (INCLUDE_CCM) || defined (INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 14092 14093 /* 14094 * Function: 14095 * bcm_fp_oam_event_register 14096 * Purpose: 14097 * Register a callback for handling OAM events 14098 * Parameters: 14099 * unit - (IN) BCM device number 14100 * event_types - (IN) The set of OAM events for which the specified 14101 * callback should be called. 14102 * cb - (IN) A pointer to the callback function to call for 14103 * the specified OAM events 14104 * user_data - (IN) Pointer to user data to supply in the callback 14105 * Returns: 14106 * BCM_E_XXX 14107 */ 14108 int 14109 bcm_fp_oam_event_register(int unit, bcm_oam_event_types_t event_types, 14110 bcm_oam_event_cb cb, void *user_data) 14111 { 14112 _bcm_fp_oam_control_t *oc; 14113 _bcm_oam_event_handler_t *event_h_p; 14114 _bcm_oam_event_handler_t *prev_p = NULL; 14115 bcm_oam_event_type_t e_type; 14116 uint32 event_bmp; 14117 int rv = 0; 14118 #if defined (INCLUDE_CCM) 14119 int update_event_mask = 0; 14120 #endif 14121 #if defined (INCLUDE_BHH) 14122 int update_bhh_event_mask = 0; 14123 #endif 14124 #if defined(INCLUDE_MPLS_LM_DM) 14125 int update_mpls_lm_dm_event_mask = 0; 14126 #endif 14127 /* Validate event callback input parameter. */ 14128 if (NULL == cb) { 14129 return (BCM_E_PARAM); 14130 } 14131 14132 /* Check if an event is set for register in the events bitmap. */ 14133 SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, event_bmp); 14134 if (0 == event_bmp) { 14135 /* No events specified. */ 14136 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: " 14137 "No events specified for register.\n"), unit)); 14138 return (BCM_E_PARAM); 14139 } 14140 14141 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 14142 _BCM_OAM_LOCK(oc); 14143 14144 for (event_h_p = oc->event_handler_list_p; event_h_p != NULL; 14145 event_h_p = event_h_p->next_p) { 14146 if (event_h_p->cb == cb) { 14147 break; 14148 } 14149 prev_p = event_h_p; 14150 } 14151 14152 if (NULL == event_h_p) { 14153 14154 _BCM_OAM_ALLOC(event_h_p, _bcm_oam_event_handler_t, 14155 sizeof(_bcm_oam_event_handler_t), "OAM event handler"); 14156 14157 if (NULL == event_h_p) { 14158 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: " 14159 "Event handler alloc failed - %s.\n"), unit, 14160 bcm_errmsg(BCM_E_MEMORY))); 14161 _BCM_OAM_UNLOCK(oc); 14162 return (BCM_E_MEMORY); 14163 } 14164 14165 event_h_p->next_p = NULL; 14166 event_h_p->cb = cb; 14167 event_h_p->user_data = user_data; 14168 14169 SHR_BITCLR_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount); 14170 if (prev_p != NULL) { 14171 prev_p->next_p = event_h_p; 14172 } else { 14173 oc->event_handler_list_p = event_h_p; 14174 } 14175 } 14176 14177 for (e_type = 0; e_type < bcmOAMEventCount; ++e_type) { 14178 if (SHR_BITGET(event_types.w, e_type)) { 14179 #if defined(INCLUDE_BHH) 14180 if(soc_feature(unit, soc_feature_bhh)) { 14181 /* 14182 * BHH events are generated by the uKernel 14183 */ 14184 if ((e_type == bcmOAMEventBHHLBTimeout) || 14185 (e_type == bcmOAMEventBHHLBDiscoveryUpdate) || 14186 (e_type == bcmOAMEventBHHCCMTimeout) || 14187 (e_type == bcmOAMEventBHHCCMTimeoutClear) || 14188 (e_type == bcmOAMEventBHHCCMState) || 14189 (e_type == bcmOAMEventBHHCCMRdi) || 14190 (e_type == bcmOAMEventBHHCCMUnknownMegLevel) || 14191 (e_type == bcmOAMEventBHHCCMUnknownMegId) || 14192 (e_type == bcmOAMEventBHHCCMUnknownMepId) || 14193 (e_type == bcmOAMEventBHHCCMUnknownPeriod) || 14194 (e_type == bcmOAMEventBHHCCMUnknownPriority) || 14195 (e_type == bcmOAMEventBHHCCMRdiClear) || 14196 (e_type == bcmOAMEventBHHCCMUnknownMegLevelClear) || 14197 (e_type == bcmOAMEventBHHCCMUnknownMegIdClear) || 14198 (e_type == bcmOAMEventBHHCCMUnknownMepIdClear) || 14199 (e_type == bcmOAMEventBHHCCMUnknownPeriodClear) || 14200 (e_type == bcmOAMEventBHHCCMUnknownPriorityClear) || 14201 (e_type == bcmOAMEventBhhPmCounterRollover) || 14202 (e_type == bcmOAMEventCsfLos) || 14203 (e_type == bcmOAMEventCsfFdi) || 14204 (e_type == bcmOAMEventCsfRdi) || 14205 (e_type == bcmOAMEventCsfDci)) { 14206 SHR_BITSET(event_h_p->event_types.w, e_type); 14207 oc->event_handler_cnt[e_type] += 1; 14208 update_bhh_event_mask = 1; 14209 continue; 14210 } 14211 } 14212 #endif 14213 14214 #if defined(INCLUDE_CCM) 14215 if(soc_feature(unit, soc_feature_uc_ccm)) { 14216 /* CCM events are generated by the uKernel */ 14217 if ((e_type == bcmOAMEventEndpointPortDown) || 14218 (e_type == bcmOAMEventEndpointPortUp) || 14219 (e_type == bcmOAMEventEndpointInterfaceDown) || 14220 (e_type == bcmOAMEventEndpointInterfaceUp) || 14221 (e_type == bcmOAMEventEndpointInterfaceTesting) || 14222 (e_type == bcmOAMEventEndpointInterfaceUnkonwn) || 14223 (e_type == bcmOAMEventEndpointInterfaceDormant) || 14224 (e_type == bcmOAMEventEndpointInterfaceNotPresent) || 14225 (e_type == bcmOAMEventEndpointInterfaceLLDown) || 14226 (e_type == bcmOAMEventGroupCCMxcon) || 14227 (e_type == bcmOAMEventGroupCCMError) || 14228 (e_type == bcmOAMEventGroupRemote) || 14229 (e_type == bcmOAMEventGroupCCMTimeout) || 14230 (e_type == bcmOAMEventGroupMACStatus) || 14231 (e_type == bcmOAMEventGroupCCMxconClear) || 14232 (e_type == bcmOAMEventGroupCCMErrorClear) || 14233 (e_type == bcmOAMEventGroupRemoteClear) || 14234 (e_type == bcmOAMEventGroupCCMTimeoutClear) || 14235 (e_type == bcmOAMEventGroupMACStatusClear) || 14236 (e_type == bcmOAMEventEndpointCCMTimeout) || 14237 (e_type == bcmOAMEventEndpointCCMTimein) || 14238 (e_type == bcmOAMEventEndpointRemote) || 14239 (e_type == bcmOAMEventEndpointRemoteUp)) { 14240 14241 SHR_BITSET(event_h_p->event_types.w, e_type); 14242 oc->event_handler_cnt[e_type] += 1; 14243 update_event_mask = 1; 14244 continue; 14245 } 14246 } 14247 #endif /* INCLUDE_CCM */ 14248 14249 #if defined(INCLUDE_MPLS_LM_DM) 14250 if (soc_feature(unit, soc_feature_mpls_lm_dm)) { 14251 if ((e_type == bcmOAMEventMplsLmDmPmCounterRollover)) { 14252 /* 14253 * MPLS_LM_DM events are generated by the uKernel 14254 */ 14255 SHR_BITSET(event_h_p->event_types.w, e_type); 14256 oc->event_handler_cnt[e_type] += 1; 14257 update_mpls_lm_dm_event_mask = 1; 14258 continue; 14259 } 14260 } 14261 #endif /* INCLUDE_MPLS_LM_DM */ 14262 } 14263 } 14264 14265 #if defined(INCLUDE_BHH) 14266 if (soc_feature(unit, soc_feature_bhh) && 14267 update_bhh_event_mask) { 14268 /* 14269 * Update BHH Events mask 14270 */ 14271 rv = _bcm_fp_oam_bhh_event_mask_set(unit); 14272 } 14273 #endif /* INCLUDE_BHH */ 14274 14275 #if defined(INCLUDE_CCM) 14276 if ((soc_feature(unit, soc_feature_uc_ccm)) && (update_event_mask)) { 14277 /* Update CCM Events mask */ 14278 rv = _bcm_fp_oam_ccm_event_mask_set(unit); 14279 } 14280 #endif /* INCLUDE_CCM */ 14281 14282 #if defined(INCLUDE_MPLS_LM_DM) 14283 if ((soc_feature(unit, soc_feature_mpls_lm_dm)) && 14284 update_mpls_lm_dm_event_mask) { 14285 /* 14286 * Update MPLS_LM_DM Events mask 14287 */ 14288 rv = _bcm_fp_mpls_lm_dm_event_mask_set(unit); 14289 if (BCM_FAILURE(rv)) { 14290 _BCM_OAM_UNLOCK(oc); 14291 LOG_ERROR(BSL_LS_BCM_OAM, 14292 (BSL_META_U(unit, 14293 "OAM(unit %d) Error: failed to set MPLS LM DM event mask-" 14294 " %s.\n"), unit, bcm_errmsg(rv))); 14295 return (rv); 14296 } 14297 } 14298 #endif /* INCLUDE_MPLS_LM_DM */ 14299 14300 _BCM_OAM_UNLOCK(oc); 14301 return (rv); 14302 } 14303 14304 /* 14305 * Function: 14306 * bcm_fp_oam_event_unregister 14307 * Purpose: 14308 * Unregister event and its callback from the event handler list 14309 * Parameters: 14310 * unit - (IN) BCM device number 14311 * event_types - (IN) The set of OAM events for which the specified 14312 * callback should not be called. 14313 * cb - (IN) A pointer to the callback function to unregister 14314 * from the specified OAM events 14315 * Returns: 14316 * BCM_E_XXX 14317 */ 14318 int 14319 bcm_fp_oam_event_unregister(int unit, bcm_oam_event_types_t event_types, 14320 bcm_oam_event_cb cb) 14321 { 14322 _bcm_fp_oam_control_t *oc; 14323 _bcm_oam_event_handler_t *event_h_p; 14324 _bcm_oam_event_handler_t *prev_p = NULL; 14325 bcm_oam_event_type_t e_type; 14326 uint32 event_bmp; 14327 int rv = 0; 14328 #if defined (INCLUDE_CCM) 14329 int update_event_mask = 0; 14330 #endif 14331 #if defined (INCLUDE_BHH) 14332 int update_bhh_event_mask = 0; 14333 #endif 14334 #if defined(INCLUDE_MPLS_LM_DM) 14335 int update_mpls_lm_dm_event_mask = 0; 14336 #endif 14337 /* Validate event callback input parameter. */ 14338 if (NULL == cb) { 14339 return (BCM_E_PARAM); 14340 } 14341 14342 /* Check if an event is set for unregister in the events bitmap. */ 14343 SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, event_bmp); 14344 if (0 == event_bmp) { 14345 /* No events specified. */ 14346 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: " 14347 "No events specified for unregister.\n"), unit)); 14348 return (BCM_E_PARAM); 14349 } 14350 14351 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 14352 _BCM_OAM_LOCK(oc); 14353 14354 for (event_h_p = oc->event_handler_list_p; event_h_p != NULL; 14355 event_h_p = event_h_p->next_p) { 14356 if (event_h_p->cb == cb) { 14357 break; 14358 } 14359 prev_p = event_h_p; 14360 } 14361 14362 if (NULL == event_h_p) { 14363 _BCM_OAM_UNLOCK(oc); 14364 return (BCM_E_NOT_FOUND); 14365 } 14366 14367 for (e_type = 0; e_type < bcmOAMEventCount; ++e_type) { 14368 if (SHR_BITGET(event_types.w, e_type)) { 14369 #if defined(INCLUDE_BHH) 14370 if(soc_feature(unit, soc_feature_bhh)) { 14371 /* 14372 * BHH events are generated by the uKernel 14373 */ 14374 if ((e_type == bcmOAMEventBHHLBTimeout) || 14375 (e_type == bcmOAMEventBHHLBDiscoveryUpdate) || 14376 (e_type == bcmOAMEventBHHCCMTimeout) || 14377 (e_type == bcmOAMEventBHHCCMTimeoutClear) || 14378 (e_type == bcmOAMEventBHHCCMState) || 14379 (e_type == bcmOAMEventBHHCCMRdi) || 14380 (e_type == bcmOAMEventBHHCCMUnknownMegLevel) || 14381 (e_type == bcmOAMEventBHHCCMUnknownMegId) || 14382 (e_type == bcmOAMEventBHHCCMUnknownMepId) || 14383 (e_type == bcmOAMEventBHHCCMUnknownPeriod) || 14384 (e_type == bcmOAMEventBHHCCMUnknownPriority) || 14385 (e_type == bcmOAMEventBHHCCMRdiClear) || 14386 (e_type == bcmOAMEventBHHCCMUnknownMegLevelClear) || 14387 (e_type == bcmOAMEventBHHCCMUnknownMegIdClear) || 14388 (e_type == bcmOAMEventBHHCCMUnknownMepIdClear) || 14389 (e_type == bcmOAMEventBHHCCMUnknownPeriodClear) || 14390 (e_type == bcmOAMEventBHHCCMUnknownPriorityClear) || 14391 (e_type == bcmOAMEventBhhPmCounterRollover)) { 14392 SHR_BITCLR(event_h_p->event_types.w, e_type); 14393 oc->event_handler_cnt[e_type] -= 1; 14394 update_bhh_event_mask = 1; 14395 continue; 14396 } 14397 } 14398 #endif 14399 14400 #if defined(INCLUDE_CCM) 14401 if(soc_feature(unit, soc_feature_uc_ccm)) { 14402 /* CCM events are generated by the uKernel */ 14403 if ((e_type == bcmOAMEventEndpointPortDown) || 14404 (e_type == bcmOAMEventEndpointPortUp) || 14405 (e_type == bcmOAMEventEndpointInterfaceDown) || 14406 (e_type == bcmOAMEventEndpointInterfaceUp) || 14407 (e_type == bcmOAMEventEndpointInterfaceTestingToUp) || 14408 (e_type == bcmOAMEventEndpointInterfaceUnknownToUp) || 14409 (e_type == bcmOAMEventEndpointInterfaceDormantToUp) || 14410 (e_type == bcmOAMEventEndpointInterfaceNotPresentToUp) || 14411 (e_type == bcmOAMEventEndpointInterfaceLLDownToUp) || 14412 (e_type == bcmOAMEventEndpointInterfaceTesting) || 14413 (e_type == bcmOAMEventEndpointInterfaceUnkonwn) || 14414 (e_type == bcmOAMEventEndpointInterfaceDormant) || 14415 (e_type == bcmOAMEventEndpointInterfaceNotPresent) || 14416 (e_type == bcmOAMEventEndpointInterfaceLLDown) || 14417 (e_type == bcmOAMEventGroupCCMxcon) || 14418 (e_type == bcmOAMEventGroupCCMError) || 14419 (e_type == bcmOAMEventGroupRemote) || 14420 (e_type == bcmOAMEventGroupCCMTimeout) || 14421 (e_type == bcmOAMEventEndpointCCMTimeout) || 14422 (e_type == bcmOAMEventEndpointCCMTimein) || 14423 (e_type == bcmOAMEventEndpointRemote) || 14424 (e_type == bcmOAMEventEndpointRemoteUp)) { 14425 14426 SHR_BITCLR(event_h_p->event_types.w, e_type); 14427 oc->event_handler_cnt[e_type] -= 1; 14428 update_event_mask = 1; 14429 continue; 14430 } 14431 } 14432 #endif /* INCLUDE_CCM */ 14433 14434 #if defined(INCLUDE_MPLS_LM_DM) 14435 if (soc_feature(unit, soc_feature_mpls_lm_dm)) { 14436 if ((e_type == bcmOAMEventMplsLmDmPmCounterRollover)) { 14437 /* 14438 * MPLS_LM_DM events are generated by the uKernel 14439 */ 14440 SHR_BITCLR(event_h_p->event_types.w, e_type); 14441 oc->event_handler_cnt[e_type] -= 1; 14442 update_mpls_lm_dm_event_mask = 1; 14443 continue; 14444 } 14445 } 14446 #endif /* INCLUDE_MPLS_LM_DM */ 14447 } 14448 } 14449 SHR_BITTEST_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount, event_bmp); 14450 14451 if (0 == event_bmp) { 14452 14453 if (NULL != prev_p) { 14454 14455 prev_p->next_p = event_h_p->next_p; 14456 14457 } else { 14458 14459 oc->event_handler_list_p = event_h_p->next_p; 14460 14461 } 14462 sal_free(event_h_p); 14463 } 14464 14465 #if defined(INCLUDE_BHH) 14466 if (soc_feature(unit, soc_feature_bhh) && 14467 update_bhh_event_mask) { 14468 /* 14469 * Update BHH Events mask 14470 */ 14471 rv = _bcm_fp_oam_bhh_event_mask_set(unit); 14472 } 14473 #endif /* INCLUDE_BHH */ 14474 14475 #if defined(INCLUDE_CCM) 14476 if ((soc_feature(unit, soc_feature_uc_ccm)) && (update_event_mask)) { 14477 /* Update CCM Events mask */ 14478 rv = _bcm_fp_oam_ccm_event_mask_set(unit); 14479 } 14480 #endif /* INCLUDE_CCM */ 14481 14482 #if defined(INCLUDE_MPLS_LM_DM) 14483 if ((soc_feature(unit, soc_feature_mpls_lm_dm)) && 14484 update_mpls_lm_dm_event_mask) { 14485 /* 14486 * Update MPLS_LM_DM Events mask 14487 */ 14488 rv = _bcm_fp_mpls_lm_dm_event_mask_set(unit); 14489 if (BCM_FAILURE(rv)) { 14490 _BCM_OAM_UNLOCK(oc); 14491 LOG_ERROR(BSL_LS_BCM_OAM, 14492 (BSL_META_U(unit, 14493 "OAM(unit %d) Error: failed to set MPLS LM DM event mask-" 14494 " %s.\n"), unit, bcm_errmsg(rv))); 14495 return (rv); 14496 } 14497 } 14498 #endif /* INCLUDE_MPLS_LM_DM */ 14499 14500 _BCM_OAM_UNLOCK(oc); 14501 return (rv); 14502 } 14503 14504 /* 14505 * Function: 14506 * _bcm_fp_oam_resource_count_init 14507 * Purpose: 14508 * Retrieves and initializes endpoint count information for this device. 14509 * Parameters: 14510 * unit - (IN) BCM unit number. 14511 * oc - (IN) Pointer to device OAM control structure. 14512 * Retruns: 14513 * BCM_E_XXX 14514 */ 14515 STATIC int 14516 _bcm_fp_oam_resource_count_init(int unit, _bcm_fp_oam_control_t *oc) 14517 { 14518 /* Input parameter check. */ 14519 if (NULL == oc) { 14520 return (BCM_E_PARAM); 14521 } 14522 14523 #if defined(INCLUDE_CCM) 14524 if (soc_feature(unit, soc_feature_uc_ccm)) { 14525 /* 14526 * Get endpoint firmware table index count values and 14527 * initialize device OAM control structure members variables. 14528 */ 14529 oc->mep_count = soc_property_get(unit, spn_OAM_CCM_MAX_MEPS, 256); 14530 oc->group_count = soc_property_get(unit, spn_OAM_CCM_MAX_GROUPS, 256); 14531 } 14532 #endif /* INCLUDE_CCM */ 14533 #if defined(INCLUDE_BHH) 14534 if (soc_feature(unit, soc_feature_bhh)) { 14535 14536 /* Get SOC properties for BHH */ 14537 oc->bhh_endpoint_count = soc_property_get(unit, spn_BHH_NUM_SESSIONS, 128); 14538 oc->bhh_base_group_id = soc_property_get(unit, spn_BHH_BASE_GROUP_ID, 256); 14539 oc->bhh_base_endpoint_id = soc_property_get(unit, spn_BHH_BASE_ENDPOINT_ID, 14540 512); 14541 } 14542 #endif /* INCLUDE_BHH */ 14543 14544 return (BCM_E_NONE); 14545 } 14546 14547 /* 14548 * Function: 14549 * _bcm_fp_oam_control_free 14550 * Purpose: 14551 * Free OAM control structure resources allocated by this unit. 14552 * Parameters: 14553 * unit - (IN) BCM unit number. 14554 * oc - (IN) Pointer to OAM control structure. 14555 * Retruns: 14556 * BCM_E_XXX 14557 */ 14558 STATIC int 14559 _bcm_fp_oam_control_free(int unit, _bcm_fp_oam_control_t *oc) 14560 { 14561 _fp_oam_control[unit] = NULL; 14562 14563 #if defined(INCLUDE_BHH) 14564 int status = 0; 14565 #endif 14566 14567 if (NULL == oc) { 14568 /* Module already un-initialized */ 14569 return (BCM_E_NONE); 14570 } 14571 14572 /* Free protection mutex */ 14573 if (NULL != oc->oc_lock) { 14574 sal_mutex_destroy(oc->oc_lock); 14575 oc->oc_lock = NULL; 14576 } 14577 14578 /* Destory group indices list */ 14579 if (NULL != oc->group_pool) { 14580 shr_idxres_list_destroy(oc->group_pool); 14581 oc->group_pool = NULL; 14582 } 14583 14584 /* Free group memory. */ 14585 if (NULL != oc->group_data) { 14586 sal_free(oc->group_data); 14587 oc->group_data = NULL; 14588 } 14589 14590 /* Destroy LMEP indices list */ 14591 if (NULL != oc->mep_pool) { 14592 shr_idxres_list_destroy(oc->mep_pool); 14593 oc->mep_pool = NULL; 14594 } 14595 14596 /* Free LMEP memory. */ 14597 if (NULL != oc->mep_data) { 14598 sal_free(oc->mep_data); 14599 } 14600 #if 0 14601 /* Free hash data storage memory */ 14602 if (NULL != oc->oam_hash_data) { 14603 sal_free(oc->oam_hash_data); 14604 } 14605 #endif 14606 #if defined(INCLUDE_BHH) 14607 /* Free BHH hash data storage memory */ 14608 if (NULL != oc->bhh_ep_data) { 14609 sal_free(oc->bhh_ep_data); 14610 } 14611 /* Destory endpoint hash table. */ 14612 if (NULL != oc->bhh_mep_htbl) { 14613 status = shr_htb_destroy(&oc->bhh_mep_htbl, NULL); 14614 if (BCM_FAILURE(status)) { 14615 LOG_ERROR(BSL_LS_BCM_OAM, 14616 (BSL_META_U(unit, 14617 "Freeing bhh_mep_htbl failed\n"))); 14618 } 14619 } 14620 /* Free BHH group memory. */ 14621 if (NULL != oc->bhh_group_data) { 14622 sal_free(oc->bhh_group_data); 14623 } 14624 /* Destroy BHH EP indices list */ 14625 if (NULL != oc->bhh_pool) { 14626 shr_idxres_list_destroy(oc->bhh_pool); 14627 oc->bhh_pool = NULL; 14628 } 14629 /* Free BHH DMA buffer */ 14630 if (NULL != oc->bhh_dma_buffer) { 14631 soc_cm_sfree(oc->unit, oc->bhh_dma_buffer); 14632 } 14633 /* Free BHH reply DMA buffer */ 14634 if (NULL != oc->bhh_dmabuf_reply) { 14635 soc_cm_sfree(oc->unit, oc->bhh_dmabuf_reply); 14636 } 14637 if (soc_feature(unit, soc_feature_oam_pm)) { 14638 if (_BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc)) { 14639 soc_cm_sfree(oc->unit, oc->pm_bhh_dma_buffer); 14640 } 14641 } 14642 #endif 14643 14644 #if defined(INCLUDE_MPLS_LM_DM) 14645 if (NULL != oc->mpls_lm_dm_dma_buffer) { 14646 soc_cm_sfree(oc->unit, oc->mpls_lm_dm_dma_buffer); 14647 oc->mpls_lm_dm_dma_buffer = NULL; 14648 } 14649 14650 if (NULL != oc->mpls_lm_dm_pool) { 14651 shr_idxres_list_destroy(oc->mpls_lm_dm_pool); 14652 oc->mpls_lm_dm_pool = NULL; 14653 } 14654 14655 if (NULL != oc->mpls_lm_dm_ep_data) { 14656 sal_free(oc->mpls_lm_dm_ep_data); 14657 oc->mpls_lm_dm_ep_data = NULL; 14658 } 14659 #endif /* INCLUDE_MPLS_LM_DM */ 14660 14661 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 14662 if (soc_feature(unit, soc_feature_oam_pm)) { 14663 if (pm_profile_control[unit]) { 14664 sal_free(pm_profile_control[unit]); 14665 pm_profile_control[unit] = NULL; 14666 } 14667 } 14668 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */ 14669 14670 /* Free OAM control structure memory. */ 14671 sal_free(oc); 14672 oc = NULL; 14673 14674 return (BCM_E_NONE); 14675 14676 } 14677 14678 14679 /* 14680 * Function: 14681 * bcm_fp_oam_detach 14682 * Purpose: 14683 * Shut down OAM subsystem 14684 * Parameters: 14685 * unit - (IN) BCM device number 14686 * Returns: 14687 * BCM_E_XXX 14688 */ 14689 int 14690 bcm_fp_oam_detach(int unit) 14691 { 14692 int rv = 0; 14693 _bcm_fp_oam_control_t *oc = NULL; 14694 #if defined(INCLUDE_CCM) || defined(INCLUDE_BHH) 14695 uint16 reply_len; 14696 #endif /* INCLUDE_CCM || INCLUDE_BHH */ 14697 14698 /* Get OAM Control Structure. */ 14699 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 14700 14701 /* Stop CCM Event Thread */ 14702 #if defined(INCLUDE_CCM) 14703 if (soc_feature(unit, soc_feature_uc_ccm)) { 14704 if (oc->ccm_ukernel_ready) { 14705 /* Event Handler thread exit signal */ 14706 sal_usecs_t timeout = sal_time_usecs() + 5000000; 14707 while (NULL != oc->event_thread_id) { 14708 soc_cmic_uc_msg_receive_cancel(unit, oc->ccm_uc_num, 14709 MOS_MSG_CLASS_CCM_EVENT); 14710 14711 if (sal_time_usecs() < timeout) { 14712 /*give some time to already running CCM callback thread 14713 * to schedule and exit */ 14714 sal_usleep(10000); 14715 } else { 14716 /*timeout*/ 14717 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 14718 "CCM event thread did not exit.\n"))); 14719 _BCM_OAM_UNLOCK(oc); 14720 return BCM_E_INTERNAL; 14721 } 14722 } 14723 14724 if (!SOC_WARM_BOOT(unit)) { 14725 /* 14726 * Send CCM Uninit message to uC 14727 * Ignore error since that may indicate uKernel was reloaded. 14728 */ 14729 rv = _bcm_fp_oam_msg_send_receive(unit, 14730 MOS_MSG_CLASS_CCM, 14731 MOS_MSG_SUBCLASS_CCM_UNINIT, 14732 0, 0, 14733 MOS_MSG_SUBCLASS_CCM_UNINIT_REPLY, 14734 &reply_len); 14735 if (BCM_SUCCESS(rv) && (reply_len != 0)) { 14736 if (NULL != oc->oc_lock) { 14737 _BCM_OAM_UNLOCK(oc); 14738 } 14739 return BCM_E_INTERNAL; 14740 } else { 14741 if ((rv == BCM_E_TIMEOUT) || (rv == BCM_E_INIT)) { 14742 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(unit, "CCM: " 14743 "Uninit error - %s\n"), bcm_errmsg(rv))); 14744 rv = BCM_E_NONE; 14745 } 14746 } 14747 } 14748 } 14749 } 14750 #endif /* INCLUDE_CCM */ 14751 14752 14753 /* Stop BHH Event Thread */ 14754 #if defined(INCLUDE_BHH) 14755 if (soc_feature(unit, soc_feature_bhh)) { 14756 int uc_status; 14757 if (oc->ukernel_not_ready == 0) { 14758 /* 14759 * Event Handler thread exit signal 14760 */ 14761 sal_usecs_t timeout = sal_time_usecs() + 5000000; 14762 while (NULL != oc->bhh_event_thread_id) { 14763 soc_cmic_uc_msg_receive_cancel(unit, oc->bhh_uc_num, 14764 MOS_MSG_CLASS_BHH_EVENT); 14765 14766 if (sal_time_usecs() < timeout) { 14767 /*give some time to already running bhh callback thread 14768 * to schedule and exit */ 14769 sal_usleep(10000); 14770 } else { 14771 /*timeout*/ 14772 LOG_ERROR(BSL_LS_BCM_OAM, 14773 (BSL_META_U(unit, 14774 "BHH event thread did not exit.\n"))); 14775 return BCM_E_INTERNAL; 14776 } 14777 } 14778 if (!SOC_WARM_BOOT(unit)) { 14779 /* 14780 * Send BHH Uninit message to uC 14781 */ 14782 SOC_IF_ERROR_RETURN(soc_uc_status(unit, oc->bhh_uc_num, &uc_status)); 14783 if (uc_status) { 14784 rv = _bcm_fp_oam_msg_send_receive(unit, 14785 MOS_MSG_CLASS_BHH, 14786 MOS_MSG_SUBCLASS_BHH_UNINIT, 14787 0, 0, 14788 MOS_MSG_SUBCLASS_BHH_UNINIT_REPLY, 14789 &reply_len); 14790 if (BCM_SUCCESS(rv) && (reply_len != 0)) { 14791 LOG_ERROR(BSL_LS_BCM_OAM, 14792 (BSL_META_U(unit, 14793 "BHH UNINIT failed - error %s\n"), 14794 bcm_errmsg(rv))); 14795 return BCM_E_INTERNAL; 14796 } 14797 } 14798 /* Ignore timeout/init error since that may indicate 14799 * uKernel was reloaded/msging is not up.*/ 14800 if ((rv == BCM_E_TIMEOUT) || (rv == BCM_E_INIT)) { 14801 LOG_DEBUG(BSL_LS_BCM_OAM, 14802 (BSL_META_U(unit, 14803 "BHH UNINIT failed - %s\n"), 14804 bcm_errmsg(rv))); 14805 rv = BCM_E_NONE; 14806 } 14807 14808 } 14809 } 14810 14811 } 14812 #endif /* INCLUDE_BHH */ 14813 14814 #if defined(INCLUDE_MPLS_LM_DM) 14815 if (soc_feature(unit, soc_feature_mpls_lm_dm)) { 14816 rv = _bcm_fp_oam_mpls_lm_dm_detach(unit); 14817 if (rv != BCM_E_NONE) { 14818 LOG_ERROR(BSL_LS_BCM_OAM, 14819 (BSL_META_U(unit, 14820 "MPLS LM/DM UNINIT failed - error %s\n"), 14821 bcm_errmsg(rv))); 14822 } 14823 } 14824 #endif /* INCLUDE_MPLS_LM_DM */ 14825 14826 14827 _bcm_fp_oam_control_free(unit, oc); 14828 return rv; 14829 } 14830 14831 /* 14832 * Function: 14833 * bcm_fp_oam_endpoint_create 14834 * Purpose: 14835 * Create or replace an OAM endpoint object 14836 * Parameters: 14837 * unit - (IN) BCM device number 14838 * endpoint_info - (IN/OUT) Pointer to endpoint information buffer. 14839 * Returns: 14840 * BCM_E_XXX 14841 */ 14842 int 14843 bcm_fp_oam_endpoint_create(int unit, bcm_oam_endpoint_info_t *endpoint_info) 14844 { 14845 int rv = BCM_E_PARAM; 14846 14847 #if defined (INCLUDE_CCM) 14848 if (soc_feature(unit, soc_feature_uc_ccm) && 14849 (endpoint_info->type == bcmOAMEndpointTypeEthernet)) { 14850 rv = bcm_fp_oam_ccm_endpoint_create(unit, endpoint_info); 14851 } 14852 #endif 14853 14854 #if defined (INCLUDE_BHH) 14855 if (soc_feature(unit, soc_feature_bhh) && 14856 BHH_EP_TYPE (endpoint_info)){ 14857 rv = _bcm_fp_oam_bhh_endpoint_create (unit, endpoint_info); 14858 } 14859 #endif 14860 14861 #if defined(INCLUDE_MPLS_LM_DM) 14862 if (soc_feature(unit, soc_feature_mpls_lm_dm)) { 14863 if (_MPLS_LM_DM_ENDPOINT_TYPE(endpoint_info->type)) { 14864 rv = _bcm_fp_oam_mpls_lm_dm_endpoint_create(unit, endpoint_info); 14865 } 14866 } 14867 #endif /* INCLUDE_MPLS_LM_DM */ 14868 return rv; 14869 } 14870 14871 /* 14872 * Function: 14873 * bcm_fp_oam_endpoint_get 14874 * Purpose: 14875 * Fetches an OAM endpoint object 14876 * Parameters: 14877 * unit - (IN) BCM device number 14878 * endpoint - (IN) Endpoint ID to get. 14879 * result =s: 14880 * BCM_E_XXX 14881 */ 14882 int 14883 bcm_fp_oam_endpoint_get(int unit, bcm_oam_endpoint_t endpoint, 14884 bcm_oam_endpoint_info_t *endpoint_info) 14885 { 14886 int rv = BCM_E_PARAM; /* Operation return status */ 14887 _bcm_fp_oam_control_t *oc = NULL; 14888 14889 /* Get OAM control structure handle. */ 14890 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 14891 14892 _BCM_OAM_LOCK(oc); 14893 14894 14895 #if defined (INCLUDE_CCM) 14896 if (soc_feature(unit, soc_feature_uc_ccm) && 14897 ((endpoint >= 0) && (endpoint < oc->mep_count))) { 14898 endpoint_info->id = endpoint; 14899 rv = bcm_fp_oam_ccm_endpoint_get(unit, endpoint_info); 14900 } 14901 #endif 14902 14903 #if defined (INCLUDE_BHH) 14904 if (soc_feature(unit, soc_feature_bhh) && 14905 ((endpoint >= oc->bhh_base_endpoint_id) && 14906 (endpoint < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)))) { 14907 if (oc->ukernel_not_ready == 1){ 14908 LOG_ERROR(BSL_LS_BCM_OAM, 14909 (BSL_META_U(unit, 14910 "OAM(unit %d) Error: BTE(ukernel) " 14911 "not ready.\n"), unit)); 14912 _BCM_OAM_UNLOCK(oc); 14913 return (BCM_E_INIT); 14914 } 14915 endpoint_info->id = endpoint; 14916 rv = _bcm_fp_oam_bhh_endpoint_get(unit, endpoint_info); 14917 } 14918 #endif 14919 14920 #if defined (INCLUDE_MPLS_LM_DM) 14921 if(soc_feature(unit, soc_feature_mpls_lm_dm)) { 14922 if(_MPLS_LM_DM_EP_ID_RANGE(endpoint)) { 14923 rv = _bcm_fp_oam_mpls_lm_dm_endpoint_get(unit, endpoint, 14924 endpoint_info); 14925 } 14926 } 14927 #endif /* INCLUDE_MPLS_LM_DM */ 14928 14929 _BCM_OAM_UNLOCK(oc); 14930 return (rv); 14931 } 14932 14933 /* 14934 * Function: 14935 * bcm_fp_oam_endpoint_destroy 14936 * Purpose: 14937 * Destroy an OAM endpoint object 14938 * Parameters: 14939 * unit - (IN) BCM device number 14940 * endpoint - (IN) Endpoint ID to destroy. 14941 * result =s: 14942 * BCM_E_XXX 14943 */ 14944 int 14945 bcm_fp_oam_endpoint_destroy(int unit, bcm_oam_endpoint_t endpoint) 14946 { 14947 int rv = BCM_E_PARAM; /* Operation return status */ 14948 _bcm_fp_oam_control_t *oc = NULL; 14949 14950 /* Get OAM control structure handle. */ 14951 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 14952 14953 _BCM_OAM_LOCK(oc); 14954 14955 14956 #if defined (INCLUDE_CCM) 14957 if (soc_feature(unit, soc_feature_uc_ccm) && 14958 ((endpoint >= 0) && (endpoint < oc->mep_count))) { 14959 rv = bcm_fp_oam_ccm_endpoint_destroy(unit, endpoint); 14960 } 14961 #endif 14962 14963 #if defined (INCLUDE_BHH) 14964 if (soc_feature(unit, soc_feature_bhh) && 14965 ((endpoint >= oc->bhh_base_endpoint_id) && 14966 (endpoint < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)))) { 14967 if (oc->ukernel_not_ready == 1){ 14968 LOG_ERROR(BSL_LS_BCM_OAM, 14969 (BSL_META_U(unit, 14970 "OAM(unit %d) Error: BTE(ukernel) " 14971 "not ready.\n"), unit)); 14972 _BCM_OAM_UNLOCK(oc); 14973 return (BCM_E_INIT); 14974 } 14975 rv = _bcm_fp_oam_bhh_endpoint_destroy(unit, endpoint); 14976 } 14977 #endif 14978 14979 #if defined (INCLUDE_MPLS_LM_DM) 14980 if(soc_feature(unit, soc_feature_mpls_lm_dm)) { 14981 if(_MPLS_LM_DM_EP_ID_RANGE(endpoint)) { 14982 rv = _bcm_fp_oam_mpls_lm_dm_endpoint_destroy(unit, endpoint); 14983 } 14984 } 14985 #endif /* INCLUDE_MPLS_LM_DM */ 14986 14987 _BCM_OAM_UNLOCK(oc); 14988 return (rv); 14989 } 14990 14991 /* 14992 * Function: 14993 * bcm_fp_oam_endpoint_destroy_all 14994 * Purpose: 14995 * Destroy all OAM endpoint objects associated with a group. 14996 * Parameters: 14997 * unit - (IN) BCM device number 14998 * group - (IN) The OAM group whose endpoints should be destroyed 14999 * Returns: 15000 * BCM_E_XXX 15001 */ 15002 int 15003 bcm_fp_oam_endpoint_destroy_all(int unit, bcm_oam_group_t group) 15004 { 15005 int rv = BCM_E_PARAM; /* Operation return status */ 15006 _bcm_fp_oam_control_t *oc = NULL; 15007 15008 /* Get OAM control structure handle. */ 15009 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 15010 15011 _BCM_OAM_LOCK(oc); 15012 15013 #if defined (INCLUDE_BHH) 15014 if (soc_feature(unit, soc_feature_bhh) && 15015 ((group >= oc->bhh_base_group_id) && 15016 (group < (oc->bhh_base_group_id + oc->bhh_endpoint_count)))) { 15017 if (oc->ukernel_not_ready == 1){ 15018 LOG_ERROR(BSL_LS_BCM_OAM, 15019 (BSL_META_U(unit, 15020 "OAM(unit %d) Error: BTE(ukernel) " 15021 "not ready.\n"), unit)); 15022 _BCM_OAM_UNLOCK(oc); 15023 return (BCM_E_INIT); 15024 } 15025 rv = _bcm_fp_oam_bhh_endpoint_destroy_all(unit, group); 15026 } 15027 #endif 15028 _BCM_OAM_UNLOCK(oc); 15029 15030 return (rv); 15031 } 15032 15033 /* 15034 * Function: 15035 * bcm_fp_oam_endpoint_traverse 15036 * Purpose: 15037 * Traverse the entire set of BHH endpoints associated with BHH group 15038 * and calls specified callback for each one 15039 * Parameters: 15040 * unit - (IN) BCM device number 15041 * cb - (IN) Pointer to call back function. 15042 * user_data - (IN) Pointer to user supplied data. 15043 * Returns: 15044 * BCM_E_XXX 15045 */ 15046 int 15047 bcm_fp_oam_endpoint_traverse(int unit, bcm_oam_group_t group, 15048 bcm_oam_endpoint_traverse_cb cb, 15049 void *user_data) 15050 { int rv = BCM_E_PARAM; /* Operation return status */ 15051 _bcm_fp_oam_control_t *oc = NULL; 15052 15053 /* Get OAM control structure handle. */ 15054 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 15055 15056 _BCM_OAM_LOCK(oc); 15057 #if defined (INCLUDE_CCM) 15058 if (soc_feature(unit, soc_feature_uc_ccm) 15059 && (group > 0 && group <= oc->group_count)) { 15060 if (!oc->ccm_ukernel_ready) { 15061 LOG_ERROR(BSL_LS_BCM_OAM, 15062 (BSL_META_U(unit, 15063 "CCM(unit %d) Error: BTE(ukernel) " 15064 "not ready.\n"), unit)); 15065 _BCM_OAM_UNLOCK(oc); 15066 return (BCM_E_INIT); 15067 } 15068 15069 rv = _bcm_fp_oam_ccm_endpoint_traverse(unit, group, cb,user_data); 15070 15071 if (BCM_FAILURE(rv)) { 15072 LOG_ERROR(BSL_LS_BCM_OAM, 15073 (BSL_META_U(unit, 15074 "CCM(unit %d) Error: Endpoint traverse " 15075 "routine : %s.\n"), unit, bcm_errmsg(rv))); 15076 } 15077 } 15078 #endif 15079 15080 #if defined (INCLUDE_BHH) 15081 if (soc_feature(unit, soc_feature_bhh) && 15082 ((group >= oc->bhh_base_group_id) && 15083 (group < (oc->bhh_base_group_id + oc->bhh_endpoint_count)))) { 15084 if (oc->ukernel_not_ready == 1){ 15085 LOG_ERROR(BSL_LS_BCM_OAM, 15086 (BSL_META_U(unit, 15087 "OAM(unit %d) Error: BTE(ukernel) " 15088 "not ready.\n"), unit)); 15089 _BCM_OAM_UNLOCK(oc); 15090 return (BCM_E_INIT); 15091 } 15092 rv = _bcm_fp_oam_bhh_endpoint_traverse (unit, group, cb, user_data); 15093 } 15094 #endif 15095 _BCM_OAM_UNLOCK(oc); 15096 return (rv); 15097 } 15098 15099 /* 15100 * Function: 15101 * bcm_fp_oam_group_create 15102 * Purpose: 15103 * Create or replace an OAM group object 15104 * Parameters: 15105 * unit - (IN) BCM device number 15106 * group_info - (IN/OUT) Pointer to group information buffer. 15107 * Returns: 15108 * BCM_E_XXX 15109 */ 15110 int 15111 bcm_fp_oam_group_create(int unit, bcm_oam_group_info_t *group_info) 15112 { 15113 int rv = BCM_E_PARAM; 15114 15115 #if defined (INCLUDE_CCM) 15116 if (soc_feature(unit, soc_feature_uc_ccm) && 15117 !(group_info->flags & BCM_OAM_GROUP_TYPE_BHH)) { 15118 rv = bcm_fp_oam_ccm_group_create(unit, group_info); 15119 } 15120 #endif 15121 15122 #if defined (INCLUDE_BHH) 15123 if (soc_feature(unit, soc_feature_bhh) && 15124 (group_info->flags & BCM_OAM_GROUP_TYPE_BHH)) { 15125 rv = _bcm_fp_oam_bhh_group_create (unit, group_info); 15126 } 15127 #endif 15128 return rv; 15129 } 15130 15131 /* 15132 * Function: 15133 * bcm_fp_oam_group_get 15134 * Purpose: 15135 * Fetches an OAM group object 15136 * Parameters: 15137 * unit - (IN) BCM device number 15138 * group - (IN) Group ID to get. 15139 * result =s: 15140 * BCM_E_XXX 15141 */ 15142 int 15143 bcm_fp_oam_group_get(int unit, bcm_oam_group_t group, 15144 bcm_oam_group_info_t *group_info) 15145 { 15146 int rv = BCM_E_PARAM; /* Operation return status */ 15147 _bcm_fp_oam_control_t *oc = NULL; 15148 15149 /* Get OAM control structure handle. */ 15150 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 15151 15152 _BCM_OAM_LOCK(oc); 15153 15154 15155 #if defined (INCLUDE_CCM) 15156 if (soc_feature(unit, soc_feature_uc_ccm) && 15157 ((group >= 0) && (group < oc->group_count))) { 15158 group_info->id = group; 15159 rv = bcm_fp_oam_ccm_group_get(unit, group_info); 15160 } 15161 #endif 15162 15163 #if defined (INCLUDE_BHH) 15164 if (soc_feature(unit, soc_feature_bhh) && 15165 ((group >= oc->bhh_base_group_id) && 15166 (group < (oc->bhh_base_group_id + oc->bhh_endpoint_count)))) { 15167 if (oc->ukernel_not_ready == 1){ 15168 LOG_ERROR(BSL_LS_BCM_OAM, 15169 (BSL_META_U(unit, 15170 "OAM(unit %d) Error: BTE(ukernel) " 15171 "not ready.\n"), unit)); 15172 _BCM_OAM_UNLOCK(oc); 15173 return (BCM_E_INIT); 15174 } 15175 group_info->id = group; 15176 rv = _bcm_fp_oam_bhh_group_get(unit, group_info); 15177 } 15178 #endif 15179 _BCM_OAM_UNLOCK(oc); 15180 return (rv); 15181 } 15182 15183 /* 15184 * Function: 15185 * bcm_fp_oam_group_destroy 15186 * Purpose: 15187 * Destroy an OAM group object 15188 * Parameters: 15189 * unit - (IN) BCM device number 15190 * group - (IN) Group ID to destroy. 15191 * result =s: 15192 * BCM_E_XXX 15193 */ 15194 int 15195 bcm_fp_oam_group_destroy(int unit, bcm_oam_group_t group) 15196 { 15197 int rv = BCM_E_PARAM; /* Operation return status */ 15198 _bcm_fp_oam_control_t *oc = NULL; 15199 15200 /* Get OAM control structure handle. */ 15201 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 15202 15203 _BCM_OAM_LOCK(oc); 15204 15205 15206 #if defined (INCLUDE_CCM) 15207 if (soc_feature(unit, soc_feature_uc_ccm) && 15208 ((group >= 0) && (group < oc->group_count))) { 15209 rv = bcm_fp_oam_ccm_group_destroy(unit, group); 15210 } 15211 #endif 15212 15213 #if defined (INCLUDE_BHH) 15214 if (soc_feature(unit, soc_feature_bhh) && 15215 ((group >= oc->bhh_base_group_id) && 15216 (group < (oc->bhh_base_group_id + oc->bhh_endpoint_count)))) { 15217 if (oc->ukernel_not_ready == 1){ 15218 LOG_ERROR(BSL_LS_BCM_OAM, 15219 (BSL_META_U(unit, 15220 "OAM(unit %d) Error: BTE(ukernel) " 15221 "not ready.\n"), unit)); 15222 _BCM_OAM_UNLOCK(oc); 15223 return (BCM_E_INIT); 15224 } 15225 rv = _bcm_fp_oam_bhh_group_destroy(unit, group); 15226 } 15227 #endif 15228 _BCM_OAM_UNLOCK(oc); 15229 return (rv); 15230 } 15231 15232 /* 15233 * Function: 15234 * bcm_fp_oam_group_destroy_all 15235 * Purpose: 15236 * Destroy all OAM groups 15237 * Parameters: 15238 * unit - (IN) BCM device number 15239 * Returns: 15240 * BCM_E_XXX 15241 */ 15242 int 15243 bcm_fp_oam_group_destroy_all(int unit) 15244 { 15245 int rv = BCM_E_UNAVAIL; /* Operation return status */ 15246 _bcm_fp_oam_control_t *oc = NULL; 15247 15248 /* Get OAM control structure handle. */ 15249 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 15250 15251 _BCM_OAM_LOCK(oc); 15252 15253 #if defined (INCLUDE_BHH) 15254 if (soc_feature(unit, soc_feature_bhh) && 15255 (oc->ukernel_not_ready == 0)){ 15256 rv = _bcm_fp_oam_bhh_group_destroy_all(unit); 15257 } 15258 #endif 15259 _BCM_OAM_UNLOCK(oc); 15260 return (rv); 15261 15262 } 15263 15264 /* 15265 * Function: 15266 * bcm_fp_oam_group_traverse 15267 * Purpose: 15268 * Traverse the entire set of OAM groups, calling a specified 15269 * callback for each one 15270 * Parameters: 15271 * unit - (IN) BCM device number 15272 * cb - (IN) Pointer to call back function. 15273 * user_data - (IN) Pointer to user supplied data. 15274 * Returns: 15275 * BCM_E_XXX 15276 */ 15277 int 15278 bcm_fp_oam_group_traverse(int unit, bcm_oam_group_traverse_cb cb, 15279 void *user_data) 15280 { 15281 int rv = BCM_E_UNAVAIL; /* Operation return status */ 15282 _bcm_fp_oam_control_t *oc = NULL; 15283 15284 /* Get OAM control structure handle. */ 15285 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 15286 15287 _BCM_OAM_LOCK(oc); 15288 #if defined (INCLUDE_CCM) 15289 if (soc_feature(unit, soc_feature_uc_ccm)) { 15290 if (oc->ccm_ukernel_ready) { 15291 rv = _bcm_fp_oam_ccm_group_traverse(unit, cb, user_data); 15292 15293 if (BCM_FAILURE(rv)) { 15294 LOG_ERROR(BSL_LS_BCM_OAM, 15295 (BSL_META_U(unit, 15296 "CCM(unit %d) Error: Group traverse " 15297 "routine : %s.\n"), unit, bcm_errmsg(rv))); 15298 } 15299 } 15300 } 15301 #endif 15302 #if defined (INCLUDE_BHH) 15303 if (soc_feature(unit, soc_feature_bhh) && 15304 (oc->ukernel_not_ready == 0)){ 15305 rv = _bcm_fp_oam_bhh_group_traverse (unit, cb, user_data); 15306 } 15307 #endif 15308 _BCM_OAM_UNLOCK(oc); 15309 return (rv); 15310 15311 } 15312 15313 15314 /* 15315 * Function: 15316 * bcm_fp_oam_loss_add 15317 * Purpose: 15318 * Loss Measurement add 15319 * Parameters: 15320 * unit - Device unit number 15321 * Returns: 15322 * None 15323 */ 15324 int 15325 bcm_fp_oam_loss_add(int unit, bcm_oam_loss_t *loss_p) 15326 { 15327 int rv = BCM_E_UNAVAIL; 15328 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 15329 _bcm_fp_oam_control_t *oc = NULL; 15330 15331 /* Get OAM control structure handle. */ 15332 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 15333 _BCM_OAM_LOCK(oc); 15334 15335 #if defined (INCLUDE_BHH) 15336 if (soc_feature(unit, soc_feature_bhh) && 15337 ((loss_p->id >= oc->bhh_base_endpoint_id) && 15338 (loss_p->id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)))) { 15339 if (oc->ukernel_not_ready == 1){ 15340 LOG_ERROR(BSL_LS_BCM_OAM, 15341 (BSL_META_U(unit, 15342 "OAM(unit %d) Error: BTE(ukernel) " 15343 "not ready.\n"), unit)); 15344 _BCM_OAM_UNLOCK(oc); 15345 return (BCM_E_INIT); 15346 } 15347 rv = _bcm_fp_oam_bhh_loss_add(unit, loss_p); 15348 } 15349 #endif /* INCLUDE_BHH */ 15350 15351 #if defined (INCLUDE_MPLS_LM_DM) 15352 if(soc_feature(unit, soc_feature_mpls_lm_dm)) { 15353 if(_MPLS_LM_DM_EP_ID_RANGE(loss_p->id)) { 15354 rv = _bcm_fp_oam_mpls_lm_dm_loss_add(unit, loss_p); 15355 } 15356 } 15357 #endif /* INCLUDE_MPLS_LM_DM */ 15358 15359 _BCM_OAM_UNLOCK(oc); 15360 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */ 15361 return rv; 15362 } 15363 15364 /* 15365 * Function: 15366 * bcm_fp_oam_loss_get 15367 * Purpose: 15368 * Loss Measurement get 15369 * Parameters: 15370 * unit - Device unit number 15371 * Returns: 15372 * None 15373 */ 15374 int 15375 bcm_fp_oam_loss_get(int unit, bcm_oam_loss_t *loss_p) 15376 { 15377 int rv = BCM_E_UNAVAIL; 15378 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 15379 _bcm_fp_oam_control_t *oc = NULL; 15380 15381 /* Get OAM control structure handle. */ 15382 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 15383 _BCM_OAM_LOCK(oc); 15384 15385 #if defined (INCLUDE_BHH) 15386 if (soc_feature(unit, soc_feature_bhh) && 15387 ((loss_p->id >= oc->bhh_base_endpoint_id) && 15388 (loss_p->id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)))) { 15389 if (oc->ukernel_not_ready == 1){ 15390 LOG_ERROR(BSL_LS_BCM_OAM, 15391 (BSL_META_U(unit, 15392 "OAM(unit %d) Error: BTE(ukernel) " 15393 "not ready.\n"), unit)); 15394 _BCM_OAM_UNLOCK(oc); 15395 return (BCM_E_INIT); 15396 } 15397 rv = _bcm_fp_oam_bhh_loss_get(unit, loss_p); 15398 } 15399 #endif /* INCLUDE_BHH */ 15400 15401 #if defined (INCLUDE_MPLS_LM_DM) 15402 if(soc_feature(unit, soc_feature_mpls_lm_dm)) { 15403 if(_MPLS_LM_DM_EP_ID_RANGE(loss_p->id)) { 15404 rv = _bcm_fp_oam_mpls_lm_dm_loss_get(unit, loss_p); 15405 } 15406 } 15407 #endif /* INCLUDE_MPLS_LM_DM */ 15408 15409 _BCM_OAM_UNLOCK(oc); 15410 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */ 15411 return rv; 15412 } 15413 15414 /* 15415 * Function: 15416 * bcm_fp_oam_loss_delete 15417 * Purpose: 15418 * Loss Measurement Delete 15419 * Parameters: 15420 * unit - Device unit number 15421 * Returns: 15422 * None 15423 */ 15424 int 15425 bcm_fp_oam_loss_delete(int unit, bcm_oam_loss_t *loss_p) 15426 { 15427 int rv = BCM_E_UNAVAIL; 15428 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 15429 _bcm_fp_oam_control_t *oc = NULL; 15430 15431 /* Get OAM control structure handle. */ 15432 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 15433 _BCM_OAM_LOCK(oc); 15434 15435 #if defined (INCLUDE_BHH) 15436 if (soc_feature(unit, soc_feature_bhh) && 15437 ((loss_p->id >= oc->bhh_base_endpoint_id) && 15438 (loss_p->id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)))) { 15439 if (oc->ukernel_not_ready == 1){ 15440 LOG_ERROR(BSL_LS_BCM_OAM, 15441 (BSL_META_U(unit, 15442 "OAM(unit %d) Error: BTE(ukernel) " 15443 "not ready.\n"), unit)); 15444 _BCM_OAM_UNLOCK(oc); 15445 return (BCM_E_INIT); 15446 } 15447 rv = _bcm_fp_oam_bhh_loss_delete(unit, loss_p); 15448 } 15449 #endif /* INCLUDE_BHH */ 15450 15451 #if defined (INCLUDE_MPLS_LM_DM) 15452 if(soc_feature(unit, soc_feature_mpls_lm_dm)) { 15453 if(_MPLS_LM_DM_EP_ID_RANGE(loss_p->id)) { 15454 rv = _bcm_fp_oam_mpls_lm_dm_loss_delete(unit, loss_p->id); 15455 } 15456 } 15457 #endif /* INCLUDE_MPLS_LM_DM */ 15458 15459 _BCM_OAM_UNLOCK(oc); 15460 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */ 15461 return rv; 15462 } 15463 15464 /* 15465 * Function: 15466 * bcm_fp_oam_delay_add 15467 * Purpose: 15468 * Delay Measurement add 15469 * Parameters: 15470 * unit - Device unit number 15471 * Returns: 15472 * None 15473 */ 15474 int 15475 bcm_fp_oam_delay_add(int unit, bcm_oam_delay_t *delay_p) 15476 { 15477 int rv = BCM_E_UNAVAIL; 15478 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 15479 _bcm_fp_oam_control_t *oc = NULL; 15480 15481 /* Get OAM control structure handle. */ 15482 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 15483 _BCM_OAM_LOCK(oc); 15484 15485 #if defined (INCLUDE_BHH) 15486 if (soc_feature(unit, soc_feature_bhh) && 15487 ((delay_p->id >= oc->bhh_base_endpoint_id) && 15488 (delay_p->id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)))) { 15489 if (oc->ukernel_not_ready == 1){ 15490 LOG_ERROR(BSL_LS_BCM_OAM, 15491 (BSL_META_U(unit, 15492 "OAM(unit %d) Error: BTE(ukernel) " 15493 "not ready.\n"), unit)); 15494 _BCM_OAM_UNLOCK(oc); 15495 return (BCM_E_INIT); 15496 } 15497 rv = _bcm_fp_oam_bhh_delay_add(unit, delay_p); 15498 } 15499 #endif /* INCLUDE_BHH */ 15500 15501 #if defined (INCLUDE_MPLS_LM_DM) 15502 if(soc_feature(unit, soc_feature_mpls_lm_dm)) { 15503 if(_MPLS_LM_DM_EP_ID_RANGE(delay_p->id)) { 15504 rv = _bcm_fp_oam_mpls_lm_dm_delay_add(unit, delay_p); 15505 } 15506 } 15507 #endif /* INCLUDE_MPLS_LM_DM */ 15508 15509 _BCM_OAM_UNLOCK(oc); 15510 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */ 15511 return rv; 15512 } 15513 15514 /* 15515 * Function: 15516 * bcm_fp_oam_delay_get 15517 * Purpose: 15518 * Delay Measurements get 15519 * Parameters: 15520 * unit - Device unit number 15521 * Returns: 15522 * None 15523 */ 15524 int 15525 bcm_fp_oam_delay_get(int unit, bcm_oam_delay_t *delay_p) 15526 { 15527 int rv = BCM_E_UNAVAIL; 15528 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 15529 _bcm_fp_oam_control_t *oc = NULL; 15530 15531 /* Get OAM control structure handle. */ 15532 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 15533 _BCM_OAM_LOCK(oc); 15534 15535 #if defined (INCLUDE_BHH) 15536 if (soc_feature(unit, soc_feature_bhh) && 15537 ((delay_p->id >= oc->bhh_base_endpoint_id) && 15538 (delay_p->id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)))) { 15539 if (oc->ukernel_not_ready == 1){ 15540 LOG_ERROR(BSL_LS_BCM_OAM, 15541 (BSL_META_U(unit, 15542 "OAM(unit %d) Error: BTE(ukernel) " 15543 "not ready.\n"), unit)); 15544 _BCM_OAM_UNLOCK(oc); 15545 return (BCM_E_INIT); 15546 } 15547 rv = _bcm_fp_oam_bhh_delay_get(unit, delay_p); 15548 } 15549 #endif /* INCLUDE_BHH */ 15550 15551 #if defined (INCLUDE_MPLS_LM_DM) 15552 if(soc_feature(unit, soc_feature_mpls_lm_dm)) { 15553 if(_MPLS_LM_DM_EP_ID_RANGE(delay_p->id)) { 15554 rv = _bcm_fp_oam_mpls_lm_dm_delay_get(unit, delay_p); 15555 } 15556 } 15557 #endif /* INCLUDE_MPLS_LM_DM */ 15558 15559 _BCM_OAM_UNLOCK(oc); 15560 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */ 15561 return rv; 15562 } 15563 15564 /* 15565 * Function: 15566 * bcm_fp_oam_delay_delete 15567 * Purpose: 15568 * Delay Measurement Delete 15569 * Parameters: 15570 * unit - Device unit number 15571 * Returns: 15572 * None 15573 */ 15574 int 15575 bcm_fp_oam_delay_delete(int unit, bcm_oam_delay_t *delay_p) 15576 { 15577 int rv = BCM_E_UNAVAIL; 15578 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 15579 _bcm_fp_oam_control_t *oc = NULL; 15580 15581 /* Get OAM control structure handle. */ 15582 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 15583 _BCM_OAM_LOCK(oc); 15584 15585 #if defined (INCLUDE_BHH) 15586 if (soc_feature(unit, soc_feature_bhh) && 15587 ((delay_p->id >= oc->bhh_base_endpoint_id) && 15588 (delay_p->id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)))) { 15589 if (oc->ukernel_not_ready == 1){ 15590 LOG_ERROR(BSL_LS_BCM_OAM, 15591 (BSL_META_U(unit, 15592 "OAM(unit %d) Error: BTE(ukernel) " 15593 "not ready.\n"), unit)); 15594 _BCM_OAM_UNLOCK(oc); 15595 return (BCM_E_INIT); 15596 } 15597 rv = _bcm_fp_oam_bhh_delay_delete(unit, delay_p); 15598 } 15599 #endif /* INCLUDE_BHH */ 15600 15601 #if defined (INCLUDE_MPLS_LM_DM) 15602 if(soc_feature(unit, soc_feature_mpls_lm_dm)) { 15603 if(_MPLS_LM_DM_EP_ID_RANGE(delay_p->id)) { 15604 rv = _bcm_fp_oam_mpls_lm_dm_delay_delete(unit, delay_p->id); 15605 } 15606 } 15607 #endif /* INCLUDE_MPLS_LM_DM */ 15608 15609 _BCM_OAM_UNLOCK(oc); 15610 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */ 15611 return rv; 15612 } 15613 15614 /* 15615 * Function: 15616 * _bcm_fp_oam_sync 15617 * Purpose: 15618 * Store OAM configuration to level two storage cache memory. 15619 * Parameters: 15620 * unit - (IN) Device unit number 15621 * Returns: 15622 * BCM_E_XXX 15623 */ 15624 int 15625 _bcm_fp_oam_sync(int unit) 15626 { 15627 int rv = BCM_E_UNAVAIL; 15628 15629 #if defined(BCM_WARM_BOOT_SUPPORT) 15630 #if defined(INCLUDE_BHH) 15631 if (soc_feature(unit, soc_feature_bhh)) { 15632 BCM_IF_ERROR_RETURN(_bcm_fp_oam_bhh_sync(unit)); 15633 } 15634 #endif /* INCLUDE_BHH */ 15635 15636 #if defined(INCLUDE_MPLS_LM_DM) 15637 if (soc_feature(unit, soc_feature_mpls_lm_dm)) { 15638 BCM_IF_ERROR_RETURN(_bcm_fp_oam_mpls_lm_dm_sync(unit)); 15639 } 15640 #endif /* INCLUDE_MPLS_LM_DM */ 15641 #endif /* BCM_WARM_BOOT_SUPPORT */ 15642 15643 return rv; 15644 } 15645 15646 15647 #endif /*INCLUDE_CCM || INCLUDE_BHH || INCLUDE_MPLS_LM_DM */ 15648 /*******************************************************************************/ 15649 /* Common routines for CCM, BHH & MPLS LM/DM App end */ 15650 /*******************************************************************************/ 15651 15652 15653 15654 /* 15655 * Function: bcm_td2p_oam_init 15656 * 15657 * Purpose: 15658 * Initialize OAM module. 15659 * Parameters: 15660 * unit - (IN) BCM device number 15661 * Returns: 15662 * BCM_E_UNIT - Invalid BCM unit number. 15663 * BCM_E_UNAVAIL - OAM not support on this device. 15664 * BCM_E_MEMORY - Allocation failure 15665 * CM_E_XXX - Error code from bcm_XX_oam_init() 15666 * BCM_E_NONE - Success 15667 */ 15668 int 15669 bcm_td2p_oam_init(int unit) 15670 { 15671 int rv; /* Operation return value. */ 15672 #if defined (INCLUDE_CCM) || defined (INCLUDE_BHH) 15673 uint32 size = 0; /* Size of memory allocation. */ 15674 #endif /* INCLUDE_CCM || INCLUDE_BHH */ 15675 15676 #if defined(INCLUDE_CCM) || defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 15677 _bcm_fp_oam_control_t *oc = NULL; /* OAM control structure. */ 15678 #endif /* INCLUDE_CCM || INCLUDE_BHH || INCLUDE_MPLS_LM_DM */ 15679 15680 #if defined (INCLUDE_BHH) 15681 int uc = 0; 15682 uint8 *buffer, *buffer_ptr; 15683 uint16 buffer_len, reply_len; 15684 #endif /* INCLUDE_BHH */ 15685 15686 #if defined (INCLUDE_CCM) || defined (INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 15687 if(soc_feature(unit, soc_feature_uc_ccm) || 15688 soc_feature(unit, soc_feature_bhh) || 15689 soc_feature(unit, soc_feature_mpls_lm_dm)) { 15690 15691 /* Detach first if the module has been previously initialized. */ 15692 if (NULL != _fp_oam_control[unit]) { 15693 _fp_oam_control[unit]->init = FALSE; 15694 rv = bcm_fp_oam_detach(unit); 15695 if (BCM_FAILURE(rv)) { 15696 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 15697 "Module deinit - %s.\n"), bcm_errmsg(rv))); 15698 return (rv); 15699 } 15700 } 15701 15702 15703 /* Allocate OAM control memory for this unit. */ 15704 _BCM_OAM_ALLOC(oc, _bcm_fp_oam_control_t, 15705 sizeof(_bcm_fp_oam_control_t), "OAM control"); 15706 if (NULL == oc) { 15707 return (BCM_E_MEMORY); 15708 } 15709 15710 /* Create protection mutex. */ 15711 oc->oc_lock = sal_mutex_create("oam_control.lock"); 15712 if (NULL == oc->oc_lock) { 15713 _bcm_fp_oam_control_free(unit, oc); 15714 return (BCM_E_MEMORY); 15715 } 15716 15717 /* Set up the unit OAM control structure. */ 15718 _fp_oam_control[unit] = oc; 15719 15720 /* Get number of endpoints and groups supported by this unit. */ 15721 rv = _bcm_fp_oam_resource_count_init(unit, oc); 15722 if (BCM_FAILURE(rv)) { 15723 _bcm_fp_oam_control_free(unit, oc); 15724 return (rv); 15725 } 15726 oc->unit = unit; 15727 15728 } 15729 #endif /* INCLUDE_CCM || INCLUDE_BHH || INCLUDE_MPLS_LM_DM */ 15730 15731 /* Initialize PM */ 15732 #if defined (INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 15733 if (soc_feature(unit, soc_feature_oam_pm)) { 15734 rv = _bcm_fp_oam_pm_init(unit); 15735 if (BCM_FAILURE(rv)) { 15736 _bcm_fp_oam_control_free(unit, oc); 15737 return (rv); 15738 } 15739 } 15740 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */ 15741 15742 #if defined (INCLUDE_CCM) 15743 if(soc_feature(unit, soc_feature_uc_ccm)) { 15744 shr_ccm_msg_ctrl_init_t ccm_init_msg; 15745 uint8 *buffer_p1 = NULL; 15746 uint8 *buffer_p2 = NULL; 15747 uint16 s_len = 0; 15748 uint16 r_len = 0; 15749 15750 15751 /* Core #0 is used for CCM in Saber2*/ 15752 if (soc_uc_in_reset(unit, _CCM_UC_NUM)) { 15753 15754 LOG_WARN(BSL_LS_BCM_OAM, (BSL_META_U(unit, "CCM Warn:" 15755 " uKernel Not Ready, CCM not started.\n If CCM" 15756 " app is not not needed, compile SDK by excluding CCM" 15757 " from FEATURE_LIST.\n"))); 15758 15759 } else { 15760 15761 /* Initialize uController side 15762 * Start CCM application in BTE (Broadcom Task Engine) uController. 15763 * _CCM_UC_NUM runs the CCM Application. 15764 */ 15765 rv = soc_cmic_uc_appl_init(unit, _CCM_UC_NUM, MOS_MSG_CLASS_CCM, 15766 _UC_MSG_TIMEOUT_USECS, _CCM_SDK_VERSION, 15767 _CCM_UC_MIN_VERSION, NULL, NULL); 15768 15769 if (!(BCM_FAILURE(rv))) { 15770 15771 /* Create Group list.*/ 15772 rv = shr_idxres_list_create(&oc->group_pool, 0, 15773 oc->group_count - 1, 15774 0, oc->group_count - 1, "group pool"); 15775 if (BCM_FAILURE(rv)) { 15776 _bcm_fp_oam_control_free(unit, oc); 15777 return (rv); 15778 } 15779 15780 /* Allocate group memory */ 15781 size = sizeof(_bcm_fp_oam_group_data_t) * oc->group_count; 15782 _BCM_OAM_ALLOC(oc->group_data, _bcm_fp_oam_group_data_t, size, 15783 "Group Info"); 15784 if (BCM_FAILURE(rv)) { 15785 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "CCM Error: " 15786 "Group data Alloca failed - %s.\n"), bcm_errmsg(rv))); 15787 _bcm_fp_oam_control_free(unit, oc); 15788 return (rv); 15789 } 15790 15791 /* Create Mep list. */ 15792 rv = shr_idxres_list_create(&oc->mep_pool, 0, oc->mep_count - 1, 15793 0, oc->mep_count - 1, "mep pool"); 15794 if (BCM_FAILURE(rv)) { 15795 _bcm_fp_oam_control_free(unit, oc); 15796 return (rv); 15797 } 15798 15799 /* Allocate group memory */ 15800 size = sizeof(_bcm_fp_oam_mep_data_t) * oc->mep_count; 15801 _BCM_OAM_ALLOC(oc->mep_data, _bcm_fp_oam_mep_data_t, size, 15802 "MEP Info"); 15803 if (BCM_FAILURE(rv)) { 15804 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "CCM Error: " 15805 "MEP data Alloca failed - %s.\n"), bcm_errmsg(rv))); 15806 _bcm_fp_oam_control_free(unit, oc); 15807 return (rv); 15808 } 15809 15810 /* Allocate DMA Memory */ 15811 oc->dma_buffer_len = sizeof(shr_ccm_msg_ctrl_t); 15812 oc->dma_buffer = soc_cm_salloc(unit, oc->dma_buffer_len, 15813 "CCM DMA buffer"); 15814 if (!oc->dma_buffer) { 15815 _bcm_fp_oam_control_free(unit, oc); 15816 return (BCM_E_MEMORY); 15817 } 15818 15819 oc->ccm_ukernel_ready = 1; 15820 oc->ccm_uc_num = _CCM_UC_NUM; 15821 15822 /* Send Initialize CCM App on UKERNEL */ 15823 /* Set control message data */ 15824 sal_memset(&ccm_init_msg, 0, sizeof(ccm_init_msg)); 15825 ccm_init_msg.max_groups = oc->group_count; 15826 ccm_init_msg.max_meps = oc->mep_count; 15827 ccm_init_msg.rx_channel = _CCM_RX_CHANNEL_ID; 15828 15829 /* Pack control message data into DMA buffer */ 15830 buffer_p1 = oc->dma_buffer; 15831 buffer_p2 = shr_ccm_msg_ctrl_init_pack(buffer_p1, &ccm_init_msg); 15832 s_len = buffer_p2 - buffer_p1; 15833 15834 /* Send CCM Init message to uC */ 15835 rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM, 15836 MOS_MSG_SUBCLASS_CCM_INIT, s_len, 0, 15837 MOS_MSG_SUBCLASS_CCM_INIT_REPLY, &r_len); 15838 15839 if (BCM_FAILURE(rv) || (r_len != 0)) { 15840 /* Could not start MPLS_LM_DM appl */ 15841 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 15842 "CCM Session alloc failed\n"))); 15843 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit)); 15844 return rv; 15845 } 15846 15847 /* If we have Warmrebooted, recover S/w state from UKENREL */ 15848 #ifdef BCM_WARM_BOOT_SUPPORT 15849 if (SOC_WARM_BOOT(unit)) { 15850 rv = _bcm_fp_oam_ccm_reinit(unit); 15851 if (BCM_FAILURE(rv)) { 15852 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit)); 15853 return (rv); 15854 } 15855 } 15856 #endif 15857 /* Start event message callback thread */ 15858 if (oc->event_thread_id == NULL) { 15859 oc->event_thread_id = sal_thread_create("bcmCCM", 15860 SAL_THREAD_STKSZ, _FP_OAM_CCM_EVENT_THREAD_PRIO, 15861 _bcm_fp_oam_ccm_callback_thread, (void*)oc); 15862 if (oc->event_thread_id == SAL_THREAD_ERROR) { 15863 oc->event_thread_id = NULL; 15864 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit)); 15865 return (BCM_E_MEMORY); 15866 } 15867 } 15868 15869 } else { 15870 /* Could not start CCM appl */ 15871 LOG_WARN(BSL_LS_BCM_OAM, (BSL_META_U(unit, 15872 "OAM WARN: CCM Application not available\n"))); 15873 /* Most likely core 0 has a different Application image */ 15874 } 15875 } 15876 } /* soc_feature_ccm */ 15877 #endif /* INCLUDE_CCM */ 15878 15879 #if defined (INCLUDE_BHH) 15880 if (soc_feature(unit, soc_feature_bhh)) { 15881 15882 uint8 carrier_code[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; 15883 char *carrier_code_str; 15884 uint32 node_id = 0; 15885 bhh_sdk_msg_ctrl_init_t msg_init; 15886 int priority; 15887 int ukernel_not_ready = 0; 15888 uint8 bhh_consolidate_final_event = 0; 15889 int uc_status; 15890 15891 /* 15892 * Start BHH application in BTE (Broadcom Task Engine) uController, 15893 * if not already running (warm boot). 15894 * Determine which uController is running BHH by choosing the first 15895 * uC that returns successfully. 15896 */ 15897 for (uc = 0; uc < SOC_INFO(unit).num_ucs; uc++) { 15898 rv = soc_uc_status(unit, uc, &uc_status); 15899 if ((rv == SOC_E_NONE) && (uc_status != 0)) { 15900 rv = soc_cmic_uc_appl_init(unit, uc, MOS_MSG_CLASS_BHH, 15901 _BHH_UC_MSG_TIMEOUT_USECS, 15902 BHH_SDK_VERSION, 15903 BHH_UC_MIN_VERSION, _bcm_oam_bhh_appl_callback, NULL); 15904 if (SOC_E_NONE == rv) { 15905 /* BHH started successfully */ 15906 oc->bhh_uc_num = uc; 15907 break; 15908 } 15909 } 15910 } 15911 15912 if (uc >= SOC_INFO(unit).num_ucs) {/* Could not find or start BHH appl */ 15913 ukernel_not_ready = 1; 15914 LOG_ERROR(BSL_LS_BCM_OAM, 15915 (BSL_META_U(unit, 15916 "uKernel Not Ready, bhh not started\n"))); 15917 } 15918 oc->ukernel_not_ready = ukernel_not_ready; 15919 15920 if(ukernel_not_ready == 0){ 15921 /* Create BHH Group list.*/ 15922 /* BHH groups are equalent to BHH endpoints - 1 to 1 mapping*/ 15923 rv = shr_idxres_list_create(&oc->bhh_group_pool, 0, 15924 oc->bhh_endpoint_count - 1, 15925 0, oc->bhh_endpoint_count - 1, "BHH group pool"); 15926 if (BCM_FAILURE(rv)) { 15927 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit)); 15928 return (rv); 15929 } 15930 /* Allocate BHH group memory */ 15931 size = sizeof(_bhh_fp_oam_group_data_t) * oc->bhh_endpoint_count; 15932 _BCM_OAM_ALLOC(oc->bhh_group_data, _bhh_fp_oam_group_data_t, size, 15933 "BHH Group Info"); 15934 15935 if (NULL == oc->bhh_group_data) { 15936 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit)); 15937 return (BCM_E_MEMORY); 15938 } 15939 15940 /* Mem_1: Allocate BHH endpoints hash data memory */ 15941 size = sizeof(_bhh_fp_oam_ep_data_t) * oc->bhh_endpoint_count; 15942 _BCM_OAM_ALLOC(oc->bhh_ep_data, _bhh_fp_oam_ep_data_t, 15943 size, "Hash data"); 15944 if (NULL == oc->bhh_ep_data) { 15945 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit)); 15946 return (BCM_E_MEMORY); 15947 } 15948 /*Calculating hash table size (which should be power of 2) 15949 from the given number of BHH 15950 endpoints to the nearest power of 2*/ 15951 int hash_size = 1; 15952 if (oc->bhh_endpoint_count && !(oc->bhh_endpoint_count & 15953 (oc->bhh_endpoint_count - 1))){ 15954 hash_size = oc->bhh_endpoint_count; 15955 } else { 15956 while (hash_size < oc->bhh_endpoint_count) { 15957 hash_size <<= 1; 15958 } 15959 } 15960 rv = shr_htb_create(&oc->bhh_mep_htbl, hash_size, 15961 sizeof(_bhh_fp_oam_hash_key_t), "BHH MEP Hash"); 15962 if (BCM_FAILURE(rv)) { 15963 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit)); 15964 return (rv); 15965 } 15966 15967 /* Create BHH endpoint indices list. */ 15968 rv = shr_idxres_list_create(&oc->bhh_pool, 0, 15969 oc->bhh_endpoint_count - 1, 15970 0, oc->bhh_endpoint_count - 1, "bhh pool"); 15971 if (BCM_FAILURE(rv)) { 15972 LOG_ERROR(BSL_LS_BCM_OAM, 15973 (BSL_META_U(unit, 15974 "OAM(unit %d) Error: Creating BHH pool " 15975 "failed \n"), 15976 unit)); 15977 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit)); 15978 return (rv); 15979 } 15980 15981 node_id = soc_property_get(unit, spn_BHH_NODE_ID, 0); 15982 bhh_consolidate_final_event = soc_property_get(unit, 15983 spn_BHH_CONSOLIDATED_FINAL_EVENT, 0); 15984 15985 carrier_code_str = soc_property_get_str(unit, spn_BHH_CARRIER_CODE); 15986 if (carrier_code_str != NULL) { 15987 /* 15988 * Note that the carrier code is specified in colon separated 15989 * MAC address format. 15990 */ 15991 if (_shr_parse_macaddr(carrier_code_str, carrier_code) < 0) { 15992 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit)); 15993 return (BCM_E_INTERNAL); 15994 } 15995 } 15996 15997 oc->bhh_max_encap_length = 15998 soc_property_get(unit, 15999 spn_BHH_ENCAP_MAX_LENGTH, 16000 _BCM_OAM_BHH_DEFAULT_ENCAP_LENGTH); 16001 16002 if(oc->bhh_max_encap_length > _BCM_OAM_BHH_MAX_ENCAP_LENGTH) { 16003 LOG_ERROR(BSL_LS_BCM_OAM, 16004 (BSL_META_U(unit, 16005 "Invalid max encap_length=%u\n"), 16006 oc->bhh_max_encap_length)); 16007 return BCM_E_CONFIG; 16008 } 16009 16010 if (soc_feature(unit, soc_feature_oam_pm)) { 16011 rv = _bcm_fp_oam_bhh_pm_init(unit); 16012 if (BCM_FAILURE(rv)) { 16013 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit)); 16014 return (BCM_E_INTERNAL); 16015 } 16016 } 16017 16018 /* 16019 * Allocate DMA buffers 16020 * 16021 * DMA buffer will be used to send and receive 'long' messages 16022 * between SDK Host and uController (BTE). 16023 */ 16024 oc->bhh_dma_buffer_len = sizeof(bhh_sdk_msg_ctrl_t); 16025 oc->bhh_dma_buffer = soc_cm_salloc(unit, oc->bhh_dma_buffer_len, 16026 "BHH DMA buffer"); 16027 if (!oc->bhh_dma_buffer) { 16028 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit)); 16029 LOG_ERROR(BSL_LS_BCM_OAM, 16030 (BSL_META_U(unit, 16031 "OAM(unit %d) Error: Allocating BHH buffer" 16032 " failed \n"), 16033 unit)); 16034 return (BCM_E_MEMORY); 16035 } 16036 sal_memset(oc->bhh_dma_buffer, 0, oc->bhh_dma_buffer_len); 16037 16038 oc->bhh_dmabuf_reply = soc_cm_salloc(unit, sizeof(bhh_sdk_msg_ctrl_t), 16039 "BHH uC reply"); 16040 if (!oc->bhh_dmabuf_reply) { 16041 LOG_ERROR(BSL_LS_BCM_OAM, 16042 (BSL_META_U(unit, 16043 "OAM(unit %d) Error: Allocating BHH reply " 16044 "buffer failed \n"), 16045 unit)); 16046 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit)); 16047 return (BCM_E_MEMORY); 16048 } 16049 sal_memset(oc->bhh_dmabuf_reply, 0, sizeof(bhh_sdk_msg_ctrl_t)); 16050 16051 16052 /* RX DMA channel (0..3) local to the uC */ 16053 oc->rx_channel = BCM_KT_BHH_RX_CHANNEL; 16054 #ifdef BCM_WARM_BOOT_SUPPORT 16055 if (!SOC_WARM_BOOT(unit)) { 16056 rv = _bcm_fp_oam_bhh_scache_alloc(unit); 16057 if ((BCM_E_NOT_FOUND != rv) && (BCM_FAILURE(rv))) { 16058 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit)); 16059 return (rv); 16060 } 16061 #endif 16062 /* Set control message data */ 16063 sal_memset(&msg_init, 0, sizeof(msg_init)); 16064 msg_init.num_sessions = oc->bhh_endpoint_count; 16065 msg_init.rx_channel = oc->rx_channel; 16066 msg_init.node_id = node_id; 16067 sal_memcpy(msg_init.carrier_code, carrier_code, 16068 SHR_BHH_CARRIER_CODE_LEN); 16069 if (soc_feature(unit, soc_feature_oam_pm)) { 16070 msg_init.data_collection_mode = 16071 oc->pm_bhh_lmdm_data_collection_mode; 16072 } 16073 16074 msg_init.max_encap_length = oc->bhh_max_encap_length; 16075 if (bhh_consolidate_final_event) { 16076 msg_init.flags |= BHH_SDK_MSG_CTRL_INIT_ONLY_FINAL_EVENT; 16077 } 16078 /* Pack control message data into DMA buffer */ 16079 buffer = oc->bhh_dma_buffer; 16080 buffer_ptr = bhh_sdk_msg_ctrl_init_pack(unit, buffer, &msg_init); 16081 buffer_len = buffer_ptr - buffer; 16082 16083 /* Send BHH Init message to uC */ 16084 rv = _bcm_fp_oam_msg_send_receive(unit, 16085 MOS_MSG_CLASS_BHH, 16086 MOS_MSG_SUBCLASS_BHH_INIT, 16087 buffer_len, 0, 16088 MOS_MSG_SUBCLASS_BHH_INIT_REPLY, 16089 &reply_len); 16090 16091 if (BCM_FAILURE(rv) || (reply_len != 0)) { 16092 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit)); 16093 LOG_ERROR(BSL_LS_BCM_OAM, 16094 (BSL_META_U(unit, 16095 "OAM(unit %d) Error: BHH init " 16096 "failed \n"), 16097 unit)); 16098 return (BCM_E_INTERNAL); 16099 } 16100 16101 #ifdef BCM_WARM_BOOT_SUPPORT 16102 } else if (SOC_WARM_BOOT(unit)) { 16103 rv = _bcm_fp_oam_bhh_reinit(unit); 16104 if (BCM_FAILURE(rv)) { 16105 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit)); 16106 return (rv); 16107 } 16108 } 16109 #endif 16110 16111 /* 16112 * Start event message callback thread 16113 */ 16114 priority = soc_property_get(unit, spn_BHH_THREAD_PRI, 16115 BHH_THREAD_PRI_DFLT); 16116 16117 if (oc->bhh_event_thread_id == NULL) { 16118 if ((oc->bhh_event_thread_id = 16119 sal_thread_create("bcmBHH", SAL_THREAD_STKSZ, 16120 priority, 16121 _bcm_fp_oam_bhh_callback_thread, 16122 (void*)oc)) == SAL_THREAD_ERROR) { 16123 oc->bhh_event_thread_id = NULL; 16124 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit)); 16125 return (BCM_E_MEMORY); 16126 } 16127 } 16128 } 16129 } 16130 #endif /* INCLUDE_BHH */ 16131 16132 #if defined(INCLUDE_MPLS_LM_DM) 16133 if (soc_feature(unit, soc_feature_mpls_lm_dm)) { 16134 rv = _bcm_fp_oam_mpls_lm_dm_init(unit, oc); 16135 if (rv != BCM_E_NONE) { 16136 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit)); 16137 return rv; 16138 } 16139 } 16140 #endif /* INCLUDE_MPLS_LM_DM */ 16141 16142 #if defined(BCM_WARM_BOOT_SUPPORT) 16143 if (!SOC_WARM_BOOT(unit)) 16144 #endif 16145 { 16146 /* Set default olp header type mapping */ 16147 rv = _bcm_td2p_oam_olp_header_type_mapping_set(unit); 16148 if (BCM_FAILURE(rv)) { 16149 return (rv); 16150 } 16151 16152 /* Enable OLP on HG ports */ 16153 BCM_IF_ERROR_RETURN(_bcm_td2p_oam_hg_olp_enable(unit)); 16154 16155 /* Set Magic port used for remote OLP over HG communication */ 16156 BCM_IF_ERROR_RETURN(_bcm_td2p_oam_olp_magic_port_set(unit)); 16157 16158 #if defined (BCM_APACHE_SUPPORT) 16159 if(SOC_IS_APACHE(unit)) { 16160 BCM_IF_ERROR_RETURN(_bcm_apache_oam_default_hw_config_set(unit)); 16161 } 16162 #endif /* BCM_APACHE_SUPPORT */ 16163 } 16164 return (BCM_E_NONE); 16165 } 16166 16167 #if defined(INCLUDE_CCM) 16168 void 16169 _bcm_fp_oam_ccm_hash_data_dump(int unit, _bcm_fp_oam_mep_data_t *ep_p) 16170 { 16171 LOG_CLI((BSL_META_U(unit,"Flags = 0x%x\r\n"),ep_p->mep_data.flags)); 16172 LOG_CLI((BSL_META_U(unit,"EP ID = %d\r\n"),ep_p->mep_data.ep_id)); 16173 LOG_CLI((BSL_META_U(unit,"Grp id = %d\r\n"),ep_p->mep_data.group_id)); 16174 LOG_CLI((BSL_META_U(unit,"Src Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"), 16175 ep_p->mep_data.sa[0], ep_p->mep_data.sa[1], 16176 ep_p->mep_data.sa[2], ep_p->mep_data.sa[3], 16177 ep_p->mep_data.sa[4], ep_p->mep_data.sa[5])); 16178 LOG_CLI((BSL_META_U(unit,"Dst Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"), 16179 ep_p->mep_data.da[0], ep_p->mep_data.da[1], 16180 ep_p->mep_data.da[2], ep_p->mep_data.da[3], 16181 ep_p->mep_data.da[4], ep_p->mep_data.da[5])); 16182 LOG_CLI((BSL_META_U(unit,"Type = %d\r\n"),ep_p->mep_data.type)); 16183 LOG_CLI((BSL_META_U(unit,"Level = %d\r\n"),ep_p->mep_data.level)); 16184 LOG_CLI((BSL_META_U(unit,"Name = %d\r\n"),ep_p->mep_data.name)); 16185 LOG_CLI((BSL_META_U(unit,"Period = %d\r\n"),ep_p->mep_data.period)); 16186 LOG_CLI((BSL_META_U(unit,"Outer Vlan = %d\r\n"),ep_p->mep_data.vlan)); 16187 LOG_CLI((BSL_META_U(unit,"Inner Vlan = %d\r\n"),ep_p->mep_data.inner_vlan)); 16188 LOG_CLI((BSL_META_U(unit,"pkt pri = 0x%x\r\n"),ep_p->mep_data.pkt_pri)); 16189 LOG_CLI((BSL_META_U(unit,"Inner Vlan Pri = %d\r\n"),ep_p->mep_data.inner_vlan_pri)); 16190 LOG_CLI((BSL_META_U(unit,"Outer TPID = 0x%04X\r\n"),ep_p->mep_data.tpid)); 16191 LOG_CLI((BSL_META_U(unit,"Inner TPID = 0x%04X\r\n"),ep_p->mep_data.inner_tpid)); 16192 LOG_CLI((BSL_META_U(unit,"Gport = %d\r\n"),ep_p->mep_data.gport)); 16193 LOG_CLI((BSL_META_U(unit,"SGLP = %d\r\n"),ep_p->mep_data.sglp)); 16194 LOG_CLI((BSL_META_U(unit,"DGLP = %d\r\n"),ep_p->mep_data.dglp)); 16195 LOG_CLI((BSL_META_U(unit,"Trunk Index = %d\r\n"),ep_p->mep_data.trunk_index)); 16196 LOG_CLI((BSL_META_U(unit,"Faults = %d\r\n"),ep_p->mep_data.faults)); 16197 LOG_CLI((BSL_META_U(unit,"persistent_faults = %d\r\n"), 16198 ep_p->mep_data.persistent_faults)); 16199 LOG_CLI((BSL_META_U(unit,"port_state = %d\r\n"), 16200 ep_p->mep_data.port_state)); 16201 LOG_CLI((BSL_META_U(unit,"intf_state = %d\r\n"), 16202 ep_p->mep_data.intf_state)); 16203 LOG_CLI((BSL_META_U(unit,"num_ctrs = %d\r\n\n"), 16204 ep_p->mep_data.num_ctrs)); 16205 } 16206 #endif /* INCLUDE_CCM */ 16207 16208 #if defined(INCLUDE_MPLS_LM_DM) 16209 void 16210 _bcm_fp_oam_mpls_lm_dm_hash_data_dump(int unit, _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep_p) 16211 { 16212 LOG_CLI((BSL_META_U(unit,"EP ID = %d\r\n"),ep_p->id)); 16213 LOG_CLI((BSL_META_U(unit,"Flags = 0x%x\r\n"),ep_p->flags)); 16214 LOG_CLI((BSL_META_U(unit,"Type = %d\r\n"),ep_p->type)); 16215 LOG_CLI((BSL_META_U(unit,"VCCV_TYPE = %d\r\n"),ep_p->vccv_type)); 16216 LOG_CLI((BSL_META_U(unit,"Gport = %d\r\n"),ep_p->gport)); 16217 LOG_CLI((BSL_META_U(unit,"Tx_Gport = %d\r\n"),ep_p->tx_gport)); 16218 LOG_CLI((BSL_META_U(unit,"Trunk Index = %d\r\n"),ep_p->trunk_index)); 16219 LOG_CLI((BSL_META_U(unit,"Src Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"), 16220 ep_p->src_mac[0], ep_p->src_mac[1], 16221 ep_p->src_mac[2], ep_p->src_mac[3], 16222 ep_p->src_mac[4], ep_p->src_mac[5])); 16223 LOG_CLI((BSL_META_U(unit,"Dst Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"), 16224 ep_p->dst_mac[0], ep_p->dst_mac[1], 16225 ep_p->dst_mac[2], ep_p->dst_mac[3], 16226 ep_p->dst_mac[4], ep_p->dst_mac[5])); 16227 LOG_CLI((BSL_META_U(unit,"Outer Vlan = %d\r\n"),ep_p->outer_vlan)); 16228 LOG_CLI((BSL_META_U(unit,"Outer TPID = 0x%04X\r\n"),ep_p->outer_tpid)); 16229 LOG_CLI((BSL_META_U(unit,"Outer pri = 0x%x\r\n"),ep_p->outer_pri)); 16230 LOG_CLI((BSL_META_U(unit,"Inner Vlan = %d\r\n"),ep_p->inner_vlan)); 16231 LOG_CLI((BSL_META_U(unit,"Inner TPID = 0x%04X\r\n"),ep_p->inner_tpid)); 16232 LOG_CLI((BSL_META_U(unit,"Inner Vlan Pri = %d\r\n"),ep_p->inner_pri)); 16233 16234 LOG_CLI((BSL_META_U(unit,"Session Id = %d\r\n"),ep_p->session_id)); 16235 LOG_CLI((BSL_META_U(unit,"Session num entries = %d\r\n"), 16236 ep_p->session_num_entries)); 16237 LOG_CLI((BSL_META_U(unit,"HW Base Session Id = %d\r\n\n"), 16238 ep_p->hw_base_session_id)); 16239 } 16240 #endif /* INCLUDE_MPLS_LM_DM */ 16241 16242 #if defined(INCLUDE_CCM) || defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 16243 /* 16244 * Function: 16245 * _bcm_fp_oam_sw_dump 16246 * Purpose: 16247 * Displays oam information maintained by software. 16248 * Parameters: 16249 * unit - Device unit number 16250 * Returns: 16251 * None 16252 */ 16253 void 16254 _bcm_fp_oam_sw_dump(int unit) 16255 { 16256 int ep_id; 16257 int rv; 16258 _bcm_fp_oam_control_t *oc; 16259 16260 LOG_CLI((BSL_META_U(unit,"OAM\n"))); 16261 /* Get OAM control structure. */ 16262 rv = _bcm_fp_oam_control_get(unit, &oc); 16263 if(BCM_FAILURE(rv)) { 16264 LOG_ERROR(BSL_LS_BCM_OAM, 16265 (BSL_META_U(unit, 16266 "OAM(unit %d) Error: Get oam control variable\n"), 16267 unit)); 16268 16269 return; 16270 } 16271 16272 #if defined(INCLUDE_CCM) 16273 if ((soc_feature(unit, soc_feature_uc_ccm)) && 16274 (oc->ccm_ukernel_ready)) { 16275 LOG_CLI((BSL_META_U(unit,"CCM EPs data :\n"))); 16276 for(ep_id=0; ep_id < oc->mep_count; ep_id++) { 16277 if (oc->mep_data[ep_id].in_use) { 16278 _bcm_fp_oam_ccm_hash_data_dump(unit, &(oc->mep_data[ep_id])); 16279 } 16280 } 16281 } 16282 #endif /* INCLUDE_CCM */ 16283 16284 #if defined(INCLUDE_MPLS_LM_DM) 16285 if ((soc_feature(unit, soc_feature_mpls_lm_dm)) && 16286 (oc->mpls_lm_dm_ukernel_ready)) { 16287 _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep_p; 16288 LOG_CLI((BSL_META_U(unit,"MPLS LM/DM EPs data :\n"))); 16289 _MPLS_LM_DM_EP_ITER(ep_p, ep_id) { 16290 if (!ep_p->in_use) { 16291 continue; 16292 } 16293 _bcm_fp_oam_mpls_lm_dm_hash_data_dump(unit, ep_p); 16294 } 16295 } 16296 #endif /* INCLUDE_MPLS_LM_DM */ 16297 16298 #if defined (INCLUDE_BHH) 16299 if ((soc_feature(unit, soc_feature_bhh)) && 16300 (oc->ukernel_not_ready == 0)) { 16301 LOG_CLI((BSL_META_U(unit,"BHH EPs data :\n"))); 16302 for(ep_id=0; ep_id < oc->bhh_endpoint_count; ep_id++) { 16303 if (oc->bhh_ep_data[ep_id].in_use) { 16304 _bcm_fp_oam_bhh_hash_data_dump(unit, &oc->bhh_ep_data[ep_id]); 16305 } 16306 } 16307 } 16308 #endif 16309 } 16310 16311 /* 16312 * Function: 16313 * _bcm_fp_oam_port_trunk_update_msg_send 16314 * Purpose: 16315 * Send port to trunk mapping update msg to UKERNEL 16316 * Parameters: 16317 * unit - (IN) BCM device number 16318 * num_ports - number of ports. 16319 * trunk_id - ports map to which trunk_id 16320 * list_of_ports - list of ports 16321 * 16322 * Returns: 16323 * BCM_E_XXX 16324 */ 16325 static int 16326 _bcm_fp_oam_port_trunk_update_msg_send(int unit, uint16 num_ports, 16327 uint16 trunk_id, uint16 *list_of_ports) 16328 { 16329 shr_ccm_msg_ctrl_port_trunk_upd_t upd_msg; 16330 _bcm_fp_oam_control_t *oc = NULL; 16331 uint8 *dma_buffer = NULL; /* DMA buffer */ 16332 uint8 *dma_buffer_ptr = NULL; /* DMA buffer ptr after pack */ 16333 uint16 s_msg_len = 0; /* Send Message length */ 16334 uint16 r_msg_len = 0; /* Msg response length */ 16335 int rv = BCM_E_NONE, index; 16336 16337 /* Get OAM Control Structure. */ 16338 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 16339 16340 /* Clear upd_msg structure */ 16341 sal_memset(&upd_msg, 0, sizeof(upd_msg)); 16342 16343 16344 /* Fill upd_msg structure */ 16345 if (num_ports < MAX_PORTS) { 16346 upd_msg.num_ports = num_ports; 16347 } else { 16348 return BCM_E_PARAM; 16349 } 16350 16351 upd_msg.trunk_id = trunk_id; 16352 16353 for (index = 0; index < num_ports; index++) { 16354 upd_msg.list_of_ports[index] = list_of_ports[index]; 16355 } 16356 16357 16358 /* Pack Update data to buffer */ 16359 dma_buffer = oc->dma_buffer; 16360 dma_buffer_ptr = shr_ccm_msg_ctrl_port_trunk_upd_pack(dma_buffer, &upd_msg); 16361 s_msg_len = dma_buffer_ptr - dma_buffer; 16362 rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM, 16363 MOS_MSG_SUBCLASS_CCM_PORT_TRUNK_UPDATE, s_msg_len, 0, 16364 MOS_MSG_SUBCLASS_CCM_PORT_TRUNK_UPDATE_REPLY, &r_msg_len); 16365 16366 if (BCM_FAILURE(rv)) { 16367 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 16368 "Port trunk update Msg returned error %s.\n"), bcm_errmsg(rv))); 16369 rv = BCM_E_INTERNAL; 16370 } 16371 return (rv); 16372 } 16373 16374 /* 16375 * Function: 16376 * _bcm_fp_oam_port_trunk_map_get 16377 * Purpose: 16378 * Get port to trunk mapping from UKERNEL 16379 * Parameters: 16380 * unit - (IN) BCM device number 16381 * num_ports - number of ports. 16382 * trunk_id - ports map to which trunk_id 16383 * list_of_ports - list of ports 16384 * 16385 * Returns: 16386 * BCM_E_XXX 16387 */ 16388 static int 16389 _bcm_fp_oam_port_trunk_map_get(int unit, uint16 *num_ports, 16390 uint16 trunk_id, uint16 *list_of_ports) 16391 { 16392 shr_ccm_msg_ctrl_port_trunk_upd_t get_msg; 16393 _bcm_fp_oam_control_t *oc = NULL; 16394 uint8 *dma_buffer = NULL; /* DMA buffer */ 16395 uint8 *dma_buffer_ptr = NULL; /* DMA buffer ptr after pack */ 16396 uint16 r_msg_len = 0; /* Msg response length */ 16397 int rv = BCM_E_NONE, index; 16398 16399 /* Get OAM Control Structure. */ 16400 BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc)); 16401 16402 /* Send trunk_id in the send length variable */ 16403 rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM, 16404 MOS_MSG_SUBCLASS_CCM_PORT_TRUNK_GET, trunk_id, 0, 16405 MOS_MSG_SUBCLASS_CCM_PORT_TRUNK_GET_REPLY, &r_msg_len); 16406 16407 if (BCM_FAILURE(rv)) { 16408 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 16409 "Port trunk map get Msg returned error %s.\n"), bcm_errmsg(rv))); 16410 return(BCM_E_INTERNAL); 16411 } 16412 16413 /* Clear get_msg structure */ 16414 sal_memset(&get_msg, 0, sizeof(get_msg)); 16415 16416 /* UnPack control message data in the DMA buffer */ 16417 dma_buffer = oc->dma_buffer; 16418 dma_buffer_ptr = shr_ccm_msg_ctrl_port_trunk_upd_unpack(dma_buffer, &get_msg); 16419 16420 if (r_msg_len != dma_buffer_ptr - dma_buffer) { 16421 rv = BCM_E_INTERNAL; 16422 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 16423 "Trunk map get Msg length check failed, trunk:%d.\n"), trunk_id)); 16424 return (rv); 16425 } 16426 16427 *num_ports = get_msg.num_ports; 16428 16429 for (index = 0; index < *num_ports; index++) { 16430 list_of_ports[index] = get_msg.list_of_ports[index]; 16431 } 16432 16433 return (rv); 16434 } 16435 16436 int 16437 _bcm_fp_oam_trunk_ports_update(int unit, bcm_gport_t trunk_gport, 16438 int max_ports, bcm_gport_t *port_arr, 16439 uint8 delete) 16440 { 16441 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 16442 uint16 *list_of_ports = NULL; 16443 int rv = BCM_E_NONE; 16444 bcm_module_t module_id; 16445 bcm_port_t port_id; 16446 bcm_trunk_t port_trunk_id; 16447 int local_id, result, i; 16448 16449 if (!BCM_GPORT_IS_TRUNK(trunk_gport)) { 16450 return BCM_E_PARAM; 16451 } 16452 16453 if (max_ports >= MAX_PORTS) { 16454 return BCM_E_PARAM; 16455 } 16456 16457 if (!port_arr) { 16458 return BCM_E_PARAM; 16459 } 16460 16461 /* Get trunk_id from gport */ 16462 trunk_id = BCM_GPORT_TRUNK_GET(trunk_gport); 16463 16464 if (trunk_id == BCM_TRUNK_INVALID) { 16465 return BCM_E_PARAM; 16466 } 16467 16468 _BCM_OAM_ALLOC(list_of_ports, uint16, sizeof(uint16) * max_ports , "list of ports"); 16469 16470 for (i = 0; i < max_ports; i++) { 16471 module_id = -1; 16472 port_id = -1; 16473 port_trunk_id = BCM_TRUNK_INVALID; 16474 local_id = -1; 16475 result = FALSE; 16476 16477 /* Get (Modid + Port) value from Gport */ 16478 rv = _bcm_esw_gport_resolve(unit, port_arr[i], 16479 &module_id, &port_id, &port_trunk_id, 16480 &local_id); 16481 if ((BCM_FAILURE(rv)) || 16482 (port_trunk_id != BCM_TRUNK_INVALID)) { 16483 goto cleanup; 16484 } 16485 rv = _bcm_esw_modid_is_local(unit, module_id, &result); 16486 16487 if (BCM_FAILURE(rv)) { 16488 goto cleanup; 16489 } else if (!result) { 16490 /* We will handle only local ports */ 16491 rv = BCM_E_PARAM; 16492 goto cleanup; 16493 } 16494 16495 list_of_ports[i] = port_id; 16496 } 16497 16498 if (delete) { 16499 rv = _bcm_fp_oam_port_trunk_update_msg_send( 16500 unit, max_ports, CCM_INVALID_TRUNK_NUM, list_of_ports); 16501 } else { 16502 rv = _bcm_fp_oam_port_trunk_update_msg_send( 16503 unit, max_ports, trunk_id, list_of_ports); 16504 } 16505 16506 if (BCM_FAILURE(rv)) { 16507 LOG_DEBUG(BSL_LS_BCM_OAM, 16508 (BSL_META_U(unit, 16509 "OAM(unit %d) Error: Trunk map update " 16510 "failed \n"), 16511 unit)); 16512 } 16513 16514 cleanup: 16515 sal_free(list_of_ports); 16516 16517 return rv; 16518 } 16519 16520 int _bcm_fp_oam_trunk_ports_update_trunk_id(int unit, bcm_trunk_t trunk_id) 16521 { 16522 bcm_port_t port_id_list[MAX_PORTS]; 16523 uint16 *list_of_ports = NULL; 16524 int local_member_count = 0, i; 16525 int rv = BCM_E_NONE; 16526 16527 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, trunk_id, MAX_PORTS, 16528 port_id_list, 16529 &local_member_count)); 16530 _BCM_OAM_ALLOC(list_of_ports, uint16, sizeof(uint16) * local_member_count, "list of ports"); 16531 16532 for(i = 0; i < local_member_count; i++) { 16533 list_of_ports[i] = port_id_list[i]; 16534 } 16535 16536 rv = _bcm_fp_oam_port_trunk_update_msg_send(unit, local_member_count, 16537 trunk_id, list_of_ports); 16538 16539 16540 sal_free(list_of_ports); 16541 return rv; 16542 16543 } 16544 16545 /*Add ports (specified by port_arr) to trunk (specified by trunk_gport) mapping 16546 to port-trunk database in OAM */ 16547 int 16548 bcm_fp_oam_trunk_ports_add (int unit, bcm_gport_t trunk_gport, 16549 int max_ports, bcm_gport_t *port_arr) 16550 { 16551 return _bcm_fp_oam_trunk_ports_update(unit, trunk_gport, max_ports, port_arr, 0); 16552 } 16553 16554 /*Delete ports (specified by port_arr) to trunk (specified by trunk_gport) 16555 mapping from port-trunk database in OAM */ 16556 int 16557 bcm_fp_oam_trunk_ports_delete (int unit, bcm_gport_t trunk_gport, 16558 int max_ports, bcm_gport_t *port_arr) 16559 { 16560 return _bcm_fp_oam_trunk_ports_update(unit, trunk_gport, max_ports, port_arr, 1); 16561 } 16562 16563 /*Get ports (in port_arr) that are mapped to trunk (specified by trunk_gport) 16564 from port-trunk database in OAM */ 16565 int 16566 bcm_fp_oam_trunk_ports_get (int unit, bcm_gport_t trunk_gport, 16567 int max_ports, bcm_gport_t *port_arr, 16568 int *port_count) 16569 { 16570 bcm_trunk_t trunk_id = 0; 16571 uint16 *list_of_ports = NULL; 16572 int rv = BCM_E_NONE, i; 16573 bcm_port_t port; 16574 bcm_gport_t gport; 16575 uint16 num_ports = 0; 16576 16577 if (!BCM_GPORT_IS_TRUNK(trunk_gport)) { 16578 return BCM_E_PARAM; 16579 } 16580 16581 if (max_ports >= MAX_PORTS) { 16582 return BCM_E_PARAM; 16583 } 16584 16585 if (!port_arr) { 16586 return BCM_E_PARAM; 16587 } 16588 16589 /* Get trunk_id from gport */ 16590 trunk_id = BCM_GPORT_TRUNK_GET(trunk_gport); 16591 16592 if (trunk_id == BCM_TRUNK_INVALID) { 16593 return BCM_E_PARAM; 16594 } 16595 16596 _BCM_OAM_ALLOC(list_of_ports, uint16, sizeof(uint16) * max_ports , "list of ports"); 16597 16598 16599 rv = _bcm_fp_oam_port_trunk_map_get( 16600 unit, &num_ports, trunk_id, list_of_ports); 16601 16602 16603 if (BCM_FAILURE(rv)) { 16604 LOG_DEBUG(BSL_LS_BCM_OAM, 16605 (BSL_META_U(unit, 16606 "OAM(unit %d) Error: Trunk map get" 16607 "failed \n"), 16608 unit)); 16609 goto cleanup; 16610 } 16611 16612 *port_count = num_ports; 16613 16614 /* If the size of array sent by user is smaller than 16615 * actual number of ports, then reduce the count to 16616 * array size. 16617 */ 16618 if (*port_count > max_ports) { 16619 *port_count = max_ports; 16620 } 16621 16622 for (i = 0; i < *port_count; i++) { 16623 gport = BCM_GPORT_INVALID; 16624 port = list_of_ports[i]; 16625 rv = bcm_esw_port_gport_get(unit, port, &gport); 16626 if (BCM_FAILURE(rv) || gport == BCM_GPORT_INVALID) { 16627 rv = BCM_E_INTERNAL; 16628 goto cleanup; 16629 } 16630 port_arr[i] = gport; 16631 } 16632 16633 16634 cleanup: 16635 sal_free(list_of_ports); 16636 16637 return rv; 16638 } 16639 16640 #endif