l2gre.c (307244B)
1 /* 2 * 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 * 8 * ESW L2GRE API 9 */ 10 11 #include <soc/defs.h> 12 #include <sal/core/libc.h> 13 #include <shared/bsl.h> 14 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3) 15 #include <soc/drv.h> 16 #include <soc/mem.h> 17 #include <soc/util.h> 18 #include <soc/hash.h> 19 #include <soc/debug.h> 20 #include <bcm/types.h> 21 #include <bcm/error.h> 22 23 #include <bcm/types.h> 24 #include <bcm/l3.h> 25 #include <soc/ism_hash.h> 26 27 #include <bcm_int/esw/mbcm.h> 28 #include <bcm_int/api_xlate_port.h> 29 #include <bcm_int/esw_dispatch.h> 30 #include <bcm_int/esw/virtual.h> 31 #include <bcm_int/esw/trx.h> 32 #include <bcm_int/esw/triumph3.h> 33 #include <bcm_int/esw/l2gre.h> 34 #include <bcm_int/esw/stack.h> 35 #include <bcm_int/common/multicast.h> 36 #include <bcm_int/esw/triumph.h> 37 #include <soc/scache.h> 38 #include <bcm_int/esw/switch.h> 39 #if defined(BCM_TRIDENT3_SUPPORT) 40 #include <bcm_int/esw/trident3.h> 41 #include <soc/esw/cancun.h> 42 #endif 43 44 _bcm_tr3_l2gre_bookkeeping_t *_bcm_tr3_l2gre_bk_info[BCM_MAX_NUM_UNITS] = { 0 }; 45 46 #define L2GRE_INFO(_unit_) (_bcm_tr3_l2gre_bk_info[_unit_]) 47 #define L3_INFO(_unit_) (&_bcm_l3_bk_info[_unit_]) 48 #define VIRTUAL_INFO(unit) (&_bcm_virtual_bk_info[unit]) 49 50 /* 51 * EGR_IP_TUNNEL table usage bitmap operations 52 */ 53 #define _BCM_L2GRE_IP_TNL_USED_GET(_u_, _tnl_) \ 54 SHR_BITGET(L2GRE_INFO(_u_)->l2gre_ip_tnl_bitmap, (_tnl_)) 55 #define _BCM_L2GRE_IP_TNL_USED_SET(_u_, _tnl_) \ 56 SHR_BITSET(L2GRE_INFO((_u_))->l2gre_ip_tnl_bitmap, (_tnl_)) 57 #define _BCM_L2GRE_IP_TNL_USED_CLR(_u_, _tnl_) \ 58 SHR_BITCLR(L2GRE_INFO((_u_))->l2gre_ip_tnl_bitmap, (_tnl_)) 59 60 #define _BCM_L2GRE_CLEANUP(_rv_) \ 61 if ( (_rv_) < 0) { \ 62 goto cleanup; \ 63 } 64 65 #if defined(BCM_TRIDENT3_SUPPORT) 66 #define L2GRE_DVP_EVXLT_KEY_VFI 1 67 #endif 68 69 70 STATIC int _bcm_tr3_l2gre_bud_loopback_disable(int unit); 71 STATIC int _bcm_tr3_l2gre_sd_tag_set( int unit, bcm_l2gre_vpn_config_t *l2gre_vpn_info, 72 bcm_l2gre_port_t *l2gre_port, 73 _bcm_tr3_l2gre_nh_info_t *egr_nh_info, 74 uint32 *vxlate_entry, 75 int *tpid_index ); 76 STATIC void _bcm_tr3_l2gre_sd_tag_get( int unit, bcm_l2gre_vpn_config_t *l2gre_vpn_info, 77 bcm_l2gre_port_t *l2gre_port, 78 egr_l3_next_hop_entry_t *egr_nh, 79 uint32 *vxlate_entry, 80 int network_port_flag ); 81 STATIC int _bcm_tr3_l2gre_egr_xlate_entry_set(int unit, bcm_l2gre_vpn_config_t *vpn_info); 82 STATIC int _bcm_tr3_l2gre_egr_xlate_entry_reset(int unit, bcm_vpn_t vpn); 83 STATIC int _bcm_tr3_l2gre_egr_xlate_entry_get(int unit, int vfi, soc_mem_t *, uint32 *vxlate_entry); 84 STATIC int _bcm_tr3_l2gre_match_vpnid_entry_set(int unit, bcm_l2gre_vpn_config_t *vpn_info); 85 STATIC int _bcm_tr3_l2gre_match_vpnid_entry_reset(int unit, uint32 vpnid); 86 87 int _bcm_tr3_l2gre_port_get(int unit, bcm_vpn_t vpn, int vp, bcm_l2gre_port_t *l2gre_port); 88 89 90 /* 91 * Function: 92 * _bcm_l2gre_check_init 93 * Purpose: 94 * Check if L2GRE is initialized 95 * Parameters: 96 * unit - Device Number 97 * Returns: 98 * BCM_E_XXX 99 */ 100 101 102 STATIC int 103 _bcm_l2gre_check_init(int unit) 104 { 105 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 106 107 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 108 return BCM_E_UNIT; 109 } 110 111 l2gre_info = L2GRE_INFO(unit); 112 113 if ((l2gre_info == NULL) || (l2gre_info->initialized == FALSE)) { 114 return BCM_E_INIT; 115 } else { 116 return BCM_E_NONE; 117 } 118 } 119 120 /* 121 * Function: 122 * bcm_tr3_l2gre_lock 123 * Purpose: 124 * Take L2GRE Lock Sempahore 125 * Parameters: 126 * unit - Device Number 127 * Returns: 128 * BCM_E_XXX 129 */ 130 131 132 int 133 bcm_tr3_l2gre_lock(int unit) 134 { 135 int rv; 136 137 rv = _bcm_l2gre_check_init(unit); 138 139 if ( rv == BCM_E_NONE ) { 140 sal_mutex_take(L2GRE_INFO((unit))->l2gre_mutex, sal_mutex_FOREVER); 141 } 142 return rv; 143 } 144 145 146 147 /* 148 * Function: 149 * bcm_tr3_l2gre_unlock 150 * Purpose: 151 * Release L2GRE Lock Semaphore 152 * Parameters: 153 * unit - Device Number 154 * Returns: 155 * BCM_E_XXX 156 */ 157 158 159 void 160 bcm_tr3_l2gre_unlock(int unit) 161 { 162 int rv; 163 164 rv = _bcm_l2gre_check_init(unit); 165 if ( rv == BCM_E_NONE ) { 166 sal_mutex_give(L2GRE_INFO((unit))->l2gre_mutex); 167 } 168 } 169 170 171 /* 172 * Function: 173 * _bcm_tr3_l2gre_free_resource 174 * Purpose: 175 * Free all allocated software resources 176 * Parameters: 177 * unit - SOC unit number 178 * Returns: 179 * Nothing 180 */ 181 182 183 STATIC void 184 _bcm_tr3_l2gre_free_resource(int unit) 185 { 186 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info = L2GRE_INFO(unit); 187 188 /* If software tables were not allocated we are done. */ 189 if (NULL == L2GRE_INFO(unit)) { 190 return; 191 } 192 193 /* Destroy EGR_IP_TUNNEL usage bitmap */ 194 if (l2gre_info->l2gre_ip_tnl_bitmap) { 195 sal_free(l2gre_info->l2gre_ip_tnl_bitmap); 196 l2gre_info->l2gre_ip_tnl_bitmap = NULL; 197 } 198 199 if (l2gre_info->match_key) { 200 sal_free(l2gre_info->match_key); 201 l2gre_info->match_key = NULL; 202 } 203 204 if (l2gre_info->l2gre_tunnel_init) { 205 sal_free(l2gre_info->l2gre_tunnel_init); 206 l2gre_info->l2gre_tunnel_init = NULL; 207 } 208 209 if (l2gre_info->l2gre_tunnel_term) { 210 sal_free(l2gre_info->l2gre_tunnel_term); 211 l2gre_info->l2gre_tunnel_term = NULL; 212 } 213 214 /* Free module data. */ 215 sal_free(L2GRE_INFO(unit)); 216 L2GRE_INFO(unit) = NULL; 217 } 218 219 /* 220 * Function: 221 * bcm_tr3_l2gre_allocate_bk 222 * Purpose: 223 * Initialize L2GRe software book-kepping 224 * Parameters: 225 * unit - Device Number 226 * Returns: 227 * BCM_E_XXX 228 */ 229 230 STATIC int 231 bcm_tr3_l2gre_allocate_bk(int unit) 232 { 233 /* Allocate/Init unit software tables. */ 234 if (NULL == L2GRE_INFO(unit)) { 235 BCM_TR3_L2GRE_ALLOC(L2GRE_INFO(unit), sizeof(_bcm_tr3_l2gre_bookkeeping_t), 236 "l2gre_bk_module_data"); 237 if (NULL == L2GRE_INFO(unit)) { 238 return (BCM_E_MEMORY); 239 } else { 240 L2GRE_INFO(unit)->initialized = FALSE; 241 } 242 } 243 return BCM_E_NONE; 244 } 245 246 /* 247 * Function: 248 * _bcm_tr3_l2gre_hw_clear 249 * Purpose: 250 * Perform hw tables clean up for L2GRE module. 251 * Parameters: 252 * unit - Device Number 253 * Returns: 254 * BCM_E_XXX 255 */ 256 257 STATIC int 258 _bcm_tr3_l2gre_hw_clear(int unit) 259 { 260 int rv = BCM_E_NONE, rv_error = BCM_E_NONE; 261 262 rv = bcm_tr3_l2gre_tunnel_terminator_destroy_all(unit); 263 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) { 264 rv_error = rv; 265 } 266 267 rv = bcm_tr3_l2gre_tunnel_initiator_destroy_all(unit); 268 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) { 269 rv_error = rv; 270 } 271 272 rv = bcm_tr3_l2gre_vpn_destroy_all(unit); 273 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) { 274 rv_error = rv; 275 } 276 277 rv = _bcm_tr3_l2gre_bud_loopback_disable(unit); 278 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) { 279 rv_error = rv; 280 } 281 282 return rv_error; 283 } 284 285 /* 286 * Function: 287 * bcm_tr3_l2gre_cleanup 288 * Purpose: 289 * DeInit L2GRE software module 290 * Parameters: 291 * unit - Device Number 292 * Returns: 293 * BCM_E_XXX 294 */ 295 296 int 297 bcm_tr3_l2gre_cleanup(int unit) 298 { 299 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 300 int rv = BCM_E_UNAVAIL; 301 302 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 303 return BCM_E_UNIT; 304 } 305 306 l2gre_info = L2GRE_INFO(unit); 307 308 if (FALSE == l2gre_info->initialized) { 309 return (BCM_E_NONE); 310 } 311 312 rv = bcm_tr3_l2gre_lock (unit); 313 if (BCM_FAILURE(rv)) { 314 return rv; 315 } 316 317 if (0 == SOC_HW_ACCESS_DISABLE(unit)) { 318 rv = _bcm_tr3_l2gre_hw_clear(unit); 319 } 320 321 /* Mark the state as uninitialized */ 322 l2gre_info->initialized = FALSE; 323 324 sal_mutex_give(l2gre_info->l2gre_mutex); 325 326 /* Destroy protection mutex. */ 327 sal_mutex_destroy(l2gre_info->l2gre_mutex ); 328 329 /* Free software resources */ 330 (void) _bcm_tr3_l2gre_free_resource(unit); 331 332 return rv; 333 } 334 335 /* 336 * Function: 337 * bcm_tr3_l2gre_port_match_count_adjust 338 * Purpose: 339 * Obtain ref-count for a L2GRE port 340 * Returns: 341 * BCM_E_XXX 342 */ 343 344 void 345 bcm_tr3_l2gre_port_match_count_adjust(int unit, int vp, int step) 346 { 347 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info = L2GRE_INFO(unit); 348 349 l2gre_info->match_key[vp].match_count += step; 350 } 351 352 #ifdef BCM_WARM_BOOT_SUPPORT 353 354 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1, 0) 355 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1, 1) 356 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_1 357 358 /* 359 * Function: 360 * _bcm_tr3_l2gre_wb_alloc 361 * 362 * Purpose: 363 * Alloc persisitent memory for Level 2 Warm Boot scache. 364 * 365 * Parameters: 366 * unit - (IN) Device Unit Number. 367 * 368 * Returns: 369 * BCM_E_XXX 370 */ 371 STATIC int 372 _bcm_tr3_l2gre_wb_alloc(int unit) 373 { 374 int alloc_sz = 0; 375 int rv = BCM_E_NONE; 376 int num_vp = 0; 377 uint8 *l2gre_state; 378 int stable_size = 0; 379 soc_scache_handle_t scache_handle; 380 381 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 382 383 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 384 return BCM_E_NONE; 385 } 386 387 /* Size of Tunnel Terminator & Initiator of all VP */ 388 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 389 alloc_sz += num_vp * (sizeof(bcm_ip_t) *2 + sizeof(uint16)) * 2; 390 391 /* Size of All match_key's flags & match_tunnel_index */ 392 alloc_sz += num_vp * sizeof(uint32) * 2; 393 394 395 if (soc_feature(unit, soc_feature_td2_l2gre) && 396 soc_feature(unit, soc_feature_vp_lag)) { 397 /* 398 * Size of All match_key's index && gport(trunk_id, modid, port) && 399 * match_vlan && match_inner_vlan 400 */ 401 alloc_sz += num_vp * (sizeof(uint32) + sizeof(bcm_gport_t) + 402 sizeof(bcm_vlan_t) * 2); 403 } 404 405 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_L2GRE, 0); 406 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 407 alloc_sz, (uint8**)&l2gre_state, 408 BCM_WB_DEFAULT_VERSION, NULL); 409 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 410 return rv; 411 } 412 413 return BCM_E_NONE; 414 } 415 416 /* 417 * Function: 418 * _bcm_tr3_l2gre_wb_recover 419 * 420 * Purpose: 421 * Recover L2GRE module info for Level 2 Warm Boot from persisitent memory 422 * 423 * Warm Boot Version Map: 424 * WB_VERSION_1_0 425 * 426 * Parameters: 427 * unit - (IN) Device Unit Number. 428 * 429 * Returns: 430 * BCM_E_XXX 431 */ 432 STATIC int 433 _bcm_tr3_l2gre_wb_recover(int unit) 434 { 435 int i, rv = BCM_E_NONE; 436 int num_vp = 0; 437 int stable_size; 438 uint16 recovered_ver = 0; 439 uint8 *l2gre_state = NULL; 440 soc_scache_handle_t scache_handle; 441 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 442 bcm_gport_t gport; 443 int additional_scache_size = 0; 444 445 l2gre_info = L2GRE_INFO(unit); 446 447 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 448 449 /* Requires extended scache support level-2 warmboot */ 450 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 451 return BCM_E_NONE; 452 } 453 454 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_L2GRE, 0); 455 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 456 0, &l2gre_state, 457 BCM_WB_DEFAULT_VERSION, &recovered_ver); 458 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 459 return rv; 460 } else if (rv == BCM_E_NOT_FOUND) { 461 return _bcm_tr3_l2gre_wb_alloc(unit); 462 } 463 464 if (l2gre_state == NULL) { 465 return BCM_E_NONE; 466 } 467 468 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 469 470 /* Recover the L2GRE Tunnnel Terminator information */ 471 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 472 for (i = 0; i < num_vp; i++) { 473 sal_memcpy(&(l2gre_info->l2gre_tunnel_init[i].dip), 474 l2gre_state, sizeof(bcm_ip_t)); 475 l2gre_state += sizeof(bcm_ip_t); 476 sal_memcpy(&(l2gre_info->l2gre_tunnel_init[i].sip), 477 l2gre_state, sizeof(bcm_ip_t)); 478 l2gre_state += sizeof(bcm_ip_t); 479 sal_memcpy(&(l2gre_info->l2gre_tunnel_init[i].tunnel_state), 480 l2gre_state, sizeof(uint16)); 481 l2gre_state += sizeof(uint16); 482 } 483 484 /* Recover the L2GRE Tunnnel Initiator information */ 485 for (i = 0; i < num_vp; i++) { 486 sal_memcpy(&(l2gre_info->l2gre_tunnel_term[i].dip), 487 l2gre_state, sizeof(bcm_ip_t)); 488 l2gre_state += sizeof(bcm_ip_t); 489 sal_memcpy(&(l2gre_info->l2gre_tunnel_term[i].sip), 490 l2gre_state, sizeof(bcm_ip_t)); 491 l2gre_state += sizeof(bcm_ip_t); 492 sal_memcpy(&(l2gre_info->l2gre_tunnel_term[i].tunnel_state), 493 l2gre_state, sizeof(uint16)); 494 l2gre_state += sizeof(uint16); 495 } 496 497 /* Recover the flags & match_tunnel_index of each Match Key */ 498 for (i = 0; i < num_vp; i++) { 499 sal_memcpy(&(l2gre_info->match_key[i].flags), 500 l2gre_state, sizeof(uint32)); 501 l2gre_state += sizeof(uint32); 502 sal_memcpy(&(l2gre_info->match_key[i].match_tunnel_index), 503 l2gre_state, sizeof(uint32)); 504 l2gre_state += sizeof(uint32); 505 } 506 507 if (soc_feature(unit, soc_feature_td2_l2gre) && 508 soc_feature(unit, soc_feature_vp_lag)) { 509 /* 510 * Recover the index && gport(trunk_id, modid, port) && match_vlan && 511 * match_inner_vlan of each Match Key 512 */ 513 if (recovered_ver >= BCM_WB_VERSION_1_1) { 514 for (i = 0; i < num_vp; i++) { 515 sal_memcpy(&(l2gre_info->match_key[i].index), l2gre_state, 516 sizeof(uint32)); 517 l2gre_state += sizeof(uint32); 518 sal_memcpy(&gport, l2gre_state, sizeof(bcm_gport_t)); 519 if (BCM_GPORT_IS_TRUNK(gport)) { 520 l2gre_info->match_key[i].trunk_id = 521 BCM_GPORT_TRUNK_GET(gport); 522 } else if (BCM_GPORT_IS_MODPORT(gport)) { 523 l2gre_info->match_key[i].modid = 524 BCM_GPORT_MODPORT_MODID_GET(gport); 525 l2gre_info->match_key[i].port = 526 BCM_GPORT_MODPORT_PORT_GET(gport); 527 } 528 l2gre_state += sizeof(bcm_gport_t); 529 sal_memcpy(&(l2gre_info->match_key[i].match_vlan), l2gre_state, 530 sizeof(bcm_vlan_t)); 531 l2gre_state += sizeof(bcm_vlan_t); 532 sal_memcpy(&(l2gre_info->match_key[i].match_inner_vlan), 533 l2gre_state, sizeof(bcm_vlan_t)); 534 l2gre_state += sizeof(bcm_vlan_t); 535 } 536 } else { 537 additional_scache_size += 538 num_vp * 539 (sizeof(uint32) + sizeof(bcm_gport_t) + sizeof(bcm_vlan_t) * 2); 540 } 541 } 542 543 if (additional_scache_size > 0) { 544 rv = soc_scache_realloc(unit, scache_handle, additional_scache_size); 545 if(BCM_FAILURE(rv)) { 546 return rv; 547 } 548 } 549 550 return BCM_E_NONE; 551 } 552 553 /* 554 * Function: 555 * _bcm_tr3_l2gre_sync 556 * 557 * Purpose: 558 * Record L2GRE module persistent info for Level 2 Warm Boot 559 * 560 * Warm Boot Version Map: 561 * WB_VERSION_1_0 562 * 563 * Parameters: 564 * unit - (IN) Device Unit Number. 565 * 566 * Returns: 567 * BCM_E_XXX 568 */ 569 int 570 _bcm_tr3_l2gre_sync(int unit) 571 { 572 int i, num_vp = 0; 573 int stable_size; 574 uint8 *l2gre_state; 575 soc_scache_handle_t scache_handle; 576 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 577 bcm_gport_t gport; 578 579 /* Parameter validation checks */ 580 if (!SOC_UNIT_VALID(unit)) { 581 return BCM_E_UNIT; 582 } 583 584 l2gre_info = L2GRE_INFO(unit); 585 586 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 587 588 /* Requires extended scache support level-2 warmboot */ 589 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 590 return BCM_E_NONE; 591 } 592 593 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_L2GRE, 0); 594 BCM_IF_ERROR_RETURN( 595 _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 596 0, &l2gre_state, BCM_WB_DEFAULT_VERSION, NULL)); 597 598 599 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 600 601 /* Store the L2GRE Tunnnel Terminator information */ 602 for (i = 0; i < num_vp; i++) { 603 sal_memcpy(l2gre_state, &(l2gre_info->l2gre_tunnel_init[i].dip), 604 sizeof(bcm_ip_t)); 605 l2gre_state += sizeof(bcm_ip_t); 606 sal_memcpy(l2gre_state, &(l2gre_info->l2gre_tunnel_init[i].sip), 607 sizeof(bcm_ip_t)); 608 l2gre_state += sizeof(bcm_ip_t); 609 sal_memcpy(l2gre_state, &(l2gre_info->l2gre_tunnel_init[i].tunnel_state), 610 sizeof(uint16)); 611 l2gre_state += sizeof(uint16); 612 } 613 614 /* Store the L2GRE Tunnnel Initiator information */ 615 for (i = 0; i < num_vp; i++) { 616 sal_memcpy(l2gre_state, &(l2gre_info->l2gre_tunnel_term[i].dip), 617 sizeof(bcm_ip_t)); 618 l2gre_state += sizeof(bcm_ip_t); 619 sal_memcpy(l2gre_state, &(l2gre_info->l2gre_tunnel_term[i].sip), 620 sizeof(bcm_ip_t)); 621 l2gre_state += sizeof(bcm_ip_t); 622 sal_memcpy(l2gre_state, &(l2gre_info->l2gre_tunnel_term[i].tunnel_state), 623 sizeof(uint16)); 624 l2gre_state += sizeof(uint16); 625 } 626 627 /* Store the flags & match_tunnel_index of each Match Key */ 628 for (i = 0; i < num_vp; i++) { 629 sal_memcpy(l2gre_state, &(l2gre_info->match_key[i].flags), 630 sizeof(uint32)); 631 l2gre_state += sizeof(uint32); 632 sal_memcpy(l2gre_state, &(l2gre_info->match_key[i].match_tunnel_index), 633 sizeof(uint32)); 634 l2gre_state += sizeof(uint32); 635 } 636 637 if (soc_feature(unit, soc_feature_td2_l2gre) && 638 soc_feature(unit, soc_feature_vp_lag)) { 639 /* 640 * Since we can't recover index && gport(trunk_id, modid, port) && 641 * match_vlan && match_inner_vlan from HW if we add this l2gre port to 642 * VPLAG, so we need to store it for warmboot recovery. 643 */ 644 for (i = 0; i < num_vp; i++) { 645 sal_memcpy(l2gre_state, &(l2gre_info->match_key[i].index), 646 sizeof(uint32)); 647 l2gre_state += sizeof(uint32); 648 if (l2gre_info->match_key[i].trunk_id != -1) { 649 BCM_GPORT_TRUNK_SET(gport, l2gre_info->match_key[i].trunk_id); 650 } else if (l2gre_info->match_key[i].modid != -1) { 651 BCM_GPORT_MODPORT_SET(gport, 652 l2gre_info->match_key[i].modid, 653 l2gre_info->match_key[i].port); 654 } else { 655 gport = BCM_GPORT_INVALID; 656 } 657 sal_memcpy(l2gre_state, &gport, sizeof(bcm_gport_t)); 658 l2gre_state += sizeof(bcm_gport_t); 659 sal_memcpy(l2gre_state, &(l2gre_info->match_key[i].match_vlan), 660 sizeof(bcm_vlan_t)); 661 l2gre_state += sizeof(bcm_vlan_t); 662 sal_memcpy(l2gre_state, 663 &(l2gre_info->match_key[i].match_inner_vlan), 664 sizeof(bcm_vlan_t)); 665 l2gre_state += sizeof(bcm_vlan_t); 666 } 667 } 668 669 return BCM_E_NONE; 670 } 671 672 /* 673 * Function: 674 * _bcm_tr3_l2gre_reinit 675 * Purpose: 676 * Warm boot recovery for the L2GRE software module 677 * Parameters: 678 * unit - Device Number 679 * Returns: 680 * BCM_E_XXX 681 */ 682 STATIC int 683 _bcm_tr3_l2gre_reinit(int unit) 684 { 685 soc_mem_t mem; 686 int i, index_min, index_max; 687 uint32 entry[SOC_MAX_MEM_WORDS]; 688 int port_type, vp, vxlate_flag; 689 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 690 uint32 trunk, tgid, mod_id, port_num, key_type; 691 soc_field_t validf, keytypef; 692 int keytype_ovid, keytype_ivid, keytype_iovid, keytype_cfi; 693 soc_field_t type_field; 694 int match_key_update_flag = FALSE; 695 soc_field_t tgid_fld = TGIDf; 696 697 l2gre_info = L2GRE_INFO(unit); 698 699 /* Recover tunnel terminator endpoints */ 700 mem = EGR_IP_TUNNELm; 701 index_min = soc_mem_index_min(unit, mem); 702 index_max = soc_mem_index_max(unit, mem); 703 704 #if defined(BCM_TRIDENT3_SUPPORT) 705 if (SOC_MEM_FIELD_VALID(unit, EGR_IP_TUNNELm, DATA_TYPEf)) { 706 type_field = DATA_TYPEf; 707 } else 708 #endif 709 { 710 type_field = ENTRY_TYPEf; 711 } 712 713 for (i = index_min; i <= index_max; i++) { 714 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, i, entry)); 715 716 /* Looking for IPV4 tunnels of type L2GRE only */ 717 if (soc_EGR_IP_TUNNELm_field32_get(unit, entry, 718 type_field) != 0x1) { 719 continue; 720 } 721 722 if (soc_EGR_IP_TUNNELm_field32_get(unit, entry, 723 TUNNEL_TYPEf) != 0x7) { 724 continue; 725 } 726 727 l2gre_info->l2gre_tunnel_term[i].sip = 728 soc_EGR_IP_TUNNELm_field32_get(unit, entry, SIPf); 729 730 l2gre_info->l2gre_tunnel_term[i].dip = 731 soc_EGR_IP_TUNNELm_field32_get(unit, entry, DIPf); 732 733 } 734 735 /* Recover l2gre match key */ 736 737 /* Recovery based on entry in VLAN_XLATE tbl */ 738 if (soc_mem_is_valid(unit, VLAN_XLATE_EXTDm)) { 739 mem = VLAN_XLATE_EXTDm; 740 validf = VALID_0f; 741 keytypef = KEY_TYPE_0f; 742 } else 743 #if defined(BCM_TRIDENT3_SUPPORT) 744 if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) { 745 mem = VLAN_XLATE_1_DOUBLEm; 746 validf = BASE_VALID_0f; 747 keytypef = KEY_TYPEf; 748 } else 749 #endif 750 if (soc_mem_is_valid(unit, VLAN_XLATEm)) { 751 mem = VLAN_XLATEm; 752 validf = VALIDf; 753 keytypef = KEY_TYPEf; 754 } else { 755 return BCM_E_INTERNAL; 756 } 757 758 #ifdef BCM_TRIDENT2_SUPPORT 759 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) { 760 keytype_ovid = VLXLT_HASH_KEY_TYPE_OVID; 761 keytype_ivid = VLXLT_HASH_KEY_TYPE_IVID; 762 keytype_iovid = VLXLT_HASH_KEY_TYPE_IVID_OVID; 763 keytype_cfi = VLXLT_HASH_KEY_TYPE_PRI_CFI; 764 } else 765 #endif 766 { 767 /*coverity[mixed_enums]*/ 768 keytype_ovid = TR3_VLXLT_X_HASH_KEY_TYPE_OVID; 769 /*coverity[mixed_enums]*/ 770 keytype_ivid = TR3_VLXLT_X_HASH_KEY_TYPE_IVID; 771 /*coverity[mixed_enums]*/ 772 keytype_iovid = TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID; 773 /*coverity[mixed_enums]*/ 774 keytype_cfi = TR3_VLXLT_X_HASH_KEY_TYPE_PRI_CFI; 775 } 776 777 index_min = soc_mem_index_min(unit, mem); 778 index_max = soc_mem_index_max(unit, mem); 779 780 for (i = index_min; i <= index_max; i++) { 781 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, i, entry)); 782 #if defined(BCM_TRIDENT3_SUPPORT) 783 if (soc_feature(unit, soc_feature_base_valid)) { 784 if (soc_mem_field32_get(unit, mem, entry, validf) != 3) { 785 continue; 786 } 787 if (soc_mem_field32_get(unit, mem, entry, BASE_VALID_1f) != 7) { 788 continue; 789 } 790 } else 791 #endif 792 { 793 if (soc_mem_field32_get(unit, mem, entry, validf) == 0) { 794 continue; 795 } 796 } 797 798 if (soc_mem_field32_get(unit, mem, entry, XLATE__MPLS_ACTIONf) != 0x1) { 799 continue; 800 } 801 802 vxlate_flag = FALSE; 803 match_key_update_flag = FALSE; 804 805 vp = soc_mem_field32_get(unit, mem, entry, XLATE__SOURCE_VPf); 806 807 /* Proceed only if this VP belongs to L2GRE */ 808 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 809 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 810 _bcm_vp_info_t vp_info; 811 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 812 if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) { 813 l2gre_info->match_key[vp].flags = 814 _BCM_L2GRE_PORT_MATCH_TYPE_SHARED; 815 } else 816 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 817 { 818 match_key_update_flag = TRUE; 819 } 820 821 key_type = soc_mem_field32_get(unit, mem, entry, keytypef); 822 if ((keytype_ovid == key_type) || (keytype_ivid == key_type) || 823 (keytype_iovid == key_type) || (keytype_cfi == key_type)) { 824 vxlate_flag = TRUE; 825 } 826 } 827 828 if (match_key_update_flag) { 829 trunk = soc_mem_field32_get(unit, mem, entry, XLATE__Tf); 830 tgid = soc_mem_field32_get(unit, mem, entry, XLATE__TGIDf); 831 mod_id = soc_mem_field32_get(unit, mem, entry, XLATE__MODULE_IDf); 832 port_num = soc_mem_field32_get(unit, mem, entry, XLATE__PORT_NUMf); 833 834 if (keytype_ovid == key_type) { 835 l2gre_info->match_key[vp].flags = 836 _BCM_L2GRE_PORT_MATCH_TYPE_VLAN; 837 l2gre_info->match_key[vp].match_vlan = 838 soc_mem_field32_get(unit, mem, entry, XLATE__OVIDf); 839 } else if (keytype_ivid == key_type) { 840 l2gre_info->match_key[vp].flags = 841 _BCM_L2GRE_PORT_MATCH_TYPE_INNER_VLAN; 842 l2gre_info->match_key[vp].match_inner_vlan = 843 soc_mem_field32_get(unit, mem, entry, XLATE__IVIDf); 844 } else if (keytype_iovid == key_type) { 845 l2gre_info->match_key[vp].flags = 846 _BCM_L2GRE_PORT_MATCH_TYPE_VLAN_STACKED; 847 l2gre_info->match_key[vp].match_vlan = 848 soc_mem_field32_get(unit, mem, entry, XLATE__OVIDf); 849 l2gre_info->match_key[vp].match_inner_vlan = 850 soc_mem_field32_get(unit, mem, entry, XLATE__IVIDf); 851 } else if (keytype_cfi == key_type) { 852 l2gre_info->match_key[vp].flags = 853 _BCM_L2GRE_PORT_MATCH_TYPE_VLAN_PRI; 854 l2gre_info->match_key[vp].match_vlan = 855 soc_mem_field32_get(unit, mem, entry, OTAGf); 856 } 857 858 if (vxlate_flag) { 859 if (trunk) { 860 l2gre_info->match_key[vp].trunk_id = tgid; 861 } else { 862 l2gre_info->match_key[vp].port = port_num; 863 l2gre_info->match_key[vp].modid = mod_id; 864 } 865 } 866 } 867 868 if (vxlate_flag) { 869 bcm_tr3_l2gre_port_match_count_adjust(unit, vp, 1); 870 } 871 } 872 873 /* Recovery based on entry in MPLS tbl */ 874 mem = MPLS_ENTRYm; 875 index_min = soc_mem_index_min(unit, mem); 876 index_max = soc_mem_index_max(unit, mem); 877 878 for (i = index_min; i <= index_max; i++) { 879 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, i, entry)); 880 #if defined(BCM_TRIDENT3_SUPPORT) 881 if (soc_feature(unit, soc_feature_base_valid)) { 882 if (soc_mem_field32_get(unit, mem, entry, BASE_VALID_0f) != 3) { 883 continue; 884 } 885 if (soc_mem_field32_get(unit, mem, entry, BASE_VALID_1f) != 7) { 886 continue; 887 } 888 } else 889 #endif 890 { 891 if (soc_mem_field32_get(unit, mem, entry, VALIDf) == 0) { 892 continue; 893 } 894 } 895 896 /* Looking for entries of type l2gre only */ 897 key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf); 898 if ((key_type != 0x8) && (key_type != 0x6)) { 899 continue; 900 } 901 902 vp = soc_mem_field32_get(unit, mem, entry, L2GRE_SIP__SVPf); 903 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 904 l2gre_info->match_key[vp].flags = _BCM_L2GRE_PORT_MATCH_TYPE_VPNID; 905 } 906 } 907 908 /* Recovery based on entry in SOURCE_TRUNK_MAP tbl */ 909 mem = SOURCE_TRUNK_MAP_TABLEm; 910 index_min = soc_mem_index_min(unit, mem); 911 index_max = soc_mem_index_max(unit, mem); 912 913 if (SOC_IS_TRIDENT3X(unit) && soc_mem_field_valid(unit, mem, SRC_TGIDf)) { 914 tgid_fld = SRC_TGIDf; 915 } 916 917 for (i = index_min; i <= index_max; i++) { 918 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, i, entry)); 919 920 vp = soc_mem_field32_get(unit, mem, entry, SOURCE_VPf); 921 922 /* Proceed only if this VP belongs to L2GRE */ 923 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 924 925 port_type = soc_mem_field32_get(unit, mem, entry, PORT_TYPEf); 926 if (port_type) { /* trunk port */ 927 l2gre_info->match_key[vp].flags =_BCM_L2GRE_PORT_MATCH_TYPE_TRUNK; 928 l2gre_info->match_key[vp].trunk_id = 929 soc_mem_field32_get(unit, mem, entry, tgid_fld); 930 } else { 931 l2gre_info->match_key[vp].flags = _BCM_L2GRE_PORT_MATCH_TYPE_PORT; 932 l2gre_info->match_key[vp].index = i; 933 } 934 } 935 } 936 937 /* Recover L2 scache */ 938 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_wb_recover(unit)); 939 940 return BCM_E_NONE; 941 } 942 #endif /* BCM_WARM_BOOT_SUPPORT */ 943 944 /* 945 * Function: 946 * bcm_tr3_l2gre_init 947 * Purpose: 948 * Initialize the L2GRE software module 949 * Parameters: 950 * unit - Device Number 951 * Returns: 952 * BCM_E_XXX 953 */ 954 955 956 int 957 bcm_tr3_l2gre_init(int unit) 958 { 959 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 960 int i, num_tnl=0, num_vp=0; 961 int rv = BCM_E_NONE; 962 963 if (!L3_INFO(unit)->l3_initialized) { 964 LOG_ERROR(BSL_LS_BCM_L2GRE, 965 (BSL_META_U(unit, 966 "L3 module must be initialized prior to L2GRE Init\n"))); 967 return BCM_E_CONFIG; 968 } 969 970 /* Allocate BK Info */ 971 BCM_IF_ERROR_RETURN(bcm_tr3_l2gre_allocate_bk(unit)); 972 l2gre_info = L2GRE_INFO(unit); 973 974 /* 975 * allocate resources 976 */ 977 if (l2gre_info->initialized) { 978 BCM_IF_ERROR_RETURN(bcm_tr3_l2gre_cleanup(unit)); 979 BCM_IF_ERROR_RETURN(bcm_tr3_l2gre_allocate_bk(unit)); 980 l2gre_info = L2GRE_INFO(unit); 981 } 982 983 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 984 l2gre_info->match_key = 985 sal_alloc(sizeof(_bcm_l2gre_match_port_info_t) * num_vp, "match_key"); 986 if (l2gre_info->match_key == NULL) { 987 _bcm_tr3_l2gre_free_resource(unit); 988 return BCM_E_MEMORY; 989 } 990 991 sal_memset(l2gre_info->match_key, 0, 992 sizeof(_bcm_l2gre_match_port_info_t) * num_vp); 993 /* Stay same after recover */ 994 for (i = 0; i < num_vp; i++) { 995 bcm_tr3_l2gre_match_clear(unit, i); 996 } 997 998 /* Create EGR_IP_TUNNEL usage bitmap */ 999 num_tnl = soc_mem_index_count(unit, EGR_IP_TUNNELm); 1000 1001 l2gre_info->l2gre_ip_tnl_bitmap = 1002 sal_alloc(SHR_BITALLOCSIZE(num_tnl), "l2gre_ip_tnl_bitmap"); 1003 if (l2gre_info->l2gre_ip_tnl_bitmap == NULL) { 1004 _bcm_tr3_l2gre_free_resource(unit); 1005 return BCM_E_MEMORY; 1006 } 1007 sal_memset(l2gre_info->l2gre_ip_tnl_bitmap, 0, SHR_BITALLOCSIZE(num_tnl)); 1008 1009 /* Create L2GRE protection mutex. */ 1010 l2gre_info->l2gre_mutex = sal_mutex_create("l2gre_mutex"); 1011 if (!l2gre_info->l2gre_mutex) { 1012 _bcm_tr3_l2gre_free_resource(unit); 1013 return BCM_E_MEMORY; 1014 } 1015 1016 if (NULL == l2gre_info->l2gre_tunnel_term) { 1017 l2gre_info->l2gre_tunnel_term = 1018 sal_alloc(sizeof(_bcm_l2gre_tunnel_endpoint_t) * num_vp, "L2gre tunnel term store"); 1019 if (l2gre_info->l2gre_tunnel_term == NULL) { 1020 _bcm_tr3_l2gre_free_resource(unit); 1021 return BCM_E_MEMORY; 1022 } 1023 sal_memset(l2gre_info->l2gre_tunnel_term, 0, 1024 sizeof(_bcm_l2gre_tunnel_endpoint_t) * num_vp); 1025 } 1026 1027 if (NULL == l2gre_info->l2gre_tunnel_init) { 1028 l2gre_info->l2gre_tunnel_init = 1029 sal_alloc(sizeof(_bcm_l2gre_tunnel_endpoint_t) * num_vp, "L2gre tunnel init store"); 1030 if (l2gre_info->l2gre_tunnel_init == NULL) { 1031 _bcm_tr3_l2gre_free_resource(unit); 1032 return BCM_E_MEMORY; 1033 } 1034 sal_memset(l2gre_info->l2gre_tunnel_init, 0, 1035 sizeof(_bcm_l2gre_tunnel_endpoint_t) * num_vp); 1036 } 1037 1038 #ifdef BCM_WARM_BOOT_SUPPORT 1039 1040 if (SOC_WARM_BOOT(unit)) { 1041 rv = _bcm_tr3_l2gre_reinit(unit); 1042 } else { 1043 rv = _bcm_tr3_l2gre_wb_alloc(unit); 1044 } 1045 if (BCM_FAILURE(rv)) { 1046 _bcm_tr3_l2gre_free_resource(unit); 1047 } 1048 #endif /* BCM_WARM_BOOT_SUPPORT */ 1049 1050 /* Mark the state as initialized */ 1051 l2gre_info->initialized = TRUE; 1052 1053 return rv; 1054 } 1055 1056 /* 1057 * Function: 1058 * _bcm_tr3_l2gre_bud_loopback_enable 1059 * Purpose: 1060 * Enable loopback for L2GRE BUD node multicast 1061 * Parameters: 1062 * IN : unit 1063 * Returns: 1064 * BCM_E_XXX 1065 */ 1066 1067 STATIC int 1068 _bcm_tr3_l2gre_bud_loopback_enable(int unit) 1069 { 1070 int field_num = 0; 1071 1072 soc_field_t lport_fields[] = { 1073 L2GRE_TERMINATION_ALLOWEDf, 1074 V4IPMC_ENABLEf, 1075 L2GRE_VPNID_LOOKUP_KEY_TYPEf, 1076 PORT_TYPEf, 1077 L2GRE_DEFAULT_SVP_ENABLEf 1078 }; 1079 uint32 lport_values[] = { 1080 0x1, /* L2GRE_TERMINATION_ALLOWEDf */ 1081 0x1, /* V4IPMC_ENABLEf */ 1082 0x0, /* L2GRE_VPNID_LOOKUP_KEY_TYPEf */ 1083 0x0, /* PORT_TYPEf */ 1084 0x1 /* L2GRE_DEFAULT_SVP_ENABLEf */ 1085 }; 1086 1087 if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, L2GRE_DEFAULT_SVP_ENABLEf)) { 1088 field_num = 5; 1089 } else { 1090 field_num = 3; /* TD3TBD */ 1091 } 1092 1093 /* Update LPORT Profile Table */ 1094 return _bcm_lport_profile_fields32_modify(unit, LPORT_PROFILE_LPORT_TAB, 1095 field_num, lport_fields, lport_values); 1096 } 1097 1098 /* 1099 * Function: 1100 * _bcm_tr3_l2gre_bud_loopback_disable 1101 * Purpose: 1102 * Disable loopback for L2GRE BUD node multicast 1103 * Parameters: 1104 * IN : unit 1105 * Returns: 1106 * BCM_E_XXX 1107 */ 1108 1109 STATIC int 1110 _bcm_tr3_l2gre_bud_loopback_disable(int unit) 1111 { 1112 int field_num = 0; 1113 1114 soc_field_t lport_fields[] = { 1115 L2GRE_TERMINATION_ALLOWEDf, 1116 L2GRE_VPNID_LOOKUP_KEY_TYPEf, 1117 V4IPMC_ENABLEf, 1118 PORT_TYPEf, 1119 L2GRE_DEFAULT_SVP_ENABLEf 1120 }; 1121 uint32 lport_values[] = { 1122 0x0, /* L2GRE_TERMINATION_ALLOWEDf */ 1123 0x0, /* L2GRE_VPNID_LOOKUP_KEY_TYPEf */ 1124 0x0, /* V4IPMC_ENABLEf */ 1125 0x0, /* PORT_TYPEf */ 1126 0x0, /* L2GRE_DEFAULT_SVP_ENABLEf */ 1127 }; 1128 1129 if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, L2GRE_DEFAULT_SVP_ENABLEf)) { 1130 field_num = 5; 1131 } else if (SOC_IS_TRIDENT3X(unit)) { 1132 field_num = 2; 1133 } else { 1134 field_num = 3; 1135 } 1136 1137 /* Update LPORT Profile Table */ 1138 return _bcm_lport_profile_fields32_modify(unit, LPORT_PROFILE_LPORT_TAB, 1139 field_num, lport_fields, lport_values); 1140 } 1141 1142 /* Function: 1143 * _bcm_tr3_l2gre_vpn_is_valid 1144 * Purpose: 1145 * Find if given L2GRE VPN is Valid 1146 * Parameters: 1147 * unit - Device Number 1148 * l2vpn - L2GRE VPN 1149 * Returns: 1150 * BCM_E_XXXX 1151 */ 1152 int 1153 _bcm_tr3_l2gre_vpn_is_valid( int unit, bcm_vpn_t l2vpn) 1154 { 1155 bcm_vpn_t l2gre_vpn_min=0; 1156 int vfi_index=-1, num_vfi=0; 1157 1158 num_vfi = soc_mem_index_count(unit, VFIm); 1159 1160 /* Check for Valid vpn */ 1161 _BCM_L2GRE_VPN_SET(l2gre_vpn_min, _BCM_VPN_TYPE_VFI, 0); 1162 if ( l2vpn < l2gre_vpn_min || l2vpn > (l2gre_vpn_min+num_vfi-1) ) { 1163 return BCM_E_PARAM; 1164 } 1165 1166 _BCM_L2GRE_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, l2vpn); 1167 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeL2Gre)) { 1168 return BCM_E_NOT_FOUND; 1169 } 1170 1171 return BCM_E_NONE; 1172 } 1173 1174 /* Function: 1175 * _bcm_tr3_l2gre_vpn_is_eline 1176 * Purpose: 1177 * Find if given L2GRE VPN is ELINE 1178 * Parameters: 1179 * unit - Device Number 1180 * l2vpn - L2GRE VPN 1181 * isEline - Flag 1182 * Returns: 1183 * BCM_E_XXXX 1184 * Assumes: 1185 * l2vpn is valid 1186 */ 1187 1188 STATIC int 1189 _bcm_tr3_l2gre_vpn_is_eline( int unit, bcm_vpn_t l2vpn, uint8 *isEline) 1190 { 1191 int vfi_index=-1; 1192 vfi_entry_t vfi_entry; 1193 1194 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_vpn_is_valid(unit, l2vpn)); 1195 1196 _BCM_L2GRE_VPN_GET(vfi_index, _BCM_L2GRE_VPN_TYPE_ELINE, l2vpn); 1197 BCM_IF_ERROR_RETURN(READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry)); 1198 1199 if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) { 1200 *isEline = 1; /* ELINE */ 1201 } else { 1202 *isEline = 0; /* ELAN */ 1203 } 1204 1205 return BCM_E_NONE; 1206 } 1207 1208 /* Function: 1209 * _bcm_tr3_l2gre_vp_is_eline 1210 * Purpose: 1211 * Find if given L2GRE VP is ELINE 1212 * Parameters: 1213 * unit - Device Number 1214 * vp - L2GRE VP 1215 * isEline - Flag 1216 * Returns: 1217 * BCM_E_XXXX 1218 * Assumes: 1219 * l2vpn is valid 1220 */ 1221 1222 int 1223 _bcm_tr3_l2gre_vp_is_eline( int unit, int vp, uint8 *isEline) 1224 { 1225 source_vp_entry_t svp; 1226 vfi_entry_t vfi_entry; 1227 int rv = BCM_E_PARAM; 1228 int vfi_index; 1229 1230 if (vp == -1) { 1231 return BCM_E_PARAM; 1232 } 1233 1234 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 1235 return BCM_E_NOT_FOUND; 1236 } 1237 1238 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 1239 if (rv < 0) { 1240 return rv; 1241 } 1242 1243 vfi_index = soc_SOURCE_VPm_field32_get(unit, &svp, VFIf); 1244 BCM_IF_ERROR_RETURN 1245 (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry)); 1246 1247 /* Set the returned VPN id */ 1248 if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) { 1249 *isEline = 0x1; 1250 } else { 1251 *isEline = 0x0; 1252 } 1253 return BCM_E_NONE; 1254 } 1255 1256 /* 1257 * Function: 1258 * _bcm_tr3_l2gre_nexthop_glp_get 1259 * Purpose: 1260 * Get the modid, port, trunk values for a L2GRE nexthop 1261 * Returns: 1262 * BCM_E_XXX 1263 */ 1264 STATIC int 1265 _bcm_tr3_l2gre_nexthop_glp_get(int unit, int nh_idx, 1266 bcm_module_t *modid, bcm_port_t *port, bcm_trunk_t *trunk_id) 1267 1268 { 1269 ing_l3_next_hop_entry_t ing_nh; 1270 1271 BCM_IF_ERROR_RETURN (soc_mem_read(unit, 1272 ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, nh_idx, &ing_nh)); 1273 1274 #if defined(BCM_TRIDENT3_SUPPORT) 1275 if (soc_feature(unit, soc_feature_generic_dest)) { 1276 uint32 dt, dv; 1277 1278 dv = soc_mem_field32_dest_get(unit, 1279 ING_L3_NEXT_HOPm, &ing_nh, DESTINATIONf, &dt); 1280 if (dt == SOC_MEM_FIF_DEST_LAG) { 1281 *trunk_id = dv & SOC_MEM_FIF_DGPP_TGID_MASK; 1282 } else if (dt == SOC_MEM_FIF_DEST_DGPP) { 1283 *port = (dv & SOC_MEM_FIF_DGPP_PORT_MASK); 1284 *modid = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 1285 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 1286 } else { 1287 return BCM_E_INTERNAL; 1288 } 1289 } else 1290 #endif 1291 { 1292 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 1293 *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf); 1294 } else { 1295 /* Only add this to replication set if destination is local */ 1296 *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf); 1297 *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf); 1298 } 1299 } 1300 1301 return BCM_E_NONE; 1302 } 1303 1304 /* 1305 * Function: 1306 * _bcm_tr3_l2gre_port_resolve 1307 * Purpose: 1308 * Get the modid, port, trunk values for a L2GRE port 1309 * Returns: 1310 * BCM_E_XXX 1311 */ 1312 int 1313 _bcm_tr3_l2gre_port_resolve(int unit, bcm_gport_t l2gre_port_id, 1314 bcm_if_t encap_id, bcm_module_t *modid, bcm_port_t *port, 1315 bcm_trunk_t *trunk_id, int *id) 1316 1317 { 1318 int rv = BCM_E_NONE; 1319 egr_l3_next_hop_entry_t egr_nh; 1320 ing_dvp_table_entry_t dvp; 1321 int ecmp, nh_index, nh_ecmp_index, vp; 1322 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry. */ 1323 int idx, max_ent_count, base_idx; 1324 1325 rv = _bcm_l2gre_check_init(unit); 1326 if (rv < 0) { 1327 return rv; 1328 } 1329 1330 if (!BCM_GPORT_IS_L2GRE_PORT(l2gre_port_id)) { 1331 return (BCM_E_BADID); 1332 } 1333 1334 vp = BCM_GPORT_L2GRE_PORT_ID_GET(l2gre_port_id); 1335 if (vp == -1) { 1336 return BCM_E_PARAM; 1337 } 1338 1339 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 1340 return BCM_E_NOT_FOUND; 1341 } 1342 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 1343 ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf); 1344 if (!ecmp) { 1345 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 1346 1347 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_nexthop_glp_get(unit, 1348 nh_index, modid, port, trunk_id)); 1349 } else { 1350 /* Select the desired nhop from ECMP group - pointed by encap_id */ 1351 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf); 1352 BCM_IF_ERROR_RETURN(soc_mem_read(unit, 1353 L3_ECMP_COUNTm, MEM_BLOCK_ANY, nh_ecmp_index, hw_buf)); 1354 1355 if (soc_feature(unit, soc_feature_l3_ecmp_1k_groups)) { 1356 max_ent_count = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 1357 hw_buf, COUNTf); 1358 base_idx = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 1359 hw_buf, BASE_PTRf); 1360 } else { 1361 max_ent_count = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 1362 hw_buf, COUNT_0f); 1363 base_idx = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 1364 hw_buf, BASE_PTR_0f); 1365 } 1366 max_ent_count++; /* Count is zero based. */ 1367 1368 if(encap_id == -1) { 1369 BCM_IF_ERROR_RETURN(soc_mem_read(unit, 1370 L3_ECMPm, MEM_BLOCK_ANY, base_idx, hw_buf)); 1371 nh_index = soc_mem_field32_get(unit, 1372 L3_ECMPm, hw_buf, NEXT_HOP_INDEXf); 1373 1374 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_nexthop_glp_get(unit, 1375 nh_index, modid, port, trunk_id)); 1376 } else { 1377 for (idx = 0; idx < max_ent_count; idx++) { 1378 BCM_IF_ERROR_RETURN(soc_mem_read(unit, L3_ECMPm, 1379 MEM_BLOCK_ANY, (base_idx+idx), hw_buf)); 1380 nh_index = soc_mem_field32_get(unit, 1381 L3_ECMPm, hw_buf, NEXT_HOP_INDEXf); 1382 BCM_IF_ERROR_RETURN (soc_mem_read(unit, 1383 EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, nh_index, &egr_nh)); 1384 if (encap_id == soc_mem_field32_get(unit, 1385 EGR_L3_NEXT_HOPm, &egr_nh, INTF_NUMf)) { 1386 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_nexthop_glp_get(unit, 1387 nh_index, modid, port, trunk_id)); 1388 break; 1389 } 1390 } 1391 } 1392 } 1393 *id = vp; 1394 return rv; 1395 } 1396 1397 /* 1398 * Function: 1399 * _bcm_tr3_l2gre_port_nh_cnt_dec 1400 * Purpose: 1401 * Decrease L2GRE nexthop count. 1402 * Parameters: 1403 * unit - (IN) SOC unit number. 1404 * vp - (IN) Virtual port number. 1405 * Returns: 1406 * BCM_E_XXX 1407 */ 1408 1409 1410 STATIC int 1411 _bcm_tr3_l2gre_port_nh_cnt_dec(int unit, int vp) 1412 { 1413 int nh_ecmp_index = -1; 1414 ing_dvp_table_entry_t dvp; 1415 uint32 flags = 0; 1416 int ref_count = 0; 1417 int ecmp = -1; 1418 1419 BCM_IF_ERROR_RETURN( 1420 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 1421 1422 ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf); 1423 if (ecmp) { 1424 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf); 1425 flags = BCM_L3_MULTIPATH; 1426 /* Decrement reference count */ 1427 BCM_IF_ERROR_RETURN( 1428 bcm_xgs3_get_ref_count_from_nhi(unit, flags, &ref_count, nh_ecmp_index)); 1429 } else { 1430 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 1431 NEXT_HOP_INDEXf); 1432 if(nh_ecmp_index != 0) { 1433 /* Decrement reference count */ 1434 BCM_IF_ERROR_RETURN( 1435 bcm_xgs3_get_ref_count_from_nhi(unit, flags, &ref_count, nh_ecmp_index)); 1436 } 1437 } 1438 1439 return BCM_E_NONE; 1440 } 1441 1442 /* 1443 * Function: 1444 * _bcm_tr3_l2gre_port_cnt_update 1445 * Purpose: 1446 * Update port's VP count. 1447 * Parameters: 1448 * unit - (IN) SOC unit number. 1449 * gport - (IN) GPORT ID. 1450 * vp - (IN) Virtual port number. 1451 * incr - (IN) If TRUE, increment VP count, else decrease VP count. 1452 * Returns: 1453 * BCM_X_XXX 1454 */ 1455 1456 STATIC int 1457 _bcm_tr3_l2gre_port_cnt_update(int unit, bcm_gport_t gport, 1458 int vp, int incr_decr_flag) 1459 { 1460 int mod_out=-1, port_out=-1, tgid_out=-1, vp_out=-1; 1461 bcm_port_t local_member_array[SOC_MAX_NUM_PORTS]; 1462 int local_member_count=0; 1463 int idx=-1; 1464 int mod_local=-1; 1465 _bcm_port_info_t *port_info; 1466 uint32 port_flags; 1467 1468 BCM_IF_ERROR_RETURN( 1469 _bcm_tr3_l2gre_port_resolve(unit, gport, -1, &mod_out, 1470 &port_out, &tgid_out, &vp_out)); 1471 1472 if (vp_out == -1) { 1473 return BCM_E_PARAM; 1474 } 1475 1476 /* Update the physical port's SW state. If associated with a trunk, 1477 * update each local physical port's SW state. 1478 */ 1479 1480 if (BCM_TRUNK_INVALID != tgid_out) { 1481 1482 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid_out, 1483 SOC_MAX_NUM_PORTS, local_member_array, &local_member_count)); 1484 1485 for (idx = 0; idx < local_member_count; idx++) { 1486 _bcm_port_info_access(unit, local_member_array[idx], &port_info); 1487 if (incr_decr_flag) { 1488 port_info->vp_count++; 1489 } else { 1490 port_info->vp_count--; 1491 } 1492 BCM_IF_ERROR_RETURN( 1493 bcm_esw_port_vlan_member_get( 1494 unit, local_member_array[idx], &port_flags)); 1495 BCM_IF_ERROR_RETURN( 1496 bcm_esw_port_vlan_member_set( 1497 unit, local_member_array[idx], port_flags)); 1498 } 1499 } else { 1500 BCM_IF_ERROR_RETURN 1501 (_bcm_esw_modid_is_local(unit, mod_out, &mod_local)); 1502 if (mod_local) { 1503 if (soc_feature(unit, soc_feature_sysport_remap)) { 1504 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 1505 } 1506 _bcm_port_info_access(unit, port_out, &port_info); 1507 if (incr_decr_flag) { 1508 port_info->vp_count++; 1509 } else { 1510 port_info->vp_count--; 1511 } 1512 BCM_IF_ERROR_RETURN( 1513 bcm_esw_port_vlan_member_get( 1514 unit, port_out, &port_flags)); 1515 BCM_IF_ERROR_RETURN( 1516 bcm_esw_port_vlan_member_set( 1517 unit, port_out, port_flags)); 1518 } 1519 } 1520 1521 return BCM_E_NONE; 1522 } 1523 1524 /* 1525 * Function: 1526 * bcm_tr3_l2gre_vpn_create 1527 * Purpose: 1528 * Create a VPN instance 1529 * Parameters: 1530 * unit - (IN) Device Number 1531 * info - (IN/OUT) VPN configuration info 1532 * Returns: 1533 * BCM_E_XXX 1534 */ 1535 1536 int 1537 bcm_tr3_l2gre_vpn_create(int unit, bcm_l2gre_vpn_config_t *info) 1538 { 1539 int rv = BCM_E_PARAM; 1540 vfi_entry_t vfi_entry; 1541 soc_mem_t mem; 1542 uint32 vxlate[SOC_MAX_MEM_WORDS]; 1543 int vfi_index; 1544 int bc_group=0, umc_group=0, uuc_group=0; 1545 int bc_group_type, umc_group_type, uuc_group_type; 1546 uint8 vpn_alloc_flag = 0; 1547 uint8 vpnid_alloc_flag = 0; 1548 uint32 vpnid = 0; 1549 1550 /* Allocate VFI */ 1551 if (info->flags & BCM_L2GRE_VPN_REPLACE) { 1552 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_vpn_is_valid(unit, info->vpn)); 1553 _BCM_L2GRE_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, info->vpn); 1554 } else if (info->flags & BCM_L2GRE_VPN_WITH_ID) { 1555 rv = _bcm_tr3_l2gre_vpn_is_valid(unit, info->vpn); 1556 if (BCM_E_NONE == rv) { 1557 return BCM_E_EXISTS; 1558 } else if (BCM_E_NOT_FOUND != rv) { 1559 return rv; 1560 } 1561 1562 _BCM_L2GRE_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, info->vpn); 1563 BCM_IF_ERROR_RETURN(_bcm_vfi_alloc_with_id(unit, VFIm, _bcmVfiTypeL2Gre, vfi_index)); 1564 vpn_alloc_flag = 1; 1565 } else { 1566 BCM_IF_ERROR_RETURN(_bcm_vfi_alloc(unit, VFIm, _bcmVfiTypeL2Gre, &vfi_index)); 1567 _BCM_L2GRE_VPN_SET(info->vpn, _BCM_VPN_TYPE_VFI, vfi_index); 1568 vpn_alloc_flag = 1; 1569 } 1570 1571 /* Initial and configurate VFI */ 1572 BCM_IF_ERROR_RETURN(READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry)); 1573 if (info->flags & BCM_L2GRE_VPN_ELINE) { 1574 soc_VFIm_field32_set(unit, &vfi_entry, PT2PT_ENf, 0x1); 1575 } else if (info->flags & BCM_L2GRE_VPN_ELAN) { 1576 /* Check that the groups are valid. */ 1577 bc_group_type = _BCM_MULTICAST_TYPE_GET(info->broadcast_group); 1578 bc_group = _BCM_MULTICAST_ID_GET(info->broadcast_group); 1579 umc_group_type = _BCM_MULTICAST_TYPE_GET(info->unknown_multicast_group); 1580 umc_group = _BCM_MULTICAST_ID_GET(info->unknown_multicast_group); 1581 uuc_group_type = _BCM_MULTICAST_TYPE_GET(info->unknown_unicast_group); 1582 uuc_group = _BCM_MULTICAST_ID_GET(info->unknown_unicast_group); 1583 1584 if ((bc_group_type != _BCM_MULTICAST_TYPE_L2GRE) || 1585 (umc_group_type != _BCM_MULTICAST_TYPE_L2GRE) || 1586 (uuc_group_type != _BCM_MULTICAST_TYPE_L2GRE) || 1587 (bc_group >= soc_mem_index_count(unit, L3_IPMCm)) || 1588 (umc_group >= soc_mem_index_count(unit, L3_IPMCm)) || 1589 (uuc_group >= soc_mem_index_count(unit, L3_IPMCm))) { 1590 rv = BCM_E_PARAM; 1591 goto cleanup; 1592 } 1593 1594 /* Configurate VFI for ELAN vpn */ 1595 #if defined(BCM_TRIDENT3_SUPPORT) 1596 if (soc_feature(unit, soc_feature_generic_dest)) { 1597 soc_mem_field32_dest_set(unit, VFIm, &vfi_entry, 1598 UMC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, umc_group); 1599 soc_mem_field32_dest_set(unit, VFIm, &vfi_entry, 1600 UUC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, uuc_group); 1601 soc_mem_field32_dest_set(unit, VFIm, &vfi_entry, 1602 BC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, bc_group); 1603 } else 1604 #endif 1605 { 1606 soc_VFIm_field32_set(unit, &vfi_entry, UMC_INDEXf, umc_group); 1607 soc_VFIm_field32_set(unit, &vfi_entry, UUC_INDEXf, uuc_group); 1608 soc_VFIm_field32_set(unit, &vfi_entry, BC_INDEXf, bc_group); 1609 } 1610 } 1611 #if defined(BCM_TRIDENT3_SUPPORT) 1612 if (SOC_IS_TRIDENT3X(unit)) { 1613 uint32 profile_idx = 0; 1614 rv = _bcm_td3_def_vfi_profile_add(unit, 1615 info->flags & BCM_L2GRE_VPN_ELINE, &profile_idx); 1616 if (BCM_E_NONE == rv) { 1617 soc_VFIm_field32_set(unit, &vfi_entry, VFI_PROFILE_PTRf, profile_idx); 1618 } 1619 _BCM_L2GRE_CLEANUP(rv); 1620 } 1621 #endif 1622 /* Write VFI to ASIC */ 1623 rv = WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry); 1624 _BCM_L2GRE_CLEANUP(rv); 1625 1626 if (info->flags & BCM_L2GRE_VPN_WITH_VPNID) { 1627 /* Configurate mpls entry for ingress VPNID */ 1628 rv = _bcm_tr3_l2gre_match_vpnid_entry_set(unit, info); 1629 _BCM_L2GRE_CLEANUP(rv); 1630 vpnid_alloc_flag = 1; 1631 1632 /* Configurate EGR_VLAN_XLATE for Egress VPNID */ 1633 rv = _bcm_tr3_l2gre_egr_xlate_entry_set(unit, info); 1634 _BCM_L2GRE_CLEANUP(rv); 1635 } else { 1636 /* Reset vpnid entry */ 1637 rv = _bcm_tr3_l2gre_egr_xlate_entry_get(unit, vfi_index, &mem, vxlate); 1638 if (BCM_E_NOT_FOUND == rv) { 1639 return BCM_E_NONE; 1640 } else if (BCM_E_NONE == rv) { 1641 vpnid = soc_mem_field32_get(unit, mem, vxlate, L2GRE_VFI__VPNIDf); 1642 rv = _bcm_tr3_l2gre_match_vpnid_entry_reset(unit, vpnid); 1643 _BCM_L2GRE_CLEANUP(rv); 1644 } else { 1645 goto cleanup; 1646 } 1647 1648 /* Reset egr_vxlate entry */ 1649 rv = _bcm_tr3_l2gre_egr_xlate_entry_reset(unit, info->vpn); 1650 BCM_IF_ERROR_RETURN(rv); 1651 } 1652 1653 return BCM_E_NONE; 1654 1655 cleanup: 1656 if (vpnid_alloc_flag) { 1657 _bcm_tr3_l2gre_match_vpnid_entry_reset(unit, info->vpnid); 1658 } 1659 if ( vpn_alloc_flag ) { 1660 _bcm_vfi_free(unit, _bcmVfiTypeVxlan, vfi_index); 1661 } 1662 1663 return rv; 1664 } 1665 1666 /* Function: 1667 * _bcm_tr3_xlate_entry_get 1668 * Purpose: 1669 * Get EGR_VLAN_XLATE per VPN instance 1670 * Parameters: 1671 * unit - Device Number 1672 * vfi - l2gre VPN 1673 * vxlate_entry - EGR_VLAN_XLATE entry 1674 * Returns: 1675 * BCM_E_XXXX 1676 */ 1677 1678 STATIC int 1679 _bcm_tr3_l2gre_egr_xlate_entry_get( int unit, int vfi, soc_mem_t *mem, uint32 *vxlate_entry) 1680 { 1681 int index=0; 1682 1683 sal_memset(vxlate_entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 1684 1685 #if defined(BCM_TRIDENT3_SUPPORT) 1686 if (soc_feature(unit, soc_feature_base_valid)) { 1687 *mem = EGR_VLAN_XLATE_1_DOUBLEm; 1688 1689 soc_mem_field32_set(unit, *mem, vxlate_entry, BASE_VALID_0f, 3); 1690 soc_mem_field32_set(unit, *mem, vxlate_entry, BASE_VALID_1f, 7); 1691 soc_mem_field32_set(unit, *mem, vxlate_entry, 1692 KEY_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_VFI); 1693 soc_mem_field32_set(unit, *mem, vxlate_entry, 1694 DATA_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_VFI); 1695 } else 1696 #endif 1697 { 1698 *mem = EGR_VLAN_XLATEm; 1699 1700 if (SOC_IS_TRIUMPH3(unit)) { 1701 soc_mem_field32_set(unit, *mem, vxlate_entry, 1702 KEY_TYPEf, _BCM_TR3_L2GRE_KEY_TYPE_LOOKUP_VFI); 1703 } else if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) { 1704 soc_mem_field32_set(unit, *mem, vxlate_entry, 1705 ENTRY_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_VFI); 1706 } 1707 soc_mem_field32_set(unit, *mem, vxlate_entry, VALIDf, 1); 1708 } 1709 soc_mem_field32_set(unit, *mem, vxlate_entry, L2GRE_VFI__VFIf, vfi); 1710 1711 BCM_IF_ERROR_RETURN(soc_mem_search(unit, *mem, 1712 MEM_BLOCK_ANY, &index, vxlate_entry, vxlate_entry, 0)); 1713 1714 return BCM_E_NONE; 1715 } 1716 1717 1718 /* 1719 * Function: 1720 * bcm_tr3_l2gre_vpn_destroy 1721 * Purpose: 1722 * Delete a VPN instance 1723 * Parameters: 1724 * unit - Device Number 1725 * vpn - VPN instance ID 1726 * Returns: 1727 * BCM_E_XXX 1728 */ 1729 1730 int 1731 bcm_tr3_l2gre_vpn_destroy(int unit, bcm_vpn_t l2vpn) 1732 { 1733 int vfi = 0; 1734 soc_mem_t mem; 1735 uint32 vxlate[SOC_MAX_MEM_WORDS]; 1736 int rv; 1737 uint8 isEline; 1738 uint32 vpnid = 0; 1739 1740 /* Get vfi index */ 1741 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_vpn_is_eline(unit, l2vpn, &isEline)); 1742 if (isEline == 0x1 ) { 1743 _BCM_L2GRE_VPN_GET(vfi, _BCM_L2GRE_VPN_TYPE_ELINE, l2vpn); 1744 } else if (isEline == 0x0 ) { 1745 _BCM_L2GRE_VPN_GET(vfi, _BCM_L2GRE_VPN_TYPE_ELAN, l2vpn); 1746 } 1747 1748 rv = _bcm_tr3_l2gre_egr_xlate_entry_get(unit, vfi, &mem, vxlate); 1749 if (BCM_E_NONE == rv) { 1750 /* Reset match vnid table */ 1751 vpnid = soc_mem_field32_get(unit, mem, vxlate, L2GRE_VFI__VPNIDf); 1752 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_match_vpnid_entry_reset(unit, vpnid)); 1753 1754 /* Delete egr_vxlate entry */ 1755 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_egr_xlate_entry_reset(unit, l2vpn)); 1756 } else if (BCM_E_NOT_FOUND != rv) { 1757 return rv; 1758 } 1759 1760 /* Delete all L2GRE ports on this VPN */ 1761 rv = bcm_tr3_l2gre_port_delete_all(unit, l2vpn); 1762 BCM_IF_ERROR_RETURN(rv); 1763 1764 1765 /* Reset VFI table */ 1766 (void)_bcm_vfi_free(unit, _bcmVfiTypeL2Gre, vfi); 1767 return BCM_E_NONE; 1768 } 1769 1770 /* Function: 1771 * bcm_tr3_l2gre_vpn_id_destroy_all 1772 * Purpose: 1773 * Delete all L2-VPN instances 1774 * Parameters: 1775 * unit - Device Number 1776 * Returns: 1777 * BCM_E_XXXX 1778 */ 1779 1780 int 1781 bcm_tr3_l2gre_vpn_destroy_all(int unit) 1782 { 1783 int num_vfi, idx; 1784 bcm_vpn_t l2vpn; 1785 1786 /* Destroy all L2GRE VPNs */ 1787 num_vfi = soc_mem_index_count(unit, VFIm); 1788 for (idx = 0; idx < num_vfi; idx++) { 1789 if (_bcm_vfi_used_get(unit, idx, _bcmVfiTypeL2Gre)) { 1790 _BCM_L2GRE_VPN_SET(l2vpn, _BCM_VPN_TYPE_VFI, idx); 1791 BCM_IF_ERROR_RETURN(bcm_tr3_l2gre_vpn_destroy(unit, l2vpn)); 1792 } 1793 } 1794 return BCM_E_NONE; 1795 } 1796 1797 1798 /* Function: 1799 * bcm_tr3_l2gre_vpn_get 1800 * Purpose: 1801 * Get L2-VPN instance 1802 * Parameters: 1803 * unit - Device Number 1804 * l2vpn - L2GRE VPN 1805 * info - L2GRE VPN Config 1806 * Returns: 1807 * BCM_E_XXXX 1808 */ 1809 1810 int 1811 bcm_tr3_l2gre_vpn_get( int unit, bcm_vpn_t l2vpn, bcm_l2gre_vpn_config_t *info) 1812 { 1813 int vfi_index = 0; 1814 vfi_entry_t vfi_entry; 1815 soc_mem_t mem; 1816 uint32 vxlate[SOC_MAX_MEM_WORDS]; 1817 uint8 isEline; 1818 int rv = BCM_E_NONE; 1819 1820 /* Get vfi index */ 1821 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_vpn_is_eline(unit, l2vpn, &isEline)); 1822 if (isEline == 0x1 ) { 1823 _BCM_L2GRE_VPN_GET(vfi_index, _BCM_L2GRE_VPN_TYPE_ELINE, l2vpn); 1824 } else if (isEline == 0x0 ) { 1825 _BCM_L2GRE_VPN_GET(vfi_index, _BCM_L2GRE_VPN_TYPE_ELAN, l2vpn); 1826 } 1827 BCM_IF_ERROR_RETURN(READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry)); 1828 1829 /* Set the returned VPN id */ 1830 if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) { 1831 info->flags = BCM_L2GRE_VPN_ELINE; 1832 } else { 1833 info->flags = BCM_L2GRE_VPN_ELAN; 1834 #if defined(BCM_TRIDENT3_SUPPORT) 1835 if (soc_feature(unit, soc_feature_generic_dest)) { 1836 uint32 dt, dv; 1837 1838 dv = soc_mem_field32_dest_get(unit, VFIm, 1839 &vfi_entry, BC_DESTINATIONf, &dt); 1840 if (dt == SOC_MEM_FIF_DEST_IPMC) { 1841 _BCM_MULTICAST_GROUP_SET(info->broadcast_group, 1842 _BCM_MULTICAST_TYPE_L2GRE, dv); 1843 } else { 1844 return BCM_E_INTERNAL; 1845 } 1846 1847 dv = soc_mem_field32_dest_get(unit, VFIm, 1848 &vfi_entry, UUC_DESTINATIONf, &dt); 1849 if (dt == SOC_MEM_FIF_DEST_IPMC) { 1850 _BCM_MULTICAST_GROUP_SET(info->unknown_unicast_group, 1851 _BCM_MULTICAST_TYPE_L2GRE, dv); 1852 } else { 1853 return BCM_E_INTERNAL; 1854 } 1855 1856 dv = soc_mem_field32_dest_get(unit, VFIm, 1857 &vfi_entry, UMC_DESTINATIONf, &dt); 1858 if (dt == SOC_MEM_FIF_DEST_IPMC) { 1859 _BCM_MULTICAST_GROUP_SET(info->unknown_multicast_group, 1860 _BCM_MULTICAST_TYPE_L2GRE, dv); 1861 } else { 1862 return BCM_E_INTERNAL; 1863 } 1864 } else 1865 #endif 1866 { 1867 _BCM_MULTICAST_GROUP_SET(info->broadcast_group, 1868 _BCM_MULTICAST_TYPE_L2GRE, 1869 soc_VFIm_field32_get(unit, &vfi_entry, BC_INDEXf)); 1870 _BCM_MULTICAST_GROUP_SET(info->unknown_unicast_group, 1871 _BCM_MULTICAST_TYPE_L2GRE, 1872 soc_VFIm_field32_get(unit, &vfi_entry, UUC_INDEXf)); 1873 _BCM_MULTICAST_GROUP_SET(info->unknown_multicast_group, 1874 _BCM_MULTICAST_TYPE_L2GRE, 1875 soc_VFIm_field32_get(unit, &vfi_entry, UMC_INDEXf)); 1876 } 1877 } 1878 _BCM_L2GRE_VPN_SET(info->vpn, _BCM_VPN_TYPE_VFI, vfi_index); 1879 1880 rv = _bcm_tr3_l2gre_egr_xlate_entry_get(unit, vfi_index, &mem, vxlate); 1881 if (BCM_E_NONE == rv) { 1882 /* Get VPNID */ 1883 info->flags |= BCM_L2GRE_VPN_WITH_VPNID; 1884 info->vpnid = soc_mem_field32_get(unit, mem, vxlate, L2GRE_VFI__VPNIDf); 1885 1886 /* Get SDTAG settings */ 1887 (void)_bcm_tr3_l2gre_sd_tag_get( unit, info, NULL, NULL, vxlate, 1); 1888 } else if (BCM_E_NOT_FOUND != rv) { 1889 return rv; 1890 } 1891 1892 return rv; 1893 } 1894 1895 /* Function: 1896 * _bcm_tr3_l2gre_vpn_get 1897 * Purpose: 1898 * Get L2-VPN instance for L2GRE 1899 * Parameters: 1900 * unit - Device Number 1901 * vfi_index - vfi_index 1902 * vid (OUT) VLAN Id (l2vpn id) 1903 * Returns: 1904 * BCM_E_XXXX 1905 */ 1906 int 1907 _bcm_tr3_l2gre_vpn_get(int unit, int vfi_index, bcm_vlan_t *vid) 1908 { 1909 vfi_entry_t vfi_entry; 1910 1911 BCM_IF_ERROR_RETURN 1912 (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry)); 1913 1914 if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) { 1915 _BCM_L2GRE_VPN_SET(*vid, _BCM_L2GRE_VPN_TYPE_ELINE, vfi_index); 1916 } else { 1917 _BCM_L2GRE_VPN_SET(*vid, _BCM_L2GRE_VPN_TYPE_ELAN, vfi_index); 1918 } 1919 return BCM_E_NONE; 1920 } 1921 1922 /* 1923 * Function: 1924 * bcm_tr3_l2gre_vpn_traverse 1925 * Purpose: 1926 * Get information about a VPN instance 1927 * Parameters: 1928 * unit - (IN) Device Number 1929 * cb - (IN) User-provided callback 1930 * info - (IN/OUT) Cookie 1931 * Returns: 1932 * BCM_E_XXX 1933 */ 1934 1935 int bcm_tr3_l2gre_vpn_traverse(int unit, bcm_l2gre_vpn_traverse_cb cb, 1936 void *user_data) 1937 { 1938 int idx, num_vfi; 1939 int vpn; 1940 bcm_l2gre_vpn_config_t info; 1941 1942 /* L2GRE VPNs */ 1943 num_vfi = soc_mem_index_count(unit, VFIm); 1944 for (idx = 0; idx < num_vfi; idx++) { 1945 if (_bcm_vfi_used_get(unit, idx, _bcmVfiTypeL2Gre)) { 1946 _BCM_L2GRE_VPN_SET(vpn, _BCM_VPN_TYPE_VFI, idx); 1947 bcm_l2gre_vpn_config_t_init(&info); 1948 BCM_IF_ERROR_RETURN(bcm_tr3_l2gre_vpn_get(unit, vpn, &info)); 1949 BCM_IF_ERROR_RETURN(cb(unit, &info, user_data)); 1950 } 1951 } 1952 return BCM_E_NONE; 1953 } 1954 1955 /* 1956 * Function: 1957 * _bcm_tr3_l2gre_tunnel_terminate_entry_key_set 1958 * Purpose: 1959 * Set L2GRE Tunnel Terminate entry key set 1960 * Parameters: 1961 * IN : Unit 1962 * IN : tnl_info 1963 * IN(OUT) : tr_ent VLAN_XLATE entry pointer 1964 * IN : clean_flag 1965 * Returns: 1966 * BCM_E_XXX 1967 */ 1968 1969 STATIC void 1970 _bcm_tr3_l2gre_tunnel_terminate_entry_key_set(int unit, soc_mem_t *mem, 1971 bcm_tunnel_terminator_t *tnl_info, uint32 *tr_ent, uint8 out_mode) 1972 { 1973 sal_memset(tr_ent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 1974 1975 #if defined(BCM_TRIDENT3_SUPPORT) 1976 if (soc_feature(unit, soc_feature_base_valid)) { 1977 *mem = VLAN_XLATE_1_DOUBLEm; 1978 1979 soc_mem_field32_set(unit, *mem, tr_ent, BASE_VALID_0f, 3); 1980 soc_mem_field32_set(unit, *mem, tr_ent, BASE_VALID_1f, 7); 1981 soc_mem_field32_set(unit, *mem, tr_ent, KEY_TYPEf, 1982 _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP); 1983 soc_mem_field32_set(unit, *mem, tr_ent, DATA_TYPEf, 1984 _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP); 1985 } else 1986 #endif 1987 { 1988 *mem = VLAN_XLATEm; 1989 1990 if (SOC_IS_TRIUMPH3(unit)) { 1991 soc_mem_field32_set(unit, *mem, tr_ent, KEY_TYPEf, 1992 _BCM_TR3_L2GRE_KEY_TYPE_LOOKUP_DIP); /* L2GRE_DIP Key */ 1993 } else if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) { 1994 soc_mem_field32_set(unit, *mem, tr_ent, KEY_TYPEf, 1995 _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP); /* L2GRE_DIP Key */ 1996 } 1997 soc_mem_field32_set(unit, *mem, tr_ent, VALIDf, 0x1); 1998 } 1999 soc_mem_field32_set(unit, *mem, tr_ent, L2GRE_DIP__DIPf, tnl_info->dip); 2000 2001 if (out_mode == _BCM_L2GRE_MULTICAST_BUD) { 2002 soc_mem_field32_set(unit, *mem, tr_ent, 2003 L2GRE_DIP__NETWORK_RECEIVERS_PRESENTf, 0x1); 2004 _bcm_tr3_l2gre_bud_loopback_enable(unit); 2005 } else if (out_mode == _BCM_L2GRE_MULTICAST_LEAF) { 2006 soc_mem_field32_set(unit, *mem, tr_ent, 2007 L2GRE_DIP__NETWORK_RECEIVERS_PRESENTf, 0x0); 2008 } 2009 } 2010 2011 /* 2012 * Function: 2013 * _bcm_tr3_l2gre_tunnel_terminator_reference_count 2014 * Purpose: 2015 * Find L2GRE Tunnel terminator DIP reference count 2016 * Returns: BCM_E_XXX 2017 */ 2018 2019 STATIC int 2020 _bcm_tr3_l2gre_tunnel_terminator_reference_count(int unit, bcm_ip_t dest_ip_addr) 2021 { 2022 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 2023 int tunnel_idx=0, num_vp=0, ref_count=0; 2024 2025 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 2026 l2gre_info = L2GRE_INFO(unit); 2027 2028 for (tunnel_idx=0; tunnel_idx< num_vp; tunnel_idx++) { 2029 if (l2gre_info->l2gre_tunnel_term[tunnel_idx].dip == dest_ip_addr) { 2030 ref_count ++; 2031 } 2032 } 2033 return ref_count; 2034 } 2035 2036 /* 2037 * Function: 2038 * _bcm_tr3_l2gre_multicast_tunnel_state_set 2039 * Purpose: 2040 * Set L2GRE Tunnel terminator Multicast State 2041 * Returns: BCM_E_XXX 2042 */ 2043 2044 2045 STATIC void 2046 _bcm_tr3_l2gre_multicast_tunnel_state_set (int unit, int tunnel_idx, uint8 tunnel_state) 2047 { 2048 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 2049 2050 l2gre_info = L2GRE_INFO(unit); 2051 2052 if (tunnel_idx != -1) { 2053 l2gre_info->l2gre_tunnel_term[tunnel_idx].tunnel_state = tunnel_state; 2054 } 2055 } 2056 2057 2058 /* 2059 * Function: 2060 * _bcm_tr3_l2gre_multicast_tunnel_state_index_get 2061 * Purpose: 2062 * Get L2GRE Tunnel terminator Multicast State and Tunnel Index 2063 * Returns: BCM_E_XXX 2064 */ 2065 2066 2067 STATIC void 2068 _bcm_tr3_l2gre_multicast_tunnel_state_index_get (int unit, 2069 bcm_ip_t mc_ip_addr, bcm_ip_t src_ip_addr, uint8 *tunnel_state, int *tunnel_index) 2070 { 2071 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 2072 int idx=0, num_vp=0; 2073 2074 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 2075 l2gre_info = L2GRE_INFO(unit); 2076 2077 for (idx=0; idx< num_vp; idx++) { 2078 if (l2gre_info->l2gre_tunnel_term[idx].dip == mc_ip_addr) { 2079 if (l2gre_info->l2gre_tunnel_term[idx].sip == src_ip_addr) { 2080 *tunnel_state = l2gre_info->l2gre_tunnel_term[idx].tunnel_state; 2081 *tunnel_index = idx; 2082 break; 2083 } 2084 } 2085 } 2086 } 2087 2088 /* 2089 * Function: 2090 * _bcm_tr3_l2gre_tunnel_terminator_state_find 2091 * Purpose: 2092 * Find L2GRE Tunnel terminator DIP State 2093 * Returns: BCM_E_XXX 2094 */ 2095 2096 STATIC int 2097 _bcm_tr3_l2gre_tunnel_terminator_state_find(int unit, bcm_ip_t dest_ip_addr) 2098 { 2099 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 2100 int tunnel_idx=0, num_vp=0, tunnel_state=0; 2101 2102 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 2103 l2gre_info = L2GRE_INFO(unit); 2104 2105 for (tunnel_idx=0; tunnel_idx< num_vp; tunnel_idx++) { 2106 if (l2gre_info->l2gre_tunnel_term[tunnel_idx].dip == dest_ip_addr) { 2107 if (l2gre_info->l2gre_tunnel_term[tunnel_idx].tunnel_state == _BCM_L2GRE_TUNNEL_TERM_MULTICAST_LEAF ) { 2108 tunnel_state += 0; 2109 } else if (l2gre_info->l2gre_tunnel_term[tunnel_idx].tunnel_state == _BCM_L2GRE_TUNNEL_TERM_MULTICAST_BUD ) { 2110 tunnel_state += 1; 2111 } 2112 } 2113 } 2114 return tunnel_state; 2115 } 2116 2117 /* 2118 * Function: 2119 * bcm_tr3_l2gre_multicast_leaf_entry_check 2120 * Purpose: 2121 * To find whether LEAF-multicast entry exists for DIP? 2122 * Returns: 2123 * BCM_E_XXX 2124 */ 2125 2126 int 2127 bcm_tr3_l2gre_multicast_leaf_entry_check(int unit, bcm_ip_t mc_ip_addr, bcm_ip_t src_ip_addr, int multicast_flag) 2128 { 2129 int rv=BCM_E_NONE, index=0; 2130 int tunnel_ref_count = 0; 2131 uint8 tunnel_multicast_state = 0; 2132 int tunnel_mc_states = 0, tunnel_idx=0; 2133 soc_mem_t mem; 2134 uint32 vxlate[SOC_MAX_MEM_WORDS] = {0}; 2135 2136 tunnel_ref_count = _bcm_tr3_l2gre_tunnel_terminator_reference_count(unit, mc_ip_addr); 2137 2138 if (tunnel_ref_count < 1) { 2139 /* Tunnel not created */ 2140 return BCM_E_NONE; 2141 } else if (tunnel_ref_count >= 1) { 2142 (void )_bcm_tr3_l2gre_multicast_tunnel_state_index_get (unit, 2143 mc_ip_addr, src_ip_addr, &tunnel_multicast_state, &tunnel_idx); 2144 2145 /* Set (SIP, DIP) based Software State */ 2146 if (multicast_flag == BCM_L2GRE_MULTICAST_TUNNEL_STATE_BUD_ENABLE) { 2147 if (tunnel_multicast_state == _BCM_L2GRE_TUNNEL_TERM_MULTICAST_LEAF) { 2148 (void) _bcm_tr3_l2gre_multicast_tunnel_state_set(unit, 2149 tunnel_idx, _BCM_L2GRE_TUNNEL_TERM_MULTICAST_BUD); 2150 } 2151 } else if (multicast_flag == BCM_L2GRE_MULTICAST_TUNNEL_STATE_BUD_DISABLE){ 2152 if (tunnel_multicast_state == _BCM_L2GRE_TUNNEL_TERM_MULTICAST_BUD) { 2153 (void) _bcm_tr3_l2gre_multicast_tunnel_state_set(unit, 2154 tunnel_idx, _BCM_L2GRE_TUNNEL_TERM_MULTICAST_LEAF); 2155 } 2156 } 2157 2158 /* Set DIP-based cumulative hardware State */ 2159 tunnel_mc_states = _bcm_tr3_l2gre_tunnel_terminator_state_find(unit, mc_ip_addr); 2160 2161 #if defined(BCM_TRIDENT3_SUPPORT) 2162 if (soc_feature(unit, soc_feature_base_valid)) { 2163 mem = VLAN_XLATE_1_DOUBLEm; 2164 2165 soc_mem_field32_set(unit, mem, vxlate, BASE_VALID_0f, 3); 2166 soc_mem_field32_set(unit, mem, vxlate, BASE_VALID_1f, 7); 2167 soc_mem_field32_set(unit, mem, vxlate, 2168 KEY_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP); 2169 soc_mem_field32_set(unit, mem, vxlate, 2170 DATA_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP); 2171 } else 2172 #endif 2173 { 2174 mem = VLAN_XLATEm; 2175 2176 if (SOC_IS_TRIUMPH3(unit)) { 2177 soc_mem_field32_set(unit, mem, vxlate, 2178 KEY_TYPEf, _BCM_TR3_L2GRE_KEY_TYPE_LOOKUP_DIP); 2179 } else if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) { 2180 soc_mem_field32_set(unit, mem, vxlate, 2181 KEY_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP); 2182 } 2183 soc_mem_field32_set(unit, mem, vxlate, VALIDf, 1); 2184 } 2185 soc_mem_field32_set(unit, mem, vxlate, L2GRE_DIP__DIPf, mc_ip_addr); 2186 2187 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, vxlate, vxlate, 0); 2188 if (rv == SOC_E_NONE) { 2189 if (tunnel_mc_states) { 2190 /* Create Transit entry: LEAF to BUD */ 2191 soc_mem_field32_set(unit, mem, vxlate, 2192 L2GRE_DIP__NETWORK_RECEIVERS_PRESENTf, 0x1); 2193 _bcm_tr3_l2gre_bud_loopback_enable(unit); 2194 } else { 2195 /* Delete Transit entry : BUD to LEAF */ 2196 soc_mem_field32_set(unit, mem, vxlate, 2197 L2GRE_DIP__NETWORK_RECEIVERS_PRESENTf, 0x0); 2198 } 2199 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, vxlate); 2200 } 2201 } 2202 return BCM_E_NONE; 2203 } 2204 2205 /* 2206 * Function: 2207 * bcm_tr3_l2gre_tunnel_terminator_create 2208 * Purpose: 2209 * Set L2GRE Tunnel terminator 2210 * Parameters: 2211 * unit - Device Number 2212 * tnl_info 2213 * Returns: 2214 * BCM_E_XXX 2215 */ 2216 int 2217 bcm_tr3_l2gre_tunnel_terminator_create(int unit, bcm_tunnel_terminator_t *tnl_info) 2218 { 2219 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 2220 int index=-1, tunnel_idx=-1; 2221 int rv = BCM_E_NONE; 2222 soc_mem_t mem; 2223 uint32 vxlate[SOC_MAX_MEM_WORDS] = {0}; 2224 2225 if (soc_feature(unit, soc_feature_base_valid)) { 2226 mem = VLAN_XLATE_1_DOUBLEm; 2227 } 2228 2229 if (tnl_info->type != bcmTunnelTypeL2Gre) { 2230 return BCM_E_PARAM; 2231 } 2232 2233 /* Program tunnel id */ 2234 if (tnl_info->flags & BCM_TUNNEL_TERM_TUNNEL_WITH_ID) { 2235 if (!BCM_GPORT_IS_TUNNEL(tnl_info->tunnel_id)) { 2236 return BCM_E_PARAM; 2237 } 2238 tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(tnl_info->tunnel_id); 2239 } else { 2240 /* Only BCM_TUNNEL_TERM_TUNNEL_WITH_ID supported */ 2241 /* Use tunnel_id retuned by _create */ 2242 return BCM_E_PARAM; 2243 } 2244 2245 /* Add First Tunnel term-entry for given DIP to Hardware */ 2246 if (_bcm_tr3_l2gre_tunnel_terminator_reference_count(unit, tnl_info->dip) < 1) { 2247 2248 (void)_bcm_tr3_l2gre_tunnel_terminate_entry_key_set(unit, &mem, tnl_info, vxlate, 0); 2249 2250 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, vxlate, vxlate, 0); 2251 if (rv == SOC_E_NOT_FOUND) { 2252 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, vxlate); 2253 } else if (rv < 0) { 2254 return rv; 2255 } 2256 } 2257 2258 l2gre_info = L2GRE_INFO(unit); 2259 if (BCM_SUCCESS(rv) && (tunnel_idx != -1)) { 2260 l2gre_info->l2gre_tunnel_term[tunnel_idx].sip = tnl_info->sip; 2261 l2gre_info->l2gre_tunnel_term[tunnel_idx].dip = tnl_info->dip; 2262 l2gre_info->l2gre_tunnel_term[tunnel_idx].tunnel_state = _BCM_L2GRE_TUNNEL_TERM_MULTICAST_LEAF; 2263 } 2264 return rv; 2265 } 2266 2267 /* 2268 * Function: 2269 * bcm_tr3_l2gre_tunnel_terminator_update 2270 * Purpose: 2271 * Update L2GRE Tunnel terminator multicast state 2272 * Parameters: 2273 * unit - Device Number 2274 * tnl_info 2275 * Returns: 2276 * BCM_E_XXX 2277 */ 2278 int 2279 bcm_tr3_l2gre_tunnel_terminator_update(int unit, bcm_tunnel_terminator_t *tnl_info) 2280 { 2281 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 2282 int rv = BCM_E_NONE; 2283 int tunnel_idx=-1; 2284 bcm_ip_t mc_ip_addr, src_ip_addr; 2285 2286 l2gre_info = L2GRE_INFO(unit); 2287 2288 /* Program tunnel id */ 2289 if (tnl_info->flags & BCM_TUNNEL_TERM_TUNNEL_WITH_ID) { 2290 if (!BCM_GPORT_IS_TUNNEL(tnl_info->tunnel_id)) { 2291 return BCM_E_PARAM; 2292 } 2293 tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(tnl_info->tunnel_id); 2294 } else { 2295 /* Only BCM_TUNNEL_TERM_TUNNEL_WITH_ID supported */ 2296 /* Use tunnel_id retuned by _create */ 2297 return BCM_E_PARAM; 2298 } 2299 2300 mc_ip_addr = l2gre_info->l2gre_tunnel_term[tunnel_idx].dip; 2301 src_ip_addr = l2gre_info->l2gre_tunnel_term[tunnel_idx].sip; 2302 2303 rv = bcm_tr3_l2gre_multicast_leaf_entry_check(unit, 2304 mc_ip_addr, src_ip_addr, tnl_info->multicast_flag); 2305 return rv; 2306 } 2307 2308 /* 2309 * Function: 2310 * bcm_tr3_l2gre_tunnel_terminate_destroy 2311 * Purpose: 2312 * Destroy L2GRE tunnel_terminate Entry 2313 * Parameters: 2314 * IN : Unit 2315 * IN : l2gre_tunnel_id 2316 * Returns: 2317 * BCM_E_XXX 2318 */ 2319 2320 int 2321 bcm_tr3_l2gre_tunnel_terminator_destroy(int unit, bcm_gport_t l2gre_tunnel_id) 2322 { 2323 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 2324 int tunnel_idx, index; 2325 uint32 tunnel_dip=0; 2326 int rv = BCM_E_NONE; 2327 soc_mem_t mem = VLAN_XLATEm; 2328 uint32 vxlate[SOC_MAX_MEM_WORDS] = {0}; 2329 2330 if (!BCM_GPORT_IS_TUNNEL(l2gre_tunnel_id)) { 2331 return BCM_E_PARAM; 2332 } 2333 tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(l2gre_tunnel_id); 2334 2335 l2gre_info = L2GRE_INFO(unit); 2336 tunnel_dip = l2gre_info->l2gre_tunnel_term[tunnel_idx].dip; 2337 2338 /* Remove Tunnel term-entry for given DIP from Hardware based on ref-count */ 2339 if (_bcm_tr3_l2gre_tunnel_terminator_reference_count(unit, tunnel_dip) == 1) { 2340 #if defined(BCM_TRIDENT3_SUPPORT) 2341 if (soc_feature(unit, soc_feature_base_valid)) { 2342 mem = VLAN_XLATE_1_DOUBLEm; 2343 2344 soc_mem_field32_set(unit, mem, vxlate, BASE_VALID_0f, 3); 2345 soc_mem_field32_set(unit, mem, vxlate, BASE_VALID_1f, 7); 2346 soc_mem_field32_set(unit, mem, vxlate, 2347 KEY_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP); 2348 soc_mem_field32_set(unit, mem, vxlate, 2349 DATA_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP); 2350 } else 2351 #endif 2352 { 2353 mem = VLAN_XLATEm; 2354 2355 if (SOC_IS_TRIUMPH3(unit)) { 2356 soc_mem_field32_set(unit, mem, vxlate, 2357 KEY_TYPEf, _BCM_TR3_L2GRE_KEY_TYPE_LOOKUP_DIP); 2358 } else if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) { 2359 soc_mem_field32_set(unit, mem, vxlate, 2360 KEY_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP); 2361 } 2362 soc_mem_field32_set(unit, mem, vxlate, VALIDf, 1); 2363 } 2364 soc_mem_field32_set(unit, mem, vxlate, L2GRE_DIP__DIPf, tunnel_dip); 2365 soc_mem_field32_set(unit, mem, vxlate, L2GRE_DIP__NETWORK_RECEIVERS_PRESENTf, 0); 2366 2367 BCM_IF_ERROR_RETURN( 2368 soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, vxlate, vxlate, 0)); 2369 2370 /* Delete the entry from HW */ 2371 BCM_IF_ERROR_RETURN(soc_mem_delete(unit, mem, MEM_BLOCK_ALL, vxlate)); 2372 } 2373 2374 if (BCM_SUCCESS(rv) && (tunnel_idx != -1)) { 2375 l2gre_info->l2gre_tunnel_term[tunnel_idx].dip = 0; 2376 l2gre_info->l2gre_tunnel_term[tunnel_idx].tunnel_state = _BCM_L2GRE_TUNNEL_TERM_MULTICAST_LEAF; 2377 } 2378 2379 return rv; 2380 } 2381 2382 /* 2383 * Function: 2384 * bcm_tr3_l2gre_tunnel_terminator_destroy_all 2385 * Purpose: 2386 * Destroy all incoming L2GRE tunnel 2387 * Parameters: 2388 * unit - (IN) Device Number 2389 */ 2390 int 2391 bcm_tr3_l2gre_tunnel_terminator_destroy_all(int unit) 2392 { 2393 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 2394 int rv = BCM_E_UNAVAIL, tnl_idx=0,num_vp=0; 2395 uint32 *vtab, *vtabp; 2396 int i, imin, imax, nent; 2397 soc_mem_t mem; 2398 2399 #if defined(BCM_TRIDENT3_SUPPORT) 2400 if (soc_feature(unit, soc_feature_base_valid)) { 2401 mem = VLAN_XLATE_1_DOUBLEm; 2402 } else 2403 #endif 2404 { 2405 mem = VLAN_XLATEm; 2406 } 2407 2408 l2gre_info = L2GRE_INFO(unit); 2409 2410 if (!SOC_HW_RESET(unit) && (SOC_SWITCH_BYPASS_MODE(unit) == SOC_SWITCH_BYPASS_MODE_NONE)) { 2411 imin = soc_mem_index_min(unit, mem); 2412 imax = soc_mem_index_max(unit, mem); 2413 nent = soc_mem_index_count(unit, mem); 2414 2415 vtab = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, mem), "vlan_xlate"); 2416 if (vtab == NULL) { 2417 return BCM_E_MEMORY; 2418 } 2419 sal_memset(vtab, 0, nent * sizeof(*vtab)); 2420 2421 soc_mem_lock(unit, mem); 2422 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 2423 imin, imax, vtab); 2424 if (BCM_FAILURE(rv)) { 2425 soc_mem_unlock(unit, mem); 2426 soc_cm_sfree(unit, vtab); 2427 return rv; 2428 } 2429 for (i = 0; i < nent; i++) { 2430 vtabp = soc_mem_table_idx_to_pointer(unit, mem, 2431 void *, vtab, i); 2432 2433 #if defined(BCM_TRIDENT3_SUPPORT) 2434 if (soc_feature(unit, soc_feature_base_valid)) { 2435 if (soc_mem_field32_get(unit, mem, vtabp, BASE_VALID_0f) != 3) { 2436 continue; 2437 } 2438 if (soc_mem_field32_get(unit, mem, vtabp, BASE_VALID_1f) != 7) { 2439 continue; 2440 } 2441 if (soc_mem_field32_get(unit, mem, vtabp, KEY_TYPEf) != 2442 _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP) { 2443 continue; 2444 } 2445 if (soc_mem_field32_get(unit, mem, vtabp, DATA_TYPEf) != 2446 _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP) { 2447 continue; 2448 } 2449 } else 2450 #endif 2451 { 2452 if (!soc_mem_field32_get(unit, mem, vtabp, VALIDf)) { 2453 continue; 2454 } 2455 2456 if (SOC_IS_TRIUMPH3(unit)) { 2457 if (soc_mem_field32_get(unit, mem, vtabp, 2458 KEY_TYPEf) != _BCM_TR3_L2GRE_KEY_TYPE_LOOKUP_DIP) { 2459 continue; 2460 } 2461 } else if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) { 2462 if (soc_mem_field32_get(unit, mem, vtabp, 2463 KEY_TYPEf) != _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP) { 2464 continue; 2465 } 2466 } 2467 } 2468 2469 /* Delete the entry from HW */ 2470 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, vtabp); 2471 if (rv < 0) { 2472 soc_mem_unlock(unit, mem); 2473 soc_cm_sfree(unit, vtab); 2474 return rv; 2475 } 2476 } 2477 soc_mem_unlock(unit, mem); 2478 soc_cm_sfree(unit, vtab); 2479 } 2480 2481 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 2482 for (tnl_idx = 0; tnl_idx < num_vp; tnl_idx++) { 2483 l2gre_info->l2gre_tunnel_term[tnl_idx].dip = 0; 2484 l2gre_info->l2gre_tunnel_term[tnl_idx].tunnel_state = 0; 2485 } 2486 2487 return BCM_E_NONE; 2488 } 2489 2490 /* 2491 * Function: 2492 * bcm_tr3_l2gre_tunnel_initiator_get 2493 * Purpose: 2494 * Get L2GRE tunnel_terminate Entry 2495 * Parameters: 2496 * unit - (IN) Device Number 2497 * info - (IN/OUT) Tunnel terminator structure 2498 */ 2499 int 2500 bcm_tr3_l2gre_tunnel_terminator_get(int unit, bcm_tunnel_terminator_t *tnl_info) 2501 { 2502 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 2503 int tunnel_idx=-1, index=-1; 2504 uint32 tunnel_dip=0; 2505 soc_mem_t mem = VLAN_XLATEm; 2506 uint32 vxlate[SOC_MAX_MEM_WORDS] = {0}; 2507 2508 /* Program tunnel id */ 2509 if (!BCM_GPORT_IS_TUNNEL(tnl_info->tunnel_id)) { 2510 return BCM_E_PARAM; 2511 } 2512 tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(tnl_info->tunnel_id); 2513 2514 l2gre_info = L2GRE_INFO(unit); 2515 tunnel_dip = l2gre_info->l2gre_tunnel_term[tunnel_idx].dip; 2516 2517 #if defined(BCM_TRIDENT3_SUPPORT) 2518 if (soc_feature(unit, soc_feature_base_valid)) { 2519 mem = VLAN_XLATE_1_DOUBLEm; 2520 2521 soc_mem_field32_set(unit, mem, vxlate, BASE_VALID_0f, 3); 2522 soc_mem_field32_set(unit, mem, vxlate, BASE_VALID_1f, 7); 2523 soc_mem_field32_set(unit, mem, vxlate, 2524 KEY_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP); 2525 soc_mem_field32_set(unit, mem, vxlate, 2526 DATA_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP); 2527 } else 2528 #endif 2529 { 2530 mem = VLAN_XLATEm; 2531 2532 if (SOC_IS_TRIUMPH3(unit)) { 2533 soc_mem_field32_set(unit, mem, vxlate, 2534 KEY_TYPEf, _BCM_TR3_L2GRE_KEY_TYPE_LOOKUP_DIP); 2535 } else if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) { 2536 soc_mem_field32_set(unit, mem, vxlate, 2537 KEY_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP); 2538 } 2539 soc_mem_field32_set(unit, mem, vxlate, VALIDf, 1); 2540 } 2541 soc_mem_field32_set(unit, mem, vxlate, L2GRE_DIP__DIPf, tunnel_dip); 2542 2543 BCM_IF_ERROR_RETURN( 2544 soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, vxlate, vxlate, 0)); 2545 2546 tnl_info->sip = l2gre_info->l2gre_tunnel_term[tunnel_idx].sip; 2547 tnl_info->dip = l2gre_info->l2gre_tunnel_term[tunnel_idx].dip; 2548 tnl_info->type = bcmTunnelTypeL2Gre; 2549 if (l2gre_info->l2gre_tunnel_term[tunnel_idx].tunnel_state 2550 == _BCM_L2GRE_TUNNEL_TERM_MULTICAST_BUD) { 2551 tnl_info->multicast_flag = BCM_L2GRE_MULTICAST_TUNNEL_STATE_BUD_ENABLE; 2552 } else if (l2gre_info->l2gre_tunnel_term[tunnel_idx].tunnel_state 2553 == _BCM_L2GRE_TUNNEL_TERM_MULTICAST_LEAF){ 2554 tnl_info->multicast_flag = BCM_L2GRE_MULTICAST_TUNNEL_STATE_BUD_DISABLE; 2555 } else { 2556 tnl_info->multicast_flag = 0; 2557 } 2558 2559 return BCM_E_NONE; 2560 } 2561 2562 /* 2563 * Function: 2564 * bcm_tr3_l2gre_tunnel_terminator_traverse 2565 * Purpose: 2566 * Traverse L2GRE tunnel terminator entries 2567 * Parameters: 2568 * unit - (IN) Device Number 2569 * cb - (IN) User callback function, called once per entry 2570 * user_data - (IN) User supplied cookie used in parameter in callback function 2571 */ 2572 int 2573 bcm_tr3_l2gre_tunnel_terminator_traverse(int unit, bcm_tunnel_terminator_traverse_cb cb, void *user_data) 2574 { 2575 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 2576 int num_tnl = 0, idx = 0; 2577 bcm_tunnel_terminator_t info; 2578 int rv = BCM_E_NONE; 2579 2580 l2gre_info = L2GRE_INFO(unit); 2581 num_tnl = soc_mem_index_count(unit, SOURCE_VPm); 2582 2583 /* Iterate over all the entries - search valid ones. */ 2584 for(idx = 0; idx < num_tnl; idx++) { 2585 /* Check a valid entry */ 2586 if (l2gre_info->l2gre_tunnel_term[idx].dip) { 2587 /* Reset buffer before read. */ 2588 bcm_tunnel_terminator_t_init(&info); 2589 2590 BCM_GPORT_TUNNEL_ID_SET(info.tunnel_id, idx); 2591 2592 rv = bcm_tr3_l2gre_tunnel_terminator_get(unit,&info); 2593 2594 /* search failure */ 2595 if (BCM_FAILURE(rv)) { 2596 break; 2597 } 2598 2599 if (cb) { 2600 rv = (*cb) (unit, &info, user_data); 2601 #ifdef BCM_CB_ABORT_ON_ERR 2602 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 2603 break; 2604 } 2605 #endif 2606 } 2607 } 2608 } 2609 2610 return rv; 2611 } 2612 2613 2614 /* 2615 * Function: 2616 * _bcm_tr3_l2gre_tunnel_init_add 2617 * Purpose: 2618 * Add tunnel initiator entry to hw. 2619 * Parameters: 2620 * unit - (IN)SOC unit number. 2621 * idx - (IN)Index to insert tunnel initiator. 2622 * info - (IN)Tunnel initiator entry info. 2623 * Returns: 2624 * BCM_E_XXX 2625 */ 2626 STATIC int 2627 _bcm_tr3_l2gre_tunnel_init_add(int unit, int idx, bcm_tunnel_initiator_t *info) 2628 { 2629 int rv = BCM_E_NONE; /* Return value */ 2630 int df_val; /* Don't fragment encoding */ 2631 soc_mem_t mem = EGR_IP_TUNNELm; /* Tunnel initiator table memory */ 2632 uint32 tnl_entry[SOC_MAX_MEM_WORDS] = {0}; 2633 soc_field_t type_field; 2634 2635 #if defined(BCM_TRIDENT3_SUPPORT) 2636 if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) { 2637 type_field = DATA_TYPEf; 2638 } else 2639 #endif 2640 { 2641 type_field = ENTRY_TYPEf; 2642 } 2643 2644 /* If replacing existing entry, first read the entry to get old 2645 profile pointer and TPID */ 2646 if (info->flags & BCM_TUNNEL_REPLACE) { 2647 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, tnl_entry); 2648 BCM_IF_ERROR_RETURN(rv); 2649 } 2650 2651 /* Set destination address. */ 2652 soc_mem_field_set(unit, mem, tnl_entry, DIPf, (uint32 *)&info->dip); 2653 2654 /* Set source address. */ 2655 soc_mem_field_set(unit, mem, tnl_entry, SIPf, (uint32 *)&info->sip); 2656 2657 /* IP tunnel hdr DF bit for IPv4. */ 2658 df_val = 0; 2659 if (info->flags & BCM_TUNNEL_INIT_USE_INNER_DF) { 2660 df_val |= 0x2; 2661 } else if (info->flags & BCM_TUNNEL_INIT_IPV4_SET_DF) { 2662 df_val |= 0x1; 2663 } 2664 soc_mem_field32_set(unit, mem, tnl_entry, IPV4_DF_SELf, df_val); 2665 2666 /* Set DSCP value. */ 2667 soc_mem_field32_set(unit, mem, tnl_entry, DSCPf, info->dscp); 2668 2669 /* Tunnel header DSCP select. */ 2670 soc_mem_field32_set(unit, mem, tnl_entry, DSCP_SELf, info->dscp_sel); 2671 2672 /* Set TTL. */ 2673 soc_mem_field32_set(unit, mem, tnl_entry, TTLf, info->ttl); 2674 2675 /* Set Tunnel type = L2GRE */ 2676 soc_mem_field32_set(unit, mem, tnl_entry, TUNNEL_TYPEf, _BCM_L2GRE_TUNNEL_TYPE); 2677 2678 /* Set entry type = IPv4 */ 2679 soc_mem_field32_set(unit, mem, tnl_entry, type_field, 0x1); 2680 2681 if ((info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_FIXED) || 2682 (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_RANDOM)) { 2683 int val; 2684 uint16 random; 2685 #if defined(BCM_TRIDENT3_SUPPORT) 2686 if (SOC_IS_TRIDENT3X(unit)) { 2687 uint64 rval; 2688 uint32 base_idx; 2689 egr_sequence_number_table_entry_t entry; 2690 2691 BCM_IF_ERROR_RETURN(READ_EGR_SEQUENCE_NUMBER_CTRLr(unit, &rval)); 2692 base_idx = soc_reg64_field32_get(unit, EGR_SEQUENCE_NUMBER_CTRLr, 2693 rval,EGR_IP_TUNNEL_OFFSET_BASEf); 2694 2695 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_SEQUENCE_NUMBER_TABLEm, 2696 MEM_BLOCK_ANY, idx + base_idx, &entry)); 2697 if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_FIXED) { 2698 soc_EGR_SEQUENCE_NUMBER_TABLEm_field32_set(unit, &entry, 2699 SEQUENCE_NUMBERf, 2700 info->ip4_id); 2701 } else if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_RANDOM) { 2702 random = (uint16) (sal_time_usecs() & 0xFFFF); 2703 soc_EGR_SEQUENCE_NUMBER_TABLEm_field32_set(unit, &entry, 2704 SEQUENCE_NUMBERf, 2705 random); 2706 } 2707 BCM_IF_ERROR_RETURN(soc_mem_write( 2708 unit, EGR_SEQUENCE_NUMBER_TABLEm, MEM_BLOCK_ANY, 2709 idx + base_idx, &entry)); 2710 2711 } else 2712 #endif 2713 { 2714 BCM_IF_ERROR_RETURN( 2715 bcm_esw_switch_control_get(unit, bcmSwitchTunnelIp4IdShared, &val)); 2716 if (val == 0) { 2717 egr_fragment_id_table_entry_t entry; 2718 sal_memset(&entry, 0, sizeof(egr_fragment_id_table_entry_t)); 2719 2720 if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_FIXED) { 2721 soc_EGR_FRAGMENT_ID_TABLEm_field32_set(unit, &entry, 2722 FRAGMENT_IDf, 2723 info->ip4_id); 2724 } else if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_RANDOM) { 2725 random = (uint16) (sal_time_usecs() & 0xFFFF); 2726 soc_EGR_FRAGMENT_ID_TABLEm_field32_set(unit, &entry, 2727 FRAGMENT_IDf, 2728 random); 2729 } 2730 BCM_IF_ERROR_RETURN(soc_mem_write( 2731 unit, EGR_FRAGMENT_ID_TABLEm, SOC_BLOCK_ALL, idx, &entry)); 2732 } 2733 } 2734 } 2735 2736 /* Write buffer to hw. */ 2737 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, tnl_entry); 2738 return rv; 2739 2740 } 2741 2742 2743 /* 2744 * Function: 2745 * _bcm_tr3_l2gre_tunnel_initiator_entry_add 2746 * Purpose: 2747 * Configure L2GRE Tunnel initiator hardware Entry 2748 * Returns: 2749 * BCM_E_XXX 2750 */ 2751 STATIC int 2752 _bcm_tr3_l2gre_tunnel_initiator_entry_add(int unit, uint32 flags, bcm_tunnel_initiator_t *info, int *tnl_idx) 2753 { 2754 int rv = BCM_E_NONE; 2755 2756 rv = bcm_xgs3_tnl_init_add(unit, flags, info, tnl_idx); 2757 if (BCM_FAILURE(rv)) { 2758 return rv; 2759 } 2760 /* Write the entry to HW */ 2761 rv = _bcm_tr3_l2gre_tunnel_init_add(unit, *tnl_idx, info); 2762 if (BCM_FAILURE(rv)) { 2763 flags = _BCM_L3_SHR_WRITE_DISABLE; 2764 (void) bcm_xgs3_tnl_init_del(unit, flags, *tnl_idx); 2765 } 2766 return rv; 2767 } 2768 2769 /* 2770 * Function: 2771 * bcm_tr3_l2gre_tunnel_initiator_create 2772 * Purpose: 2773 * Set L2GRE Tunnel initiator 2774 * Parameters: 2775 * unit - Device Number 2776 * Returns: 2777 * BCM_E_XXX 2778 */ 2779 int 2780 bcm_tr3_l2gre_tunnel_initiator_create(int unit, bcm_tunnel_initiator_t *info) 2781 { 2782 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 2783 int tnl_idx=-1, rv = BCM_E_NONE; 2784 uint32 flags; 2785 int idx=0, num_tnl=0, num_vp=0; 2786 uint8 sip_entry_present=0; 2787 uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry. */ 2788 2789 /* Input parameters check. */ 2790 if (NULL == info) { 2791 return (BCM_E_PARAM); 2792 } 2793 if (info->type != bcmTunnelTypeL2Gre) { 2794 return BCM_E_PARAM; 2795 } 2796 if (!BCM_TTL_VALID(info->ttl)) { 2797 return BCM_E_PARAM; 2798 } 2799 if (info->dscp_sel > 2 || info->dscp_sel < 0) { 2800 return BCM_E_PARAM; 2801 } 2802 if (info->dscp > 63 || info->dscp < 0) { 2803 return BCM_E_PARAM; 2804 } 2805 2806 l2gre_info = L2GRE_INFO(unit); 2807 num_tnl = soc_mem_index_count(unit, EGR_IP_TUNNELm); 2808 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 2809 2810 /* Allocate either existing or new tunnel initiator entry */ 2811 flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE | 2812 _BCM_L3_SHR_SKIP_INDEX_ZERO; 2813 2814 /* Check if Same SIP exists: MAP first 512 entries to EGR_IP_TUNNEL 2815 Rest of entries map to L2GRE_TUNNEL with Same SIP, different DIP */ 2816 for (idx=0; idx < num_tnl; idx++) { 2817 if (l2gre_info->l2gre_tunnel_init[idx].sip == info->sip) { 2818 tnl_idx = idx; /* Entry_idx within Hardware-Range */ 2819 sip_entry_present = 1; 2820 break; 2821 } 2822 } 2823 2824 /* Check if Same SIP exists in Soft-state */ 2825 if (!sip_entry_present) { 2826 for (idx=num_tnl; idx < num_vp; idx++) { 2827 if (l2gre_info->l2gre_tunnel_init[idx].sip == info->sip) { 2828 for (tnl_idx=0; tnl_idx < num_tnl; tnl_idx++) { 2829 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_IP_TUNNELm, MEM_BLOCK_ANY, tnl_idx, tnl_entry)); 2830 if (info->sip == soc_mem_field32_get(unit, EGR_IP_TUNNELm, tnl_entry, SIPf)) { 2831 /* Entry_idx within Hardware-Range */ 2832 BCM_GPORT_TUNNEL_ID_SET(info->tunnel_id, tnl_idx); 2833 info->flags |= BCM_TUNNEL_REPLACE; 2834 break; 2835 } 2836 } 2837 break; 2838 } 2839 } 2840 } 2841 2842 if (sip_entry_present) { 2843 /* 2 Cases: Entry-update, (Multiple-dip, same-SIP) */ 2844 if (l2gre_info->l2gre_tunnel_init[tnl_idx].dip != info->dip) { 2845 /* Obtain index to Software-State to store (SIP,DIP) */ 2846 for (idx=num_tnl; idx < num_vp; idx++) { 2847 if (l2gre_info->l2gre_tunnel_init[idx].sip == 0) { 2848 tnl_idx = idx; /* Obtain Free index */ 2849 break; 2850 } 2851 } 2852 } else { 2853 /* Parse tunnel replace flag */ 2854 if (info->flags & BCM_TUNNEL_REPLACE) { 2855 flags |= _BCM_L3_SHR_UPDATE | _BCM_L3_SHR_WITH_ID; 2856 tnl_idx = BCM_GPORT_TUNNEL_ID_GET(info->tunnel_id); 2857 rv = _bcm_tr3_l2gre_tunnel_initiator_entry_add(unit, flags, info, &tnl_idx); 2858 if (BCM_FAILURE(rv)) { 2859 return rv; 2860 } 2861 } 2862 } 2863 } else { 2864 /* Parse tunnel replace flag */ 2865 if (info->flags & BCM_TUNNEL_REPLACE) { 2866 flags |= _BCM_L3_SHR_UPDATE | _BCM_L3_SHR_WITH_ID; 2867 tnl_idx = BCM_GPORT_TUNNEL_ID_GET(info->tunnel_id); 2868 } 2869 rv = _bcm_tr3_l2gre_tunnel_initiator_entry_add(unit, flags, info, &tnl_idx); 2870 if (BCM_FAILURE(rv)) { 2871 return rv; 2872 } 2873 } 2874 2875 if (tnl_idx !=- 1) { 2876 l2gre_info->l2gre_tunnel_init[tnl_idx].sip = info->sip; 2877 l2gre_info->l2gre_tunnel_init[tnl_idx].dip = info->dip; 2878 BCM_GPORT_TUNNEL_ID_SET(info->tunnel_id, tnl_idx); 2879 } else { 2880 return BCM_E_NOT_FOUND; 2881 } 2882 2883 return rv; 2884 } 2885 2886 /* 2887 * Function: 2888 * _bcm_tr3_l2gre_tunnel_init_get 2889 * Purpose: 2890 * Get a tunnel initiator entry from hw. 2891 * Parameters: 2892 * unit - (IN)SOC unit number. 2893 * idx - (IN/OUT)Index to read tunnel initiator. 2894 * info - (OUT)Tunnel initiator entry info. 2895 * Returns: 2896 * BCM_E_XXX 2897 */ 2898 STATIC int 2899 _bcm_tr3_l2gre_tunnel_init_get(int unit, int *hw_idx, bcm_tunnel_initiator_t *info) 2900 { 2901 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 2902 egr_fragment_id_table_entry_t entry; 2903 int df_val; /* Don't fragment encoded value. */ 2904 int tnl_type; /* Tunnel type. */ 2905 uint32 entry_type = BCM_XGS3_TUNNEL_INIT_V4;/* Entry type (IPv4/IPv6/MPLS)*/ 2906 int num_tnl=0, tnl_idx =0, idx=0; 2907 bcm_ip_t sip=0; /* Tunnel header SIP (IPv4). */ 2908 soc_field_t type_field; 2909 soc_mem_t mem = EGR_IP_TUNNELm; 2910 uint32 tnl_entry[SOC_MAX_MEM_WORDS] = {0}; 2911 2912 #if defined(BCM_TRIDENT3_SUPPORT) 2913 if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) { 2914 type_field = DATA_TYPEf; 2915 } else 2916 #endif 2917 { 2918 type_field = ENTRY_TYPEf; 2919 } 2920 2921 idx = *hw_idx; 2922 2923 /* Initialize the buffer. */ 2924 l2gre_info = L2GRE_INFO(unit); 2925 num_tnl = soc_mem_index_count(unit, EGR_IP_TUNNELm); 2926 2927 if (idx >= num_tnl) { /* Software State */ 2928 sip = l2gre_info->l2gre_tunnel_init[idx].sip; 2929 info->dip = l2gre_info->l2gre_tunnel_init[idx].dip; 2930 2931 /* Find matching entry within Hardware */ 2932 for (tnl_idx=0; tnl_idx < num_tnl; tnl_idx++) { 2933 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, tnl_idx, tnl_entry)); 2934 if (sip == soc_mem_field32_get(unit, mem, tnl_entry, SIPf)) { 2935 idx = tnl_idx; /* Entry_idx within Hardware-Range */ 2936 break; 2937 } 2938 } 2939 } else { 2940 info->dip = l2gre_info->l2gre_tunnel_init[idx].dip; 2941 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, tnl_entry)); 2942 } 2943 2944 /* Get tunnel type. */ 2945 tnl_type = soc_mem_field32_get(unit, mem, tnl_entry, TUNNEL_TYPEf); 2946 if (tnl_type != _BCM_L2GRE_TUNNEL_TYPE) { 2947 return BCM_E_CONFIG; 2948 } 2949 2950 /* Get entry_type. */ 2951 entry_type = soc_mem_field32_get(unit, mem, tnl_entry, type_field); 2952 if (entry_type != 0x1) { 2953 return BCM_E_CONFIG; 2954 } 2955 2956 /* Parse hw buffer. */ 2957 /* Check will not fail. entry_type already validated */ 2958 if (BCM_XGS3_TUNNEL_INIT_V4 == entry_type) { 2959 /* Get destination ip. */ 2960 info->dip = soc_mem_field32_get(unit, mem, tnl_entry, DIPf); 2961 2962 /* Get source ip. */ 2963 info->sip = soc_mem_field32_get(unit, mem, tnl_entry, SIPf); 2964 } 2965 2966 /* Tunnel header DSCP select. */ 2967 info->dscp_sel = soc_mem_field32_get(unit, mem, tnl_entry, DSCP_SELf); 2968 2969 /* Tunnel header DSCP value. */ 2970 info->dscp = soc_mem_field32_get(unit, mem, tnl_entry, DSCPf); 2971 2972 /* IP tunnel hdr DF bit for IPv4 */ 2973 df_val = soc_mem_field32_get(unit, mem, tnl_entry, IPV4_DF_SELf); 2974 if (0x2 <= df_val) { 2975 info->flags |= BCM_TUNNEL_INIT_USE_INNER_DF; 2976 } else if (0x1 == df_val) { 2977 info->flags |= BCM_TUNNEL_INIT_IPV4_SET_DF; 2978 } 2979 2980 /* Get TTL. */ 2981 info->ttl = soc_mem_field32_get(unit, mem, tnl_entry, TTLf); 2982 2983 /* Translate hw tunnel type into API encoding. - bcmTunnelTypeL2Gre */ 2984 BCM_IF_ERROR_RETURN(_bcm_trx_tnl_hw_code_to_type(unit, tnl_type, 2985 entry_type, 2986 &info->type)); 2987 if (idx < num_tnl) { 2988 #if defined(BCM_TRIDENT3_SUPPORT) 2989 if (SOC_IS_TRIDENT3X(unit)) { 2990 uint64 rval; 2991 uint32 base_idx; 2992 2993 BCM_IF_ERROR_RETURN(READ_EGR_SEQUENCE_NUMBER_CTRLr(unit, &rval)); 2994 base_idx = soc_reg64_field32_get(unit, EGR_SEQUENCE_NUMBER_CTRLr, rval, 2995 EGR_IP_TUNNEL_OFFSET_BASEf); 2996 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_SEQUENCE_NUMBER_TABLEm, 2997 MEM_BLOCK_ANY, idx + base_idx, &entry)); 2998 info->ip4_id = soc_mem_field32_get(unit, EGR_SEQUENCE_NUMBER_TABLEm, 2999 &entry, SEQUENCE_NUMBERf); 3000 } else 3001 #endif 3002 { 3003 BCM_IF_ERROR_RETURN(soc_mem_read( 3004 unit, EGR_FRAGMENT_ID_TABLEm, MEM_BLOCK_ANY, idx, &entry)); 3005 info->ip4_id = soc_mem_field32_get( 3006 unit, EGR_FRAGMENT_ID_TABLEm, &entry, FRAGMENT_IDf); 3007 } 3008 } 3009 3010 *hw_idx = idx; 3011 return BCM_E_NONE; 3012 } 3013 3014 /* 3015 * Function: 3016 * bcm_tr3_l2gre_tunnel_initiator_destroy 3017 * Purpose: 3018 * Destroy outgoing L2GRE tunnel 3019 * Parameters: 3020 * unit - (IN) Device Number 3021 * l2gre_tunnel_id - (IN) Tunnel ID (Gport) 3022 */ 3023 int 3024 bcm_tr3_l2gre_tunnel_initiator_destroy(int unit, bcm_gport_t l2gre_tunnel_id) 3025 { 3026 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 3027 int tnl_idx=-1, temp_tnl_idx=-1, rv = BCM_E_NONE, ref_count=0, idx=0; 3028 uint32 flags = 0; 3029 bcm_tunnel_initiator_t info; /* Tunnel initiator structure */ 3030 int num_vp=0; 3031 bcm_ip_t sip=0; /* Tunnel header SIP (IPv4). */ 3032 3033 l2gre_info = L2GRE_INFO(unit); 3034 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 3035 3036 /* Input parameters check. */ 3037 if (!BCM_GPORT_IS_TUNNEL(l2gre_tunnel_id)) { 3038 return BCM_E_PARAM; 3039 } 3040 tnl_idx = BCM_GPORT_TUNNEL_ID_GET(l2gre_tunnel_id); 3041 3042 bcm_tunnel_initiator_t_init(&info); 3043 sip = l2gre_info->l2gre_tunnel_init[tnl_idx].sip; 3044 /* Remove HW TNL entry only if all matching SIP gets removed */ 3045 for (idx=0; idx < num_vp; idx++) { 3046 if (l2gre_info->l2gre_tunnel_init[idx].sip == sip) { 3047 ref_count++; 3048 } 3049 } 3050 if (ref_count == 1) { 3051 /* Get the entry first */ 3052 temp_tnl_idx = tnl_idx; 3053 rv = _bcm_tr3_l2gre_tunnel_init_get(unit, &tnl_idx, &info); 3054 if (BCM_FAILURE(rv)) { 3055 return rv; 3056 } 3057 /* Destroy the tunnel entry */ 3058 (void) bcm_xgs3_tnl_init_del(unit, flags, tnl_idx); 3059 l2gre_info->l2gre_tunnel_init[temp_tnl_idx].sip = 0; 3060 l2gre_info->l2gre_tunnel_init[temp_tnl_idx].dip = 0; 3061 } else if (ref_count) { 3062 l2gre_info->l2gre_tunnel_init[tnl_idx].sip = 0; 3063 l2gre_info->l2gre_tunnel_init[tnl_idx].dip = 0; 3064 } 3065 3066 return rv; 3067 } 3068 3069 /* 3070 * Function: 3071 * bcm_tr3_l2gre_tunnel_initiator_destroy_all 3072 * Purpose: 3073 * Destroy all outgoing L2GRE tunnel 3074 * Parameters: 3075 * unit - (IN) Device Number 3076 */ 3077 int 3078 bcm_tr3_l2gre_tunnel_initiator_destroy_all(int unit) 3079 { 3080 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 3081 soc_field_t type_field; 3082 egr_ip_tunnel_entry_t *tnl_entry, *tnl_entries; 3083 int rv = BCM_E_NONE, tnl_idx, num_entries, num_vp; 3084 3085 #if defined(BCM_TRIDENT3_SUPPORT) 3086 if (SOC_MEM_FIELD_VALID(unit, EGR_IP_TUNNELm, DATA_TYPEf)) { 3087 type_field = DATA_TYPEf; 3088 } else 3089 #endif 3090 { 3091 type_field = ENTRY_TYPEf; 3092 } 3093 3094 l2gre_info = L2GRE_INFO(unit); 3095 num_entries = soc_mem_index_count(unit, EGR_IP_TUNNELm); 3096 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 3097 3098 tnl_entries = soc_cm_salloc(unit, num_entries * sizeof(*tnl_entries), 3099 "egr_ip_tunnel"); 3100 if (tnl_entries == NULL) { 3101 return BCM_E_MEMORY; 3102 } 3103 sal_memset(tnl_entries, 0, num_entries * sizeof(*tnl_entries)); 3104 3105 soc_mem_lock(unit, EGR_IP_TUNNELm); 3106 rv = soc_mem_read_range(unit, EGR_IP_TUNNELm, MEM_BLOCK_ANY, 3107 0, num_entries - 1, tnl_entries); 3108 if (BCM_FAILURE(rv)) { 3109 soc_mem_unlock(unit, EGR_IP_TUNNELm); 3110 soc_cm_sfree(unit, tnl_entries); 3111 return rv; 3112 } 3113 for (tnl_idx = 0; tnl_idx < num_entries; tnl_idx++) { 3114 tnl_entry = soc_mem_table_idx_to_pointer(unit, EGR_IP_TUNNELm, 3115 egr_ip_tunnel_entry_t *, tnl_entries, tnl_idx); 3116 3117 if (!soc_EGR_IP_TUNNELm_field32_get(unit, tnl_entry, type_field)) { 3118 continue; 3119 } 3120 if (soc_EGR_IP_TUNNELm_field32_get(unit, tnl_entry, 3121 TUNNEL_TYPEf) != _BCM_L2GRE_TUNNEL_TYPE) { 3122 continue; 3123 } 3124 3125 /* Destroy the tunnel entry */ 3126 (void) bcm_xgs3_tnl_init_del(unit, 0, tnl_idx); 3127 l2gre_info->l2gre_tunnel_init[tnl_idx].sip = 0; 3128 l2gre_info->l2gre_tunnel_init[tnl_idx].dip = 0; 3129 } 3130 soc_mem_unlock(unit, EGR_IP_TUNNELm); 3131 soc_cm_sfree(unit, tnl_entries); 3132 3133 for (tnl_idx = num_entries; tnl_idx < num_vp; tnl_idx++) { 3134 l2gre_info->l2gre_tunnel_init[tnl_idx].sip = 0; 3135 l2gre_info->l2gre_tunnel_init[tnl_idx].dip = 0; 3136 } 3137 return BCM_E_NONE; 3138 3139 } 3140 3141 /* 3142 * Function: 3143 * bcm_tr3_l2gre_tunnel_initiator_get 3144 * Purpose: 3145 * Get an outgong L2GRE tunnel info 3146 * Parameters: 3147 * unit - (IN) Device Number 3148 * info - (IN/OUT) Tunnel initiator structure 3149 */ 3150 int 3151 bcm_tr3_l2gre_tunnel_initiator_get(int unit, bcm_tunnel_initiator_t *info) 3152 { 3153 int tnl_idx, rv = BCM_E_NONE; 3154 3155 /* Input parameters check. */ 3156 if (info == NULL) { 3157 return BCM_E_PARAM; 3158 } 3159 if (!BCM_GPORT_IS_TUNNEL(info->tunnel_id)) { 3160 return BCM_E_PARAM; 3161 } 3162 tnl_idx = BCM_GPORT_TUNNEL_ID_GET(info->tunnel_id); 3163 3164 /* Get the entry */ 3165 rv = _bcm_tr3_l2gre_tunnel_init_get(unit, &tnl_idx, info); 3166 return rv; 3167 } 3168 3169 /* 3170 * Function: 3171 * bcm_tr3_l2gre_tunnel_initiator_traverse 3172 * Purpose: 3173 * Traverse L2GRE tunnel initiator entries 3174 * Parameters: 3175 * unit - (IN) Device Number 3176 * cb - (IN) User callback function, called once per entry 3177 * user_data - (IN) User supplied cookie used in parameter in callback function 3178 */ 3179 int 3180 bcm_tr3_l2gre_tunnel_initiator_traverse(int unit, bcm_tunnel_initiator_traverse_cb cb, void *user_data) 3181 { 3182 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 3183 int num_vp = 0, idx = 0; 3184 bcm_tunnel_initiator_t info; 3185 int rv = BCM_E_NONE; 3186 3187 l2gre_info = L2GRE_INFO(unit); 3188 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 3189 3190 /* Iterate over all the entries - search valid ones. */ 3191 for(idx = 0; idx < num_vp; idx++) { 3192 /* Check a valid entry */ 3193 if (l2gre_info->l2gre_tunnel_init[idx].sip != 0) { 3194 /* Reset buffer before read. */ 3195 bcm_tunnel_initiator_t_init(&info); 3196 3197 BCM_GPORT_TUNNEL_ID_SET(info.tunnel_id, idx); 3198 rv = bcm_tr3_l2gre_tunnel_initiator_get(unit, &info); 3199 3200 /* search failure */ 3201 if (BCM_FAILURE(rv)) { 3202 if (rv != BCM_E_CONFIG) { 3203 break; 3204 } 3205 continue; 3206 } 3207 3208 if (cb) { 3209 rv = (*cb) (unit, &info, user_data); 3210 #ifdef BCM_CB_ABORT_ON_ERR 3211 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 3212 break; 3213 } 3214 #endif 3215 } 3216 } 3217 } 3218 3219 /* Reset last read status. */ 3220 if (BCM_E_CONFIG == rv) { 3221 rv = BCM_E_NONE; 3222 } 3223 3224 return rv; 3225 } 3226 3227 /* 3228 * Function: 3229 * _bcm_tr3_l2gre_ingress_dvp_set 3230 * Purpose: 3231 * Set Ingress DVP tables 3232 * Parameters: 3233 * IN : Unit 3234 * IN : vp 3235 * IN : l2gre_port 3236 * Returns: 3237 * BCM_E_XXX 3238 */ 3239 3240 STATIC int 3241 _bcm_tr3_l2gre_ingress_dvp_set(int unit, int vp, uint32 mpath_flag, 3242 int vp_nh_ecmp_index, bcm_l2gre_port_t *l2gre_port) 3243 { 3244 int rv = BCM_E_NONE; 3245 int vp_type = -1; 3246 int network_port = -1; 3247 int flag = -1; 3248 bcm_if_t intf; 3249 3250 if (l2gre_port->flags & BCM_L2GRE_PORT_REPLACE) { 3251 flag = _bcmVpIngDvpConfigUpdate; 3252 } else { 3253 flag = _bcmVpIngDvpConfigSet; 3254 } 3255 3256 if (mpath_flag) { 3257 intf = BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit) + vp_nh_ecmp_index; 3258 } else { 3259 intf = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + vp_nh_ecmp_index; 3260 } 3261 3262 /* Default Split Horizon Group Id 3263 * 0 - For Access Port;1 - For Network Port*/ 3264 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 3265 if (l2gre_port->flags & BCM_L2GRE_PORT_EGRESS_TUNNEL) { 3266 network_port = (_BCM_SWITCH_NETWORK_GROUP_ID_VALID(unit, 3267 l2gre_port->network_group_id)) ? 3268 l2gre_port->network_group_id : 1; 3269 } else { 3270 network_port = (_BCM_SWITCH_NETWORK_GROUP_ID_VALID(unit, 3271 l2gre_port->network_group_id)) ? 3272 l2gre_port->network_group_id : 0; 3273 } 3274 } else { 3275 network_port = (l2gre_port->flags & BCM_L2GRE_PORT_EGRESS_TUNNEL) ? 3276 1 : 0; 3277 } 3278 3279 #ifdef BCM_RIOT_SUPPORT 3280 if ((l2gre_port->flags & BCM_L2GRE_PORT_EGRESS_TUNNEL) && 3281 BCMI_RIOT_IS_ENABLED(unit)) { 3282 network_port = 0; 3283 } 3284 #endif 3285 3286 vp_type = (l2gre_port->flags & BCM_L2GRE_PORT_EGRESS_TUNNEL) ? 3287 _BCM_L2GRE_INGRESS_DEST_VP_TYPE : _BCM_L2GRE_DEST_VP_TYPE_ACCESS; 3288 rv = _bcm_vp_ing_dvp_config(unit, flag, vp, vp_type, intf, network_port); 3289 3290 return rv; 3291 } 3292 3293 /* 3294 * Function: 3295 * _bcm_tr3_l2gre_ingress_dvp_reset 3296 * Purpose: 3297 * Reset Ingress DVP tables 3298 * Parameters: 3299 * IN : Unit 3300 * IN : vp 3301 * Returns: 3302 * BCM_E_XXX 3303 */ 3304 3305 STATIC int 3306 _bcm_tr3_l2gre_ingress_dvp_reset(int unit, int vp) 3307 { 3308 int rv=BCM_E_UNAVAIL; 3309 rv = _bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigClear, vp, 3310 ING_DVP_CONFIG_INVALID_VP_TYPE, 3311 ING_DVP_CONFIG_INVALID_INTF_ID, 3312 ING_DVP_CONFIG_INVALID_PORT_TYPE); 3313 return rv; 3314 } 3315 3316 /* 3317 * Function: 3318 * _bcm_tr3_l2gre_egress_dvp_set 3319 * Purpose: 3320 * Set Egress DVP tables 3321 * Parameters: 3322 * IN : Unit 3323 * IN : vp 3324 * IN : l2gre_port 3325 * Returns: 3326 * BCM_E_XXX 3327 */ 3328 3329 STATIC int 3330 _bcm_tr3_l2gre_egress_dvp_set(int unit, int vp, int drop, bcm_l2gre_port_t *l2gre_port) 3331 { 3332 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 3333 int rv=BCM_E_UNAVAIL; 3334 egr_dvp_attribute_entry_t egr_dvp_attribute; 3335 egr_dvp_attribute_1_entry_t egr_dvp_attribute_1; 3336 bcm_ip_t dip=0; /* DIP for tunnel header */ 3337 bcm_ip_t sip=0; /* SIP for tunnel header */ 3338 int tunnel_index=-1, idx=0, num_tnl=0; 3339 int network_group=0; 3340 3341 3342 l2gre_info = L2GRE_INFO(unit); 3343 num_tnl = soc_mem_index_count(unit, EGR_IP_TUNNELm); 3344 3345 tunnel_index = BCM_GPORT_TUNNEL_ID_GET(l2gre_port->egress_tunnel_id); 3346 if (tunnel_index < num_tnl) { 3347 /* Obtain Tunnel DIP */ 3348 dip = l2gre_info->l2gre_tunnel_init[tunnel_index].dip; 3349 } else { 3350 /* Obtain Tunnel SIP */ 3351 sip = l2gre_info->l2gre_tunnel_init[tunnel_index].sip; 3352 /* Obtain Tunnel DIP */ 3353 dip = l2gre_info->l2gre_tunnel_init[tunnel_index].dip; 3354 /* Restrict tunnel_index to Hardware Range */ 3355 for (idx=0; idx < num_tnl; idx++) { 3356 if (l2gre_info->l2gre_tunnel_init[idx].sip == sip) { 3357 tunnel_index = idx; /* Entry_idx for SIP within EGR_IP_TUNNEL */ 3358 break; 3359 } 3360 } 3361 } 3362 3363 /* Zero write buffer. */ 3364 sal_memset(&egr_dvp_attribute, 0, sizeof(egr_dvp_attribute_entry_t)); 3365 #if defined(BCM_TRIDENT3_SUPPORT) 3366 if (SOC_MEM_FIELD_VALID(unit, EGR_DVP_ATTRIBUTEm, DATA_TYPEf)) { 3367 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, 3368 &egr_dvp_attribute, DATA_TYPEf, _BCM_L2GRE_EGRESS_DEST_VP_TYPE); 3369 } else 3370 #endif 3371 { 3372 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, 3373 &egr_dvp_attribute, VP_TYPEf, _BCM_L2GRE_EGRESS_DEST_VP_TYPE); 3374 } 3375 3376 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 3377 L2GRE__TUNNEL_INDEXf, tunnel_index); 3378 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 3379 L2GRE__DIPf, dip); 3380 3381 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 3382 network_group = l2gre_port->network_group_id; 3383 rv = _bcm_validate_splithorizon_network_group(unit, 3384 l2gre_port->flags & BCM_L2GRE_PORT_NETWORK, &network_group); 3385 BCM_IF_ERROR_RETURN(rv); 3386 3387 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 3388 L2GRE__DVP_NETWORK_GROUPf, network_group); 3389 } else { 3390 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 3391 L2GRE__DVP_IS_NETWORK_PORTf, 0x1); 3392 } 3393 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 3394 L2GRE__DISABLE_VP_PRUNINGf, 0x0); 3395 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 3396 L2GRE__DELETE_VNTAGf, 0x1); 3397 3398 #if defined(BCM_TRIDENT3_SUPPORT) 3399 if (SOC_IS_TRIDENT3X(unit)) { 3400 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, 3401 &egr_dvp_attribute, L2GRE__CLASS_IDf, l2gre_port->if_class); 3402 3403 /* L2 MTU - This is different from L3 MTU */ 3404 if (l2gre_port->mtu > 0) { 3405 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, 3406 &egr_dvp_attribute, L2GRE__MTU_VALUEf, l2gre_port->mtu); 3407 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, 3408 &egr_dvp_attribute, L2GRE__MTU_ENABLEf, 0x1); 3409 } 3410 3411 if (l2gre_port->flags & BCM_L2GRE_PORT_MULTICAST) { 3412 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, 3413 &egr_dvp_attribute, L2GRE__UUC_DROPf, drop ? 1 : 0); 3414 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, 3415 &egr_dvp_attribute, L2GRE__UMC_DROPf, drop ? 1 : 0); 3416 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, 3417 &egr_dvp_attribute, L2GRE__BC_DROPf, drop ? 1 : 0); 3418 } 3419 } else 3420 #endif 3421 { 3422 /* Zero write buffer. */ 3423 sal_memset(&egr_dvp_attribute_1, 0, sizeof(egr_dvp_attribute_1_entry_t)); 3424 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTE_1m, 3425 &egr_dvp_attribute_1, L2GRE__CLASS_IDf, l2gre_port->if_class); 3426 3427 /* L2 MTU - This is different from L3 MTU */ 3428 if (l2gre_port->mtu > 0) { 3429 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTE_1m, 3430 &egr_dvp_attribute_1, L2GRE__MTU_VALUEf, l2gre_port->mtu); 3431 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTE_1m, 3432 &egr_dvp_attribute_1, L2GRE__MTU_ENABLEf, 0x1); 3433 } 3434 3435 if (l2gre_port->flags & BCM_L2GRE_PORT_MULTICAST) { 3436 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTE_1m, 3437 &egr_dvp_attribute_1, L2GRE__UUC_DROPf, drop ? 1 : 0); 3438 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTE_1m, 3439 &egr_dvp_attribute_1, L2GRE__UMC_DROPf, drop ? 1 : 0); 3440 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTE_1m, 3441 &egr_dvp_attribute_1, L2GRE__BC_DROPf, drop ? 1 : 0); 3442 } 3443 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_DVP_ATTRIBUTE_1m, 3444 MEM_BLOCK_ALL, vp, &egr_dvp_attribute_1)); 3445 } 3446 3447 #if defined(BCM_TRIDENT3_SUPPORT) 3448 if(SOC_MEM_FIELD_VALID(unit, EGR_DVP_ATTRIBUTEm, L2GRE__EVXLT_KEY_SELf)) { 3449 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, 3450 &egr_dvp_attribute, L2GRE__EVXLT_KEY_SELf, L2GRE_DVP_EVXLT_KEY_VFI); 3451 } 3452 #endif 3453 3454 rv = soc_mem_write(unit, EGR_DVP_ATTRIBUTEm, 3455 MEM_BLOCK_ALL, vp, &egr_dvp_attribute); 3456 3457 return rv; 3458 } 3459 3460 #if defined(BCM_TRIDENT3_SUPPORT) 3461 /* 3462 * Function: 3463 * _bcm_tr3_l2gre_acc_egress_dvp_set 3464 * Purpose: 3465 * Set access egress DVP tables 3466 * Parameters: 3467 * IN : Unit 3468 * IN : vp 3469 * IN : l2gre_port 3470 * Returns: 3471 * BCM_E_XXX 3472 */ 3473 STATIC int 3474 _bcm_tr3_l2gre_acc_egress_dvp_set(int unit, int vp, 3475 bcm_l2gre_port_t *l2gre_port) 3476 { 3477 int rv = BCM_E_NONE; 3478 egr_dvp_attribute_entry_t egr_dvp_attribute; 3479 int network_group = 0; 3480 soc_mem_t mem = EGR_DVP_ATTRIBUTEm; 3481 3482 if (SOC_MEM_FIELD_VALID(unit, mem, COMMON__DVP_NETWORK_GROUPf)) { 3483 sal_memset(&egr_dvp_attribute, 0, sizeof(egr_dvp_attribute_entry_t)); 3484 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, vp, &egr_dvp_attribute); 3485 BCM_IF_ERROR_RETURN(rv); 3486 network_group = l2gre_port->network_group_id; 3487 rv = _bcm_validate_splithorizon_network_group(unit, 3488 l2gre_port->flags & BCM_L2GRE_PORT_NETWORK, &network_group); 3489 BCM_IF_ERROR_RETURN(rv); 3490 soc_mem_field32_set(unit, mem, &egr_dvp_attribute, 3491 COMMON__DVP_NETWORK_GROUPf, network_group); 3492 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, vp, &egr_dvp_attribute); 3493 } 3494 return rv; 3495 } 3496 #endif 3497 3498 /* 3499 * Function: 3500 * _bcm_tr3_l2gre_egress_dvp_get 3501 * Purpose: 3502 * Get Egress DVP tables 3503 * Parameters: 3504 * IN : Unit 3505 * IN : vp 3506 * IN : l2gre_port 3507 * Returns: 3508 * BCM_E_XXX 3509 */ 3510 3511 STATIC int 3512 _bcm_tr3_l2gre_egress_dvp_get(int unit, int vp, bcm_l2gre_port_t *l2gre_port) 3513 { 3514 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info; 3515 int rv=BCM_E_NONE; 3516 egr_dvp_attribute_entry_t egr_dvp_attribute; 3517 egr_dvp_attribute_1_entry_t egr_dvp_attribute_1; 3518 int tunnel_index=-1; 3519 bcm_ip_t dip=0; /* DIP for tunnel header */ 3520 int idx=0, num_vp=0; 3521 3522 l2gre_info = L2GRE_INFO(unit); 3523 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 3524 3525 sal_memset(&egr_dvp_attribute, 0, sizeof(egr_dvp_attribute_entry_t)); 3526 rv = soc_mem_read(unit, EGR_DVP_ATTRIBUTEm, 3527 MEM_BLOCK_ANY, vp, &egr_dvp_attribute); 3528 BCM_IF_ERROR_RETURN(rv); 3529 dip = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 3530 &egr_dvp_attribute, L2GRE__DIPf); 3531 3532 /* Find DIP within Softare State */ 3533 for (idx=0; idx < num_vp; idx++) { 3534 if (l2gre_info->l2gre_tunnel_init[idx].dip == dip) { 3535 tunnel_index = idx; 3536 break; 3537 } 3538 } 3539 3540 BCM_GPORT_TUNNEL_ID_SET(l2gre_port->egress_tunnel_id, tunnel_index); 3541 3542 #if defined(BCM_TRIDENT3_SUPPORT) 3543 if (SOC_IS_TRIDENT3X(unit)) { 3544 l2gre_port->if_class = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 3545 &egr_dvp_attribute, L2GRE__CLASS_IDf); 3546 if (soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 3547 &egr_dvp_attribute, L2GRE__MTU_ENABLEf)) { 3548 l2gre_port->mtu = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 3549 &egr_dvp_attribute, L2GRE__MTU_VALUEf); 3550 } 3551 } else 3552 #endif 3553 { 3554 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_DVP_ATTRIBUTE_1m, 3555 MEM_BLOCK_ANY, vp, &egr_dvp_attribute_1)); 3556 3557 l2gre_port->if_class = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTE_1m, 3558 &egr_dvp_attribute_1, L2GRE__CLASS_IDf); 3559 if (soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTE_1m, 3560 &egr_dvp_attribute_1, L2GRE__MTU_ENABLEf)) { 3561 l2gre_port->mtu = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTE_1m, 3562 &egr_dvp_attribute_1, L2GRE__MTU_VALUEf); 3563 } 3564 } 3565 3566 return rv; 3567 } 3568 3569 /* 3570 * Function: 3571 * _bcm_tr3_l2gre_egress_dvp_reset 3572 * Purpose: 3573 * Reet Egress DVP tables 3574 * Parameters: 3575 * IN : Unit 3576 * IN : vp 3577 * Returns: 3578 * BCM_E_XXX 3579 */ 3580 3581 STATIC int 3582 _bcm_tr3_l2gre_egress_dvp_reset(int unit, int vp) 3583 { 3584 uint32 dvp[SOC_MAX_MEM_WORDS]; 3585 3586 sal_memset(dvp, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 3587 BCM_IF_ERROR_RETURN(soc_mem_write(unit, 3588 EGR_DVP_ATTRIBUTEm, MEM_BLOCK_ALL, vp, dvp)); 3589 3590 if (!SOC_IS_TRIDENT3X(unit)) { 3591 BCM_IF_ERROR_RETURN(soc_mem_write(unit, 3592 EGR_DVP_ATTRIBUTE_1m, MEM_BLOCK_ALL, vp, dvp)); 3593 } 3594 3595 return BCM_E_NONE; 3596 } 3597 3598 /* 3599 * Function: 3600 * _bcm_tr3_l2gre_egr_xlate_entry_set 3601 * Purpose: 3602 * Reset L2GRE egr_xlate Entry 3603 * Parameters: 3604 * IN : Unit 3605 * IN : l2gre vpn info 3606 * Returns: 3607 * BCM_E_XXX 3608 */ 3609 3610 STATIC int 3611 _bcm_tr3_l2gre_egr_xlate_entry_set(int unit, bcm_l2gre_vpn_config_t *vpn_info) 3612 { 3613 int rv = BCM_E_NONE; 3614 int vfi_index = -1; 3615 int tpid_index = -1; 3616 soc_mem_t mem; 3617 uint32 vxlate[SOC_MAX_MEM_WORDS]; 3618 3619 if (NULL == vpn_info) { 3620 return BCM_E_PARAM; 3621 } 3622 3623 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_vpn_is_valid(unit, vpn_info->vpn)); 3624 _BCM_L2GRE_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn_info->vpn); 3625 3626 /* Reset old egress vlan xlate */ 3627 if (vpn_info->flags & BCM_L2GRE_VPN_REPLACE) { 3628 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_egr_xlate_entry_reset(unit, vpn_info->vpn)); 3629 } 3630 3631 sal_memset(vxlate, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 3632 /* Configurate EGR_VLAN_XLATE for Egress VPNID */ 3633 #if defined(BCM_TRIDENT3_SUPPORT) 3634 if (soc_feature(unit, soc_feature_base_valid)) { 3635 mem = EGR_VLAN_XLATE_1_DOUBLEm; 3636 3637 soc_mem_field32_set(unit, mem, vxlate, BASE_VALID_0f, 3); 3638 soc_mem_field32_set(unit, mem, vxlate, BASE_VALID_1f, 7); 3639 soc_mem_field32_set(unit, mem, vxlate, 3640 KEY_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_VFI); 3641 soc_mem_field32_set(unit, mem, vxlate, 3642 DATA_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_VFI); 3643 } else 3644 #endif 3645 { 3646 mem = EGR_VLAN_XLATEm; 3647 3648 if (SOC_IS_TRIUMPH3(unit)) { 3649 soc_mem_field32_set(unit, mem, vxlate, 3650 KEY_TYPEf, _BCM_TR3_L2GRE_KEY_TYPE_LOOKUP_VFI); 3651 } else if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) { 3652 soc_mem_field32_set(unit, mem, vxlate, 3653 ENTRY_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_VFI); 3654 } 3655 soc_mem_field32_set(unit, mem, vxlate, VALIDf, 1); 3656 } 3657 soc_mem_field32_set(unit, mem, vxlate, L2GRE_VFI__VFIf, vfi_index); 3658 soc_mem_field32_set(unit, mem, vxlate, L2GRE_VFI__VPNIDf, vpn_info->vpnid); 3659 3660 if (vpn_info->flags & BCM_L2GRE_VPN_SERVICE_TAGGED) { 3661 /* Configure EGR_VLAN_XLATE - SD_TAG setting */ 3662 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_sd_tag_set(unit, vpn_info, NULL, NULL, vxlate, &tpid_index)); 3663 } 3664 3665 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, vxlate); 3666 if (rv < 0) 3667 { 3668 if (tpid_index != -1) { 3669 _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 3670 } 3671 return rv; 3672 } 3673 3674 return BCM_E_NONE; 3675 } 3676 3677 3678 /* 3679 * Function: 3680 * _bcm_tr3_l2gre_egr_xlate_entry_reset 3681 * Purpose: 3682 * Reset L2GRE egr_xlate Entry 3683 * Parameters: 3684 * IN : Unit 3685 * IN : vpn 3686 * Returns: 3687 * BCM_E_XXX 3688 */ 3689 3690 STATIC int 3691 _bcm_tr3_l2gre_egr_xlate_entry_reset(int unit, bcm_vpn_t vpn) 3692 { 3693 int rv = BCM_E_UNAVAIL; 3694 int index; 3695 int vfi; 3696 int tpid_index = -1; 3697 int action_present = 0, action_not_present = 0; 3698 soc_mem_t mem; 3699 uint32 vxlate[SOC_MAX_MEM_WORDS]; 3700 3701 sal_memset(vxlate, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 3702 _BCM_L2GRE_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn); 3703 3704 #if defined(BCM_TRIDENT3_SUPPORT) 3705 if (soc_feature(unit, soc_feature_base_valid)) { 3706 mem = EGR_VLAN_XLATE_1_DOUBLEm; 3707 3708 soc_mem_field32_set(unit, mem, vxlate, BASE_VALID_0f, 3); 3709 soc_mem_field32_set(unit, mem, vxlate, BASE_VALID_1f, 7); 3710 soc_mem_field32_set(unit, mem, vxlate, 3711 KEY_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_VFI); 3712 soc_mem_field32_set(unit, mem, vxlate, 3713 DATA_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_VFI); 3714 } else 3715 #endif 3716 { 3717 mem = EGR_VLAN_XLATEm; 3718 3719 if (SOC_IS_TRIUMPH3(unit)) { 3720 soc_mem_field32_set(unit, mem, vxlate, 3721 KEY_TYPEf, _BCM_TR3_L2GRE_KEY_TYPE_LOOKUP_VFI); 3722 } else if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) { 3723 soc_mem_field32_set(unit, mem, vxlate, 3724 ENTRY_TYPEf, _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_VFI); 3725 } 3726 soc_mem_field32_set(unit, mem, vxlate, VALIDf, 1); 3727 } 3728 soc_mem_field32_set(unit, mem, vxlate, L2GRE_VFI__VFIf, vfi); 3729 3730 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, vxlate, vxlate, 0); 3731 if (rv == BCM_E_NOT_FOUND) { 3732 return BCM_E_NONE; 3733 } else if (rv != BCM_E_NONE) { 3734 return rv; 3735 } 3736 3737 /* If tpid exist, delete it */ 3738 action_present = soc_mem_field32_get(unit, mem, vxlate, 3739 L2GRE_VFI__SD_TAG_ACTION_IF_PRESENTf); 3740 action_not_present = soc_mem_field32_get(unit, mem, vxlate, 3741 L2GRE_VFI__SD_TAG_ACTION_IF_NOT_PRESENTf); 3742 if (1 == action_present || 4 == action_present || 3743 7 == action_present || 1 == action_not_present) { 3744 tpid_index = soc_mem_field32_get(unit, mem, vxlate, 3745 L2GRE_VFI__SD_TAG_TPID_INDEXf); 3746 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_delete(unit, tpid_index)); 3747 } 3748 3749 /* Delete the entry from HW */ 3750 BCM_IF_ERROR_RETURN(soc_mem_delete(unit, mem, MEM_BLOCK_ALL, vxlate)); 3751 3752 return BCM_E_NONE; 3753 } 3754 3755 3756 /* 3757 * Function: 3758 * bcm_tr3_l2gre_port_untagged_profile_set 3759 * Purpose: 3760 * Set VLan profile per Physical port entry 3761 * Parameters: 3762 * unit - (IN) SOC unit # 3763 * port - (IN) Physical port 3764 * Returns: 3765 * BCM_E_XXX 3766 */ 3767 3768 int 3769 bcm_tr3_l2gre_port_untagged_profile_set (int unit, bcm_port_t port) 3770 { 3771 bcm_vlan_action_set_t action; 3772 uint32 ing_profile_idx = 0xffffffff; 3773 3774 bcm_vlan_action_set_t_init(&action); 3775 action.ut_outer = 0x0; /* No Op */ 3776 action.ut_inner = 0x0; /* No Op */ 3777 3778 BCM_IF_ERROR_RETURN( 3779 _bcm_trx_vlan_action_profile_entry_add( 3780 unit, &action, &ing_profile_idx)); 3781 3782 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, 3783 _BCM_CPU_TABS_NONE, TAG_ACTION_PROFILE_PTRf, ing_profile_idx)); 3784 3785 return BCM_E_NONE; 3786 } 3787 3788 /* 3789 * Function: 3790 * bcm_tr3_l2gre_port_untagged_profile_reset 3791 * Purpose: 3792 * Reset VLan profile per Physical port entry 3793 * Parameters: 3794 * unit - (IN) SOC unit # 3795 * port - (IN) Physical port 3796 * Returns: 3797 * BCM_E_XXX 3798 */ 3799 3800 int 3801 bcm_tr3_l2gre_port_untagged_profile_reset(int unit, bcm_port_t port) 3802 { 3803 int ing_profile_idx = -1; 3804 int def_profile_idx = 0; 3805 3806 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_get(unit, 3807 port, TAG_ACTION_PROFILE_PTRf, &ing_profile_idx)); 3808 #if defined(BCM_TRIDENT3_SUPPORT) 3809 if (SOC_IS_TRIDENT3X(unit) && (ing_profile_idx == 0)) { 3810 /*index 0 is invalid in Ingress Vlan Tag Action Profile*/ 3811 return BCM_E_NONE; 3812 } 3813 #endif 3814 BCM_IF_ERROR_RETURN( 3815 _bcm_trx_vlan_action_profile_entry_delete(unit, ing_profile_idx)); 3816 #if defined(BCM_TRIDENT3_SUPPORT) 3817 /* default profile defined in _bcm_trx_vlan_action_profile_init */ 3818 if (SOC_MEM_IS_VALID(unit, ING_DEVICE_PORTm)) { 3819 def_profile_idx = 1; 3820 } 3821 #endif 3822 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, 3823 port, _BCM_CPU_TABS_NONE, TAG_ACTION_PROFILE_PTRf, def_profile_idx)); 3824 3825 return BCM_E_NONE; 3826 } 3827 3828 /* 3829 * Function: 3830 * _bcm_tr3_l2gre_sd_tag_set 3831 * Purpose: 3832 * Program SD_TAG settings 3833 * Parameters: 3834 * unit - (IN) SOC unit # 3835 * l2gre_port - (IN) L2GRE VP 3836 * egr_nh_info (IN/OUT) Egress NHop Info 3837 * Returns: 3838 * BCM_E_XXX 3839 */ 3840 3841 STATIC int 3842 _bcm_tr3_l2gre_sd_tag_set( int unit, bcm_l2gre_vpn_config_t *l2gre_vpn_info, 3843 bcm_l2gre_port_t *l2gre_port, 3844 _bcm_tr3_l2gre_nh_info_t *egr_nh_info, 3845 uint32 *vxlate_entry, 3846 int *tpid_index ) 3847 { 3848 soc_mem_t hw_mem; 3849 3850 if (l2gre_vpn_info != NULL ) { 3851 #if defined(BCM_TRIDENT3_SUPPORT) 3852 if (soc_feature(unit, soc_feature_base_valid)) { 3853 hw_mem = EGR_VLAN_XLATE_1_DOUBLEm; 3854 } else 3855 #endif 3856 { 3857 hw_mem = EGR_VLAN_XLATEm; 3858 } 3859 3860 if (l2gre_vpn_info->flags & BCM_L2GRE_VPN_SERVICE_VLAN_ADD) { 3861 if (l2gre_vpn_info->egress_service_vlan >= BCM_VLAN_INVALID) { 3862 return BCM_E_PARAM; 3863 } 3864 soc_mem_field32_set(unit, hw_mem, 3865 vxlate_entry, L2GRE_VFI__SD_TAG_VIDf, 3866 l2gre_vpn_info->egress_service_vlan); 3867 soc_mem_field32_set(unit, hw_mem, 3868 vxlate_entry, L2GRE_VFI__SD_TAG_ACTION_IF_NOT_PRESENTf, 3869 0x1); /* ADD */ 3870 } 3871 3872 if (l2gre_vpn_info->flags & BCM_L2GRE_VPN_SERVICE_VLAN_TPID_REPLACE) { 3873 if (l2gre_vpn_info->egress_service_vlan >= BCM_VLAN_INVALID) { 3874 return BCM_E_PARAM; 3875 } 3876 soc_mem_field32_set(unit, hw_mem, 3877 vxlate_entry, L2GRE_VFI__SD_TAG_VIDf, 3878 l2gre_vpn_info->egress_service_vlan); 3879 soc_mem_field32_set(unit, hw_mem, 3880 vxlate_entry, L2GRE_VFI__SD_TAG_ACTION_IF_PRESENTf, 3881 0x1); /* REPLACE_VID_TPID */ 3882 } else if (l2gre_vpn_info->flags & BCM_L2GRE_VPN_SERVICE_VLAN_REPLACE) { 3883 if (l2gre_vpn_info->egress_service_vlan >= BCM_VLAN_INVALID) { 3884 return BCM_E_PARAM; 3885 } 3886 soc_mem_field32_set(unit, hw_mem, 3887 vxlate_entry, L2GRE_VFI__SD_TAG_VIDf, 3888 l2gre_vpn_info->egress_service_vlan); 3889 soc_mem_field32_set(unit, hw_mem, 3890 vxlate_entry, L2GRE_VFI__SD_TAG_ACTION_IF_PRESENTf, 3891 0x2); /* REPLACE_VID_ONLY */ 3892 } else if (l2gre_vpn_info->flags & BCM_L2GRE_VPN_SERVICE_VLAN_DELETE) { 3893 soc_mem_field32_set(unit, hw_mem, 3894 vxlate_entry, L2GRE_VFI__SD_TAG_ACTION_IF_PRESENTf, 3895 0x3); /* DELETE */ 3896 } else if (l2gre_vpn_info->flags & BCM_L2GRE_VPN_SERVICE_VLAN_PRI_TPID_REPLACE) { 3897 if (l2gre_vpn_info->egress_service_vlan >= BCM_VLAN_INVALID) { 3898 return BCM_E_PARAM; 3899 } 3900 if (l2gre_vpn_info->pkt_pri > BCM_PRIO_MAX) { 3901 return BCM_E_PARAM; 3902 } 3903 if (l2gre_vpn_info->pkt_cfi > 1) { 3904 return BCM_E_PARAM; 3905 } 3906 soc_mem_field32_set(unit, hw_mem, 3907 vxlate_entry, L2GRE_VFI__SD_TAG_VIDf, 3908 l2gre_vpn_info->egress_service_vlan); 3909 if (soc_mem_field_valid(unit, hw_mem, 3910 L2GRE_VFI__SD_TAG_NEW_PRIf)) { 3911 soc_mem_field32_set(unit, hw_mem, 3912 vxlate_entry, L2GRE_VFI__SD_TAG_NEW_PRIf, 3913 l2gre_vpn_info->pkt_pri); 3914 } 3915 if (soc_mem_field_valid(unit, hw_mem, 3916 L2GRE_VFI__SD_TAG_NEW_CFIf)) { 3917 soc_mem_field32_set(unit, hw_mem, 3918 vxlate_entry, L2GRE_VFI__SD_TAG_NEW_CFIf, 3919 l2gre_vpn_info->pkt_cfi); 3920 } 3921 3922 soc_mem_field32_set(unit, hw_mem, 3923 vxlate_entry, L2GRE_VFI__SD_TAG_ACTION_IF_PRESENTf, 3924 0x4); /* REPLACE_VID_PRI_TPID */ 3925 3926 } else if (l2gre_vpn_info->flags & BCM_L2GRE_VPN_SERVICE_VLAN_PRI_REPLACE ){ 3927 if (l2gre_vpn_info->egress_service_vlan >= BCM_VLAN_INVALID) { 3928 return BCM_E_PARAM; 3929 } 3930 if (l2gre_vpn_info->pkt_pri > BCM_PRIO_MAX) { 3931 return BCM_E_PARAM; 3932 } 3933 if (l2gre_vpn_info->pkt_cfi > 1) { 3934 return BCM_E_PARAM; 3935 } 3936 soc_mem_field32_set(unit, hw_mem, 3937 vxlate_entry, L2GRE_VFI__SD_TAG_VIDf, 3938 l2gre_vpn_info->egress_service_vlan); 3939 3940 if (soc_mem_field_valid(unit, hw_mem, 3941 L2GRE_VFI__SD_TAG_NEW_PRIf)) { 3942 soc_mem_field32_set(unit, hw_mem, 3943 vxlate_entry, L2GRE_VFI__SD_TAG_NEW_PRIf, 3944 l2gre_vpn_info->pkt_pri); 3945 } 3946 if (soc_mem_field_valid(unit, hw_mem, 3947 L2GRE_VFI__SD_TAG_NEW_CFIf)) { 3948 soc_mem_field32_set(unit, hw_mem, 3949 vxlate_entry, L2GRE_VFI__SD_TAG_NEW_CFIf, 3950 l2gre_vpn_info->pkt_cfi); 3951 } 3952 3953 soc_mem_field32_set(unit, hw_mem, 3954 vxlate_entry, L2GRE_VFI__SD_TAG_ACTION_IF_PRESENTf, 3955 0x5); /* REPLACE_VID_PRI */ 3956 }else if (l2gre_vpn_info->flags & BCM_L2GRE_VPN_SERVICE_PRI_REPLACE ) { 3957 if (l2gre_vpn_info->pkt_pri > BCM_PRIO_MAX) { 3958 return BCM_E_PARAM; 3959 } 3960 if (l2gre_vpn_info->pkt_cfi > 1) { 3961 return BCM_E_PARAM; 3962 } 3963 if (soc_mem_field_valid(unit, hw_mem, 3964 L2GRE_VFI__SD_TAG_NEW_PRIf)) { 3965 soc_mem_field32_set(unit, hw_mem, 3966 vxlate_entry, L2GRE_VFI__SD_TAG_NEW_PRIf, 3967 l2gre_vpn_info->pkt_pri); 3968 } 3969 if (soc_mem_field_valid(unit, hw_mem, 3970 L2GRE_VFI__SD_TAG_NEW_CFIf)) { 3971 soc_mem_field32_set(unit, hw_mem, 3972 vxlate_entry, L2GRE_VFI__SD_TAG_NEW_CFIf, 3973 l2gre_vpn_info->pkt_cfi); 3974 } 3975 3976 soc_mem_field32_set(unit, hw_mem, 3977 vxlate_entry, L2GRE_VFI__SD_TAG_ACTION_IF_PRESENTf, 3978 0x6); /* REPLACE_PRI_ONLY */ 3979 3980 } else if (l2gre_vpn_info->flags & BCM_L2GRE_VPN_SERVICE_TPID_REPLACE ) { 3981 soc_mem_field32_set(unit, hw_mem, 3982 vxlate_entry, L2GRE_VFI__SD_TAG_ACTION_IF_PRESENTf, 3983 0x7); /* REPLACE_TPID_ONLY */ 3984 } 3985 3986 if ((l2gre_vpn_info->flags & BCM_L2GRE_VPN_SERVICE_VLAN_ADD) || 3987 (l2gre_vpn_info->flags & BCM_L2GRE_VPN_SERVICE_VLAN_TPID_REPLACE) || 3988 (l2gre_vpn_info->flags & BCM_L2GRE_VPN_SERVICE_TPID_REPLACE) || 3989 (l2gre_vpn_info->flags & BCM_L2GRE_VPN_SERVICE_VLAN_PRI_TPID_REPLACE)) { 3990 /* TPID value is used */ 3991 BCM_IF_ERROR_RETURN( 3992 _bcm_fb2_outer_tpid_entry_add(unit, l2gre_vpn_info->egress_service_tpid, tpid_index)); 3993 soc_mem_field32_set(unit, hw_mem, 3994 vxlate_entry, L2GRE_VFI__SD_TAG_TPID_INDEXf, *tpid_index); 3995 } 3996 } else { 3997 3998 if (l2gre_port->flags & BCM_L2GRE_PORT_SERVICE_VLAN_ADD) { 3999 if (l2gre_port->egress_service_vlan >= BCM_VLAN_INVALID) { 4000 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 4001 if (soc_feature(unit, soc_feature_vp_sharing)) { 4002 egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID; 4003 } else 4004 #endif 4005 { 4006 return BCM_E_PARAM; 4007 } 4008 } else { 4009 egr_nh_info->sd_tag_vlan = l2gre_port->egress_service_vlan; 4010 } 4011 4012 egr_nh_info->sd_tag_action_not_present = 0x1; /* ADD */ 4013 } 4014 4015 if (l2gre_port->flags & BCM_L2GRE_PORT_SERVICE_VLAN_TPID_REPLACE) { 4016 if (l2gre_port->egress_service_vlan >= BCM_VLAN_INVALID) { 4017 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 4018 if (soc_feature(unit, soc_feature_vp_sharing)) { 4019 egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID; 4020 } else 4021 #endif 4022 { 4023 return BCM_E_PARAM; 4024 } 4025 } else { 4026 egr_nh_info->sd_tag_vlan = l2gre_port->egress_service_vlan; 4027 } 4028 /* REPLACE_VID_TPID */ 4029 egr_nh_info->sd_tag_action_present = 0x1; 4030 } else if (l2gre_port->flags & BCM_L2GRE_PORT_SERVICE_VLAN_REPLACE) { 4031 if (l2gre_port->egress_service_vlan >= BCM_VLAN_INVALID) { 4032 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 4033 if (soc_feature(unit, soc_feature_vp_sharing)) { 4034 egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID; 4035 } else 4036 #endif 4037 { 4038 return BCM_E_PARAM; 4039 } 4040 } else { 4041 egr_nh_info->sd_tag_vlan = l2gre_port->egress_service_vlan; 4042 } 4043 /* REPLACE_VID_ONLY */ 4044 egr_nh_info->sd_tag_action_present = 0x2; 4045 } else if (l2gre_port->flags & BCM_L2GRE_PORT_SERVICE_VLAN_DELETE) { 4046 egr_nh_info->sd_tag_action_present = 0x3; /* DELETE */ 4047 egr_nh_info->sd_tag_action_not_present = 0; 4048 } else if (l2gre_port->flags & BCM_L2GRE_PORT_SERVICE_VLAN_PRI_TPID_REPLACE) { 4049 if (l2gre_port->egress_service_vlan >= BCM_VLAN_INVALID) { 4050 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 4051 if (soc_feature(unit, soc_feature_vp_sharing)) { 4052 egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID; 4053 } else 4054 #endif 4055 { 4056 return BCM_E_PARAM; 4057 } 4058 } else { 4059 egr_nh_info->sd_tag_vlan = l2gre_port->egress_service_vlan; 4060 } 4061 4062 if (l2gre_port->pkt_pri > BCM_PRIO_MAX) { 4063 return BCM_E_PARAM; 4064 } 4065 if (l2gre_port->pkt_cfi > 1) { 4066 return BCM_E_PARAM; 4067 } 4068 4069 /* REPLACE_VID_PRI_TPID */ 4070 egr_nh_info->sd_tag_pri = l2gre_port->pkt_pri; 4071 egr_nh_info->sd_tag_cfi = l2gre_port->pkt_cfi; 4072 egr_nh_info->sd_tag_action_present = 0x4; 4073 } else if (l2gre_port->flags & BCM_L2GRE_PORT_SERVICE_VLAN_PRI_REPLACE ) { 4074 if (l2gre_port->egress_service_vlan >= BCM_VLAN_INVALID) { 4075 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 4076 if (soc_feature(unit, soc_feature_vp_sharing)) { 4077 egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID; 4078 } else 4079 #endif 4080 { 4081 return BCM_E_PARAM; 4082 } 4083 } else { 4084 egr_nh_info->sd_tag_vlan = l2gre_port->egress_service_vlan; 4085 } 4086 if (l2gre_port->pkt_pri > BCM_PRIO_MAX) { 4087 return BCM_E_PARAM; 4088 } 4089 if (l2gre_port->pkt_cfi > 1) { 4090 return BCM_E_PARAM; 4091 } 4092 4093 /* REPLACE_VID_PRI_ONLY */ 4094 egr_nh_info->sd_tag_pri = l2gre_port->pkt_pri; 4095 egr_nh_info->sd_tag_cfi = l2gre_port->pkt_cfi; 4096 egr_nh_info->sd_tag_action_present = 0x5; 4097 } else if (l2gre_port->flags & BCM_L2GRE_PORT_SERVICE_PRI_REPLACE ) { 4098 if (l2gre_port->pkt_pri > BCM_PRIO_MAX) { 4099 return BCM_E_PARAM; 4100 } 4101 if (l2gre_port->pkt_cfi > 1) { 4102 return BCM_E_PARAM; 4103 } 4104 /* REPLACE_PRI_ONLY */ 4105 egr_nh_info->sd_tag_pri = l2gre_port->pkt_pri; 4106 egr_nh_info->sd_tag_cfi = l2gre_port->pkt_cfi; 4107 egr_nh_info->sd_tag_action_present = 0x6; 4108 } else if (l2gre_port->flags & BCM_L2GRE_PORT_SERVICE_TPID_REPLACE ) { 4109 /* REPLACE_TPID_ONLY */ 4110 egr_nh_info->sd_tag_action_present = 0x7; 4111 } 4112 4113 if ((l2gre_port->flags & BCM_L2GRE_PORT_SERVICE_VLAN_ADD) || 4114 (l2gre_port->flags & BCM_L2GRE_PORT_SERVICE_VLAN_TPID_REPLACE) || 4115 (l2gre_port->flags & BCM_L2GRE_PORT_SERVICE_TPID_REPLACE) || 4116 (l2gre_port->flags & BCM_L2GRE_PORT_SERVICE_VLAN_PRI_TPID_REPLACE)) { 4117 /* TPID value is used */ 4118 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_add(unit, l2gre_port->egress_service_tpid, tpid_index)); 4119 egr_nh_info->tpid_index = *tpid_index; 4120 } 4121 } 4122 return BCM_E_NONE; 4123 } 4124 4125 /* 4126 * Function: 4127 * _bcm_tr3_l2gre_sd_tag_get 4128 * Purpose: 4129 * Get SD_TAG settings 4130 * Parameters: 4131 * unit - (IN) SOC unit # 4132 * l2gre_port - (IN) L2GRE VP 4133 * egr_nh_info (IN/OUT) Egress NHop Info 4134 * Returns: 4135 * BCM_E_XXX 4136 */ 4137 4138 STATIC void 4139 _bcm_tr3_l2gre_sd_tag_get( int unit, bcm_l2gre_vpn_config_t *l2gre_vpn_info, 4140 bcm_l2gre_port_t *l2gre_port, 4141 egr_l3_next_hop_entry_t *egr_nh, 4142 uint32 *vxlate_entry, 4143 int network_port_flag ) 4144 { 4145 int action_present, action_not_present; 4146 soc_mem_t hw_mem; 4147 4148 if (network_port_flag) { 4149 #if defined(BCM_TRIDENT3_SUPPORT) 4150 if (soc_feature(unit, soc_feature_base_valid)) { 4151 hw_mem = EGR_VLAN_XLATE_1_DOUBLEm; 4152 } else 4153 #endif 4154 { 4155 hw_mem = EGR_VLAN_XLATEm; 4156 } 4157 4158 action_present = soc_mem_field32_get(unit, hw_mem, vxlate_entry, 4159 L2GRE_VFI__SD_TAG_ACTION_IF_PRESENTf); 4160 action_not_present = soc_mem_field32_get(unit, hw_mem, vxlate_entry, 4161 L2GRE_VFI__SD_TAG_ACTION_IF_NOT_PRESENTf); 4162 4163 switch (action_present) { 4164 case 0: 4165 if (action_not_present == 1) { 4166 l2gre_vpn_info->flags |= BCM_L2GRE_VPN_SERVICE_VLAN_ADD; 4167 } 4168 l2gre_vpn_info->egress_service_vlan = 4169 soc_mem_field32_get(unit, hw_mem, vxlate_entry, L2GRE_VFI__SD_TAG_VIDf); 4170 break; 4171 4172 case 1: 4173 if (action_not_present == 1) { 4174 l2gre_vpn_info->flags |= BCM_L2GRE_VPN_SERVICE_VLAN_ADD; 4175 } 4176 l2gre_vpn_info->flags |= BCM_L2GRE_VPN_SERVICE_VLAN_TPID_REPLACE; 4177 l2gre_vpn_info->egress_service_vlan = 4178 soc_mem_field32_get(unit, hw_mem, vxlate_entry, L2GRE_VFI__SD_TAG_VIDf); 4179 break; 4180 4181 case 2: 4182 if (action_not_present == 1) { 4183 l2gre_vpn_info->flags |= BCM_L2GRE_VPN_SERVICE_VLAN_ADD; 4184 } 4185 l2gre_vpn_info->flags |= BCM_L2GRE_VPN_SERVICE_VLAN_REPLACE; 4186 l2gre_vpn_info->egress_service_vlan = 4187 soc_mem_field32_get(unit, hw_mem, vxlate_entry, L2GRE_VFI__SD_TAG_VIDf); 4188 break; 4189 4190 case 3: 4191 if (action_not_present == 1) { 4192 l2gre_vpn_info->flags |= BCM_L2GRE_VPN_SERVICE_VLAN_ADD; 4193 } 4194 l2gre_vpn_info->flags |= BCM_L2GRE_VPN_SERVICE_VLAN_DELETE; 4195 l2gre_vpn_info->egress_service_vlan = BCM_VLAN_INVALID; 4196 break; 4197 4198 case 4: 4199 if (action_not_present == 1) { 4200 l2gre_vpn_info->flags |= BCM_L2GRE_VPN_SERVICE_VLAN_ADD; 4201 } 4202 l2gre_vpn_info->flags |= BCM_L2GRE_VPN_SERVICE_VLAN_PRI_TPID_REPLACE; 4203 l2gre_vpn_info->egress_service_vlan = 4204 soc_mem_field32_get(unit, hw_mem, vxlate_entry, L2GRE_VFI__SD_TAG_VIDf); 4205 l2gre_vpn_info->pkt_pri = 4206 soc_mem_field32_get(unit, hw_mem, vxlate_entry, L2GRE_VFI__SD_TAG_NEW_PRIf); 4207 l2gre_vpn_info->pkt_cfi = 4208 soc_mem_field32_get(unit, hw_mem, vxlate_entry, L2GRE_VFI__SD_TAG_NEW_CFIf); 4209 break; 4210 4211 case 5: 4212 if (action_not_present == 1) { 4213 l2gre_vpn_info->flags |= BCM_L2GRE_VPN_SERVICE_VLAN_ADD; 4214 } 4215 l2gre_vpn_info->flags |= BCM_L2GRE_VPN_SERVICE_VLAN_PRI_REPLACE; 4216 l2gre_vpn_info->egress_service_vlan = 4217 soc_mem_field32_get(unit, hw_mem, vxlate_entry, L2GRE_VFI__SD_TAG_VIDf); 4218 l2gre_vpn_info->pkt_pri = 4219 soc_mem_field32_get(unit, hw_mem, vxlate_entry, L2GRE_VFI__SD_TAG_NEW_PRIf); 4220 l2gre_vpn_info->pkt_cfi = 4221 soc_mem_field32_get(unit, hw_mem, vxlate_entry, L2GRE_VFI__SD_TAG_NEW_CFIf); 4222 break; 4223 4224 case 6: 4225 if (action_not_present == 1) { 4226 l2gre_vpn_info->flags |= BCM_L2GRE_VPN_SERVICE_VLAN_ADD; 4227 } 4228 l2gre_vpn_info->flags |= BCM_L2GRE_VPN_SERVICE_PRI_REPLACE; 4229 l2gre_vpn_info->egress_service_vlan = BCM_VLAN_INVALID; 4230 l2gre_vpn_info->pkt_pri = 4231 soc_mem_field32_get(unit, hw_mem, vxlate_entry, L2GRE_VFI__SD_TAG_NEW_PRIf); 4232 l2gre_vpn_info->pkt_cfi = 4233 soc_mem_field32_get(unit, hw_mem, vxlate_entry, L2GRE_VFI__SD_TAG_NEW_CFIf); 4234 break; 4235 4236 case 7: 4237 if (action_not_present == 1) { 4238 l2gre_vpn_info->flags |= BCM_L2GRE_VPN_SERVICE_VLAN_ADD; 4239 } 4240 l2gre_vpn_info->flags |= BCM_L2GRE_VPN_SERVICE_TPID_REPLACE; 4241 l2gre_vpn_info->egress_service_vlan = BCM_VLAN_INVALID; 4242 break; 4243 4244 default: 4245 break; 4246 } 4247 }else { 4248 action_present = 4249 soc_EGR_L3_NEXT_HOPm_field32_get(unit, 4250 egr_nh, 4251 SD_TAG__SD_TAG_ACTION_IF_PRESENTf); 4252 action_not_present = 4253 soc_EGR_L3_NEXT_HOPm_field32_get(unit, 4254 egr_nh, 4255 SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf); 4256 4257 switch (action_present) { 4258 case 0: 4259 if (action_not_present == 1) { 4260 l2gre_port->flags |= BCM_L2GRE_PORT_SERVICE_VLAN_ADD; 4261 } 4262 l2gre_port->egress_service_vlan = 4263 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__SD_TAG_VIDf); 4264 break; 4265 4266 case 1: 4267 if (action_not_present == 1) { 4268 l2gre_port->flags |= BCM_L2GRE_PORT_SERVICE_VLAN_ADD; 4269 } 4270 l2gre_port->flags |= BCM_L2GRE_PORT_SERVICE_VLAN_TPID_REPLACE; 4271 l2gre_port->egress_service_vlan = 4272 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__SD_TAG_VIDf); 4273 break; 4274 4275 case 2: 4276 if (action_not_present == 1) { 4277 l2gre_port->flags |= BCM_L2GRE_PORT_SERVICE_VLAN_ADD; 4278 } 4279 l2gre_port->flags |= BCM_L2GRE_PORT_SERVICE_VLAN_REPLACE; 4280 l2gre_port->egress_service_vlan = 4281 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__SD_TAG_VIDf); 4282 break; 4283 4284 case 3: 4285 if (action_not_present == 1) { 4286 l2gre_port->flags |= BCM_L2GRE_PORT_SERVICE_VLAN_ADD; 4287 } 4288 l2gre_port->flags |= BCM_L2GRE_PORT_SERVICE_VLAN_DELETE; 4289 l2gre_port->egress_service_vlan = BCM_VLAN_INVALID; 4290 break; 4291 4292 case 4: 4293 if (action_not_present == 1) { 4294 l2gre_port->flags |= BCM_L2GRE_PORT_SERVICE_VLAN_ADD; 4295 } 4296 l2gre_port->flags |= BCM_L2GRE_PORT_SERVICE_VLAN_PRI_TPID_REPLACE; 4297 l2gre_port->egress_service_vlan = 4298 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__SD_TAG_VIDf); 4299 l2gre_port->pkt_pri = 4300 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__NEW_PRIf); 4301 l2gre_port->pkt_cfi = 4302 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__NEW_CFIf); 4303 break; 4304 4305 case 5: 4306 if (action_not_present == 1) { 4307 l2gre_port->flags |= BCM_L2GRE_PORT_SERVICE_VLAN_ADD; 4308 } 4309 l2gre_port->flags |= BCM_L2GRE_PORT_SERVICE_VLAN_PRI_REPLACE; 4310 l2gre_port->egress_service_vlan = 4311 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__SD_TAG_VIDf); 4312 l2gre_port->pkt_pri = 4313 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__NEW_PRIf); 4314 l2gre_port->pkt_cfi = 4315 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__NEW_CFIf); 4316 break; 4317 4318 case 6: 4319 if (action_not_present == 1) { 4320 l2gre_port->flags |= BCM_L2GRE_PORT_SERVICE_VLAN_ADD; 4321 } 4322 l2gre_port->flags |= BCM_L2GRE_PORT_SERVICE_PRI_REPLACE; 4323 l2gre_port->egress_service_vlan = BCM_VLAN_INVALID; 4324 l2gre_port->pkt_pri = 4325 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__NEW_PRIf); 4326 l2gre_port->pkt_cfi = 4327 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__NEW_CFIf); 4328 break; 4329 4330 case 7: 4331 if (action_not_present == 1) { 4332 l2gre_port->flags |= BCM_L2GRE_PORT_SERVICE_VLAN_ADD; 4333 } 4334 l2gre_port->flags |= BCM_L2GRE_PORT_SERVICE_TPID_REPLACE; 4335 l2gre_port->egress_service_vlan = BCM_VLAN_INVALID; 4336 break; 4337 4338 default: 4339 break; 4340 } 4341 } 4342 } 4343 4344 /* 4345 * Function: 4346 * _bcm_tr3_l2gre_nexthop_entry_modify 4347 * Purpose: 4348 * Modify Egress entry 4349 * Parameters: 4350 * unit - Device Number 4351 * nh_index - Next Hop Index 4352 * new_entry_type - New Entry type 4353 * Returns: 4354 * BCM_E_XXX 4355 */ 4356 4357 STATIC int 4358 _bcm_tr3_l2gre_nexthop_entry_modify(int unit, int nh_index, int drop, 4359 _bcm_tr3_l2gre_nh_info_t *egr_nh_info, int new_entry_type) 4360 { 4361 egr_l3_next_hop_entry_t egr_nh; 4362 int rv = BCM_E_NONE; 4363 uint32 old_entry_type=0, intf_num=0, vntag_actions=0; 4364 uint32 vntag_dst_vif=0, vntag_pf=0, vntag_force_lf=0; 4365 uint32 etag_pcp_de_sourcef=0, etag_pcpf=0, etag_dot1p_mapping_ptr=0; 4366 bcm_mac_t mac_addr; /* Next hop forwarding destination mac. */ 4367 soc_field_t type_field; 4368 4369 #if defined(BCM_TRIDENT3_SUPPORT) 4370 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, DATA_TYPEf)) { 4371 type_field = DATA_TYPEf; 4372 } else 4373 #endif 4374 { 4375 type_field = ENTRY_TYPEf; 4376 } 4377 4378 sal_memset(&mac_addr, 0, sizeof (mac_addr)); 4379 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, 4380 nh_index, &egr_nh)); 4381 4382 old_entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, type_field); 4383 4384 if ((new_entry_type == _BCM_L2GRE_EGR_NEXT_HOP_SDTAG_VIEW) && 4385 (old_entry_type == _BCM_L2GRE_EGR_NEXT_HOP_L3_VIEW)) { 4386 /*Zero buffers.*/ 4387 sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t)); 4388 if (egr_nh_info->sd_tag_vlan != -1) { 4389 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 4390 if (soc_feature(unit, soc_feature_vp_sharing)) { 4391 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, SD_TAG__SD_TAG_NOT_VALIDf)) { 4392 if (egr_nh_info->sd_tag_vlan == BCM_VLAN_INVALID) { 4393 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4394 &egr_nh, SD_TAG__SD_TAG_NOT_VALIDf, 1); 4395 } else { 4396 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4397 &egr_nh, SD_TAG__SD_TAG_NOT_VALIDf, 0); 4398 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4399 &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info->sd_tag_vlan); 4400 } 4401 } else { 4402 if (egr_nh_info->sd_tag_vlan < BCM_VLAN_INVALID) { 4403 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4404 &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info->sd_tag_vlan); 4405 } 4406 } 4407 } else 4408 #endif 4409 { 4410 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4411 &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info->sd_tag_vlan); 4412 } 4413 } 4414 4415 if (egr_nh_info->sd_tag_action_present != -1) { 4416 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4417 SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 4418 egr_nh_info->sd_tag_action_present); 4419 } 4420 4421 if (egr_nh_info->sd_tag_action_not_present != -1) { 4422 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4423 SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf, 4424 egr_nh_info->sd_tag_action_not_present); 4425 } 4426 4427 if (egr_nh_info->sd_tag_pri != -1) { 4428 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__NEW_PRIf)) { 4429 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4430 SD_TAG__NEW_PRIf, 4431 egr_nh_info->sd_tag_pri); 4432 } 4433 } 4434 4435 if (egr_nh_info->sd_tag_cfi != -1) { 4436 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__NEW_CFIf)) { 4437 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4438 SD_TAG__NEW_CFIf, 4439 egr_nh_info->sd_tag_cfi); 4440 } 4441 } 4442 4443 if (egr_nh_info->tpid_index != -1) { 4444 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4445 &egr_nh, SD_TAG__SD_TAG_TPID_INDEXf, 4446 egr_nh_info->tpid_index); 4447 } 4448 4449 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4450 SD_TAG__BC_DROPf, drop ? 1 : 0); 4451 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4452 SD_TAG__UUC_DROPf, drop ? 1 : 0); 4453 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4454 SD_TAG__UMC_DROPf, drop ? 1 : 0); 4455 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4456 SD_TAG__DVPf, egr_nh_info->dvp); 4457 #if defined(BCM_TRIDENT3_SUPPORT) 4458 if (SOC_IS_TRIDENT3X(unit)) { 4459 } else 4460 #endif 4461 { 4462 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 4463 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4464 &egr_nh, SD_TAG__DVP_NETWORK_GROUPf, 4465 egr_nh_info->dvp_network_group_id); 4466 } else { 4467 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4468 &egr_nh, SD_TAG__DVP_IS_NETWORK_PORTf, 4469 egr_nh_info->dvp_is_network); 4470 } 4471 } 4472 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4473 SD_TAG__HG_LEARN_OVERRIDEf, egr_nh_info->is_eline ? 1 : 0); 4474 /* HG_MODIFY_ENABLE must be 0x0 for Ingress and Egress Chip */ 4475 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4476 SD_TAG__HG_MODIFY_ENABLEf, 0x0); 4477 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4478 SD_TAG__HG_HDR_SELf, 1); 4479 4480 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4481 type_field, _BCM_L2GRE_EGR_NEXT_HOP_SDTAG_VIEW); /* SD_TAG view */ 4482 } else if ((new_entry_type == _BCM_L2GRE_EGR_NEXT_HOP_L3_VIEW) && 4483 (old_entry_type == _BCM_L2GRE_EGR_NEXT_HOP_SDTAG_VIEW)) { 4484 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4485 type_field, _BCM_L2GRE_EGR_NEXT_HOP_L3_VIEW); /* Normal view */ 4486 /* No intf_num in SDTAG view, get first valid index */ 4487 if (soc_feature(unit, soc_feature_l3_egr_intf_zero_invalid)) { 4488 intf_num = soc_mem_index_min(unit, 4489 BCM_XGS3_L3_MEM(unit, intf)) + 1; 4490 } else { 4491 intf_num = soc_mem_index_min(unit, 4492 BCM_XGS3_L3_MEM(unit, intf)); 4493 } 4494 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4495 L3__INTF_NUMf, intf_num); 4496 } else if ((new_entry_type == _BCM_L2GRE_EGR_NEXT_HOP_L3MC_VIEW) && 4497 (old_entry_type == _BCM_L2GRE_EGR_NEXT_HOP_L3_VIEW)) { 4498 4499 /* Get mac address. */ 4500 soc_mem_mac_addr_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4501 L3__MAC_ADDRESSf, mac_addr); 4502 4503 /* Get int_num */ 4504 intf_num = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4505 L3__INTF_NUMf); 4506 4507 vntag_actions = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4508 L3__VNTAG_ACTIONSf); 4509 4510 vntag_dst_vif = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4511 L3__VNTAG_DST_VIFf); 4512 4513 vntag_pf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4514 L3MC__VNTAG_Pf); 4515 4516 vntag_force_lf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4517 L3MC__VNTAG_FORCE_Lf); 4518 4519 etag_pcp_de_sourcef = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4520 L3MC__ETAG_PCP_DE_SOURCEf); 4521 4522 etag_pcpf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4523 L3MC__ETAG_PCPf); 4524 4525 etag_dot1p_mapping_ptr = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4526 L3MC__ETAG_DOT1P_MAPPING_PTRf); 4527 4528 sal_memset(&egr_nh, 0, sizeof (egr_nh)); 4529 soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4530 L3MC__MAC_ADDRESSf, mac_addr); 4531 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4532 L3MC__INTF_NUMf, intf_num); 4533 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4534 L3MC__DVPf, egr_nh_info->dvp); 4535 #ifdef BCM_TRIDENT2PLUS_SUPPORT 4536 if (soc_feature(unit, soc_feature_egr_l3_next_hop_next_ptr)) { 4537 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4538 L3MC__NEXT_PTR_TYPEf, 1); 4539 } else 4540 #endif 4541 { 4542 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4543 L3MC__DVP_VALIDf, 0x1); 4544 } 4545 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3MC__L2_MC_DA_DISABLEf)) { 4546 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4547 L3MC__L2_MC_DA_DISABLEf, 0x1); 4548 } 4549 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3MC__L2_MC_SA_DISABLEf)) { 4550 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4551 L3MC__L2_MC_SA_DISABLEf, 0x1); 4552 } 4553 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3MC__L2_MC_VLAN_DISABLEf)) { 4554 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4555 L3MC__L2_MC_VLAN_DISABLEf, 0x1); 4556 } 4557 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4558 L3MC__L2_DROPf, 0x0); 4559 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4560 L3MC__L3_DROPf, drop ? 1 : 0); 4561 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4562 L3MC__L3MC_USE_CONFIGURED_MACf, 0x1); 4563 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4564 L3MC__VNTAG_ACTIONSf, vntag_actions); 4565 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4566 L3MC__VNTAG_DST_VIFf, vntag_dst_vif); 4567 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4568 L3MC__VNTAG_Pf, vntag_pf); 4569 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4570 L3MC__VNTAG_FORCE_Lf, vntag_force_lf); 4571 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4572 L3MC__ETAG_PCP_DE_SOURCEf, etag_pcp_de_sourcef); 4573 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4574 L3MC__ETAG_PCPf, etag_pcpf); 4575 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4576 L3MC__ETAG_DOT1P_MAPPING_PTRf, etag_dot1p_mapping_ptr); 4577 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4578 type_field, _BCM_L2GRE_EGR_NEXT_HOP_L3MC_VIEW); 4579 } else if ((new_entry_type == _BCM_L2GRE_EGR_NEXT_HOP_L3MC_VIEW) && 4580 (old_entry_type == _BCM_L2GRE_EGR_NEXT_HOP_L3MC_VIEW)) { 4581 4582 /* Get mac address. */ 4583 soc_mem_mac_addr_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4584 L3MC__MAC_ADDRESSf, mac_addr); 4585 4586 /* Get int_num */ 4587 intf_num = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4588 L3MC__INTF_NUMf); 4589 4590 vntag_actions = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4591 L3MC__VNTAG_ACTIONSf); 4592 4593 vntag_dst_vif = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4594 L3MC__VNTAG_DST_VIFf); 4595 4596 vntag_pf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4597 L3MC__VNTAG_Pf); 4598 4599 vntag_force_lf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4600 L3MC__VNTAG_FORCE_Lf); 4601 4602 etag_pcp_de_sourcef = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4603 L3MC__ETAG_PCP_DE_SOURCEf); 4604 4605 etag_pcpf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4606 L3MC__ETAG_PCPf); 4607 4608 etag_dot1p_mapping_ptr = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4609 L3MC__ETAG_DOT1P_MAPPING_PTRf); 4610 4611 soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4612 L3MC__MAC_ADDRESSf, mac_addr); 4613 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4614 L3MC__INTF_NUMf, intf_num); 4615 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 4616 if (soc_feature(unit, soc_feature_egr_l3_next_hop_next_ptr)) { 4617 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4618 L3MC__NEXT_PTR_TYPEf, 0x1); 4619 } else 4620 #endif 4621 { 4622 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4623 L3MC__DVP_VALIDf, 0x1); 4624 } 4625 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4626 L3MC__DVPf, egr_nh_info->dvp); 4627 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4628 L3MC__L2_MC_DA_DISABLEf, 0x1); 4629 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4630 L3MC__L2_MC_SA_DISABLEf, 0x1); 4631 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4632 L3MC__L2_MC_VLAN_DISABLEf, 0x1); 4633 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4634 L3MC__L2_DROPf, 0x0); 4635 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4636 L3MC__L3_DROPf, drop ? 1 : 0); 4637 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4638 L3MC__L3MC_USE_CONFIGURED_MACf, 0x1); 4639 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4640 L3MC__VNTAG_ACTIONSf, vntag_actions); 4641 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4642 L3MC__VNTAG_DST_VIFf, vntag_dst_vif); 4643 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4644 L3MC__VNTAG_Pf, vntag_pf); 4645 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4646 L3MC__VNTAG_FORCE_Lf, vntag_force_lf); 4647 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4648 L3MC__ETAG_PCP_DE_SOURCEf, etag_pcp_de_sourcef); 4649 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4650 L3MC__ETAG_PCPf, etag_pcpf); 4651 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4652 L3MC__ETAG_DOT1P_MAPPING_PTRf, etag_dot1p_mapping_ptr); 4653 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4654 type_field, _BCM_L2GRE_EGR_NEXT_HOP_L3MC_VIEW); 4655 } else if ((new_entry_type == _BCM_L2GRE_EGR_NEXT_HOP_L3_VIEW) && 4656 (old_entry_type == _BCM_L2GRE_EGR_NEXT_HOP_L3MC_VIEW)) { 4657 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4658 type_field, _BCM_L2GRE_EGR_NEXT_HOP_L3_VIEW); 4659 } else if ((new_entry_type == _BCM_L2GRE_EGR_NEXT_HOP_SDTAG_VIEW) && 4660 (old_entry_type == _BCM_L2GRE_EGR_NEXT_HOP_SDTAG_VIEW)) { 4661 4662 /* Case of L2GRE Proxy Next-Hop */ 4663 if (egr_nh_info->sd_tag_vlan != -1) { 4664 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 4665 if (soc_feature(unit, soc_feature_vp_sharing)) { 4666 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, SD_TAG__SD_TAG_NOT_VALIDf)) { 4667 if (egr_nh_info->sd_tag_vlan == BCM_VLAN_INVALID) { 4668 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4669 &egr_nh, SD_TAG__SD_TAG_NOT_VALIDf, 1); 4670 } else { 4671 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4672 &egr_nh, SD_TAG__SD_TAG_NOT_VALIDf, 0); 4673 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4674 &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info->sd_tag_vlan); 4675 } 4676 } else { 4677 if (egr_nh_info->sd_tag_vlan < BCM_VLAN_INVALID) { 4678 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4679 &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info->sd_tag_vlan); 4680 } 4681 } 4682 } else 4683 #endif 4684 { 4685 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4686 &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info->sd_tag_vlan); 4687 } 4688 } 4689 4690 if (egr_nh_info->sd_tag_action_present != -1) { 4691 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4692 SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 4693 egr_nh_info->sd_tag_action_present); 4694 } 4695 4696 if (egr_nh_info->sd_tag_action_not_present != -1) { 4697 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4698 SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf, 4699 egr_nh_info->sd_tag_action_not_present); 4700 } 4701 4702 if (egr_nh_info->sd_tag_pri != -1) { 4703 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__NEW_PRIf)) { 4704 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4705 SD_TAG__NEW_PRIf, 4706 egr_nh_info->sd_tag_pri); 4707 } 4708 } 4709 4710 if (egr_nh_info->sd_tag_cfi != -1) { 4711 if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__NEW_CFIf)) { 4712 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4713 SD_TAG__NEW_CFIf, 4714 egr_nh_info->sd_tag_cfi); 4715 } 4716 } 4717 4718 if (egr_nh_info->tpid_index != -1) { 4719 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4720 &egr_nh, SD_TAG__SD_TAG_TPID_INDEXf, 4721 egr_nh_info->tpid_index); 4722 } 4723 4724 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 4725 SD_TAG__DVPf, egr_nh_info->dvp); 4726 #if defined(BCM_TRIDENT3_SUPPORT) 4727 if (SOC_IS_TRIDENT3X(unit)) { 4728 } else 4729 #endif 4730 { 4731 if (egr_nh_info->sd_tag_cfi != -1) { 4732 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 4733 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4734 &egr_nh, SD_TAG__DVP_NETWORK_GROUPf, 4735 egr_nh_info->dvp_network_group_id); 4736 } else { 4737 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 4738 &egr_nh, SD_TAG__DVP_IS_NETWORK_PORTf, 4739 egr_nh_info->dvp_is_network); 4740 } 4741 } 4742 } 4743 4744 } 4745 4746 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 4747 MEM_BLOCK_ALL, nh_index, &egr_nh); 4748 return rv; 4749 } 4750 4751 /* 4752 * Function: 4753 * _bcm_tr3_l2gre_next_hop_set 4754 * Purpose: 4755 * Set L2GRE NextHop entry 4756 * Parameters: 4757 * IN : Unit 4758 * IN : nh_index 4759 * Returns: 4760 * BCM_E_XXX 4761 */ 4762 4763 int 4764 _bcm_tr3_l2gre_next_hop_set(int unit, int nh_index, uint32 flags) 4765 { 4766 int rv=BCM_E_NONE; 4767 bcm_port_t port = -1; 4768 bcm_module_t modid = -1, local_modid = -1; 4769 bcm_trunk_t tgid = -1; 4770 int num_ports=0, idx=-1; 4771 bcm_port_t local_ports[SOC_MAX_NUM_PORTS]; 4772 int old_nh_index=-1; 4773 int replace=0; 4774 int gport = 0; 4775 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 4776 bcm_trunk_member_t *tmp_member_gports_array = NULL; 4777 #endif 4778 4779 replace = flags & BCM_L3_REPLACE; 4780 4781 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_nexthop_glp_get(unit, 4782 nh_index, &modid, &port, &tgid)); 4783 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &local_modid)); 4784 if (tgid != -1) { 4785 rv = _bcm_trunk_id_validate(unit, tgid); 4786 if (BCM_FAILURE(rv)) { 4787 return BCM_E_PORT; 4788 } 4789 rv = bcm_esw_trunk_get(unit, tgid, NULL, 0, NULL, &num_ports); 4790 if (BCM_FAILURE(rv)) { 4791 return BCM_E_PORT; 4792 } 4793 if (num_ports == 0) { 4794 return BCM_E_NONE; 4795 } 4796 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 4797 if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 4798 tmp_member_gports_array = sal_alloc( 4799 sizeof(bcm_trunk_member_t) * num_ports, "tmp_member_gports_arry"); 4800 if (tmp_member_gports_array == NULL) { 4801 return BCM_E_MEMORY; 4802 } 4803 sal_memset(tmp_member_gports_array, 0, 4804 sizeof(bcm_trunk_member_t) * num_ports); 4805 rv = bcm_esw_trunk_get(unit, tgid, NULL, 4806 num_ports, tmp_member_gports_array, &num_ports); 4807 if (BCM_FAILURE(rv)) { 4808 goto clean_up; 4809 } 4810 } else 4811 #endif 4812 { 4813 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid, 4814 SOC_MAX_NUM_PORTS, local_ports, &num_ports)); 4815 modid = local_modid; 4816 } 4817 } else { 4818 if (modid != local_modid) { 4819 if (!soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 4820 /* Ignore EGR_PORT_TO_NHI_MAPPINGs */ 4821 return BCM_E_NONE; 4822 } 4823 } 4824 4825 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 4826 if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 4827 /* Alloc one trunk member size memory */ 4828 tmp_member_gports_array = sal_alloc( 4829 sizeof(bcm_trunk_member_t), "tmp_member_gports_arry"); 4830 if (tmp_member_gports_array == NULL) { 4831 return BCM_E_MEMORY; 4832 } 4833 sal_memset(tmp_member_gports_array, 0, 4834 sizeof(bcm_trunk_member_t)); 4835 BCM_GPORT_MODPORT_SET(gport, modid, port); 4836 tmp_member_gports_array[num_ports++].gport = gport; 4837 } else 4838 #endif 4839 { 4840 local_ports[num_ports++] = port; 4841 } 4842 } 4843 4844 if (!(flags & BCM_L3_IPMC)) { /* Only for L2GRE Unicast Nexthops */ 4845 for (idx = 0; idx < num_ports; idx++) { 4846 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 4847 if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 4848 gport = tmp_member_gports_array[idx].gport; 4849 } else 4850 #endif 4851 { 4852 BCM_GPORT_MODPORT_SET(gport, modid, local_ports[idx]); 4853 } 4854 4855 rv = _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index); 4856 if (BCM_FAILURE(rv)) { 4857 goto clean_up; 4858 } 4859 if (old_nh_index && !replace) { 4860 if (old_nh_index != nh_index) { 4861 /* Limitation: For TD/TR3, 4862 L2GRE egress port can be configured with one NHI*/ 4863 rv = BCM_E_RESOURCE; 4864 goto clean_up; 4865 } 4866 } else { 4867 rv = _bcm_trx_gport_to_nhi_set(unit, gport, nh_index); 4868 if (BCM_FAILURE(rv)) { 4869 goto clean_up; 4870 } 4871 } 4872 } 4873 } 4874 4875 clean_up: 4876 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 4877 if (NULL != tmp_member_gports_array) { 4878 sal_free(tmp_member_gports_array); 4879 } 4880 #endif 4881 return rv; 4882 } 4883 4884 /* 4885 * Function: 4886 * bcm_tr3_l2gre_nexthop_get 4887 * Purpose: 4888 * Get L2GRE NextHop entry 4889 * Parameters: 4890 * IN : Unit 4891 * IN : nh_index 4892 * Returns: 4893 * BCM_E_XXX 4894 */ 4895 4896 int 4897 bcm_tr3_l2gre_nexthop_get(int unit, int nh_index, bcm_l2gre_port_t *l2gre_port) 4898 { 4899 soc_mem_t hw_mem; 4900 egr_l3_next_hop_entry_t egr_nh; 4901 4902 hw_mem = EGR_L3_NEXT_HOPm; 4903 BCM_IF_ERROR_RETURN(soc_mem_read(unit, hw_mem, 4904 MEM_BLOCK_ANY, nh_index, &egr_nh)); 4905 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3__DVP_VALIDf)) { 4906 if (0x1 == soc_mem_field32_get(unit, hw_mem, &egr_nh, 4907 L3__DVP_VALIDf)) { 4908 l2gre_port->flags |= BCM_L2GRE_PORT_MULTICAST; 4909 } 4910 } else { 4911 if (soc_mem_field32_get(unit, hw_mem, &egr_nh, L3__DVPf) != 0) { 4912 l2gre_port->flags |= BCM_L2GRE_PORT_MULTICAST; 4913 } 4914 } 4915 4916 return BCM_E_NONE; 4917 } 4918 4919 /* 4920 * Function: 4921 * bcm_tr3_l2gre_egr_nexthop_multicast_set 4922 * Purpose: 4923 * Set L2GRE Egress NextHop Multicast 4924 * Parameters: 4925 * IN : Unit 4926 * IN : nh_index 4927 * Returns: 4928 * BCM_E_XXX 4929 */ 4930 4931 STATIC int 4932 bcm_tr3_l2gre_egr_nexthop_multicast_set(int unit, int nh_index, int vp, bcm_l2gre_port_t *l2gre_port) 4933 { 4934 soc_mem_t hw_mem; 4935 egr_l3_next_hop_entry_t egr_nh; 4936 4937 if (l2gre_port->flags & BCM_L2GRE_PORT_MULTICAST) { 4938 hw_mem = EGR_L3_NEXT_HOPm; 4939 BCM_IF_ERROR_RETURN(soc_mem_read(unit, hw_mem, 4940 MEM_BLOCK_ANY, nh_index, &egr_nh)); 4941 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3__DVP_VALIDf)) { 4942 soc_mem_field32_set(unit, hw_mem, &egr_nh, 4943 L3__DVP_VALIDf, 0x1); 4944 } 4945 soc_mem_field32_set(unit, hw_mem, &egr_nh, 4946 L3__DVPf, vp); 4947 BCM_IF_ERROR_RETURN(soc_mem_write(unit, hw_mem, 4948 MEM_BLOCK_ALL, nh_index, &egr_nh)); 4949 } 4950 return BCM_E_NONE; 4951 } 4952 4953 4954 /* 4955 * Function: 4956 * bcm_tr3_l2gre_port_egress_nexthop_reset 4957 * Purpose: 4958 * Reset L2GRE Egress NextHop 4959 * Parameters: 4960 * IN : Unit 4961 * IN : nh_index 4962 * Returns: 4963 * BCM_E_XXX 4964 */ 4965 4966 int 4967 bcm_tr3_l2gre_port_egress_nexthop_reset(int unit, int nh_index, int vp_type, int vp, bcm_vpn_t vpn) 4968 { 4969 egr_l3_next_hop_entry_t egr_nh; 4970 int rv=BCM_E_NONE; 4971 int action_present=0, action_not_present=0, old_tpid_idx = -1; 4972 uint32 entry_type=0; 4973 4974 if (vp_type== _BCM_L2GRE_DEST_VP_TYPE_ACCESS) { 4975 /* egressing into a regular port */ 4976 #if defined(BCM_TRIDENT3_SUPPORT) 4977 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, DATA_TYPEf)) { 4978 entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, DATA_TYPEf); 4979 } else 4980 #endif 4981 { 4982 entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, ENTRY_TYPEf); 4983 } 4984 if (entry_type != _BCM_L2GRE_EGR_NEXT_HOP_SDTAG_VIEW) { 4985 /* coverity[assigned_value] */ 4986 rv = BCM_E_PARAM; 4987 } 4988 4989 action_present = 4990 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 4991 SD_TAG__SD_TAG_ACTION_IF_PRESENTf); 4992 action_not_present = 4993 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 4994 SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf); 4995 if ((action_not_present == 0x1) || (action_present == 0x1)) { 4996 old_tpid_idx = 4997 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 4998 SD_TAG__SD_TAG_TPID_INDEXf); 4999 } 5000 5001 /* Normalize Next-hop Entry -- L3 View */ 5002 rv = _bcm_tr3_l2gre_nexthop_entry_modify(unit, nh_index, 0, 5003 NULL, _BCM_L2GRE_EGR_NEXT_HOP_L3_VIEW); 5004 5005 } 5006 5007 if (old_tpid_idx != -1) { 5008 (void) _bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_idx); 5009 } 5010 return rv; 5011 } 5012 5013 /* 5014 * Function: 5015 * bcm_tr3_l2gre_nexthop_reset 5016 * Purpose: 5017 * Reset L2GRE NextHop entry 5018 * Parameters: 5019 * IN : Unit 5020 * IN : nh_index 5021 * Returns: 5022 * BCM_E_XXX 5023 */ 5024 5025 STATIC int 5026 bcm_tr3_l2gre_nexthop_reset(int unit, int nh_index) 5027 { 5028 int rv=BCM_E_NONE; 5029 ing_l3_next_hop_entry_t ing_nh; 5030 bcm_port_t port=0; 5031 bcm_trunk_t tgid= BCM_TRUNK_INVALID; 5032 int num_ports=0, idx=-1; 5033 bcm_port_t local_ports[SOC_MAX_NUM_PORTS]; 5034 soc_mem_t hw_mem; 5035 bcm_module_t modid=0, local_modid=0; 5036 int old_nh_index=-1; 5037 int gport = 0; 5038 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 5039 bcm_trunk_member_t *tmp_member_gports_array = NULL; 5040 #endif 5041 5042 hw_mem = ING_L3_NEXT_HOPm; 5043 BCM_IF_ERROR_RETURN(soc_mem_read(unit, hw_mem, 5044 MEM_BLOCK_ANY, nh_index, &ing_nh)); 5045 soc_mem_field32_set(unit, hw_mem, &ing_nh, 5046 DROPf, 0x0); 5047 soc_mem_field32_set(unit, hw_mem, &ing_nh, 5048 ENTRY_TYPEf, 0x0); 5049 if (soc_mem_field_valid(unit, ING_L3_NEXT_HOPm, DVP_ATTRIBUTE_1_INDEXf) ) { 5050 soc_mem_field32_set(unit, hw_mem, 5051 &ing_nh, DVP_ATTRIBUTE_1_INDEXf, 0); 5052 } 5053 BCM_IF_ERROR_RETURN(soc_mem_write(unit, hw_mem, 5054 MEM_BLOCK_ALL, nh_index, &ing_nh)); 5055 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_nexthop_glp_get(unit, 5056 nh_index, &modid, &port, &tgid)); 5057 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &local_modid)); 5058 if (tgid != BCM_TRUNK_INVALID) { 5059 rv = _bcm_trunk_id_validate(unit, tgid); 5060 if (BCM_FAILURE(rv)) { 5061 return BCM_E_PORT; 5062 } 5063 rv = bcm_esw_trunk_get(unit, tgid, NULL, 0, NULL, &num_ports); 5064 if (BCM_FAILURE(rv)) { 5065 return BCM_E_PORT; 5066 } 5067 if (num_ports == 0) { 5068 return BCM_E_NONE; 5069 } 5070 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 5071 if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 5072 tmp_member_gports_array = sal_alloc( 5073 sizeof(bcm_trunk_member_t) * num_ports, "tmp_member_gports_arry"); 5074 if (tmp_member_gports_array == NULL) { 5075 return BCM_E_MEMORY; 5076 } 5077 sal_memset(tmp_member_gports_array, 0, 5078 sizeof(bcm_trunk_member_t) * num_ports); 5079 rv = bcm_esw_trunk_get(unit, tgid, NULL, 5080 num_ports, tmp_member_gports_array, &num_ports); 5081 if (BCM_FAILURE(rv)) { 5082 goto clean_up; 5083 } 5084 } else 5085 #endif 5086 { 5087 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid, 5088 SOC_MAX_NUM_PORTS, local_ports, &num_ports)); 5089 modid = local_modid; 5090 } 5091 } else { 5092 if (modid != local_modid) { 5093 if (!soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 5094 /* Ignore EGR_PORT_TO_NHI_MAPPINGs */ 5095 return BCM_E_NONE; 5096 } 5097 } 5098 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 5099 if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 5100 /* Alloc one trunk member size memory */ 5101 tmp_member_gports_array = sal_alloc( 5102 sizeof(bcm_trunk_member_t), "tmp_member_gports_arry"); 5103 if (tmp_member_gports_array == NULL) { 5104 return BCM_E_MEMORY; 5105 } 5106 sal_memset(tmp_member_gports_array, 0, 5107 sizeof(bcm_trunk_member_t)); 5108 BCM_GPORT_MODPORT_SET(gport, modid, port); 5109 tmp_member_gports_array[num_ports++].gport = gport; 5110 } else 5111 #endif 5112 { 5113 local_ports[num_ports++] = port; 5114 } 5115 } 5116 5117 for (idx = 0; idx < num_ports; idx++) { 5118 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 5119 if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 5120 gport = tmp_member_gports_array[idx].gport; 5121 } else 5122 #endif 5123 { 5124 BCM_GPORT_MODPORT_SET(gport, modid, local_ports[idx]); 5125 } 5126 5127 rv = _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index); 5128 if (BCM_FAILURE(rv)) { 5129 goto clean_up; 5130 } 5131 if (old_nh_index == nh_index) { 5132 rv = _bcm_trx_gport_to_nhi_set(unit, gport, 0); 5133 if (BCM_FAILURE(rv)) { 5134 goto clean_up; 5135 } 5136 } 5137 } 5138 5139 clean_up: 5140 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 5141 if (NULL != tmp_member_gports_array) { 5142 sal_free(tmp_member_gports_array); 5143 } 5144 #endif 5145 return rv; 5146 } 5147 5148 5149 /* 5150 * Function: 5151 * bcm_tr3_l2gre_egress_set 5152 * Purpose: 5153 * Set [MTU] L2GRE Egress NextHop 5154 * Parameters: 5155 * IN : Unit 5156 * IN : nh_index 5157 * Returns: 5158 * BCM_E_XXX 5159 */ 5160 5161 int 5162 bcm_tr3_l2gre_egress_set(int unit, int nh_index, uint32 flags) 5163 { 5164 ing_l3_next_hop_entry_t ing_nh; 5165 soc_mem_t hw_mem; 5166 int rv=BCM_E_NONE; 5167 5168 hw_mem = ING_L3_NEXT_HOPm; 5169 BCM_IF_ERROR_RETURN(soc_mem_read(unit, hw_mem, 5170 MEM_BLOCK_ANY, nh_index, &ing_nh)); 5171 soc_mem_field32_set(unit, hw_mem, &ing_nh, 5172 ENTRY_TYPEf, _BCM_L2GRE_INGRESS_NEXT_HOP_ENTRY_TYPE); /* L2 DVP */ 5173 if (SOC_MEM_FIELD_VALID(unit, hw_mem, MTU_SIZEf)) { 5174 soc_mem_field32_set(unit, hw_mem, &ing_nh, MTU_SIZEf, 0x3fff); 5175 } 5176 else if (soc_mem_field_valid(unit, ING_L3_NEXT_HOPm, 5177 DVP_ATTRIBUTE_1_INDEXf)) { 5178 /* Set default ING_L3_NEXT_HOP_ATTRIBUTE_1 MTU_SIZE 5179 * Note: Assumption that first entry has MTU size of 0x3fff 5180 */ 5181 soc_mem_field32_set(unit, hw_mem, 5182 &ing_nh, DVP_ATTRIBUTE_1_INDEXf, 0); 5183 } 5184 BCM_IF_ERROR_RETURN(soc_mem_write(unit, hw_mem, 5185 MEM_BLOCK_ALL, nh_index, &ing_nh)); 5186 5187 rv = _bcm_tr3_l2gre_next_hop_set(unit, nh_index, flags); 5188 return rv; 5189 } 5190 5191 /* 5192 * Function: 5193 * bcm_tr3_l2gre_egress_reset 5194 * Purpose: 5195 * Reset L2GRE Egress NextHop 5196 * Parameters: 5197 * IN : Unit 5198 * IN : nh_index 5199 * Returns: 5200 * BCM_E_XXX 5201 */ 5202 5203 int 5204 bcm_tr3_l2gre_egress_reset(int unit, int nh_index) 5205 { 5206 ing_l3_next_hop_entry_t ing_nh; 5207 soc_mem_t hw_mem; 5208 int rv=BCM_E_NONE; 5209 5210 hw_mem = ING_L3_NEXT_HOPm; 5211 BCM_IF_ERROR_RETURN(soc_mem_read(unit, hw_mem, 5212 MEM_BLOCK_ANY, nh_index, &ing_nh)); 5213 soc_mem_field32_set(unit, hw_mem, &ing_nh, 5214 ENTRY_TYPEf, 0x0); 5215 if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) { 5216 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 5217 &ing_nh, MTU_SIZEf, 0x0); 5218 } 5219 BCM_IF_ERROR_RETURN(soc_mem_write(unit, hw_mem, 5220 MEM_BLOCK_ALL, nh_index, &ing_nh)); 5221 5222 rv = bcm_tr3_l2gre_nexthop_reset(unit, nh_index); 5223 return rv; 5224 } 5225 5226 5227 /* 5228 * Function: 5229 * bcm_tr3_l2gre_egress_get 5230 * Purpose: 5231 * Get L2GRE Egress NextHop 5232 * Parameters: 5233 * IN : Unit 5234 * IN : nh_index 5235 * Returns: 5236 * BCM_E_XXX 5237 */ 5238 5239 int 5240 bcm_tr3_l2gre_egress_get(int unit, bcm_l3_egress_t *egr, int nh_index) 5241 { 5242 int int_l3_flag; 5243 int_l3_flag = BCM_XGS3_L3_ENT_FLAG(BCM_XGS3_L3_TBL_PTR(unit, next_hop), 5244 nh_index); 5245 if (int_l3_flag == _BCM_L3_L2GRE_ONLY) { 5246 egr->flags |= BCM_L3_L2GRE_ONLY; 5247 } 5248 5249 return BCM_E_NONE; 5250 } 5251 5252 5253 /* 5254 * Function: 5255 * _bcm_tr3_l2gre_port_nh_add 5256 * Purpose: 5257 * Add L2GRE Next Hop entry 5258 * Parameters: 5259 * Returns: 5260 * BCM_E_XXX 5261 */ 5262 5263 STATIC int 5264 _bcm_tr3_l2gre_port_nh_add(int unit, bcm_l2gre_port_t *l2gre_port, int vp, 5265 bcm_vpn_t vpn, int drop) 5266 { 5267 egr_l3_next_hop_entry_t egr_nh; 5268 _bcm_tr3_l2gre_nh_info_t egr_nh_info; 5269 int rv=BCM_E_NONE; 5270 int action_present, action_not_present, tpid_index = -1; 5271 int old_tpid_idx = -1; 5272 uint32 mpath_flag=0; 5273 int vp_nh_ecmp_index=-1; 5274 int ref_count = 0; 5275 5276 5277 egr_nh_info.dvp = vp; 5278 egr_nh_info.entry_type = -1; 5279 egr_nh_info.dvp_is_network = -1; 5280 egr_nh_info.sd_tag_action_present = -1; 5281 egr_nh_info.sd_tag_action_not_present = -1; 5282 egr_nh_info.intf_num = -1; 5283 egr_nh_info.sd_tag_vlan = -1; 5284 egr_nh_info.sd_tag_pri = -1; 5285 egr_nh_info.sd_tag_cfi = -1; 5286 egr_nh_info.tpid_index = -1; 5287 egr_nh_info.is_eline = 0; /* Change to 1 for Eline */ 5288 egr_nh_info.dvp_network_group_id = 0; 5289 5290 /* 5291 * Get egress next-hop index from egress object and 5292 * increment egress object reference count. 5293 */ 5294 rv = bcm_xgs3_get_nh_from_egress_object(unit, l2gre_port->egress_if, 5295 &mpath_flag, 1, &vp_nh_ecmp_index); 5296 BCM_IF_ERROR_RETURN(rv); 5297 5298 /* Read the existing egress next_hop entry */ 5299 if (mpath_flag == 0) { 5300 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 5301 vp_nh_ecmp_index, &egr_nh); 5302 _BCM_L2GRE_CLEANUP(rv) 5303 } 5304 5305 if (l2gre_port->flags & BCM_L2GRE_PORT_EGRESS_TUNNEL) { 5306 5307 /* Program DVP entry - Egress */ 5308 rv = _bcm_tr3_l2gre_egress_dvp_set(unit, vp, drop, l2gre_port); 5309 _BCM_L2GRE_CLEANUP(rv); 5310 5311 5312 /* Program DVP entry - Ingress */ 5313 rv = _bcm_tr3_l2gre_ingress_dvp_set(unit, vp, mpath_flag, vp_nh_ecmp_index, l2gre_port); 5314 _BCM_L2GRE_CLEANUP(rv); 5315 5316 /* Default Split Horizon Group Id 5317 * 0 - For Access Port;1 - For Network Port*/ 5318 if (l2gre_port->flags & BCM_L2GRE_PORT_MULTICAST) { 5319 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 5320 egr_nh_info.dvp_network_group_id = 5321 (_BCM_SWITCH_NETWORK_GROUP_ID_VALID 5322 (unit, l2gre_port->network_group_id)) ? 5323 l2gre_port->network_group_id : 1; 5324 } else { 5325 egr_nh_info.dvp_is_network = 1; /* Enable */ 5326 } 5327 #if defined(BCM_TRIDENT3_SUPPORT) 5328 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, DATA_TYPEf)) { 5329 egr_nh_info.entry_type = 5330 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, DATA_TYPEf); 5331 } else 5332 #endif 5333 { 5334 egr_nh_info.entry_type = 5335 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, ENTRY_TYPEf); 5336 } 5337 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit) ||SOC_IS_TRIDENT3X(unit)) { 5338 rv = _bcm_tr3_l2gre_nexthop_entry_modify(unit, vp_nh_ecmp_index, drop, 5339 &egr_nh_info, _BCM_TD2_L2GRE_EGR_NEXT_HOP_L3MC_VIEW); 5340 } else if (SOC_IS_TRIUMPH3(unit)){ 5341 rv = bcm_tr3_l2gre_egr_nexthop_multicast_set(unit, vp_nh_ecmp_index, vp, l2gre_port); 5342 } 5343 _BCM_L2GRE_CLEANUP(rv); 5344 } 5345 } else { 5346 /* Egress into Access - Non Tunnel */ 5347 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 5348 egr_nh_info.dvp_network_group_id = 5349 (_BCM_SWITCH_NETWORK_GROUP_ID_VALID 5350 (unit, l2gre_port->network_group_id)) ? 5351 l2gre_port->network_group_id : 0; 5352 #if defined(BCM_TRIDENT3_SUPPORT) 5353 if(SOC_IS_TRIDENT3X(unit)) { 5354 rv = _bcm_tr3_l2gre_acc_egress_dvp_set(unit, vp, l2gre_port); 5355 _BCM_L2GRE_CLEANUP(rv); 5356 } 5357 #endif 5358 } else { 5359 egr_nh_info.dvp_is_network = 0; /* Disable */ 5360 } 5361 if (l2gre_port->flags & BCM_L2GRE_PORT_REPLACE) { 5362 action_present = 5363 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 5364 SD_TAG__SD_TAG_ACTION_IF_PRESENTf); 5365 action_not_present = 5366 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 5367 SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf); 5368 if ((action_not_present == 0x1) || (action_present == 0x1)) { 5369 /* If SD tag action is ADD or REPLACE_VID_TPID, the tpid 5370 * index of the entry getting replaced is valid. Save 5371 * the old tpid index to be deleted later. 5372 */ 5373 old_tpid_idx = 5374 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 5375 SD_TAG__SD_TAG_TPID_INDEXf); 5376 } 5377 } 5378 5379 if (l2gre_port->flags & BCM_L2GRE_PORT_SERVICE_TAGGED) { 5380 egr_nh_info.entry_type = _BCM_L2GRE_EGR_NEXT_HOP_SDTAG_VIEW; /* SD_TAG_ACTIONS */ 5381 /* Configure SD_TAG setting */ 5382 rv = _bcm_tr3_l2gre_sd_tag_set(unit, NULL, l2gre_port, &egr_nh_info, NULL, &tpid_index); 5383 _BCM_L2GRE_CLEANUP(rv); 5384 5385 /* Configure EGR Next Hop entry -- SD_TAG view */ 5386 rv = _bcm_tr3_l2gre_nexthop_entry_modify(unit, vp_nh_ecmp_index, drop, 5387 &egr_nh_info, _BCM_L2GRE_EGR_NEXT_HOP_SDTAG_VIEW); 5388 _BCM_L2GRE_CLEANUP(rv); 5389 } 5390 if (!(l2gre_port->flags & BCM_L2GRE_PORT_MULTICAST)) { 5391 /* Program DVP entry with ECMP / Next Hop Index */ 5392 rv = _bcm_tr3_l2gre_ingress_dvp_set(unit, vp, mpath_flag, vp_nh_ecmp_index, l2gre_port); 5393 _BCM_L2GRE_CLEANUP(rv); 5394 } 5395 } 5396 5397 /* Delete old TPID, Nexthop indexes */ 5398 if (old_tpid_idx != -1) { 5399 (void)_bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_idx); 5400 } 5401 return rv; 5402 5403 cleanup: 5404 if (tpid_index != -1) { 5405 (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 5406 } 5407 if (vp_nh_ecmp_index != -1) { 5408 /* Decrement reference count */ 5409 (void) bcm_xgs3_get_ref_count_from_nhi( 5410 unit, mpath_flag, &ref_count, vp_nh_ecmp_index); 5411 } 5412 return rv; 5413 } 5414 5415 /* 5416 * Function: 5417 * _bcm_tr3_l2gre_port_nh_delete 5418 * Purpose: 5419 * Delete L2GRE Next Hop entry 5420 * Parameters: 5421 * Returns: 5422 * BCM_E_XXX 5423 */ 5424 5425 STATIC int 5426 _bcm_tr3_l2gre_port_nh_delete(int unit, bcm_vpn_t vpn, int vp) 5427 { 5428 int rv=BCM_E_NONE; 5429 int nh_ecmp_index=-1; 5430 ing_dvp_table_entry_t dvp; 5431 uint32 vp_type=0; 5432 uint32 flags=0; 5433 int ref_count=0; 5434 int ecmp =-1; 5435 5436 BCM_IF_ERROR_RETURN( 5437 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 5438 5439 vp_type = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, VP_TYPEf); 5440 ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf); 5441 if (ecmp) { 5442 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf); 5443 flags = BCM_L3_MULTIPATH; 5444 /* Decrement reference count */ 5445 BCM_IF_ERROR_RETURN( 5446 bcm_xgs3_get_ref_count_from_nhi(unit, flags, &ref_count, nh_ecmp_index)); 5447 } else { 5448 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 5449 NEXT_HOP_INDEXf); 5450 if(nh_ecmp_index != 0) { 5451 /* Decrement reference count */ 5452 BCM_IF_ERROR_RETURN( 5453 bcm_xgs3_get_ref_count_from_nhi(unit, flags, &ref_count, nh_ecmp_index)); 5454 } 5455 5456 if (ref_count == 1) { 5457 if (nh_ecmp_index) { 5458 BCM_IF_ERROR_RETURN( 5459 bcm_tr3_l2gre_port_egress_nexthop_reset 5460 (unit, nh_ecmp_index, vp_type, vp, vpn)); 5461 } 5462 } 5463 } 5464 return rv; 5465 } 5466 5467 /* 5468 * Function: 5469 * _bcm_tr3_l2gre_port_nh_get 5470 * Purpose: 5471 * Get L2GRE Next Hop entry 5472 * Parameters: 5473 * Returns: 5474 * BCM_E_XXX 5475 */ 5476 5477 STATIC int 5478 _bcm_tr3_l2gre_port_nh_get(int unit, bcm_vpn_t vpn, int vp, bcm_l2gre_port_t *l2gre_port) 5479 { 5480 egr_l3_next_hop_entry_t egr_nh; 5481 ing_dvp_table_entry_t dvp; 5482 int nh_ecmp_index=0; 5483 uint32 ecmp; 5484 int rv = BCM_E_NONE; 5485 5486 /* Read the HW entries */ 5487 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 5488 5489 if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp, VP_TYPEf) == 5490 _BCM_L2GRE_INGRESS_DEST_VP_TYPE) { 5491 /* Egress into L2GRE tunnel, find the tunnel_if */ 5492 l2gre_port->flags |= BCM_L2GRE_PORT_EGRESS_TUNNEL; 5493 BCM_IF_ERROR_RETURN( 5494 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 5495 ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf); 5496 if (ecmp) { 5497 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf); 5498 l2gre_port->egress_if = nh_ecmp_index + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 5499 } else { 5500 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 5501 /* Extract next hop index from unipath egress object. */ 5502 l2gre_port->egress_if = nh_ecmp_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 5503 } 5504 5505 rv = bcm_tr3_l2gre_nexthop_get(unit, nh_ecmp_index, l2gre_port); 5506 BCM_IF_ERROR_RETURN(rv); 5507 5508 } else if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 5509 VP_TYPEf) == _BCM_L2GRE_DEST_VP_TYPE_ACCESS) { 5510 /* Egress into Access-side, find the tunnel_if */ 5511 BCM_IF_ERROR_RETURN( 5512 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 5513 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 5514 /* Extract next hop index from unipath egress object. */ 5515 l2gre_port->egress_if = nh_ecmp_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 5516 5517 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 5518 nh_ecmp_index, &egr_nh)); 5519 if (BCM_SUCCESS(rv)) { 5520 (void) _bcm_tr3_l2gre_sd_tag_get( unit, NULL, l2gre_port, &egr_nh, 5521 NULL, 0); 5522 } 5523 5524 } else { 5525 return BCM_E_NOT_FOUND; 5526 } 5527 5528 return BCM_E_NONE; 5529 } 5530 5531 /* 5532 * Function: 5533 * _bcm_tr3_l2gre_match_vpnid_entry_set 5534 * Purpose: 5535 * Reset L2GRE Match VPNID Entry 5536 * Parameters: 5537 * IN : Unit 5538 * IN : Vpnid 5539 * Returns: 5540 * BCM_E_XXX 5541 */ 5542 5543 int 5544 _bcm_tr3_l2gre_match_vpnid_entry_set(int unit, bcm_l2gre_vpn_config_t *vpn_info) 5545 { 5546 uint32 vpnid = 0; 5547 int rv = BCM_E_NONE; 5548 int vfi_index = -1; 5549 soc_mem_t mmem = MPLS_ENTRYm; 5550 uint32 ment[SOC_MAX_MEM_WORDS]; 5551 soc_mem_t mem; 5552 uint32 vxlate[SOC_MAX_MEM_WORDS]; 5553 5554 if (NULL == vpn_info) { 5555 return BCM_E_PARAM; 5556 } 5557 if (vpn_info->vpnid == 0) { 5558 return BCM_E_PARAM; 5559 } 5560 5561 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_vpn_is_valid(unit, vpn_info->vpn)); 5562 _BCM_L2GRE_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn_info->vpn); 5563 /* Delete old match vpnid entry */ 5564 if (vpn_info->flags & BCM_L2GRE_VPN_REPLACE) { 5565 rv = _bcm_tr3_l2gre_egr_xlate_entry_get(unit, vfi_index, &mem, vxlate); 5566 if (BCM_E_NONE == rv) { 5567 vpnid = soc_mem_field32_get(unit, mem, vxlate, L2GRE_VFI__VPNIDf); 5568 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_match_vpnid_entry_reset(unit, vpnid)); 5569 } else if (BCM_E_NOT_FOUND != rv) { 5570 return rv; 5571 } 5572 } 5573 5574 /* Configure Ingress VPNID */ 5575 sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 5576 #if defined(BCM_TRIDENT3_SUPPORT) 5577 if (soc_feature(unit, soc_feature_base_valid)) { 5578 soc_mem_field32_set(unit, mmem, ment, BASE_VALID_0f, 3); 5579 soc_mem_field32_set(unit, mmem, ment, BASE_VALID_1f, 7); 5580 soc_mem_field32_set(unit, mmem, ment, 5581 DATA_TYPEf, _BCM_L2GRE_KEY_TYPE_VPNID_VFI); 5582 } else 5583 #endif 5584 { 5585 soc_mem_field32_set(unit, mmem, ment, VALIDf, 1); 5586 } 5587 soc_mem_field32_set(unit, mmem, ment, L2GRE_VPNID__VPNIDf, vpn_info->vpnid); 5588 soc_mem_field32_set(unit, mmem, ment, L2GRE_VPNID__VFIf, vfi_index); 5589 soc_mem_field32_set(unit, mmem, ment, KEY_TYPEf, _BCM_L2GRE_KEY_TYPE_VPNID_VFI); 5590 BCM_IF_ERROR_RETURN(soc_mem_insert(unit, mmem, MEM_BLOCK_ALL, ment)); 5591 5592 return BCM_E_NONE; 5593 } 5594 5595 /* 5596 * Function: 5597 * _bcm_tr3_mpls_match_label_entry_reset 5598 * Purpose: 5599 * Reset L2GRE Match VPNID Entry 5600 * Parameters: 5601 * IN : Unit 5602 * IN : Vpnid 5603 * Returns: 5604 * BCM_E_XXX 5605 */ 5606 5607 int 5608 _bcm_tr3_l2gre_match_vpnid_entry_reset(int unit, uint32 vpnid) 5609 { 5610 soc_mem_t mem = MPLS_ENTRYm; 5611 uint32 ment[SOC_MAX_MEM_WORDS]; 5612 5613 sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 5614 5615 #if defined(BCM_TRIDENT3_SUPPORT) 5616 if (soc_feature(unit, soc_feature_base_valid)) { 5617 soc_mem_field32_set(unit, mem, ment, BASE_VALID_0f, 3); 5618 soc_mem_field32_set(unit, mem, ment, BASE_VALID_1f, 7); 5619 soc_mem_field32_set(unit, mem, ment, 5620 DATA_TYPEf, _BCM_L2GRE_KEY_TYPE_VPNID_VFI); 5621 } else 5622 #endif 5623 { 5624 soc_mem_field32_set(unit, mem, ment, VALIDf, 1); 5625 } 5626 soc_mem_field32_set(unit, mem, ment, L2GRE_VPNID__VPNIDf, vpnid); 5627 soc_mem_field32_set(unit, mem, ment, KEY_TYPEf, _BCM_L2GRE_KEY_TYPE_VPNID_VFI); 5628 5629 BCM_IF_ERROR_RETURN(soc_mem_delete(unit, mem, MEM_BLOCK_ALL, ment)); 5630 5631 return BCM_E_NONE; 5632 } 5633 5634 /* 5635 * Function: 5636 * _bcm_tr3_mpls_match_tunnel_entry_set 5637 * Purpose: 5638 * Set L2GRE Match Tunnel Entry 5639 * Parameters: 5640 * IN : Unit 5641 * IN : mpls_entry 5642 * Returns: 5643 * BCM_E_XXX 5644 */ 5645 5646 int 5647 bcm_tr3_l2gre_match_tunnel_entry_set(int unit, int vp, bcm_l2gre_port_t *l2gre_port) 5648 { 5649 int rv = BCM_E_UNAVAIL; 5650 int index; 5651 int tunnel_idx = -1; 5652 uint32 tunnel_sip; 5653 soc_mem_t mem = MPLS_ENTRYm; 5654 uint32 ment[SOC_MAX_MEM_WORDS] = {0}; 5655 uint32 rment[SOC_MAX_MEM_WORDS] = {0}; 5656 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info = L2GRE_INFO(unit); 5657 5658 if (!BCM_GPORT_IS_TUNNEL(l2gre_port->match_tunnel_id)) { 5659 return BCM_E_PARAM; 5660 } 5661 5662 tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(l2gre_port->match_tunnel_id); 5663 tunnel_sip = l2gre_info->l2gre_tunnel_term[tunnel_idx].sip; 5664 l2gre_info->match_key[vp].match_tunnel_index = tunnel_idx; 5665 5666 if (l2gre_port->flags & BCM_L2GRE_PORT_MULTICAST) { 5667 return BCM_E_NONE; 5668 } 5669 5670 #if defined(BCM_TRIDENT3_SUPPORT) 5671 if (soc_feature(unit, soc_feature_base_valid)) { 5672 soc_mem_field32_set(unit, mem, ment, BASE_VALID_0f, 3); 5673 soc_mem_field32_set(unit, mem, ment, BASE_VALID_1f, 7); 5674 soc_mem_field32_set(unit, mem, ment, 5675 DATA_TYPEf, _BCM_L2GRE_KEY_TYPE_TUNNEL); 5676 } else 5677 #endif 5678 { 5679 soc_mem_field32_set(unit, mem, ment, VALIDf, 1); 5680 } 5681 soc_mem_field32_set(unit, mem, ment, L2GRE_SIP__SIPf, tunnel_sip); 5682 soc_mem_field32_set(unit, mem, ment, L2GRE_SIP__SVPf, vp); 5683 soc_mem_field32_set(unit, mem, ment, KEY_TYPEf, _BCM_L2GRE_KEY_TYPE_TUNNEL); 5684 5685 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, ment, &rment, 0); 5686 if (rv == SOC_E_NONE) { 5687 BCM_IF_ERROR_RETURN( 5688 soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, ment)); 5689 } else if (rv != SOC_E_NOT_FOUND) { 5690 return rv; 5691 } else { 5692 BCM_IF_ERROR_RETURN(soc_mem_insert(unit, mem, MEM_BLOCK_ALL, ment)); 5693 } 5694 l2gre_info->match_key[vp].flags = _BCM_L2GRE_PORT_MATCH_TYPE_VPNID; 5695 5696 return BCM_E_NONE; 5697 } 5698 5699 /* 5700 * Function: 5701 * _bcm_tr3_mpls_match_tunnel_entry_reset 5702 * Purpose: 5703 * Reet L2GRE Match Tunnel Entry 5704 * Parameters: 5705 * IN : Unit 5706 * IN : mpls_entry 5707 * Returns: 5708 * BCM_E_XXX 5709 */ 5710 5711 int 5712 bcm_tr3_l2gre_match_tunnel_entry_reset(int unit, int vp) 5713 { 5714 int rv = BCM_E_UNAVAIL; 5715 int index; 5716 int tunnel_idx = -1; 5717 soc_mem_t mem = MPLS_ENTRYm; 5718 uint32 ment[SOC_MAX_MEM_WORDS] = {0}; 5719 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info = L2GRE_INFO(unit); 5720 5721 tunnel_idx = l2gre_info->match_key[vp].match_tunnel_index; 5722 #if defined(BCM_TRIDENT3_SUPPORT) 5723 if (soc_feature(unit, soc_feature_base_valid)) { 5724 soc_mem_field32_set(unit, mem, ment, BASE_VALID_0f, 3); 5725 soc_mem_field32_set(unit, mem, ment, BASE_VALID_1f, 7); 5726 soc_mem_field32_set(unit, mem, ment, 5727 DATA_TYPEf, _BCM_L2GRE_KEY_TYPE_TUNNEL); 5728 } else 5729 #endif 5730 { 5731 soc_mem_field32_set(unit, mem, ment, VALIDf, 1); 5732 } 5733 soc_mem_field32_set(unit, mem, ment, L2GRE_SIP__SIPf, 5734 l2gre_info->l2gre_tunnel_term[tunnel_idx].sip); 5735 soc_mem_field32_set(unit, mem, ment, KEY_TYPEf, _BCM_L2GRE_KEY_TYPE_TUNNEL); 5736 5737 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, ment, ment, 0); 5738 if (BCM_E_NONE == rv) { 5739 sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 5740 BCM_IF_ERROR_RETURN( 5741 soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, ment)); 5742 } else if (BCM_E_NOT_FOUND == rv) { 5743 return BCM_E_NONE; 5744 } else { 5745 return rv; 5746 } 5747 5748 l2gre_info->l2gre_tunnel_term[tunnel_idx].sip = 0; 5749 5750 return BCM_E_NONE; 5751 } 5752 5753 /* 5754 * Function: 5755 * _bcm_tr3_mpls_match_vlan_extd_entry_update 5756 * Purpose: 5757 * Update L2GRE Match Vlan_xlate_extd Entry 5758 * Parameters: 5759 * IN : Unit 5760 * IN : vlan_xlate_extd_entry_t 5761 * OUT : vlan_xlate_extd_entry_t 5762 5763 */ 5764 5765 STATIC int 5766 _bcm_tr3_l2gre_match_vxlate_extd_entry_update(int unit, vlan_xlate_extd_entry_t *vent, 5767 vlan_xlate_extd_entry_t *return_ent) 5768 { 5769 uint32 vp, key_type, value; 5770 5771 /* Check if Key_Type identical */ 5772 key_type = soc_VLAN_XLATE_EXTDm_field32_get (unit, vent, KEY_TYPE_0f); 5773 value = soc_VLAN_XLATE_EXTDm_field32_get (unit, return_ent, KEY_TYPE_0f); 5774 if (key_type != value) { 5775 return BCM_E_PARAM; 5776 } 5777 5778 /* Retain original Keys -- Update data only */ 5779 soc_VLAN_XLATE_EXTDm_field32_set(unit, return_ent, XLATE__MPLS_ACTIONf, 0x1); 5780 soc_VLAN_XLATE_EXTDm_field32_set(unit, return_ent, XLATE__DISABLE_VLAN_CHECKSf, 1); 5781 vp = soc_VLAN_XLATE_EXTDm_field32_get (unit, vent, XLATE__SOURCE_VPf); 5782 soc_VLAN_XLATE_EXTDm_field32_set(unit, return_ent, XLATE__SOURCE_VPf, vp); 5783 5784 return BCM_E_NONE; 5785 } 5786 5787 5788 /* 5789 * Function: 5790 * _bcm_tr3_l2gre_match_vxlate_extd_entry_set 5791 * Purpose: 5792 * Set L2GRE Match Vxlate Entry 5793 * Parameters: 5794 * IN : Unit 5795 * IN : l2gre_port 5796 * IN : vlan_xlate_extd_entry_t 5797 * Returns: 5798 * BCM_E_XXX 5799 */ 5800 5801 STATIC int 5802 _bcm_tr3_l2gre_match_vxlate_extd_entry_set(int unit, bcm_l2gre_port_t *l2gre_port, vlan_xlate_extd_entry_t *vent) 5803 { 5804 vlan_xlate_extd_entry_t return_vent; 5805 int rv = BCM_E_UNAVAIL; 5806 int index; 5807 5808 rv = soc_mem_search(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ANY, &index, 5809 vent, &return_vent, 0); 5810 5811 if (rv == SOC_E_NONE) { 5812 BCM_IF_ERROR_RETURN( 5813 _bcm_tr3_l2gre_match_vxlate_extd_entry_update (unit, vent, &return_vent)); 5814 rv = soc_mem_write(unit, VLAN_XLATE_EXTDm, 5815 MEM_BLOCK_ALL, index, 5816 &return_vent); 5817 } else if (rv != SOC_E_NOT_FOUND) { 5818 return rv; 5819 } else { 5820 if (l2gre_port->flags & BCM_L2GRE_PORT_REPLACE) { 5821 return BCM_E_NOT_FOUND; 5822 } else { 5823 rv = soc_mem_insert(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ALL, vent); 5824 } 5825 } 5826 5827 return rv; 5828 } 5829 5830 /* 5831 * Function: 5832 * bcm_tr3_l2gre_match_clear 5833 * Purpose: 5834 * Clear L2GRE Match Software State 5835 * Parameters: 5836 * unit - (IN) Device Number 5837 * vp - (IN) Source Virtual Port 5838 * Returns: 5839 * void 5840 */ 5841 5842 void 5843 bcm_tr3_l2gre_match_clear (int unit, int vp) 5844 { 5845 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info = L2GRE_INFO(unit); 5846 5847 l2gre_info->match_key[vp].flags = 0; 5848 l2gre_info->match_key[vp].match_vlan = 0; 5849 l2gre_info->match_key[vp].match_inner_vlan = 0; 5850 l2gre_info->match_key[vp].trunk_id = -1; 5851 l2gre_info->match_key[vp].port = 0; 5852 l2gre_info->match_key[vp].modid = -1; 5853 l2gre_info->match_key[vp].match_tunnel_index= 0; 5854 l2gre_info->match_key[vp].match_vpnid = 0; 5855 5856 return; 5857 } 5858 5859 /* 5860 * Function: 5861 * _bcm_tr3_l2gre_trunk_table_set 5862 * Purpose: 5863 * Configure L2GRE Trunk port entry 5864 * Parameters: 5865 * unit - (IN) Device Number 5866 * port - (IN) Trunk member port 5867 * tgid - (IN) Trunk group Id 5868 * vp - (IN) Virtual port 5869 * Returns: 5870 * BCM_E_XXX 5871 */ 5872 5873 STATIC int 5874 _bcm_tr3_l2gre_trunk_table_set(int unit, bcm_port_t port, bcm_trunk_t tgid, int vp) 5875 { 5876 source_trunk_map_table_entry_t trunk_map_entry;/*Trunk table entry buffer.*/ 5877 bcm_module_t my_modid; 5878 int src_trk_idx = -1; 5879 int port_type; 5880 int rv = BCM_E_NONE; 5881 5882 if (tgid != BCM_TRUNK_INVALID) { 5883 port_type = 1; /* TRUNK_PORT_TYPE */ 5884 } else { 5885 return BCM_E_PARAM; 5886 } 5887 5888 /* Get module id for unit. */ 5889 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 5890 5891 /* Get index to source trunk map table */ 5892 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, my_modid, 5893 port, &src_trk_idx)); 5894 5895 soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm); 5896 5897 /* Read source trunk map table. */ 5898 BCM_IF_ERROR_RETURN (soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, 5899 MEM_BLOCK_ANY, src_trk_idx, &trunk_map_entry)); 5900 5901 5902 /* Set trunk group id. */ 5903 if (SOC_IS_TRIDENT3X(unit)) { 5904 soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry, 5905 SRC_TGIDf, tgid); 5906 } else { 5907 soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry, 5908 TGIDf, tgid); 5909 } 5910 5911 /* Set port is part of Trunk group */ 5912 soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry, 5913 PORT_TYPEf, port_type); 5914 5915 /* Enable SVP Mode */ 5916 if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) { 5917 soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry, 5918 SVP_VALIDf, 0x1); 5919 } 5920 5921 /* Set SVP */ 5922 soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry, 5923 SOURCE_VPf, vp); 5924 5925 /* Write entry to hw. */ 5926 rv = soc_mem_write(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ALL, 5927 src_trk_idx, &trunk_map_entry); 5928 5929 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 5930 5931 return rv; 5932 } 5933 5934 5935 /* 5936 * Function: 5937 * _bcm_tr3_l2gre_trunk_table_reset 5938 * Purpose: 5939 * Reset L2GRE Trunk port entry 5940 * Parameters: 5941 * unit - (IN) Device Number 5942 * port - (IN) Trunk member port 5943 * tgid - (IN) Trunk group Id 5944 * Returns: 5945 * BCM_E_XXX 5946 */ 5947 5948 STATIC int 5949 _bcm_tr3_l2gre_trunk_table_reset(int unit, bcm_port_t port, 5950 bcm_trunk_t tgid, 5951 bcm_module_t my_modid) 5952 { 5953 source_trunk_map_table_entry_t trunk_map_entry;/*Trunk table entry buffer.*/ 5954 int src_trk_idx = -1; 5955 int rv = BCM_E_NONE; 5956 int vp; 5957 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info = L2GRE_INFO(unit); 5958 5959 /* Get index to source trunk map table */ 5960 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, my_modid, 5961 port, &src_trk_idx)); 5962 5963 soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm); 5964 5965 /* Read source trunk map table. */ 5966 rv = soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, 5967 MEM_BLOCK_ANY, src_trk_idx, &trunk_map_entry); 5968 if (rv < 0) { 5969 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 5970 return rv; 5971 } 5972 5973 /* Get Source vp from SOURCE_TRUNK_MAP_TABLE table */ 5974 vp = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, 5975 &trunk_map_entry, SOURCE_VPf); 5976 /* 5977 * If this trunk Id is not present in l2gre structure, 5978 * there is no need to reset. 5979 */ 5980 if (l2gre_info->match_key[vp].trunk_id != tgid) { 5981 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 5982 return rv; 5983 } 5984 /* Disable SVP Mode */ 5985 if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) { 5986 soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry, 5987 SVP_VALIDf, 0); 5988 } 5989 5990 /* Set SVP */ 5991 soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry, 5992 SOURCE_VPf, 0); 5993 5994 /* Write entry to hw. */ 5995 rv = soc_mem_write(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ALL, 5996 src_trk_idx, &trunk_map_entry); 5997 5998 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 5999 6000 return rv; 6001 } 6002 /* 6003 * Function: 6004 * bcm_tr3_l2gre_match_trunk_add 6005 * Purpose: 6006 * Assign SVP of L2GRE Trunk port 6007 * Parameters: 6008 * unit - (IN) Device Number 6009 * tgid - (IN) Trunk group Id 6010 * vp - (IN) Source Virtual Port 6011 * Returns: 6012 * BCM_E_XXX 6013 */ 6014 6015 int 6016 bcm_tr3_l2gre_match_trunk_add(int unit, bcm_trunk_t tgid, int vp) 6017 { 6018 int port_idx=0; 6019 int local_port_out[SOC_MAX_NUM_PORTS]; 6020 int local_member_count=0; 6021 int rv = BCM_E_NONE; 6022 bcm_module_t my_modid; 6023 6024 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid, 6025 SOC_MAX_NUM_PORTS, local_port_out, &local_member_count)); 6026 for (port_idx = 0; port_idx < local_member_count; port_idx++) { 6027 rv = _bcm_tr3_l2gre_trunk_table_set(unit, local_port_out[port_idx], tgid, vp); 6028 if (BCM_FAILURE(rv)) { 6029 goto trunk_cleanup; 6030 } 6031 rv = _bcm_esw_port_tab_set( 6032 unit, local_port_out[port_idx], 6033 _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0x1); /* L2_SVP */ 6034 if (BCM_FAILURE(rv)) { 6035 goto trunk_cleanup; 6036 } 6037 } 6038 6039 return BCM_E_NONE; 6040 6041 trunk_cleanup: 6042 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 6043 for (;port_idx >= 0; port_idx--) { 6044 (void)_bcm_esw_port_tab_set(unit, local_port_out[port_idx], 6045 _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0x0); 6046 (void) _bcm_tr3_l2gre_trunk_table_reset(unit, 6047 local_port_out[port_idx], tgid, 6048 my_modid); 6049 } 6050 return rv; 6051 } 6052 6053 /* 6054 * Function: 6055 * bcm_tr3_l2gre_match_trunk_delete 6056 * Purpose: 6057 * Remove SVP of L2GRE Trunk port 6058 * Parameters: 6059 * unit - (IN) Device Number 6060 * tgid - (IN) Trunk group Id 6061 * vp - (IN) Source Virtual Port 6062 * Returns: 6063 * BCM_E_XXX 6064 */ 6065 6066 int 6067 bcm_tr3_l2gre_match_trunk_delete(int unit, bcm_trunk_t tgid, int vp) 6068 { 6069 int port_idx=0; 6070 int local_port_out[SOC_MAX_NUM_PORTS]; 6071 int local_member_count=0; 6072 int rv = BCM_E_NONE; 6073 bcm_module_t my_modid; 6074 6075 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid, 6076 SOC_MAX_NUM_PORTS, local_port_out, &local_member_count)); 6077 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 6078 6079 for (port_idx = 0; port_idx < local_member_count; port_idx++) { 6080 rv = _bcm_tr3_l2gre_trunk_table_reset(unit, 6081 local_port_out[port_idx], tgid, 6082 my_modid); 6083 if (BCM_FAILURE(rv)) { 6084 goto trunk_cleanup; 6085 } 6086 rv = _bcm_esw_port_tab_set( 6087 unit, local_port_out[port_idx], 6088 _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0x0); 6089 if (BCM_FAILURE(rv)) { 6090 goto trunk_cleanup; 6091 } 6092 } 6093 6094 return BCM_E_NONE; 6095 6096 trunk_cleanup: 6097 for (;port_idx >= 0; port_idx--) { 6098 (void)_bcm_esw_port_tab_set(unit, local_port_out[port_idx], 6099 _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0x1);/* L2_SVP */ 6100 (void) _bcm_tr3_l2gre_trunk_table_set(unit, local_port_out[port_idx], tgid, vp); 6101 } 6102 return rv; 6103 } 6104 6105 /* 6106 * Function: 6107 * bcm_tr3_l2gre_match_add 6108 * Purpose: 6109 * Assign match criteria of an L2GRE port 6110 * Parameters: 6111 * unit - (IN) Device Number 6112 * l2gre_port - (IN) l2gre port information 6113 * vp - (IN) Source Virtual Port 6114 * Returns: 6115 * BCM_E_XXX 6116 */ 6117 6118 int 6119 bcm_tr3_l2gre_match_add(int unit, bcm_l2gre_port_t *l2gre_port, int vp, bcm_vpn_t vpn) 6120 { 6121 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info = L2GRE_INFO(unit); 6122 int rv = BCM_E_NONE; 6123 bcm_module_t mod_out = -1; 6124 bcm_port_t port_out = -1; 6125 bcm_trunk_t trunk_id = -1; 6126 vlan_xlate_extd_entry_t vent; 6127 int mod_id_idx=0; /* Module Id */ 6128 int src_trk_idx=0; /*Source Trunk table index.*/ 6129 int gport_id=-1; 6130 6131 rv = _bcm_tr3_l2gre_port_resolve(unit, l2gre_port->l2gre_port_id, -1, &mod_out, 6132 &port_out, &trunk_id, &gport_id); 6133 BCM_IF_ERROR_RETURN(rv); 6134 6135 sal_memset(&vent, 0, sizeof(vlan_xlate_extd_entry_t)); 6136 6137 /* Get module id for unit. */ 6138 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &mod_id_idx)); 6139 6140 if (l2gre_port->criteria == BCM_L2GRE_PORT_MATCH_PORT_VLAN ) { 6141 6142 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 6143 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 6144 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MPLS_ACTIONf, 0x1); /* SVP */ 6145 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__DISABLE_VLAN_CHECKSf, 1); 6146 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__SOURCE_VPf, vp); 6147 if (!BCM_VLAN_VALID(l2gre_port->match_vlan)) { 6148 return BCM_E_PARAM; 6149 } 6150 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 6151 TR3_VLXLT_X_HASH_KEY_TYPE_OVID); 6152 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 6153 TR3_VLXLT_X_HASH_KEY_TYPE_OVID); 6154 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__OVIDf, 6155 l2gre_port->match_vlan); 6156 l2gre_info->match_key[vp].flags = _BCM_L2GRE_PORT_MATCH_TYPE_VLAN; 6157 l2gre_info->match_key[vp].match_vlan = l2gre_port->match_vlan; 6158 6159 if (BCM_GPORT_IS_TRUNK(l2gre_port->match_port)) { 6160 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 6161 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, trunk_id); 6162 l2gre_info->match_key[vp].trunk_id = trunk_id; 6163 } else { 6164 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, mod_out); 6165 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, port_out); 6166 l2gre_info->match_key[vp].port = port_out; 6167 l2gre_info->match_key[vp].modid = mod_out; 6168 } 6169 rv = _bcm_tr3_l2gre_match_vxlate_extd_entry_set(unit, l2gre_port, &vent); 6170 BCM_IF_ERROR_RETURN(rv); 6171 if (!(l2gre_port->flags & BCM_L2GRE_PORT_REPLACE)) { 6172 bcm_tr3_l2gre_port_match_count_adjust(unit, vp, 1); 6173 } 6174 } else if (l2gre_port->criteria == 6175 BCM_L2GRE_PORT_MATCH_PORT_INNER_VLAN) { 6176 6177 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 6178 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 6179 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MPLS_ACTIONf, 0x1); /* SVP */ 6180 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__DISABLE_VLAN_CHECKSf, 1); 6181 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__SOURCE_VPf, vp); 6182 if (!BCM_VLAN_VALID(l2gre_port->match_inner_vlan)) { 6183 return BCM_E_PARAM; 6184 } 6185 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 6186 TR3_VLXLT_X_HASH_KEY_TYPE_IVID); 6187 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 6188 TR3_VLXLT_X_HASH_KEY_TYPE_IVID); 6189 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__IVIDf, 6190 l2gre_port->match_inner_vlan); 6191 l2gre_info->match_key[vp].flags = _BCM_L2GRE_PORT_MATCH_TYPE_INNER_VLAN; 6192 l2gre_info->match_key[vp].match_inner_vlan = l2gre_port->match_inner_vlan; 6193 6194 if (BCM_GPORT_IS_TRUNK(l2gre_port->match_port)) { 6195 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 6196 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, trunk_id); 6197 l2gre_info->match_key[vp].trunk_id = trunk_id; 6198 } else { 6199 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, mod_out); 6200 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, port_out); 6201 l2gre_info->match_key[vp].port = port_out; 6202 l2gre_info->match_key[vp].modid = mod_out; 6203 } 6204 rv = _bcm_tr3_l2gre_match_vxlate_extd_entry_set(unit, l2gre_port, &vent); 6205 BCM_IF_ERROR_RETURN(rv); 6206 if (!(l2gre_port->flags & BCM_L2GRE_PORT_REPLACE)) { 6207 bcm_tr3_l2gre_port_match_count_adjust(unit, vp, 1); 6208 } 6209 } else if (l2gre_port->criteria == 6210 BCM_L2GRE_PORT_MATCH_PORT_VLAN_STACKED) { 6211 6212 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 6213 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 6214 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MPLS_ACTIONf, 0x1); /* SVP */ 6215 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__DISABLE_VLAN_CHECKSf, 1); 6216 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__SOURCE_VPf, vp); 6217 if (!BCM_VLAN_VALID(l2gre_port->match_vlan) || 6218 !BCM_VLAN_VALID(l2gre_port->match_inner_vlan)) { 6219 return BCM_E_PARAM; 6220 } 6221 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 6222 TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID); 6223 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 6224 TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID); 6225 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__OVIDf, 6226 l2gre_port->match_vlan); 6227 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__IVIDf, 6228 l2gre_port->match_inner_vlan); 6229 l2gre_info->match_key[vp].flags = _BCM_L2GRE_PORT_MATCH_TYPE_VLAN_STACKED; 6230 l2gre_info->match_key[vp].match_vlan = l2gre_port->match_vlan; 6231 l2gre_info->match_key[vp].match_inner_vlan = l2gre_port->match_inner_vlan; 6232 if (BCM_GPORT_IS_TRUNK(l2gre_port->match_port)) { 6233 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 6234 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, trunk_id); 6235 l2gre_info->match_key[vp].trunk_id = trunk_id; 6236 } else { 6237 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, mod_out); 6238 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, port_out); 6239 l2gre_info->match_key[vp].port = port_out; 6240 l2gre_info->match_key[vp].modid = mod_out; 6241 } 6242 rv = _bcm_tr3_l2gre_match_vxlate_extd_entry_set(unit, l2gre_port, &vent); 6243 BCM_IF_ERROR_RETURN(rv); 6244 if (!(l2gre_port->flags & BCM_L2GRE_PORT_REPLACE)) { 6245 bcm_tr3_l2gre_port_match_count_adjust(unit, vp, 1); 6246 } 6247 } else if (l2gre_port->criteria == 6248 BCM_L2GRE_PORT_MATCH_VLAN_PRI) { 6249 6250 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 6251 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 6252 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MPLS_ACTIONf, 0x1); /* SVP */ 6253 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__DISABLE_VLAN_CHECKSf, 1); 6254 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__SOURCE_VPf, vp); 6255 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 6256 TR3_VLXLT_X_HASH_KEY_TYPE_PRI_CFI); 6257 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 6258 TR3_VLXLT_X_HASH_KEY_TYPE_PRI_CFI); 6259 /* match_vlan : Bits 12-15 contains VLAN_PRI + CFI, vlan=BCM_E_NONE */ 6260 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, OTAGf, 6261 l2gre_port->match_vlan); 6262 l2gre_info->match_key[vp].flags = _BCM_L2GRE_PORT_MATCH_TYPE_VLAN_PRI; 6263 l2gre_info->match_key[vp].match_vlan = l2gre_port->match_vlan; 6264 6265 if (BCM_GPORT_IS_TRUNK(l2gre_port->match_port)) { 6266 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 6267 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, trunk_id); 6268 l2gre_info->match_key[vp].trunk_id = trunk_id; 6269 } else { 6270 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, mod_out); 6271 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, port_out); 6272 l2gre_info->match_key[vp].port = port_out; 6273 l2gre_info->match_key[vp].modid = mod_out; 6274 } 6275 rv = _bcm_tr3_l2gre_match_vxlate_extd_entry_set(unit, l2gre_port, &vent); 6276 BCM_IF_ERROR_RETURN(rv); 6277 if (!(l2gre_port->flags & BCM_L2GRE_PORT_REPLACE)) { 6278 bcm_tr3_l2gre_port_match_count_adjust(unit, vp, 1); 6279 } 6280 }else if (l2gre_port->criteria == BCM_L2GRE_PORT_MATCH_PORT) { 6281 if (BCM_GPORT_IS_TRUNK(l2gre_port->match_port)) { 6282 rv = bcm_tr3_l2gre_match_trunk_add(unit, trunk_id, vp); 6283 if (rv >= 0) { 6284 l2gre_info->match_key[vp].flags = _BCM_L2GRE_PORT_MATCH_TYPE_TRUNK; 6285 l2gre_info->match_key[vp].trunk_id = trunk_id; 6286 } 6287 BCM_IF_ERROR_RETURN(rv); 6288 } else { 6289 int is_local; 6290 6291 BCM_IF_ERROR_RETURN 6292 ( _bcm_esw_modid_is_local(unit, mod_out, &is_local)); 6293 6294 /* Get index to source trunk map table */ 6295 BCM_IF_ERROR_RETURN( 6296 _bcm_esw_src_mod_port_table_index_get(unit, mod_out, 6297 port_out, &src_trk_idx)); 6298 6299 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 6300 src_trk_idx, SOURCE_VPf, vp); 6301 BCM_IF_ERROR_RETURN(rv); 6302 6303 if (is_local) { 6304 rv = soc_mem_field32_modify(unit, PORT_TABm, port_out, 6305 PORT_OPERATIONf, 0x1); /* L2_SVP */ 6306 BCM_IF_ERROR_RETURN(rv); 6307 6308 /* Set TAG_ACTION_PROFILE_PTR */ 6309 rv = bcm_tr3_l2gre_port_untagged_profile_set(unit, port_out); 6310 BCM_IF_ERROR_RETURN(rv); 6311 } 6312 6313 l2gre_info->match_key[vp].flags = _BCM_L2GRE_PORT_MATCH_TYPE_PORT; 6314 l2gre_info->match_key[vp].index = src_trk_idx; 6315 } 6316 }else if (l2gre_port->criteria == BCM_L2GRE_PORT_MATCH_VPNID) { 6317 BCM_IF_ERROR_RETURN( 6318 bcm_tr3_l2gre_match_tunnel_entry_set(unit, vp, l2gre_port)); 6319 } 6320 6321 return rv; 6322 } 6323 6324 /* 6325 * Function: 6326 * bcm_tr3_l2gre_match_delete 6327 * Purpose: 6328 * Delete match criteria of an L2GRE port 6329 * Parameters: 6330 * unit - (IN) Device Number 6331 * l2gre_port - (IN) L2GRE port information 6332 * vp - (IN) Source Virtual Port 6333 * Returns: 6334 * BCM_E_XXX 6335 */ 6336 6337 int 6338 bcm_tr3_l2gre_match_delete(int unit, int vp) 6339 { 6340 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info = L2GRE_INFO(unit); 6341 int rv=BCM_E_NONE; 6342 vlan_xlate_extd_entry_t vent; 6343 bcm_trunk_t trunk_id; 6344 int src_trk_idx=0; /*Source Trunk table index.*/ 6345 int mod_id_idx=0; /* Module_Id */ 6346 int port=0; 6347 6348 sal_memset(&vent, 0, sizeof(vlan_xlate_extd_entry_t)); 6349 6350 /* Get module id for unit. */ 6351 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &mod_id_idx)); 6352 6353 if (l2gre_info->match_key[vp].flags == _BCM_L2GRE_PORT_MATCH_TYPE_VLAN) { 6354 6355 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 6356 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 6357 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 6358 TR3_VLXLT_X_HASH_KEY_TYPE_OVID); 6359 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 6360 TR3_VLXLT_X_HASH_KEY_TYPE_OVID); 6361 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__OVIDf, 6362 l2gre_info->match_key[vp].match_vlan); 6363 if (l2gre_info->match_key[vp].modid != -1) { 6364 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, 6365 l2gre_info->match_key[vp].modid); 6366 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, 6367 l2gre_info->match_key[vp].port); 6368 } else { 6369 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 6370 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, 6371 l2gre_info->match_key[vp].trunk_id); 6372 } 6373 rv = soc_mem_delete(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ANY, &vent); 6374 BCM_IF_ERROR_RETURN(rv); 6375 6376 (void) bcm_tr3_l2gre_match_clear (unit, vp); 6377 bcm_tr3_l2gre_port_match_count_adjust(unit, vp, -1); 6378 6379 } else if (l2gre_info->match_key[vp].flags == 6380 _BCM_L2GRE_PORT_MATCH_TYPE_INNER_VLAN) { 6381 6382 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 6383 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 6384 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 6385 TR3_VLXLT_X_HASH_KEY_TYPE_IVID); 6386 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 6387 TR3_VLXLT_X_HASH_KEY_TYPE_IVID); 6388 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__IVIDf, 6389 l2gre_info->match_key[vp].match_inner_vlan); 6390 if (l2gre_info->match_key[vp].modid != -1) { 6391 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, 6392 l2gre_info->match_key[vp].modid); 6393 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, 6394 l2gre_info->match_key[vp].port); 6395 } else { 6396 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 6397 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, 6398 l2gre_info->match_key[vp].trunk_id); 6399 } 6400 rv = soc_mem_delete(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ANY, &vent); 6401 BCM_IF_ERROR_RETURN(rv); 6402 6403 (void) bcm_tr3_l2gre_match_clear (unit, vp); 6404 bcm_tr3_l2gre_port_match_count_adjust(unit, vp, -1); 6405 }else if (l2gre_info->match_key[vp].flags == 6406 _BCM_L2GRE_PORT_MATCH_TYPE_VLAN_STACKED) { 6407 6408 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 6409 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 6410 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 6411 TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID); 6412 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 6413 TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID); 6414 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__OVIDf, 6415 l2gre_info->match_key[vp].match_vlan); 6416 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__IVIDf, 6417 l2gre_info->match_key[vp].match_inner_vlan); 6418 if (l2gre_info->match_key[vp].modid != -1) { 6419 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, 6420 l2gre_info->match_key[vp].modid); 6421 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, 6422 l2gre_info->match_key[vp].port); 6423 } else { 6424 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 6425 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, 6426 l2gre_info->match_key[vp].trunk_id); 6427 } 6428 rv = soc_mem_delete(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ANY, &vent); 6429 BCM_IF_ERROR_RETURN(rv); 6430 6431 (void) bcm_tr3_l2gre_match_clear (unit, vp); 6432 bcm_tr3_l2gre_port_match_count_adjust(unit, vp, -1); 6433 6434 } else if (l2gre_info->match_key[vp].flags == 6435 _BCM_L2GRE_PORT_MATCH_TYPE_VLAN_PRI) { 6436 6437 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_0f, 1); 6438 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, VALID_1f, 1); 6439 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_0f, 6440 TR3_VLXLT_X_HASH_KEY_TYPE_PRI_CFI); 6441 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, KEY_TYPE_1f, 6442 TR3_VLXLT_X_HASH_KEY_TYPE_PRI_CFI); 6443 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__OTAGf, 6444 l2gre_info->match_key[vp].match_vlan); 6445 if (l2gre_info->match_key[vp].modid != -1) { 6446 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__MODULE_IDf, 6447 l2gre_info->match_key[vp].modid); 6448 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__PORT_NUMf, 6449 l2gre_info->match_key[vp].port); 6450 } else { 6451 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__Tf, 1); 6452 soc_VLAN_XLATE_EXTDm_field32_set(unit, &vent, XLATE__TGIDf, 6453 l2gre_info->match_key[vp].trunk_id); 6454 } 6455 rv = soc_mem_delete(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ANY, &vent); 6456 BCM_IF_ERROR_RETURN(rv); 6457 6458 (void) bcm_tr3_l2gre_match_clear (unit, vp); 6459 bcm_tr3_l2gre_port_match_count_adjust(unit, vp, -1); 6460 }else if (l2gre_info->match_key[vp].flags == 6461 _BCM_L2GRE_PORT_MATCH_TYPE_PORT) { 6462 int is_local; 6463 6464 src_trk_idx = l2gre_info->match_key[vp].index; 6465 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 6466 src_trk_idx, SOURCE_VPf, 0); 6467 BCM_IF_ERROR_RETURN(rv); 6468 6469 BCM_IF_ERROR_RETURN(_bcm_esw_src_modid_port_get( unit, src_trk_idx, 6470 &mod_id_idx, &port)); 6471 BCM_IF_ERROR_RETURN 6472 ( _bcm_esw_modid_is_local(unit, mod_id_idx, &is_local)); 6473 6474 if (is_local) { 6475 /* Convert system ports to physical ports */ 6476 if (soc_feature(unit, soc_feature_sysport_remap)) { 6477 BCM_XLATE_SYSPORT_S2P(unit, &port); 6478 } 6479 6480 rv = soc_mem_field32_modify(unit, PORT_TABm, port, 6481 PORT_OPERATIONf, 0x0); /* NORMAL */ 6482 BCM_IF_ERROR_RETURN(rv); 6483 6484 /* Reset TAG_ACTION_PROFILE_PTR */ 6485 rv = bcm_tr3_l2gre_port_untagged_profile_reset(unit, port); 6486 BCM_IF_ERROR_RETURN(rv); 6487 } 6488 (void) bcm_tr3_l2gre_match_clear (unit, vp); 6489 } else if (l2gre_info->match_key[vp].flags == 6490 _BCM_L2GRE_PORT_MATCH_TYPE_TRUNK) { 6491 trunk_id = l2gre_info->match_key[vp].trunk_id; 6492 rv = bcm_tr3_l2gre_match_trunk_delete(unit, trunk_id, vp); 6493 BCM_IF_ERROR_RETURN(rv); 6494 6495 (void) bcm_tr3_l2gre_match_clear (unit, vp); 6496 } else if (l2gre_info->match_key[vp].flags == 6497 _BCM_L2GRE_PORT_MATCH_TYPE_VPNID) { 6498 rv = bcm_tr3_l2gre_match_tunnel_entry_reset(unit, vp); 6499 } 6500 return rv; 6501 } 6502 6503 /* 6504 * Function: 6505 * bcm_tr3_l2gre_match_get 6506 * Purpose: 6507 * Obtain match information of an L2GRE port 6508 * Parameters: 6509 * unit - (IN) Device Number 6510 * l2gre_port - (OUT) L2GRE port information 6511 * vp - (IN) Source Virtual Port 6512 * Returns: 6513 * BCM_E_XXX 6514 */ 6515 6516 int 6517 bcm_tr3_l2gre_match_get(int unit, bcm_l2gre_port_t *l2gre_port, int vp) 6518 { 6519 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info = L2GRE_INFO(unit); 6520 int rv = BCM_E_NONE; 6521 bcm_module_t mod_in=0, mod_out; 6522 bcm_port_t port_in=0, port_out; 6523 bcm_trunk_t trunk_id=0; 6524 int src_trk_idx=0; /*Source Trunk table index.*/ 6525 int tunnel_idx = -1; 6526 int mode_in=0; /* Module_Id */ 6527 6528 /* Get module id for unit. */ 6529 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &mode_in)); 6530 6531 if (l2gre_info->match_key[vp].flags & _BCM_L2GRE_PORT_MATCH_TYPE_VLAN) { 6532 6533 l2gre_port->criteria = BCM_L2GRE_PORT_MATCH_PORT_VLAN; 6534 l2gre_port->match_vlan = l2gre_info->match_key[vp].match_vlan; 6535 6536 if (l2gre_info->match_key[vp].trunk_id != -1) { 6537 trunk_id = l2gre_info->match_key[vp].trunk_id; 6538 BCM_GPORT_TRUNK_SET(l2gre_port->match_port, trunk_id); 6539 } else { 6540 port_in = l2gre_info->match_key[vp].port; 6541 mod_in = l2gre_info->match_key[vp].modid; 6542 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 6543 mod_in, port_in, &mod_out, &port_out); 6544 BCM_GPORT_MODPORT_SET(l2gre_port->match_port, mod_out, port_out); 6545 } 6546 } else if (l2gre_info->match_key[vp].flags & 6547 _BCM_L2GRE_PORT_MATCH_TYPE_INNER_VLAN) { 6548 l2gre_port->criteria = BCM_L2GRE_PORT_MATCH_PORT_INNER_VLAN; 6549 l2gre_port->match_inner_vlan = l2gre_info->match_key[vp].match_inner_vlan; 6550 6551 if (l2gre_info->match_key[vp].trunk_id != -1) { 6552 trunk_id = l2gre_info->match_key[vp].trunk_id; 6553 BCM_GPORT_TRUNK_SET(l2gre_port->match_port, trunk_id); 6554 } else { 6555 port_in = l2gre_info->match_key[vp].port; 6556 mod_in = l2gre_info->match_key[vp].modid; 6557 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 6558 mod_in, port_in, &mod_out, &port_out); 6559 BCM_GPORT_MODPORT_SET(l2gre_port->match_port, mod_out, port_out); 6560 } 6561 }else if (l2gre_info->match_key[vp].flags & 6562 _BCM_L2GRE_PORT_MATCH_TYPE_VLAN_STACKED) { 6563 6564 l2gre_port->criteria = BCM_L2GRE_PORT_MATCH_PORT_VLAN_STACKED; 6565 l2gre_port->match_vlan = l2gre_info->match_key[vp].match_vlan; 6566 l2gre_port->match_inner_vlan = l2gre_info->match_key[vp].match_inner_vlan; 6567 6568 if (l2gre_info->match_key[vp].trunk_id != -1) { 6569 trunk_id = l2gre_info->match_key[vp].trunk_id; 6570 BCM_GPORT_TRUNK_SET(l2gre_port->match_port, trunk_id); 6571 } else { 6572 port_in = l2gre_info->match_key[vp].port; 6573 mod_in = l2gre_info->match_key[vp].modid; 6574 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 6575 mod_in, port_in, &mod_out, &port_out); 6576 BCM_GPORT_MODPORT_SET(l2gre_port->match_port, mod_out, port_out); 6577 } 6578 } else if (l2gre_info->match_key[vp].flags & _BCM_L2GRE_PORT_MATCH_TYPE_VLAN_PRI) { 6579 6580 l2gre_port->criteria = BCM_L2GRE_PORT_MATCH_VLAN_PRI; 6581 l2gre_port->match_vlan = l2gre_info->match_key[vp].match_vlan; 6582 6583 if (l2gre_info->match_key[vp].trunk_id != -1) { 6584 trunk_id = l2gre_info->match_key[vp].trunk_id; 6585 BCM_GPORT_TRUNK_SET(l2gre_port->match_port, trunk_id); 6586 } else { 6587 port_in = l2gre_info->match_key[vp].port; 6588 mod_in = l2gre_info->match_key[vp].modid; 6589 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 6590 mod_in, port_in, &mod_out, &port_out); 6591 BCM_GPORT_MODPORT_SET(l2gre_port->match_port, mod_out, port_out); 6592 } 6593 } else if (l2gre_info->match_key[vp].flags & 6594 _BCM_L2GRE_PORT_MATCH_TYPE_PORT) { 6595 6596 src_trk_idx = l2gre_info->match_key[vp].index; 6597 BCM_IF_ERROR_RETURN(_bcm_esw_src_modid_port_get( unit, src_trk_idx, 6598 &mod_in, &port_in)); 6599 6600 l2gre_port->criteria = BCM_L2GRE_PORT_MATCH_PORT; 6601 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 6602 mod_in, port_in, &mod_out, &port_out); 6603 BCM_GPORT_MODPORT_SET(l2gre_port->match_port, mod_out, port_out); 6604 }else if (l2gre_info->match_key[vp].flags & 6605 _BCM_L2GRE_PORT_MATCH_TYPE_TRUNK) { 6606 6607 trunk_id = l2gre_info->match_key[vp].trunk_id; 6608 l2gre_port->criteria = BCM_L2GRE_PORT_MATCH_PORT; 6609 BCM_GPORT_TRUNK_SET(l2gre_port->match_port, trunk_id); 6610 } else if ((l2gre_info->match_key[vp].flags & 6611 _BCM_L2GRE_PORT_MATCH_TYPE_VPNID)) { 6612 l2gre_port->criteria = BCM_L2GRE_PORT_MATCH_VPNID; 6613 6614 tunnel_idx = l2gre_info->match_key[vp].match_tunnel_index; 6615 BCM_GPORT_TUNNEL_ID_SET(l2gre_port->match_tunnel_id, tunnel_idx); 6616 6617 } else { 6618 l2gre_port->criteria = BCM_L2GRE_PORT_MATCH_NONE; 6619 } 6620 return rv; 6621 } 6622 6623 /* 6624 * Function: 6625 * _bcm_tr3_l2gre_eline_vp_map_set 6626 * Purpose: 6627 * Set L2GRE ELINE ports from VPN 6628 * Parameters: 6629 * unit - (IN) Device Number 6630 * vpn - (IN) VPN instance ID 6631 * Returns: 6632 * BCM_E_XXX 6633 */ 6634 STATIC int 6635 _bcm_tr3_l2gre_eline_vp_map_set(int unit, int vfi_index, int vp1, int vp2) 6636 { 6637 vfi_entry_t vfi_entry; 6638 int rv=BCM_E_NONE; 6639 int num_vp; 6640 6641 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeL2Gre)) { 6642 return BCM_E_NOT_FOUND; 6643 } 6644 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 6645 6646 BCM_IF_ERROR_RETURN 6647 (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry)); 6648 6649 if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) { 6650 if ((vp1 > 0) && (vp1 < num_vp)) { 6651 soc_VFIm_field32_set(unit, &vfi_entry, VP_0f, vp1); 6652 } else { 6653 return BCM_E_PARAM; 6654 } 6655 if ((vp2 > 0) && (vp2 < num_vp)) { 6656 soc_VFIm_field32_set(unit, &vfi_entry, VP_1f, vp2); 6657 } else { 6658 return BCM_E_PARAM; 6659 } 6660 } else { 6661 /* ELAN */ 6662 return BCM_E_PARAM; 6663 } 6664 6665 rv = WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry); 6666 return rv; 6667 } 6668 6669 /* 6670 * Function: 6671 * _bcm_tr3_l2gre_eline_vp_map_get 6672 * Purpose: 6673 * Get L2GRE ELINE ports from VPN 6674 * Parameters: 6675 * unit - (IN) Device Number 6676 * vpn - (IN) VPN instance ID 6677 * Returns: 6678 * BCM_E_XXX 6679 */ 6680 6681 STATIC int 6682 _bcm_tr3_l2gre_eline_vp_map_get(int unit, int vfi_index, int *vp1, int *vp2) 6683 { 6684 vfi_entry_t vfi_entry; 6685 6686 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeL2Gre)) { 6687 return BCM_E_NOT_FOUND; 6688 } 6689 6690 BCM_IF_ERROR_RETURN 6691 (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry)); 6692 6693 if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) { 6694 *vp1 = soc_VFIm_field32_get(unit, &vfi_entry, VP_0f); 6695 *vp2 = soc_VFIm_field32_get(unit, &vfi_entry, VP_1f); 6696 return BCM_E_NONE; 6697 } else { 6698 return BCM_E_PARAM; 6699 } 6700 } 6701 6702 /* 6703 * Function: 6704 * _bcm_tr3_l2gre_eline_vp_map_clear 6705 * Purpose: 6706 * Clear L2GRE ELINE ports from VPN 6707 * Parameters: 6708 * unit - (IN) Device Number 6709 * vpn - (IN) VPN instance ID 6710 * Returns: 6711 * BCM_E_XXX 6712 */ 6713 6714 STATIC int 6715 _bcm_tr3_l2gre_eline_vp_map_clear(int unit, int vfi_index, int vp1, int vp2) 6716 { 6717 vfi_entry_t vfi_entry; 6718 int rv=BCM_E_NONE; 6719 int num_vp; 6720 6721 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeL2Gre)) { 6722 return BCM_E_NOT_FOUND; 6723 } 6724 6725 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 6726 6727 BCM_IF_ERROR_RETURN 6728 (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry)); 6729 6730 if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) { 6731 if ((vp1 > 0) && (vp1 < num_vp)) { 6732 soc_VFIm_field32_set(unit, &vfi_entry, VP_0f, 0); 6733 } else if ((vp2 > 0) && (vp2 < num_vp)) { 6734 soc_VFIm_field32_set(unit, &vfi_entry, VP_1f, 0); 6735 } else { 6736 return BCM_E_PARAM; 6737 } 6738 } else { 6739 /* ELAN */ 6740 return BCM_E_PARAM; 6741 } 6742 rv = WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry); 6743 return rv; 6744 } 6745 6746 /* 6747 * Function: 6748 * _bcm_tr3_l2gre_eline_vp_configure 6749 * Purpose: 6750 * Configure L2GRE ELINE virtual port 6751 * Parameters: 6752 * unit - (IN) Device Number 6753 * vpn - (IN) VPN instance ID 6754 * Returns: 6755 * BCM_E_XXX 6756 */ 6757 6758 int 6759 _bcm_tr3_l2gre_eline_vp_configure (int unit, int vfi_index, int active_vp, 6760 source_vp_entry_t *svp, int tpid_enable, bcm_l2gre_port_t *l2gre_port) 6761 { 6762 int rv = BCM_E_NONE; 6763 int network_group=0; 6764 6765 /* Set SOURCE_VP */ 6766 soc_SOURCE_VPm_field32_set(unit, svp, CLASS_IDf, 6767 l2gre_port->if_class); 6768 /* Default Split Horizon Group Id 6769 * 0 - For Access Port;1 - For Network Port*/ 6770 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 6771 if (l2gre_port->flags & BCM_L2GRE_PORT_NETWORK) { 6772 network_group = l2gre_port->network_group_id; 6773 rv = _bcm_validate_splithorizon_network_group(unit, 6774 l2gre_port->flags & BCM_L2GRE_PORT_NETWORK, &network_group); 6775 BCM_IF_ERROR_RETURN(rv); 6776 soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_GROUPf, 6777 network_group); 6778 } else { 6779 network_group = l2gre_port->network_group_id; 6780 rv = _bcm_validate_splithorizon_network_group(unit, 6781 l2gre_port->flags & BCM_L2GRE_PORT_NETWORK, &network_group); 6782 BCM_IF_ERROR_RETURN(rv); 6783 soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_GROUPf, 6784 network_group); 6785 } 6786 } else { 6787 soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_PORTf, 6788 (l2gre_port->flags & BCM_L2GRE_PORT_NETWORK) ? 1 : 0); 6789 } 6790 if (l2gre_port->flags & BCM_L2GRE_PORT_SERVICE_TAGGED) { 6791 soc_SOURCE_VPm_field32_set(unit, svp, SD_TAG_MODEf, 1); 6792 soc_SOURCE_VPm_field32_set(unit, svp, TPID_ENABLEf, tpid_enable); 6793 } else { 6794 soc_SOURCE_VPm_field32_set(unit, svp, SD_TAG_MODEf, 0); 6795 } 6796 6797 soc_SOURCE_VPm_field32_set(unit, svp, DISABLE_VLAN_CHECKSf, 1); 6798 soc_SOURCE_VPm_field32_set(unit, svp, 6799 ENTRY_TYPEf, _BCM_L2GRE_SOURCE_VP_TYPE_VFI); /* VFI Type */ 6800 soc_SOURCE_VPm_field32_set(unit, svp, VFIf, vfi_index); 6801 6802 BCM_IF_ERROR_RETURN 6803 (WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, active_vp, svp)); 6804 6805 return rv; 6806 } 6807 6808 6809 /* 6810 * Function: 6811 * _bcm_tr3_l2gre_elan_vp_configure 6812 * Purpose: 6813 * Configure L2GRE ELINE virtual port 6814 * Parameters: 6815 * unit - (IN) Device Number 6816 * vpn - (IN) VPN instance ID 6817 * Returns: 6818 * BCM_E_XXX 6819 */ 6820 6821 int 6822 _bcm_tr3_l2gre_elan_vp_configure (int unit, int vfi_index, int active_vp, 6823 source_vp_entry_t *svp, int tpid_enable, bcm_l2gre_port_t *l2gre_port) 6824 { 6825 int rv = BCM_E_NONE; 6826 int network_group=0; 6827 int cml_default_enable=0, cml_default_new=0, cml_default_move=0; 6828 6829 /* Set SOURCE_VP */ 6830 soc_SOURCE_VPm_field32_set(unit, svp, CLASS_IDf, 6831 l2gre_port->if_class); 6832 6833 /* Default Split Horizon Group Id 6834 * 0 - For Access Port;1 - For Network Port*/ 6835 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 6836 if (l2gre_port->flags & BCM_L2GRE_PORT_NETWORK) { 6837 network_group = l2gre_port->network_group_id; 6838 rv = _bcm_validate_splithorizon_network_group(unit, 6839 l2gre_port->flags & BCM_L2GRE_PORT_NETWORK, &network_group); 6840 BCM_IF_ERROR_RETURN(rv); 6841 soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_GROUPf, 6842 network_group); 6843 } else { 6844 network_group = l2gre_port->network_group_id; 6845 rv = _bcm_validate_splithorizon_network_group(unit, 6846 l2gre_port->flags & BCM_L2GRE_PORT_NETWORK, &network_group); 6847 BCM_IF_ERROR_RETURN(rv); 6848 soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_GROUPf, 6849 network_group); 6850 } 6851 } else { 6852 soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_PORTf, 6853 (l2gre_port->flags & BCM_L2GRE_PORT_NETWORK) ? 1 : 0); 6854 } 6855 6856 if (l2gre_port->flags & BCM_L2GRE_PORT_SERVICE_TAGGED) { 6857 soc_SOURCE_VPm_field32_set(unit, svp, SD_TAG_MODEf, 1); 6858 soc_SOURCE_VPm_field32_set(unit, svp, TPID_ENABLEf, tpid_enable); 6859 } else { 6860 soc_SOURCE_VPm_field32_set(unit, svp, SD_TAG_MODEf, 0); 6861 } 6862 if (vfi_index == _BCM_L2GRE_VFI_INVALID) { 6863 soc_SOURCE_VPm_field32_set(unit, svp, 6864 ENTRY_TYPEf, _BCM_L2GRE_SOURCE_VP_TYPE_INVALID); /* INVALID */ 6865 } else { 6866 /* Initialize VP parameters */ 6867 soc_SOURCE_VPm_field32_set(unit, svp, 6868 ENTRY_TYPEf, _BCM_L2GRE_SOURCE_VP_TYPE_VFI); /* VFI Type */ 6869 } 6870 soc_SOURCE_VPm_field32_set(unit, svp, VFIf, vfi_index); 6871 rv = _bcm_vp_default_cml_mode_get (unit, 6872 &cml_default_enable, &cml_default_new, 6873 &cml_default_move); 6874 if (rv < 0) { 6875 return rv; 6876 } 6877 if (cml_default_enable) { 6878 /* Set the CML to default values */ 6879 soc_SOURCE_VPm_field32_set(unit, svp, CML_FLAGS_NEWf, cml_default_new); 6880 soc_SOURCE_VPm_field32_set(unit, svp, CML_FLAGS_MOVEf, cml_default_move); 6881 } else { 6882 /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */ 6883 soc_SOURCE_VPm_field32_set(unit, svp, CML_FLAGS_NEWf, 0x8); 6884 soc_SOURCE_VPm_field32_set(unit, svp, CML_FLAGS_MOVEf, 0x8); 6885 } 6886 if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) { 6887 soc_SOURCE_VPm_field32_set(unit, svp, DISABLE_VLAN_CHECKSf, 0x1); 6888 } 6889 6890 BCM_IF_ERROR_RETURN 6891 (WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, active_vp, svp)); 6892 6893 return rv; 6894 } 6895 6896 /* 6897 * Function: 6898 * _bcm_tr3_l2gre_access_niv_pe_set 6899 * Purpose: 6900 * Set L2GRE Access virtual port which is of NIV/PE type 6901 * Parameters: 6902 * unit - (IN) Device Number 6903 * vp - (IN) Access Virtual Port 6904 * vfi - (IN) Virtial forwarding instance 6905 * Returns: 6906 * BCM_E_XXX 6907 */ 6908 6909 STATIC int 6910 _bcm_tr3_l2gre_access_niv_pe_set (int unit, int vp, int vfi) 6911 { 6912 source_vp_entry_t svp; 6913 int rv = BCM_E_PARAM; 6914 6915 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 6916 if (rv < 0) { 6917 return rv; 6918 } 6919 6920 if (vfi == _BCM_L2GRE_VFI_INVALID) { 6921 soc_SOURCE_VPm_field32_set(unit, &svp, 6922 ENTRY_TYPEf, _BCM_L2GRE_SOURCE_VP_TYPE_INVALID); 6923 } else { 6924 /* Initialize VP parameters */ 6925 soc_SOURCE_VPm_field32_set(unit, &svp, 6926 ENTRY_TYPEf, _BCM_L2GRE_SOURCE_VP_TYPE_VFI); 6927 } 6928 soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, vfi); 6929 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 6930 return rv; 6931 } 6932 6933 /* 6934 * Function: 6935 * _bcm_tr3_l2gre_access_niv_pe_reset 6936 * Purpose: 6937 * Reset L2GRE Access virtual port which is of NIV/PE type 6938 * Parameters: 6939 * unit - (IN) Device Number 6940 * vp - (IN) Access Virtual Port 6941 * Returns: 6942 * BCM_E_XXX 6943 */ 6944 6945 STATIC int 6946 _bcm_tr3_l2gre_access_niv_pe_reset (int unit, int vp) 6947 { 6948 source_vp_entry_t svp; 6949 int rv = BCM_E_PARAM; 6950 6951 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 6952 if (rv < 0) { 6953 return rv; 6954 } 6955 6956 /* Initialize VP parameters */ 6957 soc_SOURCE_VPm_field32_set(unit, &svp, 6958 ENTRY_TYPEf, _BCM_L2GRE_SOURCE_VP_TYPE_VLAN); 6959 soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, 0); 6960 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 6961 return rv; 6962 } 6963 6964 /* 6965 * Function: 6966 * _bcm_tr3_l2gre_eline_port_add 6967 * Purpose: 6968 * Add L2GRE ELINE port to a VPN 6969 * Parameters: 6970 * unit - (IN) Device Number 6971 * vpn - (IN) VPN instance ID 6972 * l2gre_port - (IN/OUT) L2GRE port information (OUT : l2gre_port_id) 6973 * Returns: 6974 * BCM_E_XXX 6975 */ 6976 6977 STATIC int 6978 _bcm_tr3_l2gre_eline_port_add(int unit, bcm_vpn_t vpn, bcm_l2gre_port_t *l2gre_port) 6979 { 6980 int active_vp = 0; /* default VP */ 6981 source_vp_entry_t svp1, svp2; 6982 uint8 vp_valid_flag = 0; 6983 int tpid_enable = 0, tpid_index=-1; 6984 int customer_drop=0; 6985 int rv = BCM_E_PARAM; 6986 int num_vp=0; 6987 int vp1=0, vp2=0, vfi_index= -1; 6988 _bcm_vp_info_t vp_info; 6989 6990 _bcm_vp_info_init(&vp_info); 6991 vp_info.vp_type = _bcmVpTypeL2Gre; 6992 6993 if ( vpn != BCM_L2GRE_VPN_INVALID) { 6994 _BCM_L2GRE_VPN_GET(vfi_index, _BCM_L2GRE_VPN_TYPE_ELINE, vpn); 6995 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeL2Gre)) { 6996 return BCM_E_NOT_FOUND; 6997 } 6998 } else { 6999 vfi_index = _BCM_L2GRE_VFI_INVALID; 7000 } 7001 7002 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 7003 7004 if ( vpn != BCM_L2GRE_VPN_INVALID) { 7005 7006 /* ---- Read in current table values for VP1 and VP2 ----- */ 7007 (void) _bcm_tr3_l2gre_eline_vp_map_get (unit, vfi_index, &vp1, &vp2); 7008 7009 if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeL2Gre)) { 7010 BCM_IF_ERROR_RETURN ( 7011 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp1, &svp1)); 7012 if (soc_SOURCE_VPm_field32_get(unit, &svp1, ENTRY_TYPEf) == 0x1) { 7013 vp_valid_flag |= 0x1; /* -- VP1 Valid ----- */ 7014 } 7015 } 7016 7017 if (_bcm_vp_used_get(unit, vp2, _bcmVpTypeL2Gre)) { 7018 BCM_IF_ERROR_RETURN ( 7019 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp2, &svp2)); 7020 if (soc_SOURCE_VPm_field32_get(unit, &svp2, ENTRY_TYPEf) == 0x1) { 7021 vp_valid_flag |= 0x2; /* -- VP2 Valid ----- */ 7022 } 7023 } 7024 7025 if (l2gre_port->flags & BCM_L2GRE_PORT_REPLACE) { 7026 active_vp = BCM_GPORT_L2GRE_PORT_ID_GET(l2gre_port->l2gre_port_id); 7027 if (active_vp == -1) { 7028 return BCM_E_PARAM; 7029 } 7030 if (!_bcm_vp_used_get(unit, active_vp, _bcmVpTypeL2Gre)) { 7031 return BCM_E_NOT_FOUND; 7032 } 7033 7034 /* Decrement old-port's nexthop count */ 7035 rv = _bcm_tr3_l2gre_port_nh_cnt_dec(unit, active_vp); 7036 if(rv < 0) { 7037 return rv; 7038 } 7039 7040 /* Decrement old-port's VP count */ 7041 rv = _bcm_tr3_l2gre_port_cnt_update(unit, l2gre_port->l2gre_port_id, 7042 active_vp, FALSE); 7043 if (rv < 0) { 7044 return rv; 7045 } 7046 } 7047 } 7048 7049 switch (vp_valid_flag) { 7050 7051 case 0x0: /* No VP is valid */ 7052 if (l2gre_port->flags & BCM_L2GRE_PORT_REPLACE) { 7053 return BCM_E_NOT_FOUND; 7054 } 7055 7056 if (l2gre_port->flags & BCM_L2GRE_PORT_WITH_ID) { 7057 vp1 = BCM_GPORT_L2GRE_PORT_ID_GET(l2gre_port->l2gre_port_id); 7058 if (vp1 == -1) { 7059 return BCM_E_PARAM; 7060 } 7061 7062 if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeL2Gre)) { 7063 return BCM_E_EXISTS; 7064 } 7065 if (vp1 >= num_vp) { 7066 return (BCM_E_BADID); 7067 } 7068 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT); 7069 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp1, vp_info)); 7070 7071 } else { 7072 7073 /* No entries are used, allocate a new VP index for VP1 */ 7074 7075 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT); 7076 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp1); 7077 if (rv < 0) { 7078 return rv; 7079 } 7080 #if defined(BCM_TRIUMPH3_SUPPORT) 7081 /* 7082 * EGR_MPLS_VC_AND_SWAP_LABEL_TABLE and EGR_DVP_ATTRIBUTE_1 are overlaid 7083 * tables on TR3. If there is conflict between thesw two tables, the entries for 7084 * EGR_DVP_ATTRIBUTE_1 own higher priority. 7085 */ 7086 if (soc_feature(unit, soc_feature_mpls) && 7087 soc_feature(unit, soc_feature_vc_and_swap_table_overlaid) && 7088 (l2gre_port->flags & BCM_L2GRE_PORT_EGRESS_TUNNEL)) { 7089 rv = _bcm_tr_mpls_vc_and_swap_table_entry_adjust(unit, vp1); 7090 if (rv < 0) { 7091 (void)_bcm_vp_free(unit, _bcmVpTypeL2Gre, 1, vp1); 7092 return rv; 7093 } 7094 } 7095 #endif 7096 /* Allocate a new VP index for VP2 */ 7097 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 7098 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp2); 7099 if (rv < 0) { 7100 (void) _bcm_vp_free(unit, _bcmVpTypeL2Gre, 1, vp1); 7101 return rv; 7102 } 7103 } 7104 7105 active_vp = vp1; 7106 vp_valid_flag = 1; 7107 sal_memset(&svp1, 0, sizeof(source_vp_entry_t)); 7108 sal_memset(&svp2, 0, sizeof(source_vp_entry_t)); 7109 (void) _bcm_tr3_l2gre_eline_vp_map_set(unit, vfi_index, vp1, vp2); 7110 break; 7111 7112 7113 case 0x1: /* Only VP1 is valid */ 7114 if (l2gre_port->flags & BCM_L2GRE_PORT_REPLACE) { 7115 if (active_vp != vp1) { 7116 return BCM_E_NOT_FOUND; 7117 } 7118 } else if (l2gre_port->flags & BCM_L2GRE_PORT_WITH_ID) { 7119 vp2 = BCM_GPORT_L2GRE_PORT_ID_GET(l2gre_port->l2gre_port_id); 7120 if (vp2 == -1) { 7121 return BCM_E_PARAM; 7122 } 7123 7124 if (_bcm_vp_used_get(unit, vp2, _bcmVpTypeL2Gre)) { 7125 return BCM_E_EXISTS; 7126 } 7127 if (vp2 >= num_vp) { 7128 return (BCM_E_BADID); 7129 } 7130 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 7131 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp2, vp_info)); 7132 7133 } else { 7134 active_vp = vp2; 7135 vp_valid_flag = 3; 7136 sal_memset(&svp2, 0, sizeof(source_vp_entry_t)); 7137 } 7138 7139 (void) _bcm_tr3_l2gre_eline_vp_map_set(unit, vfi_index, vp1, vp2); 7140 break; 7141 7142 7143 7144 case 0x2: /* Only VP2 is valid */ 7145 if (l2gre_port->flags & BCM_L2GRE_PORT_REPLACE) { 7146 if (active_vp != vp2) { 7147 return BCM_E_NOT_FOUND; 7148 } 7149 } else if (l2gre_port->flags & BCM_L2GRE_PORT_WITH_ID) { 7150 vp1 = BCM_GPORT_L2GRE_PORT_ID_GET(l2gre_port->l2gre_port_id); 7151 if (vp1 == -1) { 7152 return BCM_E_PARAM; 7153 } 7154 7155 if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeL2Gre)) { 7156 return BCM_E_EXISTS; 7157 } 7158 if (vp1 >= num_vp) { 7159 return (BCM_E_BADID); 7160 } 7161 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT); 7162 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp1, vp_info)); 7163 7164 } else { 7165 active_vp = vp1; 7166 vp_valid_flag = 3; 7167 sal_memset(&svp1, 0, sizeof(source_vp_entry_t)); 7168 } 7169 7170 (void) _bcm_tr3_l2gre_eline_vp_map_set(unit, vfi_index, vp1, vp2); 7171 break; 7172 7173 7174 7175 case 0x3: /* VP1 and VP2 are valid */ 7176 if (!(l2gre_port->flags & BCM_L2GRE_PORT_REPLACE)) { 7177 return BCM_E_FULL; 7178 } 7179 break; 7180 } 7181 7182 if (active_vp == -1) { 7183 return BCM_E_CONFIG; 7184 } 7185 7186 /* Set L2GRE port ID */ 7187 if (!(l2gre_port->flags & BCM_L2GRE_PORT_REPLACE)) { 7188 BCM_GPORT_L2GRE_PORT_ID_SET(l2gre_port->l2gre_port_id, active_vp); 7189 } 7190 7191 /* ======== Configure Next-Hop Properties ========== */ 7192 customer_drop = (l2gre_port->flags & BCM_L2GRE_PORT_DROP) ? 1 : 0; 7193 rv = _bcm_tr3_l2gre_port_nh_add(unit, l2gre_port, active_vp, vpn, customer_drop); 7194 if (rv < 0) { 7195 if (!(l2gre_port->flags & BCM_L2GRE_PORT_REPLACE)) { 7196 (void) _bcm_vp_free(unit, _bcmVfiTypeL2Gre, 1, active_vp); 7197 } 7198 return rv; 7199 } 7200 7201 /* ======== Configure Service-Tag Properties =========== */ 7202 if (l2gre_port->flags & BCM_L2GRE_PORT_SERVICE_TAGGED) { 7203 #if defined(BCM_TRIDENT3_SUPPORT) 7204 if (SOC_IS_TRIDENT3X(unit)) { 7205 rv = _bcm_fb2_outer_tpid_entry_add(unit,l2gre_port->egress_service_tpid, &tpid_index); 7206 } else 7207 #endif 7208 { 7209 rv = _bcm_fb2_outer_tpid_lkup(unit, l2gre_port->egress_service_tpid, 7210 &tpid_index); 7211 } 7212 if (rv < 0) { 7213 goto l2gre_cleanup; 7214 } 7215 tpid_enable = (1 << tpid_index); 7216 } 7217 7218 /* ======== Configure SVP Properties ========== */ 7219 if (active_vp == vp1) { 7220 rv = _bcm_esw_l2gre_eline_vp_configure (unit, vfi_index, active_vp, &svp1, 7221 tpid_enable, l2gre_port); 7222 } else if (active_vp == vp2) { 7223 rv = _bcm_esw_l2gre_eline_vp_configure (unit, vfi_index, active_vp, &svp2, 7224 tpid_enable, l2gre_port); 7225 } 7226 if (rv < 0) { 7227 goto l2gre_cleanup; 7228 } 7229 7230 rv = _bcm_esw_l2gre_match_add(unit, l2gre_port, active_vp, vpn); 7231 if (rv < 0) { 7232 goto l2gre_cleanup; 7233 } 7234 7235 /* Increment new-port's VP count */ 7236 rv = _bcm_tr3_l2gre_port_cnt_update(unit, l2gre_port->l2gre_port_id, active_vp, TRUE); 7237 if (rv < 0) { 7238 goto l2gre_cleanup; 7239 } 7240 7241 /* Set L2GRE port ID */ 7242 if (!(l2gre_port->flags & BCM_L2GRE_PORT_REPLACE)) { 7243 BCM_GPORT_L2GRE_PORT_ID_SET(l2gre_port->l2gre_port_id, active_vp); 7244 } 7245 7246 l2gre_cleanup: 7247 if (rv < 0) { 7248 if (tpid_enable) { 7249 (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 7250 } 7251 /* Free the VP's */ 7252 if (vp_valid_flag) { 7253 if (vp1 != -1) { 7254 (void) _bcm_vp_free(unit, _bcmVpTypeL2Gre, 1, vp1); 7255 } 7256 if (vp2 != -1) { 7257 (void) _bcm_vp_free(unit, _bcmVpTypeL2Gre, 1, vp2); 7258 } 7259 } 7260 } 7261 return rv; 7262 } 7263 7264 /* 7265 * Function: 7266 * _bcm_tr3_l2gre_elan_port_add 7267 * Purpose: 7268 * Add L2GRE ELAN port to a VPN 7269 * Parameters: 7270 * unit - (IN) Device Number 7271 * vpn - (IN) VPN instance ID 7272 * l2gre_port - (IN/OUT) l2gre port information (OUT : l2gre_port_id) 7273 * Returns: 7274 * BCM_E_XXX 7275 */ 7276 7277 STATIC int 7278 _bcm_tr3_l2gre_elan_port_add(int unit, bcm_vpn_t vpn, bcm_l2gre_port_t *l2gre_port) 7279 { 7280 int vp, num_vp, vfi=0; 7281 source_vp_entry_t svp; 7282 int tpid_enable = 0, tpid_index=-1; 7283 int drop, rv = BCM_E_PARAM; 7284 _bcm_vp_info_t vp_info; 7285 7286 _bcm_vp_info_init(&vp_info); 7287 vp_info.vp_type = _bcmVpTypeL2Gre; 7288 if (l2gre_port->flags & BCM_L2GRE_PORT_NETWORK) { 7289 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 7290 } else { 7291 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT); 7292 } 7293 7294 if (l2gre_port->criteria != BCM_L2GRE_PORT_MATCH_SHARE) { 7295 if ( vpn != BCM_L2GRE_VPN_INVALID) { 7296 _BCM_L2GRE_VPN_GET(vfi, _BCM_L2GRE_VPN_TYPE_ELAN, vpn); 7297 if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeL2Gre)) { 7298 return BCM_E_NOT_FOUND; 7299 } 7300 } else { 7301 vfi = _BCM_L2GRE_VFI_INVALID; 7302 } 7303 } else { 7304 vp_info.flags |= _BCM_VP_INFO_SHARED_PORT; 7305 } 7306 7307 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 7308 7309 /* ======== Allocate/Get Virtual_Port =============== */ 7310 if (l2gre_port->flags & BCM_L2GRE_PORT_REPLACE) { 7311 if (BCM_GPORT_IS_NIV_PORT(l2gre_port->l2gre_port_id) || 7312 BCM_GPORT_IS_EXTENDER_PORT(l2gre_port->l2gre_port_id)) { 7313 if (BCM_GPORT_IS_NIV_PORT(l2gre_port->l2gre_port_id)) { 7314 vp = BCM_GPORT_NIV_PORT_ID_GET((l2gre_port->l2gre_port_id)); 7315 } else if (BCM_GPORT_IS_EXTENDER_PORT(l2gre_port->l2gre_port_id)) { 7316 vp = BCM_GPORT_EXTENDER_PORT_ID_GET((l2gre_port->l2gre_port_id)); 7317 } 7318 rv = _bcm_tr3_l2gre_access_niv_pe_set (unit, vp, vfi); 7319 if (BCM_SUCCESS(rv)) { 7320 /* Set L2GRE port ID */ 7321 BCM_GPORT_L2GRE_PORT_ID_SET(l2gre_port->l2gre_port_id, vp); 7322 rv = _bcm_vp_used_set(unit, vp, vp_info); 7323 } 7324 return rv; 7325 } 7326 7327 vp = BCM_GPORT_L2GRE_PORT_ID_GET(l2gre_port->l2gre_port_id); 7328 if (vp == -1) { 7329 return BCM_E_PARAM; 7330 } 7331 7332 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 7333 return BCM_E_NOT_FOUND; 7334 } 7335 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 7336 if (rv < 0) { 7337 return rv; 7338 } 7339 /* Decrement old-port's nexthop count */ 7340 rv = _bcm_tr3_l2gre_port_nh_cnt_dec(unit, vp); 7341 if(rv < 0) { 7342 return rv; 7343 } 7344 /* Decrement old-port's VP count */ 7345 rv = _bcm_tr3_l2gre_port_cnt_update(unit, l2gre_port->l2gre_port_id, vp, FALSE); 7346 if (rv < 0) { 7347 return rv; 7348 } 7349 7350 } else if (l2gre_port->flags & BCM_L2GRE_PORT_WITH_ID ) { 7351 if (!BCM_GPORT_IS_L2GRE_PORT(l2gre_port->l2gre_port_id)) { 7352 return (BCM_E_BADID); 7353 } 7354 7355 vp = BCM_GPORT_L2GRE_PORT_ID_GET(l2gre_port->l2gre_port_id); 7356 if (vp == -1) { 7357 return BCM_E_PARAM; 7358 } 7359 if (vp >= num_vp) { 7360 return (BCM_E_BADID); 7361 } 7362 7363 if (l2gre_port->flags & BCM_L2GRE_PORT_NETWORK) { 7364 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 7365 } else { 7366 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT); 7367 } 7368 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info)); 7369 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 7370 } else { 7371 /* allocate a new VP index */ 7372 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp); 7373 if (rv < 0) { 7374 return rv; 7375 } 7376 #if defined(BCM_TRIUMPH3_SUPPORT) 7377 /* 7378 * EGR_MPLS_VC_AND_SWAP_LABEL_TABLE and EGR_DVP_ATTRIBUTE_1 are overlaid 7379 * tables on TR3. If there is conflict between thesw two tables, the entries for 7380 * EGR_DVP_ATTRIBUTE_1 own higher priority. 7381 */ 7382 if (soc_feature(unit, soc_feature_mpls) && 7383 soc_feature(unit, soc_feature_vc_and_swap_table_overlaid) && 7384 (l2gre_port->flags & BCM_L2GRE_PORT_EGRESS_TUNNEL)) { 7385 rv = _bcm_tr_mpls_vc_and_swap_table_entry_adjust(unit, vp); 7386 if (rv < 0) { 7387 (void)_bcm_vp_free(unit, _bcmVpTypeL2Gre, 1, vp); 7388 return rv; 7389 } 7390 } 7391 #endif 7392 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 7393 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info)); 7394 } 7395 7396 /* ======== Configure Next-Hop/DVP Properties ========== */ 7397 drop = (l2gre_port->flags & BCM_L2GRE_PORT_DROP) ? 1 : 0; 7398 rv = _bcm_tr3_l2gre_port_nh_add(unit, l2gre_port, vp, vpn, drop); 7399 if (rv < 0) { 7400 if (!(l2gre_port->flags & BCM_L2GRE_PORT_REPLACE)) { 7401 (void) _bcm_vp_free(unit, _bcmVpTypeL2Gre, 1, vp); 7402 } 7403 return rv; 7404 } 7405 7406 /* ======== Configure Service-Tag Properties =========== */ 7407 if (l2gre_port->flags & BCM_L2GRE_PORT_SERVICE_TAGGED) { 7408 #if defined(BCM_TRIDENT3_SUPPORT) 7409 if (SOC_IS_TRIDENT3X(unit)) { 7410 rv = _bcm_fb2_outer_tpid_entry_add(unit,l2gre_port->egress_service_tpid, &tpid_index); 7411 } else 7412 #endif 7413 { 7414 rv = _bcm_fb2_outer_tpid_lkup(unit, l2gre_port->egress_service_tpid, 7415 &tpid_index); 7416 } 7417 if (rv < 0) { 7418 goto l2gre_cleanup; 7419 } 7420 if (tpid_index != -1) { 7421 tpid_enable = (1 << tpid_index); 7422 } 7423 } 7424 7425 /* ======== Configure SVP Properties ========== */ 7426 rv = _bcm_esw_l2gre_elan_vp_configure (unit, vfi, vp, &svp, 7427 tpid_enable, l2gre_port); 7428 if (rv < 0) { 7429 goto l2gre_cleanup; 7430 } 7431 7432 if (rv == BCM_E_NONE) { 7433 /* Set L2GRE port ID */ 7434 BCM_GPORT_L2GRE_PORT_ID_SET(l2gre_port->l2gre_port_id, vp); 7435 } 7436 7437 /* Increment new-port's VP count */ 7438 rv = _bcm_tr3_l2gre_port_cnt_update(unit, l2gre_port->l2gre_port_id, vp, TRUE); 7439 if (rv < 0) { 7440 goto l2gre_cleanup; 7441 } 7442 7443 /* ======== Configure match to VP Properties ========== */ 7444 rv = _bcm_esw_l2gre_match_add(unit, l2gre_port, vp, vpn); 7445 if (rv < 0) { 7446 goto l2gre_cleanup; 7447 } 7448 7449 l2gre_cleanup: 7450 if (rv < 0) { 7451 if (tpid_enable) { 7452 (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 7453 } 7454 if (!(l2gre_port->flags & BCM_L2GRE_PORT_REPLACE)) { 7455 (void) _bcm_vp_free(unit, _bcmVpTypeL2Gre, 1, vp); 7456 _bcm_tr3_l2gre_port_nh_delete(unit, vpn, vp); 7457 } 7458 } 7459 return rv; 7460 } 7461 7462 /* 7463 * Function: 7464 * _bcm_tr3_l2gre_eline_port_delete 7465 * Purpose: 7466 * Delete L2GRE ELINE port from a VPN 7467 * Parameters: 7468 * unit - (IN) Device Number 7469 * vpn - (IN) VPN instance ID 7470 * l2gre_port_id - (IN) l2gre port information 7471 * Returns: 7472 * BCM_E_XXX 7473 */ 7474 7475 int 7476 _bcm_tr3_l2gre_eline_port_delete(int unit, bcm_vpn_t vpn, int active_vp) 7477 { 7478 source_vp_entry_t svp; 7479 int vp1=0, vp2=0, vfi_index= -1; 7480 int rv = BCM_E_UNAVAIL; 7481 bcm_gport_t l2gre_port_id; 7482 7483 if ( vpn != BCM_L2GRE_VPN_INVALID) { 7484 _BCM_L2GRE_VPN_GET(vfi_index, _BCM_L2GRE_VPN_TYPE_ELINE, vpn); 7485 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeL2Gre)) { 7486 return BCM_E_NOT_FOUND; 7487 } 7488 } else { 7489 vfi_index = _BCM_L2GRE_VFI_INVALID; 7490 } 7491 7492 if (!_bcm_vp_used_get(unit, active_vp, _bcmVpTypeL2Gre)) { 7493 return BCM_E_NOT_FOUND; 7494 } 7495 7496 /* Set L2GRE port ID */ 7497 BCM_GPORT_L2GRE_PORT_ID_SET(l2gre_port_id, active_vp); 7498 7499 /* Delete the next-hop info */ 7500 rv = _bcm_tr3_l2gre_port_nh_delete(unit, vpn, active_vp); 7501 if ( rv < 0 ) { 7502 if (rv != BCM_E_NOT_FOUND) { 7503 return rv; 7504 } else { 7505 rv = 0; 7506 } 7507 } 7508 7509 rv = _bcm_esw_l2gre_match_delete(unit, active_vp); 7510 if ( rv < 0 ) { 7511 if (rv != BCM_E_NOT_FOUND) { 7512 return rv; 7513 } else { 7514 rv = BCM_E_NONE; 7515 } 7516 } 7517 7518 /* ---- Read in current table values for VP1 and VP2 ----- */ 7519 (void) _bcm_tr3_l2gre_eline_vp_map_get (unit, vfi_index, &vp1, &vp2); 7520 7521 /* If the other port is valid, point it to itself */ 7522 if (active_vp == vp1) { 7523 if (BCM_SUCCESS(rv)) { 7524 rv = _bcm_tr3_l2gre_eline_vp_map_clear (unit, vfi_index, active_vp, 0); 7525 } 7526 } else if (active_vp == vp2) { 7527 if (BCM_SUCCESS(rv)) { 7528 rv = _bcm_tr3_l2gre_eline_vp_map_clear (unit, vfi_index, 0, active_vp); 7529 } 7530 } 7531 7532 if (rv >= 0) { 7533 7534 #ifdef BCM_TRIDENT2_SUPPORT 7535 if (soc_mem_is_valid(unit, SOURCE_VP_2m)) { 7536 source_vp_2_entry_t svp_2_entry; 7537 int network_port_flag=0; 7538 _bcm_vp_info_t vp_info; 7539 7540 /* Check for Network-Port */ 7541 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, active_vp, &vp_info)); 7542 if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) { 7543 network_port_flag = TRUE; 7544 } 7545 7546 if (!network_port_flag) { 7547 /* Clear SOURCE_VP_2 entry */ 7548 sal_memset(&svp_2_entry, 0, sizeof(source_vp_2_entry_t)); 7549 BCM_IF_ERROR_RETURN 7550 (WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, active_vp, &svp_2_entry)); 7551 } 7552 } 7553 #endif /* BCM_TRIDENT2_SUPPORT */ 7554 7555 /* Invalidate the VP being deleted */ 7556 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 7557 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, active_vp, &svp); 7558 if (BCM_SUCCESS(rv)) { 7559 rv = _bcm_tr3_l2gre_egress_dvp_reset(unit, active_vp); 7560 if (rv < 0) { 7561 return rv; 7562 } 7563 rv = _bcm_tr3_l2gre_ingress_dvp_reset(unit, active_vp); 7564 } 7565 } 7566 7567 if (rv < 0) { 7568 return rv; 7569 } 7570 7571 /* Decrement port's VP count */ 7572 rv = _bcm_tr3_l2gre_port_cnt_update(unit, l2gre_port_id, active_vp, FALSE); 7573 if (rv < 0) { 7574 return rv; 7575 } 7576 7577 /* Free the VP */ 7578 (void) _bcm_vp_free(unit, _bcmVfiTypeL2Gre, 1, active_vp); 7579 return rv; 7580 7581 } 7582 7583 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 7584 /* 7585 * Function: 7586 * bcm_tr3_share_vp_get 7587 * Purpose: 7588 * Get shared VPs info per VPN 7589 * Parameters: 7590 * unit - (IN) Device Number 7591 * vpn - (IN) VPN that shared vp belong to 7592 * vp_bitmap - (OUT) shared vp bitmap 7593 * Returns: 7594 * BCM_E_XXX 7595 */ 7596 int 7597 bcm_tr3_share_vp_get(int unit, bcm_vpn_t vpn, SHR_BITDCL *vp_bitmap) 7598 { 7599 void *vent; 7600 soc_mem_t mem; 7601 int index_min = 0; 7602 int index_max = 0; 7603 uint8 *xlate_buf = NULL; 7604 int buf_size = 0; 7605 int i = 0; 7606 int rv = BCM_E_NONE; 7607 int vfi = -1; 7608 int vp = -1; 7609 7610 if (vpn != BCM_L2GRE_VPN_INVALID) { 7611 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_vpn_is_valid(unit, vpn)); 7612 _BCM_L2GRE_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn); 7613 } 7614 #if defined(BCM_TRIDENT3_SUPPORT) 7615 if (soc_feature(unit, soc_feature_base_valid)) { 7616 mem = VLAN_XLATE_1_DOUBLEm; 7617 } else 7618 #endif 7619 { 7620 mem = VLAN_XLATEm; 7621 } 7622 index_min = soc_mem_index_min(unit, mem); 7623 index_max = soc_mem_index_max(unit, mem); 7624 7625 buf_size = SOC_MEM_TABLE_BYTES(unit, mem); 7626 xlate_buf = soc_cm_salloc(unit, buf_size, "VLAN_XLATE buffer"); 7627 if (NULL == xlate_buf) { 7628 return BCM_E_MEMORY; 7629 } 7630 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index_min, index_max, xlate_buf); 7631 if (rv < 0) { 7632 soc_cm_sfree(unit, xlate_buf); 7633 return rv; 7634 } 7635 7636 for (i = index_min; i <= index_max; i++) { 7637 vent = soc_mem_table_idx_to_pointer(unit, 7638 mem, void *, xlate_buf, i); 7639 #if defined(BCM_TRIDENT3_SUPPORT) 7640 if (soc_feature(unit, soc_feature_base_valid)) { 7641 if (soc_mem_field32_get(unit, mem, vent, BASE_VALID_0f) != 3) { 7642 continue; 7643 } 7644 if (soc_mem_field32_get(unit, mem, vent, BASE_VALID_1f) != 7) { 7645 continue; 7646 } 7647 } else 7648 #endif 7649 { 7650 if (soc_mem_field32_get(unit, mem, vent, VALIDf) == 0) { 7651 continue; 7652 } 7653 } 7654 7655 if (soc_mem_field32_get(unit, mem, vent, XLATE__MPLS_ACTIONf) != 0x1) { 7656 continue; 7657 } 7658 7659 if (vfi != -1 && soc_mem_field32_get(unit, mem, vent, XLATE__VFIf) != vfi) { 7660 continue; 7661 } 7662 7663 vp = soc_mem_field32_get(unit, mem, vent, XLATE__SOURCE_VPf); 7664 SHR_BITSET(vp_bitmap, vp); 7665 } 7666 7667 (void)soc_cm_sfree(unit, xlate_buf); 7668 7669 return BCM_E_NONE; 7670 } 7671 7672 /* 7673 * Function: 7674 * _bcm_tr3_share_vp_delete 7675 * Purpose: 7676 * Delete match criteria of shared VPs 7677 * Parameters: 7678 * unit - (IN) Device Number 7679 * vpn - (IN) VPN that shared vp belong to 7680 * vp - (IN) Source Virtual Port 7681 * Returns: 7682 * BCM_E_XXX 7683 */ 7684 int 7685 _bcm_tr3_share_vp_delete(int unit, bcm_vpn_t vpn, int vp) 7686 { 7687 void *vent; 7688 soc_mem_t mem; 7689 int index_min = 0; 7690 int index_max = 0; 7691 uint8 *xlate_buf = NULL; 7692 int buf_size = 0; 7693 int i = 0; 7694 int rv = BCM_E_NONE; 7695 int vfi = -1; 7696 int source_vp = -1; 7697 7698 if (vpn != BCM_L2GRE_VPN_INVALID) { 7699 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_vpn_is_valid(unit, vpn)); 7700 _BCM_L2GRE_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn); 7701 } 7702 #if defined(BCM_TRIDENT3_SUPPORT) 7703 if (soc_feature(unit, soc_feature_base_valid)) { 7704 mem = VLAN_XLATE_1_DOUBLEm; 7705 } else 7706 #endif 7707 { 7708 mem = VLAN_XLATEm; 7709 } 7710 7711 index_min = soc_mem_index_min(unit, mem); 7712 index_max = soc_mem_index_max(unit, mem); 7713 7714 buf_size = SOC_MEM_TABLE_BYTES(unit, mem); 7715 xlate_buf = soc_cm_salloc(unit, buf_size, "VLAN_XLATE buffer"); 7716 if (NULL == xlate_buf) { 7717 return BCM_E_MEMORY; 7718 } 7719 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index_min, index_max, xlate_buf); 7720 if (rv < 0) { 7721 soc_cm_sfree(unit, xlate_buf); 7722 return rv; 7723 } 7724 7725 for (i = index_min; i <= index_max; i++) { 7726 vent = soc_mem_table_idx_to_pointer(unit, 7727 mem, void *, xlate_buf, i); 7728 #if defined(BCM_TRIDENT3_SUPPORT) 7729 if (soc_feature(unit, soc_feature_base_valid)) { 7730 if (soc_mem_field32_get(unit, mem, vent, BASE_VALID_0f) != 3) { 7731 continue; 7732 } 7733 if (soc_mem_field32_get(unit, mem, vent, BASE_VALID_1f) != 7) { 7734 continue; 7735 } 7736 } else 7737 #endif 7738 { 7739 if (soc_mem_field32_get(unit, mem, vent, VALIDf) == 0) { 7740 continue; 7741 } 7742 } 7743 if (soc_mem_field32_get(unit, mem, vent, XLATE__MPLS_ACTIONf) != 0x1) { 7744 continue; 7745 } 7746 7747 if (vfi != -1 && soc_mem_field32_get(unit, mem, vent, XLATE__VFIf) != vfi) { 7748 continue; 7749 } 7750 7751 source_vp = soc_mem_field32_get(unit, mem, vent, XLATE__SOURCE_VPf); 7752 if (vp != source_vp) { 7753 continue; 7754 } 7755 rv = soc_mem_delete_index(unit, mem, MEM_BLOCK_ALL, i); 7756 if (rv < 0) { 7757 soc_cm_sfree(unit, xlate_buf); 7758 return rv; 7759 } 7760 bcm_tr3_l2gre_port_match_count_adjust(unit, source_vp, -1); 7761 } 7762 7763 (void)soc_cm_sfree(unit, xlate_buf); 7764 7765 return BCM_E_NONE; 7766 } 7767 #endif 7768 7769 /* 7770 * Function: 7771 * _bcm_tr3_l2gre_elan_port_delete 7772 * Purpose: 7773 * Delete L2GRE ELAN port from a VPN 7774 * Parameters: 7775 * unit - (IN) Device Number 7776 * vpn - (IN) VPN instance ID 7777 * l2gre_port_id - (IN) l2gre port information 7778 * Returns: 7779 * BCM_E_XXX 7780 */ 7781 7782 int 7783 _bcm_tr3_l2gre_elan_port_delete(int unit, bcm_vpn_t vpn, int vp) 7784 { 7785 source_vp_entry_t svp; 7786 int rv = BCM_E_UNAVAIL; 7787 int vfi_index= -1; 7788 bcm_gport_t l2gre_port_id; 7789 int network_port_flag=0; 7790 bcm_l2gre_port_t l2gre_port; 7791 _bcm_vp_info_t vp_info; 7792 7793 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 7794 return BCM_E_NOT_FOUND; 7795 } 7796 7797 /* Check for Network-Port */ 7798 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 7799 if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) { 7800 network_port_flag = TRUE; 7801 } 7802 7803 if ( vpn != BCM_L2GRE_VPN_INVALID) { 7804 if (!network_port_flag) { /* Check VPN only for Access VP */ 7805 _BCM_L2GRE_VPN_GET(vfi_index, _BCM_L2GRE_VPN_TYPE_ELAN, vpn); 7806 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeL2Gre)) { 7807 return BCM_E_NOT_FOUND; 7808 } 7809 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv) || 7810 _bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 7811 (void) _bcm_vp_free(unit, _bcmVpTypeL2Gre, 1, vp); 7812 rv = _bcm_tr3_l2gre_access_niv_pe_reset (unit, vp); 7813 return rv; 7814 } 7815 } 7816 } 7817 7818 /* Set L2GRE port ID */ 7819 BCM_GPORT_L2GRE_PORT_ID_SET(l2gre_port_id, vp); 7820 bcm_l2gre_port_t_init(&l2gre_port); 7821 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_port_get(unit, vpn, vp, &l2gre_port)); 7822 7823 /* Delete the next-hop info */ 7824 rv = _bcm_tr3_l2gre_port_nh_delete(unit, vpn, vp); 7825 7826 if ( rv < 0 ) { 7827 if (rv != BCM_E_NOT_FOUND) { 7828 return rv; 7829 } else { 7830 rv = 0; 7831 } 7832 } 7833 7834 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 7835 if ((!network_port_flag) && (vp_info.flags & _BCM_VP_INFO_SHARED_PORT)) { 7836 if (L2GRE_INFO(unit)->match_key[vp].match_count > 0) { 7837 BCM_IF_ERROR_RETURN(_bcm_tr3_share_vp_delete(unit, vpn, vp)); 7838 } 7839 if (vpn != BCM_L2GRE_VPN_INVALID) { 7840 return BCM_E_NONE; 7841 } 7842 7843 (void) bcm_tr3_l2gre_match_clear (unit, vp); 7844 } else 7845 #endif 7846 { 7847 rv = _bcm_esw_l2gre_match_delete(unit, vp); 7848 if ( rv < 0 ) { 7849 if (rv != BCM_E_NOT_FOUND) { 7850 return rv; 7851 } 7852 } 7853 } 7854 7855 /* Clear the SVP and DVP table entries */ 7856 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 7857 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 7858 if (rv < 0) { 7859 return rv; 7860 } 7861 7862 if (!network_port_flag) { 7863 #ifdef BCM_TRIDENT2_SUPPORT 7864 if (soc_mem_is_valid(unit, SOURCE_VP_2m)) { 7865 source_vp_2_entry_t svp_2_entry; 7866 7867 /* Clear SOURCE_VP_2 entry */ 7868 sal_memset(&svp_2_entry, 0, sizeof(source_vp_2_entry_t)); 7869 BCM_IF_ERROR_RETURN 7870 (WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, vp, &svp_2_entry)); 7871 } 7872 #endif /* BCM_TRIDENT2_SUPPORT */ 7873 } 7874 7875 rv = _bcm_tr3_l2gre_egress_dvp_reset(unit, vp); 7876 if (rv < 0) { 7877 return rv; 7878 } 7879 7880 rv = _bcm_tr3_l2gre_ingress_dvp_reset(unit, vp); 7881 if (rv < 0) { 7882 return rv; 7883 } 7884 7885 /* Decrement port's VP count */ 7886 rv = _bcm_tr3_l2gre_port_cnt_update(unit, l2gre_port_id, vp, FALSE); 7887 if (rv < 0) { 7888 return rv; 7889 } 7890 7891 /* Free the VP */ 7892 (void) _bcm_vp_free(unit, _bcmVfiTypeL2Gre, 1, vp); 7893 return rv; 7894 } 7895 7896 7897 /* 7898 * Function: 7899 * _bcm_tr3_l2gre_port_get 7900 * Purpose: 7901 * Get L2GRE port information from a VPN 7902 * Parameters: 7903 * unit - (IN) Device Number 7904 * vpn - (IN) VPN instance ID 7905 * l2gre_port_id - (IN) l2gre port information 7906 * Returns: 7907 * BCM_E_XXX 7908 */ 7909 7910 int 7911 _bcm_tr3_l2gre_port_get(int unit, bcm_vpn_t vpn, int vp, bcm_l2gre_port_t *l2gre_port) 7912 { 7913 int i, rv = BCM_E_NONE; 7914 uint32 tpid_enable = 0; 7915 source_vp_entry_t svp; 7916 int split_horizon_port_flag=0; 7917 _bcm_vp_info_t vp_info; 7918 7919 /* Initialize the structure */ 7920 bcm_l2gre_port_t_init(l2gre_port); 7921 BCM_GPORT_L2GRE_PORT_ID_SET(l2gre_port->l2gre_port_id, vp); 7922 7923 /* Check for Network-Port */ 7924 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 7925 if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) { 7926 split_horizon_port_flag = TRUE; 7927 } 7928 7929 if ( vpn != BCM_L2GRE_VPN_INVALID) { 7930 if (!split_horizon_port_flag) { /* Check VPN only for Access VP */ 7931 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv) || 7932 _bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 7933 return BCM_E_NONE; 7934 } 7935 } 7936 } 7937 7938 /* Get the match parameters */ 7939 rv = _bcm_esw_l2gre_match_get(unit, l2gre_port, vp); 7940 BCM_IF_ERROR_RETURN(rv); 7941 7942 /* Get the next-hop parameters */ 7943 rv = _bcm_tr3_l2gre_port_nh_get(unit, vpn, vp, l2gre_port); 7944 BCM_IF_ERROR_RETURN(rv); 7945 7946 /* Get Tunnel index */ 7947 rv = _bcm_tr3_l2gre_egress_dvp_get(unit, vp, l2gre_port); 7948 BCM_IF_ERROR_RETURN(rv); 7949 7950 /* Fill in SVP parameters */ 7951 BCM_IF_ERROR_RETURN (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp)); 7952 l2gre_port->if_class = soc_SOURCE_VPm_field32_get(unit, &svp, CLASS_IDf); 7953 if (split_horizon_port_flag) { 7954 l2gre_port->flags |= BCM_L2GRE_PORT_NETWORK; 7955 l2gre_port->flags |= BCM_L2GRE_PORT_EGRESS_TUNNEL; 7956 } 7957 7958 if (soc_SOURCE_VPm_field32_get(unit, &svp, SD_TAG_MODEf)) { 7959 #if defined(BCM_TRIDENT3_SUPPORT) 7960 if (SOC_IS_TRIDENT3X(unit)) { 7961 uint32 svp1[SOC_MAX_MEM_WORDS]; 7962 7963 BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vp, svp1)); 7964 soc_SVP_ATTRS_1m_field_get(unit, &svp1, TPID_ENABLEf, &tpid_enable); 7965 } else 7966 #endif 7967 { 7968 tpid_enable = soc_SOURCE_VPm_field32_get(unit, &svp, TPID_ENABLEf); 7969 } 7970 7971 if (tpid_enable) { 7972 l2gre_port->flags |= BCM_L2GRE_PORT_SERVICE_TAGGED; 7973 for (i = 0; i < 4; i++) { 7974 if (tpid_enable & (1 << i)) { 7975 _bcm_fb2_outer_tpid_entry_get(unit, 7976 &l2gre_port->egress_service_tpid, i); 7977 } 7978 } 7979 } 7980 } 7981 7982 return BCM_E_NONE; 7983 } 7984 7985 7986 /* 7987 * Function: 7988 * _bcm_tr3_l2gre_default_port_add 7989 * Purpose: 7990 * Add L2GRE port to a VPN 7991 * Parameters: 7992 * unit - (IN) Device Number 7993 * vpn - (IN) VPN instance ID 7994 * l2gre_port - (IN/OUT) l2gre_port information (OUT : l2gre_port_id) 7995 * Returns: 7996 * BCM_E_XXX 7997 */ 7998 7999 STATIC int 8000 _bcm_tr3_l2gre_default_port_add(int unit, bcm_l2gre_port_t *l2gre_port) 8001 { 8002 source_vp_entry_t svp; 8003 int rv = BCM_E_PARAM, vp=0, num_vp=0; 8004 int cml_default_enable=0, cml_default_new=0, cml_default_move=0; 8005 _bcm_vp_info_t vp_info; 8006 int network_group=0; 8007 8008 _bcm_vp_info_init(&vp_info); 8009 vp_info.vp_type = _bcmVpTypeL2Gre; 8010 if (l2gre_port->flags & BCM_L2GRE_PORT_NETWORK) { 8011 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 8012 } else { 8013 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT); 8014 } 8015 8016 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 8017 8018 /* ======== Allocate/Get Virtual_Port =============== */ 8019 if (l2gre_port->flags & BCM_L2GRE_PORT_REPLACE) { 8020 vp = BCM_GPORT_L2GRE_PORT_ID_GET(l2gre_port->l2gre_port_id); 8021 if (vp == -1) { 8022 return BCM_E_PARAM; 8023 } 8024 8025 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 8026 return BCM_E_NOT_FOUND; 8027 } 8028 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 8029 if (rv < 0) { 8030 return rv; 8031 } 8032 8033 /* Decrement old-port's nexthop count */ 8034 rv = _bcm_tr3_l2gre_port_nh_cnt_dec(unit, vp); 8035 if(rv < 0) { 8036 return rv; 8037 } 8038 8039 /* Decrement old-port's VP count */ 8040 rv = _bcm_tr3_l2gre_port_cnt_update(unit, l2gre_port->l2gre_port_id, vp, FALSE); 8041 if (rv < 0) { 8042 return rv; 8043 } 8044 8045 } else if (l2gre_port->flags & BCM_L2GRE_PORT_WITH_ID ) { 8046 if (!BCM_GPORT_IS_L2GRE_PORT(l2gre_port->l2gre_port_id)) { 8047 return (BCM_E_BADID); 8048 } 8049 8050 vp = BCM_GPORT_L2GRE_PORT_ID_GET(l2gre_port->l2gre_port_id); 8051 if (vp == -1) { 8052 return BCM_E_PARAM; 8053 } 8054 if (vp >= num_vp) { 8055 return (BCM_E_BADID); 8056 } 8057 8058 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info)); 8059 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 8060 } else { 8061 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp); 8062 if (rv < 0) { 8063 return rv; 8064 } 8065 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 8066 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info)); 8067 } 8068 8069 /* ======== Configure SVP/DVP Properties ========== */ 8070 soc_SOURCE_VPm_field32_set(unit, &svp, CLASS_IDf, 8071 l2gre_port->if_class); 8072 8073 /* Default Split Horizon Group Id 8074 * 0 - For Access Port;1 - For Network Port*/ 8075 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 8076 if (l2gre_port->flags & BCM_L2GRE_PORT_NETWORK) { 8077 network_group = l2gre_port->network_group_id; 8078 rv = _bcm_validate_splithorizon_network_group(unit, 8079 l2gre_port->flags & BCM_L2GRE_PORT_NETWORK, &network_group); 8080 BCM_IF_ERROR_RETURN(rv); 8081 soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_GROUPf, 8082 network_group); 8083 } else { 8084 network_group = l2gre_port->network_group_id; 8085 rv = _bcm_validate_splithorizon_network_group(unit, 8086 l2gre_port->flags & BCM_L2GRE_PORT_NETWORK, &network_group); 8087 BCM_IF_ERROR_RETURN(rv); 8088 soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_GROUPf, 8089 network_group); 8090 } 8091 } else { 8092 soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 8093 (l2gre_port->flags & BCM_L2GRE_PORT_NETWORK) ? 1 : 0); 8094 } 8095 8096 soc_SOURCE_VPm_field32_set(unit, &svp, 8097 ENTRY_TYPEf, _BCM_L2GRE_SOURCE_VP_TYPE_VFI); 8098 8099 rv = _bcm_vp_default_cml_mode_get (unit, 8100 &cml_default_enable, &cml_default_new, 8101 &cml_default_move); 8102 if (rv < 0) { 8103 return rv; 8104 } 8105 if (cml_default_enable) { 8106 /* Set the CML to default values */ 8107 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml_default_new); 8108 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml_default_move); 8109 } else { 8110 /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */ 8111 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, 0x8); 8112 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, 0x8); 8113 } 8114 if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) { 8115 soc_SOURCE_VPm_field32_set(unit, &svp, DISABLE_VLAN_CHECKSf, 1); 8116 } 8117 8118 /* Configure L2GRE_DEFAULT_NETWORK_SVPr.SVP */ 8119 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 8120 BCM_IF_ERROR_RETURN(rv); 8121 8122 #if defined(BCM_TRIDENT3_SUPPORT) 8123 if (SOC_IS_TRIDENT3X(unit)) { 8124 if ( BCM_E_NONE != soc_cancun_app_dest_entry_set (unit, SOURCE_VPm, 8125 vp, ENTRY_TYPEf, CANCUN_APP__SOURCE_VP__No_Control_Word, 8126 _BCM_L2GRE_SOURCE_VP_TYPE_VFI)) { 8127 LOG_ERROR(BSL_LS_BCM_L2GRE, 8128 (BSL_META_U(unit,"SOURCE_VP cancun app cfg error\n"))); 8129 } 8130 } 8131 #endif 8132 8133 BCM_GPORT_L2GRE_PORT_ID_SET(l2gre_port->l2gre_port_id, vp); 8134 8135 /* Increment new-port's VP count */ 8136 rv = _bcm_tr3_l2gre_port_cnt_update(unit, l2gre_port->l2gre_port_id, vp, TRUE); 8137 BCM_IF_ERROR_RETURN(rv); 8138 8139 return (soc_reg_field32_modify(unit, L2GRE_DEFAULT_NETWORK_SVPr, 8140 REG_PORT_ANY, SVPf, vp)); 8141 8142 } 8143 8144 /* 8145 * Function: 8146 * _bcm_tr3_l2gre_default_port_delete 8147 * Purpose: 8148 * Delete L2GRE Default port from a VPN 8149 * Parameters: 8150 * unit - (IN) Device Number 8151 * vpn - (IN) VPN instance ID 8152 * l2gre_port_id - (IN) L2gre port information 8153 * Returns: 8154 * BCM_E_XXX 8155 */ 8156 8157 int 8158 _bcm_tr3_l2gre_default_port_delete(int unit, bcm_vpn_t vpn, int vp) 8159 { 8160 source_vp_entry_t svp; 8161 int rv = BCM_E_UNAVAIL; 8162 int vfi_index= -1; 8163 bcm_gport_t l2gre_port_id; 8164 8165 if ( vpn != BCM_L2GRE_VPN_INVALID) { 8166 _BCM_L2GRE_VPN_GET(vfi_index, _BCM_L2GRE_VPN_TYPE_ELAN, vpn); 8167 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeL2Gre)) { 8168 return BCM_E_NOT_FOUND; 8169 } 8170 } 8171 8172 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 8173 return BCM_E_NOT_FOUND; 8174 } 8175 8176 /* Set L2GRE port ID */ 8177 BCM_GPORT_L2GRE_PORT_ID_SET(l2gre_port_id, vp); 8178 8179 /* Clear the SVP and DVP table entries */ 8180 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 8181 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 8182 if (rv < 0) { 8183 return rv; 8184 } 8185 8186 /* Decrement port's VP count */ 8187 rv = _bcm_tr3_l2gre_port_cnt_update(unit, l2gre_port_id, vp, FALSE); 8188 if (rv < 0) { 8189 return rv; 8190 } 8191 8192 /* Free the VP */ 8193 (void) _bcm_vp_free(unit, _bcmVpTypeL2Gre, 1, vp); 8194 8195 rv = soc_reg_field32_modify(unit, L2GRE_DEFAULT_NETWORK_SVPr, 8196 REG_PORT_ANY, SVPf, 0); 8197 return rv; 8198 8199 } 8200 8201 /* 8202 * Function: 8203 * bcm_tr3_l2gre_port_add 8204 * Purpose: 8205 * Add L2GRE port to a VPN 8206 * Parameters: 8207 * unit - (IN) Device Number 8208 * vpn - (IN) VPN instance ID 8209 * l2gre_port - (IN/OUT) l2gre_port information (OUT : l2gre_port_id) 8210 * Returns: 8211 * BCM_E_XXX 8212 */ 8213 8214 int 8215 bcm_tr3_l2gre_port_add(int unit, bcm_vpn_t vpn, bcm_l2gre_port_t *l2gre_port) 8216 { 8217 int mode, rv = BCM_E_PARAM; 8218 uint8 isEline=0xFF; 8219 int vfi_index=0; 8220 int bit_num_dvp = 0, bit_num_svp = 0; 8221 8222 BCM_IF_ERROR_RETURN(bcm_xgs3_l3_egress_mode_get(unit, &mode)); 8223 if (!mode) { 8224 LOG_INFO(BSL_LS_BCM_L3, 8225 (BSL_META_U(unit, 8226 "L3 egress mode must be set first\n"))); 8227 return BCM_E_DISABLED; 8228 } 8229 8230 if (l2gre_port->if_class) { 8231 bit_num_dvp = soc_mem_field_length(unit, EGR_DVP_ATTRIBUTE_1m, L2GRE__CLASS_IDf); 8232 bit_num_svp = soc_mem_field_length(unit, SOURCE_VPm, CLASS_IDf); 8233 if ((l2gre_port->if_class > (( 1 << bit_num_dvp ) - 1)) || 8234 (l2gre_port->if_class > (( 1 << bit_num_svp ) - 1))){ 8235 return BCM_E_PARAM; 8236 } 8237 } 8238 8239 if (l2gre_port->flags & BCM_L2GRE_PORT_NETWORK) { 8240 _BCM_L2GRE_VPN_GET(vfi_index, _BCM_L2GRE_VPN_TYPE_ELINE, vpn); 8241 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeL2Gre)) { 8242 isEline = 0x0; /* ELAN Dont care VPN Case */ 8243 } 8244 } 8245 8246 if (l2gre_port->criteria == BCM_L2GRE_PORT_MATCH_SHARE) { 8247 if (soc_feature(unit, soc_feature_vp_sharing)) { 8248 if (vpn != BCM_L2GRE_VPN_INVALID) { 8249 return BCM_E_PARAM; 8250 } 8251 isEline = 0x0; 8252 } else { 8253 return BCM_E_UNAVAIL; 8254 } 8255 } 8256 8257 #if defined(BCM_TRIDENT3_SUPPORT) 8258 if ((l2gre_port->flags & BCM_L2GRE_PORT_DEFAULT) && 8259 !SOC_REG_IS_VALID(unit, L2GRE_DEFAULT_NETWORK_SVPr)) { 8260 return BCM_E_UNAVAIL; 8261 } 8262 #endif 8263 if ((vpn != BCM_L2GRE_VPN_INVALID) && (isEline != 0x0)) { 8264 BCM_IF_ERROR_RETURN 8265 (_bcm_tr3_l2gre_vpn_is_eline(unit, vpn, &isEline)); 8266 } 8267 8268 if (l2gre_port->flags & BCM_L2GRE_PORT_DEFAULT) { 8269 if (soc_feature(unit, soc_feature_l2gre_default_tunnel)) { 8270 rv = _bcm_tr3_l2gre_default_port_add(unit, l2gre_port); 8271 #if defined(BCM_TRIDENT3_SUPPORT) 8272 if (BCM_SUCCESS(rv) && SOC_REG_IS_VALID(unit, DEFAULT_SVP_ENABLEr)) { 8273 rv = soc_reg_field32_modify 8274 (unit, DEFAULT_SVP_ENABLEr, REG_PORT_ANY, 8275 L2GRE_DEFAULT_SVP_ENABLEf, 1); 8276 if (rv == SOC_E_NOT_FOUND) { 8277 rv = SOC_E_NONE; 8278 } 8279 } 8280 #endif 8281 return rv; 8282 } 8283 } 8284 8285 if (isEline == 0x1 ) { 8286 rv = _bcm_tr3_l2gre_eline_port_add(unit, vpn, l2gre_port); 8287 } else if (isEline == 0x0 ) { 8288 rv = _bcm_tr3_l2gre_elan_port_add(unit, vpn, l2gre_port); 8289 } 8290 8291 return rv; 8292 } 8293 8294 8295 /* 8296 * Function: 8297 * bcm_tr3_l2gre_port_delete 8298 * Purpose: 8299 * Delete L2GRE port from a VPN 8300 * Parameters: 8301 * unit - (IN) Device Number 8302 * vpn - (IN) VPN instance ID 8303 * l2gre_port_id - (IN) l2gre port information 8304 * Returns: 8305 * BCM_E_XXX 8306 */ 8307 8308 int 8309 bcm_tr3_l2gre_port_delete(int unit, bcm_vpn_t vpn, bcm_gport_t l2gre_port_id) 8310 { 8311 int vp; 8312 int rv = BCM_E_UNAVAIL; 8313 uint32 reg_val=0; 8314 uint8 isEline=0; 8315 uint32 stat_counter_id; 8316 int num_ctr = 0; 8317 8318 if (vpn != BCM_L2GRE_VPN_INVALID) { 8319 /* Check for Valid Vpn */ 8320 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_vpn_is_valid(unit, vpn)); 8321 } 8322 8323 vp = BCM_GPORT_L2GRE_PORT_ID_GET(l2gre_port_id); 8324 if (vp == -1) { 8325 return BCM_E_PARAM; 8326 } 8327 8328 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 8329 return BCM_E_NOT_FOUND; 8330 } 8331 8332 /* Check counters before delete port */ 8333 if (bcm_esw_l2gre_stat_id_get(unit, l2gre_port_id, vpn, 8334 bcmL2greOutPackets, &stat_counter_id) == BCM_E_NONE) { 8335 num_ctr++; 8336 } 8337 if (bcm_esw_l2gre_stat_id_get(unit, l2gre_port_id, vpn, 8338 bcmL2greInPackets, &stat_counter_id) == BCM_E_NONE) { 8339 num_ctr++; 8340 } 8341 8342 if (num_ctr != 0) { 8343 return BCM_E_RESOURCE;/* Need detach counters before delete port */ 8344 } 8345 8346 /* Check for L2GRE default port */ 8347 if (SOC_REG_IS_VALID(unit, L2GRE_DEFAULT_NETWORK_SVPr)) { 8348 if (soc_feature(unit, soc_feature_l2gre_default_tunnel)) { 8349 BCM_IF_ERROR_RETURN(READ_L2GRE_DEFAULT_NETWORK_SVPr(unit, ®_val)); 8350 if (vp == soc_reg_field_get(unit, L2GRE_DEFAULT_NETWORK_SVPr, 8351 reg_val, SVPf)) { 8352 rv = _bcm_tr3_l2gre_default_port_delete(unit, vpn, vp); 8353 #if defined(BCM_TRIDENT3_SUPPORT) 8354 if (BCM_SUCCESS(rv) && SOC_REG_IS_VALID(unit, DEFAULT_SVP_ENABLEr)) { 8355 rv = soc_reg_field32_modify 8356 (unit, DEFAULT_SVP_ENABLEr, REG_PORT_ANY, 8357 L2GRE_DEFAULT_SVP_ENABLEf, 0); 8358 if (rv == SOC_E_NOT_FOUND) { 8359 rv = SOC_E_NONE; 8360 } 8361 } 8362 #endif 8363 return rv; 8364 } 8365 } 8366 } 8367 if (vpn != BCM_L2GRE_VPN_INVALID) { 8368 BCM_IF_ERROR_RETURN 8369 (_bcm_tr3_l2gre_vpn_is_eline(unit, vpn, &isEline)); 8370 } else { 8371 isEline = 0; 8372 } 8373 8374 if (isEline == 0x1 ) { 8375 rv = _bcm_tr3_l2gre_eline_port_delete(unit, vpn, vp); 8376 } else if (isEline == 0x0 ) { 8377 rv = _bcm_tr3_l2gre_elan_port_delete(unit, vpn, vp); 8378 } 8379 return rv; 8380 } 8381 8382 /* 8383 * Function: 8384 * bcm_tr3_l2gre_port_delete_all 8385 * Purpose: 8386 * Delete all L2GRE ports from a VPN 8387 * Parameters: 8388 * unit - (IN) Device Number 8389 * vpn - (IN) VPN instance ID 8390 * Returns: 8391 * BCM_E_XXX 8392 */ 8393 int 8394 bcm_tr3_l2gre_port_delete_all(int unit, bcm_vpn_t vpn) 8395 { 8396 int rv = BCM_E_NONE; 8397 int vfi_index; 8398 int vp1 = 0, vp2 = 0; 8399 uint8 isEline=0xFF; 8400 bcm_gport_t l2gre_port_id; 8401 uint32 reg_val=0; 8402 8403 BCM_IF_ERROR_RETURN 8404 (_bcm_tr3_l2gre_vpn_is_eline(unit, vpn, &isEline)); 8405 8406 if (isEline == 0x1 ) { 8407 if ( vpn != BCM_L2GRE_VPN_INVALID) { 8408 _BCM_L2GRE_VPN_GET(vfi_index, _BCM_L2GRE_VPN_TYPE_ELINE, vpn); 8409 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeL2Gre)) { 8410 return BCM_E_NOT_FOUND; 8411 } 8412 } else { 8413 vfi_index = _BCM_L2GRE_VFI_INVALID; 8414 } 8415 8416 /* ---- Read in current table values for VP1 and VP2 ----- */ 8417 (void) _bcm_tr3_l2gre_eline_vp_map_get (unit, vfi_index, &vp1, &vp2); 8418 if (vp1 != 0) { 8419 rv = _bcm_tr3_l2gre_eline_port_delete(unit, vpn, vp1); 8420 BCM_IF_ERROR_RETURN(rv); 8421 } 8422 if (vp2 != 0) { 8423 rv = _bcm_tr3_l2gre_eline_port_delete(unit, vpn, vp2); 8424 BCM_IF_ERROR_RETURN(rv); 8425 } 8426 } else if (isEline == 0x0 ) { 8427 uint32 vfi, vp, num_vp; 8428 source_vp_entry_t svp; 8429 8430 _BCM_L2GRE_VPN_GET(vfi, _BCM_L2GRE_VPN_TYPE_ELAN, vpn); 8431 if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeL2Gre)) { 8432 rv = BCM_E_NOT_FOUND; 8433 return rv; 8434 } 8435 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 8436 for (vp = 0; vp < num_vp; vp++) { 8437 /* Check for the validity of the VP */ 8438 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 8439 continue; 8440 } 8441 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 8442 if (rv < 0) { 8443 return rv; 8444 } 8445 if (SOC_REG_IS_VALID(unit, L2GRE_DEFAULT_NETWORK_SVPr)) { 8446 if (soc_feature(unit, soc_feature_l2gre_default_tunnel)) { 8447 BCM_IF_ERROR_RETURN(READ_L2GRE_DEFAULT_NETWORK_SVPr(unit, ®_val)); 8448 if (vp == soc_reg_field_get(unit, L2GRE_DEFAULT_NETWORK_SVPr, 8449 reg_val, SVPf)) { 8450 rv = _bcm_tr3_l2gre_default_port_delete(unit, vpn, vp); 8451 if (rv < 0) { 8452 return rv; 8453 } 8454 #if defined(BCM_TRIDENT3_SUPPORT) 8455 if (SOC_REG_IS_VALID(unit, DEFAULT_SVP_ENABLEr)) { 8456 rv = (soc_reg_field32_modify 8457 (unit, DEFAULT_SVP_ENABLEr, REG_PORT_ANY, L2GRE_DEFAULT_SVP_ENABLEf, 0)); 8458 if (BCM_FAILURE(rv)) { 8459 if (rv != BCM_E_NOT_FOUND) { 8460 return rv; 8461 } else { 8462 rv = BCM_E_NONE; 8463 } 8464 } 8465 } 8466 #endif 8467 } 8468 } 8469 } 8470 if ((soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0x1 && 8471 vfi == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf)) 8472 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 8473 || SHR_BITGET(VIRTUAL_INFO(unit)->vp_shared_vp_bitmap, vp) 8474 #endif 8475 ) { 8476 /* Set L2GRE port ID */ 8477 BCM_GPORT_L2GRE_PORT_ID_SET(l2gre_port_id, vp); 8478 rv = bcm_tr3_l2gre_port_delete(unit, vpn, l2gre_port_id); 8479 if (rv < 0) { 8480 return rv; 8481 } 8482 } 8483 } 8484 } 8485 return rv; 8486 } 8487 8488 /* 8489 * Function: 8490 * bcm_tr3_l2gre_port_get 8491 * Purpose: 8492 * Get an L2GRE port from a VPN 8493 * Parameters: 8494 * unit - (IN) Device Number 8495 * vpn - (IN) VPN instance ID 8496 * l2gre_port - (IN/OUT) l2gre port information 8497 */ 8498 int 8499 bcm_tr3_l2gre_port_get(int unit, bcm_vpn_t vpn, bcm_l2gre_port_t *l2gre_port) 8500 { 8501 int vp; 8502 int rv = BCM_E_NONE; 8503 8504 if (vpn != BCM_L2GRE_VPN_INVALID) { 8505 /* Check for Valid Vpn */ 8506 BCM_IF_ERROR_RETURN(_bcm_tr3_l2gre_vpn_is_valid(unit, vpn)); 8507 } 8508 vp = BCM_GPORT_L2GRE_PORT_ID_GET(l2gre_port->l2gre_port_id); 8509 if (vp == -1) { 8510 return BCM_E_PARAM; 8511 } 8512 8513 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 8514 return BCM_E_NOT_FOUND; 8515 } 8516 8517 rv = _bcm_tr3_l2gre_port_get(unit, vpn, vp, l2gre_port); 8518 return rv; 8519 } 8520 8521 /* 8522 * Function: 8523 * bcm_tr3_l2gre_port_get_all 8524 * Purpose: 8525 * Get all L2GRE ports from a VPN 8526 * Parameters: 8527 * unit - (IN) Device Number 8528 * vpn - (IN) VPN instance ID 8529 * port_max - (IN) Maximum number of interfaces in array 8530 * port_array - (OUT) Array of L2GRE ports 8531 * port_count - (OUT) Number of interfaces returned in array 8532 */ 8533 int 8534 bcm_tr3_l2gre_port_get_all(int unit, bcm_vpn_t vpn, int port_max, 8535 bcm_l2gre_port_t *port_array, int *port_count) 8536 { 8537 int vp, rv = BCM_E_NONE; 8538 int vfi_index; 8539 int vp1 = 0, vp2 = 0; 8540 uint8 isEline=0xFF; 8541 SHR_BITDCL *share_vp_bitmap = NULL; 8542 8543 BCM_IF_ERROR_RETURN 8544 (_bcm_tr3_l2gre_vpn_is_eline(unit, vpn, &isEline)); 8545 8546 *port_count = 0; 8547 8548 if (isEline == 0x1 ) { 8549 if ( vpn != BCM_L2GRE_VPN_INVALID) { 8550 _BCM_L2GRE_VPN_GET(vfi_index, _BCM_L2GRE_VPN_TYPE_ELAN, vpn); 8551 if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeL2Gre)) { 8552 return BCM_E_NOT_FOUND; 8553 } 8554 } else { 8555 vfi_index = _BCM_L2GRE_VFI_INVALID; 8556 } 8557 8558 /* ---- Read in current table values for VP1 and VP2 ----- */ 8559 (void) _bcm_tr3_l2gre_eline_vp_map_get (unit, vfi_index, &vp1, &vp2); 8560 vp = vp1; 8561 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 8562 if (*port_count < port_max) { 8563 rv = _bcm_tr3_l2gre_port_get(unit, vpn, vp, 8564 &port_array[*port_count]); 8565 if (rv < 0) { 8566 return rv; 8567 } 8568 (*port_count)++; 8569 } 8570 } 8571 8572 vp = vp2; 8573 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 8574 if (*port_count < port_max) { 8575 rv = _bcm_tr3_l2gre_port_get(unit, vpn, vp, 8576 &port_array[*port_count]); 8577 if (rv < 0) { 8578 return rv; 8579 } 8580 (*port_count)++; 8581 } 8582 } 8583 } else if (isEline == 0x0 ) { 8584 uint32 vfi, entry_type; 8585 int num_vp; 8586 source_vp_entry_t svp; 8587 8588 _BCM_L2GRE_VPN_GET(vfi, _BCM_L2GRE_VPN_TYPE_ELAN, vpn); 8589 if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeL2Gre)) { 8590 rv = BCM_E_NOT_FOUND; 8591 return rv; 8592 } 8593 8594 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 8595 /*get sharing VP bitmap*/ 8596 share_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), "sharr_vp_bitmap"); 8597 if (share_vp_bitmap == NULL) { 8598 return BCM_E_MEMORY; 8599 } 8600 sal_memset(share_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp)); 8601 8602 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 8603 if (soc_feature(unit, soc_feature_vp_sharing)) { 8604 rv = bcm_tr3_share_vp_get(unit, vpn, share_vp_bitmap); 8605 _BCM_L2GRE_CLEANUP(rv) 8606 } 8607 #endif 8608 for (vp = 0; vp < num_vp; vp++) { 8609 /* Check for the validity of the VP */ 8610 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 8611 continue; 8612 } 8613 if (*port_count == port_max) { 8614 break; 8615 } 8616 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 8617 _BCM_L2GRE_CLEANUP(rv) 8618 entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf); 8619 8620 if ((vfi == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf) && 8621 entry_type == _BCM_L2GRE_SOURCE_VP_TYPE_VFI) 8622 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 8623 || SHR_BITGET(share_vp_bitmap, vp) 8624 #endif 8625 8626 ) { 8627 /* Check if number of ports is requested */ 8628 if (0 == port_max) { 8629 (*port_count)++; 8630 continue; 8631 } else if (*port_count == port_max) { 8632 break; 8633 } 8634 8635 rv = _bcm_tr3_l2gre_port_get(unit, vpn, vp, 8636 &port_array[*port_count]); 8637 _BCM_L2GRE_CLEANUP(rv) 8638 (*port_count)++; 8639 } 8640 } 8641 sal_free(share_vp_bitmap); 8642 } 8643 return rv; 8644 cleanup: 8645 sal_free(share_vp_bitmap); 8646 return rv; 8647 8648 } 8649 8650 /* 8651 * Function: 8652 * bcm_tr3_l2gre_port_learn_set 8653 * Purpose: 8654 * Set the CML bits for a l2gre port. 8655 * Returns: 8656 * BCM_E_XXX 8657 */ 8658 int 8659 bcm_tr3_l2gre_port_learn_set(int unit, bcm_gport_t l2gre_port_id, 8660 uint32 flags) 8661 { 8662 int cml, rv = BCM_E_NONE, entry_type; 8663 uint32 vp; 8664 source_vp_entry_t svp; 8665 8666 rv = _bcm_l2gre_check_init(unit); 8667 if (rv != BCM_E_NONE){ 8668 return rv; 8669 } 8670 8671 cml = 0; 8672 if (!(flags & BCM_PORT_LEARN_FWD)) { 8673 cml |= (1 << 0); 8674 } 8675 if (flags & BCM_PORT_LEARN_CPU) { 8676 cml |= (1 << 1); 8677 } 8678 if (flags & BCM_PORT_LEARN_PENDING) { 8679 cml |= (1 << 2); 8680 } 8681 if (flags & BCM_PORT_LEARN_ARL) { 8682 cml |= (1 << 3); 8683 } 8684 8685 /* Get the VP index from the gport */ 8686 vp = BCM_GPORT_L2GRE_PORT_ID_GET(l2gre_port_id); 8687 8688 MEM_LOCK(unit, SOURCE_VPm); 8689 /* Be sure the entry is used and is set for L2GRE */ 8690 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 8691 MEM_UNLOCK(unit, SOURCE_VPm); 8692 return BCM_E_NOT_FOUND; 8693 } 8694 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 8695 if (rv < 0) { 8696 MEM_UNLOCK(unit, SOURCE_VPm); 8697 return rv; 8698 } 8699 8700 /* Ensure that the entry_type is 1 for L2GRE */ 8701 entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf); 8702 if (entry_type != 1){ 8703 MEM_UNLOCK(unit, SOURCE_VPm); 8704 return BCM_E_NOT_FOUND; 8705 } 8706 8707 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml); 8708 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml); 8709 /* coverity[negative_returns : FALSE] */ 8710 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 8711 MEM_UNLOCK(unit, SOURCE_VPm); 8712 8713 return rv; 8714 } 8715 8716 /* 8717 * Function: 8718 * bcm_tr3_l2gre_port_learn_get 8719 * Purpose: 8720 * Get the CML bits for a L2GRE port 8721 * Returns: 8722 * BCM_E_XXX 8723 */ 8724 int 8725 bcm_tr3_l2gre_port_learn_get(int unit, bcm_gport_t l2gre_port_id, 8726 uint32 *flags) 8727 { 8728 int rv, vp, cml = 0, entry_type; 8729 source_vp_entry_t svp; 8730 8731 rv = _bcm_l2gre_check_init(unit); 8732 if (rv != BCM_E_NONE){ 8733 return rv; 8734 } 8735 8736 /* Get the VP index from the gport */ 8737 vp = BCM_GPORT_L2GRE_PORT_ID_GET(l2gre_port_id); 8738 if (vp == -1) { 8739 return BCM_E_PARAM; 8740 } 8741 8742 /* Be sure the entry is used and is set for L2GRE */ 8743 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 8744 return BCM_E_NOT_FOUND; 8745 } 8746 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 8747 if (rv < 0) { 8748 return rv; 8749 } 8750 8751 /* Ensure that the entry_type is 1 for L2GRE */ 8752 entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf); 8753 if (entry_type != 1){ 8754 return BCM_E_NOT_FOUND; 8755 } 8756 8757 cml = soc_SOURCE_VPm_field32_get(unit, &svp, CML_FLAGS_NEWf); 8758 8759 *flags = 0; 8760 if (!(cml & (1 << 0))) { 8761 *flags |= BCM_PORT_LEARN_FWD; 8762 } 8763 if (cml & (1 << 1)) { 8764 *flags |= BCM_PORT_LEARN_CPU; 8765 } 8766 if (cml & (1 << 2)) { 8767 *flags |= BCM_PORT_LEARN_PENDING; 8768 } 8769 if (cml & (1 << 3)) { 8770 *flags |= BCM_PORT_LEARN_ARL; 8771 } 8772 8773 return BCM_E_NONE; 8774 } 8775 8776 /* 8777 * Function: 8778 * bcm_tr3_l2gre_trunk_member_add 8779 * Purpose: 8780 * Activate Trunk Port-membership from 8781 * EGR_PORT_TO_NHI_MAPPING or EGR_DGPP_TO_NHI 8782 * Parameters: 8783 * unit - (IN) Device Number 8784 * tgid - (IN) Trunk Group ID 8785 * trunk_member_count - (IN) Count of Trunk members to be added 8786 * trunk_member_array - (IN) Trunk member ports to be added 8787 */ 8788 int 8789 bcm_tr3_l2gre_trunk_member_add(int unit, bcm_trunk_t trunk_id, 8790 int trunk_member_count, bcm_port_t *trunk_member_array) 8791 { 8792 int idx = 0; 8793 int rv = BCM_E_NONE; 8794 int nh_index = 0, old_nh_index = -1; 8795 bcm_l3_egress_t egr; 8796 int gport = 0; 8797 int modid = 0; 8798 int local_member = 0; 8799 8800 rv = _bcm_trunk_id_validate(unit, trunk_id); 8801 if (BCM_FAILURE(rv)) { 8802 return BCM_E_PORT; 8803 } 8804 8805 /* Obtain nh_index for trunk_id */ 8806 rv = _bcm_xgs3_trunk_nh_store_get(unit, trunk_id, &nh_index); 8807 if (nh_index == 0) { 8808 return rv; 8809 } 8810 bcm_l3_egress_t_init(&egr); 8811 BCM_IF_ERROR_RETURN(bcm_tr3_l2gre_egress_get(unit, &egr, nh_index)); 8812 if (egr.flags & BCM_L3_L2GRE_ONLY) { 8813 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 8814 for (idx = 0; idx < trunk_member_count; idx++) { 8815 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 8816 if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) { 8817 gport = trunk_member_array[idx]; 8818 } else 8819 #endif 8820 { 8821 rv = bcm_esw_port_local_get(unit, trunk_member_array[idx], &local_member); 8822 /* Only support trunk local ports */ 8823 if(BCM_FAILURE(rv)) { 8824 continue; 8825 } 8826 BCM_GPORT_MODPORT_SET(gport, modid, local_member); 8827 } 8828 BCM_IF_ERROR_RETURN( 8829 _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index)); 8830 if (!old_nh_index) { 8831 BCM_IF_ERROR_RETURN( 8832 _bcm_trx_gport_to_nhi_set(unit, gport, nh_index)); 8833 } 8834 } 8835 } 8836 return BCM_E_NONE; 8837 } 8838 8839 /* 8840 * Function: 8841 * bcm_tr3_l2gre_trunk_member_delete 8842 * Purpose: 8843 * Clear Trunk Port-membership from 8844 * EGR_PORT_TO_NHI_MAPPING or EGR_DGPP_TO_NHI 8845 * Parameters: 8846 * unit - (IN) Device Number 8847 * tgid - (IN) Trunk Group ID 8848 * trunk_member_count - (IN) Count of Trunk members to be deleted 8849 * trunk_member_array - (IN) Trunk member ports to be deleted 8850 */ 8851 int 8852 bcm_tr3_l2gre_trunk_member_delete(int unit, bcm_trunk_t trunk_id, 8853 int trunk_member_count, bcm_port_t *trunk_member_array) 8854 { 8855 int idx = 0; 8856 int rv = BCM_E_NONE, rv2 = BCM_E_NONE; 8857 int old_nh_index = 0; 8858 int nh_index = 0; 8859 bcm_l3_egress_t egr; 8860 int gport = 0; 8861 bcm_trunk_t local_tgid; 8862 int local_id; 8863 bcm_port_t port; 8864 bcm_module_t my_modid; 8865 8866 rv = _bcm_trunk_id_validate(unit, trunk_id); 8867 if (BCM_FAILURE(rv)) { 8868 return BCM_E_PORT; 8869 } 8870 8871 /* Obtain nh_index for trunk_id */ 8872 rv = _bcm_xgs3_trunk_nh_store_get(unit, trunk_id, &nh_index); 8873 if (nh_index == 0) { 8874 for (idx = 0; idx < trunk_member_count; idx++) { 8875 rv2 = _bcm_esw_gport_resolve(unit, trunk_member_array[idx], 8876 &my_modid, &port, &local_tgid, 8877 &local_id); 8878 if(BCM_FAILURE(rv2)) { 8879 rv += rv2; 8880 continue; 8881 } 8882 rv += _bcm_tr3_l2gre_trunk_table_reset(unit, port, trunk_id, 8883 my_modid); 8884 } 8885 if (BCM_FAILURE(rv)) { 8886 return rv; 8887 } 8888 } else { 8889 bcm_l3_egress_t_init(&egr); 8890 BCM_IF_ERROR_RETURN(bcm_tr3_l2gre_egress_get(unit, &egr, nh_index)); 8891 8892 if (egr.flags & BCM_L3_L2GRE_ONLY) { 8893 for (idx = 0; idx < trunk_member_count; idx++) { 8894 gport = trunk_member_array[idx]; 8895 BCM_IF_ERROR_RETURN( 8896 _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index)); 8897 if (old_nh_index) { 8898 BCM_IF_ERROR_RETURN( 8899 _bcm_trx_gport_to_nhi_set(unit, gport, 0)); 8900 } 8901 } 8902 } 8903 } 8904 return rv; 8905 } 8906 8907 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 8908 /* 8909 * Function: 8910 * _bcm_tr3_l2gre_sw_dump 8911 * Purpose: 8912 * Displays TR3 L2GRE information maintained by software. 8913 * Parameters: 8914 * unit - Device unit number 8915 * Returns: 8916 * None 8917 */ 8918 void 8919 _bcm_tr3_l2gre_sw_dump(int unit) 8920 { 8921 int i, num_vp; 8922 _bcm_tr3_l2gre_bookkeeping_t *l2gre_info = L2GRE_INFO(unit); 8923 8924 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 8925 8926 LOG_CLI((BSL_META_U(unit, 8927 "Tunnel Initiator Endpoints:\n"))); 8928 for (i = 0; i < num_vp; i++) { 8929 if (L2GRE_INFO(unit)->l2gre_tunnel_init[i].dip != 0 && 8930 L2GRE_INFO(unit)->l2gre_tunnel_init[i].sip != 0 ) { 8931 LOG_CLI((BSL_META_U(unit, 8932 "Tunnel idx:%d, sip:%x, dip:%x\n"), i, 8933 l2gre_info->l2gre_tunnel_init[i].sip, 8934 l2gre_info->l2gre_tunnel_init[i].dip)); 8935 } 8936 } 8937 8938 LOG_CLI((BSL_META_U(unit, 8939 "Tunnel Terminator Endpoints:\n"))); 8940 for (i = 0; i < num_vp; i++) { 8941 if (L2GRE_INFO(unit)->l2gre_tunnel_term[i].dip != 0 && 8942 L2GRE_INFO(unit)->l2gre_tunnel_term[i].sip != 0 ) { 8943 LOG_CLI((BSL_META_U(unit, 8944 "Tunnel idx:%d, sip:%x, dip:%x\n"), i, 8945 l2gre_info->l2gre_tunnel_term[i].sip, 8946 l2gre_info->l2gre_tunnel_term[i].dip)); 8947 } 8948 } 8949 8950 LOG_CLI((BSL_META_U(unit, "Match Info: \n"))); 8951 8952 for (i = 0; i < num_vp; i++) { 8953 _bcm_l2gre_match_port_info_t *key = &l2gre_info->match_key[i]; 8954 8955 if ((key->trunk_id == -1) && (key->modid == -1) && 8956 (key->port == 0) && (key->flags == 0)) { 8957 continue; 8958 } 8959 8960 LOG_CLI((BSL_META_U(unit, "L2GRE port vp = %d, "), i)); 8961 LOG_CLI((BSL_META_U(unit, "Flags = %x, "), key->flags)); 8962 LOG_CLI((BSL_META_U(unit, "Index = %x, "), key->index)); 8963 LOG_CLI((BSL_META_U(unit, "TGID = %d, "), key->trunk_id)); 8964 LOG_CLI((BSL_META_U(unit, "Modid = %d, "), key->modid)); 8965 LOG_CLI((BSL_META_U(unit, "Port = %d, "), key->port)); 8966 LOG_CLI((BSL_META_U(unit, "Match VLAN = %d, "), key->match_vlan)); 8967 LOG_CLI((BSL_META_U(unit, "Match Inner VLAN = %d, "), 8968 key->match_inner_vlan)); 8969 LOG_CLI((BSL_META_U(unit, "Match VPNid = %d, "), 8970 key->match_vpnid)); 8971 LOG_CLI((BSL_META_U(unit, "Match Tunnel Index = %x\n"), 8972 key->match_tunnel_index)); 8973 } 8974 8975 return; 8976 } 8977 #endif 8978 8979 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */ 8980