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_group.c (120045B)


      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 
     13 #include <bcm_int/esw/flowtracker/ft_group.h>
     14 
     15 #if defined(BCM_FLOWTRACKER_SUPPORT)
     16 /*
     17  * Global defines.
     18  */
     19 
     20 extern int ft_initialized[BCM_MAX_NUM_UNITS];
     21 
     22 bcmi_ft_group_flush_info_t
     23     bcmi_ft_group_flush_fields[BCMI_FT_GROUP_FLUSH_MAX_SCALE] =
     24     {{GROUP_ID0_VALIDf, GROUP_ID0f},
     25      {GROUP_ID1_VALIDf, GROUP_ID1f},
     26      {GROUP_ID2_VALIDf, GROUP_ID2f},
     27      {GROUP_ID3_VALIDf, GROUP_ID3f}};
     28 
     29 /* Internal Database for timestamp management. */
     30 bcmi_ft_group_ts_t bcmi_ft_group_ts_info[BCMI_FT_GROUP_MAX_TS_TYPE] =
     31     {{bcmFlowtrackerTrackingParamTypeTimestampNewLearn,
     32         BCMI_FT_GROUP_TS_NEW_LEARN, 4, 0},
     33      {bcmFlowtrackerTrackingParamTypeTimestampFlowStart,
     34         BCMI_FT_GROUP_TS_FLOW_START, 0, 0},
     35      {bcmFlowtrackerTrackingParamTypeTimestampFlowEnd,
     36         BCMI_FT_GROUP_TS_FLOW_END, 1, 0},
     37      {bcmFlowtrackerTrackingParamTypeTimestampCheckEvent1,
     38         BCMI_FT_GROUP_TS_CHECK_EVENT1, 2, 0},
     39      {bcmFlowtrackerTrackingParamTypeTimestampCheckEvent2,
     40         BCMI_FT_GROUP_TS_CHECK_EVENT2, 3, 0}};
     41 
     42 /* Group Sw state. */
     43 bcmi_ft_group_sw_info_t **bcmi_ft_group_sw_state[BCM_MAX_NUM_UNITS];
     44 
     45 /* Group bitmap. */
     46 bcmi_ft_group_bitmap_t bcmi_ft_group_bitmap[BCM_MAX_NUM_UNITS];
     47 
     48 
     49 /* FT group Internal methods. */
     50 
     51 /* clear the Flowtracker subsystem. */
     52 /*
     53  * Function:
     54  *     bcmi_ft_group_state_clear
     55  * Purpose:
     56  *     Clear Flowtracker group state.
     57  * Parameters:
     58  *     unit - (IN) BCM device id
     59  *     id   - (IN) FT group id.
     60  *
     61  * Returns:
     62  *     None.
     63  */
     64 
     65 void
     66 bcmi_ft_group_state_clear(int unit)
     67 {
     68 
     69     if (bcmi_ft_group_sw_state[unit] != NULL) {
     70         sal_free(bcmi_ft_group_sw_state[unit]);
     71         bcmi_ft_group_sw_state[unit] = NULL;
     72     }
     73 
     74     if (bcmi_ft_group_bitmap[unit].ft_group_bitmap != NULL) {
     75         sal_free(bcmi_ft_group_bitmap[unit].ft_group_bitmap);
     76         bcmi_ft_group_bitmap[unit].ft_group_bitmap = NULL;
     77     }
     78 
     79     return;
     80 }
     81 
     82 /*
     83  * Function:
     84  *     bcmi_ft_group_state_init
     85  * Purpose:
     86  *     Initialize Flowtracker group state.
     87  * Parameters:
     88  *     unit - (IN) BCM device id
     89  *
     90  * Returns:
     91  *     None.
     92  */
     93 int bcmi_ft_group_state_init(int unit)
     94 {
     95 
     96     int num_groups = 0;
     97     soc_mem_t mem;
     98 
     99     mem = BSC_KG_GROUP_TABLEm;
    100 
    101     /* total number of groups. */
    102     num_groups = soc_mem_index_count(unit, mem);
    103 
    104     /* Allocate group software state. */
    105     bcmi_ft_group_sw_state[unit] = (bcmi_ft_group_sw_info_t **)
    106         sal_alloc((num_groups *
    107             sizeof(bcmi_ft_group_sw_info_t *)),
    108         "flowtracker group sw state");
    109 
    110     if (bcmi_ft_group_sw_state[unit] == NULL) {
    111         return BCM_E_MEMORY;
    112     }
    113 
    114     sal_memset(bcmi_ft_group_sw_state[unit], 0,
    115         (num_groups * sizeof(bcmi_ft_group_sw_info_t *)));
    116 
    117     /* Allocate Group bitmap space for all the groups. */
    118     BCMI_FT_GROUP_BITMAP(unit) =
    119         sal_alloc(SHR_BITALLOCSIZE(num_groups),"ft_group_bitmap");
    120 
    121     if (bcmi_ft_group_bitmap[unit].ft_group_bitmap == NULL) {
    122         bcmi_ft_group_state_clear(unit);
    123     }
    124 
    125     sal_memset(bcmi_ft_group_bitmap[unit].ft_group_bitmap, 0,
    126                SHR_BITALLOCSIZE(num_groups));
    127 
    128     /*
    129      * Each group structure is not allocated here.
    130      * That will be allocated when each group is created.
    131      */
    132 
    133     return BCM_E_NONE;
    134 }
    135 
    136 /*
    137  * Function:
    138  *     bcmi_ft_group_get_free_index
    139  * Purpose:
    140  *     get free index for the group.
    141  * Parameters:
    142  *     unit - (IN) BCM device id
    143  *     id   - (OUT) FT group id.
    144  *
    145  * Returns:
    146  *     BCM_E_XXX.
    147  */
    148 int
    149 bcmi_ft_group_get_free_index(int unit, int *index)
    150 {
    151 
    152     int num_groups = 0;
    153     int i = 0;
    154 
    155     soc_mem_t mem;
    156     mem = BSC_KG_GROUP_TABLEm;
    157 
    158     /* Total number of groups in device. */
    159     num_groups = soc_mem_index_count(unit, mem);
    160 
    161     if (*index != -1) {
    162         /*
    163          * if valid index is sent, then use it.
    164          * Index free check is already done.
    165          */
    166         i = *index;
    167     }
    168 
    169     for (; i<num_groups; i++) {
    170         if (!(SHR_BITGET(BCMI_FT_GROUP_BITMAP(unit), i))) {
    171             /* Got the free index. use it. */
    172             SHR_BITSET(BCMI_FT_GROUP_BITMAP(unit), i);
    173             *index = i;
    174             return BCM_E_NONE;
    175         }
    176     }
    177 
    178     return BCM_E_RESOURCE;
    179 }
    180 
    181 /*
    182  * Function:
    183  *     bcmi_ft_group_is_invalid
    184  * Purpose:
    185  *     Check if the group is invalid.
    186  * Parameters:
    187  *     unit - (IN) BCM device id
    188  *     group_index   - (OUT) FT group id.
    189  *
    190  * Returns:
    191  *     BCM_E_XXX
    192  */
    193 int
    194 bcmi_ft_group_is_invalid(
    195             int unit,
    196             bcm_flowtracker_group_t group_index)
    197 {
    198     int num_groups = 0;
    199 
    200     num_groups = soc_mem_index_max(unit, BSC_KG_GROUP_TABLEm);
    201 
    202     if (!ft_initialized[unit]) {
    203         return BCM_E_INIT;
    204     }
    205 
    206     if (group_index > num_groups) {
    207         return BCM_E_PARAM;
    208     }
    209 
    210     if (BCMI_FT_GROUP_BITMAP(unit) == NULL) {
    211         return BCM_E_INIT;
    212     }
    213 
    214     if (bcmi_ft_group_sw_state[unit] == NULL) {
    215         return BCM_E_INIT;
    216     }
    217 
    218     if (!(SHR_BITGET(BCMI_FT_GROUP_BITMAP(unit), group_index))) {
    219         return BCM_E_NOT_FOUND;
    220     }
    221 
    222     if (BCMI_FT_GROUP(unit, group_index) == NULL) {
    223         return BCM_E_NOT_FOUND;
    224     }
    225 
    226     return BCM_E_NONE;
    227 }
    228 
    229 /*
    230  * Function:
    231  *     bcmi_ft_group_collector_is_valid
    232  * Purpose:
    233  *     Check if collector is associated with ft group.
    234  * Parameters:
    235  *     unit - (IN) BCM device id
    236  *     id   - (IN) FT group id.
    237  *
    238  * Returns:
    239  *     BCM_E_XXX
    240  */
    241 int
    242 bcmi_ft_group_collector_is_valid(
    243             int unit,
    244             bcm_flowtracker_group_t id)
    245 {
    246     if (!ft_initialized[unit]) {
    247         return BCM_E_INIT;
    248     }
    249 
    250     if (BCMI_FT_GROUP(unit, id)->collector_id == BCMI_FT_COLLECTOR_ID_INVALID) {
    251         return BCM_E_NOT_FOUND;
    252     }
    253 
    254     return BCM_E_NONE;
    255 }
    256 
    257 /*
    258  * Function:
    259  *     bcmi_ft_group_create
    260  * Purpose:
    261  *     Create flowtracker group id.
    262  * Description :
    263  *     This function only creates a sw group index
    264  *     and allocates sw memory to store groups information.
    265  * Parameters:
    266  *     unit - (IN) BCM device id
    267  *     options - (IN) options for group creation
    268  *     id   - (OUT) FT group id.
    269  *     flow_group_info - (IN) Information of group.
    270  *
    271  * Returns:
    272  *     BCM_E_XXX
    273  */
    274 int
    275 bcmi_ft_group_create(
    276     int unit,
    277     uint32 options,
    278     bcm_flowtracker_group_t *id,
    279     bcm_flowtracker_group_info_t *flow_group_info)
    280 {
    281     int group_index = -1;
    282     int rv = BCM_E_NONE;
    283     int create = 1;
    284     bcm_flowtracker_group_stat_t group_stats;
    285 
    286     if (id == NULL) {
    287         return BCM_E_PARAM;
    288     }
    289 
    290     if (flow_group_info == NULL) {
    291         return BCM_E_PARAM;
    292     }
    293 
    294     if (!ft_initialized[unit]) {
    295         return BCM_E_INIT;
    296     }
    297 
    298     if ((options & BCM_FLOWTRACKER_GROUP_REPLACE) &&
    299        (!(options & BCM_FLOWTRACKER_GROUP_WITH_ID))) {
    300         return BCM_E_PARAM;
    301     }
    302 
    303     if (options & BCM_FLOWTRACKER_GROUP_REPLACE) {
    304         group_index = *id;
    305 
    306         if (group_index > soc_mem_index_max(unit, BSC_KG_GROUP_TABLEm)) {
    307             return BCM_E_PARAM;
    308         }
    309 
    310         /* Check if valid group and id range. */
    311         if (bcmi_ft_group_is_invalid(unit, group_index)) {
    312             return (BCM_E_NOT_FOUND);
    313         }
    314 
    315         if (BCMI_FT_GROUP(unit, group_index)) {
    316             if (BCMI_FT_GROUP_IS_BUSY(unit, group_index)) {
    317                 return BCM_E_CONFIG;
    318             }
    319         }
    320 
    321     } else {
    322         if (options & BCM_FLOWTRACKER_GROUP_WITH_ID) {
    323 
    324             group_index = *id;
    325 
    326             /* Check if valid group and id range. */
    327             if (!bcmi_ft_group_is_invalid(unit, group_index)) {
    328                 return (BCM_E_EXISTS);
    329             }
    330 
    331         }
    332 
    333         /*  Allocating a new group. Get a free group index. */
    334         BCM_IF_ERROR_RETURN(bcmi_ft_group_get_free_index(unit,
    335             &group_index));
    336 
    337         /* Allocate the sw state for this group first. */
    338         BCMI_FT_GROUP(unit, group_index) = (bcmi_ft_group_sw_info_t *)
    339             sal_alloc(sizeof(bcmi_ft_group_sw_info_t),
    340             "flowtracker group sw state");
    341 
    342         if (BCMI_FT_GROUP(unit, group_index) == NULL) {
    343             return BCM_E_MEMORY;
    344         }
    345 
    346         /* memset everything to zero. */
    347         sal_memset(BCMI_FT_GROUP(unit, group_index), 0,
    348             sizeof(bcmi_ft_group_sw_info_t));
    349 
    350     }
    351 
    352     /* Write group related information in hw tables.*/
    353     rv = bcmi_ft_group_entry_update(unit, group_index, flow_group_info, create);
    354 
    355     CLEANUP_ON_ERROR(rv)
    356 
    357     /* Set by default direction of group as forward. */
    358     bcmi_flowtracker_group_control_set(unit,group_index,
    359         bcmFlowtrackerGroupControlFlowDirection,
    360         bcmFlowtrackerFlowDirectionForward);
    361 
    362     /* Set by default, flowtrack and new learn control */
    363     BCMI_FT_GROUP_FTFP_DATA(unit, group_index).new_learn = TRUE;
    364     BCMI_FT_GROUP_FTFP_DATA(unit, group_index).flowtrack = TRUE;
    365 
    366     /* Copy flags. */
    367     (BCMI_FT_GROUP(unit, group_index))->flags = flow_group_info->group_flags;
    368     if (flow_group_info->group_flags & BCM_FLOWTRACKER_GROUP_USER_ENTRIES_ONLY) {
    369         BCMI_FT_GROUP_FTFP_DATA(unit, group_index).new_learn = 0;
    370     }
    371 
    372     /* Assign invalid ids at group creation. */
    373     (BCMI_FT_GROUP(unit, group_index))->template_id = BCMI_FT_TEMPLATE_ID_INVALID;
    374     (BCMI_FT_GROUP(unit, group_index))->collector_id = BCMI_FT_COLLECTOR_ID_INVALID;
    375 
    376     /* Clear up old stats */
    377     bcm_flowtracker_group_stat_t_init(&group_stats);
    378     rv = bcm_esw_flowtracker_group_stat_set(unit, group_index, &group_stats);
    379     CLEANUP_ON_ERROR(rv);
    380 
    381     *id = group_index;
    382 
    383     return BCM_E_NONE;
    384 
    385 cleanup:
    386     bcmi_ft_group_clear(unit, group_index);
    387 
    388     return rv;
    389 }
    390 
    391 /*
    392  * Function:
    393  *     bcmi_ft_group_create
    394  * Purpose:
    395  *     Create flowtracker group id.
    396  * Description :
    397  *     This function only creates a sw group index
    398  *     and allocates sw memory to store groups information.
    399  * Parameters:
    400  *     unit - (IN) BCM device id
    401  *     options - (IN) options for group creation
    402  *     id   - (OUT) FT group id.
    403  *     flow_group_info - (IN) Information of group.
    404  *
    405  * Returns:
    406  *     BCM_E_XXX
    407  */
    408 
    409 int
    410 bcmi_ft_group_entry_update(int unit, bcm_flowtracker_group_t group_id,
    411                            bcm_flowtracker_group_info_t *info,
    412                            int create)
    413 {
    414     int rv = BCM_E_NONE;
    415     int fid_len = 0;
    416     bsc_kg_group_table_entry_t kg_group_entry;
    417     bsc_dg_group_table_entry_t dg_group_entry;
    418 
    419     sal_memset(&kg_group_entry, 0, sizeof(bsc_kg_group_table_entry_t));
    420     sal_memset(&dg_group_entry, 0, sizeof(bsc_dg_group_table_entry_t));
    421 
    422     if (create) {
    423 
    424         if (!info) {
    425             return BCM_E_PARAM;
    426         }
    427         fid_len = soc_mem_field_length(unit, BSC_DG_GROUP_TABLEm, CLASS_IDf);
    428 
    429         if (info->group_class > ((1 << fid_len) -1)) {
    430             return BCM_E_PARAM;
    431         }
    432 
    433         soc_mem_field32_set(unit, BSC_DG_GROUP_TABLEm, &dg_group_entry,
    434                         CLASS_IDf, info->group_class);
    435 
    436         soc_mem_field32_set(unit, BSC_DG_GROUP_TABLEm, &dg_group_entry,
    437                         GROUP_VALIDf, 1);
    438 
    439         soc_mem_field32_set(unit, BSC_KG_GROUP_TABLEm, &kg_group_entry,
    440                         GROUP_VALIDf, 1);
    441     }
    442 
    443     /* Write into hardware memory. */
    444     rv = soc_mem_write(unit, BSC_KG_GROUP_TABLEm, MEM_BLOCK_ALL,
    445                        group_id, &kg_group_entry);
    446 
    447     if (BCM_FAILURE(rv)) {
    448         return rv;
    449     }
    450 
    451     /* Write into the hardware. */
    452     rv = soc_mem_write(unit, BSC_DG_GROUP_TABLEm, MEM_BLOCK_ALL,
    453                        group_id, &dg_group_entry);
    454 
    455     return rv;
    456 }
    457 
    458 /*
    459  * Function:
    460  *     bcmi_ft_group_get
    461  * Purpose:
    462  *     Get information of flowtracker group.
    463  * Parameters:
    464  *     unit - (IN) BCM device id
    465  *     id   - (IN) FT group id.
    466  *     flow_group_info - (IN) Information of group.
    467  *
    468  * Returns:
    469  *     BCM_E_XXX
    470  */
    471 int
    472 bcmi_ft_group_get(
    473         int unit,
    474         bcm_flowtracker_group_t id,
    475         bcm_flowtracker_group_info_t *flow_group_info)
    476 {
    477 
    478     bsc_dg_group_table_entry_t dg_group_entry;
    479 
    480 
    481     if (flow_group_info == NULL) {
    482         return BCM_E_PARAM;
    483     }
    484 
    485     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
    486 
    487     sal_memset(&dg_group_entry, 0, sizeof(bsc_dg_group_table_entry_t));
    488 
    489     /* First read the group entry. */
    490     BCM_IF_ERROR_RETURN (soc_mem_read(unit, BSC_DG_GROUP_TABLEm,
    491         MEM_BLOCK_ANY, id, &dg_group_entry));
    492 
    493     flow_group_info->group_class =
    494         soc_mem_field32_get(unit, BSC_DG_GROUP_TABLEm, &dg_group_entry,
    495                         CLASS_IDf);
    496 
    497     return BCM_E_NONE;
    498 }
    499 
    500 /*
    501  * Function:
    502  *     bcmi_ft_group_clear
    503  * Purpose:
    504  *     Clear flowtracker group.
    505  * Parameters:
    506  *     unit - (IN) BCM device id
    507  *     id   - (OUT) FT group id.
    508  *
    509  * Returns:
    510  *     BCM_E_XXX
    511  */
    512 int
    513 bcmi_ft_group_clear(
    514         int unit,
    515         bcm_flowtracker_group_t id)
    516 {
    517 
    518     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
    519 
    520     /* Make sure that extraction info was cleared. */
    521     if (BCMI_FT_GROUP_EXT_DATA_INFO(unit, id) != NULL) {
    522         sal_free(BCMI_FT_GROUP_EXT_DATA_INFO(unit, id));
    523         BCMI_FT_GROUP_EXT_DATA_INFO(unit, id) = NULL;
    524     }
    525 
    526     if (BCMI_FT_GROUP_TRACK_PARAM(unit, id) != NULL) {
    527         sal_free(BCMI_FT_GROUP_TRACK_PARAM(unit, id));
    528         BCMI_FT_GROUP_TRACK_PARAM(unit, id) = NULL;
    529     }
    530 
    531     if (BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_key != NULL) {
    532         sal_free(BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_key);
    533         BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_key = NULL;
    534     }
    535 
    536     if (BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_data != NULL) {
    537         sal_free(BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_data);
    538         BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_data = NULL;
    539     }
    540 
    541 
    542     /* Clear the sw state. */
    543     sal_free(BCMI_FT_GROUP(unit, id));
    544     BCMI_FT_GROUP(unit, id) = NULL;
    545 
    546     /* Free the bitmap. */
    547     SHR_BITCLR(BCMI_FT_GROUP_BITMAP(unit), id);
    548 
    549 
    550     return BCM_E_NONE;
    551 }
    552 
    553 /*
    554  * Function:
    555  *     bcmi_ft_group_destroy
    556  * Purpose:
    557  *     Destroy flowtracker group.
    558  * Parameters:
    559  *     unit - (IN) BCM device id
    560  *     id   - (OUT) FT group id.
    561  *
    562  * Returns:
    563  *     BCM_E_XXX
    564  */
    565 int
    566 bcmi_ft_group_destroy(
    567         int unit,
    568         bcm_flowtracker_group_t id)
    569 {
    570 
    571     int rv = BCM_E_NONE;
    572 
    573     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
    574 
    575     if (BCMI_FT_GROUP_IS_BUSY(unit, id)) {
    576         LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
    577             "Trying to delete flow Group (%d) while it is installed.\n "), id));
    578 
    579         return BCM_E_BUSY;
    580     }
    581 
    582     if (BCMI_FT_GROUP_CHECK_LIST(unit, id)) {
    583         LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
    584             "Deleting Flow Group (%d) while check is attached.\n "), id));
    585         return BCM_E_BUSY;
    586     }
    587 
    588     /* Check that collector is detached from the group. This check
    589      * also make sure that user entries, in case of software managed Group
    590      * are also removed
    591      */
    592     if (BCMI_FT_COLLECTOR_ID_INVALID !=
    593             BCMI_FT_GROUP(unit, id)->collector_id) {
    594         LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
    595                         "Deleting Flow Group (%d) while collector is"
    596                         " attached.\n "), id));
    597         return BCM_E_BUSY;
    598     }
    599 
    600     /* Uninstall the group */
    601     if (BCMI_FT_GROUP_IS_VALIDATED(unit, id)) {
    602         BCM_IF_ERROR_RETURN(bcmi_esw_ft_group_hw_uninstall(unit, id));
    603     }
    604 
    605     rv = bcmi_ft_group_profiles_destroy(unit, id);
    606     if (BCM_FAILURE(rv)) {
    607         return rv;
    608     }
    609 
    610     rv = bcmi_ft_group_entry_update(unit, id, NULL, 0);
    611     if (BCM_FAILURE(rv)) {
    612         return rv;
    613     }
    614 
    615     bcmi_ft_group_clear(unit, id);
    616 
    617     return rv;
    618 }
    619 
    620 /*
    621  * Function:
    622  *      bcmi_ft_group_get_all
    623  * Purpose:
    624  *      Returns the list of flowtracker group created in the system.
    625  * Parameters:
    626  *      unit                - (IN) BCM device number
    627  *      max_size            - (IN) Size of array 'idz'
    628  *      idz                 - (OUT) Array of flowtracker group.
    629  *      list_size           - (OUT) Numbe of indices filled in 'idz'
    630  * Returns:
    631  *      BCM_E_XXX   - BCM error code.
    632  */
    633 int
    634 bcmi_ft_group_get_all(
    635     int unit,
    636     int max_size,
    637     bcm_flowtracker_group_t *idz,
    638     int *list_size)
    639 {
    640     int max_avail_groups = 0;
    641     int i = 0, j = 0;
    642     soc_mem_t mem;
    643 
    644     /* If the max_size is non zero and list == NULL, return
    645      * BCM_E_PARAM.
    646      */
    647     if ((max_size != 0) && (idz == NULL)) {
    648         return BCM_E_PARAM;
    649     }
    650 
    651     if (list_size == NULL) {
    652         return BCM_E_PARAM;
    653     }
    654 
    655     /* Total number of groups in device. */
    656     mem = BSC_KG_GROUP_TABLEm;
    657     max_avail_groups = soc_mem_index_count(unit, mem);
    658 
    659     SHR_BITCOUNT_RANGE(BCMI_FT_GROUP_BITMAP(unit),
    660             *list_size, 0, max_avail_groups);
    661 
    662     if (max_size == 0) {
    663         return BCM_E_NONE;
    664     }
    665 
    666     for (i = 0, j = 0; (i < max_avail_groups) && (j < max_size); i++) {
    667         if (SHR_BITGET(BCMI_FT_GROUP_BITMAP(unit), i)) {
    668             idz[j] = i;
    669             j++;
    670         }
    671     }
    672     *list_size = j;
    673 
    674     return BCM_E_NONE;
    675 }
    676 
    677 /*
    678  * Function:
    679  *     bcmi_ft_group_tracking_param_set
    680  * Purpose:
    681  *     Set tracking parameters for the group.
    682  * Parameters:
    683  *     unit - (IN) BCM device id
    684  *     id   - (OUT) FT group id.
    685  *     num_tracking_elements - (IN) number of tracking params.
    686  *     list_of_tracking_elements - (IN) list of tracking params.
    687  *
    688  * Returns:
    689  *     BCM_E_XXX
    690  */
    691 int
    692 bcmi_ft_group_tracking_param_set(
    693     int unit,
    694     bcm_flowtracker_group_t id,
    695     int num_tracking_elements,
    696     bcm_flowtracker_tracking_param_info_t *list_of_tracking_elements)
    697 {
    698 
    699     int rv = BCM_E_NONE;
    700 
    701     /*
    702      * This function does nothing but it just sets the tracking
    703      * parameters in the sw state.
    704      */
    705 
    706     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
    707 
    708     if (BCMI_FT_GROUP_IS_BUSY(unit, id)) {
    709         return BCM_E_CONFIG;
    710     }
    711 
    712     if ((num_tracking_elements < 0) || (list_of_tracking_elements == NULL)) {
    713         return BCM_E_PARAM;
    714     }
    715 
    716     /* Clear the existing tracking params. */
    717     if (BCMI_FT_GROUP_TRACK_PARAM(unit, id)) {
    718         sal_free(BCMI_FT_GROUP_TRACK_PARAM(unit, id));
    719         BCMI_FT_GROUP_TRACK_PARAM(unit, id) = NULL;
    720     }
    721 
    722     if (num_tracking_elements == 0) {
    723         /* User wants to clear the tracking params. */
    724         return BCM_E_NONE;
    725     }
    726 
    727     /* Check if the list elements are valid. */
    728     rv = bcmi_ft_group_param_element_validate(unit,
    729                                               id,
    730                                               num_tracking_elements,
    731                                               list_of_tracking_elements);
    732 
    733     if (BCM_FAILURE(rv)) {
    734         return rv;
    735     }
    736 
    737     BCMI_FT_GROUP_TRACK_PARAM(unit, id) =
    738         (bcm_flowtracker_tracking_param_info_t *)
    739         sal_alloc((sizeof(bcm_flowtracker_tracking_param_info_t) *
    740                    num_tracking_elements),
    741         "flowtracker group tracking parameters");
    742 
    743     if (BCMI_FT_GROUP_TRACK_PARAM(unit, id) == NULL) {
    744         return BCM_E_MEMORY;
    745     }
    746 
    747     /* Update sw state with the tracking parameters. */
    748     (BCMI_FT_GROUP_TRACK_PARAM_NUM(unit, id)) = num_tracking_elements;
    749 
    750     sal_memcpy((BCMI_FT_GROUP_TRACK_PARAM(unit, id)),
    751                 list_of_tracking_elements,
    752                 (sizeof(bcm_flowtracker_tracking_param_info_t) *
    753                  num_tracking_elements));
    754 
    755     /* Set tracking param based triggers. last param is 1. */
    756     bcmi_ft_group_ts_triggers_set(unit, id, 0, BCMI_FT_TS_TYPE_TP,
    757         bcmFlowtrackerFlowCheckTsSet);
    758 
    759     return rv;
    760 }
    761 
    762 /*
    763  * Function:
    764  *     bcmi_ft_group_param_element_validate
    765  * Purpose:
    766  *     Set tracking parameters for the group.
    767  * Parameters:
    768  *     unit - (IN) BCM device id
    769  *     id   - (OUT) FT group id.
    770  *     num_tracking_elements - (IN) number of tracking params.
    771  *     list_of_tracking_elements - (IN) list of tracking params.
    772  *
    773  * Returns:
    774  *     BCM_E_XXX
    775  */
    776 
    777 int
    778 bcmi_ft_group_param_element_validate(
    779     int unit,
    780     bcm_flowtracker_group_t flow_group_id,
    781     int num_tracking_elements,
    782     bcm_flowtracker_tracking_param_info_t *list_of_tracking_elements)
    783 {
    784     int rv = BCM_E_NONE;
    785     int iter = 0;
    786     int ts_count = 0;
    787     bcm_flowtracker_tracking_param_info_t element_info;
    788 
    789     for (iter = 0; iter < num_tracking_elements; iter++) {
    790         sal_memcpy((void *)(&element_info),
    791                    (void *)(&(list_of_tracking_elements[iter])),
    792                    sizeof(bcm_flowtracker_tracking_param_info_t));
    793 
    794         if (element_info.param >= bcmFlowtrackerTrackingParamTypeCount) {
    795             return BCM_E_PARAM;
    796         }
    797 
    798         if (bcmi_ft_tracking_param_is_timestamp(unit, element_info.param)) {
    799             ts_count++;
    800         }
    801 
    802         if (ts_count > BCMI_FT_GROUP_MAX_TS) {
    803 
    804             LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
    805                     (BSL_META_U(unit, "Maximum timestamps allowed on a group"
    806                                 " are only = %d\n"), BCMI_FT_GROUP_MAX_TS));
    807             return BCM_E_CONFIG;
    808         }
    809 
    810         /* Tracking Param Flowtracker Check is validated. */
    811         if (element_info.param == bcmFlowtrackerTrackingParamTypeFlowtrackerCheck) {
    812             rv = bcmi_ft_group_check_validate(unit,
    813                         BCMI_FT_GROUP_CHECK_MATCH_PRIMARY,
    814                         flow_group_id, element_info.check_id);
    815             BCM_IF_ERROR_RETURN(rv);
    816         }
    817 
    818         /* VNID is not supported in tracking param data as we can not export it currently. */
    819         if ((element_info.flags != BCM_FLOWTRACKER_TRACKING_PARAM_TYPE_KEY) &&
    820             ((element_info.param == bcmFlowtrackerTrackingParamTypeVxlanNetworkId) ||
    821             (element_info.param == bcmFlowtrackerTrackingParamTypeTunnelClass))) {
    822             return BCM_E_PARAM;
    823         }
    824     }
    825 
    826     return BCM_E_NONE;
    827 }
    828 
    829 
    830 /*
    831  * Function:
    832  *     bcmi_ft_group_tracking_param_orde_get
    833  * Purpose:
    834  *     Get tracking parameters for the group.
    835  *     The tracking params can be in order how user
    836  *     has sent the data or internal reordered data based on
    837  *     template.
    838  * Parameters:
    839  *     unit - (IN) BCM device id
    840  *     order - (IN) ordered elements based on template.
    841  *     id   - (OUT) FT group id.
    842  *     max_size - max size that user asked for.
    843  *     list_of_tracking_elements - (IN) list of tracking params.
    844  *     num_tracking_elements - (IN) number of tracking params.
    845  *
    846  * Returns:
    847  *     BCM_E_XXX
    848  */
    849 int
    850 bcmi_group_tracking_param_order_get(
    851         int unit,
    852         int order,
    853         bcm_flowtracker_group_t id,
    854         int max_size,
    855         bcm_flowtracker_tracking_param_info_t *list_of_tracking_elements,
    856         int *num_tracking_elements)
    857 {
    858 
    859     if (num_tracking_elements == NULL) {
    860         return BCM_E_PARAM;
    861     }
    862 
    863 
    864     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
    865 
    866     /* If the max_alu_info is non zero and list == NULL, return
    867      * BCM_E_PARAM.
    868      */
    869     if ((max_size != 0) && (list_of_tracking_elements == NULL)) {
    870         return BCM_E_PARAM;
    871     }
    872 
    873     if (order) {
    874         *num_tracking_elements = BCMI_FT_GROUP_ORDERED_TRACK_PARAM_NUM(unit, id);
    875     } else {
    876         *num_tracking_elements = BCMI_FT_GROUP_TRACK_PARAM_NUM(unit, id);
    877     }
    878 
    879     /* If max_alu_info == 0,
    880      * return the number of export elements in list_size
    881      * variable.
    882      */
    883     if (max_size == 0 && list_of_tracking_elements == NULL) {
    884 
    885         return BCM_E_NONE;
    886     }
    887 
    888     /* Pick the number of elements to send back. */
    889     *num_tracking_elements = (*num_tracking_elements < max_size) ?
    890                               (*num_tracking_elements) : max_size;
    891 
    892 
    893     if (order) {
    894         sal_memcpy(list_of_tracking_elements,
    895                BCMI_FT_GROUP_TRACK_PARAM(unit, id),
    896                (sizeof(bcm_flowtracker_tracking_param_info_t) *
    897                (*num_tracking_elements)));
    898     } else {
    899         sal_memcpy(list_of_tracking_elements,
    900                BCMI_FT_GROUP_TRACK_PARAM(unit, id),
    901                (sizeof(bcm_flowtracker_tracking_param_info_t) *
    902                (*num_tracking_elements)));
    903     }
    904 
    905     return BCM_E_NONE;
    906 }
    907 
    908 
    909 /*
    910  * Function:
    911  *     bcmi_ft_group_tracking_param_get
    912  * Purpose:
    913  *     Get tracking parameters for the group.
    914  * Parameters:
    915  *     unit - (IN) BCM device id
    916  *     id   - (OUT) FT group id.
    917  *     max_size - max size that user asked for.
    918  *     list_of_tracking_elements - (IN) list of tracking params.
    919  *     num_tracking_elements - (IN) number of tracking params.
    920  *
    921  * Returns:
    922  *     BCM_E_XXX
    923  */
    924 int
    925 bcmi_ft_group_tracking_param_get(
    926         int unit,
    927         bcm_flowtracker_group_t id,
    928         int max_size,
    929         bcm_flowtracker_tracking_param_info_t *list_of_tracking_elements,
    930         int *num_tracking_elements)
    931 
    932 {
    933 
    934     BCM_IF_ERROR_RETURN(bcmi_group_tracking_param_order_get(unit, 0,
    935         id, max_size, list_of_tracking_elements, num_tracking_elements));
    936 
    937     return BCM_E_NONE;
    938 }
    939 
    940 /*
    941  * Function:
    942  *     bcmi_ft_group_param_operate
    943  * Purpose:
    944  *     Operate group state parameters.
    945  * Parameters:
    946  *     unit - (IN) BCM device id
    947  *     value - (IN) data Value of the update
    948  *     opr   - (IN) operation to be performed on data.
    949  *     arg  - (IN) argument value.
    950  *
    951  * Returns:
    952  *     BCM_E_XXX
    953  */
    954 int
    955 bcmi_ft_group_param_operate(int unit,
    956                            uint32 *value,
    957                            bcmi_ft_group_params_operation_t opr,
    958                            int arg)
    959 {
    960 
    961 
    962     if (opr >= bcmiFtGroupParamOprCount) {
    963         return BCM_E_PARAM;
    964     }
    965 
    966     switch (opr) {
    967 
    968         case bcmiFtGroupParamsOprInc:
    969             *value += arg;
    970         break;
    971 
    972         case bcmiFtGroupParamsOprDec:
    973             *value -= arg;
    974         break;
    975 
    976         case bcmiFtGroupParamsOprUpdate:
    977             *value = arg;
    978         break;
    979 
    980         default:
    981             return BCM_E_PARAM;
    982     }
    983 
    984     return BCM_E_NONE;
    985 }
    986 
    987 /*
    988  * Function:
    989  *     bcmi_ft_group_param_update
    990  * Purpose:
    991  *     Update group state parameters.
    992  * Parameters:
    993  *     unit - (IN) BCM device id
    994  *     id   - (IN) FT group id.
    995  *     param - (IN) Group's parameters.
    996  *     opr   - (IN) operation to be performed on data.
    997  *     arg  - (IN) argument value.
    998  *
    999  * Returns:
   1000  *     BCM_E_XXX
   1001  */
   1002 int
   1003 bcmi_ft_group_param_update(int unit,
   1004                            bcm_flowtracker_group_t id,
   1005                            bcmi_ft_group_params_t param,
   1006                            bcmi_ft_group_params_operation_t opr,
   1007                            int arg)
   1008 {
   1009 
   1010 
   1011    /* First check if group is valid. */
   1012     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   1013 
   1014     switch (param) {
   1015 
   1016     case bcmiFtGroupParamFtfpEntryNum:
   1017         bcmi_ft_group_param_operate(unit,
   1018             (&(BCMI_FT_GROUP(unit, id)->num_ftfp_entries)), opr, arg);
   1019     break;
   1020     default:
   1021         return BCM_E_PARAM;
   1022     }
   1023 
   1024     return BCM_E_NONE;
   1025 }
   1026 
   1027 /*
   1028  * Function:
   1029  *     bcmi_ft_group_param_retrieve
   1030  * Purpose:
   1031  *     Get group state parameters.
   1032  * Parameters:
   1033  *     unit - (IN) BCM device id
   1034  *     id   - (IN) FT group id.
   1035  *     param - (IN) Group's parameters.
   1036  *     arg  - (OUT) argument value.
   1037  *
   1038  * Returns:
   1039  *     BCM_E_XXX
   1040  */
   1041 int
   1042 bcmi_ft_group_param_retrieve(int unit,
   1043                         bcm_flowtracker_group_t id,
   1044                         bcmi_ft_group_params_t param,
   1045                         int *arg)
   1046 {
   1047 
   1048    /* First check if group is valid. */
   1049     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   1050 
   1051     switch (param) {
   1052 
   1053     case bcmiFtGroupParamFtfpEntryNum:
   1054         *arg = BCMI_FT_GROUP(unit, id)->num_ftfp_entries;
   1055     break;
   1056 
   1057     default:
   1058         return BCM_E_PARAM;
   1059     }
   1060 
   1061     return BCM_E_NONE;
   1062 }
   1063 
   1064 
   1065 /*
   1066  * Function:
   1067  *     bcmi_ft_group_32bit_to_16_bit_param_conversion
   1068  * Purpose:
   1069  *     BCM56370 can not store more than 16 bits in PDD.
   1070  *     therefore some 32 parameters may need split to perform
   1071  *     various checks and export.
   1072  * Parameters:
   1073  *     unit - (IN) BCM device id
   1074  *     id   - (IN) FT group id.
   1075  *     info  - (IN) list if ALU/load information.
   1076  *
   1077  * Returns:
   1078  *     BCM_E_XXX
   1079  */
   1080 int
   1081 bcmi_ft_group_32bit_to_16_bit_param_conversion(
   1082                int unit,
   1083                bcm_flowtracker_group_t id,
   1084                bcmi_ft_group_alu_info_t **info)
   1085 {
   1086 
   1087     bcmi_ft_group_alu_info_t *temp;
   1088     int num_alus_loads = 0, new_num_alus_loads = 0;
   1089     bcmi_ft_group_alu_info_t alu1, alu2;
   1090     bcmi_ft_group_alu_info_t *new_alloc = NULL;
   1091     int i = 0;
   1092     bcmi_flowtracker_flowchecker_info_t fc_info;
   1093 
   1094     /* Get total number of alus in this chunk. */
   1095     num_alus_loads = (BCMI_FT_GROUP_EXT_INFO(unit, id)).num_data_info;
   1096 
   1097     if (!num_alus_loads) {
   1098         return BCM_E_NONE;
   1099     }
   1100 
   1101     if (*info == NULL) {
   1102         return BCM_E_NONE;
   1103     }
   1104 
   1105     temp = *info;
   1106 
   1107     sal_memset(&alu1, 0, sizeof(bcmi_ft_group_alu_info_t));
   1108     sal_memset(&alu2, 0, sizeof(bcmi_ft_group_alu_info_t));
   1109     sal_memset(&fc_info, 0, sizeof(bcmi_flowtracker_flowchecker_info_t));
   1110 
   1111     /* allocate the bitmap based on the type, length */
   1112     for (i=0; i<num_alus_loads; i++) {
   1113         /*temp = (&((*info)[i]));*/
   1114         temp = *info;
   1115         if (BCMI_FT_IDX_IS_CHECK(temp[i].flowchecker_id)) {
   1116 
   1117             BCM_IF_ERROR_RETURN(bcmi_ft_flowchecker_get
   1118                 (unit, temp[i].flowchecker_id, &fc_info));
   1119         }
   1120 
   1121         /* If check has update DoS attack || if exporting dos attack as data. */
   1122         if ((((temp[i].action_element_type == bcmFlowtrackerTrackingParamTypeDosAttack) ||
   1123              (temp[i].action_element_type == bcmFlowtrackerTrackingParamTypeInnerDosAttack)) &&
   1124             (fc_info.action_info.action == bcmFlowtrackerCheckActionUpdateValue)) ||
   1125             ((temp[i].key1.is_alu == 0) &&
   1126             ((temp[i].element_type1 == bcmFlowtrackerTrackingParamTypeDosAttack) ||
   1127             (temp[i].element_type1 == bcmFlowtrackerTrackingParamTypeInnerDosAttack)))) {
   1128 
   1129             /* The length sent is 32 bits but we need to allocate 16 bits for tracking.*/
   1130             new_num_alus_loads = num_alus_loads + 1;
   1131 
   1132             /* allocate space needed to save this state in group. */
   1133             new_alloc = (bcmi_ft_group_alu_info_t *) sal_alloc((new_num_alus_loads) *
   1134                 sizeof(bcmi_ft_group_alu_info_t), "Group alu info.");
   1135             /* Copy state till last element. */
   1136             sal_memcpy(new_alloc, temp, i * sizeof(bcmi_ft_group_alu_info_t));
   1137 
   1138             /* Now break this element into 2 elements. */
   1139             sal_memcpy(&alu1, &temp[i], sizeof(bcmi_ft_group_alu_info_t));
   1140             sal_memcpy(&alu2, &temp[i], sizeof(bcmi_ft_group_alu_info_t));
   1141 
   1142             /* Now change the ALUs from 32 bit to 16 bit. */
   1143             alu1.key1.length = 16;
   1144             alu2.key1.length = 16;
   1145             alu1.key1.location = temp[i].key1.location;
   1146             alu2.key1.location = temp[i].key1.location+16;
   1147 
   1148             if (temp[i].key1.is_alu) {
   1149                 sal_memcpy(&alu1.key2, &alu1.key1, sizeof(bcmi_ft_alu_key_t));
   1150                 sal_memcpy(&alu2.key2, &alu2.key1, sizeof(bcmi_ft_alu_key_t));
   1151                 /* Set the flags.*/
   1152                 alu1.flags |= BCMI_FT_ALU_LOAD_NEXT_ATTACH;
   1153 
   1154                 /* As checks are identical, keep keys same. */
   1155                 alu1.key1.location = temp[i].key1.location;
   1156                 alu1.key2.location = temp[i].key1.location+16;
   1157                 alu2.key1.location = temp[i].key1.location;
   1158                 alu2.key2.location = temp[i].key1.location+16;
   1159 
   1160                 alu1.element_type2 = alu1.element_type1;
   1161                 alu2.element_type2 = alu2.element_type1;
   1162 
   1163                 /* Reverse the picking of truncated data at different ALU. */
   1164                 alu1.action_key.location = temp[i].action_key.location+16;
   1165                 alu2.action_key.location = temp[i].action_key.location;
   1166 
   1167                 alu1.action_key.length = 16;
   1168                 alu2.action_key.length = 16;
   1169             }
   1170 
   1171 
   1172             sal_memcpy(&new_alloc[i], &alu1, sizeof(bcmi_ft_group_alu_info_t));
   1173             sal_memcpy(&new_alloc[i+1], &alu2, sizeof(bcmi_ft_group_alu_info_t));
   1174 
   1175             /* Now copy the rest of information. */
   1176             sal_memcpy(&new_alloc[i+2], &temp[i+1],
   1177                 (num_alus_loads - (i+1)) * sizeof(bcmi_ft_group_alu_info_t));
   1178 
   1179            (BCMI_FT_GROUP_EXT_INFO(unit, id)).num_data_info = new_num_alus_loads;
   1180            sal_free(*info);
   1181            *info = new_alloc;
   1182            /* Update number of loads for next check and move iterator 1 further. */
   1183            num_alus_loads = new_num_alus_loads;
   1184            i++;
   1185         }
   1186     }
   1187 
   1188     return BCM_E_NONE;
   1189 
   1190 }
   1191 
   1192 /*
   1193  * Function:
   1194  *     bcmi_ft_group_extraction_alu_info_set
   1195  * Purpose:
   1196  *     Set Alu extraction info in group sw state.
   1197  * Parameters:
   1198  *     unit - (IN) BCM device id
   1199  *     id   - (IN) FT group id.
   1200  *     num_alu_info - (IN) Number of ALU/lod info structure.
   1201  *     alu_info  - (IN) list if ALU/load information.
   1202  *
   1203  * Returns:
   1204  *     BCM_E_XXX
   1205  */
   1206 int
   1207 bcmi_ft_group_extraction_alu_info_set(
   1208               int unit,
   1209               bcm_flowtracker_group_t id,
   1210               int key_or_data,
   1211               int num_alu_info,
   1212               bcmi_ft_group_alu_info_t *alu_info)
   1213 {
   1214 
   1215     bcmi_ft_group_alu_info_t **temp = NULL;
   1216     int *num_info = 0;
   1217 
   1218     if (BCMI_FT_GROUP_IS_BUSY(unit, id)) {
   1219         return BCM_E_CONFIG;
   1220     }
   1221 
   1222     if (num_alu_info == 0) {
   1223         /* Make sure that extraction info was cleared. */
   1224         if (key_or_data) {
   1225             LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
   1226                     (BSL_META_U(unit, "Key elements cleared"
   1227                                 " for group = %d\n"), id));
   1228             if (BCMI_FT_GROUP_EXT_KEY_INFO(unit, id) != NULL) {
   1229                 sal_free(BCMI_FT_GROUP_EXT_KEY_INFO(unit, id));
   1230                 BCMI_FT_GROUP_EXT_KEY_INFO(unit, id) = NULL;
   1231             }
   1232             BCMI_FT_GROUP_EXT_INFO(unit, id).num_key_info = 0;
   1233         } else {
   1234             LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
   1235                     (BSL_META_U(unit, "Data/Alu elements cleared"
   1236                                 " for group = %d\n"), id));
   1237             if (BCMI_FT_GROUP_EXT_DATA_INFO(unit, id) != NULL) {
   1238                 sal_free(BCMI_FT_GROUP_EXT_DATA_INFO(unit, id));
   1239                 BCMI_FT_GROUP_EXT_DATA_INFO(unit, id) = NULL;
   1240             }
   1241             BCMI_FT_GROUP_EXT_INFO(unit, id).num_data_info = 0;
   1242         }
   1243 
   1244         /* Nothing to do */
   1245         return BCM_E_NONE;
   1246     }
   1247 
   1248     if (alu_info == NULL) {
   1249         return BCM_E_PARAM;
   1250     }
   1251 
   1252 
   1253     if (key_or_data) {
   1254         LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
   1255             (BSL_META_U(unit, "Key ALU elements added for group = %d are : %d\n"),
   1256             id, num_alu_info));
   1257 
   1258         temp = (&(BCMI_FT_GROUP_EXT_KEY_INFO(unit, id)));
   1259         num_info = (&(BCMI_FT_GROUP_EXT_INFO(unit, id).num_key_info));
   1260     } else {
   1261         LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
   1262             (BSL_META_U(unit, "Data ALU elements added for group = %d are : %d\n"),
   1263             id, num_alu_info));
   1264         temp = (&(BCMI_FT_GROUP_EXT_DATA_INFO(unit, id)));
   1265         num_info = (&(BCMI_FT_GROUP_EXT_INFO(unit, id).num_data_info));
   1266     }
   1267 
   1268     /* allocate space needed to save this state in group. */
   1269     *temp = (bcmi_ft_group_alu_info_t *) sal_alloc(num_alu_info *
   1270                 sizeof(bcmi_ft_group_alu_info_t), "Group alu info.");
   1271 
   1272     if (*temp == NULL) {
   1273         return BCM_E_MEMORY;
   1274     }
   1275 
   1276    *num_info = num_alu_info;
   1277 
   1278     /* Store all the information in local memory. */
   1279     sal_memcpy(*temp, alu_info,
   1280         (num_alu_info * sizeof(bcmi_ft_group_alu_info_t)));
   1281 
   1282     /* Check if Session Data requires 32-bit to 16-bit conversion */
   1283     if (soc_feature(unit, soc_feature_hx5_ft_32bit_param_update)) {
   1284         if (key_or_data == 0) {
   1285             BCM_IF_ERROR_RETURN(bcmi_ft_group_32bit_to_16_bit_param_conversion
   1286                     (unit, id, (&(BCMI_FT_GROUP_EXT_DATA_INFO(unit, id)))));
   1287         }
   1288     }
   1289 
   1290     return BCM_E_NONE;
   1291 }
   1292 
   1293 /*
   1294  * Function:
   1295  *     bcmi_ft_group_extraction_alu_info_get
   1296  * Purpose:
   1297  *     Get Alu extraction info of group sw state.
   1298  * Parameters:
   1299  *     unit - (IN) BCM device id
   1300  *     id   - (IN) FT group id.
   1301  *     max_alu_info - (IN) max information user asked for.
   1302  *     alu_info  - (OUT) list if ALU/load information.
   1303  *     num_alu_info - (OUT) Number of ALU/lod info structure.
   1304  *
   1305  * Returns:
   1306  *     BCM_E_XXX
   1307  */
   1308 int
   1309 bcmi_ft_group_extraction_alu_info_get(
   1310               int unit,
   1311               bcm_flowtracker_group_t id,
   1312               int key_or_data,
   1313               int max_alu_info,
   1314               bcmi_ft_group_alu_info_t *alu_info,
   1315               int *num_alu_info)
   1316 {
   1317 
   1318     bcmi_ft_group_alu_info_t **temp =  NULL;
   1319     int *num_info = 0;
   1320 
   1321     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   1322 
   1323     /* If the max_alu_info is non zero and list == NULL, return
   1324      * BCM_E_PARAM.
   1325      */
   1326     if ((max_alu_info != 0) && (alu_info == NULL)) {
   1327         return BCM_E_PARAM;
   1328     }
   1329 
   1330     if (num_alu_info == NULL) {
   1331         return BCM_E_PARAM;
   1332     }
   1333 
   1334     *num_alu_info = (BCMI_FT_GROUP_EXT_INFO(unit, id)).num_data_info;
   1335 
   1336     /* If max_alu_info == 0 and list_of_export_elements == NULL,
   1337      * return the number of export elements in list_size
   1338      * variable.
   1339      */
   1340     if ((max_alu_info == 0) && (alu_info == NULL)) {
   1341 
   1342         return BCM_E_NONE;
   1343     }
   1344 
   1345     if (key_or_data) {
   1346 
   1347         if (!BCMI_FT_GROUP_EXT_KEY_INFO(unit, id)) {
   1348             return BCM_E_NOT_FOUND;
   1349         }
   1350 
   1351 
   1352         temp = (&(BCMI_FT_GROUP_EXT_KEY_INFO(unit, id)));
   1353         num_info = (&(BCMI_FT_GROUP_EXT_INFO(unit, id).num_key_info));
   1354 
   1355     } else {
   1356 
   1357         if (!BCMI_FT_GROUP_EXT_DATA_INFO(unit, id)) {
   1358             return BCM_E_NOT_FOUND;
   1359         }
   1360 
   1361         temp = (&(BCMI_FT_GROUP_EXT_DATA_INFO(unit, id)));
   1362         num_info = (&(BCMI_FT_GROUP_EXT_INFO(unit, id).num_data_info));
   1363     }
   1364 
   1365     /* Pick the number of elements to send back. */
   1366     *num_alu_info = (*num_info < max_alu_info) ?
   1367                     (*num_info) : max_alu_info;
   1368 
   1369     /* Send the information back to FTFP module. */
   1370     sal_memcpy(alu_info, *temp,
   1371         ((*num_alu_info) * sizeof(bcmi_ft_group_alu_info_t)));
   1372 
   1373 
   1374     return BCM_E_NONE;
   1375 }
   1376 
   1377 /*
   1378  * Function:
   1379  *     bcmi_ft_group_extraction_hw_info_set
   1380  * Purpose:
   1381  *     Set hardware extraction info in group sw state.
   1382  * Parameters:
   1383  *     unit - (IN) BCM device id
   1384  *     id   - (IN) FT group id.
   1385  *     key_or_data - (IN) key/data
   1386  *     num_elements - (IN) Number of elements of hw extraction.
   1387  *     elements - (IN) list of hw extrator info.
   1388  *
   1389  * Returns:
   1390  *     BCM_E_XXX
   1391  */
   1392 int
   1393 bcmi_ft_group_extraction_hw_info_set(
   1394               int unit,
   1395               bcm_flowtracker_group_t id,
   1396               int key_or_data,
   1397               int num_elements,
   1398               bcmi_ft_hw_extractor_info_t *elements)
   1399 {
   1400 
   1401     bcmi_ft_hw_extractor_info_t **temp = NULL;
   1402     int *num_info = NULL;
   1403 
   1404     if (num_elements == 0) {
   1405         /* Make sure that extraction info was cleared. */
   1406         if (key_or_data) {
   1407             LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
   1408                     (BSL_META_U(unit, "Key hw extractors info"
   1409                                 "cleared for group = %d\n"), id));
   1410             if (BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_key != NULL) {
   1411                 sal_free(BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_key);
   1412                 BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_key = NULL;
   1413             }
   1414             BCMI_FT_GROUP_EXT_HW_INFO(unit, id).num_ft_key = 0;
   1415         } else {
   1416             LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
   1417                     (BSL_META_U(unit, "Data/Alu hw extractors info"
   1418                                 "cleared for group = %d\n"), id));
   1419             if (BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_data != NULL) {
   1420                 sal_free(BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_data);
   1421                 BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_data = NULL;
   1422             }
   1423             BCMI_FT_GROUP_EXT_HW_INFO(unit, id).num_ft_data = 0;
   1424         }
   1425 
   1426         /* Nothing to do */
   1427         return BCM_E_NONE;
   1428     }
   1429 
   1430     if (elements == NULL) {
   1431         return BCM_E_PARAM;
   1432     }
   1433 
   1434     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   1435 
   1436     if (key_or_data) {
   1437         LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
   1438             (BSL_META_U(unit, "Key elements added for group = %d are : %d\n"),
   1439             id, num_elements));
   1440 
   1441         temp = (&(BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_key));
   1442         num_info = (&(BCMI_FT_GROUP_EXT_HW_INFO(unit, id).num_ft_key));
   1443     } else {
   1444 
   1445         LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
   1446             (BSL_META_U(unit, "Data elements added for group = %d are : %d\n"),
   1447             id, num_elements));
   1448 
   1449         temp = (&(BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_data));
   1450         num_info = (&(BCMI_FT_GROUP_EXT_HW_INFO(unit, id).num_ft_data));
   1451     }
   1452 
   1453     if (*temp != NULL) {
   1454         sal_free(*temp);
   1455         *temp = NULL;
   1456     }
   1457 
   1458     /* allocate space needed to save this state in group. */
   1459     *temp = (bcmi_ft_hw_extractor_info_t*)
   1460             sal_alloc(num_elements *
   1461                 sizeof(bcmi_ft_hw_extractor_info_t), "hardware extractor info");
   1462 
   1463     if (*temp == NULL) {
   1464         return BCM_E_MEMORY;
   1465     }
   1466 
   1467     (*num_info) = num_elements;
   1468 
   1469     sal_memcpy((*temp), elements,
   1470         (num_elements * sizeof(bcmi_ft_hw_extractor_info_t)));
   1471 
   1472     return BCM_E_NONE;
   1473 }
   1474 
   1475 /*
   1476  * Function:
   1477  *     bcmi_ft_group_extraction_hw_info_get
   1478  * Purpose:
   1479  *     Get hardware extraction info in group sw state.
   1480  * Parameters:
   1481  *     unit - (IN) BCM device id
   1482  *     id   - (IN) FT group id.
   1483  *     key_or_data - (IN) key/data
   1484  *     max_elements - (IN) Max elements that user asked for.
   1485  *     elements - (OUT) list of hw extrator info.
   1486  *     num_elements - (OUT) Number of elements of hw extraction.
   1487  *
   1488  * Returns:
   1489  *     BCM_E_XXX
   1490  */
   1491 int
   1492 bcmi_ft_group_extraction_hw_info_get(
   1493               int unit,
   1494               int key_or_data,
   1495               bcm_flowtracker_group_t id,
   1496               int max_elements,
   1497               bcmi_ft_hw_extractor_info_t *elements,
   1498               int *num_elements)
   1499 {
   1500     bcmi_ft_hw_extractor_info_t **temp = NULL;
   1501     int *num_info = NULL;
   1502 
   1503     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   1504 
   1505     /* If the max_alu_info is non zero and list == NULL, return
   1506      * BCM_E_PARAM.
   1507      */
   1508     if ((max_elements != 0) && (elements == NULL)) {
   1509         return BCM_E_PARAM;
   1510     }
   1511 
   1512     if (num_elements == NULL) {
   1513         return BCM_E_PARAM;
   1514     }
   1515 
   1516     if (key_or_data) {
   1517         temp = (&(BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_key));
   1518         num_info = (&(BCMI_FT_GROUP_EXT_HW_INFO(unit, id).num_ft_key));
   1519     } else {
   1520         temp = (&(BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_data));
   1521         num_info = (&(BCMI_FT_GROUP_EXT_HW_INFO(unit, id).num_ft_data));
   1522     }
   1523 
   1524     *num_elements = *num_info;
   1525 
   1526     /* If max_elements == 0 and elements == NULL,
   1527      * return the number of elements present.
   1528      */
   1529     if ((max_elements == 0) && (elements == NULL)) {
   1530 
   1531         return BCM_E_NONE;
   1532     }
   1533 
   1534     /* Pick the number of elements to send back. */
   1535     *num_elements = ((*num_info) < max_elements) ?
   1536                     (*num_info) : max_elements;
   1537 
   1538 
   1539 
   1540     sal_memcpy(elements, *temp,
   1541         ((*num_elements) * sizeof(bcmi_ft_hw_extractor_info_t)));
   1542 
   1543     return BCM_E_NONE;
   1544 }
   1545 
   1546 /*
   1547  * Function:
   1548  *     bcmi_ft_group_extraction_mode_set
   1549  * Purpose:
   1550  *     Set extraction mode.
   1551  * Parameters:
   1552  *     unit - (IN) BCM device id
   1553  *     key_or_data - (IN) key/data
   1554  *     id   - (IN) FT group id.
   1555  *     mode - (IN) Mode of the extration key/data.
   1556  *
   1557  * Returns:
   1558  *     BCM_E_XXX
   1559  */
   1560 int
   1561 bcmi_ft_group_extraction_mode_set(
   1562               int unit,
   1563               int key_or_data,
   1564               bcm_flowtracker_group_t id,
   1565               bcmi_ft_group_key_data_mode_t mode)
   1566 {
   1567 
   1568     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   1569 
   1570     if (BCMI_FT_GROUP_IS_BUSY(unit, id)) {
   1571         return BCM_E_CONFIG;
   1572     }
   1573 
   1574     if (key_or_data) {
   1575         BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_key_mode = mode;
   1576         BCMI_FT_GROUP_FTFP_DATA(unit, id).session_key_mode = mode;
   1577     } else {
   1578         BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_data_mode = mode;
   1579     }
   1580 
   1581     return BCM_E_NONE;
   1582 }
   1583 
   1584 /*
   1585  * Function:
   1586  *     bcmi_ft_group_extraction_mode_get
   1587  * Purpose:
   1588  *     Get extraction mode.
   1589  * Parameters:
   1590  *     unit - (IN) BCM device id
   1591  *     key_or_data - (IN) key/data
   1592  *     id   - (IN) FT group id.
   1593  *     mode - (OUT) Mode of the extration key/data.
   1594  *
   1595  * Returns:
   1596  *     BCM_E_XXX
   1597  */
   1598 int
   1599 bcmi_ft_group_extraction_mode_get(
   1600               int unit,
   1601               int key_or_data,
   1602               bcm_flowtracker_group_t id,
   1603               bcmi_ft_group_key_data_mode_t *mode)
   1604 {
   1605     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   1606 
   1607     if (key_or_data) {
   1608         *mode = BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_key_mode;
   1609     } else {
   1610         *mode = BCMI_FT_GROUP_EXT_HW_INFO(unit, id).ft_data_mode;
   1611     }
   1612 
   1613     return BCM_E_NONE;
   1614 }
   1615 
   1616 /*
   1617  * Function:
   1618  *     bcmi_ft_group_session_key_type_set
   1619  * Purpose:
   1620  *     Set session key type.
   1621  * Parameters:
   1622  *     unit - (IN) BCM device id
   1623  *     id   - (IN) FT group id.
   1624  *     key_type - (IN) Session Key Type
   1625  *
   1626  * Returns:
   1627  *     BCM_E_XXX
   1628  */
   1629 int
   1630 bcmi_ft_group_session_key_type_set(
   1631               int unit,
   1632               bcm_flowtracker_group_t id,
   1633               uint32 key_type)
   1634 {
   1635 
   1636     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   1637 
   1638     BCMI_FT_GROUP(unit, id)->ftfp_data.session_key_type = key_type;
   1639 
   1640     return BCM_E_NONE;
   1641 }
   1642 
   1643 /*
   1644  * Function:
   1645  *     bcmi_ft_group_session_key_type_get
   1646  * Purpose:
   1647  *     Get session key type.
   1648  * Parameters:
   1649  *     unit - (IN) BCM device id
   1650  *     id   - (IN) FT group id.
   1651  *     key_type - (OUT) Session Key Type.
   1652  *
   1653  * Returns:
   1654  *     BCM_E_XXX
   1655  */
   1656 int
   1657 bcmi_ft_group_session_key_type_get(
   1658               int unit,
   1659               bcm_flowtracker_group_t id,
   1660               uint32 *key_type)
   1661 {
   1662     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   1663 
   1664     *key_type = BCMI_FT_GROUP(unit, id)->ftfp_data.session_key_type;
   1665 
   1666     return BCM_E_NONE;
   1667 }
   1668 
   1669 int
   1670 bcmi_ft_group_ftfp_profiles_set(
   1671               int unit,
   1672               bcm_flowtracker_group_t id,
   1673               bcmi_ft_session_profiles_t *profile_info)
   1674 {
   1675     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   1676 
   1677     BCMI_FT_GROUP(unit, id)->ftfp_data.profiles.session_key_profile_idx =
   1678         profile_info->session_key_profile_idx;
   1679 
   1680     BCMI_FT_GROUP(unit, id)->ftfp_data.profiles.session_data_profile_idx =
   1681         profile_info->session_data_profile_idx;
   1682 
   1683     BCMI_FT_GROUP(unit, id)->ftfp_data.profiles.alu_data_profile_idx =
   1684         profile_info->alu_data_profile_idx;
   1685 
   1686     return BCM_E_NONE;
   1687 }
   1688 
   1689 int
   1690 bcmi_ft_group_ftfp_profiles_get(
   1691               int unit,
   1692               bcm_flowtracker_group_t id,
   1693               bcmi_ft_session_profiles_t *profile_info)
   1694 {
   1695     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   1696 
   1697     if (!profile_info) {
   1698         return (BCM_E_PARAM);
   1699     }
   1700 
   1701     profile_info->session_key_profile_idx =
   1702         BCMI_FT_GROUP(unit, id)->ftfp_data.profiles.session_key_profile_idx;
   1703 
   1704     profile_info->session_data_profile_idx =
   1705         BCMI_FT_GROUP(unit, id)->ftfp_data.profiles.session_data_profile_idx;
   1706 
   1707     profile_info->alu_data_profile_idx =
   1708         BCMI_FT_GROUP(unit, id)->ftfp_data.profiles.alu_data_profile_idx;
   1709 
   1710     return BCM_E_NONE;
   1711 }
   1712 
   1713 
   1714 
   1715 int
   1716 bcmi_ft_group_ftfp_data_get(
   1717               int unit,
   1718               bcm_flowtracker_group_t id,
   1719               bcmi_ft_group_ftfp_data_t *data)
   1720 {
   1721 
   1722     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   1723 
   1724     if (!data) {
   1725         return (BCM_E_PARAM);
   1726     }
   1727 
   1728     data->direction = BCMI_FT_GROUP_FTFP_DATA(unit, id).direction;
   1729     data->flowtrack = BCMI_FT_GROUP_FTFP_DATA(unit, id).flowtrack;
   1730     data->new_learn = BCMI_FT_GROUP_FTFP_DATA(unit, id).new_learn;
   1731     data->session_key_type = BCMI_FT_GROUP_FTFP_DATA(unit, id).session_key_type;
   1732 
   1733     data->session_key_mode = BCMI_FT_GROUP_FTFP_DATA(unit, id).session_key_mode;
   1734 
   1735     data->profiles.session_key_profile_idx =
   1736         BCMI_FT_GROUP(unit, id)->ftfp_data.profiles.session_key_profile_idx;
   1737     data->profiles.session_data_profile_idx =
   1738         BCMI_FT_GROUP(unit, id)->ftfp_data.profiles.session_data_profile_idx;
   1739     data->profiles.alu_data_profile_idx =
   1740         BCMI_FT_GROUP(unit, id)->ftfp_data.profiles.alu_data_profile_idx;
   1741 
   1742     return BCM_E_NONE;
   1743 }
   1744 
   1745 /*
   1746  * Function:
   1747  *     bcmi_ft_group_hw_install
   1748  * Purpose:
   1749  *     Install hardware resource for the group.
   1750  * Description:
   1751  *     All the groups parameters are added into groups software
   1752  *     state. The hardware resources will only get allocated when
   1753  *     extraction algorithm finished setting up the hardware extrators.
   1754  *     Later hardware extration information will be added into
   1755  *     groups's software state. After that when the group is added
   1756  *     into FTFP entry then this hardware install method will be
   1757  *     called.
   1758  * Parameters:
   1759  *     unit - (IN) BCM device id
   1760  *     id   - (IN) FT group id.
   1761  *
   1762  * Returns:
   1763  *     BCM_E_XXX
   1764  */
   1765 int
   1766 bcmi_ft_group_hw_install(int unit, bcm_flowtracker_group_t id)
   1767 {
   1768     int rv =  BCM_E_NONE;
   1769     int num_alus_loads = 0, i=0;
   1770     bcmi_ft_group_alu_info_t *temp = NULL;
   1771     int load16_idz[TOTAL_GROUP_LOAD16_DATA_NUM];
   1772     int load8_idz[TOTAL_GROUP_LOAD8_DATA_NUM];
   1773     int num_load_16=0, num_load_8=0;
   1774     bcmi_ft_alu_load_type_t type = bcmiFtAluLoadTypeNone;
   1775     int total_load8_mem = TOTAL_GROUP_LOAD8_DATA_NUM;
   1776     int total_load16_mem = TOTAL_GROUP_LOAD16_DATA_NUM;
   1777     bcmi_ft_group_key_data_mode_t mode = 0;
   1778     int length=0, alu=0;
   1779 
   1780     /* Read the group state for the ALU inforamtion. */
   1781     if (!(BCMI_FT_GROUP_EXT_DATA_OR_TS_TRIGGERS_SET(unit, id))) {
   1782         return BCM_E_INTERNAL;
   1783     }
   1784 
   1785     if (BCMI_FT_GROUP_IS_BUSY(unit, id)) {
   1786         return BCM_E_CONFIG;
   1787     }
   1788 
   1789     for (; i<total_load16_mem; i++) {
   1790         load16_idz[i] = -1;
   1791 
   1792         if (i<total_load8_mem) {
   1793             load8_idz[i] = -1;
   1794         }
   1795     }
   1796 
   1797     /* assign the ALU memory chunk to local pointer. */
   1798     temp = BCMI_FT_GROUP_EXT_DATA_INFO(unit, id);
   1799 
   1800     /* Get total number of alus in this chunk. */
   1801     num_alus_loads = (BCMI_FT_GROUP_EXT_INFO(unit, id)).num_data_info;
   1802 
   1803     /* allocate the bitmap based on the type, length */
   1804     for (i=0; i<num_alus_loads; i++) {
   1805 
   1806         if (temp->key1.location >= BCMI_FT_SESSION_DATA_SINGLE_LEN) {
   1807             rv = BCM_E_PARAM;
   1808             goto cleanup;
   1809         }
   1810 
   1811         /* Normalize length and alu status from multiple keys. */
   1812         rv = bcmi_ft_alu_load_values_normalize(unit, temp, &length, &alu);
   1813         CLEANUP_ON_ERROR(rv)
   1814 
   1815         /* Now get the type of the memory and take action. */
   1816         rv = bcmi_ft_alu_load_type_get(unit, alu, length, &type);
   1817         CLEANUP_ON_ERROR(rv)
   1818 
   1819         if (type == bcmiFtAluLoadTypeLoad16) {
   1820             load16_idz[num_load_16] = i;
   1821             num_load_16++;
   1822             if (num_load_16 > total_load16_mem) {
   1823                 rv = BCM_E_PARAM;
   1824                 goto cleanup;
   1825             }
   1826             temp++;
   1827             /* We do not need to do anything here. */
   1828             continue;
   1829         } else if (type == bcmiFtAluLoadTypeLoad8 ) {
   1830             load8_idz[num_load_8] = i;
   1831             num_load_8++;
   1832             if (num_load_8 > total_load8_mem) {
   1833                 rv = BCM_E_PARAM;
   1834                 goto cleanup;
   1835             }
   1836             temp++;
   1837             /* We do not need to do anything here. */
   1838             continue;
   1839         }
   1840                 /* This ALU memory is used. go for next one. */
   1841                 /* This ALU memory is used. go for next one. */
   1842 
   1843         /* Configure the ALU memory. */
   1844         /*rv = bcmi_ft_group_alu_configure(unit, id, temp, type);*/
   1845         BCMI_FT_METHOD_INSTALL_CHECK(type);
   1846         CLEANUP_ON_ERROR(rv);
   1847 
   1848         rv = (BCMI_FT_METHOD_INSTALL_EXEC(type))(unit, id, temp,
   1849                   NULL);
   1850         CLEANUP_ON_ERROR(rv)
   1851 
   1852         /* Set that index into the group table. */
   1853         temp++;
   1854     }
   1855 
   1856     /*
   1857      * The upper loop has created the ALU indexes and wrote into them.
   1858      * Now we need to set the load profiles based on the indices
   1859      * that we created above.
   1860      * If there is no load information then no need to configure load memories.
   1861      */
   1862     if (load16_idz[0] != -1) {
   1863         BCMI_FT_METHOD_INSTALL_CHECK(bcmiFtAluLoadTypeLoad16);
   1864         CLEANUP_ON_ERROR(rv);
   1865 
   1866         rv = (BCMI_FT_METHOD_INSTALL_EXEC(bcmiFtAluLoadTypeLoad16))
   1867                   (unit, id, NULL, load16_idz);
   1868 
   1869         CLEANUP_ON_ERROR(rv)
   1870     }
   1871 
   1872     if (load8_idz[0] != -1) {
   1873         BCMI_FT_METHOD_INSTALL_CHECK(bcmiFtAluLoadTypeLoad8);
   1874         CLEANUP_ON_ERROR(rv);
   1875 
   1876         rv = (BCMI_FT_METHOD_INSTALL_EXEC(bcmiFtAluLoadTypeLoad8))
   1877                   (unit, id, NULL, load8_idz);
   1878 
   1879         CLEANUP_ON_ERROR(rv);
   1880     }
   1881 
   1882     /* Set the timestamp entry. */
   1883     rv = bcmi_ft_group_timestamp_set(unit, id);
   1884     BCMI_CLEANUP_IF_ERROR(rv);
   1885 
   1886     /* Add the pdd/pde policy entry. */
   1887     bcmi_ft_group_pdd_policy_profile_add(unit, id);
   1888 
   1889     /* Create template information list. */
   1890     rv = bcmi_ft_group_template_data_create(unit, id, load16_idz, load8_idz);
   1891     BCMI_CLEANUP_IF_ERROR(rv);
   1892 
   1893     /* Set the single/double session mode based on extraction length. */
   1894     rv = bcmi_ft_group_ft_mode_update(unit, id);
   1895     BCMI_CLEANUP_IF_ERROR(rv);
   1896 
   1897     /*
   1898      * we also need to set mode in group table.
   1899      * FTFP and group data can both update data mode.
   1900      * So check again if FTFP has also updated and
   1901      * then install in group table.
   1902      */
   1903     bcmi_ft_group_extraction_mode_get(unit, 0, id, &mode);
   1904 
   1905     if (mode) {
   1906         soc_mem_field32_modify(unit, BSC_KG_GROUP_TABLEm, id, DATA_MODEf, 1);
   1907     }
   1908 
   1909     /* Install Session profiles and update ftfp data */
   1910     rv = _bcm_field_ft_session_profiles_install(unit, id);
   1911     BCMI_CLEANUP_IF_ERROR(rv);
   1912 
   1913     /* Set the installed status. */
   1914     BCMI_FT_GROUP_IS_VALIDATED(unit, id) = 1;
   1915 
   1916     return BCM_E_NONE;
   1917 
   1918 cleanup :
   1919     bcmi_ft_group_hw_uninstall(unit, id);
   1920     return rv;
   1921 }
   1922 
   1923 
   1924 /*
   1925  * Function:
   1926  *     bcmi_ft_group_hw_uninstall
   1927  * Purpose:
   1928  *     Uninstall hardware resource for the group.
   1929  * Parameters:
   1930  *     unit - (IN) BCM device id
   1931  *     id   - (IN) FT group id.
   1932  *
   1933  * Returns:
   1934  *     BCM_E_XXX
   1935  */
   1936 int
   1937 bcmi_ft_group_hw_uninstall(int unit, bcm_flowtracker_group_t id)
   1938 {
   1939     int rv =  BCM_E_NONE;
   1940     int num_alus = 0, i = 0;
   1941     bcmi_ft_group_alu_info_t *temp = NULL;
   1942 /*    int index  = 1;*/
   1943     int load16_idz[TOTAL_GROUP_LOAD16_DATA_NUM];
   1944     int load8_idz[TOTAL_GROUP_LOAD8_DATA_NUM];
   1945     int num_load_16=0, num_load_8=0;
   1946     bcmi_ft_alu_load_type_t type = bcmiFtAluLoadTypeNone;
   1947     int total_load8_mem = TOTAL_GROUP_LOAD8_DATA_NUM;
   1948     int total_load16_mem = TOTAL_GROUP_LOAD16_DATA_NUM;
   1949     bcmi_ft_group_template_list_t **head;
   1950     int length=0, alu=0;
   1951 
   1952     if (bcmi_ft_group_is_invalid(unit, id)) {
   1953         LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
   1954             "Invalid flow Group (%d)\n "), id));
   1955 
   1956         return BCM_E_CONFIG;
   1957     }
   1958 
   1959     /* Read the group state for the ALU inforamtion. */
   1960     if (!(BCMI_FT_GROUP_EXT_DATA_OR_TS_TRIGGERS_SET(unit, id))) {
   1961         LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
   1962             "Extraction information is not yet set for Group. (%d)\n "), id));
   1963 
   1964         return BCM_E_INTERNAL;
   1965     }
   1966 
   1967     for (; i<total_load16_mem; i++) {
   1968         load16_idz[i] = -1;
   1969 
   1970         if (i<total_load8_mem) {
   1971             load8_idz[i] = -1;
   1972         }
   1973     }
   1974 
   1975     /* assign the ALU memory chunk to local pointer. */
   1976     temp = BCMI_FT_GROUP_EXT_DATA_INFO(unit, id);
   1977 
   1978     /* Get the head of the templs info list. */
   1979     head = &((BCMI_FT_GROUP(unit, id))->template_head);
   1980 
   1981     /* Get total number of alus in this chunk. */
   1982     num_alus = (BCMI_FT_GROUP_EXT_INFO(unit, id)).num_data_info;
   1983 
   1984     /* allocate the bitmap based on the type, length */
   1985     for (i=0; i<num_alus; i++) {
   1986 
   1987         /* Normalize length and alu status from multiple keys. */
   1988         rv = bcmi_ft_alu_load_values_normalize(unit, temp, &length, &alu);
   1989         if (BCM_FAILURE(rv)) {
   1990             return rv;
   1991         }
   1992 
   1993         /* Now get the type of the memory and take action. */
   1994         rv = bcmi_ft_alu_load_type_get(unit, alu, length, &type);
   1995         if (BCM_FAILURE(rv)) {
   1996             return rv;
   1997         }
   1998 
   1999         if (type == bcmiFtAluLoadTypeLoad16) {
   2000             load16_idz[num_load_16] = i;
   2001             num_load_16++;
   2002             if (num_load_16 > total_load16_mem) {
   2003                 /* This actually should not happen. just a -ve check */
   2004                 return BCM_E_PARAM;
   2005             }
   2006             temp++;
   2007             /* We do not need to do anything here. */
   2008             continue;
   2009         } else if (type == bcmiFtAluLoadTypeLoad8 ) {
   2010             load8_idz[num_load_8] = i;
   2011             num_load_8++;
   2012             if (num_load_8 > total_load8_mem) {
   2013                 /* This actually should not happen. just a -ve check */
   2014                 return BCM_E_PARAM;
   2015             }
   2016             temp++;
   2017             /* We do not need to do anything here. */
   2018             continue;
   2019         }
   2020 
   2021         /* Index is obtained, now start writing into that memory. */
   2022         rv = (BCMI_FT_METHOD_UNINSTALL_EXEC(type))(unit, id, temp,
   2023                   NULL);
   2024 
   2025         if (BCM_FAILURE(rv)) {
   2026             /*
   2027              * The group uninstall is called when install fails and not
   2028              * all the memories are written. At that time, we need to clear
   2029              * whatever is being written already for that group.
   2030              * But because we are trying to clear the whole group,
   2031              * we may find BCM_E_NOT_FOUND for some memories which were
   2032              * not yet installed in that group.
   2033              * In real uninstall case, logically no chance to get
   2034              * BCM_E_NOT_FOUND as this installing is all handled internally.
   2035              * In mem clear fails with above error then just continue as
   2036              * most probably the memory was installed yet.
   2037              */
   2038             if (rv != BCM_E_NOT_FOUND) {
   2039                 return rv;
   2040             }
   2041         }
   2042 
   2043         /* Set that index into the group table. */
   2044         temp++;
   2045     }
   2046 
   2047     /*
   2048      * Clear the load16 memories now.
   2049      */
   2050     if (load16_idz[0] != -1) {
   2051         rv = (BCMI_FT_METHOD_UNINSTALL_EXEC(bcmiFtAluLoadTypeLoad16))
   2052                  (unit, id, NULL, load16_idz);
   2053         if (BCM_FAILURE(rv)) {
   2054             if (rv != BCM_E_NOT_FOUND) {
   2055                 return rv;
   2056             }
   2057         }
   2058     }
   2059 
   2060     /*
   2061      * Clear the load8 memories now.
   2062      */
   2063     if (load8_idz[0] != -1) {
   2064        rv = (BCMI_FT_METHOD_UNINSTALL_EXEC(bcmiFtAluLoadTypeLoad8))
   2065                  (unit, id, NULL, load8_idz);
   2066 
   2067         if (BCM_FAILURE(rv)) {
   2068             if (rv != BCM_E_NOT_FOUND) {
   2069                 return rv;
   2070             }
   2071         }
   2072     }
   2073 
   2074     /* delete the pdd/pde policy entry. */
   2075     rv = bcmi_ft_group_pdd_policy_profile_delete(unit, id);
   2076     if (BCM_FAILURE(rv)) {
   2077         return rv;
   2078     }
   2079 
   2080     bcmi_ft_group_template_list_delete_all(unit, head);
   2081 
   2082     /* Clear in use memories of group. */
   2083     sal_memset(BCMI_FT_GROUP_ALU16_MEM_USE(unit, id), 0,
   2084         (sizeof(uint32) *
   2085         BCMI_FT_ALU_LOAD_MEM_COUNT(unit, bcmiFtAluLoadTypeAlu16)));
   2086     sal_memset(BCMI_FT_GROUP_ALU32_MEM_USE(unit, id), 0,
   2087         (sizeof(uint32) *
   2088         BCMI_FT_ALU_LOAD_MEM_COUNT(unit, bcmiFtAluLoadTypeAlu32)));
   2089 
   2090     /* Un-install Session profiles and update ftfp data */
   2091     rv = _bcm_field_ft_session_profiles_uninstall(unit, id);
   2092     if (BCM_FAILURE(rv)) {
   2093         return rv;
   2094     }
   2095 
   2096     /* reset the validated status. */
   2097     BCMI_FT_GROUP_IS_VALIDATED(unit, id) = 0;
   2098 
   2099     return rv;
   2100 
   2101 }
   2102 
   2103 /*
   2104  * Function:
   2105  *     bcmi_ft_group_pdd_policy_profile_add
   2106  * Purpose:
   2107  *     Add policy profile entry for group action profile.
   2108  * Parameters:
   2109  *     unit - (IN) BCM device id
   2110  *     id   - (IN) FT group id.
   2111  *
   2112  * Returns:
   2113  *     BCM_E_XXX
   2114  */
   2115 int
   2116 bcmi_ft_group_pdd_policy_profile_add(
   2117         int unit,
   2118         bcm_flowtracker_group_t id)
   2119 {
   2120     bsc_kg_group_table_entry_t kg_group_entry;
   2121     bsc_dt_pde_profile_entry_t pde_entry;
   2122     void *entries[1];
   2123     uint32 index = 0;
   2124     int rv = BCM_E_NONE;
   2125     int old_index = 0;
   2126     int ref_count = 0;
   2127 
   2128     /* Group has the pdd profile entry. Here we just need to set it. */
   2129 
   2130     /* set the entry to profile entries. */
   2131     entries[0] = (&(BCMI_FT_GROUP(unit, id)->pdd_entry));
   2132 
   2133     /* First read the group entry. */
   2134     BCM_IF_ERROR_RETURN (soc_mem_read(unit, BSC_KG_GROUP_TABLEm,
   2135         MEM_BLOCK_ANY, id, &kg_group_entry));
   2136 
   2137     /* now write this index into the group. */
   2138     old_index = soc_mem_field32_get(unit, BSC_KG_GROUP_TABLEm,
   2139         ((uint32 *)&kg_group_entry), SESSION_DATA_TYPEf);
   2140 
   2141     if (old_index) {
   2142         bcmi_ft_group_pdd_profile_entry_delete(unit, old_index);
   2143     }
   2144 
   2145     /* Create teh profile entry for new age out profile. */
   2146     BCM_IF_ERROR_RETURN(bcmi_ft_group_pdd_profile_entry_add(unit, entries, 1,
   2147         (uint32 *)&index));
   2148 
   2149     /* now write this new index into the group. */
   2150     soc_mem_field32_set(unit, BSC_KG_GROUP_TABLEm, ((uint32 *)&kg_group_entry),
   2151         SESSION_DATA_TYPEf, index);
   2152 
   2153     /* Write the entry back into the group table. */
   2154     rv = soc_mem_write(unit, BSC_KG_GROUP_TABLEm, MEM_BLOCK_ANY, id, &kg_group_entry);
   2155 
   2156     if (BCM_FAILURE(rv)) {
   2157         return rv;
   2158     }
   2159 
   2160     bcmi_ft_group_pdd_to_pde_coversion(unit, id, &pde_entry);
   2161 
   2162     rv = bcmi_ft_group_pdd_profile_refcount_get(unit, index, &ref_count);
   2163 
   2164     if (BCM_FAILURE(rv)) {
   2165         bcmi_ft_group_pdd_profile_entry_delete(unit, index);
   2166         return rv;
   2167     }
   2168 
   2169     if (ref_count == 1) {
   2170         /* This is a new entry. Write the PDE entry also at same index. */
   2171         bcmi_ft_group_pdd_to_pde_coversion(unit, id, &pde_entry);
   2172         rv = soc_mem_write(unit, BSC_DT_PDE_PROFILEm, MEM_BLOCK_ANY, index,
   2173                  &pde_entry);
   2174 
   2175         if (BCM_FAILURE(rv)) {
   2176             bcmi_ft_group_pdd_profile_entry_delete(unit, index);
   2177             return rv;
   2178         }
   2179     }
   2180 
   2181     return BCM_E_NONE;
   2182 }
   2183 
   2184 /*
   2185  * Function:
   2186  *     bcmi_ft_group_pdd_policy_profile_delete
   2187  * Purpose:
   2188  *     Delete policy profile entry for group action profile.
   2189  * Parameters:
   2190  *     unit - (IN) BCM device id
   2191  *     id   - (IN) FT group id.
   2192  *
   2193  * Returns:
   2194  *     BCM_E_XXX
   2195  */
   2196 int
   2197 bcmi_ft_group_pdd_policy_profile_delete(
   2198         int unit,
   2199         bcm_flowtracker_group_t id)
   2200 {
   2201 
   2202     bsc_kg_group_table_entry_t entry;
   2203     bsc_dt_pde_profile_entry_t pde_entry;
   2204     int old_index = 0;
   2205     int rv = BCM_E_NONE;
   2206     int ref_count = 0;
   2207     int alu_load_type = bcmiFtAluLoadTypeNone;
   2208     bcmi_ft_group_pdd_bus_info_t *pdd_info = NULL;
   2209     int total_mems = 0, mem_idx = 0;
   2210 
   2211     /* Group has the pdd profile entry. Here we just need to set it. */
   2212 
   2213     /* First read the group entry. */
   2214     BCM_IF_ERROR_RETURN (soc_mem_read(unit, BSC_KG_GROUP_TABLEm,
   2215             MEM_BLOCK_ANY, id, &entry));
   2216 
   2217     /* now write this index into the group. */
   2218     old_index = soc_mem_field32_get(unit, BSC_KG_GROUP_TABLEm,
   2219             ((uint32 *)&entry), SESSION_DATA_TYPEf);
   2220 
   2221     if (old_index) {
   2222         bcmi_ft_group_pdd_profile_entry_delete(unit, old_index);
   2223     }
   2224 
   2225     /* now write this new index into the group. */
   2226     soc_mem_field32_set(unit, BSC_KG_GROUP_TABLEm, ((uint32 *)&entry),
   2227              SESSION_DATA_TYPEf, 0);
   2228 
   2229     /* Write the entry back into the group table. */
   2230     rv = soc_mem_write(unit, BSC_KG_GROUP_TABLEm, MEM_BLOCK_ANY, id, &entry);
   2231 
   2232     if (BCM_FAILURE(rv)) {
   2233         return rv;
   2234     }
   2235 
   2236     /*
   2237      * First check the refcount of pdd entry.
   2238      * Clear only if no other group is pointing to it.
   2239      */
   2240     rv = bcmi_ft_group_pdd_profile_refcount_get(unit, old_index, &ref_count);
   2241 
   2242     if (BCM_FAILURE(rv)) {
   2243         return rv;
   2244     }
   2245 
   2246     if (ref_count == 0) {
   2247         /* Delete the PDE profile entry also.. */
   2248         sal_memset(&pde_entry, 0, sizeof(bsc_dt_pde_profile_entry_t));
   2249         rv = soc_mem_write(unit, BSC_DT_PDE_PROFILEm, MEM_BLOCK_ANY, old_index,
   2250                  &pde_entry);
   2251 
   2252         if (BCM_FAILURE(rv)) {
   2253             return rv;
   2254         }
   2255     }
   2256 
   2257     /*
   2258      * The group is uninstalled. clear the group's PDD entry.
   2259      * Clear only ALU and Load memories. Rest should not be removed.
   2260      */
   2261     for (alu_load_type=0; alu_load_type<=bcmiFtAluLoadTypeAlu32;
   2262         alu_load_type++) {
   2263 
   2264         total_mems = alu_load_index_info[unit][alu_load_type].total_mem_count;
   2265 
   2266         if (alu_load_type == bcmiFtAluLoadTypeLoad16) {
   2267             total_mems = TOTAL_GROUP_LOAD16_DATA_NUM;
   2268         } else  if (alu_load_type == bcmiFtAluLoadTypeLoad8) {
   2269             total_mems = TOTAL_GROUP_LOAD8_DATA_NUM;
   2270         }
   2271 
   2272         /* For all the alu/load types, check what memories are set in pdd. */
   2273         for (mem_idx=0; mem_idx<total_mems; mem_idx++) {
   2274             /* Now get if this particular field is set in pdd. */
   2275             pdd_info = alu_load_index_info[unit][alu_load_type].pdd_bus_info;
   2276             if (!pdd_info) {
   2277                 return BCM_E_INTERNAL;
   2278             }
   2279             soc_mem_field32_set(unit, BSD_POLICY_ACTION_PROFILEm,
   2280                     (uint32 *)(&(BCMI_FT_GROUP(unit, id)->pdd_entry)),
   2281                     pdd_info[mem_idx].param_id, 0);
   2282         }
   2283     }
   2284 
   2285     return BCM_E_NONE;
   2286 }
   2287 
   2288 /*
   2289  * Function:
   2290  *     bcmi_ft_group_flush_set
   2291  * Purpose:
   2292  *     Remove hash entry from hash table.
   2293  * Parameters:
   2294  *     unit        - (IN) BCM device id
   2295  *     flags       - (IN) Flags for group clear.
   2296  *     num_groups  - (IN) Number of groups to be cleared.
   2297  *     idz         - (IN) list of Ids of all the groups..
   2298  *
   2299  * Returns:
   2300  *     BCM_E_XXX
   2301  */
   2302 int
   2303 bcmi_ft_group_flush_set(
   2304         int unit,
   2305         uint32 flags,
   2306         int num_groups,
   2307         bcm_flowtracker_group_t *idz)
   2308 {
   2309 
   2310     uint64 val64;
   2311     soc_reg_t reg = 0;
   2312     int i = 0;
   2313     int rv;
   2314     int count = 5; /* count 5 is to make 20ms delay */
   2315     uint32 flow_limit[4] = {0};
   2316     int flow_limit_valid[4] = {FALSE};
   2317 
   2318     if (idz == NULL) {
   2319         return BCM_E_PARAM;
   2320     }
   2321 
   2322     if ((num_groups < 1) || (num_groups > 4)) {
   2323         return BCM_E_PARAM;
   2324     }
   2325 
   2326     if (flags & BCM_FLOWTRACKER_GROUP_CLEAR_FLOW_DATA_ONLY) {
   2327         return BCM_E_UNAVAIL;
   2328     }
   2329 
   2330     reg = BSC_AG_GROUP_FLUSH_CONFIG_64r;
   2331     /* Initializr to zero. */
   2332     COMPILER_64_ZERO(val64);
   2333 
   2334     /* Validate each group index. */
   2335     for (; i < num_groups; i++) {
   2336         BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, idz[i]));
   2337 
   2338         if (BCMI_FT_GROUP(unit, idz[i])->flags
   2339                 & BCM_FLOWTRACKER_GROUP_USER_ENTRIES_ONLY) {
   2340             LOG_INFO(BSL_LS_BCM_FLOWTRACKER,
   2341                     (BSL_META_U(unit, "Group Flush is not supported for the"
   2342                                 " group = %d\n"), idz[i]));
   2343             return BCM_E_PARAM;
   2344         }
   2345     }
   2346 
   2347     /* Initiate flush for groups. */
   2348     for (i = 0; i < num_groups; i++) {
   2349         soc_reg64_field32_set(unit, reg, &val64,
   2350             bcmi_ft_group_flush_fields[i].group_id, idz[i]);
   2351 
   2352         soc_reg64_field32_set(unit, reg, &val64,
   2353             bcmi_ft_group_flush_fields[i].group_valid, 1);
   2354 
   2355         LOG_INFO(BSL_LS_BCM_FLOWTRACKER,
   2356             (BSL_META_U(unit, "Group Flush initiated for the group = %d\n"),
   2357             idz[i]));
   2358 
   2359 
   2360     }
   2361 
   2362     /* Set flow limit to 0 so that no new flows is learnt. */
   2363     for (i = 0; i < num_groups; i++) {
   2364         rv = bcmi_ft_group_flow_limit_get(unit, idz[i], &flow_limit[i]);
   2365         /* Flow Limit is not set on this Group */
   2366         if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_CONFIG)) {
   2367             flow_limit_valid[i] = FALSE;
   2368         } else {
   2369             flow_limit_valid[i] = TRUE;
   2370             BCM_IF_ERROR_RETURN(bcmi_ft_group_flow_limit_set(unit, idz[i], 0));
   2371         }
   2372     }
   2373 
   2374     /*
   2375      * Give delay of 4 msec.
   2376      * This is to ensure that all packets have reached groups queue
   2377      * after entring into the flowtracker and got identified
   2378      * to use this group in FTFP.
   2379      */
   2380     sal_usleep(4000);
   2381 
   2382     BCM_IF_ERROR_RETURN(WRITE_BSC_AG_GROUP_FLUSH_CONFIG_64r(unit, val64));
   2383 
   2384     /*
   2385      * Now that we have written into the group register,
   2386      * we need to check if done bit is set.
   2387      * Count valus is 5 to make 20 ms delay but
   2388      * hardware gurantees to come out in a max time of 16 msecs.
   2389      */
   2390     while (count > 1) {
   2391         BCM_IF_ERROR_RETURN(READ_BSC_AG_GROUP_FLUSH_CONFIG_64r(unit, &val64));
   2392 
   2393         if (soc_reg64_field32_get(unit, reg, val64, GROUP_FLUSH_DONEf)) {
   2394             LOG_INFO(BSL_LS_BCM_FLOWTRACKER,
   2395                 (BSL_META_U(unit, "The Group Flush is done for all the requested groups.\n")));
   2396 
   2397             break;
   2398         }
   2399         count--;
   2400         sal_usleep(4000);
   2401     }
   2402 
   2403     /* initialize it again to clear the register value.*/
   2404     COMPILER_64_ZERO(val64);
   2405 
   2406     /* Clear the flush register. */
   2407     BCM_IF_ERROR_RETURN(WRITE_BSC_AG_GROUP_FLUSH_CONFIG_64r(unit, val64));
   2408 
   2409     /* Apply flow limit back to flowtracker group */
   2410     for (i = 0; i < num_groups; i++) {
   2411         if (flow_limit_valid[i] == TRUE) {
   2412             BCM_IF_ERROR_RETURN(bcmi_ft_group_flow_limit_set(unit, idz[i], flow_limit[i]));
   2413         }
   2414     }
   2415 
   2416     return BCM_E_NONE;
   2417 }
   2418 
   2419 /*
   2420  * Function:
   2421  *    bcmi_ft_group_template_data_create
   2422  * Purpose:
   2423  *    Add this flowtracker into the group.
   2424  * Parameters:
   2425  *     unit - (IN) BCM device id
   2426  *     id   - (IN) Flowtracker_group.
   2427  *     load16_indexes - (IN) load16 element array.
   2428  *     load8_indexes - (IN) load8 element array.
   2429  *
   2430  * Returns:
   2431  *     BCM_E_XXX.
   2432  */
   2433 int
   2434 bcmi_ft_group_template_data_create(
   2435         int unit,
   2436         bcm_flowtracker_group_t id,
   2437         int *load16_indexes,
   2438         int *load8_indexes)
   2439 {
   2440 
   2441     bcmi_ft_group_template_list_t **head;
   2442     int running_length = 0;
   2443     bcmi_ft_group_alu_info_t *temp = NULL;
   2444     bcmi_ft_group_alu_info_t *start = NULL;
   2445     int i=0;
   2446     int rv = BCM_E_NONE;
   2447     bcmi_ft_group_alu_info_t *local = NULL;
   2448     bcmi_ft_alu_load_type_t alu_load_type = bcmiFtAluLoadTypeNone;
   2449     int copy_to_cpu = 0;
   2450     int meter_enabled = 0;
   2451     bcmi_ft_group_param_type_t ts_type = bcmiFtGroupParamTypeTsNewLearn;
   2452     soc_field_t ts_data_fields[4] =
   2453                     {DATA_0f, DATA_1f, DATA_2f, DATA_3f};
   2454 
   2455     /* First we should look into the in order of the PDD data. */
   2456 
   2457     /* Get the head of the templs info list. */
   2458     head = &((BCMI_FT_GROUP(unit, id))->template_head);
   2459 
   2460     /*
   2461      * Get the input from session data and then check
   2462      * each type of memories to form the template data.
   2463      * Start with LOAD8 as they are first in the list.
   2464      * We need to do it in order of PDD as that will be the order
   2465      * how the data will be exported. For now, load8 will start from 0.
   2466      */
   2467 
   2468     /* assign the ALU memory chunk to local pointer. */
   2469     start = BCMI_FT_GROUP_EXT_DATA_INFO(unit, id);
   2470     temp = start;
   2471 
   2472     i = 0;
   2473     /* Start setting the space for 4 timestamps. */
   2474     if (soc_mem_field32_get(unit, BSD_POLICY_ACTION_PROFILEm,
   2475         (&(BCMI_FT_GROUP(unit, id)->pdd_entry)), BSD_FLEX_TIMESTAMP_0f)) {
   2476         ts_type = bcmi_ft_group_get_ts_type(unit, id, ts_data_fields[i]);
   2477 
   2478         rv = bcmi_ft_group_template_list_add(unit, head,
   2479                 running_length, 48, ts_type, NULL);
   2480         BCMI_CLEANUP_IF_ERROR(rv);
   2481 
   2482         /* Timestamp 0 is enabled. length=48 bits. */
   2483         running_length +=48;
   2484         i++;
   2485     }
   2486 
   2487     /* Start setting the space for 4 timestamps. */
   2488     if (soc_mem_field32_get(unit, BSD_POLICY_ACTION_PROFILEm,
   2489         (&(BCMI_FT_GROUP(unit, id)->pdd_entry)), BSD_FLEX_TIMESTAMP_1f)) {
   2490         /* Timestamp 1 is enabled. length=48 bits. */
   2491         ts_type = bcmi_ft_group_get_ts_type(unit, id, ts_data_fields[i]);
   2492 
   2493         rv = bcmi_ft_group_template_list_add(unit, head,
   2494                 running_length, 48, ts_type, NULL);
   2495         BCMI_CLEANUP_IF_ERROR(rv);
   2496 
   2497         /* Timestamp 0 is enabled. length=48 bits. */
   2498         running_length +=48;
   2499         i++;
   2500     }
   2501 
   2502     /* Start setting the space for 4 timestamps. */
   2503     if (soc_mem_field32_get(unit, BSD_POLICY_ACTION_PROFILEm,
   2504         (&(BCMI_FT_GROUP(unit, id)->pdd_entry)), BSD_FLEX_TIMESTAMP_2f)) {
   2505         /* Timestamp 2 is enabled. length=48 bits. */
   2506         ts_type = bcmi_ft_group_get_ts_type(unit, id, ts_data_fields[i]);
   2507 
   2508         rv = bcmi_ft_group_template_list_add(unit, head,
   2509                 running_length, 48, ts_type, NULL);
   2510         BCMI_CLEANUP_IF_ERROR(rv);
   2511 
   2512         /* Timestamp 0 is enabled. length=48 bits. */
   2513         running_length +=48;
   2514         i++;
   2515     }
   2516 
   2517     /* Start setting the space for 4 timestamps. */
   2518     if (soc_mem_field32_get(unit, BSD_POLICY_ACTION_PROFILEm,
   2519         (&(BCMI_FT_GROUP(unit, id)->pdd_entry)), BSD_FLEX_TIMESTAMP_3f)) {
   2520         /* Timestamp 3 is enabled. length=48 bits. */
   2521         ts_type = bcmi_ft_group_get_ts_type(unit, id, ts_data_fields[i]);
   2522 
   2523         rv = bcmi_ft_group_template_list_add(unit, head,
   2524                 running_length, 48, ts_type, NULL);
   2525         BCMI_CLEANUP_IF_ERROR(rv);
   2526 
   2527         /* Timestamp 0 is enabled. length=48 bits. */
   2528         running_length +=48;
   2529         i++;
   2530     }
   2531 
   2532 
   2533     meter_enabled = soc_mem_field32_get(unit, BSD_POLICY_ACTION_PROFILEm,
   2534         (&(BCMI_FT_GROUP(unit, id)->pdd_entry)),
   2535         BSD_FLEX_FLOW_METERf);
   2536 
   2537     if (meter_enabled) {
   2538         /* 48 bits are used for metering. */
   2539         rv = bcmi_ft_group_template_list_add(unit, head,
   2540                 running_length, 48, bcmiFtGroupParamTypeMeter, NULL);
   2541         BCMI_CLEANUP_IF_ERROR(rv);
   2542 
   2543         running_length +=48;
   2544     }
   2545 
   2546     /* Add ALU32s into the template list based on PDD. */
   2547     for (i=0; i<TOTAL_GROUP_ALU32_MEM; i++) {
   2548         alu_load_type = bcmiFtAluLoadTypeAlu32;
   2549 
   2550         if (bcmi_ft_group_alu_load_pdd_status_get(
   2551             unit, id, alu_load_type, i)) {
   2552 
   2553             /* Check for this index and get corresponding data. */
   2554             rv = bcmi_ft_group_alu_load_index_match_data_get
   2555                      (unit, id, alu_load_type, i, &temp);
   2556 
   2557             if (BCM_FAILURE(rv)) {
   2558                 continue;
   2559             }
   2560             rv = bcmi_ft_group_template_list_add(unit, head,
   2561                 running_length, 32, bcmiFtGroupParamTypeTracking, temp);
   2562 
   2563             BCMI_CLEANUP_IF_ERROR(rv);
   2564             running_length += 32;
   2565         }
   2566     }
   2567 
   2568     temp = start;
   2569     /* Get all the elements for load16.*/
   2570     for (i=TOTAL_GROUP_LOAD16_DATA_NUM-1; i>=0; i--) {
   2571         int len=0;
   2572         if (load16_indexes[i] == -1) {
   2573             continue;
   2574         }
   2575         local = (&(start[load16_indexes[i]]));
   2576 
   2577         if ((local->element_type1 == bcmFlowtrackerTrackingParamTypeDosAttack) ||
   2578             (local->element_type1 == bcmFlowtrackerTrackingParamTypeInnerDosAttack)) {
   2579            /* Add 16 bit length to display proper results in export. */
   2580            len = 16;
   2581            i--;
   2582         }
   2583 
   2584         /* If there is some data then add it into list. */
   2585         rv = bcmi_ft_group_template_list_add(unit, head,
   2586             running_length, 16+len, bcmiFtGroupParamTypeTracking, local);
   2587 
   2588         BCMI_CLEANUP_IF_ERROR(rv);
   2589         running_length += (16+len);
   2590     }
   2591 
   2592     temp = start;
   2593 
   2594 
   2595     /* Add ALU16s into template list based on PDD. */
   2596     for (i=0; i<TOTAL_GROUP_ALU16_MEM; i++) {
   2597         alu_load_type = bcmiFtAluLoadTypeAlu16;
   2598 
   2599         if (bcmi_ft_group_alu_load_pdd_status_get(
   2600             unit, id, alu_load_type, i)) {
   2601 
   2602             /* Check for this index and get corresponding data. */
   2603             rv = bcmi_ft_group_alu_load_index_match_data_get
   2604                      (unit, id, alu_load_type, i, &temp);
   2605 
   2606             if (BCM_FAILURE(rv)) {
   2607                 continue;
   2608             }
   2609             rv = bcmi_ft_group_template_list_add(unit, head,
   2610                 running_length, 16, bcmiFtGroupParamTypeTracking, temp);
   2611 
   2612             BCMI_CLEANUP_IF_ERROR(rv);
   2613             running_length += 16;
   2614         }
   2615     }
   2616 
   2617     copy_to_cpu = soc_mem_field32_get(unit, BSD_POLICY_ACTION_PROFILEm,
   2618         (&(BCMI_FT_GROUP(unit, id)->pdd_entry)),
   2619         BSD_FLEX_FLOW_COUNT_TO_CPUf);
   2620 
   2621     if (copy_to_cpu) {
   2622         rv = bcmi_ft_group_template_list_add(unit, head,
   2623             running_length, 16, bcmiFtGroupParamTypeCollectorCopy, NULL);
   2624 
   2625         BCMI_CLEANUP_IF_ERROR(rv);
   2626         running_length += 16;
   2627     }
   2628 
   2629     /* Get all the elements of load8 and then add them into order. */
   2630     for (i=TOTAL_GROUP_LOAD8_DATA_NUM-1; i>=0; i--) {
   2631         if (load8_indexes[i] == -1) {
   2632             continue;
   2633         }
   2634         local = (&(start[load8_indexes[i]]));
   2635 
   2636         rv = bcmi_ft_group_template_list_add(unit, head,
   2637             running_length, 8, bcmiFtGroupParamTypeTracking, local);
   2638 
   2639         BCMI_CLEANUP_IF_ERROR(rv);
   2640         running_length += 8;
   2641     }
   2642 
   2643     /* We can put FT_STATE here but anyways it is not exposed to user. */
   2644     return BCM_E_NONE;
   2645 
   2646 cleanup :
   2647     bcmi_ft_group_template_list_delete_all(unit, head);
   2648     return rv;
   2649 }
   2650 
   2651 
   2652 /*
   2653  * Function:
   2654  *    bcmi_ft_group_template_list_add
   2655  * Purpose:
   2656  *    Add this flowtracker into the group.
   2657  * Parameters:
   2658  *     unit - (IN) BCM device id
   2659  *     head - (INOUT) Head pointer of the list.
   2660  *     start - (IN) start of location.
   2661  *     length - (IN) length of element.
   2662  *     type  - (IN) type of element.
   2663  *
   2664  * Returns:
   2665  *     BCM_E_XXX.
   2666  */
   2667 int
   2668 bcmi_ft_group_template_list_add(
   2669         int unit,
   2670         bcmi_ft_group_template_list_t **head,
   2671         int start,
   2672         int length,
   2673         bcmi_ft_group_param_type_t type,
   2674         bcmi_ft_group_alu_info_t *info)
   2675 {
   2676     int rv = BCM_E_NONE;
   2677     int shift_bits = 0;
   2678     bcmi_flowtracker_flowchecker_info_t check_info;
   2679     bcmi_ft_group_template_list_t *temp_node = NULL;
   2680     bcmi_ft_group_template_list_t *node_iter = NULL;
   2681     bcmi_ft_group_template_list_t *node_prev = NULL;
   2682 
   2683     temp_node = (bcmi_ft_group_template_list_t *)
   2684         sal_alloc(sizeof(bcmi_ft_group_template_list_t),
   2685                 "flowchecker list Node");
   2686     if (temp_node == NULL) {
   2687         return BCM_E_MEMORY;
   2688     }
   2689     sal_memset(temp_node, 0, sizeof (bcmi_ft_group_template_list_t));
   2690 
   2691     temp_node->info.cont_offset = start;
   2692     temp_node->info.data_shift = 0;
   2693     temp_node->info.cont_width = length;
   2694     temp_node->info.param_type = type;
   2695     temp_node->next = NULL;
   2696 
   2697     if (info != NULL) {
   2698         temp_node->info.param = info->element_type1;
   2699         temp_node->info.check_id = info->flowchecker_id;
   2700         temp_node->info.index = info->alu_load_index;
   2701         temp_node->info.type = info->alu_load_type;
   2702         temp_node->info.flags = info->flags;
   2703 
   2704         if (temp_node->info.check_id) {
   2705             temp_node->info.param_type = bcmiFtGroupParamTypeFlowchecker;
   2706 
   2707             /* Shift data_offset, if required */
   2708             sal_memset(&check_info, 0,
   2709                     sizeof (bcmi_flowtracker_flowchecker_info_t));
   2710             rv = bcmi_ft_flowchecker_get
   2711                 (unit, temp_node->info.check_id, &check_info);
   2712             if (BCM_FAILURE(rv)) {
   2713                 sal_free(temp_node);
   2714                 return rv;
   2715             }
   2716             bcmi_ft_check_action_shift_bits_get(unit,
   2717                     check_info.action_info.action, info, &shift_bits);
   2718             temp_node->info.data_shift = shift_bits;
   2719         }
   2720     }
   2721 
   2722     /* Insert temp_node at appropriate location. */
   2723     node_prev = NULL;
   2724     node_iter = (*head);
   2725     while (node_iter != NULL) {
   2726         if (info && (node_iter->info.type == info->alu_load_type)) {
   2727             if (node_iter->info.index > info->alu_load_index) {
   2728                 break;
   2729             }
   2730         }
   2731         node_prev = node_iter;
   2732         node_iter = node_iter->next;
   2733     }
   2734 
   2735     if (node_prev != NULL) {
   2736         /* Insert after node_prev */
   2737         temp_node->next = node_prev->next;
   2738         node_prev->next = temp_node;
   2739     } else {
   2740         /* Insert at HEAD */
   2741         temp_node->next = (*head);
   2742         (*head) = temp_node;
   2743     }
   2744 
   2745     return BCM_E_NONE;
   2746 }
   2747 
   2748 /*
   2749  * Function:
   2750  *    bcmi_ft_group_template_list_delete_all
   2751  * Purpose:
   2752  *    Delete this flowtracker check from group list.
   2753  * Parameters:
   2754  *     unit - (IN) BCM device id
   2755  *     head - (INOUT) Head pointer of the list.
   2756  *
   2757  * Returns:
   2758  *     BCM_E_XXX.
   2759  */
   2760 void
   2761 bcmi_ft_group_template_list_delete_all(
   2762         int unit,
   2763         bcmi_ft_group_template_list_t **head)
   2764 {
   2765 
   2766     bcmi_ft_group_template_list_t *temp, *prev;
   2767 
   2768     if (!head) {
   2769         return;
   2770     }
   2771 
   2772     prev = temp = (*head);
   2773 
   2774     while(temp) {
   2775         prev = temp;
   2776         temp = temp->next;
   2777         sal_free(prev);
   2778         prev = NULL;
   2779 
   2780     }
   2781 
   2782     *head = NULL;
   2783     return;
   2784 }
   2785 
   2786 /*
   2787  * Function:
   2788  *      bcmi_flowtracker_group_control_set
   2789  * Purpose:
   2790  *      Set value of group control.
   2791  * Parameters:
   2792  *      unit          - (IN)  BCM device number
   2793  *      id            - (IN)  Flow group Id
   2794  *      type          - (IN)  type of group control.
   2795  *      arg           - (IN) value of control
   2796  * Returns:
   2797  *      BCM_E_XXX   - BCM error code.
   2798  */
   2799 int
   2800 bcmi_flowtracker_group_control_set(
   2801     int unit,
   2802     bcm_flowtracker_group_t id,
   2803     bcm_flowtracker_group_control_type_t type,
   2804     int arg)
   2805 {
   2806 
   2807     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   2808 
   2809     switch(type) {
   2810         case bcmFlowtrackerGroupControlNewLearnEnable:
   2811             if (arg > 1) {
   2812                 return BCM_E_PARAM;
   2813             }
   2814 
   2815             if ((BCMI_FT_GROUP(unit, id))->flags & BCM_FLOWTRACKER_GROUP_USER_ENTRIES_ONLY) {
   2816                 return BCM_E_CONFIG;
   2817             }
   2818 
   2819             BCM_IF_ERROR_RETURN(
   2820                 _bcm_field_ft_group_control_set(unit, id, type, arg));
   2821 
   2822             /* Add that value in local data and send notification to ftfp. */
   2823             BCMI_FT_GROUP_FTFP_DATA(unit, id).new_learn = arg;
   2824         break;
   2825 
   2826         case bcmFlowtrackerGroupControlFlowtrackerEnable:
   2827             if (arg > 1 ) {
   2828                 return BCM_E_PARAM;
   2829             }
   2830 
   2831             /* Check if FT Collector is present if when FT Group is busy */
   2832             if (BCMI_FT_GROUP_IS_BUSY(unit, id)) {
   2833                 if (BCMI_FT_GROUP(unit, id)->collector_id == BCMI_FT_COLLECTOR_ID_INVALID) {
   2834                     LOG_ERROR(BSL_LS_BCM_FLOWTRACKER,
   2835                             (BSL_META_U(unit, "Collector is not associated"
   2836                                         " with Flowtracker Group (%d)\n "), id));
   2837                     return BCM_E_CONFIG;
   2838                 }
   2839             }
   2840 
   2841             BCM_IF_ERROR_RETURN(
   2842                 _bcm_field_ft_group_control_set(unit, id, type, arg));
   2843 
   2844             /* Add that value in local data and send notification to ftfp. */
   2845             BCMI_FT_GROUP_FTFP_DATA(unit, id).flowtrack = arg;
   2846         break;
   2847 
   2848         case bcmFlowtrackerGroupControlFlowDirection:
   2849 
   2850             if (arg == bcmFlowtrackerFlowDirectionBidirectional) {
   2851                 if (!(soc_feature(unit,
   2852                     soc_feature_flowtracker_ver_1_bidirectional))) {
   2853                     return BCM_E_UNAVAIL;
   2854                 }
   2855             } else if (arg == bcmFlowtrackerFlowDirectionReverse) {
   2856                 return BCM_E_UNAVAIL;
   2857             }
   2858 
   2859             if (BCMI_FT_GROUP_IS_BUSY(unit, id)) {
   2860                 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
   2861                     "Not allowed to alter installed flow Group (%d)\n "), id));
   2862 
   2863                 return BCM_E_CONFIG;
   2864             }
   2865 
   2866             if (arg >= bcmFlowtrackerFlowDirectionCount) {
   2867                 return BCM_E_PARAM;
   2868             }
   2869 
   2870             if (arg == BCMI_FT_GROUP_FTFP_DATA(unit, id).direction) {
   2871                 return BCM_E_NONE;
   2872             }
   2873 
   2874             BCM_IF_ERROR_RETURN(
   2875                 _bcm_field_ft_group_control_set(unit, id, type, arg));
   2876 
   2877             /* Add that value in local data and send notification to ftfp. */
   2878             BCMI_FT_GROUP_FTFP_DATA(unit, id).direction = arg;
   2879             /*
   2880              * To change the direction run time, we need to change
   2881              * ALU/LOAD memories associated with this group.
   2882              */
   2883             BCM_IF_ERROR_RETURN(
   2884                 bcmi_ft_group_alu_load_trigger_set(unit, id, arg));
   2885         break;
   2886 
   2887         default:
   2888             /* Nothing else is supported.. */
   2889         return BCM_E_PARAM;
   2890    }
   2891 
   2892 
   2893     return BCM_E_NONE;
   2894 }
   2895 
   2896 /*
   2897  * Function:
   2898  *      bcmi_flowtracker_group_control_get
   2899  * Purpose:
   2900  *      Set value of group control.
   2901  * Parameters:
   2902  *      unit          - (IN)  BCM device number
   2903  *      id            - (IN)  Flow group Id
   2904  *      type          - (IN)  type of group control.
   2905  *      arg           - (OUT) value of control
   2906  * Returns:
   2907  *      BCM_E_XXX   - BCM error code.
   2908  */
   2909 int
   2910 bcmi_flowtracker_group_control_get(
   2911     int unit,
   2912     bcm_flowtracker_group_t id,
   2913     bcm_flowtracker_group_control_type_t type,
   2914     int *arg)
   2915 {
   2916 
   2917     int rv = BCM_E_NONE;
   2918 
   2919     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   2920 
   2921     switch(type) {
   2922 
   2923         case bcmFlowtrackerGroupControlNewLearnEnable:
   2924             /* Add that value in local data and send notification to ftfp. */
   2925             *arg = BCMI_FT_GROUP_FTFP_DATA(unit, id).new_learn;
   2926         break;
   2927 
   2928         case bcmFlowtrackerGroupControlFlowtrackerEnable:
   2929             /* Add that value in local data and send notification to ftfp. */
   2930             *arg = BCMI_FT_GROUP_FTFP_DATA(unit, id).flowtrack;
   2931         break;
   2932 
   2933         case bcmFlowtrackerGroupControlFlowDirection:
   2934             /* Add that value in local data and send notification to ftfp. */
   2935             *arg = BCMI_FT_GROUP_FTFP_DATA(unit, id).direction;
   2936         break;
   2937 
   2938         default:
   2939             /* Nothing else is supported.. */
   2940         return BCM_E_PARAM;
   2941    }
   2942 
   2943     return rv;
   2944 }
   2945 
   2946 /*
   2947  * Function:
   2948  *      bcmi_ft_group_stat_get
   2949  * Purpose:
   2950  *      Get statistics of group.
   2951  * Parameters:
   2952  *      unit          - (IN)  BCM device number
   2953  *      id            - (IN)  Flow group Id
   2954  *      group_stats   - (OUT) stats of the group.
   2955  * Returns:
   2956  *      BCM_E_XXX   - BCM error code.
   2957  */
   2958 int
   2959 bcmi_ft_group_stat_get(
   2960         int unit,
   2961         bcm_flowtracker_group_t id,
   2962         bcm_flowtracker_group_stat_t *group_stats)
   2963 {
   2964 
   2965     uint64 val;
   2966     uint32 val32 = 0;
   2967 
   2968     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   2969 
   2970     if (!group_stats) {
   2971         return BCM_E_PARAM;
   2972     }
   2973 
   2974     sal_memset(group_stats, 0, sizeof(bcm_flowtracker_group_stat_t));
   2975 
   2976     COMPILER_64_ZERO(val);
   2977     BCM_IF_ERROR_RETURN(soc_counter_get(unit, REG_PORT_ANY,
   2978         SOC_COUNTER_NON_DMA_FT_GROUP_FLOW_NUM_EXCEEDED_CNT, id, &val));
   2979 
   2980     COMPILER_64_COPY(group_stats->flow_exceeded_count, val);
   2981 
   2982     COMPILER_64_TO_32_LO(val32, val);
   2983 
   2984     LOG_INFO(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
   2985         "flow_exceeded_count = %d for group: %d\n"), val32, id));
   2986 
   2987 
   2988     BCM_IF_ERROR_RETURN(soc_counter_get(unit, REG_PORT_ANY,
   2989         SOC_COUNTER_NON_DMA_FT_GROUP_FLOW_MISSED_CNT, id, &val));
   2990 
   2991     COMPILER_64_COPY(group_stats->flow_missed_count, val);
   2992 
   2993     COMPILER_64_TO_32_LO(val32, val);
   2994 
   2995     LOG_INFO(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
   2996         "flow_missed_count = %d for group: %d\n"), val32, id));
   2997 
   2998 
   2999     BCM_IF_ERROR_RETURN(soc_counter_get(unit, REG_PORT_ANY,
   3000         SOC_COUNTER_NON_DMA_FT_GROUP_FLOW_AGE_OUT_CNT, id, &val));
   3001 
   3002     COMPILER_64_COPY(group_stats->flow_aged_out_count, val);
   3003 
   3004     LOG_INFO(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
   3005         "flow_aged_out_count = %d for group: %d\n"), val32, id));
   3006 
   3007     BCM_IF_ERROR_RETURN(soc_counter_get(unit, REG_PORT_ANY,
   3008         SOC_COUNTER_NON_DMA_FT_GROUP_FLOW_LEARNT_CNT, id, &val));
   3009 
   3010     if (BCMI_FT_GROUP(unit, id)->flags &
   3011             BCM_FLOWTRACKER_GROUP_USER_ENTRIES_ONLY) {
   3012         COMPILER_64_ZERO(val);
   3013     }
   3014 
   3015     COMPILER_64_COPY(group_stats->flow_learnt_count, val);
   3016 
   3017     COMPILER_64_TO_32_LO(val32, val);
   3018 
   3019     LOG_INFO(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
   3020         "flow_learnt_count = %d for group: %d\n"), val32, id));
   3021 
   3022 
   3023     BCM_IF_ERROR_RETURN(soc_counter_get(unit, REG_PORT_ANY,
   3024         SOC_COUNTER_NON_DMA_FT_GROUP_FLOW_METER_EXCEEDED_CNT, id, &val));
   3025 
   3026     COMPILER_64_COPY(group_stats->flow_meter_exceeded_count, val);
   3027 
   3028     COMPILER_64_TO_32_LO(val32, val);
   3029 
   3030 
   3031     LOG_INFO(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
   3032         "flow_meter_exceeded_count = %d for group: %d\n"), val32, id));
   3033 
   3034     return BCM_E_NONE;
   3035 
   3036 }
   3037 
   3038 /*
   3039  * Function:
   3040  *      bcmi_ft_group_stat_set
   3041  * Purpose:
   3042  *      Set statistics of group.
   3043  * Parameters:
   3044  *      unit          - (IN)  BCM device number
   3045  *      id            - (IN)  Flow group Id
   3046  *      group_stats   - (IN) stats of the group.
   3047  * Returns:
   3048  *      BCM_E_XXX   - BCM error code.
   3049  */
   3050 int
   3051 bcmi_ft_group_stat_set(
   3052         int unit,
   3053         bcm_flowtracker_group_t id,
   3054         bcm_flowtracker_group_stat_t *group_stats)
   3055 {
   3056 
   3057     uint64 val;
   3058 
   3059     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   3060 
   3061     if (!group_stats) {
   3062         return BCM_E_PARAM;
   3063     }
   3064 
   3065     /* Flows missed because of group's flows limit is reached. */
   3066     COMPILER_64_COPY(val, group_stats->flow_exceeded_count);
   3067 
   3068     BCM_IF_ERROR_RETURN(soc_counter_set(unit, REG_PORT_ANY,
   3069         SOC_COUNTER_NON_DMA_FT_GROUP_FLOW_NUM_EXCEEDED_CNT, id, val));
   3070 
   3071 
   3072     /* Flows missed because of table full on this group. */
   3073     COMPILER_64_COPY(val, group_stats->flow_missed_count);
   3074 
   3075     BCM_IF_ERROR_RETURN(soc_counter_set(unit, REG_PORT_ANY,
   3076         SOC_COUNTER_NON_DMA_FT_GROUP_FLOW_MISSED_CNT, id, val));
   3077 
   3078 
   3079     /* Flows aged out on this group. */
   3080     COMPILER_64_COPY(val, group_stats->flow_aged_out_count);
   3081 
   3082     BCM_IF_ERROR_RETURN(soc_counter_set(unit, REG_PORT_ANY,
   3083         SOC_COUNTER_NON_DMA_FT_GROUP_FLOW_AGE_OUT_CNT, id, val));
   3084 
   3085     /* FLows learnt on a group. */
   3086     COMPILER_64_COPY(val, group_stats->flow_learnt_count);
   3087 
   3088     BCM_IF_ERROR_RETURN(soc_counter_set(unit, REG_PORT_ANY,
   3089         SOC_COUNTER_NON_DMA_FT_GROUP_FLOW_LEARNT_CNT, id, val));
   3090 
   3091 
   3092     /* Flow meter exceed count. */
   3093     COMPILER_64_COPY(val, group_stats->flow_meter_exceeded_count);
   3094 
   3095     BCM_IF_ERROR_RETURN(soc_counter_set(unit, REG_PORT_ANY,
   3096         SOC_COUNTER_NON_DMA_FT_GROUP_FLOW_METER_EXCEEDED_CNT, id, val));
   3097 
   3098     return BCM_E_NONE;
   3099 
   3100 }
   3101 
   3102 /*
   3103  * Function:
   3104  *      bcmi_ft_group_export_trigger_verify
   3105  * Purpose:
   3106  *      verify export triggers on group.
   3107  * Parameters:
   3108  *      unit                - (IN) BCM device number
   3109  *      id                  - (IN) Flow group Id
   3110  *      export_trigger_info - (IN) Export trigger info.
   3111  * Returns:
   3112  *      BCM_E_XXX   - BCM error code.
   3113  */
   3114 int
   3115 bcmi_ft_group_export_trigger_verify(
   3116         int unit,
   3117         bcm_flowtracker_group_t id,
   3118         bcm_flowtracker_export_trigger_info_t *export_trigger_info)
   3119 {
   3120     uint32 val;
   3121     uint32 interval = 0;
   3122     uint64 reg64;
   3123 
   3124     /* export trigger for periodic timer. */
   3125     val = ((BCM_FLOWTRACKER_TRIGGER_GET(*export_trigger_info,
   3126                     bcmFlowtrackerExportTriggerTimer)) ? 1 : 0);
   3127     if (val != 0) {
   3128         COMPILER_64_SET(reg64, 0, 0);
   3129         BCM_IF_ERROR_RETURN(READ_BSC_AG_PERIODIC_EXPORTr(unit, &reg64));
   3130         interval = soc_reg64_field32_get(unit,
   3131                 BSC_AG_PERIODIC_EXPORTr, reg64, EXPORT_PERIODf);
   3132         if (interval == 0) {
   3133             LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, "Periodic"
   3134                             " export interval is not configured\n\r")));
   3135             return BCM_E_CONFIG;
   3136         }
   3137     }
   3138 
   3139     val = ((BCM_FLOWTRACKER_TRIGGER_GET(*export_trigger_info,
   3140                     bcmFlowtrackerExportTriggerNewLearn)) ? 1 : 0);
   3141     if (val != 0) {
   3142         if (BCMI_FT_GROUP(unit, id)->flags
   3143                 & BCM_FLOWTRACKER_GROUP_USER_ENTRIES_ONLY) {
   3144             LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, "Export"
   3145                             " on New Learn is not supported on Software"
   3146                             " mananged Flowtracker group\n\r")));
   3147             return BCM_E_CONFIG;
   3148         }
   3149     }
   3150 
   3151     /* export trigger for ageout. */
   3152     val = ((BCM_FLOWTRACKER_TRIGGER_GET(*export_trigger_info,
   3153                     bcmFlowtrackerExportTriggerAgeOut)) ? 1 : 0);
   3154     if (val != 0) {
   3155         if (BCMI_FT_GROUP(unit, id)->flags
   3156                 & BCM_FLOWTRACKER_GROUP_USER_ENTRIES_ONLY) {
   3157             LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, "Export"
   3158                             " on ageout is not supported on Software"
   3159                             " mananged Flowtracker group\n\r")));
   3160             return BCM_E_CONFIG;
   3161         }
   3162     }
   3163 
   3164     /* export trigger on drop . */
   3165     val = ((BCM_FLOWTRACKER_TRIGGER_GET(*export_trigger_info,
   3166                     bcmFlowtrackerExportTriggerDrop)) ? 1 : 0);
   3167     if (val != 0) {
   3168         LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit, "Export"
   3169                         " on drop is not supported\n\r")));
   3170         return BCM_E_PARAM;
   3171     }
   3172 
   3173     return BCM_E_NONE;
   3174 }
   3175 
   3176 /*
   3177  * Function:
   3178  *      bcmi_ft_group_export_trigger_set
   3179  * Purpose:
   3180  *      Set export triggers on group.
   3181  * Parameters:
   3182  *      unit                - (IN) BCM device number
   3183  *      id                  - (IN) Flow group Id
   3184  *      export_trigger_info - (IN) Export trigger info.
   3185  * Returns:
   3186  *      BCM_E_XXX   - BCM error code.
   3187  */
   3188 int
   3189 bcmi_ft_group_export_trigger_set(
   3190         int unit,
   3191         bcm_flowtracker_group_t id,
   3192         bcm_flowtracker_export_trigger_info_t *export_trigger_info)
   3193 {
   3194     uint32 val = 0;
   3195     bsc_kg_group_table_entry_t kg_entry;
   3196 
   3197     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   3198 
   3199     if (!export_trigger_info) {
   3200         return BCM_E_PARAM;
   3201     }
   3202 
   3203     BCM_IF_ERROR_RETURN(bcmi_ft_group_export_trigger_verify(unit,
   3204                 id, export_trigger_info));
   3205 
   3206     /* Set export trigger for new learn. */
   3207     val = ((BCM_FLOWTRACKER_TRIGGER_GET(*export_trigger_info,
   3208             bcmFlowtrackerExportTriggerNewLearn)) ? 1 : 0);
   3209 
   3210     BCM_IF_ERROR_RETURN (soc_mem_read(unit, BSC_KG_GROUP_TABLEm,
   3211          MEM_BLOCK_ANY, id, &kg_entry));
   3212 
   3213     soc_mem_field32_set(unit, BSC_KG_GROUP_TABLEm, &kg_entry,
   3214         EXPORT_LEARNf, val);
   3215 
   3216     /* Set export trigger for periodic timer. */
   3217     val = ((BCM_FLOWTRACKER_TRIGGER_GET(*export_trigger_info,
   3218             bcmFlowtrackerExportTriggerTimer)) ? 1 : 0);
   3219 
   3220     soc_mem_field32_set(unit, BSC_KG_GROUP_TABLEm, &kg_entry,
   3221         PERIODIC_EXPORT_ENf, val);
   3222 
   3223     /* Write the entry back into group table. */
   3224     BCM_IF_ERROR_RETURN(soc_mem_write(unit, BSC_KG_GROUP_TABLEm, MEM_BLOCK_ALL,
   3225         id, &kg_entry));
   3226 
   3227     /* Set export trigger for age out. */
   3228     val = ((BCM_FLOWTRACKER_TRIGGER_GET(*export_trigger_info,
   3229                     bcmFlowtrackerExportTriggerAgeOut)) ? 1 : 0);
   3230 
   3231     BCM_IF_ERROR_RETURN(bcmi_ft_group_age_export_trigger_set(unit, id, val));
   3232 
   3233     return BCM_E_NONE;
   3234 }
   3235 
   3236 
   3237 /*
   3238  * Function:
   3239  *      bcmi_ft_group_export_trigger_get
   3240  * Purpose:
   3241  *      Get export triggers of group.
   3242  * Parameters:
   3243  *      unit                - (IN) BCM device number
   3244  *      id                  - (IN) Flow group Id
   3245  *      export_trigger_info - (OUT) Export trigger info.
   3246  * Returns:
   3247  *      BCM_E_XXX   - BCM error code.
   3248  */
   3249 int
   3250 bcmi_ft_group_export_trigger_get(
   3251         int unit,
   3252         bcm_flowtracker_group_t id,
   3253         bcm_flowtracker_export_trigger_info_t *export_trigger_info)
   3254 {
   3255 
   3256     bsc_kg_group_table_entry_t kg_entry;
   3257     uint32 val = 0;
   3258 
   3259     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   3260 
   3261     if (!export_trigger_info) {
   3262         return BCM_E_PARAM;
   3263     }
   3264 
   3265     sal_memset(export_trigger_info, 0,
   3266         sizeof(bcm_flowtracker_export_trigger_info_t));
   3267 
   3268     /* Read the group table. */
   3269     BCM_IF_ERROR_RETURN (soc_mem_read(unit, BSC_KG_GROUP_TABLEm,
   3270          MEM_BLOCK_ANY, id, &kg_entry));
   3271 
   3272     val = soc_mem_field32_get(unit, BSC_KG_GROUP_TABLEm, &kg_entry,
   3273               EXPORT_LEARNf);
   3274 
   3275     /* Set export trigger for new learn. */
   3276     if (val) {
   3277         BCM_FLOWTRACKER_TRIGGER_SET(*export_trigger_info,
   3278             bcmFlowtrackerExportTriggerNewLearn);
   3279     }
   3280 
   3281     val = soc_mem_field32_get(unit, BSC_KG_GROUP_TABLEm, &kg_entry,
   3282               PERIODIC_EXPORT_ENf);
   3283 
   3284     /* Set export trigger for periodic timer. */
   3285     if (val) {
   3286         BCM_FLOWTRACKER_TRIGGER_SET(*export_trigger_info,
   3287             bcmFlowtrackerExportTriggerTimer);
   3288     }
   3289 
   3290     /* Check export trigger for age out. */
   3291     BCM_IF_ERROR_RETURN(bcmi_ft_group_age_export_trigger_get(unit, id, &val));
   3292     if (val) {
   3293         BCM_FLOWTRACKER_TRIGGER_SET(*export_trigger_info,
   3294             bcmFlowtrackerExportTriggerAgeOut);
   3295     }
   3296 
   3297 
   3298     return BCM_E_NONE;
   3299 }
   3300 
   3301 /*
   3302  * Function:
   3303  *      bcmi_ft_group_cpu_notification_trigger_set
   3304  * Purpose:
   3305  *      Set cpu notificaiton on of group.
   3306  * Parameters:
   3307  *      unit                - (IN) BCM device number
   3308  *      id                  - (IN) Flow group Id
   3309  *      notifications       - (IN) Export trigger info.
   3310  * Returns:
   3311  *      BCM_E_XXX   - BCM error code.
   3312  */
   3313 int
   3314 bcmi_ft_group_cpu_notification_trigger_set(
   3315         int unit,
   3316         bcm_flowtracker_group_t id,
   3317         bcm_flowtracker_cpu_notification_info_t *notifications)
   3318 {
   3319 
   3320     bsc_kg_group_table_entry_t kg_entry;
   3321     uint32 val = 0;
   3322 
   3323     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   3324 
   3325     if (!notifications) {
   3326         return BCM_E_PARAM;
   3327     }
   3328 
   3329     BCM_IF_ERROR_RETURN (soc_mem_read(unit, BSC_KG_GROUP_TABLEm,
   3330         MEM_BLOCK_ANY, id, &kg_entry));
   3331 
   3332     /* Notify CPU if flow exceeded than configured on group. */
   3333     val = ((BCM_FLOWTRACKER_CPU_NOTIFICATION_GET(
   3334         *notifications,
   3335         bcmFlowtrackerCpuNotificationFlowExceeded)) ? 1 : 0);
   3336 
   3337     soc_mem_field32_set(unit, BSC_KG_GROUP_TABLEm, &kg_entry,
   3338         FLOW_EXCEED_INTR_ENf, val);
   3339 
   3340 
   3341     /* Notify CPU if Table is full and no new flow can be learnt. */
   3342     val = ((BCM_FLOWTRACKER_CPU_NOTIFICATION_GET(
   3343         *notifications,
   3344         bcmbcmFlowtrackerCpuNotificationTableFull)) ? 1 : 0);
   3345 
   3346     soc_mem_field32_set(unit, BSC_KG_GROUP_TABLEm, &kg_entry,
   3347         FT_TABLE_FULL_INTR_ENf, val);
   3348 
   3349     /* Write the entry back into group table. */
   3350     BCM_IF_ERROR_RETURN(soc_mem_write(unit, BSC_KG_GROUP_TABLEm, MEM_BLOCK_ALL,
   3351         id, &kg_entry));
   3352 
   3353     return BCM_E_NONE;
   3354 }
   3355 
   3356 /*
   3357  * Function:
   3358  *      bcmi_ft_group_cpu_notification_trigger_get
   3359  * Purpose:
   3360  *      Get cpu notifications of group.
   3361  * Parameters:
   3362  *      unit                - (IN) BCM device number
   3363  *      id                  - (IN) Flow group Id
   3364  *      notifications       - (OUT) Export trigger info.
   3365  * Returns:
   3366  *      BCM_E_XXX   - BCM error code.
   3367  */
   3368 int
   3369 bcmi_ft_group_cpu_notification_trigger_get(
   3370         int unit,
   3371         bcm_flowtracker_group_t id,
   3372         bcm_flowtracker_cpu_notification_info_t *notifications)
   3373 {
   3374 
   3375     bsc_kg_group_table_entry_t kg_entry;
   3376     uint32 val = 0;
   3377 
   3378     BCM_IF_ERROR_RETURN(bcmi_ft_group_is_invalid(unit, id));
   3379 
   3380     if (!notifications) {
   3381         return BCM_E_PARAM;
   3382     }
   3383 
   3384     /* Initialize all notifications to 0. */
   3385     sal_memset(notifications, 0,
   3386         sizeof(bcm_flowtracker_cpu_notification_info_t));
   3387 
   3388     BCM_IF_ERROR_RETURN (soc_mem_read(unit, BSC_KG_GROUP_TABLEm,
   3389         MEM_BLOCK_ANY, id, &kg_entry));
   3390 
   3391     val = soc_mem_field32_get(unit, BSC_KG_GROUP_TABLEm, &kg_entry,
   3392         FLOW_EXCEED_INTR_ENf);
   3393 
   3394     if (val) {
   3395         BCM_FLOWTRACKER_CPU_NOTIFICATION_SET(
   3396             *notifications,
   3397             bcmFlowtrackerCpuNotificationFlowExceeded);
   3398     }
   3399 
   3400     val = soc_mem_field32_get(unit, BSC_KG_GROUP_TABLEm, &kg_entry,
   3401         FT_TABLE_FULL_INTR_ENf);
   3402 
   3403     if (val) {
   3404         BCM_FLOWTRACKER_CPU_NOTIFICATION_SET(
   3405             *notifications,
   3406             bcmbcmFlowtrackerCpuNotificationTableFull);
   3407     }
   3408 
   3409     /* Notify CPU if Table is full and no new flow can be learnt. */
   3410     val = ((BCM_FLOWTRACKER_CPU_NOTIFICATION_GET(
   3411         *notifications,
   3412         bcmbcmFlowtrackerCpuNotificationTableFull)) ? 1 : 0);
   3413 
   3414     soc_mem_field32_set(unit, BSC_KG_GROUP_TABLEm, &kg_entry,
   3415         FT_TABLE_FULL_INTR_ENf, val);
   3416 
   3417     /* Write the entry back into group table. */
   3418     BCM_IF_ERROR_RETURN(soc_mem_write(unit, BSC_KG_GROUP_TABLEm, MEM_BLOCK_ALL,
   3419         id, &kg_entry));
   3420 
   3421     return BCM_E_NONE;
   3422 }
   3423 
   3424 
   3425 int
   3426 bcmi_ft_group_element_print(
   3427     int unit,
   3428     bcm_flowtracker_tracking_param_type_t element)
   3429 {
   3430 
   3431     switch(element) {
   3432     case bcmFlowtrackerTrackingParamTypeNone:
   3433         LOG_CLI((BSL_META_U(unit, "None")));
   3434         break;
   3435     case bcmFlowtrackerTrackingParamTypeSrcIPv4:
   3436         LOG_CLI((BSL_META_U(unit, "SrcIPv4")));
   3437         break;
   3438     case bcmFlowtrackerTrackingParamTypeDstIPv4 :
   3439         LOG_CLI((BSL_META_U(unit, "DstIPv4")));
   3440         break;
   3441     case bcmFlowtrackerTrackingParamTypeSrcIPv6 :
   3442         LOG_CLI((BSL_META_U(unit, "SrcIPv6")));
   3443         break;
   3444     case bcmFlowtrackerTrackingParamTypeDstIPv6 :
   3445         LOG_CLI((BSL_META_U(unit, "DstIPv6")));
   3446         break;
   3447     case bcmFlowtrackerTrackingParamTypeL4SrcPort :
   3448         LOG_CLI((BSL_META_U(unit, "L4SrcPort")));
   3449         break;
   3450     case bcmFlowtrackerTrackingParamTypeL4DstPort :
   3451         LOG_CLI((BSL_META_U(unit, "L4DstPort")));
   3452         break;
   3453     case bcmFlowtrackerTrackingParamTypeIPProtocol :
   3454         LOG_CLI((BSL_META_U(unit, "IPProto")));
   3455         break;
   3456     case bcmFlowtrackerTrackingParamTypePktCount :
   3457         LOG_CLI((BSL_META_U(unit, "PktCount")));
   3458         break;
   3459     case bcmFlowtrackerTrackingParamTypeByteCount :
   3460         LOG_CLI((BSL_META_U(unit, "ByteCount")));
   3461         break;
   3462     case bcmFlowtrackerTrackingParamTypeVRF :
   3463         LOG_CLI((BSL_META_U(unit, "VRF")));
   3464         break;
   3465     case bcmFlowtrackerTrackingParamTypeTTL :
   3466         LOG_CLI((BSL_META_U(unit, "TTL")));
   3467         break;
   3468     case bcmFlowtrackerTrackingParamTypeIPLength :
   3469         LOG_CLI((BSL_META_U(unit, "IPLength")));
   3470         break;
   3471     case bcmFlowtrackerTrackingParamTypeTcpWindowSize :
   3472         LOG_CLI((BSL_META_U
   3473             (unit, "TcpWindowSize")));
   3474         break;
   3475     case bcmFlowtrackerTrackingParamTypeDosAttack:
   3476         LOG_CLI((BSL_META_U
   3477             (unit, "DosAttack")));
   3478         break;
   3479     case bcmFlowtrackerTrackingParamTypeInnerDosAttack:
   3480         LOG_CLI((BSL_META_U
   3481             (unit, "InnerDosAttack")));
   3482         break;
   3483     case bcmFlowtrackerTrackingParamTypeVxlanNetworkId:
   3484         LOG_CLI((BSL_META_U
   3485             (unit, "VxlanNetworkId")));
   3486         break;
   3487     case bcmFlowtrackerTrackingParamTypeNextHeader:
   3488         LOG_CLI((BSL_META_U(unit, "NextHeader")));
   3489         break;
   3490     case bcmFlowtrackerTrackingParamTypeHopLimit:
   3491         LOG_CLI((BSL_META_U(unit, "HopLimit")));
   3492         break;
   3493     case bcmFlowtrackerTrackingParamTypeInnerSrcIPv4:
   3494         LOG_CLI((BSL_META_U
   3495             (unit, "InnerSrcIPv4")));
   3496         break;
   3497     case bcmFlowtrackerTrackingParamTypeInnerDstIPv4:
   3498         LOG_CLI((BSL_META_U
   3499             (unit, " InnerDstIPv4")));
   3500         break;
   3501     case bcmFlowtrackerTrackingParamTypeInnerSrcIPv6:
   3502         LOG_CLI((BSL_META_U
   3503             (unit, " InnerSrcIPv6")));
   3504         break;
   3505     case bcmFlowtrackerTrackingParamTypeInnerDstIPv6:
   3506         LOG_CLI((BSL_META_U
   3507             (unit, " InnerDstIPv6")));
   3508         break;
   3509     case bcmFlowtrackerTrackingParamTypeInnerIPProtocol:
   3510         LOG_CLI((BSL_META_U
   3511             (unit, " InnerIPProtocol")));
   3512         break;
   3513     case bcmFlowtrackerTrackingParamTypeInnerTTL:
   3514         LOG_CLI((BSL_META_U(unit, " InnerTTL")));
   3515         break;
   3516     case bcmFlowtrackerTrackingParamTypeInnerNextHeader:
   3517         LOG_CLI((BSL_META_U
   3518             (unit, " InnerNextHeader")));
   3519         break;
   3520     case bcmFlowtrackerTrackingParamTypeInnerHopLimit:
   3521         LOG_CLI((BSL_META_U
   3522             (unit, " InnerHopLimit")));
   3523         break;
   3524     case bcmFlowtrackerTrackingParamTypeInnerL4SrcPort:
   3525         LOG_CLI((BSL_META_U
   3526             (unit, " InnerL4SrcPort")));
   3527         break;
   3528     case bcmFlowtrackerTrackingParamTypeInnerL4DstPort:
   3529         LOG_CLI((BSL_META_U
   3530             (unit, " InnerL4DstPort")));
   3531         break;
   3532     case bcmFlowtrackerTrackingParamTypeTcpFlags:
   3533         LOG_CLI((BSL_META_U(unit, " TcpFlags")));
   3534         break;
   3535     case bcmFlowtrackerTrackingParamTypeOuterVlanTag:
   3536         LOG_CLI((BSL_META_U
   3537             (unit, " OuterVlanTag")));
   3538         break;
   3539     case bcmFlowtrackerTrackingParamTypeIP6Length:
   3540         LOG_CLI((BSL_META_U(unit, " IP6Length")));
   3541         break;
   3542     case bcmFlowtrackerTrackingParamTypeInnerIPLength:
   3543         LOG_CLI((BSL_META_U
   3544             (unit, " InnerIPLength")));
   3545         break;
   3546     case bcmFlowtrackerTrackingParamTypeInnerIP6Length:
   3547         LOG_CLI((BSL_META_U
   3548             (unit, " InnerIP6Length")));
   3549         break;
   3550     case bcmFlowtrackerTrackingParamTypeTunnelClass:
   3551         LOG_CLI((BSL_META_U
   3552             (unit, "TunnelClass")));
   3553         break;
   3554     default:
   3555         return BCM_E_PARAM;
   3556     }
   3557 
   3558     return BCM_E_NONE;
   3559 }
   3560 
   3561 /*
   3562  * Function:
   3563  *      bcmi_ft_tracking_param_is_timestamp
   3564  * Purpose:
   3565  *      Get cpu notifications of group.
   3566  * Parameters:
   3567  *      unit                - (IN) BCM device number
   3568  *      t_param             - (IN) tracking parameter
   3569  * Returns:
   3570  *      TRUE/FALSE.
   3571  */
   3572 int
   3573 bcmi_ft_tracking_param_is_timestamp(
   3574         int unit,
   3575         bcm_flowtracker_tracking_param_type_t t_param)
   3576 {
   3577 
   3578     switch (t_param) {
   3579         case bcmFlowtrackerTrackingParamTypeTimestampNewLearn:
   3580         case bcmFlowtrackerTrackingParamTypeTimestampFlowStart:
   3581         case bcmFlowtrackerTrackingParamTypeTimestampFlowEnd:
   3582         case bcmFlowtrackerTrackingParamTypeTimestampCheckEvent1:
   3583         case bcmFlowtrackerTrackingParamTypeTimestampCheckEvent2:
   3584             return TRUE;
   3585         default :
   3586             return FALSE;
   3587     }
   3588 
   3589     return FALSE;
   3590 }
   3591 
   3592 /*
   3593  * Function:
   3594  *      bcmi_ft_group_check_ts_set
   3595  * Purpose:
   3596  *      Get cpu notifications of group.
   3597  * Parameters:
   3598  *      unit                - (IN) BCM device number
   3599  *      id                  - (IN) FLOW group id
   3600  *      flowchecker_id      - (IN) check id.
   3601  * Returns:
   3602  *      BCM_E_XXX.
   3603  */
   3604 int
   3605 bcmi_ft_group_check_ts_set(
   3606         int unit,
   3607         bcm_flowtracker_group_t id,
   3608         bcm_flowtracker_check_t flowchecker_id,
   3609         bcmi_flowtracker_check_set_t reset)
   3610 {
   3611 
   3612     bcmi_flowtracker_flowchecker_info_t fc_info;
   3613     sal_memset(&fc_info, 0, sizeof(bcmi_flowtracker_flowchecker_info_t));
   3614 
   3615     BCM_IF_ERROR_RETURN(bcmi_ft_flowchecker_get
   3616         (unit, flowchecker_id, &fc_info));
   3617 
   3618     BCM_IF_ERROR_RETURN(bcmi_ft_group_ts_triggers_set(unit, id, fc_info.flags,
   3619         BCMI_FT_TS_TYPE_FC, reset));
   3620 
   3621     return BCM_E_NONE;
   3622 }
   3623 
   3624 
   3625 /*
   3626  * Function:
   3627  *      bcmi_ft_group_ts_triggers_set
   3628  * Purpose:
   3629  *      Get cpu notifications of group.
   3630  * Parameters:
   3631  *      unit                - (IN) BCM device number
   3632  *      id                  - (IN) FLOW group id
   3633  *      check_flags         - (IN) flags from flow check
   3634  *      trigger_type        - (IN) tracking param/flow check trigger type.
   3635  * Returns:
   3636  *      BCM_E_XXX.
   3637  */
   3638 int
   3639 bcmi_ft_group_ts_triggers_set(
   3640         int unit,
   3641         bcm_flowtracker_group_t id,
   3642         uint32 check_flags,
   3643         int trigger_type,
   3644         bcmi_flowtracker_check_set_t reset)
   3645 {
   3646     int num_elements = 0;
   3647     bcm_flowtracker_tracking_param_info_t *t_info = NULL;
   3648     int ts_count = 0;
   3649     int i = 0, j = 0;
   3650     uint32 ts_triggers = 0;
   3651 
   3652     num_elements = BCMI_FT_GROUP_TRACK_PARAM_NUM(unit, id);
   3653     t_info = BCMI_FT_GROUP_TRACK_PARAM(unit, id);
   3654     ts_triggers = BCMI_FT_GROUP_TS_TRIGGERS(unit, id);
   3655 
   3656     if (trigger_type == BCMI_FT_TS_TYPE_TP) {
   3657 
   3658         /* Cleanup any old triggers for this type. */
   3659         ts_triggers &=
   3660             ~(BCMI_FT_GROUP_TS_NEW_LEARN | BCMI_FT_GROUP_TS_FLOW_START |
   3661               BCMI_FT_GROUP_TS_FLOW_END);
   3662 
   3663         /* Set triggers based on the tracking params.*/
   3664         for (i = 0; i < num_elements; i++) {
   3665             if (bcmi_ft_tracking_param_is_timestamp(unit, t_info->param)) {
   3666                 for (j = 0; j < BCMI_FT_GROUP_MAX_TS_TYPE; j++) {
   3667                     if (t_info->param != bcmi_ft_group_ts_info[j].ts_param) {
   3668                         continue;
   3669                     }
   3670 
   3671                     ts_triggers |= bcmi_ft_group_ts_info[j].flag_id;
   3672                 }
   3673             }
   3674             t_info++;
   3675         }
   3676     } else {
   3677         /* ALU triggers can also be set from ALU methods. */
   3678         if (check_flags & BCM_FLOWTRACKER_CHECK_TIMESTAMP_CHECK_EVENT1) {
   3679             if (reset == bcmFlowtrackerFlowCheckTsSet) {
   3680                 ts_triggers |= BCMI_FT_GROUP_TS_CHECK_EVENT1;
   3681             } else {
   3682                 ts_triggers &= ~(BCMI_FT_GROUP_TS_CHECK_EVENT1);
   3683             }
   3684         }
   3685 
   3686         if (check_flags & BCM_FLOWTRACKER_CHECK_TIMESTAMP_CHECK_EVENT2) {
   3687             if (reset == bcmFlowtrackerFlowCheckTsSet) {
   3688                 ts_triggers |= BCMI_FT_GROUP_TS_CHECK_EVENT2;
   3689             } else {
   3690                 ts_triggers &= ~(BCMI_FT_GROUP_TS_CHECK_EVENT2);
   3691             }
   3692         }
   3693     }
   3694 
   3695     ts_count = 0;
   3696     for (i = 0; i < BCMI_FT_GROUP_MAX_TS_TYPE; i++) {
   3697         if ((ts_triggers) & (1 << i)) {
   3698             ts_count++;
   3699         }
   3700     }
   3701 
   3702     if (ts_count > BCMI_FT_GROUP_MAX_TS) {
   3703         return BCM_E_CONFIG;
   3704     }
   3705 
   3706     BCMI_FT_GROUP_TS_TRIGGERS(unit, id) = ts_triggers;
   3707 
   3708     return BCM_E_NONE;
   3709 
   3710 }
   3711 
   3712 /*
   3713  * Function:
   3714  *      bcmi_ft_group_get_param_type
   3715  * Purpose:
   3716  *      Get tracking parameter type from tracking parameters.
   3717  * Parameters:
   3718  *      unit                - (IN) BCM device number
   3719  *      param               - (IN) tracking parameter
   3720  * Returns:
   3721  *      bcmi_ft_group_param_type_t.
   3722  */
   3723 bcmi_ft_group_param_type_t
   3724 bcmi_ft_group_get_param_type(
   3725         int unit,
   3726         bcm_flowtracker_tracking_param_type_t t_param)
   3727 {
   3728 
   3729     bcmi_ft_group_param_type_t param_type;
   3730 
   3731     param_type = bcmiFtGroupParamTypeTracking;
   3732 
   3733     switch (t_param) {
   3734         case bcmFlowtrackerTrackingParamTypeTimestampNewLearn:
   3735             param_type = bcmiFtGroupParamTypeTsNewLearn;
   3736             break;
   3737         case bcmFlowtrackerTrackingParamTypeTimestampFlowStart:
   3738             param_type = bcmiFtGroupParamTypeTsFlowStart;
   3739             break;
   3740         case bcmFlowtrackerTrackingParamTypeTimestampFlowEnd:
   3741             param_type = bcmiFtGroupParamTypeTsFlowEnd;
   3742             break;
   3743         case bcmFlowtrackerTrackingParamTypeTimestampCheckEvent1:
   3744             param_type = bcmiFtGroupParamTypeTsCheckEvent1;
   3745             break;
   3746         case bcmFlowtrackerTrackingParamTypeTimestampCheckEvent2:
   3747             param_type = bcmiFtGroupParamTypeTsCheckEvent2;
   3748             break;
   3749         default :
   3750             param_type = bcmiFtGroupParamTypeTracking;
   3751     }
   3752 
   3753     return param_type;
   3754 }
   3755 
   3756 
   3757 /*
   3758  * Function:
   3759  *      bcmi_ft_group_get_tracking_param
   3760  * Purpose:
   3761  *      Get tracking parameter from tracking parameters type
   3762  * Parameters:
   3763  *      unit                - (IN) BCM device number
   3764  *      param               - (IN) tracking parameter
   3765  * Returns:
   3766  *      bcm_flowtracker_tracking_param_type_t.
   3767  */
   3768 bcm_flowtracker_tracking_param_type_t
   3769 bcmi_ft_group_get_tracking_param(
   3770         int unit,
   3771         bcmi_ft_group_param_type_t pram_type)
   3772 {
   3773 
   3774     bcm_flowtracker_tracking_param_type_t param;
   3775 
   3776     param = bcmFlowtrackerTrackingParamTypeNone;
   3777 
   3778     switch (pram_type) {
   3779         case bcmiFtGroupParamTypeTsNewLearn:
   3780             param = bcmFlowtrackerTrackingParamTypeTimestampNewLearn;
   3781             break;
   3782         case bcmiFtGroupParamTypeTsFlowStart:
   3783             param = bcmFlowtrackerTrackingParamTypeTimestampFlowStart;
   3784             break;
   3785         case bcmiFtGroupParamTypeTsFlowEnd:
   3786             param = bcmFlowtrackerTrackingParamTypeTimestampFlowEnd;
   3787             break;
   3788         case bcmiFtGroupParamTypeTsCheckEvent1:
   3789             param = bcmFlowtrackerTrackingParamTypeTimestampCheckEvent1;
   3790             break;
   3791         case bcmiFtGroupParamTypeTsCheckEvent2:
   3792             param = bcmFlowtrackerTrackingParamTypeTimestampCheckEvent2;
   3793             break;
   3794         default :
   3795             param = bcmFlowtrackerTrackingParamTypeNone;
   3796     }
   3797 
   3798     return param;
   3799 }
   3800 
   3801 /*
   3802  * Function:
   3803  *      bcmi_ft_group_get_ts_type
   3804  * Purpose:
   3805  *      Get tracking parameter type matching a field.
   3806  * Parameters:
   3807  *      unit                - (IN) BCM device number
   3808  *      id                  - (IN) flow Group id.
   3809  *      fid                 - (IN) ts data field.
   3810  * Returns:
   3811  *      bcmi_ft_group_param_type_t
   3812  */
   3813 bcmi_ft_group_param_type_t
   3814 bcmi_ft_group_get_ts_type(
   3815         int unit,
   3816         bcm_flowtracker_group_t id,
   3817         soc_field_t fid)
   3818 {
   3819     bsc_dg_group_timestamp_profile_entry_t entry;
   3820     bsc_dg_group_table_entry_t dg_entry;
   3821     uint32 index=0;
   3822     uint32 fmt[1];
   3823     int i=0;
   3824     uint32 bit_sel = 0;
   3825 /*
   3826     soc_field_t ts_data_fields[4] =
   3827                     {DATA_0f, DATA_1f, DATA_2f, DATA_3f};
   3828 */
   3829 
   3830     /* Initialize the timestamp profile entry. */
   3831     sal_memset(&entry, 0,
   3832         sizeof(bsc_dg_group_timestamp_profile_entry_t));
   3833     /* Initialize group entry. */
   3834     sal_memset(&dg_entry, 0, sizeof(bsc_dg_group_table_entry_t));
   3835 
   3836     /* First read the group entry. */
   3837     BCM_IF_ERROR_RETURN (soc_mem_read(unit, BSC_DG_GROUP_TABLEm,
   3838             MEM_BLOCK_ANY, id, &dg_entry));
   3839 
   3840     /* now write this new index into the group. */
   3841     index = soc_mem_field32_get(unit, BSC_DG_GROUP_TABLEm,
   3842         ((uint32 *)&dg_entry), TIMESTAMP_PROFILE_IDXf);
   3843 
   3844     /* First read the group entry. */
   3845     BCM_IF_ERROR_RETURN (soc_mem_read(unit, BSC_DG_GROUP_TIMESTAMP_PROFILEm,
   3846             MEM_BLOCK_ANY, index, &entry));
   3847 
   3848 
   3849     /* Set the entry. */
   3850     soc_mem_field_get(unit, BSC_DG_GROUP_TIMESTAMP_PROFILEm,
   3851         (uint32 *)(&entry), fid, fmt);
   3852 
   3853     bit_sel = soc_format_field32_get(unit, BSC_KMAP_CONTROLfmt, fmt,
   3854                   KMAP_INPUT_SELECT_0f);
   3855 
   3856     for (; i<BCMI_FT_GROUP_MAX_TS_TYPE; i++) {
   3857         if (bit_sel == bcmi_ft_group_ts_info[i].ts_trigger_bit_sel) {
   3858             return bcmi_ft_group_get_param_type(unit,
   3859                  bcmi_ft_group_ts_info[i].ts_param);
   3860          }
   3861     }
   3862 
   3863     return bcmiFtGroupParamTypeTracking;
   3864 
   3865 }
   3866 
   3867 /*
   3868  * Function:
   3869  *      bcmi_ft_group_entry_add_check
   3870  * Purpose:
   3871  *      Check if Flowtracker Group is ready to be added to ftfp entry.
   3872  * Parameters:
   3873  *      unit - (IN) Unit number.
   3874  *      id - (IN) Flowtracker flow group ID.
   3875  * Returns:
   3876  *      BCM_E_xxx
   3877  * Notes:
   3878  */
   3879 int
   3880 bcmi_ft_group_entry_add_check(
   3881     int unit,
   3882     bcm_flowtracker_group_t id)
   3883 {
   3884     int rv;
   3885     int ft_enable;
   3886     int num_key_info = 0;
   3887     uint32 flow_limit;
   3888 
   3889     /* Check if FT Group created */
   3890     rv = bcmi_ft_group_is_invalid(unit, id);
   3891     if (BCM_FAILURE(rv)) {
   3892         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, "FP(unit %d)"
   3893                         " Error: Flowtracker Group %d is not"
   3894                         " created.\n"), unit, id));
   3895         return rv;
   3896     }
   3897 
   3898     /* Check if FT Group template params extracted */
   3899     rv = bcmi_esw_ft_group_extraction_alu_info_get(unit,
   3900             id, 1, 0, NULL, &num_key_info);
   3901     if ((rv != BCM_E_NONE) || (num_key_info == 0)) {
   3902         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, "FP(unit %d)"
   3903                         "Error: Flowtracker Group %d is not"
   3904                         " validated.\n"), unit, id));
   3905         return BCM_E_CONFIG;
   3906     }
   3907 
   3908     /* If Flowtracking is disabled or flow_limit is 0, pass */
   3909     ft_enable = BCMI_FT_GROUP_FTFP_DATA(unit, id).flowtrack;
   3910     rv = bcmi_ft_group_flow_limit_get(unit, id, &flow_limit);
   3911     if (rv != BCM_E_NONE) {
   3912         flow_limit = 0;
   3913     }
   3914     if ((ft_enable == FALSE) || (flow_limit == 0)) {
   3915         return BCM_E_NONE;
   3916     }
   3917 
   3918     /* Check if collector is attached */
   3919     rv = bcmi_ft_group_collector_is_valid(unit, id);
   3920     if (rv != BCM_E_NONE) {
   3921         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3922                         "FP(unit %d) Error: Collector is not "
   3923                         "associated with FlowtrackerGroup %d\r\n"),
   3924                     unit, id));
   3925     }
   3926 
   3927     return rv;
   3928 }
   3929 
   3930 /*
   3931  * Function:
   3932  *      bcmi_ft_group_is_check_valid
   3933  * Purpose:
   3934  *      Check if FlowCheck is associated with ft group.
   3935  * Parameters:
   3936  *      unit - (IN) Unit number.
   3937  *      id - (IN) Flowtracker flow group ID.
   3938  *      check_id - (IN) Check Id to verify
   3939  * Returns:
   3940  *      BCM_E_xxx
   3941  * Notes:
   3942  */
   3943 int bcmi_ft_group_is_check_valid(
   3944     int unit,
   3945     bcm_flowtracker_group_t id,
   3946     bcm_flowtracker_check_t check_id)
   3947 {
   3948     bcmi_ft_flowchecker_list_t *check_list = NULL;
   3949 
   3950     check_list = BCMI_FT_GROUP_FLOWCHECKER_HEAD(unit, id);
   3951     if (check_list == NULL) {
   3952         return BCM_E_PARAM;
   3953     }
   3954 
   3955     while (check_list != NULL) {
   3956         if (check_list->flowchecker_id == check_id) {
   3957             return BCM_E_NONE;
   3958         }
   3959         check_list = check_list->next;
   3960     }
   3961 
   3962     return BCM_E_PARAM;
   3963 }
   3964 
   3965 /*
   3966  * Function:
   3967  *      bcmi_ft_group_export_checks_validate
   3968  * Purpose:
   3969  *      Verify flowchecks in in export list.
   3970  * Parameters:
   3971  *      unit - (IN) Unit number.
   3972  *      id - (IN) Flowtracker flow group ID.
   3973  *      num_in_export_elements - Number of export elements.
   3974  *      in_export_elements - (IN) List of export elements.
   3975  * Returns:
   3976  *      BCM_E_xxx
   3977  * Notes:
   3978  */
   3979 int
   3980 bcmi_ft_group_export_checks_validate(
   3981     int unit,
   3982     bcm_flowtracker_group_t id,
   3983     int num_in_export_elements,
   3984     bcm_flowtracker_export_element_info_t *in_export_elements)
   3985 {
   3986     int rv = BCM_E_NONE;
   3987     int iter = 0, iter1 = 0;
   3988     int options = 0;
   3989     int num_trackin_params = 0;
   3990     bcm_flowtracker_check_t check_id;
   3991     bcm_flowtracker_export_element_info_t *export_elem_info = NULL;
   3992     bcm_flowtracker_tracking_param_info_t *tracking_param_list = NULL;
   3993 
   3994     tracking_param_list = BCMI_FT_GROUP_TRACK_PARAM(unit, id);
   3995     num_trackin_params = BCMI_FT_GROUP_TRACK_PARAM_NUM(unit, id);
   3996     options = BCMI_FT_GROUP_CHECK_MATCH_PRIMARY |
   3997               BCMI_FT_GROUP_CHECK_MATCH_GROUP;
   3998 
   3999     for (iter = 0; iter < num_in_export_elements; iter++) {
   4000         export_elem_info = &in_export_elements[iter];
   4001 
   4002         /* Skip if export element is not flowcheck. */
   4003         if (export_elem_info->element !=
   4004                 bcmFlowtrackerExportElementTypeFlowtrackerCheck) {
   4005             continue;
   4006         }
   4007 
   4008         check_id = export_elem_info->check_id;
   4009 
   4010         /* Validate if Check_id is allowed for the given list */
   4011         rv = bcmi_ft_group_check_validate(unit, options, id, check_id);
   4012         BCM_IF_ERROR_RETURN(rv);
   4013 
   4014         /* Make sure that tracking param list also has check_id */
   4015         if (BCMI_FT_IDX_IS_PRIMARY_CHECK(check_id)) {
   4016             for (iter1 = 0; iter1 < num_trackin_params; iter1++) {
   4017                 if ((tracking_param_list[iter1].param ==
   4018                             bcmFlowtrackerTrackingParamTypeFlowtrackerCheck) &&
   4019                         (check_id == tracking_param_list[iter1].check_id)) {
   4020                     break;
   4021                 }
   4022             }
   4023             if (iter1 == num_trackin_params) {
   4024                 LOG_ERROR(BSL_LS_BCM_FLOWTRACKER, (BSL_META_U(unit,
   4025                                 "Given Flow Check(0x%x) is missing from"
   4026                                 " tracking params input list of Group(%d)\n"),
   4027                             check_id, id));
   4028                 return BCM_E_PARAM;
   4029             }
   4030         }
   4031     }
   4032 
   4033     return BCM_E_NONE;
   4034 }
   4035 
   4036 /*
   4037  * Function:
   4038  *      bcmi_ft_group_norm_tracking_params_list_get
   4039  * Purpose:
   4040  *      Get the list of tracking_param info eligible for
   4041  *      normalization in the given flowtracker group.
   4042  * Parameters:
   4043  *      unit - (IN) Unit number.
   4044  *      id - (IN) Flowtracker flow group ID.
   4045  *      norm_tracking_params_info - (OUT) list of norm tracking params.
   4046  * Returns:
   4047  *      BCM_E_xxx
   4048  * Notes:
   4049  *      The returned 'norm_tracking_params_info' is ordered based on
   4050  *      priority of normalization and if some params are not present
   4051  *      in the given FT Group, it is set to NULL.
   4052  */
   4053 int
   4054 bcmi_ft_group_norm_tracking_params_info_get(
   4055     int unit,
   4056     bcm_flowtracker_group_t id,
   4057     bcm_flowtracker_tracking_param_info_t **norm_tracking_params_info)
   4058 {
   4059     int i = 0, j = 0;
   4060     int num_tracking_params = 0;
   4061     bcm_flowtracker_tracking_param_info_t *tracking_params_info = NULL;
   4062 
   4063     /* Tracking params pairs for normalization ordered in the priority
   4064      * param used as base of normalization. */
   4065     bcm_flowtracker_tracking_param_type_t
   4066         norm_tracking_pairs[BCMI_FT_GROUP_NORM_TRACKING_PARAMS] = {
   4067             bcmFlowtrackerTrackingParamTypeSrcIPv4,
   4068             bcmFlowtrackerTrackingParamTypeDstIPv4,
   4069             bcmFlowtrackerTrackingParamTypeSrcIPv6,
   4070             bcmFlowtrackerTrackingParamTypeDstIPv6,
   4071             bcmFlowtrackerTrackingParamTypeInnerSrcIPv4,
   4072             bcmFlowtrackerTrackingParamTypeInnerDstIPv4,
   4073             bcmFlowtrackerTrackingParamTypeInnerSrcIPv6,
   4074             bcmFlowtrackerTrackingParamTypeInnerDstIPv6,
   4075             bcmFlowtrackerTrackingParamTypeL4SrcPort,
   4076             bcmFlowtrackerTrackingParamTypeL4DstPort,
   4077             bcmFlowtrackerTrackingParamTypeInnerL4SrcPort,
   4078             bcmFlowtrackerTrackingParamTypeInnerL4DstPort
   4079         };
   4080 
   4081     tracking_params_info = BCMI_FT_GROUP_TRACK_PARAM(unit, id);
   4082     num_tracking_params = BCMI_FT_GROUP_TRACK_PARAM_NUM(unit, id);
   4083 
   4084     for (i = 0; i < COUNTOF(norm_tracking_pairs); i++) {
   4085         for (j = 0; j < num_tracking_params; j++) {
   4086             if (tracking_params_info[j].flags &
   4087                     BCM_FLOWTRACKER_TRACKING_PARAM_TYPE_KEY) {
   4088                 if (tracking_params_info[j].param == norm_tracking_pairs[i]) {
   4089                     norm_tracking_params_info[i] = &tracking_params_info[j];
   4090                     break;
   4091                 }
   4092             }
   4093         }
   4094     }
   4095 
   4096     return BCM_E_NONE;
   4097 }
   4098 
   4099 #else /* BCM_FLOWTRCAKER_SUPPORT*/
   4100 int bcmi_ft_group_not_empty;
   4101 #endif /* BCM_FLOWTRCAKER_SUPPORT */
   4102