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

field.c (134592B)


      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:        field.c
      8  * Purpose:     Field Processor routines Specific to Helix5.
      9  */
     10 
     11 #include <soc/defs.h>
     12 
     13 #if defined (BCM_HELIX5_SUPPORT) && defined(BCM_FIELD_SUPPORT)
     14 
     15 #include <bcm/error.h>
     16 #include <bcm/field.h>
     17 #include <shared/bsl.h>
     18 
     19 #include <bcm_int/esw/field.h>
     20 #include <bcm_int/esw/tomahawk.h>
     21 #include <bcm_int/esw/helix5.h>
     22 #include <bcm_int/esw/keygen_api.h>
     23 #include <bcm_int/esw/flowtracker/ft_group.h>
     24 
     25 /*
     26  * Typedef :
     27  *   _field_ft_group_qual_part_info_t
     28  * Purpose:
     29  *   Temporary structure used to convert keygen qualifiers and
     30  *   offsets information to field group qual_arr member field.
     31  */
     32 typedef struct _field_ft_group_qual_part_info_s {
     33     int count;
     34     bcm_field_qset_t qset;
     35 } _field_ft_group_qual_part_info_t;
     36 
     37 /*
     38  * Function:
     39  *    _field_hx5_ft_stage_extractors_init
     40  *
     41  * Purpose:
     42  *    Initializes flowtracker stage extractors information.
     43  *
     44  * Parameters:
     45  *    unit       - (IN) BCM device number.
     46  *    stage_fc   - (IN) Field stage control structure.
     47  *
     48  * Returns:
     49  *    BCM_E_PARAM       - Null field stage control structure.
     50  *    BCM_E_INTERNAL    - Invalid CAP Stage ID.
     51  *    BCM_E_NONE        - Success.
     52  */
     53 STATIC int
     54 _field_hx5_ft_stage_extractors_init(int unit,
     55                                     _field_stage_t *stage_fc)
     56 {
     57     int rv = BCM_E_NONE;
     58     int mode = 0;
     59     bcmi_keygen_ext_cfg_db_t **ext_cfg_db_arr = NULL;
     60 
     61     /* Validate input params */
     62     if (stage_fc ==  NULL) {
     63         return BCM_E_PARAM;
     64     }
     65 
     66     if (stage_fc->ext_cfg_db_arr != NULL) {
     67         return BCM_E_NONE;
     68     }
     69 
     70     _FP_XGS3_ALLOC(ext_cfg_db_arr,
     71                    sizeof(bcmi_keygen_ext_cfg_db_t *) * BCMI_KEYGEN_MODE_COUNT,
     72                    " ft stage ext cfg db");
     73 
     74     if (ext_cfg_db_arr == NULL) {
     75         return BCM_E_MEMORY;
     76     }
     77 
     78     for (mode = BCMI_KEYGEN_MODE_SINGLE;
     79          mode < BCMI_KEYGEN_MODE_COUNT; mode++) {
     80         switch(mode) {
     81             case BCMI_KEYGEN_MODE_SINGLE:
     82             case BCMI_KEYGEN_MODE_DBLINTRA:
     83                 _FP_XGS3_ALLOC(ext_cfg_db_arr[mode],
     84                                     sizeof(bcmi_keygen_ext_cfg_db_t),
     85                                     " ft ext db");
     86                 if (ext_cfg_db_arr[mode] == NULL) {
     87                     rv = BCM_E_MEMORY;
     88                 }
     89                 if (BCM_SUCCESS(rv)) {
     90                     rv = _field_ft_keygen_profile_aab_extractors_db_create(unit,
     91                             ext_cfg_db_arr[mode], mode);
     92                 }
     93                 break;
     94             default:
     95                 continue;
     96         }
     97         if (BCM_FAILURE(rv)) {
     98             break;
     99         }
    100     }
    101 
    102     if (BCM_FAILURE(rv)) {
    103         if (ext_cfg_db_arr != NULL) {
    104             for (mode = BCMI_KEYGEN_MODE_SINGLE;
    105                  mode < BCMI_KEYGEN_MODE_COUNT; mode++) {
    106                 if (ext_cfg_db_arr[mode] != NULL) {
    107                     (void) bcmi_keygen_ext_cfg_db_free(unit,
    108                                                 ext_cfg_db_arr[mode]);
    109                     ext_cfg_db_arr[mode] = NULL;
    110                 }
    111             }
    112             sal_free(ext_cfg_db_arr);
    113         }
    114     } else {
    115         stage_fc->ext_cfg_db_arr = ext_cfg_db_arr;
    116     }
    117 
    118     return BCM_E_NONE;
    119 }
    120 
    121 /*
    122  * Function:
    123  *    _field_hx5_ft_session_keygen_profiles_init
    124  *
    125  * Purpose:
    126  *    Initializes flowtracker stage session keygen profiles.
    127  *
    128  * Parameters:
    129  *    unit       - (IN) BCM device number.
    130  *    stage_fc   - (IN) Field stage control structure.
    131  *
    132  * Returns:
    133  *    BCM_E_PARAM       - Null field stage control structure.
    134  *    BCM_E_INTERNAL    - Invalid CAP Stage ID.
    135  *    BCM_E_NONE        - Success.
    136  */
    137 STATIC int
    138 _field_hx5_ft_session_keygen_profiles_init(int unit,
    139                                            _field_stage_t *stage_fc)
    140 {
    141     int rv = BCM_E_NONE;
    142     soc_mem_t mem[5] = {INVALIDm};
    143     int entry_words[5] = {0};
    144     int min_idx[5] = {0};
    145     int max_idx[5] = {0};
    146     int idx_min, idx_max;
    147     int user_entry_profiles;
    148     _field_ft_info_t *ft_info = NULL;
    149 
    150     /* Valid only for Flowtracker */
    151     if (stage_fc->stage_id != _BCM_FIELD_STAGE_FLOWTRACKER) {
    152         return rv;
    153     }
    154 
    155     ft_info = stage_fc->ft_info;
    156 
    157     user_entry_profiles = soc_property_get(unit,
    158                               spn_FLOWTRACKER_NUM_UNIQUE_USER_ENTRY_KEYS, 0);
    159     if ((user_entry_profiles < 0) || (user_entry_profiles > 128)) {
    160         user_entry_profiles = 128;
    161     }
    162 
    163     /* Session Key keygen profile */
    164     soc_profile_mem_t_init(&(ft_info->session_key_profile));
    165 
    166     mem[0] = BSK_SESSION_KEY_LTS_MUX_CTRL_0m;
    167     entry_words[0] = BYTES2WORDS(sizeof(bsk_session_key_lts_mux_ctrl_0_entry_t));
    168     mem[1] = BSK_SESSION_KEY_LTS_MASK_0m;
    169     entry_words[1] = BYTES2WORDS(sizeof(bsk_session_key_lts_mask_0_entry_t));
    170     mem[2] = BSK_SESSION_KEY_LTS_MUX_CTRL_1m;
    171     entry_words[2] = BYTES2WORDS(sizeof(bsk_session_key_lts_mux_ctrl_1_entry_t));
    172     mem[3] = BSK_SESSION_KEY_LTS_MASK_1m;
    173     entry_words[3] = BYTES2WORDS(sizeof(bsk_session_key_lts_mask_1_entry_t));
    174     mem[4] = BSK_SESSION_KEY_LTS_MUX_CTRL_2_PLUS_MASKm;
    175     entry_words[4] = BYTES2WORDS(sizeof(bsk_session_key_lts_mux_ctrl_2_plus_mask_entry_t));
    176 
    177     idx_min = soc_mem_index_min(unit, mem[0]);
    178     idx_max = (soc_mem_index_max(unit, mem[0]) - user_entry_profiles);
    179 
    180     min_idx[0] = min_idx[1] = min_idx[2] = min_idx[3] = min_idx[4] = idx_min;
    181     max_idx[0] = max_idx[1] = max_idx[2] = max_idx[3] = max_idx[4] = idx_max;
    182 
    183     if (idx_min <= idx_max) {
    184         rv = soc_profile_mem_index_create(unit, mem,
    185                 entry_words, min_idx, max_idx,
    186                 NULL, 5, &(ft_info->session_key_profile));
    187         if (BCM_FAILURE(rv)) {
    188             LOG_ERROR(BSL_LS_BCM_FP,
    189                     (BSL_META_U(unit,
    190                                 "Flowtracker FP Error: Session key"
    191                                 " Keygen profile - Failed.\n")));
    192             return (rv);
    193         }
    194     }
    195 
    196     /* Session Key keygen profile for user installed flows. */
    197     if (user_entry_profiles > 0) {
    198         soc_profile_mem_t_init(&(ft_info->session_key_user_profile));
    199 
    200         idx_min = (soc_mem_index_max(unit, mem[0]) - user_entry_profiles + 1);
    201         idx_max = (soc_mem_index_max(unit, mem[0]));
    202 
    203         min_idx[0] = min_idx[1] = min_idx[2] = min_idx[3] = min_idx[4] = idx_min;
    204         max_idx[0] = max_idx[1] = max_idx[2] = max_idx[3] = max_idx[4] = idx_max;
    205 
    206         if (idx_min <= idx_max) {
    207             rv = soc_profile_mem_index_create(unit, mem,
    208                     entry_words, min_idx, max_idx,
    209                     NULL, 5, &(ft_info->session_key_user_profile));
    210             if (BCM_FAILURE(rv)) {
    211                 LOG_ERROR(BSL_LS_BCM_FP,
    212                         (BSL_META_U(unit,
    213                                     "Flowtracker FP Error: Session key Keygen"
    214                                     " profile for user flows - Failed.\n")));
    215                 return (rv);
    216             }
    217         }
    218     }
    219 
    220 
    221     /* Session Data keygen profile */
    222     soc_profile_mem_t_init(&(ft_info->session_data_profile));
    223     mem[0] = BSK_SESSION_DATA_LTS_MUX_CTRL_0m;
    224     entry_words[0] = BYTES2WORDS(sizeof(bsk_session_data_lts_mux_ctrl_0_entry_t));
    225     mem[1] = BSK_SESSION_DATA_LTS_MASK_0m;
    226     entry_words[1] = BYTES2WORDS(sizeof(bsk_session_data_lts_mask_0_entry_t));
    227     mem[2] = BSK_SESSION_DATA_LTS_MUX_CTRL_1_PLUS_MASKm;
    228     entry_words[2] = BYTES2WORDS(sizeof(bsk_session_data_lts_mux_ctrl_1_plus_mask_entry_t));
    229 
    230     rv = soc_profile_mem_create(unit, mem,
    231                 entry_words, 3, &(ft_info->session_data_profile));
    232     if (BCM_FAILURE(rv)) {
    233         soc_profile_mem_destroy(unit, &(ft_info->session_key_profile));
    234         LOG_ERROR(BSL_LS_BCM_FP,
    235                   (BSL_META_U(unit,
    236                               "Flowtracker FP Error: Session Data"
    237                               " Keygen profile - Failed.\n")));
    238         return (rv);
    239     }
    240 
    241     /* Alu data keygen profile */
    242     soc_profile_mem_t_init(&(ft_info->alu_data_profile));
    243     mem[0] = BSK_ALU_DATA_LTS_MUX_CTRL_PLUS_MASKm;
    244     entry_words[0] = BYTES2WORDS(sizeof(bsk_alu_data_lts_mux_ctrl_plus_mask_entry_t));
    245 
    246     rv = soc_profile_mem_create(unit, mem,
    247                 entry_words, 1, &(ft_info->alu_data_profile));
    248     if (BCM_FAILURE(rv)) {
    249         soc_profile_mem_destroy(unit, &(ft_info->session_data_profile));
    250         soc_profile_mem_destroy(unit, &(ft_info->session_key_profile));
    251         LOG_ERROR(BSL_LS_BCM_FP,
    252                   (BSL_META_U(unit,
    253                               "Flowtracker FP Error: Alu Data "
    254                               "Keygen profile - Failed.\n")));
    255         return (rv);
    256     }
    257 
    258     return rv;
    259 }
    260 
    261 /*
    262  * Function:
    263  *    _field_hx5_ft_stage_ftinfo_init
    264  *
    265  * Purpose:
    266  *    Initializes strucutures and databases for flowtracker core module
    267  *    which is maintained/used by flowtracker stage.
    268  *
    269  * Parameters:
    270  *    unit       - (IN) BCM device number.
    271  *    stage_fc   - (IN) Field stage control structure.
    272  *
    273  * Returns:
    274  *    BCM_E_XXX
    275  */
    276 STATIC int
    277 _field_hx5_ft_stage_ftinfo_init(int unit,
    278                                 _field_stage_t *stage_fc)
    279 {
    280     int rv = BCM_E_NONE;
    281     _field_ft_info_t *ft_info = NULL;
    282 
    283     if (stage_fc == NULL) {
    284         return BCM_E_PARAM;
    285     }
    286 
    287     _FP_XGS3_ALLOC(ft_info, sizeof (_field_ft_info_t), "FT core info");
    288     if (ft_info == NULL) {
    289         return BCM_E_MEMORY;
    290     }
    291 
    292     stage_fc->ft_info = ft_info;
    293 
    294     /* Initialize session keygen profiles */
    295     rv = _field_hx5_ft_session_keygen_profiles_init(unit, stage_fc);
    296     if (BCM_FAILURE(rv)) {
    297         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    298             "FP(unit %d) Error: _field_hx5_ft_session_keygen_profiles_init=%d\n"),
    299                   unit, rv));
    300         sal_free(stage_fc->ft_info);
    301         stage_fc->ft_info = NULL;
    302         return (rv);
    303     }
    304 
    305     /* Tracking param-flowcheck qualifier map db init */
    306     rv = _field_ft_tracking_param_qual_map_db_init(unit, ft_info);
    307     if (rv != BCM_E_NONE) {
    308         (void) _field_ft_tracking_param_qual_map_db_cleanup(unit, ft_info);
    309         sal_free(stage_fc->ft_info);
    310         stage_fc->ft_info = NULL;
    311         return rv;
    312     }
    313 
    314     /* Flow key Qualifiers cfg is same as stage qualifers */
    315     ft_info->flow_key_qual_cfg = stage_fc->qual_cfg_info_db;
    316 
    317     /* Flow key Extractors cfg is same as stage extractors cfg */
    318     ft_info->flow_key_ext_cfg_arr = stage_fc->ext_cfg_db_arr;
    319 
    320     /* Flow data Qualifiers cfg is same as stage qualifiers */
    321     ft_info->flow_data_qual_cfg = stage_fc->qual_cfg_info_db;
    322 
    323     /* Flow data Extractors cfg is profile AB - 256 bits */
    324     _FP_XGS3_ALLOC(ft_info->flow_data_ext_cfg,
    325                     sizeof(bcmi_keygen_ext_cfg_db_t),
    326                     "flow data extr cfg");
    327     if (ft_info->flow_data_ext_cfg == NULL) {
    328        (void) _field_ft_tracking_param_qual_map_db_cleanup(unit, ft_info);
    329         sal_free(stage_fc->ft_info);
    330         stage_fc->ft_info = NULL;
    331         return BCM_E_MEMORY;
    332     }
    333 
    334     rv = _field_ft_keygen_profile_ab_extractors_db_create(unit,
    335                 ft_info->flow_data_ext_cfg, BCMI_KEYGEN_MODE_SINGLE);
    336 
    337     if (rv != BCM_E_NONE) {
    338         if (stage_fc->ft_info != NULL) {
    339             if (stage_fc->ft_info->flow_data_ext_cfg != NULL) {
    340                 sal_free(stage_fc->ft_info->flow_data_ext_cfg);
    341             }
    342             (void) _field_ft_tracking_param_qual_map_db_cleanup(unit, ft_info);
    343             sal_free(stage_fc->ft_info);
    344             stage_fc->ft_info = NULL;
    345         }
    346     }
    347     return rv;
    348 }
    349 
    350 /*
    351  * Function:
    352  *    _field_hx5_ft_stage_ftinfo_deinit
    353  *
    354  * Purpose:
    355  *    De-initializes strucutures and databases for flowtracker core module
    356  *    which is maintained/used by flowtracker stage.
    357  *
    358  * Parameters:
    359  *    unit       - (IN) BCM device number.
    360  *    stage_fc   - (IN) Stage field control structure.
    361  *
    362  * Returns:
    363  *    BCM_E_XXX
    364  */
    365 STATIC int
    366 _field_hx5_ft_stage_ftinfo_deinit(int unit,
    367                                   _field_stage_t *stage_fc)
    368 {
    369     _field_ft_info_t *ft_info  =NULL;
    370 
    371     if (stage_fc == NULL) {
    372         return BCM_E_NONE;
    373     }
    374 
    375     if (stage_fc->ft_info == NULL) {
    376         return BCM_E_NONE;
    377     }
    378     ft_info = stage_fc->ft_info;
    379 
    380     /* destroy session keygen profiles */
    381     soc_profile_mem_destroy(unit, &(ft_info->session_key_profile));
    382     soc_profile_mem_destroy(unit, &(ft_info->session_data_profile));
    383     soc_profile_mem_destroy(unit, &(ft_info->alu_data_profile));
    384 
    385     ft_info->flow_key_qual_cfg = NULL;
    386     ft_info->flow_key_ext_cfg_arr = NULL;
    387     ft_info->flow_data_qual_cfg = NULL;
    388 
    389     /* Flow data Extractors cfg */
    390     if (ft_info->flow_data_ext_cfg != NULL) {
    391         bcmi_keygen_ext_cfg_db_free(unit, ft_info->flow_data_ext_cfg);
    392         ft_info->flow_data_ext_cfg = NULL;
    393     }
    394 
    395     (void) _field_ft_tracking_param_qual_map_db_cleanup(unit, ft_info);
    396 
    397     sal_free(stage_fc->ft_info);
    398     stage_fc->ft_info = NULL;
    399 
    400     return BCM_E_NONE;
    401 }
    402 
    403 /*
    404  * Function:
    405  *    _field_hx5_ft_stage_quals_ibus_map_init
    406  *
    407  * Purpose:
    408  *    Initializes flowtracker stage qualifiers ingress field bus mapping.
    409  *
    410  * Parameters:
    411  *    unit       - (IN) BCM device number.
    412  *    stage_fc   - (IN) Stage field control structure.
    413  *
    414  * Returns:
    415  *    BCM_E_PARAM       - Null field stage control structure.
    416  *    BCM_E_INTERNAL    - Invalid CAP Stage ID.
    417  *    BCM_E_NONE        - Success.
    418  */
    419 STATIC int
    420 _field_hx5_ft_stage_quals_ibus_map_init(int unit,
    421                              _field_stage_t *stage_fc)
    422 {
    423     uint32 pp_ports = 0;
    424     bcmi_keygen_qual_flags_bmp_t qual_flags;
    425     bcmi_keygen_qual_cfg_info_db_t *db = NULL;
    426     BCMI_KEYGEN_FUNC_ENTER(unit);
    427     BCMI_KEYGEN_QUAL_CFG_DECL;
    428 
    429     /* validate input params */
    430     if (stage_fc == NULL) {
    431         return BCM_E_PARAM;
    432     }
    433 
    434     _FP_XGS3_ALLOC(stage_fc->qual_cfg_info_db,
    435             sizeof(bcmi_keygen_qual_cfg_info_db_t),
    436             "flowtracker qualifiers");
    437     if (NULL == stage_fc->qual_cfg_info_db) {
    438         return (BCM_E_MEMORY);
    439     }
    440 
    441     db = stage_fc->qual_cfg_info_db;
    442     sal_memset(&qual_flags, 0, sizeof(bcmi_keygen_qual_flags_bmp_t));
    443 
    444     /* Dummy Qualifiers */
    445     /* Stage */
    446     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    447     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyStage, qual_flags);
    448 
    449     /* Stage Flowtracker */
    450     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    451     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyStageIngressFlowtracker, qual_flags);
    452 
    453     /* Underlay Packet fields - PARSER1_FIELD_BUS */
    454     /* Source MAC Address */
    455     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    456     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 0, 0, 16);
    457     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 1, 16, 16);
    458     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(2, BCMI_KEYGEN_EXT_SECTION_L1E16, 2, 32, 16);
    459     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifySrcMac, qual_flags);
    460 
    461     /* Destination MAC Address */
    462     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    463     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 3, 48, 16);
    464     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 4, 64, 16);
    465     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(2, BCMI_KEYGEN_EXT_SECTION_L1E16, 5, 80, 16);
    466     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyDstMac, qual_flags);
    467 
    468     /* Outer Vlan */
    469     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    470     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 10, 160, 16);
    471     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyOuterVlan, qual_flags);
    472 
    473     /* Outer Vlan Identifier */
    474     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    475     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 10, 160, 12);
    476     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyOuterVlanId, qual_flags);
    477 
    478     /* Outer Vlan CFI */
    479     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    480     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 10, 172, 1);
    481     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyOuterVlanCfi, qual_flags);
    482 
    483     /* Outer Vlan Priority */
    484     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    485     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 10, 173, 3);
    486     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyOuterVlanPri, qual_flags);
    487 
    488     /* Inner Vlan */
    489     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    490     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 11, 176, 16);
    491     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerVlan, qual_flags);
    492 
    493     /* Inner Vlan Identifier */
    494     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    495     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 11, 176, 12);
    496     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerVlanId, qual_flags);
    497 
    498     /* Inner Vlan CFI */
    499     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    500     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 11, 188, 1);
    501     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerVlanCfi, qual_flags);
    502 
    503     /* Inner Vlan Priority */
    504     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    505     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 11, 189, 3);
    506     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerVlanPri, qual_flags);
    507 
    508     /* Outer Ethertype */
    509     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    510     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 13, 208, 16);
    511     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyEtherType, qual_flags);
    512 
    513     /* IPv4 Source Address */
    514     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    515     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 14, 224, 16);
    516     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 15, 240, 16);
    517     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifySrcIp, qual_flags);
    518 
    519     /* IPv4 IP Protocol */
    520     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    521     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 17, 272, 8);
    522     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyIpProtocol, qual_flags);
    523 
    524     /* IPv4 TTL */
    525     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    526     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 17, 280, 8);
    527     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyTtl, qual_flags);
    528 
    529     /* IPv4 Total Length */
    530     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    531     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 20, 320, 16);
    532     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyIp4Length, qual_flags);
    533 
    534     /* IPv4 TOS / DSCP */
    535     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    536     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 21, 336, 8);
    537     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyTos, qual_flags);
    538 
    539     /* IPv6 Source Address */
    540     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    541     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 14, 224, 16);
    542     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 15, 240, 16);
    543     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(2, BCMI_KEYGEN_EXT_SECTION_L1E16, 16, 256, 16);
    544     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(3, BCMI_KEYGEN_EXT_SECTION_L1E16, 17, 272, 16);
    545     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(4, BCMI_KEYGEN_EXT_SECTION_L1E16, 18, 288, 16);
    546     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(5, BCMI_KEYGEN_EXT_SECTION_L1E16, 19, 304, 16);
    547     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(6, BCMI_KEYGEN_EXT_SECTION_L1E16, 20, 320, 16);
    548     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(7, BCMI_KEYGEN_EXT_SECTION_L1E16, 21, 336, 16);
    549     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifySrcIp6, qual_flags);
    550 
    551     /* IPv6 LSB 64-bit Source Address */
    552     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    553     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 14, 224, 16);
    554     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 15, 240, 16);
    555     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(2, BCMI_KEYGEN_EXT_SECTION_L1E16, 16, 256, 16);
    556     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(3, BCMI_KEYGEN_EXT_SECTION_L1E16, 17, 272, 16);
    557     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifySrcIp6Low, qual_flags);
    558 
    559     /* IPv6 MSB 64-bit Source Address */
    560     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    561     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 18, 288, 16);
    562     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 19, 304, 16);
    563     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(2, BCMI_KEYGEN_EXT_SECTION_L1E16, 20, 320, 16);
    564     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(3, BCMI_KEYGEN_EXT_SECTION_L1E16, 21, 336, 16);
    565     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifySrcIp6High, qual_flags);
    566 
    567     /* IPv4 Destination Address */
    568     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    569     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 22, 352, 16);
    570     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 23, 368, 16);
    571     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyDstIp, qual_flags);
    572 
    573     /* IPv6 Flow Label */
    574     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    575     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 22, 352, 16);
    576     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 23, 368, 4);
    577     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyIp6FlowLabel, qual_flags);
    578 
    579     /* IPv6 Traffic class */
    580     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    581     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 23, 372, 8);
    582     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyIp6PktTrafficClass, qual_flags);
    583 
    584     /* IPv6 Destination Address */
    585     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    586     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 24, 384, 16);
    587     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 25, 400, 16);
    588     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(2, BCMI_KEYGEN_EXT_SECTION_L1E16, 26, 416, 16);
    589     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(3, BCMI_KEYGEN_EXT_SECTION_L1E16, 27, 432, 16);
    590     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(4, BCMI_KEYGEN_EXT_SECTION_L1E16, 28, 448, 16);
    591     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(5, BCMI_KEYGEN_EXT_SECTION_L1E16, 29, 464, 16);
    592     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(6, BCMI_KEYGEN_EXT_SECTION_L1E16, 30, 480, 16);
    593     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(7, BCMI_KEYGEN_EXT_SECTION_L1E16, 31, 496, 16);
    594     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyDstIp6, qual_flags);
    595 
    596     /* IPv6 LSB 64-bit Destination Address */
    597     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    598     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 24, 384, 16);
    599     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 25, 400, 16);
    600     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(2, BCMI_KEYGEN_EXT_SECTION_L1E16, 26, 416, 16);
    601     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(3, BCMI_KEYGEN_EXT_SECTION_L1E16, 27, 432, 16);
    602     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyDstIp6Low, qual_flags);
    603 
    604     /* IPv6 MSB 64-bit Destination Address */
    605     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    606     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 28, 448, 16);
    607     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 29, 464, 16);
    608     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(2, BCMI_KEYGEN_EXT_SECTION_L1E16, 30, 480, 16);
    609     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(3, BCMI_KEYGEN_EXT_SECTION_L1E16, 31, 496, 16);
    610     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyDstIp6High, qual_flags);
    611 
    612     /* IPv6 Hop limit */
    613     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    614     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 32, 512, 8);
    615     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyIp6PktHopLimit, qual_flags);
    616 
    617     /* IPv6 Next Header */
    618     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    619     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 32, 520, 8);
    620     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyIp6PktNextHeader, qual_flags);
    621 
    622     /* IPv6 Payload Length */
    623     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    624     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 33, 528, 16);
    625     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyIp6Length, qual_flags);
    626 
    627     /* L4 Destination Port */
    628     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    629     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 34, 544, 16);
    630     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyL4DstPort, qual_flags);
    631 
    632     /* L4 Source Port */
    633     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    634     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 35, 560, 16);
    635     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyL4SrcPort, qual_flags);
    636 
    637     /* TCP Window Size */
    638     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    639     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 36, 576, 16);
    640     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyTcpWindowSize, qual_flags);
    641 
    642     /* TCP Control Flags */
    643     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    644     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 37, 592, 8);
    645     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyTcpControl, qual_flags);
    646 
    647     /* VxLan Reserved 56-63 bits */
    648     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    649     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 38, 608, 8);
    650     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyVxlanHeaderBits56_63, qual_flags);
    651 
    652     /* VxLan Identifier */
    653     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    654     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 38, 616, 8);
    655     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 39, 624, 16);
    656     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyVxlanNetworkId, qual_flags);
    657 
    658     /* VxLan Reserved 8-31 bits */
    659     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    660     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 40, 640, 16);
    661     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 41, 656, 8);
    662     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyVxlanHeaderBits8_31, qual_flags);
    663 
    664     /* VxLan Flags */
    665     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    666     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 41, 664, 8);
    667     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyVxlanFlags, qual_flags);
    668 
    669     /* Overlay packet fields - PARSER2_FIELD_BUS */
    670     /* Tunneled Payload / Inner IPv4 Source Address */
    671     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    672     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 78, 1248, 16);
    673     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 79, 1264, 16);
    674     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerSrcIp, qual_flags);
    675 
    676     /* Tunneled Payload / Inner IPv4 Ip Protocol */
    677     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    678     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 81, 1296, 8);
    679     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerIpProtocol, qual_flags);
    680 
    681     /* Inner IPv4 TTL */
    682     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    683     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 81, 1304, 8);
    684     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerTtl, qual_flags);
    685 
    686     /* Tunnel Payload / Inner IPv4 Total Length */
    687     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    688     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 84, 1344, 16);
    689     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyTunnelPayloadIp4Length, qual_flags);
    690 
    691     /* Inner IPv4 TOS / DSCP */
    692     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    693     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 85, 1360, 8);
    694     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerTos, qual_flags);
    695 
    696     /* Inner IPv6 Source Address */
    697     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    698     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 78, 1248, 16);
    699     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 79, 1264, 16);
    700     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(2, BCMI_KEYGEN_EXT_SECTION_L1E16, 80, 1280, 16);
    701     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(3, BCMI_KEYGEN_EXT_SECTION_L1E16, 81, 1296, 16);
    702     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(4, BCMI_KEYGEN_EXT_SECTION_L1E16, 82, 1312, 16);
    703     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(5, BCMI_KEYGEN_EXT_SECTION_L1E16, 83, 1328, 16);
    704     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(6, BCMI_KEYGEN_EXT_SECTION_L1E16, 84, 1344, 16);
    705     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(7, BCMI_KEYGEN_EXT_SECTION_L1E16, 85, 1360, 16);
    706     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerSrcIp6, qual_flags);
    707 
    708     /* Inner IPv6 MSB 64-bit Source Address */
    709     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    710     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 82, 1312, 16);
    711     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 83, 1328, 16);
    712     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(2, BCMI_KEYGEN_EXT_SECTION_L1E16, 84, 1344, 16);
    713     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(3, BCMI_KEYGEN_EXT_SECTION_L1E16, 85, 1360, 16);
    714     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerSrcIp6High, qual_flags);
    715 
    716     /* Inner IPv4 Destination Address */
    717     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    718     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 86, 1376, 16);
    719     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 87, 1392, 16);
    720     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerDstIp, qual_flags);
    721 
    722     /* Inner IPv6 Flow Label */
    723     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    724     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 86, 1376, 16);
    725     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 87, 1392, 4);
    726     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerIp6FlowLabel, qual_flags);
    727 
    728     /* Inner IPv6 Traffic class */
    729     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    730     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 87, 1396, 8);
    731     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerIp6PktTrafficClass, qual_flags);
    732 
    733     /* Inner IPv6 Destination Address */
    734     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    735     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 88, 1408, 16);
    736     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 89, 1424, 16);
    737     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(2, BCMI_KEYGEN_EXT_SECTION_L1E16, 90, 1440, 16);
    738     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(3, BCMI_KEYGEN_EXT_SECTION_L1E16, 91, 1456, 16);
    739     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(4, BCMI_KEYGEN_EXT_SECTION_L1E16, 92, 1472, 16);
    740     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(5, BCMI_KEYGEN_EXT_SECTION_L1E16, 93, 1488, 16);
    741     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(6, BCMI_KEYGEN_EXT_SECTION_L1E16, 94, 1504, 16);
    742     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(7, BCMI_KEYGEN_EXT_SECTION_L1E16, 95, 1520, 16);
    743     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerDstIp6, qual_flags);
    744 
    745     /* Inner IPv6 MSB 64-bit Destination Address */
    746     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    747     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 92, 1472, 16);
    748     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 93, 1488, 16);
    749     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(2, BCMI_KEYGEN_EXT_SECTION_L1E16, 94, 1504, 16);
    750     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(3, BCMI_KEYGEN_EXT_SECTION_L1E16, 95, 1520, 16);
    751     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerDstIp6High, qual_flags);
    752 
    753     /* Inner IPv6 Hop limit */
    754     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    755     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 96, 1536, 8);
    756     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerIp6PktHopLimit, qual_flags);
    757 
    758     /* Inner IPv6 Next Header */
    759     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    760     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 96, 1544, 8);
    761     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerIp6PktNextHeader, qual_flags);
    762 
    763     /* Tunnel Payload / Inner IPv6 Payload Length */
    764     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    765     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 97, 1552, 16);
    766     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyTunnelPayloadIp6Length, qual_flags);
    767 
    768     /* Inner L4 Destination Port */
    769     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    770     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 98, 1568, 16);
    771     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerL4DstPort, qual_flags);
    772 
    773     /* Inner L4 Source Port */
    774     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    775     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 99, 1584, 16);
    776     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerL4SrcPort, qual_flags);
    777 
    778     /* OBJECT BUS */
    779     /* Module Header SGPP - Module Id + Port */
    780     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    781     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 129, 2064, 16);
    782     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyHiGigSrcModPortGport, qual_flags);
    783 
    784     /* Module Header SGPP - Module Id */
    785     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    786     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 129, 2072, 8);
    787     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyHiGigSrcModuleGport, qual_flags);
    788 
    789     /* Module Header SGPP - Port */
    790     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    791     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 129, 2064, 8);
    792     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyHiGigSrcPortGport, qual_flags);
    793 
    794     /* SGLP Module Id + Port */
    795     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    796     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 130, 2080, 16);
    797     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifySrcModPortGport, qual_flags);
    798 
    799     /* SGLP Module Id */
    800     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    801     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 130, 2088, 8);
    802     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifySrcModuleGport, qual_flags);
    803 
    804     /*INGRESS_PP_PORT */
    805     pp_ports = 7;
    806     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    807     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 133, 2128, pp_ports);
    808     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInPort, qual_flags);
    809 
    810     /* Source Trunk Map class ID */
    811     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    812     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 135, 2160, 12);
    813     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInterfaceClassPort, qual_flags);
    814 
    815     /* VFP_CLASSID HI */
    816     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    817     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 136, 2176, 10);
    818     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifySrcClassField, qual_flags);
    819 
    820     /* VFP_CLASSID LO */
    821     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    822     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 137, 2192, 10);
    823     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyDstClassField, qual_flags);
    824 
    825     /* VPN */
    826     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    827     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 138, 2208, 10);
    828     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyVpn, qual_flags);
    829 
    830     /* Virtual Routing forwarding object */
    831     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    832     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 139, 2224, 16);
    833     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyVrf, qual_flags);
    834 
    835     /* Incoming L3 Interface */
    836     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    837     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 140, 2240, 13);
    838     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyL3Ingress, qual_flags);
    839 
    840     /* Higig Dst Module + Port */
    841     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    842     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 143, 2288, 16);
    843     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyHiGigDstModPortGport, qual_flags);
    844 
    845     /* Source VP Class Id */
    846     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    847     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 153, 2448, 12);
    848     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInterfaceClassVPort, qual_flags);
    849 
    850     /* L3_IIF Class ID */
    851     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    852     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 154, 2464, 12);
    853     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInterfaceClassL3, qual_flags);
    854 
    855     /* HVE1_DOS_ATTACK_RESULTS_BUS */
    856     /* DOS Attack Events */
    857     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    858     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 173, 2768, 16);
    859     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 174, 2784, 16);
    860     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyDosAttackEvents, qual_flags);
    861 
    862     /* HVE2_DOS_ATTACK_RESULTS_BUS */
    863     /* Inner DOS Attack Events */
    864     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    865     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 175, 2800, 16);
    866     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 176, 2816, 16);
    867     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerDosAttackEvents, qual_flags);
    868 
    869     /* PARSER1_HVE_BUS */
    870     /* Vlan Format */
    871     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    872     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 178, 2849, 2);
    873     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyVlanFormat, qual_flags);
    874 
    875     /* L2 Format */
    876     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    877     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 178, 2857, 2);
    878     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyL2Format, qual_flags);
    879 
    880     /* L2/L3 Unicast/Multicast/Broadcast */
    881     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    882     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 179, 2866, 2);
    883     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 179, 2876, 2);
    884     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyPktDstAddrType, qual_flags);
    885 
    886     /* Outer Priority tagged */
    887     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    888     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 179, 2873, 1);
    889     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyOuterPriTaggedPkt, qual_flags);
    890 
    891     /* IP with TTL=0 */
    892     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    893     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 179, 2878, 1);
    894     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyIpTtlZeroPkt, qual_flags);
    895 
    896     /* IP Flags */
    897     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    898     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 181, 2899, 2);
    899     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyIpFlags, qual_flags);
    900 
    901     /* L4 Valid */
    902     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    903     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 181, 2908, 1);
    904     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyL4Ports, qual_flags);
    905 
    906     /* Inner Tpid */
    907     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    908     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 182, 2928, 2);
    909     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerTpid, qual_flags);
    910 
    911     /* Outer Tpid */
    912     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    913     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 183, 2942, 2);
    914     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyOuterTpid, qual_flags);
    915 
    916     /* PARSER2_HVE_BUS */
    917     /* Inner L2/L3 Unicast/Multicast/Broadcast */
    918     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    919     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 193, 3090, 2);
    920     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 193, 3099, 2);
    921     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyPktInnerDstAddrType, qual_flags);
    922 
    923     /* Inner L4 Valid */
    924     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    925     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 195, 3132, 1);
    926     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyInnerL4Ports, qual_flags);
    927 
    928     /* Tunnel Class for Flowtracker usage */
    929     BCMI_KEYGEN_QUAL_CFG_INIT(unit);
    930     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(0, BCMI_KEYGEN_EXT_SECTION_L1E16, 157, 2512, 16);
    931     BCMI_KEYGEN_QUAL_CFG_OFFSET_ADD(1, BCMI_KEYGEN_EXT_SECTION_L1E16, 158, 2528, 8);
    932     BCMI_KEYGEN_QUAL_CFG_INSERT(unit, db, bcmFieldQualifyTunnelId, qual_flags);
    933 
    934 exit:
    935 
    936     BCMI_KEYGEN_FUNC_EXIT();
    937 }
    938 
    939 /*
    940  * Function:
    941  *    _bcm_field_hx5_ft_tcam_policy_mem_get
    942  *
    943  * Purpose:
    944  *    Get tcam+policy combo memory
    945  *
    946  * Parameters:
    947  *    unit       - (IN) BCM device number.
    948  *    tcam_mem   - (OUT) tcam table
    949  *    policy_mem - (OUT) policy table
    950  *
    951  * Returns:
    952  *    BCM_E_XXX
    953  */
    954 STATIC int
    955 _bcm_field_hx5_ft_tcam_policy_mem_get(int unit,
    956                                       soc_mem_t *tcam_mem,
    957                                       soc_mem_t *policy_mem)
    958 {
    959     *tcam_mem = BSK_FTFP_TCAMm;
    960     *policy_mem = BSK_FTFP_POLICYm;
    961 
    962     return BCM_E_NONE;
    963 }
    964 
    965 /*
    966  * Function:
    967  *    _field_hx5_ft_entry_qual_tcam_set
    968  *
    969  * Purpose:
    970  *    Sets tcam key and mask information to buffer
    971  *
    972  * Parameters:
    973  *    unit       - (IN) BCM device number.
    974  *    f_ent      - (IN) Field entry structure.
    975  *    tcam_mem   - (IN) tcam hw table.
    976  *    tcam_idx   - (IN) tcam hw index
    977  *    entry_buf  - (IN/OUT) Entry buffer.
    978  *
    979  * Returns:
    980  *    BCM_E_XXX
    981  */
    982 STATIC int
    983 _field_hx5_ft_entry_qual_tcam_set(int unit,
    984                                   _field_entry_t *f_ent,
    985                                   soc_mem_t tcam_mem,
    986                                   int tcam_idx,
    987                                   uint32 *entry_buf)
    988 {
    989     _field_tcam_t *tcam = NULL;
    990 
    991     if ((f_ent == NULL) || (entry_buf == NULL))   {
    992         return BCM_E_PARAM;
    993     }
    994 
    995     tcam = &f_ent->tcam;
    996     if (tcam == NULL) {
    997         return (BCM_E_INTERNAL);
    998     }
    999 
   1000     soc_mem_field_set(unit, tcam_mem, entry_buf, KEYf, tcam->key);
   1001     soc_mem_field_set(unit, tcam_mem, entry_buf, MASKf, tcam->mask);
   1002     soc_mem_field32_set(unit, tcam_mem, entry_buf, VALIDf, 3);
   1003 
   1004     return BCM_E_NONE;
   1005 }
   1006 
   1007 /*
   1008  * Function:
   1009  *    _field_hx5_ft_entry_policy_set
   1010  *
   1011  * Purpose:
   1012  *    Sets policy data information to buffer
   1013  *
   1014  * Parameters:
   1015  *    unit       - (IN) BCM device number.
   1016  *    f_ent      - (IN) Field entry structure.
   1017  *    policy_mem - (IN) Policy hw table.
   1018  *    e_buf      - (IN/OUT) Entry buffer.
   1019  *
   1020  * Returns:
   1021  *    BCM_E_PARAM       - Null field stage control structure.
   1022  *    BCM_E_INTERNAL    - Invalid CAP Stage ID.
   1023  *    BCM_E_NONE        - Success.
   1024  */
   1025 STATIC int
   1026 _field_hx5_ft_entry_policy_set(int unit,
   1027                                _field_entry_t *f_ent,
   1028                                soc_mem_t policy_mem,
   1029                                uint32 *e_buf)
   1030 {
   1031     int rv = BCM_E_NONE;
   1032     _field_action_t *fa = NULL;
   1033     uint32 value = 0;
   1034     uint32 do_not_ft_def = 1;
   1035     uint32 action_ft = 0, action_ft_set = FALSE;
   1036     uint32 action_new_learn = 0, action_new_learn_set = FALSE;
   1037     bcm_flowtracker_group_t ft_group_id = -1;
   1038     bcmi_ft_group_ftfp_data_t ftfp_data;
   1039     bcmi_ft_session_profiles_t *profiles = NULL;
   1040 
   1041     if ((f_ent ==NULL) || (policy_mem == INVALIDm) || (e_buf == NULL)) {
   1042         return (BCM_E_PARAM);
   1043     }
   1044 
   1045     /* policy install is needed only for Entry part 0 */
   1046     if (f_ent->flags & _FP_ENTRY_SECOND_HALF) {
   1047         return BCM_E_NONE;
   1048     }
   1049 
   1050     /* Loop through all actions */
   1051     for (fa = f_ent->actions;
   1052            (fa != NULL) && (fa->flags & _FP_ACTION_VALID);
   1053            fa = fa->next) {
   1054         switch(fa->action) {
   1055             case bcmFieldActionFlowtrackerGroupId:
   1056                 ft_group_id = fa->param[0];
   1057                 break;
   1058             case bcmFieldActionFlowtrackerEnable:
   1059                 action_ft_set = TRUE;
   1060                 action_ft = fa->param[0];
   1061                 break;
   1062             case bcmFieldActionFlowtrackerNewLearnEnable:
   1063                 action_new_learn_set = TRUE;
   1064                 action_new_learn = fa->param[0];
   1065                 break;
   1066             default:
   1067                 return (BCM_E_INTERNAL);
   1068         }
   1069     }
   1070 
   1071     if (ft_group_id != -1) {
   1072         /* Read all relevent information from FT module */
   1073         BCM_IF_ERROR_RETURN(bcmi_ft_group_ftfp_data_get(unit,
   1074                         ft_group_id, &ftfp_data));
   1075         profiles = &ftfp_data.profiles;
   1076 
   1077         /* Set Group Id */
   1078         if(SOC_MEM_FIELD_VALID(unit, policy_mem, GROUP_IDf)) {
   1079             value = ft_group_id;
   1080             soc_mem_field_set(unit, policy_mem, (void *) e_buf,
   1081                     GROUP_IDf, &(value));
   1082         }
   1083 
   1084         /* Set bi-directional flow */
   1085         if (SOC_MEM_FIELD_VALID(unit, policy_mem, BIDIRECTIONAL_FLOWf)) {
   1086             value = 0;
   1087             if (ftfp_data.direction == bcmFlowtrackerFlowDirectionBidirectional) {
   1088                 value = 1;
   1089             }
   1090             BCM_IF_ERROR_RETURN(_field_hx5_ft_normalize_controls_set(unit,
   1091                     ft_group_id, policy_mem, value, e_buf));
   1092             soc_mem_field_set(unit, policy_mem, (void *) e_buf,
   1093                 BIDIRECTIONAL_FLOWf, &(value));
   1094         }
   1095 
   1096         /* Set Do not FT */
   1097         if (SOC_MEM_FIELD_VALID(unit, policy_mem, DO_NOT_FTf)) {
   1098             if (action_ft_set == TRUE) {
   1099                 value = (action_ft) ? 0 : 1;
   1100             } else {
   1101                 value = (ftfp_data.flowtrack) ? 0 : 1;
   1102             }
   1103             soc_mem_field_set(unit, policy_mem, (void *) e_buf,
   1104                     DO_NOT_FTf, &(value));
   1105         }
   1106 
   1107         /* Set New Learn Disable */
   1108         if (SOC_MEM_FIELD_VALID(unit, policy_mem, LEARN_DISABLEf)) {
   1109             if (action_new_learn_set == TRUE) {
   1110                 value = (action_new_learn) ? 0 : 1;
   1111             } else {
   1112                 value = (ftfp_data.new_learn) ? 0: 1;
   1113             }
   1114             soc_mem_field_set(unit, policy_mem, (void *) e_buf,
   1115                     LEARN_DISABLEf, &(value));
   1116         }
   1117 
   1118         /* Set Session Key Profile index */
   1119         if ((SOC_MEM_FIELD_VALID(unit,
   1120                 policy_mem, SESSION_KEY_LTS_PROFILEf)) &&
   1121             (profiles->session_key_profile_idx != 0)) {
   1122             value = profiles->session_key_profile_idx - 1;
   1123             soc_mem_field_set(unit, policy_mem, (void *) e_buf,
   1124                     SESSION_KEY_LTS_PROFILEf, &(value));
   1125         }
   1126 
   1127         /* Set Session Data Profile index */
   1128         if ((SOC_MEM_FIELD_VALID(unit,
   1129                 policy_mem, SESSION_DATA_LTS_PROFILEf)) &&
   1130             (profiles->session_data_profile_idx != 0)) {
   1131             value = profiles->session_data_profile_idx - 1;
   1132             soc_mem_field_set(unit, policy_mem, (void *) e_buf,
   1133                     SESSION_DATA_LTS_PROFILEf, &(value));
   1134         }
   1135 
   1136         /* Set Alu Data Profile index */
   1137         if ((SOC_MEM_FIELD_VALID(unit,
   1138                 policy_mem, ALU_DATA_LTS_PROFILEf)) &&
   1139             (profiles->alu_data_profile_idx != 0)) {
   1140             value = profiles->alu_data_profile_idx - 1;
   1141             soc_mem_field_set(unit, policy_mem, (void *) e_buf,
   1142                     ALU_DATA_LTS_PROFILEf, &(value));
   1143         }
   1144 
   1145         /* Set Key Type */
   1146         if (SOC_MEM_FIELD_VALID(unit, policy_mem, SESSION_KEY_TYPEf)) {
   1147             /* Set this value to Profile_id of Session_key */
   1148             value = ftfp_data.session_key_type;
   1149             soc_mem_field_set(unit, policy_mem, (void *) e_buf,
   1150                     SESSION_KEY_TYPEf, &(value));
   1151         }
   1152 
   1153         /* Session Key Mode */
   1154         if (SOC_MEM_FIELD_VALID(unit, policy_mem, SESSION_KEY_MODEf)) {
   1155             value =
   1156                 (ftfp_data.session_key_mode == bcmiFtGroupModeDouble) ? 1 : 0;
   1157 
   1158             soc_mem_field_set(unit, policy_mem, (void *) e_buf,
   1159                     SESSION_KEY_MODEf, &(value));
   1160         }
   1161     } else {
   1162         /* Group is not associated, set do not Ft */
   1163         if (SOC_MEM_FIELD_VALID(unit, policy_mem, DO_NOT_FTf)) {
   1164             soc_mem_field_set(unit, policy_mem, (void *) e_buf,
   1165                     DO_NOT_FTf, &do_not_ft_def);
   1166         }
   1167     }
   1168     /* Reset DIRTY flag */
   1169     for (fa = f_ent->actions;
   1170            (fa != NULL) && (fa->flags & _FP_ACTION_VALID);
   1171            fa = fa->next) {
   1172         fa->flags &= (~_FP_ACTION_DIRTY);
   1173     }
   1174 
   1175     return rv;
   1176 }
   1177 
   1178 /*
   1179  * Function:
   1180  *    _field_hx5_ft_tcam_policy_init
   1181  *
   1182  * Purpose:
   1183  *    Fill Tcam/Policy memories with default entries.
   1184  *    Default entries are required to handle broadscan port.
   1185  *
   1186  * Parameters:
   1187  *    unit       - (IN) BCM device number.
   1188  *    stage_fc   - (IN) Field stage control structure.
   1189  *
   1190  * Returns:
   1191  *    BCM_E_PARAM       - Wrong Input params
   1192  *    BCM_E_NONE        - Success.
   1193  */
   1194 int
   1195 _field_hx5_ft_tcam_policy_init(int unit,
   1196                                _field_stage_t *stage_fc)
   1197 {
   1198     int rv = 0;
   1199     uint32 do_not_ft_def = 1;
   1200     uint32 broadscan_port = 0;
   1201     uint32 e_buf[SOC_MAX_MEM_FIELD_WORDS] = {0};
   1202     uint32 policy_buf[SOC_MAX_MEM_FIELD_WORDS] = {0};
   1203     uint32 key_key_buf[SOC_MAX_MEM_FIELD_WORDS] = {0};
   1204     uint32 mask_key_buf[SOC_MAX_MEM_FIELD_WORDS] = {0};
   1205     soc_mem_t tcam_mem = INVALIDf;
   1206     soc_mem_t policy_mem = INVALIDf;
   1207 
   1208     /* If user wants to flowtrack ipfix packets coming from FAE Port */
   1209     if (!soc_feature(unit, soc_feature_bscan_fae_port_flow_exclude)) {
   1210         return BCM_E_NONE;
   1211     }
   1212 
   1213     /* Decrease tcam_sz by 4 */
   1214     /* 1 for Single-wide, 2 for Double-wide and 1 Reserved */
   1215     stage_fc->tcam_sz -= 4;
   1216     /* Move tcam stat Idx up by 2 */
   1217     stage_fc->slices[0]->start_tcam_idx +=4;
   1218     /* Reduce number of Free Entry in the slice by 2 */
   1219     stage_fc->slices[0]->free_count -= 4;
   1220     /* Reduce number of entries in the slice by 2 */
   1221     stage_fc->slices[0]->entry_count -= 4;
   1222 
   1223     /* Get FAE Port */
   1224     broadscan_port = FAE_PORT(unit);
   1225 
   1226     /* Disable Ingress Filtering */
   1227     rv = bcm_esw_port_control_set(unit, broadscan_port,
   1228             bcmPortControlFilterIngress, FALSE);
   1229     BCM_IF_ERROR_RETURN(rv);
   1230 
   1231     /*
   1232      * Modify Combo table to disard traffic coming from broadscan port.
   1233      * Single-Wide default entry
   1234      *
   1235      * mod BSK_FTFP_COMBO_TCAM_POLICY 0 1 VALID=3 MASK_KEY=0x7F KEY_KEY=0x47 \
   1236      *                                    MASK_MODE=1 KEY_MODE=0 DO_NOT_FT=1
   1237      *
   1238      * Double-Wide default entry
   1239      * mod BSK_FTFP_COMBO_TCAM_POLICY 2 1 VALID=3 MASK_MODE=1 KEY_MODE=1 \
   1240      MASK_KEY=0x7F KEY_KEY=0x47 DO_NOT_FT=1
   1241      * mod BSK_FTFP_COMBO_TCAM_POLICY 3 1 VALID=3 MASK_MODE=1 KEY_MODE=1
   1242      */
   1243 
   1244     rv = _bcm_field_hx5_ft_tcam_policy_mem_get(unit, &tcam_mem, &policy_mem);
   1245     BCM_IF_ERROR_RETURN(rv);
   1246 
   1247     /* Init Tcam+Policy at Index=0 */
   1248     sal_memset(e_buf, 0, sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS);
   1249     sal_memset(policy_buf, 0, sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS);
   1250 
   1251     /* Set fields in policy */
   1252     soc_mem_field32_set(unit, policy_mem,
   1253             (void *) policy_buf, DO_NOT_FTf, do_not_ft_def);
   1254 
   1255     /* Set fields in Tcam */
   1256     key_key_buf[0] = broadscan_port;
   1257     mask_key_buf[0]=0x7f;
   1258     soc_mem_field_set(unit, tcam_mem,
   1259             e_buf, KEY_KEYf, &key_key_buf[0]);
   1260     soc_mem_field_set(unit, tcam_mem,
   1261             e_buf, MASK_KEYf, &mask_key_buf[0]);
   1262     soc_mem_field32_set(unit, tcam_mem,
   1263             (void *) e_buf, KEY_MODEf, 0);
   1264     soc_mem_field32_set(unit, tcam_mem,
   1265             (void *) e_buf, MASK_MODEf, 1);
   1266     soc_mem_field32_set(unit, tcam_mem,
   1267             (void *) e_buf, VALIDf, 3);
   1268 
   1269     /* Write to hardware */
   1270     rv = soc_mem_write(unit, policy_mem, MEM_BLOCK_ALL, 0, policy_buf);
   1271     BCM_IF_ERROR_RETURN(rv);
   1272     rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, 0, e_buf);
   1273     BCM_IF_ERROR_RETURN(rv);
   1274 
   1275     /* Init Tcam+Policy at Index=2 */
   1276     sal_memset(e_buf, 0, sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS);
   1277     sal_memset(policy_buf, 0, sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS);
   1278 
   1279     /* Set fields in policy */
   1280     soc_mem_field32_set(unit, policy_mem,
   1281             (void *) policy_buf, DO_NOT_FTf, do_not_ft_def);
   1282 
   1283     /* Set fields in Tcam */
   1284     key_key_buf[0] = broadscan_port;
   1285     mask_key_buf[0]=0x7f;
   1286     soc_mem_field_set(unit, tcam_mem,
   1287             (void *) e_buf, KEY_KEYf, &key_key_buf[0]);
   1288     soc_mem_field_set(unit, tcam_mem,
   1289             (void *) e_buf, MASK_KEYf, &mask_key_buf[0]);
   1290     soc_mem_field32_set(unit, tcam_mem,
   1291             (void *) e_buf, KEY_MODEf, 1);
   1292     soc_mem_field32_set(unit, tcam_mem,
   1293             (void *) e_buf, MASK_MODEf, 1);
   1294     soc_mem_field32_set(unit, tcam_mem,
   1295             (void *) e_buf, VALIDf, 3);
   1296 
   1297     /* Write to hardware */
   1298     rv = soc_mem_write(unit, policy_mem, MEM_BLOCK_ALL, 2, policy_buf);
   1299     BCM_IF_ERROR_RETURN(rv);
   1300     rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, 2, e_buf);
   1301     BCM_IF_ERROR_RETURN(rv);
   1302 
   1303     /* Init Tcam+Policy at Index=3 */
   1304     sal_memset(e_buf, 0, sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS);
   1305 
   1306     /* Set fields in Tcam */
   1307     soc_mem_field32_set(unit, tcam_mem,
   1308             (void *) e_buf, KEY_MODEf, 1);
   1309     soc_mem_field32_set(unit, tcam_mem,
   1310             (void *) e_buf, MASK_MODEf, 1);
   1311     soc_mem_field32_set(unit, tcam_mem,
   1312             (void *) e_buf, VALIDf, 3);
   1313 
   1314     /* Write to hardware */
   1315     rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, 3, e_buf);
   1316     BCM_IF_ERROR_RETURN(rv);
   1317 
   1318     return rv;
   1319 }
   1320 
   1321 /*
   1322  * Function:
   1323  *    _field_hx5_ftstage_init
   1324  *
   1325  * Purpose:
   1326  *    Initializes flowtracker stage related information.
   1327  *
   1328  * Parameters:
   1329  *    unit       - (IN) BCM device number.
   1330  *    fc         - (IN) Field control structure.
   1331  *    stage_fc   - (IN) Field stage control structure.
   1332  *
   1333  * Returns:
   1334  *    BCM_E_PARAM       - Null field stage control structure.
   1335  *    BCM_E_INTERNAL    - Invalid CAP Stage ID.
   1336  *    BCM_E_NONE        - Success.
   1337  */
   1338 int
   1339 _field_hx5_ftstage_init(int unit,
   1340                         _field_control_t *fc,
   1341                         _field_stage_t *stage_fc)
   1342 {
   1343     int rv = BCM_E_NONE;
   1344 
   1345     /* Input parameter Check */
   1346     if ((fc == NULL) || (stage_fc == NULL)) {
   1347         return (BCM_E_PARAM);
   1348     }
   1349 
   1350     /* Applicable only for flowtracker stage */
   1351     if (stage_fc->stage_id != _BCM_FIELD_STAGE_FLOWTRACKER) {
   1352         return (BCM_E_NONE);
   1353     }
   1354 
   1355     /* Initialize stage's extractor configuration */
   1356     rv = _field_hx5_ft_stage_extractors_init(unit, stage_fc);
   1357     if (BCM_FAILURE(rv)) {
   1358         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1359             "FP(unit %d) Error: _field_hx5_ft_stage_extractors_init=%d\n"),
   1360             unit, rv));
   1361         return (rv);
   1362     }
   1363 
   1364     /* Initializing supported Qset */
   1365     sal_memset(&stage_fc->_field_supported_qset, 0, sizeof(bcm_field_qset_t));
   1366 
   1367     /* Initialize stage Preselector information for Lt slices and entries */
   1368     rv = _bcm_field_th_stage_preselector_init(unit, fc, stage_fc);
   1369     if (BCM_FAILURE(rv)) {
   1370         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1371            "FP(unit %d) Error: _bcm_field_th_stage_preselector_init=%d"
   1372            "\n"), unit, rv));
   1373         return (rv);
   1374     }
   1375 
   1376     /* Qualifiers ingress field bus map */
   1377     rv = _field_hx5_ft_stage_quals_ibus_map_init(unit, stage_fc);
   1378     if (BCM_FAILURE(rv)) {
   1379         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1380            "FP(unit %d) Error: _field_hx5_ft_stage_quals_ibus_map_init=%d"
   1381            "\n"), unit, rv));
   1382         return (rv);
   1383     }
   1384 
   1385     /* Init information used by FT core module */
   1386     rv = _field_hx5_ft_stage_ftinfo_init(unit, stage_fc);
   1387     if (BCM_FAILURE(rv)) {
   1388         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1389            "FP(unit %d) Error: _field_hx5_ft_stage_ftinfo_init=%d"
   1390            "\n"), unit, rv));
   1391         return (rv);
   1392     }
   1393 
   1394     return (rv);
   1395 }
   1396 
   1397 /*
   1398  * Function:
   1399  *    _field_hx5_ftstage_deinit
   1400  *
   1401  * Purpose:
   1402  *    De-initializes flowtracker stage.
   1403  *
   1404  * Parameters:
   1405  *    unit       - (IN) BCM device number.
   1406  *    stage_fc   - (IN) Stage field control structure.
   1407  *
   1408  * Returns:
   1409  *    BCM_E_PARAM       - Null field stage control structure.
   1410  *    BCM_E_INTERNAL    - Invalid CAP Stage ID.
   1411  *    BCM_E_NONE        - Success.
   1412  */
   1413 int
   1414 _field_hx5_ftstage_deinit(int unit,
   1415                           _field_stage_t *stage_fc)
   1416 {
   1417     /* Input parameter check. */
   1418     if (NULL == stage_fc) {
   1419         return (BCM_E_NONE);
   1420     }
   1421 
   1422     if (stage_fc->stage_id != _BCM_FIELD_STAGE_FLOWTRACKER) {
   1423         return BCM_E_NONE;
   1424     }
   1425 
   1426     /* De-init ft related info */
   1427     (void) _field_hx5_ft_stage_ftinfo_deinit(unit, stage_fc);
   1428 
   1429     /* Rest of allocations freed in common code */
   1430 
   1431     return BCM_E_NONE;
   1432 }
   1433 
   1434 /*
   1435  * Function:
   1436  *    _field_hx5_ft_slice_validate
   1437  *
   1438  * Purpose:
   1439  *    Validates if field group can be allowed to create in given slice.
   1440  *
   1441  * Parameters:
   1442  *    unit       - (IN) BCM device number.
   1443  *    stage_fc   - (IN) Stage field control structure.
   1444  *    fg         - (IN) Field group control structure.
   1445  *    slice_id   - (IN) Slice number
   1446  *
   1447  * Returns:
   1448  *    BCM_E_PARAM       - Null field stage control structure.
   1449  *    BCM_E_INTERNAL    - Invalid CAP Stage ID.
   1450  *    BCM_E_NONE        - Success.
   1451  */
   1452 int
   1453 _field_hx5_ft_slice_validate(int unit,
   1454                              _field_stage_t *stage_fc,
   1455                              _field_group_t *fg,
   1456                              int slice_id)
   1457 {
   1458     int rv = BCM_E_NONE;
   1459 
   1460     /* Validate lt slice */
   1461     rv = _field_th_group_lt_slice_validate(unit, stage_fc, fg, slice_id, NULL);
   1462 
   1463     return rv;
   1464 }
   1465 
   1466 /*
   1467  * Function:
   1468  *    _field_hx5_ft_group_key_type_clear
   1469  *
   1470  * Purpose:
   1471  *    Clears group key type assignment in field group in flowtracker stage.
   1472  *
   1473  * Parameters:
   1474  *    unit       - (IN) BCM device number.
   1475  *    stage_fc   - (IN) Stage field control structure.
   1476  *    fg         - (IN) Field group control structure.
   1477  *
   1478  * Returns:
   1479  *    BCM_E_PARAM       - Null field stage control structure.
   1480  *    BCM_E_INTERNAL    - Invalid CAP Stage ID.
   1481  *    BCM_E_NONE        - Success.
   1482  */
   1483 int
   1484 _field_hx5_ft_group_keytype_clear(int unit,
   1485                                    _field_stage_t *stage_fc,
   1486                                    _field_group_t *fg)
   1487 {
   1488     int keytype = 0;
   1489     _field_ft_info_t *ft_info = NULL;
   1490 
   1491     if ((stage_fc == NULL) || (fg == NULL)) {
   1492         return BCM_E_PARAM;;
   1493     }
   1494 
   1495     if (fg->stage_id != _BCM_FIELD_STAGE_FLOWTRACKER) {
   1496         return (BCM_E_NONE);
   1497     }
   1498 
   1499     if (stage_fc->ft_info == NULL) {
   1500         return BCM_E_INTERNAL;
   1501     }
   1502 
   1503     ft_info = stage_fc->ft_info;
   1504 
   1505     keytype = (fg->lt_id >> _FP_GROUP_FT_KEYTYPE_SHIFT) &
   1506                             (_FP_GROUP_FT_KEYTYPE_MASK);
   1507     SHR_BITCLR(ft_info->key_type_bmp, keytype);
   1508 
   1509     return BCM_E_NONE;
   1510 }
   1511 
   1512 /*
   1513  * Function:
   1514  *    _field_hx5_ft_group_keytype_assign
   1515  *
   1516  * Purpose:
   1517  *    Group key type to field group in flowtracker stage.
   1518  *
   1519  * Parameters:
   1520  *    unit       - (IN) BCM device number.
   1521  *    stage_fc   - (IN) Stage field control structure.
   1522  *    fg         - (IN) Field group control structure.
   1523  *
   1524  * Returns:
   1525  *    BCM_E_PARAM       - Null field stage control structure.
   1526  *    BCM_E_INTERNAL    - Invalid CAP Stage ID.
   1527  *    BCM_E_NONE        - Success.
   1528  */
   1529 int
   1530 _field_hx5_ft_group_keytype_assign(int unit,
   1531                                    _field_stage_t *stage_fc,
   1532                                    _field_group_t *fg)
   1533 {
   1534     int keytype = 0;
   1535     int double_wide = 0;
   1536     _field_ft_info_t *ft_info = NULL;
   1537 
   1538     /* Validate input params */
   1539     if ((stage_fc == NULL) || (fg == NULL)) {
   1540         return BCM_E_PARAM;
   1541     }
   1542 
   1543     /* Applicable only in flowtracker stage. */
   1544     if (fg->stage_id != _BCM_FIELD_STAGE_FLOWTRACKER) {
   1545         return (BCM_E_NONE);
   1546     }
   1547 
   1548     ft_info = stage_fc->ft_info;
   1549     if (ft_info == NULL) {
   1550         return BCM_E_INTERNAL;
   1551     }
   1552 
   1553     /* Unique value for each group */
   1554     for (keytype = 0;
   1555          keytype < _BCM_FIELD_FT_GROUP_KEY_TYPE_MAX;
   1556          keytype++) {
   1557         if (!SHR_BITGET(stage_fc->ft_info->key_type_bmp, keytype)) {
   1558             SHR_BITSET(stage_fc->ft_info->key_type_bmp, keytype);
   1559             break;
   1560         }
   1561     }
   1562     if (keytype == _BCM_FIELD_FT_GROUP_KEY_TYPE_MAX) {
   1563         return BCM_E_INTERNAL;
   1564     }
   1565 
   1566     if (fg->flags & _FP_GROUP_DW_DEPTH_EXPANDED) {
   1567         double_wide = 1;
   1568     }
   1569 
   1570     fg->lt_id = (keytype << _FP_GROUP_FT_KEYTYPE_SHIFT) | double_wide;
   1571 
   1572     return BCM_E_NONE;
   1573 }
   1574 
   1575 /*
   1576  * Function:
   1577  *    _field_hx5_ft_entries_free_get
   1578  *
   1579  * Purpose:
   1580  *    Return number of free entries in slice for given group.
   1581  *
   1582  * Parameters:
   1583  *    unit       - (IN) BCM device number.
   1584  *    fs         - (IN) field slice structure.
   1585  *    fg         - (IN) Field group control structure.
   1586  *    free_cnt   - (OUT) Out argument for number of free entries.
   1587  *
   1588  * Returns:
   1589  *    BCM_E_PARAM       - Null field stage control structure.
   1590  *    BCM_E_INTERNAL    - Invalid CAP Stage ID.
   1591  *    BCM_E_NONE        - Success.
   1592  */
   1593 int
   1594 _field_hx5_ft_entries_free_get(int unit,
   1595                                _field_slice_t *fs,
   1596                                _field_group_t *fg,
   1597                                int *free_cnt)
   1598 {
   1599     /* Input Paramter Check. */
   1600     if ((fg == NULL) || (fs == NULL) || (free_cnt == NULL)) {
   1601         return (BCM_E_PARAM);
   1602     }
   1603 
   1604     /* Initialize free entry count. */
   1605     *free_cnt = 0;
   1606 
   1607     /* Calculate free entry count. */
   1608     if (fg->flags & _FP_GROUP_DW_DEPTH_EXPANDED) {
   1609         *free_cnt = fs->free_count >> 1;
   1610     } else {
   1611         *free_cnt = fs->free_count;
   1612     }
   1613 
   1614     return (BCM_E_NONE);
   1615 }
   1616 
   1617 /*
   1618  * Function:
   1619  *    _bcm_field_hx5_ft_entry_keytype_set
   1620  *
   1621  * Purpose:
   1622  *    Qualify entry in flowtracker stage with group keytype
   1623  *
   1624  * Parameters:
   1625  *    unit       - (IN) BCM device number.
   1626  *    f_ent      - (IN) Field entry structure.
   1627  *
   1628  * Returns:
   1629  *    BCM_E_PARAM       - Null field stage control structure.
   1630  *    BCM_E_INTERNAL    - Invalid CAP Stage ID.
   1631  *    BCM_E_NONE        - Success.
   1632  */
   1633 int
   1634 _bcm_field_hx5_ft_entry_keytype_set(int unit,
   1635                                     _field_entry_t *f_ent)
   1636 {
   1637     int rv = BCM_E_NONE;
   1638     uint32 lt_id_mask = 0xFF;
   1639     _bcm_field_qual_offset_t q_offset;
   1640 
   1641     if (f_ent == NULL) {
   1642         return BCM_E_PARAM;
   1643     }
   1644 
   1645     if (f_ent->group->lt_id == -1) {
   1646         return BCM_E_INTERNAL;
   1647     }
   1648 
   1649     sal_memset(&q_offset, 0,
   1650             sizeof (_bcm_field_qual_offset_t));
   1651 
   1652     q_offset.field = KEYf;
   1653     q_offset.num_offsets = 1;
   1654     q_offset.offset[0] = 0;
   1655     q_offset.width[0] = 8;
   1656     q_offset.qual_width = 8;
   1657 
   1658     BCM_IF_ERROR_RETURN(_bcm_field_qual_value_set(unit, &q_offset,
   1659             f_ent, (uint32 *)&f_ent->group->lt_id, &lt_id_mask));
   1660 
   1661     return rv;
   1662 }
   1663 
   1664 /*
   1665  * Function:
   1666  *    _field_hx5_ft_entry_policy_mem_install
   1667  *
   1668  * Purpose:
   1669  *    Installs policy hw table for entry.
   1670  *
   1671  * Parameters:
   1672  *    unit       - (IN) BCM device number.
   1673  *    f_ent      - (IN) field entry structure.
   1674  *    policy_mem - (IN) policy hw table
   1675  *    tcam_idx   - (IN) Index in policy table
   1676  *
   1677  * Returns:
   1678  *    BCM_E_PARAM       - Null field stage control structure.
   1679  *    BCM_E_INTERNAL    - Invalid CAP Stage ID.
   1680  *    BCM_E_NONE        - Success.
   1681  */
   1682 int
   1683 _field_hx5_ft_entry_policy_mem_install(int unit,
   1684                                        _field_entry_t *f_ent,
   1685                                        soc_mem_t policy_mem,
   1686                                        int tcam_idx)
   1687 {
   1688     int rv = BCM_E_NONE;
   1689     uint32 e_buf[SOC_MAX_MEM_FIELD_WORDS] = {0};
   1690 
   1691     /* Validate input params */
   1692     if ((f_ent == NULL) || (policy_mem == INVALIDm) || (tcam_idx == -1)) {
   1693         return BCM_E_PARAM;
   1694     }
   1695 
   1696     /* Read policy memory */
   1697     rv = soc_mem_read(unit, policy_mem, MEM_BLOCK_ANY, tcam_idx, e_buf);
   1698     BCM_IF_ERROR_RETURN(rv);
   1699 
   1700     /* Set policy buffer */
   1701     rv = _field_hx5_ft_entry_policy_set(unit, f_ent, policy_mem, e_buf);
   1702     BCM_IF_ERROR_RETURN(rv);
   1703 
   1704     /* Write to hardware */
   1705     rv = soc_mem_write(unit, policy_mem, MEM_BLOCK_ALL, tcam_idx, e_buf);
   1706     return rv;
   1707 
   1708 }
   1709 
   1710 /*
   1711  * Function:
   1712  *    _field_ft_entry_tcam_policy_install
   1713  *
   1714  * Purpose:
   1715  *    Installs tcam + policy hw tables for entry.
   1716  *
   1717  * Parameters:
   1718  *    unit       - (IN) BCM device number.
   1719  *    f_ent      - (IN) field entry structure.
   1720  *    tcam_idx   - (IN) Index in tcam table
   1721  *
   1722  * Returns:
   1723  *    BCM_E_PARAM       - Null field stage control structure.
   1724  *    BCM_E_INTERNAL    - Invalid CAP Stage ID.
   1725  *    BCM_E_NONE        - Success.
   1726  */
   1727 int
   1728 _field_hx5_ft_entry_tcam_policy_install(int unit,
   1729                                         _field_entry_t *f_ent,
   1730                                         int tcam_idx)
   1731 {
   1732     int rv = BCM_E_NONE;
   1733     soc_mem_t tcam_mem = INVALIDm;
   1734     soc_mem_t policy_mem = INVALIDm;
   1735     uint32 entry_buf[SOC_MAX_MEM_FIELD_WORDS] = {0};
   1736 
   1737     if (f_ent == NULL) {
   1738         return (BCM_E_PARAM);
   1739     }
   1740 
   1741     /* Get the combo TCAM+Policy */
   1742     rv = _bcm_field_hx5_ft_tcam_policy_mem_get(unit, &tcam_mem, &policy_mem);
   1743     BCM_IF_ERROR_RETURN(rv);
   1744 
   1745     if ((tcam_idx < soc_mem_index_min(unit, tcam_mem)) ||
   1746         (tcam_idx > soc_mem_index_max(unit, tcam_mem))) {
   1747         return (BCM_E_PARAM);
   1748     }
   1749 
   1750     rv = soc_mem_read(unit, tcam_mem, MEM_BLOCK_ANY,
   1751                 tcam_idx, entry_buf);
   1752     BCM_IF_ERROR_RETURN(rv);
   1753 
   1754     /* Set Policy data buffer */
   1755     rv = _field_hx5_ft_entry_policy_mem_install(unit, f_ent, policy_mem, tcam_idx);
   1756     if (BCM_FAILURE(rv))  {
   1757         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META(
   1758                 "Failed to Install Policy Table for Entry[%d]"
   1759                 " tcam_idx:[%d].\n\r"),
   1760                 f_ent->eid, tcam_idx));
   1761         return rv;
   1762     }
   1763 
   1764     /* Set Qualifier for TCAM Table */
   1765     rv = _field_hx5_ft_entry_qual_tcam_set(unit, f_ent, tcam_mem,
   1766                     tcam_idx, entry_buf);
   1767 
   1768     /* Write to h/w Table */
   1769     if (BCM_SUCCESS(rv)) {
   1770         soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL,
   1771                 tcam_idx, entry_buf);
   1772 
   1773         /* Increment the HW Slice entry count */
   1774         f_ent->fs->hw_ent_count++;
   1775 
   1776         LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1777             "==> %s(): Entry[%d] Installed - mem:%d tcam_idx:%d slice:%d\n\r"),
   1778             __func__, f_ent->eid, tcam_mem, tcam_idx, f_ent->fs->slice_number));
   1779     } else {
   1780        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META(
   1781                  "Failed to Install the TCAM Entry[%d] tcam_idx:[%d].\n\r"),
   1782                  f_ent->eid, tcam_idx));
   1783     }
   1784 
   1785     return rv;
   1786 }
   1787 
   1788 /*
   1789  * Function:
   1790  *    _bcm_field_hx5_ft_entry_move
   1791  *
   1792  * Purpose:
   1793  *    Move tcam entry to new index
   1794  *
   1795  * Parameters:
   1796  *    unit       - (IN) BCM device number.
   1797  *    f_ent      - (IN) field entry structure.
   1798  *    parts_count- (IN) Number of parts of entry.
   1799  *    tcam_idx_old- (IN) Old tcam Indices of entry
   1800  *    tcam_idx_new- (IN) New tcam Indices of entry
   1801  *
   1802  * Returns:
   1803  *    BCM_E_PARAM       - Null field stage control structure.
   1804  *    BCM_E_INTERNAL    - Invalid CAP Stage ID.
   1805  *    BCM_E_NONE        - Success.
   1806  */
   1807 int
   1808 _bcm_field_hx5_ft_entry_move(int unit,
   1809                              _field_entry_t *f_ent,
   1810                              int parts_count,
   1811                              int *tcam_idx_old,
   1812                              int *tcam_idx_new)
   1813 {
   1814     int rv = BCM_E_NONE;
   1815     int part = 0;
   1816     int is_backup_entry = 0;
   1817     soc_mem_t tcam_mem = INVALIDm;
   1818     soc_mem_t policy_mem = INVALIDm;
   1819     int new_slice_numb = 0;
   1820     int new_slice_idx = 0;
   1821     int tcam_idx_min = 0, tcam_idx_max = 0;
   1822     uint32 entry_buf[SOC_MAX_MEM_FIELD_WORDS] = {0};
   1823     _field_slice_t *fs = NULL;
   1824     _field_stage_t *stage_fc = NULL;
   1825 
   1826     if ((f_ent == NULL) || (tcam_idx_old == NULL) || (tcam_idx_new == NULL)) {
   1827         return (BCM_E_PARAM);
   1828     }
   1829 
   1830     rv = _field_stage_control_get(unit, f_ent->group->stage_id, &stage_fc);
   1831     BCM_IF_ERROR_RETURN(rv);
   1832 
   1833     /* Get entry tcam and actions. */
   1834     rv = _bcm_field_hx5_ft_tcam_policy_mem_get(unit, &tcam_mem, &policy_mem);
   1835     BCM_IF_ERROR_RETURN(rv);
   1836 
   1837     /* Sanity check for index */
   1838     tcam_idx_max = soc_mem_index_max(unit, tcam_mem);
   1839     tcam_idx_min = soc_mem_index_min(unit, tcam_mem);
   1840 
   1841     for (part = 0; part < parts_count; part++) {
   1842         if ((tcam_idx_old[part] > tcam_idx_max) ||
   1843             (tcam_idx_old[part] < tcam_idx_min) ||
   1844             (tcam_idx_new[part] > tcam_idx_max) ||
   1845             (tcam_idx_new[part] < tcam_idx_min)) {
   1846             return (BCM_E_PARAM);
   1847         }
   1848     }
   1849 
   1850     if ((NULL != f_ent->ent_copy) &&
   1851             (f_ent->ent_copy->eid ==  _FP_INTERNAL_RESERVED_ID)) {
   1852         is_backup_entry = 1;
   1853     }
   1854 
   1855     /* Write to destination */
   1856     for (part = parts_count - 1; part >= 0; part--) {
   1857         if (part == 0) {
   1858             sal_memset(entry_buf, 0 , sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS);
   1859 
   1860             rv = soc_mem_read(unit, policy_mem, MEM_BLOCK_ANY,
   1861                         tcam_idx_old[part], entry_buf);
   1862             BCM_IF_ERROR_RETURN(rv);
   1863 
   1864             /* Write duplicate  tcam entry to new tcam index. */
   1865             rv = soc_mem_write(unit, policy_mem, MEM_BLOCK_ALL,
   1866                         tcam_idx_new[part], entry_buf);
   1867             BCM_IF_ERROR_RETURN(rv);
   1868         }
   1869 
   1870         sal_memset(entry_buf, 0 , sizeof(uint32) * SOC_MAX_MEM_FIELD_WORDS);
   1871 
   1872         rv = soc_mem_read(unit, tcam_mem, MEM_BLOCK_ANY,
   1873                 tcam_idx_old[part], entry_buf);
   1874         BCM_IF_ERROR_RETURN(rv);
   1875 
   1876         /* Write duplicate  tcam entry to new tcam index. */
   1877         rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL,
   1878                 tcam_idx_new[part], entry_buf);
   1879         BCM_IF_ERROR_RETURN(rv);
   1880     }
   1881 
   1882     for (part = 0; part < parts_count; part++) {
   1883         /* Calculate entry new slice & offset in the slice. */
   1884         rv = _bcm_field_tcam_idx_to_slice_offset (unit, stage_fc,
   1885                 f_ent->group->instance,
   1886                 tcam_idx_new[part],
   1887                 &new_slice_numb,
   1888                 &new_slice_idx);
   1889         BCM_IF_ERROR_RETURN(rv);
   1890         fs = &stage_fc->slices[f_ent->group->instance][new_slice_numb];
   1891         fs->hw_ent_count++;
   1892 
   1893        /*
   1894         * fp_entry_move is invoked even for backup entry create
   1895         * to copy TCAM and FP_POLICY_TABLE tables. In this case
   1896         * TCAM and FP_POLICY_TABLEs should not be erased for
   1897         * original entry.
   1898         */
   1899        if (1 != is_backup_entry) {
   1900            /*
   1901             * Clear old location
   1902             */
   1903            rv = _bcm_field_th_tcam_policy_clear(unit, f_ent,
   1904                    tcam_idx_old[part]);
   1905            BCM_IF_ERROR_RETURN(rv);
   1906        }
   1907     }
   1908 
   1909     return rv;
   1910 }
   1911 
   1912 /*
   1913  * Function:
   1914  *    _bcm_field_hx5_ft_tcam_policy_clear
   1915  *
   1916  * Purpose:
   1917  *    Clears hw table at given index.
   1918  *
   1919  * Parameters:
   1920  *    unit       - (IN) BCM device number.
   1921  *    f_ent      - (IN) field entry structure.
   1922  *    tcam_idx   - (IN) tcam index.
   1923  *
   1924  * Returns:
   1925  *    BCM_E_PARAM       - Null field stage control structure.
   1926  *    BCM_E_INTERNAL    - Invalid CAP Stage ID.
   1927  *    BCM_E_NONE        - Success.
   1928  */
   1929 int
   1930 _bcm_field_hx5_ft_tcam_policy_clear(int unit,
   1931                                     _field_entry_t *f_ent,
   1932                                     int tcam_idx)
   1933 {
   1934     int rv = BCM_E_NONE;
   1935     soc_mem_t tcam_mem = INVALIDm;
   1936     soc_mem_t policy_mem = INVALIDm;
   1937     uint32 null_buf[SOC_MAX_MEM_FIELD_WORDS] = {0};
   1938 
   1939     rv = _bcm_field_hx5_ft_tcam_policy_mem_get(unit, &tcam_mem, &policy_mem);
   1940     BCM_IF_ERROR_RETURN(rv);
   1941 
   1942     if (tcam_idx > soc_mem_index_max(unit, tcam_mem)) {
   1943         return BCM_E_PARAM;
   1944     }
   1945 
   1946     SOC_IF_ERROR_RETURN(soc_mem_write(unit, tcam_mem,
   1947                 MEM_BLOCK_ALL, tcam_idx, null_buf));
   1948 
   1949     SOC_IF_ERROR_RETURN(soc_mem_write(unit, policy_mem,
   1950                 MEM_BLOCK_ALL, tcam_idx, null_buf));
   1951     return rv;
   1952 }
   1953 
   1954 /*
   1955  * Function:
   1956  *    _field_hx5_ft_stage_entry_enable_set
   1957  *
   1958  * Purpose:
   1959  *     Enable/Disable an entry from the hardware tables.
   1960  *
   1961  * Parameters:
   1962  *     unit        - (IN) BCM device number
   1963  *     f_ent       - (IN) Reference to Entry structure
   1964  *     enable_flag - (IN) Flag to enable or disable
   1965  *
   1966  * Returns:
   1967  *     BCM_E_XXX
   1968  *
   1969  * Notes:
   1970  *     This does not destroy the entry, nor deallocate any related resources;
   1971  *     it only enables/disables a rule from hardware table using VALIDf of the
   1972  *     corresponding hardware entry. To deallocate the memory used by the entry
   1973  *     call bcm_field_entry_destroy.
   1974  */
   1975 int
   1976 _field_hx5_ft_stage_entry_enable_set(int unit,
   1977                                      _field_entry_t *f_ent,
   1978                                      int enable_flag)
   1979 {
   1980     int rv = BCM_E_NONE;
   1981     int part = 0, parts_count = 0;
   1982     _field_group_t *fg = NULL;
   1983 
   1984     fg = f_ent->group;
   1985 
   1986     /* Get number of parts */
   1987     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
   1988                                             fg->flags, &parts_count);
   1989     for (part = 0; part < parts_count; part++) {
   1990         rv = _field_th_stage_entry_enable_set(unit, &f_ent[part], enable_flag);
   1991     }
   1992 
   1993     return rv;
   1994 }
   1995 
   1996 /*
   1997  * Function:
   1998  *    _bcm_field_hx5_ft_action_params_check
   1999  *
   2000  * Purpose:
   2001  *    Verifies action to be associated with entry.
   2002  *
   2003  * Parameters:
   2004  *    unit       - (IN) BCM device number.
   2005  *    f_ent      - (IN) field entry structure.
   2006  *    fa         - (IN) field action structure.
   2007  *
   2008  * Returns:
   2009  *    BCM_E_PARAM       - Null field stage control structure.
   2010  *    BCM_E_INTERNAL    - Invalid CAP Stage ID.
   2011  *    BCM_E_NONE        - Success.
   2012  */
   2013 int
   2014 _bcm_field_hx5_ft_action_params_check(int unit,
   2015                                      _field_entry_t *f_ent,
   2016                                      _field_action_t *fa)
   2017 {
   2018     int rv = BCM_E_NONE;
   2019     bcm_flowtracker_group_t id = 0;
   2020     _field_action_t *fa_iter = NULL;
   2021 
   2022     if (f_ent->group->stage_id != _BCM_FIELD_STAGE_FLOWTRACKER) {
   2023         return BCM_E_NONE;
   2024     }
   2025 
   2026     fa_iter = f_ent->actions;
   2027     while(fa_iter != NULL) {
   2028         if (fa_iter->flags & _FP_ACTION_VALID) {
   2029             if ((fa->action == bcmFieldActionFlowtrackerNewLearnEnable) &&
   2030                     (fa_iter->action == bcmFieldActionFlowtrackerGroupId)) {
   2031                 id = fa_iter->param[0];
   2032                 if (BCMI_FT_GROUP(unit, id)->flags
   2033                         & BCM_FLOWTRACKER_GROUP_USER_ENTRIES_ONLY) {
   2034                     return BCM_E_CONFIG;
   2035                 }
   2036             } else if ((fa->action == bcmFieldActionFlowtrackerGroupId) &&
   2037                     (fa_iter->action == bcmFieldActionFlowtrackerNewLearnEnable)) {
   2038                 id = fa->param[0];
   2039                 if (BCMI_FT_GROUP(unit, id)->flags
   2040                         & BCM_FLOWTRACKER_GROUP_USER_ENTRIES_ONLY) {
   2041                     return BCM_E_CONFIG;
   2042                 }
   2043             }
   2044         }
   2045         fa_iter = fa_iter->next;
   2046     }
   2047 
   2048     switch(fa->action) {
   2049         case bcmFieldActionFlowtrackerGroupId:
   2050             id = fa->param[0];
   2051 
   2052             /* Check FT module compliance */
   2053             rv = bcmi_ft_group_entry_add_check(unit, id);
   2054             break;
   2055 
   2056         case bcmFieldActionFlowtrackerEnable:
   2057         case bcmFieldActionFlowtrackerNewLearnEnable:
   2058             if (fa->param[0] > 1) {
   2059                 LOG_ERROR(BSL_LS_BCM_FP,
   2060                         (BSL_META_U(unit, "FP(unit %d) Error: Incorrect"
   2061                                     " argument passed.\r\n"), unit));
   2062                 rv = BCM_E_PARAM;
   2063             }
   2064             break;
   2065         default:
   2066             break;
   2067     }
   2068 
   2069     return rv;
   2070 }
   2071 
   2072 /*
   2073  * Function:
   2074  *    _bcm_field_hx5_ft_group_aset_update
   2075  *
   2076  * Purpose:
   2077  *    Updates aset of field group.
   2078  *
   2079  * Parameters:
   2080  *    unit       - (IN) BCM device number.
   2081  *    fg         - (IN) field group structure.
   2082  *    aset       - (IN) New action set structure.
   2083  *
   2084  * Returns:
   2085  *    BCM_E_PARAM       - Wrong input argument.
   2086  *    BCM_E_UNAVAIL     - Incoming Action is not supported.
   2087  *    BCM_E_NONE        - Success.
   2088  */
   2089 int
   2090 _bcm_field_hx5_ft_group_aset_update(int unit,
   2091                                     _field_group_t *fg,
   2092                                     bcm_field_aset_t *aset)
   2093 {
   2094     int a_idx = 0;
   2095     int aset_diff = FALSE;
   2096     _bcm_field_aset_t aset_modified;
   2097 
   2098     if ((fg == NULL) || (aset == NULL)) {
   2099         return BCM_E_PARAM;
   2100     }
   2101 
   2102     /* Copy original aset of field group */
   2103     sal_memcpy(&aset_modified, &fg->aset, sizeof(_bcm_field_aset_t));
   2104 
   2105     /* Set new actions to aset */
   2106     for (a_idx = 0; a_idx < bcmFieldActionCount; a_idx++) {
   2107         if (BCM_FIELD_ASET_TEST(*aset, a_idx)) {
   2108             if (!_field_stage_action_support_check(unit, fg, a_idx)) {
   2109                 LOG_ERROR(BSL_LS_BCM_FP,
   2110                         (BSL_META_U(unit, "FP(unit %d) Error: action =%s is"
   2111                                     " not supported for given group stage.\n"),
   2112                          unit, _field_action_name(a_idx)));
   2113                 return BCM_E_UNAVAIL;
   2114             }
   2115             if (!BCM_FIELD_ASET_TEST(fg->aset, a_idx)) {
   2116                 BCM_FIELD_ASET_ADD(aset_modified, a_idx);
   2117                 aset_diff = TRUE;
   2118             }
   2119         }
   2120     }
   2121 
   2122     /* Copy modified aset to field group aset */
   2123     if (aset_diff == TRUE) {
   2124         sal_memcpy(&fg->aset, &aset_modified, sizeof(_bcm_field_aset_t));
   2125     }
   2126 
   2127     return BCM_E_NONE;
   2128 }
   2129 
   2130 /*
   2131  * Function:
   2132  *    _bcm_field_hx5_ft_group_hw_alloc
   2133  *
   2134  * Purpose:
   2135  *    If flowtracker group id is associated with the entry,
   2136  *    flowtracker APIs are called to install SESSION_KEY/DATA,
   2137  *    flowtracker ALUs and other hardware tables.
   2138  *
   2139  * Parameters:
   2140  *    unit       - (IN) BCM device number.
   2141  *    f_ent      - (In) Field entry structure.
   2142  *
   2143  * Returns:
   2144  *    BCM_E_XXX
   2145  */
   2146 int
   2147 _bcm_field_hx5_ft_group_hw_alloc(int unit,
   2148                                 _field_entry_t *f_ent)
   2149 {
   2150     int rv = BCM_E_NONE;
   2151     int num_key_info = 0;
   2152     bcm_flowtracker_group_t id = -1;
   2153     int ref_count = 0;
   2154     _field_action_t *fa = NULL;
   2155     bcmi_ft_session_profiles_t profiles;
   2156 
   2157     if (f_ent->group->stage_id != _BCM_FIELD_STAGE_FLOWTRACKER) {
   2158         return BCM_E_NONE;
   2159     }
   2160 
   2161     sal_memset(&profiles, 0, sizeof(bcmi_ft_session_profiles_t));
   2162 
   2163      for (fa = f_ent->actions;
   2164             (fa != NULL) && (fa->flags & _FP_ACTION_VALID);
   2165             fa = fa->next) {
   2166          if (fa->action != bcmFieldActionFlowtrackerGroupId) {
   2167              continue;
   2168          }
   2169          if (!(fa->flags & _FP_ACTION_DIRTY)) {
   2170              continue;
   2171          }
   2172 
   2173          fa->old_index = fa->hw_index;
   2174          id = fa->param[0];
   2175 
   2176          /* Get reference count */
   2177          BCM_IF_ERROR_RETURN(
   2178                  bcmi_esw_ft_group_param_retrieve(unit, id,
   2179                      bcmiFtGroupParamFtfpEntryNum, &ref_count));
   2180          if (ref_count == 0) {
   2181              /* Check Ft Group tracking params extraction */
   2182              rv = bcmi_esw_ft_group_extraction_alu_info_get(unit,
   2183                      id, 1, 0, NULL, &num_key_info);
   2184              if ((rv != BCM_E_NONE) || (num_key_info == 0)) {
   2185                  return BCM_E_CONFIG;
   2186              }
   2187          }
   2188          /* Increment reference count */
   2189          if (BCM_SUCCESS(rv)) {
   2190              rv = bcmi_esw_ft_group_param_update(unit, id,
   2191                      bcmiFtGroupParamFtfpEntryNum,
   2192                      bcmiFtGroupParamsOprInc, 1);
   2193          }
   2194          fa->hw_index = id;
   2195      }
   2196 
   2197     return (rv);
   2198 }
   2199 
   2200 /*
   2201  * Function:
   2202  *    _bcm_field_hx5_ft_group_hw_free
   2203  *
   2204  * Purpose:
   2205  *    If flowtracker group id is dis-associated from the entry,
   2206  *    flowtracker APIs are called to clear SESSION_KEY/DATA,
   2207  *    flowtracker ALUs and other hardware tables.
   2208  *
   2209  * Parameters:
   2210  *    unit       - (IN) BCM device number.
   2211  *    f_ent      - (In) Field entry structure.
   2212  *
   2213  * Returns:
   2214  *    BCM_E_XXX
   2215  */
   2216 int
   2217 _bcm_field_hx5_ft_group_hw_free(int unit,
   2218                                 _field_entry_t *f_ent,
   2219                                 int flags)
   2220 {
   2221     uint16 id = 0;
   2222     _field_action_t *fa = NULL;
   2223     bcmi_ft_session_profiles_t profiles;
   2224 
   2225     if (f_ent->group->stage_id != _BCM_FIELD_STAGE_FLOWTRACKER) {
   2226         return BCM_E_NONE;
   2227     }
   2228 
   2229     sal_memset(&profiles, 0, sizeof(bcmi_ft_session_profiles_t));
   2230 
   2231     for (fa = f_ent->actions; NULL != fa; fa = fa->next) {
   2232         if (bcmFieldActionFlowtrackerGroupId != fa->action) {
   2233             continue;
   2234         }
   2235         if (fa->flags & _BCM_FIELD_ACTION_REF_STALE) {
   2236             /* Flowtracker Group is Stale */
   2237             continue;
   2238         }
   2239         if ((flags & _FP_ACTION_OLD_RESOURCE_FREE) &&
   2240                 (fa->old_index != _FP_INVALID_INDEX)) {
   2241             id = fa->old_index;
   2242             /* Decrement reference count */
   2243             BCM_IF_ERROR_RETURN(
   2244                     bcmi_esw_ft_group_param_update(unit,
   2245                         id, bcmiFtGroupParamFtfpEntryNum,
   2246                         bcmiFtGroupParamsOprDec, 1));
   2247             fa->old_index = _FP_INVALID_INDEX;
   2248         }
   2249         if ((flags & _FP_ACTION_RESOURCE_FREE) &&
   2250                 (fa->hw_index != _FP_INVALID_INDEX)) {
   2251             id = fa->hw_index;
   2252             /* Decrement reference count */
   2253             BCM_IF_ERROR_RETURN(
   2254                     bcmi_esw_ft_group_param_update(unit, id,
   2255                         bcmiFtGroupParamFtfpEntryNum,
   2256                         bcmiFtGroupParamsOprDec, 1));
   2257             if (!(flags & _BCM_FIELD_ACTION_REF_STALE)) {
   2258                 fa->hw_index = _FP_INVALID_INDEX;
   2259             }
   2260         }
   2261         if (flags & _BCM_FIELD_ACTION_REF_STALE) {
   2262             fa->flags |= _BCM_FIELD_ACTION_REF_STALE;
   2263         }
   2264     }
   2265 
   2266     return (BCM_E_NONE);
   2267 }
   2268 
   2269 /*
   2270  * Function:
   2271  *    _bcm_field_hx5_hint_dosattack_event_flags
   2272  *
   2273  * Purpose:
   2274  *    Update qual_info for dos attack events when hint
   2275  *    is provided.
   2276  *
   2277  * Parameters:
   2278  *    unit       - (IN) BCM device number.
   2279  *    hint_node  - (IN) hint structure.
   2280  *    qual_info  - (IN/OUT) Qualifier information for extraction.
   2281  *
   2282  * Returns:
   2283  *    BCM_E_XXX
   2284  */
   2285 int
   2286 _bcm_field_hx5_dosattack_event_qual_bitmap(int unit,
   2287                     _field_hint_t *hint_node,
   2288                     bcmi_keygen_qual_info_t *qual_info)
   2289 {
   2290     uint32 event_flags[1];
   2291     uint32 event_bit = 0, bit_pos = 0;
   2292     soc_field_t field = INVALIDf;
   2293     soc_format_t fmt = INVALIDfmt;
   2294     soc_field_info_t *field_info = NULL;
   2295 
   2296     if ((qual_info == NULL) || (hint_node == NULL)) {
   2297         return BCM_E_PARAM;
   2298     }
   2299 
   2300     event_flags[0] = hint_node->hint->dosattack_event_flags;
   2301 
   2302     SHR_BIT_ITER(event_flags, 32, event_bit) {
   2303         field = INVALIDf;
   2304         switch((1 << event_bit)) {
   2305             case BCM_FIELD_DOSATTACK_MACSA_DA_SAME:
   2306                 field = MACSA_EQ_MACDAf;
   2307                 break;
   2308             case BCM_FIELD_DOSATTACK_IPFRAG_OFFSET:
   2309                 field = IP_FRAG_OFFSET_VALUE_OF_1f;
   2310                 break;
   2311             case BCM_FIELD_DOSATTACK_V6_TYPE0_ROUTING_HDR:
   2312                 field = TYPE_ZERO_ROUTING_HDR_PRESENTf;
   2313                 break;
   2314             case BCM_FIELD_DOSATTACK_V6_NON_LAST_FRAG_LT_1280:
   2315                 field = V6_NON_LAST_FRAGMENT_SIZE_TOO_SMALLf;
   2316                 break;
   2317             case BCM_FIELD_DOSATTACK_FIRST_TCPIP_FRAG_SMALL:
   2318                 field = TCP_HDR_TOO_SMALLf;
   2319                 break;
   2320             case BCM_FIELD_DOSATTACK_TCP_OFFSET:
   2321                 field = TCP_FRAG_OFFSET_EQ_ONEf;
   2322                 break;
   2323             case BCM_FIELD_DOSATTACK_SYN_FRAG:
   2324                 field = TCP_FLAGS_SYN_EQ_ONE_ACK_EQ_ZERO_AND_SRC_PORT_LT_1024f;
   2325                 break;
   2326             case BCM_FIELD_DOSATTACK_FLAGZERO_SEQZERO:
   2327                 field = TCP_ALL_FLAGS_EQ_ZERO_AND_SEQNUM_EQ_ZEROf;
   2328                 break;
   2329             case BCM_FIELD_DOSATTACK_TCPFLAGS_FUP:
   2330                 field = TCP_FLAGS_FIN_URG_AND_PSH_EQ_ONE_AND_SEQNUM_EQ_ZEROf;
   2331                 break;
   2332             case BCM_FIELD_DOSATTACK_TCPFLAGS_SF:
   2333                 field = TCP_FLAGS_FIN_AND_SYN_EQ_ONEf;
   2334                 break;
   2335             case BCM_FIELD_DOSATTACK_TCPPORTS_EQUAL:
   2336                 field = TCP_SPORT_EQ_DPORTf;
   2337                 break;
   2338             case BCM_FIELD_DOSATTACK_UDPPORTS_EQUAL:
   2339                 field = UDP_SPORT_EQ_DPORTf;
   2340                 break;
   2341             case BCM_FIELD_DOSATTACK_ICMP:
   2342                 field = ICMP_ECHO_PKT_SIZE_TOO_BIGf;
   2343                 break;
   2344             case BCM_FIELD_DOSATTACK_ICMPFRAGMENTS:
   2345                 field = ICMP_FRAGMENTED_PKTf;
   2346                 break;
   2347             case BCM_FIELD_DOSATTACK_TCPFLAGS_SR:
   2348                 field = TCP_SYN_RSTf;
   2349                 break;
   2350             case BCM_FIELD_DOSATTACK_TCPFLAGS_SYN_FIRSTFRAG:
   2351                 field = TCP_SYN_FIRST_FRAGMENTf;
   2352                 break;
   2353             case BCM_FIELD_DOSATTACK_TCPFLAGS_FIN_NOACK:
   2354                 field = TCP_FIN_NO_ACKf;
   2355                 break;
   2356             case BCM_FIELD_DOSATTACK_TCPFLAGS_RST_NOACK:
   2357                 field = TCP_RST_NO_ACKf;
   2358                 break;
   2359             case BCM_FIELD_DOSATTACK_TCPFLAGS_NOSFRA:
   2360                 field = TCP_NO_SYN_FIN_RST_ACKf;
   2361                 break;
   2362             case BCM_FIELD_DOSATTACK_TCP_DSTPORT_ZERO:
   2363                 field = TCP_DPORT_ZEROf;
   2364                 break;
   2365             case BCM_FIELD_DOSATTACK_TCP_SRCPORT_ZERO:
   2366                 field = TCP_DPORT_ZEROf;
   2367                 break;
   2368             case BCM_FIELD_DOSATTACK_TCP_DST_IP_BCAST:
   2369                 field = TCP_IP_BROADCAST_CHECKf;
   2370                 break;
   2371             case BCM_FIELD_DOSATTACK_TCPFLAGS_ZERO:
   2372                 field = TCP_FLAG_ZEROf;
   2373                 break;
   2374             case BCM_FIELD_DOSATTACK_TCPFLAGS_RESVD_NONZERO:
   2375                 field = TCP_RESERVED_NON_ZEROf;
   2376                 break;
   2377             case BCM_FIELD_DOSATTACK_TCPFLAGS_ACK:
   2378                 field = TCP_ACK_ACKNUMBER_ZEROf;
   2379                 break;
   2380             case BCM_FIELD_DOSATTACK_TCPFLAGS_URG_NOURGPTR:
   2381                 field = TCP_URG_NO_URG_POINTERf;
   2382                 break;
   2383             case BCM_FIELD_DOSATTACK_TCPFLAGS_NOURG_URGPTR:
   2384                 field = TCP_NO_URG_URG_POINTERf;
   2385                 break;
   2386             case BCM_FIELD_DOSATTACK_TCPFLAGS_SYNOPTION:
   2387                 field = TCP_SYN_WITH_DATA_PAYLOADf;
   2388                 break;
   2389             default:
   2390                 return BCM_E_PARAM;
   2391         }
   2392 
   2393         fmt = HVE_DOS_ATTACK_RESULTS_FORMATfmt;
   2394         if (soc_format_field_valid(unit, fmt, field) == FALSE) {
   2395             return BCM_E_PARAM;
   2396         }
   2397         field_info = soc_format_fieldinfo_get(unit, fmt, field);
   2398         bit_pos = field_info->bp;
   2399 
   2400         SHR_BITSET(qual_info->bitmap, bit_pos);
   2401     }
   2402     qual_info->partial = TRUE;
   2403 
   2404     return BCM_E_NONE;
   2405 }
   2406 
   2407 /******************* Extraction *****************************/
   2408 /*
   2409  * Function:
   2410  *    _field_offset_part_get
   2411  *
   2412  * Purpose:
   2413  *    Returns group part number for given offset in keygen context.
   2414  *
   2415  * Parameters:
   2416  *    offset_arr - (IN) Offset array in keygen context.
   2417  *    index      - (IN) Index in offset array.
   2418  *    part       - (OUT) pointer to part.
   2419  *
   2420  * Returns:
   2421  *    BCM_E_INTERNAL    - Incorrect arguments.
   2422  *    BCM_E_NONE        - Success.
   2423  */
   2424 STATIC int
   2425 _field_offset_part_get(bcmi_keygen_qual_offset_t *offset_arr,
   2426             uint8 index, int *part)
   2427 {
   2428     int rv = BCM_E_NONE;
   2429 
   2430     if ((offset_arr == NULL) || (part == NULL)) {
   2431         return BCM_E_PARAM;
   2432     }
   2433 
   2434     if (index < BCMI_KEYGEN_QUAL_OFFSETS_MAX) {
   2435         *part = offset_arr->offset[index] / 180;
   2436     } else {
   2437         rv = BCM_E_INTERNAL;
   2438     }
   2439 
   2440     return rv;
   2441 }
   2442 
   2443 /*
   2444  * Function:
   2445  *    _field_hx5_ft_qual_offset_split_req
   2446  *
   2447  * Purpose:
   2448  *    Checks if spliting is required in given offset_info
   2449  *    at given offset.
   2450  *
   2451  * Parameters:
   2452  *    uint       - (IN) Device Unit.
   2453  *    offset_arr - (IN) Offset array in keygen context.
   2454  *    offset     - (IN) Offset to verify
   2455  *    split_pos  - (OUT) Split bit position
   2456  *
   2457  * Returns:
   2458  *    TRUE       - Splitting is required.
   2459  *    FALSE      - Splitting is not required.
   2460  */
   2461 STATIC int
   2462 _field_hx5_ft_qual_offset_split_req(int unit,
   2463         bcmi_keygen_qual_offset_t *offset_arr,
   2464         int offset,
   2465         int *split_pos)
   2466 {
   2467     int q_offset = 0;
   2468     int width = 0;
   2469 
   2470     q_offset = offset_arr->offset[offset];
   2471     width = offset_arr->width[offset];
   2472 
   2473     if ((q_offset < 180) && (q_offset + width) > 180) {
   2474         if (split_pos != NULL) {
   2475             *split_pos = 180;
   2476         }
   2477         return TRUE;
   2478     }
   2479 
   2480     return FALSE;
   2481 }
   2482 
   2483 /*
   2484  * Function:
   2485  *    _field_hx5_ft_qual_offset_arr_split
   2486  *
   2487  * Purpose:
   2488  *    Split offset info info 2 parts if group_part boundary
   2489  *    lies in-between the qualifier offsets.
   2490  *
   2491  * Parameters:
   2492  *    uint       - (IN) Unit
   2493  *    split_idx  - (IN) Qualifier offset which requires splitting.
   2494  *    qual_offset_info - (IN/OUT) qualifier offset info
   2495  *
   2496  * Returns:
   2497  *    BCM_E_XXX
   2498  *
   2499  * Notes:
   2500  *    In Flowtracker, keygen types A/A/B are 128 bits in size. But,
   2501  *    double-wide group mode is 360 bits with 180 bits in either
   2502  *    parts. Due to this unsymmetry in keygen type bit size and
   2503  *    group parts size, it can happen that 180 bit part boundary
   2504  *    lies in-between offset info in at max 1 qualifier. So, it
   2505  *    is required to split that offset_arr into 2 parts for
   2506  *    correct population of group_qual info.
   2507  */
   2508 STATIC int
   2509 _field_hx5_ft_qual_offset_arr_split(int unit,
   2510             int split_idx,
   2511             _field_ft_qual_ext_offset_info_t *qual_ext_offset_info)
   2512 {
   2513     int rv = BCM_E_NONE;
   2514     int width = 0;
   2515     int offset = 0;
   2516     int q_offset = 0;
   2517     int ext_num = 0;
   2518     int split_offset = 0;
   2519     int num_offsets = 0;
   2520     int split_pos = 0;
   2521     _field_ft_qual_sel_t *sel_offset_arr = NULL;
   2522     bcmi_keygen_qual_offset_t *offset_arr = NULL;
   2523 
   2524     offset_arr = qual_ext_offset_info->offset_arr;
   2525     sel_offset_arr = qual_ext_offset_info->sel_offset_arr;
   2526 
   2527     /* Search for split offset */
   2528     for (offset = 0; offset < BCMI_KEYGEN_QUAL_OFFSETS_MAX; offset++) {
   2529         if (!offset_arr[split_idx].width[offset]) {
   2530             continue;
   2531         }
   2532         if (_field_hx5_ft_qual_offset_split_req(unit,
   2533                     &offset_arr[split_idx], offset, &split_pos) == TRUE) {
   2534             split_offset = offset;
   2535             width = offset_arr[split_idx].width[offset];
   2536             q_offset = offset_arr[split_idx].offset[offset];
   2537             ext_num = sel_offset_arr[split_idx].ext_num[offset];
   2538             break;
   2539         }
   2540         num_offsets++;
   2541         if (num_offsets == offset_arr[split_idx].num_offsets) {
   2542             break;
   2543         }
   2544     }
   2545 
   2546     /* Split */
   2547     if (num_offsets < offset_arr[split_idx].num_offsets) {
   2548         if (((split_offset + 1) >= BCMI_KEYGEN_QUAL_OFFSETS_MAX) ||
   2549             (offset_arr[split_idx].width[BCMI_KEYGEN_QUAL_OFFSETS_MAX - 1])) {
   2550             /* Cannot split, not enough free indices */
   2551             return BCM_E_INTERNAL;
   2552         }
   2553         for (offset = (BCMI_KEYGEN_QUAL_OFFSETS_MAX - 1);
   2554             offset > split_offset; offset--) {
   2555             offset_arr[split_idx].offset[offset] =
   2556                 offset_arr[split_idx].offset[offset - 1];
   2557             offset_arr[split_idx].width[offset] =
   2558                 offset_arr[split_idx].width[offset - 1];
   2559             sel_offset_arr[split_idx].ext_num[offset] =
   2560                 sel_offset_arr[split_idx].ext_num[offset - 1];
   2561         }
   2562 
   2563         width = (q_offset + width) - split_pos;
   2564         offset_arr[split_idx].offset[split_offset] = q_offset;
   2565         offset_arr[split_idx].width[split_offset] = split_pos - q_offset;
   2566         sel_offset_arr[split_idx].ext_num[split_offset] = ext_num;
   2567         offset_arr[split_idx].offset[split_offset + 1] = split_pos;
   2568         offset_arr[split_idx].width[split_offset + 1] = width;
   2569         sel_offset_arr[split_idx].ext_num[split_offset + 1] = ext_num;
   2570 
   2571         offset_arr[split_idx].num_offsets += 1;
   2572         sel_offset_arr[split_idx].num_offsets += 1;
   2573     }
   2574 
   2575     return rv;
   2576 }
   2577 
   2578 /*
   2579  * Function:
   2580  *    _bcm_field_hx5_ft_keygen_extractors_mask_set
   2581  *
   2582  * Purpose:
   2583  *    Extractor mask memory are calculated based on
   2584  *    extractors codes and qualifier offsets/width.
   2585  *
   2586  * Parameters:
   2587  *    uint       - (IN) Unit
   2588  *    qual_ext_offset_info - (IN) qualifier offset info
   2589  *    ext_codes  - (IN/OUT) Extractors code.
   2590  *
   2591  * Returns:
   2592  *    BCM_E_XXX
   2593  *
   2594  * Notes:
   2595  *    In flowtracker, keygen type A has 128 bits of mask. This mask
   2596  *    needs to be calculated based onn extractor codes and qualifier
   2597  *    offset/width pair.
   2598  *    Shift_offsets are first calculated to get correct shifted
   2599  *    offsets of qualifier offsets.
   2600  */
   2601 int
   2602 _bcm_field_hx5_ft_keygen_extractors_mask_set(int unit,
   2603         _field_ft_qual_ext_offset_info_t *qual_ext_offset_info,
   2604         _field_ft_keygen_ext_codes_t *ext_codes)
   2605 {
   2606     int rv = BCM_E_NONE;
   2607     int qual_idx = 0;
   2608     int q_offset = 0;
   2609     int q_width = 0;
   2610     int ext_num = 0;
   2611     int num_offsets = 0;
   2612     int offset = 0;
   2613     int shift_offsets_arr[30] = {0};
   2614 
   2615     (void) _field_hx5_ft_keygen_ext_shift_offsets_get(unit,
   2616             ext_codes, &shift_offsets_arr[0]);
   2617 
   2618     while(qual_idx < qual_ext_offset_info->size) {
   2619         num_offsets = 0;
   2620         for (offset = 0; offset < BCMI_KEYGEN_QUAL_OFFSETS_MAX; offset++) {
   2621             if (!qual_ext_offset_info->offset_arr[qual_idx].width[offset]) {
   2622                 continue;
   2623             }
   2624 
   2625             q_offset = qual_ext_offset_info->offset_arr[qual_idx].offset[offset];
   2626             q_width = qual_ext_offset_info->offset_arr[qual_idx].width[offset];
   2627             ext_num = qual_ext_offset_info->sel_offset_arr[qual_idx].ext_num[offset];
   2628 
   2629             BCM_IF_ERROR_RETURN(
   2630                 _bcm_field_ft_keygen_profile_extractors_mask_set(unit,
   2631                         q_offset, q_width, ext_num, shift_offsets_arr, ext_codes));
   2632 
   2633             num_offsets++;
   2634             if (num_offsets ==
   2635                     qual_ext_offset_info->offset_arr[qual_idx].num_offsets) {
   2636                 break;
   2637             }
   2638         }
   2639         qual_idx++;
   2640     }
   2641 
   2642     return rv;
   2643 }
   2644 
   2645 /*
   2646  * Function:
   2647  *    _field_hx5_ft_qual_offset_ext_shift_apply
   2648  *
   2649  * Purpose:
   2650  *    Updates offset values in qual_offset_info based on extractors
   2651  *    shift logic and group parts.
   2652  *
   2653  * Parameters:
   2654  *    uint       - (IN) Unit.
   2655  *    split_allowed - (IN) Check if we need to do split
   2656  *    ext_codes  - (IN) Extractors code.
   2657  *    qual_offset_info - (IN/OUT) qualifier offset info
   2658  *
   2659  * Returns:
   2660  *    BCM_E_XXX
   2661  */
   2662 int
   2663 _field_hx5_ft_qual_offset_ext_shift_apply(int unit,
   2664         int split_allowed,
   2665         _field_ft_keygen_ext_codes_t *ext_codes,
   2666         _field_ft_qual_ext_offset_info_t *qual_ext_offset_info)
   2667 {
   2668     int idx = 0;
   2669     int rv = BCM_E_NONE;
   2670     int offset = 0;
   2671     int q_offset = 0;
   2672     int shift_idx = 0;
   2673     int num_offsets = 0;
   2674     int offset_arr_split = FALSE;
   2675     int shift_offsets_arr[30] = {0};
   2676 
   2677     (void) _field_hx5_ft_keygen_ext_shift_offsets_get(unit,
   2678             ext_codes, &shift_offsets_arr[0]);
   2679 
   2680     idx = 0;
   2681     while (idx < qual_ext_offset_info->size) {
   2682         num_offsets = 0;
   2683         offset_arr_split = FALSE;
   2684         for (offset = 0; offset < BCMI_KEYGEN_QUAL_OFFSETS_MAX; offset++) {
   2685             if (!qual_ext_offset_info->offset_arr[idx].width[offset]) {
   2686                 continue;
   2687             }
   2688             q_offset = qual_ext_offset_info->offset_arr[idx].offset[offset];
   2689             shift_idx = q_offset / 16;
   2690             q_offset = (q_offset % 16) + shift_offsets_arr[shift_idx];
   2691             qual_ext_offset_info->offset_arr[idx].offset[offset] = q_offset;
   2692 
   2693             if (_field_hx5_ft_qual_offset_split_req(unit, &qual_ext_offset_info->
   2694                         offset_arr[idx], offset, NULL) == TRUE) {
   2695                 offset_arr_split = TRUE;
   2696             }
   2697             num_offsets++;
   2698             if (num_offsets ==
   2699                     qual_ext_offset_info->offset_arr[idx].num_offsets) {
   2700                 break;
   2701             }
   2702         }
   2703         if ((split_allowed) && (offset_arr_split)) {
   2704             BCM_IF_ERROR_RETURN(_field_hx5_ft_qual_offset_arr_split(unit,
   2705                         idx, qual_ext_offset_info));
   2706         }
   2707         idx++;
   2708     }
   2709 
   2710     return rv;
   2711 }
   2712 
   2713 /*
   2714  * Function:
   2715  *    _field_hx5_ft_group_keygen_ext_codes_set
   2716  *
   2717  * Purpose:
   2718  *   Extract flowtracker stage field group keygen extractor codes.
   2719  *
   2720  * Parameters:
   2721  *    unit       - (IN) BCM device number
   2722  *    fg         - (IN) Field group structure.
   2723  *    keygen_oper- (IN) Kegen operational structure.
   2724  *
   2725  * Returns:
   2726  *    BCM_E_MEMEORY     - Failed to allocate memory.
   2727  *    BCM_E_PARAM       - Input params is wrong.
   2728  *    BCM_E_NONE        - Success.
   2729  */
   2730 STATIC int
   2731 _field_hx5_ft_group_keygen_ext_codes_set(int unit,
   2732                                         _field_group_t *fg,
   2733                                         bcmi_keygen_oper_t *keygen_oper)
   2734 {
   2735     int rv = BCM_E_NONE;
   2736     int keygen_profile;
   2737     bcmi_keygen_ext_ctrl_sel_info_t *ext_ctrl_sel_info;
   2738     uint16 ext_ctrl_sel_info_count;
   2739     _field_ft_keygen_ext_codes_t *ext_codes = NULL;
   2740 
   2741     /* Validate input params. */
   2742     if ((fg == NULL) || (keygen_oper == NULL)) {
   2743         return BCM_E_PARAM;
   2744     }
   2745 
   2746     if (fg->ft_ext_codes == NULL) {
   2747         /* Allocate memory */
   2748         _FP_XGS3_ALLOC(ext_codes, sizeof(_field_ft_keygen_ext_codes_t),
   2749                 "field group ext codes");
   2750         if (ext_codes == NULL) {
   2751             return BCM_E_MEMORY;
   2752         }
   2753         (void) _bcm_field_ft_keygen_extractors_init(ext_codes);
   2754         keygen_profile = _BCM_FIELD_FT_KEYGEN_PROFILE_AAB;
   2755     } else {
   2756         ext_codes = fg->ft_ext_codes;
   2757         keygen_profile = ext_codes->keygen_profile;
   2758     }
   2759 
   2760     ext_ctrl_sel_info_count = keygen_oper->ext_ctrl_sel_info_count;
   2761     ext_ctrl_sel_info = keygen_oper->ext_ctrl_sel_info;
   2762 
   2763     rv = _bcm_field_hx5_ft_keygen_extractors_set(unit, keygen_profile,
   2764                 ext_ctrl_sel_info_count, ext_ctrl_sel_info, ext_codes);
   2765 
   2766     if (BCM_SUCCESS(rv)) {
   2767         fg->ft_ext_codes = ext_codes;
   2768     } else {
   2769         fg->ft_ext_codes = NULL;
   2770         sal_free(ext_codes);
   2771     }
   2772 
   2773     return rv;
   2774 }
   2775 
   2776 /*
   2777  * Function:
   2778  *    _field_hx5_ft_qual_offset_info_merge
   2779  *
   2780  * Purpose:
   2781  *    Create single offset_arr/qid_arr from output of Keygen_oper
   2782  *
   2783  * Parameters:
   2784  *    uint       - (IN) Unit.
   2785  *    keygen_oper - (IN) Output from Keygen algorithm.
   2786  *    keygen_parts_count - (IN) Number of Parts in Keygen output.
   2787  *    qual_offset_info - (OUT) qualifier offset info
   2788  *
   2789  * Returns:
   2790  *    BCM_E_XXX
   2791  */
   2792 int
   2793 _field_hx5_ft_qual_offset_info_merge(int unit,
   2794                                   bcmi_keygen_oper_t *keygen_oper,
   2795                                   int keygen_parts_count,
   2796                                   _field_ft_qual_ext_offset_info_t *qual_ext_offset_info)
   2797 {
   2798     int rv = BCM_E_NONE;
   2799     int q_idx = 0, idx = 0;
   2800     int keygen_part = 0;
   2801     int offset = 0;
   2802     int sel_offset = 0;
   2803     int new_qual_idx = 0;
   2804     uint16 num_offsets = 0;
   2805     bcm_field_qset_t qset;
   2806     bcmi_keygen_qual_offset_info_t *info = NULL;
   2807 
   2808     new_qual_idx = 0;
   2809     BCM_FIELD_QSET_INIT(qset);
   2810     /* Loop through all keygen parts */
   2811     for (keygen_part = 0; keygen_part < keygen_parts_count; keygen_part++) {
   2812         info = &(keygen_oper->qual_offset_info[keygen_part]);
   2813         sel_offset = 160 * keygen_part;
   2814 
   2815         /* Loop through qual info in the keygen part */
   2816         for (idx = 0; idx < info->size; idx++, q_idx++) {
   2817             /* Check if qual is also allocated, use that index */
   2818             if (BCM_FIELD_QSET_TEST(qset, info->qid_arr[idx])) {
   2819                 for (q_idx = 0; q_idx < new_qual_idx; q_idx++) {
   2820                     if (qual_ext_offset_info->qid_arr[q_idx] ==
   2821                             info->qid_arr[idx]) {
   2822                         break;
   2823                     }
   2824                 }
   2825                 if (q_idx == new_qual_idx) {
   2826                     return BCM_E_INTERNAL;
   2827                 }
   2828             } else {
   2829                 /* Assign new index */
   2830                 q_idx = new_qual_idx;
   2831                 new_qual_idx++;
   2832             }
   2833             num_offsets = 0;
   2834             for (offset = 0; offset < BCMI_KEYGEN_QUAL_OFFSETS_MAX; offset++) {
   2835                 if (!info->offset_arr[idx].width[offset]) {
   2836                     continue;
   2837                 }
   2838                 if (qual_ext_offset_info->offset_arr[q_idx].width[offset]) {
   2839                     return (BCM_E_INTERNAL);
   2840                 }
   2841                 qual_ext_offset_info->offset_arr[q_idx].offset[offset] =
   2842                     info->offset_arr[idx].offset[offset] + sel_offset;
   2843                 qual_ext_offset_info->offset_arr[q_idx].width[offset] =
   2844                     info->offset_arr[idx].width[offset];
   2845                 qual_ext_offset_info->sel_offset_arr[q_idx].ext_num[offset] =
   2846                     (info->offset_arr[idx].offset[offset] + sel_offset) / 16;
   2847                 num_offsets++;
   2848                 if (num_offsets == info->offset_arr[idx].num_offsets) {
   2849                     break;
   2850                 }
   2851             }
   2852             qual_ext_offset_info->qid_arr[q_idx] = info->qid_arr[idx];
   2853             qual_ext_offset_info->offset_arr[q_idx].num_offsets += num_offsets;
   2854             qual_ext_offset_info->sel_offset_arr[q_idx].num_offsets += num_offsets;
   2855             /* Add qual to Qset */
   2856             BCM_FIELD_QSET_ADD(qset, info->qid_arr[idx]);
   2857         }
   2858     }
   2859     qual_ext_offset_info->size = new_qual_idx;
   2860 
   2861     return rv;
   2862 }
   2863 
   2864 /*
   2865  * Function:
   2866  *    _field_hx5_ft_qual_ext_offset_info_free
   2867  *
   2868  * Purpose:
   2869  *    Free qual_ext_offset_info
   2870  *
   2871  * Parameters:
   2872  *    uint       - (IN) Unit.
   2873  *    qual_ext_offset_info - (OUT) qualifier ext offset info
   2874  *
   2875  * Returns:
   2876  *    None
   2877  * Notes:
   2878  *    Double pointes is passed as input. So, memory for
   2879  *    qual_ext_offset_info is also freed.
   2880  */
   2881 void
   2882 _field_hx5_ft_qual_ext_offset_info_free(int unit,
   2883             _field_ft_qual_ext_offset_info_t **qual_ext_offset_info)
   2884 {
   2885     _field_ft_qual_ext_offset_info_t *temp_info = NULL;
   2886 
   2887     if (*qual_ext_offset_info == NULL) {
   2888         return;
   2889     }
   2890 
   2891     temp_info = *qual_ext_offset_info;
   2892 
   2893     if (temp_info->qid_arr != NULL) {
   2894         sal_free(temp_info->qid_arr);
   2895         temp_info->qid_arr = NULL;
   2896     }
   2897     if (temp_info->offset_arr != NULL) {
   2898         sal_free(temp_info->offset_arr);
   2899         temp_info->offset_arr = NULL;
   2900     }
   2901     if (temp_info->sel_offset_arr != NULL) {
   2902         sal_free(temp_info->sel_offset_arr);
   2903         temp_info->sel_offset_arr = NULL;
   2904     }
   2905 
   2906     sal_free(temp_info);
   2907     *qual_ext_offset_info = NULL;
   2908 }
   2909 
   2910 /*
   2911  * Function:
   2912  *    _field_hx5_ft_qual_ext_offset_info_get
   2913  *
   2914  * Purpose:
   2915  *    Create a temporary structure to work on keygen_oper
   2916  *
   2917  * Parameters:
   2918  *    uint       - (IN) Unit.
   2919  *    keygen_parts_count - (IN) Number of Parts in Keygen output.
   2920  *    keygen_oper - (IN) Output from Keygen algorithm.
   2921  *    qual_ext_offset_info - (OUT) qualifier ext offset info
   2922  *
   2923  * Returns:
   2924  *    BCM_E_XXX
   2925  * Notes:
   2926  *    Double pointer is passed as input. So, memory for
   2927  *    qual_ext_offset_info is also allocated.
   2928  */
   2929 int
   2930 _field_hx5_ft_qual_ext_offset_info_get(int unit,
   2931                                 int keygen_parts_count,
   2932                                 bcmi_keygen_oper_t *keygen_oper,
   2933                                 _field_ft_qual_ext_offset_info_t **qual_ext_offset_info)
   2934 {
   2935     int rv = BCM_E_NONE;
   2936     int keygen_part = 0;
   2937     int qual_offset_info_count = 0;
   2938     _field_ft_qual_ext_offset_info_t *temp_info = NULL;
   2939     bcmi_keygen_qual_offset_info_t *qual_offset_info = NULL;
   2940 
   2941     if ((keygen_oper == NULL) ||
   2942         (keygen_oper->qual_offset_info == NULL) ||
   2943         (keygen_oper->ext_ctrl_sel_info == NULL)) {
   2944         return BCM_E_PARAM;
   2945     }
   2946 
   2947     /* Get number of qualifiers offset info */
   2948     for (keygen_part = 0; keygen_part < keygen_parts_count; keygen_part++) {
   2949         qual_offset_info = &(keygen_oper->qual_offset_info[keygen_part]);
   2950         qual_offset_info_count += qual_offset_info->size;
   2951     }
   2952 
   2953     _FP_XGS3_ALLOC(temp_info,
   2954             sizeof(_field_ft_qual_ext_offset_info_t),
   2955             " Qual Ext offset info");
   2956     if (temp_info == NULL) {
   2957         return BCM_E_MEMORY;
   2958     }
   2959 
   2960     /* Allocate joint memory for all qual offset infos. */
   2961     temp_info->size = qual_offset_info_count;
   2962     _FP_XGS3_ALLOC(temp_info->qid_arr,
   2963             qual_offset_info_count * sizeof(bcm_field_qualify_t),
   2964             "Group Qualifier Info");
   2965     _FP_XGS3_ALLOC(temp_info->offset_arr,
   2966             qual_offset_info_count * sizeof(bcmi_keygen_qual_offset_t),
   2967             "Group Qualifier Offset Info");
   2968     _FP_XGS3_ALLOC(temp_info->sel_offset_arr,
   2969             qual_offset_info_count * sizeof(_field_ft_qual_sel_t),
   2970             "Group Qualifier Offset Info");
   2971 
   2972     if ((temp_info->qid_arr == NULL) ||
   2973             (temp_info->offset_arr == NULL) ||
   2974             (temp_info->sel_offset_arr == NULL)) {
   2975         rv = BCM_E_MEMORY;
   2976     }
   2977 
   2978     if (BCM_SUCCESS(rv)) {
   2979         *qual_ext_offset_info = temp_info;
   2980 
   2981         /* Merge all keygen_parts to joint memory. */
   2982         rv = _field_hx5_ft_qual_offset_info_merge(unit,
   2983             keygen_oper, keygen_parts_count, *qual_ext_offset_info);
   2984     }
   2985 
   2986     if (BCM_FAILURE(rv)) {
   2987         if (temp_info != NULL) {
   2988             *qual_ext_offset_info = temp_info;
   2989             (void) _field_hx5_ft_qual_ext_offset_info_free(unit,
   2990                                 qual_ext_offset_info);
   2991         }
   2992         *qual_ext_offset_info = NULL;
   2993     }
   2994 
   2995     return rv;
   2996 }
   2997 
   2998 /*
   2999  * Function:
   3000  *    _field_hx5_ft_group_qual_offset_info_make
   3001  *
   3002  * Purpose:
   3003  *    Create group Qual info for given group part
   3004  *
   3005  * Parameters:
   3006  *    uint       - (IN) Unit.
   3007  *    fg         - (IN/OUT) Structure to field group.
   3008  *    qual_ext_offset_info - (IN) qualifier offset info.
   3009  *
   3010  * Returns:
   3011  *    BCM_E_XXX
   3012  */
   3013 STATIC int
   3014 _field_hx5_ft_group_qual_offset_info_make(int unit,
   3015             _field_group_t *fg,
   3016             _field_ft_qual_ext_offset_info_t *qual_ext_offset_info)
   3017 {
   3018     int rv = BCM_E_NONE;
   3019     int idx = 0;
   3020     int part = 0;
   3021     int info_idx = 0;
   3022     int offset = 0;
   3023     int parts_count = 0;
   3024     int qual_offset_info_count = 0;
   3025     uint16 qual = 0;
   3026     uint16 num_offsets = 0;
   3027     uint8 part_offset_found[2];
   3028     uint8 new_idx_allocated[2];
   3029     bcm_field_qualify_t *qid_arr = NULL;
   3030     _bcm_field_group_qual_t *fg_qual_arr = NULL;
   3031     bcmi_keygen_qual_offset_t *offset_arr = NULL;
   3032     _field_ft_group_qual_part_info_t grp_part_info[2];
   3033 
   3034     /* Validate input params. */
   3035     if ((fg == NULL) || (qual_ext_offset_info == NULL)) {
   3036         return BCM_E_INTERNAL;
   3037     }
   3038 
   3039     qid_arr = qual_ext_offset_info->qid_arr;
   3040     offset_arr = qual_ext_offset_info->offset_arr;
   3041     qual_offset_info_count = qual_ext_offset_info->size;
   3042 
   3043     /* Get number of entry parts. */
   3044     BCM_IF_ERROR_RETURN(_bcm_field_entry_tcam_parts_count(unit,
   3045                 fg->stage_id, fg->flags, &parts_count));
   3046 
   3047     for (part = 0; part < parts_count; part++) {
   3048         grp_part_info[part].count = 0;
   3049         BCM_FIELD_QSET_INIT(grp_part_info[part].qset);
   3050     }
   3051 
   3052     /* Step 1: Loop through all info and get count in multiple group parts */
   3053     for (info_idx = 0; info_idx < qual_offset_info_count; info_idx++) {
   3054         qual = qid_arr[info_idx];
   3055         num_offsets = 0;
   3056         part_offset_found[0] = part_offset_found[1] = FALSE;
   3057         for (offset = 0; offset < BCMI_KEYGEN_QUAL_OFFSETS_MAX; offset++) {
   3058             if (offset_arr[info_idx].width[offset] == 0) {
   3059                 continue;
   3060             }
   3061             rv = _field_offset_part_get(&offset_arr[info_idx], offset, &part);
   3062             if ((rv != BCM_E_NONE) || (part >= parts_count)) {
   3063                 rv = BCM_E_INTERNAL;
   3064                 goto cleanup;
   3065             }
   3066             part_offset_found[part] = TRUE;
   3067             num_offsets++;
   3068             if (num_offsets == offset_arr[info_idx].num_offsets) {
   3069                 break;
   3070             }
   3071         }
   3072         for (part = 0; part < parts_count; part++) {
   3073             if (part_offset_found[part] == TRUE) {
   3074                 if (!BCM_FIELD_QSET_TEST(grp_part_info[part].qset, qual)) {
   3075                     grp_part_info[part].count++;
   3076                     BCM_FIELD_QSET_ADD(grp_part_info[part].qset, qual);
   3077                 }
   3078             }
   3079         }
   3080     }
   3081 
   3082     /* Step 2: Allocate memory to each group parts */
   3083     for (part = 0; part < parts_count; part++) {
   3084         fg_qual_arr = &(fg->qual_arr[0][part]);
   3085         fg_qual_arr->size = grp_part_info[part].count;
   3086 
   3087         if (fg_qual_arr->size != 0) {
   3088             _FP_XGS3_ALLOC(fg_qual_arr->qid_arr,
   3089                     fg_qual_arr->size * sizeof(uint16),
   3090                     "Group Qualifier Array");
   3091             _FP_XGS3_ALLOC(fg_qual_arr->offset_arr,
   3092                     fg_qual_arr->size * sizeof(_bcm_field_qual_offset_t),
   3093                     "Group Qualifier Offset Info");
   3094             if ((fg_qual_arr->qid_arr == NULL) ||
   3095                     (fg_qual_arr->offset_arr == NULL)) {
   3096                 rv = BCM_E_MEMORY;
   3097                 goto cleanup;
   3098             }
   3099         } else {
   3100             fg_qual_arr->qid_arr = NULL;
   3101             fg_qual_arr->offset_arr = NULL;
   3102         }
   3103         grp_part_info[part].count = 0;
   3104         BCM_FIELD_QSET_INIT(grp_part_info[part].qset);
   3105     }
   3106 
   3107     /* Step 3: Fill up group qual parts */
   3108     for (info_idx = 0; info_idx < qual_offset_info_count; info_idx++) {
   3109         qual = qid_arr[info_idx];
   3110         num_offsets = 0;
   3111         new_idx_allocated[0] = new_idx_allocated[1] = FALSE;
   3112         for (offset = 0; offset < BCMI_KEYGEN_QUAL_OFFSETS_MAX; offset++) {
   3113             if (offset_arr[info_idx].width[offset] == 0) {
   3114                 continue;
   3115             }
   3116             (void) _field_offset_part_get(&offset_arr[info_idx], offset, &part);
   3117             fg_qual_arr = &(fg->qual_arr[0][part]);
   3118             if (new_idx_allocated[part] == TRUE) {
   3119                 idx = grp_part_info[part].count;
   3120             } else {
   3121                 if (BCM_FIELD_QSET_TEST(grp_part_info[part].qset, qual)) {
   3122                     for (idx = (grp_part_info[part].count - 1); idx >= 0; idx--) {
   3123                         if (fg_qual_arr->qid_arr[idx] == qual) {
   3124                             break;
   3125                         }
   3126                     }
   3127                     if (idx < 0) {
   3128                         rv = BCM_E_INTERNAL;
   3129                         goto cleanup;
   3130                     }
   3131                 } else {
   3132                     new_idx_allocated[part] = TRUE;
   3133                     idx = grp_part_info[part].count;
   3134                     BCM_FIELD_QSET_ADD(grp_part_info[part].qset, qual);
   3135                 }
   3136             }
   3137             if ((idx >= fg_qual_arr->size) ||
   3138                 (fg_qual_arr->offset_arr[idx].width[offset] != 0)) {
   3139                 rv = BCM_E_INTERNAL;
   3140                 goto cleanup;
   3141             }
   3142             fg_qual_arr->qid_arr[idx] = qual;
   3143             fg_qual_arr->offset_arr[idx].offset[offset] =
   3144                 offset_arr[info_idx].offset[offset];
   3145             fg_qual_arr->offset_arr[idx].width[offset] =
   3146                 offset_arr[info_idx].width[offset];
   3147             fg_qual_arr->offset_arr[idx].field = KEYf;
   3148             if (fg_qual_arr->offset_arr[idx].num_offsets <= offset) {
   3149                 fg_qual_arr->offset_arr[idx].num_offsets = (offset + 1);
   3150             }
   3151 
   3152             num_offsets++;
   3153             if (num_offsets == offset_arr[info_idx].num_offsets) {
   3154                 break;
   3155             }
   3156         }
   3157         for (part = 0; part < parts_count; part++) {
   3158             if (new_idx_allocated[part] == TRUE) {
   3159                 grp_part_info[part].count++;
   3160             }
   3161         }
   3162     }
   3163 
   3164 cleanup:
   3165 
   3166     if(BCM_FAILURE(rv)) {
   3167         for (part = 0; part < parts_count; part++) {
   3168             fg_qual_arr = &(fg->qual_arr[0][part]);
   3169             if (fg_qual_arr->qid_arr != NULL) {
   3170                 sal_free(fg_qual_arr->qid_arr);
   3171                 fg_qual_arr->qid_arr = NULL;
   3172             }
   3173             if (fg_qual_arr->offset_arr != NULL) {
   3174                 sal_free(fg_qual_arr->offset_arr);
   3175                 fg_qual_arr->offset_arr = NULL;
   3176             }
   3177         }
   3178     }
   3179 
   3180     return (rv);
   3181 }
   3182 
   3183 /*
   3184  * Function:
   3185  *    _field_hx5_ft_group_keygen_oper_insert
   3186  *
   3187  * Purpose:
   3188  *    Convert and save output of keygen algorithm.
   3189  *
   3190  * Parameters:
   3191  *    unit       - (IN) Unit.
   3192  *    fg         - (IN) Field Group structure.
   3193  *    keygen_parts_count - (IN) Number of keygen parts
   3194  *    keygen_oper - (IN) Output from Keygen algorithm.
   3195  *
   3196  * Returns:
   3197  *    BCM_E_XXX
   3198  */
   3199 STATIC int
   3200 _field_hx5_ft_group_keygen_oper_insert(int unit,
   3201                                        _field_group_t *fg,
   3202                                        int keygen_parts_count,
   3203                                        bcmi_keygen_oper_t *keygen_oper)
   3204 {
   3205     int rv = BCM_E_NONE;
   3206     _field_ft_qual_ext_offset_info_t *qual_ext_offset_info = NULL;
   3207 
   3208     if ((fg == NULL) || (keygen_oper == NULL)) {
   3209         return BCM_E_INTERNAL;
   3210     }
   3211 
   3212     /* Verify if atleast one qualifier is extracted */
   3213     if (keygen_oper->ext_ctrl_sel_info_count == 0) {
   3214         return BCM_E_NONE;
   3215     }
   3216 
   3217     /* Dump Keygen Oper Qual Offsets and Extractors codes */
   3218     LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3219                             "fp_group=%d Keygen Oper Info \n"),fg->gid));
   3220     (void) _bcm_field_keygen_qual_offset_info_dump(unit,
   3221                 keygen_parts_count, keygen_oper);
   3222 
   3223     rv = _field_hx5_ft_group_keygen_ext_codes_set(unit, fg, keygen_oper);
   3224     BCM_IF_ERROR_RETURN(rv);
   3225 
   3226     rv = _field_hx5_ft_qual_ext_offset_info_get(unit, keygen_parts_count,
   3227                 keygen_oper, &qual_ext_offset_info);
   3228     if (BCM_FAILURE(rv)) {
   3229         goto cleanup;
   3230     }
   3231 
   3232     /* Update Mask of extractors */
   3233     rv = _bcm_field_hx5_ft_keygen_extractors_mask_set(unit,
   3234                     qual_ext_offset_info, fg->ft_ext_codes);
   3235     if (BCM_FAILURE(rv)) {
   3236         goto cleanup;
   3237     }
   3238 
   3239     /*
   3240      * Apply shifts on qualifier offsets due to hw extractors shift logic.
   3241      * This will also split offsets to multiple group parts, if required.
   3242      */
   3243     rv = _field_hx5_ft_qual_offset_ext_shift_apply(unit,
   3244                     1, fg->ft_ext_codes, qual_ext_offset_info);
   3245     if (rv != BCM_E_NONE) {
   3246         goto cleanup;
   3247     }
   3248     /* Save qualifiers per group part */
   3249     rv = _field_hx5_ft_group_qual_offset_info_make(unit,
   3250                     fg, qual_ext_offset_info);
   3251     if (BCM_FAILURE(rv)) {
   3252         goto cleanup;
   3253     }
   3254 
   3255     /* Dump Hardware extractor information */
   3256     (void) _bcm_field_hx5_ft_keygen_hw_extractors_dump(unit, fg->ft_ext_codes);
   3257 
   3258 cleanup:
   3259 
   3260     if (qual_ext_offset_info != NULL) {
   3261         (void) _field_hx5_ft_qual_ext_offset_info_free(unit,
   3262                     &qual_ext_offset_info);
   3263     }
   3264 
   3265     return rv;
   3266 }
   3267 
   3268 /*
   3269  * Function:
   3270  *    _field_hx5_ft_keygen_oper_qual_add
   3271  *
   3272  * Purpose:
   3273  *    Add skipped qualifier Inport and its extractor codes to keygen_oper
   3274  *    info. Before calling keygen algorithm, qualifier InPort and corres-
   3275  *    ponding extractors are skipped from keygen algo processing as it is
   3276  *    required to be extracted with same extractors for all groups. Once
   3277  *    keygen_oper is formed qual InPort is added back to it for generating
   3278  *    final qual_arr info for the field group. Qual InPort is added to
   3279  *    part-0 of keygen output.
   3280  *
   3281  * Parameters:
   3282  *    unit       - (IN) Unit.
   3283  *    keygen_cfg - (IN) Keygen config
   3284  *    keygen_oper- (IN/OUT) Output from Keygen algorithm.
   3285  *
   3286  * Returns:
   3287  *    BCM_E_XXX
   3288  */
   3289 
   3290 STATIC int
   3291 _field_hx5_ft_keygen_oper_qual_add(int unit,
   3292                                    bcmi_keygen_cfg_t *keygen_cfg,
   3293                                    bcmi_keygen_oper_t *keygen_oper)
   3294 {
   3295     uint16 idx = 0;
   3296     uint16 offset = 0, num_offsets = 0;
   3297     uint16 ext_ctrl_info_count = 0, skipped_sz = 0;
   3298     uint16 qual_offset_info_size = 0;
   3299     uint16 qual_offset_info_alloc = FALSE;
   3300     bcm_field_qualify_t *qid_arr = NULL;
   3301     bcmi_keygen_qual_offset_t *offset_arr = NULL;
   3302     bcmi_keygen_qual_offset_info_t *qual_offset_info = NULL;
   3303     bcmi_keygen_ext_ctrl_sel_info_t *ext_ctrl_sel_info = NULL;
   3304 
   3305     if ((keygen_cfg == NULL) || (keygen_oper == NULL)) {
   3306         return BCM_E_PARAM;
   3307     }
   3308 
   3309     /* No qualifiers/extractors were skipped */
   3310     if (keygen_cfg->ext_ctrl_sel_info_count == 0) {
   3311         return BCM_E_NONE;
   3312     }
   3313 
   3314     /* Get total qual info size at part-0 of keygen_oper */
   3315     qual_offset_info = &(keygen_oper->qual_offset_info[0]);
   3316     if (qual_offset_info != NULL) {
   3317         qual_offset_info_size = qual_offset_info->size;
   3318     }
   3319     qual_offset_info_size++;
   3320 
   3321     /* Get total extractors */
   3322     ext_ctrl_info_count = keygen_oper->ext_ctrl_sel_info_count;
   3323     ext_ctrl_info_count += keygen_cfg->ext_ctrl_sel_info_count;
   3324 
   3325     /* Allocate memories */
   3326     if (qual_offset_info == NULL) {
   3327         qual_offset_info_alloc = TRUE;
   3328         _FP_XGS3_ALLOC(qual_offset_info,
   3329             keygen_cfg->num_parts * sizeof(bcmi_keygen_qual_offset_info_t),
   3330             "Qual Offset Info");
   3331     }
   3332     _FP_XGS3_ALLOC(qid_arr,
   3333             qual_offset_info_size * sizeof(bcm_field_qualify_t),
   3334             "Keygen oper qid arr");
   3335     _FP_XGS3_ALLOC(offset_arr,
   3336             qual_offset_info_size * sizeof(bcmi_keygen_qual_offset_t),
   3337             "Keygen oper offset arr");
   3338     _FP_XGS3_ALLOC(ext_ctrl_sel_info,
   3339             ext_ctrl_info_count * sizeof(bcmi_keygen_ext_ctrl_sel_info_t),
   3340             "Ext Ctrl Offset Info");
   3341     if ((qual_offset_info == NULL) || (qid_arr == NULL) ||
   3342         (offset_arr == NULL) || (ext_ctrl_sel_info == NULL)) {
   3343         if ((qual_offset_info != NULL) && (qual_offset_info_alloc == TRUE)) {
   3344             sal_free(qual_offset_info);
   3345         }
   3346         if (qid_arr != NULL) {
   3347             sal_free(qid_arr);
   3348         }
   3349         if (offset_arr != NULL) {
   3350             sal_free(offset_arr);
   3351         }
   3352         if (ext_ctrl_sel_info != NULL) {
   3353             sal_free(ext_ctrl_sel_info);
   3354         }
   3355         return BCM_E_MEMORY;
   3356     }
   3357     /* Add InPort Qual info */
   3358     qid_arr[0] = bcmFieldQualifyInPort;
   3359     offset_arr[0].num_offsets = 1;
   3360     offset_arr[0].offset[0] = 0;
   3361     offset_arr[0].width[0] = 7;
   3362     for (idx = 0; idx < qual_offset_info->size; idx++) {
   3363         num_offsets = 0;
   3364         for (offset = 0; offset < BCMI_KEYGEN_QUAL_OFFSETS_MAX; offset++) {
   3365             if (qual_offset_info->offset_arr[idx].width[offset] == 0) {
   3366                 continue;
   3367             }
   3368             num_offsets++;
   3369             offset_arr[idx + 1].offset[offset] =
   3370                 qual_offset_info->offset_arr[idx].offset[offset];
   3371             offset_arr[idx + 1].width[offset] =
   3372                 qual_offset_info->offset_arr[idx].width[offset];
   3373             if (num_offsets == qual_offset_info->offset_arr[idx].num_offsets) {
   3374                 break;
   3375             }
   3376         }
   3377         offset_arr[idx + 1].num_offsets = num_offsets;
   3378         qid_arr[idx + 1] = qual_offset_info->qid_arr[idx];
   3379     }
   3380 
   3381     /* Copy ext ctrl sel info */
   3382     skipped_sz = keygen_cfg->ext_ctrl_sel_info_count;
   3383     sal_memcpy(&ext_ctrl_sel_info[0], keygen_cfg->ext_ctrl_sel_info,
   3384             skipped_sz * sizeof(bcmi_keygen_ext_ctrl_sel_info_t));
   3385     if (keygen_oper->ext_ctrl_sel_info_count != 0) {
   3386         sal_memcpy(&ext_ctrl_sel_info[skipped_sz],
   3387                 keygen_oper->ext_ctrl_sel_info,
   3388                 keygen_oper->ext_ctrl_sel_info_count *
   3389                 sizeof(bcmi_keygen_ext_ctrl_sel_info_t));
   3390     }
   3391 
   3392     /* Free modified members in keygen_oper */
   3393     if (keygen_oper->ext_ctrl_sel_info != NULL) {
   3394         sal_free(keygen_oper->ext_ctrl_sel_info);
   3395         keygen_oper->ext_ctrl_sel_info = NULL;
   3396     }
   3397     if (qual_offset_info_alloc == FALSE) {
   3398         if (keygen_oper->qual_offset_info[0].qid_arr != NULL) {
   3399             sal_free(keygen_oper->qual_offset_info[0].qid_arr);
   3400             keygen_oper->qual_offset_info[0].qid_arr = NULL;
   3401         }
   3402         if (keygen_oper->qual_offset_info[0].offset_arr != NULL) {
   3403             sal_free(keygen_oper->qual_offset_info[0].offset_arr);
   3404             keygen_oper->qual_offset_info[0].offset_arr = NULL;
   3405         }
   3406     }
   3407 
   3408     /* Update keygen_oper with modified members */
   3409     keygen_oper->ext_ctrl_sel_info_count = ext_ctrl_info_count;
   3410     keygen_oper->ext_ctrl_sel_info = ext_ctrl_sel_info;
   3411     if (qual_offset_info_alloc == TRUE) {
   3412         keygen_oper->qual_offset_info = qual_offset_info;
   3413     }
   3414     keygen_oper->qual_offset_info[0].qid_arr = qid_arr;
   3415     keygen_oper->qual_offset_info[0].offset_arr = offset_arr;
   3416     keygen_oper->qual_offset_info[0].size = qual_offset_info_size;
   3417 
   3418     return BCM_E_NONE;
   3419 }
   3420 
   3421 /*
   3422  * Function:
   3423  *    _field_hx5_ft_ext_code_assign
   3424  *
   3425  * Purpose:
   3426  *    Calculate extractors values and qualifiers offsets in
   3427  *    final key.
   3428  *
   3429  * Parameters:
   3430  *    unit       - (IN) BCM device number.
   3431  *    fsm_ptr    - (IN) Field group creation state machine.
   3432  *    stage_fc   - (IN) Field stage control structure.
   3433  *
   3434  * Returns:
   3435  *    BCM_E_XXX
   3436  */
   3437 int _field_hx5_ft_ext_code_assign(int unit,
   3438                                   int selcode_clear,
   3439                                   _field_group_add_fsm_t *fsm_ptr)
   3440 {
   3441     int rv = BCM_E_NONE;
   3442     uint16 rkey_size = 0;
   3443     uint16 skipped_size = 0;
   3444     uint16 qual_info_count = 0;
   3445     uint16 keygen_parts_count = 0;
   3446     uint16 qual_inport_excluded = FALSE;
   3447     bcm_field_qset_t qset_req;
   3448     bcmi_keygen_cfg_t keygen_cfg;
   3449     bcmi_keygen_oper_t keygen_oper;
   3450     bcmi_keygen_mode_t keygen_mode;
   3451     bcmi_keygen_mode_t keygen_ext_mode;
   3452     _field_group_t *fg = NULL;
   3453     _field_stage_t *stage_fc = NULL;
   3454     bcmi_keygen_qual_info_t *qual_info_arr = NULL;
   3455 
   3456     /* Input parameters check. */
   3457     if (NULL == fsm_ptr) {
   3458         return (BCM_E_PARAM);
   3459     }
   3460 
   3461     fg = fsm_ptr->fg;
   3462     stage_fc = fsm_ptr->stage_fc;
   3463 
   3464     sal_memset(&keygen_cfg, 0, sizeof(bcmi_keygen_cfg_t));
   3465     sal_memset(&keygen_oper, 0, sizeof(bcmi_keygen_oper_t));
   3466     sal_memcpy(&qset_req, &(fg->qset), sizeof(bcm_field_qset_t));
   3467 
   3468     /* Need to remove Qual InPort from the qset */
   3469     if ((BCM_FIELD_QSET_TEST(qset_req, bcmFieldQualifyInPort) &&
   3470         (soc_feature(unit, soc_feature_bscan_fae_port_flow_exclude)))) {
   3471         qual_inport_excluded = TRUE;
   3472         BCM_FIELD_QSET_REMOVE(qset_req, bcmFieldQualifyInPort);
   3473     }
   3474 
   3475     /* Remove dummy qualifiers. */
   3476     BCM_FIELD_QSET_REMOVE(qset_req, bcmFieldQualifyStage);
   3477     BCM_FIELD_QSET_REMOVE(qset_req, bcmFieldQualifyStageIngressFlowtracker);
   3478 
   3479     /* Get Group Qualifiers info array. */
   3480     rv = _field_th_group_qual_info_get(unit, stage_fc, fg,
   3481                 &(qset_req), &qual_info_arr, &qual_info_count);
   3482     BCM_IF_ERROR_RETURN(rv);
   3483 
   3484     if (fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE &&
   3485         !(fg->flags & _FP_GROUP_DW_DEPTH_EXPANDED)) {
   3486         keygen_mode = BCMI_KEYGEN_MODE_SINGLE;
   3487         keygen_ext_mode = BCMI_KEYGEN_MODE_SINGLE;
   3488         keygen_parts_count = 2;
   3489     } else if (fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE &&
   3490                fg->flags & _FP_GROUP_DW_DEPTH_EXPANDED) {
   3491         keygen_mode = BCMI_KEYGEN_MODE_DBLINTRA;
   3492         keygen_ext_mode = BCMI_KEYGEN_MODE_DBLINTRA;
   3493         keygen_parts_count = 3;
   3494     } else {
   3495         rv = BCM_E_INTERNAL;
   3496         keygen_parts_count = 0;
   3497         goto cleanup;
   3498     }
   3499 
   3500     keygen_cfg.qual_info_arr = qual_info_arr;
   3501     keygen_cfg.qual_info_count = qual_info_count;
   3502     keygen_cfg.qual_cfg_info_db = stage_fc->qual_cfg_info_db;
   3503     keygen_cfg.ext_cfg_db = stage_fc->ext_cfg_db_arr[keygen_ext_mode];
   3504     keygen_cfg.mode = keygen_mode;
   3505     keygen_cfg.num_parts = keygen_parts_count;
   3506 
   3507     if (fsm_ptr->flags & _FP_GROUP_CONFIG_VALIDATE) {
   3508         keygen_cfg.flags = BCMI_KEYGEN_CFG_FLAGS_VALIDATE_ONLY;
   3509     }
   3510     if ((fg->ft_ext_codes != NULL) &&
   3511             (fsm_ptr->flags & _FP_GROUP_QSET_UPDATE)) {
   3512         /* Create keygen ext codes to exclude already extracted qualifiers. */
   3513         keygen_cfg.flags |= BCMI_KEYGEN_CFG_FLAGS_QSET_UPDATE;
   3514         rv = _field_hx5_ft_keygen_ext_ctrl_info_get(unit,
   3515                 fg->ft_ext_codes, &keygen_cfg.ext_ctrl_sel_info,
   3516                 &keygen_cfg.ext_ctrl_sel_info_count);
   3517         if (BCM_FAILURE(rv)) {
   3518             goto cleanup;
   3519         }
   3520     } else {
   3521         if (soc_feature(unit, soc_feature_bscan_fae_port_flow_exclude) &&
   3522             (qual_inport_excluded == TRUE)) {
   3523             /* Create keygen ext codes to skip extractors for InPort */
   3524             keygen_cfg.flags |= BCMI_KEYGEN_CFG_FLAGS_QSET_UPDATE;
   3525             rv = _field_hx5_ft_keygen_ext_ctrl_info_skip(unit,
   3526                      &keygen_cfg, &skipped_size);
   3527             if (BCM_FAILURE(rv)) {
   3528                 goto cleanup;
   3529             }
   3530         }
   3531     }
   3532 
   3533     if (!(fsm_ptr->flags & _FP_GROUP_QSET_UPDATE)) {
   3534         rv = bcmi_keygen_keysize_get(unit, &keygen_cfg, &rkey_size);
   3535         if (BCM_FAILURE(rv)) {
   3536             goto cleanup;
   3537         }
   3538         if (((keygen_mode == BCMI_KEYGEN_MODE_SINGLE)
   3539                     && ((rkey_size + skipped_size) > 180)) ||
   3540                 ((keygen_mode == BCMI_KEYGEN_MODE_DBLINTRA)
   3541                  && ((rkey_size + skipped_size) > 360))) {
   3542             rv = BCM_E_CONFIG;
   3543             goto cleanup;
   3544         }
   3545     }
   3546 
   3547     rv = bcmi_keygen_cfg_process(unit, &keygen_cfg, &keygen_oper);
   3548     if (BCM_FAILURE(rv)) {
   3549         goto cleanup;
   3550     }
   3551 
   3552     /* Update keygen_oper with InPort Qual Info */
   3553     if (soc_feature(unit, soc_feature_bscan_fae_port_flow_exclude) &&
   3554         (qual_inport_excluded == TRUE)) {
   3555         rv = _field_hx5_ft_keygen_oper_qual_add(unit,
   3556                     &keygen_cfg, &keygen_oper);
   3557         if (BCM_FAILURE(rv)) {
   3558             goto cleanup;
   3559         }
   3560     }
   3561 
   3562     if ((fsm_ptr->flags & _FP_GROUP_CONFIG_VALIDATE) == 0) {
   3563         rv = _field_hx5_ft_group_keygen_oper_insert(unit,
   3564                     fsm_ptr->fg, keygen_parts_count, &keygen_oper);
   3565     }
   3566 
   3567 cleanup:
   3568 
   3569     (void)bcmi_keygen_oper_free(unit, keygen_parts_count, &keygen_oper);
   3570     if (qual_info_arr != NULL) {
   3571         sal_free(qual_info_arr);
   3572     }
   3573     if (keygen_cfg.ext_ctrl_sel_info != NULL) {
   3574         sal_free(keygen_cfg.ext_ctrl_sel_info);
   3575         keygen_cfg.ext_ctrl_sel_info = NULL;
   3576     }
   3577 
   3578     return rv;
   3579 }
   3580 
   3581 /*
   3582  * Function:
   3583  *    _bcm_field_hx5_ft_group_update
   3584  *
   3585  * Purpose:
   3586  *    Extract group ext codes again with new qualifiers and update
   3587  *    qualifier info per part.
   3588  *
   3589  * Parameters:
   3590  *    unit       - (IN) Unit number
   3591  *    group      - (IN) Group Id
   3592  *    qset       - (IN) New qualifiers qset
   3593  *
   3594  * Returns:
   3595  *    BCM_E_NONE        - Success.
   3596  */
   3597 int
   3598 _bcm_field_hx5_ft_group_update(int unit,
   3599         bcm_field_group_t group, bcm_field_qset_t *qset)
   3600 {
   3601     int rv = BCM_E_NONE; /* Return status.  */
   3602     int idx = 0;         /* Index Variable. */
   3603     int pidx = 0;        /* Index Variable. */
   3604     int qid_index = 0;   /* Index Variable. */
   3605     int qid;             /* Qualifier ID.   */
   3606     int parts_count = 0; /* number of slices allocated for the group. */
   3607     uint8 part;          /* Group Partition. */
   3608     uint8 has_ft_ext_codes = FALSE;      /* If original field group has extractors */
   3609     uint16 *qid_array[_FP_MAX_ENTRY_WIDTH] = { NULL };
   3610                                             /* Array of qualifiers.    */
   3611     uint16 size = 0;                        /* Total number of qualifiers in
   3612                                                each partition of the group. */
   3613     _field_group_t *fg = NULL;           /* Field group operational Structure. */
   3614     _field_group_t *temp_fg = NULL;      /* Temp field group operational structure. */
   3615     _field_stage_t *stage_fc = NULL;     /* Field Stage operational structure. */
   3616     bcm_field_qset_t temp_qset;          /* Temporary qset information. */
   3617     _bcm_field_qual_offset_t  *offset_array[_FP_MAX_ENTRY_WIDTH] = { NULL };
   3618                                          /* Array of qualifiers offset information. */
   3619     _field_group_add_fsm_t fsm_ptr;
   3620 
   3621     BCM_IF_ERROR_RETURN(_field_group_get(unit, group, &fg));
   3622     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
   3623                 _BCM_FIELD_STAGE_FLOWTRACKER, &stage_fc));
   3624 
   3625     sal_memcpy(&temp_qset, qset, sizeof(bcm_field_qset_t));
   3626 
   3627     for (qid = 0; qid < _bcmFieldQualifyCount; qid++) {
   3628         if (BCM_FIELD_QSET_TEST(fg->qset, qid)) {
   3629             BCM_FIELD_QSET_REMOVE(temp_qset, qid);
   3630         }
   3631     }
   3632 
   3633     _FP_XGS3_ALLOC(temp_fg, sizeof(_field_group_t), "Temp group for update");
   3634     if (NULL == temp_fg) {
   3635         return BCM_E_MEMORY;
   3636     }
   3637 
   3638     temp_fg->gid = fg->gid;
   3639     temp_fg->flags = fg->flags;
   3640     sal_memcpy(&temp_fg->qset, &temp_qset, sizeof(bcm_field_qset_t));
   3641     sal_memset(&fsm_ptr, 0, sizeof(_field_group_add_fsm_t));
   3642 
   3643     fsm_ptr.fg = temp_fg;
   3644     fsm_ptr.stage_fc = stage_fc;
   3645     fsm_ptr.flags = _FP_GROUP_QSET_UPDATE;
   3646 
   3647     /* Allocate memory for ext codes */
   3648     if (fg->ft_ext_codes != NULL) {
   3649         _FP_XGS3_ALLOC(temp_fg->ft_ext_codes,
   3650                 sizeof(_field_ft_keygen_ext_codes_t),
   3651                 "field group ext codes");
   3652         if (temp_fg->ft_ext_codes == NULL) {
   3653             sal_free(temp_fg);
   3654             return BCM_E_MEMORY;
   3655         }
   3656 
   3657         has_ft_ext_codes = TRUE;
   3658         sal_memcpy(temp_fg->ft_ext_codes, fg->ft_ext_codes,
   3659                 sizeof(_field_ft_keygen_ext_codes_t));
   3660     }
   3661     rv = _field_hx5_ft_ext_code_assign(unit, 0, &fsm_ptr);
   3662 
   3663     if (BCM_FAILURE(rv)) {
   3664         LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3665             "FP(unit %d) Verb: Processing group QSET.\n"), unit));
   3666         goto cleanup;
   3667     }
   3668 
   3669     for (part = 0; part < _FP_MAX_ENTRY_WIDTH; part++)  {
   3670         /* If no new qualifier is extracted in the part, skip the part. */
   3671         size = temp_fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].size;
   3672         if (size == 0) {
   3673             continue;
   3674         }
   3675         size += fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].size;
   3676         if (size != 0) {
   3677              _FP_XGS3_ALLOC(qid_array[part], size * sizeof(uint16), "Qid Array");
   3678              if (NULL == qid_array[part]) {
   3679                 rv = BCM_E_MEMORY;
   3680                 goto cleanup;
   3681              }
   3682              _FP_XGS3_ALLOC(offset_array[part], size * sizeof(_bcm_field_qual_offset_t),
   3683                                                         "Qualifier Offset Array");
   3684              if (NULL == offset_array[part]) {
   3685                 rv = BCM_E_MEMORY;
   3686                 goto cleanup;
   3687              }
   3688 
   3689              qid_index = 0;
   3690              for (idx = 0; idx < fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].size; idx++) {
   3691 
   3692                  sal_memcpy(&qid_array[part][qid_index],
   3693                         &(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].qid_arr[idx]),
   3694                         sizeof(uint16));
   3695 
   3696                  sal_memcpy(&offset_array[part][qid_index],
   3697                             &(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].offset_arr[idx]),
   3698                             sizeof(_bcm_field_qual_offset_t));
   3699 
   3700                  qid_index++;
   3701 
   3702              }
   3703 
   3704              fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].size = size;
   3705 
   3706              /* Copy qualifier array and offset array of new
   3707               * qualifiers in this partition.
   3708               */
   3709              size = temp_fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].size;
   3710              sal_memcpy(&qid_array[part][qid_index],
   3711                         temp_fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].qid_arr,
   3712                         size * sizeof(uint16));
   3713 
   3714              sal_memcpy(&offset_array[part][qid_index],
   3715                         temp_fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].offset_arr,
   3716                         size * sizeof(_bcm_field_qual_offset_t));
   3717 
   3718              if (NULL != fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].qid_arr) {
   3719                  sal_free(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].qid_arr);
   3720              }
   3721 
   3722              if (NULL != fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].offset_arr) {
   3723                  sal_free(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].offset_arr);
   3724              }
   3725 
   3726              if (NULL != temp_fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].qid_arr) {
   3727                  sal_free(temp_fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].qid_arr);
   3728              }
   3729 
   3730              if (NULL != temp_fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].offset_arr) {
   3731                  sal_free(temp_fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].offset_arr);
   3732              }
   3733 
   3734              fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].qid_arr = qid_array[part];
   3735              fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part].offset_arr = offset_array[part];
   3736         }
   3737     }
   3738 
   3739     rv = _bcm_field_th_entry_tcam_parts_count(unit, fg->flags, &parts_count);
   3740     if (BCM_FAILURE(rv)) {
   3741         goto cleanup;
   3742     }
   3743 
   3744     for (part = 0; part < _FP_MAX_ENTRY_WIDTH; part++)  {
   3745          offset_array[part] = NULL;
   3746          qid_array[part] = NULL;
   3747     }
   3748 
   3749     if (has_ft_ext_codes == TRUE) {
   3750         sal_memcpy(fg->ft_ext_codes, temp_fg->ft_ext_codes,
   3751                       (sizeof(_field_ft_keygen_ext_codes_t)));
   3752     } else {
   3753         fg->ft_ext_codes = temp_fg->ft_ext_codes;
   3754     }
   3755 
   3756     /* Install entry parts in hardware. Loop through all presels */
   3757     for (pidx = 0; pidx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; pidx++) {
   3758         if (fg->presel_ent_arr[pidx] != NULL) {
   3759             rv = _field_hx5_ft_group_keygen_install(unit,
   3760                     fg->presel_ent_arr[pidx]);
   3761         }
   3762         if (BCM_FAILURE(rv)) {
   3763             goto cleanup;
   3764         }
   3765     }
   3766 
   3767     for (qid = 0; qid < _bcmFieldQualifyCount; qid++) {
   3768         if (BCM_FIELD_QSET_TEST(*qset, qid)) {
   3769             BCM_FIELD_QSET_ADD(fg->qset, qid);
   3770         }
   3771     }
   3772 
   3773 cleanup:
   3774     for (part = 0; part < _FP_MAX_ENTRY_WIDTH; part++) {
   3775          if (NULL != qid_array[part]) {
   3776              sal_free(qid_array[part]);
   3777              qid_array[part] = NULL;
   3778          }
   3779 
   3780          if(NULL != offset_array[part]) {
   3781              sal_free(offset_array[part]);
   3782              offset_array[part] = NULL;
   3783          }
   3784     }
   3785 
   3786     if (NULL != temp_fg) {
   3787         if ((temp_fg->ft_ext_codes != NULL) &&
   3788             (has_ft_ext_codes == TRUE)) {
   3789             sal_free(temp_fg->ft_ext_codes);
   3790         }
   3791         sal_free(temp_fg);
   3792     }
   3793 
   3794     return (rv);
   3795 }
   3796 
   3797 /****** Extraction ends ***************************************/
   3798 
   3799 /*
   3800  * Function:
   3801  *    _bcm_field_keygen_qual_offset_info_dump
   3802  *
   3803  * Purpose:
   3804  *    Dump the output of keygen for qualifiers and extractor
   3805  *    codes.
   3806  *
   3807  * Parameters:
   3808  *    unit       - (IN) Unit number
   3809  *    keygen_parts_count - (IN) Keygen parts
   3810  *    keygen_oper - (IN) Keygen operation info
   3811  *
   3812  * Returns:
   3813  *    BCM_E_NONE        - Success.
   3814  */
   3815 int
   3816 _bcm_field_keygen_qual_offset_info_dump(int unit,
   3817                                  int keygen_parts_count,
   3818                                  bcmi_keygen_oper_t *keygen_oper)
   3819 {
   3820     int idx = 0;
   3821     int part = 0;
   3822     int offset = 0;
   3823     int num_offsets = 0;
   3824     bcm_field_qualify_t qid;
   3825     bcmi_keygen_qual_offset_info_t *q_info = NULL;
   3826     bcmi_keygen_ext_ctrl_sel_info_t *e_info = NULL;
   3827 
   3828     if (keygen_oper == NULL) {
   3829         return BCM_E_NONE;
   3830     }
   3831     if (keygen_oper->ext_ctrl_sel_info_count == 0) {
   3832         LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3833                         " Extraction info not available\n\r")));
   3834         return BCM_E_NONE;
   3835     }
   3836 
   3837     /* Qualifiers offsets and widths */
   3838     for (part = 0; part < keygen_parts_count; part++) {
   3839         q_info = &(keygen_oper->qual_offset_info[part]);
   3840 
   3841         for (idx = 0; idx < q_info->size; idx++) {
   3842             qid = q_info->qid_arr[idx];
   3843             LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3844                             "qi[p=%d][%d] %s ->"), part, idx,
   3845                         _field_qual_name(qid)));
   3846             num_offsets = 0;
   3847             for (offset = 0; offset < BCMI_KEYGEN_QUAL_OFFSETS_MAX; offset++) {
   3848                 if (!q_info->offset_arr[idx].width[offset]) {
   3849                     continue;
   3850                 }
   3851                 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3852                                 " {[%d] offset:%d, width:%d}"),
   3853                             offset, q_info->offset_arr[idx].offset[offset],
   3854                             q_info->offset_arr[idx].width[offset]));
   3855                 num_offsets++;
   3856                 if (num_offsets == q_info->offset_arr[idx].num_offsets) {
   3857                     break;
   3858                 }
   3859                 if (((num_offsets + 1) % 3) == 0) {
   3860                     LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, "\n\r\t\t")));
   3861                 }
   3862             }
   3863             LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit, "\n\r")));
   3864         }
   3865     }
   3866 
   3867     /* Extractors */
   3868     for (idx = 0; idx < keygen_oper->ext_ctrl_sel_info_count; idx++) {
   3869         e_info = &keygen_oper->ext_ctrl_sel_info[idx];
   3870         LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3871                         "ei[p=%d][%d] -> ext_Id=0x%x ctrl_sel=%d "),
   3872                     e_info->part, idx, e_info->ext_num, e_info->ctrl_sel));
   3873         LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,"val=%d l=%d g=%d\n\r"),
   3874                     e_info->ctrl_sel_val, e_info->level, e_info->gran));
   3875     }
   3876 
   3877     return (BCM_E_NONE);
   3878 }
   3879 
   3880 #endif