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_user.c (49362B)


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