openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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 */