ft_user.c (49362B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: ft_user.c 8 * Purpose: Routines managing user inserted flows in FT 9 * Requires: 10 */ 11 12 13 #include <bcm_int/esw/flowtracker/ft_user.h> 14 #include <bcm_int/esw/flowtracker/ft_group.h> 15 16 #if defined(BCM_FLOWTRACKER_SUPPORT) 17 18 #define BCMI_FTK_DMA_CHUNK_SIZE 4096 19 20 /* Internal structure to traverse memory */ 21 typedef struct bcmi_ftk_user_entry_traverse_data_s { 22 bcm_flowtracker_group_t flow_group_id; 23 uint32 flow_key_mode; 24 uint32 flow_key_type; 25 int handle_idx; 26 int num_user_entry_handles; 27 int actual_entries; 28 bcm_flowtracker_user_entry_handle_t *user_entry_handle_list; 29 } bcmi_ftk_user_entry_traverse_data_t; 30 31 32 /* Generic memory allocation routine. */ 33 #define FTK_ALLOC(_ptr_, _size_, _descr_) \ 34 do { \ 35 int _lsize_; \ 36 _lsize_ = (_size_ ); \ 37 if (NULL == (_ptr_)) { \ 38 (_ptr_) = sal_alloc((_lsize_), (_descr_)); \ 39 } \ 40 if((_ptr_) != NULL) { \ 41 sal_memset((_ptr_), 0, (_lsize_)); \ 42 } else { \ 43 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, \ 44 (BSL_META("FTK Error: Allocation failure %s\n"), (_descr_))); \ 45 } \ 46 } while (0) 47 48 49 /* Generic memory free routine. */ 50 #define FTK_FREE(_ptr_) \ 51 do { \ 52 if (NULL != (_ptr_)) { \ 53 sal_free((_ptr_)); \ 54 } \ 55 (_ptr_) = NULL; \ 56 } while (0) 57 58 #define FTK_CPY(_to_, _from_, _size_) \ 59 do { \ 60 sal_memcpy((_to_), (_from_), (_size_)); \ 61 } while (0) 62 63 64 #define FTK_PRINT_ARRAY(_unit, _string_, _nbytes_, _arr_ptr_) \ 65 do { \ 66 int ii; \ 67 LOG_INFO(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(_unit, "%s "), (_string_))); \ 68 for (ii = 0; ii < _nbytes_; ii++) { \ 69 if ((ii + 1) != _nbytes_) { \ 70 LOG_INFO(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(_unit, "%02x "), _arr_ptr_[ii])); \ 71 } else { \ 72 LOG_INFO(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(_unit, "%02x\n"), _arr_ptr_[ii])); \ 73 } \ 74 } \ 75 } while (0) 76 77 #define FTK_PRINT_ARRAY_U32(_unit, _string_, _nwords_, _arr_ptr_) \ 78 do { \ 79 int ii; \ 80 LOG_INFO(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(_unit, "%s "), (_string_))); \ 81 for (ii = 0; ii < _nwords_; ii++) { \ 82 if ((ii + 1) != _nwords_) { \ 83 LOG_INFO(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(_unit, "%08x "), _arr_ptr_[ii])); \ 84 } else { \ 85 LOG_INFO(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(_unit, "%08x\n"), _arr_ptr_[ii])); \ 86 } \ 87 } \ 88 } while (0) 89 90 /* FT group Internal methods. */ 91 typedef int (*bcmi_ftk_mem_entry_traverse_cb)(int unit, 92 soc_mem_t mem, uint32 index, void *entry, 93 void *user_data, int *fin); 94 95 int bcmi_ftk_mem_traverse(int unit, soc_mem_t mem, 96 bcmi_ftk_mem_entry_traverse_cb cb, 97 void *user_data); 98 99 /* 100 * Function: 101 * bcmi_ft_user_cleanup 102 * Purpose: 103 * Clear Flowtracker user entries states. 104 * Parameters: 105 * unit - (IN) BCM device id 106 * 107 * Returns: 108 * None. 109 */ 110 void 111 bcmi_ft_user_cleanup(int unit) 112 { 113 return; 114 } 115 116 /* 117 * Function: 118 * bcmi_ft_user_init 119 * Purpose: 120 * Initialize Flowtracker user state. 121 * Parameters: 122 * unit - (IN) BCM device id 123 * 124 * Returns: 125 * None. 126 */ 127 int 128 bcmi_ft_user_init(int unit) 129 { 130 /* No structure to initialize */ 131 return BCM_E_NONE; 132 } 133 134 /* 135 * Function: 136 * bcmi_ftk_user_entry_param_check 137 * Purpose: 138 * Verify user tracking param info. 139 * Parameters: 140 * unit - (IN) BCM device id. 141 * group - (IN) Flowtracker Group. 142 * num_user_entry_params - (IN) Number of elements in user_entry_param_list 143 * user_entry_param_list - (IN) User tracking param info. 144 * 145 * Returns: 146 * BCM_E_XXX 147 */ 148 STATIC int 149 bcmi_ftk_user_entry_param_check( 150 int unit, 151 bcm_flowtracker_group_t group, 152 int num_user_entry_params, 153 bcm_flowtracker_tracking_param_info_t *user_entry_param_list) 154 { 155 int ix, jx; 156 int num_params; 157 bcm_flowtracker_tracking_param_info_t *t1, *t2; 158 159 num_params = BCMI_FT_GROUP_TRACK_PARAM_NUM(unit, group); 160 for (ix = 0; ix < num_params; ix++) { 161 t1 = &(BCMI_FT_GROUP_TRACK_PARAM(unit, group)[ix]); 162 163 /* skip checking for non-key tracking params */ 164 if (!t1->flags & BCM_FLOWTRACKER_TRACKING_PARAM_TYPE_KEY) { 165 continue; 166 } 167 for (jx = 0; jx < num_user_entry_params; jx++) { 168 t2 = &(user_entry_param_list[jx]); 169 if (t2->param == t1->param) { 170 break; 171 } 172 } 173 174 /* key param is not found in user params */ 175 if (jx == num_user_entry_params) { 176 return BCM_E_PARAM; 177 } 178 179 } 180 181 return BCM_E_NONE; 182 } 183 184 /* 185 * Function: 186 * bcmi_ftk_user_entry_key_info_normalize 187 * Purpose: 188 * Normalize user tracking param info pair for bidir flows. 189 * Parameters: 190 * unit - (IN) BCM device id. 191 * group - (IN) Flowtracker Group. 192 * norm_tracking_params_info - (IN) List of normalization tracking params. 193 * num_user_entry_params - (IN) Number of elements in user_entry_param_list 194 * user_entry_param_list - (IN) User tracking param info. 195 * 196 * Returns: 197 * BCM_E_XXX 198 */ 199 STATIC int 200 bcmi_ftk_user_entry_key_info_normalize( 201 int unit, 202 bcm_flowtracker_group_t group, 203 bcm_flowtracker_tracking_param_info_t **norm_tracking_params_info, 204 int num_user_entry_params, 205 bcm_flowtracker_tracking_param_info_t *user_entry_param_list) 206 { 207 int ii = 0; 208 int srcdst = 0; 209 int width = 0, num_keys = 0; 210 bcmi_ft_group_alu_info_t *key_ext_info = NULL; 211 bcm_flowtracker_tracking_param_info_t *t1 = NULL; 212 bcm_flowtracker_tracking_param_info_t *t2 = NULL; 213 bcm_flowtracker_tracking_param_type_t temp_param; 214 215 key_ext_info = BCMI_FT_GROUP_EXT_KEY_INFO(unit, group); 216 num_keys = BCMI_FT_GROUP_EXT_INFO(unit, group).num_key_info; 217 218 /* Find src and dst tp info in user_param_list */ 219 for (ii = 0, srcdst = 0; 220 (ii < num_user_entry_params) && (srcdst < 2); ii++) { 221 if (user_entry_param_list[ii].param == 222 norm_tracking_params_info[0]->param) { 223 t1 = &user_entry_param_list[ii]; 224 srcdst++; 225 } else if (user_entry_param_list[ii].param == 226 norm_tracking_params_info[1]->param) { 227 t2 = &user_entry_param_list[ii]; 228 srcdst++; 229 } 230 } 231 if ((t1 == NULL) || (t2 == NULL)) { 232 return BCM_E_PARAM; 233 } 234 235 /* Find key extractor info */ 236 for (ii = 0; ii < num_keys; ii++) { 237 if (t1->param == key_ext_info[ii].element_type1) { 238 width = key_ext_info[ii].key1.length; 239 } else if (t2->param == key_ext_info[ii].element_type1) { 240 width = key_ext_info[ii].key1.length; 241 } 242 243 if (width != 0) { 244 break; 245 } 246 } 247 248 /* Swap, if required */ 249 for (ii = 0; ii < width; ii++) { 250 if (t1->tracking_data[ii] == t2->tracking_data[ii]) { 251 continue; 252 } 253 254 if (t1->tracking_data[ii] < t2->tracking_data[ii]) { 255 temp_param = t2->param; 256 t2->param = t1->param; 257 t1->param = temp_param; 258 break; 259 } 260 } 261 262 return BCM_E_NONE; 263 } 264 265 /* 266 * Function: 267 * bcmi_ftk_user_entry_key_normalize 268 * Purpose: 269 * Normalize user tracking param info for bidir flows. 270 * Parameters: 271 * unit - (IN) BCM device id. 272 * group - (IN) Flowtracker Group. 273 * num_user_entry_params - (IN) Number of elements in user_entry_param_list 274 * user_entry_param_list - (IN) User tracking param info. 275 * 276 * Returns: 277 * BCM_E_XXX 278 * Note: 279 * When both tracking param in the pair pare present, 280 * then we can normalize it otherwise skip. 281 */ 282 STATIC int 283 bcmi_ftk_user_entry_key_normalize( 284 int unit, 285 bcm_flowtracker_group_t group, 286 int num_user_entry_params, 287 bcm_flowtracker_tracking_param_info_t *user_entry_param_list) 288 { 289 int idx = 0; 290 int rv = BCM_E_NONE; 291 bcm_flowtracker_tracking_param_info_t 292 *norm_tracking_params_info[BCMI_FT_GROUP_NORM_TRACKING_PARAMS] = {NULL}; 293 294 rv = bcmi_ft_group_norm_tracking_params_info_get(unit, 295 group, &norm_tracking_params_info[0]); 296 BCM_IF_ERROR_RETURN(rv); 297 298 /* Normalize if both params are present */ 299 for (idx = 0; idx < BCMI_FT_GROUP_NORM_TRACKING_PARAMS; idx += 2) { 300 if ((norm_tracking_params_info[idx] != NULL) && 301 (norm_tracking_params_info[idx + 1] != NULL)) { 302 rv = bcmi_ftk_user_entry_key_info_normalize(unit, 303 group, &norm_tracking_params_info[idx], 304 num_user_entry_params, user_entry_param_list); 305 if (BCM_FAILURE(rv)) { 306 return rv; 307 } 308 } 309 } 310 311 return BCM_E_NONE; 312 } 313 314 /* 315 * Function: 316 * bcmi_ftk_user_entry_data_fill 317 * Purpose: 318 * Fill mem entry for session data. 319 * Parameters: 320 * unit - (IN) BCM device id. 321 * group - (IN) Flowtracker Group. 322 * ftd_mem - (IN) Session Data memory. 323 * ftd_entry - (OUT) Session data entry buffer. 324 * 325 * Returns: 326 * BCM_E_XXX 327 */ 328 STATIC int 329 bcmi_ftk_user_entry_data_fill( 330 int unit, 331 bcm_flowtracker_group_t group, 332 soc_mem_t ftd_mem, 333 uint32 *ftd_entry) 334 { 335 int ii; 336 int rv; 337 int profile_idx; 338 int offset, length; 339 uint16 init16_data = 0; 340 uint32 init32_data = 0; 341 int ftd_width, ftd_words; 342 uint8 *ft_data = NULL, *ft_tmp; 343 uint32 *ftd_fld = NULL; 344 uint8 ftd_val[6], *ftd_val_tmp; 345 bcmi_ft_group_template_list_t *ftg_template = NULL; 346 347 soc_format_t fmt; 348 bsc_dg_group_table_entry_t dg_entry; 349 uint32 profile_data[2], profile_field[2]; 350 351 /* First read the group entry. */ 352 rv = soc_mem_read(unit, BSC_DG_GROUP_TABLEm, 353 MEM_BLOCK_ANY, group, &dg_entry); 354 BCMI_CLEANUP_IF_ERROR(rv); 355 356 /* Allocate memory for ft_data */ 357 ftd_width = BITS2BYTES(soc_mem_field_length(unit, ftd_mem, OPAQUE_DATAf)); 358 ftd_words = BYTES2WORDS(ftd_width); 359 360 FTK_ALLOC(ftd_fld, ftd_width, "ftd field"); 361 FTK_ALLOC(ft_data, ftd_width, "ft data"); 362 363 364 ftg_template = ((BCMI_FT_GROUP(unit, group))->template_head); 365 for (; (ftg_template != NULL); ftg_template = ftg_template->next) { 366 367 offset = (ftg_template->info.cont_offset); 368 length = (ftg_template->info.cont_width); 369 if (ftg_template->info.data_shift != 0) { 370 length -= ftg_template->info.data_shift; 371 } 372 373 ftd_val_tmp = ftd_val; 374 375 switch(ftg_template->info.param_type) { 376 case bcmiFtGroupParamTypeMeter: 377 378 fmt = BSC_TL_DG_TO_DT_METER_CONTROL_BUSfmt; 379 380 profile_idx = soc_mem_field32_get(unit, BSC_DG_GROUP_TABLEm, 381 ((uint32 *)&dg_entry), 382 GROUP_METER_PROFILE_IDXf); 383 rv = soc_mem_read(unit, BSC_DG_GROUP_METER_PROFILEm, 384 MEM_BLOCK_ANY, profile_idx, profile_data); 385 BCMI_CLEANUP_IF_ERROR(rv); 386 387 soc_mem_field_get(unit, BSC_DG_GROUP_METER_PROFILEm, 388 profile_data, DATAf, profile_field); 389 390 init32_data = soc_format_field32_get(unit, fmt, 391 profile_field, REFRESHCOUNTf); 392 393 _SHR_PACK_U16(ftd_val_tmp, init16_data); 394 _SHR_PACK_U16(ftd_val_tmp, (init32_data >> 16)); 395 _SHR_PACK_U16(ftd_val_tmp, (init32_data & 0xFFFF)); 396 397 FTK_CPY(&ft_data[BITS2BYTES(offset)], ftd_val, BITS2BYTES(length)); 398 break; 399 400 case bcmiFtGroupParamTypeCollectorCopy: 401 402 fmt = BSC_TL_DG_TO_DT_COPY_TO_COLLECTOR_CONTROL_BUSfmt; 403 404 profile_idx = soc_mem_field32_get(unit, BSC_DG_GROUP_TABLEm, 405 ((uint32 *)&dg_entry), 406 COPY_TO_COLLECTOR_PROFILE_IDXf); 407 rv = soc_mem_read(unit, BSC_DG_GROUP_COPY_TO_COLLECTOR_PROFILEm, 408 MEM_BLOCK_ANY, profile_idx, profile_data); 409 BCMI_CLEANUP_IF_ERROR(rv); 410 411 soc_mem_field_get(unit, BSC_DG_GROUP_COPY_TO_COLLECTOR_PROFILEm, 412 profile_data, DATAf, profile_field); 413 414 415 if (soc_format_field32_get(unit, fmt, profile_field, 416 INITIAL_COPY_COUNT_ENABLEf)) { 417 418 init16_data = soc_format_field32_get(unit, fmt, 419 profile_field, MAX_COUNTf); 420 421 soc_mem_field32_set(unit, ftd_mem, ftd_entry, 422 INITIAL_COPY_COLLECTOR_PHASEf, 1); 423 } 424 425 _SHR_PACK_U16(ftd_val_tmp, init16_data); 426 FTK_CPY(&ft_data[BITS2BYTES(offset)], ftd_val, BITS2BYTES(length)); 427 428 break; 429 430 default: 431 break; 432 } 433 434 435 if (ftg_template->info.flags & BCMI_FT_ALU_LOAD_NEXT_ATTACH) { 436 /* This is surely at least second last. so we can blindly go next.*/ 437 ftg_template = ftg_template->next; 438 } 439 } 440 441 ft_tmp = ft_data; 442 443 for (ii = 0; ii < (ftd_words); ii++) { 444 _SHR_UNPACK_U32(ft_tmp, ftd_fld[(ftd_words - ii - 1)]); 445 } 446 FTK_PRINT_ARRAY(unit, "FTD_OPAQUE_FIELD: ", (ftd_words), ftd_fld); 447 448 449 FTK_PRINT_ARRAY_U32(unit, "FTD_OPAQUE_FIELD: ", (ftd_words), ftd_fld); 450 451 452 /* Set OPAQUE_DATA in the session table. */ 453 soc_mem_field_set(unit, ftd_mem, ftd_entry, OPAQUE_DATAf, ftd_fld); 454 FTK_PRINT_ARRAY_U32(unit, "FTD_ENTRY: ", soc_mem_entry_words(unit, ftd_mem), ftd_entry); 455 456 cleanup: 457 FTK_FREE(ftd_fld); 458 FTK_FREE(ft_data); 459 460 return rv; 461 } 462 463 /* 464 * Function: 465 * bcmi_ftk_user_entry_key_fill 466 * Purpose: 467 * Fill mem entry for session key 468 * Parameters: 469 * unit - (IN) BCM device id. 470 * group - (IN) Flowtracker Group. 471 * num_user_entry_params - (IN) Numer of elements in user_entry_param_list. 472 * user_entry_param_list - (IN) User entry tracking param data info. 473 * key_type - (IN) Session Key Type. 474 * key_mode - (IN) Session Key Mode. 475 * ftk_width - (IN) Width of Session key entry. 476 * ft_key - (OUT) Pointer to Session Key entry buffer. 477 * 478 * Returns: 479 * BCM_E_XXX 480 */ 481 STATIC int 482 bcmi_ftk_user_entry_key_fill( 483 int unit, 484 bcm_flowtracker_group_t group, 485 int num_user_entry_params, 486 bcm_flowtracker_tracking_param_info_t *user_entry_param_list, 487 uint32 key_type, 488 uint32 key_mode, 489 int ftk_width, 490 uint8 *ft_key) 491 { 492 int ix, jx; 493 uint8 *ele_data; 494 bcmi_ft_alu_key_t *key_alu; 495 int key_offset, keytype_offset; 496 int start, length, num_key_els; 497 bcmi_ft_group_alu_info_t *key_ext_info; 498 bcm_flowtracker_tracking_param_info_t *t1 = NULL; 499 500 key_ext_info = BCMI_FT_GROUP_EXT_KEY_INFO(unit, group); 501 num_key_els = BCMI_FT_GROUP_EXT_INFO(unit, group).num_key_info; 502 503 504 /* Ensure num_params is same as num key elements */ 505 if (num_user_entry_params != num_key_els) { 506 return BCM_E_PARAM; 507 } 508 509 /* 1st Byte: KeyType + Mode */ 510 ft_key[(ftk_width - 1)] = (((key_type & 0x7F) << 1) | (key_mode & 0x1)); 511 keytype_offset = 8; 512 513 ftk_width = BYTES2BITS(ftk_width); 514 515 for (ix = 0; ix < num_key_els; ix++) { 516 key_alu = &(key_ext_info->key1); 517 start = key_alu->location; 518 length = key_alu->length; 519 520 for (jx = 0; jx < num_user_entry_params; jx++) { 521 t1 = &(user_entry_param_list[jx]); 522 523 if (key_ext_info->element_type1 == t1->param) { 524 break; 525 } 526 } 527 528 529 /* tracking param not found */ 530 if (jx == num_user_entry_params) { 531 return BCM_E_PARAM; 532 } 533 key_offset = (ftk_width - (keytype_offset + start + length)); 534 535 ele_data = &(t1->tracking_data[0]); 536 FTK_CPY(&ft_key[BITS2BYTES(key_offset)], ele_data, BITS2BYTES(length)); 537 538 LOG_INFO(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, "element type: %d start = %d len = %d\n"), t1->param, start, length)); 539 FTK_PRINT_ARRAY(unit, "Element:", BITS2BYTES(length), t1->tracking_data); 540 541 key_ext_info++; 542 } 543 544 545 546 FTK_PRINT_ARRAY(unit, "Full Key:", (ftk_width/8), ft_key); 547 548 return BCM_E_NONE; 549 } 550 551 /* 552 * Function: 553 * bcmi_ftk_group_sw_entries_check 554 * Purpose: 555 * Verify if user entries allowed on given flowtracker group. 556 * Parameters: 557 * unit - (IN) BCM device id. 558 * group - (IN) Flowtracker Group. 559 * 560 * Returns: 561 * BCM_E_XXX 562 */ 563 STATIC int 564 bcmi_ftk_group_sw_entries_check(int unit, bcm_flowtracker_group_t group) 565 { 566 BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, group)); 567 568 if (!BCMI_FT_GROUP_IS_VALIDATED(unit,group)) { 569 return BCM_E_CONFIG; 570 } 571 572 /* Make sure that the flow group is a SW-only group. */ 573 if (!BCMI_FT_GROUP(unit, group)->flags & 574 BCM_FLOWTRACKER_GROUP_USER_ENTRIES_ONLY) { 575 return BCM_E_CONFIG; 576 } 577 578 return BCM_E_NONE; 579 } 580 581 /* 582 * Function: 583 * bcmi_ftk_group_learn_counter_update 584 * Purpose: 585 * Update learn counter for given flowtracker group. 586 * Parameters: 587 * unit - (IN) BCM device id. 588 * group - (IN) Flowtracker Group. 589 * incr - (IN) Change. 590 * 591 * Returns: 592 * BCM_E_XXX 593 */ 594 STATIC int 595 bcmi_ftk_group_learn_counter_update( 596 int unit, 597 bcm_flowtracker_group_t id, 598 int incr) 599 { 600 uint64 val; 601 602 COMPILER_64_ZERO(val); 603 604 /* Read Learn Counter */ 605 BCM_IF_ERROR_RETURN(soc_counter_get(unit, REG_PORT_ANY, 606 SOC_COUNTER_NON_DMA_FT_GROUP_FLOW_LEARNT_CNT, id, &val)); 607 608 /* Update Learn counter */ 609 if (incr == 1) { 610 COMPILER_64_ADD_32(val, 1); 611 } else { 612 COMPILER_64_SUB_32(val, 1); 613 } 614 615 /* Write Learn counter */ 616 BCM_IF_ERROR_RETURN(soc_counter_set(unit, REG_PORT_ANY, 617 SOC_COUNTER_NON_DMA_FT_GROUP_FLOW_LEARNT_CNT, id, val)); 618 619 return BCM_E_NONE; 620 } 621 622 /* 623 * Function: 624 * bcmi_ftk_user_entry_add 625 * Purpose: 626 * Add a user flow entry basis user input key elements. API 627 * expects that all tracking parametrs of type = 'KEY' in the 628 * group are specified. 629 * Parameters: 630 * unit - (IN) Unit number. 631 * flow_group_id - (IN) Flowtracker flow group ID. 632 * options - (IN) Options for creting the flowtracker user entry. 633 * num_user_entry_params - (IN) Number of user entry params. 634 * user_entry_param_list - (IN) List of user entry params to add flow entry. 635 * entry_handle - (OUT) User entry handle corresponding to the entry added. 636 * Returns: 637 * BCM_E_xxx 638 * Notes: 639 */ 640 int 641 bcmi_ftk_user_entry_add( 642 int unit, 643 bcm_flowtracker_group_t flow_group_id, 644 uint32 options, 645 int num_user_entry_params, 646 bcm_flowtracker_tracking_param_info_t *user_entry_param_list, 647 bcm_flowtracker_user_entry_handle_t *entry_handle) 648 { 649 int ii; 650 int memsize; 651 int ft_index, ag_index; 652 uint32 key_type, key_mode; 653 int dnt_entry_created = 0; 654 int ftk_single_bits = 0, ftk_single_bytes = 0; 655 int ftk_single_words = 0, ftk_width = 0; 656 uint8 *ft_key = NULL, *ft_key_tmp; 657 uint32 *ftk_fld = NULL; 658 uint32 *ftd_entry = NULL; 659 uint32 *ftk_entry = NULL; 660 uint32 *ft_key_buf = NULL; 661 bsc_ag_age_table_entry_t ag_entry; 662 do_not_ft_entry_entry_t *dnt_entry = NULL; 663 bcm_flowtracker_group_t hw_group_id; 664 bcmi_ft_group_ftfp_data_t ftfp_data; 665 soc_mem_t dnt_mem, ftk_mem, ftd_mem, ag_mem; 666 bcmi_ft_group_key_data_mode_t k_mode, d_mode; 667 668 int rv = BCM_E_NONE; 669 670 if (num_user_entry_params < 0) { 671 return BCM_E_PARAM; 672 } 673 674 if (entry_handle == NULL) { 675 return BCM_E_PARAM; 676 } 677 dnt_mem = DO_NOT_FT_ENTRYm; 678 679 /* Make sure group is valid */ 680 BCM_IF_ERROR_RETURN(bcmi_ftk_group_sw_entries_check(unit, flow_group_id)); 681 682 /* The list of user info elements in the entry_add API 683 * match with the tracking params of TYPE=?KEY? in the 684 * flow group. if there is a mismatch, return error. 685 */ 686 rv = bcmi_ftk_user_entry_param_check(unit, flow_group_id, 687 num_user_entry_params, user_entry_param_list); 688 BCM_IF_ERROR_RETURN(rv); 689 690 691 rv = bcmi_ft_group_extraction_mode_get(unit, 0, flow_group_id, &k_mode); 692 BCM_IF_ERROR_RETURN(rv); 693 694 rv = bcmi_ft_group_extraction_mode_get(unit, 1, flow_group_id, &d_mode); 695 BCM_IF_ERROR_RETURN(rv); 696 697 698 ftk_single_bits = soc_mem_field_length(unit, dnt_mem, KEY_0f); 699 ftk_single_bytes = BITS2BYTES(ftk_single_bits); 700 ftk_single_words = BYTES2WORDS(ftk_single_bytes); 701 702 /* Allocate memory for ft_key */ 703 ftk_width = (ftk_single_bytes * 2); 704 FTK_ALLOC(ft_key, ftk_width, "ft key"); 705 FTK_ALLOC(ftk_fld, ftk_width, "ft field"); 706 FTK_ALLOC(ft_key_buf, ftk_width, "ft key buffer"); 707 708 rv = bcmi_ft_group_ftfp_data_get(unit, flow_group_id, &ftfp_data); 709 BCMI_CLEANUP_IF_ERROR(rv); 710 711 key_type = ftfp_data.session_key_type; 712 key_mode = ftfp_data.session_key_mode; 713 714 /* Normalize key user param fields */ 715 if (ftfp_data.direction == bcmFlowtrackerFlowDirectionBidirectional) { 716 rv = bcmi_ftk_user_entry_key_normalize(unit, flow_group_id, 717 num_user_entry_params, 718 user_entry_param_list); 719 BCMI_CLEANUP_IF_ERROR(rv); 720 } 721 722 /* Prepare key table entry using key extraction info 723 * from the group data structures. 724 */ 725 rv = bcmi_ftk_user_entry_key_fill(unit, flow_group_id, 726 num_user_entry_params, 727 user_entry_param_list, 728 key_type, key_mode, 729 ftk_width, ft_key); 730 BCMI_CLEANUP_IF_ERROR(rv); 731 732 733 734 /* Install the key entry in the one-entry ?DO_NOT_FT_ENTRY? 735 * table and set actions as DO_NOT_LEARN = DO_NOT_FT = 1. 736 */ 737 memsize = soc_mem_entry_bytes(unit, dnt_mem); 738 FTK_ALLOC(dnt_entry, memsize, "DONOTFT Mem Entry"); 739 740 if (k_mode == bcmiFtGroupModeSingle) { 741 ftk_mem = FT_KEY_SINGLEm; 742 } else { 743 ftk_mem = FT_KEY_DOUBLEm; 744 } 745 ag_mem = BSC_AG_AGE_TABLEm; 746 747 memsize = soc_mem_entry_bytes(unit, ftk_mem); 748 FTK_ALLOC(ftk_entry, memsize, "FT Key Mem Entry"); 749 750 ft_key_tmp = ft_key; 751 752 for (ii = 0; ii < BYTES2WORDS(ftk_width); ii++) { 753 _SHR_UNPACK_U32(ft_key_tmp, ftk_fld[(BYTES2WORDS(ftk_width) - ii - 1)]); 754 } 755 756 if (k_mode == bcmiFtGroupModeSingle) { 757 758 /* Single Wide Key */ 759 760 SHR_BITCOPY_RANGE(ft_key_buf, 0, ftk_fld, 0, ftk_single_bits); 761 FTK_PRINT_ARRAY_U32(unit, "FTK_FIELD0 : ", ftk_single_words, ft_key_buf); 762 soc_mem_field_set(unit, dnt_mem, (uint32 *)dnt_entry, KEY_0f, ft_key_buf); 763 soc_mem_field_set(unit, ftk_mem, (uint32 *)ftk_entry, KEYf, ft_key_buf); 764 765 } else { 766 767 /* Double Wide Key */ 768 769 SHR_BITCOPY_RANGE(ft_key_buf, 0, ftk_fld, 0, ftk_single_bits); 770 FTK_PRINT_ARRAY_U32(unit, "FTK_FIELD0 : ", ftk_single_words, ft_key_buf); 771 soc_mem_field_set(unit, dnt_mem, (uint32 *)dnt_entry, KEY_0f, ft_key_buf); 772 soc_mem_field_set(unit, ftk_mem, (uint32 *)ftk_entry, KEY_0f, ft_key_buf); 773 774 SHR_BITCOPY_RANGE(ft_key_buf, 0, ftk_fld, ftk_single_bits, ftk_single_bits); 775 FTK_PRINT_ARRAY_U32(unit, "FTK_FIELD1 : ", ftk_single_words, ft_key_buf); 776 soc_mem_field_set(unit, dnt_mem, (uint32 *)dnt_entry, KEY_1f, ft_key_buf); 777 soc_mem_field_set(unit, ftk_mem, (uint32 *)ftk_entry, KEY_1f, ft_key_buf); 778 } 779 780 if (k_mode == bcmiFtGroupModeDouble) { 781 782 soc_mem_field32_set(unit, dnt_mem, (uint32 *)dnt_entry, BASE_VALID_1f, 2); 783 soc_mem_field32_set(unit, ftk_mem, (uint32 *)ftk_entry, BASE_VALID_1f, 2); 784 785 soc_mem_field32_set(unit, dnt_mem, (uint32 *)dnt_entry, BASE_VALID_0f, 1); 786 soc_mem_field32_set(unit, ftk_mem, (uint32 *)ftk_entry, BASE_VALID_0f, 1); 787 } else { 788 789 soc_mem_field32_set(unit, dnt_mem, (uint32 *)dnt_entry, BASE_VALID_0f, 1); 790 soc_mem_field32_set(unit, ftk_mem, (uint32 *)ftk_entry, BASE_VALIDf, 1); 791 } 792 793 794 soc_mem_field32_set(unit, dnt_mem, (uint32 *)dnt_entry, KEY_TYPEf, key_mode); 795 soc_mem_field32_set(unit, ftk_mem, (uint32 *)ftk_entry, KEY_TYPEf, key_mode); 796 797 soc_mem_field32_set(unit, dnt_mem, (uint32 *)dnt_entry, DO_NOT_LEARNf, 1); 798 soc_mem_field32_set(unit, dnt_mem, (uint32 *)dnt_entry, DO_NOT_FTf, 1); 799 800 soc_mem_field32_set(unit, dnt_mem, (uint32 *)dnt_entry, VALIDf, 1); 801 802 rv = soc_mem_write(unit, dnt_mem, MEM_BLOCK_ALL, 0, dnt_entry); 803 BCMI_CLEANUP_IF_ERROR(rv); 804 dnt_entry_created = 1; 805 806 rv = soc_mem_search(unit, ftk_mem, MEM_BLOCK_ALL, &ft_index, 807 ftk_entry, ftk_entry, 0); 808 if (BCM_SUCCESS(rv)) { 809 ag_index = (d_mode == bcmiFtGroupModeDouble) ? 810 (ft_index * 2) : (ft_index); 811 sal_memset(&ag_entry, 0, sizeof (bsc_ag_age_table_entry_t)); 812 rv = soc_mem_read(unit, ag_mem, MEM_BLOCK_ANY, ag_index, &ag_entry); 813 BCMI_CLEANUP_IF_ERROR(rv); 814 815 hw_group_id = soc_mem_field32_get(unit, ag_mem, &ag_entry, GROUP_IDf); 816 LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, "Key parameters for" 817 " user entry exists for group=%d. \n"), hw_group_id)); 818 rv = BCM_E_EXISTS; 819 BCMI_CLEANUP_IF_ERROR(rv); 820 } 821 822 /* Insert the entry into FT_KEY_SINGLE or FT_KEY_DOUBLE 823 * based on the group?s ft_key_mode. 824 */ 825 rv = soc_mem_generic_insert(unit, ftk_mem, MEM_BLOCK_ALL, 0, ftk_entry, NULL, &ft_index); 826 827 /* If the insert fails, clean up the single entry and 828 * return the error code to user. 829 */ 830 BCMI_CLEANUP_IF_ERROR(rv); 831 LOG_INFO(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, "FT insert successful: ft index = %d\n"), ft_index)); 832 833 834 /* If insert succeeds, use the index from the insert 835 * operation to populate the BSC_DT_FLEX_SESSION_DATA_SINGLE 836 * or BSC_DT_FLEX_SESSION_DATA_DOUBLE based in the group?s 837 * ft_data_mode. 838 * The actual offset for each ALU engine can be derived 839 * from the PDD bitmap (alternately, this info is already 840 * available in the group?s template info). 841 */ 842 if (d_mode == bcmiFtGroupModeSingle) { 843 ftd_mem = BSC_DT_FLEX_SESSION_DATA_SINGLEm; 844 ag_index = ft_index; 845 } else { 846 ftd_mem = BSC_DT_FLEX_SESSION_DATA_DOUBLEm; 847 ag_index = ft_index * 2; 848 } 849 850 memsize = soc_mem_entry_bytes(unit, ftd_mem); 851 FTK_ALLOC(ftd_entry, memsize, "FT DATA Mem Entry"); 852 853 /* Pre-load data table entry for non-zero elements. 854 */ 855 rv = bcmi_ftk_user_entry_data_fill(unit, flow_group_id, 856 ftd_mem, ftd_entry); 857 BCMI_CLEANUP_IF_ERROR(rv); 858 859 /* set VALID=1 in the SESSION_TABLE */ 860 soc_mem_field32_set(unit, ftd_mem, ftd_entry, VALIDf, 1); 861 862 /* Write DATA table entry. */ 863 rv = soc_mem_write(unit, ftd_mem, MEM_BLOCK_ALL, ft_index, ftd_entry); 864 BCMI_CLEANUP_IF_ERROR(rv); 865 866 FTK_PRINT_ARRAY_U32(unit, "FTD_ENTRY: ", BYTES2WORDS(memsize), ftd_entry); 867 868 /* If insert succeeds, use the index from the insert operation 869 * to populate GROUP_ID in BSC_AG_AGE_TABLE and mark ENTRY_VALID=1. 870 */ 871 sal_memset(&ag_entry, 0, sizeof (bsc_ag_age_table_entry_t)); 872 soc_mem_field32_set(unit, ag_mem, &ag_entry, GROUP_IDf, flow_group_id); 873 soc_mem_field32_set(unit, ag_mem, &ag_entry, ENTRY_VALIDf, 1); 874 rv = soc_mem_write(unit, ag_mem, MEM_BLOCK_ALL, ag_index, &ag_entry); 875 BCMI_CLEANUP_IF_ERROR(rv); 876 877 /* Delete the one-entry DO_NOT_FT_ENTRY to allow 878 * flowtracking for the user installed entry. 879 */ 880 soc_mem_field32_set(unit, dnt_mem, dnt_entry, DO_NOT_LEARNf, 0); 881 soc_mem_field32_set(unit, dnt_mem, dnt_entry, DO_NOT_FTf, 0); 882 883 soc_mem_field32_set(unit, dnt_mem, dnt_entry, VALIDf, 0); 884 rv = soc_mem_write(unit, dnt_mem, MEM_BLOCK_ALL, 0, dnt_entry); 885 BCMI_CLEANUP_IF_ERROR(rv); 886 dnt_entry_created = 0; 887 888 /* Populate output entry_handle */ 889 entry_handle->flow_key_mode = k_mode; 890 entry_handle->flow_key_type = key_type; 891 entry_handle->flow_index = ft_index; 892 entry_handle->flow_group_id = flow_group_id; 893 894 /* Update Learn counter */ 895 bcmi_ftk_group_learn_counter_update(unit, flow_group_id, 1); 896 897 cleanup: 898 if (dnt_entry_created == 1) { 899 soc_mem_field32_set(unit, dnt_mem, dnt_entry, DO_NOT_LEARNf, 0); 900 soc_mem_field32_set(unit, dnt_mem, dnt_entry, DO_NOT_FTf, 0); 901 902 soc_mem_field32_set(unit, dnt_mem, dnt_entry, VALIDf, 0); 903 (void)soc_mem_write(unit, dnt_mem, MEM_BLOCK_ALL, 0, dnt_entry); 904 } 905 906 FTK_FREE(dnt_entry); 907 FTK_FREE(ft_key); 908 FTK_FREE(ftk_fld); 909 FTK_FREE(ft_key_buf); 910 FTK_FREE(ftk_entry); 911 FTK_FREE(ftd_entry); 912 913 return rv; 914 } 915 916 /* 917 * Function: 918 * bcmi_ftk_user_entry_handle_validate 919 * Purpose: 920 * Validate given entry handle. 921 * Parameters: 922 * unit - (IN) BCM device id. 923 * entry_hdl - (IN) Entry handle. 924 * 925 * Returns: 926 * BCM_E_XXX 927 */ 928 STATIC int 929 bcmi_ftk_user_entry_handle_validate( 930 int unit, 931 bcm_flowtracker_user_entry_handle_t *entry_hdl) 932 { 933 int rv; 934 int ag_index; 935 soc_mem_t mem; 936 bsc_ag_age_table_entry_t entry; 937 bcmi_ft_group_key_data_mode_t k_mode; 938 939 if (entry_hdl == NULL) { 940 return BCM_E_PARAM; 941 } 942 943 rv = bcmi_ftk_group_sw_entries_check(unit, entry_hdl->flow_group_id); 944 BCM_IF_ERROR_RETURN(rv); 945 946 rv = bcmi_ft_group_extraction_mode_get(unit, 947 1, entry_hdl->flow_group_id, &k_mode); 948 BCM_IF_ERROR_RETURN(rv); 949 950 if (k_mode == bcmiFtGroupModeDouble) { 951 ag_index = entry_hdl->flow_index * 2; 952 } else { 953 ag_index = entry_hdl->flow_index; 954 } 955 956 mem = BSC_AG_AGE_TABLEm; 957 sal_memset(&entry, 0, sizeof (bsc_ag_age_table_entry_t)); 958 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, ag_index, &entry); 959 BCM_IF_ERROR_RETURN(rv); 960 961 if(FALSE == soc_mem_field32_get(unit, mem, &entry, ENTRY_VALIDf)) { 962 return BCM_E_NOT_FOUND; 963 } 964 965 if(entry_hdl->flow_group_id != 966 soc_mem_field32_get(unit, mem, &entry, GROUP_IDf)) { 967 return BCM_E_PARAM; 968 } 969 970 return BCM_E_NONE; 971 } 972 973 974 /* 975 * Function: 976 * bcmi_ftk_user_entry_get 977 * Purpose: 978 * Fetch user entry info given the entry handle. 979 * Parameters: 980 * unit - (IN) Unit number. 981 * entry_handle - (IN) Flowtracker user entry handle. 982 * num_user_entry_params - (IN) Number of user entry params. 983 * user_entry_param_list - (IN/OUT) List of user entry params added in the flow entry. 984 * actual_user_entry_params - (OUT) Actual number of params in the user entry. 985 * Returns: 986 * BCM_E_xxx 987 * Notes: 988 */ 989 int 990 bcmi_ftk_user_entry_get( 991 int unit, 992 bcm_flowtracker_user_entry_handle_t *entry_handle, 993 int num_user_entry_params, 994 bcm_flowtracker_tracking_param_info_t *user_entry_param_list, 995 int *actual_user_entry_params) 996 { 997 int ii; 998 uint8 *ele_data; 999 bcmi_ft_alu_key_t *key_alu; 1000 int start, length, num_key_els; 1001 int actual_params = 0; 1002 int key_offset, keytype_offset; 1003 1004 int memsize; 1005 int ft_index; 1006 int ftk_single_bits = 0; 1007 int ftk_single_bytes, ftk_width; 1008 int ftk_single_words; 1009 uint8 *ft_key = NULL, *ft_key_tmp; 1010 uint32 *ftk_fld = NULL; 1011 uint32 *ftk_entry = NULL; 1012 uint32 *ft_key_buf = NULL; 1013 soc_mem_t ftk_mem; 1014 bcmi_ft_group_key_data_mode_t k_mode; 1015 bcmi_ft_group_alu_info_t *key_ext_info; 1016 bcm_flowtracker_tracking_param_info_t *track_param; 1017 bcm_flowtracker_group_t flow_group_id; 1018 1019 int rv = BCM_E_NONE; 1020 1021 if (entry_handle == NULL) { 1022 return BCM_E_PARAM; 1023 } 1024 if (actual_user_entry_params == NULL) { 1025 return BCM_E_PARAM; 1026 } 1027 if ((num_user_entry_params > 0) && (user_entry_param_list == NULL)) { 1028 return BCM_E_PARAM; 1029 } 1030 1031 rv = bcmi_ftk_user_entry_handle_validate(unit, entry_handle); 1032 BCM_IF_ERROR_RETURN(rv); 1033 1034 1035 ft_index = entry_handle->flow_index; 1036 k_mode = entry_handle->flow_key_mode; 1037 flow_group_id = entry_handle->flow_group_id; 1038 1039 /* Make sure group is valid */ 1040 BCM_IF_ERROR_RETURN(bcmi_ftk_group_sw_entries_check(unit, flow_group_id)); 1041 1042 if (k_mode == bcmiFtGroupModeSingle) { 1043 ftk_mem = FT_KEY_SINGLEm; 1044 } else { 1045 ftk_mem = FT_KEY_DOUBLEm; 1046 } 1047 1048 memsize = soc_mem_entry_bytes(unit, ftk_mem); 1049 FTK_ALLOC(ftk_entry, memsize, "FT Key Mem Entry"); 1050 1051 rv = soc_mem_read(unit, ftk_mem, MEM_BLOCK_ANY, ft_index, ftk_entry); 1052 BCMI_CLEANUP_IF_ERROR(rv); 1053 1054 ftk_single_bits = soc_mem_field_length(unit, DO_NOT_FT_ENTRYm, KEY_0f); 1055 ftk_single_bytes = BITS2BYTES(ftk_single_bits); 1056 ftk_single_words = BYTES2WORDS(ftk_single_bytes); 1057 1058 /* Allocate memory for ft_key */ 1059 ftk_width = (ftk_single_bytes * 2); 1060 FTK_ALLOC(ft_key, ftk_width, "ft key"); 1061 FTK_ALLOC(ftk_fld, ftk_width, "ft field"); 1062 FTK_ALLOC(ft_key_buf, ftk_width, "ft key buffer"); 1063 1064 ft_key_tmp = ft_key; 1065 1066 if (k_mode == bcmiFtGroupModeSingle) { 1067 soc_mem_field_get(unit, ftk_mem, (uint32 *)ftk_entry, KEYf, ft_key_buf); 1068 FTK_PRINT_ARRAY_U32(unit, "FTK_FIELD0: ", ftk_single_words, ft_key_buf); 1069 SHR_BITCOPY_RANGE(ftk_fld, 0, ft_key_buf, 0, ftk_single_bits); 1070 } else { 1071 1072 /* High part of the Key */ 1073 soc_mem_field_get(unit, ftk_mem, (uint32 *)ftk_entry, KEY_1f, ft_key_buf); 1074 FTK_PRINT_ARRAY_U32(unit, "FTK_FIELD1: ", ftk_single_words, ft_key_buf); 1075 SHR_BITCOPY_RANGE(ftk_fld, ftk_single_bits, ft_key_buf, 0, ftk_single_bits); 1076 1077 /* Low part of the Key */ 1078 soc_mem_field_get(unit, ftk_mem, (uint32 *)ftk_entry, KEY_0f, ft_key_buf); 1079 FTK_PRINT_ARRAY_U32(unit, "FTK_FIELD0: ", ftk_single_words, ft_key_buf); 1080 SHR_BITCOPY_RANGE(ftk_fld, 0, ft_key_buf, 0, ftk_single_bits); 1081 } 1082 for (ii = 0; ii < BYTES2WORDS(ftk_width); ii++) { 1083 _SHR_PACK_U32(ft_key_tmp, ftk_fld[(BYTES2WORDS(ftk_width) - ii - 1)]); 1084 } 1085 FTK_PRINT_ARRAY(unit, "Full Key: ", ftk_width, ft_key); 1086 1087 key_ext_info = BCMI_FT_GROUP_EXT_KEY_INFO(unit, flow_group_id); 1088 num_key_els = BCMI_FT_GROUP_EXT_INFO(unit, flow_group_id).num_key_info; 1089 1090 keytype_offset = 8; 1091 ftk_width = BYTES2BITS(ftk_width); 1092 1093 for (ii = 0; ii < num_key_els; ii++) { 1094 key_alu = &(key_ext_info->key1); 1095 start = key_alu->location; 1096 length = key_alu->length; 1097 1098 if (actual_params < num_user_entry_params) { 1099 track_param = &(user_entry_param_list[actual_params]); 1100 ele_data = &(track_param->tracking_data[0]); 1101 1102 key_offset = (ftk_width - (keytype_offset + start + length)); 1103 track_param->param = key_ext_info->element_type1; 1104 FTK_CPY(ele_data, &ft_key[BITS2BYTES(key_offset)], BITS2BYTES(length)); 1105 1106 FTK_PRINT_ARRAY(unit, "Element:", BITS2BYTES(length), track_param->tracking_data); 1107 } 1108 1109 1110 actual_params++; 1111 key_ext_info++; 1112 } 1113 1114 *actual_user_entry_params = actual_params; 1115 1116 cleanup: 1117 1118 FTK_FREE(ft_key); 1119 FTK_FREE(ftk_fld); 1120 FTK_FREE(ftk_entry); 1121 FTK_FREE(ft_key_buf); 1122 1123 return rv; 1124 } 1125 1126 /* 1127 * Function: 1128 * bcmi_ftk_user_entry_handle_from_table 1129 * Purpose: 1130 * Create user entry handle if given index in 1131 * ag age table is valid. 1132 * Parameters: 1133 * unit - (IN) BCM device id. 1134 * mem - (IN) Memory. 1135 * index - (IN) Current index. 1136 * entry - (IN) Entry buffer 1137 * user_data - (IN/OUT) User data 1138 * finish - (OUT) Indicate that no need to traverse more 1139 * 1140 * Returns: 1141 * BCM_E_XXX 1142 */ 1143 STATIC int 1144 bcmi_ftk_user_entry_handle_from_table(int unit, soc_mem_t mem, 1145 uint32 index, void *entry, void *user_data, 1146 int *finish) 1147 { 1148 int handle_idx; 1149 int num_user_entry_handles; 1150 bcm_flowtracker_group_t flow_group_id; 1151 bcmi_ftk_user_entry_traverse_data_t *data = NULL; 1152 bcm_flowtracker_user_entry_handle_t *entry_handle = NULL; 1153 1154 if (!soc_mem_field32_get(unit, mem, entry, ENTRY_VALIDf)) { 1155 return BCM_E_NONE; 1156 } 1157 1158 data = (bcmi_ftk_user_entry_traverse_data_t *) user_data; 1159 1160 flow_group_id = soc_mem_field32_get(unit, mem, entry, GROUP_IDf); 1161 if (flow_group_id != data->flow_group_id) { 1162 return BCM_E_NONE; 1163 } 1164 1165 handle_idx = data->handle_idx; 1166 num_user_entry_handles = data->num_user_entry_handles; 1167 1168 if (handle_idx < num_user_entry_handles) { 1169 entry_handle = &(data->user_entry_handle_list[handle_idx]); 1170 1171 entry_handle->flow_key_mode = data->flow_key_mode; 1172 entry_handle->flow_key_type = data->flow_key_type; 1173 entry_handle->flow_group_id = data->flow_group_id; 1174 1175 if (data->flow_key_mode == bcmiFtGroupModeDouble) { 1176 entry_handle->flow_index = index / 2; 1177 } else { 1178 entry_handle->flow_index = index; 1179 } 1180 handle_idx++; 1181 } 1182 1183 data->handle_idx = handle_idx; 1184 data->actual_entries++; 1185 1186 if((num_user_entry_handles != 0) && 1187 (data->actual_entries == num_user_entry_handles)) { 1188 *finish = TRUE; 1189 } 1190 1191 return BCM_E_NONE; 1192 } 1193 1194 /* 1195 * Function: 1196 * bcmi_ftk_mem_traverse 1197 * Purpose: 1198 * Traverse function for calling callback per 1199 * entry in given table.. 1200 * Parameters: 1201 * unit - (IN) BCM device id. 1202 * mem - (IN) Memory. 1203 * cb - (IN) Callback function. 1204 * user_data - (IN/OUT) User data 1205 * 1206 * Returns: 1207 * BCM_E_XXX 1208 */ 1209 int 1210 bcmi_ftk_mem_traverse(int unit, soc_mem_t mem, 1211 bcmi_ftk_mem_entry_traverse_cb cb, void *user_data) 1212 { 1213 int rv = BCM_E_NONE; 1214 int fin = FALSE; 1215 int8 *buffer = NULL; 1216 void *entry = NULL; 1217 uint32 idx = 0, e_idx = 0; 1218 int mem_min = 0, mem_max = 0; 1219 uint32 chunk_size = 0, mem_entry_size = 0; 1220 1221 mem_min = soc_mem_index_min(unit, mem); 1222 mem_max = soc_mem_index_max(unit, mem); 1223 1224 chunk_size = ((mem_max - mem_min + 1) > BCMI_FTK_DMA_CHUNK_SIZE) ? 1225 BCMI_FTK_DMA_CHUNK_SIZE : (mem_max - mem_min + 1); 1226 mem_entry_size = SOC_MEM_WORDS(unit, mem) * sizeof(uint32); 1227 1228 buffer = soc_cm_salloc(unit, mem_entry_size * chunk_size, "mem buffer"); 1229 if (buffer == NULL) { 1230 return BCM_E_MEMORY; 1231 } 1232 for (idx = mem_min; ((idx <= mem_max) && (!fin)); idx += chunk_size) { 1233 chunk_size = ((mem_max - idx + 1) > BCMI_FTK_DMA_CHUNK_SIZE) ? 1234 BCMI_FTK_DMA_CHUNK_SIZE : (mem_max - idx + 1); 1235 1236 if ((rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ALL, 1237 idx, idx + chunk_size - 1, buffer)) != SOC_E_NONE) { 1238 break; 1239 } 1240 for (e_idx = 0; ((e_idx < chunk_size) && (!fin)); e_idx++) { 1241 entry = soc_mem_table_idx_to_pointer(unit, mem, void *, 1242 buffer, e_idx); 1243 rv = (*cb)(unit, mem, idx + e_idx, entry, user_data, &fin); 1244 if (BCM_FAILURE(rv)) { 1245 break; 1246 } 1247 } 1248 if (BCM_FAILURE(rv)) { 1249 break; 1250 } 1251 } 1252 1253 if (buffer != NULL) { 1254 soc_cm_sfree(unit, buffer); 1255 } 1256 return rv; 1257 } 1258 1259 /* 1260 * Function: 1261 * bcmi_ftk_user_entry_get_all 1262 * Purpose: 1263 * Fetch all user entries added in a against a given flow group. 1264 * Parameters: 1265 * unit - (IN) Unit number. 1266 * flow_group_id - (IN) Flowtracker flow group ID. 1267 * num_user_entry_handles - (IN) Number of export elements intended in the tempate. 1268 * user_entry_handle_list - (IN/OUT) List of user entry handles corresponding to the user entries added. 1269 * actual_user_entry_handles - (OUT) Actual number of user entry handles corresponding to the entries added. 1270 * Returns: 1271 * BCM_E_xxx 1272 * Notes: 1273 */ 1274 int 1275 bcmi_ftk_user_entry_get_all( 1276 int unit, 1277 bcm_flowtracker_group_t flow_group_id, 1278 int num_user_entry_handles, 1279 bcm_flowtracker_user_entry_handle_t *user_entry_handle_list, 1280 int *actual_user_entry_handles) 1281 { 1282 int rv = BCM_E_NONE; 1283 bcmi_ftk_user_entry_traverse_data_t data; 1284 bcmi_ft_group_ftfp_data_t ftfp_data; 1285 1286 BCM_IF_ERROR_RETURN( 1287 bcmi_ftk_group_sw_entries_check(unit, flow_group_id)); 1288 1289 rv = bcmi_ft_group_ftfp_data_get(unit, flow_group_id, &ftfp_data); 1290 BCM_IF_ERROR_RETURN(rv); 1291 1292 sal_memset(&data, 0, sizeof(bcmi_ftk_user_entry_traverse_data_t)); 1293 1294 data.flow_group_id = flow_group_id; 1295 data.flow_key_mode = ftfp_data.session_key_mode; 1296 data.flow_key_type = ftfp_data.session_key_type; 1297 data.num_user_entry_handles = num_user_entry_handles; 1298 data.handle_idx = 0; 1299 data.actual_entries = 0; 1300 data.user_entry_handle_list = user_entry_handle_list; 1301 1302 rv = bcmi_ftk_mem_traverse(unit, BSC_AG_AGE_TABLEm, 1303 bcmi_ftk_user_entry_handle_from_table, (void *) &data); 1304 BCM_IF_ERROR_RETURN(rv); 1305 1306 *actual_user_entry_handles = data.actual_entries; 1307 1308 return BCM_E_NONE; 1309 } 1310 1311 /* 1312 * Function: 1313 * bcmi_ftk_user_entry_delete 1314 * Purpose: 1315 * Delete user flow entry that is added earlier. 1316 * Parameters: 1317 * unit - (IN) Unit number. 1318 * flow_group_id - (IN) Flowtracker flow group ID. 1319 * entry_handle - (IN) User entry handle corresponding to the entry added. 1320 * Returns: 1321 * BCM_E_xxx 1322 * Notes: 1323 */ 1324 int 1325 bcmi_ftk_user_entry_delete( 1326 int unit, 1327 bcm_flowtracker_group_t flow_group_id, 1328 bcm_flowtracker_user_entry_handle_t *entry_handle) 1329 { 1330 int rv = BCM_E_NONE; 1331 int memsize; 1332 int ft_index, ag_index; 1333 uint32 key_type; 1334 int dnt_entry_created = 0; 1335 int ftk_single_bytes; 1336 uint32 *ftk_fld = NULL; 1337 uint32 *ftk_entry = NULL; 1338 soc_mem_t dnt_mem, ftk_mem, ftd_mem, ag_mem; 1339 do_not_ft_entry_entry_t *dnt_entry = NULL; 1340 bcmi_ft_group_key_data_mode_t k_mode, d_mode; 1341 1342 if (entry_handle == NULL) { 1343 return BCM_E_PARAM; 1344 } 1345 1346 /* Make sure group is valid */ 1347 rv = bcmi_ftk_group_sw_entries_check(unit, flow_group_id); 1348 BCM_IF_ERROR_RETURN(rv); 1349 1350 /* Validate entry handle */ 1351 rv = bcmi_ftk_user_entry_handle_validate(unit, entry_handle); 1352 BCM_IF_ERROR_RETURN(rv); 1353 1354 dnt_mem = DO_NOT_FT_ENTRYm; 1355 ag_mem = BSC_AG_AGE_TABLEm; 1356 1357 ft_index = entry_handle->flow_index; 1358 d_mode = k_mode = entry_handle->flow_key_mode; 1359 key_type = entry_handle->flow_key_type; 1360 1361 if (k_mode == bcmiFtGroupModeSingle) { 1362 ftk_mem = FT_KEY_SINGLEm; 1363 } else { 1364 ftk_mem = FT_KEY_DOUBLEm; 1365 } 1366 1367 /* Install the key entry in the one-entry ?DO_NOT_FT_ENTRY? 1368 * table and set actions as DO_NOT_LEARN = DO_NOT_FT = 1. 1369 */ 1370 ftk_single_bytes = soc_mem_field_length(unit, dnt_mem, KEY_0f); 1371 ftk_single_bytes = BITS2BYTES(ftk_single_bytes); 1372 1373 FTK_ALLOC(ftk_fld, ftk_single_bytes, "ft field"); 1374 1375 memsize = soc_mem_entry_bytes(unit, dnt_mem); 1376 FTK_ALLOC(dnt_entry, memsize, "DONOTFT Mem Entry"); 1377 1378 1379 memsize = soc_mem_entry_bytes(unit, ftk_mem); 1380 FTK_ALLOC(ftk_entry, memsize, "FT Key Mem Entry"); 1381 1382 rv = soc_mem_read(unit, ftk_mem, MEM_BLOCK_ANY, ft_index, ftk_entry); 1383 BCMI_CLEANUP_IF_ERROR(rv); 1384 1385 if (k_mode == bcmiFtGroupModeSingle) { 1386 1387 /* Single Wide Key */ 1388 soc_mem_field_get(unit, ftk_mem, (uint32 *)ftk_entry, KEYf, ftk_fld); 1389 soc_mem_field_set(unit, dnt_mem, (uint32 *)dnt_entry, KEY_0f, ftk_fld); 1390 1391 soc_mem_field32_set(unit, dnt_mem, (uint32 *)dnt_entry, BASE_VALID_0f, 1); 1392 } else { 1393 1394 /* Double Wide Key */ 1395 soc_mem_field_get(unit, ftk_mem, (uint32 *)ftk_entry, KEY_0f, ftk_fld); 1396 soc_mem_field_set(unit, dnt_mem, (uint32 *)dnt_entry, KEY_0f, ftk_fld); 1397 1398 soc_mem_field_get(unit, ftk_mem, (uint32 *)ftk_entry, KEY_1f, ftk_fld); 1399 soc_mem_field_set(unit, dnt_mem, (uint32 *)dnt_entry, KEY_1f, ftk_fld); 1400 1401 soc_mem_field32_set(unit, dnt_mem, (uint32 *)dnt_entry, BASE_VALID_1f, 1); 1402 soc_mem_field32_set(unit, dnt_mem, (uint32 *)dnt_entry, BASE_VALID_0f, 0); 1403 } 1404 1405 1406 key_type = soc_mem_field32_get(unit, ftk_mem, (uint32 *)ftk_entry, KEY_TYPEf); 1407 soc_mem_field32_set(unit, dnt_mem, (uint32 *)dnt_entry, KEY_TYPEf, key_type); 1408 1409 soc_mem_field32_set(unit, dnt_mem, (uint32 *)dnt_entry, DO_NOT_LEARNf, 1); 1410 soc_mem_field32_set(unit, dnt_mem, (uint32 *)dnt_entry, DO_NOT_FTf, 1); 1411 1412 soc_mem_field32_set(unit, dnt_mem, (uint32 *)dnt_entry, VALIDf, 1); 1413 1414 rv = soc_mem_write(unit, dnt_mem, MEM_BLOCK_ALL, 0, dnt_entry); 1415 BCMI_CLEANUP_IF_ERROR(rv); 1416 dnt_entry_created = 1; 1417 1418 1419 /* Delete flow from key table */ 1420 rv = soc_mem_delete(unit, ftk_mem, MEM_BLOCK_ALL, ftk_entry); 1421 LOG_INFO(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, "FT key delete: rv = %d. \n"), rv)); 1422 BCMI_CLEANUP_IF_ERROR(rv); 1423 1424 1425 if (d_mode == bcmiFtGroupModeSingle) { 1426 ftd_mem = BSC_DT_FLEX_SESSION_DATA_SINGLEm; 1427 ag_index = ft_index; 1428 } else { 1429 ftd_mem = BSC_DT_FLEX_SESSION_DATA_DOUBLEm; 1430 ag_index = ft_index * 2; 1431 } 1432 1433 1434 /* Set VALID=0 in DATA table. */ 1435 rv = soc_mem_field32_modify(unit, ftd_mem, ft_index, VALIDf, 0); 1436 BCMI_CLEANUP_IF_ERROR(rv); 1437 1438 /* Set VALID=0 in AGE table. */ 1439 rv = soc_mem_field32_modify(unit, ag_mem, ag_index, ENTRY_VALIDf, 0); 1440 BCMI_CLEANUP_IF_ERROR(rv); 1441 1442 /* Update Learn counter */ 1443 bcmi_ftk_group_learn_counter_update(unit, flow_group_id, -1); 1444 1445 cleanup: 1446 if (dnt_entry_created == 1) { 1447 1448 /* Delete the one-entry DO_NOT_FT_ENTRY to allow 1449 * flowtracking for the user installed entry. 1450 */ 1451 soc_mem_field32_set(unit, dnt_mem, dnt_entry, DO_NOT_LEARNf, 0); 1452 soc_mem_field32_set(unit, dnt_mem, dnt_entry, DO_NOT_FTf, 0); 1453 1454 soc_mem_field32_set(unit, dnt_mem, dnt_entry, VALIDf, 0); 1455 (void) soc_mem_write(unit, dnt_mem, MEM_BLOCK_ALL, 0, dnt_entry); 1456 } 1457 1458 FTK_FREE(dnt_entry); 1459 FTK_FREE(ftk_fld); 1460 FTK_FREE(ftk_entry); 1461 1462 return rv; 1463 1464 } 1465 1466 /* 1467 * Function: 1468 * bcmi_ftk_user_entry_delete_all 1469 * Purpose: 1470 * Delete user flow entry that is added earlier. 1471 * Parameters: 1472 * unit - (IN) Unit number. 1473 * flow_group_id - (IN) Flowtracker flow group ID. 1474 * Returns: 1475 * BCM_E_xxx 1476 * Notes: 1477 */ 1478 int 1479 bcmi_ftk_user_entry_delete_all( 1480 int unit, 1481 bcm_flowtracker_group_t flow_group_id) 1482 { 1483 int ix; 1484 int rv; 1485 int num_hdl; 1486 bcm_flowtracker_user_entry_handle_t *hdl_list = NULL; 1487 1488 rv = bcmi_ftk_user_entry_get_all( 1489 unit, 1490 flow_group_id, 1491 0, 1492 NULL, 1493 &num_hdl); 1494 BCM_IF_ERROR_RETURN(rv); 1495 1496 if (num_hdl == 0) { 1497 return BCM_E_NONE; 1498 } 1499 1500 FTK_ALLOC(hdl_list, 1501 (num_hdl * sizeof(bcm_flowtracker_user_entry_handle_t)), 1502 "FTK Entry handles"); 1503 1504 rv = bcmi_ftk_user_entry_get_all( 1505 unit, 1506 flow_group_id, 1507 num_hdl, 1508 hdl_list, 1509 &num_hdl); 1510 BCMI_CLEANUP_IF_ERROR(rv); 1511 1512 for (ix = 0; ix < num_hdl; ix++) { 1513 rv = bcmi_ftk_user_entry_delete(unit, flow_group_id, &(hdl_list[ix])); 1514 BCMI_CLEANUP_IF_ERROR(rv); 1515 } 1516 1517 cleanup: 1518 FTK_FREE(hdl_list); 1519 1520 return rv; 1521 1522 } 1523 1524 #else /* BCM_FLOWTRCAKER_SUPPORT*/ 1525 int bcmi_ft_group_not_empty; 1526 #endif /* BCM_FLOWTRCAKER_SUPPORT */ 1527