flexflow_init.c (28665B)
1 /* 2 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 3 * 4 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 5 */ 6 7 8 #include <sal/core/libc.h> 9 #if defined(INCLUDE_L3) 10 11 #include <soc/drv.h> 12 #include <soc/scache.h> 13 #include <bcm/error.h> 14 #include <bcm/module.h> 15 #include <bcm_int/esw/trx.h> 16 #include <bcm_int/esw/xgs5.h> 17 #include <bcm_int/esw/flow.h> 18 #include <bcm_int/esw/switch.h> 19 #include <soc/esw/flow_db_core.h> 20 #include <bcm_int/esw/virtual.h> 21 22 _bcm_flow_bookkeeping_t *_bcm_flow_bk_info[BCM_MAX_NUM_UNITS] = { 0 }; 23 24 #define VIRTUAL_INFO(_unit_) (&_bcm_virtual_bk_info[_unit_]) 25 #define L3_INFO(_unit_) (&_bcm_l3_bk_info[_unit_]) 26 27 /* 28 * Function: 29 * _bcm_td3_flow_free_resource 30 * Purpose: 31 * Free all allocated software resources 32 * Parameters: 33 * unit - SOC unit number 34 * Returns: 35 * Nothing 36 */ 37 38 STATIC void 39 _bcm_td3_flow_free_resource(int unit) 40 { 41 _bcm_flow_bookkeeping_t *flow_info = FLOW_INFO(unit); 42 43 /* If software tables were not allocated we are done. */ 44 if (NULL == FLOW_INFO(unit)) { 45 return; 46 } 47 48 /* Destroy EGR_DVP_ATTRIBUTE usage bitmap */ 49 if (flow_info->dvp_attr_bitmap) { 50 sal_free(flow_info->dvp_attr_bitmap); 51 flow_info->dvp_attr_bitmap = NULL; 52 } 53 54 /* Destroy soft init tunnel table */ 55 if (flow_info->init_tunnel) { 56 sal_free(flow_info->init_tunnel); 57 flow_info->init_tunnel = NULL; 58 } 59 60 /* Destroy iif_ref_cnt table */ 61 if (flow_info->iif_ref_cnt) { 62 sal_free(flow_info->iif_ref_cnt); 63 flow_info->iif_ref_cnt = NULL; 64 } 65 66 /* Destroy vp_ref_cnt table */ 67 if (flow_info->vp_ref_cnt) { 68 sal_free(flow_info->vp_ref_cnt); 69 flow_info->vp_ref_cnt = NULL; 70 } 71 72 /* 73 if (flow_info->flow_tunnel_term) { 74 sal_free(flow_info->flow_tunnel_term); 75 flow_info->flow_tunnel_term = NULL; 76 } 77 */ 78 79 if (flow_info->flow_vpn_vlan) { 80 sal_free(flow_info->flow_vpn_vlan); 81 flow_info->flow_vpn_vlan = NULL; 82 } 83 84 if (flow_info->match_key) { 85 sal_free(flow_info->match_key); 86 flow_info->match_key = NULL; 87 } 88 89 /* Free module data. */ 90 sal_free(FLOW_INFO(unit)); 91 FLOW_INFO(unit) = NULL; 92 } 93 /* 94 * Function: 95 * bcm_td3_flow_allocate_bk 96 * Purpose: 97 * Initialize FLOW software book-kepping 98 * Parameters: 99 * unit - Device Number 100 * Returns: 101 * BCM_E_XXX 102 */ 103 104 STATIC int 105 bcm_td3_flow_allocate_bk(int unit) 106 { 107 /* Allocate/Init unit software tables. */ 108 if (NULL == FLOW_INFO(unit)) { 109 BCM_TD3_FLOW_ALLOC(FLOW_INFO(unit), sizeof(_bcm_flow_bookkeeping_t), 110 "flow_bk_module_data"); 111 if (NULL == FLOW_INFO(unit)) { 112 return (BCM_E_MEMORY); 113 } else { 114 FLOW_INFO(unit)->initialized = FALSE; 115 } 116 } 117 return BCM_E_NONE; 118 } 119 120 /* 121 * Function: 122 * _bcm_td3_flow_hw_clear 123 * Purpose: 124 * Free all allocated hardware resources 125 * Parameters: 126 * unit - SOC unit number 127 * Returns: 128 * BCM_E_XXX 129 */ 130 131 STATIC int 132 _bcm_td3_flow_hw_clear(int unit) 133 { 134 int rv = BCM_E_NONE, rv1 = BCM_E_NONE; 135 136 rv = bcmi_esw_flow_tunnel_terminator_destroy_all(unit); 137 if (BCM_FAILURE(rv)) { 138 rv1 = rv; 139 } 140 141 rv = bcmi_esw_flow_tunnel_initiator_destroy_all(unit); 142 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv1)) { 143 rv1 = rv; 144 } 145 146 rv = bcmi_esw_flow_vpn_destroy_all(unit); 147 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv1)) { 148 rv1 = rv; 149 } 150 151 152 return rv1; 153 } 154 155 #ifdef BCM_WARM_BOOT_SUPPORT 156 157 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1, 0) 158 #define BCM_WB_VERSION_2_0 SOC_SCACHE_VERSION(2, 0) 159 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_2_0 160 161 STATIC int _bcm_flow_wb_alloc(int unit); 162 163 /* 164 * Function: 165 * _bcm_flow_wb_recover 166 * 167 * Purpose: 168 * Recover VXLAN module info for Level 2 Warm Boot from persisitent memory 169 * 170 * Warm Boot Version Map: 171 * see _bcm_esw_flow_sync definition 172 * 173 * Parameters: 174 * unit - (IN) Device Unit Number. 175 * 176 * Returns: 177 * BCM_E_XXX 178 */ 179 STATIC int 180 _bcm_flow_wb_recover(int unit) 181 { 182 int sz = 0, rv = BCM_E_NONE; 183 int num_dvp = 0; 184 int num_iif; 185 int num_vp; 186 int stable_size; 187 uint16 recovered_ver = 0; 188 uint8 *flow_scache_ptr = NULL; 189 soc_scache_handle_t scache_handle; 190 _bcm_flow_bookkeeping_t *flow_info; 191 int num_soft_tnl = 0; 192 int i; 193 int additional_scache_size = 0; 194 195 flow_info = FLOW_INFO(unit); 196 197 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 198 199 /* Requires extended scache support level-2 warmboot */ 200 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 201 return BCM_E_NONE; 202 } 203 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FLOW, 0); 204 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 205 0, &flow_scache_ptr, 206 BCM_WB_DEFAULT_VERSION, &recovered_ver); 207 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 208 return rv; 209 } else if (rv == BCM_E_NOT_FOUND) { 210 return _bcm_flow_wb_alloc(unit); 211 } 212 213 if (flow_scache_ptr != NULL) { 214 num_dvp = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm); 215 num_soft_tnl = num_dvp + soc_mem_index_count(unit, EGR_L3_INTFm); 216 sz = sizeof(uint16); /* idx of _bcm_flow_init_tunnel_entry_t */ 217 218 /* recover init_tunnel state */ 219 for (i = 0; i < num_soft_tnl; i++) { 220 sal_memcpy(&flow_info->init_tunnel[i].idx, flow_scache_ptr, sz); 221 flow_scache_ptr += sz; 222 } 223 224 /* recover the dvp_attr_bitmap */ 225 sz = SHR_BITALLOCSIZE(num_dvp); 226 sal_memcpy(flow_info->dvp_attr_bitmap,flow_scache_ptr,sz); 227 flow_scache_ptr += sz; 228 229 num_iif = soc_mem_index_count(unit, L3_IIFm); 230 sz = sizeof(uint16); /* iif_ref_cnt */ 231 for (i = 0; i < num_iif; i++) { 232 sal_memcpy(&flow_info->iif_ref_cnt[i], flow_scache_ptr, sz); 233 flow_scache_ptr += sz; 234 } 235 236 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 237 sz = sizeof(uint16); /* vp_ref_cnt */ 238 for (i = 0; i < num_vp; i++) { 239 sal_memcpy(&flow_info->vp_ref_cnt[i], flow_scache_ptr, sz); 240 flow_scache_ptr += sz; 241 } 242 243 /* recover the memory usage reference count table */ 244 sz = sizeof(uint32); 245 for (i = 0; i < _BM_FLOW_MEM_USE_MAX; i++) { 246 sal_memcpy(&flow_info->mem_use_cnt[i], flow_scache_ptr, sz); 247 flow_scache_ptr += sz; 248 } 249 250 sz = sizeof(bcm_flow_match_vp_t); 251 if (recovered_ver >= BCM_WB_VERSION_2_0) { 252 for (i = 0; i < num_vp; i++) { 253 sal_memcpy(&flow_info->match_key[i], flow_scache_ptr, sz); 254 flow_scache_ptr += sz; 255 } 256 } else { 257 additional_scache_size += num_vp * sz; 258 } 259 260 /* Reallocate additional scache size if current scache requirement 261 * is more than the one recovered. 262 */ 263 if (additional_scache_size > 0) { 264 rv = soc_scache_realloc(unit,scache_handle,additional_scache_size); 265 if(BCM_FAILURE(rv)) { 266 return rv; 267 } 268 } 269 } 270 return BCM_E_NONE; 271 } 272 273 /* 274 * Function: 275 * _bcm_flow_wb_alloc 276 * 277 * Purpose: 278 * Alloc persisitent memory for Level 2 Warm Boot scache. 279 * 280 * Parameters: 281 * unit - (IN) Device Unit Number. 282 * 283 * Returns: 284 * BCM_E_XXX 285 */ 286 287 STATIC int 288 _bcm_flow_wb_alloc(int unit) 289 { 290 int alloc_sz = 0, rv = BCM_E_NONE; 291 soc_scache_handle_t scache_handle; 292 int num_soft_tnl = 0, num_dvp = 0; 293 uint8 *flow_scache_ptr = NULL; 294 int stable_size; 295 int num_iif; 296 int num_vp; 297 298 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 299 300 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 301 return BCM_E_NONE; 302 } 303 304 /* init tunnel entry table size */ 305 num_dvp = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm); 306 num_soft_tnl = num_dvp + soc_mem_index_count(unit, EGR_L3_INTFm); 307 /* num_soft_tnl * idx of _bcm_flow_init_tunnel_entry_t */ 308 alloc_sz = num_soft_tnl * sizeof(uint16); 309 310 /* dvp_attr_bitmap size */ 311 alloc_sz += SHR_BITALLOCSIZE(num_dvp); 312 313 /* iif_ref_cnt table size */ 314 num_iif = soc_mem_index_count(unit, L3_IIFm); 315 /* num_iif * iif_ref_cnt */ 316 alloc_sz += num_iif * sizeof(uint16); 317 318 /* vp_ref_cnt table size */ 319 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 320 /* num_vp * vp_ref_cnt */ 321 alloc_sz += num_vp * sizeof(uint16); 322 323 /* mem_use_cnt table size */ 324 alloc_sz += _BM_FLOW_MEM_USE_MAX * sizeof(uint32); 325 326 /*match_key array size from BCM_WB_VERSION_2_0*/ 327 alloc_sz += num_vp * sizeof(bcm_flow_match_vp_t); 328 329 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FLOW, 0); 330 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 331 alloc_sz, (uint8**)&flow_scache_ptr, 332 BCM_WB_DEFAULT_VERSION, NULL); 333 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 334 return rv; 335 } 336 337 return BCM_E_NONE; 338 } 339 340 /* 341 * Function: 342 * _bcm_flow_next_hop_refcnt_restore 343 * Purpose: 344 * Recover the next hop egress object reference count increased by 345 * bcm_flow_port_encap_set when attaching the object to the flow port. 346 * This routine is only used in warmboot. 347 * 348 * Parameters: 349 * unit - Device Number 350 * Returns: 351 * BCM_E_XXX 352 */ 353 STATIC int 354 _bcm_flow_next_hop_refcnt_restore(int unit) 355 { 356 int num_vp; 357 ing_dvp_table_entry_t dvp; 358 int vp; 359 int nh_index; 360 int ecmp; 361 int ecmp_index; 362 int width; 363 364 /* restore nextHop reference count set by flow_port_encap_set */ 365 num_vp = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm); 366 for (vp = 1; vp < num_vp; vp++) { 367 if (_BCM_FLOW_EGR_DVP_USED_GET(unit,vp)) { 368 SOC_IF_ERROR_RETURN(READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, 369 vp, &dvp)); 370 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 371 NEXT_HOP_INDEXf); 372 ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 373 ECMPf); 374 ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf); 375 if (ecmp) { 376 width = BCM_XGS3_L3_MAX_ECMP_MODE(unit) ? 377 _BCM_SINGLE_WIDE : _BCM_DOUBLE_WIDE; 378 379 /* increment ecmp group reference count. */ 380 BCM_XGS3_L3_ENT_REF_CNT_INC 381 (BCM_XGS3_L3_TBL_PTR(unit, ecmp_grp), ecmp_index, width); 382 383 } else if (nh_index) { 384 BCM_XGS3_L3_ENT_REF_CNT_INC(BCM_XGS3_L3_TBL_PTR(unit, next_hop), 385 nh_index, _BCM_SINGLE_WIDE); 386 387 } 388 } 389 } 390 return BCM_E_NONE; 391 } 392 393 STATIC int 394 _bcm_flow_encap_traverse_cb_tpid_refcnt(int unit, 395 bcm_flow_encap_config_t *info, uint32 num_of_fields, 396 bcm_flow_logical_field_t *field, 397 void *user_data) 398 { 399 int rv; 400 int tpid_inx; 401 402 if (info->flags & (BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_TPID_REPLACE | 403 BCM_FLOW_ENCAP_FLAG_VLAN_PRI_TPID_REPLACE | 404 BCM_FLOW_ENCAP_FLAG_TPID_REPLACE | 405 BCM_FLOW_ENCAP_FLAG_SERVICE_VLAN_ADD) ) { 406 /* tpid reference count */ 407 if (info->flags & _BCM_FLOW_ENCAP_FLAG_TPID_INDEX) { 408 tpid_inx = info->tpid; 409 (void)_bcm_fb2_outer_tpid_tab_ref_count_add(unit,tpid_inx,1); 410 } else if (info->tpid) { 411 rv = _bcm_fb2_outer_tpid_lkup(unit,info->tpid, &tpid_inx); 412 if (BCM_SUCCESS(rv)) { 413 (void)_bcm_fb2_outer_tpid_tab_ref_count_add(unit,tpid_inx,1); 414 } 415 } 416 } 417 return BCM_E_NONE; 418 } 419 /* 420 * Function: 421 * _bcm_flow_egr_mac_da_restore 422 * Purpose: 423 * WB recovery for egr mac da profile ref count 424 * Parameters: 425 * unit - (IN) Device Number 426 * ecmp_nh_index - (IN) ecmp group number 427 * Returns: 428 * BCM_E_XXX 429 */ 430 STATIC int 431 _bcm_flow_egr_mac_da_restore(int unit) 432 { 433 int min, max, i; 434 soc_mem_t mem; 435 uint32 view_id; 436 uint32 data_type = 0; 437 soc_flow_db_ctrl_field_t field_list; 438 uint32 l3_if_entry[SOC_MAX_MEM_WORDS]; 439 int num_fields = 0; 440 int rv = BCM_E_NONE; 441 442 sal_memset(&l3_if_entry, 0, sizeof(l3_if_entry)); 443 444 mem = BCM_XGS3_L3_MEM(unit, intf); 445 min = soc_mem_index_min(unit, mem); 446 max = soc_mem_index_max(unit, mem); 447 448 for (i = min; i < max; i++) { 449 BCM_IF_ERROR_RETURN 450 (BCM_XGS3_MEM_READ(unit, mem, i, &l3_if_entry)); 451 452 if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) { 453 data_type = soc_mem_field32_get(unit, mem, &l3_if_entry, DATA_TYPEf); 454 } 455 456 if (data_type == 0) { 457 continue; 458 } 459 460 if(soc_mem_field_valid(unit, mem, FLOW_SELECT_CTRL_IDf)) { 461 field_list.field_id = FLOW_SELECT_CTRL_IDf; 462 field_list.value = soc_mem_field32_get(unit, mem, 463 &l3_if_entry, FLOW_SELECT_CTRL_IDf); 464 num_fields = 1; 465 } 466 /* coverity[callee_ptr_arith : FALSE] */ 467 rv = soc_flow_db_mem_to_view_id_get(unit, 468 mem, 469 SOC_FLOW_DB_KEY_TYPE_INVALID, 470 data_type, 471 num_fields, 472 &field_list, 473 &view_id); 474 475 /* Recover MAC_DA profile count */ 476 if ((rv == BCM_E_NONE) && soc_mem_field_valid(unit, view_id, 477 PROFILED_ASSIGNMENT_SRC_MAC_ADDRESS_ACTION_SETf)) { 478 479 uint32 macda_idx; 480 481 macda_idx = soc_mem_field32_get(unit, view_id, &l3_if_entry, 482 PROFILED_ASSIGNMENT_SRC_MAC_ADDRESS_ACTION_SETf); 483 484 _bcm_common_profile_mem_ref_cnt_update( 485 unit, EGR_MAC_DA_PROFILEm, macda_idx, 1); 486 } 487 } 488 489 return rv; 490 } 491 /* 492 * Function: 493 * _bcm_flow_reinit 494 * Purpose: 495 * Warm boot recovery for the VXLAN software module 496 * Parameters: 497 * unit - Device Number 498 * Returns: 499 * BCM_E_XXX 500 */ 501 STATIC int 502 _bcm_flow_reinit(int unit) 503 { 504 int rv = BCM_E_NONE; 505 506 /* Tunnel initiator hash and ref-count recovery */ 507 rv = _bcm_flow_tunnel_initiator_reinit(unit); 508 if (BCM_FAILURE(rv)) { 509 return rv; 510 } 511 512 /* Recover L2 scache */ 513 rv = _bcm_flow_wb_recover(unit); 514 BCM_IF_ERROR_RETURN(rv); 515 516 /* increase the used next hop object reference count */ 517 rv = _bcm_flow_next_hop_refcnt_restore(unit); 518 BCM_IF_ERROR_RETURN(rv); 519 520 /* increase the used egr mac da reference count */ 521 rv = _bcm_flow_egr_mac_da_restore(unit); 522 BCM_IF_ERROR_RETURN(rv); 523 524 /* traverse egress adaptation tables to recover the tpid reference count */ 525 rv = bcmi_esw_flow_encap_traverse(0, 526 _bcm_flow_encap_traverse_cb_tpid_refcnt,NULL); 527 BCM_IF_ERROR_RETURN(rv); 528 529 return rv; 530 } 531 532 /* 533 * Function: 534 * _bcm_esw_flow_sync 535 * 536 * Purpose: 537 * Record flow module persistent info for Level 2 Warm Boot 538 * 539 * Warm Boot Version Map: 540 * WB_VERSION_1_0 541 * Parameters: 542 * unit - (IN) Device Unit Number. 543 * 544 * Returns: 545 * BCM_E_XXX 546 */ 547 548 int 549 _bcm_esw_flow_sync(int unit) 550 { 551 int sz = 0, rv = BCM_E_NONE; 552 int num_soft_tnl = 0, num_dvp = 0; 553 int stable_size; 554 uint8 *flow_scache_ptr = NULL; 555 soc_scache_handle_t scache_handle; 556 _bcm_flow_bookkeeping_t *flow_info; 557 int num_iif; 558 int num_vp; 559 int i; 560 561 if (!soc_feature(unit, soc_feature_flex_flow)) { 562 return BCM_E_UNAVAIL; 563 } 564 565 /* Parameter validation checks */ 566 if (!SOC_UNIT_VALID(unit)) { 567 return BCM_E_UNIT; 568 } 569 BCM_IF_ERROR_RETURN(bcmi_esw_flow_check_init(unit)); 570 571 flow_info = FLOW_INFO(unit); 572 573 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 574 575 /* Requires extended scache support level-2 warmboot */ 576 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 577 return BCM_E_NONE; 578 } 579 580 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FLOW, 0); 581 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 582 0, &flow_scache_ptr, 583 BCM_WB_DEFAULT_VERSION, NULL); 584 if (BCM_FAILURE(rv) && (rv != BCM_E_INTERNAL)) { 585 return rv; 586 } 587 588 num_dvp = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm); 589 num_soft_tnl = num_dvp + soc_mem_index_count(unit, EGR_L3_INTFm); 590 591 /* save init_tunnel entry table */ 592 sz = sizeof(uint16); /* idx of _bcm_flow_init_tunnel_entry_t */ 593 for (i = 0; i < num_soft_tnl; i++) { 594 sal_memcpy(flow_scache_ptr,&flow_info->init_tunnel[i].idx, sz); 595 flow_scache_ptr += sz; 596 } 597 598 /* save the dvp_attr_bitmap */ 599 sz = SHR_BITALLOCSIZE(num_dvp); 600 sal_memcpy(flow_scache_ptr, flow_info->dvp_attr_bitmap, sz); 601 flow_scache_ptr += sz; 602 603 /* save iif_ref_cnt table */ 604 num_iif = soc_mem_index_count(unit, L3_IIFm); 605 sz = sizeof(uint16); /* iif_ref_cnt */ 606 for (i = 0; i < num_iif; i++) { 607 sal_memcpy(flow_scache_ptr,&flow_info->iif_ref_cnt[i], sz); 608 flow_scache_ptr += sz; 609 } 610 611 /* save vp_ref_cnt table */ 612 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 613 sz = sizeof(uint16); /* vp_ref_cnt */ 614 for (i = 0; i < num_vp; i++) { 615 sal_memcpy(flow_scache_ptr,&flow_info->vp_ref_cnt[i], sz); 616 flow_scache_ptr += sz; 617 } 618 619 /* save the memory usage reference count table */ 620 sz = sizeof(uint32); 621 for (i = 0; i < _BM_FLOW_MEM_USE_MAX; i++) { 622 sal_memcpy(flow_scache_ptr,&flow_info->mem_use_cnt[i], sz); 623 flow_scache_ptr += sz; 624 } 625 626 /* save match_key array */ 627 sz = sizeof(bcm_flow_match_vp_t); 628 for (i = 0; i < num_vp; i++) { 629 sal_memcpy(flow_scache_ptr,&flow_info->match_key[i], sz); 630 flow_scache_ptr += sz; 631 } 632 633 return rv; 634 } 635 636 #endif /* BCM_WARM_BOOT_SUPPORT */ 637 638 /* 639 * Function: 640 * bcmi_esw_flow_init 641 * Purpose: 642 * Initialize the FLOW software module 643 * Parameters: 644 * unit - Device Number 645 * Returns: 646 * BCM_E_XXX 647 */ 648 int 649 bcmi_esw_flow_init(int unit) 650 { 651 _bcm_flow_bookkeeping_t *flow_info; 652 int num_dvp; 653 int rv = BCM_E_NONE; 654 int num_vfi = 0; 655 int num_tnl; 656 int num_iif; 657 int num_vp; 658 uint64 rval; 659 660 if (!L3_INFO(unit)->l3_initialized) { 661 LOG_ERROR(BSL_LS_BCM_FLOW, 662 (BSL_META_U(unit, 663 "L3 module must be initialized prior to FLOW Init\n"))); 664 return BCM_E_CONFIG; 665 } 666 667 if (BCM_FAILURE(soc_flow_db_status_get(unit))) { 668 return BCM_E_INIT; 669 } 670 /* Allocate BK Info */ 671 BCM_IF_ERROR_RETURN(bcm_td3_flow_allocate_bk(unit)); 672 flow_info = FLOW_INFO(unit); 673 674 /* 675 * allocate resources 676 */ 677 if (flow_info->initialized) { 678 BCM_IF_ERROR_RETURN(bcmi_esw_flow_cleanup(unit)); 679 BCM_IF_ERROR_RETURN(bcm_td3_flow_allocate_bk(unit)); 680 flow_info = FLOW_INFO(unit); 681 } 682 683 /* Create EGR_DVP_ATTRIBUTEm usage bitmap */ 684 num_dvp = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm); 685 686 flow_info->dvp_attr_bitmap = 687 sal_alloc(SHR_BITALLOCSIZE(num_dvp), "dvp_attr_bitmap"); 688 if (flow_info->dvp_attr_bitmap == NULL) { 689 _bcm_td3_flow_free_resource(unit); 690 return BCM_E_MEMORY; 691 } 692 sal_memset(flow_info->dvp_attr_bitmap, 0, SHR_BITALLOCSIZE(num_dvp)); 693 694 /* Create soft tunnel index table */ 695 /* L2 tunnel associated with dvp, dvp represents the soft tunnnel index */ 696 num_tnl = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm); 697 698 /* L3 tunnel associated with egr_intf, soft tunnel index: 699 * max l2 tunnel + EGR_L3_INTFm index. 700 */ 701 num_tnl += soc_mem_index_count(unit, EGR_L3_INTFm); 702 flow_info->init_tunnel = 703 sal_alloc(sizeof(_bcm_flow_init_tunnel_entry_t) * num_tnl, 704 "flow_init_tunnel"); 705 if (flow_info->init_tunnel == NULL) { 706 _bcm_td3_flow_free_resource(unit); 707 return BCM_E_MEMORY; 708 } 709 sal_memset(flow_info->init_tunnel, 0, 710 sizeof(_bcm_flow_init_tunnel_entry_t) * num_tnl); 711 712 /* Create iif_ref_cnt table */ 713 num_iif = soc_mem_index_count(unit, L3_IIFm); 714 flow_info->iif_ref_cnt = 715 sal_alloc(sizeof(uint16) * num_iif, 716 "flow_match iif_ref_cnt"); 717 if (flow_info->iif_ref_cnt == NULL) { 718 _bcm_td3_flow_free_resource(unit); 719 return BCM_E_MEMORY; 720 } 721 sal_memset(flow_info->iif_ref_cnt, 0, 722 sizeof(uint16) * num_iif); 723 724 /* Create vp_ref_cnt table */ 725 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 726 flow_info->vp_ref_cnt = 727 sal_alloc(sizeof(uint16) * num_vp, 728 "flow_match vp_ref_cnt"); 729 if (flow_info->vp_ref_cnt == NULL) { 730 _bcm_td3_flow_free_resource(unit); 731 return BCM_E_MEMORY; 732 } 733 sal_memset(flow_info->vp_ref_cnt, 0, 734 sizeof(uint16) * num_vp); 735 736 flow_info->match_key = 737 sal_alloc(sizeof(bcm_flow_match_vp_t) * num_vp, 738 "flow_match match_key"); 739 if (flow_info->match_key == NULL) { 740 _bcm_td3_flow_free_resource(unit); 741 return BCM_E_MEMORY; 742 } 743 sal_memset(flow_info->match_key, 0, 744 sizeof(bcm_flow_match_vp_t) * num_vp); 745 746 rv = READ_EGR_SEQUENCE_NUMBER_CTRLr(unit, &rval); 747 if (SOC_FAILURE(rv)) { 748 _bcm_td3_flow_free_resource(unit); 749 return rv; 750 } 751 flow_info->frag_base_inx = soc_reg64_field32_get(unit, 752 EGR_SEQUENCE_NUMBER_CTRLr, rval, EGR_IP_TUNNEL_OFFSET_BASEf); 753 754 /* Create FLOW protection mutex. */ 755 flow_info->flow_mutex = sal_mutex_create("flow_mutex"); 756 if (!flow_info->flow_mutex) { 757 _bcm_td3_flow_free_resource(unit); 758 return BCM_E_MEMORY; 759 } 760 761 #if 0 762 if (NULL == flow_info->flow_tunnel_term) { 763 flow_info->flow_tunnel_term = 764 sal_alloc(sizeof(_bcm_vxlan_tunnel_endpoint_t) * num_vp, "flow tunnel term store"); 765 if (flow_info->flow_tunnel_term == NULL) { 766 _bcm_td3_flow_free_resource(unit); 767 return BCM_E_MEMORY; 768 } 769 sal_memset(flow_info->flow_tunnel_term, 0, 770 sizeof(_bcm_vxlan_tunnel_endpoint_t) * num_vp); 771 } 772 773 #endif 774 775 num_vfi = soc_mem_index_count(unit, VFIm); 776 if (NULL == flow_info->flow_vpn_vlan) { 777 flow_info->flow_vpn_vlan = 778 sal_alloc(sizeof(bcm_vlan_t) * num_vfi, "flow vpn vlan store"); 779 if (flow_info->flow_vpn_vlan == NULL) { 780 _bcm_td3_flow_free_resource(unit); 781 return BCM_E_MEMORY; 782 } 783 sal_memset(flow_info->flow_vpn_vlan, 0, sizeof(bcm_vlan_t) * num_vfi); 784 } 785 786 #ifdef BCM_WARM_BOOT_SUPPORT 787 if (SOC_WARM_BOOT(unit)) { 788 rv = _bcm_flow_reinit(unit); 789 if (BCM_FAILURE(rv)) { 790 _bcm_td3_flow_free_resource(unit); 791 } 792 } else { 793 rv = _bcm_flow_wb_alloc(unit); 794 795 if (BCM_SUCCESS(rv) && 796 soc_property_get(unit, spn_IP6_VXLAN_MSHG_ENABLE, 0)) { 797 bcmi_esw_flow_mshg_prune_egress_init(unit); 798 } 799 } 800 #endif /* BCM_WARM_BOOT_SUPPORT */ 801 802 /* Mark the state as initialized */ 803 flow_info->initialized = TRUE; 804 805 return rv; 806 } 807 808 /* 809 * Function: 810 * bcmi_esw_flow_check_init 811 * Purpose: 812 * Check if FLOW is initialized 813 * Parameters: 814 * unit - Device Number 815 * Returns: 816 * BCM_E_XXX 817 */ 818 819 int 820 bcmi_esw_flow_check_init(int unit) 821 { 822 _bcm_flow_bookkeeping_t *flow_info; 823 824 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 825 return BCM_E_UNIT; 826 } 827 828 flow_info = FLOW_INFO(unit); 829 830 if ((flow_info == NULL) || (flow_info->initialized == FALSE)) { 831 return BCM_E_INIT; 832 } else { 833 return BCM_E_NONE; 834 } 835 } 836 837 /* 838 * Function: 839 * bcmi_esw_flow_cleanup 840 * Purpose: 841 * DeInit FLOW software module 842 * Parameters: 843 * unit - Device Number 844 * Returns: 845 * BCM_E_XXX 846 */ 847 848 int 849 bcmi_esw_flow_cleanup(int unit) 850 { 851 _bcm_flow_bookkeeping_t *flow_info; 852 int rv = BCM_E_UNAVAIL; 853 854 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 855 return BCM_E_UNIT; 856 } 857 858 flow_info = FLOW_INFO(unit); 859 860 if (FALSE == flow_info->initialized) { 861 return (BCM_E_NONE); 862 } 863 864 rv = bcmi_esw_flow_lock (unit); 865 if (BCM_FAILURE(rv)) { 866 return rv; 867 } 868 869 if (0 == SOC_HW_ACCESS_DISABLE(unit)) { 870 rv = _bcm_td3_flow_hw_clear(unit); 871 } 872 873 /* Mark the state as uninitialized */ 874 flow_info->initialized = FALSE; 875 876 sal_mutex_give(flow_info->flow_mutex); 877 878 /* Destroy protection mutex. */ 879 sal_mutex_destroy(flow_info->flow_mutex ); 880 881 /* Free software resources */ 882 (void) _bcm_td3_flow_free_resource(unit); 883 884 return rv; 885 } 886 887 /* 888 * Function: 889 * bcmi_esw_flow_lock 890 * Purpose: 891 * Take FLOW Lock Sempahore 892 * Parameters: 893 * unit - Device Number 894 * Returns: 895 * BCM_E_XXX 896 */ 897 898 int 899 bcmi_esw_flow_lock(int unit) 900 { 901 int rv=BCM_E_NONE; 902 903 rv = bcmi_esw_flow_check_init(unit); 904 905 if ( rv == BCM_E_NONE ) { 906 sal_mutex_take(FLOW_INFO((unit))->flow_mutex, sal_mutex_FOREVER); 907 } 908 return rv; 909 } 910 911 /* 912 * Function: 913 * bcmi_esw_flow_unlock 914 * Purpose: 915 * Release FLOW Lock Semaphore 916 * Parameters: 917 * unit - Device Number 918 * Returns: 919 * BCM_E_XXX 920 */ 921 922 923 void 924 bcmi_esw_flow_unlock(int unit) 925 { 926 int rv=BCM_E_NONE; 927 928 rv = bcmi_esw_flow_check_init(unit); 929 if ( rv == BCM_E_NONE ) { 930 sal_mutex_give(FLOW_INFO((unit))->flow_mutex); 931 } 932 } 933 934 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 935 STATIC 936 void _bcmi_esw_flow_sw_dump(int unit) 937 { 938 int num_dvp = 0; 939 int num_iif = 0; 940 int num_vp = 0; 941 int num_vfi = 0; 942 int num_soft_tnl = 0; 943 _bcm_flow_bookkeeping_t *flow_info = NULL; 944 int i = 0; 945 uint16 flag = FALSE; 946 947 flow_info = FLOW_INFO(unit); 948 949 num_dvp = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm); 950 num_soft_tnl = num_dvp + soc_mem_index_count(unit, EGR_L3_INTFm); 951 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 952 num_iif = soc_mem_index_count(unit, L3_IIFm); 953 num_vfi = soc_mem_index_count(unit, VFIm); 954 955 for (i = 0, flag = FALSE; i < num_vfi; i++) { 956 if (VIRTUAL_INFO(unit)->flow_vfi_bitmap) { 957 if (SHR_BITGET(VIRTUAL_INFO(unit)->flow_vfi_bitmap, i)) { 958 if (flag == TRUE) { 959 LOG_CLI((BSL_META_U(unit," , %d"), i)); 960 } else { 961 LOG_CLI((BSL_META_U(unit, 962 "%-32s : %d \n"),"Flow VFI", i)); 963 } 964 flag = TRUE; 965 } 966 } 967 } 968 969 for (i = 0, flag = FALSE; i < num_vp; i++) { 970 if (VIRTUAL_INFO(unit)->flow_vp_bitmap) { 971 if (SHR_BITGET(VIRTUAL_INFO(unit)->flow_vp_bitmap, i)) { 972 if (flag == TRUE) { 973 LOG_CLI((BSL_META_U(unit," , %d"), i)); 974 } else { 975 LOG_CLI((BSL_META_U(unit, 976 "\n%-32s : %d"), "Flow VP", i)); 977 } 978 flag = TRUE; 979 } 980 } 981 } 982 983 for (i = 0, flag = FALSE; i < num_soft_tnl; i++) { 984 if(flow_info->init_tunnel[i].idx) { 985 if (flag == TRUE) { 986 LOG_CLI((BSL_META_U(unit," , %d"), i)); 987 } else { 988 LOG_CLI((BSL_META_U(unit, 989 "\n%-32s : %d"), 990 "init_tunnel soft index", 991 num_soft_tnl)); 992 } 993 flag = TRUE; 994 } 995 } 996 997 LOG_CLI((BSL_META_U(unit, 998 "\n%-32s : 0x%x"), 999 "DVP Attribute bitmap",*flow_info->dvp_attr_bitmap)); 1000 1001 for (i = 0; i < num_iif; i++) { 1002 if (flow_info->iif_ref_cnt[i]) { 1003 LOG_CLI((BSL_META_U(unit, 1004 "\n %-10s : %d, %-14s : %d"), 1005 "IIF index", i, "IIF use count", flow_info->iif_ref_cnt[i])); 1006 } 1007 } 1008 1009 for (i = 0; i < num_vp; i++) { 1010 if (flow_info->vp_ref_cnt[i]) { 1011 LOG_CLI((BSL_META_U(unit, 1012 "\n%-10s : %d, %-14s : %d"), 1013 "VP index", i, "VP use count", flow_info->vp_ref_cnt[i])); 1014 } 1015 } 1016 1017 LOG_CLI((BSL_META_U(unit,"\n"))); 1018 return; 1019 } 1020 /* 1021 * Function: 1022 * bcmi_esw_flow_sw_dump 1023 * Purpose: 1024 * Displays flow information maintained by software. 1025 * Parameters: 1026 * unit - Device unit number 1027 * Returns: 1028 * None 1029 */ 1030 void 1031 bcmi_esw_flow_sw_dump(int unit) 1032 { 1033 if (soc_feature(unit, soc_feature_flex_flow)) { 1034 _bcmi_esw_flow_sw_dump(unit); 1035 } 1036 return; 1037 } 1038 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */ 1039 1040 #endif