failover.c (17152B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * TR3 failover API 8 */ 9 10 #include <soc/defs.h> 11 #include <sal/core/libc.h> 12 13 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3) 14 15 #include <soc/drv.h> 16 #include <soc/mem.h> 17 #include <soc/util.h> 18 #include <soc/debug.h> 19 #include <bcm/types.h> 20 #include <bcm/error.h> 21 #include <bcm_int/esw/mbcm.h> 22 #include <bcm_int/esw_dispatch.h> 23 #include <bcm_int/esw/firebolt.h> 24 #include <bcm_int/esw/triumph2.h> 25 #include <bcm/failover.h> 26 #include <bcm_int/common/multicast.h> 27 #include <bcm_int/esw/multicast.h> 28 #include <bcm_int/esw/failover.h> 29 30 STATIC int 31 _bcm_tr3_failover_nhi_get(int unit, bcm_gport_t port, int *nh_index) 32 { 33 int vp=0xFFFF; 34 ing_dvp_table_entry_t dvp; 35 36 if (!BCM_GPORT_IS_MPLS_PORT(port) && 37 !BCM_GPORT_IS_MIM_PORT(port) ) { 38 return BCM_E_PARAM; 39 } 40 41 if ( BCM_GPORT_IS_MPLS_PORT(port)) { 42 vp = BCM_GPORT_MPLS_PORT_ID_GET(port); 43 } else if ( BCM_GPORT_IS_MIM_PORT(port)) { 44 vp = BCM_GPORT_MIM_PORT_ID_GET(port); 45 } 46 47 if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) { 48 return BCM_E_PARAM; 49 } 50 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 51 52 /* Next-hop index is used for multicast replication */ 53 *nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 54 return BCM_E_NONE; 55 } 56 /* 57 * Function: 58 * bcm_tr3_failover_status_set 59 * Purpose: 60 * Set the parameters for a failover object 61 * Parameters: 62 * IN : unit 63 * IN : failover_id 64 * IN : value 65 * Returns: 66 * BCM_E_XXX 67 */ 68 69 int 70 bcm_tr3_failover_status_set(int unit, bcm_failover_element_t *failover, int value) 71 { 72 int rv = BCM_E_UNAVAIL; 73 int nh_index; 74 initial_prot_group_table_entry_t prot_group_entry; 75 rx_prot_group_table_entry_t rx_prot_group_entry; 76 initial_prot_nhi_table_entry_t prot_nhi_entry; 77 78 if ((value < 0) || (value > 1)) { 79 return BCM_E_PARAM; 80 } 81 82 if (failover->failover_id != BCM_FAILOVER_INVALID) { 83 /* Group protection for Port and Tunnel: Egress and Ingress */ 84 BCM_IF_ERROR_RETURN( 85 bcm_tr2_failover_id_validate ( unit, failover->failover_id )); 86 87 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_GROUP_TABLEm, 88 MEM_BLOCK_ANY, failover->failover_id, &prot_group_entry)); 89 90 soc_mem_field32_set(unit, INITIAL_PROT_GROUP_TABLEm, 91 &prot_group_entry, STATUSf, value); 92 93 BCM_IF_ERROR_RETURN( 94 soc_mem_write(unit, INITIAL_PROT_GROUP_TABLEm, 95 MEM_BLOCK_ALL, failover->failover_id, &prot_group_entry)); 96 97 BCM_IF_ERROR_RETURN (soc_mem_read(unit, RX_PROT_GROUP_TABLEm, 98 MEM_BLOCK_ANY, failover->failover_id, &rx_prot_group_entry)); 99 100 soc_mem_field32_set(unit, RX_PROT_GROUP_TABLEm, 101 &rx_prot_group_entry, DROP_DATA_ENABLEf, value); 102 103 rv = soc_mem_write(unit, RX_PROT_GROUP_TABLEm, 104 MEM_BLOCK_ALL, failover->failover_id, &rx_prot_group_entry); 105 106 }else if (failover->intf != BCM_IF_INVALID) { 107 /* Only Egress is applicable */ 108 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, failover->intf)) { 109 nh_index = failover->intf - BCM_XGS3_EGRESS_IDX_MIN(unit); 110 } else { 111 nh_index = failover->intf - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 112 } 113 114 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLEm, 115 MEM_BLOCK_ANY, nh_index, &prot_nhi_entry)); 116 117 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, 118 &prot_nhi_entry, REPLACE_ENABLEf, value); 119 120 rv = soc_mem_write(unit, INITIAL_PROT_NHI_TABLEm, 121 MEM_BLOCK_ALL, nh_index, &prot_nhi_entry); 122 123 } else if (failover->port != BCM_GPORT_INVALID) { 124 /* Individual protection for Pseudo-wire: Egress and Ingress */ 125 BCM_IF_ERROR_RETURN ( 126 _bcm_tr3_failover_nhi_get(unit, failover->port , &nh_index)); 127 128 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLEm, 129 MEM_BLOCK_ANY, nh_index, &prot_nhi_entry)); 130 131 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, 132 &prot_nhi_entry, REPLACE_ENABLEf, value); 133 134 rv = soc_mem_write(unit, INITIAL_PROT_NHI_TABLEm, 135 MEM_BLOCK_ALL, nh_index, &prot_nhi_entry); 136 137 138 139 } 140 return rv; 141 } 142 143 144 /* 145 * Function: 146 * bcm_tr3_failover_status_get 147 * Purpose: 148 * Get the parameters for a failover object 149 * Parameters: 150 * IN : unit 151 * IN : failover_id 152 * OUT : value 153 * Returns: 154 * BCM_E_XXX 155 */ 156 157 int 158 bcm_tr3_failover_status_get(int unit, bcm_failover_element_t *failover, int *value) 159 { 160 initial_prot_group_table_entry_t prot_group_entry; 161 rx_prot_group_table_entry_t rx_prot_group_entry; 162 initial_prot_nhi_table_entry_t prot_nhi_entry; 163 int nh_index; 164 165 166 if (failover->failover_id != BCM_FAILOVER_INVALID) { 167 168 BCM_IF_ERROR_RETURN( bcm_tr2_failover_id_validate ( unit, failover->failover_id )); 169 170 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_GROUP_TABLEm, 171 MEM_BLOCK_ANY, failover->failover_id, &prot_group_entry)); 172 173 *value = soc_mem_field32_get(unit, INITIAL_PROT_GROUP_TABLEm, 174 &prot_group_entry, STATUSf); 175 176 BCM_IF_ERROR_RETURN (soc_mem_read(unit, RX_PROT_GROUP_TABLEm, 177 MEM_BLOCK_ANY, failover->failover_id, &rx_prot_group_entry)); 178 179 *value &= soc_mem_field32_get(unit, RX_PROT_GROUP_TABLEm, 180 &rx_prot_group_entry, DROP_DATA_ENABLEf); 181 182 }else if (failover->intf != BCM_IF_INVALID) { 183 184 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, failover->intf)) { 185 nh_index = failover->intf - BCM_XGS3_EGRESS_IDX_MIN(unit); 186 } else { 187 nh_index = failover->intf - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 188 } 189 190 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLEm, 191 MEM_BLOCK_ANY, nh_index, &prot_nhi_entry)); 192 193 *value = soc_mem_field32_get(unit, INITIAL_PROT_NHI_TABLEm, 194 &prot_nhi_entry, REPLACE_ENABLEf); 195 196 } else if (failover->port != BCM_GPORT_INVALID) { 197 198 BCM_IF_ERROR_RETURN ( 199 _bcm_tr3_failover_nhi_get(unit, failover->port , &nh_index)); 200 201 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLEm, 202 MEM_BLOCK_ANY, nh_index, &prot_nhi_entry)); 203 204 *value = soc_mem_field32_get(unit, INITIAL_PROT_NHI_TABLEm, 205 &prot_nhi_entry, REPLACE_ENABLEf); 206 207 } 208 return BCM_E_NONE; 209 } 210 211 212 /* 213 * Function: 214 * bcm_tr3_failover_prot_nhi_set 215 * Purpose: 216 * Set the parameters for PROT_NHI 217 * Parameters: 218 * IN : unit 219 * IN : Primary Next Hop Index 220 * IN : Protection Next Hop Index 221 * IN : Failover Group Index 222 * Returns: 223 * BCM_E_XXX 224 */ 225 226 int 227 bcm_tr3_failover_prot_nhi_set(int unit, uint32 flags, int nh_index, uint32 prot_nh_index, 228 bcm_multicast_t mc_group, bcm_failover_t failover_id) 229 { 230 initial_prot_nhi_table_entry_t prot_nhi_entry; 231 int rv; 232 int l3mc_index; 233 234 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLEm, 235 MEM_BLOCK_ANY, nh_index, &prot_nhi_entry)); 236 237 /* if mc_group is valid */ 238 if (_BCM_MULTICAST_IS_SET(mc_group)) { 239 l3mc_index = _BCM_MULTICAST_ID_GET(mc_group); 240 if ((l3mc_index >= 0) && (l3mc_index < soc_mem_index_count(unit, L3_IPMCm))) { 241 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, 242 &prot_nhi_entry, REPLACEMENT_DATAf, 243 l3mc_index); 244 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, 245 &prot_nhi_entry, REPLACEMENT_TYPEf, 246 0x1); 247 } 248 } else { 249 /* if prot_nh_index is valid */ 250 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, 251 &prot_nhi_entry, REPLACEMENT_DATAf, 252 prot_nh_index); 253 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, 254 &prot_nhi_entry, REPLACEMENT_TYPEf, 255 0x0); 256 } 257 258 /* if failover_id is valid */ 259 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, 260 &prot_nhi_entry, PROT_GROUPf, 261 (uint32) failover_id); 262 263 rv = soc_mem_write(unit, INITIAL_PROT_NHI_TABLEm, 264 MEM_BLOCK_ALL, nh_index, &prot_nhi_entry); 265 266 if (rv == SOC_E_NONE && _BCM_FAILOVER_PROT_NHI_MAP_IS_VALID(unit)) { 267 _BCM_FAILOVER_PROT_NHI_MAP_USED_SET(unit, nh_index); 268 } 269 270 return rv; 271 272 } 273 274 275 /* 276 * Function: bcm_tr3_failover_prot_nhi_get 277 * Purpose: 278 * Get the parameters for PROT_NHI 279 * Parameters: 280 * IN : unit 281 * IN : primary Next Hop Index 282 * OUT : Failover Group Index 283 * OUT : Protection Next Hop Index 284 * Returns: 285 * BCM_E_XXX 286 */ 287 288 289 int 290 bcm_tr3_failover_prot_nhi_get(int unit, int nh_index, 291 bcm_failover_t *failover_id, int *prot_nh_index, bcm_multicast_t *mc_group) 292 { 293 initial_prot_nhi_table_entry_t prot_nhi_entry; 294 uint32 replacement_type; 295 int l3mc_index; 296 297 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLEm, 298 MEM_BLOCK_ANY, nh_index, &prot_nhi_entry)); 299 300 *failover_id = soc_mem_field32_get(unit, INITIAL_PROT_NHI_TABLEm, 301 &prot_nhi_entry, PROT_GROUPf); 302 303 replacement_type = soc_mem_field32_get(unit, INITIAL_PROT_NHI_TABLEm, 304 &prot_nhi_entry, REPLACEMENT_TYPEf); 305 306 if (!replacement_type) { 307 *prot_nh_index = soc_mem_field32_get(unit, INITIAL_PROT_NHI_TABLEm, 308 &prot_nhi_entry, REPLACEMENT_DATAf); 309 } else { 310 l3mc_index = soc_mem_field32_get(unit, INITIAL_PROT_NHI_TABLEm, 311 &prot_nhi_entry, REPLACEMENT_DATAf); 312 _BCM_MULTICAST_GROUP_SET(*mc_group, 313 _BCM_MULTICAST_TYPE_EGRESS_OBJECT, 314 l3mc_index); 315 } 316 317 return BCM_E_NONE; 318 319 } 320 321 /* 322 * Function: 323 * bcm_tr3_failover_prot_nhi_cleanup 324 * Purpose: 325 * Create the entry for PROT_NHI 326 * Parameters: 327 * IN : unit 328 * IN : Primary Next Hop Index 329 * Returns: 330 * BCM_E_XXX 331 */ 332 333 334 int 335 bcm_tr3_failover_prot_nhi_cleanup (int unit, int nh_index) 336 { 337 initial_prot_nhi_table_entry_t prot_nhi_entry; 338 int rv; 339 340 rv = soc_mem_read(unit, INITIAL_PROT_NHI_TABLEm, 341 MEM_BLOCK_ANY, nh_index, &prot_nhi_entry); 342 343 if (rv < 0){ 344 return BCM_E_NOT_FOUND; 345 } 346 347 sal_memset(&prot_nhi_entry, 0, sizeof(initial_prot_nhi_table_entry_t)); 348 349 rv = soc_mem_write(unit, INITIAL_PROT_NHI_TABLEm, 350 MEM_BLOCK_ALL, nh_index, &prot_nhi_entry); 351 352 if (rv == SOC_E_NONE && _BCM_FAILOVER_PROT_NHI_MAP_IS_VALID(unit)) { 353 _BCM_FAILOVER_PROT_NHI_MAP_USED_CLR(unit, nh_index); 354 } 355 return rv; 356 357 } 358 359 /* 360 * Function: 361 * bcm_tr3_failover_prot_nhi_update 362 * Purpose: 363 * Update the next_hop entry for failover 364 * Parameters: 365 * IN : unit 366 * IN : Old Failover next hop index 367 * IN : New Failover next hop index 368 * Returns: 369 * BCM_E_XXX 370 */ 371 372 373 int 374 bcm_tr3_failover_prot_nhi_update (int unit, int old_nh_index, int new_nh_index) 375 { 376 uint32 prot_nhi_entry; 377 int rv = BCM_E_NONE; 378 int num_entry, index; 379 uint32 mask = 0; 380 uint32 imask = 0; 381 uint32 data_old = 0; 382 uint32 data_new = 0; 383 int fld_len = 0; 384 385 num_entry = soc_mem_index_count(unit, INITIAL_PROT_NHI_TABLEm); 386 387 fld_len = soc_mem_field_length(unit, INITIAL_PROT_NHI_TABLEm, REPLACEMENT_DATAf); 388 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, &mask, REPLACEMENT_DATAf, (1<<fld_len) - 1); 389 fld_len = soc_mem_field_length(unit, INITIAL_PROT_NHI_TABLEm, REPLACEMENT_TYPEf); 390 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, &mask, REPLACEMENT_TYPEf, (1<<fld_len) - 1); 391 392 imask = ~mask; 393 394 /* REPLACEMENT_TYPE should be 0 */ 395 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, &data_old, REPLACEMENT_DATAf, 396 old_nh_index); 397 398 /* REPLACEMENT_TYPE should be 0 */ 399 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, &data_new, REPLACEMENT_DATAf, 400 new_nh_index); 401 402 for ( index=0; index < num_entry; index++ ) { 403 if (_BCM_FAILOVER_PROT_NHI_MAP_IS_VALID(unit)) { 404 if (_BCM_FAILOVER_PROT_NHI_MAP_USED_GET(unit, index) == 0) { 405 continue; 406 } 407 } 408 rv = soc_mem_read(unit, INITIAL_PROT_NHI_TABLEm, 409 MEM_BLOCK_ANY, index, &prot_nhi_entry); 410 if (rv < 0) { 411 return BCM_E_NOT_FOUND; 412 } 413 414 if ((prot_nhi_entry & mask) == data_old) { 415 prot_nhi_entry &= imask; 416 prot_nhi_entry |= data_new; 417 rv = soc_mem_write(unit, INITIAL_PROT_NHI_TABLEm, 418 MEM_BLOCK_ALL, index, &prot_nhi_entry); 419 if (rv < 0) { 420 return BCM_E_NOT_FOUND; 421 } 422 } 423 } 424 return rv; 425 } 426 427 428 /* 429 * Function: 430 * bcm_tr3_failover_egr_check 431 * Purpose: 432 * Check for failover enable - Egress Object 433 * Parameters: 434 * IN : unit 435 * IN : Egress Object 436 * Returns: 437 * BCM_E_XXX 438 */ 439 440 441 int 442 bcm_tr3_failover_egr_check (int unit, bcm_l3_egress_t *egr) 443 { 444 int l3mc_index = -1; 445 446 if (_BCM_MULTICAST_IS_SET(egr->failover_mc_group )) { 447 l3mc_index = _BCM_MULTICAST_ID_GET(egr->failover_mc_group); 448 if ((l3mc_index >= 0) && (l3mc_index < soc_mem_index_count(unit, L3_IPMCm))) { 449 return BCM_E_NONE; 450 } else { 451 return BCM_E_PARAM; 452 } 453 } else if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, egr->failover_if_id) || 454 BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, egr->failover_if_id)) { 455 return (BCM_E_NONE); 456 } 457 return BCM_E_PARAM; 458 } 459 460 /* 461 * Function: 462 * bcm_tr3_failover_mpls_check 463 * Purpose: 464 * Check for failover enable - MPLS port 465 * Parameters: 466 * IN : unit 467 * IN : Egress Object 468 * Returns: 469 * BCM_E_XXX 470 */ 471 472 473 int 474 bcm_tr3_failover_mpls_check (int unit, bcm_mpls_port_t *mpls_port) 475 { 476 int failover_vp = -1; 477 int l3mc_index = -1; 478 479 /* Get egress next-hop index from Failover MPLS gport */ 480 if (_BCM_MULTICAST_IS_SET(mpls_port->failover_mc_group)) { 481 l3mc_index = _BCM_MULTICAST_ID_GET(mpls_port->failover_mc_group); 482 if ((l3mc_index >= 0) && (l3mc_index < soc_mem_index_count(unit, L3_IPMCm))) { 483 return BCM_E_NONE; 484 } else { 485 return BCM_E_PARAM; 486 } 487 } else { 488 failover_vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id); 489 if (failover_vp == -1) { 490 return BCM_E_PARAM; 491 } 492 if ( (failover_vp >= 1) && (failover_vp < soc_mem_index_count(unit, SOURCE_VPm)) ) { 493 return BCM_E_NONE; 494 } else { 495 return BCM_E_PARAM; 496 } 497 } 498 return BCM_E_PARAM; 499 } 500 501 /* 502 * Function: 503 * bcm_tr3_failover_extender_check 504 * Purpose: 505 * Check for failover enable - EXTENDER port 506 * Parameters: 507 * IN : unit 508 * IN : Egress Object 509 * Returns: 510 * BCM_E_XXX 511 */ 512 int 513 bcm_tr3_failover_extender_check(int unit, 514 bcm_extender_port_t *extender_port) 515 { 516 int failover_vp = -1; 517 int l3mc_index = -1; 518 519 if (extender_port->failover_id > 0 && extender_port->failover_id < 1024) { 520 /* Get egress next-hop index from Failover EXTENDER gport */ 521 if (_BCM_MULTICAST_IS_SET(extender_port->failover_mc_group) 522 && SOC_MEM_FIELD_VALID(unit, INITIAL_PROT_NHI_TABLEm, 523 REPLACEMENT_TYPEf)) { 524 l3mc_index = 525 _BCM_MULTICAST_ID_GET(extender_port->failover_mc_group); 526 if (l3mc_index >= 0 527 && l3mc_index < soc_mem_index_count(unit, L3_IPMCm)) { 528 return BCM_E_NONE; 529 } else { 530 return BCM_E_PARAM; 531 } 532 } else { 533 failover_vp = 534 BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port->failover_port_id); 535 if (failover_vp == -1) { 536 return BCM_E_PARAM; 537 } 538 if (failover_vp > 0 539 && failover_vp < soc_mem_index_count(unit, SOURCE_VPm)) { 540 return BCM_E_NONE; 541 } else { 542 return BCM_E_PARAM; 543 } 544 } 545 } 546 return BCM_E_PARAM; 547 } 548 549 550 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */