flowtracker.c (293619B)
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 * Flowtracker - Flow Tracking embedded APP interface 8 * Purpose: API to configure flowtracker embedded app interface. 9 */ 10 11 #include <shared/bsl.h> 12 #include <soc/defs.h> 13 #include <soc/drv.h> 14 #include <soc/tomahawk.h> 15 #include <shared/alloc.h> 16 #include <shared/idxres_fl.h> 17 18 #include <bcm/types.h> 19 #include <bcm/error.h> 20 21 #include <bcm_int/esw/flowtracker.h> 22 #include <bcm_int/esw/tomahawk.h> 23 #include <bcm_int/esw/maverick2.h> 24 #include <bcm_int/esw/xgs5.h> 25 #include <bcm_int/esw/switch.h> 26 #include <bcm_int/esw/collector.h> 27 #include <bcm_int/esw/udf.h> 28 29 #if defined(INCLUDE_FLOWTRACKER) 30 31 /* Flow tracker global information */ 32 _bcm_int_ft_info_t *ft_global_info[BCM_MAX_NUM_UNITS] = {0}; 33 34 /* List of flowtracker export templates info */ 35 extern _bcm_int_ft_export_template_info_t *ft_export_template_info_list[BCM_MAX_NUM_UNITS]; 36 37 /* List of flowtracker collector info*/ 38 extern _bcm_int_ft_collector_info_t *ft_collector_info_list[BCM_MAX_NUM_UNITS]; 39 extern _bcm_int_ft_v2_collector_info_t *ft_v2_collector_info_list[BCM_MAX_NUM_UNITS]; 40 extern _bcm_int_ft_v2_export_profile_info_t *ft_v2_export_profile_info_list[BCM_MAX_NUM_UNITS]; 41 42 /* List of flowtracker flow_group info*/ 43 extern _bcm_int_ft_flow_group_info_t *ft_flow_group_info_list[BCM_MAX_NUM_UNITS]; 44 45 /* List of flowtracker flow_group info*/ 46 extern _bcm_int_ft_elph_profile_info_t *ft_elph_profile_info_list[BCM_MAX_NUM_UNITS]; 47 48 /* Action conflict check */ 49 #define FT_ACTION_CONFLICT(_action_a, _action_b) \ 50 if ((_action_a) == (_action_b)) { \ 51 return BCM_E_CONFIG; \ 52 } 53 54 /* Map export elements to internal names */ 55 typedef struct _bcm_th_ft_template_support_mapping_s { 56 bcm_flowtracker_export_element_type_t element; 57 shr_ft_template_info_elem_t int_element; 58 uint16 data_size; 59 } _bcm_th_ft_template_support_mapping_t; 60 61 /* Template elements API <--> app mapping */ 62 STATIC _bcm_th_ft_template_support_mapping_t _bcm_th_ft_template_element_mapping[] = { 63 {bcmFlowtrackerExportElementTypeSrcIPv4, SHR_FT_TEMPLATE_INFO_ELEM_SRC_IPV4, 4}, 64 {bcmFlowtrackerExportElementTypeDstIPv4, SHR_FT_TEMPLATE_INFO_ELEM_DST_IPV4, 4}, 65 {bcmFlowtrackerExportElementTypeL4SrcPort, SHR_FT_TEMPLATE_INFO_ELEM_L4_SRC_PORT, 2}, 66 {bcmFlowtrackerExportElementTypeL4DstPort, SHR_FT_TEMPLATE_INFO_ELEM_L4_DST_PORT, 2}, 67 {bcmFlowtrackerExportElementTypeIPProtocol, SHR_FT_TEMPLATE_INFO_ELEM_IP_PROTOCOL, 1}, 68 {bcmFlowtrackerExportElementTypePktCount, SHR_FT_TEMPLATE_INFO_ELEM_PKT_TOTAL_COUNT, 4}, 69 {bcmFlowtrackerExportElementTypeByteCount, SHR_FT_TEMPLATE_INFO_ELEM_BYTE_TOTAL_COUNT, 6}, 70 {bcmFlowtrackerExportElementTypeFlowStartTimeMsecs, SHR_FT_TEMPLATE_INFO_ELEM_FLOW_START_TS_MSEC, 8}, 71 {bcmFlowtrackerExportElementTypeObservationTimeMsecs, SHR_FT_TEMPLATE_INFO_ELEM_OBS_TS_MSEC, 8}, 72 {bcmFlowtrackerExportElementTypeFlowtrackerGroup, SHR_FT_TEMPLATE_INFO_ELEM_GROUP_ID, 1}, 73 {bcmFlowtrackerExportElementTypeOuterVlanTag, SHR_FT_TEMPLATE_INFO_ELEM_VNID, 2}, 74 {bcmFlowtrackerExportElementTypeCustom, SHR_FT_TEMPLATE_INFO_ELEM_CUSTOM, 16}, 75 {bcmFlowtrackerExportElementTypeInnerSrcIPv4, SHR_FT_TEMPLATE_INFO_ELEM_INNER_SRC_IPV4, 4}, 76 {bcmFlowtrackerExportElementTypeInnerDstIPv4, SHR_FT_TEMPLATE_INFO_ELEM_INNER_DST_IPV4, 4}, 77 {bcmFlowtrackerExportElementTypeInnerL4SrcPort, SHR_FT_TEMPLATE_INFO_ELEM_INNER_L4_SRC_PORT, 2}, 78 {bcmFlowtrackerExportElementTypeInnerL4DstPort, SHR_FT_TEMPLATE_INFO_ELEM_INNER_L4_DST_PORT, 2}, 79 {bcmFlowtrackerExportElementTypeInnerIPProtocol, SHR_FT_TEMPLATE_INFO_ELEM_INNER_IP_PROTOCOL, 1}, 80 }; 81 82 #ifdef BCM_WARM_BOOT_SUPPORT 83 STATIC int _bcm_th_ft_scache_alloc(int unit, int create); 84 STATIC int _bcm_th_ft_wb_recover(int unit); 85 #define _BCM_FT_WB_INVALID_COLLECTOR_ID 0xFFFF 86 #endif /* BCM_WARM_BOOT_SUPPORT */ 87 88 /* TD3 chunk index to FT qualifier mapping */ 89 static int _bcm_td3_ft_udf_chunk_to_qual_mapping[] = { 90 SHR_FT_EM_QUAL_UDF_CHUNK0, 91 SHR_FT_EM_QUAL_UDF_CHUNK1, 92 SHR_FT_EM_QUAL_UDF_CHUNK2, 93 SHR_FT_EM_QUAL_UDF_CHUNK3, 94 SHR_FT_EM_QUAL_UDF_CHUNK4, 95 SHR_FT_EM_QUAL_UDF_CHUNK5, 96 SHR_FT_EM_QUAL_UDF_CHUNK6, 97 SHR_FT_EM_QUAL_UDF_CHUNK7, 98 SHR_FT_EM_QUAL_UDF_CHUNK8, 99 SHR_FT_EM_QUAL_UDF_CHUNK9, 100 SHR_FT_EM_QUAL_UDF_CHUNK10, 101 SHR_FT_EM_QUAL_UDF_CHUNK11, 102 SHR_FT_EM_QUAL_UDF_CHUNK12, 103 SHR_FT_EM_QUAL_UDF_CHUNK13, 104 SHR_FT_EM_QUAL_UDF_CHUNK14, 105 SHR_FT_EM_QUAL_UDF_CHUNK15, 106 }; 107 108 #define _BCM_FT_TH_MAX_UDF_CHUNKS 16 109 /*--------------------------------------------------------------------------------------* 110 * Each chunk or chunk pair corresponds to the data qualifier as marked below: 111 * 112 * 15 -- 14 13 -- 12 11 -- 10 9 8 7 -- 6 5 -- 4 3 -- 2 1 0 113 *{________} {_______} {_______} {___}{___} {______} {______} {_____} {___}{___} 114 * Data9 Data8 Data7 Data6 Data5 Data4 Data3 Data2 Data1 Data0 115 * (32bit) (32bit) (32bit) (16bit)(16bit) (32bit) (32bit) (32bit)(16bit)(16bit) 116 * {_________________________________________} {___________________________________} 117 * || || 118 * UDF_2 UDF_1 119 *--------------------------------------------------------------------------------------*/ 120 121 typedef struct _bcm_th_ft_udf_chunk_info_s { 122 /* Internal FT qualifier */ 123 int qual; 124 125 /* Size of the chunk */ 126 int size; 127 } _bcm_th_ft_udf_chunk_info_t; 128 129 STATIC _bcm_th_ft_udf_chunk_info_t _bcm_th_ft_udf_chunk_info[_BCM_FT_TH_MAX_UDF_CHUNKS] = 130 { 131 {SHR_FT_EM_QUAL_UDF_CHUNK0, 2}, 132 {SHR_FT_EM_QUAL_UDF_CHUNK1, 2}, 133 {SHR_FT_EM_QUAL_UDF_CHUNK2, 4}, 134 {SHR_FT_EM_QUAL_UDF_CHUNK2, 4}, 135 {SHR_FT_EM_QUAL_UDF_CHUNK3, 4}, 136 {SHR_FT_EM_QUAL_UDF_CHUNK3, 4}, 137 {SHR_FT_EM_QUAL_UDF_CHUNK4, 4}, 138 {SHR_FT_EM_QUAL_UDF_CHUNK4, 4}, 139 {SHR_FT_EM_QUAL_UDF_CHUNK5, 2}, 140 {SHR_FT_EM_QUAL_UDF_CHUNK6, 2}, 141 {SHR_FT_EM_QUAL_UDF_CHUNK7, 4}, 142 {SHR_FT_EM_QUAL_UDF_CHUNK7, 4}, 143 {SHR_FT_EM_QUAL_UDF_CHUNK8, 4}, 144 {SHR_FT_EM_QUAL_UDF_CHUNK8, 4}, 145 {SHR_FT_EM_QUAL_UDF_CHUNK9, 4}, 146 {SHR_FT_EM_QUAL_UDF_CHUNK9, 4}, 147 }; 148 /* 149 * Function: 150 * _bcm_th_ft_template_validate_convert 151 * Purpose: 152 * Validate the template and convert to app format 153 * Parameters: 154 * unit - (IN) BCM device number 155 * set_id - (IN) Set Id 156 * num_elements - (IN) Number of template elements 157 * elements - (IN) Elements list 158 * template - (OUT) Template info in internal format 159 * Returns: 160 * BCM_E_XXX - BCM error code. 161 */ 162 STATIC int 163 _bcm_th_ft_template_validate_convert(int unit, 164 uint16 set_id, 165 int num_elements, 166 bcm_flowtracker_export_element_info_t *elements, 167 _bcm_int_ft_export_template_info_t *template) 168 { 169 int i, j; 170 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 171 172 sal_memset(template, 0, sizeof(_bcm_int_ft_export_template_info_t)); 173 174 /* Validate set id. Should be between 256 and 65535 */ 175 if (!BCM_INT_FT_TEMPLATE_SET_ID_VALID(set_id)) { 176 return BCM_E_PARAM; 177 } 178 template->set_id = set_id; 179 180 if (num_elements > SHR_FT_TEMPLATE_MAX_INFO_ELEMENTS) { 181 return BCM_E_PARAM; 182 } 183 template->num_export_elements = num_elements; 184 185 for (i = 0; i < num_elements; i++) { 186 for (j = 0; j < SHR_FT_TEMPLATE_MAX_INFO_ELEMENTS; j++) { 187 if (elements[i].element == _bcm_th_ft_template_element_mapping[j].element) { 188 if (((elements[i].element == bcmFlowtrackerExportElementTypeOuterVlanTag) || 189 (elements[i].element == bcmFlowtrackerExportElementTypeCustom) || 190 (elements[i].element == bcmFlowtrackerExportElementTypeInnerSrcIPv4) || 191 (elements[i].element == bcmFlowtrackerExportElementTypeInnerDstIPv4) || 192 (elements[i].element == bcmFlowtrackerExportElementTypeInnerL4SrcPort) || 193 (elements[i].element == bcmFlowtrackerExportElementTypeInnerL4DstPort) || 194 (elements[i].element == bcmFlowtrackerExportElementTypeInnerIPProtocol)) && 195 (ft_info->cfg_mode < SHR_FT_CFG_MODE_V2)) { 196 return BCM_E_PARAM; 197 } 198 199 if ((elements[i].data_size != 0) && 200 (elements[i].data_size != 201 _bcm_th_ft_template_element_mapping[j].data_size)) { 202 return BCM_E_PARAM; 203 } 204 205 if (elements[i].element == 206 bcmFlowtrackerExportElementTypeFlowStartTimeMsecs) { 207 if (!(ft_info->flags & BCM_INT_FT_INFO_FLAGS_FLOW_START_TS)) { 208 return BCM_E_PARAM; 209 } 210 } 211 template->elements[i].element = 212 _bcm_th_ft_template_element_mapping[j].int_element; 213 template->elements[i].data_size = 214 _bcm_th_ft_template_element_mapping[j].data_size; 215 template->elements[i].id = 216 elements[i].info_elem_id; 217 if (elements[i].flags & 218 BCM_FLOWTRACKER_EXPORT_ELEMENT_FLAGS_ENTERPRISE) { 219 template->elements[i].enterprise = 1; 220 } 221 break; 222 } 223 } 224 if (j >= SHR_FT_TEMPLATE_MAX_INFO_ELEMENTS) { 225 /* No match found */ 226 return BCM_E_PARAM; 227 } 228 } 229 230 return BCM_E_NONE; 231 } 232 233 /* 234 * Function: 235 * _bcm_th_ft_collector_info_validate 236 * Purpose: 237 * Validate the collector params 238 * Parameters: 239 * unit - (IN) BCM device number 240 * collector - (IN) Collector data structure 241 * Returns: 242 * BCM_E_XXX - BCM error code. 243 */ 244 STATIC int 245 _bcm_th_ft_collector_info_validate(int unit, 246 bcm_flowtracker_collector_info_t *collector) 247 { 248 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 249 250 /* Only IPv4 over UDP is supported */ 251 if (collector->transport_type != 252 bcmFlowtrackerCollectorTransportTypeIpfixIpv4Udp) { 253 return BCM_E_UNAVAIL; 254 } 255 256 /* Validate the export length */ 257 if (collector->max_packet_length < SHR_FT_MIN_EXPORT_LENGTH || 258 collector->max_packet_length > ft_info->max_export_pkt_length) { 259 return BCM_E_PARAM; 260 } 261 262 return BCM_E_NONE; 263 } 264 265 /* 266 * Function: 267 * _bcm_th_ft_collector_export_profile_validate 268 * Purpose: 269 * Validate the collector and export profile params 270 * Parameters: 271 * unit - (IN) BCM device number 272 * collector - (IN) Collector data structure 273 * export_profile - (IN) Export profile data structure 274 * Returns: 275 * BCM_E_XXX - BCM error code. 276 */ 277 STATIC int 278 _bcm_th_ft_collector_export_profile_validate( 279 int unit, 280 bcm_collector_info_t *collector, 281 bcm_collector_export_profile_t *export_profile) 282 { 283 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 284 285 /* Check if the wire format can be supported */ 286 switch (export_profile->wire_format) { 287 case bcmCollectorWireFormatIpfix: 288 if (!(ft_info->uc_features & SHR_FT_UC_FEATURE_IPFIX_EXPORT)) { 289 return BCM_E_UNAVAIL; 290 } 291 break; 292 293 case bcmCollectorWireFormatProtoBuf: 294 if (!(ft_info->uc_features & SHR_FT_UC_FEATURE_PROTOBUF_EXPORT)) { 295 return BCM_E_UNAVAIL; 296 } 297 break; 298 299 default: 300 return BCM_E_UNAVAIL; 301 } 302 303 /* Only IPv4 over UDP is supported */ 304 if (collector->transport_type != bcmCollectorTransportTypeIpv4Udp) { 305 return BCM_E_UNAVAIL; 306 } 307 308 /* Validate the export length */ 309 if (export_profile->max_packet_length < SHR_FT_MIN_EXPORT_LENGTH || 310 export_profile->max_packet_length > ft_info->max_export_pkt_length) { 311 return BCM_E_PARAM; 312 } 313 314 return BCM_E_NONE; 315 } 316 317 /* 318 * Function: 319 * _bcm_th_ft_validate_aging_timer_interval 320 * Purpose: 321 * Validate the aging interval 322 * Parameters: 323 * unit - (IN) BCM device number 324 * aging_interval_ms - (IN) Aging interval in msec 325 * Returns: 326 * BCM_E_XXX - BCM error code. 327 */ 328 STATIC int 329 _bcm_th_ft_validate_aging_timer_interval(int unit, uint32 aging_interval_ms) 330 { 331 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 332 333 if (aging_interval_ms == 0) { 334 return BCM_E_PARAM; 335 } 336 337 if ((aging_interval_ms % BCM_INT_FT_AGING_INTERVAL_STEP_MSECS) != 0) { 338 return BCM_E_PARAM; 339 } 340 341 if (aging_interval_ms > 342 BCM_INT_FT_AGING_INTERVAL_SCAN_MULTIPLE * (ft_info->scan_interval_usecs / 1000)) { 343 return BCM_E_PARAM; 344 } 345 346 return BCM_E_NONE; 347 } 348 349 /* 350 * Function: 351 * _bcm_th_ft_fill_em_key_format_msg 352 * Purpose: 353 * Convert the EM 5-tuple key format from field data structure to 354 * App message format 355 * Parameters: 356 * qual - (IN) Qualifier info 357 * msg - (OUT) Key format message 358 * Returns: 359 * BCM_E_XXX - BCM error code. 360 */ 361 STATIC int 362 _bcm_th_ft_fill_em_key_format_msg(_bcm_field_group_qual_t qual, 363 shr_ft_msg_ctrl_em_key_format_t *msg) 364 { 365 int i, j, k; 366 uint16 offset, next_offset, width; 367 uint8 word_boundary; 368 369 if (qual.size != 5) { /* IPv4 5-tuple */ 370 return BCM_E_PARAM; 371 } 372 373 for (i = 0; i < qual.size; i++) { 374 for (j = 0; j < qual.offset_arr[i].num_offsets; j++) { 375 if (qual.offset_arr[i].offset[j] > 79) { 376 /* In Exact Match Mode 128 - whole key is not presented 377 * for lookup. Instead Bit 0-47 and Bit 80-160 are provided 378 * to UFT. Hence qualifier offsets at position greater than 379 * 80 bit are shifted by 32 bit for key. 380 */ 381 qual.offset_arr[i].offset[j] -= 32; 382 } 383 } 384 } 385 386 /* Some qual parts are contiguous but field stores them as separate parts, 387 * combine them to reduce the number of bitops the FW has to perform on each 388 * flow 389 */ 390 for (i = 0; i < qual.size; i++) { 391 j = 0; 392 while(j < (qual.offset_arr[i].num_offsets - 1)) { 393 offset = qual.offset_arr[i].offset[j]; 394 width = qual.offset_arr[i].width[j]; 395 next_offset = qual.offset_arr[i].offset[j + 1]; 396 397 if ((offset + width) == next_offset) { 398 /* Increase the width */ 399 qual.offset_arr[i].width[j] += qual.offset_arr[i].width[j + 1]; 400 401 /* Remove the next element */ 402 for (k = j + 1; k < (qual.offset_arr[i].num_offsets - 1); k++) { 403 qual.offset_arr[i].offset[k] = qual.offset_arr[i].offset[k + 1]; 404 qual.offset_arr[i].width[k] = qual.offset_arr[i].width[k + 1]; 405 } 406 qual.offset_arr[i].num_offsets--; 407 } else { 408 j++; 409 } 410 } 411 } 412 413 sal_memset(msg, 0, sizeof(*msg)); 414 msg->key_size = 128; /* 128 bit view of the EM table is used */ 415 msg->num_qual = qual.size; 416 417 for (i = 0; i < qual.size; i++) { 418 switch (qual.qid_arr[i]) { 419 case bcmFieldQualifySrcIp: 420 msg->qual[i] = SHR_FT_EM_QUAL_SRC_IPV4; 421 break; 422 423 case bcmFieldQualifyDstIp: 424 msg->qual[i] = SHR_FT_EM_QUAL_DST_IPV4; 425 break; 426 427 case bcmFieldQualifyIpProtocol: 428 msg->qual[i] = SHR_FT_EM_QUAL_IP_PROTOCOL; 429 break; 430 431 case bcmFieldQualifyL4SrcPort: 432 msg->qual[i] = SHR_FT_EM_QUAL_L4_SRC_PORT; 433 break; 434 435 case bcmFieldQualifyL4DstPort: 436 msg->qual[i] = SHR_FT_EM_QUAL_L4_DST_PORT; 437 break; 438 439 default: 440 return BCM_E_PARAM; 441 } 442 443 for (j = 0, k = 0; j < qual.offset_arr[i].num_offsets; j++) { 444 offset = qual.offset_arr[i].offset[j]; 445 width = qual.offset_arr[i].width[j]; 446 447 word_boundary = offset + (SHR_FT_EM_KEY_DWORD_SIZE - 448 (offset % SHR_FT_EM_KEY_DWORD_SIZE)); 449 if ((offset + width) > word_boundary) { 450 /* The key is present in multiple words, split it into different 451 * offsets to help the FW 452 */ 453 msg->qual_parts[i].offset[k] = offset; 454 msg->qual_parts[i].width[k] = word_boundary - offset; 455 456 do { 457 k++; 458 msg->qual_parts[i].offset[k] = word_boundary; 459 msg->qual_parts[i].width[k] = width - (word_boundary - offset); 460 word_boundary += SHR_FT_EM_KEY_DWORD_SIZE; 461 } while(msg->qual_parts[i].width[k] > SHR_FT_EM_KEY_DWORD_SIZE); 462 463 k++; 464 465 } else { 466 msg->qual_parts[i].offset[k] = offset; 467 msg->qual_parts[i].width[k] = width; 468 k++; 469 } 470 } 471 msg->qual_parts[i].num_parts = k; 472 473 } 474 475 return BCM_E_NONE; 476 } 477 478 /* 479 * Function: 480 * _bcm_th_ft_field_qual_convert 481 * Purpose: 482 * Convert the field qualifier to app notation 483 * Parameters: 484 * field_qual - (IN) Field qualifier 485 * ft_qual - (OUT) Qualifier in app notation 486 * Returns: 487 * BCM_E_XXX - BCM error code. 488 */ 489 STATIC int 490 _bcm_th_ft_field_qual_convert(int field_qual, shr_ft_em_qual_t *ft_qual) 491 { 492 switch (field_qual) { 493 case bcmFieldQualifySrcIp: 494 *ft_qual = SHR_FT_EM_QUAL_SRC_IPV4; 495 break; 496 497 case bcmFieldQualifyDstIp: 498 *ft_qual = SHR_FT_EM_QUAL_DST_IPV4; 499 break; 500 501 case bcmFieldQualifyIpProtocol: 502 *ft_qual = SHR_FT_EM_QUAL_IP_PROTOCOL; 503 break; 504 505 case bcmFieldQualifyL4SrcPort: 506 *ft_qual = SHR_FT_EM_QUAL_L4_SRC_PORT; 507 break; 508 509 case bcmFieldQualifyL4DstPort: 510 *ft_qual = SHR_FT_EM_QUAL_L4_DST_PORT; 511 break; 512 513 case bcmFieldQualifyVxlanNetworkId: 514 *ft_qual = SHR_FT_EM_QUAL_VNID; 515 break; 516 517 case _bcmFieldQualifyData0: 518 *ft_qual = SHR_FT_EM_QUAL_UDF_CHUNK0; 519 break; 520 521 case _bcmFieldQualifyData1: 522 *ft_qual = SHR_FT_EM_QUAL_UDF_CHUNK1; 523 break; 524 525 case _bcmFieldQualifyData2: 526 *ft_qual = SHR_FT_EM_QUAL_UDF_CHUNK2; 527 break; 528 529 case _bcmFieldQualifyData3: 530 *ft_qual = SHR_FT_EM_QUAL_UDF_CHUNK3; 531 break; 532 533 case _bcmFieldQualifyData4: 534 *ft_qual = SHR_FT_EM_QUAL_UDF_CHUNK4; 535 break; 536 537 case _bcmFieldQualifyData5: 538 *ft_qual = SHR_FT_EM_QUAL_UDF_CHUNK5; 539 break; 540 541 case _bcmFieldQualifyData6: 542 *ft_qual = SHR_FT_EM_QUAL_UDF_CHUNK6; 543 break; 544 545 case _bcmFieldQualifyData7: 546 *ft_qual = SHR_FT_EM_QUAL_UDF_CHUNK7; 547 break; 548 549 case _bcmFieldQualifyData8: 550 *ft_qual = SHR_FT_EM_QUAL_UDF_CHUNK8; 551 break; 552 553 case _bcmFieldQualifyData9: 554 *ft_qual = SHR_FT_EM_QUAL_UDF_CHUNK9; 555 break; 556 557 case _bcmFieldQualifyData10: 558 *ft_qual = SHR_FT_EM_QUAL_UDF_CHUNK10; 559 break; 560 561 case _bcmFieldQualifyData11: 562 *ft_qual = SHR_FT_EM_QUAL_UDF_CHUNK11; 563 break; 564 565 case _bcmFieldQualifyData12: 566 *ft_qual = SHR_FT_EM_QUAL_UDF_CHUNK12; 567 break; 568 569 case _bcmFieldQualifyData13: 570 *ft_qual = SHR_FT_EM_QUAL_UDF_CHUNK13; 571 break; 572 573 case _bcmFieldQualifyData14: 574 *ft_qual = SHR_FT_EM_QUAL_UDF_CHUNK14; 575 break; 576 577 case _bcmFieldQualifyData15: 578 *ft_qual = SHR_FT_EM_QUAL_UDF_CHUNK15; 579 break; 580 581 case _bcmFieldQualifyPreLogicalTableId: 582 *ft_qual = SHR_FT_EM_QUAL_LT_ID; 583 break; 584 585 case bcmFieldQualifyInPort: 586 *ft_qual = SHR_FT_EM_QUAL_IN_PORT; 587 break; 588 589 default: 590 return BCM_E_PARAM; 591 } 592 return BCM_E_NONE; 593 } 594 595 /* 596 * Function: 597 * _bcm_td3_ft_em_group_create_msg_udf_get 598 * Purpose: 599 * Convert the UDF Id to the format, that app can understand 600 * Parameters: 601 * unit - (IN) BCM device number 602 * udf_id - (IN) UDF Id 603 * hint_id - (IN) Hint Id of the group 604 * tp_info - (OUT) Tracking param info 605 * qual_info - (OUT) UDF info split into multiple qualifiers 606 * num_qual - (OUT) Number of qualifers required to hold the UDF info 607 * Returns: 608 * BCM_E_XXX - BCM error code. 609 */ 610 STATIC int 611 _bcm_td3_ft_em_group_create_msg_udf_get(int unit, 612 bcm_udf_id_t udf_id, 613 bcm_field_hintid_t hint_id, 614 shr_ft_msg_ctrl_tp_info_t *tp_info, 615 shr_ft_msg_ctrl_qual_info_t *qual_info, 616 int *num_qual) 617 { 618 bcm_udf_chunk_info_t udf_chunk_info; 619 bcm_udf_abstract_pkt_format_info_t pkt_format_info; 620 uint16 base_offset; 621 int chunk, num_chunks; 622 _field_hints_t *f_ht = NULL; 623 _field_hint_t *hint_entry = NULL; 624 int hint, hint_start = 0, hint_width = 0; 625 int rv; 626 627 /* Get the UDF chunk info */ 628 bcm_udf_chunk_info_t_init(&udf_chunk_info); 629 rv = bcm_esw_udf_chunk_info_get(unit, udf_id, &udf_chunk_info); 630 BCM_IF_ERROR_RETURN(rv); 631 632 /* Get the base offset used by all the UDF chunks */ 633 rv = bcm_esw_udf_abstract_pkt_format_info_get(unit, 634 udf_chunk_info.abstract_pkt_format, 635 &pkt_format_info); 636 BCM_IF_ERROR_RETURN(rv); 637 638 switch (pkt_format_info.base_offset) { 639 case bcmUdfPktBaseOffsetStartOfOuterL2: 640 base_offset = SHR_FT_UDF_BASE_OFFSET_OUTER_L2; 641 break; 642 643 case bcmUdfPktBaseOffsetStartOfOuterL3: 644 base_offset = SHR_FT_UDF_BASE_OFFSET_OUTER_L3; 645 break; 646 647 case bcmUdfPktBaseOffsetStartOfOuterL4: 648 base_offset = SHR_FT_UDF_BASE_OFFSET_OUTER_L4; 649 break; 650 651 case bcmUdfPktBaseOffsetStartOfOuterL5: 652 base_offset = SHR_FT_UDF_BASE_OFFSET_OUTER_L5; 653 break; 654 655 default: 656 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 657 (BSL_META_U(unit, 658 "FT(unit %d) Error: Invalid base offset: " 659 "%d\n"), 660 unit, pkt_format_info.base_offset)); 661 return BCM_E_PARAM; 662 } 663 664 /* See if there are any hints associated with this Udf Id */ 665 hint = 0; 666 BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, hint_id, &f_ht)); 667 if (f_ht != NULL) { 668 hint_entry = f_ht->hints; 669 while (hint_entry != NULL) { 670 if ((hint_entry->hint->hint_type == bcmFieldHintTypeExtraction) && 671 (hint_entry->hint->qual == bcmFieldQualifyUdf) && 672 (hint_entry->hint->udf_id == udf_id)) { 673 674 if (((hint_entry->hint->start_bit % 8) != 0) || 675 (((hint_entry->hint->end_bit + 1) % 8) != 0)) { 676 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 677 (BSL_META_U(unit, 678 "FT(unit %d) Error: Hints not byte aligned \n"), 679 unit)); 680 return BCM_E_PARAM; 681 } 682 683 /* UDFs are extracted from the MSB, but hints are specified from the LSB */ 684 hint = 1; 685 hint_start = udf_chunk_info.width - ((hint_entry->hint->end_bit + 1) / 8); 686 hint_width = (hint_entry->hint->end_bit - hint_entry->hint->start_bit + 1) / 8; 687 688 if ((udf_chunk_info.width - hint_width) > 689 _BCM_UDF_CTRL_OFFSET_GRAN(unit)) { 690 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 691 (BSL_META_U(unit, 692 "FT(unit %d) Error: Hint removes more " 693 "than 1 chunk \n"), 694 unit)); 695 return BCM_E_PARAM; 696 } 697 698 break; 699 } 700 hint_entry = hint_entry->next; 701 } 702 } 703 704 num_chunks = 0; 705 *num_qual = 0; 706 for (chunk = 0; chunk < _BCM_UDF_CTRL_MAX_UDF_CHUNKS(unit); chunk++) { 707 if(udf_chunk_info.chunk_bmap & (1 << chunk)) { 708 /* Populate the qualifier info */ 709 qual_info[*num_qual].qual = _bcm_td3_ft_udf_chunk_to_qual_mapping[chunk]; 710 qual_info[*num_qual].base_offset = base_offset; 711 tp_info->qual[num_chunks] = 712 _bcm_td3_ft_udf_chunk_to_qual_mapping[chunk]; 713 tp_info->udf = 1; 714 715 716 if (hint) { 717 if (num_chunks == 0) { 718 qual_info[*num_qual].relative_offset = 719 udf_chunk_info.offset + hint_start; 720 } else { 721 qual_info[*num_qual].relative_offset = 722 qual_info[*num_qual - 1].relative_offset + _BCM_UDF_CTRL_OFFSET_GRAN(unit); 723 } 724 725 if (hint_width <= _BCM_UDF_CTRL_OFFSET_GRAN(unit)) { 726 qual_info[*num_qual].width = hint_width; 727 } else { 728 hint_width -= _BCM_UDF_CTRL_OFFSET_GRAN(unit); 729 qual_info[*num_qual].width = _BCM_UDF_CTRL_OFFSET_GRAN(unit); 730 } 731 } else { 732 qual_info[*num_qual].width = _BCM_UDF_CTRL_OFFSET_GRAN(unit); 733 qual_info[*num_qual].relative_offset = 734 (_BCM_UDF_CTRL_OFFSET_GRAN(unit) * num_chunks) + 735 udf_chunk_info.offset; 736 } 737 738 num_chunks++; 739 (*num_qual)++; 740 } 741 } 742 tp_info->num_qual = num_chunks; 743 744 return BCM_E_NONE; 745 } 746 747 /* 748 * Function: 749 * _bcm_th_ft_em_group_create_msg_udf_get 750 * Purpose: 751 * Convert the UDF Id to the format, that app can understand 752 * Parameters: 753 * unit - (IN) BCM device number 754 * udf_id - (IN) UDF Id 755 * hint_id - (IN) Hint Id of the group 756 * tp_info - (OUT) Tracking param info 757 * qual_info - (OUT) UDF info split into multiple qualifiers 758 * num_qual - (OUT) Number of qualifers required to hold the UDF info 759 * Returns: 760 * BCM_E_XXX - BCM error code. 761 */ 762 int 763 _bcm_th_ft_em_group_create_msg_udf_get(int unit, 764 bcm_udf_id_t udf_id, 765 bcm_field_hintid_t hint_id, 766 shr_ft_msg_ctrl_tp_info_t *tp_info, 767 shr_ft_msg_ctrl_qual_info_t *qual_info, 768 int *num_qual) 769 { 770 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; 771 uint16 base_offset; 772 int chunk, num_chunks; 773 int chunk_size; 774 _field_hints_t *f_ht = NULL; 775 _field_hint_t *hint_entry = NULL; 776 int hint, hint_start = 0, hint_width = 0; 777 int rv; 778 779 rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id, &offset_info); 780 BCM_IF_ERROR_RETURN(rv); 781 782 if (((offset_info->start % 2) != 0) || ((offset_info->width % 2) != 0)) { 783 /* UDF width & start must be aligned to 2B boundary. Hints need to be 784 * used to mask off the unneeded bits 785 */ 786 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 787 (BSL_META_U(unit, 788 "FT(unit %d) Error: UDF start (%u) / width (%u)" 789 "not aligned to 2B \n"), 790 unit, offset_info->start, offset_info->width)); 791 return BCM_E_PARAM; 792 } 793 794 795 switch (offset_info->layer) { 796 case bcmUdfLayerL2Header: 797 base_offset = SHR_FT_UDF_BASE_OFFSET_OUTER_L2; 798 break; 799 800 case bcmUdfLayerL3OuterHeader: 801 base_offset = SHR_FT_UDF_BASE_OFFSET_OUTER_L3; 802 break; 803 804 case bcmUdfLayerL4OuterHeader: 805 base_offset = SHR_FT_UDF_BASE_OFFSET_OUTER_L4; 806 break; 807 808 default: 809 return BCM_E_UNAVAIL; 810 } 811 812 /* See if there are any hints associated with this Udf Id */ 813 hint = 0; 814 BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, hint_id, &f_ht)); 815 if (f_ht != NULL) { 816 hint_entry = f_ht->hints; 817 while (hint_entry != NULL) { 818 if ((hint_entry->hint->hint_type == bcmFieldHintTypeExtraction) && 819 (hint_entry->hint->qual == bcmFieldQualifyUdf) && 820 (hint_entry->hint->udf_id == udf_id)) { 821 822 if (((hint_entry->hint->start_bit % 8) != 0) || 823 (((hint_entry->hint->end_bit + 1) % 8) != 0)) { 824 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 825 (BSL_META_U(unit, 826 "FT(unit %d) Error: Hints not byte aligned \n"), 827 unit)); 828 return BCM_E_PARAM; 829 } 830 831 /* UDFs are extracted from the MSB, but hints are specified from the LSB */ 832 hint = 1; 833 hint_start = offset_info->width - ((hint_entry->hint->end_bit + 1) / 8); 834 hint_width = (hint_entry->hint->end_bit - hint_entry->hint->start_bit + 1) / 8; 835 836 if ((offset_info->width - hint_width) > 2) { 837 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 838 (BSL_META_U(unit, 839 "FT(unit %d) Error: Hint removes more " 840 "than 2B \n"), 841 unit)); 842 return BCM_E_PARAM; 843 } 844 845 break; 846 } 847 hint_entry = hint_entry->next; 848 } 849 } 850 851 if (!hint) { 852 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 853 (BSL_META_U(unit, 854 "FT(unit %d) Error: Cannot find hints for " 855 "UDF Id (%d) \n"), 856 unit, udf_id)); 857 return BCM_E_NOT_FOUND; 858 } 859 860 chunk = 0; 861 num_chunks = 0; 862 *num_qual = 0; 863 864 while (chunk < _BCM_FT_TH_MAX_UDF_CHUNKS) { 865 /* Get the chunk size in bytes */ 866 chunk_size = _bcm_th_ft_udf_chunk_info[chunk].size; 867 868 if(offset_info->hw_bmap & (1 << chunk)) { 869 /* Fill in the qual details in the message */ 870 qual_info[*num_qual].qual = _bcm_th_ft_udf_chunk_info[chunk].qual; 871 qual_info[*num_qual].base_offset = base_offset; 872 873 /* Fill up the TP info */ 874 tp_info->qual[num_chunks] = _bcm_th_ft_udf_chunk_info[chunk].qual; 875 tp_info->udf = 1; 876 877 if (num_chunks == 0) { 878 qual_info[*num_qual].relative_offset = offset_info->start + hint_start; 879 } else { 880 qual_info[*num_qual].relative_offset = 881 qual_info[*num_qual - 1].relative_offset + qual_info[*num_qual - 1].width; 882 } 883 884 if (hint_width <= chunk_size) { 885 qual_info[*num_qual].width = hint_width; 886 } else { 887 hint_width -= chunk_size; 888 qual_info[*num_qual].width = chunk_size; 889 } 890 891 892 num_chunks++; 893 (*num_qual)++; 894 } 895 chunk += (chunk_size / 2); 896 } 897 898 tp_info->num_qual = num_chunks; 899 900 return BCM_E_NONE; 901 } 902 903 /* 904 * Function: 905 * _bcm_th_ft_fill_em_group_create_msg 906 * Purpose: 907 * Convert the EM key format from field data structure to 908 * App message format 909 * Parameters: 910 * unit - (IN) BCM device number 911 * msg - (OUT) Key format message 912 * Returns: 913 * BCM_E_XXX - BCM error code. 914 */ 915 int 916 _bcm_th_ft_fill_em_group_create_msg(int unit, 917 bcm_field_group_t *em_group, 918 uint8 ft_em_group, 919 int num_tracking_params, 920 bcm_flowtracker_tracking_param_info_t *tracking_params, 921 shr_ft_msg_ctrl_em_group_create_t *msg) 922 { 923 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 924 _bcm_field_group_qual_t **qual_arr; 925 uint16 *qid_arr, qid; 926 _bcm_field_qual_offset_t *offset_arr; 927 int num_parts_count, max_parts_count; 928 int i, j, k, qidx, offset_idx; 929 uint16 offset, next_offset, width; 930 uint16 word_boundary; 931 int rv; 932 int udf; 933 int num_qual, qual_count, em_qual_count; 934 shr_ft_em_qual_t ft_qual; 935 shr_ft_msg_ctrl_qual_info_t *qual_info; 936 _field_group_t *fg, *tmp_fg; 937 int action; 938 int key_boundary = 79; 939 940 if (soc_feature(unit, soc_feature_th3_style_fp)) { 941 key_boundary = 51; 942 } 943 944 BCM_IF_ERROR_RETURN(_field_group_get(unit, em_group[0], &fg)); 945 946 if (fg->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) { 947 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 948 (BSL_META_U(unit, 949 "FT(unit %d) Error: Group Stage is not ExactMatch \n"), 950 unit)); 951 return BCM_E_PARAM; 952 } 953 954 if ((fg->em_mode != _FieldExactMatchMode128) && 955 (fg->em_mode != _FieldExactMatchMode320)) { 956 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 957 (BSL_META_U(unit, 958 "FT(unit %d) Error: Only 128/320b EM view is supported \n"), 959 unit)); 960 return BCM_E_PARAM; 961 } 962 963 qual_arr = sal_alloc(_FP_MAX_ENTRY_TYPES * sizeof(_bcm_field_group_qual_t*), 964 "FT EM qual_arr"); 965 if (qual_arr == NULL) { 966 return BCM_E_MEMORY; 967 } 968 for (i = 0; i < _FP_MAX_ENTRY_TYPES; i++) { 969 qual_arr[i] = sal_alloc(_FP_MAX_ENTRY_WIDTH * sizeof(_bcm_field_group_qual_t), 970 "FT EM qual_arr"); 971 if (qual_arr[i] == NULL) { 972 for (j = 0; j < i; j++) { 973 sal_free(qual_arr[j]); 974 } 975 return BCM_E_MEMORY; 976 } 977 } 978 979 /* Get the EM key format */ 980 if (fg->em_mode == _FieldExactMatchMode128) { 981 max_parts_count = 1; 982 } else { 983 max_parts_count = 2; 984 } 985 rv = _bcm_esw_field_group_info_key_get(unit, em_group[0], 986 max_parts_count, qual_arr, 987 &num_parts_count); 988 if (BCM_FAILURE(rv)) { 989 for (i = 0; i < _FP_MAX_ENTRY_TYPES; i++) { 990 sal_free(qual_arr[i]); 991 } 992 sal_free(qual_arr); 993 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 994 (BSL_META_U(unit, 995 "FT(unit %d) Error: _bcm_esw_field_group_info_key_get " 996 "failed rv=%d\n"), 997 unit, rv)); 998 return rv; 999 } 1000 1001 /* Get the total number of qualifiers across all the parts. This may include 1002 * duplicates if a single qualifier is split across multiple parts 1003 */ 1004 em_qual_count = 0; 1005 for (i = 0; i < num_parts_count; i++) { 1006 em_qual_count += qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size; 1007 } 1008 1009 qid_arr = sal_alloc(em_qual_count * sizeof(uint16), "FT EM qid arr"); 1010 if (qid_arr == NULL) { 1011 for (i = 0; i < _FP_MAX_ENTRY_TYPES; i++) { 1012 sal_free(qual_arr[i]); 1013 } 1014 sal_free(qual_arr); 1015 return BCM_E_MEMORY; 1016 } 1017 sal_memset(qid_arr, 0, em_qual_count * sizeof(uint16)); 1018 1019 offset_arr = sal_alloc(em_qual_count * sizeof(_bcm_field_qual_offset_t), 1020 "FT EM qid arr"); 1021 if (offset_arr == NULL) { 1022 sal_free(qid_arr); 1023 for (i = 0; i < _FP_MAX_ENTRY_TYPES; i++) { 1024 sal_free(qual_arr[i]); 1025 } 1026 sal_free(qual_arr); 1027 return BCM_E_MEMORY; 1028 } 1029 sal_memset(offset_arr, 0, em_qual_count * sizeof(_bcm_field_qual_offset_t)); 1030 1031 /* Copy over the first part */ 1032 sal_memcpy(qid_arr, qual_arr[_FP_ENTRY_TYPE_DEFAULT][0].qid_arr, 1033 qual_arr[_FP_ENTRY_TYPE_DEFAULT][0].size * sizeof(uint16)); 1034 sal_memcpy(offset_arr, qual_arr[_FP_ENTRY_TYPE_DEFAULT][0].offset_arr, 1035 qual_arr[_FP_ENTRY_TYPE_DEFAULT][0].size * sizeof(_bcm_field_qual_offset_t)); 1036 qual_count = qual_arr[_FP_ENTRY_TYPE_DEFAULT][0].size; 1037 1038 /* Copy over the remaining parts, adjust the offset and filter duplicates */ 1039 for (i = 1; i < num_parts_count; i++) { 1040 for (j = 0; j < qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size; j++) { 1041 qid = qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr[j]; 1042 1043 /* Check if it is a case of a single qualifier split across 1044 * multiple parts 1045 */ 1046 for (k = 0; k < qual_count; k++) { 1047 if (qid_arr[k] == qid) { 1048 qidx = k; 1049 break; 1050 } 1051 } 1052 if (k >= qual_count) { 1053 /* Not a duplicate */ 1054 qidx = qual_count; 1055 qual_count++; 1056 } 1057 qid_arr[qidx] = qid; 1058 /* Insert to the list */ 1059 for (k = 0, offset_idx = offset_arr[qidx].num_offsets; 1060 k < qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr[j].num_offsets; 1061 k++, offset_idx++) { 1062 offset_arr[qidx].offset[offset_idx] = 1063 160 * i + qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr[j].offset[k]; 1064 offset_arr[qidx].width[offset_idx] = 1065 qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr[j].width[k]; 1066 } 1067 offset_arr[qidx].num_offsets = offset_idx; 1068 } 1069 } 1070 1071 for (i = 0; i < _FP_MAX_ENTRY_TYPES; i++) { 1072 sal_free(qual_arr[i]); 1073 } 1074 sal_free(qual_arr); 1075 1076 /* Check if any qualifier has more parts that the app can handle */ 1077 for (qidx = 0; qidx < qual_count; qidx++) { 1078 if (offset_arr[qidx].num_offsets > SHR_FT_EM_KEY_MAX_QUAL_PARTS) { 1079 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 1080 (BSL_META_U(unit, 1081 "FT(unit %d) Error: Excess num_offsets than expected " 1082 "num_offsets=%u\n"), 1083 unit, offset_arr[qidx].num_offsets)); 1084 return BCM_E_PARAM; 1085 } 1086 } 1087 1088 if (qual_count >= SHR_FT_EM_MAX_QUAL) { 1089 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 1090 (BSL_META_U(unit, 1091 "FT(unit %d) Error: Excess qualifiers than expected " 1092 "qual_count=%u\n"), 1093 unit, qual_count)); 1094 sal_free(qid_arr); 1095 sal_free(offset_arr); 1096 return BCM_E_PARAM; 1097 } 1098 1099 if (fg->em_mode == _FieldExactMatchMode128) { 1100 /* In Exact Match Mode 128 - whole key is not presented 1101 * for lookup. Instead Bit 0-47 and Bit 80-160 are provided 1102 * to UFT. Hence qualifier offsets at position greater than 1103 * 80 bit are shifted by 32 bit for key. 1104 */ 1105 for (i = 0; i < qual_count; i++) { 1106 for (j = 0; j < offset_arr[i].num_offsets; j++) { 1107 if (offset_arr[i].offset[j] > key_boundary) { 1108 offset_arr[i].offset[j] -= 32; 1109 } 1110 } 1111 } 1112 } 1113 /* Some qual parts are contiguous but field stores them as separate parts, 1114 * combine them to reduce the number of bitops the FW has to perform on each 1115 * flow 1116 */ 1117 for (i = 0; i < qual_count; i++) { 1118 j = 0; 1119 while(j < (offset_arr[i].num_offsets - 1)) { 1120 offset = offset_arr[i].offset[j]; 1121 width = offset_arr[i].width[j]; 1122 next_offset = offset_arr[i].offset[j + 1]; 1123 1124 if ((offset + width) == next_offset) { 1125 /* Increase the width */ 1126 offset_arr[i].width[j] += offset_arr[i].width[j + 1]; 1127 1128 /* Remove the next element */ 1129 for (k = j + 1; k < (offset_arr[i].num_offsets - 1); k++) { 1130 offset_arr[i].offset[k] = offset_arr[i].offset[k + 1]; 1131 offset_arr[i].width[k] = offset_arr[i].width[k + 1]; 1132 } 1133 offset_arr[i].num_offsets--; 1134 } else { 1135 j++; 1136 } 1137 } 1138 } 1139 1140 sal_memset(msg, 0, sizeof(*msg)); 1141 msg->group_idx = ft_em_group; 1142 msg->num_pipes = ft_info->num_pipes; 1143 msg->lt_id[0] = fg->lt_id; 1144 for (i = 1; i < ft_info->num_pipes; i++) { 1145 if (!SOC_IS_TOMAHAWK3(unit)) { 1146 BCM_IF_ERROR_RETURN(_field_group_get(unit, em_group[i], &tmp_fg)); 1147 msg->lt_id[i] = tmp_fg->lt_id; 1148 } else { 1149 /* In TH3, EM is in global mode. So fill up the same LT ID 1150 * in all pipe information. 1151 */ 1152 msg->lt_id[i] = fg->lt_id; 1153 } 1154 } 1155 msg->key_size = (fg->em_mode == _FieldExactMatchMode128) ? 128 : 320; 1156 1157 /* Fill up the tracking params and part of qualifier info */ 1158 qidx = 0; 1159 msg->num_tp = num_tracking_params; 1160 for (i = 0; i < num_tracking_params; i++) { 1161 udf = 0; 1162 switch (tracking_params[i].param) { 1163 case bcmFlowtrackerTrackingParamTypeSrcIPv4: 1164 msg->tp_info[i].param = SHR_FT_TP_SRC_IPV4; 1165 msg->tp_info[i].num_qual = 1; 1166 msg->tp_info[i].qual[0] = SHR_FT_EM_QUAL_SRC_IPV4; 1167 msg->qual_info[qidx].qual = SHR_FT_EM_QUAL_SRC_IPV4; 1168 qidx++; 1169 break; 1170 1171 case bcmFlowtrackerTrackingParamTypeDstIPv4: 1172 msg->tp_info[i].param = SHR_FT_TP_DST_IPV4; 1173 msg->tp_info[i].num_qual = 1; 1174 msg->tp_info[i].qual[0] = SHR_FT_EM_QUAL_DST_IPV4; 1175 msg->qual_info[qidx].qual = SHR_FT_EM_QUAL_DST_IPV4; 1176 qidx++; 1177 break; 1178 1179 case bcmFlowtrackerTrackingParamTypeL4SrcPort: 1180 msg->tp_info[i].param = SHR_FT_TP_L4_SRC_PORT; 1181 msg->tp_info[i].num_qual = 1; 1182 msg->tp_info[i].qual[0] = SHR_FT_EM_QUAL_L4_SRC_PORT; 1183 msg->qual_info[qidx].qual = SHR_FT_EM_QUAL_L4_SRC_PORT; 1184 qidx++; 1185 break; 1186 1187 case bcmFlowtrackerTrackingParamTypeL4DstPort: 1188 msg->tp_info[i].param = SHR_FT_TP_L4_DST_PORT; 1189 msg->tp_info[i].num_qual = 1; 1190 msg->tp_info[i].qual[0] = SHR_FT_EM_QUAL_L4_DST_PORT; 1191 msg->qual_info[qidx].qual = SHR_FT_EM_QUAL_L4_DST_PORT; 1192 qidx++; 1193 break; 1194 1195 case bcmFlowtrackerTrackingParamTypeIPProtocol: 1196 msg->tp_info[i].param = SHR_FT_TP_IP_PROTOCOL; 1197 msg->tp_info[i].num_qual = 1; 1198 msg->tp_info[i].qual[0] = SHR_FT_EM_QUAL_IP_PROTOCOL; 1199 msg->qual_info[qidx].qual = SHR_FT_EM_QUAL_IP_PROTOCOL; 1200 qidx++; 1201 break; 1202 1203 case bcmFlowtrackerTrackingParamTypeVxlanNetworkId: 1204 msg->tp_info[i].param = SHR_FT_TP_VNID; 1205 msg->tp_info[i].num_qual = 1; 1206 msg->tp_info[i].qual[0] = SHR_FT_EM_QUAL_VNID; 1207 msg->qual_info[qidx].qual = SHR_FT_EM_QUAL_VNID; 1208 qidx++; 1209 break; 1210 1211 case bcmFlowtrackerTrackingParamTypeInnerSrcIPv4: 1212 msg->tp_info[i].param = SHR_FT_TP_INNER_SRC_IPV4; 1213 udf = 1; 1214 break; 1215 1216 case bcmFlowtrackerTrackingParamTypeInnerDstIPv4: 1217 msg->tp_info[i].param = SHR_FT_TP_INNER_DST_IPV4; 1218 udf = 1; 1219 break; 1220 1221 case bcmFlowtrackerTrackingParamTypeInnerL4SrcPort: 1222 msg->tp_info[i].param = SHR_FT_TP_INNER_L4_SRC_PORT; 1223 udf = 1; 1224 break; 1225 1226 case bcmFlowtrackerTrackingParamTypeInnerL4DstPort: 1227 msg->tp_info[i].param = SHR_FT_TP_INNER_L4_DST_PORT; 1228 udf = 1; 1229 break; 1230 1231 case bcmFlowtrackerTrackingParamTypeInnerIPProtocol: 1232 msg->tp_info[i].param = SHR_FT_TP_INNER_IP_PROTOCOL; 1233 udf = 1; 1234 break; 1235 1236 case bcmFlowtrackerTrackingParamTypeCustom: 1237 msg->tp_info[i].param = SHR_FT_TP_CUSTOM; 1238 udf = 1; 1239 break; 1240 1241 case bcmFlowtrackerTrackingParamTypeInPort: 1242 msg->tp_info[i].param = SHR_FT_TP_IN_PORT; 1243 msg->tp_info[i].num_qual = 1; 1244 msg->tp_info[i].qual[0] = SHR_FT_EM_QUAL_IN_PORT; 1245 msg->qual_info[qidx].qual = SHR_FT_EM_QUAL_IN_PORT; 1246 qidx++; 1247 break; 1248 1249 default: 1250 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 1251 (BSL_META_U(unit, 1252 "FT(unit %d) Error: Invalid tracking param: " 1253 "%d\n"), 1254 unit, tracking_params[i].param)); 1255 sal_free(qid_arr); 1256 sal_free(offset_arr); 1257 return BCM_E_PARAM; 1258 } 1259 1260 if (udf == 1) { 1261 if (SOC_IS_TRIDENT3(unit)) { 1262 rv = _bcm_td3_ft_em_group_create_msg_udf_get(unit, 1263 tracking_params[i].udf_id, 1264 fg->hintid, 1265 &(msg->tp_info[i]), 1266 &(msg->qual_info[qidx]), 1267 &num_qual); 1268 } else if (SOC_IS_TOMAHAWK(unit) || SOC_IS_TOMAHAWK2(unit)) { 1269 rv = _bcm_th_ft_em_group_create_msg_udf_get(unit, 1270 tracking_params[i].udf_id, 1271 fg->hintid, 1272 &(msg->tp_info[i]), 1273 &(msg->qual_info[qidx]), 1274 &num_qual); 1275 } else { 1276 rv = BCM_E_UNAVAIL; 1277 } 1278 if (rv != BCM_E_NONE) { 1279 sal_free(qid_arr); 1280 sal_free(offset_arr); 1281 return rv; 1282 } 1283 qidx += num_qual; 1284 } 1285 } 1286 1287 /* Check if LT ID is an implicit qualifier and add it to the list */ 1288 for (i = 0; i < qual_count; i++) { 1289 1290 if (qid_arr[i] == _bcmFieldQualifyPreLogicalTableId) { 1291 rv = _bcm_th_ft_field_qual_convert(qid_arr[i], &ft_qual); 1292 BCM_IF_ERROR_RETURN(rv); 1293 1294 msg->qual_info[qidx].qual = SHR_FT_EM_QUAL_LT_ID; 1295 qidx++; 1296 break; 1297 } 1298 } 1299 1300 msg->num_qual = qidx; 1301 1302 if (msg->num_qual != qual_count) { 1303 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 1304 (BSL_META_U(unit, 1305 "FT(unit %d) Error: Unexpected number of qualifiers: " 1306 "(%u, %u)\n"), 1307 unit, msg->num_qual, qual_count)); 1308 sal_free(qid_arr); 1309 sal_free(offset_arr); 1310 return BCM_E_PARAM; 1311 } 1312 1313 /* Fill the rest of qualifier information */ 1314 for (i = 0; i < qual_count; i++) { 1315 rv = _bcm_th_ft_field_qual_convert(qid_arr[i], &ft_qual); 1316 if (rv != BCM_E_NONE) { 1317 sal_free(qid_arr); 1318 sal_free(offset_arr); 1319 return rv; 1320 } 1321 1322 /* Find the info structure corresponding to this qualifier */ 1323 for (j = 0; j < qual_count; j++) { 1324 if (msg->qual_info[j].qual == ft_qual) { 1325 qual_info = &(msg->qual_info[j]); 1326 break; 1327 } 1328 } 1329 if (j >= qual_count) { 1330 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 1331 (BSL_META_U(unit, 1332 "FT(unit %d) Error: %u qualifier not found\n"), 1333 unit, ft_qual)); 1334 sal_free(qid_arr); 1335 sal_free(offset_arr); 1336 return BCM_E_PARAM; 1337 } 1338 1339 for (j = 0, k = 0; j < offset_arr[i].num_offsets; j++) { 1340 offset = offset_arr[i].offset[j]; 1341 width = offset_arr[i].width[j]; 1342 1343 if (k >= SHR_FT_EM_KEY_MAX_QUAL_PARTS) { 1344 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 1345 (BSL_META_U(unit, 1346 "FT(unit %d) Error: Excess num_offsets than expected " 1347 "num_offsets=%u\n"), 1348 unit, k)); 1349 return BCM_E_RESOURCE; 1350 } 1351 1352 word_boundary = offset + (SHR_FT_EM_KEY_DWORD_SIZE - 1353 (offset % SHR_FT_EM_KEY_DWORD_SIZE)); 1354 if ((offset + width) > word_boundary) { 1355 /* The key is present in multiple words, split it into different 1356 * offsets to help the FW 1357 */ 1358 qual_info->part_offset[k] = offset; 1359 qual_info->part_width[k] = word_boundary - offset; 1360 1361 do { 1362 k++; 1363 if (k >= SHR_FT_EM_KEY_MAX_QUAL_PARTS) { 1364 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 1365 (BSL_META_U(unit, 1366 "FT(unit %d) Error: Excess num_offsets than expected " 1367 "num_offsets=%u\n"), 1368 unit, k)); 1369 return BCM_E_RESOURCE; 1370 } 1371 qual_info->part_offset[k] = word_boundary; 1372 qual_info->part_width[k] = width - (word_boundary - offset); 1373 word_boundary += SHR_FT_EM_KEY_DWORD_SIZE; 1374 } while(qual_info->part_width[k] > SHR_FT_EM_KEY_DWORD_SIZE); 1375 1376 k++; 1377 if (k > SHR_FT_EM_KEY_MAX_QUAL_PARTS) { 1378 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 1379 (BSL_META_U(unit, 1380 "FT(unit %d) Error: Excess num_offsets than expected " 1381 "num_offsets=%u\n"), 1382 unit, k)); 1383 return BCM_E_RESOURCE; 1384 } 1385 } else { 1386 qual_info->part_offset[k] = offset; 1387 qual_info->part_width[k] = width; 1388 k++; 1389 if (k > SHR_FT_EM_KEY_MAX_QUAL_PARTS) { 1390 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 1391 (BSL_META_U(unit, 1392 "FT(unit %d) Error: Excess num_offsets than expected " 1393 "num_offsets=%u\n"), 1394 unit, k)); 1395 return BCM_E_RESOURCE; 1396 } 1397 } 1398 } 1399 qual_info->num_parts = k; 1400 1401 } 1402 1403 /* Populate the ASET */ 1404 for (action = 0; action < bcmFieldActionCount; action++) { 1405 if (BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionPolicerGroup)) { 1406 msg->aset |= SHR_FT_EM_ACTION_METER; 1407 } else if (BCM_FIELD_ASET_TEST(fg->aset, bcmFieldActionStatGroup)) { 1408 msg->aset |= SHR_FT_EM_ACTION_CTR; 1409 } else { 1410 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 1411 (BSL_META_U(unit, 1412 "FT(unit %d) Error: Invalid action: %u \n"), 1413 unit, action)); 1414 sal_free(qid_arr); 1415 sal_free(offset_arr); 1416 return BCM_E_PARAM; 1417 } 1418 } 1419 1420 sal_free(qid_arr); 1421 sal_free(offset_arr); 1422 return BCM_E_NONE; 1423 } 1424 1425 /* 1426 * Function: 1427 * _bcm_th_ft_field_config_init 1428 * Purpose: 1429 * Create EM group and export to R5 1430 * Parameters: 1431 * unit - (IN) BCM device number 1432 * Returns: 1433 * BCM_E_XXX - BCM error code. 1434 */ 1435 STATIC int _bcm_th_ft_field_config_init(int unit) 1436 { 1437 int rv; 1438 bcm_field_group_config_t group_config; 1439 _bcm_field_group_qual_t **qual_arr; 1440 int num_parts_count; 1441 int pipe; 1442 int i, j; 1443 shr_ft_msg_ctrl_em_key_format_t em_key_format; 1444 bcm_port_config_t pc; 1445 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 1446 exact_match_qos_actions_profile_entry_t qos_prof_entry = {{0}}; 1447 void *profile_entry[1]; 1448 soc_profile_mem_t *profile_mem = NULL; 1449 soc_mem_t pipe_mem; 1450 uint32 qos_index; 1451 int entry_words; 1452 1453 if (!SOC_WARM_BOOT(unit)) { 1454 /* Create the EM group, with 5-tuple as qual and counter as action */ 1455 if (!soc_feature(unit, soc_feature_mv2_style_flowtracker)) { 1456 BCM_IF_ERROR_RETURN( 1457 bcm_esw_field_group_oper_mode_set(unit, 1458 bcmFieldQualifyStageIngressExactMatch, 1459 bcmFieldGroupOperModePipeLocal)); 1460 } 1461 bcm_port_config_t_init(&pc); 1462 BCM_IF_ERROR_RETURN(bcm_esw_port_config_get(unit, &pc)); 1463 1464 1465 for (pipe = 0; pipe < ft_info->num_pipes; pipe++) { 1466 bcm_field_group_config_t_init(&group_config); 1467 1468 if (soc_feature(unit, soc_feature_mv2_style_flowtracker)) { 1469 group_config.flags = BCM_FIELD_GROUP_CREATE_WITH_ID | 1470 BCM_FIELD_GROUP_CREATE_WITH_ASET; 1471 group_config.priority = 10; 1472 } else { 1473 group_config.flags = BCM_FIELD_GROUP_CREATE_WITH_ID | 1474 BCM_FIELD_GROUP_CREATE_WITH_ASET | 1475 BCM_FIELD_GROUP_CREATE_WITH_PORT; 1476 } 1477 1478 group_config.group = _FP_FLOWTRACKER_RESERVED_EM_GID_MIN + pipe; 1479 group_config.mode = bcmFieldGroupModeAuto; 1480 if (BCM_PBMP_IS_NULL(pc.per_pipe[pipe])) { 1481 /* No ports in this pipe */ 1482 continue; 1483 } else { 1484 BCM_PBMP_ASSIGN(group_config.ports, pc.per_pipe[pipe]); 1485 } 1486 1487 /* Set EM qset to 5-tuple */ 1488 BCM_FIELD_QSET_INIT(group_config.qset); 1489 BCM_FIELD_QSET_ADD(group_config.qset, bcmFieldQualifyStageIngressExactMatch); 1490 BCM_FIELD_QSET_ADD(group_config.qset, bcmFieldQualifySrcIp); 1491 BCM_FIELD_QSET_ADD(group_config.qset, bcmFieldQualifyDstIp); 1492 BCM_FIELD_QSET_ADD(group_config.qset, bcmFieldQualifyIpProtocol); 1493 BCM_FIELD_QSET_ADD(group_config.qset, bcmFieldQualifyL4SrcPort); 1494 BCM_FIELD_QSET_ADD(group_config.qset, bcmFieldQualifyL4DstPort); 1495 1496 /* Set EM aset */ 1497 BCM_FIELD_ASET_INIT(group_config.aset); 1498 1499 /* Enable counter set in action profile for flex counter update */ 1500 if (!soc_feature(unit, soc_feature_mv2_style_flowtracker)) { 1501 BCM_FIELD_ASET_ADD(group_config.aset, bcmFieldActionStatGroup); 1502 } 1503 1504 /* Enable METER_SET in action_profile for EM to see incoming color 1505 * for ETRAP Color Aware actions 1506 */ 1507 BCM_FIELD_ASET_ADD(group_config.aset, bcmFieldActionPolicerGroup); 1508 1509 rv = _bcm_esw_field_group_config_create(unit, &group_config, 1510 _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC); 1511 if (BCM_FAILURE(rv)) { 1512 return rv; 1513 } 1514 1515 if (soc_feature(unit, soc_feature_mv2_style_flowtracker)) { 1516 group_config.group = _FP_FLOWTRACKER_RESERVED_EM_GID_MIN + ft_info->num_pipes; 1517 group_config.priority = 10 + ft_info->num_pipes; 1518 rv = _bcm_esw_field_group_config_create(unit, &group_config, 1519 _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC); 1520 if (BCM_FAILURE(rv)) { 1521 return rv; 1522 } 1523 } 1524 } 1525 1526 /* Key format export to app */ 1527 qual_arr = sal_alloc(_FP_MAX_ENTRY_TYPES * sizeof(_bcm_field_group_qual_t*), 1528 "FT EM qual_arr"); 1529 if (qual_arr == NULL) { 1530 return BCM_E_MEMORY; 1531 } 1532 for (i = 0; i < _FP_MAX_ENTRY_TYPES; i++) { 1533 qual_arr[i] = sal_alloc(_FP_MAX_ENTRY_WIDTH * sizeof(_bcm_field_group_qual_t), 1534 "FT EM qual_arr"); 1535 if (qual_arr[i] == NULL) { 1536 for (j = 0; j < i; j++) { 1537 sal_free(qual_arr[j]); 1538 } 1539 return BCM_E_MEMORY; 1540 } 1541 } 1542 1543 1544 /* Get the EM key format */ 1545 rv = _bcm_esw_field_group_info_key_get(unit, 1546 _FP_FLOWTRACKER_RESERVED_EM_GID_MIN, 1547 1, qual_arr, &num_parts_count); 1548 if (BCM_FAILURE(rv)) { 1549 for (i = 0; i < _FP_MAX_ENTRY_TYPES; i++) { 1550 sal_free(qual_arr[i]); 1551 } 1552 sal_free(qual_arr); 1553 return rv; 1554 } 1555 1556 /* Fill up the EM KEY, key has only one part */ 1557 rv = _bcm_th_ft_fill_em_key_format_msg(qual_arr[_FP_ENTRY_TYPE_DEFAULT][0], 1558 &em_key_format); 1559 1560 for (i = 0; i < _FP_MAX_ENTRY_TYPES; i++) { 1561 sal_free(qual_arr[i]); 1562 } 1563 sal_free(qual_arr); 1564 1565 if (BCM_FAILURE(rv)) { 1566 return rv; 1567 } 1568 1569 /* Send the EM Key to EAPP */ 1570 rv = _bcm_xgs5_ft_eapp_send_em_key_format_msg(unit, &em_key_format); 1571 if (BCM_FAILURE(rv)) { 1572 return rv; 1573 } 1574 } 1575 1576 /* Create profile memory for the Exact Match QoS profile memory */ 1577 for (pipe = 0; pipe < ft_info->num_pipes; pipe++) { 1578 entry_words = soc_mem_entry_words(unit, 1579 EXACT_MATCH_QOS_ACTIONS_PROFILE_PIPE0m); 1580 pipe_mem = SOC_MEM_UNIQUE_ACC(unit, 1581 EXACT_MATCH_QOS_ACTIONS_PROFILEm)[pipe]; 1582 1583 profile_mem = sal_alloc(sizeof(soc_profile_mem_t), " FT QoS profile"); 1584 if (profile_mem == NULL) { 1585 return BCM_E_MEMORY; 1586 } 1587 soc_profile_mem_t_init(profile_mem); 1588 1589 rv = soc_profile_mem_create(unit, &pipe_mem, &entry_words, 1, 1590 profile_mem); 1591 if (BCM_FAILURE(rv)) { 1592 return (rv); 1593 } 1594 1595 1596 if (SOC_WARM_BOOT(unit)) { 1597 /* Increment the ref count of the reserved entry (0) */ 1598 rv = soc_profile_mem_reference(unit, profile_mem, 0, 1); 1599 } else { 1600 /* Reserve the 0th entry for default action (no QoS actions) */ 1601 profile_entry[0] = &qos_prof_entry; 1602 rv = soc_profile_mem_add(unit, profile_mem, (void *) &profile_entry, 1603 1, &qos_index); 1604 } 1605 if (BCM_FAILURE(rv)) { 1606 return (rv); 1607 } 1608 1609 ft_info->pipe_info[pipe].qos_profile_mem = profile_mem; 1610 } 1611 1612 return BCM_E_NONE; 1613 } 1614 1615 /* 1616 * Function: 1617 * _bcm_th_ft_field_config_detach 1618 * Purpose: 1619 * Delete EM group 1620 * Parameters: 1621 * unit - (IN) BCM device number 1622 * Returns: 1623 * BCM_E_XXX - BCM error code. 1624 */ 1625 STATIC int _bcm_th_ft_field_config_detach(int unit) 1626 { 1627 int rv; 1628 int pipe; 1629 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 1630 1631 if (!SOC_WARM_BOOT(unit)) { 1632 for (pipe = 0; pipe < ft_info->num_pipes; pipe++) { 1633 rv = _bcm_esw_field_group_config_destroy( 1634 unit, 1635 _FP_FLOWTRACKER_RESERVED_EM_GID_MIN + pipe, 1636 _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC); 1637 1638 if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) { 1639 /* Ignore BCM_E_NOT_FOUND as the group may not have been 1640 * created yet 1641 */ 1642 return rv; 1643 } 1644 if (soc_feature(unit, soc_feature_mv2_style_flowtracker)) { 1645 rv = _bcm_esw_field_group_config_destroy( 1646 unit, 1647 _FP_FLOWTRACKER_RESERVED_EM_GID_MIN + ft_info->num_pipes, 1648 _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC); 1649 if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) { 1650 /* Ignore BCM_E_NOT_FOUND as the group may not have been 1651 * created yet 1652 */ 1653 return rv; 1654 } 1655 } 1656 1657 if (ft_info->pipe_info[pipe].qos_profile_mem != NULL) { 1658 rv = soc_profile_mem_destroy(unit, 1659 ft_info->pipe_info[pipe].qos_profile_mem); 1660 if (BCM_FAILURE(rv)) { 1661 return rv; 1662 } 1663 } 1664 } 1665 1666 /* Set the EM group mode back to global (default) */ 1667 BCM_IF_ERROR_RETURN( 1668 bcm_esw_field_group_oper_mode_set(unit, 1669 bcmFieldQualifyStageIngressExactMatch, 1670 bcmFieldGroupOperModeGlobal)); 1671 } 1672 1673 for (pipe = 0; pipe < ft_info->num_pipes; pipe++) { 1674 if (ft_info->pipe_info[pipe].qos_profile_mem != NULL) { 1675 rv = soc_profile_mem_destroy(unit, 1676 ft_info->pipe_info[pipe].qos_profile_mem); 1677 if (BCM_FAILURE(rv)) { 1678 return rv; 1679 } 1680 } 1681 } 1682 1683 return BCM_E_NONE; 1684 } 1685 1686 /* 1687 * Function: 1688 * _soc_th_ft_em_ser_handler 1689 * Purpose: 1690 * Handle SER error on EM table 1691 * Parameters: 1692 * unit - (IN) BCM device number 1693 * pipe - (IN) Pipe index 1694 * mem - (IN) Memory (EM) 1695 * index - (IN) Index 1696 * Returns: 1697 * SOC_E_XXX - BCM error code. 1698 */ 1699 int 1700 _soc_th_ft_em_ser_handler(int unit, int pipe, soc_mem_t mem, int index) 1701 { 1702 int rv = SOC_E_NONE; 1703 void *null_entry = NULL; 1704 soc_mem_t pipe_mem; 1705 1706 if ((mem != FPEM_ECCm) && (mem != EXACT_MATCH_ECCm)) { 1707 return SOC_E_PARAM; 1708 } 1709 /* Convert to pipe unique view */ 1710 pipe_mem = SOC_MEM_UNIQUE_ACC(unit, mem)[pipe]; 1711 1712 /* Clear out the entry */ 1713 null_entry = soc_mem_entry_null(unit, pipe_mem); 1714 SOC_IF_ERROR_RETURN(soc_mem_write(unit, pipe_mem, MEM_BLOCK_ALL, index, null_entry)); 1715 1716 /* Flowtracker module uses the double wide EXACT_MATCH_2 view, clear out 1717 * the other half also 1718 */ 1719 if ((index % 2) == 0) { 1720 SOC_IF_ERROR_RETURN(soc_mem_write(unit, pipe_mem, MEM_BLOCK_ALL, index + 1, null_entry)); 1721 } else { 1722 SOC_IF_ERROR_RETURN(soc_mem_write(unit, pipe_mem, MEM_BLOCK_ALL, index - 1, null_entry)); 1723 } 1724 1725 /* Send the SER event to EAPP */ 1726 rv = _bcm_xgs5_ft_eapp_send_ser_event_msg(unit, pipe, mem, (index / 2)); 1727 if (BCM_FAILURE(rv)) { 1728 return rv; 1729 } 1730 1731 return SOC_E_NONE; 1732 } 1733 1734 /* 1735 * Function: 1736 * _bcm_th_ft_export_interval_validate 1737 * Purpose: 1738 * Common validations for export interval. 1739 * Parameters: 1740 * unit - (IN) BCM device number 1741 * export_interval - (IN) Export interval configured. 1742 * Returns: 1743 * BCM_E_XXX - BCM error code. 1744 */ 1745 int 1746 _bcm_th_ft_export_interval_validate(int unit, uint32 export_interval) 1747 { 1748 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 1749 1750 if (ft_info->elph_mode) { 1751 if (export_interval < BCM_INT_FT_ELPH_DEF_EXPORT_INTERVAL_MSECS) { 1752 return BCM_E_CONFIG; 1753 } 1754 } else { 1755 if (export_interval < BCM_INT_FT_DEF_EXPORT_INTERVAL_MSECS) { 1756 return BCM_E_CONFIG; 1757 } 1758 } 1759 1760 if ((export_interval * 1000) < ft_info->scan_interval_usecs) { 1761 /* Export interval cannot be smaller than scan interval */ 1762 return BCM_E_CONFIG; 1763 } 1764 1765 return BCM_E_NONE; 1766 } 1767 1768 1769 /* 1770 * Function: 1771 * _bcm_th_ft_cfg_mode_v1_supported 1772 * Purpose: 1773 * Is API cfg mode v1 supported or not. 1774 * Parameters: 1775 * unit - (IN) BCM device number 1776 * Returns: 1777 * 1 - Supported, 0 - Not supported. 1778 */ 1779 1780 uint8 _bcm_th_ft_cfg_mode_v1_supported(int unit) 1781 { 1782 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_MAVERICK2(unit)) { 1783 return 0; 1784 } 1785 return 1; 1786 } 1787 1788 /* 1789 * Function: 1790 * bcm_th_ft_init 1791 * Purpose: 1792 * Initialize the Flowtracker subsystem. 1793 * Parameters: 1794 * unit - (IN) BCM device number 1795 * Returns: 1796 * BCM_E_XXX - BCM error code. 1797 */ 1798 int _bcm_th_ft_init(int unit) 1799 { 1800 int flowtracker_enable = 0; 1801 int rv = BCM_E_NONE, pipe, pool_idx; 1802 bcm_stat_flex_flowtracker_counter_info_t flex_ctr_info; 1803 _bcm_int_ft_pipe_info_t *pipe_info = NULL; 1804 bcm_stat_flex_flowtracker_pool_info_t pool_info; 1805 char max_flows_pipe_soc_prop_str[50]; 1806 int pipe_flow_limit; 1807 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 1808 uint8 cfg_mode; 1809 int i, j; 1810 1811 flowtracker_enable = soc_property_get(unit, spn_FLOWTRACKER_ENABLE, 0); 1812 1813 1814 switch (flowtracker_enable) { 1815 case 0: 1816 /* Flowtracker not enabled, return */ 1817 return BCM_E_NONE; 1818 1819 case 1: 1820 cfg_mode = SHR_FT_CFG_MODE_V1; 1821 if (!_bcm_th_ft_cfg_mode_v1_supported(unit)) { 1822 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 1823 (BSL_META_U(unit, 1824 "FT(unit %d) Error: flowtracker_enable value = 1 is not supported\n"), unit)); 1825 return BCM_E_CONFIG; 1826 } 1827 break; 1828 1829 case 2: 1830 cfg_mode = SHR_FT_CFG_MODE_V2; 1831 break; 1832 1833 default: 1834 /* Unsupported value */ 1835 return BCM_E_PARAM; 1836 } 1837 1838 if (ft_info != NULL) { 1839 BCM_IF_ERROR_RETURN(_bcm_th_ft_detach(unit)); 1840 ft_info = NULL; 1841 } 1842 1843 _BCM_FT_ALLOC(ft_info, _bcm_int_ft_info_t, 1844 sizeof(_bcm_int_ft_info_t), "FT_INFO"); 1845 if (ft_info == NULL) { 1846 return BCM_E_MEMORY; 1847 } 1848 ft_global_info[unit] = ft_info; 1849 1850 /* Set config mode */ 1851 ft_info->cfg_mode = cfg_mode; 1852 1853 /* Fill the number of pipes info. */ 1854 ft_info->num_pipes = NUM_PIPE(unit); 1855 1856 /* Initialise MV2 Flow Tracker in hardware */ 1857 #if defined(BCM_MAVERICK2_SUPPORT) 1858 if (soc_feature(unit, soc_feature_mv2_style_flowtracker)) { 1859 rv = _bcm_mv2_flowtracker_config_init(unit, ft_info); 1860 if (BCM_FAILURE(rv)) { 1861 BCM_IF_ERROR_RETURN(_bcm_th_ft_detach(unit)); 1862 return rv; 1863 } 1864 } 1865 #endif /* BCM_MAVERICK2_SUPPORT */ 1866 1867 /* Call flex counter API to get information regarding pools */ 1868 sal_memset(&flex_ctr_info, 0, sizeof(flex_ctr_info)); 1869 rv = _bcm_stat_flex_flowtracker_counter_info_get(unit, &flex_ctr_info); 1870 if (BCM_FAILURE(rv)) { 1871 BCM_IF_ERROR_RETURN(_bcm_th_ft_detach(unit)); 1872 return rv; 1873 } 1874 1875 /* Get SOC properties */ 1876 ft_info->max_flow_groups = soc_property_get(unit, 1877 spn_FLOWTRACKER_MAX_FLOW_GROUPS, 1878 BCM_INT_FT_MAX_FLOW_GROUPS); 1879 1880 if (ft_info->max_flow_groups > BCM_INT_FT_MAX_FLOW_GROUPS) { 1881 BCM_IF_ERROR_RETURN(_bcm_th_ft_detach(unit)); 1882 return BCM_E_CONFIG; 1883 } 1884 if (ft_info->max_flow_groups == 0) { 1885 BCM_IF_ERROR_RETURN(_bcm_th_ft_detach(unit)); 1886 return BCM_E_CONFIG; 1887 } 1888 1889 ft_info->max_flows_total = 0; 1890 for (pipe = 0; pipe < ft_info->num_pipes; pipe++) { 1891 sal_memset(max_flows_pipe_soc_prop_str, 0, 50); 1892 sal_snprintf(max_flows_pipe_soc_prop_str, 50, "%s%d", 1893 "flowtracker_max_flows_pipe", pipe); 1894 ft_info->pipe_info[pipe].max_flows = 1895 soc_property_get(unit, 1896 max_flows_pipe_soc_prop_str, 1897 0); 1898 ft_info->max_flows_total += ft_info->pipe_info[pipe].max_flows; 1899 } 1900 if (ft_info->max_flows_total == 0) { 1901 /* Per pipe limit is not configured, check for global and divide 1902 * equally 1903 */ 1904 pipe_flow_limit = soc_property_get(unit, 1905 spn_FLOWTRACKER_MAX_FLOWS, 1906 BCM_INT_FT_DEF_MAX_FLOWS) / 1907 ft_info->num_pipes; 1908 1909 for (pipe = 0; pipe < ft_info->num_pipes; pipe++) { 1910 ft_info->pipe_info[pipe].max_flows = pipe_flow_limit; 1911 } 1912 ft_info->max_flows_total = pipe_flow_limit * ft_info->num_pipes; 1913 1914 } 1915 if (ft_info->max_flows_total == 0) { 1916 BCM_IF_ERROR_RETURN(_bcm_th_ft_detach(unit)); 1917 return BCM_E_CONFIG; 1918 } 1919 1920 1921 ft_info->max_export_pkt_length = 1922 soc_property_get(unit, spn_FLOWTRACKER_MAX_EXPORT_PKT_LENGTH, 1923 BCM_INT_FT_DEF_MAX_EXPORT_LENGTH); 1924 1925 if ((ft_info->max_export_pkt_length < SHR_FT_MIN_EXPORT_LENGTH) || 1926 (ft_info->max_export_pkt_length > SHR_FT_MAX_EXPORT_LENGTH)) { 1927 BCM_IF_ERROR_RETURN(_bcm_th_ft_detach(unit)); 1928 return BCM_E_CONFIG; 1929 } 1930 1931 ft_info->enterprise_number = 1932 soc_property_get(unit, spn_FLOWTRACKER_ENTERPRISE_NUMBER, 0); 1933 1934 if (soc_property_get(unit, spn_FLOWTRACKER_FLOW_START_TIMESTAMP_IE_ENABLE, 0)) { 1935 ft_info->flags |= BCM_INT_FT_INFO_FLAGS_FLOW_START_TS; 1936 } 1937 1938 if (soc_property_get(unit, spn_FLOWTRACKER_ELEPHANT_ENABLE, 0)) { 1939 if (!soc_feature(unit, soc_feature_hw_etrap)) { 1940 ft_info->elph_mode = 1; 1941 } else { 1942 return BCM_E_CONFIG; 1943 } 1944 } 1945 1946 ft_info->export_interval = 1947 (soc_property_get(unit, spn_FLOWTRACKER_EXPORT_INTERVAL_USECS, 1948 BCM_INT_FT_DEF_EXPORT_INTERVAL_MSECS * 1000)) / 1000; 1949 1950 if (ft_info->elph_mode) { 1951 ft_info->scan_interval_usecs = 1952 soc_property_get(unit, 1953 spn_FLOWTRACKER_ELEPHANT_SCAN_INTERVAL_USECS, 1954 BCM_INT_FT_ELPH_DEF_SCAN_INTERVAL_USECS); 1955 if (ft_info->scan_interval_usecs < BCM_INT_FT_ELPH_MIN_SCAN_INTERVAL_USECS) { 1956 return BCM_E_CONFIG; 1957 } 1958 if ((ft_info->scan_interval_usecs % BCM_INT_FT_ELPH_SCAN_INTERVAL_STEP_USECS) != 0) { 1959 return BCM_E_CONFIG; 1960 } 1961 } else { 1962 if (soc_property_get_str(unit, spn_FLOWTRACKER_SCAN_INTERVAL_USECS) == NULL) { 1963 /* If scan interval soc property is not used, fallback to default behavior 1964 * of deriving scan interval from export interval. 1965 */ 1966 if (ft_info->export_interval > (BCM_INT_FT_MAX_SCAN_INTERVAL_USECS / 1000)) { 1967 ft_info->scan_interval_usecs = BCM_INT_FT_MAX_SCAN_INTERVAL_USECS; 1968 } else { 1969 ft_info->scan_interval_usecs = ft_info->export_interval * 1000; 1970 } 1971 } else { 1972 /* With common collector infrastructure, export interval can be dynamically 1973 * changed. Hence scan interval will not be made a function of export interval. 1974 * Instead, it will be obtained from user through config property. 1975 */ 1976 ft_info->scan_interval_usecs = soc_property_get(unit, 1977 spn_FLOWTRACKER_SCAN_INTERVAL_USECS, 1978 BCM_INT_FT_DEF_SCAN_INTERVAL_USECS); 1979 if (ft_info->scan_interval_usecs < BCM_INT_FT_DEF_SCAN_INTERVAL_USECS) { 1980 return BCM_E_CONFIG; 1981 } 1982 if ((ft_info->scan_interval_usecs % BCM_INT_FT_SCAN_INTERVAL_STEP_USECS) != 0) { 1983 return BCM_E_CONFIG; 1984 } 1985 } 1986 } 1987 1988 BCM_IF_ERROR_RETURN(_bcm_th_ft_export_interval_validate(unit, ft_info->export_interval)); 1989 1990 /* Fill the per pipe info */ 1991 for (pipe = 0; pipe < ft_info->num_pipes; pipe++) { 1992 pipe_info = &(ft_info->pipe_info[pipe]); 1993 if (ft_info->pipe_info[pipe].max_flows == 0) { 1994 pipe_info->num_ctr_pools = 0; 1995 } else { 1996 pipe_info->num_ctr_pools = flex_ctr_info.pool_num; 1997 } 1998 1999 for (pool_idx = 0; pool_idx < pipe_info->num_ctr_pools; pool_idx++) { 2000 sal_memset(&pool_info, 0, sizeof(pool_info)); 2001 pool_info = flex_ctr_info.pool_info[pool_idx]; 2002 pipe_info->ctr_pools[pool_idx] = pool_info.pool_id; 2003 pipe_info->ctr_pool_size[pool_idx] = pool_info.end_idx + 1; 2004 } 2005 } 2006 2007 if (soc_property_get(unit, spn_FLOWTRACKER_DROP_MONITOR_ENABLE, 0)) { 2008 ft_info->flags |= BCM_INT_FT_INFO_FLAGS_DROP_MONITOR; 2009 } 2010 2011 ft_info->fsp_reinject_max_length = soc_property_get(unit, 2012 spn_FLOWTRACKER_FSP_REINJECT_MAX_LENGTH, 2013 128); 2014 if ((ft_info->fsp_reinject_max_length < 2015 SHR_FT_MIN_EXPORT_LENGTH) || 2016 (ft_info->fsp_reinject_max_length > 2017 SHR_FT_MAX_EXPORT_LENGTH)) { 2018 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 2019 (BSL_META_U(unit, 2020 "FT(unit %d) Error: Invalid " 2021 " reinjected FSP packet\n"), unit)); 2022 return BCM_E_CONFIG; 2023 } 2024 2025 /* Initialize the embedded app */ 2026 rv = bcm_xgs5_ft_eapp_init(unit); 2027 if (BCM_FAILURE(rv)) { 2028 BCM_IF_ERROR_RETURN(_bcm_th_ft_detach(unit)); 2029 return rv; 2030 } 2031 2032 /* Create EM group and export to app in V1 */ 2033 if (ft_info->cfg_mode == SHR_FT_CFG_MODE_V1) { 2034 rv = _bcm_th_ft_field_config_init(unit); 2035 if (BCM_FAILURE(rv)) { 2036 BCM_IF_ERROR_RETURN(_bcm_th_ft_detach(unit)); 2037 return rv; 2038 } 2039 } 2040 2041 /* Initalize the data structures */ 2042 rv = shr_idxres_list_create(&(ft_info->template_pool), 2043 BCM_INT_FT_TEMPLATE_START_ID, 2044 BCM_INT_FT_TEMPLATE_END_ID, 2045 BCM_INT_FT_TEMPLATE_START_ID, 2046 BCM_INT_FT_TEMPLATE_END_ID, 2047 "flowtracker template pool"); 2048 if (BCM_FAILURE(rv)) { 2049 BCM_IF_ERROR_RETURN(_bcm_th_ft_detach(unit)); 2050 return rv; 2051 } 2052 2053 rv = shr_idxres_list_create(&(ft_info->collector_pool), 2054 BCM_INT_FT_COLLECTOR_START_ID, 2055 BCM_INT_FT_COLLECTOR_END_ID, 2056 BCM_INT_FT_COLLECTOR_START_ID, 2057 BCM_INT_FT_COLLECTOR_END_ID, 2058 "flowtracker collector pool"); 2059 if (BCM_FAILURE(rv)) { 2060 BCM_IF_ERROR_RETURN(_bcm_th_ft_detach(unit)); 2061 return rv; 2062 } 2063 2064 if (ft_info->cfg_mode >= SHR_FT_CFG_MODE_V2) { 2065 rv = shr_idxres_list_create(&(ft_info->export_profile_pool), 2066 BCM_INT_FT_EXPORT_PROFILE_START_ID, 2067 BCM_INT_FT_EXPORT_PROFILE_END_ID, 2068 BCM_INT_FT_EXPORT_PROFILE_START_ID, 2069 BCM_INT_FT_EXPORT_PROFILE_END_ID, 2070 "flowtracker export_profile pool"); 2071 if (BCM_FAILURE(rv)) { 2072 BCM_IF_ERROR_RETURN(_bcm_th_ft_detach(unit)); 2073 return rv; 2074 } 2075 } 2076 2077 rv = shr_idxres_list_create(&(ft_info->flow_group_pool), 2078 BCM_INT_FT_GROUP_START_ID, 2079 ft_info->max_flow_groups + BCM_INT_FT_GROUP_START_ID - 1, 2080 BCM_INT_FT_GROUP_START_ID, 2081 ft_info->max_flow_groups + BCM_INT_FT_GROUP_START_ID - 1, 2082 "flowtracker flow group pool"); 2083 if (BCM_FAILURE(rv)) { 2084 BCM_IF_ERROR_RETURN(_bcm_th_ft_detach(unit)); 2085 return rv; 2086 } 2087 2088 rv = shr_idxres_list_create(&(ft_info->elph_profile_pool), 2089 BCM_INT_FT_ELPH_PROFILE_START_ID, 2090 BCM_INT_FT_ELPH_PROFILE_END_ID, 2091 BCM_INT_FT_ELPH_PROFILE_START_ID, 2092 BCM_INT_FT_ELPH_PROFILE_END_ID, 2093 "flowtracker elephant profile pool"); 2094 if (BCM_FAILURE(rv)) { 2095 BCM_IF_ERROR_RETURN(_bcm_th_ft_detach(unit)); 2096 return rv; 2097 } 2098 2099 soc_th_ft_em_ser_handler_register(unit, _soc_th_ft_em_ser_handler); 2100 2101 ft_info->default_grp_id = 0; 2102 for (i = 0; i < SHR_FT_MAX_EM_GROUPS; ++i) { 2103 for (j = 0; j < ft_info->num_pipes; ++j) { 2104 ft_info->em_group_id_map[i][j] = BCM_INT_FT_INVALID_EM_GROUP_ID; 2105 } 2106 } 2107 2108 #ifdef BCM_WARM_BOOT_SUPPORT 2109 if (SOC_WARM_BOOT(unit)) { 2110 rv = _bcm_th_ft_wb_recover(unit); 2111 } else { 2112 rv = _bcm_th_ft_scache_alloc(unit, 1); 2113 } 2114 #endif /* BCM_WARM_BOOT_SUPPORT */ 2115 2116 if (rv == BCM_E_NOT_FOUND) { 2117 /* Continue with initialization if scache not found */ 2118 rv = BCM_E_NONE; 2119 } 2120 if (BCM_FAILURE(rv)) { 2121 return (rv); 2122 } 2123 2124 return BCM_E_NONE; 2125 } 2126 2127 /* 2128 * Function: 2129 * _bcm_th_ft_hw_clear 2130 * Purpose: 2131 * Clear the H/w resources EM group & Flex counter 2132 * Parameters: 2133 * unit - (IN) BCM device number 2134 * Returns: 2135 * BCM_E_XXX - BCM error code. 2136 */ 2137 STATIC int _bcm_th_ft_hw_clear(int unit) 2138 { 2139 int rv; 2140 int pipe, ctr_pool, pool_idx; 2141 soc_mem_t ctr_mem[] = { 2142 ING_FLEX_CTR_COUNTER_TABLE_0m, 2143 ING_FLEX_CTR_COUNTER_TABLE_1m, 2144 ING_FLEX_CTR_COUNTER_TABLE_2m, 2145 ING_FLEX_CTR_COUNTER_TABLE_3m, 2146 ING_FLEX_CTR_COUNTER_TABLE_4m, 2147 ING_FLEX_CTR_COUNTER_TABLE_5m, 2148 ING_FLEX_CTR_COUNTER_TABLE_6m, 2149 ING_FLEX_CTR_COUNTER_TABLE_7m, 2150 ING_FLEX_CTR_COUNTER_TABLE_8m, 2151 ING_FLEX_CTR_COUNTER_TABLE_9m, 2152 ING_FLEX_CTR_COUNTER_TABLE_10m, 2153 ING_FLEX_CTR_COUNTER_TABLE_11m, 2154 ING_FLEX_CTR_COUNTER_TABLE_12m, 2155 ING_FLEX_CTR_COUNTER_TABLE_13m, 2156 ING_FLEX_CTR_COUNTER_TABLE_14m, 2157 ING_FLEX_CTR_COUNTER_TABLE_15m, 2158 ING_FLEX_CTR_COUNTER_TABLE_16m, 2159 ING_FLEX_CTR_COUNTER_TABLE_17m, 2160 ING_FLEX_CTR_COUNTER_TABLE_18m, 2161 ING_FLEX_CTR_COUNTER_TABLE_19m, 2162 }; 2163 soc_mem_t mem; 2164 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 2165 int th3 = 0; 2166 2167 th3 = SOC_IS_TOMAHAWK3(unit); 2168 if (th3) { 2169 rv = soc_mem_clear(unit, EXACT_MATCH_2m, MEM_BLOCK_ALL, TRUE); 2170 if (SOC_FAILURE(rv)) { 2171 return rv; 2172 } 2173 } 2174 2175 2176 for (pipe = 0; pipe < ft_info->num_pipes; pipe++) { 2177 if (!th3) { 2178 mem = SOC_MEM_UNIQUE_ACC(unit, EXACT_MATCH_2m)[pipe]; 2179 rv = soc_mem_clear(unit, mem, MEM_BLOCK_ALL, TRUE); 2180 if (SOC_FAILURE(rv)) { 2181 return rv; 2182 } 2183 } 2184 2185 for (pool_idx = 0; 2186 pool_idx < ft_info->pipe_info[pipe].num_ctr_pools; 2187 pool_idx++) { 2188 2189 ctr_pool = ft_info->pipe_info[pipe].ctr_pools[pool_idx]; 2190 mem = SOC_MEM_UNIQUE_ACC(unit, ctr_mem[ctr_pool])[pipe]; 2191 rv = soc_mem_clear(unit, mem, MEM_BLOCK_ALL, TRUE); 2192 if (SOC_FAILURE(rv)) { 2193 return rv; 2194 } 2195 } 2196 } 2197 2198 return BCM_E_NONE; 2199 } 2200 2201 /* 2202 * Function: 2203 * _bcm_th_ft_detach 2204 * Purpose: 2205 * Detach the Flowtracker subsystem. 2206 * Parameters: 2207 * unit - (IN) BCM device number 2208 * Returns: 2209 * BCM_E_XXX - BCM error code. 2210 */ 2211 int _bcm_th_ft_detach(int unit) 2212 { 2213 int rv = BCM_E_NONE; 2214 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 2215 2216 if (ft_info == NULL) { 2217 return BCM_E_NONE; 2218 } 2219 2220 /* De-init Maverick2 Flow Tracker in hardware */ 2221 #if defined(BCM_MAVERICK2_SUPPORT) 2222 if (soc_feature(unit, soc_feature_mv2_style_flowtracker)) { 2223 rv = _bcm_mv2_flowtracker_config_detach(unit); 2224 if (BCM_FAILURE(rv)) { 2225 return rv; 2226 } 2227 } 2228 #endif /* BCM_MAVERICK2_SUPPORT */ 2229 2230 /* Delete the EM group */ 2231 if (ft_info->cfg_mode == SHR_FT_CFG_MODE_V1) { 2232 BCM_IF_ERROR_RETURN(_bcm_th_ft_field_config_detach(unit)); 2233 } 2234 2235 /* Destroy the allocated data structures */ 2236 if (ft_info->template_pool != NULL) { 2237 rv = shr_idxres_list_destroy(ft_info->template_pool); 2238 if (BCM_FAILURE(rv)) { 2239 return rv; 2240 } 2241 ft_info->template_pool = NULL; 2242 } 2243 2244 if (ft_info->collector_pool != NULL) { 2245 rv = shr_idxres_list_destroy(ft_info->collector_pool); 2246 if (BCM_FAILURE(rv)) { 2247 return rv; 2248 } 2249 ft_info->collector_pool = NULL; 2250 } 2251 2252 if (ft_info->export_profile_pool != NULL) { 2253 rv = shr_idxres_list_destroy(ft_info->export_profile_pool); 2254 if (BCM_FAILURE(rv)) { 2255 return rv; 2256 } 2257 ft_info->export_profile_pool = NULL; 2258 } 2259 2260 if (ft_info->flow_group_pool != NULL) { 2261 rv = shr_idxres_list_destroy(ft_info->flow_group_pool); 2262 if (BCM_FAILURE(rv)) { 2263 return rv; 2264 } 2265 ft_info->flow_group_pool = NULL; 2266 } 2267 2268 /* De-init the embedded app */ 2269 rv = bcm_xgs5_ft_eapp_detach(unit); 2270 if (BCM_FAILURE(rv)) { 2271 return rv; 2272 } 2273 2274 if (!SOC_WARM_BOOT(unit)) { 2275 /* Clear the H/w resources */ 2276 BCM_IF_ERROR_RETURN(_bcm_th_ft_hw_clear(unit)); 2277 } 2278 2279 sal_free(ft_info); 2280 ft_global_info[unit] = NULL; 2281 2282 return BCM_E_NONE; 2283 } 2284 2285 /* 2286 * Function: 2287 * _bcm_th_ft_export_template_create 2288 * Purpose: 2289 * Create an export template 2290 * Parameters: 2291 * unit - (IN) BCM device number 2292 * options - (IN) Template create options 2293 * id - (INOUT) Template Id 2294 * set_id - (IN) set_id to be used for the template 2295 * num_export_elements - (IN) Number of elements in the template 2296 * list_of_export_elements - (IN) Export element list 2297 * Returns: 2298 * BCM_E_XXX - BCM error code. 2299 */ 2300 int 2301 _bcm_th_ft_export_template_create( 2302 int unit, 2303 uint32 options, 2304 bcm_flowtracker_export_template_t *id, 2305 uint16 set_id, 2306 int num_export_elements, 2307 bcm_flowtracker_export_element_info_t *list_of_export_elements) 2308 { 2309 _bcm_int_ft_export_template_info_t template_int_info; 2310 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 2311 int rv = BCM_E_NONE; 2312 2313 if (ft_info == NULL) { 2314 return BCM_E_INIT; 2315 } 2316 2317 /* Check if template is supported templates and convert to internal 2318 * representation. 2319 */ 2320 rv = _bcm_th_ft_template_validate_convert(unit, 2321 set_id, 2322 num_export_elements, 2323 list_of_export_elements, 2324 &template_int_info); 2325 BCM_IF_ERROR_RETURN(rv); 2326 2327 /* If WITH_ID, reserve the ID */ 2328 if (options & BCM_FLOWTRACKER_EXPORT_TEMPLATE_WITH_ID) { 2329 rv = shr_idxres_list_reserve(ft_info->template_pool, 2330 *id, *id); 2331 if (BCM_FAILURE(rv)) { 2332 return ((rv == BCM_E_RESOURCE) ? BCM_E_EXISTS : rv); 2333 } 2334 } else { 2335 /* Else allocate the ID */ 2336 rv = shr_idxres_list_alloc(ft_info->template_pool, 2337 (shr_idxres_element_t *)id); 2338 if (BCM_FAILURE(rv)) { 2339 return rv; 2340 } 2341 } 2342 2343 /* Add it to the list of templates */ 2344 rv = _bcm_xgs5_ft_template_list_template_add(unit, *id, &template_int_info); 2345 if (BCM_FAILURE(rv)) { 2346 /* Free up the template id allocated */ 2347 BCM_IF_ERROR_RETURN(shr_idxres_list_free(ft_info->template_pool, *id)); 2348 return rv; 2349 } 2350 2351 /* Inform FT EAPP of the change/addition in/of export template information */ 2352 rv = _bcm_xgs5_ft_eapp_send_template_create_msg(unit, *id); 2353 if (BCM_FAILURE(rv)) { 2354 /* Free up the template id allocated */ 2355 BCM_IF_ERROR_RETURN(shr_idxres_list_free(ft_info->template_pool, *id)); 2356 BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_template_list_template_delete(unit, *id)); 2357 return rv; 2358 } 2359 2360 return BCM_E_NONE; 2361 } 2362 2363 /* 2364 * Function: 2365 * _bcm_th_ft_export_template_get 2366 * Purpose: 2367 * Get a flowtracker export template with ID. 2368 * Parameters: 2369 * unit - (IN) BCM device number 2370 * id - (IN) Template Id 2371 * set_id - (OUT) Set Id of the template 2372 * max_size - (IN) Size of the export element list array 2373 * list_of_export_elements - (OUT) Export element list 2374 * list_size - (OUT) Number of elements in the list 2375 * Returns: 2376 * BCM_E_XXX - BCM error code. 2377 */ 2378 int _bcm_th_ft_export_template_get( 2379 int unit, 2380 bcm_flowtracker_export_template_t id, 2381 uint16 *set_id, 2382 int max_size, 2383 bcm_flowtracker_export_element_info_t *list_of_export_elements, 2384 int *list_size) 2385 { 2386 _bcm_int_ft_export_template_info_t template_int_info; 2387 int num_elements_to_copy = 0; 2388 int i, j; 2389 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 2390 int rv = BCM_E_NONE; 2391 2392 if (ft_info == NULL) { 2393 return BCM_E_INIT; 2394 } 2395 2396 sal_memset(&template_int_info, 0, sizeof(template_int_info)); 2397 2398 /* If the max_size is non zero and list == NULL, return 2399 * BCM_E_PARAM. 2400 */ 2401 if (max_size != 0 && list_of_export_elements == NULL) { 2402 return BCM_E_PARAM; 2403 } 2404 2405 /* Get the template info based on template id */ 2406 rv = _bcm_xgs5_ft_template_list_template_get(unit, id, &template_int_info); 2407 2408 /* If not found, return BCM_E_NOT_FOUND */ 2409 if (BCM_FAILURE(rv)) { 2410 return rv; 2411 } 2412 2413 /* If max_size == 0 and list_of_export_elements == NULL, 2414 * return the number of export elements in list_size 2415 * variable. 2416 */ 2417 if (max_size == 0 && list_of_export_elements == NULL) { 2418 *list_size = template_int_info.num_export_elements; 2419 return BCM_E_NONE; 2420 } 2421 2422 *set_id = template_int_info.set_id; 2423 2424 /* Else, if number of export elements less than max_size, 2425 * fill the list with the elements and fill list_size with 2426 * num_export_elements. 2427 */ 2428 if (template_int_info.num_export_elements < max_size) { 2429 num_elements_to_copy = template_int_info.num_export_elements; 2430 } else { 2431 /* Else, if number of export elements greater than or equal to max_size, 2432 * fill the list with the elements upto max_size and fill list_size 2433 * with max_size. 2434 */ 2435 num_elements_to_copy = max_size; 2436 } 2437 for (i = 0; i < num_elements_to_copy; i++) { 2438 /* Convert internal representation to API enum */ 2439 for (j = 0; j < SHR_FT_TEMPLATE_MAX_INFO_ELEMENTS; j++) { 2440 if (template_int_info.elements[i].element == 2441 _bcm_th_ft_template_element_mapping[j].int_element) { 2442 list_of_export_elements[i].element = 2443 _bcm_th_ft_template_element_mapping[j].element; 2444 list_of_export_elements[i].data_size = 2445 _bcm_th_ft_template_element_mapping[j].data_size; 2446 break; 2447 } 2448 } 2449 list_of_export_elements[i].info_elem_id = 2450 template_int_info.elements[i].id; 2451 if (template_int_info.elements[i].enterprise) { 2452 list_of_export_elements[i].flags |= 2453 BCM_FLOWTRACKER_EXPORT_ELEMENT_FLAGS_ENTERPRISE; 2454 } 2455 } 2456 *list_size = num_elements_to_copy; 2457 2458 return BCM_E_NONE; 2459 } 2460 2461 /* 2462 * Function: 2463 * _bcm_th_ft_export_template_destroy 2464 * Purpose: 2465 * Destroy a flowtracker export template 2466 * Parameters: 2467 * unit - (IN) BCM device number 2468 * id - (IN) Template Id 2469 * Returns: 2470 * BCM_E_XXX - BCM error code. 2471 */ 2472 int _bcm_th_ft_export_template_destroy(int unit, 2473 bcm_flowtracker_export_template_t id) 2474 { 2475 int rv = BCM_E_NONE; 2476 _bcm_int_ft_export_template_info_t template_int_info; 2477 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 2478 2479 if (ft_info == NULL) { 2480 return BCM_E_INIT; 2481 } 2482 2483 /* Check if the template is in use by some flow group */ 2484 rv = _bcm_xgs5_ft_flow_group_list_template_in_use_check(unit, id); 2485 if (rv == BCM_E_EXISTS) { 2486 /* One cannot delete a template without deleting the 2487 * association of the template to the flow group. 2488 */ 2489 return BCM_E_CONFIG; 2490 } 2491 2492 sal_memset(&template_int_info, 0, sizeof(template_int_info)); 2493 rv = _bcm_xgs5_ft_template_list_template_get(unit, id, &template_int_info); 2494 if (BCM_FAILURE(rv)) { 2495 return rv; 2496 } 2497 2498 if (template_int_info.interval_secs != 0) { 2499 /* We are still periodically exporting this template, reject 2500 * the delete 2501 */ 2502 return BCM_E_CONFIG; 2503 } 2504 2505 /* Delete the template from the list with the given template Id */ 2506 rv = _bcm_xgs5_ft_template_list_template_delete(unit, id); 2507 2508 /* If not found, return not found */ 2509 if (BCM_FAILURE(rv)) { 2510 return rv; 2511 } 2512 2513 /* Else inform FT EAPP of deleted export template */ 2514 rv = _bcm_xgs5_ft_eapp_send_template_delete_msg(unit, id); 2515 2516 if (BCM_FAILURE(rv)) { 2517 return rv; 2518 } 2519 2520 /* Free up the ID from the pool */ 2521 BCM_IF_ERROR_RETURN(shr_idxres_list_free(ft_info->template_pool, id)); 2522 2523 return BCM_E_NONE; 2524 } 2525 2526 /* 2527 * Function: 2528 * _bcm_th_ft_collector_create 2529 * Purpose: 2530 * Create a flowtracker collector with given collector info. 2531 * Parameters: 2532 * unit - (IN) BCM device number 2533 * options - (IN) Collector create options 2534 * id - (INOUT) Collector Id 2535 * collector_info - (IN) Collector info 2536 * Returns: 2537 * BCM_E_XXX - BCM error code. 2538 */ 2539 int _bcm_th_ft_collector_create(int unit, 2540 uint32 options, 2541 bcm_flowtracker_collector_t *id, 2542 bcm_flowtracker_collector_info_t *collector_info) 2543 { 2544 int rv = BCM_E_NONE; 2545 _bcm_int_ft_collector_info_t old_collector_int_info; 2546 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 2547 2548 if (ft_info == NULL) { 2549 return BCM_E_INIT; 2550 } 2551 2552 if (ft_info->cfg_mode != SHR_FT_CFG_MODE_V1) { 2553 /* API only supported in v1 flowtracker */ 2554 return BCM_E_UNAVAIL; 2555 } 2556 2557 /* Validate collector_info for any unsupported encap or 2558 * export length etc. 2559 */ 2560 rv = _bcm_th_ft_collector_info_validate(unit, collector_info); 2561 if (BCM_FAILURE(rv)) { 2562 return rv; 2563 } 2564 2565 /* 1. IF replace, WITH_ID is mandatory. If not provided, return 2566 * BCM_E_PARAM. 2567 * 2568 * 2. Also verify that a collector with such an ID 2569 * exists, else return BCM_E_NOT_FOUND 2570 */ 2571 if ((options & BCM_FLOWTRACKER_COLLECTOR_REPLACE) && 2572 !(options & BCM_FLOWTRACKER_COLLECTOR_WITH_ID)) { 2573 return BCM_E_PARAM; 2574 } 2575 2576 if ((options & BCM_FLOWTRACKER_COLLECTOR_WITH_ID) && 2577 (options & BCM_FLOWTRACKER_COLLECTOR_REPLACE)) { 2578 sal_memset(&old_collector_int_info, 0, sizeof(old_collector_int_info)); 2579 rv = _bcm_xgs5_ft_collector_list_collector_get(unit, *id, 2580 &old_collector_int_info); 2581 if (BCM_FAILURE(rv)) { 2582 return rv; 2583 } 2584 } 2585 2586 /* WITH_ID */ 2587 if (options & BCM_FLOWTRACKER_COLLECTOR_WITH_ID) { 2588 if (!(options & BCM_FLOWTRACKER_COLLECTOR_REPLACE)) { 2589 /* If WITH_ID and not replace, reserve the ID */ 2590 rv = shr_idxres_list_reserve(ft_info->collector_pool, 2591 *id, *id); 2592 if (BCM_FAILURE(rv)) { 2593 return ((rv == BCM_E_RESOURCE) ? BCM_E_EXISTS : rv); 2594 } 2595 } 2596 } else { 2597 /* Else allocate the ID */ 2598 rv = shr_idxres_list_alloc(ft_info->collector_pool, 2599 (shr_idxres_element_t *)id); 2600 if (BCM_FAILURE(rv)) { 2601 return rv; 2602 } 2603 } 2604 2605 /* WITH_ID and replace. */ 2606 if ((options & BCM_FLOWTRACKER_COLLECTOR_WITH_ID) && 2607 (options & BCM_FLOWTRACKER_COLLECTOR_REPLACE)) { 2608 /* Modify the collector info in the list with ID. */ 2609 rv = _bcm_xgs5_ft_collector_list_collector_modify(unit, *id, 2610 collector_info); 2611 } 2612 else { 2613 /* Add it to the list of collectors */ 2614 rv = _bcm_xgs5_ft_collector_list_collector_add(unit, *id, collector_info); 2615 } 2616 if (BCM_FAILURE(rv)) { 2617 /* Free up the collector id allocated */ 2618 if (!(options & BCM_FLOWTRACKER_COLLECTOR_REPLACE)) { 2619 BCM_IF_ERROR_RETURN( 2620 shr_idxres_list_free(ft_info->collector_pool,*id)); 2621 } 2622 return rv; 2623 } 2624 2625 /* Inform FT EAPP of the change/addition in/of collector information */ 2626 rv = _bcm_xgs5_ft_eapp_send_collector_create_msg( 2627 unit, *id, 2628 BCM_INT_COLLECTOR_INVALID_EXPORT_PROFILE_ID); 2629 if (BCM_FAILURE(rv)) { 2630 if (!(options & BCM_FLOWTRACKER_COLLECTOR_REPLACE)) { 2631 BCM_IF_ERROR_RETURN( 2632 shr_idxres_list_free(ft_info->collector_pool, *id)); 2633 BCM_IF_ERROR_RETURN( 2634 _bcm_xgs5_ft_collector_list_collector_delete(unit, *id)); 2635 } 2636 return rv; 2637 } 2638 2639 return BCM_E_NONE; 2640 } 2641 2642 /* 2643 * Function: 2644 * _bcm_th_ft_collector_get 2645 * Purpose: 2646 * Get flowtracker collector information 2647 * Parameters: 2648 * unit - (IN) BCM device number 2649 * id - (IN) Collector Id 2650 * collector_info - (OUT) Collector info 2651 * Returns: 2652 * BCM_E_XXX - BCM error code. 2653 */ 2654 int _bcm_th_ft_collector_get(int unit, 2655 bcm_flowtracker_collector_t id, 2656 bcm_flowtracker_collector_info_t *collector_info) 2657 { 2658 _bcm_int_ft_collector_info_t collector_int_info; 2659 int rv = BCM_E_NONE; 2660 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 2661 2662 if (ft_info == NULL) { 2663 return BCM_E_INIT; 2664 } 2665 2666 if (ft_info->cfg_mode != SHR_FT_CFG_MODE_V1) { 2667 /* API only supported in v1 flowtracker */ 2668 return BCM_E_UNAVAIL; 2669 } 2670 2671 /* Ensure collector_info is not NULL */ 2672 if (collector_info == NULL) { 2673 return BCM_E_PARAM; 2674 } 2675 2676 sal_memset(&collector_int_info, 0, sizeof(collector_int_info)); 2677 /* Get the collector info from the list 2678 * using ID. 2679 */ 2680 rv = _bcm_xgs5_ft_collector_list_collector_get(unit, id, 2681 &collector_int_info); 2682 2683 /* If not found, return BCM_E_NOT_FOUND */ 2684 if (BCM_FAILURE(rv)) { 2685 return rv; 2686 } 2687 2688 /* Else return SUCCESS */ 2689 sal_memcpy(collector_info, &(collector_int_info.collector_info), 2690 sizeof(bcm_flowtracker_collector_info_t)); 2691 2692 return BCM_E_NONE; 2693 } 2694 2695 /* 2696 * Function: 2697 * _bcm_th_ft_collector_get_all 2698 * Purpose: 2699 * Get the list of all flowtracker collectors configured. 2700 * Parameters: 2701 * unit - (IN) BCM device number 2702 * max_size - (IN) Size of the collector list array 2703 * collector_list - (OUT) Collector id list 2704 * list_szie - (OUT) NUmber of elements in the list 2705 * Returns: 2706 * BCM_E_XXX - BCM error code. 2707 */ 2708 int _bcm_th_ft_collector_get_all( 2709 int unit, 2710 int max_size, 2711 bcm_flowtracker_collector_t *collector_list, 2712 int *list_size) 2713 { 2714 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 2715 int i; 2716 int num_collectors; 2717 2718 if (ft_info == NULL) { 2719 return BCM_E_INIT; 2720 } 2721 2722 if (ft_info->cfg_mode != SHR_FT_CFG_MODE_V1) { 2723 /* API only supported in v1 flowtracker */ 2724 return BCM_E_UNAVAIL; 2725 } 2726 2727 /* If the max_size is non zero and list == NULL, return 2728 * BCM_E_PARAM. 2729 */ 2730 if (max_size != 0 && collector_list == NULL) { 2731 return BCM_E_PARAM; 2732 } 2733 2734 num_collectors = 0; 2735 *list_size = 0; 2736 for (i = BCM_INT_FT_COLLECTOR_START_ID; i <= BCM_INT_FT_COLLECTOR_END_ID; i++) { 2737 if (ft_collector_info_list[unit][i].collector_id == i) { 2738 /* Collector exists */ 2739 num_collectors++; 2740 if (*list_size < max_size) { 2741 collector_list[*list_size] = i; 2742 (*list_size)++; 2743 } 2744 } 2745 } 2746 2747 /* If the max_size is 0 then return the number of collectors configured in 2748 * list_size 2749 */ 2750 if (max_size == 0) { 2751 *list_size = num_collectors; 2752 return BCM_E_NONE; 2753 } 2754 2755 return BCM_E_NONE; 2756 } 2757 2758 /* 2759 * Function: 2760 * _bcm_th_ft_collector_destroy 2761 * Purpose: 2762 * Destroy a flowtracker collector 2763 * Parameters: 2764 * unit - (IN) BCM device number 2765 * collector_id - (IN) Collector Id 2766 * Returns: 2767 * BCM_E_XXX - BCM error code. 2768 */ 2769 int _bcm_th_ft_collector_destroy(int unit, 2770 bcm_flowtracker_collector_t id) 2771 { 2772 int rv = BCM_E_NONE; 2773 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 2774 2775 if (ft_info == NULL) { 2776 return BCM_E_INIT; 2777 } 2778 2779 if (ft_info->cfg_mode != SHR_FT_CFG_MODE_V1) { 2780 /* API only supported in v1 flowtracker */ 2781 return BCM_E_UNAVAIL; 2782 } 2783 2784 /* Check if the collector is in use by some flow group */ 2785 rv = _bcm_xgs5_ft_flow_group_list_collector_in_use_check(unit, id); 2786 if (rv == BCM_E_EXISTS) { 2787 /* One cannot delete a collector without deleting the 2788 * association of the collector to the flow group. 2789 */ 2790 return BCM_E_CONFIG; 2791 } 2792 2793 /* Delete the collector from the collector list with 2794 * given ID. 2795 */ 2796 rv = _bcm_xgs5_ft_collector_list_collector_delete(unit, id); 2797 /* If not found in the list, return BCM_E_NOT_FOUND */ 2798 if (BCM_FAILURE(rv)) { 2799 return rv; 2800 } 2801 2802 /* Else inform FT EAPP of deleted collector */ 2803 rv = _bcm_xgs5_ft_eapp_send_collector_delete_msg(unit, id); 2804 if (BCM_FAILURE(rv)) { 2805 return rv; 2806 } 2807 2808 /* Free up the ID from the pool */ 2809 BCM_IF_ERROR_RETURN(shr_idxres_list_free(ft_info->collector_pool, id)); 2810 2811 return BCM_E_NONE; 2812 } 2813 2814 /* 2815 * Function: 2816 * _bcm_th_ft_template_transmit_config_set 2817 * Purpose: 2818 * Set the template set transmit configuration 2819 * Parameters: 2820 * unit - (IN) BCM device number 2821 * template_id - (IN) Template Id 2822 * collector_id - (IN) Collector Id 2823 * config - (IN) Template transmit config 2824 * Returns: 2825 * BCM_E_XXX - BCM error code. 2826 */ 2827 int 2828 _bcm_th_ft_template_transmit_config_set( 2829 int unit, 2830 bcm_flowtracker_export_template_t template_id, 2831 bcm_flowtracker_collector_t collector_id, 2832 bcm_flowtracker_template_transmit_config_t *config) 2833 { 2834 _bcm_int_ft_export_template_info_t template_int_info; 2835 _bcm_int_ft_collector_info_t collector_int_info; 2836 int coll_int_id = 0; 2837 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 2838 int rv; 2839 2840 if (ft_info == NULL) { 2841 return BCM_E_INIT; 2842 } 2843 2844 2845 /* Check if template and collector are configured */ 2846 sal_memset(&template_int_info, 0, sizeof(template_int_info)); 2847 rv = _bcm_xgs5_ft_template_list_template_get(unit, template_id, 2848 &template_int_info); 2849 if (BCM_FAILURE(rv)) { 2850 return rv; 2851 } 2852 2853 if (ft_info->cfg_mode == SHR_FT_CFG_MODE_V1) { 2854 sal_memset(&collector_int_info, 0, sizeof(collector_int_info)); 2855 rv = _bcm_xgs5_ft_collector_list_collector_get(unit, collector_id, 2856 &collector_int_info); 2857 if (BCM_FAILURE(rv)) { 2858 return rv; 2859 } 2860 } else { 2861 rv = _bcm_xgs5_ft_v2_collector_list_collector_get(unit, collector_id, 2862 &coll_int_id); 2863 if (BCM_FAILURE(rv)) { 2864 return rv; 2865 } 2866 } 2867 2868 /* Copy over the information */ 2869 template_int_info.interval_secs = config->retransmit_interval_secs; 2870 template_int_info.initial_burst = config->initial_burst; 2871 2872 rv = _bcm_xgs5_ft_template_list_template_modify(unit, template_id, 2873 &template_int_info); 2874 BCM_IF_ERROR_RETURN(rv); 2875 2876 /* Send message to EAPP */ 2877 BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_eapp_send_template_xmit_start(unit, 2878 template_id, 2879 collector_id)); 2880 2881 return BCM_E_NONE; 2882 } 2883 2884 /* 2885 * Function: 2886 * _bcm_th_flowtracker_template_transmit_config_get 2887 * Purpose: 2888 * Get the template set transmit configuration 2889 * Parameters: 2890 * unit - (IN) BCM device number 2891 * template_id - (IN) Template Id 2892 * collector_id - (IN) Collector Id 2893 * config - (OUT) Template transmit config 2894 * Returns: 2895 * BCM_E_XXX - BCM error code. 2896 */ 2897 int 2898 _bcm_th_ft_template_transmit_config_get( 2899 int unit, 2900 bcm_flowtracker_export_template_t template_id, 2901 bcm_flowtracker_collector_t collector_id, 2902 bcm_flowtracker_template_transmit_config_t *config) 2903 { 2904 _bcm_int_ft_export_template_info_t template_int_info; 2905 _bcm_int_ft_collector_info_t collector_int_info; 2906 int coll_int_id = 0; 2907 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 2908 int rv; 2909 2910 if (ft_info == NULL) { 2911 return BCM_E_INIT; 2912 } 2913 2914 /* Check if template and collector are configured */ 2915 sal_memset(&template_int_info, 0, sizeof(template_int_info)); 2916 rv = _bcm_xgs5_ft_template_list_template_get(unit, template_id, 2917 &template_int_info); 2918 if (BCM_FAILURE(rv)) { 2919 return rv; 2920 } 2921 2922 if (ft_info->cfg_mode == SHR_FT_CFG_MODE_V1) { 2923 sal_memset(&collector_int_info, 0, sizeof(collector_int_info)); 2924 rv = _bcm_xgs5_ft_collector_list_collector_get(unit, collector_id, 2925 &collector_int_info); 2926 if (BCM_FAILURE(rv)) { 2927 return rv; 2928 } 2929 } else { 2930 rv = _bcm_xgs5_ft_v2_collector_list_collector_get(unit, collector_id, 2931 &coll_int_id); 2932 if (BCM_FAILURE(rv)) { 2933 return rv; 2934 } 2935 } 2936 2937 /* Copy over the information */ 2938 config->retransmit_interval_secs = template_int_info.interval_secs; 2939 config->initial_burst = template_int_info.initial_burst; 2940 2941 return BCM_E_NONE; 2942 } 2943 2944 /* 2945 * Function: 2946 * _bcm_th_ft_flow_group_create 2947 * Purpose: 2948 * Create a flowtracker flow group 2949 * Parameters: 2950 * unit - (IN) BCM device number 2951 * options - (IN) Group create options 2952 * id - (INOUT) Group Id 2953 * flow_group_info - (IN) Group Info 2954 * Returns: 2955 * BCM_E_XXX - BCM error code. 2956 */ 2957 int _bcm_th_ft_flow_group_create(int unit, 2958 uint32 options, 2959 bcm_flowtracker_group_t *id, 2960 bcm_flowtracker_group_info_t *flow_group_info) 2961 { 2962 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 2963 int i, rv = BCM_E_NONE; 2964 _bcm_int_ft_flow_group_info_t flow_group_int_info; 2965 2966 if (ft_info == NULL) { 2967 return BCM_E_INIT; 2968 } 2969 2970 /* 1. IF replace, WITH_ID is mandatory. If not provided, return 2971 * BCM_E_PARAM. 2972 * 2973 * 2. Also verify that a flow group with such an ID 2974 * exists, else return BCM_E_NOT_FOUND 2975 */ 2976 if ((options & BCM_FLOWTRACKER_GROUP_REPLACE) && 2977 !(options & BCM_FLOWTRACKER_GROUP_WITH_ID)) { 2978 return BCM_E_PARAM; 2979 } 2980 2981 if ((options & BCM_FLOWTRACKER_GROUP_REPLACE) && 2982 (options & BCM_FLOWTRACKER_GROUP_WITH_ID)) { 2983 if ((flow_group_info->group_flags & BCM_FLOWTRACKER_GROUP_DEFAULT) && 2984 (ft_info->default_grp_id != *id)) { 2985 return (BCM_E_CONFIG); 2986 } 2987 2988 if ((!(flow_group_info->group_flags & BCM_FLOWTRACKER_GROUP_DEFAULT)) && 2989 (ft_info->default_grp_id == *id)) { 2990 return (BCM_E_PARAM); 2991 } 2992 2993 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, *id); 2994 if (BCM_E_EXISTS != rv) { 2995 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 2996 (BSL_META_U(unit, 2997 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 2998 unit, *id)); 2999 return (BCM_E_NOT_FOUND); 3000 } 3001 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 3002 /* Get the flow group info for this group id */ 3003 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, *id, 3004 &flow_group_int_info); 3005 3006 /* Return BCM_E_NOT_FOUND if not found */ 3007 if (BCM_FAILURE(rv)) { 3008 return rv; 3009 } 3010 3011 for (i = 0; i < ft_info->num_pipes; ++i) { 3012 if (flow_group_info->field_group[i] != flow_group_int_info.field_group[i]) { 3013 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 3014 (BSL_META_U(unit, 3015 "FT(unit %d) Error: Group (ID:%d) field group can not modify.\n"), 3016 unit, *id)); 3017 return (BCM_E_CONFIG); 3018 } 3019 } 3020 } 3021 3022 /* WITH_ID */ 3023 if (options & BCM_FLOWTRACKER_GROUP_WITH_ID) { 3024 if ((flow_group_info->group_flags & BCM_FLOWTRACKER_GROUP_DEFAULT) && 3025 ft_info->default_grp_id) { 3026 return (BCM_E_CONFIG); 3027 } 3028 3029 if (!(options & BCM_FLOWTRACKER_GROUP_REPLACE)) { 3030 /* If WITH_ID and not replace, reserve the ID */ 3031 rv = shr_idxres_list_reserve(ft_info->flow_group_pool, 3032 *id, *id); 3033 if (BCM_FAILURE(rv)) { 3034 return ((rv == BCM_E_RESOURCE) ? BCM_E_EXISTS : rv); 3035 } 3036 } 3037 } else { 3038 /* Else allocate the ID */ 3039 rv = shr_idxres_list_alloc(ft_info->flow_group_pool, 3040 (shr_idxres_element_t *)id); 3041 if (BCM_FAILURE(rv)) { 3042 return rv; 3043 } 3044 } 3045 3046 if (!(options & BCM_FLOWTRACKER_GROUP_REPLACE)) { 3047 /* Add it to the list of flow_groups if it is not a replace */ 3048 rv = _bcm_xgs5_ft_flow_group_list_flow_group_add(unit, *id); 3049 if (BCM_FAILURE(rv)) { 3050 /* Free up the flow_group id allocated */ 3051 if (!(options & BCM_FLOWTRACKER_GROUP_REPLACE)) { 3052 BCM_IF_ERROR_RETURN( 3053 shr_idxres_list_free(ft_info->flow_group_pool, *id)); 3054 } 3055 return rv; 3056 } 3057 } 3058 3059 /* Observation domain Id is a global paramter. Setting it for one group 3060 * changes it for all groups 3061 */ 3062 ft_info->observation_domain_id = flow_group_info->observation_domain_id; 3063 3064 /* Program Flowtracker group with default properties */ 3065 #if defined(BCM_MAVERICK2_SUPPORT) 3066 if (soc_feature(unit, soc_feature_mv2_style_flowtracker)) { 3067 if (!(options & BCM_FLOWTRACKER_GROUP_REPLACE)) { 3068 rv = _bcm_mv2_flowtracker_flow_group_default_config_set(unit, *id); 3069 if (BCM_FAILURE(rv)) { 3070 BCM_IF_ERROR_RETURN( 3071 shr_idxres_list_free(ft_info->flow_group_pool, *id)); 3072 return rv; 3073 } 3074 } 3075 } 3076 #endif /* BCM_MAVERICK2_SUPPORT */ 3077 3078 /* Inform FT EAPP of the change/addition in/of flow_group information */ 3079 if (options & BCM_FLOWTRACKER_GROUP_REPLACE) { 3080 /* Only thing that can be replaced using flow group replace API is 3081 * observation domain. 3082 */ 3083 rv = _bcm_xgs5_ft_eapp_send_flow_group_update_msg( 3084 unit, *id, 3085 SHR_FT_GROUP_UPDATE_OBSERVATION_DOMAIN, 3086 flow_group_info->observation_domain_id); 3087 } else { 3088 rv = _bcm_xgs5_ft_eapp_send_flow_group_create_msg(unit, *id); 3089 } 3090 3091 if (BCM_FAILURE(rv)) { 3092 /* Free up the flow_group id allocated */ 3093 if (!(options & BCM_FLOWTRACKER_GROUP_REPLACE)) { 3094 BCM_IF_ERROR_RETURN(shr_idxres_list_free(ft_info->flow_group_pool, 3095 *id)); 3096 BCM_IF_ERROR_RETURN( 3097 _bcm_xgs5_ft_flow_group_list_flow_group_delete(unit, *id)); 3098 #if defined(BCM_MAVERICK2_SUPPORT) 3099 if (soc_feature(unit, soc_feature_mv2_style_flowtracker)) { 3100 BCM_IF_ERROR_RETURN( 3101 _bcm_mv2_flowtracker_flow_group_config_clear(unit, *id)); 3102 } 3103 #endif /* BCM_MAVERICK2_SUPPORT */ 3104 } 3105 return rv; 3106 } 3107 3108 if ((flow_group_info->group_flags & BCM_FLOWTRACKER_GROUP_DEFAULT) && 3109 (!ft_info->default_grp_id)) { 3110 ft_info->default_grp_id = *id; 3111 /* 3112 * Inform FT EAPP of the change in the flow group 3113 * info using flow group default group id. 3114 */ 3115 rv = _bcm_xgs5_ft_eapp_send_flow_group_update_msg(unit, *id, 3116 SHR_FT_GROUP_UPDATE_DEFAULT_GROUP, 3117 1); 3118 if (BCM_FAILURE(rv)) { 3119 return rv; 3120 } 3121 } 3122 3123 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 3124 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, *id, 3125 &flow_group_int_info); 3126 BCM_IF_ERROR_RETURN(rv); 3127 3128 for (i = 0; i < ft_info->num_pipes; ++i) { 3129 flow_group_int_info.field_group[i] = flow_group_info->field_group[i]; 3130 } 3131 rv = _bcm_xgs5_ft_flow_group_list_flow_group_modify(unit, *id, 3132 &flow_group_int_info); 3133 BCM_IF_ERROR_RETURN(rv); 3134 3135 return BCM_E_NONE; 3136 } 3137 3138 /* 3139 * Function: 3140 * _bcm_th_ft_flow_group_get 3141 * Purpose: 3142 * Get flowtracker flow group information 3143 * Parameters: 3144 * unit - (IN) BCM device number 3145 * id - (IN) Group Id 3146 * flow_group_info - (OUT) Group Info 3147 * Returns: 3148 * BCM_E_XXX - BCM error code. 3149 */ 3150 int _bcm_th_ft_flow_group_get(int unit, 3151 bcm_flowtracker_group_t id, 3152 bcm_flowtracker_group_info_t *flow_group_info) 3153 { 3154 _bcm_int_ft_flow_group_info_t flow_group_int_info; 3155 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 3156 int i, rv = BCM_E_NONE; 3157 3158 if (ft_info == NULL) { 3159 return BCM_E_INIT; 3160 } 3161 3162 /* Ensure flow_Group_info is not NULL */ 3163 if (flow_group_info == NULL) { 3164 return BCM_E_PARAM; 3165 } 3166 3167 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, id); 3168 if (BCM_E_EXISTS != rv) { 3169 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 3170 (BSL_META_U(unit, 3171 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 3172 unit, id)); 3173 return (BCM_E_NOT_FOUND); 3174 } 3175 3176 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 3177 /* Get the flow group info for this group id */ 3178 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, id, 3179 &flow_group_int_info); 3180 3181 /* Return BCM_E_NOT_FOUND if not found */ 3182 if (BCM_FAILURE(rv)) { 3183 return rv; 3184 } 3185 3186 /* Else return SUCCESS */ 3187 flow_group_info->observation_domain_id = ft_info->observation_domain_id; 3188 for (i = 0; i < ft_info->num_pipes; ++i) { 3189 flow_group_info->field_group[i] = flow_group_int_info.field_group[i]; 3190 } 3191 if (ft_info->default_grp_id == id) { 3192 flow_group_info->group_flags |= BCM_FLOWTRACKER_GROUP_DEFAULT; 3193 } 3194 3195 return BCM_E_NONE; 3196 } 3197 3198 /* 3199 * Function: 3200 * _bcm_th_ft_flow_group_get_all 3201 * Purpose: 3202 * Get list of all flow groups created 3203 * Parameters: 3204 * unit - (IN) BCM device number 3205 * max_size - (IN) Size of the flow group list array 3206 * flow_group_list - (OUT) List of flow groups created 3207 * list_size - (OUT) Number of flow grups in the list 3208 * Returns: 3209 * BCM_E_XXX - BCM error code. 3210 */ 3211 int _bcm_th_ft_flow_group_get_all(int unit, 3212 int max_size, 3213 bcm_flowtracker_group_t *flow_group_list, 3214 int *list_size) 3215 { 3216 bcm_flowtracker_group_t temp_flow_group_list[BCM_INT_FT_MAX_FLOW_GROUPS]; 3217 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 3218 int rv = BCM_E_NONE, num_flow_groups = 0, num_flow_groups_to_copy = 0; 3219 3220 if (ft_info == NULL) { 3221 return BCM_E_INIT; 3222 } 3223 3224 /* If the max_size is non zero and list == NULL, return 3225 * BCM_E_PARAM. 3226 */ 3227 if (max_size != 0 && flow_group_list == NULL) { 3228 return BCM_E_PARAM; 3229 } 3230 3231 /* Get the list of flow groups */ 3232 rv = _bcm_xgs5_ft_flow_group_list_get_all_ids (unit, temp_flow_group_list, 3233 &num_flow_groups); 3234 if (BCM_FAILURE(rv)) { 3235 return rv; 3236 } 3237 3238 /* If the max_size is 0 and flow_group_info_list is 3239 * NULL, then return the number of flow_groups in 3240 * list_size 3241 */ 3242 if (max_size == 0) { 3243 *list_size = num_flow_groups; 3244 return BCM_E_NONE; 3245 } 3246 3247 /* If the number of flow_groups is less than max_size, 3248 * fill the list for number of flow_groups and fill 3249 * list_size with number_of_flow_groups. 3250 */ 3251 if (num_flow_groups < max_size) { 3252 num_flow_groups_to_copy = num_flow_groups; 3253 } else { 3254 3255 /* If the number of flow_groups is greater than or equal to 3256 * max_size, fill the list for max_size and fill list_size 3257 * with max_size. 3258 */ 3259 num_flow_groups_to_copy = max_size; 3260 } 3261 3262 sal_memcpy(flow_group_list, temp_flow_group_list, 3263 num_flow_groups_to_copy * sizeof(bcm_flowtracker_group_t)); 3264 *list_size = num_flow_groups_to_copy; 3265 3266 return BCM_E_NONE; 3267 } 3268 3269 /* 3270 * Function: 3271 * _bcm_th_ft_flow_group_flow_limit_set 3272 * Purpose: 3273 * Set flow limit on the flow group 3274 * Parameters: 3275 * unit - (IN) BCM device number 3276 * id - (IN) Flow group Id 3277 * flow_limit - (IN) Max number of flows that can be learnt on the group 3278 * Returns: 3279 * BCM_E_XXX - BCM error code. 3280 * Notes: In case of TH/TH2/TH3/TD3A0 flow limit is set in emb app. 3281 * Whereas in case of maverick2 flow limit is set in hardware. 3282 */ 3283 int _bcm_th_ft_flow_group_flow_limit_set(int unit, 3284 bcm_flowtracker_group_t id, 3285 uint32 flow_limit) 3286 { 3287 _bcm_int_ft_flow_group_info_t flow_group_int_info; 3288 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 3289 int rv = BCM_E_NONE; 3290 3291 if (ft_info == NULL) { 3292 return BCM_E_INIT; 3293 } 3294 3295 /* Validate flow limit against max flow limit 3296 */ 3297 if (flow_limit > ft_info->max_flows_total) { 3298 return BCM_E_PARAM; 3299 } 3300 3301 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, id); 3302 if (BCM_E_EXISTS != rv) { 3303 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 3304 (BSL_META_U(unit, 3305 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 3306 unit, id)); 3307 return (BCM_E_NOT_FOUND); 3308 } 3309 3310 /* Get flow group info with the ID from the 3311 * flow group list 3312 */ 3313 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 3314 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, id, 3315 &flow_group_int_info); 3316 3317 if (BCM_FAILURE(rv)) { 3318 return rv; 3319 } 3320 3321 /* If found, modify the flow group info in the 3322 * list with this flow limit information. 3323 */ 3324 flow_group_int_info.flow_limit = flow_limit; 3325 rv = _bcm_xgs5_ft_flow_group_list_flow_group_modify(unit, id, 3326 &flow_group_int_info); 3327 3328 if (BCM_FAILURE(rv)) { 3329 return rv; 3330 } 3331 3332 /* Inform FT EAPP of the change in the flow group 3333 * info using flow group update msg. 3334 */ 3335 rv = _bcm_xgs5_ft_eapp_send_flow_group_update_msg( 3336 unit, id, 3337 SHR_FT_GROUP_UPDATE_FLOW_THRESHOLD, 3338 flow_limit); 3339 if (BCM_FAILURE(rv)) { 3340 return rv; 3341 } 3342 3343 #if defined(BCM_MAVERICK2_SUPPORT) 3344 if (soc_feature(unit, soc_feature_mv2_style_flowtracker)) { 3345 rv = _bcm_mv2_flowtracker_flow_group_flow_limit_set(unit, id, 3346 flow_limit); 3347 if (BCM_FAILURE(rv)) { 3348 return rv; 3349 } 3350 } 3351 #endif /* BCM_MAVERICK2_SUPPORT */ 3352 3353 return BCM_E_NONE; 3354 } 3355 3356 /* 3357 * Function: 3358 * _bcm_th_ft_flow_group_flow_limit_get 3359 * Purpose: 3360 * Get flow limit of the flow group 3361 * Parameters: 3362 * unit - (IN) BCM device number 3363 * id - (IN) Flow group Id 3364 * flow_limit - (OUT) Flow limit 3365 * Returns: 3366 * BCM_E_XXX - BCM error code. 3367 * Notes: In case of TH/TH2/TH3/TD3A0 flow limit is retreived from emb app. 3368 * Whereas in case of maverick2 flow limit is retreived from hardware. 3369 */ 3370 int _bcm_th_ft_flow_group_flow_limit_get(int unit, 3371 bcm_flowtracker_group_t id, 3372 uint32 *flow_limit) 3373 { 3374 _bcm_int_ft_flow_group_info_t flow_group_int_info; 3375 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 3376 int rv = BCM_E_NONE; 3377 3378 if (ft_info == NULL) { 3379 return BCM_E_INIT; 3380 } 3381 3382 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, id); 3383 if (BCM_E_EXISTS != rv) { 3384 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 3385 (BSL_META_U(unit, 3386 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 3387 unit, id)); 3388 return (BCM_E_NOT_FOUND); 3389 } 3390 3391 /* Get flow group info with the ID from the 3392 * flow group list 3393 */ 3394 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 3395 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, id, 3396 &flow_group_int_info); 3397 /* If not found, return BCM_E_NOT_FOUND */ 3398 if (BCM_FAILURE(rv)) { 3399 return rv; 3400 } 3401 3402 /* If found, return the flow limit info in 3403 * flow_limit param. 3404 */ 3405 *flow_limit = flow_group_int_info.flow_limit; 3406 3407 #if defined(BCM_MAVERICK2_SUPPORT) 3408 if (soc_feature(unit, soc_feature_mv2_style_flowtracker)) { 3409 rv = _bcm_mv2_flowtracker_flow_group_flow_limit_get(unit, id, 3410 flow_limit); 3411 if (BCM_FAILURE(rv)) { 3412 return rv; 3413 } 3414 } 3415 #endif /* BCM_MAVERICK2_SUPPORT */ 3416 3417 return BCM_E_NONE; 3418 } 3419 3420 /* 3421 * Function: 3422 * _bcm_th_ft_flow_group_stat_modeid_set 3423 * Purpose: 3424 * Set stat modeid on the flow group 3425 * Parameters: 3426 * unit - (IN) BCM device number 3427 * id - (IN) Flow group Id 3428 * stat_modeid - (IN) Stat Modeid 3429 * Returns: 3430 * BCM_E_XXX - BCM error code. 3431 * Notes: In case of TH/TH2/TH3/TD3A0 default modeid is reserved in init. 3432 * Whereas in case of maverick2 stat mode is created first by user 3433 * and set in hardware 3434 */ 3435 int 3436 _bcm_th_ft_flow_group_stat_modeid_set(int unit, 3437 bcm_flowtracker_group_t id, 3438 uint32 stat_modeid) 3439 { 3440 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 3441 int rv = BCM_E_UNAVAIL; 3442 3443 if (ft_info == NULL) { 3444 return BCM_E_INIT; 3445 } 3446 3447 #if defined(BCM_MAVERICK2_SUPPORT) 3448 if (soc_feature(unit, soc_feature_mv2_style_flowtracker)) { 3449 rv = _bcm_mv2_flowtracker_flow_group_stat_modeid_set(unit, id, 3450 stat_modeid); 3451 if (BCM_FAILURE(rv)) { 3452 return rv; 3453 } 3454 } 3455 #endif /* BCM_MAVERICK2_SUPPORT */ 3456 3457 return rv; 3458 } 3459 3460 /* 3461 * Function: 3462 * _bcm_th_ft_flow_group_stat_modeid_get 3463 * Purpose: 3464 * Get stat modeid associated to flow group 3465 * Parameters: 3466 * unit - (IN) BCM device number 3467 * id - (IN) Flow group Id 3468 * stat_modeid - (OUT) Stat Modeid 3469 * Returns: 3470 * BCM_E_XXX - BCM error code. 3471 * Notes: In case of TH/TH2/TH3/TD3A0 default modeid is reserved in init. 3472 * Whereas in case of maverick2 stat mode is created first by user 3473 * and get from hardware. 3474 */ 3475 int 3476 _bcm_th_ft_flow_group_stat_modeid_get(int unit, 3477 bcm_flowtracker_group_t id, 3478 uint32 *stat_modeid) 3479 { 3480 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 3481 int rv = BCM_E_UNAVAIL; 3482 3483 if (ft_info == NULL) { 3484 return BCM_E_INIT; 3485 } 3486 3487 #if defined(BCM_MAVERICK2_SUPPORT) 3488 if (soc_feature(unit, soc_feature_mv2_style_flowtracker)) { 3489 rv = _bcm_mv2_flowtracker_flow_group_stat_modeid_get(unit, id, 3490 stat_modeid); 3491 if (BCM_FAILURE(rv)) { 3492 return rv; 3493 } 3494 } 3495 #endif /* BCM_MAVERICK2_SUPPORT */ 3496 3497 return rv; 3498 } 3499 3500 /* 3501 * Function: 3502 * _bcm_th_ft_flow_group_age_timer_set 3503 * Purpose: 3504 * Set aging timer interval in ms on the flow group. Aging interval has to 3505 * be configured in steps of 1sec with a minimum of 1sec. Default value of 3506 * 1 minute 3507 * Parameters: 3508 * unit - (IN) BCM device number 3509 * id - (IN) Flow group Id 3510 * aging_interval_ms - (IN) Aging interval in msec 3511 * Returns: 3512 * BCM_E_XXX - BCM error code. 3513 */ 3514 int _bcm_th_ft_flow_group_age_timer_set(int unit, 3515 bcm_flowtracker_group_t id, 3516 uint32 aging_interval_ms) 3517 { 3518 _bcm_int_ft_flow_group_info_t flow_group_int_info; 3519 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 3520 int rv = BCM_E_NONE; 3521 3522 if (ft_info == NULL || ft_info->elph_mode == TRUE) { 3523 return BCM_E_INIT; 3524 } 3525 3526 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, id); 3527 if (BCM_E_EXISTS != rv) { 3528 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 3529 (BSL_META_U(unit, 3530 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 3531 unit, id)); 3532 return (BCM_E_NOT_FOUND); 3533 } 3534 3535 /* Validate if aging timer interval is a multiple of 100ms 3536 * and greater than 100ms. 3537 */ 3538 rv = _bcm_th_ft_validate_aging_timer_interval(unit, aging_interval_ms); 3539 if (BCM_FAILURE(rv)) { 3540 return rv; 3541 } 3542 3543 /* Get flow group info with the ID from the 3544 * flow group list 3545 */ 3546 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 3547 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, id, 3548 &flow_group_int_info); 3549 3550 3551 /* If not found, return BCM_E_NOT_FOUND */ 3552 if (BCM_FAILURE(rv)) { 3553 return rv; 3554 } 3555 3556 /* If found, modify the flow group info in the 3557 * list with this aging interval information. 3558 */ 3559 flow_group_int_info.aging_interval_msecs = aging_interval_ms; 3560 rv = _bcm_xgs5_ft_flow_group_list_flow_group_modify(unit, id, 3561 &flow_group_int_info); 3562 3563 if (BCM_FAILURE(rv)) { 3564 return rv; 3565 } 3566 3567 /* Inform FT EAPP of the change in the flow group 3568 * info using flow group update msg. 3569 */ 3570 rv = _bcm_xgs5_ft_eapp_send_flow_group_update_msg(unit, id, 3571 SHR_FT_GROUP_UPDATE_AGING_INTERVAL, aging_interval_ms); 3572 if (BCM_FAILURE(rv)) { 3573 return rv; 3574 } 3575 return BCM_E_NONE; 3576 } 3577 3578 /* 3579 * Function: 3580 * _bcm_th_ft_flow_group_age_timer_get 3581 * Purpose: 3582 * Get aging timer interval in ms set on the flow group. 3583 * Parameters: 3584 * unit - (IN) BCM device number 3585 * id - (IN) Flow group Id 3586 * aging_interval_ms - (OUT) Aging interval in msec 3587 * Returns: 3588 * BCM_E_XXX - BCM error code. 3589 */ 3590 int _bcm_th_ft_flow_group_age_timer_get(int unit, 3591 bcm_flowtracker_group_t id, 3592 uint32 *aging_interval_ms) 3593 { 3594 _bcm_int_ft_flow_group_info_t flow_group_int_info; 3595 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 3596 int rv = BCM_E_NONE; 3597 3598 if (ft_info == NULL || ft_info->elph_mode == TRUE) { 3599 return BCM_E_INIT; 3600 } 3601 3602 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, id); 3603 if (BCM_E_EXISTS != rv) { 3604 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 3605 (BSL_META_U(unit, 3606 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 3607 unit, id)); 3608 return (BCM_E_NOT_FOUND); 3609 } 3610 3611 /* Get flow group info with the ID from the 3612 * flow group list 3613 */ 3614 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 3615 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, id, 3616 &flow_group_int_info); 3617 3618 if (BCM_FAILURE(rv)) { 3619 return rv; 3620 } 3621 3622 /* If found, return the aging info in 3623 * aging_interval_ms param. 3624 */ 3625 *aging_interval_ms = flow_group_int_info.aging_interval_msecs; 3626 return BCM_E_NONE; 3627 } 3628 3629 /* 3630 * Function: 3631 * _bcm_th_ft_flow_group_tracking_params_validate 3632 * Purpose: 3633 * Validate Tracking params 3634 * Parameters: 3635 * unit - (IN) BCM device number 3636 * id - (IN) Flow group Id 3637 * num_tracking_params - (IN) Number of tracking params in the list. 3638 * tracking_params_list - (IN) Tracking Params list. 3639 * Returns: 3640 * BCM_E_XXX - BCM error code. 3641 */ 3642 int _bcm_th_ft_flow_group_tracking_params_validate( 3643 int unit, 3644 bcm_flowtracker_group_t id, 3645 int num_tracking_params, 3646 bcm_flowtracker_tracking_param_info_t *tracking_params_list) 3647 { 3648 int i; 3649 uint8 in_port_qual_present = 0; 3650 3651 if (soc_feature(unit, soc_feature_th3_style_fp)) { 3652 for (i = 0; i < num_tracking_params; i++) { 3653 if (tracking_params_list[i].param == bcmFlowtrackerTrackingParamTypeInPort) { 3654 in_port_qual_present = 1; 3655 break; 3656 } 3657 } 3658 if (!in_port_qual_present) { 3659 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 3660 (BSL_META_U(unit, 3661 "FT(unit %d) Error: Tracking param type in port is mandatory for TH3 style platforms.\n"), 3662 unit)); 3663 return BCM_E_PARAM; 3664 } 3665 } 3666 3667 return BCM_E_NONE; 3668 } 3669 3670 /* 3671 * Function: 3672 * _bcm_th_ft_flow_group_tracking_params_set 3673 * Purpose: 3674 * Set Tracking params 3675 * Create EM group table for new groups 3676 * Parameters: 3677 * unit - (IN) BCM device number 3678 * id - (IN) Flow group Id 3679 * num_tracking_params - (IN) Number of tracking params in the list. 3680 * tracking_params_list - (IN) Tracking Params list. 3681 * Returns: 3682 * BCM_E_XXX - BCM error code. 3683 */ 3684 int _bcm_th_ft_flow_group_tracking_params_set( 3685 int unit, 3686 bcm_flowtracker_group_t id, 3687 int num_tracking_params, 3688 bcm_flowtracker_tracking_param_info_t *tracking_params_list) 3689 { 3690 _bcm_int_ft_flow_group_info_t flow_group_int_info; 3691 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 3692 int i, j, rv = BCM_E_NONE; 3693 int em_group_id_map_status = 0; 3694 int em_group_idx = 0; 3695 shr_ft_msg_ctrl_em_group_create_t em_group_msg; 3696 3697 if (ft_info == NULL) { 3698 return BCM_E_INIT; 3699 } 3700 3701 if (ft_info->cfg_mode < SHR_FT_CFG_MODE_V2) { 3702 return BCM_E_CONFIG; 3703 } 3704 3705 if (((num_tracking_params == 0) || 3706 (tracking_params_list == NULL)) || 3707 (ft_info->default_grp_id == id)) { 3708 return BCM_E_PARAM; 3709 } 3710 3711 BCM_IF_ERROR_RETURN(_bcm_th_ft_flow_group_tracking_params_validate(unit, 3712 id, 3713 num_tracking_params, 3714 tracking_params_list)); 3715 3716 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, id); 3717 if (BCM_E_EXISTS != rv) { 3718 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 3719 (BSL_META_U(unit, 3720 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 3721 unit, id)); 3722 return (BCM_E_NOT_FOUND); 3723 } 3724 3725 /* 3726 * Get flow group info with the ID from the 3727 * flow group list 3728 */ 3729 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 3730 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, id, 3731 &flow_group_int_info); 3732 3733 /* If not found, return BCM_E_NOT_FOUND */ 3734 if (BCM_FAILURE(rv)) { 3735 return rv; 3736 } 3737 3738 if (flow_group_int_info.num_tracking_params != 0) { 3739 return BCM_E_EXISTS; 3740 } 3741 3742 for (i = 0; i < SHR_FT_MAX_EM_GROUPS; ++i) { 3743 for (j = 0; j < ft_info->num_pipes; ++j) { 3744 if (ft_info->em_group_id_map[i][j] == flow_group_int_info.field_group[j]) { 3745 em_group_id_map_status = 1; 3746 em_group_idx = i; 3747 } else { 3748 em_group_id_map_status = 0; 3749 break; 3750 } 3751 } 3752 if (em_group_id_map_status) { 3753 break; 3754 } 3755 } 3756 3757 if (em_group_id_map_status) { 3758 BCM_IF_ERROR_RETURN( 3759 _bcm_xgs5_ft_eapp_send_flow_group_update_msg(unit, id, 3760 SHR_FT_GROUP_UPDATE_EM_GROUP_IDX, 3761 em_group_idx)); 3762 } else { 3763 for (i = 0; i < SHR_FT_MAX_EM_GROUPS; ++i) { 3764 if (ft_info->em_group_id_map[i][0] == BCM_INT_FT_INVALID_EM_GROUP_ID) { 3765 for (j = 0; j < ft_info->num_pipes; ++j) { 3766 ft_info->em_group_id_map[i][j] = flow_group_int_info.field_group[j]; 3767 } 3768 BCM_IF_ERROR_RETURN(_bcm_th_ft_fill_em_group_create_msg(unit, 3769 flow_group_int_info.field_group, 3770 i, 3771 num_tracking_params, 3772 tracking_params_list, 3773 &em_group_msg)); 3774 3775 BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_eapp_send_em_group_create_msg(unit, 3776 &em_group_msg)); 3777 BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_eapp_send_flow_group_update_msg(unit, id, 3778 SHR_FT_GROUP_UPDATE_EM_GROUP_IDX, 3779 i)); 3780 break; 3781 } 3782 } 3783 if (i >= SHR_FT_MAX_EM_GROUPS) { 3784 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 3785 (BSL_META_U(unit, 3786 "FT(unit %d) Error: Maximum number of EM Groups created.\n"), 3787 unit)); 3788 return BCM_E_RESOURCE; 3789 } 3790 } 3791 3792 flow_group_int_info.num_tracking_params = num_tracking_params; 3793 _BCM_FT_ALLOC(flow_group_int_info.tracking_params, 3794 bcm_flowtracker_tracking_param_info_t, 3795 num_tracking_params * sizeof(bcm_flowtracker_tracking_param_info_t), 3796 "Group Tracking Params list"); 3797 if (flow_group_int_info.tracking_params == NULL) { 3798 return BCM_E_MEMORY; 3799 } 3800 3801 sal_memcpy(flow_group_int_info.tracking_params, tracking_params_list, 3802 sizeof(bcm_flowtracker_tracking_param_info_t) * num_tracking_params); 3803 3804 rv = _bcm_xgs5_ft_flow_group_list_flow_group_modify(unit, id, 3805 &flow_group_int_info); 3806 BCM_IF_ERROR_RETURN(rv); 3807 3808 return BCM_E_NONE; 3809 } 3810 3811 /* 3812 * Function: 3813 * _bcm_th_ft_flow_group_tracking_params_get 3814 * Purpose: 3815 * Set Tracking params 3816 * Create EM group table for new groups 3817 * Parameters: 3818 * unit - (IN) BCM device number 3819 * id - (IN) Flow group Id 3820 * max_size - (IN) Maximum number of tracking params that 3821 * can be accomodated in the list. 3822 * list_size - (OUT) Number of tracking params in the list. 3823 * tracking_params_list - (OUT) Tracking Params list. 3824 * Returns: 3825 * BCM_E_XXX - BCM error code. 3826 */ 3827 int _bcm_th_ft_flow_group_tracking_params_get( 3828 int unit, 3829 bcm_flowtracker_group_t id, 3830 int max_size, 3831 int *list_size, 3832 bcm_flowtracker_tracking_param_info_t *tracking_params_list) 3833 { 3834 _bcm_int_ft_flow_group_info_t flow_group_int_info; 3835 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 3836 int rv = BCM_E_NONE; 3837 3838 if (ft_info == NULL) { 3839 return BCM_E_INIT; 3840 } 3841 3842 if (ft_info->cfg_mode < SHR_FT_CFG_MODE_V2) { 3843 return BCM_E_CONFIG; 3844 } 3845 3846 /* If the max_size is non zero and list == NULL, return 3847 * BCM_E_PARAM. 3848 */ 3849 if (max_size != 0 && tracking_params_list == NULL) { 3850 return BCM_E_PARAM; 3851 } 3852 3853 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, id); 3854 if (BCM_E_EXISTS != rv) { 3855 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 3856 (BSL_META_U(unit, 3857 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 3858 unit, id)); 3859 return (BCM_E_NOT_FOUND); 3860 } 3861 3862 /* 3863 * Get flow group info with the ID from the 3864 * flow group list 3865 */ 3866 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 3867 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, id, 3868 &flow_group_int_info); 3869 3870 /* If not found, return BCM_E_NOT_FOUND */ 3871 if (BCM_FAILURE(rv)) { 3872 return rv; 3873 } 3874 3875 if (max_size == 0) { 3876 *list_size = flow_group_int_info.num_tracking_params; 3877 return BCM_E_NONE; 3878 } 3879 3880 if (flow_group_int_info.num_tracking_params > max_size) { 3881 *list_size = max_size; 3882 } else { 3883 *list_size = flow_group_int_info.num_tracking_params; 3884 } 3885 3886 sal_memcpy(tracking_params_list, flow_group_int_info.tracking_params, 3887 sizeof(bcm_flowtracker_tracking_param_info_t) * (*list_size)); 3888 3889 return BCM_E_NONE; 3890 } 3891 3892 /* 3893 * Function: 3894 * _bcm_th_ft_flow_group_export_trigger_set 3895 * Purpose: 3896 * Set Export trigger and Inform FT EAPP of the change 3897 * flow group using export trigger set. 3898 * Parameters: 3899 * unit - (IN) BCM device number 3900 * id - (IN) Flow group Id 3901 * export_trigger_info - (IN) Export trigger 3902 * Returns: 3903 * BCM_E_XXX - BCM error code. 3904 */ 3905 int _bcm_th_ft_flow_group_export_trigger_set(int unit, 3906 bcm_flowtracker_group_t id, 3907 bcm_flowtracker_export_trigger_info_t *export_trigger_info) 3908 { 3909 _bcm_int_ft_flow_group_info_t flow_group_int_info; 3910 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 3911 int rv = BCM_E_NONE; 3912 3913 if (ft_info == NULL) { 3914 return BCM_E_INIT; 3915 } 3916 3917 if (ft_info->cfg_mode < SHR_FT_CFG_MODE_V2) { 3918 return BCM_E_CONFIG; 3919 } 3920 3921 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, id); 3922 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, id); 3923 if (BCM_E_EXISTS != rv) { 3924 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 3925 (BSL_META_U(unit, 3926 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 3927 unit, id)); 3928 return (BCM_E_NOT_FOUND); 3929 } 3930 3931 /* 3932 * Get flow group info with the ID from the 3933 * flow group list 3934 */ 3935 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 3936 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, id, 3937 &flow_group_int_info); 3938 3939 /* If not found, return BCM_E_NOT_FOUND */ 3940 if (BCM_FAILURE(rv)) { 3941 return rv; 3942 } 3943 3944 flow_group_int_info.export_trigger = 0; 3945 if (BCM_FLOWTRACKER_TRIGGER_GET(*export_trigger_info, 3946 bcmFlowtrackerExportTriggerTimer)) { 3947 flow_group_int_info.export_trigger |= SHR_FT_EXPORT_TRIGGER_PERIODIC; 3948 } 3949 3950 if (BCM_FLOWTRACKER_TRIGGER_GET(*export_trigger_info, 3951 bcmFlowtrackerExportTriggerNewLearn)) { 3952 if (ft_info->uc_features & SHR_FT_UC_FEATURE_EXPORT_TRIGGER_NEW_LEARN) { 3953 flow_group_int_info.export_trigger |= SHR_FT_EXPORT_TRIGGER_NEW_LEARN; 3954 } else { 3955 return BCM_E_UNAVAIL; 3956 } 3957 } 3958 3959 if (BCM_FLOWTRACKER_TRIGGER_GET(*export_trigger_info, 3960 bcmFlowtrackerExportTriggerAgeOut)) { 3961 if (ft_info->uc_features & SHR_FT_UC_FEATURE_EXPORT_TRIGGER_AGE_OUT) { 3962 flow_group_int_info.export_trigger |= SHR_FT_EXPORT_TRIGGER_AGE_OUT; 3963 } else { 3964 return BCM_E_UNAVAIL; 3965 } 3966 } 3967 3968 if (BCM_FLOWTRACKER_TRIGGER_GET(*export_trigger_info, 3969 bcmFlowtrackerExportTriggerDrop)) { 3970 if ((ft_info->uc_features & SHR_FT_UC_FEATURE_EXPORT_TRIGGER_DROP) && 3971 (ft_info->flags & BCM_INT_FT_INFO_FLAGS_DROP_MONITOR)) { 3972 flow_group_int_info.export_trigger |= SHR_FT_EXPORT_TRIGGER_DROP; 3973 } else { 3974 return BCM_E_UNAVAIL; 3975 } 3976 } 3977 3978 /* 3979 * Inform FT EAPP of the change in the flow group 3980 * info using flow group export trigger set. 3981 */ 3982 rv = _bcm_xgs5_ft_eapp_send_flow_group_update_msg(unit, id, 3983 SHR_FT_GROUP_UPDATE_EXPORT_TRIGGERS, 3984 flow_group_int_info.export_trigger); 3985 if (BCM_FAILURE(rv)) { 3986 return rv; 3987 } 3988 3989 rv = _bcm_xgs5_ft_flow_group_list_flow_group_modify(unit, id, 3990 &flow_group_int_info); 3991 BCM_IF_ERROR_RETURN(rv); 3992 3993 return BCM_E_NONE; 3994 } 3995 3996 /* 3997 * Function: 3998 * _bcm_th_ft_flow_group_export_trigger_get 3999 * Purpose: 4000 * Set Export trigger and Inform FT EAPP of the change 4001 * flow group using export trigger set. 4002 * Parameters: 4003 * unit - (IN) BCM device number 4004 * id - (IN) Flow group Id 4005 * export_trigger_info - (OUT) Export trigger 4006 * Returns: 4007 * BCM_E_XXX - BCM error code. 4008 */ 4009 int _bcm_th_ft_flow_group_export_trigger_get(int unit, 4010 bcm_flowtracker_group_t id, 4011 bcm_flowtracker_export_trigger_info_t *export_trigger_info) 4012 { 4013 _bcm_int_ft_flow_group_info_t flow_group_int_info; 4014 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 4015 int rv = BCM_E_NONE; 4016 4017 if (ft_info == NULL) { 4018 return BCM_E_INIT; 4019 } 4020 4021 if (ft_info->cfg_mode < SHR_FT_CFG_MODE_V2) { 4022 return BCM_E_CONFIG; 4023 } 4024 4025 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, id); 4026 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, id); 4027 if (BCM_E_EXISTS != rv) { 4028 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 4029 (BSL_META_U(unit, 4030 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 4031 unit, id)); 4032 return (BCM_E_NOT_FOUND); 4033 } 4034 4035 /* 4036 * Get flow group info with the ID from the 4037 * flow group list 4038 */ 4039 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 4040 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, id, 4041 &flow_group_int_info); 4042 4043 /* If not found, return BCM_E_NOT_FOUND */ 4044 if (BCM_FAILURE(rv)) { 4045 return rv; 4046 } 4047 4048 if (flow_group_int_info.export_trigger & SHR_FT_EXPORT_TRIGGER_PERIODIC) { 4049 BCM_FLOWTRACKER_TRIGGER_SET(*export_trigger_info, 4050 bcmFlowtrackerExportTriggerTimer); 4051 } 4052 4053 if (flow_group_int_info.export_trigger & SHR_FT_EXPORT_TRIGGER_NEW_LEARN) { 4054 BCM_FLOWTRACKER_TRIGGER_SET(*export_trigger_info, 4055 bcmFlowtrackerExportTriggerNewLearn); 4056 } 4057 4058 if (flow_group_int_info.export_trigger & SHR_FT_EXPORT_TRIGGER_AGE_OUT) { 4059 BCM_FLOWTRACKER_TRIGGER_SET(*export_trigger_info, 4060 bcmFlowtrackerExportTriggerAgeOut); 4061 } 4062 4063 if (flow_group_int_info.export_trigger & SHR_FT_EXPORT_TRIGGER_DROP) { 4064 BCM_FLOWTRACKER_TRIGGER_SET(*export_trigger_info, 4065 bcmFlowtrackerExportTriggerDrop); 4066 } 4067 4068 return BCM_E_NONE; 4069 } 4070 4071 /* 4072 * Function: 4073 * _bcm_th_ft_flow_group_flow_count_get 4074 * Purpose: 4075 * Get the number of flows learnt in the flow group 4076 * Parameters: 4077 * unit - (IN) BCM device number 4078 * id - (IN) Flow group Id 4079 * flow_count - (OUT) Number of flows learnt 4080 * Returns: 4081 * BCM_E_XXX - BCM error code. 4082 * Notes: In Case of TH/TH2/TH3/TD3A0 flow count is retreived from emb app. 4083 * where as in case of maverick2 flow count comes from hardware. 4084 */ 4085 int _bcm_th_ft_flow_group_flow_count_get(int unit, 4086 bcm_flowtracker_group_t id, 4087 uint32 *flow_count) 4088 { 4089 _bcm_int_ft_flow_group_info_t flow_group_int_info; 4090 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 4091 int rv = BCM_E_NONE; 4092 4093 if (ft_info == NULL) { 4094 return BCM_E_INIT; 4095 } 4096 4097 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, id); 4098 if (BCM_E_EXISTS != rv) { 4099 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 4100 (BSL_META_U(unit, 4101 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 4102 unit, id)); 4103 return (BCM_E_NOT_FOUND); 4104 } 4105 4106 /* Get flow group info with the ID from the 4107 * flow group list 4108 */ 4109 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 4110 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, id, 4111 &flow_group_int_info); 4112 4113 4114 /* If not found, return BCM_E_NOT_FOUND */ 4115 if (BCM_FAILURE(rv)) { 4116 return rv; 4117 } 4118 4119 /* Get the flow count from FT EAPP using 4120 * flow_group get msg. 4121 */ 4122 rv = _bcm_xgs5_ft_eapp_send_flow_group_get_msg(unit, id, flow_count); 4123 4124 /* Return the failure if any failure */ 4125 if (BCM_FAILURE(rv)) { 4126 return rv; 4127 } 4128 4129 #if defined(BCM_MAVERICK2_SUPPORT) 4130 if (soc_feature(unit, soc_feature_mv2_style_flowtracker)) { 4131 rv = _bcm_mv2_flowtracker_flow_group_flow_count_get(unit, id, 4132 flow_count); 4133 if (BCM_FAILURE(rv)) { 4134 return rv; 4135 } 4136 } 4137 #endif /* BCM_MAVERICK2_SUPPORT */ 4138 4139 return BCM_E_NONE; 4140 } 4141 4142 /* 4143 * Function: 4144 * _bcm_th_ft_flow_group_destroy 4145 * Purpose: 4146 * Destroy a flowtracker flow group 4147 * Parameters: 4148 * unit - (IN) BCM device number 4149 * id - (IN) Flow group Id 4150 * Returns: 4151 * BCM_E_XXX - BCM error code. 4152 */ 4153 int _bcm_th_ft_flow_group_destroy(int unit, 4154 bcm_flowtracker_group_t id) 4155 { 4156 int rv = BCM_E_NONE; 4157 _bcm_int_ft_flow_group_info_t flow_group_int_info; 4158 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 4159 _bcm_int_ft_flow_group_info_t *flow_group_list = ft_flow_group_info_list[unit]; 4160 _bcm_int_ft_flow_group_info_t *group = NULL; 4161 int i, j, em_group_id_map_status = 0; 4162 4163 if (ft_info == NULL) { 4164 return BCM_E_INIT; 4165 } 4166 4167 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, id); 4168 if (BCM_E_EXISTS != rv) { 4169 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 4170 (BSL_META_U(unit, 4171 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 4172 unit, id)); 4173 return (BCM_E_NOT_FOUND); 4174 } 4175 4176 4177 /* Get flow group info with the ID from the 4178 * flow group list 4179 */ 4180 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 4181 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, id, 4182 &flow_group_int_info); 4183 BCM_IF_ERROR_RETURN(rv); 4184 4185 if (ft_info->elph_mode == TRUE && flow_group_int_info.elph_profile_id != 0) { 4186 /* Elephant profile must be detached prior to group delete */ 4187 return BCM_E_CONFIG; 4188 } 4189 if (flow_group_int_info.num_actions != 0) { 4190 /* Actions must be unset prior to group delete */ 4191 return BCM_E_CONFIG; 4192 } 4193 4194 /* Collector and export profile must be detached prior to destroy */ 4195 if (ft_info->cfg_mode >= SHR_FT_CFG_MODE_V2) { 4196 if ((flow_group_int_info.collector_id != BCM_INT_COLLECTOR_INVALID_COLLECTOR_ID) || 4197 (flow_group_int_info.export_profile_id != BCM_INT_COLLECTOR_INVALID_EXPORT_PROFILE_ID)) { 4198 return BCM_E_CONFIG; 4199 } 4200 } 4201 4202 /* Delete the flow group from the flow group list with 4203 * given ID. 4204 */ 4205 rv = _bcm_xgs5_ft_flow_group_list_flow_group_delete(unit, id); 4206 /* If not found in the list, return BCM_E_NOT_FOUND */ 4207 if (BCM_FAILURE(rv)) { 4208 return rv; 4209 } 4210 4211 /* Else inform FT EAPP of deleted flow group */ 4212 rv = _bcm_xgs5_ft_eapp_send_flow_group_delete_msg(unit, id); 4213 if (BCM_FAILURE(rv)) { 4214 return rv; 4215 } 4216 4217 /* Free up the ID from the pool */ 4218 BCM_IF_ERROR_RETURN(shr_idxres_list_free(ft_info->flow_group_pool, id)); 4219 4220 if (ft_info->default_grp_id == id) { 4221 ft_info->default_grp_id = 0; 4222 } 4223 4224 for (i = BCM_INT_FT_GROUP_START_ID; 4225 i < (ft_info->max_flow_groups + BCM_INT_FT_GROUP_START_ID); 4226 i++) { 4227 group = &(flow_group_list[i]); 4228 if ((group->flow_group_id != i) || (group->flow_group_id == id)) { 4229 continue; 4230 } 4231 for (j = 0; j < ft_info->num_pipes; ++j) { 4232 if (flow_group_int_info.field_group[j] == group->field_group[j]) { 4233 em_group_id_map_status = 1; 4234 } else { 4235 em_group_id_map_status = 0; 4236 } 4237 } 4238 if (em_group_id_map_status) { 4239 break; 4240 } 4241 } 4242 4243 if (!em_group_id_map_status) { 4244 for (i = 0; i < SHR_FT_MAX_EM_GROUPS; ++i) { 4245 if (ft_info->em_group_id_map[i][0] == flow_group_int_info.field_group[0]) { 4246 for (j = 0; j < ft_info->num_pipes; ++j) { 4247 ft_info->em_group_id_map[i][j] = -1; 4248 } 4249 BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_eapp_send_em_group_delete_msg(unit, 4250 i)); 4251 break; 4252 } 4253 } 4254 } 4255 return BCM_E_NONE; 4256 } 4257 4258 /* 4259 * Function: 4260 * _bcm_th_ft_group_clear 4261 * Purpose: 4262 * Clear a flow group's flow entries. 4263 * Parameters: 4264 * unit - (IN) BCM device number 4265 * id - (IN) Flow group Id 4266 * flags - (IN) Clear params 4267 * Returns: 4268 * BCM_E_XXX - BCM error code. 4269 */ 4270 int _bcm_th_ft_group_clear(int unit, 4271 bcm_flowtracker_group_t id, 4272 uint32 flags) 4273 { 4274 _bcm_int_ft_flow_group_info_t flow_group_int_info; 4275 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 4276 uint32 int_flags; 4277 int rv = BCM_E_NONE; 4278 4279 if (ft_info == NULL) { 4280 return BCM_E_INIT; 4281 } 4282 4283 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, id); 4284 if (BCM_E_EXISTS != rv) { 4285 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 4286 (BSL_META_U(unit, 4287 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 4288 unit, id)); 4289 return (BCM_E_NOT_FOUND); 4290 } 4291 4292 /* Get flow group info with the ID from the 4293 * flow group list 4294 */ 4295 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 4296 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, id, 4297 &flow_group_int_info); 4298 if (BCM_FAILURE(rv)) { 4299 return rv; 4300 } 4301 4302 if (flags == BCM_FLOWTRACKER_GROUP_CLEAR_ALL) { 4303 int_flags = SHR_FT_GROUP_UPDATE_FLUSH; 4304 } else if (flags == BCM_FLOWTRACKER_GROUP_CLEAR_FLOW_DATA_ONLY) { 4305 int_flags = SHR_FT_GROUP_UPDATE_COUNTER_CLEAR; 4306 } else { 4307 return BCM_E_PARAM; 4308 } 4309 4310 /* Send the group clear msg to the app */ 4311 rv = _bcm_xgs5_ft_eapp_send_flow_group_update_msg(unit, id, int_flags, 0); 4312 return rv; 4313 } 4314 4315 /* 4316 * Function: 4317 * _bcm_th_ft_flow_group_collector_add 4318 * Purpose: 4319 * Associate flow group to a collector with an export template. 4320 * Parameters: 4321 * unit - (IN) BCM device number 4322 * flow_group_id - (IN) Flow group Id 4323 * collector_id - (IN) Collector Id 4324 * template_id - (IN) Template Id 4325 * Returns: 4326 * BCM_E_XXX - BCM error code. 4327 */ 4328 int 4329 _bcm_th_ft_flow_group_collector_add(int unit, 4330 bcm_flowtracker_group_t flow_group_id, 4331 bcm_flowtracker_collector_t collector_id, 4332 bcm_flowtracker_export_template_t template_id) 4333 { 4334 _bcm_int_ft_flow_group_info_t flow_group_int_info; 4335 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 4336 int rv = BCM_E_NONE; 4337 4338 if (ft_info == NULL) { 4339 return BCM_E_INIT; 4340 } 4341 4342 if (ft_info->cfg_mode != SHR_FT_CFG_MODE_V1) { 4343 /* API only supported in v1 flowtracker */ 4344 return BCM_E_UNAVAIL; 4345 } 4346 4347 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, flow_group_id); 4348 if (BCM_E_EXISTS != rv) { 4349 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 4350 (BSL_META_U(unit, 4351 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 4352 unit, flow_group_id)); 4353 return (BCM_E_NOT_FOUND); 4354 } 4355 4356 /* Verify if such a collector and template exists */ 4357 rv = shr_idxres_list_elem_state(ft_info->collector_pool, collector_id); 4358 if (BCM_E_EXISTS != rv) { 4359 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 4360 (BSL_META_U(unit, 4361 "FT(unit %d) Error: Collector (ID:%d) does not exist.\n"), 4362 unit, collector_id)); 4363 return (BCM_E_PARAM); 4364 } 4365 4366 rv = shr_idxres_list_elem_state(ft_info->template_pool, template_id); 4367 if (BCM_E_EXISTS != rv) { 4368 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 4369 (BSL_META_U(unit, 4370 "FT(unit %d) Error: Template (ID:%d) does not exist.\n"), 4371 unit, template_id)); 4372 return (BCM_E_PARAM); 4373 } 4374 4375 /* Get flow group info with the ID from the 4376 * flow group list 4377 */ 4378 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 4379 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, flow_group_id, 4380 &flow_group_int_info); 4381 4382 /* If not found, return BCM_E_NOT_FOUND */ 4383 if (BCM_FAILURE(rv)) { 4384 return rv; 4385 } 4386 4387 /* Send the collector ID and Template ID set msg to the FT EAPP */ 4388 rv = _bcm_xgs5_ft_eapp_send_flow_group_update_msg(unit, flow_group_id, 4389 SHR_FT_GROUP_UPDATE_COLLECTOR_TEMPLATE_SET, 4390 0); 4391 if (BCM_FAILURE(rv)) { 4392 return rv; 4393 } 4394 4395 /* Update the group info with the collector ID and 4396 * template ID. 4397 */ 4398 flow_group_int_info.collector_id = collector_id; 4399 flow_group_int_info.template_id = template_id; 4400 rv = _bcm_xgs5_ft_flow_group_list_flow_group_modify(unit, 4401 flow_group_id, 4402 &flow_group_int_info); 4403 if (BCM_FAILURE(rv)) { 4404 return rv; 4405 } 4406 4407 return BCM_E_NONE; 4408 } 4409 4410 /* 4411 * Function: 4412 * _bcm_th_ft_flow_group_collector_delete 4413 * Purpose: 4414 * Dis-associate flow group from a collector with an export template. 4415 * Parameters: 4416 * unit - (IN) BCM device number 4417 * flow_group_id - (IN) Flow group Id 4418 * collector_id - (IN) Collector Id 4419 * template_id - (IN) Template Id 4420 * Returns: 4421 * BCM_E_XXX - BCM error code. 4422 */ 4423 int _bcm_th_ft_flow_group_collector_delete( 4424 int unit, 4425 bcm_flowtracker_group_t flow_group_id, 4426 bcm_flowtracker_collector_t collector_id, 4427 bcm_flowtracker_export_template_t template_id) 4428 { 4429 _bcm_int_ft_flow_group_info_t flow_group_int_info; 4430 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 4431 int rv = BCM_E_NONE; 4432 4433 if (ft_info == NULL) { 4434 return BCM_E_INIT; 4435 } 4436 4437 if (ft_info->cfg_mode != SHR_FT_CFG_MODE_V1) { 4438 /* API only supported in v1 flowtracker */ 4439 return BCM_E_UNAVAIL; 4440 } 4441 4442 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, flow_group_id); 4443 if (BCM_E_EXISTS != rv) { 4444 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 4445 (BSL_META_U(unit, 4446 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 4447 unit, flow_group_id)); 4448 return (BCM_E_NOT_FOUND); 4449 } 4450 4451 /* Verify if such a collector and template exists */ 4452 rv = shr_idxres_list_elem_state(ft_info->collector_pool, collector_id); 4453 if (BCM_E_EXISTS != rv) { 4454 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 4455 (BSL_META_U(unit, 4456 "FT(unit %d) Error: Collector (ID:%d) does not exist.\n"), 4457 unit, collector_id)); 4458 return (BCM_E_PARAM); 4459 } 4460 4461 rv = shr_idxres_list_elem_state(ft_info->template_pool, template_id); 4462 if (BCM_E_EXISTS != rv) { 4463 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 4464 (BSL_META_U(unit, 4465 "FT(unit %d) Error: Template (ID:%d) does not exist.\n"), 4466 unit, template_id)); 4467 return (BCM_E_PARAM); 4468 } 4469 4470 /* Get flow group info with the ID from the 4471 * flow group list 4472 */ 4473 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 4474 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, flow_group_id, 4475 &flow_group_int_info); 4476 4477 /* If not found, return BCM_E_NOT_FOUND */ 4478 if (BCM_FAILURE(rv)) { 4479 return rv; 4480 } 4481 4482 /* Update the group info with collector ID and template ID 4483 * to invalid value (0). 4484 */ 4485 flow_group_int_info.collector_id = 0; 4486 flow_group_int_info.template_id = 0; 4487 rv = _bcm_xgs5_ft_flow_group_list_flow_group_modify(unit, 4488 flow_group_id, 4489 &flow_group_int_info); 4490 if (BCM_FAILURE(rv)) { 4491 return rv; 4492 } 4493 4494 /* Send the collector ID and Template ID unset msg to the FT EAPP */ 4495 rv = _bcm_xgs5_ft_eapp_send_flow_group_update_msg( 4496 unit, flow_group_id, 4497 SHR_FT_GROUP_UPDATE_COLLECTOR_TEMPLATE_UNSET, 4498 0); 4499 if (BCM_FAILURE(rv)) { 4500 return rv; 4501 } 4502 return BCM_E_NONE; 4503 } 4504 4505 /* 4506 * Function: 4507 * _bcm_th_ft_flow_group_collector_get_all 4508 * Purpose: 4509 * Get list of all collectors, templates attached to a flow group 4510 * Parameters: 4511 * unit - (IN) BCM device number 4512 * flow_group_id - (IN) Flow group Id 4513 * max_list_size - (IN) Size of the list arrays 4514 * list_of_collectors - (OUT) Collector list 4515 * list_of_templates - (OUT) Template list 4516 * list_size - (OUT) Number of elements in the lists 4517 * Returns: 4518 * BCM_E_XXX - BCM error code. 4519 */ 4520 int _bcm_th_ft_flow_group_collector_get_all( 4521 int unit, 4522 bcm_flowtracker_group_t flow_group_id, 4523 int max_list_size, 4524 bcm_flowtracker_collector_t *list_of_collectors, 4525 bcm_flowtracker_export_template_t *list_of_templates, 4526 int *list_size) 4527 { 4528 _bcm_int_ft_flow_group_info_t flow_group_int_info; 4529 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 4530 int rv = BCM_E_NONE; 4531 4532 if (ft_info == NULL) { 4533 return BCM_E_INIT; 4534 } 4535 4536 if (ft_info->cfg_mode != SHR_FT_CFG_MODE_V1) { 4537 /* API only supported in v1 flowtracker */ 4538 return BCM_E_UNAVAIL; 4539 } 4540 4541 /* If the max_size is non zero and list == NULL, return 4542 * BCM_E_PARAM. 4543 */ 4544 if ((max_list_size != 0) && 4545 (list_of_collectors == NULL || 4546 list_of_templates == NULL)) { 4547 return BCM_E_PARAM; 4548 } 4549 4550 /* Get flow group info with the ID from the 4551 * flow group list 4552 */ 4553 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 4554 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, flow_group_id, 4555 &flow_group_int_info); 4556 4557 /* If not found, return BCM_E_NOT_FOUND */ 4558 if (BCM_FAILURE(rv)) { 4559 return rv; 4560 } 4561 4562 /* If the max_size is 0, 4563 * then return the number of collectors and templates in 4564 * list_size. Currently we support only one collector and one template. 4565 */ 4566 if (max_list_size == 0) { 4567 if (flow_group_int_info.collector_id != 0 && 4568 flow_group_int_info.template_id != 0) { 4569 *list_size = 1; 4570 } else { 4571 *list_size = 0; 4572 } 4573 return BCM_E_NONE; 4574 } 4575 4576 4577 list_of_collectors[0] = flow_group_int_info.collector_id; 4578 list_of_templates[0] = flow_group_int_info.template_id; 4579 4580 *list_size = 1; 4581 4582 return BCM_E_NONE; 4583 } 4584 4585 /* 4586 * Function: 4587 * _bcm_th_ft_flow_group_collector_attach 4588 * Purpose: 4589 * Associate flow group to a collector with an export template. 4590 * Parameters: 4591 * unit - (IN) BCM device number 4592 * flow_group_id - (IN) Flow group Id 4593 * collector_id - (IN) Collector Id 4594 * template_id - (IN) Template Id 4595 * Returns: 4596 * BCM_E_XXX - BCM error code. 4597 */ 4598 int 4599 _bcm_th_ft_group_collector_attach(int unit, 4600 bcm_flowtracker_group_t flow_group_id, 4601 bcm_collector_t collector_id, 4602 int export_profile_id, 4603 bcm_flowtracker_export_template_t template_id) 4604 { 4605 _bcm_int_ft_flow_group_info_t flow_group_int_info; 4606 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 4607 bcm_collector_info_t collector_info; 4608 bcm_collector_export_profile_t export_profile_info; 4609 int coll_int_id, export_profile_int_id; 4610 int coll_ref_cnt = 0; 4611 int rv = BCM_E_NONE; 4612 4613 if (ft_info == NULL) { 4614 return BCM_E_INIT; 4615 } 4616 4617 if (ft_info->cfg_mode < SHR_FT_CFG_MODE_V2) { 4618 /* API not supported in v1 flowtracker */ 4619 return BCM_E_UNAVAIL; 4620 } 4621 4622 /* Verify if flow group exists */ 4623 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, flow_group_id); 4624 if (BCM_E_EXISTS != rv) { 4625 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 4626 (BSL_META_U(unit, 4627 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 4628 unit, flow_group_id)); 4629 return (BCM_E_NOT_FOUND); 4630 } 4631 4632 /* Get flow group info with the ID from the flow group list */ 4633 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 4634 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, flow_group_id, 4635 &flow_group_int_info); 4636 BCM_IF_ERROR_RETURN(rv); 4637 4638 /* Check if the flow group is already attached to a collector */ 4639 if (flow_group_int_info.collector_id != 4640 BCM_INT_COLLECTOR_INVALID_COLLECTOR_ID) { 4641 /* Only one colector can be attached to a group */ 4642 return BCM_E_RESOURCE; 4643 } 4644 4645 /* Get collector info */ 4646 bcm_collector_info_t_init(&collector_info); 4647 BCM_IF_ERROR_RETURN(bcm_esw_collector_get(unit, collector_id, &collector_info)); 4648 4649 /* Get export profile info */ 4650 bcm_collector_export_profile_t_init(&export_profile_info); 4651 BCM_IF_ERROR_RETURN( 4652 bcm_esw_collector_export_profile_get(unit, 4653 export_profile_id, 4654 &export_profile_info)); 4655 4656 /* Verify if template exists */ 4657 if (export_profile_info.wire_format == bcmCollectorWireFormatIpfix) { 4658 rv = shr_idxres_list_elem_state(ft_info->template_pool, template_id); 4659 if (BCM_E_EXISTS != rv) { 4660 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 4661 (BSL_META_U(unit, 4662 "FT(unit %d) Error: Template (ID:%d) does not exist.\n"), 4663 unit, template_id)); 4664 return (BCM_E_NOT_FOUND); 4665 } 4666 } 4667 4668 /* Validate the collector and export profile */ 4669 rv = _bcm_th_ft_collector_export_profile_validate(unit, &collector_info, 4670 &export_profile_info); 4671 BCM_IF_ERROR_RETURN(rv); 4672 4673 if (export_profile_info.wire_format == bcmCollectorWireFormatIpfix) { 4674 if (_bcm_esw_collector_check_user_is_other(unit, collector_id, _BCM_COLLECTOR_EXPORT_APP_FT_IPFIX)) { 4675 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 4676 (BSL_META_U(unit, 4677 "FT(unit %d) Error: Collector (ID:%d) is associated to another wire format.\n"), 4678 unit, collector_id)); 4679 return (BCM_E_CONFIG); 4680 } 4681 } else { 4682 if (_bcm_esw_collector_check_user_is_other(unit, collector_id, _BCM_COLLECTOR_EXPORT_APP_FT_PROTOBUF)) { 4683 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 4684 (BSL_META_U(unit, 4685 "FT(unit %d) Error: Collector (ID:%d) is associated to another wire format.\n"), 4686 unit, collector_id)); 4687 return (BCM_E_CONFIG); 4688 } 4689 } 4690 4691 if ((ft_info->uc_features & SHR_FT_UC_FEATURE_EXPORT_INTERVAL_CHANGE) && 4692 (export_profile_info.export_interval != BCM_COLLECTOR_EXPORT_INTERVAL_INVALID)) { 4693 coll_ref_cnt = _bcm_esw_collector_ref_count_get(unit, collector_id); 4694 if (coll_ref_cnt > 0) { 4695 /* If flowtracker is already using this collector, 4696 * verify if the export profile's interval is matching 4697 * already configured value. If not, throw error. 4698 * Export interval can be changed only when all collectors are detached. 4699 */ 4700 /* Multiply by 1000 to convert usecs to msecs */ 4701 if (export_profile_info.export_interval != (ft_info->export_interval * 1000)) { 4702 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 4703 (BSL_META_U(unit, 4704 "FT(unit %d) Error: Only one export interval is supported.\n"), 4705 unit)); 4706 return BCM_E_CONFIG; 4707 } 4708 } 4709 /* 0 is a special case in API. Do not validate. */ 4710 if (export_profile_info.export_interval != 0) { 4711 BCM_IF_ERROR_RETURN(_bcm_th_ft_export_interval_validate(unit, export_profile_info.export_interval)); 4712 } 4713 } 4714 4715 /* Check if this collector is already created */ 4716 rv = _bcm_xgs5_ft_v2_collector_list_collector_get(unit, collector_id, 4717 &coll_int_id); 4718 if (rv == BCM_E_NOT_FOUND) { 4719 4720 /* Allocate an internal ID */ 4721 rv = shr_idxres_list_alloc(ft_info->collector_pool, 4722 (shr_idxres_element_t *)(&coll_int_id)); 4723 BCM_IF_ERROR_RETURN(rv); 4724 4725 /* Add it to the list */ 4726 rv = _bcm_xgs5_ft_v2_collector_list_collector_add(unit, collector_id, 4727 coll_int_id); 4728 if (BCM_FAILURE(rv)) { 4729 BCM_IF_ERROR_RETURN(shr_idxres_list_free(ft_info->collector_pool, 4730 coll_int_id)); 4731 return rv; 4732 } 4733 4734 /* Check if this export profile is already created */ 4735 rv = _bcm_xgs5_ft_v2_collector_list_export_profile_get(unit, export_profile_id, 4736 &export_profile_int_id); 4737 if (rv == BCM_E_NOT_FOUND) { 4738 /* Allocate an internal ID */ 4739 rv = shr_idxres_list_alloc(ft_info->export_profile_pool, 4740 (shr_idxres_element_t *)(&export_profile_int_id)); 4741 if (rv != BCM_E_NONE) { 4742 rv = _bcm_xgs5_ft_v2_collector_list_collector_delete(unit, 4743 collector_id); 4744 BCM_IF_ERROR_RETURN(shr_idxres_list_free(ft_info->collector_pool, 4745 coll_int_id)); 4746 } 4747 4748 /* Add it to the list */ 4749 rv = _bcm_xgs5_ft_v2_collector_list_export_profile_add(unit, 4750 export_profile_id, 4751 export_profile_int_id); 4752 if (rv != BCM_E_NONE) { 4753 rv = _bcm_xgs5_ft_v2_collector_list_collector_delete(unit, 4754 collector_id); 4755 BCM_IF_ERROR_RETURN(shr_idxres_list_free(ft_info->collector_pool, 4756 coll_int_id)); 4757 } 4758 } else if (rv != BCM_E_NONE) { 4759 rv = _bcm_xgs5_ft_v2_collector_list_collector_delete(unit, 4760 collector_id); 4761 BCM_IF_ERROR_RETURN(shr_idxres_list_free(ft_info->collector_pool, 4762 coll_int_id)); 4763 } 4764 4765 /* Send collector create message to E-App */ 4766 rv = _bcm_xgs5_ft_eapp_send_collector_create_msg(unit, collector_id, 4767 export_profile_id); 4768 if (BCM_FAILURE(rv)) { 4769 BCM_IF_ERROR_RETURN( 4770 _bcm_xgs5_ft_v2_collector_list_collector_delete(unit, 4771 collector_id)); 4772 BCM_IF_ERROR_RETURN( 4773 _bcm_xgs5_ft_v2_collector_list_export_profile_delete(unit, 4774 export_profile_id)); 4775 4776 BCM_IF_ERROR_RETURN(shr_idxres_list_free(ft_info->collector_pool, 4777 coll_int_id)); 4778 BCM_IF_ERROR_RETURN(shr_idxres_list_free(ft_info->export_profile_pool, 4779 export_profile_int_id)); 4780 return rv; 4781 } 4782 } else if (rv == BCM_E_NONE) { 4783 /* Check if this export profile is already created */ 4784 rv = _bcm_xgs5_ft_v2_collector_list_export_profile_get(unit, export_profile_id, 4785 &export_profile_int_id); 4786 if (rv == BCM_E_NOT_FOUND) { 4787 /* Allocate an internal ID */ 4788 rv = shr_idxres_list_alloc(ft_info->export_profile_pool, 4789 (shr_idxres_element_t *)(&export_profile_int_id)); 4790 BCM_IF_ERROR_RETURN(rv); 4791 4792 /* Add it to the list */ 4793 rv = _bcm_xgs5_ft_v2_collector_list_export_profile_add(unit, 4794 export_profile_id, 4795 export_profile_int_id); 4796 BCM_IF_ERROR_RETURN(rv); 4797 4798 } else if (rv != BCM_E_NONE) { 4799 return rv; 4800 } 4801 } else { 4802 return rv; 4803 } 4804 4805 /* Send the collector ID and Template ID set msg to the FT EAPP */ 4806 rv = _bcm_xgs5_ft_eapp_send_flow_group_update_msg( 4807 unit, flow_group_id, 4808 SHR_FT_GROUP_UPDATE_COLLECTOR_TEMPLATE_SET, 0); 4809 BCM_IF_ERROR_RETURN(rv); 4810 4811 /* Update the group info with the collector ID and 4812 * template ID. 4813 */ 4814 flow_group_int_info.collector_id = collector_id; 4815 flow_group_int_info.export_profile_id = export_profile_id; 4816 flow_group_int_info.template_id = template_id; 4817 rv = _bcm_xgs5_ft_flow_group_list_flow_group_modify(unit, 4818 flow_group_id, 4819 &flow_group_int_info); 4820 BCM_IF_ERROR_RETURN(rv); 4821 4822 /* Increment the ref counts */ 4823 BCM_IF_ERROR_RETURN( 4824 _bcm_esw_collector_export_profile_ref_count_update(unit, 4825 export_profile_id, 4826 1)); 4827 BCM_IF_ERROR_RETURN(_bcm_esw_collector_ref_count_update(unit, 4828 collector_id, 1)); 4829 4830 if (export_profile_info.wire_format == bcmCollectorWireFormatIpfix) { 4831 BCM_IF_ERROR_RETURN(_bcm_esw_collector_user_update(unit, 4832 collector_id, _BCM_COLLECTOR_EXPORT_APP_FT_IPFIX)); 4833 } else { 4834 BCM_IF_ERROR_RETURN(_bcm_esw_collector_user_update(unit, 4835 collector_id, _BCM_COLLECTOR_EXPORT_APP_FT_PROTOBUF)); 4836 } 4837 4838 /* Multiply by 1000 to convert usecs to msecs */ 4839 if ((ft_info->uc_features & SHR_FT_UC_FEATURE_EXPORT_INTERVAL_CHANGE) 4840 && (export_profile_info.export_interval != (ft_info->export_interval * 1000)) 4841 && (export_profile_info.export_interval != BCM_COLLECTOR_EXPORT_INTERVAL_INVALID)) { 4842 /* Update the export interval and send a msg */ 4843 ft_info->export_interval = (export_profile_info.export_interval/1000); 4844 /* Send the export interval update msg to the FT EAPP */ 4845 rv = _bcm_xgs5_ft_eapp_send_export_interval_update_msg( 4846 unit, ft_info->export_interval); 4847 BCM_IF_ERROR_RETURN(rv); 4848 } 4849 4850 return BCM_E_NONE; 4851 } 4852 4853 /* 4854 * Function: 4855 * _bcm_th_ft_flow_group_collector_detach 4856 * Purpose: 4857 * Disassociate flow group from a collector and an export template. 4858 * Parameters: 4859 * unit - (IN) BCM device number 4860 * flow_group_id - (IN) Flow group Id 4861 * collector_id - (IN) Collector Id 4862 * template_id - (IN) Template Id 4863 * Returns: 4864 * BCM_E_XXX - BCM error code. 4865 */ 4866 int 4867 _bcm_th_ft_group_collector_detach(int unit, 4868 bcm_flowtracker_group_t flow_group_id, 4869 bcm_collector_t collector_id, 4870 int export_profile_id, 4871 bcm_flowtracker_export_template_t template_id) 4872 { 4873 bcm_collector_export_profile_t export_profile_info; 4874 _bcm_int_ft_flow_group_info_t flow_group_int_info; 4875 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 4876 int coll_int_id, export_profile_int_id; 4877 int in_use; 4878 int rv = BCM_E_NONE; 4879 4880 if (ft_info == NULL) { 4881 return BCM_E_INIT; 4882 } 4883 4884 if (ft_info->cfg_mode < SHR_FT_CFG_MODE_V2) { 4885 /* API not supported in v1 flowtracker */ 4886 return BCM_E_UNAVAIL; 4887 } 4888 4889 /* Verify if flow group exists */ 4890 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, flow_group_id); 4891 if (BCM_E_EXISTS != rv) { 4892 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 4893 (BSL_META_U(unit, 4894 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 4895 unit, flow_group_id)); 4896 return (BCM_E_NOT_FOUND); 4897 } 4898 4899 /* Check if the collector is created */ 4900 rv = _bcm_xgs5_ft_v2_collector_list_collector_get(unit, collector_id, 4901 &coll_int_id); 4902 BCM_IF_ERROR_RETURN(rv); 4903 4904 /* Check if the export profile is created */ 4905 rv = _bcm_xgs5_ft_v2_collector_list_export_profile_get(unit, export_profile_id, 4906 &export_profile_int_id); 4907 BCM_IF_ERROR_RETURN(rv); 4908 4909 /* Get export profile info */ 4910 bcm_collector_export_profile_t_init(&export_profile_info); 4911 BCM_IF_ERROR_RETURN( 4912 bcm_esw_collector_export_profile_get(unit, 4913 export_profile_id, 4914 &export_profile_info)); 4915 4916 /* Verify if template exists */ 4917 if (export_profile_info.wire_format == bcmCollectorWireFormatIpfix) { 4918 rv = shr_idxres_list_elem_state(ft_info->template_pool, template_id); 4919 if (BCM_E_EXISTS != rv) { 4920 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 4921 (BSL_META_U(unit, 4922 "FT(unit %d) Error: Template (ID:%d) does not exist.\n"), 4923 unit, template_id)); 4924 return (BCM_E_NOT_FOUND); 4925 } 4926 } 4927 4928 /* Get flow group info with the ID from the flow group list */ 4929 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 4930 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, flow_group_id, 4931 &flow_group_int_info); 4932 BCM_IF_ERROR_RETURN(rv); 4933 4934 /* Check if this collector & export_profile is attached to the flow group */ 4935 if ((flow_group_int_info.collector_id != collector_id) || 4936 (flow_group_int_info.export_profile_id != export_profile_id)) { 4937 return BCM_E_PARAM; 4938 } 4939 4940 /* Send the collector ID and Template ID unset msg to the FT EAPP */ 4941 rv = _bcm_xgs5_ft_eapp_send_flow_group_update_msg( 4942 unit, flow_group_id, 4943 SHR_FT_GROUP_UPDATE_COLLECTOR_TEMPLATE_UNSET, 4944 0); 4945 BCM_IF_ERROR_RETURN(rv); 4946 4947 /* Update the group info with the collector ID and 4948 * template ID. 4949 */ 4950 flow_group_int_info.collector_id = BCM_INT_COLLECTOR_INVALID_COLLECTOR_ID; 4951 flow_group_int_info.export_profile_id = BCM_INT_COLLECTOR_INVALID_EXPORT_PROFILE_ID; 4952 flow_group_int_info.template_id = 0; 4953 rv = _bcm_xgs5_ft_flow_group_list_flow_group_modify(unit, 4954 flow_group_id, 4955 &flow_group_int_info); 4956 BCM_IF_ERROR_RETURN(rv); 4957 4958 /* Check if the collector is in use */ 4959 _bcm_xgs5_ft_v2_collector_list_collector_in_use(unit, collector_id, &in_use); 4960 if (!in_use) { 4961 /* Collector is not in use, delete it and decrement the ref_count */ 4962 rv = _bcm_xgs5_ft_eapp_send_collector_delete_msg(unit, collector_id); 4963 BCM_IF_ERROR_RETURN(rv); 4964 4965 rv = _bcm_xgs5_ft_v2_collector_list_collector_delete(unit, collector_id); 4966 BCM_IF_ERROR_RETURN(rv); 4967 4968 BCM_IF_ERROR_RETURN(shr_idxres_list_free(ft_info->collector_pool, 4969 coll_int_id)); 4970 } 4971 4972 /* Check if the collector is in use */ 4973 _bcm_xgs5_ft_v2_collector_list_export_profile_in_use(unit, export_profile_id, 4974 &in_use); 4975 if (!in_use) { 4976 rv = _bcm_xgs5_ft_v2_collector_list_export_profile_delete(unit, 4977 export_profile_id); 4978 BCM_IF_ERROR_RETURN(rv); 4979 4980 BCM_IF_ERROR_RETURN(shr_idxres_list_free(ft_info->export_profile_pool, 4981 export_profile_int_id)); 4982 } 4983 4984 /* Decrement the ref counts */ 4985 rv = _bcm_esw_collector_export_profile_ref_count_update(unit, 4986 export_profile_id, 4987 -1); 4988 BCM_IF_ERROR_RETURN(rv); 4989 4990 rv = _bcm_esw_collector_ref_count_update(unit, 4991 collector_id, 4992 -1); 4993 4994 BCM_IF_ERROR_RETURN(rv); 4995 4996 return BCM_E_NONE; 4997 } 4998 4999 /* 5000 * Function: 5001 * _bcm_th_ft_group_collector_attach_get_all 5002 * Purpose: 5003 * Get the list of collectors and templates associated with the flow group 5004 * Parameters: 5005 * unit - (IN) BCM device number 5006 * flow_group_id - (IN) Flow group Id 5007 * max_list_size - (IN) Size of the list arrays 5008 * list_of_collectors - (OUT) Collector list 5009 * list_of_templates - (OUT) Template list 5010 * list_size - (OUT) Number of elements in the lists 5011 * Returns: 5012 * BCM_E_XXX - BCM error code. 5013 */ 5014 int _bcm_th_ft_group_collector_attach_get_all( 5015 int unit, 5016 bcm_flowtracker_group_t flow_group_id, 5017 int max_list_size, 5018 bcm_collector_t *list_of_collectors, 5019 int *list_of_export_profile_ids, 5020 bcm_flowtracker_export_template_t *list_of_templates, 5021 int *list_size) 5022 { 5023 _bcm_int_ft_flow_group_info_t flow_group_int_info; 5024 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 5025 int rv = BCM_E_NONE; 5026 5027 if (ft_info == NULL) { 5028 return BCM_E_INIT; 5029 } 5030 5031 if (ft_info->cfg_mode < SHR_FT_CFG_MODE_V2) { 5032 /* API not supported in v1 flowtracker */ 5033 return BCM_E_UNAVAIL; 5034 } 5035 5036 /* Verify if flow group exists */ 5037 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, flow_group_id); 5038 if (BCM_E_EXISTS != rv) { 5039 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 5040 (BSL_META_U(unit, 5041 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 5042 unit, flow_group_id)); 5043 return (BCM_E_NOT_FOUND); 5044 } 5045 5046 /* Get flow group info with the ID from the flow group list */ 5047 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 5048 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, flow_group_id, 5049 &flow_group_int_info); 5050 BCM_IF_ERROR_RETURN(rv); 5051 5052 /* max_list_size == 0, just populate list_size and return */ 5053 if (max_list_size == 0) { 5054 if (flow_group_int_info.collector_id == 5055 BCM_INT_COLLECTOR_INVALID_COLLECTOR_ID) { 5056 *list_size = 0; 5057 } else { 5058 /* Only one collector and template can be attached to a group */ 5059 *list_size = 1; 5060 } 5061 return BCM_E_NONE; 5062 } 5063 5064 /* Get the collector info */ 5065 5066 *list_size = 1; 5067 list_of_templates[0] = flow_group_int_info.template_id; 5068 list_of_collectors[0] = flow_group_int_info.collector_id; 5069 list_of_export_profile_ids[0] = flow_group_int_info.export_profile_id; 5070 5071 return BCM_E_NONE; 5072 } 5073 5074 /* 5075 * Function: 5076 * _bcm_th_flowtracker_group_data_get 5077 * Purpose: 5078 * Get flow data for a given flow key within the given flow group. 5079 * Parameters: 5080 * unit - (IN) BCM device number 5081 * flow_group_id - (IN) Flow group Id 5082 * flow_key - (IN) Five tuple that constitutes a flow 5083 * flow_data - (OUT) Data associated with the flow key 5084 * Returns: 5085 * BCM_E_XXX - BCM error code. 5086 */ 5087 int _bcm_th_ft_group_data_get(int unit, 5088 bcm_flowtracker_group_t flow_group_id, 5089 bcm_flowtracker_flow_key_t *flow_key, 5090 bcm_flowtracker_flow_data_t *flow_data) 5091 { 5092 _bcm_int_ft_flow_group_info_t flow_group_int_info; 5093 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 5094 int rv = BCM_E_NONE; 5095 5096 if (ft_info == NULL) { 5097 return BCM_E_INIT; 5098 } 5099 5100 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, flow_group_id); 5101 if (BCM_E_EXISTS != rv) { 5102 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 5103 (BSL_META_U(unit, 5104 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 5105 unit, flow_group_id)); 5106 return (BCM_E_NOT_FOUND); 5107 } 5108 5109 /* Get flow group info with the ID from the 5110 * flow group list 5111 */ 5112 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 5113 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, flow_group_id, 5114 &flow_group_int_info); 5115 if (BCM_FAILURE(rv)) { 5116 return rv; 5117 } 5118 5119 /* Get the flow data from the EApp */ 5120 rv = _bcm_xgs5_ft_eapp_send_flow_group_flow_data_get_msg(unit, flow_group_id, 5121 flow_key, flow_data); 5122 return rv; 5123 } 5124 5125 /* 5126 * Function: 5127 * bcm_th_ft_group_actions_conflict_check 5128 * Purpose: 5129 * Set list of actions on a flow group. 5130 * Parameters: 5131 * num_actions - (IN) Number of actions in the list. 5132 * action_list - (IN) Action list. 5133 * Returns: 5134 * BCM_E_XXX - BCM error code. 5135 */ 5136 STATIC int 5137 _bcm_th_ft_group_actions_conflict_check( 5138 int num_actions, 5139 bcm_flowtracker_group_action_info_t *action_list) 5140 { 5141 int i, j; 5142 bcm_flowtracker_group_action_t action_a, action_b; 5143 5144 for (i = 0; i < num_actions; i++) { 5145 action_a = action_list[i].action; 5146 5147 for (j = (i + 1); j < num_actions; j++) { 5148 action_b = action_list[j].action; 5149 5150 switch(action_a) { 5151 case bcmFlowtrackerGroupActionRpDropPrecedence: 5152 FT_ACTION_CONFLICT(action_b, bcmFlowtrackerGroupActionRpDropPrecedence); 5153 break; 5154 5155 case bcmFlowtrackerGroupActionYpDropPrecedence: 5156 FT_ACTION_CONFLICT(action_b, bcmFlowtrackerGroupActionYpDropPrecedence); 5157 break; 5158 5159 case bcmFlowtrackerGroupActionGpDropPrecedence: 5160 FT_ACTION_CONFLICT(action_b, bcmFlowtrackerGroupActionGpDropPrecedence); 5161 break; 5162 5163 case bcmFlowtrackerGroupActionUcastCosQNew: 5164 FT_ACTION_CONFLICT(action_b, bcmFlowtrackerGroupActionUcastCosQNew); 5165 FT_ACTION_CONFLICT(action_b, bcmFlowtrackerGroupActionPrioIntNew); 5166 break; 5167 5168 case bcmFlowtrackerGroupActionMcastCosQNew: 5169 FT_ACTION_CONFLICT(action_b, bcmFlowtrackerGroupActionMcastCosQNew); 5170 FT_ACTION_CONFLICT(action_b, bcmFlowtrackerGroupActionPrioIntNew); 5171 break; 5172 5173 case bcmFlowtrackerGroupActionPrioIntNew: 5174 FT_ACTION_CONFLICT(action_b, bcmFlowtrackerGroupActionPrioIntNew); 5175 FT_ACTION_CONFLICT(action_b, bcmFlowtrackerGroupActionUcastCosQNew); 5176 FT_ACTION_CONFLICT(action_b, bcmFlowtrackerGroupActionMcastCosQNew); 5177 break; 5178 5179 default: 5180 break; 5181 } 5182 } 5183 } 5184 return BCM_E_NONE; 5185 } 5186 5187 /* 5188 * Function: 5189 * _bcm_th_ft_group_actions_convert 5190 * Purpose: 5191 * Convert actions to internal representation 5192 * Parameters: 5193 * num_actions - (IN) Number of actions in the list. 5194 * action_list - (IN) Action list. 5195 * inum_actions - (OUT) Number of actions in the iaction_list. 5196 * iaction_list - (OUT) Action list in internal representation 5197 * Returns: 5198 * BCM_E_XXX - BCM error code. 5199 */ 5200 STATIC int 5201 _bcm_th_ft_group_actions_convert(int unit, int num_actions, 5202 bcm_flowtracker_group_action_info_t *action_list, 5203 int *inum_actions, 5204 _bcm_int_ft_action_info_t *iaction_list, 5205 int *inum_qos_actions) 5206 { 5207 int i, j, k; 5208 int rv; 5209 int ucast_mcast = 0; 5210 int cosq; 5211 int non_qos_action = 0; 5212 bcm_module_t module; 5213 bcm_port_t port = 0; 5214 bcm_trunk_t trunk; 5215 int id; 5216 5217 for (i = 0, j = 0; i < num_actions; i++) { 5218 switch(action_list[i].action) { 5219 case bcmFlowtrackerGroupActionRpDropPrecedence: 5220 iaction_list[j].action = _bcmIntFtActionRpDropPrecedence; 5221 iaction_list[j].param0 = action_list[i].params.param0; 5222 j++; 5223 break; 5224 5225 case bcmFlowtrackerGroupActionYpDropPrecedence: 5226 iaction_list[j].action = _bcmIntFtActionYpDropPrecedence; 5227 iaction_list[j].param0 = action_list[i].params.param0; 5228 j++; 5229 break; 5230 5231 case bcmFlowtrackerGroupActionGpDropPrecedence: 5232 iaction_list[j].action = _bcmIntFtActionGpDropPrecedence; 5233 iaction_list[j].param0 = action_list[i].params.param0; 5234 j++; 5235 break; 5236 5237 case bcmFlowtrackerGroupActionUcastCosQNew: 5238 rv = _bcm_esw_flowtracker_ucast_cosq_resolve(unit, 5239 action_list[i].params.param0, 5240 &cosq); 5241 BCM_IF_ERROR_RETURN(rv); 5242 5243 /* Actions need to be programmed diffferently if both unicast 5244 * and multicast actions are present. Overwrite the multicast 5245 * action if it is present. 5246 */ 5247 for (k = 0; k < j; k++) { 5248 if (iaction_list[k].action == _bcmIntFtActionGpMcastCosQNew) { 5249 iaction_list[k].action = _bcmIntFtActionGpCosQNew; 5250 iaction_list[k].param0 = (iaction_list[k].param0 << 4) | cosq; 5251 ucast_mcast = 1; 5252 } 5253 5254 if (iaction_list[k].action == _bcmIntFtActionYpMcastCosQNew) { 5255 iaction_list[k].action = _bcmIntFtActionYpCosQNew; 5256 iaction_list[k].param0 = (iaction_list[k].param0 << 4) | cosq; 5257 ucast_mcast = 1; 5258 } 5259 5260 if (iaction_list[k].action == _bcmIntFtActionRpMcastCosQNew) { 5261 iaction_list[k].action = _bcmIntFtActionRpCosQNew; 5262 iaction_list[k].param0 = (iaction_list[k].param0 << 4) | cosq; 5263 ucast_mcast = 1; 5264 } 5265 } 5266 5267 if (ucast_mcast == 0) { /* Only unicast */ 5268 iaction_list[j].action = _bcmIntFtActionGpUcastCosQNew; 5269 iaction_list[j].param0 = cosq; 5270 j++; 5271 5272 iaction_list[j].action = _bcmIntFtActionYpUcastCosQNew; 5273 iaction_list[j].param0 = cosq; 5274 j++; 5275 5276 iaction_list[j].action = _bcmIntFtActionRpUcastCosQNew; 5277 iaction_list[j].param0 = cosq; 5278 j++; 5279 } 5280 break; 5281 5282 case bcmFlowtrackerGroupActionMcastCosQNew: 5283 rv = _bcm_esw_flowtracker_mcast_cosq_resolve(unit, 5284 action_list[i].params.param0, 5285 &cosq); 5286 BCM_IF_ERROR_RETURN(rv); 5287 5288 /* Actions need to be programmed diffferently if both unicast 5289 * and multicast actions are present. Overwrite the multicast 5290 * action if it is present. 5291 */ 5292 for (k = 0; k < j; k++) { 5293 if (iaction_list[k].action == _bcmIntFtActionGpUcastCosQNew) { 5294 iaction_list[k].action = _bcmIntFtActionGpCosQNew; 5295 iaction_list[k].param0 = (cosq << 4) | iaction_list[k].param0; 5296 ucast_mcast = 1; 5297 } 5298 5299 if (iaction_list[k].action == _bcmIntFtActionYpUcastCosQNew) { 5300 iaction_list[k].action = _bcmIntFtActionYpCosQNew; 5301 iaction_list[k].param0 = (cosq << 4) | iaction_list[k].param0; 5302 ucast_mcast = 1; 5303 } 5304 5305 if (iaction_list[k].action == _bcmIntFtActionRpUcastCosQNew) { 5306 iaction_list[k].action = _bcmIntFtActionRpCosQNew; 5307 iaction_list[k].param0 = (cosq << 4) | iaction_list[k].param0; 5308 ucast_mcast = 1; 5309 } 5310 } 5311 5312 if (ucast_mcast == 0) { /* Only multicast */ 5313 iaction_list[j].action = _bcmIntFtActionGpMcastCosQNew; 5314 iaction_list[j].param0 = cosq; 5315 j++; 5316 5317 iaction_list[j].action = _bcmIntFtActionYpMcastCosQNew; 5318 iaction_list[j].param0 = cosq; 5319 j++; 5320 5321 iaction_list[j].action = _bcmIntFtActionRpMcastCosQNew; 5322 iaction_list[j].param0 = cosq; 5323 j++; 5324 } 5325 break; 5326 5327 case bcmFlowtrackerGroupActionPrioIntNew: 5328 iaction_list[j].action = _bcmIntFtActionGpPrioIntNew; 5329 iaction_list[j].param0 = action_list[i].params.param0; 5330 j++; 5331 5332 iaction_list[j].action = _bcmIntFtActionYpPrioIntNew; 5333 iaction_list[j].param0 = action_list[i].params.param0; 5334 j++; 5335 5336 iaction_list[j].action = _bcmIntFtActionRpPrioIntNew; 5337 iaction_list[j].param0 = action_list[i].params.param0; 5338 j++; 5339 break; 5340 5341 case bcmFlowtrackerGroupActionFspReinject: 5342 if (BCM_GPORT_IS_COSQ(action_list[i].params.param0)) { 5343 rv = _bcm_esw_flowtracker_mcast_cosq_resolve(unit, 5344 action_list[i].params.param0, 5345 &cosq); 5346 BCM_IF_ERROR_RETURN(rv); 5347 iaction_list[j].param0 = cosq; 5348 } else { 5349 if (action_list[i].params.param0) { 5350 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, 5351 action_list[i].params.param0, 5352 &module, &port, &trunk, &id)); 5353 } 5354 if (((action_list[i].params.param0 == 0) || (port == 0)) && 5355 (action_list[i].params.param1 < NUM_CPU_COSQ(unit))) { 5356 iaction_list[j].param0 = action_list[i].params.param1; 5357 } else { 5358 return BCM_E_PARAM; 5359 } 5360 } 5361 5362 iaction_list[j].action = _bcmIntFtFspReinjectActionIntNew; 5363 j++; 5364 non_qos_action++; 5365 break; 5366 5367 case bcmFlowtrackerGroupActionDropMonitor: 5368 iaction_list[j].action = _bcmIntFtDropMonitorActionIntNew; 5369 j++; 5370 non_qos_action++; 5371 break; 5372 5373 default: 5374 return BCM_E_PARAM; 5375 } 5376 } 5377 5378 *inum_actions = j; 5379 *inum_qos_actions = j - non_qos_action; 5380 return BCM_E_NONE; 5381 } 5382 5383 /* 5384 * Function: 5385 * _bcm_th_ft_val_set 5386 * Purpose: 5387 * Write the width size of data from data to buf at offset. 5388 * Parameters: 5389 * data - (IN) Data to be written into buf 5390 * offset - (IN) Offset at which data has to be copied to p_fn_data 5391 * width - (IN) Size of the data to be written into p_fn_data 5392 * buf - (OUT) Out buffer 5393 * Returns: 5394 * BCM_E_XXX 5395 */ 5396 int 5397 _bcm_th_ft_val_set(uint32 *data, uint32 offset, uint32 width, uint32 *buf) 5398 { 5399 uint32 u32_mask; 5400 int idx, wp, bp, len; 5401 5402 wp = offset / 32; 5403 bp = offset & (32 - 1); 5404 idx = 0; 5405 5406 for (len = width; len > 0; len -= 32) { 5407 if (bp) { 5408 if (len < 32) { 5409 u32_mask = (1 << len) - 1; 5410 if ((data[idx] & ~u32_mask) != 0) { 5411 return (BCM_E_PARAM); 5412 } 5413 } else { 5414 u32_mask = 0xffffffff; 5415 } 5416 5417 buf[wp] &= ~(u32_mask << bp); 5418 buf[wp++] |= data[idx] << bp; 5419 buf[wp] &= ~(u32_mask >> (32 - bp)); 5420 buf[wp] |= data[idx] >> (32 - bp) & ((1 << bp) - 1); 5421 5422 } else { 5423 if (len < 32) { 5424 u32_mask = (1 << len) - 1; 5425 if ((data[idx] & ~u32_mask) != 0) { 5426 return (BCM_E_PARAM); 5427 } 5428 buf[wp] &= ~u32_mask; 5429 buf[wp++] |= data[idx]; 5430 } else { 5431 buf[wp++] = data[idx]; 5432 } 5433 } 5434 5435 idx++; 5436 } 5437 5438 return BCM_E_NONE; 5439 } 5440 5441 /* 5442 * Function: 5443 * _bcm_th_ft_actions_buf_set 5444 * Purpose: 5445 * Set action list to the specifid offsets in the buffer 5446 * Parameters: 5447 * num_actions - (IN) Number of actions in a_offset[] 5448 * a_offset - (IN) Action offset list 5449 * bufp - (OUT) Out buffer 5450 * Returns: 5451 * BCM_E_XXX - BCM error code. 5452 */ 5453 STATIC int 5454 _bcm_th_ft_actions_buf_set(int num_actions, 5455 _bcm_int_ft_action_offset_t *a_offset, uint32 *buf) 5456 { 5457 int i, j; 5458 uint32 offset; 5459 uint32 width; 5460 uint32 value; 5461 5462 for (i = 0; i < num_actions; i++) { 5463 for (j = 0; j < BCM_INT_FT_ACTION_MAX_PARTS; j++) { 5464 if (a_offset[i].width[j] > 0) { 5465 offset = a_offset[i].offset[j]; 5466 width = a_offset[i].width[j]; 5467 value = a_offset[i].value[j]; 5468 /* 5469 * COVERITY 5470 * 5471 * This flow takes care of the Out-of-bounds access issue 5472 * for data and mask. 5473 */ 5474 /* coverity[callee_ptr_arith : FALSE] */ 5475 BCM_IF_ERROR_RETURN(_bcm_th_ft_val_set(&value, offset, 5476 width, buf)); 5477 } 5478 } 5479 } 5480 return BCM_E_NONE; 5481 } 5482 5483 /* 5484 * Function: 5485 * _bcm_th_ft_group_qos_actions_install 5486 * Purpose: 5487 * Install list of action to the H/w 5488 * Parameters: 5489 * unit - (IN) BCM device number 5490 * num_actions - (IN) Number of actions in the action_list. 5491 * action_list - (IN) Action list to install 5492 * qp_idx - (OUT) QoS profile Index 5493 * Returns: 5494 * BCM_E_XXX - BCM error code. 5495 */ 5496 STATIC int 5497 _bcm_th_ft_group_qos_actions_install(int unit, int num_actions, 5498 _bcm_int_ft_action_info_t *action_list, 5499 uint32 *qp_idx) 5500 { 5501 int i; 5502 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 5503 _bcm_int_ft_action_offset_t a_offset[_bcmIntFtActionCount]; 5504 soc_mem_t mem; 5505 exact_match_qos_actions_profile_entry_t qos_prof_entry; 5506 void *entries[1]; 5507 uint32 *bufp = NULL; 5508 int pipe; 5509 int rv; 5510 5511 sal_memset(a_offset, 0, _bcmIntFtActionCount * 5512 sizeof(_bcm_int_ft_action_offset_t)); 5513 5514 /* Convert actions to H/w format */ 5515 for (i = 0; i < num_actions; i++) { 5516 switch(action_list[i].action) { 5517 case _bcmIntFtActionGpDropPrecedence: 5518 a_offset[i].offset[0] = 4; 5519 a_offset[i].width[0] = 2; 5520 a_offset[i].value[0] = action_list[i].param0; 5521 break; 5522 5523 case _bcmIntFtActionYpDropPrecedence: 5524 a_offset[i].offset[0] = 2; 5525 a_offset[i].width[0] = 2; 5526 a_offset[i].value[0] = action_list[i].param0; 5527 break; 5528 5529 case _bcmIntFtActionRpDropPrecedence: 5530 a_offset[i].offset[0] = 0; 5531 a_offset[i].width[0] = 2; 5532 a_offset[i].value[0] = action_list[i].param0; 5533 break; 5534 5535 case _bcmIntFtActionGpUcastCosQNew: 5536 a_offset[i].offset[0] = 38; 5537 a_offset[i].width[0] = 4; 5538 a_offset[i].value[0] = 8; 5539 5540 a_offset[i].offset[1] = 22; 5541 a_offset[i].width[1] = 4; 5542 a_offset[i].value[1] = action_list[i].param0; 5543 break; 5544 5545 case _bcmIntFtActionYpUcastCosQNew: 5546 a_offset[i].offset[0] = 34; 5547 a_offset[i].width[0] = 4; 5548 a_offset[i].value[0] = 8; 5549 5550 a_offset[i].offset[1] = 14; 5551 a_offset[i].width[1] = 4; 5552 a_offset[i].value[1] = action_list[i].param0; 5553 break; 5554 5555 case _bcmIntFtActionRpUcastCosQNew: 5556 a_offset[i].offset[0] = 30; 5557 a_offset[i].width[0] = 4; 5558 a_offset[i].value[0] = 8; 5559 5560 a_offset[i].offset[1] = 6; 5561 a_offset[i].width[1] = 4; 5562 a_offset[i].value[1] = action_list[i].param0; 5563 break; 5564 5565 case _bcmIntFtActionGpMcastCosQNew: 5566 a_offset[i].offset[0] = 38; 5567 a_offset[i].width[0] = 4; 5568 a_offset[i].value[0] = 9; 5569 5570 a_offset[i].offset[1] = 26; 5571 a_offset[i].width[1] = 4; 5572 a_offset[i].value[1] = action_list[i].param0; 5573 break; 5574 5575 case _bcmIntFtActionYpMcastCosQNew: 5576 a_offset[i].offset[0] = 34; 5577 a_offset[i].width[0] = 4; 5578 a_offset[i].value[0] = 9; 5579 5580 a_offset[i].offset[1] = 18; 5581 a_offset[i].width[1] = 4; 5582 a_offset[i].value[1] = action_list[i].param0; 5583 break; 5584 5585 case _bcmIntFtActionRpMcastCosQNew: 5586 a_offset[i].offset[0] = 30; 5587 a_offset[i].width[0] = 4; 5588 a_offset[i].value[0] = 9; 5589 5590 a_offset[i].offset[1] = 10; 5591 a_offset[i].width[1] = 4; 5592 a_offset[i].value[1] = action_list[i].param0; 5593 break; 5594 5595 case _bcmIntFtActionGpCosQNew: 5596 a_offset[i].offset[0] = 38; 5597 a_offset[i].width[0] = 4; 5598 a_offset[i].value[0] = 1; 5599 5600 a_offset[i].offset[1] = 22; 5601 a_offset[i].width[1] = 8; 5602 a_offset[i].value[1] = action_list[i].param0; 5603 break; 5604 5605 case _bcmIntFtActionYpCosQNew: 5606 a_offset[i].offset[0] = 34; 5607 a_offset[i].width[0] = 4; 5608 a_offset[i].value[0] = 1; 5609 5610 a_offset[i].offset[1] = 14; 5611 a_offset[i].width[1] = 8; 5612 a_offset[i].value[1] = action_list[i].param0; 5613 break; 5614 5615 case _bcmIntFtActionRpCosQNew: 5616 a_offset[i].offset[0] = 30; 5617 a_offset[i].width[0] = 4; 5618 a_offset[i].value[0] = 1; 5619 5620 a_offset[i].offset[1] = 6; 5621 a_offset[i].width[1] = 8; 5622 a_offset[i].value[1] = action_list[i].param0; 5623 break; 5624 5625 case _bcmIntFtActionGpPrioIntNew: 5626 a_offset[i].offset[0] = 38; 5627 a_offset[i].width[0] = 4; 5628 a_offset[i].value[0] = 5; 5629 5630 a_offset[i].offset[1] = 22; 5631 a_offset[i].width[1] = 3; 5632 a_offset[i].value[1] = action_list[i].param0; 5633 break; 5634 5635 case _bcmIntFtActionYpPrioIntNew: 5636 a_offset[i].offset[0] = 34; 5637 a_offset[i].width[0] = 4; 5638 a_offset[i].value[0] = 5; 5639 5640 a_offset[i].offset[1] = 14; 5641 a_offset[i].width[1] = 3; 5642 a_offset[i].value[1] = action_list[i].param0; 5643 break; 5644 5645 case _bcmIntFtActionRpPrioIntNew: 5646 a_offset[i].offset[0] = 30; 5647 a_offset[i].width[0] = 4; 5648 a_offset[i].value[0] = 5; 5649 5650 a_offset[i].offset[1] = 6; 5651 a_offset[i].width[1] = 3; 5652 a_offset[i].value[1] = action_list[i].param0; 5653 break; 5654 5655 default: 5656 return BCM_E_PARAM; 5657 } 5658 } 5659 5660 /* Write to H/w, num_actions == 0 implies a delete, don't write as there is 5661 * already a default empty entry 5662 */ 5663 if (num_actions != 0) { 5664 /* Initialize Qos Profile Actions Entry */ 5665 mem = EXACT_MATCH_QOS_ACTIONS_PROFILEm; 5666 bufp = (uint32 *)&qos_prof_entry; 5667 sal_memcpy(bufp, soc_mem_entry_null(unit, mem), 5668 soc_mem_entry_words(unit, mem) * sizeof(uint32)); 5669 5670 /* Set the actions in the buffer */ 5671 rv = _bcm_th_ft_actions_buf_set(num_actions, a_offset, bufp); 5672 BCM_IF_ERROR_RETURN(rv); 5673 5674 5675 entries[0] = bufp; 5676 for (pipe = 0; pipe < ft_info->num_pipes; pipe++) { 5677 /* Add entry to Qos Actions Profile Tables In Hardware in all pipes */ 5678 rv = soc_profile_mem_add(unit, 5679 ft_info->pipe_info[pipe].qos_profile_mem, 5680 entries, 1, qp_idx); 5681 BCM_IF_ERROR_RETURN(rv); 5682 } 5683 } else { 5684 /* Set the qos profile Id to the default entry */ 5685 *qp_idx = 0; 5686 } 5687 5688 return BCM_E_NONE; 5689 } 5690 5691 /* 5692 * Function: 5693 * _bcm_th_ft_group_qos_actions_remove 5694 * Purpose: 5695 * Remove the qos actions pointed by the profile ID 5696 * Parameters: 5697 * unit - (IN) BCM device number 5698 * qp_idx - (IN) QoS profile Index 5699 * Returns: 5700 * BCM_E_XXX - BCM error code. 5701 */ 5702 STATIC int 5703 _bcm_th_ft_group_qos_actions_remove(int unit, uint32 qp_idx) 5704 { 5705 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 5706 int pipe; 5707 int rv; 5708 5709 for (pipe = 0; pipe < ft_info->num_pipes; pipe++) { 5710 rv = soc_profile_mem_delete(unit, 5711 ft_info->pipe_info[pipe].qos_profile_mem, 5712 qp_idx); 5713 BCM_IF_ERROR_RETURN(rv); 5714 } 5715 5716 return BCM_E_NONE; 5717 } 5718 5719 /* 5720 * Function: 5721 * _bcm_th_ft_group_num_qos_actions_get 5722 * Purpose: 5723 * Number of existing qos actions pointed by the profile ID 5724 * Parameters: 5725 * unit - (IN) BCM device number 5726 * action_list - (IN) Action list. 5727 * Returns: 5728 * BCM_E_XXX - BCM error code. 5729 */ 5730 STATIC int 5731 _bcm_th_ft_group_num_qos_actions_get(int unit, 5732 _bcm_int_ft_flow_group_info_t *flow_group_int_info) 5733 { 5734 int i, num_qos_actions = 0; 5735 for (i = 0; i < flow_group_int_info->num_actions; i++) { 5736 switch(flow_group_int_info->action_list[i].action) { 5737 case bcmFlowtrackerGroupActionRpDropPrecedence: 5738 case bcmFlowtrackerGroupActionYpDropPrecedence: 5739 case bcmFlowtrackerGroupActionGpDropPrecedence: 5740 case bcmFlowtrackerGroupActionUcastCosQNew: 5741 case bcmFlowtrackerGroupActionMcastCosQNew: 5742 case bcmFlowtrackerGroupActionPrioIntNew: 5743 num_qos_actions++; 5744 break; 5745 5746 case bcmFlowtrackerGroupActionFspReinject: 5747 case bcmFlowtrackerGroupActionDropMonitor: 5748 break; 5749 default: 5750 return BCM_E_PARAM; 5751 } 5752 } 5753 return (num_qos_actions); 5754 } 5755 5756 /* 5757 * Function: 5758 * _bcm_th_ft_group_actions_set 5759 * Purpose: 5760 * Set list of actions on a flow group. 5761 * Parameters: 5762 * unit - (IN) BCM device number 5763 * flow_group_id - (IN) Flow group Id 5764 * flags - (IN) Flags 5765 * num_actions - (IN) Number of actions in the list. 5766 * action_list - (IN) Action list. 5767 * Returns: 5768 * BCM_E_XXX - BCM error code. 5769 */ 5770 int 5771 _bcm_th_ft_group_actions_set(int unit, 5772 bcm_flowtracker_group_t flow_group_id, 5773 uint32 flags, 5774 int num_actions, 5775 bcm_flowtracker_group_action_info_t *action_list) 5776 { 5777 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 5778 _bcm_int_ft_flow_group_info_t flow_group_int_info; 5779 int inum_actions, inum_qos_actions; 5780 _bcm_int_ft_action_info_t iaction_list[_bcmIntFtActionCount]; 5781 uint32 qp_idx = 0; 5782 int i; 5783 int prev_num_qos_actions = 0; 5784 shr_ft_msg_ctrl_group_actions_set_t action_msg; 5785 5786 int rv = BCM_E_NONE; 5787 5788 if (ft_info == NULL) { 5789 return BCM_E_INIT; 5790 } 5791 5792 for (i = 0; i < num_actions; i++) { 5793 switch(action_list[i].action) { 5794 case bcmFlowtrackerGroupActionRpDropPrecedence: 5795 case bcmFlowtrackerGroupActionYpDropPrecedence: 5796 case bcmFlowtrackerGroupActionGpDropPrecedence: 5797 case bcmFlowtrackerGroupActionUcastCosQNew: 5798 case bcmFlowtrackerGroupActionMcastCosQNew: 5799 case bcmFlowtrackerGroupActionPrioIntNew: 5800 if (ft_info->elph_mode != TRUE) { 5801 return BCM_E_INIT; 5802 } 5803 if (!(flags & BCM_FLOWTRACKER_GROUP_ACTIONS_SET_FLAGS_ELEPHANT_FLOWS)) { 5804 /* Actions can be applied only on elephant flows */ 5805 return BCM_E_PARAM; 5806 } 5807 break; 5808 case bcmFlowtrackerGroupActionFspReinject: 5809 if (!(ft_info->uc_features & SHR_FT_UC_FEATURE_FSP_REINJECT)) { 5810 /* Action applied only on FSP feature is enable */ 5811 return BCM_E_UNAVAIL; 5812 } 5813 break; 5814 case bcmFlowtrackerGroupActionDropMonitor: 5815 if (!(ft_info->uc_features & SHR_FT_UC_FEATURE_DROP_MONITOR) || 5816 !(ft_info->flags & BCM_INT_FT_INFO_FLAGS_DROP_MONITOR)) { 5817 /* Action applied only on Drop Monitor feature is enable */ 5818 return BCM_E_UNAVAIL; 5819 } 5820 break; 5821 default: 5822 return BCM_E_PARAM; 5823 } 5824 } 5825 5826 if ((num_actions != 0) && (action_list == NULL)) { 5827 return BCM_E_PARAM; 5828 } 5829 5830 /* Check if group exists */ 5831 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, flow_group_id); 5832 if (BCM_E_EXISTS != rv) { 5833 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 5834 (BSL_META_U(unit, 5835 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 5836 unit, flow_group_id)); 5837 return (BCM_E_NOT_FOUND); 5838 } 5839 5840 /* Get flow group info with the ID from the flow group list */ 5841 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 5842 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, flow_group_id, 5843 &flow_group_int_info); 5844 BCM_IF_ERROR_RETURN(rv); 5845 5846 if ((flow_group_int_info.num_actions == 0) && (num_actions == 0)) { 5847 /* Nothing installed, and a delete is requested num_actions == 0, 5848 * implies delete 5849 */ 5850 return BCM_E_PARAM; 5851 } 5852 5853 /* Check if the actions conflict */ 5854 rv = _bcm_th_ft_group_actions_conflict_check(num_actions, action_list); 5855 BCM_IF_ERROR_RETURN(rv); 5856 5857 /* Convert actions to internal representation */ 5858 rv = _bcm_th_ft_group_actions_convert(unit, num_actions, action_list, 5859 &inum_actions, iaction_list, 5860 &inum_qos_actions); 5861 BCM_IF_ERROR_RETURN(rv); 5862 5863 /* Install the actions to H/w */ 5864 if (inum_qos_actions) { 5865 BCM_IF_ERROR_RETURN(_bcm_th_ft_group_qos_actions_install(unit, inum_actions, 5866 iaction_list, &qp_idx)); 5867 } 5868 5869 /* Delete the old action if present */ 5870 prev_num_qos_actions = _bcm_th_ft_group_num_qos_actions_get(unit, 5871 &flow_group_int_info); 5872 if (flow_group_int_info.num_actions != 0) { 5873 if (prev_num_qos_actions) { 5874 rv = _bcm_th_ft_group_qos_actions_remove(unit, 5875 flow_group_int_info.qos_profile_id); 5876 BCM_IF_ERROR_RETURN(rv); 5877 flow_group_int_info.qos_profile_id = 0; 5878 } 5879 if (flow_group_int_info.num_actions > prev_num_qos_actions) { 5880 sal_memset(&action_msg, 0, 5881 sizeof(shr_ft_msg_ctrl_group_actions_set_t)); 5882 action_msg.group_idx = flow_group_id; 5883 rv = _bcm_xgs5_ft_eapp_send_group_actions_set_msg(unit, 5884 &action_msg); 5885 BCM_IF_ERROR_RETURN(rv); 5886 } 5887 sal_free(flow_group_int_info.action_list); 5888 flow_group_int_info.action_list = NULL; 5889 flow_group_int_info.num_actions = 0; 5890 } 5891 5892 /* Send the new qos profile id to Eapp */ 5893 if (inum_qos_actions) { 5894 rv = _bcm_xgs5_ft_eapp_send_flow_group_update_msg(unit, flow_group_id, 5895 SHR_FT_GROUP_UPDATE_ELPH_QOS_PROFILE_ID, 5896 qp_idx); 5897 BCM_IF_ERROR_RETURN(rv); 5898 } 5899 5900 /* Send FSP and Drop action to Eapp */ 5901 if (inum_actions != inum_qos_actions) { 5902 sal_memset(&action_msg, 0, 5903 sizeof(shr_ft_msg_ctrl_group_actions_set_t)); 5904 for (i = 0; i < num_actions; i++) { 5905 if (action_list[i].action == bcmFlowtrackerGroupActionDropMonitor) { 5906 action_msg.actions |= SHR_FT_GROUP_ACTION_DROP_MONITOR; 5907 } 5908 if (action_list[i].action == bcmFlowtrackerGroupActionFspReinject) { 5909 action_msg.actions |= SHR_FT_GROUP_ACTION_FSP_REINJECT; 5910 action_msg.fsp_cosq = iaction_list[i].param0; 5911 } 5912 } 5913 action_msg.group_idx = flow_group_id; 5914 rv = _bcm_xgs5_ft_eapp_send_group_actions_set_msg(unit, 5915 &action_msg); 5916 BCM_IF_ERROR_RETURN(rv); 5917 } 5918 5919 if (num_actions != 0) { 5920 flow_group_int_info.num_actions = num_actions; 5921 _BCM_FT_ALLOC(flow_group_int_info.action_list, 5922 _bcm_int_ft_group_action_info_t, 5923 num_actions * sizeof(_bcm_int_ft_group_action_info_t), 5924 "Group action list"); 5925 if (flow_group_int_info.action_list == NULL) { 5926 return BCM_E_MEMORY; 5927 } 5928 for (i = 0; i < num_actions; i++) { 5929 flow_group_int_info.action_list[i].action = action_list[i].action; 5930 if ((action_list[i].action == bcmFlowtrackerGroupActionDropMonitor) || 5931 (action_list[i].action == bcmFlowtrackerGroupActionFspReinject)) { 5932 flow_group_int_info.action_list[i].num_params = 2; 5933 flow_group_int_info.action_list[i].params[0] = 5934 action_list[i].params.param0; 5935 flow_group_int_info.action_list[i].params[1] = 5936 action_list[i].params.param1; 5937 } else { 5938 flow_group_int_info.action_list[i].num_params = 1; 5939 flow_group_int_info.action_list[i].params[0] = 5940 action_list[i].params.param0; 5941 } 5942 } 5943 flow_group_int_info.qos_profile_id = qp_idx; 5944 } 5945 rv = _bcm_xgs5_ft_flow_group_list_flow_group_modify(unit, flow_group_id, 5946 &flow_group_int_info); 5947 BCM_IF_ERROR_RETURN(rv); 5948 5949 return BCM_E_NONE; 5950 } 5951 5952 /* 5953 * Function: 5954 * _bcm_th_ft_group_actions_get 5955 * Purpose: 5956 * Get list of actions applied on a flow group. 5957 * Parameters: 5958 * unit - (IN) BCM device number 5959 * flow_group_id - (IN) Flow group Id 5960 * flags - (IN) Flags 5961 * max_actions - (IN) Maximum number of actions that can be 5962 * accomodated in the list. 5963 * action_list - (OUT) Action list. 5964 * num_actions - (OUT) Actual number of actions in the list 5965 * Returns: 5966 * BCM_E_XXX - BCM error code. 5967 */ 5968 int 5969 _bcm_th_ft_group_actions_get(int unit, 5970 bcm_flowtracker_group_t flow_group_id, 5971 uint32 flags, 5972 int max_actions, 5973 bcm_flowtracker_group_action_info_t *action_list, 5974 int *num_actions) 5975 { 5976 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 5977 _bcm_int_ft_flow_group_info_t flow_group_int_info; 5978 int rv = BCM_E_NONE; 5979 int i; 5980 5981 if (ft_info == NULL) { 5982 return BCM_E_INIT; 5983 } 5984 5985 /* If the max_actions is non zero and list == NULL, return 5986 * BCM_E_PARAM. 5987 */ 5988 if (max_actions != 0 && action_list == NULL) { 5989 return BCM_E_PARAM; 5990 } 5991 5992 /* Check if group exists */ 5993 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, flow_group_id); 5994 if (BCM_E_EXISTS != rv) { 5995 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 5996 (BSL_META_U(unit, 5997 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 5998 unit, flow_group_id)); 5999 return (BCM_E_NOT_FOUND); 6000 } 6001 6002 /* Get flow group info with the ID from the flow group list */ 6003 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 6004 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, flow_group_id, 6005 &flow_group_int_info); 6006 BCM_IF_ERROR_RETURN(rv); 6007 6008 if (max_actions == 0) { 6009 *num_actions = flow_group_int_info.num_actions; 6010 return BCM_E_NONE; 6011 } 6012 6013 if (flow_group_int_info.num_actions > max_actions) { 6014 *num_actions = max_actions; 6015 } else { 6016 *num_actions = flow_group_int_info.num_actions; 6017 } 6018 6019 for (i = 0; i < *num_actions; i++) { 6020 action_list[i].action = flow_group_int_info.action_list[i].action; 6021 if ((action_list[i].action == bcmFlowtrackerGroupActionDropMonitor) || 6022 (action_list[i].action == bcmFlowtrackerGroupActionFspReinject)) { 6023 action_list[i].params.param0 = 6024 flow_group_int_info.action_list[i].params[0]; 6025 action_list[i].params.param1 = 6026 flow_group_int_info.action_list[i].params[1]; 6027 } else { 6028 action_list[i].params.param0 = 6029 flow_group_int_info.action_list[i].params[0]; 6030 } 6031 } 6032 6033 return BCM_E_NONE; 6034 } 6035 /* 6036 * Function: 6037 * _bcm_th_ft_elephant_filter_validate 6038 * Purpose: 6039 * Validate elephant filter 6040 * Parameters: 6041 * demotion - (IN) 1 - Demotion filter, 6042 * 0 - Promotion filter 6043 * filter - (IN/OUT) Elephant filter 6044 * Returns: 6045 * BCM_E_XXX - BCM error code. 6046 */ 6047 STATIC int 6048 _bcm_th_ft_elephant_filter_validate(int unit, 6049 uint8 demotion, 6050 bcm_flowtracker_elephant_filter_t *filter) 6051 { 6052 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 6053 6054 if (filter->monitor_interval_usecs == 0) { 6055 /* No filter configured, add default filter if it is demotion, 6056 * promotion filters are optional 6057 */ 6058 if (demotion) { 6059 filter->monitor_interval_usecs = ft_info->scan_interval_usecs; 6060 COMPILER_64_SET(filter->size_threshold_bytes, 0, 1); 6061 } 6062 return BCM_E_NONE; 6063 } 6064 6065 if ((filter->monitor_interval_usecs % (ft_info->scan_interval_usecs)) != 0) { 6066 return BCM_E_PARAM; 6067 } 6068 6069 if ((filter->rate_low_threshold_kbits_sec % 6070 BCM_INT_FT_ELPH_RATE_THRESHOLD_STEP) != 0) { 6071 return BCM_E_PARAM; 6072 } 6073 6074 if ((filter->rate_high_threshold_kbits_sec % 6075 BCM_INT_FT_ELPH_RATE_THRESHOLD_STEP) != 0) { 6076 return BCM_E_PARAM; 6077 } 6078 return BCM_E_NONE; 6079 } 6080 6081 /* 6082 * Function: 6083 * _bcm_th_ft_elephant_profile_create 6084 * Purpose: 6085 * Create flowtracker elephant profile 6086 * Parameters: 6087 * unit - (IN) BCM device number 6088 * options - (IN) Elephant profile creation options. 6089 * profile - (IN) Elephant profile information 6090 * profile_id - (IN/OUT) Elephant profile id 6091 * Returns: 6092 * BCM_E_XXX - BCM error code. 6093 */ 6094 int _bcm_th_ft_elephant_profile_create( 6095 int unit, 6096 uint32 options, 6097 bcm_flowtracker_elephant_profile_info_t *profile, 6098 bcm_flowtracker_elephant_profile_t *profile_id) 6099 { 6100 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 6101 int rv = BCM_E_NONE; 6102 int i; 6103 6104 if (ft_info == NULL || ft_info->elph_mode != TRUE) { 6105 return BCM_E_INIT; 6106 } 6107 6108 /* Validate the profile */ 6109 if (profile->num_promotion_filters > BCM_FLOWTRACKER_ELEPHANT_MAX_PROMOTION_FILTERS) { 6110 return BCM_E_PARAM; 6111 } 6112 for (i = 0; i < profile->num_promotion_filters; i++) { 6113 BCM_IF_ERROR_RETURN( 6114 _bcm_th_ft_elephant_filter_validate(unit, 0, 6115 &(profile->promotion_filters[i]))); 6116 } 6117 BCM_IF_ERROR_RETURN( 6118 _bcm_th_ft_elephant_filter_validate(unit, 1, 6119 &(profile->demotion_filter))); 6120 6121 if (options & BCM_FLOWTRACKER_ELEPHANT_PROFILE_WITH_ID) { 6122 if (*profile_id > BCM_INT_FT_MAX_ELEPHANT_PROFILES) { 6123 return BCM_E_PARAM; 6124 } 6125 /* Reserve the requested Id */ 6126 rv = shr_idxres_list_reserve(ft_info->elph_profile_pool, 6127 *profile_id, *profile_id); 6128 if (BCM_FAILURE(rv)) { 6129 return ((rv == BCM_E_RESOURCE) ? BCM_E_EXISTS : rv); 6130 } 6131 } else { 6132 /* Allocate a free ID */ 6133 rv = shr_idxres_list_alloc(ft_info->elph_profile_pool, 6134 (shr_idxres_element_t *)profile_id); 6135 if (BCM_FAILURE(rv)) { 6136 return rv; 6137 } 6138 } 6139 6140 /* Add it to the list of elephant profiles */ 6141 rv = _bcm_xgs5_ft_elph_profile_list_add(unit, *profile_id, profile); 6142 if (BCM_FAILURE(rv)) { 6143 /* Free up the profile id allocated */ 6144 BCM_IF_ERROR_RETURN(shr_idxres_list_free(ft_info->elph_profile_pool, 6145 *profile_id)); 6146 return rv; 6147 } 6148 6149 /* Send elephant profile create msg */ 6150 rv = _bcm_xgs5_ft_eapp_send_elph_profile_create_msg(unit, *profile_id); 6151 if (BCM_FAILURE(rv)) { 6152 BCM_IF_ERROR_RETURN(shr_idxres_list_free(ft_info->elph_profile_pool, 6153 *profile_id)); 6154 BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_elph_profile_list_delete(unit, 6155 *profile_id)); 6156 return rv; 6157 } 6158 6159 return BCM_E_NONE; 6160 } 6161 6162 6163 /* 6164 * Function: 6165 * _bcm_th_ft_elephant_profile_destroy 6166 * Purpose: 6167 * Destroy a flowtracker elephant profile. 6168 * Parameters: 6169 * unit - (IN) BCM device number 6170 * profile_id - (IN/OUT) Elephant profile id 6171 * Returns: 6172 * BCM_E_XXX - BCM error code. 6173 */ 6174 int _bcm_th_ft_elephant_profile_destroy( 6175 int unit, 6176 bcm_flowtracker_elephant_profile_t profile_id) 6177 { 6178 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 6179 int rv = BCM_E_NONE; 6180 6181 if (ft_info == NULL || ft_info->elph_mode != TRUE) { 6182 return BCM_E_INIT; 6183 } 6184 6185 rv = shr_idxres_list_elem_state(ft_info->elph_profile_pool, profile_id); 6186 if (BCM_E_EXISTS != rv) { 6187 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 6188 (BSL_META_U(unit, 6189 "FT(unit %d) Error: Profile (ID:%d) does not exist.\n"), 6190 unit, profile_id)); 6191 return (BCM_E_NOT_FOUND); 6192 } 6193 6194 6195 /* Check if the elephant profile is in use by some flow group */ 6196 rv = _bcm_xgs5_ft_flow_group_list_elph_profile_in_use_check(unit, profile_id); 6197 if (rv == BCM_E_EXISTS) { 6198 /* One cannot delete an elephant profile without deleting the 6199 * association of the profile to the flow group. 6200 */ 6201 return BCM_E_CONFIG; 6202 } 6203 6204 6205 /* Delete the elephant profile from the list with 6206 * given ID. 6207 */ 6208 rv = _bcm_xgs5_ft_elph_profile_list_delete(unit, profile_id); 6209 /* If not found in the list, return BCM_E_NOT_FOUND */ 6210 if (BCM_FAILURE(rv)) { 6211 return rv; 6212 } 6213 6214 /* Inform FT EAPP of deleted profile */ 6215 rv = _bcm_xgs5_ft_eapp_send_collector_delete_msg(unit, profile_id); 6216 if (BCM_FAILURE(rv)) { 6217 return rv; 6218 } 6219 6220 /* Free up the ID from the pool */ 6221 BCM_IF_ERROR_RETURN(shr_idxres_list_free(ft_info->elph_profile_pool, 6222 profile_id)); 6223 6224 return BCM_E_NONE; 6225 } 6226 6227 /* 6228 * Function: 6229 * _bcm_th_ft_elephant_profile_get 6230 * Purpose: 6231 * Get flowtracker elephant profile information. 6232 * Parameters: 6233 * unit - (IN) BCM device number 6234 * profile_id - (IN) Elephant profile id 6235 * profile - (OUT) Elephant profile information 6236 * Returns: 6237 * BCM_E_XXX - BCM error code. 6238 */ 6239 int _bcm_th_ft_elephant_profile_get( 6240 int unit, 6241 bcm_flowtracker_elephant_profile_t profile_id, 6242 bcm_flowtracker_elephant_profile_info_t *profile) 6243 { 6244 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 6245 _bcm_int_ft_elph_profile_info_t profile_int_info; 6246 int rv = BCM_E_NONE; 6247 6248 if (ft_info == NULL || ft_info->elph_mode != TRUE) { 6249 return BCM_E_INIT; 6250 } 6251 6252 if (profile == NULL) { 6253 return BCM_E_PARAM; 6254 } 6255 6256 rv = shr_idxres_list_elem_state(ft_info->elph_profile_pool, profile_id); 6257 if (BCM_E_EXISTS != rv) { 6258 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 6259 (BSL_META_U(unit, 6260 "FT(unit %d) Error: Profile (ID:%d) does not exist.\n"), 6261 unit, profile_id)); 6262 return (BCM_E_NOT_FOUND); 6263 } 6264 6265 6266 BCM_IF_ERROR_RETURN( 6267 _bcm_xgs5_ft_elph_profile_list_get(unit, profile_id, 6268 &profile_int_info)); 6269 6270 sal_memcpy(profile, &(profile_int_info.profile), 6271 sizeof(bcm_flowtracker_elephant_profile_info_t)); 6272 6273 return BCM_E_NONE; 6274 } 6275 6276 /* 6277 * Function: 6278 * _bcm_th_ft_elephant_profile_get_all 6279 * Purpose: 6280 * Get the list of all flowtracker elephant profiles configured. 6281 * Parameters: 6282 * unit - (IN) BCM device number 6283 * max - (IN) Max number of profile information that can be 6284 * accomodated within profile_list. 6285 * profile_list - (OUT) Elephant profile information 6286 * count - (OUT) Actual number of elephant profiles 6287 * Returns: 6288 * BCM_E_XXX - BCM error code. 6289 */ 6290 int _bcm_th_ft_elephant_profile_get_all( 6291 int unit, 6292 int max, 6293 bcm_flowtracker_elephant_profile_t *profile_list, 6294 int *count) 6295 { 6296 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 6297 int num_profiles, i; 6298 6299 if (ft_info == NULL || ft_info->elph_mode != TRUE) { 6300 return BCM_E_INIT; 6301 } 6302 6303 /* If the max_size is non zero and list == NULL, return 6304 * BCM_E_PARAM. 6305 */ 6306 if (max != 0 && profile_list == NULL) { 6307 return BCM_E_PARAM; 6308 } 6309 6310 num_profiles = 0; 6311 *count = 0; 6312 for (i = BCM_INT_FT_ELPH_PROFILE_START_ID; 6313 i <= BCM_INT_FT_ELPH_PROFILE_END_ID; 6314 i++) { 6315 if (ft_elph_profile_info_list[unit][i].id == i) { 6316 /* Profile exists */ 6317 num_profiles++; 6318 if (*count < max) { 6319 profile_list[*count] = i; 6320 (*count)++; 6321 } 6322 } 6323 } 6324 6325 if (max == 0) { 6326 /* Special case, just return the number of profiles */ 6327 *count = num_profiles; 6328 return BCM_E_NONE; 6329 } 6330 6331 return BCM_E_NONE; 6332 } 6333 6334 /* 6335 * Function: 6336 * _bcm_th_ft_group_elephant_profile_attach 6337 * Purpose: 6338 * Attach a flow group with an elephant profile. 6339 * Parameters: 6340 * unit - (IN) BCM device number 6341 * flow_group_id - (IN) Flow group Id 6342 * profile_id - (IN) Elephant profile id 6343 * Returns: 6344 * BCM_E_XXX - BCM error code. 6345 */ 6346 int _bcm_th_ft_group_elephant_profile_attach( 6347 int unit, 6348 bcm_flowtracker_group_t flow_group_id, 6349 bcm_flowtracker_elephant_profile_t profile_id) 6350 { 6351 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 6352 _bcm_int_ft_flow_group_info_t flow_group_int_info; 6353 int rv = BCM_E_NONE; 6354 6355 if (ft_info == NULL || ft_info->elph_mode != TRUE) { 6356 return BCM_E_INIT; 6357 } 6358 6359 /* Check if profile ID exists */ 6360 rv = shr_idxres_list_elem_state(ft_info->elph_profile_pool, profile_id); 6361 if (BCM_E_EXISTS != rv) { 6362 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 6363 (BSL_META_U(unit, 6364 "FT(unit %d) Error: Profile (ID:%d) does not exist.\n"), 6365 unit, profile_id)); 6366 return (BCM_E_NOT_FOUND); 6367 } 6368 6369 /* Check if the flow group exists */ 6370 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, flow_group_id); 6371 if (BCM_E_EXISTS != rv) { 6372 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 6373 (BSL_META_U(unit, 6374 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 6375 unit, flow_group_id)); 6376 return (BCM_E_NOT_FOUND); 6377 } 6378 6379 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 6380 /* Get the flow group info for this group id */ 6381 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, flow_group_id, 6382 &flow_group_int_info); 6383 if (BCM_FAILURE(rv)) { 6384 return rv; 6385 } 6386 6387 rv = _bcm_xgs5_ft_eapp_send_flow_group_update_msg( 6388 unit, flow_group_id, 6389 SHR_FT_GROUP_UPDATE_ELPH_PROFILE, 6390 profile_id); 6391 if (BCM_FAILURE(rv)) { 6392 return rv; 6393 } 6394 6395 6396 flow_group_int_info.elph_profile_id = profile_id; 6397 rv = _bcm_xgs5_ft_flow_group_list_flow_group_modify(unit, flow_group_id, 6398 &flow_group_int_info); 6399 if (BCM_FAILURE(rv)) { 6400 return rv; 6401 } 6402 return BCM_E_NONE; 6403 } 6404 6405 /* 6406 * Function: 6407 * _bcm_th_ft_group_elephant_profile_attach_get 6408 * Purpose: 6409 * Get the elephant profile Id attached with a flow group. 6410 * Parameters: 6411 * unit - (IN) BCM device number 6412 * flow_group_id - (IN) Flow group Id 6413 * profile_id - (OUT) Elephant profile id 6414 * Returns: 6415 * BCM_E_XXX - BCM error code. 6416 */ 6417 int _bcm_th_ft_group_elephant_profile_attach_get( 6418 int unit, 6419 bcm_flowtracker_group_t flow_group_id, 6420 bcm_flowtracker_elephant_profile_t *profile_id) 6421 { 6422 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 6423 _bcm_int_ft_flow_group_info_t flow_group_int_info; 6424 int rv = BCM_E_NONE; 6425 6426 if (ft_info == NULL || ft_info->elph_mode != TRUE) { 6427 return BCM_E_INIT; 6428 } 6429 6430 /* Check if the flow group exists */ 6431 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, flow_group_id); 6432 if (BCM_E_EXISTS != rv) { 6433 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 6434 (BSL_META_U(unit, 6435 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 6436 unit, flow_group_id)); 6437 return (BCM_E_NOT_FOUND); 6438 } 6439 6440 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 6441 /* Get the flow group info for this group id */ 6442 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, flow_group_id, 6443 &flow_group_int_info); 6444 if (BCM_FAILURE(rv)) { 6445 return rv; 6446 } 6447 6448 if (flow_group_int_info.elph_profile_id == 0) { 6449 return BCM_E_NOT_FOUND; 6450 } 6451 *profile_id = flow_group_int_info.elph_profile_id; 6452 6453 return BCM_E_NONE; 6454 } 6455 6456 /* 6457 * Function: 6458 * _bcm_th_ft_group_elephant_profile_detach 6459 * Purpose: 6460 * Detach a flow group with an elephant profile. 6461 * Parameters: 6462 * unit - (IN) BCM device number 6463 * flow_group_id - (IN) Flow group Id 6464 * Returns: 6465 * BCM_E_XXX - BCM error code. 6466 */ 6467 int 6468 _bcm_th_ft_group_elephant_profile_detach(int unit, 6469 bcm_flowtracker_group_t flow_group_id) 6470 { 6471 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 6472 _bcm_int_ft_flow_group_info_t flow_group_int_info; 6473 int rv = BCM_E_NONE; 6474 6475 if (ft_info == NULL || ft_info->elph_mode != TRUE) { 6476 return BCM_E_INIT; 6477 } 6478 6479 /* Check if the flow group exists */ 6480 rv = shr_idxres_list_elem_state(ft_info->flow_group_pool, flow_group_id); 6481 if (BCM_E_EXISTS != rv) { 6482 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, 6483 (BSL_META_U(unit, 6484 "FT(unit %d) Error: Group (ID:%d) does not exist.\n"), 6485 unit, flow_group_id)); 6486 return (BCM_E_NOT_FOUND); 6487 } 6488 6489 sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info)); 6490 /* Get the flow group info for this group id */ 6491 rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, flow_group_id, 6492 &flow_group_int_info); 6493 if (BCM_FAILURE(rv)) { 6494 return rv; 6495 } 6496 6497 if (flow_group_int_info.elph_profile_id == 0) { 6498 /* Profile not attached */ 6499 return BCM_E_PARAM; 6500 } 6501 6502 if (flow_group_int_info.flow_limit != 0) { 6503 /* Flow limit has to be set to 0 before detaching elephant profile */ 6504 return BCM_E_INTERNAL; 6505 } 6506 6507 rv = _bcm_xgs5_ft_eapp_send_flow_group_update_msg( 6508 unit, flow_group_id, 6509 SHR_FT_GROUP_UPDATE_ELPH_PROFILE, 6510 0); 6511 if (BCM_FAILURE(rv)) { 6512 return rv; 6513 } 6514 6515 6516 flow_group_int_info.elph_profile_id = 0; 6517 rv = _bcm_xgs5_ft_flow_group_list_flow_group_modify(unit, flow_group_id, 6518 &flow_group_int_info); 6519 if (BCM_FAILURE(rv)) { 6520 return rv; 6521 } 6522 return BCM_E_NONE; 6523 } 6524 6525 6526 #ifdef BCM_WARM_BOOT_SUPPORT 6527 6528 #define BCM_WB_FT_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 6529 #define BCM_WB_FT_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 6530 #define BCM_WB_FT_DEFAULT_VERSION BCM_WB_FT_VERSION_1_1 6531 6532 #define FT_SCACHE_WRITE(_scache, _val, _type) \ 6533 do { \ 6534 _type _tmp = (_type) (_val); \ 6535 sal_memcpy((_scache), &(_tmp), sizeof(_type)); \ 6536 (_scache) += sizeof(_type); \ 6537 } while(0) 6538 6539 #define FT_SCACHE_READ(_scache, _var, _type) \ 6540 do { \ 6541 _type _tmp; \ 6542 sal_memcpy(&(_tmp), (_scache), sizeof(_type)); \ 6543 (_scache) += sizeof(_type); \ 6544 (_var) = (_tmp); \ 6545 } while(0) 6546 6547 /* 6548 * Function: 6549 * _bcm_th_ft_scache_v0_global_size_get 6550 * Purpose: 6551 * Get the size required to sync Flowtracker global data to scache v0 6552 * Parameters: 6553 * unit - (IN) Device unit number 6554 * Returns: 6555 * Required size 6556 */ 6557 STATIC uint32 6558 _bcm_th_ft_scache_v0_global_size_get(int unit) 6559 { 6560 uint32 size = 0; 6561 6562 /* Reserved bits */ 6563 size += sizeof(uint32); 6564 6565 /* Number of uC */ 6566 size += sizeof(uint8); 6567 6568 /* Mode */ 6569 size += sizeof(uint8); 6570 6571 /* Observation domain Id */ 6572 size += sizeof(uint32); 6573 6574 return size; 6575 } 6576 6577 /* 6578 * Function: 6579 * _bcm_th_ft_scache_v0_global_sync 6580 * Purpose: 6581 * Sync Flowtracker global data to scache v0 6582 * Parameters: 6583 * unit - (IN) Device unit number 6584 * scache - (IN) Pointer to current scache location 6585 * Returns: 6586 * BCM_E_XXX 6587 */ 6588 STATIC void 6589 _bcm_th_ft_scache_v0_global_sync(int unit, uint8 **scache) 6590 { 6591 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 6592 6593 /* Reserve first 32 bits */ 6594 FT_SCACHE_WRITE(*scache, 0, uint32); 6595 6596 /* Number of uC */ 6597 FT_SCACHE_WRITE(*scache, 1, uint8); 6598 6599 if (ft_info->elph_mode) { 6600 /* Elephant mode */ 6601 FT_SCACHE_WRITE(*scache, 1, uint8); 6602 } else { 6603 /* Standard mode */ 6604 FT_SCACHE_WRITE(*scache, 0, uint8); 6605 } 6606 6607 /* Observation Domain ID */ 6608 FT_SCACHE_WRITE(*scache, ft_info->observation_domain_id, uint32); 6609 } 6610 6611 /* 6612 * Function: 6613 * _bcm_th_ft_scache_v0_global_recover 6614 * Purpose: 6615 * Recover Flowtracker global data from scache v0 6616 * Parameters: 6617 * unit - (IN) Device unit number 6618 * scache - (IN) Pointer to current scache location 6619 * Returns: 6620 * BCM_E_XXX 6621 */ 6622 STATIC int 6623 _bcm_th_ft_scache_v0_global_recover(int unit, uint8 **scache) 6624 { 6625 uint8 num_uc; 6626 uint8 mode; 6627 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 6628 6629 /* Reserved bits */ 6630 *scache += sizeof(uint32); 6631 6632 /* Number of uC */ 6633 FT_SCACHE_READ(*scache, num_uc, uint8); 6634 if (num_uc != 1) { 6635 return BCM_E_PARAM; 6636 } 6637 6638 /* Mode */ 6639 FT_SCACHE_READ(*scache, mode, uint8); 6640 /* Only possible mode is elephant/standard. Elephant mode is recovered 6641 * from soc property, validate if they are in agreement. 6642 */ 6643 if (mode > 1) { 6644 return BCM_E_PARAM; 6645 } else if (mode == 1 && !ft_info->elph_mode) { 6646 return BCM_E_PARAM; 6647 } else if (mode == 0 && ft_info->elph_mode) { 6648 return BCM_E_PARAM; 6649 } 6650 6651 /* Observation Domain ID */ 6652 FT_SCACHE_READ(*scache, ft_info->observation_domain_id, uint32); 6653 6654 return BCM_E_NONE; 6655 } 6656 6657 /* 6658 * Function: 6659 * _bcm_th_ft_scache_v0_group_size_get 6660 * Purpose: 6661 * Get the size required to sync Flowtracker group data to scache v0 6662 * Parameters: 6663 * unit - (IN) Device unit number 6664 * Returns: 6665 * Required size 6666 */ 6667 STATIC uint32 6668 _bcm_th_ft_scache_v0_group_size_get(int unit) 6669 { 6670 uint32 size = 0; 6671 int i, j; 6672 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 6673 6674 /* group Id */ 6675 size += sizeof(uint16); 6676 6677 /* in_use */ 6678 size += sizeof(uint8); 6679 6680 /* Collector Id */ 6681 size += sizeof(uint16); 6682 6683 /* Template Id */ 6684 size += sizeof(uint16); 6685 6686 /* Aging interval */ 6687 size += sizeof(uint32); 6688 6689 /* Flow limit */ 6690 size += sizeof(uint32); 6691 6692 /* Elephant profile Id */ 6693 size += sizeof(uint16); 6694 6695 /* QoS profile Id */ 6696 size += sizeof(uint16); 6697 6698 /* Number of actions */ 6699 size += sizeof(uint16); 6700 6701 for (i = 0; i < BCM_INT_FT_MAX_GROUP_ACTIONS; i++) { 6702 /* Action */ 6703 size += sizeof(uint16); 6704 6705 /* Number of params */ 6706 size += sizeof(uint8); 6707 6708 for (j = 0; j < BCM_INT_FT_MAX_GROUP_ACTION_PARAMS; j++) { 6709 /* Action params */ 6710 size += sizeof(uint32); 6711 } 6712 } 6713 6714 /* Multiply by number of groups */ 6715 size *= ft_info->max_flow_groups; 6716 6717 return size; 6718 } 6719 6720 /* 6721 * Function: 6722 * _bcm_th_ft_scache_v0_group_sync 6723 * Purpose: 6724 * Sync Flowtracker group data to scache v0 6725 * Parameters: 6726 * unit - (IN) Device unit number 6727 * scache - (IN) Pointer to current scache location 6728 * Returns: 6729 * BCM_E_XXX 6730 */ 6731 STATIC void 6732 _bcm_th_ft_scache_v0_group_sync(int unit, uint8 **scache) 6733 { 6734 int i, j, k; 6735 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 6736 _bcm_int_ft_flow_group_info_t *flow_group_list = ft_flow_group_info_list[unit]; 6737 _bcm_int_ft_flow_group_info_t *group = NULL; 6738 6739 for (i = BCM_INT_FT_GROUP_START_ID; 6740 i < (ft_info->max_flow_groups + BCM_INT_FT_GROUP_START_ID); 6741 i++) { 6742 group = &(flow_group_list[i]); 6743 6744 /* group Id */ 6745 FT_SCACHE_WRITE(*scache, i, uint16); 6746 6747 if (group->flow_group_id == i) { 6748 /* Group exists, set in_use = 1 */ 6749 FT_SCACHE_WRITE(*scache, 1, uint8); 6750 } else { 6751 /* Group does not exist, set in_use = 0 */ 6752 FT_SCACHE_WRITE(*scache, 0, uint8); 6753 continue; 6754 } 6755 6756 /* Collector Id */ 6757 FT_SCACHE_WRITE(*scache, group->collector_id, uint16); 6758 6759 /* Template Id */ 6760 FT_SCACHE_WRITE(*scache, group->template_id, uint16); 6761 6762 /* Aging interval */ 6763 FT_SCACHE_WRITE(*scache, group->aging_interval_msecs, uint32); 6764 6765 /* Flow limit */ 6766 FT_SCACHE_WRITE(*scache, group->flow_limit, uint32); 6767 6768 /* Elephant profile Id */ 6769 FT_SCACHE_WRITE(*scache, group->elph_profile_id, uint16); 6770 6771 /* QoS profile Id */ 6772 FT_SCACHE_WRITE(*scache, group->qos_profile_id, uint16); 6773 6774 /* Number of actions */ 6775 FT_SCACHE_WRITE(*scache, group->num_actions, uint16); 6776 6777 for (j = 0; j < group->num_actions; j++) { 6778 /* Action */ 6779 FT_SCACHE_WRITE(*scache, group->action_list[j].action, uint16); 6780 6781 /* Number of params */ 6782 FT_SCACHE_WRITE(*scache, group->action_list[j].num_params, uint8); 6783 6784 for (k = 0; k < group->action_list[j].num_params; k++) { 6785 /* Action params */ 6786 FT_SCACHE_WRITE(*scache, group->action_list[j].params[k], uint32); 6787 } 6788 } 6789 } 6790 } 6791 6792 /* 6793 * Function: 6794 * _bcm_th_ft_scache_v0_group_recover 6795 * Purpose: 6796 * Recover Flowtracker group data from scache v0 6797 * Parameters: 6798 * unit - (IN) Device unit number 6799 * scache - (IN) Pointer to current scache location 6800 * Returns: 6801 * BCM_E_XXX 6802 */ 6803 STATIC int 6804 _bcm_th_ft_scache_v0_group_recover(int unit, uint8 **scache) 6805 { 6806 int i, j, k; 6807 int rv; 6808 int pipe; 6809 uint8 num_params; 6810 uint8 in_use; 6811 uint16 group_id; 6812 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 6813 _bcm_int_ft_flow_group_info_t *flow_group_list = ft_flow_group_info_list[unit]; 6814 _bcm_int_ft_flow_group_info_t *group = NULL; 6815 6816 for (i = BCM_INT_FT_GROUP_START_ID; 6817 i < (ft_info->max_flow_groups + BCM_INT_FT_GROUP_START_ID); 6818 i++) { 6819 group = &(flow_group_list[i]); 6820 6821 /* Group ID*/ 6822 FT_SCACHE_READ(*scache, group_id, uint16); 6823 if (group_id != i) { 6824 return BCM_E_INTERNAL; 6825 } 6826 6827 /* in_use */ 6828 FT_SCACHE_READ(*scache, in_use, uint8); 6829 if (in_use == 0) { 6830 continue; 6831 } 6832 group->flow_group_id = i; 6833 6834 rv = shr_idxres_list_reserve(ft_info->flow_group_pool, i, i); 6835 BCM_IF_ERROR_RETURN(rv); 6836 6837 /* Collector Id */ 6838 FT_SCACHE_READ(*scache, group->collector_id, uint16); 6839 if (ft_info->cfg_mode >= SHR_FT_CFG_MODE_V2 && 6840 (group->collector_id != _BCM_FT_WB_INVALID_COLLECTOR_ID)) { 6841 BCM_IF_ERROR_RETURN( 6842 _bcm_esw_collector_ref_count_update(unit, 6843 group->collector_id, 1)); 6844 } 6845 6846 6847 /* Template Id */ 6848 FT_SCACHE_READ(*scache, group->template_id, uint16); 6849 6850 /* Aging interval */ 6851 FT_SCACHE_READ(*scache, group->aging_interval_msecs, uint32); 6852 6853 /* Flow limit */ 6854 FT_SCACHE_READ(*scache, group->flow_limit, uint32); 6855 6856 /* Elephant profile Id */ 6857 FT_SCACHE_READ(*scache, group->elph_profile_id, uint16); 6858 6859 /* QoS profile Id */ 6860 FT_SCACHE_READ(*scache, group->qos_profile_id, uint16); 6861 if (group->qos_profile_id != 0) { 6862 for (pipe = 0; pipe < ft_info->num_pipes; pipe++) { 6863 rv = soc_profile_mem_reference(unit, 6864 ft_info->pipe_info[pipe].qos_profile_mem, 6865 group->qos_profile_id, 1); 6866 BCM_IF_ERROR_RETURN(rv); 6867 } 6868 } 6869 6870 /* Number of actions */ 6871 FT_SCACHE_READ(*scache, group->num_actions, uint16); 6872 if (group->num_actions > BCM_INT_FT_MAX_GROUP_ACTIONS) { 6873 return BCM_E_INTERNAL; 6874 } 6875 6876 /* Allocate memory for the action list */ 6877 if (group->num_actions > 0) { 6878 _BCM_FT_ALLOC(group->action_list, 6879 _bcm_int_ft_group_action_info_t, 6880 group->num_actions * sizeof(_bcm_int_ft_group_action_info_t), 6881 "Group action list"); 6882 if (group->action_list == NULL) { 6883 return BCM_E_MEMORY; 6884 } 6885 } 6886 6887 for (j = 0; j < group->num_actions; j++) { 6888 /* Action */ 6889 FT_SCACHE_READ(*scache, group->action_list[j].action, uint16); 6890 6891 if (group->action_list[j].action >= bcmFlowtrackerGroupActionCount) { 6892 /* Unrecognized action */ 6893 return BCM_E_INTERNAL; 6894 } 6895 6896 /* Number of params */ 6897 FT_SCACHE_READ(*scache, num_params, uint8); 6898 if (num_params > BCM_INT_FT_MAX_GROUP_ACTION_PARAMS) { 6899 return BCM_E_INTERNAL; 6900 } 6901 6902 /* Action params */ 6903 for (k = 0; k < num_params; k++) { 6904 FT_SCACHE_READ(*scache, group->action_list[j].params[k], uint32); 6905 } 6906 } 6907 } 6908 return BCM_E_NONE; 6909 } 6910 6911 /* 6912 * Function: 6913 * _bcm_th_ft_scache_v0_collector_size_get 6914 * Purpose: 6915 * Get the size required to sync Flowtracker collector data to scache v0 6916 * Parameters: 6917 * unit - (IN) Device unit number 6918 * Returns: 6919 * Required size 6920 */ 6921 STATIC uint32 6922 _bcm_th_ft_scache_v0_collector_size_get(int unit) 6923 { 6924 uint32 size = 0; 6925 6926 /* Collector Id */ 6927 size += sizeof(uint16); 6928 6929 /* in_use */ 6930 size += sizeof(uint8); 6931 6932 /* Transport type */ 6933 size += sizeof(uint16); 6934 6935 /* Dst mac addr */ 6936 size += (sizeof(uint8) * 6); 6937 6938 /* Src mac addr */ 6939 size += (sizeof(uint8) * 6); 6940 6941 /* Vlan tag structure */ 6942 size += sizeof(uint8); 6943 6944 /* Outer TPID */ 6945 size += sizeof(uint16); 6946 6947 /* Inner TPID */ 6948 size += sizeof(uint16); 6949 6950 /* Outer vlan tag */ 6951 size += sizeof(uint32); 6952 6953 /* Inner vlan tag */ 6954 size += sizeof(uint32); 6955 6956 /* Sync IP header (only IPv4 is supported) */ 6957 /* Src IP */ 6958 size += sizeof(uint32); 6959 6960 /* Dst IP */ 6961 size += sizeof(uint32); 6962 6963 /* DSCP */ 6964 size += sizeof(uint8); 6965 6966 /* TTL */ 6967 size += sizeof(uint8); 6968 6969 /* Src ports */ 6970 size += sizeof(uint16); 6971 6972 /* Dst port */ 6973 size += sizeof(uint16); 6974 6975 /* Max pkt length */ 6976 size += sizeof(uint16); 6977 6978 /* Multiply by number of collectors */ 6979 size *= BCM_INT_FT_MAX_COLLECTORS; 6980 6981 return size; 6982 } 6983 6984 /* 6985 * Function: 6986 * _bcm_th_ft_scache_v0_collector_sync 6987 * Purpose: 6988 * Sync Flowtracker collector data to scache v0 6989 * Parameters: 6990 * unit - (IN) Device unit number 6991 * scache - (IN) Pointer to current scache location 6992 * Returns: 6993 * BCM_E_XXX 6994 */ 6995 STATIC void 6996 _bcm_th_ft_scache_v0_collector_sync(int unit, uint8 **scache) 6997 { 6998 int i, j; 6999 _bcm_int_ft_collector_info_t *collector_list = ft_collector_info_list[unit]; 7000 _bcm_int_ft_collector_info_t *collector = NULL; 7001 7002 for (i = BCM_INT_FT_COLLECTOR_START_ID; i <= BCM_INT_FT_COLLECTOR_END_ID; i++) { 7003 7004 collector = &(collector_list[i]); 7005 7006 /* Collector Id */ 7007 FT_SCACHE_WRITE(*scache, i, uint16); 7008 7009 if (collector->collector_id == i) { 7010 /* Collector exists, set in_use = 1 */ 7011 FT_SCACHE_WRITE(*scache, 1, uint8); 7012 } else { 7013 /* Collector does not exist, set in_use = 0 */ 7014 FT_SCACHE_WRITE(*scache, 0, uint8); 7015 continue; 7016 } 7017 7018 7019 /* Transport type */ 7020 FT_SCACHE_WRITE(*scache, collector->collector_info.transport_type, uint16); 7021 7022 /* Dst mac addr */ 7023 for (j = 0; j < 6; j++) { 7024 FT_SCACHE_WRITE(*scache, collector->collector_info.eth.dst_mac[j], 7025 uint8); 7026 } 7027 7028 /* Src mac addr */ 7029 for (j = 0; j < 6; j++) { 7030 FT_SCACHE_WRITE(*scache, collector->collector_info.eth.src_mac[j], 7031 uint8); 7032 } 7033 7034 /* Vlan tag structure */ 7035 FT_SCACHE_WRITE(*scache, collector->collector_info.eth.vlan_tag_structure, 7036 uint8); 7037 7038 /* Outer TPID */ 7039 FT_SCACHE_WRITE(*scache, collector->collector_info.eth.outer_tpid, uint16); 7040 7041 /* Inner TPID */ 7042 FT_SCACHE_WRITE(*scache, collector->collector_info.eth.inner_tpid, uint16); 7043 7044 /* Outer vlan tag */ 7045 FT_SCACHE_WRITE(*scache, collector->collector_info.eth.outer_vlan_tag, 7046 uint32); 7047 7048 /* Inner vlan tag */ 7049 FT_SCACHE_WRITE(*scache, collector->collector_info.eth.inner_vlan_tag, 7050 uint32); 7051 7052 /* Sync IP header (only IPv4 is supported) */ 7053 /* Src IP */ 7054 FT_SCACHE_WRITE(*scache, collector->collector_info.ipv4.src_ip, uint32); 7055 7056 /* Dst IP */ 7057 FT_SCACHE_WRITE(*scache, collector->collector_info.ipv4.dst_ip, uint32); 7058 7059 /* DSCP */ 7060 FT_SCACHE_WRITE(*scache, collector->collector_info.ipv4.dscp, uint8); 7061 7062 /* TTL */ 7063 FT_SCACHE_WRITE(*scache, collector->collector_info.ipv4.ttl, uint8); 7064 7065 /* Src port */ 7066 FT_SCACHE_WRITE(*scache, collector->collector_info.udp.src_port, uint16); 7067 7068 /* Dst port */ 7069 FT_SCACHE_WRITE(*scache, collector->collector_info.udp.dst_port, uint16); 7070 7071 /* Max pkt length */ 7072 FT_SCACHE_WRITE(*scache, collector->collector_info.max_packet_length, uint16); 7073 } 7074 } 7075 7076 /* 7077 * Function: 7078 * _bcm_th_ft_scache_v0_collector_recover 7079 * Purpose: 7080 * Recover Flowtracker collector data from scache v0 7081 * Parameters: 7082 * unit - (IN) Device unit number 7083 * scache - (IN) Pointer to current scache location 7084 * Returns: 7085 * BCM_E_XXX 7086 */ 7087 STATIC int 7088 _bcm_th_ft_scache_v0_collector_recover(int unit, uint8 **scache) 7089 { 7090 int i, j; 7091 int rv; 7092 uint8 in_use; 7093 uint16 collector_id; 7094 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 7095 _bcm_int_ft_collector_info_t *collector_list = ft_collector_info_list[unit]; 7096 _bcm_int_ft_collector_info_t *collector = NULL; 7097 7098 for (i = BCM_INT_FT_COLLECTOR_START_ID; i <= BCM_INT_FT_COLLECTOR_END_ID; i++) { 7099 7100 collector = &(collector_list[i]); 7101 7102 /* Collector Id */ 7103 FT_SCACHE_READ(*scache, collector_id, uint16); 7104 if (collector_id != i) { 7105 return BCM_E_INTERNAL; 7106 } 7107 7108 /* in_use */ 7109 FT_SCACHE_READ(*scache, in_use, uint8); 7110 if (in_use == 0) { 7111 continue; 7112 } 7113 7114 collector->collector_id = i; 7115 7116 rv = shr_idxres_list_reserve(ft_info->collector_pool, i, i); 7117 BCM_IF_ERROR_RETURN(rv); 7118 7119 /* Transport type */ 7120 FT_SCACHE_READ(*scache, collector->collector_info.transport_type, uint16); 7121 if (collector->collector_info.transport_type != 7122 bcmFlowtrackerCollectorTransportTypeIpfixIpv4Udp) { 7123 return BCM_E_INTERNAL; 7124 } 7125 7126 /* Dst mac addr */ 7127 for (j = 0; j < 6; j++) { 7128 FT_SCACHE_READ(*scache, collector->collector_info.eth.dst_mac[j], 7129 uint8); 7130 } 7131 7132 /* Src mac addr */ 7133 for (j = 0; j < 6; j++) { 7134 FT_SCACHE_READ(*scache, collector->collector_info.eth.src_mac[j], 7135 uint8); 7136 } 7137 7138 /* Vlan tag structure */ 7139 FT_SCACHE_READ(*scache, collector->collector_info.eth.vlan_tag_structure, 7140 uint8); 7141 7142 /* Outer TPID */ 7143 FT_SCACHE_READ(*scache, collector->collector_info.eth.outer_tpid, uint16); 7144 7145 /* Inner TPID */ 7146 FT_SCACHE_READ(*scache, collector->collector_info.eth.inner_tpid, uint16); 7147 7148 /* Outer vlan tag */ 7149 FT_SCACHE_READ(*scache, collector->collector_info.eth.outer_vlan_tag, 7150 uint32); 7151 7152 /* Inner vlan tag */ 7153 FT_SCACHE_READ(*scache, collector->collector_info.eth.inner_vlan_tag, 7154 uint32); 7155 7156 /* IP header (only IPv4 is supported) */ 7157 /* Src IP */ 7158 FT_SCACHE_READ(*scache, collector->collector_info.ipv4.src_ip, uint32); 7159 7160 /* Dst IP */ 7161 FT_SCACHE_READ(*scache, collector->collector_info.ipv4.dst_ip, uint32); 7162 7163 /* DSCP */ 7164 FT_SCACHE_READ(*scache, collector->collector_info.ipv4.dscp, uint8); 7165 7166 /* TTL */ 7167 FT_SCACHE_READ(*scache, collector->collector_info.ipv4.ttl, uint8); 7168 7169 /* Src port */ 7170 FT_SCACHE_READ(*scache, collector->collector_info.udp.src_port, uint16); 7171 7172 /* Dst port */ 7173 FT_SCACHE_READ(*scache, collector->collector_info.udp.dst_port, uint16); 7174 7175 /* Max pkt length */ 7176 FT_SCACHE_READ(*scache, collector->collector_info.max_packet_length, uint16); 7177 } 7178 return BCM_E_NONE; 7179 } 7180 7181 /* 7182 * Function: 7183 * _bcm_th_ft_scache_v0_template_size_get 7184 * Purpose: 7185 * Get the size required to sync Flowtracker template data to scache v0 7186 * Parameters: 7187 * unit - (IN) Device unit number 7188 * Returns: 7189 * Required size 7190 */ 7191 STATIC uint32 7192 _bcm_th_ft_scache_v0_template_size_get(int unit) 7193 { 7194 int i; 7195 uint32 size = 0; 7196 7197 /* Template Id */ 7198 size += sizeof(uint16); 7199 7200 /* in_use */ 7201 size += sizeof(uint8); 7202 7203 /* Set ID */ 7204 size += sizeof(uint16); 7205 7206 /* Number of export elements */ 7207 size += sizeof(uint16); 7208 7209 for (i = 0; i < SHR_FT_TEMPLATE_MAX_INFO_ELEMENTS; i++) { 7210 /* Element Id */ 7211 size += sizeof(uint16); 7212 7213 /* Data size */ 7214 size += sizeof(uint8); 7215 7216 /* Information Element Id */ 7217 size += sizeof(uint16); 7218 7219 /* Enterprise flag */ 7220 size += sizeof(uint8); 7221 } 7222 7223 /* Multiply by number of templates */ 7224 size *= BCM_INT_FT_MAX_TEMPLATES; 7225 7226 return size; 7227 } 7228 7229 /* 7230 * Function: 7231 * _bcm_th_ft_scache_v0_template_sync 7232 * Purpose: 7233 * Sync Flowtracker template data to scache v0 7234 * Parameters: 7235 * unit - (IN) Device unit number 7236 * scache - (IN) Pointer to current scache location 7237 * Returns: 7238 * None 7239 */ 7240 STATIC void 7241 _bcm_th_ft_scache_v0_template_sync(int unit, uint8 **scache) 7242 { 7243 int i, j; 7244 _bcm_int_ft_export_template_info_t *template_list = ft_export_template_info_list[unit]; 7245 _bcm_int_ft_export_template_info_t *template = NULL; 7246 7247 7248 for (i = BCM_INT_FT_TEMPLATE_START_ID; i <= BCM_INT_FT_TEMPLATE_END_ID; i++) { 7249 7250 template = &(template_list[i]); 7251 7252 /* Template Id */ 7253 FT_SCACHE_WRITE(*scache, i, uint16); 7254 7255 if (template->template_id == i) { 7256 /* Template exists, set in_use = 1 */ 7257 FT_SCACHE_WRITE(*scache, 1, uint8); 7258 } else { 7259 /* Template does not exist, set in_use = 0 */ 7260 FT_SCACHE_WRITE(*scache, 0, uint8); 7261 continue; 7262 } 7263 7264 7265 /* Set ID */ 7266 FT_SCACHE_WRITE(*scache, template->set_id, uint16); 7267 7268 /* Number of export elements */ 7269 FT_SCACHE_WRITE(*scache, template->num_export_elements, uint16); 7270 7271 for (j = 0; j < template->num_export_elements; j++) { 7272 /* Element Id */ 7273 FT_SCACHE_WRITE(*scache, template->elements[j].element, uint16); 7274 7275 /* Data size */ 7276 FT_SCACHE_WRITE(*scache, template->elements[j].data_size, uint16); 7277 7278 /* Information Element Id */ 7279 FT_SCACHE_WRITE(*scache, template->elements[j].id, uint16); 7280 7281 /* Enterprise flag */ 7282 FT_SCACHE_WRITE(*scache, template->elements[j].enterprise, uint8); 7283 } 7284 } 7285 } 7286 7287 /* 7288 * Function: 7289 * _bcm_th_ft_scache_v0_template_recover 7290 * Purpose: 7291 * Recover Flowtracker template data from scache v0 7292 * Parameters: 7293 * unit - (IN) Device unit number 7294 * scache - (IN) Pointer to current scache location 7295 * Returns: 7296 * BCM_E_XXX 7297 */ 7298 STATIC int 7299 _bcm_th_ft_scache_v0_template_recover(int unit, uint8 **scache) 7300 { 7301 int i, j; 7302 int rv; 7303 uint8 in_use; 7304 uint16 template_id; 7305 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 7306 _bcm_int_ft_export_template_info_t *template_list = ft_export_template_info_list[unit]; 7307 _bcm_int_ft_export_template_info_t *template = NULL; 7308 7309 7310 for (i = BCM_INT_FT_TEMPLATE_START_ID; i <= BCM_INT_FT_TEMPLATE_END_ID; i++) { 7311 7312 template = &(template_list[i]); 7313 7314 /* Template Id */ 7315 FT_SCACHE_READ(*scache, template_id, uint16); 7316 if (template_id != i) { 7317 return BCM_E_INTERNAL; 7318 } 7319 7320 /* in_use */ 7321 FT_SCACHE_READ(*scache, in_use, uint8); 7322 if (in_use == 0) { 7323 continue; 7324 } 7325 7326 template->template_id = i; 7327 7328 rv = shr_idxres_list_reserve(ft_info->template_pool, i, i); 7329 BCM_IF_ERROR_RETURN(rv); 7330 7331 /* Set ID */ 7332 FT_SCACHE_READ(*scache, template->set_id, uint16); 7333 7334 /* Number of export elements */ 7335 FT_SCACHE_READ(*scache, template->num_export_elements, uint16); 7336 7337 for (j = 0; j < template->num_export_elements; j++) { 7338 /* Element Id */ 7339 FT_SCACHE_READ(*scache, template->elements[j].element, uint16); 7340 if (template->elements[j].element >= SHR_FT_TEMPLATE_MAX_INFO_ELEMENTS) { 7341 /* Unrecognized element */ 7342 return BCM_E_INTERNAL; 7343 } 7344 7345 /* Data size */ 7346 FT_SCACHE_READ(*scache, template->elements[j].data_size, uint16); 7347 7348 /* Information Element Id */ 7349 FT_SCACHE_READ(*scache, template->elements[j].id, uint16); 7350 7351 /* Enterprise flag */ 7352 FT_SCACHE_READ(*scache, template->elements[j].enterprise, uint8); 7353 } 7354 } 7355 return BCM_E_NONE; 7356 } 7357 7358 /* 7359 * Function: 7360 * _bcm_th_ft_scache_v0_template_xmit_size_get 7361 * Purpose: 7362 * Get the size required to sync Flowtracker template xmit data to scache v0 7363 * Parameters: 7364 * unit - (IN) Device unit number 7365 * Returns: 7366 * Required size 7367 */ 7368 STATIC uint32 7369 _bcm_th_ft_scache_v0_template_xmit_size_get(int unit) 7370 { 7371 uint32 size = 0; 7372 7373 /* Template ID */ 7374 size += sizeof(uint16); 7375 7376 /* Collector Id */ 7377 size += sizeof(uint16); 7378 7379 /* Interval secs */ 7380 size += sizeof(uint16); 7381 7382 /* Initial burst */ 7383 size += sizeof(uint16); 7384 7385 /* Multiply by number of collector and templates */ 7386 size *= (BCM_INT_FT_MAX_COLLECTORS * BCM_INT_FT_MAX_TEMPLATES); 7387 7388 return size; 7389 } 7390 7391 /* 7392 * Function: 7393 * _bcm_th_ft_scache_v0_template_xmit_sync 7394 * Purpose: 7395 * Sync Flowtracker template xmit data to scache v0 7396 * Parameters: 7397 * unit - (IN) Device unit number 7398 * scache - (IN) Pointer to current scache location 7399 * Returns: 7400 * BCM_E_XXX 7401 */ 7402 STATIC void 7403 _bcm_th_ft_scache_v0_template_xmit_sync(int unit, uint8 **scache) 7404 { 7405 _bcm_int_ft_export_template_info_t *template = NULL; 7406 7407 /* Template xmit is stored 'template x collector' number of time. We support 7408 * only one collector and template currently, so only a single xmit config is 7409 * writen to scache. 7410 */ 7411 template = &(ft_export_template_info_list[unit][BCM_INT_FT_TEMPLATE_START_ID]); 7412 7413 /* Template ID */ 7414 FT_SCACHE_WRITE(*scache, 1, uint16); 7415 7416 /* Collector Id */ 7417 FT_SCACHE_WRITE(*scache, 1, uint16); 7418 7419 /* Interval secs */ 7420 FT_SCACHE_WRITE(*scache, template->interval_secs, uint16); 7421 7422 /* Initial burst */ 7423 FT_SCACHE_WRITE(*scache, template->initial_burst, uint16); 7424 7425 } 7426 7427 /* 7428 * Function: 7429 * _bcm_th_ft_scache_v0_template_xmit_recover 7430 * Purpose: 7431 * Recover Flowtracker template xmit data from scache v0 7432 * Parameters: 7433 * unit - (IN) Device unit number 7434 * scache - (IN) Pointer to current scache location 7435 * Returns: 7436 * BCM_E_XXX 7437 */ 7438 STATIC int 7439 _bcm_th_ft_scache_v0_template_xmit_recover(int unit, uint8 **scache) 7440 { 7441 _bcm_int_ft_export_template_info_t *template = NULL; 7442 7443 /* Template xmit is stored 'template x collector' number of time. We support 7444 * only one collector and template currently, so only a single xmit config 7445 * needs to be read from scache. 7446 */ 7447 template = &(ft_export_template_info_list[unit][BCM_INT_FT_TEMPLATE_START_ID]); 7448 7449 /* Skip template ID */ 7450 *scache += sizeof(uint16); 7451 7452 /* Skip Collector Id */ 7453 *scache += sizeof(uint16); 7454 7455 /* Interval secs */ 7456 FT_SCACHE_READ(*scache, template->interval_secs, uint16); 7457 7458 /* Initial burst */ 7459 FT_SCACHE_READ(*scache, template->initial_burst, uint16); 7460 7461 return BCM_E_NONE; 7462 } 7463 7464 /* 7465 * Function: 7466 * _bcm_th_ft_scache_v0_elph_prof_size_get 7467 * Purpose: 7468 * Get the size required to sync Flowtracker elephant profile 7469 * data to scache v0 7470 * Parameters: 7471 * unit - (IN) Device unit number 7472 * Returns: 7473 * Required size 7474 */ 7475 STATIC uint32 7476 _bcm_th_ft_scache_v0_elph_prof_size_get(int unit) 7477 { 7478 int i; 7479 uint32 size = 0; 7480 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 7481 7482 if (!ft_info->elph_mode) { 7483 return 0; 7484 } 7485 7486 /* Profile Id */ 7487 size += sizeof(uint8); 7488 7489 /* in_use */ 7490 size += sizeof(uint8); 7491 7492 /* Num promotion filters */ 7493 size += sizeof(uint8); 7494 7495 for (i = 0; i < BCM_FLOWTRACKER_ELEPHANT_MAX_PROMOTION_FILTERS; i++) { 7496 /* Flags */ 7497 size += sizeof(uint32); 7498 7499 /* Monitoring Interval */ 7500 size += sizeof(uint32); 7501 7502 /* Low rate threshold */ 7503 size += sizeof(uint32); 7504 7505 /* High rate threshold */ 7506 size += sizeof(uint32); 7507 7508 /* Size threshold upper */ 7509 size += sizeof(uint32); 7510 7511 /* Size threshold lower */ 7512 size += sizeof(uint32); 7513 } 7514 7515 /* Flags */ 7516 size += sizeof(uint32); 7517 7518 /* Monitoring Interval */ 7519 size += sizeof(uint32); 7520 7521 /* Low rate threshold */ 7522 size += sizeof(uint32); 7523 7524 /* High rate threshold */ 7525 size += sizeof(uint32); 7526 7527 /* Size threshold upper */ 7528 size += sizeof(uint32); 7529 7530 /* Size threshold lower */ 7531 size += sizeof(uint32); 7532 7533 /* Multiply by number of elephant profiles */ 7534 size *= BCM_INT_FT_MAX_ELEPHANT_PROFILES; 7535 7536 return size; 7537 } 7538 7539 /* 7540 * Function: 7541 * _bcm_th_ft_scache_v0_elph_prof_sync 7542 * Purpose: 7543 * Sync Flowtracker elephant profile data to scache v0 7544 * Parameters: 7545 * unit - (IN) Device unit number 7546 * scache - (IN) Pointer to current scache location 7547 * Returns: 7548 * BCM_E_XXX 7549 */ 7550 STATIC void 7551 _bcm_th_ft_scache_v0_elph_prof_sync(int unit, uint8 **scache) 7552 { 7553 int i, j; 7554 uint32 u32_h, u32_l; 7555 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 7556 _bcm_int_ft_elph_profile_info_t *elph_profile_list = ft_elph_profile_info_list[unit]; 7557 _bcm_int_ft_elph_profile_info_t *elph = NULL; 7558 bcm_flowtracker_elephant_filter_t *filter = NULL; 7559 7560 if (!ft_info->elph_mode) { 7561 return; 7562 } 7563 7564 for (i = BCM_INT_FT_ELPH_PROFILE_START_ID; i <= BCM_INT_FT_ELPH_PROFILE_END_ID; i++) { 7565 elph = &(elph_profile_list[i]); 7566 7567 /* Profile Id */ 7568 FT_SCACHE_WRITE(*scache, i, uint8); 7569 7570 if (elph->id == i) { 7571 /* Profile exists, set in_use = 1 */ 7572 FT_SCACHE_WRITE(*scache, 1, uint8); 7573 } else { 7574 /* Profile does not exist, set in_use = 0 */ 7575 FT_SCACHE_WRITE(*scache, 0, uint8); 7576 continue; 7577 } 7578 7579 /* Num promotion filters */ 7580 FT_SCACHE_WRITE(*scache, elph->profile.num_promotion_filters, uint8); 7581 7582 for (j = 0; j < elph->profile.num_promotion_filters; j++) { 7583 filter = &(elph->profile.promotion_filters[j]); 7584 7585 /* Flags */ 7586 FT_SCACHE_WRITE(*scache, filter->flags, uint32); 7587 7588 /* Monitoring Interval */ 7589 FT_SCACHE_WRITE(*scache, filter->monitor_interval_usecs, uint32); 7590 7591 /* Low rate threshold */ 7592 FT_SCACHE_WRITE(*scache, filter->rate_low_threshold_kbits_sec, uint32); 7593 7594 /* High rate threshold */ 7595 FT_SCACHE_WRITE(*scache, filter->rate_high_threshold_kbits_sec, uint32); 7596 7597 /* Size threshold */ 7598 COMPILER_64_TO_32_HI(u32_h, filter->size_threshold_bytes); 7599 COMPILER_64_TO_32_LO(u32_l, filter->size_threshold_bytes); 7600 FT_SCACHE_WRITE(*scache, u32_h, uint32); 7601 FT_SCACHE_WRITE(*scache, u32_l, uint32); 7602 } 7603 7604 filter = &(elph->profile.demotion_filter); 7605 7606 /* Flags */ 7607 FT_SCACHE_WRITE(*scache, filter->flags, uint32); 7608 7609 /* Monitoring Interval */ 7610 FT_SCACHE_WRITE(*scache, filter->monitor_interval_usecs, uint32); 7611 7612 /* Low rate threshold */ 7613 FT_SCACHE_WRITE(*scache, filter->rate_low_threshold_kbits_sec, uint32); 7614 7615 /* High rate threshold */ 7616 FT_SCACHE_WRITE(*scache, filter->rate_high_threshold_kbits_sec, uint32); 7617 7618 /* Size threshold */ 7619 COMPILER_64_TO_32_HI(u32_h, filter->size_threshold_bytes); 7620 COMPILER_64_TO_32_LO(u32_l, filter->size_threshold_bytes); 7621 FT_SCACHE_WRITE(*scache, u32_h, uint32); 7622 FT_SCACHE_WRITE(*scache, u32_l, uint32); 7623 7624 } 7625 } 7626 7627 /* 7628 * Function: 7629 * _bcm_th_ft_scache_v0_elph_prof_recover 7630 * Purpose: 7631 * Recover Flowtracker elephant profile data from scache v0 7632 * Parameters: 7633 * unit - (IN) Device unit number 7634 * scache - (IN) Pointer to current scache location 7635 * Returns: 7636 * BCM_E_XXX 7637 */ 7638 STATIC int 7639 _bcm_th_ft_scache_v0_elph_prof_recover(int unit, uint8 **scache) 7640 { 7641 int i, j; 7642 int rv; 7643 uint8 in_use; 7644 uint32 u32_h, u32_l; 7645 uint16 profile_id; 7646 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 7647 _bcm_int_ft_elph_profile_info_t *elph_profile_list = ft_elph_profile_info_list[unit]; 7648 _bcm_int_ft_elph_profile_info_t *elph = NULL; 7649 bcm_flowtracker_elephant_filter_t *filter = NULL; 7650 7651 if (!ft_info->elph_mode) { 7652 return BCM_E_NONE; 7653 } 7654 7655 for (i = BCM_INT_FT_ELPH_PROFILE_START_ID; i <= BCM_INT_FT_ELPH_PROFILE_END_ID; i++) { 7656 elph = &(elph_profile_list[i]); 7657 7658 /* Profile Id */ 7659 FT_SCACHE_READ(*scache, profile_id, uint8); 7660 if (profile_id != i) { 7661 return BCM_E_INTERNAL; 7662 } 7663 7664 /* in_use */ 7665 FT_SCACHE_READ(*scache, in_use, uint8); 7666 if (in_use == 0) { 7667 continue; 7668 } 7669 7670 elph->id = i; 7671 7672 rv = shr_idxres_list_reserve(ft_info->elph_profile_pool, i, i); 7673 BCM_IF_ERROR_RETURN(rv); 7674 7675 /* Num promotion filters */ 7676 FT_SCACHE_READ(*scache, elph->profile.num_promotion_filters, uint8); 7677 if (elph->profile.num_promotion_filters > 7678 BCM_FLOWTRACKER_ELEPHANT_MAX_PROMOTION_FILTERS) { 7679 return BCM_E_INTERNAL; 7680 } 7681 7682 for (j = 0; j < elph->profile.num_promotion_filters; j++) { 7683 filter = &(elph->profile.promotion_filters[j]); 7684 7685 /* Flags */ 7686 FT_SCACHE_READ(*scache, filter->flags, uint32); 7687 7688 /* Monitoring Interval */ 7689 FT_SCACHE_READ(*scache, filter->monitor_interval_usecs, uint32); 7690 7691 /* Low rate threshold */ 7692 FT_SCACHE_READ(*scache, filter->rate_low_threshold_kbits_sec, uint32); 7693 7694 /* High rate threshold */ 7695 FT_SCACHE_READ(*scache, filter->rate_high_threshold_kbits_sec, uint32); 7696 7697 /* Size threshold */ 7698 FT_SCACHE_READ(*scache, u32_h, uint32); 7699 FT_SCACHE_READ(*scache, u32_l, uint32); 7700 COMPILER_64_SET(filter->size_threshold_bytes, u32_h, u32_l); 7701 } 7702 7703 filter = &(elph->profile.demotion_filter); 7704 7705 /* Flags */ 7706 FT_SCACHE_READ(*scache, filter->flags, uint32); 7707 7708 /* Monitoring Interval */ 7709 FT_SCACHE_READ(*scache, filter->monitor_interval_usecs, uint32); 7710 7711 /* Low rate threshold */ 7712 FT_SCACHE_READ(*scache, filter->rate_low_threshold_kbits_sec, uint32); 7713 7714 /* High rate threshold */ 7715 FT_SCACHE_READ(*scache, filter->rate_high_threshold_kbits_sec, uint32); 7716 7717 /* Size threshold */ 7718 FT_SCACHE_READ(*scache, u32_h, uint32); 7719 FT_SCACHE_READ(*scache, u32_l, uint32); 7720 COMPILER_64_SET(filter->size_threshold_bytes, u32_h, u32_l); 7721 } 7722 return BCM_E_NONE; 7723 } 7724 7725 /* 7726 * Function: 7727 * _bcm_th_ft_scache_v0_size_get 7728 * Purpose: 7729 * Get Flowtracker scache v0 size 7730 * Parameters: 7731 * unit - (IN) Device unit number 7732 * Returns: 7733 * Size required 7734 */ 7735 STATIC uint32 7736 _bcm_th_ft_scache_v0_size_get(int unit) 7737 { 7738 uint32 size = 0; 7739 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 7740 7741 /* Get global data size */ 7742 size += _bcm_th_ft_scache_v0_global_size_get(unit); 7743 7744 /* Get group data size */ 7745 size += _bcm_th_ft_scache_v0_group_size_get(unit); 7746 7747 /* Get collector data size */ 7748 if (ft_info->cfg_mode == SHR_FT_CFG_MODE_V1) { 7749 size += _bcm_th_ft_scache_v0_collector_size_get(unit); 7750 } 7751 7752 /* Get template data size */ 7753 size += _bcm_th_ft_scache_v0_template_size_get(unit); 7754 7755 /* Get template xmit data size */ 7756 size += _bcm_th_ft_scache_v0_template_xmit_size_get(unit); 7757 7758 /* Get elephant profile data size */ 7759 size += _bcm_th_ft_scache_v0_elph_prof_size_get(unit); 7760 7761 return size; 7762 } 7763 7764 /* 7765 * Function: 7766 * _bcm_th_ft_scache_v0_sync 7767 * Purpose: 7768 * Sync Flowtracker scache v0 7769 * Parameters: 7770 * unit - (IN) Device unit number 7771 * scache - (IN) Pointer to current scache location 7772 * Returns: 7773 * None 7774 */ 7775 STATIC void 7776 _bcm_th_ft_scache_v0_sync(int unit, uint8 **scache) 7777 { 7778 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 7779 7780 /* Sync global data */ 7781 _bcm_th_ft_scache_v0_global_sync(unit, scache); 7782 7783 /* Sync group data */ 7784 _bcm_th_ft_scache_v0_group_sync(unit, scache); 7785 7786 /* Sync collector data */ 7787 if (ft_info->cfg_mode == SHR_FT_CFG_MODE_V1) { 7788 _bcm_th_ft_scache_v0_collector_sync(unit, scache); 7789 } 7790 7791 /* Sync template data */ 7792 _bcm_th_ft_scache_v0_template_sync(unit, scache); 7793 7794 /* Sync template xmit data */ 7795 _bcm_th_ft_scache_v0_template_xmit_sync(unit, scache); 7796 7797 /* Sync elephant profile data */ 7798 _bcm_th_ft_scache_v0_elph_prof_sync(unit, scache); 7799 } 7800 7801 /* 7802 * Function: 7803 * _bcm_th_ft_scache_v0_recover 7804 * Purpose: 7805 * Recover Flowtracker scache v0 data 7806 * Parameters: 7807 * unit - (IN) Device unit number 7808 * scache - (IN) Pointer to current scache location 7809 * Returns: 7810 * BCM_E_XXX 7811 */ 7812 STATIC int 7813 _bcm_th_ft_scache_v0_recover(int unit, uint8 **scache) 7814 { 7815 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 7816 7817 /* Recover global data */ 7818 BCM_IF_ERROR_RETURN(_bcm_th_ft_scache_v0_global_recover(unit, scache)); 7819 7820 /* Recover group data */ 7821 BCM_IF_ERROR_RETURN(_bcm_th_ft_scache_v0_group_recover(unit, scache)); 7822 7823 /* Recover collector data */ 7824 if (ft_info->cfg_mode == SHR_FT_CFG_MODE_V1) { 7825 BCM_IF_ERROR_RETURN(_bcm_th_ft_scache_v0_collector_recover(unit, scache)); 7826 } 7827 7828 /* Recover template data */ 7829 BCM_IF_ERROR_RETURN(_bcm_th_ft_scache_v0_template_recover(unit, scache)); 7830 7831 /* Recover template xmit data */ 7832 BCM_IF_ERROR_RETURN(_bcm_th_ft_scache_v0_template_xmit_recover(unit, scache)); 7833 7834 /* Recover elephant profile data */ 7835 BCM_IF_ERROR_RETURN(_bcm_th_ft_scache_v0_elph_prof_recover(unit, scache)); 7836 7837 return BCM_E_NONE; 7838 } 7839 7840 /* 7841 * Function: 7842 * _bcm_th_ft_scache_v1_global_size_get 7843 * Purpose: 7844 * Get the size required to sync Flowtracker global data to scache v1 7845 * Parameters: 7846 * unit - (IN) Device unit number 7847 * Returns: 7848 * Required size 7849 */ 7850 STATIC uint32 7851 _bcm_th_ft_scache_v1_global_size_get(int unit) 7852 { 7853 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 7854 uint32 size = 0; 7855 int i, j; 7856 7857 /* Default group Id */ 7858 size += sizeof(uint16); 7859 7860 /* Maximum EM group */ 7861 size += sizeof(uint16); 7862 7863 /* EM group Mapping */ 7864 for (i = 0; i < SHR_FT_MAX_EM_GROUPS; i++) { 7865 for (j = 0; j < ft_info->num_pipes; ++j) { 7866 size += sizeof(int); 7867 } 7868 } 7869 7870 return size; 7871 } 7872 7873 /* 7874 * Function: 7875 * _bcm_th_ft_scache_v1_global_sync 7876 * Purpose: 7877 * Sync Flowtracker global data to scache v0 7878 * Parameters: 7879 * unit - (IN) Device unit number 7880 * scache - (IN) Pointer to current scache location 7881 * Returns: 7882 * BCM_E_XXX 7883 */ 7884 STATIC void 7885 _bcm_th_ft_scache_v1_global_sync(int unit, uint8 **scache) 7886 { 7887 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 7888 int i, j; 7889 7890 /* Default group ID */ 7891 FT_SCACHE_WRITE(*scache, ft_info->default_grp_id, uint16); 7892 7893 /* Maximum EM group */ 7894 FT_SCACHE_WRITE(*scache, SHR_FT_MAX_EM_GROUPS, uint16); 7895 7896 /* EM group Mapping */ 7897 for (i = 0; i < SHR_FT_MAX_EM_GROUPS; i++) { 7898 for (j = 0; j < ft_info->num_pipes; ++j) { 7899 FT_SCACHE_WRITE(*scache, ft_info->em_group_id_map[i][j], int); 7900 } 7901 } 7902 } 7903 7904 /* 7905 * Function: 7906 * _bcm_th_ft_scache_v1_global_recover 7907 * Purpose: 7908 * Recover Flowtracker global data from scache v0 7909 * Parameters: 7910 * unit - (IN) Device unit number 7911 * scache - (IN) Pointer to current scache location 7912 * Returns: 7913 * BCM_E_XXX 7914 */ 7915 STATIC int 7916 _bcm_th_ft_scache_v1_global_recover(int unit, uint8 **scache) 7917 { 7918 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 7919 int i, j; 7920 uint16 max_em_grp = 0; 7921 7922 /* Default group ID */ 7923 FT_SCACHE_READ(*scache, ft_info->default_grp_id, uint16); 7924 7925 /* Maximum EM group */ 7926 FT_SCACHE_READ(*scache, max_em_grp, uint16); 7927 7928 /* EM group Mapping */ 7929 for (i = 0; i < max_em_grp; i++) { 7930 for (j = 0; j < ft_info->num_pipes; ++j) { 7931 FT_SCACHE_READ(*scache, ft_info->em_group_id_map[i][j], int); 7932 } 7933 } 7934 7935 return BCM_E_NONE; 7936 } 7937 7938 /* 7939 * Function: 7940 * _bcm_th_ft_scache_v1_group_size_get 7941 * Purpose: 7942 * Get the size required to sync flow group data to scache v1 7943 * Parameters: 7944 * unit - (IN) Device unit number 7945 * Returns: 7946 * Required size 7947 */ 7948 STATIC uint32 7949 _bcm_th_ft_scache_v1_group_size_get(int unit) 7950 { 7951 uint32 size = 0; 7952 int i; 7953 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 7954 7955 /* Group in_use */ 7956 size += sizeof(uint8); 7957 7958 /* Export profile Id */ 7959 size += sizeof(int); 7960 7961 /* Export triggers */ 7962 size += sizeof(uint32); 7963 7964 for (i = 0; i < ft_info->num_pipes; i++) { 7965 /* Field group */ 7966 size += sizeof(bcm_field_group_t); 7967 } 7968 7969 /* Number of Tracking Params */ 7970 size += sizeof(int); 7971 7972 for (i = 0; i < SHR_FT_MAX_TP; i++) { 7973 /* Flags for tracking parameters. */ 7974 size += sizeof(uint32); 7975 7976 /* Type of tracking parameter. */ 7977 size += sizeof(uint16); 7978 7979 /* UDF Id */ 7980 size += sizeof(int); 7981 } 7982 7983 /* Multiply by number of groups */ 7984 size *= ft_info->max_flow_groups; 7985 7986 return (size); 7987 } 7988 7989 /* 7990 * Function: 7991 * _bcm_th_ft_scache_v1_group_sync 7992 * Purpose: 7993 * Sync group data with scache v1 7994 * Parameters: 7995 * unit - (IN) Device unit number 7996 * scache - (IN) Pointer to current scache location 7997 * Returns: 7998 * BCM_E_XXX 7999 */ 8000 STATIC void 8001 _bcm_th_ft_scache_v1_group_sync(int unit, uint8 **scache) 8002 { 8003 int i, j; 8004 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 8005 _bcm_int_ft_flow_group_info_t *flow_group_list = ft_flow_group_info_list[unit]; 8006 _bcm_int_ft_flow_group_info_t *group = NULL; 8007 8008 for (i = BCM_INT_FT_GROUP_START_ID; 8009 i < (ft_info->max_flow_groups + BCM_INT_FT_GROUP_START_ID); 8010 i++) { 8011 group = &(flow_group_list[i]); 8012 8013 if (group->flow_group_id == i) { 8014 /* Group exists, set in_use = 1 */ 8015 FT_SCACHE_WRITE(*scache, 1, uint8); 8016 } else { 8017 /* Group does not exist, set in_use = 0 */ 8018 FT_SCACHE_WRITE(*scache, 0, uint8); 8019 continue; 8020 } 8021 8022 /* Export profile Id */ 8023 FT_SCACHE_WRITE(*scache, group->export_profile_id, int); 8024 8025 /* Export triggers */ 8026 FT_SCACHE_WRITE(*scache, group->export_trigger, uint32); 8027 8028 /* Field group */ 8029 for (j = 0; j < ft_info->num_pipes; ++j) { 8030 FT_SCACHE_WRITE(*scache, group->field_group[j], int); 8031 } 8032 8033 /* Number of Tracking Params */ 8034 FT_SCACHE_WRITE(*scache, group->num_tracking_params, int); 8035 8036 for (j = 0; j < group->num_tracking_params; j++) { 8037 /* Flags for tracking parameters. */ 8038 FT_SCACHE_WRITE(*scache, group->tracking_params[j].flags, uint32); 8039 8040 /* Type of tracking parameter. */ 8041 FT_SCACHE_WRITE(*scache, group->tracking_params[j].param, uint16); 8042 8043 /* UDF Id */ 8044 FT_SCACHE_WRITE(*scache, group->tracking_params[j].udf_id, int); 8045 } 8046 } 8047 } 8048 8049 /* 8050 * Function: 8051 * _bcm_th_ft_scache_v1_group_recover 8052 * Purpose: 8053 * Recover Flowtracker group data from scache v1 8054 * Parameters: 8055 * unit - (IN) Device unit number 8056 * scache - (IN) Pointer to current scache location 8057 * Returns: 8058 * BCM_E_XXX 8059 */ 8060 STATIC int 8061 _bcm_th_ft_scache_v1_group_recover(int unit, uint8 **scache) 8062 { 8063 int i, j; 8064 uint8 in_use; 8065 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 8066 _bcm_int_ft_flow_group_info_t *flow_group_list = ft_flow_group_info_list[unit]; 8067 _bcm_int_ft_flow_group_info_t *group = NULL; 8068 bcm_collector_export_profile_t export_profile_info; 8069 8070 for (i = BCM_INT_FT_GROUP_START_ID; 8071 i < (ft_info->max_flow_groups + BCM_INT_FT_GROUP_START_ID); 8072 i++) { 8073 group = &(flow_group_list[i]); 8074 8075 /* in_use */ 8076 FT_SCACHE_READ(*scache, in_use, uint8); 8077 if (in_use == 0) { 8078 continue; 8079 } 8080 8081 /* Export profile Id */ 8082 FT_SCACHE_READ(*scache, group->export_profile_id, int); 8083 if (group->export_profile_id != 8084 BCM_INT_COLLECTOR_INVALID_EXPORT_PROFILE_ID) { 8085 BCM_IF_ERROR_RETURN( 8086 _bcm_esw_collector_export_profile_ref_count_update(unit, 8087 group->export_profile_id, 8088 1)); 8089 } 8090 8091 if (ft_info->cfg_mode >= SHR_FT_CFG_MODE_V2) { 8092 bcm_collector_export_profile_t_init(&export_profile_info); 8093 /* Get the export profile to get the wire format */ 8094 BCM_IF_ERROR_RETURN( 8095 bcm_esw_collector_export_profile_get(unit, 8096 group->export_profile_id, 8097 &export_profile_info)); 8098 8099 if (group->collector_id != _BCM_FT_WB_INVALID_COLLECTOR_ID) { 8100 if (export_profile_info.wire_format == bcmCollectorWireFormatIpfix) { 8101 BCM_IF_ERROR_RETURN( 8102 _bcm_esw_collector_user_update(unit, 8103 group->collector_id, _BCM_COLLECTOR_EXPORT_APP_FT_IPFIX)); 8104 } else { 8105 BCM_IF_ERROR_RETURN( 8106 _bcm_esw_collector_user_update(unit, 8107 group->collector_id, _BCM_COLLECTOR_EXPORT_APP_FT_PROTOBUF)); 8108 } 8109 } 8110 } 8111 8112 /* Export triggers */ 8113 FT_SCACHE_READ(*scache, group->export_trigger, uint32); 8114 8115 /* Field group */ 8116 for (j = 0; j < ft_info->num_pipes; ++j) { 8117 FT_SCACHE_READ(*scache, group->field_group[j], int); 8118 } 8119 8120 /* Number of Tracking Params */ 8121 FT_SCACHE_READ(*scache, group->num_tracking_params, int); 8122 8123 /* Allocate memory for the Tracking Params list */ 8124 if (group->num_tracking_params > 0) { 8125 _BCM_FT_ALLOC(group->tracking_params, 8126 bcm_flowtracker_tracking_param_info_t, 8127 (group->num_tracking_params * 8128 sizeof(bcm_flowtracker_tracking_param_info_t)), 8129 "Group Tracking Params list"); 8130 if (group->tracking_params == NULL) { 8131 return BCM_E_MEMORY; 8132 } 8133 } 8134 8135 for (j = 0; j < group->num_tracking_params; j++) { 8136 /* Flags for tracking parameters. */ 8137 FT_SCACHE_READ(*scache, group->tracking_params[j].flags, uint32); 8138 8139 /* Type of tracking parameter. */ 8140 FT_SCACHE_READ(*scache, group->tracking_params[j].param, uint16); 8141 8142 /* UDF Id */ 8143 FT_SCACHE_READ(*scache, group->tracking_params[j].udf_id, int); 8144 } 8145 } 8146 8147 return BCM_E_NONE; 8148 } 8149 8150 /* 8151 * Function: 8152 * _bcm_th_ft_scache_v1_collector_size_get 8153 * Purpose: 8154 * Get the size required to sync collector data to scache v1 8155 * Parameters: 8156 * unit - (IN) Device unit number 8157 * Returns: 8158 * Required size 8159 */ 8160 STATIC uint32 8161 _bcm_th_ft_scache_v1_collector_size_get(int unit) 8162 { 8163 uint32 size = 0; 8164 8165 /* Collector Internal Id */ 8166 size += sizeof(int); 8167 8168 size *= BCM_INT_COLLECTOR_MAX_COLLECTORS; 8169 8170 return size; 8171 } 8172 8173 /* 8174 * Function: 8175 * _bcm_th_ft_scache_v1_collector_sync 8176 * Purpose: 8177 * Sync collector data with scache v1 8178 * Parameters: 8179 * unit - (IN) Device unit number 8180 * scache - (IN) Pointer to current scache location 8181 * Returns: 8182 * BCM_E_XXX 8183 */ 8184 STATIC void 8185 _bcm_th_ft_scache_v1_collector_sync(int unit, uint8 **scache) 8186 { 8187 int i; 8188 _bcm_int_ft_v2_collector_info_t *collector_list = ft_v2_collector_info_list[unit]; 8189 _bcm_int_ft_v2_collector_info_t *collector = NULL; 8190 8191 /* Start & End Id */ 8192 FT_SCACHE_WRITE(*scache, BCM_INT_COLLECTOR_COLLECTOR_START_ID, uint16); 8193 FT_SCACHE_WRITE(*scache, BCM_INT_COLLECTOR_COLLECTOR_END_ID, uint16); 8194 8195 for (i = BCM_INT_COLLECTOR_COLLECTOR_START_ID; 8196 i <= BCM_INT_COLLECTOR_COLLECTOR_END_ID; 8197 i++) { 8198 8199 collector = &(collector_list[i]); 8200 8201 /* Collector Id */ 8202 FT_SCACHE_WRITE(*scache, i, int); 8203 8204 if (collector->int_id == 0) { 8205 /* Collector exists, set in_use = 0 */ 8206 FT_SCACHE_WRITE(*scache, 0, uint8); 8207 continue; 8208 } 8209 /* Collector exists, set in_use = 1 */ 8210 FT_SCACHE_WRITE(*scache, 1, uint8); 8211 8212 /* Collector Internal id */ 8213 FT_SCACHE_WRITE(*scache, collector->int_id, int); 8214 } 8215 } 8216 8217 /* 8218 * Function: 8219 * _bcm_th_ft_scache_v1_collector_recover 8220 * Purpose: 8221 * Recover Flowtracker group data from scache v1 8222 * Parameters: 8223 * unit - (IN) Device unit number 8224 * scache - (IN) Pointer to current scache location 8225 * Returns: 8226 * BCM_E_XXX 8227 */ 8228 STATIC int 8229 _bcm_th_ft_scache_v1_collector_recover(int unit, uint8 **scache) 8230 { 8231 int i; 8232 uint8 in_use; 8233 uint16 start_id, end_id; 8234 int collector_id; 8235 int rv = BCM_E_NONE; 8236 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 8237 _bcm_int_ft_v2_collector_info_t *collector_list = ft_v2_collector_info_list[unit]; 8238 _bcm_int_ft_v2_collector_info_t *collector = NULL; 8239 8240 /* Start & end Id */ 8241 FT_SCACHE_READ(*scache, start_id, uint16); 8242 FT_SCACHE_READ(*scache, end_id, uint16); 8243 if ((start_id != BCM_INT_COLLECTOR_COLLECTOR_START_ID) || 8244 (end_id != BCM_INT_COLLECTOR_COLLECTOR_END_ID)) { 8245 return BCM_E_PARAM; 8246 } 8247 8248 for (i = BCM_INT_COLLECTOR_COLLECTOR_START_ID; 8249 i <= BCM_INT_COLLECTOR_COLLECTOR_END_ID; 8250 i++) { 8251 8252 collector = &(collector_list[i]); 8253 8254 /* Collector Id */ 8255 FT_SCACHE_READ(*scache, collector_id, int); 8256 if (collector_id != i) { 8257 return BCM_E_INTERNAL; 8258 } 8259 8260 /* in_use */ 8261 FT_SCACHE_READ(*scache, in_use, uint8); 8262 if (in_use == 0) { 8263 continue; 8264 } 8265 8266 /* Collector Internal id */ 8267 FT_SCACHE_READ(*scache, collector->int_id, int); 8268 8269 rv = shr_idxres_list_reserve(ft_info->collector_pool, 8270 collector->int_id, collector->int_id); 8271 BCM_IF_ERROR_RETURN(rv); 8272 } 8273 8274 return BCM_E_NONE; 8275 } 8276 8277 /* 8278 * Function: 8279 * _bcm_th_ft_scache_v1_export_profile_size_get 8280 * Purpose: 8281 * Get the size required to sync export_profile data to scache v1 8282 * Parameters: 8283 * unit - (IN) Device unit number 8284 * Returns: 8285 * Required size 8286 */ 8287 STATIC uint32 8288 _bcm_th_ft_scache_v1_export_profile_size_get(int unit) 8289 { 8290 uint32 size = 0; 8291 8292 /* Export_Profile Internal Id */ 8293 size += sizeof(int); 8294 8295 size *= BCM_INT_COLLECTOR_MAX_EXPORT_PROFILES; 8296 8297 return size; 8298 } 8299 8300 /* 8301 * Function: 8302 * _bcm_th_ft_scache_v1_export_profile_sync 8303 * Purpose: 8304 * Sync export_profile data with scache v1 8305 * Parameters: 8306 * unit - (IN) Device unit number 8307 * scache - (IN) Pointer to current scache location 8308 * Returns: 8309 * BCM_E_XXX 8310 */ 8311 STATIC void 8312 _bcm_th_ft_scache_v1_export_profile_sync(int unit, uint8 **scache) 8313 { 8314 int i; 8315 _bcm_int_ft_v2_export_profile_info_t *export_profile_list = ft_v2_export_profile_info_list[unit]; 8316 _bcm_int_ft_v2_export_profile_info_t *export_profile = NULL; 8317 8318 /* Start & End Id */ 8319 FT_SCACHE_WRITE(*scache, BCM_INT_COLLECTOR_EXPORT_PROFILE_START_ID, uint16); 8320 FT_SCACHE_WRITE(*scache, BCM_INT_COLLECTOR_EXPORT_PROFILE_END_ID, uint16); 8321 8322 for (i = BCM_INT_COLLECTOR_EXPORT_PROFILE_START_ID; 8323 i <= BCM_INT_COLLECTOR_EXPORT_PROFILE_END_ID; 8324 i++) { 8325 8326 export_profile = &(export_profile_list[i]); 8327 8328 /* Export_Profile Id */ 8329 FT_SCACHE_WRITE(*scache, i, int); 8330 8331 if (export_profile->int_id == 0) { 8332 /* Export_Profile exists, set in_use = 0 */ 8333 FT_SCACHE_WRITE(*scache, 0, uint8); 8334 continue; 8335 } 8336 /* Export_Profile exists, set in_use = 1 */ 8337 FT_SCACHE_WRITE(*scache, 1, uint8); 8338 8339 /* Export_Profile Internal id */ 8340 FT_SCACHE_WRITE(*scache, export_profile->int_id, int); 8341 } 8342 } 8343 8344 /* 8345 * Function: 8346 * _bcm_th_ft_scache_v1_export_profile_recover 8347 * Purpose: 8348 * Recover Flowtracker group data from scache v1 8349 * Parameters: 8350 * unit - (IN) Device unit number 8351 * scache - (IN) Pointer to current scache location 8352 * Returns: 8353 * BCM_E_XXX 8354 */ 8355 STATIC int 8356 _bcm_th_ft_scache_v1_export_profile_recover(int unit, uint8 **scache) 8357 { 8358 int i; 8359 uint8 in_use; 8360 int rv = BCM_E_NONE; 8361 uint16 start_id, end_id; 8362 int export_profile_id; 8363 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 8364 _bcm_int_ft_v2_export_profile_info_t *export_profile_list = ft_v2_export_profile_info_list[unit]; 8365 _bcm_int_ft_v2_export_profile_info_t *export_profile = NULL; 8366 8367 /* Start & end Id */ 8368 FT_SCACHE_READ(*scache, start_id, uint16); 8369 FT_SCACHE_READ(*scache, end_id, uint16); 8370 if ((start_id != BCM_INT_COLLECTOR_EXPORT_PROFILE_START_ID) || 8371 (end_id != BCM_INT_COLLECTOR_EXPORT_PROFILE_END_ID)) { 8372 return BCM_E_PARAM; 8373 } 8374 8375 for (i = BCM_INT_COLLECTOR_EXPORT_PROFILE_START_ID; 8376 i <= BCM_INT_COLLECTOR_EXPORT_PROFILE_END_ID; 8377 i++) { 8378 8379 export_profile = &(export_profile_list[i]); 8380 8381 /* Export_Profile Id */ 8382 FT_SCACHE_READ(*scache, export_profile_id, int); 8383 if (export_profile_id != i) { 8384 return BCM_E_INTERNAL; 8385 } 8386 8387 /* in_use */ 8388 FT_SCACHE_READ(*scache, in_use, uint8); 8389 if (in_use == 0) { 8390 continue; 8391 } 8392 8393 /* Export_Profile Internal id */ 8394 FT_SCACHE_READ(*scache, export_profile->int_id, int); 8395 8396 rv = shr_idxres_list_reserve(ft_info->export_profile_pool, 8397 export_profile->int_id, export_profile->int_id); 8398 BCM_IF_ERROR_RETURN(rv); 8399 } 8400 8401 return BCM_E_NONE; 8402 } 8403 8404 /* 8405 * Function: 8406 * _bcm_th_ft_scache_v1_size_get 8407 * Purpose: 8408 * Get Flowtracker scache v1 size 8409 * Parameters: 8410 * unit - (IN) Device unit number 8411 * Returns: 8412 * Size required 8413 */ 8414 STATIC uint32 8415 _bcm_th_ft_scache_v1_size_get(int unit) 8416 { 8417 uint32 size = 0; 8418 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 8419 8420 if (ft_info->cfg_mode == SHR_FT_CFG_MODE_V1) { 8421 return 0; 8422 } 8423 8424 /* Get global data size */ 8425 size += _bcm_th_ft_scache_v1_global_size_get(unit); 8426 8427 /* Group data */ 8428 size += _bcm_th_ft_scache_v1_group_size_get(unit); 8429 8430 /* Collector data */ 8431 size += _bcm_th_ft_scache_v1_collector_size_get(unit); 8432 8433 /* Export profile data */ 8434 size += _bcm_th_ft_scache_v1_export_profile_size_get(unit); 8435 8436 return size; 8437 } 8438 8439 /* 8440 * Function: 8441 * _bcm_th_ft_scache_v1_sync 8442 * Purpose: 8443 * Sync Flowtracker scache v1 8444 * Parameters: 8445 * unit - (IN) Device unit number 8446 * scache - (IN) Pointer to current scache location 8447 * Returns: 8448 * None 8449 */ 8450 STATIC void 8451 _bcm_th_ft_scache_v1_sync(int unit, uint8 **scache) 8452 { 8453 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 8454 8455 if (ft_info->cfg_mode == SHR_FT_CFG_MODE_V1) { 8456 return; 8457 } 8458 8459 /* Sync global data */ 8460 _bcm_th_ft_scache_v1_global_sync(unit, scache); 8461 8462 /* Sync group data */ 8463 _bcm_th_ft_scache_v1_group_sync(unit, scache); 8464 8465 /* Sync collector data */ 8466 _bcm_th_ft_scache_v1_collector_sync(unit, scache); 8467 8468 /* Sync export_profile data */ 8469 _bcm_th_ft_scache_v1_export_profile_sync(unit, scache); 8470 } 8471 8472 /* 8473 * Function: 8474 * _bcm_th_ft_scache_v1_recover 8475 * Purpose: 8476 * Recover Flowtracker scache v1 data 8477 * Parameters: 8478 * unit - (IN) Device unit number 8479 * scache - (IN) Pointer to current scache location 8480 * Returns: 8481 * BCM_E_XXX 8482 */ 8483 STATIC int 8484 _bcm_th_ft_scache_v1_recover(int unit, uint8 **scache) 8485 { 8486 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 8487 8488 if (ft_info->cfg_mode == SHR_FT_CFG_MODE_V1) { 8489 return BCM_E_NONE; 8490 } 8491 8492 /* Recover global data */ 8493 BCM_IF_ERROR_RETURN(_bcm_th_ft_scache_v1_global_recover(unit, scache)); 8494 8495 /* Recover group data */ 8496 BCM_IF_ERROR_RETURN(_bcm_th_ft_scache_v1_group_recover(unit, scache)); 8497 8498 /* Recover collector data */ 8499 BCM_IF_ERROR_RETURN(_bcm_th_ft_scache_v1_collector_recover(unit, scache)); 8500 8501 /* Recover export_profile data */ 8502 BCM_IF_ERROR_RETURN(_bcm_th_ft_scache_v1_export_profile_recover(unit, scache)); 8503 8504 return BCM_E_NONE; 8505 } 8506 8507 8508 /* 8509 * Function: 8510 * _bcm_th_ft_scache_alloc 8511 * Purpose: 8512 * Flowtracker WB scache alloc 8513 * Parameters: 8514 * unit - (IN) Unit number. 8515 * create - (IN) 1 - Create, 0 - Realloc 8516 * Returns: 8517 * BCM_E_XXX 8518 * Notes: 8519 */ 8520 STATIC int _bcm_th_ft_scache_alloc(int unit, int create) 8521 { 8522 uint32 cur_size = 0; 8523 uint32 rqd_size = 0; 8524 int rv = BCM_E_NONE; 8525 soc_scache_handle_t scache_handle; 8526 uint8 *scache = NULL; 8527 8528 rqd_size += _bcm_th_ft_scache_v0_size_get(unit); 8529 rqd_size += _bcm_th_ft_scache_v1_size_get(unit); 8530 8531 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FLOWTRACKER, 0); 8532 8533 if (create) { 8534 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 1, rqd_size, 8535 &scache, BCM_WB_FT_DEFAULT_VERSION, NULL); 8536 BCM_IF_ERROR_RETURN(rv); 8537 } else { 8538 /* Get current size */ 8539 rv = soc_scache_ptr_get(unit, scache_handle, &scache, &cur_size); 8540 SOC_IF_ERROR_RETURN(rv); 8541 8542 if (rqd_size > cur_size) { 8543 /* Request the extra size */ 8544 rv = soc_scache_realloc(unit, scache_handle, rqd_size - cur_size); 8545 SOC_IF_ERROR_RETURN(rv); 8546 } 8547 } 8548 8549 return BCM_E_NONE; 8550 } 8551 8552 /* 8553 * Function: 8554 * _bcm_th_ft_sync 8555 * Purpose: 8556 * Warmboot scache sync 8557 * Parameters: 8558 * unit - (IN) Unit number. 8559 * Returns: 8560 * BCM_E_XXX 8561 * Notes: 8562 */ 8563 int _bcm_th_ft_sync(int unit) 8564 { 8565 int stable_size; 8566 soc_scache_handle_t scache_handle; 8567 uint8 *scache = NULL; 8568 _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit); 8569 8570 if (ft_info == NULL) { 8571 return BCM_E_NONE; 8572 } 8573 8574 /* Get FT module storage size. */ 8575 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 8576 8577 /* If level 2 store is not configured return from here. */ 8578 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) { 8579 return BCM_E_NONE; 8580 } 8581 8582 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FLOWTRACKER, 0); 8583 BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0, 8584 &scache, BCM_WB_FT_DEFAULT_VERSION, 8585 NULL)); 8586 if (NULL == scache) { 8587 return BCM_E_INTERNAL; 8588 } 8589 8590 /* Sync FT scache */ 8591 _bcm_th_ft_scache_v0_sync(unit, &scache); 8592 _bcm_th_ft_scache_v1_sync(unit, &scache); 8593 8594 return BCM_E_NONE; 8595 } 8596 8597 /* 8598 * Function: 8599 * _bcm_th_ft_wb_recover 8600 * Purpose: 8601 * Flowtracker WB recovery 8602 * Parameters: 8603 * unit - (IN) Unit number. 8604 * Returns: 8605 * BCM_E_XXX 8606 * Notes: 8607 */ 8608 STATIC int _bcm_th_ft_wb_recover(int unit) 8609 { 8610 int stable_size; /* Secondary storage size. */ 8611 uint8 *scache = NULL; 8612 soc_scache_handle_t scache_handle; 8613 int rv = BCM_E_NONE; 8614 uint16 recovered_ver = 0; 8615 8616 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 8617 8618 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) { 8619 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FLOWTRACKER, 0); 8620 8621 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0, 8622 &scache, BCM_WB_FT_DEFAULT_VERSION, 8623 &recovered_ver); 8624 if (BCM_E_NOT_FOUND == rv) { 8625 /* Upgrading from SDK release that does not have warmboot state */ 8626 rv = _bcm_th_ft_scache_alloc(unit, 1); 8627 return rv; 8628 } else if (BCM_FAILURE(rv)) { 8629 return rv; 8630 } 8631 8632 if (NULL == scache) { 8633 return BCM_E_NOT_FOUND; 8634 } 8635 } else { 8636 return BCM_E_NONE; 8637 } 8638 8639 /* Scache recovery */ 8640 BCM_IF_ERROR_RETURN(_bcm_th_ft_scache_v0_recover(unit, &scache)); 8641 if (recovered_ver >= BCM_WB_FT_VERSION_1_1) { 8642 BCM_IF_ERROR_RETURN(_bcm_th_ft_scache_v1_recover(unit, &scache)); 8643 } 8644 8645 /* Realloc any extra scache that may be needed */ 8646 BCM_IF_ERROR_RETURN(_bcm_th_ft_scache_alloc(unit, 0)); 8647 8648 return rv; 8649 } 8650 #endif /* BCM_WARM_BOOT_SUPPORT */ 8651 #else /* INCLUDE_FLOWTRACKER */ 8652 int _bcm_th_ft_not_empty; 8653 #endif /* INCLUDE_FLOWTRACKER */