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

ipfix.c (124228B)


      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:       ipfix.c
      8  * Purpose:    IPFIX API
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <soc/drv.h>
     14 #include <soc/scache.h>
     15 #include <soc/profile_mem.h>
     16 #include <bcm/error.h>
     17 #include <bcm/ipfix.h>
     18 #include <bcm/mirror.h>
     19 #include <bcm_int/common/multicast.h>
     20 #include <bcm_int/esw/xgs3.h>
     21 #include <bcm_int/esw/port.h>
     22 #include <bcm_int/esw/virtual.h>
     23 #include <bcm_int/esw/multicast.h>
     24 #include <bcm_int/esw/ipfix.h>
     25 #include <bcm_int/esw/mirror.h>
     26 
     27 #ifdef BCM_CMICM_SUPPORT
     28 #include <soc/cmicm.h>
     29 #endif
     30 
     31 #ifdef BCM_WARM_BOOT_SUPPORT
     32 #include <bcm/module.h>
     33 #include <bcm_int/esw/switch.h>
     34 #endif
     35 
     36 #ifdef BCM_IPFIX_SUPPORT
     37 static _bcm_ipfix_ctrl_t *_bcm_ipfix_ctrl[BCM_MAX_NUM_UNITS];
     38 
     39 #ifdef BCM_TRIUMPH_SUPPORT
     40 static const _bcm_ipfix_id_def_t _ipfix_tr_id_def = {
     41     { ING_IPFIX_PORT_CONFIGr, EGR_IPFIX_PORT_CONFIGr },
     42     { ING_IPFIX_PROFILEm, EGR_IPFIX_PROFILEm },
     43     { ING_IPFIX_EXPORT_FIFOm, EGR_IPFIX_EXPORT_FIFOm },
     44     { IPFIX_AGE_CONTROLr, EGR_IPFIX_AGE_CONTROLr },
     45     { ING_IPFIX_MIRROR_CONTROL_64r, EGR_IPFIX_MIRROR_CONTROL_64r },
     46     { MTP_INDEX0f, MTP_INDEX1f, MTP_INDEX2f, MTP_INDEX3f },
     47 };
     48 
     49 /* Mapping between profile and field in bcm_ipfix_config_t */
     50 static const _bcm_ipfix_profile_def_t _ipfix_tr_profile_def[] = {
     51     {
     52         _BCM_IPFIX_PROFILE_TYPE_MEM,
     53         IP_DSCP_PROFILEf,
     54         { /* stage */
     55             { /* ingress */
     56                 _BCM_IPFIX_PROFILE_ID_ING_DSCP_XLATE_TABLE,
     57                 { ING_IPFIX_DSCP_XLATE_TABLEm, INVALIDm },
     58                 { sizeof(ing_ipfix_dscp_xlate_table_entry_t) / sizeof(uint32),
     59                   0 },
     60             },
     61             { /* egress */
     62                 _BCM_IPFIX_PROFILE_ID_EGR_DSCP_XLATE_TABLE,
     63                 { EGR_IPFIX_DSCP_XLATE_TABLEm, INVALIDm },
     64                 { sizeof(egr_ipfix_dscp_xlate_table_entry_t) / sizeof(uint32),
     65                   0 },
     66             },
     67         },
     68     },
     69     {
     70         _BCM_IPFIX_PROFILE_TYPE_MEM,
     71         IP_IPV4_MASK_PROFILEf,
     72         { /* stage */
     73             { /* ingress */
     74                 _BCM_IPFIX_PROFILE_ID_ING_IPV4_MASK_SET_A,
     75                 { ING_IPFIX_IPV4_MASK_SET_Am, ING_IPFIX_IPV4_MASK_SET_Bm },
     76                 { sizeof(ing_ipfix_ipv4_mask_set_a_entry_t) / sizeof(uint32),
     77                   sizeof(ing_ipfix_ipv4_mask_set_b_entry_t) / sizeof(uint32) },
     78             },
     79             { /* egress */
     80                 _BCM_IPFIX_PROFILE_ID_EGR_IPV4_MASK_SET_A,
     81                 { EGR_IPFIX_IPV4_MASK_SET_Am, INVALIDm },
     82                 { sizeof(egr_ipfix_ipv4_mask_set_a_entry_t) / sizeof(uint32),
     83                   0 },
     84             },
     85         },
     86     },
     87     {
     88         _BCM_IPFIX_PROFILE_TYPE_MEM,
     89         IP_IPV6_MASK_PROFILEf,
     90         { /* stage */
     91             { /* ingress */
     92                 _BCM_IPFIX_PROFILE_ID_ING_IPV6_MASK_SET_A,
     93                 { ING_IPFIX_IPV6_MASK_SET_Am, ING_IPFIX_IPV6_MASK_SET_Bm },
     94                 { sizeof(ing_ipfix_ipv6_mask_set_a_entry_t) / sizeof(uint32),
     95                   sizeof(ing_ipfix_ipv6_mask_set_b_entry_t) / sizeof(uint32) },
     96             },
     97             { /* egress */
     98                 _BCM_IPFIX_PROFILE_ID_EGR_IPV6_MASK_SET_A,
     99                 { EGR_IPFIX_IPV6_MASK_SET_Am, INVALIDm },
    100                 { sizeof(egr_ipfix_ipv6_mask_set_a_entry_t) / sizeof(uint32),
    101                   0 },
    102             },
    103         },
    104     },
    105     {
    106         _BCM_IPFIX_PROFILE_TYPE_REG,
    107         PORT_LIMIT_PROFILEf,
    108         { /* stage */
    109             { /* ingress */
    110                 _BCM_IPFIX_PROFILE_ID_ING_PORT_RECORD_LIMIT_SET,
    111                 { ING_IPFIX_PORT_RECORD_LIMIT_SETr, INVALIDr },
    112                 { 0, 0 },
    113             },
    114             { /* egress */
    115                 _BCM_IPFIX_PROFILE_ID_EGR_PORT_RECORD_LIMIT_SET,
    116                 { EGR_IPFIX_PORT_RECORD_LIMIT_SETr, INVALIDr },
    117                 { 0, 0 },
    118             },
    119         },
    120     },
    121     {
    122         _BCM_IPFIX_PROFILE_TYPE_REG,
    123         MIN_LIVE_TIME_PROFILEf,
    124         { /* stage */
    125             { /* ingress */
    126                 _BCM_IPFIX_PROFILE_ID_ING_MINIMUM_LIVE_TIME_SET,
    127                 { ING_IPFIX_MINIMUM_LIVE_TIME_SETr, INVALIDr },
    128                 { 0, 0 },
    129             },
    130             { /* egress */
    131                 _BCM_IPFIX_PROFILE_ID_EGR_MINIMUM_LIVE_TIME_SET,
    132                 { EGR_IPFIX_MINIMUM_LIVE_TIME_SETr, INVALIDr },
    133                 { 0, 0 },
    134             },
    135         },
    136     },
    137 #ifdef BCM_TRIUMPH2_SUPPORT
    138     {
    139         _BCM_IPFIX_PROFILE_TYPE_REG,
    140         MAX_LIVE_TIME_PROFILEf,
    141         { /* stage */
    142             { /* ingress */
    143                 _BCM_IPFIX_PROFILE_ID_ING_MAXIMUM_LIVE_TIME_SET,
    144                 { ING_IPFIX_MAXIMUM_LIVE_TIME_SETr, INVALIDr },
    145                 { 0, 0 },
    146             },
    147             { /* egress */
    148                 _BCM_IPFIX_PROFILE_ID_EGR_MAXIMUM_LIVE_TIME_SET,
    149                 { EGR_IPFIX_MAXIMUM_LIVE_TIME_SETr, INVALIDr },
    150                 { 0, 0 },
    151             },
    152         },
    153     },
    154 #endif /* BCM_TRIUMPH2_SUPPORT */
    155     {
    156         _BCM_IPFIX_PROFILE_TYPE_REG,
    157         MAX_IDLE_AGE_PROFILEf,
    158         { /* stage */
    159             { /* ingress */
    160                 _BCM_IPFIX_PROFILE_ID_ING_MAXIMUM_IDLE_AGE_SET,
    161                 { ING_IPFIX_MAXIMUM_IDLE_AGE_SETr, INVALIDr },
    162                 { 0, 0 },
    163             },
    164             { /* egress */
    165                 _BCM_IPFIX_PROFILE_ID_EGR_MAXIMUM_IDLE_AGE_SET,
    166                 { EGR_IPFIX_MAXIMUM_IDLE_AGE_SETr, INVALIDr },
    167                 { 0, 0 },
    168             },
    169         },
    170     },
    171     {
    172         _BCM_IPFIX_PROFILE_TYPE_REG,
    173         SAMPLING_LIMIT_PROFILEf,
    174         { /* stage */
    175             { /* ingress */
    176                 _BCM_IPFIX_PROFILE_ID_ING_SAMPLING_LIMIT_SET,
    177                 { ING_IPFIX_SAMPLING_LIMIT_SETr, INVALIDr },
    178                 { 0, 0 },
    179             },
    180             { /* egress */
    181                 _BCM_IPFIX_PROFILE_ID_EGR_SAMPLING_LIMIT_SET,
    182                 { EGR_IPFIX_SAMPLING_LIMIT_SETr, INVALIDr },
    183                 { 0, 0 },
    184             },
    185         },
    186     },
    187     {
    188         _BCM_IPFIX_PROFILE_TYPE_NONE, /* end of table mark */
    189     },
    190 };
    191 
    192 /*
    193  * Mapping between bcm_ipfix_config_t.flags bit mask and field
    194  * of ING_IPFIX_PORT_CONFIG (or EGR_IPFIX_PORT_CONFIG)
    195  */
    196 static const _bcm_ipfix_flags_def_t _ipfix_tr_port_config_flags_def[] = {
    197     { BCM_IPFIX_CONFIG_TCP_END_DETECT, TCP_END_DETECT_ENABLEf },
    198     { BCM_IPFIX_CONFIG_KEY_SRC_IP, IP_SIP_ENABLEf },
    199     { BCM_IPFIX_CONFIG_KEY_DST_IP, IP_DIP_ENABLEf },
    200     { BCM_IPFIX_CONFIG_KEY_IP_PROT, IP_PROTOCOL_ENABLEf },
    201     { BCM_IPFIX_CONFIG_KEY_IP_DSCP, IP_DSCP_ENABLEf },
    202     { BCM_IPFIX_CONFIG_KEY_IP_ECN, IP_ECN_ENABLEf },
    203     { BCM_IPFIX_CONFIG_KEY_L4_SRC_PORT, IP_TCP_SRC_PORT_ENABLEf },
    204     { BCM_IPFIX_CONFIG_KEY_L4_DST_PORT, IP_TCP_DEST_PORT_ENABLEf },
    205     { BCM_IPFIX_CONFIG_KEY_IP6_FLOW, IP_IPV6_LABEL_ENABLEf },
    206     { BCM_IPFIX_CONFIG_KEY_ICMP_TYPE, IP_ICMP_TYPE_ENABLEf },
    207     { BCM_IPFIX_CONFIG_KEY_ICMP_CODE, IP_ICMP_CODE_ENABLEf },
    208     { BCM_IPFIX_CONFIG_KEY_MACDA, L2_MAC_DA_ENABLEf },
    209     { BCM_IPFIX_CONFIG_KEY_MACSA, L2_MAC_SA_ENABLEf },
    210     { BCM_IPFIX_CONFIG_KEY_VLAN_ID, L2_VLAN_ID_ENABLEf },
    211     { BCM_IPFIX_CONFIG_KEY_VLAN_PRI, L2_VLAN_PRI_ENABLEf },
    212     { BCM_IPFIX_CONFIG_KEY_ETHER_TYPE, L2_ETH_TYPE_ENABLEf },
    213     { BCM_IPFIX_CONFIG_KEY_VLAN_TAGGED, L2_TAGGED_ENABLEf },
    214     { 0 },
    215 };
    216 #endif /* BCM_TRIUMPH_SUPPORT */
    217 
    218 #ifdef BCM_WARM_BOOT_SUPPORT
    219 
    220 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
    221 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_0
    222 
    223 /*
    224  * Function:
    225  *      _bcm_ipfix_reinit
    226  * Description:
    227  *      Recovers ipfix rate config data info.   
    228  * Parameters:
    229  *      unit - (IN) BCM unit number
    230  * Notes:
    231  *      None.
    232  */
    233 STATIC int 
    234 _bcm_ipfix_reinit(int unit)
    235 {
    236     _bcm_ipfix_ctrl_t *ipfix_ctrl = _bcm_ipfix_ctrl[unit];
    237     soc_scache_handle_t scache_handle;
    238     uint8   *ipfix_scache = NULL;
    239     int size;
    240     int rv = BCM_E_NONE;
    241     int arry_size;
    242     
    243     sal_memset(&scache_handle , 0, sizeof(soc_scache_handle_t));
    244     size = soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm);
    245     arry_size = _SHR_BITDCLSIZE(size);
    246 
    247     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_IPFIX, 0);
    248     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &ipfix_scache, 
    249                                  BCM_WB_DEFAULT_VERSION, NULL);
    250     if (BCM_E_NOT_FOUND == rv) {
    251         ipfix_scache = NULL;
    252     } else if (BCM_FAILURE(rv)) {
    253         return rv;
    254     } else {
    255         sal_memcpy(&ipfix_ctrl->rate_used_count, ipfix_scache,
    256                             sizeof(ipfix_ctrl->rate_used_count));       
    257         ipfix_scache += sizeof(ipfix_ctrl->rate_used_count);
    258         /*
    259          * Copy rate_id pbmp value from scache to ipfix control structure.
    260          */
    261         sal_memcpy(ipfix_ctrl->rate_used_bmp, ipfix_ctrl, arry_size);
    262     }
    263 
    264     return rv;
    265 }
    266 #endif
    267 
    268 STATIC int
    269 _bcm_ipfix_gport_resolve(int unit,
    270                          bcm_gport_t gport,
    271                          bcm_port_t *local_port)
    272 {
    273     bcm_module_t    modid;
    274     bcm_port_t      port;
    275     bcm_trunk_t     tgid;
    276     int             id;
    277 
    278     if (BCM_GPORT_IS_SET(gport)) {
    279         BCM_IF_ERROR_RETURN
    280             (_bcm_esw_gport_resolve(unit, gport, &modid, &port, &tgid, &id));
    281         if (id != -1 || tgid != -1) {
    282             return BCM_E_PARAM;
    283         }
    284         *local_port = port;
    285     } else {
    286         if (!SOC_PORT_VALID(unit, gport)) {
    287             return BCM_E_PORT;
    288         }
    289         *local_port = gport;
    290     }
    291 
    292     return BCM_E_NONE;
    293 }
    294 
    295 STATIC int
    296 _bcm_ipfix_init(int unit,
    297                 const _bcm_ipfix_profile_def_t *profile_def,
    298                 const _bcm_ipfix_id_def_t *id_def)
    299 {
    300     _bcm_ipfix_ctrl_t *ipfix_ctrl = _bcm_ipfix_ctrl[unit];
    301     const _bcm_ipfix_profile_def_t *def;
    302     void *profile;
    303     soc_reg_t reg;
    304     int stage, ids[2], entry_words[2];
    305     uint32 rval;
    306     int size;
    307 #ifdef BCM_WARM_BOOT_SUPPORT
    308     soc_scache_handle_t scache_handle;
    309     uint32 ipfix_scache_size;
    310     uint32 flow_rate_tbl_size;
    311     uint8 *ipfix_scache = NULL;
    312     int rv = BCM_E_NONE;
    313 #endif /* !BCM_WARM_BOOT_SUPPORT */
    314 
    315     if (ipfix_ctrl == NULL) {
    316         ipfix_ctrl = sal_alloc(sizeof(_bcm_ipfix_ctrl_t), "IPFIX Control Data");
    317         if (ipfix_ctrl == NULL) {
    318             return BCM_E_MEMORY;
    319         }
    320         sal_memset(ipfix_ctrl, 0, sizeof(_bcm_ipfix_ctrl_t));
    321 
    322         if (soc_feature(unit, soc_feature_ipfix_rate)) {
    323             size = soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm);
    324             ipfix_ctrl->rate_used_bmp = 
    325                     sal_alloc(SHR_BITALLOCSIZE(size), "IPFIX Rate Used BMP");
    326             if (ipfix_ctrl->rate_used_bmp == NULL) {
    327                 sal_free(ipfix_ctrl);
    328                 return BCM_E_MEMORY;
    329             }
    330             sal_memset(ipfix_ctrl->rate_used_bmp, 0, SHR_BITALLOCSIZE(size));
    331             SHR_BITSET(ipfix_ctrl->rate_used_bmp, 0); /* index 0 is reserved */
    332         }
    333 
    334         _bcm_ipfix_ctrl[unit] = ipfix_ctrl;
    335 
    336         for (def = profile_def; def->type != _BCM_IPFIX_PROFILE_TYPE_NONE;
    337              def++) {
    338             for (stage = 0; stage < 2; stage++) {
    339                 if (!soc_mem_field_valid(unit, id_def->profile[stage],
    340                                          def->index_field)) {
    341                     continue;
    342                 }
    343                 profile = &ipfix_ctrl->profiles[def->stage[stage].profile_id];
    344                 if (def->type == _BCM_IPFIX_PROFILE_TYPE_REG) {
    345                     soc_profile_reg_t_init(profile);
    346                 } else if (def->type == _BCM_IPFIX_PROFILE_TYPE_MEM) {
    347                     soc_profile_mem_t_init(profile);
    348                 }
    349             }
    350         }
    351 
    352         ipfix_ctrl->pid = SAL_THREAD_ERROR;
    353 #ifdef BCM_TRIUMPH3_SUPPORT
    354         if (SOC_IS_TRIUMPH3(unit)) {
    355             ipfix_ctrl->dma_chan[0] = SOC_MEM_FIFO_DMA_CHANNEL_2;
    356         } else
    357 #endif /* BCM_TRIUMPH3_SUPPORT */
    358         {
    359             ipfix_ctrl->dma_chan[0] = SOC_MEM_FIFO_DMA_CHANNEL_0;
    360         }
    361         ipfix_ctrl->dma_chan[1] = SOC_MEM_FIFO_DMA_CHANNEL_3;
    362 
    363 #ifdef BCM_WARM_BOOT_SUPPORT
    364         if (soc_feature(unit, soc_feature_ipfix_rate)) {
    365             /*
    366              * Get the number of flow rate meter entries supported in the 
    367              * ING_IPFIX_FLOW_RATE_METER_TABLEm table.
    368              */
    369             flow_rate_tbl_size = 
    370                     soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm);
    371             ipfix_scache_size = SHR_BITALLOCSIZE(flow_rate_tbl_size) + 
    372                                     sizeof(ipfix_ctrl->rate_used_count);
    373             SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_IPFIX, 0);
    374             rv = _bcm_esw_scache_ptr_get(unit, scache_handle,
    375                                             (0 == SOC_WARM_BOOT(unit)),
    376                                             ipfix_scache_size,
    377                                             &ipfix_scache, 
    378                                             BCM_WB_DEFAULT_VERSION, NULL);
    379             if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    380                 _bcm_esw_ipfix_deinit(unit);
    381                 return rv;
    382             }
    383             sal_memset(&ipfix_scache, 0, sizeof(ipfix_scache_size));
    384         }
    385 #endif /* !BCM_WARM_BOOT_SUPPORT */
    386     }
    387 
    388     for (def = profile_def; def->type != _BCM_IPFIX_PROFILE_TYPE_NONE; def++) {
    389         for (stage = 0; stage < 2; stage++) {
    390             if (!soc_mem_field_valid(unit, id_def->profile[stage],
    391                                      def->index_field)) {
    392                 continue;
    393             }
    394             profile = &ipfix_ctrl->profiles[def->stage[stage].profile_id];
    395             ids[0] = def->stage[stage].reg_mem_id[0];
    396             ids[1] = def->stage[stage].reg_mem_id[1];
    397             if (def->type == _BCM_IPFIX_PROFILE_TYPE_REG) {
    398                 BCM_IF_ERROR_RETURN(soc_profile_reg_create(unit, ids, 1,
    399                                     profile));
    400             } else if (def->type == _BCM_IPFIX_PROFILE_TYPE_MEM) {
    401                 entry_words[0] = def->stage[stage].entry_words[0];
    402                 entry_words[1] = def->stage[stage].entry_words[1];
    403                 BCM_IF_ERROR_RETURN
    404                     (soc_profile_mem_create(unit, ids, entry_words,
    405                                             ids[1] != INVALIDm ? 2 : 1,
    406                                             profile));
    407             }
    408         }
    409     }
    410 
    411     for (stage = 0; stage < 2; stage++) {
    412         reg = id_def->age_control[stage];
    413         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
    414         soc_reg_field_set(unit, reg, &rval, AGE_ENABLEf, 1);
    415         if (SAL_BOOT_QUICKTURN) {
    416             if (soc_reg_field_valid(unit, reg, CLK_GRANf)) {         
    417                 soc_reg_field_set(unit, reg, &rval, CLK_GRANf, 0);
    418             }
    419         }
    420         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
    421     }
    422     
    423 #ifdef BCM_TRIUMPH3_SUPPORT
    424     if (SOC_IS_TRIUMPH3(unit)) {
    425         BCM_IF_ERROR_RETURN(READ_AUX_ARB_CONTROL_2r(unit, &rval));
    426         soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &rval,
    427                 IPFIX_REFRESH_ENABLEf, 1);
    428         if (SAL_BOOT_QUICKTURN) {
    429             soc_reg_field_set(unit, AUX_ARB_CONTROL_2r,
    430                               &rval, IPFIX_CLK_GRANf, 0);
    431         }
    432         BCM_IF_ERROR_RETURN(WRITE_AUX_ARB_CONTROL_2r(unit, rval));
    433     }
    434 #endif
    435 
    436 #if defined(BCM_WARM_BOOT_SUPPORT) && defined(BCM_IPFIX_SUPPORT)
    437     if (SOC_WARM_BOOT(unit)) {
    438         /*
    439          * Reload IPFIX module data.
    440          */
    441         BCM_IF_ERROR_RETURN(_bcm_ipfix_reinit(unit));
    442     }
    443 #endif /* !BCM_WARM_BOOT_SUPPORT */
    444     return BCM_E_NONE;
    445 }
    446 
    447 STATIC int
    448 _bcm_ipfix_profile_del(int unit,
    449                        const _bcm_ipfix_profile_def_t *profile_def,
    450                        const _bcm_ipfix_id_def_t *id_def,
    451                        bcm_ipfix_stage_t stage,
    452                        bcm_port_t port,
    453                        int count)
    454 {
    455     _bcm_ipfix_ctrl_t *ipfix_ctrl;
    456     const _bcm_ipfix_profile_def_t *def;
    457     void *profile;
    458     union {
    459         ing_ipfix_profile_entry_t ing_ipfix_profile;
    460         egr_ipfix_profile_entry_t egr_ipfix_profile;
    461     } profile_entry;
    462     soc_mem_t profile_mem;
    463     uint32 index;
    464     int rv;
    465 
    466     ipfix_ctrl = _bcm_ipfix_ctrl[unit];
    467     profile_mem = id_def->profile[stage];
    468 
    469     BCM_IF_ERROR_RETURN(soc_mem_read(unit, profile_mem, MEM_BLOCK_ANY,
    470                                      port, &profile_entry));
    471     rv = BCM_E_NONE;
    472     for (def = profile_def; count && def->type != _BCM_IPFIX_PROFILE_TYPE_NONE;
    473          count--, def++) {
    474         if (!soc_mem_field_valid(unit, profile_mem, def->index_field)) {
    475             continue;
    476         }
    477         profile = &ipfix_ctrl->profiles[def->stage[stage].profile_id];
    478         index = soc_mem_field32_get(unit, profile_mem, &profile_entry,
    479                                     def->index_field);
    480         if (def->type == _BCM_IPFIX_PROFILE_TYPE_REG) {
    481             rv |= soc_profile_reg_delete(unit, profile, index);
    482         } else if (def->type == _BCM_IPFIX_PROFILE_TYPE_MEM) {
    483             if (def->stage[stage].reg_mem_id[0] ==
    484                 ING_IPFIX_DSCP_XLATE_TABLEm ||
    485                 def->stage[stage].reg_mem_id[0] ==
    486                 EGR_IPFIX_DSCP_XLATE_TABLEm) {
    487                 index *= 64;
    488             }
    489             rv |= soc_profile_mem_delete(unit, profile, index);
    490         }
    491     }
    492 
    493     return rv;
    494 }
    495 
    496 /*
    497  * Function:
    498  *     _bcm_ipfix_rate_id_check
    499  * Description:
    500  *     To check the status of the specified rate_id
    501  * Parameters:
    502  *     unit            device number
    503  *     rate_id         rate identifier
    504  * Return:
    505  *     BCM_E_UNAVAIL   ipfix feature is not supported for this device
    506  *     BCM_E_INIT      ipfix component is not initialized on this device
    507  *     BCM_E_BADID     specified rate_id is not in valid range
    508  *     BCM_E_NOT_FOUND spefified rate_id is in valid range but not in used
    509  *     BCM_E_NONE      specified rate_id is in used
    510  */
    511 STATIC int
    512 _bcm_ipfix_rate_id_check(int unit,
    513                          bcm_ipfix_rate_id_t rate_id)
    514 {
    515     if (!soc_feature(unit, soc_feature_ipfix_rate)) {
    516         return BCM_E_UNAVAIL;
    517     }
    518 
    519     if (_bcm_ipfix_ctrl[unit] == NULL) {
    520         return BCM_E_INIT;
    521     }
    522 
    523     /* rate_id 0 is reserved by hardware to indicate disabling rate metering */
    524     if (rate_id < 1 || rate_id >=
    525         soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm)) {
    526         return BCM_E_BADID;
    527     }
    528 
    529     if (!SHR_BITGET(_bcm_ipfix_ctrl[unit]->rate_used_bmp, rate_id)) {
    530         return BCM_E_NOT_FOUND;
    531     }
    532 
    533     return BCM_E_NONE;
    534 }
    535 
    536 /*
    537  * Function:
    538  *     _bcm_ipfix_rate_get
    539  * Description:
    540  *     To check the status of the specified rate_id
    541  * Parameters:
    542  *     unit            device number
    543  *     rate_id         rate identifier
    544  *     rate_info       pointer to rate info structure
    545  * Return:
    546  *     BCM_E_XXX
    547  * Note:
    548  *     Caller needs to make sure all arguments are valid for this internal
    549  *     function.
    550  */
    551 STATIC int
    552 _bcm_ipfix_rate_get(int unit,
    553                     bcm_ipfix_rate_id_t rate_id,
    554                     bcm_ipfix_rate_t *rate_info)
    555 {
    556     ing_ipfix_flow_rate_meter_table_entry_t entry;
    557     uint32 cng;
    558 
    559     BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm,
    560                                      MEM_BLOCK_ANY, rate_id, &entry));
    561 
    562     sal_memset(rate_info, 0, sizeof(*rate_info));
    563     rate_info->rate_id = rate_id;
    564     rate_info->flags |= BCM_IPFIX_RATE_VIOLATION_WITH_ID;
    565     /* the token size for BUCKETCOUNT is 1/128 of a flow */
    566     rate_info->count =
    567         soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
    568                             BUCKETCOUNTf) >> 7;
    569     rate_info->limit =
    570         soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
    571                             BUCKETSIZEf);
    572     rate_info->rate =
    573         soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
    574                             REFRESHCOUNTf);
    575     if (soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
    576                             DROPf)) {
    577         rate_info->flags |= BCM_IPFIX_RATE_VIOLATION_DROP;
    578     }
    579     if (soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
    580                             COPY_TO_CPUf)) {
    581         rate_info->flags |= BCM_IPFIX_RATE_VIOLATION_COPY_TO_CPU;
    582     }
    583     if (soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
    584                             CHANGE_DSCPf)) {
    585         rate_info->flags |= BCM_IPFIX_RATE_VIOLATION_DSCP_SET;
    586         rate_info->dscp =
    587             soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
    588                                 NEW_DSCPf);
    589     }
    590     if (soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
    591                             CHANGE_CNGf)) {
    592         rate_info->flags |= BCM_IPFIX_RATE_VIOLATION_COLOR_SET;
    593         cng = soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm,
    594                                   &entry, NEW_CNGf);
    595         rate_info->color = _BCM_COLOR_DECODING(unit, cng);
    596     }
    597     if (soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
    598                             CHANGE_PKT_PRIf)) {
    599         rate_info->flags |= BCM_IPFIX_RATE_VIOLATION_PKT_PRI_SET;
    600         rate_info->pkt_pri =
    601             soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
    602                                 NEW_PRIf);
    603     }
    604     if (soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
    605                             CHANGE_INT_PRIf)) {
    606         rate_info->flags |= BCM_IPFIX_RATE_VIOLATION_INT_PRI_SET;
    607         rate_info->int_pri =
    608             soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
    609                                 NEW_INT_PRIf);
    610     }
    611 
    612     return BCM_E_NONE;
    613 }
    614 #endif /* BCM_IPFIX_SUPPORT */
    615 
    616 /*
    617  * Function:
    618  *     bcm_esw_ipfix_register
    619  * Description:
    620  *     To register the callback function for flow info export
    621  * Parameters:
    622  *     unit          device number
    623  *     callback      user callback function
    624  *     userdata      user data used as argument during callback
    625  * Return:
    626  *     BCM_E_NONE
    627  *     BCM_E_PARAM
    628  *     BCM_E_RESOURCE
    629  *     BCM_E_UNAVAIL
    630  */
    631 int
    632 bcm_esw_ipfix_register(int unit,
    633                        bcm_ipfix_callback_t callback,
    634                        void *userdata)
    635 {
    636 #ifdef BCM_IPFIX_SUPPORT
    637     _bcm_ipfix_ctrl_t *ipfix_ctrl;
    638     const _bcm_ipfix_profile_def_t *profile_def = NULL;
    639     const _bcm_ipfix_id_def_t *id_def = NULL;
    640     _bcm_ipfix_callback_entry_t *entry;
    641     int free_index, i;
    642 
    643     if (!soc_feature(unit, soc_feature_ipfix)) {
    644         return BCM_E_UNAVAIL;
    645     }
    646 
    647 #ifdef BCM_TRIUMPH_SUPPORT
    648     if (SOC_IS_TR_VL(unit)) {
    649         profile_def = _ipfix_tr_profile_def;
    650         id_def = &_ipfix_tr_id_def;
    651     }
    652 #endif /* BCM_TRIUMPH_SUPPORT */
    653     if (profile_def == NULL || id_def == NULL) {
    654         return BCM_E_INTERNAL;
    655     }
    656 
    657     if (_bcm_ipfix_ctrl[unit] == NULL) {
    658         BCM_IF_ERROR_RETURN(_bcm_ipfix_init(unit, profile_def, id_def));
    659     }
    660     ipfix_ctrl = _bcm_ipfix_ctrl[unit];
    661 
    662     if (callback == NULL) {
    663         return BCM_E_PARAM;
    664     }
    665 
    666     free_index = -1;
    667     for (i = 0; i < _BCM_IPFIX_CB_MAX; i++) {
    668         entry = &ipfix_ctrl->callback_entry[i];
    669         if (entry->state == _BCM_IPFIX_CALLBACK_STATE_INVALID ||
    670             (ipfix_ctrl->pid == SAL_THREAD_ERROR &&
    671              entry->state == _BCM_IPFIX_CALLBACK_STATE_UNREGISTERED)) {
    672             if (free_index < 0) {
    673                 free_index = i;
    674             }
    675         } else if (entry->state == _BCM_IPFIX_CALLBACK_STATE_ACTIVE ||
    676                    entry->state == _BCM_IPFIX_CALLBACK_STATE_REGISTERED) {
    677             if (entry->callback == callback && entry->userdata == userdata) {
    678                 return BCM_E_NONE;
    679             }
    680         }
    681     }
    682 
    683     if (free_index < 0) {
    684         return BCM_E_RESOURCE;
    685     }
    686 
    687     entry = &ipfix_ctrl->callback_entry[free_index];
    688     entry->callback = callback;
    689     entry->userdata = userdata;
    690     entry->state = _BCM_IPFIX_CALLBACK_STATE_REGISTERED;
    691 
    692     return BCM_E_NONE;
    693 #else /* BCM_IPFIX_SUPPORT */
    694     return BCM_E_UNAVAIL;
    695 #endif /* BCM_IPFIX_SUPPORT */
    696 }
    697 
    698 /*
    699  * Function:
    700  *     bcm_esw_ipfix_unregister
    701  * Description:
    702  *     To unregister the callback function for flow info export
    703  * Parameters:
    704  *     unit          device number
    705  *     callback      user callback function
    706  *     userdata      user data used as argument during callback
    707  * Return:
    708  *     BCM_E_NONE
    709  *     BCM_E_NOT_FOUND
    710  *     BCM_E_UNAVAIL
    711  *     BCM_E_INIT
    712  */
    713 int
    714 bcm_esw_ipfix_unregister(int unit,
    715                          bcm_ipfix_callback_t callback,
    716                          void *userdata)
    717 {
    718 #ifdef BCM_IPFIX_SUPPORT
    719     _bcm_ipfix_ctrl_t *ipfix_ctrl;
    720     _bcm_ipfix_callback_entry_t *entry;
    721     int i;
    722 
    723     if (!soc_feature(unit, soc_feature_ipfix)) {
    724         return BCM_E_UNAVAIL;
    725     }
    726 
    727     if (_bcm_ipfix_ctrl[unit] == NULL) {
    728         return BCM_E_INIT;
    729     }
    730     ipfix_ctrl = _bcm_ipfix_ctrl[unit];
    731 
    732     for (i = 0; i < _BCM_IPFIX_CB_MAX; i++) {
    733         entry = &ipfix_ctrl->callback_entry[i];
    734 
    735         if (ipfix_ctrl->pid == SAL_THREAD_ERROR ||
    736             entry->state == _BCM_IPFIX_CALLBACK_STATE_ACTIVE) {
    737             if (entry->callback == callback && entry->userdata == userdata) {
    738                 entry->state = _BCM_IPFIX_CALLBACK_STATE_UNREGISTERED;
    739                 return BCM_E_NONE;
    740             }
    741         }
    742     }
    743 
    744     return BCM_E_NOT_FOUND;
    745 #else /* BCM_IPFIX_SUPPORT */
    746     return BCM_E_UNAVAIL;
    747 #endif /* BCM_IPFIX_SUPPORT */
    748 }
    749 
    750 /*
    751  * Function:
    752  *     bcm_esw_ipfix_config_set
    753  * Description:
    754  *     To set per port IPFIX configuration
    755  * Parameters:
    756  *     unit            device number
    757  *     stage           BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS
    758  *     port            port number
    759  *     config          pointer to ipfix configuration
    760  * Return:
    761  *     BCM_E_NONE
    762  *     BCM_E_PARAM
    763  *     BCM_E_RESOURCE
    764  *     BCM_E_UNAVAIL
    765  *     BCM_E_PORT
    766  */
    767 int
    768 bcm_esw_ipfix_config_set(int unit,
    769                          bcm_ipfix_stage_t stage,
    770                          bcm_port_t port,
    771                          bcm_ipfix_config_t *config)
    772 {
    773 #ifdef BCM_IPFIX_SUPPORT
    774     _bcm_ipfix_ctrl_t *ipfix_ctrl;
    775     const _bcm_ipfix_profile_def_t *profile_def = NULL, *def;
    776     const _bcm_ipfix_id_def_t *id_def = NULL;
    777     const _bcm_ipfix_flags_def_t *flags_def = NULL;
    778     void *profile;
    779     union {
    780         ing_ipfix_profile_entry_t ing_ipfix_profile;
    781         egr_ipfix_profile_entry_t egr_ipfix_profile;
    782     } profile_entry;
    783     union {
    784         ing_ipfix_ipv4_mask_set_a_entry_t ing_ipfix_ipv4_mask_set_a;
    785         ing_ipfix_ipv4_mask_set_b_entry_t ing_ipfix_ipv4_mask_set_b;
    786         ing_ipfix_ipv6_mask_set_a_entry_t ing_ipfix_ipv6_mask_set_a;
    787         ing_ipfix_ipv6_mask_set_b_entry_t ing_ipfix_ipv6_mask_set_b;
    788         egr_ipfix_ipv4_mask_set_a_entry_t egr_ipfix_ipv4_mask_set_a;
    789         egr_ipfix_ipv6_mask_set_a_entry_t egr_ipfix_ipv6_mask_set_a;
    790         ing_ipfix_dscp_xlate_table_entry_t ing_ipfix_dscp_xlate_table[64];
    791         egr_ipfix_dscp_xlate_table_entry_t egr_ipfix_dscp_xlate_table[64];
    792         uint32 w[1];
    793     } entry0, entry1;
    794     void *entries[2];
    795     uint64 rval64, *rval64s[2];
    796     soc_reg_t reg;
    797     soc_mem_t mems[2], profile_mem;
    798     uint32 rval, fval, index, flags;
    799     int rv, count, size, i;
    800 
    801     if (!soc_feature(unit, soc_feature_ipfix)) {
    802         return BCM_E_UNAVAIL;
    803     }
    804 
    805 #ifdef BCM_TRIUMPH_SUPPORT
    806     if (SOC_IS_TR_VL(unit)) {
    807         profile_def = _ipfix_tr_profile_def;
    808         id_def = &_ipfix_tr_id_def;
    809         flags_def = _ipfix_tr_port_config_flags_def;
    810     }
    811 #endif /* BCM_TRIUMPH_SUPPORT */
    812     if (profile_def == NULL || id_def == NULL || flags_def == NULL) {
    813         return BCM_E_INTERNAL;
    814     }
    815 
    816     if (_bcm_ipfix_ctrl[unit] == NULL) {
    817         BCM_IF_ERROR_RETURN(_bcm_ipfix_init(unit, profile_def, id_def));
    818     }
    819     ipfix_ctrl = _bcm_ipfix_ctrl[unit];
    820 
    821     if (stage != BCM_IPFIX_STAGE_INGRESS && stage != BCM_IPFIX_STAGE_EGRESS) {
    822         return BCM_E_PARAM;
    823     }
    824 
    825     BCM_IF_ERROR_RETURN(_bcm_ipfix_gport_resolve(unit, port, &port));
    826 
    827     if (config == NULL) {
    828         return BCM_E_PARAM;
    829     }
    830 
    831     profile_mem = id_def->profile[stage];
    832 
    833     reg = id_def->port_config[stage];
    834     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
    835 
    836     /* Remove all previously programmed profile for the port */
    837     if (soc_reg_field_get(unit, reg, rval, IPFIX_ENABLEf)) {
    838         soc_reg_field_set(unit, reg, &rval, IPFIX_ENABLEf, 0);
    839         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
    840 
    841         BCM_IF_ERROR_RETURN(_bcm_ipfix_profile_del(unit, profile_def, id_def,
    842                                                    stage, port, -1));
    843     }
    844 
    845     /* Profile */
    846     sal_memset(&profile_entry, 0, sizeof(profile_entry));
    847     for (count = 0, def = profile_def;
    848          def->type != _BCM_IPFIX_PROFILE_TYPE_NONE; count++, def++) {
    849         if (!soc_mem_field_valid(unit, profile_mem, def->index_field)) {
    850             continue;
    851         }
    852         profile = &ipfix_ctrl->profiles[def->stage[stage].profile_id];
    853         rv = BCM_E_NONE;
    854         if (def->type == _BCM_IPFIX_PROFILE_TYPE_REG) {
    855             reg = def->stage[stage].reg_mem_id[0];
    856             rval = 0;
    857             switch (reg) {
    858             case ING_IPFIX_PORT_RECORD_LIMIT_SETr:
    859             case EGR_IPFIX_PORT_RECORD_LIMIT_SETr:
    860                 soc_reg_field_set(unit, reg, &rval, ENTRY_LIMITf,
    861                                   config->entry_limit);
    862                 break;
    863             case ING_IPFIX_MINIMUM_LIVE_TIME_SETr:
    864             case EGR_IPFIX_MINIMUM_LIVE_TIME_SETr:
    865                 soc_reg_field_set(unit, reg, &rval, MIN_RECORD_LIFEf,
    866                                   config->min_time);
    867                 break;
    868             case ING_IPFIX_MAXIMUM_LIVE_TIME_SETr:
    869             case EGR_IPFIX_MAXIMUM_LIVE_TIME_SETr:
    870                 soc_reg_field_set(unit, reg, &rval, MAX_RECORD_LIFEf,
    871                                   config->max_time);
    872                 break;
    873             case ING_IPFIX_MAXIMUM_IDLE_AGE_SETr:
    874             case EGR_IPFIX_MAXIMUM_IDLE_AGE_SETr:
    875                 soc_reg_field_set(unit, reg, &rval, MAX_IDLE_AGEf,
    876                                   config->max_idle_time);
    877                 break;
    878             case ING_IPFIX_SAMPLING_LIMIT_SETr:
    879             case EGR_IPFIX_SAMPLING_LIMIT_SETr:
    880                 soc_reg_field_set(unit, reg, &rval, SAMPLING_LIMITf,
    881                                   config->sample_rate);
    882                 break;
    883             default:
    884                 continue;
    885             }
    886             COMPILER_64_SET(rval64, 0, rval);
    887             rval64s[0] = &rval64;
    888             rv = soc_profile_reg_add(unit, profile, rval64s, 1, &index);
    889         } else if (def->type == _BCM_IPFIX_PROFILE_TYPE_MEM) {
    890             mems[0] = def->stage[stage].reg_mem_id[0];
    891             mems[1] = def->stage[stage].reg_mem_id[1];
    892             size = 1;
    893             switch (mems[0]) {
    894             case ING_IPFIX_DSCP_XLATE_TABLEm:
    895                 sal_memset(&entry0, 0, sizeof(entry0));
    896                 size = BCM_IPFIX_DSCP_MASK_COUNT;
    897                 for (i = 0; i < size; i++) {
    898                     soc_mem_field32_set(unit, mems[0],
    899                                         &entry0.ing_ipfix_dscp_xlate_table[i],
    900                                         DSCP_KEYf, config->dscp_mask[i]);
    901                 }
    902                 break;
    903             case EGR_IPFIX_DSCP_XLATE_TABLEm:
    904                 sal_memset(&entry0, 0, sizeof(entry0));
    905                 size = BCM_IPFIX_DSCP_MASK_COUNT;
    906                 for (i = 0; i < size; i++) {
    907                     soc_mem_field32_set(unit, mems[0],
    908                                         &entry0.egr_ipfix_dscp_xlate_table[i],
    909                                         DSCP_KEYf, config->dscp_mask[i]);
    910                 }
    911                 break;
    912             case ING_IPFIX_IPV4_MASK_SET_Am:
    913             case EGR_IPFIX_IPV4_MASK_SET_Am:
    914                 sal_memset(&entry0, 0, sizeof(entry0));
    915                 soc_mem_field_set(unit, mems[0], entry0.w, IPV4_SIP_MASKf,
    916                                   (uint32 *)&config->src_ip4_mask);
    917                 soc_mem_field_set(unit, mems[0], entry0.w, IPV4_DIP_MASKf,
    918                                   (uint32 *)&config->dst_ip4_mask);
    919                 if (mems[1] != INVALIDm) {
    920                     sal_memset(&entry1, 0, sizeof(entry1));
    921                     soc_mem_field_set(unit, mems[1], entry1.w,
    922                                       TUNNEL_IPV4_SIP_MASKf,
    923                                       (uint32 *)&config->tunnel_src_ip4_mask);
    924                     soc_mem_field_set(unit, mems[1], entry1.w,
    925                                       TUNNEL_IPV4_DIP_MASKf,
    926                                       (uint32 *)&config->tunnel_dst_ip4_mask);
    927                 }
    928                 break;
    929             case ING_IPFIX_IPV6_MASK_SET_Am:
    930             case EGR_IPFIX_IPV6_MASK_SET_Am:
    931                 soc_mem_field_set(unit, mems[0], entry0.w, IPV6_SIP_MASKf,
    932                                   (uint32 *)&config->src_ip6_mask);
    933                 soc_mem_field_set(unit, mems[0], entry0.w, IPV6_DIP_MASKf,
    934                                   (uint32 *)&config->dst_ip6_mask);
    935                 if (mems[1] != INVALIDm) {
    936                     sal_memset(&entry1, 0, sizeof(entry1));
    937                     soc_mem_field_set(unit, mems[1], entry1.w,
    938                                       TUNNEL_IPV6_SIP_MASKf,
    939                                       (uint32 *)&config->tunnel_src_ip6_mask);
    940                     soc_mem_field_set(unit, mems[1], entry1.w,
    941                                       TUNNEL_IPV6_DIP_MASKf,
    942                                       (uint32 *)&config->tunnel_dst_ip6_mask);
    943                 }
    944                 break;
    945             default:
    946                 continue;
    947             }
    948             entries[0] = &entry0;
    949             entries[1] = &entry1;
    950             rv = soc_profile_mem_add(unit, profile, entries, size, &index);
    951             index /= size;
    952         }
    953         if (SOC_FAILURE(rv)) {
    954             BCM_IF_ERROR_RETURN(_bcm_ipfix_profile_del(unit, profile_def,
    955                                                        id_def, stage, port,
    956                                                        count));
    957             return rv;
    958         }
    959         soc_mem_field32_set(unit, profile_mem, &profile_entry,
    960                             def->index_field, index);
    961     }
    962     BCM_IF_ERROR_RETURN
    963         (soc_mem_write(unit, profile_mem, MEM_BLOCK_ANY, port,
    964                        &profile_entry));
    965 
    966     /* Port config register */
    967     reg = id_def->port_config[stage];
    968     flags = config->flags;
    969     rval = 0;
    970     for (i = 0; flags_def[i].bit_mask; i++) {
    971         if (flags & flags_def[i].bit_mask) {
    972             soc_reg_field_set(unit, reg, &rval, flags_def[i].field, 1);
    973         }
    974     }
    975     fval = (flags & BCM_IPFIX_CONFIG_ENABLE_IP4 ? 1 : 0) |
    976            (flags & BCM_IPFIX_CONFIG_ENABLE_IP6 ? 2 : 0) |
    977            (flags & BCM_IPFIX_CONFIG_ENABLE_NON_IP ? 4 : 0);
    978     soc_reg_field_set(unit, reg, &rval, IPFIX_ENABLEf, fval);
    979     fval = (flags & BCM_IPFIX_CONFIG_KEY_IP4_USE_L2 ? 0 : 1) |
    980            (flags & BCM_IPFIX_CONFIG_KEY_IP6_USE_L2 ? 0 : 2);
    981     soc_reg_field_set(unit, reg, &rval, IPFIX_KEY_SELECTf, fval);
    982     if (config->sample_rate > 1) {
    983         soc_reg_field_set(unit, reg, &rval, IPFIX_SAMPLE_MODEf, 1);
    984     }
    985 
    986     if (flags & (BCM_IPFIX_CONFIG_RECORD_DISCARD_PKT |
    987                  BCM_IPFIX_CONFIG_RECORD_NON_DISCARD_PKT)) {
    988         /* Record all packets */
    989         fval = 1;
    990     } else if (flags & BCM_IPFIX_CONFIG_RECORD_DISCARD_PKT) {
    991         /* Record only discarded packets */
    992         fval = 2;
    993     } else if (flags & BCM_IPFIX_CONFIG_RECORD_NON_DISCARD_PKT) {
    994         /* Record only non-discarded packets */
    995         fval = 0;
    996     } else {
    997         /* Don't Record any packets */
    998         fval = 3;
    999     }
   1000 
   1001     soc_reg_field_set(unit, reg, &rval, DISCARDED_FLOWS_MODEf, fval);
   1002     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   1003         SOC_IS_VALKYRIE2(unit)|| SOC_IS_TRIUMPH3(unit)) {
   1004         if (flags & BCM_IPFIX_CONFIG_KEY_SOURCE_PORT_OR_INTERFACE) {
   1005             soc_reg_field_set(unit, reg, &rval, IP_IPFIX_INTF_ENABLEf, 1);
   1006         }
   1007         if (flags & BCM_IPFIX_CONFIG_TCP_FLAGS_LAST) {
   1008             soc_reg_field_set(unit, reg, &rval, TCP_FLAG_MODEf, 1);
   1009         }
   1010     }
   1011     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
   1012 
   1013     return BCM_E_NONE;
   1014 #else /* BCM_IPFIX_SUPPORT */
   1015     return BCM_E_UNAVAIL;
   1016 #endif /* BCM_IPFIX_SUPPORT */
   1017 }
   1018 
   1019 /*
   1020  * Function:
   1021  *     bcm_esw_ipfix_config_get
   1022  * Description:
   1023  *     To get per port IPFIX configuration
   1024  * Parameters:
   1025  *     unit            device number
   1026  *     stage           BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS
   1027  *     port            port number
   1028  *     config          pointer to ipfix configuration
   1029  * Return:
   1030  *     BCM_E_NONE
   1031  *     BCM_E_PARAM
   1032  *     BCM_E_UNAVAIL
   1033  *     BCM_E_INIT
   1034  *     BCM_E_PORT
   1035  */
   1036 int
   1037 bcm_esw_ipfix_config_get(int unit,
   1038                          bcm_ipfix_stage_t stage,
   1039                          bcm_port_t port,
   1040                          bcm_ipfix_config_t *config)
   1041 {
   1042 #ifdef BCM_IPFIX_SUPPORT
   1043     const _bcm_ipfix_profile_def_t *profile_def = NULL, *def;
   1044     const _bcm_ipfix_id_def_t *id_def = NULL;
   1045     const _bcm_ipfix_flags_def_t *flags_def = NULL;
   1046     union {
   1047         ing_ipfix_profile_entry_t ing_ipfix_profile;
   1048         egr_ipfix_profile_entry_t egr_ipfix_profile;
   1049     } profile_entry;
   1050     union {
   1051         ing_ipfix_dscp_xlate_table_entry_t ing_ipfix_dscp_xlate_table;
   1052         ing_ipfix_ipv4_mask_set_a_entry_t ing_ipfix_ipv4_mask_set_a;
   1053         ing_ipfix_ipv4_mask_set_b_entry_t ing_ipfix_ipv4_mask_set_b;
   1054         ing_ipfix_ipv6_mask_set_a_entry_t ing_ipfix_ipv6_mask_set_a;
   1055         ing_ipfix_ipv6_mask_set_b_entry_t ing_ipfix_ipv6_mask_set_b;
   1056         egr_ipfix_dscp_xlate_table_entry_t egr_ipfix_dscp_xlate_table;
   1057         egr_ipfix_ipv4_mask_set_a_entry_t egr_ipfix_ipv4_mask_set_a;
   1058         egr_ipfix_ipv6_mask_set_a_entry_t egr_ipfix_ipv6_mask_set_a;
   1059         uint32 w[1];
   1060     } entry;
   1061     soc_reg_t reg;
   1062     soc_mem_t mems[2], profile_mem;
   1063     uint32 rval, fval, index, flags;
   1064     int i;
   1065 
   1066     if (!soc_feature(unit, soc_feature_ipfix)) {
   1067         return BCM_E_UNAVAIL;
   1068     }
   1069 
   1070 #ifdef BCM_TRIUMPH_SUPPORT
   1071     if (SOC_IS_TR_VL(unit)) {
   1072         profile_def = _ipfix_tr_profile_def;
   1073         id_def = &_ipfix_tr_id_def;
   1074         flags_def = _ipfix_tr_port_config_flags_def;
   1075     }
   1076 #endif /* BCM_TRIUMPH_SUPPORT */
   1077     if (profile_def == NULL || id_def == NULL || flags_def == NULL) {
   1078         return BCM_E_INTERNAL;
   1079     }
   1080 
   1081     if (_bcm_ipfix_ctrl[unit] == NULL) {
   1082         return BCM_E_INIT;
   1083     }
   1084 
   1085     if ((stage != BCM_IPFIX_STAGE_INGRESS && stage != BCM_IPFIX_STAGE_EGRESS)
   1086         || config == NULL) {
   1087         return BCM_E_PARAM;
   1088     }
   1089 
   1090     BCM_IF_ERROR_RETURN(_bcm_ipfix_gport_resolve(unit, port, &port));
   1091 
   1092     profile_mem = id_def->profile[stage];
   1093 
   1094     /* Profile */
   1095     BCM_IF_ERROR_RETURN
   1096         (soc_mem_read(unit, profile_mem, MEM_BLOCK_ANY, port, &profile_entry));
   1097     for (def = profile_def; def->type != _BCM_IPFIX_PROFILE_TYPE_NONE; def++) {
   1098         if (!soc_mem_field_valid(unit, profile_mem, def->index_field)) {
   1099             continue;
   1100         }
   1101         index = soc_mem_field32_get(unit, profile_mem, &profile_entry,
   1102                                     def->index_field);
   1103         if (def->type == _BCM_IPFIX_PROFILE_TYPE_REG) {
   1104             reg = def->stage[stage].reg_mem_id[0];
   1105             BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval));
   1106             switch (reg) {
   1107             case ING_IPFIX_PORT_RECORD_LIMIT_SETr:
   1108             case EGR_IPFIX_PORT_RECORD_LIMIT_SETr:
   1109                 config->entry_limit = soc_reg_field_get(unit, reg, rval,
   1110                                                         ENTRY_LIMITf);
   1111                 break;
   1112             case ING_IPFIX_MINIMUM_LIVE_TIME_SETr:
   1113             case EGR_IPFIX_MINIMUM_LIVE_TIME_SETr:
   1114                 config->min_time = soc_reg_field_get(unit, reg, rval,
   1115                                                      MIN_RECORD_LIFEf);
   1116                 break;
   1117             case ING_IPFIX_MAXIMUM_LIVE_TIME_SETr:
   1118             case EGR_IPFIX_MAXIMUM_LIVE_TIME_SETr:
   1119                 config->max_time = soc_reg_field_get(unit, reg, rval,
   1120                                                      MAX_RECORD_LIFEf);
   1121                 break;
   1122             case ING_IPFIX_MAXIMUM_IDLE_AGE_SETr:
   1123             case EGR_IPFIX_MAXIMUM_IDLE_AGE_SETr:
   1124                 config->max_idle_time = soc_reg_field_get(unit, reg, rval,
   1125                                                           MAX_IDLE_AGEf);
   1126                 break;
   1127             case ING_IPFIX_SAMPLING_LIMIT_SETr:
   1128             case EGR_IPFIX_SAMPLING_LIMIT_SETr:
   1129                 config->sample_rate = soc_reg_field_get(unit, reg, rval,
   1130                                                         SAMPLING_LIMITf);
   1131                 break;
   1132             default:
   1133                 continue;
   1134             }
   1135         } else if (def->type == _BCM_IPFIX_PROFILE_TYPE_MEM) {
   1136             mems[0] = def->stage[stage].reg_mem_id[0];
   1137             mems[1] = def->stage[stage].reg_mem_id[1];
   1138             switch (mems[0]) {
   1139             case ING_IPFIX_DSCP_XLATE_TABLEm:
   1140             case EGR_IPFIX_DSCP_XLATE_TABLEm:
   1141                 for (i = 0; i < BCM_IPFIX_DSCP_MASK_COUNT; i++) {
   1142                     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mems[0],
   1143                                         MEM_BLOCK_ANY, index * 64 + i,
   1144                                         &entry));
   1145                     config->dscp_mask[i] =
   1146                         soc_mem_field32_get(unit, mems[0], entry.w, DSCP_KEYf);
   1147                 }
   1148                 break;
   1149             case ING_IPFIX_IPV4_MASK_SET_Am:
   1150             case EGR_IPFIX_IPV4_MASK_SET_Am:
   1151                 BCM_IF_ERROR_RETURN
   1152                     (soc_mem_read(unit, mems[0], MEM_BLOCK_ANY, index,
   1153                                   &entry));
   1154                 soc_mem_field_get(unit, mems[0], entry.w, IPV4_SIP_MASKf,
   1155                                   (uint32 *)&config->src_ip4_mask);
   1156                 soc_mem_field_get(unit, mems[0], entry.w, IPV4_DIP_MASKf,
   1157                                   (uint32 *)&config->dst_ip4_mask);
   1158                 if (mems[1] != INVALIDm) {
   1159                     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mems[1],
   1160                                                      MEM_BLOCK_ANY, index,
   1161                                                      &entry));
   1162                     soc_mem_field_get(unit, mems[1], entry.w,
   1163                                       TUNNEL_IPV4_SIP_MASKf,
   1164                                       (uint32 *)&config->tunnel_src_ip4_mask);
   1165                     soc_mem_field_get(unit, mems[1], entry.w,
   1166                                       TUNNEL_IPV4_DIP_MASKf,
   1167                                       (uint32 *)&config->tunnel_dst_ip4_mask);
   1168                 }
   1169                 break;
   1170             case ING_IPFIX_IPV6_MASK_SET_Am:
   1171             case EGR_IPFIX_IPV6_MASK_SET_Am:
   1172                 BCM_IF_ERROR_RETURN
   1173                     (soc_mem_read(unit, mems[0], MEM_BLOCK_ANY, index,
   1174                                   &entry));
   1175                 soc_mem_field_get(unit, mems[0], entry.w, IPV6_SIP_MASKf,
   1176                                   (uint32 *)&config->src_ip6_mask);
   1177                 soc_mem_field_get(unit, mems[0], entry.w, IPV6_DIP_MASKf,
   1178                                   (uint32 *)&config->dst_ip6_mask);
   1179                 if (mems[1] != INVALIDm) {
   1180                     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mems[1],
   1181                                                      MEM_BLOCK_ANY, index,
   1182                                                      &entry));
   1183                     soc_mem_field_get(unit, mems[1], entry.w,
   1184                                       TUNNEL_IPV6_SIP_MASKf,
   1185                                       (uint32 *)&config->tunnel_src_ip6_mask);
   1186                     soc_mem_field_get(unit, mems[1], entry.w,
   1187                                       TUNNEL_IPV6_DIP_MASKf,
   1188                                       (uint32 *)&config->tunnel_dst_ip6_mask);
   1189                 }
   1190                 break;
   1191             default:
   1192                 continue;
   1193             }
   1194         }
   1195     }
   1196 
   1197     /* Port config register */
   1198     reg = id_def->port_config[stage];
   1199     flags = 0;
   1200     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
   1201     for (i = 0; flags_def[i].bit_mask; i++) {
   1202         if (soc_reg_field_get(unit, reg, rval, flags_def[i].field)) {
   1203             flags |= flags_def[i].bit_mask;
   1204         }
   1205     }
   1206     fval = soc_reg_field_get(unit, reg, rval, IPFIX_ENABLEf);
   1207     flags |= ((fval & 1 ? BCM_IPFIX_CONFIG_ENABLE_IP4 : 0) |
   1208               (fval & 2 ? BCM_IPFIX_CONFIG_ENABLE_IP6 : 0) |
   1209               (fval & 4 ? BCM_IPFIX_CONFIG_ENABLE_NON_IP : 0));
   1210     fval = soc_reg_field_get(unit, reg, rval, IPFIX_KEY_SELECTf);
   1211     flags |= ((fval & 1 ? 0 : BCM_IPFIX_CONFIG_KEY_IP4_USE_L2) |
   1212               (fval & 2 ? 0 : BCM_IPFIX_CONFIG_KEY_IP6_USE_L2));
   1213     fval = soc_reg_field_get(unit, reg, rval, IPFIX_SAMPLE_MODEf);
   1214     if (!fval) {
   1215         config->sample_rate = 0;
   1216     }
   1217     fval = soc_reg_field_get(unit, reg, rval, DISCARDED_FLOWS_MODEf);
   1218     if (fval == 0) {
   1219         flags |= BCM_IPFIX_CONFIG_RECORD_NON_DISCARD_PKT;
   1220     } else if (fval == 1) {
   1221         flags |= (BCM_IPFIX_CONFIG_RECORD_NON_DISCARD_PKT |
   1222                   BCM_IPFIX_CONFIG_RECORD_DISCARD_PKT);
   1223     } else if (fval == 2) {
   1224         flags |= BCM_IPFIX_CONFIG_RECORD_DISCARD_PKT;
   1225     }
   1226     config->flags = flags;
   1227 
   1228     return BCM_E_NONE;
   1229 #else /* BCM_IPFIX_SUPPORT */
   1230     return BCM_E_UNAVAIL;
   1231 #endif /* BCM_IPFIX_SUPPORT */
   1232 }
   1233 
   1234 /*
   1235  * Function:
   1236  *     bcm_esw_ipfix_rate_create
   1237  * Description:
   1238  *     Add an IPFIX flow rate meter entry
   1239  * Parameters:
   1240  *     unit            device number
   1241  *     rate_info       pointer to rate information
   1242  * Return:
   1243  *     BCM_E_NONE
   1244  *     BCM_E_PARAM
   1245  *     BCM_E_RESOURCE
   1246  *     BCM_E_UNAVAIL
   1247  */
   1248 int
   1249 bcm_esw_ipfix_rate_create(int unit,
   1250                           bcm_ipfix_rate_t *rate_info)
   1251 {
   1252 #ifdef BCM_IPFIX_SUPPORT
   1253     _bcm_ipfix_ctrl_t *ipfix_ctrl;
   1254     const _bcm_ipfix_profile_def_t *profile_def = NULL;
   1255     const _bcm_ipfix_id_def_t *id_def = NULL;
   1256     ing_ipfix_flow_rate_meter_table_entry_t entry;
   1257     bcm_ipfix_rate_id_t free_rate_id;
   1258     int rv, size, bmp_size, i;
   1259     uint32 bits, cng, rval;
   1260 
   1261     if (!soc_feature(unit, soc_feature_ipfix_rate)) {
   1262         return BCM_E_UNAVAIL;
   1263     }
   1264 
   1265 #ifdef BCM_TRIUMPH_SUPPORT
   1266     if (SOC_IS_TR_VL(unit)) {
   1267         profile_def = _ipfix_tr_profile_def;
   1268         id_def = &_ipfix_tr_id_def;
   1269     }
   1270 #endif /* BCM_TRIUMPH_SUPPORT */
   1271     if (profile_def == NULL || id_def == NULL) {
   1272         return BCM_E_INTERNAL;
   1273     }
   1274 
   1275     if (_bcm_ipfix_ctrl[unit] == NULL) {
   1276         BCM_IF_ERROR_RETURN(_bcm_ipfix_init(unit, profile_def, id_def));
   1277     }
   1278     ipfix_ctrl = _bcm_ipfix_ctrl[unit];
   1279     size = soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm);
   1280 
   1281     if (rate_info == NULL) {
   1282         return BCM_E_PARAM;
   1283     }
   1284 
   1285     if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_WITH_ID) {
   1286         rv = _bcm_ipfix_rate_id_check(unit, rate_info->rate_id);
   1287         if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_REPLACE) {
   1288             if (BCM_FAILURE(rv)) {
   1289                 return rv;
   1290             }
   1291         } else {
   1292             if (BCM_SUCCESS(rv)) {
   1293                 return BCM_E_EXISTS;
   1294             } else if (rv != BCM_E_NOT_FOUND) {
   1295                 return rv;
   1296             }
   1297         }
   1298     } else {
   1299         if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_REPLACE) {
   1300             return BCM_E_PARAM;
   1301         }
   1302     }
   1303 
   1304     if (rate_info->limit >=
   1305         (1 << soc_mem_field_length(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm,
   1306                                    BUCKETSIZEf))) {
   1307         return BCM_E_PARAM;
   1308     }
   1309 
   1310     if (rate_info->rate >=
   1311         (1 << soc_mem_field_length(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm,
   1312                                    REFRESHCOUNTf))) {
   1313         return BCM_E_PARAM;
   1314     }
   1315 
   1316     if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_DSCP_SET) {
   1317         if (rate_info->dscp > 63) {
   1318             return BCM_E_PARAM;
   1319         }
   1320     }
   1321 
   1322     if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_COLOR_SET) {
   1323         if (rate_info->color < 0 || rate_info->color >= bcmColorCount) {
   1324             return BCM_E_PARAM;
   1325         }
   1326     }
   1327 
   1328     if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_PKT_PRI_SET) {
   1329         if (rate_info->pkt_pri < 0 || rate_info->pkt_pri > 7) {
   1330             return BCM_E_PARAM;
   1331         }
   1332     }
   1333 
   1334     if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_INT_PRI_SET) {
   1335         if (rate_info->int_pri < 0 ||
   1336             rate_info->int_pri >=
   1337             (1 << soc_mem_field_length(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm,
   1338                                        NEW_INT_PRIf))) {
   1339 
   1340             return BCM_E_PARAM;
   1341         }
   1342     }
   1343 
   1344     if (!(rate_info->flags & BCM_IPFIX_RATE_VIOLATION_WITH_ID)) {
   1345         free_rate_id = size;
   1346         bmp_size = _SHR_BITDCLSIZE(size);
   1347         /* find the index of first zero from rate_used_bmp */
   1348         for (i = 0; i < bmp_size; i++) {
   1349             if (ipfix_ctrl->rate_used_bmp[i] == 0xffffffff) {
   1350                 continue;
   1351             }
   1352             bits = ipfix_ctrl->rate_used_bmp[i];
   1353             bits &= (bits << 1) | 0x00000001;
   1354             bits &= (bits << 2) | 0x00000003;
   1355             bits &= (bits << 4) | 0x0000000f;
   1356             bits &= (bits << 8) | 0x000000ff;
   1357             bits &= (bits << 16) | 0x0000ffff;
   1358             free_rate_id = (i << 5) + _shr_popcount(bits);
   1359             break;
   1360         }
   1361         if (free_rate_id >= size) {
   1362             return BCM_E_RESOURCE;
   1363         }
   1364         rate_info->rate_id = free_rate_id;
   1365     }
   1366 
   1367     sal_memset(&entry, 0, sizeof(entry));
   1368     soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1369                         BUCKETSIZEf, rate_info->limit);
   1370     soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1371                         REFRESHCOUNTf, rate_info->rate);
   1372     if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_DROP) {
   1373         soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1374                             DROPf, 1);
   1375     }
   1376     if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_COPY_TO_CPU) {
   1377         soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1378                             COPY_TO_CPUf, 1);
   1379     }
   1380     if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_DSCP_SET) {
   1381         soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1382                             CHANGE_DSCPf, 1);
   1383         soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1384                             NEW_DSCPf, rate_info->dscp);
   1385     }
   1386     if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_COLOR_SET) {
   1387         soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1388                             CHANGE_CNGf, 1);
   1389         cng = _BCM_COLOR_ENCODING(unit, rate_info->color);
   1390         soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1391                             NEW_CNGf, cng);
   1392     }
   1393     if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_PKT_PRI_SET) {
   1394         soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1395                             CHANGE_PKT_PRIf, 1);
   1396         soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1397                             NEW_PRIf, rate_info->pkt_pri);
   1398     }
   1399     if (rate_info->flags & BCM_IPFIX_RATE_VIOLATION_INT_PRI_SET) {
   1400         soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1401                             CHANGE_INT_PRIf, 1);
   1402         soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1403                             NEW_INT_PRIf, rate_info->int_pri);
   1404     }
   1405     BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm,
   1406                                       MEM_BLOCK_ANY, rate_info->rate_id,
   1407                                       &entry));
   1408 
   1409     SHR_BITSET(ipfix_ctrl->rate_used_bmp, rate_info->rate_id);
   1410 
   1411     if (!(rate_info->flags & BCM_IPFIX_RATE_VIOLATION_REPLACE)) {
   1412         if (!ipfix_ctrl->rate_used_count) {
   1413             BCM_IF_ERROR_RETURN(READ_ING_IPFIX_CONFIGr(unit, &rval));
   1414             soc_reg_field_set(unit, ING_IPFIX_CONFIGr, &rval,
   1415                               FLOW_RATE_ENABLEf, 1);
   1416             BCM_IF_ERROR_RETURN(WRITE_ING_IPFIX_CONFIGr(unit, rval));
   1417         }
   1418         ipfix_ctrl->rate_used_count++;
   1419     }
   1420 
   1421     return BCM_E_NONE;
   1422 #else /* BCM_IPFIX_SUPPORT */
   1423     return BCM_E_UNAVAIL;
   1424 #endif /* BCM_IPFIX_SUPPORT */
   1425 }
   1426 
   1427 /*
   1428  * Function:
   1429  *     bcm_esw_ipfix_rate_destroy
   1430  * Description:
   1431  *     Delete an IPFIX flow rate meter entry
   1432  * Parameters:
   1433  *     unit            device number
   1434  *     rate_id         rate identifier
   1435  * Return:
   1436  *     BCM_E_NONE
   1437  *     BCM_E_NOT_FOUND
   1438  *     BCM_E_BADID
   1439  *     BCM_E_UNAVAIL
   1440  *     BCM_E_INIT
   1441  */
   1442 int
   1443 bcm_esw_ipfix_rate_destroy(int unit,
   1444                            bcm_ipfix_rate_id_t rate_id)
   1445 {
   1446 #ifdef BCM_IPFIX_SUPPORT
   1447     _bcm_ipfix_ctrl_t *ipfix_ctrl;
   1448     uint32 rval;
   1449 
   1450     BCM_IF_ERROR_RETURN(_bcm_ipfix_rate_id_check(unit, rate_id));
   1451 
   1452     ipfix_ctrl = _bcm_ipfix_ctrl[unit];
   1453 
   1454     SHR_BITCLR(ipfix_ctrl->rate_used_bmp, rate_id);
   1455 
   1456     ipfix_ctrl->rate_used_count--;
   1457     if (!ipfix_ctrl->rate_used_count) {
   1458         BCM_IF_ERROR_RETURN(READ_ING_IPFIX_CONFIGr(unit, &rval));
   1459         soc_reg_field_set(unit, ING_IPFIX_CONFIGr, &rval, FLOW_RATE_ENABLEf,
   1460                           0);
   1461         BCM_IF_ERROR_RETURN(WRITE_ING_IPFIX_CONFIGr(unit, rval));
   1462     }
   1463 
   1464     return BCM_E_NONE;
   1465 #else /* BCM_IPFIX_SUPPORT */
   1466     return BCM_E_UNAVAIL;
   1467 #endif /* BCM_IPFIX_SUPPORT */
   1468 }
   1469 
   1470 /*
   1471  * Function:
   1472  *     bcm_esw_ipfix_rate_get
   1473  * Description:
   1474  *     Get IPFIX flow rate meter entry for the specified id
   1475  * Parameters:
   1476  *     unit            device number
   1477  *     rate_info       pointer to rate information carrying rate identifier
   1478  * Return:
   1479  *     BCM_E_NONE
   1480  *     BCM_E_PARAM
   1481  *     BCM_E_NOT_FOUND
   1482  *     BCM_E_BADID
   1483  *     BCM_E_UNAVAIL
   1484  *     BCM_E_INIT
   1485  */
   1486 int
   1487 bcm_esw_ipfix_rate_get(int unit,
   1488                        bcm_ipfix_rate_t *rate_info)
   1489 {
   1490 #ifdef BCM_IPFIX_SUPPORT
   1491     if (rate_info == NULL) {
   1492         return BCM_E_PARAM;
   1493     }
   1494 
   1495     BCM_IF_ERROR_RETURN(_bcm_ipfix_rate_id_check(unit, rate_info->rate_id));
   1496 
   1497     return _bcm_ipfix_rate_get(unit, rate_info->rate_id, rate_info);
   1498 #else /* BCM_IPFIX_SUPPORT */
   1499     return BCM_E_UNAVAIL;
   1500 #endif /* BCM_IPFIX_SUPPORT */
   1501 }
   1502 
   1503 /*
   1504  * Function:
   1505  *     bcm_esw_ipfix_rate_traverse
   1506  * Description:
   1507  *     Traverse through IPFIX flow rate meter entries
   1508  * Parameters:
   1509  *     unit            device number
   1510  *     cb              user callback function
   1511  *     userdata        user data used as argument during callback
   1512  * Return:
   1513  *     BCM_E_NONE
   1514  *     BCM_E_PARAM
   1515  *     BCM_E_UNAVAIL
   1516  *     BCM_E_INIT
   1517  */
   1518 int
   1519 bcm_esw_ipfix_rate_traverse(int unit,
   1520                             bcm_ipfix_rate_traverse_cb cb,
   1521                             void *userdata)
   1522 {
   1523 #ifdef BCM_IPFIX_SUPPORT
   1524     bcm_ipfix_rate_t rate_info;
   1525     int size, index;
   1526 
   1527     if (!soc_feature(unit, soc_feature_ipfix_rate)) {
   1528         return BCM_E_UNAVAIL;
   1529     }
   1530 
   1531     if (_bcm_ipfix_ctrl[unit] == NULL) {
   1532         return BCM_E_INIT;
   1533     }
   1534 
   1535     if (cb == NULL) {
   1536         return BCM_E_PARAM;
   1537     }
   1538 
   1539     size = soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm);
   1540     for (index = 1; index < size; index++) {
   1541         if (!SHR_BITGET(_bcm_ipfix_ctrl[unit]->rate_used_bmp, index)) {
   1542             continue;
   1543         }
   1544         BCM_IF_ERROR_RETURN(_bcm_ipfix_rate_get(unit, index, &rate_info));
   1545         (*cb)(unit, &rate_info, userdata);
   1546     }
   1547 
   1548     return BCM_E_NONE;
   1549 #else /* BCM_IPFIX_SUPPORT */
   1550     return BCM_E_UNAVAIL;
   1551 #endif /* BCM_IPFIX_SUPPORT */
   1552 }
   1553 
   1554 /*
   1555  * Function:
   1556  *     bcm_esw_ipfix_rate_destroy_all
   1557  * Description:
   1558  *     Delete all IPFIX flow rate meter entries
   1559  * Parameters:
   1560  *     unit            device number
   1561  * Return:
   1562  *     BCM_E_NONE
   1563  *     BCM_E_UNAVAIL
   1564  *     BCM_E_INIT
   1565  */
   1566 int
   1567 bcm_esw_ipfix_rate_destroy_all(int unit)
   1568 {
   1569 #ifdef BCM_IPFIX_SUPPORT
   1570     _bcm_ipfix_ctrl_t *ipfix_ctrl;
   1571     int size;
   1572 
   1573     if (!soc_feature(unit, soc_feature_ipfix_rate)) {
   1574         return BCM_E_UNAVAIL;
   1575     }
   1576 
   1577     if (_bcm_ipfix_ctrl[unit] == NULL) {
   1578         return BCM_E_INIT;
   1579     }
   1580     ipfix_ctrl = _bcm_ipfix_ctrl[unit];
   1581     size = soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm);
   1582 
   1583     sal_memset(ipfix_ctrl->rate_used_bmp, 0, SHR_BITALLOCSIZE(size));
   1584     SHR_BITSET(ipfix_ctrl->rate_used_bmp, 0); /* index 0 is reserved */
   1585 
   1586     return BCM_E_NONE;
   1587 #else /* BCM_IPFIX_SUPPORT */
   1588     return BCM_E_UNAVAIL;
   1589 #endif /* BCM_IPFIX_SUPPORT */
   1590 }
   1591 
   1592 /*
   1593  * Function:
   1594  *     bcm_esw_ipfix_rate_mirror_add
   1595  * Description:
   1596  *     Add a mirror destination to the IPFIX flow rate meter entry
   1597  * Parameters:
   1598  *     unit            device number
   1599  *     rate_id         rate identifier
   1600  *     mirror_dest_id  pre-allocated mirror destination identifier
   1601  * Return:
   1602  *     BCM_E_NONE
   1603  *     BCM_E_NOT_FOUND
   1604  *     BCM_E_EXISTS
   1605  *     BCM_E_BADID
   1606  *     BCM_E_RESOURCE
   1607  *     BCM_E_UNAVAIL
   1608  *     BCM_E_INIT
   1609  */
   1610 int
   1611 bcm_esw_ipfix_rate_mirror_add(int unit,
   1612                               bcm_ipfix_rate_id_t rate_id,
   1613                               bcm_gport_t mirror_dest_id)
   1614 {
   1615 #ifdef BCM_IPFIX_SUPPORT
   1616     const _bcm_ipfix_id_def_t *id_def = NULL;
   1617     ing_ipfix_flow_rate_meter_table_entry_t entry;
   1618     uint32 mirror_bmp;
   1619     int mtp_index, free_index, index;
   1620 
   1621     BCM_IF_ERROR_RETURN(_bcm_ipfix_rate_id_check(unit, rate_id));
   1622 
   1623 #ifdef BCM_TRIUMPH_SUPPORT
   1624     if (SOC_IS_TR_VL(unit)) {
   1625         id_def = &_ipfix_tr_id_def;
   1626     }
   1627 #endif /* BCM_TRIUMPH_SUPPORT */
   1628     if (id_def == NULL) {
   1629         return BCM_E_INTERNAL;
   1630     }
   1631 
   1632     if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) {
   1633         return BCM_E_BADID;
   1634     }
   1635     mtp_index = BCM_GPORT_MIRROR_GET(mirror_dest_id);
   1636 
   1637     BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm,
   1638                                      MEM_BLOCK_ANY, rate_id, &entry));
   1639     mirror_bmp = soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm,
   1640                                      &entry, MIRRORf);
   1641 
   1642     free_index = -1;
   1643     for (index = _BCM_IPFIX_RATE_MIRROR_COUNT - 1; index >= 0; index--) {
   1644         if (!(mirror_bmp & (1 << index))) {
   1645             free_index = index;
   1646             continue;
   1647         }
   1648         if (soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1649                                 id_def->mtp_index[index]) == mtp_index) {
   1650             return BCM_E_EXISTS;
   1651         }
   1652     }
   1653     if (free_index < 0) {
   1654         return BCM_E_RESOURCE;
   1655     }
   1656 
   1657     soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1658                         id_def->mtp_index[free_index], mtp_index);
   1659     soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1660                         MIRRORf, mirror_bmp | (1 << free_index));
   1661     BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm,
   1662                                       MEM_BLOCK_ANY, rate_id, &entry));
   1663 
   1664     return BCM_E_NONE;
   1665 #else /* BCM_IPFIX_SUPPORT */
   1666     return BCM_E_UNAVAIL;
   1667 #endif /* BCM_IPFIX_SUPPORT */
   1668 }
   1669 
   1670 /*
   1671  * Function:
   1672  *     bcm_esw_ipfix_rate_mirror_delete
   1673  * Description:
   1674  *     Delete a mirror destination from the IPFIX flow rate meter entry
   1675  * Parameters:
   1676  *     unit            device number
   1677  *     rate_id         rate identifier
   1678  *     mirror_dest_id  pre-allocated mirror destination identifier
   1679  * Return:
   1680  *     BCM_E_NONE
   1681  *     BCM_E_NOT_FOUND
   1682  *     BCM_E_BADID
   1683  *     BCM_E_UNAVAIL
   1684  *     BCM_E_INIT
   1685  */
   1686 int
   1687 bcm_esw_ipfix_rate_mirror_delete(int unit,
   1688                                  bcm_ipfix_rate_id_t rate_id,
   1689                                  bcm_gport_t mirror_dest_id)
   1690 {
   1691 #ifdef BCM_IPFIX_SUPPORT
   1692     const _bcm_ipfix_id_def_t *id_def = NULL;
   1693     ing_ipfix_flow_rate_meter_table_entry_t entry;
   1694     uint32 mirror_bmp;
   1695     int mtp_index, index;
   1696 
   1697     BCM_IF_ERROR_RETURN(_bcm_ipfix_rate_id_check(unit, rate_id));
   1698 
   1699 #ifdef BCM_TRIUMPH_SUPPORT
   1700     if (SOC_IS_TR_VL(unit)) {
   1701         id_def = &_ipfix_tr_id_def;
   1702     }
   1703 #endif /* BCM_TRIUMPH_SUPPORT */
   1704     if (id_def == NULL) {
   1705         return BCM_E_INTERNAL;
   1706     }
   1707 
   1708     if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) {
   1709         return BCM_E_BADID;
   1710     }
   1711     mtp_index = BCM_GPORT_MIRROR_GET(mirror_dest_id);
   1712 
   1713     BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm,
   1714                                      MEM_BLOCK_ANY, rate_id, &entry));
   1715     mirror_bmp = soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm,
   1716                                      &entry, MIRRORf);
   1717 
   1718     for (index = 0; index < _BCM_IPFIX_RATE_MIRROR_COUNT; index++) {
   1719         if (!(mirror_bmp & (1 << index))) {
   1720             continue;
   1721         }
   1722         if (soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1723                                 id_def->mtp_index[index]) == mtp_index) {
   1724             break;
   1725         }
   1726     }
   1727     if (index == _BCM_IPFIX_RATE_MIRROR_COUNT) {
   1728         return BCM_E_NOT_FOUND;
   1729     }
   1730 
   1731     soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1732                         MIRRORf, mirror_bmp ^ (1 << index));
   1733     BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm,
   1734                                       MEM_BLOCK_ANY, rate_id, &entry));
   1735 
   1736     return BCM_E_NONE;
   1737 #else /* BCM_IPFIX_SUPPORT */
   1738     return BCM_E_UNAVAIL;
   1739 #endif /* BCM_IPFIX_SUPPORT */
   1740 }
   1741 
   1742 /*
   1743  * Function:
   1744  *     bcm_esw_ipfix_rate_mirror_delete_all
   1745  * Description:
   1746  *     Delete all mirror destination associated to the IPFIX flow rate meter
   1747  *     entry
   1748  * Parameters:
   1749  *     unit            device number
   1750  *     rate_id         rate identifier
   1751  * Return:
   1752  *     BCM_E_NONE
   1753  *     BCM_E_NOT_FOUND
   1754  *     BCM_E_BADID
   1755  *     BCM_E_UNAVAIL
   1756  *     BCM_E_INIT
   1757  */
   1758 int
   1759 bcm_esw_ipfix_rate_mirror_delete_all(int unit,
   1760                                      bcm_ipfix_rate_id_t rate_id)
   1761 {
   1762 #ifdef BCM_IPFIX_SUPPORT
   1763     ing_ipfix_flow_rate_meter_table_entry_t entry;
   1764 
   1765     BCM_IF_ERROR_RETURN(_bcm_ipfix_rate_id_check(unit, rate_id));
   1766 
   1767     BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm,
   1768                                      MEM_BLOCK_ANY, rate_id, &entry));
   1769     soc_mem_field32_set(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm, &entry,
   1770                         MIRRORf, 0);
   1771     BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm,
   1772                                       MEM_BLOCK_ANY, rate_id, &entry));
   1773 
   1774     return BCM_E_NONE;
   1775 #else /* BCM_IPFIX_SUPPORT */
   1776     return BCM_E_UNAVAIL;
   1777 #endif /* BCM_IPFIX_SUPPORT */
   1778 }
   1779 
   1780 /*
   1781  * Function:
   1782  *     bcm_esw_ipfix_rate_mirror_get
   1783  * Description:
   1784  *     Get all mirror destination from the IPFIX flow rate meter entry
   1785  * Parameters:
   1786  *     unit              device number
   1787  *     rate_id           rate identifier
   1788  *     mirror_dest_size  size of mirror_dest_id array
   1789  *     mirror_dest_id    array to store mirror destination identifier
   1790  *     mirror_dest_count number of entries stored in the mirror_dest_id array
   1791  * Return:
   1792  *     BCM_E_NONE
   1793  *     BCM_E_NOT_FOUND
   1794  *     BCM_E_BADID
   1795  *     BCM_E_UNAVAIL
   1796  *     BCM_E_INIT
   1797  */
   1798 int
   1799 bcm_esw_ipfix_rate_mirror_get(int unit,
   1800                               bcm_ipfix_rate_id_t rate_id,
   1801                               int mirror_dest_size,
   1802                               bcm_gport_t *mirror_dest_id,
   1803                               int *mirror_dest_count)
   1804 {
   1805 #ifdef BCM_IPFIX_SUPPORT
   1806     const _bcm_ipfix_id_def_t *id_def = NULL;
   1807     ing_ipfix_flow_rate_meter_table_entry_t entry;
   1808     uint32 mirror_bmp;
   1809     int mtp_index, index;
   1810 
   1811     BCM_IF_ERROR_RETURN(_bcm_ipfix_rate_id_check(unit, rate_id));
   1812 
   1813 #ifdef BCM_TRIUMPH_SUPPORT
   1814     if (SOC_IS_TR_VL(unit)) {
   1815         id_def = &_ipfix_tr_id_def;
   1816     }
   1817 #endif /* BCM_TRIUMPH_SUPPORT */
   1818     if (id_def == NULL) {
   1819         return BCM_E_INTERNAL;
   1820     }
   1821 
   1822     if (mirror_dest_id == NULL || mirror_dest_count == NULL) {
   1823         return BCM_E_PARAM;
   1824     }
   1825 
   1826     BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm,
   1827                                      MEM_BLOCK_ANY, rate_id, &entry));
   1828 
   1829     mirror_bmp = soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm,
   1830                                      &entry, MIRRORf);
   1831 
   1832     *mirror_dest_count = 0;
   1833     for (index = 0; index < _BCM_IPFIX_RATE_MIRROR_COUNT; index++) {
   1834         if (!(mirror_bmp & (1 << index))) {
   1835             continue;
   1836         }
   1837         if (*mirror_dest_count >= mirror_dest_size) {
   1838             break;
   1839         }
   1840         mtp_index = soc_mem_field32_get(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm,
   1841                                         &entry, id_def->mtp_index[index]);
   1842         BCM_GPORT_MIRROR_SET(mirror_dest_id[*mirror_dest_count], mtp_index);
   1843         (*mirror_dest_count)++;
   1844     }
   1845 
   1846     return BCM_E_NONE;
   1847 #else /* BCM_IPFIX_SUPPORT */
   1848     return BCM_E_UNAVAIL;
   1849 #endif /* BCM_IPFIX_SUPPORT */
   1850 }
   1851 
   1852 /*
   1853  * Function:
   1854  *     bcm_esw_ipfix_mirror_config_set
   1855  * Description:
   1856  *     Set IPFIX mirror control configuration of the specified port
   1857  * Parameters:
   1858  *     unit            device number
   1859  *     stage           BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS
   1860  *     port            generic port identifier
   1861  *     config          pointer to ipfix mirror configuration
   1862  * Return:
   1863  *     BCM_E_NONE
   1864  *     BCM_E_PARAM
   1865  *     BCM_E_UNAVAIL
   1866  *     BCM_E_INIT
   1867  *     BCM_E_PORT
   1868  */
   1869 int
   1870 bcm_esw_ipfix_mirror_config_set(int unit,
   1871                                 bcm_ipfix_stage_t stage,
   1872                                 bcm_gport_t port,
   1873                                 bcm_ipfix_mirror_config_t *config)
   1874 {
   1875 #ifdef BCM_IPFIX_SUPPORT
   1876     const _bcm_ipfix_id_def_t *id_def = NULL;
   1877     soc_reg_t reg;
   1878     uint64 rval64;
   1879 
   1880     if (!soc_feature(unit, soc_feature_ipfix_flow_mirror)) {
   1881         return BCM_E_UNAVAIL;
   1882     }
   1883 
   1884 #ifdef BCM_TRIUMPH_SUPPORT
   1885     if (SOC_IS_TR_VL(unit)) {
   1886         id_def = &_ipfix_tr_id_def;
   1887     }
   1888 #endif /* BCM_TRIUMPH_SUPPORT */
   1889     if (id_def == NULL) {
   1890         return BCM_E_INTERNAL;
   1891     }
   1892 
   1893     if (_bcm_ipfix_ctrl[unit] == NULL) {
   1894         return BCM_E_INIT;
   1895     }
   1896 
   1897     if (stage != BCM_IPFIX_STAGE_INGRESS && stage != BCM_IPFIX_STAGE_EGRESS) {
   1898         return BCM_E_PARAM;
   1899     }
   1900 
   1901     BCM_IF_ERROR_RETURN(_bcm_ipfix_gport_resolve(unit, port, &port));
   1902 
   1903     if (config == NULL) {
   1904         return BCM_E_PARAM;
   1905     }
   1906 
   1907     reg = id_def->mirror_control[stage];
   1908 
   1909     if (config->pkt_count >=
   1910         (1 << soc_reg_field_length(unit, reg, MIRROR_COUNTf))) {
   1911         return BCM_E_PARAM;
   1912     }
   1913 
   1914     if (config->tcp_flags_mask >=
   1915         (1 << soc_reg_field_length(unit, reg, TCP_FLAG_MASKf))) {
   1916         return BCM_E_PARAM;
   1917     }
   1918 
   1919     if (config->flags & BCM_IPFIX_MIRROR_CONFIG_TTL_OFFSET_MAX) {
   1920         if (config->ttl_offset_max >=
   1921             (1 << soc_reg_field_length(unit, reg, TTL_RANGE_VALf))) {
   1922             return BCM_E_PARAM;
   1923         }
   1924     }
   1925 
   1926     COMPILER_64_ZERO(rval64);
   1927     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64));
   1928     soc_reg64_field32_set(unit, reg, &rval64, MIRROR_COUNTf,
   1929                           config->pkt_count);
   1930     soc_reg64_field32_set(unit, reg, &rval64, TCP_FLAG_MASKf,
   1931                           config->tcp_flags_mask);
   1932     if (config->flags & BCM_IPFIX_MIRROR_CONFIG_TTL_OFFSET_MAX) {
   1933         soc_reg64_field32_set(unit, reg, &rval64, TTL_RANGE_CHECK_ENABLEf, 1);
   1934         soc_reg64_field32_set(unit, reg, &rval64, TTL_RANGE_VALf,
   1935                               config->ttl_offset_max);
   1936     }
   1937     if (config->flags & BCM_IPFIX_MIRROR_CONFIG_FRAGMENT) {
   1938         soc_reg64_field32_set(unit, reg, &rval64, FRAGMENT_MASKf, 1);
   1939     }
   1940     if (config->flags & BCM_IPFIX_MIRROR_CONFIG_NON_FRAGMENT) {
   1941         soc_reg64_field32_set(unit, reg, &rval64, NON_FRAGMENT_MASKf, 1);
   1942     }
   1943     SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64));
   1944 
   1945     return BCM_E_NONE;
   1946 #else /* BCM_IPFIX_SUPPORT */
   1947     return BCM_E_UNAVAIL;
   1948 #endif /* BCM_IPFIX_SUPPORT */
   1949 }
   1950 
   1951 /*
   1952  * Function:
   1953  *     bcm_esw_ipfix_mirror_config_get
   1954  * Description:
   1955  *     Get IPFIX mirror control configuration of the specified port
   1956  * Parameters:
   1957  *     unit            device number
   1958  *     stage           BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS
   1959  *     port            generic port identifier
   1960  *     config          pointer to ipfix mirror configuration
   1961  * Return:
   1962  *     BCM_E_NONE
   1963  *     BCM_E_PARAM
   1964  *     BCM_E_UNAVAIL
   1965  *     BCM_E_INIT
   1966  *     BCM_E_PORT
   1967  */
   1968 int
   1969 bcm_esw_ipfix_mirror_config_get(int unit,
   1970                                 bcm_ipfix_stage_t stage,
   1971                                 bcm_gport_t port,
   1972                                 bcm_ipfix_mirror_config_t *config)
   1973 {
   1974 #ifdef BCM_IPFIX_SUPPORT
   1975     const _bcm_ipfix_id_def_t *id_def = NULL;
   1976     soc_reg_t reg;
   1977     uint64 rval64;
   1978 
   1979     if (!soc_feature(unit, soc_feature_ipfix_flow_mirror)) {
   1980         return BCM_E_UNAVAIL;
   1981     }
   1982 
   1983 #ifdef BCM_TRIUMPH_SUPPORT
   1984     if (SOC_IS_TR_VL(unit)) {
   1985         id_def = &_ipfix_tr_id_def;
   1986     }
   1987 #endif /* BCM_TRIUMPH_SUPPORT */
   1988     if (id_def == NULL) {
   1989         return BCM_E_INTERNAL;
   1990     }
   1991 
   1992     if (_bcm_ipfix_ctrl[unit] == NULL) {
   1993         return BCM_E_INIT;
   1994     }
   1995 
   1996     if (stage != BCM_IPFIX_STAGE_INGRESS && stage != BCM_IPFIX_STAGE_EGRESS) {
   1997         return BCM_E_PARAM;
   1998     }
   1999 
   2000     BCM_IF_ERROR_RETURN(_bcm_ipfix_gport_resolve(unit, port, &port));
   2001 
   2002     if (config == NULL) {
   2003         return BCM_E_PARAM;
   2004     }
   2005 
   2006     reg = id_def->mirror_control[stage];
   2007 
   2008     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64));
   2009     config->flags = 0;
   2010     config->pkt_count = soc_reg64_field32_get(unit, reg, rval64,
   2011                                               MIRROR_COUNTf);
   2012     config->tcp_flags_mask = soc_reg64_field32_get(unit, reg, rval64,
   2013                                                    TCP_FLAG_MASKf);
   2014     if (soc_reg64_field32_get(unit, reg, rval64, TTL_RANGE_CHECK_ENABLEf)) {
   2015         config->flags |= BCM_IPFIX_MIRROR_CONFIG_TTL_OFFSET_MAX;
   2016         config->ttl_offset_max = soc_reg64_field32_get(unit, reg, rval64,
   2017                                                        TTL_RANGE_VALf);
   2018     }
   2019     if (soc_reg64_field32_get(unit, reg, rval64, FRAGMENT_MASKf)) {
   2020         config->flags |= BCM_IPFIX_MIRROR_CONFIG_FRAGMENT;
   2021     }
   2022     if (soc_reg64_field32_get(unit, reg, rval64, NON_FRAGMENT_MASKf)) {
   2023         config->flags |= BCM_IPFIX_MIRROR_CONFIG_NON_FRAGMENT;
   2024     }
   2025 
   2026     return BCM_E_NONE;
   2027 #else /* BCM_IPFIX_SUPPORT */
   2028     return BCM_E_UNAVAIL;
   2029 #endif /* BCM_IPFIX_SUPPORT */
   2030 }
   2031 
   2032 /*
   2033  * Function:
   2034  *     bcm_esw_ipfix_mirror_port_dest_add
   2035  * Description:
   2036  *     Add an IPFIX mirror destination to the specified port
   2037  * Parameters:
   2038  *     unit            device number
   2039  *     stage           BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS
   2040  *     port            generic port identifier
   2041  *     mirror_dest_id  pre-allocated mirror destination identifier
   2042  * Return:
   2043  *     BCM_E_NONE
   2044  *     BCM_E_PARAM
   2045  *     BCM_E_EXISTS
   2046  *     BCM_E_BADID
   2047  *     BCM_E_RESOURCE
   2048  *     BCM_E_UNAVAIL
   2049  *     BCM_E_INIT
   2050  *     BCM_E_PORT
   2051  */
   2052 int
   2053 bcm_esw_ipfix_mirror_port_dest_add(int unit,
   2054                                    bcm_ipfix_stage_t stage,
   2055                                    bcm_gport_t port,
   2056                                    bcm_gport_t mirror_dest_id)
   2057 {
   2058 #ifdef BCM_IPFIX_SUPPORT
   2059     const _bcm_ipfix_id_def_t *id_def = NULL;
   2060     soc_reg_t reg;
   2061     uint64 rval64;
   2062     uint32 mirror_bmp;
   2063     int mtp_index, free_index, index;
   2064 #ifdef BCM_TRIUMPH_SUPPORT
   2065     uint32 flags = BCM_MIRROR_PORT_INGRESS;
   2066     int rv;
   2067 #endif /* BCM_TRIUMPH_SUPPORT */
   2068 
   2069     if (!soc_feature(unit, soc_feature_ipfix_flow_mirror)) {
   2070         return BCM_E_UNAVAIL;
   2071     }
   2072 
   2073 #ifdef BCM_TRIUMPH_SUPPORT
   2074     if (SOC_IS_TR_VL(unit)) {
   2075         id_def = &_ipfix_tr_id_def;
   2076     }
   2077 #endif /* BCM_TRIUMPH_SUPPORT */
   2078     if (id_def == NULL) {
   2079         return BCM_E_INTERNAL;
   2080     }
   2081 
   2082     if (_bcm_ipfix_ctrl[unit] == NULL) {
   2083         return BCM_E_INIT;
   2084     }
   2085 
   2086     if (stage != BCM_IPFIX_STAGE_INGRESS && stage != BCM_IPFIX_STAGE_EGRESS) {
   2087         return BCM_E_PARAM;
   2088     }
   2089 
   2090     BCM_IF_ERROR_RETURN(_bcm_ipfix_gport_resolve(unit, port, &port));
   2091 
   2092     if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) {
   2093         return BCM_E_BADID;
   2094     }
   2095 
   2096     reg = id_def->mirror_control[stage];
   2097 
   2098     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64));
   2099 
   2100 #ifdef BCM_TRIUMPH_SUPPORT
   2101     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_APOLLO(unit)) {
   2102         if (stage == BCM_IPFIX_STAGE_EGRESS) {
   2103             flags = BCM_MIRROR_PORT_EGRESS_TRUE;
   2104         }
   2105         BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_reserve(unit, mirror_dest_id, flags, &mtp_index));
   2106     } else
   2107 #endif /* BCM_TRIUMPH_SUPPORT */
   2108     {
   2109         mtp_index = BCM_GPORT_MIRROR_GET(mirror_dest_id);
   2110     }
   2111 
   2112     mirror_bmp = soc_reg64_field32_get(unit, reg, rval64, MIRRORf);
   2113 
   2114     free_index = -1;
   2115     for (index = _BCM_IPFIX_RATE_MIRROR_COUNT - 1; index >= 0; index--) {
   2116         if (!(mirror_bmp & (1 << index))) {
   2117             free_index = index;
   2118             continue;
   2119         }
   2120         if (soc_reg64_field32_get(unit, reg, rval64,
   2121                                   id_def->mtp_index[index]) == mtp_index) {
   2122             return BCM_E_EXISTS;
   2123         }
   2124     }
   2125     if (free_index < 0) {
   2126 #ifdef BCM_TRIUMPH_SUPPORT
   2127     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_APOLLO(unit)) {
   2128         _bcm_esw_mirror_mtp_unreserve(unit, mtp_index, TRUE, flags);
   2129     }
   2130 #endif /* BCM_TRIUMPH_SUPPORT */
   2131 
   2132         return BCM_E_RESOURCE;
   2133     }
   2134 
   2135     soc_reg64_field32_set(unit, reg, &rval64, id_def->mtp_index[free_index],
   2136                           mtp_index);
   2137     soc_reg64_field32_set(unit, reg, &rval64, MIRRORf,
   2138                           mirror_bmp | (1 << free_index));
   2139     SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64));
   2140 
   2141 #ifdef BCM_TRIUMPH_SUPPORT
   2142     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_APOLLO(unit)) {
   2143         rv = soc_reg_set(unit, reg, port, 0, rval64);
   2144         if (BCM_FAILURE(rv)) {
   2145             _bcm_esw_mirror_mtp_unreserve(unit, mtp_index, TRUE, flags);
   2146             return rv;
   2147         }
   2148 
   2149         if (stage == BCM_IPFIX_STAGE_INGRESS) {
   2150             /*INGRESS rely on MIRROR_CONTROL, EGRSS_TRUE donot rely on this*/
   2151             BCM_IF_ERROR_RETURN(_bcm_esw_mirror_enable_set(unit, port, TRUE));
   2152         }
   2153     } else
   2154 #endif /* BCM_TRIUMPH_SUPPORT */
   2155     {
   2156         SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64));
   2157     }
   2158 
   2159     return BCM_E_NONE;
   2160 #else /* BCM_IPFIX_SUPPORT */
   2161     return BCM_E_UNAVAIL;
   2162 #endif /* BCM_IPFIX_SUPPORT */
   2163 }
   2164 
   2165 /*
   2166  * Function:
   2167  *     bcm_esw_ipfix_mirror_port_dest_delete
   2168  * Description:
   2169  *     Delete an IPFIX mirror destination from the specified port
   2170  * Parameters:
   2171  *     unit            device number
   2172  *     stage           BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS
   2173  *     port            generic port identifier
   2174  *     mirror_dest_id  pre-allocated mirror destination identifier
   2175  * Return:
   2176  *     BCM_E_NONE
   2177  *     BCM_E_PARAM
   2178  *     BCM_E_NOT_FOUND
   2179  *     BCM_E_BADID
   2180  *     BCM_E_UNAVAIL
   2181  *     BCM_E_INIT
   2182  *     BCM_E_PORT
   2183  */
   2184 int
   2185 bcm_esw_ipfix_mirror_port_dest_delete(int unit,
   2186                                       bcm_ipfix_stage_t stage,
   2187                                       bcm_gport_t port,
   2188                                       bcm_gport_t mirror_dest_id)
   2189 {
   2190 #ifdef BCM_IPFIX_SUPPORT
   2191     const _bcm_ipfix_id_def_t *id_def = NULL;
   2192     soc_reg_t reg;
   2193     uint64 rval64;
   2194     uint32 mirror_bmp;
   2195     int mtp_index, index;
   2196 #ifdef BCM_TRIUMPH_SUPPORT
   2197     uint32 flags = BCM_MIRROR_PORT_INGRESS;
   2198 #endif /* BCM_TRIUMPH_SUPPORT */
   2199 
   2200     if (!soc_feature(unit, soc_feature_ipfix_flow_mirror)) {
   2201         return BCM_E_UNAVAIL;
   2202     }
   2203 
   2204 #ifdef BCM_TRIUMPH_SUPPORT
   2205     if (SOC_IS_TR_VL(unit)) {
   2206         id_def = &_ipfix_tr_id_def;
   2207     }
   2208 #endif /* BCM_TRIUMPH_SUPPORT */
   2209     if (id_def == NULL) {
   2210         return BCM_E_INTERNAL;
   2211     }
   2212 
   2213     if (_bcm_ipfix_ctrl[unit] == NULL) {
   2214         return BCM_E_INIT;
   2215     }
   2216 
   2217     if (stage != BCM_IPFIX_STAGE_INGRESS && stage != BCM_IPFIX_STAGE_EGRESS) {
   2218         return BCM_E_PARAM;
   2219     }
   2220 
   2221     BCM_IF_ERROR_RETURN(_bcm_ipfix_gport_resolve(unit, port, &port));
   2222 
   2223     if (!BCM_GPORT_IS_MIRROR(mirror_dest_id)) {
   2224         return BCM_E_BADID;
   2225     }
   2226 
   2227 #ifdef BCM_TRIUMPH_SUPPORT
   2228     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_APOLLO(unit)) {
   2229         if (stage == BCM_IPFIX_STAGE_EGRESS) {
   2230             flags = BCM_MIRROR_PORT_EGRESS_TRUE;
   2231         }
   2232         BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_match(unit, mirror_dest_id, flags, &mtp_index));
   2233     } else
   2234 #endif /* BCM_TRIUMPH_SUPPORT */
   2235     {
   2236         mtp_index = BCM_GPORT_MIRROR_GET(mirror_dest_id);
   2237     }
   2238 
   2239     reg = id_def->mirror_control[stage];
   2240 
   2241     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64));
   2242     mirror_bmp = soc_reg64_field32_get(unit, reg, rval64, MIRRORf);
   2243 
   2244     for (index = 0; index < _BCM_IPFIX_RATE_MIRROR_COUNT; index++) {
   2245         if (!(mirror_bmp & (1 << index))) {
   2246             continue;
   2247         }
   2248         if (soc_reg64_field32_get(unit, reg, rval64,
   2249                                   id_def->mtp_index[index]) == mtp_index) {
   2250             soc_reg64_field32_set(unit, reg, &rval64, id_def->mtp_index[index], 0);
   2251             break;
   2252         }
   2253     }
   2254     if (index == _BCM_IPFIX_RATE_MIRROR_COUNT) {
   2255         return BCM_E_NOT_FOUND;
   2256     }
   2257 
   2258     soc_reg64_field32_set(unit, reg, &rval64, MIRRORf,
   2259                           mirror_bmp ^ (1 << index));
   2260     SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64));
   2261 
   2262 #ifdef BCM_TRIUMPH_SUPPORT
   2263     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_APOLLO(unit)) {
   2264         BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_unreserve(unit, mtp_index, TRUE, flags));
   2265     }
   2266 #endif /* BCM_TRIUMPH_SUPPORT */
   2267 
   2268     return BCM_E_NONE;
   2269 #else /* BCM_IPFIX_SUPPORT */
   2270     return BCM_E_UNAVAIL;
   2271 #endif /* BCM_IPFIX_SUPPORT */
   2272 }
   2273 
   2274 /*
   2275  * Function:
   2276  *     bcm_esw_ipfix_mirror_port_dest_delete_all
   2277  * Description:
   2278  *     Delete all IPFIX mirror destination from the specified port
   2279  * Parameters:
   2280  *     unit            device number
   2281  *     stage           BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS
   2282  *     port            generic port identifier
   2283  * Return:
   2284  *     BCM_E_NONE
   2285  *     BCM_E_PARAM
   2286  *     BCM_E_UNAVAIL
   2287  *     BCM_E_INIT
   2288  *     BCM_E_PORT
   2289  */
   2290 int
   2291 bcm_esw_ipfix_mirror_port_dest_delete_all(int unit,
   2292                                           bcm_ipfix_stage_t stage,
   2293                                           bcm_gport_t port)
   2294 {
   2295 #ifdef BCM_IPFIX_SUPPORT
   2296     const _bcm_ipfix_id_def_t *id_def = NULL;
   2297     soc_reg_t reg;
   2298     uint64 rval64;
   2299 #ifdef BCM_TRIUMPH_SUPPORT
   2300     uint32 mirror_bmp;
   2301     int mtp_index, index;
   2302 #endif /* BCM_TRIUMPH_SUPPORT */
   2303 
   2304     if (!soc_feature(unit, soc_feature_ipfix_flow_mirror)) {
   2305         return BCM_E_UNAVAIL;
   2306     }
   2307 
   2308 #ifdef BCM_TRIUMPH_SUPPORT
   2309     if (SOC_IS_TR_VL(unit)) {
   2310         id_def = &_ipfix_tr_id_def;
   2311     }
   2312 #endif /* BCM_TRIUMPH_SUPPORT */
   2313     if (id_def == NULL) {
   2314         return BCM_E_INTERNAL;
   2315     }
   2316 
   2317     if (_bcm_ipfix_ctrl[unit] == NULL) {
   2318         return BCM_E_INIT;
   2319     }
   2320 
   2321     if (stage != BCM_IPFIX_STAGE_INGRESS && stage != BCM_IPFIX_STAGE_EGRESS) {
   2322         return BCM_E_PARAM;
   2323     }
   2324 
   2325     BCM_IF_ERROR_RETURN(_bcm_ipfix_gport_resolve(unit, port, &port));
   2326 
   2327     reg = id_def->mirror_control[stage];
   2328 
   2329     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64));
   2330 
   2331 #ifdef BCM_TRIUMPH_SUPPORT
   2332     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_APOLLO(unit)) {
   2333         mirror_bmp = soc_reg64_field32_get(unit, reg, rval64, MIRRORf);
   2334         for (index = 0; index < _BCM_IPFIX_RATE_MIRROR_COUNT; index++) {
   2335             if (!(mirror_bmp & (1 << index))) {
   2336                 continue;
   2337             }
   2338 
   2339             mtp_index = soc_reg64_field32_get(unit, reg, rval64,
   2340                                         id_def->mtp_index[index]);
   2341 
   2342             if (stage == BCM_IPFIX_STAGE_INGRESS) {
   2343                 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_unreserve(unit, mtp_index,
   2344                                            TRUE, BCM_MIRROR_PORT_INGRESS));
   2345             } else {
   2346                 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_mtp_unreserve(unit, mtp_index,
   2347                                            TRUE, BCM_MIRROR_PORT_EGRESS_TRUE));
   2348             }
   2349 
   2350             soc_reg64_field32_set(unit, reg, &rval64, id_def->mtp_index[index], 0);
   2351         }
   2352     }
   2353 #endif /* BCM_TRIUMPH_SUPPORT */
   2354 
   2355     soc_reg64_field32_set(unit, reg, &rval64, MIRRORf, 0);
   2356     SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64));
   2357 
   2358     return BCM_E_NONE;
   2359 #else /* BCM_IPFIX_SUPPORT */
   2360     return BCM_E_UNAVAIL;
   2361 #endif /* BCM_IPFIX_SUPPORT */
   2362 }
   2363 
   2364 /*
   2365  * Function:
   2366  *     bcm_esw_ipfix_mirror_port_dest_get
   2367  * Description:
   2368  *     Get all IPFIX mirror destination of the specified port
   2369  * Parameters:
   2370  *     unit              device number
   2371  *     stage             BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS
   2372  *     port              generic port identifier
   2373  *     mirror_dest_size  size of mirror_dest_id array
   2374  *     mirror_dest_id    array to store mirror destination identifier
   2375  *     mirror_dest_count number of entries stored in the mirror_dest_id array
   2376  * Return:
   2377  *     BCM_E_NONE
   2378  *     BCM_E_PARAM
   2379  *     BCM_E_UNAVAIL
   2380  *     BCM_E_INIT
   2381  *     BCM_E_PORT
   2382  */
   2383 int
   2384 bcm_esw_ipfix_mirror_port_dest_get(int unit,
   2385                                    bcm_ipfix_stage_t stage,
   2386                                    bcm_gport_t port,
   2387                                    int mirror_dest_size,
   2388                                    bcm_gport_t *mirror_dest_id,
   2389                                    int *mirror_dest_count)
   2390 {
   2391 #ifdef BCM_IPFIX_SUPPORT
   2392     const _bcm_ipfix_id_def_t *id_def = NULL;
   2393     soc_reg_t reg;
   2394     uint64 rval64;
   2395     uint32 mirror_bmp;
   2396     int mtp_index, index;
   2397 
   2398     if (!soc_feature(unit, soc_feature_ipfix_flow_mirror)) {
   2399         return BCM_E_UNAVAIL;
   2400     }
   2401 
   2402 #ifdef BCM_TRIUMPH_SUPPORT
   2403     if (SOC_IS_TR_VL(unit)) {
   2404         id_def = &_ipfix_tr_id_def;
   2405     }
   2406 #endif /* BCM_TRIUMPH_SUPPORT */
   2407     if (id_def == NULL) {
   2408         return BCM_E_INTERNAL;
   2409     }
   2410 
   2411     if (_bcm_ipfix_ctrl[unit] == NULL) {
   2412         return BCM_E_INIT;
   2413     }
   2414 
   2415     if (stage != BCM_IPFIX_STAGE_INGRESS && stage != BCM_IPFIX_STAGE_EGRESS) {
   2416         return BCM_E_PARAM;
   2417     }
   2418 
   2419     BCM_IF_ERROR_RETURN(_bcm_ipfix_gport_resolve(unit, port, &port));
   2420 
   2421     if (mirror_dest_id == NULL || mirror_dest_count == NULL) {
   2422         return BCM_E_PARAM;
   2423     }
   2424 
   2425     reg = id_def->mirror_control[stage];
   2426 
   2427     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64));
   2428     mirror_bmp = soc_reg64_field32_get(unit, reg, rval64, MIRRORf);
   2429 
   2430     for (index = 0; index < _BCM_IPFIX_RATE_MIRROR_COUNT; index++) {
   2431         if (!(mirror_bmp & (1 << index))) {
   2432             continue;
   2433         }
   2434         if (*mirror_dest_count >= mirror_dest_size) {
   2435             break;
   2436         }
   2437         mtp_index = soc_reg64_field32_get(unit, reg, rval64,
   2438                                           id_def->mtp_index[index]);
   2439         BCM_GPORT_MIRROR_SET(mirror_dest_id[*mirror_dest_count], mtp_index);
   2440         (*mirror_dest_count)++;
   2441     }
   2442 
   2443     return BCM_E_NONE;
   2444 #else /* BCM_IPFIX_SUPPORT */
   2445     return BCM_E_UNAVAIL;
   2446 #endif /* BCM_IPFIX_SUPPORT */
   2447 }
   2448 
   2449 /*
   2450  * Function:
   2451  *     bcm_ipfix_dump_export_entry
   2452  * Description:
   2453  *     To print export entry
   2454  * Parameters:
   2455  *     unit            Device number
   2456  *     data            Pointer to converted data in API format
   2457  * Return:
   2458  *     None
   2459  */
   2460 void
   2461 bcm_ipfix_dump_export_entry(int unit, bcm_ipfix_data_t *data)
   2462 {
   2463 #ifdef BCM_IPFIX_SUPPORT
   2464     char *stage_str, *type_str, *reason_str;
   2465 
   2466     if (data->stage == BCM_IPFIX_STAGE_INGRESS) {
   2467         stage_str = "ingress";
   2468     } else if (data->stage == BCM_IPFIX_STAGE_EGRESS) {
   2469         stage_str = "egress";
   2470     } else {
   2471         stage_str = "unknown stage";
   2472     }
   2473 
   2474     if (data->flags & BCM_IPFIX_DATA_TYPE_L2) {
   2475         type_str = "(L2)";
   2476     } else if (data->flags & BCM_IPFIX_DATA_TYPE_IP4) {
   2477         type_str = "(IPv4)";
   2478     } else if (data->flags & BCM_IPFIX_DATA_TYPE_IP6) {
   2479         type_str = "(IPv6)";
   2480     } else {
   2481         type_str = "(Unknown)";
   2482     }
   2483 
   2484     if (data->flags & BCM_IPFIX_DATA_REASON_FLOW_TIMEOUT) {
   2485         reason_str = "flow expired";
   2486     } else if (data->flags & BCM_IPFIX_DATA_REASON_FLOW_END) {
   2487         reason_str = "flow end";
   2488     } else if (data->flags & BCM_IPFIX_DATA_REASON_FLOW) {
   2489         reason_str = "early export";
   2490     } else if (data->flags & BCM_IPFIX_DATA_REASON_COUNT) {
   2491         reason_str = "counter overflow";
   2492     } else if (data->flags & BCM_IPFIX_DATA_REASON_TIMESTAMP) {
   2493         reason_str = "timestamp overflow";
   2494     } else {
   2495         reason_str = "unknown";
   2496     }
   2497 
   2498     LOG_CLI((BSL_META_U(unit,
   2499                         "\t%s %s port %d reason=%s\n"),
   2500              type_str, stage_str, data->port, reason_str));
   2501     LOG_CLI((BSL_META_U(unit,
   2502                         "\tstart_timestamp=%d last_timestamp=%d"
   2503              " byte_count=%d pkt_count=%d\n"),
   2504              data->start_timestamp, data->last_timestamp,
   2505              data->byte_count, data->pkt_count));
   2506     LOG_CLI((BSL_META_U(unit,
   2507                         "\tnon_fragment_pkt_detected=%d fragmented_pkt_detected=%d\n"),
   2508              data->flags & BCM_IPFIX_DATA_NON_FRAGMENT_PKT_DETECTED ? 1: 0,
   2509              data->flags & BCM_IPFIX_DATA_FRAGMENT_PKT_DETECTED ? 1: 0));
   2510     LOG_CLI((BSL_META_U(unit,
   2511                         "\tttl_changed_detected=%d ttl=%d tcp_flags=0x%x\n"),
   2512              data->flags & BCM_IPFIX_DATA_TTL_CHANGED_DETECTED ? 1: 0,
   2513              data->ttl, data->tcp_flags));
   2514     LOG_CLI((BSL_META_U(unit,
   2515                         "\tdrop_detected=%d dest_port=0x%x egress_vlan=%d "
   2516                         "dest_multicast=0x%x\n"),
   2517              data->flags & BCM_IPFIX_DATA_DROP_DETECTED ? 1: 0,
   2518              data->dest_port, data->egress_vlan, data->dest_multicast));
   2519 
   2520     if (data->flags & BCM_IPFIX_DATA_TYPE_L2) {
   2521         LOG_CLI((BSL_META_U(unit,
   2522                             "\tvlan_tagged=%d vlan=%d vlan_prio=0x%x "
   2523                             "ether_type=0x%x\n"),
   2524                  data->flags & BCM_IPFIX_DATA_VLAN_TAGGED ? 1 : 0,
   2525                  data->vlan, data->vlan_prio, data->ether_type));
   2526         LOG_CLI((BSL_META_U(unit,
   2527                             "\tsrc_mac_addr=%02x-%02x-%02x-%02x-%02x-%02x"
   2528                             " dst_mac_addr=%02x-%02x-%02x-%02x-%02x-%02x\n"),
   2529                  data->src_mac_addr[0], data->src_mac_addr[1],
   2530                  data->src_mac_addr[2], data->src_mac_addr[3],
   2531                  data->src_mac_addr[4], data->src_mac_addr[5],
   2532                  data->dst_mac_addr[0], data->dst_mac_addr[1],
   2533                  data->dst_mac_addr[2], data->dst_mac_addr[3],
   2534                  data->dst_mac_addr[4], data->dst_mac_addr[5]));
   2535     } else if (data->flags & BCM_IPFIX_DATA_TYPE_IP4) {
   2536         LOG_CLI((BSL_META_U(unit,
   2537                             "\tsrc_ip4_addr=%d.%d.%d.%d dst_ip4_addr=%d.%d.%d.%d\n"),
   2538                  (data->src_ip4_addr >> 24) & 0xff,
   2539                  (data->src_ip4_addr >> 16) & 0xff,
   2540                  (data->src_ip4_addr >> 8) & 0xff,
   2541                  data->src_ip4_addr & 0xff,
   2542                  (data->dst_ip4_addr >> 24) & 0xff,
   2543                  (data->dst_ip4_addr >> 16) & 0xff,
   2544                  (data->dst_ip4_addr >> 8) & 0xff,
   2545                  data->dst_ip4_addr & 0xff));
   2546         LOG_CLI((BSL_META_U(unit,
   2547                             "\tip_protocol=0x%x tos=0x%x\n"),
   2548                  data->ip_protocol, data->tos));
   2549         LOG_CLI((BSL_META_U(unit,
   2550                             "\tl4_src_port=%d l4_dst_port=%d source_port=0x%x "
   2551                             "vlan=%d\n"),
   2552                  data->l4_src_port, data->l4_dst_port, data->source_port,
   2553                  data->vlan));
   2554     } else if (data->flags & BCM_IPFIX_DATA_TYPE_IP6) {
   2555         LOG_CLI((BSL_META_U(unit,
   2556                             "\tsrc_ip6_addr=%02x%02x:%02x%02x:%02x%02x:%02x%02x:"
   2557                             "%02x%02x:%02x%02x:%02x%02x:%02x%02x\n"),
   2558                  data->src_ip6_addr[0], data->src_ip6_addr[1],
   2559                  data->src_ip6_addr[2], data->src_ip6_addr[3],
   2560                  data->src_ip6_addr[4], data->src_ip6_addr[5],
   2561                  data->src_ip6_addr[6], data->src_ip6_addr[7],
   2562                  data->src_ip6_addr[8], data->src_ip6_addr[9],
   2563                  data->src_ip6_addr[10], data->src_ip6_addr[11],
   2564                  data->src_ip6_addr[12], data->src_ip6_addr[13],
   2565                  data->src_ip6_addr[14], data->src_ip6_addr[15]));
   2566         LOG_CLI((BSL_META_U(unit,
   2567                             "\tdst_ip6_addr=%02x%02x:%02x%02x:%02x%02x:%02x%02x:"
   2568                             "%02x%02x:%02x%02x:%02x%02x:%02x%02x\n"),
   2569                  data->dst_ip6_addr[0], data->dst_ip6_addr[1],
   2570                  data->dst_ip6_addr[2], data->dst_ip6_addr[3],
   2571                  data->dst_ip6_addr[4], data->dst_ip6_addr[5],
   2572                  data->dst_ip6_addr[6], data->dst_ip6_addr[7],
   2573                  data->dst_ip6_addr[8], data->dst_ip6_addr[9],
   2574                  data->dst_ip6_addr[10], data->dst_ip6_addr[11],
   2575                  data->dst_ip6_addr[12], data->dst_ip6_addr[13],
   2576                  data->dst_ip6_addr[14], data->dst_ip6_addr[15]));
   2577         LOG_CLI((BSL_META_U(unit,
   2578                             "\tip_protocol=0x%x tos=0x%x ip6_flow_label=0x%x\n"),
   2579                  data->ip_protocol, data->tos, data->ip6_flow_label));
   2580         LOG_CLI((BSL_META_U(unit,
   2581                             "\tl4_src_port=%d l4_dst_port=%d source_port=0x%x "
   2582                             "vlan=%d\n"),
   2583                  data->l4_src_port, data->l4_dst_port, data->source_port,
   2584                  data->vlan));
   2585     }
   2586 #endif /* BCM_IPFIX_SUPPORT */
   2587 }
   2588 
   2589 #ifdef BCM_IPFIX_SUPPORT
   2590 /*
   2591  * Function:
   2592  *     _bcm_ipfix_get_field
   2593  * Description:
   2594  *     A generic routine to extract a fragment of bits from source bit stream
   2595  * Parameters:
   2596  *     str             Source bit stream, bit 0 is the LSB at LS word offset
   2597  *     minbit          Bit number of the first bit of the extracted data
   2598  *     maxbit          Bit number of the last bit of the extracted data
   2599  *     data_vp         Pointer to array for the extracted data
   2600  * Return:
   2601  *     None
   2602  */
   2603 STATIC void
   2604 _bcm_ipfix_get_field(uint32 *str,
   2605                      uint32 minbit,
   2606                      uint32 maxbit,
   2607                      void *data_vp)
   2608 {
   2609     int len, str_index, data_index, right_shift_count, left_shift_count;
   2610     uint32 *data = data_vp;
   2611 
   2612     len = maxbit - minbit + 1;
   2613     str_index = minbit >> 5;
   2614     data_index = 0;
   2615     right_shift_count = minbit & 0x1f;
   2616     left_shift_count = 32 - right_shift_count;
   2617 
   2618     if (right_shift_count) {
   2619         for (; len > 0; len -= 32) {
   2620             data[data_index] = str[str_index++] >> right_shift_count;
   2621             data[data_index++] |= str[str_index] << left_shift_count;
   2622         }
   2623     } else {
   2624         for (; len > 0; len -= 32) {
   2625             data[data_index++] = str[str_index++];
   2626         }
   2627     }
   2628     if (len & 0x1f) {
   2629         data[data_index - 1] &= (1 << (len & 0x1f)) - 1;
   2630     }
   2631 }
   2632 
   2633 /*
   2634  * Function:
   2635  *     _bcm_ipfix_set_field
   2636  * Description:
   2637  *     A generic routine to implant a fragment of bits into target bit stream
   2638  * Parameters:
   2639  *     str             Target bit stream, bit 0 is the LSB at LS word offset
   2640  *     minbit          Bit number of the first bit of the extracted data
   2641  *     maxbit          Bit number of the last bit of the extracted data
   2642  *     data_vp         Pointer to array for the source data
   2643  * Return:
   2644  *     None
   2645  */
   2646 STATIC void
   2647 _bcm_ipfix_set_field(uint32 *str,
   2648                      uint32 minbit,
   2649                      uint32 maxbit,
   2650                      void *data_vp)
   2651 {
   2652     int len, str_index, data_index, right_shift_count, left_shift_count;
   2653     uint32 *data = data_vp;
   2654     uint32 mask;
   2655 
   2656     len = maxbit - minbit + 1;
   2657     str_index = minbit >> 5;
   2658     data_index = 0;
   2659     left_shift_count = minbit & 0x1f;
   2660     right_shift_count = 32 - left_shift_count;
   2661 
   2662     if (left_shift_count) {
   2663         mask = 0xffffffff;
   2664         for (; len >= 32; len -= 32) {
   2665             str[str_index] &= ~(mask << left_shift_count);
   2666             str[str_index++] |= data[data_index] << left_shift_count;
   2667             str[str_index] &= ~(mask >> right_shift_count);
   2668             str[str_index] |= data[data_index++] >> right_shift_count;
   2669         }
   2670         if (len) {
   2671             mask = (1 << len) - 1;
   2672             str[str_index] &= ~(mask << left_shift_count);
   2673             str[str_index++] |= data[data_index] << left_shift_count;
   2674             str[str_index] &= ~(mask >> right_shift_count);
   2675             str[str_index] |= data[data_index] >> right_shift_count;
   2676         }
   2677     } else {
   2678         for (; len >= 32; len -= 32) {
   2679             str[str_index++] = data[data_index++];
   2680         }
   2681         if (len) {
   2682             mask = (1 << len) - 1;
   2683             str[str_index] &= ~mask;
   2684             str[str_index] |= data[data_index];
   2685         }
   2686     }
   2687 }
   2688 
   2689 /*
   2690  * Function:
   2691  *     _bcm_ipfix_process_export_entry
   2692  * Description:
   2693  *     To unpack export entry and convert into API format
   2694  * Parameters:
   2695  *     unit            Device number
   2696  *     stage           BCM_IPFIX_STAGE_INGRESS or BCM_IPFIX_STAGE_EGRESS
   2697  *     entry           Export entry from hardware
   2698  *     data            Pointer to converted data in API format
   2699  * Return:
   2700  *     BCM_E_NONE
   2701  *     BCM_E_INTERNAL
   2702  *     BCM_E_BUSY      Type is IPV6 upper, convert when IPV6 lower is seen
   2703  *     BCM_E_NOT_FOUND Export entry does not have valid bit set
   2704  */
   2705 STATIC int
   2706 _bcm_ipfix_process_export_entry(int unit,
   2707                                 bcm_ipfix_stage_t stage,
   2708                                 void *entry,
   2709                                 bcm_ipfix_data_t *data)
   2710 {
   2711     const _bcm_ipfix_id_def_t *id_def = NULL;
   2712     soc_mem_t mem;
   2713     uint32 type, flags;
   2714     bcm_module_t modid;
   2715     bcm_port_t port;
   2716 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3)
   2717     uint32 intf_type, intf, tunnel;
   2718     tunnel_entry_t tunnel_entry;
   2719 #endif /* BCM_TRIUMPH2_SUPPORT && INCLUDE_L3 */
   2720     static struct {
   2721         int type;
   2722         uint32 reason;
   2723         uint32 session[3]; /* 95 bits */
   2724         uint32 data[2];    /* 34 bits */
   2725         uint32 key[11];    /* 340 bits */
   2726     } fields[2];
   2727     uint32 fval[12];
   2728 
   2729 #ifdef BCM_TRIUMPH_SUPPORT
   2730     if (SOC_IS_TR_VL(unit)) {
   2731         id_def = &_ipfix_tr_id_def;
   2732     }
   2733 #endif /* BCM_TRIUMPH_SUPPORT */
   2734     if (id_def == NULL) {
   2735         return BCM_E_INTERNAL;
   2736     }
   2737 
   2738     mem = id_def->export_fifo[stage];
   2739 
   2740     if (!soc_mem_field32_get(unit, mem, entry, VALIDf)) {
   2741         fields[stage].type = -1;
   2742         return BCM_E_NOT_FOUND;
   2743     }
   2744 
   2745     type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf);
   2746     if (type != 3) {
   2747         fields[stage].reason = soc_mem_field32_get(unit, mem, entry,
   2748                                                    FIFO_REASON_CODEf);
   2749         soc_mem_field_get(unit, mem, entry, DATA_INFOf,
   2750                           fields[stage].data);
   2751         soc_mem_field_get(unit, mem, entry, SESSION_INFOf,
   2752                           fields[stage].session);
   2753     }
   2754     switch (type) {
   2755     case 0: /* L2 */
   2756         soc_mem_field_get(unit, mem, entry, L2_KEYf, fields[stage].key);
   2757         sal_memset(data, 0, sizeof(bcm_ipfix_data_t));
   2758         flags = BCM_IPFIX_DATA_TYPE_L2;
   2759         _bcm_ipfix_get_field(fields[stage].key, 6, 21, fval);
   2760         data->ether_type = fval[0];
   2761         _bcm_ipfix_get_field(fields[stage].key, 22, 22, fval);
   2762         if (fval[0]) {
   2763             flags |= BCM_IPFIX_DATA_VLAN_TAGGED;
   2764         }
   2765         _bcm_ipfix_get_field(fields[stage].key, 23, 25, fval);
   2766         data->vlan_prio = fval[0];
   2767         _bcm_ipfix_get_field(fields[stage].key, 26, 37, fval);
   2768         data->vlan = fval[0];
   2769         _bcm_ipfix_get_field(fields[stage].key, 38, 85, fval);
   2770         SAL_MAC_ADDR_FROM_UINT32(data->dst_mac_addr, fval);
   2771         _bcm_ipfix_get_field(fields[stage].key, 86, 133, fval);
   2772         SAL_MAC_ADDR_FROM_UINT32(data->src_mac_addr, fval);
   2773         break;
   2774     case 1: /* IPv4 */
   2775         soc_mem_field_get(unit, mem, entry, IPV4_KEYf, fields[stage].key);
   2776         sal_memset(data, 0, sizeof(bcm_ipfix_data_t));
   2777         flags = BCM_IPFIX_DATA_TYPE_IP4;
   2778         if (SOC_IS_TRIUMPH(unit)) {
   2779             _bcm_ipfix_get_field(fields[stage].key, 64, 95,
   2780                                  &data->dst_ip4_addr);
   2781             _bcm_ipfix_get_field(fields[stage].key, 96, 127,
   2782                                  &data->src_ip4_addr);
   2783         } else if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   2784                    SOC_IS_VALKYRIE2(unit)) {
   2785             _bcm_ipfix_get_field(fields[stage].key, 69, 100,
   2786                                  &data->dst_ip4_addr);
   2787             _bcm_ipfix_get_field(fields[stage].key, 101, 132,
   2788                                  &data->src_ip4_addr);
   2789         } else if (SOC_IS_TRIUMPH3(unit)) {
   2790             _bcm_ipfix_get_field(fields[stage].key, 72, 103,
   2791                                  &data->dst_ip4_addr);
   2792             _bcm_ipfix_get_field(fields[stage].key, 104, 135,
   2793                                  &data->src_ip4_addr);
   2794         }
   2795         break;
   2796     case 2: /* IPv6 Upper half */
   2797         if (SOC_IS_TRIUMPH(unit)) {
   2798             soc_mem_field_get(unit, mem, entry, IPV6_UPPER_KEYf,
   2799                               &fields[stage].key[7]);
   2800         } else if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   2801                    SOC_IS_VALKYRIE2(unit)) {
   2802             soc_mem_field_get(unit, mem, entry, IPV6_UPPER_KEYf, fval);
   2803             _bcm_ipfix_set_field(fields[stage].key, 229, 344, fval);
   2804         } else if (SOC_IS_TRIUMPH3(unit)) {
   2805             soc_mem_field_get(unit, mem, entry, IPV6_UPPER_KEYf, fval);
   2806             _bcm_ipfix_set_field(fields[stage].key, 232, 347, fval);
   2807         }
   2808         fields[stage].type = type;
   2809         return BCM_E_BUSY;
   2810     case 3: /* IPv6 Lower half, key only */
   2811         if (fields[stage].type != 2) {
   2812             return BCM_E_NOT_FOUND;
   2813         }
   2814         sal_memset(data, 0, sizeof(bcm_ipfix_data_t));
   2815         flags = BCM_IPFIX_DATA_TYPE_IP6;
   2816         if (SOC_IS_TRIUMPH(unit)) {
   2817             soc_mem_field_get(unit, mem, entry, IPV6_LOWER_KEYf,
   2818                               fields[stage].key);
   2819         } else if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   2820                    SOC_IS_VALKYRIE2(unit)) {
   2821             soc_mem_field_get(unit, mem, entry, IPV6_LOWER_KEYf, fval);
   2822             _bcm_ipfix_set_field(fields[stage].key, 0, 228, fval);
   2823         } else if (SOC_IS_TRIUMPH3(unit)) {
   2824             soc_mem_field_get(unit, mem, entry, IPV6_LOWER_KEYf, fval);
   2825             _bcm_ipfix_set_field(fields[stage].key, 0, 231, fval);
   2826         }
   2827         if (SOC_IS_TRIUMPH(unit)) {
   2828             _bcm_ipfix_get_field(fields[stage].key, 64, 83,
   2829                                  &data->ip6_flow_label);
   2830             _bcm_ipfix_get_field(fields[stage].key, 84, 211, fval);
   2831             SAL_IP6_ADDR_FROM_UINT32(data->dst_ip6_addr, fval);
   2832             _bcm_ipfix_get_field(fields[stage].key, 212, 339, fval);
   2833             SAL_IP6_ADDR_FROM_UINT32(data->src_ip6_addr, fval);
   2834         } else if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   2835                    SOC_IS_VALKYRIE2(unit)) {
   2836             _bcm_ipfix_get_field(fields[stage].key, 69, 88,
   2837                                  &data->ip6_flow_label);
   2838             _bcm_ipfix_get_field(fields[stage].key, 89, 216, fval);
   2839             SAL_IP6_ADDR_FROM_UINT32(data->dst_ip6_addr, fval);
   2840             _bcm_ipfix_get_field(fields[stage].key, 217, 344, fval);
   2841             SAL_IP6_ADDR_FROM_UINT32(data->src_ip6_addr, fval);
   2842          } else if (SOC_IS_TRIUMPH3(unit)) {
   2843             _bcm_ipfix_get_field(fields[stage].key, 72, 91,
   2844                                  &data->ip6_flow_label);
   2845             _bcm_ipfix_get_field(fields[stage].key, 92, 219, fval);
   2846             SAL_IP6_ADDR_FROM_UINT32(data->dst_ip6_addr, fval);
   2847             _bcm_ipfix_get_field(fields[stage].key, 220, 347, fval);
   2848             SAL_IP6_ADDR_FROM_UINT32(data->src_ip6_addr, fval);
   2849          }
   2850         break;
   2851     default:
   2852         return BCM_E_INTERNAL;
   2853     }
   2854     fields[stage].type = type;
   2855     _bcm_ipfix_get_field(fields[stage].key, 0, 5, fval);
   2856     data->port = fval[0];
   2857     if (fields[stage].type) { /* Common IP key fields */
   2858         _bcm_ipfix_get_field(fields[stage].key, 6, 13, fval);
   2859         data->ip_protocol = fval[0];
   2860         _bcm_ipfix_get_field(fields[stage].key, 14, 21, fval);
   2861         data->tos = fval[0];
   2862         _bcm_ipfix_get_field(fields[stage].key, 22, 37, fval);
   2863         data->l4_src_port = fval[0];
   2864         _bcm_ipfix_get_field(fields[stage].key, 38, 53, fval);
   2865         data->l4_dst_port = fval[0];
   2866 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3)
   2867         if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   2868             SOC_IS_VALKYRIE2(unit)) {
   2869             _bcm_ipfix_get_field(fields[stage].key, 54, 55, &intf_type);
   2870             _bcm_ipfix_get_field(fields[stage].key, 56, 68, &intf);
   2871             switch (intf_type) {
   2872             case 0: /* VLAN */
   2873                 data->vlan = intf;
   2874                 break;
   2875             case 1: /* L3_IIF */
   2876                 if (intf < 4096) { /* vlan id */
   2877                     data->vlan = intf;
   2878                 } else if (intf < 4096 + 512) { /* L3_TUNNEL index */
   2879                     if (SOC_MEM_FIELD_VALID(unit, L3_TUNNELm, TUNNEL_IDf)) {
   2880                         BCM_IF_ERROR_RETURN
   2881                             (soc_mem_read(unit, L3_TUNNELm, MEM_BLOCK_ANY,
   2882                                           intf - 4096, &tunnel_entry));
   2883                         tunnel = soc_mem_field32_get
   2884                             (unit, L3_TUNNELm, &tunnel_entry, TUNNEL_IDf);
   2885                         if (tunnel) {
   2886                             BCM_GPORT_TUNNEL_ID_SET(data->source_port, tunnel);
   2887                         }
   2888                     }
   2889                 } else { /* MPLS */
   2890                     /* vrf = intf - 4096 - 512 */
   2891                 }
   2892                 break;
   2893             case 2: /* SVP */
   2894                 if (_bcm_vp_used_get(unit, intf, _bcmVpTypeMpls)) {
   2895                     BCM_GPORT_MPLS_PORT_ID_SET(data->source_port, intf);
   2896                 } else if (_bcm_vp_used_get(unit, intf, _bcmVpTypeMim)) {
   2897                     BCM_GPORT_MIM_PORT_ID_SET(data->source_port, intf);
   2898                 } else if (_bcm_vp_used_get(unit, intf, _bcmVpTypeSubport)) {
   2899                     BCM_GPORT_SUBPORT_GROUP_SET(data->source_port, intf);
   2900                 } else if (_bcm_vp_used_get(unit, intf, _bcmVpTypeWlan)) {
   2901                     BCM_GPORT_WLAN_PORT_ID_SET(data->source_port, intf);
   2902                 }
   2903             }
   2904         }
   2905 #endif /* BCM_TRIUMPH2_SUPPORT && INCLUDE_L3 */
   2906     }
   2907 
   2908     data->stage = stage;
   2909 #ifdef BCM_TRIUMPH3_SUPPORT    
   2910     if (SOC_IS_TRIUMPH3(unit)) {
   2911         _bcm_ipfix_get_field(fields[stage].data, 35, 35, fval);
   2912         if (fval[0]) {
   2913             flags |= BCM_IPFIX_DATA_NON_FRAGMENT_PKT_DETECTED;
   2914         }
   2915         _bcm_ipfix_get_field(fields[stage].data, 34, 34, fval);
   2916         if (fval[0]) {
   2917             flags |= BCM_IPFIX_DATA_FRAGMENT_PKT_DETECTED;
   2918         }
   2919         _bcm_ipfix_get_field(fields[stage].data, 33, 33, fval);
   2920         if (fval[0]) {
   2921             flags |= BCM_IPFIX_DATA_TTL_CHANGED_DETECTED;
   2922         }
   2923         _bcm_ipfix_get_field(fields[stage].data, 18, 18, fval);
   2924         if (fval[0]) {
   2925             flags |= BCM_IPFIX_DATA_DROP_DETECTED;
   2926         }
   2927         _bcm_ipfix_get_field(fields[stage].data, 25, 32, &data->ttl);
   2928         _bcm_ipfix_get_field(fields[stage].data, 19, 24, &data->tcp_flags);
   2929     } else 
   2930 #endif /* BCM_TRIUMPH3_SUPPORT */    
   2931     {
   2932         _bcm_ipfix_get_field(fields[stage].data, 33, 33, fval);
   2933         if (fval[0]) {
   2934             flags |= BCM_IPFIX_DATA_NON_FRAGMENT_PKT_DETECTED;
   2935         }
   2936         _bcm_ipfix_get_field(fields[stage].data, 32, 32, fval);
   2937         if (fval[0]) {
   2938             flags |= BCM_IPFIX_DATA_FRAGMENT_PKT_DETECTED;
   2939         }
   2940         _bcm_ipfix_get_field(fields[stage].data, 31, 31, fval);
   2941         if (fval[0]) {
   2942             flags |= BCM_IPFIX_DATA_TTL_CHANGED_DETECTED;
   2943         }
   2944         _bcm_ipfix_get_field(fields[stage].data, 16, 16, fval);
   2945         if (fval[0]) {
   2946             flags |= BCM_IPFIX_DATA_DROP_DETECTED;
   2947         }
   2948         _bcm_ipfix_get_field(fields[stage].data, 23, 30, &data->ttl);
   2949         _bcm_ipfix_get_field(fields[stage].data, 17, 22, &data->tcp_flags);
   2950     }
   2951     _bcm_ipfix_get_field(fields[stage].data, 0, 2, fval);
   2952     switch (fval[0]) {
   2953     case 0: /* unicast - modid / port */
   2954 #ifdef BCM_TRIUMPH3_SUPPORT
   2955         if (SOC_IS_TRIUMPH3(unit)) {
   2956             /* DESTINATIONf: bits 3-9: PORTID, bits 10-17: MODULE */
   2957             _bcm_ipfix_get_field(fields[stage].data, 3, 9, &port);
   2958             _bcm_ipfix_get_field(fields[stage].data, 10, 17, &modid);
   2959         } else 
   2960 #endif /* BCM_TRIUMPH3_SUPPORT */
   2961         {
   2962             /* DESTINATIONf: bits 3-8: PORTID, bits 9-15: MODULE */
   2963             _bcm_ipfix_get_field(fields[stage].data, 3, 8, &port);
   2964             _bcm_ipfix_get_field(fields[stage].data, 9, 15, &modid);
   2965         }
   2966         BCM_GPORT_MODPORT_SET(data->dest_port, modid, port);
   2967         break;
   2968     case 1: /* unicast - trunk */
   2969         SOC_GPORT_TRUNK_SET(data->dest_port, fval[0]);
   2970         break;
   2971     case 2: /* L2 multicast ID */
   2972         _bcm_ipfix_get_field(fields[stage].data, 3, 15, fval);
   2973         _BCM_MULTICAST_GROUP_SET
   2974             (data->dest_multicast, _BCM_MULTICAST_TYPE_L2, fval[0]);
   2975         break;
   2976     case 3: /* L3 multicast ID */
   2977 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3)
   2978 #ifdef BCM_TRIUMPH3_SUPPORT
   2979         if (SOC_IS_TRIUMPH3(unit)) {
   2980             _bcm_ipfix_get_field(fields[stage].data, 3, 17, fval);
   2981         } else
   2982 #endif /* BCM_TRIUMPH3_SUPPORT */
   2983         {
   2984             _bcm_ipfix_get_field(fields[stage].data, 3, 15, fval);
   2985         }
   2986         if (_bcm_tr_multicast_ipmc_group_type_get
   2987             (unit, fval[0], &data->dest_multicast) == BCM_E_NOT_FOUND) {
   2988             _BCM_MULTICAST_GROUP_SET
   2989                 (data->dest_multicast, _BCM_MULTICAST_TYPE_L3, fval[0]);
   2990         }
   2991 #endif /* BCM_TRX_SUPPORT && INCLUDE_L3 */
   2992         break;
   2993     case 4: /* L2 broadcast (VLAN ID) */
   2994     case 5: /* L2 DLF at time of first packet (VLAN ID) */
   2995         _bcm_ipfix_get_field(fields[stage].data, 3, 15, fval);
   2996         data->egress_vlan = fval[0];
   2997         break;
   2998     default:
   2999         break;
   3000     }
   3001 
   3002     _bcm_ipfix_get_field(fields[stage].session, 0, 15, &data->start_timestamp);
   3003     _bcm_ipfix_get_field(fields[stage].session, 16, 31, &data->last_timestamp);
   3004     _bcm_ipfix_get_field(fields[stage].session, 32, 63, &data->byte_count);
   3005     _bcm_ipfix_get_field(fields[stage].session, 64, 89, &data->pkt_count);
   3006     if (soc_feature(unit, soc_feature_ipfix_rate)) {
   3007         _bcm_ipfix_get_field(fields[stage].session, 90, 90, fval);
   3008         if (fval[0]) {
   3009             flags |= BCM_IPFIX_DATA_RATE_VIOLATION;
   3010         }
   3011     }
   3012 
   3013     switch(fields[stage].reason) {
   3014     case 1:
   3015         flags |= BCM_IPFIX_DATA_REASON_FLOW_END;
   3016         break;
   3017     case 2:
   3018         flags |= BCM_IPFIX_DATA_REASON_FLOW_TIMEOUT;
   3019         break;
   3020     case 3:
   3021         flags |= BCM_IPFIX_DATA_REASON_FLOW;
   3022         break;
   3023     case 4:
   3024         flags |= BCM_IPFIX_DATA_REASON_COUNT;
   3025         break;
   3026     case 5:
   3027         flags |= BCM_IPFIX_DATA_REASON_TIMESTAMP;
   3028         break;
   3029     default:
   3030         break;
   3031     }
   3032 
   3033     data->flags = flags;
   3034 
   3035     return BCM_E_NONE;
   3036 }
   3037 
   3038 /*
   3039  * Function:
   3040  *     _bcm_ipfix_fifo_dma_thread
   3041  * Description:
   3042  *     A task thread to process IPFIX export FIFOs via FIFO DMA
   3043  * Parameters:
   3044  *     unit_vp          Device number
   3045  * Return:
   3046  *     None
   3047  */
   3048 STATIC void
   3049 _bcm_ipfix_fifo_dma_thread(void *unit_vp)
   3050 {
   3051     int unit = PTR_TO_INT(unit_vp);
   3052     _bcm_ipfix_ctrl_t *ipfix_ctrl = _bcm_ipfix_ctrl[unit];
   3053     _bcm_ipfix_callback_entry_t *cb_entry;
   3054     const _bcm_ipfix_id_def_t *id_def = NULL;
   3055     bcm_ipfix_data_t data;
   3056     int rv, entries_per_buf, adv_threshold, interval, count, i, j, non_empty;
   3057     int stage, chan, entry_words[2];
   3058     void *host_buf[2], *export_entry[2];
   3059 #ifdef BCM_CMICM_SUPPORT
   3060     uint32 rval = 0;
   3061     uint8 overflow_ch2 = 0, overflow_ch3 = 0;
   3062     uint8 timeout_ch2 = 0, timeout_ch3 = 0;
   3063     int cmc = SOC_PCI_CMC(unit);
   3064 #endif /* BCM_CMICM_SUPPORT */
   3065 
   3066 #ifdef BCM_TRIUMPH_SUPPORT
   3067     if (SOC_IS_TR_VL(unit)) {
   3068         id_def = &_ipfix_tr_id_def;
   3069     }
   3070 #endif /* BCM_TRIUMPH_SUPPORT */
   3071     if (id_def == NULL) {
   3072         ipfix_ctrl->pid = SAL_THREAD_ERROR;
   3073         soc_event_generate(unit, SOC_SWITCH_EVENT_THREAD_ERROR, 
   3074                            SOC_SWITCH_EVENT_THREAD_IPFIX, __LINE__, 
   3075                            BCM_E_INTERNAL);
   3076         sal_thread_exit(0);
   3077         return;
   3078     }
   3079 
   3080     entries_per_buf = soc_property_get(unit, spn_IPFIX_HOSTBUF_SIZE, 1024);
   3081     adv_threshold = entries_per_buf / 2;
   3082 
   3083     entry_words[0] = soc_mem_entry_words(unit, id_def->export_fifo[0]);
   3084     host_buf[0] =
   3085         soc_cm_salloc(unit, entries_per_buf * entry_words[0] * sizeof(uint32),
   3086                       "Ingress IPFIX DMA Buffer");
   3087     if (host_buf[0] == NULL) {
   3088         soc_event_generate(unit, SOC_SWITCH_EVENT_THREAD_ERROR, 
   3089                            SOC_SWITCH_EVENT_THREAD_IPFIX, __LINE__, 
   3090                            BCM_E_MEMORY);
   3091         goto cleanup_exit;
   3092     }
   3093 
   3094     entry_words[1] = soc_mem_entry_words(unit, id_def->export_fifo[1]);
   3095     host_buf[1] =
   3096         soc_cm_salloc(unit, entries_per_buf * entry_words[1] * sizeof(uint32),
   3097                       "Egress IPFIX DMA Buffer");
   3098     if (host_buf[1] == NULL) {
   3099         soc_event_generate(unit, SOC_SWITCH_EVENT_THREAD_ERROR, 
   3100                            SOC_SWITCH_EVENT_THREAD_IPFIX, __LINE__, 
   3101                            BCM_E_MEMORY);
   3102         goto cleanup_exit;
   3103     }
   3104 
   3105     for (stage = 0; stage < 2; stage++) {
   3106         rv = soc_mem_fifo_dma_start(unit, ipfix_ctrl->dma_chan[stage],
   3107                                    id_def->export_fifo[stage],
   3108                                    MEM_BLOCK_ANY, entries_per_buf,
   3109                                    host_buf[stage]); 
   3110         if (BCM_FAILURE(rv)) {
   3111             soc_event_generate(unit, SOC_SWITCH_EVENT_THREAD_ERROR, 
   3112                                SOC_SWITCH_EVENT_THREAD_IPFIX, __LINE__, rv);
   3113             goto cleanup_exit;
   3114         }
   3115 #ifdef BCM_CMICM_SUPPORT
   3116         export_entry[stage] = host_buf[stage]; 
   3117 #endif
   3118     }
   3119 
   3120     while ((interval = ipfix_ctrl->interval)) {
   3121         if (SOC_CONTROL(unit)->ipfixIntrEnb) {
   3122 #ifdef BCM_TRIUMPH3_SUPPORT
   3123             if (SOC_IS_TRIUMPH3(unit)) {
   3124                 (void)soc_cmicm_intr0_enable
   3125                             (unit, 
   3126                              IRQ_CMCx_FIFO_CH_DMA(SOC_MEM_FIFO_DMA_CHANNEL_2) | 
   3127                              IRQ_CMCx_FIFO_CH_DMA(SOC_MEM_FIFO_DMA_CHANNEL_3));
   3128             } else
   3129 #endif /* BCM_TRIUMPH3_SUPPORT */
   3130             {
   3131                 (void)soc_intr_enable(unit, (IRQ_FIFO_CH0_DMA | IRQ_FIFO_CH3_DMA));
   3132             }
   3133 
   3134 #ifdef BCM_CMICM_SUPPORT
   3135             if (soc_feature(unit, soc_feature_cmicm)) {
   3136                  /* check for timeout & overflow */
   3137                 rval = soc_pci_read(unit, 
   3138                           CMIC_CMCx_FIFO_CHy_RD_DMA_STAT_OFFSET(cmc, 
   3139                                           SOC_MEM_FIFO_DMA_CHANNEL_2));          
   3140                 overflow_ch2 = soc_reg_field_get(unit, 
   3141                                  CMIC_CMC0_FIFO_CH2_RD_DMA_STATr, rval,
   3142                                  HOSTMEM_OVERFLOWf);
   3143                 timeout_ch2 = soc_reg_field_get(unit, 
   3144                                 CMIC_CMC0_FIFO_CH2_RD_DMA_STATr, rval,
   3145                                 HOSTMEM_TIMEOUTf); 
   3146                 overflow_ch2 |= timeout_ch2;
   3147 
   3148                 rval = soc_pci_read(unit, 
   3149                           CMIC_CMCx_FIFO_CHy_RD_DMA_STAT_OFFSET(cmc, 
   3150                                           SOC_MEM_FIFO_DMA_CHANNEL_3));          
   3151                 overflow_ch3 = soc_reg_field_get(unit, 
   3152                                  CMIC_CMC0_FIFO_CH3_RD_DMA_STATr, rval,
   3153                                  HOSTMEM_OVERFLOWf);
   3154                 timeout_ch3 = soc_reg_field_get(unit, 
   3155                                 CMIC_CMC0_FIFO_CH3_RD_DMA_STATr, rval,
   3156                                 HOSTMEM_TIMEOUTf); 
   3157                 overflow_ch3 |= timeout_ch3;
   3158             }
   3159 #endif /* BCM_CMICM_SUPPORT */
   3160         }
   3161 
   3162         if (sal_sem_take(SOC_CONTROL(unit)->ipfixIntr, interval) < 0) {
   3163             LOG_VERBOSE(BSL_LS_BCM_DMA,
   3164                         (BSL_META_U(unit,
   3165                                     "IPFIX polling timeout\n")));
   3166         } else {
   3167             LOG_VERBOSE(BSL_LS_BCM_DMA,
   3168                         (BSL_META_U(unit,
   3169                                     "IPFIX woken up\n")));
   3170         }
   3171 
   3172         for (i = 0; i < _BCM_IPFIX_CB_MAX; i++) {
   3173             cb_entry = &ipfix_ctrl->callback_entry[i];
   3174             switch (cb_entry->state) {
   3175             case _BCM_IPFIX_CALLBACK_STATE_REGISTERED:
   3176                 cb_entry->state = _BCM_IPFIX_CALLBACK_STATE_ACTIVE;
   3177                 break;
   3178             case _BCM_IPFIX_CALLBACK_STATE_UNREGISTERED:
   3179                 cb_entry->state = _BCM_IPFIX_CALLBACK_STATE_INVALID;
   3180                 break;
   3181             default:
   3182                 break;
   3183             }
   3184         }
   3185 
   3186         do {
   3187             non_empty = FALSE;
   3188             for (stage = 0; stage < 2; stage++) {
   3189                 chan = ipfix_ctrl->dma_chan[stage];
   3190 #ifdef BCM_CMICM_SUPPORT
   3191                 if (soc_feature(unit, soc_feature_cmicm)) {
   3192                     rv = soc_mem_fifo_dma_get_num_entries(unit, chan, &count);
   3193                 } else
   3194 #endif
   3195                 { 
   3196                     rv = soc_mem_fifo_dma_get_read_ptr(unit, chan, &export_entry[0],
   3197                                                        &count);
   3198                 }
   3199                 if (SOC_SUCCESS(rv)) {
   3200                     non_empty = TRUE;
   3201                     if (count > adv_threshold) {
   3202                         count = adv_threshold;
   3203                     }
   3204                     for (i = 0; i < count; i++) {
   3205 #ifdef BCM_CMICM_SUPPORT
   3206                         rv = _bcm_ipfix_process_export_entry(unit, stage,
   3207                                                              export_entry[stage],
   3208                                                              &data);
   3209                         export_entry[stage] =
   3210                             (uint32 *)export_entry[stage] + entry_words[stage];
   3211                         /*From the begining of host buffer*/	 
   3212                         if (((uint32 *)export_entry[stage] - (uint32 *)host_buf[stage])/entry_words[stage] 
   3213 	                        == entries_per_buf) {
   3214 	                        export_entry[stage] = host_buf[stage];
   3215 	                    }
   3216 #else
   3217                         rv = _bcm_ipfix_process_export_entry(unit, stage,
   3218                                                              export_entry[0],
   3219                                                              &data);
   3220                         export_entry[0] =
   3221                             (uint32 *)export_entry[0] + entry_words[stage];
   3222 #endif        
   3223                         if (rv < 0) {
   3224                             continue;
   3225                         }
   3226 						
   3227 						
   3228                         if (bsl_check(bslLayerBcm, bslSourceDma, bslSeverityVerbose, unit)) {
   3229                             bcm_ipfix_dump_export_entry(unit, &data);
   3230                         }
   3231                         for (j = 0; j < _BCM_IPFIX_CB_MAX; j++) {
   3232                             cb_entry = &ipfix_ctrl->callback_entry[j];
   3233                             if (cb_entry->state ==
   3234                                 _BCM_IPFIX_CALLBACK_STATE_ACTIVE) {
   3235                                 cb_entry->callback(unit, &data,
   3236                                                    cb_entry->userdata);
   3237                             }
   3238                         }
   3239                     }
   3240 #ifdef BCM_CMICM_SUPPORT
   3241                     if (soc_feature(unit, soc_feature_cmicm)) {
   3242                         (void)_soc_mem_sbus_fifo_dma_set_entries_read(unit, chan, count);
   3243                     } else
   3244 #endif
   3245                     { 
   3246                         (void)soc_mem_fifo_dma_advance_read_ptr(unit, chan, count);
   3247                     }
   3248                 }
   3249             }
   3250         } while (non_empty);
   3251         /* clearing of the FIFO_CH_DMA_INT interrupt by resetring 
   3252            overflow & timeout status in FIFO_CHx_RD_DMA_STAT_CLR reg */
   3253 #ifdef BCM_CMICM_SUPPORT
   3254             if (soc_feature(unit, soc_feature_cmicm)) {
   3255                 if (overflow_ch2) {
   3256                     rval = 0;
   3257                     soc_reg_field_set(unit, 
   3258                                  CMIC_CMC0_FIFO_CH2_RD_DMA_STAT_CLRr, &rval,
   3259                                  HOSTMEM_OVERFLOWf, 1);
   3260                     soc_reg_field_set(unit, 
   3261                                  CMIC_CMC0_FIFO_CH2_RD_DMA_STAT_CLRr, &rval,
   3262                                  HOSTMEM_TIMEOUTf, 1);
   3263                     soc_pci_write(unit, 
   3264                               CMIC_CMCx_FIFO_CHy_RD_DMA_STAT_CLR_OFFSET(cmc, 
   3265                               SOC_MEM_FIFO_DMA_CHANNEL_2), rval);
   3266                 }
   3267                 if (overflow_ch3) {
   3268                     rval = 0;
   3269                     soc_reg_field_set(unit, 
   3270                                  CMIC_CMC0_FIFO_CH3_RD_DMA_STAT_CLRr, &rval,
   3271                                  HOSTMEM_OVERFLOWf, 1);
   3272                     soc_reg_field_set(unit, 
   3273                                  CMIC_CMC0_FIFO_CH3_RD_DMA_STAT_CLRr, &rval,
   3274                                  HOSTMEM_TIMEOUTf, 1);
   3275                     soc_pci_write(unit, 
   3276                               CMIC_CMCx_FIFO_CHy_RD_DMA_STAT_CLR_OFFSET(cmc, 
   3277                               SOC_MEM_FIFO_DMA_CHANNEL_3), rval);
   3278                 }
   3279             }
   3280 #endif /* BCM_CMICM_SUPPORT */
   3281     }
   3282 
   3283 cleanup_exit:
   3284     (void)soc_mem_fifo_dma_stop(unit, ipfix_ctrl->dma_chan[0]);
   3285     (void)soc_mem_fifo_dma_stop(unit, ipfix_ctrl->dma_chan[1]);
   3286 
   3287     if (host_buf[0] != NULL) {
   3288         soc_cm_sfree(unit, host_buf[0]);
   3289     }
   3290     if (host_buf[1] != NULL) {
   3291         soc_cm_sfree(unit, host_buf[1]);
   3292     }
   3293     ipfix_ctrl->pid = SAL_THREAD_ERROR;
   3294     sal_thread_exit(0);
   3295 }
   3296 #endif /* BCM_IPFIX_SUPPORT */
   3297 
   3298 #ifdef BCM_WARM_BOOT_SUPPORT
   3299 /*
   3300  * Function:
   3301  *      _bcm_esw_ipfix_sync
   3302  * Purpose:
   3303  *      Record ipfix module persisitent info for Level 2 Warm Boot
   3304  * Parameters: 
   3305  *      unit - StrataSwitch unit number.
   3306  * Returns:
   3307  *      BCM_E_XXX
   3308  */ 
   3309 int     
   3310 _bcm_esw_ipfix_sync(int unit) 
   3311 {
   3312 #ifdef BCM_IPFIX_SUPPORT
   3313     _bcm_ipfix_ctrl_t *ipfix_ctrl = _bcm_ipfix_ctrl[unit];
   3314     soc_scache_handle_t scache_handle;
   3315     uint8 *ipfix_scache = NULL;  
   3316     int size;
   3317     int arry_size;
   3318 
   3319     if (soc_feature(unit, soc_feature_ipfix_rate)) {
   3320         /*
   3321          * Return error if IPFIX is not initialized.
   3322          */
   3323         if (_bcm_ipfix_ctrl[unit] == NULL) {
   3324             return BCM_E_INIT;
   3325         }
   3326 
   3327         sal_memset(&scache_handle, 0, sizeof(soc_scache_handle_t));
   3328         /*
   3329          * Get ipfix base address handle and start writing 
   3330          * Level-2 recovery data to memory.
   3331          */
   3332         size = soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm);
   3333         arry_size = _SHR_BITDCLSIZE(size);
   3334         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_IPFIX, 0);
   3335         BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 
   3336                                                     FALSE, 0,
   3337                                                     &ipfix_scache, 
   3338                                                     BCM_WB_DEFAULT_VERSION, 
   3339                                                     NULL));
   3340         sal_memcpy(ipfix_scache, &ipfix_ctrl->rate_used_count, 
   3341                     sizeof(ipfix_ctrl->rate_used_count)); 
   3342         ipfix_scache += sizeof(ipfix_ctrl->rate_used_count);
   3343         sal_memcpy(ipfix_scache, ipfix_ctrl->rate_used_bmp, arry_size);
   3344     }
   3345 #endif /* !BCM_IPFIX_SUPPORT */
   3346     return BCM_E_NONE;
   3347 }
   3348 #endif /* !BCM_WARM_BOOT_SUPPORT */
   3349 
   3350 /*
   3351  * Function:
   3352  *     bcm_ipfix_export_fifo_control
   3353  * Description:
   3354  *     To start/stop ipfix export fifo processing thread
   3355  * Parameters:
   3356  *     unit            device number
   3357  *     sal_usecs_t     polling interval, set to 0 to stop the thread
   3358  * Return:
   3359  *     BCM_E_NONE
   3360  *     BCM_E_MEMORY
   3361  *     BCM_E_UNAVAIL
   3362  */
   3363 int
   3364 bcm_ipfix_export_fifo_control(int unit, sal_usecs_t interval)
   3365 {
   3366 #ifdef BCM_IPFIX_SUPPORT
   3367     _bcm_ipfix_ctrl_t *ipfix_ctrl = _bcm_ipfix_ctrl[unit];
   3368     const _bcm_ipfix_profile_def_t *profile_def = NULL;
   3369     const _bcm_ipfix_id_def_t *id_def = NULL;
   3370     int pri;
   3371     char name[16];
   3372 
   3373     if (!soc_feature(unit, soc_feature_ipfix) ||
   3374         !soc_feature(unit, soc_feature_fifo_dma)) {
   3375         return BCM_E_UNAVAIL;
   3376     }
   3377 
   3378 #ifdef BCM_TRIUMPH_SUPPORT
   3379     if (SOC_IS_TR_VL(unit)) {
   3380         profile_def = _ipfix_tr_profile_def;
   3381         id_def = &_ipfix_tr_id_def;
   3382     }
   3383 #endif /* BCM_TRIUMPH_SUPPORT */
   3384     if (profile_def == NULL || id_def == NULL) {
   3385         return BCM_E_INTERNAL;
   3386     }
   3387 
   3388     if (ipfix_ctrl == NULL) {
   3389         BCM_IF_ERROR_RETURN(_bcm_ipfix_init(unit, profile_def, id_def));
   3390         ipfix_ctrl = _bcm_ipfix_ctrl[unit];
   3391     }
   3392 
   3393     sal_snprintf(name, sizeof(name), "bcmIpfixDma.%d", unit);
   3394 
   3395     ipfix_ctrl->interval = interval;
   3396     if (interval) {
   3397         if (ipfix_ctrl->pid == SAL_THREAD_ERROR) {
   3398             pri = soc_property_get(unit, spn_IPFIX_THREAD_PRI, 100);
   3399             ipfix_ctrl->pid = sal_thread_create(name, SAL_THREAD_STKSZ, pri,
   3400                                                 _bcm_ipfix_fifo_dma_thread,
   3401                                                 INT_TO_PTR(unit));
   3402             if (ipfix_ctrl->pid == SAL_THREAD_ERROR) {
   3403                 LOG_ERROR(BSL_LS_BCM_IPFIX,
   3404                           (BSL_META_U(unit,
   3405                                       "Could not start thread\n")));
   3406                 return BCM_E_MEMORY;
   3407             }
   3408         }
   3409     } else {
   3410         /* Wake up thread so it will check the changed interval value */
   3411         sal_sem_give(SOC_CONTROL(unit)->ipfixIntr);
   3412     }
   3413 
   3414     return BCM_E_NONE;
   3415 #else /* BCM_IPFIX_SUPPORT */
   3416     return BCM_E_UNAVAIL;
   3417 #endif /* BCM_IPFIX_SUPPORT */
   3418 }
   3419 
   3420 int _bcm_esw_ipfix_deinit(int unit)
   3421 {
   3422 #ifdef BCM_IPFIX_SUPPORT
   3423     soc_timeout_t timeout;
   3424     _bcm_ipfix_ctrl_t *ipfix_ctrl = _bcm_ipfix_ctrl[unit];
   3425     int i;
   3426 #ifdef BCM_TRIUMPH3_SUPPORT
   3427     uint32 rval;
   3428 #endif
   3429 
   3430     if (NULL == ipfix_ctrl) {
   3431         return (BCM_E_NONE);
   3432     }
   3433 
   3434     bcm_ipfix_export_fifo_control(unit, 0);
   3435 
   3436     soc_timeout_init(&timeout, SAL_BOOT_BCMSIM ? 30000000 : 10000000, 0);
   3437 
   3438     while (ipfix_ctrl->pid != SAL_THREAD_ERROR)
   3439     {
   3440         if (soc_timeout_check(&timeout) != 0)
   3441         {
   3442             LOG_ERROR(BSL_LS_BCM_IPFIX,
   3443                       (BSL_META_U(unit,
   3444                                   "IPFIX thread did not exit.\n")));
   3445 
   3446             return BCM_E_INTERNAL;
   3447         }
   3448     }
   3449 
   3450     for (i = 0; i < _BCM_IPFIX_CB_MAX; i++) {
   3451         ipfix_ctrl->callback_entry[i].state =
   3452             _BCM_IPFIX_CALLBACK_STATE_INVALID;
   3453     }
   3454 
   3455 #ifdef BCM_TRIUMPH3_SUPPORT
   3456     if (SOC_IS_TRIUMPH3(unit)) {
   3457         BCM_IF_ERROR_RETURN(READ_AUX_ARB_CONTROL_2r(unit, &rval));
   3458         soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &rval,
   3459                 IPFIX_REFRESH_ENABLEf, 0);
   3460         BCM_IF_ERROR_RETURN(WRITE_AUX_ARB_CONTROL_2r(unit, rval));
   3461     }
   3462 #endif
   3463 
   3464     return BCM_E_NONE;
   3465 #else /* BCM_IPFIX_SUPPORT */
   3466     return BCM_E_UNAVAIL;
   3467 #endif /* BCM_IPFIX_SUPPORT */
   3468 }
   3469 
   3470 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
   3471 /*
   3472  * Function:
   3473  *     _bcm_ipfix_sw_dump
   3474  * Description:
   3475  *     Displays IPFIX information maintained in software.
   3476  * Parameters:
   3477  *     unit - Device unit number.
   3478  * Return:
   3479  *     None
   3480  */
   3481 void _bcm_ipfix_sw_dump(int unit)
   3482 {
   3483 #ifdef BCM_IPFIX_SUPPORT
   3484     _bcm_ipfix_ctrl_t *ipfix_ctrl = _bcm_ipfix_ctrl[unit];
   3485     int size;
   3486     int rate_id;
   3487     int rate_id_exists = 0;
   3488 
   3489     if (NULL == ipfix_ctrl) {
   3490         LOG_ERROR(BSL_LS_BCM_IPFIX,
   3491                   (BSL_META_U(unit,
   3492                               "IPFIX module not initialized.\n")));
   3493         return;
   3494     }
   3495     size = soc_mem_index_count(unit, ING_IPFIX_FLOW_RATE_METER_TABLEm);
   3496     LOG_CLI((BSL_META_U(unit,
   3497                         "\n SW Information IPFIX - Unit %d\n"), unit));
   3498     LOG_CLI((BSL_META_U(unit,
   3499                         "\n\tIPFIX Flow Rate Meter ID Info\n")));
   3500     LOG_CLI((BSL_META_U(unit,
   3501                         "\t-----------------------------\n")));
   3502     for (rate_id = 1; rate_id < size; rate_id++)  {
   3503         if (SHR_BITGET(_bcm_ipfix_ctrl[unit]->rate_used_bmp, rate_id)) {
   3504             LOG_CLI((BSL_META_U(unit,
   3505                                 "\t\tMeterId:%d - exists\n"), rate_id));
   3506             rate_id_exists = 1;
   3507         }
   3508     }
   3509     if (rate_id_exists == 0) {
   3510             LOG_CLI((BSL_META_U(unit,
   3511                                 "\t\tNone.\n")));
   3512     }
   3513     if (ipfix_ctrl->rate_used_count == 0) {
   3514         LOG_CLI((BSL_META_U(unit,
   3515                             "\n\tFlow Rate Meter config - Disabled\n")));
   3516     } else {
   3517         LOG_CLI((BSL_META_U(unit,
   3518                             "\n\tFlow Rate Meter config - Enabled\n")));
   3519     }
   3520 #endif /* !BCM_IPFIX_SUPPORT */
   3521     return;
   3522 }
   3523 #endif /* !BCM_WARM_BOOT_SUPPORT_SW_DUMP */