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

ft_check.c (45785B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        ft_group.c
      8  * Purpose:     The purpose of this file is to set flow tracker group methods.
      9  * Requires:
     10  */
     11 
     12 #include <bcm_int/esw/flowtracker/ft_group.h>
     13 
     14 #if defined(BCM_FLOWTRACKER_SUPPORT)
     15 
     16 /* External Common Group software State. */
     17 extern bcmi_ft_group_sw_info_t **bcmi_ft_group_sw_state[BCM_MAX_NUM_UNITS];
     18 
     19 bcmi_ft_flowchecker_sw_state_t bcmi_ft_flowchecker_state[BCM_MAX_NUM_UNITS];
     20 
     21 /*
     22  * Function:
     23  *     bcmi_ft_flowchecker_get_free_index
     24  * Purpose:
     25  *     Get gree index of the flowtracker check element.
     26  * Description:
     27  *     At present the checks are numbered equal to group
     28  *     number but there is a provision to increase it to any
     29  *     number by adding them to the linked list.
     30  *     But it may not be required as checks can be shared
     31  *     among various groups and therefore we may not need
     32  *     exlicit check for each group.
     33  * Parameters:
     34  *     unit - (IN) BCM device id
     35  *
     36  * Returns:
     37  *     iBCM_E_XXX.
     38  */
     39 int
     40 bcmi_ft_flowchecker_get_free_index(int unit, int *index)
     41 {
     42 
     43     int num_flowcheckers = 0;
     44     soc_mem_t mem;
     45     int i = 0;
     46 
     47     /* assign the memory. */
     48     mem = BSC_KG_GROUP_TABLEm;
     49 
     50     /* Total number of groups in device. */
     51     num_flowcheckers = soc_mem_index_max(unit, mem);
     52 
     53     if (*index != -1) {
     54         i = *index;
     55         num_flowcheckers = *index;
     56     }
     57 
     58     for (; i<=num_flowcheckers; i++) {
     59         if (!(SHR_BITGET(BCMI_FT_FLOWCHECKER_BITMAP(unit), i))) {
     60             /* Got the free index. use it. */
     61             SHR_BITSET(BCMI_FT_FLOWCHECKER_BITMAP(unit), i);
     62             *index = i;
     63             return BCM_E_NONE;
     64         }
     65     }
     66 
     67     return BCM_E_RESOURCE;
     68 }
     69 
     70 /*
     71  * Function:
     72  *    bcmi_ft_flowchecker_init
     73  * Purpose:
     74  *    Initialize software state of flowtracker checks.
     75  * Parameters:
     76  *     unit - (IN) BCM device id
     77  *
     78  * Returns:
     79  *     BCM_E_XXX.
     80  */
     81 
     82 int bcmi_ft_flowchecker_init(int unit)
     83 {
     84 
     85     int num_flowcheckers = 0;
     86     soc_mem_t mem;
     87     mem = BSC_KG_GROUP_TABLEm;
     88 
     89     /* Total number of groups in device. */
     90     num_flowcheckers = soc_mem_index_count(unit, mem);
     91 
     92     /* Allocate space for the flowchecker database structures. */
     93     BCMI_FT_FLOWCHECKER_STATE(unit) = (bcmi_flowtracker_flowchecker_info_t **)
     94         sal_alloc((num_flowcheckers *
     95             sizeof(bcmi_flowtracker_flowchecker_info_t *)),
     96         "flowtracker group sw state");
     97 
     98     if (BCMI_FT_FLOWCHECKER_STATE(unit) == NULL) {
     99         return BCM_E_MEMORY;
    100     }
    101     sal_memset(BCMI_FT_FLOWCHECKER_STATE(unit), 0,
    102         (num_flowcheckers * sizeof(bcmi_ft_flowchecker_sw_state_t *)));
    103 
    104     /* allocate Group bitmap for whole chip. */
    105     BCMI_FT_FLOWCHECKER_BITMAP(unit) =
    106         sal_alloc(SHR_BITALLOCSIZE(num_flowcheckers),
    107         "ft_flowchecker_bitmap");
    108 
    109     if (BCMI_FT_FLOWCHECKER_BITMAP(unit) == NULL) {
    110         return BCM_E_MEMORY;
    111     }
    112 
    113     sal_memset(BCMI_FT_FLOWCHECKER_BITMAP(unit), 0,
    114                SHR_BITALLOCSIZE(num_flowcheckers));
    115 
    116     /* Allocate memory for refcounting the flowchecker indexes. */
    117     bcmi_ft_flowchecker_state[unit].fc_idx_refcount = (uint32 *)
    118         sal_alloc((num_flowcheckers * sizeof(uint32)),
    119         "flowchecker refcount state");
    120 
    121     if (bcmi_ft_flowchecker_state[unit].fc_idx_refcount == NULL) {
    122         return BCM_E_MEMORY;
    123     }
    124 
    125     sal_memset(bcmi_ft_flowchecker_state[unit].fc_idx_refcount, 0,
    126         (num_flowcheckers * sizeof(uint32)));
    127 
    128     /* Reserve the 0th index. */
    129 /*    SHR_BITSET(BCMI_FT_FLOWCHECKER_BITMAP(unit), 0);*/
    130 
    131     return BCM_E_NONE;
    132 }
    133 
    134 /*
    135  * Function:
    136  *    bcmi_ft_flowchecker_cleanup
    137  * Purpose:
    138  *    Cleanup software state of flowtracker checks.
    139  * Parameters:
    140  *     unit - (IN) BCM device id
    141  *
    142  * Returns:
    143  *     None.
    144  */
    145 
    146 void
    147 bcmi_ft_flowchecker_cleanup(int unit)
    148 {
    149 
    150     if (bcmi_ft_flowchecker_state[unit].fc_idx_refcount != NULL) {
    151         sal_free(bcmi_ft_flowchecker_state[unit].fc_idx_refcount);
    152         bcmi_ft_flowchecker_state[unit].fc_idx_refcount = NULL;
    153     }
    154 
    155     if (BCMI_FT_FLOWCHECKER_BITMAP(unit) != NULL) {
    156         sal_free(BCMI_FT_FLOWCHECKER_BITMAP(unit));
    157         BCMI_FT_FLOWCHECKER_BITMAP(unit) = NULL;
    158     }
    159 
    160     if (BCMI_FT_FLOWCHECKER_STATE(unit) != NULL) {
    161         sal_free(BCMI_FT_FLOWCHECKER_STATE(unit));
    162         BCMI_FT_FLOWCHECKER_STATE(unit) = NULL;
    163     }
    164 
    165 }
    166 
    167 /*
    168  * Function:
    169  *    bcmi_ft_flowchecker_is_invalid
    170  * Purpose:
    171  *    Chekc if the flowtracker check index is valid
    172  * Parameters:
    173  *     unit - (IN) BCM device id
    174  *     flowchecker_id - (IN) flowchecker index.
    175  * Returns:
    176  *     BCM_E_XXX.
    177  */
    178 int
    179 bcmi_ft_flowchecker_is_invalid(int unit, int flowchecker_id)
    180 {
    181 
    182     int num_flowcheckers = 0;
    183 
    184     /* Total number of groups/flowcheckers in device. */
    185     num_flowcheckers = soc_mem_index_max(unit, BSC_KG_GROUP_TABLEm);
    186 
    187     if (flowchecker_id > num_flowcheckers) {
    188         return BCM_E_PARAM;
    189     }
    190 
    191     if (BCMI_FT_FLOWCHECKER_BITMAP(unit) == NULL) {
    192         return BCM_E_INIT;
    193     }
    194 
    195     if (!(SHR_BITGET(BCMI_FT_FLOWCHECKER_BITMAP(unit), flowchecker_id))) {
    196         return BCM_E_NOT_FOUND;
    197     }
    198 
    199     if (BCMI_FT_FLOWCHECKER_INFO(unit, flowchecker_id) == NULL) {
    200         return BCM_E_NOT_FOUND;
    201     }
    202 
    203     return BCM_E_NONE;
    204 }
    205 
    206 int
    207 bcmi_ft_check_param_sanity(
    208             int unit,
    209             bcm_flowtracker_check_info_t flow_check_info)
    210 {
    211     uint32 max_value = 0, min_value = 0;
    212     const char *plist_str[] = BCM_FT_TRACKING_PARAM_STRINGS;
    213 
    214     switch(flow_check_info.param) {
    215         /* Tracking Params which are not mapped to qualifier. */
    216         case bcmFlowtrackerTrackingParamTypeNone:
    217         case bcmFlowtrackerTrackingParamTypePktCount:
    218         case bcmFlowtrackerTrackingParamTypeByteCount:
    219         case bcmFlowtrackerTrackingParamTypeTimestampNewLearn:
    220         case bcmFlowtrackerTrackingParamTypeTimestampFlowStart:
    221         case bcmFlowtrackerTrackingParamTypeTimestampFlowEnd:
    222         case bcmFlowtrackerTrackingParamTypeTimestampCheckEvent1:
    223         case bcmFlowtrackerTrackingParamTypeTimestampCheckEvent2:
    224         case bcmFlowtrackerTrackingParamTypeCount:
    225             return BCM_E_PARAM;
    226 
    227         /* Tracking params too big for flow check. */
    228         case bcmFlowtrackerTrackingParamTypeSrcIPv6:
    229         case bcmFlowtrackerTrackingParamTypeDstIPv6:
    230         case bcmFlowtrackerTrackingParamTypeInnerSrcIPv6:
    231         case bcmFlowtrackerTrackingParamTypeInnerDstIPv6:
    232             return BCM_E_PARAM;
    233 
    234         case bcmFlowtrackerTrackingParamTypeDosAttack:
    235         case bcmFlowtrackerTrackingParamTypeInnerDosAttack:
    236             if (!soc_feature(unit,
    237                         soc_feature_flowtracker_ver_1_dos_attack_check)) {
    238 
    239                 LOG_INFO(BSL_LS_BCM_FLOWTRACKER,
    240                         (BSL_META_U(unit, "Tracking Param(%s) is not supported in"
    241                                     " flowcheck.\n"),
    242                          plist_str[flow_check_info.param]));
    243                 return BCM_E_UNAVAIL;
    244             }
    245             break;
    246 
    247         default:
    248             /* Other tracking params are valid for Flowcheck */
    249             break;
    250     }
    251 
    252     /* Tracking params which are mapped to qualifier. */
    253     BCM_IF_ERROR_RETURN(_bcm_field_ft_tracking_param_range_get(unit,
    254                    flow_check_info.param, &min_value, &max_value));
    255 
    256     if (flow_check_info.min_value < min_value) {
    257         return BCM_E_PARAM;
    258     }
    259 
    260     if (flow_check_info.max_value > max_value) {
    261         return BCM_E_PARAM;
    262     }
    263 
    264     if ((flow_check_info.min_value != 0) &&
    265         (flow_check_info.max_value != 0)) {
    266 
    267         if (flow_check_info.min_value > flow_check_info.max_value) {
    268             return BCM_E_PARAM;
    269         }
    270     }
    271 
    272     if (!flow_check_info.operation) {
    273         /* No operation is sent. return config error. */
    274         return BCM_E_CONFIG;
    275     }
    276 
    277 
    278     return BCM_E_NONE;
    279 }
    280 
    281 /*
    282  * Function:
    283  *    bcmi_ft_check_create
    284  * Purpose:
    285  *    Create flowtracker index from information
    286  *    provided by user.
    287  * Parameters:
    288  *     unit - (IN) BCM device id
    289  *     options - (IN) options to create flowtracker check.
    290  *     flow_check_info - (IN) information to create flowtracker check.
    291  *     flowchecker_id - (OUT) Placeholder for index generated.
    292  *
    293  * Returns:
    294  *     BCM_E_XXX.
    295  */
    296 int
    297 bcmi_ft_check_create(
    298             int unit, uint32 options,
    299             bcm_flowtracker_check_info_t flow_check_info,
    300             bcm_flowtracker_check_t *flowchecker_id)
    301 {
    302 
    303     int index = -1;
    304     bcmi_flowtracker_flowchecker_info_t fc_info;
    305 
    306     /* Check if input params are correct. */
    307     if (flowchecker_id == NULL) {
    308         return BCM_E_PARAM;
    309     }
    310 
    311     BCM_IF_ERROR_RETURN(bcmi_ft_check_param_sanity(unit, flow_check_info));
    312 
    313     if ((options & BCM_FLOWTRACKER_CHECK_SECOND) &&
    314         (options & BCM_FLOWTRACKER_CHECK_WITH_ID)) {
    315         LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
    316             "Secondary check is not allowed with BCM_FLOWTRACKER_CHECK_WITH_ID. \n")));
    317         return BCM_E_CONFIG;
    318     }
    319 
    320     if (options & BCM_FLOWTRACKER_CHECK_WITH_ID) {
    321 
    322         if (!BCMI_FT_IDX_IS_CHECK(*flowchecker_id)) {
    323             return BCM_E_PARAM;
    324         }
    325 
    326         /* get the index from bitmap. */
    327         index = BCMI_FT_FLOWCHECKER_INDEX_GET(*flowchecker_id);
    328 
    329         if (!(bcmi_ft_flowchecker_is_invalid(unit, index))) {
    330             return BCM_E_PARAM;
    331         }
    332     }
    333 
    334     if (options & BCM_FLOWTRACKER_CHECK_SECOND) {
    335         if (!BCMI_FT_IDX_IS_CHECK(flow_check_info.primary_check_id)) {
    336             return BCM_E_PARAM;
    337         }
    338 
    339         sal_memset(&fc_info, 0, sizeof(bcmi_flowtracker_flowchecker_info_t));
    340 
    341         BCM_IF_ERROR_RETURN(bcmi_ft_flowchecker_get
    342             (unit, flow_check_info.primary_check_id, &fc_info));
    343 
    344         if (bcmi_ft_flowchecker_opr_is_dual(unit, fc_info.check1.operation)) {
    345             /* Dual operations used in first check.*/
    346             return BCM_E_CONFIG;
    347         }
    348 
    349         if ((flow_check_info.flags &
    350             BCM_FLOWTRACKER_CHECK_DATA_CLEAR_ON_EXPORT) || (flow_check_info.flags &
    351             BCM_FLOWTRACKER_CHECK_EXPORT_MODE_THRESHOLD)) {
    352 
    353             LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
    354                 "Export configuration now not allowed on Secondary Check.\n")));
    355             return BCM_E_CONFIG;
    356         }
    357 
    358         if (fc_info.check2.operation) {
    359             LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
    360                 "Secondary Check already exists for this primary. \n")));
    361             return BCM_E_EXISTS;
    362         }
    363 
    364         if (soc_feature(unit, soc_feature_hx5_ft_32bit_param_update)) {
    365             /* Not allowed to create a second check if dos attack is updated.*/
    366             if (((fc_info.check1.param ==
    367                  bcmFlowtrackerTrackingParamTypeDosAttack) ||
    368                 (fc_info.check1.param ==
    369                  bcmFlowtrackerTrackingParamTypeInnerDosAttack)) &&
    370                     (fc_info.action_info.action ==
    371                      bcmFlowtrackerCheckActionUpdateValue)) {
    372 
    373                 return BCM_E_CONFIG;
    374             }
    375         }
    376 
    377         index = BCMI_FT_FLOWCHECKER_INDEX_GET(flow_check_info.primary_check_id);
    378 
    379         if ((bcmi_ft_flowchecker_is_invalid(unit, index))) {
    380             LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
    381                 "The primary check is not created or invalid.\n")));
    382 
    383             return BCM_E_PARAM;
    384         }
    385 
    386         /* If Primary is associated with any FT Group, we should not allow
    387          * added second to it. */
    388         if (BCMI_FT_FLOWCHECKER_REFCOUNT(unit, index)) {
    389             return BCM_E_CONFIG;
    390         }
    391 
    392         BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.param   =
    393             flow_check_info.param;
    394         BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.min_value =
    395             flow_check_info.min_value;
    396         BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.max_value =
    397             flow_check_info.max_value;
    398         BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.operation =
    399             flow_check_info.operation;
    400         BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.flags =
    401             flow_check_info.flags;
    402         BCMI_FT_FLOWCHECKER_INFO(unit, index)->flags |=
    403             flow_check_info.flags;
    404 
    405         /* Set flowchecker type in the index. */
    406         *flowchecker_id =
    407             BCMI_FT_FLOWCHECKER_INDEX_SET(index, BCM_FT_IDX_TYPE_2ND_CHECK);
    408 
    409         return BCM_E_NONE;
    410     }
    411 
    412     BCM_IF_ERROR_RETURN(bcmi_ft_flowchecker_get_free_index(unit, &index));
    413 
    414     /* Allocate memory for the new flowchecker. */
    415     BCMI_FT_FLOWCHECKER_INFO(unit, index) =
    416         (bcmi_flowtracker_flowchecker_info_t *)
    417         sal_alloc(sizeof(bcmi_flowtracker_flowchecker_info_t),
    418         "flowtracker info");
    419 
    420     if (BCMI_FT_FLOWCHECKER_INFO(unit, index) == NULL) {
    421         return BCM_E_MEMORY;
    422     }
    423 
    424     /* Rather than doing memcpy, we should actually set each element. */
    425     sal_memset(BCMI_FT_FLOWCHECKER_INFO(unit, index), 0,
    426         sizeof(bcmi_flowtracker_flowchecker_info_t));
    427 
    428 
    429     /* We can also do memset here as the data is same.
    430     bcmi_ft_flowchecker_info_set(unit, BCMI_FT_FLOWCHECKER_INFO(unit, index),
    431         flow_check_info);
    432     */
    433 
    434     BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.param   =
    435         flow_check_info.param;
    436     BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.min_value =
    437         flow_check_info.min_value;
    438     BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.max_value =
    439         flow_check_info.max_value;
    440     BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.operation =
    441         flow_check_info.operation;
    442     BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.flags =
    443         flow_check_info.flags;
    444     BCMI_FT_FLOWCHECKER_INFO(unit, index)->flags |=
    445         flow_check_info.flags;
    446 
    447     /* Set flowchecker type in the index. */
    448     *flowchecker_id =
    449         BCMI_FT_FLOWCHECKER_INDEX_SET(index, BCM_FT_IDX_TYPE_CHECK);
    450 
    451     return BCM_E_NONE;
    452 }
    453 
    454 /*
    455  * Function:
    456  *    bcmi_ft_check_get
    457  * Purpose:
    458  *    Get flowtracker information from the index
    459  *    provided by user. This is user interfacing method
    460  *    which will only send particular info which user API exposes.
    461  * Parameters:
    462  *     unit - (IN) BCM device id
    463  *     flowchecker_id - (IN) flowtracker check index.
    464  *     flow_check_info - (OUT) information to create flowtracker check.
    465  *
    466  * Returns:
    467  *     BCM_E_XXX.
    468  */
    469 int bcmi_ft_check_get(
    470             int unit,
    471             bcm_flowtracker_check_t flowchecker_id,
    472             bcm_flowtracker_check_info_t *flow_check_info)
    473 {
    474 
    475     int index;
    476 
    477     /* Check if input params are correct. */
    478     if (!flow_check_info) {
    479         return BCM_E_PARAM;
    480     }
    481 
    482     if (!BCMI_FT_IDX_IS_CHECK(flowchecker_id)) {
    483         return BCM_E_PARAM;
    484     }
    485 
    486     /* get the index from bitmap. */
    487     index = BCMI_FT_FLOWCHECKER_INDEX_GET(flowchecker_id);
    488 
    489     if (bcmi_ft_flowchecker_is_invalid(unit, index)) {
    490         return BCM_E_PARAM;
    491     }
    492 
    493     sal_memset(flow_check_info, 0, sizeof(bcm_flowtracker_check_info_t));
    494 
    495     if (BCMI_FT_IDX_IS_2ND_CHECK(flowchecker_id)) {
    496         flow_check_info->param     =
    497             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.param;
    498         flow_check_info->min_value =
    499             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.min_value;
    500         flow_check_info->max_value =
    501             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.max_value;
    502         flow_check_info->operation =
    503             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.operation;
    504         flow_check_info->flags =
    505             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.flags;
    506 
    507         if (BCMI_FT_FLOWCHECKER_INFO(unit, index)->flags &
    508                 BCM_FLOWTRACKER_CHECK_TIMESTAMP_CHECK_EVENT2) {
    509             flow_check_info->flags |=
    510                 BCM_FLOWTRACKER_CHECK_TIMESTAMP_CHECK_EVENT2;
    511         }
    512         flow_check_info->primary_check_id =
    513             BCMI_FT_FLOWCHECKER_INDEX_SET(index, BCM_FT_IDX_TYPE_CHECK);
    514 
    515     } else {
    516 
    517         flow_check_info->param     =
    518             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.param;
    519         flow_check_info->min_value =
    520             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.min_value;
    521         flow_check_info->max_value =
    522             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.max_value;
    523         flow_check_info->operation =
    524             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.operation;
    525         flow_check_info->flags =
    526             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.flags;
    527 
    528         if (BCMI_FT_FLOWCHECKER_INFO(unit, index)->flags &
    529             BCM_FLOWTRACKER_CHECK_TIMESTAMP_CHECK_EVENT1) {
    530             flow_check_info->flags |=
    531                 BCM_FLOWTRACKER_CHECK_TIMESTAMP_CHECK_EVENT1;
    532         }
    533 
    534     }
    535 
    536     return BCM_E_NONE;
    537 }
    538 
    539 /*
    540  * Function:
    541  *    bcmi_ft_check_traverse
    542  * Purpose:
    543  *    Traverse througth all the flowtracker check objects.
    544  * Parameters:
    545  *     unit - (IN) BCM device id
    546  *     cb   - (IN) Callback
    547  *     user_data - (INOUT) User data which is sent back.
    548  *
    549  * Returns:
    550  *     BCM_E_XXX.
    551  */
    552 int
    553 bcmi_ft_check_traverse(
    554             int unit,
    555             bcm_flowtracker_check_traverse_cb cb,
    556             void *user_data)
    557 {
    558     bcm_flowtracker_check_t flowchecker_id;
    559     bcm_flowtracker_check_info_t flow_check_info;
    560     int index = 0;
    561     int num_flowcheckers = 0;
    562     soc_mem_t mem;
    563     mem = BSC_KG_GROUP_TABLEm;
    564 
    565     /* Total number of groups in device. */
    566     num_flowcheckers = soc_mem_index_count(unit, mem);
    567 
    568     if (cb == NULL) {
    569         return BCM_E_PARAM;
    570     }
    571 
    572     for(; index<num_flowcheckers; index++) {
    573 
    574         if (bcmi_ft_flowchecker_is_invalid(unit, index)) {
    575             continue;
    576         }
    577         sal_memset(&flow_check_info, 0, sizeof(bcm_flowtracker_check_info_t));
    578 
    579         flowchecker_id =
    580             BCMI_FT_FLOWCHECKER_INDEX_SET(index, BCM_FT_IDX_TYPE_CHECK);
    581 
    582         flow_check_info.param     =
    583             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.param;
    584         flow_check_info.min_value =
    585             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.min_value;
    586         flow_check_info.max_value =
    587             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.max_value;
    588         flow_check_info.operation =
    589             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.operation;
    590         flow_check_info.flags =
    591             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.flags;
    592 
    593         /* Invoke call back routine. */
    594         (*cb)(unit, flowchecker_id, &flow_check_info, user_data);
    595 
    596         /* Now send second check information. */
    597         if (!BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.param) {
    598             continue;
    599         }
    600 
    601         sal_memset(&flow_check_info, 0, sizeof(bcm_flowtracker_check_info_t));
    602 
    603         flowchecker_id =
    604             BCMI_FT_FLOWCHECKER_INDEX_SET(index, BCM_FT_IDX_TYPE_2ND_CHECK);
    605 
    606         flow_check_info.param     =
    607             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.param;
    608         flow_check_info.min_value =
    609             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.min_value;
    610         flow_check_info.max_value =
    611             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.max_value;
    612         flow_check_info.operation =
    613             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.operation;
    614         flow_check_info.flags =
    615             BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.flags;
    616 
    617         flow_check_info.primary_check_id =
    618             BCMI_FT_FLOWCHECKER_INDEX_SET(index, BCM_FT_IDX_TYPE_CHECK);
    619 
    620         /* Invoke call back routine. */
    621         (*cb)(unit, flowchecker_id, &flow_check_info, user_data);
    622     }
    623 
    624     return BCM_E_NONE;
    625 }
    626 
    627 /*
    628  * Function:
    629  *    bcmi_ft_check_get
    630  * Purpose:
    631  *    Get flowtracker information from the index
    632  *    provided by user. This is internal function
    633  *    which provides all the internal data.
    634  * Parameters:
    635  *     unit - (IN) BCM device id
    636  *     flowchecker_id - (IN) flowtracker check index.
    637  *     flow_check_info - (OUT) information to create flowtracker check.
    638  *
    639  * Returns:
    640  *     BCM_E_XXX.
    641  */
    642 int
    643 bcmi_ft_flowchecker_get(
    644             int unit,
    645             bcm_flowtracker_check_t flowchecker_id,
    646             bcmi_flowtracker_flowchecker_info_t *flow_check_info)
    647 {
    648 
    649     int index;
    650 
    651     /* Check if input params are correct. */
    652     if (!flow_check_info) {
    653         return BCM_E_PARAM;
    654     }
    655     if (!BCMI_FT_IDX_IS_CHECK(flowchecker_id)) {
    656         return BCM_E_PARAM;
    657     }
    658 
    659     /* get the index from bitmap. */
    660     index = BCMI_FT_FLOWCHECKER_INDEX_GET(flowchecker_id);
    661 
    662     if (bcmi_ft_flowchecker_is_invalid(unit, index)) {
    663         return BCM_E_PARAM;
    664     }
    665 
    666     /* Get the flags. */
    667     flow_check_info->flags =
    668         BCMI_FT_FLOWCHECKER_INFO(unit, index)->flags;
    669 
    670     /* Data of first check. */
    671     flow_check_info->check1.param     =
    672         BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.param;
    673     flow_check_info->check1.min_value =
    674         BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.min_value;
    675     flow_check_info->check1.max_value =
    676         BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.max_value;
    677     flow_check_info->check1.operation =
    678         BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.operation;
    679     flow_check_info->check1.flags =
    680         BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.flags;
    681 
    682     /* Data of second check. */
    683     flow_check_info->check2.param     =
    684         BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.param;
    685     flow_check_info->check2.min_value =
    686         BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.min_value;
    687     flow_check_info->check2.max_value =
    688         BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.max_value;
    689     flow_check_info->check2.operation =
    690         BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.operation;
    691     flow_check_info->check2.flags =
    692         BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.flags;
    693 
    694     flow_check_info->action_info.param =
    695         BCMI_FT_FLOWCHECKER_INFO(unit, index)->action_info.param;
    696     flow_check_info->action_info.action  =
    697         BCMI_FT_FLOWCHECKER_INFO(unit, index)->action_info.action;
    698 
    699 
    700     flow_check_info->export_info.export_check_threshold =
    701         BCMI_FT_FLOWCHECKER_INFO(unit, index)->
    702             export_info.export_check_threshold;
    703 
    704     flow_check_info->export_info.operation =
    705         BCMI_FT_FLOWCHECKER_INFO(unit, index)->export_info.operation;
    706 
    707     return BCM_E_NONE;
    708 }
    709 
    710 /*
    711  * Function:
    712  *    bcmi_ft_check_destroy
    713  * Purpose:
    714  *    Destroy flowtracker from the index
    715  *    provided by user.
    716  * Parameters:
    717  *     unit - (IN) BCM device id
    718  *     flowchecker_id - (IN) Placeholder for index generated.
    719  *
    720  * Returns:
    721  *     BCM_E_XXX.
    722  */
    723 int
    724 bcmi_ft_check_destroy(
    725             int unit,
    726             bcm_flowtracker_check_t flowchecker_id)
    727 {
    728 
    729     int index;
    730 
    731     if (!BCMI_FT_IDX_IS_CHECK(flowchecker_id)) {
    732         return BCM_E_PARAM;
    733     }
    734 
    735     /* get the index from bitmap. */
    736     index = BCMI_FT_FLOWCHECKER_INDEX_GET(flowchecker_id);
    737 
    738     BCM_IF_ERROR_RETURN(bcmi_ft_flowchecker_is_invalid(unit, index));
    739 
    740     if (BCMI_FT_FLOWCHECKER_REFCOUNT(unit, index)) {
    741         /* For removing checks, they should be removed from FT groups. */
    742         LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
    743             "The check is still attached to FT groups.\n")));
    744         return BCM_E_BUSY;
    745     }
    746 
    747     if (BCMI_FT_IDX_IS_2ND_CHECK(flowchecker_id)) {
    748         /* Check if second check is configured. */
    749         if (!BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.operation) {
    750             return BCM_E_NOT_FOUND;
    751         }
    752 
    753         sal_memset((void *) (&(BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2)),
    754             0, sizeof(bcm_flowtracker_check_info_t));
    755 
    756         /* Second flowchecker is deleted. return. */
    757         return BCM_E_NONE;
    758     } else {
    759         /* Check if second check is configured. */
    760         if (BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.operation) {
    761             LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
    762                             "Second Check is associated\n")));
    763             return BCM_E_BUSY;
    764         }
    765     }
    766 
    767     /* Free the flowchecker sw state. */
    768     sal_free(BCMI_FT_FLOWCHECKER_INFO(unit, index));
    769 
    770     /* Clear the bit for flowchecker. */
    771     SHR_BITCLR(BCMI_FT_FLOWCHECKER_BITMAP(unit), index);
    772 
    773     return BCM_E_NONE;
    774 }
    775 
    776 /*
    777  * Function:
    778  *    bcmi_ft_check_destroy_all
    779  * Purpose:
    780  *    Destroy all flowtrackers from the index
    781  *    provided by user which are not linked to any group.
    782  * Parameters:
    783  *     unit - (IN) BCM device id
    784  *
    785  * Returns:
    786  *     BCM_E_XXX.
    787  */
    788 int
    789 bcmi_ft_check_destroy_all(int unit)
    790 {
    791     int index = 0;
    792     int num_flowcheckers = 0;
    793     soc_mem_t mem;
    794     mem = BSC_KG_GROUP_TABLEm;
    795 
    796     /* Total number of groups in device. */
    797     num_flowcheckers = soc_mem_index_count(unit, mem);
    798 
    799     for(index = 0; index < num_flowcheckers; index++) {
    800 
    801         /*
    802          * If we are not able to destroy then either it does not exists
    803          * or may be it is linked to group. both cases, we just bypass.
    804          */
    805 
    806         (void) bcmi_ft_check_destroy(unit, BCMI_FT_FLOWCHECKER_INDEX_SET( \
    807                     index, BCM_FT_IDX_TYPE_2ND_CHECK));
    808         (void) bcmi_ft_check_destroy(unit, BCMI_FT_FLOWCHECKER_INDEX_SET( \
    809                     index, BCM_FT_IDX_TYPE_CHECK));
    810     }
    811 
    812     return BCM_E_NONE;
    813 }
    814 
    815 /*
    816  * Function:
    817  *    bcmi_ft_check_action_info_set
    818  * Purpose:
    819  *    Set action informaiton on the flowtracker check
    820  * Parameters:
    821  *     unit - (IN) BCM device id
    822  *     flowchecker_id - (IN) flowtracker check index.
    823  *     info - (IN) action information.
    824  *
    825  * Returns:
    826  *     BCM_E_XXX.
    827  */
    828 int
    829 bcmi_ft_check_action_info_set(
    830     int unit,
    831     bcm_flowtracker_check_t check_id,
    832     bcm_flowtracker_check_action_info_t info)
    833 {
    834     int index = 0;
    835 
    836     if (!BCMI_FT_IDX_IS_CHECK(check_id)) {
    837         return BCM_E_PARAM;
    838     }
    839 
    840     if (BCMI_FT_IDX_IS_2ND_CHECK(check_id)) {
    841         LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
    842             "Actions can only be set on primary check.\n")));
    843 
    844         return BCM_E_PARAM;
    845     }
    846 
    847 
    848     /* get the index from bitmap. */
    849     index = BCMI_FT_FLOWCHECKER_INDEX_GET(check_id);
    850 
    851     if (bcmi_ft_flowchecker_is_invalid(unit, index)) {
    852         return BCM_E_PARAM;
    853     }
    854 
    855     /*
    856      * If the check is created on Dos Attacks and it is
    857      * dual operation on check 1 then raise error.
    858      */
    859     if (soc_feature(unit, soc_feature_hx5_ft_32bit_param_update)) {
    860 
    861         if ((info.action == bcmFlowtrackerCheckActionUpdateValue) &&
    862             ((BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.param ==
    863                 bcmFlowtrackerTrackingParamTypeDosAttack) ||
    864             (BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.param ==
    865                 bcmFlowtrackerTrackingParamTypeInnerDosAttack))) {
    866 
    867             if (bcmi_ft_flowchecker_opr_is_dual(unit,
    868                 (BCMI_FT_FLOWCHECKER_INFO(unit, index)->check1.operation))) {
    869                 return BCM_E_CONFIG;
    870             }
    871             /* Not allowed to create second check if dos vector is updated. */
    872             if (BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.param) {
    873                 return BCM_E_CONFIG;
    874             }
    875         }
    876     }
    877 
    878     BCMI_FT_FLOWCHECKER_INFO(unit, index)->action_info.param = info.param;
    879     BCMI_FT_FLOWCHECKER_INFO(unit, index)->action_info.action  = info.action;
    880 
    881     return BCM_E_NONE;
    882 }
    883 
    884 /*
    885  * Function:
    886  *    bcmi_ft_check_action_info_get
    887  * Purpose:
    888  *    Get action informaiton from the flowtracker check
    889  * Parameters:
    890  *     unit - (IN) BCM device id
    891  *     flowchecker_id - (IN) flowtracker check index.
    892  *     info - (OUT) action information.
    893  *
    894  * Returns:
    895  *     BCM_E_XXX.
    896  */
    897 int
    898 bcmi_ft_check_action_info_get(
    899     int unit,
    900     bcm_flowtracker_check_t check_id,
    901     bcm_flowtracker_check_action_info_t *info)
    902 {
    903     int index = 0;
    904 
    905     if (!BCMI_FT_IDX_IS_CHECK(check_id)) {
    906         return BCM_E_PARAM;
    907     }
    908 
    909     if (BCMI_FT_IDX_IS_2ND_CHECK(check_id)) {
    910         LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
    911             "Actions can only be retrieved on primary check.\n")));
    912 
    913         return BCM_E_PARAM;
    914     }
    915 
    916     /* get the index from bitmap. */
    917     index = BCMI_FT_FLOWCHECKER_INDEX_GET(check_id);
    918 
    919     if (bcmi_ft_flowchecker_is_invalid(unit, index)) {
    920         return BCM_E_PARAM;
    921     }
    922 
    923     info->param = BCMI_FT_FLOWCHECKER_INFO(unit, index)->action_info.param;
    924     info->action  = BCMI_FT_FLOWCHECKER_INFO(unit, index)->action_info.action;
    925 
    926     return BCM_E_NONE;
    927 }
    928 
    929 /*
    930  * Function:
    931  *    bcmi_ft_check_export_info_set
    932  * Purpose:
    933  *    set export informaiton from the flowtracker check
    934  * Parameters:
    935  *     unit - (IN) BCM device id
    936  *     flowchecker_id - (IN) flowtracker check index.
    937  *     info - (IN) export information.
    938  *
    939  * Returns:
    940  *     BCM_E_XXX.
    941  */
    942 int
    943 bcmi_ft_check_export_info_set(
    944     int unit,
    945     bcm_flowtracker_check_t check_id,
    946     bcm_flowtracker_check_export_info_t info)
    947 {
    948     int index = 0;
    949 
    950     if (!BCMI_FT_IDX_IS_CHECK(check_id)) {
    951         return BCM_E_PARAM;
    952     }
    953 
    954     if (BCMI_FT_IDX_IS_2ND_CHECK(check_id)) {
    955         LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
    956             "Export info can only be set on primary check.\n")));
    957 
    958         return BCM_E_PARAM;
    959     }
    960 
    961     /* get the index from bitmap. */
    962     index = BCMI_FT_FLOWCHECKER_INDEX_GET(check_id);
    963 
    964     if (bcmi_ft_flowchecker_is_invalid(unit, index)) {
    965         return BCM_E_PARAM;
    966     }
    967 
    968     if (bcmi_ft_flowchecker_opr_is_dual(unit, info.operation)) {
    969         /* No dual operations are supported for export threshold.*/
    970         return BCM_E_PARAM;
    971     }
    972 
    973     if (info.export_check_threshold &&
    974         (info.operation != bcmFlowtrackerCheckOpGreaterEqual)) {
    975 
    976         LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
    977             "Export threshold is only supported with GreaterEqual operation.\n")));
    978 
    979         return BCM_E_CONFIG;
    980     }
    981 
    982 
    983     BCMI_FT_FLOWCHECKER_INFO(unit, index)->export_info.export_check_threshold =
    984         info.export_check_threshold;
    985     BCMI_FT_FLOWCHECKER_INFO(unit, index)->export_info.operation =
    986         info.operation;
    987 
    988     return BCM_E_NONE;
    989 }
    990 
    991 /*
    992  * Function:
    993  *    bcmi_ft_check_export_info_get
    994  * Purpose:
    995  *    Get export informaiton from the flowtracker check
    996  * Parameters:
    997  *     unit - (IN) BCM device id
    998  *     flowchecker_id - (IN) flowtracker check index.
    999  *     info - (OUT) export information.
   1000  *
   1001  * Returns:
   1002  *     BCM_E_XXX.
   1003  */
   1004 int
   1005 bcmi_ft_check_export_info_get(
   1006     int unit,
   1007     bcm_flowtracker_check_t check_id,
   1008     bcm_flowtracker_check_export_info_t *info)
   1009 {
   1010     int index = 0;
   1011 
   1012     if (!BCMI_FT_IDX_IS_CHECK(check_id)) {
   1013         return BCM_E_PARAM;
   1014     }
   1015 
   1016     if (BCMI_FT_IDX_IS_2ND_CHECK(check_id)) {
   1017         LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
   1018             "Export info can only be retrieved from primary check.\n")));
   1019 
   1020         return BCM_E_PARAM;
   1021     }
   1022 
   1023     /* get the index from bitmap. */
   1024     index = BCMI_FT_FLOWCHECKER_INDEX_GET(check_id);
   1025 
   1026     if (bcmi_ft_flowchecker_is_invalid(unit, index)) {
   1027         return BCM_E_PARAM;
   1028     }
   1029 
   1030     info->export_check_threshold =
   1031         BCMI_FT_FLOWCHECKER_INFO(unit, index)->
   1032         export_info.export_check_threshold;
   1033 
   1034     info->operation =
   1035         BCMI_FT_FLOWCHECKER_INFO(unit, index)->export_info.operation;
   1036 
   1037     return BCM_E_NONE;
   1038 }
   1039 
   1040 /*
   1041  * Function:
   1042  *    bcmi_ft_flowchecker_list_length_get
   1043  * Purpose:
   1044  *    Add this flowtracker into the group.
   1045  * Parameters:
   1046  *     unit - (IN) BCM device id
   1047  *     head - (INOUT) Head pointer of the list.
   1048  *
   1049  * Returns:
   1050  *     BCM_E_XXX.
   1051  */
   1052 int
   1053 bcmi_ft_flowchecker_list_length_get(
   1054         int unit,
   1055         bcmi_ft_flowchecker_list_t **head)
   1056 {
   1057 
   1058    int length = 0;
   1059     bcmi_ft_flowchecker_list_t *temp = NULL;
   1060 
   1061     if (!head) {
   1062         return 0;
   1063     }
   1064 
   1065     temp = (*head);
   1066 
   1067     while(temp) {
   1068         length++;
   1069         temp = temp->next;
   1070     }
   1071 
   1072     return length;
   1073 }
   1074 /*
   1075  * Function:
   1076  *    bcmi_ft_flowchecker_list_add
   1077  * Purpose:
   1078  *    Add this flowtracker into the group.
   1079  * Parameters:
   1080  *     unit - (IN) BCM device id
   1081  *     head - (INOUT) Head pointer of the list.
   1082  *     flowchecker_id - (IN) flowtracker check index.
   1083  *
   1084  * Returns:
   1085  *     BCM_E_XXX.
   1086  */
   1087 int
   1088 bcmi_ft_flowchecker_list_add(
   1089         int unit,
   1090         bcmi_ft_flowchecker_list_t **head,
   1091         bcm_flowtracker_check_t flowchecker_id)
   1092 {
   1093     bcmi_ft_flowchecker_list_t *temp_node = NULL;
   1094     bcmi_ft_flowchecker_list_t *node_iter = NULL;
   1095     bcmi_ft_flowchecker_list_t *node_prev = NULL;
   1096 
   1097     /* Create node */
   1098     temp_node = (bcmi_ft_flowchecker_list_t *)
   1099                     sal_alloc(sizeof(bcmi_ft_flowchecker_list_t),
   1100                         "flowchecker list Node");
   1101     if (temp_node == NULL) {
   1102         return BCM_E_MEMORY;
   1103     }
   1104     temp_node->flowchecker_id = flowchecker_id;
   1105     temp_node->next = NULL;
   1106 
   1107     node_prev = NULL;
   1108     node_iter = (*head);
   1109     while (node_iter != NULL) {
   1110         if (node_iter->flowchecker_id == flowchecker_id) {
   1111             sal_free(temp_node);
   1112             return BCM_E_NONE;
   1113         }
   1114         node_prev = node_iter;
   1115         node_iter = node_iter->next;
   1116     }
   1117 
   1118     /* Insert */
   1119     if (node_prev != NULL) {
   1120         temp_node->next = node_prev->next;
   1121         node_prev->next = temp_node;
   1122     } else {
   1123         temp_node->next = (*head);
   1124         (*head) = temp_node;
   1125     }
   1126 
   1127     return BCM_E_NONE;
   1128 }
   1129 
   1130 /*
   1131  * Function:
   1132  *    bcmi_ft_flowchecker_list_delete
   1133  * Purpose:
   1134  *    Delete this flowtracker check from group list.
   1135  * Parameters:
   1136  *     unit - (IN) BCM device id
   1137  *     head - (INOUT) Head pointer of the list.
   1138  *     flowchecker_id - (IN) flowtracker check index.
   1139  *
   1140  * Returns:
   1141  *     BCM_E_XXX.
   1142  */
   1143 int
   1144 bcmi_ft_flowchecker_list_delete(
   1145         int unit,
   1146         bcmi_ft_flowchecker_list_t **head,
   1147         bcm_flowtracker_check_t flowchecker_id)
   1148 {
   1149 
   1150     bcmi_ft_flowchecker_list_t *temp, *prev;
   1151 #if 0
   1152     int index = 0;
   1153 
   1154     if (!BCMI_FT_IDX_IS_CHECK(flowchecker_id)) {
   1155         return BCM_E_NONE;
   1156     }
   1157 
   1158     /* get the index from bitmap. */
   1159     index = BCMI_FT_FLOWCHECKER_INDEX_GET(flowchecker_id);
   1160 
   1161     if (bcmi_ft_flowchecker_is_invalid(unit, index)) {
   1162         return BCM_E_NONE;
   1163     }
   1164 #endif
   1165     if (!head || (!(*head))) {
   1166         return BCM_E_NOT_FOUND;
   1167     }
   1168 
   1169     prev = temp = (*head);
   1170 
   1171     while(temp) {
   1172         if (temp->flowchecker_id == flowchecker_id) {
   1173             if (temp == (*head)) {
   1174                 (*head) = temp->next;
   1175             } else {
   1176                 prev->next = temp->next;
   1177             }
   1178             sal_free(temp);
   1179             temp = NULL;
   1180             return BCM_E_NONE;
   1181         }
   1182         prev = temp;
   1183         temp = temp->next;
   1184     }
   1185 
   1186     return BCM_E_NOT_FOUND;
   1187 }
   1188 
   1189 /*
   1190  * Function:
   1191  *    bcmi_ft_check_parts_get
   1192  * Purpose:
   1193  *    Get check parts for given primary check.
   1194  * Parameters:
   1195  *     unit - (IN) BCM device id
   1196  *     flowchecker_id - (IN) flowtracker check index.
   1197  *     check_ids - (OUT) Pointer to check Ids
   1198  *     num_parts - (OUT) Number of parts
   1199  *
   1200  * Returns:
   1201  *     BCM_E_XXX.
   1202  */
   1203 
   1204 int
   1205 bcmi_ft_check_parts_get(
   1206         int unit,
   1207         bcm_flowtracker_check_t flowchecker_id,
   1208         bcm_flowtracker_check_t *check_ids,
   1209         int *num_parts)
   1210 {
   1211     int part = 0;
   1212     int index = 0;
   1213     bcmi_flowtracker_flowchecker_info_t fc_info;
   1214     sal_memset(&fc_info, 0, sizeof(bcmi_flowtracker_flowchecker_info_t));
   1215 
   1216     BCM_IF_ERROR_RETURN(bcmi_ft_flowchecker_get
   1217             (unit, flowchecker_id, &fc_info));
   1218 
   1219     /* Adding Primary */
   1220     check_ids[part++] = flowchecker_id;
   1221 
   1222     /* get the index from bitmap. */
   1223     index = BCMI_FT_FLOWCHECKER_INDEX_GET(flowchecker_id);
   1224 
   1225     /* Adding Secondary */
   1226     if (BCMI_FT_FLOWCHECKER_INFO(unit, index)->check2.operation) {
   1227         check_ids[part++] =
   1228             BCMI_FT_FLOWCHECKER_INDEX_SET(index, BCM_FT_IDX_TYPE_2ND_CHECK);
   1229     }
   1230 
   1231     *num_parts = part;
   1232 
   1233     return BCM_E_NONE;
   1234 }
   1235 
   1236 /*
   1237  * Function:
   1238  *    bcmi_ft_group_flowchecker_add
   1239  * Purpose:
   1240  *    Add this flowtracker check into group.
   1241  * Parameters:
   1242  *     unit - (IN) BCM device id
   1243  *     id  - (IN) flowtracker group index.
   1244  *     flowchecker_id - (IN) flowtracker check index.
   1245  *
   1246  * Returns:
   1247  *     BCM_E_XXX.
   1248  */
   1249 
   1250 int
   1251 bcmi_ft_group_flowchecker_add(
   1252         int unit,
   1253         bcm_flowtracker_group_t id,
   1254         bcm_flowtracker_check_t flowchecker_id)
   1255 {
   1256     int part = 0;
   1257     int index;
   1258     int rv = BCM_E_NONE;
   1259     int num_parts = 0;
   1260     bcm_flowtracker_check_t check_ids[2];
   1261     bcmi_ft_flowchecker_list_t **head = NULL;
   1262 
   1263     /* validate flow group index. */
   1264     if (bcmi_ft_group_is_invalid(unit, id)) {
   1265         return (BCM_E_PARAM);
   1266     }
   1267 
   1268     if (!BCMI_FT_IDX_IS_CHECK(flowchecker_id)) {
   1269         return BCM_E_PARAM;
   1270     }
   1271 
   1272     /* get the index from bitmap. */
   1273     index = BCMI_FT_FLOWCHECKER_INDEX_GET(flowchecker_id);
   1274 
   1275     /* Validate flow checker index. */
   1276     if (bcmi_ft_flowchecker_is_invalid(unit, index)) {
   1277         return BCM_E_PARAM;
   1278     }
   1279 
   1280     if (BCMI_FT_GROUP_IS_BUSY(unit, id)) {
   1281         LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, "Adding check to"
   1282                         " installed Group (%d) is not allowed. \n"), id));
   1283         return BCM_E_CONFIG;
   1284     }
   1285     if (!BCMI_FT_IDX_IS_PRIMARY_CHECK(flowchecker_id)) {
   1286         LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, "Given check"
   1287                         " is not primary\n")));
   1288         return BCM_E_PARAM;
   1289     }
   1290 
   1291     /* set Check timestamp */
   1292     rv = bcmi_ft_group_check_ts_set(unit, id, flowchecker_id,
   1293             bcmFlowtrackerFlowCheckTsSet);
   1294     BCM_IF_ERROR_RETURN(rv);
   1295 
   1296     /* Get associated flowchecks */
   1297     rv = bcmi_ft_check_parts_get(unit, flowchecker_id, check_ids, &num_parts);
   1298     BCM_IF_ERROR_RETURN(rv);
   1299 
   1300     /* Add to flowchecker list of group */
   1301     head = &(BCMI_FT_GROUP_FLOWCHECKER_HEAD(unit, id));
   1302     for (part = 0; (part < num_parts) && BCM_SUCCESS(rv); part++) {
   1303         rv = bcmi_ft_flowchecker_list_add(unit, head, check_ids[part]);
   1304     }
   1305 
   1306     if (BCM_FAILURE(rv)) {
   1307         for (part = 0; part < num_parts; part++) {
   1308             bcmi_ft_flowchecker_list_delete(unit, head, check_ids[part]);
   1309         }
   1310 
   1311         return rv;
   1312     }
   1313 
   1314     BCMI_FT_FLOWCHECKER_REFCOUNT_INC(unit, index);
   1315 
   1316     return rv;
   1317 }
   1318 
   1319 /*
   1320  * Function:
   1321  *    bcmi_ft_group_flowchecker_delete
   1322  * Purpose:
   1323  *    Delete this flowtracker check from group.
   1324  * Parameters:
   1325  *     unit - (IN) BCM device id
   1326  *     id  - (IN) flowtracker group index.
   1327  *     flowchecker_id - (IN) flowtracker check index.
   1328  *
   1329  * Returns:
   1330  *     BCM_E_XXX.
   1331  */
   1332 int
   1333 bcmi_ft_group_flowchecker_delete(
   1334         int unit,
   1335         bcm_flowtracker_group_t id,
   1336         bcm_flowtracker_check_t flowchecker_id)
   1337 {
   1338     int rv = BCM_E_NONE;
   1339     int index;
   1340     int part = 0;
   1341     int num_parts = 0;
   1342     bcmi_ft_flowchecker_list_t **head = NULL;
   1343     bcm_flowtracker_check_t check_ids[2];
   1344 
   1345     /* validate flow group index. */
   1346     if (bcmi_ft_group_is_invalid(unit, id)) {
   1347         return (BCM_E_PARAM);
   1348     }
   1349 
   1350     if (!BCMI_FT_IDX_IS_CHECK(flowchecker_id)) {
   1351         return BCM_E_PARAM;
   1352     }
   1353 
   1354     /* get the index from bitmap. */
   1355     index = BCMI_FT_FLOWCHECKER_INDEX_GET(flowchecker_id);
   1356 
   1357     /* Validate flow checker index. */
   1358     if (bcmi_ft_flowchecker_is_invalid(unit, index)) {
   1359         return BCM_E_PARAM;
   1360     }
   1361 
   1362     if (BCMI_FT_GROUP_IS_BUSY(unit, id)) {
   1363         LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, "Please uninstall"
   1364                         " Group (%d). operation is not allowed. \n"), id));
   1365         return BCM_E_CONFIG;
   1366     }
   1367 
   1368     if (!BCMI_FT_IDX_IS_PRIMARY_CHECK(flowchecker_id)) {
   1369         LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, "Given check"
   1370                         " is not primary\n")));
   1371         return BCM_E_PARAM;
   1372     }
   1373 
   1374     /* reset Check timestamps */
   1375     rv = bcmi_ft_group_check_ts_set(unit, id, flowchecker_id,
   1376             bcmFlowtrackerFlowCheckTsReset);
   1377     BCM_IF_ERROR_RETURN(rv);
   1378 
   1379     /* Get associated flowchecks */
   1380     rv = bcmi_ft_check_parts_get(unit, flowchecker_id, check_ids, &num_parts);
   1381     BCM_IF_ERROR_RETURN(rv);
   1382 
   1383     head = &(BCMI_FT_GROUP_FLOWCHECKER_HEAD(unit, id));
   1384     for (part = 0; (part < num_parts) && (BCM_SUCCESS(rv)); part++) {
   1385         rv = bcmi_ft_flowchecker_list_delete(unit, head, check_ids[part]);
   1386     }
   1387 
   1388     if (BCM_SUCCESS(rv)) {
   1389         BCMI_FT_FLOWCHECKER_REFCOUNT_DEC(unit, index);
   1390     }
   1391 
   1392     return rv;
   1393 }
   1394 
   1395 /*
   1396  * Function:
   1397  *    bcmi_ft_group_flowchecker_get_all
   1398  * Purpose:
   1399  *    Get all the flowtracker checks from group.
   1400  * Parameters:
   1401  *     unit - (IN) BCM device id
   1402  *     id  - (IN) flowtracker group index.
   1403  *     max_checks - (IN) max number of flowtracker check ids to be sent..
   1404  *     list_of_check_ids - (IN) list of the flowtracker check ids.
   1405  *     num_checks - NUmber of checks actually sent.
   1406  *
   1407  * Returns:
   1408  *     BCM_E_XXX.
   1409  */
   1410 int
   1411 bcmi_flowtracker_check_get_all(
   1412     int unit,
   1413     bcm_flowtracker_group_t id,
   1414     int skip_non_primary,
   1415     int max_checks,
   1416     bcm_flowtracker_check_t *list_of_check_ids,
   1417     int *num_checks)
   1418 {
   1419 
   1420     bcmi_ft_flowchecker_list_t *temp;
   1421     int only_count = 0;
   1422     int i = 0;
   1423 
   1424     /* validate flow group index. */
   1425     if (bcmi_ft_group_is_invalid(unit, id)) {
   1426         return (BCM_E_PARAM);
   1427     }
   1428 
   1429     /* If the max_checks is non zero and list == NULL, return
   1430      * BCM_E_PARAM.
   1431      */
   1432     if (max_checks != 0 && list_of_check_ids == NULL) {
   1433         return BCM_E_PARAM;
   1434     }
   1435 
   1436     /* If max_alu_info == 0 and list_of_export_elements == NULL,
   1437      * return the number of export elements in list_size
   1438      * variable.
   1439      */
   1440     if (max_checks == 0 && list_of_check_ids == NULL) {
   1441         only_count = 1;
   1442     }
   1443 
   1444     temp = BCMI_FT_GROUP_FLOWCHECKER_HEAD(unit, id);
   1445 
   1446     while (temp) {
   1447         /*
   1448          * Go till end and start putting ids in array.
   1449          * The limit is given by max_checks.
   1450          */
   1451         if ((!only_count) && (max_checks != -1) && (i < max_checks)) {
   1452             if ((skip_non_primary == TRUE) &&
   1453                     (!BCMI_FT_IDX_IS_PRIMARY_CHECK(temp->flowchecker_id))) {
   1454                 temp = temp->next;
   1455                 continue;
   1456             }
   1457             list_of_check_ids[i] =  temp->flowchecker_id;
   1458         }
   1459 
   1460         i++;
   1461         temp = temp->next;
   1462     }
   1463 
   1464     *num_checks = i;
   1465 
   1466     return BCM_E_NONE;
   1467 }
   1468 
   1469 
   1470 /*
   1471  * Function:
   1472  *    bcmi_ft_check_compare
   1473  * Purpose:
   1474  *    Compare two flowtracker checks.
   1475  * Parameters:
   1476  *    unit - (IN) BCM device id
   1477  *    check_id1 - (IN) first flowtracker check index.
   1478  *    check_id2 - (IN) Second flowtracker check index.
   1479  * Returns:
   1480  *     BCM_E_XXX.
   1481  */
   1482 int
   1483 bcmi_ft_check_compare(
   1484         int unit,
   1485         bcm_flowtracker_check_t check_id1,
   1486         bcm_flowtracker_check_t check_id2)
   1487 {
   1488 
   1489     bcmi_flowtracker_flowchecker_info_t fc_info1, fc_info2;
   1490 
   1491 
   1492     sal_memset(&fc_info1, 0, sizeof(bcmi_flowtracker_flowchecker_info_t));
   1493     sal_memset(&fc_info2, 0, sizeof(bcmi_flowtracker_flowchecker_info_t));
   1494 
   1495     /* If both flow checks are same then return match. */
   1496     if (check_id1 == check_id2) {
   1497         return BCM_E_NONE;
   1498     }
   1499 
   1500     /* Validate flow checker index. */
   1501     if (bcmi_ft_flowchecker_is_invalid(unit,
   1502         BCMI_FT_FLOWCHECKER_INDEX_GET(check_id1))) {
   1503 
   1504         return BCM_E_NOT_FOUND;
   1505     }
   1506 
   1507     /* Validate flow checker index. */
   1508     if (bcmi_ft_flowchecker_is_invalid(unit,
   1509         BCMI_FT_FLOWCHECKER_INDEX_GET(check_id2))) {
   1510 
   1511         return BCM_E_NOT_FOUND;
   1512     }
   1513 
   1514     BCM_IF_ERROR_RETURN(bcmi_ft_flowchecker_get
   1515             (unit, check_id1, &fc_info1));
   1516 
   1517     BCM_IF_ERROR_RETURN(bcmi_ft_flowchecker_get
   1518             (unit, check_id2, &fc_info2));
   1519 
   1520     /* Compare the flow checks and if same then return MATCH. */
   1521     if (!(sal_memcmp(&fc_info1, &fc_info2,
   1522             sizeof(bcmi_flowtracker_flowchecker_info_t)))) {
   1523        return BCM_E_NONE;
   1524     }
   1525 
   1526     return BCM_E_NOT_FOUND;
   1527 }
   1528 
   1529 /*
   1530  * Function:
   1531  *    bcmi_ft_check_list_compare
   1532  * Purpose:
   1533  *    Compare all the checks in group list.
   1534  * Parameters:
   1535  *    unit - (IN) BCM device id
   1536  *    head - (IN) Head of the flowchecker list.
   1537  *    check_id - (IN) flowtracker check index.
   1538  * Returns:
   1539  *     BCM_E_XXX.
   1540  */
   1541 int
   1542 bcmi_ft_check_list_compare(
   1543         int unit,
   1544         bcmi_ft_flowchecker_list_t **head,
   1545         bcm_flowtracker_check_t check_id)
   1546 {
   1547 
   1548     bcmi_ft_flowchecker_list_t *temp;
   1549 
   1550     if ((head == NULL) || (*head == NULL)) {
   1551         return BCM_E_NOT_FOUND;
   1552     }
   1553 
   1554     temp = *head;
   1555 
   1556     while (temp != NULL) {
   1557         if (!(bcmi_ft_check_compare(unit, check_id, temp->flowchecker_id))) {
   1558             return BCM_E_NONE;
   1559         }
   1560         temp = temp->next;
   1561     }
   1562 
   1563     return BCM_E_NOT_FOUND;
   1564 }
   1565 
   1566 /*
   1567  * Function:
   1568  *    bcmi_ft_group_check_validate
   1569  * Purpose:
   1570  *    Validate Flowcheck if given configuration is allowed
   1571  *    based in options params.
   1572  * Parameters:
   1573  *    unit - (IN) BCM device id
   1574  *    optiosn - (IN) Match criteria
   1575  *    id - (IN) Flowtracker group
   1576  *    check_id - (IN) flowtracker check
   1577  * Returns:
   1578  *     BCM_E_XXX.
   1579  */
   1580 int
   1581 bcmi_ft_group_check_validate(
   1582         int unit,
   1583         uint32 options,
   1584         bcm_flowtracker_group_t id,
   1585         bcm_flowtracker_check_t check_id)
   1586 {
   1587     int index;
   1588     int found = FALSE;
   1589     bcmi_ft_flowchecker_list_t *head = NULL;
   1590     bcmi_ft_flowchecker_list_t *temp = NULL;
   1591 
   1592     if (!BCMI_FT_IDX_IS_CHECK(check_id)) {
   1593         return BCM_E_PARAM;
   1594     }
   1595     index = BCMI_FT_FLOWCHECKER_INDEX_GET(check_id);
   1596     if (bcmi_ft_flowchecker_is_invalid(unit, index)) {
   1597         return BCM_E_PARAM;
   1598     }
   1599 
   1600     if (options & BCMI_FT_GROUP_CHECK_MATCH_PRIMARY) {
   1601         if (!BCMI_FT_IDX_IS_PRIMARY_CHECK(check_id)) {
   1602             return BCM_E_PARAM;
   1603         }
   1604     }
   1605 
   1606     if(options & BCMI_FT_GROUP_CHECK_MATCH_GROUP) {
   1607         /* Search for CheckId in the Group */
   1608         if (bcmi_ft_group_is_invalid(unit, id)) {
   1609             return BCM_E_NOT_FOUND;
   1610         }
   1611         head = BCMI_FT_GROUP_FLOWCHECKER_HEAD(unit, id);
   1612         if (!head) {
   1613             return BCM_E_NOT_FOUND;
   1614         }
   1615         temp = (head);
   1616         while(temp) {
   1617             if (temp->flowchecker_id == check_id) {
   1618                 found = TRUE;
   1619                 break;
   1620             }
   1621             temp = temp->next;
   1622         }
   1623         if (found == FALSE) {
   1624             return BCM_E_PARAM;
   1625         }
   1626     }
   1627 
   1628     return BCM_E_NONE;
   1629 }
   1630 
   1631 
   1632 #else /* BCM_FLOWTRCAKER_SUPPORT*/
   1633 int bcmi_ft_check_not_empty;
   1634 #endif /* BCM_FLOWTRCAKER_SUPPORT */