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

flowtracker.c (120792B)


      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  * Flowtracker - Flow Tracking embedded APP interface
      8  * Purpose: APIs to configure flowtracker embedded app interface.
      9  */
     10 
     11 #if defined(INCLUDE_FLOWTRACKER)
     12 
     13 #include <shared/bsl.h>
     14 #include <soc/defs.h>
     15 #include <soc/drv.h>
     16 #include <soc/uc.h>
     17 #include <shared/alloc.h>
     18 #include <soc/shared/ft.h>
     19 #include <soc/shared/ft_msg.h>
     20 #include <soc/shared/ft_pack.h>
     21 #include <soc/shared/shr_pkt.h>
     22 
     23 
     24 #include <bcm/types.h>
     25 #include <bcm/error.h>
     26 
     27 #include <bcm_int/esw/flowtracker.h>
     28 #include <bcm_int/esw/xgs5.h>
     29 #include <bcm_int/common/rx.h>
     30 #include <bcm_int/esw_dispatch.h>
     31 #include <bcm_int/esw/collector.h>
     32 
     33 
     34 /* List of flowtracker export templates info */
     35 _bcm_int_ft_export_template_info_t *ft_export_template_info_list[BCM_MAX_NUM_UNITS] = {0};
     36 /* List of flowtracker collector info*/
     37 _bcm_int_ft_collector_info_t *ft_collector_info_list[BCM_MAX_NUM_UNITS] = {0};
     38 _bcm_int_ft_v2_collector_info_t *ft_v2_collector_info_list[BCM_MAX_NUM_UNITS] = {0};
     39 _bcm_int_ft_v2_export_profile_info_t *ft_v2_export_profile_info_list[BCM_MAX_NUM_UNITS] = {0};
     40 
     41 /* List of flowtracker flow_group info*/
     42 _bcm_int_ft_flow_group_info_t *ft_flow_group_info_list[BCM_MAX_NUM_UNITS] = {0};
     43 
     44 /* List of flowtracker elph_profile info*/
     45 _bcm_int_ft_elph_profile_info_t *ft_elph_profile_info_list[BCM_MAX_NUM_UNITS] = {0};
     46 
     47 
     48 /******************************************************
     49 *                                                     *
     50 *                 UTILITY FUNCTIONS                   *
     51  */
     52 
     53 /*
     54  * Functions:
     55  *      _bcm_xgs5_ft_<header>_get
     56  * Purpose:
     57  *      The following set of _get() functions builds a given header for
     58  *      a given collector.
     59  * Parameters:
     60  *      collector_info -  (IN) Pointer to Collector information structure.
     61  *      <... other IN args ...>
     62  *      <header>  - (OUT) Returns header.
     63  * Returns:
     64  *      BCM_E_XXX
     65  * Notes:
     66  */
     67 STATIC int
     68 _bcm_xgs5_ft_udp_header_get(
     69                 bcm_flowtracker_collector_info_t *collector_info,
     70                 shr_udp_header_t *udp)
     71 {
     72     /* Set UDP */
     73     sal_memset(udp, 0, sizeof(*udp));
     74     udp->src = collector_info->udp.src_port;
     75     udp->dst = collector_info->udp.dst_port;
     76     /* Do not set UDP length since this will be filled by
     77      * EAPP.
     78      */
     79     udp->length = 0;
     80     udp->sum = 0;    /* Calculated later */
     81 
     82     return BCM_E_NONE;
     83 }
     84 
     85 STATIC int
     86 _bcm_xgs5_ft_v2_udp_header_get(
     87                 bcm_collector_info_t *collector_info,
     88                 shr_udp_header_t *udp)
     89 {
     90     /* Set UDP */
     91     sal_memset(udp, 0, sizeof(*udp));
     92     udp->src = collector_info->udp.src_port;
     93     udp->dst = collector_info->udp.dst_port;
     94     /* Do not set UDP length since this will be filled by
     95      * EAPP.
     96      */
     97     udp->length = 0;
     98     udp->sum = 0;    /* Calculated later */
     99 
    100     return BCM_E_NONE;
    101 }
    102 
    103 STATIC int
    104 _bcm_xgs5_ft_ipv4_header_get(uint8 protocol,
    105                               uint8 tos, uint8 ttl,
    106                               bcm_ip_t src_ip_addr, bcm_ip_t dst_ip_addr,
    107                               shr_ipv4_header_t *ip)
    108 {
    109     uint8 buffer[SHR_IPV4_HEADER_LENGTH];
    110 
    111     sal_memset(ip, 0, sizeof(*ip));
    112 
    113     ip->version  = SHR_IPV4_VERSION;
    114     ip->h_length = SHR_IPV4_HEADER_LENGTH_WORDS;
    115     ip->dscp     = tos;
    116     ip->ecn      = 0;
    117     /* Dont fill in length since length will be calculated by
    118      * EAPP.
    119      */
    120     ip->length   = 0;
    121     ip->id       = 0;
    122     ip->flags    = 0;
    123     ip->f_offset = 0;
    124     ip->ttl      = ttl;
    125     ip->protocol = protocol;
    126     ip->sum      = 0;
    127     ip->src      = src_ip_addr;
    128     ip->dst      = dst_ip_addr;
    129 
    130     /* Calculate IP header checksum */
    131     shr_ipv4_header_pack(buffer, ip);
    132     ip->sum = 0;
    133 
    134     return BCM_E_NONE;
    135 }
    136 
    137 
    138 STATIC int
    139 _bcm_xgs5_ft_ip_headers_get(bcm_flowtracker_collector_info_t *collector_info,
    140                              uint16 *etype,
    141                              shr_ipv4_header_t *ipv4)
    142 {
    143     int ip_protocol;
    144 
    145     ip_protocol = SHR_IP_PROTOCOL_UDP;
    146 
    147 
    148     *etype = SHR_L2_ETYPE_IPV4;
    149 
    150     BCM_IF_ERROR_RETURN
    151         (_bcm_xgs5_ft_ipv4_header_get( ip_protocol,
    152                                        collector_info->ipv4.dscp,
    153                                        collector_info->ipv4.ttl,
    154                                        collector_info->ipv4.src_ip,
    155                                        collector_info->ipv4.dst_ip,
    156                                        ipv4));
    157 
    158     return BCM_E_NONE;
    159 }
    160 
    161 STATIC int
    162 _bcm_xgs5_ft_v2_ip_headers_get(bcm_collector_info_t *collector_info,
    163                                uint16 *etype,
    164                                shr_ipv4_header_t *ipv4)
    165 {
    166     int ip_protocol;
    167 
    168     ip_protocol = SHR_IP_PROTOCOL_UDP;
    169 
    170 
    171     *etype = SHR_L2_ETYPE_IPV4;
    172 
    173     BCM_IF_ERROR_RETURN
    174         (_bcm_xgs5_ft_ipv4_header_get(ip_protocol,
    175                                       collector_info->ipv4.dscp,
    176                                       collector_info->ipv4.ttl,
    177                                       collector_info->ipv4.src_ip,
    178                                       collector_info->ipv4.dst_ip,
    179                                       ipv4));
    180 
    181     return BCM_E_NONE;
    182 }
    183 
    184 STATIC int
    185 _bcm_xgs5_ft_l2_header_get(bcm_flowtracker_collector_info_t *collector_info,
    186                            uint16 etype, shr_l2_header_t *l2)
    187 {
    188     sal_memset(l2, 0, sizeof(*l2));
    189 
    190     /* Destination and Source MAC */
    191     sal_memcpy(l2->dst_mac, collector_info->eth.dst_mac, SHR_MAC_ADDR_LENGTH);
    192     sal_memcpy(l2->src_mac, collector_info->eth.src_mac, SHR_MAC_ADDR_LENGTH);
    193 
    194     /*
    195      * VLAN Tag(s)
    196      */
    197     if (collector_info->eth.vlan_tag_structure == BCM_FLOWTRACKER_COLLECTOR_ETH_HDR_UNTAGGED) { 
    198         /* Set to 0 to indicate untagged */
    199         l2->outer_vlan_tag.tpid = 0;
    200         l2->inner_vlan_tag.tpid = 0;
    201     } else {
    202         /* Fill outer vlan */
    203         if ((collector_info->eth.vlan_tag_structure == BCM_FLOWTRACKER_COLLECTOR_ETH_HDR_SINGLE_TAGGED) ||
    204             (collector_info->eth.vlan_tag_structure == BCM_FLOWTRACKER_COLLECTOR_ETH_HDR_DOUBLE_TAGGED))
    205         {
    206             l2->outer_vlan_tag.tpid     = collector_info->eth.outer_tpid;
    207             l2->outer_vlan_tag.tci.prio = BCM_VLAN_CTRL_PRIO(collector_info->eth.outer_vlan_tag);
    208             l2->outer_vlan_tag.tci.cfi  = BCM_VLAN_CTRL_CFI(collector_info->eth.outer_vlan_tag);
    209             l2->outer_vlan_tag.tci.vid  = BCM_VLAN_CTRL_ID(collector_info->eth.outer_vlan_tag);
    210         } else {
    211             return BCM_E_PARAM;
    212         }
    213         /* Fill inner vlan if double tagged */
    214         if (collector_info->eth.vlan_tag_structure == BCM_FLOWTRACKER_COLLECTOR_ETH_HDR_DOUBLE_TAGGED) {
    215             l2->inner_vlan_tag.tpid     = collector_info->eth.inner_tpid;
    216             l2->inner_vlan_tag.tci.prio = BCM_VLAN_CTRL_PRIO(collector_info->eth.inner_vlan_tag);
    217             l2->inner_vlan_tag.tci.cfi  = BCM_VLAN_CTRL_CFI(collector_info->eth.inner_vlan_tag);
    218             l2->inner_vlan_tag.tci.vid  = BCM_VLAN_CTRL_ID(collector_info->eth.inner_vlan_tag);
    219         } else {
    220             l2->inner_vlan_tag.tpid = 0;  /* Set to 0 to indicate not inner tagged */
    221         }
    222     }
    223 
    224     /* Ether Type */
    225     l2->etype = etype;
    226 
    227     return BCM_E_NONE;
    228 }
    229 
    230 STATIC int
    231 _bcm_xgs5_ft_v2_l2_header_get(bcm_collector_info_t *collector_info,
    232                               uint16 etype, shr_l2_header_t *l2)
    233 {
    234     sal_memset(l2, 0, sizeof(*l2));
    235 
    236     /* Destination and Source MAC */
    237     sal_memcpy(l2->dst_mac, collector_info->eth.dst_mac, SHR_MAC_ADDR_LENGTH);
    238     sal_memcpy(l2->src_mac, collector_info->eth.src_mac, SHR_MAC_ADDR_LENGTH);
    239 
    240     /*
    241      * VLAN Tag(s)
    242      */
    243     if (collector_info->eth.vlan_tag_structure == BCM_COLLECTOR_ETH_HDR_UNTAGGED) { 
    244         /* Set to 0 to indicate untagged */
    245         l2->outer_vlan_tag.tpid = 0;
    246         l2->inner_vlan_tag.tpid = 0;
    247     } else {
    248         /* Fill outer vlan */
    249         if ((collector_info->eth.vlan_tag_structure == BCM_COLLECTOR_ETH_HDR_SINGLE_TAGGED) ||
    250             (collector_info->eth.vlan_tag_structure == BCM_COLLECTOR_ETH_HDR_DOUBLE_TAGGED))
    251         {
    252             l2->outer_vlan_tag.tpid     = collector_info->eth.outer_tpid;
    253             l2->outer_vlan_tag.tci.prio = BCM_VLAN_CTRL_PRIO(collector_info->eth.outer_vlan_tag);
    254             l2->outer_vlan_tag.tci.cfi  = BCM_VLAN_CTRL_CFI(collector_info->eth.outer_vlan_tag);
    255             l2->outer_vlan_tag.tci.vid  = BCM_VLAN_CTRL_ID(collector_info->eth.outer_vlan_tag);
    256         } else {
    257             return BCM_E_PARAM;
    258         }
    259         /* Fill inner vlan if double tagged */
    260         if (collector_info->eth.vlan_tag_structure == BCM_COLLECTOR_ETH_HDR_DOUBLE_TAGGED) {
    261             l2->inner_vlan_tag.tpid     = collector_info->eth.inner_tpid;
    262             l2->inner_vlan_tag.tci.prio = BCM_VLAN_CTRL_PRIO(collector_info->eth.inner_vlan_tag);
    263             l2->inner_vlan_tag.tci.cfi  = BCM_VLAN_CTRL_CFI(collector_info->eth.inner_vlan_tag);
    264             l2->inner_vlan_tag.tci.vid  = BCM_VLAN_CTRL_ID(collector_info->eth.inner_vlan_tag);
    265         } else {
    266             l2->inner_vlan_tag.tpid = 0;  /* Set to 0 to indicate not inner tagged */
    267         }
    268     }
    269 
    270     /* Ether Type */
    271     l2->etype = etype;
    272 
    273     return BCM_E_NONE;
    274 }
    275 
    276 /*
    277  * Function:
    278  *      _bcm_xgs5_ft_eapp_collector_encap_build_pack
    279  * Purpose:
    280  *      Builds and packs the Flowtracker export packet
    281  *      encapsulation for a given collector
    282  * Parameters:
    283  *      unit                 - (IN)  BCM device number
    284  *      collector_id         - (IN)  Collector Id
    285  *      collector_create_msg - (OUT) Message which contains the encapsulation.
    286  * Returns:
    287  *      BCM_E_XXX
    288  * Notes:
    289  *      The returning encapsulation includes only all the
    290  *      encapsulation headers and does not include
    291  *      the IPFIX control packet.
    292  */
    293 STATIC int
    294 _bcm_xgs5_ft_eapp_collector_encap_build_pack(
    295                        int unit,
    296                        int collector_id,
    297                        shr_ft_msg_ctrl_collector_create_t *collector_create_msg)
    298 {
    299     uint8          *buffer  = collector_create_msg->encap;
    300     uint8          *cur_ptr;
    301     uint16         etype = 0;
    302     shr_udp_header_t  udp;
    303     shr_ipv4_header_t ipv4;
    304     shr_l2_header_t   l2;
    305     uint16         ip_offset = 0;
    306     uint16         udp_offset = 0;
    307     _bcm_int_ft_collector_info_t collector_int_info;
    308     int rv;
    309 
    310 
    311     sal_memset(&collector_int_info, 0, sizeof(collector_int_info));
    312     /* Get the collector info for this collector id */
    313     rv = _bcm_xgs5_ft_collector_list_collector_get(unit, collector_id, &collector_int_info);
    314 
    315     /* Return BCM_E_NOT_FOUND if not found */
    316     if (BCM_FAILURE(rv)) {
    317         return rv;
    318     }
    319     sal_memset(collector_create_msg, 0, sizeof(shr_ft_msg_ctrl_collector_create_t));
    320     collector_create_msg->id = collector_id;
    321     collector_create_msg->mtu = collector_int_info.collector_info.max_packet_length;
    322 
    323     sal_memset(&udp, 0, sizeof(udp));
    324     sal_memset(&ipv4, 0, sizeof(ipv4));
    325     sal_memset(&l2, 0, sizeof(l2));
    326 
    327 
    328     /*
    329      * Get necessary headers/labels information.
    330      *
    331      * Following order is important since some headers/labels
    332      * may depend on previous header/label information.
    333      */
    334     if (collector_int_info.collector_info.transport_type ==
    335                      bcmFlowtrackerCollectorTransportTypeIpfixIpv4Udp) {
    336         BCM_IF_ERROR_RETURN
    337             (_bcm_xgs5_ft_udp_header_get(&(collector_int_info.collector_info), &udp));
    338     }
    339 
    340     if (collector_int_info.collector_info.transport_type ==
    341                      bcmFlowtrackerCollectorTransportTypeIpfixIpv4Udp) {
    342         BCM_IF_ERROR_RETURN
    343             (_bcm_xgs5_ft_ip_headers_get(&(collector_int_info.collector_info),
    344                                           &etype,
    345                                           &ipv4));
    346     }
    347 
    348     /* Always build L2 Header */
    349     BCM_IF_ERROR_RETURN
    350         (_bcm_xgs5_ft_l2_header_get(&(collector_int_info.collector_info),
    351                                     etype, &l2));
    352 
    353     /*
    354      * Pack header/labels into given buffer (network packet format).
    355      *
    356      * Following packing order must be followed to correctly
    357      * build the packet encapsulation.
    358      */
    359     cur_ptr = buffer;
    360 
    361     /* L2 Header is always present */
    362     cur_ptr = shr_l2_header_pack(cur_ptr, &l2);
    363 
    364     if (collector_int_info.collector_info.transport_type ==
    365                      bcmFlowtrackerCollectorTransportTypeIpfixIpv4Udp) {
    366         /*
    367          * IP offset
    368          */
    369         ip_offset = cur_ptr - buffer;
    370 
    371         cur_ptr = shr_ipv4_header_pack(cur_ptr, &ipv4);
    372     }
    373 
    374     if (collector_int_info.collector_info.transport_type ==
    375                      bcmFlowtrackerCollectorTransportTypeIpfixIpv4Udp) {
    376         /*
    377          * UDP offset
    378          */
    379         udp_offset = cur_ptr - buffer;
    380         cur_ptr = shr_udp_header_pack(cur_ptr, &udp);
    381     }
    382 
    383 
    384     /* Set Flowtracker export pkt encapsulation length */
    385     collector_create_msg->encap_length = cur_ptr - buffer;
    386 
    387     /* Set Flowtracker export pkt IP base offset */
    388     collector_create_msg->ip_offset = ip_offset;
    389 
    390     /* Set Flowtracker export pkt IP Base checksum */
    391     collector_create_msg->ip_base_checksum =
    392              shr_initial_chksum_get(SHR_IPV4_HEADER_LENGTH, buffer + ip_offset);
    393 
    394     /* Set Flowtracker export pkt UDP Base checksum */
    395     if (collector_int_info.collector_info.transport_type ==
    396                      bcmFlowtrackerCollectorTransportTypeIpfixIpv4Udp) {
    397         collector_create_msg->udp_base_checksum =
    398                               shr_udp_initial_checksum_get(0, &ipv4, NULL, NULL, &udp);
    399     }
    400     /* Set Flowtracker export pkt UDP base offset */
    401     collector_create_msg->udp_offset = udp_offset;
    402 
    403 
    404     return BCM_E_NONE;
    405 }
    406 
    407 /*
    408  * Function:
    409  *      _bcm_xgs5_ft_v2_eapp_collector_encap_build_pack
    410  * Purpose:
    411  *      Builds and packs the Flowtracker export packet
    412  *      encapsulation for a given collector
    413  * Parameters:
    414  *      unit                 - (IN)  BCM device number
    415  *      collector_id        -  (IN) Collector Id
    416  *      collector_create_msg - (OUT) Message which contains the encapsulation.
    417  * Returns:
    418  *      BCM_E_XXX
    419  * Notes:
    420  *      The returning encapsulation includes only all the
    421  *      encapsulation headers and does not include
    422  *      the IPFIX control packet.
    423  */
    424 STATIC int
    425 _bcm_xgs5_ft_v2_eapp_collector_encap_build_pack(
    426                        int unit,
    427                        bcm_collector_t collector_id,
    428                        int export_profile_id,
    429                        shr_ft_msg_ctrl_collector_create_t *collector_create_msg)
    430 {
    431     uint8          *buffer  = collector_create_msg->encap;
    432     uint8          *cur_ptr;
    433     uint16         etype = 0;
    434     shr_udp_header_t  udp;
    435     shr_ipv4_header_t ipv4;
    436     shr_l2_header_t   l2;
    437     uint16         ip_offset = 0;
    438     uint16         udp_offset = 0;
    439     bcm_collector_info_t collector_info;
    440     bcm_collector_export_profile_t export_profile_info;
    441     int coll_int_id;
    442     int rv;
    443 
    444     /* Get the collector internal info for this collector id */
    445     rv = _bcm_xgs5_ft_v2_collector_list_collector_get(unit, collector_id,
    446                                                       &coll_int_id);
    447 
    448     /* Return BCM_E_NOT_FOUND if not found */
    449     if (BCM_FAILURE(rv)) {
    450         return rv;
    451     }
    452 
    453     /* Get the collector info */
    454     bcm_collector_info_t_init(&collector_info);
    455     rv = bcm_esw_collector_get(unit, collector_id, &collector_info);
    456     BCM_IF_ERROR_RETURN(rv);
    457 
    458 
    459     /* Get the export profile info */
    460     bcm_collector_export_profile_t_init(&export_profile_info);
    461     rv = bcm_esw_collector_export_profile_get(unit,
    462                                               export_profile_id,
    463                                               &export_profile_info);
    464     BCM_IF_ERROR_RETURN(rv);
    465 
    466     sal_memset(collector_create_msg, 0, sizeof(shr_ft_msg_ctrl_collector_create_t));
    467     collector_create_msg->id = coll_int_id;
    468     collector_create_msg->mtu = export_profile_info.max_packet_length;
    469 
    470     sal_memset(&udp, 0, sizeof(udp));
    471     sal_memset(&ipv4, 0, sizeof(ipv4));
    472     sal_memset(&l2, 0, sizeof(l2));
    473 
    474 
    475     /*
    476      * Get necessary headers/labels information.
    477      *
    478      * Following order is important since some headers/labels
    479      * may depend on previous header/label information.
    480      */
    481     if (collector_info.transport_type == bcmCollectorTransportTypeIpv4Udp) {
    482         BCM_IF_ERROR_RETURN
    483             (_bcm_xgs5_ft_v2_udp_header_get(&collector_info, &udp));
    484     }
    485 
    486     if (collector_info.transport_type == bcmCollectorTransportTypeIpv4Udp) {
    487         BCM_IF_ERROR_RETURN
    488             (_bcm_xgs5_ft_v2_ip_headers_get(&collector_info,
    489                                           &etype,
    490                                           &ipv4));
    491     }
    492 
    493     /* Always build L2 Header */
    494     BCM_IF_ERROR_RETURN
    495         (_bcm_xgs5_ft_v2_l2_header_get(&collector_info, etype, &l2));
    496 
    497     /*
    498      * Pack header/labels into given buffer (network packet format).
    499      *
    500      * Following packing order must be followed to correctly
    501      * build the packet encapsulation.
    502      */
    503     cur_ptr = buffer;
    504 
    505     /* L2 Header is always present */
    506     cur_ptr = shr_l2_header_pack(cur_ptr, &l2);
    507 
    508     if (collector_info.transport_type == bcmCollectorTransportTypeIpv4Udp) {
    509         /*
    510          * IP offset
    511          */
    512         ip_offset = cur_ptr - buffer;
    513 
    514         cur_ptr = shr_ipv4_header_pack(cur_ptr, &ipv4);
    515     }
    516 
    517     if (collector_info.transport_type == bcmCollectorTransportTypeIpv4Udp) {
    518         /*
    519          * UDP offset
    520          */
    521         udp_offset = cur_ptr - buffer;
    522         cur_ptr = shr_udp_header_pack(cur_ptr, &udp);
    523     }
    524 
    525 
    526     /* Set Flowtracker export pkt encapsulation length */
    527     collector_create_msg->encap_length = cur_ptr - buffer;
    528 
    529     /* Set Flowtracker export pkt IP base offset */
    530     collector_create_msg->ip_offset = ip_offset;
    531 
    532     /* Set Flowtracker export pkt IP Base checksum */
    533     collector_create_msg->ip_base_checksum =
    534              shr_initial_chksum_get(SHR_IPV4_HEADER_LENGTH, buffer + ip_offset);
    535 
    536     /* Set Flowtracker export pkt UDP Base checksum */
    537     if (collector_info.transport_type == bcmCollectorTransportTypeIpv4Udp) {
    538         collector_create_msg->udp_base_checksum =
    539                               shr_udp_initial_checksum_get(0, &ipv4, NULL, NULL, &udp);
    540     }
    541     /* Set Flowtracker export pkt UDP base offset */
    542     collector_create_msg->udp_offset = udp_offset;
    543 
    544     if (export_profile_info.wire_format == bcmCollectorWireFormatProtoBuf) {
    545         /* Set Flowtracker export pkt Component ID */
    546         collector_create_msg->component_id = collector_info.protobuf.component_id;
    547 
    548         /* Set Flowtracker export pkt System ID length */
    549         collector_create_msg->system_id_length = collector_info.protobuf.system_id_length;
    550 
    551         /* Set Flowtracker export pkt System ID */
    552         memcpy(&collector_create_msg->system_id, &collector_info.protobuf.system_id,
    553                collector_info.protobuf.system_id_length);
    554     }
    555 
    556     return BCM_E_NONE;
    557 }
    558 
    559 /*
    560  * Function:
    561  *      _bcm_xgs5_ft_eapp_template_encap_build_pack
    562  * Purpose:
    563  *      Build the template set encap
    564  * Parameters:
    565  *      template_int_info - (IN)   Template Information
    566  *      encap_length      - (OUT)  Encap length
    567  *      encap             - (OUT)  Encap
    568  * Returns:
    569  *      None
    570  */
    571 STATIC void
    572 _bcm_xgs5_ft_eapp_template_encap_build_pack(
    573                   int unit,
    574                   _bcm_int_ft_export_template_info_t *template_int_info,
    575                   uint16 *encap_length, uint8 *buf)
    576 {
    577     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
    578     uint8  *cur_ptr = buf;
    579     uint16  element_id;
    580     int     i;
    581 
    582     /*
    583      * +----------------------+------------------+
    584      * |     Bits 0...15      |   Bits 16...31   |
    585      * +----------------------+------------------+
    586      * | Set ID = 2(Template) |    Set Length    |
    587      * +----------------------+------------------+
    588      * |     Template ID      | Number of fields |
    589      * +----------------------+------------------+
    590      * |        Type          |   Field Length   |
    591      * +----------------------+------------------+
    592      * |        Type          |   Field Length   |
    593      * +----------------------+------------------+
    594      * |        Type          |   Field Length   |
    595      * +----------------------+------------------+
    596      */
    597 
    598     SHR_PKT_PACK_U16(cur_ptr, FT_INT_TEMPLATE_XMIT_SET_ID);
    599 
    600     /* Skip over length */
    601     cur_ptr += 2;
    602 
    603     SHR_PKT_PACK_U16(cur_ptr, template_int_info->set_id);
    604     SHR_PKT_PACK_U16(cur_ptr, template_int_info->num_export_elements);
    605 
    606     for (i = 0; i < template_int_info->num_export_elements; i++) {
    607         if (template_int_info->elements[i].enterprise == 0) {
    608             /* Non enterprise element, format below */
    609             /*
    610              * +-+--------------------+------------------+
    611              * |0|      1...15        |     16...31      |
    612              * +-+--------------------+------------------+
    613              * |0|      Type          |   Field Length   |
    614              * +----------------------+------------------+
    615              */
    616             SHR_PKT_PACK_U16(cur_ptr, template_int_info->elements[i].id);
    617             SHR_PKT_PACK_U16(cur_ptr, template_int_info->elements[i].data_size);
    618         } else {
    619             /* Enterprise specific */
    620             /*
    621              * +-+--------------------+------------------+
    622              * |0|      1...15        |     16...31      |
    623              * +-+--------------------+------------------+
    624              * |1|      Type          |   Field Length   |
    625              * +----------------------+------------------+
    626              * |             Enterprise number           |
    627              * +----------------------+------------------+
    628              */
    629             /* Set the enterprise bit */
    630             element_id = (1 << 15) | template_int_info->elements[i].id;
    631             SHR_PKT_PACK_U16(cur_ptr, element_id);
    632             SHR_PKT_PACK_U16(cur_ptr, template_int_info->elements[i].data_size);
    633             SHR_PKT_PACK_U32(cur_ptr, ft_info->enterprise_number);
    634         }
    635     }
    636 
    637     *encap_length = cur_ptr - buf;
    638 }
    639 /******************************************************
    640 *                                                     *
    641 *        EXPORT TEMPLATE LIST MANAGEMENT FUNCTIONS    *
    642  */
    643 
    644 /*
    645  * Function:
    646  *     _bcm_xgs5_ft_template_list_template_add
    647  * Purpose:
    648  *     Add a template to the template list.
    649  * Parameters:
    650  *     unit              - (IN) BCM device number
    651  *     template_id       - (IN) The template ID
    652  *     template_int_info - (IN) Template info to be added
    653  * Returns:
    654  *     BCM_E_XXX
    655  */
    656 int
    657 _bcm_xgs5_ft_template_list_template_add(int unit,
    658                            bcm_flowtracker_export_template_t template_id,
    659                            _bcm_int_ft_export_template_info_t *template_int_info)
    660 {
    661     _bcm_int_ft_export_template_info_t *template_info_list_node =
    662                    &(ft_export_template_info_list[unit][template_id]);
    663 
    664     if (template_info_list_node->template_id != 0) {
    665         /* Not free */
    666         return BCM_E_EXISTS;
    667     }
    668 
    669     template_int_info->template_id = template_id;
    670     memcpy(template_info_list_node, template_int_info,
    671            sizeof(_bcm_int_ft_export_template_info_t));
    672 
    673 
    674     LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
    675             (BSL_META_U(unit,
    676                         "FT(unit %d) Info: %s" 
    677                         " (Template=0x%x).\n"), unit, __FUNCTION__,
    678                          template_id));
    679     return (BCM_E_NONE);
    680 }
    681 
    682 /*
    683  * Function:
    684  *     _bcm_xgs5_ft_template_list_template_delete
    685  * Purpose:
    686  *     Delete a template from the template list.
    687  * Parameters:
    688  *     unit          - (IN) BCM device number
    689  *     template_id   - (IN) The template ID
    690  * Returns:
    691  *     BCM_E_XXX
    692  */
    693 int
    694 _bcm_xgs5_ft_template_list_template_delete (int unit,
    695                               bcm_flowtracker_export_template_t template_id)
    696 {
    697     _bcm_int_ft_export_template_info_t *template_info_list_node =
    698         &(ft_export_template_info_list[unit][template_id]);
    699 
    700     if (template_info_list_node->template_id != template_id) {
    701         LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
    702                   (BSL_META_U(unit,
    703                               "FT(unit %d) Info: Template is not present"), unit));
    704         return (BCM_E_NOT_FOUND);
    705     }
    706 
    707     sal_memset(template_info_list_node, 0,
    708                             sizeof(_bcm_int_ft_export_template_info_t));
    709 
    710     return (BCM_E_NONE);
    711 }
    712 
    713 /*
    714  * Function:
    715  *     _bcm_xgs5_ft_template_list_template_modify
    716  * Purpose:
    717  *     Modfiy a template in the template list.
    718  * Parameters:
    719  *     unit            - (IN) BCM device number
    720  *     template_id     - (IN) Template Id
    721  *     template_info   - (IN) Template informatin.
    722  * Returns:
    723  *     BCM_E_XXX
    724  */
    725 int
    726 _bcm_xgs5_ft_template_list_template_modify(
    727                                int unit,
    728                                bcm_flowtracker_export_template_t template_id,
    729                                _bcm_int_ft_export_template_info_t *template_info)
    730 {
    731     _bcm_int_ft_export_template_info_t *list_node =
    732                               &(ft_export_template_info_list[unit][template_id]);
    733 
    734     if (list_node->template_id != template_id) {
    735         /* Not found */
    736         LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
    737                   (BSL_META_U(unit,
    738                               "FT(unit %d) Info: Template ID does not exist"), unit));
    739         return (BCM_E_NOT_FOUND);
    740     }
    741 
    742     sal_memcpy(list_node, template_info,
    743                sizeof(_bcm_int_ft_export_template_info_t));
    744 
    745     return BCM_E_NONE;
    746 }
    747 
    748 /*
    749  * Function:
    750  *     _bcm_xgs5_ft_template_list_template_get
    751  * Purpose:
    752  *     Get a template from the template list.
    753  * Parameters:
    754  *     unit          - (IN) BCM device number
    755  *     template_id   - (IN) The template ID
    756  *     template_info - (OUT) template information
    757  * Returns:
    758  *     BCM_E_XXX
    759  */
    760 int
    761 _bcm_xgs5_ft_template_list_template_get (int unit,
    762                               bcm_flowtracker_export_template_t template_id,
    763                               _bcm_int_ft_export_template_info_t *template_info)
    764 {
    765     _bcm_int_ft_export_template_info_t *list_node =
    766                   &(ft_export_template_info_list[unit][template_id]);
    767 
    768     if (list_node->template_id == template_id) {
    769         sal_memcpy(template_info, list_node, sizeof(_bcm_int_ft_export_template_info_t));
    770     } else {
    771         return (BCM_E_NOT_FOUND);
    772     }
    773 
    774     return BCM_E_NONE;
    775 }
    776 
    777 /*
    778  * Function:
    779  *     _bcm_xgs5_ft_template_list_destroy
    780  * Purpose:
    781  *     Destroy the template list.
    782  * Parameters:
    783  *     unit          - (IN) BCM device number
    784  * Returns:
    785  *     BCM_E_XXX
    786  */
    787 int
    788 _bcm_xgs5_ft_template_list_destroy (int unit)
    789 {
    790     if (ft_export_template_info_list[unit] != NULL) {
    791         sal_free(ft_export_template_info_list[unit]);
    792     }
    793     ft_export_template_info_list[unit] = NULL;
    794     return BCM_E_NONE;
    795 }
    796 
    797 /*
    798  * Function:
    799  *     _bcm_xgs5_ft_template_list_create
    800  * Purpose:
    801  *     Create the template list.
    802  * Parameters:
    803  *     unit          - (IN) BCM device number
    804  * Returns:
    805  *     BCM_E_XXX
    806  */
    807 int
    808 _bcm_xgs5_ft_template_list_create (int unit)
    809 {
    810     if (ft_export_template_info_list[unit] == NULL) {
    811         /* Allocate template list */
    812         _BCM_FT_ALLOC(ft_export_template_info_list[unit], _bcm_int_ft_export_template_info_t,
    813                       sizeof(_bcm_int_ft_export_template_info_t) *
    814                          (BCM_INT_FT_MAX_TEMPLATES + BCM_INT_FT_TEMPLATE_START_ID),
    815                       "template list");
    816     }
    817 
    818     if (ft_export_template_info_list[unit] == NULL) {
    819         return BCM_E_MEMORY;
    820     }
    821     return BCM_E_NONE;
    822 }
    823 
    824 /******************************************************
    825 *                                                     *
    826 *        COLLECTOR LIST MANAGEMENT FUNCTIONS          *
    827  */
    828 
    829 /*
    830  * Function:
    831  *     _bcm_xgs5_ft_collector_list_collector_add
    832  * Purpose:
    833  *     Add a collector to the collector list.
    834  * Parameters:
    835  *     unit          - (IN) BCM device number
    836  *     collector_id   - (IN) The collector ID
    837  *     collector_info - (IN) Collector informatin.
    838  * Returns:
    839  *     BCM_E_XXX
    840  */
    841 int
    842 _bcm_xgs5_ft_collector_list_collector_add(int unit,
    843                            bcm_flowtracker_collector_t collector_id,
    844                            bcm_flowtracker_collector_info_t *collector_info)
    845 {
    846     _bcm_int_ft_collector_info_t *collector_info_list_node =
    847         &(ft_collector_info_list[unit][collector_id]);
    848 
    849     if (collector_info_list_node->collector_id != 0) {
    850         return BCM_E_EXISTS;
    851     }
    852     collector_info_list_node->collector_id = collector_id;
    853 
    854     sal_memcpy(&(collector_info_list_node->collector_info), collector_info,
    855                sizeof(bcm_flowtracker_collector_info_t));
    856 
    857     LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
    858             (BSL_META_U(unit,
    859                         "FT(unit %d) Info: %s" 
    860                         " (Collector=0x%x).\n"), unit, __FUNCTION__,
    861                          collector_id));
    862     return (BCM_E_NONE);
    863 }
    864 
    865 /*
    866  * Function:
    867  *     _bcm_xgs5_ft_collector_list_collector_delete
    868  * Purpose:
    869  *     Delete a collector from the collector list.
    870  * Parameters:
    871  *     unit          - (IN) BCM device number
    872  *     collector_id   - (IN) The collector ID
    873  * Returns:
    874  *     BCM_E_XXX
    875  */
    876 int
    877 _bcm_xgs5_ft_collector_list_collector_delete (int unit,
    878                               bcm_flowtracker_collector_t collector_id)
    879 {
    880     _bcm_int_ft_collector_info_t *collector_info_list_node =
    881         &(ft_collector_info_list[unit][collector_id]);
    882 
    883     if (collector_info_list_node->collector_id != collector_id) {
    884         LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
    885                   (BSL_META_U(unit,
    886                               "FT(unit %d) Info: collector ID does not exist"), unit));
    887         return (BCM_E_NOT_FOUND);
    888     }
    889 
    890     sal_memset(collector_info_list_node, 0,
    891                                  sizeof(_bcm_int_ft_collector_info_t));
    892 
    893     return (BCM_E_NONE);
    894 }
    895 
    896 /*
    897  * Function:
    898  *     _bcm_xgs5_ft_collector_list_collector_modify
    899  * Purpose:
    900  *     Modfiy a collector in the collector list.
    901  * Parameters:
    902  *     unit          - (IN) BCM device number
    903  *     collector_id   - (IN) The collector ID
    904  *     collector_info - (IN) Collector informatin.
    905  * Returns:
    906  *     BCM_E_XXX
    907  */
    908 int
    909 _bcm_xgs5_ft_collector_list_collector_modify(int unit,
    910                            bcm_flowtracker_collector_t collector_id,
    911                            bcm_flowtracker_collector_info_t *collector_info)
    912 {
    913     _bcm_int_ft_collector_info_t *list_node =
    914         &(ft_collector_info_list[unit][collector_id]);
    915 
    916     if (list_node->collector_id != collector_id) {
    917         LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
    918                   (BSL_META_U(unit,
    919                               "FT(unit %d) Info: collector ID does not exist"), unit));
    920         return (BCM_E_NOT_FOUND);
    921     }
    922 
    923     sal_memcpy(&(list_node->collector_info), collector_info,
    924                sizeof(bcm_flowtracker_collector_info_t));
    925 
    926     return BCM_E_NONE;
    927 }
    928 
    929 /*
    930  * Function:
    931  *     _bcm_xgs5_ft_collector_list_collector_get
    932  * Purpose:
    933  *     Get a collector from the collector list.
    934  * Parameters:
    935  *     unit          - (IN) BCM device number
    936  *     collector_id   - (IN) The collector ID
    937  *     collector_info - (OUT) collector information
    938  * Returns:
    939  *     BCM_E_XXX
    940  */
    941 int
    942 _bcm_xgs5_ft_collector_list_collector_get (int unit,
    943                               bcm_flowtracker_collector_t collector_id,
    944                               _bcm_int_ft_collector_info_t *collector_info)
    945 {
    946     _bcm_int_ft_collector_info_t *list_node =
    947         &(ft_collector_info_list[unit][collector_id]);
    948 
    949     if (list_node->collector_id != collector_id) {
    950         LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
    951                   (BSL_META_U(unit,
    952                               "FT(unit %d) Info: collector ID does not exist"), unit));
    953         return (BCM_E_NOT_FOUND);
    954     }
    955 
    956     sal_memcpy(collector_info, list_node, 
    957                 sizeof(_bcm_int_ft_collector_info_t));
    958 
    959 
    960     return BCM_E_NONE;
    961 }
    962 
    963 /*
    964  * Function:
    965  *     _bcm_xgs5_ft_collector_list_destroy
    966  * Purpose:
    967  *     Destroy the collector list.
    968  * Parameters:
    969  *     unit          - (IN) BCM device number
    970  * Returns:
    971  *     BCM_E_XXX
    972  */
    973 int
    974 _bcm_xgs5_ft_collector_list_destroy (int unit)
    975 {
    976     if (ft_collector_info_list[unit] != NULL) {
    977         sal_free(ft_collector_info_list[unit]);
    978     }
    979 
    980     ft_collector_info_list[unit] = NULL;
    981     return BCM_E_NONE;
    982 }
    983 
    984 /*
    985  * Function:
    986  *     _bcm_xgs5_ft_collector_list_create
    987  * Purpose:
    988  *     Create the collector list.
    989  * Parameters:
    990  *     unit          - (IN) BCM device number
    991  * Returns:
    992  *     BCM_E_XXX
    993  */
    994 int
    995 _bcm_xgs5_ft_collector_list_create (int unit)
    996 {
    997     if (ft_collector_info_list[unit] == NULL) {
    998         _BCM_FT_ALLOC(ft_collector_info_list[unit], _bcm_int_ft_collector_info_t,
    999                       sizeof(_bcm_int_ft_collector_info_t) *
   1000                        (BCM_INT_FT_MAX_COLLECTORS + BCM_INT_FT_COLLECTOR_START_ID),
   1001                 "collector list");
   1002 
   1003     }
   1004 
   1005     if (ft_collector_info_list[unit] == NULL) {
   1006         return BCM_E_MEMORY;
   1007     }
   1008     return BCM_E_NONE;
   1009 }
   1010 
   1011 /*******************************************************
   1012  *                                                     *
   1013  *        FTv2 COLLECTOR LIST MANAGEMENT FUNCTIONS     *
   1014  */
   1015 
   1016 /*
   1017  * Function:
   1018  *     _bcm_xgs5_ft_v2_collector_list_collector_add
   1019  * Purpose:
   1020  *     Add a collector to the collector list.
   1021  * Parameters:
   1022  *     unit          - (IN) BCM device number
   1023  *     collector_id  - (IN) The collector ID
   1024  *     coll_int_id   - (IN) Collector internal Id
   1025  * Returns:
   1026  *     BCM_E_XXX
   1027  */
   1028 int
   1029 _bcm_xgs5_ft_v2_collector_list_collector_add(int unit,
   1030                                              bcm_collector_t collector_id,
   1031                                              int coll_int_id)
   1032 {
   1033     _bcm_int_ft_v2_collector_info_t *collector_info =
   1034                              &(ft_v2_collector_info_list[unit][collector_id]);
   1035 
   1036     if (collector_id > BCM_INT_COLLECTOR_COLLECTOR_END_ID) {
   1037         return BCM_E_PARAM;
   1038     }
   1039 
   1040     if (collector_info->int_id != 0) {
   1041         return BCM_E_EXISTS;
   1042     }
   1043 
   1044     collector_info->int_id = coll_int_id;
   1045 
   1046     return (BCM_E_NONE);
   1047 }
   1048 
   1049 /*
   1050  * Function:
   1051  *     _bcm_xgs5_ft_v2_collector_list_collector_delete
   1052  * Purpose:
   1053  *     Delete a collector from the collector list.
   1054  * Parameters:
   1055  *     unit          - (IN) BCM device number
   1056  *     collector_id  - (IN) The collector ID
   1057  * Returns:
   1058  *     BCM_E_XXX
   1059  */
   1060 int
   1061 _bcm_xgs5_ft_v2_collector_list_collector_delete(int unit,
   1062                                                 bcm_collector_t collector_id)
   1063 {
   1064     _bcm_int_ft_v2_collector_info_t *collector_info =
   1065                             &(ft_v2_collector_info_list[unit][collector_id]);
   1066 
   1067     if (collector_id > BCM_INT_COLLECTOR_COLLECTOR_END_ID) {
   1068         return BCM_E_PARAM;
   1069     }
   1070 
   1071     if (collector_info->int_id == 0) {
   1072         return BCM_E_NOT_FOUND;
   1073     }
   1074 
   1075     collector_info->int_id = 0;
   1076 
   1077     return (BCM_E_NONE);
   1078 }
   1079 
   1080 
   1081 /*
   1082  * Function:
   1083  *     _bcm_xgs5_ft_v2_collector_list_collector_get
   1084  * Purpose:
   1085  *     Get a collector from the collector list.
   1086  * Parameters:
   1087  *     unit          - (IN)  BCM device number
   1088  *     collector_id  - (IN)  The collector ID
   1089  *     collint_id    - (OUT) Collector Internal Id
   1090  * Returns:
   1091  *     BCM_E_XXX
   1092  */
   1093 int
   1094 _bcm_xgs5_ft_v2_collector_list_collector_get(int unit,
   1095                                              bcm_collector_t collector_id,
   1096                                              int *coll_int_id)
   1097 {
   1098     _bcm_int_ft_v2_collector_info_t *collector_info =
   1099                             &(ft_v2_collector_info_list[unit][collector_id]);
   1100 
   1101     if (collector_id > BCM_INT_COLLECTOR_COLLECTOR_END_ID) {
   1102         return BCM_E_PARAM;
   1103     }
   1104 
   1105     if (collector_info->int_id == 0) {
   1106         return BCM_E_NOT_FOUND;
   1107     }
   1108 
   1109     *coll_int_id = collector_info->int_id;
   1110 
   1111     return BCM_E_NONE;
   1112 }
   1113 
   1114 
   1115 
   1116 /*
   1117  * Function:
   1118  *     _bcm_xgs5_ft_v2_collector_list_collector_in_use
   1119  * Purpose:
   1120  *     Check if a collector is attached to any flow groups
   1121  * Parameters:
   1122  *     unit           - (IN) BCM device number
   1123  *     collector_id   - (IN) The collector ID
   1124  *     coll_int_id    - (OUT) Internal collector ID
   1125  * Returns:
   1126  *     None
   1127  */
   1128 void
   1129 _bcm_xgs5_ft_v2_collector_list_collector_in_use(int unit,
   1130                                                 bcm_collector_t collector_id,
   1131                                                 int *in_use)
   1132 {
   1133     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   1134     _bcm_int_ft_flow_group_info_t *flow_group_info = NULL;
   1135     int flow_group_id;
   1136 
   1137     *in_use = 0;
   1138     for (flow_group_id = BCM_INT_FT_GROUP_START_ID;
   1139          flow_group_id < (BCM_INT_FT_GROUP_START_ID + ft_info->max_flow_groups);
   1140          flow_group_id++) {
   1141         flow_group_info = &(ft_flow_group_info_list[unit][flow_group_id]);
   1142 
   1143         if (flow_group_info->flow_group_id != flow_group_id) {
   1144             continue;
   1145         }
   1146 
   1147         if (flow_group_info->collector_id == collector_id) {
   1148             *in_use = 1;
   1149             return;
   1150         }
   1151     }
   1152 }
   1153 
   1154 /*
   1155  * Function:
   1156  *     _bcm_xgs5_ft_v2_collector_list_destroy
   1157  * Purpose:
   1158  *     Destroy the collector list.
   1159  * Parameters:
   1160  *     unit          - (IN) BCM device number
   1161  * Returns:
   1162  *     BCM_E_XXX
   1163  */
   1164 int
   1165 _bcm_xgs5_ft_v2_collector_list_destroy(int unit)
   1166 {
   1167     if (ft_v2_collector_info_list[unit] != NULL) {
   1168         sal_free(ft_v2_collector_info_list[unit]);
   1169     }
   1170 
   1171     ft_v2_collector_info_list[unit] = NULL;
   1172     return BCM_E_NONE;
   1173 }
   1174 
   1175 /*
   1176  * Function:
   1177  *     _bcm_xgs5_ft_v2_collector_list_create
   1178  * Purpose:
   1179  *     Destroy the collector list.
   1180  * Parameters:
   1181  *     unit          - (IN) BCM device number
   1182  * Returns:
   1183  *     BCM_E_XXX
   1184  */
   1185 int
   1186 _bcm_xgs5_ft_v2_collector_list_create(int unit)
   1187 {
   1188     if (ft_v2_collector_info_list[unit] == NULL) {
   1189         _BCM_FT_ALLOC(ft_v2_collector_info_list[unit], _bcm_int_ft_v2_collector_info_t,
   1190                       sizeof(_bcm_int_ft_v2_collector_info_t) *
   1191                        (BCM_INT_COLLECTOR_COLLECTOR_START_ID + BCM_INT_COLLECTOR_MAX_COLLECTORS),
   1192                 "collector list");
   1193 
   1194     }
   1195 
   1196     if (ft_v2_collector_info_list[unit] == NULL) {
   1197         return BCM_E_MEMORY;
   1198     }
   1199     return BCM_E_NONE;
   1200 }
   1201 
   1202 /*
   1203  * Function:
   1204  *     _bcm_xgs5_ft_v2_collector_list_export_profile_add
   1205  * Purpose:
   1206  *     Add a export profile to the list.
   1207  * Parameters:
   1208  *     unit                  - (IN) BCM device number
   1209  *     export_profile_id     - (IN) Export profile Id
   1210  *     export_profile_int_id - (IN) Export profile Internal Id
   1211  * Returns:
   1212  *     BCM_E_XXX
   1213  */
   1214 int
   1215 _bcm_xgs5_ft_v2_collector_list_export_profile_add(int unit,
   1216                                                   int export_profile_id,
   1217                                                   int export_profile_int_id)
   1218 {
   1219     _bcm_int_ft_v2_export_profile_info_t *export_profile_info =
   1220                  &(ft_v2_export_profile_info_list[unit][export_profile_id]);
   1221 
   1222     if (export_profile_id > BCM_INT_COLLECTOR_EXPORT_PROFILE_END_ID) {
   1223         return BCM_E_PARAM;
   1224     }
   1225 
   1226     if (export_profile_info->int_id != 0) {
   1227         return BCM_E_EXISTS;
   1228     }
   1229 
   1230     export_profile_info->int_id = export_profile_int_id;
   1231 
   1232     return (BCM_E_NONE);
   1233 }
   1234 
   1235 /*
   1236  * Function:
   1237  *     _bcm_xgs5_ft_v2_collector_list_export_profile_delete
   1238  * Purpose:
   1239  *     Delete an export profile from the list
   1240  * Parameters:
   1241  *     unit              - (IN) BCM device number
   1242  *     export_profile_id - (IN) export_profile ID
   1243  * Returns:
   1244  *     BCM_E_XXX
   1245  */
   1246 int
   1247 _bcm_xgs5_ft_v2_collector_list_export_profile_delete(int unit,
   1248                                                      int export_profile_id)
   1249 {
   1250     _bcm_int_ft_v2_export_profile_info_t *export_profile_info =
   1251                  &(ft_v2_export_profile_info_list[unit][export_profile_id]);
   1252 
   1253     if (export_profile_id > BCM_INT_COLLECTOR_EXPORT_PROFILE_END_ID) {
   1254         return BCM_E_PARAM;
   1255     }
   1256 
   1257     if (export_profile_info->int_id == 0) {
   1258         return BCM_E_NOT_FOUND;
   1259     }
   1260 
   1261     export_profile_info->int_id = 0;
   1262 
   1263     return (BCM_E_NONE);
   1264 }
   1265 
   1266 
   1267 /*
   1268  * Function:
   1269  *     _bcm_xgs5_ft_v2_collector_list_export_profile_get
   1270  * Purpose:
   1271  *     Get a collector from the collector list.
   1272  * Parameters:
   1273  *     unit                   - (IN)  BCM device number
   1274  *     export_profile_id      - (IN)  export_profile ID
   1275  *     export_profile_int_id  - (IN)  export_profile internal ID
   1276  * Returns:
   1277  *     BCM_E_XXX
   1278  */
   1279 int
   1280 _bcm_xgs5_ft_v2_collector_list_export_profile_get(int unit,
   1281                                                   int export_profile_id,
   1282                                                   int *export_profile_int_id)
   1283 {
   1284     _bcm_int_ft_v2_export_profile_info_t *export_profile_info =
   1285                  &(ft_v2_export_profile_info_list[unit][export_profile_id]);
   1286 
   1287     if (export_profile_id > BCM_INT_COLLECTOR_EXPORT_PROFILE_END_ID) {
   1288         return BCM_E_PARAM;
   1289     }
   1290 
   1291     if (export_profile_info->int_id == 0) {
   1292         return BCM_E_NOT_FOUND;
   1293     }
   1294 
   1295     *export_profile_int_id = export_profile_info->int_id;
   1296 
   1297     return BCM_E_NONE;
   1298 }
   1299 
   1300 
   1301 
   1302 /*
   1303  * Function:
   1304  *     _bcm_xgs5_ft_v2_collector_list_export_profile_in_use
   1305  * Purpose:
   1306  *     Check if a export_profile is attached to any flow groups
   1307  * Parameters:
   1308  *     unit              - (IN)  BCM device number
   1309  *     export_profile_id - (IN)  export_profile ID
   1310  *     in_use            - (OUT) Indicates if the export profile is in use
   1311  * Returns:
   1312  *     None
   1313  */
   1314 void
   1315 _bcm_xgs5_ft_v2_collector_list_export_profile_in_use(int unit,
   1316                                                      int export_profile_id,
   1317                                                      int *in_use)
   1318 {
   1319     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   1320     _bcm_int_ft_flow_group_info_t *flow_group_info = NULL;
   1321     int flow_group_id;
   1322 
   1323     *in_use = 0;
   1324     for (flow_group_id = BCM_INT_FT_GROUP_START_ID;
   1325          flow_group_id < (BCM_INT_FT_GROUP_START_ID + ft_info->max_flow_groups);
   1326          flow_group_id++) {
   1327         flow_group_info = &(ft_flow_group_info_list[unit][flow_group_id]);
   1328 
   1329         if (flow_group_info->flow_group_id != flow_group_id) {
   1330             continue;
   1331         }
   1332 
   1333         if (flow_group_info->export_profile_id == export_profile_id) {
   1334             *in_use = 1;
   1335             return;
   1336         }
   1337     }
   1338 }
   1339 
   1340 
   1341 /*
   1342  * Function:
   1343  *     _bcm_xgs5_ft_v2_export_profile_list_destroy
   1344  * Purpose:
   1345  *     Destroy the export_profile list.
   1346  * Parameters:
   1347  *     unit          - (IN) BCM device number
   1348  * Returns:
   1349  *     BCM_E_XXX
   1350  */
   1351 int
   1352 _bcm_xgs5_ft_v2_collector_list_export_profile_destroy(int unit)
   1353 {
   1354     if (ft_v2_export_profile_info_list[unit] != NULL) {
   1355         sal_free(ft_v2_export_profile_info_list[unit]);
   1356     }
   1357 
   1358     ft_v2_export_profile_info_list[unit] = NULL;
   1359     return BCM_E_NONE;
   1360 }
   1361 
   1362 /*
   1363  * Function:
   1364  *     _bcm_xgs5_ft_v2_export_profile_list_create
   1365  * Purpose:
   1366  *     Destroy the export_profile list.
   1367  * Parameters:
   1368  *     unit          - (IN) BCM device number
   1369  * Returns:
   1370  *     BCM_E_XXX
   1371  */
   1372 int
   1373 _bcm_xgs5_ft_v2_collector_list_export_profile_create(int unit)
   1374 {
   1375     if (ft_v2_export_profile_info_list[unit] == NULL) {
   1376         _BCM_FT_ALLOC(ft_v2_export_profile_info_list[unit], _bcm_int_ft_v2_export_profile_info_t,
   1377                       sizeof(_bcm_int_ft_v2_export_profile_info_t) *
   1378                        (BCM_INT_COLLECTOR_EXPORT_PROFILE_START_ID +
   1379                                            BCM_INT_COLLECTOR_MAX_EXPORT_PROFILES),
   1380                 "export_profile list");
   1381 
   1382     }
   1383 
   1384     if (ft_v2_export_profile_info_list[unit] == NULL) {
   1385         return BCM_E_MEMORY;
   1386     }
   1387     return BCM_E_NONE;
   1388 }
   1389 
   1390 /******************************************************
   1391 *                                                     *
   1392 *        FLOW GROUP LIST MANAGEMENT FUNCTIONS         *
   1393  */
   1394 
   1395 /*
   1396  * Function:
   1397  *     _bcm_xgs5_ft_flow_group_list_flow_group_add
   1398  * Purpose:
   1399  *     Add a flow_group to the flow_group list.
   1400  * Parameters:
   1401  *     unit          - (IN) BCM device number
   1402  *     flow_group_id   - (IN) The flow_group ID
   1403  * Returns:
   1404  *     BCM_E_XXX
   1405  */
   1406 int
   1407 _bcm_xgs5_ft_flow_group_list_flow_group_add(int unit,
   1408                                             bcm_flowtracker_group_t flow_group_id)
   1409 {
   1410     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   1411     _bcm_int_ft_flow_group_info_t *flow_group_info_list_node =
   1412         &(ft_flow_group_info_list[unit][flow_group_id]);
   1413 
   1414     if (flow_group_info_list_node->flow_group_id != 0) {
   1415         /* Not free */
   1416         return BCM_E_EXISTS;
   1417     }
   1418 
   1419     flow_group_info_list_node->flow_group_id = flow_group_id;
   1420     if (ft_info->cfg_mode >= SHR_FT_CFG_MODE_V2) {
   1421         flow_group_info_list_node->collector_id =
   1422                                  BCM_INT_COLLECTOR_INVALID_COLLECTOR_ID;
   1423         flow_group_info_list_node->export_profile_id =
   1424                                 BCM_INT_COLLECTOR_INVALID_EXPORT_PROFILE_ID;
   1425     }
   1426 
   1427     LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
   1428             (BSL_META_U(unit,
   1429                         "FT(unit %d) Info: %s" 
   1430                         " (Flow_group=0x%x).\n"), unit, __FUNCTION__,
   1431                          flow_group_id));
   1432     return (BCM_E_NONE);
   1433 }
   1434 
   1435 /*
   1436  * Function:
   1437  *     _bcm_xgs5_ft_flow_group_list_flow_group_delete
   1438  * Purpose:
   1439  *     Delete a flow_group from the flow_group list.
   1440  * Parameters:
   1441  *     unit          - (IN) BCM device number
   1442  *     flow_group_id   - (IN) The flow_group ID
   1443  * Returns:
   1444  *     BCM_E_XXX
   1445  */
   1446 int
   1447 _bcm_xgs5_ft_flow_group_list_flow_group_delete (int unit,
   1448                               bcm_flowtracker_group_t flow_group_id)
   1449 {
   1450     _bcm_int_ft_flow_group_info_t *flow_group_info_list_node =
   1451         &(ft_flow_group_info_list[unit][flow_group_id]);
   1452 
   1453     if (flow_group_info_list_node->flow_group_id != flow_group_id) {
   1454         /* Not found */
   1455         LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
   1456                   (BSL_META_U(unit,
   1457                               "FT(unit %d) Info: flow group ID does not exist"), unit));
   1458         return BCM_E_NOT_FOUND;
   1459     }
   1460 
   1461     sal_memset(flow_group_info_list_node, 0,
   1462                                  sizeof(_bcm_int_ft_flow_group_info_t));
   1463 
   1464     return (BCM_E_NONE);
   1465 }
   1466 
   1467 /*
   1468  * Function:
   1469  *     _bcm_xgs5_ft_flow_group_list_flow_group_modify
   1470  * Purpose:
   1471  *     Modfiy a flow_group in the flow_group list.
   1472  * Parameters:
   1473  *     unit          - (IN) BCM device number
   1474  *     flow_group_id   - (IN) The flow_group ID
   1475  *     flow_group_info - (IN) flow_group informatin.
   1476  * Returns:
   1477  *     BCM_E_XXX
   1478  */
   1479 int
   1480 _bcm_xgs5_ft_flow_group_list_flow_group_modify(
   1481                            int unit,
   1482                            bcm_flowtracker_group_t flow_group_id,
   1483                            _bcm_int_ft_flow_group_info_t *flow_group_int_info)
   1484 {
   1485     _bcm_int_ft_flow_group_info_t *list_node =
   1486         &(ft_flow_group_info_list[unit][flow_group_id]);
   1487 
   1488     if (list_node->flow_group_id != flow_group_id) {
   1489         /* Not found */
   1490         LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
   1491                   (BSL_META_U(unit,
   1492                               "FT(unit %d) Info: flow_group ID does not exist"), unit));
   1493         return (BCM_E_NOT_FOUND);
   1494     }
   1495 
   1496     sal_memcpy(list_node, flow_group_int_info, 
   1497             sizeof(_bcm_int_ft_flow_group_info_t));
   1498 
   1499 
   1500     return BCM_E_NONE;
   1501 }
   1502 
   1503 /*
   1504  * Function:
   1505  *     _bcm_xgs5_ft_flow_group_list_flow_group_get
   1506  * Purpose:
   1507  *     Get a flow_group from the flow_group list.
   1508  * Parameters:
   1509  *     unit          - (IN) BCM device number
   1510  *     flow_group_id   - (IN) The flow_group ID
   1511  *     flow_group_int_info - (OUT) flow_group information
   1512  * Returns:
   1513  *     BCM_E_XXX
   1514  */
   1515 int
   1516 _bcm_xgs5_ft_flow_group_list_flow_group_get (
   1517                               int unit,
   1518                               bcm_flowtracker_group_t flow_group_id,
   1519                               _bcm_int_ft_flow_group_info_t *flow_group_int_info)
   1520 {
   1521     _bcm_int_ft_flow_group_info_t *list_node =
   1522         &(ft_flow_group_info_list[unit][flow_group_id]);
   1523 
   1524     if (list_node->flow_group_id != flow_group_id) {
   1525         /* Not found */
   1526         LOG_DEBUG(BSL_LS_BCM_FLOWTRACKER,
   1527                   (BSL_META_U(unit,
   1528                               "FT(unit %d) Info: flow_group ID does not exist"), unit));
   1529         return (BCM_E_NOT_FOUND);
   1530     }
   1531     sal_memcpy(flow_group_int_info, list_node,
   1532                sizeof(_bcm_int_ft_flow_group_info_t));
   1533 
   1534     return BCM_E_NONE;
   1535 }
   1536 
   1537 /*
   1538  * Function:
   1539  *    _bcm_xgs5_ft_flow_group_list_get_all_ids 
   1540  * Purpose:
   1541  *     Get list of flow group ids configured.
   1542  * Parameters:
   1543  *     unit          - (IN) BCM device number
   1544  *     flow_group_id_list   - (OUT) The list of flow_group IDs.
   1545  *                            The caller is expected to have allocated it
   1546  *                            for max number of flow groups.
   1547  *     num_flow_groups      - (OUT) The number of flow groups configured.
   1548  * Returns:
   1549  *     BCM_E_XXX
   1550  */
   1551 int
   1552 _bcm_xgs5_ft_flow_group_list_get_all_ids(
   1553             int unit,
   1554             bcm_flowtracker_group_t *flow_group_id_list,
   1555             int *num_flow_groups)
   1556 {
   1557     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   1558     _bcm_int_ft_flow_group_info_t *list_node = NULL;
   1559     int flow_group_id = 0, cnt = 0;
   1560 
   1561     for (flow_group_id = BCM_INT_FT_GROUP_START_ID;
   1562          flow_group_id < (BCM_INT_FT_GROUP_START_ID + ft_info->max_flow_groups);
   1563          flow_group_id++) {
   1564         list_node = &(ft_flow_group_info_list[unit][flow_group_id]);
   1565         /* Non zero flow_group_id indicates configured flow groups.*/
   1566         if (list_node->flow_group_id != 0) {
   1567             flow_group_id_list[cnt] = list_node->flow_group_id;
   1568             cnt++;
   1569         }
   1570     }
   1571     *num_flow_groups = cnt;
   1572     return BCM_E_NONE;
   1573 }
   1574 
   1575 /*
   1576  * Function:
   1577  *    _bcm_xgs5_ft_flow_group_list_collector_in_use_check 
   1578  * Purpose:
   1579  *     Find if any flow group in the flow_group_list uses the passed collector.
   1580  * Parameters:
   1581  *     unit          - (IN) BCM device number
   1582  *     collector_id   - (IN) collector_id
   1583  * Returns:
   1584  *     BCM_E_EXISTS - If collector_id is used by any of the flow groups.
   1585  *     BCM_E_NONE   - otherwise.
   1586  */
   1587 int
   1588 _bcm_xgs5_ft_flow_group_list_collector_in_use_check(int unit, 
   1589                     bcm_flowtracker_collector_t collector_id)
   1590 {
   1591     _bcm_int_ft_flow_group_info_t *list_node = NULL;
   1592     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   1593     int flow_group_id;
   1594 
   1595     for (flow_group_id = BCM_INT_FT_GROUP_START_ID;
   1596          flow_group_id < (BCM_INT_FT_GROUP_START_ID + ft_info->max_flow_groups);
   1597          flow_group_id++) { 
   1598         list_node = &(ft_flow_group_info_list[unit][flow_group_id]);
   1599         /* Valid flow group ids have non zero flow group ID. */
   1600         if (list_node->flow_group_id != 0) {
   1601             if (list_node->collector_id == collector_id) {
   1602                 return BCM_E_EXISTS;
   1603             }
   1604         }
   1605     }
   1606     return BCM_E_NONE;
   1607 }
   1608 
   1609 /*
   1610  * Function:
   1611  *    _bcm_xgs5_ft_flow_group_list_template_in_use_check 
   1612  * Purpose:
   1613  *     Find if any flow group in the flow_group_list uses the passed template.
   1614  * Parameters:
   1615  *     unit          - (IN) BCM device number
   1616  *     template_id   - (IN) template_id
   1617  * Returns:
   1618  *     BCM_E_EXISTS - If template_id is used by any of the flow groups.
   1619  *     BCM_E_NONE   - otherwise.
   1620  */
   1621 int
   1622 _bcm_xgs5_ft_flow_group_list_template_in_use_check(int unit, 
   1623                     bcm_flowtracker_export_template_t template_id)
   1624 {
   1625     _bcm_int_ft_flow_group_info_t *list_node = NULL;
   1626     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   1627     int flow_group_id;
   1628 
   1629     for (flow_group_id = BCM_INT_FT_GROUP_START_ID;
   1630          flow_group_id < (BCM_INT_FT_GROUP_START_ID + ft_info->max_flow_groups);
   1631          flow_group_id++) { 
   1632         list_node = &(ft_flow_group_info_list[unit][flow_group_id]);
   1633         /* Valid flow group ids have non zero flow group ID. */
   1634         if (list_node->flow_group_id != 0) {
   1635             if (list_node->template_id == template_id) {
   1636                 return BCM_E_EXISTS;
   1637             }
   1638         }
   1639     }
   1640     return BCM_E_NONE;
   1641 }
   1642 
   1643 /*
   1644  * Function:
   1645  *    _bcm_xgs5_ft_flow_group_list_elph_profile_in_use_check
   1646  * Purpose:
   1647  *     Find if any flow group in the flow_group_list uses the elephant profile
   1648  * Parameters:
   1649  *     unit         - (IN) BCM device number
   1650  *     profile_id   - (IN) profile id
   1651  * Returns:
   1652  *     BCM_E_EXISTS - If elephant profile id is used by any of the flow groups.
   1653  *     BCM_E_NONE   - otherwise.
   1654  */
   1655 int
   1656 _bcm_xgs5_ft_flow_group_list_elph_profile_in_use_check(int unit,
   1657                                     bcm_flowtracker_export_template_t profile_id)
   1658 {
   1659     _bcm_int_ft_flow_group_info_t *list_node = NULL;
   1660     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   1661     int flow_group_id;
   1662 
   1663     for (flow_group_id = BCM_INT_FT_GROUP_START_ID;
   1664          flow_group_id < (BCM_INT_FT_GROUP_START_ID + ft_info->max_flow_groups);
   1665          flow_group_id++) {
   1666         list_node = &(ft_flow_group_info_list[unit][flow_group_id]);
   1667         /* Valid flow group ids have non zero flow group ID. */
   1668         if (list_node->flow_group_id != 0) {
   1669             if (list_node->elph_profile_id == profile_id) {
   1670                 return BCM_E_EXISTS;
   1671             }
   1672         }
   1673     }
   1674     return BCM_E_NONE;
   1675 }
   1676 
   1677 /*
   1678  * Function:
   1679  *     _bcm_xgs5_ft_flow_group_list_destroy
   1680  * Purpose:
   1681  *     Destroy the flow_group list.
   1682  * Parameters:
   1683  *     unit          - (IN) BCM device number
   1684  * Returns:
   1685  *     BCM_E_XXX
   1686  */
   1687 int
   1688 _bcm_xgs5_ft_flow_group_list_destroy (int unit)
   1689 {
   1690     _bcm_int_ft_flow_group_info_t *list_node = NULL;
   1691     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   1692     int flow_group_id;
   1693 
   1694     if (ft_flow_group_info_list[unit] != NULL) {
   1695         for (flow_group_id = BCM_INT_FT_GROUP_START_ID;
   1696              flow_group_id < (BCM_INT_FT_GROUP_START_ID + ft_info->max_flow_groups);
   1697              flow_group_id++) {
   1698             list_node = &(ft_flow_group_info_list[unit][flow_group_id]);
   1699             if (list_node->action_list != NULL) {
   1700                 sal_free(list_node->action_list);
   1701             }
   1702         }
   1703         sal_free(ft_flow_group_info_list[unit]);
   1704     }
   1705 
   1706     ft_flow_group_info_list[unit] = NULL;
   1707 
   1708     return BCM_E_NONE;
   1709 }
   1710 
   1711 
   1712 /*
   1713  * Function:
   1714  *     _bcm_xgs5_ft_flow_group_list_create
   1715  * Purpose:
   1716  *     Create the flow_group list.
   1717  * Parameters:
   1718  *     unit          - (IN) BCM device number
   1719  * Returns:
   1720  *     BCM_E_XXX
   1721  */
   1722 int
   1723 _bcm_xgs5_ft_flow_group_list_create (int unit)
   1724 {
   1725     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   1726 
   1727     if (ft_flow_group_info_list[unit] == NULL) {
   1728         _BCM_FT_ALLOC(ft_flow_group_info_list[unit],
   1729                       _bcm_int_ft_flow_group_info_t,
   1730                       sizeof(_bcm_int_ft_flow_group_info_t) *
   1731                       (ft_info->max_flow_groups + BCM_INT_FT_GROUP_START_ID),
   1732                       "Flow_group list");
   1733     }
   1734 
   1735     if (ft_flow_group_info_list[unit] == NULL) {
   1736         return BCM_E_MEMORY;
   1737     }
   1738 
   1739     return BCM_E_NONE;
   1740 }
   1741 
   1742 /*******************************************************
   1743  *                                                     *
   1744  *                    Elephant APIs                    *
   1745  */
   1746 
   1747 /*
   1748  * Function:
   1749  *     _bcm_xgs5_ft_elph_profile_list_add
   1750  * Purpose:
   1751  *     Add a elephant profile to the list.
   1752  * Parameters:
   1753  *     unit         - (IN) BCM device number
   1754  *     id           - (IN) Elephant profile ID
   1755  *     profile      - (IN) Elephant profile
   1756  * Returns:
   1757  *     BCM_E_XXX
   1758  */
   1759 int
   1760 _bcm_xgs5_ft_elph_profile_list_add(int unit,
   1761                                    bcm_flowtracker_elephant_profile_t id,
   1762                                    bcm_flowtracker_elephant_profile_info_t *profile)
   1763 {
   1764     _bcm_int_ft_elph_profile_info_t *elph_profile_int_info =
   1765                                            &(ft_elph_profile_info_list[unit][id]);
   1766 
   1767     elph_profile_int_info->id = id;
   1768 
   1769     sal_memcpy(&(elph_profile_int_info->profile), profile,
   1770                sizeof(bcm_flowtracker_elephant_profile_info_t));
   1771 
   1772     return BCM_E_NONE;
   1773 }
   1774 
   1775 /*
   1776  * Function:
   1777  *     _bcm_xgs5_ft_elph_profile_list_get
   1778  * Purpose:
   1779  *     Get a elephant profile from the list.
   1780  * Parameters:
   1781  *     unit         - (IN)  BCM device number
   1782  *     id           - (IN)  Elephant profile ID
   1783  *     profile      - (OUT) Elephant profile
   1784  * Returns:
   1785  *     BCM_E_XXX
   1786  */
   1787 int
   1788 _bcm_xgs5_ft_elph_profile_list_get(int unit,
   1789                                    bcm_flowtracker_elephant_profile_t id,
   1790                                    _bcm_int_ft_elph_profile_info_t *profile)
   1791 {
   1792     _bcm_int_ft_elph_profile_info_t *list_node =
   1793                                &(ft_elph_profile_info_list[unit][id]);
   1794 
   1795     if (list_node->id != id) {
   1796         return BCM_E_NOT_FOUND;
   1797     }
   1798     sal_memcpy(profile, list_node, sizeof(_bcm_int_ft_elph_profile_info_t));
   1799 
   1800     return BCM_E_NONE;
   1801 }
   1802 
   1803 /*
   1804  * Function:
   1805  *     _bcm_xgs5_ft_elph_profile_list_delete
   1806  * Purpose:
   1807  *     Add a elephant profile to the list.
   1808  * Parameters:
   1809  *     unit         - (IN) BCM device number
   1810  *     id           - (IN) Elephant profile ID
   1811  * Returns:
   1812  *     BCM_E_XXX
   1813  */
   1814 int
   1815 _bcm_xgs5_ft_elph_profile_list_delete(int unit,
   1816                                       bcm_flowtracker_elephant_profile_t id)
   1817 {
   1818     _bcm_int_ft_elph_profile_info_t *profile_int_info =
   1819                                            &(ft_elph_profile_info_list[unit][id]);
   1820 
   1821     if (profile_int_info->id != id) {
   1822         return BCM_E_NOT_FOUND;
   1823     }
   1824 
   1825     sal_memset(profile_int_info, 0, sizeof(_bcm_int_ft_elph_profile_info_t));
   1826 
   1827     return BCM_E_NONE;
   1828 }
   1829 
   1830 /*
   1831  * Function:
   1832  *     _bcm_xgs5_ft_elph_profile_list_create
   1833  * Purpose:
   1834  *     Create the elephant profile list.
   1835  * Parameters:
   1836  *     unit          - (IN) BCM device number
   1837  * Returns:
   1838  *     BCM_E_XXX
   1839  */
   1840 int
   1841 _bcm_xgs5_ft_elph_profile_list_create(int unit)
   1842 {
   1843     if (ft_elph_profile_info_list[unit] == NULL) {
   1844         _BCM_FT_ALLOC(ft_elph_profile_info_list[unit], _bcm_int_ft_elph_profile_info_t,
   1845                       sizeof(_bcm_int_ft_elph_profile_info_t) *
   1846                       (BCM_INT_FT_ELPH_PROFILE_START_ID + BCM_INT_FT_MAX_ELEPHANT_PROFILES),
   1847                       "Elephant profile list");
   1848     }
   1849 
   1850     if (ft_elph_profile_info_list[unit] == NULL) {
   1851         return BCM_E_MEMORY;
   1852     }
   1853 
   1854     return BCM_E_NONE;
   1855 }
   1856 
   1857 /*
   1858  * Function:
   1859  *     _bcm_xgs5_ft_elph_profile_destroy
   1860  * Purpose:
   1861  *     Destroy the elephant profile list.
   1862  * Parameters:
   1863  *     unit          - (IN) BCM device number
   1864  * Returns:
   1865  *     BCM_E_XXX
   1866  */
   1867 int
   1868 _bcm_xgs5_ft_elph_profile_list_destroy(int unit)
   1869 {
   1870     if (ft_elph_profile_info_list[unit] != NULL) {
   1871         sal_free(ft_elph_profile_info_list[unit]);
   1872     }
   1873     ft_elph_profile_info_list[unit] = NULL;
   1874     return BCM_E_NONE;
   1875 }
   1876 
   1877 /******************************************************
   1878 *                                                     *
   1879 *        FLOWTRACKER EMB APP MSGING FUNCTIONS         *
   1880  */
   1881 
   1882 /*
   1883  * Function:
   1884  *      _bcm_xgs5_ft_convert_uc_error
   1885  * Purpose:
   1886  *      Converts uController error code to corresponding BCM error code.
   1887  * Parameters:
   1888  *      uc_rv  - (IN) uController error code to convert.
   1889  * Returns:
   1890  *      BCM_E_XXX   - BCM error code.
   1891  * Notes:
   1892  */
   1893 STATIC int
   1894 _bcm_xgs5_ft_convert_uc_error(uint32 uc_rv)
   1895 {
   1896     int rv = BCM_E_NONE;
   1897 
   1898     switch(uc_rv) {
   1899     case SHR_FT_UC_E_NONE:
   1900         rv = BCM_E_NONE;
   1901         break;
   1902     case SHR_FT_UC_E_INTERNAL:
   1903         rv = BCM_E_INTERNAL;
   1904         break;
   1905     case SHR_FT_UC_E_MEMORY:
   1906         rv = BCM_E_MEMORY;
   1907         break;
   1908     case SHR_FT_UC_E_UNIT:
   1909         rv = BCM_E_UNIT;
   1910         break;
   1911     case SHR_FT_UC_E_PARAM:
   1912         rv = BCM_E_PARAM;
   1913         break;
   1914     case SHR_FT_UC_E_EMPTY:
   1915         rv = BCM_E_EMPTY;
   1916         break;
   1917     case SHR_FT_UC_E_FULL:
   1918         rv = BCM_E_FULL;
   1919         break;
   1920     case SHR_FT_UC_E_NOT_FOUND:
   1921         rv = BCM_E_NOT_FOUND;
   1922         break;
   1923     case SHR_FT_UC_E_EXISTS:
   1924         rv = BCM_E_EXISTS;
   1925         break;
   1926     case SHR_FT_UC_E_TIMEOUT:
   1927         rv = BCM_E_TIMEOUT;
   1928         break;
   1929     case SHR_FT_UC_E_BUSY:
   1930         rv = BCM_E_BUSY;
   1931         break;
   1932     case SHR_FT_UC_E_FAIL:
   1933         rv = BCM_E_FAIL;
   1934         break;
   1935     case SHR_FT_UC_E_DISABLED:
   1936         rv = BCM_E_DISABLED;
   1937         break;
   1938     case SHR_FT_UC_E_BADID:
   1939         rv = BCM_E_BADID;
   1940         break;
   1941     case SHR_FT_UC_E_RESOURCE:
   1942         rv = BCM_E_RESOURCE;
   1943         break;
   1944     case SHR_FT_UC_E_CONFIG:
   1945         rv = BCM_E_CONFIG;
   1946         break;
   1947     case SHR_FT_UC_E_UNAVAIL:
   1948         rv = BCM_E_UNAVAIL;
   1949         break;
   1950     case SHR_FT_UC_E_INIT:
   1951         rv = BCM_E_INIT;
   1952         break;
   1953     case SHR_FT_UC_E_PORT:
   1954         rv = BCM_E_PORT;
   1955         break;
   1956     default:
   1957         rv = BCM_E_INTERNAL;
   1958         break;
   1959     }
   1960 
   1961     return rv;
   1962 }
   1963 
   1964 STATIC int
   1965 _bcm_xgs5_ft_msg_send_receive(int unit, uint8 s_subclass,
   1966                                uint16 s_len, uint32 s_data,
   1967                                uint8 r_subclass, uint16 *r_len,
   1968                                sal_usecs_t timeout)
   1969 {
   1970     int rv;
   1971     mos_msg_data_t send, reply;
   1972     uint32 uc_rv;
   1973     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   1974     uint8 *dma_buffer;
   1975     int dma_buffer_len;
   1976 
   1977 
   1978     dma_buffer = ft_info->dma_buffer;
   1979     dma_buffer_len = ft_info->dma_buffer_len;
   1980 
   1981     sal_memset(&send, 0, sizeof(send));
   1982     sal_memset(&reply, 0, sizeof(reply));
   1983     send.s.mclass = MOS_MSG_CLASS_FT;
   1984     send.s.subclass = s_subclass;
   1985     send.s.len = bcm_htons(s_len);
   1986 
   1987     /*
   1988      * Set 'data' to DMA buffer address if a DMA operation is
   1989      * required for send or receive.
   1990      */
   1991     if (MOS_MSG_DMA_MSG(s_subclass) ||
   1992         MOS_MSG_DMA_MSG(r_subclass)) {
   1993         send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer));
   1994     } else {
   1995         send.s.data = bcm_htonl(s_data);
   1996     }
   1997 
   1998     /* Flush DMA memory */
   1999     if (MOS_MSG_DMA_MSG(s_subclass)) {
   2000         soc_cm_sflush(unit, dma_buffer, s_len);
   2001     }
   2002 
   2003     /* Invalidate DMA memory to read */
   2004     if (MOS_MSG_DMA_MSG(r_subclass)) {
   2005         soc_cm_sinval(unit, dma_buffer, dma_buffer_len);
   2006     }
   2007 
   2008     rv = soc_cmic_uc_msg_send_receive(unit, 0,
   2009                                       &send, &reply,
   2010                                       timeout);
   2011     if (rv != SOC_E_NONE){
   2012         return BCM_E_INTERNAL;
   2013     }
   2014 
   2015     /* Convert FT uController error code to BCM */
   2016     uc_rv  = bcm_ntohl(reply.s.data);
   2017     rv     = _bcm_xgs5_ft_convert_uc_error(uc_rv);
   2018 
   2019     *r_len = bcm_ntohs(reply.s.len);
   2020 
   2021     /*Check reply class and subclass*/
   2022     if((rv == SOC_E_NONE) && ((reply.s.mclass != MOS_MSG_CLASS_FT) ||
   2023         (reply.s.subclass != r_subclass)))
   2024     {
   2025         return BCM_E_INTERNAL;
   2026     }
   2027     return rv;
   2028 }
   2029 
   2030 /*
   2031  * Function:
   2032  *      _bcm_xgs5_ft_eapp_send_features_exchange_msg
   2033  * Purpose:
   2034  *      Exchange features with the EApp
   2035  * Parameters:
   2036  *      unit          - (IN)  BCM device number
   2037  * Returns:
   2038  *      BCM_E_XXX   - BCM error code.
   2039  */
   2040 STATIC int _bcm_xgs5_ft_eapp_send_features_exchange_msg(int unit)
   2041 {
   2042     shr_ft_msg_ctrl_sdk_features_t send_msg;
   2043     shr_ft_msg_ctrl_uc_features_t  rcv_msg;
   2044     uint8 *buffer_req = NULL, *buffer_ptr = NULL;
   2045     uint16 buffer_len = 0, reply_len = 0;
   2046     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   2047     int rv;
   2048 
   2049     sal_memset(&send_msg, 0, sizeof(send_msg));
   2050     sal_memset(&rcv_msg, 0, sizeof(rcv_msg));
   2051 
   2052     /* Populate the SDK features */
   2053     send_msg.cfg_mode = ft_info->cfg_mode;
   2054 
   2055     /* Exchange supported features with the FW */
   2056     buffer_req = ft_info->dma_buffer;
   2057     buffer_ptr = shr_ft_msg_ctrl_sdk_features_pack(buffer_req, &send_msg);
   2058     buffer_len = buffer_ptr - buffer_req;
   2059 
   2060     rv = _bcm_xgs5_ft_msg_send_receive(unit,
   2061                                        MOS_MSG_SUBCLASS_FT_FEATURES_EXCHANGE,
   2062                                        buffer_len, 0,
   2063                                        MOS_MSG_SUBCLASS_FT_FEATURES_EXCHANGE_REPLY,
   2064                                        &reply_len,
   2065                                        SHR_FT_MAX_UC_MSG_TIMEOUT);
   2066 
   2067     if (rv == BCM_E_UNAVAIL) {
   2068         /* Older FW not supporting this message, assume default feature support */
   2069         ft_info->uc_features = (SHR_FT_UC_FEATURE_IPFIX_EXPORT |
   2070                                 SHR_FT_UC_FEATURE_ELPH);
   2071         if (ft_info->cfg_mode != SHR_FT_CFG_MODE_V1) {
   2072             /* Only FTv1 is supported when working with older FW */
   2073             return BCM_E_CONFIG;
   2074         }
   2075         return BCM_E_NONE;
   2076     } else if (rv != BCM_E_NONE) {
   2077         return rv;
   2078     }
   2079 
   2080     buffer_req = ft_info->dma_buffer;
   2081     buffer_ptr = shr_ft_msg_ctrl_uc_features_unpack(buffer_req, &rcv_msg);
   2082     buffer_len = buffer_ptr - buffer_req;
   2083 
   2084     if (buffer_len != reply_len) {
   2085         return BCM_E_INTERNAL;
   2086     }
   2087 
   2088     /* Check if soc properties configured aligns with the app features */
   2089     if (ft_info->elph_mode && !(rcv_msg.features & SHR_FT_UC_FEATURE_ELPH)) {
   2090         return BCM_E_CONFIG;
   2091     }
   2092 
   2093     ft_info->uc_features = rcv_msg.features;
   2094 
   2095     return BCM_E_NONE;
   2096 }
   2097 
   2098 int _bcm_xgs5_ft_eapp_send_ctrl_init_msg (int unit) 
   2099 {
   2100     shr_ft_msg_ctrl_init_t ctrl_init_msg;
   2101     uint8 *buffer_req = NULL, *buffer_ptr = NULL;
   2102     int i = 0, pool;
   2103     uint16 buffer_len = 0, reply_len = 0;
   2104     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   2105 
   2106     
   2107     if (soc_feature(unit, soc_feature_mv2_dummy_flowtracker)) {
   2108         return BCM_E_NONE;
   2109     }
   2110 
   2111     sal_memset(&ctrl_init_msg, 0, sizeof(ctrl_init_msg));
   2112 
   2113     ctrl_init_msg.max_groups = ft_info->max_flow_groups;
   2114     ctrl_init_msg.num_pipes = ft_info->num_pipes; 
   2115     for (i = 0; i < ctrl_init_msg.num_pipes; i++) {
   2116         ctrl_init_msg.pipe[i].max_flows = ft_info->pipe_info[i].max_flows;
   2117         ctrl_init_msg.pipe[i].num_ctr_pools = ft_info->pipe_info[i].num_ctr_pools;
   2118         for (pool = 0; pool < ctrl_init_msg.pipe[i].num_ctr_pools; pool++) {
   2119             ctrl_init_msg.pipe[i].ctr_pools[pool] = 
   2120                 ft_info->pipe_info[i].ctr_pools[pool];
   2121             ctrl_init_msg.pipe[i].ctr_pool_size[pool] = 
   2122                         ft_info->pipe_info[i].ctr_pool_size[pool];
   2123         }
   2124     }
   2125     ctrl_init_msg.rx_channel = BCM_INT_FT_EAPP_RX_CHANNEL;
   2126     ctrl_init_msg.max_export_pkt_length = ft_info->max_export_pkt_length;
   2127     ctrl_init_msg.cur_time_secs = sal_time();
   2128 
   2129     /* Timer intervals */
   2130     ctrl_init_msg.export_interval_msecs = ft_info->export_interval;
   2131     ctrl_init_msg.scan_interval_usecs   = ft_info->scan_interval_usecs;
   2132     ctrl_init_msg.age_timer_tick_msecs  = BCM_INT_FT_AGING_INTERVAL_STEP_MSECS;
   2133 
   2134     /* Initialization flags */
   2135     if (ft_info->flags & BCM_INT_FT_INFO_FLAGS_FLOW_START_TS) {
   2136         ctrl_init_msg.flags |= SHR_FT_MSG_INIT_FLAGS_FLOW_START_TS;
   2137     }
   2138     if (ft_info->elph_mode) {
   2139         ctrl_init_msg.flags |= SHR_FT_MSG_INIT_FLAGS_ELEPHANT;
   2140         ctrl_init_msg.num_elph_profiles = BCM_INT_FT_MAX_ELEPHANT_PROFILES;
   2141     }
   2142     if (ft_info->flags & BCM_INT_FT_INFO_FLAGS_DROP_MONITOR) {
   2143         ctrl_init_msg.flags |= SHR_FT_MSG_INIT_FLAGS_DROP_MONITOR;
   2144     }
   2145     ctrl_init_msg.fsp_reinject_max_length = ft_info->fsp_reinject_max_length;
   2146 
   2147     buffer_req      = ft_info->dma_buffer;
   2148     buffer_ptr      = shr_ft_msg_ctrl_init_pack(buffer_req, &ctrl_init_msg);
   2149     buffer_len      = buffer_ptr - buffer_req;
   2150 
   2151     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_msg_send_receive(unit, MOS_MSG_SUBCLASS_FT_INIT,
   2152                                                      buffer_len, 0,
   2153                                     MOS_MSG_SUBCLASS_FT_INIT_REPLY, &reply_len, 
   2154                                     SHR_FT_MAX_UC_MSG_TIMEOUT));
   2155     return BCM_E_NONE;
   2156 }
   2157 
   2158 int _bcm_xgs5_ft_eapp_send_em_key_format_msg (int unit, 
   2159             shr_ft_msg_ctrl_em_key_format_t *em_key_format) 
   2160 {
   2161     uint8 *buffer_req = NULL, *buffer_ptr = NULL;
   2162     uint16 buffer_len = 0, reply_len = 0;
   2163     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   2164 
   2165     
   2166     if (soc_feature(unit, soc_feature_mv2_dummy_flowtracker)) {
   2167         return BCM_E_NONE;
   2168     }
   2169 
   2170     buffer_req      = ft_info->dma_buffer;
   2171     buffer_ptr      = shr_ft_msg_ctrl_em_key_format_pack(buffer_req, em_key_format);
   2172     buffer_len      = buffer_ptr - buffer_req;
   2173 
   2174     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_msg_send_receive(unit, MOS_MSG_SUBCLASS_FT_EM_KEY_FORMAT,
   2175                                                      buffer_len, 0,
   2176                                     MOS_MSG_SUBCLASS_FT_EM_KEY_FORMAT_REPLY, &reply_len, 
   2177                                     SHR_FT_MAX_UC_MSG_TIMEOUT));
   2178     return BCM_E_NONE;
   2179 }
   2180 
   2181 int _bcm_xgs5_ft_eapp_send_em_group_create_msg(int unit,
   2182                                                shr_ft_msg_ctrl_em_group_create_t *msg)
   2183 {
   2184     uint8 *buffer_req = NULL, *buffer_ptr = NULL;
   2185     uint16 buffer_len = 0, reply_len = 0;
   2186     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   2187 
   2188     buffer_req      = ft_info->dma_buffer;
   2189     buffer_ptr      = shr_ft_msg_ctrl_em_group_create_pack(buffer_req, msg);
   2190     buffer_len      = buffer_ptr - buffer_req;
   2191 
   2192     BCM_IF_ERROR_RETURN(
   2193            _bcm_xgs5_ft_msg_send_receive(unit,
   2194                                          MOS_MSG_SUBCLASS_FT_EM_GROUP_CREATE,
   2195                                          buffer_len, 0,
   2196                                          MOS_MSG_SUBCLASS_FT_EM_GROUP_CREATE_REPLY,
   2197                                          &reply_len,
   2198                                          SHR_FT_MAX_UC_MSG_TIMEOUT));
   2199     return BCM_E_NONE;
   2200 
   2201 }
   2202 
   2203 int _bcm_xgs5_ft_eapp_send_em_group_delete_msg(int unit,
   2204                                                int em_group_id)
   2205 {
   2206     uint16 reply_len = 0;
   2207 
   2208     BCM_IF_ERROR_RETURN(
   2209            _bcm_xgs5_ft_msg_send_receive(unit, MOS_MSG_SUBCLASS_FT_EM_GROUP_DELETE,
   2210                                          em_group_id, 0,
   2211                                          MOS_MSG_SUBCLASS_FT_EM_GROUP_DELETE_REPLY,
   2212                                          &reply_len,
   2213                                          SHR_FT_MAX_UC_MSG_TIMEOUT));
   2214     return BCM_E_NONE;
   2215 
   2216 }
   2217 
   2218 int _bcm_xgs5_ft_eapp_send_flow_group_create_msg (int unit, 
   2219                     bcm_flowtracker_group_t flow_group_id) 
   2220 {
   2221     shr_ft_msg_ctrl_group_create_t group_create_msg;
   2222     _bcm_int_ft_flow_group_info_t flow_group_int_info;
   2223     uint8 *buffer_req = NULL, *buffer_ptr = NULL;
   2224     uint16 buffer_len = 0, reply_len = 0;
   2225     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   2226     int rv = BCM_E_NONE;
   2227     
   2228     
   2229     if (soc_feature(unit, soc_feature_mv2_dummy_flowtracker)) {
   2230         return BCM_E_NONE;
   2231     }
   2232 
   2233     sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info));
   2234     /* Get the flow group info for this group id */
   2235     rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, flow_group_id, &flow_group_int_info);
   2236 
   2237     /* Return BCM_E_NOT_FOUND if not found */
   2238     if (BCM_FAILURE(rv)) {
   2239         return rv;
   2240     }
   2241 
   2242     sal_memset(&group_create_msg, 0, sizeof(group_create_msg));
   2243     group_create_msg.group_idx = flow_group_id;
   2244     group_create_msg.domain_id = ft_info->observation_domain_id;
   2245     /* Creating group with 0 as flow limit, so that you dont learn until flow limit is set */
   2246     group_create_msg.flow_limit = 0;
   2247 
   2248     /* Creating group with default number for aging time. */
   2249     group_create_msg.aging_interval_msecs = BCM_INT_FT_DEF_AGING_INTERVAL_MSECS;
   2250 
   2251     buffer_req      = ft_info->dma_buffer;
   2252     buffer_ptr      = shr_ft_msg_ctrl_group_create_pack(buffer_req, &group_create_msg);
   2253     buffer_len      = buffer_ptr - buffer_req;
   2254 
   2255     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_msg_send_receive(unit, MOS_MSG_SUBCLASS_FT_GROUP_CREATE,
   2256                                                      buffer_len, 0,
   2257                                     MOS_MSG_SUBCLASS_FT_GROUP_CREATE_REPLY, &reply_len, 
   2258                                     SHR_FT_MAX_UC_MSG_TIMEOUT));
   2259     return BCM_E_NONE;
   2260 }
   2261 
   2262 int _bcm_xgs5_ft_eapp_send_flow_group_delete_msg (int unit, 
   2263                     bcm_flowtracker_group_t flow_group_id) 
   2264 {
   2265     uint16 reply_len = 0;
   2266     
   2267     
   2268     if (soc_feature(unit, soc_feature_mv2_dummy_flowtracker)) {
   2269         return BCM_E_NONE;
   2270     }
   2271 
   2272     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_msg_send_receive(unit, MOS_MSG_SUBCLASS_FT_GROUP_DELETE,
   2273                                                       flow_group_id, 0,
   2274                                     MOS_MSG_SUBCLASS_FT_GROUP_DELETE_REPLY, &reply_len, 
   2275                                     SHR_FT_MAX_UC_MSG_TIMEOUT));
   2276     return BCM_E_NONE;
   2277 }
   2278 
   2279 /* NOTE: currently expecting only one flag out of multiple flags and its updated value
   2280  * is expected.
   2281  */
   2282 int _bcm_xgs5_ft_eapp_send_flow_group_update_msg (int unit, 
   2283                     bcm_flowtracker_group_t flow_group_id,
   2284                     uint32 update_flags, uint32 update_value)
   2285 {
   2286     shr_ft_msg_ctrl_group_update_t group_update_msg;
   2287     _bcm_int_ft_flow_group_info_t flow_group_int_info;
   2288     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   2289     uint8 *buffer_req = NULL, *buffer_ptr = NULL;
   2290     uint16 buffer_len = 0, reply_len = 0;
   2291     int rv = BCM_E_NONE;
   2292 
   2293     
   2294     if (soc_feature(unit, soc_feature_mv2_dummy_flowtracker)) {
   2295         return BCM_E_NONE;
   2296     }
   2297 
   2298     sal_memset(&flow_group_int_info, 0, sizeof(flow_group_int_info));
   2299     /* Get the flow group info for this group id */
   2300     rv = _bcm_xgs5_ft_flow_group_list_flow_group_get(unit, flow_group_id, &flow_group_int_info);
   2301 
   2302     /* Return BCM_E_NOT_FOUND if not found */
   2303     if (BCM_FAILURE(rv)) {
   2304         return rv;
   2305     }
   2306 
   2307     sal_memset(&group_update_msg, 0, sizeof(group_update_msg));
   2308     group_update_msg.group_idx = flow_group_id;
   2309     group_update_msg.update    = update_flags;
   2310     group_update_msg.param0    = update_value;
   2311 
   2312     buffer_req      = ft_info->dma_buffer;
   2313     buffer_ptr      = shr_ft_msg_ctrl_group_update_pack(buffer_req, &group_update_msg);
   2314     buffer_len      = buffer_ptr - buffer_req;
   2315 
   2316     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_msg_send_receive(unit, MOS_MSG_SUBCLASS_FT_GROUP_UPDATE,
   2317                                                      buffer_len, 0,
   2318                                     MOS_MSG_SUBCLASS_FT_GROUP_UPDATE_REPLY, &reply_len, 
   2319                                     SHR_FT_MAX_UC_MSG_TIMEOUT));
   2320     return BCM_E_NONE;
   2321 }
   2322 
   2323 /* NOTE: Currently we use flow group get msg to EAPP
   2324  *       only for getting flow_count.
   2325  */
   2326 int _bcm_xgs5_ft_eapp_send_flow_group_get_msg (int unit, 
   2327                     bcm_flowtracker_group_t flow_group_id,
   2328                     uint32 *flow_count)
   2329 {
   2330     shr_ft_msg_ctrl_group_get_t group_get_msg;
   2331     uint8 *buffer_req = NULL, *buffer_ptr = NULL;
   2332     uint16 buffer_len = 0, reply_len = 0;
   2333     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   2334 
   2335     
   2336     if (soc_feature(unit, soc_feature_mv2_dummy_flowtracker)) {
   2337         return BCM_E_NONE;
   2338     }
   2339 
   2340     sal_memset(&group_get_msg, 0, sizeof(group_get_msg));
   2341 
   2342 
   2343     /* Do a group get for flow_group_id */
   2344     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_msg_send_receive(unit, MOS_MSG_SUBCLASS_FT_GROUP_GET,
   2345                                                       flow_group_id, 0,
   2346                                     MOS_MSG_SUBCLASS_FT_GROUP_GET_REPLY, &reply_len, 
   2347                                     SHR_FT_MAX_UC_MSG_TIMEOUT));
   2348 
   2349     buffer_req      = ft_info->dma_buffer;
   2350     buffer_ptr      = shr_ft_msg_ctrl_group_get_unpack(buffer_req, &group_get_msg);
   2351     buffer_len      = buffer_ptr - buffer_req;
   2352 
   2353     if (buffer_len != reply_len) {
   2354         return BCM_E_INTERNAL;
   2355     }
   2356     
   2357     *flow_count = group_get_msg.flow_count;
   2358     
   2359     return BCM_E_NONE;
   2360 }
   2361 
   2362 int _bcm_xgs5_ft_eapp_send_template_create_msg (int unit, 
   2363                     bcm_flowtracker_export_template_t template_id) 
   2364 {
   2365     _bcm_int_ft_export_template_info_t template_int_info;
   2366     shr_ft_msg_ctrl_template_create_t template_create_msg;
   2367     uint8 *buffer_req = NULL, *buffer_ptr = NULL;
   2368     uint16 buffer_len = 0, reply_len = 0;
   2369     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   2370     int rv = BCM_E_NONE;
   2371     int i = 0;
   2372 
   2373     
   2374     if (soc_feature(unit, soc_feature_mv2_dummy_flowtracker)) {
   2375         return BCM_E_NONE;
   2376     }
   2377 
   2378     sal_memset(&template_int_info, 0, sizeof(template_int_info));
   2379     /* Get the template info for this template id */
   2380     rv = _bcm_xgs5_ft_template_list_template_get(unit, template_id, &template_int_info);
   2381 
   2382     /* Return BCM_E_NOT_FOUND if not found */
   2383     if (BCM_FAILURE(rv)) {
   2384         return rv;
   2385     }
   2386     sal_memset(&template_create_msg, 0, sizeof(template_create_msg));
   2387     template_create_msg.id             = template_id;
   2388     template_create_msg.set_id         = template_int_info.set_id;
   2389     template_create_msg.num_info_elems = template_int_info.num_export_elements;
   2390 
   2391     for (i = 0; i < template_create_msg.num_info_elems; i++) {
   2392         template_create_msg.info_elems[i] = template_int_info.elements[i].element;
   2393         template_create_msg.data_size[i]  = template_int_info.elements[i].data_size;
   2394     }
   2395 
   2396     buffer_req      = ft_info->dma_buffer;
   2397     buffer_ptr      = shr_ft_msg_ctrl_template_create_pack(buffer_req, &template_create_msg);
   2398     buffer_len      = buffer_ptr - buffer_req;
   2399 
   2400     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_msg_send_receive(unit, MOS_MSG_SUBCLASS_FT_TEMPLATE_CREATE,
   2401                                                      buffer_len, 0,
   2402                                     MOS_MSG_SUBCLASS_FT_TEMPLATE_CREATE_REPLY, &reply_len, 
   2403                                     SHR_FT_MAX_UC_MSG_TIMEOUT));
   2404     return BCM_E_NONE;
   2405 }
   2406 
   2407 int _bcm_xgs5_ft_eapp_send_template_delete_msg (int unit, 
   2408                     bcm_flowtracker_export_template_t template_id) 
   2409 {
   2410     uint16 reply_len = 0;
   2411     
   2412     
   2413     if (soc_feature(unit, soc_feature_mv2_dummy_flowtracker)) {
   2414         return BCM_E_NONE;
   2415     }
   2416 
   2417     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_msg_send_receive(unit, 
   2418                                     MOS_MSG_SUBCLASS_FT_TEMPLATE_DELETE,
   2419                                     template_id, 0,
   2420                                     MOS_MSG_SUBCLASS_FT_TEMPLATE_DELETE_REPLY, &reply_len, 
   2421                                     SHR_FT_MAX_UC_MSG_TIMEOUT));
   2422     return BCM_E_NONE;
   2423 }
   2424 
   2425 int _bcm_xgs5_ft_eapp_send_collector_create_msg(int unit,
   2426                                                 int collector_id,
   2427                                                 int export_profile_id)
   2428 {
   2429     shr_ft_msg_ctrl_collector_create_t collector_create_msg;
   2430     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   2431     uint8 *buffer_req = NULL, *buffer_ptr = NULL;
   2432     uint16 buffer_len = 0, reply_len = 0;
   2433     int rv = BCM_E_NONE;
   2434 
   2435     
   2436     if (soc_feature(unit, soc_feature_mv2_dummy_flowtracker)) {
   2437         return BCM_E_NONE;
   2438     }
   2439 
   2440     if (ft_info->cfg_mode == SHR_FT_CFG_MODE_V1) {
   2441         rv = _bcm_xgs5_ft_eapp_collector_encap_build_pack(unit, collector_id,
   2442                                                           &collector_create_msg);
   2443     } else {
   2444         rv = _bcm_xgs5_ft_v2_eapp_collector_encap_build_pack(unit, collector_id,
   2445                                                              export_profile_id,
   2446                                                              &collector_create_msg);
   2447     }
   2448     BCM_IF_ERROR_RETURN(rv);
   2449 
   2450     /* Check if there is space to insert at least the headers  */
   2451     if ((collector_create_msg.encap_length +
   2452          BCM_INT_FT_IPFIX_MSG_HDR_LENGTH   +
   2453          BCM_INT_FT_SET_HDR_LENGTH         +
   2454          BCM_INT_FT_L2_CRC_LENGTH)  > collector_create_msg.mtu) {
   2455         return BCM_E_PARAM;
   2456     }
   2457 
   2458     buffer_req      = ft_info->dma_buffer;
   2459     buffer_ptr      = shr_ft_msg_ctrl_collector_create_pack(buffer_req, &collector_create_msg);
   2460     buffer_len      = buffer_ptr - buffer_req;
   2461 
   2462     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_msg_send_receive(unit, MOS_MSG_SUBCLASS_FT_COLLECTOR_CREATE,
   2463                                                      buffer_len, 0,
   2464                                     MOS_MSG_SUBCLASS_FT_COLLECTOR_CREATE_REPLY, &reply_len, 
   2465                                     SHR_FT_MAX_UC_MSG_TIMEOUT));
   2466     return BCM_E_NONE;
   2467 }
   2468 
   2469 int _bcm_xgs5_ft_eapp_send_collector_delete_msg (int unit,
   2470                                                  uint16 collector_id)
   2471 {
   2472     uint16 reply_len = 0;
   2473     
   2474     
   2475     if (soc_feature(unit, soc_feature_mv2_dummy_flowtracker)) {
   2476         return BCM_E_NONE;
   2477     }
   2478 
   2479     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_msg_send_receive(unit, 
   2480                                         MOS_MSG_SUBCLASS_FT_COLLECTOR_DELETE,
   2481                                                       collector_id, 0,
   2482                                     MOS_MSG_SUBCLASS_FT_COLLECTOR_DELETE_REPLY, &reply_len, 
   2483                                     SHR_FT_MAX_UC_MSG_TIMEOUT));
   2484     return BCM_E_NONE;
   2485 }
   2486 
   2487 int _bcm_xgs5_ft_eapp_send_export_interval_update_msg (int unit,
   2488                                                  uint32 export_interval)
   2489 {
   2490     uint16 reply_len = 0;
   2491     
   2492     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_msg_send_receive(unit, 
   2493                                         MOS_MSG_SUBCLASS_FT_EXPORT_INTERVAL_UPDATE,
   2494                                                      0, export_interval,
   2495                                     MOS_MSG_SUBCLASS_FT_EXPORT_INTERVAL_UPDATE_REPLY, 
   2496                                     &reply_len, 
   2497                                     SHR_FT_MAX_UC_MSG_TIMEOUT));
   2498     return BCM_E_NONE;
   2499 }
   2500 /*
   2501  * Function:
   2502  *      _bcm_xgs5_ft_send_eapp_template_xmit_start
   2503  * Purpose:
   2504  *      Start the template set transmit
   2505  * Parameters:
   2506  *      unit          - (IN)  BCM device number
   2507  *      template_id   - (IN)  Template Id
   2508  *      collector_id  - (IN)  Collector Id
   2509  * Returns:
   2510  *      BCM_E_XXX   - BCM error code.
   2511  */
   2512 int
   2513 _bcm_xgs5_ft_eapp_send_template_xmit_start(int unit,
   2514                                   bcm_flowtracker_export_template_t template_id,
   2515                                   bcm_flowtracker_collector_t collector_id)
   2516 {
   2517     _bcm_int_ft_export_template_info_t template_int_info;
   2518     shr_ft_msg_ctrl_template_xmit_t             msg;
   2519     _bcm_int_ft_info_t                *ft_info = FT_INFO_GET(unit);
   2520     uint8                                      *buffer_req = NULL;
   2521     uint8                                      *buffer_ptr = NULL;
   2522     uint16                                      buffer_len = 0;
   2523     uint16                                      reply_len = 0;
   2524     int                                         rv = BCM_E_NONE;
   2525 
   2526     
   2527     if (soc_feature(unit, soc_feature_mv2_dummy_flowtracker)) {
   2528         return BCM_E_NONE;
   2529     }
   2530 
   2531     sal_memset(&template_int_info, 0, sizeof(template_int_info));
   2532 
   2533     /* Get the template info for this template id */
   2534     rv = _bcm_xgs5_ft_template_list_template_get(unit, template_id,
   2535                                                  &template_int_info);
   2536     if (BCM_FAILURE(rv)) {
   2537         return rv;
   2538     }
   2539 
   2540     sal_memset(&msg, 0, sizeof(msg));
   2541 
   2542     /* Build the template encap */
   2543     _bcm_xgs5_ft_eapp_template_encap_build_pack(unit,
   2544                                                 &template_int_info,
   2545                                                 &(msg.encap_length),
   2546                                                 msg.encap);
   2547     msg.template_id   = template_id;
   2548     msg.collector_id  = collector_id;
   2549     msg.interval_secs = template_int_info.interval_secs;
   2550     msg.initial_burst = template_int_info.initial_burst;
   2551 
   2552     buffer_req = ft_info->dma_buffer;
   2553     buffer_ptr = shr_ft_msg_ctrl_template_xmit_pack(buffer_req, &msg);
   2554     buffer_len = buffer_ptr - buffer_req;
   2555 
   2556     BCM_IF_ERROR_RETURN(
   2557           _bcm_xgs5_ft_msg_send_receive(unit,
   2558                                         MOS_MSG_SUBCLASS_FT_TEMPLATE_XMIT,
   2559                                         buffer_len, 0,
   2560                                         MOS_MSG_SUBCLASS_FT_TEMPLATE_XMIT_REPLY,
   2561                                         &reply_len,
   2562                                         SHR_FT_MAX_UC_MSG_TIMEOUT));
   2563     return BCM_E_NONE;
   2564 }
   2565 
   2566 /*
   2567  * Function:
   2568  *      _bcm_xgs5_ft_eapp_send_group_actions_set_msg
   2569  * Purpose:
   2570  *      Set actions on a group
   2571  * Parameters:
   2572  *      unit          - (IN)  BCM device number
   2573  * Returns:
   2574  *      BCM_E_XXX   - BCM error code.
   2575  */
   2576 int
   2577 _bcm_xgs5_ft_eapp_send_group_actions_set_msg(int unit,
   2578                                              shr_ft_msg_ctrl_group_actions_set_t *msg)
   2579 {
   2580     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   2581     uint8 *buffer_req = NULL;
   2582     uint8 *buffer_ptr = NULL;
   2583     uint16 buffer_len = 0;
   2584     uint16 reply_len = 0;
   2585 
   2586     buffer_req = ft_info->dma_buffer;
   2587     buffer_ptr = shr_ft_msg_ctrl_group_actions_set_pack(buffer_req, msg);
   2588     buffer_len = buffer_ptr - buffer_req;
   2589 
   2590     BCM_IF_ERROR_RETURN(
   2591           _bcm_xgs5_ft_msg_send_receive(unit,
   2592                                         MOS_MSG_SUBCLASS_FT_GROUP_ACTIONS_SET,
   2593                                         buffer_len, 0,
   2594                                         MOS_MSG_SUBCLASS_FT_GROUP_ACTIONS_SET_REPLY,
   2595                                         &reply_len,
   2596                                         SHR_FT_MAX_UC_MSG_TIMEOUT));
   2597 
   2598     return BCM_E_NONE;
   2599 }
   2600 
   2601 /******************************************************
   2602 *                                                     *
   2603 *        FLOWTRACKER EMB APP APIs                     *
   2604  */
   2605 
   2606 int bcm_xgs5_ft_eapp_init(int unit)
   2607 {
   2608     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   2609     int rv = BCM_E_NONE;
   2610     int uc = 0;
   2611 
   2612     
   2613     if (!soc_feature(unit, soc_feature_mv2_dummy_flowtracker)) {
   2614         /* Init the app */
   2615         if (!soc_uc_in_reset(unit, uc)) {
   2616             rv = soc_cmic_uc_appl_init(unit, uc, MOS_MSG_CLASS_FT,
   2617                                        SHR_FT_MAX_UC_MSG_TIMEOUT,
   2618                                        FT_MSG_VERSION, FT_MSG_BASE_VERSION,
   2619                                        NULL, NULL);
   2620             if (SOC_E_NONE != rv) {
   2621                 BCM_IF_ERROR_RETURN(bcm_xgs5_ft_eapp_detach(unit));
   2622                 return rv;
   2623             }
   2624         } else {
   2625             BCM_IF_ERROR_RETURN(bcm_xgs5_ft_eapp_detach(unit));
   2626             return BCM_E_INIT;
   2627         }
   2628     }
   2629 
   2630     /*
   2631      * Allocate DMA buffer
   2632      *
   2633      * DMA buffer will be used to send and receive 'long' messages
   2634      * between SDK Host and uController (BTE).
   2635      */
   2636     ft_info->dma_buffer_len = sizeof(shr_ft_msg_ctrl_t);
   2637     ft_info->dma_buffer = soc_cm_salloc(unit, ft_info->dma_buffer_len,
   2638                                          "FT DMA buffer");
   2639     if (!ft_info->dma_buffer) {
   2640         BCM_IF_ERROR_RETURN(bcm_xgs5_ft_eapp_detach(unit));
   2641         return BCM_E_MEMORY;
   2642     }
   2643     sal_memset(ft_info->dma_buffer, 0, ft_info->dma_buffer_len);
   2644 
   2645     if (!SOC_WARM_BOOT(unit)) {
   2646         /* Send the init config to UKERNEL */
   2647         rv = _bcm_xgs5_ft_eapp_send_ctrl_init_msg(unit);
   2648         if (BCM_FAILURE(rv)) {
   2649             BCM_IF_ERROR_RETURN(bcm_xgs5_ft_eapp_detach(unit));
   2650             return rv;
   2651         }
   2652     }
   2653 
   2654     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_eapp_send_features_exchange_msg(unit));
   2655 
   2656     /* Create template list, collector list and flow group list */
   2657     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_template_list_create(unit));
   2658     if (ft_info->cfg_mode == SHR_FT_CFG_MODE_V1) {
   2659         BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_collector_list_create(unit));
   2660     } else {
   2661         BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_v2_collector_list_create(unit));
   2662         BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_v2_collector_list_export_profile_create(unit));
   2663     }
   2664     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_flow_group_list_create(unit));
   2665     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_elph_profile_list_create(unit));
   2666 
   2667     return BCM_E_NONE;
   2668 }
   2669 
   2670 int bcm_xgs5_ft_eapp_detach(int unit)
   2671 {
   2672     _bcm_int_ft_info_t          *ft_info = FT_INFO_GET(unit);
   2673     int                          rv = BCM_E_NONE;
   2674     int                          uc = 0, status = 0;
   2675     uint16                       reply_len = 0;
   2676 
   2677     
   2678     if (!soc_feature(unit, soc_feature_mv2_dummy_flowtracker)) {
   2679     if (!SOC_WARM_BOOT(unit)) {
   2680         /* Un Init the app */
   2681         SOC_IF_ERROR_RETURN(soc_uc_status(unit, uc, &status));
   2682         if (status) {
   2683             rv = _bcm_xgs5_ft_msg_send_receive(unit,
   2684                                                MOS_MSG_SUBCLASS_FT_SHUTDOWN,
   2685                                                0, 0,
   2686                                                MOS_MSG_SUBCLASS_FT_SHUTDOWN_REPLY,
   2687                                                &reply_len,
   2688                                                SHR_FT_MAX_UC_MSG_TIMEOUT);
   2689             if (BCM_SUCCESS(rv) && (reply_len != 0)) {
   2690                 return BCM_E_INTERNAL;
   2691             }
   2692         }
   2693     }
   2694     }
   2695 
   2696     /*
   2697      * Free DMA buffer
   2698  */
   2699     if (ft_info->dma_buffer != NULL) {
   2700         soc_cm_sfree(unit, ft_info->dma_buffer);
   2701     }
   2702 
   2703     /* Free up template list, collector list and flow group list */
   2704     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_template_list_destroy(unit));
   2705     if (ft_info->cfg_mode == SHR_FT_CFG_MODE_V1) {
   2706         BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_collector_list_destroy(unit));
   2707     } else {
   2708         BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_v2_collector_list_destroy(unit));
   2709         BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_v2_collector_list_export_profile_destroy(unit));
   2710     }
   2711     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_flow_group_list_destroy(unit));
   2712     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_elph_profile_list_destroy(unit));
   2713 
   2714     return BCM_E_NONE;
   2715 }
   2716 
   2717 /* Drop reasons, DO NOT change the order */
   2718 static bcm_rx_reason_t ft_drop_reasons[] = {
   2719     bcmRxReasonInvalid,
   2720     bcmRxReasonL3SourceMiss,
   2721     bcmRxReasonL3DestMiss,
   2722     bcmRxReasonMcastMiss,
   2723     bcmRxReasonIpMcastMiss,
   2724     bcmRxReasonUnknownVlan,
   2725     bcmRxReasonL3HeaderMismatch,
   2726     bcmRxReasonDosAttack,
   2727     bcmRxReasonMartianAddr,
   2728     bcmRxReasonTunnelError,
   2729     bcmRxReasonParityError,
   2730     bcmRxReasonL3MtuFail,
   2731     bcmRxReasonHigigHdrError,
   2732     bcmRxReasonMcastIdxError,
   2733     bcmRxReasonClassBasedMove,
   2734     bcmRxReasonL3AddrBindFail,
   2735     bcmRxReasonMplsLabelMiss,
   2736     bcmRxReasonMplsInvalidAction,
   2737     bcmRxReasonMplsInvalidPayload,
   2738     bcmRxReasonTunnelObjectValidationFail,
   2739     bcmRxReasonMplsSequenceNumber,
   2740     bcmRxReasonL2NonUnicastMiss,
   2741     bcmRxReasonNivPrioDrop,
   2742     bcmRxReasonNivRpfFail,
   2743     bcmRxReasonUnknownSubtendingPort,
   2744     bcmRxReasonTunnelAdaptLookupMiss,
   2745     bcmRxReasonPacketFlowSelectMiss,
   2746     bcmRxReasonTunnelDecapEcnError,
   2747     bcmRxReasonFailoverDrop,
   2748     bcmRxReasonOtherLookupMiss,
   2749     bcmRxReasonInvalidTpid,
   2750     bcmRxReasonTunnelTtlError,
   2751     bcmRxReasonMplsIllegalReservedLabel,
   2752     bcmRxReasonL3HeaderError,
   2753     bcmRxReasonL2HeaderError,
   2754     bcmRxReasonTtl1,
   2755     bcmRxReasonTtl,
   2756     bcmRxReasonFcoeZoneCheckFail,
   2757     bcmRxReasonIpmcInterfaceMismatch,
   2758     bcmRxReasonMplsTtl,
   2759     bcmRxReasonMplsUnknownAch,
   2760     bcmRxReasonOAMError,
   2761     bcmRxReasonL2GreSipMiss,
   2762     bcmRxReasonL2GreVpnIdMiss,
   2763     bcmRxReasonBfd,
   2764     bcmRxReasonCongestionCnmProxyError,
   2765     bcmRxReasonVxlanSipMiss,
   2766     bcmRxReasonVxlanVpnIdMiss,
   2767     bcmRxReasonNivInterfaceMiss,
   2768     bcmRxReasonNivTagInvalid,
   2769     bcmRxReasonNivTagDrop,
   2770     bcmRxReasonNivUntagDrop,
   2771     bcmRxReasonTrillInvalid,
   2772     bcmRxReasonTrillMiss,
   2773     bcmRxReasonTrillRpfFail,
   2774     bcmRxReasonTrillTtl,
   2775     bcmRxReasonNat,
   2776     bcmRxReasonTcpUdpNatMiss,
   2777     bcmRxReasonIcmpNatMiss,
   2778     bcmRxReasonNatFragment,
   2779     bcmRxReasonNatMiss
   2780 };
   2781 
   2782 /*
   2783  * Function:
   2784  *      _bcm_xgs5_ft_eapp_send_flow_group_flow_data_msg
   2785  * Purpose:
   2786  *      Get flow data for a given flow key within the given flow group.
   2787  * Parameters:
   2788  *      unit          - (IN)  BCM device number
   2789  *      flow_group_id - (IN)  Flow group Id
   2790  *      flow_key      - (IN)  Five tuple that constitutes a flow
   2791  *      flow_data     - (OUT) Data associated with the flow key
   2792  * Returns:
   2793  *      BCM_E_XXX     - BCM error code.
   2794  */
   2795 int _bcm_xgs5_ft_eapp_send_flow_group_flow_data_get_msg(
   2796                                            int unit,
   2797                                            bcm_flowtracker_group_t flow_group_id,
   2798                                            bcm_flowtracker_flow_key_t *flow_key,
   2799                                            bcm_flowtracker_flow_data_t *flow_data)
   2800 {
   2801     shr_ft_msg_ctrl_group_flow_data_get_t       send_msg;
   2802     shr_ft_msg_ctrl_group_flow_data_get_reply_t reply_msg;
   2803     _bcm_int_ft_info_t                         *ft_info = FT_INFO_GET(unit);
   2804     uint8                                      *buffer_req = NULL;
   2805     uint8                                      *buffer_ptr = NULL;
   2806     uint16                                      buffer_len = 0, reply_len = 0;
   2807     int                                         i;
   2808     bcm_rx_reason_t                             drop_reason;
   2809     int                                         rv = BCM_E_NONE;
   2810 
   2811     
   2812     if (soc_feature(unit, soc_feature_mv2_dummy_flowtracker)) {
   2813         return BCM_E_NONE;
   2814     }
   2815 
   2816     sal_memset(&send_msg, 0, sizeof(send_msg));
   2817     send_msg.group_idx         = flow_group_id;
   2818     send_msg.src_ip            = flow_key->src_ip.addr.ipv4_addr;
   2819     send_msg.dst_ip            = flow_key->dst_ip.addr.ipv4_addr;
   2820     send_msg.l4_src_port       = flow_key->l4_src_port;
   2821     send_msg.l4_dst_port       = flow_key->l4_dst_port;
   2822     send_msg.ip_protocol       = flow_key->ip_protocol;
   2823     send_msg.inner_src_ip      = flow_key->inner_src_ip.addr.ipv4_addr;
   2824     send_msg.inner_dst_ip      = flow_key->inner_dst_ip.addr.ipv4_addr;
   2825     send_msg.inner_l4_src_port = flow_key->inner_l4_src_port;
   2826     send_msg.inner_l4_dst_port = flow_key->inner_l4_dst_port;
   2827     send_msg.inner_ip_protocol = flow_key->inner_ip_protocol;
   2828     send_msg.vnid              = flow_key->vxlan_network_id;
   2829     send_msg.custom_length     = SHR_FT_CUSTOM_KEY_MAX_LENGTH;
   2830     sal_memcpy(send_msg.custom, flow_key->custom, send_msg.custom_length);
   2831     send_msg.in_port           = flow_key->in_port;
   2832 
   2833     buffer_req = ft_info->dma_buffer;
   2834     buffer_ptr = shr_ft_msg_ctrl_group_flow_data_get_pack(buffer_req, &send_msg);
   2835     buffer_len = buffer_ptr - buffer_req;
   2836 
   2837     BCM_IF_ERROR_RETURN(
   2838       _bcm_xgs5_ft_msg_send_receive(unit,
   2839                                     MOS_MSG_SUBCLASS_FT_GROUP_FLOW_DATA_GET,
   2840                                     buffer_len, 0,
   2841                                     MOS_MSG_SUBCLASS_FT_GROUP_FLOW_DATA_GET_REPLY,
   2842                                     &reply_len,
   2843                                     SHR_FT_MAX_UC_MSG_TIMEOUT));
   2844 
   2845     buffer_req = ft_info->dma_buffer;
   2846     buffer_ptr = shr_ft_msg_ctrl_group_flow_data_get_reply_unpack(buffer_req, &reply_msg);
   2847     buffer_len = buffer_ptr - buffer_req;
   2848 
   2849     if (buffer_len != reply_len) {
   2850         return BCM_E_INTERNAL;
   2851     }
   2852 
   2853     COMPILER_64_SET(flow_data->packet_count, reply_msg.pkt_count_upper,
   2854                     reply_msg.pkt_count_lower);
   2855 
   2856     COMPILER_64_SET(flow_data->byte_count, reply_msg.byte_count_upper,
   2857                     reply_msg.byte_count_lower);
   2858 
   2859     COMPILER_64_SET(flow_data->flow_start_timestamp_msecs,
   2860                     reply_msg.flow_start_ts_upper,
   2861                     reply_msg.flow_start_ts_lower);
   2862 
   2863     COMPILER_64_SET(flow_data->observation_timestamp_msecs,
   2864                     reply_msg.obs_ts_upper, reply_msg.obs_ts_lower);
   2865 
   2866     /* Get the drop reasons */
   2867     BCM_RX_REASON_CLEAR_ALL(flow_data->pkt_drop_reasons);
   2868     for (i = 0; i < reply_msg.num_drop_reasons; i++) {
   2869         if (reply_msg.drop_reasons[i] == SHR_FT_DROP_RX_REASON_INVALID) {
   2870             continue;
   2871         } else if (reply_msg.drop_reasons[i] >= SHR_FT_DROP_RX_REASON_MAX_VALUE) {
   2872             return BCM_E_PARAM;
   2873         }
   2874 
   2875         drop_reason = ft_drop_reasons[reply_msg.drop_reasons[i]];
   2876         BCM_RX_REASON_SET(flow_data->pkt_drop_reasons, drop_reason);
   2877     }
   2878 
   2879     return rv;
   2880 }
   2881 
   2882 /*
   2883  * Function:
   2884  *      _bcm_xgs5_ft_eapp_send_ser_event_msg
   2885  * Purpose:
   2886  *      Send SER event msg to app
   2887  * Parameters:
   2888  *      unit      - (IN) BCM device number
   2889  *      pipe      - (IN) Pipe index
   2890  *      mem       - (IN) Memory (EM)
   2891  *      index     - (IN) Index
   2892  * Returns:
   2893  *      BCM_E_XXX     - BCM error code.
   2894  */
   2895 int
   2896 _bcm_xgs5_ft_eapp_send_ser_event_msg(int unit, int pipe, soc_mem_t mem, int index)
   2897 {
   2898     shr_ft_msg_ctrl_ser_event_t  ser_event_msg;
   2899     _bcm_int_ft_info_t          *ft_info = FT_INFO_GET(unit);
   2900     uint8                       *buffer_req = NULL, *buffer_ptr = NULL;
   2901     uint16                       buffer_len = 0, reply_len = 0;
   2902 
   2903     
   2904     if (soc_feature(unit, soc_feature_mv2_dummy_flowtracker)) {
   2905         return BCM_E_NONE;
   2906     }
   2907 
   2908     sal_memset(&ser_event_msg, 0, sizeof(ser_event_msg));
   2909     ser_event_msg.pipe  = pipe;
   2910     ser_event_msg.mem   = mem;
   2911     ser_event_msg.index = index;
   2912 
   2913     buffer_req = ft_info->dma_buffer;
   2914     buffer_ptr = shr_ft_msg_ctrl_ser_event_pack(buffer_req, &ser_event_msg);
   2915     buffer_len = buffer_ptr - buffer_req;
   2916 
   2917     BCM_IF_ERROR_RETURN(
   2918             _bcm_xgs5_ft_msg_send_receive(unit, MOS_MSG_SUBCLASS_FT_SER_EVENT,
   2919                                           buffer_len, 0,
   2920                                           MOS_MSG_SUBCLASS_FT_SER_EVENT_REPLY,
   2921                                           &reply_len,
   2922                                           SHR_FT_MAX_UC_MSG_TIMEOUT));
   2923 
   2924     return BCM_E_NONE;
   2925 }
   2926 
   2927 /*
   2928  * Function:
   2929  *      _bcm_xgs5_ft_eapp_elph_filter_copy
   2930  * Purpose:
   2931  *      Copy the filter cfg from API to app format
   2932  * Parameters:
   2933  *      unit  - (IN)  BCM device number
   2934  *      src   - (IN)  Filter API format
   2935  *      dst   - (OUT) Filter app format
   2936  * Returns:
   2937  *      None
   2938  */
   2939 STATIC void
   2940 _bcm_xgs5_ft_eapp_elph_filter_copy(int unit,
   2941                                    bcm_flowtracker_elephant_filter_t *src,
   2942                                    shr_ft_msg_ctrl_elph_profile_filter_t *dst)
   2943 {
   2944     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   2945 
   2946     COMPILER_64_TO_32_HI(dst->size_threshold_bytes_upper_32,
   2947                          src->size_threshold_bytes);
   2948 
   2949     COMPILER_64_TO_32_LO(dst->size_threshold_bytes_lower_32,
   2950                          src->size_threshold_bytes);
   2951 
   2952     /* Copy the rate thresholds, API configures it as kbits/sec, whereas app
   2953      * expects it as bytes/100usec
   2954      */
   2955     dst->rate_low_threshold  = src->rate_low_threshold_kbits_sec / 80;
   2956     dst->rate_high_threshold = src->rate_high_threshold_kbits_sec / 80;
   2957 
   2958     /* Convert the monitoring interval to scan count */
   2959     dst->scan_count = src->monitor_interval_usecs / ft_info->scan_interval_usecs;
   2960 
   2961     if (src->flags & BCM_FLOWTRACKER_ELEPHANT_FILTER_FLAGS_INCREASING_RATE) {
   2962         dst->incr_rate = 1;
   2963     }
   2964 }
   2965 
   2966 /*
   2967  * Function:
   2968  *      _bcm_xgs5_ft_eapp_send_elph_profile_create_msg
   2969  * Purpose:
   2970  *      Send Elephant profile create msg
   2971  * Parameters:
   2972  *      unit       - (IN) BCM device number
   2973  *      profile_id - (IN) Elephant profile Id
   2974  * Returns:
   2975  *      BCM_E_XXX     - BCM error code.
   2976  */
   2977 int
   2978 _bcm_xgs5_ft_eapp_send_elph_profile_create_msg(int unit, int profile_id)
   2979 {
   2980     shr_ft_msg_ctrl_elph_profile_create_t  msg;
   2981     uint8                                 *buffer_req = NULL, *buffer_ptr = NULL;
   2982     uint16                                 buffer_len = 0, reply_len = 0;
   2983     _bcm_int_ft_info_t                    *ft_info = FT_INFO_GET(unit);
   2984     _bcm_int_ft_elph_profile_info_t        profile_info;
   2985 
   2986     sal_memset(&msg, 0, sizeof(msg));
   2987     msg.profile_idx = profile_id;
   2988 
   2989     
   2990     if (soc_feature(unit, soc_feature_mv2_dummy_flowtracker)) {
   2991         return BCM_E_NONE;
   2992     }
   2993 
   2994     BCM_IF_ERROR_RETURN(_bcm_xgs5_ft_elph_profile_list_get(unit, profile_id,
   2995                                                            &profile_info));
   2996 
   2997     /* App expects 2 promotion filters followed by a demotion filter always.
   2998      * Dummy filters should have already been inserted by now in profile_info
   2999      */
   3000     msg.num_filters = BCM_FLOWTRACKER_ELEPHANT_MAX_PROMOTION_FILTERS + 1;
   3001     _bcm_xgs5_ft_eapp_elph_filter_copy(unit,
   3002                                        &(profile_info.profile.promotion_filters[0]),
   3003                                        &(msg.filters[0]));
   3004     _bcm_xgs5_ft_eapp_elph_filter_copy(unit,
   3005                                        &(profile_info.profile.promotion_filters[1]),
   3006                                        &(msg.filters[1]));
   3007     _bcm_xgs5_ft_eapp_elph_filter_copy(unit,
   3008                                        &(profile_info.profile.demotion_filter),
   3009                                        &(msg.filters[2]));
   3010 
   3011 
   3012     buffer_req = ft_info->dma_buffer;
   3013     buffer_ptr = shr_ft_msg_ctrl_elph_profile_create_pack(buffer_req, &msg);
   3014     buffer_len = buffer_ptr - buffer_req;
   3015 
   3016     BCM_IF_ERROR_RETURN(
   3017         _bcm_xgs5_ft_msg_send_receive(unit,
   3018                                       MOS_MSG_SUBCLASS_FT_ELPH_PROFILE_CREATE,
   3019                                       buffer_len, 0,
   3020                                       MOS_MSG_SUBCLASS_FT_ELPH_PROFILE_CREATE_REPLY,
   3021                                       &reply_len,
   3022                                       SHR_FT_MAX_UC_MSG_TIMEOUT));
   3023 
   3024     return BCM_E_NONE;
   3025 }
   3026 
   3027 /*
   3028  * Function:
   3029  *      _bcm_xgs5_ft_eapp_send_elph_profile_delete_msg
   3030  * Purpose:
   3031  *      Send Elephant profile delete msg
   3032  * Parameters:
   3033  *      unit       - (IN) BCM device number
   3034  *      profile_id - (IN) Elephant profile Id
   3035  * Returns:
   3036  *      BCM_E_XXX     - BCM error code.
   3037  */
   3038 int
   3039 _bcm_xgs5_ft_eapp_send_elph_profile_delete_msg(int unit, int profile_id)
   3040 {
   3041     uint16 reply_len = 0;
   3042 
   3043     
   3044     if (soc_feature(unit, soc_feature_mv2_dummy_flowtracker)) {
   3045         return BCM_E_NONE;
   3046     }
   3047 
   3048     BCM_IF_ERROR_RETURN(
   3049        _bcm_xgs5_ft_msg_send_receive(unit,
   3050                                      MOS_MSG_SUBCLASS_FT_ELPH_PROFILE_DELETE,
   3051                                      profile_id, 0,
   3052                                      MOS_MSG_SUBCLASS_FT_ELPH_PROFILE_DELETE_REPLY,
   3053                                      &reply_len,
   3054                                      SHR_FT_MAX_UC_MSG_TIMEOUT));
   3055     return BCM_E_NONE;
   3056 }
   3057 
   3058 
   3059 /******************************************************
   3060 *                                                     *
   3061 *                Debug functions                      *
   3062  */
   3063 char *_bcm_xgs5_ft_template_element_str[bcmFlowtrackerExportElementTypeCount] = 
   3064 {
   3065     "SrcIPv4",
   3066     "DstIPv4",
   3067     "Unknown",
   3068     "Unknown",
   3069     "L4SrcPort",
   3070     "L4DstPort",
   3071     "IPProtocol",
   3072     "PktCount",
   3073     "ByteCount",
   3074     "Unknown",
   3075     "Unknown",
   3076     "Unknown",
   3077     "ObservationTimeMsecs",
   3078     "FlowStartTimeMsecs",
   3079     "GroupId",
   3080     "Unknown",
   3081     "Unknown",
   3082     "Unknown",
   3083     "Unknown",
   3084     "Unknown",
   3085     "Unknown",
   3086     "Unknown",
   3087     "Unknown",
   3088     "Unknown",
   3089     "Unknown",
   3090     "Unknown",
   3091     "Unknown",
   3092     "Unknown",
   3093     "Unknown",
   3094     "Unknown",
   3095     "Unknown",
   3096     "Unknown",
   3097     "Unknown",
   3098     "Unknown",
   3099     "Unknown",
   3100     "Unknown",
   3101     "Unknown",
   3102     "Unknown",
   3103     "Unknown",
   3104     "Unknown",
   3105     "Unknown",
   3106     "Unknown",
   3107     "Unknown",
   3108     "Unknown",
   3109     "Unknown",
   3110 };
   3111 
   3112 /*
   3113  * Function:
   3114  *     _bcm_xgs5_ft_template_dump
   3115  * Purpose:
   3116  *     Dump the template.
   3117  * Parameters:
   3118  *     template_node - (IN) Template info.
   3119  * Returns:
   3120  *     Nothing
   3121  */
   3122 void
   3123 _bcm_xgs5_ft_template_dump (
   3124    _bcm_int_ft_export_template_info_t *template_node)
   3125 {
   3126     int i;
   3127 
   3128     LOG_CLI((BSL_META("Template ID = %d\r\n"),template_node->template_id));
   3129     LOG_CLI((BSL_META("\tSet ID = %u\r\n"), template_node->set_id));
   3130     LOG_CLI((BSL_META("\tNum of export elements = %d\r\n"), template_node->num_export_elements));
   3131     for (i = 0; i < template_node->num_export_elements;
   3132          i++) {
   3133         LOG_CLI((BSL_META("\t\tElement[%d]=%s\r\n"), i,
   3134          _bcm_xgs5_ft_template_element_str[template_node->elements[i].element]));
   3135     }
   3136 }
   3137 
   3138 /*
   3139  * Function:
   3140  *     _bcm_xgs5_ft_template_list_dump
   3141  * Purpose:
   3142  *     Dump the template list.
   3143  * Parameters:
   3144  *     unit          - (IN) BCM device number
   3145  * Returns:
   3146  *     Nothing
   3147  */
   3148 void
   3149 _bcm_xgs5_ft_template_list_dump (int unit)
   3150 {
   3151     _bcm_int_ft_export_template_info_t *template_node = NULL;
   3152     int i;
   3153 
   3154     if (ft_export_template_info_list[unit] == NULL) {
   3155         return;
   3156     }
   3157 
   3158     for (i = BCM_INT_FT_TEMPLATE_START_ID; i <= BCM_INT_FT_TEMPLATE_END_ID; i++) {
   3159         template_node = &(ft_export_template_info_list[unit][i]);
   3160         if (template_node->template_id != 0) {
   3161             _bcm_xgs5_ft_template_dump(template_node);
   3162         }
   3163     } 
   3164 }
   3165 
   3166 void
   3167 _bcm_xgs5_ft_collector_encap_l2_dump(
   3168                     bcm_flowtracker_collector_eth_header_t *eth)
   3169 {
   3170    LOG_CLI((BSL_META("\t\tDST_MAC = %x:%x:%x:%x:%x:%x\r\n"),
   3171                     eth->dst_mac[0],
   3172                     eth->dst_mac[1],
   3173                     eth->dst_mac[2],
   3174                     eth->dst_mac[3],
   3175                     eth->dst_mac[4],
   3176                     eth->dst_mac[5])); 
   3177    LOG_CLI((BSL_META("\t\tSRC_MAC = %x:%x:%x:%x:%x:%x\r\n"),
   3178                     eth->src_mac[0],
   3179                     eth->src_mac[1],
   3180                     eth->src_mac[2],
   3181                     eth->src_mac[3],
   3182                     eth->src_mac[4],
   3183                     eth->src_mac[5])); 
   3184      LOG_CLI((BSL_META("\t\tVlan tag structure = %d\r\n"),
   3185                     eth->vlan_tag_structure));
   3186      LOG_CLI((BSL_META("\t\touter_tpid = %u\r\n"),
   3187                     eth->outer_tpid));
   3188      LOG_CLI((BSL_META("\t\tinner_tpid = %u\r\n"),
   3189                     eth->inner_tpid));
   3190      LOG_CLI((BSL_META("\t\touter_vlan_tag = %u\r\n"),
   3191                     eth->outer_vlan_tag));
   3192      LOG_CLI((BSL_META("\t\tinner_vlan_tag = %u\r\n"),
   3193                     eth->inner_vlan_tag));
   3194 }
   3195 
   3196 void
   3197 _bcm_xgs5_ft_collector_encap_ipv4_dump(
   3198         bcm_flowtracker_collector_ipv4_header_t *ipv4)
   3199 {
   3200      LOG_CLI((BSL_META("\t\tsrc_ip = %x\r\n"),
   3201                     ipv4->src_ip));
   3202      LOG_CLI((BSL_META("\t\tdst_ip = %x\r\n"),
   3203                     ipv4->dst_ip));
   3204      LOG_CLI((BSL_META("\t\tdscp = %u\r\n"),
   3205                     ipv4->dscp));
   3206      LOG_CLI((BSL_META("\t\tttl = %u\r\n"),
   3207                     ipv4->ttl));
   3208 }
   3209 
   3210 void
   3211 _bcm_xgs5_ft_collector_encap_udp_dump(
   3212         bcm_flowtracker_collector_udp_header_t *udp)
   3213 {
   3214      LOG_CLI((BSL_META("\t\tDst L4 port = %d\r\n"),
   3215                     udp->dst_port));
   3216      LOG_CLI((BSL_META("\t\tSrc L4 port = %d\r\n"),
   3217                     udp->src_port));
   3218 }
   3219 
   3220 char *_bcm_xgs5_ft_collector_transport_type_str[bcmFlowtrackerCollectorTransportTypeCount] =
   3221 {
   3222     "IPv4 UDP",
   3223     "IPv6 UDP",
   3224     "Raw"
   3225 };
   3226 
   3227 /*
   3228  * Function:
   3229  *     _bcm_xgs5_ft_collector_dump
   3230  * Purpose:
   3231  *     Dump the collector info.
   3232  * Parameters:
   3233  *     unit          - (IN) BCM device number
   3234  *     collector_node - (IN) Collector information.
   3235  * Returns:
   3236  *     Nothing
   3237  */
   3238 void
   3239 _bcm_xgs5_ft_collector_dump ( 
   3240     _bcm_int_ft_collector_info_t *collector_node)
   3241 {
   3242      LOG_CLI((BSL_META("Collector ID = %d\r\n"),collector_node->collector_id));
   3243      LOG_CLI((BSL_META("\tTransport type = %s\r\n"),
   3244   _bcm_xgs5_ft_collector_transport_type_str[collector_node->collector_info.transport_type]));
   3245      LOG_CLI((BSL_META("\tEncap info:\r\n")));
   3246      _bcm_xgs5_ft_collector_encap_l2_dump(&(collector_node->collector_info.eth));
   3247      _bcm_xgs5_ft_collector_encap_ipv4_dump(
   3248              &(collector_node->collector_info.ipv4));
   3249      _bcm_xgs5_ft_collector_encap_udp_dump(&(collector_node->collector_info.udp));
   3250      LOG_CLI((BSL_META("\tMax packet length = %u\r\n"), 
   3251                     collector_node->collector_info.max_packet_length));
   3252 }
   3253 /*
   3254  * Function:
   3255  *     _bcm_xgs5_ft_collector_list_dump
   3256  * Purpose:
   3257  *     Dump the collector list.
   3258  * Parameters:
   3259  *     unit          - (IN) BCM device number
   3260  * Returns:
   3261  *     Nothing
   3262  */
   3263 void
   3264 _bcm_xgs5_ft_collector_list_dump (int unit)
   3265 {
   3266     _bcm_int_ft_collector_info_t *collector_node = NULL;
   3267     int i;
   3268 
   3269     if (ft_collector_info_list[unit] == NULL) {
   3270         return;
   3271     }
   3272 
   3273     for (i = BCM_INT_FT_COLLECTOR_START_ID; i <= BCM_INT_FT_COLLECTOR_END_ID; i++) {
   3274         collector_node = &(ft_collector_info_list[unit][i]);
   3275         if (collector_node->collector_id != 0) {
   3276             _bcm_xgs5_ft_collector_dump(collector_node);
   3277         }
   3278     } 
   3279 }
   3280 
   3281 /*
   3282  * Function:
   3283  *     _bcm_xgs5_ft_flow_group_dump
   3284  * Purpose:
   3285  *     Dump the flow_group info.
   3286  * Parameters:
   3287  *     flow_group_node - (IN) flow_group information.
   3288  * Returns:
   3289  *     Nothing
   3290  */
   3291 void
   3292 _bcm_xgs5_ft_flow_group_dump (
   3293                          int unit,
   3294                          _bcm_int_ft_flow_group_info_t *flow_group_node)
   3295 {
   3296     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   3297 
   3298      LOG_CLI((BSL_META("Flow group ID = %u\r\n"),
   3299                         flow_group_node->flow_group_id));
   3300      LOG_CLI((BSL_META("\tObservation domain ID = %u\r\n"),
   3301                         ft_info->observation_domain_id));
   3302      LOG_CLI((BSL_META("\tExport interval(us) = %u\r\n"),
   3303                         ft_info->export_interval));
   3304      LOG_CLI((BSL_META("\tAging interval(ms) = %u\r\n"),
   3305                         flow_group_node->aging_interval_msecs));
   3306      LOG_CLI((BSL_META("\tFlow limit = %u\r\n"),flow_group_node->flow_limit));
   3307      LOG_CLI((BSL_META("\tCollector ID = %u\r\n"),flow_group_node->collector_id));
   3308      LOG_CLI((BSL_META("\tTemplate ID = %u\r\n"),flow_group_node->template_id));
   3309      if (ft_info->elph_mode == TRUE) {
   3310          LOG_CLI((BSL_META("\Elephant Profile ID = %u\r\n"),
   3311                                              flow_group_node->elph_profile_id));
   3312      }
   3313 }
   3314 
   3315 /*
   3316  * Function:
   3317  *     _bcm_xgs5_ft_flow_group_list_dump
   3318  * Purpose:
   3319  *     Dump the flow_group list.
   3320  * Parameters:
   3321  *     unit          - (IN) BCM device number
   3322  * Returns:
   3323  *     Nothing
   3324  */
   3325 void
   3326 _bcm_xgs5_ft_flow_group_list_dump (int unit)
   3327 {
   3328     _bcm_int_ft_flow_group_info_t *flow_group_node = NULL;
   3329     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   3330     int i;
   3331 
   3332     if (ft_flow_group_info_list[unit] == NULL) {
   3333         return;
   3334     }
   3335 
   3336     for (i = BCM_INT_FT_GROUP_START_ID;
   3337          i < (BCM_INT_FT_GROUP_START_ID + ft_info->max_flow_groups); i++) {
   3338         flow_group_node = &(ft_flow_group_info_list[unit][i]);
   3339         if (flow_group_node->flow_group_id != 0) {
   3340             _bcm_xgs5_ft_flow_group_dump(unit, flow_group_node);
   3341         }
   3342     } 
   3343 }
   3344 /*
   3345  * Function:
   3346  *     _bcm_xgs5_ft_elph_profile_dump
   3347  * Purpose:
   3348  *     Dump an elephant profile info.
   3349  * Parameters:
   3350  *     elph_profile - (IN) Elephant profile information.
   3351  * Returns:
   3352  *     Nothing
   3353  */
   3354 void
   3355 _bcm_xgs5_ft_elph_profile_dump(_bcm_int_ft_elph_profile_info_t *profile_info)
   3356 {
   3357     int i;
   3358 
   3359     LOG_CLI((BSL_META("Profile Id            = %d\r\n"), profile_info->id));
   3360     LOG_CLI((BSL_META("Num promotion filters = %d\r\n"),
   3361              profile_info->profile.num_promotion_filters));
   3362     for (i = 0; i < profile_info->profile.num_promotion_filters; i++) {
   3363         LOG_CLI((BSL_META("Promotion Filter : %d\r\n"), i));
   3364         LOG_CLI((BSL_META("\tFlags               = 0x%08x\r\n"),
   3365                  profile_info->profile.promotion_filters[i].flags));
   3366         LOG_CLI((BSL_META("\tMonitor Interval    = %u usecs\r\n"),
   3367                  profile_info->profile.promotion_filters[i].monitor_interval_usecs));
   3368         LOG_CLI((BSL_META("\tRate Low threshold  = %u kbps\r\n"),
   3369                  profile_info->profile.promotion_filters[i].rate_low_threshold_kbits_sec));
   3370         LOG_CLI((BSL_META("\tRate High threshold = %u kbps\r\n"),
   3371                  profile_info->profile.promotion_filters[i].rate_high_threshold_kbits_sec));
   3372         LOG_CLI((BSL_META("\tSize threshold      = {0x%x, 0x%x} bytes\r\n"),
   3373                  COMPILER_64_HI(profile_info->profile.promotion_filters[i].size_threshold_bytes),
   3374                  COMPILER_64_LO(profile_info->profile.promotion_filters[i].size_threshold_bytes)));
   3375     }
   3376     LOG_CLI((BSL_META("Demotion Filter : \r\n")));
   3377     LOG_CLI((BSL_META("\tFlags               = 0x%08x\r\n"),
   3378              profile_info->profile.demotion_filter.flags));
   3379     LOG_CLI((BSL_META("\tMonitor Interval    = %u usecs\r\n"),
   3380              profile_info->profile.demotion_filter.monitor_interval_usecs));
   3381     LOG_CLI((BSL_META("\tRate Low threshold  = %u kbps\r\n"),
   3382              profile_info->profile.demotion_filter.rate_low_threshold_kbits_sec));
   3383     LOG_CLI((BSL_META("\tRate High threshold = %u kbps\r\n"),
   3384              profile_info->profile.demotion_filter.rate_high_threshold_kbits_sec));
   3385     LOG_CLI((BSL_META("\tSize threshold      = {0x%x, 0x%x} bytes\r\n"),
   3386              COMPILER_64_HI(profile_info->profile.demotion_filter.size_threshold_bytes),
   3387              COMPILER_64_LO(profile_info->profile.demotion_filter.size_threshold_bytes)));
   3388 
   3389 }
   3390 
   3391 /*
   3392  * Function:
   3393  *     _bcm_xgs5_ft_elph_profile_list_dump
   3394  * Purpose:
   3395  *     Dump the elephant profile list.
   3396  * Parameters:
   3397  *     unit          - (IN) BCM device number
   3398  * Returns:
   3399  *     None
   3400  */
   3401 void
   3402 _bcm_xgs5_ft_elph_profile_list_dump(int unit)
   3403 {
   3404     int i;
   3405     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   3406     _bcm_int_ft_elph_profile_info_t *profile_int_info = NULL;
   3407 
   3408     if (ft_info->elph_mode != TRUE) {
   3409         return;
   3410     }
   3411 
   3412     LOG_CLI((BSL_META("Dumping elephant profile Info : \r\n")));
   3413     for (i = BCM_INT_FT_ELPH_PROFILE_START_ID;
   3414          i <= BCM_INT_FT_ELPH_PROFILE_END_ID; i++) {
   3415 
   3416         profile_int_info = &(ft_elph_profile_info_list[unit][i]);
   3417         if (profile_int_info->id != i) {
   3418             continue;
   3419         }
   3420         _bcm_xgs5_ft_elph_profile_dump(profile_int_info);
   3421     }
   3422 }
   3423 
   3424 /*
   3425  * Function:
   3426  *      _bcm_esw_flowtracker_dump_stats_learn
   3427  * Purpose:
   3428  *      Dump the learn statistics
   3429  * Parameters:
   3430  *      unit             - (IN)    BCM device number
   3431  * Returns:
   3432  *      BCM_E_XXX   - BCM error code.
   3433  */
   3434 void _bcm_xgs5_flowtracker_dump_stats_learn(int unit)
   3435 {
   3436     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   3437     shr_ft_msg_ctrl_stats_learn_t msg;
   3438     char *status[] = SHR_FT_LEARN_PKT_STATUS_NAMES;
   3439     uint8 *buffer_req = NULL, *buffer_ptr = NULL;
   3440     uint16 buffer_len = 0, reply_len = 0;
   3441     int max_status;
   3442     int rv;
   3443     int i = 0;
   3444 
   3445     if (ft_info == NULL) {
   3446         LOG_CLI((BSL_META("Flowtracker not enabled \r\n")));
   3447         return;
   3448     }
   3449 
   3450     sal_memset(&msg, 0, sizeof(msg));
   3451 
   3452     /* Get the statistics from the FW */
   3453     rv = _bcm_xgs5_ft_msg_send_receive(unit,
   3454                                        MOS_MSG_SUBCLASS_FT_STATS_LEARN_GET,
   3455                                        0, 0,
   3456                                        MOS_MSG_SUBCLASS_FT_STATS_LEARN_GET_REPLY,
   3457                                        &reply_len,
   3458                                        SHR_FT_MAX_UC_MSG_TIMEOUT);
   3459 
   3460     if (rv != BCM_E_NONE) {
   3461         LOG_CLI((BSL_META("Messaging failure rv=%d\r\n"), rv));
   3462         return;
   3463     }
   3464 
   3465     buffer_req      = ft_info->dma_buffer;
   3466     buffer_ptr      = shr_ft_msg_ctrl_stats_learn_get_unpack(buffer_req, &msg);
   3467     buffer_len      = buffer_ptr - buffer_req;
   3468 
   3469     if (buffer_len != reply_len) {
   3470         LOG_CLI((BSL_META("Messaging failure \r\n")));
   3471         return;
   3472     }
   3473 
   3474     /* Get the max status, they maybe different depending on SDK, FW version */
   3475     max_status  = _BCM_FT_MIN(msg.num_status, SHR_FT_LEARN_PKT_MAX_STATUS);
   3476 
   3477     LOG_CLI((BSL_META(" +------------------------+-------------+--------------------+ \n")));
   3478     LOG_CLI((BSL_META(" |         Status         |    Count    |   Average (usec)   | \n")));
   3479     LOG_CLI((BSL_META(" +------------------------+-------------+--------------------+ \n")));
   3480     for (i = 0; i < max_status; i++) {
   3481         LOG_CLI((BSL_META(" | %s | %11u | %18u |\n"),
   3482                           status[i], msg.count[i], msg.avg_usecs[i]));
   3483         LOG_CLI((BSL_META(" +------------------------+-------------+--------------------+ \n")));
   3484     }
   3485     LOG_CLI((BSL_META("\n")));
   3486 
   3487 }
   3488 
   3489 /*
   3490  * Function:
   3491  *      _bcm_esw_flowtracker_dump_stats_export
   3492  * Purpose:
   3493  *      Dump the export statistics
   3494  * Parameters:
   3495  *      unit             - (IN)    BCM device number
   3496  * Returns:
   3497  *      BCM_E_XXX   - BCM error code.
   3498  */
   3499 void _bcm_xgs5_flowtracker_dump_stats_export(int unit)
   3500 {
   3501     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   3502     shr_ft_msg_ctrl_stats_export_t msg;
   3503     uint8 *buffer_req = NULL, *buffer_ptr = NULL;
   3504     uint16 buffer_len = 0, reply_len = 0;
   3505     int rv;
   3506 
   3507     if (ft_info == NULL) {
   3508         LOG_CLI((BSL_META("Flowtracker not enabled \r\n")));
   3509         return;
   3510     }
   3511 
   3512     sal_memset(&msg, 0, sizeof(msg));
   3513 
   3514     /* Get the statistics from the FW */
   3515     rv = _bcm_xgs5_ft_msg_send_receive(unit,
   3516                                        MOS_MSG_SUBCLASS_FT_STATS_EXPORT_GET,
   3517                                        0, 0,
   3518                                        MOS_MSG_SUBCLASS_FT_STATS_EXPORT_GET_REPLY,
   3519                                        &reply_len,
   3520                                        SHR_FT_MAX_UC_MSG_TIMEOUT);
   3521 
   3522     if (rv != BCM_E_NONE) {
   3523         LOG_CLI((BSL_META("Messaging failure rv=%d\r\n"), rv));
   3524         return;
   3525     }
   3526 
   3527     buffer_req      = ft_info->dma_buffer;
   3528     buffer_ptr      = shr_ft_msg_ctrl_stats_export_get_unpack(buffer_req, &msg);
   3529     buffer_len      = buffer_ptr - buffer_req;
   3530 
   3531     if (buffer_len != reply_len) {
   3532         LOG_CLI((BSL_META("Messaging failure \r\n")));
   3533         return;
   3534     }
   3535 
   3536     LOG_CLI((BSL_META("Export packets      : %u \n"), msg.num_pkts));
   3537     LOG_CLI((BSL_META("Export flows        : %u \n"), msg.num_flows));
   3538     LOG_CLI((BSL_META("Export time stamp   : %u \n"), msg.ts));
   3539     LOG_CLI((BSL_META("Sequence number     : %u \n"), msg.seq_num));
   3540     LOG_CLI((BSL_META("\n")));
   3541 
   3542     return;
   3543 }
   3544 
   3545 /*
   3546  * Function:
   3547  *      _bcm_esw_flowtracker_dump_stats_age
   3548  * Purpose:
   3549  *      Dump the age statistics
   3550  * Parameters:
   3551  *      unit             - (IN)    BCM device number
   3552  * Returns:
   3553  *      BCM_E_XXX   - BCM error code.
   3554  */
   3555 void _bcm_xgs5_flowtracker_dump_stats_age(int unit)
   3556 {
   3557     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   3558     shr_ft_msg_ctrl_stats_age_t msg;
   3559     uint8 *buffer_req = NULL, *buffer_ptr = NULL;
   3560     uint16 buffer_len = 0, reply_len = 0;
   3561     int rv;
   3562 
   3563     if (ft_info == NULL) {
   3564         LOG_CLI((BSL_META("Flowtracker not enabled \r\n")));
   3565         return;
   3566     }
   3567 
   3568     if (ft_info->elph_mode == TRUE) {
   3569         LOG_CLI((BSL_META("Cannot dump age stats in elephant mode \r\n")));
   3570         return;
   3571     }
   3572 
   3573 
   3574     sal_memset(&msg, 0, sizeof(msg));
   3575 
   3576     /* Get the statistics from the FW */
   3577     rv = _bcm_xgs5_ft_msg_send_receive(unit,
   3578                                        MOS_MSG_SUBCLASS_FT_STATS_AGE_GET,
   3579                                        0, 0,
   3580                                        MOS_MSG_SUBCLASS_FT_STATS_AGE_GET_REPLY,
   3581                                        &reply_len,
   3582                                        SHR_FT_MAX_UC_MSG_TIMEOUT);
   3583 
   3584     if (rv != BCM_E_NONE) {
   3585         LOG_CLI((BSL_META("Messaging failure rv=%d\r\n"), rv));
   3586         return;
   3587     }
   3588 
   3589     buffer_req      = ft_info->dma_buffer;
   3590     buffer_ptr      = shr_ft_msg_ctrl_stats_age_get_unpack(buffer_req, &msg);
   3591     buffer_len      = buffer_ptr - buffer_req;
   3592 
   3593     if (buffer_len != reply_len) {
   3594         LOG_CLI((BSL_META("Messaging failure \r\n")));
   3595         return;
   3596     }
   3597 
   3598     LOG_CLI((BSL_META("Num flows aged : %u \n"), msg.num_flows));
   3599     LOG_CLI((BSL_META("\n")));
   3600 
   3601     return;
   3602 }
   3603 
   3604 /*
   3605  * Function:
   3606  *      _bcm_esw_flowtracker_dump_stats_elephant
   3607  * Purpose:
   3608  *      Dump the elephant statistics
   3609  * Parameters:
   3610  *      unit             - (IN)    BCM device number
   3611  * Returns:
   3612  *      BCM_E_XXX   - BCM error code.
   3613  */
   3614 void _bcm_xgs5_flowtracker_dump_stats_elephant(int unit)
   3615 {
   3616 
   3617     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   3618     shr_ft_msg_ctrl_stats_elph_t msg;
   3619     uint8 *buffer_req = NULL, *buffer_ptr = NULL;
   3620     uint16 buffer_len = 0, reply_len = 0;
   3621     char *states[SHR_FT_ELPH_FLOW_STATE_COUNT] = SHR_FT_ELPH_STATES;
   3622     int num_states, num_actions;
   3623     int i, j;
   3624     int rv;
   3625 
   3626     if (ft_info == NULL) {
   3627         LOG_CLI((BSL_META("Flowtracker not enabled \r\n")));
   3628         return;
   3629     }
   3630 
   3631     if (ft_info->elph_mode != TRUE) {
   3632         LOG_CLI((BSL_META("Not in elephant mode \r\n")));
   3633         return;
   3634     }
   3635 
   3636 
   3637     sal_memset(&msg, 0, sizeof(msg));
   3638 
   3639     /* Get the statistics from the FW */
   3640     rv = _bcm_xgs5_ft_msg_send_receive(unit,
   3641                                        MOS_MSG_SUBCLASS_FT_STATS_ELPH_GET,
   3642                                        0, 0,
   3643                                        MOS_MSG_SUBCLASS_FT_STATS_ELPH_GET_REPLY,
   3644                                        &reply_len,
   3645                                        SHR_FT_MAX_UC_MSG_TIMEOUT);
   3646 
   3647     if (rv != BCM_E_NONE) {
   3648         LOG_CLI((BSL_META("Messaging failure rv=%d\r\n"), rv));
   3649         return;
   3650     }
   3651 
   3652     buffer_req      = ft_info->dma_buffer;
   3653     buffer_ptr      = shr_ft_msg_ctrl_stats_elph_get_unpack(buffer_req, &msg);
   3654     buffer_len      = buffer_ptr - buffer_req;
   3655 
   3656     if (buffer_len != reply_len) {
   3657         LOG_CLI((BSL_META("Messaging failure \r\n")));
   3658         return;
   3659     }
   3660 
   3661     /* Take the minimum value to avoid any version difference issues */
   3662     num_states  = _BCM_FT_MIN(msg.num_states, SHR_FT_ELPH_FLOW_STATE_COUNT);
   3663     num_actions = _BCM_FT_MIN(msg.num_actions, SHR_FT_ELPH_ACTION_COUNT);
   3664 
   3665     LOG_CLI((BSL_META(" +-------------------+------------+------------+------------+ \n")));
   3666     LOG_CLI((BSL_META(" |                   |    None    |   Promote  |   Demote   | \n")));
   3667     LOG_CLI((BSL_META(" +-------------------+------------+------------+------------+ \n")));
   3668     for (i = 0; i < num_states; i++) {
   3669         LOG_CLI((BSL_META(" | %10s |"), states[i]));
   3670         for (j = 0; j < num_actions; j++) {
   3671             LOG_CLI((BSL_META(" %10u |"), msg.trans_count[i][j]));
   3672         }
   3673         LOG_CLI((BSL_META("\n")));
   3674         LOG_CLI((BSL_META(" +-------------------+------------+------------+------------+ \n")));
   3675     }
   3676     LOG_CLI((BSL_META("\n")));
   3677 
   3678     return;
   3679 }
   3680 
   3681 
   3682 /* Dump routine for dumping flow group list,
   3683  * collector list and template list.
   3684  */
   3685 void _bcm_xgs5_flowtracker_sw_dump(int unit)
   3686 {
   3687     _bcm_int_ft_info_t *ft_info = FT_INFO_GET(unit);
   3688 
   3689     if (ft_info == NULL) {
   3690         return;
   3691     }
   3692 
   3693     _bcm_xgs5_ft_flow_group_list_dump(unit);
   3694     _bcm_xgs5_ft_collector_list_dump(unit);
   3695     _bcm_xgs5_ft_template_list_dump(unit);
   3696     _bcm_xgs5_ft_elph_profile_list_dump(unit);
   3697     _bcm_xgs5_flowtracker_dump_stats_learn(unit);
   3698     _bcm_xgs5_flowtracker_dump_stats_export(unit);
   3699     if (ft_info->elph_mode == TRUE) {
   3700         _bcm_xgs5_flowtracker_dump_stats_elephant(unit);
   3701     } else {
   3702         _bcm_xgs5_flowtracker_dump_stats_age(unit);
   3703     }
   3704 }
   3705 
   3706 #else /* INCLUDE_FLOWTRACKER */
   3707 int _bcm_xgs5_flowtracker_not_empty;
   3708 #endif /* INCLUDE_FLOWTRACKER */